Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add guest cycle count test with input from file. #1761

Open
wants to merge 10 commits into
base: nightly
Choose a base branch
from
Open
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
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,6 @@ reveal_*.tx

*.txs

elf/
elf/
*input.bin
*transactions.txt
159 changes: 159 additions & 0 deletions bin/citrea/tests/bitcoin_e2e/guest_cycles.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
use std::fs::File;
use std::io::{BufRead, BufReader};
use std::path::PathBuf;
use std::process::Command;
use std::time::Duration;
use std::{env, fs};

use async_trait::async_trait;
use bitcoin_da::service::FINALITY_DEPTH;
use citrea_e2e::config::{SequencerConfig, SequencerMempoolConfig, TestCaseConfig, TestCaseEnv};
use citrea_e2e::framework::TestFramework;
use citrea_e2e::test_case::{TestCase, TestCaseRunner};
use citrea_e2e::Result;
use citrea_sequencer::SequencerRpcClient;
use risc0_zkvm::{default_prover, ExecutorEnvBuilder, ProveInfo, ProverOpts};

/// Helper test to generate a batch proof input. Risc0 host code should be modified
/// to save the input to a file if it will be used in `guest_cycles` test. If the input
/// struct has not changed, you don't need to run this, and you can just use the one at
/// 'test-data/kumquat-input.bin'
struct GenerateProofInput {
transactions_file_path: PathBuf,
}

#[async_trait]
impl TestCase for GenerateProofInput {
fn test_config() -> TestCaseConfig {
TestCaseConfig {
with_batch_prover: true,
genesis_dir: Some(format!(
"{}/tests/bitcoin_e2e/test-data/gen-proof-input-genesis",
env!("CARGO_MANIFEST_DIR")
)),
..Default::default()
}
}

fn sequencer_config() -> SequencerConfig {
SequencerConfig {
min_soft_confirmations_per_commitment: 50,
mempool_conf: SequencerMempoolConfig {
pending_tx_limit: 1_000_000,
pending_tx_size: 100_000_000,
queue_tx_limit: 1_000_000,
queue_tx_size: 100_000_000,
base_fee_tx_limit: 1_000_000,
base_fee_tx_size: 100_000_000,
max_account_slots: 1_000_000,
},
test_mode: false,
block_production_interval_ms: 500,
..Default::default()
}
}

fn test_env() -> TestCaseEnv {
TestCaseEnv {
test: vec![("RISC0_DEV_MODE", "1")],
..Default::default()
}
}

async fn run_test(&mut self, f: &mut TestFramework) -> Result<()> {
let da = f.bitcoin_nodes.get(0).unwrap();
let sequencer = f.sequencer.as_ref().unwrap();
let batch_prover = f.batch_prover.as_ref().unwrap();

let file = File::open(&self.transactions_file_path).unwrap();
let reader = BufReader::new(file);

// Send each transaction from the file
for line in reader.lines() {
let signed_tx = line.unwrap();

// Skip empty lines
if signed_tx.trim().is_empty() {
continue;
}

sequencer
.client
.http_client()
.eth_send_raw_transaction(hex::decode(signed_tx).unwrap().into())
.await
.unwrap();
}
println!("All txs sent");

da.wait_mempool_len(4, None).await?;
da.generate(FINALITY_DEPTH).await?;

let finalized_height = da.get_finalized_height().await.unwrap();

println!("Waiting batch prover l1 height: {finalized_height}");
batch_prover
.wait_for_l1_height(finalized_height, Some(Duration::from_secs(100_800)))
.await?;

Ok(())
}
}

#[tokio::test]
#[ignore]
async fn generate_proof_input() -> Result<()> {
// Specify the path to your transactions file here
let transactions_file_path =
PathBuf::from("tests/bitcoin_e2e/test-data/signed-transactions.txt");

TestCaseRunner::new(GenerateProofInput {
transactions_file_path,
})
.set_citrea_path(env::var("CITREA_E2E_TEST_BINARY")?)
.run()
.await
}

#[tokio::test]
#[ignore]
async fn guest_cycles() {
let input =
fs::read("tests/bitcoin_e2e/test-data/kumquat-2seqcomms-100blocks-input.bin").unwrap();
println!("Input size: {}", input.len());

// Convert tmpdir to path so it's not deleted after the run for debugging purposes
let tmpdir = tempfile::tempdir().unwrap().into_path();

let mut elf_path = tmpdir.clone();
elf_path.push("batch_proof_bitcoin");

// Build guest elf with nightly network
let status = Command::new("make")
.arg("batch-proof-bitcoin-docker")
.current_dir("../../guests/risc0")
.env("CITREA_NETWORK", "nightly")
.env("OUT_PATH", &elf_path)
.status()
.expect("'make batch-proof-bitcoin-docker' command failed");
assert!(status.success());

println!("\nELF path: {:?}", elf_path);
let elf = fs::read(elf_path).unwrap();

let exec_env = ExecutorEnvBuilder::default()
.write_slice(&input)
.build()
.unwrap();

env::set_var("RISC0_DEV_MODE", "1");
env::set_var("RISC0_INFO", "1");
env::set_var("RUST_LOG", "info");
let prover = default_prover();

let ProveInfo { stats, .. } = prover
.prove_with_opts(exec_env, &elf, &ProverOpts::groth16())
.unwrap();

println!("Execution stats: {:?}", stats);
}
1 change: 1 addition & 0 deletions bin/citrea/tests/bitcoin_e2e/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ pub mod light_client_test;
// pub mod mempool_accept;
pub mod bitcoin_test;
pub mod full_node;
pub mod guest_cycles;
pub mod sequencer_commitments;
pub mod sequencer_test;
pub mod tx_chain;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"pub_keys": []
}
Loading
Loading