Skip to content

Commit

Permalink
feat(anvil): add mined transactions to state dump
Browse files Browse the repository at this point in the history
  • Loading branch information
tuler committed Jul 11, 2024
1 parent 72e44fb commit 0928504
Show file tree
Hide file tree
Showing 6 changed files with 74 additions and 9 deletions.
2 changes: 1 addition & 1 deletion crates/anvil/core/src/eth/transaction/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1109,7 +1109,7 @@ pub struct TransactionEssentials {
}

/// Represents all relevant information of an executed transaction
#[derive(Clone, Debug, PartialEq, Eq)]
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
pub struct TransactionInfo {
pub transaction_hash: B256,
pub transaction_index: u64,
Expand Down
41 changes: 39 additions & 2 deletions crates/anvil/src/eth/backend/db.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
//! Helper types for working with [revm](foundry_evm::revm)

use crate::revm::primitives::AccountInfo;
use crate::{mem::storage::MinedTransaction, revm::primitives::AccountInfo};
use alloy_consensus::Header;
use alloy_primitives::{keccak256, Address, Bytes, B256, U256, U64};
use alloy_rpc_types::BlockId;
use anvil_core::eth::{block::Block, transaction::TypedTransaction};
use anvil_core::eth::{
block::Block,
transaction::{TransactionInfo, TypedReceipt, TypedTransaction},
};
use foundry_common::errors::FsPathError;
use foundry_evm::{
backend::{
Expand Down Expand Up @@ -120,6 +123,7 @@ pub trait Db:
at: BlockEnv,
best_number: U64,
blocks: Vec<SerializableBlock>,
transactions: Vec<SerializableTransaction>,
) -> DatabaseResult<Option<SerializableState>>;

/// Deserialize and add all chain data to the backend storage
Expand Down Expand Up @@ -193,6 +197,7 @@ impl<T: DatabaseRef<Error = DatabaseError> + Send + Sync + Clone + fmt::Debug> D
_at: BlockEnv,
_best_number: U64,
_blocks: Vec<SerializableBlock>,
_transaction: Vec<SerializableTransaction>,
) -> DatabaseResult<Option<SerializableState>> {
Ok(None)
}
Expand Down Expand Up @@ -325,6 +330,8 @@ pub struct SerializableState {
pub best_block_number: Option<U64>,
#[serde(default)]
pub blocks: Vec<SerializableBlock>,
#[serde(default)]
pub transactions: Vec<SerializableTransaction>,
}

impl SerializableState {
Expand Down Expand Up @@ -378,3 +385,33 @@ impl From<SerializableBlock> for Block {
}
}
}

#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct SerializableTransaction {
pub info: TransactionInfo,
pub receipt: TypedReceipt,
pub block_hash: B256,
pub block_number: u64,
}

impl From<MinedTransaction> for SerializableTransaction {
fn from(transaction: MinedTransaction) -> Self {
Self {
info: transaction.info,
receipt: transaction.receipt,
block_hash: transaction.block_hash,
block_number: transaction.block_number,
}
}
}

impl From<SerializableTransaction> for MinedTransaction {
fn from(transaction: SerializableTransaction) -> Self {
Self {
info: transaction.info,
receipt: transaction.receipt,
block_hash: transaction.block_hash,
block_number: transaction.block_number,
}
}
}
4 changes: 3 additions & 1 deletion crates/anvil/src/eth/backend/mem/fork_db.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::{
eth::backend::db::{
Db, MaybeForkedDatabase, MaybeFullDatabase, SerializableAccountRecord, SerializableBlock,
SerializableState, StateDb,
SerializableState, SerializableTransaction, StateDb,
},
revm::primitives::AccountInfo,
};
Expand Down Expand Up @@ -37,6 +37,7 @@ impl Db for ForkedDatabase {
at: BlockEnv,
best_number: U64,
blocks: Vec<SerializableBlock>,
transactions: Vec<SerializableTransaction>,
) -> DatabaseResult<Option<SerializableState>> {
let mut db = self.database().clone();
let accounts = self
Expand Down Expand Up @@ -66,6 +67,7 @@ impl Db for ForkedDatabase {
accounts,
best_block_number: Some(best_number),
blocks,
transactions,
}))
}

