From f3e27a42edcb6a652dc1451a13fe604639410bd0 Mon Sep 17 00:00:00 2001 From: Blake Date: Wed, 18 Mar 2026 20:39:02 +0800 Subject: [PATCH 01/14] feat: adapt to Ziren's new groth16 verifier and handle the upgrade issue. --- Cargo.lock | 107 +++++++++------ Cargo.toml | 9 +- circuits/README.md | 2 +- circuits/commit-chain-proof/guest/Cargo.toml | 6 +- circuits/commit-chain-proof/host/src/lib.rs | 47 ++++++- circuits/header-chain-proof/guest/Cargo.toml | 6 +- circuits/header-chain-proof/host/src/lib.rs | 47 ++++++- circuits/operator-proof/guest/Cargo.toml | 4 + circuits/operator-proof/host/src/lib.rs | 45 ++++++- circuits/proof-builder/src/lib.rs | 5 + circuits/state-chain-proof/guest/Cargo.toml | 6 +- circuits/state-chain-proof/host/src/lib.rs | 47 ++++++- circuits/watchtower-proof/guest/Cargo.toml | 4 + circuits/watchtower-proof/host/src/lib.rs | 41 ++++++ .../bitcoin-light-client-circuit/src/lib.rs | 123 ++++++++++++++---- crates/bitvm2-ga/src/tests.rs | 4 +- crates/commit-chain/src/commit_chain.rs | 2 + crates/commit-chain/src/lib.rs | 13 +- crates/header-chain/src/header_chain.rs | 3 + crates/header-chain/src/lib.rs | 13 +- crates/state-chain/src/lib.rs | 13 +- crates/state-chain/src/state_chain.rs | 2 + node/src/utils.rs | 22 +++- 23 files changed, 489 insertions(+), 82 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5c4ea744..b4d6d6f9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2414,9 +2414,9 @@ dependencies = [ "tendermint", "tendermint-light-client-verifier", "tracing", - "zkm-primitives", + "zkm-primitives 1.2.4 (git+https://github.com/ProjectZKM/Ziren)", "zkm-verifier", - "zkm-zkvm", + "zkm-zkvm 1.2.4 (git+https://github.com/ProjectZKM/Ziren)", ] [[package]] @@ -2765,7 +2765,7 @@ dependencies = [ "pairing 0.23.0", "rand_core 0.6.4", "subtle", - "zkm-lib", + "zkm-lib 1.2.4 (git+https://github.com/ProjectZKM/Ziren)", ] [[package]] @@ -3191,7 +3191,7 @@ dependencies = [ "tendermint-light-client-verifier", "tracing", "zkm-verifier", - "zkm-zkvm", + "zkm-zkvm 1.2.4 (git+https://github.com/ProjectZKM/Ziren)", ] [[package]] @@ -5319,7 +5319,7 @@ dependencies = [ "serde", "sha2 0.10.9", "zkm-verifier", - "zkm-zkvm", + "zkm-zkvm 1.2.4 (git+https://github.com/ProjectZKM/Ziren)", ] [[package]] @@ -11481,7 +11481,7 @@ dependencies = [ "tendermint-light-client-verifier", "tracing", "zkm-verifier", - "zkm-zkvm", + "zkm-zkvm 1.2.4 (git+https://github.com/ProjectZKM/Ziren)", ] [[package]] @@ -11676,7 +11676,7 @@ dependencies = [ "num-bigint 0.4.6", "rand 0.8.5", "rustc-hex", - "zkm-lib", + "zkm-lib 1.2.4 (git+https://github.com/ProjectZKM/Ziren)", ] [[package]] @@ -13829,7 +13829,6 @@ dependencies = [ [[package]] name = "zkm-build" version = "1.2.4" -source = "git+https://github.com/ProjectZKM/Ziren#980997f64e258c706d280dd4f2d0c3829341a4f2" dependencies = [ "anyhow", "cargo_metadata", @@ -13840,7 +13839,6 @@ dependencies = [ [[package]] name = "zkm-core-executor" version = "1.2.4" -source = "git+https://github.com/ProjectZKM/Ziren#980997f64e258c706d280dd4f2d0c3829341a4f2" dependencies = [ "anyhow", "bincode", @@ -13871,14 +13869,13 @@ dependencies = [ "typenum", "vec_map", "zkm-curves", - "zkm-primitives", + "zkm-primitives 1.2.4", "zkm-stark", ] [[package]] name = "zkm-core-machine" version = "1.2.4" -source = "git+https://github.com/ProjectZKM/Ziren#980997f64e258c706d280dd4f2d0c3829341a4f2" dependencies = [ "bincode", "cfg-if", @@ -13923,14 +13920,13 @@ dependencies = [ "zkm-core-executor", "zkm-curves", "zkm-derive", - "zkm-primitives", + "zkm-primitives 1.2.4", "zkm-stark", ] [[package]] name = "zkm-cuda" version = "1.2.4" -source = "git+https://github.com/ProjectZKM/Ziren#980997f64e258c706d280dd4f2d0c3829341a4f2" dependencies = [ "bincode", "ctrlc", @@ -13948,7 +13944,6 @@ dependencies = [ [[package]] name = "zkm-curves" version = "1.2.4" -source = "git+https://github.com/ProjectZKM/Ziren#980997f64e258c706d280dd4f2d0c3829341a4f2" dependencies = [ "cfg-if", "curve25519-dalek", @@ -13965,14 +13960,13 @@ dependencies = [ "thiserror 1.0.69", "tracing", "typenum", - "zkm-primitives", + "zkm-primitives 1.2.4", "zkm-stark", ] [[package]] name = "zkm-derive" version = "1.2.4" -source = "git+https://github.com/ProjectZKM/Ziren#980997f64e258c706d280dd4f2d0c3829341a4f2" dependencies = [ "quote", "syn 1.0.109", @@ -13981,20 +13975,49 @@ dependencies = [ [[package]] name = "zkm-lib" version = "1.2.4" -source = "git+https://github.com/ProjectZKM/Ziren#980997f64e258c706d280dd4f2d0c3829341a4f2" dependencies = [ "bincode", "cfg-if", "elliptic-curve", "serde", "sha2 0.10.9", - "zkm-primitives", + "zkm-primitives 1.2.4", +] + +[[package]] +name = "zkm-lib" +version = "1.2.4" +source = "git+https://github.com/ProjectZKM/Ziren#d5b7577c683dfceeecb90325d3277d34dc52bf17" +dependencies = [ + "bincode", + "cfg-if", + "elliptic-curve", + "serde", + "sha2 0.10.9", + "zkm-primitives 1.2.4 (git+https://github.com/ProjectZKM/Ziren)", ] [[package]] name = "zkm-primitives" version = "1.2.4" -source = "git+https://github.com/ProjectZKM/Ziren#980997f64e258c706d280dd4f2d0c3829341a4f2" +dependencies = [ + "bincode", + "hex", + "lazy_static", + "num-bigint 0.4.6", + "p3-field", + "p3-koala-bear", + "p3-monty-31", + "p3-poseidon2", + "p3-symmetric", + "serde", + "sha2 0.10.9", +] + +[[package]] +name = "zkm-primitives" +version = "1.2.4" +source = "git+https://github.com/ProjectZKM/Ziren#d5b7577c683dfceeecb90325d3277d34dc52bf17" dependencies = [ "bincode", "hex", @@ -14012,7 +14035,6 @@ dependencies = [ [[package]] name = "zkm-prover" version = "1.2.4" -source = "git+https://github.com/ProjectZKM/Ziren#980997f64e258c706d280dd4f2d0c3829341a4f2" dependencies = [ "anyhow", "bincode", @@ -14033,13 +14055,13 @@ dependencies = [ "rayon", "serde", "serde_json", - "serial_test", + "sha2 0.10.9", "thiserror 1.0.69", "tracing", "tracing-subscriber 0.3.22", "zkm-core-executor", "zkm-core-machine", - "zkm-primitives", + "zkm-primitives 1.2.4", "zkm-recursion-circuit", "zkm-recursion-compiler", "zkm-recursion-core", @@ -14050,7 +14072,6 @@ dependencies = [ [[package]] name = "zkm-recursion-circuit" version = "1.2.4" -source = "git+https://github.com/ProjectZKM/Ziren#980997f64e258c706d280dd4f2d0c3829341a4f2" dependencies = [ "hashbrown 0.14.5", "itertools 0.13.0", @@ -14073,7 +14094,7 @@ dependencies = [ "zkm-core-executor", "zkm-core-machine", "zkm-derive", - "zkm-primitives", + "zkm-primitives 1.2.4", "zkm-recursion-compiler", "zkm-recursion-core", "zkm-recursion-gnark-ffi", @@ -14083,7 +14104,6 @@ dependencies = [ [[package]] name = "zkm-recursion-compiler" version = "1.2.4" -source = "git+https://github.com/ProjectZKM/Ziren#980997f64e258c706d280dd4f2d0c3829341a4f2" dependencies = [ "backtrace", "itertools 0.13.0", @@ -14095,7 +14115,7 @@ dependencies = [ "tracing", "vec_map", "zkm-core-machine", - "zkm-primitives", + "zkm-primitives 1.2.4", "zkm-recursion-core", "zkm-recursion-derive", "zkm-stark", @@ -14104,7 +14124,6 @@ dependencies = [ [[package]] name = "zkm-recursion-core" version = "1.2.4" -source = "git+https://github.com/ProjectZKM/Ziren#980997f64e258c706d280dd4f2d0c3829341a4f2" dependencies = [ "backtrace", "ff 0.13.1", @@ -14134,14 +14153,13 @@ dependencies = [ "zkhash", "zkm-core-machine", "zkm-derive", - "zkm-primitives", + "zkm-primitives 1.2.4", "zkm-stark", ] [[package]] name = "zkm-recursion-derive" version = "1.2.4" -source = "git+https://github.com/ProjectZKM/Ziren#980997f64e258c706d280dd4f2d0c3829341a4f2" dependencies = [ "quote", "syn 1.0.109", @@ -14150,7 +14168,6 @@ dependencies = [ [[package]] name = "zkm-recursion-gnark-ffi" version = "1.2.4" -source = "git+https://github.com/ProjectZKM/Ziren#980997f64e258c706d280dd4f2d0c3829341a4f2" dependencies = [ "anyhow", "bincode", @@ -14174,7 +14191,6 @@ dependencies = [ [[package]] name = "zkm-sdk" version = "1.2.4" -source = "git+https://github.com/ProjectZKM/Ziren#980997f64e258c706d280dd4f2d0c3829341a4f2" dependencies = [ "alloy-primitives", "alloy-signer 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -14213,7 +14229,7 @@ dependencies = [ "zkm-core-executor", "zkm-core-machine", "zkm-cuda", - "zkm-primitives", + "zkm-primitives 1.2.4", "zkm-prover", "zkm-stark", ] @@ -14221,7 +14237,6 @@ dependencies = [ [[package]] name = "zkm-stark" version = "1.2.4" -source = "git+https://github.com/ProjectZKM/Ziren#980997f64e258c706d280dd4f2d0c3829341a4f2" dependencies = [ "arrayref", "hashbrown 0.14.5", @@ -14256,14 +14271,13 @@ dependencies = [ "tracing-forest", "tracing-subscriber 0.3.22", "zkm-derive", - "zkm-primitives", - "zkm-zkvm", + "zkm-primitives 1.2.4", + "zkm-zkvm 1.2.4", ] [[package]] name = "zkm-verifier" version = "1.2.4" -source = "git+https://github.com/ProjectZKM/Ziren#980997f64e258c706d280dd4f2d0c3829341a4f2" dependencies = [ "anyhow", "ark-bn254", @@ -14289,12 +14303,27 @@ dependencies = [ "thiserror 2.0.18", "zkm-core-executor", "zkm-core-machine", - "zkm-primitives", + "zkm-primitives 1.2.4", "zkm-recursion-core", "zkm-sdk", "zkm-stark", ] +[[package]] +name = "zkm-zkvm" +version = "1.2.4" +dependencies = [ + "bincode", + "cfg-if", + "getrandom 0.2.17", + "lazy_static", + "rand 0.8.5", + "serde", + "sha2 0.10.9", + "zkm-lib 1.2.4", + "zkm-primitives 1.2.4", +] + [[package]] name = "zkm-zkvm" version = "1.2.4" @@ -14310,8 +14339,8 @@ dependencies = [ "rand 0.8.5", "serde", "sha2 0.10.9", - "zkm-lib", - "zkm-primitives", + "zkm-lib 1.2.4 (git+https://github.com/ProjectZKM/Ziren)", + "zkm-primitives 1.2.4 (git+https://github.com/ProjectZKM/Ziren)", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index df96280d..7b7ff885 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -174,4 +174,11 @@ rust.missing_debug_implementations = "warn" rust.unreachable_pub = "warn" rust.unused_must_use = "deny" rust.rust_2018_idioms = { level = "deny", priority = -1 } -rustdoc.all = "warn" \ No newline at end of file +rustdoc.all = "warn" + +[patch."https://github.com/ProjectZKM/Ziren"] +zkm-build = { path = "../zkm2/crates/build" } +zkm-core-executor = { path = "../zkm2/crates/core/executor" } +zkm-prover = { path = "../zkm2/crates/prover" } +zkm-sdk = { path = "../zkm2/crates/sdk" } +zkm-verifier = { path = "../zkm2/crates/verifier" } \ No newline at end of file diff --git a/circuits/README.md b/circuits/README.md index 43376730..f9afef1b 100644 --- a/circuits/README.md +++ b/circuits/README.md @@ -56,7 +56,7 @@ For case 2, > * If there is no Ziren upgrade during this interval, and the inputs of the proof aggregation are compressed proofs, but with different `start_pc`, `pc`, etc. > * If there is some Ziren upgrades during this interval, once we support the multiple verification keys in Ziren, this problem can be reduced to the former one. -With multiple proof recursions, we generate a Groth16 proof, and verify with `Groth16Verifier::verify(proof, zkm_public_values, zkm_vk_hash, groth16_vk)`. +With multiple proof recursions, we generate a Groth16 proof, and verify with `Groth16Verifier::verify(proof, zkm_public_values, zkm_vk_hash, snark_vk_meta, groth16_vk)`. ## Preparation diff --git a/circuits/commit-chain-proof/guest/Cargo.toml b/circuits/commit-chain-proof/guest/Cargo.toml index d83b9014..997f94a4 100644 --- a/circuits/commit-chain-proof/guest/Cargo.toml +++ b/circuits/commit-chain-proof/guest/Cargo.toml @@ -36,4 +36,8 @@ alloy-primitives-v1-1-0 = { git = "https://github.com/ziren-patches/core.git", p alloy-primitives-v1-1-2 = { git = "https://github.com/ziren-patches/core.git", package = "alloy-primitives", branch = "patch-alloy-primitives-1.1.2" } alloy-primitives-v1-4-1 = { git = "https://github.com/ziren-patches/core.git", package = "alloy-primitives", branch = "patch-alloy-primitives-1.4.1" } secp256k1-v0-29-1 = { git = "https://github.com/ziren-patches/rust-secp256k1", package = "secp256k1", branch = "patch-0.29.1" } -#secp256k1-v0-30-0 = { git = "https://github.com/ziren-patches/rust-secp256k1", package = "secp256k1", branch = "patch-0.30.0" } \ No newline at end of file +#secp256k1-v0-30-0 = { git = "https://github.com/ziren-patches/rust-secp256k1", package = "secp256k1", branch = "patch-0.30.0" } + +[patch."https://github.com/ProjectZKM/Ziren"] +zkm-zkvm = { path = "../../../../zkm2/crates/zkvm/entrypoint" } +zkm-verifier = { path = "../../../../zkm2/crates/verifier" } diff --git a/circuits/commit-chain-proof/host/src/lib.rs b/circuits/commit-chain-proof/host/src/lib.rs index 545e91df..31c52432 100644 --- a/circuits/commit-chain-proof/host/src/lib.rs +++ b/circuits/commit-chain-proof/host/src/lib.rs @@ -19,6 +19,35 @@ const COMMIT_CHAIN: &[u8] = include_elf!("guest"); use std::fs; use clap::Parser; +const ZKM_VERSION_BYTES_LEN: usize = 8; + +fn encode_zkm_version_fixed(version: &str) -> anyhow::Result<[u8; ZKM_VERSION_BYTES_LEN]> { + let raw = version.as_bytes(); + if raw.is_empty() { + anyhow::bail!("zkm_version is empty"); + } + if raw.len() > ZKM_VERSION_BYTES_LEN { + anyhow::bail!( + "zkm_version '{}' too long: {} > {}", + version, + raw.len(), + ZKM_VERSION_BYTES_LEN + ); + } + let mut encoded = [0u8; ZKM_VERSION_BYTES_LEN]; + encoded[..raw.len()].copy_from_slice(raw); + Ok(encoded) +} + +fn read_zkm_version_from_file(input_proof: &str) -> anyhow::Result<[u8; ZKM_VERSION_BYTES_LEN]> { + let zkm_version = String::from_utf8( + fs::read(format!("{input_proof}.zkm_version.bin")) + .context("Failed to read input zkm version file")?, + ) + .context("Invalid UTF-8 in input zkm version file")?; + encode_zkm_version_fixed(zkm_version.trim()) +} + /// The arguments for the cli. #[derive(Debug, Clone, Parser, serde::Deserialize, serde::Serialize)] pub struct Args { @@ -181,12 +210,15 @@ impl ProofBuilder for CommitChainProofBuilder { //let prev: CommitChainCircuitOutput = serde_json::from_slice(&public_inputs).unwrap(); Some(public_inputs) }; - let (prev_proof, zkm_proof, zkm_public_values, zkm_vk_hash) = match prev_receipt.clone() { + let (prev_proof, zkm_proof, zkm_public_values, zkm_vk_hash, zkm_version) = + match prev_receipt.clone() { Some(public_inputs) => { let proof_bytes = fs::read(input_proof).context("Failed to read input proof file")?; let zkm_vk_hash = fs::read(&format!("{}.vk_hash.bin", input_proof)).context("Read vk hash")?; + let zkm_version = read_zkm_version_from_file(input_proof) + .context("Failed to parse input zkm version")?; let prev_output: CommitChainCircuitOutput = zkm_sdk::ZKMPublicValues::from(&public_inputs).read(); ( @@ -194,13 +226,21 @@ impl ProofBuilder for CommitChainProofBuilder { proof_bytes, public_inputs, zkm_vk_hash.to_vec(), + zkm_version, ) } - None => (CommitChainPrevProofType::GenesisBlock, Vec::new(), Vec::new(), Vec::new()), + None => ( + CommitChainPrevProofType::GenesisBlock, + Vec::new(), + Vec::new(), + Vec::new(), + [0u8; ZKM_VERSION_BYTES_LEN], + ), }; let input: CommitChainCircuitInput = CommitChainCircuitInput { zkm_vk_hash, + zkm_version, zkm_proof, prev_proof, commits: commits.to_vec(), @@ -267,11 +307,14 @@ impl ProofBuilder for CommitChainProofBuilder { std::fs::write(&format!("{}", output_proof), proof.bytes())?; let public_value_hex = hex::encode(proof.public_values.to_vec()); let proof_size = proof.bytes().len(); + let zkm_version = proof.zkm_version.clone(); + encode_zkm_version_fixed(&zkm_version).context("Invalid zkm version for output proof")?; std::fs::write( &format!("{}.public_inputs.bin", output_proof), proof.public_values.to_vec(), )?; std::fs::write(&format!("{}.vk_hash.bin", output_proof), self.verifying_key.bytes32())?; + std::fs::write(&format!("{}.zkm_version.bin", output_proof), zkm_version)?; Ok((public_value_hex, proof_size)) } } diff --git a/circuits/header-chain-proof/guest/Cargo.toml b/circuits/header-chain-proof/guest/Cargo.toml index d12b95c5..5939724f 100644 --- a/circuits/header-chain-proof/guest/Cargo.toml +++ b/circuits/header-chain-proof/guest/Cargo.toml @@ -37,4 +37,8 @@ alloy-primitives-v1-0-0 = { git = "https://github.com/ziren-patches/core.git", p alloy-primitives-v1-1-0 = { git = "https://github.com/ziren-patches/core.git", package = "alloy-primitives", branch = "patch-alloy-primitives-1.1.0" } alloy-primitives-v1-1-2 = { git = "https://github.com/ziren-patches/core.git", package = "alloy-primitives", branch = "patch-alloy-primitives-1.1.2" } #secp256k1-v0-29-1 = { git = "https://github.com/ziren-patches/rust-secp256k1", package = "secp256k1", branch = "patch-0.29.1" } -#secp256k1-v0-30-0 = { git = "https://github.com/ziren-patches/rust-secp256k1", package = "secp256k1", branch = "patch-0.30.0" } \ No newline at end of file +#secp256k1-v0-30-0 = { git = "https://github.com/ziren-patches/rust-secp256k1", package = "secp256k1", branch = "patch-0.30.0" } + +[patch."https://github.com/ProjectZKM/Ziren"] +zkm-zkvm = { path = "../../../../zkm2/crates/zkvm/entrypoint" } +zkm-verifier = { path = "../../../../zkm2/crates/verifier" } diff --git a/circuits/header-chain-proof/host/src/lib.rs b/circuits/header-chain-proof/host/src/lib.rs index e415969a..1c325219 100644 --- a/circuits/header-chain-proof/host/src/lib.rs +++ b/circuits/header-chain-proof/host/src/lib.rs @@ -16,6 +16,35 @@ use anyhow::Context; use clap::Parser; use std::sync::OnceLock; +const ZKM_VERSION_BYTES_LEN: usize = 8; + +fn encode_zkm_version_fixed(version: &str) -> anyhow::Result<[u8; ZKM_VERSION_BYTES_LEN]> { + let raw = version.as_bytes(); + if raw.is_empty() { + anyhow::bail!("zkm_version is empty"); + } + if raw.len() > ZKM_VERSION_BYTES_LEN { + anyhow::bail!( + "zkm_version '{}' too long: {} > {}", + version, + raw.len(), + ZKM_VERSION_BYTES_LEN + ); + } + let mut encoded = [0u8; ZKM_VERSION_BYTES_LEN]; + encoded[..raw.len()].copy_from_slice(raw); + Ok(encoded) +} + +fn read_zkm_version_from_file(input_proof: &str) -> anyhow::Result<[u8; ZKM_VERSION_BYTES_LEN]> { + let zkm_version = String::from_utf8( + fs::read(format!("{input_proof}.zkm_version.bin")) + .context("Failed to read input zkm version file")?, + ) + .context("Invalid UTF-8 in input zkm version file")?; + encode_zkm_version_fixed(zkm_version.trim()) +} + /// The arguments for the cli. #[derive(Debug, Clone, Parser, serde::Deserialize, serde::Serialize)] pub struct Args { @@ -203,20 +232,30 @@ impl ProofBuilder for HeaderChainProofBuilder { Some(public_inputs) }; - let (prev_proof, zkm_proof, zkm_public_values, zkm_vk_hash) = match prev_receipt.clone() { + let (prev_proof, zkm_proof, zkm_public_values, zkm_vk_hash, zkm_version) = + match prev_receipt.clone() { Some(public_inputs) => { let proof_bytes = fs::read(input_proof).context("Failed to read input proof file").unwrap(); let zkm_vk_hash = fs::read(&format!("{}.vk_hash.bin", input_proof)).unwrap(); + let zkm_version = read_zkm_version_from_file(input_proof) + .context("Failed to parse input zkm version")?; let prev_output = zkm_sdk::ZKMPublicValues::from(&public_inputs).read(); ( HeaderChainPrevProofType::PrevProof(prev_output), proof_bytes, public_inputs, zkm_vk_hash.to_vec(), + zkm_version, ) } - None => (HeaderChainPrevProofType::GenesisBlock, Vec::new(), Vec::new(), Vec::new()), + None => ( + HeaderChainPrevProofType::GenesisBlock, + Vec::new(), + Vec::new(), + Vec::new(), + [0u8; ZKM_VERSION_BYTES_LEN], + ), }; tracing::info!( @@ -232,6 +271,7 @@ impl ProofBuilder for HeaderChainProofBuilder { zkm_proof, zkm_public_values, zkm_vk_hash, + zkm_version, block_headers, }; @@ -290,11 +330,14 @@ impl ProofBuilder for HeaderChainProofBuilder { std::fs::write(&format!("{}", output_proof), proof.bytes())?; let public_value_hex = hex::encode(proof.public_values.to_vec()); let proof_size = proof.bytes().len(); + let zkm_version = proof.zkm_version.clone(); + encode_zkm_version_fixed(&zkm_version).context("Invalid zkm version for output proof")?; std::fs::write( &format!("{}.public_inputs.bin", output_proof), proof.public_values.to_vec(), )?; std::fs::write(&format!("{}.vk_hash.bin", output_proof), self.verifying_key.bytes32())?; + std::fs::write(&format!("{}.zkm_version.bin", output_proof), zkm_version)?; tracing::info!("Generate proof successfully, proof: {:?}", proof); Ok((public_value_hex, proof_size)) diff --git a/circuits/operator-proof/guest/Cargo.toml b/circuits/operator-proof/guest/Cargo.toml index 519efdeb..83d9c98a 100644 --- a/circuits/operator-proof/guest/Cargo.toml +++ b/circuits/operator-proof/guest/Cargo.toml @@ -42,3 +42,7 @@ alloy-primitives-v1-4-1 = { git = "https://github.com/ziren-patches/core.git", p secp256k1-v0-29-1 = { git = "https://github.com/ziren-patches/rust-secp256k1", package = "secp256k1", branch = "patch-0.29.1" } #secp256k1-v0-30-0 = { git = "https://github.com/ziren-patches/rust-secp256k1", package = "secp256k1", branch = "patch-0.30.0" } #bitcoin = { git = "https://github.com/ProjectZKM/rust-bitcoin", branch = "patch-0.32.7" } + +[patch."https://github.com/ProjectZKM/Ziren"] +zkm-zkvm = { path = "../../../../zkm2/crates/zkvm/entrypoint" } +zkm-verifier = { path = "../../../../zkm2/crates/verifier" } diff --git a/circuits/operator-proof/host/src/lib.rs b/circuits/operator-proof/host/src/lib.rs index 0e63d730..a1b9bd2c 100644 --- a/circuits/operator-proof/host/src/lib.rs +++ b/circuits/operator-proof/host/src/lib.rs @@ -88,6 +88,34 @@ use std::fs; use sha2::{Digest, Sha256}; use std::sync::OnceLock; static ELF_ID: OnceLock = OnceLock::new(); +const ZKM_VERSION_BYTES_LEN: usize = 8; + +fn encode_zkm_version_fixed(version: &str) -> anyhow::Result<[u8; ZKM_VERSION_BYTES_LEN]> { + let raw = version.as_bytes(); + if raw.is_empty() { + anyhow::bail!("zkm_version is empty"); + } + if raw.len() > ZKM_VERSION_BYTES_LEN { + anyhow::bail!( + "zkm_version '{}' too long: {} > {}", + version, + raw.len(), + ZKM_VERSION_BYTES_LEN + ); + } + let mut encoded = [0u8; ZKM_VERSION_BYTES_LEN]; + encoded[..raw.len()].copy_from_slice(raw); + Ok(encoded) +} + +fn read_zkm_version_from_file(input_proof: &str) -> anyhow::Result<[u8; ZKM_VERSION_BYTES_LEN]> { + let zkm_version = String::from_utf8( + fs::read(format!("{input_proof}.zkm_version.bin")) + .context("Failed to read input zkm version file")?, + ) + .context("Invalid UTF-8 in input zkm version file")?; + encode_zkm_version_fixed(zkm_version.trim()) +} pub async fn fetch_target_block_and_watchtower_tx( esplora_url: &str, @@ -284,11 +312,14 @@ impl ProofBuilder for OperatorProofBuilder { .unwrap(); let zkm_vk_hash = fs::read(&format!("{}.vk_hash.bin", header_chain_input_proof)).unwrap(); + let zkm_version = read_zkm_version_from_file(header_chain_input_proof) + .context("Failed to parse header-chain zkm version")?; HeaderChainCircuitInput { prev_proof: HeaderChainPrevProofType::GenesisBlock, // unused zkm_proof, zkm_public_values, zkm_vk_hash, + zkm_version, block_headers: vec![], } }; @@ -302,11 +333,14 @@ impl ProofBuilder for OperatorProofBuilder { .unwrap(); let zkm_vk_hash = fs::read(&format!("{}.vk_hash.bin", commit_chain_input_proof)).unwrap(); + let zkm_version = read_zkm_version_from_file(commit_chain_input_proof) + .context("Failed to parse commit-chain zkm version")?; CommitChainCircuitInput { prev_proof: CommitChainPrevProofType::GenesisBlock, // unused zkm_proof, zkm_public_values, zkm_vk_hash, + zkm_version, commits: vec![], } }; @@ -320,11 +354,14 @@ impl ProofBuilder for OperatorProofBuilder { fs::read(&format!("{}.public_inputs.bin", state_chain_input_proof)).unwrap(); let zkm_vk_hash = fs::read(&format!("{}.vk_hash.bin", state_chain_input_proof)).unwrap(); + let zkm_version = read_zkm_version_from_file(state_chain_input_proof) + .context("Failed to parse state-chain zkm version")?; StateChainCircuitInput { prev_proof: StateChainPrevProofType::GenesisBlock, // unused zkm_proof, zkm_public_values, zkm_vk_hash, + zkm_version, blocks: vec![], } }; @@ -426,7 +463,10 @@ impl ProofBuilder for OperatorProofBuilder { }; let public_value_hex = hex::encode(proof.public_values.to_vec()); let proof_size = proof.bytes().len(); + let zkm_version = proof.zkm_version.clone(); + encode_zkm_version_fixed(&zkm_version).context("Invalid zkm version for output proof")?; std::fs::write(&format!("{}.vk_hash.bin", output), self.verifying_key.bytes32())?; + std::fs::write(&format!("{}.zkm_version.bin", output), zkm_version)?; let proof = bincode::serialize(&proof).unwrap(); std::fs::write(&format!("{}", output), proof)?; Ok((public_value_hex, proof_size)) @@ -439,7 +479,7 @@ mod tests { use ark_bn254::Bn254; use ark_groth16::{Groth16, r1cs_to_qap::LibsnarkReduction}; - use zkm_verifier::{GROTH16_VK_BYTES, convert_ark}; + use zkm_verifier::{GROTH16_VK_BYTES, convert_ark, get_snark_vk_meta}; #[tokio::test] #[ignore = "local test"] @@ -460,7 +500,8 @@ mod tests { let groth16_vk = &GROTH16_VK_BYTES; let vk_hash = String::from_utf8(vk_bytes).unwrap(); - let ark_proof = convert_ark(&proof, &vk_hash, groth16_vk).unwrap(); + let snark_vk_meta = get_snark_vk_meta(&proof.zkm_version).unwrap(); + let ark_proof = convert_ark(&proof, &vk_hash, &snark_vk_meta, groth16_vk).unwrap(); // Verify the arkworks proof. let ok = Groth16::::verify_proof( diff --git a/circuits/proof-builder/src/lib.rs b/circuits/proof-builder/src/lib.rs index f14a7c50..f11b106d 100644 --- a/circuits/proof-builder/src/lib.rs +++ b/circuits/proof-builder/src/lib.rs @@ -205,6 +205,7 @@ pub struct ProofData { pub proof: Vec, pub vk: String, pub public_inputs: Vec, + pub zkm_version: String, } impl ProofData { @@ -222,6 +223,10 @@ impl ProofData { proof_data.vk = String::from_utf8(fs::read(format!("{path}.vk_hash.bin")).unwrap_or_default()) .unwrap_or_default(); + proof_data.zkm_version = String::from_utf8( + fs::read(format!("{path}.zkm_version.bin")).unwrap_or_default(), + ) + .unwrap_or_default(); } } proof_data diff --git a/circuits/state-chain-proof/guest/Cargo.toml b/circuits/state-chain-proof/guest/Cargo.toml index 3e17dffe..34eb058a 100644 --- a/circuits/state-chain-proof/guest/Cargo.toml +++ b/circuits/state-chain-proof/guest/Cargo.toml @@ -34,4 +34,8 @@ alloy-primitives-v1-1-0 = { git = "https://github.com/ziren-patches/core.git", p alloy-primitives-v1-1-2 = { git = "https://github.com/ziren-patches/core.git", package = "alloy-primitives", branch = "patch-alloy-primitives-1.1.2" } alloy-primitives-v1-4-1 = { git = "https://github.com/ziren-patches/core.git", package = "alloy-primitives", branch = "patch-alloy-primitives-1.4.1" } secp256k1-v0-29-1 = { git = "https://github.com/ziren-patches/rust-secp256k1", package = "secp256k1", branch = "patch-0.29.1" } -#secp256k1-v0-30-0 = { git = "https://github.com/ziren-patches/rust-secp256k1", package = "secp256k1", branch = "patch-0.30.0" } \ No newline at end of file +#secp256k1-v0-30-0 = { git = "https://github.com/ziren-patches/rust-secp256k1", package = "secp256k1", branch = "patch-0.30.0" } + +[patch."https://github.com/ProjectZKM/Ziren"] +zkm-zkvm = { path = "../../../../zkm2/crates/zkvm/entrypoint" } +zkm-verifier = { path = "../../../../zkm2/crates/verifier" } diff --git a/circuits/state-chain-proof/host/src/lib.rs b/circuits/state-chain-proof/host/src/lib.rs index f52e8bc6..ff7e0c60 100644 --- a/circuits/state-chain-proof/host/src/lib.rs +++ b/circuits/state-chain-proof/host/src/lib.rs @@ -32,6 +32,35 @@ const STATE_CHAIN: &[u8] = include_elf!("guest"); use std::fs; use clap::Parser; +const ZKM_VERSION_BYTES_LEN: usize = 8; + +fn encode_zkm_version_fixed(version: &str) -> anyhow::Result<[u8; ZKM_VERSION_BYTES_LEN]> { + let raw = version.as_bytes(); + if raw.is_empty() { + anyhow::bail!("zkm_version is empty"); + } + if raw.len() > ZKM_VERSION_BYTES_LEN { + anyhow::bail!( + "zkm_version '{}' too long: {} > {}", + version, + raw.len(), + ZKM_VERSION_BYTES_LEN + ); + } + let mut encoded = [0u8; ZKM_VERSION_BYTES_LEN]; + encoded[..raw.len()].copy_from_slice(raw); + Ok(encoded) +} + +fn read_zkm_version_from_file(input_proof: &str) -> anyhow::Result<[u8; ZKM_VERSION_BYTES_LEN]> { + let zkm_version = String::from_utf8( + fs::read(format!("{input_proof}.zkm_version.bin")) + .context("Failed to read input zkm version file")?, + ) + .context("Invalid UTF-8 in input zkm version file")?; + encode_zkm_version_fixed(zkm_version.trim()) +} + /// The arguments for the cli. #[derive(Debug, Clone, Parser, serde::Deserialize, serde::Serialize)] pub struct Args { @@ -317,12 +346,15 @@ impl ProofBuilder for StateChainProofBuilder { Some(public_inputs) }; - let (prev_proof, zkm_proof, zkm_public_values, zkm_vk_hash) = match prev_receipt.clone() { + let (prev_proof, zkm_proof, zkm_public_values, zkm_vk_hash, zkm_version) = + match prev_receipt.clone() { Some(public_inputs) => { let proof_bytes = fs::read(input_proof).context("Failed to read input proof file")?; let zkm_vk_hash = fs::read(&format!("{}.vk_hash.bin", input_proof)).context("Read vk_hash")?; + let zkm_version = read_zkm_version_from_file(input_proof) + .context("Failed to parse input zkm version")?; let prev_output: StateChainCircuitOutput = zkm_sdk::ZKMPublicValues::from(&public_inputs).read(); ( @@ -330,9 +362,16 @@ impl ProofBuilder for StateChainProofBuilder { proof_bytes, public_inputs, zkm_vk_hash.to_vec(), + zkm_version, ) } - None => (StateChainPrevProofType::GenesisBlock, Vec::new(), Vec::new(), Vec::new()), + None => ( + StateChainPrevProofType::GenesisBlock, + Vec::new(), + Vec::new(), + Vec::new(), + [0u8; ZKM_VERSION_BYTES_LEN], + ), }; let input: StateChainCircuitInput = StateChainCircuitInput { @@ -340,6 +379,7 @@ impl ProofBuilder for StateChainProofBuilder { zkm_proof, zkm_public_values, zkm_vk_hash, + zkm_version, blocks: blocks.clone(), }; // Generate the proofs. @@ -390,11 +430,14 @@ impl ProofBuilder for StateChainProofBuilder { std::fs::write(&format!("{}", output_proof), proof.bytes())?; let public_value_hex = hex::encode(proof.public_values.to_vec()); let proof_size = proof.bytes().len(); + let zkm_version = proof.zkm_version.clone(); + encode_zkm_version_fixed(&zkm_version).context("Invalid zkm version for output proof")?; std::fs::write( &format!("{}.public_inputs.bin", output_proof), proof.public_values.to_vec(), )?; std::fs::write(&format!("{}.vk_hash.bin", output_proof), self.verifying_key.bytes32())?; + std::fs::write(&format!("{}.zkm_version.bin", output_proof), zkm_version)?; tracing::info!("Generate proof successfully, proof: {:?}", proof); Ok((public_value_hex, proof_size)) diff --git a/circuits/watchtower-proof/guest/Cargo.toml b/circuits/watchtower-proof/guest/Cargo.toml index 2db98cac..88c0baee 100644 --- a/circuits/watchtower-proof/guest/Cargo.toml +++ b/circuits/watchtower-proof/guest/Cargo.toml @@ -42,3 +42,7 @@ alloy-primitives-v1-4-1 = { git = "https://github.com/ziren-patches/core.git", p secp256k1-v0-29-1 = { git = "https://github.com/ziren-patches/rust-secp256k1", package = "secp256k1", branch = "patch-0.29.1" } #secp256k1-v0-30-0 = { git = "https://github.com/ziren-patches/rust-secp256k1", package = "secp256k1", branch = "patch-0.30.0" } #bitcoin = { git = "https://github.com/ProjectZKM/rust-bitcoin", branch = "patch-0.32.7" } + +[patch."https://github.com/ProjectZKM/Ziren"] +zkm-zkvm = { path = "../../../../zkm2/crates/zkvm/entrypoint" } +zkm-verifier = { path = "../../../../zkm2/crates/verifier" } diff --git a/circuits/watchtower-proof/host/src/lib.rs b/circuits/watchtower-proof/host/src/lib.rs index 114a444d..8e02d1d1 100644 --- a/circuits/watchtower-proof/host/src/lib.rs +++ b/circuits/watchtower-proof/host/src/lib.rs @@ -21,6 +21,35 @@ use proof_builder::{LongRunning, ProofBuilder, ProofRequest}; use clap::Parser; use std::fs; +const ZKM_VERSION_BYTES_LEN: usize = 8; + +fn encode_zkm_version_fixed(version: &str) -> anyhow::Result<[u8; ZKM_VERSION_BYTES_LEN]> { + let raw = version.as_bytes(); + if raw.is_empty() { + anyhow::bail!("zkm_version is empty"); + } + if raw.len() > ZKM_VERSION_BYTES_LEN { + anyhow::bail!( + "zkm_version '{}' too long: {} > {}", + version, + raw.len(), + ZKM_VERSION_BYTES_LEN + ); + } + let mut encoded = [0u8; ZKM_VERSION_BYTES_LEN]; + encoded[..raw.len()].copy_from_slice(raw); + Ok(encoded) +} + +fn read_zkm_version_from_file(input_proof: &str) -> anyhow::Result<[u8; ZKM_VERSION_BYTES_LEN]> { + let zkm_version = String::from_utf8( + fs::read(format!("{input_proof}.zkm_version.bin")) + .context("Failed to read input zkm version file")?, + ) + .context("Invalid UTF-8 in input zkm version file")?; + encode_zkm_version_fixed(zkm_version.trim()) +} + // The arguments for the cli. #[derive(Debug, Clone, Parser, serde::Deserialize, serde::Serialize)] pub struct Args { @@ -140,12 +169,15 @@ impl ProofBuilder for WatchtowerProofBuilder { .unwrap(); let zkm_vk_hash = fs::read(&format!("{}.vk_hash.bin", header_chain_input_proof)).unwrap(); + let zkm_version = read_zkm_version_from_file(header_chain_input_proof) + .context("Failed to parse header-chain zkm version")?; HeaderChainCircuitInput { prev_proof: HeaderChainPrevProofType::GenesisBlock, // unused zkm_proof, zkm_public_values, zkm_vk_hash, + zkm_version, block_headers: vec![], } }; @@ -159,11 +191,14 @@ impl ProofBuilder for WatchtowerProofBuilder { .unwrap(); let zkm_vk_hash = fs::read(&format!("{}.vk_hash.bin", commit_chain_input_proof)).unwrap(); + let zkm_version = read_zkm_version_from_file(commit_chain_input_proof) + .context("Failed to parse commit-chain zkm version")?; CommitChainCircuitInput { prev_proof: CommitChainPrevProofType::GenesisBlock, // unused zkm_proof, zkm_public_values, zkm_vk_hash, + zkm_version, commits: vec![], } }; @@ -177,11 +212,14 @@ impl ProofBuilder for WatchtowerProofBuilder { fs::read(&format!("{}.public_inputs.bin", state_chain_input_proof)).unwrap(); let zkm_vk_hash = fs::read(&format!("{}.vk_hash.bin", state_chain_input_proof)).unwrap(); + let zkm_version = read_zkm_version_from_file(state_chain_input_proof) + .context("Failed to parse state-chain zkm version")?; StateChainCircuitInput { prev_proof: StateChainPrevProofType::GenesisBlock, // unused zkm_proof, zkm_public_values, zkm_vk_hash, + zkm_version, blocks: vec![], } }; @@ -263,8 +301,11 @@ impl ProofBuilder for WatchtowerProofBuilder { std::fs::write(&format!("{}", output), proof.bytes())?; let public_value_hex = hex::encode(proof.public_values.to_vec()); let proof_size = proof.bytes().len(); + let zkm_version = proof.zkm_version.clone(); + encode_zkm_version_fixed(&zkm_version).context("Invalid zkm version for output proof")?; std::fs::write(&format!("{}.public_inputs.bin", output), proof.public_values.to_vec())?; std::fs::write(&format!("{}.vk_hash.bin", output), self.verifying_key.bytes32())?; + std::fs::write(&format!("{}.zkm_version.bin", output), zkm_version)?; Ok((public_value_hex, proof_size)) } } diff --git a/crates/bitcoin-light-client-circuit/src/lib.rs b/crates/bitcoin-light-client-circuit/src/lib.rs index 59b5f78a..8cf10694 100644 --- a/crates/bitcoin-light-client-circuit/src/lib.rs +++ b/crates/bitcoin-light-client-circuit/src/lib.rs @@ -19,7 +19,7 @@ use header_chain::{ }; use state_chain::{StateChainCircuitInput, StateChainPrevProofType}; use zkm_primitives::io::ZKMPublicValues; -use zkm_verifier::Groth16Verifier; +use zkm_verifier::{Groth16Verifier, get_snark_vk_meta}; use bitcoin::{ScriptBuf, TxOut, Txid, secp256k1::PublicKey}; pub use guest_executor::io::EthClientExecutorInput; @@ -28,11 +28,42 @@ pub const GRAPH_ID_SIZE: usize = 16; pub const PROOF_SIZE: usize = 260; pub const PUBLIC_INPUTS_SIZE: usize = 36; pub const VK_HASH_SIZE: usize = 66; -pub const COMMITMENT_SIZE: usize = GRAPH_ID_SIZE + PROOF_SIZE + PUBLIC_INPUTS_SIZE + VK_HASH_SIZE; +pub const ZKM_VERSION_SIZE: usize = 8; +pub const COMMITMENT_SIZE: usize = + GRAPH_ID_SIZE + PROOF_SIZE + PUBLIC_INPUTS_SIZE + VK_HASH_SIZE + ZKM_VERSION_SIZE; pub const TOTAL_WORK_SIZE: usize = 32; pub const CONSENSUS_BLOCK_HEIGHT_SIZE: usize = 4; +fn encode_zkm_version_fixed(zkm_version: &str) -> Result<[u8; ZKM_VERSION_SIZE], String> { + let raw = zkm_version.as_bytes(); + if raw.is_empty() { + return Err("zkm_version is empty".to_string()); + } + if raw.len() > ZKM_VERSION_SIZE { + return Err(format!( + "zkm_version '{}' too long: {} > {}", + zkm_version, + raw.len(), + ZKM_VERSION_SIZE + )); + } + let mut encoded = [0u8; ZKM_VERSION_SIZE]; + encoded[..raw.len()].copy_from_slice(raw); + Ok(encoded) +} + +fn decode_zkm_version_fixed(zkm_version: &[u8; ZKM_VERSION_SIZE]) -> Result { + let end = zkm_version + .iter() + .position(|b| *b == 0) + .unwrap_or(zkm_version.len()); + if end == 0 { + return Err("zkm_version is empty".to_string()); + } + String::from_utf8(zkm_version[..end].to_vec()).map_err(|e| format!("invalid zkm_version: {e}")) +} + pub fn watch_longest_chain( genesis_sequencer_commit_txid: [u8; 32], latest_sequencer_commit_txid: [u8; 32], @@ -50,6 +81,7 @@ pub fn watch_longest_chain( &commit_chain.zkm_proof, &commit_chain.zkm_public_values, &commit_chain.zkm_vk_hash, + &commit_chain.zkm_version, ) .expect("Failed to verify commit chain proof"); @@ -71,6 +103,7 @@ pub fn watch_longest_chain( &header_chain.zkm_proof, &header_chain.zkm_public_values, &header_chain.zkm_vk_hash, + &header_chain.zkm_version, ) .expect("Failed to verify header chain proof"); @@ -83,8 +116,13 @@ pub fn watch_longest_chain( println!("SPV"); assert!(spv.verify(&btc_header_chain_output.chain_state.block_hashes_mmr)); - verify_proof(&state_chain.zkm_proof, &state_chain.zkm_public_values, &state_chain.zkm_vk_hash) - .expect("Failed to verify state chain proof"); + verify_proof( + &state_chain.zkm_proof, + &state_chain.zkm_public_values, + &state_chain.zkm_vk_hash, + &state_chain.zkm_version, + ) + .expect("Failed to verify state chain proof"); let prev_output = ZKMPublicValues::from(&state_chain.zkm_public_values).read(); let prev_proof = StateChainPrevProofType::PrevProof(prev_output); let StateChainPrevProofType::PrevProof(state_chain_output) = &prev_proof else { @@ -158,6 +196,7 @@ pub fn propose_longest_chain( &commit_chain.zkm_proof, &commit_chain.zkm_public_values, &commit_chain.zkm_vk_hash, + &commit_chain.zkm_version, ) .expect("Failed to verify commit chain proof"); let prev_output = ZKMPublicValues::from(&commit_chain.zkm_public_values).read(); @@ -180,6 +219,7 @@ pub fn propose_longest_chain( &operator_header_chain.zkm_proof, &operator_header_chain.zkm_public_values, &operator_header_chain.zkm_vk_hash, + &operator_header_chain.zkm_version, ) .expect("Failed to verify header chain proof"); let prev_output = ZKMPublicValues::from(&operator_header_chain.zkm_public_values).read(); @@ -235,6 +275,7 @@ pub fn propose_longest_chain( proof, public_values, vk, + watchtower_zkm_version, watchtower_total_work, watchtower_consensus_block_height, ) = match parse_watchtower_commitment(commitment) { @@ -245,7 +286,7 @@ pub fn propose_longest_chain( } }; - match verify_proof(&proof, &public_values, &vk) { + match verify_proof(&proof, &public_values, &vk, &watchtower_zkm_version) { Ok(_) => {} Err(err) => { println!("Watchtower[{i}] invalid proof: {err}"); @@ -288,8 +329,13 @@ pub fn propose_longest_chain( println!("verify el block"); - verify_proof(&state_chain.zkm_proof, &state_chain.zkm_public_values, &state_chain.zkm_vk_hash) - .expect("Failed to verify state chain proof"); + verify_proof( + &state_chain.zkm_proof, + &state_chain.zkm_public_values, + &state_chain.zkm_vk_hash, + &state_chain.zkm_version, + ) + .expect("Failed to verify state chain proof"); let prev_output = ZKMPublicValues::from(&state_chain.zkm_public_values).read(); let prev_proof = StateChainPrevProofType::PrevProof(prev_output); @@ -430,13 +476,22 @@ pub fn build_watchtower_commitment( proof: &[u8; PROOF_SIZE], public_inputs: &[u8; PUBLIC_INPUTS_SIZE], vk_hash: &str, -) -> Vec { + zkm_version: &str, +) -> Result, String> { let mut comm = graph_id.to_vec(); comm.extend_from_slice(proof); comm.extend_from_slice(public_inputs); - assert_eq!(vk_hash.len(), VK_HASH_SIZE); + if vk_hash.len() != VK_HASH_SIZE { + return Err(format!( + "invalid vk_hash length: {}, expected {}", + vk_hash.len(), + VK_HASH_SIZE + )); + } comm.extend_from_slice(vk_hash.as_bytes()); - comm + let zkm_version = encode_zkm_version_fixed(zkm_version)?; + comm.extend_from_slice(&zkm_version); + Ok(comm) } pub type WatchtowerCommitmentResult = ( @@ -444,6 +499,7 @@ pub type WatchtowerCommitmentResult = ( [u8; PROOF_SIZE], [u8; PUBLIC_INPUTS_SIZE], [u8; VK_HASH_SIZE], + [u8; ZKM_VERSION_SIZE], [u8; TOTAL_WORK_SIZE], [u8; CONSENSUS_BLOCK_HEIGHT_SIZE], ); @@ -472,6 +528,10 @@ pub fn parse_watchtower_commitment( let mut zkm_vk_hash_bytes = [0u8; VK_HASH_SIZE]; zkm_vk_hash_bytes.copy_from_slice(&commitment[end..end + VK_HASH_SIZE]); + end += VK_HASH_SIZE; + + let mut zkm_version = [0u8; ZKM_VERSION_SIZE]; + zkm_version.copy_from_slice(&commitment[end..end + ZKM_VERSION_SIZE]); // extract ChainState let mut watchtower_total_work = [0u8; TOTAL_WORK_SIZE]; @@ -494,6 +554,7 @@ pub fn parse_watchtower_commitment( proof, zkm_public_values, zkm_vk_hash_bytes, + zkm_version, watchtower_total_work, watchtower_consensus_block_height, )) @@ -504,10 +565,13 @@ pub fn verify_proof( proof: &[u8], zkm_public_values: &[u8], zkm_vk_hash: &[u8], + zkm_version: &[u8; ZKM_VERSION_SIZE], ) -> Result<(), String> { let groth16_vk = *zkm_verifier::GROTH16_VK_BYTES; let zkm_vk_hash = String::from_utf8(zkm_vk_hash.to_vec()).map_err(|e| e.to_string())?; - match Groth16Verifier::verify(proof, zkm_public_values, &zkm_vk_hash, groth16_vk) { + let zkm_version = decode_zkm_version_fixed(zkm_version)?; + let snark_vk_meta = get_snark_vk_meta(&zkm_version).map_err(|e| e.to_string())?; + match Groth16Verifier::verify(proof, zkm_public_values, &zkm_vk_hash, &snark_vk_meta, groth16_vk) { Ok(_) => Ok(()), Err(err) => Err(format!("Verify Groth16 proof, err: {err:?}")), } @@ -521,6 +585,7 @@ mod tests { const PUBLIC_INPUTS: &[u8] = include_bytes!("../../../circuits/data/watchtower/output3.bin.public_inputs.bin"); const VK_HASH: &str = include_str!("../../../circuits/data/watchtower/output3.bin.vk_hash.bin"); + const ZKM_VERSION: &str = "v1.2.4"; #[test] fn test_build_watchtower_commitment() { @@ -535,7 +600,9 @@ mod tests { &PROOF.try_into().unwrap(), &PUBLIC_INPUTS.try_into().unwrap(), VK_HASH, - ); + ZKM_VERSION, + ) + .unwrap(); println!("comm: {:?}", comm.len()); println!("comm hex: {:?}", hex::encode(&comm)); @@ -546,8 +613,9 @@ mod tests { assert_eq!(expected.1, PROOF); assert_eq!(expected.2, PUBLIC_INPUTS); assert_eq!(expected.3, VK_HASH.as_bytes()); - assert_eq!(expected.4, U256::from(total_work).to_be_bytes()); - assert_eq!(expected.5, U32::from(block_height).to_le_bytes()); + assert_eq!(expected.4, encode_zkm_version_fixed(ZKM_VERSION).unwrap()); + assert_eq!(expected.5, U256::from(total_work).to_be_bytes()); + assert_eq!(expected.6, U32::from(block_height).to_le_bytes()); } #[test] @@ -590,14 +658,23 @@ mod tests { let tx: Transaction = deserialize(&bytes).unwrap(); let commitment = extract_data_from_commitment_outputs(&tx.output); - let ( - parsed_graph_id, - _proof, - _public_values, - _vk, - _watchtower_total_work, - _watchtower_consensus_block_height, - ) = parse_watchtower_commitment(&commitment).unwrap(); - assert_eq!(hex::encode(parsed_graph_id), "9bf28a9ccba44a0cbdd17ce6bb8262a1"); + let parse_result = parse_watchtower_commitment(&commitment); + assert!(parse_result.is_err(), "legacy commitment without version should fail"); + } + + #[test] + fn test_build_watchtower_commitment_rejects_long_version() { + let graph_id = hex::decode("00112233445566778899aabbccddeeff") + .unwrap() + .try_into() + .unwrap(); + let result = build_watchtower_commitment( + &graph_id, + &PROOF.try_into().unwrap(), + &PUBLIC_INPUTS.try_into().unwrap(), + VK_HASH, + "v123456789", + ); + assert!(result.is_err()); } } diff --git a/crates/bitvm2-ga/src/tests.rs b/crates/bitvm2-ga/src/tests.rs index c5dc119a..97d48c81 100644 --- a/crates/bitvm2-ga/src/tests.rs +++ b/crates/bitvm2-ga/src/tests.rs @@ -1008,9 +1008,11 @@ mod tests { &PROOF.try_into().unwrap(), &PUBLIC_INPUTS.try_into().unwrap(), VK_HASH, + "v1.2.4", //total_work, //consensus_commit_block_height, - ); + ) + .unwrap(); let mut watchtower_0_challenge = build_watchtower_challenge_tx( &graph, diff --git a/crates/commit-chain/src/commit_chain.rs b/crates/commit-chain/src/commit_chain.rs index d66fee85..43b01a65 100644 --- a/crates/commit-chain/src/commit_chain.rs +++ b/crates/commit-chain/src/commit_chain.rs @@ -86,6 +86,7 @@ pub struct CommitChainState { pub const PROOF_SIZE: usize = 260; pub const PUBLIC_INPUTS_SIZE: usize = 36; pub const VK_HASH_SIZE: usize = 66; +pub const ZKM_VERSION_SIZE: usize = 8; #[derive(Serialize, Deserialize, PartialEq, Clone, Debug)] pub struct CommitChainCircuitOutput { @@ -98,6 +99,7 @@ pub struct CommitChainCircuitInput { pub zkm_proof: Vec, pub zkm_public_values: Vec, pub zkm_vk_hash: Vec, + pub zkm_version: [u8; ZKM_VERSION_SIZE], pub commits: Vec, } diff --git a/crates/commit-chain/src/lib.rs b/crates/commit-chain/src/lib.rs index 079aa141..83d281d6 100644 --- a/crates/commit-chain/src/lib.rs +++ b/crates/commit-chain/src/lib.rs @@ -2,7 +2,15 @@ mod publisher; pub use publisher::*; mod commit_chain; pub use commit_chain::*; -use zkm_verifier::Groth16Verifier; +use zkm_verifier::{Groth16Verifier, get_snark_vk_meta}; + +fn decode_zkm_version(version: &[u8; ZKM_VERSION_SIZE]) -> Result { + let end = version.iter().position(|b| *b == 0).unwrap_or(version.len()); + if end == 0 { + return Err("zkm_version is empty".to_string()); + } + String::from_utf8(version[..end].to_vec()).map_err(|e| format!("invalid zkm_version: {e}")) +} pub fn commit_chain_circuit(input: CommitChainCircuitInput) -> CommitChainCircuitOutput { let mut chain_state = match input.prev_proof { @@ -13,10 +21,13 @@ pub fn commit_chain_circuit(input: CommitChainCircuitInput) -> CommitChainCircui println!("verify commit chain of prev proof"); let groth16_vk = *zkm_verifier::GROTH16_VK_BYTES; let zkm_vk_hash = String::from_utf8(input.zkm_vk_hash.to_vec()).unwrap(); + let zkm_version = decode_zkm_version(&input.zkm_version).unwrap(); + let snark_vk_meta = get_snark_vk_meta(&zkm_version).unwrap(); Groth16Verifier::verify( &input.zkm_proof, &input.zkm_public_values, &zkm_vk_hash, + &snark_vk_meta, groth16_vk, ) .unwrap(); diff --git a/crates/header-chain/src/header_chain.rs b/crates/header-chain/src/header_chain.rs index 473fad16..204031a4 100644 --- a/crates/header-chain/src/header_chain.rs +++ b/crates/header-chain/src/header_chain.rs @@ -91,6 +91,8 @@ pub const NETWORK_CONSTANTS: NetworkConstants = { } }; +pub const ZKM_VERSION_SIZE: usize = 8; + /// An epoch should be two weeks (represented as number of seconds) /// seconds/minute * minutes/hour * hours/day * 14 days const EXPECTED_EPOCH_TIMESPAN: u32 = 60 * 60 * 24 * 14; @@ -379,6 +381,7 @@ pub struct HeaderChainCircuitInput { pub zkm_proof: Vec, pub zkm_public_values: Vec, pub zkm_vk_hash: Vec, + pub zkm_version: [u8; ZKM_VERSION_SIZE], pub prev_proof: HeaderChainPrevProofType, pub block_headers: Vec, } diff --git a/crates/header-chain/src/lib.rs b/crates/header-chain/src/lib.rs index 7d995b64..10a01944 100644 --- a/crates/header-chain/src/lib.rs +++ b/crates/header-chain/src/lib.rs @@ -12,7 +12,15 @@ pub use transaction::*; pub mod spv; pub use spv::SPV; -use zkm_verifier::Groth16Verifier; +use zkm_verifier::{Groth16Verifier, get_snark_vk_meta}; + +fn decode_zkm_version(version: &[u8; ZKM_VERSION_SIZE]) -> Result { + let end = version.iter().position(|b| *b == 0).unwrap_or(version.len()); + if end == 0 { + return Err("zkm_version is empty".to_string()); + } + String::from_utf8(version[..end].to_vec()).map_err(|e| format!("invalid zkm_version: {e}")) +} /// The main entry point of the header chain circuit. pub fn header_chain_circuit(input: HeaderChainCircuitInput) -> BlockHeaderCircuitOutput { @@ -24,10 +32,13 @@ pub fn header_chain_circuit(input: HeaderChainCircuitInput) -> BlockHeaderCircui println!("verify header chain of prev proof"); let groth16_vk = *zkm_verifier::GROTH16_VK_BYTES; let zkm_vk_hash = String::from_utf8(input.zkm_vk_hash.to_vec()).unwrap(); + let zkm_version = decode_zkm_version(&input.zkm_version).unwrap(); + let snark_vk_meta = get_snark_vk_meta(&zkm_version).unwrap(); Groth16Verifier::verify( &input.zkm_proof, &input.zkm_public_values, &zkm_vk_hash, + &snark_vk_meta, groth16_vk, ) .unwrap(); diff --git a/crates/state-chain/src/lib.rs b/crates/state-chain/src/lib.rs index a21c185b..80926a48 100644 --- a/crates/state-chain/src/lib.rs +++ b/crates/state-chain/src/lib.rs @@ -3,7 +3,15 @@ mod state_chain; pub use cbft::*; pub use state_chain::*; -use zkm_verifier::Groth16Verifier; +use zkm_verifier::{Groth16Verifier, get_snark_vk_meta}; + +fn decode_zkm_version(version: &[u8; ZKM_VERSION_SIZE]) -> Result { + let end = version.iter().position(|b| *b == 0).unwrap_or(version.len()); + if end == 0 { + return Err("zkm_version is empty".to_string()); + } + String::from_utf8(version[..end].to_vec()).map_err(|e| format!("invalid zkm_version: {e}")) +} pub fn state_chain_circuit(input: StateChainCircuitInput) -> StateChainCircuitOutput { let mut chain_state = match input.prev_proof { @@ -17,10 +25,13 @@ pub fn state_chain_circuit(input: StateChainCircuitInput) -> StateChainCircuitOu println!("verify state chain of prev proof"); let groth16_vk = *zkm_verifier::GROTH16_VK_BYTES; let zkm_vk_hash = String::from_utf8(input.zkm_vk_hash.to_vec()).unwrap(); + let zkm_version = decode_zkm_version(&input.zkm_version).unwrap(); + let snark_vk_meta = get_snark_vk_meta(&zkm_version).unwrap(); Groth16Verifier::verify( &input.zkm_proof, &input.zkm_public_values, &zkm_vk_hash, + &snark_vk_meta, groth16_vk, ) .unwrap(); diff --git a/crates/state-chain/src/state_chain.rs b/crates/state-chain/src/state_chain.rs index b5b8b5f9..40fa5e33 100644 --- a/crates/state-chain/src/state_chain.rs +++ b/crates/state-chain/src/state_chain.rs @@ -10,6 +10,7 @@ use tendermint_light_client_verifier::types::LightBlock; // Contract address, base slot and key, the expected value of the slot is hardcoded to 1. type WithdrawalSlot = (Address, [u8; 32], Vec<[u8; 16]>); +pub const ZKM_VERSION_SIZE: usize = 8; /// The input proof of the commit chain circuit. /// The proof can be either None (implying the beginning) or a Succinct proof. @@ -49,6 +50,7 @@ pub struct StateChainCircuitInput { pub zkm_proof: Vec, pub zkm_public_values: Vec, pub zkm_vk_hash: Vec, + pub zkm_version: [u8; ZKM_VERSION_SIZE], pub prev_proof: StateChainPrevProofType, pub blocks: Vec, } diff --git a/node/src/utils.rs b/node/src/utils.rs index 5968d535..e0daa1a7 100644 --- a/node/src/utils.rs +++ b/node/src/utils.rs @@ -71,7 +71,7 @@ use store::{ }; use stun_client::{Attribute, Class, Client}; use zkm_sdk::{ZKM_CIRCUIT_VERSION, ZKMProofWithPublicValues}; -use zkm_verifier::{GROTH16_VK_BYTES, convert_ark}; +use zkm_verifier::{GROTH16_VK_BYTES, convert_ark, get_snark_vk_meta}; use crate::env; use crate::rpc_service::routes::v1::{ @@ -1761,7 +1761,14 @@ fn gen_watchtower_commitment(graph_id: Uuid, proof_data: ProofData) -> Result Date: Thu, 19 Mar 2026 10:29:00 +0800 Subject: [PATCH 02/14] feat: introduce zkm-version crate for version encoding and decoding --- Cargo.lock | 13 ++++ Cargo.toml | 4 +- circuits/commit-chain-proof/host/Cargo.toml | 1 + circuits/commit-chain-proof/host/src/lib.rs | 75 ++++++------------- circuits/header-chain-proof/host/Cargo.toml | 1 + circuits/header-chain-proof/host/src/lib.rs | 72 ++++++------------ circuits/operator-proof/host/Cargo.toml | 1 + circuits/operator-proof/host/src/lib.rs | 29 +------ circuits/state-chain-proof/host/Cargo.toml | 1 + circuits/state-chain-proof/host/src/lib.rs | 75 ++++++------------- circuits/watchtower-proof/host/Cargo.toml | 1 + circuits/watchtower-proof/host/src/lib.rs | 29 +------ .../bitcoin-light-client-circuit/Cargo.toml | 1 + .../bitcoin-light-client-circuit/src/lib.rs | 71 ++++++++---------- crates/commit-chain/Cargo.toml | 1 + crates/commit-chain/src/commit_chain.rs | 2 +- crates/commit-chain/src/lib.rs | 11 +-- crates/header-chain/Cargo.toml | 3 +- crates/header-chain/src/header_chain.rs | 2 +- crates/header-chain/src/lib.rs | 11 +-- crates/state-chain/Cargo.toml | 3 +- crates/state-chain/src/lib.rs | 11 +-- crates/state-chain/src/state_chain.rs | 2 +- crates/zkm-version/Cargo.toml | 9 +++ crates/zkm-version/src/lib.rs | 65 ++++++++++++++++ 25 files changed, 215 insertions(+), 279 deletions(-) create mode 100644 crates/zkm-version/Cargo.toml create mode 100644 crates/zkm-version/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index b4d6d6f9..3210bdf9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2416,6 +2416,7 @@ dependencies = [ "tracing", "zkm-primitives 1.2.4 (git+https://github.com/ProjectZKM/Ziren)", "zkm-verifier", + "zkm-version", "zkm-zkvm 1.2.4 (git+https://github.com/ProjectZKM/Ziren)", ] @@ -3191,6 +3192,7 @@ dependencies = [ "tendermint-light-client-verifier", "tracing", "zkm-verifier", + "zkm-version", "zkm-zkvm 1.2.4 (git+https://github.com/ProjectZKM/Ziren)", ] @@ -3218,6 +3220,7 @@ dependencies = [ "zkm-build", "zkm-prover", "zkm-sdk", + "zkm-version", ] [[package]] @@ -5319,6 +5322,7 @@ dependencies = [ "serde", "sha2 0.10.9", "zkm-verifier", + "zkm-version", "zkm-zkvm 1.2.4 (git+https://github.com/ProjectZKM/Ziren)", ] @@ -5351,6 +5355,7 @@ dependencies = [ "zkm-prover", "zkm-sdk", "zkm-verifier", + "zkm-version", ] [[package]] @@ -7849,6 +7854,7 @@ dependencies = [ "zkm-prover", "zkm-sdk", "zkm-verifier", + "zkm-version", ] [[package]] @@ -11481,6 +11487,7 @@ dependencies = [ "tendermint-light-client-verifier", "tracing", "zkm-verifier", + "zkm-version", "zkm-zkvm 1.2.4 (git+https://github.com/ProjectZKM/Ziren)", ] @@ -11522,6 +11529,7 @@ dependencies = [ "zkm-prover", "zkm-sdk", "zkm-verifier", + "zkm-version", ] [[package]] @@ -13060,6 +13068,7 @@ dependencies = [ "zkm-prover", "zkm-sdk", "zkm-verifier", + "zkm-version", ] [[package]] @@ -14309,6 +14318,10 @@ dependencies = [ "zkm-stark", ] +[[package]] +name = "zkm-version" +version = "0.3.3" + [[package]] name = "zkm-zkvm" version = "1.2.4" diff --git a/Cargo.toml b/Cargo.toml index 7b7ff885..1d6344ab 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,6 +7,7 @@ resolver = "3" members = [ "node", "proof-builder-rpc", + "crates/zkm-version", "crates/cbft-rpc", "crates/bitvm2-ga", "crates/store", @@ -97,6 +98,7 @@ zkm-verifier = { git = "https://github.com/ProjectZKM/Ziren", features = ["ark"] bitvm2-lib = { path = "crates/bitvm2-ga" } store = { path = "crates/store" } util = { path = "crates/util" } +zkm-version = { path = "crates/zkm-version" } client = { path = "crates/client" } bitcoin-light-client-circuit = { path = "crates/bitcoin-light-client-circuit" } header-chain = { path = "crates/header-chain" } @@ -181,4 +183,4 @@ zkm-build = { path = "../zkm2/crates/build" } zkm-core-executor = { path = "../zkm2/crates/core/executor" } zkm-prover = { path = "../zkm2/crates/prover" } zkm-sdk = { path = "../zkm2/crates/sdk" } -zkm-verifier = { path = "../zkm2/crates/verifier" } \ No newline at end of file +zkm-verifier = { path = "../zkm2/crates/verifier" } diff --git a/circuits/commit-chain-proof/host/Cargo.toml b/circuits/commit-chain-proof/host/Cargo.toml index 53e946ce..b511f4e4 100644 --- a/circuits/commit-chain-proof/host/Cargo.toml +++ b/circuits/commit-chain-proof/host/Cargo.toml @@ -25,6 +25,7 @@ tendermint-light-client-verifier = { workspace = true, default-features = false, ] } proof-builder.workspace = true +zkm-version.workspace = true # Ziren zkm-sdk.workspace = true diff --git a/circuits/commit-chain-proof/host/src/lib.rs b/circuits/commit-chain-proof/host/src/lib.rs index 31c52432..710d45e0 100644 --- a/circuits/commit-chain-proof/host/src/lib.rs +++ b/circuits/commit-chain-proof/host/src/lib.rs @@ -7,6 +7,7 @@ use zkm_sdk::{ HashableKey, Prover, ProverClient, ZKMProofKind, ZKMProofWithPublicValues, ZKMStdin, include_elf, }; +use zkm_version::{ZKM_VERSION_BYTES_LEN, encode_zkm_version_fixed, read_zkm_version_from_file}; use sha2::{Digest, Sha256}; use std::sync::OnceLock; @@ -19,34 +20,6 @@ const COMMIT_CHAIN: &[u8] = include_elf!("guest"); use std::fs; use clap::Parser; -const ZKM_VERSION_BYTES_LEN: usize = 8; - -fn encode_zkm_version_fixed(version: &str) -> anyhow::Result<[u8; ZKM_VERSION_BYTES_LEN]> { - let raw = version.as_bytes(); - if raw.is_empty() { - anyhow::bail!("zkm_version is empty"); - } - if raw.len() > ZKM_VERSION_BYTES_LEN { - anyhow::bail!( - "zkm_version '{}' too long: {} > {}", - version, - raw.len(), - ZKM_VERSION_BYTES_LEN - ); - } - let mut encoded = [0u8; ZKM_VERSION_BYTES_LEN]; - encoded[..raw.len()].copy_from_slice(raw); - Ok(encoded) -} - -fn read_zkm_version_from_file(input_proof: &str) -> anyhow::Result<[u8; ZKM_VERSION_BYTES_LEN]> { - let zkm_version = String::from_utf8( - fs::read(format!("{input_proof}.zkm_version.bin")) - .context("Failed to read input zkm version file")?, - ) - .context("Invalid UTF-8 in input zkm version file")?; - encode_zkm_version_fixed(zkm_version.trim()) -} /// The arguments for the cli. #[derive(Debug, Clone, Parser, serde::Deserialize, serde::Serialize)] @@ -212,31 +185,31 @@ impl ProofBuilder for CommitChainProofBuilder { }; let (prev_proof, zkm_proof, zkm_public_values, zkm_vk_hash, zkm_version) = match prev_receipt.clone() { - Some(public_inputs) => { - let proof_bytes = - fs::read(input_proof).context("Failed to read input proof file")?; - let zkm_vk_hash = - fs::read(&format!("{}.vk_hash.bin", input_proof)).context("Read vk hash")?; + Some(public_inputs) => { + let proof_bytes = + fs::read(input_proof).context("Failed to read input proof file")?; + let zkm_vk_hash = fs::read(&format!("{}.vk_hash.bin", input_proof)) + .context("Read vk hash")?; let zkm_version = read_zkm_version_from_file(input_proof) .context("Failed to parse input zkm version")?; - let prev_output: CommitChainCircuitOutput = - zkm_sdk::ZKMPublicValues::from(&public_inputs).read(); - ( - CommitChainPrevProofType::PrevProof(prev_output), - proof_bytes, - public_inputs, - zkm_vk_hash.to_vec(), - zkm_version, - ) - } - None => ( - CommitChainPrevProofType::GenesisBlock, - Vec::new(), - Vec::new(), - Vec::new(), - [0u8; ZKM_VERSION_BYTES_LEN], - ), - }; + let prev_output: CommitChainCircuitOutput = + zkm_sdk::ZKMPublicValues::from(&public_inputs).read(); + ( + CommitChainPrevProofType::PrevProof(prev_output), + proof_bytes, + public_inputs, + zkm_vk_hash.to_vec(), + zkm_version, + ) + } + None => ( + CommitChainPrevProofType::GenesisBlock, + Vec::new(), + Vec::new(), + Vec::new(), + [0u8; ZKM_VERSION_BYTES_LEN], + ), + }; let input: CommitChainCircuitInput = CommitChainCircuitInput { zkm_vk_hash, diff --git a/circuits/header-chain-proof/host/Cargo.toml b/circuits/header-chain-proof/host/Cargo.toml index 8c98b6a4..00dec26c 100644 --- a/circuits/header-chain-proof/host/Cargo.toml +++ b/circuits/header-chain-proof/host/Cargo.toml @@ -29,6 +29,7 @@ bitcoin = { workspace = true } client = { workspace = true } proof-builder = { workspace = true } util = { workspace = true } +zkm-version.workspace = true # Ziren zkm-sdk.workspace = true diff --git a/circuits/header-chain-proof/host/src/lib.rs b/circuits/header-chain-proof/host/src/lib.rs index 1c325219..3f93f52a 100644 --- a/circuits/header-chain-proof/host/src/lib.rs +++ b/circuits/header-chain-proof/host/src/lib.rs @@ -11,40 +11,12 @@ use std::{ use util::get_btc_block_confirms; use zkm_sdk::ZKMProofKind; use zkm_sdk::{HashableKey, Prover, ProverClient, ZKMProofWithPublicValues, ZKMStdin, include_elf}; +use zkm_version::{ZKM_VERSION_BYTES_LEN, encode_zkm_version_fixed, read_zkm_version_from_file}; static ELF_ID: OnceLock = OnceLock::new(); use anyhow::Context; use clap::Parser; use std::sync::OnceLock; -const ZKM_VERSION_BYTES_LEN: usize = 8; - -fn encode_zkm_version_fixed(version: &str) -> anyhow::Result<[u8; ZKM_VERSION_BYTES_LEN]> { - let raw = version.as_bytes(); - if raw.is_empty() { - anyhow::bail!("zkm_version is empty"); - } - if raw.len() > ZKM_VERSION_BYTES_LEN { - anyhow::bail!( - "zkm_version '{}' too long: {} > {}", - version, - raw.len(), - ZKM_VERSION_BYTES_LEN - ); - } - let mut encoded = [0u8; ZKM_VERSION_BYTES_LEN]; - encoded[..raw.len()].copy_from_slice(raw); - Ok(encoded) -} - -fn read_zkm_version_from_file(input_proof: &str) -> anyhow::Result<[u8; ZKM_VERSION_BYTES_LEN]> { - let zkm_version = String::from_utf8( - fs::read(format!("{input_proof}.zkm_version.bin")) - .context("Failed to read input zkm version file")?, - ) - .context("Invalid UTF-8 in input zkm version file")?; - encode_zkm_version_fixed(zkm_version.trim()) -} - /// The arguments for the cli. #[derive(Debug, Clone, Parser, serde::Deserialize, serde::Serialize)] pub struct Args { @@ -234,29 +206,29 @@ impl ProofBuilder for HeaderChainProofBuilder { let (prev_proof, zkm_proof, zkm_public_values, zkm_vk_hash, zkm_version) = match prev_receipt.clone() { - Some(public_inputs) => { - let proof_bytes = - fs::read(input_proof).context("Failed to read input proof file").unwrap(); - let zkm_vk_hash = fs::read(&format!("{}.vk_hash.bin", input_proof)).unwrap(); + Some(public_inputs) => { + let proof_bytes = + fs::read(input_proof).context("Failed to read input proof file").unwrap(); + let zkm_vk_hash = fs::read(&format!("{}.vk_hash.bin", input_proof)).unwrap(); let zkm_version = read_zkm_version_from_file(input_proof) .context("Failed to parse input zkm version")?; - let prev_output = zkm_sdk::ZKMPublicValues::from(&public_inputs).read(); - ( - HeaderChainPrevProofType::PrevProof(prev_output), - proof_bytes, - public_inputs, - zkm_vk_hash.to_vec(), - zkm_version, - ) - } - None => ( - HeaderChainPrevProofType::GenesisBlock, - Vec::new(), - Vec::new(), - Vec::new(), - [0u8; ZKM_VERSION_BYTES_LEN], - ), - }; + let prev_output = zkm_sdk::ZKMPublicValues::from(&public_inputs).read(); + ( + HeaderChainPrevProofType::PrevProof(prev_output), + proof_bytes, + public_inputs, + zkm_vk_hash.to_vec(), + zkm_version, + ) + } + None => ( + HeaderChainPrevProofType::GenesisBlock, + Vec::new(), + Vec::new(), + Vec::new(), + [0u8; ZKM_VERSION_BYTES_LEN], + ), + }; tracing::info!( "header-chain length: {}, start: {}, batch_size: {}", diff --git a/circuits/operator-proof/host/Cargo.toml b/circuits/operator-proof/host/Cargo.toml index 86968e7a..f187d5ca 100644 --- a/circuits/operator-proof/host/Cargo.toml +++ b/circuits/operator-proof/host/Cargo.toml @@ -43,6 +43,7 @@ cbft-rpc = { workspace = true } bitcoin = { workspace = true } client = { workspace = true } proof-builder.workspace = true +zkm-version.workspace = true # Ziren zkm-sdk.workspace = true diff --git a/circuits/operator-proof/host/src/lib.rs b/circuits/operator-proof/host/src/lib.rs index a1b9bd2c..391dadfc 100644 --- a/circuits/operator-proof/host/src/lib.rs +++ b/circuits/operator-proof/host/src/lib.rs @@ -20,6 +20,7 @@ use zkm_sdk::{ HashableKey, Prover, ProverClient, ZKMProofKind, ZKMProofWithPublicValues, ZKMStdin, include_elf, }; +use zkm_version::{encode_zkm_version_fixed, read_zkm_version_from_file}; use clap::Parser; /// The arguments for the cli. @@ -88,34 +89,6 @@ use std::fs; use sha2::{Digest, Sha256}; use std::sync::OnceLock; static ELF_ID: OnceLock = OnceLock::new(); -const ZKM_VERSION_BYTES_LEN: usize = 8; - -fn encode_zkm_version_fixed(version: &str) -> anyhow::Result<[u8; ZKM_VERSION_BYTES_LEN]> { - let raw = version.as_bytes(); - if raw.is_empty() { - anyhow::bail!("zkm_version is empty"); - } - if raw.len() > ZKM_VERSION_BYTES_LEN { - anyhow::bail!( - "zkm_version '{}' too long: {} > {}", - version, - raw.len(), - ZKM_VERSION_BYTES_LEN - ); - } - let mut encoded = [0u8; ZKM_VERSION_BYTES_LEN]; - encoded[..raw.len()].copy_from_slice(raw); - Ok(encoded) -} - -fn read_zkm_version_from_file(input_proof: &str) -> anyhow::Result<[u8; ZKM_VERSION_BYTES_LEN]> { - let zkm_version = String::from_utf8( - fs::read(format!("{input_proof}.zkm_version.bin")) - .context("Failed to read input zkm version file")?, - ) - .context("Invalid UTF-8 in input zkm version file")?; - encode_zkm_version_fixed(zkm_version.trim()) -} pub async fn fetch_target_block_and_watchtower_tx( esplora_url: &str, diff --git a/circuits/state-chain-proof/host/Cargo.toml b/circuits/state-chain-proof/host/Cargo.toml index da7404d8..e0c4dfdc 100644 --- a/circuits/state-chain-proof/host/Cargo.toml +++ b/circuits/state-chain-proof/host/Cargo.toml @@ -35,6 +35,7 @@ cbft-rpc.workspace = true proof-builder.workspace = true alloy-consensus.workspace = true util.workspace = true +zkm-version.workspace = true # Ziren zkm-sdk.workspace = true diff --git a/circuits/state-chain-proof/host/src/lib.rs b/circuits/state-chain-proof/host/src/lib.rs index ff7e0c60..696b7c98 100644 --- a/circuits/state-chain-proof/host/src/lib.rs +++ b/circuits/state-chain-proof/host/src/lib.rs @@ -20,6 +20,7 @@ use zkm_sdk::{ HashableKey, Prover, ProverClient, ZKMProofKind, ZKMProofWithPublicValues, ZKMStdin, include_elf, }; +use zkm_version::{ZKM_VERSION_BYTES_LEN, encode_zkm_version_fixed, read_zkm_version_from_file}; use sha2::{Digest, Sha256}; use std::sync::OnceLock; @@ -32,34 +33,6 @@ const STATE_CHAIN: &[u8] = include_elf!("guest"); use std::fs; use clap::Parser; -const ZKM_VERSION_BYTES_LEN: usize = 8; - -fn encode_zkm_version_fixed(version: &str) -> anyhow::Result<[u8; ZKM_VERSION_BYTES_LEN]> { - let raw = version.as_bytes(); - if raw.is_empty() { - anyhow::bail!("zkm_version is empty"); - } - if raw.len() > ZKM_VERSION_BYTES_LEN { - anyhow::bail!( - "zkm_version '{}' too long: {} > {}", - version, - raw.len(), - ZKM_VERSION_BYTES_LEN - ); - } - let mut encoded = [0u8; ZKM_VERSION_BYTES_LEN]; - encoded[..raw.len()].copy_from_slice(raw); - Ok(encoded) -} - -fn read_zkm_version_from_file(input_proof: &str) -> anyhow::Result<[u8; ZKM_VERSION_BYTES_LEN]> { - let zkm_version = String::from_utf8( - fs::read(format!("{input_proof}.zkm_version.bin")) - .context("Failed to read input zkm version file")?, - ) - .context("Invalid UTF-8 in input zkm version file")?; - encode_zkm_version_fixed(zkm_version.trim()) -} /// The arguments for the cli. #[derive(Debug, Clone, Parser, serde::Deserialize, serde::Serialize)] @@ -348,31 +321,31 @@ impl ProofBuilder for StateChainProofBuilder { let (prev_proof, zkm_proof, zkm_public_values, zkm_vk_hash, zkm_version) = match prev_receipt.clone() { - Some(public_inputs) => { - let proof_bytes = - fs::read(input_proof).context("Failed to read input proof file")?; - let zkm_vk_hash = - fs::read(&format!("{}.vk_hash.bin", input_proof)).context("Read vk_hash")?; + Some(public_inputs) => { + let proof_bytes = + fs::read(input_proof).context("Failed to read input proof file")?; + let zkm_vk_hash = fs::read(&format!("{}.vk_hash.bin", input_proof)) + .context("Read vk_hash")?; let zkm_version = read_zkm_version_from_file(input_proof) .context("Failed to parse input zkm version")?; - let prev_output: StateChainCircuitOutput = - zkm_sdk::ZKMPublicValues::from(&public_inputs).read(); - ( - StateChainPrevProofType::PrevProof(prev_output), - proof_bytes, - public_inputs, - zkm_vk_hash.to_vec(), - zkm_version, - ) - } - None => ( - StateChainPrevProofType::GenesisBlock, - Vec::new(), - Vec::new(), - Vec::new(), - [0u8; ZKM_VERSION_BYTES_LEN], - ), - }; + let prev_output: StateChainCircuitOutput = + zkm_sdk::ZKMPublicValues::from(&public_inputs).read(); + ( + StateChainPrevProofType::PrevProof(prev_output), + proof_bytes, + public_inputs, + zkm_vk_hash.to_vec(), + zkm_version, + ) + } + None => ( + StateChainPrevProofType::GenesisBlock, + Vec::new(), + Vec::new(), + Vec::new(), + [0u8; ZKM_VERSION_BYTES_LEN], + ), + }; let input: StateChainCircuitInput = StateChainCircuitInput { prev_proof, diff --git a/circuits/watchtower-proof/host/Cargo.toml b/circuits/watchtower-proof/host/Cargo.toml index 427c24b7..beabedf3 100644 --- a/circuits/watchtower-proof/host/Cargo.toml +++ b/circuits/watchtower-proof/host/Cargo.toml @@ -31,6 +31,7 @@ commit-chain = { workspace = true } bitcoin = { workspace = true } client = { workspace = true } proof-builder.workspace = true +zkm-version.workspace = true # Ziren zkm-sdk.workspace = true diff --git a/circuits/watchtower-proof/host/src/lib.rs b/circuits/watchtower-proof/host/src/lib.rs index 8e02d1d1..d8326e9b 100644 --- a/circuits/watchtower-proof/host/src/lib.rs +++ b/circuits/watchtower-proof/host/src/lib.rs @@ -21,34 +21,7 @@ use proof_builder::{LongRunning, ProofBuilder, ProofRequest}; use clap::Parser; use std::fs; -const ZKM_VERSION_BYTES_LEN: usize = 8; - -fn encode_zkm_version_fixed(version: &str) -> anyhow::Result<[u8; ZKM_VERSION_BYTES_LEN]> { - let raw = version.as_bytes(); - if raw.is_empty() { - anyhow::bail!("zkm_version is empty"); - } - if raw.len() > ZKM_VERSION_BYTES_LEN { - anyhow::bail!( - "zkm_version '{}' too long: {} > {}", - version, - raw.len(), - ZKM_VERSION_BYTES_LEN - ); - } - let mut encoded = [0u8; ZKM_VERSION_BYTES_LEN]; - encoded[..raw.len()].copy_from_slice(raw); - Ok(encoded) -} - -fn read_zkm_version_from_file(input_proof: &str) -> anyhow::Result<[u8; ZKM_VERSION_BYTES_LEN]> { - let zkm_version = String::from_utf8( - fs::read(format!("{input_proof}.zkm_version.bin")) - .context("Failed to read input zkm version file")?, - ) - .context("Invalid UTF-8 in input zkm version file")?; - encode_zkm_version_fixed(zkm_version.trim()) -} +use zkm_version::{encode_zkm_version_fixed, read_zkm_version_from_file}; // The arguments for the cli. #[derive(Debug, Clone, Parser, serde::Deserialize, serde::Serialize)] diff --git a/crates/bitcoin-light-client-circuit/Cargo.toml b/crates/bitcoin-light-client-circuit/Cargo.toml index 7baefa63..db4df6eb 100644 --- a/crates/bitcoin-light-client-circuit/Cargo.toml +++ b/crates/bitcoin-light-client-circuit/Cargo.toml @@ -18,6 +18,7 @@ state-chain = { path = "../state-chain" } zkm-verifier = { git = "https://github.com/ProjectZKM/Ziren", package = "zkm-verifier" } zkm-zkvm = { git = "https://github.com/ProjectZKM/Ziren", package = "zkm-zkvm", features = ["verify"] } zkm-primitives = { git = "https://github.com/ProjectZKM/Ziren" } +zkm-version = { workspace = true } #zkm-verifier = { path = "../../../Ziren/crates/verifier" } #zkm-zkvm = { path = "../../../Ziren/crates/zkvm/entrypoint", features = ["verify"] } diff --git a/crates/bitcoin-light-client-circuit/src/lib.rs b/crates/bitcoin-light-client-circuit/src/lib.rs index 8cf10694..8eb0e633 100644 --- a/crates/bitcoin-light-client-circuit/src/lib.rs +++ b/crates/bitcoin-light-client-circuit/src/lib.rs @@ -20,6 +20,9 @@ use header_chain::{ use state_chain::{StateChainCircuitInput, StateChainPrevProofType}; use zkm_primitives::io::ZKMPublicValues; use zkm_verifier::{Groth16Verifier, get_snark_vk_meta}; +use zkm_version::{ + ZKM_VERSION_BYTES_LEN, ZkmVersionBytes, decode_zkm_version_fixed, encode_zkm_version_fixed, +}; use bitcoin::{ScriptBuf, TxOut, Txid, secp256k1::PublicKey}; pub use guest_executor::io::EthClientExecutorInput; @@ -28,42 +31,13 @@ pub const GRAPH_ID_SIZE: usize = 16; pub const PROOF_SIZE: usize = 260; pub const PUBLIC_INPUTS_SIZE: usize = 36; pub const VK_HASH_SIZE: usize = 66; -pub const ZKM_VERSION_SIZE: usize = 8; +pub const ZKM_VERSION_SIZE: usize = ZKM_VERSION_BYTES_LEN; pub const COMMITMENT_SIZE: usize = GRAPH_ID_SIZE + PROOF_SIZE + PUBLIC_INPUTS_SIZE + VK_HASH_SIZE + ZKM_VERSION_SIZE; pub const TOTAL_WORK_SIZE: usize = 32; pub const CONSENSUS_BLOCK_HEIGHT_SIZE: usize = 4; -fn encode_zkm_version_fixed(zkm_version: &str) -> Result<[u8; ZKM_VERSION_SIZE], String> { - let raw = zkm_version.as_bytes(); - if raw.is_empty() { - return Err("zkm_version is empty".to_string()); - } - if raw.len() > ZKM_VERSION_SIZE { - return Err(format!( - "zkm_version '{}' too long: {} > {}", - zkm_version, - raw.len(), - ZKM_VERSION_SIZE - )); - } - let mut encoded = [0u8; ZKM_VERSION_SIZE]; - encoded[..raw.len()].copy_from_slice(raw); - Ok(encoded) -} - -fn decode_zkm_version_fixed(zkm_version: &[u8; ZKM_VERSION_SIZE]) -> Result { - let end = zkm_version - .iter() - .position(|b| *b == 0) - .unwrap_or(zkm_version.len()); - if end == 0 { - return Err("zkm_version is empty".to_string()); - } - String::from_utf8(zkm_version[..end].to_vec()).map_err(|e| format!("invalid zkm_version: {e}")) -} - pub fn watch_longest_chain( genesis_sequencer_commit_txid: [u8; 32], latest_sequencer_commit_txid: [u8; 32], @@ -499,7 +473,7 @@ pub type WatchtowerCommitmentResult = ( [u8; PROOF_SIZE], [u8; PUBLIC_INPUTS_SIZE], [u8; VK_HASH_SIZE], - [u8; ZKM_VERSION_SIZE], + ZkmVersionBytes, [u8; TOTAL_WORK_SIZE], [u8; CONSENSUS_BLOCK_HEIGHT_SIZE], ); @@ -565,13 +539,19 @@ pub fn verify_proof( proof: &[u8], zkm_public_values: &[u8], zkm_vk_hash: &[u8], - zkm_version: &[u8; ZKM_VERSION_SIZE], + zkm_version: &ZkmVersionBytes, ) -> Result<(), String> { let groth16_vk = *zkm_verifier::GROTH16_VK_BYTES; let zkm_vk_hash = String::from_utf8(zkm_vk_hash.to_vec()).map_err(|e| e.to_string())?; let zkm_version = decode_zkm_version_fixed(zkm_version)?; let snark_vk_meta = get_snark_vk_meta(&zkm_version).map_err(|e| e.to_string())?; - match Groth16Verifier::verify(proof, zkm_public_values, &zkm_vk_hash, &snark_vk_meta, groth16_vk) { + match Groth16Verifier::verify( + proof, + zkm_public_values, + &zkm_vk_hash, + &snark_vk_meta, + groth16_vk, + ) { Ok(_) => Ok(()), Err(err) => Err(format!("Verify Groth16 proof, err: {err:?}")), } @@ -664,17 +644,32 @@ mod tests { #[test] fn test_build_watchtower_commitment_rejects_long_version() { - let graph_id = hex::decode("00112233445566778899aabbccddeeff") - .unwrap() - .try_into() - .unwrap(); + let graph_id = hex::decode("00112233445566778899aabbccddeeff").unwrap().try_into().unwrap(); + let too_long_version = "v1234567890123456"; + assert_eq!(too_long_version.len(), ZKM_VERSION_SIZE + 1); let result = build_watchtower_commitment( &graph_id, &PROOF.try_into().unwrap(), &PUBLIC_INPUTS.try_into().unwrap(), VK_HASH, - "v123456789", + too_long_version, ); assert!(result.is_err()); } + + #[test] + fn test_build_watchtower_commitment_accepts_rc_version() { + let graph_id = hex::decode("00112233445566778899aabbccddeeff").unwrap().try_into().unwrap(); + let rc_version = "v1.12.15-rc1"; + let commitment = build_watchtower_commitment( + &graph_id, + &PROOF.try_into().unwrap(), + &PUBLIC_INPUTS.try_into().unwrap(), + VK_HASH, + rc_version, + ) + .unwrap(); + let parsed = parse_watchtower_commitment(&commitment).unwrap(); + assert_eq!(decode_zkm_version_fixed(&parsed.4).unwrap(), rc_version); + } } diff --git a/crates/commit-chain/Cargo.toml b/crates/commit-chain/Cargo.toml index a0afcbd6..4c86186e 100644 --- a/crates/commit-chain/Cargo.toml +++ b/crates/commit-chain/Cargo.toml @@ -15,6 +15,7 @@ guest-executor = { workspace = true } # Ziren zkm-verifier = { git = "https://github.com/ProjectZKM/Ziren", package = "zkm-verifier" } zkm-zkvm = { git = "https://github.com/ProjectZKM/Ziren", package = "zkm-zkvm", features = ["verify"] } +zkm-version = { workspace = true } #zkm-verifier = { path = "../../../Ziren/crates/verifier" } #zkm-zkvm = { path = "../../../Ziren/crates/zkvm/entrypoint", features = ["verify"] } diff --git a/crates/commit-chain/src/commit_chain.rs b/crates/commit-chain/src/commit_chain.rs index 43b01a65..c88a2910 100644 --- a/crates/commit-chain/src/commit_chain.rs +++ b/crates/commit-chain/src/commit_chain.rs @@ -86,7 +86,7 @@ pub struct CommitChainState { pub const PROOF_SIZE: usize = 260; pub const PUBLIC_INPUTS_SIZE: usize = 36; pub const VK_HASH_SIZE: usize = 66; -pub const ZKM_VERSION_SIZE: usize = 8; +pub const ZKM_VERSION_SIZE: usize = zkm_version::ZKM_VERSION_BYTES_LEN; #[derive(Serialize, Deserialize, PartialEq, Clone, Debug)] pub struct CommitChainCircuitOutput { diff --git a/crates/commit-chain/src/lib.rs b/crates/commit-chain/src/lib.rs index 83d281d6..d30ce1f0 100644 --- a/crates/commit-chain/src/lib.rs +++ b/crates/commit-chain/src/lib.rs @@ -3,14 +3,7 @@ pub use publisher::*; mod commit_chain; pub use commit_chain::*; use zkm_verifier::{Groth16Verifier, get_snark_vk_meta}; - -fn decode_zkm_version(version: &[u8; ZKM_VERSION_SIZE]) -> Result { - let end = version.iter().position(|b| *b == 0).unwrap_or(version.len()); - if end == 0 { - return Err("zkm_version is empty".to_string()); - } - String::from_utf8(version[..end].to_vec()).map_err(|e| format!("invalid zkm_version: {e}")) -} +use zkm_version::decode_zkm_version_fixed; pub fn commit_chain_circuit(input: CommitChainCircuitInput) -> CommitChainCircuitOutput { let mut chain_state = match input.prev_proof { @@ -21,7 +14,7 @@ pub fn commit_chain_circuit(input: CommitChainCircuitInput) -> CommitChainCircui println!("verify commit chain of prev proof"); let groth16_vk = *zkm_verifier::GROTH16_VK_BYTES; let zkm_vk_hash = String::from_utf8(input.zkm_vk_hash.to_vec()).unwrap(); - let zkm_version = decode_zkm_version(&input.zkm_version).unwrap(); + let zkm_version = decode_zkm_version_fixed(&input.zkm_version).unwrap(); let snark_vk_meta = get_snark_vk_meta(&zkm_version).unwrap(); Groth16Verifier::verify( &input.zkm_proof, diff --git a/crates/header-chain/Cargo.toml b/crates/header-chain/Cargo.toml index 7febffd3..d24842eb 100644 --- a/crates/header-chain/Cargo.toml +++ b/crates/header-chain/Cargo.toml @@ -12,6 +12,7 @@ serde = { workspace = true, default-features = false } crypto-bigint = { version = "0.5.5", default-features = false } zkm-zkvm = { git = "https://github.com/ProjectZKM/Ziren", package = "zkm-zkvm", features = ["verify"] } zkm-verifier = { git = "https://github.com/ProjectZKM/Ziren", package = "zkm-verifier" } +zkm-version = { workspace = true } [dev-dependencies] -hex-literal = "1.0.0" \ No newline at end of file +hex-literal = "1.0.0" diff --git a/crates/header-chain/src/header_chain.rs b/crates/header-chain/src/header_chain.rs index 204031a4..276a4130 100644 --- a/crates/header-chain/src/header_chain.rs +++ b/crates/header-chain/src/header_chain.rs @@ -91,7 +91,7 @@ pub const NETWORK_CONSTANTS: NetworkConstants = { } }; -pub const ZKM_VERSION_SIZE: usize = 8; +pub const ZKM_VERSION_SIZE: usize = zkm_version::ZKM_VERSION_BYTES_LEN; /// An epoch should be two weeks (represented as number of seconds) /// seconds/minute * minutes/hour * hours/day * 14 days diff --git a/crates/header-chain/src/lib.rs b/crates/header-chain/src/lib.rs index 10a01944..bd772678 100644 --- a/crates/header-chain/src/lib.rs +++ b/crates/header-chain/src/lib.rs @@ -13,14 +13,7 @@ pub use transaction::*; pub mod spv; pub use spv::SPV; use zkm_verifier::{Groth16Verifier, get_snark_vk_meta}; - -fn decode_zkm_version(version: &[u8; ZKM_VERSION_SIZE]) -> Result { - let end = version.iter().position(|b| *b == 0).unwrap_or(version.len()); - if end == 0 { - return Err("zkm_version is empty".to_string()); - } - String::from_utf8(version[..end].to_vec()).map_err(|e| format!("invalid zkm_version: {e}")) -} +use zkm_version::decode_zkm_version_fixed; /// The main entry point of the header chain circuit. pub fn header_chain_circuit(input: HeaderChainCircuitInput) -> BlockHeaderCircuitOutput { @@ -32,7 +25,7 @@ pub fn header_chain_circuit(input: HeaderChainCircuitInput) -> BlockHeaderCircui println!("verify header chain of prev proof"); let groth16_vk = *zkm_verifier::GROTH16_VK_BYTES; let zkm_vk_hash = String::from_utf8(input.zkm_vk_hash.to_vec()).unwrap(); - let zkm_version = decode_zkm_version(&input.zkm_version).unwrap(); + let zkm_version = decode_zkm_version_fixed(&input.zkm_version).unwrap(); let snark_vk_meta = get_snark_vk_meta(&zkm_version).unwrap(); Groth16Verifier::verify( &input.zkm_proof, diff --git a/crates/state-chain/Cargo.toml b/crates/state-chain/Cargo.toml index 6ff57a35..56154706 100644 --- a/crates/state-chain/Cargo.toml +++ b/crates/state-chain/Cargo.toml @@ -15,6 +15,7 @@ header-chain = { path = "../header-chain" } # Ziren zkm-verifier = { git = "https://github.com/ProjectZKM/Ziren", package = "zkm-verifier" } zkm-zkvm = { git = "https://github.com/ProjectZKM/Ziren", package = "zkm-zkvm", features = ["verify"] } +zkm-version = { workspace = true } #zkm-verifier = { path = "../../../Ziren/crates/verifier" } #zkm-zkvm = { path = "../../../Ziren/crates/zkvm/entrypoint", features = ["verify"] } @@ -54,4 +55,4 @@ blake3 = "1.6.1" [build-dependencies] prost-build = "0.13" #pbjson-build = "0.8" -#pbjson-types = "0.8" \ No newline at end of file +#pbjson-types = "0.8" diff --git a/crates/state-chain/src/lib.rs b/crates/state-chain/src/lib.rs index 80926a48..87a9c661 100644 --- a/crates/state-chain/src/lib.rs +++ b/crates/state-chain/src/lib.rs @@ -4,14 +4,7 @@ mod state_chain; pub use cbft::*; pub use state_chain::*; use zkm_verifier::{Groth16Verifier, get_snark_vk_meta}; - -fn decode_zkm_version(version: &[u8; ZKM_VERSION_SIZE]) -> Result { - let end = version.iter().position(|b| *b == 0).unwrap_or(version.len()); - if end == 0 { - return Err("zkm_version is empty".to_string()); - } - String::from_utf8(version[..end].to_vec()).map_err(|e| format!("invalid zkm_version: {e}")) -} +use zkm_version::decode_zkm_version_fixed; pub fn state_chain_circuit(input: StateChainCircuitInput) -> StateChainCircuitOutput { let mut chain_state = match input.prev_proof { @@ -25,7 +18,7 @@ pub fn state_chain_circuit(input: StateChainCircuitInput) -> StateChainCircuitOu println!("verify state chain of prev proof"); let groth16_vk = *zkm_verifier::GROTH16_VK_BYTES; let zkm_vk_hash = String::from_utf8(input.zkm_vk_hash.to_vec()).unwrap(); - let zkm_version = decode_zkm_version(&input.zkm_version).unwrap(); + let zkm_version = decode_zkm_version_fixed(&input.zkm_version).unwrap(); let snark_vk_meta = get_snark_vk_meta(&zkm_version).unwrap(); Groth16Verifier::verify( &input.zkm_proof, diff --git a/crates/state-chain/src/state_chain.rs b/crates/state-chain/src/state_chain.rs index 40fa5e33..84dc93a5 100644 --- a/crates/state-chain/src/state_chain.rs +++ b/crates/state-chain/src/state_chain.rs @@ -10,7 +10,7 @@ use tendermint_light_client_verifier::types::LightBlock; // Contract address, base slot and key, the expected value of the slot is hardcoded to 1. type WithdrawalSlot = (Address, [u8; 32], Vec<[u8; 16]>); -pub const ZKM_VERSION_SIZE: usize = 8; +pub const ZKM_VERSION_SIZE: usize = zkm_version::ZKM_VERSION_BYTES_LEN; /// The input proof of the commit chain circuit. /// The proof can be either None (implying the beginning) or a Succinct proof. diff --git a/crates/zkm-version/Cargo.toml b/crates/zkm-version/Cargo.toml new file mode 100644 index 00000000..c269a83b --- /dev/null +++ b/crates/zkm-version/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "zkm-version" +version.workspace = true +edition.workspace = true + +[dependencies] + +[lints] +workspace = true diff --git a/crates/zkm-version/src/lib.rs b/crates/zkm-version/src/lib.rs new file mode 100644 index 00000000..df4cdf80 --- /dev/null +++ b/crates/zkm-version/src/lib.rs @@ -0,0 +1,65 @@ +pub const ZKM_VERSION_BYTES_LEN: usize = 16; +pub type ZkmVersionBytes = [u8; ZKM_VERSION_BYTES_LEN]; + +pub fn encode_zkm_version_fixed(version: &str) -> Result { + let raw = version.as_bytes(); + if raw.is_empty() { + return Err("zkm_version is empty".to_string()); + } + if raw.len() > ZKM_VERSION_BYTES_LEN { + return Err(format!( + "zkm_version '{}' too long: {} > {}", + version, + raw.len(), + ZKM_VERSION_BYTES_LEN + )); + } + + let mut encoded = [0u8; ZKM_VERSION_BYTES_LEN]; + encoded[..raw.len()].copy_from_slice(raw); + Ok(encoded) +} + +pub fn decode_zkm_version_fixed(version: &ZkmVersionBytes) -> Result { + let end = version.iter().position(|b| *b == 0).unwrap_or(version.len()); + if end == 0 { + return Err("zkm_version is empty".to_string()); + } + String::from_utf8(version[..end].to_vec()).map_err(|e| format!("invalid zkm_version: {e}")) +} + +pub fn read_zkm_version_from_file(input_proof: &str) -> Result { + let version_path = format!("{input_proof}.zkm_version.bin"); + let raw = std::fs::read(&version_path) + .map_err(|e| format!("failed to read zkm_version file '{}': {e}", version_path))?; + let version = String::from_utf8(raw) + .map_err(|e| format!("invalid UTF-8 in zkm_version file '{}': {e}", version_path))?; + encode_zkm_version_fixed(version.trim()) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn encode_rejects_empty_version() { + let result = encode_zkm_version_fixed(""); + assert!(result.is_err()); + } + + #[test] + fn encode_accepts_16_bytes_version() { + let version = "v123456789012345"; + assert_eq!(version.len(), ZKM_VERSION_BYTES_LEN); + let encoded = encode_zkm_version_fixed(version).unwrap(); + assert_eq!(decode_zkm_version_fixed(&encoded).unwrap(), version); + } + + #[test] + fn encode_rejects_17_bytes_version() { + let version = "v1234567890123456"; + assert_eq!(version.len(), ZKM_VERSION_BYTES_LEN + 1); + let result = encode_zkm_version_fixed(version); + assert!(result.is_err()); + } +} From 6e716e812d1cdf7aa05c83bca0b891015a13a861 Mon Sep 17 00:00:00 2001 From: Blake Date: Fri, 20 Mar 2026 00:44:22 +0800 Subject: [PATCH 03/14] refactor: replace fixed-size zkm_version with String and simplify related handling --- circuits/commit-chain-proof/host/src/lib.rs | 9 ++-- circuits/header-chain-proof/host/src/lib.rs | 9 ++-- circuits/operator-proof/host/src/lib.rs | 3 +- circuits/state-chain-proof/host/src/lib.rs | 9 ++-- circuits/watchtower-proof/host/src/lib.rs | 3 +- .../bitcoin-light-client-circuit/src/lib.rs | 25 +++++++++-- crates/commit-chain/src/commit_chain.rs | 2 +- crates/commit-chain/src/lib.rs | 4 +- crates/header-chain/src/header_chain.rs | 2 +- crates/header-chain/src/lib.rs | 4 +- crates/state-chain/src/lib.rs | 4 +- crates/state-chain/src/state_chain.rs | 2 +- crates/zkm-version/src/lib.rs | 45 ++++++++++++++++++- 13 files changed, 84 insertions(+), 37 deletions(-) diff --git a/circuits/commit-chain-proof/host/src/lib.rs b/circuits/commit-chain-proof/host/src/lib.rs index 710d45e0..4f1a85f0 100644 --- a/circuits/commit-chain-proof/host/src/lib.rs +++ b/circuits/commit-chain-proof/host/src/lib.rs @@ -7,7 +7,7 @@ use zkm_sdk::{ HashableKey, Prover, ProverClient, ZKMProofKind, ZKMProofWithPublicValues, ZKMStdin, include_elf, }; -use zkm_version::{ZKM_VERSION_BYTES_LEN, encode_zkm_version_fixed, read_zkm_version_from_file}; +use zkm_version::read_zkm_version_from_file; use sha2::{Digest, Sha256}; use std::sync::OnceLock; @@ -190,8 +190,8 @@ impl ProofBuilder for CommitChainProofBuilder { fs::read(input_proof).context("Failed to read input proof file")?; let zkm_vk_hash = fs::read(&format!("{}.vk_hash.bin", input_proof)) .context("Read vk hash")?; - let zkm_version = read_zkm_version_from_file(input_proof) - .context("Failed to parse input zkm version")?; + let zkm_version = read_zkm_version_from_file(input_proof) + .context("Failed to parse input zkm version")?; let prev_output: CommitChainCircuitOutput = zkm_sdk::ZKMPublicValues::from(&public_inputs).read(); ( @@ -207,7 +207,7 @@ impl ProofBuilder for CommitChainProofBuilder { Vec::new(), Vec::new(), Vec::new(), - [0u8; ZKM_VERSION_BYTES_LEN], + String::new(), ), }; @@ -281,7 +281,6 @@ impl ProofBuilder for CommitChainProofBuilder { let public_value_hex = hex::encode(proof.public_values.to_vec()); let proof_size = proof.bytes().len(); let zkm_version = proof.zkm_version.clone(); - encode_zkm_version_fixed(&zkm_version).context("Invalid zkm version for output proof")?; std::fs::write( &format!("{}.public_inputs.bin", output_proof), proof.public_values.to_vec(), diff --git a/circuits/header-chain-proof/host/src/lib.rs b/circuits/header-chain-proof/host/src/lib.rs index 3f93f52a..e9caaa09 100644 --- a/circuits/header-chain-proof/host/src/lib.rs +++ b/circuits/header-chain-proof/host/src/lib.rs @@ -11,7 +11,7 @@ use std::{ use util::get_btc_block_confirms; use zkm_sdk::ZKMProofKind; use zkm_sdk::{HashableKey, Prover, ProverClient, ZKMProofWithPublicValues, ZKMStdin, include_elf}; -use zkm_version::{ZKM_VERSION_BYTES_LEN, encode_zkm_version_fixed, read_zkm_version_from_file}; +use zkm_version::read_zkm_version_from_file; static ELF_ID: OnceLock = OnceLock::new(); use anyhow::Context; use clap::Parser; @@ -210,8 +210,8 @@ impl ProofBuilder for HeaderChainProofBuilder { let proof_bytes = fs::read(input_proof).context("Failed to read input proof file").unwrap(); let zkm_vk_hash = fs::read(&format!("{}.vk_hash.bin", input_proof)).unwrap(); - let zkm_version = read_zkm_version_from_file(input_proof) - .context("Failed to parse input zkm version")?; + let zkm_version = read_zkm_version_from_file(input_proof) + .context("Failed to parse input zkm version")?; let prev_output = zkm_sdk::ZKMPublicValues::from(&public_inputs).read(); ( HeaderChainPrevProofType::PrevProof(prev_output), @@ -226,7 +226,7 @@ impl ProofBuilder for HeaderChainProofBuilder { Vec::new(), Vec::new(), Vec::new(), - [0u8; ZKM_VERSION_BYTES_LEN], + String::new(), ), }; @@ -303,7 +303,6 @@ impl ProofBuilder for HeaderChainProofBuilder { let public_value_hex = hex::encode(proof.public_values.to_vec()); let proof_size = proof.bytes().len(); let zkm_version = proof.zkm_version.clone(); - encode_zkm_version_fixed(&zkm_version).context("Invalid zkm version for output proof")?; std::fs::write( &format!("{}.public_inputs.bin", output_proof), proof.public_values.to_vec(), diff --git a/circuits/operator-proof/host/src/lib.rs b/circuits/operator-proof/host/src/lib.rs index 391dadfc..7e1917c2 100644 --- a/circuits/operator-proof/host/src/lib.rs +++ b/circuits/operator-proof/host/src/lib.rs @@ -20,7 +20,7 @@ use zkm_sdk::{ HashableKey, Prover, ProverClient, ZKMProofKind, ZKMProofWithPublicValues, ZKMStdin, include_elf, }; -use zkm_version::{encode_zkm_version_fixed, read_zkm_version_from_file}; +use zkm_version::read_zkm_version_from_file; use clap::Parser; /// The arguments for the cli. @@ -437,7 +437,6 @@ impl ProofBuilder for OperatorProofBuilder { let public_value_hex = hex::encode(proof.public_values.to_vec()); let proof_size = proof.bytes().len(); let zkm_version = proof.zkm_version.clone(); - encode_zkm_version_fixed(&zkm_version).context("Invalid zkm version for output proof")?; std::fs::write(&format!("{}.vk_hash.bin", output), self.verifying_key.bytes32())?; std::fs::write(&format!("{}.zkm_version.bin", output), zkm_version)?; let proof = bincode::serialize(&proof).unwrap(); diff --git a/circuits/state-chain-proof/host/src/lib.rs b/circuits/state-chain-proof/host/src/lib.rs index 696b7c98..c10578b6 100644 --- a/circuits/state-chain-proof/host/src/lib.rs +++ b/circuits/state-chain-proof/host/src/lib.rs @@ -20,7 +20,7 @@ use zkm_sdk::{ HashableKey, Prover, ProverClient, ZKMProofKind, ZKMProofWithPublicValues, ZKMStdin, include_elf, }; -use zkm_version::{ZKM_VERSION_BYTES_LEN, encode_zkm_version_fixed, read_zkm_version_from_file}; +use zkm_version::read_zkm_version_from_file; use sha2::{Digest, Sha256}; use std::sync::OnceLock; @@ -326,8 +326,8 @@ impl ProofBuilder for StateChainProofBuilder { fs::read(input_proof).context("Failed to read input proof file")?; let zkm_vk_hash = fs::read(&format!("{}.vk_hash.bin", input_proof)) .context("Read vk_hash")?; - let zkm_version = read_zkm_version_from_file(input_proof) - .context("Failed to parse input zkm version")?; + let zkm_version = read_zkm_version_from_file(input_proof) + .context("Failed to parse input zkm version")?; let prev_output: StateChainCircuitOutput = zkm_sdk::ZKMPublicValues::from(&public_inputs).read(); ( @@ -343,7 +343,7 @@ impl ProofBuilder for StateChainProofBuilder { Vec::new(), Vec::new(), Vec::new(), - [0u8; ZKM_VERSION_BYTES_LEN], + String::new(), ), }; @@ -404,7 +404,6 @@ impl ProofBuilder for StateChainProofBuilder { let public_value_hex = hex::encode(proof.public_values.to_vec()); let proof_size = proof.bytes().len(); let zkm_version = proof.zkm_version.clone(); - encode_zkm_version_fixed(&zkm_version).context("Invalid zkm version for output proof")?; std::fs::write( &format!("{}.public_inputs.bin", output_proof), proof.public_values.to_vec(), diff --git a/circuits/watchtower-proof/host/src/lib.rs b/circuits/watchtower-proof/host/src/lib.rs index d8326e9b..8284eb0e 100644 --- a/circuits/watchtower-proof/host/src/lib.rs +++ b/circuits/watchtower-proof/host/src/lib.rs @@ -21,7 +21,7 @@ use proof_builder::{LongRunning, ProofBuilder, ProofRequest}; use clap::Parser; use std::fs; -use zkm_version::{encode_zkm_version_fixed, read_zkm_version_from_file}; +use zkm_version::read_zkm_version_from_file; // The arguments for the cli. #[derive(Debug, Clone, Parser, serde::Deserialize, serde::Serialize)] @@ -275,7 +275,6 @@ impl ProofBuilder for WatchtowerProofBuilder { let public_value_hex = hex::encode(proof.public_values.to_vec()); let proof_size = proof.bytes().len(); let zkm_version = proof.zkm_version.clone(); - encode_zkm_version_fixed(&zkm_version).context("Invalid zkm version for output proof")?; std::fs::write(&format!("{}.public_inputs.bin", output), proof.public_values.to_vec())?; std::fs::write(&format!("{}.vk_hash.bin", output), self.verifying_key.bytes32())?; std::fs::write(&format!("{}.zkm_version.bin", output), zkm_version)?; diff --git a/crates/bitcoin-light-client-circuit/src/lib.rs b/crates/bitcoin-light-client-circuit/src/lib.rs index 8eb0e633..be61befd 100644 --- a/crates/bitcoin-light-client-circuit/src/lib.rs +++ b/crates/bitcoin-light-client-circuit/src/lib.rs @@ -260,7 +260,7 @@ pub fn propose_longest_chain( } }; - match verify_proof(&proof, &public_values, &vk, &watchtower_zkm_version) { + match verify_proof_fixed_version(&proof, &public_values, &vk, &watchtower_zkm_version) { Ok(_) => {} Err(err) => { println!("Watchtower[{i}] invalid proof: {err}"); @@ -539,12 +539,11 @@ pub fn verify_proof( proof: &[u8], zkm_public_values: &[u8], zkm_vk_hash: &[u8], - zkm_version: &ZkmVersionBytes, + zkm_version: &str, ) -> Result<(), String> { let groth16_vk = *zkm_verifier::GROTH16_VK_BYTES; let zkm_vk_hash = String::from_utf8(zkm_vk_hash.to_vec()).map_err(|e| e.to_string())?; - let zkm_version = decode_zkm_version_fixed(zkm_version)?; - let snark_vk_meta = get_snark_vk_meta(&zkm_version).map_err(|e| e.to_string())?; + let snark_vk_meta = get_snark_vk_meta(zkm_version).map_err(|e| e.to_string())?; match Groth16Verifier::verify( proof, zkm_public_values, @@ -557,6 +556,16 @@ pub fn verify_proof( } } +pub fn verify_proof_fixed_version( + proof: &[u8], + zkm_public_values: &[u8], + zkm_vk_hash: &[u8], + zkm_version: &ZkmVersionBytes, +) -> Result<(), String> { + let decoded_zkm_version = decode_zkm_version_fixed(zkm_version)?; + verify_proof(proof, zkm_public_values, zkm_vk_hash, &decoded_zkm_version) +} + #[cfg(test)] mod tests { use super::*; @@ -672,4 +681,12 @@ mod tests { let parsed = parse_watchtower_commitment(&commitment).unwrap(); assert_eq!(decode_zkm_version_fixed(&parsed.4).unwrap(), rc_version); } + + #[test] + fn test_verify_proof_accepts_non_fixed_length_version() { + let long_version = "v1.12.15-rc1+build.20260319"; + let result = verify_proof(&[], &[], &[], long_version); + assert!(result.is_err()); + assert!(!result.unwrap_err().contains("too long")); + } } diff --git a/crates/commit-chain/src/commit_chain.rs b/crates/commit-chain/src/commit_chain.rs index c88a2910..6a0d256a 100644 --- a/crates/commit-chain/src/commit_chain.rs +++ b/crates/commit-chain/src/commit_chain.rs @@ -99,7 +99,7 @@ pub struct CommitChainCircuitInput { pub zkm_proof: Vec, pub zkm_public_values: Vec, pub zkm_vk_hash: Vec, - pub zkm_version: [u8; ZKM_VERSION_SIZE], + pub zkm_version: String, pub commits: Vec, } diff --git a/crates/commit-chain/src/lib.rs b/crates/commit-chain/src/lib.rs index d30ce1f0..3b508a8b 100644 --- a/crates/commit-chain/src/lib.rs +++ b/crates/commit-chain/src/lib.rs @@ -3,7 +3,6 @@ pub use publisher::*; mod commit_chain; pub use commit_chain::*; use zkm_verifier::{Groth16Verifier, get_snark_vk_meta}; -use zkm_version::decode_zkm_version_fixed; pub fn commit_chain_circuit(input: CommitChainCircuitInput) -> CommitChainCircuitOutput { let mut chain_state = match input.prev_proof { @@ -14,8 +13,7 @@ pub fn commit_chain_circuit(input: CommitChainCircuitInput) -> CommitChainCircui println!("verify commit chain of prev proof"); let groth16_vk = *zkm_verifier::GROTH16_VK_BYTES; let zkm_vk_hash = String::from_utf8(input.zkm_vk_hash.to_vec()).unwrap(); - let zkm_version = decode_zkm_version_fixed(&input.zkm_version).unwrap(); - let snark_vk_meta = get_snark_vk_meta(&zkm_version).unwrap(); + let snark_vk_meta = get_snark_vk_meta(&input.zkm_version).unwrap(); Groth16Verifier::verify( &input.zkm_proof, &input.zkm_public_values, diff --git a/crates/header-chain/src/header_chain.rs b/crates/header-chain/src/header_chain.rs index 276a4130..d36a3841 100644 --- a/crates/header-chain/src/header_chain.rs +++ b/crates/header-chain/src/header_chain.rs @@ -381,7 +381,7 @@ pub struct HeaderChainCircuitInput { pub zkm_proof: Vec, pub zkm_public_values: Vec, pub zkm_vk_hash: Vec, - pub zkm_version: [u8; ZKM_VERSION_SIZE], + pub zkm_version: String, pub prev_proof: HeaderChainPrevProofType, pub block_headers: Vec, } diff --git a/crates/header-chain/src/lib.rs b/crates/header-chain/src/lib.rs index bd772678..80b757d4 100644 --- a/crates/header-chain/src/lib.rs +++ b/crates/header-chain/src/lib.rs @@ -13,7 +13,6 @@ pub use transaction::*; pub mod spv; pub use spv::SPV; use zkm_verifier::{Groth16Verifier, get_snark_vk_meta}; -use zkm_version::decode_zkm_version_fixed; /// The main entry point of the header chain circuit. pub fn header_chain_circuit(input: HeaderChainCircuitInput) -> BlockHeaderCircuitOutput { @@ -25,8 +24,7 @@ pub fn header_chain_circuit(input: HeaderChainCircuitInput) -> BlockHeaderCircui println!("verify header chain of prev proof"); let groth16_vk = *zkm_verifier::GROTH16_VK_BYTES; let zkm_vk_hash = String::from_utf8(input.zkm_vk_hash.to_vec()).unwrap(); - let zkm_version = decode_zkm_version_fixed(&input.zkm_version).unwrap(); - let snark_vk_meta = get_snark_vk_meta(&zkm_version).unwrap(); + let snark_vk_meta = get_snark_vk_meta(&input.zkm_version).unwrap(); Groth16Verifier::verify( &input.zkm_proof, &input.zkm_public_values, diff --git a/crates/state-chain/src/lib.rs b/crates/state-chain/src/lib.rs index 87a9c661..4cf21b54 100644 --- a/crates/state-chain/src/lib.rs +++ b/crates/state-chain/src/lib.rs @@ -4,7 +4,6 @@ mod state_chain; pub use cbft::*; pub use state_chain::*; use zkm_verifier::{Groth16Verifier, get_snark_vk_meta}; -use zkm_version::decode_zkm_version_fixed; pub fn state_chain_circuit(input: StateChainCircuitInput) -> StateChainCircuitOutput { let mut chain_state = match input.prev_proof { @@ -18,8 +17,7 @@ pub fn state_chain_circuit(input: StateChainCircuitInput) -> StateChainCircuitOu println!("verify state chain of prev proof"); let groth16_vk = *zkm_verifier::GROTH16_VK_BYTES; let zkm_vk_hash = String::from_utf8(input.zkm_vk_hash.to_vec()).unwrap(); - let zkm_version = decode_zkm_version_fixed(&input.zkm_version).unwrap(); - let snark_vk_meta = get_snark_vk_meta(&zkm_version).unwrap(); + let snark_vk_meta = get_snark_vk_meta(&input.zkm_version).unwrap(); Groth16Verifier::verify( &input.zkm_proof, &input.zkm_public_values, diff --git a/crates/state-chain/src/state_chain.rs b/crates/state-chain/src/state_chain.rs index 84dc93a5..ef5db6d9 100644 --- a/crates/state-chain/src/state_chain.rs +++ b/crates/state-chain/src/state_chain.rs @@ -50,7 +50,7 @@ pub struct StateChainCircuitInput { pub zkm_proof: Vec, pub zkm_public_values: Vec, pub zkm_vk_hash: Vec, - pub zkm_version: [u8; ZKM_VERSION_SIZE], + pub zkm_version: String, pub prev_proof: StateChainPrevProofType, pub blocks: Vec, } diff --git a/crates/zkm-version/src/lib.rs b/crates/zkm-version/src/lib.rs index df4cdf80..ad0bc202 100644 --- a/crates/zkm-version/src/lib.rs +++ b/crates/zkm-version/src/lib.rs @@ -28,18 +28,42 @@ pub fn decode_zkm_version_fixed(version: &ZkmVersionBytes) -> Result Result { +pub fn parse_zkm_version(version: &str) -> Result { + let trimmed = version.trim(); + if trimmed.is_empty() { + return Err("zkm_version is empty".to_string()); + } + Ok(trimmed.to_string()) +} + +pub fn read_zkm_version_from_file(input_proof: &str) -> Result { let version_path = format!("{input_proof}.zkm_version.bin"); let raw = std::fs::read(&version_path) .map_err(|e| format!("failed to read zkm_version file '{}': {e}", version_path))?; let version = String::from_utf8(raw) .map_err(|e| format!("invalid UTF-8 in zkm_version file '{}': {e}", version_path))?; - encode_zkm_version_fixed(version.trim()) + parse_zkm_version(&version) +} + +pub fn read_zkm_version_fixed_from_file(input_proof: &str) -> Result { + let version = read_zkm_version_from_file(input_proof)?; + encode_zkm_version_fixed(&version) } #[cfg(test)] mod tests { use super::*; + use std::fs; + use std::path::PathBuf; + use std::time::{SystemTime, UNIX_EPOCH}; + + fn write_temp_version_file(version: &str) -> String { + let nanos = SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_nanos(); + let base: PathBuf = std::env::temp_dir().join(format!("zkm-version-test-{nanos}")); + let base_str = base.to_string_lossy().to_string(); + fs::write(format!("{base_str}.zkm_version.bin"), version).unwrap(); + base_str + } #[test] fn encode_rejects_empty_version() { @@ -62,4 +86,21 @@ mod tests { let result = encode_zkm_version_fixed(version); assert!(result.is_err()); } + + #[test] + fn read_version_file_accepts_non_fixed_length_version() { + let version = "v1.12.15-rc1+build.20260319"; + let input_proof = write_temp_version_file(version); + let read = read_zkm_version_from_file(&input_proof).unwrap(); + assert_eq!(read, version); + let _ = fs::remove_file(format!("{input_proof}.zkm_version.bin")); + } + + #[test] + fn read_version_file_rejects_empty() { + let input_proof = write_temp_version_file(" "); + let result = read_zkm_version_from_file(&input_proof); + assert!(result.is_err()); + let _ = fs::remove_file(format!("{input_proof}.zkm_version.bin")); + } } From 1c8bce8a7a135bb3299b77136098ea0cce7a364b Mon Sep 17 00:00:00 2001 From: Blake Date: Sat, 21 Mar 2026 01:40:23 +0800 Subject: [PATCH 04/14] feat: update dependencies to use pre-release-v1.2.5 version of Ziren and adapt Groth16 verifier updates --- Cargo.lock | 172 +++++++++++++----- Cargo.toml | 14 +- circuits/commit-chain-proof/guest/Cargo.toml | 4 +- circuits/header-chain-proof/guest/Cargo.toml | 4 +- circuits/operator-proof/guest/Cargo.toml | 4 +- circuits/operator-proof/host/src/lib.rs | 9 +- circuits/state-chain-proof/guest/Cargo.toml | 4 +- circuits/watchtower-proof/guest/Cargo.toml | 4 +- .../bitcoin-light-client-circuit/Cargo.toml | 16 +- .../bitcoin-light-client-circuit/src/lib.rs | 39 +++- crates/commit-chain/Cargo.toml | 6 +- crates/commit-chain/src/lib.rs | 10 +- crates/header-chain/Cargo.toml | 4 +- crates/header-chain/src/lib.rs | 10 +- crates/state-chain/Cargo.toml | 6 +- crates/state-chain/src/lib.rs | 10 +- node/src/utils.rs | 22 +-- 17 files changed, 225 insertions(+), 113 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3210bdf9..87d4fa04 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2414,10 +2414,10 @@ dependencies = [ "tendermint", "tendermint-light-client-verifier", "tracing", - "zkm-primitives 1.2.4 (git+https://github.com/ProjectZKM/Ziren)", + "zkm-primitives 1.2.4", "zkm-verifier", "zkm-version", - "zkm-zkvm 1.2.4 (git+https://github.com/ProjectZKM/Ziren)", + "zkm-zkvm 1.2.4", ] [[package]] @@ -2766,7 +2766,7 @@ dependencies = [ "pairing 0.23.0", "rand_core 0.6.4", "subtle", - "zkm-lib 1.2.4 (git+https://github.com/ProjectZKM/Ziren)", + "zkm-lib 1.2.4", ] [[package]] @@ -3193,7 +3193,7 @@ dependencies = [ "tracing", "zkm-verifier", "zkm-version", - "zkm-zkvm 1.2.4 (git+https://github.com/ProjectZKM/Ziren)", + "zkm-zkvm 1.2.4", ] [[package]] @@ -4157,6 +4157,29 @@ dependencies = [ "syn 2.0.114", ] +[[package]] +name = "env_filter" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a1c3cc8e57274ec99de65301228b537f1e4eedc1b8e0f9411c6caac8ae7308f" +dependencies = [ + "log", + "regex", +] + +[[package]] +name = "env_logger" +version = "0.11.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2daee4ea451f429a58296525ddf28b45a3b64f1acf6587e2067437bb11e218d" +dependencies = [ + "anstream", + "anstyle", + "env_filter", + "jiff", + "log", +] + [[package]] name = "equivalent" version = "1.0.2" @@ -5323,7 +5346,7 @@ dependencies = [ "sha2 0.10.9", "zkm-verifier", "zkm-version", - "zkm-zkvm 1.2.4 (git+https://github.com/ProjectZKM/Ziren)", + "zkm-zkvm 1.2.4", ] [[package]] @@ -6177,6 +6200,30 @@ version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "92ecc6618181def0457392ccd0ee51198e065e016d1d527a7ac1b6dc7c1f09d2" +[[package]] +name = "jiff" +version = "0.2.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a3546dc96b6d42c5f24902af9e2538e82e39ad350b0c766eb3fbf2d8f3d8359" +dependencies = [ + "jiff-static", + "log", + "portable-atomic", + "portable-atomic-util", + "serde_core", +] + +[[package]] +name = "jiff-static" +version = "0.2.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a8c8b344124222efd714b73bb41f8b5120b27a7cc1c75593a6ff768d9d05aa4" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.114", +] + [[package]] name = "jobserver" version = "0.1.34" @@ -8730,6 +8777,15 @@ version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f89776e4d69bb58bc6993e99ffa1d11f228b839984854c7daeb5d37f87cbe950" +[[package]] +name = "portable-atomic-util" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "091397be61a01d4be58e7841595bd4bfedb15f1cd54977d79b8271e94ed799a3" +dependencies = [ + "portable-atomic", +] + [[package]] name = "potential_utf" version = "0.1.4" @@ -11488,7 +11544,7 @@ dependencies = [ "tracing", "zkm-verifier", "zkm-version", - "zkm-zkvm 1.2.4 (git+https://github.com/ProjectZKM/Ziren)", + "zkm-zkvm 1.2.4", ] [[package]] @@ -11684,7 +11740,7 @@ dependencies = [ "num-bigint 0.4.6", "rand 0.8.5", "rustc-hex", - "zkm-lib 1.2.4 (git+https://github.com/ProjectZKM/Ziren)", + "zkm-lib 1.2.4", ] [[package]] @@ -13837,7 +13893,8 @@ dependencies = [ [[package]] name = "zkm-build" -version = "1.2.4" +version = "1.2.5" +source = "git+https://github.com/blake-pro/Ziren.git?branch=pre-release-v1.2.5#a7446e7ef377c12fb2a42e6082f234ae0949536a" dependencies = [ "anyhow", "cargo_metadata", @@ -13847,13 +13904,15 @@ dependencies = [ [[package]] name = "zkm-core-executor" -version = "1.2.4" +version = "1.2.5" +source = "git+https://github.com/blake-pro/Ziren.git?branch=pre-release-v1.2.5#a7446e7ef377c12fb2a42e6082f234ae0949536a" dependencies = [ "anyhow", "bincode", "bytemuck", "elf", "enum-map", + "env_logger", "eyre", "hashbrown 0.14.5", "hex", @@ -13861,6 +13920,7 @@ dependencies = [ "log", "nohash-hasher", "num", + "num_enum", "p3-field", "p3-koala-bear", "p3-maybe-rayon", @@ -13875,19 +13935,22 @@ dependencies = [ "thiserror 1.0.69", "tiny-keccak", "tracing", + "tracing-subscriber 0.3.22", "typenum", "vec_map", "zkm-curves", - "zkm-primitives 1.2.4", + "zkm-primitives 1.2.5", "zkm-stark", ] [[package]] name = "zkm-core-machine" -version = "1.2.4" +version = "1.2.5" +source = "git+https://github.com/blake-pro/Ziren.git?branch=pre-release-v1.2.5#a7446e7ef377c12fb2a42e6082f234ae0949536a" dependencies = [ "bincode", "cfg-if", + "crossbeam-channel", "elliptic-curve", "generic-array 1.3.5", "hashbrown 0.14.5", @@ -13929,13 +13992,14 @@ dependencies = [ "zkm-core-executor", "zkm-curves", "zkm-derive", - "zkm-primitives 1.2.4", + "zkm-primitives 1.2.5", "zkm-stark", ] [[package]] name = "zkm-cuda" -version = "1.2.4" +version = "1.2.5" +source = "git+https://github.com/blake-pro/Ziren.git?branch=pre-release-v1.2.5#a7446e7ef377c12fb2a42e6082f234ae0949536a" dependencies = [ "bincode", "ctrlc", @@ -13952,7 +14016,8 @@ dependencies = [ [[package]] name = "zkm-curves" -version = "1.2.4" +version = "1.2.5" +source = "git+https://github.com/blake-pro/Ziren.git?branch=pre-release-v1.2.5#a7446e7ef377c12fb2a42e6082f234ae0949536a" dependencies = [ "cfg-if", "curve25519-dalek", @@ -13969,14 +14034,16 @@ dependencies = [ "thiserror 1.0.69", "tracing", "typenum", - "zkm-primitives 1.2.4", + "zkm-primitives 1.2.5", "zkm-stark", ] [[package]] name = "zkm-derive" -version = "1.2.4" +version = "1.2.5" +source = "git+https://github.com/blake-pro/Ziren.git?branch=pre-release-v1.2.5#a7446e7ef377c12fb2a42e6082f234ae0949536a" dependencies = [ + "proc-macro2", "quote", "syn 1.0.109", ] @@ -13984,6 +14051,7 @@ dependencies = [ [[package]] name = "zkm-lib" version = "1.2.4" +source = "git+https://github.com/ProjectZKM/Ziren#d5b7577c683dfceeecb90325d3277d34dc52bf17" dependencies = [ "bincode", "cfg-if", @@ -13995,20 +14063,21 @@ dependencies = [ [[package]] name = "zkm-lib" -version = "1.2.4" -source = "git+https://github.com/ProjectZKM/Ziren#d5b7577c683dfceeecb90325d3277d34dc52bf17" +version = "1.2.5" +source = "git+https://github.com/blake-pro/Ziren.git?branch=pre-release-v1.2.5#a7446e7ef377c12fb2a42e6082f234ae0949536a" dependencies = [ "bincode", "cfg-if", "elliptic-curve", "serde", "sha2 0.10.9", - "zkm-primitives 1.2.4 (git+https://github.com/ProjectZKM/Ziren)", + "zkm-primitives 1.2.5", ] [[package]] name = "zkm-primitives" version = "1.2.4" +source = "git+https://github.com/ProjectZKM/Ziren#d5b7577c683dfceeecb90325d3277d34dc52bf17" dependencies = [ "bincode", "hex", @@ -14025,8 +14094,8 @@ dependencies = [ [[package]] name = "zkm-primitives" -version = "1.2.4" -source = "git+https://github.com/ProjectZKM/Ziren#d5b7577c683dfceeecb90325d3277d34dc52bf17" +version = "1.2.5" +source = "git+https://github.com/blake-pro/Ziren.git?branch=pre-release-v1.2.5#a7446e7ef377c12fb2a42e6082f234ae0949536a" dependencies = [ "bincode", "hex", @@ -14043,11 +14112,13 @@ dependencies = [ [[package]] name = "zkm-prover" -version = "1.2.4" +version = "1.2.5" +source = "git+https://github.com/blake-pro/Ziren.git?branch=pre-release-v1.2.5#a7446e7ef377c12fb2a42e6082f234ae0949536a" dependencies = [ "anyhow", "bincode", "clap", + "crossbeam-channel", "dirs", "eyre", "itertools 0.13.0", @@ -14064,13 +14135,12 @@ dependencies = [ "rayon", "serde", "serde_json", - "sha2 0.10.9", "thiserror 1.0.69", "tracing", "tracing-subscriber 0.3.22", "zkm-core-executor", "zkm-core-machine", - "zkm-primitives 1.2.4", + "zkm-primitives 1.2.5", "zkm-recursion-circuit", "zkm-recursion-compiler", "zkm-recursion-core", @@ -14080,7 +14150,8 @@ dependencies = [ [[package]] name = "zkm-recursion-circuit" -version = "1.2.4" +version = "1.2.5" +source = "git+https://github.com/blake-pro/Ziren.git?branch=pre-release-v1.2.5#a7446e7ef377c12fb2a42e6082f234ae0949536a" dependencies = [ "hashbrown 0.14.5", "itertools 0.13.0", @@ -14103,7 +14174,7 @@ dependencies = [ "zkm-core-executor", "zkm-core-machine", "zkm-derive", - "zkm-primitives 1.2.4", + "zkm-primitives 1.2.5", "zkm-recursion-compiler", "zkm-recursion-core", "zkm-recursion-gnark-ffi", @@ -14112,7 +14183,8 @@ dependencies = [ [[package]] name = "zkm-recursion-compiler" -version = "1.2.4" +version = "1.2.5" +source = "git+https://github.com/blake-pro/Ziren.git?branch=pre-release-v1.2.5#a7446e7ef377c12fb2a42e6082f234ae0949536a" dependencies = [ "backtrace", "itertools 0.13.0", @@ -14124,7 +14196,7 @@ dependencies = [ "tracing", "vec_map", "zkm-core-machine", - "zkm-primitives 1.2.4", + "zkm-primitives 1.2.5", "zkm-recursion-core", "zkm-recursion-derive", "zkm-stark", @@ -14132,7 +14204,8 @@ dependencies = [ [[package]] name = "zkm-recursion-core" -version = "1.2.4" +version = "1.2.5" +source = "git+https://github.com/blake-pro/Ziren.git?branch=pre-release-v1.2.5#a7446e7ef377c12fb2a42e6082f234ae0949536a" dependencies = [ "backtrace", "ff 0.13.1", @@ -14162,13 +14235,14 @@ dependencies = [ "zkhash", "zkm-core-machine", "zkm-derive", - "zkm-primitives 1.2.4", + "zkm-primitives 1.2.5", "zkm-stark", ] [[package]] name = "zkm-recursion-derive" -version = "1.2.4" +version = "1.2.5" +source = "git+https://github.com/blake-pro/Ziren.git?branch=pre-release-v1.2.5#a7446e7ef377c12fb2a42e6082f234ae0949536a" dependencies = [ "quote", "syn 1.0.109", @@ -14176,7 +14250,8 @@ dependencies = [ [[package]] name = "zkm-recursion-gnark-ffi" -version = "1.2.4" +version = "1.2.5" +source = "git+https://github.com/blake-pro/Ziren.git?branch=pre-release-v1.2.5#a7446e7ef377c12fb2a42e6082f234ae0949536a" dependencies = [ "anyhow", "bincode", @@ -14199,7 +14274,8 @@ dependencies = [ [[package]] name = "zkm-sdk" -version = "1.2.4" +version = "1.2.5" +source = "git+https://github.com/blake-pro/Ziren.git?branch=pre-release-v1.2.5#a7446e7ef377c12fb2a42e6082f234ae0949536a" dependencies = [ "alloy-primitives", "alloy-signer 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -14238,14 +14314,15 @@ dependencies = [ "zkm-core-executor", "zkm-core-machine", "zkm-cuda", - "zkm-primitives 1.2.4", + "zkm-primitives 1.2.5", "zkm-prover", "zkm-stark", ] [[package]] name = "zkm-stark" -version = "1.2.4" +version = "1.2.5" +source = "git+https://github.com/blake-pro/Ziren.git?branch=pre-release-v1.2.5#a7446e7ef377c12fb2a42e6082f234ae0949536a" dependencies = [ "arrayref", "hashbrown 0.14.5", @@ -14280,13 +14357,14 @@ dependencies = [ "tracing-forest", "tracing-subscriber 0.3.22", "zkm-derive", - "zkm-primitives 1.2.4", - "zkm-zkvm 1.2.4", + "zkm-primitives 1.2.5", + "zkm-zkvm 1.2.5", ] [[package]] name = "zkm-verifier" -version = "1.2.4" +version = "1.2.5" +source = "git+https://github.com/blake-pro/Ziren.git?branch=pre-release-v1.2.5#a7446e7ef377c12fb2a42e6082f234ae0949536a" dependencies = [ "anyhow", "ark-bn254", @@ -14299,6 +14377,7 @@ dependencies = [ "itertools 0.13.0", "lazy_static", "once_cell", + "p3-bn254-fr", "p3-commit", "p3-field", "p3-koala-bear", @@ -14312,7 +14391,7 @@ dependencies = [ "thiserror 2.0.18", "zkm-core-executor", "zkm-core-machine", - "zkm-primitives 1.2.4", + "zkm-primitives 1.2.5", "zkm-recursion-core", "zkm-sdk", "zkm-stark", @@ -14325,11 +14404,15 @@ version = "0.3.3" [[package]] name = "zkm-zkvm" version = "1.2.4" +source = "git+https://github.com/ProjectZKM/Ziren#d5b7577c683dfceeecb90325d3277d34dc52bf17" dependencies = [ "bincode", "cfg-if", "getrandom 0.2.17", "lazy_static", + "libm", + "p3-field", + "p3-koala-bear", "rand 0.8.5", "serde", "sha2 0.10.9", @@ -14339,21 +14422,18 @@ dependencies = [ [[package]] name = "zkm-zkvm" -version = "1.2.4" -source = "git+https://github.com/ProjectZKM/Ziren#980997f64e258c706d280dd4f2d0c3829341a4f2" +version = "1.2.5" +source = "git+https://github.com/blake-pro/Ziren.git?branch=pre-release-v1.2.5#a7446e7ef377c12fb2a42e6082f234ae0949536a" dependencies = [ "bincode", "cfg-if", "getrandom 0.2.17", "lazy_static", - "libm", - "p3-field", - "p3-koala-bear", "rand 0.8.5", "serde", "sha2 0.10.9", - "zkm-lib 1.2.4 (git+https://github.com/ProjectZKM/Ziren)", - "zkm-primitives 1.2.4 (git+https://github.com/ProjectZKM/Ziren)", + "zkm-lib 1.2.5", + "zkm-primitives 1.2.5", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 1d6344ab..c9449065 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -88,6 +88,8 @@ zkm-core-executor = { git = "https://github.com/ProjectZKM/Ziren" } zkm-prover = { git = "https://github.com/ProjectZKM/Ziren" } zkm-sdk = { git = "https://github.com/ProjectZKM/Ziren" } zkm-verifier = { git = "https://github.com/ProjectZKM/Ziren", features = ["ark"] } +zkm-primitives = { git = "https://github.com/ProjectZKM/Ziren" } +zkm-zkvm = { git = "https://github.com/ProjectZKM/Ziren", features = ["verify"] } #zkm-build = { path = "../Ziren/crates/build" } #zkm-core-executor = { path = "../Ziren/crates/core/executor" } @@ -179,8 +181,10 @@ rust.rust_2018_idioms = { level = "deny", priority = -1 } rustdoc.all = "warn" [patch."https://github.com/ProjectZKM/Ziren"] -zkm-build = { path = "../zkm2/crates/build" } -zkm-core-executor = { path = "../zkm2/crates/core/executor" } -zkm-prover = { path = "../zkm2/crates/prover" } -zkm-sdk = { path = "../zkm2/crates/sdk" } -zkm-verifier = { path = "../zkm2/crates/verifier" } +zkm-build = { git = "https://github.com/blake-pro/Ziren.git", branch = "pre-release-v1.2.5" } +zkm-core-executor = { git = "https://github.com/blake-pro/Ziren.git", branch = "pre-release-v1.2.5" } +zkm-prover = { git = "https://github.com/blake-pro/Ziren.git", branch = "pre-release-v1.2.5" } +zkm-sdk = { git = "https://github.com/blake-pro/Ziren.git", branch = "pre-release-v1.2.5" } +zkm-verifier = { git = "https://github.com/blake-pro/Ziren.git", branch = "pre-release-v1.2.5" } +zkm-primitives = { git = "https://github.com/blake-pro/Ziren.git", branch = "pre-release-v1.2.5" } +zkm-zkvm = { git = "https://github.com/blake-pro/Ziren.git", branch = "pre-release-v1.2.5" } diff --git a/circuits/commit-chain-proof/guest/Cargo.toml b/circuits/commit-chain-proof/guest/Cargo.toml index 997f94a4..9dd816c1 100644 --- a/circuits/commit-chain-proof/guest/Cargo.toml +++ b/circuits/commit-chain-proof/guest/Cargo.toml @@ -39,5 +39,5 @@ secp256k1-v0-29-1 = { git = "https://github.com/ziren-patches/rust-secp256k1", p #secp256k1-v0-30-0 = { git = "https://github.com/ziren-patches/rust-secp256k1", package = "secp256k1", branch = "patch-0.30.0" } [patch."https://github.com/ProjectZKM/Ziren"] -zkm-zkvm = { path = "../../../../zkm2/crates/zkvm/entrypoint" } -zkm-verifier = { path = "../../../../zkm2/crates/verifier" } +zkm-zkvm = { git = "https://github.com/blake-pro/Ziren.git", branch = "pre-release-v1.2.5" } +zkm-verifier = { git = "https://github.com/blake-pro/Ziren.git", branch = "pre-release-v1.2.5" } diff --git a/circuits/header-chain-proof/guest/Cargo.toml b/circuits/header-chain-proof/guest/Cargo.toml index 5939724f..8f6af345 100644 --- a/circuits/header-chain-proof/guest/Cargo.toml +++ b/circuits/header-chain-proof/guest/Cargo.toml @@ -40,5 +40,5 @@ alloy-primitives-v1-1-2 = { git = "https://github.com/ziren-patches/core.git", p #secp256k1-v0-30-0 = { git = "https://github.com/ziren-patches/rust-secp256k1", package = "secp256k1", branch = "patch-0.30.0" } [patch."https://github.com/ProjectZKM/Ziren"] -zkm-zkvm = { path = "../../../../zkm2/crates/zkvm/entrypoint" } -zkm-verifier = { path = "../../../../zkm2/crates/verifier" } +zkm-zkvm = { git = "https://github.com/blake-pro/Ziren.git", branch = "pre-release-v1.2.5" } +zkm-verifier = { git = "https://github.com/blake-pro/Ziren.git", branch = "pre-release-v1.2.5" } diff --git a/circuits/operator-proof/guest/Cargo.toml b/circuits/operator-proof/guest/Cargo.toml index 83d9c98a..f3d169a0 100644 --- a/circuits/operator-proof/guest/Cargo.toml +++ b/circuits/operator-proof/guest/Cargo.toml @@ -44,5 +44,5 @@ secp256k1-v0-29-1 = { git = "https://github.com/ziren-patches/rust-secp256k1", p #bitcoin = { git = "https://github.com/ProjectZKM/rust-bitcoin", branch = "patch-0.32.7" } [patch."https://github.com/ProjectZKM/Ziren"] -zkm-zkvm = { path = "../../../../zkm2/crates/zkvm/entrypoint" } -zkm-verifier = { path = "../../../../zkm2/crates/verifier" } +zkm-zkvm = { git = "https://github.com/blake-pro/Ziren.git", branch = "pre-release-v1.2.5" } +zkm-verifier = { git = "https://github.com/blake-pro/Ziren.git", branch = "pre-release-v1.2.5" } diff --git a/circuits/operator-proof/host/src/lib.rs b/circuits/operator-proof/host/src/lib.rs index 7e1917c2..0853f091 100644 --- a/circuits/operator-proof/host/src/lib.rs +++ b/circuits/operator-proof/host/src/lib.rs @@ -451,7 +451,7 @@ mod tests { use ark_bn254::Bn254; use ark_groth16::{Groth16, r1cs_to_qap::LibsnarkReduction}; - use zkm_verifier::{GROTH16_VK_BYTES, convert_ark, get_snark_vk_meta}; + use zkm_verifier::{Groth16Verifier, IMM_GROTH16_VK_BYTES, convert_ark_imm_wrap_vk}; #[tokio::test] #[ignore = "local test"] @@ -470,10 +470,11 @@ mod tests { U256::from_le_bytes(a.2.clone()) ); - let groth16_vk = &GROTH16_VK_BYTES; + let groth16_vk = &IMM_GROTH16_VK_BYTES; + let part_stark_vk = Groth16Verifier::get_part_stark_vk(&proof.zkm_version); let vk_hash = String::from_utf8(vk_bytes).unwrap(); - let snark_vk_meta = get_snark_vk_meta(&proof.zkm_version).unwrap(); - let ark_proof = convert_ark(&proof, &vk_hash, &snark_vk_meta, groth16_vk).unwrap(); + let ark_proof = + convert_ark_imm_wrap_vk(&proof, &vk_hash, groth16_vk, part_stark_vk).unwrap(); // Verify the arkworks proof. let ok = Groth16::::verify_proof( diff --git a/circuits/state-chain-proof/guest/Cargo.toml b/circuits/state-chain-proof/guest/Cargo.toml index 34eb058a..44a817a9 100644 --- a/circuits/state-chain-proof/guest/Cargo.toml +++ b/circuits/state-chain-proof/guest/Cargo.toml @@ -37,5 +37,5 @@ secp256k1-v0-29-1 = { git = "https://github.com/ziren-patches/rust-secp256k1", p #secp256k1-v0-30-0 = { git = "https://github.com/ziren-patches/rust-secp256k1", package = "secp256k1", branch = "patch-0.30.0" } [patch."https://github.com/ProjectZKM/Ziren"] -zkm-zkvm = { path = "../../../../zkm2/crates/zkvm/entrypoint" } -zkm-verifier = { path = "../../../../zkm2/crates/verifier" } +zkm-zkvm = { git = "https://github.com/blake-pro/Ziren.git", branch = "pre-release-v1.2.5" } +zkm-verifier = { git = "https://github.com/blake-pro/Ziren.git", branch = "pre-release-v1.2.5" } diff --git a/circuits/watchtower-proof/guest/Cargo.toml b/circuits/watchtower-proof/guest/Cargo.toml index 88c0baee..5018b950 100644 --- a/circuits/watchtower-proof/guest/Cargo.toml +++ b/circuits/watchtower-proof/guest/Cargo.toml @@ -44,5 +44,5 @@ secp256k1-v0-29-1 = { git = "https://github.com/ziren-patches/rust-secp256k1", p #bitcoin = { git = "https://github.com/ProjectZKM/rust-bitcoin", branch = "patch-0.32.7" } [patch."https://github.com/ProjectZKM/Ziren"] -zkm-zkvm = { path = "../../../../zkm2/crates/zkvm/entrypoint" } -zkm-verifier = { path = "../../../../zkm2/crates/verifier" } +zkm-zkvm = { git = "https://github.com/blake-pro/Ziren.git", branch = "pre-release-v1.2.5" } +zkm-verifier = { git = "https://github.com/blake-pro/Ziren.git", branch = "pre-release-v1.2.5" } diff --git a/crates/bitcoin-light-client-circuit/Cargo.toml b/crates/bitcoin-light-client-circuit/Cargo.toml index db4df6eb..d7d30b4d 100644 --- a/crates/bitcoin-light-client-circuit/Cargo.toml +++ b/crates/bitcoin-light-client-circuit/Cargo.toml @@ -9,15 +9,15 @@ bitcoin = { workspace = true, features = ["serde", "rand", "secp-recovery"] } bincode = "1.3.3" # workspace -guest-executor = { workspace = true } -header-chain = { path = "../header-chain" } -commit-chain = { path = "../commit-chain" } -state-chain = { path = "../state-chain" } +guest-executor = { workspace = true } +header-chain = { workspace = true } +commit-chain = { workspace = true } +state-chain = { workspace = true } # Ziren -zkm-verifier = { git = "https://github.com/ProjectZKM/Ziren", package = "zkm-verifier" } -zkm-zkvm = { git = "https://github.com/ProjectZKM/Ziren", package = "zkm-zkvm", features = ["verify"] } -zkm-primitives = { git = "https://github.com/ProjectZKM/Ziren" } +zkm-verifier = { workspace = true } +zkm-zkvm = { workspace = true } +zkm-primitives = { workspace = true } zkm-version = { workspace = true } #zkm-verifier = { path = "../../../Ziren/crates/verifier" } #zkm-zkvm = { path = "../../../Ziren/crates/zkvm/entrypoint", features = ["verify"] } @@ -30,7 +30,7 @@ revm-database-interface = { workspace = true, features = ["serde"]} #revm = { workspace = true, branch = "patch-31.0.2", features = ["serde", "bn"], default-features = false } sha2 = "0.10.9" -hex = "0.4.3" +hex = { workspace = true } #prost = { version = "0.13", features = ["prost-derive"], default-features = false } #prost-derive = { version = "0.13", default-features = true } diff --git a/crates/bitcoin-light-client-circuit/src/lib.rs b/crates/bitcoin-light-client-circuit/src/lib.rs index be61befd..4e8ade28 100644 --- a/crates/bitcoin-light-client-circuit/src/lib.rs +++ b/crates/bitcoin-light-client-circuit/src/lib.rs @@ -18,8 +18,9 @@ use header_chain::{ HeaderChainPrevProofType, MMRHost, SPV, verify_merkle_proof, }; use state_chain::{StateChainCircuitInput, StateChainPrevProofType}; +use std::panic::{AssertUnwindSafe, catch_unwind}; use zkm_primitives::io::ZKMPublicValues; -use zkm_verifier::{Groth16Verifier, get_snark_vk_meta}; +use zkm_verifier::{Groth16Verifier, IMM_GROTH16_VK_BYTES}; use zkm_version::{ ZKM_VERSION_BYTES_LEN, ZkmVersionBytes, decode_zkm_version_fixed, encode_zkm_version_fixed, }; @@ -535,21 +536,28 @@ pub fn parse_watchtower_commitment( } // Check the public values are consistent with the total work and block hash +fn groth16_verifier_keys(zkm_version: &str) -> Result<(&'static [u8], &'static [u8]), String> { + let imm_groth16_vk = *IMM_GROTH16_VK_BYTES; + let part_stark_vk = + catch_unwind(AssertUnwindSafe(|| Groth16Verifier::get_part_stark_vk(zkm_version))) + .map_err(|_| format!("failed to load part_stark_vk for zkm_version '{zkm_version}'"))?; + Ok((imm_groth16_vk, part_stark_vk)) +} + pub fn verify_proof( proof: &[u8], zkm_public_values: &[u8], zkm_vk_hash: &[u8], zkm_version: &str, ) -> Result<(), String> { - let groth16_vk = *zkm_verifier::GROTH16_VK_BYTES; + let (groth16_vk, part_stark_vk) = groth16_verifier_keys(zkm_version)?; let zkm_vk_hash = String::from_utf8(zkm_vk_hash.to_vec()).map_err(|e| e.to_string())?; - let snark_vk_meta = get_snark_vk_meta(zkm_version).map_err(|e| e.to_string())?; - match Groth16Verifier::verify( + match Groth16Verifier::verify_by_imm_groth16_vk( proof, zkm_public_values, &zkm_vk_hash, - &snark_vk_meta, groth16_vk, + part_stark_vk, ) { Ok(_) => Ok(()), Err(err) => Err(format!("Verify Groth16 proof, err: {err:?}")), @@ -576,6 +584,21 @@ mod tests { const VK_HASH: &str = include_str!("../../../circuits/data/watchtower/output3.bin.vk_hash.bin"); const ZKM_VERSION: &str = "v1.2.4"; + #[test] + fn test_groth16_verifier_keys_keep_common_vk_available() { + assert!(!IMM_GROTH16_VK_BYTES.is_empty()); + + match groth16_verifier_keys(ZKM_VERSION) { + Ok((imm_groth16_vk, part_stark_vk)) => { + assert_eq!(imm_groth16_vk, *IMM_GROTH16_VK_BYTES); + assert!(!part_stark_vk.is_empty()); + } + Err(err) => { + assert!(err.contains("failed to load part_stark_vk")); + } + } + } + #[test] fn test_build_watchtower_commitment() { let graph_id = hex::decode("00112233445566778899aabbccddeeff").unwrap().try_into().unwrap(); @@ -689,4 +712,10 @@ mod tests { assert!(result.is_err()); assert!(!result.unwrap_err().contains("too long")); } + + #[test] + fn test_groth16_verifier_keys_reject_unknown_version_without_panic() { + let result = groth16_verifier_keys("v0.0.0-test"); + assert!(result.is_err()); + } } diff --git a/crates/commit-chain/Cargo.toml b/crates/commit-chain/Cargo.toml index 4c86186e..87e10883 100644 --- a/crates/commit-chain/Cargo.toml +++ b/crates/commit-chain/Cargo.toml @@ -13,8 +13,8 @@ guest-executor = { workspace = true } #header-chain = { path = "../header-chain" } # Ziren -zkm-verifier = { git = "https://github.com/ProjectZKM/Ziren", package = "zkm-verifier" } -zkm-zkvm = { git = "https://github.com/ProjectZKM/Ziren", package = "zkm-zkvm", features = ["verify"] } +zkm-verifier = { workspace = true } +zkm-zkvm = { workspace = true } zkm-version = { workspace = true } #zkm-verifier = { path = "../../../Ziren/crates/verifier" } #zkm-zkvm = { path = "../../../Ziren/crates/zkvm/entrypoint", features = ["verify"] } @@ -27,7 +27,7 @@ revm-database-interface = { workspace = true, features = ["serde"]} #revm = { workspace = true, features = ["serde", "bn"], default-features = false } sha2 = "0.10.9" -hex = "0.4.3" +hex = { workspace = true } #prost = { version = "0.13", features = ["prost-derive"], default-features = false } #prost-derive = { version = "0.13", default-features = true } diff --git a/crates/commit-chain/src/lib.rs b/crates/commit-chain/src/lib.rs index 3b508a8b..de1524f7 100644 --- a/crates/commit-chain/src/lib.rs +++ b/crates/commit-chain/src/lib.rs @@ -2,7 +2,7 @@ mod publisher; pub use publisher::*; mod commit_chain; pub use commit_chain::*; -use zkm_verifier::{Groth16Verifier, get_snark_vk_meta}; +use zkm_verifier::{Groth16Verifier, IMM_GROTH16_VK_BYTES}; pub fn commit_chain_circuit(input: CommitChainCircuitInput) -> CommitChainCircuitOutput { let mut chain_state = match input.prev_proof { @@ -11,15 +11,15 @@ pub fn commit_chain_circuit(input: CommitChainCircuitInput) -> CommitChainCircui } CommitChainPrevProofType::PrevProof(prev_proof) => { println!("verify commit chain of prev proof"); - let groth16_vk = *zkm_verifier::GROTH16_VK_BYTES; + let groth16_vk = *IMM_GROTH16_VK_BYTES; + let part_stark_vk = Groth16Verifier::get_part_stark_vk(&input.zkm_version); let zkm_vk_hash = String::from_utf8(input.zkm_vk_hash.to_vec()).unwrap(); - let snark_vk_meta = get_snark_vk_meta(&input.zkm_version).unwrap(); - Groth16Verifier::verify( + Groth16Verifier::verify_by_imm_groth16_vk( &input.zkm_proof, &input.zkm_public_values, &zkm_vk_hash, - &snark_vk_meta, groth16_vk, + part_stark_vk, ) .unwrap(); prev_proof.chain_state diff --git a/crates/header-chain/Cargo.toml b/crates/header-chain/Cargo.toml index d24842eb..d8da991a 100644 --- a/crates/header-chain/Cargo.toml +++ b/crates/header-chain/Cargo.toml @@ -10,8 +10,8 @@ sha2 = { version = "0.10.9", default-features = false } bitcoin = { workspace = true, features = ["serde", "rand", "secp-recovery"] } serde = { workspace = true, default-features = false } crypto-bigint = { version = "0.5.5", default-features = false } -zkm-zkvm = { git = "https://github.com/ProjectZKM/Ziren", package = "zkm-zkvm", features = ["verify"] } -zkm-verifier = { git = "https://github.com/ProjectZKM/Ziren", package = "zkm-verifier" } +zkm-zkvm = { workspace = true } +zkm-verifier = { workspace = true } zkm-version = { workspace = true } [dev-dependencies] diff --git a/crates/header-chain/src/lib.rs b/crates/header-chain/src/lib.rs index 80b757d4..ce91b0bf 100644 --- a/crates/header-chain/src/lib.rs +++ b/crates/header-chain/src/lib.rs @@ -12,7 +12,7 @@ pub use transaction::*; pub mod spv; pub use spv::SPV; -use zkm_verifier::{Groth16Verifier, get_snark_vk_meta}; +use zkm_verifier::{Groth16Verifier, IMM_GROTH16_VK_BYTES}; /// The main entry point of the header chain circuit. pub fn header_chain_circuit(input: HeaderChainCircuitInput) -> BlockHeaderCircuitOutput { @@ -22,15 +22,15 @@ pub fn header_chain_circuit(input: HeaderChainCircuitInput) -> BlockHeaderCircui HeaderChainPrevProofType::GenesisBlock => ChainState::new(), HeaderChainPrevProofType::PrevProof(prev_proof) => { println!("verify header chain of prev proof"); - let groth16_vk = *zkm_verifier::GROTH16_VK_BYTES; + let groth16_vk = *IMM_GROTH16_VK_BYTES; + let part_stark_vk = Groth16Verifier::get_part_stark_vk(&input.zkm_version); let zkm_vk_hash = String::from_utf8(input.zkm_vk_hash.to_vec()).unwrap(); - let snark_vk_meta = get_snark_vk_meta(&input.zkm_version).unwrap(); - Groth16Verifier::verify( + Groth16Verifier::verify_by_imm_groth16_vk( &input.zkm_proof, &input.zkm_public_values, &zkm_vk_hash, - &snark_vk_meta, groth16_vk, + part_stark_vk, ) .unwrap(); diff --git a/crates/state-chain/Cargo.toml b/crates/state-chain/Cargo.toml index 56154706..44d2d33c 100644 --- a/crates/state-chain/Cargo.toml +++ b/crates/state-chain/Cargo.toml @@ -13,8 +13,8 @@ guest-executor = { workspace = true } header-chain = { path = "../header-chain" } # Ziren -zkm-verifier = { git = "https://github.com/ProjectZKM/Ziren", package = "zkm-verifier" } -zkm-zkvm = { git = "https://github.com/ProjectZKM/Ziren", package = "zkm-zkvm", features = ["verify"] } +zkm-verifier = { workspace = true } +zkm-zkvm = { workspace = true } zkm-version = { workspace = true } #zkm-verifier = { path = "../../../Ziren/crates/verifier" } #zkm-zkvm = { path = "../../../Ziren/crates/zkvm/entrypoint", features = ["verify"] } @@ -27,7 +27,7 @@ revm-database-interface = { workspace = true, features = ["serde"]} #revm = { workspace = true, features = ["serde", "bn"], default-features = false } sha2 = "0.10.9" -hex = "0.4.3" +hex = { workspace = true } prost = { version = "0.13", features = ["prost-derive"], default-features = false } prost-derive = { version = "0.13", default-features = true } diff --git a/crates/state-chain/src/lib.rs b/crates/state-chain/src/lib.rs index 4cf21b54..fd24a5d7 100644 --- a/crates/state-chain/src/lib.rs +++ b/crates/state-chain/src/lib.rs @@ -3,7 +3,7 @@ mod state_chain; pub use cbft::*; pub use state_chain::*; -use zkm_verifier::{Groth16Verifier, get_snark_vk_meta}; +use zkm_verifier::{Groth16Verifier, IMM_GROTH16_VK_BYTES}; pub fn state_chain_circuit(input: StateChainCircuitInput) -> StateChainCircuitOutput { let mut chain_state = match input.prev_proof { @@ -15,15 +15,15 @@ pub fn state_chain_circuit(input: StateChainCircuitInput) -> StateChainCircuitOu } StateChainPrevProofType::PrevProof(prev_proof) => { println!("verify state chain of prev proof"); - let groth16_vk = *zkm_verifier::GROTH16_VK_BYTES; + let groth16_vk = *IMM_GROTH16_VK_BYTES; + let part_stark_vk = Groth16Verifier::get_part_stark_vk(&input.zkm_version); let zkm_vk_hash = String::from_utf8(input.zkm_vk_hash.to_vec()).unwrap(); - let snark_vk_meta = get_snark_vk_meta(&input.zkm_version).unwrap(); - Groth16Verifier::verify( + Groth16Verifier::verify_by_imm_groth16_vk( &input.zkm_proof, &input.zkm_public_values, &zkm_vk_hash, - &snark_vk_meta, groth16_vk, + part_stark_vk, ) .unwrap(); prev_proof.chain_state diff --git a/node/src/utils.rs b/node/src/utils.rs index e0daa1a7..3fdafafa 100644 --- a/node/src/utils.rs +++ b/node/src/utils.rs @@ -71,7 +71,7 @@ use store::{ }; use stun_client::{Attribute, Class, Client}; use zkm_sdk::{ZKM_CIRCUIT_VERSION, ZKMProofWithPublicValues}; -use zkm_verifier::{GROTH16_VK_BYTES, convert_ark, get_snark_vk_meta}; +use zkm_verifier::{Groth16Verifier, IMM_GROTH16_VK_BYTES, convert_ark_imm_wrap_vk}; use crate::env; use crate::rpc_service::routes::v1::{ @@ -1954,17 +1954,15 @@ pub async fn get_operator_proof( // TODO: additionally check constant and included_watchtower with included_watchtowers. //proof.public_values.head(); info!("get_operator_proof parse proof successfully"); - let groth16_vk = &GROTH16_VK_BYTES; - let snark_vk_meta = get_snark_vk_meta(&proof.zkm_version).map_err(|e| { - anyhow!( - "failed to load snark vk meta for zkm_version '{}': {e}", - proof.zkm_version - ) - })?; - let ark_proof = - convert_ark(&proof, &proof_data.vk, &snark_vk_meta, groth16_vk).map_err( - |e| anyhow!("failed to convert operator proof to ark format: {e}"), - )?; + let groth16_vk = &IMM_GROTH16_VK_BYTES; + let part_stark_vk = Groth16Verifier::get_part_stark_vk(&proof.zkm_version); + let ark_proof = convert_ark_imm_wrap_vk( + &proof, + &proof_data.vk, + groth16_vk, + part_stark_vk, + ) + .map_err(|e| anyhow!("failed to convert operator proof to ark format: {e}"))?; info!("get_operator_proof parse proof successfully"); Ok(( From a41af3d9c0ec50fca0a13c00fb04e3e6d0c185ff Mon Sep 17 00:00:00 2001 From: Blake Date: Thu, 26 Mar 2026 11:22:41 +0800 Subject: [PATCH 05/14] feat: add part_stark_vk handling and attestation functionality --- Cargo.lock | 79 +- Cargo.toml | 4 +- circuits/commit-chain-proof/guest/Cargo.toml | 2 +- circuits/operator-proof/guest/src/main.rs | 11 +- circuits/operator-proof/host/Cargo.toml | 2 +- circuits/operator-proof/host/src/lib.rs | 94 ++- circuits/watchtower-proof/guest/src/main.rs | 8 +- circuits/watchtower-proof/host/src/lib.rs | 55 +- .../src/attestation.rs | 696 ++++++++++++++++++ .../bitcoin-light-client-circuit/src/lib.rs | 310 +++++--- crates/bitvm2-ga/src/tests.rs | 9 +- crates/commit-chain/src/commit_chain.rs | 1 + crates/commit-chain/src/lib.rs | 6 +- crates/header-chain/src/header_chain.rs | 1 + crates/header-chain/src/lib.rs | 6 +- crates/state-chain/src/lib.rs | 6 +- crates/state-chain/src/state_chain.rs | 1 + crates/zkm-version/Cargo.toml | 1 + crates/zkm-version/src/lib.rs | 14 +- node/Cargo.toml | 6 +- node/src/bin/part_stark_vk_attest.rs | 114 +++ node/src/utils.rs | 26 +- 22 files changed, 1229 insertions(+), 223 deletions(-) create mode 100644 crates/bitcoin-light-client-circuit/src/attestation.rs create mode 100644 node/src/bin/part_stark_vk_attest.rs diff --git a/Cargo.lock b/Cargo.lock index 87d4fa04..6c62c5bb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2272,7 +2272,7 @@ dependencies = [ "bitflags 2.10.0", "cexpr", "clang-sys", - "itertools 0.13.0", + "itertools 0.10.5", "log", "prettyplease 0.2.37", "proc-macro2", @@ -2414,10 +2414,10 @@ dependencies = [ "tendermint", "tendermint-light-client-verifier", "tracing", - "zkm-primitives 1.2.4", + "zkm-primitives", "zkm-verifier", "zkm-version", - "zkm-zkvm 1.2.4", + "zkm-zkvm", ] [[package]] @@ -3193,7 +3193,7 @@ dependencies = [ "tracing", "zkm-verifier", "zkm-version", - "zkm-zkvm 1.2.4", + "zkm-zkvm", ] [[package]] @@ -5346,7 +5346,7 @@ dependencies = [ "sha2 0.10.9", "zkm-verifier", "zkm-version", - "zkm-zkvm 1.2.4", + "zkm-zkvm", ] [[package]] @@ -11544,7 +11544,7 @@ dependencies = [ "tracing", "zkm-verifier", "zkm-version", - "zkm-zkvm 1.2.4", + "zkm-zkvm", ] [[package]] @@ -13939,7 +13939,7 @@ dependencies = [ "typenum", "vec_map", "zkm-curves", - "zkm-primitives 1.2.5", + "zkm-primitives", "zkm-stark", ] @@ -13992,7 +13992,7 @@ dependencies = [ "zkm-core-executor", "zkm-curves", "zkm-derive", - "zkm-primitives 1.2.5", + "zkm-primitives", "zkm-stark", ] @@ -14034,7 +14034,7 @@ dependencies = [ "thiserror 1.0.69", "tracing", "typenum", - "zkm-primitives 1.2.5", + "zkm-primitives", "zkm-stark", ] @@ -14058,7 +14058,7 @@ dependencies = [ "elliptic-curve", "serde", "sha2 0.10.9", - "zkm-primitives 1.2.4", + "zkm-primitives", ] [[package]] @@ -14071,25 +14071,7 @@ dependencies = [ "elliptic-curve", "serde", "sha2 0.10.9", - "zkm-primitives 1.2.5", -] - -[[package]] -name = "zkm-primitives" -version = "1.2.4" -source = "git+https://github.com/ProjectZKM/Ziren#d5b7577c683dfceeecb90325d3277d34dc52bf17" -dependencies = [ - "bincode", - "hex", - "lazy_static", - "num-bigint 0.4.6", - "p3-field", - "p3-koala-bear", - "p3-monty-31", - "p3-poseidon2", - "p3-symmetric", - "serde", - "sha2 0.10.9", + "zkm-primitives", ] [[package]] @@ -14140,7 +14122,7 @@ dependencies = [ "tracing-subscriber 0.3.22", "zkm-core-executor", "zkm-core-machine", - "zkm-primitives 1.2.5", + "zkm-primitives", "zkm-recursion-circuit", "zkm-recursion-compiler", "zkm-recursion-core", @@ -14174,7 +14156,7 @@ dependencies = [ "zkm-core-executor", "zkm-core-machine", "zkm-derive", - "zkm-primitives 1.2.5", + "zkm-primitives", "zkm-recursion-compiler", "zkm-recursion-core", "zkm-recursion-gnark-ffi", @@ -14196,7 +14178,7 @@ dependencies = [ "tracing", "vec_map", "zkm-core-machine", - "zkm-primitives 1.2.5", + "zkm-primitives", "zkm-recursion-core", "zkm-recursion-derive", "zkm-stark", @@ -14235,7 +14217,7 @@ dependencies = [ "zkhash", "zkm-core-machine", "zkm-derive", - "zkm-primitives 1.2.5", + "zkm-primitives", "zkm-stark", ] @@ -14314,7 +14296,7 @@ dependencies = [ "zkm-core-executor", "zkm-core-machine", "zkm-cuda", - "zkm-primitives 1.2.5", + "zkm-primitives", "zkm-prover", "zkm-stark", ] @@ -14357,8 +14339,8 @@ dependencies = [ "tracing-forest", "tracing-subscriber 0.3.22", "zkm-derive", - "zkm-primitives 1.2.5", - "zkm-zkvm 1.2.5", + "zkm-primitives", + "zkm-zkvm", ] [[package]] @@ -14391,7 +14373,7 @@ dependencies = [ "thiserror 2.0.18", "zkm-core-executor", "zkm-core-machine", - "zkm-primitives 1.2.5", + "zkm-primitives", "zkm-recursion-core", "zkm-sdk", "zkm-stark", @@ -14400,24 +14382,8 @@ dependencies = [ [[package]] name = "zkm-version" version = "0.3.3" - -[[package]] -name = "zkm-zkvm" -version = "1.2.4" -source = "git+https://github.com/ProjectZKM/Ziren#d5b7577c683dfceeecb90325d3277d34dc52bf17" dependencies = [ - "bincode", - "cfg-if", - "getrandom 0.2.17", - "lazy_static", - "libm", - "p3-field", - "p3-koala-bear", - "rand 0.8.5", - "serde", - "sha2 0.10.9", - "zkm-lib 1.2.4", - "zkm-primitives 1.2.4", + "anyhow", ] [[package]] @@ -14429,11 +14395,14 @@ dependencies = [ "cfg-if", "getrandom 0.2.17", "lazy_static", + "libm", + "p3-field", + "p3-koala-bear", "rand 0.8.5", "serde", "sha2 0.10.9", "zkm-lib 1.2.5", - "zkm-primitives 1.2.5", + "zkm-primitives", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index c9449065..545ca09f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -87,7 +87,7 @@ zkm-build = { git = "https://github.com/ProjectZKM/Ziren" } zkm-core-executor = { git = "https://github.com/ProjectZKM/Ziren" } zkm-prover = { git = "https://github.com/ProjectZKM/Ziren" } zkm-sdk = { git = "https://github.com/ProjectZKM/Ziren" } -zkm-verifier = { git = "https://github.com/ProjectZKM/Ziren", features = ["ark"] } +zkm-verifier = { git = "https://github.com/ProjectZKM/Ziren" } zkm-primitives = { git = "https://github.com/ProjectZKM/Ziren" } zkm-zkvm = { git = "https://github.com/ProjectZKM/Ziren", features = ["verify"] } @@ -95,7 +95,7 @@ zkm-zkvm = { git = "https://github.com/ProjectZKM/Ziren", features = ["verify"] #zkm-core-executor = { path = "../Ziren/crates/core/executor" } #zkm-prover = { path = "../Ziren/crates/prover" } #zkm-sdk = { path = "../Ziren/crates/sdk" } -#zkm-verifier = { path = "../Ziren/crates/verifier", features = ["ark"] } +#zkm-verifier = { path = "../Ziren/crates/verifier" } bitvm2-lib = { path = "crates/bitvm2-ga" } store = { path = "crates/store" } diff --git a/circuits/commit-chain-proof/guest/Cargo.toml b/circuits/commit-chain-proof/guest/Cargo.toml index 9dd816c1..cbacee2d 100644 --- a/circuits/commit-chain-proof/guest/Cargo.toml +++ b/circuits/commit-chain-proof/guest/Cargo.toml @@ -12,7 +12,7 @@ commit-chain = { path = "../../../crates/commit-chain" } # Ziren zkm-zkvm = { git = "https://github.com/ProjectZKM/Ziren", package = "zkm-zkvm", features = ["verify"] } -zkm-verifier = { git = "https://github.com/ProjectZKM/Ziren", package = "zkm-verifier" } +#zkm-verifier = { git = "https://github.com/ProjectZKM/Ziren", package = "zkm-verifier" } #zkm-verifier = { path = "../../../../Ziren/crates/verifier" } #zkm-zkvm = { path = "../../../../Ziren/crates/zkvm/entrypoint", features = ["verify"] } diff --git a/circuits/operator-proof/guest/src/main.rs b/circuits/operator-proof/guest/src/main.rs index abaa74be..f5c6dbcd 100644 --- a/circuits/operator-proof/guest/src/main.rs +++ b/circuits/operator-proof/guest/src/main.rs @@ -5,7 +5,7 @@ use header_chain::{ HeaderChainCircuitInput, SPV, }; use alloy_primitives::{U256, Address}; -use bitcoin_light_client_circuit::EthClientExecutorInput; +use bitcoin_light_client_circuit::{EthClientExecutorInput, OperatorAttestationInputs}; use commit_chain::CommitChainCircuitInput; use state_chain::StateChainCircuitInput; use bitcoin::{ScriptBuf, TxOut, Transaction}; @@ -27,10 +27,11 @@ pub fn main() { let operator_header_chain: HeaderChainCircuitInput = zkm_zkvm::io::read(); let operator_commit_chain: CommitChainCircuitInput = zkm_zkvm::io::read(); let operator_state_chain: StateChainCircuitInput = zkm_zkvm::io::read(); + let attestation: OperatorAttestationInputs = zkm_zkvm::io::read(); let spv_ss_commit: SPV = zkm_zkvm::io::read(); let operator_committed_blockhash: [u8; 32] = zkm_zkvm::io::read(); - let (btc_best_block_hash, constant, included_watchtowers) = bitcoin_light_client_circuit::propose_longest_chain( + let output = bitcoin_light_client_circuit::propose_longest_chain( included_watchertowers, graph_id, operator_genesis_sequencer_commit_txid, @@ -41,12 +42,10 @@ pub fn main() { operator_header_chain, operator_commit_chain, operator_state_chain, + attestation, spv_ss_commit, operator_committed_blockhash, ); - zkm_zkvm::io::commit(&btc_best_block_hash); - zkm_zkvm::io::commit(&constant); - zkm_zkvm::io::commit(&included_watchtowers); + zkm_zkvm::io::commit(&output); } - diff --git a/circuits/operator-proof/host/Cargo.toml b/circuits/operator-proof/host/Cargo.toml index f187d5ca..b4ecf6f0 100644 --- a/circuits/operator-proof/host/Cargo.toml +++ b/circuits/operator-proof/host/Cargo.toml @@ -48,7 +48,7 @@ zkm-version.workspace = true # Ziren zkm-sdk.workspace = true zkm-prover.workspace = true -zkm-verifier.workspace = true +zkm-verifier = { workspace = true, features = ["ark"] } [dev-dependencies] bitvm2-lib.workspace = true diff --git a/circuits/operator-proof/host/src/lib.rs b/circuits/operator-proof/host/src/lib.rs index 0853f091..480496fa 100644 --- a/circuits/operator-proof/host/src/lib.rs +++ b/circuits/operator-proof/host/src/lib.rs @@ -6,14 +6,17 @@ use bitcoin::{ hashes::Hash, secp256k1::{PublicKey, XOnlyPublicKey}, }; -use bitcoin_light_client_circuit::build_spv; -use bitcoin_script::script; use borsh::BorshDeserialize; use client::btc_chain::BTCClient; -use commit_chain::{CommitChainCircuitInput, CommitChainPrevProofType}; -use header_chain::{CircuitBlockHeader, HeaderChainCircuitInput, HeaderChainPrevProofType}; +use commit_chain::{ + CommitChainCircuitInput, CommitChainCircuitOutput, CommitChainPrevProofType, + extract_data_from_commitment_outputs, +}; +use header_chain::{ + BlockHeaderCircuitOutput, CircuitBlockHeader, HeaderChainCircuitInput, HeaderChainPrevProofType, +}; use proof_builder::{LongRunning, ProofBuilder, ProofRequest}; -use state_chain::{StateChainCircuitInput, StateChainPrevProofType}; +use state_chain::{StateChainCircuitInput, StateChainCircuitOutput, StateChainPrevProofType}; use std::str::FromStr; use util::get_btc_block_confirms; use zkm_sdk::{ @@ -22,6 +25,12 @@ use zkm_sdk::{ }; use zkm_version::read_zkm_version_from_file; +use bincode::deserialize; +use bitcoin_light_client_circuit::{ + OperatorAttestationInputs, build_spv, load_unique_part_stark_vk_witnesses, + parse_watchtower_commitment, parse_watchtower_public_outputs, part_stark_vk_attestation_dir, +}; +use bitcoin_script::script; use clap::Parser; /// The arguments for the cli. #[derive(Debug, Clone, Parser, serde::Deserialize, serde::Serialize)] @@ -84,11 +93,14 @@ impl LongRunning for Args { /// A program that aggregates the proofs of the simple program. const OPERATOR: &[u8] = include_elf!("guest"); +use serde::de::DeserializeOwned; use std::fs; +use std::panic::{AssertUnwindSafe, catch_unwind}; use sha2::{Digest, Sha256}; use std::sync::OnceLock; static ELF_ID: OnceLock = OnceLock::new(); +use zkm_verifier::Groth16Verifier; pub async fn fetch_target_block_and_watchtower_tx( esplora_url: &str, @@ -230,6 +242,25 @@ impl OperatorProofBuilder { } } +fn load_proof_public_output(proof_path: &str) -> anyhow::Result { + let public_inputs = fs::read(format!("{proof_path}.public_inputs.bin")) + .context("Failed to read public inputs")?; + deserialize(&public_inputs).context("Failed to decode proof public outputs") +} + +fn load_current_part_stark_vk(zkm_version: &str) -> anyhow::Result> { + catch_unwind(AssertUnwindSafe(|| Groth16Verifier::get_part_stark_vk(zkm_version).to_vec())) + .map_err(|_| anyhow::anyhow!("Failed to load part_stark_vk for zkm_version {zkm_version}")) +} + +fn extract_watchtower_part_stark_vk(tx: &Transaction) -> Option> { + let commitment = + catch_unwind(AssertUnwindSafe(|| extract_data_from_commitment_outputs(&tx.output))).ok()?; + let (_, _, public_values, _, _) = parse_watchtower_commitment(&commitment).ok()?; + let outputs = parse_watchtower_public_outputs(&public_values).ok()?; + Some(outputs.part_stark_vk) +} + impl ProofBuilder for OperatorProofBuilder { fn client(&self) -> &zkm_sdk::ProverClient { &self.client @@ -338,6 +369,43 @@ impl ProofBuilder for OperatorProofBuilder { blocks: vec![], } }; + let header_chain_output: BlockHeaderCircuitOutput = + load_proof_public_output(header_chain_input_proof)?; + let commit_chain_output: CommitChainCircuitOutput = + load_proof_public_output(commit_chain_input_proof)?; + let state_chain_output: StateChainCircuitOutput = + load_proof_public_output(state_chain_input_proof)?; + let current_part_stark_vk = load_current_part_stark_vk(&self.client.version())?; + let current_source_index = 3usize; + let mut requested_part_stark_vks = vec![ + header_chain_output.part_stark_vk, + commit_chain_output.part_stark_vk, + state_chain_output.part_stark_vk, + current_part_stark_vk, + ]; + let mut watchtower_source_indexes = + vec![current_source_index; watchtower_challenge_txns.len()]; + for (index, tx) in watchtower_challenge_txns.iter().enumerate() { + if let Some(part_stark_vk) = extract_watchtower_part_stark_vk(tx) { + watchtower_source_indexes[index] = requested_part_stark_vks.len(); + requested_part_stark_vks.push(part_stark_vk); + } + } + let attestation_dir = part_stark_vk_attestation_dir(); + let (unique_witnesses, witness_refs) = + load_unique_part_stark_vk_witnesses(&attestation_dir, &requested_part_stark_vks) + .map_err(anyhow::Error::msg)?; + let attestation_inputs = OperatorAttestationInputs { + unique_witnesses, + header_ref: witness_refs[0], + commit_ref: witness_refs[1], + state_ref: witness_refs[2], + watchtower_refs: watchtower_source_indexes + .into_iter() + .map(|source_index| witness_refs[source_index]) + .collect(), + current_ref: witness_refs[current_source_index], + }; // --- spv --- // //let latest_sequencer_commit_txid = Txid::from_str(&latest_sequencer_commit_txid).unwrap(); @@ -397,6 +465,7 @@ impl ProofBuilder for OperatorProofBuilder { stdin.write(&header_chain_input); stdin.write(&commit_chain_input); stdin.write(&state_chain_input); + stdin.write(&attestation_inputs); stdin.write(&spv_ss_commit); stdin.write(&operator_committed_blockhash.to_byte_array()); @@ -437,6 +506,7 @@ impl ProofBuilder for OperatorProofBuilder { let public_value_hex = hex::encode(proof.public_values.to_vec()); let proof_size = proof.bytes().len(); let zkm_version = proof.zkm_version.clone(); + std::fs::write(&format!("{}.public_inputs.bin", output), proof.public_values.to_vec())?; std::fs::write(&format!("{}.vk_hash.bin", output), self.verifying_key.bytes32())?; std::fs::write(&format!("{}.zkm_version.bin", output), zkm_version)?; let proof = bincode::serialize(&proof).unwrap(); @@ -462,19 +532,19 @@ mod tests { let proof: ZKMProofWithPublicValues = bincode::deserialize(&proof_bytes).unwrap(); - let a: ([u8; 32], [u8; 32], [u8; 32]) = proof.public_values.clone().read(); + let a: bitcoin_light_client_circuit::OperatorPublicOutputs = + proof.public_values.clone().read(); println!( "block hash: {:?}, constant: {:?}, included map: {:?}", - hex::encode(a.0), - hex::encode(a.1), - U256::from_le_bytes(a.2.clone()) + hex::encode(a.btc_best_block_hash), + hex::encode(a.constant), + U256::from_le_bytes(a.included_watchtowers) ); - let groth16_vk = &IMM_GROTH16_VK_BYTES; - let part_stark_vk = Groth16Verifier::get_part_stark_vk(&proof.zkm_version); let vk_hash = String::from_utf8(vk_bytes).unwrap(); let ark_proof = - convert_ark_imm_wrap_vk(&proof, &vk_hash, groth16_vk, part_stark_vk).unwrap(); + convert_ark_imm_wrap_vk(&proof, &vk_hash, &IMM_GROTH16_VK_BYTES, &a.part_stark_vk) + .unwrap(); // Verify the arkworks proof. let ok = Groth16::::verify_proof( diff --git a/circuits/watchtower-proof/guest/src/main.rs b/circuits/watchtower-proof/guest/src/main.rs index cda108ac..c522794c 100644 --- a/circuits/watchtower-proof/guest/src/main.rs +++ b/circuits/watchtower-proof/guest/src/main.rs @@ -6,6 +6,7 @@ use header_chain::{ HeaderChainCircuitInput, SPV, }; +use bitcoin_light_client_circuit::WatchtowerAttestationInputs; use commit_chain::CommitChainCircuitInput; use state_chain::StateChainCircuitInput; @@ -15,16 +16,17 @@ pub fn main() { let header_chain: HeaderChainCircuitInput = zkm_zkvm::io::read(); // private inputs let commit_chain: CommitChainCircuitInput = zkm_zkvm::io::read(); let state_chain: StateChainCircuitInput = zkm_zkvm::io::read(); + let attestation: WatchtowerAttestationInputs = zkm_zkvm::io::read(); let spv: SPV = zkm_zkvm::io::read(); - let (total_work, btc_best_block_height) = bitcoin_light_client_circuit::watch_longest_chain( + let output = bitcoin_light_client_circuit::watch_longest_chain( genesis_sequencer_commit_txid, latest_sequencer_commit_txid, header_chain, commit_chain, state_chain, + attestation, spv ); - zkm_zkvm::io::commit(&total_work); - zkm_zkvm::io::commit(&btc_best_block_height); + zkm_zkvm::io::commit(&output); } diff --git a/circuits/watchtower-proof/host/src/lib.rs b/circuits/watchtower-proof/host/src/lib.rs index 8284eb0e..6af16ebf 100644 --- a/circuits/watchtower-proof/host/src/lib.rs +++ b/circuits/watchtower-proof/host/src/lib.rs @@ -1,26 +1,35 @@ #![feature(trim_prefix_suffix)] //! Generate watchtower proof +use anyhow::Context; +use bincode::deserialize; use borsh::BorshDeserialize; -use header_chain::{CircuitBlockHeader, HeaderChainCircuitInput, HeaderChainPrevProofType}; +use commit_chain::{CommitChainCircuitInput, CommitChainCircuitOutput, CommitChainPrevProofType}; +use header_chain::{ + BlockHeaderCircuitOutput, CircuitBlockHeader, HeaderChainCircuitInput, HeaderChainPrevProofType, +}; use zkm_sdk::{ HashableKey, Prover, ProverClient, ZKMProofKind, ZKMProofWithPublicValues, ZKMStdin, include_elf, }; use bitcoin::{Block, Network, Transaction, Txid, hashes::Hash}; -use bitcoin_light_client_circuit::build_spv; -use commit_chain::{CommitChainCircuitInput, CommitChainPrevProofType}; +use bitcoin_light_client_circuit::{ + WatchtowerAttestationInputs, build_spv, load_unique_part_stark_vk_witnesses, + part_stark_vk_attestation_dir, +}; use sha2::{Digest, Sha256}; -use state_chain::{StateChainCircuitInput, StateChainPrevProofType}; +use state_chain::{StateChainCircuitInput, StateChainCircuitOutput, StateChainPrevProofType}; use std::str::FromStr; use std::sync::OnceLock; static ELF_ID: OnceLock = OnceLock::new(); -use anyhow::Context; use proof_builder::{LongRunning, ProofBuilder, ProofRequest}; use clap::Parser; +use serde::de::DeserializeOwned; use std::fs; +use std::panic::{AssertUnwindSafe, catch_unwind}; +use zkm_verifier::Groth16Verifier; use zkm_version::read_zkm_version_from_file; // The arguments for the cli. @@ -96,6 +105,17 @@ impl WatchtowerProofBuilder { } } +fn load_proof_public_output(proof_path: &str) -> anyhow::Result { + let public_inputs = fs::read(format!("{proof_path}.public_inputs.bin")) + .context("Failed to read public inputs")?; + deserialize(&public_inputs).context("Failed to decode proof public outputs") +} + +fn load_current_part_stark_vk(zkm_version: &str) -> anyhow::Result> { + catch_unwind(AssertUnwindSafe(|| Groth16Verifier::get_part_stark_vk(zkm_version).to_vec())) + .map_err(|_| anyhow::anyhow!("Failed to load part_stark_vk for zkm_version {zkm_version}")) +} + impl ProofBuilder for WatchtowerProofBuilder { fn client(&self) -> &zkm_sdk::ProverClient { &self.client @@ -196,6 +216,30 @@ impl ProofBuilder for WatchtowerProofBuilder { blocks: vec![], } }; + let header_chain_output: BlockHeaderCircuitOutput = + load_proof_public_output(header_chain_input_proof)?; + let commit_chain_output: CommitChainCircuitOutput = + load_proof_public_output(commit_chain_input_proof)?; + let state_chain_output: StateChainCircuitOutput = + load_proof_public_output(state_chain_input_proof)?; + let current_part_stark_vk = load_current_part_stark_vk(&self.client.version())?; + let attestation_dir = part_stark_vk_attestation_dir(); + let requested_part_stark_vks = vec![ + header_chain_output.part_stark_vk, + commit_chain_output.part_stark_vk, + state_chain_output.part_stark_vk, + current_part_stark_vk, + ]; + let (unique_witnesses, witness_refs) = + load_unique_part_stark_vk_witnesses(&attestation_dir, &requested_part_stark_vks) + .map_err(anyhow::Error::msg)?; + let attestation_inputs = WatchtowerAttestationInputs { + unique_witnesses, + header_ref: witness_refs[0], + commit_ref: witness_refs[1], + state_ref: witness_refs[2], + current_ref: witness_refs[3], + }; // --- spv --- // let genesis_sequencer_commit_txid = Txid::from_str(&genesis_sequencer_commit_txid)?; @@ -235,6 +279,7 @@ impl ProofBuilder for WatchtowerProofBuilder { stdin.write(&header_chain_input); stdin.write(&commit_chain_input); stdin.write(&state_chain_input); + stdin.write(&attestation_inputs); stdin.write(&spv); let elf_id = if ELF_ID.get().is_none() { ELF_ID diff --git a/crates/bitcoin-light-client-circuit/src/attestation.rs b/crates/bitcoin-light-client-circuit/src/attestation.rs new file mode 100644 index 00000000..97adbf65 --- /dev/null +++ b/crates/bitcoin-light-client-circuit/src/attestation.rs @@ -0,0 +1,696 @@ +use bitcoin::hashes::{Hash, sha256}; +use bitcoin::secp256k1::{Message, PublicKey, Secp256k1, SecretKey, ecdsa::Signature}; +use serde::{Deserialize, Serialize}; +use std::collections::{BTreeMap, BTreeSet}; +use std::path::{Path, PathBuf}; + +pub const PART_STARK_VK_TREE_HEIGHT: usize = 6; +pub const PART_STARK_VK_TREE_LEAFS: usize = 1 << PART_STARK_VK_TREE_HEIGHT; +pub const PART_STARK_VK_ROOT_SIGNATURE_DOMAIN: &[u8] = b"bitvm2:part_stark_vk_root:v1"; +pub const PART_STARK_VK_ATTESTATION_DIR_ENV: &str = "PART_STARK_VK_ATTESTATION_DIR"; +pub const DEFAULT_PART_STARK_VK_ATTESTATION_DIR: &str = "./part-stark-vk-attestations"; + +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] +pub struct PartStarkVkRootSignature { + pub signer_pubkey_index: usize, + pub signature: Vec, +} + +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] +pub struct PartStarkVkAttestationBundle { + pub part_stark_vk: Vec, + pub leaf_index: usize, + pub merkle_path: Vec<[u8; 32]>, + pub root: [u8; 32], + pub signatures: Vec, +} + +pub type UniquePartStarkVkWitness = PartStarkVkAttestationBundle; + +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] +pub struct ProofPartStarkVkRef { + pub proof_index: usize, + pub witness_index: usize, +} + +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] +pub struct WatchtowerAttestationInputs { + pub unique_witnesses: Vec, + pub header_ref: usize, + pub commit_ref: usize, + pub state_ref: usize, + pub current_ref: usize, +} + +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] +pub struct OperatorAttestationInputs { + pub unique_witnesses: Vec, + pub header_ref: usize, + pub commit_ref: usize, + pub state_ref: usize, + pub watchtower_refs: Vec, + pub current_ref: usize, +} + +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] +pub struct PartStarkVkTreeState { + pub tree_height: usize, + pub leaves: Vec>, +} + +pub fn required_part_stark_vk_root_signers(total_publishers: usize) -> usize { + (total_publishers * 2).div_ceil(3) +} + +pub fn part_stark_vk_attestation_dir() -> PathBuf { + std::env::var(PART_STARK_VK_ATTESTATION_DIR_ENV) + .map(PathBuf::from) + .unwrap_or_else(|_| PathBuf::from(DEFAULT_PART_STARK_VK_ATTESTATION_DIR)) +} + +pub fn part_stark_vk_leaf_hash(part_stark_vk: &[u8]) -> [u8; 32] { + let mut bytes = Vec::with_capacity(1 + 4 + part_stark_vk.len()); + bytes.push(0x00); + bytes.extend_from_slice(&(part_stark_vk.len() as u32).to_le_bytes()); + bytes.extend_from_slice(part_stark_vk); + sha256::Hash::hash(&bytes).to_byte_array() +} + +pub fn part_stark_vk_internal_hash(left: [u8; 32], right: [u8; 32]) -> [u8; 32] { + let mut bytes = Vec::with_capacity(1 + 32 + 32); + bytes.push(0x01); + bytes.extend_from_slice(&left); + bytes.extend_from_slice(&right); + sha256::Hash::hash(&bytes).to_byte_array() +} + +pub fn empty_part_stark_vk_leaf_hash() -> [u8; 32] { + part_stark_vk_leaf_hash(&[]) +} + +pub fn part_stark_vk_bundle_id(part_stark_vk: &[u8]) -> String { + hex::encode(part_stark_vk_leaf_hash(part_stark_vk)) +} + +pub fn part_stark_vk_tree_state_path(dir: &Path) -> PathBuf { + dir.join("tree_state.json") +} + +pub fn part_stark_vk_bundle_path(dir: &Path, part_stark_vk: &[u8]) -> PathBuf { + dir.join("bundles").join(format!("{}.json", part_stark_vk_bundle_id(part_stark_vk))) +} + +fn build_part_stark_vk_leaf_layer( + part_stark_vks: &[Vec], + tree_height: usize, +) -> Result, String> { + let total_leafs = 1usize << tree_height; + if part_stark_vks.len() > total_leafs { + return Err(format!( + "too many part_stark_vk leafs: {}, max {}", + part_stark_vks.len(), + total_leafs + )); + } + + let mut nodes = vec![empty_part_stark_vk_leaf_hash(); total_leafs]; + for (index, part_stark_vk) in part_stark_vks.iter().enumerate() { + nodes[index] = part_stark_vk_leaf_hash(part_stark_vk); + } + Ok(nodes) +} + +pub fn build_part_stark_vk_merkle_root( + part_stark_vks: &[Vec], + tree_height: usize, +) -> Result<[u8; 32], String> { + let mut level = build_part_stark_vk_leaf_layer(part_stark_vks, tree_height)?; + while level.len() > 1 { + level = level + .chunks_exact(2) + .map(|pair| part_stark_vk_internal_hash(pair[0], pair[1])) + .collect(); + } + Ok(level[0]) +} + +pub fn build_part_stark_vk_merkle_path( + part_stark_vks: &[Vec], + tree_height: usize, + leaf_index: usize, +) -> Result, String> { + let total_leafs = 1usize << tree_height; + if leaf_index >= total_leafs { + return Err(format!("leaf index {} out of range {}", leaf_index, total_leafs)); + } + + let mut level = build_part_stark_vk_leaf_layer(part_stark_vks, tree_height)?; + let mut index = leaf_index; + let mut path = Vec::with_capacity(tree_height); + while level.len() > 1 { + path.push(level[index ^ 1]); + level = level + .chunks_exact(2) + .map(|pair| part_stark_vk_internal_hash(pair[0], pair[1])) + .collect(); + index /= 2; + } + Ok(path) +} + +pub fn verify_part_stark_vk_merkle_path( + part_stark_vk: &[u8], + leaf_index: usize, + merkle_path: &[[u8; 32]], + expected_root: [u8; 32], + tree_height: usize, +) -> Result<(), String> { + if merkle_path.len() != tree_height { + return Err(format!( + "invalid merkle path length: {}, expected {}", + merkle_path.len(), + tree_height + )); + } + + let total_leafs = 1usize << tree_height; + if leaf_index >= total_leafs { + return Err(format!("leaf index {} out of range {}", leaf_index, total_leafs)); + } + + let mut node = part_stark_vk_leaf_hash(part_stark_vk); + let mut index = leaf_index; + for sibling in merkle_path { + node = if index % 2 == 0 { + part_stark_vk_internal_hash(node, *sibling) + } else { + part_stark_vk_internal_hash(*sibling, node) + }; + index /= 2; + } + + if node != expected_root { + return Err("part_stark_vk merkle root mismatch".to_string()); + } + Ok(()) +} + +pub fn build_attestation_message_digest(tree_height: usize, root: [u8; 32]) -> [u8; 32] { + let mut bytes = Vec::with_capacity(PART_STARK_VK_ROOT_SIGNATURE_DOMAIN.len() + 1 + 1 + 1 + 32); + bytes.extend_from_slice(PART_STARK_VK_ROOT_SIGNATURE_DOMAIN); + bytes.push(0x00); + bytes.push(tree_height as u8); + bytes.push(0x00); + bytes.extend_from_slice(&root); + sha256::Hash::hash(&bytes).to_byte_array() +} + +fn verify_part_stark_vk_root_signatures( + signatures: &[PartStarkVkRootSignature], + publisher_public_keys: &[PublicKey], + tree_height: usize, + root: [u8; 32], +) -> Result<(), String> { + if publisher_public_keys.is_empty() { + return Err("publisher_public_keys is empty".to_string()); + } + + let required = required_part_stark_vk_root_signers(publisher_public_keys.len()); + let message = Message::from_digest(build_attestation_message_digest(tree_height, root)); + let secp = Secp256k1::verification_only(); + let mut seen = std::collections::BTreeSet::new(); + let mut valid = 0usize; + + for root_signature in signatures { + if root_signature.signer_pubkey_index >= publisher_public_keys.len() { + return Err(format!( + "signer_pubkey_index {} out of range {}", + root_signature.signer_pubkey_index, + publisher_public_keys.len() + )); + } + if !seen.insert(root_signature.signer_pubkey_index) { + continue; + } + + let signature = Signature::from_compact(&root_signature.signature) + .map_err(|err| format!("invalid signature encoding: {err}"))?; + let mut normalized = signature; + normalized.normalize_s(); + if normalized != signature { + return Err("signature is not low-s normalized".to_string()); + } + + secp.verify_ecdsa( + &message, + &signature, + &publisher_public_keys[root_signature.signer_pubkey_index], + ) + .map_err(|err| format!("invalid publisher root signature: {err}"))?; + valid += 1; + } + + if valid < required { + return Err(format!( + "not enough valid publisher signatures: got {}, required {}", + valid, required + )); + } + Ok(()) +} + +/// Verify that a `part_stark_vk` belongs to the fixed-height history tree and that the root is +/// approved by the current commit-chain publisher set. +pub fn verify_part_stark_vk_attestation( + bundle: &PartStarkVkAttestationBundle, + publisher_public_keys: &[PublicKey], + tree_height: usize, +) -> Result<(), String> { + verify_part_stark_vk_merkle_path( + &bundle.part_stark_vk, + bundle.leaf_index, + &bundle.merkle_path, + bundle.root, + tree_height, + )?; + verify_part_stark_vk_root_signatures( + &bundle.signatures, + publisher_public_keys, + tree_height, + bundle.root, + )?; + Ok(()) +} + +pub fn verify_part_stark_vk_witness_ref( + unique_witnesses: &[UniquePartStarkVkWitness], + witness_index: usize, + expected_part_stark_vk: &[u8], + publisher_public_keys: &[PublicKey], + tree_height: usize, +) -> Result<(), String> { + let witness = unique_witnesses.get(witness_index).ok_or_else(|| { + format!("witness index {} out of range {}", witness_index, unique_witnesses.len()) + })?; + if witness.part_stark_vk != expected_part_stark_vk { + return Err("part_stark_vk witness payload mismatch".to_string()); + } + verify_part_stark_vk_attestation(witness, publisher_public_keys, tree_height) +} + +pub fn verify_current_part_stark_vk_witness( + unique_witnesses: &[UniquePartStarkVkWitness], + witness_index: usize, + publisher_public_keys: &[PublicKey], + tree_height: usize, +) -> Result, String> { + let witness = unique_witnesses.get(witness_index).ok_or_else(|| { + format!("witness index {} out of range {}", witness_index, unique_witnesses.len()) + })?; + verify_part_stark_vk_attestation(witness, publisher_public_keys, tree_height)?; + Ok(witness.part_stark_vk.clone()) +} + +pub fn load_part_stark_vk_tree_state(dir: &Path) -> Result { + let path = part_stark_vk_tree_state_path(dir); + let bytes = std::fs::read(&path) + .map_err(|err| format!("failed to read tree state '{}': {err}", path.display()))?; + serde_json::from_slice(&bytes) + .map_err(|err| format!("failed to decode tree state '{}': {err}", path.display())) +} + +pub fn save_part_stark_vk_tree_state( + dir: &Path, + state: &PartStarkVkTreeState, +) -> Result<(), String> { + std::fs::create_dir_all(dir) + .map_err(|err| format!("failed to create attestation dir '{}': {err}", dir.display()))?; + let path = part_stark_vk_tree_state_path(dir); + let bytes = serde_json::to_vec_pretty(state) + .map_err(|err| format!("failed to encode tree state '{}': {err}", path.display()))?; + std::fs::write(&path, bytes) + .map_err(|err| format!("failed to write tree state '{}': {err}", path.display())) +} + +pub fn load_part_stark_vk_attestation_bundle( + dir: &Path, + part_stark_vk: &[u8], +) -> Result { + let path = part_stark_vk_bundle_path(dir, part_stark_vk); + let bytes = std::fs::read(&path) + .map_err(|err| format!("failed to read attestation bundle '{}': {err}", path.display()))?; + serde_json::from_slice(&bytes) + .map_err(|err| format!("failed to decode attestation bundle '{}': {err}", path.display())) +} + +pub fn save_part_stark_vk_attestation_bundle( + dir: &Path, + bundle: &PartStarkVkAttestationBundle, +) -> Result<(), String> { + let bundle_dir = dir.join("bundles"); + std::fs::create_dir_all(&bundle_dir).map_err(|err| { + format!("failed to create attestation bundle dir '{}': {err}", bundle_dir.display()) + })?; + let path = part_stark_vk_bundle_path(dir, &bundle.part_stark_vk); + let bytes = serde_json::to_vec_pretty(bundle).map_err(|err| { + format!("failed to encode attestation bundle '{}': {err}", path.display()) + })?; + std::fs::write(&path, bytes) + .map_err(|err| format!("failed to write attestation bundle '{}': {err}", path.display())) +} + +pub fn sign_part_stark_vk_root( + secret_key: &SecretKey, + tree_height: usize, + root: [u8; 32], +) -> Vec { + let secp = Secp256k1::new(); + let message = Message::from_digest(build_attestation_message_digest(tree_height, root)); + let signature = secp.sign_ecdsa(&message, secret_key); + signature.serialize_compact().to_vec() +} + +pub fn build_part_stark_vk_root_signatures( + signer_secret_keys: &[(usize, &SecretKey)], + tree_height: usize, + root: [u8; 32], +) -> Result, String> { + if signer_secret_keys.is_empty() { + return Err("publisher_secret_keys is empty".to_string()); + } + + let mut seen = BTreeSet::new(); + let mut signatures = Vec::with_capacity(signer_secret_keys.len()); + for (signer_pubkey_index, secret_key) in signer_secret_keys { + if !seen.insert(*signer_pubkey_index) { + return Err(format!( + "duplicate signer_pubkey_index {} in publisher_secret_keys", + signer_pubkey_index + )); + } + signatures.push(PartStarkVkRootSignature { + signer_pubkey_index: *signer_pubkey_index, + signature: sign_part_stark_vk_root(secret_key, tree_height, root), + }); + } + + Ok(signatures) +} + +pub fn build_part_stark_vk_attestation_bundle( + leaves: &[Vec], + tree_height: usize, + leaf_index: usize, + signatures: Vec, +) -> Result { + let part_stark_vk = leaves + .get(leaf_index) + .ok_or_else(|| format!("leaf index {} out of range {}", leaf_index, leaves.len()))? + .clone(); + Ok(PartStarkVkAttestationBundle { + part_stark_vk, + leaf_index, + merkle_path: build_part_stark_vk_merkle_path(leaves, tree_height, leaf_index)?, + root: build_part_stark_vk_merkle_root(leaves, tree_height)?, + signatures, + }) +} + +pub fn append_part_stark_vk_and_sign( + dir: &Path, + part_stark_vk: Vec, + publisher_secret_keys: &[SecretKey], +) -> Result { + let indexed_secret_keys = + publisher_secret_keys.iter().enumerate().collect::>(); + append_part_stark_vk_and_sign_with_signers(dir, part_stark_vk, &indexed_secret_keys) +} + +pub fn append_part_stark_vk_and_sign_with_signers( + dir: &Path, + part_stark_vk: Vec, + publisher_secret_keys: &[(usize, &SecretKey)], +) -> Result { + let mut state = if part_stark_vk_tree_state_path(dir).exists() { + load_part_stark_vk_tree_state(dir)? + } else { + PartStarkVkTreeState { tree_height: PART_STARK_VK_TREE_HEIGHT, leaves: vec![] } + }; + if state.tree_height != PART_STARK_VK_TREE_HEIGHT { + return Err(format!( + "unsupported tree height {}, expected {}", + state.tree_height, PART_STARK_VK_TREE_HEIGHT + )); + } + if state.leaves.len() >= (1usize << state.tree_height) { + return Err("part_stark_vk history tree is full".to_string()); + } + if state.leaves.iter().any(|leaf| leaf == &part_stark_vk) { + return Err("part_stark_vk already exists in tree".to_string()); + } + state.leaves.push(part_stark_vk.clone()); + let bundle = + resign_part_stark_vk_tree(dir, &state, publisher_secret_keys, state.leaves.len() - 1)?; + save_part_stark_vk_tree_state(dir, &state)?; + Ok(bundle) +} + +pub fn resign_current_part_stark_vk_root( + dir: &Path, + publisher_secret_keys: &[SecretKey], +) -> Result<(), String> { + let indexed_secret_keys = + publisher_secret_keys.iter().enumerate().collect::>(); + resign_current_part_stark_vk_root_with_signers(dir, &indexed_secret_keys) +} + +pub fn resign_current_part_stark_vk_root_with_signers( + dir: &Path, + publisher_secret_keys: &[(usize, &SecretKey)], +) -> Result<(), String> { + let state = load_part_stark_vk_tree_state(dir)?; + if state.leaves.is_empty() { + return Err("part_stark_vk tree is empty".to_string()); + } + for leaf_index in 0..state.leaves.len() { + let _ = resign_part_stark_vk_tree(dir, &state, publisher_secret_keys, leaf_index)?; + } + Ok(()) +} + +fn resign_part_stark_vk_tree( + dir: &Path, + state: &PartStarkVkTreeState, + publisher_secret_keys: &[(usize, &SecretKey)], + leaf_index: usize, +) -> Result { + let root = build_part_stark_vk_merkle_root(&state.leaves, state.tree_height)?; + let signatures = + build_part_stark_vk_root_signatures(publisher_secret_keys, state.tree_height, root)?; + let bundle = build_part_stark_vk_attestation_bundle( + &state.leaves, + state.tree_height, + leaf_index, + signatures, + )?; + save_part_stark_vk_attestation_bundle(dir, &bundle)?; + Ok(bundle) +} + +pub fn load_unique_part_stark_vk_witnesses( + dir: &Path, + part_stark_vks: &[Vec], +) -> Result<(Vec, Vec), String> { + let mut unique_witnesses = Vec::new(); + let mut witness_indexes = Vec::with_capacity(part_stark_vks.len()); + let mut seen = BTreeMap::, usize>::new(); + + for part_stark_vk in part_stark_vks { + if let Some(index) = seen.get(part_stark_vk) { + witness_indexes.push(*index); + continue; + } + let bundle = load_part_stark_vk_attestation_bundle(dir, part_stark_vk)?; + let index = unique_witnesses.len(); + unique_witnesses.push(bundle); + seen.insert(part_stark_vk.clone(), index); + witness_indexes.push(index); + } + + Ok((unique_witnesses, witness_indexes)) +} + +#[cfg(test)] +mod tests { + use bitcoin::secp256k1::{Message, Secp256k1, SecretKey, ecdsa::Signature}; + + use super::{ + PartStarkVkAttestationBundle, PartStarkVkRootSignature, build_attestation_message_digest, + build_part_stark_vk_merkle_path, build_part_stark_vk_merkle_root, + build_part_stark_vk_root_signatures, part_stark_vk_leaf_hash, + verify_part_stark_vk_attestation, + }; + + fn sample_part_stark_vk() -> Vec { + hex::decode("2000000000000000d157a916a6350249c6e4efd850dcdac3abf5489d36de2d1aa233c9253522871000000000") + .unwrap() + } + + #[test] + fn test_part_stark_vk_leaf_hash_matches_spec() { + assert_eq!( + hex::encode(part_stark_vk_leaf_hash(&[])), + "8855508aade16ec573d21e6a485dfd0a7624085c1a14b5ecdd6485de0c6839a4" + ); + } + + #[test] + fn test_build_part_stark_vk_merkle_root_matches_spec() { + let leaves = vec![sample_part_stark_vk(), b"hello".to_vec()]; + + assert_eq!( + hex::encode(build_part_stark_vk_merkle_root(&leaves, 6).unwrap()), + "8a091f11cab951f0c1228a891c902475b84709e568885a45658840e1b88599d4" + ); + } + + #[test] + fn test_build_attestation_message_digest_matches_spec() { + let root = hex::decode("8a091f11cab951f0c1228a891c902475b84709e568885a45658840e1b88599d4") + .unwrap() + .try_into() + .unwrap(); + + assert_eq!( + hex::encode(build_attestation_message_digest(6, root)), + "ab04ddc2489b88a48bd0a764fdcabedf2a7aa85a9efdfda5073ebf80b9fabd6a" + ); + } + + #[test] + fn test_verify_part_stark_vk_attestation_accepts_quorum_and_ignores_duplicate_signers() { + let secp = Secp256k1::new(); + let secret_keys = [ + SecretKey::from_slice(&[1u8; 32]).unwrap(), + SecretKey::from_slice(&[2u8; 32]).unwrap(), + SecretKey::from_slice(&[3u8; 32]).unwrap(), + SecretKey::from_slice(&[4u8; 32]).unwrap(), + ]; + let publisher_public_keys = secret_keys + .iter() + .map(|sk| bitcoin::secp256k1::PublicKey::from_secret_key(&secp, sk)) + .collect::>(); + + let part_stark_vk = sample_part_stark_vk(); + let leaves = vec![part_stark_vk.clone()]; + let root = build_part_stark_vk_merkle_root(&leaves, 6).unwrap(); + let digest = build_attestation_message_digest(6, root); + let message = Message::from_digest(digest); + + let sig0 = secp.sign_ecdsa(&message, &secret_keys[0]); + let sig1 = secp.sign_ecdsa(&message, &secret_keys[1]); + let sig2 = secp.sign_ecdsa(&message, &secret_keys[2]); + + let bundle = PartStarkVkAttestationBundle { + part_stark_vk, + leaf_index: 0, + merkle_path: build_part_stark_vk_merkle_path(&leaves, 6, 0).unwrap(), + root, + signatures: vec![ + PartStarkVkRootSignature { + signer_pubkey_index: 0, + signature: sig0.serialize_compact().to_vec(), + }, + PartStarkVkRootSignature { + signer_pubkey_index: 1, + signature: sig1.serialize_compact().to_vec(), + }, + PartStarkVkRootSignature { + signer_pubkey_index: 1, + signature: sig1.serialize_compact().to_vec(), + }, + PartStarkVkRootSignature { + signer_pubkey_index: 2, + signature: sig2.serialize_compact().to_vec(), + }, + ], + }; + + assert!(verify_part_stark_vk_attestation(&bundle, &publisher_public_keys, 6).is_ok()); + } + + #[test] + fn test_verify_part_stark_vk_attestation_rejects_non_member_signer() { + let secp = Secp256k1::new(); + let secret_keys = [ + SecretKey::from_slice(&[1u8; 32]).unwrap(), + SecretKey::from_slice(&[2u8; 32]).unwrap(), + SecretKey::from_slice(&[3u8; 32]).unwrap(), + ]; + let publisher_public_keys = secret_keys + .iter() + .map(|sk| bitcoin::secp256k1::PublicKey::from_secret_key(&secp, sk)) + .collect::>(); + + let outsider = SecretKey::from_slice(&[9u8; 32]).unwrap(); + let part_stark_vk = sample_part_stark_vk(); + let leaves = vec![part_stark_vk.clone()]; + let root = build_part_stark_vk_merkle_root(&leaves, 6).unwrap(); + let digest = build_attestation_message_digest(6, root); + let message = Message::from_digest(digest); + let outsider_sig: Signature = secp.sign_ecdsa(&message, &outsider); + + let bundle = PartStarkVkAttestationBundle { + part_stark_vk, + leaf_index: 0, + merkle_path: build_part_stark_vk_merkle_path(&leaves, 6, 0).unwrap(), + root, + signatures: vec![PartStarkVkRootSignature { + signer_pubkey_index: 0, + signature: outsider_sig.serialize_compact().to_vec(), + }], + }; + + assert!(verify_part_stark_vk_attestation(&bundle, &publisher_public_keys, 6).is_err()); + } + + #[test] + fn test_build_part_stark_vk_root_signatures_supports_sparse_signer_indexes() { + let secp = Secp256k1::new(); + let secret_keys = [ + SecretKey::from_slice(&[1u8; 32]).unwrap(), + SecretKey::from_slice(&[2u8; 32]).unwrap(), + SecretKey::from_slice(&[3u8; 32]).unwrap(), + SecretKey::from_slice(&[4u8; 32]).unwrap(), + SecretKey::from_slice(&[5u8; 32]).unwrap(), + ]; + let publisher_public_keys = secret_keys + .iter() + .map(|sk| bitcoin::secp256k1::PublicKey::from_secret_key(&secp, sk)) + .collect::>(); + + let leaves = vec![sample_part_stark_vk()]; + let root = build_part_stark_vk_merkle_root(&leaves, 6).unwrap(); + let signatures = build_part_stark_vk_root_signatures( + &[ + (0, &secret_keys[0]), + (2, &secret_keys[2]), + (3, &secret_keys[3]), + (4, &secret_keys[4]), + ], + 6, + root, + ) + .unwrap(); + + let bundle = PartStarkVkAttestationBundle { + part_stark_vk: leaves[0].clone(), + leaf_index: 0, + merkle_path: build_part_stark_vk_merkle_path(&leaves, 6, 0).unwrap(), + root, + signatures, + }; + + assert!(verify_part_stark_vk_attestation(&bundle, &publisher_public_keys, 6).is_ok()); + } +} diff --git a/crates/bitcoin-light-client-circuit/src/lib.rs b/crates/bitcoin-light-client-circuit/src/lib.rs index 4e8ade28..cf912a80 100644 --- a/crates/bitcoin-light-client-circuit/src/lib.rs +++ b/crates/bitcoin-light-client-circuit/src/lib.rs @@ -1,6 +1,8 @@ +mod attestation; mod signature; mod utils; use alloy_primitives::U32; +pub use attestation::*; pub use signature::*; use state_chain::verify_sequencer_commit; pub use utils::*; @@ -27,26 +29,42 @@ use zkm_version::{ use bitcoin::{ScriptBuf, TxOut, Txid, secp256k1::PublicKey}; pub use guest_executor::io::EthClientExecutorInput; +use serde::{Deserialize, Serialize}; pub const GRAPH_ID_SIZE: usize = 16; pub const PROOF_SIZE: usize = 260; pub const PUBLIC_INPUTS_SIZE: usize = 36; +pub const WATCHTOWER_COMMITMENT_PUBLIC_INPUTS_LEN_SIZE: usize = 4; pub const VK_HASH_SIZE: usize = 66; pub const ZKM_VERSION_SIZE: usize = ZKM_VERSION_BYTES_LEN; -pub const COMMITMENT_SIZE: usize = - GRAPH_ID_SIZE + PROOF_SIZE + PUBLIC_INPUTS_SIZE + VK_HASH_SIZE + ZKM_VERSION_SIZE; pub const TOTAL_WORK_SIZE: usize = 32; pub const CONSENSUS_BLOCK_HEIGHT_SIZE: usize = 4; +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] +pub struct WatchtowerPublicOutputs { + pub total_work: [u8; TOTAL_WORK_SIZE], + pub consensus_block_height: [u8; CONSENSUS_BLOCK_HEIGHT_SIZE], + pub part_stark_vk: Vec, +} + +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] +pub struct OperatorPublicOutputs { + pub btc_best_block_hash: [u8; 32], + pub constant: [u8; 32], + pub included_watchtowers: [u8; 32], + pub part_stark_vk: Vec, +} + pub fn watch_longest_chain( genesis_sequencer_commit_txid: [u8; 32], latest_sequencer_commit_txid: [u8; 32], header_chain: HeaderChainCircuitInput, commit_chain: CommitChainCircuitInput, state_chain: StateChainCircuitInput, + attestation: WatchtowerAttestationInputs, spv: SPV, -) -> ([u8; 32], u32) { +) -> WatchtowerPublicOutputs { println!("commit header, size: {}", commit_chain.commits.len()); // verify latest_sequencer_commit is valid: // * Check both latest_sequencer_commit_txid and genesis_sequencer_commit_txid are in all_sequencer_commit_txids (which is a private input) @@ -103,6 +121,37 @@ pub fn watch_longest_chain( let StateChainPrevProofType::PrevProof(state_chain_output) = &prev_proof else { panic!("Only PrevProof is supported in watch_longest_chain"); }; + verify_part_stark_vk_witness_ref( + &attestation.unique_witnesses, + attestation.header_ref, + &btc_header_chain_output.part_stark_vk, + &commit_chain_output.chain_state.publisher_public_keys, + PART_STARK_VK_TREE_HEIGHT, + ) + .expect("Failed to verify header-chain part_stark_vk attestation"); + verify_part_stark_vk_witness_ref( + &attestation.unique_witnesses, + attestation.commit_ref, + &commit_chain_output.part_stark_vk, + &commit_chain_output.chain_state.publisher_public_keys, + PART_STARK_VK_TREE_HEIGHT, + ) + .expect("Failed to verify commit-chain part_stark_vk attestation"); + verify_part_stark_vk_witness_ref( + &attestation.unique_witnesses, + attestation.state_ref, + &state_chain_output.part_stark_vk, + &commit_chain_output.chain_state.publisher_public_keys, + PART_STARK_VK_TREE_HEIGHT, + ) + .expect("Failed to verify state-chain part_stark_vk attestation"); + let current_part_stark_vk = verify_current_part_stark_vk_witness( + &attestation.unique_witnesses, + attestation.current_ref, + &commit_chain_output.chain_state.publisher_public_keys, + PART_STARK_VK_TREE_HEIGHT, + ) + .expect("Failed to verify watchtower part_stark_vk attestation"); // check the signature. let cosmos_block_bytes = &state_chain_output.chain_state.latest_cosmos_block; let cosmos_block: LightBlock = @@ -126,7 +175,11 @@ pub fn watch_longest_chain( println!("commit public inputs"); // commit public inputs - (btc_header_chain_output.chain_state.total_work, commit_chain_output.chain_state.block_height) + WatchtowerPublicOutputs { + total_work: btc_header_chain_output.chain_state.total_work, + consensus_block_height: commit_chain_output.chain_state.block_height.to_le_bytes(), + part_stark_vk: current_part_stark_vk, + } } pub fn u256_to_le_bits(u: U256) -> [bool; 256] { @@ -162,9 +215,10 @@ pub fn propose_longest_chain( operator_header_chain: HeaderChainCircuitInput, commit_chain: CommitChainCircuitInput, state_chain: StateChainCircuitInput, + attestation: OperatorAttestationInputs, spv_ss_commit: SPV, operator_committed_blockhash: [u8; 32], -) -> ([u8; 32], [u8; 32], [u8; 32]) { +) -> OperatorPublicOutputs { // verify operator_latest_sequencer_commit_txid is valid, and on operator head chain // * Check operator_latest_sequencer_commit_txid is derived from genesis_sequencer_commit_txid verify_proof( @@ -202,6 +256,22 @@ pub fn propose_longest_chain( let HeaderChainPrevProofType::PrevProof(btc_header_chain_output) = &prev_proof else { panic!("Only PrevProof is supported in propose_longest_chain"); }; + verify_part_stark_vk_witness_ref( + &attestation.unique_witnesses, + attestation.header_ref, + &btc_header_chain_output.part_stark_vk, + &commit_chain_output.chain_state.publisher_public_keys, + PART_STARK_VK_TREE_HEIGHT, + ) + .expect("Failed to verify header-chain part_stark_vk attestation"); + verify_part_stark_vk_witness_ref( + &attestation.unique_witnesses, + attestation.commit_ref, + &commit_chain_output.part_stark_vk, + &commit_chain_output.chain_state.publisher_public_keys, + PART_STARK_VK_TREE_HEIGHT, + ) + .expect("Failed to verify commit-chain part_stark_vk attestation"); let operator_total_work = btc_header_chain_output.chain_state.total_work; let operator_consensus_block_height = U32::from(commit_chain_output.chain_state.block_height); // commit header chain best block hash as pis @@ -245,21 +315,14 @@ pub fn propose_longest_chain( let commitment = &extract_data_from_commitment_outputs(&tx.output)[..]; println!("commitment: {commitment:?}"); println!("commitment hex: {}", hex::encode(commitment)); - let ( - parsed_graph_id, - proof, - public_values, - vk, - watchtower_zkm_version, - watchtower_total_work, - watchtower_consensus_block_height, - ) = match parse_watchtower_commitment(commitment) { - Ok(c) => c, - Err(err) => { - println!("Watchtower[{i}] parse commitment error, {err}"); - continue; - } - }; + let (parsed_graph_id, proof, public_values, vk, watchtower_zkm_version) = + match parse_watchtower_commitment(commitment) { + Ok(c) => c, + Err(err) => { + println!("Watchtower[{i}] parse commitment error, {err}"); + continue; + } + }; match verify_proof_fixed_version(&proof, &public_values, &vk, &watchtower_zkm_version) { Ok(_) => {} @@ -278,25 +341,48 @@ pub fn propose_longest_chain( continue; } println!("check total work with watchtower {i}"); + let watchtower_outputs = match parse_watchtower_public_outputs(&public_values) { + Ok(outputs) => outputs, + Err(err) => { + println!("Watchtower[{i}] public outputs parse error, {err}"); + continue; + } + }; + if let Err(err) = verify_part_stark_vk_witness_ref( + &attestation.unique_witnesses, + *attestation + .watchtower_refs + .get(i) + .expect("watchtower attestation refs length mismatch"), + &watchtower_outputs.part_stark_vk, + &commit_chain_output.chain_state.publisher_public_keys, + PART_STARK_VK_TREE_HEIGHT, + ) { + println!("Watchtower[{i}] invalid part_stark_vk attestation: {err}"); + continue; + } // extract ChainState // check watchtower_chain_state.total_work <= operator_header_chain.total_work - println!("watchtower total work: {:?}", U256::from_be_bytes(watchtower_total_work)); + println!( + "watchtower total work: {:?}", + U256::from_be_bytes(watchtower_outputs.total_work) + ); println!("operator total work: {operator_total_work:?}"); println!( "watchtower_consensus_block_height : {:?}", - U32::from_le_bytes(watchtower_consensus_block_height) + U32::from_le_bytes(watchtower_outputs.consensus_block_height) ); println!("operator_consensus_block_height : {operator_consensus_block_height:?}"); assert!( - U256::from_be_bytes(watchtower_total_work) + U256::from_be_bytes(watchtower_outputs.total_work) <= U256::from_be_bytes(operator_total_work) ); // check watchtower.consensus.block_height <= consensus.block_height assert!( - U32::from_le_bytes(watchtower_consensus_block_height) + U32::from_le_bytes(watchtower_outputs.consensus_block_height) <= operator_consensus_block_height ); } @@ -317,6 +403,21 @@ pub fn propose_longest_chain( let StateChainPrevProofType::PrevProof(state_chain_output) = &prev_proof else { panic!("Only PrevProof is supported in propose_longest_chain"); }; + verify_part_stark_vk_witness_ref( + &attestation.unique_witnesses, + attestation.state_ref, + &state_chain_output.part_stark_vk, + &commit_chain_output.chain_state.publisher_public_keys, + PART_STARK_VK_TREE_HEIGHT, + ) + .expect("Failed to verify state-chain part_stark_vk attestation"); + let current_part_stark_vk = verify_current_part_stark_vk_witness( + &attestation.unique_witnesses, + attestation.current_ref, + &commit_chain_output.chain_state.publisher_public_keys, + PART_STARK_VK_TREE_HEIGHT, + ) + .expect("Failed to verify operator part_stark_vk attestation"); // check the signature. let cosmos_block_bytes = &state_chain_output.chain_state.latest_cosmos_block; let cosmos_block: LightBlock = @@ -370,7 +471,12 @@ pub fn propose_longest_chain( ); //operator_public_input - (operator_committed_blockhash, constant, included_watchtowers.to_le_bytes::<32>()) + OperatorPublicOutputs { + btc_best_block_hash: operator_committed_blockhash, + constant, + included_watchtowers: included_watchtowers.to_le_bytes::<32>(), + part_stark_vk: current_part_stark_vk, + } } pub fn hash_operator_constant( @@ -448,13 +554,17 @@ pub fn build_spv( pub fn build_watchtower_commitment( graph_id: &[u8; GRAPH_ID_SIZE], - proof: &[u8; PROOF_SIZE], - public_inputs: &[u8; PUBLIC_INPUTS_SIZE], + proof: &[u8], + public_inputs: &[u8], vk_hash: &str, zkm_version: &str, ) -> Result, String> { + if proof.len() != PROOF_SIZE { + return Err(format!("invalid proof length: {}, expected {}", proof.len(), PROOF_SIZE)); + } let mut comm = graph_id.to_vec(); comm.extend_from_slice(proof); + comm.extend_from_slice(&(public_inputs.len() as u32).to_le_bytes()); comm.extend_from_slice(public_inputs); if vk_hash.len() != VK_HASH_SIZE { return Err(format!( @@ -469,37 +579,47 @@ pub fn build_watchtower_commitment( Ok(comm) } -pub type WatchtowerCommitmentResult = ( - [u8; GRAPH_ID_SIZE], - [u8; PROOF_SIZE], - [u8; PUBLIC_INPUTS_SIZE], - [u8; VK_HASH_SIZE], - ZkmVersionBytes, - [u8; TOTAL_WORK_SIZE], - [u8; CONSENSUS_BLOCK_HEIGHT_SIZE], -); +pub type WatchtowerCommitmentResult = + ([u8; GRAPH_ID_SIZE], Vec, Vec, [u8; VK_HASH_SIZE], ZkmVersionBytes); pub fn parse_watchtower_commitment( commitment: &[u8], ) -> Result { - if commitment.len() != COMMITMENT_SIZE { + let min_commitment_size = GRAPH_ID_SIZE + + PROOF_SIZE + + WATCHTOWER_COMMITMENT_PUBLIC_INPUTS_LEN_SIZE + + VK_HASH_SIZE + + ZKM_VERSION_SIZE; + if commitment.len() < min_commitment_size { return Err(format!( - "invalid commitment size: {}, expected: {}", + "invalid commitment size: {}, expected at least {}", commitment.len(), - COMMITMENT_SIZE + min_commitment_size )); } let mut end = GRAPH_ID_SIZE; let mut graph_id = [0u8; GRAPH_ID_SIZE]; graph_id.copy_from_slice(&commitment[0..GRAPH_ID_SIZE]); - let mut proof = [0u8; PROOF_SIZE]; - proof.copy_from_slice(&commitment[end..end + PROOF_SIZE]); + let proof = commitment[end..end + PROOF_SIZE].to_vec(); end += PROOF_SIZE; - let mut zkm_public_values = [0u8; PUBLIC_INPUTS_SIZE]; - zkm_public_values.copy_from_slice(&commitment[end..end + PUBLIC_INPUTS_SIZE]); - end += PUBLIC_INPUTS_SIZE; + let public_inputs_len = u32::from_le_bytes( + commitment[end..end + WATCHTOWER_COMMITMENT_PUBLIC_INPUTS_LEN_SIZE].try_into().unwrap(), + ) as usize; + end += WATCHTOWER_COMMITMENT_PUBLIC_INPUTS_LEN_SIZE; + + let expected_size = min_commitment_size + public_inputs_len; + if commitment.len() != expected_size { + return Err(format!( + "invalid commitment size: {}, expected {}", + commitment.len(), + expected_size + )); + } + + let zkm_public_values = commitment[end..end + public_inputs_len].to_vec(); + end += public_inputs_len; let mut zkm_vk_hash_bytes = [0u8; VK_HASH_SIZE]; zkm_vk_hash_bytes.copy_from_slice(&commitment[end..end + VK_HASH_SIZE]); @@ -508,31 +628,15 @@ pub fn parse_watchtower_commitment( let mut zkm_version = [0u8; ZKM_VERSION_SIZE]; zkm_version.copy_from_slice(&commitment[end..end + ZKM_VERSION_SIZE]); - // extract ChainState - let mut watchtower_total_work = [0u8; TOTAL_WORK_SIZE]; - watchtower_total_work.copy_from_slice(&zkm_public_values[0..TOTAL_WORK_SIZE]); - let mut watchtower_consensus_block_height = [0u8; CONSENSUS_BLOCK_HEIGHT_SIZE]; - watchtower_consensus_block_height.copy_from_slice( - &zkm_public_values[TOTAL_WORK_SIZE..TOTAL_WORK_SIZE + CONSENSUS_BLOCK_HEIGHT_SIZE], - ); - - println!("watchtower total work: {watchtower_total_work:?}"); - println!("watchtower total work: {:?}", U256::from_be_bytes(watchtower_total_work)); - println!("watchtower consensus block height: {watchtower_consensus_block_height:?}"); - println!( - "watchtower consensus block height: {:?}", - U32::from_le_bytes(watchtower_consensus_block_height) - ); + Ok((graph_id, proof, zkm_public_values, zkm_vk_hash_bytes, zkm_version)) +} - Ok(( - graph_id, - proof, - zkm_public_values, - zkm_vk_hash_bytes, - zkm_version, - watchtower_total_work, - watchtower_consensus_block_height, - )) +pub fn parse_watchtower_public_outputs( + zkm_public_values: &[u8], +) -> Result { + let mut public_values = ZKMPublicValues::from(zkm_public_values); + catch_unwind(AssertUnwindSafe(|| public_values.read::())) + .map_err(|_| "failed to deserialize watchtower public outputs".to_string()) } // Check the public values are consistent with the total work and block hash @@ -540,7 +644,7 @@ fn groth16_verifier_keys(zkm_version: &str) -> Result<(&'static [u8], &'static [ let imm_groth16_vk = *IMM_GROTH16_VK_BYTES; let part_stark_vk = catch_unwind(AssertUnwindSafe(|| Groth16Verifier::get_part_stark_vk(zkm_version))) - .map_err(|_| format!("failed to load part_stark_vk for zkm_version '{zkm_version}'"))?; + .map_err(|_| format!("failed to load part_stark_vk for zkm_version '{zkm_version}'"))?; Ok((imm_groth16_vk, part_stark_vk)) } @@ -603,18 +707,20 @@ mod tests { fn test_build_watchtower_commitment() { let graph_id = hex::decode("00112233445566778899aabbccddeeff").unwrap().try_into().unwrap(); - let total_work = 1006120; - let block_height = 503043; + let total_work = 1006120u64; + let block_height = 503043u32; + let part_stark_vk = vec![7u8; 44]; + let expected_outputs = WatchtowerPublicOutputs { + total_work: U256::from(total_work).to_be_bytes(), + consensus_block_height: U32::from(block_height).to_le_bytes(), + part_stark_vk: part_stark_vk.clone(), + }; + let public_inputs = bincode::serialize(&expected_outputs).unwrap(); println!("public inputs: {:?}", PUBLIC_INPUTS.len()); println!("vk hash: {:?}", VK_HASH.len()); - let comm = build_watchtower_commitment( - &graph_id, - &PROOF.try_into().unwrap(), - &PUBLIC_INPUTS.try_into().unwrap(), - VK_HASH, - ZKM_VERSION, - ) - .unwrap(); + let comm = + build_watchtower_commitment(&graph_id, PROOF, &public_inputs, VK_HASH, ZKM_VERSION) + .unwrap(); println!("comm: {:?}", comm.len()); println!("comm hex: {:?}", hex::encode(&comm)); @@ -623,11 +729,11 @@ mod tests { assert_eq!(expected.0, graph_id); assert_eq!(expected.1, PROOF); - assert_eq!(expected.2, PUBLIC_INPUTS); + assert_eq!(expected.2, public_inputs); assert_eq!(expected.3, VK_HASH.as_bytes()); assert_eq!(expected.4, encode_zkm_version_fixed(ZKM_VERSION).unwrap()); - assert_eq!(expected.5, U256::from(total_work).to_be_bytes()); - assert_eq!(expected.6, U32::from(block_height).to_le_bytes()); + let parsed_outputs = parse_watchtower_public_outputs(&expected.2).unwrap(); + assert_eq!(parsed_outputs, expected_outputs); } #[test] @@ -679,13 +785,8 @@ mod tests { let graph_id = hex::decode("00112233445566778899aabbccddeeff").unwrap().try_into().unwrap(); let too_long_version = "v1234567890123456"; assert_eq!(too_long_version.len(), ZKM_VERSION_SIZE + 1); - let result = build_watchtower_commitment( - &graph_id, - &PROOF.try_into().unwrap(), - &PUBLIC_INPUTS.try_into().unwrap(), - VK_HASH, - too_long_version, - ); + let result = + build_watchtower_commitment(&graph_id, PROOF, PUBLIC_INPUTS, VK_HASH, too_long_version); assert!(result.is_err()); } @@ -693,18 +794,33 @@ mod tests { fn test_build_watchtower_commitment_accepts_rc_version() { let graph_id = hex::decode("00112233445566778899aabbccddeeff").unwrap().try_into().unwrap(); let rc_version = "v1.12.15-rc1"; - let commitment = build_watchtower_commitment( - &graph_id, - &PROOF.try_into().unwrap(), - &PUBLIC_INPUTS.try_into().unwrap(), - VK_HASH, - rc_version, - ) - .unwrap(); + let commitment = + build_watchtower_commitment(&graph_id, PROOF, PUBLIC_INPUTS, VK_HASH, rc_version) + .unwrap(); let parsed = parse_watchtower_commitment(&commitment).unwrap(); assert_eq!(decode_zkm_version_fixed(&parsed.4).unwrap(), rc_version); } + #[test] + fn test_parse_watchtower_public_outputs_rejects_short_public_inputs() { + let result = parse_watchtower_public_outputs(&[0u8; TOTAL_WORK_SIZE + 1]); + assert!(result.is_err()); + } + + #[test] + fn test_parse_watchtower_public_outputs_reads_bincode_serialized_struct() { + let expected = WatchtowerPublicOutputs { + total_work: [9u8; TOTAL_WORK_SIZE], + consensus_block_height: 123u32.to_le_bytes(), + part_stark_vk: vec![7u8; 44], + }; + + let public_inputs = bincode::serialize(&expected).unwrap(); + let parsed = parse_watchtower_public_outputs(&public_inputs).unwrap(); + + assert_eq!(parsed, expected); + } + #[test] fn test_verify_proof_accepts_non_fixed_length_version() { let long_version = "v1.12.15-rc1+build.20260319"; diff --git a/crates/bitvm2-ga/src/tests.rs b/crates/bitvm2-ga/src/tests.rs index 97d48c81..88263ace 100644 --- a/crates/bitvm2-ga/src/tests.rs +++ b/crates/bitvm2-ga/src/tests.rs @@ -1002,15 +1002,10 @@ mod tests { //let consensus_commit_block_height = 503043; let comm = bitcoin_light_client_circuit::build_watchtower_commitment( &graph_id, - //&[0u8; PROOF_SIZE], - //&[0u8; PUBLIC_INPUTS_SIZE], - //"", - &PROOF.try_into().unwrap(), - &PUBLIC_INPUTS.try_into().unwrap(), + PROOF, + PUBLIC_INPUTS, VK_HASH, "v1.2.4", - //total_work, - //consensus_commit_block_height, ) .unwrap(); diff --git a/crates/commit-chain/src/commit_chain.rs b/crates/commit-chain/src/commit_chain.rs index 6a0d256a..78273bd6 100644 --- a/crates/commit-chain/src/commit_chain.rs +++ b/crates/commit-chain/src/commit_chain.rs @@ -91,6 +91,7 @@ pub const ZKM_VERSION_SIZE: usize = zkm_version::ZKM_VERSION_BYTES_LEN; #[derive(Serialize, Deserialize, PartialEq, Clone, Debug)] pub struct CommitChainCircuitOutput { pub chain_state: CommitChainState, + pub part_stark_vk: Vec, } #[derive(Serialize, Deserialize, PartialEq, Clone, Debug)] diff --git a/crates/commit-chain/src/lib.rs b/crates/commit-chain/src/lib.rs index de1524f7..550f02a6 100644 --- a/crates/commit-chain/src/lib.rs +++ b/crates/commit-chain/src/lib.rs @@ -5,6 +5,7 @@ pub use commit_chain::*; use zkm_verifier::{Groth16Verifier, IMM_GROTH16_VK_BYTES}; pub fn commit_chain_circuit(input: CommitChainCircuitInput) -> CommitChainCircuitOutput { + let current_part_stark_vk = Groth16Verifier::get_part_stark_vk(&input.zkm_version).to_vec(); let mut chain_state = match input.prev_proof { CommitChainPrevProofType::GenesisBlock => { CommitChainState::new(input.commits[0].genesis_txid) @@ -12,14 +13,13 @@ pub fn commit_chain_circuit(input: CommitChainCircuitInput) -> CommitChainCircui CommitChainPrevProofType::PrevProof(prev_proof) => { println!("verify commit chain of prev proof"); let groth16_vk = *IMM_GROTH16_VK_BYTES; - let part_stark_vk = Groth16Verifier::get_part_stark_vk(&input.zkm_version); let zkm_vk_hash = String::from_utf8(input.zkm_vk_hash.to_vec()).unwrap(); Groth16Verifier::verify_by_imm_groth16_vk( &input.zkm_proof, &input.zkm_public_values, &zkm_vk_hash, groth16_vk, - part_stark_vk, + ¤t_part_stark_vk, ) .unwrap(); prev_proof.chain_state @@ -27,5 +27,5 @@ pub fn commit_chain_circuit(input: CommitChainCircuitInput) -> CommitChainCircui }; chain_state.apply_commit(input.commits); - CommitChainCircuitOutput { chain_state } + CommitChainCircuitOutput { chain_state, part_stark_vk: current_part_stark_vk } } diff --git a/crates/header-chain/src/header_chain.rs b/crates/header-chain/src/header_chain.rs index d36a3841..3a6e5538 100644 --- a/crates/header-chain/src/header_chain.rs +++ b/crates/header-chain/src/header_chain.rs @@ -365,6 +365,7 @@ fn calculate_work(target: &[u8; 32]) -> U256 { )] pub struct BlockHeaderCircuitOutput { pub chain_state: ChainState, + pub part_stark_vk: Vec, } /// The input proof of the header chain circuit. diff --git a/crates/header-chain/src/lib.rs b/crates/header-chain/src/lib.rs index ce91b0bf..f2ca0147 100644 --- a/crates/header-chain/src/lib.rs +++ b/crates/header-chain/src/lib.rs @@ -16,6 +16,7 @@ use zkm_verifier::{Groth16Verifier, IMM_GROTH16_VK_BYTES}; /// The main entry point of the header chain circuit. pub fn header_chain_circuit(input: HeaderChainCircuitInput) -> BlockHeaderCircuitOutput { + let current_part_stark_vk = Groth16Verifier::get_part_stark_vk(&input.zkm_version).to_vec(); // println!("Detected network: {:?}", NETWORK_TYPE); // println!("NETWORK_CONSTANTS: {:?}", NETWORK_CONSTANTS); let mut chain_state = match input.prev_proof { @@ -23,14 +24,13 @@ pub fn header_chain_circuit(input: HeaderChainCircuitInput) -> BlockHeaderCircui HeaderChainPrevProofType::PrevProof(prev_proof) => { println!("verify header chain of prev proof"); let groth16_vk = *IMM_GROTH16_VK_BYTES; - let part_stark_vk = Groth16Verifier::get_part_stark_vk(&input.zkm_version); let zkm_vk_hash = String::from_utf8(input.zkm_vk_hash.to_vec()).unwrap(); Groth16Verifier::verify_by_imm_groth16_vk( &input.zkm_proof, &input.zkm_public_values, &zkm_vk_hash, groth16_vk, - part_stark_vk, + ¤t_part_stark_vk, ) .unwrap(); @@ -39,5 +39,5 @@ pub fn header_chain_circuit(input: HeaderChainCircuitInput) -> BlockHeaderCircui }; chain_state.apply_blocks(input.block_headers); - BlockHeaderCircuitOutput { chain_state } + BlockHeaderCircuitOutput { chain_state, part_stark_vk: current_part_stark_vk } } diff --git a/crates/state-chain/src/lib.rs b/crates/state-chain/src/lib.rs index fd24a5d7..49c959c5 100644 --- a/crates/state-chain/src/lib.rs +++ b/crates/state-chain/src/lib.rs @@ -6,6 +6,7 @@ pub use state_chain::*; use zkm_verifier::{Groth16Verifier, IMM_GROTH16_VK_BYTES}; pub fn state_chain_circuit(input: StateChainCircuitInput) -> StateChainCircuitOutput { + let current_part_stark_vk = Groth16Verifier::get_part_stark_vk(&input.zkm_version).to_vec(); let mut chain_state = match input.prev_proof { StateChainPrevProofType::GenesisBlock => { let block_hash: [u8; 32] = input.blocks[0].evm_block.current_block.hash_slow().into(); @@ -16,14 +17,13 @@ pub fn state_chain_circuit(input: StateChainCircuitInput) -> StateChainCircuitOu StateChainPrevProofType::PrevProof(prev_proof) => { println!("verify state chain of prev proof"); let groth16_vk = *IMM_GROTH16_VK_BYTES; - let part_stark_vk = Groth16Verifier::get_part_stark_vk(&input.zkm_version); let zkm_vk_hash = String::from_utf8(input.zkm_vk_hash.to_vec()).unwrap(); Groth16Verifier::verify_by_imm_groth16_vk( &input.zkm_proof, &input.zkm_public_values, &zkm_vk_hash, groth16_vk, - part_stark_vk, + ¤t_part_stark_vk, ) .unwrap(); prev_proof.chain_state @@ -31,5 +31,5 @@ pub fn state_chain_circuit(input: StateChainCircuitInput) -> StateChainCircuitOu }; chain_state.apply_blocks(input.blocks); - StateChainCircuitOutput { chain_state } + StateChainCircuitOutput { chain_state, part_stark_vk: current_part_stark_vk } } diff --git a/crates/state-chain/src/state_chain.rs b/crates/state-chain/src/state_chain.rs index ef5db6d9..1949af37 100644 --- a/crates/state-chain/src/state_chain.rs +++ b/crates/state-chain/src/state_chain.rs @@ -43,6 +43,7 @@ pub struct StateChainState { #[derive(Serialize, Deserialize, PartialEq, Clone, Debug)] pub struct StateChainCircuitOutput { pub chain_state: StateChainState, + pub part_stark_vk: Vec, } #[derive(Serialize, Deserialize, PartialEq, Clone, Debug)] diff --git a/crates/zkm-version/Cargo.toml b/crates/zkm-version/Cargo.toml index c269a83b..5f24ec48 100644 --- a/crates/zkm-version/Cargo.toml +++ b/crates/zkm-version/Cargo.toml @@ -4,6 +4,7 @@ version.workspace = true edition.workspace = true [dependencies] +anyhow = { workspace = true } [lints] workspace = true diff --git a/crates/zkm-version/src/lib.rs b/crates/zkm-version/src/lib.rs index ad0bc202..254200d8 100644 --- a/crates/zkm-version/src/lib.rs +++ b/crates/zkm-version/src/lib.rs @@ -1,3 +1,5 @@ +use anyhow::{Context, Result}; + pub const ZKM_VERSION_BYTES_LEN: usize = 16; pub type ZkmVersionBytes = [u8; ZKM_VERSION_BYTES_LEN]; @@ -36,18 +38,18 @@ pub fn parse_zkm_version(version: &str) -> Result { Ok(trimmed.to_string()) } -pub fn read_zkm_version_from_file(input_proof: &str) -> Result { +pub fn read_zkm_version_from_file(input_proof: &str) -> Result { let version_path = format!("{input_proof}.zkm_version.bin"); let raw = std::fs::read(&version_path) - .map_err(|e| format!("failed to read zkm_version file '{}': {e}", version_path))?; + .with_context(|| format!("failed to read zkm_version file '{version_path}'"))?; let version = String::from_utf8(raw) - .map_err(|e| format!("invalid UTF-8 in zkm_version file '{}': {e}", version_path))?; - parse_zkm_version(&version) + .with_context(|| format!("invalid UTF-8 in zkm_version file '{version_path}'"))?; + parse_zkm_version(&version).map_err(anyhow::Error::msg) } -pub fn read_zkm_version_fixed_from_file(input_proof: &str) -> Result { +pub fn read_zkm_version_fixed_from_file(input_proof: &str) -> Result { let version = read_zkm_version_from_file(input_proof)?; - encode_zkm_version_fixed(&version) + encode_zkm_version_fixed(&version).map_err(anyhow::Error::msg) } #[cfg(test)] diff --git a/node/Cargo.toml b/node/Cargo.toml index c9bd33e0..89be098a 100644 --- a/node/Cargo.toml +++ b/node/Cargo.toml @@ -35,6 +35,10 @@ path = "src/bin/send_bridge_out.rs" name = "update-db" path = "src/bin/db_inject.rs" +[[bin]] +name = "part-stark-vk-attest" +path = "src/bin/part_stark_vk_attest.rs" + [dependencies] libp2p = { workspace = true, features = [ "autonat", @@ -106,7 +110,7 @@ indicatif = "0.17.8" dirs = "5.0.1" zkm-sdk = { workspace = true } -zkm-verifier = { workspace = true } +zkm-verifier = { workspace = true, features = ["ark"] } borsh = {version = "1.5.3", features = ["derive"] } proof-builder = { workspace = true } diff --git a/node/src/bin/part_stark_vk_attest.rs b/node/src/bin/part_stark_vk_attest.rs new file mode 100644 index 00000000..fd39f79a --- /dev/null +++ b/node/src/bin/part_stark_vk_attest.rs @@ -0,0 +1,114 @@ +use anyhow::{Context, Result, anyhow, bail}; +use bitcoin::secp256k1::SecretKey; +use bitcoin_light_client_circuit::{ + append_part_stark_vk_and_sign_with_signers, part_stark_vk_attestation_dir, + resign_current_part_stark_vk_root_with_signers, +}; +use clap::{Parser, Subcommand}; +use std::path::PathBuf; +use std::str::FromStr; +use zkm_verifier::Groth16Verifier; + +#[derive(Debug, Clone)] +struct PublisherSignerArg { + signer_pubkey_index: usize, + secret_key: SecretKey, +} + +impl FromStr for PublisherSignerArg { + type Err = anyhow::Error; + + fn from_str(value: &str) -> Result { + let (signer_pubkey_index, secret_key) = value + .split_once(':') + .ok_or_else(|| anyhow!("invalid signer format, expected :"))?; + Ok(Self { + signer_pubkey_index: signer_pubkey_index + .parse() + .context("invalid signer_pubkey_index")?, + secret_key: SecretKey::from_str(secret_key).context("invalid secret_key hex")?, + }) + } +} + +#[derive(Debug, Parser)] +struct Cli { + #[command(subcommand)] + command: Command, +} + +#[derive(Debug, Subcommand)] +enum Command { + Append { + #[arg(long)] + part_stark_vk_file: Option, + #[arg(long)] + zkm_version: Option, + #[arg(long, value_delimiter = ',')] + publisher_signers: Vec, + #[arg(long)] + attestation_dir: Option, + }, + ResignCurrentRoot { + #[arg(long, value_delimiter = ',')] + publisher_signers: Vec, + #[arg(long)] + attestation_dir: Option, + }, +} + +fn resolve_attestation_dir(attestation_dir: Option) -> PathBuf { + attestation_dir.unwrap_or_else(part_stark_vk_attestation_dir) +} + +fn resolve_signers(publisher_signers: &[PublisherSignerArg]) -> Result> { + if publisher_signers.is_empty() { + bail!("publisher_signers is empty"); + } + Ok(publisher_signers + .iter() + .map(|signer| (signer.signer_pubkey_index, &signer.secret_key)) + .collect()) +} + +fn load_part_stark_vk( + part_stark_vk_file: Option, + zkm_version: Option, +) -> Result> { + match (part_stark_vk_file, zkm_version) { + (Some(_), Some(_)) => bail!("part_stark_vk_file and zkm_version are mutually exclusive"), + (None, None) => bail!("either part_stark_vk_file or zkm_version must be provided"), + (Some(path), None) => std::fs::read(&path) + .with_context(|| format!("failed to read part_stark_vk file '{}'", path.display())), + (None, Some(zkm_version)) => Ok(Groth16Verifier::get_part_stark_vk(&zkm_version).to_vec()), + } +} + +fn main() -> Result<()> { + dotenv::dotenv().ok(); + let cli = Cli::parse(); + + match cli.command { + Command::Append { part_stark_vk_file, zkm_version, publisher_signers, attestation_dir } => { + let attestation_dir = resolve_attestation_dir(attestation_dir); + let part_stark_vk = load_part_stark_vk(part_stark_vk_file, zkm_version)?; + let signer_refs = resolve_signers(&publisher_signers)?; + let bundle = append_part_stark_vk_and_sign_with_signers( + &attestation_dir, + part_stark_vk, + &signer_refs, + ) + .map_err(anyhow::Error::msg)?; + println!("{}", serde_json::to_string_pretty(&bundle)?); + } + Command::ResignCurrentRoot { publisher_signers, attestation_dir } => { + let attestation_dir = resolve_attestation_dir(attestation_dir); + let signer_refs = resolve_signers(&publisher_signers)?; + resign_current_part_stark_vk_root_with_signers(&attestation_dir, &signer_refs) + .map_err(anyhow::Error::msg)?; + println!("resigned part_stark_vk root attestations in {}", attestation_dir.display()); + } + } + + Ok(()) +} diff --git a/node/src/utils.rs b/node/src/utils.rs index 3fdafafa..12b649d8 100644 --- a/node/src/utils.rs +++ b/node/src/utils.rs @@ -71,7 +71,7 @@ use store::{ }; use stun_client::{Attribute, Class, Client}; use zkm_sdk::{ZKM_CIRCUIT_VERSION, ZKMProofWithPublicValues}; -use zkm_verifier::{Groth16Verifier, IMM_GROTH16_VK_BYTES, convert_ark_imm_wrap_vk}; +use zkm_verifier::{IMM_GROTH16_VK_BYTES, convert_ark_imm_wrap_vk}; use crate::env; use crate::rpc_service::routes::v1::{ @@ -1753,18 +1753,13 @@ fn gen_watchtower_commitment(graph_id: Uuid, proof_data: ProofData) -> Result Date: Thu, 26 Mar 2026 23:25:33 +0800 Subject: [PATCH 06/14] feat: update zkm-verifier dependency to use v1.2.5 and refactor GOAT RPC client to use Alloy's reqwest client --- Cargo.lock | 1956 +++++++++++------- Cargo.toml | 7 + circuits/commit-chain-proof/guest/Cargo.toml | 2 +- crates/client/src/goat_chain/goat_adaptor.rs | 7 +- 4 files changed, 1261 insertions(+), 711 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6c62c5bb..d54fd954 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -14,9 +14,9 @@ dependencies = [ [[package]] name = "addchain" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b2e69442aa5628ea6951fa33e24efe8313f4321a91bd729fc2f75bdfc858570" +checksum = "2e33f6a175ec6a9e0aca777567f9ff7c3deefc255660df887e7fa3585e9801d8" dependencies = [ "num-bigint 0.3.3", "num-integer", @@ -56,7 +56,7 @@ checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0" dependencies = [ "cfg-if", "cipher", - "cpufeatures", + "cpufeatures 0.2.17", ] [[package]] @@ -102,34 +102,34 @@ checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" [[package]] name = "alloy" -version = "1.5.2" -source = "git+https://github.com/alloy-rs/alloy#3203f839dd801e1966b4970136b59051f3856770" +version = "1.8.2" +source = "git+https://github.com/alloy-rs/alloy#c36b7b2c867e7b13ede7a5f6f8112a83c363400e" dependencies = [ - "alloy-consensus 1.5.2", + "alloy-consensus 1.8.2", "alloy-contract", "alloy-core", - "alloy-eips 1.5.2", - "alloy-genesis 1.5.2", - "alloy-network 1.5.2", - "alloy-provider 1.5.2", + "alloy-eips 1.8.2", + "alloy-genesis 1.8.2", + "alloy-network 1.8.2", + "alloy-provider 1.8.2", "alloy-pubsub", - "alloy-rpc-client 1.5.2", - "alloy-rpc-types 1.5.2", - "alloy-serde 1.5.2", - "alloy-signer 1.5.2 (git+https://github.com/alloy-rs/alloy)", + "alloy-rpc-client 1.8.2", + "alloy-rpc-types 1.8.2", + "alloy-serde 1.8.2", + "alloy-signer 1.8.2", "alloy-signer-local", - "alloy-transport 1.5.2", - "alloy-transport-http 1.5.2", + "alloy-transport 1.8.2", + "alloy-transport-http 1.8.2", "alloy-transport-ipc", "alloy-transport-ws", - "alloy-trie 0.9.3", + "alloy-trie 0.9.5", ] [[package]] name = "alloy-chains" -version = "0.2.30" +version = "0.2.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90f374d3c6d729268bbe2d0e0ff992bb97898b2df756691a62ee1d5f0506bc39" +checksum = "f4e9e31d834fe25fe991b8884e4b9f0e59db4a97d86e05d1464d6899c013cd62" dependencies = [ "alloy-primitives", "alloy-rlp", @@ -147,7 +147,7 @@ dependencies = [ "alloy-primitives", "alloy-rlp", "alloy-serde 1.0.41", - "alloy-trie 0.9.3", + "alloy-trie 0.9.5", "alloy-tx-macros 1.0.41", "auto_impl", "c-kzg", @@ -165,15 +165,15 @@ dependencies = [ [[package]] name = "alloy-consensus" -version = "1.5.2" -source = "git+https://github.com/alloy-rs/alloy#3203f839dd801e1966b4970136b59051f3856770" +version = "1.8.2" +source = "git+https://github.com/alloy-rs/alloy#c36b7b2c867e7b13ede7a5f6f8112a83c363400e" dependencies = [ - "alloy-eips 1.5.2", + "alloy-eips 1.8.2", "alloy-primitives", "alloy-rlp", - "alloy-serde 1.5.2", - "alloy-trie 0.9.3", - "alloy-tx-macros 1.5.2", + "alloy-serde 1.8.2", + "alloy-trie 0.9.5", + "alloy-tx-macros 1.8.2", "auto_impl", "borsh", "c-kzg", @@ -204,44 +204,45 @@ dependencies = [ [[package]] name = "alloy-consensus-any" -version = "1.5.2" -source = "git+https://github.com/alloy-rs/alloy#3203f839dd801e1966b4970136b59051f3856770" +version = "1.8.2" +source = "git+https://github.com/alloy-rs/alloy#c36b7b2c867e7b13ede7a5f6f8112a83c363400e" dependencies = [ - "alloy-consensus 1.5.2", - "alloy-eips 1.5.2", + "alloy-consensus 1.8.2", + "alloy-eips 1.8.2", "alloy-primitives", "alloy-rlp", - "alloy-serde 1.5.2", + "alloy-serde 1.8.2", "serde", ] [[package]] name = "alloy-contract" -version = "1.5.2" -source = "git+https://github.com/alloy-rs/alloy#3203f839dd801e1966b4970136b59051f3856770" +version = "1.8.2" +source = "git+https://github.com/alloy-rs/alloy#c36b7b2c867e7b13ede7a5f6f8112a83c363400e" dependencies = [ - "alloy-consensus 1.5.2", + "alloy-consensus 1.8.2", "alloy-dyn-abi", "alloy-json-abi", - "alloy-network 1.5.2", - "alloy-network-primitives 1.5.2", + "alloy-network 1.8.2", + "alloy-network-primitives 1.8.2", "alloy-primitives", - "alloy-provider 1.5.2", + "alloy-provider 1.8.2", "alloy-pubsub", - "alloy-rpc-types-eth 1.5.2", + "alloy-rpc-types-eth 1.8.2", "alloy-sol-types", - "alloy-transport 1.5.2", + "alloy-transport 1.8.2", "futures", "futures-util", "serde_json", "thiserror 2.0.18", + "tracing", ] [[package]] name = "alloy-core" -version = "1.5.4" +version = "1.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcfbc46fa201350bf859add798d818bbe68b84882a8af832e4433791d28a975d" +checksum = "23e8604b0c092fabc80d075ede181c9b9e596249c70b99253082d7e689836529" dependencies = [ "alloy-dyn-abi", "alloy-json-abi", @@ -252,9 +253,9 @@ dependencies = [ [[package]] name = "alloy-dyn-abi" -version = "1.5.4" +version = "1.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14ff5ee5f27aa305bda825c735f686ad71bb65508158f059f513895abe69b8c3" +checksum = "cc2db5c583aaef0255aa63a4fe827f826090142528bba48d1bf4119b62780cad" dependencies = [ "alloy-json-abi", "alloy-primitives", @@ -263,7 +264,7 @@ dependencies = [ "itoa", "serde", "serde_json", - "winnow", + "winnow 0.7.15", ] [[package]] @@ -308,9 +309,9 @@ dependencies = [ [[package]] name = "alloy-eip7928" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3231de68d5d6e75332b7489cfcc7f4dfabeba94d990a10e4b923af0e6623540" +checksum = "f8222b1d88f9a6d03be84b0f5e76bb60cd83991b43ad8ab6477f0e4a7809b98d" dependencies = [ "alloy-primitives", "alloy-rlp", @@ -341,8 +342,8 @@ dependencies = [ [[package]] name = "alloy-eips" -version = "1.5.2" -source = "git+https://github.com/alloy-rs/alloy#3203f839dd801e1966b4970136b59051f3856770" +version = "1.8.2" +source = "git+https://github.com/alloy-rs/alloy#c36b7b2c867e7b13ede7a5f6f8112a83c363400e" dependencies = [ "alloy-eip2124", "alloy-eip2930", @@ -350,7 +351,7 @@ dependencies = [ "alloy-eip7928", "alloy-primitives", "alloy-rlp", - "alloy-serde 1.5.2", + "alloy-serde 1.8.2", "auto_impl", "borsh", "c-kzg", @@ -359,7 +360,6 @@ dependencies = [ "serde", "serde_with", "sha2 0.10.9", - "thiserror 2.0.18", ] [[package]] @@ -390,20 +390,20 @@ dependencies = [ "alloy-eips 1.0.41", "alloy-primitives", "alloy-serde 1.0.41", - "alloy-trie 0.9.3", + "alloy-trie 0.9.5", "serde", "serde_with", ] [[package]] name = "alloy-genesis" -version = "1.5.2" -source = "git+https://github.com/alloy-rs/alloy#3203f839dd801e1966b4970136b59051f3856770" +version = "1.8.2" +source = "git+https://github.com/alloy-rs/alloy#c36b7b2c867e7b13ede7a5f6f8112a83c363400e" dependencies = [ - "alloy-eips 1.5.2", + "alloy-eips 1.8.2", "alloy-primitives", - "alloy-serde 1.5.2", - "alloy-trie 0.9.3", + "alloy-serde 1.8.2", + "alloy-trie 0.9.5", "borsh", "serde", "serde_with", @@ -424,9 +424,9 @@ dependencies = [ [[package]] name = "alloy-json-abi" -version = "1.5.4" +version = "1.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8708475665cc00e081c085886e68eada2f64cfa08fc668213a9231655093d4de" +checksum = "e9dbe713da0c737d9e5e387b0ba790eb98b14dd207fe53eef50e19a5a8ec3dac" dependencies = [ "alloy-primitives", "alloy-sol-type-parser", @@ -450,8 +450,8 @@ dependencies = [ [[package]] name = "alloy-json-rpc" -version = "1.5.2" -source = "git+https://github.com/alloy-rs/alloy#3203f839dd801e1966b4970136b59051f3856770" +version = "1.8.2" +source = "git+https://github.com/alloy-rs/alloy#c36b7b2c867e7b13ede7a5f6f8112a83c363400e" dependencies = [ "alloy-primitives", "alloy-sol-types", @@ -489,19 +489,19 @@ dependencies = [ [[package]] name = "alloy-network" -version = "1.5.2" -source = "git+https://github.com/alloy-rs/alloy#3203f839dd801e1966b4970136b59051f3856770" -dependencies = [ - "alloy-consensus 1.5.2", - "alloy-consensus-any 1.5.2", - "alloy-eips 1.5.2", - "alloy-json-rpc 1.5.2", - "alloy-network-primitives 1.5.2", +version = "1.8.2" +source = "git+https://github.com/alloy-rs/alloy#c36b7b2c867e7b13ede7a5f6f8112a83c363400e" +dependencies = [ + "alloy-consensus 1.8.2", + "alloy-consensus-any 1.8.2", + "alloy-eips 1.8.2", + "alloy-json-rpc 1.8.2", + "alloy-network-primitives 1.8.2", "alloy-primitives", - "alloy-rpc-types-any 1.5.2", - "alloy-rpc-types-eth 1.5.2", - "alloy-serde 1.5.2", - "alloy-signer 1.5.2 (git+https://github.com/alloy-rs/alloy)", + "alloy-rpc-types-any 1.8.2", + "alloy-rpc-types-eth 1.8.2", + "alloy-serde 1.8.2", + "alloy-signer 1.8.2", "alloy-sol-types", "async-trait", "auto_impl", @@ -526,13 +526,13 @@ dependencies = [ [[package]] name = "alloy-network-primitives" -version = "1.5.2" -source = "git+https://github.com/alloy-rs/alloy#3203f839dd801e1966b4970136b59051f3856770" +version = "1.8.2" +source = "git+https://github.com/alloy-rs/alloy#c36b7b2c867e7b13ede7a5f6f8112a83c363400e" dependencies = [ - "alloy-consensus 1.5.2", - "alloy-eips 1.5.2", + "alloy-consensus 1.8.2", + "alloy-eips 1.8.2", "alloy-primitives", - "alloy-serde 1.5.2", + "alloy-serde 1.8.2", "serde", ] @@ -567,9 +567,9 @@ dependencies = [ [[package]] name = "alloy-primitives" -version = "1.5.4" +version = "1.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b88cf92ed20685979ed1d8472422f0c6c2d010cec77caf63aaa7669cc1a7bc2" +checksum = "de3b431b4e72cd8bd0ec7a50b4be18e73dab74de0dba180eef171055e5d5926e" dependencies = [ "alloy-rlp", "bytes", @@ -634,27 +634,27 @@ dependencies = [ [[package]] name = "alloy-provider" -version = "1.5.2" -source = "git+https://github.com/alloy-rs/alloy#3203f839dd801e1966b4970136b59051f3856770" +version = "1.8.2" +source = "git+https://github.com/alloy-rs/alloy#c36b7b2c867e7b13ede7a5f6f8112a83c363400e" dependencies = [ "alloy-chains", - "alloy-consensus 1.5.2", - "alloy-eips 1.5.2", - "alloy-json-rpc 1.5.2", - "alloy-network 1.5.2", - "alloy-network-primitives 1.5.2", + "alloy-consensus 1.8.2", + "alloy-eips 1.8.2", + "alloy-json-rpc 1.8.2", + "alloy-network 1.8.2", + "alloy-network-primitives 1.8.2", "alloy-primitives", "alloy-pubsub", - "alloy-rpc-client 1.5.2", + "alloy-rpc-client 1.8.2", "alloy-rpc-types-anvil", - "alloy-rpc-types-debug 1.5.2", - "alloy-rpc-types-eth 1.5.2", - "alloy-rpc-types-trace 1.5.2", + "alloy-rpc-types-debug 1.8.2", + "alloy-rpc-types-eth 1.8.2", + "alloy-rpc-types-trace 1.8.2", "alloy-rpc-types-txpool", - "alloy-signer 1.5.2 (git+https://github.com/alloy-rs/alloy)", + "alloy-signer 1.8.2", "alloy-sol-types", - "alloy-transport 1.5.2", - "alloy-transport-http 1.5.2", + "alloy-transport 1.8.2", + "alloy-transport-http 1.8.2", "alloy-transport-ipc", "alloy-transport-ws", "async-stream", @@ -667,7 +667,7 @@ dependencies = [ "lru 0.16.3", "parking_lot", "pin-project", - "reqwest 0.12.28", + "reqwest 0.13.2", "serde", "serde_json", "thiserror 2.0.18", @@ -679,12 +679,12 @@ dependencies = [ [[package]] name = "alloy-pubsub" -version = "1.5.2" -source = "git+https://github.com/alloy-rs/alloy#3203f839dd801e1966b4970136b59051f3856770" +version = "1.8.2" +source = "git+https://github.com/alloy-rs/alloy#c36b7b2c867e7b13ede7a5f6f8112a83c363400e" dependencies = [ - "alloy-json-rpc 1.5.2", + "alloy-json-rpc 1.8.2", "alloy-primitives", - "alloy-transport 1.5.2", + "alloy-transport 1.8.2", "auto_impl", "bimap", "futures", @@ -700,9 +700,9 @@ dependencies = [ [[package]] name = "alloy-rlp" -version = "0.3.12" +version = "0.3.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f70d83b765fdc080dbcd4f4db70d8d23fe4761f2f02ebfa9146b833900634b4" +checksum = "e93e50f64a77ad9c5470bf2ad0ca02f228da70c792a8f06634801e202579f35e" dependencies = [ "alloy-rlp-derive", "arrayvec", @@ -711,13 +711,13 @@ dependencies = [ [[package]] name = "alloy-rlp-derive" -version = "0.3.12" +version = "0.3.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64b728d511962dda67c1bc7ea7c03736ec275ed2cf4c35d9585298ac9ccf3b73" +checksum = "ce8849c74c9ca0f5a03da1c865e3eb6f768df816e67dd3721a398a8a7e398011" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -744,19 +744,19 @@ dependencies = [ [[package]] name = "alloy-rpc-client" -version = "1.5.2" -source = "git+https://github.com/alloy-rs/alloy#3203f839dd801e1966b4970136b59051f3856770" +version = "1.8.2" +source = "git+https://github.com/alloy-rs/alloy#c36b7b2c867e7b13ede7a5f6f8112a83c363400e" dependencies = [ - "alloy-json-rpc 1.5.2", + "alloy-json-rpc 1.8.2", "alloy-primitives", "alloy-pubsub", - "alloy-transport 1.5.2", - "alloy-transport-http 1.5.2", + "alloy-transport 1.8.2", + "alloy-transport-http 1.8.2", "alloy-transport-ipc", "alloy-transport-ws", "futures", "pin-project", - "reqwest 0.12.28", + "reqwest 0.13.2", "serde", "serde_json", "tokio", @@ -780,28 +780,28 @@ dependencies = [ [[package]] name = "alloy-rpc-types" -version = "1.5.2" -source = "git+https://github.com/alloy-rs/alloy#3203f839dd801e1966b4970136b59051f3856770" +version = "1.8.2" +source = "git+https://github.com/alloy-rs/alloy#c36b7b2c867e7b13ede7a5f6f8112a83c363400e" dependencies = [ "alloy-primitives", "alloy-rpc-types-anvil", - "alloy-rpc-types-debug 1.5.2", - "alloy-rpc-types-engine 1.5.2", - "alloy-rpc-types-eth 1.5.2", - "alloy-rpc-types-trace 1.5.2", + "alloy-rpc-types-debug 1.8.2", + "alloy-rpc-types-engine 1.8.2", + "alloy-rpc-types-eth 1.8.2", + "alloy-rpc-types-trace 1.8.2", "alloy-rpc-types-txpool", - "alloy-serde 1.5.2", + "alloy-serde 1.8.2", "serde", ] [[package]] name = "alloy-rpc-types-anvil" -version = "1.5.2" -source = "git+https://github.com/alloy-rs/alloy#3203f839dd801e1966b4970136b59051f3856770" +version = "1.8.2" +source = "git+https://github.com/alloy-rs/alloy#c36b7b2c867e7b13ede7a5f6f8112a83c363400e" dependencies = [ "alloy-primitives", - "alloy-rpc-types-eth 1.5.2", - "alloy-serde 1.5.2", + "alloy-rpc-types-eth 1.8.2", + "alloy-serde 1.8.2", "serde", ] @@ -817,12 +817,12 @@ dependencies = [ [[package]] name = "alloy-rpc-types-any" -version = "1.5.2" -source = "git+https://github.com/alloy-rs/alloy#3203f839dd801e1966b4970136b59051f3856770" +version = "1.8.2" +source = "git+https://github.com/alloy-rs/alloy#c36b7b2c867e7b13ede7a5f6f8112a83c363400e" dependencies = [ - "alloy-consensus-any 1.5.2", - "alloy-rpc-types-eth 1.5.2", - "alloy-serde 1.5.2", + "alloy-consensus-any 1.8.2", + "alloy-rpc-types-eth 1.8.2", + "alloy-serde 1.8.2", ] [[package]] @@ -838,8 +838,8 @@ dependencies = [ [[package]] name = "alloy-rpc-types-debug" -version = "1.5.2" -source = "git+https://github.com/alloy-rs/alloy#3203f839dd801e1966b4970136b59051f3856770" +version = "1.8.2" +source = "git+https://github.com/alloy-rs/alloy#c36b7b2c867e7b13ede7a5f6f8112a83c363400e" dependencies = [ "alloy-primitives", "derive_more 2.1.1", @@ -862,14 +862,14 @@ dependencies = [ [[package]] name = "alloy-rpc-types-engine" -version = "1.5.2" -source = "git+https://github.com/alloy-rs/alloy#3203f839dd801e1966b4970136b59051f3856770" +version = "1.8.2" +source = "git+https://github.com/alloy-rs/alloy#c36b7b2c867e7b13ede7a5f6f8112a83c363400e" dependencies = [ - "alloy-consensus 1.5.2", - "alloy-eips 1.5.2", + "alloy-consensus 1.8.2", + "alloy-eips 1.8.2", "alloy-primitives", "alloy-rlp", - "alloy-serde 1.5.2", + "alloy-serde 1.8.2", "derive_more 2.1.1", "rand 0.8.5", "serde", @@ -898,16 +898,16 @@ dependencies = [ [[package]] name = "alloy-rpc-types-eth" -version = "1.5.2" -source = "git+https://github.com/alloy-rs/alloy#3203f839dd801e1966b4970136b59051f3856770" +version = "1.8.2" +source = "git+https://github.com/alloy-rs/alloy#c36b7b2c867e7b13ede7a5f6f8112a83c363400e" dependencies = [ - "alloy-consensus 1.5.2", - "alloy-consensus-any 1.5.2", - "alloy-eips 1.5.2", - "alloy-network-primitives 1.5.2", + "alloy-consensus 1.8.2", + "alloy-consensus-any 1.8.2", + "alloy-eips 1.8.2", + "alloy-network-primitives 1.8.2", "alloy-primitives", "alloy-rlp", - "alloy-serde 1.5.2", + "alloy-serde 1.8.2", "alloy-sol-types", "itertools 0.14.0", "serde", @@ -931,12 +931,12 @@ dependencies = [ [[package]] name = "alloy-rpc-types-trace" -version = "1.5.2" -source = "git+https://github.com/alloy-rs/alloy#3203f839dd801e1966b4970136b59051f3856770" +version = "1.8.2" +source = "git+https://github.com/alloy-rs/alloy#c36b7b2c867e7b13ede7a5f6f8112a83c363400e" dependencies = [ "alloy-primitives", - "alloy-rpc-types-eth 1.5.2", - "alloy-serde 1.5.2", + "alloy-rpc-types-eth 1.8.2", + "alloy-serde 1.8.2", "serde", "serde_json", "thiserror 2.0.18", @@ -944,12 +944,12 @@ dependencies = [ [[package]] name = "alloy-rpc-types-txpool" -version = "1.5.2" -source = "git+https://github.com/alloy-rs/alloy#3203f839dd801e1966b4970136b59051f3856770" +version = "1.8.2" +source = "git+https://github.com/alloy-rs/alloy#c36b7b2c867e7b13ede7a5f6f8112a83c363400e" dependencies = [ "alloy-primitives", - "alloy-rpc-types-eth 1.5.2", - "alloy-serde 1.5.2", + "alloy-rpc-types-eth 1.8.2", + "alloy-serde 1.8.2", "serde", ] @@ -965,8 +965,8 @@ dependencies = [ [[package]] name = "alloy-serde" -version = "1.5.2" -source = "git+https://github.com/alloy-rs/alloy#3203f839dd801e1966b4970136b59051f3856770" +version = "1.8.2" +source = "git+https://github.com/alloy-rs/alloy#c36b7b2c867e7b13ede7a5f6f8112a83c363400e" dependencies = [ "alloy-primitives", "serde", @@ -989,9 +989,9 @@ dependencies = [ [[package]] name = "alloy-signer" -version = "1.5.2" +version = "1.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f7481dc8316768f042495eaf305d450c32defbc9bce09d8bf28afcd956895bb" +checksum = "97f40010b5e8f79b70bf163b38cd15f529b18ca88c4427c0e43441ee54e4ed82" dependencies = [ "alloy-primitives", "async-trait", @@ -1004,8 +1004,8 @@ dependencies = [ [[package]] name = "alloy-signer" -version = "1.5.2" -source = "git+https://github.com/alloy-rs/alloy#3203f839dd801e1966b4970136b59051f3856770" +version = "1.8.2" +source = "git+https://github.com/alloy-rs/alloy#c36b7b2c867e7b13ede7a5f6f8112a83c363400e" dependencies = [ "alloy-primitives", "async-trait", @@ -1018,13 +1018,13 @@ dependencies = [ [[package]] name = "alloy-signer-local" -version = "1.5.2" -source = "git+https://github.com/alloy-rs/alloy#3203f839dd801e1966b4970136b59051f3856770" +version = "1.8.2" +source = "git+https://github.com/alloy-rs/alloy#c36b7b2c867e7b13ede7a5f6f8112a83c363400e" dependencies = [ - "alloy-consensus 1.5.2", - "alloy-network 1.5.2", + "alloy-consensus 1.8.2", + "alloy-network 1.8.2", "alloy-primitives", - "alloy-signer 1.5.2 (git+https://github.com/alloy-rs/alloy)", + "alloy-signer 1.8.2", "async-trait", "k256", "rand 0.8.5", @@ -1033,23 +1033,23 @@ dependencies = [ [[package]] name = "alloy-sol-macro" -version = "1.5.4" +version = "1.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5fa1ca7e617c634d2bd9fa71f9ec8e47c07106e248b9fcbd3eaddc13cabd625" +checksum = "ab81bab693da9bb79f7a95b64b394718259fdd7e41dceeced4cad57cb71c4f6a" dependencies = [ "alloy-sol-macro-expander", "alloy-sol-macro-input", "proc-macro-error2", "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] name = "alloy-sol-macro-expander" -version = "1.5.4" +version = "1.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27c00c0c3a75150a9dc7c8c679ca21853a137888b4e1c5569f92d7e2b15b5102" +checksum = "489f1620bb7e2483fb5819ed01ab6edc1d2f93939dce35a5695085a1afd1d699" dependencies = [ "alloy-json-abi", "alloy-sol-macro-input", @@ -1060,15 +1060,15 @@ dependencies = [ "proc-macro2", "quote", "sha3", - "syn 2.0.114", + "syn 2.0.117", "syn-solidity", ] [[package]] name = "alloy-sol-macro-input" -version = "1.5.4" +version = "1.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "297db260eb4d67c105f68d6ba11b8874eec681caec5505eab8fbebee97f790bc" +checksum = "56cef806ad22d4392c5fc83cf8f2089f988eb99c7067b4e0c6f1971fc1cca318" dependencies = [ "alloy-json-abi", "const-hex", @@ -1078,25 +1078,25 @@ dependencies = [ "proc-macro2", "quote", "serde_json", - "syn 2.0.114", + "syn 2.0.117", "syn-solidity", ] [[package]] name = "alloy-sol-type-parser" -version = "1.5.4" +version = "1.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94b91b13181d3bcd23680fd29d7bc861d1f33fbe90fdd0af67162434aeba902d" +checksum = "a6df77fea9d6a2a75c0ef8d2acbdfd92286cc599983d3175ccdc170d3433d249" dependencies = [ "serde", - "winnow", + "winnow 0.7.15", ] [[package]] name = "alloy-sol-types" -version = "1.5.4" +version = "1.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc442cc2a75207b708d481314098a0f8b6f7b58e3148dd8d8cc7407b0d6f9385" +checksum = "64612d29379782a5dde6f4b6570d9c756d734d760c0c94c254d361e678a6591f" dependencies = [ "alloy-json-abi", "alloy-primitives", @@ -1129,10 +1129,10 @@ dependencies = [ [[package]] name = "alloy-transport" -version = "1.5.2" -source = "git+https://github.com/alloy-rs/alloy#3203f839dd801e1966b4970136b59051f3856770" +version = "1.8.2" +source = "git+https://github.com/alloy-rs/alloy#c36b7b2c867e7b13ede7a5f6f8112a83c363400e" dependencies = [ - "alloy-json-rpc 1.5.2", + "alloy-json-rpc 1.8.2", "auto_impl", "base64 0.22.1", "derive_more 2.1.1", @@ -1165,12 +1165,13 @@ dependencies = [ [[package]] name = "alloy-transport-http" -version = "1.5.2" -source = "git+https://github.com/alloy-rs/alloy#3203f839dd801e1966b4970136b59051f3856770" +version = "1.8.2" +source = "git+https://github.com/alloy-rs/alloy#c36b7b2c867e7b13ede7a5f6f8112a83c363400e" dependencies = [ - "alloy-json-rpc 1.5.2", - "alloy-transport 1.5.2", - "reqwest 0.12.28", + "alloy-json-rpc 1.8.2", + "alloy-transport 1.8.2", + "itertools 0.14.0", + "reqwest 0.13.2", "serde_json", "tower 0.5.3", "tracing", @@ -1179,12 +1180,12 @@ dependencies = [ [[package]] name = "alloy-transport-ipc" -version = "1.5.2" -source = "git+https://github.com/alloy-rs/alloy#3203f839dd801e1966b4970136b59051f3856770" +version = "1.8.2" +source = "git+https://github.com/alloy-rs/alloy#c36b7b2c867e7b13ede7a5f6f8112a83c363400e" dependencies = [ - "alloy-json-rpc 1.5.2", + "alloy-json-rpc 1.8.2", "alloy-pubsub", - "alloy-transport 1.5.2", + "alloy-transport 1.8.2", "bytes", "futures", "interprocess", @@ -1198,17 +1199,19 @@ dependencies = [ [[package]] name = "alloy-transport-ws" -version = "1.5.2" -source = "git+https://github.com/alloy-rs/alloy#3203f839dd801e1966b4970136b59051f3856770" +version = "1.8.2" +source = "git+https://github.com/alloy-rs/alloy#c36b7b2c867e7b13ede7a5f6f8112a83c363400e" dependencies = [ "alloy-pubsub", - "alloy-transport 1.5.2", + "alloy-transport 1.8.2", "futures", "http 1.4.0", + "rustls 0.23.37", "serde_json", "tokio", - "tokio-tungstenite 0.26.2", + "tokio-tungstenite 0.28.0", "tracing", + "url", "ws_stream_wasm", ] @@ -1230,17 +1233,17 @@ dependencies = [ [[package]] name = "alloy-trie" -version = "0.9.3" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "428aa0f0e0658ff091f8f667c406e034b431cb10abd39de4f507520968acc499" +checksum = "3f14b5d9b2c2173980202c6ff470d96e7c5e202c65a9f67884ad565226df7fbb" dependencies = [ "alloy-primitives", "alloy-rlp", - "arrayvec", "derive_more 2.1.1", - "nybbles 0.4.7", + "nybbles 0.4.8", "serde", "smallvec", + "thiserror 2.0.18", "tracing", ] @@ -1250,21 +1253,21 @@ version = "1.0.41" source = "git+https://github.com/ziren-patches/alloy?branch=patch-1.0.41#08557d4e5f4ca766194a45c1925d8f1625258793" dependencies = [ "alloy-primitives", - "darling", + "darling 0.21.3", "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] name = "alloy-tx-macros" -version = "1.5.2" -source = "git+https://github.com/alloy-rs/alloy#3203f839dd801e1966b4970136b59051f3856770" +version = "1.8.2" +source = "git+https://github.com/alloy-rs/alloy#c36b7b2c867e7b13ede7a5f6f8112a83c363400e" dependencies = [ - "darling", + "darling 0.23.0", "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -1287,9 +1290,9 @@ dependencies = [ [[package]] name = "anstream" -version = "0.6.21" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43d5b281e737544384e969a5ccad3f1cdd24b48086a0fc1b2a5262a26b8f4f4a" +checksum = "824a212faf96e9acacdbd09febd34438f8f711fb84e09a8916013cd7815ca28d" dependencies = [ "anstyle", "anstyle-parse", @@ -1302,15 +1305,15 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.13" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5192cca8006f1fd4f7237516f40fa183bb07f8fbdfedaa0036de5ea9b0b45e78" +checksum = "940b3a0ca603d1eade50a4846a2afffd5ef57a9feac2c0e2ec2e14f9ead76000" [[package]] name = "anstyle-parse" -version = "0.2.7" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2" +checksum = "52ce7f38b242319f7cabaa6813055467063ecdc9d355bbb4ce0c68908cd8130e" dependencies = [ "utf8parse", ] @@ -1337,9 +1340,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.100" +version = "1.0.102" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" +checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" [[package]] name = "ark-bls12-381" @@ -1395,7 +1398,7 @@ checksum = "e7e89fe77d1f0f4fe5b96dfc940923d88d17b6a773808124f21e764dfb063c6a" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -1506,7 +1509,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "62945a2f7e6de02a31fe400aa489f0e0f5b2502e69f95f853adb82a96c7a6b60" dependencies = [ "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -1544,7 +1547,7 @@ dependencies = [ "num-traits", "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -1634,7 +1637,7 @@ checksum = "213888f660fddcca0d257e88e54ac05bca01885f258ccdf695bafd77031bb69d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -1692,9 +1695,6 @@ name = "arrayvec" version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" -dependencies = [ - "serde", -] [[package]] name = "ascii-canvas" @@ -1729,7 +1729,7 @@ checksum = "3109e49b1e4909e9db6515a30c633684d68cdeaa252f215214cb4fa1a5bfee2c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", "synstructure", ] @@ -1741,14 +1741,14 @@ checksum = "7b18050c2cd6fe86c3a76584ef5e0baf286d038cda203eb6223df2cc413565f7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] name = "asn1_der" -version = "0.7.6" +version = "0.7.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "155a5a185e42c6b77ac7b88a15143d930a9e9727a5b7b77eed417404ab15c247" +checksum = "4858a9d740c5007a9069007c3b4e91152d0506f13c1b31dd49051fd537656156" [[package]] name = "async-channel" @@ -1775,9 +1775,9 @@ dependencies = [ [[package]] name = "async-executor" -version = "1.13.3" +version = "1.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "497c00e0fd83a72a79a39fcbd8e3e2f055d6f6c7e025f3b3d91f4f8e76527fb8" +checksum = "c96bf972d85afc50bf5ab8fe2d54d1586b4e0b46c97c50a0c9e71e2f7bcd812a" dependencies = [ "async-task", "concurrent-queue", @@ -1815,7 +1815,7 @@ dependencies = [ "futures-lite", "parking", "polling", - "rustix 1.1.3", + "rustix 1.1.4", "slab", "windows-sys 0.61.2", ] @@ -1849,7 +1849,7 @@ checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -1897,7 +1897,7 @@ checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -1914,7 +1914,7 @@ checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -1985,7 +1985,7 @@ checksum = "ffdcb70bdbc4d478427380519163274ac86e52916e10f0a8889adf0f96d3fee7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -1994,6 +1994,28 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" +[[package]] +name = "aws-lc-rs" +version = "1.16.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a054912289d18629dc78375ba2c3726a3afe3ff71b4edba9dedfca0e3446d1fc" +dependencies = [ + "aws-lc-sys", + "zeroize", +] + +[[package]] +name = "aws-lc-sys" +version = "0.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fa7e52a4c5c547c741610a2c6f123f3881e409b714cd27e6798ef020c514f0a" +dependencies = [ + "cc", + "cmake", + "dunce", + "fs_extra", +] + [[package]] name = "axum" version = "0.6.20" @@ -2155,7 +2177,7 @@ checksum = "604fde5e028fea851ce1d8570bbdc034bec850d157f7569d10f347d06808c05c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -2269,10 +2291,10 @@ version = "0.70.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f49d8fed880d473ea71efb9bf597651e77201bdd4893efe54c9e5d65ae04ce6f" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "cexpr", "clang-sys", - "itertools 0.10.5", + "itertools 0.13.0", "log", "prettyplease 0.2.37", "proc-macro2", @@ -2280,7 +2302,7 @@ dependencies = [ "regex", "rustc-hash 1.1.0", "shlex", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -2334,7 +2356,7 @@ checksum = "238b90427dfad9da4a9abd60f3ec1cdee6b80454bde49ed37f1781dd8e9dc7f9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -2519,9 +2541,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.10.0" +version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3" +checksum = "843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af" dependencies = [ "serde_core", ] @@ -2601,7 +2623,7 @@ dependencies = [ "strum 0.26.3", "tokio", "tracing", - "uuid 1.20.0", + "uuid 1.22.0", ] [[package]] @@ -2660,9 +2682,9 @@ dependencies = [ "tokio-util", "tower-http", "tracing", - "tracing-subscriber 0.3.22", + "tracing-subscriber 0.3.23", "util", - "uuid 1.20.0", + "uuid 1.22.0", "zeroize", "zkm-sdk", "zkm-verifier", @@ -2699,7 +2721,7 @@ dependencies = [ "cc", "cfg-if", "constant_time_eq 0.4.2", - "cpufeatures", + "cpufeatures 0.2.17", ] [[package]] @@ -2783,25 +2805,26 @@ dependencies = [ [[package]] name = "borsh" -version = "1.6.0" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1da5ab77c1437701eeff7c88d968729e7766172279eab0676857b3d63af7a6f" +checksum = "cfd1e3f8955a5d7de9fab72fc8373fade9fb8a703968cb200ae3dc6cf08e185a" dependencies = [ "borsh-derive", + "bytes", "cfg_aliases", ] [[package]] name = "borsh-derive" -version = "1.6.0" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0686c856aa6aac0c4498f936d7d6a02df690f614c03e4d906d1018062b5c5e2c" +checksum = "bfcfdc083699101d5a7965e49925975f2f55060f94f9a05e7187be95d530ca59" dependencies = [ "once_cell", "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -2816,9 +2839,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.19.1" +version = "3.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5dd9dc738b7a8311c7ade152424974d8115f2cdad61e8dab8dac9f2362298510" +checksum = "5d20789868f4b01b2f2caec9f5c4e0213b41e3e5702a50157d699ae31ced2fcb" [[package]] name = "byte-slice-cast" @@ -2828,9 +2851,9 @@ checksum = "7575182f7272186991736b70173b0ea045398f984bf5ebbb3804736ce1330c9d" [[package]] name = "bytemuck" -version = "1.24.0" +version = "1.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fbdf580320f38b612e485521afda1ee26d10cc9884efaaa750d383e13e3c5f4" +checksum = "c8efb64bd706a16a1bdde310ae86b351e4d21550d98d056f22f8a7f7a2183fec" dependencies = [ "bytemuck_derive", ] @@ -2843,7 +2866,7 @@ checksum = "f9abbd1bc6865053c427f7198e6af43bfdedc55ab791faed4fbd361d789575ff" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -2854,9 +2877,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.11.0" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b35204fbdc0b3f4446b89fc1ac2cf84a8a68971995d0bf2e925ec7cd960f9cb3" +checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33" dependencies = [ "serde", ] @@ -2883,9 +2906,9 @@ dependencies = [ [[package]] name = "c-kzg" -version = "2.1.5" +version = "2.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e00bf4b112b07b505472dbefd19e37e53307e2bfed5a79e0cc161d58ccd0e687" +checksum = "6648ed1e4ea8e8a1a4a2c78e1cda29a3fd500bc622899c340d8525ea9a76b24a" dependencies = [ "blst", "cc", @@ -2950,9 +2973,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.2.55" +version = "1.2.57" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47b26a0954ae34af09b50f0de26458fa95369a0d478d8236d3f93082b219bd29" +checksum = "7a0dd1ca384932ff3641c8718a02769f1698e7563dc6974ffd03346116310423" dependencies = [ "find-msvc-tools", "jobserver", @@ -2960,6 +2983,12 @@ dependencies = [ "shlex", ] +[[package]] +name = "cesu8" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" + [[package]] name = "cexpr" version = "0.6.0" @@ -2989,7 +3018,18 @@ checksum = "c3613f74bd2eac03dad61bd53dbe620703d4371614fe0bc3b9f04dd36fe4e818" dependencies = [ "cfg-if", "cipher", - "cpufeatures", + "cpufeatures 0.2.17", +] + +[[package]] +name = "chacha20" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f8d983286843e49675a4b7a2d174efe136dc93a18d69130dd18198a6c167601" +dependencies = [ + "cfg-if", + "cpufeatures 0.3.0", + "rand_core 0.10.0", ] [[package]] @@ -2999,7 +3039,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "10cd79432192d1c0f4e1a0fef9527696cc039165d729fb41b3f4f4f354c2dc35" dependencies = [ "aead", - "chacha20", + "chacha20 0.9.1", "cipher", "poly1305", "zeroize", @@ -3007,9 +3047,9 @@ dependencies = [ [[package]] name = "chrono" -version = "0.4.43" +version = "0.4.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fac4744fb15ae8337dc853fee7fb3f4e48c0fbaa23d0afe49c447b4fab126118" +checksum = "c673075a2e0e5f4a1dde27ce9dee1ea4558c7ffe648f576438a20ca1d2acc4b0" dependencies = [ "iana-time-zone", "js-sys", @@ -3043,9 +3083,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.56" +version = "4.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75ca66430e33a14957acc24c5077b503e7d374151b2b4b3a10c83b4ceb4be0e" +checksum = "b193af5b67834b676abd72466a96c1024e6a6ad978a1f484bd90b85c94041351" dependencies = [ "clap_builder", "clap_derive", @@ -3053,9 +3093,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.56" +version = "4.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "793207c7fa6300a0608d1080b858e5fdbe713cdc1c8db9fb17777d8a13e63df0" +checksum = "714a53001bf66416adb0e2ef5ac857140e7dc3a0c48fb28b2f10762fc4b5069f" dependencies = [ "anstream", "anstyle", @@ -3065,21 +3105,21 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.55" +version = "4.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a92793da1a46a5f2a02a6f4c46c6496b28c43638adea8306fcb0caa1634f24e5" +checksum = "1110bd8a634a1ab8cb04345d8d878267d57c3cf1b38d91b71af6686408bbca6a" dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] name = "clap_lex" -version = "0.7.7" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3e64b0cc0439b12df2fa678eae89a1c56a529fd067a9115f7827f1fffd22b32" +checksum = "c8d4a3bb8b1e0c1050499d1815f5ab16d04f0959b233085fb31653fbfc9d98f9" [[package]] name = "client" @@ -3099,7 +3139,16 @@ dependencies = [ "tempfile", "tokio", "tracing", - "uuid 1.20.0", + "uuid 1.22.0", +] + +[[package]] +name = "cmake" +version = "0.1.57" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75443c44cd6b379beb8c5b45d85d0773baf31cce901fe7bb252f4eff3008ef7d" +dependencies = [ + "cc", ] [[package]] @@ -3156,9 +3205,9 @@ dependencies = [ [[package]] name = "colorchoice" -version = "1.0.4" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" +checksum = "1d07550c9036bf2ae0c684c4297d503f838287c83c53686d05370d0e139ae570" [[package]] name = "colored" @@ -3170,6 +3219,16 @@ dependencies = [ "windows-sys 0.59.0", ] +[[package]] +name = "combine" +version = "4.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd" +dependencies = [ + "bytes", + "memchr", +] + [[package]] name = "commit-chain" version = "0.3.3" @@ -3216,7 +3275,7 @@ dependencies = [ "tendermint-light-client-verifier", "tokio", "tracing", - "tracing-subscriber 0.3.22", + "tracing-subscriber 0.3.23", "zkm-build", "zkm-prover", "zkm-sdk", @@ -3257,12 +3316,12 @@ dependencies = [ [[package]] name = "const-hex" -version = "1.17.0" +version = "1.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3bb320cac8a0750d7f25280aa97b09c26edfe161164238ecbbb31092b079e735" +checksum = "531185e432bb31db1ecda541e9e7ab21468d4d844ad7505e0546a49b4945d49b" dependencies = [ "cfg-if", - "cpufeatures", + "cpufeatures 0.2.17", "proptest", "serde_core", ] @@ -3330,6 +3389,16 @@ dependencies = [ "libc", ] +[[package]] +name = "core-foundation" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2a6cd9ae233e7f62ba4e9353e81a88df7fc8a5987b8d445b4d90c879bd156f6" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "core-foundation-sys" version = "0.8.7" @@ -3366,6 +3435,15 @@ dependencies = [ "libc", ] +[[package]] +name = "cpufeatures" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b2a41393f66f16b0823bb79094d54ac5fbd34ab292ddafb9a0456ac9f87d201" +dependencies = [ + "libc", +] + [[package]] name = "crc" version = "3.4.0" @@ -3525,12 +3603,12 @@ dependencies = [ [[package]] name = "ctrlc" -version = "3.5.1" +version = "3.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73736a89c4aff73035ba2ed2e565061954da00d4970fc9ac25dcc85a2a20d790" +checksum = "e0b1fab2ae45819af2d0731d60f2afe17227ebb1a1538a236da84c93e9a60162" dependencies = [ "dispatch2", - "nix 0.30.1", + "nix 0.31.2", "windows-sys 0.61.2", ] @@ -3541,7 +3619,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be" dependencies = [ "cfg-if", - "cpufeatures", + "cpufeatures 0.2.17", "curve25519-dalek-derive", "digest 0.10.7", "fiat-crypto", @@ -3558,7 +3636,7 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -3580,8 +3658,18 @@ version = "0.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9cdf337090841a411e2a7f3deb9187445851f91b309c0c0a29e05f74a00a48c0" dependencies = [ - "darling_core", - "darling_macro", + "darling_core 0.21.3", + "darling_macro 0.21.3", +] + +[[package]] +name = "darling" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25ae13da2f202d56bd7f91c25fba009e7717a1e4a1cc98a76d844b65ae912e9d" +dependencies = [ + "darling_core 0.23.0", + "darling_macro 0.23.0", ] [[package]] @@ -3596,7 +3684,21 @@ dependencies = [ "quote", "serde", "strsim", - "syn 2.0.114", + "syn 2.0.117", +] + +[[package]] +name = "darling_core" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9865a50f7c335f53564bb694ef660825eb8610e0a53d3e11bf1b0d3df31e03b0" +dependencies = [ + "ident_case", + "proc-macro2", + "quote", + "serde", + "strsim", + "syn 2.0.117", ] [[package]] @@ -3605,9 +3707,20 @@ version = "0.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d38308df82d1080de0afee5d069fa14b0326a88c14f15c5ccda35b4a6c414c81" dependencies = [ - "darling_core", + "darling_core 0.21.3", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "darling_macro" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3984ec7bd6cfa798e62b4a642426a5be0e68f9401cfc2a01e3fa9ea2fcdb8d" +dependencies = [ + "darling_core 0.23.0", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -3725,7 +3838,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ab67060fc6b8ef687992d439ca0fa36e7ed17e9a0b16b25b601e8757df720de" dependencies = [ "data-encoding", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -3755,9 +3868,9 @@ dependencies = [ [[package]] name = "deranged" -version = "0.5.5" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ececcb659e7ba858fb4f10388c250a7252eb0a27373f1a72b8748afdd248e587" +checksum = "7cd812cc2bc1d69d4764bd80df88b4317eaef9e773c75226407d9bc0876b211c" dependencies = [ "powerfmt", "serde_core", @@ -3776,13 +3889,13 @@ dependencies = [ [[package]] name = "derive-where" -version = "1.6.0" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef941ded77d15ca19b40374869ac6000af1c9f2a4c0f3d4c70926287e6364a8f" +checksum = "d08b3a0bcc0d079199cd476b2cae8435016ec11d1c0986c6901c5ac223041534" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -3793,7 +3906,7 @@ checksum = "6edb4b64a43d977b8e99788fe3a04d483834fba1215a7e02caa415b626497f7f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -3822,7 +3935,7 @@ checksum = "cb7330aeadfbe296029522e6c40f315320aba36fc43a5b3632f3795348f3bd22" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -3835,7 +3948,7 @@ dependencies = [ "proc-macro2", "quote", "rustc_version 0.4.1", - "syn 2.0.114", + "syn 2.0.117", "unicode-xid", ] @@ -3904,11 +4017,11 @@ dependencies = [ [[package]] name = "dispatch2" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89a09f22a6c6069a18470eb92d2298acf25463f14256d24778e1230d789a2aec" +checksum = "1e0e367e4e7da84520dedcac1901e4da967309406d1e51017ae1abfb97adbd38" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "block2", "libc", "objc2", @@ -3922,14 +4035,14 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] name = "doctest-file" -version = "1.0.0" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aac81fa3e28d21450aa4d2ac065992ba96a1d7303efbce51a95f4fd175b67562" +checksum = "c2db04e74f0a9a93103b50e90b96024c9b2bdca8bce6a632ec71b88736d3d359" [[package]] name = "dotenv" @@ -4022,7 +4135,7 @@ dependencies = [ "enum-ordinalize", "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -4064,9 +4177,9 @@ dependencies = [ [[package]] name = "ena" -version = "0.14.3" +version = "0.14.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d248bdd43ce613d87415282f69b9bb99d947d290b10962dd6c56233312c2ad5" +checksum = "eabffdaee24bd1bf95c5ef7cec31260444317e72ea56c4c91750e8b7ee58d5f1" dependencies = [ "log", ] @@ -4113,7 +4226,7 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -4134,7 +4247,7 @@ checksum = "f282cfdfe92516eb26c2af8589c274c7c17681f5ecc03c18255fe741c6aa64eb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -4154,14 +4267,14 @@ checksum = "8ca9601fb2d62598ee17836250842873a413586e5d7ed88b356e38ddbb0ec631" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] name = "env_filter" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a1c3cc8e57274ec99de65301228b537f1e4eedc1b8e0f9411c6caac8ae7308f" +checksum = "32e90c2accc4b07a8456ea0debdc2e7587bdd890680d71173a15d4ae604f6eef" dependencies = [ "log", "regex", @@ -4169,9 +4282,9 @@ dependencies = [ [[package]] name = "env_logger" -version = "0.11.9" +version = "0.11.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2daee4ea451f429a58296525ddf28b45a3b64f1acf6587e2067437bb11e218d" +checksum = "0621c04f2196ac3f488dd583365b9c09be011a4ab8b9f37248ffcc8f6198b56a" dependencies = [ "anstream", "anstyle", @@ -4358,7 +4471,7 @@ dependencies = [ "reqwest 0.11.27", "serde", "serde_json", - "syn 2.0.114", + "syn 2.0.117", "toml 0.8.23", "walkdir", ] @@ -4376,7 +4489,7 @@ dependencies = [ "proc-macro2", "quote", "serde_json", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -4402,7 +4515,7 @@ dependencies = [ "serde", "serde_json", "strum 0.26.3", - "syn 2.0.114", + "syn 2.0.117", "tempfile", "thiserror 1.0.69", "tiny-keccak", @@ -4682,9 +4795,9 @@ checksum = "1d674e81391d1e1ab681a28d99df07927c6d4aa5b027d7da16ba32d1d21ecd99" [[package]] name = "flate2" -version = "1.1.8" +version = "1.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b375d6465b98090a5f25b1c7703f3859783755aa9a80433b36e0379a3ec2f369" +checksum = "843fba2746e448b37e26a819579957415c8cef339bf08564fe8b7ddbd959573c" dependencies = [ "crc32fast", "miniz_oxide", @@ -4762,6 +4875,12 @@ dependencies = [ "winapi", ] +[[package]] +name = "fs_extra" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c" + [[package]] name = "funty" version = "2.0.0" @@ -4770,9 +4889,9 @@ checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" [[package]] name = "futures" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" +checksum = "8b147ee9d1f6d097cef9ce628cd2ee62288d963e16fb287bd9286455b241382d" dependencies = [ "futures-channel", "futures-core", @@ -4795,9 +4914,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" +checksum = "07bbe89c50d7a535e539b8c17bc0b49bdb77747034daa8087407d655f3f7cc1d" dependencies = [ "futures-core", "futures-sink", @@ -4805,20 +4924,19 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" +checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d" [[package]] name = "futures-executor" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" +checksum = "baf29c38818342a3b26b5b923639e7b1f4a61fc5e76102d4b1981c6dc7a7579d" dependencies = [ "futures-core", "futures-task", "futures-util", - "num_cpus", ] [[package]] @@ -4834,9 +4952,9 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" +checksum = "cecba35d7ad927e23624b22ad55235f2239cfa44fd10428eecbeba6d6a717718" [[package]] name = "futures-lite" @@ -4863,13 +4981,13 @@ dependencies = [ [[package]] name = "futures-macro" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" +checksum = "e835b70203e41293343137df5c0664546da5745f82ec9b84d40be8336958447b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -4879,21 +4997,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8f2f12607f92c69b12ed746fabf9ca4f5c482cba46679c1a75b874ed7c26adb" dependencies = [ "futures-io", - "rustls 0.23.36", + "rustls 0.23.37", "rustls-pki-types", ] [[package]] name = "futures-sink" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" +checksum = "c39754e157331b013978ec91992bde1ac089843443c49cbc7f46150b0fad0893" [[package]] name = "futures-task" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" +checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393" [[package]] name = "futures-timer" @@ -4907,9 +5025,9 @@ dependencies = [ [[package]] name = "futures-util" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" +checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6" dependencies = [ "futures-channel", "futures-core", @@ -4919,7 +5037,6 @@ dependencies = [ "futures-task", "memchr", "pin-project-lite", - "pin-utils", "slab", ] @@ -4988,11 +5105,25 @@ dependencies = [ "cfg-if", "js-sys", "libc", - "r-efi", + "r-efi 5.3.0", "wasip2", "wasm-bindgen", ] +[[package]] +name = "getrandom" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0de51e6874e94e7bf76d726fc5d13ba782deca734ff60d5bb2fb2607c7406555" +dependencies = [ + "cfg-if", + "libc", + "r-efi 6.0.0", + "rand_core 0.10.0", + "wasip2", + "wasip3", +] + [[package]] name = "ghash" version = "0.5.1" @@ -5015,7 +5146,7 @@ version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b903b73e45dc0c6c596f2d37eccece7c1c8bb6e4407b001096387c63d0d93724" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "libc", "libgit2-sys", "log", @@ -5024,9 +5155,9 @@ dependencies = [ [[package]] name = "glam" -version = "0.31.0" +version = "0.32.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74a4d85559e2637d3d839438b5b3d75c31e655276f9544d72475c36b92fabbed" +checksum = "f70749695b063ecbf6b62949ccccde2e733ec3ecbbd71d467dca4e5c6c97cca0" [[package]] name = "glob" @@ -5124,7 +5255,7 @@ dependencies = [ [[package]] name = "guest-executor" version = "0.1.0" -source = "git+https://github.com/ProjectZKM/reth-processor?branch=feat%2Fslot-state-check#0b280a7cc8cd7c12bcf28a06fbdef3cb9a9ae196" +source = "git+https://github.com/ProjectZKM/reth-processor?branch=feat%2Fslot-state-check#294aa06127be4bfda47a7fd4905b93bb8e664dca" dependencies = [ "alloy-consensus 1.0.41", "alloy-evm", @@ -5372,7 +5503,7 @@ dependencies = [ "sha2 0.10.9", "tokio", "tracing", - "tracing-subscriber 0.3.22", + "tracing-subscriber 0.3.23", "util", "zkm-build", "zkm-prover", @@ -5563,7 +5694,7 @@ dependencies = [ [[package]] name = "host-executor" version = "0.1.0" -source = "git+https://github.com/ProjectZKM/reth-processor?branch=feat%2Fslot-state-check#0b280a7cc8cd7c12bcf28a06fbdef3cb9a9ae196" +source = "git+https://github.com/ProjectZKM/reth-processor?branch=feat%2Fslot-state-check#294aa06127be4bfda47a7fd4905b93bb8e664dca" dependencies = [ "alloy-chains", "alloy-consensus 1.0.41", @@ -5749,12 +5880,12 @@ dependencies = [ "http 1.4.0", "hyper 1.8.1", "hyper-util", - "rustls 0.23.36", + "rustls 0.23.37", "rustls-pki-types", "tokio", "tokio-rustls 0.26.4", "tower-service", - "webpki-roots 1.0.5", + "webpki-roots 1.0.6", ] [[package]] @@ -5784,14 +5915,13 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.19" +version = "0.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "727805d60e7938b76b826a6ef209eb70eaa1812794f9424d4a4e2d740662df5f" +checksum = "96547c2556ec9d12fb1578c4eaf448b04993e7fb79cbaad930a656880a6bdfa0" dependencies = [ "base64 0.22.1", "bytes", "futures-channel", - "futures-core", "futures-util", "http 1.4.0", "http-body 1.0.1", @@ -5800,7 +5930,7 @@ dependencies = [ "libc", "percent-encoding", "pin-project-lite", - "socket2 0.6.2", + "socket2 0.6.3", "tokio", "tower-service", "tracing", @@ -5911,6 +6041,12 @@ dependencies = [ "zerovec", ] +[[package]] +name = "id-arena" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954" + [[package]] name = "ident_case" version = "1.0.1" @@ -5940,22 +6076,22 @@ dependencies = [ [[package]] name = "if-addrs" -version = "0.10.2" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cabb0019d51a643781ff15c9c8a3e5dedc365c47211270f4e8f82812fedd8f0a" +checksum = "c0a05c691e1fae256cf7013d99dad472dc52d5543322761f83ec8d47eab40d2b" dependencies = [ "libc", - "windows-sys 0.48.0", + "windows-sys 0.61.2", ] [[package]] name = "if-watch" -version = "3.2.1" +version = "3.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdf9d64cfcf380606e64f9a0bcf493616b65331199f984151a6fa11a7b3cde38" +checksum = "71c02a5161c313f0cbdbadc511611893584a10a7b6153cb554bdf83ddce99ec2" dependencies = [ "async-io", - "core-foundation", + "core-foundation 0.9.4", "fnv", "futures", "if-addrs", @@ -5966,9 +6102,9 @@ dependencies = [ "netlink-proto", "netlink-sys", "rtnetlink", - "system-configuration 0.6.1", + "system-configuration 0.7.0", "tokio", - "windows 0.53.0", + "windows 0.62.2", ] [[package]] @@ -6027,7 +6163,7 @@ checksum = "a0eb5a3343abf848c0984fe4604b2b105da9539376e24fc0a3b0007411ae4fd9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -6102,9 +6238,9 @@ dependencies = [ [[package]] name = "interprocess" -version = "2.2.3" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d941b405bd2322993887859a8ee6ac9134945a24ec5ec763a8a962fc64dfec2d" +checksum = "6be5e5c847dbdb44564bd85294740d031f4f8aeb3464e5375ef7141f7538db69" dependencies = [ "doctest-file", "futures-core", @@ -6117,21 +6253,22 @@ dependencies = [ [[package]] name = "ipconfig" -version = "0.3.2" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b58db92f96b720de98181bbbe63c831e87005ab460c1bf306eb2622b4707997f" +checksum = "4d40460c0ce33d6ce4b0630ad68ff63d6661961c48b6dba35e5a4d81cfb48222" dependencies = [ - "socket2 0.5.10", + "socket2 0.6.3", "widestring", - "windows-sys 0.48.0", - "winreg", + "windows-registry", + "windows-result", + "windows-sys 0.61.2", ] [[package]] name = "ipnet" -version = "2.11.0" +version = "2.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" +checksum = "d98f6fed1fde3f8c21bc40a1abb88dd75e67924f9cffc3ef95607bad8017f8e2" [[package]] name = "ipnetwork" @@ -6144,9 +6281,9 @@ dependencies = [ [[package]] name = "iri-string" -version = "0.7.10" +version = "0.7.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c91338f0783edbd6195decb37bae672fd3b165faffb89bf7b9e6942f8b1a731a" +checksum = "d8e7418f59cc01c88316161279a7f665217ae316b388e58a0d10e29f54f1e5eb" dependencies = [ "memchr", "serde", @@ -6196,9 +6333,9 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.17" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92ecc6618181def0457392ccd0ee51198e065e016d1d527a7ac1b6dc7c1f09d2" +checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" [[package]] name = "jiff" @@ -6221,7 +6358,51 @@ checksum = "2a8c8b344124222efd714b73bb41f8b5120b27a7cc1c75593a6ff768d9d05aa4" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", +] + +[[package]] +name = "jni" +version = "0.21.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a87aa2bb7d2af34197c04845522473242e1aa17c12f4935d5856491a7fb8c97" +dependencies = [ + "cesu8", + "cfg-if", + "combine", + "jni-sys 0.3.1", + "log", + "thiserror 1.0.69", + "walkdir", + "windows-sys 0.45.0", +] + +[[package]] +name = "jni-sys" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41a652e1f9b6e0275df1f15b32661cf0d4b78d4d87ddec5e0c3c20f097433258" +dependencies = [ + "jni-sys 0.4.1", +] + +[[package]] +name = "jni-sys" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6377a88cb3910bee9b0fa88d4f42e1d2da8e79915598f65fb0c7ee14c878af2" +dependencies = [ + "jni-sys-macros", +] + +[[package]] +name = "jni-sys-macros" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38c0b942f458fe50cdac086d2f946512305e5631e720728f2a61aabcd47a6264" +dependencies = [ + "quote", + "syn 2.0.117", ] [[package]] @@ -6236,9 +6417,9 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.85" +version = "0.3.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c942ebf8e95485ca0d52d97da7c5a2c387d0e7f0ba4c35e93bfcaee045955b3" +checksum = "b49715b7073f385ba4bc528e5747d02e66cb39c6146efb66b781f131f0fb399c" dependencies = [ "once_cell", "wasm-bindgen", @@ -6301,11 +6482,11 @@ dependencies = [ [[package]] name = "keccak" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecc2af9a1119c51f12a14607e783cb977bde58bc069ff0c3da1095e635d70654" +checksum = "cb26cec98cce3a3d96cbb7bced3c4b16e3d13f27ec56dbd62cbc8f39cfb9d653" dependencies = [ - "cpufeatures", + "cpufeatures 0.2.17", ] [[package]] @@ -6379,11 +6560,17 @@ dependencies = [ "spin 0.9.8", ] +[[package]] +name = "leb128fmt" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" + [[package]] name = "libc" -version = "0.2.180" +version = "0.2.183" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcc35a38544a891a5f7c865aca548a982ccb3b8650a5b06d0fd33a10283c56fc" +checksum = "b5b646652bf6661599e1da8901b3b9522896f01e736bad5f723fe7a3a27f899d" [[package]] name = "libgit2-sys" @@ -6730,7 +6917,7 @@ dependencies = [ "quinn", "rand 0.8.5", "ring 0.17.14", - "rustls 0.23.36", + "rustls 0.23.37", "socket2 0.5.10", "thiserror 2.0.18", "tokio", @@ -6810,7 +6997,7 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -6841,8 +7028,8 @@ dependencies = [ "libp2p-identity", "rcgen", "ring 0.17.14", - "rustls 0.23.36", - "rustls-webpki 0.103.9", + "rustls 0.23.37", + "rustls-webpki 0.103.10", "thiserror 2.0.18", "x509-parser", "yasna", @@ -6896,18 +7083,19 @@ dependencies = [ "thiserror 2.0.18", "tracing", "yamux 0.12.1", - "yamux 0.13.8", + "yamux 0.13.10", ] [[package]] name = "libredox" -version = "0.1.12" +version = "0.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d0b95e02c851351f877147b7deea7b1afb1df71b63aa5f8270716e0c5720616" +checksum = "7ddbf48fd451246b1f8c2610bd3b4ac0cc6e149d89832867093ab69a17194f08" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "libc", - "redox_syscall 0.7.0", + "plain", + "redox_syscall 0.7.3", ] [[package]] @@ -6923,9 +7111,9 @@ dependencies = [ [[package]] name = "libz-sys" -version = "1.1.23" +version = "1.1.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15d118bbf3771060e7311cc7bb0545b01d08a8b4a7de949198dec1fa0ca1c0f7" +checksum = "d52f4c29e2a68ac30c9087e1b772dc9f44a2b66ed44edf2266cf2be9b03dafc1" dependencies = [ "cc", "libc", @@ -6947,9 +7135,9 @@ checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" [[package]] name = "linux-raw-sys" -version = "0.11.0" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039" +checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53" [[package]] name = "litemap" @@ -7025,7 +7213,7 @@ checksum = "1b27834086c65ec3f9387b096d66e99f221cf081c2b738042aa252bcd41204e3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -7036,7 +7224,7 @@ checksum = "757aee279b8bdbb9f9e676796fd459e4207a1f986e87886700abf589f5abf771" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -7072,9 +7260,9 @@ dependencies = [ [[package]] name = "memchr" -version = "2.7.6" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" +checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" [[package]] name = "memuse" @@ -7183,9 +7371,9 @@ dependencies = [ [[package]] name = "moka" -version = "0.12.13" +version = "0.12.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4ac832c50ced444ef6be0767a008b02c106a909ba79d1d830501e94b96f6b7e" +checksum = "957228ad12042ee839f93c8f257b62b4c0ab5eaae1d4fa60de53b27c9d7c5046" dependencies = [ "crossbeam-channel", "crossbeam-epoch", @@ -7195,13 +7383,13 @@ dependencies = [ "portable-atomic", "smallvec", "tagptr", - "uuid 1.20.0", + "uuid 1.22.0", ] [[package]] name = "mpt" version = "0.1.0" -source = "git+https://github.com/ProjectZKM/reth-processor?branch=feat%2Fslot-state-check#0b280a7cc8cd7c12bcf28a06fbdef3cb9a9ae196" +source = "git+https://github.com/ProjectZKM/reth-processor?branch=feat%2Fslot-state-check#294aa06127be4bfda47a7fd4905b93bb8e664dca" dependencies = [ "alloy-primitives", "alloy-rlp", @@ -7300,63 +7488,47 @@ dependencies = [ [[package]] name = "native-tls" -version = "0.2.14" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87de3442987e9dbec73158d5c715e7ad9072fda936bb03d19d7fa10e00520f0e" +checksum = "465500e14ea162429d264d44189adc38b199b62b1c21eea9f69e4b73cb03bbf2" dependencies = [ "libc", "log", "openssl", - "openssl-probe", + "openssl-probe 0.2.1", "openssl-sys", "schannel", - "security-framework", + "security-framework 3.7.0", "security-framework-sys", "tempfile", ] [[package]] name = "netlink-packet-core" -version = "0.7.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72724faf704479d67b388da142b186f916188505e7e0b26719019c525882eda4" +checksum = "3463cbb78394cb0141e2c926b93fc2197e473394b761986eca3b9da2c63ae0f4" dependencies = [ - "anyhow", - "byteorder", - "netlink-packet-utils", + "paste", ] [[package]] name = "netlink-packet-route" -version = "0.17.1" +version = "0.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "053998cea5a306971f88580d0829e90f270f940befd7cf928da179d4187a5a66" +checksum = "4ce3636fa715e988114552619582b530481fd5ef176a1e5c1bf024077c2c9445" dependencies = [ - "anyhow", - "bitflags 1.3.2", - "byteorder", + "bitflags 2.11.0", "libc", + "log", "netlink-packet-core", - "netlink-packet-utils", ] [[package]] -name = "netlink-packet-utils" -version = "0.5.2" +name = "netlink-proto" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ede8a08c71ad5a95cdd0e4e52facd37190977039a4704eb82a283f713747d34" -dependencies = [ - "anyhow", - "byteorder", - "paste", - "thiserror 1.0.69", -] - -[[package]] -name = "netlink-proto" -version = "0.11.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72452e012c2f8d612410d89eea01e2d9b56205274abb35d53f60200b2ec41d60" +checksum = "b65d130ee111430e47eed7896ea43ca693c387f097dd97376bffafbf25812128" dependencies = [ "bytes", "futures", @@ -7387,22 +7559,23 @@ checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" [[package]] name = "nix" -version = "0.26.4" +version = "0.30.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "598beaf3cc6fdd9a5dfb1630c2800c7acd31df7aaf0f565796fba2b53ca1af1b" +checksum = "74523f3a35e05aba87a1d978330aef40f67b0304ac79c1c00b294c9830543db6" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.11.0", "cfg-if", + "cfg_aliases", "libc", ] [[package]] name = "nix" -version = "0.30.1" +version = "0.31.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74523f3a35e05aba87a1d978330aef40f67b0304ac79c1c00b294c9830543db6" +checksum = "5d6d0705320c1e6ba1d912b5e37cf18071b6c2e9b7fa8215a1e8a7651966f5d3" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "cfg-if", "cfg_aliases", "libc", @@ -7432,9 +7605,9 @@ dependencies = [ [[package]] name = "ntapi" -version = "0.4.2" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c70f219e21142367c70c0b30c6a9e3a14d55b4d12a204d897fbec83a0363f081" +checksum = "c3b335231dfd352ffb0f8017f3b6027a4917f7df785ea2143d8af2adc66980ae" dependencies = [ "winapi", ] @@ -7511,9 +7684,9 @@ dependencies = [ [[package]] name = "num-conv" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf97ec579c3c42f953ef76dbf8d55ac91fb219dde70e49aa4a6b7d74e9919050" +checksum = "c6673768db2d862beb9b39a78fdcb1a69439615d5794a1be50caa9bc92c81967" [[package]] name = "num-integer" @@ -7583,9 +7756,9 @@ dependencies = [ [[package]] name = "num_enum" -version = "0.7.5" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1207a7e20ad57b847bbddc6776b968420d38292bbfe2089accff5e19e82454c" +checksum = "5d0bca838442ec211fa11de3a8b0e0e8f3a4522575b5c4c06ed722e005036f26" dependencies = [ "num_enum_derive", "rustversion", @@ -7593,14 +7766,14 @@ dependencies = [ [[package]] name = "num_enum_derive" -version = "0.7.5" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff32365de1b6743cb203b710788263c44a03de03802daf96092f2da4fe6ba4d7" +checksum = "680998035259dcfcafe653688bf2aa6d3e2dc05e98be6ab46afb089dc84f1df8" dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -7645,9 +7818,9 @@ dependencies = [ [[package]] name = "nybbles" -version = "0.4.7" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b5676b5c379cf5b03da1df2b3061c4a4e2aa691086a56ac923e08c143f53f59" +checksum = "0d49ff0c0d00d4a502b39df9af3a525e1efeb14b9dabb5bb83335284c1309210" dependencies = [ "alloy-rlp", "cfg-if", @@ -7659,9 +7832,9 @@ dependencies = [ [[package]] name = "objc2" -version = "0.6.3" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7c2599ce0ec54857b29ce62166b0ed9b4f6f1a70ccc9a71165b6154caca8c05" +checksum = "3a12a8ed07aefc768292f076dc3ac8c48f3781c8f2d5851dd3d98950e8c5a89f" dependencies = [ "objc2-encode", ] @@ -7692,9 +7865,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.21.3" +version = "1.21.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" +checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" dependencies = [ "critical-section", "portable-atomic", @@ -7814,11 +7987,11 @@ dependencies = [ [[package]] name = "openssl" -version = "0.10.75" +version = "0.10.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08838db121398ad17ab8531ce9de97b244589089e290a384c900cb9ff7434328" +checksum = "951c002c75e16ea2c65b8c7e4d3d51d5530d8dfa7d060b4776828c88cfb18ecf" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "cfg-if", "foreign-types", "libc", @@ -7835,7 +8008,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -7844,11 +8017,17 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" +[[package]] +name = "openssl-probe" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c87def4c32ab89d880effc9e097653c8da5d6ef28e6b539d313baaacfbafcbe" + [[package]] name = "openssl-sys" -version = "0.9.111" +version = "0.9.112" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82cab2d520aa75e3c58898289429321eb788c3106963d0dc886ec7a5f4adc321" +checksum = "57d55af3b3e226502be1526dfdba67ab0e9c96fc293004e79576b2b9edb0dbdb" dependencies = [ "cc", "libc", @@ -7894,7 +8073,7 @@ dependencies = [ "state-chain", "tokio", "tracing", - "tracing-subscriber 0.3.22", + "tracing-subscriber 0.3.23", "url", "util", "zkm-build", @@ -8278,7 +8457,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -8450,9 +8629,9 @@ checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" [[package]] name = "pest" -version = "2.8.5" +version = "2.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c9eb05c21a464ea704b53158d358a31e6425db2f63a1a7312268b05fe2b75f7" +checksum = "e0848c601009d37dfa3430c4666e147e49cdcf1b92ecd3e63657d8a5f19da662" dependencies = [ "memchr", "ucd-trie", @@ -8539,7 +8718,7 @@ dependencies = [ "phf_shared 0.11.3", "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -8552,7 +8731,7 @@ dependencies = [ "phf_shared 0.13.1", "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -8575,29 +8754,29 @@ dependencies = [ [[package]] name = "pin-project" -version = "1.1.10" +version = "1.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677f1add503faace112b9f1373e43e9e054bfdd22ff1a63c1bc485eaec6a6a8a" +checksum = "f1749c7ed4bcaf4c3d0a3efc28538844fb29bcdd7d2b67b2be7e20ba861ff517" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.1.10" +version = "1.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861" +checksum = "d9b20ed30f105399776b9c883e68e536ef602a16ae6f596d2c473591d6ad64c6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] name = "pin-project-lite" -version = "0.2.16" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" +checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" [[package]] name = "pin-utils" @@ -8607,9 +8786,9 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "piper" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96c8c490f422ef9a4efd2cb5b42b76c8613d7e7dfc1caf667b8a3350a5acc066" +checksum = "c835479a4443ded371d6c535cbfd8d31ad92c5d23ae9770a61bc155e4992a3c1" dependencies = [ "atomic-waker", "fastrand", @@ -8643,6 +8822,12 @@ version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" +[[package]] +name = "plain" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6" + [[package]] name = "pnet" version = "0.33.0" @@ -8744,7 +8929,7 @@ dependencies = [ "concurrent-queue", "hermit-abi", "pin-project-lite", - "rustix 1.1.3", + "rustix 1.1.4", "windows-sys 0.61.2", ] @@ -8754,7 +8939,7 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8159bd90725d2df49889a078b54f4f79e87f1f8a8444194cdca81d38f5393abf" dependencies = [ - "cpufeatures", + "cpufeatures 0.2.17", "opaque-debug", "universal-hash", ] @@ -8766,16 +8951,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d1fe60d06143b2430aa532c94cfe9e29783047f06c0d7fd359a9a51b729fa25" dependencies = [ "cfg-if", - "cpufeatures", + "cpufeatures 0.2.17", "opaque-debug", "universal-hash", ] [[package]] name = "portable-atomic" -version = "1.13.0" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f89776e4d69bb58bc6993e99ffa1d11f228b839984854c7daeb5d37f87cbe950" +checksum = "c33a9471896f1c69cecef8d20cbe2f7accd12527ce60845ff44c153bb2a21b49" [[package]] name = "portable-atomic-util" @@ -8833,7 +9018,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" dependencies = [ "proc-macro2", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -8862,7 +9047,7 @@ dependencies = [ [[package]] name = "primitives" version = "0.1.0" -source = "git+https://github.com/ProjectZKM/reth-processor?branch=feat%2Fslot-state-check#0b280a7cc8cd7c12bcf28a06fbdef3cb9a9ae196" +source = "git+https://github.com/ProjectZKM/reth-processor?branch=feat%2Fslot-state-check#294aa06127be4bfda47a7fd4905b93bb8e664dca" dependencies = [ "alloy-eips 1.0.41", "alloy-genesis 1.0.41", @@ -8880,11 +9065,11 @@ dependencies = [ [[package]] name = "proc-macro-crate" -version = "3.4.0" +version = "3.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "219cb19e96be00ab2e37d6e299658a0cfa83e52429179969b0f0121b4ac46983" +checksum = "e67ba7e9b2b56446f1d419b1d807906278ffa1a658a8a5d8a39dcb1f5a78614f" dependencies = [ - "toml_edit 0.23.10+spec-1.0.0", + "toml_edit 0.25.8+spec-1.1.0", ] [[package]] @@ -8930,7 +9115,7 @@ dependencies = [ "proc-macro-error-attr2", "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -8962,7 +9147,7 @@ checksum = "440f724eba9f6996b75d63681b0a92b06947f1457076d503a4d2e2c8f56442b8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -9014,21 +9199,21 @@ dependencies = [ "toml 0.8.23", "tower-http", "tracing", - "tracing-subscriber 0.3.22", + "tracing-subscriber 0.3.23", "util", - "uuid 1.20.0", + "uuid 1.22.0", "watchtower-proof", ] [[package]] name = "proptest" -version = "1.9.0" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bee689443a2bd0a16ab0348b52ee43e3b2d1b1f931c8aa5c9f8de4c86fbe8c40" +checksum = "4b45fcc2344c680f5025fe57779faef368840d0bd1f42f216291f0dc4ace4744" dependencies = [ "bit-set 0.8.0", "bit-vec 0.8.0", - "bitflags 2.10.0", + "bitflags 2.11.0", "num-traits", "rand 0.9.2", "rand_chacha 0.9.0", @@ -9097,7 +9282,7 @@ dependencies = [ "prost 0.13.5", "prost-types 0.13.5", "regex", - "syn 2.0.114", + "syn 2.0.117", "tempfile", ] @@ -9124,7 +9309,7 @@ dependencies = [ "itertools 0.14.0", "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -9148,7 +9333,7 @@ dependencies = [ [[package]] name = "provider" version = "0.1.0" -source = "git+https://github.com/ProjectZKM/reth-processor?branch=feat%2Fslot-state-check#0b280a7cc8cd7c12bcf28a06fbdef3cb9a9ae196" +source = "git+https://github.com/ProjectZKM/reth-processor?branch=feat%2Fslot-state-check#294aa06127be4bfda47a7fd4905b93bb8e664dca" dependencies = [ "alloy-json-rpc 1.0.41", "alloy-provider 1.0.41", @@ -9198,8 +9383,8 @@ dependencies = [ "quinn-proto", "quinn-udp", "rustc-hash 2.1.1", - "rustls 0.23.36", - "socket2 0.6.2", + "rustls 0.23.37", + "socket2 0.6.3", "thiserror 2.0.18", "tokio", "tracing", @@ -9208,17 +9393,18 @@ dependencies = [ [[package]] name = "quinn-proto" -version = "0.11.13" +version = "0.11.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1906b49b0c3bc04b5fe5d86a77925ae6524a19b816ae38ce1e426255f1d8a31" +checksum = "434b42fec591c96ef50e21e886936e66d3cc3f737104fdb9b737c40ffb94c098" dependencies = [ + "aws-lc-rs", "bytes", "getrandom 0.3.4", "lru-slab", "rand 0.9.2", "ring 0.17.14", "rustc-hash 2.1.1", - "rustls 0.23.36", + "rustls 0.23.37", "rustls-pki-types", "slab", "thiserror 2.0.18", @@ -9236,16 +9422,16 @@ dependencies = [ "cfg_aliases", "libc", "once_cell", - "socket2 0.6.2", + "socket2 0.6.3", "tracing", "windows-sys 0.60.2", ] [[package]] name = "quote" -version = "1.0.44" +version = "1.0.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21b2ebcf727b7760c461f091f9f0f539b77b8e87f2fd88131e7f1b433b3cece4" +checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" dependencies = [ "proc-macro2", ] @@ -9256,6 +9442,12 @@ version = "5.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" +[[package]] +name = "r-efi" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" + [[package]] name = "radium" version = "0.7.0" @@ -9285,6 +9477,17 @@ dependencies = [ "serde", ] +[[package]] +name = "rand" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc266eb313df6c5c09c1c7b1fbe2510961e5bcd3add930c1e31f7ed9da0feff8" +dependencies = [ + "chacha20 0.10.0", + "getrandom 0.4.2", + "rand_core 0.10.0", +] + [[package]] name = "rand_chacha" version = "0.3.1" @@ -9324,6 +9527,12 @@ dependencies = [ "serde", ] +[[package]] +name = "rand_core" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c8d0fd677905edcbeedbf2edb6494d676f0e98d54d5cf9bda0b061cb8fb8aba" + [[package]] name = "rand_xorshift" version = "0.4.0" @@ -9335,9 +9544,9 @@ dependencies = [ [[package]] name = "rapidhash" -version = "4.2.1" +version = "4.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d8b5b858a440a0bc02625b62dd95131b9201aa9f69f411195dd4a7cfb1de3d7" +checksum = "b5e48930979c155e2f33aa36ab3119b5ee81332beb6482199a8ecd6029b80b59" dependencies = [ "rustversion", ] @@ -9396,16 +9605,16 @@ version = "0.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", ] [[package]] name = "redox_syscall" -version = "0.7.0" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49f3fe0889e69e2ae9e41f4d6c4c0181701d00e4697b356fb1f74173a5e0ee27" +checksum = "6ce70a74e890531977d37e532c34d45e9055d2409ed08ddba14529471ed0be16" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", ] [[package]] @@ -9436,14 +9645,14 @@ checksum = "b7186006dcb21920990093f30e3dea63b7d6e977bf1256be20c3563a5db070da" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] name = "regex" -version = "1.12.2" +version = "1.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "843bc0191f75f3e22651ae5f1e72939ab2f72a4bc30fa80a066bd66edefc24d4" +checksum = "e10754a14b9137dd7b1e3e5b0493cc9171fdd105e0ab477f51b72e7f3ac0e276" dependencies = [ "aho-corasick", "memchr", @@ -9453,9 +9662,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.13" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5276caf25ac86c8d810222b3dbb938e512c55c6831a10f3e6ed1c93b84041f1c" +checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f" dependencies = [ "aho-corasick", "memchr", @@ -9464,9 +9673,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.8" +version = "0.8.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a2d987857b319362043e95f5353c0535c1f58eec5336fdfcf626430af7def58" +checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a" [[package]] name = "reqwest" @@ -9495,7 +9704,7 @@ dependencies = [ "percent-encoding", "pin-project-lite", "rustls 0.21.12", - "rustls-native-certs", + "rustls-native-certs 0.6.3", "rustls-pemfile", "serde", "serde_json", @@ -9539,7 +9748,7 @@ dependencies = [ "percent-encoding", "pin-project-lite", "quinn", - "rustls 0.23.36", + "rustls 0.23.37", "rustls-pki-types", "serde", "serde_json", @@ -9556,7 +9765,44 @@ dependencies = [ "wasm-bindgen-futures", "wasm-streams", "web-sys", - "webpki-roots 1.0.5", + "webpki-roots 1.0.6", +] + +[[package]] +name = "reqwest" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab3f43e3283ab1488b624b44b0e988d0acea0b3214e694730a055cb6b2efa801" +dependencies = [ + "base64 0.22.1", + "bytes", + "futures-core", + "http 1.4.0", + "http-body 1.0.1", + "http-body-util", + "hyper 1.8.1", + "hyper-rustls 0.27.7", + "hyper-util", + "js-sys", + "log", + "percent-encoding", + "pin-project-lite", + "quinn", + "rustls 0.23.37", + "rustls-pki-types", + "rustls-platform-verifier", + "serde", + "serde_json", + "sync_wrapper 1.0.2", + "tokio", + "tokio-rustls 0.26.4", + "tower 0.5.3", + "tower-http", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", ] [[package]] @@ -9576,7 +9822,7 @@ dependencies = [ "alloy-evm", "alloy-genesis 1.0.41", "alloy-primitives", - "alloy-trie 0.9.3", + "alloy-trie 0.9.5", "auto_impl", "derive_more 2.1.1", "reth-ethereum-forks", @@ -9594,7 +9840,7 @@ dependencies = [ "alloy-eips 1.0.41", "alloy-genesis 1.0.41", "alloy-primitives", - "alloy-trie 0.9.3", + "alloy-trie 0.9.5", "bytes", "modular-bitfield", "op-alloy-consensus", @@ -9610,7 +9856,7 @@ source = "git+https://github.com/ziren-patches/reth?branch=patch-1.9.3#fb7e5b4b3 dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -9755,7 +10001,7 @@ dependencies = [ "alloy-evm", "alloy-primitives", "alloy-rlp", - "nybbles 0.4.7", + "nybbles 0.4.8", "reth-storage-errors", "thiserror 2.0.18", ] @@ -9819,7 +10065,7 @@ dependencies = [ "alloy-consensus 1.0.41", "alloy-eips 1.0.41", "alloy-primitives", - "alloy-trie 0.9.3", + "alloy-trie 0.9.5", "reth-chainspec", "reth-consensus", "reth-consensus-common", @@ -9902,7 +10148,7 @@ dependencies = [ "alloy-primitives", "alloy-rlp", "alloy-rpc-types-eth 1.0.41", - "alloy-trie 0.9.3", + "alloy-trie 0.9.5", "auto_impl", "bytes", "derive_more 2.1.1", @@ -9996,7 +10242,7 @@ dependencies = [ "alloy-eips 1.0.41", "alloy-primitives", "alloy-rlp", - "alloy-trie 0.9.3", + "alloy-trie 0.9.5", "auto_impl", "itertools 0.14.0", "reth-execution-errors", @@ -10017,10 +10263,10 @@ dependencies = [ "alloy-consensus 1.0.41", "alloy-primitives", "alloy-rlp", - "alloy-trie 0.9.3", + "alloy-trie 0.9.5", "derive_more 2.1.1", "itertools 0.14.0", - "nybbles 0.4.7", + "nybbles 0.4.8", "rayon", "reth-primitives-traits", "revm-database", @@ -10033,7 +10279,7 @@ source = "git+https://github.com/ziren-patches/reth?branch=patch-1.9.3#fb7e5b4b3 dependencies = [ "alloy-primitives", "alloy-rlp", - "alloy-trie 0.9.3", + "alloy-trie 0.9.5", "auto_impl", "reth-execution-errors", "reth-primitives-traits", @@ -10220,7 +10466,7 @@ name = "revm-state" version = "8.1.1" source = "git+https://github.com/ziren-patches/revm?branch=patch-31.0.2#0cd8a9cffabcc01fd92b8f12d6d601040e0ec88f" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "revm-bytecode", "revm-primitives", "serde", @@ -10299,7 +10545,7 @@ dependencies = [ [[package]] name = "rpc-db" version = "0.1.0" -source = "git+https://github.com/ProjectZKM/reth-processor?branch=feat%2Fslot-state-check#0b280a7cc8cd7c12bcf28a06fbdef3cb9a9ae196" +source = "git+https://github.com/ProjectZKM/reth-processor?branch=feat%2Fslot-state-check#294aa06127be4bfda47a7fd4905b93bb8e664dca" dependencies = [ "alloy-consensus 1.0.41", "alloy-primitives", @@ -10343,18 +10589,18 @@ dependencies = [ [[package]] name = "rtnetlink" -version = "0.13.1" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a552eb82d19f38c3beed3f786bd23aa434ceb9ac43ab44419ca6d67a7e186c0" +checksum = "4b960d5d873a75b5be9761b1e73b146f52dddcd27bac75263f40fba686d4d7b5" dependencies = [ - "futures", + "futures-channel", + "futures-util", "log", "netlink-packet-core", "netlink-packet-route", - "netlink-packet-utils", "netlink-proto", "netlink-sys", - "nix 0.26.4", + "nix 0.30.1", "thiserror 1.0.69", "tokio", ] @@ -10450,7 +10696,7 @@ version = "0.38.44" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "errno", "libc", "linux-raw-sys 0.4.15", @@ -10459,14 +10705,14 @@ dependencies = [ [[package]] name = "rustix" -version = "1.1.3" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "146c9e247ccc180c1f61615433868c99f3de3ae256a30a43b49f67c2d9171f34" +checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "errno", "libc", - "linux-raw-sys 0.11.0", + "linux-raw-sys 0.12.1", "windows-sys 0.61.2", ] @@ -10496,14 +10742,15 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.36" +version = "0.23.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c665f33d38cea657d9614f766881e4d510e0eda4239891eea56b4cadcf01801b" +checksum = "758025cb5fccfd3bc2fd74708fd4682be41d99e5dff73c377c0646c6012c73a4" dependencies = [ + "aws-lc-rs", "once_cell", "ring 0.17.14", "rustls-pki-types", - "rustls-webpki 0.103.9", + "rustls-webpki 0.103.10", "subtle", "zeroize", ] @@ -10514,10 +10761,22 @@ version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a9aace74cb666635c918e9c12bc0d348266037aa8eb599b5cba565709a8dff00" dependencies = [ - "openssl-probe", + "openssl-probe 0.1.6", "rustls-pemfile", "schannel", - "security-framework", + "security-framework 2.11.1", +] + +[[package]] +name = "rustls-native-certs" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "612460d5f7bea540c490b2b6395d8e34a953e52b491accd6c86c8164c5932a63" +dependencies = [ + "openssl-probe 0.2.1", + "rustls-pki-types", + "schannel", + "security-framework 3.7.0", ] [[package]] @@ -10539,6 +10798,33 @@ dependencies = [ "zeroize", ] +[[package]] +name = "rustls-platform-verifier" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d99feebc72bae7ab76ba994bb5e121b8d83d910ca40b36e0921f53becc41784" +dependencies = [ + "core-foundation 0.10.1", + "core-foundation-sys", + "jni", + "log", + "once_cell", + "rustls 0.23.37", + "rustls-native-certs 0.8.3", + "rustls-platform-verifier-android", + "rustls-webpki 0.103.10", + "security-framework 3.7.0", + "security-framework-sys", + "webpki-root-certs", + "windows-sys 0.61.2", +] + +[[package]] +name = "rustls-platform-verifier-android" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f87165f0995f63a9fbeea62b64d10b4d9d8e78ec6d7d51fb2125fda7bb36788f" + [[package]] name = "rustls-webpki" version = "0.101.7" @@ -10551,10 +10837,11 @@ dependencies = [ [[package]] name = "rustls-webpki" -version = "0.103.9" +version = "0.103.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7df23109aa6c1567d1c575b9952556388da57401e4ace1d15f79eedad0d8f53" +checksum = "df33b2b81ac578cabaf06b89b0631153a3f416b0a886e8a7a1707fb51abbd1ef" dependencies = [ + "aws-lc-rs", "ring 0.17.14", "rustls-pki-types", "untrusted 0.9.0", @@ -10591,9 +10878,9 @@ dependencies = [ [[package]] name = "ryu" -version = "1.0.22" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a50f4cf475b65d88e057964e0e9bb1f0aa9bbb2036dc65c64596b42932536984" +checksum = "9774ba4a74de5f7b1c1451ed6cd5285a32eddb5cccb8cc655a4e50009e06477f" [[package]] name = "salsa20" @@ -10634,7 +10921,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -10648,9 +10935,9 @@ dependencies = [ [[package]] name = "schannel" -version = "0.1.28" +version = "0.1.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "891d81b926048e76efe18581bf793546b4c0eaf8448d72be8de2bbee5fd166e1" +checksum = "91c1b7e4904c873ef0710c1f407dde2e6287de2bebc1bbbf7d430bb7cbffd939" dependencies = [ "windows-sys 0.61.2", ] @@ -10669,9 +10956,9 @@ dependencies = [ [[package]] name = "schemars" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54e910108742c57a770f492731f99be216a52fadd361b06c8fb59d74ccc267d2" +checksum = "a2b42f36aa1cd011945615b92222f6bf73c599a102a300334cd7f8dbeec726cc" dependencies = [ "dyn-clone", "ref-cast", @@ -10812,8 +11099,21 @@ version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" dependencies = [ - "bitflags 2.10.0", - "core-foundation", + "bitflags 2.11.0", + "core-foundation 0.9.4", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework" +version = "3.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7f4bc775c73d9a02cde8bf7b2ec4c9d12743edf609006c7facc23998404cd1d" +dependencies = [ + "bitflags 2.11.0", + "core-foundation 0.10.1", "core-foundation-sys", "libc", "security-framework-sys", @@ -10821,9 +11121,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.15.0" +version = "2.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc1f0cbffaac4852523ce30d8bd3c5cdc873501d96ff467ca09b6767bb8cd5c0" +checksum = "6ce2691df843ecc5d231c0b14ece2acc3efb62c0a398c7e1d875f3983ce020e3" dependencies = [ "core-foundation-sys", "libc", @@ -10935,7 +11235,7 @@ checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -10970,7 +11270,7 @@ checksum = "175ee3e80ae9982737ca543e96133087cbd9a485eecc3bc4de9c1a37b47ea59c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -10996,9 +11296,9 @@ dependencies = [ [[package]] name = "serde_with" -version = "3.16.1" +version = "3.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fa237f2807440d238e0364a218270b98f767a00d3dada77b1c53ae88940e2e7" +checksum = "dd5414fad8e6907dbdd5bc441a50ae8d6e26151a03b1de04d89a5576de61d01f" dependencies = [ "base64 0.22.1", "chrono", @@ -11006,7 +11306,7 @@ dependencies = [ "indexmap 1.9.3", "indexmap 2.13.0", "schemars 0.9.0", - "schemars 1.2.0", + "schemars 1.2.1", "serde_core", "serde_json", "serde_with_macros", @@ -11015,14 +11315,14 @@ dependencies = [ [[package]] name = "serde_with_macros" -version = "3.16.1" +version = "3.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52a8e3ca0ca629121f70ab50f95249e5a6f925cc0f6ffe8256c45b728875706c" +checksum = "d3db8978e608f1fe7357e211969fd9abdcae80bac1ba7a3369bb7eb6b404eb65" dependencies = [ - "darling", + "darling 0.23.0", "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -11037,9 +11337,9 @@ dependencies = [ [[package]] name = "serial_test" -version = "3.3.1" +version = "3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d0b343e184fc3b7bb44dff0705fffcf4b3756ba6aff420dddd8b24ca145e555" +checksum = "911bd979bf1070a3f3aa7b691a3b3e9968f339ceeec89e08c280a8a22207a32f" dependencies = [ "futures-executor", "futures-util", @@ -11052,13 +11352,13 @@ dependencies = [ [[package]] name = "serial_test_derive" -version = "3.3.1" +version = "3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f50427f258fb77356e4cd4aa0e87e2bd2c66dbcee41dc405282cae2bfc26c83" +checksum = "0a7d91949b85b0d2fb687445e448b40d322b6b3e4af6b44a29b21d9a5f33e6d9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -11068,7 +11368,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" dependencies = [ "cfg-if", - "cpufeatures", + "cpufeatures 0.2.17", "digest 0.10.7", ] @@ -11080,7 +11380,7 @@ checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" dependencies = [ "block-buffer 0.9.0", "cfg-if", - "cpufeatures", + "cpufeatures 0.2.17", "digest 0.9.0", "opaque-debug", ] @@ -11092,7 +11392,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" dependencies = [ "cfg-if", - "cpufeatures", + "cpufeatures 0.2.17", "digest 0.10.7", ] @@ -11180,9 +11480,9 @@ checksum = "e320a6c5ad31d271ad523dcf3ad13e2767ad8b1cb8f047f75a8aeaf8da139da2" [[package]] name = "simple_asn1" -version = "0.6.3" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "297f631f50729c8c99b84667867963997ec0b50f32b2a7dbcab828ef0541e8bb" +checksum = "0d585997b0ac10be3c5ee635f1bab02d512760d14b7c468801ac8a01d9ae5f1d" dependencies = [ "num-bigint 0.4.6", "num-traits", @@ -11204,9 +11504,9 @@ checksum = "9fed904c7fb2856d868b92464fc8fa597fce366edea1a9cbfaa8cb5fe080bd6d" [[package]] name = "slab" -version = "0.4.11" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a2ae44ef20feb57a68b23d846850f861394c2e02dc425a50098ae8c90267589" +checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" [[package]] name = "smallvec" @@ -11256,12 +11556,12 @@ dependencies = [ [[package]] name = "socket2" -version = "0.6.2" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86f4aa3ad99f2088c990dfa82d367e19cb29268ed67c574d10d0a4bfe71f07e0" +checksum = "3a766e1110788c36f4fa1c2b71b387a7815aa65f88ce0229841826633d93723e" dependencies = [ "libc", - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -11363,7 +11663,7 @@ dependencies = [ "tokio-stream", "tracing", "url", - "uuid 1.20.0", + "uuid 1.22.0", ] [[package]] @@ -11376,7 +11676,7 @@ dependencies = [ "quote", "sqlx-core", "sqlx-macros-core", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -11399,7 +11699,7 @@ dependencies = [ "sqlx-mysql", "sqlx-postgres", "sqlx-sqlite", - "syn 2.0.114", + "syn 2.0.117", "tokio", "url", ] @@ -11412,7 +11712,7 @@ checksum = "aa003f0038df784eb8fecbbac13affe3da23b45194bd57dba231c8f48199c526" dependencies = [ "atoi", "base64 0.22.1", - "bitflags 2.10.0", + "bitflags 2.11.0", "byteorder", "bytes", "crc", @@ -11443,7 +11743,7 @@ dependencies = [ "stringprep", "thiserror 2.0.18", "tracing", - "uuid 1.20.0", + "uuid 1.22.0", "whoami", ] @@ -11455,7 +11755,7 @@ checksum = "db58fcd5a53cf07c184b154801ff91347e4c30d17a3562a635ff028ad5deda46" dependencies = [ "atoi", "base64 0.22.1", - "bitflags 2.10.0", + "bitflags 2.11.0", "byteorder", "crc", "dotenvy", @@ -11481,7 +11781,7 @@ dependencies = [ "stringprep", "thiserror 2.0.18", "tracing", - "uuid 1.20.0", + "uuid 1.22.0", "whoami", ] @@ -11507,7 +11807,7 @@ dependencies = [ "thiserror 2.0.18", "tracing", "url", - "uuid 1.20.0", + "uuid 1.22.0", ] [[package]] @@ -11578,7 +11878,7 @@ dependencies = [ "state-chain", "tokio", "tracing", - "tracing-subscriber 0.3.22", + "tracing-subscriber 0.3.23", "url", "util", "zkm-build", @@ -11618,7 +11918,7 @@ dependencies = [ "tokio", "tokio-util", "tracing", - "uuid 1.20.0", + "uuid 1.22.0", "walkdir", ] @@ -11685,7 +11985,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -11697,7 +11997,7 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -11797,9 +12097,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.114" +version = "2.0.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4d107df263a3013ef9b1879b0df87d706ff80f65a86ea879bd9c31f9b307c2a" +checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" dependencies = [ "proc-macro2", "quote", @@ -11808,14 +12108,14 @@ dependencies = [ [[package]] name = "syn-solidity" -version = "1.5.4" +version = "1.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2379beea9476b89d0237078be761cf8e012d92d5ae4ae0c9a329f974838870fc" +checksum = "53f425ae0b12e2f5ae65542e00898d500d4d318b4baf09f40fd0d410454e9947" dependencies = [ "paste", "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -11841,7 +12141,7 @@ checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -11866,18 +12166,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" dependencies = [ "bitflags 1.3.2", - "core-foundation", + "core-foundation 0.9.4", "system-configuration-sys 0.5.0", ] [[package]] name = "system-configuration" -version = "0.6.1" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" +checksum = "a13f3d0daba03132c0aa9767f98351b3488edc2c100cda2d2ec2b04f3d8d3c8b" dependencies = [ - "bitflags 2.10.0", - "core-foundation", + "bitflags 2.11.0", + "core-foundation 0.9.4", "system-configuration-sys 0.6.0", ] @@ -11915,14 +12215,14 @@ checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" [[package]] name = "tempfile" -version = "3.24.0" +version = "3.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "655da9c7eb6305c55742045d5a8d2037996d61d8de95806335c7c86ce0f82e9c" +checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd" dependencies = [ "fastrand", - "getrandom 0.3.4", + "getrandom 0.4.2", "once_cell", - "rustix 1.1.3", + "rustix 1.1.4", "windows-sys 0.61.2", ] @@ -12037,7 +12337,7 @@ dependencies = [ "tokio", "tracing", "url", - "uuid 1.20.0", + "uuid 1.22.0", "walkdir", ] @@ -12078,7 +12378,7 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -12089,7 +12389,7 @@ checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -12112,9 +12412,9 @@ dependencies = [ [[package]] name = "time" -version = "0.3.46" +version = "0.3.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9da98b7d9b7dad93488a84b8248efc35352b0b2657397d4167e7ad67e5d535e5" +checksum = "743bd48c283afc0388f9b8827b976905fb217ad9e647fae3a379a9283c4def2c" dependencies = [ "deranged", "itoa", @@ -12135,9 +12435,9 @@ checksum = "7694e1cfe791f8d31026952abf09c69ca6f6fa4e1a1229e18988f06a04a12dca" [[package]] name = "time-macros" -version = "0.2.26" +version = "0.2.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78cc610bac2dcee56805c99642447d4c5dbde4d01f752ffea0199aee1f601dc4" +checksum = "2e70e4c5a0e0a8a4823ad65dfe1a6930e4f4d756dcd9dd7939022b5e8c501215" dependencies = [ "num-conv", "time-core", @@ -12164,9 +12464,9 @@ dependencies = [ [[package]] name = "tinyvec" -version = "1.10.0" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa5fdc3bce6191a1dbc8c02d5c8bffcf557bafa17c124c5264a458f1b0613fa" +checksum = "3e61e67053d25a4e82c844e8424039d9745781b3fc4f32b8d55ed50f5f667ef3" dependencies = [ "tinyvec_macros", ] @@ -12179,9 +12479,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.49.0" +version = "1.50.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72a2903cd7736441aac9df9d7688bd0ce48edccaadf181c3b90be801e81d3d86" +checksum = "27ad5e34374e03cfffefc301becb44e9dc3c17584f414349ebe29ed26661822d" dependencies = [ "bytes", "libc", @@ -12189,7 +12489,7 @@ dependencies = [ "parking_lot", "pin-project-lite", "signal-hook-registry", - "socket2 0.6.2", + "socket2 0.6.3", "tokio-macros", "windows-sys 0.61.2", ] @@ -12206,13 +12506,13 @@ dependencies = [ [[package]] name = "tokio-macros" -version = "2.6.0" +version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af407857209536a95c8e56f8231ef2c2e2aff839b22e07a1ffcbc617e9db9fa5" +checksum = "5c55a2eff8b69ce66c84f85e1da1c233edc36ceb85a2058d11b0d6a3c7e7569c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -12252,7 +12552,7 @@ version = "0.26.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1729aa945f29d91ba541258c8df89027d5792d85a8841fb65e8bf0f4ede4ef61" dependencies = [ - "rustls 0.23.36", + "rustls 0.23.37", "tokio", ] @@ -12297,17 +12597,17 @@ dependencies = [ [[package]] name = "tokio-tungstenite" -version = "0.26.2" +version = "0.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a9daff607c6d2bf6c16fd681ccb7eecc83e4e2cdc1ca067ffaadfca5de7f084" +checksum = "d25a406cddcc431a75d3d9afc6a7c0f7428d4891dd973e4d54c56b46127bf857" dependencies = [ "futures-util", "log", - "rustls 0.23.36", + "rustls 0.23.37", "rustls-pki-types", "tokio", "tokio-rustls 0.26.4", - "tungstenite 0.26.2", + "tungstenite 0.28.0", "webpki-roots 0.26.11", ] @@ -12356,9 +12656,9 @@ dependencies = [ [[package]] name = "toml_datetime" -version = "0.7.5+spec-1.1.0" +version = "1.1.0+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92e1cfed4a3038bc5a127e35a2d360f145e1f4b971b551a2ba5fd7aedf7e1347" +checksum = "97251a7c317e03ad83774a8752a7e81fb6067740609f75ea2b585b569a59198f" dependencies = [ "serde_core", ] @@ -12374,28 +12674,28 @@ dependencies = [ "serde_spanned", "toml_datetime 0.6.11", "toml_write", - "winnow", + "winnow 0.7.15", ] [[package]] name = "toml_edit" -version = "0.23.10+spec-1.0.0" +version = "0.25.8+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84c8b9f757e028cee9fa244aea147aab2a9ec09d5325a9b01e0a49730c2b5269" +checksum = "16bff38f1d86c47f9ff0647e6838d7bb362522bdf44006c7068c2b1e606f1f3c" dependencies = [ "indexmap 2.13.0", - "toml_datetime 0.7.5+spec-1.1.0", + "toml_datetime 1.1.0+spec-1.1.0", "toml_parser", - "winnow", + "winnow 1.0.0", ] [[package]] name = "toml_parser" -version = "1.0.6+spec-1.1.0" +version = "1.1.0+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3198b4b0a8e11f09dd03e133c0280504d0801269e9afa46362ffde1cbeebf44" +checksum = "2334f11ee363607eb04df9b8fc8a13ca1715a72ba8662a26ac285c98aabb4011" dependencies = [ - "winnow", + "winnow 1.0.0", ] [[package]] @@ -12426,7 +12726,7 @@ dependencies = [ "pin-project", "prost 0.11.9", "prost-derive 0.11.9", - "rustls-native-certs", + "rustls-native-certs 0.6.3", "rustls-pemfile", "tokio", "tokio-rustls 0.23.4", @@ -12494,7 +12794,7 @@ version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d4e6559d53cc268e5031cd8429d05415bc4cb4aefc4aa5d6cc35fbf5b924a1f8" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "bytes", "futures-util", "http 1.4.0", @@ -12550,7 +12850,7 @@ checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -12573,7 +12873,7 @@ dependencies = [ "smallvec", "thiserror 1.0.69", "tracing", - "tracing-subscriber 0.3.22", + "tracing-subscriber 0.3.23", ] [[package]] @@ -12608,9 +12908,9 @@ dependencies = [ [[package]] name = "tracing-subscriber" -version = "0.3.22" +version = "0.3.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f30143827ddab0d256fd843b7a66d164e9f271cfa0dde49142c5ca0ca291f1e" +checksum = "cb7f578e5945fb242538965c2d0b04418d38ec25c79d160cd279bf0731c8d319" dependencies = [ "matchers", "nu-ansi-term", @@ -12662,9 +12962,9 @@ dependencies = [ [[package]] name = "tungstenite" -version = "0.26.2" +version = "0.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4793cb5e56680ecbb1d843515b23b6de9a75eb04b66643e256a396d43be33c13" +checksum = "8628dcc84e5a09eb3d8423d6cb682965dea9133204e8fb3efee74c2a0c259442" dependencies = [ "bytes", "data-encoding", @@ -12672,7 +12972,7 @@ dependencies = [ "httparse", "log", "rand 0.9.2", - "rustls 0.23.36", + "rustls 0.23.37", "rustls-pki-types", "sha1", "thiserror 2.0.18", @@ -12766,9 +13066,9 @@ checksum = "5c1cb5db39152898a79168971543b1cb5020dff7fe43c8dc468b0885f5e29df5" [[package]] name = "unicode-ident" -version = "1.0.22" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5" +checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" [[package]] name = "unicode-normalization" @@ -12787,9 +13087,9 @@ checksum = "7df058c713841ad818f1dc5d3fd88063241cc61f49f5fbea4b951e8cf5a8d71d" [[package]] name = "unicode-segmentation" -version = "1.12.0" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" +checksum = "da36089a805484bcccfffe0739803392c8298778a2d2f09febf76fac5ad9025b" [[package]] name = "unicode-width" @@ -12898,13 +13198,13 @@ dependencies = [ [[package]] name = "uuid" -version = "1.20.0" +version = "1.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee48d38b119b0cd71fe4141b30f5ba9c7c5d9f4e7a3a8b4a674e4b6ef789976f" +checksum = "a68d3c8f01c0cfa54a75291d83601161799e4a89a39e0929f4b0354d88757a37" dependencies = [ - "getrandom 0.3.4", + "getrandom 0.4.2", "js-sys", - "rand 0.9.2", + "rand 0.10.0", "serde_core", "wasm-bindgen", ] @@ -12998,6 +13298,15 @@ dependencies = [ "wit-bindgen", ] +[[package]] +name = "wasip3" +version = "0.4.0+wasi-0.3.0-rc-2026-01-06" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5" +dependencies = [ + "wit-bindgen", +] + [[package]] name = "wasite" version = "0.1.0" @@ -13006,9 +13315,9 @@ checksum = "b8dad83b4f25e74f184f64c43b150b91efe7647395b42289f38e50566d82855b" [[package]] name = "wasm-bindgen" -version = "0.2.108" +version = "0.2.114" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64024a30ec1e37399cf85a7ffefebdb72205ca1c972291c51512360d90bd8566" +checksum = "6532f9a5c1ece3798cb1c2cfdba640b9b3ba884f5db45973a6f442510a87d38e" dependencies = [ "cfg-if", "once_cell", @@ -13019,9 +13328,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.58" +version = "0.4.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70a6e77fd0ae8029c9ea0063f87c46fde723e7d887703d74ad2616d792e51e6f" +checksum = "e9c5522b3a28661442748e09d40924dfb9ca614b21c00d3fd135720e48b67db8" dependencies = [ "cfg-if", "futures-util", @@ -13033,9 +13342,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.108" +version = "0.2.114" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "008b239d9c740232e71bd39e8ef6429d27097518b6b30bdf9086833bd5b6d608" +checksum = "18a2d50fcf105fb33bb15f00e7a77b772945a2ee45dcf454961fd843e74c18e6" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -13043,26 +13352,48 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.108" +version = "0.2.114" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5256bae2d58f54820e6490f9839c49780dff84c65aeab9e772f15d5f0e913a55" +checksum = "03ce4caeaac547cdf713d280eda22a730824dd11e6b8c3ca9e42247b25c631e3" dependencies = [ "bumpalo", "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.108" +version = "0.2.114" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f01b580c9ac74c8d8f0c0e4afb04eeef2acf145458e52c03845ee9cd23e3d12" +checksum = "75a326b8c223ee17883a4251907455a2431acc2791c98c26279376490c378c16" dependencies = [ "unicode-ident", ] +[[package]] +name = "wasm-encoder" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "990065f2fe63003fe337b932cfb5e3b80e0b4d0f5ff650e6985b1048f62c8319" +dependencies = [ + "leb128fmt", + "wasmparser", +] + +[[package]] +name = "wasm-metadata" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb0e353e6a2fbdc176932bbaab493762eb1255a7900fe0fea1a2f96c296cc909" +dependencies = [ + "anyhow", + "indexmap 2.13.0", + "wasm-encoder", + "wasmparser", +] + [[package]] name = "wasm-streams" version = "0.4.2" @@ -13076,6 +13407,18 @@ dependencies = [ "web-sys", ] +[[package]] +name = "wasmparser" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" +dependencies = [ + "bitflags 2.11.0", + "hashbrown 0.15.5", + "indexmap 2.13.0", + "semver 1.0.27", +] + [[package]] name = "wasmtimer" version = "0.4.3" @@ -13119,7 +13462,7 @@ dependencies = [ "state-chain", "tokio", "tracing", - "tracing-subscriber 0.3.22", + "tracing-subscriber 0.3.23", "zkm-build", "zkm-prover", "zkm-sdk", @@ -13129,9 +13472,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.85" +version = "0.3.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "312e32e551d92129218ea9a2452120f4aabc03529ef03e4d0d82fb2780608598" +checksum = "854ba17bb104abfb26ba36da9729addc7ce7f06f5c0f90f3c391f8461cca21f9" dependencies = [ "js-sys", "wasm-bindgen", @@ -13157,6 +13500,15 @@ dependencies = [ "untrusted 0.9.0", ] +[[package]] +name = "webpki-root-certs" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "804f18a4ac2676ffb4e8b5b5fa9ae38af06df08162314f96a68d2a363e21a8ca" +dependencies = [ + "rustls-pki-types", +] + [[package]] name = "webpki-roots" version = "0.25.4" @@ -13169,14 +13521,14 @@ version = "0.26.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "521bc38abb08001b01866da9f51eb7c5d647a19260e00054a8c7fd5f9e57f7a9" dependencies = [ - "webpki-roots 1.0.5", + "webpki-roots 1.0.6", ] [[package]] name = "webpki-roots" -version = "1.0.5" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12bed680863276c63889429bfd6cab3b99943659923822de1c8a39c49e4d722c" +checksum = "22cfaf3c063993ff62e73cb4311efde4db1efb31ab78a3e5c457939ad5cc0bed" dependencies = [ "rustls-pki-types", ] @@ -13252,30 +13604,31 @@ dependencies = [ [[package]] name = "windows" -version = "0.53.0" +version = "0.62.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efc5cf48f83140dcaab716eeaea345f9e93d0018fb81162753a3f76c3397b538" +checksum = "527fadee13e0c05939a6a05d5bd6eec6cd2e3dbd648b9f8e447c6518133d8580" dependencies = [ - "windows-core 0.53.0", - "windows-targets 0.52.6", + "windows-collections", + "windows-core 0.62.2", + "windows-future", + "windows-numerics", ] [[package]] -name = "windows-core" -version = "0.52.0" +name = "windows-collections" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" +checksum = "23b2d95af1a8a14a3c7367e1ed4fc9c20e0a26e79551b1454d72583c97cc6610" dependencies = [ - "windows-targets 0.52.6", + "windows-core 0.62.2", ] [[package]] name = "windows-core" -version = "0.53.0" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9dcc5b895a6377f1ab9fa55acedab1fd5ac0db66ad1e6c7f47e28a22e446a5dd" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" dependencies = [ - "windows-result 0.1.2", "windows-targets 0.52.6", ] @@ -13288,10 +13641,21 @@ dependencies = [ "windows-implement", "windows-interface", "windows-link", - "windows-result 0.4.1", + "windows-result", "windows-strings", ] +[[package]] +name = "windows-future" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1d6f90251fe18a279739e78025bd6ddc52a7e22f921070ccdc67dde84c605cb" +dependencies = [ + "windows-core 0.62.2", + "windows-link", + "windows-threading", +] + [[package]] name = "windows-implement" version = "0.60.2" @@ -13300,7 +13664,7 @@ checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -13311,7 +13675,7 @@ checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -13321,12 +13685,24 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" [[package]] -name = "windows-result" -version = "0.1.2" +name = "windows-numerics" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e383302e8ec8515204254685643de10811af0ed97ea37210dc26fb0032647f8" +checksum = "6e2e40844ac143cdb44aead537bbf727de9b044e107a0f1220392177d15b0f26" dependencies = [ - "windows-targets 0.52.6", + "windows-core 0.62.2", + "windows-link", +] + +[[package]] +name = "windows-registry" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02752bf7fbdcce7f2a27a742f798510f3e5ad88dbe84871e5168e2120c3d5720" +dependencies = [ + "windows-link", + "windows-result", + "windows-strings", ] [[package]] @@ -13347,6 +13723,15 @@ dependencies = [ "windows-link", ] +[[package]] +name = "windows-sys" +version = "0.45.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +dependencies = [ + "windows-targets 0.42.2", +] + [[package]] name = "windows-sys" version = "0.48.0" @@ -13392,6 +13777,21 @@ dependencies = [ "windows-link", ] +[[package]] +name = "windows-targets" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" +dependencies = [ + "windows_aarch64_gnullvm 0.42.2", + "windows_aarch64_msvc 0.42.2", + "windows_i686_gnu 0.42.2", + "windows_i686_msvc 0.42.2", + "windows_x86_64_gnu 0.42.2", + "windows_x86_64_gnullvm 0.42.2", + "windows_x86_64_msvc 0.42.2", +] + [[package]] name = "windows-targets" version = "0.48.5" @@ -13440,6 +13840,21 @@ dependencies = [ "windows_x86_64_msvc 0.53.1", ] +[[package]] +name = "windows-threading" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3949bd5b99cafdf1c7ca86b43ca564028dfe27d66958f2470940f73d86d75b37" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" + [[package]] name = "windows_aarch64_gnullvm" version = "0.48.5" @@ -13458,6 +13873,12 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" +[[package]] +name = "windows_aarch64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" + [[package]] name = "windows_aarch64_msvc" version = "0.48.5" @@ -13476,6 +13897,12 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" +[[package]] +name = "windows_i686_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" + [[package]] name = "windows_i686_gnu" version = "0.48.5" @@ -13506,6 +13933,12 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" +[[package]] +name = "windows_i686_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" + [[package]] name = "windows_i686_msvc" version = "0.48.5" @@ -13524,6 +13957,12 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" +[[package]] +name = "windows_x86_64_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" + [[package]] name = "windows_x86_64_gnu" version = "0.48.5" @@ -13542,6 +13981,12 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" + [[package]] name = "windows_x86_64_gnullvm" version = "0.48.5" @@ -13560,6 +14005,12 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" +[[package]] +name = "windows_x86_64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" + [[package]] name = "windows_x86_64_msvc" version = "0.48.5" @@ -13580,9 +14031,18 @@ checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" [[package]] name = "winnow" -version = "0.7.14" +version = "0.7.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a5364e9d77fcdeeaa6062ced926ee3381faa2ee02d3eb83a5c27a8825540829" +checksum = "df79d97927682d2fd8adb29682d1140b343be4ac0f08fd68b7765d9c059d3945" +dependencies = [ + "memchr", +] + +[[package]] +name = "winnow" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a90e88e4667264a994d34e6d1ab2d26d398dcdca8b7f52bec8668957517fc7d8" dependencies = [ "memchr", ] @@ -13602,6 +14062,88 @@ name = "wit-bindgen" version = "0.51.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5" +dependencies = [ + "wit-bindgen-rust-macro", +] + +[[package]] +name = "wit-bindgen-core" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea61de684c3ea68cb082b7a88508a8b27fcc8b797d738bfc99a82facf1d752dc" +dependencies = [ + "anyhow", + "heck 0.5.0", + "wit-parser", +] + +[[package]] +name = "wit-bindgen-rust" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21" +dependencies = [ + "anyhow", + "heck 0.5.0", + "indexmap 2.13.0", + "prettyplease 0.2.37", + "syn 2.0.117", + "wasm-metadata", + "wit-bindgen-core", + "wit-component", +] + +[[package]] +name = "wit-bindgen-rust-macro" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c0f9bfd77e6a48eccf51359e3ae77140a7f50b1e2ebfe62422d8afdaffab17a" +dependencies = [ + "anyhow", + "prettyplease 0.2.37", + "proc-macro2", + "quote", + "syn 2.0.117", + "wit-bindgen-core", + "wit-bindgen-rust", +] + +[[package]] +name = "wit-component" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2" +dependencies = [ + "anyhow", + "bitflags 2.11.0", + "indexmap 2.13.0", + "log", + "serde", + "serde_derive", + "serde_json", + "wasm-encoder", + "wasm-metadata", + "wasmparser", + "wit-parser", +] + +[[package]] +name = "wit-parser" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736" +dependencies = [ + "anyhow", + "id-arena", + "indexmap 2.13.0", + "log", + "semver 1.0.27", + "serde", + "serde_derive", + "serde_json", + "unicode-xid", + "wasmparser", +] [[package]] name = "writeable" @@ -13698,9 +14240,9 @@ dependencies = [ [[package]] name = "yamux" -version = "0.13.8" +version = "0.13.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "deab71f2e20691b4728b349c6cee8fc7223880fa67b6b4f92225ec32225447e5" +checksum = "1991f6690292030e31b0144d73f5e8368936c58e45e7068254f7138b23b00672" dependencies = [ "futures", "log", @@ -13746,28 +14288,28 @@ checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", "synstructure", ] [[package]] name = "zerocopy" -version = "0.8.36" +version = "0.8.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dafd85c832c1b68bbb4ec0c72c7f6f4fc5179627d2bc7c26b30e4c0cc11e76cc" +checksum = "efbb2a062be311f2ba113ce66f697a4dc589f85e78a4aea276200804cea0ed87" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.8.36" +version = "0.8.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cb7e4e8436d9db52fbd6625dbf2f45243ab84994a72882ec8227b99e72b439a" +checksum = "0e8bc7269b54418e7aeeef514aa68f8690b8c0489a06b0136e5f57c4c5ccab89" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -13787,7 +14329,7 @@ checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", "synstructure", ] @@ -13808,7 +14350,7 @@ checksum = "85a5b4158499876c763cb03bc4e49185d3cccbabb15b33c627f7884f43db852e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -13841,7 +14383,7 @@ checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -13935,7 +14477,7 @@ dependencies = [ "thiserror 1.0.69", "tiny-keccak", "tracing", - "tracing-subscriber 0.3.22", + "tracing-subscriber 0.3.23", "typenum", "vec_map", "zkm-curves", @@ -13986,7 +14528,7 @@ dependencies = [ "tiny-keccak", "tracing", "tracing-forest", - "tracing-subscriber 0.3.22", + "tracing-subscriber 0.3.23", "typenum", "web-time", "zkm-core-executor", @@ -14119,7 +14661,7 @@ dependencies = [ "serde_json", "thiserror 1.0.69", "tracing", - "tracing-subscriber 0.3.22", + "tracing-subscriber 0.3.23", "zkm-core-executor", "zkm-core-machine", "zkm-primitives", @@ -14260,7 +14802,7 @@ version = "1.2.5" source = "git+https://github.com/blake-pro/Ziren.git?branch=pre-release-v1.2.5#a7446e7ef377c12fb2a42e6082f234ae0949536a" dependencies = [ "alloy-primitives", - "alloy-signer 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)", + "alloy-signer 1.6.3", "anyhow", "async-trait", "bincode", @@ -14290,7 +14832,7 @@ dependencies = [ "tonic-build", "tracing", "twirp-rs", - "uuid 1.20.0", + "uuid 1.22.0", "vergen", "zkm-build", "zkm-core-executor", @@ -14337,7 +14879,7 @@ dependencies = [ "sysinfo", "tracing", "tracing-forest", - "tracing-subscriber 0.3.22", + "tracing-subscriber 0.3.23", "zkm-derive", "zkm-primitives", "zkm-zkvm", @@ -14407,9 +14949,9 @@ dependencies = [ [[package]] name = "zmij" -version = "1.0.17" +version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02aae0f83f69aafc94776e879363e9771d7ecbffe2c7fbb6c14c5e00dfe88439" +checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" [[package]] name = "zstd" diff --git a/Cargo.toml b/Cargo.toml index 545ca09f..0e14cd09 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -188,3 +188,10 @@ zkm-sdk = { git = "https://github.com/blake-pro/Ziren.git", branch = "pre-releas zkm-verifier = { git = "https://github.com/blake-pro/Ziren.git", branch = "pre-release-v1.2.5" } zkm-primitives = { git = "https://github.com/blake-pro/Ziren.git", branch = "pre-release-v1.2.5" } zkm-zkvm = { git = "https://github.com/blake-pro/Ziren.git", branch = "pre-release-v1.2.5" } +#zkm-build = { path = "../zkm2/crates/build" } +#zkm-core-executor = { path = "../zkm2/crates/core/executor" } +#zkm-prover = { path = "../zkm2/crates/prover" } +#zkm-sdk = { path = "../zkm2/crates/sdk" } +#zkm-verifier = { path = "../zkm2/crates/verifier" } +#zkm-primitives = { path = "../zkm2/crates/primitives" } +#zkm-zkvm = { path = "../zkm2/crates/zkvm/entrypoint" } \ No newline at end of file diff --git a/circuits/commit-chain-proof/guest/Cargo.toml b/circuits/commit-chain-proof/guest/Cargo.toml index cbacee2d..9dd816c1 100644 --- a/circuits/commit-chain-proof/guest/Cargo.toml +++ b/circuits/commit-chain-proof/guest/Cargo.toml @@ -12,7 +12,7 @@ commit-chain = { path = "../../../crates/commit-chain" } # Ziren zkm-zkvm = { git = "https://github.com/ProjectZKM/Ziren", package = "zkm-zkvm", features = ["verify"] } -#zkm-verifier = { git = "https://github.com/ProjectZKM/Ziren", package = "zkm-verifier" } +zkm-verifier = { git = "https://github.com/ProjectZKM/Ziren", package = "zkm-verifier" } #zkm-verifier = { path = "../../../../Ziren/crates/verifier" } #zkm-zkvm = { path = "../../../../Ziren/crates/zkvm/entrypoint", features = ["verify"] } diff --git a/crates/client/src/goat_chain/goat_adaptor.rs b/crates/client/src/goat_chain/goat_adaptor.rs index 354aba8c..babad5f0 100644 --- a/crates/client/src/goat_chain/goat_adaptor.rs +++ b/crates/client/src/goat_chain/goat_adaptor.rs @@ -16,6 +16,7 @@ use alloy::providers::ext::DebugApi; use alloy::providers::fillers::{FillProvider, JoinFill, RecommendedFillers}; use alloy::rpc::types::TransactionReceipt; use alloy::rpc::types::trace::geth::{CallConfig, GethDebugTracingOptions, GethTrace}; +use alloy::transports::http::reqwest::Client as AlloyReqwestClient; use alloy::{ network::{Ethereum, EthereumWallet, NetworkWallet, eip2718::Encodable2718}, primitives::{Address, B256, Bytes, ChainId, FixedBytes, TxHash, U256, keccak256}, @@ -37,16 +38,16 @@ const EIP1559_MAX_BASE_FEE_WEI: u128 = 2_000_000_000; const EIP1559_BASE_FEE_MULTIPLIER_NUM: u128 = 125; const EIP1559_BASE_FEE_MULTIPLIER_DEN: u128 = 100; -fn build_goat_rpc_client() -> reqwest::Client { +fn build_goat_rpc_client() -> AlloyReqwestClient { let timeout = Duration::from_secs(get_goat_rpc_timeout_secs()); - match reqwest::Client::builder().timeout(timeout).build() { + match AlloyReqwestClient::builder().timeout(timeout).build() { Ok(client) => client, Err(err) => { tracing::warn!( timeout_secs = timeout.as_secs(), "failed to build GOAT RPC reqwest client with timeout: {err}, fallback to default client" ); - reqwest::Client::new() + AlloyReqwestClient::new() } } } From 4ee10c19526d3a01f456420cb74cc5ce70d379ba Mon Sep 17 00:00:00 2001 From: Blake Date: Mon, 30 Mar 2026 01:45:58 +0800 Subject: [PATCH 07/14] feat: enhance part_stark_vk handling with attestation and versioning improvements --- circuits/commit-chain-proof/guest/src/main.rs | 2 +- circuits/header-chain-proof/guest/src/main.rs | 6 +- circuits/operator-proof/host/src/lib.rs | 2 +- circuits/proof-builder/src/lib.rs | 43 +++ circuits/watchtower-proof/host/src/lib.rs | 16 +- circuits/watchtower-proof/host/src/main.rs | 1 + .../src/attestation.rs | 274 +++++++++++++++--- .../bitcoin-light-client-circuit/src/lib.rs | 228 +++++++++++---- crates/bitvm2-ga/src/tests.rs | 6 +- node/src/bin/part_stark_vk_attest.rs | 61 +++- node/src/utils.rs | 6 +- proof-builder-rpc/src/api/proof_handler.rs | 18 ++ proof-builder-rpc/src/task/mod.rs | 27 ++ .../src/task/watchtower_proof.rs | 2 + 14 files changed, 586 insertions(+), 106 deletions(-) diff --git a/circuits/commit-chain-proof/guest/src/main.rs b/circuits/commit-chain-proof/guest/src/main.rs index c26ed23f..e994e13c 100644 --- a/circuits/commit-chain-proof/guest/src/main.rs +++ b/circuits/commit-chain-proof/guest/src/main.rs @@ -1,6 +1,6 @@ #![no_main] zkm_zkvm::entrypoint!(main); -use commit_chain::{CommitChainCircuitInput, commit_chain_circuit}; +use commit_chain::commit_chain_circuit; pub fn main() { let input = zkm_zkvm::io::read(); diff --git a/circuits/header-chain-proof/guest/src/main.rs b/circuits/header-chain-proof/guest/src/main.rs index 462d0195..a1b3b59f 100644 --- a/circuits/header-chain-proof/guest/src/main.rs +++ b/circuits/header-chain-proof/guest/src/main.rs @@ -1,11 +1,7 @@ #![no_main] zkm_zkvm::entrypoint!(main); -use header_chain::{ - verify_merkle_proof, BlockHeaderCircuitOutput, BlockInclusionProof, ChainState, - CircuitTransaction, HeaderChainCircuitInput, HeaderChainPrevProofType, - header_chain_circuit, -}; +use header_chain::{header_chain_circuit, HeaderChainCircuitInput}; use borsh::{BorshDeserialize, BorshSerialize}; diff --git a/circuits/operator-proof/host/src/lib.rs b/circuits/operator-proof/host/src/lib.rs index 480496fa..8f53fb5b 100644 --- a/circuits/operator-proof/host/src/lib.rs +++ b/circuits/operator-proof/host/src/lib.rs @@ -258,7 +258,7 @@ fn extract_watchtower_part_stark_vk(tx: &Transaction) -> Option> { catch_unwind(AssertUnwindSafe(|| extract_data_from_commitment_outputs(&tx.output))).ok()?; let (_, _, public_values, _, _) = parse_watchtower_commitment(&commitment).ok()?; let outputs = parse_watchtower_public_outputs(&public_values).ok()?; - Some(outputs.part_stark_vk) + Some(outputs.attested_part_stark_vk) } impl ProofBuilder for OperatorProofBuilder { diff --git a/circuits/proof-builder/src/lib.rs b/circuits/proof-builder/src/lib.rs index f11b106d..5a96f776 100644 --- a/circuits/proof-builder/src/lib.rs +++ b/circuits/proof-builder/src/lib.rs @@ -42,6 +42,7 @@ pub enum ProofRequest { header_chain_input_proof: String, commit_chain_input_proof: String, state_chain_input_proof: String, + attested_zkm_version: String, output: String, target_block: Block, block_pos: u32, @@ -112,6 +113,7 @@ pub struct OnDemandTask { pub header_chain_input_proof: String, pub commit_chain_input_proof: String, pub state_chain_input_proof: String, + pub attested_zkm_version: String, pub watchtower_challenge_init_txid: Option, pub watchtower_challenge_txids: Vec, @@ -206,6 +208,7 @@ pub struct ProofData { pub vk: String, pub public_inputs: Vec, pub zkm_version: String, + pub proof_part_stark_vk: Vec, } impl ProofData { @@ -227,6 +230,8 @@ impl ProofData { fs::read(format!("{path}.zkm_version.bin")).unwrap_or_default(), ) .unwrap_or_default(); + proof_data.proof_part_stark_vk = + fs::read(format!("{path}.proof_part_stark_vk.bin")).unwrap_or_default(); } } proof_data @@ -246,6 +251,7 @@ pub struct WatchtowerProofRequest { pub public_key: String, pub challenge_init_txid: String, pub execution_layer_block_number: i64, + pub attested_zkm_version: String, } #[derive(Debug, Serialize, Deserialize)] @@ -282,3 +288,40 @@ pub struct WatchtowerProofTimeoutUpdateResponse { pub data: Option, pub error: Option, } + +#[cfg(test)] +mod tests { + use super::*; + use std::path::PathBuf; + use std::time::{SystemTime, UNIX_EPOCH}; + + fn temp_proof_base() -> PathBuf { + let nanos = SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_nanos(); + std::env::temp_dir().join(format!("proof-data-test-{nanos}")) + } + + #[test] + fn load_proof_data_reads_proof_part_stark_vk_sidecar() { + let base = temp_proof_base(); + let base_str = base.to_string_lossy().to_string(); + fs::write(&base, [1u8, 2, 3]).unwrap(); + fs::write(format!("{base_str}.public_inputs.bin"), [4u8, 5, 6]).unwrap(); + fs::write(format!("{base_str}.vk_hash.bin"), b"vk-hash").unwrap(); + fs::write(format!("{base_str}.zkm_version.bin"), b"v1.2.5").unwrap(); + fs::write(format!("{base_str}.proof_part_stark_vk.bin"), [9u8, 8, 7]).unwrap(); + + let proof_data = ProofData::load_proof_data(&base_str, ProofType::Watchtower); + + assert_eq!(proof_data.proof, vec![1u8, 2, 3]); + assert_eq!(proof_data.public_inputs, vec![4u8, 5, 6]); + assert_eq!(proof_data.vk, "vk-hash"); + assert_eq!(proof_data.zkm_version, "v1.2.5"); + assert_eq!(proof_data.proof_part_stark_vk, vec![9u8, 8, 7]); + + let _ = fs::remove_file(&base); + let _ = fs::remove_file(format!("{base_str}.public_inputs.bin")); + let _ = fs::remove_file(format!("{base_str}.vk_hash.bin")); + let _ = fs::remove_file(format!("{base_str}.zkm_version.bin")); + let _ = fs::remove_file(format!("{base_str}.proof_part_stark_vk.bin")); + } +} diff --git a/circuits/watchtower-proof/host/src/lib.rs b/circuits/watchtower-proof/host/src/lib.rs index 6af16ebf..03fb2f3c 100644 --- a/circuits/watchtower-proof/host/src/lib.rs +++ b/circuits/watchtower-proof/host/src/lib.rs @@ -59,6 +59,10 @@ pub struct Args { #[clap(long, env, short)] pub state_chain_input_proof: String, + #[clap(long, env, default_value = "")] + #[serde(default)] + pub attested_zkm_version: String, + #[clap(long, env)] pub output: String, } @@ -111,7 +115,7 @@ fn load_proof_public_output(proof_path: &str) -> anyhow::Re deserialize(&public_inputs).context("Failed to decode proof public outputs") } -fn load_current_part_stark_vk(zkm_version: &str) -> anyhow::Result> { +fn load_part_stark_vk(zkm_version: &str) -> anyhow::Result> { catch_unwind(AssertUnwindSafe(|| Groth16Verifier::get_part_stark_vk(zkm_version).to_vec())) .map_err(|_| anyhow::anyhow!("Failed to load part_stark_vk for zkm_version {zkm_version}")) } @@ -142,6 +146,7 @@ impl ProofBuilder for WatchtowerProofBuilder { header_chain_input_proof, commit_chain_input_proof, state_chain_input_proof, + attested_zkm_version, latest_sequencer_commit_txid, genesis_sequencer_commit_txid, target_block, @@ -222,13 +227,16 @@ impl ProofBuilder for WatchtowerProofBuilder { load_proof_public_output(commit_chain_input_proof)?; let state_chain_output: StateChainCircuitOutput = load_proof_public_output(state_chain_input_proof)?; - let current_part_stark_vk = load_current_part_stark_vk(&self.client.version())?; + if attested_zkm_version.is_empty() { + anyhow::bail!("attested_zkm_version is required for watchtower proof generation"); + } + let attested_part_stark_vk = load_part_stark_vk(attested_zkm_version)?; let attestation_dir = part_stark_vk_attestation_dir(); let requested_part_stark_vks = vec![ header_chain_output.part_stark_vk, commit_chain_output.part_stark_vk, state_chain_output.part_stark_vk, - current_part_stark_vk, + attested_part_stark_vk, ]; let (unique_witnesses, witness_refs) = load_unique_part_stark_vk_witnesses(&attestation_dir, &requested_part_stark_vks) @@ -320,9 +328,11 @@ impl ProofBuilder for WatchtowerProofBuilder { let public_value_hex = hex::encode(proof.public_values.to_vec()); let proof_size = proof.bytes().len(); let zkm_version = proof.zkm_version.clone(); + let proof_part_stark_vk = load_part_stark_vk(&zkm_version)?; std::fs::write(&format!("{}.public_inputs.bin", output), proof.public_values.to_vec())?; std::fs::write(&format!("{}.vk_hash.bin", output), self.verifying_key.bytes32())?; std::fs::write(&format!("{}.zkm_version.bin", output), zkm_version)?; + std::fs::write(&format!("{}.proof_part_stark_vk.bin", output), proof_part_stark_vk)?; Ok((public_value_hex, proof_size)) } } diff --git a/circuits/watchtower-proof/host/src/main.rs b/circuits/watchtower-proof/host/src/main.rs index d5d2a818..ad0522fb 100644 --- a/circuits/watchtower-proof/host/src/main.rs +++ b/circuits/watchtower-proof/host/src/main.rs @@ -25,6 +25,7 @@ async fn main() { header_chain_input_proof: args.header_chain_input_proof.clone(), commit_chain_input_proof: args.commit_chain_input_proof.clone(), state_chain_input_proof: args.state_chain_input_proof.clone(), + attested_zkm_version: args.attested_zkm_version.clone(), output: args.output.clone(), target_block, block_pos, diff --git a/crates/bitcoin-light-client-circuit/src/attestation.rs b/crates/bitcoin-light-client-circuit/src/attestation.rs index 97adbf65..9fed7641 100644 --- a/crates/bitcoin-light-client-circuit/src/attestation.rs +++ b/crates/bitcoin-light-client-circuit/src/attestation.rs @@ -1,12 +1,13 @@ -use bitcoin::hashes::{Hash, sha256}; -use bitcoin::secp256k1::{Message, PublicKey, Secp256k1, SecretKey, ecdsa::Signature}; +use bitcoin::hashes::{sha256, Hash}; +use bitcoin::secp256k1::{ecdsa::Signature, Message, PublicKey, Secp256k1, SecretKey}; use serde::{Deserialize, Serialize}; use std::collections::{BTreeMap, BTreeSet}; use std::path::{Path, PathBuf}; pub const PART_STARK_VK_TREE_HEIGHT: usize = 6; pub const PART_STARK_VK_TREE_LEAFS: usize = 1 << PART_STARK_VK_TREE_HEIGHT; -pub const PART_STARK_VK_ROOT_SIGNATURE_DOMAIN: &[u8] = b"bitvm2:part_stark_vk_root:v1"; +pub const PART_STARK_VK_ROOT_SIGNATURE_DOMAIN: &[u8] = b"bitvm2:part_stark_vk_root:v2"; +pub const PART_STARK_VK_PUBLISHER_SET_DOMAIN: &[u8] = b"bitvm2:publisher_set:v1"; pub const PART_STARK_VK_ATTESTATION_DIR_ENV: &str = "PART_STARK_VK_ATTESTATION_DIR"; pub const DEFAULT_PART_STARK_VK_ATTESTATION_DIR: &str = "./part-stark-vk-attestations"; @@ -22,6 +23,8 @@ pub struct PartStarkVkAttestationBundle { pub leaf_index: usize, pub merkle_path: Vec<[u8; 32]>, pub root: [u8; 32], + pub threshold: u16, + pub publisher_set_id: [u8; 32], pub signatures: Vec, } @@ -58,16 +61,27 @@ pub struct PartStarkVkTreeState { pub leaves: Vec>, } -pub fn required_part_stark_vk_root_signers(total_publishers: usize) -> usize { - (total_publishers * 2).div_ceil(3) -} - pub fn part_stark_vk_attestation_dir() -> PathBuf { std::env::var(PART_STARK_VK_ATTESTATION_DIR_ENV) .map(PathBuf::from) .unwrap_or_else(|_| PathBuf::from(DEFAULT_PART_STARK_VK_ATTESTATION_DIR)) } +/// Hash the ordered publisher set together with the active threshold. +pub fn compute_publisher_set_id(publisher_public_keys: &[PublicKey], threshold: u16) -> [u8; 32] { + let mut bytes = Vec::with_capacity( + PART_STARK_VK_PUBLISHER_SET_DOMAIN.len() + 1 + 2 + 4 + publisher_public_keys.len() * 33, + ); + bytes.extend_from_slice(PART_STARK_VK_PUBLISHER_SET_DOMAIN); + bytes.push(0x00); + bytes.extend_from_slice(&threshold.to_le_bytes()); + bytes.extend_from_slice(&(publisher_public_keys.len() as u32).to_le_bytes()); + for pubkey in publisher_public_keys { + bytes.extend_from_slice(&pubkey.serialize()); + } + sha256::Hash::hash(&bytes).to_byte_array() +} + pub fn part_stark_vk_leaf_hash(part_stark_vk: &[u8]) -> [u8; 32] { let mut bytes = Vec::with_capacity(1 + 4 + part_stark_vk.len()); bytes.push(0x00); @@ -195,12 +209,21 @@ pub fn verify_part_stark_vk_merkle_path( Ok(()) } -pub fn build_attestation_message_digest(tree_height: usize, root: [u8; 32]) -> [u8; 32] { - let mut bytes = Vec::with_capacity(PART_STARK_VK_ROOT_SIGNATURE_DOMAIN.len() + 1 + 1 + 1 + 32); +/// Domain-separate the attestation root by tree height, threshold and publisher set identity. +pub fn build_attestation_message_digest( + tree_height: usize, + root: [u8; 32], + threshold: u16, + publisher_set_id: [u8; 32], +) -> [u8; 32] { + let mut bytes = + Vec::with_capacity(PART_STARK_VK_ROOT_SIGNATURE_DOMAIN.len() + 1 + 1 + 1 + 2 + 32 + 32); bytes.extend_from_slice(PART_STARK_VK_ROOT_SIGNATURE_DOMAIN); bytes.push(0x00); bytes.push(tree_height as u8); bytes.push(0x00); + bytes.extend_from_slice(&threshold.to_le_bytes()); + bytes.extend_from_slice(&publisher_set_id); bytes.extend_from_slice(&root); sha256::Hash::hash(&bytes).to_byte_array() } @@ -208,15 +231,31 @@ pub fn build_attestation_message_digest(tree_height: usize, root: [u8; 32]) -> [ fn verify_part_stark_vk_root_signatures( signatures: &[PartStarkVkRootSignature], publisher_public_keys: &[PublicKey], + threshold: u16, tree_height: usize, root: [u8; 32], + publisher_set_id: [u8; 32], ) -> Result<(), String> { if publisher_public_keys.is_empty() { return Err("publisher_public_keys is empty".to_string()); } - - let required = required_part_stark_vk_root_signers(publisher_public_keys.len()); - let message = Message::from_digest(build_attestation_message_digest(tree_height, root)); + let required = usize::from(threshold); + if required == 0 { + return Err("threshold must be greater than 0".to_string()); + } + if required > publisher_public_keys.len() { + return Err(format!( + "threshold {} exceeds publisher_public_keys length {}", + required, + publisher_public_keys.len() + )); + } + let message = Message::from_digest(build_attestation_message_digest( + tree_height, + root, + threshold, + publisher_set_id, + )); let secp = Secp256k1::verification_only(); let mut seen = std::collections::BTreeSet::new(); let mut valid = 0usize; @@ -264,8 +303,19 @@ fn verify_part_stark_vk_root_signatures( pub fn verify_part_stark_vk_attestation( bundle: &PartStarkVkAttestationBundle, publisher_public_keys: &[PublicKey], + threshold: u16, tree_height: usize, ) -> Result<(), String> { + if bundle.threshold != threshold { + return Err(format!( + "attestation threshold mismatch: bundle {}, expected {}", + bundle.threshold, threshold + )); + } + let expected_publisher_set_id = compute_publisher_set_id(publisher_public_keys, threshold); + if bundle.publisher_set_id != expected_publisher_set_id { + return Err("attestation publisher_set_id mismatch".to_string()); + } verify_part_stark_vk_merkle_path( &bundle.part_stark_vk, bundle.leaf_index, @@ -276,9 +326,12 @@ pub fn verify_part_stark_vk_attestation( verify_part_stark_vk_root_signatures( &bundle.signatures, publisher_public_keys, + threshold, tree_height, bundle.root, + bundle.publisher_set_id, )?; + Ok(()) } @@ -287,6 +340,7 @@ pub fn verify_part_stark_vk_witness_ref( witness_index: usize, expected_part_stark_vk: &[u8], publisher_public_keys: &[PublicKey], + threshold: u16, tree_height: usize, ) -> Result<(), String> { let witness = unique_witnesses.get(witness_index).ok_or_else(|| { @@ -295,19 +349,20 @@ pub fn verify_part_stark_vk_witness_ref( if witness.part_stark_vk != expected_part_stark_vk { return Err("part_stark_vk witness payload mismatch".to_string()); } - verify_part_stark_vk_attestation(witness, publisher_public_keys, tree_height) + verify_part_stark_vk_attestation(witness, publisher_public_keys, threshold, tree_height) } pub fn verify_current_part_stark_vk_witness( unique_witnesses: &[UniquePartStarkVkWitness], witness_index: usize, publisher_public_keys: &[PublicKey], + threshold: u16, tree_height: usize, ) -> Result, String> { let witness = unique_witnesses.get(witness_index).ok_or_else(|| { format!("witness index {} out of range {}", witness_index, unique_witnesses.len()) })?; - verify_part_stark_vk_attestation(witness, publisher_public_keys, tree_height)?; + verify_part_stark_vk_attestation(witness, publisher_public_keys, threshold, tree_height)?; Ok(witness.part_stark_vk.clone()) } @@ -363,9 +418,16 @@ pub fn sign_part_stark_vk_root( secret_key: &SecretKey, tree_height: usize, root: [u8; 32], + threshold: u16, + publisher_set_id: [u8; 32], ) -> Vec { let secp = Secp256k1::new(); - let message = Message::from_digest(build_attestation_message_digest(tree_height, root)); + let message = Message::from_digest(build_attestation_message_digest( + tree_height, + root, + threshold, + publisher_set_id, + )); let signature = secp.sign_ecdsa(&message, secret_key); signature.serialize_compact().to_vec() } @@ -374,6 +436,8 @@ pub fn build_part_stark_vk_root_signatures( signer_secret_keys: &[(usize, &SecretKey)], tree_height: usize, root: [u8; 32], + threshold: u16, + publisher_set_id: [u8; 32], ) -> Result, String> { if signer_secret_keys.is_empty() { return Err("publisher_secret_keys is empty".to_string()); @@ -390,7 +454,13 @@ pub fn build_part_stark_vk_root_signatures( } signatures.push(PartStarkVkRootSignature { signer_pubkey_index: *signer_pubkey_index, - signature: sign_part_stark_vk_root(secret_key, tree_height, root), + signature: sign_part_stark_vk_root( + secret_key, + tree_height, + root, + threshold, + publisher_set_id, + ), }); } @@ -401,6 +471,8 @@ pub fn build_part_stark_vk_attestation_bundle( leaves: &[Vec], tree_height: usize, leaf_index: usize, + threshold: u16, + publisher_set_id: [u8; 32], signatures: Vec, ) -> Result { let part_stark_vk = leaves @@ -412,6 +484,8 @@ pub fn build_part_stark_vk_attestation_bundle( leaf_index, merkle_path: build_part_stark_vk_merkle_path(leaves, tree_height, leaf_index)?, root: build_part_stark_vk_merkle_root(leaves, tree_height)?, + threshold, + publisher_set_id, signatures, }) } @@ -419,16 +493,26 @@ pub fn build_part_stark_vk_attestation_bundle( pub fn append_part_stark_vk_and_sign( dir: &Path, part_stark_vk: Vec, + publisher_public_keys: &[PublicKey], + threshold: u16, publisher_secret_keys: &[SecretKey], ) -> Result { let indexed_secret_keys = publisher_secret_keys.iter().enumerate().collect::>(); - append_part_stark_vk_and_sign_with_signers(dir, part_stark_vk, &indexed_secret_keys) + append_part_stark_vk_and_sign_with_signers( + dir, + part_stark_vk, + publisher_public_keys, + threshold, + &indexed_secret_keys, + ) } pub fn append_part_stark_vk_and_sign_with_signers( dir: &Path, part_stark_vk: Vec, + publisher_public_keys: &[PublicKey], + threshold: u16, publisher_secret_keys: &[(usize, &SecretKey)], ) -> Result { let mut state = if part_stark_vk_tree_state_path(dir).exists() { @@ -449,23 +533,38 @@ pub fn append_part_stark_vk_and_sign_with_signers( return Err("part_stark_vk already exists in tree".to_string()); } state.leaves.push(part_stark_vk.clone()); - let bundle = - resign_part_stark_vk_tree(dir, &state, publisher_secret_keys, state.leaves.len() - 1)?; + let bundle = resign_part_stark_vk_tree( + dir, + &state, + publisher_public_keys, + threshold, + publisher_secret_keys, + state.leaves.len() - 1, + )?; save_part_stark_vk_tree_state(dir, &state)?; Ok(bundle) } pub fn resign_current_part_stark_vk_root( dir: &Path, + publisher_public_keys: &[PublicKey], + threshold: u16, publisher_secret_keys: &[SecretKey], ) -> Result<(), String> { let indexed_secret_keys = publisher_secret_keys.iter().enumerate().collect::>(); - resign_current_part_stark_vk_root_with_signers(dir, &indexed_secret_keys) + resign_current_part_stark_vk_root_with_signers( + dir, + publisher_public_keys, + threshold, + &indexed_secret_keys, + ) } pub fn resign_current_part_stark_vk_root_with_signers( dir: &Path, + publisher_public_keys: &[PublicKey], + threshold: u16, publisher_secret_keys: &[(usize, &SecretKey)], ) -> Result<(), String> { let state = load_part_stark_vk_tree_state(dir)?; @@ -473,7 +572,14 @@ pub fn resign_current_part_stark_vk_root_with_signers( return Err("part_stark_vk tree is empty".to_string()); } for leaf_index in 0..state.leaves.len() { - let _ = resign_part_stark_vk_tree(dir, &state, publisher_secret_keys, leaf_index)?; + let _ = resign_part_stark_vk_tree( + dir, + &state, + publisher_public_keys, + threshold, + publisher_secret_keys, + leaf_index, + )?; } Ok(()) } @@ -481,16 +587,26 @@ pub fn resign_current_part_stark_vk_root_with_signers( fn resign_part_stark_vk_tree( dir: &Path, state: &PartStarkVkTreeState, + publisher_public_keys: &[PublicKey], + threshold: u16, publisher_secret_keys: &[(usize, &SecretKey)], leaf_index: usize, ) -> Result { let root = build_part_stark_vk_merkle_root(&state.leaves, state.tree_height)?; - let signatures = - build_part_stark_vk_root_signatures(publisher_secret_keys, state.tree_height, root)?; + let publisher_set_id = compute_publisher_set_id(publisher_public_keys, threshold); + let signatures = build_part_stark_vk_root_signatures( + publisher_secret_keys, + state.tree_height, + root, + threshold, + publisher_set_id, + )?; let bundle = build_part_stark_vk_attestation_bundle( &state.leaves, state.tree_height, leaf_index, + threshold, + publisher_set_id, signatures, )?; save_part_stark_vk_attestation_bundle(dir, &bundle)?; @@ -522,13 +638,13 @@ pub fn load_unique_part_stark_vk_witnesses( #[cfg(test)] mod tests { - use bitcoin::secp256k1::{Message, Secp256k1, SecretKey, ecdsa::Signature}; + use bitcoin::secp256k1::{ecdsa::Signature, Message, Secp256k1, SecretKey}; use super::{ - PartStarkVkAttestationBundle, PartStarkVkRootSignature, build_attestation_message_digest, - build_part_stark_vk_merkle_path, build_part_stark_vk_merkle_root, - build_part_stark_vk_root_signatures, part_stark_vk_leaf_hash, - verify_part_stark_vk_attestation, + build_attestation_message_digest, build_part_stark_vk_merkle_path, build_part_stark_vk_merkle_root, + build_part_stark_vk_root_signatures, compute_publisher_set_id, + part_stark_vk_leaf_hash, verify_part_stark_vk_attestation, PartStarkVkAttestationBundle, + PartStarkVkRootSignature, }; fn sample_part_stark_vk() -> Vec { @@ -556,15 +672,31 @@ mod tests { #[test] fn test_build_attestation_message_digest_matches_spec() { + let secp = Secp256k1::new(); + let secret_keys = [ + SecretKey::from_slice(&[1u8; 32]).unwrap(), + SecretKey::from_slice(&[2u8; 32]).unwrap(), + SecretKey::from_slice(&[3u8; 32]).unwrap(), + SecretKey::from_slice(&[4u8; 32]).unwrap(), + ]; + let publisher_public_keys = secret_keys + .iter() + .map(|sk| bitcoin::secp256k1::PublicKey::from_secret_key(&secp, sk)) + .collect::>(); let root = hex::decode("8a091f11cab951f0c1228a891c902475b84709e568885a45658840e1b88599d4") .unwrap() .try_into() .unwrap(); - - assert_eq!( - hex::encode(build_attestation_message_digest(6, root)), - "ab04ddc2489b88a48bd0a764fdcabedf2a7aa85a9efdfda5073ebf80b9fabd6a" + let threshold = 3u16; + let publisher_set_id = compute_publisher_set_id(&publisher_public_keys, threshold); + let mut reversed_public_keys = publisher_public_keys.clone(); + reversed_public_keys.reverse(); + + assert_ne!( + build_attestation_message_digest(6, root, threshold, publisher_set_id), + build_attestation_message_digest(6, root, threshold - 1, publisher_set_id) ); + assert_ne!(publisher_set_id, compute_publisher_set_id(&reversed_public_keys, threshold)); } #[test] @@ -584,7 +716,9 @@ mod tests { let part_stark_vk = sample_part_stark_vk(); let leaves = vec![part_stark_vk.clone()]; let root = build_part_stark_vk_merkle_root(&leaves, 6).unwrap(); - let digest = build_attestation_message_digest(6, root); + let threshold = 3u16; + let publisher_set_id = compute_publisher_set_id(&publisher_public_keys, threshold); + let digest = build_attestation_message_digest(6, root, threshold, publisher_set_id); let message = Message::from_digest(digest); let sig0 = secp.sign_ecdsa(&message, &secret_keys[0]); @@ -596,6 +730,8 @@ mod tests { leaf_index: 0, merkle_path: build_part_stark_vk_merkle_path(&leaves, 6, 0).unwrap(), root, + threshold, + publisher_set_id, signatures: vec![ PartStarkVkRootSignature { signer_pubkey_index: 0, @@ -616,7 +752,9 @@ mod tests { ], }; - assert!(verify_part_stark_vk_attestation(&bundle, &publisher_public_keys, 6).is_ok()); + assert!( + verify_part_stark_vk_attestation(&bundle, &publisher_public_keys, threshold, 6).is_ok() + ); } #[test] @@ -636,7 +774,9 @@ mod tests { let part_stark_vk = sample_part_stark_vk(); let leaves = vec![part_stark_vk.clone()]; let root = build_part_stark_vk_merkle_root(&leaves, 6).unwrap(); - let digest = build_attestation_message_digest(6, root); + let threshold = 2u16; + let publisher_set_id = compute_publisher_set_id(&publisher_public_keys, threshold); + let digest = build_attestation_message_digest(6, root, threshold, publisher_set_id); let message = Message::from_digest(digest); let outsider_sig: Signature = secp.sign_ecdsa(&message, &outsider); @@ -645,13 +785,18 @@ mod tests { leaf_index: 0, merkle_path: build_part_stark_vk_merkle_path(&leaves, 6, 0).unwrap(), root, + threshold, + publisher_set_id, signatures: vec![PartStarkVkRootSignature { signer_pubkey_index: 0, signature: outsider_sig.serialize_compact().to_vec(), }], }; - assert!(verify_part_stark_vk_attestation(&bundle, &publisher_public_keys, 6).is_err()); + assert!( + verify_part_stark_vk_attestation(&bundle, &publisher_public_keys, threshold, 6) + .is_err() + ); } #[test] @@ -671,6 +816,8 @@ mod tests { let leaves = vec![sample_part_stark_vk()]; let root = build_part_stark_vk_merkle_root(&leaves, 6).unwrap(); + let threshold = 4u16; + let publisher_set_id = compute_publisher_set_id(&publisher_public_keys, threshold); let signatures = build_part_stark_vk_root_signatures( &[ (0, &secret_keys[0]), @@ -680,6 +827,49 @@ mod tests { ], 6, root, + threshold, + publisher_set_id, + ) + .unwrap(); + + let bundle = PartStarkVkAttestationBundle { + part_stark_vk: leaves[0].clone(), + leaf_index: 0, + merkle_path: build_part_stark_vk_merkle_path(&leaves, 6, 0).unwrap(), + root, + threshold, + publisher_set_id, + signatures, + }; + + assert!( + verify_part_stark_vk_attestation(&bundle, &publisher_public_keys, threshold, 6).is_ok() + ); + } + + #[test] + fn test_verify_part_stark_vk_attestation_rejects_threshold_mismatch() { + let secp = Secp256k1::new(); + let secret_keys = [ + SecretKey::from_slice(&[1u8; 32]).unwrap(), + SecretKey::from_slice(&[2u8; 32]).unwrap(), + SecretKey::from_slice(&[3u8; 32]).unwrap(), + SecretKey::from_slice(&[4u8; 32]).unwrap(), + ]; + let publisher_public_keys = secret_keys + .iter() + .map(|sk| bitcoin::secp256k1::PublicKey::from_secret_key(&secp, sk)) + .collect::>(); + let leaves = vec![sample_part_stark_vk()]; + let root = build_part_stark_vk_merkle_root(&leaves, 6).unwrap(); + let signed_threshold = 3u16; + let publisher_set_id = compute_publisher_set_id(&publisher_public_keys, signed_threshold); + let signatures = build_part_stark_vk_root_signatures( + &[(0, &secret_keys[0]), (1, &secret_keys[1]), (2, &secret_keys[2])], + 6, + root, + signed_threshold, + publisher_set_id, ) .unwrap(); @@ -688,9 +878,19 @@ mod tests { leaf_index: 0, merkle_path: build_part_stark_vk_merkle_path(&leaves, 6, 0).unwrap(), root, + threshold: signed_threshold, + publisher_set_id, signatures, }; - assert!(verify_part_stark_vk_attestation(&bundle, &publisher_public_keys, 6).is_ok()); + assert!( + verify_part_stark_vk_attestation( + &bundle, + &publisher_public_keys, + signed_threshold - 1, + 6 + ) + .is_err() + ); } } diff --git a/crates/bitcoin-light-client-circuit/src/lib.rs b/crates/bitcoin-light-client-circuit/src/lib.rs index cf912a80..b19ae4dd 100644 --- a/crates/bitcoin-light-client-circuit/src/lib.rs +++ b/crates/bitcoin-light-client-circuit/src/lib.rs @@ -23,9 +23,7 @@ use state_chain::{StateChainCircuitInput, StateChainPrevProofType}; use std::panic::{AssertUnwindSafe, catch_unwind}; use zkm_primitives::io::ZKMPublicValues; use zkm_verifier::{Groth16Verifier, IMM_GROTH16_VK_BYTES}; -use zkm_version::{ - ZKM_VERSION_BYTES_LEN, ZkmVersionBytes, decode_zkm_version_fixed, encode_zkm_version_fixed, -}; +use zkm_version::{ZKM_VERSION_BYTES_LEN, ZkmVersionBytes, decode_zkm_version_fixed}; use bitcoin::{ScriptBuf, TxOut, Txid, secp256k1::PublicKey}; pub use guest_executor::io::EthClientExecutorInput; @@ -35,6 +33,7 @@ pub const GRAPH_ID_SIZE: usize = 16; pub const PROOF_SIZE: usize = 260; pub const PUBLIC_INPUTS_SIZE: usize = 36; pub const WATCHTOWER_COMMITMENT_PUBLIC_INPUTS_LEN_SIZE: usize = 4; +pub const WATCHTOWER_COMMITMENT_PROOF_PART_STARK_VK_LEN_SIZE: usize = 4; pub const VK_HASH_SIZE: usize = 66; pub const ZKM_VERSION_SIZE: usize = ZKM_VERSION_BYTES_LEN; @@ -45,7 +44,7 @@ pub const CONSENSUS_BLOCK_HEIGHT_SIZE: usize = 4; pub struct WatchtowerPublicOutputs { pub total_work: [u8; TOTAL_WORK_SIZE], pub consensus_block_height: [u8; CONSENSUS_BLOCK_HEIGHT_SIZE], - pub part_stark_vk: Vec, + pub attested_part_stark_vk: Vec, } #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] @@ -126,6 +125,7 @@ pub fn watch_longest_chain( attestation.header_ref, &btc_header_chain_output.part_stark_vk, &commit_chain_output.chain_state.publisher_public_keys, + commit_chain_output.chain_state.threshold, PART_STARK_VK_TREE_HEIGHT, ) .expect("Failed to verify header-chain part_stark_vk attestation"); @@ -134,6 +134,7 @@ pub fn watch_longest_chain( attestation.commit_ref, &commit_chain_output.part_stark_vk, &commit_chain_output.chain_state.publisher_public_keys, + commit_chain_output.chain_state.threshold, PART_STARK_VK_TREE_HEIGHT, ) .expect("Failed to verify commit-chain part_stark_vk attestation"); @@ -142,13 +143,15 @@ pub fn watch_longest_chain( attestation.state_ref, &state_chain_output.part_stark_vk, &commit_chain_output.chain_state.publisher_public_keys, + commit_chain_output.chain_state.threshold, PART_STARK_VK_TREE_HEIGHT, ) .expect("Failed to verify state-chain part_stark_vk attestation"); - let current_part_stark_vk = verify_current_part_stark_vk_witness( + let attested_part_stark_vk = verify_current_part_stark_vk_witness( &attestation.unique_witnesses, attestation.current_ref, &commit_chain_output.chain_state.publisher_public_keys, + commit_chain_output.chain_state.threshold, PART_STARK_VK_TREE_HEIGHT, ) .expect("Failed to verify watchtower part_stark_vk attestation"); @@ -178,7 +181,7 @@ pub fn watch_longest_chain( WatchtowerPublicOutputs { total_work: btc_header_chain_output.chain_state.total_work, consensus_block_height: commit_chain_output.chain_state.block_height.to_le_bytes(), - part_stark_vk: current_part_stark_vk, + attested_part_stark_vk, } } @@ -261,6 +264,7 @@ pub fn propose_longest_chain( attestation.header_ref, &btc_header_chain_output.part_stark_vk, &commit_chain_output.chain_state.publisher_public_keys, + commit_chain_output.chain_state.threshold, PART_STARK_VK_TREE_HEIGHT, ) .expect("Failed to verify header-chain part_stark_vk attestation"); @@ -269,6 +273,7 @@ pub fn propose_longest_chain( attestation.commit_ref, &commit_chain_output.part_stark_vk, &commit_chain_output.chain_state.publisher_public_keys, + commit_chain_output.chain_state.threshold, PART_STARK_VK_TREE_HEIGHT, ) .expect("Failed to verify commit-chain part_stark_vk attestation"); @@ -315,7 +320,7 @@ pub fn propose_longest_chain( let commitment = &extract_data_from_commitment_outputs(&tx.output)[..]; println!("commitment: {commitment:?}"); println!("commitment hex: {}", hex::encode(commitment)); - let (parsed_graph_id, proof, public_values, vk, watchtower_zkm_version) = + let (parsed_graph_id, proof, public_values, vk, proof_part_stark_vk) = match parse_watchtower_commitment(commitment) { Ok(c) => c, Err(err) => { @@ -324,14 +329,6 @@ pub fn propose_longest_chain( } }; - match verify_proof_fixed_version(&proof, &public_values, &vk, &watchtower_zkm_version) { - Ok(_) => {} - Err(err) => { - println!("Watchtower[{i}] invalid proof: {err}"); - continue; - } - } - if parsed_graph_id != graph_id { println!( "Watchtower[{i}] invalid commitment: graph id: parsed = {}, expected = {}", @@ -354,13 +351,22 @@ pub fn propose_longest_chain( .watchtower_refs .get(i) .expect("watchtower attestation refs length mismatch"), - &watchtower_outputs.part_stark_vk, + &watchtower_outputs.attested_part_stark_vk, &commit_chain_output.chain_state.publisher_public_keys, + commit_chain_output.chain_state.threshold, PART_STARK_VK_TREE_HEIGHT, ) { println!("Watchtower[{i}] invalid part_stark_vk attestation: {err}"); continue; } + match verify_proof_with_part_stark_vk(&proof, &public_values, &vk, &proof_part_stark_vk) + { + Ok(_) => {} + Err(err) => { + println!("Watchtower[{i}] invalid proof: {err}"); + continue; + } + } // extract ChainState // check watchtower_chain_state.total_work <= operator_header_chain.total_work @@ -408,6 +414,7 @@ pub fn propose_longest_chain( attestation.state_ref, &state_chain_output.part_stark_vk, &commit_chain_output.chain_state.publisher_public_keys, + commit_chain_output.chain_state.threshold, PART_STARK_VK_TREE_HEIGHT, ) .expect("Failed to verify state-chain part_stark_vk attestation"); @@ -415,6 +422,7 @@ pub fn propose_longest_chain( &attestation.unique_witnesses, attestation.current_ref, &commit_chain_output.chain_state.publisher_public_keys, + commit_chain_output.chain_state.threshold, PART_STARK_VK_TREE_HEIGHT, ) .expect("Failed to verify operator part_stark_vk attestation"); @@ -557,12 +565,24 @@ pub fn build_watchtower_commitment( proof: &[u8], public_inputs: &[u8], vk_hash: &str, - zkm_version: &str, + proof_part_stark_vk: &[u8], ) -> Result, String> { if proof.len() != PROOF_SIZE { return Err(format!("invalid proof length: {}, expected {}", proof.len(), PROOF_SIZE)); } - let mut comm = graph_id.to_vec(); + if proof_part_stark_vk.is_empty() { + return Err("proof_part_stark_vk must not be empty".to_string()); + } + let mut comm = Vec::with_capacity( + GRAPH_ID_SIZE + + PROOF_SIZE + + WATCHTOWER_COMMITMENT_PUBLIC_INPUTS_LEN_SIZE + + public_inputs.len() + + VK_HASH_SIZE + + WATCHTOWER_COMMITMENT_PROOF_PART_STARK_VK_LEN_SIZE + + proof_part_stark_vk.len(), + ); + comm.extend_from_slice(graph_id); comm.extend_from_slice(proof); comm.extend_from_slice(&(public_inputs.len() as u32).to_le_bytes()); comm.extend_from_slice(public_inputs); @@ -574,13 +594,13 @@ pub fn build_watchtower_commitment( )); } comm.extend_from_slice(vk_hash.as_bytes()); - let zkm_version = encode_zkm_version_fixed(zkm_version)?; - comm.extend_from_slice(&zkm_version); + comm.extend_from_slice(&(proof_part_stark_vk.len() as u32).to_le_bytes()); + comm.extend_from_slice(proof_part_stark_vk); Ok(comm) } pub type WatchtowerCommitmentResult = - ([u8; GRAPH_ID_SIZE], Vec, Vec, [u8; VK_HASH_SIZE], ZkmVersionBytes); + ([u8; GRAPH_ID_SIZE], Vec, Vec, [u8; VK_HASH_SIZE], Vec); pub fn parse_watchtower_commitment( commitment: &[u8], @@ -589,7 +609,7 @@ pub fn parse_watchtower_commitment( + PROOF_SIZE + WATCHTOWER_COMMITMENT_PUBLIC_INPUTS_LEN_SIZE + VK_HASH_SIZE - + ZKM_VERSION_SIZE; + + WATCHTOWER_COMMITMENT_PROOF_PART_STARK_VK_LEN_SIZE; if commitment.len() < min_commitment_size { return Err(format!( "invalid commitment size: {}, expected at least {}", @@ -599,7 +619,7 @@ pub fn parse_watchtower_commitment( } let mut end = GRAPH_ID_SIZE; let mut graph_id = [0u8; GRAPH_ID_SIZE]; - graph_id.copy_from_slice(&commitment[0..GRAPH_ID_SIZE]); + graph_id.copy_from_slice(&commitment[..end]); let proof = commitment[end..end + PROOF_SIZE].to_vec(); end += PROOF_SIZE; @@ -609,7 +629,22 @@ pub fn parse_watchtower_commitment( ) as usize; end += WATCHTOWER_COMMITMENT_PUBLIC_INPUTS_LEN_SIZE; - let expected_size = min_commitment_size + public_inputs_len; + let proof_part_stark_vk_len_offset = end + public_inputs_len + VK_HASH_SIZE; + if commitment.len() + < proof_part_stark_vk_len_offset + WATCHTOWER_COMMITMENT_PROOF_PART_STARK_VK_LEN_SIZE + { + return Err(format!( + "invalid commitment size: {}, missing proof_part_stark_vk length field", + commitment.len() + )); + } + let proof_part_stark_vk_len = u32::from_le_bytes( + commitment[proof_part_stark_vk_len_offset + ..proof_part_stark_vk_len_offset + WATCHTOWER_COMMITMENT_PROOF_PART_STARK_VK_LEN_SIZE] + .try_into() + .unwrap(), + ) as usize; + let expected_size = min_commitment_size + public_inputs_len + proof_part_stark_vk_len; if commitment.len() != expected_size { return Err(format!( "invalid commitment size: {}, expected {}", @@ -625,10 +660,17 @@ pub fn parse_watchtower_commitment( zkm_vk_hash_bytes.copy_from_slice(&commitment[end..end + VK_HASH_SIZE]); end += VK_HASH_SIZE; - let mut zkm_version = [0u8; ZKM_VERSION_SIZE]; - zkm_version.copy_from_slice(&commitment[end..end + ZKM_VERSION_SIZE]); - - Ok((graph_id, proof, zkm_public_values, zkm_vk_hash_bytes, zkm_version)) + let proof_part_stark_vk_len = u32::from_le_bytes( + commitment[end..end + WATCHTOWER_COMMITMENT_PROOF_PART_STARK_VK_LEN_SIZE] + .try_into() + .unwrap(), + ) as usize; + if proof_part_stark_vk_len == 0 { + return Err("proof_part_stark_vk must not be empty".to_string()); + } + end += WATCHTOWER_COMMITMENT_PROOF_PART_STARK_VK_LEN_SIZE; + let proof_part_stark_vk = commitment[end..end + proof_part_stark_vk_len].to_vec(); + Ok((graph_id, proof, zkm_public_values, zkm_vk_hash_bytes, proof_part_stark_vk)) } pub fn parse_watchtower_public_outputs( @@ -654,7 +696,18 @@ pub fn verify_proof( zkm_vk_hash: &[u8], zkm_version: &str, ) -> Result<(), String> { - let (groth16_vk, part_stark_vk) = groth16_verifier_keys(zkm_version)?; + let (_, part_stark_vk) = groth16_verifier_keys(zkm_version)?; + verify_proof_with_part_stark_vk(proof, zkm_public_values, zkm_vk_hash, part_stark_vk) +} + +/// Verify a Groth16 proof against an explicit part_stark_vk instead of a version lookup. +pub fn verify_proof_with_part_stark_vk( + proof: &[u8], + zkm_public_values: &[u8], + zkm_vk_hash: &[u8], + part_stark_vk: &[u8], +) -> Result<(), String> { + let groth16_vk = *IMM_GROTH16_VK_BYTES; let zkm_vk_hash = String::from_utf8(zkm_vk_hash.to_vec()).map_err(|e| e.to_string())?; match Groth16Verifier::verify_by_imm_groth16_vk( proof, @@ -682,6 +735,7 @@ pub fn verify_proof_fixed_version( mod tests { use super::*; use bitcoin::Transaction; + use zkm_version::encode_zkm_version_fixed; const PROOF: &[u8] = include_bytes!("../../../circuits/data/watchtower/output3.bin.proof.bin"); const PUBLIC_INPUTS: &[u8] = include_bytes!("../../../circuits/data/watchtower/output3.bin.public_inputs.bin"); @@ -709,18 +763,24 @@ mod tests { let total_work = 1006120u64; let block_height = 503043u32; - let part_stark_vk = vec![7u8; 44]; + let attested_part_stark_vk = vec![7u8; 44]; + let proof_part_stark_vk = vec![8u8; 52]; let expected_outputs = WatchtowerPublicOutputs { total_work: U256::from(total_work).to_be_bytes(), consensus_block_height: U32::from(block_height).to_le_bytes(), - part_stark_vk: part_stark_vk.clone(), + attested_part_stark_vk: attested_part_stark_vk.clone(), }; let public_inputs = bincode::serialize(&expected_outputs).unwrap(); println!("public inputs: {:?}", PUBLIC_INPUTS.len()); println!("vk hash: {:?}", VK_HASH.len()); - let comm = - build_watchtower_commitment(&graph_id, PROOF, &public_inputs, VK_HASH, ZKM_VERSION) - .unwrap(); + let comm = build_watchtower_commitment( + &graph_id, + PROOF, + &public_inputs, + VK_HASH, + &proof_part_stark_vk, + ) + .unwrap(); println!("comm: {:?}", comm.len()); println!("comm hex: {:?}", hex::encode(&comm)); @@ -731,7 +791,7 @@ mod tests { assert_eq!(expected.1, PROOF); assert_eq!(expected.2, public_inputs); assert_eq!(expected.3, VK_HASH.as_bytes()); - assert_eq!(expected.4, encode_zkm_version_fixed(ZKM_VERSION).unwrap()); + assert_eq!(expected.4, proof_part_stark_vk); let parsed_outputs = parse_watchtower_public_outputs(&expected.2).unwrap(); assert_eq!(parsed_outputs, expected_outputs); } @@ -777,28 +837,85 @@ mod tests { let commitment = extract_data_from_commitment_outputs(&tx.output); let parse_result = parse_watchtower_commitment(&commitment); - assert!(parse_result.is_err(), "legacy commitment without version should fail"); + assert!(parse_result.is_err(), "legacy commitment with trailing zkm_version should fail"); } #[test] - fn test_build_watchtower_commitment_rejects_long_version() { - let graph_id = hex::decode("00112233445566778899aabbccddeeff").unwrap().try_into().unwrap(); - let too_long_version = "v1234567890123456"; - assert_eq!(too_long_version.len(), ZKM_VERSION_SIZE + 1); - let result = - build_watchtower_commitment(&graph_id, PROOF, PUBLIC_INPUTS, VK_HASH, too_long_version); - assert!(result.is_err()); + fn test_parse_watchtower_commitment_rejects_legacy_v1_payload() { + let graph_id: [u8; GRAPH_ID_SIZE] = + hex::decode("00112233445566778899aabbccddeeff").unwrap().try_into().unwrap(); + let mut legacy = graph_id.to_vec(); + legacy.extend_from_slice(PROOF); + legacy.extend_from_slice(&(PUBLIC_INPUTS.len() as u32).to_le_bytes()); + legacy.extend_from_slice(PUBLIC_INPUTS); + legacy.extend_from_slice(VK_HASH.as_bytes()); + legacy.extend_from_slice(&encode_zkm_version_fixed(ZKM_VERSION).unwrap()); + assert!(parse_watchtower_commitment(&legacy).is_err()); } #[test] - fn test_build_watchtower_commitment_accepts_rc_version() { - let graph_id = hex::decode("00112233445566778899aabbccddeeff").unwrap().try_into().unwrap(); - let rc_version = "v1.12.15-rc1"; - let commitment = - build_watchtower_commitment(&graph_id, PROOF, PUBLIC_INPUTS, VK_HASH, rc_version) - .unwrap(); - let parsed = parse_watchtower_commitment(&commitment).unwrap(); - assert_eq!(decode_zkm_version_fixed(&parsed.4).unwrap(), rc_version); + fn test_parse_watchtower_commitment_rejects_missing_proof_part_stark_vk() { + let graph_id: [u8; GRAPH_ID_SIZE] = + hex::decode("00112233445566778899aabbccddeeff").unwrap().try_into().unwrap(); + let mut commitment = graph_id.to_vec(); + commitment.extend_from_slice(PROOF); + commitment.extend_from_slice(&(PUBLIC_INPUTS.len() as u32).to_le_bytes()); + commitment.extend_from_slice(PUBLIC_INPUTS); + commitment.extend_from_slice(VK_HASH.as_bytes()); + assert!(parse_watchtower_commitment(&commitment).is_err()); + } + + #[test] + fn test_parse_watchtower_commitment_accepts_versionless_dual_key_payload() { + let graph_id: [u8; GRAPH_ID_SIZE] = + hex::decode("00112233445566778899aabbccddeeff").unwrap().try_into().unwrap(); + let proof_part_stark_vk = vec![9u8; 48]; + let mut commitment = graph_id.to_vec(); + commitment.extend_from_slice(PROOF); + commitment.extend_from_slice(&(PUBLIC_INPUTS.len() as u32).to_le_bytes()); + commitment.extend_from_slice(PUBLIC_INPUTS); + commitment.extend_from_slice(VK_HASH.as_bytes()); + commitment.extend_from_slice(&(proof_part_stark_vk.len() as u32).to_le_bytes()); + commitment.extend_from_slice(&proof_part_stark_vk); + + assert!( + parse_watchtower_commitment(&commitment).is_ok(), + "versionless dual-key commitment should parse" + ); + } + + #[test] + fn test_parse_watchtower_commitment_rejects_empty_proof_part_stark_vk() { + let graph_id: [u8; GRAPH_ID_SIZE] = + hex::decode("00112233445566778899aabbccddeeff").unwrap().try_into().unwrap(); + let mut commitment = graph_id.to_vec(); + commitment.extend_from_slice(PROOF); + commitment.extend_from_slice(&(PUBLIC_INPUTS.len() as u32).to_le_bytes()); + commitment.extend_from_slice(PUBLIC_INPUTS); + commitment.extend_from_slice(VK_HASH.as_bytes()); + commitment.extend_from_slice(&0u32.to_le_bytes()); + + assert!(parse_watchtower_commitment(&commitment).is_err()); + } + + #[test] + fn test_parse_watchtower_commitment_rejects_versioned_payload() { + let graph_id: [u8; GRAPH_ID_SIZE] = + hex::decode("00112233445566778899aabbccddeeff").unwrap().try_into().unwrap(); + let proof_part_stark_vk = vec![3u8; 12]; + let mut versioned = vec![2u8]; + versioned.extend_from_slice(&graph_id); + versioned.extend_from_slice(PROOF); + versioned.extend_from_slice(&(PUBLIC_INPUTS.len() as u32).to_le_bytes()); + versioned.extend_from_slice(PUBLIC_INPUTS); + versioned.extend_from_slice(VK_HASH.as_bytes()); + versioned.extend_from_slice(&(proof_part_stark_vk.len() as u32).to_le_bytes()); + versioned.extend_from_slice(&proof_part_stark_vk); + + assert!( + parse_watchtower_commitment(&versioned).is_err(), + "versioned watchtower commitment should be rejected" + ); } #[test] @@ -812,7 +929,7 @@ mod tests { let expected = WatchtowerPublicOutputs { total_work: [9u8; TOTAL_WORK_SIZE], consensus_block_height: 123u32.to_le_bytes(), - part_stark_vk: vec![7u8; 44], + attested_part_stark_vk: vec![7u8; 44], }; let public_inputs = bincode::serialize(&expected).unwrap(); @@ -829,6 +946,13 @@ mod tests { assert!(!result.unwrap_err().contains("too long")); } + #[test] + fn test_verify_proof_with_part_stark_vk_uses_explicit_vk_bytes() { + let part_stark_vk = groth16_verifier_keys(ZKM_VERSION).unwrap().1.to_vec(); + let result = verify_proof_with_part_stark_vk(&[], &[], &[], &part_stark_vk); + assert!(result.is_err()); + } + #[test] fn test_groth16_verifier_keys_reject_unknown_version_without_panic() { let result = groth16_verifier_keys("v0.0.0-test"); diff --git a/crates/bitvm2-ga/src/tests.rs b/crates/bitvm2-ga/src/tests.rs index 88263ace..9aa9cb73 100644 --- a/crates/bitvm2-ga/src/tests.rs +++ b/crates/bitvm2-ga/src/tests.rs @@ -996,6 +996,10 @@ mod tests { include_bytes!("../../../circuits/data/watchtower/output3.bin.public_inputs.bin"); const VK_HASH: &str = include_str!("../../../circuits/data/watchtower/output3.bin.vk_hash.bin"); + let proof_part_stark_vk = + bitcoin_light_client_circuit::parse_watchtower_public_outputs(PUBLIC_INPUTS) + .unwrap() + .attested_part_stark_vk; let graph_id = hex::decode("00112233445566778899aabbccddeeff").unwrap().try_into().unwrap(); //graph.parameters.graph_id.to_bytes_le(); //let total_work = 1006120; @@ -1005,7 +1009,7 @@ mod tests { PROOF, PUBLIC_INPUTS, VK_HASH, - "v1.2.4", + &proof_part_stark_vk, ) .unwrap(); diff --git a/node/src/bin/part_stark_vk_attest.rs b/node/src/bin/part_stark_vk_attest.rs index fd39f79a..18982845 100644 --- a/node/src/bin/part_stark_vk_attest.rs +++ b/node/src/bin/part_stark_vk_attest.rs @@ -1,10 +1,11 @@ use anyhow::{Context, Result, anyhow, bail}; -use bitcoin::secp256k1::SecretKey; +use bitcoin::secp256k1::{PublicKey, SecretKey}; use bitcoin_light_client_circuit::{ append_part_stark_vk_and_sign_with_signers, part_stark_vk_attestation_dir, resign_current_part_stark_vk_root_with_signers, }; use clap::{Parser, Subcommand}; +use commit_chain::CommitInfo; use std::path::PathBuf; use std::str::FromStr; use zkm_verifier::Groth16Verifier; @@ -44,12 +45,16 @@ enum Command { part_stark_vk_file: Option, #[arg(long)] zkm_version: Option, + #[arg(long)] + commit_info_file: PathBuf, #[arg(long, value_delimiter = ',')] publisher_signers: Vec, #[arg(long)] attestation_dir: Option, }, ResignCurrentRoot { + #[arg(long)] + commit_info_file: PathBuf, #[arg(long, value_delimiter = ',')] publisher_signers: Vec, #[arg(long)] @@ -71,6 +76,37 @@ fn resolve_signers(publisher_signers: &[PublisherSignerArg]) -> Result Result<(Vec, u16)> { + let bytes = std::fs::read(commit_info_file).with_context(|| { + format!("failed to read commit_info file '{}'", commit_info_file.display()) + })?; + let commit_info: CommitInfo = serde_json::from_slice(&bytes).with_context(|| { + format!("failed to decode commit_info file '{}'", commit_info_file.display()) + })?; + if commit_info.publisher_public_keys.is_empty() { + bail!("commit_info publisher_public_keys is empty"); + } + if commit_info.threshold == 0 { + bail!("commit_info threshold must be greater than 0"); + } + let publisher_public_keys = commit_info + .publisher_public_keys + .iter() + .map(|compressed_pk| { + PublicKey::from_str(compressed_pk) + .with_context(|| format!("invalid publisher public key '{}'", compressed_pk)) + }) + .collect::>>()?; + if usize::from(commit_info.threshold) > publisher_public_keys.len() { + bail!( + "commit_info threshold {} exceeds publisher_public_keys length {}", + commit_info.threshold, + publisher_public_keys.len() + ); + } + Ok((publisher_public_keys, commit_info.threshold)) +} + fn load_part_stark_vk( part_stark_vk_file: Option, zkm_version: Option, @@ -89,23 +125,38 @@ fn main() -> Result<()> { let cli = Cli::parse(); match cli.command { - Command::Append { part_stark_vk_file, zkm_version, publisher_signers, attestation_dir } => { + Command::Append { + part_stark_vk_file, + zkm_version, + commit_info_file, + publisher_signers, + attestation_dir, + } => { let attestation_dir = resolve_attestation_dir(attestation_dir); let part_stark_vk = load_part_stark_vk(part_stark_vk_file, zkm_version)?; + let (publisher_public_keys, threshold) = load_publisher_set(&commit_info_file)?; let signer_refs = resolve_signers(&publisher_signers)?; let bundle = append_part_stark_vk_and_sign_with_signers( &attestation_dir, part_stark_vk, + &publisher_public_keys, + threshold, &signer_refs, ) .map_err(anyhow::Error::msg)?; println!("{}", serde_json::to_string_pretty(&bundle)?); } - Command::ResignCurrentRoot { publisher_signers, attestation_dir } => { + Command::ResignCurrentRoot { commit_info_file, publisher_signers, attestation_dir } => { let attestation_dir = resolve_attestation_dir(attestation_dir); + let (publisher_public_keys, threshold) = load_publisher_set(&commit_info_file)?; let signer_refs = resolve_signers(&publisher_signers)?; - resign_current_part_stark_vk_root_with_signers(&attestation_dir, &signer_refs) - .map_err(anyhow::Error::msg)?; + resign_current_part_stark_vk_root_with_signers( + &attestation_dir, + &publisher_public_keys, + threshold, + &signer_refs, + ) + .map_err(anyhow::Error::msg)?; println!("resigned part_stark_vk root attestations in {}", attestation_dir.display()); } } diff --git a/node/src/utils.rs b/node/src/utils.rs index 12b649d8..a989535c 100644 --- a/node/src/utils.rs +++ b/node/src/utils.rs @@ -1756,12 +1756,15 @@ fn gen_watchtower_commitment(graph_id: Uuid, proof_data: ProofData) -> Result( i64, i64, Option, + Option, Vec, Vec, Vec, @@ -224,6 +225,7 @@ async fn read_watchtower_challenge_details<'a>( let ( task_index, execution_layer_block_number, + attested_zkm_version, watchtower_challenge_init_txid, watchtower_challenge_txids, included_watchtowers, @@ -241,6 +243,7 @@ async fn read_watchtower_challenge_details<'a>( ( task.id, task.execution_layer_block_number, + task.extra.clone(), None, watchtower_challenge_txids, vec![true], @@ -291,6 +294,7 @@ async fn read_watchtower_challenge_details<'a>( ( task.id, task.execution_layer_block_number, + None, challenge_init_txids.first().cloned(), challenge_txids, included_watchtowers, @@ -306,6 +310,7 @@ async fn read_watchtower_challenge_details<'a>( Ok(( task_index, execution_layer_block_number, + attested_zkm_version, watchtower_challenge_init_txid, watchtower_challenge_txids, included_watchtowers, @@ -328,6 +333,7 @@ pub(crate) async fn fetch_on_demand_task( let ( task_index, execution_layer_block_number, + _attested_zkm_version, watchtower_challenge_init_txid, watchtower_challenge_txids, included_watchtowers, @@ -487,6 +493,23 @@ pub(crate) async fn fetch_on_demand_task( }; let commits: Vec = serde_json::from_str(&content)?; let latest_sequencer_commit_txid = commits[0].commit_txn.compute_txid().to_string(); + let attested_zkm_version = match (_attested_zkm_version, graph_id.as_ref()) { + (Some(attested_zkm_version), _) => attested_zkm_version, + (None, Some(graph_id)) => { + let graph_id = Uuid::parse_str(graph_id)?; + match storage_processor.find_graph(&graph_id).await? { + Some(graph) => graph.zkm_version, + None => { + tracing::warn!("Graph {graph_id} not found when building on-demand task"); + return Ok(None); + } + } + } + (None, None) => { + tracing::warn!("graph_id missing when building on-demand task"); + return Ok(None); + } + }; Ok(Some(OnDemandTask { task_index, @@ -494,6 +517,7 @@ pub(crate) async fn fetch_on_demand_task( header_chain_input_proof, commit_chain_input_proof, state_chain_input_proof, + attested_zkm_version, watchtower_challenge_init_txid, watchtower_challenge_txids, included_watchtowers, @@ -646,6 +670,7 @@ pub(crate) async fn add_watchtower_task( public_key: String, challenge_init_txid: String, execution_layer_block_number: i64, + attested_zkm_version: String, ) -> anyhow::Result { let mut storage_processor = local_db.acquire().await?; Ok(storage_processor @@ -660,6 +685,7 @@ pub(crate) async fn add_watchtower_task( updated_at: current_time_secs(), execution_layer_block_number, included: true, + extra: Some(attested_zkm_version), ..Default::default() }) .await?) @@ -900,6 +926,7 @@ mod tests { public_key, challenge_init_txid, number, + "v1.2.4".to_string(), ) .await .unwrap(); diff --git a/proof-builder-rpc/src/task/watchtower_proof.rs b/proof-builder-rpc/src/task/watchtower_proof.rs index c795ecd8..541afed1 100644 --- a/proof-builder-rpc/src/task/watchtower_proof.rs +++ b/proof-builder-rpc/src/task/watchtower_proof.rs @@ -42,6 +42,7 @@ pub(crate) fn spawn_watchtower_proof_task( args.header_chain_input_proof = next_task.header_chain_input_proof; args.commit_chain_input_proof = next_task.commit_chain_input_proof; args.state_chain_input_proof = next_task.state_chain_input_proof; + args.attested_zkm_version = next_task.attested_zkm_version; args.output = format!("{}/{}.bin", std::path::Path::new(&args.output).parent().unwrap().to_str().unwrap(), next_task.task_index, @@ -76,6 +77,7 @@ pub(crate) fn spawn_watchtower_proof_task( header_chain_input_proof: args.header_chain_input_proof.clone(), commit_chain_input_proof: args.commit_chain_input_proof.clone(), state_chain_input_proof: args.state_chain_input_proof.clone(), + attested_zkm_version: args.attested_zkm_version.clone(), output: args.output.clone(), target_block, block_pos, From 6e83c4877c0595006f0217e09e9edfb19d65e396 Mon Sep 17 00:00:00 2001 From: Blake Date: Mon, 30 Mar 2026 11:16:34 +0800 Subject: [PATCH 08/14] simplify part_stark_vk handling and attestation processes, improve witness verification logic --- circuits/operator-proof/host/src/lib.rs | 14 +- circuits/watchtower-proof/host/src/lib.rs | 9 +- .../src/attestation.rs | 210 ++++++++++++++---- .../bitcoin-light-client-circuit/src/lib.rs | 109 ++++----- 4 files changed, 219 insertions(+), 123 deletions(-) diff --git a/circuits/operator-proof/host/src/lib.rs b/circuits/operator-proof/host/src/lib.rs index 8f53fb5b..595165c4 100644 --- a/circuits/operator-proof/host/src/lib.rs +++ b/circuits/operator-proof/host/src/lib.rs @@ -383,11 +383,8 @@ impl ProofBuilder for OperatorProofBuilder { state_chain_output.part_stark_vk, current_part_stark_vk, ]; - let mut watchtower_source_indexes = - vec![current_source_index; watchtower_challenge_txns.len()]; - for (index, tx) in watchtower_challenge_txns.iter().enumerate() { + for tx in watchtower_challenge_txns { if let Some(part_stark_vk) = extract_watchtower_part_stark_vk(tx) { - watchtower_source_indexes[index] = requested_part_stark_vks.len(); requested_part_stark_vks.push(part_stark_vk); } } @@ -397,14 +394,7 @@ impl ProofBuilder for OperatorProofBuilder { .map_err(anyhow::Error::msg)?; let attestation_inputs = OperatorAttestationInputs { unique_witnesses, - header_ref: witness_refs[0], - commit_ref: witness_refs[1], - state_ref: witness_refs[2], - watchtower_refs: watchtower_source_indexes - .into_iter() - .map(|source_index| witness_refs[source_index]) - .collect(), - current_ref: witness_refs[current_source_index], + current_index: witness_refs[current_source_index], }; // --- spv --- // diff --git a/circuits/watchtower-proof/host/src/lib.rs b/circuits/watchtower-proof/host/src/lib.rs index 03fb2f3c..e1e21849 100644 --- a/circuits/watchtower-proof/host/src/lib.rs +++ b/circuits/watchtower-proof/host/src/lib.rs @@ -241,13 +241,8 @@ impl ProofBuilder for WatchtowerProofBuilder { let (unique_witnesses, witness_refs) = load_unique_part_stark_vk_witnesses(&attestation_dir, &requested_part_stark_vks) .map_err(anyhow::Error::msg)?; - let attestation_inputs = WatchtowerAttestationInputs { - unique_witnesses, - header_ref: witness_refs[0], - commit_ref: witness_refs[1], - state_ref: witness_refs[2], - current_ref: witness_refs[3], - }; + let attestation_inputs = + WatchtowerAttestationInputs { unique_witnesses, current_index: witness_refs[3] }; // --- spv --- // let genesis_sequencer_commit_txid = Txid::from_str(&genesis_sequencer_commit_txid)?; diff --git a/crates/bitcoin-light-client-circuit/src/attestation.rs b/crates/bitcoin-light-client-circuit/src/attestation.rs index 9fed7641..95cc4f4f 100644 --- a/crates/bitcoin-light-client-circuit/src/attestation.rs +++ b/crates/bitcoin-light-client-circuit/src/attestation.rs @@ -1,5 +1,5 @@ -use bitcoin::hashes::{sha256, Hash}; -use bitcoin::secp256k1::{ecdsa::Signature, Message, PublicKey, Secp256k1, SecretKey}; +use bitcoin::hashes::{Hash, sha256}; +use bitcoin::secp256k1::{Message, PublicKey, Secp256k1, SecretKey, ecdsa::Signature}; use serde::{Deserialize, Serialize}; use std::collections::{BTreeMap, BTreeSet}; use std::path::{Path, PathBuf}; @@ -30,29 +30,16 @@ pub struct PartStarkVkAttestationBundle { pub type UniquePartStarkVkWitness = PartStarkVkAttestationBundle; -#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] -pub struct ProofPartStarkVkRef { - pub proof_index: usize, - pub witness_index: usize, -} - #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] pub struct WatchtowerAttestationInputs { pub unique_witnesses: Vec, - pub header_ref: usize, - pub commit_ref: usize, - pub state_ref: usize, - pub current_ref: usize, + pub current_index: usize, } #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] pub struct OperatorAttestationInputs { pub unique_witnesses: Vec, - pub header_ref: usize, - pub commit_ref: usize, - pub state_ref: usize, - pub watchtower_refs: Vec, - pub current_ref: usize, + pub current_index: usize, } #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] @@ -335,34 +322,38 @@ pub fn verify_part_stark_vk_attestation( Ok(()) } -pub fn verify_part_stark_vk_witness_ref( +/// Verify each unique witness once so later lookups can reuse the verified payload. +pub fn verify_unique_part_stark_vk_witnesses( unique_witnesses: &[UniquePartStarkVkWitness], - witness_index: usize, - expected_part_stark_vk: &[u8], publisher_public_keys: &[PublicKey], threshold: u16, tree_height: usize, ) -> Result<(), String> { - let witness = unique_witnesses.get(witness_index).ok_or_else(|| { - format!("witness index {} out of range {}", witness_index, unique_witnesses.len()) - })?; - if witness.part_stark_vk != expected_part_stark_vk { - return Err("part_stark_vk witness payload mismatch".to_string()); + for witness in unique_witnesses { + verify_part_stark_vk_attestation(witness, publisher_public_keys, threshold, tree_height)?; } - verify_part_stark_vk_attestation(witness, publisher_public_keys, threshold, tree_height) + Ok(()) } -pub fn verify_current_part_stark_vk_witness( +/// Check whether a target `part_stark_vk` is present in the verified witness set. +pub fn assert_part_stark_vk_in_verified_witnesses( unique_witnesses: &[UniquePartStarkVkWitness], - witness_index: usize, - publisher_public_keys: &[PublicKey], - threshold: u16, - tree_height: usize, + expected_part_stark_vk: &[u8], +) -> Result<(), String> { + if unique_witnesses.iter().any(|witness| witness.part_stark_vk == expected_part_stark_vk) { + return Ok(()); + } + Err("part_stark_vk not found in verified witnesses".to_string()) +} + +/// Return the current `part_stark_vk` selected by the verified witness index. +pub fn get_current_part_stark_vk( + unique_witnesses: &[UniquePartStarkVkWitness], + current_index: usize, ) -> Result, String> { - let witness = unique_witnesses.get(witness_index).ok_or_else(|| { - format!("witness index {} out of range {}", witness_index, unique_witnesses.len()) + let witness = unique_witnesses.get(current_index).ok_or_else(|| { + format!("current index {} out of range {}", current_index, unique_witnesses.len()) })?; - verify_part_stark_vk_attestation(witness, publisher_public_keys, threshold, tree_height)?; Ok(witness.part_stark_vk.clone()) } @@ -638,13 +629,18 @@ pub fn load_unique_part_stark_vk_witnesses( #[cfg(test)] mod tests { - use bitcoin::secp256k1::{ecdsa::Signature, Message, Secp256k1, SecretKey}; + use std::time::{SystemTime, UNIX_EPOCH}; + + use bitcoin::secp256k1::{Message, Secp256k1, SecretKey, ecdsa::Signature}; use super::{ - build_attestation_message_digest, build_part_stark_vk_merkle_path, build_part_stark_vk_merkle_root, - build_part_stark_vk_root_signatures, compute_publisher_set_id, - part_stark_vk_leaf_hash, verify_part_stark_vk_attestation, PartStarkVkAttestationBundle, - PartStarkVkRootSignature, + PartStarkVkAttestationBundle, PartStarkVkRootSignature, + assert_part_stark_vk_in_verified_witnesses, build_attestation_message_digest, + build_part_stark_vk_merkle_path, build_part_stark_vk_merkle_root, + build_part_stark_vk_root_signatures, compute_publisher_set_id, get_current_part_stark_vk, + load_unique_part_stark_vk_witnesses, part_stark_vk_leaf_hash, + save_part_stark_vk_attestation_bundle, verify_part_stark_vk_attestation, + verify_unique_part_stark_vk_witnesses, }; fn sample_part_stark_vk() -> Vec { @@ -652,6 +648,61 @@ mod tests { .unwrap() } + fn sample_part_stark_vk_alt() -> Vec { + b"alternate-part-stark-vk".to_vec() + } + + fn sample_publishers() -> (Vec, Vec) { + let secp = Secp256k1::new(); + let secret_keys = vec![ + SecretKey::from_slice(&[1u8; 32]).unwrap(), + SecretKey::from_slice(&[2u8; 32]).unwrap(), + SecretKey::from_slice(&[3u8; 32]).unwrap(), + SecretKey::from_slice(&[4u8; 32]).unwrap(), + ]; + let publisher_public_keys = secret_keys + .iter() + .map(|sk| bitcoin::secp256k1::PublicKey::from_secret_key(&secp, sk)) + .collect::>(); + (secret_keys, publisher_public_keys) + } + + fn sample_attestation_bundle( + leaves: &[Vec], + leaf_index: usize, + threshold: u16, + publisher_public_keys: &[bitcoin::secp256k1::PublicKey], + signer_secret_keys: &[SecretKey], + ) -> PartStarkVkAttestationBundle { + let root = build_part_stark_vk_merkle_root(leaves, 6).unwrap(); + let publisher_set_id = compute_publisher_set_id(publisher_public_keys, threshold); + let indexed_secret_keys = + signer_secret_keys.iter().enumerate().collect::>(); + let signatures = build_part_stark_vk_root_signatures( + &indexed_secret_keys[..usize::from(threshold)], + 6, + root, + threshold, + publisher_set_id, + ) + .unwrap(); + + PartStarkVkAttestationBundle { + part_stark_vk: leaves[leaf_index].clone(), + leaf_index, + merkle_path: build_part_stark_vk_merkle_path(leaves, 6, leaf_index).unwrap(), + root, + threshold, + publisher_set_id, + signatures, + } + } + + fn unique_test_dir(prefix: &str) -> std::path::PathBuf { + let nanos = SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_nanos(); + std::env::temp_dir().join(format!("bitvm2-{prefix}-{nanos}")) + } + #[test] fn test_part_stark_vk_leaf_hash_matches_spec() { assert_eq!( @@ -830,7 +881,7 @@ mod tests { threshold, publisher_set_id, ) - .unwrap(); + .unwrap(); let bundle = PartStarkVkAttestationBundle { part_stark_vk: leaves[0].clone(), @@ -890,7 +941,86 @@ mod tests { signed_threshold - 1, 6 ) + .is_err() + ); + } + + #[test] + fn test_verify_unique_part_stark_vk_witnesses_accepts_multiple_bundles() { + let (secret_keys, publisher_public_keys) = sample_publishers(); + let leaves = vec![sample_part_stark_vk(), sample_part_stark_vk_alt()]; + let unique_witnesses = vec![ + sample_attestation_bundle(&leaves, 0, 3, &publisher_public_keys, &secret_keys), + sample_attestation_bundle(&leaves, 1, 3, &publisher_public_keys, &secret_keys), + ]; + + assert!( + verify_unique_part_stark_vk_witnesses(&unique_witnesses, &publisher_public_keys, 3, 6) + .is_ok() + ); + } + + #[test] + fn test_assert_part_stark_vk_in_verified_witnesses_checks_membership() { + let (secret_keys, publisher_public_keys) = sample_publishers(); + let leaves = vec![sample_part_stark_vk(), sample_part_stark_vk_alt()]; + let unique_witnesses = vec![ + sample_attestation_bundle(&leaves, 0, 3, &publisher_public_keys, &secret_keys), + sample_attestation_bundle(&leaves, 1, 3, &publisher_public_keys, &secret_keys), + ]; + + verify_unique_part_stark_vk_witnesses(&unique_witnesses, &publisher_public_keys, 3, 6) + .unwrap(); + assert!(assert_part_stark_vk_in_verified_witnesses(&unique_witnesses, &leaves[1]).is_ok()); + assert!( + assert_part_stark_vk_in_verified_witnesses(&unique_witnesses, b"missing-part-stark-vk") .is_err() ); } + + #[test] + fn test_get_current_part_stark_vk_returns_selected_payload() { + let (secret_keys, publisher_public_keys) = sample_publishers(); + let leaves = vec![sample_part_stark_vk(), sample_part_stark_vk_alt()]; + let unique_witnesses = vec![ + sample_attestation_bundle(&leaves, 0, 3, &publisher_public_keys, &secret_keys), + sample_attestation_bundle(&leaves, 1, 3, &publisher_public_keys, &secret_keys), + ]; + + assert_eq!(get_current_part_stark_vk(&unique_witnesses, 1).unwrap(), leaves[1]); + } + + #[test] + fn test_get_current_part_stark_vk_rejects_out_of_range_index() { + let (secret_keys, publisher_public_keys) = sample_publishers(); + let leaves = vec![sample_part_stark_vk()]; + let unique_witnesses = + vec![sample_attestation_bundle(&leaves, 0, 3, &publisher_public_keys, &secret_keys)]; + + assert!(get_current_part_stark_vk(&unique_witnesses, 1).is_err()); + } + + #[test] + fn test_load_unique_part_stark_vk_witnesses_reuses_duplicate_indexes() { + let (secret_keys, publisher_public_keys) = sample_publishers(); + let leaves = vec![sample_part_stark_vk(), sample_part_stark_vk_alt()]; + let dir = unique_test_dir("attestation-duplicate-indexes"); + std::fs::create_dir_all(dir.join("bundles")).unwrap(); + + let first_bundle = + sample_attestation_bundle(&leaves, 0, 3, &publisher_public_keys, &secret_keys); + let second_bundle = + sample_attestation_bundle(&leaves, 1, 3, &publisher_public_keys, &secret_keys); + save_part_stark_vk_attestation_bundle(&dir, &first_bundle).unwrap(); + save_part_stark_vk_attestation_bundle(&dir, &second_bundle).unwrap(); + + let requested = vec![leaves[0].clone(), leaves[1].clone(), leaves[0].clone()]; + let (unique_witnesses, witness_indexes) = + load_unique_part_stark_vk_witnesses(&dir, &requested).unwrap(); + + assert_eq!(unique_witnesses.len(), 2); + assert_eq!(witness_indexes, vec![0, 1, 0]); + + std::fs::remove_dir_all(dir).unwrap(); + } } diff --git a/crates/bitcoin-light-client-circuit/src/lib.rs b/crates/bitcoin-light-client-circuit/src/lib.rs index b19ae4dd..f88dd400 100644 --- a/crates/bitcoin-light-client-circuit/src/lib.rs +++ b/crates/bitcoin-light-client-circuit/src/lib.rs @@ -8,24 +8,24 @@ use state_chain::verify_sequencer_commit; pub use utils::*; use alloy_primitives::U256; +use bitcoin::hashes::{sha256, Hash, HashEngine}; use bitcoin::Block; use bitcoin::Transaction; -use bitcoin::hashes::{Hash, HashEngine, sha256}; use commit_chain::sequencer_hash; use commit_chain::{ - CommitChainCircuitInput, CommitChainPrevProofType, extract_data_from_commitment_outputs, + extract_data_from_commitment_outputs, CommitChainCircuitInput, CommitChainPrevProofType, }; use header_chain::{ - BitcoinMerkleTree, CircuitBlockHeader, CircuitTransaction, HeaderChainCircuitInput, - HeaderChainPrevProofType, MMRHost, SPV, verify_merkle_proof, + verify_merkle_proof, BitcoinMerkleTree, CircuitBlockHeader, CircuitTransaction, + HeaderChainCircuitInput, HeaderChainPrevProofType, MMRHost, SPV, }; use state_chain::{StateChainCircuitInput, StateChainPrevProofType}; -use std::panic::{AssertUnwindSafe, catch_unwind}; +use std::panic::{catch_unwind, AssertUnwindSafe}; use zkm_primitives::io::ZKMPublicValues; use zkm_verifier::{Groth16Verifier, IMM_GROTH16_VK_BYTES}; -use zkm_version::{ZKM_VERSION_BYTES_LEN, ZkmVersionBytes, decode_zkm_version_fixed}; +use zkm_version::{decode_zkm_version_fixed, ZkmVersionBytes, ZKM_VERSION_BYTES_LEN}; -use bitcoin::{ScriptBuf, TxOut, Txid, secp256k1::PublicKey}; +use bitcoin::{secp256k1::PublicKey, ScriptBuf, TxOut, Txid}; pub use guest_executor::io::EthClientExecutorInput; use serde::{Deserialize, Serialize}; @@ -120,41 +120,35 @@ pub fn watch_longest_chain( let StateChainPrevProofType::PrevProof(state_chain_output) = &prev_proof else { panic!("Only PrevProof is supported in watch_longest_chain"); }; - verify_part_stark_vk_witness_ref( + + verify_unique_part_stark_vk_witnesses( &attestation.unique_witnesses, - attestation.header_ref, - &btc_header_chain_output.part_stark_vk, &commit_chain_output.chain_state.publisher_public_keys, commit_chain_output.chain_state.threshold, PART_STARK_VK_TREE_HEIGHT, ) - .expect("Failed to verify header-chain part_stark_vk attestation"); - verify_part_stark_vk_witness_ref( + .expect("Failed to verify unique part_stark_vk attestations"); + + assert_part_stark_vk_in_verified_witnesses( &attestation.unique_witnesses, - attestation.commit_ref, - &commit_chain_output.part_stark_vk, - &commit_chain_output.chain_state.publisher_public_keys, - commit_chain_output.chain_state.threshold, - PART_STARK_VK_TREE_HEIGHT, + &btc_header_chain_output.part_stark_vk, ) - .expect("Failed to verify commit-chain part_stark_vk attestation"); - verify_part_stark_vk_witness_ref( + .expect("Failed to match header-chain part_stark_vk in verified witnesses"); + assert_part_stark_vk_in_verified_witnesses( &attestation.unique_witnesses, - attestation.state_ref, - &state_chain_output.part_stark_vk, - &commit_chain_output.chain_state.publisher_public_keys, - commit_chain_output.chain_state.threshold, - PART_STARK_VK_TREE_HEIGHT, + &commit_chain_output.part_stark_vk, ) - .expect("Failed to verify state-chain part_stark_vk attestation"); - let attested_part_stark_vk = verify_current_part_stark_vk_witness( + .expect("Failed to match commit-chain part_stark_vk in verified witnesses"); + assert_part_stark_vk_in_verified_witnesses( &attestation.unique_witnesses, - attestation.current_ref, - &commit_chain_output.chain_state.publisher_public_keys, - commit_chain_output.chain_state.threshold, - PART_STARK_VK_TREE_HEIGHT, + &state_chain_output.part_stark_vk, ) - .expect("Failed to verify watchtower part_stark_vk attestation"); + .expect("Failed to match state-chain part_stark_vk in verified witnesses"); + + let attested_part_stark_vk = + get_current_part_stark_vk(&attestation.unique_witnesses, attestation.current_index) + .expect("Failed to read watchtower current part_stark_vk"); + // check the signature. let cosmos_block_bytes = &state_chain_output.chain_state.latest_cosmos_block; let cosmos_block: LightBlock = @@ -259,24 +253,24 @@ pub fn propose_longest_chain( let HeaderChainPrevProofType::PrevProof(btc_header_chain_output) = &prev_proof else { panic!("Only PrevProof is supported in propose_longest_chain"); }; - verify_part_stark_vk_witness_ref( + + verify_unique_part_stark_vk_witnesses( &attestation.unique_witnesses, - attestation.header_ref, - &btc_header_chain_output.part_stark_vk, &commit_chain_output.chain_state.publisher_public_keys, commit_chain_output.chain_state.threshold, PART_STARK_VK_TREE_HEIGHT, ) - .expect("Failed to verify header-chain part_stark_vk attestation"); - verify_part_stark_vk_witness_ref( + .expect("Failed to verify unique part_stark_vk attestations"); + assert_part_stark_vk_in_verified_witnesses( + &attestation.unique_witnesses, + &btc_header_chain_output.part_stark_vk, + ) + .expect("Failed to match header-chain part_stark_vk in verified witnesses"); + assert_part_stark_vk_in_verified_witnesses( &attestation.unique_witnesses, - attestation.commit_ref, &commit_chain_output.part_stark_vk, - &commit_chain_output.chain_state.publisher_public_keys, - commit_chain_output.chain_state.threshold, - PART_STARK_VK_TREE_HEIGHT, ) - .expect("Failed to verify commit-chain part_stark_vk attestation"); + .expect("Failed to match commit-chain part_stark_vk in verified witnesses"); let operator_total_work = btc_header_chain_output.chain_state.total_work; let operator_consensus_block_height = U32::from(commit_chain_output.chain_state.block_height); // commit header chain best block hash as pis @@ -345,18 +339,11 @@ pub fn propose_longest_chain( continue; } }; - if let Err(err) = verify_part_stark_vk_witness_ref( + if let Err(err) = assert_part_stark_vk_in_verified_witnesses( &attestation.unique_witnesses, - *attestation - .watchtower_refs - .get(i) - .expect("watchtower attestation refs length mismatch"), &watchtower_outputs.attested_part_stark_vk, - &commit_chain_output.chain_state.publisher_public_keys, - commit_chain_output.chain_state.threshold, - PART_STARK_VK_TREE_HEIGHT, ) { - println!("Watchtower[{i}] invalid part_stark_vk attestation: {err}"); + println!("Watchtower[{i}] missing verified part_stark_vk: {err}"); continue; } match verify_proof_with_part_stark_vk(&proof, &public_values, &vk, &proof_part_stark_vk) @@ -409,23 +396,17 @@ pub fn propose_longest_chain( let StateChainPrevProofType::PrevProof(state_chain_output) = &prev_proof else { panic!("Only PrevProof is supported in propose_longest_chain"); }; - verify_part_stark_vk_witness_ref( + + assert_part_stark_vk_in_verified_witnesses( &attestation.unique_witnesses, - attestation.state_ref, &state_chain_output.part_stark_vk, - &commit_chain_output.chain_state.publisher_public_keys, - commit_chain_output.chain_state.threshold, - PART_STARK_VK_TREE_HEIGHT, ) - .expect("Failed to verify state-chain part_stark_vk attestation"); - let current_part_stark_vk = verify_current_part_stark_vk_witness( - &attestation.unique_witnesses, - attestation.current_ref, - &commit_chain_output.chain_state.publisher_public_keys, - commit_chain_output.chain_state.threshold, - PART_STARK_VK_TREE_HEIGHT, - ) - .expect("Failed to verify operator part_stark_vk attestation"); + .expect("Failed to match state-chain part_stark_vk in verified witnesses"); + + let current_part_stark_vk = + get_current_part_stark_vk(&attestation.unique_witnesses, attestation.current_index) + .expect("Failed to read operator current part_stark_vk"); + // check the signature. let cosmos_block_bytes = &state_chain_output.chain_state.latest_cosmos_block; let cosmos_block: LightBlock = From 61e63ed40c59864d22602b8a121b87424baa5cdc Mon Sep 17 00:00:00 2001 From: Blake Date: Tue, 7 Apr 2026 15:37:43 +0800 Subject: [PATCH 09/14] remove zkm_version references and streamline version handling in the codebase --- Cargo.lock | 16 - Cargo.toml | 11 +- circuits/commit-chain-proof/host/Cargo.toml | 1 - circuits/commit-chain-proof/host/src/lib.rs | 20 +- circuits/header-chain-proof/host/Cargo.toml | 1 - circuits/header-chain-proof/host/src/lib.rs | 13 +- circuits/operator-proof/host/Cargo.toml | 1 - circuits/operator-proof/host/src/lib.rs | 192 ++++++-- circuits/proof-builder/src/lib.rs | 3 - circuits/state-chain-proof/host/Cargo.toml | 1 - circuits/state-chain-proof/host/src/lib.rs | 13 +- circuits/watchtower-proof/host/Cargo.toml | 1 - circuits/watchtower-proof/host/src/lib.rs | 134 ++++-- circuits/watchtower-proof/host/src/main.rs | 1 - .../bitcoin-light-client-circuit/Cargo.toml | 1 - .../src/attestation.rs | 37 +- .../bitcoin-light-client-circuit/src/lib.rs | 449 +++++++++++------- crates/bitvm2-ga/src/tests.rs | 14 +- crates/bitvm2-ga/src/types.rs | 1 - crates/commit-chain/Cargo.toml | 1 - crates/commit-chain/src/commit_chain.rs | 250 +++++++++- crates/commit-chain/src/lib.rs | 12 +- crates/commit-chain/src/publisher.rs | 58 +++ crates/header-chain/Cargo.toml | 1 - crates/header-chain/src/header_chain.rs | 2 - crates/state-chain/Cargo.toml | 1 - crates/state-chain/src/state_chain.rs | 1 - ...3379bf8df51054958887f27081ff7f8f47cc.json} | 6 +- .../20260406120000_drop_graph_zkm_version.sql | 2 + crates/store/src/localdb.rs | 5 +- crates/store/src/schema.rs | 1 - crates/zkm-version/Cargo.toml | 10 - crates/zkm-version/src/lib.rs | 108 ----- node/src/bin/part_stark_vk_attest.rs | 14 +- node/src/bin/sequencer-set-publish.rs | 8 +- node/src/handle.rs | 2 +- node/src/lib.rs | 17 +- .../src/rpc_service/handler/bitvm2_handler.rs | 3 - node/src/rpc_service/mod.rs | 2 - node/src/utils.rs | 43 +- node/src/vk.rs | 29 +- proof-builder-rpc/src/api/proof_handler.rs | 12 +- proof-builder-rpc/src/task/mod.rs | 49 +- .../src/task/watchtower_proof.rs | 2 - 44 files changed, 972 insertions(+), 577 deletions(-) rename crates/store/.sqlx/{query-0d2299e1894169e179a5716f3a9e5cc2bce15d8facaf649e25d9919fb26f103e.json => query-a574aa126ca49083135ef445cb213379bf8df51054958887f27081ff7f8f47cc.json} (68%) create mode 100644 crates/store/migrations/20260406120000_drop_graph_zkm_version.sql delete mode 100644 crates/zkm-version/Cargo.toml delete mode 100644 crates/zkm-version/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index d54fd954..ecef8244 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2438,7 +2438,6 @@ dependencies = [ "tracing", "zkm-primitives", "zkm-verifier", - "zkm-version", "zkm-zkvm", ] @@ -3251,7 +3250,6 @@ dependencies = [ "tendermint-light-client-verifier", "tracing", "zkm-verifier", - "zkm-version", "zkm-zkvm", ] @@ -3279,7 +3277,6 @@ dependencies = [ "zkm-build", "zkm-prover", "zkm-sdk", - "zkm-version", ] [[package]] @@ -5476,7 +5473,6 @@ dependencies = [ "serde", "sha2 0.10.9", "zkm-verifier", - "zkm-version", "zkm-zkvm", ] @@ -5509,7 +5505,6 @@ dependencies = [ "zkm-prover", "zkm-sdk", "zkm-verifier", - "zkm-version", ] [[package]] @@ -8080,7 +8075,6 @@ dependencies = [ "zkm-prover", "zkm-sdk", "zkm-verifier", - "zkm-version", ] [[package]] @@ -11843,7 +11837,6 @@ dependencies = [ "tendermint-light-client-verifier", "tracing", "zkm-verifier", - "zkm-version", "zkm-zkvm", ] @@ -11885,7 +11878,6 @@ dependencies = [ "zkm-prover", "zkm-sdk", "zkm-verifier", - "zkm-version", ] [[package]] @@ -13467,7 +13459,6 @@ dependencies = [ "zkm-prover", "zkm-sdk", "zkm-verifier", - "zkm-version", ] [[package]] @@ -14921,13 +14912,6 @@ dependencies = [ "zkm-stark", ] -[[package]] -name = "zkm-version" -version = "0.3.3" -dependencies = [ - "anyhow", -] - [[package]] name = "zkm-zkvm" version = "1.2.5" diff --git a/Cargo.toml b/Cargo.toml index 0e14cd09..f1b85e34 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,7 +7,6 @@ resolver = "3" members = [ "node", "proof-builder-rpc", - "crates/zkm-version", "crates/cbft-rpc", "crates/bitvm2-ga", "crates/store", @@ -100,7 +99,6 @@ zkm-zkvm = { git = "https://github.com/ProjectZKM/Ziren", features = ["verify"] bitvm2-lib = { path = "crates/bitvm2-ga" } store = { path = "crates/store" } util = { path = "crates/util" } -zkm-version = { path = "crates/zkm-version" } client = { path = "crates/client" } bitcoin-light-client-circuit = { path = "crates/bitcoin-light-client-circuit" } header-chain = { path = "crates/header-chain" } @@ -187,11 +185,4 @@ zkm-prover = { git = "https://github.com/blake-pro/Ziren.git", branch = "pre-rel zkm-sdk = { git = "https://github.com/blake-pro/Ziren.git", branch = "pre-release-v1.2.5" } zkm-verifier = { git = "https://github.com/blake-pro/Ziren.git", branch = "pre-release-v1.2.5" } zkm-primitives = { git = "https://github.com/blake-pro/Ziren.git", branch = "pre-release-v1.2.5" } -zkm-zkvm = { git = "https://github.com/blake-pro/Ziren.git", branch = "pre-release-v1.2.5" } -#zkm-build = { path = "../zkm2/crates/build" } -#zkm-core-executor = { path = "../zkm2/crates/core/executor" } -#zkm-prover = { path = "../zkm2/crates/prover" } -#zkm-sdk = { path = "../zkm2/crates/sdk" } -#zkm-verifier = { path = "../zkm2/crates/verifier" } -#zkm-primitives = { path = "../zkm2/crates/primitives" } -#zkm-zkvm = { path = "../zkm2/crates/zkvm/entrypoint" } \ No newline at end of file +zkm-zkvm = { git = "https://github.com/blake-pro/Ziren.git", branch = "pre-release-v1.2.5" } \ No newline at end of file diff --git a/circuits/commit-chain-proof/host/Cargo.toml b/circuits/commit-chain-proof/host/Cargo.toml index b511f4e4..53e946ce 100644 --- a/circuits/commit-chain-proof/host/Cargo.toml +++ b/circuits/commit-chain-proof/host/Cargo.toml @@ -25,7 +25,6 @@ tendermint-light-client-verifier = { workspace = true, default-features = false, ] } proof-builder.workspace = true -zkm-version.workspace = true # Ziren zkm-sdk.workspace = true diff --git a/circuits/commit-chain-proof/host/src/lib.rs b/circuits/commit-chain-proof/host/src/lib.rs index 4f1a85f0..17131b1d 100644 --- a/circuits/commit-chain-proof/host/src/lib.rs +++ b/circuits/commit-chain-proof/host/src/lib.rs @@ -7,7 +7,6 @@ use zkm_sdk::{ HashableKey, Prover, ProverClient, ZKMProofKind, ZKMProofWithPublicValues, ZKMStdin, include_elf, }; -use zkm_version::read_zkm_version_from_file; use sha2::{Digest, Sha256}; use std::sync::OnceLock; @@ -116,12 +115,19 @@ pub async fn fetch_commit_chain( .iter() .map(|compressed_pk| PublicKey::from_str(compressed_pk).unwrap()) .collect(); + let next_publisher_public_keys = ci.next_publisher_public_keys.as_ref().map(|keys| { + keys.iter() + .map(|compressed_pk| PublicKey::from_str(compressed_pk).unwrap()) + .collect::>() + }); tracing::info!("sequencer_hash: {:?}", sequencer_hash(&ci.sequencers)); let commit = CircuitCommit { commit_txn, sequencers: ci.sequencers.clone(), publisher_public_keys, threshold: ci.threshold, + next_publisher_public_keys, + next_threshold: ci.next_threshold, genesis_txid: Txid::from_str(&ci.genesis_txid)?.as_raw_hash().to_byte_array(), block_height, }; @@ -190,8 +196,16 @@ impl ProofBuilder for CommitChainProofBuilder { fs::read(input_proof).context("Failed to read input proof file")?; let zkm_vk_hash = fs::read(&format!("{}.vk_hash.bin", input_proof)) .context("Read vk hash")?; - let zkm_version = read_zkm_version_from_file(input_proof) - .context("Failed to parse input zkm version")?; + let version_path = format!("{input_proof}.zkm_version.bin"); + let zkm_version = fs::read(&version_path) + .with_context(|| { + format!("failed to read zkm_version file '{version_path}'") + }) + .and_then(|raw_zkm_version| { + String::from_utf8(raw_zkm_version).with_context(|| { + format!("invalid UTF-8 in zkm_version file '{version_path}'") + }) + })?; let prev_output: CommitChainCircuitOutput = zkm_sdk::ZKMPublicValues::from(&public_inputs).read(); ( diff --git a/circuits/header-chain-proof/host/Cargo.toml b/circuits/header-chain-proof/host/Cargo.toml index 00dec26c..8c98b6a4 100644 --- a/circuits/header-chain-proof/host/Cargo.toml +++ b/circuits/header-chain-proof/host/Cargo.toml @@ -29,7 +29,6 @@ bitcoin = { workspace = true } client = { workspace = true } proof-builder = { workspace = true } util = { workspace = true } -zkm-version.workspace = true # Ziren zkm-sdk.workspace = true diff --git a/circuits/header-chain-proof/host/src/lib.rs b/circuits/header-chain-proof/host/src/lib.rs index e9caaa09..4a2e678e 100644 --- a/circuits/header-chain-proof/host/src/lib.rs +++ b/circuits/header-chain-proof/host/src/lib.rs @@ -11,7 +11,6 @@ use std::{ use util::get_btc_block_confirms; use zkm_sdk::ZKMProofKind; use zkm_sdk::{HashableKey, Prover, ProverClient, ZKMProofWithPublicValues, ZKMStdin, include_elf}; -use zkm_version::read_zkm_version_from_file; static ELF_ID: OnceLock = OnceLock::new(); use anyhow::Context; use clap::Parser; @@ -210,8 +209,16 @@ impl ProofBuilder for HeaderChainProofBuilder { let proof_bytes = fs::read(input_proof).context("Failed to read input proof file").unwrap(); let zkm_vk_hash = fs::read(&format!("{}.vk_hash.bin", input_proof)).unwrap(); - let zkm_version = read_zkm_version_from_file(input_proof) - .context("Failed to parse input zkm version")?; + let version_path = format!("{input_proof}.zkm_version.bin"); + let zkm_version = fs::read(&version_path) + .with_context(|| { + format!("failed to read zkm_version file '{version_path}'") + }) + .and_then(|raw_zkm_version| { + String::from_utf8(raw_zkm_version).with_context(|| { + format!("invalid UTF-8 in zkm_version file '{version_path}'") + }) + })?; let prev_output = zkm_sdk::ZKMPublicValues::from(&public_inputs).read(); ( HeaderChainPrevProofType::PrevProof(prev_output), diff --git a/circuits/operator-proof/host/Cargo.toml b/circuits/operator-proof/host/Cargo.toml index b4ecf6f0..2bc6c649 100644 --- a/circuits/operator-proof/host/Cargo.toml +++ b/circuits/operator-proof/host/Cargo.toml @@ -43,7 +43,6 @@ cbft-rpc = { workspace = true } bitcoin = { workspace = true } client = { workspace = true } proof-builder.workspace = true -zkm-version.workspace = true # Ziren zkm-sdk.workspace = true diff --git a/circuits/operator-proof/host/src/lib.rs b/circuits/operator-proof/host/src/lib.rs index 595165c4..a1585a4a 100644 --- a/circuits/operator-proof/host/src/lib.rs +++ b/circuits/operator-proof/host/src/lib.rs @@ -9,8 +9,7 @@ use bitcoin::{ use borsh::BorshDeserialize; use client::btc_chain::BTCClient; use commit_chain::{ - CommitChainCircuitInput, CommitChainCircuitOutput, CommitChainPrevProofType, - extract_data_from_commitment_outputs, + CommitChainCircuitInput, CommitChainPrevProofType, extract_data_from_commitment_outputs, }; use header_chain::{ BlockHeaderCircuitOutput, CircuitBlockHeader, HeaderChainCircuitInput, HeaderChainPrevProofType, @@ -23,15 +22,16 @@ use zkm_sdk::{ HashableKey, Prover, ProverClient, ZKMProofKind, ZKMProofWithPublicValues, ZKMStdin, include_elf, }; -use zkm_version::read_zkm_version_from_file; +use zkm_verifier::Groth16Verifier; use bincode::deserialize; use bitcoin_light_client_circuit::{ OperatorAttestationInputs, build_spv, load_unique_part_stark_vk_witnesses, - parse_watchtower_commitment, parse_watchtower_public_outputs, part_stark_vk_attestation_dir, + parse_watchtower_commitment, part_stark_vk_attestation_dir, }; use bitcoin_script::script; use clap::Parser; + /// The arguments for the cli. #[derive(Debug, Clone, Parser, serde::Deserialize, serde::Serialize)] pub struct Args { @@ -100,7 +100,6 @@ use std::panic::{AssertUnwindSafe, catch_unwind}; use sha2::{Digest, Sha256}; use std::sync::OnceLock; static ELF_ID: OnceLock = OnceLock::new(); -use zkm_verifier::Groth16Verifier; pub async fn fetch_target_block_and_watchtower_tx( esplora_url: &str, @@ -114,10 +113,10 @@ pub async fn fetch_target_block_and_watchtower_tx( u32, bitcoin::Block, BlockHash, - bitcoin::Transaction, + Transaction, Vec, Vec, - Vec, + Vec, Vec, )> { let watchtower_challenge_txids: Vec<&str> = watchtower_challenge_txids.split(",").collect(); @@ -248,17 +247,38 @@ fn load_proof_public_output(proof_path: &str) -> anyhow::Re deserialize(&public_inputs).context("Failed to decode proof public outputs") } -fn load_current_part_stark_vk(zkm_version: &str) -> anyhow::Result> { +fn extract_watchtower_part_stark_vk(tx: &Transaction) -> Option> { + let commitment = extract_data_from_commitment_outputs(&tx.output); + let (_, _, _, _, proof_part_stark_vk) = parse_watchtower_commitment(&commitment).ok()?; + Some(proof_part_stark_vk) +} + +fn load_part_stark_vk(zkm_version: &str) -> anyhow::Result> { catch_unwind(AssertUnwindSafe(|| Groth16Verifier::get_part_stark_vk(zkm_version).to_vec())) .map_err(|_| anyhow::anyhow!("Failed to load part_stark_vk for zkm_version {zkm_version}")) } -fn extract_watchtower_part_stark_vk(tx: &Transaction) -> Option> { - let commitment = - catch_unwind(AssertUnwindSafe(|| extract_data_from_commitment_outputs(&tx.output))).ok()?; - let (_, _, public_values, _, _) = parse_watchtower_commitment(&commitment).ok()?; - let outputs = parse_watchtower_public_outputs(&public_values).ok()?; - Some(outputs.attested_part_stark_vk) +/// Collect both the version-derived verifier key and the recursive inner verifier key +/// for header/state subproofs, plus each watchtower proof verifier key from commitments. +fn collect_requested_part_stark_vks( + header_chain_input: &HeaderChainCircuitInput, + header_chain_output: &BlockHeaderCircuitOutput, + state_chain_input: &StateChainCircuitInput, + state_chain_output: &StateChainCircuitOutput, + watchtower_challenge_txns: &[Transaction], +) -> anyhow::Result>> { + let mut requested_part_stark_vks = vec![ + load_part_stark_vk(&header_chain_input.zkm_version)?, + header_chain_output.part_stark_vk.clone(), + load_part_stark_vk(&state_chain_input.zkm_version)?, + state_chain_output.part_stark_vk.clone(), + ]; + for tx in watchtower_challenge_txns { + if let Some(part_stark_vk) = extract_watchtower_part_stark_vk(tx) { + requested_part_stark_vks.push(part_stark_vk); + } + } + Ok(requested_part_stark_vks) } impl ProofBuilder for OperatorProofBuilder { @@ -316,8 +336,14 @@ impl ProofBuilder for OperatorProofBuilder { .unwrap(); let zkm_vk_hash = fs::read(&format!("{}.vk_hash.bin", header_chain_input_proof)).unwrap(); - let zkm_version = read_zkm_version_from_file(header_chain_input_proof) - .context("Failed to parse header-chain zkm version")?; + let version_path = format!("{header_chain_input_proof}.zkm_version.bin"); + let zkm_version = fs::read(&version_path) + .with_context(|| format!("failed to read zkm_version file '{version_path}'")) + .and_then(|raw_zkm_version| { + String::from_utf8(raw_zkm_version).with_context(|| { + format!("invalid UTF-8 in zkm_version file '{version_path}'") + }) + })?; HeaderChainCircuitInput { prev_proof: HeaderChainPrevProofType::GenesisBlock, // unused zkm_proof, @@ -337,8 +363,14 @@ impl ProofBuilder for OperatorProofBuilder { .unwrap(); let zkm_vk_hash = fs::read(&format!("{}.vk_hash.bin", commit_chain_input_proof)).unwrap(); - let zkm_version = read_zkm_version_from_file(commit_chain_input_proof) - .context("Failed to parse commit-chain zkm version")?; + let version_path = format!("{commit_chain_input_proof}.zkm_version.bin"); + let zkm_version = fs::read(&version_path) + .with_context(|| format!("failed to read zkm_version file '{version_path}'")) + .and_then(|raw_zkm_version| { + String::from_utf8(raw_zkm_version).with_context(|| { + format!("invalid UTF-8 in zkm_version file '{version_path}'") + }) + })?; CommitChainCircuitInput { prev_proof: CommitChainPrevProofType::GenesisBlock, // unused zkm_proof, @@ -358,8 +390,15 @@ impl ProofBuilder for OperatorProofBuilder { fs::read(&format!("{}.public_inputs.bin", state_chain_input_proof)).unwrap(); let zkm_vk_hash = fs::read(&format!("{}.vk_hash.bin", state_chain_input_proof)).unwrap(); - let zkm_version = read_zkm_version_from_file(state_chain_input_proof) - .context("Failed to parse state-chain zkm version")?; + let version_path = format!("{state_chain_input_proof}.zkm_version.bin"); + let zkm_version = fs::read(&version_path) + .with_context(|| format!("failed to read zkm_version file '{version_path}'")) + .and_then(|raw_zkm_version| { + String::from_utf8(raw_zkm_version).with_context(|| { + format!("invalid UTF-8 in zkm_version file '{version_path}'") + }) + })?; + StateChainCircuitInput { prev_proof: StateChainPrevProofType::GenesisBlock, // unused zkm_proof, @@ -369,33 +408,23 @@ impl ProofBuilder for OperatorProofBuilder { blocks: vec![], } }; + let header_chain_output: BlockHeaderCircuitOutput = load_proof_public_output(header_chain_input_proof)?; - let commit_chain_output: CommitChainCircuitOutput = - load_proof_public_output(commit_chain_input_proof)?; let state_chain_output: StateChainCircuitOutput = load_proof_public_output(state_chain_input_proof)?; - let current_part_stark_vk = load_current_part_stark_vk(&self.client.version())?; - let current_source_index = 3usize; - let mut requested_part_stark_vks = vec![ - header_chain_output.part_stark_vk, - commit_chain_output.part_stark_vk, - state_chain_output.part_stark_vk, - current_part_stark_vk, - ]; - for tx in watchtower_challenge_txns { - if let Some(part_stark_vk) = extract_watchtower_part_stark_vk(tx) { - requested_part_stark_vks.push(part_stark_vk); - } - } + let requested_part_stark_vks = collect_requested_part_stark_vks( + &header_chain_input, + &header_chain_output, + &state_chain_input, + &state_chain_output, + watchtower_challenge_txns, + )?; let attestation_dir = part_stark_vk_attestation_dir(); - let (unique_witnesses, witness_refs) = + let (unique_witnesses, _) = load_unique_part_stark_vk_witnesses(&attestation_dir, &requested_part_stark_vks) .map_err(anyhow::Error::msg)?; - let attestation_inputs = OperatorAttestationInputs { - unique_witnesses, - current_index: witness_refs[current_source_index], - }; + let attestation_inputs = OperatorAttestationInputs { unique_witnesses }; // --- spv --- // //let latest_sequencer_commit_txid = Txid::from_str(&latest_sequencer_commit_txid).unwrap(); @@ -511,8 +540,82 @@ mod tests { use ark_bn254::Bn254; use ark_groth16::{Groth16, r1cs_to_qap::LibsnarkReduction}; + use std::panic::{AssertUnwindSafe, catch_unwind}; + use zkm_verifier::{Groth16Verifier, IMM_GROTH16_VK_BYTES, convert_ark_imm_wrap_vk}; + fn sample_header_input(zkm_version: &str) -> HeaderChainCircuitInput { + HeaderChainCircuitInput { + prev_proof: HeaderChainPrevProofType::GenesisBlock, + zkm_proof: vec![], + zkm_public_values: vec![], + zkm_vk_hash: vec![], + zkm_version: zkm_version.to_string(), + block_headers: vec![], + } + } + + fn sample_state_input(zkm_version: &str) -> StateChainCircuitInput { + StateChainCircuitInput { + prev_proof: StateChainPrevProofType::GenesisBlock, + zkm_proof: vec![], + zkm_public_values: vec![], + zkm_vk_hash: vec![], + zkm_version: zkm_version.to_string(), + blocks: vec![], + } + } + + fn sample_header_output(part_stark_vk: Vec) -> BlockHeaderCircuitOutput { + BlockHeaderCircuitOutput { chain_state: header_chain::ChainState::new(), part_stark_vk } + } + + fn sample_state_output(part_stark_vk: Vec) -> StateChainCircuitOutput { + StateChainCircuitOutput { + chain_state: state_chain::StateChainState::new(0, [0u8; 32], Vec::new()), + part_stark_vk, + } + } + + #[test] + fn test_collect_requested_part_stark_vks_includes_outer_inner_and_watchtower_keys() { + let old_vk = load_part_stark_vk("v1.2.4").unwrap(); + let new_vk = load_part_stark_vk("v1.2.5").unwrap(); + + let graph_id = [7u8; 16]; + let proof = vec![3u8; 260]; + let public_inputs = vec![9u8; 36]; + let vk_hash = "ab".repeat(33); + let watchtower_comm = bitcoin_light_client_circuit::build_watchtower_commitment( + &graph_id, + &proof, + &public_inputs, + &vk_hash, + &new_vk, + ) + .unwrap(); + let watchtower_tx = Transaction { + version: bitcoin::transaction::Version::TWO, + lock_time: bitcoin::absolute::LockTime::ZERO, + input: vec![], + output: vec![TxOut { + value: bitcoin::Amount::ZERO, + script_pubkey: bitcoin::ScriptBuf::new_op_return(watchtower_comm.as_ref()), + }], + }; + + let requested = collect_requested_part_stark_vks( + &sample_header_input("v1.2.5"), + &sample_header_output(old_vk.clone()), + &sample_state_input("v1.2.5"), + &sample_state_output(old_vk.clone()), + &[watchtower_tx], + ) + .unwrap(); + + assert_eq!(requested, vec![new_vk.clone(), old_vk.clone(), new_vk.clone(), old_vk, new_vk]); + } + #[tokio::test] #[ignore = "local test"] async fn test_parse_operator_proof() { @@ -532,8 +635,15 @@ mod tests { ); let vk_hash = String::from_utf8(vk_bytes).unwrap(); + let part_stark_vk = catch_unwind(AssertUnwindSafe(|| { + Groth16Verifier::get_part_stark_vk(&proof.zkm_version) + })) + .map_err(|_| { + anyhow::anyhow!("Failed to load part_stark_vk for zkm_version {}", proof.zkm_version) + }) + .unwrap(); let ark_proof = - convert_ark_imm_wrap_vk(&proof, &vk_hash, &IMM_GROTH16_VK_BYTES, &a.part_stark_vk) + convert_ark_imm_wrap_vk(&proof, &vk_hash, &IMM_GROTH16_VK_BYTES, part_stark_vk) .unwrap(); // Verify the arkworks proof. diff --git a/circuits/proof-builder/src/lib.rs b/circuits/proof-builder/src/lib.rs index 5a96f776..710d9098 100644 --- a/circuits/proof-builder/src/lib.rs +++ b/circuits/proof-builder/src/lib.rs @@ -42,7 +42,6 @@ pub enum ProofRequest { header_chain_input_proof: String, commit_chain_input_proof: String, state_chain_input_proof: String, - attested_zkm_version: String, output: String, target_block: Block, block_pos: u32, @@ -113,7 +112,6 @@ pub struct OnDemandTask { pub header_chain_input_proof: String, pub commit_chain_input_proof: String, pub state_chain_input_proof: String, - pub attested_zkm_version: String, pub watchtower_challenge_init_txid: Option, pub watchtower_challenge_txids: Vec, @@ -251,7 +249,6 @@ pub struct WatchtowerProofRequest { pub public_key: String, pub challenge_init_txid: String, pub execution_layer_block_number: i64, - pub attested_zkm_version: String, } #[derive(Debug, Serialize, Deserialize)] diff --git a/circuits/state-chain-proof/host/Cargo.toml b/circuits/state-chain-proof/host/Cargo.toml index e0c4dfdc..da7404d8 100644 --- a/circuits/state-chain-proof/host/Cargo.toml +++ b/circuits/state-chain-proof/host/Cargo.toml @@ -35,7 +35,6 @@ cbft-rpc.workspace = true proof-builder.workspace = true alloy-consensus.workspace = true util.workspace = true -zkm-version.workspace = true # Ziren zkm-sdk.workspace = true diff --git a/circuits/state-chain-proof/host/src/lib.rs b/circuits/state-chain-proof/host/src/lib.rs index c10578b6..e302f8ab 100644 --- a/circuits/state-chain-proof/host/src/lib.rs +++ b/circuits/state-chain-proof/host/src/lib.rs @@ -20,7 +20,6 @@ use zkm_sdk::{ HashableKey, Prover, ProverClient, ZKMProofKind, ZKMProofWithPublicValues, ZKMStdin, include_elf, }; -use zkm_version::read_zkm_version_from_file; use sha2::{Digest, Sha256}; use std::sync::OnceLock; @@ -326,8 +325,16 @@ impl ProofBuilder for StateChainProofBuilder { fs::read(input_proof).context("Failed to read input proof file")?; let zkm_vk_hash = fs::read(&format!("{}.vk_hash.bin", input_proof)) .context("Read vk_hash")?; - let zkm_version = read_zkm_version_from_file(input_proof) - .context("Failed to parse input zkm version")?; + let version_path = format!("{input_proof}.zkm_version.bin"); + let zkm_version = fs::read(&version_path) + .with_context(|| { + format!("failed to read zkm_version file '{version_path}'") + }) + .and_then(|raw_zkm_version| { + String::from_utf8(raw_zkm_version).with_context(|| { + format!("invalid UTF-8 in zkm_version file '{version_path}'") + }) + })?; let prev_output: StateChainCircuitOutput = zkm_sdk::ZKMPublicValues::from(&public_inputs).read(); ( diff --git a/circuits/watchtower-proof/host/Cargo.toml b/circuits/watchtower-proof/host/Cargo.toml index beabedf3..427c24b7 100644 --- a/circuits/watchtower-proof/host/Cargo.toml +++ b/circuits/watchtower-proof/host/Cargo.toml @@ -31,7 +31,6 @@ commit-chain = { workspace = true } bitcoin = { workspace = true } client = { workspace = true } proof-builder.workspace = true -zkm-version.workspace = true # Ziren zkm-sdk.workspace = true diff --git a/circuits/watchtower-proof/host/src/lib.rs b/circuits/watchtower-proof/host/src/lib.rs index e1e21849..4d3ec74a 100644 --- a/circuits/watchtower-proof/host/src/lib.rs +++ b/circuits/watchtower-proof/host/src/lib.rs @@ -3,7 +3,7 @@ use anyhow::Context; use bincode::deserialize; use borsh::BorshDeserialize; -use commit_chain::{CommitChainCircuitInput, CommitChainCircuitOutput, CommitChainPrevProofType}; +use commit_chain::{CommitChainCircuitInput, CommitChainPrevProofType}; use header_chain::{ BlockHeaderCircuitOutput, CircuitBlockHeader, HeaderChainCircuitInput, HeaderChainPrevProofType, }; @@ -30,7 +30,6 @@ use serde::de::DeserializeOwned; use std::fs; use std::panic::{AssertUnwindSafe, catch_unwind}; use zkm_verifier::Groth16Verifier; -use zkm_version::read_zkm_version_from_file; // The arguments for the cli. #[derive(Debug, Clone, Parser, serde::Deserialize, serde::Serialize)] @@ -59,10 +58,6 @@ pub struct Args { #[clap(long, env, short)] pub state_chain_input_proof: String, - #[clap(long, env, default_value = "")] - #[serde(default)] - pub attested_zkm_version: String, - #[clap(long, env)] pub output: String, } @@ -120,6 +115,22 @@ fn load_part_stark_vk(zkm_version: &str) -> anyhow::Result> { .map_err(|_| anyhow::anyhow!("Failed to load part_stark_vk for zkm_version {zkm_version}")) } +/// Collect both the version-derived verifier key and the recursive inner verifier key +/// for header/state subproofs so witness loading survives Ziren upgrades. +fn collect_requested_part_stark_vks( + header_chain_input: &HeaderChainCircuitInput, + header_chain_output: &BlockHeaderCircuitOutput, + state_chain_input: &StateChainCircuitInput, + state_chain_output: &StateChainCircuitOutput, +) -> anyhow::Result>> { + Ok(vec![ + load_part_stark_vk(&header_chain_input.zkm_version)?, + header_chain_output.part_stark_vk.clone(), + load_part_stark_vk(&state_chain_input.zkm_version)?, + state_chain_output.part_stark_vk.clone(), + ]) +} + impl ProofBuilder for WatchtowerProofBuilder { fn client(&self) -> &zkm_sdk::ProverClient { &self.client @@ -146,7 +157,6 @@ impl ProofBuilder for WatchtowerProofBuilder { header_chain_input_proof, commit_chain_input_proof, state_chain_input_proof, - attested_zkm_version, latest_sequencer_commit_txid, genesis_sequencer_commit_txid, target_block, @@ -167,8 +177,14 @@ impl ProofBuilder for WatchtowerProofBuilder { .unwrap(); let zkm_vk_hash = fs::read(&format!("{}.vk_hash.bin", header_chain_input_proof)).unwrap(); - let zkm_version = read_zkm_version_from_file(header_chain_input_proof) - .context("Failed to parse header-chain zkm version")?; + let version_path = format!("{header_chain_input_proof}.zkm_version.bin"); + let zkm_version = fs::read(&version_path) + .with_context(|| format!("failed to read zkm_version file '{version_path}'")) + .and_then(|raw_zkm_version| { + String::from_utf8(raw_zkm_version).with_context(|| { + format!("invalid UTF-8 in zkm_version file '{version_path}'") + }) + })?; HeaderChainCircuitInput { prev_proof: HeaderChainPrevProofType::GenesisBlock, // unused @@ -189,8 +205,14 @@ impl ProofBuilder for WatchtowerProofBuilder { .unwrap(); let zkm_vk_hash = fs::read(&format!("{}.vk_hash.bin", commit_chain_input_proof)).unwrap(); - let zkm_version = read_zkm_version_from_file(commit_chain_input_proof) - .context("Failed to parse commit-chain zkm version")?; + let version_path = format!("{commit_chain_input_proof}.zkm_version.bin"); + let zkm_version = fs::read(&version_path) + .with_context(|| format!("failed to read zkm_version file '{version_path}'")) + .and_then(|raw_zkm_version| { + String::from_utf8(raw_zkm_version).with_context(|| { + format!("invalid UTF-8 in zkm_version file '{version_path}'") + }) + })?; CommitChainCircuitInput { prev_proof: CommitChainPrevProofType::GenesisBlock, // unused zkm_proof, @@ -210,8 +232,14 @@ impl ProofBuilder for WatchtowerProofBuilder { fs::read(&format!("{}.public_inputs.bin", state_chain_input_proof)).unwrap(); let zkm_vk_hash = fs::read(&format!("{}.vk_hash.bin", state_chain_input_proof)).unwrap(); - let zkm_version = read_zkm_version_from_file(state_chain_input_proof) - .context("Failed to parse state-chain zkm version")?; + let version_path = format!("{state_chain_input_proof}.zkm_version.bin"); + let zkm_version = fs::read(&version_path) + .with_context(|| format!("failed to read zkm_version file '{version_path}'")) + .and_then(|raw_zkm_version| { + String::from_utf8(raw_zkm_version).with_context(|| { + format!("invalid UTF-8 in zkm_version file '{version_path}'") + }) + })?; StateChainCircuitInput { prev_proof: StateChainPrevProofType::GenesisBlock, // unused zkm_proof, @@ -223,26 +251,19 @@ impl ProofBuilder for WatchtowerProofBuilder { }; let header_chain_output: BlockHeaderCircuitOutput = load_proof_public_output(header_chain_input_proof)?; - let commit_chain_output: CommitChainCircuitOutput = - load_proof_public_output(commit_chain_input_proof)?; let state_chain_output: StateChainCircuitOutput = load_proof_public_output(state_chain_input_proof)?; - if attested_zkm_version.is_empty() { - anyhow::bail!("attested_zkm_version is required for watchtower proof generation"); - } - let attested_part_stark_vk = load_part_stark_vk(attested_zkm_version)?; let attestation_dir = part_stark_vk_attestation_dir(); - let requested_part_stark_vks = vec![ - header_chain_output.part_stark_vk, - commit_chain_output.part_stark_vk, - state_chain_output.part_stark_vk, - attested_part_stark_vk, - ]; - let (unique_witnesses, witness_refs) = + let requested_part_stark_vks = collect_requested_part_stark_vks( + &header_chain_input, + &header_chain_output, + &state_chain_input, + &state_chain_output, + )?; + let (unique_witnesses, _) = load_unique_part_stark_vk_witnesses(&attestation_dir, &requested_part_stark_vks) .map_err(anyhow::Error::msg)?; - let attestation_inputs = - WatchtowerAttestationInputs { unique_witnesses, current_index: witness_refs[3] }; + let attestation_inputs = WatchtowerAttestationInputs { unique_witnesses }; // --- spv --- // let genesis_sequencer_commit_txid = Txid::from_str(&genesis_sequencer_commit_txid)?; @@ -331,3 +352,60 @@ impl ProofBuilder for WatchtowerProofBuilder { Ok((public_value_hex, proof_size)) } } + +#[cfg(test)] +mod tests { + use super::*; + + fn sample_header_input(zkm_version: &str) -> HeaderChainCircuitInput { + HeaderChainCircuitInput { + prev_proof: HeaderChainPrevProofType::GenesisBlock, + zkm_proof: vec![], + zkm_public_values: vec![], + zkm_vk_hash: vec![], + zkm_version: zkm_version.to_string(), + block_headers: vec![], + } + } + + fn sample_state_input(zkm_version: &str) -> StateChainCircuitInput { + StateChainCircuitInput { + prev_proof: StateChainPrevProofType::GenesisBlock, + zkm_proof: vec![], + zkm_public_values: vec![], + zkm_vk_hash: vec![], + zkm_version: zkm_version.to_string(), + blocks: vec![], + } + } + + fn sample_header_output(part_stark_vk: Vec) -> BlockHeaderCircuitOutput { + BlockHeaderCircuitOutput { + chain_state: header_chain::ChainState::new(), + part_stark_vk, + } + } + + fn sample_state_output(part_stark_vk: Vec) -> StateChainCircuitOutput { + StateChainCircuitOutput { + chain_state: state_chain::StateChainState::new(0, [0u8; 32], Vec::new()), + part_stark_vk, + } + } + + #[test] + fn test_collect_requested_part_stark_vks_includes_outer_and_inner_versions() { + let old_vk = load_part_stark_vk("v1.2.4").unwrap(); + let new_vk = load_part_stark_vk("v1.2.5").unwrap(); + + let requested = collect_requested_part_stark_vks( + &sample_header_input("v1.2.5"), + &sample_header_output(old_vk.clone()), + &sample_state_input("v1.2.5"), + &sample_state_output(old_vk.clone()), + ) + .unwrap(); + + assert_eq!(requested, vec![new_vk.clone(), old_vk.clone(), new_vk, old_vk]); + } +} diff --git a/circuits/watchtower-proof/host/src/main.rs b/circuits/watchtower-proof/host/src/main.rs index ad0522fb..d5d2a818 100644 --- a/circuits/watchtower-proof/host/src/main.rs +++ b/circuits/watchtower-proof/host/src/main.rs @@ -25,7 +25,6 @@ async fn main() { header_chain_input_proof: args.header_chain_input_proof.clone(), commit_chain_input_proof: args.commit_chain_input_proof.clone(), state_chain_input_proof: args.state_chain_input_proof.clone(), - attested_zkm_version: args.attested_zkm_version.clone(), output: args.output.clone(), target_block, block_pos, diff --git a/crates/bitcoin-light-client-circuit/Cargo.toml b/crates/bitcoin-light-client-circuit/Cargo.toml index d7d30b4d..172e5530 100644 --- a/crates/bitcoin-light-client-circuit/Cargo.toml +++ b/crates/bitcoin-light-client-circuit/Cargo.toml @@ -18,7 +18,6 @@ state-chain = { workspace = true } zkm-verifier = { workspace = true } zkm-zkvm = { workspace = true } zkm-primitives = { workspace = true } -zkm-version = { workspace = true } #zkm-verifier = { path = "../../../Ziren/crates/verifier" } #zkm-zkvm = { path = "../../../Ziren/crates/zkvm/entrypoint", features = ["verify"] } diff --git a/crates/bitcoin-light-client-circuit/src/attestation.rs b/crates/bitcoin-light-client-circuit/src/attestation.rs index 95cc4f4f..42fe8ab7 100644 --- a/crates/bitcoin-light-client-circuit/src/attestation.rs +++ b/crates/bitcoin-light-client-circuit/src/attestation.rs @@ -33,13 +33,11 @@ pub type UniquePartStarkVkWitness = PartStarkVkAttestationBundle; #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] pub struct WatchtowerAttestationInputs { pub unique_witnesses: Vec, - pub current_index: usize, } #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] pub struct OperatorAttestationInputs { pub unique_witnesses: Vec, - pub current_index: usize, } #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] @@ -346,17 +344,6 @@ pub fn assert_part_stark_vk_in_verified_witnesses( Err("part_stark_vk not found in verified witnesses".to_string()) } -/// Return the current `part_stark_vk` selected by the verified witness index. -pub fn get_current_part_stark_vk( - unique_witnesses: &[UniquePartStarkVkWitness], - current_index: usize, -) -> Result, String> { - let witness = unique_witnesses.get(current_index).ok_or_else(|| { - format!("current index {} out of range {}", current_index, unique_witnesses.len()) - })?; - Ok(witness.part_stark_vk.clone()) -} - pub fn load_part_stark_vk_tree_state(dir: &Path) -> Result { let path = part_stark_vk_tree_state_path(dir); let bytes = std::fs::read(&path) @@ -637,7 +624,7 @@ mod tests { PartStarkVkAttestationBundle, PartStarkVkRootSignature, assert_part_stark_vk_in_verified_witnesses, build_attestation_message_digest, build_part_stark_vk_merkle_path, build_part_stark_vk_merkle_root, - build_part_stark_vk_root_signatures, compute_publisher_set_id, get_current_part_stark_vk, + build_part_stark_vk_root_signatures, compute_publisher_set_id, load_unique_part_stark_vk_witnesses, part_stark_vk_leaf_hash, save_part_stark_vk_attestation_bundle, verify_part_stark_vk_attestation, verify_unique_part_stark_vk_witnesses, @@ -978,28 +965,6 @@ mod tests { ); } - #[test] - fn test_get_current_part_stark_vk_returns_selected_payload() { - let (secret_keys, publisher_public_keys) = sample_publishers(); - let leaves = vec![sample_part_stark_vk(), sample_part_stark_vk_alt()]; - let unique_witnesses = vec![ - sample_attestation_bundle(&leaves, 0, 3, &publisher_public_keys, &secret_keys), - sample_attestation_bundle(&leaves, 1, 3, &publisher_public_keys, &secret_keys), - ]; - - assert_eq!(get_current_part_stark_vk(&unique_witnesses, 1).unwrap(), leaves[1]); - } - - #[test] - fn test_get_current_part_stark_vk_rejects_out_of_range_index() { - let (secret_keys, publisher_public_keys) = sample_publishers(); - let leaves = vec![sample_part_stark_vk()]; - let unique_witnesses = - vec![sample_attestation_bundle(&leaves, 0, 3, &publisher_public_keys, &secret_keys)]; - - assert!(get_current_part_stark_vk(&unique_witnesses, 1).is_err()); - } - #[test] fn test_load_unique_part_stark_vk_witnesses_reuses_duplicate_indexes() { let (secret_keys, publisher_public_keys) = sample_publishers(); diff --git a/crates/bitcoin-light-client-circuit/src/lib.rs b/crates/bitcoin-light-client-circuit/src/lib.rs index f88dd400..96b055f3 100644 --- a/crates/bitcoin-light-client-circuit/src/lib.rs +++ b/crates/bitcoin-light-client-circuit/src/lib.rs @@ -8,24 +8,24 @@ use state_chain::verify_sequencer_commit; pub use utils::*; use alloy_primitives::U256; -use bitcoin::hashes::{sha256, Hash, HashEngine}; use bitcoin::Block; use bitcoin::Transaction; +use bitcoin::hashes::{Hash, HashEngine, sha256}; use commit_chain::sequencer_hash; use commit_chain::{ - extract_data_from_commitment_outputs, CommitChainCircuitInput, CommitChainPrevProofType, + CommitChainCircuitInput, CommitChainCircuitOutput, CommitChainPrevProofType, + extract_data_from_commitment_outputs, }; use header_chain::{ - verify_merkle_proof, BitcoinMerkleTree, CircuitBlockHeader, CircuitTransaction, - HeaderChainCircuitInput, HeaderChainPrevProofType, MMRHost, SPV, + BitcoinMerkleTree, CircuitBlockHeader, CircuitTransaction, HeaderChainCircuitInput, + HeaderChainPrevProofType, MMRHost, SPV, verify_merkle_proof, }; use state_chain::{StateChainCircuitInput, StateChainPrevProofType}; -use std::panic::{catch_unwind, AssertUnwindSafe}; +use std::panic::{AssertUnwindSafe, catch_unwind}; use zkm_primitives::io::ZKMPublicValues; use zkm_verifier::{Groth16Verifier, IMM_GROTH16_VK_BYTES}; -use zkm_version::{decode_zkm_version_fixed, ZkmVersionBytes, ZKM_VERSION_BYTES_LEN}; -use bitcoin::{secp256k1::PublicKey, ScriptBuf, TxOut, Txid}; +use bitcoin::{ScriptBuf, TxOut, Txid, secp256k1::PublicKey}; pub use guest_executor::io::EthClientExecutorInput; use serde::{Deserialize, Serialize}; @@ -35,7 +35,6 @@ pub const PUBLIC_INPUTS_SIZE: usize = 36; pub const WATCHTOWER_COMMITMENT_PUBLIC_INPUTS_LEN_SIZE: usize = 4; pub const WATCHTOWER_COMMITMENT_PROOF_PART_STARK_VK_LEN_SIZE: usize = 4; pub const VK_HASH_SIZE: usize = 66; -pub const ZKM_VERSION_SIZE: usize = ZKM_VERSION_BYTES_LEN; pub const TOTAL_WORK_SIZE: usize = 32; pub const CONSENSUS_BLOCK_HEIGHT_SIZE: usize = 4; @@ -44,7 +43,6 @@ pub const CONSENSUS_BLOCK_HEIGHT_SIZE: usize = 4; pub struct WatchtowerPublicOutputs { pub total_work: [u8; TOTAL_WORK_SIZE], pub consensus_block_height: [u8; CONSENSUS_BLOCK_HEIGHT_SIZE], - pub attested_part_stark_vk: Vec, } #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] @@ -52,7 +50,6 @@ pub struct OperatorPublicOutputs { pub btc_best_block_hash: [u8; 32], pub constant: [u8; 32], pub included_watchtowers: [u8; 32], - pub part_stark_vk: Vec, } pub fn watch_longest_chain( @@ -65,23 +62,17 @@ pub fn watch_longest_chain( spv: SPV, ) -> WatchtowerPublicOutputs { println!("commit header, size: {}", commit_chain.commits.len()); - // verify latest_sequencer_commit is valid: - // * Check both latest_sequencer_commit_txid and genesis_sequencer_commit_txid are in all_sequencer_commit_txids (which is a private input) - // * Check latest_sequencer_commit_txid is derived from genesis_sequencer_commit_txid - // verify the commit chain proof - verify_proof( - &commit_chain.zkm_proof, - &commit_chain.zkm_public_values, - &commit_chain.zkm_vk_hash, - &commit_chain.zkm_version, + let commit_chain_output = + verify_commit_chain_output(&commit_chain).expect("Failed to verify commit chain proof"); + let (publisher_public_keys, threshold) = + commit_chain_attestation_authority(&commit_chain_output); + verify_unique_part_stark_vk_witnesses( + &attestation.unique_witnesses, + publisher_public_keys, + threshold, + PART_STARK_VK_TREE_HEIGHT, ) - .expect("Failed to verify commit chain proof"); - - let prev_output = ZKMPublicValues::from(&commit_chain.zkm_public_values).read(); - let prev_proof = CommitChainPrevProofType::PrevProof(prev_output); - let CommitChainPrevProofType::PrevProof(commit_chain_output) = &prev_proof else { - panic!("Only PrevProof is supported in watch_longest_chain"); - }; + .expect("Failed to verify unique part_stark_vk attestations"); assert_eq!( commit_chain_output.chain_state.commit_txn.compute_txid(), @@ -91,11 +82,16 @@ pub fn watch_longest_chain( println!("header chain: applying: {}", header_chain.block_headers.len()); // verify header_chain is valid - verify_proof( + let header_part_stark_vk = attested_part_stark_vk_for_zkm_version( + &attestation.unique_witnesses, + &header_chain.zkm_version, + ) + .expect("Failed to resolve attested header-chain part_stark_vk"); + verify_proof_with_part_stark_vk( &header_chain.zkm_proof, &header_chain.zkm_public_values, &header_chain.zkm_vk_hash, - &header_chain.zkm_version, + &header_part_stark_vk, ) .expect("Failed to verify header chain proof"); @@ -108,11 +104,16 @@ pub fn watch_longest_chain( println!("SPV"); assert!(spv.verify(&btc_header_chain_output.chain_state.block_hashes_mmr)); - verify_proof( + let state_part_stark_vk = attested_part_stark_vk_for_zkm_version( + &attestation.unique_witnesses, + &state_chain.zkm_version, + ) + .expect("Failed to resolve attested state-chain part_stark_vk"); + verify_proof_with_part_stark_vk( &state_chain.zkm_proof, &state_chain.zkm_public_values, &state_chain.zkm_vk_hash, - &state_chain.zkm_version, + &state_part_stark_vk, ) .expect("Failed to verify state chain proof"); let prev_output = ZKMPublicValues::from(&state_chain.zkm_public_values).read(); @@ -120,34 +121,16 @@ pub fn watch_longest_chain( let StateChainPrevProofType::PrevProof(state_chain_output) = &prev_proof else { panic!("Only PrevProof is supported in watch_longest_chain"); }; - - verify_unique_part_stark_vk_witnesses( - &attestation.unique_witnesses, - &commit_chain_output.chain_state.publisher_public_keys, - commit_chain_output.chain_state.threshold, - PART_STARK_VK_TREE_HEIGHT, - ) - .expect("Failed to verify unique part_stark_vk attestations"); - assert_part_stark_vk_in_verified_witnesses( &attestation.unique_witnesses, &btc_header_chain_output.part_stark_vk, ) - .expect("Failed to match header-chain part_stark_vk in verified witnesses"); - assert_part_stark_vk_in_verified_witnesses( - &attestation.unique_witnesses, - &commit_chain_output.part_stark_vk, - ) - .expect("Failed to match commit-chain part_stark_vk in verified witnesses"); + .expect("Failed to match header-chain part_stark_vk in verified witnesses"); assert_part_stark_vk_in_verified_witnesses( &attestation.unique_witnesses, &state_chain_output.part_stark_vk, ) - .expect("Failed to match state-chain part_stark_vk in verified witnesses"); - - let attested_part_stark_vk = - get_current_part_stark_vk(&attestation.unique_witnesses, attestation.current_index) - .expect("Failed to read watchtower current part_stark_vk"); + .expect("Failed to match state-chain part_stark_vk in verified witnesses"); // check the signature. let cosmos_block_bytes = &state_chain_output.chain_state.latest_cosmos_block; @@ -175,7 +158,6 @@ pub fn watch_longest_chain( WatchtowerPublicOutputs { total_work: btc_header_chain_output.chain_state.total_work, consensus_block_height: commit_chain_output.chain_state.block_height.to_le_bytes(), - attested_part_stark_vk, } } @@ -218,18 +200,18 @@ pub fn propose_longest_chain( ) -> OperatorPublicOutputs { // verify operator_latest_sequencer_commit_txid is valid, and on operator head chain // * Check operator_latest_sequencer_commit_txid is derived from genesis_sequencer_commit_txid - verify_proof( - &commit_chain.zkm_proof, - &commit_chain.zkm_public_values, - &commit_chain.zkm_vk_hash, - &commit_chain.zkm_version, + let commit_chain_output = + verify_commit_chain_output(&commit_chain).expect("Failed to verify commit chain proof"); + let (publisher_public_keys, threshold) = + commit_chain_attestation_authority(&commit_chain_output); + verify_unique_part_stark_vk_witnesses( + &attestation.unique_witnesses, + publisher_public_keys, + threshold, + PART_STARK_VK_TREE_HEIGHT, ) - .expect("Failed to verify commit chain proof"); - let prev_output = ZKMPublicValues::from(&commit_chain.zkm_public_values).read(); - let prev_proof = CommitChainPrevProofType::PrevProof(prev_output); - let CommitChainPrevProofType::PrevProof(commit_chain_output) = &prev_proof else { - panic!("Only PrevProof is supported in propose_longest_chain"); - }; + .expect("Failed to verify unique part_stark_vk attestations"); + assert_eq!( commit_chain_output.chain_state.commit_txn.compute_txid(), spv_ss_commit.transaction.0.compute_txid() @@ -241,11 +223,16 @@ pub fn propose_longest_chain( // https://github.com/KSlashh/BitVM/blob/v2/goat/src/transactions/watchtower_challenge.rs#L128 // verify operator_header_chain is valid - verify_proof( + let header_part_stark_vk = attested_part_stark_vk_for_zkm_version( + &attestation.unique_witnesses, + &operator_header_chain.zkm_version, + ) + .expect("Failed to resolve attested header-chain part_stark_vk"); + verify_proof_with_part_stark_vk( &operator_header_chain.zkm_proof, &operator_header_chain.zkm_public_values, &operator_header_chain.zkm_vk_hash, - &operator_header_chain.zkm_version, + &header_part_stark_vk, ) .expect("Failed to verify header chain proof"); let prev_output = ZKMPublicValues::from(&operator_header_chain.zkm_public_values).read(); @@ -253,24 +240,11 @@ pub fn propose_longest_chain( let HeaderChainPrevProofType::PrevProof(btc_header_chain_output) = &prev_proof else { panic!("Only PrevProof is supported in propose_longest_chain"); }; - - verify_unique_part_stark_vk_witnesses( - &attestation.unique_witnesses, - &commit_chain_output.chain_state.publisher_public_keys, - commit_chain_output.chain_state.threshold, - PART_STARK_VK_TREE_HEIGHT, - ) - .expect("Failed to verify unique part_stark_vk attestations"); assert_part_stark_vk_in_verified_witnesses( &attestation.unique_witnesses, &btc_header_chain_output.part_stark_vk, ) - .expect("Failed to match header-chain part_stark_vk in verified witnesses"); - assert_part_stark_vk_in_verified_witnesses( - &attestation.unique_witnesses, - &commit_chain_output.part_stark_vk, - ) - .expect("Failed to match commit-chain part_stark_vk in verified witnesses"); + .expect("Failed to match header-chain part_stark_vk in verified witnesses"); let operator_total_work = btc_header_chain_output.chain_state.total_work; let operator_consensus_block_height = U32::from(commit_chain_output.chain_state.block_height); // commit header chain best block hash as pis @@ -289,105 +263,46 @@ pub fn propose_longest_chain( for i in 0..watchtower_challenge_txns.len() { if included_watchertowers_bits[i] { let tx = &watchtower_challenge_txns[i]; - println!("Verify watchtower[{i}] tx: {}, {:?}", tx.compute_txid(), tx); let prev_out = &watchtower_challenge_txn_prev_outs[i]; - let prev_index = tx.input[0].previous_output.vout as usize; let pubkey = &watchtower_challenge_txn_pubkey[i]; - - let sig = bitcoin::taproot::Signature::from_slice(&tx.input[0].witness[0]).unwrap(); - // check tx signature is valid - match verify_taproot_leaf_schnorr_signature( - &watchtower_challenge_txn_scripts[i], + let watchtower_outputs = verify_included_watchtower_challenge( + i, + &graph_id, tx, - prev_index, prev_out, + &watchtower_challenge_txn_scripts[i], pubkey, - &sig, - ) { - Ok(_) => {} - Err(msg) => { - println!("Watchtower[{i}] signature verification: {msg}"); - continue; - } - }; - - let commitment = &extract_data_from_commitment_outputs(&tx.output)[..]; - println!("commitment: {commitment:?}"); - println!("commitment hex: {}", hex::encode(commitment)); - let (parsed_graph_id, proof, public_values, vk, proof_part_stark_vk) = - match parse_watchtower_commitment(commitment) { - Ok(c) => c, - Err(err) => { - println!("Watchtower[{i}] parse commitment error, {err}"); - continue; - } - }; - - if parsed_graph_id != graph_id { - println!( - "Watchtower[{i}] invalid commitment: graph id: parsed = {}, expected = {}", - hex::encode(parsed_graph_id), - hex::encode(graph_id) - ); - continue; - } - println!("check total work with watchtower {i}"); - let watchtower_outputs = match parse_watchtower_public_outputs(&public_values) { - Ok(outputs) => outputs, - Err(err) => { - println!("Watchtower[{i}] public outputs parse error, {err}"); - continue; - } - }; - if let Err(err) = assert_part_stark_vk_in_verified_witnesses( &attestation.unique_witnesses, - &watchtower_outputs.attested_part_stark_vk, - ) { - println!("Watchtower[{i}] missing verified part_stark_vk: {err}"); - continue; - } - match verify_proof_with_part_stark_vk(&proof, &public_values, &vk, &proof_part_stark_vk) - { - Ok(_) => {} - Err(err) => { - println!("Watchtower[{i}] invalid proof: {err}"); - continue; - } - } + operator_total_work, + operator_consensus_block_height, + ) + .unwrap_or_else(|err| panic!("Watchtower[{i}] invalid included challenge: {err}")); - // extract ChainState - // check watchtower_chain_state.total_work <= operator_header_chain.total_work println!( "watchtower total work: {:?}", U256::from_be_bytes(watchtower_outputs.total_work) ); println!("operator total work: {operator_total_work:?}"); - println!( "watchtower_consensus_block_height : {:?}", U32::from_le_bytes(watchtower_outputs.consensus_block_height) ); println!("operator_consensus_block_height : {operator_consensus_block_height:?}"); - - assert!( - U256::from_be_bytes(watchtower_outputs.total_work) - <= U256::from_be_bytes(operator_total_work) - ); - // check watchtower.consensus.block_height <= consensus.block_height - assert!( - U32::from_le_bytes(watchtower_outputs.consensus_block_height) - <= operator_consensus_block_height - ); } } println!("verify el block"); - verify_proof( + let state_part_stark_vk = attested_part_stark_vk_for_zkm_version( + &attestation.unique_witnesses, + &state_chain.zkm_version, + ) + .expect("Failed to resolve attested state-chain part_stark_vk"); + verify_proof_with_part_stark_vk( &state_chain.zkm_proof, &state_chain.zkm_public_values, &state_chain.zkm_vk_hash, - &state_chain.zkm_version, + &state_part_stark_vk, ) .expect("Failed to verify state chain proof"); @@ -401,11 +316,7 @@ pub fn propose_longest_chain( &attestation.unique_witnesses, &state_chain_output.part_stark_vk, ) - .expect("Failed to match state-chain part_stark_vk in verified witnesses"); - - let current_part_stark_vk = - get_current_part_stark_vk(&attestation.unique_witnesses, attestation.current_index) - .expect("Failed to read operator current part_stark_vk"); + .expect("Failed to match state-chain part_stark_vk in verified witnesses"); // check the signature. let cosmos_block_bytes = &state_chain_output.chain_state.latest_cosmos_block; @@ -454,8 +365,8 @@ pub fn propose_longest_chain( // .iter() // .position(|header| header.compute_block_hash() == operator_committed_blockhash); //assert!(included.is_some(), "operator committed blockhash is not included in header chain"); - assert!( - operator_committed_blockhash == btc_best_block_hash, + assert_eq!( + operator_committed_blockhash, btc_best_block_hash, "operator committed blockhash is not included in header chain" ); @@ -464,7 +375,6 @@ pub fn propose_longest_chain( btc_best_block_hash: operator_committed_blockhash, constant, included_watchtowers: included_watchtowers.to_le_bytes::<32>(), - part_stark_vk: current_part_stark_vk, } } @@ -671,6 +581,112 @@ fn groth16_verifier_keys(zkm_version: &str) -> Result<(&'static [u8], &'static [ Ok((imm_groth16_vk, part_stark_vk)) } +/// Resolve the version-derived `part_stark_vk` and require it to be attested before use. +fn attested_part_stark_vk_for_zkm_version( + unique_witnesses: &[UniquePartStarkVkWitness], + zkm_version: &str, +) -> Result, String> { + let (_, part_stark_vk) = groth16_verifier_keys(zkm_version)?; + assert_part_stark_vk_in_verified_witnesses(unique_witnesses, part_stark_vk)?; + Ok(part_stark_vk.to_vec()) +} + +/// Verify one included watchtower challenge end-to-end and return its parsed public outputs. +fn verify_included_watchtower_challenge( + index: usize, + graph_id: &[u8; GRAPH_ID_SIZE], + tx: &Transaction, + prev_out: &TxOut, + script: &ScriptBuf, + pubkey: &PublicKey, + unique_witnesses: &[UniquePartStarkVkWitness], + operator_total_work: [u8; TOTAL_WORK_SIZE], + operator_consensus_block_height: U32, +) -> Result { + println!("Verify watchtower[{index}] tx: {}, {:?}", tx.compute_txid(), tx); + let input = tx + .input + .first() + .ok_or_else(|| "watchtower tx must contain at least one input".to_string())?; + let witness = input + .witness + .iter() + .next() + .ok_or_else(|| "watchtower tx witness must contain a taproot signature".to_string())?; + let sig = bitcoin::taproot::Signature::from_slice(witness.as_ref()) + .map_err(|err| format!("invalid taproot signature: {err}"))?; + let prev_index = input.previous_output.vout as usize; + verify_taproot_leaf_schnorr_signature(script, tx, prev_index, prev_out, pubkey, &sig) + .map_err(|err| format!("signature verification failed: {err}"))?; + + let commitment = extract_data_from_commitment_outputs(&tx.output); + println!("commitment: {commitment:?}"); + println!("commitment hex: {}", hex::encode(&commitment)); + + let (parsed_graph_id, proof, public_values, vk, proof_part_stark_vk) = + parse_watchtower_commitment(&commitment)?; + if parsed_graph_id != *graph_id { + return Err(format!( + "graph id mismatch: parsed={}, expected={}", + hex::encode(parsed_graph_id), + hex::encode(graph_id) + )); + } + assert_part_stark_vk_in_verified_witnesses(unique_witnesses, &proof_part_stark_vk)?; + verify_proof_with_part_stark_vk(&proof, &public_values, &vk, &proof_part_stark_vk)?; + + println!("check total work with watchtower {index}"); + let watchtower_outputs = parse_watchtower_public_outputs(&public_values)?; + if U256::from_be_bytes(watchtower_outputs.total_work) > U256::from_be_bytes(operator_total_work) + { + return Err("watchtower total work exceeds operator total work".to_string()); + } + if U32::from_le_bytes(watchtower_outputs.consensus_block_height) + > operator_consensus_block_height + { + return Err( + "watchtower consensus block height exceeds operator consensus block height".to_string() + ); + } + Ok(watchtower_outputs) +} + +/// Verify commit-chain with the trusted base-layer verifier and return its output. +fn verify_commit_chain_output( + commit_chain: &CommitChainCircuitInput, +) -> Result { + let trusted_part_stark_vk = commit_chain::trusted_commit_chain_part_stark_vk(); + verify_proof_with_part_stark_vk( + &commit_chain.zkm_proof, + &commit_chain.zkm_public_values, + &commit_chain.zkm_vk_hash, + &trusted_part_stark_vk, + )?; + + let output = match &commit_chain.prev_proof { + CommitChainPrevProofType::PrevProof(_) => { + ZKMPublicValues::from(&commit_chain.zkm_public_values).read() + } + CommitChainPrevProofType::GenesisBlock => { + return Err( + "Only PrevProof is supported when verifying commit-chain output".to_string() + ); + } + }; + + Ok(output) +} + +/// Return the publisher set that authorizes part_stark_vk attestations for this commit-chain output. +fn commit_chain_attestation_authority( + commit_chain_output: &CommitChainCircuitOutput, +) -> (&[PublicKey], u16) { + ( + &commit_chain_output.chain_state.publisher_public_keys, + commit_chain_output.chain_state.threshold, + ) +} + pub fn verify_proof( proof: &[u8], zkm_public_values: &[u8], @@ -702,21 +718,11 @@ pub fn verify_proof_with_part_stark_vk( } } -pub fn verify_proof_fixed_version( - proof: &[u8], - zkm_public_values: &[u8], - zkm_vk_hash: &[u8], - zkm_version: &ZkmVersionBytes, -) -> Result<(), String> { - let decoded_zkm_version = decode_zkm_version_fixed(zkm_version)?; - verify_proof(proof, zkm_public_values, zkm_vk_hash, &decoded_zkm_version) -} - #[cfg(test)] mod tests { use super::*; + use crate::PartStarkVkAttestationBundle; use bitcoin::Transaction; - use zkm_version::encode_zkm_version_fixed; const PROOF: &[u8] = include_bytes!("../../../circuits/data/watchtower/output3.bin.proof.bin"); const PUBLIC_INPUTS: &[u8] = include_bytes!("../../../circuits/data/watchtower/output3.bin.public_inputs.bin"); @@ -744,12 +750,10 @@ mod tests { let total_work = 1006120u64; let block_height = 503043u32; - let attested_part_stark_vk = vec![7u8; 44]; let proof_part_stark_vk = vec![8u8; 52]; let expected_outputs = WatchtowerPublicOutputs { total_work: U256::from(total_work).to_be_bytes(), consensus_block_height: U32::from(block_height).to_le_bytes(), - attested_part_stark_vk: attested_part_stark_vk.clone(), }; let public_inputs = bincode::serialize(&expected_outputs).unwrap(); println!("public inputs: {:?}", PUBLIC_INPUTS.len()); @@ -830,7 +834,9 @@ mod tests { legacy.extend_from_slice(&(PUBLIC_INPUTS.len() as u32).to_le_bytes()); legacy.extend_from_slice(PUBLIC_INPUTS); legacy.extend_from_slice(VK_HASH.as_bytes()); - legacy.extend_from_slice(&encode_zkm_version_fixed(ZKM_VERSION).unwrap()); + let mut legacy_zkm_version = [0u8; 16]; + legacy_zkm_version[..ZKM_VERSION.len()].copy_from_slice(ZKM_VERSION.as_bytes()); + legacy.extend_from_slice(&legacy_zkm_version); assert!(parse_watchtower_commitment(&legacy).is_err()); } @@ -910,7 +916,6 @@ mod tests { let expected = WatchtowerPublicOutputs { total_work: [9u8; TOTAL_WORK_SIZE], consensus_block_height: 123u32.to_le_bytes(), - attested_part_stark_vk: vec![7u8; 44], }; let public_inputs = bincode::serialize(&expected).unwrap(); @@ -939,4 +944,98 @@ mod tests { let result = groth16_verifier_keys("v0.0.0-test"); assert!(result.is_err()); } + + fn sample_unique_witness(part_stark_vk: Vec) -> PartStarkVkAttestationBundle { + PartStarkVkAttestationBundle { + part_stark_vk, + leaf_index: 0, + merkle_path: vec![], + root: [0u8; 32], + threshold: 1, + publisher_set_id: [0u8; 32], + signatures: vec![], + } + } + + #[test] + fn test_attested_part_stark_vk_for_zkm_version_accepts_verified_witness_payload() { + let part_stark_vk = groth16_verifier_keys(ZKM_VERSION).unwrap().1.to_vec(); + let unique_witnesses = vec![sample_unique_witness(part_stark_vk.clone())]; + + assert_eq!( + attested_part_stark_vk_for_zkm_version(&unique_witnesses, ZKM_VERSION).unwrap(), + part_stark_vk + ); + } + + #[test] + fn test_attested_part_stark_vk_for_zkm_version_rejects_missing_witness_payload() { + let unique_witnesses = vec![sample_unique_witness(vec![7u8; 32])]; + + assert!(attested_part_stark_vk_for_zkm_version(&unique_witnesses, ZKM_VERSION).is_err()); + } + + fn sample_commit_tx() -> Transaction { + use bitcoin::{absolute::LockTime, transaction::Version}; + + Transaction { + version: Version::TWO, + lock_time: LockTime::ZERO, + input: vec![], + output: vec![], + } + } + + fn sample_commit_chain_output( + genesis_txid: [u8; 32], + commit_txn: Transaction, + publisher_public_keys: Vec, + threshold: u16, + ) -> CommitChainCircuitOutput { + CommitChainCircuitOutput { + chain_state: commit_chain::CommitChainState { + block_height: 7, + commit_txn, + genesis_txid, + sequencers: vec![], + publisher_public_keys, + threshold, + }, + } + } + + #[test] + fn test_commit_chain_attestation_authority_uses_chain_state() { + let publisher_public_keys = + commit_chain::create_dummy_publisher_keys(3, bitcoin::Network::Regtest) + .into_iter() + .map(|(_, pk)| pk) + .collect::>(); + let threshold = 2u16; + let commit_chain_output = sample_commit_chain_output( + [3u8; 32], + sample_commit_tx(), + publisher_public_keys.clone(), + threshold, + ); + + let (actual_keys, actual_threshold) = + commit_chain_attestation_authority(&commit_chain_output); + assert_eq!(actual_keys, publisher_public_keys.as_slice()); + assert_eq!(actual_threshold, threshold); + } + + #[test] + fn test_operator_public_outputs_bincode_shape_excludes_part_stark_vk() { + let expected = OperatorPublicOutputs { + btc_best_block_hash: [1u8; 32], + constant: [2u8; 32], + included_watchtowers: [3u8; 32], + }; + + let public_inputs = bincode::serialize(&expected).unwrap(); + let parsed: OperatorPublicOutputs = bincode::deserialize(&public_inputs).unwrap(); + + assert_eq!(parsed, expected); + } } diff --git a/crates/bitvm2-ga/src/tests.rs b/crates/bitvm2-ga/src/tests.rs index 9aa9cb73..4a254c18 100644 --- a/crates/bitvm2-ga/src/tests.rs +++ b/crates/bitvm2-ga/src/tests.rs @@ -429,10 +429,6 @@ mod tests { (guest_pubs, proof, pis, vk) } - fn get_test_operator_proof() { - // data/operator-proof/output.bin.* - } - async fn gen_test_graph( esplora: &EsploraClient, disprove_scripts: Vec, @@ -568,7 +564,6 @@ mod tests { .collect(), hashlocks: hashlocks().1.to_vec(), guest_constant_value: [0u8; 32], // all zero for test - zkm_version: "v1.2.3".to_string(), }; generate_bitvm_graph(graph_parameters, disprove_scripts).unwrap() @@ -996,12 +991,11 @@ mod tests { include_bytes!("../../../circuits/data/watchtower/output3.bin.public_inputs.bin"); const VK_HASH: &str = include_str!("../../../circuits/data/watchtower/output3.bin.vk_hash.bin"); - let proof_part_stark_vk = - bitcoin_light_client_circuit::parse_watchtower_public_outputs(PUBLIC_INPUTS) - .unwrap() - .attested_part_stark_vk; + const PROOF_PART_STARK_VK: &[u8] = + include_bytes!("../../../circuits/data/watchtower/output3.bin.proof_part_stark_vk.bin"); + let proof_part_stark_vk = PROOF_PART_STARK_VK.to_vec(); - let graph_id = hex::decode("00112233445566778899aabbccddeeff").unwrap().try_into().unwrap(); //graph.parameters.graph_id.to_bytes_le(); + let graph_id = *graph.parameters.graph_id.as_bytes(); //let total_work = 1006120; //let consensus_commit_block_height = 503043; let comm = bitcoin_light_client_circuit::build_watchtower_commitment( diff --git a/crates/bitvm2-ga/src/types.rs b/crates/bitvm2-ga/src/types.rs index ab41581a..5229ab89 100644 --- a/crates/bitvm2-ga/src/types.rs +++ b/crates/bitvm2-ga/src/types.rs @@ -110,7 +110,6 @@ pub struct Bitvm2GraphParameters { pub watchtower_pubkeys: Vec, pub hashlocks: Vec<[u8; 20]>, // one for each watchtower pub guest_constant_value: [u8; 32], - pub zkm_version: String, } impl Bitvm2InstanceParameters { diff --git a/crates/commit-chain/Cargo.toml b/crates/commit-chain/Cargo.toml index 87e10883..05a2c247 100644 --- a/crates/commit-chain/Cargo.toml +++ b/crates/commit-chain/Cargo.toml @@ -15,7 +15,6 @@ guest-executor = { workspace = true } # Ziren zkm-verifier = { workspace = true } zkm-zkvm = { workspace = true } -zkm-version = { workspace = true } #zkm-verifier = { path = "../../../Ziren/crates/verifier" } #zkm-zkvm = { path = "../../../Ziren/crates/zkvm/entrypoint", features = ["verify"] } diff --git a/crates/commit-chain/src/commit_chain.rs b/crates/commit-chain/src/commit_chain.rs index 78273bd6..18e3519a 100644 --- a/crates/commit-chain/src/commit_chain.rs +++ b/crates/commit-chain/src/commit_chain.rs @@ -15,6 +15,10 @@ use bitcoin::{Transaction, TxOut, Witness, secp256k1::PublicKey}; pub struct CommitInfo { pub threshold: u16, pub publisher_public_keys: Vec, + #[serde(default)] + pub next_threshold: Option, + #[serde(default)] + pub next_publisher_public_keys: Option>, pub txid: String, pub genesis_txid: String, pub sequencers: Vec, @@ -34,10 +38,24 @@ pub struct CircuitCommit { pub genesis_txid: [u8; 32], pub publisher_public_keys: Vec, pub threshold: u16, + #[serde(default)] + pub next_publisher_public_keys: Option>, + #[serde(default)] + pub next_threshold: Option, pub sequencers: Vec, pub block_height: u32, // Bitcoin block height of current commitment } +impl CommitInfo { + /// Return the publisher set that becomes active after this commit is mined. + pub fn active_publisher_set(&self) -> (&[String], u16) { + match (self.next_publisher_public_keys.as_deref(), self.next_threshold) { + (Some(next_keys), Some(next_threshold)) => (next_keys, next_threshold), + _ => (&self.publisher_public_keys, self.threshold), + } + } +} + #[derive(Serialize, Deserialize, PartialEq, Clone, Debug)] pub struct SequencerInfo { /// Validator account address @@ -83,15 +101,23 @@ pub struct CommitChainState { pub threshold: u16, } +impl CircuitCommit { + /// Return the publisher set that is committed into this tx's next update connector. + pub fn active_publisher_set(&self) -> (&[PublicKey], u16) { + match (self.next_publisher_public_keys.as_deref(), self.next_threshold) { + (Some(next_keys), Some(next_threshold)) => (next_keys, next_threshold), + _ => (&self.publisher_public_keys, self.threshold), + } + } +} + pub const PROOF_SIZE: usize = 260; pub const PUBLIC_INPUTS_SIZE: usize = 36; pub const VK_HASH_SIZE: usize = 66; -pub const ZKM_VERSION_SIZE: usize = zkm_version::ZKM_VERSION_BYTES_LEN; #[derive(Serialize, Deserialize, PartialEq, Clone, Debug)] pub struct CommitChainCircuitOutput { pub chain_state: CommitChainState, - pub part_stark_vk: Vec, } #[derive(Serialize, Deserialize, PartialEq, Clone, Debug)] @@ -131,8 +157,7 @@ impl CommitChainState { for commit in &commits { let mut latest_commit_txn_with_wtns = commit.commit_txn.clone(); let latest_sequencers = &commit.sequencers; - let publisher_public_keys = &commit.publisher_public_keys; - let threshold = commit.threshold; + let (next_publisher_public_keys, next_threshold) = commit.active_publisher_set(); assert_eq!(commit.genesis_txid, self.genesis_txid); @@ -160,23 +185,35 @@ impl CommitChainState { let prev_commit_txid = prev_commit_txn_value.compute_txid(); assert_eq!(update_connector.previous_output.txid, prev_commit_txid); assert_eq!(update_connector.previous_output.vout, 0); - // check the latest publishing txn's signature is signed by prev publishers + // Verify that the spending witness matches the publisher set committed by the + // previous update connector. let prevout = &prev_commit_txn_value.output[0]; let redeem_script = crate::create_sequencer_update_script( - &publisher_public_keys[..], - threshold as usize, + &self.publisher_public_keys[..], + self.threshold as usize, ); crate::publisher::verify_p2wsh_multisig_witness( &latest_commit_txn_with_wtns, 0, prevout, &redeem_script, - publisher_public_keys, - threshold as usize, + &self.publisher_public_keys, + self.threshold as usize, ) .unwrap(); } + let expected_next_connector_script = crate::create_sequencer_update_script( + next_publisher_public_keys, + next_threshold as usize, + ); + let expected_next_connector_script_pubkey = + bitcoin::ScriptBuf::new_p2wsh(&expected_next_connector_script.wscript_hash()); + assert_eq!( + latest_commit_txn_with_wtns.output[0].script_pubkey, + expected_next_connector_script_pubkey + ); + // remove witness latest_commit_txn_with_wtns.input.iter_mut().for_each(|input| { input.witness = Witness::new(); @@ -184,8 +221,8 @@ impl CommitChainState { self.sequencers = latest_sequencers.clone(); self.commit_txn = latest_commit_txn_with_wtns.clone(); - self.publisher_public_keys = publisher_public_keys.clone(); - self.threshold = threshold; + self.publisher_public_keys = next_publisher_public_keys.to_vec(); + self.threshold = next_threshold; self.block_height = commit.block_height; } } @@ -233,7 +270,14 @@ pub fn extract_op_return_data(tx_output: &[TxOut]) -> Vec { #[cfg(test)] mod tests { use super::*; + use crate::{ + create_dummy_publisher_keys, create_sequencer_update_script, finalize, sign_partial, + }; use bitcoin::{Amount, ScriptBuf}; + use bitcoin::{ + EcdsaSighashType, OutPoint, Sequence, TxIn, Witness, absolute::LockTime, + transaction::Version, + }; #[test] fn test_extract_op_return() { // Example: construct a fake tx with OP_RETURN @@ -275,4 +319,188 @@ mod tests { chain_state.commit_txn.compute_txid() ); } + + #[test] + fn test_apply_commit_tracks_next_publisher_set_as_active_state() { + let current_keys = create_dummy_publisher_keys(3, bitcoin::Network::Regtest); + let current_pubkeys: Vec = current_keys.iter().map(|(_, pk)| *pk).collect(); + let next_keys = create_dummy_publisher_keys(4, bitcoin::Network::Regtest); + let next_pubkeys: Vec = next_keys.iter().map(|(_, pk)| *pk).collect(); + let final_keys = create_dummy_publisher_keys(5, bitcoin::Network::Regtest); + let final_pubkeys: Vec = final_keys.iter().map(|(_, pk)| *pk).collect(); + + let current_threshold = 2u16; + let next_threshold = 3u16; + let final_threshold = 4u16; + let empty_sequencers = vec![]; + let commit0_op_return = if let tendermint_light_client_verifier::types::Hash::Sha256(hash) = + sequencer_hash(&empty_sequencers) + { + ScriptBuf::new_op_return(&hash) + } else { + panic!("expected sha256 sequencer hash"); + }; + let commit0 = Transaction { + version: Version::TWO, + lock_time: LockTime::ZERO, + input: vec![], + output: vec![ + TxOut { + value: Amount::from_sat(100_000), + script_pubkey: ScriptBuf::new_p2wsh( + &create_sequencer_update_script( + ¤t_pubkeys, + current_threshold as usize, + ) + .wscript_hash(), + ), + }, + TxOut { value: Amount::ZERO, script_pubkey: commit0_op_return }, + ], + }; + let mut genesis_txid = [0u8; 32]; + genesis_txid.copy_from_slice(commit0.compute_txid().as_raw_hash().as_ref()); + + let commit0_info = CircuitCommit { + commit_txn: commit0.clone(), + genesis_txid, + publisher_public_keys: vec![], + threshold: 0, + next_publisher_public_keys: Some(current_pubkeys.clone()), + next_threshold: Some(current_threshold), + sequencers: empty_sequencers.clone(), + block_height: 1, + }; + + let commit1_redeem_script = + create_sequencer_update_script(¤t_pubkeys, current_threshold as usize); + let commit1_op_return = if let tendermint_light_client_verifier::types::Hash::Sha256(hash) = + sequencer_hash(&empty_sequencers) + { + ScriptBuf::new_op_return(&hash) + } else { + panic!("expected sha256 sequencer hash"); + }; + let mut commit1 = Transaction { + version: Version::TWO, + lock_time: LockTime::ZERO, + input: vec![TxIn { + previous_output: OutPoint::new(commit0.compute_txid(), 0), + script_sig: ScriptBuf::new(), + sequence: Sequence::MAX, + witness: Witness::default(), + }], + output: vec![ + TxOut { + value: Amount::from_sat(90_000), + script_pubkey: ScriptBuf::new_p2wsh( + &create_sequencer_update_script(&next_pubkeys, next_threshold as usize) + .wscript_hash(), + ), + }, + TxOut { value: Amount::ZERO, script_pubkey: commit1_op_return }, + ], + }; + let (sig1, _) = sign_partial( + &mut commit1, + ¤t_keys[0].0, + &commit1_redeem_script, + Amount::from_sat(100_000), + EcdsaSighashType::All, + ) + .unwrap(); + let (sig2, _) = sign_partial( + &mut commit1, + ¤t_keys[1].0, + &commit1_redeem_script, + Amount::from_sat(100_000), + EcdsaSighashType::All, + ) + .unwrap(); + finalize(&mut commit1, vec![sig1, sig2], &commit1_redeem_script).unwrap(); + let commit1_info = CircuitCommit { + commit_txn: commit1.clone(), + genesis_txid, + publisher_public_keys: current_pubkeys.clone(), + threshold: current_threshold, + next_publisher_public_keys: Some(next_pubkeys.clone()), + next_threshold: Some(next_threshold), + sequencers: empty_sequencers.clone(), + block_height: 2, + }; + + let commit2_redeem_script = + create_sequencer_update_script(&next_pubkeys, next_threshold as usize); + let commit2_op_return = if let tendermint_light_client_verifier::types::Hash::Sha256(hash) = + sequencer_hash(&empty_sequencers) + { + ScriptBuf::new_op_return(&hash) + } else { + panic!("expected sha256 sequencer hash"); + }; + let mut commit2 = Transaction { + version: Version::TWO, + lock_time: LockTime::ZERO, + input: vec![TxIn { + previous_output: OutPoint::new(commit1.compute_txid(), 0), + script_sig: ScriptBuf::new(), + sequence: Sequence::MAX, + witness: Witness::default(), + }], + output: vec![ + TxOut { + value: Amount::from_sat(80_000), + script_pubkey: ScriptBuf::new_p2wsh( + &create_sequencer_update_script(&final_pubkeys, final_threshold as usize) + .wscript_hash(), + ), + }, + TxOut { value: Amount::ZERO, script_pubkey: commit2_op_return }, + ], + }; + let (sig3, _) = sign_partial( + &mut commit2, + &next_keys[0].0, + &commit2_redeem_script, + Amount::from_sat(90_000), + EcdsaSighashType::All, + ) + .unwrap(); + let (sig4, _) = sign_partial( + &mut commit2, + &next_keys[1].0, + &commit2_redeem_script, + Amount::from_sat(90_000), + EcdsaSighashType::All, + ) + .unwrap(); + let (sig5, _) = sign_partial( + &mut commit2, + &next_keys[2].0, + &commit2_redeem_script, + Amount::from_sat(90_000), + EcdsaSighashType::All, + ) + .unwrap(); + finalize(&mut commit2, vec![sig3, sig4, sig5], &commit2_redeem_script).unwrap(); + let commit2_info = CircuitCommit { + commit_txn: commit2.clone(), + genesis_txid, + publisher_public_keys: next_pubkeys.clone(), + threshold: next_threshold, + next_publisher_public_keys: Some(final_pubkeys.clone()), + next_threshold: Some(final_threshold), + sequencers: empty_sequencers, + block_height: 3, + }; + + let mut chain_state = CommitChainState::new(genesis_txid); + chain_state.apply_commit(vec![commit0_info]); + assert_eq!(chain_state.publisher_public_keys, current_pubkeys); + assert_eq!(chain_state.threshold, current_threshold); + + chain_state.apply_commit(vec![commit1_info, commit2_info]); + assert_eq!(chain_state.publisher_public_keys, final_pubkeys); + assert_eq!(chain_state.threshold, final_threshold); + } } diff --git a/crates/commit-chain/src/lib.rs b/crates/commit-chain/src/lib.rs index 550f02a6..bc9d5d37 100644 --- a/crates/commit-chain/src/lib.rs +++ b/crates/commit-chain/src/lib.rs @@ -4,8 +4,15 @@ mod commit_chain; pub use commit_chain::*; use zkm_verifier::{Groth16Verifier, IMM_GROTH16_VK_BYTES}; +pub const TRUSTED_COMMIT_CHAIN_ZKM_VERSION: &str = "v1.2.5"; + +/// Return the fixed `part_stark_vk` used by commit-chain's internal recursive verifier. +pub fn trusted_commit_chain_part_stark_vk() -> Vec { + Groth16Verifier::get_part_stark_vk(TRUSTED_COMMIT_CHAIN_ZKM_VERSION).to_vec() +} + pub fn commit_chain_circuit(input: CommitChainCircuitInput) -> CommitChainCircuitOutput { - let current_part_stark_vk = Groth16Verifier::get_part_stark_vk(&input.zkm_version).to_vec(); + let current_part_stark_vk = trusted_commit_chain_part_stark_vk(); let mut chain_state = match input.prev_proof { CommitChainPrevProofType::GenesisBlock => { CommitChainState::new(input.commits[0].genesis_txid) @@ -14,6 +21,7 @@ pub fn commit_chain_circuit(input: CommitChainCircuitInput) -> CommitChainCircui println!("verify commit chain of prev proof"); let groth16_vk = *IMM_GROTH16_VK_BYTES; let zkm_vk_hash = String::from_utf8(input.zkm_vk_hash.to_vec()).unwrap(); + assert_eq!(input.zkm_version, TRUSTED_COMMIT_CHAIN_ZKM_VERSION); Groth16Verifier::verify_by_imm_groth16_vk( &input.zkm_proof, &input.zkm_public_values, @@ -27,5 +35,5 @@ pub fn commit_chain_circuit(input: CommitChainCircuitInput) -> CommitChainCircui }; chain_state.apply_commit(input.commits); - CommitChainCircuitOutput { chain_state, part_stark_vk: current_part_stark_vk } + CommitChainCircuitOutput { chain_state } } diff --git a/crates/commit-chain/src/publisher.rs b/crates/commit-chain/src/publisher.rs index d69239f5..193a3d86 100644 --- a/crates/commit-chain/src/publisher.rs +++ b/crates/commit-chain/src/publisher.rs @@ -86,6 +86,11 @@ pub fn verify_p2wsh_multisig_witness( let secp = Secp256k1::verification_only(); let txin = &tx.input[input_index]; let witness: &Witness = &txin.witness; + let expected_script_pubkey = ScriptBuf::new_p2wsh(&redeem_script.wscript_hash()); + + if prevout.script_pubkey != expected_script_pubkey { + return Err("prevout script_pubkey does not match redeem_script".into()); + } // Expect witness: [, sig1, sig2, ..., redeem_script_bytes] if witness.len() < 2 { @@ -261,4 +266,57 @@ mod tests { assert!(ok, "2-of-3 multisig witness should verify"); } + + #[test] + fn test_verify_p2wsh_multisig_witness_rejects_prevout_script_mismatch() { + let keys = create_dummy_publisher_keys(3, bitcoin::Network::Regtest); + let pubkeys: Vec = keys.iter().map(|(_, pk)| *pk).collect(); + let threshold = 2; + let redeem_script = create_sequencer_update_script(&pubkeys, threshold); + let prev_value = Amount::from_sat(100_000); + let prevout = TxOut { + value: prev_value, + script_pubkey: ScriptBuf::new_p2wsh(&ScriptBuf::new().wscript_hash()), + }; + let prev_outpoint = + OutPoint { txid: bitcoin::Txid::from_byte_array([0u8; 32].into()), vout: 0 }; + + let mut tx = Transaction { + version: Version::TWO, + lock_time: LockTime::ZERO, + input: vec![TxIn { + previous_output: prev_outpoint, + script_sig: ScriptBuf::new(), + sequence: Sequence::MAX, + witness: Witness::default(), + }], + output: vec![TxOut { + value: Amount::from_sat(99_000), + script_pubkey: { + let btc_pk0 = bitcoin::PublicKey::from(pubkeys[0]); + Address::p2pkh(&btc_pk0, Network::Testnet).script_pubkey() + }, + }], + }; + + let (sig1, _) = + sign_partial(&mut tx, &keys[0].0, &redeem_script, prev_value, EcdsaSighashType::All) + .unwrap(); + let (sig2, _) = + sign_partial(&mut tx, &keys[1].0, &redeem_script, prev_value, EcdsaSighashType::All) + .unwrap(); + finalize(&mut tx, vec![sig1, sig2], &redeem_script).unwrap(); + + assert!( + verify_p2wsh_multisig_witness( + &tx, + 0, + &prevout, + &redeem_script, + &pubkeys, + threshold as usize, + ) + .is_err() + ); + } } diff --git a/crates/header-chain/Cargo.toml b/crates/header-chain/Cargo.toml index d8da991a..9c65f27a 100644 --- a/crates/header-chain/Cargo.toml +++ b/crates/header-chain/Cargo.toml @@ -12,7 +12,6 @@ serde = { workspace = true, default-features = false } crypto-bigint = { version = "0.5.5", default-features = false } zkm-zkvm = { workspace = true } zkm-verifier = { workspace = true } -zkm-version = { workspace = true } [dev-dependencies] hex-literal = "1.0.0" diff --git a/crates/header-chain/src/header_chain.rs b/crates/header-chain/src/header_chain.rs index 3a6e5538..cd7f452a 100644 --- a/crates/header-chain/src/header_chain.rs +++ b/crates/header-chain/src/header_chain.rs @@ -91,8 +91,6 @@ pub const NETWORK_CONSTANTS: NetworkConstants = { } }; -pub const ZKM_VERSION_SIZE: usize = zkm_version::ZKM_VERSION_BYTES_LEN; - /// An epoch should be two weeks (represented as number of seconds) /// seconds/minute * minutes/hour * hours/day * 14 days const EXPECTED_EPOCH_TIMESPAN: u32 = 60 * 60 * 24 * 14; diff --git a/crates/state-chain/Cargo.toml b/crates/state-chain/Cargo.toml index 44d2d33c..c7a1aa50 100644 --- a/crates/state-chain/Cargo.toml +++ b/crates/state-chain/Cargo.toml @@ -15,7 +15,6 @@ header-chain = { path = "../header-chain" } # Ziren zkm-verifier = { workspace = true } zkm-zkvm = { workspace = true } -zkm-version = { workspace = true } #zkm-verifier = { path = "../../../Ziren/crates/verifier" } #zkm-zkvm = { path = "../../../Ziren/crates/zkvm/entrypoint", features = ["verify"] } diff --git a/crates/state-chain/src/state_chain.rs b/crates/state-chain/src/state_chain.rs index 1949af37..ce735638 100644 --- a/crates/state-chain/src/state_chain.rs +++ b/crates/state-chain/src/state_chain.rs @@ -10,7 +10,6 @@ use tendermint_light_client_verifier::types::LightBlock; // Contract address, base slot and key, the expected value of the slot is hardcoded to 1. type WithdrawalSlot = (Address, [u8; 32], Vec<[u8; 16]>); -pub const ZKM_VERSION_SIZE: usize = zkm_version::ZKM_VERSION_BYTES_LEN; /// The input proof of the commit chain circuit. /// The proof can be either None (implying the beginning) or a Succinct proof. diff --git a/crates/store/.sqlx/query-0d2299e1894169e179a5716f3a9e5cc2bce15d8facaf649e25d9919fb26f103e.json b/crates/store/.sqlx/query-a574aa126ca49083135ef445cb213379bf8df51054958887f27081ff7f8f47cc.json similarity index 68% rename from crates/store/.sqlx/query-0d2299e1894169e179a5716f3a9e5cc2bce15d8facaf649e25d9919fb26f103e.json rename to crates/store/.sqlx/query-a574aa126ca49083135ef445cb213379bf8df51054958887f27081ff7f8f47cc.json index 2e02efd9..a5cebc2d 100644 --- a/crates/store/.sqlx/query-0d2299e1894169e179a5716f3a9e5cc2bce15d8facaf649e25d9919fb26f103e.json +++ b/crates/store/.sqlx/query-a574aa126ca49083135ef445cb213379bf8df51054958887f27081ff7f8f47cc.json @@ -1,12 +1,12 @@ { "db_name": "SQLite", - "query": "INSERT OR\n REPLACE INTO graph (graph_id, instance_id, kickoff_index, from_addr, to_addr, amount, challenge_amount,\n status, sub_status, operator_pubkey, cur_prekickoff_txid, next_prekickoff, force_skip_kickoff_txid,\n quick_challenge_txid, challenge_incomplete_kickoff_txid, pegin_txid, kickoff_txid, take1_txid,\n challenge_txid, take2_txid, disprove_txid, watchtower_challenge_init_txid, watchtower_challenge_timeout_txids, nack_txids,\n blockhash_commit_timeout_txid, assert_init_txid, assert_commit_timeout_txids, init_withdraw_tx_hash,\n bridge_out_start_at, zkm_version, status_updated_at, proceed_withdraw_height, created_at, updated_at)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", + "query": "INSERT OR\n REPLACE INTO graph (graph_id, instance_id, kickoff_index, from_addr, to_addr, amount, challenge_amount,\n status, sub_status, operator_pubkey, cur_prekickoff_txid, next_prekickoff, force_skip_kickoff_txid,\n quick_challenge_txid, challenge_incomplete_kickoff_txid, pegin_txid, kickoff_txid, take1_txid,\n challenge_txid, take2_txid, disprove_txid, watchtower_challenge_init_txid, watchtower_challenge_timeout_txids, nack_txids,\n blockhash_commit_timeout_txid, assert_init_txid, assert_commit_timeout_txids, init_withdraw_tx_hash,\n bridge_out_start_at, status_updated_at, proceed_withdraw_height, created_at, updated_at)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", "describe": { "columns": [], "parameters": { - "Right": 34 + "Right": 33 }, "nullable": [] }, - "hash": "0d2299e1894169e179a5716f3a9e5cc2bce15d8facaf649e25d9919fb26f103e" + "hash": "a574aa126ca49083135ef445cb213379bf8df51054958887f27081ff7f8f47cc" } diff --git a/crates/store/migrations/20260406120000_drop_graph_zkm_version.sql b/crates/store/migrations/20260406120000_drop_graph_zkm_version.sql new file mode 100644 index 00000000..3938b9ba --- /dev/null +++ b/crates/store/migrations/20260406120000_drop_graph_zkm_version.sql @@ -0,0 +1,2 @@ +-- Drop graph-level zkm_version because version semantics now live on proofs only +ALTER TABLE graph DROP COLUMN `zkm_version`; diff --git a/crates/store/src/localdb.rs b/crates/store/src/localdb.rs index 5acc76ab..32f2d60f 100644 --- a/crates/store/src/localdb.rs +++ b/crates/store/src/localdb.rs @@ -1107,8 +1107,8 @@ impl<'a> StorageProcessor<'a> { quick_challenge_txid, challenge_incomplete_kickoff_txid, pegin_txid, kickoff_txid, take1_txid, challenge_txid, take2_txid, disprove_txid, watchtower_challenge_init_txid, watchtower_challenge_timeout_txids, nack_txids, blockhash_commit_timeout_txid, assert_init_txid, assert_commit_timeout_txids, init_withdraw_tx_hash, - bridge_out_start_at, zkm_version, status_updated_at, proceed_withdraw_height, created_at, updated_at) - VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", + bridge_out_start_at, status_updated_at, proceed_withdraw_height, created_at, updated_at) + VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", graph.graph_id, graph.instance_id, graph.kickoff_index, @@ -1138,7 +1138,6 @@ impl<'a> StorageProcessor<'a> { assert_commit_timeout_txids_json, graph.init_withdraw_tx_hash, graph.bridge_out_start_at, - graph.zkm_version, graph.status_updated_at, graph.proceed_withdraw_height, graph.created_at, diff --git a/crates/store/src/schema.rs b/crates/store/src/schema.rs index 9d94029f..c40da0cd 100644 --- a/crates/store/src/schema.rs +++ b/crates/store/src/schema.rs @@ -408,7 +408,6 @@ pub struct Graph { pub assert_commit_timeout_txids: Vec, pub init_withdraw_tx_hash: Option, pub bridge_out_start_at: i64, - pub zkm_version: String, pub status_updated_at: i64, pub proceed_withdraw_height: i64, pub created_at: i64, diff --git a/crates/zkm-version/Cargo.toml b/crates/zkm-version/Cargo.toml deleted file mode 100644 index 5f24ec48..00000000 --- a/crates/zkm-version/Cargo.toml +++ /dev/null @@ -1,10 +0,0 @@ -[package] -name = "zkm-version" -version.workspace = true -edition.workspace = true - -[dependencies] -anyhow = { workspace = true } - -[lints] -workspace = true diff --git a/crates/zkm-version/src/lib.rs b/crates/zkm-version/src/lib.rs deleted file mode 100644 index 254200d8..00000000 --- a/crates/zkm-version/src/lib.rs +++ /dev/null @@ -1,108 +0,0 @@ -use anyhow::{Context, Result}; - -pub const ZKM_VERSION_BYTES_LEN: usize = 16; -pub type ZkmVersionBytes = [u8; ZKM_VERSION_BYTES_LEN]; - -pub fn encode_zkm_version_fixed(version: &str) -> Result { - let raw = version.as_bytes(); - if raw.is_empty() { - return Err("zkm_version is empty".to_string()); - } - if raw.len() > ZKM_VERSION_BYTES_LEN { - return Err(format!( - "zkm_version '{}' too long: {} > {}", - version, - raw.len(), - ZKM_VERSION_BYTES_LEN - )); - } - - let mut encoded = [0u8; ZKM_VERSION_BYTES_LEN]; - encoded[..raw.len()].copy_from_slice(raw); - Ok(encoded) -} - -pub fn decode_zkm_version_fixed(version: &ZkmVersionBytes) -> Result { - let end = version.iter().position(|b| *b == 0).unwrap_or(version.len()); - if end == 0 { - return Err("zkm_version is empty".to_string()); - } - String::from_utf8(version[..end].to_vec()).map_err(|e| format!("invalid zkm_version: {e}")) -} - -pub fn parse_zkm_version(version: &str) -> Result { - let trimmed = version.trim(); - if trimmed.is_empty() { - return Err("zkm_version is empty".to_string()); - } - Ok(trimmed.to_string()) -} - -pub fn read_zkm_version_from_file(input_proof: &str) -> Result { - let version_path = format!("{input_proof}.zkm_version.bin"); - let raw = std::fs::read(&version_path) - .with_context(|| format!("failed to read zkm_version file '{version_path}'"))?; - let version = String::from_utf8(raw) - .with_context(|| format!("invalid UTF-8 in zkm_version file '{version_path}'"))?; - parse_zkm_version(&version).map_err(anyhow::Error::msg) -} - -pub fn read_zkm_version_fixed_from_file(input_proof: &str) -> Result { - let version = read_zkm_version_from_file(input_proof)?; - encode_zkm_version_fixed(&version).map_err(anyhow::Error::msg) -} - -#[cfg(test)] -mod tests { - use super::*; - use std::fs; - use std::path::PathBuf; - use std::time::{SystemTime, UNIX_EPOCH}; - - fn write_temp_version_file(version: &str) -> String { - let nanos = SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_nanos(); - let base: PathBuf = std::env::temp_dir().join(format!("zkm-version-test-{nanos}")); - let base_str = base.to_string_lossy().to_string(); - fs::write(format!("{base_str}.zkm_version.bin"), version).unwrap(); - base_str - } - - #[test] - fn encode_rejects_empty_version() { - let result = encode_zkm_version_fixed(""); - assert!(result.is_err()); - } - - #[test] - fn encode_accepts_16_bytes_version() { - let version = "v123456789012345"; - assert_eq!(version.len(), ZKM_VERSION_BYTES_LEN); - let encoded = encode_zkm_version_fixed(version).unwrap(); - assert_eq!(decode_zkm_version_fixed(&encoded).unwrap(), version); - } - - #[test] - fn encode_rejects_17_bytes_version() { - let version = "v1234567890123456"; - assert_eq!(version.len(), ZKM_VERSION_BYTES_LEN + 1); - let result = encode_zkm_version_fixed(version); - assert!(result.is_err()); - } - - #[test] - fn read_version_file_accepts_non_fixed_length_version() { - let version = "v1.12.15-rc1+build.20260319"; - let input_proof = write_temp_version_file(version); - let read = read_zkm_version_from_file(&input_proof).unwrap(); - assert_eq!(read, version); - let _ = fs::remove_file(format!("{input_proof}.zkm_version.bin")); - } - - #[test] - fn read_version_file_rejects_empty() { - let input_proof = write_temp_version_file(" "); - let result = read_zkm_version_from_file(&input_proof); - assert!(result.is_err()); - let _ = fs::remove_file(format!("{input_proof}.zkm_version.bin")); - } -} diff --git a/node/src/bin/part_stark_vk_attest.rs b/node/src/bin/part_stark_vk_attest.rs index 18982845..3b939c17 100644 --- a/node/src/bin/part_stark_vk_attest.rs +++ b/node/src/bin/part_stark_vk_attest.rs @@ -83,28 +83,28 @@ fn load_publisher_set(commit_info_file: &PathBuf) -> Result<(Vec, u16 let commit_info: CommitInfo = serde_json::from_slice(&bytes).with_context(|| { format!("failed to decode commit_info file '{}'", commit_info_file.display()) })?; - if commit_info.publisher_public_keys.is_empty() { + let (encoded_public_keys, threshold) = commit_info.active_publisher_set(); + if encoded_public_keys.is_empty() { bail!("commit_info publisher_public_keys is empty"); } - if commit_info.threshold == 0 { + if threshold == 0 { bail!("commit_info threshold must be greater than 0"); } - let publisher_public_keys = commit_info - .publisher_public_keys + let publisher_public_keys = encoded_public_keys .iter() .map(|compressed_pk| { PublicKey::from_str(compressed_pk) .with_context(|| format!("invalid publisher public key '{}'", compressed_pk)) }) .collect::>>()?; - if usize::from(commit_info.threshold) > publisher_public_keys.len() { + if usize::from(threshold) > publisher_public_keys.len() { bail!( "commit_info threshold {} exceeds publisher_public_keys length {}", - commit_info.threshold, + threshold, publisher_public_keys.len() ); } - Ok((publisher_public_keys, commit_info.threshold)) + Ok((publisher_public_keys, threshold)) } fn load_part_stark_vk( diff --git a/node/src/bin/sequencer-set-publish.rs b/node/src/bin/sequencer-set-publish.rs index d3900eb7..c6fe4f6c 100644 --- a/node/src/bin/sequencer-set-publish.rs +++ b/node/src/bin/sequencer-set-publish.rs @@ -111,6 +111,7 @@ impl OutputData { async fn save_commit_info( output_file: &str, btc_public_keys: &[secp256k1::PublicKey], + next_btc_public_keys: &[secp256k1::PublicKey], sequencers: Vec, init_genesis: bool, commit_info_file: &str, @@ -129,6 +130,10 @@ async fn save_commit_info( txid: txid.clone(), threshold: (btc_public_keys.len() * 2).div_ceil(3) as u16, publisher_public_keys: btc_public_keys.iter().map(|pubkey| pubkey.to_string()).collect(), + next_threshold: Some((next_btc_public_keys.len() * 2).div_ceil(3) as u16), + next_publisher_public_keys: Some( + next_btc_public_keys.iter().map(|pubkey| pubkey.to_string()).collect(), + ), genesis_txid, sequencers: sequencers.iter().cloned().map(|v| v.into()).collect(), }; @@ -361,7 +366,7 @@ async fn main() -> Result<(), Box> { &goat_client, owner_btc_key_wif, publisher_btc_pubkeys.clone(), - next_publisher_btc_pubkeys, + next_publisher_btc_pubkeys.clone(), fee_tx, update_connector, goat_block_number, @@ -373,6 +378,7 @@ async fn main() -> Result<(), Box> { match save_commit_info( &args.output_file, &publisher_btc_pubkeys, + &next_publisher_btc_pubkeys, sequencers, init_genesis, &commit_info, diff --git a/node/src/handle.rs b/node/src/handle.rs index de1f1860..25f644b7 100644 --- a/node/src/handle.rs +++ b/node/src/handle.rs @@ -3226,7 +3226,7 @@ async fn handle_disprove_ready_challenger( txins }; // 2. check assertions committed by Operator, if any assertion is invalid, sign & broadcast disprove txn - let vk = crate::vk::get_vk(&graph.parameters.zkm_version).await?; + let vk = crate::vk::get_vk().await?; let disprove_scripts = get_disprove_scripts(&graph.parameters).await?; let disprove_scripts = disprove_scripts.try_into().map_err(|_| anyhow!("Mismatch disprove scripts num"))?; diff --git a/node/src/lib.rs b/node/src/lib.rs index 3042c519..4897ef59 100644 --- a/node/src/lib.rs +++ b/node/src/lib.rs @@ -39,7 +39,6 @@ mod dbg { use serde::Deserialize; use serde::Serialize; use uuid::Uuid; - use zkm_sdk::ZKM_CIRCUIT_VERSION; fn dbg_network() -> Network { Network::Testnet4 @@ -140,7 +139,6 @@ mod dbg { watchtower_pubkeys, hashlocks, guest_constant_value: [3u8; 32], - zkm_version: ZKM_CIRCUIT_VERSION.to_string(), } } fn build_dbg_simplified_graph() -> SimplifiedBitvm2Graph { @@ -171,6 +169,21 @@ mod dbg { ); } + #[test] + fn dbg_serde_ignores_legacy_graph_zkm_version() { + let graph = build_dbg_simplified_graph(); + let mut value = serde_json::to_value(&graph).unwrap(); + value + .get_mut("parameters") + .and_then(serde_json::Value::as_object_mut) + .unwrap() + .insert("zkm_version".to_string(), serde_json::Value::String("v1.2.4".to_string())); + + let decoded: SimplifiedBitvm2Graph = serde_json::from_value(value).unwrap(); + assert_eq!(decoded.parameters.graph_id, graph.parameters.graph_id); + assert_eq!(decoded.parameters.graph_nonce, graph.parameters.graph_nonce); + } + #[tokio::test] #[ignore = "requires local db"] async fn dbg_serde_from_db() { diff --git a/node/src/rpc_service/handler/bitvm2_handler.rs b/node/src/rpc_service/handler/bitvm2_handler.rs index 50b83a97..86448b72 100644 --- a/node/src/rpc_service/handler/bitvm2_handler.rs +++ b/node/src/rpc_service/handler/bitvm2_handler.rs @@ -838,7 +838,6 @@ pub async fn get_instances_overview( /// "assert_commit_timeout_txids": [], /// "init_withdraw_tx_hash": null, /// "bridge_out_start_at": 1699123456, -/// "zkm_version": "zkm1.0.0", /// "status_updated_at": 1699123456, /// "created_at": 1699123456, /// "updated_at": 1699123456 @@ -931,7 +930,6 @@ pub async fn get_graph( /// "assert_commit_timeout_txids": [], /// "init_withdraw_tx_hash": null, /// "bridge_out_start_at": 1699123456, -/// "zkm_version": "zkm1.0.0", /// "status_updated_at": 1699123456, /// "created_at": 1699123456, /// "updated_at": 1699123456 @@ -1034,7 +1032,6 @@ pub async fn get_graphs( /// "assert_commit_timeout_txids": [], /// "init_withdraw_tx_hash": null, /// "bridge_out_start_at": 0, -/// "zkm_version": "zkm1.0.0", /// "status_updated_at": 1699123456, /// "created_at": 1699123456, /// "updated_at": 1699123456 diff --git a/node/src/rpc_service/mod.rs b/node/src/rpc_service/mod.rs index 8e261b0d..b2a67541 100644 --- a/node/src/rpc_service/mod.rs +++ b/node/src/rpc_service/mod.rs @@ -581,7 +581,6 @@ mod tests { assert_commit_timeout_txids: vec![], init_withdraw_tx_hash: Some(format!("0x{}", hex::encode(generate_random_bytes(32)))), bridge_out_start_at: current_time_secs() + 100, - zkm_version: "zkm_0.1.0".to_string(), status_updated_at: current_time_secs(), proceed_withdraw_height: 0, created_at: current_time_secs(), @@ -617,7 +616,6 @@ mod tests { assert_commit_timeout_txids: vec![], init_withdraw_tx_hash: None, bridge_out_start_at: 0, - zkm_version: "zkm_0.1.0".to_string(), status_updated_at: current_time_secs(), proceed_withdraw_height: 0, created_at: current_time_secs(), diff --git a/node/src/utils.rs b/node/src/utils.rs index a989535c..b198d3ac 100644 --- a/node/src/utils.rs +++ b/node/src/utils.rs @@ -56,6 +56,7 @@ use serde::{Deserialize, Serialize}; use std::fs::{self, File}; use std::io::{BufReader, BufWriter}; use std::net::SocketAddr; +use std::panic::{AssertUnwindSafe, catch_unwind}; use std::path::{Path, PathBuf}; use std::str::FromStr; @@ -70,8 +71,8 @@ use store::{ PeginInstanceProcessData, SerializableTxid, UInt64Array3, }; use stun_client::{Attribute, Class, Client}; -use zkm_sdk::{ZKM_CIRCUIT_VERSION, ZKMProofWithPublicValues}; -use zkm_verifier::{IMM_GROTH16_VK_BYTES, convert_ark_imm_wrap_vk}; +use zkm_sdk::ZKMProofWithPublicValues; +use zkm_verifier::{Groth16Verifier, IMM_GROTH16_VK_BYTES, convert_ark_imm_wrap_vk}; use crate::env; use crate::rpc_service::routes::v1::{ @@ -1614,15 +1615,15 @@ pub async fn is_take2_timelock_expired( /// Loads partial scripts from a local cache file. /// If cache file does not exist, generate partial scripts by vk an cache it -pub async fn get_partial_scripts(version: String) -> Result> { - let scripts_cache_path = format!("{SCRIPT_CACHE_FILE_NAME}_{version}.bin"); +pub async fn get_partial_scripts() -> Result> { + let scripts_cache_path = format!("{SCRIPT_CACHE_FILE_NAME}.bin"); if Path::new(&scripts_cache_path).exists() { let file = File::open(scripts_cache_path)?; let reader = BufReader::new(file); let scripts_bytes: Vec = bincode::deserialize_from(reader)?; Ok(scripts_bytes) } else { - let partial_scripts = generate_partial_scripts(&get_vk(&version).await?); + let partial_scripts = generate_partial_scripts(&get_vk().await?); if let Some(parent) = Path::new(&scripts_cache_path).parent() { fs::create_dir_all(parent)?; }; @@ -1634,7 +1635,7 @@ pub async fn get_partial_scripts(version: String) -> Result> { } pub async fn get_disprove_scripts(graph_params: &Bitvm2GraphParameters) -> Result> { - let partial_scripts = get_partial_scripts(graph_params.zkm_version.clone()).await?; + let partial_scripts = get_partial_scripts().await?; let (mut disprove_scripts, disprove_scripts_1) = generate_disprove_scripts( &partial_scripts, graph_params.operator_wots_pubkeys.clone(), @@ -1769,6 +1770,11 @@ fn gen_watchtower_commitment(graph_id: Uuid, proof_data: ProofData) -> Result Result> { + catch_unwind(AssertUnwindSafe(|| Groth16Verifier::get_part_stark_vk(zkm_version).to_vec())) + .map_err(|_| anyhow!("failed to load part_stark_vk for zkm_version {zkm_version}")) +} + // proof network /// Returns: /// - `Ok(Some(WatchtowerCommitment), _)` if watchtower proof is available @@ -1806,7 +1812,6 @@ pub async fn get_watchtower_commitment( public_key: env::get_node_pubkey()?.to_string(), challenge_init_txid: challenge_init_txid.0.to_string(), execution_layer_block_number: graph.proceed_withdraw_height, // NOTE: this number may be zero - attested_zkm_version: graph.zkm_version.clone(), }, ) .await?; @@ -1938,13 +1943,7 @@ pub async fn get_operator_proof( info!("get_operator_proof get proof successfully"); let proof: ZKMProofWithPublicValues = bincode::deserialize(proof_data.proof.as_slice()).unwrap(); - if proof.zkm_version != bitvm_graph.parameters.zkm_version { - bail!( - "zkm_version mismatch, expected {}, got {}", - bitvm_graph.parameters.zkm_version, - proof.zkm_version - ); - } + let proof_part_stark_vk = load_part_stark_vk_for_zkm_version(&proof.zkm_version)?; let output: bitcoin_light_client_circuit::OperatorPublicOutputs = proof.public_values.clone().read(); // TODO: additionally check constant and included_watchtower with included_watchtowers. @@ -1954,7 +1953,7 @@ pub async fn get_operator_proof( &proof, &proof_data.vk, &IMM_GROTH16_VK_BYTES, - &output.part_stark_vk, + &proof_part_stark_vk, ) .map_err(|e| anyhow!("failed to convert operator proof to ark format: {e}"))?; info!("get_operator_proof parse proof successfully"); @@ -2700,7 +2699,6 @@ pub async fn build_graph_params( watchtower_pubkeys, hashlocks, guest_constant_value, - zkm_version: ZKM_CIRCUIT_VERSION.to_string(), // use the latest version }) } @@ -3864,7 +3862,6 @@ fn convert_graph(bitvm2_graph: &Bitvm2Graph, current_time: i64) -> Graph { .collect(), init_withdraw_tx_hash: None, bridge_out_start_at: 0, - zkm_version: bitvm2_graph.parameters.zkm_version.clone(), status_updated_at: current_time, proceed_withdraw_height: 0, created_at: current_time, @@ -4838,4 +4835,16 @@ mod tests { assert_eq!(url.as_str(), "http://127.0.0.1:8900/v1/proofs/operator_proofs"); } + + #[test] + fn test_load_part_stark_vk_for_zkm_version_accepts_known_version() { + let part_stark_vk = load_part_stark_vk_for_zkm_version("v1.2.4").unwrap(); + assert!(!part_stark_vk.is_empty()); + } + + #[test] + fn test_load_part_stark_vk_for_zkm_version_rejects_unknown_version_without_panic() { + let err = load_part_stark_vk_for_zkm_version("v0.0.0-test").unwrap_err(); + assert!(err.to_string().contains("failed to load part_stark_vk")); + } } diff --git a/node/src/vk.rs b/node/src/vk.rs index b202275f..708b3b6b 100644 --- a/node/src/vk.rs +++ b/node/src/vk.rs @@ -24,23 +24,23 @@ pub(crate) fn block_on(fut: impl std::future::Future) -> T { } } -pub async fn get_vk(zkm_version: &str) -> Result { - let build_dir = try_install_circuit_artifacts(zkm_version); +pub async fn get_vk() -> Result { + let build_dir = try_install_circuit_artifacts(); let vk_file = build_dir.join("groth16_vk.bin"); let content = fs::read(&vk_file)?; Ok(load_ark_groth16_verifying_key_from_bytes(&content)?) } #[must_use] -pub fn groth16_circuit_artifacts_dir(zkm_version: &str) -> PathBuf { - dirs::home_dir().unwrap().join(".zkm").join("circuits/groth16").join(zkm_version) +pub fn groth16_circuit_artifacts_dir() -> PathBuf { + dirs::home_dir().unwrap().join(".zkm").join("circuits/groth16/imm-wrap-vk") } /// Tries to install the groth16 circuit artifacts if they are not already installed. #[must_use] -pub fn try_install_circuit_artifacts(zkm_version: &str) -> PathBuf { +pub fn try_install_circuit_artifacts() -> PathBuf { let artifacts_type = "groth16"; - let build_dir = groth16_circuit_artifacts_dir(zkm_version); + let build_dir = groth16_circuit_artifacts_dir(); if build_dir.exists() { println!( @@ -49,19 +49,18 @@ pub fn try_install_circuit_artifacts(zkm_version: &str) -> PathBuf { build_dir.display() ); } else { - install_circuit_artifacts(build_dir.clone(), artifacts_type, zkm_version); + install_circuit_artifacts(build_dir.clone(), artifacts_type); } build_dir } #[allow(clippy::needless_pass_by_value)] -pub fn install_circuit_artifacts(build_dir: PathBuf, artifacts_type: &str, zkm_version: &str) { +pub fn install_circuit_artifacts(build_dir: PathBuf, artifacts_type: &str) { // Create the build directory. - std::fs::create_dir_all(&build_dir).expect("failed to create build directory"); + fs::create_dir_all(&build_dir).expect("failed to create build directory"); // Download the artifacts. - let download_url = - format!("{CIRCUIT_ARTIFACTS_URL_BASE}/{zkm_version}-{artifacts_type}.tar.gz"); + let download_url = format!("{CIRCUIT_ARTIFACTS_URL_BASE}/{artifacts_type}-imm-wrap-vk.tar.gz"); let mut artifacts_tar_gz_file = tempfile::NamedTempFile::new().expect("failed to create tempfile"); let client = reqwest::Client::builder().build().expect("failed to create reqwest client"); @@ -119,10 +118,10 @@ mod tests { #[tokio::test] #[ignore] async fn test_get_vk() { - let latest = zkm_sdk::ZKM_CIRCUIT_VERSION; - get_vk(latest).await.unwrap(); + let vk = get_vk().await.unwrap(); + let imm_v = + load_ark_groth16_verifying_key_from_bytes(&zkm_verifier::IMM_GROTH16_VK_BYTES).unwrap(); - let older = "v1.2.2"; - get_vk(older).await.unwrap(); + assert_eq!(vk, imm_v); } } diff --git a/proof-builder-rpc/src/api/proof_handler.rs b/proof-builder-rpc/src/api/proof_handler.rs index c6a9d23a..37e72da4 100644 --- a/proof-builder-rpc/src/api/proof_handler.rs +++ b/proof-builder-rpc/src/api/proof_handler.rs @@ -228,21 +228,12 @@ pub(super) async fn post_watchtower_proof_task( .to_string(); let mut storage_process = api_state.local_db.acquire().await.api_error("POST_WATCHTOWER_PROOF_TASK_ERROR")?; - let graph = storage_process + storage_process .find_graph(&graph_id) .await .api_error("POST_WATCHTOWER_PROOF_TASK_ERROR")? .ok_or_else(|| anyhow::anyhow!("graph {graph_id} not found")) .api_error("POST_WATCHTOWER_PROOF_TASK_ERROR")?; - if payload.attested_zkm_version != graph.zkm_version { - return ok_response(WatchtowerProofResponse { - proof_data: None, - error: Some(format!( - "attested_zkm_version mismatch, expected {}, got {}", - graph.zkm_version, payload.attested_zkm_version - )), - }); - } let watchtower_proof = find_watchtower_task(&api_state.local_db, instance_id, graph_id, &payload.public_key) @@ -278,7 +269,6 @@ pub(super) async fn post_watchtower_proof_task( payload.public_key, challenge_init_txid, payload.execution_layer_block_number, - payload.attested_zkm_version, ) .await .api_error("POST_WATCHTOWER_PROOF_TASK_ERROR")?; diff --git a/proof-builder-rpc/src/task/mod.rs b/proof-builder-rpc/src/task/mod.rs index f811c5d5..e58fcb03 100644 --- a/proof-builder-rpc/src/task/mod.rs +++ b/proof-builder-rpc/src/task/mod.rs @@ -14,7 +14,6 @@ use ::header_chain_proof::HeaderChainProofBuilder; use ::state_chain_proof::StateChainProofBuilder; use bitcoin::{BlockHash, Network, Txid}; use client::btc_chain::BTCClient; -use commit_chain::CircuitCommit; use std::str::FromStr; use std::time::UNIX_EPOCH; use uuid::Uuid; @@ -215,7 +214,6 @@ async fn read_watchtower_challenge_details<'a>( i64, i64, Option, - Option, Vec, Vec, Vec, @@ -225,7 +223,6 @@ async fn read_watchtower_challenge_details<'a>( let ( task_index, execution_layer_block_number, - attested_zkm_version, watchtower_challenge_init_txid, watchtower_challenge_txids, included_watchtowers, @@ -243,7 +240,6 @@ async fn read_watchtower_challenge_details<'a>( ( task.id, task.execution_layer_block_number, - task.extra.clone(), None, watchtower_challenge_txids, vec![true], @@ -279,7 +275,7 @@ async fn read_watchtower_challenge_details<'a>( if let Some(first) = challenge_init_txids.first() { if !challenge_init_txids.iter().all(|x| first == x) { anyhow::bail!( - "Inconsistant watchtower challenge info from instance {} and graph_id {}", + "Inconsistent watchtower challenge info from instance {} and graph_id {}", task.instance_id, task.graph_id ); @@ -294,7 +290,6 @@ async fn read_watchtower_challenge_details<'a>( ( task.id, task.execution_layer_block_number, - None, challenge_init_txids.first().cloned(), challenge_txids, included_watchtowers, @@ -310,7 +305,6 @@ async fn read_watchtower_challenge_details<'a>( Ok(( task_index, execution_layer_block_number, - attested_zkm_version, watchtower_challenge_init_txid, watchtower_challenge_txids, included_watchtowers, @@ -333,7 +327,6 @@ pub(crate) async fn fetch_on_demand_task( let ( task_index, execution_layer_block_number, - _attested_zkm_version, watchtower_challenge_init_txid, watchtower_challenge_txids, included_watchtowers, @@ -483,41 +476,28 @@ pub(crate) async fn fetch_on_demand_task( }; tracing::info!("commit_chain_input_proof: {commit_chain_input_proof:?}"); let commit_chain_input_proof = commit_chain_input_proof.path_to_proof.unwrap(); - let file = format!("{commit_chain_input_proof}.commits"); - let content = match std::fs::read_to_string(&file) { - Ok(d) => d, - Err(e) => { - tracing::error!("read {file:?} error, {e}"); - return Ok(None); - } - }; - let commits: Vec = serde_json::from_str(&content)?; - let latest_sequencer_commit_txid = commits[0].commit_txn.compute_txid().to_string(); - let attested_zkm_version = match (_attested_zkm_version, graph_id.as_ref()) { - (Some(attested_zkm_version), _) => attested_zkm_version, - (None, Some(graph_id)) => { - let graph_id = Uuid::parse_str(graph_id)?; - match storage_processor.find_graph(&graph_id).await? { - Some(graph) => graph.zkm_version, - None => { - tracing::warn!("Graph {graph_id} not found when building on-demand task"); - return Ok(None); - } + let commits_file = format!("{commit_chain_input_proof}.commits"); + let commits: Vec = + match serde_json::from_str(&std::fs::read_to_string(&commits_file)?) { + Ok(commits) => commits, + Err(err) => { + tracing::warn!("Failed to read commit-chain commits, error: {err}"); + return Ok(None); } - } - (None, None) => { - tracing::warn!("graph_id missing when building on-demand task"); + }; + let latest_sequencer_commit_txid = match commits.first() { + Some(commit) => commit.commit_txn.compute_txid().to_string(), + None => { + tracing::warn!("Commit-chain proof does not contain any commits yet"); return Ok(None); } }; - Ok(Some(OnDemandTask { task_index, latest_sequencer_commit_txid, header_chain_input_proof, commit_chain_input_proof, state_chain_input_proof, - attested_zkm_version, watchtower_challenge_init_txid, watchtower_challenge_txids, included_watchtowers, @@ -670,7 +650,6 @@ pub(crate) async fn add_watchtower_task( public_key: String, challenge_init_txid: String, execution_layer_block_number: i64, - attested_zkm_version: String, ) -> anyhow::Result { let mut storage_processor = local_db.acquire().await?; Ok(storage_processor @@ -685,7 +664,6 @@ pub(crate) async fn add_watchtower_task( updated_at: current_time_secs(), execution_layer_block_number, included: true, - extra: Some(attested_zkm_version), ..Default::default() }) .await?) @@ -926,7 +904,6 @@ mod tests { public_key, challenge_init_txid, number, - "v1.2.4".to_string(), ) .await .unwrap(); diff --git a/proof-builder-rpc/src/task/watchtower_proof.rs b/proof-builder-rpc/src/task/watchtower_proof.rs index 541afed1..c795ecd8 100644 --- a/proof-builder-rpc/src/task/watchtower_proof.rs +++ b/proof-builder-rpc/src/task/watchtower_proof.rs @@ -42,7 +42,6 @@ pub(crate) fn spawn_watchtower_proof_task( args.header_chain_input_proof = next_task.header_chain_input_proof; args.commit_chain_input_proof = next_task.commit_chain_input_proof; args.state_chain_input_proof = next_task.state_chain_input_proof; - args.attested_zkm_version = next_task.attested_zkm_version; args.output = format!("{}/{}.bin", std::path::Path::new(&args.output).parent().unwrap().to_str().unwrap(), next_task.task_index, @@ -77,7 +76,6 @@ pub(crate) fn spawn_watchtower_proof_task( header_chain_input_proof: args.header_chain_input_proof.clone(), commit_chain_input_proof: args.commit_chain_input_proof.clone(), state_chain_input_proof: args.state_chain_input_proof.clone(), - attested_zkm_version: args.attested_zkm_version.clone(), output: args.output.clone(), target_block, block_pos, From 00de76c19b3121fd9c365eacfc23addb7f31679d Mon Sep 17 00:00:00 2001 From: Blake Date: Tue, 7 Apr 2026 18:13:58 +0800 Subject: [PATCH 10/14] remove zkm_version reference from localdb.rs and add proof_part_stark_vk file --- .../watchtower/output3.bin.proof_part_stark_vk.bin | Bin 0 -> 44 bytes crates/store/src/localdb.rs | 1 - 2 files changed, 1 deletion(-) create mode 100644 circuits/data/watchtower/output3.bin.proof_part_stark_vk.bin diff --git a/circuits/data/watchtower/output3.bin.proof_part_stark_vk.bin b/circuits/data/watchtower/output3.bin.proof_part_stark_vk.bin new file mode 100644 index 0000000000000000000000000000000000000000..7fb52b0c02fd3ddf6c47f3182d4832b5867dc4cb GIT binary patch literal 44 ucmY#jfPjnPE5(+XGI<_*^8QA^om+=jfAyGac28Gok?~1YQ>AtRkSYLSI}iB) literal 0 HcmV?d00001 diff --git a/crates/store/src/localdb.rs b/crates/store/src/localdb.rs index 32f2d60f..d80ad4b0 100644 --- a/crates/store/src/localdb.rs +++ b/crates/store/src/localdb.rs @@ -1221,7 +1221,6 @@ impl<'a> StorageProcessor<'a> { assert_commit_timeout_txids, init_withdraw_tx_hash, bridge_out_start_at, - zkm_version, status_updated_at, proceed_withdraw_height, CASE From c0597e9d0bcb08e4b16420c977a5bc661b13c2f1 Mon Sep 17 00:00:00 2001 From: Blake Date: Fri, 10 Apr 2026 16:34:18 +0800 Subject: [PATCH 11/14] update part_stark_vk handling with version normalization and attestation improvements --- Cargo.lock | 783 ++++++++---------- Cargo.toml | 14 +- circuits/commit-chain-proof/guest/Cargo.toml | 4 +- circuits/commit-chain-proof/host/src/lib.rs | 9 +- circuits/data/commit-chain/0-1.bin.commits | 2 +- circuits/data/commit-chain/1-1.bin.commits | 2 +- circuits/header-chain-proof/guest/Cargo.toml | 8 +- circuits/header-chain-proof/guest/src/main.rs | 1 - circuits/header-chain-proof/host/src/lib.rs | 2 +- circuits/operator-proof/guest/Cargo.toml | 4 +- circuits/state-chain-proof/guest/Cargo.toml | 4 +- circuits/state-chain-proof/host/src/lib.rs | 2 +- circuits/watchtower-proof/guest/Cargo.toml | 4 +- circuits/watchtower-proof/host/src/lib.rs | 5 +- .../src/attestation.rs | 538 +++++++++++- .../bitcoin-light-client-circuit/src/lib.rs | 16 +- crates/commit-chain/src/lib.rs | 2 +- crates/header-chain/Cargo.toml | 2 +- node/Cargo.toml | 1 + node/src/bin/part_stark_vk_attest.rs | 230 +++-- 20 files changed, 1071 insertions(+), 562 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ecef8244..a79b2df9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -102,24 +102,24 @@ checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" [[package]] name = "alloy" -version = "1.8.2" -source = "git+https://github.com/alloy-rs/alloy#c36b7b2c867e7b13ede7a5f6f8112a83c363400e" +version = "1.8.3" +source = "git+https://github.com/alloy-rs/alloy#5cc9464fa40b71b925170dec861530381857509c" dependencies = [ - "alloy-consensus 1.8.2", + "alloy-consensus 1.8.3", "alloy-contract", "alloy-core", - "alloy-eips 1.8.2", - "alloy-genesis 1.8.2", - "alloy-network 1.8.2", - "alloy-provider 1.8.2", + "alloy-eips 1.8.3", + "alloy-genesis 1.8.3", + "alloy-network 1.8.3", + "alloy-provider 1.8.3", "alloy-pubsub", - "alloy-rpc-client 1.8.2", - "alloy-rpc-types 1.8.2", - "alloy-serde 1.8.2", - "alloy-signer 1.8.2", + "alloy-rpc-client 1.8.3", + "alloy-rpc-types 1.8.3", + "alloy-serde 1.8.3", + "alloy-signer 1.8.3 (git+https://github.com/alloy-rs/alloy)", "alloy-signer-local", - "alloy-transport 1.8.2", - "alloy-transport-http 1.8.2", + "alloy-transport 1.8.3", + "alloy-transport-http 1.8.3", "alloy-transport-ipc", "alloy-transport-ws", "alloy-trie 0.9.5", @@ -165,15 +165,15 @@ dependencies = [ [[package]] name = "alloy-consensus" -version = "1.8.2" -source = "git+https://github.com/alloy-rs/alloy#c36b7b2c867e7b13ede7a5f6f8112a83c363400e" +version = "1.8.3" +source = "git+https://github.com/alloy-rs/alloy#5cc9464fa40b71b925170dec861530381857509c" dependencies = [ - "alloy-eips 1.8.2", + "alloy-eips 1.8.3", "alloy-primitives", "alloy-rlp", - "alloy-serde 1.8.2", + "alloy-serde 1.8.3", "alloy-trie 0.9.5", - "alloy-tx-macros 1.8.2", + "alloy-tx-macros 1.8.3", "auto_impl", "borsh", "c-kzg", @@ -204,33 +204,33 @@ dependencies = [ [[package]] name = "alloy-consensus-any" -version = "1.8.2" -source = "git+https://github.com/alloy-rs/alloy#c36b7b2c867e7b13ede7a5f6f8112a83c363400e" +version = "1.8.3" +source = "git+https://github.com/alloy-rs/alloy#5cc9464fa40b71b925170dec861530381857509c" dependencies = [ - "alloy-consensus 1.8.2", - "alloy-eips 1.8.2", + "alloy-consensus 1.8.3", + "alloy-eips 1.8.3", "alloy-primitives", "alloy-rlp", - "alloy-serde 1.8.2", + "alloy-serde 1.8.3", "serde", ] [[package]] name = "alloy-contract" -version = "1.8.2" -source = "git+https://github.com/alloy-rs/alloy#c36b7b2c867e7b13ede7a5f6f8112a83c363400e" +version = "1.8.3" +source = "git+https://github.com/alloy-rs/alloy#5cc9464fa40b71b925170dec861530381857509c" dependencies = [ - "alloy-consensus 1.8.2", + "alloy-consensus 1.8.3", "alloy-dyn-abi", "alloy-json-abi", - "alloy-network 1.8.2", - "alloy-network-primitives 1.8.2", + "alloy-network 1.8.3", + "alloy-network-primitives 1.8.3", "alloy-primitives", - "alloy-provider 1.8.2", + "alloy-provider 1.8.3", "alloy-pubsub", - "alloy-rpc-types-eth 1.8.2", + "alloy-rpc-types-eth 1.8.3", "alloy-sol-types", - "alloy-transport 1.8.2", + "alloy-transport 1.8.3", "futures", "futures-util", "serde_json", @@ -342,8 +342,8 @@ dependencies = [ [[package]] name = "alloy-eips" -version = "1.8.2" -source = "git+https://github.com/alloy-rs/alloy#c36b7b2c867e7b13ede7a5f6f8112a83c363400e" +version = "1.8.3" +source = "git+https://github.com/alloy-rs/alloy#5cc9464fa40b71b925170dec861530381857509c" dependencies = [ "alloy-eip2124", "alloy-eip2930", @@ -351,7 +351,7 @@ dependencies = [ "alloy-eip7928", "alloy-primitives", "alloy-rlp", - "alloy-serde 1.8.2", + "alloy-serde 1.8.3", "auto_impl", "borsh", "c-kzg", @@ -397,12 +397,12 @@ dependencies = [ [[package]] name = "alloy-genesis" -version = "1.8.2" -source = "git+https://github.com/alloy-rs/alloy#c36b7b2c867e7b13ede7a5f6f8112a83c363400e" +version = "1.8.3" +source = "git+https://github.com/alloy-rs/alloy#5cc9464fa40b71b925170dec861530381857509c" dependencies = [ - "alloy-eips 1.8.2", + "alloy-eips 1.8.3", "alloy-primitives", - "alloy-serde 1.8.2", + "alloy-serde 1.8.3", "alloy-trie 0.9.5", "borsh", "serde", @@ -450,8 +450,8 @@ dependencies = [ [[package]] name = "alloy-json-rpc" -version = "1.8.2" -source = "git+https://github.com/alloy-rs/alloy#c36b7b2c867e7b13ede7a5f6f8112a83c363400e" +version = "1.8.3" +source = "git+https://github.com/alloy-rs/alloy#5cc9464fa40b71b925170dec861530381857509c" dependencies = [ "alloy-primitives", "alloy-sol-types", @@ -489,19 +489,19 @@ dependencies = [ [[package]] name = "alloy-network" -version = "1.8.2" -source = "git+https://github.com/alloy-rs/alloy#c36b7b2c867e7b13ede7a5f6f8112a83c363400e" +version = "1.8.3" +source = "git+https://github.com/alloy-rs/alloy#5cc9464fa40b71b925170dec861530381857509c" dependencies = [ - "alloy-consensus 1.8.2", - "alloy-consensus-any 1.8.2", - "alloy-eips 1.8.2", - "alloy-json-rpc 1.8.2", - "alloy-network-primitives 1.8.2", + "alloy-consensus 1.8.3", + "alloy-consensus-any 1.8.3", + "alloy-eips 1.8.3", + "alloy-json-rpc 1.8.3", + "alloy-network-primitives 1.8.3", "alloy-primitives", - "alloy-rpc-types-any 1.8.2", - "alloy-rpc-types-eth 1.8.2", - "alloy-serde 1.8.2", - "alloy-signer 1.8.2", + "alloy-rpc-types-any 1.8.3", + "alloy-rpc-types-eth 1.8.3", + "alloy-serde 1.8.3", + "alloy-signer 1.8.3 (git+https://github.com/alloy-rs/alloy)", "alloy-sol-types", "async-trait", "auto_impl", @@ -526,13 +526,13 @@ dependencies = [ [[package]] name = "alloy-network-primitives" -version = "1.8.2" -source = "git+https://github.com/alloy-rs/alloy#c36b7b2c867e7b13ede7a5f6f8112a83c363400e" +version = "1.8.3" +source = "git+https://github.com/alloy-rs/alloy#5cc9464fa40b71b925170dec861530381857509c" dependencies = [ - "alloy-consensus 1.8.2", - "alloy-eips 1.8.2", + "alloy-consensus 1.8.3", + "alloy-eips 1.8.3", "alloy-primitives", - "alloy-serde 1.8.2", + "alloy-serde 1.8.3", "serde", ] @@ -578,7 +578,7 @@ dependencies = [ "derive_more 2.1.1", "foldhash 0.2.0", "hashbrown 0.16.1", - "indexmap 2.13.0", + "indexmap 2.13.1", "itoa", "k256", "keccak-asm", @@ -587,7 +587,7 @@ dependencies = [ "rand 0.9.2", "rapidhash", "ruint", - "rustc-hash 2.1.1", + "rustc-hash 2.1.2", "serde", "sha3", ] @@ -634,27 +634,27 @@ dependencies = [ [[package]] name = "alloy-provider" -version = "1.8.2" -source = "git+https://github.com/alloy-rs/alloy#c36b7b2c867e7b13ede7a5f6f8112a83c363400e" +version = "1.8.3" +source = "git+https://github.com/alloy-rs/alloy#5cc9464fa40b71b925170dec861530381857509c" dependencies = [ "alloy-chains", - "alloy-consensus 1.8.2", - "alloy-eips 1.8.2", - "alloy-json-rpc 1.8.2", - "alloy-network 1.8.2", - "alloy-network-primitives 1.8.2", + "alloy-consensus 1.8.3", + "alloy-eips 1.8.3", + "alloy-json-rpc 1.8.3", + "alloy-network 1.8.3", + "alloy-network-primitives 1.8.3", "alloy-primitives", "alloy-pubsub", - "alloy-rpc-client 1.8.2", + "alloy-rpc-client 1.8.3", "alloy-rpc-types-anvil", - "alloy-rpc-types-debug 1.8.2", - "alloy-rpc-types-eth 1.8.2", - "alloy-rpc-types-trace 1.8.2", + "alloy-rpc-types-debug 1.8.3", + "alloy-rpc-types-eth 1.8.3", + "alloy-rpc-types-trace 1.8.3", "alloy-rpc-types-txpool", - "alloy-signer 1.8.2", + "alloy-signer 1.8.3 (git+https://github.com/alloy-rs/alloy)", "alloy-sol-types", - "alloy-transport 1.8.2", - "alloy-transport-http 1.8.2", + "alloy-transport 1.8.3", + "alloy-transport-http 1.8.3", "alloy-transport-ipc", "alloy-transport-ws", "async-stream", @@ -679,12 +679,12 @@ dependencies = [ [[package]] name = "alloy-pubsub" -version = "1.8.2" -source = "git+https://github.com/alloy-rs/alloy#c36b7b2c867e7b13ede7a5f6f8112a83c363400e" +version = "1.8.3" +source = "git+https://github.com/alloy-rs/alloy#5cc9464fa40b71b925170dec861530381857509c" dependencies = [ - "alloy-json-rpc 1.8.2", + "alloy-json-rpc 1.8.3", "alloy-primitives", - "alloy-transport 1.8.2", + "alloy-transport 1.8.3", "auto_impl", "bimap", "futures", @@ -700,9 +700,9 @@ dependencies = [ [[package]] name = "alloy-rlp" -version = "0.3.13" +version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e93e50f64a77ad9c5470bf2ad0ca02f228da70c792a8f06634801e202579f35e" +checksum = "dc90b1e703d3c03f4ff7f48e82dd0bc1c8211ab7d079cd836a06fcfeb06651cb" dependencies = [ "alloy-rlp-derive", "arrayvec", @@ -711,9 +711,9 @@ dependencies = [ [[package]] name = "alloy-rlp-derive" -version = "0.3.13" +version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce8849c74c9ca0f5a03da1c865e3eb6f768df816e67dd3721a398a8a7e398011" +checksum = "f36834a5c0a2fa56e171bf256c34d70fca07d0c0031583edea1c4946b7889c9e" dependencies = [ "proc-macro2", "quote", @@ -744,14 +744,14 @@ dependencies = [ [[package]] name = "alloy-rpc-client" -version = "1.8.2" -source = "git+https://github.com/alloy-rs/alloy#c36b7b2c867e7b13ede7a5f6f8112a83c363400e" +version = "1.8.3" +source = "git+https://github.com/alloy-rs/alloy#5cc9464fa40b71b925170dec861530381857509c" dependencies = [ - "alloy-json-rpc 1.8.2", + "alloy-json-rpc 1.8.3", "alloy-primitives", "alloy-pubsub", - "alloy-transport 1.8.2", - "alloy-transport-http 1.8.2", + "alloy-transport 1.8.3", + "alloy-transport-http 1.8.3", "alloy-transport-ipc", "alloy-transport-ws", "futures", @@ -780,28 +780,28 @@ dependencies = [ [[package]] name = "alloy-rpc-types" -version = "1.8.2" -source = "git+https://github.com/alloy-rs/alloy#c36b7b2c867e7b13ede7a5f6f8112a83c363400e" +version = "1.8.3" +source = "git+https://github.com/alloy-rs/alloy#5cc9464fa40b71b925170dec861530381857509c" dependencies = [ "alloy-primitives", "alloy-rpc-types-anvil", - "alloy-rpc-types-debug 1.8.2", - "alloy-rpc-types-engine 1.8.2", - "alloy-rpc-types-eth 1.8.2", - "alloy-rpc-types-trace 1.8.2", + "alloy-rpc-types-debug 1.8.3", + "alloy-rpc-types-engine 1.8.3", + "alloy-rpc-types-eth 1.8.3", + "alloy-rpc-types-trace 1.8.3", "alloy-rpc-types-txpool", - "alloy-serde 1.8.2", + "alloy-serde 1.8.3", "serde", ] [[package]] name = "alloy-rpc-types-anvil" -version = "1.8.2" -source = "git+https://github.com/alloy-rs/alloy#c36b7b2c867e7b13ede7a5f6f8112a83c363400e" +version = "1.8.3" +source = "git+https://github.com/alloy-rs/alloy#5cc9464fa40b71b925170dec861530381857509c" dependencies = [ "alloy-primitives", - "alloy-rpc-types-eth 1.8.2", - "alloy-serde 1.8.2", + "alloy-rpc-types-eth 1.8.3", + "alloy-serde 1.8.3", "serde", ] @@ -817,12 +817,12 @@ dependencies = [ [[package]] name = "alloy-rpc-types-any" -version = "1.8.2" -source = "git+https://github.com/alloy-rs/alloy#c36b7b2c867e7b13ede7a5f6f8112a83c363400e" +version = "1.8.3" +source = "git+https://github.com/alloy-rs/alloy#5cc9464fa40b71b925170dec861530381857509c" dependencies = [ - "alloy-consensus-any 1.8.2", - "alloy-rpc-types-eth 1.8.2", - "alloy-serde 1.8.2", + "alloy-consensus-any 1.8.3", + "alloy-rpc-types-eth 1.8.3", + "alloy-serde 1.8.3", ] [[package]] @@ -838,10 +838,11 @@ dependencies = [ [[package]] name = "alloy-rpc-types-debug" -version = "1.8.2" -source = "git+https://github.com/alloy-rs/alloy#c36b7b2c867e7b13ede7a5f6f8112a83c363400e" +version = "1.8.3" +source = "git+https://github.com/alloy-rs/alloy#5cc9464fa40b71b925170dec861530381857509c" dependencies = [ "alloy-primitives", + "alloy-rlp", "derive_more 2.1.1", "serde", "serde_with", @@ -862,14 +863,14 @@ dependencies = [ [[package]] name = "alloy-rpc-types-engine" -version = "1.8.2" -source = "git+https://github.com/alloy-rs/alloy#c36b7b2c867e7b13ede7a5f6f8112a83c363400e" +version = "1.8.3" +source = "git+https://github.com/alloy-rs/alloy#5cc9464fa40b71b925170dec861530381857509c" dependencies = [ - "alloy-consensus 1.8.2", - "alloy-eips 1.8.2", + "alloy-consensus 1.8.3", + "alloy-eips 1.8.3", "alloy-primitives", "alloy-rlp", - "alloy-serde 1.8.2", + "alloy-serde 1.8.3", "derive_more 2.1.1", "rand 0.8.5", "serde", @@ -898,16 +899,16 @@ dependencies = [ [[package]] name = "alloy-rpc-types-eth" -version = "1.8.2" -source = "git+https://github.com/alloy-rs/alloy#c36b7b2c867e7b13ede7a5f6f8112a83c363400e" +version = "1.8.3" +source = "git+https://github.com/alloy-rs/alloy#5cc9464fa40b71b925170dec861530381857509c" dependencies = [ - "alloy-consensus 1.8.2", - "alloy-consensus-any 1.8.2", - "alloy-eips 1.8.2", - "alloy-network-primitives 1.8.2", + "alloy-consensus 1.8.3", + "alloy-consensus-any 1.8.3", + "alloy-eips 1.8.3", + "alloy-network-primitives 1.8.3", "alloy-primitives", "alloy-rlp", - "alloy-serde 1.8.2", + "alloy-serde 1.8.3", "alloy-sol-types", "itertools 0.14.0", "serde", @@ -931,12 +932,12 @@ dependencies = [ [[package]] name = "alloy-rpc-types-trace" -version = "1.8.2" -source = "git+https://github.com/alloy-rs/alloy#c36b7b2c867e7b13ede7a5f6f8112a83c363400e" +version = "1.8.3" +source = "git+https://github.com/alloy-rs/alloy#5cc9464fa40b71b925170dec861530381857509c" dependencies = [ "alloy-primitives", - "alloy-rpc-types-eth 1.8.2", - "alloy-serde 1.8.2", + "alloy-rpc-types-eth 1.8.3", + "alloy-serde 1.8.3", "serde", "serde_json", "thiserror 2.0.18", @@ -944,12 +945,12 @@ dependencies = [ [[package]] name = "alloy-rpc-types-txpool" -version = "1.8.2" -source = "git+https://github.com/alloy-rs/alloy#c36b7b2c867e7b13ede7a5f6f8112a83c363400e" +version = "1.8.3" +source = "git+https://github.com/alloy-rs/alloy#5cc9464fa40b71b925170dec861530381857509c" dependencies = [ "alloy-primitives", - "alloy-rpc-types-eth 1.8.2", - "alloy-serde 1.8.2", + "alloy-rpc-types-eth 1.8.3", + "alloy-serde 1.8.3", "serde", ] @@ -965,8 +966,8 @@ dependencies = [ [[package]] name = "alloy-serde" -version = "1.8.2" -source = "git+https://github.com/alloy-rs/alloy#c36b7b2c867e7b13ede7a5f6f8112a83c363400e" +version = "1.8.3" +source = "git+https://github.com/alloy-rs/alloy#5cc9464fa40b71b925170dec861530381857509c" dependencies = [ "alloy-primitives", "serde", @@ -989,9 +990,9 @@ dependencies = [ [[package]] name = "alloy-signer" -version = "1.6.3" +version = "1.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97f40010b5e8f79b70bf163b38cd15f529b18ca88c4427c0e43441ee54e4ed82" +checksum = "43f447aefab0f1c0649f71edc33f590992d4e122bc35fb9cdbbf67d4421ace85" dependencies = [ "alloy-primitives", "async-trait", @@ -1004,8 +1005,8 @@ dependencies = [ [[package]] name = "alloy-signer" -version = "1.8.2" -source = "git+https://github.com/alloy-rs/alloy#c36b7b2c867e7b13ede7a5f6f8112a83c363400e" +version = "1.8.3" +source = "git+https://github.com/alloy-rs/alloy#5cc9464fa40b71b925170dec861530381857509c" dependencies = [ "alloy-primitives", "async-trait", @@ -1018,13 +1019,13 @@ dependencies = [ [[package]] name = "alloy-signer-local" -version = "1.8.2" -source = "git+https://github.com/alloy-rs/alloy#c36b7b2c867e7b13ede7a5f6f8112a83c363400e" +version = "1.8.3" +source = "git+https://github.com/alloy-rs/alloy#5cc9464fa40b71b925170dec861530381857509c" dependencies = [ - "alloy-consensus 1.8.2", - "alloy-network 1.8.2", + "alloy-consensus 1.8.3", + "alloy-network 1.8.3", "alloy-primitives", - "alloy-signer 1.8.2", + "alloy-signer 1.8.3 (git+https://github.com/alloy-rs/alloy)", "async-trait", "k256", "rand 0.8.5", @@ -1055,7 +1056,7 @@ dependencies = [ "alloy-sol-macro-input", "const-hex", "heck 0.5.0", - "indexmap 2.13.0", + "indexmap 2.13.1", "proc-macro-error2", "proc-macro2", "quote", @@ -1129,10 +1130,10 @@ dependencies = [ [[package]] name = "alloy-transport" -version = "1.8.2" -source = "git+https://github.com/alloy-rs/alloy#c36b7b2c867e7b13ede7a5f6f8112a83c363400e" +version = "1.8.3" +source = "git+https://github.com/alloy-rs/alloy#5cc9464fa40b71b925170dec861530381857509c" dependencies = [ - "alloy-json-rpc 1.8.2", + "alloy-json-rpc 1.8.3", "auto_impl", "base64 0.22.1", "derive_more 2.1.1", @@ -1165,11 +1166,11 @@ dependencies = [ [[package]] name = "alloy-transport-http" -version = "1.8.2" -source = "git+https://github.com/alloy-rs/alloy#c36b7b2c867e7b13ede7a5f6f8112a83c363400e" +version = "1.8.3" +source = "git+https://github.com/alloy-rs/alloy#5cc9464fa40b71b925170dec861530381857509c" dependencies = [ - "alloy-json-rpc 1.8.2", - "alloy-transport 1.8.2", + "alloy-json-rpc 1.8.3", + "alloy-transport 1.8.3", "itertools 0.14.0", "reqwest 0.13.2", "serde_json", @@ -1180,12 +1181,12 @@ dependencies = [ [[package]] name = "alloy-transport-ipc" -version = "1.8.2" -source = "git+https://github.com/alloy-rs/alloy#c36b7b2c867e7b13ede7a5f6f8112a83c363400e" +version = "1.8.3" +source = "git+https://github.com/alloy-rs/alloy#5cc9464fa40b71b925170dec861530381857509c" dependencies = [ - "alloy-json-rpc 1.8.2", + "alloy-json-rpc 1.8.3", "alloy-pubsub", - "alloy-transport 1.8.2", + "alloy-transport 1.8.3", "bytes", "futures", "interprocess", @@ -1199,11 +1200,11 @@ dependencies = [ [[package]] name = "alloy-transport-ws" -version = "1.8.2" -source = "git+https://github.com/alloy-rs/alloy#c36b7b2c867e7b13ede7a5f6f8112a83c363400e" +version = "1.8.3" +source = "git+https://github.com/alloy-rs/alloy#5cc9464fa40b71b925170dec861530381857509c" dependencies = [ "alloy-pubsub", - "alloy-transport 1.8.2", + "alloy-transport 1.8.3", "futures", "http 1.4.0", "rustls 0.23.37", @@ -1261,8 +1262,8 @@ dependencies = [ [[package]] name = "alloy-tx-macros" -version = "1.8.2" -source = "git+https://github.com/alloy-rs/alloy#c36b7b2c867e7b13ede7a5f6f8112a83c363400e" +version = "1.8.3" +source = "git+https://github.com/alloy-rs/alloy#5cc9464fa40b71b925170dec861530381857509c" dependencies = [ "darling 0.23.0", "proc-macro2", @@ -2006,9 +2007,9 @@ dependencies = [ [[package]] name = "aws-lc-sys" -version = "0.39.0" +version = "0.39.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fa7e52a4c5c547c741610a2c6f123f3881e409b714cd27e6798ef020c514f0a" +checksum = "83a25cf98105baa966497416dbd42565ce3a8cf8dbfd59803ec9ad46f3126399" dependencies = [ "cc", "cmake", @@ -2057,7 +2058,7 @@ dependencies = [ "http 1.4.0", "http-body 1.0.1", "http-body-util", - "hyper 1.8.1", + "hyper 1.9.0", "hyper-util", "itoa", "matchit 0.7.3", @@ -2092,7 +2093,7 @@ dependencies = [ "http 1.4.0", "http-body 1.0.1", "http-body-util", - "hyper 1.8.1", + "hyper 1.9.0", "hyper-util", "itoa", "matchit 0.8.4", @@ -2361,13 +2362,13 @@ dependencies = [ [[package]] name = "bitcoin" -version = "0.31.2" +version = "0.31.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c85783c2fe40083ea54a33aa2f0ba58831d90fcd190f5bdc47e74e84d2a96ae" +checksum = "69197dee21fe23b45f5239bf88086efaa0cb8679f3e704906eb818e8ea169c14" dependencies = [ "bech32 0.10.0-beta", - "bitcoin-internals 0.2.0", - "bitcoin_hashes 0.13.0", + "bitcoin-internals 0.2.1", + "bitcoin_hashes 0.13.1", "hex-conservative 0.1.2", "hex_lit", "secp256k1 0.28.2", @@ -2393,9 +2394,9 @@ dependencies = [ [[package]] name = "bitcoin-internals" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9425c3bf7089c983facbae04de54513cce73b41c7f9ff8c845b54e7bc64ebbfb" +checksum = "994dc6fcc13751c85370b7de118e672b193b9b65167bf09e258f124c97fb9685" [[package]] name = "bitcoin-internals" @@ -2489,11 +2490,10 @@ dependencies = [ [[package]] name = "bitcoin_hashes" -version = "0.13.0" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1930a4dabfebb8d7d9992db18ebe3ae2876f0a305fab206fd168df931ede293b" +checksum = "446819536d8121575eeb7e89efdbadb3f055e87e4bb66c6679a6d5cc2f4b64fd" dependencies = [ - "bitcoin-internals 0.2.0", "hex-conservative 0.1.2", ] @@ -2600,7 +2600,7 @@ dependencies = [ "ark-groth16", "ark-serialize 0.5.0", "bincode", - "bitcoin 0.31.2", + "bitcoin 0.31.3", "bitcoin 0.32.8", "bitcoin-light-client-circuit", "bitcoin-script", @@ -2622,7 +2622,7 @@ dependencies = [ "strum 0.26.3", "tokio", "tracing", - "uuid 1.22.0", + "uuid 1.23.0", ] [[package]] @@ -2656,7 +2656,7 @@ dependencies = [ "hex", "http 1.4.0", "http-body-util", - "indexmap 2.13.0", + "indexmap 2.13.1", "indicatif", "libp2p", "libp2p-metrics", @@ -2668,6 +2668,7 @@ dependencies = [ "rand 0.8.5", "reqwest 0.12.28", "secp256k1 0.29.1", + "semver 1.0.28", "serde", "serde_json", "sha2 0.10.9", @@ -2683,7 +2684,7 @@ dependencies = [ "tracing", "tracing-subscriber 0.3.23", "util", - "uuid 1.22.0", + "uuid 1.23.0", "zeroize", "zkm-sdk", "zkm-verifier", @@ -2711,16 +2712,16 @@ dependencies = [ [[package]] name = "blake3" -version = "1.8.3" +version = "1.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2468ef7d57b3fb7e16b576e8377cdbde2320c60e1491e961d11da40fc4f02a2d" +checksum = "4d2d5991425dfd0785aed03aedcf0b321d61975c9b5b3689c774a2610ae0b51e" dependencies = [ "arrayref", "arrayvec", "cc", "cfg-if", "constant_time_eq 0.4.2", - "cpufeatures 0.2.17", + "cpufeatures 0.3.0", ] [[package]] @@ -2787,7 +2788,7 @@ dependencies = [ "pairing 0.23.0", "rand_core 0.6.4", "subtle", - "zkm-lib 1.2.4", + "zkm-lib 1.2.4 (git+https://github.com/ProjectZKM/Ziren)", ] [[package]] @@ -2944,7 +2945,7 @@ checksum = "2d886547e41f740c616ae73108f6eb70afe6d940c7bc697cb30f13daec073037" dependencies = [ "camino", "cargo-platform", - "semver 1.0.27", + "semver 1.0.28", "serde", "serde_json", "thiserror 1.0.69", @@ -2972,9 +2973,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.2.57" +version = "1.2.59" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a0dd1ca384932ff3641c8718a02769f1698e7563dc6974ffd03346116310423" +checksum = "b7a4d3ec6524d28a329fc53654bbadc9bdd7b0431f5d65f1a56ffb28a1ee5283" dependencies = [ "find-msvc-tools", "jobserver", @@ -3138,14 +3139,14 @@ dependencies = [ "tempfile", "tokio", "tracing", - "uuid 1.22.0", + "uuid 1.23.0", ] [[package]] name = "cmake" -version = "0.1.57" +version = "0.1.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75443c44cd6b379beb8c5b45d85d0773baf31cce901fe7bb252f4eff3008ef7d" +checksum = "c0f78a02292a74a88ac736019ab962ece0bc380e3f977bf72e376c5d78ff0678" dependencies = [ "cc", ] @@ -4267,29 +4268,6 @@ dependencies = [ "syn 2.0.117", ] -[[package]] -name = "env_filter" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32e90c2accc4b07a8456ea0debdc2e7587bdd890680d71173a15d4ae604f6eef" -dependencies = [ - "log", - "regex", -] - -[[package]] -name = "env_logger" -version = "0.11.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0621c04f2196ac3f488dd583365b9c09be011a4ab8b9f37248ffcc8f6198b56a" -dependencies = [ - "anstream", - "anstyle", - "env_filter", - "jiff", - "log", -] - [[package]] name = "equivalent" version = "1.0.2" @@ -4528,7 +4506,7 @@ dependencies = [ "chrono", "ethers-core", "reqwest 0.11.27", - "semver 1.0.27", + "semver 1.0.28", "serde", "serde_json", "thiserror 1.0.69", @@ -4637,7 +4615,7 @@ dependencies = [ "path-slash", "rayon", "regex", - "semver 1.0.27", + "semver 1.0.28", "serde", "serde_json", "solang-parser", @@ -4689,9 +4667,9 @@ dependencies = [ [[package]] name = "fastrand" -version = "2.3.0" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" +checksum = "9f1f227452a390804cdb637b74a86990f2a7d7ba4b7d5693aac9b4dd6defd8d6" [[package]] name = "fastrlp" @@ -5301,7 +5279,7 @@ dependencies = [ "futures-sink", "futures-util", "http 0.2.12", - "indexmap 2.13.0", + "indexmap 2.13.1", "slab", "tokio", "tokio-util", @@ -5320,7 +5298,7 @@ dependencies = [ "futures-core", "futures-sink", "http 1.4.0", - "indexmap 2.13.0", + "indexmap 2.13.1", "slab", "tokio", "tokio-util", @@ -5831,9 +5809,9 @@ dependencies = [ [[package]] name = "hyper" -version = "1.8.1" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ab2d4f250c3d7b1c9fcdff1cece94ea4e2dfbec68614f7b87cb205f24ca9d11" +checksum = "6299f016b246a94207e63da54dbe807655bf9e00044f73ded42c3ac5305fbcca" dependencies = [ "atomic-waker", "bytes", @@ -5846,7 +5824,6 @@ dependencies = [ "httpdate", "itoa", "pin-project-lite", - "pin-utils", "smallvec", "tokio", "want", @@ -5873,7 +5850,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3c93eb611681b207e1fe55d5a71ecf91572ec8a6705cdb6857f7d8d5242cf58" dependencies = [ "http 1.4.0", - "hyper 1.8.1", + "hyper 1.9.0", "hyper-util", "rustls 0.23.37", "rustls-pki-types", @@ -5920,7 +5897,7 @@ dependencies = [ "futures-util", "http 1.4.0", "http-body 1.0.1", - "hyper 1.8.1", + "hyper 1.9.0", "ipnet", "libc", "percent-encoding", @@ -5957,12 +5934,13 @@ dependencies = [ [[package]] name = "icu_collections" -version = "2.1.1" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c6b649701667bbe825c3b7e6388cb521c23d88644678e83c0c4d0a621a34b43" +checksum = "2984d1cd16c883d7935b9e07e44071dca8d917fd52ecc02c04d5fa0b5a3f191c" dependencies = [ "displaydoc", "potential_utf", + "utf8_iter", "yoke", "zerofrom", "zerovec", @@ -5970,9 +5948,9 @@ dependencies = [ [[package]] name = "icu_locale_core" -version = "2.1.1" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edba7861004dd3714265b4db54a3c390e880ab658fec5f7db895fae2046b5bb6" +checksum = "92219b62b3e2b4d88ac5119f8904c10f8f61bf7e95b640d25ba3075e6cac2c29" dependencies = [ "displaydoc", "litemap", @@ -5983,9 +5961,9 @@ dependencies = [ [[package]] name = "icu_normalizer" -version = "2.1.1" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f6c8828b67bf8908d82127b2054ea1b4427ff0230ee9141c54251934ab1b599" +checksum = "c56e5ee99d6e3d33bd91c5d85458b6005a22140021cc324cea84dd0e72cff3b4" dependencies = [ "icu_collections", "icu_normalizer_data", @@ -5997,15 +5975,15 @@ dependencies = [ [[package]] name = "icu_normalizer_data" -version = "2.1.1" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7aedcccd01fc5fe81e6b489c15b247b8b0690feb23304303a9e560f37efc560a" +checksum = "da3be0ae77ea334f4da67c12f149704f19f81d1adf7c51cf482943e84a2bad38" [[package]] name = "icu_properties" -version = "2.1.2" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "020bfc02fe870ec3a66d93e677ccca0562506e5872c650f893269e08615d74ec" +checksum = "bee3b67d0ea5c2cca5003417989af8996f8604e34fb9ddf96208a033901e70de" dependencies = [ "icu_collections", "icu_locale_core", @@ -6017,15 +5995,15 @@ dependencies = [ [[package]] name = "icu_properties_data" -version = "2.1.2" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "616c294cf8d725c6afcd8f55abc17c56464ef6211f9ed59cccffe534129c77af" +checksum = "8e2bbb201e0c04f7b4b3e14382af113e17ba4f63e2c9d2ee626b720cbce54a14" [[package]] name = "icu_provider" -version = "2.1.1" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85962cf0ce02e1e0a629cc34e7ca3e373ce20dda4c4d7294bbd0bf1fdb59e614" +checksum = "139c4cf31c8b5f33d7e199446eff9c1e02decfc2f0eec2c8d71f65befa45b421" dependencies = [ "displaydoc", "icu_locale_core", @@ -6114,7 +6092,7 @@ dependencies = [ "futures", "http 1.4.0", "http-body-util", - "hyper 1.8.1", + "hyper 1.9.0", "hyper-util", "log", "rand 0.8.5", @@ -6180,9 +6158,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.13.0" +version = "2.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7714e70437a7dc3ac8eb7e6f8df75fd8eb422675fc7678aff7364301092b1017" +checksum = "45a8a2b9cb3e0b0c1803dbb0758ffac5de2f425b23c28f518faabd9d805342ff" dependencies = [ "equivalent", "hashbrown 0.16.1", @@ -6276,9 +6254,9 @@ dependencies = [ [[package]] name = "iri-string" -version = "0.7.11" +version = "0.7.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8e7418f59cc01c88316161279a7f665217ae316b388e58a0d10e29f54f1e5eb" +checksum = "25e659a4bb38e810ebc252e53b5814ff908a8c58c2a9ce2fae1bbec24cbf4e20" dependencies = [ "memchr", "serde", @@ -6332,30 +6310,6 @@ version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" -[[package]] -name = "jiff" -version = "0.2.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a3546dc96b6d42c5f24902af9e2538e82e39ad350b0c766eb3fbf2d8f3d8359" -dependencies = [ - "jiff-static", - "log", - "portable-atomic", - "portable-atomic-util", - "serde_core", -] - -[[package]] -name = "jiff-static" -version = "0.2.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a8c8b344124222efd714b73bb41f8b5120b27a7cc1c75593a6ff768d9d05aa4" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", -] - [[package]] name = "jni" version = "0.21.1" @@ -6412,10 +6366,12 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.91" +version = "0.3.94" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b49715b7073f385ba4bc528e5747d02e66cb39c6146efb66b781f131f0fb399c" +checksum = "2e04e2ef80ce82e13552136fabeef8a5ed1f985a96805761cbb9a2c34e7664d9" dependencies = [ + "cfg-if", + "futures-util", "once_cell", "wasm-bindgen", ] @@ -6486,9 +6442,9 @@ dependencies = [ [[package]] name = "keccak-asm" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b646a74e746cd25045aa0fd42f4f7f78aa6d119380182c7e63a5593c4ab8df6f" +checksum = "fa468878266ad91431012b3e5ef1bf9b170eab22883503a318d46857afa4579a" dependencies = [ "digest 0.10.7", "sha3-asm", @@ -6563,9 +6519,9 @@ checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" [[package]] name = "libc" -version = "0.2.183" +version = "0.2.184" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5b646652bf6661599e1da8901b3b9522896f01e736bad5f723fe7a3a27f899d" +checksum = "48f5d2a454e16a5ea0f4ced81bd44e4cfc7bd3a507b61887c99fd3538b28e4af" [[package]] name = "libgit2-sys" @@ -7106,9 +7062,9 @@ dependencies = [ [[package]] name = "libz-sys" -version = "1.1.25" +version = "1.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d52f4c29e2a68ac30c9087e1b772dc9f44a2b66ed44edf2266cf2be9b03dafc1" +checksum = "fc3a226e576f50782b3305c5ccf458698f92798987f551c6a02efe8276721e22" dependencies = [ "cc", "libc", @@ -7136,9 +7092,9 @@ checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53" [[package]] name = "litemap" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6373607a59f0be73a39b6fe456b8192fcc3585f602af20751600e974dd455e77" +checksum = "92daf443525c4cce67b150400bc2316076100ce0b3686209eb8cf3c31612e6f0" [[package]] name = "lock_api" @@ -7334,9 +7290,9 @@ dependencies = [ [[package]] name = "mio" -version = "1.1.1" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a69bcab0ad47271a0234d9422b131806bf3968021e5dc9328caf2d4cd58557fc" +checksum = "50b7e5b27aa02a74bac8c3f23f448f8d87ff11f92d3aac1a6ed369ee08cc56c1" dependencies = [ "libc", "wasi", @@ -7378,7 +7334,7 @@ dependencies = [ "portable-atomic", "smallvec", "tagptr", - "uuid 1.22.0", + "uuid 1.23.0", ] [[package]] @@ -8638,7 +8594,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db" dependencies = [ "fixedbitset 0.4.2", - "indexmap 2.13.0", + "indexmap 2.13.1", ] [[package]] @@ -8648,7 +8604,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3672b37090dbd86368a4145bc067582552b29c27377cad4e0a306c97f9bd7772" dependencies = [ "fixedbitset 0.5.7", - "indexmap 2.13.0", + "indexmap 2.13.1", ] [[package]] @@ -8956,20 +8912,11 @@ version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c33a9471896f1c69cecef8d20cbe2f7accd12527ce60845ff44c153bb2a21b49" -[[package]] -name = "portable-atomic-util" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "091397be61a01d4be58e7841595bd4bfedb15f1cd54977d79b8271e94ed799a3" -dependencies = [ - "portable-atomic", -] - [[package]] name = "potential_utf" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b73949432f5e2a09657003c25bca5e19a0e9c84f8058ca374f49e0ebe605af77" +checksum = "0103b1cef7ec0cf76490e969665504990193874ea05c85ff9bab8b911d0a0564" dependencies = [ "zerovec", ] @@ -9063,7 +9010,7 @@ version = "3.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e67ba7e9b2b56446f1d419b1d807906278ffa1a658a8a5d8a39dcb1f5a78614f" dependencies = [ - "toml_edit 0.25.8+spec-1.1.0", + "toml_edit 0.25.11+spec-1.1.0", ] [[package]] @@ -9195,7 +9142,7 @@ dependencies = [ "tracing", "tracing-subscriber 0.3.23", "util", - "uuid 1.22.0", + "uuid 1.23.0", "watchtower-proof", ] @@ -9376,7 +9323,7 @@ dependencies = [ "pin-project-lite", "quinn-proto", "quinn-udp", - "rustc-hash 2.1.1", + "rustc-hash 2.1.2", "rustls 0.23.37", "socket2 0.6.3", "thiserror 2.0.18", @@ -9397,7 +9344,7 @@ dependencies = [ "lru-slab", "rand 0.9.2", "ring 0.17.14", - "rustc-hash 2.1.1", + "rustc-hash 2.1.2", "rustls 0.23.37", "rustls-pki-types", "slab", @@ -9733,7 +9680,7 @@ dependencies = [ "http 1.4.0", "http-body 1.0.1", "http-body-util", - "hyper 1.8.1", + "hyper 1.9.0", "hyper-rustls 0.27.7", "hyper-util", "js-sys", @@ -9774,7 +9721,7 @@ dependencies = [ "http 1.4.0", "http-body 1.0.1", "http-body-util", - "hyper 1.8.1", + "hyper 1.9.0", "hyper-rustls 0.27.7", "hyper-util", "js-sys", @@ -10647,9 +10594,9 @@ checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" [[package]] name = "rustc-hash" -version = "2.1.1" +version = "2.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" +checksum = "94300abf3f1ae2e2b8ffb7b58043de3d399c73fa6f4b73826402a5c457614dbe" [[package]] name = "rustc-hex" @@ -10672,7 +10619,7 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" dependencies = [ - "semver 1.0.27", + "semver 1.0.28", ] [[package]] @@ -11041,7 +10988,7 @@ version = "0.28.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d24b59d129cdadea20aea4fb2352fa053712e5d713eee47d700cd4b2bc002f10" dependencies = [ - "bitcoin_hashes 0.13.0", + "bitcoin_hashes 0.13.1", "secp256k1-sys 0.9.2", ] @@ -11134,9 +11081,9 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.27" +version = "1.0.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2" +checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" dependencies = [ "serde", "serde_core", @@ -11298,7 +11245,7 @@ dependencies = [ "chrono", "hex", "indexmap 1.9.3", - "indexmap 2.13.0", + "indexmap 2.13.1", "schemars 0.9.0", "schemars 1.2.1", "serde_core", @@ -11402,9 +11349,9 @@ dependencies = [ [[package]] name = "sha3-asm" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b31139435f327c93c6038ed350ae4588e2c70a13d50599509fee6349967ba35a" +checksum = "59cbb88c189d6352cc8ae96a39d19c7ecad8f7330b29461187f2587fdc2988d5" dependencies = [ "cc", "cfg-if", @@ -11468,9 +11415,9 @@ dependencies = [ [[package]] name = "simd-adler32" -version = "0.3.8" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e320a6c5ad31d271ad523dcf3ad13e2767ad8b1cb8f047f75a8aeaf8da139da2" +checksum = "703d5c7ef118737c72f1af64ad2f6f8c5e1921f818cdcb97b8fe6fc69bf66214" [[package]] name = "simple_asn1" @@ -11643,7 +11590,7 @@ dependencies = [ "futures-util", "hashbrown 0.15.5", "hashlink 0.10.0", - "indexmap 2.13.0", + "indexmap 2.13.1", "log", "memchr", "once_cell", @@ -11657,7 +11604,7 @@ dependencies = [ "tokio-stream", "tracing", "url", - "uuid 1.22.0", + "uuid 1.23.0", ] [[package]] @@ -11737,7 +11684,7 @@ dependencies = [ "stringprep", "thiserror 2.0.18", "tracing", - "uuid 1.22.0", + "uuid 1.23.0", "whoami", ] @@ -11775,7 +11722,7 @@ dependencies = [ "stringprep", "thiserror 2.0.18", "tracing", - "uuid 1.22.0", + "uuid 1.23.0", "whoami", ] @@ -11801,7 +11748,7 @@ dependencies = [ "thiserror 2.0.18", "tracing", "url", - "uuid 1.22.0", + "uuid 1.23.0", ] [[package]] @@ -11900,7 +11847,7 @@ dependencies = [ "bitcoin 0.32.8", "futures", "hex", - "indexmap 2.13.0", + "indexmap 2.13.1", "reqwest 0.12.28", "serde", "serde_json", @@ -11910,7 +11857,7 @@ dependencies = [ "tokio", "tokio-util", "tracing", - "uuid 1.22.0", + "uuid 1.23.0", "walkdir", ] @@ -12032,7 +11979,7 @@ dependencies = [ "num-bigint 0.4.6", "rand 0.8.5", "rustc-hex", - "zkm-lib 1.2.4", + "zkm-lib 1.2.4 (git+https://github.com/ProjectZKM/Ziren)", ] [[package]] @@ -12067,7 +12014,7 @@ dependencies = [ "hex", "once_cell", "reqwest 0.11.27", - "semver 1.0.27", + "semver 1.0.28", "serde", "serde_json", "sha2 0.10.9", @@ -12315,7 +12262,7 @@ dependencies = [ "pin-project", "rand 0.8.5", "reqwest 0.11.27", - "semver 1.0.27", + "semver 1.0.28", "serde", "serde_bytes", "serde_json", @@ -12329,7 +12276,7 @@ dependencies = [ "tokio", "tracing", "url", - "uuid 1.22.0", + "uuid 1.23.0", "walkdir", ] @@ -12446,9 +12393,9 @@ dependencies = [ [[package]] name = "tinystr" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42d3e9c45c09de15d06dd8acf5f4e0e399e85927b7f00711024eb7ae10fa4869" +checksum = "c8323304221c2a851516f22236c5722a72eaa19749016521d6dff0824447d96d" dependencies = [ "displaydoc", "zerovec", @@ -12471,13 +12418,13 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.50.0" +version = "1.51.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27ad5e34374e03cfffefc301becb44e9dc3c17584f414349ebe29ed26661822d" +checksum = "f66bf9585cda4b724d3e78ab34b73fb2bbaba9011b9bfdf69dc836382ea13b8c" dependencies = [ "bytes", "libc", - "mio 1.1.1", + "mio 1.2.0", "parking_lot", "pin-project-lite", "signal-hook-registry", @@ -12498,9 +12445,9 @@ dependencies = [ [[package]] name = "tokio-macros" -version = "2.6.1" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c55a2eff8b69ce66c84f85e1da1c233edc36ceb85a2058d11b0d6a3c7e7569c" +checksum = "385a6cb71ab9ab790c5fe8d67f1645e6c450a7ce006a33de03daa956cf70a496" dependencies = [ "proc-macro2", "quote", @@ -12648,9 +12595,9 @@ dependencies = [ [[package]] name = "toml_datetime" -version = "1.1.0+spec-1.1.0" +version = "1.1.1+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97251a7c317e03ad83774a8752a7e81fb6067740609f75ea2b585b569a59198f" +checksum = "3165f65f62e28e0115a00b2ebdd37eb6f3b641855f9d636d3cd4103767159ad7" dependencies = [ "serde_core", ] @@ -12661,7 +12608,7 @@ version = "0.22.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" dependencies = [ - "indexmap 2.13.0", + "indexmap 2.13.1", "serde", "serde_spanned", "toml_datetime 0.6.11", @@ -12671,23 +12618,23 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.25.8+spec-1.1.0" +version = "0.25.11+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16bff38f1d86c47f9ff0647e6838d7bb362522bdf44006c7068c2b1e606f1f3c" +checksum = "0b59c4d22ed448339746c59b905d24568fcbb3ab65a500494f7b8c3e97739f2b" dependencies = [ - "indexmap 2.13.0", - "toml_datetime 1.1.0+spec-1.1.0", + "indexmap 2.13.1", + "toml_datetime 1.1.1+spec-1.1.0", "toml_parser", - "winnow 1.0.0", + "winnow 1.0.1", ] [[package]] name = "toml_parser" -version = "1.1.0+spec-1.1.0" +version = "1.1.2+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2334f11ee363607eb04df9b8fc8a13ca1715a72ba8662a26ac285c98aabb4011" +checksum = "a2abe9b86193656635d2411dc43050282ca48aa31c2451210f4202550afb7526" dependencies = [ - "winnow 1.0.0", + "winnow 1.0.1", ] [[package]] @@ -12991,7 +12938,7 @@ dependencies = [ "futures", "http 1.4.0", "http-body-util", - "hyper 1.8.1", + "hyper 1.9.0", "prost 0.13.5", "reqwest 0.12.28", "serde", @@ -13079,9 +13026,9 @@ checksum = "7df058c713841ad818f1dc5d3fd88063241cc61f49f5fbea4b951e8cf5a8d71d" [[package]] name = "unicode-segmentation" -version = "1.13.1" +version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da36089a805484bcccfffe0739803392c8298778a2d2f09febf76fac5ad9025b" +checksum = "9629274872b2bfaf8d66f5f15725007f635594914870f65218920345aa11aa8c" [[package]] name = "unicode-width" @@ -13190,9 +13137,9 @@ dependencies = [ [[package]] name = "uuid" -version = "1.22.0" +version = "1.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a68d3c8f01c0cfa54a75291d83601161799e4a89a39e0929f4b0354d88757a37" +checksum = "5ac8b6f42ead25368cf5b098aeb3dc8a1a2c05a3eee8a9a1a68c640edbfc79d9" dependencies = [ "getrandom 0.4.2", "js-sys", @@ -13307,9 +13254,9 @@ checksum = "b8dad83b4f25e74f184f64c43b150b91efe7647395b42289f38e50566d82855b" [[package]] name = "wasm-bindgen" -version = "0.2.114" +version = "0.2.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6532f9a5c1ece3798cb1c2cfdba640b9b3ba884f5db45973a6f442510a87d38e" +checksum = "0551fc1bb415591e3372d0bc4780db7e587d84e2a7e79da121051c5c4b89d0b0" dependencies = [ "cfg-if", "once_cell", @@ -13320,23 +13267,19 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.64" +version = "0.4.67" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9c5522b3a28661442748e09d40924dfb9ca614b21c00d3fd135720e48b67db8" +checksum = "03623de6905b7206edd0a75f69f747f134b7f0a2323392d664448bf2d3c5d87e" dependencies = [ - "cfg-if", - "futures-util", "js-sys", - "once_cell", "wasm-bindgen", - "web-sys", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.114" +version = "0.2.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18a2d50fcf105fb33bb15f00e7a77b772945a2ee45dcf454961fd843e74c18e6" +checksum = "7fbdf9a35adf44786aecd5ff89b4563a90325f9da0923236f6104e603c7e86be" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -13344,9 +13287,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.114" +version = "0.2.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03ce4caeaac547cdf713d280eda22a730824dd11e6b8c3ca9e42247b25c631e3" +checksum = "dca9693ef2bab6d4e6707234500350d8dad079eb508dca05530c85dc3a529ff2" dependencies = [ "bumpalo", "proc-macro2", @@ -13357,9 +13300,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.114" +version = "0.2.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75a326b8c223ee17883a4251907455a2431acc2791c98c26279376490c378c16" +checksum = "39129a682a6d2d841b6c429d0c51e5cb0ed1a03829d8b3d1e69a011e62cb3d3b" dependencies = [ "unicode-ident", ] @@ -13381,7 +13324,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bb0e353e6a2fbdc176932bbaab493762eb1255a7900fe0fea1a2f96c296cc909" dependencies = [ "anyhow", - "indexmap 2.13.0", + "indexmap 2.13.1", "wasm-encoder", "wasmparser", ] @@ -13407,8 +13350,8 @@ checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" dependencies = [ "bitflags 2.11.0", "hashbrown 0.15.5", - "indexmap 2.13.0", - "semver 1.0.27", + "indexmap 2.13.1", + "semver 1.0.28", ] [[package]] @@ -13463,9 +13406,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.91" +version = "0.3.94" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "854ba17bb104abfb26ba36da9729addc7ce7f06f5c0f90f3c391f8461cca21f9" +checksum = "cd70027e39b12f0849461e08ffc50b9cd7688d942c1c8e3c7b22273236b4dd0a" dependencies = [ "js-sys", "wasm-bindgen", @@ -14031,9 +13974,9 @@ dependencies = [ [[package]] name = "winnow" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a90e88e4667264a994d34e6d1ab2d26d398dcdca8b7f52bec8668957517fc7d8" +checksum = "09dac053f1cd375980747450bfc7250c264eaae0583872e845c0c7cd578872b5" dependencies = [ "memchr", ] @@ -14076,7 +14019,7 @@ checksum = "b7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21" dependencies = [ "anyhow", "heck 0.5.0", - "indexmap 2.13.0", + "indexmap 2.13.1", "prettyplease 0.2.37", "syn 2.0.117", "wasm-metadata", @@ -14107,7 +14050,7 @@ checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2" dependencies = [ "anyhow", "bitflags 2.11.0", - "indexmap 2.13.0", + "indexmap 2.13.1", "log", "serde", "serde_derive", @@ -14126,9 +14069,9 @@ checksum = "ecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736" dependencies = [ "anyhow", "id-arena", - "indexmap 2.13.0", + "indexmap 2.13.1", "log", - "semver 1.0.27", + "semver 1.0.28", "serde", "serde_derive", "serde_json", @@ -14138,9 +14081,9 @@ dependencies = [ [[package]] name = "writeable" -version = "0.6.2" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9edde0db4769d2dc68579893f2306b26c6ecfbe0ef499b013d731b7b9247e0b9" +checksum = "1ffae5123b2d3fc086436f8834ae3ab053a283cfac8fe0a0b8eaae044768a4c4" [[package]] name = "ws_stream_wasm" @@ -14262,9 +14205,9 @@ dependencies = [ [[package]] name = "yoke" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72d6e5c6afb84d73944e5cedb052c4680d5657337201555f9f2a16b7406d4954" +checksum = "abe8c5fda708d9ca3df187cae8bfb9ceda00dd96231bed36e445a1a48e66f9ca" dependencies = [ "stable_deref_trait", "yoke-derive", @@ -14273,9 +14216,9 @@ dependencies = [ [[package]] name = "yoke-derive" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d" +checksum = "de844c262c8848816172cef550288e7dc6c7b7814b4ee56b3e1553f275f1858e" dependencies = [ "proc-macro2", "quote", @@ -14285,18 +14228,18 @@ dependencies = [ [[package]] name = "zerocopy" -version = "0.8.47" +version = "0.8.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efbb2a062be311f2ba113ce66f697a4dc589f85e78a4aea276200804cea0ed87" +checksum = "eed437bf9d6692032087e337407a86f04cd8d6a16a37199ed57949d415bd68e9" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.8.47" +version = "0.8.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e8bc7269b54418e7aeeef514aa68f8690b8c0489a06b0136e5f57c4c5ccab89" +checksum = "70e3cd084b1788766f53af483dd21f93881ff30d7320490ec3ef7526d203bad4" dependencies = [ "proc-macro2", "quote", @@ -14305,18 +14248,18 @@ dependencies = [ [[package]] name = "zerofrom" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5" +checksum = "69faa1f2a1ea75661980b013019ed6687ed0e83d069bc1114e2cc74c6c04c4df" dependencies = [ "zerofrom-derive", ] [[package]] name = "zerofrom-derive" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" +checksum = "11532158c46691caf0f2593ea8358fed6bbf68a0315e80aae9bd41fbade684a1" dependencies = [ "proc-macro2", "quote", @@ -14346,9 +14289,9 @@ dependencies = [ [[package]] name = "zerotrie" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a59c17a5562d507e4b54960e8569ebee33bee890c70aa3fe7b97e85a9fd7851" +checksum = "0f9152d31db0792fa83f70fb2f83148effb5c1f5b8c7686c3459e361d9bc20bf" dependencies = [ "displaydoc", "yoke", @@ -14357,9 +14300,9 @@ dependencies = [ [[package]] name = "zerovec" -version = "0.11.5" +version = "0.11.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c28719294829477f525be0186d13efa9a3c602f7ec202ca9e353d310fb9a002" +checksum = "90f911cbc359ab6af17377d242225f4d75119aec87ea711a880987b18cd7b239" dependencies = [ "yoke", "zerofrom", @@ -14368,9 +14311,9 @@ dependencies = [ [[package]] name = "zerovec-derive" -version = "0.11.2" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3" +checksum = "625dc425cab0dca6dc3c3319506e6593dcb08a9f387ea3b284dbd52a92c40555" dependencies = [ "proc-macro2", "quote", @@ -14426,8 +14369,8 @@ dependencies = [ [[package]] name = "zkm-build" -version = "1.2.5" -source = "git+https://github.com/blake-pro/Ziren.git?branch=pre-release-v1.2.5#a7446e7ef377c12fb2a42e6082f234ae0949536a" +version = "1.2.4" +source = "git+https://github.com/blake-pro/Ziren.git?branch=v1.2.4-imm#f40ebf9c916689d7454425eda5f9fa18a50395e2" dependencies = [ "anyhow", "cargo_metadata", @@ -14437,15 +14380,14 @@ dependencies = [ [[package]] name = "zkm-core-executor" -version = "1.2.5" -source = "git+https://github.com/blake-pro/Ziren.git?branch=pre-release-v1.2.5#a7446e7ef377c12fb2a42e6082f234ae0949536a" +version = "1.2.4" +source = "git+https://github.com/blake-pro/Ziren.git?branch=v1.2.4-imm#f40ebf9c916689d7454425eda5f9fa18a50395e2" dependencies = [ "anyhow", "bincode", "bytemuck", "elf", "enum-map", - "env_logger", "eyre", "hashbrown 0.14.5", "hex", @@ -14453,7 +14395,6 @@ dependencies = [ "log", "nohash-hasher", "num", - "num_enum", "p3-field", "p3-koala-bear", "p3-maybe-rayon", @@ -14468,7 +14409,6 @@ dependencies = [ "thiserror 1.0.69", "tiny-keccak", "tracing", - "tracing-subscriber 0.3.23", "typenum", "vec_map", "zkm-curves", @@ -14478,12 +14418,11 @@ dependencies = [ [[package]] name = "zkm-core-machine" -version = "1.2.5" -source = "git+https://github.com/blake-pro/Ziren.git?branch=pre-release-v1.2.5#a7446e7ef377c12fb2a42e6082f234ae0949536a" +version = "1.2.4" +source = "git+https://github.com/blake-pro/Ziren.git?branch=v1.2.4-imm#f40ebf9c916689d7454425eda5f9fa18a50395e2" dependencies = [ "bincode", "cfg-if", - "crossbeam-channel", "elliptic-curve", "generic-array 1.3.5", "hashbrown 0.14.5", @@ -14531,8 +14470,8 @@ dependencies = [ [[package]] name = "zkm-cuda" -version = "1.2.5" -source = "git+https://github.com/blake-pro/Ziren.git?branch=pre-release-v1.2.5#a7446e7ef377c12fb2a42e6082f234ae0949536a" +version = "1.2.4" +source = "git+https://github.com/blake-pro/Ziren.git?branch=v1.2.4-imm#f40ebf9c916689d7454425eda5f9fa18a50395e2" dependencies = [ "bincode", "ctrlc", @@ -14549,8 +14488,8 @@ dependencies = [ [[package]] name = "zkm-curves" -version = "1.2.5" -source = "git+https://github.com/blake-pro/Ziren.git?branch=pre-release-v1.2.5#a7446e7ef377c12fb2a42e6082f234ae0949536a" +version = "1.2.4" +source = "git+https://github.com/blake-pro/Ziren.git?branch=v1.2.4-imm#f40ebf9c916689d7454425eda5f9fa18a50395e2" dependencies = [ "cfg-if", "curve25519-dalek", @@ -14573,10 +14512,9 @@ dependencies = [ [[package]] name = "zkm-derive" -version = "1.2.5" -source = "git+https://github.com/blake-pro/Ziren.git?branch=pre-release-v1.2.5#a7446e7ef377c12fb2a42e6082f234ae0949536a" +version = "1.2.4" +source = "git+https://github.com/blake-pro/Ziren.git?branch=v1.2.4-imm#f40ebf9c916689d7454425eda5f9fa18a50395e2" dependencies = [ - "proc-macro2", "quote", "syn 1.0.109", ] @@ -14584,7 +14522,7 @@ dependencies = [ [[package]] name = "zkm-lib" version = "1.2.4" -source = "git+https://github.com/ProjectZKM/Ziren#d5b7577c683dfceeecb90325d3277d34dc52bf17" +source = "git+https://github.com/blake-pro/Ziren.git?branch=v1.2.4-imm#f40ebf9c916689d7454425eda5f9fa18a50395e2" dependencies = [ "bincode", "cfg-if", @@ -14596,8 +14534,8 @@ dependencies = [ [[package]] name = "zkm-lib" -version = "1.2.5" -source = "git+https://github.com/blake-pro/Ziren.git?branch=pre-release-v1.2.5#a7446e7ef377c12fb2a42e6082f234ae0949536a" +version = "1.2.4" +source = "git+https://github.com/ProjectZKM/Ziren#1d43121312d4b93c0989984bf0c7ab77d9a0ce04" dependencies = [ "bincode", "cfg-if", @@ -14609,8 +14547,8 @@ dependencies = [ [[package]] name = "zkm-primitives" -version = "1.2.5" -source = "git+https://github.com/blake-pro/Ziren.git?branch=pre-release-v1.2.5#a7446e7ef377c12fb2a42e6082f234ae0949536a" +version = "1.2.4" +source = "git+https://github.com/blake-pro/Ziren.git?branch=v1.2.4-imm#f40ebf9c916689d7454425eda5f9fa18a50395e2" dependencies = [ "bincode", "hex", @@ -14627,13 +14565,12 @@ dependencies = [ [[package]] name = "zkm-prover" -version = "1.2.5" -source = "git+https://github.com/blake-pro/Ziren.git?branch=pre-release-v1.2.5#a7446e7ef377c12fb2a42e6082f234ae0949536a" +version = "1.2.4" +source = "git+https://github.com/blake-pro/Ziren.git?branch=v1.2.4-imm#f40ebf9c916689d7454425eda5f9fa18a50395e2" dependencies = [ "anyhow", "bincode", "clap", - "crossbeam-channel", "dirs", "eyre", "itertools 0.13.0", @@ -14665,8 +14602,8 @@ dependencies = [ [[package]] name = "zkm-recursion-circuit" -version = "1.2.5" -source = "git+https://github.com/blake-pro/Ziren.git?branch=pre-release-v1.2.5#a7446e7ef377c12fb2a42e6082f234ae0949536a" +version = "1.2.4" +source = "git+https://github.com/blake-pro/Ziren.git?branch=v1.2.4-imm#f40ebf9c916689d7454425eda5f9fa18a50395e2" dependencies = [ "hashbrown 0.14.5", "itertools 0.13.0", @@ -14698,8 +14635,8 @@ dependencies = [ [[package]] name = "zkm-recursion-compiler" -version = "1.2.5" -source = "git+https://github.com/blake-pro/Ziren.git?branch=pre-release-v1.2.5#a7446e7ef377c12fb2a42e6082f234ae0949536a" +version = "1.2.4" +source = "git+https://github.com/blake-pro/Ziren.git?branch=v1.2.4-imm#f40ebf9c916689d7454425eda5f9fa18a50395e2" dependencies = [ "backtrace", "itertools 0.13.0", @@ -14719,8 +14656,8 @@ dependencies = [ [[package]] name = "zkm-recursion-core" -version = "1.2.5" -source = "git+https://github.com/blake-pro/Ziren.git?branch=pre-release-v1.2.5#a7446e7ef377c12fb2a42e6082f234ae0949536a" +version = "1.2.4" +source = "git+https://github.com/blake-pro/Ziren.git?branch=v1.2.4-imm#f40ebf9c916689d7454425eda5f9fa18a50395e2" dependencies = [ "backtrace", "ff 0.13.1", @@ -14756,8 +14693,8 @@ dependencies = [ [[package]] name = "zkm-recursion-derive" -version = "1.2.5" -source = "git+https://github.com/blake-pro/Ziren.git?branch=pre-release-v1.2.5#a7446e7ef377c12fb2a42e6082f234ae0949536a" +version = "1.2.4" +source = "git+https://github.com/blake-pro/Ziren.git?branch=v1.2.4-imm#f40ebf9c916689d7454425eda5f9fa18a50395e2" dependencies = [ "quote", "syn 1.0.109", @@ -14765,8 +14702,8 @@ dependencies = [ [[package]] name = "zkm-recursion-gnark-ffi" -version = "1.2.5" -source = "git+https://github.com/blake-pro/Ziren.git?branch=pre-release-v1.2.5#a7446e7ef377c12fb2a42e6082f234ae0949536a" +version = "1.2.4" +source = "git+https://github.com/blake-pro/Ziren.git?branch=v1.2.4-imm#f40ebf9c916689d7454425eda5f9fa18a50395e2" dependencies = [ "anyhow", "bincode", @@ -14789,11 +14726,11 @@ dependencies = [ [[package]] name = "zkm-sdk" -version = "1.2.5" -source = "git+https://github.com/blake-pro/Ziren.git?branch=pre-release-v1.2.5#a7446e7ef377c12fb2a42e6082f234ae0949536a" +version = "1.2.4" +source = "git+https://github.com/blake-pro/Ziren.git?branch=v1.2.4-imm#f40ebf9c916689d7454425eda5f9fa18a50395e2" dependencies = [ "alloy-primitives", - "alloy-signer 1.6.3", + "alloy-signer 1.8.3 (registry+https://github.com/rust-lang/crates.io-index)", "anyhow", "async-trait", "bincode", @@ -14823,7 +14760,7 @@ dependencies = [ "tonic-build", "tracing", "twirp-rs", - "uuid 1.22.0", + "uuid 1.23.0", "vergen", "zkm-build", "zkm-core-executor", @@ -14836,8 +14773,8 @@ dependencies = [ [[package]] name = "zkm-stark" -version = "1.2.5" -source = "git+https://github.com/blake-pro/Ziren.git?branch=pre-release-v1.2.5#a7446e7ef377c12fb2a42e6082f234ae0949536a" +version = "1.2.4" +source = "git+https://github.com/blake-pro/Ziren.git?branch=v1.2.4-imm#f40ebf9c916689d7454425eda5f9fa18a50395e2" dependencies = [ "arrayref", "hashbrown 0.14.5", @@ -14878,8 +14815,8 @@ dependencies = [ [[package]] name = "zkm-verifier" -version = "1.2.5" -source = "git+https://github.com/blake-pro/Ziren.git?branch=pre-release-v1.2.5#a7446e7ef377c12fb2a42e6082f234ae0949536a" +version = "1.2.4" +source = "git+https://github.com/blake-pro/Ziren.git?branch=v1.2.4-imm#f40ebf9c916689d7454425eda5f9fa18a50395e2" dependencies = [ "anyhow", "ark-bn254", @@ -14914,8 +14851,8 @@ dependencies = [ [[package]] name = "zkm-zkvm" -version = "1.2.5" -source = "git+https://github.com/blake-pro/Ziren.git?branch=pre-release-v1.2.5#a7446e7ef377c12fb2a42e6082f234ae0949536a" +version = "1.2.4" +source = "git+https://github.com/blake-pro/Ziren.git?branch=v1.2.4-imm#f40ebf9c916689d7454425eda5f9fa18a50395e2" dependencies = [ "bincode", "cfg-if", @@ -14927,7 +14864,7 @@ dependencies = [ "rand 0.8.5", "serde", "sha2 0.10.9", - "zkm-lib 1.2.5", + "zkm-lib 1.2.4 (git+https://github.com/blake-pro/Ziren.git?branch=v1.2.4-imm)", "zkm-primitives", ] diff --git a/Cargo.toml b/Cargo.toml index f1b85e34..37b67fe8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -179,10 +179,10 @@ rust.rust_2018_idioms = { level = "deny", priority = -1 } rustdoc.all = "warn" [patch."https://github.com/ProjectZKM/Ziren"] -zkm-build = { git = "https://github.com/blake-pro/Ziren.git", branch = "pre-release-v1.2.5" } -zkm-core-executor = { git = "https://github.com/blake-pro/Ziren.git", branch = "pre-release-v1.2.5" } -zkm-prover = { git = "https://github.com/blake-pro/Ziren.git", branch = "pre-release-v1.2.5" } -zkm-sdk = { git = "https://github.com/blake-pro/Ziren.git", branch = "pre-release-v1.2.5" } -zkm-verifier = { git = "https://github.com/blake-pro/Ziren.git", branch = "pre-release-v1.2.5" } -zkm-primitives = { git = "https://github.com/blake-pro/Ziren.git", branch = "pre-release-v1.2.5" } -zkm-zkvm = { git = "https://github.com/blake-pro/Ziren.git", branch = "pre-release-v1.2.5" } \ No newline at end of file +zkm-build = { git = "https://github.com/blake-pro/Ziren.git", branch = "v1.2.4-imm" } +zkm-core-executor = { git = "https://github.com/blake-pro/Ziren.git", branch = "v1.2.4-imm" } +zkm-prover = { git = "https://github.com/blake-pro/Ziren.git", branch = "v1.2.4-imm" } +zkm-sdk = { git = "https://github.com/blake-pro/Ziren.git", branch = "v1.2.4-imm" } +zkm-verifier = { git = "https://github.com/blake-pro/Ziren.git", branch = "v1.2.4-imm" } +zkm-primitives = { git = "https://github.com/blake-pro/Ziren.git", branch = "v1.2.4-imm" } +zkm-zkvm = { git = "https://github.com/blake-pro/Ziren.git", branch = "v1.2.4-imm" } \ No newline at end of file diff --git a/circuits/commit-chain-proof/guest/Cargo.toml b/circuits/commit-chain-proof/guest/Cargo.toml index 9dd816c1..ac64881a 100644 --- a/circuits/commit-chain-proof/guest/Cargo.toml +++ b/circuits/commit-chain-proof/guest/Cargo.toml @@ -39,5 +39,5 @@ secp256k1-v0-29-1 = { git = "https://github.com/ziren-patches/rust-secp256k1", p #secp256k1-v0-30-0 = { git = "https://github.com/ziren-patches/rust-secp256k1", package = "secp256k1", branch = "patch-0.30.0" } [patch."https://github.com/ProjectZKM/Ziren"] -zkm-zkvm = { git = "https://github.com/blake-pro/Ziren.git", branch = "pre-release-v1.2.5" } -zkm-verifier = { git = "https://github.com/blake-pro/Ziren.git", branch = "pre-release-v1.2.5" } +zkm-zkvm = { git = "https://github.com/blake-pro/Ziren.git", branch = "v1.2.4-imm" } +zkm-verifier = { git = "https://github.com/blake-pro/Ziren.git", branch = "v1.2.4-imm" } diff --git a/circuits/commit-chain-proof/host/src/lib.rs b/circuits/commit-chain-proof/host/src/lib.rs index 17131b1d..936d059d 100644 --- a/circuits/commit-chain-proof/host/src/lib.rs +++ b/circuits/commit-chain-proof/host/src/lib.rs @@ -221,7 +221,7 @@ impl ProofBuilder for CommitChainProofBuilder { Vec::new(), Vec::new(), Vec::new(), - String::new(), + "v1.2.4".into(), ), }; @@ -265,9 +265,10 @@ impl ProofBuilder for CommitChainProofBuilder { tracing::info!("Commit chain proof cycles: {}", cycles); - if let Err(e) = self.client.verify(&proof, &self.verifying_key) { - panic!("{}", e); - } + // todo: verify the proof laterr + // if let Err(e) = self.client.verify(&proof, &self.verifying_key) { + // panic!("{}", e); + // } let input = bincode::serialize(&input)?; Ok((input, proof, cycles, proving_time)) diff --git a/circuits/data/commit-chain/0-1.bin.commits b/circuits/data/commit-chain/0-1.bin.commits index 897f0754..47fa016c 100644 --- a/circuits/data/commit-chain/0-1.bin.commits +++ b/circuits/data/commit-chain/0-1.bin.commits @@ -1 +1 @@ -[{"commit_txn":{"version":2,"lock_time":0,"input":[{"previous_output":"622eeea26cd959df530643268a94d859ebcb3ba0917691a77b830481af640501:0","script_sig":"","sequence":4294967295,"witness":["30440220411d76ca263fee5bcb6b0e18d7aad8232ca0f2e99eaaed0bc8b977169e2f1b6d022053186175329f8714d7802ad0e92365744d087dfdf858f9819142351dbb697d5281","02add57ae77706046bc4af1e9533fb2ccaa96316e656756dd0884407ae72501ce4"]}],"output":[{"value":500,"script_pubkey":"0020e38259e612b85728633fa8b8d00457594ed650fb5c6559b881575f49226d048a"},{"value":0,"script_pubkey":"6a4035e3a5a2736974eac20a6290f79fd153ba4d45df444ec953704f03f8cb3dd5b5070292c12aec12a7b213f65b1deb03c6b59b69620b6a1d9b110bda3a00346878"}]},"genesis_txid":[62,113,183,217,27,117,122,227,144,26,0,59,106,246,51,184,53,250,56,55,165,81,188,30,132,254,190,180,247,102,127,10],"publisher_public_keys":["02add57ae77706046bc4af1e9533fb2ccaa96316e656756dd0884407ae72501ce4","025d415767660a937ee954d08fa09dc055b4a14e5ffc22c38372499dd198cf7aa4","02cb5075f2ff841fa49728a8e7d6b22b471f756cf6b3f7c625dcc5e325ebe7e233"],"threshold":2,"sequencers":[{"address":"9104a28cdf6a00a546a1c365007ebf017b0645af","pub_key":[2,164,213,70,208,195,228,161,14,136,64,141,227,85,111,57,106,134,108,153,204,28,225,73,21,111,180,225,54,254,104,172,110],"power":2000000,"name":null},{"address":"70cce9b7fb446d4ccf793c8cbc12dbef99a10f83","pub_key":[3,196,102,123,104,171,225,100,11,219,187,51,186,113,186,15,45,4,175,100,30,205,166,95,208,95,225,161,219,63,153,87,105],"power":1750000,"name":null},{"address":"fc139929ae753d5580dc6145d9bc8c5c25f73298","pub_key":[3,212,171,157,196,79,116,160,72,222,230,127,158,112,84,118,51,1,46,182,155,255,134,203,202,133,13,89,35,37,29,185,128],"power":1000000,"name":null}],"block_height":119164}] \ No newline at end of file +[{"commit_txn":{"version":2,"lock_time":0,"input":[{"previous_output":"dc3ab4f512c412f417347ee8624bec6fa9ddef4e4ab832e0749986b8fac41812:0","script_sig":"","sequence":4294967295,"witness":["30440220055614d8ae09d309d24df5ff37ccdf0bfd3343abbf92bf72065f8fb5f8526efe022044da12fc0f78d65890dd09dea787d6113f3c511c177db00207ca00bae4df8d4281","02add57ae77706046bc4af1e9533fb2ccaa96316e656756dd0884407ae72501ce4"]}],"output":[{"value":500,"script_pubkey":"0020e38259e612b85728633fa8b8d00457594ed650fb5c6559b881575f49226d048a"},{"value":0,"script_pubkey":"6a40600316026949ac291ff23c2f2b045a92868a9be546ff440d74524ba97d25f22b2b9791b90336e820684537ded50aeb9c5fdf591d5d1992cd5e04a1d74e07a2f7"}]},"genesis_txid":[38,32,132,254,96,19,216,150,70,107,27,2,105,4,169,155,65,232,159,113,86,110,97,178,230,248,167,101,45,5,250,154],"publisher_public_keys":["02add57ae77706046bc4af1e9533fb2ccaa96316e656756dd0884407ae72501ce4","025d415767660a937ee954d08fa09dc055b4a14e5ffc22c38372499dd198cf7aa4","02cb5075f2ff841fa49728a8e7d6b22b471f756cf6b3f7c625dcc5e325ebe7e233"],"threshold":2,"next_publisher_public_keys":null,"next_threshold":null,"sequencers":[{"address":"9104a28cdf6a00a546a1c365007ebf017b0645af","pub_key":[2,164,213,70,208,195,228,161,14,136,64,141,227,85,111,57,106,134,108,153,204,28,225,73,21,111,180,225,54,254,104,172,110],"power":2000000,"name":null},{"address":"70cce9b7fb446d4ccf793c8cbc12dbef99a10f83","pub_key":[3,196,102,123,104,171,225,100,11,219,187,51,186,113,186,15,45,4,175,100,30,205,166,95,208,95,225,161,219,63,153,87,105],"power":1750000,"name":null},{"address":"fc139929ae753d5580dc6145d9bc8c5c25f73298","pub_key":[3,212,171,157,196,79,116,160,72,222,230,127,158,112,84,118,51,1,46,182,155,255,134,203,202,133,13,89,35,37,29,185,128],"power":1100000,"name":null}],"block_height":120054}] \ No newline at end of file diff --git a/circuits/data/commit-chain/1-1.bin.commits b/circuits/data/commit-chain/1-1.bin.commits index 32e2c7a0..7557444f 100644 --- a/circuits/data/commit-chain/1-1.bin.commits +++ b/circuits/data/commit-chain/1-1.bin.commits @@ -1 +1 @@ -[{"commit_txn":{"version":2,"lock_time":0,"input":[{"previous_output":"0a7f66f7b4befe841ebc51a53738fa35b833f66a3b001a90e37a751bd9b7713e:0","script_sig":"","sequence":4294967295,"witness":["","3045022100b4257b7dacefc591048fc816052c899c710943dd3c4c39bfa818c53035994243022018256e7e1bea6b2dbcfdb62e58b0bc98ef7aa26c678a7298ac0dc4b9552825bc81","3044022068f8468be22db5613d0b3a6fda5fa70110b178b11c2ea5fcdc5714e04557202a022009c2e10755678389deb00eb872114a7529afc2e3e8f4bb211c1984245914e51d81","522102add57ae77706046bc4af1e9533fb2ccaa96316e656756dd0884407ae72501ce421025d415767660a937ee954d08fa09dc055b4a14e5ffc22c38372499dd198cf7aa42102cb5075f2ff841fa49728a8e7d6b22b471f756cf6b3f7c625dcc5e325ebe7e23353ae"]},{"previous_output":"7d0f6eadd008275745a3eb1d57b85f5387aa3b6488106f5bcf4868a5edcbd5f3:0","script_sig":"","sequence":4294967295,"witness":["304402206b5a5c8c0de45e121ea382c09d63b6cf87ed889db2024c2f66504cf3b5b5c49e022077edb94b793e01d78f54d874d640880540ec79e645cbd944d9f4c30568334ebe81","02add57ae77706046bc4af1e9533fb2ccaa96316e656756dd0884407ae72501ce4"]}],"output":[{"value":500,"script_pubkey":"0020e38259e612b85728633fa8b8d00457594ed650fb5c6559b881575f49226d048a"},{"value":0,"script_pubkey":"6a4035e3a5a2736974eac20a6290f79fd153ba4d45df444ec953704f03f8cb3dd5b5070292c12aec12a7b213f65b1deb03c6b59b69620b6a1d9b110bda3a00346878"}]},"genesis_txid":[62,113,183,217,27,117,122,227,144,26,0,59,106,246,51,184,53,250,56,55,165,81,188,30,132,254,190,180,247,102,127,10],"publisher_public_keys":["02add57ae77706046bc4af1e9533fb2ccaa96316e656756dd0884407ae72501ce4","025d415767660a937ee954d08fa09dc055b4a14e5ffc22c38372499dd198cf7aa4","02cb5075f2ff841fa49728a8e7d6b22b471f756cf6b3f7c625dcc5e325ebe7e233"],"threshold":2,"sequencers":[{"address":"9104a28cdf6a00a546a1c365007ebf017b0645af","pub_key":[2,164,213,70,208,195,228,161,14,136,64,141,227,85,111,57,106,134,108,153,204,28,225,73,21,111,180,225,54,254,104,172,110],"power":2000000,"name":null},{"address":"70cce9b7fb446d4ccf793c8cbc12dbef99a10f83","pub_key":[3,196,102,123,104,171,225,100,11,219,187,51,186,113,186,15,45,4,175,100,30,205,166,95,208,95,225,161,219,63,153,87,105],"power":1750000,"name":null},{"address":"fc139929ae753d5580dc6145d9bc8c5c25f73298","pub_key":[3,212,171,157,196,79,116,160,72,222,230,127,158,112,84,118,51,1,46,182,155,255,134,203,202,133,13,89,35,37,29,185,128],"power":1000000,"name":null}],"block_height":119166}] \ No newline at end of file +[{"commit_txn":{"version":2,"lock_time":0,"input":[{"previous_output":"9afa052d65a7f8e6b2616e56719fe8419ba90469021b6b4696d81360fe842026:0","script_sig":"","sequence":4294967295,"witness":["","3044022036aea0879bb34a78225ba291c4b812b0a4b5a699471648a048b3b54b277b600102200a723b69e171740a01d03cb19ab90f3aaa94f3e1267d64bed23df1e60546f33381","3044022044a53670d03d464c710ba0b65547b7ead2a916c0d4821273e6d37de1ee923bd802206d0639be92e8e6d76e870b3fd9086ab7644122b2b47cb7684115a6265a1a801f81","522102add57ae77706046bc4af1e9533fb2ccaa96316e656756dd0884407ae72501ce421025d415767660a937ee954d08fa09dc055b4a14e5ffc22c38372499dd198cf7aa42102cb5075f2ff841fa49728a8e7d6b22b471f756cf6b3f7c625dcc5e325ebe7e23353ae"]},{"previous_output":"f650ed861a45a849004e75c5203d27365ff2fba8954c2af0c1d57612485954dd:0","script_sig":"","sequence":4294967295,"witness":["3045022100f43050df85a8daa024a7f49cde271bca25bef857e00b224700185b756a0095000220771508ae331a3fb17e21ec762b0839f8928c7ae03fa1c61fa96f3b0388772fcb81","02add57ae77706046bc4af1e9533fb2ccaa96316e656756dd0884407ae72501ce4"]}],"output":[{"value":500,"script_pubkey":"0020e38259e612b85728633fa8b8d00457594ed650fb5c6559b881575f49226d048a"},{"value":0,"script_pubkey":"6a402beffe4c53efd70f42c04ac0c83002a2a062bfeabaa5fffc6eb1280d411f0bb22b9791b90336e820684537ded50aeb9c5fdf591d5d1992cd5e04a1d74e07a2f7"}]},"genesis_txid":[38,32,132,254,96,19,216,150,70,107,27,2,105,4,169,155,65,232,159,113,86,110,97,178,230,248,167,101,45,5,250,154],"publisher_public_keys":["02add57ae77706046bc4af1e9533fb2ccaa96316e656756dd0884407ae72501ce4","025d415767660a937ee954d08fa09dc055b4a14e5ffc22c38372499dd198cf7aa4","02cb5075f2ff841fa49728a8e7d6b22b471f756cf6b3f7c625dcc5e325ebe7e233"],"threshold":2,"next_publisher_public_keys":null,"next_threshold":null,"sequencers":[{"address":"70cce9b7fb446d4ccf793c8cbc12dbef99a10f83","pub_key":[3,196,102,123,104,171,225,100,11,219,187,51,186,113,186,15,45,4,175,100,30,205,166,95,208,95,225,161,219,63,153,87,105],"power":1750000,"name":null},{"address":"9104a28cdf6a00a546a1c365007ebf017b0645af","pub_key":[2,164,213,70,208,195,228,161,14,136,64,141,227,85,111,57,106,134,108,153,204,28,225,73,21,111,180,225,54,254,104,172,110],"power":1500000,"name":null},{"address":"fc139929ae753d5580dc6145d9bc8c5c25f73298","pub_key":[3,212,171,157,196,79,116,160,72,222,230,127,158,112,84,118,51,1,46,182,155,255,134,203,202,133,13,89,35,37,29,185,128],"power":1100000,"name":null}],"block_height":121470}] \ No newline at end of file diff --git a/circuits/header-chain-proof/guest/Cargo.toml b/circuits/header-chain-proof/guest/Cargo.toml index 8f6af345..88216bbb 100644 --- a/circuits/header-chain-proof/guest/Cargo.toml +++ b/circuits/header-chain-proof/guest/Cargo.toml @@ -10,7 +10,7 @@ publish = false bincode = "1.3.3" # workspace header-chain = { path = "../../../crates/header-chain" } -borsh = {version = "1.5.3", features = ["derive"] } +borsh = { version = "1.5.3", features = ["derive"] } # Ziren zkm-zkvm = { git = "https://github.com/ProjectZKM/Ziren", package = "zkm-zkvm", features = ["verify"] } @@ -36,9 +36,9 @@ p256 = { git = "https://github.com/ziren-patches/elliptic-curves", branch = "pat alloy-primitives-v1-0-0 = { git = "https://github.com/ziren-patches/core.git", package = "alloy-primitives", branch = "patch-alloy-primitives-1.0.0" } alloy-primitives-v1-1-0 = { git = "https://github.com/ziren-patches/core.git", package = "alloy-primitives", branch = "patch-alloy-primitives-1.1.0" } alloy-primitives-v1-1-2 = { git = "https://github.com/ziren-patches/core.git", package = "alloy-primitives", branch = "patch-alloy-primitives-1.1.2" } -#secp256k1-v0-29-1 = { git = "https://github.com/ziren-patches/rust-secp256k1", package = "secp256k1", branch = "patch-0.29.1" } +secp256k1-v0-29-1 = { git = "https://github.com/ziren-patches/rust-secp256k1", package = "secp256k1", branch = "patch-0.29.1" } #secp256k1-v0-30-0 = { git = "https://github.com/ziren-patches/rust-secp256k1", package = "secp256k1", branch = "patch-0.30.0" } [patch."https://github.com/ProjectZKM/Ziren"] -zkm-zkvm = { git = "https://github.com/blake-pro/Ziren.git", branch = "pre-release-v1.2.5" } -zkm-verifier = { git = "https://github.com/blake-pro/Ziren.git", branch = "pre-release-v1.2.5" } +zkm-zkvm = { git = "https://github.com/blake-pro/Ziren.git", branch = "v1.2.4-imm" } +zkm-verifier = { git = "https://github.com/blake-pro/Ziren.git", branch = "v1.2.4-imm" } diff --git a/circuits/header-chain-proof/guest/src/main.rs b/circuits/header-chain-proof/guest/src/main.rs index a1b3b59f..6d6aa768 100644 --- a/circuits/header-chain-proof/guest/src/main.rs +++ b/circuits/header-chain-proof/guest/src/main.rs @@ -5,7 +5,6 @@ use header_chain::{header_chain_circuit, HeaderChainCircuitInput}; use borsh::{BorshDeserialize, BorshSerialize}; - pub fn main() { let input: HeaderChainCircuitInput = zkm_zkvm::io::read(); let output = header_chain_circuit(input); diff --git a/circuits/header-chain-proof/host/src/lib.rs b/circuits/header-chain-proof/host/src/lib.rs index 4a2e678e..01de2633 100644 --- a/circuits/header-chain-proof/host/src/lib.rs +++ b/circuits/header-chain-proof/host/src/lib.rs @@ -233,7 +233,7 @@ impl ProofBuilder for HeaderChainProofBuilder { Vec::new(), Vec::new(), Vec::new(), - String::new(), + "v1.2.4".into(), ), }; diff --git a/circuits/operator-proof/guest/Cargo.toml b/circuits/operator-proof/guest/Cargo.toml index f3d169a0..27484283 100644 --- a/circuits/operator-proof/guest/Cargo.toml +++ b/circuits/operator-proof/guest/Cargo.toml @@ -44,5 +44,5 @@ secp256k1-v0-29-1 = { git = "https://github.com/ziren-patches/rust-secp256k1", p #bitcoin = { git = "https://github.com/ProjectZKM/rust-bitcoin", branch = "patch-0.32.7" } [patch."https://github.com/ProjectZKM/Ziren"] -zkm-zkvm = { git = "https://github.com/blake-pro/Ziren.git", branch = "pre-release-v1.2.5" } -zkm-verifier = { git = "https://github.com/blake-pro/Ziren.git", branch = "pre-release-v1.2.5" } +zkm-zkvm = { git = "https://github.com/blake-pro/Ziren.git", branch = "v1.2.4-imm" } +zkm-verifier = { git = "https://github.com/blake-pro/Ziren.git", branch = "v1.2.4-imm" } diff --git a/circuits/state-chain-proof/guest/Cargo.toml b/circuits/state-chain-proof/guest/Cargo.toml index 44a817a9..95d9433f 100644 --- a/circuits/state-chain-proof/guest/Cargo.toml +++ b/circuits/state-chain-proof/guest/Cargo.toml @@ -37,5 +37,5 @@ secp256k1-v0-29-1 = { git = "https://github.com/ziren-patches/rust-secp256k1", p #secp256k1-v0-30-0 = { git = "https://github.com/ziren-patches/rust-secp256k1", package = "secp256k1", branch = "patch-0.30.0" } [patch."https://github.com/ProjectZKM/Ziren"] -zkm-zkvm = { git = "https://github.com/blake-pro/Ziren.git", branch = "pre-release-v1.2.5" } -zkm-verifier = { git = "https://github.com/blake-pro/Ziren.git", branch = "pre-release-v1.2.5" } +zkm-zkvm = { git = "https://github.com/blake-pro/Ziren.git", branch = "v1.2.4-imm" } +zkm-verifier = { git = "https://github.com/blake-pro/Ziren.git", branch = "v1.2.4-imm" } diff --git a/circuits/state-chain-proof/host/src/lib.rs b/circuits/state-chain-proof/host/src/lib.rs index e302f8ab..f51d5194 100644 --- a/circuits/state-chain-proof/host/src/lib.rs +++ b/circuits/state-chain-proof/host/src/lib.rs @@ -350,7 +350,7 @@ impl ProofBuilder for StateChainProofBuilder { Vec::new(), Vec::new(), Vec::new(), - String::new(), + "v1.2.4".into(), ), }; diff --git a/circuits/watchtower-proof/guest/Cargo.toml b/circuits/watchtower-proof/guest/Cargo.toml index 5018b950..453203b6 100644 --- a/circuits/watchtower-proof/guest/Cargo.toml +++ b/circuits/watchtower-proof/guest/Cargo.toml @@ -44,5 +44,5 @@ secp256k1-v0-29-1 = { git = "https://github.com/ziren-patches/rust-secp256k1", p #bitcoin = { git = "https://github.com/ProjectZKM/rust-bitcoin", branch = "patch-0.32.7" } [patch."https://github.com/ProjectZKM/Ziren"] -zkm-zkvm = { git = "https://github.com/blake-pro/Ziren.git", branch = "pre-release-v1.2.5" } -zkm-verifier = { git = "https://github.com/blake-pro/Ziren.git", branch = "pre-release-v1.2.5" } +zkm-zkvm = { git = "https://github.com/blake-pro/Ziren.git", branch = "v1.2.4-imm" } +zkm-verifier = { git = "https://github.com/blake-pro/Ziren.git", branch = "v1.2.4-imm" } diff --git a/circuits/watchtower-proof/host/src/lib.rs b/circuits/watchtower-proof/host/src/lib.rs index 4d3ec74a..d01589a9 100644 --- a/circuits/watchtower-proof/host/src/lib.rs +++ b/circuits/watchtower-proof/host/src/lib.rs @@ -380,10 +380,7 @@ mod tests { } fn sample_header_output(part_stark_vk: Vec) -> BlockHeaderCircuitOutput { - BlockHeaderCircuitOutput { - chain_state: header_chain::ChainState::new(), - part_stark_vk, - } + BlockHeaderCircuitOutput { chain_state: header_chain::ChainState::new(), part_stark_vk } } fn sample_state_output(part_stark_vk: Vec) -> StateChainCircuitOutput { diff --git a/crates/bitcoin-light-client-circuit/src/attestation.rs b/crates/bitcoin-light-client-circuit/src/attestation.rs index 42fe8ab7..3b3c6c97 100644 --- a/crates/bitcoin-light-client-circuit/src/attestation.rs +++ b/crates/bitcoin-light-client-circuit/src/attestation.rs @@ -1,6 +1,6 @@ -use bitcoin::hashes::{Hash, sha256}; use bitcoin::secp256k1::{Message, PublicKey, Secp256k1, SecretKey, ecdsa::Signature}; use serde::{Deserialize, Serialize}; +use sha2::{Digest, Sha256}; use std::collections::{BTreeMap, BTreeSet}; use std::path::{Path, PathBuf}; @@ -9,7 +9,7 @@ pub const PART_STARK_VK_TREE_LEAFS: usize = 1 << PART_STARK_VK_TREE_HEIGHT; pub const PART_STARK_VK_ROOT_SIGNATURE_DOMAIN: &[u8] = b"bitvm2:part_stark_vk_root:v2"; pub const PART_STARK_VK_PUBLISHER_SET_DOMAIN: &[u8] = b"bitvm2:publisher_set:v1"; pub const PART_STARK_VK_ATTESTATION_DIR_ENV: &str = "PART_STARK_VK_ATTESTATION_DIR"; -pub const DEFAULT_PART_STARK_VK_ATTESTATION_DIR: &str = "./part-stark-vk-attestations"; +pub const DEFAULT_PART_STARK_VK_ATTESTATION_DIR: &str = "data/psv-attestations"; #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] pub struct PartStarkVkRootSignature { @@ -46,6 +46,26 @@ pub struct PartStarkVkTreeState { pub leaves: Vec>, } +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] +pub struct LatestPartStarkVkAttestationManifest { + pub tree_height: usize, + pub ordered_versions: Vec, + pub root: [u8; 32], + pub threshold: Option, + pub publisher_set_id: Option<[u8; 32]>, + pub publisher_public_keys: Option>, + pub signatures: Vec, + pub part_stark_vk_leaf_hashes: BTreeMap, +} + +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] +pub struct VersionedPartStarkVkMerkleProof { + pub version: String, + pub part_stark_vk: Vec, + pub leaf_index: usize, + pub merkle_path: Vec<[u8; 32]>, +} + pub fn part_stark_vk_attestation_dir() -> PathBuf { std::env::var(PART_STARK_VK_ATTESTATION_DIR_ENV) .map(PathBuf::from) @@ -64,7 +84,8 @@ pub fn compute_publisher_set_id(publisher_public_keys: &[PublicKey], threshold: for pubkey in publisher_public_keys { bytes.extend_from_slice(&pubkey.serialize()); } - sha256::Hash::hash(&bytes).to_byte_array() + + Sha256::digest(bytes).into() } pub fn part_stark_vk_leaf_hash(part_stark_vk: &[u8]) -> [u8; 32] { @@ -72,7 +93,8 @@ pub fn part_stark_vk_leaf_hash(part_stark_vk: &[u8]) -> [u8; 32] { bytes.push(0x00); bytes.extend_from_slice(&(part_stark_vk.len() as u32).to_le_bytes()); bytes.extend_from_slice(part_stark_vk); - sha256::Hash::hash(&bytes).to_byte_array() + + Sha256::digest(bytes).into() } pub fn part_stark_vk_internal_hash(left: [u8; 32], right: [u8; 32]) -> [u8; 32] { @@ -80,7 +102,8 @@ pub fn part_stark_vk_internal_hash(left: [u8; 32], right: [u8; 32]) -> [u8; 32] bytes.push(0x01); bytes.extend_from_slice(&left); bytes.extend_from_slice(&right); - sha256::Hash::hash(&bytes).to_byte_array() + + Sha256::digest(bytes).into() } pub fn empty_part_stark_vk_leaf_hash() -> [u8; 32] { @@ -99,6 +122,18 @@ pub fn part_stark_vk_bundle_path(dir: &Path, part_stark_vk: &[u8]) -> PathBuf { dir.join("bundles").join(format!("{}.json", part_stark_vk_bundle_id(part_stark_vk))) } +pub fn latest_part_stark_vk_attestation_manifest_path(dir: &Path) -> PathBuf { + dir.join("manifest.json") +} + +pub fn latest_part_stark_vk_attestation_proofs_dir(dir: &Path) -> PathBuf { + dir.join("proofs") +} + +pub fn latest_part_stark_vk_attestation_proof_path(dir: &Path, version: &str) -> PathBuf { + latest_part_stark_vk_attestation_proofs_dir(dir).join(format!("{version}.json")) +} + fn build_part_stark_vk_leaf_layer( part_stark_vks: &[Vec], tree_height: usize, @@ -210,7 +245,8 @@ pub fn build_attestation_message_digest( bytes.extend_from_slice(&threshold.to_le_bytes()); bytes.extend_from_slice(&publisher_set_id); bytes.extend_from_slice(&root); - sha256::Hash::hash(&bytes).to_byte_array() + + Sha256::digest(bytes).into() } fn verify_part_stark_vk_root_signatures( @@ -352,6 +388,254 @@ pub fn load_part_stark_vk_tree_state(dir: &Path) -> Result Result<(), String> { + if !path.exists() { + return Ok(()); + } + if path.is_dir() { + std::fs::remove_dir_all(path) + .map_err(|err| format!("failed to remove dir '{}': {err}", path.display()))?; + } else { + std::fs::remove_file(path) + .map_err(|err| format!("failed to remove file '{}': {err}", path.display()))?; + } + Ok(()) +} + +/// Build the latest snapshot manifest and per-version merkle proofs from ordered versions. +fn build_latest_part_stark_vk_attestation_snapshot( + ordered_versions: &[String], + part_stark_vks: &[Vec], + threshold: Option, + publisher_set_id: Option<[u8; 32]>, + publisher_public_keys: Option>, + signatures: Vec, +) -> Result<(LatestPartStarkVkAttestationManifest, Vec), String> { + if ordered_versions.is_empty() { + return Err("ordered_versions is empty".to_string()); + } + if ordered_versions.len() != part_stark_vks.len() { + return Err(format!( + "ordered_versions length {} does not match part_stark_vks length {}", + ordered_versions.len(), + part_stark_vks.len() + )); + } + + let root = build_part_stark_vk_merkle_root(part_stark_vks, PART_STARK_VK_TREE_HEIGHT)?; + let mut part_stark_vk_leaf_hashes = BTreeMap::new(); + let mut proofs = Vec::with_capacity(ordered_versions.len()); + for (leaf_index, (version, part_stark_vk)) in + ordered_versions.iter().zip(part_stark_vks).enumerate() + { + let leaf_hash = part_stark_vk_bundle_id(part_stark_vk); + if part_stark_vk_leaf_hashes.insert(version.clone(), leaf_hash).is_some() { + return Err(format!("duplicate ordered version '{version}'")); + } + proofs.push(VersionedPartStarkVkMerkleProof { + version: version.clone(), + part_stark_vk: part_stark_vk.clone(), + leaf_index, + merkle_path: build_part_stark_vk_merkle_path( + part_stark_vks, + PART_STARK_VK_TREE_HEIGHT, + leaf_index, + )?, + }); + } + + Ok(( + LatestPartStarkVkAttestationManifest { + tree_height: PART_STARK_VK_TREE_HEIGHT, + ordered_versions: ordered_versions.to_vec(), + root, + threshold, + publisher_set_id, + publisher_public_keys, + signatures, + part_stark_vk_leaf_hashes, + }, + proofs, + )) +} + +/// Rewrite the attestation directory so it only contains the current snapshot files. +fn write_latest_part_stark_vk_attestation_snapshot( + dir: &Path, + manifest: &LatestPartStarkVkAttestationManifest, + proofs: &[VersionedPartStarkVkMerkleProof], +) -> Result<(), String> { + std::fs::create_dir_all(dir) + .map_err(|err| format!("failed to create attestation dir '{}': {err}", dir.display()))?; + remove_path_if_exists(&latest_part_stark_vk_attestation_proofs_dir(dir))?; + remove_path_if_exists(&dir.join("bundles"))?; + remove_path_if_exists(&part_stark_vk_tree_state_path(dir))?; + remove_path_if_exists(&latest_part_stark_vk_attestation_manifest_path(dir))?; + + let proofs_dir = latest_part_stark_vk_attestation_proofs_dir(dir); + std::fs::create_dir_all(&proofs_dir).map_err(|err| { + format!("failed to create attestation proofs dir '{}': {err}", proofs_dir.display()) + })?; + + for proof in proofs { + let path = latest_part_stark_vk_attestation_proof_path(dir, &proof.version); + let bytes = serde_json::to_vec_pretty(proof) + .map_err(|err| format!("failed to encode proof '{}': {err}", path.display()))?; + std::fs::write(&path, bytes) + .map_err(|err| format!("failed to write proof '{}': {err}", path.display()))?; + } + + let manifest_path = latest_part_stark_vk_attestation_manifest_path(dir); + let manifest_bytes = serde_json::to_vec_pretty(manifest).map_err(|err| { + format!("failed to encode latest attestation manifest '{}': {err}", manifest_path.display()) + })?; + std::fs::write(&manifest_path, manifest_bytes).map_err(|err| { + format!("failed to write latest attestation manifest '{}': {err}", manifest_path.display()) + })?; + Ok(()) +} + +/// Persist a full latest snapshot, optionally including publisher metadata and signatures. +pub fn save_latest_part_stark_vk_attestation_snapshot( + dir: &Path, + ordered_versions: &[String], + part_stark_vks: &[Vec], + threshold: Option, + publisher_set_id: Option<[u8; 32]>, + publisher_public_keys: Option>, + signatures: Vec, +) -> Result<(), String> { + let publisher_public_keys = + publisher_public_keys.map(|keys| keys.into_iter().map(|key| key.to_string()).collect()); + let (manifest, proofs) = build_latest_part_stark_vk_attestation_snapshot( + ordered_versions, + part_stark_vks, + threshold, + publisher_set_id, + publisher_public_keys, + signatures, + )?; + write_latest_part_stark_vk_attestation_snapshot(dir, &manifest, &proofs) +} + +/// Load the latest manifest that describes the current attestation snapshot. +pub fn load_latest_part_stark_vk_attestation_manifest( + dir: &Path, +) -> Result { + let path = latest_part_stark_vk_attestation_manifest_path(dir); + let bytes = std::fs::read(&path).map_err(|err| { + format!("failed to read latest attestation manifest '{}': {err}", path.display()) + })?; + serde_json::from_slice(&bytes).map_err(|err| { + format!("failed to decode latest attestation manifest '{}': {err}", path.display()) + }) +} + +/// Load every version proof referenced by the latest manifest in manifest order. +pub fn load_latest_part_stark_vk_attestation_proofs( + dir: &Path, + ordered_versions: &[String], +) -> Result, String> { + let mut proofs = Vec::with_capacity(ordered_versions.len()); + for version in ordered_versions { + let path = latest_part_stark_vk_attestation_proof_path(dir, version); + let bytes = std::fs::read(&path).map_err(|err| { + format!("failed to read attestation proof '{}': {err}", path.display()) + })?; + let proof: VersionedPartStarkVkMerkleProof = + serde_json::from_slice(&bytes).map_err(|err| { + format!("failed to decode attestation proof '{}': {err}", path.display()) + })?; + proofs.push(proof); + } + Ok(proofs) +} + +/// Merge one signer into the latest snapshot, resetting signatures when the signing context changes. +pub fn sign_latest_part_stark_vk_snapshot( + dir: &Path, + ordered_versions: &[String], + part_stark_vks: &[Vec], + publisher_public_keys: &[PublicKey], + threshold: u16, + signer_pubkey_index: usize, + secret_key: &SecretKey, +) -> Result { + if publisher_public_keys.is_empty() { + return Err("publisher_public_keys is empty".to_string()); + } + let required = usize::from(threshold); + if required == 0 { + return Err("threshold must be greater than 0".to_string()); + } + if required > publisher_public_keys.len() { + return Err(format!( + "threshold {} exceeds publisher_public_keys length {}", + required, + publisher_public_keys.len() + )); + } + if signer_pubkey_index >= publisher_public_keys.len() { + return Err(format!( + "signer_pubkey_index {} out of range {}", + signer_pubkey_index, + publisher_public_keys.len() + )); + } + + let signer_public_key = PublicKey::from_secret_key(&Secp256k1::new(), secret_key); + if publisher_public_keys[signer_pubkey_index] != signer_public_key { + return Err(format!( + "publisher_secret_key does not match publisher public key at index {}", + signer_pubkey_index + )); + } + + let root = build_part_stark_vk_merkle_root(part_stark_vks, PART_STARK_VK_TREE_HEIGHT)?; + let publisher_set_id = compute_publisher_set_id(publisher_public_keys, threshold); + let mut signatures = match load_latest_part_stark_vk_attestation_manifest(dir) { + Ok(existing) + if existing.ordered_versions == ordered_versions + && existing.root == root + && existing.publisher_set_id == Some(publisher_set_id) => + { + existing.signatures + } + _ => Vec::new(), + }; + + let signature = PartStarkVkRootSignature { + signer_pubkey_index, + signature: sign_part_stark_vk_root( + secret_key, + PART_STARK_VK_TREE_HEIGHT, + root, + threshold, + publisher_set_id, + ), + }; + + if let Some(existing_signature) = + signatures.iter_mut().find(|existing| existing.signer_pubkey_index == signer_pubkey_index) + { + *existing_signature = signature; + } else { + signatures.push(signature); + } + signatures.sort_by_key(|existing| existing.signer_pubkey_index); + + save_latest_part_stark_vk_attestation_snapshot( + dir, + ordered_versions, + part_stark_vks, + Some(threshold), + Some(publisher_set_id), + Some(publisher_public_keys.to_vec()), + signatures, + )?; + load_latest_part_stark_vk_attestation_manifest(dir) +} + pub fn save_part_stark_vk_tree_state( dir: &Path, state: &PartStarkVkTreeState, @@ -595,6 +879,63 @@ pub fn load_unique_part_stark_vk_witnesses( dir: &Path, part_stark_vks: &[Vec], ) -> Result<(Vec, Vec), String> { + if !latest_part_stark_vk_attestation_manifest_path(dir).exists() { + return Err(format!( + "missing latest attestation manifest '{}'", + latest_part_stark_vk_attestation_manifest_path(dir).display() + )); + } + + load_unique_part_stark_vk_witnesses_from_latest_snapshot(dir, part_stark_vks) +} + +fn load_unique_part_stark_vk_witnesses_from_latest_snapshot( + dir: &Path, + part_stark_vks: &[Vec], +) -> Result<(Vec, Vec), String> { + let manifest = load_latest_part_stark_vk_attestation_manifest(dir)?; + let threshold = manifest + .threshold + .ok_or_else(|| "latest attestation manifest is missing threshold".to_string())?; + let publisher_set_id = manifest + .publisher_set_id + .ok_or_else(|| "latest attestation manifest is missing publisher_set_id".to_string())?; + let proofs = load_latest_part_stark_vk_attestation_proofs(dir, &manifest.ordered_versions)?; + let mut available_witnesses = BTreeMap::, UniquePartStarkVkWitness>::new(); + + for proof in proofs { + let expected_leaf_hash = + manifest.part_stark_vk_leaf_hashes.get(&proof.version).ok_or_else(|| { + format!("missing part_stark_vk leaf hash for version '{}'", proof.version) + })?; + let actual_leaf_hash = part_stark_vk_bundle_id(&proof.part_stark_vk); + if *expected_leaf_hash != actual_leaf_hash { + return Err(format!( + "part_stark_vk leaf hash mismatch for version '{}': expected {}, got {}", + proof.version, expected_leaf_hash, actual_leaf_hash + )); + } + + verify_part_stark_vk_merkle_path( + &proof.part_stark_vk, + proof.leaf_index, + &proof.merkle_path, + manifest.root, + manifest.tree_height, + )?; + available_witnesses.entry(proof.part_stark_vk.clone()).or_insert_with(|| { + PartStarkVkAttestationBundle { + part_stark_vk: proof.part_stark_vk, + leaf_index: proof.leaf_index, + merkle_path: proof.merkle_path, + root: manifest.root, + threshold, + publisher_set_id, + signatures: manifest.signatures.clone(), + } + }); + } + let mut unique_witnesses = Vec::new(); let mut witness_indexes = Vec::with_capacity(part_stark_vks.len()); let mut seen = BTreeMap::, usize>::new(); @@ -604,7 +945,10 @@ pub fn load_unique_part_stark_vk_witnesses( witness_indexes.push(*index); continue; } - let bundle = load_part_stark_vk_attestation_bundle(dir, part_stark_vk)?; + let bundle = available_witnesses + .get(part_stark_vk) + .cloned() + .ok_or_else(|| "part_stark_vk not found in latest snapshot".to_string())?; let index = unique_witnesses.len(); unique_witnesses.push(bundle); seen.insert(part_stark_vk.clone(), index); @@ -616,18 +960,19 @@ pub fn load_unique_part_stark_vk_witnesses( #[cfg(test)] mod tests { - use std::time::{SystemTime, UNIX_EPOCH}; - use bitcoin::secp256k1::{Message, Secp256k1, SecretKey, ecdsa::Signature}; + use sha2::{Digest, Sha256}; + use std::time::{SystemTime, UNIX_EPOCH}; use super::{ - PartStarkVkAttestationBundle, PartStarkVkRootSignature, + PART_STARK_VK_TREE_HEIGHT, PartStarkVkAttestationBundle, PartStarkVkRootSignature, assert_part_stark_vk_in_verified_witnesses, build_attestation_message_digest, build_part_stark_vk_merkle_path, build_part_stark_vk_merkle_root, build_part_stark_vk_root_signatures, compute_publisher_set_id, - load_unique_part_stark_vk_witnesses, part_stark_vk_leaf_hash, - save_part_stark_vk_attestation_bundle, verify_part_stark_vk_attestation, - verify_unique_part_stark_vk_witnesses, + load_latest_part_stark_vk_attestation_manifest, load_unique_part_stark_vk_witnesses, + part_stark_vk_leaf_hash, save_latest_part_stark_vk_attestation_snapshot, + save_part_stark_vk_attestation_bundle, sign_latest_part_stark_vk_snapshot, + verify_part_stark_vk_attestation, verify_unique_part_stark_vk_witnesses, }; fn sample_part_stark_vk() -> Vec { @@ -966,18 +1311,87 @@ mod tests { } #[test] - fn test_load_unique_part_stark_vk_witnesses_reuses_duplicate_indexes() { + fn test_load_unique_part_stark_vk_witnesses_reuses_duplicate_indexes_from_latest_snapshot() { let (secret_keys, publisher_public_keys) = sample_publishers(); let leaves = vec![sample_part_stark_vk(), sample_part_stark_vk_alt()]; let dir = unique_test_dir("attestation-duplicate-indexes"); + let ordered_versions = vec!["v1.2.4".to_string(), "v1.2.5".to_string()]; + let threshold = 3; + let publisher_set_id = compute_publisher_set_id(&publisher_public_keys, threshold); + let signatures = build_part_stark_vk_root_signatures( + &[(0, &secret_keys[0]), (1, &secret_keys[1]), (2, &secret_keys[2])], + PART_STARK_VK_TREE_HEIGHT, + build_part_stark_vk_merkle_root(&leaves, PART_STARK_VK_TREE_HEIGHT).unwrap(), + threshold, + publisher_set_id, + ) + .unwrap(); + + save_latest_part_stark_vk_attestation_snapshot( + &dir, + &ordered_versions, + &leaves, + Some(threshold), + Some(publisher_set_id), + Some(publisher_public_keys.clone()), + signatures, + ) + .unwrap(); + + let requested = vec![leaves[0].clone(), leaves[1].clone(), leaves[0].clone()]; + let (unique_witnesses, witness_indexes) = + load_unique_part_stark_vk_witnesses(&dir, &requested).unwrap(); + + assert_eq!(unique_witnesses.len(), 2); + assert_eq!(witness_indexes, vec![0, 1, 0]); + + std::fs::remove_dir_all(dir).unwrap(); + } + + #[test] + fn test_load_unique_part_stark_vk_witnesses_requires_latest_manifest() { + let (secret_keys, publisher_public_keys) = sample_publishers(); + let leaves = vec![sample_part_stark_vk(), sample_part_stark_vk_alt()]; + let dir = unique_test_dir("attestation-requires-latest-manifest"); std::fs::create_dir_all(dir.join("bundles")).unwrap(); let first_bundle = sample_attestation_bundle(&leaves, 0, 3, &publisher_public_keys, &secret_keys); - let second_bundle = - sample_attestation_bundle(&leaves, 1, 3, &publisher_public_keys, &secret_keys); save_part_stark_vk_attestation_bundle(&dir, &first_bundle).unwrap(); - save_part_stark_vk_attestation_bundle(&dir, &second_bundle).unwrap(); + + let err = load_unique_part_stark_vk_witnesses(&dir, &[leaves[0].clone()]).unwrap_err(); + assert!(err.contains("missing latest attestation manifest")); + + std::fs::remove_dir_all(dir).unwrap(); + } + + #[test] + fn test_save_and_load_latest_snapshot_reuses_duplicate_indexes() { + let (secret_keys, publisher_public_keys) = sample_publishers(); + let leaves = vec![sample_part_stark_vk(), sample_part_stark_vk_alt()]; + let ordered_versions = vec!["v1.2.4".to_string(), "v1.2.5".to_string()]; + let dir = unique_test_dir("latest-attestation-snapshot"); + let threshold = 3; + let publisher_set_id = compute_publisher_set_id(&publisher_public_keys, threshold); + let signatures = build_part_stark_vk_root_signatures( + &[(0, &secret_keys[0]), (1, &secret_keys[1]), (2, &secret_keys[2])], + PART_STARK_VK_TREE_HEIGHT, + build_part_stark_vk_merkle_root(&leaves, PART_STARK_VK_TREE_HEIGHT).unwrap(), + threshold, + publisher_set_id, + ) + .unwrap(); + + save_latest_part_stark_vk_attestation_snapshot( + &dir, + &ordered_versions, + &leaves, + Some(threshold), + Some(publisher_set_id), + Some(publisher_public_keys.clone()), + signatures, + ) + .unwrap(); let requested = vec![leaves[0].clone(), leaves[1].clone(), leaves[0].clone()]; let (unique_witnesses, witness_indexes) = @@ -985,6 +1399,96 @@ mod tests { assert_eq!(unique_witnesses.len(), 2); assert_eq!(witness_indexes, vec![0, 1, 0]); + assert_eq!(unique_witnesses[0].part_stark_vk, leaves[0]); + assert_eq!(unique_witnesses[1].part_stark_vk, leaves[1]); + + std::fs::remove_dir_all(dir).unwrap(); + } + + #[test] + fn test_sign_latest_snapshot_preserves_existing_signatures_for_same_identity() { + let (secret_keys, publisher_public_keys) = sample_publishers(); + let leaves = vec![sample_part_stark_vk(), sample_part_stark_vk_alt()]; + let ordered_versions = vec!["v1.2.4".to_string(), "v1.2.5".to_string()]; + let dir = unique_test_dir("latest-attestation-signatures"); + + sign_latest_part_stark_vk_snapshot( + &dir, + &ordered_versions, + &leaves, + &publisher_public_keys, + 3, + 0, + &secret_keys[0], + ) + .unwrap(); + let first_manifest = load_latest_part_stark_vk_attestation_manifest(&dir).unwrap(); + assert_eq!(first_manifest.signatures.len(), 1); + + sign_latest_part_stark_vk_snapshot( + &dir, + &ordered_versions, + &leaves, + &publisher_public_keys, + 3, + 2, + &secret_keys[2], + ) + .unwrap(); + let second_manifest = load_latest_part_stark_vk_attestation_manifest(&dir).unwrap(); + assert_eq!(second_manifest.signatures.len(), 2); + + std::fs::remove_dir_all(dir).unwrap(); + } + + #[test] + fn test_sign_latest_snapshot_clears_stale_signatures_when_publisher_set_changes() { + let (secret_keys, publisher_public_keys) = sample_publishers(); + let leaves = vec![sample_part_stark_vk(), sample_part_stark_vk_alt()]; + let ordered_versions = vec!["v1.2.4".to_string(), "v1.2.5".to_string()]; + let dir = unique_test_dir("latest-attestation-publisher-reset"); + + sign_latest_part_stark_vk_snapshot( + &dir, + &ordered_versions, + &leaves, + &publisher_public_keys, + 3, + 0, + &secret_keys[0], + ) + .unwrap(); + sign_latest_part_stark_vk_snapshot( + &dir, + &ordered_versions, + &leaves, + &publisher_public_keys, + 3, + 1, + &secret_keys[1], + ) + .unwrap(); + + let reordered_publisher_public_keys = vec![ + publisher_public_keys[1], + publisher_public_keys[0], + publisher_public_keys[2], + publisher_public_keys[3], + ]; + sign_latest_part_stark_vk_snapshot( + &dir, + &ordered_versions, + &leaves, + &reordered_publisher_public_keys, + 3, + 0, + &secret_keys[1], + ) + .unwrap(); + + let manifest = load_latest_part_stark_vk_attestation_manifest(&dir).unwrap(); + assert_eq!(manifest.signatures.len(), 1); + assert_eq!(manifest.signatures[0].signer_pubkey_index, 0); std::fs::remove_dir_all(dir).unwrap(); } diff --git a/crates/bitcoin-light-client-circuit/src/lib.rs b/crates/bitcoin-light-client-circuit/src/lib.rs index 96b055f3..4c397469 100644 --- a/crates/bitcoin-light-client-circuit/src/lib.rs +++ b/crates/bitcoin-light-client-circuit/src/lib.rs @@ -13,8 +13,7 @@ use bitcoin::Transaction; use bitcoin::hashes::{Hash, HashEngine, sha256}; use commit_chain::sequencer_hash; use commit_chain::{ - CommitChainCircuitInput, CommitChainCircuitOutput, CommitChainPrevProofType, - extract_data_from_commitment_outputs, + CommitChainCircuitInput, CommitChainCircuitOutput, extract_data_from_commitment_outputs, }; use header_chain::{ BitcoinMerkleTree, CircuitBlockHeader, CircuitTransaction, HeaderChainCircuitInput, @@ -662,17 +661,8 @@ fn verify_commit_chain_output( &commit_chain.zkm_vk_hash, &trusted_part_stark_vk, )?; - - let output = match &commit_chain.prev_proof { - CommitChainPrevProofType::PrevProof(_) => { - ZKMPublicValues::from(&commit_chain.zkm_public_values).read() - } - CommitChainPrevProofType::GenesisBlock => { - return Err( - "Only PrevProof is supported when verifying commit-chain output".to_string() - ); - } - }; + let output: CommitChainCircuitOutput = + ZKMPublicValues::from(&commit_chain.zkm_public_values).read(); Ok(output) } diff --git a/crates/commit-chain/src/lib.rs b/crates/commit-chain/src/lib.rs index bc9d5d37..cde097d0 100644 --- a/crates/commit-chain/src/lib.rs +++ b/crates/commit-chain/src/lib.rs @@ -4,7 +4,7 @@ mod commit_chain; pub use commit_chain::*; use zkm_verifier::{Groth16Verifier, IMM_GROTH16_VK_BYTES}; -pub const TRUSTED_COMMIT_CHAIN_ZKM_VERSION: &str = "v1.2.5"; +pub const TRUSTED_COMMIT_CHAIN_ZKM_VERSION: &str = "v1.2.4"; /// Return the fixed `part_stark_vk` used by commit-chain's internal recursive verifier. pub fn trusted_commit_chain_part_stark_vk() -> Vec { diff --git a/crates/header-chain/Cargo.toml b/crates/header-chain/Cargo.toml index 9c65f27a..cf16b1bc 100644 --- a/crates/header-chain/Cargo.toml +++ b/crates/header-chain/Cargo.toml @@ -7,7 +7,7 @@ edition.workspace = true [dependencies] borsh = {version = "1.5.3", features = ["derive"] } sha2 = { version = "0.10.9", default-features = false } -bitcoin = { workspace = true, features = ["serde", "rand", "secp-recovery"] } +bitcoin = { version = "0.32.6", default-features = false, features = ["serde"] } serde = { workspace = true, default-features = false } crypto-bigint = { version = "0.5.5", default-features = false } zkm-zkvm = { workspace = true } diff --git a/node/Cargo.toml b/node/Cargo.toml index 89be098a..9395478f 100644 --- a/node/Cargo.toml +++ b/node/Cargo.toml @@ -112,6 +112,7 @@ dirs = "5.0.1" zkm-sdk = { workspace = true } zkm-verifier = { workspace = true, features = ["ark"] } borsh = {version = "1.5.3", features = ["derive"] } +semver = "1.0" proof-builder = { workspace = true } util = { workspace = true } diff --git a/node/src/bin/part_stark_vk_attest.rs b/node/src/bin/part_stark_vk_attest.rs index 3b939c17..46d83df1 100644 --- a/node/src/bin/part_stark_vk_attest.rs +++ b/node/src/bin/part_stark_vk_attest.rs @@ -1,37 +1,17 @@ -use anyhow::{Context, Result, anyhow, bail}; -use bitcoin::secp256k1::{PublicKey, SecretKey}; +use anyhow::{Context, Result, bail}; +use bitcoin::PrivateKey; +use bitcoin::secp256k1::{PublicKey, Secp256k1, SecretKey}; use bitcoin_light_client_circuit::{ - append_part_stark_vk_and_sign_with_signers, part_stark_vk_attestation_dir, - resign_current_part_stark_vk_root_with_signers, + part_stark_vk_attestation_dir, save_latest_part_stark_vk_attestation_snapshot, + sign_latest_part_stark_vk_snapshot, }; use clap::{Parser, Subcommand}; use commit_chain::CommitInfo; +use semver::Version; use std::path::PathBuf; use std::str::FromStr; use zkm_verifier::Groth16Verifier; -#[derive(Debug, Clone)] -struct PublisherSignerArg { - signer_pubkey_index: usize, - secret_key: SecretKey, -} - -impl FromStr for PublisherSignerArg { - type Err = anyhow::Error; - - fn from_str(value: &str) -> Result { - let (signer_pubkey_index, secret_key) = value - .split_once(':') - .ok_or_else(|| anyhow!("invalid signer format, expected :"))?; - Ok(Self { - signer_pubkey_index: signer_pubkey_index - .parse() - .context("invalid signer_pubkey_index")?, - secret_key: SecretKey::from_str(secret_key).context("invalid secret_key hex")?, - }) - } -} - #[derive(Debug, Parser)] struct Cli { #[command(subcommand)] @@ -40,23 +20,19 @@ struct Cli { #[derive(Debug, Subcommand)] enum Command { - Append { - #[arg(long)] - part_stark_vk_file: Option, - #[arg(long)] - zkm_version: Option, - #[arg(long)] - commit_info_file: PathBuf, + BuildTree { #[arg(long, value_delimiter = ',')] - publisher_signers: Vec, + versions: Vec, #[arg(long)] attestation_dir: Option, }, - ResignCurrentRoot { + SignRoot { + #[arg(long, value_delimiter = ',')] + versions: Vec, #[arg(long)] commit_info_file: PathBuf, - #[arg(long, value_delimiter = ',')] - publisher_signers: Vec, + #[arg(long, value_parser = decode_publisher_secret_key_wif)] + publisher_secret_key_wif: SecretKey, #[arg(long)] attestation_dir: Option, }, @@ -66,14 +42,40 @@ fn resolve_attestation_dir(attestation_dir: Option) -> PathBuf { attestation_dir.unwrap_or_else(part_stark_vk_attestation_dir) } -fn resolve_signers(publisher_signers: &[PublisherSignerArg]) -> Result> { - if publisher_signers.is_empty() { - bail!("publisher_signers is empty"); +fn normalize_version(version: &str) -> Result { + let raw_version = version.trim(); + if raw_version.is_empty() { + bail!("version cannot be empty"); } - Ok(publisher_signers + let normalized = raw_version + .strip_prefix('v') + .or_else(|| raw_version.strip_prefix('V')) + .unwrap_or(raw_version); + Version::parse(normalized).with_context(|| format!("invalid semver version '{version}'")) +} + +/// Sort versions by semantic version while rejecting duplicate normalized versions. +fn order_versions(versions: &[String]) -> Result> { + if versions.is_empty() { + bail!("versions is empty"); + } + + let mut keyed_versions = versions .iter() - .map(|signer| (signer.signer_pubkey_index, &signer.secret_key)) - .collect()) + .map(|version| Ok((normalize_version(version)?, version.clone()))) + .collect::>>()?; + keyed_versions.sort_by(|left, right| left.0.cmp(&right.0).then(left.1.cmp(&right.1))); + + let mut ordered_versions = Vec::with_capacity(keyed_versions.len()); + let mut previous: Option = None; + for (normalized, original) in keyed_versions { + if previous.as_ref() == Some(&normalized) { + bail!("duplicate version '{original}'"); + } + previous = Some(normalized); + ordered_versions.push(original); + } + Ok(ordered_versions) } fn load_publisher_set(commit_info_file: &PathBuf) -> Result<(Vec, u16)> { @@ -107,17 +109,30 @@ fn load_publisher_set(commit_info_file: &PathBuf) -> Result<(Vec, u16 Ok((publisher_public_keys, threshold)) } -fn load_part_stark_vk( - part_stark_vk_file: Option, - zkm_version: Option, -) -> Result> { - match (part_stark_vk_file, zkm_version) { - (Some(_), Some(_)) => bail!("part_stark_vk_file and zkm_version are mutually exclusive"), - (None, None) => bail!("either part_stark_vk_file or zkm_version must be provided"), - (Some(path), None) => std::fs::read(&path) - .with_context(|| format!("failed to read part_stark_vk file '{}'", path.display())), - (None, Some(zkm_version)) => Ok(Groth16Verifier::get_part_stark_vk(&zkm_version).to_vec()), - } +fn load_part_stark_vk_for_version(zkm_version: &str) -> Result> { + std::panic::catch_unwind(|| Groth16Verifier::get_part_stark_vk(zkm_version).to_vec()) + .map_err(|_| anyhow::anyhow!("failed to load part_stark_vk for version '{zkm_version}'")) +} + +fn load_part_stark_vks_for_versions(ordered_versions: &[String]) -> Result>> { + ordered_versions.iter().map(|version| load_part_stark_vk_for_version(version)).collect() +} + +fn decode_publisher_secret_key_wif(value: &str) -> Result { + let private_key = + PrivateKey::from_wif(value).map_err(|err| format!("invalid publisher WIF key: {err}"))?; + Ok(private_key.inner) +} + +/// Resolve the signer index by matching the secret key derived public key against the active set. +fn resolve_signer_index( + secret_key: &SecretKey, + publisher_public_keys: &[PublicKey], +) -> Result { + let signer_public_key = PublicKey::from_secret_key(&Secp256k1::new(), secret_key); + publisher_public_keys.iter().position(|public_key| *public_key == signer_public_key).ok_or_else( + || anyhow::anyhow!("publisher_secret_key_wif does not belong to active publisher set"), + ) } fn main() -> Result<()> { @@ -125,41 +140,106 @@ fn main() -> Result<()> { let cli = Cli::parse(); match cli.command { - Command::Append { - part_stark_vk_file, - zkm_version, - commit_info_file, - publisher_signers, - attestation_dir, - } => { + Command::BuildTree { versions, attestation_dir } => { let attestation_dir = resolve_attestation_dir(attestation_dir); - let part_stark_vk = load_part_stark_vk(part_stark_vk_file, zkm_version)?; - let (publisher_public_keys, threshold) = load_publisher_set(&commit_info_file)?; - let signer_refs = resolve_signers(&publisher_signers)?; - let bundle = append_part_stark_vk_and_sign_with_signers( + let ordered_versions = order_versions(&versions)?; + let part_stark_vks = load_part_stark_vks_for_versions(&ordered_versions)?; + save_latest_part_stark_vk_attestation_snapshot( &attestation_dir, - part_stark_vk, - &publisher_public_keys, - threshold, - &signer_refs, + &ordered_versions, + &part_stark_vks, + None, + None, + None, + vec![], ) .map_err(anyhow::Error::msg)?; - println!("{}", serde_json::to_string_pretty(&bundle)?); + println!( + "built latest part_stark_vk snapshot in {} for versions {}", + attestation_dir.display(), + ordered_versions.join(",") + ); } - Command::ResignCurrentRoot { commit_info_file, publisher_signers, attestation_dir } => { + Command::SignRoot { + versions, + commit_info_file, + publisher_secret_key_wif, + attestation_dir, + } => { let attestation_dir = resolve_attestation_dir(attestation_dir); + let ordered_versions = order_versions(&versions)?; + let part_stark_vks = load_part_stark_vks_for_versions(&ordered_versions)?; let (publisher_public_keys, threshold) = load_publisher_set(&commit_info_file)?; - let signer_refs = resolve_signers(&publisher_signers)?; - resign_current_part_stark_vk_root_with_signers( + let signer_pubkey_index = + resolve_signer_index(&publisher_secret_key_wif, &publisher_public_keys)?; + let manifest = sign_latest_part_stark_vk_snapshot( &attestation_dir, + &ordered_versions, + &part_stark_vks, &publisher_public_keys, threshold, - &signer_refs, + signer_pubkey_index, + &publisher_secret_key_wif, ) .map_err(anyhow::Error::msg)?; - println!("resigned part_stark_vk root attestations in {}", attestation_dir.display()); + println!("{}", serde_json::to_string_pretty(&manifest)?); } } Ok(()) } + +#[cfg(test)] +mod tests { + use super::*; + use bitcoin::secp256k1::Secp256k1; + + #[test] + fn test_decode_publisher_secret_key_wif_accepts_wif() { + let secret_key = + SecretKey::from_str("0101010101010101010101010101010101010101010101010101010101010101") + .unwrap(); + let private_key = PrivateKey::new(secret_key, Network::Regtest); + + let decoded = decode_publisher_secret_key_wif(&private_key.to_wif()).unwrap(); + + assert_eq!(decoded, secret_key); + } + + #[test] + fn test_order_versions_sorts_semver_with_v_prefix() { + let ordered = + order_versions(&["v1.2.10".to_string(), "v1.2.4".to_string(), "v1.2.5".to_string()]) + .unwrap(); + assert_eq!(ordered, vec!["v1.2.4", "v1.2.5", "v1.2.10"]); + } + + #[test] + fn test_order_versions_rejects_duplicate_versions() { + let err = order_versions(&["v1.2.5".to_string(), "v1.2.5".to_string()]).unwrap_err(); + assert!(err.to_string().contains("duplicate")); + } + + #[test] + fn test_resolve_signer_index_matches_active_publisher_set_order() { + let secp = Secp256k1::new(); + let secret_key_0 = + SecretKey::from_str("0101010101010101010101010101010101010101010101010101010101010101") + .unwrap(); + let secret_key_1 = + SecretKey::from_str("0202020202020202020202020202020202020202020202020202020202020202") + .unwrap(); + let secret_key_2 = + SecretKey::from_str("0303030303030303030303030303030303030303030303030303030303030303") + .unwrap(); + let publisher_public_keys = vec![ + PublicKey::from_secret_key(&secp, &secret_key_2), + PublicKey::from_secret_key(&secp, &secret_key_0), + PublicKey::from_secret_key(&secp, &secret_key_1), + ]; + + let signer_index = resolve_signer_index(&secret_key_0, &publisher_public_keys).unwrap(); + + assert_eq!(signer_index, 1); + } +} From 0231a5357c251f1dfb123f5ad7222c64397a28f5 Mon Sep 17 00:00:00 2001 From: Blake Date: Sun, 12 Apr 2026 00:55:14 +0800 Subject: [PATCH 12/14] chore: update Ziren dependencies to v1.2.5 and clean up outdated patch references --- Cargo.lock | 331 +++++++++++-------- Cargo.toml | 11 +- circuits/commit-chain-proof/guest/Cargo.toml | 8 +- circuits/header-chain-proof/guest/Cargo.toml | 8 +- circuits/operator-proof/guest/Cargo.toml | 7 +- circuits/state-chain-proof/guest/Cargo.toml | 8 +- circuits/watchtower-proof/guest/Cargo.toml | 7 +- 7 files changed, 203 insertions(+), 177 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a79b2df9..8f8f2862 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -103,7 +103,7 @@ checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" [[package]] name = "alloy" version = "1.8.3" -source = "git+https://github.com/alloy-rs/alloy#5cc9464fa40b71b925170dec861530381857509c" +source = "git+https://github.com/alloy-rs/alloy#f603b229c621a2a1697f24b2845595e451fd7af9" dependencies = [ "alloy-consensus 1.8.3", "alloy-contract", @@ -166,7 +166,7 @@ dependencies = [ [[package]] name = "alloy-consensus" version = "1.8.3" -source = "git+https://github.com/alloy-rs/alloy#5cc9464fa40b71b925170dec861530381857509c" +source = "git+https://github.com/alloy-rs/alloy#f603b229c621a2a1697f24b2845595e451fd7af9" dependencies = [ "alloy-eips 1.8.3", "alloy-primitives", @@ -205,7 +205,7 @@ dependencies = [ [[package]] name = "alloy-consensus-any" version = "1.8.3" -source = "git+https://github.com/alloy-rs/alloy#5cc9464fa40b71b925170dec861530381857509c" +source = "git+https://github.com/alloy-rs/alloy#f603b229c621a2a1697f24b2845595e451fd7af9" dependencies = [ "alloy-consensus 1.8.3", "alloy-eips 1.8.3", @@ -218,7 +218,7 @@ dependencies = [ [[package]] name = "alloy-contract" version = "1.8.3" -source = "git+https://github.com/alloy-rs/alloy#5cc9464fa40b71b925170dec861530381857509c" +source = "git+https://github.com/alloy-rs/alloy#f603b229c621a2a1697f24b2845595e451fd7af9" dependencies = [ "alloy-consensus 1.8.3", "alloy-dyn-abi", @@ -343,7 +343,7 @@ dependencies = [ [[package]] name = "alloy-eips" version = "1.8.3" -source = "git+https://github.com/alloy-rs/alloy#5cc9464fa40b71b925170dec861530381857509c" +source = "git+https://github.com/alloy-rs/alloy#f603b229c621a2a1697f24b2845595e451fd7af9" dependencies = [ "alloy-eip2124", "alloy-eip2930", @@ -398,7 +398,7 @@ dependencies = [ [[package]] name = "alloy-genesis" version = "1.8.3" -source = "git+https://github.com/alloy-rs/alloy#5cc9464fa40b71b925170dec861530381857509c" +source = "git+https://github.com/alloy-rs/alloy#f603b229c621a2a1697f24b2845595e451fd7af9" dependencies = [ "alloy-eips 1.8.3", "alloy-primitives", @@ -451,7 +451,7 @@ dependencies = [ [[package]] name = "alloy-json-rpc" version = "1.8.3" -source = "git+https://github.com/alloy-rs/alloy#5cc9464fa40b71b925170dec861530381857509c" +source = "git+https://github.com/alloy-rs/alloy#f603b229c621a2a1697f24b2845595e451fd7af9" dependencies = [ "alloy-primitives", "alloy-sol-types", @@ -490,7 +490,7 @@ dependencies = [ [[package]] name = "alloy-network" version = "1.8.3" -source = "git+https://github.com/alloy-rs/alloy#5cc9464fa40b71b925170dec861530381857509c" +source = "git+https://github.com/alloy-rs/alloy#f603b229c621a2a1697f24b2845595e451fd7af9" dependencies = [ "alloy-consensus 1.8.3", "alloy-consensus-any 1.8.3", @@ -527,7 +527,7 @@ dependencies = [ [[package]] name = "alloy-network-primitives" version = "1.8.3" -source = "git+https://github.com/alloy-rs/alloy#5cc9464fa40b71b925170dec861530381857509c" +source = "git+https://github.com/alloy-rs/alloy#f603b229c621a2a1697f24b2845595e451fd7af9" dependencies = [ "alloy-consensus 1.8.3", "alloy-eips 1.8.3", @@ -578,13 +578,13 @@ dependencies = [ "derive_more 2.1.1", "foldhash 0.2.0", "hashbrown 0.16.1", - "indexmap 2.13.1", + "indexmap 2.14.0", "itoa", "k256", "keccak-asm", "paste", "proptest", - "rand 0.9.2", + "rand 0.9.3", "rapidhash", "ruint", "rustc-hash 2.1.2", @@ -635,7 +635,7 @@ dependencies = [ [[package]] name = "alloy-provider" version = "1.8.3" -source = "git+https://github.com/alloy-rs/alloy#5cc9464fa40b71b925170dec861530381857509c" +source = "git+https://github.com/alloy-rs/alloy#f603b229c621a2a1697f24b2845595e451fd7af9" dependencies = [ "alloy-chains", "alloy-consensus 1.8.3", @@ -680,7 +680,7 @@ dependencies = [ [[package]] name = "alloy-pubsub" version = "1.8.3" -source = "git+https://github.com/alloy-rs/alloy#5cc9464fa40b71b925170dec861530381857509c" +source = "git+https://github.com/alloy-rs/alloy#f603b229c621a2a1697f24b2845595e451fd7af9" dependencies = [ "alloy-json-rpc 1.8.3", "alloy-primitives", @@ -745,7 +745,7 @@ dependencies = [ [[package]] name = "alloy-rpc-client" version = "1.8.3" -source = "git+https://github.com/alloy-rs/alloy#5cc9464fa40b71b925170dec861530381857509c" +source = "git+https://github.com/alloy-rs/alloy#f603b229c621a2a1697f24b2845595e451fd7af9" dependencies = [ "alloy-json-rpc 1.8.3", "alloy-primitives", @@ -781,7 +781,7 @@ dependencies = [ [[package]] name = "alloy-rpc-types" version = "1.8.3" -source = "git+https://github.com/alloy-rs/alloy#5cc9464fa40b71b925170dec861530381857509c" +source = "git+https://github.com/alloy-rs/alloy#f603b229c621a2a1697f24b2845595e451fd7af9" dependencies = [ "alloy-primitives", "alloy-rpc-types-anvil", @@ -797,7 +797,7 @@ dependencies = [ [[package]] name = "alloy-rpc-types-anvil" version = "1.8.3" -source = "git+https://github.com/alloy-rs/alloy#5cc9464fa40b71b925170dec861530381857509c" +source = "git+https://github.com/alloy-rs/alloy#f603b229c621a2a1697f24b2845595e451fd7af9" dependencies = [ "alloy-primitives", "alloy-rpc-types-eth 1.8.3", @@ -818,7 +818,7 @@ dependencies = [ [[package]] name = "alloy-rpc-types-any" version = "1.8.3" -source = "git+https://github.com/alloy-rs/alloy#5cc9464fa40b71b925170dec861530381857509c" +source = "git+https://github.com/alloy-rs/alloy#f603b229c621a2a1697f24b2845595e451fd7af9" dependencies = [ "alloy-consensus-any 1.8.3", "alloy-rpc-types-eth 1.8.3", @@ -839,7 +839,7 @@ dependencies = [ [[package]] name = "alloy-rpc-types-debug" version = "1.8.3" -source = "git+https://github.com/alloy-rs/alloy#5cc9464fa40b71b925170dec861530381857509c" +source = "git+https://github.com/alloy-rs/alloy#f603b229c621a2a1697f24b2845595e451fd7af9" dependencies = [ "alloy-primitives", "alloy-rlp", @@ -864,7 +864,7 @@ dependencies = [ [[package]] name = "alloy-rpc-types-engine" version = "1.8.3" -source = "git+https://github.com/alloy-rs/alloy#5cc9464fa40b71b925170dec861530381857509c" +source = "git+https://github.com/alloy-rs/alloy#f603b229c621a2a1697f24b2845595e451fd7af9" dependencies = [ "alloy-consensus 1.8.3", "alloy-eips 1.8.3", @@ -900,7 +900,7 @@ dependencies = [ [[package]] name = "alloy-rpc-types-eth" version = "1.8.3" -source = "git+https://github.com/alloy-rs/alloy#5cc9464fa40b71b925170dec861530381857509c" +source = "git+https://github.com/alloy-rs/alloy#f603b229c621a2a1697f24b2845595e451fd7af9" dependencies = [ "alloy-consensus 1.8.3", "alloy-consensus-any 1.8.3", @@ -933,7 +933,7 @@ dependencies = [ [[package]] name = "alloy-rpc-types-trace" version = "1.8.3" -source = "git+https://github.com/alloy-rs/alloy#5cc9464fa40b71b925170dec861530381857509c" +source = "git+https://github.com/alloy-rs/alloy#f603b229c621a2a1697f24b2845595e451fd7af9" dependencies = [ "alloy-primitives", "alloy-rpc-types-eth 1.8.3", @@ -946,7 +946,7 @@ dependencies = [ [[package]] name = "alloy-rpc-types-txpool" version = "1.8.3" -source = "git+https://github.com/alloy-rs/alloy#5cc9464fa40b71b925170dec861530381857509c" +source = "git+https://github.com/alloy-rs/alloy#f603b229c621a2a1697f24b2845595e451fd7af9" dependencies = [ "alloy-primitives", "alloy-rpc-types-eth 1.8.3", @@ -967,7 +967,7 @@ dependencies = [ [[package]] name = "alloy-serde" version = "1.8.3" -source = "git+https://github.com/alloy-rs/alloy#5cc9464fa40b71b925170dec861530381857509c" +source = "git+https://github.com/alloy-rs/alloy#f603b229c621a2a1697f24b2845595e451fd7af9" dependencies = [ "alloy-primitives", "serde", @@ -1006,7 +1006,7 @@ dependencies = [ [[package]] name = "alloy-signer" version = "1.8.3" -source = "git+https://github.com/alloy-rs/alloy#5cc9464fa40b71b925170dec861530381857509c" +source = "git+https://github.com/alloy-rs/alloy#f603b229c621a2a1697f24b2845595e451fd7af9" dependencies = [ "alloy-primitives", "async-trait", @@ -1020,7 +1020,7 @@ dependencies = [ [[package]] name = "alloy-signer-local" version = "1.8.3" -source = "git+https://github.com/alloy-rs/alloy#5cc9464fa40b71b925170dec861530381857509c" +source = "git+https://github.com/alloy-rs/alloy#f603b229c621a2a1697f24b2845595e451fd7af9" dependencies = [ "alloy-consensus 1.8.3", "alloy-network 1.8.3", @@ -1056,7 +1056,7 @@ dependencies = [ "alloy-sol-macro-input", "const-hex", "heck 0.5.0", - "indexmap 2.13.1", + "indexmap 2.14.0", "proc-macro-error2", "proc-macro2", "quote", @@ -1131,7 +1131,7 @@ dependencies = [ [[package]] name = "alloy-transport" version = "1.8.3" -source = "git+https://github.com/alloy-rs/alloy#5cc9464fa40b71b925170dec861530381857509c" +source = "git+https://github.com/alloy-rs/alloy#f603b229c621a2a1697f24b2845595e451fd7af9" dependencies = [ "alloy-json-rpc 1.8.3", "auto_impl", @@ -1167,7 +1167,7 @@ dependencies = [ [[package]] name = "alloy-transport-http" version = "1.8.3" -source = "git+https://github.com/alloy-rs/alloy#5cc9464fa40b71b925170dec861530381857509c" +source = "git+https://github.com/alloy-rs/alloy#f603b229c621a2a1697f24b2845595e451fd7af9" dependencies = [ "alloy-json-rpc 1.8.3", "alloy-transport 1.8.3", @@ -1182,7 +1182,7 @@ dependencies = [ [[package]] name = "alloy-transport-ipc" version = "1.8.3" -source = "git+https://github.com/alloy-rs/alloy#5cc9464fa40b71b925170dec861530381857509c" +source = "git+https://github.com/alloy-rs/alloy#f603b229c621a2a1697f24b2845595e451fd7af9" dependencies = [ "alloy-json-rpc 1.8.3", "alloy-pubsub", @@ -1201,7 +1201,7 @@ dependencies = [ [[package]] name = "alloy-transport-ws" version = "1.8.3" -source = "git+https://github.com/alloy-rs/alloy#5cc9464fa40b71b925170dec861530381857509c" +source = "git+https://github.com/alloy-rs/alloy#f603b229c621a2a1697f24b2845595e451fd7af9" dependencies = [ "alloy-pubsub", "alloy-transport 1.8.3", @@ -1263,7 +1263,7 @@ dependencies = [ [[package]] name = "alloy-tx-macros" version = "1.8.3" -source = "git+https://github.com/alloy-rs/alloy#5cc9464fa40b71b925170dec861530381857509c" +source = "git+https://github.com/alloy-rs/alloy#f603b229c621a2a1697f24b2845595e451fd7af9" dependencies = [ "darling 0.23.0", "proc-macro2", @@ -2656,7 +2656,7 @@ dependencies = [ "hex", "http 1.4.0", "http-body-util", - "indexmap 2.13.1", + "indexmap 2.14.0", "indicatif", "libp2p", "libp2p-metrics", @@ -2788,7 +2788,7 @@ dependencies = [ "pairing 0.23.0", "rand_core 0.6.4", "subtle", - "zkm-lib 1.2.4 (git+https://github.com/ProjectZKM/Ziren)", + "zkm-lib", ] [[package]] @@ -2973,9 +2973,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.2.59" +version = "1.2.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7a4d3ec6524d28a329fc53654bbadc9bdd7b0431f5d65f1a56ffb28a1ee5283" +checksum = "43c5703da9466b66a946814e1adf53ea2c90f10063b86290cc9eb67ce3478a20" dependencies = [ "find-msvc-tools", "jobserver", @@ -4268,6 +4268,29 @@ dependencies = [ "syn 2.0.117", ] +[[package]] +name = "env_filter" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32e90c2accc4b07a8456ea0debdc2e7587bdd890680d71173a15d4ae604f6eef" +dependencies = [ + "log", + "regex", +] + +[[package]] +name = "env_logger" +version = "0.11.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0621c04f2196ac3f488dd583365b9c09be011a4ab8b9f37248ffcc8f6198b56a" +dependencies = [ + "anstream", + "anstyle", + "env_filter", + "jiff", + "log", +] + [[package]] name = "equivalent" version = "1.0.2" @@ -5279,7 +5302,7 @@ dependencies = [ "futures-sink", "futures-util", "http 0.2.12", - "indexmap 2.13.1", + "indexmap 2.14.0", "slab", "tokio", "tokio-util", @@ -5298,7 +5321,7 @@ dependencies = [ "futures-core", "futures-sink", "http 1.4.0", - "indexmap 2.13.1", + "indexmap 2.14.0", "slab", "tokio", "tokio-util", @@ -5413,6 +5436,12 @@ dependencies = [ "serde_core", ] +[[package]] +name = "hashbrown" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f467dd6dccf739c208452f8014c75c18bb8301b050ad1cfb27153803edb0f51" + [[package]] name = "hashers" version = "1.0.1" @@ -5586,7 +5615,7 @@ dependencies = [ "idna", "ipnet", "once_cell", - "rand 0.9.2", + "rand 0.9.3", "socket2 0.5.10", "thiserror 2.0.18", "tinyvec", @@ -5629,7 +5658,7 @@ dependencies = [ "moka", "once_cell", "parking_lot", - "rand 0.9.2", + "rand 0.9.3", "resolv-conf", "smallvec", "thiserror 2.0.18", @@ -6158,12 +6187,12 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.13.1" +version = "2.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45a8a2b9cb3e0b0c1803dbb0758ffac5de2f425b23c28f518faabd9d805342ff" +checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9" dependencies = [ "equivalent", - "hashbrown 0.16.1", + "hashbrown 0.17.0", "serde", "serde_core", ] @@ -6310,6 +6339,30 @@ version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" +[[package]] +name = "jiff" +version = "0.2.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a3546dc96b6d42c5f24902af9e2538e82e39ad350b0c766eb3fbf2d8f3d8359" +dependencies = [ + "jiff-static", + "log", + "portable-atomic", + "portable-atomic-util", + "serde_core", +] + +[[package]] +name = "jiff-static" +version = "0.2.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a8c8b344124222efd714b73bb41f8b5120b27a7cc1c75593a6ff768d9d05aa4" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + [[package]] name = "jni" version = "0.21.1" @@ -6366,9 +6419,9 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.94" +version = "0.3.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e04e2ef80ce82e13552136fabeef8a5ed1f985a96805761cbb9a2c34e7664d9" +checksum = "2964e92d1d9dc3364cae4d718d93f227e3abb088e747d92e0395bfdedf1c12ca" dependencies = [ "cfg-if", "futures-util", @@ -6980,7 +7033,7 @@ dependencies = [ "rcgen", "ring 0.17.14", "rustls 0.23.37", - "rustls-webpki 0.103.10", + "rustls-webpki 0.103.11", "thiserror 2.0.18", "x509-parser", "yasna", @@ -7039,14 +7092,14 @@ dependencies = [ [[package]] name = "libredox" -version = "0.1.15" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ddbf48fd451246b1f8c2610bd3b4ac0cc6e149d89832867093ab69a17194f08" +checksum = "e02f3bb43d335493c96bf3fd3a321600bf6bd07ed34bc64118e9293bdffea46c" dependencies = [ "bitflags 2.11.0", "libc", "plain", - "redox_syscall 0.7.3", + "redox_syscall 0.7.4", ] [[package]] @@ -8594,7 +8647,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db" dependencies = [ "fixedbitset 0.4.2", - "indexmap 2.13.1", + "indexmap 2.14.0", ] [[package]] @@ -8604,7 +8657,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3672b37090dbd86368a4145bc067582552b29c27377cad4e0a306c97f9bd7772" dependencies = [ "fixedbitset 0.5.7", - "indexmap 2.13.1", + "indexmap 2.14.0", ] [[package]] @@ -8912,6 +8965,15 @@ version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c33a9471896f1c69cecef8d20cbe2f7accd12527ce60845ff44c153bb2a21b49" +[[package]] +name = "portable-atomic-util" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "091397be61a01d4be58e7841595bd4bfedb15f1cd54977d79b8271e94ed799a3" +dependencies = [ + "portable-atomic", +] + [[package]] name = "potential_utf" version = "0.1.5" @@ -9156,7 +9218,7 @@ dependencies = [ "bit-vec 0.8.0", "bitflags 2.11.0", "num-traits", - "rand 0.9.2", + "rand 0.9.3", "rand_chacha 0.9.0", "rand_xorshift", "regex-syntax", @@ -9342,7 +9404,7 @@ dependencies = [ "bytes", "getrandom 0.3.4", "lru-slab", - "rand 0.9.2", + "rand 0.9.3", "ring 0.17.14", "rustc-hash 2.1.2", "rustls 0.23.37", @@ -9409,9 +9471,9 @@ dependencies = [ [[package]] name = "rand" -version = "0.9.2" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1" +checksum = "7ec095654a25171c2124e9e3393a930bddbffdc939556c914957a4c3e0a87166" dependencies = [ "rand_chacha 0.9.0", "rand_core 0.9.5", @@ -9420,9 +9482,9 @@ dependencies = [ [[package]] name = "rand" -version = "0.10.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc266eb313df6c5c09c1c7b1fbe2510961e5bcd3add930c1e31f7ed9da0feff8" +checksum = "d2e8e8bcc7961af1fdac401278c6a831614941f6164ee3bf4ce61b7edb162207" dependencies = [ "chacha20 0.10.0", "getrandom 0.4.2", @@ -9551,9 +9613,9 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ce70a74e890531977d37e532c34d45e9055d2409ed08ddba14529471ed0be16" +checksum = "f450ad9c3b1da563fb6948a8e0fb0fb9269711c9c73d9ea1de5058c79c8d643a" dependencies = [ "bitflags 2.11.0", ] @@ -10566,7 +10628,7 @@ dependencies = [ "primitive-types", "proptest", "rand 0.8.5", - "rand 0.9.2", + "rand 0.9.3", "rlp", "ruint-macro", "serde_core", @@ -10691,7 +10753,7 @@ dependencies = [ "once_cell", "ring 0.17.14", "rustls-pki-types", - "rustls-webpki 0.103.10", + "rustls-webpki 0.103.11", "subtle", "zeroize", ] @@ -10753,7 +10815,7 @@ dependencies = [ "rustls 0.23.37", "rustls-native-certs 0.8.3", "rustls-platform-verifier-android", - "rustls-webpki 0.103.10", + "rustls-webpki 0.103.11", "security-framework 3.7.0", "security-framework-sys", "webpki-root-certs", @@ -10778,9 +10840,9 @@ dependencies = [ [[package]] name = "rustls-webpki" -version = "0.103.10" +version = "0.103.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df33b2b81ac578cabaf06b89b0631153a3f416b0a886e8a7a1707fb51abbd1ef" +checksum = "20a6af516fea4b20eccceaf166e8aa666ac996208e8a644ce3ef5aa783bc7cd4" dependencies = [ "aws-lc-rs", "ring 0.17.14", @@ -11245,7 +11307,7 @@ dependencies = [ "chrono", "hex", "indexmap 1.9.3", - "indexmap 2.13.1", + "indexmap 2.14.0", "schemars 0.9.0", "schemars 1.2.1", "serde_core", @@ -11590,7 +11652,7 @@ dependencies = [ "futures-util", "hashbrown 0.15.5", "hashlink 0.10.0", - "indexmap 2.13.1", + "indexmap 2.14.0", "log", "memchr", "once_cell", @@ -11847,7 +11909,7 @@ dependencies = [ "bitcoin 0.32.8", "futures", "hex", - "indexmap 2.13.1", + "indexmap 2.14.0", "reqwest 0.12.28", "serde", "serde_json", @@ -11979,7 +12041,7 @@ dependencies = [ "num-bigint 0.4.6", "rand 0.8.5", "rustc-hex", - "zkm-lib 1.2.4 (git+https://github.com/ProjectZKM/Ziren)", + "zkm-lib", ] [[package]] @@ -12608,7 +12670,7 @@ version = "0.22.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" dependencies = [ - "indexmap 2.13.1", + "indexmap 2.14.0", "serde", "serde_spanned", "toml_datetime 0.6.11", @@ -12622,7 +12684,7 @@ version = "0.25.11+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b59c4d22ed448339746c59b905d24568fcbb3ab65a500494f7b8c3e97739f2b" dependencies = [ - "indexmap 2.13.1", + "indexmap 2.14.0", "toml_datetime 1.1.1+spec-1.1.0", "toml_parser", "winnow 1.0.1", @@ -12910,7 +12972,7 @@ dependencies = [ "http 1.4.0", "httparse", "log", - "rand 0.9.2", + "rand 0.9.3", "rustls 0.23.37", "rustls-pki-types", "sha1", @@ -13143,7 +13205,7 @@ checksum = "5ac8b6f42ead25368cf5b098aeb3dc8a1a2c05a3eee8a9a1a68c640edbfc79d9" dependencies = [ "getrandom 0.4.2", "js-sys", - "rand 0.10.0", + "rand 0.10.1", "serde_core", "wasm-bindgen", ] @@ -13254,9 +13316,9 @@ checksum = "b8dad83b4f25e74f184f64c43b150b91efe7647395b42289f38e50566d82855b" [[package]] name = "wasm-bindgen" -version = "0.2.117" +version = "0.2.118" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0551fc1bb415591e3372d0bc4780db7e587d84e2a7e79da121051c5c4b89d0b0" +checksum = "0bf938a0bacb0469e83c1e148908bd7d5a6010354cf4fb73279b7447422e3a89" dependencies = [ "cfg-if", "once_cell", @@ -13267,9 +13329,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.67" +version = "0.4.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03623de6905b7206edd0a75f69f747f134b7f0a2323392d664448bf2d3c5d87e" +checksum = "f371d383f2fb139252e0bfac3b81b265689bf45b6874af544ffa4c975ac1ebf8" dependencies = [ "js-sys", "wasm-bindgen", @@ -13277,9 +13339,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.117" +version = "0.2.118" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fbdf9a35adf44786aecd5ff89b4563a90325f9da0923236f6104e603c7e86be" +checksum = "eeff24f84126c0ec2db7a449f0c2ec963c6a49efe0698c4242929da037ca28ed" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -13287,9 +13349,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.117" +version = "0.2.118" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dca9693ef2bab6d4e6707234500350d8dad079eb508dca05530c85dc3a529ff2" +checksum = "9d08065faf983b2b80a79fd87d8254c409281cf7de75fc4b773019824196c904" dependencies = [ "bumpalo", "proc-macro2", @@ -13300,9 +13362,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.117" +version = "0.2.118" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39129a682a6d2d841b6c429d0c51e5cb0ed1a03829d8b3d1e69a011e62cb3d3b" +checksum = "5fd04d9e306f1907bd13c6361b5c6bfc7b3b3c095ed3f8a9246390f8dbdee129" dependencies = [ "unicode-ident", ] @@ -13324,7 +13386,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bb0e353e6a2fbdc176932bbaab493762eb1255a7900fe0fea1a2f96c296cc909" dependencies = [ "anyhow", - "indexmap 2.13.1", + "indexmap 2.14.0", "wasm-encoder", "wasmparser", ] @@ -13350,7 +13412,7 @@ checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" dependencies = [ "bitflags 2.11.0", "hashbrown 0.15.5", - "indexmap 2.13.1", + "indexmap 2.14.0", "semver 1.0.28", ] @@ -13406,9 +13468,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.94" +version = "0.3.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd70027e39b12f0849461e08ffc50b9cd7688d942c1c8e3c7b22273236b4dd0a" +checksum = "4f2dfbb17949fa2088e5d39408c48368947b86f7834484e87b73de55bc14d97d" dependencies = [ "js-sys", "wasm-bindgen", @@ -14019,7 +14081,7 @@ checksum = "b7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21" dependencies = [ "anyhow", "heck 0.5.0", - "indexmap 2.13.1", + "indexmap 2.14.0", "prettyplease 0.2.37", "syn 2.0.117", "wasm-metadata", @@ -14050,7 +14112,7 @@ checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2" dependencies = [ "anyhow", "bitflags 2.11.0", - "indexmap 2.13.1", + "indexmap 2.14.0", "log", "serde", "serde_derive", @@ -14069,7 +14131,7 @@ checksum = "ecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736" dependencies = [ "anyhow", "id-arena", - "indexmap 2.13.1", + "indexmap 2.14.0", "log", "semver 1.0.28", "serde", @@ -14183,7 +14245,7 @@ dependencies = [ "nohash-hasher", "parking_lot", "pin-project", - "rand 0.9.2", + "rand 0.9.3", "static_assertions", "web-time", ] @@ -14369,8 +14431,8 @@ dependencies = [ [[package]] name = "zkm-build" -version = "1.2.4" -source = "git+https://github.com/blake-pro/Ziren.git?branch=v1.2.4-imm#f40ebf9c916689d7454425eda5f9fa18a50395e2" +version = "1.2.5" +source = "git+https://github.com/ProjectZKM/Ziren#c736a41cccd623427295f89b53306673adc89966" dependencies = [ "anyhow", "cargo_metadata", @@ -14380,14 +14442,15 @@ dependencies = [ [[package]] name = "zkm-core-executor" -version = "1.2.4" -source = "git+https://github.com/blake-pro/Ziren.git?branch=v1.2.4-imm#f40ebf9c916689d7454425eda5f9fa18a50395e2" +version = "1.2.5" +source = "git+https://github.com/ProjectZKM/Ziren#c736a41cccd623427295f89b53306673adc89966" dependencies = [ "anyhow", "bincode", "bytemuck", "elf", "enum-map", + "env_logger", "eyre", "hashbrown 0.14.5", "hex", @@ -14395,6 +14458,7 @@ dependencies = [ "log", "nohash-hasher", "num", + "num_enum", "p3-field", "p3-koala-bear", "p3-maybe-rayon", @@ -14409,6 +14473,7 @@ dependencies = [ "thiserror 1.0.69", "tiny-keccak", "tracing", + "tracing-subscriber 0.3.23", "typenum", "vec_map", "zkm-curves", @@ -14418,8 +14483,8 @@ dependencies = [ [[package]] name = "zkm-core-machine" -version = "1.2.4" -source = "git+https://github.com/blake-pro/Ziren.git?branch=v1.2.4-imm#f40ebf9c916689d7454425eda5f9fa18a50395e2" +version = "1.2.5" +source = "git+https://github.com/ProjectZKM/Ziren#c736a41cccd623427295f89b53306673adc89966" dependencies = [ "bincode", "cfg-if", @@ -14470,8 +14535,8 @@ dependencies = [ [[package]] name = "zkm-cuda" -version = "1.2.4" -source = "git+https://github.com/blake-pro/Ziren.git?branch=v1.2.4-imm#f40ebf9c916689d7454425eda5f9fa18a50395e2" +version = "1.2.5" +source = "git+https://github.com/ProjectZKM/Ziren#c736a41cccd623427295f89b53306673adc89966" dependencies = [ "bincode", "ctrlc", @@ -14488,8 +14553,8 @@ dependencies = [ [[package]] name = "zkm-curves" -version = "1.2.4" -source = "git+https://github.com/blake-pro/Ziren.git?branch=v1.2.4-imm#f40ebf9c916689d7454425eda5f9fa18a50395e2" +version = "1.2.5" +source = "git+https://github.com/ProjectZKM/Ziren#c736a41cccd623427295f89b53306673adc89966" dependencies = [ "cfg-if", "curve25519-dalek", @@ -14512,30 +14577,18 @@ dependencies = [ [[package]] name = "zkm-derive" -version = "1.2.4" -source = "git+https://github.com/blake-pro/Ziren.git?branch=v1.2.4-imm#f40ebf9c916689d7454425eda5f9fa18a50395e2" +version = "1.2.5" +source = "git+https://github.com/ProjectZKM/Ziren#c736a41cccd623427295f89b53306673adc89966" dependencies = [ + "proc-macro2", "quote", "syn 1.0.109", ] [[package]] name = "zkm-lib" -version = "1.2.4" -source = "git+https://github.com/blake-pro/Ziren.git?branch=v1.2.4-imm#f40ebf9c916689d7454425eda5f9fa18a50395e2" -dependencies = [ - "bincode", - "cfg-if", - "elliptic-curve", - "serde", - "sha2 0.10.9", - "zkm-primitives", -] - -[[package]] -name = "zkm-lib" -version = "1.2.4" -source = "git+https://github.com/ProjectZKM/Ziren#1d43121312d4b93c0989984bf0c7ab77d9a0ce04" +version = "1.2.5" +source = "git+https://github.com/ProjectZKM/Ziren#c736a41cccd623427295f89b53306673adc89966" dependencies = [ "bincode", "cfg-if", @@ -14547,8 +14600,8 @@ dependencies = [ [[package]] name = "zkm-primitives" -version = "1.2.4" -source = "git+https://github.com/blake-pro/Ziren.git?branch=v1.2.4-imm#f40ebf9c916689d7454425eda5f9fa18a50395e2" +version = "1.2.5" +source = "git+https://github.com/ProjectZKM/Ziren#c736a41cccd623427295f89b53306673adc89966" dependencies = [ "bincode", "hex", @@ -14565,8 +14618,8 @@ dependencies = [ [[package]] name = "zkm-prover" -version = "1.2.4" -source = "git+https://github.com/blake-pro/Ziren.git?branch=v1.2.4-imm#f40ebf9c916689d7454425eda5f9fa18a50395e2" +version = "1.2.5" +source = "git+https://github.com/ProjectZKM/Ziren#c736a41cccd623427295f89b53306673adc89966" dependencies = [ "anyhow", "bincode", @@ -14602,8 +14655,8 @@ dependencies = [ [[package]] name = "zkm-recursion-circuit" -version = "1.2.4" -source = "git+https://github.com/blake-pro/Ziren.git?branch=v1.2.4-imm#f40ebf9c916689d7454425eda5f9fa18a50395e2" +version = "1.2.5" +source = "git+https://github.com/ProjectZKM/Ziren#c736a41cccd623427295f89b53306673adc89966" dependencies = [ "hashbrown 0.14.5", "itertools 0.13.0", @@ -14635,8 +14688,8 @@ dependencies = [ [[package]] name = "zkm-recursion-compiler" -version = "1.2.4" -source = "git+https://github.com/blake-pro/Ziren.git?branch=v1.2.4-imm#f40ebf9c916689d7454425eda5f9fa18a50395e2" +version = "1.2.5" +source = "git+https://github.com/ProjectZKM/Ziren#c736a41cccd623427295f89b53306673adc89966" dependencies = [ "backtrace", "itertools 0.13.0", @@ -14656,8 +14709,8 @@ dependencies = [ [[package]] name = "zkm-recursion-core" -version = "1.2.4" -source = "git+https://github.com/blake-pro/Ziren.git?branch=v1.2.4-imm#f40ebf9c916689d7454425eda5f9fa18a50395e2" +version = "1.2.5" +source = "git+https://github.com/ProjectZKM/Ziren#c736a41cccd623427295f89b53306673adc89966" dependencies = [ "backtrace", "ff 0.13.1", @@ -14693,8 +14746,8 @@ dependencies = [ [[package]] name = "zkm-recursion-derive" -version = "1.2.4" -source = "git+https://github.com/blake-pro/Ziren.git?branch=v1.2.4-imm#f40ebf9c916689d7454425eda5f9fa18a50395e2" +version = "1.2.5" +source = "git+https://github.com/ProjectZKM/Ziren#c736a41cccd623427295f89b53306673adc89966" dependencies = [ "quote", "syn 1.0.109", @@ -14702,8 +14755,8 @@ dependencies = [ [[package]] name = "zkm-recursion-gnark-ffi" -version = "1.2.4" -source = "git+https://github.com/blake-pro/Ziren.git?branch=v1.2.4-imm#f40ebf9c916689d7454425eda5f9fa18a50395e2" +version = "1.2.5" +source = "git+https://github.com/ProjectZKM/Ziren#c736a41cccd623427295f89b53306673adc89966" dependencies = [ "anyhow", "bincode", @@ -14726,8 +14779,8 @@ dependencies = [ [[package]] name = "zkm-sdk" -version = "1.2.4" -source = "git+https://github.com/blake-pro/Ziren.git?branch=v1.2.4-imm#f40ebf9c916689d7454425eda5f9fa18a50395e2" +version = "1.2.5" +source = "git+https://github.com/ProjectZKM/Ziren#c736a41cccd623427295f89b53306673adc89966" dependencies = [ "alloy-primitives", "alloy-signer 1.8.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -14773,8 +14826,8 @@ dependencies = [ [[package]] name = "zkm-stark" -version = "1.2.4" -source = "git+https://github.com/blake-pro/Ziren.git?branch=v1.2.4-imm#f40ebf9c916689d7454425eda5f9fa18a50395e2" +version = "1.2.5" +source = "git+https://github.com/ProjectZKM/Ziren#c736a41cccd623427295f89b53306673adc89966" dependencies = [ "arrayref", "hashbrown 0.14.5", @@ -14815,8 +14868,8 @@ dependencies = [ [[package]] name = "zkm-verifier" -version = "1.2.4" -source = "git+https://github.com/blake-pro/Ziren.git?branch=v1.2.4-imm#f40ebf9c916689d7454425eda5f9fa18a50395e2" +version = "1.2.5" +source = "git+https://github.com/ProjectZKM/Ziren#c736a41cccd623427295f89b53306673adc89966" dependencies = [ "anyhow", "ark-bn254", @@ -14851,8 +14904,8 @@ dependencies = [ [[package]] name = "zkm-zkvm" -version = "1.2.4" -source = "git+https://github.com/blake-pro/Ziren.git?branch=v1.2.4-imm#f40ebf9c916689d7454425eda5f9fa18a50395e2" +version = "1.2.5" +source = "git+https://github.com/ProjectZKM/Ziren#c736a41cccd623427295f89b53306673adc89966" dependencies = [ "bincode", "cfg-if", @@ -14864,7 +14917,7 @@ dependencies = [ "rand 0.8.5", "serde", "sha2 0.10.9", - "zkm-lib 1.2.4 (git+https://github.com/blake-pro/Ziren.git?branch=v1.2.4-imm)", + "zkm-lib", "zkm-primitives", ] diff --git a/Cargo.toml b/Cargo.toml index 37b67fe8..fc503f7e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -176,13 +176,4 @@ rust.missing_debug_implementations = "warn" rust.unreachable_pub = "warn" rust.unused_must_use = "deny" rust.rust_2018_idioms = { level = "deny", priority = -1 } -rustdoc.all = "warn" - -[patch."https://github.com/ProjectZKM/Ziren"] -zkm-build = { git = "https://github.com/blake-pro/Ziren.git", branch = "v1.2.4-imm" } -zkm-core-executor = { git = "https://github.com/blake-pro/Ziren.git", branch = "v1.2.4-imm" } -zkm-prover = { git = "https://github.com/blake-pro/Ziren.git", branch = "v1.2.4-imm" } -zkm-sdk = { git = "https://github.com/blake-pro/Ziren.git", branch = "v1.2.4-imm" } -zkm-verifier = { git = "https://github.com/blake-pro/Ziren.git", branch = "v1.2.4-imm" } -zkm-primitives = { git = "https://github.com/blake-pro/Ziren.git", branch = "v1.2.4-imm" } -zkm-zkvm = { git = "https://github.com/blake-pro/Ziren.git", branch = "v1.2.4-imm" } \ No newline at end of file +rustdoc.all = "warn" \ No newline at end of file diff --git a/circuits/commit-chain-proof/guest/Cargo.toml b/circuits/commit-chain-proof/guest/Cargo.toml index ac64881a..395813bd 100644 --- a/circuits/commit-chain-proof/guest/Cargo.toml +++ b/circuits/commit-chain-proof/guest/Cargo.toml @@ -11,8 +11,8 @@ bincode = "1.3.3" commit-chain = { path = "../../../crates/commit-chain" } # Ziren -zkm-zkvm = { git = "https://github.com/ProjectZKM/Ziren", package = "zkm-zkvm", features = ["verify"] } -zkm-verifier = { git = "https://github.com/ProjectZKM/Ziren", package = "zkm-verifier" } +zkm-zkvm = { git = "https://github.com/ProjectZKM/Ziren", features = ["verify"] } +zkm-verifier = { git = "https://github.com/ProjectZKM/Ziren" } #zkm-verifier = { path = "../../../../Ziren/crates/verifier" } #zkm-zkvm = { path = "../../../../Ziren/crates/zkvm/entrypoint", features = ["verify"] } @@ -37,7 +37,3 @@ alloy-primitives-v1-1-2 = { git = "https://github.com/ziren-patches/core.git", p alloy-primitives-v1-4-1 = { git = "https://github.com/ziren-patches/core.git", package = "alloy-primitives", branch = "patch-alloy-primitives-1.4.1" } secp256k1-v0-29-1 = { git = "https://github.com/ziren-patches/rust-secp256k1", package = "secp256k1", branch = "patch-0.29.1" } #secp256k1-v0-30-0 = { git = "https://github.com/ziren-patches/rust-secp256k1", package = "secp256k1", branch = "patch-0.30.0" } - -[patch."https://github.com/ProjectZKM/Ziren"] -zkm-zkvm = { git = "https://github.com/blake-pro/Ziren.git", branch = "v1.2.4-imm" } -zkm-verifier = { git = "https://github.com/blake-pro/Ziren.git", branch = "v1.2.4-imm" } diff --git a/circuits/header-chain-proof/guest/Cargo.toml b/circuits/header-chain-proof/guest/Cargo.toml index 88216bbb..42e819c2 100644 --- a/circuits/header-chain-proof/guest/Cargo.toml +++ b/circuits/header-chain-proof/guest/Cargo.toml @@ -13,8 +13,8 @@ header-chain = { path = "../../../crates/header-chain" } borsh = { version = "1.5.3", features = ["derive"] } # Ziren -zkm-zkvm = { git = "https://github.com/ProjectZKM/Ziren", package = "zkm-zkvm", features = ["verify"] } -zkm-verifier = { git = "https://github.com/ProjectZKM/Ziren", package = "zkm-verifier" } +zkm-zkvm = { git = "https://github.com/ProjectZKM/Ziren", features = ["verify"] } +zkm-verifier = { git = "https://github.com/ProjectZKM/Ziren" } #zkm-verifier = { path = "../../../Ziren/crates/verifier" } #zkm-zkvm = { path = "../../../Ziren/crates/zkvm/entrypoint", features = ["verify"] } @@ -38,7 +38,3 @@ alloy-primitives-v1-1-0 = { git = "https://github.com/ziren-patches/core.git", p alloy-primitives-v1-1-2 = { git = "https://github.com/ziren-patches/core.git", package = "alloy-primitives", branch = "patch-alloy-primitives-1.1.2" } secp256k1-v0-29-1 = { git = "https://github.com/ziren-patches/rust-secp256k1", package = "secp256k1", branch = "patch-0.29.1" } #secp256k1-v0-30-0 = { git = "https://github.com/ziren-patches/rust-secp256k1", package = "secp256k1", branch = "patch-0.30.0" } - -[patch."https://github.com/ProjectZKM/Ziren"] -zkm-zkvm = { git = "https://github.com/blake-pro/Ziren.git", branch = "v1.2.4-imm" } -zkm-verifier = { git = "https://github.com/blake-pro/Ziren.git", branch = "v1.2.4-imm" } diff --git a/circuits/operator-proof/guest/Cargo.toml b/circuits/operator-proof/guest/Cargo.toml index 27484283..521f3c95 100644 --- a/circuits/operator-proof/guest/Cargo.toml +++ b/circuits/operator-proof/guest/Cargo.toml @@ -14,8 +14,8 @@ state-chain = { path = "../../../crates/state-chain" } bitcoin-light-client-circuit = { path = "../../../crates/bitcoin-light-client-circuit" } # Ziren -zkm-zkvm = { git = "https://github.com/ProjectZKM/Ziren", package = "zkm-zkvm", features = ["verify"] } -zkm-verifier = { git = "https://github.com/ProjectZKM/Ziren", package = "zkm-verifier" } +zkm-zkvm = { git = "https://github.com/ProjectZKM/Ziren", features = ["verify"] } +zkm-verifier = { git = "https://github.com/ProjectZKM/Ziren" } #zkm-verifier = { path = "../../../Ziren/crates/verifier" } #zkm-zkvm = { path = "../../../Ziren/crates/zkvm/entrypoint", features = ["verify"] } @@ -43,6 +43,3 @@ secp256k1-v0-29-1 = { git = "https://github.com/ziren-patches/rust-secp256k1", p #secp256k1-v0-30-0 = { git = "https://github.com/ziren-patches/rust-secp256k1", package = "secp256k1", branch = "patch-0.30.0" } #bitcoin = { git = "https://github.com/ProjectZKM/rust-bitcoin", branch = "patch-0.32.7" } -[patch."https://github.com/ProjectZKM/Ziren"] -zkm-zkvm = { git = "https://github.com/blake-pro/Ziren.git", branch = "v1.2.4-imm" } -zkm-verifier = { git = "https://github.com/blake-pro/Ziren.git", branch = "v1.2.4-imm" } diff --git a/circuits/state-chain-proof/guest/Cargo.toml b/circuits/state-chain-proof/guest/Cargo.toml index 95d9433f..9e195a81 100644 --- a/circuits/state-chain-proof/guest/Cargo.toml +++ b/circuits/state-chain-proof/guest/Cargo.toml @@ -11,8 +11,8 @@ bincode = "1.3.3" state-chain = { path = "../../../crates/state-chain" } # Ziren -zkm-zkvm = { git = "https://github.com/ProjectZKM/Ziren", package = "zkm-zkvm", features = ["verify"] } -zkm-verifier = { git = "https://github.com/ProjectZKM/Ziren", package = "zkm-verifier" } +zkm-zkvm = { git = "https://github.com/ProjectZKM/Ziren", features = ["verify"] } +zkm-verifier = { git = "https://github.com/ProjectZKM/Ziren" } #zkm-verifier = { path = "../../../Ziren/crates/verifier" } #zkm-zkvm = { path = "../../../Ziren/crates/zkvm/entrypoint", features = ["verify"] } @@ -35,7 +35,3 @@ alloy-primitives-v1-1-2 = { git = "https://github.com/ziren-patches/core.git", p alloy-primitives-v1-4-1 = { git = "https://github.com/ziren-patches/core.git", package = "alloy-primitives", branch = "patch-alloy-primitives-1.4.1" } secp256k1-v0-29-1 = { git = "https://github.com/ziren-patches/rust-secp256k1", package = "secp256k1", branch = "patch-0.29.1" } #secp256k1-v0-30-0 = { git = "https://github.com/ziren-patches/rust-secp256k1", package = "secp256k1", branch = "patch-0.30.0" } - -[patch."https://github.com/ProjectZKM/Ziren"] -zkm-zkvm = { git = "https://github.com/blake-pro/Ziren.git", branch = "v1.2.4-imm" } -zkm-verifier = { git = "https://github.com/blake-pro/Ziren.git", branch = "v1.2.4-imm" } diff --git a/circuits/watchtower-proof/guest/Cargo.toml b/circuits/watchtower-proof/guest/Cargo.toml index 453203b6..fca4952e 100644 --- a/circuits/watchtower-proof/guest/Cargo.toml +++ b/circuits/watchtower-proof/guest/Cargo.toml @@ -14,8 +14,8 @@ state-chain = { path = "../../../crates/state-chain" } bitcoin-light-client-circuit = { path = "../../../crates/bitcoin-light-client-circuit" } # Ziren -zkm-zkvm = { git = "https://github.com/ProjectZKM/Ziren", package = "zkm-zkvm", features = ["verify"] } -zkm-verifier = { git = "https://github.com/ProjectZKM/Ziren", package = "zkm-verifier" } +zkm-zkvm = { git = "https://github.com/ProjectZKM/Ziren", features = ["verify"] } +zkm-verifier = { git = "https://github.com/ProjectZKM/Ziren" } #zkm-verifier = { path = "../../../Ziren/crates/verifier" } #zkm-zkvm = { path = "../../../Ziren/crates/zkvm/entrypoint", features = ["verify"] } @@ -43,6 +43,3 @@ secp256k1-v0-29-1 = { git = "https://github.com/ziren-patches/rust-secp256k1", p #secp256k1-v0-30-0 = { git = "https://github.com/ziren-patches/rust-secp256k1", package = "secp256k1", branch = "patch-0.30.0" } #bitcoin = { git = "https://github.com/ProjectZKM/rust-bitcoin", branch = "patch-0.32.7" } -[patch."https://github.com/ProjectZKM/Ziren"] -zkm-zkvm = { git = "https://github.com/blake-pro/Ziren.git", branch = "v1.2.4-imm" } -zkm-verifier = { git = "https://github.com/blake-pro/Ziren.git", branch = "v1.2.4-imm" } From bb001535ae25a784a272fbfeeda2c71f12e12762 Mon Sep 17 00:00:00 2001 From: Blake Date: Fri, 17 Apr 2026 11:31:07 +0800 Subject: [PATCH 13/14] chore: update trusted Ziren version to v1.2.5, and add CLI guide for part_stark_vk attestation --- circuits/README.md | 2 +- circuits/commit-chain-proof/host/src/lib.rs | 2 +- circuits/header-chain-proof/host/src/lib.rs | 2 +- circuits/state-chain-proof/host/src/lib.rs | 2 +- crates/commit-chain/src/lib.rs | 2 +- docs/part-stark-vk-attest-cli.md | 281 ++++++++++++++++++++ node/src/bin/part_stark_vk_attest.rs | 1 + node/src/lib.rs | 2 +- 8 files changed, 288 insertions(+), 6 deletions(-) create mode 100644 docs/part-stark-vk-attest-cli.md diff --git a/circuits/README.md b/circuits/README.md index f9afef1b..a740c67f 100644 --- a/circuits/README.md +++ b/circuits/README.md @@ -56,7 +56,7 @@ For case 2, > * If there is no Ziren upgrade during this interval, and the inputs of the proof aggregation are compressed proofs, but with different `start_pc`, `pc`, etc. > * If there is some Ziren upgrades during this interval, once we support the multiple verification keys in Ziren, this problem can be reduced to the former one. -With multiple proof recursions, we generate a Groth16 proof, and verify with `Groth16Verifier::verify(proof, zkm_public_values, zkm_vk_hash, snark_vk_meta, groth16_vk)`. +With multiple proof recursions, we generate a Groth16 proof, and verify with `Groth16Verifier::verify_by_imm_groth16_vk(proof, zkm_public_values, zkm_vk_hash, groth16_vk, part_stark_vk)`. ## Preparation diff --git a/circuits/commit-chain-proof/host/src/lib.rs b/circuits/commit-chain-proof/host/src/lib.rs index 936d059d..72963ff6 100644 --- a/circuits/commit-chain-proof/host/src/lib.rs +++ b/circuits/commit-chain-proof/host/src/lib.rs @@ -221,7 +221,7 @@ impl ProofBuilder for CommitChainProofBuilder { Vec::new(), Vec::new(), Vec::new(), - "v1.2.4".into(), + "v1.2.5".into(), ), }; diff --git a/circuits/header-chain-proof/host/src/lib.rs b/circuits/header-chain-proof/host/src/lib.rs index 01de2633..9710a5d6 100644 --- a/circuits/header-chain-proof/host/src/lib.rs +++ b/circuits/header-chain-proof/host/src/lib.rs @@ -233,7 +233,7 @@ impl ProofBuilder for HeaderChainProofBuilder { Vec::new(), Vec::new(), Vec::new(), - "v1.2.4".into(), + "v1.2.5".into(), ), }; diff --git a/circuits/state-chain-proof/host/src/lib.rs b/circuits/state-chain-proof/host/src/lib.rs index f51d5194..e908c95a 100644 --- a/circuits/state-chain-proof/host/src/lib.rs +++ b/circuits/state-chain-proof/host/src/lib.rs @@ -350,7 +350,7 @@ impl ProofBuilder for StateChainProofBuilder { Vec::new(), Vec::new(), Vec::new(), - "v1.2.4".into(), + "v1.2.5".into(), ), }; diff --git a/crates/commit-chain/src/lib.rs b/crates/commit-chain/src/lib.rs index cde097d0..bc9d5d37 100644 --- a/crates/commit-chain/src/lib.rs +++ b/crates/commit-chain/src/lib.rs @@ -4,7 +4,7 @@ mod commit_chain; pub use commit_chain::*; use zkm_verifier::{Groth16Verifier, IMM_GROTH16_VK_BYTES}; -pub const TRUSTED_COMMIT_CHAIN_ZKM_VERSION: &str = "v1.2.4"; +pub const TRUSTED_COMMIT_CHAIN_ZKM_VERSION: &str = "v1.2.5"; /// Return the fixed `part_stark_vk` used by commit-chain's internal recursive verifier. pub fn trusted_commit_chain_part_stark_vk() -> Vec { diff --git a/docs/part-stark-vk-attest-cli.md b/docs/part-stark-vk-attest-cli.md new file mode 100644 index 00000000..73cb0bf9 --- /dev/null +++ b/docs/part-stark-vk-attest-cli.md @@ -0,0 +1,281 @@ +# `part-stark-vk-attest` CLI Guide + +This document explains how to use `part-stark-vk-attest` to build the latest `part_stark_vk` attestation snapshot and add publisher signatures to that snapshot. + +## Overview + +The CLI currently provides two subcommands: + +- `build-tree` +- `sign-root` + +The workflow is fixed: + +1. Run `build-tree` first to generate the latest snapshot from the full active version set +2. Let each publisher signer run `sign-root` once +3. After the number of signatures in `manifest.json` reaches the threshold from `commit_info`, the proof side can load the attestation snapshot + +## Binary Entry + +```bash +cargo run -p bitvm2-noded --bin part-stark-vk-attest -- ... +``` + +The binary is defined in: + +- [`node/Cargo.toml`](../node/Cargo.toml) +- [`node/src/bin/part_stark_vk_attest.rs`](../node/src/bin/part_stark_vk_attest.rs) + +## Directory Model + +The attestation directory stores only one latest snapshot. Historical snapshots are not kept. + +Default output directory: + +```text +data/psv-attestations +``` + +Latest snapshot layout: + +```text +data/psv-attestations/ + manifest.json + proofs/ + v1.2.4.json + v1.2.5.json +``` + +Where: + +- `manifest.json` stores the current Merkle root, ordered versions, publisher metadata, and aggregated signatures +- `proofs/.json` stores the `part_stark_vk`, `leaf_index`, and `merkle_path` for each version + +## Version Rules + +All `--versions` inputs represent the full active version set, not incremental additions. + +The CLI will: + +1. Sort versions by semver +2. Load `part_stark_vk` for each sorted version +3. Build the Merkle tree using that sorted order + +Example: + +```text +Input: v1.2.10,v1.2.4,v1.2.5 +Sorted: v1.2.4,v1.2.5,v1.2.10 +``` + +If versions are duplicated, the command fails. + +## `build-tree` + +### Purpose + +- Build the latest Merkle tree from the full version set +- Generate Merkle proofs for every version +- Overwrite the attestation directory +- Do not write signatures + +### Command Format + +```bash +cargo run -p bitvm2-noded --bin part-stark-vk-attest -- \ + build-tree \ + --versions \ + --attestation-dir +``` + +### Parameters + +- `--versions` + Comma-separated version list +- `--attestation-dir` + Output attestation directory; defaults to `data/psv-attestations` + +### Example + +```bash +cargo run -p bitvm2-noded --bin part-stark-vk-attest -- \ + build-tree \ + --versions v1.2.4,v1.2.5 \ + --attestation-dir circuits/data/psv-attestations +``` + +### Output + +On success, the command prints output similar to: + +```text +built latest part_stark_vk snapshot in circuits/data/psv-attestations for versions v1.2.4,v1.2.5 +``` + +Note: + +- `build-tree` creates an unsigned snapshot +- Running only `build-tree` is not enough for the proof side to consume the attestation + +## `sign-root` + +### Purpose + +- Rebuild the Merkle tree from the same version set +- Load the current publisher set and threshold from `commit_info.active_publisher_set()` +- Sign the current root with a single publisher private key +- Merge the signature into the latest `manifest.json` + +### Command Format + +```bash +cargo run -p bitvm2-noded --bin part-stark-vk-attest -- \ + sign-root \ + --versions \ + --commit-info-file \ + --publisher-secret-key-wif \ + --attestation-dir +``` + +### Parameters + +- `--versions` + Full active version set; must match the snapshot being signed +- `--commit-info-file` + Path to `commit_info.json` +- `--publisher-secret-key-wif` + Bitcoin WIF private key for a single publisher signer +- `--attestation-dir` + Attestation directory; defaults to `data/psv-attestations` + +### Signer Matching Rule + +The command does not require a manual signer index. + +`--publisher-secret-key-wif` is parsed as WIF, following the same Bitcoin private key format used in `sequencer-set-publish.rs`. + +The CLI will: + +1. Derive the compressed public key from the private key +2. Read the current active publisher set from `commit_info.active_publisher_set()` +3. Find that public key inside the active publisher set +4. Use the matching position as `signer_pubkey_index` + +If the private key does not belong to the current active publisher set, the command fails. + +### Your Current `commit_info` + +If you are using: + +- [`circuits/data/commit-chain/commit_info.json.0`](../circuits/data/commit-chain/commit_info.json.0) + +Then the command looks like: + +```bash +cargo run -p bitvm2-noded --bin part-stark-vk-attest -- \ + sign-root \ + --versions v1.2.4,v1.2.5 \ + --commit-info-file circuits/data/commit-chain/commit_info.json.0 \ + --publisher-secret-key-wif \ + --attestation-dir circuits/data/psv-attestations +``` + +### Multi-Signer Aggregation + +`sign-root` handles only one signer per invocation. + +If multiple signers exist, run it once per signer: + +```bash +cargo run -p bitvm2-noded --bin part-stark-vk-attest -- \ + sign-root \ + --versions v1.2.4,v1.2.5 \ + --commit-info-file circuits/data/commit-chain/commit_info.json.0 \ + --publisher-secret-key-wif \ + --attestation-dir circuits/data/psv-attestations + +cargo run -p bitvm2-noded --bin part-stark-vk-attest -- \ + sign-root \ + --versions v1.2.4,v1.2.5 \ + --commit-info-file circuits/data/commit-chain/commit_info.json.0 \ + --publisher-secret-key-wif \ + --attestation-dir circuits/data/psv-attestations + +cargo run -p bitvm2-noded --bin part-stark-vk-attest -- \ + sign-root \ + --versions v1.2.4,v1.2.5 \ + --commit-info-file circuits/data/commit-chain/commit_info.json.0 \ + --publisher-secret-key-wif \ + --attestation-dir circuits/data/psv-attestations +``` + +Signatures are aggregated into the same `manifest.json`. + +## Signature Invalidation Rules + +Existing signatures are cleared if any of the following changes: + +- Version list changes +- Version ordering changes +- Any resolved `part_stark_vk` bytes change +- `root` changes +- `publisher_set_id` changes + +Notes: + +- `publisher_set_id` already includes `threshold` +- A threshold change therefore appears as a `publisher_set_id` change + +## How the Proof Side Uses It + +The proof side accepts only the latest snapshot format. + +Requirements: + +- `manifest.json` must exist in the attestation directory +- Matching `proofs/.json` files must exist +- `manifest.json` must already contain enough valid signatures + +If the directory contains only the old `bundles/` files and no `manifest.json`, the proof side fails immediately. + +## Recommended Procedure + +### Step 1: Build the Latest Snapshot + +```bash +cargo run -p bitvm2-noded --bin part-stark-vk-attest -- \ + build-tree \ + --versions v1.2.4,v1.2.5 \ + --attestation-dir circuits/data/psv-attestations +``` + +### Step 2: Let Each Signer Add One Signature + +```bash +cargo run -p bitvm2-noded --bin part-stark-vk-attest -- \ + sign-root \ + --versions v1.2.4,v1.2.5 \ + --commit-info-file circuits/data/commit-chain/commit_info.json.0 \ + --publisher-secret-key-wif \ + --attestation-dir circuits/data/psv-attestations +``` + +Repeat until the number of signatures reaches the threshold from `commit_info`. + +## Common Errors + +- `versions is empty` + No version list was provided +- `duplicate version '...'` + Duplicate version after normalization +- `failed to load part_stark_vk for version '...'` + The local verifier cannot resolve that version +- `publisher_secret_key_wif does not belong to active publisher set` + The provided WIF key does not belong to the current active publisher set +- `missing latest attestation manifest '.../manifest.json'` + The proof side is loading an attestation directory without a latest snapshot + +## Relevant Implementation Files + +- [`node/src/bin/part_stark_vk_attest.rs`](../node/src/bin/part_stark_vk_attest.rs) +- [`crates/bitcoin-light-client-circuit/src/attestation.rs`](../crates/bitcoin-light-client-circuit/src/attestation.rs) diff --git a/node/src/bin/part_stark_vk_attest.rs b/node/src/bin/part_stark_vk_attest.rs index 46d83df1..411fec7e 100644 --- a/node/src/bin/part_stark_vk_attest.rs +++ b/node/src/bin/part_stark_vk_attest.rs @@ -192,6 +192,7 @@ fn main() -> Result<()> { #[cfg(test)] mod tests { use super::*; + use bitcoin::Network; use bitcoin::secp256k1::Secp256k1; #[test] diff --git a/node/src/lib.rs b/node/src/lib.rs index 4897ef59..9ecafd89 100644 --- a/node/src/lib.rs +++ b/node/src/lib.rs @@ -177,7 +177,7 @@ mod dbg { .get_mut("parameters") .and_then(serde_json::Value::as_object_mut) .unwrap() - .insert("zkm_version".to_string(), serde_json::Value::String("v1.2.4".to_string())); + .insert("zkm_version".to_string(), serde_json::Value::String("v1.2.5".to_string())); let decoded: SimplifiedBitvm2Graph = serde_json::from_value(value).unwrap(); assert_eq!(decoded.parameters.graph_id, graph.parameters.graph_id); From 61247484374e562e677d387a8861f7913e4e33c1 Mon Sep 17 00:00:00 2001 From: Blake Date: Fri, 17 Apr 2026 13:38:35 +0800 Subject: [PATCH 14/14] fix clippy --- crates/bitcoin-light-client-circuit/src/attestation.rs | 3 +-- crates/bitcoin-light-client-circuit/src/lib.rs | 3 ++- node/src/utils.rs | 8 ++++---- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/crates/bitcoin-light-client-circuit/src/attestation.rs b/crates/bitcoin-light-client-circuit/src/attestation.rs index 3b3c6c97..dd4b166b 100644 --- a/crates/bitcoin-light-client-circuit/src/attestation.rs +++ b/crates/bitcoin-light-client-circuit/src/attestation.rs @@ -215,7 +215,7 @@ pub fn verify_part_stark_vk_merkle_path( let mut node = part_stark_vk_leaf_hash(part_stark_vk); let mut index = leaf_index; for sibling in merkle_path { - node = if index % 2 == 0 { + node = if index.is_multiple_of(2) { part_stark_vk_internal_hash(node, *sibling) } else { part_stark_vk_internal_hash(*sibling, node) @@ -961,7 +961,6 @@ fn load_unique_part_stark_vk_witnesses_from_latest_snapshot( #[cfg(test)] mod tests { use bitcoin::secp256k1::{Message, Secp256k1, SecretKey, ecdsa::Signature}; - use sha2::{Digest, Sha256}; use std::time::{SystemTime, UNIX_EPOCH}; use super::{ diff --git a/crates/bitcoin-light-client-circuit/src/lib.rs b/crates/bitcoin-light-client-circuit/src/lib.rs index 4c397469..bd3560d3 100644 --- a/crates/bitcoin-light-client-circuit/src/lib.rs +++ b/crates/bitcoin-light-client-circuit/src/lib.rs @@ -591,6 +591,7 @@ fn attested_part_stark_vk_for_zkm_version( } /// Verify one included watchtower challenge end-to-end and return its parsed public outputs. +#[allow(clippy::too_many_arguments)] fn verify_included_watchtower_challenge( index: usize, graph_id: &[u8; GRAPH_ID_SIZE], @@ -612,7 +613,7 @@ fn verify_included_watchtower_challenge( .iter() .next() .ok_or_else(|| "watchtower tx witness must contain a taproot signature".to_string())?; - let sig = bitcoin::taproot::Signature::from_slice(witness.as_ref()) + let sig = bitcoin::taproot::Signature::from_slice(witness) .map_err(|err| format!("invalid taproot signature: {err}"))?; let prev_index = input.previous_output.vout as usize; verify_taproot_leaf_schnorr_signature(script, tx, prev_index, prev_out, pubkey, &sig) diff --git a/node/src/utils.rs b/node/src/utils.rs index b198d3ac..33dd76eb 100644 --- a/node/src/utils.rs +++ b/node/src/utils.rs @@ -1752,22 +1752,22 @@ pub async fn broadcast_package( fn gen_watchtower_commitment(graph_id: Uuid, proof_data: ProofData) -> Result> { let graph_id = graph_id.as_bytes(); - let proof = - proof_data.proof.as_slice().try_into().map_err(|_| anyhow!("invalid proof length"))?; + let proof = proof_data.proof.as_slice(); if proof_data.vk.len() != VK_HASH_SIZE { bail!("invalid vk_hash length"); } if proof_data.proof_part_stark_vk.is_empty() { bail!("missing proof_part_stark_vk"); } - Ok(build_watchtower_commitment( + + build_watchtower_commitment( graph_id, proof, &proof_data.public_inputs, &proof_data.vk, &proof_data.proof_part_stark_vk, ) - .map_err(|e| anyhow!("failed to build watchtower commitment: {e}"))?) + .map_err(|e| anyhow!("failed to build watchtower commitment: {e}")) } fn load_part_stark_vk_for_zkm_version(zkm_version: &str) -> Result> {