diff --git a/Cargo.lock b/Cargo.lock index b947424d8..1791c16ed 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2875,6 +2875,7 @@ dependencies = [ "tracing-subscriber", "vergen", "zero_bin_common", + "zk_evm_common", ] [[package]] @@ -3303,6 +3304,7 @@ dependencies = [ "serde", "tracing", "zero_bin_common", + "zk_evm_common", ] [[package]] @@ -3855,6 +3857,7 @@ dependencies = [ "paste", "plonky2", "serde", + "zk_evm_common", ] [[package]] @@ -3899,6 +3902,7 @@ dependencies = [ "trace_decoder", "tracing", "zero_bin_common", + "zk_evm_common", ] [[package]] @@ -4187,6 +4191,7 @@ dependencies = [ "url", "vergen", "zero_bin_common", + "zk_evm_common", ] [[package]] @@ -5420,6 +5425,7 @@ dependencies = [ "tracing-subscriber", "vergen", "zero_bin_common", + "zk_evm_common", ] [[package]] @@ -5864,6 +5870,7 @@ dependencies = [ "tracing", "tracing-subscriber", "vergen", + "zk_evm_common", ] [[package]] diff --git a/common/src/lib.rs b/common/src/lib.rs index bac6dd440..0ff0d47d5 100644 --- a/common/src/lib.rs +++ b/common/src/lib.rs @@ -14,6 +14,25 @@ pub const EMPTY_TRIE_HASH: H256 = H256([ 108, 173, 192, 1, 98, 47, 181, 227, 99, 180, 33, ]); +#[macro_export] +/// A convenience macro to check the feature flags activating chain specific +/// behaviors. Only one of these flags may be activated at a time. +macro_rules! check_chain_features { + () => { + #[cfg(any( + all(feature = "cdk_erigon", feature = "polygon_pos"), + all(feature = "cdk_erigon", feature = "eth_mainnet"), + all(feature = "polygon_pos", feature = "eth_mainnet"), + not(any( + feature = "cdk_erigon", + feature = "eth_mainnet", + feature = "polygon_pos" + )) + ))] + compile_error!("One and only one of the feature chains `cdk_erigon`, `polygon_pos` or `eth_mainnet` must be selected"); + }; +} + /// Converts an amount in `ETH` to `wei` units. pub fn eth_to_wei(eth: U256) -> U256 { // 1 ether = 10^18 wei. diff --git a/evm_arithmetization/Cargo.toml b/evm_arithmetization/Cargo.toml index 90d01c071..ffdb8d2f5 100644 --- a/evm_arithmetization/Cargo.toml +++ b/evm_arithmetization/Cargo.toml @@ -49,8 +49,8 @@ serde-big-array = { workspace = true } # Local dependencies mpt_trie = { workspace = true } smt_trie = { workspace = true, optional = true } -zk_evm_proc_macro = { workspace = true } zk_evm_common = { workspace = true } +zk_evm_proc_macro = { workspace = true } [dev-dependencies] criterion = { workspace = true } diff --git a/evm_arithmetization/src/cpu/kernel/asm/core/precompiles/main.asm b/evm_arithmetization/src/cpu/kernel/asm/core/precompiles/main.asm index 4bb924f87..1f1aa5af5 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/core/precompiles/main.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/core/precompiles/main.asm @@ -27,6 +27,7 @@ global handle_precompiles: { %eq_const(@BLAKE2_F) %jumpi(precompile_blake2_f) } + // TODO: Add support of EIP-7712 for Polygon Pos, https://github.com/0xPolygonZero/zk_evm/issues/265 // stack: retdest JUMP diff --git a/evm_arithmetization/src/cpu/kernel/asm/core/util.asm b/evm_arithmetization/src/cpu/kernel/asm/core/util.asm index 053c6159c..713b2274f 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/core/util.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/core/util.asm @@ -37,8 +37,20 @@ %macro is_precompile // stack: addr - DUP1 %ge_const(@ECREC) SWAP1 %le_const(@KZG_PEVAL) - // stack: addr>=1, addr<=10 + DUP1 %ge_const(@ECREC) + SWAP1 + // stack: addr, addr>=1 + #[cfg(feature = eth_mainnet)] + { + %le_const(@KZG_PEVAL) + // stack: addr>=1, addr<=10 + } + // TODO: Update after support of EIP-7712 for Polygon Pos, https://github.com/0xPolygonZero/zk_evm/issues/265 + #[cfg(not(feature = eth_mainnet))] + { + %le_const(@BLAKE2_F) + // stack: addr>=1, addr<=9 + } MUL // Cheaper than AND %endmacro diff --git a/evm_arithmetization/src/generation/mod.rs b/evm_arithmetization/src/generation/mod.rs index 89e697865..9c7625d2b 100644 --- a/evm_arithmetization/src/generation/mod.rs +++ b/evm_arithmetization/src/generation/mod.rs @@ -1,7 +1,6 @@ use std::collections::HashMap; use anyhow::anyhow; -use ethereum_types::H160; use ethereum_types::{Address, BigEndianHash, H256, U256}; use keccak_hash::keccak; use log::log_enabled; @@ -73,7 +72,7 @@ pub struct GenerationInputs { /// `None`, then the base fee is directly burnt. /// /// Note: this is only used when feature `cdk_erigon` is activated. - pub burn_addr: Option, + pub burn_addr: Option
, /// Withdrawal pairs `(addr, amount)`. At the end of the txs, `amount` is /// added to `addr`'s balance. See EIP-4895. pub withdrawals: Vec<(Address, U256)>, @@ -152,7 +151,7 @@ pub struct TrimmedGenerationInputs { /// Address where the burnt fees are stored. Only used if the `cfg_erigon` /// feature is activated. - pub burn_addr: Option, + pub burn_addr: Option
, /// The hash of the current block, and a list of the 256 previous block /// hashes. diff --git a/evm_arithmetization/src/lib.rs b/evm_arithmetization/src/lib.rs index 3587293d5..ca2cf2bd7 100644 --- a/evm_arithmetization/src/lib.rs +++ b/evm_arithmetization/src/lib.rs @@ -183,16 +183,7 @@ #![allow(clippy::field_reassign_with_default)] #![feature(let_chains)] -#[cfg_attr( - not(any(feature = "polygon_pos", feature = "cdk_erigon")), - cfg(feature = "eth_mainnet") -)] -#[cfg(any( - all(feature = "cdk_erigon", feature = "polygon_pos"), - all(feature = "cdk_erigon", feature = "eth_mainnet"), - all(feature = "polygon_pos", feature = "eth_mainnet"), -))] -compile_error!("Only a single network feature should be enabled at a time!"); +zk_evm_common::check_chain_features!(); // Individual STARK processing units pub mod arithmetic; diff --git a/evm_arithmetization/src/prover.rs b/evm_arithmetization/src/prover.rs index ff16cc1cb..0cd825e87 100644 --- a/evm_arithmetization/src/prover.rs +++ b/evm_arithmetization/src/prover.rs @@ -475,7 +475,7 @@ pub fn check_abort_signal(abort_signal: Option>) -> Result<()> { /// Sanity checks on the consistency between this proof payload and the feature /// flags being used. pub(crate) fn features_check(inputs: &TrimmedGenerationInputs) { - if cfg!(feature = "polygon_pos") || cfg!(feature = "cdk_erigon") { + if !cfg!(feature = "eth_mainnet") { assert!(inputs.block_metadata.parent_beacon_block_root.is_zero()); assert!(inputs.block_metadata.block_blob_gas_used.is_zero()); assert!(inputs.block_metadata.block_excess_blob_gas.is_zero()); diff --git a/proof_gen/Cargo.toml b/proof_gen/Cargo.toml index 9c72b0362..1e2f595b9 100644 --- a/proof_gen/Cargo.toml +++ b/proof_gen/Cargo.toml @@ -18,6 +18,7 @@ hashbrown = { workspace = true } # Local dependencies evm_arithmetization = { workspace = true } +zk_evm_common = { workspace = true } [features] default = ["eth_mainnet"] @@ -27,6 +28,9 @@ eth_mainnet = [ cdk_erigon = [ "evm_arithmetization/cdk_erigon" ] +polygon_pos = [ + "evm_arithmetization/polygon_pos" +] [lints] workspace = true diff --git a/proof_gen/src/lib.rs b/proof_gen/src/lib.rs index c96491af4..f1e48a109 100644 --- a/proof_gen/src/lib.rs +++ b/proof_gen/src/lib.rs @@ -134,6 +134,8 @@ //! assert!(verifier_state.verify(block_proof.intern).is_ok()); //! ``` +zk_evm_common::check_chain_features!(); + pub(crate) mod constants; pub mod proof_gen; pub mod proof_types; diff --git a/trace_decoder/Cargo.toml b/trace_decoder/Cargo.toml index 1bb940daa..262185c7a 100644 --- a/trace_decoder/Cargo.toml +++ b/trace_decoder/Cargo.toml @@ -62,17 +62,30 @@ serde_path_to_error = { workspace = true } [features] default = ["eth_mainnet"] -eth_mainnet = ["evm_arithmetization/eth_mainnet", "prover/eth_mainnet"] -cdk_erigon = ["evm_arithmetization/cdk_erigon", "prover/cdk_erigon"] +eth_mainnet = [ + "evm_arithmetization/eth_mainnet", + "prover/eth_mainnet", +] +cdk_erigon = [ + "evm_arithmetization/cdk_erigon", + "prover/cdk_erigon", +] +polygon_pos = [ + "evm_arithmetization/polygon_pos", + "prover/polygon_pos", +] [[bench]] name = "block_processing" harness = false +required-features = ["eth_mainnet"] [[test]] name = "consistent-with-header" harness = false +required-features = ["eth_mainnet"] [[test]] name = "simulate-execution" harness = false +required-features = ["eth_mainnet"] diff --git a/trace_decoder/benches/block_processing.rs b/trace_decoder/benches/block_processing.rs index c6e9716e3..6f3319d94 100644 --- a/trace_decoder/benches/block_processing.rs +++ b/trace_decoder/benches/block_processing.rs @@ -33,7 +33,7 @@ fn criterion_benchmark(c: &mut Criterion) { block_trace, other_data, }| { - trace_decoder::entrypoint(block_trace, other_data, batch_size, false).unwrap() + trace_decoder::entrypoint(block_trace, other_data, batch_size).unwrap() }, BatchSize::LargeInput, ) diff --git a/trace_decoder/src/core.rs b/trace_decoder/src/core.rs index 003c07d2b..64c0dc2ee 100644 --- a/trace_decoder/src/core.rs +++ b/trace_decoder/src/core.rs @@ -32,7 +32,6 @@ pub fn entrypoint( trace: BlockTrace, other: OtherBlockData, batch_size_hint: usize, - use_burn_addr: bool, ) -> anyhow::Result>> { ensure!(batch_size_hint != 0); @@ -53,6 +52,7 @@ pub fn entrypoint( }, checkpoint_state_trie_root, checkpoint_consolidated_hash, + burn_addr, } = other; for (_, amt) in &mut withdrawals { @@ -112,7 +112,7 @@ pub fn entrypoint( .collect(), block_metadata: b_meta.clone(), block_hashes: b_hashes.clone(), - burn_addr: use_burn_addr.then_some(Address::zero()), + burn_addr, }, ) .collect()) diff --git a/trace_decoder/src/decoding.rs b/trace_decoder/src/decoding.rs deleted file mode 100644 index be55821a0..000000000 --- a/trace_decoder/src/decoding.rs +++ /dev/null @@ -1,713 +0,0 @@ -use std::{cmp::min, collections::HashMap, ops::Range}; - -use anyhow::{anyhow, Context as _}; -use ethereum_types::H160; -use ethereum_types::{Address, BigEndianHash, H256, U256, U512}; -use evm_arithmetization::{ - generation::{ - mpt::{decode_receipt, AccountRlp}, - GenerationInputs, TrieInputs, - }, - proof::{BlockMetadata, ExtraBlockData, TrieRoots}, - testing_utils::{ - BEACON_ROOTS_CONTRACT_ADDRESS, BEACON_ROOTS_CONTRACT_ADDRESS_HASHED, HISTORY_BUFFER_LENGTH, - }, -}; -use mpt_trie::{ - nibbles::Nibbles, - partial_trie::{HashedPartialTrie, PartialTrie as _}, - special_query::path_for_query, - trie_ops::TrieOpError, - utils::{IntoTrieKey as _, TriePath}, -}; -use plonky2::hash::hash_types::RichField; - -use crate::{ - hash, - processed_block_trace::{ - NodesUsedByTxnBatch, ProcessedBlockTrace, ProcessedTxnBatchInfo, StateWrite, TxnMetaState, - }, - typed_mpt::{ReceiptTrie, StateTrie, StorageTrie, TransactionTrie, TrieKey}, - Field, OtherBlockData, PartialTriePreImages, TryIntoExt as TryIntoBounds, -}; - -/// The current state of all tries as we process txn deltas. These are mutated -/// after every txn we process in the trace. -#[derive(Clone, Debug, Default)] -struct PartialTrieState { - state: StateTrieT, - storage: HashMap, - txn: TransactionTrie, - receipt: ReceiptTrie, -} - -/// Additional information discovered during delta application. -#[derive(Debug, Default)] -struct TrieDeltaApplicationOutput { - // During delta application, if a delete occurs, we may have to make sure additional nodes - // that are not accessed by the txn remain unhashed. - additional_state_trie_paths_to_not_hash: Vec, - additional_storage_trie_paths_to_not_hash: HashMap>, -} - -pub fn into_txn_proof_gen_ir( - ProcessedBlockTrace { - tries: PartialTriePreImages { state, storage }, - txn_info, - withdrawals, - }: ProcessedBlockTrace, - other_data: OtherBlockData, - use_burn_addr: bool, - batch_size: usize, -) -> anyhow::Result>> { - let mut curr_block_tries = PartialTrieState { - state: state.clone(), - storage: storage.iter().map(|(k, v)| (*k, v.clone())).collect(), - ..Default::default() - }; - - let mut extra_data = ExtraBlockData:: { - checkpoint_state_trie_root: other_data.checkpoint_state_trie_root, - checkpoint_consolidated_hash: other_data.checkpoint_consolidated_hash, - txn_number_before: U256::zero(), - txn_number_after: U256::zero(), - gas_used_before: U256::zero(), - gas_used_after: U256::zero(), - }; - - let num_txs = txn_info - .iter() - .map(|tx_info| tx_info.meta.len()) - .sum::(); - - let mut txn_gen_inputs = txn_info - .into_iter() - .enumerate() - .map(|(txn_idx, txn_info)| { - let txn_range = - min(txn_idx * batch_size, num_txs)..min(txn_idx * batch_size + batch_size, num_txs); - let is_initial_payload = txn_range.start == 0; - - process_txn_info( - txn_range.clone(), - is_initial_payload, - txn_info, - &mut curr_block_tries, - &mut extra_data, - &other_data, - use_burn_addr, - ) - .context(format!( - "at transaction range {}..{}", - txn_range.start, txn_range.end - )) - }) - .collect::>>() - .context(format!( - "at block num {} with chain id {}", - other_data.b_data.b_meta.block_number, other_data.b_data.b_meta.block_chain_id - ))?; - - if !withdrawals.is_empty() { - add_withdrawals_to_txns(&mut txn_gen_inputs, &mut curr_block_tries, withdrawals)?; - } - - Ok(txn_gen_inputs) -} - -/// Cancun HF specific: At the start of a block, prior txn execution, we -/// need to update the storage of the beacon block root contract. -// See . -fn update_beacon_block_root_contract_storage( - trie_state: &mut PartialTrieState, - delta_out: &mut TrieDeltaApplicationOutput, - nodes_used: &mut NodesUsedByTxnBatch, - block_data: &BlockMetadata, -) -> anyhow::Result<()> { - const HISTORY_BUFFER_LENGTH_MOD: U256 = U256([HISTORY_BUFFER_LENGTH.1, 0, 0, 0]); - - let timestamp_idx = block_data.block_timestamp % HISTORY_BUFFER_LENGTH_MOD; - let timestamp = rlp::encode(&block_data.block_timestamp).to_vec(); - - let root_idx = timestamp_idx + HISTORY_BUFFER_LENGTH_MOD; - let calldata = rlp::encode(&U256::from_big_endian( - &block_data.parent_beacon_block_root.0, - )) - .to_vec(); - - let storage_trie = trie_state - .storage - .get_mut(&BEACON_ROOTS_CONTRACT_ADDRESS_HASHED) - .context(format!( - "missing account storage trie for address {:x}", - BEACON_ROOTS_CONTRACT_ADDRESS - ))?; - - let slots_nibbles = nodes_used - .storage_accesses - .entry(BEACON_ROOTS_CONTRACT_ADDRESS_HASHED) - .or_default(); - - for (ix, val) in [(timestamp_idx, timestamp), (root_idx, calldata)] { - // TODO(0xaatif): https://github.com/0xPolygonZero/zk_evm/issues/275 - // document this - let slot = TrieKey::from_nibbles(Nibbles::from_h256_be(hash( - Nibbles::from_h256_be(H256::from_uint(&ix)).bytes_be(), - ))); - - slots_nibbles.push(slot); - - // If we are writing a zero, then we actually need to perform a delete. - match val == ZERO_STORAGE_SLOT_VAL_RLPED { - false => { - storage_trie.insert(slot, val.clone()).context(format!( - "at slot {:?} with value {}", - slot, - U512::from_big_endian(val.as_slice()) - ))?; - - delta_out - .additional_storage_trie_paths_to_not_hash - .entry(BEACON_ROOTS_CONTRACT_ADDRESS_HASHED) - .or_default() - .push(slot); - } - true => { - if let Ok(Some(remaining_slot_key)) = - delete_node_and_report_remaining_key_if_branch_collapsed( - storage_trie.as_mut_hashed_partial_trie_unchecked(), - &slot, - ) - { - delta_out - .additional_storage_trie_paths_to_not_hash - .entry(BEACON_ROOTS_CONTRACT_ADDRESS_HASHED) - .or_default() - .push(remaining_slot_key); - } - } - } - } - - delta_out - .additional_state_trie_paths_to_not_hash - .push(TrieKey::from_hash(BEACON_ROOTS_CONTRACT_ADDRESS_HASHED)); - let mut account = trie_state - .state - .get_by_address(BEACON_ROOTS_CONTRACT_ADDRESS) - .context(format!( - "missing account storage trie for address {:x}", - BEACON_ROOTS_CONTRACT_ADDRESS - ))?; - - account.storage_root = storage_trie.root(); - - trie_state - .state - .insert_by_address(BEACON_ROOTS_CONTRACT_ADDRESS, account) - // TODO(0xaatif): https://github.com/0xPolygonZero/zk_evm/issues/275 - // Add an entry API - .expect("insert must succeed with the same key as a successful `get`"); - - Ok(()) -} - -fn update_txn_and_receipt_tries( - trie_state: &mut PartialTrieState, - meta: &TxnMetaState, - txn_idx: usize, -) -> anyhow::Result<()> { - if let Some(bytes) = &meta.txn_bytes { - trie_state.txn.insert(txn_idx, bytes.clone())?; - trie_state - .receipt - .insert(txn_idx, meta.receipt_node_bytes.clone())?; - } // else it's just a dummy - Ok(()) -} - -/// If the account does not have a storage trie or does but is not -/// accessed by any txns, then we still need to manually create an entry for -/// them. -fn init_any_needed_empty_storage_tries<'a>( - storage_tries: &mut HashMap, - accounts_with_storage: impl Iterator, - accts_with_unaccessed_storage: &HashMap, -) { - for h_addr in accounts_with_storage { - if !storage_tries.contains_key(h_addr) { - let trie = accts_with_unaccessed_storage - .get(h_addr) - .map(|s_root| { - let mut it = StorageTrie::default(); - it.insert_hash(TrieKey::default(), *s_root) - .expect("empty trie insert cannot fail"); - it - }) - .unwrap_or_default(); - - storage_tries.insert(*h_addr, trie); - }; - } -} - -fn create_minimal_partial_tries_needed_by_txn( - curr_block_tries: &PartialTrieState>, - nodes_used_by_txn: &NodesUsedByTxnBatch, - txn_range: Range, - delta_application_out: TrieDeltaApplicationOutput, -) -> anyhow::Result { - let mut state_trie = curr_block_tries.state.clone(); - state_trie.trim_to( - nodes_used_by_txn - .state_accesses - .iter() - .map(|it| TrieKey::from_address(*it)) - .chain(delta_application_out.additional_state_trie_paths_to_not_hash), - )?; - - let txn_keys = txn_range.map(TrieKey::from_txn_ix); - - let transactions_trie = create_trie_subset_wrapped( - curr_block_tries.txn.as_hashed_partial_trie(), - txn_keys.clone(), - TrieType::Txn, - )?; - - let receipts_trie = create_trie_subset_wrapped( - curr_block_tries.receipt.as_hashed_partial_trie(), - txn_keys, - TrieType::Receipt, - )?; - - let storage_tries = create_minimal_storage_partial_tries( - &curr_block_tries.storage, - &nodes_used_by_txn.storage_accesses, - &delta_application_out.additional_storage_trie_paths_to_not_hash, - )?; - - Ok(TrieInputs { - state_trie: state_trie.try_into()?, - transactions_trie, - receipts_trie, - storage_tries, - }) -} - -fn apply_deltas_to_trie_state( - trie_state: &mut PartialTrieState, - deltas: &NodesUsedByTxnBatch, - meta: &[TxnMetaState], -) -> anyhow::Result { - let mut out = TrieDeltaApplicationOutput::default(); - - for (hashed_acc_addr, storage_writes) in deltas.storage_writes.iter() { - let storage_trie = trie_state - .storage - .get_mut(hashed_acc_addr) - .context(format!( - "missing account storage trie {:x}", - hashed_acc_addr - ))?; - - for (key, val) in storage_writes { - let slot = TrieKey::from_hash(hash(key.into_nibbles().bytes_be())); - // If we are writing a zero, then we actually need to perform a delete. - match val == &ZERO_STORAGE_SLOT_VAL_RLPED { - false => { - storage_trie.insert(slot, val.clone()).context(format!( - "at slot {:?} with value {}", - slot, - U512::from_big_endian(val.as_slice()) - ))?; - } - true => { - if let Some(remaining_slot_key) = - delete_node_and_report_remaining_key_if_branch_collapsed( - storage_trie.as_mut_hashed_partial_trie_unchecked(), - &slot, - )? - { - out.additional_storage_trie_paths_to_not_hash - .entry(*hashed_acc_addr) - .or_default() - .push(remaining_slot_key); - } - } - }; - } - } - - for (addr, state_write) in &deltas.state_writes { - // If the account was created, then it will not exist in the trie yet. - let is_created = !trie_state.state.contains_address(*addr); - let mut account = trie_state.state.get_by_address(*addr).unwrap_or_default(); - - state_write.apply_writes_to_state_node(&mut account, &hash(addr), &trie_state.storage)?; - - trie_state.state.insert_by_address(*addr, account)?; - - if is_created { - // If the account did not exist prior this transaction, we - // need to make sure the transaction didn't revert. - - // We will check the status of the last receipt that attempted to create the - // account in this batch. - let last_creation_receipt = &meta - .iter() - .rev() - .find(|tx| tx.created_accounts.contains(addr)) - .expect("We should have found a matching transaction") - .receipt_node_bytes; - - let (_, _, receipt) = decode_receipt(last_creation_receipt) - .map_err(|_| anyhow!("couldn't RLP-decode receipt node bytes"))?; - - if !receipt.status { - // The transaction failed, hence any created account should be removed. - if let Some(remaining_account_key) = trie_state.state.reporting_remove(*addr)? { - out.additional_state_trie_paths_to_not_hash - .push(remaining_account_key); - trie_state.storage.remove(&hash(addr)); - continue; - } - } - } - } - - // Remove any accounts that self-destructed. - for addr in deltas.self_destructed_accounts.iter() { - trie_state.storage.remove(&hash(addr)); - - if let Some(remaining_account_key) = trie_state.state.reporting_remove(*addr)? { - out.additional_state_trie_paths_to_not_hash - .push(remaining_account_key); - } - } - - Ok(out) -} - -fn get_trie_trace(trie: &HashedPartialTrie, k: &Nibbles) -> TriePath { - path_for_query(trie, *k, true).collect() -} - -/// If a branch collapse occurred after a delete, then we must ensure that -/// the other single child that remains also is not hashed when passed into -/// plonky2. Returns the key to the remaining child if a collapse occurred. -pub fn delete_node_and_report_remaining_key_if_branch_collapsed( - trie: &mut HashedPartialTrie, - key: &TrieKey, -) -> Result, TrieOpError> { - let key = key.into_nibbles(); - let old_trace = get_trie_trace(trie, &key); - trie.delete(key)?; - let new_trace = get_trie_trace(trie, &key); - Ok( - node_deletion_resulted_in_a_branch_collapse(&old_trace, &new_trace) - .map(TrieKey::from_nibbles), - ) -} - -/// Comparing the path of the deleted key before and after the deletion, -/// determine if the deletion resulted in a branch collapsing into a leaf or -/// extension node, and return the path to the remaining child if this -/// occurred. -fn node_deletion_resulted_in_a_branch_collapse( - old_path: &TriePath, - new_path: &TriePath, -) -> Option { - // Collapse requires at least 2 nodes. - if old_path.0.len() < 2 { - return None; - } - - // If the node path length decreased after the delete, then a collapse occurred. - // As an aside, note that while it's true that the branch could have collapsed - // into an extension node with multiple nodes below it, the query logic will - // always stop at most one node after the keys diverge, which guarantees that - // the new trie path will always be shorter if a collapse occurred. - let branch_collapse_occurred = old_path.0.len() > new_path.0.len(); - - // Now we need to determine the key of the only remaining node after the - // collapse. - branch_collapse_occurred.then(|| new_path.iter().into_key()) -} - -/// The withdrawals are always in the final ir payload. -fn add_withdrawals_to_txns( - txn_ir: &mut [GenerationInputs], - final_trie_state: &mut PartialTrieState< - impl StateTrie + Clone + TryIntoBounds, - >, - mut withdrawals: Vec<(Address, U256)>, -) -> anyhow::Result<()> { - // Scale withdrawals amounts. - for (_addr, amt) in withdrawals.iter_mut() { - *amt = eth_to_gwei(*amt) - } - - let withdrawals_with_hashed_addrs_iter = || { - withdrawals - .iter() - .map(|(addr, v)| (*addr, hash(addr.as_bytes()), *v)) - }; - - let last_inputs = txn_ir - .last_mut() - .expect("We cannot have an empty list of payloads."); - - if last_inputs.signed_txns.is_empty() { - let mut state_trie = final_trie_state.state.clone(); - state_trie.trim_to( - // This is a dummy payload, hence it does not contain yet - // state accesses to the withdrawal addresses. - withdrawals - .iter() - .map(|(addr, _)| *addr) - .chain(match last_inputs.txn_number_before == 0.into() { - // We need to include the beacon roots contract as this payload is at the - // start of the block execution. - true => Some(BEACON_ROOTS_CONTRACT_ADDRESS), - false => None, - }) - .map(TrieKey::from_address), - )?; - last_inputs.tries.state_trie = state_trie.try_into()?; - } - - update_trie_state_from_withdrawals( - withdrawals_with_hashed_addrs_iter(), - &mut final_trie_state.state, - )?; - - last_inputs.withdrawals = withdrawals; - last_inputs.trie_roots_after.state_root = final_trie_state.state.clone().try_into()?.hash(); - - Ok(()) -} - -/// Withdrawals update balances in the account trie, so we need to update -/// our local trie state. -fn update_trie_state_from_withdrawals<'a>( - withdrawals: impl IntoIterator + 'a, - state: &mut impl StateTrie, -) -> anyhow::Result<()> { - for (addr, h_addr, amt) in withdrawals { - let mut acc_data = state.get_by_address(addr).context(format!( - "No account present at {addr:x} (hashed: {h_addr:x}) to withdraw {amt} Gwei from!" - ))?; - - acc_data.balance += amt; - - state - .insert_by_address(addr, acc_data) - // TODO(0xaatif): https://github.com/0xPolygonZero/zk_evm/issues/275 - // Add an entry API - .expect("insert must succeed with the same key as a successful `get`"); - } - - Ok(()) -} - -/// Processes a single transaction in the trace. -fn process_txn_info( - txn_range: Range, - is_initial_payload: bool, - txn_info: ProcessedTxnBatchInfo, - curr_block_tries: &mut PartialTrieState< - impl StateTrie + Clone + TryIntoBounds, - >, - extra_data: &mut ExtraBlockData, - other_data: &OtherBlockData, - use_burn_target: bool, -) -> anyhow::Result> { - log::trace!( - "Generating proof IR for txn {} through {}...", - txn_range.start, - txn_range.end - 1 - ); - - init_any_needed_empty_storage_tries( - &mut curr_block_tries.storage, - txn_info.nodes_used_by_txn.storage_accesses.keys(), - &txn_info.nodes_used_by_txn.accts_with_unaccessed_storage, - ); - - // For each non-dummy txn, we increment `txn_number_after` and - // update `gas_used_after` accordingly. - extra_data.txn_number_after += txn_info.meta.len().into(); - extra_data.gas_used_after += txn_info.meta.iter().map(|i| i.gas_used).sum::().into(); - - // Because we need to run delta application before creating the minimal - // sub-tries (we need to detect if deletes collapsed any branches), we need to - // do this clone every iteration. - let tries_at_start_of_txn = curr_block_tries.clone(); - - for (i, meta) in txn_info.meta.iter().enumerate() { - update_txn_and_receipt_tries( - curr_block_tries, - meta, - extra_data.txn_number_before.as_usize() + i, - )?; - } - - let mut delta_out = apply_deltas_to_trie_state( - curr_block_tries, - &txn_info.nodes_used_by_txn, - &txn_info.meta, - )?; - - let nodes_used_by_txn = if is_initial_payload { - let mut nodes_used = txn_info.nodes_used_by_txn; - update_beacon_block_root_contract_storage( - curr_block_tries, - &mut delta_out, - &mut nodes_used, - &other_data.b_data.b_meta, - )?; - - nodes_used - } else { - txn_info.nodes_used_by_txn - }; - - let tries = create_minimal_partial_tries_needed_by_txn( - &tries_at_start_of_txn, - &nodes_used_by_txn, - txn_range, - delta_out, - )?; - - let burn_addr = match use_burn_target { - // TODO: https://github.com/0xPolygonZero/zk_evm/issues/565 - // Retrieve the actual burn address from `cdk-erigon`. - true => Some(H160::zero()), - false => None, - }; - let gen_inputs = GenerationInputs { - txn_number_before: extra_data.txn_number_before, - burn_addr, - gas_used_before: extra_data.gas_used_before, - gas_used_after: extra_data.gas_used_after, - signed_txns: txn_info - .meta - .iter() - .filter_map(|t| t.txn_bytes.clone()) - .collect::>(), - withdrawals: Vec::default(), /* Only ever set in a dummy txn at the end of - * the block (see `[add_withdrawals_to_txns]` - * for more info). */ - tries, - trie_roots_after: TrieRoots { - state_root: curr_block_tries.state.clone().try_into()?.hash(), - transactions_root: curr_block_tries.txn.root(), - receipts_root: curr_block_tries.receipt.root(), - }, - checkpoint_state_trie_root: extra_data.checkpoint_state_trie_root, - checkpoint_consolidated_hash: extra_data.checkpoint_consolidated_hash, - contract_code: txn_info - .contract_code_accessed - .into_iter() - .map(|code| (hash(&code), code)) - .collect(), - block_metadata: other_data.b_data.b_meta.clone(), - block_hashes: other_data.b_data.b_hashes.clone(), - ger_data: None, - }; - - // After processing a transaction, we update the remaining accumulators - // for the next transaction. - extra_data.txn_number_before = extra_data.txn_number_after; - extra_data.gas_used_before = extra_data.gas_used_after; - - Ok(gen_inputs) -} - -impl StateWrite { - fn apply_writes_to_state_node( - &self, - state_node: &mut AccountRlp, - h_addr: &H256, - acc_storage_tries: &HashMap, - ) -> anyhow::Result<()> { - let storage_root_hash_change = match self.storage_trie_change { - false => None, - true => { - let storage_trie = acc_storage_tries - .get(h_addr) - .context(format!("missing account storage trie {:x}", h_addr))?; - - Some(storage_trie.root()) - } - }; - - state_node.balance = self.balance.unwrap_or(state_node.balance); - state_node.nonce = self.nonce.unwrap_or(state_node.nonce); - state_node.storage_root = storage_root_hash_change.unwrap_or(state_node.storage_root); - state_node.code_hash = self.code_hash.unwrap_or(state_node.code_hash); - - Ok(()) - } -} - -// TODO!!!: We really need to be appending the empty storage tries to the base -// trie somewhere else! This is a big hack! -fn create_minimal_storage_partial_tries<'a>( - storage_tries: &HashMap, - accesses_per_account: impl IntoIterator)>, - additional_storage_trie_paths_to_not_hash: &HashMap>, -) -> anyhow::Result> { - accesses_per_account - .into_iter() - .map(|(h_addr, mem_accesses)| { - // Guaranteed to exist due to calling `init_any_needed_empty_storage_tries` - // earlier on. - let base_storage_trie = &storage_tries[h_addr]; - - let storage_slots_to_not_hash = mem_accesses.iter().cloned().chain( - additional_storage_trie_paths_to_not_hash - .get(h_addr) - .into_iter() - .flat_map(|slots| slots.iter().cloned()), - ); - - let partial_storage_trie = create_trie_subset_wrapped( - base_storage_trie.as_hashed_partial_trie(), - storage_slots_to_not_hash, - TrieType::Storage, - )?; - - Ok((*h_addr, partial_storage_trie)) - }) - .collect() -} - -fn create_trie_subset_wrapped( - trie: &HashedPartialTrie, - accesses: impl IntoIterator, - trie_type: TrieType, -) -> anyhow::Result { - mpt_trie::trie_subsets::create_trie_subset( - trie, - accesses.into_iter().map(TrieKey::into_nibbles), - ) - .context(format!("missing keys when creating {}", trie_type)) -} - -fn eth_to_gwei(eth: U256) -> U256 { - // 1 ether = 10^9 gwei. - eth * U256::from(10).pow(9.into()) -} - -// This is just `rlp(0)`. -const ZERO_STORAGE_SLOT_VAL_RLPED: [u8; 1] = [128]; - -/// Aid for error context. -#[derive(Debug, strum::Display)] -#[allow(missing_docs)] -enum TrieType { - Storage, - Receipt, - Txn, -} diff --git a/trace_decoder/src/interface.rs b/trace_decoder/src/interface.rs index 55ae5eaf0..901fef89a 100644 --- a/trace_decoder/src/interface.rs +++ b/trace_decoder/src/interface.rs @@ -174,6 +174,10 @@ pub struct OtherBlockData { pub checkpoint_state_trie_root: H256, /// Consolidated block hashes at the checkpoint. pub checkpoint_consolidated_hash: [Field; NUM_HASH_OUT_ELTS], + /// Address where the burnt fees are stored. + /// + /// Only used if the `cfg_erigon` feature is activated. + pub burn_addr: Option
, } /// Data that is specific to a block and is constant for all txns in a given diff --git a/trace_decoder/src/lib.rs b/trace_decoder/src/lib.rs index 8c54eea8e..fba82d8f7 100644 --- a/trace_decoder/src/lib.rs +++ b/trace_decoder/src/lib.rs @@ -41,6 +41,8 @@ #![warn(missing_debug_implementations)] #![warn(missing_docs)] +zk_evm_common::check_chain_features!(); + /// Over RPC, ethereum nodes expose their tries as a series of binary /// [`wire::Instruction`]s in a node-dependant format. /// diff --git a/trace_decoder/tests/consistent-with-header.rs b/trace_decoder/tests/consistent-with-header.rs index 0cd477680..f82027e82 100644 --- a/trace_decoder/tests/consistent-with-header.rs +++ b/trace_decoder/tests/consistent-with-header.rs @@ -23,7 +23,7 @@ fn main() -> anyhow::Result<()> { } in cases()? { trials.push(Trial::test(format!("{name}@{batch_size}"), move || { - let gen_inputs = trace_decoder::entrypoint(trace, other.clone(), batch_size, false) + let gen_inputs = trace_decoder::entrypoint(trace, other.clone(), batch_size) .map_err(|e| format!("{e:?}"))?; // get the full cause chain check!(gen_inputs.len() >= 2); check!( diff --git a/trace_decoder/tests/simulate-execution.rs b/trace_decoder/tests/simulate-execution.rs index 080a02c62..c4cbe53b2 100644 --- a/trace_decoder/tests/simulate-execution.rs +++ b/trace_decoder/tests/simulate-execution.rs @@ -19,7 +19,7 @@ fn main() -> anyhow::Result<()> { other, } in cases()? { - let gen_inputs = trace_decoder::entrypoint(trace, other, batch_size, false).context( + let gen_inputs = trace_decoder::entrypoint(trace, other, batch_size).context( format!("error in `trace_decoder` for {name} at batch size {batch_size}"), )?; for (ix, gi) in gen_inputs.into_iter().enumerate() { diff --git a/zero_bin/common/Cargo.toml b/zero_bin/common/Cargo.toml index c66397ca1..1b69be922 100644 --- a/zero_bin/common/Cargo.toml +++ b/zero_bin/common/Cargo.toml @@ -33,6 +33,7 @@ directories = "5.0.1" # Local dependencies evm_arithmetization = { workspace = true } proof_gen = { workspace = true } +zk_evm_common = { workspace = true } [build-dependencies] anyhow = { workspace = true } @@ -50,6 +51,10 @@ cdk_erigon = [ "evm_arithmetization/cdk_erigon", "proof_gen/cdk_erigon", ] +polygon_pos = [ + "evm_arithmetization/polygon_pos", + "proof_gen/polygon_pos", +] [lints] workspace = true diff --git a/zero_bin/common/src/lib.rs b/zero_bin/common/src/lib.rs index d810ecb53..890558de6 100644 --- a/zero_bin/common/src/lib.rs +++ b/zero_bin/common/src/lib.rs @@ -1,3 +1,5 @@ +zk_evm_common::check_chain_features!(); + pub mod block_interval; pub mod debug_utils; pub mod env; diff --git a/zero_bin/leader/Cargo.toml b/zero_bin/leader/Cargo.toml index a0643be42..27d22a347 100644 --- a/zero_bin/leader/Cargo.toml +++ b/zero_bin/leader/Cargo.toml @@ -31,6 +31,7 @@ proof_gen = { workspace = true } prover = { workspace = true } rpc = { workspace = true } zero_bin_common = { workspace = true } +zk_evm_common = { workspace = true } [features] default = ["eth_mainnet"] @@ -50,6 +51,14 @@ cdk_erigon = [ "rpc/cdk_erigon", "zero_bin_common/cdk_erigon", ] +polygon_pos = [ + "evm_arithmetization/polygon_pos", + "ops/polygon_pos", + "proof_gen/polygon_pos", + "prover/polygon_pos", + "rpc/polygon_pos", + "zero_bin_common/polygon_pos", +] [build-dependencies] cargo_metadata = { workspace = true } diff --git a/zero_bin/leader/src/main.rs b/zero_bin/leader/src/main.rs index b230009cc..61ffb98ce 100644 --- a/zero_bin/leader/src/main.rs +++ b/zero_bin/leader/src/main.rs @@ -1,3 +1,5 @@ +zk_evm_common::check_chain_features!(); + use std::env; use std::sync::Arc; diff --git a/zero_bin/ops/Cargo.toml b/zero_bin/ops/Cargo.toml index 14b59eadd..4e49a3ae6 100644 --- a/zero_bin/ops/Cargo.toml +++ b/zero_bin/ops/Cargo.toml @@ -18,6 +18,7 @@ tracing = { workspace = true } evm_arithmetization = { workspace = true } proof_gen = { workspace = true } zero_bin_common = { workspace = true } +zk_evm_common = { workspace = true } [features] default = ["eth_mainnet"] @@ -31,3 +32,8 @@ cdk_erigon = [ "proof_gen/cdk_erigon", "zero_bin_common/cdk_erigon", ] +polygon_pos = [ + "evm_arithmetization/polygon_pos", + "proof_gen/polygon_pos", + "zero_bin_common/polygon_pos", +] diff --git a/zero_bin/ops/src/lib.rs b/zero_bin/ops/src/lib.rs index d8d884d8d..3a6d3854c 100644 --- a/zero_bin/ops/src/lib.rs +++ b/zero_bin/ops/src/lib.rs @@ -1,3 +1,5 @@ +zk_evm_common::check_chain_features!(); + use std::time::Instant; use evm_arithmetization::generation::TrimmedGenerationInputs; diff --git a/zero_bin/prover/Cargo.toml b/zero_bin/prover/Cargo.toml index fea054b88..a2ad4ccb4 100644 --- a/zero_bin/prover/Cargo.toml +++ b/zero_bin/prover/Cargo.toml @@ -29,22 +29,32 @@ evm_arithmetization = { workspace = true } proof_gen = { workspace = true } trace_decoder = { workspace = true } zero_bin_common = { workspace = true } +zk_evm_common = { workspace = true } [features] default = ["eth_mainnet"] eth_mainnet = [ "evm_arithmetization/eth_mainnet", + "ops/eth_mainnet", "proof_gen/eth_mainnet", "trace_decoder/eth_mainnet", "zero_bin_common/eth_mainnet", ] cdk_erigon = [ "evm_arithmetization/cdk_erigon", + "ops/cdk_erigon", "proof_gen/cdk_erigon", "trace_decoder/cdk_erigon", "zero_bin_common/cdk_erigon", ] +polygon_pos = [ + "evm_arithmetization/polygon_pos", + "ops/polygon_pos", + "proof_gen/polygon_pos", + "trace_decoder/polygon_pos", + "zero_bin_common/polygon_pos", +] [lints] workspace = true diff --git a/zero_bin/prover/src/lib.rs b/zero_bin/prover/src/lib.rs index f48e14a8c..29bf42127 100644 --- a/zero_bin/prover/src/lib.rs +++ b/zero_bin/prover/src/lib.rs @@ -1,3 +1,5 @@ +zk_evm_common::check_chain_features!(); + pub mod cli; use std::future::Future; @@ -73,13 +75,8 @@ impl BlockProverInput { let block_number = self.get_block_number(); - let use_burn_addr = cfg!(feature = "cdk_erigon"); - let block_generation_inputs = trace_decoder::entrypoint( - self.block_trace, - self.other_data, - batch_size, - use_burn_addr, - )?; + let block_generation_inputs = + trace_decoder::entrypoint(self.block_trace, self.other_data, batch_size)?; // Create segment proof. let seg_prove_ops = ops::SegmentProof { @@ -168,13 +165,8 @@ impl BlockProverInput { let block_number = self.get_block_number(); info!("Testing witness generation for block {block_number}."); - let use_burn_addr = cfg!(feature = "cdk_erigon"); - let block_generation_inputs = trace_decoder::entrypoint( - self.block_trace, - self.other_data, - batch_size, - use_burn_addr, - )?; + let block_generation_inputs = + trace_decoder::entrypoint(self.block_trace, self.other_data, batch_size)?; let seg_ops = ops::SegmentProofTestOnly { save_inputs_on_error, diff --git a/zero_bin/rpc/Cargo.toml b/zero_bin/rpc/Cargo.toml index f47586cd3..c694335d4 100644 --- a/zero_bin/rpc/Cargo.toml +++ b/zero_bin/rpc/Cargo.toml @@ -34,6 +34,7 @@ proof_gen = { workspace = true } prover = { workspace = true } trace_decoder = { workspace = true } zero_bin_common = { workspace = true } +zk_evm_common = { workspace = true } [build-dependencies] anyhow = { workspace = true } @@ -56,3 +57,9 @@ cdk_erigon = [ "trace_decoder/cdk_erigon", "zero_bin_common/cdk_erigon", ] +polygon_pos = [ + "evm_arithmetization/polygon_pos", + "prover/polygon_pos", + "trace_decoder/polygon_pos", + "zero_bin_common/polygon_pos", +] diff --git a/zero_bin/rpc/src/lib.rs b/zero_bin/rpc/src/lib.rs index 9da6862f3..87a581a14 100644 --- a/zero_bin/rpc/src/lib.rs +++ b/zero_bin/rpc/src/lib.rs @@ -1,7 +1,10 @@ +zk_evm_common::check_chain_features!(); + use std::sync::Arc; +use __compat_primitive_types::{H256, U256}; use alloy::{ - primitives::{Bytes, FixedBytes, B256}, + primitives::{Address, Bytes, FixedBytes, B256}, providers::Provider, rpc::types::eth::{BlockId, BlockTransactionsKind, Withdrawal}, transports::Transport, @@ -241,28 +244,48 @@ where .compat(), block_gaslimit: target_block.header.gas_limit.into(), block_chain_id: chain_id.into(), - block_base_fee: target_block - .header - .base_fee_per_gas - .context("target block is missing field `base_fee_per_gas`")? - .into(), + block_base_fee: if !cfg!(feature = "cdk_erigon") { + target_block + .header + .base_fee_per_gas + .context("target block is missing field `base_fee_per_gas`")? + .into() + } else { + target_block + .header + .base_fee_per_gas + .unwrap_or_default() // `baseFee` may be disabled to enable 0 price calls (EIP-1559) + .into() + }, block_gas_used: target_block.header.gas_used.into(), block_bloom: target_block.header.logs_bloom.compat(), - parent_beacon_block_root: target_block - .header - .parent_beacon_block_root - .context("target block is missing field `parent_beacon_block_root`")? - .compat(), - block_blob_gas_used: target_block - .header - .blob_gas_used - .context("target block is missing field `blob_gas_used`")? - .into(), - block_excess_blob_gas: target_block - .header - .excess_blob_gas - .context("target block is missing field `excess_blob_gas`")? - .into(), + parent_beacon_block_root: if cfg!(feature = "eth_mainnet") { + target_block + .header + .parent_beacon_block_root + .context("target block is missing field `parent_beacon_block_root`")? + .compat() + } else { + H256::zero() + }, + block_blob_gas_used: if cfg!(feature = "eth_mainnet") { + target_block + .header + .blob_gas_used + .context("target block is missing field `blob_gas_used`")? + .into() + } else { + U256::zero() + }, + block_excess_blob_gas: if cfg!(feature = "eth_mainnet") { + target_block + .header + .excess_blob_gas + .context("target block is missing field `excess_blob_gas`")? + .into() + } else { + U256::zero() + }, }, b_hashes: BlockHashes { prev_hashes: prev_hashes.map(|it| it.compat()).into(), @@ -281,6 +304,13 @@ where }, checkpoint_state_trie_root: checkpoint_state_trie_root.compat(), checkpoint_consolidated_hash: consolidate_hashes::(&checkpoint_prev_hashes), + burn_addr: if cfg!(feature = "cdk_erigon") { + // TODO: https://github.com/0xPolygonZero/zk_evm/issues/565 + // Retrieve the actual burn address from `cdk-erigon`. + Some(Address::ZERO.compat()) + } else { + None + }, }; Ok(other_data) } diff --git a/zero_bin/rpc/src/main.rs b/zero_bin/rpc/src/main.rs index a88c8256c..12594877a 100644 --- a/zero_bin/rpc/src/main.rs +++ b/zero_bin/rpc/src/main.rs @@ -167,12 +167,10 @@ impl Cli { block_number ))?; - let use_burn_addr = cfg!(feature = "cdk_erigon"); let generation_inputs = trace_decoder::entrypoint( block_prover_input.block_trace, block_prover_input.other_data, batch_size, - use_burn_addr, )?; if let Some(index) = tx_info.transaction_index { diff --git a/zero_bin/rpc/src/native/state.rs b/zero_bin/rpc/src/native/state.rs index 24c7b1214..a61f73e01 100644 --- a/zero_bin/rpc/src/native/state.rs +++ b/zero_bin/rpc/src/native/state.rs @@ -3,14 +3,13 @@ use std::sync::Arc; use alloy::primitives::Bytes; use alloy::{ - primitives::{keccak256, Address, StorageKey, B256, U256}, + primitives::{keccak256, Address, StorageKey, B256}, providers::Provider, rpc::types::eth::{Block, BlockTransactionsKind, EIP1186AccountProofResponse}, transports::Transport, }; use alloy_compat::Compat; use anyhow::Context as _; -use evm_arithmetization::testing_utils::{BEACON_ROOTS_CONTRACT_STATE_KEY, HISTORY_BUFFER_LENGTH}; use futures::future::{try_join, try_join_all}; use mpt_trie::{builder::PartialTrieBuilder, partial_trie::HashedPartialTrie}; use trace_decoder::{ @@ -65,6 +64,7 @@ pub fn process_states_access( ) -> anyhow::Result>> { let mut state_access = HashMap::>::new(); + #[cfg(feature = "eth_mainnet")] insert_beacon_roots_update(&mut state_access, block)?; if let Some(w) = block.withdrawals.as_ref() { @@ -88,11 +88,17 @@ pub fn process_states_access( Ok(state_access) } +#[cfg(feature = "eth_mainnet")] /// Cancun HF specific, see . fn insert_beacon_roots_update( state_access: &mut HashMap>, block: &Block, ) -> anyhow::Result<()> { + use alloy::primitives::U256; + use evm_arithmetization::testing_utils::{ + BEACON_ROOTS_CONTRACT_STATE_KEY, HISTORY_BUFFER_LENGTH, + }; + let timestamp = U256::from(block.header.timestamp); let chunk = HISTORY_BUFFER_LENGTH.value.compat(); diff --git a/zero_bin/verifier/Cargo.toml b/zero_bin/verifier/Cargo.toml index 259c6d3f5..ff0458197 100644 --- a/zero_bin/verifier/Cargo.toml +++ b/zero_bin/verifier/Cargo.toml @@ -17,6 +17,7 @@ tracing-subscriber = { workspace = true } # Local dependencies proof_gen = { workspace = true } zero_bin_common = { workspace = true } +zk_evm_common = { workspace = true } [build-dependencies] anyhow = { workspace = true } @@ -34,3 +35,7 @@ cdk_erigon = [ "proof_gen/cdk_erigon", "zero_bin_common/cdk_erigon", ] +polygon_pos = [ + "proof_gen/polygon_pos", + "zero_bin_common/polygon_pos", +] diff --git a/zero_bin/verifier/src/main.rs b/zero_bin/verifier/src/main.rs index 30f6c9ab5..aa97d6087 100644 --- a/zero_bin/verifier/src/main.rs +++ b/zero_bin/verifier/src/main.rs @@ -1,3 +1,5 @@ +zk_evm_common::check_chain_features!(); + use std::env; use std::fs::File; diff --git a/zero_bin/worker/Cargo.toml b/zero_bin/worker/Cargo.toml index 0e7d80d0b..ffb762627 100644 --- a/zero_bin/worker/Cargo.toml +++ b/zero_bin/worker/Cargo.toml @@ -38,4 +38,8 @@ eth_mainnet = [ cdk_erigon = [ "ops/cdk_erigon", "zero_bin_common/cdk_erigon", -] \ No newline at end of file +] +polygon_pos = [ + "ops/polygon_pos", + "zero_bin_common/polygon_pos", +]