Skip to content

Commit

Permalink
feat: block structlog retrieval (#682)
Browse files Browse the repository at this point in the history
* feat: use block structlogs retrieval

* fix: cleanup cli argumetns

* fix: error handling

* fix: error handling 2

* adjustments

* avoid CREATE/2

* fixes

* rename function

* remove support for CREATE/2
  • Loading branch information
atanmarko authored Oct 7, 2024
1 parent 10b6a22 commit c11d17d
Show file tree
Hide file tree
Showing 6 changed files with 199 additions and 304 deletions.
2 changes: 1 addition & 1 deletion zero/src/bin/leader/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ pub(crate) enum Command {
#[arg(long, short = 't', default_value = "jerigon")]
rpc_type: RpcType,
/// The source of jumpdest tables.
#[arg(short = 'j', long, default_value_ifs = [("rpc_type", "jerigon", "prover-simulation"), ("rpc_type", "native", "client-fetched-structlogs")], required = false)]
#[arg(short = 'j', long, default_value_ifs = [("rpc_type", "jerigon", "client-fetched-structlogs"), ("rpc_type", "native", "client-fetched-structlogs")], required = false)]
jumpdest_src: JumpdestSrc,
/// The block interval for which to generate a proof.
#[arg(long, short = 'i')]
Expand Down
2 changes: 1 addition & 1 deletion zero/src/bin/rpc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ struct RpcToolConfig {
#[arg(short = 't', long, default_value = "jerigon")]
rpc_type: RpcType,
/// The source of jumpdest tables.
#[arg(short = 'j', long, default_value_ifs = [("rpc_type", "jerigon", "prover-simulation"), ("rpc_type", "native", "client-fetched-structlogs")], required = false)]
#[arg(short = 'j', long, default_value_ifs = [("rpc_type", "jerigon", "client-fetched-structlogs"), ("rpc_type", "native", "client-fetched-structlogs")], required = false)]
jumpdest_src: JumpdestSrc,
/// Backoff in milliseconds for retry requests.
#[arg(long, default_value_t = 0)]
Expand Down
129 changes: 43 additions & 86 deletions zero/src/rpc/jerigon.rs
Original file line number Diff line number Diff line change
@@ -1,30 +1,25 @@
use core::iter::Iterator;
use std::collections::BTreeMap;
use std::ops::Deref as _;

use __compat_primitive_types::H160;
use alloy::eips::BlockNumberOrTag;
use alloy::{
providers::Provider,
rpc::types::{eth::BlockId, trace::geth::StructLog, Block, BlockTransactionsKind, Transaction},
rpc::types::{eth::BlockId, Block, BlockTransactionsKind},
transports::Transport,
};
use alloy_primitives::Address;
use anyhow::Context as _;
use evm_arithmetization::{jumpdest::JumpDestTableWitness, CodeDb};
use futures::stream::FuturesOrdered;
use futures::StreamExt as _;
use compat::Compat;
use evm_arithmetization::jumpdest::JumpDestTableWitness;
use serde::Deserialize;
use serde_json::json;
use trace_decoder::{BlockTrace, BlockTraceTriePreImages, CombinedPreImages, TxnInfo, TxnTrace};
use tracing::info;
use trace_decoder::{BlockTrace, BlockTraceTriePreImages, CombinedPreImages, TxnInfo};
use tracing::warn;

use super::{
fetch_other_block_data,
jumpdest::{self, get_normalized_structlog},
JumpdestSrc,
};
use super::{fetch_other_block_data, JumpdestSrc};
use crate::prover::BlockProverInput;
use crate::provider::CachedProvider;
use crate::rpc::jumpdest::{generate_jumpdest_table, get_block_normalized_structlogs};

/// Transaction traces retrieved from Erigon zeroTracer.
#[derive(Debug, Deserialize)]
pub struct ZeroTxResult {
Expand Down Expand Up @@ -67,30 +62,31 @@ where
.get_block(target_block_id, BlockTransactionsKind::Full)
.await?;

let jdts: Vec<Option<(JumpDestTableWitness, CodeDb)>> = match jumpdest_src {
let block_jumpdest_table_witnesses: Vec<Option<JumpDestTableWitness>> = match jumpdest_src {
JumpdestSrc::ProverSimulation => vec![None; tx_results.len()],
JumpdestSrc::ClientFetchedStructlogs => {
// In case of the error with retrieving structlogs from the server,
// continue without interruption. Equivalent to `ProverSimulation` case.
process_transactions(
&block,
cached_provider.get_provider().await?.deref(),
tx_results.iter().map(|TxnInfo { traces, meta: _ }| traces), // &tx_traces,
&tx_results,
)
.await?
.await
.unwrap_or_else(|e| {
warn!("failed to fetch server structlogs for block {target_block_id}: {e}");
Vec::new()
})
}
JumpdestSrc::ServerFetchedStructlogs => todo!("hybrid server bulk struct log retrieval/local jumpdest table generation not yet implemented"),
JumpdestSrc::Serverside => todo!(),
};

let mut code_db = CodeDb::default();
// weave in the JDTs
let txn_info = tx_results
.into_iter()
.zip(jdts)
.map(|(mut tx_info, jdt)| {
tx_info.meta.jumpdest_table = jdt.map(|(j, c)| {
code_db.extend(c);
j
});
.zip(block_jumpdest_table_witnesses)
.map(|(mut tx_info, jdtw)| {
tx_info.meta.jumpdest_table = jdtw;
tx_info
})
.collect();
Expand All @@ -106,81 +102,42 @@ where
.context("invalid hex returned from call to eth_getWitness")?,
}),
txn_info,
code_db,
code_db: Default::default(),
},
other_data,
})
}

/// Processes the transactions in the given block and updates the code db.
pub async fn process_transactions<'i, I, ProviderT, TransportT>(
/// Processes the transactions in the given block, generating jumpdest tables
/// and updates the code database
pub async fn process_transactions<'i, ProviderT, TransportT>(
block: &Block,
provider: &ProviderT,
tx_traces: I,
) -> anyhow::Result<Vec<Option<(JumpDestTableWitness, CodeDb)>>>
tx_results: &[TxnInfo],
) -> anyhow::Result<Vec<Option<JumpDestTableWitness>>>
where
ProviderT: Provider<TransportT>,
TransportT: Transport + Clone,
I: Iterator<Item = &'i BTreeMap<H160, TxnTrace>>,
{
let futures = block
let block_structlogs =
get_block_normalized_structlogs(provider, &BlockNumberOrTag::from(block.header.number))
.await?;

let tx_traces = tx_results
.iter()
.map(|tx| tx.traces.iter().map(|(h, t)| (h.compat(), t)));

let block_jumpdest_tables = block
.transactions
.as_transactions()
.context("No transactions in block")?
.context("no transactions in block")?
.iter()
.zip(block_structlogs)
.zip(tx_traces)
.map(|(tx, tx_trace)| process_transaction(provider, tx, tx_trace))
.collect::<FuturesOrdered<_>>();

futures
.collect::<Vec<_>>()
.await
.into_iter()
.collect::<Result<Vec<_>, _>>()
}

