Skip to content

Commit

Permalink
fix: support additional eth call bundle args (paradigmxyz#9383)
Browse files Browse the repository at this point in the history
  • Loading branch information
mattsse authored and int88 committed Jul 9, 2024
1 parent 4138255 commit 0afc441
Show file tree
Hide file tree
Showing 6 changed files with 135 additions and 3 deletions.
3 changes: 3 additions & 0 deletions Cargo.lock

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

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -432,6 +432,7 @@ auto_impl = "1"
aquamarine = "0.5"
bytes = "1.5"
bitflags = "2.4"
chrono = { version = "0.4.38", features = ["serde"] }
clap = "4"
const_format = { version = "0.2.32", features = ["rust_1_64"] }
dashmap = "5.5"
Expand Down Expand Up @@ -515,6 +516,7 @@ proptest-arbitrary-interop = "0.1.0"
secp256k1 = { version = "0.29", default-features = false, features = [
"global-context",
"recovery",
"serde",
] }
enr = { version = "0.12.1", default-features = false }

Expand Down
9 changes: 9 additions & 0 deletions crates/cli/commands/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,21 @@ reth-trie = { workspace = true, features = ["metrics"] }

tokio.workspace = true
itertools.workspace = true
enr.workspace = true

# crypto
secp256k1 = { workspace = true, default-features = false, features = [
"global-context",
"recovery",
"serde",
] }

# misc
ahash = "0.8"
human_bytes = "0.4.1"
eyre.workspace = true
clap = { workspace = true, features = ["derive", "env"] }
chrono = { workspace = true, features = ["serde"] }
serde.workspace = true
serde_json.workspace = true
tracing.workspace = true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ use reth_node_core::{
use reth_primitives::BlockHashOrNumber;
use std::{path::PathBuf, sync::Arc};

mod nodeset;

/// `reth p2p` command
#[derive(Debug, Parser)]
pub struct Command {
Expand Down Expand Up @@ -68,10 +70,12 @@ pub enum Subcommands {
#[arg(value_parser = hash_or_num_value_parser)]
id: BlockHashOrNumber,
},
/// Node Set Utilities
Nodeset(nodeset::Command),
}
impl Command {
/// Execute `p2p` command
pub async fn execute(&self) -> eyre::Result<()> {
pub async fn execute(self) -> eyre::Result<()> {
let data_dir = self.datadir.clone().resolve_datadir(self.chain.chain);
let config_path = self.config.clone().unwrap_or_else(|| data_dir.config());

Expand Down Expand Up @@ -151,6 +155,9 @@ impl Command {
let body = result.into_iter().next().unwrap();
println!("Successfully downloaded body: {body:?}")
}
Subcommands::Nodeset(command) => {
let _ = command.execute();
}
}

Ok(())
Expand Down
76 changes: 76 additions & 0 deletions crates/cli/commands/src/p2p/nodeset.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
//! Node set related subcommand of P2P Debugging tool,

use chrono::{DateTime, Utc};
use clap::{Parser, Subcommand};
use enr::Enr;
use reth_fs_util as fs;
use secp256k1::SecretKey;
use serde::{Deserialize, Serialize};
use std::{collections::HashMap, path::PathBuf};

/// The arguments for the `reth p2p nodeset` command
#[derive(Parser, Debug)]
pub struct Command {
#[clap(subcommand)]
subcommand: Subcommands,
}

#[derive(Serialize, Deserialize, Debug)]
struct Record {
seq: u64,
record: Enr<SecretKey>,
score: i64,
firstResponse: DateTime<Utc>,
lastResponse: DateTime<Utc>,
lastCheck: DateTime<Utc>,
}

impl Command {
/// Execute `p2p nodeset` command
pub fn execute(self) -> eyre::Result<()> {
match self.subcommand {
Subcommands::Info { file } => {
let content = fs::read_to_string(file)?;

let nodes: HashMap<String, Record> =
serde_json::from_str(&content).expect("failed to deserialize json");

println!("Set contains {} nodes", nodes.len());

let mut keys = HashMap::new();

for (_, node) in nodes.iter() {
for (key, _) in node.record.iter() {
*keys.entry(String::from_utf8_lossy(&key).to_string()).or_insert(0) += 1;
}
}

let max_key_len = keys.keys().map(|k| k.len()).max().unwrap_or(0);

let mut result: Vec<_> = keys.iter().collect();

result.sort_by(|a, b| a.0.cmp(b.0));

for (key, count) in result {
let key_len = key.len();
let padding = " ".repeat(max_key_len - key_len);
println!("{}{}: {}", padding, key, count);
}
}
}

Ok(())
}
}

#[derive(Subcommand, Debug)]
enum Subcommands {
/// Show statistics about a node set
Info {
/// The path of the JSON file used to store node set.
#[arg(long, value_name = "FILE", default_value = "known-peers.json", verbatim_doc_comment)]
file: PathBuf,
},
// TODO: implement `filter` subcommand
// ref: https://github.com/ethereum/go-ethereum/blob/master/cmd/devp2p/nodesetcmd.go#L51
}
39 changes: 37 additions & 2 deletions crates/rpc/rpc/src/eth/bundle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,9 @@ use revm::{
db::CacheDB,
primitives::{ResultAndState, TxEnv},
};
use revm_primitives::{EnvKzgSettings, EnvWithHandlerCfg, MAX_BLOB_GAS_PER_BLOCK};
use revm_primitives::{EnvKzgSettings, EnvWithHandlerCfg, SpecId, MAX_BLOB_GAS_PER_BLOCK};

use reth_provider::{ChainSpecProvider, HeaderProvider};
use reth_rpc_eth_api::{
helpers::{Call, EthTransactions, LoadPendingBlock},
EthCallBundleApiServer,
Expand Down Expand Up @@ -48,7 +49,15 @@ where
/// state, or it can be used to simulate a past block. The sender is responsible for signing the
/// transactions and using the correct nonce and ensuring validity
pub async fn call_bundle(&self, bundle: EthCallBundle) -> EthResult<EthCallBundleResponse> {
let EthCallBundle { txs, block_number, state_block_number, timestamp, .. } = bundle;
let EthCallBundle {
txs,
block_number,
state_block_number,
timestamp,
gas_limit,
difficulty,
base_fee,
} = bundle;
if txs.is_empty() {
return Err(EthApiError::InvalidParams(
EthBundleError::EmptyBundleTransactions.to_string(),
Expand Down Expand Up @@ -88,6 +97,7 @@ where
}

let block_id: reth_rpc_types::BlockId = state_block_number.into();
// Note: the block number is considered the `parent` block: <https://github.com/flashbots/mev-geth/blob/fddf97beec5877483f879a77b7dea2e58a58d653/internal/ethapi/api.go#L2104>
let (cfg, mut block_env, at) = self.inner.eth_api.evm_env_at(block_id).await?;

// need to adjust the timestamp for the next block
Expand All @@ -97,6 +107,31 @@ where
block_env.timestamp += U256::from(12);
}

if let Some(difficulty) = difficulty {
block_env.difficulty = U256::from(difficulty);
}

if let Some(gas_limit) = gas_limit {
block_env.gas_limit = U256::from(gas_limit);
}

if let Some(base_fee) = base_fee {
block_env.basefee = U256::from(base_fee);
} else if cfg.handler_cfg.spec_id.is_enabled_in(SpecId::LONDON) {
let parent_block = block_env.number.saturating_to::<u64>();
// here we need to fetch the _next_ block's basefee based on the parent block <https://github.com/flashbots/mev-geth/blob/fddf97beec5877483f879a77b7dea2e58a58d653/internal/ethapi/api.go#L2130>
let parent = LoadPendingBlock::provider(&self.inner.eth_api)
.header_by_number(parent_block)?
.ok_or_else(|| EthApiError::UnknownBlockNumber)?;
if let Some(base_fee) = parent.next_block_base_fee(
LoadPendingBlock::provider(&self.inner.eth_api)
.chain_spec()
.base_fee_params_at_block(parent_block),
) {
block_env.basefee = U256::from(base_fee);
}
}

let state_block_number = block_env.number;
// use the block number of the request
block_env.number = U256::from(block_number);
Expand Down

0 comments on commit 0afc441

Please sign in to comment.