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: adds init and timestamp genesis cli params #441

Merged
merged 1 commit into from
Nov 27, 2024
Merged
Show file tree
Hide file tree
Changes from all 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
16 changes: 13 additions & 3 deletions src/config/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@ use clap::{arg, command, Parser, Subcommand};
use rand::{rngs::StdRng, SeedableRng};
use zksync_types::{H256, U256};

use super::DEFAULT_DISK_CACHE_DIR;
use crate::config::constants::{DEFAULT_MNEMONIC, TEST_NODE_NETWORK_ID};
use crate::config::{
AccountGenerator, CacheConfig, CacheType, ShowCalls, ShowGasDetails, ShowStorageLogs,
AccountGenerator, CacheConfig, CacheType, Genesis, ShowCalls, ShowGasDetails, ShowStorageLogs,
ShowVMDetails, TestNodeConfig,
};
use crate::observability::LogLevel;
use crate::system_contracts::Options as SystemContractsOptions;

use super::DEFAULT_DISK_CACHE_DIR;
use crate::utils::parse_genesis_file;
use alloy_signer_local::coins_bip39::{English, Mnemonic};
use std::net::IpAddr;

Expand Down Expand Up @@ -170,6 +170,14 @@ pub struct Cli {
)]
pub balance: u64,

/// The timestamp of the genesis block.
#[arg(long, value_name = "NUM")]
pub timestamp: Option<u64>,

/// Initialize the genesis block with the given `genesis.json` file.
#[arg(long, value_name = "PATH", value_parser= parse_genesis_file)]
pub init: Option<Genesis>,

/// BIP39 mnemonic phrase used for generating accounts.
/// Cannot be used if `mnemonic_random` or `mnemonic_seed` are used.
#[arg(long, short, conflicts_with_all = &["mnemonic_seed", "mnemonic_random"], help_heading = "Account Configuration")]
Expand Down Expand Up @@ -332,6 +340,8 @@ impl Cli {
},
}
}))
.with_genesis_timestamp(self.timestamp)
.with_genesis(self.init)
.with_chain_id(self.chain_id)
.set_config_out(self.config_out)
.with_host(self.host)
Expand Down
2 changes: 2 additions & 0 deletions src/config/constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ pub const DERIVATION_PATH: &str = "m/44'/60'/0'/0/0";
pub const DEFAULT_LOG_FILE_PATH: &str = "era_test_node.log";
/// Default mnemonic phrase for the test node
pub const DEFAULT_MNEMONIC: &str = "test test test test test test test test test test test junk";
/// Timestamp of the first block (if not running in fork mode).
pub const NON_FORK_FIRST_BLOCK_TIMESTAMP: u64 = 1_000;
/// Default account balance for the dev accounts
#[cfg(test)]
pub const DEFAULT_ACCOUNT_BALANCE: u128 = 1_000 * 10u128.pow(18);
Expand Down
56 changes: 55 additions & 1 deletion src/config/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ use crate::fork::ForkDetails;
use crate::{observability, system_contracts};
use anyhow::anyhow;
use std::net::{IpAddr, Ipv4Addr};
use zksync_multivm::interface::L1BatchEnv;
use zksync_types::api::TransactionVariant;

