economy-transition-v6: the identity is the account - #170
Merged
Conversation
Version six encodes the account architecture ADRs 0039 through 0043 settled. A verified identity is the root, a keyless escrow is where value sits, and a revocable signer assigned to exactly one escrow is who may act on it. An escrow's balance and nonce stay in the version-one account map, so a version-six state is a version-one state plus an economy map. The escrow identifier is derived rather than allocated, from the identity and an index that never decreases, so a wallet computes it offline and a deleted escrow's identifier is never reissued. The accepted version-one account derivation survives with its subject moved from an account to a signer, which is what a public-key hash is. The signature-scheme byte carries a second authorization mode. Scheme 1 is a signer key and resolves the acting escrow from the signer entry; scheme 2 is an identity's HUB key and names its escrow in the body. Both verify the envelope signature against the header key, so admission still reads no state. Scheme 2 is what lets recovery pay a fee with no key, and recovery is therefore the ordinary signer-add rather than a transaction of its own. Kind 1 keeps its 40-octet body and reproduces the accepted 136-byte unsigned and 200-byte signed transfer exactly, and gains one rejection condition: a recipient that is not a registered escrow. That withdraws `ledger-transition-v1`'s recipient-creating transfer and makes "every account is an escrow" a structural invariant rather than a policy. The byte identity is preserved and the execution identity is not, and the compatibility section says so in those terms. Registration is fee-exempt against ADR 0042's stated preference, because credit-before-fee fails with INSUFFICIENT_BALANCE at user 1,000,001, when the airdrop is exhausted. It creates the identity, escrow zero, the first signer, and the entry airdrop atomically. The per-escrow posture generalises version three's asymmetry: relaxing needs a HUB signature, tightening needs only a signer. Its direction is derived from the two stored postures, and a mixed change counts as a relaxation. Time windows are the accepted grid's 24 one-hour slots, never a clock. Channel 8 satisfies an inequality rather than an equality: it has no accrual step and therefore no outstanding term, so a forfeited verified-user permission is never represented in state. ADR 0043 and the constitution are corrected to say "never issued" rather than "stays outstanding", which was a gloss the mechanism does not support. Five transaction kinds and two entry kinds are retired rather than reused. Three frozen result codes become unreachable because their subjects are gone. Refs #169
…erifier Adds simulation/economy_transition_v6/, 462 normative vectors, a verifier in tools/economy-transition-v6-vectors/, and four test modules with 91 tests, all registered in CMakeLists.txt. The model is a sibling of version four's rather than a binding into it, on the test ADR 0029 states: version six changes what an account is, who may hold one, what authorizes a transaction, and the state shape. What it does not duplicate is the settlement — the cap, the assignment record, and the bounded mint walk are imported from version three through version four, and the vectors require the two assignment records to equal the bytes test-vectors/economy-transition-v3.txt already fixes. Two claims are checked against a third source rather than against the model's second opinion. The kind-1 identity reproduces the accepted 136-byte unsigned and 200-byte signed transfer and transaction ID from test-vectors/protocol-primitives-v1.txt. And the signer derivation reproduces that same file's recorded account_id, because it is the accepted version-one account derivation with its subject moved from an account to a signer — a restatement checked only against its own formula would agree with itself while both were wrong. Four mutation probes establish fail-closed behaviour: a changed escrow label, a relaxation predicate that lost its slot-mask disjunct, a removed accumulation cap, and a changed account domain octet are each rejected. The last was probed with the octet changed in both the model and the independent derivation and still fails, which is the property M3.9c's third rule exists to produce. The boolean rule fired during generation and cost three renamings: three posture cases whose answer is "no confirmation" now record the negation positively rather than recording false under a name that asserts the opposite. Nothing accepted was edited. All five predecessor vector files verify at their recorded counts: 238, 579, 441, 550, and the version-one primitives. Refs #169
Records how version six was delivered, prunes the planning material the slice consumed, and sets the next action to M3.10b — the version-six execution model and its recorded transition trace, issue #153 rebound from version five. The execution model comes before the C++ codec, and the order is the repository's own lesson rather than a preference: M3.9a implemented a codec and M3.9b found two implementations agreeing perfectly about a message neither could construct, because a codec never asks where a transaction gets its arguments. Five paragraphs of superseded guidance are pruned: the version-five C++ notes, the retain-or-replace question the new text answers, the M3.9e paragraph that version six rebinds, and a duplicated harness note. The keep-accepted list now records that version four's package is load-bearing three ways and version three's twice. Also records one local hazard that cost time and will again: stale __pycache__ made a reverted mutation appear to still fail and a real failure appear to pass. Hosted runners start clean, so it is local only. Refs #169
kaikisegfault
added a commit
that referenced
this pull request
Aug 15, 2026
…rget PR #170 merged by rebase across 6fb57f6 through 15b5e90. The full hosted matrix passed on the exact candidate — gcc-debug 8m33s, clang-debug 8m57s, clang-sanitizers 9m02s, gcc-sanitizers 9m27s — and again post-merge on main in 9m48s. Those facts could not be written before the delivery PR merged. "What works now" still named economy-transition-v5 as the surface the C++ kernel must be implemented against, which version six superseded the same day. Version six now carries that entry with what it establishes, and version five is restated accurately: accepted, fully evidenced, and superseded as direction hours after it was evidenced, with no C++ ever written against it — which is the precedent working rather than failing. Closes #171
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 #169. Follows #166 (the gate result) and #168 (the founder answers).
The contract that encodes the account architecture ADRs 0039 through 0043 settled, with its model, 462 vectors, a verifier, and 91 tests.
What version six is
A verified identity is the root, a keyless escrow is where value sits, and a revocable signer assigned to exactly one escrow is who may act on it. An escrow's balance and nonce stay in the version-one account map, so a version-six state is still a version-one state plus an economy map.
The three decisions worth review
The kind-1 bytes survive a fifth version and their execution does not. The accepted 136-byte unsigned and 200-byte signed transfer and its transaction ID are reproduced exactly, and the same bytes are refused with
RECIPIENT_NOT_REGISTEREDwhen the recipient is not a registered escrow. That withdrawsledger-transition-v1's recipient-creating transfer — the last way an account could exist with no identity behind it — and makes every account is an escrow a structural invariant. No earlier version had to state a divergence between bytes and behaviour; the compatibility section says so in those terms and the vectors carry both halves.The signature-scheme byte carries a second authorization mode, and admission still reads no state. Version one fixes the byte at
1and reads offset 40 as the sender's key; version six reads it as an authority key and lets the scheme say whose. An earlier draft put the identity hash in the header and looked its key up in state — it works, and it would let an unsigned transaction reach execution. The key went in the header and the identity hash in the body, at a cost of 32 octets of redundancy on five kinds.Registration is fee-exempt, against ADR 0042's stated preference. The ADR prefers credit-before-fee because 1.71 units exceeds any plausible fee; that holds only while an airdrop exists. The airdrop is bounded at 1,000,000 identities, so user 1,000,001 creates a zero-balance escrow and fails with
INSUFFICIENT_BALANCE— the ecosystem would close to new members at exactly the point ADR 0042 says the problem stops recurring. ADR 0042 states either option satisfies the direction, so this is mechanism; it is flagged because the ADR recommends the other one.Evidence
462 vectors, each derived twice — once by
expected.py, which imports nothing fromsimulation/, and once by a live run of the model.Two claims are checked against a third source. The kind-1 identity and the signer derivation, both against
test-vectors/protocol-primitives-v1.txt. The second matters most: the signer derivation is the accepted version-one account derivation with its subject moved, so a restatement checked only against its own formula would agree with itself while both were wrong.Four mutation probes establish fail-closed behaviour:
The last is the decisive one, and it fails on the boolean rule:
signer.derivation_reproduces_the_accepted_account_identifierderives false and is rejected rather than recorded.The boolean rule fired during generation and cost three renamings. Three posture cases whose answer is "no confirmation" now record the negation positively rather than recording
falseunder a name asserting the opposite.Nothing accepted was edited
All five predecessor vector files verify at their recorded counts: 238, 579, 441, 550, and the version-one primitives. ADR 0043 and the constitution were corrected from "stays outstanding" to "never issued" for channel 8, because the mechanism the specification establishes does not support the stronger wording: the channel has no accrual step and therefore no
outstandingterm.Verification
Source, test, build, and vector changes, so
tools/verification_scope.pyclassifies the change set asfulland the hosted matrix applies.Local, for prompt feedback only:
tools/economy-transition-v6-vectors/verify.py— 462 vectors verifiedtests/toolsregistration guard — 8 tests, OKtools/verify_metadata.py— 5 skills, 204 linksHosted
Verifyon the exact commit is the accepting evidence.Next
M3.10b: the version-six execution model and its recorded transition trace, issue #153 rebound from version five. It comes before the C++ codec, on the repository's own lesson: M3.9a implemented a codec and M3.9b found two implementations agreeing perfectly about a message neither could construct.