Add PEL collection view projection

This commit is contained in:
Carl Niklas Rydberg 2026-01-23 20:18:23 +01:00
parent 3e526975ce
commit d9122b53bb
17 changed files with 2194 additions and 19 deletions

View file

@ -62,6 +62,8 @@ set(AMDUAT_UTIL_SRCS
set(AMDUAT_ASL_SRCS
src/kernel/asl/core.c
src/near_core/asl/collection_view.c
src/near_core/asl/none.c
src/near_core/asl/artifact_io.c
src/near_core/asl/io.c
src/near_core/asl/index_accel.c
@ -127,6 +129,7 @@ set(AMDUAT_PEL_SRCS
src/pel_stack/trace_dag/trace_dag.c
src/pel_stack/queue/queue.c
src/pel_stack/opreg/kernel.c
src/pel_stack/opreg/kernel_collection.c
src/pel_stack/opreg/kernel_params.c
)
@ -193,7 +196,8 @@ amduat_add_lib(format SRCS ${AMDUAT_FORMAT_SRCS})
amduat_link(format amduat_asl amduat_enc amduat_util)
amduat_add_lib(pel SRCS ${AMDUAT_PEL_SRCS})
amduat_link(pel amduat_asl_materialization_cache_fs amduat_asl amduat_enc amduat_hash_asl1 amduat_util)
amduat_link(pel amduat_asl_materialization_cache_fs amduat_asl_collection
amduat_asl amduat_enc amduat_hash_asl1 amduat_util)
amduat_add_lib(tgk SRCS ${AMDUAT_TGK_SRCS})
amduat_link(tgk amduat_asl amduat_enc amduat_hash_asl1 amduat_util)

View file

@ -28,6 +28,12 @@ typedef struct {
amduat_asl_pointer_store_t pointer_store;
} amduat_asl_collection_store_t;
typedef struct {
uint64_t snapshot_offset;
amduat_reference_t *refs;
size_t refs_len;
} amduat_asl_collection_snapshot_payload_t;
bool amduat_asl_collection_store_init(
amduat_asl_collection_store_t *collection_store,
const char *root_path,
@ -61,6 +67,13 @@ amduat_asl_collection_error_t amduat_asl_collection_read(
void amduat_asl_collection_refs_free(amduat_reference_t *refs,
size_t refs_len);
bool amduat_asl_collection_snapshot_payload_decode_v1(
amduat_octets_t payload,
amduat_asl_collection_snapshot_payload_t *out_snapshot);
void amduat_asl_collection_snapshot_payload_free(
amduat_asl_collection_snapshot_payload_t *snapshot);
#ifdef __cplusplus
} /* extern "C" */
#endif

View file

@ -0,0 +1,74 @@
#ifndef AMDUAT_ASL_COLLECTION_VIEW_H
#define AMDUAT_ASL_COLLECTION_VIEW_H
#include "amduat/asl/core.h"
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
enum { TYPE_TAG_ASL_COLLECTION_VIEW_1 = 0x00000403u };
enum { AMDUAT_TYPE_TAG_ASL_COLLECTION_VIEW_1 = TYPE_TAG_ASL_COLLECTION_VIEW_1 };
enum { TYPE_TAG_ASL_SNAPSHOT_INFO_1 = 0x00000405u };
enum { AMDUAT_TYPE_TAG_ASL_SNAPSHOT_INFO_1 = TYPE_TAG_ASL_SNAPSHOT_INFO_1 };
enum { TYPE_TAG_ASL_LOG_RANGE_1 = 0x00000406u };
enum { AMDUAT_TYPE_TAG_ASL_LOG_RANGE_1 = TYPE_TAG_ASL_LOG_RANGE_1 };
typedef struct {
uint64_t snapshot_at_offset;
amduat_reference_t *refs;
size_t refs_len;
} amduat_asl_collection_snapshot_info_t;
typedef struct {
uint64_t start_offset;
uint64_t next_offset;
amduat_reference_t *refs;
size_t refs_len;
} amduat_asl_log_range_t;
typedef struct {
uint64_t computed_from_offset;
uint64_t computed_up_to_offset;
amduat_reference_t *refs;
size_t refs_len;
} amduat_asl_collection_view_t;
bool amduat_asl_collection_snapshot_info_encode_v1(
const amduat_asl_collection_snapshot_info_t *info,
amduat_octets_t *out_bytes);
bool amduat_asl_collection_snapshot_info_decode_v1(
amduat_octets_t bytes,
amduat_asl_collection_snapshot_info_t *out_info);
void amduat_asl_collection_snapshot_info_free(
amduat_asl_collection_snapshot_info_t *info);
bool amduat_asl_log_range_encode_v1(const amduat_asl_log_range_t *range,
amduat_octets_t *out_bytes);
bool amduat_asl_log_range_decode_v1(amduat_octets_t bytes,
amduat_asl_log_range_t *out_range);
void amduat_asl_log_range_free(amduat_asl_log_range_t *range);
bool amduat_asl_collection_view_encode_v1(
const amduat_asl_collection_view_t *view,
amduat_octets_t *out_bytes);
bool amduat_asl_collection_view_decode_v1(
amduat_octets_t bytes,
amduat_asl_collection_view_t *out_view);
void amduat_asl_collection_view_free(amduat_asl_collection_view_t *view);
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* AMDUAT_ASL_COLLECTION_VIEW_H */

View file

@ -25,6 +25,16 @@ typedef struct {
amduat_octets_t actor;
} amduat_asl_log_entry_t;
typedef struct {
bool has_prev;
amduat_reference_t prev_ref;
uint64_t base_offset;
uint32_t entry_count;
bool has_timestamp;
bool has_actor;
amduat_asl_log_entry_t *entries;
} amduat_asl_log_chunk_t;
typedef struct {
amduat_asl_store_t *store;
amduat_asl_pointer_store_t pointer_store;
@ -55,6 +65,12 @@ amduat_asl_store_error_t amduat_asl_log_read(
void amduat_asl_log_entries_free(amduat_asl_log_entry_t *entries,
size_t entries_len);
amduat_asl_store_error_t amduat_asl_log_chunk_decode_v1(
amduat_octets_t bytes,
amduat_asl_log_chunk_t *out_chunk);
void amduat_asl_log_chunk_free(amduat_asl_log_chunk_t *chunk);
#ifdef __cplusplus
} /* extern "C" */
#endif

27
include/amduat/asl/none.h Normal file
View file

@ -0,0 +1,27 @@
#ifndef AMDUAT_ASL_NONE_H
#define AMDUAT_ASL_NONE_H
#include "amduat/asl/core.h"
#include <stdbool.h>
#ifdef __cplusplus
extern "C" {
#endif
enum { TYPE_TAG_ASL_NONE_1 = 0x00000404u };
enum { AMDUAT_TYPE_TAG_ASL_NONE_1 = TYPE_TAG_ASL_NONE_1 };
bool amduat_asl_none_encode_v1(amduat_octets_t *out_bytes);
bool amduat_asl_none_decode_v1(amduat_octets_t bytes);
bool amduat_asl_none_is_artifact(const amduat_artifact_t *artifact);
bool amduat_asl_none_artifact(amduat_artifact_t *out_artifact);
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* AMDUAT_ASL_NONE_H */

View file

@ -17,6 +17,11 @@ extern "C" {
#define AMDUAT_PEL_KERNEL_OP_HASH_ASL1_NAME "pel.bytes.hash.asl1"
#define AMDUAT_PEL_KERNEL_OP_PARAMS_NAME "pel.bytes.params"
#define AMDUAT_PEL_KERNEL_OP_FORMAT_ENCODE_NAME "pel.format.encode"
#define AMDUAT_PEL_KERNEL_OP_COLLECTION_SNAPSHOT_DECODE_NAME \
"collection.snapshot_decode_v1"
#define AMDUAT_PEL_KERNEL_OP_LOG_READ_RANGE_NAME "log.read_range_v1"
#define AMDUAT_PEL_KERNEL_OP_COLLECTION_MERGE_REFS_NAME \
"collection.merge_refs_v1"
enum {
AMDUAT_PEL_KERNEL_OP_CODE_CONCAT = 0x0001u,
@ -24,7 +29,10 @@ enum {
AMDUAT_PEL_KERNEL_OP_CODE_CONST = 0x0003u,
AMDUAT_PEL_KERNEL_OP_CODE_HASH_ASL1 = 0x0004u,
AMDUAT_PEL_KERNEL_OP_CODE_PARAMS = 0x0005u,
AMDUAT_PEL_KERNEL_OP_CODE_FORMAT_ENCODE = 0x0006u
AMDUAT_PEL_KERNEL_OP_CODE_FORMAT_ENCODE = 0x0006u,
AMDUAT_PEL_KERNEL_OP_CODE_COLLECTION_SNAPSHOT_DECODE = 0x0007u,
AMDUAT_PEL_KERNEL_OP_CODE_LOG_READ_RANGE = 0x0008u,
AMDUAT_PEL_KERNEL_OP_CODE_COLLECTION_MERGE_REFS = 0x0009u
};
enum {
@ -35,7 +43,13 @@ enum {
AMDUAT_PEL_KERNEL_STATUS_FORMAT_SCHEMA_INVALID = 0x00030001u,
AMDUAT_PEL_KERNEL_STATUS_FORMAT_REGISTRY_INVALID = 0x00030002u,
AMDUAT_PEL_KERNEL_STATUS_FORMAT_MISSING_FIELD = 0x00030003u,
AMDUAT_PEL_KERNEL_STATUS_FORMAT_TYPE_UNSUPPORTED = 0x00030004u
AMDUAT_PEL_KERNEL_STATUS_FORMAT_TYPE_UNSUPPORTED = 0x00030004u,
AMDUAT_PEL_KERNEL_STATUS_PARAMS_INVALID = 0x00040001u,
AMDUAT_PEL_KERNEL_STATUS_COLLECTION_SNAPSHOT_INVALID = 0x00040002u,
AMDUAT_PEL_KERNEL_STATUS_LOG_CHUNK_INVALID = 0x00040003u,
AMDUAT_PEL_KERNEL_STATUS_LOG_RANGE_INVALID = 0x00040004u,
AMDUAT_PEL_KERNEL_STATUS_COLLECTION_VIEW_INVALID = 0x00040005u,
AMDUAT_PEL_KERNEL_STATUS_REF_RESOLVE_FAILED = 0x00040006u
};
typedef enum {
@ -44,7 +58,10 @@ typedef enum {
AMDUAT_PEL_KERNEL_OP_CONST = 3,
AMDUAT_PEL_KERNEL_OP_HASH_ASL1 = 4,
AMDUAT_PEL_KERNEL_OP_PARAMS = 5,
AMDUAT_PEL_KERNEL_OP_FORMAT_ENCODE = 6
AMDUAT_PEL_KERNEL_OP_FORMAT_ENCODE = 6,
AMDUAT_PEL_KERNEL_OP_COLLECTION_SNAPSHOT_DECODE = 7,
AMDUAT_PEL_KERNEL_OP_LOG_READ_RANGE = 8,
AMDUAT_PEL_KERNEL_OP_COLLECTION_MERGE_REFS = 9
} amduat_pel_kernel_op_kind_t;
typedef struct {
@ -58,6 +75,11 @@ typedef struct {
struct amduat_pel_kernel_params;
typedef struct amduat_pel_kernel_params amduat_pel_kernel_params_t;
typedef bool (*amduat_pel_kernel_artifact_resolver_t)(
amduat_reference_t ref,
amduat_artifact_t *out_artifact,
void *ctx);
const amduat_pel_kernel_op_desc_t *amduat_pel_kernel_op_lookup(
amduat_octets_t name,
uint32_t version);
@ -67,6 +89,15 @@ const amduat_pel_kernel_op_desc_t *amduat_pel_kernel_op_descs(
const char *amduat_pel_kernel_op_name(amduat_pel_kernel_op_kind_t kind);
void amduat_pel_kernel_set_artifact_resolver(
amduat_pel_kernel_artifact_resolver_t resolver,
void *ctx);
void amduat_pel_kernel_clear_artifact_resolver(void);
bool amduat_pel_kernel_resolve_artifact(amduat_reference_t ref,
amduat_artifact_t *out_artifact);
bool amduat_pel_kernel_op_eval(
const amduat_pel_kernel_op_desc_t *desc,
const amduat_artifact_t *inputs,

View file

@ -36,6 +36,40 @@ static void amduat_asl_collection_store_u64_le(uint8_t *out, uint64_t value) {
out[7] = (uint8_t)((value >> 56) & 0xffu);
}
static bool amduat_asl_collection_read_u32_le(const uint8_t *data,
size_t len,
size_t *offset,
uint32_t *out) {
if (len - *offset < 4u) {
return false;
}
*out = (uint32_t)data[*offset] |
((uint32_t)data[*offset + 1u] << 8) |
((uint32_t)data[*offset + 2u] << 16) |
((uint32_t)data[*offset + 3u] << 24);
*offset += 4u;
return true;
}
static bool amduat_asl_collection_read_u64_le(const uint8_t *data,
size_t len,
size_t *offset,
uint64_t *out) {
if (len - *offset < 8u) {
return false;
}
*out = (uint64_t)data[*offset] |
((uint64_t)data[*offset + 1u] << 8) |
((uint64_t)data[*offset + 2u] << 16) |
((uint64_t)data[*offset + 3u] << 24) |
((uint64_t)data[*offset + 4u] << 32) |
((uint64_t)data[*offset + 5u] << 40) |
((uint64_t)data[*offset + 6u] << 48) |
((uint64_t)data[*offset + 7u] << 56);
*offset += 8u;
return true;
}
static bool amduat_asl_collection_add_size(size_t *acc, size_t add) {
if (*acc > SIZE_MAX - add) {
return false;
@ -481,3 +515,93 @@ void amduat_asl_collection_refs_free(amduat_reference_t *refs,
}
free(refs);
}
bool amduat_asl_collection_snapshot_payload_decode_v1(
amduat_octets_t payload,
amduat_asl_collection_snapshot_payload_t *out_snapshot) {
size_t offset = 0u;
uint32_t version = 0u;
uint32_t entry_count = 0u;
if (out_snapshot == NULL) {
return false;
}
out_snapshot->snapshot_offset = 0u;
out_snapshot->refs = NULL;
out_snapshot->refs_len = 0u;
if (payload.len < AMDUAT_ASL_COLLECTION_MAGIC_LEN + 4u + 8u + 4u) {
return false;
}
if (payload.data == NULL) {
return false;
}
if (memcmp(payload.data, k_amduat_asl_collection_magic,
AMDUAT_ASL_COLLECTION_MAGIC_LEN) != 0) {
return false;
}
offset += AMDUAT_ASL_COLLECTION_MAGIC_LEN;
if (!amduat_asl_collection_read_u32_le(payload.data, payload.len,
&offset, &version) ||
version != AMDUAT_ASL_COLLECTION_VERSION) {
return false;
}
if (!amduat_asl_collection_read_u64_le(payload.data, payload.len,
&offset,
&out_snapshot->snapshot_offset)) {
return false;
}
if (!amduat_asl_collection_read_u32_le(payload.data, payload.len,
&offset, &entry_count)) {
return false;
}
if (entry_count == 0u) {
return offset == payload.len;
}
if (entry_count > SIZE_MAX / sizeof(amduat_reference_t)) {
return false;
}
out_snapshot->refs =
(amduat_reference_t *)calloc(entry_count, sizeof(*out_snapshot->refs));
if (out_snapshot->refs == NULL) {
return false;
}
out_snapshot->refs_len = entry_count;
for (uint32_t i = 0u; i < entry_count; ++i) {
uint32_t ref_len = 0u;
amduat_octets_t ref_bytes;
if (!amduat_asl_collection_read_u32_le(payload.data, payload.len,
&offset, &ref_len)) {
goto fail;
}
if (payload.len - offset < ref_len) {
goto fail;
}
ref_bytes = amduat_octets(payload.data + offset, ref_len);
if (!amduat_enc_asl1_core_decode_reference_v1(
ref_bytes, &out_snapshot->refs[i])) {
goto fail;
}
offset += ref_len;
}
return offset == payload.len;
fail:
amduat_asl_collection_snapshot_payload_free(out_snapshot);
return false;
}
void amduat_asl_collection_snapshot_payload_free(
amduat_asl_collection_snapshot_payload_t *snapshot) {
if (snapshot == NULL || snapshot->refs == NULL) {
return;
}
for (size_t i = 0u; i < snapshot->refs_len; ++i) {
amduat_reference_free(&snapshot->refs[i]);
}
free(snapshot->refs);
snapshot->refs = NULL;
snapshot->refs_len = 0u;
}

View file

@ -25,16 +25,6 @@ enum {
AMDUAT_ASL_LOG_FLAG_HAS_ACTOR = 1u << 2
};
typedef struct {
bool has_prev;
amduat_reference_t prev_ref;
uint64_t base_offset;
uint32_t entry_count;
bool has_timestamp;
bool has_actor;
amduat_asl_log_entry_t *entries;
} amduat_asl_log_chunk_t;
typedef struct {
const uint8_t *data;
size_t len;
@ -115,7 +105,7 @@ static bool amduat_asl_log_add_size(size_t *acc, size_t add) {
return true;
}
static void amduat_asl_log_chunk_free(amduat_asl_log_chunk_t *chunk) {
void amduat_asl_log_chunk_free(amduat_asl_log_chunk_t *chunk) {
if (chunk == NULL) {
return;
}
@ -342,7 +332,7 @@ cleanup:
return AMDUAT_ASL_STORE_ERR_INTEGRITY;
}
static amduat_asl_store_error_t amduat_asl_log_decode_chunk(
amduat_asl_store_error_t amduat_asl_log_chunk_decode_v1(
amduat_octets_t bytes,
amduat_asl_log_chunk_t *out_chunk) {
amduat_asl_log_cursor_t cur;
@ -574,7 +564,8 @@ amduat_asl_store_error_t amduat_asl_log_append(
free(pointer_name);
return AMDUAT_ASL_STORE_ERR_INTEGRITY;
}
store_err = amduat_asl_log_decode_chunk(head_artifact.bytes, &head_chunk);
store_err = amduat_asl_log_chunk_decode_v1(head_artifact.bytes,
&head_chunk);
amduat_artifact_free(&head_artifact);
if (store_err != AMDUAT_ASL_STORE_OK) {
amduat_reference_free(&head_ref);
@ -744,7 +735,7 @@ amduat_asl_store_error_t amduat_asl_log_read(
amduat_reference_free(&head_ref);
return AMDUAT_ASL_STORE_ERR_INTEGRITY;
}
err = amduat_asl_log_decode_chunk(artifact.bytes, &chunk);
err = amduat_asl_log_chunk_decode_v1(artifact.bytes, &chunk);
amduat_artifact_free(&artifact);
if (err != AMDUAT_ASL_STORE_OK) {
if (current_ref_owned) {

View file

@ -0,0 +1,520 @@
#include "amduat/asl/collection_view.h"
#include "amduat/enc/asl1_core_codec.h"
#include <limits.h>
#include <stdlib.h>
#include <string.h>
enum {
AMDUAT_ASL_COLLECTION_VIEW_MAGIC_LEN = 8,
AMDUAT_ASL_COLLECTION_VIEW_VERSION = 1,
AMDUAT_ASL_SNAPSHOT_INFO_MAGIC_LEN = 8,
AMDUAT_ASL_SNAPSHOT_INFO_VERSION = 1,
AMDUAT_ASL_LOG_RANGE_MAGIC_LEN = 8,
AMDUAT_ASL_LOG_RANGE_VERSION = 1
};
static const uint8_t k_amduat_asl_collection_view_magic[
AMDUAT_ASL_COLLECTION_VIEW_MAGIC_LEN] = {
'A', 'S', 'L', 'C', 'V', 'W', '1', '\0'
};
static const uint8_t k_amduat_asl_snapshot_info_magic[
AMDUAT_ASL_SNAPSHOT_INFO_MAGIC_LEN] = {
'A', 'S', 'L', 'S', 'N', 'P', '1', '\0'
};
static const uint8_t k_amduat_asl_log_range_magic[
AMDUAT_ASL_LOG_RANGE_MAGIC_LEN] = {
'A', 'S', 'L', 'R', 'N', 'G', '1', '\0'
};
static void amduat_asl_store_u32_le(uint8_t *out, uint32_t value) {
out[0] = (uint8_t)(value & 0xffu);
out[1] = (uint8_t)((value >> 8) & 0xffu);
out[2] = (uint8_t)((value >> 16) & 0xffu);
out[3] = (uint8_t)((value >> 24) & 0xffu);
}
static void amduat_asl_store_u64_le(uint8_t *out, uint64_t value) {
out[0] = (uint8_t)(value & 0xffu);
out[1] = (uint8_t)((value >> 8) & 0xffu);
out[2] = (uint8_t)((value >> 16) & 0xffu);
out[3] = (uint8_t)((value >> 24) & 0xffu);
out[4] = (uint8_t)((value >> 32) & 0xffu);
out[5] = (uint8_t)((value >> 40) & 0xffu);
out[6] = (uint8_t)((value >> 48) & 0xffu);
out[7] = (uint8_t)((value >> 56) & 0xffu);
}
static bool amduat_asl_read_u32_le(const uint8_t *data,
size_t len,
size_t *offset,
uint32_t *out) {
if (len - *offset < 4u) {
return false;
}
*out = (uint32_t)data[*offset] |
((uint32_t)data[*offset + 1u] << 8) |
((uint32_t)data[*offset + 2u] << 16) |
((uint32_t)data[*offset + 3u] << 24);
*offset += 4u;
return true;
}
static bool amduat_asl_read_u64_le(const uint8_t *data,
size_t len,
size_t *offset,
uint64_t *out) {
if (len - *offset < 8u) {
return false;
}
*out = (uint64_t)data[*offset] |
((uint64_t)data[*offset + 1u] << 8) |
((uint64_t)data[*offset + 2u] << 16) |
((uint64_t)data[*offset + 3u] << 24) |
((uint64_t)data[*offset + 4u] << 32) |
((uint64_t)data[*offset + 5u] << 40) |
((uint64_t)data[*offset + 6u] << 48) |
((uint64_t)data[*offset + 7u] << 56);
*offset += 8u;
return true;
}
static bool amduat_asl_add_size(size_t *acc, size_t add) {
if (*acc > SIZE_MAX - add) {
return false;
}
*acc += add;
return true;
}
static bool amduat_asl_encode_refs(const amduat_reference_t *refs,
size_t refs_len,
size_t *out_total_len) {
size_t total = 0u;
if (refs_len > UINT32_MAX) {
return false;
}
for (size_t i = 0u; i < refs_len; ++i) {
amduat_octets_t ref_bytes = amduat_octets(NULL, 0u);
if (!amduat_enc_asl1_core_encode_reference_v1(refs[i], &ref_bytes)) {
return false;
}
if (!amduat_asl_add_size(&total, 4u + ref_bytes.len)) {
free((void *)ref_bytes.data);
return false;
}
free((void *)ref_bytes.data);
}
*out_total_len = total;
return true;
}
static bool amduat_asl_write_refs(uint8_t *buffer,
size_t total_len,
size_t *offset,
const amduat_reference_t *refs,
size_t refs_len) {
for (size_t i = 0u; i < refs_len; ++i) {
amduat_octets_t ref_bytes = amduat_octets(NULL, 0u);
if (!amduat_enc_asl1_core_encode_reference_v1(refs[i], &ref_bytes)) {
return false;
}
if (total_len - *offset < 4u + ref_bytes.len) {
free((void *)ref_bytes.data);
return false;
}
amduat_asl_store_u32_le(buffer + *offset, (uint32_t)ref_bytes.len);
*offset += 4u;
memcpy(buffer + *offset, ref_bytes.data, ref_bytes.len);
*offset += ref_bytes.len;
free((void *)ref_bytes.data);
}
return true;
}
static bool amduat_asl_decode_refs(amduat_octets_t bytes,
size_t *offset,
uint32_t refs_len,
amduat_reference_t **out_refs,
size_t *out_refs_len) {
amduat_reference_t *refs = NULL;
if (out_refs == NULL || out_refs_len == NULL) {
return false;
}
*out_refs = NULL;
*out_refs_len = 0u;
if (refs_len == 0u) {
return true;
}
if (refs_len > SIZE_MAX / sizeof(*refs)) {
return false;
}
refs = (amduat_reference_t *)calloc(refs_len, sizeof(*refs));
if (refs == NULL) {
return false;
}
for (uint32_t i = 0u; i < refs_len; ++i) {
uint32_t ref_len = 0u;
amduat_octets_t ref_bytes;
if (!amduat_asl_read_u32_le(bytes.data, bytes.len, offset, &ref_len)) {
goto fail;
}
if (bytes.len - *offset < ref_len) {
goto fail;
}
ref_bytes = amduat_octets(bytes.data + *offset, ref_len);
if (!amduat_enc_asl1_core_decode_reference_v1(ref_bytes, &refs[i])) {
goto fail;
}
*offset += ref_len;
}
*out_refs = refs;
*out_refs_len = refs_len;
return true;
fail:
for (uint32_t i = 0u; i < refs_len; ++i) {
amduat_reference_free(&refs[i]);
}
free(refs);
return false;
}
bool amduat_asl_collection_snapshot_info_encode_v1(
const amduat_asl_collection_snapshot_info_t *info,
amduat_octets_t *out_bytes) {
uint8_t *buffer;
size_t total_len = 0u;
size_t refs_len_bytes = 0u;
size_t offset = 0u;
if (out_bytes == NULL || info == NULL) {
return false;
}
out_bytes->data = NULL;
out_bytes->len = 0u;
if (!amduat_asl_add_size(&total_len,
AMDUAT_ASL_SNAPSHOT_INFO_MAGIC_LEN + 4u + 8u + 4u)) {
return false;
}
if (!amduat_asl_encode_refs(info->refs, info->refs_len, &refs_len_bytes)) {
return false;
}
if (!amduat_asl_add_size(&total_len, refs_len_bytes)) {
return false;
}
buffer = (uint8_t *)malloc(total_len);
if (buffer == NULL) {
return false;
}
memcpy(buffer + offset, k_amduat_asl_snapshot_info_magic,
AMDUAT_ASL_SNAPSHOT_INFO_MAGIC_LEN);
offset += AMDUAT_ASL_SNAPSHOT_INFO_MAGIC_LEN;
amduat_asl_store_u32_le(buffer + offset, AMDUAT_ASL_SNAPSHOT_INFO_VERSION);
offset += 4u;
amduat_asl_store_u64_le(buffer + offset, info->snapshot_at_offset);
offset += 8u;
amduat_asl_store_u32_le(buffer + offset, (uint32_t)info->refs_len);
offset += 4u;
if (!amduat_asl_write_refs(buffer, total_len, &offset,
info->refs, info->refs_len)) {
free(buffer);
return false;
}
if (offset != total_len) {
free(buffer);
return false;
}
*out_bytes = amduat_octets(buffer, total_len);
return true;
}
bool amduat_asl_collection_snapshot_info_decode_v1(
amduat_octets_t bytes,
amduat_asl_collection_snapshot_info_t *out_info) {
size_t offset = 0u;
uint32_t version = 0u;
uint32_t refs_len = 0u;
if (out_info == NULL) {
return false;
}
out_info->snapshot_at_offset = 0u;
out_info->refs = NULL;
out_info->refs_len = 0u;
if (bytes.len < AMDUAT_ASL_SNAPSHOT_INFO_MAGIC_LEN + 4u + 8u + 4u ||
bytes.data == NULL) {
return false;
}
if (memcmp(bytes.data, k_amduat_asl_snapshot_info_magic,
AMDUAT_ASL_SNAPSHOT_INFO_MAGIC_LEN) != 0) {
return false;
}
offset += AMDUAT_ASL_SNAPSHOT_INFO_MAGIC_LEN;
if (!amduat_asl_read_u32_le(bytes.data, bytes.len, &offset, &version) ||
version != AMDUAT_ASL_SNAPSHOT_INFO_VERSION) {
return false;
}
if (!amduat_asl_read_u64_le(bytes.data, bytes.len, &offset,
&out_info->snapshot_at_offset)) {
return false;
}
if (!amduat_asl_read_u32_le(bytes.data, bytes.len, &offset, &refs_len)) {
return false;
}
if (!amduat_asl_decode_refs(bytes, &offset, refs_len,
&out_info->refs, &out_info->refs_len)) {
return false;
}
return offset == bytes.len;
}
void amduat_asl_collection_snapshot_info_free(
amduat_asl_collection_snapshot_info_t *info) {
if (info == NULL || info->refs == NULL) {
return;
}
for (size_t i = 0u; i < info->refs_len; ++i) {
amduat_reference_free(&info->refs[i]);
}
free(info->refs);
info->refs = NULL;
info->refs_len = 0u;
}
bool amduat_asl_log_range_encode_v1(const amduat_asl_log_range_t *range,
amduat_octets_t *out_bytes) {
uint8_t *buffer;
size_t total_len = 0u;
size_t refs_len_bytes = 0u;
size_t offset = 0u;
if (out_bytes == NULL || range == NULL) {
return false;
}
out_bytes->data = NULL;
out_bytes->len = 0u;
if (!amduat_asl_add_size(&total_len,
AMDUAT_ASL_LOG_RANGE_MAGIC_LEN + 4u + 8u + 8u + 4u)) {
return false;
}
if (!amduat_asl_encode_refs(range->refs, range->refs_len, &refs_len_bytes)) {
return false;
}
if (!amduat_asl_add_size(&total_len, refs_len_bytes)) {
return false;
}
buffer = (uint8_t *)malloc(total_len);
if (buffer == NULL) {
return false;
}
memcpy(buffer + offset, k_amduat_asl_log_range_magic,
AMDUAT_ASL_LOG_RANGE_MAGIC_LEN);
offset += AMDUAT_ASL_LOG_RANGE_MAGIC_LEN;
amduat_asl_store_u32_le(buffer + offset, AMDUAT_ASL_LOG_RANGE_VERSION);
offset += 4u;
amduat_asl_store_u64_le(buffer + offset, range->start_offset);
offset += 8u;
amduat_asl_store_u64_le(buffer + offset, range->next_offset);
offset += 8u;
amduat_asl_store_u32_le(buffer + offset, (uint32_t)range->refs_len);
offset += 4u;
if (!amduat_asl_write_refs(buffer, total_len, &offset,
range->refs, range->refs_len)) {
free(buffer);
return false;
}
if (offset != total_len) {
free(buffer);
return false;
}
*out_bytes = amduat_octets(buffer, total_len);
return true;
}
bool amduat_asl_log_range_decode_v1(amduat_octets_t bytes,
amduat_asl_log_range_t *out_range) {
size_t offset = 0u;
uint32_t version = 0u;
uint32_t refs_len = 0u;
if (out_range == NULL) {
return false;
}
out_range->start_offset = 0u;
out_range->next_offset = 0u;
out_range->refs = NULL;
out_range->refs_len = 0u;
if (bytes.len <
AMDUAT_ASL_LOG_RANGE_MAGIC_LEN + 4u + 8u + 8u + 4u ||
bytes.data == NULL) {
return false;
}
if (memcmp(bytes.data, k_amduat_asl_log_range_magic,
AMDUAT_ASL_LOG_RANGE_MAGIC_LEN) != 0) {
return false;
}
offset += AMDUAT_ASL_LOG_RANGE_MAGIC_LEN;
if (!amduat_asl_read_u32_le(bytes.data, bytes.len, &offset, &version) ||
version != AMDUAT_ASL_LOG_RANGE_VERSION) {
return false;
}
if (!amduat_asl_read_u64_le(bytes.data, bytes.len, &offset,
&out_range->start_offset) ||
!amduat_asl_read_u64_le(bytes.data, bytes.len, &offset,
&out_range->next_offset)) {
return false;
}
if (!amduat_asl_read_u32_le(bytes.data, bytes.len, &offset, &refs_len)) {
return false;
}
if (!amduat_asl_decode_refs(bytes, &offset, refs_len,
&out_range->refs, &out_range->refs_len)) {
return false;
}
return offset == bytes.len;
}
void amduat_asl_log_range_free(amduat_asl_log_range_t *range) {
if (range == NULL || range->refs == NULL) {
return;
}
for (size_t i = 0u; i < range->refs_len; ++i) {
amduat_reference_free(&range->refs[i]);
}
free(range->refs);
range->refs = NULL;
range->refs_len = 0u;
}
bool amduat_asl_collection_view_encode_v1(
const amduat_asl_collection_view_t *view,
amduat_octets_t *out_bytes) {
uint8_t *buffer;
size_t total_len = 0u;
size_t refs_len_bytes = 0u;
size_t offset = 0u;
if (out_bytes == NULL || view == NULL) {
return false;
}
out_bytes->data = NULL;
out_bytes->len = 0u;
if (!amduat_asl_add_size(&total_len,
AMDUAT_ASL_COLLECTION_VIEW_MAGIC_LEN + 4u +
8u + 8u + 4u)) {
return false;
}
if (!amduat_asl_encode_refs(view->refs, view->refs_len, &refs_len_bytes)) {
return false;
}
if (!amduat_asl_add_size(&total_len, refs_len_bytes)) {
return false;
}
buffer = (uint8_t *)malloc(total_len);
if (buffer == NULL) {
return false;
}
memcpy(buffer + offset, k_amduat_asl_collection_view_magic,
AMDUAT_ASL_COLLECTION_VIEW_MAGIC_LEN);
offset += AMDUAT_ASL_COLLECTION_VIEW_MAGIC_LEN;
amduat_asl_store_u32_le(buffer + offset,
AMDUAT_ASL_COLLECTION_VIEW_VERSION);
offset += 4u;
amduat_asl_store_u64_le(buffer + offset, view->computed_from_offset);
offset += 8u;
amduat_asl_store_u64_le(buffer + offset, view->computed_up_to_offset);
offset += 8u;
amduat_asl_store_u32_le(buffer + offset, (uint32_t)view->refs_len);
offset += 4u;
if (!amduat_asl_write_refs(buffer, total_len, &offset,
view->refs, view->refs_len)) {
free(buffer);
return false;
}
if (offset != total_len) {
free(buffer);
return false;
}
*out_bytes = amduat_octets(buffer, total_len);
return true;
}
bool amduat_asl_collection_view_decode_v1(
amduat_octets_t bytes,
amduat_asl_collection_view_t *out_view) {
size_t offset = 0u;
uint32_t version = 0u;
uint32_t refs_len = 0u;
if (out_view == NULL) {
return false;
}
out_view->computed_from_offset = 0u;
out_view->computed_up_to_offset = 0u;
out_view->refs = NULL;
out_view->refs_len = 0u;
if (bytes.len <
AMDUAT_ASL_COLLECTION_VIEW_MAGIC_LEN + 4u + 8u + 8u + 4u ||
bytes.data == NULL) {
return false;
}
if (memcmp(bytes.data, k_amduat_asl_collection_view_magic,
AMDUAT_ASL_COLLECTION_VIEW_MAGIC_LEN) != 0) {
return false;
}
offset += AMDUAT_ASL_COLLECTION_VIEW_MAGIC_LEN;
if (!amduat_asl_read_u32_le(bytes.data, bytes.len, &offset, &version) ||
version != AMDUAT_ASL_COLLECTION_VIEW_VERSION) {
return false;
}
if (!amduat_asl_read_u64_le(bytes.data, bytes.len, &offset,
&out_view->computed_from_offset) ||
!amduat_asl_read_u64_le(bytes.data, bytes.len, &offset,
&out_view->computed_up_to_offset)) {
return false;
}
if (!amduat_asl_read_u32_le(bytes.data, bytes.len, &offset, &refs_len)) {
return false;
}
if (!amduat_asl_decode_refs(bytes, &offset, refs_len,
&out_view->refs, &out_view->refs_len)) {
return false;
}
return offset == bytes.len;
}
void amduat_asl_collection_view_free(amduat_asl_collection_view_t *view) {
if (view == NULL || view->refs == NULL) {
return;
}
for (size_t i = 0u; i < view->refs_len; ++i) {
amduat_reference_free(&view->refs[i]);
}
free(view->refs);
view->refs = NULL;
view->refs_len = 0u;
}

110
src/near_core/asl/none.c Normal file
View file

@ -0,0 +1,110 @@
#include "amduat/asl/none.h"
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
enum {
AMDUAT_ASL_NONE_MAGIC_LEN = 8,
AMDUAT_ASL_NONE_VERSION = 1
};
static const uint8_t k_amduat_asl_none_magic[AMDUAT_ASL_NONE_MAGIC_LEN] = {
'A', 'S', 'L', 'N', 'O', 'N', '1', '\0'
};
static void amduat_asl_none_store_u32_le(uint8_t *out, uint32_t value) {
out[0] = (uint8_t)(value & 0xffu);
out[1] = (uint8_t)((value >> 8) & 0xffu);
out[2] = (uint8_t)((value >> 16) & 0xffu);
out[3] = (uint8_t)((value >> 24) & 0xffu);
}
static bool amduat_asl_none_read_u32_le(const uint8_t *data,
size_t len,
size_t *offset,
uint32_t *out) {
if (len - *offset < 4u) {
return false;
}
*out = (uint32_t)data[*offset] |
((uint32_t)data[*offset + 1u] << 8) |
((uint32_t)data[*offset + 2u] << 16) |
((uint32_t)data[*offset + 3u] << 24);
*offset += 4u;
return true;
}
bool amduat_asl_none_encode_v1(amduat_octets_t *out_bytes) {
uint8_t *buffer;
size_t offset = 0u;
if (out_bytes == NULL) {
return false;
}
out_bytes->data = NULL;
out_bytes->len = 0u;
buffer = (uint8_t *)malloc(AMDUAT_ASL_NONE_MAGIC_LEN + 4u);
if (buffer == NULL) {
return false;
}
memcpy(buffer + offset, k_amduat_asl_none_magic, AMDUAT_ASL_NONE_MAGIC_LEN);
offset += AMDUAT_ASL_NONE_MAGIC_LEN;
amduat_asl_none_store_u32_le(buffer + offset, AMDUAT_ASL_NONE_VERSION);
offset += 4u;
out_bytes->data = buffer;
out_bytes->len = offset;
return true;
}
bool amduat_asl_none_decode_v1(amduat_octets_t bytes) {
size_t offset = 0u;
uint32_t version = 0u;
if (bytes.len != AMDUAT_ASL_NONE_MAGIC_LEN + 4u) {
return false;
}
if (bytes.data == NULL) {
return false;
}
if (memcmp(bytes.data, k_amduat_asl_none_magic,
AMDUAT_ASL_NONE_MAGIC_LEN) != 0) {
return false;
}
offset += AMDUAT_ASL_NONE_MAGIC_LEN;
if (!amduat_asl_none_read_u32_le(bytes.data, bytes.len, &offset, &version)) {
return false;
}
if (version != AMDUAT_ASL_NONE_VERSION) {
return false;
}
return offset == bytes.len;
}
bool amduat_asl_none_is_artifact(const amduat_artifact_t *artifact) {
if (artifact == NULL) {
return false;
}
if (!artifact->has_type_tag ||
artifact->type_tag.tag_id != AMDUAT_TYPE_TAG_ASL_NONE_1) {
return false;
}
return amduat_asl_none_decode_v1(artifact->bytes);
}
bool amduat_asl_none_artifact(amduat_artifact_t *out_artifact) {
amduat_octets_t bytes = amduat_octets(NULL, 0u);
if (out_artifact == NULL) {
return false;
}
if (!amduat_asl_none_encode_v1(&bytes)) {
return false;
}
*out_artifact =
amduat_artifact_with_type(bytes, amduat_type_tag(AMDUAT_TYPE_TAG_ASL_NONE_1));
return true;
}

View file

@ -95,6 +95,16 @@ const char *amduat_format_pel_kernel_kind_name(
return "const";
case AMDUAT_PEL_KERNEL_OP_HASH_ASL1:
return "hash_asl1";
case AMDUAT_PEL_KERNEL_OP_PARAMS:
return "params";
case AMDUAT_PEL_KERNEL_OP_FORMAT_ENCODE:
return "format_encode";
case AMDUAT_PEL_KERNEL_OP_COLLECTION_SNAPSHOT_DECODE:
return "collection_snapshot_decode";
case AMDUAT_PEL_KERNEL_OP_LOG_READ_RANGE:
return "log_read_range";
case AMDUAT_PEL_KERNEL_OP_COLLECTION_MERGE_REFS:
return "collection_merge_refs";
default:
return "unknown";
}

View file

@ -1,5 +1,6 @@
#include "amduat/pel/opreg_kernel.h"
#include "amduat/pel/opreg_kernel_params.h"
#include "kernel_collection.h"
#include "amduat/hash/asl1.h"
#include <stdbool.h>
@ -64,8 +65,32 @@ static const amduat_pel_kernel_op_desc_t k_kernel_descs[] = {
3,
1
},
{
AMDUAT_PEL_KERNEL_OP_COLLECTION_SNAPSHOT_DECODE,
AMDUAT_PEL_KERNEL_OP_CODE_COLLECTION_SNAPSHOT_DECODE,
1,
1,
1
},
{
AMDUAT_PEL_KERNEL_OP_LOG_READ_RANGE,
AMDUAT_PEL_KERNEL_OP_CODE_LOG_READ_RANGE,
3,
3,
1
},
{
AMDUAT_PEL_KERNEL_OP_COLLECTION_MERGE_REFS,
AMDUAT_PEL_KERNEL_OP_CODE_COLLECTION_MERGE_REFS,
4,
4,
1
},
};
static amduat_pel_kernel_artifact_resolver_t g_resolver = NULL;
static void *g_resolver_ctx = NULL;
const amduat_pel_kernel_op_desc_t *amduat_pel_kernel_op_lookup(
amduat_octets_t name,
uint32_t version) {
@ -90,6 +115,16 @@ const amduat_pel_kernel_op_desc_t *amduat_pel_kernel_op_lookup(
if (amduat_name_eq(name, AMDUAT_PEL_KERNEL_OP_FORMAT_ENCODE_NAME)) {
return &k_kernel_descs[5];
}
if (amduat_name_eq(name,
AMDUAT_PEL_KERNEL_OP_COLLECTION_SNAPSHOT_DECODE_NAME)) {
return &k_kernel_descs[6];
}
if (amduat_name_eq(name, AMDUAT_PEL_KERNEL_OP_LOG_READ_RANGE_NAME)) {
return &k_kernel_descs[7];
}
if (amduat_name_eq(name, AMDUAT_PEL_KERNEL_OP_COLLECTION_MERGE_REFS_NAME)) {
return &k_kernel_descs[8];
}
return NULL;
}
@ -115,11 +150,37 @@ const char *amduat_pel_kernel_op_name(amduat_pel_kernel_op_kind_t kind) {
return AMDUAT_PEL_KERNEL_OP_PARAMS_NAME;
case AMDUAT_PEL_KERNEL_OP_FORMAT_ENCODE:
return AMDUAT_PEL_KERNEL_OP_FORMAT_ENCODE_NAME;
case AMDUAT_PEL_KERNEL_OP_COLLECTION_SNAPSHOT_DECODE:
return AMDUAT_PEL_KERNEL_OP_COLLECTION_SNAPSHOT_DECODE_NAME;
case AMDUAT_PEL_KERNEL_OP_LOG_READ_RANGE:
return AMDUAT_PEL_KERNEL_OP_LOG_READ_RANGE_NAME;
case AMDUAT_PEL_KERNEL_OP_COLLECTION_MERGE_REFS:
return AMDUAT_PEL_KERNEL_OP_COLLECTION_MERGE_REFS_NAME;
default:
return NULL;
}
}
void amduat_pel_kernel_set_artifact_resolver(
amduat_pel_kernel_artifact_resolver_t resolver,
void *ctx) {
g_resolver = resolver;
g_resolver_ctx = ctx;
}
void amduat_pel_kernel_clear_artifact_resolver(void) {
g_resolver = NULL;
g_resolver_ctx = NULL;
}
bool amduat_pel_kernel_resolve_artifact(amduat_reference_t ref,
amduat_artifact_t *out_artifact) {
if (g_resolver == NULL) {
return false;
}
return g_resolver(ref, out_artifact, g_resolver_ctx);
}
static bool amduat_type_tags_match(const amduat_artifact_t *a,
const amduat_artifact_t *b) {
if (a->has_type_tag != b->has_type_tag) {
@ -1537,6 +1598,15 @@ bool amduat_pel_kernel_op_eval(
case AMDUAT_PEL_KERNEL_OP_FORMAT_ENCODE:
return amduat_kernel_format_encode(inputs, inputs_len, out_outputs,
out_outputs_len, out_status_code);
case AMDUAT_PEL_KERNEL_OP_COLLECTION_SNAPSHOT_DECODE:
return amduat_kernel_collection_snapshot_decode(
inputs, inputs_len, out_outputs, out_outputs_len, out_status_code);
case AMDUAT_PEL_KERNEL_OP_LOG_READ_RANGE:
return amduat_kernel_log_read_range(
inputs, inputs_len, out_outputs, out_outputs_len, out_status_code);
case AMDUAT_PEL_KERNEL_OP_COLLECTION_MERGE_REFS:
return amduat_kernel_collection_merge_refs(
inputs, inputs_len, out_outputs, out_outputs_len, out_status_code);
default:
*out_status_code = AMDUAT_PEL_KERNEL_STATUS_INTERNAL;
return false;

View file

@ -0,0 +1,615 @@
#include "kernel_collection.h"
#include "amduat/asl/collection.h"
#include "amduat/asl/collection_view.h"
#include "amduat/asl/log_store.h"
#include "amduat/asl/none.h"
#include "amduat/asl/record.h"
#include <limits.h>
#include <stdlib.h>
#include <string.h>
static bool amduat_alloc_outputs(size_t count,
amduat_artifact_t **out_outputs) {
amduat_artifact_t *outputs;
if (out_outputs == NULL) {
return false;
}
outputs = (amduat_artifact_t *)calloc(count, sizeof(*outputs));
if (outputs == NULL) {
return false;
}
*out_outputs = outputs;
return true;
}
static bool amduat_load_u64_le(amduat_octets_t bytes,
size_t offset,
uint64_t *out) {
const uint8_t *data;
if (out == NULL) {
return false;
}
if (bytes.len - offset < 8u || bytes.data == NULL) {
return false;
}
data = bytes.data + offset;
*out = (uint64_t)data[0] |
((uint64_t)data[1] << 8) |
((uint64_t)data[2] << 16) |
((uint64_t)data[3] << 24) |
((uint64_t)data[4] << 32) |
((uint64_t)data[5] << 40) |
((uint64_t)data[6] << 48) |
((uint64_t)data[7] << 56);
return true;
}
static bool amduat_load_u32_le(amduat_octets_t bytes,
size_t offset,
uint32_t *out) {
const uint8_t *data;
if (out == NULL) {
return false;
}
if (bytes.len - offset < 4u || bytes.data == NULL) {
return false;
}
data = bytes.data + offset;
*out = (uint32_t)data[0] |
((uint32_t)data[1] << 8) |
((uint32_t)data[2] << 16) |
((uint32_t)data[3] << 24);
return true;
}
static bool amduat_decode_params(const amduat_artifact_t *artifact,
uint64_t *out_from,
uint32_t *out_limit) {
const char k_params_schema[] = "pel/params";
amduat_asl_record_t record;
bool ok = false;
if (artifact == NULL || out_from == NULL || out_limit == NULL) {
return false;
}
if (!artifact->has_type_tag ||
artifact->type_tag.tag_id != AMDUAT_TYPE_TAG_ASL_RECORD_1) {
return false;
}
if (!amduat_asl_record_decode_v1(artifact->bytes, &record)) {
return false;
}
if (record.schema.len != strlen(k_params_schema) ||
record.schema.data == NULL ||
memcmp(record.schema.data, k_params_schema,
record.schema.len) != 0) {
amduat_asl_record_free(&record);
return false;
}
if (record.payload.len != 12u) {
amduat_asl_record_free(&record);
return false;
}
if (!amduat_load_u64_le(record.payload, 0u, out_from) ||
!amduat_load_u32_le(record.payload, 8u, out_limit)) {
amduat_asl_record_free(&record);
return false;
}
ok = true;
amduat_asl_record_free(&record);
return ok;
}
static bool amduat_log_chunk_from_artifact(
const amduat_artifact_t *artifact,
amduat_asl_log_chunk_t *out_chunk) {
if (artifact == NULL || out_chunk == NULL) {
return false;
}
if (!artifact->has_type_tag ||
artifact->type_tag.tag_id != AMDUAT_TYPE_TAG_ASL_LOG_CHUNK_1) {
return false;
}
return amduat_asl_log_chunk_decode_v1(artifact->bytes, out_chunk) ==
AMDUAT_ASL_STORE_OK;
}
bool amduat_kernel_collection_snapshot_decode(
const amduat_artifact_t *inputs,
size_t inputs_len,
amduat_artifact_t **out_outputs,
size_t *out_outputs_len,
uint32_t *out_status_code) {
amduat_asl_collection_snapshot_payload_t snapshot;
amduat_asl_collection_snapshot_info_t info;
amduat_asl_record_t record;
amduat_octets_t encoded = amduat_octets(NULL, 0u);
bool ok = false;
if (inputs == NULL || inputs_len != 1u) {
if (out_status_code) {
*out_status_code = AMDUAT_PEL_KERNEL_STATUS_INTERNAL;
}
return false;
}
memset(&snapshot, 0, sizeof(snapshot));
memset(&info, 0, sizeof(info));
memset(&record, 0, sizeof(record));
if (amduat_asl_none_is_artifact(&inputs[0])) {
info.snapshot_at_offset = 0u;
info.refs = NULL;
info.refs_len = 0u;
} else {
if (!inputs[0].has_type_tag ||
inputs[0].type_tag.tag_id != AMDUAT_TYPE_TAG_ASL_RECORD_1) {
if (out_status_code) {
*out_status_code = AMDUAT_PEL_KERNEL_STATUS_COLLECTION_SNAPSHOT_INVALID;
}
return false;
}
if (!amduat_asl_record_decode_v1(inputs[0].bytes, &record)) {
if (out_status_code) {
*out_status_code = AMDUAT_PEL_KERNEL_STATUS_COLLECTION_SNAPSHOT_INVALID;
}
return false;
}
if (record.schema.len != strlen("collection/snapshot") ||
record.schema.data == NULL ||
memcmp(record.schema.data, "collection/snapshot",
record.schema.len) != 0) {
amduat_asl_record_free(&record);
if (out_status_code) {
*out_status_code = AMDUAT_PEL_KERNEL_STATUS_COLLECTION_SNAPSHOT_INVALID;
}
return false;
}
if (!amduat_asl_collection_snapshot_payload_decode_v1(record.payload,
&snapshot)) {
amduat_asl_record_free(&record);
if (out_status_code) {
*out_status_code = AMDUAT_PEL_KERNEL_STATUS_COLLECTION_SNAPSHOT_INVALID;
}
return false;
}
info.snapshot_at_offset = snapshot.snapshot_offset;
info.refs = snapshot.refs;
info.refs_len = snapshot.refs_len;
amduat_asl_record_free(&record);
}
if (!amduat_asl_collection_snapshot_info_encode_v1(&info, &encoded)) {
amduat_asl_collection_snapshot_payload_free(&snapshot);
if (out_status_code) {
*out_status_code = AMDUAT_PEL_KERNEL_STATUS_OOM;
}
return false;
}
if (!amduat_alloc_outputs(1u, out_outputs)) {
amduat_asl_collection_snapshot_payload_free(&snapshot);
free((void *)encoded.data);
if (out_status_code) {
*out_status_code = AMDUAT_PEL_KERNEL_STATUS_OOM;
}
return false;
}
(*out_outputs)[0] = amduat_artifact_with_type(
encoded, amduat_type_tag(AMDUAT_TYPE_TAG_ASL_SNAPSHOT_INFO_1));
if (out_outputs_len != NULL) {
*out_outputs_len = 1u;
}
ok = true;
amduat_asl_collection_snapshot_payload_free(&snapshot);
return ok;
}
bool amduat_kernel_log_read_range(
const amduat_artifact_t *inputs,
size_t inputs_len,
amduat_artifact_t **out_outputs,
size_t *out_outputs_len,
uint32_t *out_status_code) {
amduat_asl_log_range_t range;
amduat_octets_t encoded = amduat_octets(NULL, 0u);
uint64_t from_offset = 0u;
uint32_t limit = 0u;
uint64_t limit_from_offset = 0u;
uint32_t limit_value = 0u;
bool ok = false;
if (inputs == NULL || inputs_len != 3u) {
if (out_status_code) {
*out_status_code = AMDUAT_PEL_KERNEL_STATUS_INTERNAL;
}
return false;
}
if (!amduat_decode_params(&inputs[1], &from_offset, &limit_value)) {
if (out_status_code) {
*out_status_code = AMDUAT_PEL_KERNEL_STATUS_PARAMS_INVALID;
}
return false;
}
if (!amduat_decode_params(&inputs[2], &limit_from_offset, &limit)) {
if (out_status_code) {
*out_status_code = AMDUAT_PEL_KERNEL_STATUS_PARAMS_INVALID;
}
return false;
}
(void)limit_from_offset;
(void)limit_value;
memset(&range, 0, sizeof(range));
range.start_offset = from_offset;
range.next_offset = from_offset;
range.refs = NULL;
range.refs_len = 0u;
if (limit == 0u || amduat_asl_none_is_artifact(&inputs[0])) {
goto encode_range;
}
{
amduat_asl_log_chunk_t *chunks = NULL;
size_t chunks_len = 0u;
amduat_asl_log_chunk_t head_chunk;
uint64_t head_end_offset = 0u;
if (!amduat_log_chunk_from_artifact(&inputs[0], &head_chunk)) {
if (out_status_code) {
*out_status_code = AMDUAT_PEL_KERNEL_STATUS_LOG_CHUNK_INVALID;
}
return false;
}
if (head_chunk.base_offset >
UINT64_MAX - (uint64_t)head_chunk.entry_count) {
amduat_asl_log_chunk_free(&head_chunk);
if (out_status_code) {
*out_status_code = AMDUAT_PEL_KERNEL_STATUS_LOG_CHUNK_INVALID;
}
return false;
}
head_end_offset = head_chunk.base_offset + head_chunk.entry_count;
{
amduat_asl_log_chunk_t *next =
(amduat_asl_log_chunk_t *)realloc(
chunks, (chunks_len + 1u) * sizeof(*chunks));
if (next == NULL) {
amduat_asl_log_chunk_free(&head_chunk);
if (out_status_code) {
*out_status_code = AMDUAT_PEL_KERNEL_STATUS_OOM;
}
return false;
}
chunks = next;
chunks[chunks_len++] = head_chunk;
}
if (from_offset >= head_end_offset) {
for (size_t i = 0u; i < chunks_len; ++i) {
amduat_asl_log_chunk_free(&chunks[i]);
}
free(chunks);
range.next_offset = from_offset;
goto encode_range;
}
while (true) {
amduat_asl_log_chunk_t chunk;
amduat_artifact_t prev_artifact;
if (chunks[chunks_len - 1u].base_offset <= from_offset ||
!chunks[chunks_len - 1u].has_prev) {
break;
}
memset(&prev_artifact, 0, sizeof(prev_artifact));
if (!amduat_pel_kernel_resolve_artifact(
chunks[chunks_len - 1u].prev_ref, &prev_artifact)) {
for (size_t i = 0u; i < chunks_len; ++i) {
amduat_asl_log_chunk_free(&chunks[i]);
}
free(chunks);
if (out_status_code) {
*out_status_code = AMDUAT_PEL_KERNEL_STATUS_REF_RESOLVE_FAILED;
}
return false;
}
if (!amduat_log_chunk_from_artifact(&prev_artifact, &chunk)) {
amduat_artifact_free(&prev_artifact);
for (size_t i = 0u; i < chunks_len; ++i) {
amduat_asl_log_chunk_free(&chunks[i]);
}
free(chunks);
if (out_status_code) {
*out_status_code = AMDUAT_PEL_KERNEL_STATUS_LOG_CHUNK_INVALID;
}
return false;
}
amduat_artifact_free(&prev_artifact);
{
amduat_asl_log_chunk_t *next =
(amduat_asl_log_chunk_t *)realloc(
chunks, (chunks_len + 1u) * sizeof(*chunks));
if (next == NULL) {
amduat_asl_log_chunk_free(&chunk);
for (size_t i = 0u; i < chunks_len; ++i) {
amduat_asl_log_chunk_free(&chunks[i]);
}
free(chunks);
if (out_status_code) {
*out_status_code = AMDUAT_PEL_KERNEL_STATUS_OOM;
}
return false;
}
chunks = next;
chunks[chunks_len++] = chunk;
}
}
if (limit > SIZE_MAX) {
for (size_t i = 0u; i < chunks_len; ++i) {
amduat_asl_log_chunk_free(&chunks[i]);
}
free(chunks);
if (out_status_code) {
*out_status_code = AMDUAT_PEL_KERNEL_STATUS_LOG_RANGE_INVALID;
}
return false;
}
if (limit != 0u) {
range.refs = (amduat_reference_t *)calloc(limit, sizeof(*range.refs));
if (range.refs == NULL) {
for (size_t i = 0u; i < chunks_len; ++i) {
amduat_asl_log_chunk_free(&chunks[i]);
}
free(chunks);
if (out_status_code) {
*out_status_code = AMDUAT_PEL_KERNEL_STATUS_OOM;
}
return false;
}
}
for (size_t i = 0u; i < chunks_len / 2u; ++i) {
amduat_asl_log_chunk_t tmp = chunks[i];
chunks[i] = chunks[chunks_len - 1u - i];
chunks[chunks_len - 1u - i] = tmp;
}
range.refs_len = 0u;
for (size_t i = 0u; i < chunks_len; ++i) {
amduat_asl_log_chunk_t *chunk = &chunks[i];
for (uint32_t j = 0u; j < chunk->entry_count; ++j) {
uint64_t offset = chunk->base_offset + j;
if (offset < from_offset) {
continue;
}
if (range.refs_len == limit) {
goto done_collect;
}
if (!amduat_reference_clone(chunk->entries[j].payload_ref,
&range.refs[range.refs_len])) {
for (size_t k = 0u; k < chunks_len; ++k) {
amduat_asl_log_chunk_free(&chunks[k]);
}
free(chunks);
amduat_asl_log_range_free(&range);
if (out_status_code) {
*out_status_code = AMDUAT_PEL_KERNEL_STATUS_OOM;
}
return false;
}
range.refs_len++;
range.next_offset = offset + 1u;
}
}
done_collect:
if (range.refs_len < limit) {
range.next_offset = head_end_offset;
}
for (size_t i = 0u; i < chunks_len; ++i) {
amduat_asl_log_chunk_free(&chunks[i]);
}
free(chunks);
}
encode_range:
if (!amduat_asl_log_range_encode_v1(&range, &encoded)) {
amduat_asl_log_range_free(&range);
if (out_status_code) {
*out_status_code = AMDUAT_PEL_KERNEL_STATUS_OOM;
}
return false;
}
if (!amduat_alloc_outputs(1u, out_outputs)) {
amduat_asl_log_range_free(&range);
free((void *)encoded.data);
if (out_status_code) {
*out_status_code = AMDUAT_PEL_KERNEL_STATUS_OOM;
}
return false;
}
(*out_outputs)[0] = amduat_artifact_with_type(
encoded, amduat_type_tag(AMDUAT_TYPE_TAG_ASL_LOG_RANGE_1));
if (out_outputs_len != NULL) {
*out_outputs_len = 1u;
}
ok = true;
amduat_asl_log_range_free(&range);
return ok;
}
bool amduat_kernel_collection_merge_refs(
const amduat_artifact_t *inputs,
size_t inputs_len,
amduat_artifact_t **out_outputs,
size_t *out_outputs_len,
uint32_t *out_status_code) {
amduat_asl_collection_snapshot_info_t snapshot;
amduat_asl_log_range_t log_range;
amduat_asl_collection_view_t view;
amduat_octets_t encoded = amduat_octets(NULL, 0u);
uint64_t from_offset = 0u;
uint32_t limit = 0u;
uint64_t limit_from_offset = 0u;
uint32_t limit_value = 0u;
size_t total_refs = 0u;
size_t start_index = 0u;
size_t end_index = 0u;
bool ok = false;
if (inputs == NULL || inputs_len != 4u) {
if (out_status_code) {
*out_status_code = AMDUAT_PEL_KERNEL_STATUS_INTERNAL;
}
return false;
}
if (!amduat_decode_params(&inputs[2], &from_offset, &limit_value) ||
!amduat_decode_params(&inputs[3], &limit_from_offset, &limit)) {
if (out_status_code) {
*out_status_code = AMDUAT_PEL_KERNEL_STATUS_PARAMS_INVALID;
}
return false;
}
(void)limit_from_offset;
(void)limit_value;
memset(&snapshot, 0, sizeof(snapshot));
memset(&log_range, 0, sizeof(log_range));
memset(&view, 0, sizeof(view));
if (!inputs[0].has_type_tag ||
inputs[0].type_tag.tag_id != AMDUAT_TYPE_TAG_ASL_SNAPSHOT_INFO_1 ||
!amduat_asl_collection_snapshot_info_decode_v1(inputs[0].bytes,
&snapshot)) {
if (out_status_code) {
*out_status_code = AMDUAT_PEL_KERNEL_STATUS_COLLECTION_SNAPSHOT_INVALID;
}
return false;
}
if (!inputs[1].has_type_tag ||
inputs[1].type_tag.tag_id != AMDUAT_TYPE_TAG_ASL_LOG_RANGE_1 ||
!amduat_asl_log_range_decode_v1(inputs[1].bytes, &log_range)) {
amduat_asl_collection_snapshot_info_free(&snapshot);
if (out_status_code) {
*out_status_code = AMDUAT_PEL_KERNEL_STATUS_LOG_RANGE_INVALID;
}
return false;
}
if (snapshot.refs_len > SIZE_MAX - log_range.refs_len) {
amduat_asl_collection_snapshot_info_free(&snapshot);
amduat_asl_log_range_free(&log_range);
if (out_status_code) {
*out_status_code = AMDUAT_PEL_KERNEL_STATUS_COLLECTION_VIEW_INVALID;
}
return false;
}
total_refs = snapshot.refs_len + log_range.refs_len;
if (from_offset > SIZE_MAX) {
start_index = total_refs;
} else {
start_index = (size_t)from_offset;
if (start_index > total_refs) {
start_index = total_refs;
}
}
if (limit > SIZE_MAX || start_index > SIZE_MAX - (size_t)limit) {
end_index = total_refs;
} else {
end_index = start_index + (size_t)limit;
if (end_index > total_refs) {
end_index = total_refs;
}
}
view.refs_len = end_index - start_index;
view.refs = NULL;
if (view.refs_len != 0u) {
view.refs = (amduat_reference_t *)calloc(view.refs_len, sizeof(*view.refs));
if (view.refs == NULL) {
amduat_asl_collection_snapshot_info_free(&snapshot);
amduat_asl_log_range_free(&log_range);
if (out_status_code) {
*out_status_code = AMDUAT_PEL_KERNEL_STATUS_OOM;
}
return false;
}
}
for (size_t i = 0u; i < view.refs_len; ++i) {
size_t idx = start_index + i;
const amduat_reference_t *src =
(idx < snapshot.refs_len)
? &snapshot.refs[idx]
: &log_range.refs[idx - snapshot.refs_len];
if (!amduat_reference_clone(*src, &view.refs[i])) {
amduat_asl_collection_view_free(&view);
amduat_asl_collection_snapshot_info_free(&snapshot);
amduat_asl_log_range_free(&log_range);
if (out_status_code) {
*out_status_code = AMDUAT_PEL_KERNEL_STATUS_OOM;
}
return false;
}
}
view.computed_from_offset = from_offset;
if (log_range.refs_len < limit) {
view.computed_up_to_offset = log_range.next_offset;
} else if (from_offset > UINT64_MAX - (uint64_t)view.refs_len) {
view.computed_up_to_offset = UINT64_MAX;
} else {
view.computed_up_to_offset = from_offset + (uint64_t)view.refs_len;
}
if (!amduat_asl_collection_view_encode_v1(&view, &encoded)) {
amduat_asl_collection_view_free(&view);
amduat_asl_collection_snapshot_info_free(&snapshot);
amduat_asl_log_range_free(&log_range);
if (out_status_code) {
*out_status_code = AMDUAT_PEL_KERNEL_STATUS_OOM;
}
return false;
}
if (!amduat_alloc_outputs(1u, out_outputs)) {
amduat_asl_collection_view_free(&view);
amduat_asl_collection_snapshot_info_free(&snapshot);
amduat_asl_log_range_free(&log_range);
free((void *)encoded.data);
if (out_status_code) {
*out_status_code = AMDUAT_PEL_KERNEL_STATUS_OOM;
}
return false;
}
(*out_outputs)[0] = amduat_artifact_with_type(
encoded, amduat_type_tag(AMDUAT_TYPE_TAG_ASL_COLLECTION_VIEW_1));
if (out_outputs_len != NULL) {
*out_outputs_len = 1u;
}
ok = true;
amduat_asl_collection_view_free(&view);
amduat_asl_collection_snapshot_info_free(&snapshot);
amduat_asl_log_range_free(&log_range);
return ok;
}

View file

@ -0,0 +1,29 @@
#ifndef AMDUAT_PEL_OPREG_KERNEL_COLLECTION_H
#define AMDUAT_PEL_OPREG_KERNEL_COLLECTION_H
#include "amduat/pel/opreg_kernel.h"
#include <stddef.h>
bool amduat_kernel_collection_snapshot_decode(
const amduat_artifact_t *inputs,
size_t inputs_len,
amduat_artifact_t **out_outputs,
size_t *out_outputs_len,
uint32_t *out_status_code);
bool amduat_kernel_log_read_range(
const amduat_artifact_t *inputs,
size_t inputs_len,
amduat_artifact_t **out_outputs,
size_t *out_outputs_len,
uint32_t *out_status_code);
bool amduat_kernel_collection_merge_refs(
const amduat_artifact_t *inputs,
size_t inputs_len,
amduat_artifact_t **out_outputs,
size_t *out_outputs_len,
uint32_t *out_status_code);
#endif /* AMDUAT_PEL_OPREG_KERNEL_COLLECTION_H */

View file

@ -133,6 +133,12 @@ bool amduat_pel_kernel_params_decode(
return amduat_decode_unit(params_bytes);
case AMDUAT_PEL_KERNEL_OP_FORMAT_ENCODE:
return amduat_decode_unit(params_bytes);
case AMDUAT_PEL_KERNEL_OP_COLLECTION_SNAPSHOT_DECODE:
return amduat_decode_unit(params_bytes);
case AMDUAT_PEL_KERNEL_OP_LOG_READ_RANGE:
return amduat_decode_unit(params_bytes);
case AMDUAT_PEL_KERNEL_OP_COLLECTION_MERGE_REFS:
return amduat_decode_unit(params_bytes);
default:
return false;
}

View file

@ -6,6 +6,7 @@
#include "amduat/enc/pel_program_dag.h"
#include "amduat/enc/pel_trace_dag.h"
#include "amduat/pel/derivation_sid.h"
#include "amduat/pel/opreg_kernel.h"
#include "amduat/util/log.h"
#include "pel_program_dag_internal.h"
#include "amduat/pel/program_dag_desc.h"
@ -35,6 +36,17 @@ void amduat_pel_surf_free_ref(amduat_reference_t *ref) {
amduat_reference_free(ref);
}
static bool amduat_pel_surf_resolve_artifact(amduat_reference_t ref,
amduat_artifact_t *out_artifact,
void *ctx) {
amduat_asl_store_t *store = (amduat_asl_store_t *)ctx;
if (store == NULL || out_artifact == NULL) {
return false;
}
return amduat_asl_store_get(store, ref, out_artifact) ==
AMDUAT_ASL_STORE_OK;
}
static void amduat_init_core_result(amduat_pel_execution_result_value_t *result,
amduat_reference_t scheme_ref,
amduat_pel_execution_status_t status,
@ -691,9 +703,12 @@ bool amduat_pel_surf_run(amduat_asl_store_t *store,
program_decoded = true;
const amduat_artifact_t *params_arg =
has_params_artifact ? &params_artifact : NULL;
amduat_pel_kernel_set_artifact_resolver(
amduat_pel_surf_resolve_artifact, store);
if (!amduat_pel_program_dag_exec_trace(
&program, input_artifacts, input_refs_len, params_arg, &outputs,
&outputs_len, &core_result, &trace_eval)) {
amduat_pel_kernel_clear_artifact_resolver();
amduat_artifact_free(&program_artifact);
amduat_enc_pel_program_dag_free(&program);
for (i = 0; i < input_refs_len; ++i) {
@ -706,6 +721,7 @@ bool amduat_pel_surf_run(amduat_asl_store_t *store,
amduat_pel_program_dag_free_outputs(outputs, outputs_len);
return false;
}
amduat_pel_kernel_clear_artifact_resolver();
executed = true;
}
}

View file

@ -4,6 +4,8 @@
#include "amduat/asl/asl_pointer_fs.h"
#include "amduat/asl/log_store.h"
#include "amduat/asl/collection.h"
#include "amduat/asl/collection_view.h"
#include "amduat/asl/none.h"
#include "amduat/asl/record.h"
#include "amduat/asl/asl_store_fs.h"
#include "amduat/asl/asl_store_fs_meta.h"
@ -74,6 +76,8 @@ static void amduat_pel_cli_print_usage(FILE *stream) {
" result Surface result tools (decode).\n"
" op Kernel op registry tools.\n"
" log Append-only log tools (append, read).\n"
" col Collection tools (append, snapshot, read, view).\n"
" rec ASL record tools (put, get).\n"
" matcache Materialization cache tools (get, sid).\n"
" ptr Named pointer tools (get, cas).\n"
" scheme Scheme refs, type tags, profile IDs.\n"
@ -145,6 +149,14 @@ static void amduat_pel_cli_print_usage(FILE *stream) {
" amduat-pel log append --log NAME --kind N --ref REF [--actor TEXT]\n"
" amduat-pel log read --log NAME --from OFFSET --limit N\n"
"\n"
"col:\n"
" amduat-pel col append --name NAME --record-ref REF [--kind N]\n"
" [--actor TEXT]\n"
" amduat-pel col snapshot --name NAME [--up-to OFFSET]\n"
" amduat-pel col read --name NAME --from OFFSET --limit N\n"
" amduat-pel col view --name NAME --from OFFSET --limit N\n"
" [--dump-program-ref]\n"
"\n"
"scheme:\n"
" amduat-pel scheme show [--format text|json] [--ref-format hex|bytes]\n"
" amduat-pel scheme dag-ref [--format hex|bytes]\n"
@ -173,7 +185,8 @@ static void amduat_pel_cli_print_usage(FILE *stream) {
" - Only PEL/PROGRAM-DAG/1 is supported; other scheme refs yield SCHEME_UNSUPPORTED.\n"
" - Expected type tags: program 0x00000101, trace 0x00000102, result 0x00000103.\n"
" - Encoding profile IDs: program 0x0101, trace 0x0102, result 0x0103.\n"
" - Kernel ops: pel.bytes.concat, pel.bytes.slice, pel.bytes.const, pel.bytes.hash.asl1, pel.bytes.params, pel.format.encode.\n"
" - Kernel ops: pel.bytes.concat, pel.bytes.slice, pel.bytes.const, pel.bytes.hash.asl1, pel.bytes.params, pel.format.encode,\n"
" collection.snapshot_decode_v1, log.read_range_v1, collection.merge_refs_v1.\n"
" - --ref-format bytes expects REF arguments to be a path or '-' (raw reference bytes).\n"
" - --inputs-file with --ref-format bytes expects raw concatenated references.\n"
" - run stores derivation records for outputs; use --no-index to skip.\n");
@ -3230,6 +3243,232 @@ static bool amduat_pel_cli_init_store(const char *root,
return true;
}
static bool amduat_pel_cli_build_collection_head_name(const char *name,
char **out_name) {
size_t name_len;
size_t total_len;
char *buffer;
size_t offset = 0u;
if (name == NULL || out_name == NULL) {
return false;
}
if (!amduat_asl_pointer_name_is_valid(name)) {
return false;
}
name_len = strlen(name);
total_len = 11u + name_len + 5u + 1u;
buffer = (char *)malloc(total_len);
if (buffer == NULL) {
return false;
}
memcpy(buffer + offset, "collection/", 11u);
offset += 11u;
memcpy(buffer + offset, name, name_len);
offset += name_len;
memcpy(buffer + offset, "/head", 5u);
offset += 5u;
buffer[offset] = '\0';
*out_name = buffer;
return true;
}
static bool amduat_pel_cli_build_collection_log_head_name(const char *name,
char **out_name) {
size_t name_len;
size_t log_name_len;
size_t total_len;
char *buffer;
size_t offset = 0u;
if (name == NULL || out_name == NULL) {
return false;
}
if (!amduat_asl_pointer_name_is_valid(name)) {
return false;
}
name_len = strlen(name);
log_name_len = 11u + name_len + 4u;
total_len = 4u + log_name_len + 5u + 1u;
buffer = (char *)malloc(total_len);
if (buffer == NULL) {
return false;
}
memcpy(buffer + offset, "log/", 4u);
offset += 4u;
memcpy(buffer + offset, "collection/", 11u);
offset += 11u;
memcpy(buffer + offset, name, name_len);
offset += name_len;
memcpy(buffer + offset, "/log", 4u);
offset += 4u;
memcpy(buffer + offset, "/head", 5u);
offset += 5u;
buffer[offset] = '\0';
*out_name = buffer;
return true;
}
static bool amduat_pel_cli_get_none_ref(amduat_asl_store_t *store,
amduat_reference_t *out_ref) {
amduat_artifact_t none_artifact;
if (store == NULL || out_ref == NULL) {
return false;
}
if (!amduat_asl_none_artifact(&none_artifact)) {
return false;
}
if (amduat_asl_store_put(store, none_artifact, out_ref) !=
AMDUAT_ASL_STORE_OK) {
amduat_artifact_free(&none_artifact);
return false;
}
amduat_artifact_free(&none_artifact);
return true;
}
static bool amduat_pel_cli_put_view_params(amduat_asl_store_t *store,
uint64_t from_offset,
uint32_t limit,
amduat_reference_t *out_ref) {
uint8_t payload[12];
amduat_asl_record_t record;
if (store == NULL || out_ref == NULL) {
return false;
}
payload[0] = (uint8_t)(from_offset & 0xffu);
payload[1] = (uint8_t)((from_offset >> 8) & 0xffu);
payload[2] = (uint8_t)((from_offset >> 16) & 0xffu);
payload[3] = (uint8_t)((from_offset >> 24) & 0xffu);
payload[4] = (uint8_t)((from_offset >> 32) & 0xffu);
payload[5] = (uint8_t)((from_offset >> 40) & 0xffu);
payload[6] = (uint8_t)((from_offset >> 48) & 0xffu);
payload[7] = (uint8_t)((from_offset >> 56) & 0xffu);
payload[8] = (uint8_t)(limit & 0xffu);
payload[9] = (uint8_t)((limit >> 8) & 0xffu);
payload[10] = (uint8_t)((limit >> 16) & 0xffu);
payload[11] = (uint8_t)((limit >> 24) & 0xffu);
record.schema = amduat_octets("pel/params", strlen("pel/params"));
record.payload = amduat_octets(payload, sizeof(payload));
if (amduat_asl_record_store_put(store,
record.schema,
record.payload,
out_ref) != AMDUAT_ASL_STORE_OK) {
return false;
}
return true;
}
static void amduat_pel_cli_program_free(amduat_pel_program_t *program) {
if (program == NULL || program->nodes == NULL) {
return;
}
for (size_t i = 0u; i < program->nodes_len; ++i) {
free(program->nodes[i].inputs);
}
free(program->nodes);
free(program->roots);
program->nodes = NULL;
program->roots = NULL;
program->nodes_len = 0u;
program->roots_len = 0u;
}
static bool amduat_pel_cli_build_collection_view_program(
amduat_pel_program_t *out_program) {
static const char k_op_snapshot[] = "collection.snapshot_decode_v1";
static const char k_op_read_range[] = "log.read_range_v1";
static const char k_op_merge[] = "collection.merge_refs_v1";
amduat_pel_node_t *nodes;
amduat_pel_root_ref_t *roots;
if (out_program == NULL) {
return false;
}
memset(out_program, 0, sizeof(*out_program));
nodes = (amduat_pel_node_t *)calloc(3u, sizeof(*nodes));
roots = (amduat_pel_root_ref_t *)calloc(1u, sizeof(*roots));
if (nodes == NULL || roots == NULL) {
free(nodes);
free(roots);
return false;
}
nodes[0].id = 1u;
nodes[0].op.name = amduat_octets(k_op_snapshot, strlen(k_op_snapshot));
nodes[0].op.version = 1u;
nodes[0].inputs_len = 1u;
nodes[0].inputs =
(amduat_pel_dag_input_t *)calloc(1u, sizeof(*nodes[0].inputs));
if (nodes[0].inputs == NULL) {
free(nodes);
free(roots);
return false;
}
nodes[0].inputs[0].kind = AMDUAT_PEL_DAG_INPUT_EXTERNAL;
nodes[0].inputs[0].value.external.input_index = 0u;
nodes[0].params = amduat_octets(NULL, 0u);
nodes[1].id = 2u;
nodes[1].op.name = amduat_octets(k_op_read_range, strlen(k_op_read_range));
nodes[1].op.version = 1u;
nodes[1].inputs_len = 3u;
nodes[1].inputs =
(amduat_pel_dag_input_t *)calloc(3u, sizeof(*nodes[1].inputs));
if (nodes[1].inputs == NULL) {
free(nodes[0].inputs);
free(nodes);
free(roots);
return false;
}
nodes[1].inputs[0].kind = AMDUAT_PEL_DAG_INPUT_EXTERNAL;
nodes[1].inputs[0].value.external.input_index = 1u;
nodes[1].inputs[1].kind = AMDUAT_PEL_DAG_INPUT_EXTERNAL;
nodes[1].inputs[1].value.external.input_index = 2u;
nodes[1].inputs[2].kind = AMDUAT_PEL_DAG_INPUT_EXTERNAL;
nodes[1].inputs[2].value.external.input_index = 3u;
nodes[1].params = amduat_octets(NULL, 0u);
nodes[2].id = 3u;
nodes[2].op.name = amduat_octets(k_op_merge, strlen(k_op_merge));
nodes[2].op.version = 1u;
nodes[2].inputs_len = 4u;
nodes[2].inputs =
(amduat_pel_dag_input_t *)calloc(4u, sizeof(*nodes[2].inputs));
if (nodes[2].inputs == NULL) {
free(nodes[1].inputs);
free(nodes[0].inputs);
free(nodes);
free(roots);
return false;
}
nodes[2].inputs[0].kind = AMDUAT_PEL_DAG_INPUT_NODE;
nodes[2].inputs[0].value.node.node_id = 1u;
nodes[2].inputs[0].value.node.output_index = 0u;
nodes[2].inputs[1].kind = AMDUAT_PEL_DAG_INPUT_NODE;
nodes[2].inputs[1].value.node.node_id = 2u;
nodes[2].inputs[1].value.node.output_index = 0u;
nodes[2].inputs[2].kind = AMDUAT_PEL_DAG_INPUT_EXTERNAL;
nodes[2].inputs[2].value.external.input_index = 2u;
nodes[2].inputs[3].kind = AMDUAT_PEL_DAG_INPUT_EXTERNAL;
nodes[2].inputs[3].value.external.input_index = 3u;
nodes[2].params = amduat_octets(NULL, 0u);
roots[0].node_id = 3u;
roots[0].output_index = 0u;
out_program->nodes = nodes;
out_program->nodes_len = 3u;
out_program->roots = roots;
out_program->roots_len = 1u;
return true;
}
static int amduat_pel_cli_cmd_log_append(
int argc,
char **argv,
@ -3895,6 +4134,283 @@ static int amduat_pel_cli_cmd_col_read(
return AMDUAT_PEL_CLI_EXIT_OK;
}
static int amduat_pel_cli_cmd_col_view(
int argc,
char **argv,
const amduat_pel_cli_global_opts_t *global) {
const char *name = NULL;
uint64_t from = 0u;
unsigned long long limit = 0u;
bool dump_program_ref = false;
amduat_asl_store_t store;
amduat_asl_store_fs_t fs;
amduat_asl_pointer_store_t pointer_store;
amduat_reference_t snapshot_ref;
amduat_reference_t log_head_ref;
amduat_reference_t none_ref;
amduat_reference_t params_ref;
amduat_reference_t program_ref;
amduat_reference_t input_refs[4];
amduat_pel_program_t program;
amduat_octets_t program_bytes = amduat_octets(NULL, 0u);
amduat_pel_run_result_t run_result;
amduat_artifact_t view_artifact;
amduat_asl_collection_view_t view;
amduat_type_tag_t expected_type_tag;
amduat_asl_encoding_profile_id_t expected_profile;
char *snapshot_name = NULL;
char *log_head_name = NULL;
bool snapshot_exists = false;
bool log_head_exists = false;
bool stdin_used = false;
int exit_code = AMDUAT_PEL_CLI_EXIT_OK;
int i;
if (global == NULL) {
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
memset(&snapshot_ref, 0, sizeof(snapshot_ref));
memset(&log_head_ref, 0, sizeof(log_head_ref));
memset(&none_ref, 0, sizeof(none_ref));
memset(&params_ref, 0, sizeof(params_ref));
memset(&program_ref, 0, sizeof(program_ref));
for (i = 0; i < argc; ++i) {
if (strcmp(argv[i], "--name") == 0) {
if (i + 1 >= argc) {
fprintf(stderr, "error: --name requires a value\n");
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
name = argv[++i];
} else if (strcmp(argv[i], "--from") == 0) {
if (i + 1 >= argc) {
fprintf(stderr, "error: --from requires a value\n");
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
from = (uint64_t)strtoull(argv[++i], NULL, 10);
} else if (strcmp(argv[i], "--limit") == 0) {
if (i + 1 >= argc) {
fprintf(stderr, "error: --limit requires a value\n");
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
limit = strtoull(argv[++i], NULL, 10);
} else if (strcmp(argv[i], "--dump-program-ref") == 0) {
dump_program_ref = true;
} else if (strcmp(argv[i], "--help") == 0 ||
strcmp(argv[i], "-h") == 0) {
amduat_pel_cli_print_usage(stdout);
return AMDUAT_PEL_CLI_EXIT_OK;
} else {
fprintf(stderr, "error: unknown option: %s\n", argv[i]);
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
}
if (name == NULL || limit == 0u) {
fprintf(stderr, "error: --name and --limit are required\n");
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
if (limit > UINT32_MAX) {
fprintf(stderr, "error: --limit out of range\n");
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
if (!amduat_pel_cli_init_store(global->root, &store, &fs)) {
fprintf(stderr, "error: failed to initialize store\n");
return AMDUAT_PEL_CLI_EXIT_CONFIG;
}
if (!amduat_asl_pointer_store_init(&pointer_store, global->root)) {
fprintf(stderr, "error: failed to init pointer store\n");
return AMDUAT_PEL_CLI_EXIT_CONFIG;
}
if (!amduat_pel_cli_get_none_ref(&store, &none_ref)) {
fprintf(stderr, "error: failed to create none artifact\n");
return AMDUAT_PEL_CLI_EXIT_STORE;
}
if (!amduat_pel_cli_build_collection_head_name(name, &snapshot_name) ||
!amduat_pel_cli_build_collection_log_head_name(name, &log_head_name)) {
fprintf(stderr, "error: invalid collection name\n");
exit_code = AMDUAT_PEL_CLI_EXIT_USAGE;
goto view_cleanup;
}
if (amduat_asl_pointer_get(&pointer_store, snapshot_name,
&snapshot_exists, &snapshot_ref) !=
AMDUAT_ASL_POINTER_OK) {
fprintf(stderr, "error: failed to read collection head\n");
exit_code = AMDUAT_PEL_CLI_EXIT_IO;
goto view_cleanup;
}
if (!snapshot_exists &&
!amduat_reference_clone(none_ref, &snapshot_ref)) {
fprintf(stderr, "error: failed to clone none ref\n");
exit_code = AMDUAT_PEL_CLI_EXIT_STORE;
goto view_cleanup;
}
if (amduat_asl_pointer_get(&pointer_store, log_head_name,
&log_head_exists, &log_head_ref) !=
AMDUAT_ASL_POINTER_OK) {
fprintf(stderr, "error: failed to read log head\n");
exit_code = AMDUAT_PEL_CLI_EXIT_IO;
goto view_cleanup;
}
if (!log_head_exists &&
!amduat_reference_clone(none_ref, &log_head_ref)) {
fprintf(stderr, "error: failed to clone none ref\n");
exit_code = AMDUAT_PEL_CLI_EXIT_STORE;
goto view_cleanup;
}
if (!amduat_pel_cli_put_view_params(&store, from, (uint32_t)limit,
&params_ref)) {
fprintf(stderr, "error: failed to store params\n");
exit_code = AMDUAT_PEL_CLI_EXIT_STORE;
goto view_cleanup;
}
if (!amduat_pel_cli_build_collection_view_program(&program)) {
fprintf(stderr, "error: failed to build program\n");
exit_code = AMDUAT_PEL_CLI_EXIT_CODEC;
goto view_cleanup;
}
if (!amduat_enc_pel_program_dag_encode_v1(&program, &program_bytes)) {
amduat_pel_cli_program_free(&program);
fprintf(stderr, "error: failed to encode program\n");
exit_code = AMDUAT_PEL_CLI_EXIT_CODEC;
goto view_cleanup;
}
amduat_pel_cli_program_free(&program);
if (!amduat_pel_program_dag_desc_get_program_binding(&expected_type_tag,
&expected_profile)) {
fprintf(stderr, "error: failed to load program binding\n");
exit_code = AMDUAT_PEL_CLI_EXIT_CODEC;
goto view_cleanup;
}
if (expected_profile != AMDUAT_PEL_ENC_PROGRAM_DAG_V1) {
fprintf(stderr, "error: unsupported program profile\n");
exit_code = AMDUAT_PEL_CLI_EXIT_UNSUPPORTED;
goto view_cleanup;
}
{
amduat_artifact_t program_artifact =
amduat_artifact_with_type(program_bytes, expected_type_tag);
if (amduat_asl_store_put(&store, program_artifact, &program_ref) !=
AMDUAT_ASL_STORE_OK) {
fprintf(stderr, "error: failed to store program\n");
exit_code = AMDUAT_PEL_CLI_EXIT_STORE;
goto view_cleanup;
}
}
if (dump_program_ref) {
fputs("program_ref=", stdout);
if (!amduat_format_ref_write_text(stdout, program_ref,
global->ref_format)) {
fprintf(stderr, "error: failed to format program ref\n");
exit_code = AMDUAT_PEL_CLI_EXIT_CODEC;
goto view_cleanup;
}
fputc('\n', stdout);
}
input_refs[0] = snapshot_ref;
input_refs[1] = log_head_ref;
input_refs[2] = params_ref;
input_refs[3] = params_ref;
memset(&run_result, 0, sizeof(run_result));
if (!amduat_pel_surf_run_with_result(&store,
amduat_pel_program_dag_scheme_ref(),
program_ref,
input_refs,
4u,
true,
params_ref,
&run_result)) {
fprintf(stderr, "error: PEL surface execution failed\n");
exit_code = AMDUAT_PEL_CLI_EXIT_STORE;
goto view_cleanup;
}
if (!run_result.has_result_value ||
run_result.result_value.core_result.status != AMDUAT_PEL_EXEC_STATUS_OK) {
fprintf(stderr, "error: projection execution failed\n");
exit_code = AMDUAT_PEL_CLI_EXIT_STORE;
goto view_cleanup;
}
if (run_result.output_refs_len != 1u) {
fprintf(stderr, "error: unexpected output count\n");
exit_code = AMDUAT_PEL_CLI_EXIT_STORE;
goto view_cleanup;
}
memset(&view_artifact, 0, sizeof(view_artifact));
if (amduat_asl_store_get(&store, run_result.output_refs[0],
&view_artifact) != AMDUAT_ASL_STORE_OK) {
fprintf(stderr, "error: failed to load view artifact\n");
exit_code = AMDUAT_PEL_CLI_EXIT_STORE;
goto view_cleanup;
}
if (!view_artifact.has_type_tag ||
view_artifact.type_tag.tag_id != AMDUAT_TYPE_TAG_ASL_COLLECTION_VIEW_1 ||
!amduat_asl_collection_view_decode_v1(view_artifact.bytes, &view)) {
amduat_artifact_free(&view_artifact);
fprintf(stderr, "error: invalid view artifact\n");
exit_code = AMDUAT_PEL_CLI_EXIT_CODEC;
goto view_cleanup;
}
amduat_artifact_free(&view_artifact);
fputs("view_ref=", stdout);
if (!amduat_format_ref_write_text(stdout, run_result.output_refs[0],
global->ref_format)) {
fprintf(stderr, "error: failed to format view ref\n");
amduat_asl_collection_view_free(&view);
exit_code = AMDUAT_PEL_CLI_EXIT_CODEC;
goto view_cleanup;
}
fputc('\n', stdout);
printf("computed_from_offset=%" PRIu64 "\n", view.computed_from_offset);
printf("computed_up_to_offset=%" PRIu64 "\n", view.computed_up_to_offset);
printf("entry_count=%zu\n", view.refs_len);
for (size_t idx = 0u; idx < view.refs_len; ++idx) {
fputs("entry_ref=", stdout);
if (!amduat_format_ref_write_text(stdout, view.refs[idx],
global->ref_format)) {
fprintf(stderr, "error: failed to format entry ref\n");
amduat_asl_collection_view_free(&view);
exit_code = AMDUAT_PEL_CLI_EXIT_CODEC;
goto view_cleanup;
}
fputc('\n', stdout);
}
amduat_asl_collection_view_free(&view);
view_cleanup:
if (run_result.has_result_value) {
amduat_enc_pel1_result_free(&run_result.result_value);
}
if (run_result.output_refs != NULL) {
amduat_pel_surf_free_refs(run_result.output_refs,
run_result.output_refs_len);
}
amduat_pel_surf_free_ref(&run_result.result_ref);
amduat_pel_cli_free_reference(&snapshot_ref);
amduat_pel_cli_free_reference(&log_head_ref);
amduat_pel_cli_free_reference(&none_ref);
amduat_pel_cli_free_reference(&params_ref);
amduat_pel_cli_free_reference(&program_ref);
free((void *)program_bytes.data);
free(snapshot_name);
free(log_head_name);
return exit_code;
}
static int amduat_pel_cli_cmd_col(
int argc,
char **argv,
@ -3912,6 +4428,9 @@ static int amduat_pel_cli_cmd_col(
if (strcmp(argv[0], "read") == 0) {
return amduat_pel_cli_cmd_col_read(argc - 1, argv + 1, global);
}
if (strcmp(argv[0], "view") == 0) {
return amduat_pel_cli_cmd_col_view(argc - 1, argv + 1, global);
}
fprintf(stderr, "error: unknown col subcommand: %s\n", argv[0]);
return AMDUAT_PEL_CLI_EXIT_USAGE;
}