Repository navigation
v0.8.3: prover/verify performance + faucet flag (#151 #152 #153) - #156
Merged
Merged
Conversation
…treams filled in parallel; ProverData is cached per shape The hiding PCS's random columns (commit, quotient chunks, the ZK randomisation polynomial) and the hiding MMCS's Merkle salts were drawn serially from one generator behind a spin lock: ~7.5 s of a 18.2 s tier-14 bundle proof on 16 threads. They are now ChaCha20 counter-mode streams (vendor/p3-merkle-tree/src/counter_rng.rs): per call the configuration's generator hands out one fresh 256-bit secret key (the lock is held for that draw only), and lane (matrix) / chunk (CHUNK_ROWS = 1024 rows) select the ChaCha nonce, so every chunk fills in parallel. Values are sampled exactly as before (StandardUniform's rejection sampling over Goldilocks), uniform and secret under the PRF assumption the previous generators (StdRng = ChaCha12, the keyed Poseidon2 sponge) already rested on. The chunking never depends on the thread count, so a seeded run is reproducible. Who hands out keys (CounterModeRng): OS entropy (SaltRng::Fresh) and a seed-keyed sponge (KeyRngV2::from_seed, a proving config's clone). A label stream (KeyRngV2::from_label, a verifier key's) hands out none and is drawn from serially, bit for bit as before, so no verifier key moves (tests/verifier_key.rs and tests/key_derivation_v2.rs unchanged and passing). The proof format and every verifier function are untouched: old verifiers accept new proofs (tests/counter_rng.rs::a_new_proof_passes_the_unchanged_v080_verifier_path). ProverData (the preprocessed commitment and its Merkle tree, 1.4 s at tier 14) is a pure function of (profile, tier, table heights): key_config salts it from the public label streams and the preprocessed columns depend on no program. prove_traces takes it from a process-wide LRU (machine::cached_prover_data, 4 shapes, tiers <= 16, single-flight), shared by every Machine the wallet and rand-prover build. tests/prover_data_cache.rs: one build for two proofs, both verify on a machine that recomputes the verifier key. deploy/sync-zkvm.sh keeps the two new test files and refuses a re-vendor from a circuits commit without these changes (to be ported to zkp-circuits). Fixes #151 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GFs5h141Ct6RTGGrCTQ1vy
… rand_mint refuses a non-minter key up front `faucet` echoed the genesis flag, so a validator bonded after genesis (chain 21's guardian hosts g1-g6) advertised a faucet, accepted rand_mint on its operator RPC, built and pooled the mint, and only then failed with MinterNotAllowed. admission::faucet_refusal is now the one predicate: the faucet on, a validator, and a key in faucet_minters (staking.faucet_minters where the genesis lists them, else the genesis validators). NodeStatus.faucet is `faucet_refusal(..).is_none()`, and Node::mint returns its reason before building anything; the non-minter's names the minter set. Tests: admission::the_faucet_is_served_only_by_a_validator_whose_key_is_a_faucet_minter (both minter sources, every refusal), node::a_validator_outside_the_faucet_minters_refuses_rand_mint_up_front (nothing pooled). docs/rpc.md: rand_mint, the field, and a v0.8.3 changelog entry. Fixes #153 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GFs5h141Ct6RTGGrCTQ1vy
…x body is decoded with faster-hex; verify numbers refreshed One admission asked the executor for the same 1.4-1.5 MB proofs four times (the canonical-proof rule, check_auth_fields' header, the digest and gas reads, the verify), and every ask decoded and re-encoded them. executor::decode_canonical_shared memoises decode_canonical on the exact bytes (16 entries, a hit compares them in full, refusals are not kept); non_canonical_proof, auth_header_of, the pinned digest, bundle_gas_limit, both verifies and the call-policy reads go through it, and check_decoded / check_msauth_decoded check by reference. The ledger and the ConfidentialExecutor trait are unchanged: the ledger keeps handing every check the bytes, in the same order, and the decodes meet where they are answered, so no verdict can move. tests/decode_memo.rs: five reads of an auth proof, one decode, the same verdicts; a padded or one-byte-flipped proof is never a hit. rand_sendTransaction decodes its body with faster-hex 0.10.1 (MIT; cargo deny: bans, licenses, sources ok) through rpc::decode_hex_body, with hex::decode's verdicts (rpc::tests::the_hex_body_decodes_as_hex_does). Measured (Apple M4 Max, 16 threads, 38 captured chain-21 transactions x 30 warm reps, two idle-gated passes): warm verify p50 72.2 -> 62.2 ms, body decode 18.1 -> 1.2 ms, cold 1.59 -> 1.56 s; one admission ~90 -> ~63 ms. docs/block-space.md, docs/node-hardware.md 2.1 and docs/compute-optimization.md 1.1 carried the tier-12 research proof's 16 ms / 838 ms; they now carry the chain-21 numbers before (73 ms / 1.6 s, the issue's) and after, and the per-block line. Fixes #152 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GFs5h141Ct6RTGGrCTQ1vy
…rrowing it (clippy needless_borrow) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GFs5h141Ct6RTGGrCTQ1vy
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
dendisuhubdy
added a commit
that referenced
this pull request
Oct 28, 2026
… the verify queue; ack only after hand-off (#157, PR #158) CHANGELOG: the #157 entry joins the v0.8.3 "Node" list. rpc.rs merged without a textual conflict: #156's faster-hex decode of the rand_sendTransaction body and #158's reply handling below it are both kept. The stem path from #155 is brought under the admission budget in the next commit. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GFs5h141Ct6RTGGrCTQ1vy
dendisuhubdy
added a commit
that referenced
this pull request
Oct 28, 2026
- CHANGELOG.md, Unreleased v0.8.3, "Node": #156 (issues #151 #152 #153) carried no entry; its three items are added from the PR's own measurements. - docs/rpc.md changelog, "newest first": the #147 wallet entry moves up beside the other v0.8.3 entries (#154 had put it under v0.8.2), and a v0.8.3 entry records the client-visible parts of #145 and #157 — the stem's `unknown` status, the meaning of the returned hash, `-32005`, and `rand_status.admission_bytes` / `admission_budget_bytes`. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GFs5h141Ct6RTGGrCTQ1vy
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.
Three v0.8.3 fixes from the 2026-10-28 chain-21 network experiment, one commit each.
#151: prover RNG runs in parallel, ProverData is cached
Random columns and Merkle salts in parallel. The hiding PCS's random columns (commit, quotient chunks, ZK randomisation polynomial) and the hiding MMCS's Merkle salts are now ChaCha20 counter-mode streams (
vendor/p3-merkle-tree/src/counter_rng.rs):(lane = matrix, chunk = 1024 rows)selects the ChaCha nonce, so all chunks fill in parallel.StandardUniformrejection sampling over Goldilocks.StdRngis ChaCha12;KeyRngV2::from_seedis a keyed Poseidon2 sponge).Which generators get the parallel path. OS entropy (
SaltRng::Fresh) and seed-keyed sponges (proving-config clones) do. Verifier-key label streams (KeyRngV2::from_label) do not: they keep the serial draw bit for bit, so no verifier key moves.tests/verifier_key.rsandtests/key_derivation_v2.rsare unchanged and pass.Wire format and verifier unchanged. No verifier function is touched.
tests/counter_rng.rs::a_new_proof_passes_the_unchanged_v080_verifier_pathchecks that a new proof passes the admission path v0.8.0 nodes run (non_canonical_proof,auth_header,verify_auth) and that it round-trips canonically.ProverData cache.
ProverDatais a pure function of(profile, tier, table heights):key_configsalts the preprocessed commit from the public label streams.So
prove_tracestakes it from a process-wide LRU (machine::cached_prover_data), shared by everyMachinethe wallet andrand-provercreate:tests/prover_data_cache.rschecks that two proofs cost one build, and that both verify on a machine that rebuilds the verifier key. That second check proves the cached commitment is the verifier key's.Tier-14 bundle proof timing. Production profile, Apple M4 Max, 16 threads,
hidden_bundle.rsmixed()case, two passes each:Auth proof, tier 10: 1 446 ms → 922 ms.
What is left is mostly Poseidon2 Merkle hashing (parallel) and quotient evaluation.
#152: one decode per admission, faster hex, docs refreshed
One decode per proof per admission.
executor::decode_canonical_sharedmemoises the canonical decode on the exact bytes: 16 entries, a hit compares the bytes in full, refusals are not kept. These paths all go through it:non_canonical_proofauth_header_ofbundle_gas_limitThe ledger and the
ConfidentialExecutortrait are unchanged. The ledger still hands each check the bytes in the same order; the decodes meet inside the executor, so no verdict can change.tests/decode_memo.rsshows five reads cost one decode with identical verdicts.Faster hex.
rand_sendTransactiondecodes its body withfaster-hex0.10.1 (MIT;cargo deny check licenses sources bans: ok).rpc::tests::the_hex_body_decodes_as_hex_doeschecks the result matcheshex::decodefor both cases, mixed case,0x, odd lengths and bad characters at lane boundaries.Docs.
docs/block-space.md,docs/node-hardware.md§2.1 anddocs/compute-optimization.md§1.1 had the tier-12 research proof's 16 ms / 838 ms. They now give the issue's chain-21 numbers (73 ms warm, 1.6 s cold, n = 38, M4 Max), the v0.8.3 numbers, and the per-block line.Admission verify timing. 38 captured chain-21 transactions × 30 warm reps, the node's executor without its verdict cache. The "after" bench clears the decode memo before each rep, so every rep is a fresh admission. Two passes each:
non_canonical+auth_header+ digest + gas)#153:
faucetmeans this node can mintadmission::faucet_refusalis now the single test for whether this node can mint. All three must hold:faucet_minters.rand_status.faucetandrand_getEmission.faucetreport exactly that.rand_mintchecks it before building anything, and a non-minter's error names the minter set.docs/rpc.mddocuments the change and has a v0.8.3 changelog entry. Tests:admission::tests::the_faucet_is_served_only_by_a_validator_whose_key_is_a_faucet_minternode::tests::a_validator_outside_the_faucet_minters_refuses_rand_mint_up_frontTests
counter_rng7prover_data_cache1decode_memo1verifier_key2key_derivation_v26key_cache2zk3privacy_floor4e2e25 (+6 ignored)executor24 (+1 ignored)auth_cheating3logup_blind2proof_binding11cargo check --features mock-cuda --testscompiles.msauth_key::tests::an_exe_in_the_tree_target_falls_back_only_when_opted_in, which asserts that the test binary sits under the source tree'starget/. It was built with a sharedCARGO_TARGET_DIRoutside the tree, and the test's file is untouched here. The faucet, status, emission and hex tests are among the 772.-D warnings:randprotocol-node --all-targets: clean.p3-fri,p3-merkle-tree(lib): clean.randprotocol-zkvm: not in the CI lint set and carries pre-existing findings; none are on lines this PR adds.cargo deny check licenses sources bans: ok.cargo check --locked: ok. The lockfile diff is onlyfaster-hex,heapless 0.8andp3-fri → p3-merkle-tree.Measurement conditions
rand --rpc http://127.0.0.1:18690process (the chain-21 experiment) existed.examples/verify_latency.rs, theprover_phase_breakdowntest) is frombench/verify-latencyand is not in this PR.Follow-ups
zkp-circuitsresearch/and itsvendor/p3-*.deploy/sync-zkvm.shnow refuses a re-vendor from a circuits commit that lacks it, and keeps the three new test files.rand-zkvm-cuda's ownHidingMmcsstill draws salts serially. The PCS random columns on that backend are parallel now.Closes #151
Closes #152
Closes #153
🤖 Generated with Claude Code
https://claude.ai/code/session_01GFs5h141Ct6RTGGrCTQ1vy