Protocol v2: the before-1.0 change batch (T14) #2

Merged
amethyst merged 36 commits from release/protocol-v2 into main 2026-10-29 08:28:33 +00:00
Owner

Branch: release/protocol-v2 → main (35 commits, 176 files,
+26,587 / −6,039). Tip: c23162f.

Merge as one unit. Use a merge commit, not squash, rebase or a
cherry-pick of any part.
Every item below changes genesis, the chain ID
or block validity. They ship together so the M8 "protocol has stopped
moving" clock restarts only once. Two intermediate commits are marked
wip(...) (00ee120, a1b3a7c). The commits between them and the tip are
not each green on their own; only the tip was verified. To bisect across
this merge, use git bisect --first-parent.

What this changes

All seven items from "The Before 1.0 change batch" in
docs/research/trajectory-combined.md are here. They implement the
accepted ADR-0066 to ADR-0069, the new ADR-0071 (T9, upgrade policy) and the
T10 limits. ADR-0072 records the owner's decisions, the implementation
choices where an ADR left room, and errata.

  1. Scheme-tagged keys and signatures (ADR-0066). Every key and
    signature is an envelope (scheme u16 ‖ len ‖ payload), and the scheme ID
    is in every signed preimage. Supported schemes are Ed25519 0x0001,
    SLH-DSA-SHA2-128s 0x0201 (RustCrypto slh-dsa =0.2.0-rc.5) and the
    hybrid 0x0402. The chain config carries a disabled-scheme set (max 8),
    and the new CHKSIGX opcode is 0x63.
  2. ONX_ADDR_V2 addresses (ADR-0067). An address is the hash of an
    AuthRoot with a hot leaf and an optional backup leaf. Under the
    emergency rule, a disabled hot scheme freezes the hot leaf and the
    backup can still recover.
  3. Account key rotation (ADR-0067 §5). KeyRotate has a normal mode
    and a recovery mode. Backup recovery is commit-reveal with a delay
    (owner decision O4): a 17,280-block delay, then a 120,960-block window.
  4. Validator rekey and hybrid signatures (ADR-0068). A rekey is a system
    record approved by more than 2/3 of stake with 2^19 blocks of notice.
    There is a lost-key path. Keys apply per height. The signature-section
    budget is parameterized per scheme.
  5. Wallet-handler policies (ADR-0069). Policies give a spending cap,
    protected transfers with delay and cancel, an allowlist and a co-signer.
    New actions are SetPolicy and CancelPending; there is a pending queue
    and a release phase.
  6. Upgrade activation (ADR-0071). Activation is by height, with notice,
    a quorum and a cancel record. There is an emergency scheme disable
    (720 blocks of notice) and a liveness guard. A node that does not
    implement the required version halts.
  7. Named consensus limits (T10). Every enforced limit is named in a spec
    with its code value.

Also in the batch:

  • 5-second slots (owner decision): block_time ≥ parent + 5, with a
    15 s drift policy.
  • Block format: ONXBLK06 carries system records, and the combined state
    root covers accounts, the validator registry and the chain config.
  • New network: PROTOCOL_VERSION 2 and a new genesis and chain ID.
  • Fixed: a consensus start-up stall that the soak test found.
    Validators now re-send their own round messages every 5 s.
  • Fixed: genesis decoding is canonical.

The full list of consensus changes is in
docs/releases/protocol-v2.md.

New genesis and chain ID

v1 (main) v2 (this branch)
Devnet chain ID bbf4242b…f559f17d ba8bbec994d15ad6176878442f6243f8a6eb7a9e10a821732833ac888d5bf804
Devnet faucet account its public key d04ab232…8737 73fcb0bc0ab8ab39f46d60f4e03746db2a1252e2ceec313453b80514a82d8df0

Nothing migrates. A v2 node refuses v1 databases, ONXBLK05 block files and
v1 genesis documents.

Specs updated to match the code

These specs changed: protocol-primitives.md, state-model.md,
transactions.md, execution.md, blocks.md, consensus.md,
economics.md, tvm-instruction-set.md, contract-language.md,
networking-dht.md and networking-block-sync.md. So did
docs/research/consensus-limits.md. ADR-0066 to ADR-0069 are now Accepted
(2026-10-19), and ADR-0071 and ADR-0072 are new.

