amduat/src/near_core/format/pel.c

785 lines
25 KiB
C

#include "amduat/format/pel.h"
#include "amduat/format/json.h"
#include "amduat/format/ref.h"
#include "amduat/util/hex.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
const char *amduat_format_pel_status_name(
amduat_pel_execution_status_t status) {
switch (status) {
case AMDUAT_PEL_EXEC_STATUS_OK:
return "OK";
case AMDUAT_PEL_EXEC_STATUS_SCHEME_UNSUPPORTED:
return "SCHEME_UNSUPPORTED";
case AMDUAT_PEL_EXEC_STATUS_INVALID_PROGRAM:
return "INVALID_PROGRAM";
case AMDUAT_PEL_EXEC_STATUS_INVALID_INPUTS:
return "INVALID_INPUTS";
case AMDUAT_PEL_EXEC_STATUS_RUNTIME_FAILED:
return "RUNTIME_FAILED";
default:
return "UNKNOWN";
}
}
const char *amduat_format_pel_error_kind_name(
amduat_pel_execution_error_kind_t kind) {
switch (kind) {
case AMDUAT_PEL_EXEC_ERROR_NONE:
return "NONE";
case AMDUAT_PEL_EXEC_ERROR_SCHEME:
return "SCHEME";
case AMDUAT_PEL_EXEC_ERROR_PROGRAM:
return "PROGRAM";
case AMDUAT_PEL_EXEC_ERROR_INPUTS:
return "INPUTS";
case AMDUAT_PEL_EXEC_ERROR_RUNTIME:
return "RUNTIME";
default:
return "UNKNOWN";
}
}
const char *amduat_format_pel_node_status_name(
amduat_pel_node_trace_status_t status) {
switch (status) {
case AMDUAT_PEL_NODE_TRACE_OK:
return "NODE_OK";
case AMDUAT_PEL_NODE_TRACE_FAILED:
return "NODE_FAILED";
case AMDUAT_PEL_NODE_TRACE_SKIPPED:
return "NODE_SKIPPED";
default:
return "NODE_UNKNOWN";
}
}
const char *amduat_format_pel_store_phase_name(
amduat_pel_store_failure_phase_t phase) {
switch (phase) {
case AMDUAT_PEL_STORE_FAILURE_PROGRAM:
return "PROGRAM";
case AMDUAT_PEL_STORE_FAILURE_INPUT:
return "INPUT";
default:
return "UNKNOWN";
}
}
const char *amduat_format_pel_store_error_name(
amduat_pel_store_error_code_t code) {
switch (code) {
case AMDUAT_PEL_STORE_ERROR_NOT_FOUND:
return "NOT_FOUND";
case AMDUAT_PEL_STORE_ERROR_INTEGRITY:
return "INTEGRITY";
case AMDUAT_PEL_STORE_ERROR_UNSUPPORTED:
return "UNSUPPORTED";
default:
return "UNKNOWN";
}
}
const char *amduat_format_pel_kernel_kind_name(
amduat_pel_kernel_op_kind_t kind) {
switch (kind) {
case AMDUAT_PEL_KERNEL_OP_CONCAT:
return "concat";
case AMDUAT_PEL_KERNEL_OP_SLICE:
return "slice";
case AMDUAT_PEL_KERNEL_OP_CONST:
return "const";
case AMDUAT_PEL_KERNEL_OP_HASH_ASL1:
return "hash_asl1";
default:
return "unknown";
}
}
static char *amduat_format_hex_encode(amduat_octets_t bytes) {
char *hex = NULL;
if (!amduat_hex_encode_alloc(bytes.data, bytes.len, &hex)) {
return NULL;
}
return hex;
}
static bool amduat_format_diagnostics_text(
FILE *stream,
const char *prefix,
const amduat_pel_diagnostic_entry_t *diags,
size_t diags_len) {
size_t i;
if (diags_len == 0) {
return true;
}
if (prefix == NULL) {
prefix = "";
}
for (i = 0; i < diags_len; ++i) {
char *msg_hex = amduat_format_hex_encode(diags[i].message);
if (msg_hex == NULL) {
return false;
}
fprintf(stream, "%sdiagnostic[%zu].code=%u\n", prefix, i, diags[i].code);
fprintf(stream, "%sdiagnostic[%zu].message_hex=%s\n",
prefix, i, msg_hex);
free(msg_hex);
}
return true;
}
static bool amduat_format_diagnostics_json(
FILE *stream,
const amduat_pel_diagnostic_entry_t *diags,
size_t diags_len) {
size_t i;
fputs("[", stream);
for (i = 0; i < diags_len; ++i) {
char *msg_hex = amduat_format_hex_encode(diags[i].message);
if (msg_hex == NULL) {
return false;
}
if (i != 0) {
fputc(',', stream);
}
fprintf(stream, "{\"code\":%u,\"message_hex\":", diags[i].code);
if (!amduat_format_json_escape(
stream, amduat_octets(msg_hex, strlen(msg_hex)))) {
free(msg_hex);
return false;
}
fputs("}", stream);
free(msg_hex);
}
fputs("]", stream);
return true;
}
static bool amduat_format_program_text(FILE *stream,
const amduat_pel_program_t *program) {
size_t i;
fprintf(stream, "nodes_len=%zu\n", program->nodes_len);
fprintf(stream, "roots_len=%zu\n", program->roots_len);
for (i = 0; i < program->nodes_len; ++i) {
const amduat_pel_node_t *node = &program->nodes[i];
size_t j;
char *params_hex;
fprintf(stream, "node[%zu].id=%u\n", i, node->id);
fprintf(stream, "node[%zu].op.name=%.*s\n", i,
(int)node->op.name.len,
node->op.name.data ? (const char *)node->op.name.data : "");
fprintf(stream, "node[%zu].op.version=%u\n", i, node->op.version);
fprintf(stream, "node[%zu].inputs_len=%zu\n", i, node->inputs_len);
for (j = 0; j < node->inputs_len; ++j) {
const amduat_pel_dag_input_t *input = &node->inputs[j];
if (input->kind == AMDUAT_PEL_DAG_INPUT_EXTERNAL) {
fprintf(stream, "node[%zu].input[%zu].kind=external\n", i, j);
fprintf(stream,
"node[%zu].input[%zu].external.input_index=%u\n",
i, j, input->value.external.input_index);
} else {
fprintf(stream, "node[%zu].input[%zu].kind=node\n", i, j);
fprintf(stream,
"node[%zu].input[%zu].node.node_id=%u\n",
i, j, input->value.node.node_id);
fprintf(stream,
"node[%zu].input[%zu].node.output_index=%u\n",
i, j, input->value.node.output_index);
}
}
params_hex = amduat_format_hex_encode(node->params);
if (params_hex == NULL) {
return false;
}
fprintf(stream, "node[%zu].params_len=%zu\n", i, node->params.len);
fprintf(stream, "node[%zu].params_hex=%s\n", i, params_hex);
free(params_hex);
}
for (i = 0; i < program->roots_len; ++i) {
fprintf(stream, "root[%zu].node_id=%u\n",
i, program->roots[i].node_id);
fprintf(stream, "root[%zu].output_index=%u\n",
i, program->roots[i].output_index);
}
return true;
}
static bool amduat_format_program_json(FILE *stream,
const amduat_pel_program_t *program) {
size_t i;
fputs("{\"nodes\":[", stream);
for (i = 0; i < program->nodes_len; ++i) {
const amduat_pel_node_t *node = &program->nodes[i];
size_t j;
char *params_hex;
if (i != 0) {
fputc(',', stream);
}
fputs("{\"id\":", stream);
fprintf(stream, "%u", node->id);
fputs(",\"op\":{\"name\":", stream);
if (!amduat_format_json_escape(stream, node->op.name)) {
return false;
}
fprintf(stream, ",\"version\":%u}", node->op.version);
fputs(",\"inputs\":[", stream);
for (j = 0; j < node->inputs_len; ++j) {
const amduat_pel_dag_input_t *input = &node->inputs[j];
if (j != 0) {
fputc(',', stream);
}
if (input->kind == AMDUAT_PEL_DAG_INPUT_EXTERNAL) {
fprintf(stream,
"{\"kind\":\"external\",\"input_index\":%u}",
input->value.external.input_index);
} else {
fprintf(stream,
"{\"kind\":\"node\",\"node_id\":%u,\"output_index\":%u}",
input->value.node.node_id,
input->value.node.output_index);
}
}
fputs("]", stream);
params_hex = amduat_format_hex_encode(node->params);
if (params_hex == NULL) {
return false;
}
fputs(",\"params_hex\":", stream);
if (!amduat_format_json_escape(
stream, amduat_octets(params_hex, strlen(params_hex)))) {
free(params_hex);
return false;
}
free(params_hex);
fputs("}", stream);
}
fputs("],\"roots\":[", stream);
for (i = 0; i < program->roots_len; ++i) {
if (i != 0) {
fputc(',', stream);
}
fprintf(stream,
"{\"node_id\":%u,\"output_index\":%u}",
program->roots[i].node_id,
program->roots[i].output_index);
}
fputs("]}", stream);
return true;
}
bool amduat_format_pel_program(FILE *stream,
const amduat_pel_program_t *program,
amduat_format_output_t format) {
if (stream == NULL || program == NULL) {
return false;
}
if (format == AMDUAT_FORMAT_OUTPUT_TEXT) {
return amduat_format_program_text(stream, program);
}
return amduat_format_program_json(stream, program);
}
static bool amduat_format_trace_text(FILE *stream,
const amduat_pel_trace_dag_value_t *trace,
amduat_format_ref_format_t ref_format) {
size_t i;
fprintf(stream, "pel1_version=%u\n", trace->pel1_version);
fprintf(stream, "scheme_ref=");
if (!amduat_format_ref_write_text(stream, trace->scheme_ref, ref_format)) {
return false;
}
fputc('\n', stream);
fprintf(stream, "program_ref=");
if (!amduat_format_ref_write_text(stream, trace->program_ref, ref_format)) {
return false;
}
fputc('\n', stream);
fprintf(stream, "status=%s(%u)\n",
amduat_format_pel_status_name(trace->status),
(unsigned int)trace->status);
fprintf(stream, "error_kind=%s(%u)\n",
amduat_format_pel_error_kind_name(trace->summary.kind),
(unsigned int)trace->summary.kind);
fprintf(stream, "status_code=%u\n",
(unsigned int)trace->summary.status_code);
fprintf(stream, "has_exec_result_ref=%s\n",
trace->has_exec_result_ref ? "true" : "false");
if (trace->has_exec_result_ref) {
fprintf(stream, "exec_result_ref=");
if (!amduat_format_ref_write_text(stream,
trace->exec_result_ref,
ref_format)) {
return false;
}
fputc('\n', stream);
}
fprintf(stream, "input_refs_len=%zu\n", trace->input_refs_len);
for (i = 0; i < trace->input_refs_len; ++i) {
fprintf(stream, "input_ref[%zu]=", i);
if (!amduat_format_ref_write_text(stream,
trace->input_refs[i],
ref_format)) {
return false;
}
fputc('\n', stream);
}
fprintf(stream, "has_params_ref=%s\n",
trace->has_params_ref ? "true" : "false");
if (trace->has_params_ref) {
fprintf(stream, "params_ref=");
if (!amduat_format_ref_write_text(stream,
trace->params_ref,
ref_format)) {
return false;
}
fputc('\n', stream);
}
fprintf(stream, "node_traces_len=%zu\n", trace->node_traces_len);
for (i = 0; i < trace->node_traces_len; ++i) {
const amduat_pel_node_trace_dag_t *node = &trace->node_traces[i];
size_t j;
char prefix[64];
fprintf(stream, "node_trace[%zu].node_id=%u\n", i, node->node_id);
fprintf(stream, "node_trace[%zu].op.name=%.*s\n", i,
(int)node->op_name.len,
node->op_name.data ? (const char *)node->op_name.data : "");
fprintf(stream, "node_trace[%zu].op.version=%u\n", i, node->op_version);
fprintf(stream, "node_trace[%zu].status=%s(%u)\n", i,
amduat_format_pel_node_status_name(node->status),
(unsigned int)node->status);
fprintf(stream, "node_trace[%zu].status_code=%u\n", i,
node->status_code);
fprintf(stream, "node_trace[%zu].output_refs_len=%zu\n", i,
node->output_refs_len);
for (j = 0; j < node->output_refs_len; ++j) {
fprintf(stream, "node_trace[%zu].output_ref[%zu]=",
i, j);
if (!amduat_format_ref_write_text(stream,
node->output_refs[j],
ref_format)) {
return false;
}
fputc('\n', stream);
}
fprintf(stream, "node_trace[%zu].diagnostics_len=%zu\n", i,
node->diagnostics_len);
snprintf(prefix, sizeof(prefix), "node_trace[%zu].", i);
if (!amduat_format_diagnostics_text(stream,
prefix,
node->diagnostics,
node->diagnostics_len)) {
return false;
}
}
return true;
}
static bool amduat_format_trace_json(FILE *stream,
const amduat_pel_trace_dag_value_t *trace,
amduat_format_ref_format_t ref_format) {
size_t i;
fputs("{\"pel1_version\":", stream);
fprintf(stream, "%u", trace->pel1_version);
fputs(",\"scheme_ref\":", stream);
if (!amduat_format_ref_write_json(stream, trace->scheme_ref, ref_format)) {
return false;
}
fputs(",\"program_ref\":", stream);
if (!amduat_format_ref_write_json(stream, trace->program_ref, ref_format)) {
return false;
}
fputs(",\"status\":", stream);
if (!amduat_format_json_escape(
stream,
amduat_octets(amduat_format_pel_status_name(trace->status),
strlen(amduat_format_pel_status_name(trace->status))))) {
return false;
}
fprintf(stream, ",\"status_code\":%u",
(unsigned int)trace->summary.status_code);
fputs(",\"error_kind\":", stream);
if (!amduat_format_json_escape(
stream,
amduat_octets(
amduat_format_pel_error_kind_name(trace->summary.kind),
strlen(amduat_format_pel_error_kind_name(trace->summary.kind))))) {
return false;
}
fprintf(stream, ",\"error_kind_code\":%u",
(unsigned int)trace->summary.kind);
fputs(",\"has_exec_result_ref\":", stream);
fputs(trace->has_exec_result_ref ? "true" : "false", stream);
fputs(",\"exec_result_ref\":", stream);
if (trace->has_exec_result_ref) {
if (!amduat_format_ref_write_json(stream,
trace->exec_result_ref,
ref_format)) {
return false;
}
} else {
fputs("null", stream);
}
fputs(",\"input_refs\":[", stream);
for (i = 0; i < trace->input_refs_len; ++i) {
if (i != 0) {
fputc(',', stream);
}
if (!amduat_format_ref_write_json(stream,
trace->input_refs[i],
ref_format)) {
return false;
}
}
fputs("]", stream);
fputs(",\"has_params_ref\":", stream);
fputs(trace->has_params_ref ? "true" : "false", stream);
fputs(",\"params_ref\":", stream);
if (trace->has_params_ref) {
if (!amduat_format_ref_write_json(stream,
trace->params_ref,
ref_format)) {
return false;
}
} else {
fputs("null", stream);
}
fputs(",\"node_traces\":[", stream);
for (i = 0; i < trace->node_traces_len; ++i) {
const amduat_pel_node_trace_dag_t *node = &trace->node_traces[i];
size_t j;
if (i != 0) {
fputc(',', stream);
}
fprintf(stream, "{\"node_id\":%u,", node->node_id);
fputs("\"op\":{\"name\":", stream);
if (!amduat_format_json_escape(stream, node->op_name)) {
return false;
}
fprintf(stream, ",\"version\":%u},", node->op_version);
fputs("\"status\":", stream);
if (!amduat_format_json_escape(
stream,
amduat_octets(amduat_format_pel_node_status_name(node->status),
strlen(amduat_format_pel_node_status_name(
node->status))))) {
return false;
}
fprintf(stream, ",\"status_code\":%u", node->status_code);
fputs(",\"output_refs\":[", stream);
for (j = 0; j < node->output_refs_len; ++j) {
if (j != 0) {
fputc(',', stream);
}
if (!amduat_format_ref_write_json(stream,
node->output_refs[j],
ref_format)) {
return false;
}
}
fputs("],\"diagnostics\":", stream);
if (!amduat_format_diagnostics_json(stream,
node->diagnostics,
node->diagnostics_len)) {
return false;
}
fputs("}", stream);
}
fputs("]}", stream);
return true;
}
bool amduat_format_pel_trace(FILE *stream,
const amduat_pel_trace_dag_value_t *trace,
amduat_format_output_t format,
amduat_format_ref_format_t ref_format) {
if (stream == NULL || trace == NULL) {
return false;
}
if (format == AMDUAT_FORMAT_OUTPUT_TEXT) {
return amduat_format_trace_text(stream, trace, ref_format);
}
return amduat_format_trace_json(stream, trace, ref_format);
}
static bool amduat_format_result_text(
FILE *stream,
const amduat_pel_surface_execution_result_t *result,
amduat_format_ref_format_t ref_format) {
size_t i;
fprintf(stream, "pel1_version=%u\n", result->pel1_version);
fprintf(stream, "scheme_ref=");
if (!amduat_format_ref_write_text(stream, result->scheme_ref, ref_format)) {
return false;
}
fputc('\n', stream);
fprintf(stream, "program_ref=");
if (!amduat_format_ref_write_text(stream, result->program_ref, ref_format)) {
return false;
}
fputc('\n', stream);
fprintf(stream, "status=%s(%u)\n",
amduat_format_pel_status_name(result->core_result.status),
(unsigned int)result->core_result.status);
fprintf(stream, "error_kind=%s(%u)\n",
amduat_format_pel_error_kind_name(result->core_result.summary.kind),
(unsigned int)result->core_result.summary.kind);
fprintf(stream, "status_code=%u\n",
(unsigned int)result->core_result.summary.status_code);
if (!amduat_format_diagnostics_text(stream,
"",
result->core_result.diagnostics,
result->core_result.diagnostics_len)) {
return false;
}
fprintf(stream, "input_refs_len=%zu\n", result->input_refs_len);
for (i = 0; i < result->input_refs_len; ++i) {
fprintf(stream, "input_ref[%zu]=", i);
if (!amduat_format_ref_write_text(stream,
result->input_refs[i],
ref_format)) {
return false;
}
fputc('\n', stream);
}
fprintf(stream, "output_refs_len=%zu\n", result->output_refs_len);
for (i = 0; i < result->output_refs_len; ++i) {
fprintf(stream, "output_ref[%zu]=", i);
if (!amduat_format_ref_write_text(stream,
result->output_refs[i],
ref_format)) {
return false;
}
fputc('\n', stream);
}
fprintf(stream, "has_params_ref=%s\n",
result->has_params_ref ? "true" : "false");
if (result->has_params_ref) {
fprintf(stream, "params_ref=");
if (!amduat_format_ref_write_text(stream,
result->params_ref,
ref_format)) {
return false;
}
fputc('\n', stream);
}
fprintf(stream, "has_trace_ref=%s\n",
result->has_trace_ref ? "true" : "false");
if (result->has_trace_ref) {
fprintf(stream, "trace_ref=");
if (!amduat_format_ref_write_text(stream,
result->trace_ref,
ref_format)) {
return false;
}
fputc('\n', stream);
}
fprintf(stream, "has_store_failure=%s\n",
result->has_store_failure ? "true" : "false");
if (result->has_store_failure) {
fprintf(stream, "store_failure.phase=%s(%u)\n",
amduat_format_pel_store_phase_name(result->store_failure.phase),
(unsigned int)result->store_failure.phase);
fprintf(stream, "store_failure.error_code=%s(%u)\n",
amduat_format_pel_store_error_name(
result->store_failure.error_code),
(unsigned int)result->store_failure.error_code);
fprintf(stream, "store_failure.failing_ref=");
if (!amduat_format_ref_write_text(
stream, result->store_failure.failing_ref, ref_format)) {
return false;
}
fputc('\n', stream);
}
return true;
}
static bool amduat_format_result_json(
FILE *stream,
const amduat_pel_surface_execution_result_t *result,
amduat_format_ref_format_t ref_format) {
size_t i;
fputs("{\"pel1_version\":", stream);
fprintf(stream, "%u", result->pel1_version);
fputs(",\"scheme_ref\":", stream);
if (!amduat_format_ref_write_json(stream, result->scheme_ref, ref_format)) {
return false;
}
fputs(",\"program_ref\":", stream);
if (!amduat_format_ref_write_json(stream, result->program_ref, ref_format)) {
return false;
}
fputs(",\"status\":", stream);
if (!amduat_format_json_escape(
stream,
amduat_octets(amduat_format_pel_status_name(
result->core_result.status),
strlen(amduat_format_pel_status_name(
result->core_result.status))))) {
return false;
}
fprintf(stream, ",\"status_code\":%u",
(unsigned int)result->core_result.summary.status_code);
fputs(",\"error_kind\":", stream);
if (!amduat_format_json_escape(
stream,
amduat_octets(amduat_format_pel_error_kind_name(
result->core_result.summary.kind),
strlen(amduat_format_pel_error_kind_name(
result->core_result.summary.kind))))) {
return false;
}
fprintf(stream, ",\"error_kind_code\":%u",
(unsigned int)result->core_result.summary.kind);
fputs(",\"diagnostics\":", stream);
if (!amduat_format_diagnostics_json(
stream,
result->core_result.diagnostics,
result->core_result.diagnostics_len)) {
return false;
}
fputs(",\"input_refs\":[", stream);
for (i = 0; i < result->input_refs_len; ++i) {
if (i != 0) {
fputc(',', stream);
}
if (!amduat_format_ref_write_json(stream,
result->input_refs[i],
ref_format)) {
return false;
}
}
fputs("]", stream);
fputs(",\"output_refs\":[", stream);
for (i = 0; i < result->output_refs_len; ++i) {
if (i != 0) {
fputc(',', stream);
}
if (!amduat_format_ref_write_json(stream,
result->output_refs[i],
ref_format)) {
return false;
}
}
fputs("]", stream);
fputs(",\"has_params_ref\":", stream);
fputs(result->has_params_ref ? "true" : "false", stream);
fputs(",\"params_ref\":", stream);
if (result->has_params_ref) {
if (!amduat_format_ref_write_json(stream,
result->params_ref,
ref_format)) {
return false;
}
} else {
fputs("null", stream);
}
fputs(",\"has_trace_ref\":", stream);
fputs(result->has_trace_ref ? "true" : "false", stream);
fputs(",\"trace_ref\":", stream);
if (result->has_trace_ref) {
if (!amduat_format_ref_write_json(stream,
result->trace_ref,
ref_format)) {
return false;
}
} else {
fputs("null", stream);
}
fputs(",\"has_store_failure\":", stream);
fputs(result->has_store_failure ? "true" : "false", stream);
fputs(",\"store_failure\":", stream);
if (result->has_store_failure) {
fputs("{\"phase\":", stream);
if (!amduat_format_json_escape(
stream,
amduat_octets(amduat_format_pel_store_phase_name(
result->store_failure.phase),
strlen(amduat_format_pel_store_phase_name(
result->store_failure.phase))))) {
return false;
}
fprintf(stream, ",\"phase_code\":%u",
(unsigned int)result->store_failure.phase);
fputs(",\"error_code\":", stream);
if (!amduat_format_json_escape(
stream,
amduat_octets(amduat_format_pel_store_error_name(
result->store_failure.error_code),
strlen(amduat_format_pel_store_error_name(
result->store_failure.error_code))))) {
return false;
}
fprintf(stream, ",\"error_code_id\":%u",
(unsigned int)result->store_failure.error_code);
fputs(",\"failing_ref\":", stream);
if (!amduat_format_ref_write_json(stream,
result->store_failure.failing_ref,
ref_format)) {
return false;
}
fputs("}", stream);
} else {
fputs("null", stream);
}
fputs("}", stream);
return true;
}
bool amduat_format_pel_result(FILE *stream,
const amduat_pel_surface_execution_result_t *result,
amduat_format_output_t format,
amduat_format_ref_format_t ref_format) {
if (stream == NULL || result == NULL) {
return false;
}
if (format == AMDUAT_FORMAT_OUTPUT_TEXT) {
return amduat_format_result_text(stream, result, ref_format);
}
return amduat_format_result_json(stream, result, ref_format);
}