Skip to content

Execute economy-transition-v6 against a version-six ledger - #181

Merged
kaikisegfault merged 3 commits into
mainfrom
feat/180-economy-transition-v6-ledger
Aug 19, 2026
Merged

Execute economy-transition-v6 against a version-six ledger#181
kaikisegfault merged 3 commits into
mainfrom
feat/180-economy-transition-v6-ledger

Conversation

@kaikisegfault

Copy link
Copy Markdown
Owner

Closes #180.

M3.10c put version six's byte and derivation surface into the kernel. A codec has no ledger, so it could not resolve an acting escrow, order the shared envelope checks, charge a fee, advance a nonce, or commit a state root. This adds the ledger and the ten transitions that read no cycle assignment.

What executes now

Admission, escrow resolution under both authorization schemes, the shared envelope checks in version one's order, ordered block execution with failed-transition atomicity, and kinds 1, 6, 10, 13, 14, 15, 16, 17, 18, and 19.

What deliberately does not

Kinds 2, 3, 4, and 5 read or write a cycle assignment, and the version-three settlement that derives one is not in the kernel. Dispatch refuses to execute them rather than answering wrongly — an implementation that cannot execute a transaction has no result to report, so it fails the block loudly instead of inventing a refusal. No conforming chain can run those four kinds until the settlement slice lands.

Two derived orders are implemented where a reader will look

ADR 0045 derived both; each now carries its reasoning in the code rather than only in the ADR.

  • DEBIT_OVERFLOW is returned inside envelope check 8. Check 8 tests amount + fixed_fee, which is the same sum kind 1's own step 5 tests; evaluating it afterwards leaves check 8 undefined on a sum that does not fit u64 and makes code 7 unreachable in a version whose specification lists exactly three unreachable frozen codes and does not list it.
  • An unrequested confirmation field is refused at execution with UNAUTHORIZED. The specification places it at admission and names MALFORMED_TRANSACTION; the predicate reads a stored posture admission cannot see, and the result-code space has no such name.

One recorded divergence from version one survives intact: INSUFFICIENT_BALANCE precedes ZERO_AMOUNT for kind 1, so a zero-amount transfer from an escrow that cannot pay the fee answers differently under the two versions.

Evidence

394 of the 512 vectors in test-vectors/economy-transition-v6-execution.txt are reproduced — every vector in the construction, genesis, registration, millionth, recovery, compatibility, posture, derived, and determinism sections. The remaining 118 are block, cycle, and ordering, which are the boundary block and the settlement it derives.

Nothing derives a second set of expected values. Four checks reach a third source rather than a second opinion of the execution file: the ordered transaction tree and the accepted version-one transfer against protocol-primitives-v1.txt, the block header and block identifier against ledger-transition-v1.txt, the ten channel caps and five base-permission legs against founder-economy-manifest-v2.txt, and the referral leg against economy-transition-v3.txt.

A coverage guard fails if any vector in a claimed section is never consulted, and it was demonstrated to fail — removing one fee_pool comparison produces vector compatibility.fee_pool was never consulted. It also fails if the three deferred sections ever become empty, so the slice boundary is itself checkable.

Probes

Nine mutation probes; seven caught. Two are reported rather than buried:

  • One was an equivalent mutation that changed no behaviour — the exact failure mode the M3.10b handoff warns about. Rewritten to make the overflow sum wrap, and then caught.
  • One passed: making signer_revoke accept a signer assigned to a different escrow changes nothing the recorded trace observes. That rejection condition, and kinds 13, 14, and 6 entirely, are unexercised by the vectors. Recorded as a known coverage gap for direct kernel tests rather than claimed as checked.

Caught probes include the shared debit omitting a transfer's amount, the overflow test removed, the unrequested-confirmation refusal dropped, the relaxation predicate weakened to require all three fields, registration charging a fee, the airdrop bound admitting one more identity, the balance check skipping zero-amount transfers, and a transfer creating its recipient instead of refusing.

Local verification

Both compilers with the project's exact flags, and Clang with address and undefined-behaviour sanitizers, against the scratch-libsodium harness. Clang caught a portability bug GCC accepted — capturing a structured binding by reference in a lambda, which C++20 does not permit — in three places. It is fixed and both compilers now agree. The 142 Python model tests for version six still pass, and the target-registration guard passes.

The full matrix runs on this exact commit.

… ledger

The codec had no ledger, so it could not resolve an acting escrow, order the
shared envelope checks, charge a fee, advance a nonce, or commit a root. This
adds the state those need and the ten transitions that read no cycle
assignment.

A version-six state is a version-one state plus one ordered economy map, and
the account map is keyed by escrow identifier with no second copy of a balance,
which is what makes the first structural invariant checkable by comparing two
key sets. Every conservation and structural check is an equality, because a
bound would admit a defect that lost a term.

Two derived orders from ADR 0045 are implemented where a reader will look for
them rather than only in the ADR. DEBIT_OVERFLOW is returned inside envelope
check 8, because check 8 tests the same sum kind 1's own step 5 tests and
evaluating it afterwards would leave check 8 undefined on a sum that does not
fit u64 and make code 7 unreachable. An unrequested confirmation field is
refused at execution with UNAUTHORIZED, because the predicate reads a stored
posture that admission cannot see and the result-code space has no
MALFORMED_TRANSACTION.

Kinds 2, 3, 4, and 5 read or write a cycle assignment and the version-three
settlement is not in the kernel yet, so dispatch refuses to execute them rather
than inventing a result. No conforming chain can run them until that lands.

No cryptography is performed in the transition layer: the caller supplies a
verifier, so a test exercises every UNAUTHORIZED path against a recorded table
and production supplies the version-one strict Ed25519 check.

Refs #180
…in C++

Requirement 11 for execution: the kernel runs five of the six recorded
scenarios transaction for transaction and compares 394 of the 512 vectors in
test-vectors/economy-transition-v6-execution.txt against what it derives.
Nothing here computes a second set of expected values.

Reproducing a recorded outcome means rebuilding the exact bytes that produced
it. A transaction identifier is a digest over the signed bytes, so the fixture
issues signature stand-ins in the model's own order, and an adopted signature
consumes a number even though it was not issued -- getting that wrong was
caught by a transaction root, which is the check working.

Four checks reach a third source rather than a second opinion of the execution
file: the ordered transaction tree and the accepted transfer against
protocol-primitives-v1, the block header and identifier against
ledger-transition-v1, the ten channel caps and five legs against
founder-economy-manifest-v2, and the referral leg against
economy-transition-v3.

A coverage guard fails if any vector in a claimed section is never consulted,
and it was demonstrated to fail when one check is removed. The three sections
it defers -- block, cycle, ordering -- are named rather than skipped silently,
and it fails if they ever become empty.

The RFC 9162 tree is now one implementation serving the economy tree, the
accounts tree, and version one's transaction tree, each pinned by a different
accepted vector file.

Refs #180
…eaches

A mutation probe found this the honest way. Making signer_revoke accept a
signer assigned to a different escrow changed nothing any recorded vector
observes, so that refusal had no evidence behind it at all. Three kinds --
escrow create, escrow delete, and direct issue -- appear in no scenario either,
and four shared envelope conditions are never exercised.

These checks derive their own expectations rather than comparing against a
vector file, because no vector records them. That is the opposite of the rule
the scenario checks follow, which is why they live in their own translation
unit: a reader must never have to wonder which kind of evidence an assertion
carries.

Covered: kind 13's four resolution conditions and its writes; kind 14's target
and fee refusals, including the two that share ESCROW_NOT_EMPTY for different
reasons, and the signer entries a deletion removes; the signer limit at sixteen
and the cross-escrow revocation the probe found; kind 6 refusing every acting
key across all three reserved channels; and FEE_LIMIT_TOO_LOW, EXPIRED,
NONCE_EXHAUSTED, NONCE_MISMATCH, and SIGNER_NOT_FOUND.

Every refusal is additionally checked to leave the state root unchanged, so
failed-transition atomicity is proved for each condition rather than only for
the refusals a recorded block happens to contain. Each hand-built fixture is
asserted to be a conserved state first, because a fixture that no sequence of
transitions could reach would make every result over it meaningless.

The probe was re-run against these checks and now fails closed.

Refs #180
@kaikisegfault
kaikisegfault merged commit 13247b2 into main Aug 19, 2026
10 of 12 checks passed
@kaikisegfault
kaikisegfault deleted the feat/180-economy-transition-v6-ledger branch August 19, 2026 03:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

M3.10d: the version-six ledger and its ten non-seat transitions in the C++20 kernel

1 participant