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

EVM: get_transaction_receipt & eth_call endpoints implementation. #513

Merged
merged 2 commits into from
Jul 19, 2023
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
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ ethers-providers = "2.0.8"
ethers-signers = { version = "2.0.8", default-features = false }
ethers-middleware = "2.0.8"

# todo https://github.com/Sovereign-Labs/sovereign-sdk/issues/498
# TODO https://github.com/Sovereign-Labs/sovereign-sdk/issues/498
anvil = { git = "https://github.com/foundry-rs/foundry", rev = "684d394db587bef427475a660c72013e97ef71d2" }
anvil-core = { git = "https://github.com/foundry-rs/foundry", features = ["fastrlp", "serde"], rev = "684d394db587bef427475a660c72013e97ef71d2" }

2 changes: 1 addition & 1 deletion examples/demo-rollup/rollup_config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ start_height = 1

[da]
# The JWT used to authenticate with the celestia light client. Instructions for generating this token can be found in the README
celestia_rpc_auth_token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJBbGxvdyI6WyJwdWJsaWMiLCJyZWFkIiwid3JpdGUiLCJhZG1pbiJdfQ.jp_hghhRkcur3g0o-QhQnkLt89YPu4oykLtZW52_ZA0"
celestia_rpc_auth_token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJBbGxvdyI6WyJwdWJsaWMiLCJyZWFkIiwid3JpdGUiLCJhZG1pbiJdfQ.i6Cx-WziFU3Jcz2INKii2uMCareIZHDDMR0v8zW5zZc"
bkolad marked this conversation as resolved.
Show resolved Hide resolved
# The address of the *trusted* Celestia light client to interact with
celestia_rpc_address = "http://127.0.0.1:26658"
# The largest response the rollup will accept from the Celestia node. Defaults to 100 MB
Expand Down
8 changes: 4 additions & 4 deletions full-node/sov-ethereum/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -127,8 +127,8 @@ pub mod experimental {

let raw_tx = {
let mut nonces = ethereum.nonces.lock().unwrap();
let n = nonces.entry(sender).and_modify(|n| *n += 1).or_insert(0);
make_raw_tx(evm_transaction, *n)?
let nonce = nonces.entry(sender).and_modify(|n| *n += 1).or_insert(0);
make_raw_tx(evm_transaction, *nonce)?
};

ethereum.send_tx_to_da(raw_tx).await?;
Expand All @@ -142,8 +142,8 @@ pub mod experimental {
fn make_raw_tx(evm_tx: EvmTransaction, nonce: u64) -> Result<Vec<u8>, std::io::Error> {
let tx = CallMessage { tx: evm_tx };
let message = Runtime::<DefaultContext>::encode_evm_call(tx);
// todo don't generate sender here.
let sender = DefaultPrivateKey::generate();
// TODO https://github.com/Sovereign-Labs/sovereign-sdk/issues/514
let sender = DefaultPrivateKey::from_hex("236e80cb222c4ed0431b093b3ac53e6aa7a2273fe1f4351cd354989a823432a27b758bf2e7670fafaf6bf0015ce0ff5aa802306fc7e3f45762853ffc37180fe6").unwrap();
let tx = Transaction::<DefaultContext>::new_signed_tx(&sender, message, nonce);
tx.try_to_vec()
}
Expand Down
2 changes: 2 additions & 0 deletions module-system/module-implementations/sov-evm/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ ethers-middleware = { workspace = true }
ethers-providers = { workspace = true }
ethers-signers = { workspace = true }


anvil = { workspace = true }
anvil-core = { workspace = true }
ethers = { workspace = true }

Expand Down
37 changes: 32 additions & 5 deletions module-system/module-implementations/sov-evm/src/call.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@ use revm::primitives::CfgEnv;
use sov_modules_api::CallResponse;
use sov_state::WorkingSet;

use crate::evm::contract_address;
use crate::evm::db::EvmDb;
use crate::evm::executor::{self};
use crate::evm::transaction::EvmTransaction;
use crate::Evm;
use crate::{Evm, TransactionReceipt};

#[cfg_attr(
feature = "native",
Expand All @@ -25,17 +26,43 @@ impl<C: sov_modules_api::Context> Evm<C> {
_context: &C,
working_set: &mut WorkingSet<C::Storage>,
) -> Result<CallResponse> {
// TODO https://github.com/Sovereign-Labs/sovereign-sdk/issues/515
// https://github.com/Sovereign-Labs/sovereign-sdk/issues/516
let cfg_env = CfgEnv::default();
let block_env = self.block_env.get(working_set).unwrap_or_default();

self.transactions.set(&tx.hash, &tx, working_set);

let evm_db: EvmDb<'_, C> = self.get_db(working_set);

// It is ok to use the unwrap here because the error type is `Infallible`.
let result = executor::execute_tx(evm_db, block_env, tx, cfg_env).unwrap();
// TODO https://github.com/Sovereign-Labs/sovereign-sdk/issues/505
let result = executor::execute_tx(evm_db, block_env, tx.clone(), cfg_env).unwrap();

let receipt = TransactionReceipt {
transaction_hash: tx.hash,
// TODO https://github.com/Sovereign-Labs/sovereign-sdk/issues/504
transaction_index: 0,
// TODO https://github.com/Sovereign-Labs/sovereign-sdk/issues/504
block_hash: Default::default(),
// TODO https://github.com/Sovereign-Labs/sovereign-sdk/issues/504
block_number: Some(0),
from: tx.sender,
to: tx.to,
// TODO https://github.com/Sovereign-Labs/sovereign-sdk/issues/504
cumulative_gas_used: Default::default(),
// TODO https://github.com/Sovereign-Labs/sovereign-sdk/issues/504
gas_used: Default::default(),
contract_address: contract_address(result).map(|addr| addr.into()),
// TODO https://github.com/Sovereign-Labs/sovereign-sdk/issues/504
status: Some(1),
root: Default::default(),
// TODO https://github.com/Sovereign-Labs/sovereign-sdk/issues/504
transaction_type: Some(1),
effective_gas_price: Default::default(),
};

self.receipts
.set(&receipt.transaction_hash, &receipt, working_set);

println!("Result {:?}", result);
Ok(CallResponse::default())
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use anvil_core::eth::transaction::EIP1559Transaction;
use anvil_core::eth::transaction::{EIP1559Transaction, EthTransactionRequest};
use bytes::Bytes;
use ethers_core::types::{OtherFields, Transaction};
use revm::primitives::{
Expand Down Expand Up @@ -105,15 +105,15 @@ impl From<EvmTransaction> for Transaction {
max_priority_fee_per_gas: Some(evm_tx.max_priority_fee_per_gas.into()),
max_fee_per_gas: Some(evm_tx.max_fee_per_gas.into()),
chain_id: Some(evm_tx.chain_id.into()),
// todo
// TODO https://github.com/Sovereign-Labs/sovereign-sdk/issues/503
block_hash: Some([0; 32].into()),
// todo
// TODO https://github.com/Sovereign-Labs/sovereign-sdk/issues/503
block_number: Some(1.into()),
// todo
// TODO https://github.com/Sovereign-Labs/sovereign-sdk/issues/503
transaction_index: Some(1.into()),
// todo
// TODO https://github.com/Sovereign-Labs/sovereign-sdk/issues/503
gas: Default::default(),
// todo
// TODO https://github.com/Sovereign-Labs/sovereign-sdk/issues/503
other: OtherFields::default(),
}
}
Expand All @@ -123,7 +123,7 @@ impl From<EIP1559Transaction> for EvmTransaction {
fn from(transaction: EIP1559Transaction) -> Self {
let to = transaction.kind.as_call().map(|addr| (*addr).into());
let tx_hash = transaction.hash();
// todo error handling
// TODO https://github.com/Sovereign-Labs/sovereign-sdk/issues/515
let sender = transaction.recover().unwrap();

Self {
Expand All @@ -137,14 +137,41 @@ impl From<EIP1559Transaction> for EvmTransaction {
to,
value: transaction.value.into(),
nonce: transaction.nonce.as_u64(),
// todo
// TODO https://github.com/Sovereign-Labs/sovereign-sdk/issues/503
access_lists: vec![],
chain_id: transaction.chain_id,
// todo remove it
// TODO https://github.com/Sovereign-Labs/sovereign-sdk/issues/503
hash: tx_hash.into(),
odd_y_parity: transaction.odd_y_parity,
r: transaction.r.into(),
s: transaction.s.into(),
}
}
}

impl From<EthTransactionRequest> for EvmTransaction {
fn from(req: EthTransactionRequest) -> Self {
Self {
sender: req.from.map(|addr| addr.into()).unwrap(),
data: req.data.map(|d| d.to_vec()).unwrap_or_default(),
gas_limit: req.gas.unwrap_or_default().as_u64(),
gas_price: req.gas_price.unwrap_or_default().into(),
max_priority_fee_per_gas: req.max_priority_fee_per_gas.unwrap_or_default().into(),
max_fee_per_gas: req.max_fee_per_gas.unwrap_or_default().into(),
to: req.to.map(|to| to.into()),
value: req.value.unwrap_or_default().into(),
nonce: req.nonce.unwrap_or_default().as_u64(),
// TODO https://github.com/Sovereign-Labs/sovereign-sdk/issues/503
access_lists: Default::default(),
chain_id: req.chain_id.unwrap_or_default().as_u64(),
// TODO https://github.com/Sovereign-Labs/sovereign-sdk/issues/515
odd_y_parity: Default::default(),
// TODO https://github.com/Sovereign-Labs/sovereign-sdk/issues/515
r: Default::default(),
// TODO https://github.com/Sovereign-Labs/sovereign-sdk/issues/515
s: Default::default(),
// TODO https://github.com/Sovereign-Labs/sovereign-sdk/issues/503
hash: Default::default(),
}
}
}
24 changes: 23 additions & 1 deletion module-system/module-implementations/sov-evm/src/evm/executor.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use std::convert::Infallible;

use revm::primitives::{CfgEnv, EVMError, Env, ExecutionResult};
use anvil::eth::backend::mem::inspector::Inspector;
use revm::primitives::{CfgEnv, EVMError, Env, ExecutionResult, ResultAndState};
use revm::{self, Database, DatabaseCommit};

use super::transaction::{BlockEnv, EvmTransaction};
Expand All @@ -23,3 +24,24 @@ pub(crate) fn execute_tx<DB: Database<Error = Infallible> + DatabaseCommit>(
evm.database(db);
evm.transact_commit()
}

pub(crate) fn inspect<DB: Database<Error = Infallible> + DatabaseCommit>(
db: DB,
block_env: BlockEnv,
tx: EvmTransaction,
config_env: CfgEnv,
) -> Result<ResultAndState, EVMError<Infallible>> {
let mut evm = revm::new();

let env = Env {
cfg: config_env,
block: block_env.into(),
tx: tx.into(),
};

evm.env = env;
evm.database(db);

let mut inspector = Inspector::default();
evm.inspect(&mut inspector)
}
11 changes: 11 additions & 0 deletions module-system/module-implementations/sov-evm/src/evm/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use revm::primitives::{ExecutionResult, Output, B160};
use sov_state::Prefix;

mod conversions;
Expand Down Expand Up @@ -56,3 +57,13 @@ impl DbAccount {
Prefix::new(prefix)
}
}

pub(crate) fn contract_address(result: ExecutionResult) -> Option<B160> {
match result {
ExecutionResult::Success {
output: Output::Create(_, Some(addr)),
..
} => Some(addr),
_ => None,
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use std::path::PathBuf;
use ethers_contract::BaseContract;
use ethers_core::abi::Abi;
use ethers_core::types::Bytes;
use revm::primitives::{ExecutionResult, Output, B160};
use revm::primitives::{ExecutionResult, Output};

pub(crate) fn output(result: ExecutionResult) -> bytes::Bytes {
match result {
Expand All @@ -15,16 +15,6 @@ pub(crate) fn output(result: ExecutionResult) -> bytes::Bytes {
}
}

pub(crate) fn contract_address(result: ExecutionResult) -> B160 {
match result {
ExecutionResult::Success {
output: Output::Create(_, Some(addr)),
..
} => addr,
_ => panic!("Expected successful contract creation"),
}
}

fn test_data_path() -> PathBuf {
let mut path = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
path.push("src");
Expand Down
6 changes: 3 additions & 3 deletions module-system/module-implementations/sov-evm/src/evm/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ use sov_state::{ProverStorage, WorkingSet};
use super::db::EvmDb;
use super::db_init::InitEvmDb;
use super::executor;
use crate::evm::test_helpers::{contract_address, output, SimpleStorageContract};
use crate::evm::test_helpers::{output, SimpleStorageContract};
use crate::evm::transaction::{BlockEnv, EvmTransaction};
use crate::evm::AccountInfo;
use crate::evm::{contract_address, AccountInfo};
use crate::Evm;

type C = sov_modules_api::default_context::DefaultContext;
Expand Down Expand Up @@ -58,7 +58,7 @@ fn simple_contract_execution<DB: Database<Error = Infallible> + DatabaseCommit +

let result =
executor::execute_tx(&mut evm_db, BlockEnv::default(), tx, CfgEnv::default()).unwrap();
contract_address(result)
contract_address(result).expect("Expected successful contract creation")
};

let set_arg = 21989;
Expand Down
8 changes: 8 additions & 0 deletions module-system/module-implementations/sov-evm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,14 @@ pub mod genesis;
#[cfg(feature = "experimental")]
pub mod query;
#[cfg(feature = "experimental")]
mod receipt;
#[cfg(feature = "experimental")]
#[cfg(test)]
mod tests;
#[cfg(feature = "experimental")]
pub use experimental::{AccountData, Evm, EvmConfig};
#[cfg(feature = "experimental")]
pub use receipt::TransactionReceipt;

#[cfg(feature = "experimental")]
mod experimental {
Expand All @@ -24,6 +28,7 @@ mod experimental {
use super::evm::transaction::BlockEnv;
use super::evm::{DbAccount, EthAddress};
use crate::evm::{Bytes32, EvmTransaction};
use crate::TransactionReceipt;

#[derive(Clone)]
pub struct AccountData {
Expand Down Expand Up @@ -63,6 +68,9 @@ mod experimental {

#[state]
pub(crate) transactions: sov_state::StateMap<Bytes32, EvmTransaction>,

#[state]
pub(crate) receipts: sov_state::StateMap<Bytes32, TransactionReceipt>,
}

impl<C: sov_modules_api::Context> sov_modules_api::Module for Evm<C> {
Expand Down
Loading