Skip to content

Commit

Permalink
Bind ELF to ProofData (#1647)
Browse files Browse the repository at this point in the history
Co-authored-by: eyusufatik <[email protected]>
Co-authored-by: Erce Can Bektüre <[email protected]>
  • Loading branch information
3 people authored Jan 3, 2025
1 parent f27657b commit fd0b552
Show file tree
Hide file tree
Showing 46 changed files with 1,234 additions and 288 deletions.
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ alloy-eips = { version = "0.4.2", default-features = false }
alloy-consensus = { version = "0.4.2", default-features = false, features = ["serde", "serde-bincode-compat"] }
alloy-network = { version = "0.4.2", default-features = false }

citrea-e2e = { git = "https://github.com/chainwayxyz/citrea-e2e", rev = "6a87ce3" }
citrea-e2e = { git = "https://github.com/chainwayxyz/citrea-e2e", rev = "82c1cdb" }

[patch.crates-io]
bitcoincore-rpc = { version = "0.18.0", git = "https://github.com/chainwayxyz/rust-bitcoincore-rpc.git", rev = "ca3cfa2" }
Expand Down
31 changes: 23 additions & 8 deletions bin/citrea/src/guests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,14 @@ lazy_static! {
pub(crate) static ref BATCH_PROOF_LATEST_MOCK_GUESTS: HashMap<SpecId, (Digest, Vec<u8>)> = {
let mut m = HashMap::new();

m.insert(
SpecId::Genesis,
(
Digest::new(citrea_risc0_batch_proof::BATCH_PROOF_MOCK_ID),
citrea_risc0_batch_proof::BATCH_PROOF_MOCK_ELF.to_vec(),
),
);

m.insert(
SpecId::Fork1,
(
Expand All @@ -42,20 +50,27 @@ lazy_static! {
};
/// The following 2 are used as latest guest builds for tests that use Bitcoin DA.
pub(crate) static ref BATCH_PROOF_LATEST_BITCOIN_GUESTS: HashMap<SpecId, (Digest, Vec<u8>)> = {
HashMap::from(
[
// this is ELF of genesis fork except for da namespace [1, 1] -> [1] and [2,2] -> [2]
(SpecId::Genesis, guest!("../../../resources/guests/risc0/genesis-batch-proof-0-short-prefix")),
(SpecId::Fork1,
(Digest::new(citrea_risc0_batch_proof::BATCH_PROOF_BITCOIN_ID),
citrea_risc0_batch_proof::BATCH_PROOF_BITCOIN_ELF.to_vec())
)
]
)
};
pub(crate) static ref LIGHT_CLIENT_LATEST_BITCOIN_GUESTS: HashMap<SpecId, (Digest, Vec<u8>)> = {
let mut m = HashMap::new();

m.insert(
SpecId::Fork1,
SpecId::Genesis,
(
Digest::new(citrea_risc0_batch_proof::BATCH_PROOF_BITCOIN_ID),
citrea_risc0_batch_proof::BATCH_PROOF_BITCOIN_ELF.to_vec(),
Digest::new(citrea_risc0_light_client::LIGHT_CLIENT_PROOF_BITCOIN_ID),
citrea_risc0_light_client::LIGHT_CLIENT_PROOF_BITCOIN_ELF.to_vec(),
)
);
m
};
pub(crate) static ref LIGHT_CLIENT_LATEST_BITCOIN_GUESTS: HashMap<SpecId, (Digest, Vec<u8>)> = {
let mut m = HashMap::new();

m.insert(
SpecId::Fork1,
(
Expand Down
179 changes: 177 additions & 2 deletions bin/citrea/tests/bitcoin_e2e/batch_prover_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,21 @@ use bitcoin_da::service::{BitcoinService, BitcoinServiceConfig, FINALITY_DEPTH};
use bitcoin_da::spec::RollupParams;
use citrea_common::tasks::manager::TaskManager;
use citrea_e2e::config::{
BatchProverConfig, ProverGuestRunConfig, SequencerConfig, SequencerMempoolConfig,
TestCaseConfig, TestCaseEnv,
BatchProverConfig, LightClientProverConfig, ProverGuestRunConfig, SequencerConfig,
SequencerMempoolConfig, TestCaseConfig, TestCaseEnv,
};
use citrea_e2e::framework::TestFramework;
use citrea_e2e::full_node::FullNode;
use citrea_e2e::node::{Config, NodeKind};
use citrea_e2e::test_case::{TestCase, TestCaseRunner};
use citrea_e2e::traits::NodeT;
use citrea_e2e::Result;
use citrea_light_client_prover::rpc::LightClientProverRpcClient;
use citrea_primitives::forks::{fork_from_block_number, get_forks};
use citrea_primitives::{TO_BATCH_PROOF_PREFIX, TO_LIGHT_CLIENT_PREFIX};
use sov_ledger_rpc::LedgerRpcClient;
use sov_modules_api::fork::ForkManager;
use sov_modules_api::SpecId;
use sov_rollup_interface::da::{DaTxRequest, SequencerCommitment};
use sov_rollup_interface::rpc::VerifiedBatchProofResponse;
use tokio::time::sleep;
Expand Down Expand Up @@ -68,6 +72,13 @@ impl TestCase for BasicProverTest {
}
}

fn batch_prover_config() -> BatchProverConfig {
BatchProverConfig {
use_latest_elf: false,
..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();
Expand Down Expand Up @@ -154,6 +165,13 @@ impl TestCase for SkipPreprovenCommitmentsTest {
}
}

fn batch_prover_config() -> BatchProverConfig {
BatchProverConfig {
use_latest_elf: false,
..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();
Expand Down Expand Up @@ -523,3 +541,160 @@ async fn parallel_proving_test() -> Result<()> {
.run()
.await
}

struct ForkElfSwitchingTest;

#[async_trait]
impl TestCase for ForkElfSwitchingTest {
fn test_config() -> TestCaseConfig {
TestCaseConfig {
with_batch_prover: true,
with_full_node: true,
with_light_client_prover: true,
..Default::default()
}
}

fn sequencer_config() -> SequencerConfig {
let fork_1_height = ForkManager::new(get_forks(), 0)
.next_fork()
.unwrap()
.activation_height;

// Set just below fork1 height so we can generate first soft com txs in genesis
// and second batch above fork1
SequencerConfig {
min_soft_confirmations_per_commitment: fork_1_height - 5,
..Default::default()
}
}

fn batch_prover_config() -> BatchProverConfig {
BatchProverConfig {
use_latest_elf: false,
..Default::default()
}
}

fn light_client_prover_config() -> LightClientProverConfig {
LightClientProverConfig {
initial_da_height: 171,
enable_recovery: false,
..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 full_node = f.full_node.as_ref().unwrap();
let light_client_prover = f.light_client_prover.as_ref().unwrap();

// send evm tx
let evm_client = make_test_client(SocketAddr::new(
sequencer.config().rpc_bind_host().parse()?,
sequencer.config().rpc_bind_port(),
))
.await?;

let pending_evm_tx = evm_client
.send_eth(Address::random(), None, None, None, 100)
.await
.unwrap();

let min_soft_confirmations = sequencer.min_soft_confirmations_per_commitment();

for _ in 0..min_soft_confirmations {
sequencer.client.send_publish_batch_request().await?;
}

// assert that evm tx is mined
let evm_tx = evm_client
.eth_get_transaction_by_hash(*pending_evm_tx.tx_hash(), None)
.await
.unwrap();

assert!(evm_tx.block_number.is_some());

let height = sequencer
.client
.ledger_get_head_soft_confirmation_height()
.await?;

assert_eq!(fork_from_block_number(height).spec_id, SpecId::Genesis);

// Generate softcom in fork1
for _ in 0..min_soft_confirmations {
sequencer.client.send_publish_batch_request().await?;
}

let height = sequencer
.client
.ledger_get_head_soft_confirmation_height()
.await?;
assert_eq!(fork_from_block_number(height).spec_id, SpecId::Fork1);

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

da.generate(FINALITY_DEPTH).await?;

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

batch_prover
.wait_for_l1_height(finalized_height, None)
.await?;

// Wait for batch proof tx to hit mempool
da.wait_mempool_len(4, None).await?;
da.generate(FINALITY_DEPTH).await?;

full_node
.wait_for_l1_height(finalized_height + FINALITY_DEPTH, None)
.await?;
let proofs = wait_for_zkproofs(full_node, finalized_height + FINALITY_DEPTH, None)
.await
.unwrap();

assert_eq!(proofs.len(), 2);
assert_eq!(
fork_from_block_number(proofs[0].proof_output.last_l2_height).spec_id,
SpecId::Genesis
);
assert_eq!(
fork_from_block_number(proofs[1].proof_output.last_l2_height).spec_id,
SpecId::Fork1
);

light_client_prover
.wait_for_l1_height(finalized_height + FINALITY_DEPTH, None)
.await?;
let lcp = light_client_prover
.client
.http_client()
.get_light_client_proof_by_l1_height(finalized_height + FINALITY_DEPTH)
.await
.unwrap()
.unwrap();

assert!(lcp
.light_client_proof_output
.unchained_batch_proofs_info
.is_empty());

assert_eq!(
lcp.light_client_proof_output.state_root.to_vec(),
proofs[1].proof_output.final_state_root
);

Ok(())
}
}

#[tokio::test]
async fn test_fork_elf_switching() -> Result<()> {
TestCaseRunner::new(ForkElfSwitchingTest)
.set_citrea_path(get_citrea_path())
.run()
.await
}
Loading

0 comments on commit fd0b552

Please sign in to comment.