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 a --dev option #3866

Merged
merged 8 commits into from
Jul 25, 2023
Merged
Show file tree
Hide file tree
Changes from 6 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
96 changes: 96 additions & 0 deletions bin/reth/src/args/dev_args.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
//! clap [Args](clap::Args) for Dev testnet configuration
use std::time::Duration;

use clap::Args;
use humantime::parse_duration;

/// Parameters for Dev testnet configuration
#[derive(Debug, Args, PartialEq, Default, Clone, Copy)]
#[command(next_help_heading = "Dev testnet")]
pub struct DevArgs {
/// Start the node in dev mode
///
/// This mode uses a local proof-of-authority consensus engine with either fixed block times
/// or automatically mined blocks.
/// Disables network discovery and enables local http server.
/// Prefunds 20 accounts derived by mnemonic "test test test test test test test test test test
/// test junk" with 10 000 ETH each.
#[arg(long = "dev", help_heading = "Dev testnet", verbatim_doc_comment)]
pistomat marked this conversation as resolved.
Show resolved Hide resolved
pub dev: bool,

/// How many transactions to mine per block.
#[arg(
long = "dev.block_max_transactions",
help_heading = "Dev testnet",
conflicts_with = "block_time"
)]
pub block_max_transactions: Option<usize>,

/// Interval between blocks.
///
/// Parses strings using [humantime::parse_duration]
/// --dev.block_time 12s
#[arg(
long = "dev.block_time",
help_heading = "Dev testnet",
conflicts_with = "block_max_transactions",
value_parser = parse_duration,
verbatim_doc_comment
)]
pub block_time: Option<Duration>,
}

#[cfg(test)]
mod tests {
use super::*;
use clap::Parser;

/// A helper type to parse Args more easily
#[derive(Parser)]
struct CommandParser<T: Args> {
#[clap(flatten)]
args: T,
}

#[test]
fn test_parse_dev_args() {
let args = CommandParser::<DevArgs>::parse_from(["reth"]).args;
assert_eq!(args, DevArgs { dev: false, block_max_transactions: None, block_time: None });

let args = CommandParser::<DevArgs>::parse_from(["reth", "--dev"]).args;
assert_eq!(args, DevArgs { dev: true, block_max_transactions: None, block_time: None });

let args = CommandParser::<DevArgs>::parse_from([
"reth",
"--dev",
"--dev.block_max_transactions",
"2",
])
.args;
assert_eq!(args, DevArgs { dev: true, block_max_transactions: Some(2), block_time: None });

let args =
CommandParser::<DevArgs>::parse_from(["reth", "--dev", "--dev.block_time", "1s"]).args;
assert_eq!(
args,
DevArgs {
dev: true,
block_max_transactions: None,
block_time: Some(std::time::Duration::from_secs(1))
}
);
}

#[test]
fn test_parse_dev_args_conflicts() {
let args = CommandParser::<DevArgs>::try_parse_from([
"reth",
"--dev",
"--dev.block_max_transactions",
"2",
"--dev.block_time",
"1s",
]);
assert!(args.is_err());
}
}
4 changes: 4 additions & 0 deletions bin/reth/src/args/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,8 @@ pub use gas_price_oracle_args::GasPriceOracleArgs;
mod txpool_args;
pub use txpool_args::TxPoolArgs;

/// DevArgs for configuring the dev testnet
mod dev_args;
pub use dev_args::DevArgs;

