Skip to content

Commit

Permalink
bus-mapping: implement history_hashes and prev. state root (scroll-te…
Browse files Browse the repository at this point in the history
  • Loading branch information
pinkiebell authored Nov 5, 2022
1 parent b87a9d2 commit 93abf02
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 11 deletions.
60 changes: 51 additions & 9 deletions bus-mapping/src/circuit_input_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ pub use block::{Block, BlockContext};
pub use call::{Call, CallContext, CallKind};
use core::fmt::Debug;
use eth_types::sign_types::{pk_bytes_le, pk_bytes_swap_endianness, SignData};
use eth_types::ToWord;
use eth_types::{self, geth_types, Address, GethExecStep, GethExecTrace, Word};
use ethers_providers::JsonRpcClient;
pub use execution::{
Expand Down Expand Up @@ -350,7 +351,6 @@ type EthBlock = eth_types::Block<eth_types::Transaction>;
pub struct BuilderClient<P: JsonRpcClient> {
cli: GethClient<P>,
chain_id: Word,
history_hashes: Vec<Word>,
circuits_params: CircuitsParams,
}

Expand All @@ -365,21 +365,52 @@ impl<P: JsonRpcClient> BuilderClient<P> {
Ok(Self {
cli: client,
chain_id: chain_id.into(),
// TODO: Get history hashes
history_hashes: Vec::new(),
circuits_params,
})
}

/// Step 1. Query geth for Block, Txs and TxExecTraces
/// Step 1. Query geth for Block, Txs, TxExecTraces, history block hashes
/// and previous state root.
pub async fn get_block(
&self,
block_num: u64,
) -> Result<(EthBlock, Vec<eth_types::GethExecTrace>), Error> {
) -> Result<(EthBlock, Vec<eth_types::GethExecTrace>, Vec<Word>, Word), Error> {
let eth_block = self.cli.get_block_by_number(block_num.into()).await?;
let geth_traces = self.cli.trace_block_by_number(block_num.into()).await?;

Ok((eth_block, geth_traces))
// fetch up to 256 blocks
let mut n_blocks = std::cmp::min(256, block_num as usize);
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?;

// set the previous state root
if prev_state_root.is_none() {
prev_state_root = Some(header.state_root.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;

// continue
next_hash = header.parent_hash;
}

Ok((
eth_block,
geth_traces,
history_hashes,
prev_state_root.unwrap_or_default(),
))
}

/// Step 2. Get State Accesses from TxExecTraces
Expand Down Expand Up @@ -480,10 +511,13 @@ impl<P: JsonRpcClient> BuilderClient<P> {
code_db: CodeDB,
eth_block: &EthBlock,
geth_traces: &[eth_types::GethExecTrace],
history_hashes: Vec<Word>,
prev_state_root: Word,
) -> Result<CircuitInputBuilder, Error> {
let block = Block::new(
self.chain_id,
self.history_hashes.clone(),
history_hashes,
prev_state_root,
eth_block,
self.circuits_params.clone(),
)?;
Expand All @@ -503,11 +537,19 @@ impl<P: JsonRpcClient> BuilderClient<P> {
),
Error,
> {
let (eth_block, geth_traces) = self.get_block(block_num).await?;
let (eth_block, geth_traces, history_hashes, prev_state_root) =
self.get_block(block_num).await?;
let access_set = self.get_state_accesses(&eth_block, &geth_traces)?;
let (proofs, codes) = self.get_state(block_num, access_set).await?;
let (state_db, code_db) = self.build_state_code_db(proofs, codes);
let builder = self.gen_inputs_from_state(state_db, code_db, &eth_block, &geth_traces)?;
let builder = self.gen_inputs_from_state(
state_db,
code_db,
&eth_block,
&geth_traces,
history_hashes,
prev_state_root,
)?;
Ok((builder, eth_block))
}
}
4 changes: 4 additions & 0 deletions bus-mapping/src/circuit_input_builder/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@ pub struct Block {
pub difficulty: Word,
/// base fee
pub base_fee: Word,
/// State root of the previous block
pub prev_state_root: Word,
/// Container of operations done in this block.
pub container: OperationContainer,
/// Transactions contained in the block
Expand All @@ -93,6 +95,7 @@ impl Block {
pub fn new<TX>(
chain_id: Word,
history_hashes: Vec<Word>,
prev_state_root: Word,
eth_block: &eth_types::Block<TX>,
circuits_params: CircuitsParams,
) -> Result<Self, Error> {
Expand All @@ -118,6 +121,7 @@ impl Block {
timestamp: eth_block.timestamp,
difficulty: eth_block.difficulty,
base_fee: eth_block.base_fee_per_gas.unwrap_or_default(),
prev_state_root,
container: OperationContainer::new(),
txs: Vec::new(),
block_steps: BlockSteps {
Expand Down
1 change: 1 addition & 0 deletions bus-mapping/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ impl BlockData {
Block::new(
self.chain_id,
self.history_hashes.clone(),
Word::default(),
&self.eth_block,
self.circuits_params.clone(),
)
Expand Down
12 changes: 10 additions & 2 deletions integration-tests/tests/circuit_input_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ async fn test_circuit_input_builder_block(block_num: u64) {
.unwrap();

// 1. Query geth for Block, Txs and TxExecTraces
let (eth_block, geth_trace) = cli.get_block(block_num).await.unwrap();
let (eth_block, geth_trace, history_hashes, prev_state_root) =
cli.get_block(block_num).await.unwrap();

// 2. Get State Accesses from TxExecTraces
let access_set = cli.get_state_accesses(&eth_block, &geth_trace).unwrap();
Expand All @@ -38,7 +39,14 @@ async fn test_circuit_input_builder_block(block_num: u64) {
// 5. For each step in TxExecTraces, gen the associated ops and state
// circuit inputs
let builder = cli
.gen_inputs_from_state(state_db, code_db, &eth_block, &geth_trace)
.gen_inputs_from_state(
state_db,
code_db,
&eth_block,
&geth_trace,
history_hashes,
prev_state_root,
)
.unwrap();

trace!("CircuitInputBuilder: {:#?}", builder);
Expand Down

0 comments on commit 93abf02

Please sign in to comment.