Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat:add rpc debug_traceCallMany #2974

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
10 changes: 10 additions & 0 deletions crates/client/src/rpc/impls/eth/debug.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,4 +77,14 @@ impl Debug for GethDebugHandler {
.trace_call(request, block_number, opts)
.map_err(|err| err.into())
}

fn debug_trace_call_many(
&self, requests: Vec<TransactionRequest>,
block_number: Option<BlockNumber>,
opts: Option<GethDebugTracingCallOptions>,
) -> JsonRpcResult<Vec<GethTrace>> {
self.inner
.trace_call_many(requests, block_number, opts)
.map_err(|err| err.into())
}
}
7 changes: 7 additions & 0 deletions crates/client/src/rpc/traits/eth_space/debug.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,11 @@ pub trait Debug {
&self, request: TransactionRequest, block_number: Option<BlockNumber>,
opts: Option<GethDebugTracingCallOptions>,
) -> JsonRpcResult<GethTrace>;

#[rpc(name = "debug_traceCallMany")]
fn debug_trace_call_many(
&self, requests: Vec<TransactionRequest>,
block_number: Option<BlockNumber>,
opts: Option<GethDebugTracingCallOptions>,
) -> JsonRpcResult<Vec<GethTrace>>;
}
7 changes: 7 additions & 0 deletions crates/rpc/rpc-eth-api/src/debug.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,11 @@ pub trait DebugApi {
&self, request: TransactionRequest, block_number: Option<BlockNumber>,
opts: Option<GethDebugTracingCallOptions>,
) -> RpcResult<GethTrace>;

#[method(name = "traceCallMany")]
async fn debug_trace_call_many(
&self, requests: Vec<TransactionRequest>,
block_number: Option<BlockNumber>,
opts: Option<GethDebugTracingCallOptions>,
) -> RpcResult<Vec<GethTrace>>;
}
102 changes: 102 additions & 0 deletions crates/rpc/rpc/src/debug.rs
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,99 @@ impl DebugApi {
Ok(res.trace.clone())
}

pub fn trace_call_many(
&self, requests: Vec<TransactionRequest>,
block_number: Option<BlockNumber>,
opts: Option<GethDebugTracingCallOptions>,
) -> Result<Vec<GethTrace>, CoreError> {
let opts = opts.unwrap_or_default();
let block_num = block_number.unwrap_or_default();

let epoch_num = self
.get_block_epoch_num(block_num)
.map_err(|err| CoreError::Msg(err))?;

// validate epoch state
self.consensus_graph()
.validate_stated_epoch(&EpochNumber::Number(epoch_num))
.map_err(|err| CoreError::Msg(err))?;

let epoch_block_hashes = self
.consensus_graph()
.get_block_hashes_by_epoch(EpochNumber::Number(epoch_num))
.map_err(|err| CoreError::Msg(err))?;
let epoch_id = epoch_block_hashes
.last()
.ok_or(CoreError::Msg("should have block hash".to_string()))?;

// construct blocks from call_request
let chain_id = self.consensus.best_chain_id();

// construct transactions
let mut transactions = Vec::with_capacity(requests.len());
for mut request in requests {
if request.from.is_none() {
return Err(CoreError::InvalidParam(
"from is required".to_string(),
Default::default(),
));
}

// nonce auto fill
if request.nonce.is_none() {
let nonce = self.consensus_graph().next_nonce(
request.from.unwrap().with_evm_space(),
BlockHashOrEpochNumber::EpochNumber(EpochNumber::Number(
epoch_num,
)),
"num",
)?;
request.nonce = Some(nonce);
}

let signed_tx = request.sign_call(
chain_id.in_evm_space(),
self.max_estimation_gas_limit,
)?;

transactions.push(Arc::new(signed_tx));
}

let epoch_blocks = self
.consensus_graph()
.data_man
.blocks_by_hash_list(
&epoch_block_hashes,
true, /* update_cache */
)
.ok_or(CoreError::Msg("blocks should exist".to_string()))?;
let pivot_block = epoch_blocks
.last()
.ok_or(CoreError::Msg("should have block".to_string()))?;

let header = BlockHeaderBuilder::new()
.with_base_price(pivot_block.block_header.base_price())
.with_parent_hash(pivot_block.block_header.hash())
.with_height(epoch_num + 1)
.with_timestamp(pivot_block.block_header.timestamp() + 1)
.with_gas_limit(*pivot_block.block_header.gas_limit())
.build();
let block = Block::new(header, transactions);
let blocks: Vec<Arc<Block>> = vec![Arc::new(block)];

let traces = self.consensus_graph().collect_blocks_geth_trace(
*epoch_id,
epoch_num,
&blocks,
opts.tracing_options,
None,
)?;

let result = traces.iter().map(|val| val.trace.clone()).collect();

Ok(result)
}

pub fn trace_block_by_num(
&self, block_num: u64, opts: Option<GethDebugTracingOptions>,
) -> Result<Vec<TraceResult>, CoreError> {
Expand Down Expand Up @@ -287,4 +380,13 @@ impl DebugApiServer for DebugApi {
self.trace_call(request, block_number, opts)
.map_err(|e| e.into())
}

async fn debug_trace_call_many(
&self, requests: Vec<TransactionRequest>,
block_number: Option<BlockNumber>,
opts: Option<GethDebugTracingCallOptions>,
) -> RpcResult<Vec<GethTrace>> {
self.trace_call_many(requests, block_number, opts)
.map_err(|e| e.into())
}
}