Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 13 additions & 13 deletions circuits/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -221,23 +221,23 @@ After calling the [`proceedWithdraw`](https://github.com/GOATNetwork/bitvm2-L2-c

```
export BITCOIN_NETWORK=regtest
export GENESIS_SEQUENCER_COMMIT_TXID=$(cat ./data/commit-chain/commit_info.json.0 | jq -r .genesis_txid)
export DIR="/home/ubuntu/data/proof-builder-rpc/circuits"
export GENESIS_SEQUENCER_COMMIT_TXID=$(cat ${DIR}/data/commit-chain/commit_info.json.0 | jq -r .genesis_txid)

export LATEST_SEQUENCER_COMMIT_TXID=$(cat ./data/commit-chain/commit_info.json.2 | jq -r .txid)
export OPERATOR_BLOCKHASH_COMMIT_TXID=$(cat ./data/commit-chain/commit_info.json.2 | jq -r .txid)
export LATEST_SEQUENCER_COMMIT_TXID=$(cat ${DIR}/data/commit-chain/commit_info.json.11 | jq -r .txid)
export OPERATOR_COMMITTED_BLOCKHASH =$(cat ${DIR}/data/commit-chain/commit_info.json.11 | jq -r .txid)

export HEADER_CHAIN_INPUT_PROOF="data/header-chain/0-116000.bin"
export COMMIT_CHAIN_INPUT_PROOF="data/commit-chain/2-1.bin"
export STATE_CHAIN_INPUT_PROOF="data/state-chain/9511050-10.bin"
export LATEST_STATE_BLOCK_HASH="0x7908184bce067fa5a4508d309cbaf22dd1e0b586ad2dd42c0e51a5308a7bd815"
export HEADER_CHAIN_INPUT_PROOF="$DIR/data/header-chain/1024-1.bin"
export COMMIT_CHAIN_INPUT_PROOF="$DIR/data/commit-chain/11-1.bin"
export STATE_CHAIN_INPUT_PROOF="$DIR/data/state-chain/10558271-40.bin"

export GRAPH_ID="0x00112233445566778899aabbccddeeff"
export EXECUTION_LAYER_BLOCK_NUMBER=9511055
export GRAPH_ID="3C2917B82FE14EF7B8CC8BEF3ECD700F"
export EXECUTION_LAYER_BLOCK_NUMBER=10558309

export INCLUDED_WATCHTOWERS=1
export WATCHTOWER_PUBLIC_KEYS="0272efe7ccae21d2541ad85d4f2961f2e5593c29dc8bc37bf87035fc2d5527a651"
export WATCHTOWER_CHALLENGE_TXIDS="3b155884a7f6dd65836045779c6cb5e0ebe11d4630f825fb45682b8cef1c79f0"
export WATCHTOWER_CHALLENGE_INIT_TXID="7f7b4344adb1b8937ddb7124e4f8bba80ee9adf5e8119de76ca8736816bda246"
export INCLUDED_WATCHTOWERS=0
export WATCHTOWER_PUBLIC_KEYS="02e7a08db9093c279535bd0078582469b82bf9f12c6dcb7588e187d2b9cc724279,02f6dce5d37a801064bdf42759dba98afccc80440c32cdc3a8d85c0ed9ae2e749b"
export WATCHTOWER_CHALLENGE_TXIDS="6247824c7c96c4701ef52163316d938412b15cf15962622b3c63f3cf41193f96,fe96c90162c369f45ae4f08140c6197a15c5f3cfe23f04be60f18802e97f4f91"
export WATCHTOWER_CHALLENGE_INIT_TXID="e7723e03ac97172cf033e40d4b9d9c0e22efa7a41eb855a1576f467684a0f6b3"

RUST_LOG=info cargo run --package operator-proof --bin operator-proof -r -- --output "data/operator-proof/output.bin"
```
Expand Down
73 changes: 35 additions & 38 deletions circuits/commit-chain-proof/host/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,51 +79,48 @@ pub async fn fetch_commit_chain(
esplora_url: &str,
commit_info_file: &str,
commits_file: &str,
start: usize,
batch_size: usize,
network: Network,
) -> anyhow::Result<Vec<CircuitCommit>> {
let btc_client = BTCClient::new(network, Some(&esplora_url));

let rdr = std::fs::File::open(commit_info_file).context("read error")?;
tracing::info!(
"Fetching commit chain, commit_info_file: {}, commits_file: {}",
commit_info_file,
commits_file
);
let rdr = std::fs::File::open(commit_info_file).context(&("read error"))?;
let ci: CommitInfo = serde_json::from_reader(rdr)?;
// NOTE: we support one commit-info per commit file currently
assert_eq!(batch_size, 1);

let mut commits: Vec<CircuitCommit> = vec![];
for _i in start..start + batch_size {
let txid = Txid::from_str(&ci.txid)?;
println!("network: {:?}, txid: {txid:?}", btc_client.network());
let commit_txn = btc_client.get_tx(&txid).await?.unwrap();
let proof = btc_client.get_merkle_proof_extend(&txid).await?;
let block_height = proof.height as u32;

let op_return_data = extract_op_return_data(&commit_txn.output);
let mut sequencer_set_hash: [u8; 32] = [0u8; 32];
sequencer_set_hash.copy_from_slice(&op_return_data[0..32]);

if let tendermint::Hash::Sha256(expected_hash) = sequencer_hash(&ci.sequencers) {
assert_eq!(expected_hash, sequencer_set_hash);
} else {
panic!("Invalid sequencer set hash");
}

let publisher_public_keys = ci
.publisher_public_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,
genesis_txid: Txid::from_str(&ci.genesis_txid)?.as_raw_hash().to_byte_array(),
block_height,
};
commits.push(commit);
let txid = Txid::from_str(&ci.txid)?;
let commit_txn = btc_client.get_tx_status(&txid).await?;
let block_height = commit_txn.block_height.unwrap();
let commit_txn = btc_client.get_tx(&txid).await?.unwrap();

let op_return_data = extract_op_return_data(&commit_txn.output);
let mut sequencer_set_hash: [u8; 32] = [0u8; 32];
sequencer_set_hash.copy_from_slice(&op_return_data[0..32]);

if let tendermint::Hash::Sha256(expected_hash) = sequencer_hash(&ci.sequencers) {
assert_eq!(expected_hash, sequencer_set_hash);
} else {
panic!("Invalid sequencer set hash");
}

let publisher_public_keys = ci
.publisher_public_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,
genesis_txid: Txid::from_str(&ci.genesis_txid)?.as_raw_hash().to_byte_array(),
block_height,
};
commits.push(commit);
std::fs::write(&commits_file, serde_json::to_vec(&commits)?)
.expect(&format!("write {commits_file} error"));
Ok(commits)
Expand Down
2 changes: 0 additions & 2 deletions circuits/commit-chain-proof/host/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,6 @@ async fn main() {
&args.esplora_url,
&args.commit_info,
&args.commits,
args.start,
args.batch_size,
args.bitcoin_network,
)
.await
Expand Down
4 changes: 2 additions & 2 deletions circuits/operator-proof/guest/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ pub fn main() {
let operator_commit_chain: CommitChainCircuitInput = zkm_zkvm::io::read();
let operator_state_chain: StateChainCircuitInput = zkm_zkvm::io::read();
let spv_ss_commit: SPV = zkm_zkvm::io::read();
let spv_operator_blockhash: 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(
included_watchertowers,
Expand All @@ -42,7 +42,7 @@ pub fn main() {
operator_commit_chain,
operator_state_chain,
spv_ss_commit,
spv_operator_blockhash,
operator_committed_blockhash,
);

zkm_zkvm::io::commit(&btc_best_block_hash);
Expand Down
59 changes: 28 additions & 31 deletions circuits/operator-proof/host/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
use alloy_primitives::U256;
use anyhow::Context;
use bitcoin::{
Network, ScriptBuf, Transaction, TxOut, Txid,
BlockHash, Network, ScriptBuf, Transaction, TxOut, Txid,
hashes::Hash,
secp256k1::{PublicKey, XOnlyPublicKey},
};
Expand All @@ -15,6 +15,7 @@ use header_chain::{CircuitBlockHeader, HeaderChainCircuitInput, HeaderChainPrevP
use proof_builder::{LongRunning, ProofBuilder, ProofRequest};
use state_chain::{StateChainCircuitInput, StateChainPrevProofType};
use std::str::FromStr;
use util::get_btc_block_confirms;
use zkm_sdk::{
HashableKey, Prover, ProverClient, ZKMProofKind, ZKMProofWithPublicValues, ZKMStdin,
include_elf,
Expand Down Expand Up @@ -43,7 +44,7 @@ pub struct Args {
pub latest_sequencer_commit_txid: String,

#[clap(long, env)]
pub operator_blockhash_commit_txid: String,
pub operator_committed_blockhash: String,

#[clap(long, env)]
pub genesis_sequencer_commit_txid: String,
Expand Down Expand Up @@ -91,17 +92,15 @@ static ELF_ID: OnceLock<String> = OnceLock::new();
pub async fn fetch_target_block_and_watchtower_tx(
esplora_url: &str,
latest_sequencer_commit_txid: &str,
operator_blockhash_commit_txid: &str,
operator_committed_blockhash: &str,
watchtower_challenge_init_txid: &String,
watchtower_challenge_txids: &str,
watchtower_public_keys: &str,
bitcoin_network: Network,
) -> anyhow::Result<(
u32,
bitcoin::Block,
u32,
bitcoin::Block,
bitcoin::Transaction,
BlockHash,
bitcoin::Transaction,
Vec<Transaction>,
Vec<TxOut>,
Expand All @@ -120,13 +119,26 @@ pub async fn fetch_target_block_and_watchtower_tx(
tracing::info!("block height: {block_pos_ss_commit}");
let target_block_ss_commit = btc_client.get_block_by_height(block_pos_ss_commit).await.unwrap();

let operator_blockhash_commit_txid = Txid::from_str(&operator_blockhash_commit_txid).unwrap();
let operator_blockhash_commit_txn =
btc_client.get_tx(&operator_blockhash_commit_txid).await.unwrap().unwrap();
let tx_status = btc_client.get_tx_status(&operator_blockhash_commit_txid).await.unwrap();
let block_pos_operator_blockhash = tx_status.block_height.unwrap();
let operator_committed_blockhash = BlockHash::from_str(operator_committed_blockhash).unwrap();
let target_block_operator_blockhash =
btc_client.get_block_by_height(block_pos_operator_blockhash).await.unwrap();
btc_client.get_block_by_hash(&operator_committed_blockhash).await?.unwrap();
let block_pos_operator_committed_blockhash =
target_block_operator_blockhash.bip34_block_height()? as u32;

// estimate if the target blocks have been proved.
let tip_block = btc_client.get_height().await?;
let delay_blocks = get_btc_block_confirms(btc_client.network());
if block_pos_ss_commit + delay_blocks >= tip_block
|| block_pos_operator_committed_blockhash + delay_blocks >= tip_block
{
anyhow::bail!(
"Target block is not confirmed enough, tip: {}, ss commit block: {}, operator blockhash commit block: {}, delay_blocks: {}",
tip_block,
block_pos_ss_commit,
block_pos_operator_committed_blockhash,
delay_blocks
);
}

// --- watchtower_challenge_txns --- //
let mut watchtower_challenge_txns = Vec::new();
Expand Down Expand Up @@ -167,10 +179,8 @@ pub async fn fetch_target_block_and_watchtower_tx(
Ok((
block_pos_ss_commit,
target_block_ss_commit,
block_pos_operator_blockhash,
target_block_operator_blockhash,
operator_committed_blockhash,
operator_latest_sequencer_commit_txn,
operator_blockhash_commit_txn,
watchtower_challenge_txns,
watchtower_challenge_txn_prev_outs,
watchtower_challenge_txn_pubkeys,
Expand Down Expand Up @@ -226,9 +236,7 @@ impl ProofBuilder for OperatorProofBuilder {
block_pos_ss_commit,
operator_latest_sequencer_commit_txn,

block_pos_operator_blockhash,
target_block_operator_blockhash,
operator_blockhash_commit_txn,
operator_committed_blockhash,

watchtower_challenge_txns,
watchtower_challenge_txn_prev_outs,
Expand Down Expand Up @@ -331,17 +339,6 @@ impl ProofBuilder for OperatorProofBuilder {
&bitcoin_block_headers,
);

tracing::info!(
"construct spv for operator blockhash commit, {}",
operator_blockhash_commit_txn.compute_txid()
);
let spv_operator_blockhash = build_spv(
&operator_blockhash_commit_txn,
*block_pos_operator_blockhash,
target_block_operator_blockhash.clone(),
&bitcoin_block_headers,
);

// Generate the proofs
let (proof, cycles, proving_time) = tracing::info_span!("generate proof").in_scope(
|| -> anyhow::Result<(ZKMProofWithPublicValues, u64, f32)> {
Expand All @@ -364,7 +361,7 @@ impl ProofBuilder for OperatorProofBuilder {
stdin.write(&commit_chain_input);
stdin.write(&state_chain_input);
stdin.write(&spv_ss_commit);
stdin.write(&spv_operator_blockhash);
stdin.write(&operator_committed_blockhash.to_byte_array());

let elf_id = if ELF_ID.get().is_none() {
ELF_ID
Expand Down Expand Up @@ -422,7 +419,7 @@ mod tests {
#[tokio::test]
#[ignore = "local test"]
async fn test_parse_operator_proof() {
let proof_path = "/home/ubuntu/data/proof-builder-rpc/circuits/data/operator/366fb3e0ed2442d39e2cb1e6dda1b08b.bin";
let proof_path = "/home/ubuntu/data/proof-builder-rpc/circuits/data/operator/3c2917b82fe14ef7b8cc8bef3ecd700f.bin";
let proof_bytes = std::fs::read(proof_path).unwrap();
let vk_bytes = fs::read(format!("{proof_path}.vk_hash.bin")).unwrap();

Expand Down
11 changes: 3 additions & 8 deletions circuits/operator-proof/host/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
//! Generate operator proof
use bitcoin::constants::TARGET_BLOCK_SPACING;
use clap::Parser;
use operator_proof::{Args, OperatorProofBuilder, fetch_target_block_and_watchtower_tx};
use proof_builder::{ProofBuilder, ProofRequest};
Expand All @@ -15,18 +14,16 @@ async fn main() {
let (
block_pos_ss_commit,
target_block_ss_commit,
block_pos_operator_blockhash,
target_block_operator_blockhash,
operator_committed_blockhash,
operator_latest_sequencer_commit_txn,
operator_blockhash_commit_txn,
watchtower_challenge_txns,
watchtower_challenge_txn_prev_outs,
watchtower_challenge_txn_pubkeys,
watchtower_challenge_txn_scripts,
) = fetch_target_block_and_watchtower_tx(
&args.esplora_url,
&args.latest_sequencer_commit_txid,
&args.operator_blockhash_commit_txid,
&args.operator_committed_blockhash,
&args.watchtower_challenge_init_txid,
&args.watchtower_challenge_txids,
&args.watchtower_public_keys,
Expand All @@ -52,9 +49,7 @@ async fn main() {
block_pos_ss_commit,
target_block_ss_commit,
operator_latest_sequencer_commit_txn,
block_pos_operator_blockhash,
target_block_operator_blockhash,
operator_blockhash_commit_txn,
operator_committed_blockhash,

watchtower_challenge_txns,
watchtower_challenge_txn_prev_outs,
Expand Down
8 changes: 3 additions & 5 deletions circuits/proof-builder/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use anyhow::Result;
use bitcoin::{Block, ScriptBuf, Transaction, TxOut};
use bitcoin::{Block, BlockHash, ScriptBuf, Transaction, TxOut};
use commit_chain::CircuitCommit;
use header_chain::CircuitBlockHeader;
use serde::{Deserialize, Serialize};
Expand Down Expand Up @@ -59,9 +59,7 @@ pub enum ProofRequest {
block_pos_ss_commit: u32,
operator_latest_sequencer_commit_txn: Transaction,

target_block_operator_blockhash: Block,
block_pos_operator_blockhash: u32,
operator_blockhash_commit_txn: Transaction,
operator_committed_blockhash: BlockHash,

watchtower_challenge_txns: Vec<Transaction>,
watchtower_challenge_txn_prev_outs: Vec<TxOut>,
Expand Down Expand Up @@ -118,5 +116,5 @@ pub struct OnDemandTask {
pub included_watchtowers: Vec<bool>,
pub watchtower_public_keys: Vec<String>,
pub graph_id: Option<String>,
pub operator_blockhash_commit_txid: Option<String>,
pub operator_committed_blockhash: Option<String>,
}
19 changes: 11 additions & 8 deletions crates/bitcoin-light-client-circuit/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ pub fn propose_longest_chain(
commit_chain: CommitChainCircuitInput,
state_chain: StateChainCircuitInput,
spv_ss_commit: SPV,
spv_operator_blockhash: SPV,
operator_committed_blockhash: [u8; 32],
) -> ([u8; 32], [u8; 32], [u8; 32]) {
// 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
Expand Down Expand Up @@ -194,8 +194,6 @@ pub fn propose_longest_chain(

// verify that the latest_sequecner_commit_tx is in the header chain
assert!(spv_ss_commit.verify(&btc_header_chain_output.chain_state.block_hashes_mmr));
// verify that the operator_blockhash is in the header chain
assert!(spv_operator_blockhash.verify(&btc_header_chain_output.chain_state.block_hashes_mmr));

// parse included_watchtowers into bits array
let included_watchertowers_bits = u256_to_le_bits(included_watchtowers);
Expand Down Expand Up @@ -340,13 +338,18 @@ pub fn propose_longest_chain(

println!("btc_best_block_hash hex: {:?}", hex::encode(btc_best_block_hash));
println!("included_watchtowers: {:?}", hex::encode(included_watchtowers.to_le_bytes::<32>()));
//let operator_public_input =
// hash_operator_inputs(btc_best_block_hash, constant, included_watchtowers);
//println!("operator public input hex: {:?}", hex::encode(operator_public_input));
//let included = operator_header_chain
// .block_headers
// .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,
"operator committed blockhash is not included in header chain"
);

//operator_public_input
let operator_blockhash = spv_operator_blockhash.transaction.0.compute_txid().to_byte_array();
(operator_blockhash, constant, included_watchtowers.to_le_bytes::<32>())
(operator_committed_blockhash, constant, included_watchtowers.to_le_bytes::<32>())
}

pub fn hash_operator_constant(
Expand Down
Loading
Loading