amduat/tests/enc/test_fcs_pcb1.c

237 lines
6.3 KiB
C
Raw Normal View History

2026-02-22 00:25:56 +01:00
#include "amduat/enc/fcs1.h"
#include "amduat/enc/asl1_core_codec.h"
#include "amduat/fps.h"
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static bool encode_varint(uint64_t value, uint8_t **out, size_t *out_len) {
uint8_t buf[10];
size_t len = 0u;
do {
uint8_t byte = (uint8_t)(value & 0x7fu);
value >>= 7u;
if (value != 0u) {
byte |= 0x80u;
}
buf[len++] = byte;
} while (value != 0u);
*out = (uint8_t *)malloc(len);
if (*out == NULL) {
return false;
}
memcpy(*out, buf, len);
*out_len = len;
return true;
}
static bool append_bytes(uint8_t **buf, size_t *len, size_t *cap,
const void *data, size_t data_len) {
if (*len + data_len > *cap) {
size_t next = *cap == 0u ? 64u : *cap * 2u;
while (next < *len + data_len) {
next *= 2u;
}
uint8_t *next_buf = (uint8_t *)realloc(*buf, next);
if (next_buf == NULL) {
return false;
}
*buf = next_buf;
*cap = next;
}
memcpy(*buf + *len, data, data_len);
*len += data_len;
return true;
}
static bool append_varint(uint8_t **buf, size_t *len, size_t *cap,
uint64_t value) {
uint8_t *enc = NULL;
size_t enc_len = 0u;
bool ok = encode_varint(value, &enc, &enc_len) &&
append_bytes(buf, len, cap, enc, enc_len);
free(enc);
return ok;
}
static bool build_pcb1_bytes(amduat_octets_t *out_bytes,
amduat_reference_t *out_cid) {
uint8_t *buf = NULL;
size_t len = 0u;
size_t cap = 0u;
uint8_t manifest[1 + 1 + 1 + 1 + 32];
size_t manifest_len = 0u;
uint8_t slot_data[] = {0x01, 0x02, 0x03};
amduat_octets_t payload;
amduat_octets_t cid_bytes;
manifest[manifest_len++] = 0x01; /* slot count */
manifest[manifest_len++] = 0x01; /* index */
manifest[manifest_len++] = 0x00; /* name len */
manifest[manifest_len++] = 0x00; /* type */
manifest[manifest_len++] = 0x20; /* digest len */
memset(manifest + manifest_len, 0, 32);
manifest_len += 32;
if (!append_bytes(&buf, &len, &cap, "PCB1", 4u)) {
return false;
}
{
uint8_t header[3] = {0x01, 0x00, 0x00};
if (!append_bytes(&buf, &len, &cap, header, sizeof(header))) {
free(buf);
return false;
}
}
if (!append_bytes(&buf, &len, &cap, (uint8_t[]){0x50}, 1u) ||
!append_varint(&buf, &len, &cap, manifest_len) ||
!append_bytes(&buf, &len, &cap, manifest, manifest_len)) {
free(buf);
return false;
}
if (!append_bytes(&buf, &len, &cap, (uint8_t[]){0x51}, 1u) ||
!append_varint(&buf, &len, &cap, sizeof(slot_data)) ||
!append_bytes(&buf, &len, &cap, slot_data, sizeof(slot_data))) {
free(buf);
return false;
}
payload = amduat_octets(buf, len);
if (!amduat_fps_cid_for_payload(AMDUAT_HASH_ASL1_ID_SHA256,
payload,
out_cid)) {
free(buf);
return false;
}
if (!amduat_enc_asl1_core_encode_reference_v1(*out_cid, &cid_bytes)) {
amduat_reference_free(out_cid);
free(buf);
return false;
}
amduat_octets_free(&cid_bytes);
*out_bytes = payload;
return true;
}
static bool build_fcs1_bytes(amduat_octets_t *out_bytes,
amduat_reference_t function_ref,
amduat_reference_t pcb_ref,
uint32_t arity) {
uint8_t *buf = NULL;
size_t len = 0u;
size_t cap = 0u;
amduat_octets_t func_bytes;
amduat_octets_t pcb_bytes;
if (!amduat_enc_asl1_core_encode_reference_v1(function_ref, &func_bytes) ||
!amduat_enc_asl1_core_encode_reference_v1(pcb_ref, &pcb_bytes)) {
return false;
}
if (!append_bytes(&buf, &len, &cap, "FCS1", 4u)) {
return false;
}
{
uint8_t header[3] = {0x01, 0x00, 0x00};
if (!append_bytes(&buf, &len, &cap, header, sizeof(header))) {
free(buf);
return false;
}
}
if (!append_bytes(&buf, &len, &cap, (uint8_t[]){0x30}, 1u) ||
!append_varint(&buf, &len, &cap, func_bytes.len) ||
!append_bytes(&buf, &len, &cap, func_bytes.data, func_bytes.len)) {
free(buf);
amduat_octets_free(&func_bytes);
amduat_octets_free(&pcb_bytes);
return false;
}
if (!append_bytes(&buf, &len, &cap, (uint8_t[]){0x31}, 1u) ||
!append_varint(&buf, &len, &cap, pcb_bytes.len) ||
!append_bytes(&buf, &len, &cap, pcb_bytes.data, pcb_bytes.len)) {
free(buf);
amduat_octets_free(&func_bytes);
amduat_octets_free(&pcb_bytes);
return false;
}
if (!append_bytes(&buf, &len, &cap, (uint8_t[]){0x32}, 1u) ||
!append_varint(&buf, &len, &cap, arity)) {
free(buf);
amduat_octets_free(&func_bytes);
amduat_octets_free(&pcb_bytes);
return false;
}
amduat_octets_free(&func_bytes);
amduat_octets_free(&pcb_bytes);
*out_bytes = amduat_octets(buf, len);
return true;
}
typedef struct {
amduat_reference_t pcb_ref;
amduat_octets_t pcb_bytes;
} resolver_ctx_t;
static bool resolve_ref(void *ctx,
amduat_reference_t ref,
amduat_octets_t *out_bytes) {
resolver_ctx_t *state = (resolver_ctx_t *)ctx;
if (state == NULL || out_bytes == NULL) {
return false;
}
if (!amduat_reference_eq(ref, state->pcb_ref)) {
return false;
}
return amduat_octets_clone(state->pcb_bytes, out_bytes);
}
int main(void) {
amduat_octets_t pcb_bytes;
amduat_reference_t pcb_ref;
amduat_octets_t fcs_bytes;
amduat_reference_t func_ref;
uint8_t func_digest[32];
resolver_ctx_t ctx;
amduat_fcs1_error_t err;
if (!build_pcb1_bytes(&pcb_bytes, &pcb_ref)) {
return 1;
}
memset(func_digest, 0x11, sizeof(func_digest));
func_ref = amduat_reference(AMDUAT_HASH_ASL1_ID_SHA256,
amduat_octets(func_digest,
sizeof(func_digest)));
if (!build_fcs1_bytes(&fcs_bytes, func_ref, pcb_ref, 1u)) {
amduat_reference_free(&pcb_ref);
amduat_octets_free(&pcb_bytes);
return 1;
}
ctx.pcb_ref = pcb_ref;
ctx.pcb_bytes = pcb_bytes;
err = amduat_fcs1_validate_v1(fcs_bytes, resolve_ref, &ctx);
if (err != AMDUAT_FCS1_OK) {
amduat_reference_free(&pcb_ref);
amduat_octets_free(&pcb_bytes);
amduat_octets_free(&fcs_bytes);
return 1;
}
amduat_reference_free(&pcb_ref);
amduat_octets_free(&pcb_bytes);
amduat_octets_free(&fcs_bytes);
return 0;
}