Skip to content

Commit

Permalink
feat(revm): Replace CacheDB with State
Browse files Browse the repository at this point in the history
  • Loading branch information
rakita committed Aug 16, 2023
1 parent 8a2c3ab commit a32615e
Show file tree
Hide file tree
Showing 74 changed files with 2,014 additions and 1,808 deletions.
32 changes: 25 additions & 7 deletions Cargo.lock

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

9 changes: 2 additions & 7 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -77,14 +77,9 @@ lto = "fat"
codegen-units = 1
incremental = false

[patch.crates-io]
revm = { git = "https://github.com/bluealloy/revm/", branch = "release/v25" }
revm-primitives = { git = "https://github.com/bluealloy/revm/", branch = "release/v25" }

[workspace.dependencies]
## reth
revm = { version = "3" }
revm-primitives = "1.1"
revm = { git = "https://github.com/bluealloy/revm.git", rev = "49a64704f488b4bc0b42a80ab291b8290ac5b0e6" }
revm-primitives = { git = "https://github.com/bluealloy/revm.git", rev = "49a64704f488b4bc0b42a80ab291b8290ac5b0e6" }
reth = { path = "./bin/reth" }
reth-primitives = { path = "./crates/primitives" }
reth-interfaces = { path = "./crates/interfaces" }
Expand Down
7 changes: 4 additions & 3 deletions bin/reth/src/debug_cmd/in_memory_merkle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use reth_network::NetworkHandle;
use reth_network_api::NetworkInfo;
use reth_primitives::{fs, stage::StageId, BlockHashOrNumber, ChainSpec};
use reth_provider::{
AccountExtReader, BlockExecutor, BlockWriter, ExecutorFactory, HashingWriter, HeaderProvider,
AccountExtReader, BlockWriter, ExecutorFactory, HashingWriter, HeaderProvider,
LatestStateProviderRef, ProviderFactory, StageCheckpointReader, StorageReader,
};
use reth_tasks::TaskExecutor;
Expand Down Expand Up @@ -168,11 +168,12 @@ impl Command {

let merkle_block_td =
provider.header_td_by_number(merkle_block_number)?.unwrap_or_default();
let block_state = executor.execute_and_verify_receipt(
executor.execute_and_verify_receipt(
&block.clone().unseal(),
merkle_block_td + block.difficulty,
None,
)?;
let block_state = executor.take_output_state();

// Unpacked `PostState::state_root_slow` function
let hashed_post_state = block_state.hash_state_slow().sorted();
Expand All @@ -194,7 +195,7 @@ impl Command {

// Insert block, state and hashes
provider_rw.insert_block(block.clone(), None)?;
block_state.write_to_db(provider_rw.tx_ref(), block.number)?;
block_state.write_to_db(provider_rw.tx_ref(), false)?;
let storage_lists = provider_rw.changed_storages_with_range(block.number..=block.number)?;
let storages = provider_rw.plainstate_storages(storage_lists)?;
provider_rw.insert_storage_for_hashing(storages)?;
Expand Down
81 changes: 60 additions & 21 deletions bin/reth/src/init.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,14 @@ use reth_db::{
transaction::{DbTx, DbTxMut},
};
use reth_primitives::{stage::StageId, Account, Bytecode, ChainSpec, StorageEntry, H256, U256};
use reth_provider::{DatabaseProviderRW, HashingWriter, HistoryWriter, PostState, ProviderFactory};
use std::{collections::BTreeMap, sync::Arc};
use reth_provider::{
change::{BundleStateInit, RevertsInit},
BundleState, DatabaseProviderRW, HashingWriter, HistoryWriter, ProviderFactory,
};
use std::{
collections::{BTreeMap, HashMap},
sync::Arc,
};
use tracing::debug;

/// Database initialization error type.
Expand Down Expand Up @@ -85,31 +91,64 @@ pub fn insert_genesis_state<DB: Database>(
tx: &<DB as DatabaseGAT<'_>>::TXMut,
genesis: &reth_primitives::Genesis,
) -> Result<(), InitDatabaseError> {
let mut state = PostState::default();
let mut state_init: BundleStateInit = HashMap::new();
let mut reverts_init = HashMap::new();
let mut contracts: HashMap<H256, Bytecode> = HashMap::new();

for (address, account) in &genesis.alloc {
let mut bytecode_hash = None;
if let Some(code) = &account.code {
let bytecode_hash = if let Some(code) = &account.code {
let bytecode = Bytecode::new_raw(code.0.clone());
// FIXME: Can bytecode_hash be Some(Bytes::new()) here?
bytecode_hash = Some(bytecode.hash);
state.add_bytecode(bytecode.hash, bytecode);
}
state.create_account(
0,
let hash = bytecode.hash_slow();
contracts.insert(hash, bytecode);
Some(hash)
} else {
None
};

// get state
let storage = account
.storage
.as_ref()
.map(|m| {
m.iter()
.map(|(key, value)| {
let value = U256::from_be_bytes(value.0);
(*key, (U256::ZERO, value))
})
.collect::<HashMap<_, _>>()
})
.unwrap_or_default();

reverts_init.insert(
*address,
Account { nonce: account.nonce.unwrap_or(0), balance: account.balance, bytecode_hash },
(Some(None), storage.keys().map(|k| StorageEntry::new(*k, U256::ZERO)).collect()),
);

state_init.insert(
*address,
(
None,
Some(Account {
nonce: account.nonce.unwrap_or_default(),
balance: account.balance,
bytecode_hash,
}),
storage,
),
);
if let Some(storage) = &account.storage {
let mut storage_changes = reth_provider::post_state::StorageChangeset::new();
for (&key, &value) in storage {
storage_changes
.insert(U256::from_be_bytes(key.0), (U256::ZERO, U256::from_be_bytes(value.0)));
}
state.change_storage(0, *address, storage_changes);
}
}
state.write_to_db(tx, 0)?;
let mut all_reverts_init: RevertsInit = HashMap::new();
all_reverts_init.insert(0, reverts_init);

let bundle = BundleState::new_init(
state_init,
all_reverts_init,
contracts.into_iter().collect(),
vec![],
0,
);

bundle.write_to_db(tx, true)?;

Ok(())
}
Expand Down
33 changes: 17 additions & 16 deletions crates/blockchain-tree/src/blockchain_tree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,7 @@ use reth_primitives::{
};
use reth_provider::{
chain::{ChainSplit, SplitAt},
post_state::PostState,
BlockExecutionWriter, BlockNumReader, BlockWriter, CanonStateNotification,
BlockExecutionWriter, BlockNumReader, BlockWriter, BundleState, CanonStateNotification,
CanonStateNotificationSender, CanonStateNotifications, Chain, DatabaseProvider,
DisplayBlocksChain, ExecutorFactory, HeaderProvider,
};
Expand Down Expand Up @@ -286,7 +285,7 @@ impl<DB: Database, C: Consensus, EF: ExecutorFactory> BlockchainTree<DB, C, EF>
trace!(target: "blockchain_tree", ?block_hash, "Constructing post state data based on canonical chain");
return Some(PostStateData {
canonical_fork: ForkBlock { number: canonical_number, hash: block_hash },
state: PostState::new(),
state: BundleState::default(),
parent_block_hashed: self.canonical_chain().inner().clone(),
})
}
Expand Down Expand Up @@ -960,6 +959,7 @@ impl<DB: Database, C: Consensus, EF: ExecutorFactory> BlockchainTree<DB, C, EF>
target: "blockchain_tree",
"Committing new canonical chain: {}", DisplayBlocksChain(new_canon_chain.blocks())
);

// if joins to the tip;
if new_canon_chain.fork_block_hash() == old_tip.hash {
chain_notification =
Expand Down Expand Up @@ -997,7 +997,6 @@ impl<DB: Database, C: Consensus, EF: ExecutorFactory> BlockchainTree<DB, C, EF>
}
Ok(val) => val,
};

// commit new canonical chain.
self.commit_canonical(new_canon_chain.clone())?;

Expand Down Expand Up @@ -1048,7 +1047,7 @@ impl<DB: Database, C: Consensus, EF: ExecutorFactory> BlockchainTree<DB, C, EF>
let (blocks, state) = chain.into_inner();

provider
.append_blocks_with_post_state(blocks.into_blocks().collect(), state)
.append_blocks_with_bundle_state(blocks.into_blocks().collect(), state)
.map_err(|e| BlockExecutionError::CanonicalCommit { inner: e.to_string() })?;

provider.commit()?;
Expand Down Expand Up @@ -1099,7 +1098,7 @@ impl<DB: Database, C: Consensus, EF: ExecutorFactory> BlockchainTree<DB, C, EF>
if blocks_and_execution.is_empty() {
Ok(None)
} else {
Ok(Some(Chain::new(blocks_and_execution)))
Ok(Some(blocks_and_execution))
}
}

