fix(json_logic): sigma DoS hardening + canonical node encoding#52
Merged
scasplte2 merged 1 commit intoJun 17, 2026
Merged
Conversation
Production-hardening remediation from the 2026-06-17 Fiat-Shamir audit. The FS/CDS soundness verdict was clean — no soundness change here; these close the separately-reported DoS / encoding findings so the opcode can be called production DoS-hardened. IMPL-1 (proposition DoS): bound the proposition's raw node-count/depth with the absolute caps (4096 nodes / 64 depth) BEFORE the recursive parsePropNode, and depth-cap the gas estimator's proposition-shape walk by the same value, so a deeply nested / very wide proposition cannot drive unbounded stack/CPU work in the parser or in the pre-charge (which runs before gas is consumed). Generalize boundProofShape -> boundRawShape (bounds both proposition and proof). IMPL-2/5 (canonical encoding): reject any field outside the canonical schema in every proposition/proof node. Removes the proof-bound-inflation surface (a leaf could carry an ignored children field) and makes the raw encoding canonical. IMPL-3 (message DoS): cap the sigma message at 4096 bytes (shared by sigma_verify and prove_dhtuple_verify) so it can't force unbounded hex-decode + SHA-256 work outside the Sigma-tree pricing. DOC-1: vector metadata root challenge mod R -> low31(SHA256(...)). DOC-2: RFC vector references -> the sigma categories of zk_opcode_test_vectors.json. DOC-3: RFC proof tree carries per-leaf responses (commitments are reconstructed). DOC-4: RFC status lists the TypeScript impl; verifyTree comment mod R -> low31; threshold share-index test prose corrected (indices are implicit child positions). Tests: 4 new shared conformance error-vectors (unknown-field x2, leaf-children, over-long message) locked cross-language; 6 new SigmaVerifySuite hardening cases; full suite 1210 green. The proposition depth cap is unit-tested per language (it cannot be a shared vector — exceeding sigma depth 64 implies ~128 JSON levels, beyond serde_json's parse recursion limit). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
scasplte2
added a commit
that referenced
this pull request
Jun 17, 2026
The shielded capstone pinned the OLD proof, which proved the UNSOUND circuit (no intra-transfer nullifier uniqueness, cross-asset mint possible) and would have stayed green while attesting the wrong circuit. Re-vendored from the regenerated metakit-sdk fixture after the soundness fixes: - vkey 0x0080c764... -> 0x0006feea6b6b974ef1d5287464c7d8b5c38816267c064a33db664dc97147e0ff - publicValues now carry feeAsset (per-asset conservation) ShieldedTransferVerifierSuite: 3/3 green (verifies in pure-JVM Sp1Groth16Verifier; tamper + wrong-publicValues still rejected). Companion to metakit-sdk PR #52. Co-authored-by: OttoBot <jim.a.aman@gmail.com> Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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.
Summary
Production-hardening remediation from the 2026-06-17 Fiat-Shamir audit of the Σ-protocol opcodes (
prove_dlog_verify/prove_dhtuple_verify/sigma_verify).The audit's Fiat-Shamir / CDS soundness verdict was clean — strong transcript binding, 31-byte injective challenge, canonical
z, reconstructed commitments, identity-point rejection, explicit CDS split checks. No soundness change in this PR. These changes close the separately-reported production-hardening + documentation findings so the opcode can be called production DoS-hardened.Findings addressed
parsePropNode; depth-cap the gas estimator's proposition-shape walk by the same value (it runs before gas is consumed).boundProofShape→boundRawShape(bounds prop + proof).children) and makes the raw encoding canonical.SigmaMaxMessageBytes, shared bysigma_verify+prove_dhtuple_verify).mod R→low31(SHA256(…)).zk_opcode_test_vectors.json.verifyTreecommentmod R→ low31; threshold share-index test prose corrected (indices are implicit child positions).Tests
children, over-long message) — locked cross-language (Scala + Rust + TS).SigmaVerifySuitecases pairing a clean baseline (parses →Right) with the malformed variant (→Left).scalafmtCheckAllclean.serde_json's parse recursion limit; both languages still reject, just at different layers).Sister PR: metakit-sdk (Rust + TypeScript mirror + shared vectors).
🤖 Generated with Claude Code