soft3/audit/chain/slice-2026-10-16.md

the vertical slice of the phase-1 root chain — 2026-10-16

One block from genesis to a second machine, locally: the consensus kernel (#189), the reference miner (#186) and the wire (#187) in one binary, three nodes on one machine, every block mined by soft3 mine --backend cpu against a node's /template + /submit, every header, body and transaction crossing the radio wire to the other nodes and validated there by the kernel. Requirements: specs/chain.md, specs/chain-wire.md, specs/chain-conformance.md. Earlier receipts: audit/chain/net-2026-10-15.md (the wire on its stand-in), audit/chain/mine-2026-10-15.md, audit/chain/conformance-2026-10-16.md.

what changed

  • main: #186 merged on the kernel (4527df7, merge of feat/chain-mine-on-kernel = #186 + the swap f1f4e94: the miner asks chain::{header, pow, daa}, its local ASERT copy is gone).
  • #187 brought onto main as one squashed commit (the branch carried a merge of main whose own changes a commit-by-commit rebase would drop), then:
    • chain/net/devchain.rs deleted; chain/net/kernel.rs implements the wire's port ChainView over the kernel's ChainApi: header-first acceptance, NeedBodies (the wire fetches the named bodies from the peer and resubmits, gossip::apply_fetched; IBD takes the gap by ranges), FutureTime held and retried each sync tick, DeepFork / Checkpoint logged and never scored, ChainError::Block scores the serving peer +10, tip-moved events carry the reorged-out bodies, a main-chain txid index for GET /tx/{txid}. Headers and u256 cross as their wire bytes; a test pins header ids, txids, bodies and tx roots on both codecs.
    • mempool admission asks the kernel (validate_tx with the neuron's lower pending nonces); a nonce gap inside the window is not scored, a nonce beyond it is (+10). The kernel's validate_tx now checks the signature before nonce, fee and balance — chain-wire §4's order; the adversarial tx flood (unsigned junk at fee 0) was going unscored without it.
    • HTTP §7 on the kernel: /tip and /template rendered by Tip::json / Template::json; /nonce {neuron, nonce, confirmed}; POST /tx {txid, kind, size, fee, account, nonce} (already present = 200); GET /tx/{txid} {txid, kind, tx, height|"mempool", block, index}, 404 {"error":"unknown"}; POST /submit 200 / 409 stale / 422 with the kernel's reason. /status genesis is the chain id (what the wallet signs for), genesis-block, next-bits from ASERT, finalized.
    • the node no longer mines (--mine/--solo/--miner, /dev/mine gone): mining is soft3 mine. soft3 chain genesis-dev writes a real GenesisFile (kernel-checked, launch names refused), soft3 chain key|tx sign with soft3::wallet::Signer.
    • gossip topic loops survive a lagged receiver instead of ending.
    • [profile.dev.package.cyber-hemera] opt-level = 3: tests mine real blocks at the floor target on debug builds.
    • scripts/chain-fleet.nu: miners are soft3 mine processes; every pid it spawns is recorded in $work/pids and killed by pid — the pkill -f is gone.

Test chain: dev, bits = POW_LIMIT_BITS (0x1e100000, 2^20 expected hashes, the easiest target the kernel accepts outside cfg(test)), genesis time two hours back so ASERT sits at the floor for the first ~240 blocks. No launch genesis is touched; genesis-dev refuses pussy, bostrom, pussy-rc.

Hash: hemera 0.3 (hemera d5f0a09). Every hash on the slice goes through the hemera API (hemera::hash, the kernel's hash32, the miner's sponge view); the move to hemera 0.4 (profile #15) re-blesses PoW vectors, the genesis particle and chain.snap in its own sweep.

stand

~/cyber/.stands/N2, Apple M4 Max, macOS 26.4.1. soft3 on slice/net over main 4527df7. Siblings at the kernel receipt's integration base (bbg 1d39975, cybergraph 0eae7ae, foculus 9e32aa6, mudra 4bfe3e8, zheng 0c882e7, joy 06de02c), lens e11eaa8 (release/0.2), nox 2f09ca3 / trident a3cef15f (release/0.4), hemera d5f0a09, radio 50600cc1, tade c7d404a. Deviation from the requested pins: zheng release/0.4 and bbg master do not build with soft3 main (bbg master lacks the vendored fjall the chain store uses; bbg 1d39975 needs zheng's feat/public-certificate-v3 API), so both stay at the kernel receipt's base.

one block from genesis to a second machine

cargo build --release --locked --bins                           # 1 m 34 s incremental
nu scripts/chain-fleet.nu --bin .target/release/soft3 --keep
chain-fleet: 3 nodes · chain dev · binary …/.target/release/soft3
  ok    binary speaks the phase-1 flags
  ok    ports free: http 17780,17781,17782,17783 radio 17790,17791,17792,17793
  ok    homes + genesis + peers under /tmp/chain-fleet.wVWUzs; wallet aaaeb678a…
chain-fleet: launched pids 74396 74398 74400
  ok    all 3 nodes answer /status
chain-fleet: soft3 mine --backend cpu --threads 1 on node-1 (pid 74421) and node-2 (pid 74423)
  ok    peers connected: node-1=1 node-2=1 node-3=2
  ok    block 1 f9a96f3fc444d… mined by 111111111… is block 1 on every node
  ok    heights agree at 7 across 3 nodes
chain-fleet: late joiner node-4 pid 75323
  ok    late joiner synced to height 8 (IBD by ranges)
txid 7d26e8969032a03206a0996e1402f2ad1a0280b4fc8c72af2bc0425edf6e0117
  ok    tx 7d26e8969… submitted to node-1, mined at 10 by node-2's miner 222222222…, bob=5 on node-3
  ok    fork of depth 3 from 10: main 13 reorged to the heavier chain 15, tip 2e253b946… on every node
chain-fleet: node-3 killed and relaunched as pid 76024
  ok    node-3 recovered from disk: height 15 before the kill, 22 after restart (replayed, then synced), conserved
chain-fleet: artifacts kept in /tmp/chain-fleet.wVWUzs
chain-fleet: GREEN

Block 1, end to end (node-1's miner log, then node-2 and node-3):

soft3 mine · chain dev · node http://127.0.0.1:17780 · cpu (1 threads) · to 1111…1111
template height 1 prev 50453f910886… bits 0x1e100000 (2^20 expected hashes)
found nonce 0x7d717dafd5726d8b00000000000ff34b after 1048576 hashes, 3.9s
block 1 accepted: f9a96f3fc444da08fdb30839140110d8c38ce8364922fbe31a4f410de3020000
node-2  net · header f9a96f3f at 1 from 630a8dba
node-3  net · header f9a96f3f at 1 from 630a8dba

An earlier run the same day (/tmp/chain-fleet.Q7vBAc) was GREEN too: heights 11, late joiner IBD of 11 blocks in one range, tx mined at 13 by node-2's miner, depth-3 fork from 14 (main 17 → fork 19), node-3 19 → 20 after restart. After both runs no process of the fleet was left.

the gates

gate command result
soft3 tests cargo test --locked (crate/) 208 lib + 12 bin + 2 adversarial + 1 miner e2e, all ok, with HOME holding a main-format pussy genesis (below)
chain conformance tests cargo test --locked --features chain-conformance --lib chain:: 106 ok
adversarial set cargo test --locked --test chain_adversary 2 ok (7.8 s): oversize, malformed, no-dialect, wrong chain, PoW-invalid header (no body requested), bad block +10 not banned, tx flood banned, body on gossip banned — against a kernel node mined by soft3 mine
conformance soft3 conformance check chain --genesis /tmp/n2-genesis/pussy.tade chain.snap: 9 entries, no drift
stack-chain-genesis chain_genesis_gate(…, genesis_dir=/tmp/n2-genesis) from release/train_gates.py exit 0, no drift, recorded red — the gate fails on any warning: line, and bbg 1d39975's vendored fjall prints 3 (journal_recovery_mode, outstanding_flushes, write_tx lifetime); soft3 prints none. Same on main at this bbg pin.

The pussy genesis for the conformance rows was rebuilt from the pinned snapshot with this build into a private directory: soft3 genesis build --chain pussy --snapshot ~/cyber/space-pussy/snapshot --out /tmp/n2-genesis/pussy.tade (4.4 s) → particle 2a83e54f…61b5, state root f2296834…5827, block 0 b863ce28…a304: the blessed vectors. The shared cache ~/cyber/.cache/genesis/pussy.tade was rewritten at 11:07 today by an unmerged branch with a longer params record (pool formats); main cannot decode it (74 trailing bytes in frame), so with the default HOME the two cache-reading tests fail on main and on this branch alike. It was left as it is.

what the deploy to cyberproxy, deimos and jupiter still needs

  • a release carrying #187 on the kernel (cargo install soft3 --version <phase-1>), built against pins that build: bbg needs its fjall vendoring on master (or soft3 moves off bbg/rs/vendor/fjall), and the stack-chain-genesis gate needs those 3 warnings gone to turn green.
  • the launch genesis files from soft3 genesis build with the final params, the hemera 0.4 re-bless done, and the ids pinned in chain::params::CHAINS; until then --genesis FILE on every machine, byte-identical (step C T−15).
  • miners: the nodes do not mine. Someone runs soft3 mine --node http://127.0.0.1:7781 --address <neuron> (Metal/WebGPU/CPU) against at least one node at genesis, or block 1 never comes.
  • endpoint ids (soft3 node id) collected into peers.toml on each box, ufw for 7791/udp, nginx snippets (README step A6), jupiter's root steps by the owner (no sudo).
  • not exercised here: three real machines over the internet (NAT, relay off, clock skew), a replay at a real height (restart replays every body; tens of blocks took seconds here), and best_header / missing_bodies scanning the in-memory store on each call — fine at slice size, to index before long chains.

Graph