From dec23d373c3a3fe6b803909071d405a44b1644f0 Mon Sep 17 00:00:00 2001 From: Roman Date: Wed, 5 Aug 2026 09:45:21 +0200 Subject: [PATCH] chore: sync with LEZ main (bundled public/private actions) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Upstream LEZ merged the parallel Message vectors into action structs (f16c3bd1e, 75326d031, e13b4cb23): * `Message` now carries `public_actions: Vec` (account id paired with its post-state) and `private_actions: Vec` (nullifier + root + commitment + encrypted post state bundled per action) instead of six parallel vectors. * `PrivacyPreservingCircuitOutput` mirrors the same bundling (`public_actions: Vec` with pre/post halves). * `Message::try_from_circuit_output(ids, nonces, output)` became the infallible `Message::from_circuit_output(nonces, output)`. * `EncryptionScheme::encrypt` keys the note on the nullifier and dropped the output-index argument. * `V03State::default()` seeds the commitment set with the protocol's dummy commitment, so `root_history` contains the live root from genesis — a nullifier bound to the live root is valid on the first transaction (previously the history started empty). Harness changes: * `synthesize_passing_proof` reconstructs the journal from bundled `PublicAction`s, mirroring the validator byte-for-byte. * `arb_privacy_preserving_tx` generates 1..=3 deduplicated `PrivateAction`s (the length-mismatch and empty-commitments shapes are unrepresentable under the paired layout and were dropped) and pairs every public account id with its post-state. * `arb_conflicting_nullifier_pair` builds the shared-nullifier pair as two private actions with distinct commitments. * Encoding/witness targets build messages via the action structs; the circuit-output-mapping invariant asserts the pre-id/post pairing. * Generator-contract and proof-synthesis tests updated accordingly (48/48 pass, with and without RISC0_DEV_MODE). Bump the pinned LEZ SHA to d6e4ae69 and refresh both lockfiles. Fixes the scheduled lez-compat failure (run 30977103292). --- .github/actions/checkout-lez/action.yml | 2 +- Cargo.lock | 274 ++++++++++++------ fuzz/Cargo.lock | 274 ++++++++++++------ .../fuzz_encoding_privacy_preserving.rs | 84 +++--- ...uzz_privacy_preserving_state_transition.rs | 19 +- .../fuzz_privacy_preserving_witness.rs | 20 +- fuzz_props/src/privacy.rs | 238 +++++++-------- fuzz_props/src/tests/privacy.rs | 158 +++++----- 8 files changed, 637 insertions(+), 432 deletions(-) diff --git a/.github/actions/checkout-lez/action.yml b/.github/actions/checkout-lez/action.yml index e4da370f3..69ce1e817 100644 --- a/.github/actions/checkout-lez/action.yml +++ b/.github/actions/checkout-lez/action.yml @@ -14,7 +14,7 @@ inputs: `just update-lez`, replace this SHA, and open a PR. The scheduled lez-compat workflow overrides this with `main` to detect upstream drift. required: false - default: d1637b65e2479e80bb617b900ec5d4024216457d + default: d6e4ae694e7419f5906b340c232704466a1917b7 runs: using: composite diff --git a/Cargo.lock b/Cargo.lock index 0ff50d779..146834c82 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -371,7 +371,7 @@ dependencies = [ "asn1-rs-derive", "asn1-rs-impl", "displaydoc", - "nom 7.1.3", + "nom", "num-traits", "rusticata-macros", "thiserror 2.0.18", @@ -801,6 +801,7 @@ name = "bridge_core" version = "0.1.0" dependencies = [ "lee_core", + "risc0-zkvm", "serde", ] @@ -1395,7 +1396,7 @@ checksum = "07da5016415d5a3c4dd39b11ed26f915f52fc4e0dc197d87908bc916e51bc1a6" dependencies = [ "asn1-rs", "displaydoc", - "nom 7.1.3", + "nom", "num-bigint 0.4.6", "num-traits", "rusticata-macros", @@ -3590,10 +3591,20 @@ version = "0.4.29" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" +[[package]] +name = "logos-blockchain-blake2btree" +version = "0.0.0" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=0dc34e2c5a6e2ff772140378659489a602ee06bc#0dc34e2c5a6e2ff772140378659489a602ee06bc" +dependencies = [ + "blake2", + "logos-blockchain-dynamic-merkle", + "logos-blockchain-merkle-tree", +] + [[package]] name = "logos-blockchain-blend-crypto" -version = "0.1.2" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=d8711bbc3d43d3ef9755ef9b73af32fd0f703160#d8711bbc3d43d3ef9755ef9b73af32fd0f703160" +version = "0.0.0" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=0dc34e2c5a6e2ff772140378659489a602ee06bc#0dc34e2c5a6e2ff772140378659489a602ee06bc" dependencies = [ "blake2", "logos-blockchain-groth16", @@ -3606,8 +3617,8 @@ dependencies = [ [[package]] name = "logos-blockchain-blend-message" -version = "0.1.2" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=d8711bbc3d43d3ef9755ef9b73af32fd0f703160#d8711bbc3d43d3ef9755ef9b73af32fd0f703160" +version = "0.0.0" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=0dc34e2c5a6e2ff772140378659489a602ee06bc#0dc34e2c5a6e2ff772140378659489a602ee06bc" dependencies = [ "blake2", "derivative", @@ -3615,6 +3626,7 @@ dependencies = [ "itertools 0.14.0", "logos-blockchain-blend-crypto", "logos-blockchain-blend-proofs", + "logos-blockchain-codec", "logos-blockchain-core", "logos-blockchain-cryptarchia-engine", "logos-blockchain-groth16", @@ -3630,13 +3642,14 @@ dependencies = [ [[package]] name = "logos-blockchain-blend-proofs" -version = "0.1.2" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=d8711bbc3d43d3ef9755ef9b73af32fd0f703160#d8711bbc3d43d3ef9755ef9b73af32fd0f703160" +version = "0.0.0" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=0dc34e2c5a6e2ff772140378659489a602ee06bc#0dc34e2c5a6e2ff772140378659489a602ee06bc" dependencies = [ "ed25519-dalek", "generic-array 1.3.5", "hex", "logos-blockchain-blend-crypto", + "logos-blockchain-codec", "logos-blockchain-groth16", "logos-blockchain-pol", "logos-blockchain-poq", @@ -3650,8 +3663,8 @@ dependencies = [ [[package]] name = "logos-blockchain-chain-broadcast-service" -version = "0.1.2" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=d8711bbc3d43d3ef9755ef9b73af32fd0f703160#d8711bbc3d43d3ef9755ef9b73af32fd0f703160" +version = "0.0.0" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=0dc34e2c5a6e2ff772140378659489a602ee06bc#0dc34e2c5a6e2ff772140378659489a602ee06bc" dependencies = [ "async-trait", "derivative", @@ -3664,8 +3677,8 @@ dependencies = [ [[package]] name = "logos-blockchain-chain-service" -version = "0.1.2" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=d8711bbc3d43d3ef9755ef9b73af32fd0f703160#d8711bbc3d43d3ef9755ef9b73af32fd0f703160" +version = "0.0.0" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=0dc34e2c5a6e2ff772140378659489a602ee06bc#0dc34e2c5a6e2ff772140378659489a602ee06bc" dependencies = [ "async-trait", "bytes", @@ -3745,8 +3758,8 @@ dependencies = [ [[package]] name = "logos-blockchain-circuits-prover" -version = "0.1.2" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=d8711bbc3d43d3ef9755ef9b73af32fd0f703160#d8711bbc3d43d3ef9755ef9b73af32fd0f703160" +version = "0.0.0" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=0dc34e2c5a6e2ff772140378659489a602ee06bc#0dc34e2c5a6e2ff772140378659489a602ee06bc" dependencies = [ "rust-rapidsnark", ] @@ -3770,10 +3783,33 @@ dependencies = [ "libc", ] +[[package]] +name = "logos-blockchain-codec" +version = "0.0.0" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=0dc34e2c5a6e2ff772140378659489a602ee06bc#0dc34e2c5a6e2ff772140378659489a602ee06bc" +dependencies = [ + "hex", + "logos-blockchain-codec-macros", + "logos-blockchain-groth16", + "logos-blockchain-utils", + "thiserror 2.0.18", +] + +[[package]] +name = "logos-blockchain-codec-macros" +version = "0.0.0" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=0dc34e2c5a6e2ff772140378659489a602ee06bc#0dc34e2c5a6e2ff772140378659489a602ee06bc" +dependencies = [ + "hex", + "proc-macro2", + "quote", + "syn 2.0.117", +] + [[package]] name = "logos-blockchain-common-http-client" -version = "0.1.2" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=d8711bbc3d43d3ef9755ef9b73af32fd0f703160#d8711bbc3d43d3ef9755ef9b73af32fd0f703160" +version = "0.0.0" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=0dc34e2c5a6e2ff772140378659489a602ee06bc#0dc34e2c5a6e2ff772140378659489a602ee06bc" dependencies = [ "futures", "hex", @@ -3795,17 +3831,18 @@ dependencies = [ [[package]] name = "logos-blockchain-core" -version = "0.1.2" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=d8711bbc3d43d3ef9755ef9b73af32fd0f703160#d8711bbc3d43d3ef9755ef9b73af32fd0f703160" +version = "0.0.0" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=0dc34e2c5a6e2ff772140378659489a602ee06bc#0dc34e2c5a6e2ff772140378659489a602ee06bc" dependencies = [ "ark-ff", "bincode", "blake2", "bytes", "const-hex", - "futures", "hex", + "logos-blockchain-blake2btree", "logos-blockchain-blend-proofs", + "logos-blockchain-codec", "logos-blockchain-cryptarchia-engine", "logos-blockchain-groth16", "logos-blockchain-key-management-system-keys", @@ -3817,9 +3854,7 @@ dependencies = [ "logos-blockchain-utils", "logos-blockchain-utxotree", "multiaddr", - "nom 8.0.0", "num-bigint 0.4.6", - "rpds", "serde", "strum", "thiserror 2.0.18", @@ -3829,11 +3864,13 @@ dependencies = [ [[package]] name = "logos-blockchain-cryptarchia-engine" -version = "0.1.2" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=d8711bbc3d43d3ef9755ef9b73af32fd0f703160#d8711bbc3d43d3ef9755ef9b73af32fd0f703160" +version = "0.0.0" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=0dc34e2c5a6e2ff772140378659489a602ee06bc#0dc34e2c5a6e2ff772140378659489a602ee06bc" dependencies = [ + "logos-blockchain-codec", "logos-blockchain-pol", "logos-blockchain-utils", + "rpds", "serde", "serde_with", "thiserror 2.0.18", @@ -3844,8 +3881,8 @@ dependencies = [ [[package]] name = "logos-blockchain-cryptarchia-sync" -version = "0.1.2" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=d8711bbc3d43d3ef9755ef9b73af32fd0f703160#d8711bbc3d43d3ef9755ef9b73af32fd0f703160" +version = "0.0.0" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=0dc34e2c5a6e2ff772140378659489a602ee06bc#0dc34e2c5a6e2ff772140378659489a602ee06bc" dependencies = [ "bytes", "futures", @@ -3861,10 +3898,19 @@ dependencies = [ "tracing", ] +[[package]] +name = "logos-blockchain-dynamic-merkle" +version = "0.0.0" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=0dc34e2c5a6e2ff772140378659489a602ee06bc#0dc34e2c5a6e2ff772140378659489a602ee06bc" +dependencies = [ + "rpds", + "serde", +] + [[package]] name = "logos-blockchain-groth16" -version = "0.1.2" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=d8711bbc3d43d3ef9755ef9b73af32fd0f703160#d8711bbc3d43d3ef9755ef9b73af32fd0f703160" +version = "0.0.0" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=0dc34e2c5a6e2ff772140378659489a602ee06bc#0dc34e2c5a6e2ff772140378659489a602ee06bc" dependencies = [ "ark-bn254", "ark-ec", @@ -3874,6 +3920,7 @@ dependencies = [ "generic-array 1.3.5", "hex", "num-bigint 0.4.6", + "rand 0.8.5", "serde", "serde_json", "thiserror 2.0.18", @@ -3881,8 +3928,8 @@ dependencies = [ [[package]] name = "logos-blockchain-http-api-common" -version = "0.1.2" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=d8711bbc3d43d3ef9755ef9b73af32fd0f703160#d8711bbc3d43d3ef9755ef9b73af32fd0f703160" +version = "0.0.0" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=0dc34e2c5a6e2ff772140378659489a602ee06bc#0dc34e2c5a6e2ff772140378659489a602ee06bc" dependencies = [ "axum", "logos-blockchain-core", @@ -3902,14 +3949,15 @@ dependencies = [ [[package]] name = "logos-blockchain-key-management-system-keys" -version = "0.1.2" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=d8711bbc3d43d3ef9755ef9b73af32fd0f703160#d8711bbc3d43d3ef9755ef9b73af32fd0f703160" +version = "0.0.0" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=0dc34e2c5a6e2ff772140378659489a602ee06bc#0dc34e2c5a6e2ff772140378659489a602ee06bc" dependencies = [ "async-trait", "bytes", "ed25519-dalek", "generic-array 1.3.5", "hex", + "logos-blockchain-codec", "logos-blockchain-groth16", "logos-blockchain-key-management-system-macros", "logos-blockchain-log-targets", @@ -3929,8 +3977,8 @@ dependencies = [ [[package]] name = "logos-blockchain-key-management-system-macros" -version = "0.1.2" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=d8711bbc3d43d3ef9755ef9b73af32fd0f703160#d8711bbc3d43d3ef9755ef9b73af32fd0f703160" +version = "0.0.0" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=0dc34e2c5a6e2ff772140378659489a602ee06bc#0dc34e2c5a6e2ff772140378659489a602ee06bc" dependencies = [ "proc-macro2", "quote", @@ -3939,8 +3987,8 @@ dependencies = [ [[package]] name = "logos-blockchain-ledger" -version = "0.1.2" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=d8711bbc3d43d3ef9755ef9b73af32fd0f703160#d8711bbc3d43d3ef9755ef9b73af32fd0f703160" +version = "0.0.0" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=0dc34e2c5a6e2ff772140378659489a602ee06bc#0dc34e2c5a6e2ff772140378659489a602ee06bc" dependencies = [ "derivative", "logos-blockchain-blend-crypto", @@ -3965,8 +4013,8 @@ dependencies = [ [[package]] name = "logos-blockchain-libp2p" -version = "0.1.2" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=d8711bbc3d43d3ef9755ef9b73af32fd0f703160#d8711bbc3d43d3ef9755ef9b73af32fd0f703160" +version = "0.0.0" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=0dc34e2c5a6e2ff772140378659489a602ee06bc#0dc34e2c5a6e2ff772140378659489a602ee06bc" dependencies = [ "async-trait", "backon", @@ -3994,30 +4042,42 @@ dependencies = [ [[package]] name = "logos-blockchain-log-targets" -version = "0.1.2" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=d8711bbc3d43d3ef9755ef9b73af32fd0f703160#d8711bbc3d43d3ef9755ef9b73af32fd0f703160" +version = "0.0.0" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=0dc34e2c5a6e2ff772140378659489a602ee06bc#0dc34e2c5a6e2ff772140378659489a602ee06bc" dependencies = [ "logos-blockchain-log-targets-macros", ] [[package]] name = "logos-blockchain-log-targets-macros" -version = "0.1.2" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=d8711bbc3d43d3ef9755ef9b73af32fd0f703160#d8711bbc3d43d3ef9755ef9b73af32fd0f703160" +version = "0.0.0" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=0dc34e2c5a6e2ff772140378659489a602ee06bc#0dc34e2c5a6e2ff772140378659489a602ee06bc" dependencies = [ "proc-macro2", "quote", "syn 2.0.117", ] +[[package]] +name = "logos-blockchain-merkle-tree" +version = "0.0.0" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=0dc34e2c5a6e2ff772140378659489a602ee06bc#0dc34e2c5a6e2ff772140378659489a602ee06bc" +dependencies = [ + "logos-blockchain-dynamic-merkle", + "rpds", + "serde", + "thiserror 2.0.18", +] + [[package]] name = "logos-blockchain-mmr" -version = "0.1.2" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=d8711bbc3d43d3ef9755ef9b73af32fd0f703160#d8711bbc3d43d3ef9755ef9b73af32fd0f703160" +version = "0.0.0" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=0dc34e2c5a6e2ff772140378659489a602ee06bc#0dc34e2c5a6e2ff772140378659489a602ee06bc" dependencies = [ "ark-ff", "logos-blockchain-groth16", "logos-blockchain-poseidon2", + "logos-blockchain-utils", "rpds", "serde", "thiserror 2.0.18", @@ -4025,8 +4085,8 @@ dependencies = [ [[package]] name = "logos-blockchain-network-service" -version = "0.1.2" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=d8711bbc3d43d3ef9755ef9b73af32fd0f703160#d8711bbc3d43d3ef9755ef9b73af32fd0f703160" +version = "0.0.0" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=0dc34e2c5a6e2ff772140378659489a602ee06bc#0dc34e2c5a6e2ff772140378659489a602ee06bc" dependencies = [ "async-trait", "futures", @@ -4035,6 +4095,7 @@ dependencies = [ "logos-blockchain-libp2p", "logos-blockchain-log-targets", "logos-blockchain-tracing", + "logos-blockchain-utils", "overwatch", "rand 0.8.5", "rand_chacha 0.3.1", @@ -4046,8 +4107,8 @@ dependencies = [ [[package]] name = "logos-blockchain-poc" -version = "0.1.2" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=d8711bbc3d43d3ef9755ef9b73af32fd0f703160#d8711bbc3d43d3ef9755ef9b73af32fd0f703160" +version = "0.0.0" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=0dc34e2c5a6e2ff772140378659489a602ee06bc#0dc34e2c5a6e2ff772140378659489a602ee06bc" dependencies = [ "logos-blockchain-circuits-poc-sys", "logos-blockchain-circuits-prover", @@ -4063,8 +4124,8 @@ dependencies = [ [[package]] name = "logos-blockchain-pol" -version = "0.1.2" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=d8711bbc3d43d3ef9755ef9b73af32fd0f703160#d8711bbc3d43d3ef9755ef9b73af32fd0f703160" +version = "0.0.0" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=0dc34e2c5a6e2ff772140378659489a602ee06bc#0dc34e2c5a6e2ff772140378659489a602ee06bc" dependencies = [ "astro-float", "logos-blockchain-circuits-pol-sys", @@ -4083,8 +4144,8 @@ dependencies = [ [[package]] name = "logos-blockchain-poq" -version = "0.1.2" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=d8711bbc3d43d3ef9755ef9b73af32fd0f703160#d8711bbc3d43d3ef9755ef9b73af32fd0f703160" +version = "0.0.0" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=0dc34e2c5a6e2ff772140378659489a602ee06bc#0dc34e2c5a6e2ff772140378659489a602ee06bc" dependencies = [ "logos-blockchain-circuits-poq-sys", "logos-blockchain-circuits-prover", @@ -4102,8 +4163,8 @@ dependencies = [ [[package]] name = "logos-blockchain-poseidon2" -version = "0.1.2" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=d8711bbc3d43d3ef9755ef9b73af32fd0f703160#d8711bbc3d43d3ef9755ef9b73af32fd0f703160" +version = "0.0.0" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=0dc34e2c5a6e2ff772140378659489a602ee06bc#0dc34e2c5a6e2ff772140378659489a602ee06bc" dependencies = [ "ark-bn254", "ark-ff", @@ -4113,8 +4174,8 @@ dependencies = [ [[package]] name = "logos-blockchain-proofs-error" -version = "0.1.2" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=d8711bbc3d43d3ef9755ef9b73af32fd0f703160#d8711bbc3d43d3ef9755ef9b73af32fd0f703160" +version = "0.0.0" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=0dc34e2c5a6e2ff772140378659489a602ee06bc#0dc34e2c5a6e2ff772140378659489a602ee06bc" dependencies = [ "logos-blockchain-circuits-types", "logos-blockchain-groth16", @@ -4124,24 +4185,24 @@ dependencies = [ [[package]] name = "logos-blockchain-services-utils" -version = "0.1.2" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=d8711bbc3d43d3ef9755ef9b73af32fd0f703160#d8711bbc3d43d3ef9755ef9b73af32fd0f703160" +version = "0.0.0" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=0dc34e2c5a6e2ff772140378659489a602ee06bc#0dc34e2c5a6e2ff772140378659489a602ee06bc" dependencies = [ "async-trait", + "bytes", "futures", "log", "logos-blockchain-log-targets", "overwatch", "serde", - "serde_json", "thiserror 2.0.18", "tracing", ] [[package]] name = "logos-blockchain-storage-service" -version = "0.1.2" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=d8711bbc3d43d3ef9755ef9b73af32fd0f703160#d8711bbc3d43d3ef9755ef9b73af32fd0f703160" +version = "0.0.0" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=0dc34e2c5a6e2ff772140378659489a602ee06bc#0dc34e2c5a6e2ff772140378659489a602ee06bc" dependencies = [ "async-trait", "bytes", @@ -4149,7 +4210,9 @@ dependencies = [ "logos-blockchain-core", "logos-blockchain-cryptarchia-engine", "logos-blockchain-log-targets", + "logos-blockchain-services-utils", "logos-blockchain-tracing", + "logos-blockchain-utils", "overwatch", "serde", "thiserror 2.0.18", @@ -4159,8 +4222,8 @@ dependencies = [ [[package]] name = "logos-blockchain-time-service" -version = "0.1.2" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=d8711bbc3d43d3ef9755ef9b73af32fd0f703160#d8711bbc3d43d3ef9755ef9b73af32fd0f703160" +version = "0.0.0" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=0dc34e2c5a6e2ff772140378659489a602ee06bc#0dc34e2c5a6e2ff772140378659489a602ee06bc" dependencies = [ "async-trait", "futures", @@ -4182,8 +4245,8 @@ dependencies = [ [[package]] name = "logos-blockchain-tracing" -version = "0.1.2" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=d8711bbc3d43d3ef9755ef9b73af32fd0f703160#d8711bbc3d43d3ef9755ef9b73af32fd0f703160" +version = "0.0.0" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=0dc34e2c5a6e2ff772140378659489a602ee06bc#0dc34e2c5a6e2ff772140378659489a602ee06bc" dependencies = [ "flate2", "logos-blockchain-log-targets", @@ -4208,15 +4271,17 @@ dependencies = [ [[package]] name = "logos-blockchain-utils" -version = "0.1.2" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=d8711bbc3d43d3ef9755ef9b73af32fd0f703160#d8711bbc3d43d3ef9755ef9b73af32fd0f703160" +version = "0.0.0" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=0dc34e2c5a6e2ff772140378659489a602ee06bc#0dc34e2c5a6e2ff772140378659489a602ee06bc" dependencies = [ "async-trait", "blake2", "cipher 0.4.4", "const-hex", + "futures", "humantime", "logos-blockchain-log-targets", + "multiaddr", "overwatch", "rand 0.8.5", "serde", @@ -4225,27 +4290,27 @@ dependencies = [ "serde_yaml", "thiserror 2.0.18", "time", + "tokio", "tracing", ] [[package]] name = "logos-blockchain-utxotree" -version = "0.1.2" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=d8711bbc3d43d3ef9755ef9b73af32fd0f703160#d8711bbc3d43d3ef9755ef9b73af32fd0f703160" +version = "0.0.0" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=0dc34e2c5a6e2ff772140378659489a602ee06bc#0dc34e2c5a6e2ff772140378659489a602ee06bc" dependencies = [ "ark-ff", - "logos-blockchain-groth16", + "logos-blockchain-dynamic-merkle", + "logos-blockchain-merkle-tree", "logos-blockchain-poseidon2", - "num-bigint 0.4.6", "rpds", "serde", - "thiserror 2.0.18", ] [[package]] name = "logos-blockchain-zksign" -version = "0.1.2" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=d8711bbc3d43d3ef9755ef9b73af32fd0f703160#d8711bbc3d43d3ef9755ef9b73af32fd0f703160" +version = "0.0.0" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=0dc34e2c5a6e2ff772140378659489a602ee06bc#0dc34e2c5a6e2ff772140378659489a602ee06bc" dependencies = [ "logos-blockchain-circuits-prover", "logos-blockchain-circuits-signature-sys", @@ -4256,6 +4321,7 @@ dependencies = [ "logos-blockchain-proofs-error", "num-bigint 0.4.6", "serde", + "serde-big-array", "serde_json", "thiserror 2.0.18", "tracing", @@ -4359,6 +4425,29 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ca88d725a0a943b096803bd34e73a4437208b6077654cc4ecb2947a5f91618d" +[[package]] +name = "manyhow" +version = "0.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b33efb3ca6d3b07393750d4030418d594ab1139cee518f0dc88db70fec873587" +dependencies = [ + "manyhow-macros", + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "manyhow-macros" +version = "0.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46fce34d199b78b6e6073abf984c9cf5fd3e9330145a93ee0738a7443e371495" +dependencies = [ + "proc-macro-utils", + "proc-macro2", + "quote", +] + [[package]] name = "match-lookup" version = "0.1.2" @@ -4743,15 +4832,6 @@ dependencies = [ "minimal-lexical", ] -[[package]] -name = "nom" -version = "8.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df9761775871bdef83bee530e60050f7e54b1105350d6884eb0fb4f46c2f9405" -dependencies = [ - "memchr", -] - [[package]] name = "nu-ansi-term" version = "0.50.3" @@ -5026,7 +5106,7 @@ checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" [[package]] name = "overwatch" version = "0.1.0" -source = "git+https://github.com/logos-co/Overwatch?rev=448c192#448c192895b8311c742b1726a1bb12ee314ad95c" +source = "git+https://github.com/logos-co/Overwatch?rev=ae887f41f5a626c341179026ad7f03953ff2072e#ae887f41f5a626c341179026ad7f03953ff2072e" dependencies = [ "async-trait", "futures", @@ -5041,10 +5121,10 @@ dependencies = [ [[package]] name = "overwatch-derive" version = "0.1.0" -source = "git+https://github.com/logos-co/Overwatch?rev=448c192#448c192895b8311c742b1726a1bb12ee314ad95c" +source = "git+https://github.com/logos-co/Overwatch?rev=ae887f41f5a626c341179026ad7f03953ff2072e#ae887f41f5a626c341179026ad7f03953ff2072e" dependencies = [ "convert_case", - "proc-macro-error2", + "manyhow", "proc-macro2", "quote", "syn 2.0.117", @@ -5322,6 +5402,17 @@ dependencies = [ "syn 2.0.117", ] +[[package]] +name = "proc-macro-utils" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eeaf08a13de400bc215877b5bdc088f241b12eb42f0a548d3390dc1c56bb7071" +dependencies = [ + "proc-macro2", + "quote", + "smallvec", +] + [[package]] name = "proc-macro2" version = "1.0.106" @@ -6310,7 +6401,7 @@ version = "4.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "faf0c4a6ece9950b9abdb62b1cfcf2a68b3b67a10ba445b3bb85be2a293d0632" dependencies = [ - "nom 7.1.3", + "nom", ] [[package]] @@ -6499,6 +6590,15 @@ dependencies = [ "serde_derive", ] +[[package]] +name = "serde-big-array" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11fc7cc2c76d73e0f27ee52abbd64eec84d46f370c88371120433196934e4b7f" +dependencies = [ + "serde", +] + [[package]] name = "serde_arrays" version = "0.2.0" @@ -8396,7 +8496,7 @@ dependencies = [ "data-encoding", "der-parser", "lazy_static", - "nom 7.1.3", + "nom", "oid-registry", "rusticata-macros", "thiserror 2.0.18", diff --git a/fuzz/Cargo.lock b/fuzz/Cargo.lock index 4d9382134..6e1adeb40 100644 --- a/fuzz/Cargo.lock +++ b/fuzz/Cargo.lock @@ -356,7 +356,7 @@ dependencies = [ "asn1-rs-derive", "asn1-rs-impl", "displaydoc", - "nom 7.1.3", + "nom", "num-traits", "rusticata-macros", "thiserror 2.0.18", @@ -765,6 +765,7 @@ name = "bridge_core" version = "0.1.0" dependencies = [ "lee_core", + "risc0-zkvm", "serde", ] @@ -1325,7 +1326,7 @@ checksum = "07da5016415d5a3c4dd39b11ed26f915f52fc4e0dc197d87908bc916e51bc1a6" dependencies = [ "asn1-rs", "displaydoc", - "nom 7.1.3", + "nom", "num-bigint", "num-traits", "rusticata-macros", @@ -3344,10 +3345,20 @@ version = "0.4.33" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ceec5bc11778974d1bcb055b18002eba7f4b3518b6a0081b3af5f21666da9ad" +[[package]] +name = "logos-blockchain-blake2btree" +version = "0.0.0" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=0dc34e2c5a6e2ff772140378659489a602ee06bc#0dc34e2c5a6e2ff772140378659489a602ee06bc" +dependencies = [ + "blake2", + "logos-blockchain-dynamic-merkle", + "logos-blockchain-merkle-tree", +] + [[package]] name = "logos-blockchain-blend-crypto" -version = "0.1.2" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=d8711bbc3d43d3ef9755ef9b73af32fd0f703160#d8711bbc3d43d3ef9755ef9b73af32fd0f703160" +version = "0.0.0" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=0dc34e2c5a6e2ff772140378659489a602ee06bc#0dc34e2c5a6e2ff772140378659489a602ee06bc" dependencies = [ "blake2", "logos-blockchain-groth16", @@ -3360,8 +3371,8 @@ dependencies = [ [[package]] name = "logos-blockchain-blend-message" -version = "0.1.2" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=d8711bbc3d43d3ef9755ef9b73af32fd0f703160#d8711bbc3d43d3ef9755ef9b73af32fd0f703160" +version = "0.0.0" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=0dc34e2c5a6e2ff772140378659489a602ee06bc#0dc34e2c5a6e2ff772140378659489a602ee06bc" dependencies = [ "blake2", "derivative", @@ -3369,6 +3380,7 @@ dependencies = [ "itertools 0.14.0", "logos-blockchain-blend-crypto", "logos-blockchain-blend-proofs", + "logos-blockchain-codec", "logos-blockchain-core", "logos-blockchain-cryptarchia-engine", "logos-blockchain-groth16", @@ -3384,13 +3396,14 @@ dependencies = [ [[package]] name = "logos-blockchain-blend-proofs" -version = "0.1.2" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=d8711bbc3d43d3ef9755ef9b73af32fd0f703160#d8711bbc3d43d3ef9755ef9b73af32fd0f703160" +version = "0.0.0" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=0dc34e2c5a6e2ff772140378659489a602ee06bc#0dc34e2c5a6e2ff772140378659489a602ee06bc" dependencies = [ "ed25519-dalek", "generic-array 1.4.3", "hex", "logos-blockchain-blend-crypto", + "logos-blockchain-codec", "logos-blockchain-groth16", "logos-blockchain-pol", "logos-blockchain-poq", @@ -3404,8 +3417,8 @@ dependencies = [ [[package]] name = "logos-blockchain-chain-broadcast-service" -version = "0.1.2" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=d8711bbc3d43d3ef9755ef9b73af32fd0f703160#d8711bbc3d43d3ef9755ef9b73af32fd0f703160" +version = "0.0.0" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=0dc34e2c5a6e2ff772140378659489a602ee06bc#0dc34e2c5a6e2ff772140378659489a602ee06bc" dependencies = [ "async-trait", "derivative", @@ -3418,8 +3431,8 @@ dependencies = [ [[package]] name = "logos-blockchain-chain-service" -version = "0.1.2" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=d8711bbc3d43d3ef9755ef9b73af32fd0f703160#d8711bbc3d43d3ef9755ef9b73af32fd0f703160" +version = "0.0.0" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=0dc34e2c5a6e2ff772140378659489a602ee06bc#0dc34e2c5a6e2ff772140378659489a602ee06bc" dependencies = [ "async-trait", "bytes", @@ -3499,8 +3512,8 @@ dependencies = [ [[package]] name = "logos-blockchain-circuits-prover" -version = "0.1.2" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=d8711bbc3d43d3ef9755ef9b73af32fd0f703160#d8711bbc3d43d3ef9755ef9b73af32fd0f703160" +version = "0.0.0" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=0dc34e2c5a6e2ff772140378659489a602ee06bc#0dc34e2c5a6e2ff772140378659489a602ee06bc" dependencies = [ "rust-rapidsnark", ] @@ -3524,10 +3537,33 @@ dependencies = [ "libc", ] +[[package]] +name = "logos-blockchain-codec" +version = "0.0.0" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=0dc34e2c5a6e2ff772140378659489a602ee06bc#0dc34e2c5a6e2ff772140378659489a602ee06bc" +dependencies = [ + "hex", + "logos-blockchain-codec-macros", + "logos-blockchain-groth16", + "logos-blockchain-utils", + "thiserror 2.0.18", +] + +[[package]] +name = "logos-blockchain-codec-macros" +version = "0.0.0" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=0dc34e2c5a6e2ff772140378659489a602ee06bc#0dc34e2c5a6e2ff772140378659489a602ee06bc" +dependencies = [ + "hex", + "proc-macro2", + "quote", + "syn 2.0.118", +] + [[package]] name = "logos-blockchain-common-http-client" -version = "0.1.2" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=d8711bbc3d43d3ef9755ef9b73af32fd0f703160#d8711bbc3d43d3ef9755ef9b73af32fd0f703160" +version = "0.0.0" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=0dc34e2c5a6e2ff772140378659489a602ee06bc#0dc34e2c5a6e2ff772140378659489a602ee06bc" dependencies = [ "futures", "hex", @@ -3549,17 +3585,18 @@ dependencies = [ [[package]] name = "logos-blockchain-core" -version = "0.1.2" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=d8711bbc3d43d3ef9755ef9b73af32fd0f703160#d8711bbc3d43d3ef9755ef9b73af32fd0f703160" +version = "0.0.0" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=0dc34e2c5a6e2ff772140378659489a602ee06bc#0dc34e2c5a6e2ff772140378659489a602ee06bc" dependencies = [ "ark-ff", "bincode", "blake2", "bytes", "const-hex", - "futures", "hex", + "logos-blockchain-blake2btree", "logos-blockchain-blend-proofs", + "logos-blockchain-codec", "logos-blockchain-cryptarchia-engine", "logos-blockchain-groth16", "logos-blockchain-key-management-system-keys", @@ -3571,9 +3608,7 @@ dependencies = [ "logos-blockchain-utils", "logos-blockchain-utxotree", "multiaddr", - "nom 8.0.0", "num-bigint", - "rpds", "serde", "strum", "thiserror 2.0.18", @@ -3583,11 +3618,13 @@ dependencies = [ [[package]] name = "logos-blockchain-cryptarchia-engine" -version = "0.1.2" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=d8711bbc3d43d3ef9755ef9b73af32fd0f703160#d8711bbc3d43d3ef9755ef9b73af32fd0f703160" +version = "0.0.0" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=0dc34e2c5a6e2ff772140378659489a602ee06bc#0dc34e2c5a6e2ff772140378659489a602ee06bc" dependencies = [ + "logos-blockchain-codec", "logos-blockchain-pol", "logos-blockchain-utils", + "rpds", "serde", "serde_with", "thiserror 2.0.18", @@ -3598,8 +3635,8 @@ dependencies = [ [[package]] name = "logos-blockchain-cryptarchia-sync" -version = "0.1.2" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=d8711bbc3d43d3ef9755ef9b73af32fd0f703160#d8711bbc3d43d3ef9755ef9b73af32fd0f703160" +version = "0.0.0" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=0dc34e2c5a6e2ff772140378659489a602ee06bc#0dc34e2c5a6e2ff772140378659489a602ee06bc" dependencies = [ "bytes", "futures", @@ -3615,10 +3652,19 @@ dependencies = [ "tracing", ] +[[package]] +name = "logos-blockchain-dynamic-merkle" +version = "0.0.0" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=0dc34e2c5a6e2ff772140378659489a602ee06bc#0dc34e2c5a6e2ff772140378659489a602ee06bc" +dependencies = [ + "rpds", + "serde", +] + [[package]] name = "logos-blockchain-groth16" -version = "0.1.2" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=d8711bbc3d43d3ef9755ef9b73af32fd0f703160#d8711bbc3d43d3ef9755ef9b73af32fd0f703160" +version = "0.0.0" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=0dc34e2c5a6e2ff772140378659489a602ee06bc#0dc34e2c5a6e2ff772140378659489a602ee06bc" dependencies = [ "ark-bn254", "ark-ec", @@ -3628,6 +3674,7 @@ dependencies = [ "generic-array 1.4.3", "hex", "num-bigint", + "rand 0.8.6", "serde", "serde_json", "thiserror 2.0.18", @@ -3635,8 +3682,8 @@ dependencies = [ [[package]] name = "logos-blockchain-http-api-common" -version = "0.1.2" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=d8711bbc3d43d3ef9755ef9b73af32fd0f703160#d8711bbc3d43d3ef9755ef9b73af32fd0f703160" +version = "0.0.0" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=0dc34e2c5a6e2ff772140378659489a602ee06bc#0dc34e2c5a6e2ff772140378659489a602ee06bc" dependencies = [ "axum", "logos-blockchain-core", @@ -3656,14 +3703,15 @@ dependencies = [ [[package]] name = "logos-blockchain-key-management-system-keys" -version = "0.1.2" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=d8711bbc3d43d3ef9755ef9b73af32fd0f703160#d8711bbc3d43d3ef9755ef9b73af32fd0f703160" +version = "0.0.0" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=0dc34e2c5a6e2ff772140378659489a602ee06bc#0dc34e2c5a6e2ff772140378659489a602ee06bc" dependencies = [ "async-trait", "bytes", "ed25519-dalek", "generic-array 1.4.3", "hex", + "logos-blockchain-codec", "logos-blockchain-groth16", "logos-blockchain-key-management-system-macros", "logos-blockchain-log-targets", @@ -3683,8 +3731,8 @@ dependencies = [ [[package]] name = "logos-blockchain-key-management-system-macros" -version = "0.1.2" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=d8711bbc3d43d3ef9755ef9b73af32fd0f703160#d8711bbc3d43d3ef9755ef9b73af32fd0f703160" +version = "0.0.0" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=0dc34e2c5a6e2ff772140378659489a602ee06bc#0dc34e2c5a6e2ff772140378659489a602ee06bc" dependencies = [ "proc-macro2", "quote", @@ -3693,8 +3741,8 @@ dependencies = [ [[package]] name = "logos-blockchain-ledger" -version = "0.1.2" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=d8711bbc3d43d3ef9755ef9b73af32fd0f703160#d8711bbc3d43d3ef9755ef9b73af32fd0f703160" +version = "0.0.0" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=0dc34e2c5a6e2ff772140378659489a602ee06bc#0dc34e2c5a6e2ff772140378659489a602ee06bc" dependencies = [ "derivative", "logos-blockchain-blend-crypto", @@ -3719,8 +3767,8 @@ dependencies = [ [[package]] name = "logos-blockchain-libp2p" -version = "0.1.2" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=d8711bbc3d43d3ef9755ef9b73af32fd0f703160#d8711bbc3d43d3ef9755ef9b73af32fd0f703160" +version = "0.0.0" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=0dc34e2c5a6e2ff772140378659489a602ee06bc#0dc34e2c5a6e2ff772140378659489a602ee06bc" dependencies = [ "async-trait", "backon", @@ -3748,30 +3796,42 @@ dependencies = [ [[package]] name = "logos-blockchain-log-targets" -version = "0.1.2" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=d8711bbc3d43d3ef9755ef9b73af32fd0f703160#d8711bbc3d43d3ef9755ef9b73af32fd0f703160" +version = "0.0.0" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=0dc34e2c5a6e2ff772140378659489a602ee06bc#0dc34e2c5a6e2ff772140378659489a602ee06bc" dependencies = [ "logos-blockchain-log-targets-macros", ] [[package]] name = "logos-blockchain-log-targets-macros" -version = "0.1.2" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=d8711bbc3d43d3ef9755ef9b73af32fd0f703160#d8711bbc3d43d3ef9755ef9b73af32fd0f703160" +version = "0.0.0" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=0dc34e2c5a6e2ff772140378659489a602ee06bc#0dc34e2c5a6e2ff772140378659489a602ee06bc" dependencies = [ "proc-macro2", "quote", "syn 2.0.118", ] +[[package]] +name = "logos-blockchain-merkle-tree" +version = "0.0.0" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=0dc34e2c5a6e2ff772140378659489a602ee06bc#0dc34e2c5a6e2ff772140378659489a602ee06bc" +dependencies = [ + "logos-blockchain-dynamic-merkle", + "rpds", + "serde", + "thiserror 2.0.18", +] + [[package]] name = "logos-blockchain-mmr" -version = "0.1.2" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=d8711bbc3d43d3ef9755ef9b73af32fd0f703160#d8711bbc3d43d3ef9755ef9b73af32fd0f703160" +version = "0.0.0" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=0dc34e2c5a6e2ff772140378659489a602ee06bc#0dc34e2c5a6e2ff772140378659489a602ee06bc" dependencies = [ "ark-ff", "logos-blockchain-groth16", "logos-blockchain-poseidon2", + "logos-blockchain-utils", "rpds", "serde", "thiserror 2.0.18", @@ -3779,8 +3839,8 @@ dependencies = [ [[package]] name = "logos-blockchain-network-service" -version = "0.1.2" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=d8711bbc3d43d3ef9755ef9b73af32fd0f703160#d8711bbc3d43d3ef9755ef9b73af32fd0f703160" +version = "0.0.0" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=0dc34e2c5a6e2ff772140378659489a602ee06bc#0dc34e2c5a6e2ff772140378659489a602ee06bc" dependencies = [ "async-trait", "futures", @@ -3789,6 +3849,7 @@ dependencies = [ "logos-blockchain-libp2p", "logos-blockchain-log-targets", "logos-blockchain-tracing", + "logos-blockchain-utils", "overwatch", "rand 0.8.6", "rand_chacha 0.3.1", @@ -3800,8 +3861,8 @@ dependencies = [ [[package]] name = "logos-blockchain-poc" -version = "0.1.2" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=d8711bbc3d43d3ef9755ef9b73af32fd0f703160#d8711bbc3d43d3ef9755ef9b73af32fd0f703160" +version = "0.0.0" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=0dc34e2c5a6e2ff772140378659489a602ee06bc#0dc34e2c5a6e2ff772140378659489a602ee06bc" dependencies = [ "logos-blockchain-circuits-poc-sys", "logos-blockchain-circuits-prover", @@ -3817,8 +3878,8 @@ dependencies = [ [[package]] name = "logos-blockchain-pol" -version = "0.1.2" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=d8711bbc3d43d3ef9755ef9b73af32fd0f703160#d8711bbc3d43d3ef9755ef9b73af32fd0f703160" +version = "0.0.0" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=0dc34e2c5a6e2ff772140378659489a602ee06bc#0dc34e2c5a6e2ff772140378659489a602ee06bc" dependencies = [ "astro-float", "logos-blockchain-circuits-pol-sys", @@ -3837,8 +3898,8 @@ dependencies = [ [[package]] name = "logos-blockchain-poq" -version = "0.1.2" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=d8711bbc3d43d3ef9755ef9b73af32fd0f703160#d8711bbc3d43d3ef9755ef9b73af32fd0f703160" +version = "0.0.0" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=0dc34e2c5a6e2ff772140378659489a602ee06bc#0dc34e2c5a6e2ff772140378659489a602ee06bc" dependencies = [ "logos-blockchain-circuits-poq-sys", "logos-blockchain-circuits-prover", @@ -3856,8 +3917,8 @@ dependencies = [ [[package]] name = "logos-blockchain-poseidon2" -version = "0.1.2" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=d8711bbc3d43d3ef9755ef9b73af32fd0f703160#d8711bbc3d43d3ef9755ef9b73af32fd0f703160" +version = "0.0.0" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=0dc34e2c5a6e2ff772140378659489a602ee06bc#0dc34e2c5a6e2ff772140378659489a602ee06bc" dependencies = [ "ark-bn254", "ark-ff", @@ -3867,8 +3928,8 @@ dependencies = [ [[package]] name = "logos-blockchain-proofs-error" -version = "0.1.2" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=d8711bbc3d43d3ef9755ef9b73af32fd0f703160#d8711bbc3d43d3ef9755ef9b73af32fd0f703160" +version = "0.0.0" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=0dc34e2c5a6e2ff772140378659489a602ee06bc#0dc34e2c5a6e2ff772140378659489a602ee06bc" dependencies = [ "logos-blockchain-circuits-types", "logos-blockchain-groth16", @@ -3878,24 +3939,24 @@ dependencies = [ [[package]] name = "logos-blockchain-services-utils" -version = "0.1.2" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=d8711bbc3d43d3ef9755ef9b73af32fd0f703160#d8711bbc3d43d3ef9755ef9b73af32fd0f703160" +version = "0.0.0" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=0dc34e2c5a6e2ff772140378659489a602ee06bc#0dc34e2c5a6e2ff772140378659489a602ee06bc" dependencies = [ "async-trait", + "bytes", "futures", "log", "logos-blockchain-log-targets", "overwatch", "serde", - "serde_json", "thiserror 2.0.18", "tracing", ] [[package]] name = "logos-blockchain-storage-service" -version = "0.1.2" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=d8711bbc3d43d3ef9755ef9b73af32fd0f703160#d8711bbc3d43d3ef9755ef9b73af32fd0f703160" +version = "0.0.0" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=0dc34e2c5a6e2ff772140378659489a602ee06bc#0dc34e2c5a6e2ff772140378659489a602ee06bc" dependencies = [ "async-trait", "bytes", @@ -3903,7 +3964,9 @@ dependencies = [ "logos-blockchain-core", "logos-blockchain-cryptarchia-engine", "logos-blockchain-log-targets", + "logos-blockchain-services-utils", "logos-blockchain-tracing", + "logos-blockchain-utils", "overwatch", "serde", "thiserror 2.0.18", @@ -3913,8 +3976,8 @@ dependencies = [ [[package]] name = "logos-blockchain-time-service" -version = "0.1.2" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=d8711bbc3d43d3ef9755ef9b73af32fd0f703160#d8711bbc3d43d3ef9755ef9b73af32fd0f703160" +version = "0.0.0" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=0dc34e2c5a6e2ff772140378659489a602ee06bc#0dc34e2c5a6e2ff772140378659489a602ee06bc" dependencies = [ "async-trait", "futures", @@ -3936,8 +3999,8 @@ dependencies = [ [[package]] name = "logos-blockchain-tracing" -version = "0.1.2" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=d8711bbc3d43d3ef9755ef9b73af32fd0f703160#d8711bbc3d43d3ef9755ef9b73af32fd0f703160" +version = "0.0.0" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=0dc34e2c5a6e2ff772140378659489a602ee06bc#0dc34e2c5a6e2ff772140378659489a602ee06bc" dependencies = [ "flate2", "logos-blockchain-log-targets", @@ -3962,15 +4025,17 @@ dependencies = [ [[package]] name = "logos-blockchain-utils" -version = "0.1.2" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=d8711bbc3d43d3ef9755ef9b73af32fd0f703160#d8711bbc3d43d3ef9755ef9b73af32fd0f703160" +version = "0.0.0" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=0dc34e2c5a6e2ff772140378659489a602ee06bc#0dc34e2c5a6e2ff772140378659489a602ee06bc" dependencies = [ "async-trait", "blake2", "cipher 0.4.4", "const-hex", + "futures", "humantime", "logos-blockchain-log-targets", + "multiaddr", "overwatch", "rand 0.8.6", "serde", @@ -3979,27 +4044,27 @@ dependencies = [ "serde_yaml", "thiserror 2.0.18", "time", + "tokio", "tracing", ] [[package]] name = "logos-blockchain-utxotree" -version = "0.1.2" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=d8711bbc3d43d3ef9755ef9b73af32fd0f703160#d8711bbc3d43d3ef9755ef9b73af32fd0f703160" +version = "0.0.0" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=0dc34e2c5a6e2ff772140378659489a602ee06bc#0dc34e2c5a6e2ff772140378659489a602ee06bc" dependencies = [ "ark-ff", - "logos-blockchain-groth16", + "logos-blockchain-dynamic-merkle", + "logos-blockchain-merkle-tree", "logos-blockchain-poseidon2", - "num-bigint", "rpds", "serde", - "thiserror 2.0.18", ] [[package]] name = "logos-blockchain-zksign" -version = "0.1.2" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=d8711bbc3d43d3ef9755ef9b73af32fd0f703160#d8711bbc3d43d3ef9755ef9b73af32fd0f703160" +version = "0.0.0" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=0dc34e2c5a6e2ff772140378659489a602ee06bc#0dc34e2c5a6e2ff772140378659489a602ee06bc" dependencies = [ "logos-blockchain-circuits-prover", "logos-blockchain-circuits-signature-sys", @@ -4010,6 +4075,7 @@ dependencies = [ "logos-blockchain-proofs-error", "num-bigint", "serde", + "serde-big-array", "serde_json", "thiserror 2.0.18", "tracing", @@ -4049,6 +4115,29 @@ dependencies = [ "libc", ] +[[package]] +name = "manyhow" +version = "0.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b33efb3ca6d3b07393750d4030418d594ab1139cee518f0dc88db70fec873587" +dependencies = [ + "manyhow-macros", + "proc-macro2", + "quote", + "syn 2.0.118", +] + +[[package]] +name = "manyhow-macros" +version = "0.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46fce34d199b78b6e6073abf984c9cf5fd3e9330145a93ee0738a7443e371495" +dependencies = [ + "proc-macro-utils", + "proc-macro2", + "quote", +] + [[package]] name = "match-lookup" version = "0.1.2" @@ -4397,15 +4486,6 @@ dependencies = [ "minimal-lexical", ] -[[package]] -name = "nom" -version = "8.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df9761775871bdef83bee530e60050f7e54b1105350d6884eb0fb4f46c2f9405" -dependencies = [ - "memchr", -] - [[package]] name = "nu-ansi-term" version = "0.50.3" @@ -4629,7 +4709,7 @@ checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" [[package]] name = "overwatch" version = "0.1.0" -source = "git+https://github.com/logos-co/Overwatch?rev=448c192#448c192895b8311c742b1726a1bb12ee314ad95c" +source = "git+https://github.com/logos-co/Overwatch?rev=ae887f41f5a626c341179026ad7f03953ff2072e#ae887f41f5a626c341179026ad7f03953ff2072e" dependencies = [ "async-trait", "futures", @@ -4644,10 +4724,10 @@ dependencies = [ [[package]] name = "overwatch-derive" version = "0.1.0" -source = "git+https://github.com/logos-co/Overwatch?rev=448c192#448c192895b8311c742b1726a1bb12ee314ad95c" +source = "git+https://github.com/logos-co/Overwatch?rev=ae887f41f5a626c341179026ad7f03953ff2072e#ae887f41f5a626c341179026ad7f03953ff2072e" dependencies = [ "convert_case", - "proc-macro-error2", + "manyhow", "proc-macro2", "quote", "syn 2.0.118", @@ -4893,6 +4973,17 @@ dependencies = [ "syn 2.0.118", ] +[[package]] +name = "proc-macro-utils" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eeaf08a13de400bc215877b5bdc088f241b12eb42f0a548d3390dc1c56bb7071" +dependencies = [ + "proc-macro2", + "quote", + "smallvec", +] + [[package]] name = "proc-macro2" version = "1.0.106" @@ -5700,7 +5791,7 @@ version = "4.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "faf0c4a6ece9950b9abdb62b1cfcf2a68b3b67a10ba445b3bb85be2a293d0632" dependencies = [ - "nom 7.1.3", + "nom", ] [[package]] @@ -5871,6 +5962,15 @@ dependencies = [ "serde_derive", ] +[[package]] +name = "serde-big-array" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11fc7cc2c76d73e0f27ee52abbd64eec84d46f370c88371120433196934e4b7f" +dependencies = [ + "serde", +] + [[package]] name = "serde_arrays" version = "0.2.0" @@ -7577,7 +7677,7 @@ dependencies = [ "data-encoding", "der-parser", "lazy_static", - "nom 7.1.3", + "nom", "oid-registry", "rusticata-macros", "thiserror 2.0.18", diff --git a/fuzz/fuzz_targets/fuzz_encoding_privacy_preserving.rs b/fuzz/fuzz_targets/fuzz_encoding_privacy_preserving.rs index 10683ff1e..5eac3db8a 100644 --- a/fuzz/fuzz_targets/fuzz_encoding_privacy_preserving.rs +++ b/fuzz/fuzz_targets/fuzz_encoding_privacy_preserving.rs @@ -2,7 +2,7 @@ //! Fuzz target: privacy-preserving encoding invariants. //! //! Tests that `to_bytes` / `from_bytes` round-trips work correctly for the -//! privacy-preserving `Message` type, and that `try_from_circuit_output` +//! privacy-preserving `Message` type, and that `from_circuit_output` //! maps each circuit-output field onto the resulting `Message` unchanged. //! //! `PrivacyPreservingTransaction` is also tested for serialisation stability @@ -15,11 +15,12 @@ use nssa::{ Message as PPMessage, WitnessSet as PPWitnessSet, circuit::Proof, + message::PublicActionWithID, }, }; use nssa_core::{ - Commitment, PrivacyPreservingCircuitOutput, - account::{Account, Nonce}, + PrivacyPreservingCircuitOutput, PublicAction, + account::{Account, AccountWithMetadata, Nonce}, program::{BlockValidityWindow, TimestampValidityWindow}, }; @@ -31,12 +32,12 @@ fn minimal_message() -> PPMessage { ), ); PPMessage { - public_account_ids: vec![addr], + public_actions: vec![PublicActionWithID { + account_id: addr, + post_state: Account::default(), + }], nonces: vec![Nonce::from(0_u128)], - public_post_states: vec![], - encrypted_private_post_states: vec![], - new_commitments: vec![], - new_nullifiers: vec![], + private_actions: vec![], block_validity_window: BlockValidityWindow::new_unbounded(), timestamp_validity_window: TimestampValidityWindow::new_unbounded(), } @@ -108,55 +109,60 @@ fuzz_props::fuzz_entry!(|data: &[u8]| { } // ── INVARIANT [CircuitOutputMapping] ────────────────────────────────────── - // `try_from_circuit_output` carries each circuit-output field onto the resulting - // `Message` unchanged, and threads through the caller-supplied public_account_ids / - // nonces. The function is infallible (it performs no validation of its own), so a - // bare `is_ok()` would be a tautology; instead assert the field mapping, which catches - // a mutation that drops, swaps, or defaults any carried field. + // `from_circuit_output` carries each circuit-output field onto the resulting + // `Message` unchanged — every public action's pre-state account id is paired with its + // post-state, private actions are carried verbatim — and threads through the + // caller-supplied nonces. The function performs no validation of its own, so assert + // the field mapping, which catches a mutation that drops, swaps, or defaults any + // carried field. { let addr = AccountId::from( &PublicKey::new_from_private_key( &PrivateKey::try_new([1_u8; 32]).expect("known-good"), ), ); - let account_ids = vec![addr]; let nonces = vec![Nonce::from(7_u128)]; - let post_states = vec![Account::default()]; - let commitments = - vec![Commitment::new(&AccountId::new([9_u8; 32]), &Account::default())]; + let pre_state = Account::default(); + let post_state = Account { + balance: 42, + ..Account::default() + }; let output = PrivacyPreservingCircuitOutput { - public_pre_states: vec![], - public_post_states: post_states.clone(), - new_commitments: commitments.clone(), - new_nullifiers: vec![], - encrypted_private_post_states: vec![], + public_actions: vec![PublicAction { + pre: AccountWithMetadata::new(pre_state, true, addr), + post: post_state.clone(), + }], + private_actions: vec![], block_validity_window: BlockValidityWindow::new_unbounded(), timestamp_validity_window: TimestampValidityWindow::new_unbounded(), }; - let msg = PPMessage::try_from_circuit_output(account_ids.clone(), nonces.clone(), output) - .expect("INVARIANT VIOLATION [CircuitOutputMapping]: \ - try_from_circuit_output is infallible and must accept any output"); + let msg = PPMessage::from_circuit_output(nonces.clone(), output); assert_eq!( - msg.public_account_ids, account_ids, + msg.public_account_ids(), + vec![addr], "INVARIANT VIOLATION [CircuitOutputMapping]: \ - public_account_ids not threaded through unchanged", + public action account ids not carried from the circuit output's pre-states", ); assert_eq!( msg.nonces, nonces, "INVARIANT VIOLATION [CircuitOutputMapping]: nonces not threaded through unchanged", ); assert_eq!( - msg.public_post_states, post_states, + msg.public_actions, + vec![PublicActionWithID { + account_id: addr, + post_state, + }], "INVARIANT VIOLATION [CircuitOutputMapping]: \ - public_post_states not carried from the circuit output", + public post-states not carried from the circuit output", ); - assert_eq!( - msg.new_commitments, commitments, + assert!( + msg.private_actions.is_empty(), "INVARIANT VIOLATION [CircuitOutputMapping]: \ - new_commitments not carried from the circuit output", + private actions must be carried verbatim (here: empty)", ); } @@ -181,24 +187,24 @@ fuzz_props::fuzz_entry!(|data: &[u8]| { // ── Varied-size message round-trips ────────────────────────────────────── // Verify round-trip for several multi-account messages. for n_accounts in [0, 1, 2, 3] { - let mut account_ids = Vec::new(); + let mut public_actions = Vec::new(); let mut nonces = Vec::new(); for i in 0..n_accounts { let key_bytes = [i + 1_u8; 32]; if let Ok(key) = PrivateKey::try_new(key_bytes) { let pk = PublicKey::new_from_private_key(&key); - account_ids.push(AccountId::from(&pk)); + public_actions.push(PublicActionWithID { + account_id: AccountId::from(&pk), + post_state: Account::default(), + }); nonces.push(Nonce::from(i as u128)); } } let msg = PPMessage { - public_account_ids: account_ids, + public_actions, nonces, - public_post_states: vec![], - encrypted_private_post_states: vec![], - new_commitments: vec![], - new_nullifiers: vec![], + private_actions: vec![], block_validity_window: BlockValidityWindow::new_unbounded(), timestamp_validity_window: TimestampValidityWindow::new_unbounded(), }; diff --git a/fuzz/fuzz_targets/fuzz_privacy_preserving_state_transition.rs b/fuzz/fuzz_targets/fuzz_privacy_preserving_state_transition.rs index 7cd92c4a9..3893eaf3b 100644 --- a/fuzz/fuzz_targets/fuzz_privacy_preserving_state_transition.rs +++ b/fuzz/fuzz_targets/fuzz_privacy_preserving_state_transition.rs @@ -69,9 +69,9 @@ fuzz_props::fuzz_entry!(|data: &[u8]| { .iter() .map(|(_, pk)| AccountId::from(pk)) .collect(); - let public_account_ids = tx.message().public_account_ids.clone(); - let public_post_states = tx.message().public_post_states.clone(); - let new_commitments = tx.message().new_commitments.clone(); + let public_account_ids = tx.message().public_account_ids(); + let public_actions = tx.message().public_actions.clone(); + let new_commitments = tx.message().commitments(); let lee_tx = LeeTransaction::PrivacyPreserving(tx); @@ -155,17 +155,14 @@ fuzz_props::fuzz_entry!(|data: &[u8]| { .collect(); assert_nonce_increment_correctness(&isolated_signers, &nonces_before, &state); - // Non-signer public accounts at applied indices are set to their post-state. - for (idx, id) in public_account_ids.iter().enumerate() { - if idx >= public_post_states.len() { - break; // public_diff zips ids with post_states, truncating to the shorter vec - } - if signer_ids.contains(id) { + // Non-signer public accounts are set to their declared post-state. + for action in &public_actions { + if signer_ids.contains(&action.account_id) { continue; // signer accounts also get a nonce increment afterwards } assert_eq!( - state.get_account_by_id(*id), - public_post_states[idx], + state.get_account_by_id(action.account_id), + action.post_state, "INVARIANT VIOLATION [PostStateApplied]: public account was not set to its \ declared post-state", ); diff --git a/fuzz/fuzz_targets/fuzz_privacy_preserving_witness.rs b/fuzz/fuzz_targets/fuzz_privacy_preserving_witness.rs index a8b8c1d90..15dc21d08 100644 --- a/fuzz/fuzz_targets/fuzz_privacy_preserving_witness.rs +++ b/fuzz/fuzz_targets/fuzz_privacy_preserving_witness.rs @@ -27,24 +27,28 @@ use nssa::{ Message as PPMessage, WitnessSet as PPWitnessSet, circuit::Proof, + message::PublicActionWithID, }, PrivacyPreservingTransaction, }; use nssa_core::{ - account::Nonce, + account::{Account, Nonce}, program::{BlockValidityWindow, TimestampValidityWindow}, }; -/// Build a minimal `Message` for testing — no commitments, no nullifiers, -/// no encrypted states. Sufficient to test signature binding. +/// Build a minimal `Message` for testing — no private actions, default public +/// post-states. Sufficient to test signature binding. fn minimal_message(account_ids: Vec, nonces: Vec) -> PPMessage { PPMessage { - public_account_ids: account_ids, + public_actions: account_ids + .into_iter() + .map(|account_id| PublicActionWithID { + account_id, + post_state: Account::default(), + }) + .collect(), nonces, - public_post_states: vec![], - encrypted_private_post_states: vec![], - new_commitments: vec![], - new_nullifiers: vec![], + private_actions: vec![], block_validity_window: BlockValidityWindow::new_unbounded(), timestamp_validity_window: TimestampValidityWindow::new_unbounded(), } diff --git a/fuzz_props/src/privacy.rs b/fuzz_props/src/privacy.rs index 8b1f46594..4bc2f003c 100644 --- a/fuzz_props/src/privacy.rs +++ b/fuzz_props/src/privacy.rs @@ -21,18 +21,18 @@ //! `../privacy_preserving_coverage_gap.md`). //! //! [`synthesize_passing_proof`] takes the per-message route: it reconstructs the exact -//! [`PrivacyPreservingCircuitOutput`] the validator will build — including -//! `public_pre_states`, which the validator reads from live chain state — then builds a -//! [`FakeReceipt`] whose `ReceiptClaim::ok` matches that journal. Check 4 then passes for +//! [`PrivacyPreservingCircuitOutput`] the validator will build — including the `pre` half +//! of each [`PublicAction`], which the validator reads from live chain state — then builds +//! a [`FakeReceipt`] whose `ReceiptClaim::ok` matches that journal. Check 4 then passes for //! that specific (message, state) pair, and execution proceeds into checks 5–6 and state //! application. //! //! # Soundness note for callers //! //! Because the proof is *forced* to pass, this harness deliberately does **not** assert -//! balance conservation: under a real proof the circuit is what guarantees the -//! `public_post_states` conserve value, and that guarantee is exactly what a synthesised -//! pass bypasses. Asserting conservation here would only re-test the fake. The sound +//! balance conservation: under a real proof the circuit is what guarantees the public +//! post-states conserve value, and that guarantee is exactly what a synthesised pass +//! bypasses. Asserting conservation here would only re-test the fake. The sound //! invariants for this path — no panic, state isolation on rejection, commitment insertion, //! signer-nonce increment, post-state application, and replay rejection — are checked by the //! `fuzz_privacy_preserving_state_transition` target. @@ -43,11 +43,13 @@ use nssa::{ AccountId, PRIVACY_PRESERVING_CIRCUIT_ID, PrivacyPreservingTransaction, PrivateKey, V03State, privacy_preserving_transaction::{ Message as PPMessage, WitnessSet as PPWitnessSet, circuit::Proof, + message::PublicActionWithID, }, }; use nssa_core::{ Commitment, CommitmentSetDigest, EncryptedAccountData, EncryptionScheme, EphemeralPublicKey, - Nullifier, PrivacyPreservingCircuitOutput, PrivateAccountKind, SharedSecretKey, + Nullifier, PrivacyPreservingCircuitOutput, PrivateAccountKind, PrivateAction, PublicAction, + SharedSecretKey, account::{Account, AccountWithMetadata, Nonce}, program::ValidityWindow, }; @@ -60,8 +62,9 @@ use crate::generators::{FuzzAccount, account_id_for_key}; /// /// `signer_account_ids` must be the ids the validator will derive from the witness set — /// i.e. `AccountId::from(public_key)` for every key the message is signed with. They drive -/// the `is_authorized` flag of each reconstructed `public_pre_state`, so they must match the -/// witness set exactly or the journal digest diverges and the proof is rejected at check 4. +/// the `is_authorized` flag of each reconstructed `PublicAction::pre`, so they must match +/// the witness set exactly or the journal digest diverges and the proof is rejected at +/// check 4. /// /// The returned proof is valid **only** for this exact `(message, state, signers)` triple; /// it must be regenerated whenever any of them changes (notably after a prior transaction @@ -72,27 +75,26 @@ pub fn synthesize_passing_proof( state: &V03State, signer_account_ids: &[AccountId], ) -> Proof { - // Reconstruct `public_pre_states` byte-for-byte as + // Reconstruct each `PublicAction` byte-for-byte as // `ValidatedStateDiff::from_privacy_preserving_transaction` does: read each public - // account from live chain state, marking it authorised iff it signed. - let public_pre_states: Vec = message - .public_account_ids + // account's pre-state from live chain state (marking it authorised iff it signed) and + // pair it with the message's declared post-state. + let public_actions: Vec = message + .public_actions .iter() - .map(|account_id| { - AccountWithMetadata::new( - state.get_account_by_id(*account_id), - signer_account_ids.contains(account_id), - *account_id, - ) + .map(|action| PublicAction { + pre: AccountWithMetadata::new( + state.get_account_by_id(action.account_id), + signer_account_ids.contains(&action.account_id), + action.account_id, + ), + post: action.post_state.clone(), }) .collect(); let output = PrivacyPreservingCircuitOutput { - public_pre_states, - public_post_states: message.public_post_states.clone(), - encrypted_private_post_states: message.encrypted_private_post_states.clone(), - new_commitments: message.new_commitments.clone(), - new_nullifiers: message.new_nullifiers.clone(), + public_actions, + private_actions: message.private_actions.clone(), block_validity_window: message.block_validity_window, timestamp_validity_window: message.timestamp_validity_window, }; @@ -108,9 +110,9 @@ pub fn synthesize_passing_proof( } /// Build a fuzz-driven [`Account`] for use as a private commitment pre-image or a -/// `public_post_state`. +/// public action's post-state. /// -/// The nonce is intentionally capped well below `u128::MAX`: a `public_post_state` is +/// The nonce is intentionally capped well below `u128::MAX`: a public post-state is /// applied verbatim and a signer's nonce is then incremented, and the protocol's /// `public_account_nonce_increment` panics on overflow. An uncapped nonce would let the /// fuzzer drive a signer to `u128::MAX` via a forced-pass post-state and then trip that @@ -146,7 +148,8 @@ pub(crate) fn arb_validity_window(u: &mut Unstructured<'_>) -> ArbResult) -> ArbResult::arbitrary(u)?); - let commitment = Commitment::new(&AccountId::new(<[u8; 32]>::arbitrary(u)?), &account); - let ciphertext = EncryptionScheme::encrypt( - &account, - &kind, - &shared_secret, - &commitment, - u32::arbitrary(u)?, - ); + let nullifier = + Nullifier::for_account_initialization(&AccountId::new(<[u8; 32]>::arbitrary(u)?)); + let ciphertext = EncryptionScheme::encrypt(&account, &kind, &shared_secret, &nullifier); Ok(EncryptedAccountData { ciphertext, epk: EphemeralPublicKey(>::arbitrary(u)?), @@ -173,12 +171,40 @@ fn arb_encrypted_account_data(u: &mut Unstructured<'_>) -> ArbResult, + live_root: CommitmentSetDigest, +) -> ArbResult { + let null_aid = AccountId::new(<[u8; 32]>::arbitrary(u)?); + let nullifier = Nullifier::for_account_initialization(&null_aid); + let root: CommitmentSetDigest = if bool::arbitrary(u)? { + live_root + } else { + <[u8; 32]>::arbitrary(u)? + }; + let commitment = Commitment::new(&AccountId::new(<[u8; 32]>::arbitrary(u)?), &arb_account(u)?); + Ok(PrivateAction { + nullifier, + root, + commitment, + encrypted_post_state: arb_encrypted_account_data(u)?, + }) +} + /// Generate a privacy-preserving transaction aimed at the **state-transition executor**. /// /// The transaction is built to *frequently* pass every validation check up to and including /// proof verification (check 4) so that the previously-uncovered checks 5–6 and /// `apply_state_diff` are exercised, while fuzz-driven choices (mismatched nullifier digest, -/// occasional garbage proof, duplicated/oversized field shapes, bounded validity windows that +/// occasional garbage proof, duplicated field shapes, bounded validity windows that /// exclude the block/timestamp) still drive the rejection and isolation paths. /// /// `state` must be the *current* state the transaction will be validated against — the @@ -220,11 +246,12 @@ pub fn arb_privacy_preserving_tx( .map(|id| state.get_account_by_id(*id).nonce) .collect(); - // ── public_account_ids (must be unique — validator check 2) ────────────────────── + // ── public_actions (account ids must be unique — validator check 2) ────────────── + // Each action pairs an account id with its declared post-state; the id set mirrors the + // pre-bundling shape: sometimes the signers themselves (the common shape), otherwise + // signers are left out so the signer-nonce-increment invariant is exercised on an + // account that is *not* also overwritten by a post-state, plus up to 3 extra ids. let mut public_account_ids: Vec = Vec::new(); - // Sometimes treat the signers themselves as updated public accounts (the common shape); - // otherwise leave them out so the signer-nonce-increment invariant is exercised on an - // account that is *not* also overwritten by a post-state. if bool::arbitrary(u)? { public_account_ids.extend_from_slice(&signer_ids); } @@ -240,72 +267,44 @@ pub fn arb_privacy_preserving_tx( public_account_ids.push(id); } } - - // ── public_post_states ── - // Range 0..=len+3 so lengths can exceed the public-account count, exercising - // both the truncation path and the oversized/length-mismatch path. - let n_post = (u8::arbitrary(u)? as usize) % (public_account_ids.len() + 4); - let public_post_states = std::iter::repeat_with(|| arb_account(u)) - .take(n_post) + let public_actions = public_account_ids + .into_iter() + .map(|account_id| { + Ok(PublicActionWithID { + account_id, + post_state: arb_account(u)?, + }) + }) .collect::>>()?; - // ── new_commitments (unique — validator check 2c; fresh against a genesis state) ── - let n_comm = (u8::arbitrary(u)? as usize) % 4; - let mut new_commitments: Vec = Vec::new(); - for _ in 0..n_comm { - let aid = AccountId::new(<[u8; 32]>::arbitrary(u)?); - let acc = arb_account(u)?; - let commitment = Commitment::new(&aid, &acc); - if !new_commitments.contains(&commitment) { - new_commitments.push(commitment); - } - } - - // ── new_nullifiers (unique — validator check 2b) ───────────────────────────────── - // Check 6 additionally requires each digest to be in the commitment set's `root_history`. - // `root_history` starts *empty* on a fresh genesis state and is only seeded once a - // commitment-bearing transaction applies (`CommitmentSet::extend` inserts the post-insert - // root). So a nullifier digest set to the live root only passes check 6 on a *later* - // transaction in the sequence — after an earlier tx grew the commitment set; against the - // first tx (empty history) even the live root is rejected. We still use the live root half - // the time so the success path becomes reachable once seeded; a random digest always drives - // the check-6 rejection path. - let n_null = (u8::arbitrary(u)? as usize) % 3; + // ── private_actions (unique nullifiers and commitments — validator check 2) ────── + // Check 6 additionally requires each action's digest to be in the commitment set's + // `root_history`. The protocol seeds the history at genesis (the `Default` state inserts + // a dummy commitment, recording the post-insert root), so an action bound to the live + // root passes check 6 even on the first transaction in a sequence; a random digest + // always drives the check-6 rejection path. + let n_priv = (u8::arbitrary(u)? as usize) % 4; let live_root = state.commitment_set_digest(); - let mut new_nullifiers: Vec<(Nullifier, CommitmentSetDigest)> = Vec::new(); - for _ in 0..n_null { - let aid = AccountId::new(<[u8; 32]>::arbitrary(u)?); - let nullifier = Nullifier::for_account_initialization(&aid); - let digest: CommitmentSetDigest = if bool::arbitrary(u)? { - live_root - } else { - <[u8; 32]>::arbitrary(u)? - }; - if !new_nullifiers.iter().any(|(n, _)| n == &nullifier) { - new_nullifiers.push((nullifier, digest)); + let mut private_actions: Vec = Vec::new(); + for _ in 0..n_priv { + let action = arb_private_action(u, live_root)?; + if !private_actions + .iter() + .any(|a| a.nullifier == action.nullifier || a.commitment == action.commitment) + { + private_actions.push(action); } } - // Validator check 1: commitments OR nullifiers must be non-empty. - if new_commitments.is_empty() && new_nullifiers.is_empty() { - let aid = AccountId::new(<[u8; 32]>::arbitrary(u)?); - let acc = arb_account(u)?; - new_commitments.push(Commitment::new(&aid, &acc)); + // Validator check 1: the private-action list must be non-empty. + if private_actions.is_empty() { + private_actions.push(arb_private_action(u, live_root)?); } - // ── encrypted_private_post_states (carried into the proof journal, not validated) ── - let n_enc = (u8::arbitrary(u)? as usize) % 3; - let encrypted_private_post_states = std::iter::repeat_with(|| arb_encrypted_account_data(u)) - .take(n_enc) - .collect::>>()?; - let message = PPMessage { - public_account_ids, + public_actions, nonces, - public_post_states, - encrypted_private_post_states, - new_commitments, - new_nullifiers, + private_actions, block_validity_window: arb_validity_window(u)?, timestamp_validity_window: arb_validity_window(u)?, }; @@ -322,14 +321,14 @@ pub fn arb_privacy_preserving_tx( Ok(PrivacyPreservingTransaction::new(message, witness_set)) } -/// Build a minimal *pure-private* transaction: one signer, no public accounts, the given -/// commitments and nullifiers, and unbounded validity windows. +/// Build a minimal *pure-private* transaction: one signer, no public actions, the given +/// private actions, and unbounded validity windows. /// /// Two properties matter for the ordering-independence oracle in /// `fuzz_transaction_ordering_independence`: /// -/// * **`public_account_ids` is empty**, so `synthesize_passing_proof` reconstructs an empty -/// `public_pre_states` and the journal does not depend on live chain state. The proof +/// * **`public_actions` is empty**, so `synthesize_passing_proof` reconstructs an empty +/// public-action list and the journal does not depend on live chain state. The proof /// therefore stays valid at check 4 even after another transaction has mutated the state — /// i.e. it is valid whether this tx is applied *first* or *second*. That is what lets us /// apply the same transaction in both orderings and compare outcomes soundly. @@ -340,17 +339,13 @@ pub fn arb_privacy_preserving_tx( fn build_pure_private_tx( state: &V03State, key: &PrivateKey, - new_commitments: Vec, - new_nullifiers: Vec<(Nullifier, CommitmentSetDigest)>, + private_actions: Vec, ) -> PrivacyPreservingTransaction { let signer_id = account_id_for_key(key); let message = PPMessage { - public_account_ids: Vec::new(), + public_actions: Vec::new(), nonces: vec![state.get_account_by_id(signer_id).nonce], - public_post_states: Vec::new(), - encrypted_private_post_states: Vec::new(), - new_commitments, - new_nullifiers, + private_actions, block_validity_window: ValidityWindow::new_unbounded(), timestamp_validity_window: ValidityWindow::new_unbounded(), }; @@ -363,11 +358,11 @@ fn build_pure_private_tx( /// (different signers, different fresh commitments) that both declare the **same** nullifier. /// /// The shared nullifier's digest is bound to the current commitment-set root -/// (`state.commitment_set_digest()`); this only satisfies check 6's `root_history` membership -/// once a commitment-bearing transaction has already grown the set, so callers should seed the -/// state first (see the target). The two transactions are otherwise independently valid, so a -/// correct state machine must accept *at most one* of them regardless of application order — -/// the property the ordering-independence target asserts. +/// (`state.commitment_set_digest()`), which is a member of `root_history` from genesis +/// onwards (the protocol seeds the history with its dummy commitment), so check 6 passes for +/// whichever transaction is applied first. The two transactions are otherwise independently +/// valid, so a correct state machine must accept *at most one* of them regardless of +/// application order — the property the ordering-independence target asserts. /// /// Returns `Err` when there are fewer than two distinct keyed accounts to draw signers from. pub fn arb_conflicting_nullifier_pair( @@ -393,7 +388,7 @@ pub fn arb_conflicting_nullifier_pair( // One nullifier, shared by both transactions, bound to a historical commitment-set root. let root = state.commitment_set_digest(); let null_aid = AccountId::new(<[u8; 32]>::arbitrary(u)?); - let shared_nullifiers = vec![(Nullifier::for_account_initialization(&null_aid), root)]; + let shared_nullifier = Nullifier::for_account_initialization(&null_aid); // Distinct fresh commitments make the two transactions genuinely different (and keep them // from colliding with each other on check 5). @@ -403,7 +398,20 @@ pub fn arb_conflicting_nullifier_pair( return Err(arbitrary::Error::IncorrectFormat); } - let tx_b = build_pure_private_tx(state, key_b, vec![comm_b], shared_nullifiers.clone()); - let tx_c = build_pure_private_tx(state, key_c, vec![comm_c], shared_nullifiers); + let action_b = PrivateAction { + nullifier: shared_nullifier, + root, + commitment: comm_b, + encrypted_post_state: arb_encrypted_account_data(u)?, + }; + let action_c = PrivateAction { + nullifier: shared_nullifier, + root, + commitment: comm_c, + encrypted_post_state: arb_encrypted_account_data(u)?, + }; + + let tx_b = build_pure_private_tx(state, key_b, vec![action_b]); + let tx_c = build_pure_private_tx(state, key_c, vec![action_c]); Ok((tx_b, tx_c)) } diff --git a/fuzz_props/src/tests/privacy.rs b/fuzz_props/src/tests/privacy.rs index d8317595a..7bc4ced56 100644 --- a/fuzz_props/src/tests/privacy.rs +++ b/fuzz_props/src/tests/privacy.rs @@ -6,10 +6,28 @@ use crate::privacy::{ synthesize_passing_proof, }; use nssa::privacy_preserving_transaction::{Message as PPMessage, WitnessSet as PPWitnessSet}; -use nssa::{AccountId, PrivacyPreservingTransaction, PrivateKey}; -use nssa_core::Commitment; +use nssa::{AccountId, PrivacyPreservingTransaction, PrivateKey, V03State}; use nssa_core::account::Account; +use nssa_core::encryption::Ciphertext; use nssa_core::program::{BlockValidityWindow, TimestampValidityWindow}; +use nssa_core::{Commitment, EncryptedAccountData, EphemeralPublicKey, Nullifier, PrivateAction}; + +/// A structurally-valid [`PrivateAction`] whose nullifier digest is the live commitment-set +/// root of `state` (a member of `root_history` from genesis onwards, since the protocol seeds +/// the history with its dummy commitment) — so checks 5 and 6 both pass on a fresh state. +fn valid_private_action(state: &V03State, seed: u8) -> PrivateAction { + let aid = AccountId::new([seed; 32]); + PrivateAction { + nullifier: Nullifier::for_account_initialization(&aid), + root: state.commitment_set_digest(), + commitment: Commitment::new(&aid, &Account::default()), + encrypted_post_state: EncryptedAccountData { + ciphertext: Ciphertext::from_inner(vec![]), + epk: EphemeralPublicKey(vec![]), + view_tag: 0, + }, + } +} /// `synthesize_passing_proof` must drive the executor *past* proof verification (check 4) /// into checks 5–6 and `apply_state_diff`. If the reconstructed journal were even one @@ -28,17 +46,15 @@ fn synthesized_proof_reaches_checks_5_6_and_applies() { let mut state = crate::genesis::genesis_state(&[], vec![]); - // No signers and a single fresh commitment: checks 1–3 are vacuous/trivially met, so - // the only way to reach checks 5–6 is for the synthesised proof to pass check 4. - let aid = AccountId::new([7_u8; 32]); - let commitment = Commitment::new(&aid, &Account::default()); + // No signers and a single valid private action (fresh commitment, nullifier bound to the + // live root): checks 1–3 are vacuous/trivially met and checks 5–6 pass, so the only way + // to reach the successful apply is for the synthesised proof to pass check 4. + let action = valid_private_action(&state, 7); + let commitment = action.commitment; let message = PPMessage { - public_account_ids: vec![], + public_actions: vec![], nonces: vec![], - public_post_states: vec![], - encrypted_private_post_states: vec![], - new_commitments: vec![commitment.clone()], - new_nullifiers: vec![], + private_actions: vec![action], block_validity_window: BlockValidityWindow::new_unbounded(), timestamp_validity_window: TimestampValidityWindow::new_unbounded(), }; @@ -87,17 +103,15 @@ fn synthesized_proof_is_rejected_without_dev_mode() { let mut state = crate::genesis::genesis_state(&[], vec![]); - // Same well-formed message as the positive test: checks 1–3 are vacuous/trivially met, so a - // rejection can only come from check 4 (proof verification) failing on the fake receipt. - let aid = AccountId::new([7_u8; 32]); - let commitment = Commitment::new(&aid, &Account::default()); + // Same well-formed message as the positive test: checks 1–3 are vacuous/trivially met and + // checks 5–6 would pass, so a rejection can only come from check 4 (proof verification) + // failing on the fake receipt. + let action = valid_private_action(&state, 7); + let commitment = action.commitment; let message = PPMessage { - public_account_ids: vec![], + public_actions: vec![], nonces: vec![], - public_post_states: vec![], - encrypted_private_post_states: vec![], - new_commitments: vec![commitment.clone()], - new_nullifiers: vec![], + private_actions: vec![action], block_validity_window: BlockValidityWindow::new_unbounded(), timestamp_validity_window: TimestampValidityWindow::new_unbounded(), }; @@ -258,7 +272,7 @@ fn arb_validity_window_bounds_use_modulo_8() { /// Two flavours of check run here: per-iteration upper bounds that must hold for /// *every* generated transaction, and end-of-run reachability checks that confirm /// the interesting shapes actually occur across the sampled inputs. -/// Which branches of the line-233 `if !accounts.is_empty() && bool::arbitrary(u)?` were +/// Which branches of the extra-id `if !accounts.is_empty() && bool::arbitrary(u)?` were /// observable across a transaction's non-signer "extra" public-account ids. #[derive(Default)] struct ExtraKinds { @@ -271,8 +285,8 @@ struct ExtraKinds { } /// Classify a message's extras. A signer's public-account id is key-derived and independent -/// of `FuzzAccount.account_id`, so any non-signer id present in `public_account_ids` was -/// appended by the line-233 `if`; a *known* id can only come from its `&&`-true branch. +/// of `FuzzAccount.account_id`, so any non-signer id present in the public-action list was +/// appended by the extra-id `if`; a *known* id can only come from its `&&`-true branch. fn classify_extras( public_account_ids: &[AccountId], signer_ids: &[AccountId], @@ -318,10 +332,7 @@ fn arb_privacy_preserving_tx_generator_invariants() { let mut saw_extra = false; let mut saw_known_extra = false; let mut saw_random_extra = false; - let mut max_commitments = 0_usize; - let mut max_nullifiers = 0_usize; - let mut saw_empty_comm_nonempty_null = false; - let mut saw_oversize_post_states = false; + let mut max_private_actions = 0_usize; let mut garbage = 0_usize; let mut saw_garbage = false; @@ -350,57 +361,52 @@ fn arb_privacy_preserving_tx_generator_invariants() { // The signer count is drawn modulo `max_signers + 1`, so it can never exceed // the cap of 3 distinct signers. assert!(n_signers <= 3, "n_signers {n_signers} exceeds the cap of 3"); - // Post-states are drawn modulo `public_account_ids.len() + 4` (0..=len+3). - assert!( - msg.public_post_states.len() <= msg.public_account_ids.len() + 3, - "public_post_states {} exceeds public_account_ids + 3 ({})", - msg.public_post_states.len(), - msg.public_account_ids.len() + 3 - ); - if msg.public_post_states.len() > msg.public_account_ids.len() { - saw_oversize_post_states = true; - } // At most 3 signers plus at most 3 extra ids (both deduplicated). assert!( - msg.public_account_ids.len() <= 6, - "public_account_ids {} exceeds signers (<=3) + extras (<=3)", - msg.public_account_ids.len() + msg.public_actions.len() <= 6, + "public_actions {} exceeds signers (<=3) + extras (<=3)", + msg.public_actions.len() ); - // `new_commitments` count is drawn modulo 4 (0..=3). - assert!( - msg.new_commitments.len() <= 3, - "new_commitments {} exceeds 3", - msg.new_commitments.len() + // The account ids across public actions must be unique (validator check 2). + let public_account_ids = msg.public_account_ids(); + let unique_ids: std::collections::HashSet<&AccountId> = public_account_ids.iter().collect(); + assert_eq!( + unique_ids.len(), + public_account_ids.len(), + "public action account ids must be deduplicated" ); - // `new_nullifiers` count is drawn modulo 3 (0..=2). + // `private_actions` count is drawn modulo 4 (0..=3), with a non-empty fallback. assert!( - msg.new_nullifiers.len() <= 2, - "new_nullifiers {} exceeds 2", - msg.new_nullifiers.len() + (1..=3).contains(&msg.private_actions.len()), + "private_actions {} outside the expected 1..=3 range", + msg.private_actions.len() ); - // `encrypted_private_post_states` count is drawn modulo 3 (0..=2). - assert!( - msg.encrypted_private_post_states.len() <= 2, - "encrypted_private_post_states {} exceeds 2", - msg.encrypted_private_post_states.len() + // Nullifiers and commitments across private actions must be unique (validator + // check 2). + let nullifiers = msg.nullifiers(); + let unique_nullifiers: std::collections::HashSet<_> = + nullifiers.iter().map(|(n, _)| *n).collect(); + assert_eq!( + unique_nullifiers.len(), + nullifiers.len(), + "private-action nullifiers must be deduplicated" + ); + let commitments = msg.commitments(); + let unique_commitments: std::collections::HashSet<_> = commitments.iter().collect(); + assert_eq!( + unique_commitments.len(), + commitments.len(), + "private-action commitments must be deduplicated" ); - // Classify the non-signer "extras" by which branch of the line-233 `if` produced + // Classify the non-signer "extras" by which branch of the extra-id `if` produced // them — a *known* fuzz-account id, a *random* id, or both. - let extras = classify_extras(&msg.public_account_ids, &signer_ids, &known_ids); + let extras = classify_extras(&public_account_ids, &signer_ids, &known_ids); saw_extra |= extras.any; saw_known_extra |= extras.known; saw_random_extra |= extras.random; - max_commitments = max_commitments.max(msg.new_commitments.len()); - max_nullifiers = max_nullifiers.max(msg.new_nullifiers.len()); - - // The fallback that guarantees "commitments or nullifiers non-empty" must fire - // only when *both* are empty. So a message with empty commitments but non-empty - // nullifiers is a valid, reachable shape — the fallback must leave it alone. - if msg.new_commitments.is_empty() && !msg.new_nullifiers.is_empty() { - saw_empty_comm_nonempty_null = true; - } + max_private_actions = max_private_actions.max(msg.private_actions.len()); // Which proof branch ran? A synthesized passing proof is a deterministic // function of (message, state, signers); re-synthesizing reproduces it @@ -445,26 +451,10 @@ fn arb_privacy_preserving_tx_generator_invariants() { saw_random_extra, "the generator never appended a *random* id as an extra" ); - // Multiple distinct commitments must be reachable (the dedup must keep, not drop). + // Multiple distinct private actions must be reachable (the dedup must keep, not drop). assert!( - max_commitments >= 2, - "the generator never produced >= 2 commitments" - ); - // Multiple distinct nullifiers must be reachable (the dedup must keep, not drop). - assert!( - max_nullifiers >= 2, - "the generator never produced >= 2 nullifiers" - ); - // The empty-commitments + non-empty-nullifiers shape must be reachable, proving the - // fallback does not over-fire. - assert!( - saw_empty_comm_nonempty_null, - "the generator never produced empty commitments with non-empty nullifiers" - ); - // The oversized shape (more post-states than public account ids) must be reachable. - assert!( - saw_oversize_post_states, - "the generator never produced more post-states than public account ids" + max_private_actions >= 2, + "the generator never produced >= 2 private actions" ); // The garbage-proof branch (~1 in 8) must be reachable at all. assert!(saw_garbage, "the generator never produced a garbage proof");