diff --git a/include/amduat/enc/asl_log.h b/include/amduat/enc/asl_log.h index ca0a6e0..9d2372a 100644 --- a/include/amduat/enc/asl_log.h +++ b/include/amduat/enc/asl_log.h @@ -38,6 +38,14 @@ bool amduat_enc_asl_log_decode_v1(amduat_octets_t bytes, void amduat_enc_asl_log_free(amduat_asl_log_record_t *records, size_t record_count); +/* Caller owns out_ref digest; free with amduat_reference_free. */ +bool amduat_asl_log_decode_artifact_ref(amduat_octets_t payload, + amduat_reference_t *out_ref); + +/* Caller owns out_bytes; free with amduat_octets_free. */ +bool amduat_asl_log_encode_artifact_ref(amduat_reference_t ref, + amduat_octets_t *out_bytes); + #ifdef __cplusplus } /* extern "C" */ #endif diff --git a/src/near_core/enc/asl_log.c b/src/near_core/enc/asl_log.c index e62eb1a..0c492e1 100644 --- a/src/near_core/enc/asl_log.c +++ b/src/near_core/enc/asl_log.c @@ -29,6 +29,11 @@ static void amduat_asl_log_store_u32_le(uint8_t *out, uint32_t value) { out[3] = (uint8_t)((value >> 24) & 0xffu); } +static void amduat_asl_log_store_u16_le(uint8_t *out, uint16_t value) { + out[0] = (uint8_t)(value & 0xffu); + out[1] = (uint8_t)((value >> 8) & 0xffu); +} + static void amduat_asl_log_store_u64_le(uint8_t *out, uint64_t value) { out[0] = (uint8_t)(value & 0xffu); out[1] = (uint8_t)((value >> 8) & 0xffu); @@ -54,6 +59,19 @@ static bool amduat_asl_log_read_u32_le(amduat_asl_log_cursor_t *cur, return true; } +static bool amduat_asl_log_read_u16_le(amduat_asl_log_cursor_t *cur, + uint16_t *out) { + const uint8_t *data; + + if (cur->len - cur->offset < 2) { + return false; + } + data = cur->data + cur->offset; + *out = (uint16_t)data[0] | ((uint16_t)data[1] << 8); + cur->offset += 2; + return true; +} + static bool amduat_asl_log_read_u64_le(amduat_asl_log_cursor_t *cur, uint64_t *out) { const uint8_t *data; @@ -92,6 +110,67 @@ static bool amduat_asl_log_is_known_record_type(uint32_t record_type) { } } +bool amduat_asl_log_decode_artifact_ref(amduat_octets_t payload, + amduat_reference_t *out_ref) { + amduat_asl_log_cursor_t cur; + uint32_t hash_id_raw; + uint16_t digest_len; + uint16_t reserved0; + + if (out_ref == NULL || payload.data == NULL || payload.len < 8u) { + return false; + } + cur.data = payload.data; + cur.len = payload.len; + cur.offset = 0; + + if (!amduat_asl_log_read_u32_le(&cur, &hash_id_raw) || + !amduat_asl_log_read_u16_le(&cur, &digest_len) || + !amduat_asl_log_read_u16_le(&cur, &reserved0)) { + return false; + } + if (hash_id_raw > UINT16_MAX || digest_len == 0 || reserved0 != 0) { + return false; + } + if (cur.len - cur.offset < digest_len) { + return false; + } + { + amduat_octets_t digest = amduat_octets(cur.data + cur.offset, digest_len); + amduat_reference_t tmp = + amduat_reference((amduat_hash_id_t)hash_id_raw, digest); + return amduat_reference_clone(tmp, out_ref); + } +} + +bool amduat_asl_log_encode_artifact_ref(amduat_reference_t ref, + amduat_octets_t *out_bytes) { + uint8_t *buf; + size_t len; + + if (out_bytes == NULL) { + return false; + } + *out_bytes = amduat_octets(NULL, 0u); + if (ref.hash_id == 0 || ref.digest.data == NULL || ref.digest.len == 0) { + return false; + } + if (ref.digest.len > UINT16_MAX) { + return false; + } + len = 8u + ref.digest.len; + buf = (uint8_t *)malloc(len); + if (buf == NULL) { + return false; + } + amduat_asl_log_store_u32_le(buf, ref.hash_id); + amduat_asl_log_store_u16_le(buf + 4u, (uint16_t)ref.digest.len); + amduat_asl_log_store_u16_le(buf + 6u, 0u); + memcpy(buf + 8u, ref.digest.data, ref.digest.len); + *out_bytes = amduat_octets(buf, len); + return true; +} + static bool amduat_asl_log_hash_record(const uint8_t prev_hash[32], uint64_t logseq, uint32_t record_type,