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

improvement: adjust napi external memory for StateManager #3841

Merged
merged 6 commits into from
Apr 20, 2023
Merged
Show file tree
Hide file tree
Changes from 5 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
3 changes: 1 addition & 2 deletions crates/rethnet_eth/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,10 @@ hash-db = { version = "0.15.2", default-features = false }
hash256-std-hasher = { version = "0.15.2", default-features = false }
hashbrown = { version = "0.13", default-features = false, features = ["ahash"] }
hex = { version = "0.4.3", default-features = false, features = ["alloc"] }
hex-literal = { version = "0.3", default-features = false }
open-fastrlp = { version = "0.1.2", default-features = false, features = ["derive"], optional = true }
primitive-types = { version = "0.11.1", default-features = false, features = ["rlp"] }
reqwest = { version = "0.11", features = ["blocking", "json"] }
revm-primitives = { git = "https://github.com/bluealloy/revm", rev = "8e6f4f2", version = "1.0", default-features = false }
revm-primitives = { git = "https://github.com/bluealloy/revm", rev = "3789509", version = "1.0", default-features = false }
# revm-primitives = { path = "../../../revm/crates/primitives", version = "1.0", default-features = false }
rlp = { version = "0.5.2", default-features = false, features = ["derive"] }
ruint = { version = "1.7.0", default-features = false }
Expand Down
34 changes: 26 additions & 8 deletions crates/rethnet_eth/src/account.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,10 @@

//! Ethereum account types

use hex_literal::hex;

use crate::{trie::KECCAK_NULL_RLP, B256, U256};

/// The KECCAK for empty code.
pub const KECCAK_EMPTY: revm_primitives::B256 = revm_primitives::B256(hex!(
"c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"
));
use revm_primitives::AccountInfo;
pub use revm_primitives::KECCAK_EMPTY;

