tlog

package
v0.1.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 11, 2026 License: Apache-2.0 Imports: 5 Imported by: 0

Documentation

Overview

Package tlog implements PRD 1 § 5.4: deterministic reconstruction of `t_root`, the Merkle commitment over a pod invocation's tool-call log `T_log`, from an ordered sequence of `proof_tool_calls`-equivalent rows.

`t_root` is one of 13 public inputs to the konareef-pod-step-v1 Nova IVC step circuit (PRD 1 § 5.1). It is byte-interoperable across the Go CLI verifier (this package), reef-core's Elixir ReefCore.Proofs.TLog (the writer side), the TypeScript SDK verifier, and the (v1.5) BSV Script verifier. Any drift between implementations breaks every proof in flight, so the leaf/inner/ length-bind encoding here is treated as wire-format spec — not "implementation detail".

Public surface:

  • Row — a single tool-call record (matches the writer-side `proof_tool_calls` row schema)
  • LeafHash — SHA-256(0x00 || record_bytes_i)
  • TRootFromRows — full t_root from an unsorted []Row
  • Z — the all-empty-T_log padding sentinel SHA-256(0x00 || 0x00)
  • LeafTag, InternalTag, LengthBindTag — PRD 1 § 5.4 tag set

All constants in this package are normative per PRD 1 § 5.4. Do not modify without a counter-amendment to the upstream PRD and the `tlog-from-db-rows` conformance vector.

internal/tlog/tlog.go — public surface for PRD 1 § 5.4 T_log reconstruction. The record_bytes encoding here is normative across every konareef verifier; treat it as wire-format spec.

Hash construction (post Lever-1, PRD 1 § 5.4): the tool-log Merkle tree is built over Poseidon-over-Pallas-Fq, NOT SHA-256. Each leaf is poseidon.LeafHash(poseidon.RecordToField(record_bytes)); internal nodes use poseidon.InternalHash; the count is bound by the 0x03 length element. All hashing delegates to internal/poseidon (the drift-gated, neptune-parity primitive); this package owns only the record_bytes encoding and the call_index ordering.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func LeafHash

func LeafHash(r Row) ([32]byte, error)

LeafHash returns the PRD 1 § 5.4 Poseidon leaf hash for a single Row: poseidon.LeafHash(poseidon.RecordToField(RecordBytes(r))). It returns an error if the record exceeds the pinned circuit cap (fail-closed: such a record could not have been proven).

func RecordBytes

func RecordBytes(r Row) []byte

RecordBytes returns the canonical PRD 1 § 5.4 per-record encoding (amended 2026-07-05 — decision `2026-07-05-konareef-digest-tool-ids`), byte-identical to paygate-zk's konareef_circuit troot_sha::encode_record:

record_bytes = 0x20                            // ULEB128(32), constant under the digest shape
            || tool_id_digest (32 B)           // SHA-256(tool_id_utf8)
            || args_hash (32 B)
            || result_hash (32 B)
            || ts (8 B big-endian u64, microseconds since Unix epoch)
            || sats (8 B big-endian u64)

Every record is a FIXED 113 bytes: the variable-length name form is superseded (it committed the raw name and had no sats). CallIndex is intentionally not part of record_bytes — it is the out-of-band sort key (PRD 4 § 4.1.4).

func TRootFromRows

func TRootFromRows(rows []Row) ([32]byte, error)

TRootFromRows reconstructs PRD 1 § 5.4's Poseidon t_root from an unordered set of Rows:

  1. Sort by Row.CallIndex ASC (PRD 4 § 4.1.4 — the sole sort key).
  2. Build record_bytes for each row.
  3. t_root = poseidon.TRoot(records) — the Z-padded balanced Poseidon tree of leaf_hash(record_to_field(record)) leaves, bound by the 0x03 length element.

It does not mutate the input slice (sort happens on an internal copy) and returns an error if the log exceeds the pinned record/count caps.

Types

type Row

type Row struct {
	// ToolID is the UTF-8 NFC tool identifier. Length is bound by
	// LEB128(len(tool_id_utf8)) at the start of record_bytes.
	ToolID string

	// ArgsHash is the 32-byte SHA-256 of the canonical tool-call
	// argument bytes. Canonicalization is the runtime's responsibility;
	// PRD 1 only binds the hash.
	ArgsHash [32]byte

	// ResultHash is the 32-byte SHA-256 of the canonical tool-call
	// result bytes. Canonicalization is the runtime's responsibility;
	// PRD 1 only binds the hash.
	ResultHash [32]byte

	// TS is the wall-clock timestamp of the call. Encoded as u64
	// big-endian microseconds since the Unix epoch (UTC). PRD 1 § 5.4
	// SHOULD be monotone non-decreasing within a single T_log, but the
	// helper does not enforce monotonicity (PRD 4 § 4.1.4 makes that
	// the writer's responsibility).
	TS time.Time

	// CallIndex is the writer-assigned ordering key. Rows are sorted by
	// CallIndex ASC before leaves are hashed; it is NOT part of the
	// leaf preimage. PRD 4 § 4.1.4 makes (proof_id, call_index) the
	// uniqueness constraint.
	CallIndex uint32

	// Sats is the satoshis paid for this tool call (0 for unpaid/local
	// tools, e.g. `bash`). Encoded big-endian as the trailing 8 bytes of
	// record_bytes (PRD 1 § 5.4 amended 2026-07-05). The circuit binds
	// Σ(sats) ≤ c; the writer is responsible for that invariant.
	Sats uint64
}

Row is a single proof_tool_calls-equivalent row, matching the writer-side schema in reef-core's `proof_tool_calls` table (P1.1). CallIndex is the SOLE sort key for T_log leaf order (PRD 4 § 4.1.4); TS is for audit/debugging only and is not used to order leaves.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL