Implement economy-transition-v6 in the C++20 kernel and retire version four's codec - #178
Merged
Merged
Conversation
…four's codec The C++20 kernel carried a codec for `economy-transition-v4`, which is the one economy contract already known to have no conforming implementation: its kind 11 opens its rejection conditions with "an unregistered `hub_identity_hash` is `NOT_HUB_VERIFIED`" over an identity the transaction never carries. Versions five and six both exist because of that defect, so the repository was compiling exactly the contract nothing can implement. `src/v6/` replaces `src/v4/` rather than sitting beside it. Every Python model and vector file is retained, because a model plus its vectors is the record of what the hosted matrix verified; a codec records nothing and is one implementation of a byte surface. ADR 0046 states the decision and its alternatives. It is a codec plus the pure derivations and it performs no state transition: the envelope and its two authorization schemes, the fourteen bodies and five retired numbers, the six HUB messages, the escrow and signer derivations, the posture predicates, the fourteen state entry encodings, the economy tree, the version-six state root, genesis, chain identity, the receipt, the bounded mint walk, and the verified-user arithmetic. The accepted version-one account derivation is now defined once in `src/v1/account.hpp` and shared by version one's admission path and version six's signer derivation, rather than copied. A second implementation of one derivation is a second place for it to drift, and the drift would be silent. Of the four rules ADR 0045 derived, a codec can reach one and does: `NOTHING_TO_MINT` is the empty walk range rather than the literal equality, so a mark can never decrease. The other three need a ledger this does not have.
Three entry points take untrusted input — the signed transaction, the receipt, and the one variable-width state value. M3.9a's version-four codec shipped with no fuzz target, which was a gap in the required evidence rather than a judgement that one did not apply. It asserts two properties beyond the absence of a crash, and both are what consensus rests on. Decoding is deterministic, so two nodes handed identical bytes reach identical answers. And decoding round-trips: anything the decoder accepts re-encodes to exactly the bytes it came from, which is what makes a canonical encoding canonical and what catches a decoder that quietly tolerated a second representation of one transaction. Registered in `PROTOCOL_STACK_TARGETS`, which carries `-Werror`, the sanitizer flags, and the libsodium link, and given a bounded smoke entry beside the other three kernel fuzz targets. M3.9a declared a target and left it off that list.
…registrations `clang-sanitizers` failed at the link: `economy_v6_fuzz` was declared, listed in `PROTOCOL_STACK_TARGETS`, and left out of the loop applying `-fsanitize=fuzzer`, so it had no libFuzzer `main`. A fuzz executable is registered in four places and only two omissions fail loudly. Out of `PROTOCOL_STACK_TARGETS` a target builds without `-Werror`, the sanitizer flags, and the libsodium link, which is the M3.9a defect; out of the instrumentation loop it runs with no coverage feedback and explores nothing while reporting success. Both are silent. `tests/tools/test_registration_test.py` now requires every file under `tests/fuzz/` to appear in all four, and each of the five omissions was demonstrated to fail it. The guard's first draft was vacuous in the shape it exists to catch: it split `CMakeLists.txt` at the first `PROTOCOL_STACK_TARGETS` and searched everything after it, which matched the target's own `add_executable` block and passed with the target removed from the list. The `list(APPEND)` block is nested inside `if(PROTOCOL_STACK_ENABLE_FUZZING)` and closes on an indented paren, so a pattern anchored to column zero does not terminate there — the same defect M3.7a found in this file's `add_test` parser. The parse is now asserted to find two blocks.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #177. Requirement 10 of
docs/project/first-goal.md, for the byte and derivation surface.What this delivers
include/protocol/v6/economy.hpp, nine sources undersrc/v6/, and five test translation units checked againsttest-vectors/economy-transition-v6.txt. It is a codec plus the pure derivations and performs no state transition — every entry point is a function of its arguments:slot_of, the confirmation predicate, and the relaxation predicate;Version four's codec is removed rather than kept beside it
The kernel was compiling exactly one economy contract and it was the one already known to have no conforming implementation — version four's kind 11 names an identity the transaction never carries, which is why versions five and six exist.
Every Python model and vector file is retained: a model plus its vectors is the record of what the hosted matrix verified, and
tools/economy-transition-v4-vectors/still verifies its 441. A codec records nothing. ADR 0046 states the decision and the two rejected alternatives.The shared account derivation
H(D("protocol-stack:v1:account") || 0x01 || pk)is now defined once insrc/v1/account.hppand used by both version one's admission path and version six'ssigner_id, rather than copied. The test checks it againsttest-vectors/protocol-primitives-v1.txt's recordedaccount_id— a third source, not a second restatement.What it establishes, and what it does not
Of ADR 0045's four derived rules a codec can reach one, and it reaches it.
NOTHING_TO_MINTis the empty walk range rather than the literal equality, so a mark can never decrease.DEBIT_OVERFLOW's position in the envelope order, the unrequested-confirmation refusal, and the cycle-assignment prologue need a ledger this does not have and are the next slice.One of the three is pinned from the admitting side even so, and a probe is why. A mutation making the codec refuse a mint carrying a nonzero confirmation field — the rule version six's text literally states, at admission, under a code the result space does not contain — passed. Nothing in the test or in either accepted vector file noticed an implementation stricter than the contract can be. The test now requires such a mint to be admitted.
Evidence
Three checks reach a third source rather than a second opinion of the version-six file: the kind-1 identity and the signer derivation against
protocol-primitives-v1.txt, the accounts tree against the same, and the two cycle-assignment records againsteconomy-transition-v3.txt, because version six's settlement is version three's imported rather than reimplemented.The populated economy root is what makes this more than a width check. The 44-entry fixture covers all fourteen assigned entry kinds, so one recorded root constrains every value encoding at once. Two probes swapping adjacent same-width fields —
signer_countwithexempt_slot_mask, andnext_escrow_indexwithescrow_count— failed there and nowhere else.Nineteen mutation probes fail closed, including the escrow label, the version-one account octet, the state-root schema version (a number, which the handoff warned would not appear in a search for
v4), the RFC 9162 split replaced by a halving, the bitmap packed least-significant-bit first, a retired kind given a width, the scheme rule dropped, and genesis admitting an account.Nothing accepted was edited. The v6 specification gains a status line and an evidence pointer and no rule; the v5 specification gains a corrected sentence about where the kernel's codec lives.
Verification
Local: the codec and all five test units compile clean under
-Wall -Wextra -Wpedantic -Werrorand pass; the version-one admission, execution, genesis, commitment, and block tests pass after the shared-derivation change;tests/tools/test_registration_test.pypasses. The full compiler and sanitizer matrix is this PR's gate.