MCEL: Merkle-Chaining Event Ledger 1.0.0.0a (A1)
A post-quantum secure block-chain ledger system
udil.h
Go to the documentation of this file.
1/* 2025-2026 Quantum Resistant Cryptographic Solutions Corporation
2 * All Rights Reserved.
3 *
4 * NOTICE:
5 * This software and all accompanying materials are the exclusive property of
6 * Quantum Resistant Cryptographic Solutions Corporation (QRCS). The intellectual
7 * and technical concepts contained herein are proprietary to QRCS and are
8 * protected under applicable Canadian, U.S., and international copyright,
9 * patent, and trade secret laws.
10 *
11 * CRYPTOGRAPHIC ALGORITHMS AND IMPLEMENTATIONS:
12 * - This software includes implementations of cryptographic primitives and
13 * algorithms that are standardized or in the public domain, such as AES
14 * and SHA-3, which are not proprietary to QRCS.
15 * - This software also includes cryptographic primitives, constructions, and
16 * algorithms designed by QRCS, including but not limited to RCS, SCB, CSX, QMAC, and
17 * related components, which are proprietary to QRCS.
18 * - All source code, implementations, protocol compositions, optimizations,
19 * parameter selections, and engineering work contained in this software are
20 * original works of QRCS and are protected under this license.
21 *
22 * LICENSE AND USE RESTRICTIONS:
23 * - This software is licensed under the Quantum Resistant Cryptographic Solutions
24 * Public Research and Evaluation License (QRCS-PREL), 2025-2026.
25 * - Permission is granted solely for non-commercial evaluation, academic research,
26 * cryptographic analysis, interoperability testing, and feasibility assessment.
27 * - Commercial use, production deployment, commercial redistribution, or
28 * integration into products or services is strictly prohibited without a
29 * separate written license agreement executed with QRCS.
30 * - Licensing and authorized distribution are solely at the discretion of QRCS.
31 *
32 * EXPERIMENTAL CRYPTOGRAPHY NOTICE:
33 * Portions of this software may include experimental, novel, or evolving
34 * cryptographic designs. Use of this software is entirely at the user's risk.
35 *
36 * DISCLAIMER:
37 * THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
38 * IMPLIED, INCLUDING BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, FITNESS
39 * FOR A PARTICULAR PURPOSE, SECURITY, OR NON-INFRINGEMENT. QRCS DISCLAIMS ALL
40 * LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
41 * ARISING FROM THE USE OR MISUSE OF THIS SOFTWARE.
42 *
43 * FULL LICENSE:
44 * This software is subject to the Quantum Resistant Cryptographic Solutions
45 * Public Research and Evaluation License (QRCS-PREL), 2025-2026. The complete license terms
46 * are provided in the accompanying LICENSE file or at https://www.qrcscorp.ca.
47 *
48 * Written by: John G. Underhill
49 * Contact: contact\qrcscorp.ca
50 */
51
52#ifndef UDIL_H
53#define UDIL_H
54
55#include "udilcommon.h"
56
106
107//#define UDIL_HASHLEN 32
108//#define MAX_DEPTH 64
109//
110//static const uint8_t TAG_CHK[] = "UDIL/CHK";
111//static const uint8_t TAG_ENV[] = "UDIL/ENV";
112//static const uint8_t TAG_ID[] = "UDIL/ID";
113//static const uint8_t TAG_LEAF[] = "UDIL/LEAF";
114//static const uint8_t TAG_NODE[] = "UDIL/NODE";
115//static const uint8_t TAG_PAY[] = "UDIL/PAY";
116//static const uint8_t TAG_REC[] = "UDIL/REC";
117//static const uint8_t TAG_SIG_CHK[] = "UDIL/SIG/CHK";
118//static const uint8_t TAG_SIG_REC[] = "UDIL/SIG/REC";
119//
120//UDIL_EXPORT_API typedef enum
121//{
122// RTYPE_MESSAGE = 0x0001,
123// RTYPE_ACK = 0x0002,
124// RTYPE_NACK = 0x0003,
125// RTYPE_RECEIPT = 0x0004,
126// RTYPE_ADMIN = 0x0005,
127// RTYPE_CHECKPOINT = 0x0006,
128// RTYPE_ANCHOR_REF = 0x0007
129//} udil_record_type;
130//
131//UDIL_EXPORT_API typedef struct udil_anchor_ref
132//{
133// uint16_t version;
134// uint8_t chk_commit[UDIL_HASHLEN];
135// uint16_t anchor_type; // 1=consortium, 2=regulator, 3=provenance-pillar
136// uint8_t anchor_id[32]; // for example txid hash, receipt id hash
137// uint64_t anchored_time;
138// uint8_t reserved[16];
139//} udil_anchor_ref;
140//
141//UDIL_EXPORT_API typedef struct udil_merkle_proof
142//{
143// uint8_t siblings[MAX_DEPTH][UDIL_HASHLEN];
144// uint8_t directions[MAX_DEPTH];
145// size_t depth;
146//} udil_merkle_proof;
147//
148//UDIL_EXPORT_API typedef struct udil_envelope
149//{
150// uint16_t version;
151// uint16_t msg_type;
152// uint8_t sender_id[UDIL_HASHLEN];
153// uint8_t receiver_id[UDIL_HASHLEN];
154// uint8_t corr_id[16];
155// uint64_t time;
156// uint64_t valid_until;
157//} udil_envelope;
158//
159//UDIL_EXPORT_API typedef struct udil_record_hdr
160//{
161// uint16_t version;
162// uint16_t rtype;
163// uint8_t ledger_id[UDIL_HASHLEN];
164// uint32_t epoch;
165// uint64_t seq;
166// uint64_t time;
167// uint8_t prev_hash[UDIL_HASHLEN];
168// uint8_t env_hash[UDIL_HASHLEN];
169// uint8_t pay_hash[UDIL_HASHLEN];
170// uint8_t corr_id[16];
171// uint32_t flags;
172//} udil_record_hdr;
173//
174//UDIL_EXPORT_API typedef struct udil_checkpoint_body
175//{
176// uint16_t body_version;
177// uint8_t ledger_id[UDIL_HASHLEN];
178// uint32_t epoch;
179// uint64_t start_seq;
180// uint64_t end_seq;
181// uint32_t record_count;
182// uint8_t batch_root[UDIL_HASHLEN];
183// uint8_t prev_checkpoint_commit[UDIL_HASHLEN];
184// uint64_t created_time;
185// uint32_t flags;
186// uint8_t reserved[16];
187//} udil_checkpoint_body;
188//
189//UDIL_EXPORT_API typedef struct udil_ledger_state
190//{
191// uint8_t ledger_id[UDIL_HASHLEN];
192// uint32_t epoch;
193// uint64_t head_seq;
194// uint8_t head_hash[UDIL_HASHLEN];
195// uint64_t last_checkpoint_end_seq;
196// uint8_t last_checkpoint_commit[UDIL_HASHLEN];
197// void* udif_signing_key;
198// void* store;
199//} udil_ledger_state;
200//
201//
202//int32_t store_append(void* store, const uint8_t* bytes, size_t len);
203//int32_t store_read_by_seq(void* store, uint64_t seq, uint8_t** out_bytes, size_t* out_len);
204//int32_t store_read_range(void* store, uint64_t start_seq, uint64_t end_seq,
205// uint8_t*** out_records, size_t** out_lens, size_t* out_count);
206//int32_t store_get_head(void* store, uint64_t* out_head_seq, uint8_t out_head_hash[UDIL_HASHLEN]);
207//int32_t store_set_head(void* store, uint64_t head_seq, const uint8_t head_hash[UDIL_HASHLEN]);
208//int32_t store_find_last_checkpoint(void* store, uint8_t out_chk_commit[UDIL_HASHLEN], uint64_t* out_end_seq);
209//
210//
212// * Detect equivocation between two checkpoints (same ledger/epoch, overlapping
213// * range, different roots or commitments).
214// *
215// * Returns:
216// * 1 if equivocation is detected, 0 otherwise.
217// */
218//UDIL_EXPORT_API int32_t udil_audit_detect_equivocation(const udil_checkpoint_body* a, const uint8_t a_commit[UDIL_HASHLEN],
219// const udil_checkpoint_body* b, const uint8_t b_commit[UDIL_HASHLEN]);
220//
222// * \brief Verify that a record commitment is included in a checkpoint Merkle root (sample audit).
223// *
224// * This function is used by auditors and counterparties to validate that a given
225// * record commitment was incorporated into a checkpointed batch without requiring
226// * access to the full ledger or plaintext message content.
227// *
228// * The verifier recomputes the Merkle root from the provided record commitment
229// * and Merkle proof, then compares it to the expected checkpoint root.
230// *
231// * \param checkpoint_root The expected 32-byte Merkle root committed by a checkpoint.
232// * \param rec_commit The 32-byte record commitment being proven included.
233// * \param proof The Merkle inclusion proof for rec_commit under checkpoint_root.
234// *
235// * \return 0 on success (proof verifies and matches checkpoint_root), otherwise a negative error code.
236// */
237//UDIL_EXPORT_API int32_t udil_audit_sample_inclusion(const uint8_t checkpoint_root[UDIL_HASHLEN], const uint8_t rec_commit[UDIL_HASHLEN], const udil_merkle_proof* proof);
238//
239// /**
240// * Compute the checkpoint commitment from a checkpoint body.
241// *
242// * chk_commit = SHAKE256("UDIL/CHK" || SER(checkpoint_body), 32)
243// *
244// * out : [out] 32-byte checkpoint commitment.
245// * body : [in] checkpoint body.
246// */
247//UDIL_EXPORT_API void udil_compute_checkpoint_commit(uint8_t out[UDIL_HASHLEN], const udil_checkpoint_body* body);
248//
250// * Compute the domain-separated envelope hash.
251// *
252// * The envelope hash commits to the canonical envelope bytes (message metadata).
253// * This is used to prove message identity without storing full payload content.
254// *
255// * out : [out] 32-byte hash output.
256// * env : [in] canonical envelope bytes.
257// * envlen : [in] number of envelope bytes.
258// */
259//UDIL_EXPORT_API void udil_compute_env_hash(uint8_t out[UDIL_HASHLEN], const uint8_t* env, size_t envlen);
260//
262// * Compute the domain-separated payload hash.
263// *
264// * The payload hash commits to the payload bytes or ciphertext bytes (if encrypted).
265// *
266// * out : [out] 32-byte hash output.
267// * pay : [in] payload bytes.
268// * paylen : [in] number of payload bytes.
269// */
270//UDIL_EXPORT_API void udil_compute_payload_hash(uint8_t out[UDIL_HASHLEN], const uint8_t* pay, size_t paylen);
271//
273// * Compute the record commitment for a record header.
274// *
275// * rec_commit = SHAKE256("UDIL/REC" || SER(record_hdr), 32)
276// *
277// * out : [out] 32-byte record commitment.
278// * hdr : [in] record header fields.
279// */
280//UDIL_EXPORT_API void udil_compute_record_commit(uint8_t out[UDIL_HASHLEN], const udil_record_hdr* hdr);
281//
283// * \brief Append an administrative reset record and transition the ledger to a new epoch.
284// *
285// * This function is used to record and justify a ledger reset event (for example,
286// * storage corruption, disaster recovery, or operator-directed reinitialization)
287// * while preserving audit continuity.
288// *
289// * A compliant implementation must:
290// * - Append an ADMIN record containing the reset reason and sufficient metadata
291// * to link the new epoch to the prior ledger state (for example, last checkpoint
292// * commitment and/or head commitment).
293// * - Increment the ledger epoch (or require the caller to do so explicitly, per spec).
294// * - Ensure that future checkpoints chain from the last known checkpoint commitment,
295// * preventing silent history deletion.
296// *
297// * \param st Ledger state object.
298// * \param reset_reason UTF-8 or opaque bytes describing the reset reason.
299// * \param reason_len Length of reset_reason in bytes.
300// *
301// * \return 0 on success, otherwise a negative error code.
302// */
303//int32_t udil_ledger_admin_reset(udil_ledger_state* st, const uint8_t* reset_reason, size_t reason_len);
304//
306// * \brief Append a new record to the local evidence ledger.
307// *
308// * This function appends a new ledger record of the specified type, binding it to:
309// * - The current ledger head (via prev_hash),
310// * - A monotonically increasing sequence number,
311// * - Optional envelope and payload commitments,
312// * - Optional correlation identifier,
313// * - Optional record body bytes.
314// *
315// * The record commitment is computed over the canonical serialized header fields
316// * and is then signed using the UDIF signing key carried in the ledger state.
317// * The storage backend is append-only, and the ledger head is updated on success.
318// *
319// * The function does not interpret message semantics. It stores evidence artifacts.
320// *
321// * \param st Ledger state object.
322// * \param rtype Record type (message, ack, receipt, admin, etc.).
323// * \param env_hash Optional 32-byte envelope hash, may be NULL if unused by rtype.
324// * \param pay_hash Optional 32-byte payload hash, may be NULL if unused by rtype.
325// * \param corr_id Optional 16-byte correlation id, may be NULL if unused.
326// * \param body Optional record body bytes (opaque), may be NULL.
327// * \param body_len Length of body in bytes, may be 0.
328// * \param out_rec_commit Optional 32-byte output buffer receiving the computed record commitment.
329// *
330// * \return 0 on success, otherwise a negative error code.
331// */
332//UDIL_EXPORT_API int32_t udil_ledger_append(udil_ledger_state* st, udil_record_type rtype, const uint8_t env_hash[UDIL_HASHLEN], const uint8_t pay_hash[UDIL_HASHLEN],
333// const uint8_t corr_id[16], const uint8_t* body, size_t body_len, uint8_t* out_rec_commit);
334//
336// * \brief Append an external anchoring reference for a checkpoint commitment.
337// *
338// * This function records that a specific checkpoint commitment has been anchored
339// * to an external witness system (for example, a regulator-operated anchor, a
340// * consortium witness, or later a global provenance pillar).
341// *
342// * The anchor reference is evidence that a checkpoint existed at or before some
343// * externally attested point in time. The anchor mechanism itself is out of scope
344// * for the local ledger and is represented here only by an identifier (receipt id,
345// * transaction id hash, or equivalent).
346// *
347// * \param st Ledger state object.
348// * \param a Anchor reference structure containing checkpoint commitment and witness identifier.
349// *
350// * \return 0 on success, otherwise a negative error code.
351// */
352//UDIL_EXPORT_API int32_t udil_ledger_append_anchor_reference(udil_ledger_state* st, const udil_anchor_ref* a);
353//
355// * \brief Construct a checkpoint body for a contiguous record range.
356// *
357// * This function computes the Merkle root over the sequence of record commitments
358// * for records in the inclusive range [start_seq, end_seq]. It then populates a
359// * checkpoint body that binds:
360// * - ledger_id and epoch,
361// * - the sequence range,
362// * - the record count,
363// * - the computed batch root,
364// * - the previous checkpoint commitment (for checkpoint chaining),
365// * - the checkpoint creation time.
366// *
367// * This function builds the checkpoint body only. Signing and appending the
368// * checkpoint is performed by udil_ledger_issue_checkpoint().
369// *
370// * \param st Ledger state object.
371// * \param start_seq First record sequence number in the checkpoint batch (inclusive).
372// * \param end_seq Last record sequence number in the checkpoint batch (inclusive).
373// * \param out_body Output checkpoint body structure.
374// *
375// * \return 0 on success, otherwise a negative error code.
376// */
377//UDIL_EXPORT_API int32_t udil_ledger_build_checkpoint_body(udil_ledger_state* st, uint64_t start_seq, uint64_t end_seq, udil_checkpoint_body* out_body);
378//
380// * \brief Build a Merkle inclusion proof for a target record within a checkpoint range.
381// *
382// * This function produces an inclusion proof showing that the record at target_seq
383// * is included in the Merkle root computed for the inclusive range [start_seq, end_seq].
384// *
385// * The proof contains sibling hashes and direction bits sufficient for an independent
386// * verifier to recompute the Merkle root from out_rec_commit and the proof, and compare
387// * it to out_root (or to a checkpoint’s batch_root).
388// *
389// * \param st Ledger state object.
390// * \param start_seq First record sequence number in the proof batch (inclusive).
391// * \param end_seq Last record sequence number in the proof batch (inclusive).
392// * \param target_seq Sequence number of the record to prove included.
393// * \param out_proof Output Merkle proof structure.
394// * \param out_rec_commit Output 32-byte record commitment for target_seq.
395// * \param out_root Output 32-byte Merkle root for [start_seq, end_seq].
396// *
397// * \return 0 on success, otherwise a negative error code.
398// */
399//UDIL_EXPORT_API int32_t udil_ledger_build_inclusion_proof(udil_ledger_state* st, uint64_t start_seq, uint64_t end_seq, uint64_t target_seq,
400// udil_merkle_proof* out_proof, uint8_t out_rec_commit[UDIL_HASHLEN], uint8_t out_root[UDIL_HASHLEN]);
401//
403// * \brief Initialize a ledger state and load persistent head and checkpoint state from storage.
404// *
405// * This function initializes the in-memory ledger state with its fixed identity and
406// * operational parameters, then synchronizes it with the persistent storage backend.
407// *
408// * A compliant implementation should:
409// * - Set ledger_id and epoch.
410// * - Associate the UDIF signing key used for signing new records and checkpoints.
411// * - Associate the append-only storage backend.
412// * - Load the current head sequence and head commitment from storage, or set a
413// * genesis head if storage is empty.
414// * - Load the last checkpoint commitment and its end sequence if available.
415// *
416// * \param st Ledger state object to initialize.
417// * \param ledger_id Stable 32-byte identifier for this ledger instance.
418// * \param epoch Epoch number (incremented on reset or signing-key rollover).
419// * \param udif_signing_key Opaque handle to the UDIF signing key for this ledger.
420// * \param store Opaque handle to the storage backend.
421// *
422// * \return 0 on success, otherwise a negative error code.
423// */
424//UDIL_EXPORT_API int32_t udil_ledger_initialize(udil_ledger_state* st, const uint8_t ledger_id[UDIL_HASHLEN], uint32_t epoch, void* udif_signing_key, void* store);
425//
427// * \brief Issue, sign, and append a checkpoint record to the ledger.
428// *
429// * This function creates a checkpoint for records in the inclusive range
430// * [start_seq, end_seq] and appends it as a checkpoint record to the ledger.
431// *
432// * A compliant implementation must:
433// * - Build the checkpoint body (udil_ledger_build_checkpoint_body()).
434// * - Compute the checkpoint commitment over the canonical body.
435// * - Sign the checkpoint commitment using the ledger’s UDIF signing key.
436// * - Append a CHECKPOINT record that contains the body and checkpoint signature.
437// * - Update the ledger state’s last checkpoint tracking values.
438// *
439// * The returned out_chk_commit is intended for external anchoring and for
440// * audit exchange.
441// *
442// * \param st Ledger state object.
443// * \param start_seq First record sequence number in the checkpoint batch (inclusive).
444// * \param end_seq Last record sequence number in the checkpoint batch (inclusive).
445// * \param out_chk_commit Output 32-byte checkpoint commitment.
446// *
447// * \return 0 on success, otherwise a negative error code.
448// */
449//UDIL_EXPORT_API int32_t udil_ledger_issue_checkpoint(udil_ledger_state* st, uint64_t start_seq, uint64_t end_seq, uint8_t out_chk_commit[UDIL_HASHLEN]);
450//
452// * \brief Parse a stored record blob into header, body, and signature components.
453// *
454// * This function decodes the record container format produced by udil_ledger_append()
455// * and returns:
456// * - the committed header fields,
457// * - the optional opaque body bytes,
458// * - the signature bytes.
459// *
460// * The caller owns the returned out_body and out_sig buffers and must free them
461// * using the allocator compatible with the implementation.
462// *
463// * This function does not verify signatures. Use udil_ledger_verify_record_blob()
464// * for verification.
465// *
466// * \param blob Raw stored record blob bytes.
467// * \param blob_len Length of blob in bytes.
468// * \param out_hdr Output parsed record header.
469// * \param out_body Output pointer to allocated body bytes (may be NULL if no body).
470// * \param out_body_len Output body length (0 if no body).
471// * \param out_sig Output pointer to allocated signature bytes.
472// * \param out_sig_len Output signature length.
473// *
474// * \return 0 on success, otherwise a negative error code.
475// */
476//UDIL_EXPORT_API int32_t udil_ledger_parse_record(const uint8_t* blob, size_t blob_len, udil_record_hdr* out_hdr, uint8_t** out_body,
477// size_t* out_body_len, uint8_t** out_sig, size_t* out_sig_len);
478//
480// * \brief Rotate the UDIF signing key used by the ledger and transition to a new epoch.
481// *
482// * This function updates the ledger’s signing key to a new UDIF key and increments
483// * the epoch to explicitly mark the key transition in the evidentiary record.
484// *
485// * A compliant implementation should:
486// * - Update st->udif_signing_key to new_udif_signing_key.
487// * - Increment st->epoch.
488// * - Preserve continuity by issuing a checkpoint over any uncheckpointed records
489// * prior to completing the rollover (policy dependent, but recommended).
490// *
491// * \param st Ledger state object.
492// * \param new_udif_signing_key Opaque handle to the new UDIF signing key.
493// *
494// * \return 0 on success, otherwise a negative error code.
495// */
496//UDIL_EXPORT_API int32_t udil_ledger_rotate_key(udil_ledger_state* st, void* new_udif_signing_key);
497//
499// * \brief Verify a stored record blob signature and recompute its record commitment.
500// *
501// * This function parses the record blob, recomputes the record commitment from the
502// * committed header fields, and verifies that the signature over the record commitment
503// * is valid under the supplied signer certificate.
504// *
505// * The output record commitment can be used as an input leaf to checkpoint Merkle trees
506// * and as an evidentiary identifier for the record.
507// *
508// * \param blob Raw stored record blob bytes.
509// * \param blob_len Length of blob in bytes.
510// * \param signer_cert The signer’s UDIF certificate bytes used for verification.
511// * \param cert_len Length of signer_cert in bytes.
512// * \param out_rec_commit Output 32-byte record commitment.
513// *
514// * \return 0 on success (signature valid), otherwise a negative error code.
515// */
516//UDIL_EXPORT_API int32_t udil_ledger_verify_record_blob(const uint8_t* blob, size_t blob_len, const uint8_t* signer_cert, size_t cert_len, uint8_t out_rec_commit[UDIL_HASHLEN]);
517//
519// * Compute the Merkle leaf node hash from a record commitment.
520// *
521// * leaf = SHAKE256("UDIL/LEAF" || rec_commit, 32)
522// *
523// * out : [out] 32-byte leaf hash.
524// * rec_commit : [in] 32-byte record commitment.
525// */
526//UDIL_EXPORT_API void udil_merkle_leaf(uint8_t out[UDIL_HASHLEN], const uint8_t rec_commit[UDIL_HASHLEN]);
527//
529// * Compute the Merkle parent node hash.
530// *
531// * parent = SHAKE256("UDIL/NODE" || left || right, 32)
532// *
533// * out : [out] 32-byte parent hash.
534// * left : [in] 32-byte left child.
535// * right : [in] 32-byte right child.
536// */
537//UDIL_EXPORT_API void udil_merkle_parent(uint8_t out[UDIL_HASHLEN], const uint8_t left[UDIL_HASHLEN], const uint8_t right[UDIL_HASHLEN]);
538//
540// * Verify a Merkle inclusion proof and recompute the root.
541// *
542// * out_root : [out] computed Merkle root from the proof.
543// * rec_commit : [in] record commitment being proven.
544// * proof : [in] inclusion proof (siblings + directions).
545// */
546//UDIL_EXPORT_API void udil_merkle_verify(uint8_t out_root[UDIL_HASHLEN], const uint8_t rec_commit[UDIL_HASHLEN], const udil_merkle_proof* proof);
547//
549// * \brief Compute the Merkle root over a contiguous set of record commitments.
550// *
551// * This function computes a deterministic Merkle root using the UDIL Merkle
552// * construction rules:
553// * - Each record commitment is first transformed into a Merkle leaf.
554// * - Parent nodes are computed pairwise from left and right children.
555// * - If a level has an odd number of nodes, the final node is duplicated.
556// *
557// * The resulting root is suitable for inclusion in a checkpoint body and
558// * for later audit verification using Merkle inclusion proofs.
559// *
560// * \param root Output buffer receiving the computed Merkle root.
561// * \param rec_commits Pointer to a flat array of record commitments
562// * (count * UDIL_HASHLEN bytes).
563// * \param count Number of record commitments in the array.
564// */
565//UDIL_EXPORT_API void udil_merkle_root(uint8_t root[UDIL_HASHLEN], const uint8_t* rec_commits, size_t count);
566//
568// * \brief Serialize an anchor reference into canonical byte form.
569// *
570// * This function serializes an \c udil_anchor_ref structure into its canonical
571// * binary representation. The serialized output is suitable for inclusion as
572// * the body of an ANCHOR_REFERENCE ledger record.
573// *
574// * The caller owns the returned buffer and must free it using the allocator
575// * compatible with the implementation.
576// *
577// * \param a Anchor reference structure to serialize.
578// * \param out_len Output parameter receiving the serialized length in bytes.
579// *
580// * \return Pointer to a newly allocated buffer containing the serialized
581// * anchor reference, or NULL on failure.
582// */
583//UDIL_EXPORT_API uint8_t* udil_serialize_anchor_reference(const udil_anchor_ref* a, size_t* out_len);
584//
586// * \brief Serialize a checkpoint body into canonical byte form.
587// *
588// * This function serializes an \c udil_checkpoint_body structure into the exact
589// * canonical format used for computing checkpoint commitments and signatures.
590// * The serialization includes all committed fields in fixed order and
591// * big-endian encoding for multi-byte integers.
592// *
593// * The returned buffer is used as input to the checkpoint commitment hash
594// * function.
595// *
596// * The caller owns the returned buffer and must free it when no longer needed.
597// *
598// * \param c Checkpoint body structure to serialize.
599// * \param out_len Output parameter receiving the serialized length in bytes.
600// *
601// * \return Pointer to a newly allocated buffer containing the serialized
602// * checkpoint body, or NULL on failure.
603// */
604//UDIL_EXPORT_API uint8_t* udil_serialize_checkpoint_body(const udil_checkpoint_body* c, size_t* out_len);
605//
607// * \brief Serialize a record header into canonical byte form.
608// *
609// * This function serializes the committed fields of an \c udil_record_hdr into
610// * a canonical binary representation. The output is used exclusively for
611// * computing the record commitment hash.
612// *
613// * Signature bytes, variable-length bodies, and container framing are not
614// * included in this serialization.
615// *
616// * The caller owns the returned buffer and must free it when finished.
617// *
618// * \param h Record header structure to serialize.
619// * \param out_len Output parameter receiving the serialized length in bytes.
620// *
621// * \return Pointer to a newly allocated buffer containing the serialized
622// * record header, or NULL on failure.
623// */
624//UDIL_EXPORT_API uint8_t* udil_serialize_record_header(const udil_record_hdr* h, size_t* out_len);
625//
627// * \brief Sign a checkpoint commitment using a UDIF signing key.
628// *
629// * This function produces a cryptographic signature over a checkpoint
630// * commitment. The commitment must already have been computed from a canonical
631// * checkpoint body.
632// *
633// * The signature binds the issuing authority, the checkpoint content, and the
634// * signing context, providing non-repudiable evidence that the checkpoint was
635// * issued by the holder of the UDIF key.
636// *
637// * \param out_sig Output buffer receiving the signature bytes.
638// * \param out_siglen Output parameter receiving the signature length in bytes.
639// * \param udif_key Opaque handle to the UDIF signing key.
640// * \param chk_commit 32-byte checkpoint commitment to be signed.
641// */
642//UDIL_EXPORT_API void udil_sign_checkpoint(uint8_t* out_sig, size_t* out_siglen, void* udif_key, const uint8_t chk_commit[UDIL_HASHLEN]);
643//
645// * \brief Sign a record commitment using a UDIF signing key.
646// *
647// * This function produces a cryptographic signature over a record commitment.
648// * The record commitment must already have been computed from the canonical
649// * record header serialization.
650// *
651// * The resulting signature provides non-repudiation for the existence and
652// * ordering of the record within the ledger.
653// *
654// * \param out_sig Output buffer receiving the signature bytes.
655// * \param out_siglen Output parameter receiving the signature length in bytes.
656// * \param udif_key Opaque handle to the UDIF signing key.
657// * \param rec_commit 32-byte record commitment to be signed.
658// */
659//UDIL_EXPORT_API void udil_sign_record(uint8_t out_sig[], size_t* out_siglen, void* udif_key, const uint8_t rec_commit[UDIL_HASHLEN]);
660//
662// * \brief Verify a checkpoint signature against a checkpoint commitment.
663// *
664// * This function verifies that a provided signature is a valid signature over
665// * the given checkpoint commitment under the supplied UDIF certificate.
666// *
667// * This verification step is required for:
668// * - Audit acceptance of a checkpoint.
669// * - Detection of forged or unauthorized checkpoints.
670// * - Establishing evidentiary validity of ledger checkpoints.
671// *
672// * \param cert UDIF certificate bytes of the purported signer.
673// * \param cert_len Length of the certificate in bytes.
674// * \param chk_commit 32-byte checkpoint commitment that was signed.
675// * \param sig Signature bytes to verify.
676// * \param siglen Length of the signature in bytes.
677// *
678// * \return 0 if the signature is valid, otherwise a negative error code.
679// */
680//int32_t udil_verify_checkpoint_signature(const uint8_t* cert, size_t cert_len, const uint8_t chk_commit[UDIL_HASHLEN], const uint8_t* sig, size_t siglen);
681//
683// * \brief Verify a record signature against a record commitment.
684// *
685// * This function verifies that a provided signature is a valid signature over
686// * the given record commitment under the supplied UDIF certificate.
687// *
688// * Successful verification proves that the record was authorized by the
689// * certificate holder and that the committed record header has not been
690// * altered.
691// *
692// * \param cert UDIF certificate bytes of the purported signer.
693// * \param cert_len Length of the certificate in bytes.
694// * \param rec_commit 32-byte record commitment that was signed.
695// * \param sig Signature bytes to verify.
696// * \param siglen Length of the signature in bytes.
697// *
698// * \return 0 if the signature is valid, otherwise a negative error code.
699// */
700//UDIL_EXPORT_API int32_t udil_verify_record_signature(const uint8_t* cert, size_t cert_len, const uint8_t rec_commit[UDIL_HASHLEN], const uint8_t* sig, size_t siglen);
701//
703// * Simple UDIL Ledger Smoke Test
704// *
705// * This function performs a minimal end to end validation of the ledger:
706// * - initialize ledger
707// * - append a record
708// * - read the record back
709// * - recompute and verify the record commitment and signature
710// *
711// * This is intended as a basic sanity test, not a full audit test.
712// * It assumes that the storage backend and UDIF sign/verify primitives
713// * are already wired and functional.
714// */
715//UDIL_EXPORT_API int32_t udil_ledger_basic_selftest(udil_ledger_state* st, const uint8_t ledger_id[UDIL_HASHLEN], void* udif_signing_key, void* store, const uint8_t* signer_cert, size_t cert_len);
716//
717//UDIL_EXPORT_API bool udil_ledger_selftest();
718
719#endif