Skip to content

Commit

Permalink
feat: implement .era2 (state snapshots) import/export from Trin Execu…
Browse files Browse the repository at this point in the history
…tion (#1344)
  • Loading branch information
KolbyML authored Sep 14, 2024
1 parent 4d17461 commit 62dd518
Show file tree
Hide file tree
Showing 16 changed files with 383 additions and 110 deletions.
2 changes: 1 addition & 1 deletion Cargo.lock

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

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ directories = "3.0"
discv5 = { version = "0.4.1", features = ["serde"] }
e2store = { path = "e2store" }
env_logger = "0.9.0"
eth_trie = { tag = "v0.1.0-alpha.1", git = "https://github.com/ethereum/eth-trie.rs" }
eth_trie = { tag = "v0.1.0-alpha.2", git = "https://github.com/ethereum/eth-trie.rs" }
ethereum_ssz = "0.7.1"
ethereum_ssz_derive = "0.7.1"
ethportal-api = { path = "ethportal-api" }
Expand Down
10 changes: 7 additions & 3 deletions e2store/src/era2.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use std::{
fs,
io::{ErrorKind, Read, Write},
ops::Deref,
path::{Path, PathBuf},
Expand All @@ -18,6 +19,8 @@ use crate::{
utils::underlying_io_error_kind,
};

pub const MAX_STORAGE_ITEMS: usize = 10_000_000;

// <network-name>-<block-number>-<short-state-root>.era2
//
// era2 := Version | CompressedHeader | account*
Expand Down Expand Up @@ -63,6 +66,7 @@ impl Era2 {
}

pub fn create(path: PathBuf, header: Header) -> anyhow::Result<Self> {
fs::create_dir_all(&path)?;
ensure!(path.is_dir(), "era2 path is not a directory: {:?}", path);
let path = path.join(format!(
"mainnet-{:010}-{}.era2",
Expand Down Expand Up @@ -108,11 +112,11 @@ impl Era2 {
match self.pending_storage_entries {
0 => bail!("Invalid append entry state: expected an account entry, got a storage entry. No storage entries left to append for the account"),
1 => ensure!(
storage.len() <= 10_000_000,
storage.len() <= MAX_STORAGE_ITEMS,
"Storage entry can't have more than 10 million items",
),
_ => ensure!(
storage.len() == 10_000_000,
storage.len() == MAX_STORAGE_ITEMS,
"Only last storage entry can have less than 10 million items",
),
}
Expand Down Expand Up @@ -221,7 +225,7 @@ impl TryFrom<AccountEntry> for Entry {
}

#[derive(Clone, Eq, PartialEq, Debug)]
pub struct StorageEntry(Vec<StorageItem>);
pub struct StorageEntry(pub Vec<StorageItem>);

impl Deref for StorageEntry {
type Target = Vec<StorageItem>;
Expand Down
34 changes: 32 additions & 2 deletions trin-execution/src/cli.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::net::SocketAddr;
use std::{net::SocketAddr, path::PathBuf};

use clap::Parser;
use clap::{Args, Parser, Subcommand};

use crate::types::block_to_trace::BlockToTrace;

Expand All @@ -26,4 +26,34 @@ pub struct TrinExecutionConfig {
help = "Enable prometheus metrics reporting (provide local IP/Port from which your Prometheus server is configured to fetch metrics)"
)]
pub enable_metrics_with_url: Option<SocketAddr>,

#[command(subcommand)]
pub command: Option<TrinExecutionSubCommands>,
}

#[derive(Subcommand, Debug, Clone, PartialEq)]
#[allow(clippy::enum_variant_names)]
pub enum TrinExecutionSubCommands {
/// Import a era2 state snapshot from a file, useful for bootstrapping a new node quickly
ImportState(ImportStateConfig),
/// Export the current state of the node to a era2 file
ExportState(ExportStateConfig),
}

#[derive(Args, Debug, Default, Clone, PartialEq)]
pub struct ImportStateConfig {
#[arg(
long = "path-to-era2",
help = "path to where the era2 state snapshot is located"
)]
pub path_to_era2: PathBuf,
}

#[derive(Args, Debug, Default, Clone, PartialEq)]
pub struct ExportStateConfig {
#[arg(
long = "path-to-era2",
help = "path to where the era2 state snapshot is located"
)]
pub path_to_era2: PathBuf,
}
18 changes: 10 additions & 8 deletions trin-execution/src/evm/block_executor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use std::{

use anyhow::{bail, ensure};
use eth_trie::{RootWithTrieDiff, Trie};
use ethportal_api::{types::state_trie::account_state::AccountState as AccountStateInfo, Header};
use ethportal_api::{types::state_trie::account_state::AccountState, Header};
use revm::{
db::{states::bundle_state::BundleRetention, State},
inspectors::TracerEip3155,
Expand All @@ -23,7 +23,7 @@ use crate::{
set_int_gauge_vec, start_timer_vec, stop_timer, BLOCK_HEIGHT, BLOCK_PROCESSING_TIMES,
TRANSACTION_PROCESSING_TIMES,
},
storage::{account::Account as RocksAccount, evm_db::EvmDB},
storage::evm_db::EvmDB,
types::block_to_trace::BlockToTrace,
};

Expand All @@ -33,7 +33,7 @@ use super::{
tx_env_modifier::TxEnvModifier,
};

const BLOCKHASH_SERVE_WINDOW: u64 = 256;
pub const BLOCKHASH_SERVE_WINDOW: u64 = 256;
const GENESIS_STATE_FILE: &str = "trin-execution/resources/genesis/mainnet.json";
const TEST_GENESIS_STATE_FILE: &str = "resources/genesis/mainnet.json";

Expand Down Expand Up @@ -146,12 +146,14 @@ impl<'a> BlockExecutor<'a> {

for (address, alloc_balance) in genesis.alloc {
let address_hash = keccak256(address);
let mut account = RocksAccount::default();
let mut account = AccountState::default();
account.balance += alloc_balance.balance;
self.evm.db().database.trie.lock().insert(
address_hash.as_ref(),
&alloy_rlp::encode(AccountStateInfo::from(&account)),
)?;
self.evm
.db()
.database
.trie
.lock()
.insert(address_hash.as_ref(), &alloy_rlp::encode(&account))?;
self.evm
.db()
.database
Expand Down
13 changes: 6 additions & 7 deletions trin-execution/src/execution.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use alloy_primitives::{keccak256, Address, Bytes, B256};
use alloy_rlp::Decodable;
use anyhow::{anyhow, bail, ensure};
use eth_trie::{RootWithTrieDiff, Trie};
use ethportal_api::{types::state_trie::account_state::AccountState as AccountStateInfo, Header};
use ethportal_api::{types::state_trie::account_state::AccountState, Header};
use std::{
collections::BTreeSet,
path::PathBuf,
Expand All @@ -17,7 +17,6 @@ use crate::{
evm::block_executor::BlockExecutor,
metrics::{start_timer_vec, stop_timer, BLOCK_PROCESSING_TIMES},
storage::{
account::Account,
evm_db::EvmDB,
execution_position::ExecutionPosition,
utils::{get_default_data_dir, setup_rocksdb},
Expand All @@ -29,7 +28,7 @@ use super::{config::StateConfig, types::trie_proof::TrieProof, utils::address_to
pub struct TrinExecution {
pub database: EvmDB,
pub config: StateConfig,
execution_position: ExecutionPosition,
pub execution_position: ExecutionPosition,
pub era_manager: Arc<Mutex<EraManager>>,
pub node_data_directory: PathBuf,
}
Expand Down Expand Up @@ -141,14 +140,14 @@ impl TrinExecution {
Ok(self.database.trie.lock().root_hash_with_changed_nodes()?)
}

pub fn get_account_state(&self, account: &Address) -> anyhow::Result<AccountStateInfo> {
pub fn get_account_state(&self, account: &Address) -> anyhow::Result<AccountState> {
let account_state = self.database.db.get(keccak256(account))?;
match account_state {
Some(account) => {
let account: Account = Decodable::decode(&mut account.as_slice())?;
Ok(AccountStateInfo::from(&account))
let account = AccountState::decode(&mut account.as_slice())?;
Ok(account)
}
None => Ok(AccountStateInfo::default()),
None => Ok(AccountState::default()),
}
}

Expand Down
1 change: 1 addition & 0 deletions trin-execution/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ pub mod evm;
pub mod execution;
pub mod metrics;
pub mod storage;
pub mod subcommands;
pub mod trie_walker;
pub mod types;
pub mod utils;
36 changes: 32 additions & 4 deletions trin-execution/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
use clap::Parser;

use revm_primitives::SpecId;
use tracing::info;
use trin_execution::{
cli::TrinExecutionConfig, evm::spec_id::get_spec_block_number, execution::TrinExecution,
cli::{TrinExecutionConfig, TrinExecutionSubCommands},
era::manager::EraManager,
evm::spec_id::get_spec_block_number,
execution::TrinExecution,
storage::utils::setup_temp_dir,
subcommands::era2::{export::StateExporter, import::StateImporter},
};
use trin_utils::log::init_tracing_logger;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
async fn main() -> anyhow::Result<()> {
init_tracing_logger();

let trin_execution_config = TrinExecutionConfig::parse();
Expand All @@ -26,7 +29,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {

let mut trin_execution = TrinExecution::new(
directory.map(|temp_directory| temp_directory.path().to_path_buf()),
trin_execution_config.into(),
trin_execution_config.clone().into(),
)
.await?;

Expand All @@ -38,6 +41,31 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
.expect("signal ctrl_c should never fail");
});

if let Some(command) = trin_execution_config.command {
match command {
TrinExecutionSubCommands::ImportState(import_state) => {
let mut state_importer = StateImporter::new(trin_execution, import_state);
state_importer.import_state()?;
state_importer.import_last_256_block_hashes().await?;

info!(
"Imported state from era2: {} {}",
state_importer.trin_execution.next_block_number() - 1,
state_importer.trin_execution.get_root()?
);
return Ok(());
}
TrinExecutionSubCommands::ExportState(export_state) => {
let mut era_manager =
EraManager::new(trin_execution.next_block_number() - 1).await?;
let header = era_manager.get_next_block().await?.clone();
let mut state_exporter = StateExporter::new(trin_execution, export_state);
state_exporter.export_state(header.header)?;
return Ok(());
}
}
}

let mut block_number = trin_execution.next_block_number();

let end_block = get_spec_block_number(SpecId::MERGE);
Expand Down
47 changes: 0 additions & 47 deletions trin-execution/src/storage/account.rs

This file was deleted.

Loading

0 comments on commit 62dd518

Please sign in to comment.