/// Processes the transaction with the given transaction hash and updates the
/// accounts state.
pub async fn process_transaction<ProviderT, TransportT>(
provider: &ProviderT,
tx: &Transaction,
tx_trace: &BTreeMap<H160, TxnTrace>,
) -> anyhow::Result<Option<(JumpDestTableWitness, CodeDb)>>
where
ProviderT: Provider<TransportT>,
TransportT: Transport + Clone,
{
let tx_traces = tx_trace
.iter()
.map(|(h, t)| (Address::from(h.to_fixed_bytes()), t.clone()))
.collect();

let structlog_opt: Option<Vec<StructLog>> = get_normalized_structlog(provider, &tx.hash)
.await
.ok()
.flatten();

let jc: Option<(JumpDestTableWitness, CodeDb)> = structlog_opt.and_then(|struct_log| {
jumpdest::generate_jumpdest_table(tx, &struct_log, &tx_traces).map_or_else(
|error| {
info!(
"{:#?}: JumpDestTable generation failed with reason: {}",
tx.hash, error
);
None
},
|(jdt, code_db)| {
info!(
"{:#?}: JumpDestTable generation succeeded with result: {}",
tx.hash, jdt
);
Some((jdt, code_db))
},
)
});

// TODO
// let jumpdest_table = jc.map(|(j, c)| j);
.map(|((tx, structlog), tx_trace)| {
structlog.and_then(|it| generate_jumpdest_table(tx, &it.1, tx_trace).ok())
})
.collect::<Vec<_>>();

Ok(jc)
Ok(block_jumpdest_tables)
}
Loading

0 comments on commit c11d17d

Please sign in to comment.