Proto Sling node#272
Open
GCdePaula wants to merge 5 commits into
Open
Conversation
The rollups node becomes a single crate: worker modules synchronize through the storage module (the only SQL surface), and one spec-oracled engine (src/engine: structure, stf, ruler, and the dispute facade) serves both the runner's forward schedule and the dispute path's random access. - One leaf semantics: process_input and the second geometry implementation are gone. The runner schedules the engine's collect() per input window; the window-root quartet row is the only durable level-0 artifact; settlement and dispute serving read the same rows (frontier fold, strict and prefix-bounded). - The boundary store (stage+rename, write-once cells, clone-based revert) carries both regimes' revert insurance; corruption tripwires panic through the loud process exit, never retry. - Revert on RX_REJECTED only, matching AdvanceStatus.sol - the chain never reverts an exception. - The staged settlement protocol: the epoch manager drives sentry claim, stage, and accept per tick, each step guarded and idempotent; a sentry always claims the locally computed post-epoch hash, never the staged value. settlement_info carries final_state, captured from the boundary store at roll (the new epoch's initial boundary IS the post-epoch state). - Absorbs prt/client-rs (the tournament reader/sender/gc and the hero's react loop, traced against the contracts - the audit ledger records verdicts and clean checks) and common-rs (merkle, arithmetic, and kms become node modules; the node was their only consumer). - Chain recordings - raw devnet log ranges captured after e2e disputes settle - are committed fixtures for the tournament fold, decoded through the production bindings. Replaces the epoch-manager/state-manager/blockchain-reader/ prt-node crates, prt/client-rs, and common-rs.
23 scenarios (echo, the honeypot stf suite, kill/respawn lifecycle points, multi_sybil's concurrent matches, kill_join), orchestrated on hardened primitives: drive loops advance one block per poll, Env.fast_forward is chess-clock-safe (sleep first), sybils auto-allocate signing accounts and refuse the node's, scenario deadlines convert hangs to failures. battery.sh runs the suite in lanes and records power provenance. The env deploys with the node's wallet as the sole sentry (claim staging period 1000), so every scenario exercises the staged protocol's claim-agreement fast path. test_env's run_epoch records the chain after settle (RECORD_CHAIN_FIXTURE) - the capture hook for the node's fold fixtures. The Lua client stays the independent commitment oracle; the harness reads the node's claim from settlement_info, never from node internals.
just check is the pre-commit gate (fmt, luacheck, clippy -D warnings, unit and integration tests) and preflights docker itself; just doctor diagnoses the checkout and names the fixing command for every gap. Generated bindings are gitignored and rebuilt by just bind; devnet artifacts carry a fingerprint. Contracts formatting joins the gate.
The knowledge base (docs/): computation-hash, dimensioning, epoch-lifecycle (the staged settlement protocol), node-architecture, test-harness, glossary, build-system. The campaign ledger (docs/plans/): sling-design, snapshots, one-engine, node-audit and friends - decisions with their reasons, incident reports, and open leads, including the tombstones for the rejected D.2 sub-window tier and gap-1 default, and the promoted setup/run split. AGENTS.md maps the repo for agent sessions; prt/contracts/AGENTS.md carries the contracts-specific context.
CI: pull_request joins the triggers (a bare push trigger gives forks no CI at all) and push narrows to the long-lived branches plus release tags, deduped by the existing concurrency group. The from-source emulator build - the build job's dominant cost - gets a cache keyed on the submodule commit: the recipes are idempotent (make no-ops on a warm tree, the diff apply detects an already-patched one), so a hit skips the work and an emulator bump rebuilds for real. Cargo caching already existed via setup-rust-toolchain's embedded rust-cache. Two stale gap-1 comments updated to the gap-2 harness default. Tooling, per the DX doctrine (fix the trap, not the docs): shell pipelines like `cmd | tail` report the LAST stage's status and have laundered real failures into green output more than once this campaign. `just logged <file> <cmd...>` writes full output to the file and reports the true exit code; recipe lines now run under bash pipefail so in-recipe pipes fail honestly too (no recipe pipes to head/tail, where pipefail would surface benign SIGPIPEs). The CI step chained `just bundle-boost apply-generated-files-diff build-emulator`, and just's CLI grammar feeds words following a parameterized recipe into its arguments: apply-generated-files-diff ran with VERSION="build-emulator", downloaded release "build-emulator", and 404ed - silently under wget -q (exit 8, two runs), legibly once curl started naming the error. The line was this branch's own CI dedup and had never executed before this PR; next/3.0's green job used a raw inline wget. Both old and new just versions consume the argument - the 1.56->1.57 upgrade between runs was a red herring. Three layers so the class dies: - The workflow calls `just setup` - dependency form passes no arguments and is immune to the grammar. - The recipe guards its VERSION (must look like a release tag) and names the trap in its error, so any future arg-eating fails in one legible line instead of a mute 404. - CI's just is pinned like rust and foundry already were; a floating "latest" upgrading mid-hunt muddied the evidence.
GCdePaula
force-pushed
the
feature/sling-node
branch
from
July 21, 2026 13:55
e7b0efd to
d8cc329
Compare
GCdePaula
marked this pull request as ready for review
July 23, 2026 14:19
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.
What this is
A ground-up rewrite of the rollups node, landed as five reviewable commits on top of
next/3.0. The headline: the node becomes a single crate where one spec-oracled engine serves both the machine runner's forward schedule and the dispute path's random access — previously two hand-maintained implementations of the same consensus-critical leaf semantics, kept in agreement only by e2e luck. It also ports the node to the staged settlement protocol (stage / sentry claim / accept) that landed on this base branch.feat(node)!— the node: one crate, one engine, the boundary store, the staged settlement port. Absorbsprt/client-rsandcommon-rs(deleted; the node was their only consumer).test(e2e)— the Lua harness: 23 scenarios (kill/respawn points, concurrent multi-sybil matches, on-chain timeout deletion), a parallel battery runner, hardened primitives. The Lua client stays an independent commitment oracle.build×2 — thejustgate (just check,just doctor), devnet fingerprinting, CI triggers + emulator build caching, andjust logged(true-exit-code runner).docs— the knowledge base (docs/) and the campaign ledger (docs/plans/): design decisions with reasons, incident reports, and an internal audit ledger.Where review attention pays most
In order of consensus-criticality:
src/engine/— the meta-cycle geometry and leaf conventions (ustep spans, checkpoints, idle churn, revert). This is THE trust core. Readdocs/computation-hash.mdfirst; the conventions are pinned by 15 spec tests against a brute-force oracle, and the revert semantics were verified againstAdvanceStatus.soldirectly (the previous node and the Lua oracle shared a wrong assumption for months — contracts are the only source of truth).src/epoch_manager/— the staged settlement port: three guarded steps per tick; sentries claim the locally computed post-epoch hash, never the staged value. The winner asserts are deliberate panics ("notify all users").src/storage/— the trust boundaries in the schema itself: four mutation classes enforced by SQL triggers, write-once collision tripwires that panic (never retry), the frontier's strict prefix-bounding, and the boundary store's stage+rename crash discipline (docs/plans/snapshots.md).src/tournament/— reader/sender/witness encodings vs the contracts.docs/plans/node-audit.mdrecords an internal adversarial audit: 10 findings with dispositions and 56 explicit clean checks (every sender argument order and witness byte layout traced against contract consumption order).The e2e harness (
prt/tests/rollups/) deserves a pass on its trust story: the oracle is self-anchored (own machine lineage, chain inputs only) and judges the node strictly from outside.How it's verified
just check(fmt, luacheck, clippy-D warnings, unit + integration tests) green; the full 23-scenario battery green multiple times, including after the rebase onto this base (perf at parity with pre-rebase baselines). Layered nets: the spec oracle on enumerable structures, golden fixtures, committed chain recordings decoded through production bindings, and the independent Lua commitment oracle on every e2e epoch. Consensus-critical migrations were characterization-first: the old implementation's outputs were pinned as fixtures before each switch, and the differentials retired with their subjects.Breaking / operational notes
prt/client-rsandcommon-rsare gone (absorbed).pull_requestplus pushes tomain/next/*/tags — feature branches get CI through PRs (forks finally get CI at all). First run populates the emulator cache; the speedup shows from the second run.Deliberately not here
The halt/exception contracts rework and its node-side dependents (the runner's halted-input wedge is a deliberate stopgap until that semantics exists on-chain); the settle-revert taxonomy and the rest of audit round 2; the per-scenario CI matrix. All tracked with their reasons in
docs/plans/.