Skip to content
This repository was 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
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
@@ -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"
58 changes: 44 additions & 14 deletions bus-mapping/src/circuit_input_builder.rs
Original file line number Diff line number Diff line change
@@ -26,22 +26,34 @@ use core::fmt::Debug;
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,
};
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},
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
@@ -707,26 +719,44 @@ impl<P: JsonRpcClient> BuilderClient<P> {
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();
}
}
}

Ok((