pub mod utils;
2 changes: 1 addition & 1 deletion bin/reth/src/args/network_args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ impl NetworkArgs {
#[derive(Debug, Args)]
pub struct DiscoveryArgs {
/// Disable the discovery service.
#[arg(short, long)]
#[arg(short, long, default_value_if("dev", "true", "true"))]
pistomat marked this conversation as resolved.
Show resolved Hide resolved
pub disable_discovery: bool,

/// Disable the DNS discovery.
Expand Down
2 changes: 1 addition & 1 deletion bin/reth/src/args/rpc_server_args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ pub(crate) const RPC_DEFAULT_MAX_TRACING_REQUESTS: u32 = 25;
#[command(next_help_heading = "RPC")]
pub struct RpcServerArgs {
/// Enable the HTTP-RPC server
#[arg(long)]
#[arg(long, default_value_if("dev", "true", "true"))]
pub http: bool,

/// Http server address to listen on
Expand Down
4 changes: 3 additions & 1 deletion bin/reth/src/args/utils.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//! Clap parser utilities

use reth_primitives::{
fs, AllGenesisFormats, BlockHashOrNumber, ChainSpec, GOERLI, MAINNET, SEPOLIA,
fs, AllGenesisFormats, BlockHashOrNumber, ChainSpec, DEV, GOERLI, MAINNET, SEPOLIA,
};
use reth_revm::primitives::B256 as H256;
use std::{
Expand All @@ -25,6 +25,7 @@ pub fn chain_spec_value_parser(s: &str) -> eyre::Result<Arc<ChainSpec>, eyre::Er
"mainnet" => MAINNET.clone(),
"goerli" => GOERLI.clone(),
"sepolia" => SEPOLIA.clone(),
"dev" => DEV.clone(),
_ => {
let raw = fs::read_to_string(PathBuf::from(shellexpand::full(s)?.into_owned()))?;
serde_json::from_str(&raw)?
Expand All @@ -39,6 +40,7 @@ pub fn genesis_value_parser(s: &str) -> eyre::Result<Arc<ChainSpec>, eyre::Error
"mainnet" => MAINNET.clone(),
"goerli" => GOERLI.clone(),
"sepolia" => SEPOLIA.clone(),
"dev" => DEV.clone(),
_ => {
let raw = fs::read_to_string(PathBuf::from(shellexpand::full(s)?.into_owned()))?;
let genesis: AllGenesisFormats = serde_json::from_str(&raw)?;
Expand Down
40 changes: 33 additions & 7 deletions bin/reth/src/node/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
//!
//! Starts the client
use crate::{
args::{get_secret_key, DebugArgs, NetworkArgs, RpcServerArgs, TxPoolArgs},
args::{get_secret_key, DebugArgs, DevArgs, NetworkArgs, RpcServerArgs, TxPoolArgs},
dirs::DataDirPath,
init::init_genesis,
prometheus_exporter,
Expand Down Expand Up @@ -111,12 +111,15 @@ pub struct Command {
/// - mainnet
/// - goerli
/// - sepolia
/// - dev
#[arg(
long,
value_name = "CHAIN_OR_PATH",
verbatim_doc_comment,
default_value = "mainnet",
value_parser = genesis_value_parser
default_value_if("dev", "true", "dev"),
value_parser = genesis_value_parser,
required = false,
)]
chain: Arc<ChainSpec>,

Expand Down Expand Up @@ -144,9 +147,8 @@ pub struct Command {
#[clap(flatten)]
db: DatabaseArgs,

/// Automatically mine blocks for new transactions
#[arg(long)]
auto_mine: bool,
#[clap(flatten)]
dev: DevArgs,
}

impl Command {
Expand Down Expand Up @@ -180,7 +182,7 @@ impl Command {

info!(target: "reth::cli", "{}", DisplayHardforks::from(self.chain.hardforks().clone()));

let consensus: Arc<dyn Consensus> = if self.auto_mine {
let consensus: Arc<dyn Consensus> = if self.dev.dev {
debug!(target: "reth::cli", "Using auto seal");
Arc::new(AutoSealConsensus::new(Arc::clone(&self.chain)))
} else {
Expand Down Expand Up @@ -303,13 +305,17 @@ impl Command {
};

// Configure the pipeline
let (mut pipeline, client) = if self.auto_mine {
let (mut pipeline, client) = if self.dev.dev {
info!(target: "reth::cli", "Starting Reth in dev mode");

let (_, client, mut task) = AutoSealBuilder::new(
Arc::clone(&self.chain),
blockchain_db.clone(),
transaction_pool.clone(),
consensus_engine_tx.clone(),
canon_state_notification_sender,
self.dev.block_max_transactions,
self.dev.block_time,
)
.build();

Expand Down Expand Up @@ -790,6 +796,8 @@ async fn run_network_until_shutdown<C>(

#[cfg(test)]
mod tests {
use reth_primitives::DEV;

use super::*;
use std::{net::IpAddr, path::Path};

Expand Down Expand Up @@ -861,4 +869,22 @@ mod tests {
let db_path = data_dir.db_path();
assert_eq!(db_path, Path::new("my/custom/path/db"));
}

#[test]
fn parse_dev() {
let cmd = Command::parse_from(["reth", "--dev"]);
let chain = DEV.clone();
assert_eq!(cmd.chain.chain, chain.chain);
assert_eq!(cmd.chain.genesis_hash, chain.genesis_hash);
assert_eq!(
cmd.chain.paris_block_and_final_difficulty,
chain.paris_block_and_final_difficulty
);
assert_eq!(cmd.chain.hardforks, chain.hardforks);

assert!(cmd.rpc.http);
assert!(cmd.network.discovery.disable_discovery);

assert!(cmd.dev.dev);
}
}
16 changes: 13 additions & 3 deletions crates/consensus/auto-seal/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ use reth_transaction_pool::TransactionPool;
use std::{
collections::HashMap,
sync::Arc,
time::{SystemTime, UNIX_EPOCH},
time::{Duration, SystemTime, UNIX_EPOCH},
};
use tokio::sync::{mpsc::UnboundedSender, RwLock, RwLockReadGuard, RwLockWriteGuard};
use tracing::{trace, warn};
Expand Down Expand Up @@ -115,13 +115,23 @@ where
pool: Pool,
to_engine: UnboundedSender<BeaconEngineMessage>,
canon_state_notification: CanonStateNotificationSender,
block_max_transactions: Option<usize>,
block_time: Option<Duration>,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

these should be mutually exclusive, but I can see how this would be more convenient coming from CLI

so at the very least, this needs to be included in the docs

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was not sure how to handle this. Throw if both are Some? Merge them to one enum parameter including both variants?

) -> Self {
let latest_header = client
.latest_header()
.ok()
.flatten()
.unwrap_or_else(|| chain_spec.sealed_genesis_header());
let mode = MiningMode::interval(std::time::Duration::from_secs(1));

let mode = if let Some(interval) = block_time {
MiningMode::interval(interval)
} else if let Some(max_transactions) = block_max_transactions {
MiningMode::instant(max_transactions, pool.pending_transactions_listener())
} else {
warn!("No mining mode specified, defaulting to ReadyTransaction");
MiningMode::instant(1, pool.pending_transactions_listener())
};

Self {
storage: Storage::new(latest_header),
Expand Down Expand Up @@ -292,7 +302,7 @@ impl StorageInner {
trace!(target: "consensus::auto", transactions=?&block.body, "executing transactions");

let (post_state, gas_used) =
executor.execute_transactions(block, U256::ZERO, Some(senders.clone()))?;
executor.execute_transactions(block, U256::ZERO, Some(senders))?;

// apply post block changes
let post_state = executor.apply_post_block_changes(block, U256::ZERO, post_state)?;
Expand Down
75 changes: 75 additions & 0 deletions crates/primitives/res/genesis/dev.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
{
"nonce": "0x0",
"timestamp": "0x6490fdd2",
"extraData": "0x",
"gasLimit": "0x1c9c380",
"difficulty": "0x0",
"mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"coinbase": "0x0000000000000000000000000000000000000000",
"stateRoot": "0x5eb6e371a698b8d68f665192350ffcecbbbf322916f4b51bd79bb6887da3f494",
"alloc": {
"0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266": {
"balance": "0xD3C21BCECCEDA1000000"
},
"0x70997970C51812dc3A010C7d01b50e0d17dc79C8": {
"balance": "0xD3C21BCECCEDA1000000"
},
"0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC": {
"balance": "0xD3C21BCECCEDA1000000"
},
"0x90F79bf6EB2c4f870365E785982E1f101E93b906": {
"balance": "0xD3C21BCECCEDA1000000"
},
"0x15d34AAf54267DB7D7c367839AAf71A00a2C6A65": {
"balance": "0xD3C21BCECCEDA1000000"
},
"0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc": {
"balance": "0xD3C21BCECCEDA1000000"
},
"0x976EA74026E726554dB657fA54763abd0C3a0aa9": {
"balance": "0xD3C21BCECCEDA1000000"
},
"0x14dC79964da2C08b23698B3D3cc7Ca32193d9955": {
"balance": "0xD3C21BCECCEDA1000000"
},
"0x23618e81E3f5cdF7f54C3d65f7FBc0aBf5B21E8f": {
"balance": "0xD3C21BCECCEDA1000000"
},
"0xa0Ee7A142d267C1f36714E4a8F75612F20a79720": {
"balance": "0xD3C21BCECCEDA1000000"
},
"0xBcd4042DE499D14e55001CcbB24a551F3b954096": {
"balance": "0xD3C21BCECCEDA1000000"
},
"0x71bE63f3384f5fb98995898A86B02Fb2426c5788": {
"balance": "0xD3C21BCECCEDA1000000"
},
"0xFABB0ac9d68B0B445fB7357272Ff202C5651694a": {
"balance": "0xD3C21BCECCEDA1000000"
},
"0x1CBd3b2770909D4e10f157cABC84C7264073C9Ec": {
"balance": "0xD3C21BCECCEDA1000000"
},
"0xdF3e18d64BC6A983f673Ab319CCaE4f1a57C7097": {
"balance": "0xD3C21BCECCEDA1000000"
},
"0xcd3B766CCDd6AE721141F452C550Ca635964ce71": {
"balance": "0xD3C21BCECCEDA1000000"
},
"0x2546BcD3c84621e976D8185a91A922aE77ECEc30": {
"balance": "0xD3C21BCECCEDA1000000"
},
"0xbDA5747bFD65F08deb54cb465eB87D40e51B197E": {
"balance": "0xD3C21BCECCEDA1000000"
},
"0xdD2FD4581271e230360230F9337D5c0430Bf44C0": {
"balance": "0xD3C21BCECCEDA1000000"
},
"0x8626f6940E2eb28930eFb4CeF49B2d1F2C9C1199": {
"balance": "0xD3C21BCECCEDA1000000"
}
},
"number": "0x0",
"gasUsed": "0x0",
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000"
}
7 changes: 6 additions & 1 deletion crates/primitives/src/chain/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use std::{fmt, str::FromStr};
mod spec;
pub use spec::{
AllGenesisFormats, ChainSpec, ChainSpecBuilder, DisplayHardforks, ForkCondition,
ForkTimestamps, GOERLI, MAINNET, SEPOLIA,
ForkTimestamps, DEV, GOERLI, MAINNET, SEPOLIA,
};

// The chain info module.
Expand Down Expand Up @@ -44,6 +44,11 @@ impl Chain {
Chain::Named(ethers_core::types::Chain::Sepolia)
}

/// Returns the dev chain.
pub const fn dev() -> Self {
Chain::Named(ethers_core::types::Chain::Dev)
}

/// The id of the chain
pub fn id(&self) -> u64 {
match self {
Expand Down
Loading
Loading