Expand Down
9 changes: 7 additions & 2 deletions crates/anvil/src/eth/backend/mem/in_memory_db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
use crate::{
eth::backend::db::{
Db, MaybeForkedDatabase, MaybeFullDatabase, SerializableAccountRecord, SerializableBlock,
SerializableState, StateDb,
SerializableState, SerializableTransaction, StateDb,
},
mem::state::state_root,
revm::{db::DbAccount, primitives::AccountInfo},
Expand Down Expand Up @@ -37,6 +37,7 @@ impl Db for MemDb {
at: BlockEnv,
best_number: U64,
blocks: Vec<SerializableBlock>,
transactions: Vec<SerializableTransaction>,
) -> DatabaseResult<Option<SerializableState>> {
let accounts = self
.inner
Expand Down Expand Up @@ -66,6 +67,7 @@ impl Db for MemDb {
accounts,
best_block_number: Some(best_number),
blocks,
transactions,
}))
}

Expand Down Expand Up @@ -160,7 +162,10 @@ mod tests {
dump_db.set_storage_at(test_addr, U256::from(1234567), U256::from(1)).unwrap();

// blocks dumping/loading tested in storage.rs
let state = dump_db.dump_state(Default::default(), U64::ZERO, Vec::new()).unwrap().unwrap();
let state = dump_db
.dump_state(Default::default(), U64::ZERO, Vec::new(), Vec::new())
.unwrap()
.unwrap();

let mut load_db = MemDb::default();

Expand Down
4 changes: 3 additions & 1 deletion crates/anvil/src/eth/backend/mem/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -744,7 +744,8 @@ impl Backend {
let at = self.env.read().block.clone();
let best_number = self.blockchain.storage.read().best_number;
let blocks = self.blockchain.storage.read().serialized_blocks();
let state = self.db.read().await.dump_state(at, best_number, blocks)?;
let transactions = self.blockchain.storage.read().serialized_transactions();
let state = self.db.read().await.dump_state(at, best_number, blocks, transactions)?;
state.ok_or_else(|| {
RpcError::invalid_params("Dumping state not supported with the current configuration")
.into()
Expand Down Expand Up @@ -781,6 +782,7 @@ impl Backend {
}

self.blockchain.storage.write().load_blocks(state.blocks.clone());
self.blockchain.storage.write().load_transactions(state.transactions.clone());

Ok(true)
}
Expand Down
23 changes: 21 additions & 2 deletions crates/anvil/src/eth/backend/mem/storage.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//! In-memory blockchain storage
use crate::eth::{
backend::{
db::{MaybeFullDatabase, SerializableBlock, StateDb},
db::{MaybeFullDatabase, SerializableBlock, SerializableTransaction, StateDb},
mem::cache::DiskStateCache,
},
error::BlockchainError,
Expand Down Expand Up @@ -334,6 +334,10 @@ impl BlockchainStorage {
self.blocks.values().map(|block| block.clone().into()).collect()
}

pub fn serialized_transactions(&self) -> Vec<SerializableTransaction> {
self.transactions.values().map(|tx: &MinedTransaction| tx.clone().into()).collect()
}

/// Deserialize and add all blocks data to the backend storage
pub fn load_blocks(&mut self, serializable_blocks: Vec<SerializableBlock>) {
for serializable_block in serializable_blocks.iter() {
Expand All @@ -344,6 +348,14 @@ impl BlockchainStorage {
self.hashes.insert(U64::from(block_number), block_hash);
}
}

/// Deserialize and add all blocks data to the backend storage
pub fn load_transactions(&mut self, serializable_transactions: Vec<SerializableTransaction>) {
for serializable_transaction in serializable_transactions.iter() {
let transaction: MinedTransaction = serializable_transaction.clone().into();
self.transactions.insert(transaction.info.transaction_hash, transaction);
}
}
}

/// A simple in-memory blockchain
Expand Down Expand Up @@ -590,7 +602,8 @@ mod tests {
}
}

// verifies that blocks in BlockchainStorage remain the same when dumped and reloaded
// verifies that blocks and transactions in BlockchainStorage remain the same when dumped and
// reloaded
#[test]
fn test_storage_dump_reload_cycle() {
let mut dump_storage = BlockchainStorage::empty();
Expand All @@ -607,11 +620,17 @@ mod tests {
let block_hash = block.header.hash_slow();
dump_storage.blocks.insert(block_hash, block);

// XXX: add test for MinedTransaction
// let transaction_hash = transaction.info.transaction_hash;
// dump_storage.transactions.insert(transaction_hash, transaction);

let serialized_blocks = dump_storage.serialized_blocks();
let serialized_transactions = dump_storage.serialized_transactions();

let mut load_storage = BlockchainStorage::empty();

load_storage.load_blocks(serialized_blocks);
load_storage.load_transactions(serialized_transactions);

let loaded_block = load_storage.blocks.get(&block_hash).unwrap();
assert_eq!(loaded_block.header.gas_limit, partial_header.gas_limit);
Expand Down

0 comments on commit 0928504

Please sign in to comment.