chore: sync with LEZ main (bundled public/private actions)

Upstream LEZ merged the parallel Message vectors into action structs
(f16c3bd1e, 75326d031, e13b4cb23):

* `Message` now carries `public_actions: Vec<PublicActionWithID>`
  (account id paired with its post-state) and `private_actions:
  Vec<PrivateAction>` (nullifier + root + commitment + encrypted post
  state bundled per action) instead of six parallel vectors.
* `PrivacyPreservingCircuitOutput` mirrors the same bundling
  (`public_actions: Vec<PublicAction>` 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).
This commit is contained in:
Roman 2026-08-05 09:45:21 +02:00
parent 6b38aa34b2
commit dec23d373c
No known key found for this signature in database
GPG Key ID: 583BDF43C238B83E
8 changed files with 637 additions and 432 deletions

View File

@ -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

274
Cargo.lock generated
View File

@ -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",

274
fuzz/Cargo.lock generated
View File

@ -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",

View File

@ -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(),
};

View File

@ -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",
);

View File

@ -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<AccountId>, nonces: Vec<Nonce>) -> 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(),
}

View File

@ -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 56 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<AccountWithMetadata> = 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<PublicAction> = 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<Validit
Ok(ValidityWindow::try_from((from, to)).unwrap_or_else(|_| ValidityWindow::new_unbounded()))
}
/// Build one fuzz-driven [`EncryptedAccountData`] for `message.encrypted_private_post_states`.
/// Build one fuzz-driven [`EncryptedAccountData`] for a [`PrivateAction`]'s
/// `encrypted_post_state`.
///
/// The executor does not validate the encrypted notes directly — they are only bound into the proof
/// journal — so this needs no real recipient keys: the three fields are public, and the only one
@ -158,14 +161,9 @@ fn arb_encrypted_account_data(u: &mut Unstructured<'_>) -> ArbResult<EncryptedAc
let account = arb_account(u)?;
let kind = PrivateAccountKind::Regular(u128::arbitrary(u)?);
let shared_secret = SharedSecretKey(<[u8; 32]>::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(<Vec<u8>>::arbitrary(u)?),
@ -173,12 +171,40 @@ fn arb_encrypted_account_data(u: &mut Unstructured<'_>) -> ArbResult<EncryptedAc
})
}
/// Build one fuzz-driven [`PrivateAction`].
///
/// The nullifier is derived from a random account id, so distinct draws collide only with
/// negligible probability (the caller still deduplicates — validator check 2). The digest is
/// the **live commitment-set root half the time** so check 6's `root_history` membership
/// passes (the root history is seeded at genesis by the protocol's dummy commitment, so the
/// live root is always a member) and the success path stays frequently reachable; a random
/// digest drives the check-6 rejection path.
fn arb_private_action(
u: &mut Unstructured<'_>,
live_root: CommitmentSetDigest,
) -> ArbResult<PrivateAction> {
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 56 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<AccountId> = 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::<ArbResult<Vec<_>>>()?;
// ── 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<Commitment> = 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<PrivateAction> = 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::<ArbResult<Vec<_>>>()?;
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<Commitment>,
new_nullifiers: Vec<(Nullifier, CommitmentSetDigest)>,
private_actions: Vec<PrivateAction>,
) -> 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))
}

View File

@ -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 56 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 13 are vacuous/trivially met, so
// the only way to reach checks 56 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 13 are vacuous/trivially met and checks 56 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 13 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 13 are vacuous/trivially met and
// checks 56 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");