/// Basic account type.
#[derive(Debug, Clone, PartialEq, Eq)]
Expand All @@ -22,7 +18,7 @@ pub const KECCAK_EMPTY: revm_primitives::B256 = revm_primitives::B256(hex!(
)]
pub struct BasicAccount {
/// Nonce of the account.
pub nonce: U256,
pub nonce: u64,
/// Balance of the account.
pub balance: U256,
/// Storage root of the account.
Expand All @@ -35,13 +31,35 @@ impl Default for BasicAccount {
fn default() -> Self {
BasicAccount {
balance: U256::ZERO,
nonce: U256::ZERO,
nonce: 0,
code_hash: KECCAK_EMPTY,
storage_root: KECCAK_NULL_RLP,
}
}
}

impl From<BasicAccount> for AccountInfo {
fn from(account: BasicAccount) -> Self {
Self {
balance: account.balance,
nonce: account.nonce,
code_hash: account.code_hash,
code: None,
}
}
}

impl From<(&AccountInfo, B256)> for BasicAccount {
fn from((account_info, storage_root): (&AccountInfo, B256)) -> Self {
Self {
nonce: account_info.nonce,
balance: account_info.balance,
storage_root,
code_hash: account_info.code_hash,
}
}
}

impl rlp::Encodable for BasicAccount {
fn rlp_append(&self, stream: &mut rlp::RlpStream) {
stream.begin_list(4);
Expand Down
1 change: 1 addition & 0 deletions crates/rethnet_eth/src/remote.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ pub enum RpcClientError {
}

/// A client for executing RPC methods on a remote Ethereum node
#[derive(Debug)]
pub struct RpcClient {
url: String,
client: reqwest::Client,
Expand Down
14 changes: 10 additions & 4 deletions crates/rethnet_eth/src/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,22 @@ pub type State = HashMap<Address, BasicAccount>;
pub type Storage = HashMap<U256, U256>;

/// Calculates the state root hash of the provided state.
pub fn state_root(state: &State) -> B256 {
sec_trie_root(state.iter().map(|(address, account)| {
pub fn state_root<'a, I>(state: I) -> B256
where
I: IntoIterator<Item = (&'a Address, &'a BasicAccount)>,
{
sec_trie_root(state.into_iter().map(|(address, account)| {
let account = rlp::encode(account);
(address, account)
}))
}

/// Calculates the storage root hash of the provided storage.
pub fn storage_root(storage: &Storage) -> B256 {
sec_trie_root(storage.iter().map(|(index, value)| {
pub fn storage_root<'a, I>(storage: I) -> B256
where
I: IntoIterator<Item = (&'a U256, &'a U256)>,
{
sec_trie_root(storage.into_iter().map(|(index, value)| {
let value = rlp::encode(value);
(index.to_be_bytes::<32>(), value)
}))
Expand Down
11 changes: 10 additions & 1 deletion crates/rethnet_evm/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,23 @@ edition = "2021"

[dependencies]
auto_impl = { version = "1.0.1", default-features = false }
cita_trie = { git = "https://github.com/Wodann/cita-trie", rev = "60efef5", version = "4.0.0", default-features = false }
hashbrown = { version = "0.13", default-features = false, features = ["ahash", "serde"] }
hasher = { git = "https://github.com/Wodann/hasher", rev = "89d3fc9", version = "0.1.4", default-features = false, features = ["hash-keccak"] }
log = { version = "0.4.17", default-features = false }
parking_lot = { version = "0.12.1", default-features = false }
rethnet_eth = { version = "0.1.0-dev", path = "../rethnet_eth", features = ["serde"] }
revm = { git = "https://github.com/bluealloy/revm", rev = "8e6f4f2", version = "3.0", default-features = false, features = ["dev", "serde", "std"] }
revm = { git = "https://github.com/bluealloy/revm", rev = "3789509", version = "3.0", default-features = false, features = ["dev", "serde", "std"] }
# revm = { path = "../../../revm/crates/revm", version = "3.0", default-features = false, features = ["dev", "serde", "std"] }
rlp = { version = "0.5.2", default-features = false }
serde = { version = "1.0.158", default-features = false, features = ["std"] }
serde_json = { version = "1.0.94", default-features = false, features = ["std"] }
thiserror = { version = "1.0.38", default-features = false }
tokio = { version = "1.21.2", default-features = false, features = ["rt-multi-thread", "sync"] }
tracing = { version = "0.1.37", features = ["attributes", "std"], optional = true }

[dev-dependencies]
test-with = { version = "0.9.1", default-features = false }

[features]
tracing = ["dep:tracing"]
14 changes: 9 additions & 5 deletions crates/rethnet_evm/src/block/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,15 @@ use rethnet_eth::{
use revm::{
db::DatabaseComponentError,
primitives::{BlockEnv, CfgEnv, EVMError, ExecutionResult, InvalidTransaction, SpecId, TxEnv},
Inspector,
};
use tokio::runtime::Runtime;

use crate::{
blockchain::AsyncBlockchain, evm::run_transaction, runtime::AsyncDatabase, state::AsyncState,
trace::Trace, HeaderData,
blockchain::AsyncBlockchain,
evm::{run_transaction, AsyncInspector},
state::{AccountModifierFn, AsyncState},
trace::Trace,
HeaderData,
};

#[derive(Debug, thiserror::Error)]
Expand Down Expand Up @@ -116,7 +118,7 @@ where
pub async fn add_transaction(
&mut self,
transaction: TxEnv,
inspector: Option<Box<dyn Inspector<AsyncDatabase<BE, SE>> + Send>>,
inspector: Option<Box<dyn AsyncInspector<BE, SE>>>,
) -> Result<(ExecutionResult, Trace), BlockTransactionError<BE, SE>> {
// transaction's gas limit cannot be greater than the remaining gas in the block
if U256::from(transaction.gas_limit) > self.gas_remaining() {
Expand Down Expand Up @@ -165,7 +167,9 @@ where
self.state
.modify_account(
address,
Box::new(move |balance, _nonce, _code| *balance += reward),
AccountModifierFn::new(Box::new(move |balance, _nonce, _code| {
*balance += reward;
})),
)
.await?;
}
Expand Down
1 change: 1 addition & 0 deletions crates/rethnet_evm/src/blockchain/sync.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ where
/// A helper class for converting a synchronous blockchain into an asynchronous blockchain.
///
/// Requires the inner blockchain to implement [`Blockchain`].
#[derive(Debug)]
pub struct AsyncBlockchain<E>
where
E: Debug + Send,
Expand Down
12 changes: 11 additions & 1 deletion crates/rethnet_evm/src/evm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,17 @@ use crate::{
trace::{Trace, TraceCollector},
};

/// Super trait for an inspector of an `AsyncDatabase` that's debuggable.
pub trait AsyncInspector<BE, SE>: Inspector<AsyncDatabase<BE, SE>> + Debug + Send
where
BE: Debug + Send + 'static,
SE: Debug + Send + 'static,
{
}

/// Creates an evm from the provided database, config, transaction, and block.
#[allow(clippy::type_complexity)]
#[cfg_attr(feature = "tracing", tracing::instrument)]
fn build_evm<BE, SE>(
blockchain: Arc<AsyncBlockchain<BE>>,
state: Arc<AsyncState<SE>>,
Expand All @@ -41,14 +50,15 @@ where
}

#[allow(clippy::type_complexity)]
#[cfg_attr(feature = "tracing", tracing::instrument)]
pub fn run_transaction<BE, SE>(
runtime: &Runtime,
blockchain: Arc<AsyncBlockchain<BE>>,
state: Arc<AsyncState<SE>>,
cfg: CfgEnv,
transaction: TxEnv,
block: BlockEnv,
inspector: Option<Box<dyn Inspector<AsyncDatabase<BE, SE>> + Send>>,
inspector: Option<Box<dyn AsyncInspector<BE, SE>>>,
) -> JoinHandle<Result<(ExecutionResult, State, Trace), EVMError<DatabaseComponentError<SE, BE>>>>
where
BE: Debug + Send + 'static,
Expand Down
1 change: 1 addition & 0 deletions crates/rethnet_evm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ pub use revm::{

pub use crate::{
block::{BlockBuilder, HeaderData},
evm::AsyncInspector,
runtime::{AsyncDatabase, Rethnet},
transaction::{PendingTransaction, TransactionError},
};
Expand Down
19 changes: 13 additions & 6 deletions crates/rethnet_evm/src/runtime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,22 @@ use std::{fmt::Debug, sync::Arc};
use revm::{
db::DatabaseComponents,
primitives::{BlockEnv, CfgEnv, ExecutionResult, SpecId, TxEnv},
Inspector,
};

use crate::{
blockchain::AsyncBlockchain, evm::run_transaction, state::AsyncState, trace::Trace,
transaction::TransactionError, State,
blockchain::AsyncBlockchain,
evm::{run_transaction, AsyncInspector},
state::AsyncState,
trace::Trace,
transaction::TransactionError,
State,
};

/// Asynchronous implementation of the Database super-trait
pub type AsyncDatabase<BE, SE> = DatabaseComponents<Arc<AsyncState<SE>>, Arc<AsyncBlockchain<BE>>>;

/// The asynchronous Rethnet runtime.
#[derive(Debug)]
pub struct Rethnet<BE, SE>
where
BE: Debug + Send + 'static,
Expand All @@ -40,11 +44,12 @@ where
}

/// Runs a transaction without committing the state.
#[cfg_attr(feature = "tracing", tracing::instrument)]
pub async fn dry_run(
&self,
transaction: TxEnv,
block: BlockEnv,
inspector: Option<Box<dyn Inspector<AsyncDatabase<BE, SE>> + Send>>,
inspector: Option<Box<dyn AsyncInspector<BE, SE>>>,
) -> Result<(ExecutionResult, State, Trace), TransactionError<BE, SE>> {
if self.cfg.spec_id > SpecId::MERGE && block.prevrandao.is_none() {
return Err(TransactionError::MissingPrevrandao);
Expand All @@ -65,11 +70,12 @@ where
}

/// Runs a transaction without committing the state, while disabling balance checks and creating accounts for new addresses.
#[cfg_attr(feature = "tracing", tracing::instrument)]
pub async fn guaranteed_dry_run(
&self,
transaction: TxEnv,
block: BlockEnv,
inspector: Option<Box<dyn Inspector<AsyncDatabase<BE, SE>> + Send>>,
inspector: Option<Box<dyn AsyncInspector<BE, SE>>>,
) -> Result<(ExecutionResult, State, Trace), TransactionError<BE, SE>> {
if self.cfg.spec_id > SpecId::MERGE && block.prevrandao.is_none() {
return Err(TransactionError::MissingPrevrandao);
Expand All @@ -93,11 +99,12 @@ where
}

/// Runs a transaction, committing the state in the process.
#[cfg_attr(feature = "tracing", tracing::instrument)]
pub async fn run(
&self,
transaction: TxEnv,
block: BlockEnv,
inspector: Option<Box<dyn Inspector<AsyncDatabase<BE, SE>> + Send>>,
inspector: Option<Box<dyn AsyncInspector<BE, SE>>>,
) -> Result<(ExecutionResult, Trace), TransactionError<BE, SE>> {
let (result, changes, trace) = self.dry_run(transaction, block, inspector).await?;

Expand Down
11 changes: 9 additions & 2 deletions crates/rethnet_evm/src/state.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,21 @@
mod account;
mod contract;
mod debug;
mod layered_state;
mod history;
mod hybrid;
mod layered;
mod remote;
mod request;
mod sync;
mod trie;

use rethnet_eth::B256;

pub use self::{
debug::{AccountModifierFn, StateDebug},
layered_state::{LayeredState, RethnetLayer},
history::StateHistory,
hybrid::HybridState,
layered::{LayeredState, RethnetLayer},
remote::RemoteDatabase,
sync::{AsyncState, SyncState},
};
Expand Down
17 changes: 17 additions & 0 deletions crates/rethnet_evm/src/state/account.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
use rethnet_eth::state::Storage;
use revm::primitives::AccountInfo;

#[derive(Clone, Debug, Default)]
pub struct RethnetAccount {
pub info: AccountInfo,
pub storage: Storage,
}

impl From<AccountInfo> for RethnetAccount {
fn from(info: AccountInfo) -> Self {
Self {
info,
storage: Default::default(),
}
}
}
Loading