diff --git a/Cargo.lock b/Cargo.lock index df4b113a..cf80dfb6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6029,6 +6029,7 @@ dependencies = [ "serde", "sha2 0.10.9", "verifier", + "zkm-primitives", "zkm-zkvm", ] @@ -12476,6 +12477,7 @@ dependencies = [ "tendermint-light-client-verifier", "tracing", "verifier", + "zkm-primitives", "zkm-zkvm", ] diff --git a/circuits/commit-chain-proof/host/src/lib.rs b/circuits/commit-chain-proof/host/src/lib.rs index 400281e8..57b6ce79 100644 --- a/circuits/commit-chain-proof/host/src/lib.rs +++ b/circuits/commit-chain-proof/host/src/lib.rs @@ -205,9 +205,8 @@ impl ProofBuilder for CommitChainProofBuilder { format!("invalid UTF-8 in zkm_version file '{version_path}'") }) })?; - let prev_output = decode_commit_chain_circuit_output(&public_inputs); ( - CommitChainPrevProofType::PrevProof(prev_output), + CommitChainPrevProofType::PrevProof, proof_bytes, public_inputs, zkm_vk_hash.to_vec(), @@ -263,10 +262,9 @@ impl ProofBuilder for CommitChainProofBuilder { tracing::info!("Commit chain proof cycles: {}", cycles); - // todo: verify the proof laterr - // if let Err(e) = self.client.verify(&proof, &self.verifying_key) { - // panic!("{}", e); - // } + self.client + .verify(&proof, &self.verifying_key) + .context("Failed to verify generated commit chain proof")?; let input = bincode::serialize(&input)?; Ok((input, proof, cycles, proving_time)) diff --git a/circuits/header-chain-proof/guest/Cargo.lock b/circuits/header-chain-proof/guest/Cargo.lock index cd02d292..a0cec3ae 100644 --- a/circuits/header-chain-proof/guest/Cargo.lock +++ b/circuits/header-chain-proof/guest/Cargo.lock @@ -1117,6 +1117,7 @@ dependencies = [ "serde", "sha2", "verifier", + "zkm-primitives", "zkm-zkvm", ] diff --git a/circuits/header-chain-proof/host/src/lib.rs b/circuits/header-chain-proof/host/src/lib.rs index 9710a5d6..82141fbe 100644 --- a/circuits/header-chain-proof/host/src/lib.rs +++ b/circuits/header-chain-proof/host/src/lib.rs @@ -219,9 +219,8 @@ impl ProofBuilder for HeaderChainProofBuilder { format!("invalid UTF-8 in zkm_version file '{version_path}'") }) })?; - let prev_output = zkm_sdk::ZKMPublicValues::from(&public_inputs).read(); ( - HeaderChainPrevProofType::PrevProof(prev_output), + HeaderChainPrevProofType::PrevProof, proof_bytes, public_inputs, zkm_vk_hash.to_vec(), @@ -282,9 +281,9 @@ impl ProofBuilder for HeaderChainProofBuilder { tracing::info!("Header chain proof cycles: {}", cycles); - if let Err(e) = self.client.verify(&proof, &self.verifying_key) { - panic!("{}", e); - } + self.client + .verify(&proof, &self.verifying_key) + .context("Failed to verify generated header chain proof")?; let input = bincode::serialize(&input)?; Ok((input, proof, cycles, proving_time)) diff --git a/circuits/operator-proof/guest/Cargo.lock b/circuits/operator-proof/guest/Cargo.lock index 91821b9a..ff3314ba 100644 --- a/circuits/operator-proof/guest/Cargo.lock +++ b/circuits/operator-proof/guest/Cargo.lock @@ -2434,6 +2434,7 @@ dependencies = [ "serde", "sha2 0.10.9", "verifier", + "zkm-primitives", "zkm-zkvm", ] @@ -5186,6 +5187,7 @@ dependencies = [ "tendermint-light-client-verifier", "tracing", "verifier", + "zkm-primitives", "zkm-zkvm", ] diff --git a/circuits/state-chain-proof/guest/Cargo.lock b/circuits/state-chain-proof/guest/Cargo.lock index 22665830..1f374068 100644 --- a/circuits/state-chain-proof/guest/Cargo.lock +++ b/circuits/state-chain-proof/guest/Cargo.lock @@ -2383,6 +2383,7 @@ dependencies = [ "serde", "sha2 0.10.9", "verifier", + "zkm-primitives", "zkm-zkvm", ] @@ -5135,6 +5136,7 @@ dependencies = [ "tendermint-light-client-verifier", "tracing", "verifier", + "zkm-primitives", "zkm-zkvm", ] diff --git a/circuits/state-chain-proof/host/src/lib.rs b/circuits/state-chain-proof/host/src/lib.rs index e908c95a..9c48a869 100644 --- a/circuits/state-chain-proof/host/src/lib.rs +++ b/circuits/state-chain-proof/host/src/lib.rs @@ -335,10 +335,8 @@ impl ProofBuilder for StateChainProofBuilder { format!("invalid UTF-8 in zkm_version file '{version_path}'") }) })?; - let prev_output: StateChainCircuitOutput = - zkm_sdk::ZKMPublicValues::from(&public_inputs).read(); ( - StateChainPrevProofType::PrevProof(prev_output), + StateChainPrevProofType::PrevProof, proof_bytes, public_inputs, zkm_vk_hash.to_vec(), @@ -389,9 +387,10 @@ impl ProofBuilder for StateChainProofBuilder { }, )?; tracing::info!("State chain proof cycles: {}", cycles); - if let Err(e) = self.client.verify(&proof, &self.verifying_key) { - panic!("{}", e); - } + + self.client + .verify(&proof, &self.verifying_key) + .context("Failed to verify generated state chain proof")?; let input = bincode::serialize(&input)?; Ok((input, proof, cycles, proving_time)) diff --git a/circuits/watchtower-proof/guest/Cargo.lock b/circuits/watchtower-proof/guest/Cargo.lock index 0dd35c97..b889d471 100644 --- a/circuits/watchtower-proof/guest/Cargo.lock +++ b/circuits/watchtower-proof/guest/Cargo.lock @@ -2434,6 +2434,7 @@ dependencies = [ "serde", "sha2 0.10.9", "verifier", + "zkm-primitives", "zkm-zkvm", ] @@ -5186,6 +5187,7 @@ dependencies = [ "tendermint-light-client-verifier", "tracing", "verifier", + "zkm-primitives", "zkm-zkvm", ] diff --git a/circuits/watchtower-proof/guest/src/main.rs b/circuits/watchtower-proof/guest/src/main.rs index 2a5431b7..8862f750 100644 --- a/circuits/watchtower-proof/guest/src/main.rs +++ b/circuits/watchtower-proof/guest/src/main.rs @@ -8,7 +8,6 @@ use state_chain::StateChainCircuitInput; pub fn main() { let genesis_sequencer_commit_txid = zkm_zkvm::io::read::<[u8; 32]>(); - let latest_sequencer_commit_txid = zkm_zkvm::io::read::<[u8; 32]>(); 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(); @@ -16,7 +15,6 @@ pub fn main() { let (total_work, btc_best_block_height) = bitcoin_light_client_circuit::watch_longest_chain( genesis_sequencer_commit_txid, - latest_sequencer_commit_txid, header_chain, commit_chain, state_chain, diff --git a/circuits/watchtower-proof/host/src/lib.rs b/circuits/watchtower-proof/host/src/lib.rs index d7aa2ccc..f82abfe3 100644 --- a/circuits/watchtower-proof/host/src/lib.rs +++ b/circuits/watchtower-proof/host/src/lib.rs @@ -121,7 +121,6 @@ impl ProofBuilder for WatchtowerProofBuilder { header_chain_input_proof, commit_chain_input_proof, state_chain_input_proof, - latest_sequencer_commit_txid, genesis_sequencer_commit_txid, target_block, block_pos, @@ -215,7 +214,6 @@ impl ProofBuilder for WatchtowerProofBuilder { }; // --- spv --- // let genesis_sequencer_commit_txid = Txid::from_str(&genesis_sequencer_commit_txid)?; - let latest_sequencer_commit_txid = Txid::from_str(&latest_sequencer_commit_txid)?; let bitcoin_block_headers = { let headers: Vec = std::fs::read(&format!("{header_chain_input_proof}.blocks"))?; headers @@ -247,7 +245,6 @@ impl ProofBuilder for WatchtowerProofBuilder { || -> anyhow::Result<(ZKMProofWithPublicValues, u64, f32)> { let mut stdin = ZKMStdin::new(); stdin.write(&genesis_sequencer_commit_txid.to_byte_array()); - stdin.write(&latest_sequencer_commit_txid.to_byte_array()); stdin.write(&header_chain_input); stdin.write(&commit_chain_input); stdin.write(&state_chain_input); diff --git a/crates/bitcoin-light-client-circuit/src/lib.rs b/crates/bitcoin-light-client-circuit/src/lib.rs index 9cb38b9f..8dc6b808 100644 --- a/crates/bitcoin-light-client-circuit/src/lib.rs +++ b/crates/bitcoin-light-client-circuit/src/lib.rs @@ -2,25 +2,24 @@ mod signature; mod utils; use alloy_primitives::U32; pub use signature::*; -use state_chain::verify_sequencer_commit; pub use utils::*; use alloy_primitives::U256; use bitcoin::Block; use bitcoin::hashes::{Hash, HashEngine, sha256}; use commit_chain::{ - CommitChainCircuitInput, CommitChainPrevProofType, decode_commit_chain_circuit_output, + CommitChainCircuitInput, decode_commit_chain_circuit_output, extract_data_from_commitment_outputs, parse_commit_chain_commitment, sequencer_hash, }; use header_chain::{ - BitcoinMerkleTree, CircuitBlockHeader, CircuitTransaction, HeaderChainCircuitInput, - HeaderChainPrevProofType, MMRHost, SPV, verify_merkle_proof, + BitcoinMerkleTree, BlockHeaderCircuitOutput, CircuitBlockHeader, CircuitTransaction, + HeaderChainCircuitInput, MMRHost, SPV, verify_merkle_proof, }; -use state_chain::{StateChainCircuitInput, StateChainPrevProofType}; +use state_chain::{StateChainCircuitInput, StateChainCircuitOutput, verify_sequencer_commit}; use zkm_primitives::io::ZKMPublicValues; use bitcoin::{ - ScriptBuf, Transaction, TxOut, Txid, + ScriptBuf, Transaction, TxOut, secp256k1::{PublicKey, XOnlyPublicKey}, }; pub use guest_executor::io::EthClientExecutorInput; @@ -64,7 +63,6 @@ pub fn decode_operator_public_outputs( 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, @@ -83,15 +81,10 @@ pub fn watch_longest_chain( ) .expect("Failed to verify commit chain proof"); - let prev_output = decode_commit_chain_circuit_output(&commit_chain.zkm_public_values); - 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"); - }; - + let commit_chain_output = decode_commit_chain_circuit_output(&commit_chain.zkm_public_values); assert_eq!( commit_chain_output.chain_state.commit_txn.compute_txid(), - Txid::from_byte_array(latest_sequencer_commit_txid) + spv.transaction.0.compute_txid() ); assert_eq!(genesis_sequencer_commit_txid, commit_chain_output.chain_state.genesis_txid); @@ -105,11 +98,8 @@ pub fn watch_longest_chain( ) .expect("Failed to verify header chain proof"); - let prev_output = ZKMPublicValues::from(&header_chain.zkm_public_values).read(); - let prev_proof = HeaderChainPrevProofType::PrevProof(prev_output); - let HeaderChainPrevProofType::PrevProof(btc_header_chain_output) = &prev_proof else { - panic!("Only PrevProof is supported in watch_longest_chain"); - }; + let btc_header_chain_output: BlockHeaderCircuitOutput = + ZKMPublicValues::from(&header_chain.zkm_public_values).read(); // verify that the latest_sequecner_commit_tx is in the header chain println!("SPV"); assert!(spv.verify(&btc_header_chain_output.chain_state.block_hashes_mmr)); @@ -121,11 +111,8 @@ pub fn watch_longest_chain( &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 { - panic!("Only PrevProof is supported in watch_longest_chain"); - }; + let state_chain_output: StateChainCircuitOutput = + ZKMPublicValues::from(&state_chain.zkm_public_values).read(); // check the signature. let cosmos_block_bytes = &state_chain_output.chain_state.latest_cosmos_block; let cosmos_block: LightBlock = @@ -255,11 +242,7 @@ pub fn propose_longest_chain( &commit_chain.zkm_version, ) .expect("Failed to verify commit chain proof"); - let prev_output = decode_commit_chain_circuit_output(&commit_chain.zkm_public_values); - 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"); - }; + let commit_chain_output = decode_commit_chain_circuit_output(&commit_chain.zkm_public_values); assert_eq!( commit_chain_output.chain_state.commit_txn.compute_txid(), spv_ss_commit.transaction.0.compute_txid() @@ -278,11 +261,8 @@ pub fn propose_longest_chain( &operator_header_chain.zkm_version, ) .expect("Failed to verify header chain proof"); - let prev_output = ZKMPublicValues::from(&operator_header_chain.zkm_public_values).read(); - let prev_proof = HeaderChainPrevProofType::PrevProof(prev_output); - let HeaderChainPrevProofType::PrevProof(btc_header_chain_output) = &prev_proof else { - panic!("Only PrevProof is supported in propose_longest_chain"); - }; + let btc_header_chain_output: BlockHeaderCircuitOutput = + ZKMPublicValues::from(&operator_header_chain.zkm_public_values).read(); 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 @@ -429,11 +409,9 @@ pub fn propose_longest_chain( ) .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 { - panic!("Only PrevProof is supported in propose_longest_chain"); - }; + let state_chain_output: StateChainCircuitOutput = + ZKMPublicValues::from(&state_chain.zkm_public_values).read(); + // check the signature. let cosmos_block_bytes = &state_chain_output.chain_state.latest_cosmos_block; let cosmos_block: LightBlock = diff --git a/crates/commit-chain/src/commit_chain.rs b/crates/commit-chain/src/commit_chain.rs index bb51246e..30428d51 100644 --- a/crates/commit-chain/src/commit_chain.rs +++ b/crates/commit-chain/src/commit_chain.rs @@ -29,7 +29,7 @@ pub struct CommitInfo { #[derive(Serialize, Deserialize, PartialEq, Clone, Debug)] pub enum CommitChainPrevProofType { GenesisBlock, - PrevProof(CommitChainCircuitOutput), + PrevProof, } #[derive(Serialize, Deserialize, PartialEq, Clone, Debug)] diff --git a/crates/commit-chain/src/lib.rs b/crates/commit-chain/src/lib.rs index bee13b09..e1736912 100644 --- a/crates/commit-chain/src/lib.rs +++ b/crates/commit-chain/src/lib.rs @@ -8,7 +8,7 @@ pub fn commit_chain_circuit(input: CommitChainCircuitInput) -> CommitChainCircui CommitChainPrevProofType::GenesisBlock => { CommitChainState::new(input.commits[0].genesis_txid) } - CommitChainPrevProofType::PrevProof(prev_proof) => { + CommitChainPrevProofType::PrevProof => { println!("verify commit chain of prev proof"); verifier::verify_groth16_proof( &input.zkm_proof, @@ -18,8 +18,7 @@ pub fn commit_chain_circuit(input: CommitChainCircuitInput) -> CommitChainCircui ) .unwrap(); - // todo: read from input.zkm_public_values - prev_proof.chain_state + decode_commit_chain_circuit_output(&input.zkm_public_values).chain_state } }; diff --git a/crates/header-chain/Cargo.toml b/crates/header-chain/Cargo.toml index d395bb17..12f18cec 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 = { workspace = true } verifier = { workspace = true } +zkm-primitives = { 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 9bfd2a68..ab7667b1 100644 --- a/crates/header-chain/src/header_chain.rs +++ b/crates/header-chain/src/header_chain.rs @@ -370,7 +370,7 @@ pub struct BlockHeaderCircuitOutput { #[derive(Serialize, Deserialize, Eq, PartialEq, Clone, Debug, BorshDeserialize, BorshSerialize)] pub enum HeaderChainPrevProofType { GenesisBlock, - PrevProof(BlockHeaderCircuitOutput), + PrevProof, } /// The input of the header chain circuit. diff --git a/crates/header-chain/src/lib.rs b/crates/header-chain/src/lib.rs index 0617922f..142335f0 100644 --- a/crates/header-chain/src/lib.rs +++ b/crates/header-chain/src/lib.rs @@ -10,6 +10,8 @@ pub use merkle_tree::*; pub use mmr::*; pub use transaction::*; +use zkm_primitives::io::ZKMPublicValues; + pub mod spv; pub use spv::SPV; @@ -19,7 +21,7 @@ pub fn header_chain_circuit(input: HeaderChainCircuitInput) -> BlockHeaderCircui // println!("NETWORK_CONSTANTS: {:?}", NETWORK_CONSTANTS); let mut chain_state = match input.prev_proof { HeaderChainPrevProofType::GenesisBlock => ChainState::new(), - HeaderChainPrevProofType::PrevProof(prev_proof) => { + HeaderChainPrevProofType::PrevProof => { println!("verify header chain of prev proof"); verifier::verify_groth16_proof( &input.zkm_proof, @@ -29,7 +31,9 @@ pub fn header_chain_circuit(input: HeaderChainCircuitInput) -> BlockHeaderCircui ) .unwrap(); - prev_proof.chain_state + let btc_header_chain_output: BlockHeaderCircuitOutput = + ZKMPublicValues::from(&input.zkm_public_values).read(); + btc_header_chain_output.chain_state } }; diff --git a/crates/state-chain/Cargo.toml b/crates/state-chain/Cargo.toml index 8e98a570..d810a532 100644 --- a/crates/state-chain/Cargo.toml +++ b/crates/state-chain/Cargo.toml @@ -15,6 +15,7 @@ header-chain = { path = "../header-chain" } # Ziren verifier = { workspace = true } zkm-zkvm = { workspace = true } +zkm-primitives = { workspace = true } #zkm-verifier = { path = "../../../Ziren/crates/verifier" } #zkm-zkvm = { path = "../../../Ziren/crates/zkvm/entrypoint", features = ["verify"] } diff --git a/crates/state-chain/src/lib.rs b/crates/state-chain/src/lib.rs index 0fe26513..1a55b0b7 100644 --- a/crates/state-chain/src/lib.rs +++ b/crates/state-chain/src/lib.rs @@ -4,6 +4,8 @@ mod state_chain; pub use cbft::*; pub use state_chain::*; +use zkm_primitives::io::ZKMPublicValues; + pub fn state_chain_circuit(input: StateChainCircuitInput) -> StateChainCircuitOutput { let mut chain_state = match input.prev_proof { StateChainPrevProofType::GenesisBlock => { @@ -12,7 +14,7 @@ pub fn state_chain_circuit(input: StateChainCircuitInput) -> StateChainCircuitOu let cosmos_block = input.blocks[0].cosmos_block.clone(); StateChainState::new(block_height, block_hash, cosmos_block) } - StateChainPrevProofType::PrevProof(prev_proof) => { + StateChainPrevProofType::PrevProof => { println!("verify state chain of prev proof"); verifier::verify_groth16_proof( &input.zkm_proof, @@ -22,7 +24,9 @@ pub fn state_chain_circuit(input: StateChainCircuitInput) -> StateChainCircuitOu ) .unwrap(); - prev_proof.chain_state + let state_chain_output: StateChainCircuitOutput = + ZKMPublicValues::from(&input.zkm_public_values).read(); + state_chain_output.chain_state } }; diff --git a/crates/state-chain/src/state_chain.rs b/crates/state-chain/src/state_chain.rs index 473db11e..3c9f3fe3 100644 --- a/crates/state-chain/src/state_chain.rs +++ b/crates/state-chain/src/state_chain.rs @@ -16,7 +16,7 @@ type WithdrawalSlot = (Address, [u8; 32], Vec<[u8; 16]>); #[derive(Serialize, Deserialize, PartialEq, Clone, Debug)] pub enum StateChainPrevProofType { GenesisBlock, - PrevProof(StateChainCircuitOutput), + PrevProof, } #[derive(Serialize, Deserialize, PartialEq, Clone, Debug)] diff --git a/node/src/vk.rs b/node/src/vk.rs index 5e5667ce..bac06124 100644 --- a/node/src/vk.rs +++ b/node/src/vk.rs @@ -1,10 +1,10 @@ #![allow(dead_code)] -use anyhow::Result; +use anyhow::{Result, ensure}; use std::fs; use std::path::PathBuf; use zkm_sdk::install::CIRCUIT_ARTIFACTS_URL_BASE; -use zkm_verifier::load_ark_groth16_verifying_key_from_bytes; +use zkm_verifier::{IMM_GROTH16_VK_BYTES, load_ark_groth16_verifying_key_from_bytes}; use { futures::StreamExt, @@ -31,6 +31,12 @@ 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)?; + ensure!( + content.as_slice() == *IMM_GROTH16_VK_BYTES, + "Groth16 verifying key at {} does not match embedded IMM Groth16 verifying key", + vk_file.display() + ); + Ok(load_ark_groth16_verifying_key_from_bytes(&content)?) }