Expand Down Expand Up @@ -1135,21 +1134,24 @@ mod tests {
use crate::block_buffer::BufferedBlocks;
use assert_matches::assert_matches;
use linked_hash_set::LinkedHashSet;
use reth_db::{test_utils::create_test_rw_db, transaction::DbTxMut, DatabaseEnv};
use reth_db::{
mdbx::{Env, WriteMap},
test_utils::create_test_rw_db,
transaction::DbTxMut,
};
use reth_interfaces::test_utils::TestConsensus;
use reth_primitives::{
proofs::EMPTY_ROOT, stage::StageCheckpoint, ChainSpecBuilder, H256, MAINNET,
};
use reth_provider::{
post_state::PostState,
test_utils::{blocks::BlockChainTestData, TestExecutorFactory},
BlockWriter, ProviderFactory,
BlockWriter, BundleState, ProviderFactory,
};
use std::{collections::HashSet, sync::Arc};

fn setup_externals(
exec_res: Vec<PostState>,
) -> TreeExternals<Arc<DatabaseEnv>, Arc<TestConsensus>, TestExecutorFactory> {
exec_res: Vec<BundleState>,
) -> TreeExternals<Arc<Env<WriteMap>>, Arc<TestConsensus>, TestExecutorFactory> {
let db = create_test_rw_db();
let consensus = Arc::new(TestConsensus::default());
let chain_spec = Arc::new(
Expand Down Expand Up @@ -1282,10 +1284,10 @@ mod tests {
BlockchainTree::new(externals, sender, config).expect("failed to create tree");

// genesis block 10 is already canonical
assert!(tree.make_canonical(&H256::zero()).is_ok());
tree.make_canonical(&H256::zero()).unwrap();

// make sure is_block_hash_canonical returns true for genesis block
assert!(tree.is_block_hash_canonical(&H256::zero()).unwrap());
tree.is_block_hash_canonical(&H256::zero()).unwrap();

// make genesis block 10 as finalized
tree.finalize_block(10);
Expand Down Expand Up @@ -1495,8 +1497,7 @@ mod tests {
assert!(tree.is_block_hash_canonical(&block1a.hash).unwrap());

// make b2 canonical
assert!(tree.make_canonical(&block2.hash()).is_ok());

tree.make_canonical(&block2.hash()).unwrap();
// Trie state:
// b2 b2a (side chain)
// | /
Expand Down Expand Up @@ -1565,7 +1566,7 @@ mod tests {
.assert(&tree);

// commit b2a
assert!(tree.make_canonical(&block2.hash).is_ok());
tree.make_canonical(&block2.hash).unwrap();

// Trie state:
// b2 b2a (side chain)
Expand Down
Loading

0 comments on commit a32615e

Please sign in to comment.