Tests, vectors and fuzzing

  • New Rust suites:
    • onx-primitives: scheme vectors, including NIST ACVP for SLH-DSA.
    • onx-stf: account policies, key rotation, system records, block
      builder, protocol-v2 vectors and wire mutation.
    • onx-tooling: quorum properties.
    • onx-cli: unit and end-to-end tests.
    • Consensus re-broadcast test.
  • Python reference: the independent implementation in reference/ now
    covers schemes, auth, policy, system records and genesis. New vector files
    are protocol_v2.json and chksig_v2.json, and every existing vector was
    regenerated. Rust agrees with every one.
  • Fuzz targets for the new signature envelope: scheme_envelope and
    account_message. Stable-toolchain mutation tests run in cargo test.

Verification (final run on c23162f's tree)

Check Result
cargo fmt --all -- --check clean
cargo clippy --workspace --all-targets -- -D warnings clean
cargo test --workspace --no-fail-fast 849 passed, 0 failed, 5 ignored (3 benchmarks, 1 timing probe, 1 test for an opcode that does not exist)
Reference generators --check (11) no drift
check-doc-links, check-spec-citations, check-research-logbook, version.py check, site.py check pass
scripts/multinode-sync-test.sh (producer and follower over ADNL, follower kill -9 and resume) pass
scripts/soak-test.py, shortened (4 validators, planned SIGKILL restarts) pass, one block per slot
Fuzzing, stable + SanitizerCoverage account_message 10 min / 57M inputs, scheme_envelope 5 min / 9M inputs; no crash
Explorer under Node, on a 34-block v2 soak chain 9/9 self-tests; 536 checks verified, 0 failed, 68 not checked (validator signatures and state root, by design)
Explorer in headless Chromium overview, message detail and genesis views render
ONX OS (feat/onx-os-protocol-v2) 12 tests OK
Kani proofs compiled against a stand-in; not run (Kani is not installable here)

Not implemented

The release notes have the full list, with reasons. In short:

  • Owner or legal decisions:
    • ADR-0067 legal items L1 and L2.
    • Runbook gaps G1 and G2.
  • Out of scope by ADR:
    • ML-DSA, SLH-DSA-128f, XMSS and Ed25519+ML-DSA are registered but
      rejected.
    • CHKSIGX supports Ed25519 only.
  • Not possible in this environment:
    • Nightly ASan fuzzing and fuzz CI.
    • Running Kani.
    • Pushing the branch.
  • Explorer gaps: it does not verify SLH-DSA signatures, validator block
    signatures or co-signer policy matching; these show as "Not checked".
  • Tooling gaps:
    • onx-cli has no chain-state queries.
    • onx-cli cannot sign an account action across several machines.
    • The Python reference has no SLH-DSA.
  • Not in the batch:
    • The release pipeline and signed SHA256SUMS.
    • The wallet emergency-sheet UX.
    • The 8-week mainnet notice is set by the 1.0 genesis ceremony, not
      enforced in code.
    • The R23 drills on a public testnet (there is none yet).
    • Reconciling the T12 runbook.

Before merging

  • Run the Kani workflow on a runner that has Kani (.forgejo/workflows/kani.yml).
  • Optional: a nightly ASan fuzz pass (fuzz/README.md).
  • At release: python3 scripts/version.py bump minor (0.3.0 → 0.4.0).
    The CHANGELOG's Unreleased section already describes v2.

After merging (deployment order)

  1. Build the v2 binaries.
  2. Stop devnet-1 (/root/onx on the devnet VM) and delete its data
    directory. v2 refuses the v1 database.
  3. Write devnet-1's genesis config in the v2 layout. A keyed balance must
    omit address or give the derived v2 address, and a [chain] section
    is optional. Then run the v2
    onx-genesis. devnet-1's current chain ID (6b0e9781…) is not the
    config/genesis.toml one, so its new ID is whatever its own genesis
    produces. Record it.
  4. Decide on empty_blocks. The v2 default is a block every 5-second slot,
    or 17,280 block files a day served by nginx from /root/onx/data/blocks.
    Set empty_blocks = false in /root/onx/onxd.toml if devnet-1 should
    keep making blocks only when there is work. docs/guides/hosting.md
    ("a block only when a message arrives") then needs updating to whichever
    you choose.
  5. Archive the v1 block files published at data.on-x-scan.com/devnet-1/.
    The v2 explorer rejects ONXBLK05 files.
  6. Edit explorer/index.html and set the pinned Devnet-1 chainId to the
    new chain ID (it is still the v1 value, 6b0e9781…). Then run
    scripts/site.py build and deploy the sites.
  7. ONX OS: merge feat/onx-os, then feat/onx-os-protocol-v2 (its devnet
    recreate writes the v2 genesis layout). Deploy it only with v2 binaries.
  8. Update the T12 runbook (docs/emergency-runbook) to the shipped
    mechanisms before merging it.

🤖 Generated with Claude Code

https://claude.ai/code/session_013JUj9jVod9FEqQDNi147PZ

**Branch:** `release/protocol-v2` → `main` (35 commits, 176 files, +26,587 / −6,039). Tip: `c23162f`. **Merge as one unit. Use a merge commit, not squash, rebase or a cherry-pick of any part.** Every item below changes genesis, the chain ID or block validity. They ship together so the M8 "protocol has stopped moving" clock restarts only once. Two intermediate commits are marked `wip(...)` (`00ee120`, `a1b3a7c`). The commits between them and the tip are not each green on their own; only the tip was verified. To bisect across this merge, use `git bisect --first-parent`. ## What this changes All seven items from "The Before 1.0 change batch" in `docs/research/trajectory-combined.md` are here. They implement the accepted ADR-0066 to ADR-0069, the new ADR-0071 (T9, upgrade policy) and the T10 limits. ADR-0072 records the owner's decisions, the implementation choices where an ADR left room, and errata. 1. **Scheme-tagged keys and signatures** (ADR-0066). Every key and signature is an envelope (`scheme u16 ‖ len ‖ payload`), and the scheme ID is in every signed preimage. Supported schemes are Ed25519 `0x0001`, SLH-DSA-SHA2-128s `0x0201` (RustCrypto `slh-dsa =0.2.0-rc.5`) and the hybrid `0x0402`. The chain config carries a disabled-scheme set (max 8), and the new `CHKSIGX` opcode is `0x63`. 2. **ONX_ADDR_V2 addresses** (ADR-0067). An address is the hash of an AuthRoot with a hot leaf and an optional backup leaf. Under the emergency rule, a disabled hot scheme freezes the hot leaf and the backup can still recover. 3. **Account key rotation** (ADR-0067 §5). `KeyRotate` has a normal mode and a recovery mode. Backup recovery is commit-reveal with a delay (owner decision O4): a 17,280-block delay, then a 120,960-block window. 4. **Validator rekey and hybrid signatures** (ADR-0068). A rekey is a system record approved by more than 2/3 of stake with 2^19 blocks of notice. There is a lost-key path. Keys apply per height. The signature-section budget is parameterized per scheme. 5. **Wallet-handler policies** (ADR-0069). Policies give a spending cap, protected transfers with delay and cancel, an allowlist and a co-signer. New actions are `SetPolicy` and `CancelPending`; there is a pending queue and a release phase. 6. **Upgrade activation** (ADR-0071). Activation is by height, with notice, a quorum and a cancel record. There is an emergency scheme disable (720 blocks of notice) and a liveness guard. A node that does not implement the required version halts. 7. **Named consensus limits** (T10). Every enforced limit is named in a spec with its code value. Also in the batch: - **5-second slots** (owner decision): `block_time ≥ parent + 5`, with a 15 s drift policy. - **Block format:** ONXBLK06 carries system records, and the combined state root covers accounts, the validator registry and the chain config. - **New network:** `PROTOCOL_VERSION` 2 and a new genesis and chain ID. - **Fixed:** a consensus start-up stall that the soak test found. Validators now re-send their own round messages every 5 s. - **Fixed:** genesis decoding is canonical. The full list of consensus changes is in [`docs/releases/protocol-v2.md`](docs/releases/protocol-v2.md). ## New genesis and chain ID | | v1 (`main`) | v2 (this branch) | | --- | --- | --- | | Devnet chain ID | `bbf4242b…f559f17d` | `ba8bbec994d15ad6176878442f6243f8a6eb7a9e10a821732833ac888d5bf804` | | Devnet faucet account | its public key `d04ab232…8737` | `73fcb0bc0ab8ab39f46d60f4e03746db2a1252e2ceec313453b80514a82d8df0` | Nothing migrates. A v2 node refuses v1 databases, ONXBLK05 block files and v1 genesis documents. ## Specs updated to match the code These specs changed: `protocol-primitives.md`, `state-model.md`, `transactions.md`, `execution.md`, `blocks.md`, `consensus.md`, `economics.md`, `tvm-instruction-set.md`, `contract-language.md`, `networking-dht.md` and `networking-block-sync.md`. So did `docs/research/consensus-limits.md`. ADR-0066 to ADR-0069 are now Accepted (2026-10-19), and ADR-0071 and ADR-0072 are new. ## Tests, vectors and fuzzing - **New Rust suites:** - `onx-primitives`: scheme vectors, including NIST ACVP for SLH-DSA. - `onx-stf`: account policies, key rotation, system records, block builder, protocol-v2 vectors and wire mutation. - `onx-tooling`: quorum properties. - `onx-cli`: unit and end-to-end tests. - Consensus re-broadcast test. - **Python reference:** the independent implementation in `reference/` now covers schemes, auth, policy, system records and genesis. New vector files are `protocol_v2.json` and `chksig_v2.json`, and every existing vector was regenerated. Rust agrees with every one. - **Fuzz targets** for the new signature envelope: `scheme_envelope` and `account_message`. Stable-toolchain mutation tests run in `cargo test`. ## Verification (final run on `c23162f`'s tree) | Check | Result | | --- | --- | | `cargo fmt --all -- --check` | clean | | `cargo clippy --workspace --all-targets -- -D warnings` | clean | | `cargo test --workspace --no-fail-fast` | **849 passed, 0 failed, 5 ignored** (3 benchmarks, 1 timing probe, 1 test for an opcode that does not exist) | | Reference generators `--check` (11) | no drift | | `check-doc-links`, `check-spec-citations`, `check-research-logbook`, `version.py check`, `site.py check` | pass | | `scripts/multinode-sync-test.sh` (producer and follower over ADNL, follower `kill -9` and resume) | pass | | `scripts/soak-test.py`, shortened (4 validators, planned SIGKILL restarts) | pass, one block per slot | | Fuzzing, stable + SanitizerCoverage | `account_message` 10 min / 57M inputs, `scheme_envelope` 5 min / 9M inputs; no crash | | Explorer under Node, on a 34-block v2 soak chain | 9/9 self-tests; 536 checks verified, 0 failed, 68 not checked (validator signatures and state root, by design) | | Explorer in headless Chromium | overview, message detail and genesis views render | | ONX OS (`feat/onx-os-protocol-v2`) | 12 tests OK | | Kani proofs | compiled against a stand-in; **not run** (Kani is not installable here) | ## Not implemented The release notes have the full list, with reasons. In short: - **Owner or legal decisions:** - ADR-0067 legal items L1 and L2. - Runbook gaps G1 and G2. - **Out of scope by ADR:** - ML-DSA, SLH-DSA-128f, XMSS and Ed25519+ML-DSA are registered but rejected. - `CHKSIGX` supports Ed25519 only. - **Not possible in this environment:** - Nightly ASan fuzzing and fuzz CI. - Running Kani. - Pushing the branch. - **Explorer gaps:** it does not verify SLH-DSA signatures, validator block signatures or co-signer policy matching; these show as "Not checked". - **Tooling gaps:** - `onx-cli` has no chain-state queries. - `onx-cli` cannot sign an account action across several machines. - The Python reference has no SLH-DSA. - **Not in the batch:** - The release pipeline and signed `SHA256SUMS`. - The wallet emergency-sheet UX. - The 8-week mainnet notice is set by the 1.0 genesis ceremony, not enforced in code. - The R23 drills on a public testnet (there is none yet). - Reconciling the T12 runbook. ## Before merging - [ ] Run the Kani workflow on a runner that has Kani (`.forgejo/workflows/kani.yml`). - [ ] Optional: a nightly ASan fuzz pass (`fuzz/README.md`). - [ ] At release: `python3 scripts/version.py bump minor` (0.3.0 → 0.4.0). The CHANGELOG's Unreleased section already describes v2. ## After merging (deployment order) 1. Build the v2 binaries. 2. Stop devnet-1 (`/root/onx` on the devnet VM) and delete its data directory. v2 refuses the v1 database. 3. Write devnet-1's genesis config in the v2 layout. A keyed balance must omit `address` or give the derived v2 address, and a `[chain]` section is optional. Then run the v2 `onx-genesis`. devnet-1's current chain ID (`6b0e9781…`) is not the `config/genesis.toml` one, so its new ID is whatever its own genesis produces. Record it. 4. Decide on `empty_blocks`. The v2 default is a block every 5-second slot, or 17,280 block files a day served by nginx from `/root/onx/data/blocks`. Set `empty_blocks = false` in `/root/onx/onxd.toml` if devnet-1 should keep making blocks only when there is work. `docs/guides/hosting.md` ("a block only when a message arrives") then needs updating to whichever you choose. 5. Archive the v1 block files published at `data.on-x-scan.com/devnet-1/`. The v2 explorer rejects ONXBLK05 files. 6. Edit `explorer/index.html` and set the pinned Devnet-1 `chainId` to the new chain ID (it is still the v1 value, `6b0e9781…`). Then run `scripts/site.py build` and deploy the sites. 7. ONX OS: merge `feat/onx-os`, then `feat/onx-os-protocol-v2` (its devnet recreate writes the v2 genesis layout). Deploy it only with v2 binaries. 8. Update the T12 runbook (`docs/emergency-runbook`) to the shipped mechanisms before merging it. 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_013JUj9jVod9FEqQDNi147PZ
Commits the pending deliverables from the earlier trajectory, cryptography
and resilience tasks exactly as packaged: ADR-0065 (D6 direction),
ADR-0066 (scheme-tagged keys), ADR-0067 (AuthRoot addresses), ADR-0068
(validator rekey), code facts, crypto inventory, the PQ benchmark crate
and results, and the D6 edits to README, MILESTONES, PHILOSOPHY and the
site copy. All ADRs are Proposed; no consensus code changes.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01DGPu7niw4NeZLTPRzqyMV9
Task T8. Specifies the Policy cell (cap per N blocks, delay with cancel
window above a threshold, allowlist root, co-signer leaf), SetPolicy and
CancelPending, the pending-outbound queue, and the rule that received
assets never change permissions. Maps each rule to the R11 incidents,
counts four consensus changes with file paths, and keeps the signed
format reusable by P4 contract accounts via the ADR-0066 envelope.
No code changes.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01DGPu7niw4NeZLTPRzqyMV9
Adds each limit the node enforces to the spec for its layer, as a named
constant whose value matches the code: the ONXBLK05 block limits
(blocks.md 3.5), wallet-handler message limits (transactions.md 3.6),
the fee-split rounding (economics.md 3.2), cell, trie, embedded-cell and
genesis limits (state-model.md), VM stack, builder and field-width
limits and the implemented SETDATA/MSG* prices (tvm-instruction-set.md),
consensus timeouts, admission and transport bounds (consensus.md 3.8),
and exact block-sync sizes. SUBBYTES gas now states the enforced 4,
with the spec price kept as P1's pending change (drift D3). Specs that
state limits version 1 does not enforce now say so.

docs/research/consensus-limits.md has the table of 48 limits with code
paths and spec sections, and the ADR-0029/0034 status note. No limits
or code changed.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01DGPu7niw4NeZLTPRzqyMV9
Kani harnesses for verify_block_auth (crates/tooling/onx/src/auth.rs)
and has_quorum_stake (crates/protocol/onx-consensus/src/lib.rs), behind
cfg(kani). For up to 8 validators with any u64 stakes they check that
quorum holds exactly when 3 * signed > 2 * total (exactly 2/3 is
rejected), that no stake sum overflows, and that duplicate or
out-of-order indices and duplicate validator keys are rejected. Ed25519
decoding and verification and the header hash are stubbed.

Also in this commit:
- scripts/kani.sh installs Kani 0.68.0 if missing and runs both crates.
- .forgejo/workflows/kani.yml runs it on runner label onx-docker. No
  runner is registered (docs/MIGRATION-forgejo.md), so it is the
  owner's call whether to keep it.
- crates/tooling/onx/tests/quorum_properties.rs checks the same
  properties with real Ed25519 signatures.
- scripts/quorum_smt.py is a Z3 proof of the u128 checked arithmetic
  and the predicate.
- Both Cargo.toml files declare check-cfg for cfg(kani).

Kani itself has not run yet: it could not be installed where this was
written. So far the Z3 proof passes, the tests pass, clippy -D warnings
is clean, and the harnesses type-check and pass clippy against a
stand-in kani crate that also checks each stub's target and signature.
No production code changed.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_013JUj9jVod9FEqQDNi147PZ
SchemeId registry, PublicKey/Signature envelopes with exact lengths,
v2 preimage pad32(tag) || scheme_id || message, the disabled-scheme set,
and verification/signing for Ed25519, SLH-DSA-SHA2-128s (FIPS 205 pure,
empty context, via slh-dsa =0.2.0-rc.5) and the AND composite 0x0402.

Vectors: ADR-0066 section 6 Ed25519 envelope vector and a NIST ACVP subset
for SLH-DSA-SHA2-128s (keyGen, sigVer, deterministic sigGen).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_013JUj9jVod9FEqQDNi147PZ
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_013JUj9jVod9FEqQDNi147PZ
Work in progress on the protocol v2 release branch; nothing here merges
on its own. Known open items: two trie tests overflow the stack with the
larger AccountState, trie tests still compare the combined state root with
the batch trie root, and clippy has not been run on the new modules.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_013JUj9jVod9FEqQDNi147PZ
Box the optional policy and recovery sections so AccountState stays small
(the trie recursion overflowed the stack with them inline), point the trie
and proof tests at the account root, update layout tests to the 181-byte
header, key the fuzz seed's established account by its derived address,
and make onx-state-model clippy-clean (including the pre-existing
arithmetic_side_effects errors in account.rs and contract_cells.rs).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_013JUj9jVod9FEqQDNi147PZ
AccountAction/AccountMessage codec for kinds 0, 1, 3, 4, 5 and 6; owner,
co-signer, backup and incoming-key authorizations over role digests;
policies (cap, protect queue, allowlist, co-signer, SetPolicy classes,
CancelPending); key rotation and commit-reveal recovery; the release phase;
validator rekey and upgrade approval records; version gating by height.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_013JUj9jVod9FEqQDNi147PZ
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_013JUj9jVod9FEqQDNi147PZ
CHKSIGX (0x63) takes a scheme id and a domain selector (0 contract, 1
account action, ADR-0069 W3); Ed25519 only in protocol v2. CHKSIGNU signs
under ONX_CHKSIGNU_V2 with the scheme id. Vectors from an independent
Python generator.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_013JUj9jVod9FEqQDNi147PZ
Votes and proposals carry Signature envelopes under ONX_VALIDATOR_SIGN_V2;
validator keys are SchemePublicKeys; the engine checks the disabled set;
hybrid 0x0402 keys use AND semantics. Named size bounds MAX_VOTE_BYTES and
MAX_PROPOSAL_BYTES; ADR-0068 §7's commit-vote size is off by one.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_013JUj9jVod9FEqQDNi147PZ
pending_actions table written with the accounts and verified against each
account's policy section on load; validator registry and chain config in
meta; block bodies carry system records; older schemas are refused.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_013JUj9jVod9FEqQDNi147PZ
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_013JUj9jVod9FEqQDNi147PZ
Keyed balances live at their AuthRoot address (optional backup_key adds the
SLH-DSA recovery leaf); validator keys are scheme-tagged; [chain] sets the
disabled schemes and upgrade notice. config/genesis.toml chain ID is now
ba8bbec994d15ad6176878442f6243f8a6eb7a9e10a821732833ac888d5bf804; the
faucet moved to its derived address 73fcb0bc...8df0.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_013JUj9jVod9FEqQDNi147PZ
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_013JUj9jVod9FEqQDNi147PZ
The Python reference now implements the V2 encodings independently:
scheme envelopes, AuthRoot leaves and proofs, every AccountAction kind,
policies and the pending queue, system records, the combined state root
and the genesis document and chain ID. Rust reproduces the Python
genesis document and the five signed ONXBLK06 block files byte for
byte; the phase5 golden roots were computed by the reference first.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_013JUj9jVod9FEqQDNi147PZ
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_013JUj9jVod9FEqQDNi147PZ
Protocol v2 has too many wallet rules to mirror by hand in the mempool
(ADR-0069 node impact). BlockBuilder runs the activation step and phase 0
on a scratch copy once, then admits system records and external messages
through the functions apply_block uses, restoring the scratch state on a
refusal.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_013JUj9jVod9FEqQDNi147PZ
- 5-second slots: the leader proposes once its clock reaches parent
  block_time + 5 and stamps its clock; validators refuse proposals more
  than 15 s ahead (MAX_FUTURE_DRIFT_SECS). An injectable Clock keeps
  tests fast. Empty blocks every slot by default (empty_blocks) so
  block-counted delays keep running on an idle chain.
- The mempool admits messages through the STF's own wallet handler
  (BlockBuilder) instead of a hand mirror, holds refusals that can go
  away, orders each sender's cancels, rotations and nonce actions, and
  takes validator rekey and upgrade records as *.sys files.
- The consensus driver, block validator, commit self-check and follower
  use the validator set and disabled schemes in force at each height;
  a node can hold its next (rekeyed) key and switches at activation.
- Scheme-tagged signatures everywhere; ADR-0068 sig-section budget per
  validator scheme; signing keys may be Ed25519 or hybrid 0x0402.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_013JUj9jVod9FEqQDNi147PZ
Records commit under ONX_DHT_RECORD_V2 and are signed under
ONX_VALIDATOR_SIGN_V2 over the v2 preimage; owners are SchemePublicKey
envelopes. Owners stay ADNL identities, which remain Ed25519 (ADNL keys
are out of ADR-0066's scope), so a non-Ed25519 owner has no address and
is refused.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_013JUj9jVod9FEqQDNi147PZ
onx-cli now builds V2 external messages (ADR-0069 §3) and system records:

- wallet create / backup-create (SLH-DSA-SHA2-128s backup mnemonic,
  ADR-0067) / address (ONX_ADDR_V2 of the AuthRoot, with --backup-key;
  --seed-file accepted);
- transfer (owner proof, optional backup leaf, co-signer, allowlist
  proof), set-policy (incoming co-signer signature), cancel (owner or
  co-signer alone), rotate (keeps the backup leaf), recovery-commit and
  recovery-reveal (commit-reveal with the 17,280-block delay, O4);
- system rekey-body / upgrade-body / approve / assemble: each validator
  signs on its own machine; assemble writes a <hash>.sys record into
  the node's tx pool.

--reveal-key is gone: in V2 the owner proof always carries the leaf, and
the first spend establishes the AuthRoot.

Tests: 21 unit tests; transfer_e2e drives the real binary against the
devnet genesis and the real STF: faucet round trip, impostor keys
(AddressKeyMismatch, then AuthRootMismatch), rotation, backup recovery
(RecoveryPending while live, reveal refused before the delay), a
protected transfer queued and cancelled, a rekey to a hybrid 0x0402 key
and an upgrade announcement assembled from separate approvals (and a
short quorum rejected).

Scripts and the launch guide use derived addresses (the faucet is no
longer at its public key); multinode-sync-test and the soak harness set
empty_blocks = false to keep their one-block-per-transfer shape. Both
pass against the v2 binaries.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_013JUj9jVod9FEqQDNi147PZ
Consensus messages are fire-and-forget over TCP. In the v2 soak run every
node starts at once, the round-0 leader proposed before two peers were
listening, and the chain made no block for 60 s (the round timeout); it
reproduced in 3 of 3 runs. The pre-v2 binaries happened to win the race.

The driver now keeps the proposal and votes it signed in the current
round and re-broadcasts them every REBROADCAST_MS (5 s) until the height
finalizes; entering a round clears them. Re-sent messages are
byte-identical, and the engine already treats duplicates as no-ops, so
this is node policy only: no wire or consensus-rule change.

With it the short soak makes a block per 5-second slot from the start
(2 of 2 runs), and survives planned SIGKILL restarts.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_013JUj9jVod9FEqQDNi147PZ
Formatting only (cargo fmt --all); no code change.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_013JUj9jVod9FEqQDNi147PZ
The V2 external message (account action, every authorization role, auth
proofs, co-signer leaves, backup keys, allowlist proof) and the system
record (rekey, upgrade) are decoded from untrusted pool files and peers.
The new account_message target and the stable wire_mutation test check
that decoding never panics and that every input that decodes re-encodes
to exactly itself.

Ran here on stable with SanitizerCoverage (no nightly, so no ASan):
account_message 10 minutes, 57M inputs; scheme_envelope 5 minutes, 9M
inputs; no crash. The README documents the stable invocation and that
fuzz CI has not existed since the Forgejo migration.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_013JUj9jVod9FEqQDNi147PZ
Every spec the T14 ADRs touch now describes the code on this branch:

- protocol-primitives: scheme registry, envelopes, v2 signing preimage,
  disabled-scheme rule, hybrid AND semantics, and the v2 tag registry
  (§3.6, §4.5, §4.6);
- state-model: the 181-byte account record with AuthRoots, auth_seq,
  policy, recovery and pending sections (§4.1–§4.1.4), the v2 genesis
  document (§4.7), AuthRoot leaves, trees, proofs and addresses with the
  corrected ADR-0067 vector (§4.8), and the validator registry, chain
  configuration and combined state root (§4.9);
- transactions: the wallet handler — kinds, roles, exact authorization
  sets, order of checks, cap, SetPolicy, cancel, rotation, recovery,
  release phase and limits (§3.6) — and the v2 wire format (§4.4);
- blocks: ONXBLK06 limits, 5-second spacing, scheme-tagged signature
  section and per-scheme budget (§3.5), body, system records and phase
  order (§3.6);
- consensus: v2 signing, constants, validator rekeys, upgrade activation,
  slot and node policy (§3.8–§3.11), proposal and vote encoding (§4.7);
- tvm-instruction-set: CHKSIGNU v2 and CHKSIGX (§4.6);
- networking-dht, networking-block-sync, economics, execution and
  contract-language G10.

docs/research/consensus-limits.md gains the protocol-version-2 table (9
changed limits, 28 new rows, each with its code path and spec section);
crypto-inventory.md gains the v2 summary. Code doc comments point at the
new sections.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_013JUj9jVod9FEqQDNi147PZ
- ADR-0066 to ADR-0069: Accepted 2026-10-19 for the T14 batch, pointing
  at ADR-0072 and the specs. ADR-0067 §8 gains an erratum note.
- ADR-0071 (T9), Upgrade policy: how activation worked before (a
  compile-time version, no procedure), BIP 50 and Constantinople, and the
  policy T14 implements — activation by height recorded on chain, notice
  as a genesis parameter (>= 4 weeks testnet, 8 weeks after 1.0), a
  published ADR and release manifest approved by more than 2/3 of stake,
  refusal of unknown versions, cancel, reproducible binaries, emergency
  scheme disable with 720 blocks of notice and the T12 runbook, and a
  liveness guard — with the code changes listed.
- ADR-0072: every owner decision given for T14, every choice the code
  makes that an ADR left open (O1–O12, W1–W6, rekey and upgrade rules,
  ONXBLK06, empty blocks, re-broadcast, mempool admission, key files),
  and three errata (ADR-0067 §8 vector, ADR-0068 §7 vote size, ADR-0069
  roles).

onxd now logs the chain-level changes a committed block makes (rekey
activations and schedules, upgrade announcements with the versions this
binary supports, cancels), which ADR-0071 asks operators to watch.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_013JUj9jVod9FEqQDNi147PZ
ONXBLK06 blocks, AccountAction messages with scheme-tagged authorizations
and AuthRoot proofs, system records, the v2 genesis and chain config.
Verifies Ed25519 signatures, AuthRoot proofs, nonces and 5-second spacing;
SLH-DSA signatures, the SLH-DSA half of hybrids, validator block signatures
and co-signer policy matching are shown as not checked. The pinned
Devnet-1 chain ID stays at the v1 value until devnet-1 is reset.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_013JUj9jVod9FEqQDNi147PZ
site.py reads PROTOCOL_VERSION_V2 and checks the explorer against the v2
header and cell vectors in reference/vectors/protocol_v2.json. The probe
console lists the v2 negative tests.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_013JUj9jVod9FEqQDNi147PZ
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_013JUj9jVod9FEqQDNi147PZ
Every consensus change, the defaults chosen, verification and what was not
implemented and why. consensus.md states the measured hybrid signing time.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_013JUj9jVod9FEqQDNi147PZ
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_013JUj9jVod9FEqQDNi147PZ
Author
Owner

Restored record (DT-22 rebuild, 2026-10-28): this pull request was originally #27 on the previous Forgejo instance, which was lost when the old server was destroyed (2026-10-27/28). Recreated from the preserved API capture with its original title and body. Head branch release/protocol-v2 at c23162f, matching the lost server head.

Restored record (DT-22 rebuild, 2026-10-28): this pull request was originally **#27** on the previous Forgejo instance, which was lost when the old server was destroyed (2026-10-27/28). Recreated from the preserved API capture with its original title and body. Head branch `release/protocol-v2` at `c23162f`, matching the lost server head.
amethyst deleted branch release/protocol-v2 2026-10-29 08:28:33 +00:00
Sign in to join this conversation.
No reviewers
No labels
Priority
Critical
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
amethyst/the-open-network-x!2
No description provided.