use crate::config::{
cache::{CacheConfig, CacheType},
Expand All @@ -22,7 +24,7 @@ use serde_json::{json, to_writer, Value};
use std::collections::HashMap;
use std::fs::File;
use zksync_types::fee_model::FeeModelConfigV2;
use zksync_types::U256;
use zksync_types::{Bloom, H256, U256};

pub mod cache;
pub mod cli;
Expand Down Expand Up @@ -100,6 +102,10 @@ pub struct TestNodeConfig {
pub account_generator: Option<AccountGenerator>,
/// Signer accounts that can sign messages/transactions
pub signer_accounts: Vec<PrivateKeySigner>,
/// The genesis to use to initialize the node
pub genesis: Option<Genesis>,
/// Genesis block timestamp
pub genesis_timestamp: Option<u64>,
/// Enable auto impersonation of accounts on startup
pub enable_auto_impersonate: bool,
/// Whether the node operates in offline mode
Expand Down Expand Up @@ -150,6 +156,8 @@ impl Default for TestNodeConfig {
enable_auto_impersonate: false,
// 100ETH default balance
genesis_balance: U256::from(100u128 * 10u128.pow(18)),
genesis_timestamp: Some(NON_FORK_FIRST_BLOCK_TIMESTAMP),
genesis: None,

// Offline mode disabled by default
offline: false,
Expand Down Expand Up @@ -288,6 +296,11 @@ impl TestNodeConfig {
);
println!("\n");

tracing::info!("Genesis Timestamp");
tracing::info!("========================");
tracing::info!("{}", self.get_genesis_timestamp().to_string().green());
println!("\n");

tracing::info!("Node Configuration");
tracing::info!("========================");
tracing::info!("Port: {}", self.port);
Expand Down Expand Up @@ -668,6 +681,26 @@ impl TestNodeConfig {
.with_genesis_accounts(accounts)
}

/// Sets the genesis timestamp
#[must_use]
pub fn with_genesis_timestamp(mut self, timestamp: Option<u64>) -> Self {
self.genesis_timestamp = timestamp;
self
}

/// Returns the genesis timestamp to use
pub fn get_genesis_timestamp(&self) -> u64 {
self.genesis_timestamp
.unwrap_or(NON_FORK_FIRST_BLOCK_TIMESTAMP)
}

/// Sets the init genesis (genesis.json)
#[must_use]
pub fn with_genesis(mut self, genesis: Option<Genesis>) -> Self {
self.genesis = genesis;
self
}

/// Sets whether to enable autoImpersonate
#[must_use]
pub fn with_auto_impersonate(mut self, enable_auto_impersonate: bool) -> Self {
Expand Down Expand Up @@ -805,3 +838,24 @@ impl AccountGenerator {
.collect()
}
}

/// Genesis
#[derive(Deserialize, Clone, Debug)]
pub struct Genesis {
/// The hash of the genesis block. If not provided, it can be computed.
pub hash: Option<H256>,
/// The parent hash of the genesis block. Usually zero.
pub parent_hash: Option<H256>,
/// The block number of the genesis block. Usually zero.
pub block_number: Option<u64>,
/// The timestamp of the genesis block.
pub timestamp: Option<u64>,
/// The L1 batch environment.
pub l1_batch_env: Option<L1BatchEnv>,
/// The transactions included in the genesis block.
pub transactions: Option<Vec<TransactionVariant>>,
/// The amount of gas used.
pub gas_used: Option<U256>,
/// The logs bloom filter.
pub logs_bloom: Option<Bloom>,
}
5 changes: 3 additions & 2 deletions src/node/eth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1465,11 +1465,12 @@ impl<S: ForkSource + std::fmt::Debug + Clone + Send + Sync + 'static> EthTestNod
#[cfg(test)]
mod tests {
use super::*;
use crate::node::NON_FORK_FIRST_BLOCK_TIMESTAMP;
use crate::{
config::{
cache::CacheConfig,
constants::{DEFAULT_ACCOUNT_BALANCE, DEFAULT_L2_GAS_PRICE},
constants::{
DEFAULT_ACCOUNT_BALANCE, DEFAULT_L2_GAS_PRICE, NON_FORK_FIRST_BLOCK_TIMESTAMP,
},
},
fork::ForkDetails,
http_fork_source::HttpForkSource,
Expand Down
56 changes: 49 additions & 7 deletions src/node/in_memory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,9 @@ use crate::{
bootloader_debug::{BootloaderDebug, BootloaderDebugTracer},
config::{
cache::CacheConfig,
constants::{LEGACY_RICH_WALLETS, RICH_WALLETS},
constants::{LEGACY_RICH_WALLETS, NON_FORK_FIRST_BLOCK_TIMESTAMP, RICH_WALLETS},
show_details::{ShowCalls, ShowGasDetails, ShowStorageLogs, ShowVMDetails},
TestNodeConfig,
Genesis, TestNodeConfig,
},
console_log::ConsoleLogHandler,
deps::{storage_view::StorageView, InMemoryStorage},
Expand All @@ -72,8 +72,6 @@ use crate::{

/// Max possible size of an ABI encoded tx (in bytes).
pub const MAX_TX_SIZE: usize = 1_000_000;
/// Timestamp of the first block (if not running in fork mode).
pub const NON_FORK_FIRST_BLOCK_TIMESTAMP: u64 = 1_000;
/// Acceptable gas overestimation limit.
pub const ESTIMATE_GAS_ACCEPTABLE_OVERESTIMATION: u64 = 1_000;
/// The maximum number of previous blocks to store the state for.
Expand All @@ -90,8 +88,45 @@ pub fn compute_hash<'a>(block_number: u64, tx_hashes: impl IntoIterator<Item = &
H256(keccak256(&digest))
}

pub fn create_genesis<TX>(timestamp: u64) -> Block<TX> {
pub fn create_genesis_from_json(
genesis: &Genesis,
timestamp: Option<u64>,
) -> Block<TransactionVariant> {
let hash = genesis.hash.unwrap_or_else(|| compute_hash(0, []));
let timestamp = timestamp
.or(genesis.timestamp)
.unwrap_or(NON_FORK_FIRST_BLOCK_TIMESTAMP);

let l1_batch_env = genesis.l1_batch_env.clone().unwrap_or_else(|| L1BatchEnv {
previous_batch_hash: None,
number: L1BatchNumber(0),
timestamp,
fee_input: BatchFeeInput::pubdata_independent(0, 0, 0),
fee_account: Address::zero(),
enforced_base_fee: None,
first_l2_block: L2BlockEnv {
number: 0,
timestamp,
prev_block_hash: H256::zero(),
max_virtual_blocks_to_create: 0,
},
});

create_block(
&l1_batch_env,
hash,
genesis.parent_hash.unwrap_or_else(H256::zero),
genesis.block_number.unwrap_or(0),
timestamp,
genesis.transactions.clone().unwrap_or_default(),
genesis.gas_used.unwrap_or_else(U256::zero),
genesis.logs_bloom.unwrap_or_else(Bloom::zero),
)
}

pub fn create_genesis<TX>(timestamp: Option<u64>) -> Block<TX> {
let hash = compute_hash(0, []);
let timestamp = timestamp.unwrap_or(NON_FORK_FIRST_BLOCK_TIMESTAMP);
let batch_env = L1BatchEnv {
previous_batch_hash: None,
number: L1BatchNumber(0),
Expand Down Expand Up @@ -294,7 +329,14 @@ impl<S: std::fmt::Debug + ForkSource> InMemoryNodeInner<S> {
let block_hash = compute_hash(0, []);
block_hashes.insert(0, block_hash);
let mut blocks = HashMap::<H256, Block<TransactionVariant>>::new();
blocks.insert(block_hash, create_genesis(NON_FORK_FIRST_BLOCK_TIMESTAMP));
let genesis_block: Block<TransactionVariant> = if let Some(ref genesis) = config.genesis
{
create_genesis_from_json(genesis, config.genesis_timestamp)
} else {
create_genesis(config.genesis_timestamp)
};

blocks.insert(block_hash, genesis_block);
let fee_input_provider = TestNodeFeeInputProvider::default();

let impersonation_manager = ImpersonationManager::default();
Expand Down Expand Up @@ -1972,7 +2014,7 @@ mod tests {

#[tokio::test]
async fn test_create_genesis_creates_block_with_hash_and_zero_parent_hash() {
let first_block = create_genesis::<TransactionVariant>(1000);
let first_block = create_genesis::<TransactionVariant>(Some(1000));

assert_eq!(first_block.hash, compute_hash(0, []));
assert_eq!(first_block.parent_hash, H256::zero());
Expand Down
9 changes: 9 additions & 0 deletions src/utils.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
use crate::config::Genesis;
use anyhow::Context;
use chrono::{DateTime, Utc};
use futures::Future;
use jsonrpc_core::{Error, ErrorCode};
use serde::{Deserialize, Serialize};
use std::convert::TryFrom;
use std::fs;
use std::{convert::TryInto, fmt, pin::Pin};
use zksync_multivm::interface::{Call, CallType, ExecutionResult, VmExecutionResultAndLogs};
use zksync_types::{
Expand All @@ -28,6 +30,13 @@ where
{
}

/// Parses the genesis file from the given path.
pub fn parse_genesis_file(path: &str) -> Result<Genesis, String> {
let file_content =
fs::read_to_string(path).map_err(|err| format!("Failed to read file: {err}"))?;
serde_json::from_str(&file_content).map_err(|err| format!("Failed to parse JSON: {err}"))
}

/// Takes long integers and returns them in human friendly format with "_".
/// For example: 12_334_093
pub fn to_human_size(input: U256) -> String {
Expand Down