Skip to content
This repository has been archived by the owner on Jul 5, 2024. It is now read-only.

refactor: opti build circuit input by cache previous block hashes #1766

Open
wants to merge 1 commit into
base: main
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
1 change: 1 addition & 0 deletions Cargo.lock

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

3 changes: 3 additions & 0 deletions bus-mapping/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ strum = "0.24"
strum_macros = "0.24"
revm-precompile = { version = "=2.2.0", default-features = false, optional = true }

tokio = { version = "1.16.1", features = ["macros", "rt-multi-thread"] }
linked-hash-map = "0.5.6"

[dev-dependencies]
hex = "0.4.3"
pretty_assertions = "1.0.0"
Expand Down
58 changes: 44 additions & 14 deletions bus-mapping/src/circuit_input_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,22 +26,34 @@
use eth_types::{
self, geth_types,
sign_types::{pk_bytes_le, pk_bytes_swap_endianness, SignData},
Address, GethExecStep, GethExecTrace, ToWord, Word,
Address, GethExecStep, GethExecTrace, Hash, ToWord, Word, H160, H256,

Check warning on line 29 in bus-mapping/src/circuit_input_builder.rs

View workflow job for this annotation

GitHub Actions / Various lints

unused imports: `H160`, `Hash`

Check warning on line 29 in bus-mapping/src/circuit_input_builder.rs

View workflow job for this annotation

GitHub Actions / Linux Build

unused imports: `H160`, `Hash`
};
use ethers_providers::JsonRpcClient;
pub use execution::{
CopyDataType, CopyEvent, CopyStep, ExecState, ExecStep, ExpEvent, ExpStep, NumberOrHash,
};
pub use input_state_ref::CircuitInputStateRef;
use itertools::Itertools;
use lazy_static::lazy_static;
use linked_hash_map::LinkedHashMap;
use log::warn;
use std::{
collections::{HashMap, HashSet},
collections::{BTreeMap, HashMap},

Check warning on line 41 in bus-mapping/src/circuit_input_builder.rs

View workflow job for this annotation

GitHub Actions / Various lints

unused import: `BTreeMap`

Check warning on line 41 in bus-mapping/src/circuit_input_builder.rs

View workflow job for this annotation

GitHub Actions / Linux Build

unused import: `BTreeMap`
ops::Deref,
sync::Arc,
};
use tokio::sync::Mutex;
pub use transaction::{Transaction, TransactionContext};
pub use withdrawal::{Withdrawal, WithdrawalContext};

lazy_static! {
/// cached parent state_root.
pub static ref PARENT_STATE_ROOT: Arc<Mutex<Word>> = Arc::new(Mutex::new(Word::zero())) ;
/// cached <cur_block_hash, parent_hash>
pub static ref ANCESTOR_BLOCKS: Arc<Mutex<LinkedHashMap<H256, H256>>> =
Arc::new(Mutex::new(LinkedHashMap::new()));
}

/// Runtime Config
///
/// Default to mainnet block
Expand Down Expand Up @@ -516,7 +528,7 @@
/// Return all the keccak inputs used during the processing of the current
/// block.
pub fn keccak_inputs(block: &Block, code_db: &CodeDB) -> Result<Vec<Vec<u8>>, Error> {
let mut keccak_inputs: HashSet<Vec<u8>> = HashSet::new();

Check failure on line 531 in bus-mapping/src/circuit_input_builder.rs

View workflow job for this annotation

GitHub Actions / Various lints

cannot find type `HashSet` in this scope

Check failure on line 531 in bus-mapping/src/circuit_input_builder.rs

View workflow job for this annotation

GitHub Actions / Various lints

failed to resolve: use of undeclared type `HashSet`

Check failure on line 531 in bus-mapping/src/circuit_input_builder.rs

View workflow job for this annotation

GitHub Actions / Linux Build

cannot find type `HashSet` in this scope

Check failure on line 531 in bus-mapping/src/circuit_input_builder.rs

View workflow job for this annotation

GitHub Actions / Linux Build

failed to resolve: use of undeclared type `HashSet`

Check failure on line 531 in bus-mapping/src/circuit_input_builder.rs

View workflow job for this annotation

GitHub Actions / Light unit tests

cannot find type `HashSet` in this scope

Check failure on line 531 in bus-mapping/src/circuit_input_builder.rs

View workflow job for this annotation

GitHub Actions / Light unit tests

failed to resolve: use of undeclared type `HashSet`

Check failure on line 531 in bus-mapping/src/circuit_input_builder.rs

View workflow job for this annotation

GitHub Actions / Heavy unit tests

cannot find type `HashSet` in this scope

Check failure on line 531 in bus-mapping/src/circuit_input_builder.rs

View workflow job for this annotation

GitHub Actions / Heavy unit tests

failed to resolve: use of undeclared type `HashSet`
// Tx Circuit
let txs: Vec<geth_types::Transaction> = block.txs.iter().map(|tx| tx.deref().clone()).collect();
for input in keccak_inputs_tx_circuit(&txs, block.chain_id.as_u64())? {
Expand Down Expand Up @@ -707,26 +719,44 @@
let mut next_hash = eth_block.parent_hash;
let mut prev_state_root: Option<Word> = None;
let mut history_hashes = vec![Word::default(); n_blocks];

while n_blocks > 0 {
n_blocks -= 1;

// TODO: consider replacing it with `eth_getHeaderByHash`, it's faster
let header = self.cli.get_block_by_hash(next_hash).await?;
// Here we use cache-and-get: check if the parent_hash in cache, if not, query and cache
// it. Then we can obtain all it from cache.
let mut acestor_block_map = ANCESTOR_BLOCKS.lock().await;
if !acestor_block_map.contains_key(&next_hash) {
// TODO: consider replacing it with `eth_getHeaderByHash`, it's faster
let header = self.cli.get_block_by_hash(next_hash.clone()).await?;
let parent_hash = header.parent_hash;
acestor_block_map.insert(next_hash.clone(), parent_hash);

if prev_state_root.is_none() {
let mut parent_block = PARENT_STATE_ROOT.lock().await;
*parent_block = header.state_root.to_word();
}
}

// set the previous state root
// set the previous state root only for the latest parent header.
if prev_state_root.is_none() {
prev_state_root = Some(header.state_root.to_word());
let parent_block = PARENT_STATE_ROOT.lock().await;
prev_state_root = Some(parent_block.to_word());
}

// latest block hash is the last item
let block_hash = header
.hash
.ok_or(Error::EthTypeError(eth_types::Error::IncompleteBlock))?
.to_word();
history_hashes[n_blocks] = block_hash;
history_hashes[n_blocks] = next_hash.to_word();

// continue, naxt_hash = next_parent_hash
next_hash = *acestor_block_map.get(&next_hash).unwrap();

// continue
next_hash = header.parent_hash;
// remove the oldest block, as we at most need 256.
// For now, I've resize the map to 2*256, Here's some waste.
if acestor_block_map.len() > 2 * 256 {
for _ in 0..(acestor_block_map.len() - 256) {
// acestor_block_map.pop_front();
let value = acestor_block_map.pop_front();

Check warning on line 757 in bus-mapping/src/circuit_input_builder.rs

View workflow job for this annotation

GitHub Actions / Various lints

unused variable: `value`

Check warning on line 757 in bus-mapping/src/circuit_input_builder.rs

View workflow job for this annotation

GitHub Actions / Linux Build

unused variable: `value`
}
}
}

Ok((
Expand Down
Loading