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

booster #4

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
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
21 changes: 11 additions & 10 deletions crates/interpreter/src/host.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use crate::{

mod dummy;
pub use dummy::DummyHost;
use revm_primitives::ChainAddress;

/// EVM context host.
pub trait Host {
Expand All @@ -17,39 +18,39 @@ pub trait Host {
/// Load an account.
///
/// Returns (is_cold, is_new_account)
fn load_account(&mut self, address: Address) -> Option<(bool, bool)>;
fn load_account(&mut self, address: ChainAddress) -> Option<(bool, bool)>;

/// Get the block hash of the given block `number`.
fn block_hash(&mut self, number: U256) -> Option<B256>;
fn block_hash(&mut self, chain_id: u64, number: U256) -> Option<B256>;

/// Get balance of `address` and if the account is cold.
fn balance(&mut self, address: Address) -> Option<(U256, bool)>;
fn balance(&mut self, address: ChainAddress) -> Option<(U256, bool)>;

/// Get code of `address` and if the account is cold.
fn code(&mut self, address: Address) -> Option<(Bytecode, bool)>;
fn code(&mut self, address: ChainAddress) -> Option<(Bytecode, bool)>;

/// Get code hash of `address` and if the account is cold.
fn code_hash(&mut self, address: Address) -> Option<(B256, bool)>;
fn code_hash(&mut self, address: ChainAddress) -> Option<(B256, bool)>;

/// Get storage value of `address` at `index` and if the account is cold.
fn sload(&mut self, address: Address, index: U256) -> Option<(U256, bool)>;
fn sload(&mut self, address: ChainAddress, index: U256) -> Option<(U256, bool)>;

/// Set storage value of account address at index.
///
/// Returns (original, present, new, is_cold).
fn sstore(&mut self, address: Address, index: U256, value: U256) -> Option<SStoreResult>;
fn sstore(&mut self, address: ChainAddress, index: U256, value: U256) -> Option<SStoreResult>;

/// Get the transient storage value of `address` at `index`.
fn tload(&mut self, address: Address, index: U256) -> U256;
fn tload(&mut self, address: ChainAddress, index: U256) -> U256;

/// Set the transient storage value of `address` at `index`.
fn tstore(&mut self, address: Address, index: U256, value: U256);
fn tstore(&mut self, address: ChainAddress, index: U256, value: U256);

/// Emit a log owned by `address` with given `LogData`.
fn log(&mut self, log: Log);

/// Mark `address` to be deleted, with funds transferred to `target`.
fn selfdestruct(&mut self, address: Address, target: Address) -> Option<SelfDestructResult>;
fn selfdestruct(&mut self, address: ChainAddress, target: ChainAddress) -> Option<SelfDestructResult>;
}

/// Represents the result of an `sstore` operation.
Expand Down
26 changes: 16 additions & 10 deletions crates/interpreter/src/host/dummy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use crate::{
Host, SStoreResult, SelfDestructResult,
};
use std::vec::Vec;
use revm_primitives::ChainAddress;

/// A dummy [Host] implementation.
#[derive(Clone, Debug, Default, PartialEq, Eq)]
Expand Down Expand Up @@ -44,32 +45,32 @@ impl Host for DummyHost {
}

#[inline]
fn load_account(&mut self, _address: Address) -> Option<(bool, bool)> {
fn load_account(&mut self, _address: ChainAddress) -> Option<(bool, bool)> {
Some((true, true))
}

#[inline]
fn block_hash(&mut self, _number: U256) -> Option<B256> {
fn block_hash(&mut self, _chain_id: u64, _number: U256) -> Option<B256> {
Some(B256::ZERO)
}

#[inline]
fn balance(&mut self, _address: Address) -> Option<(U256, bool)> {
fn balance(&mut self, _address: ChainAddress) -> Option<(U256, bool)> {
Some((U256::ZERO, false))
}

#[inline]
fn code(&mut self, _address: Address) -> Option<(Bytecode, bool)> {
fn code(&mut self, _address: ChainAddress) -> Option<(Bytecode, bool)> {
Some((Bytecode::default(), false))
}

#[inline]
fn code_hash(&mut self, __address: Address) -> Option<(B256, bool)> {
fn code_hash(&mut self, __address: ChainAddress) -> Option<(B256, bool)> {
Some((KECCAK_EMPTY, false))
}

#[inline]
fn sload(&mut self, __address: Address, index: U256) -> Option<(U256, bool)> {
fn sload(&mut self, __address: ChainAddress, index: U256) -> Option<(U256, bool)> {
match self.storage.entry(index) {
Entry::Occupied(entry) => Some((*entry.get(), false)),
Entry::Vacant(entry) => {
Expand All @@ -80,7 +81,12 @@ impl Host for DummyHost {
}

#[inline]
fn sstore(&mut self, _address: Address, index: U256, value: U256) -> Option<SStoreResult> {
fn sstore(
&mut self,
_address: ChainAddress,
index: U256,
value: U256,
) -> Option<(U256, U256, U256, bool)> {
let (present, is_cold) = match self.storage.entry(index) {
Entry::Occupied(mut entry) => (entry.insert(value), false),
Entry::Vacant(entry) => {
Expand All @@ -98,15 +104,15 @@ impl Host for DummyHost {
}

#[inline]
fn tload(&mut self, _address: Address, index: U256) -> U256 {
fn tload(&mut self, _address: ChainAddress, index: U256) -> U256 {
self.transient_storage
.get(&index)
.copied()
.unwrap_or_default()
}

#[inline]
fn tstore(&mut self, _address: Address, index: U256, value: U256) {
fn tstore(&mut self, _address: ChainAddress, index: U256, value: U256) {
self.transient_storage.insert(index, value);
}

Expand All @@ -116,7 +122,7 @@ impl Host for DummyHost {
}

#[inline]
fn selfdestruct(&mut self, _address: Address, _target: Address) -> Option<SelfDestructResult> {
fn selfdestruct(&mut self, _address: ChainAddress, _target: ChainAddress) -> Option<SelfDestructResult> {
panic!("Selfdestruct is not supported for this host")
}
}
51 changes: 39 additions & 12 deletions crates/interpreter/src/inner_models.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use revm_primitives::ChainAddress;

pub use crate::primitives::CreateScheme;
use crate::primitives::{Address, Bytes, TransactTo, TxEnv, U256};
use core::ops::Range;
Expand All @@ -7,8 +9,10 @@ use std::boxed::Box;
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct CallInputs {
/// Booster: The target chain of the call
pub chain_id: u64,
/// The target of the call.
pub contract: Address,
pub contract: ChainAddress,
/// The transfer, if any, in this call.
pub transfer: Transfer,
/// The call data of the call.
Expand All @@ -21,14 +25,16 @@ pub struct CallInputs {
pub is_static: bool,
/// The return memory offset where the output of the call is written.
pub return_memory_offset: Range<usize>,
/// Booster: Whether this is a sandboxed call.
pub is_sandboxed: bool,
}

/// Inputs for a create call.
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct CreateInputs {
/// Caller address of the EVM.
pub caller: Address,
pub caller: ChainAddress,
/// The create scheme.
pub scheme: CreateScheme,
/// The value to transfer.
Expand Down Expand Up @@ -97,12 +103,33 @@ impl CreateInputs {
/// Returns the address that this create call will create.
pub fn created_address(&self, nonce: u64) -> Address {
match self.scheme {
CreateScheme::Create => self.caller.create(nonce),
CreateScheme::Create => self.create(nonce),
CreateScheme::Create2 { salt } => self
.caller
.caller.1
.create2_from_code(salt.to_be_bytes(), &self.init_code),
}
}

/// Returns the address that this create call will create, without calculating the init code hash.
///
/// Note: `hash` must be `keccak256(&self.init_code)`.
pub fn created_address_with_hash(&self, nonce: u64, hash: &B256) -> Address {
match self.scheme {
CreateScheme::Create => self.create(nonce),
CreateScheme::Create2 { salt } => self.caller.1.create2(salt.to_be_bytes(), hash),
}
}

/// Modified CREATE address on booster chains
fn create(&self, nonce: u64) -> Address {
// If we're not on L1, change the CREATE address to contain the chain_id
let chain_id = if self.caller.0 != 1 {
Some(self.caller.0)
} else {
None
};
self.caller.1.create(nonce, chain_id)
}
}

/// Call schemes.
Expand All @@ -124,11 +151,11 @@ pub enum CallScheme {
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct CallContext {
/// Execution address.
pub address: Address,
pub address: ChainAddress,
/// Caller address of the EVM.
pub caller: Address,
pub caller: ChainAddress,
/// The address the contract code was loaded from, if any.
pub code_address: Address,
pub code_address: ChainAddress,
/// Apparent value of the EVM.
pub apparent_value: U256,
/// The scheme used for the call.
Expand All @@ -138,9 +165,9 @@ pub struct CallContext {
impl Default for CallContext {
fn default() -> Self {
CallContext {
address: Address::default(),
caller: Address::default(),
code_address: Address::default(),
address: ChainAddress::default(),
caller: ChainAddress::default(),
code_address: ChainAddress::default(),
apparent_value: U256::default(),
scheme: CallScheme::Call,
}
Expand All @@ -152,9 +179,9 @@ impl Default for CallContext {
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct Transfer {
/// The source address.
pub source: Address,
pub source: ChainAddress,
/// The target address.
pub target: Address,
pub target: ChainAddress,
/// The transfer value.
pub value: U256,
}
Expand Down
46 changes: 39 additions & 7 deletions crates/interpreter/src/instructions/host.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@ use crate::{
SStoreResult, Transfer, MAX_INITCODE_SIZE,
};
use core::cmp::min;
use revm_primitives::BLOCK_HASH_HISTORY;
use revm_primitives::{BLOCK_HASH_HISTORY, ChainAddress};
use std::{boxed::Box, vec::Vec};

pub fn balance<H: Host, SPEC: Spec>(interpreter: &mut Interpreter, host: &mut H) {
pop_address!(interpreter, address);
pop_chain_address!(interpreter, address);
let Some((balance, is_cold)) = host.balance(address) else {
interpreter.instruction_result = InstructionResult::FatalExternalError;
return;
Expand Down Expand Up @@ -45,7 +45,7 @@ pub fn selfbalance<H: Host, SPEC: Spec>(interpreter: &mut Interpreter, host: &mu
}

pub fn extcodesize<H: Host, SPEC: Spec>(interpreter: &mut Interpreter, host: &mut H) {
pop_address!(interpreter, address);
pop_chain_address!(interpreter, address);
let Some((code, is_cold)) = host.code(address) else {
interpreter.instruction_result = InstructionResult::FatalExternalError;
return;
Expand All @@ -71,7 +71,7 @@ pub fn extcodesize<H: Host, SPEC: Spec>(interpreter: &mut Interpreter, host: &mu
/// EIP-1052: EXTCODEHASH opcode
pub fn extcodehash<H: Host, SPEC: Spec>(interpreter: &mut Interpreter, host: &mut H) {
check!(interpreter, CONSTANTINOPLE);
pop_address!(interpreter, address);
pop_chain_address!(interpreter, address);
let Some((code_hash, is_cold)) = host.code_hash(address) else {
interpreter.instruction_result = InstructionResult::FatalExternalError;
return;
Expand All @@ -94,7 +94,7 @@ pub fn extcodehash<H: Host, SPEC: Spec>(interpreter: &mut Interpreter, host: &mu
}

pub fn extcodecopy<H: Host, SPEC: Spec>(interpreter: &mut Interpreter, host: &mut H) {
pop_address!(interpreter, address);
pop_chain_address!(interpreter, address);
pop!(interpreter, memory_offset, code_offset, len_u256);

let Some((code, is_cold)) = host.code(address) else {
Expand Down Expand Up @@ -128,7 +128,7 @@ pub fn blockhash<H: Host>(interpreter: &mut Interpreter, host: &mut H) {
let diff = as_usize_saturated!(diff);
// blockhash should push zero if number is same as current block number.
if diff <= BLOCK_HASH_HISTORY && diff != 0 {
let Some(hash) = host.block_hash(*number) else {
let Some(hash) = host.block_hash(interpreter.chain_id, *number) else {
interpreter.instruction_result = InstructionResult::FatalExternalError;
return;
};
Expand Down Expand Up @@ -229,7 +229,7 @@ pub fn log<const N: usize, H: Host>(interpreter: &mut Interpreter, host: &mut H)

pub fn selfdestruct<H: Host, SPEC: Spec>(interpreter: &mut Interpreter, host: &mut H) {
check_staticcall!(interpreter);
pop_address!(interpreter, target);
pop_chain_address!(interpreter, target);

let Some(res) = host.selfdestruct(interpreter.contract.address, target) else {
interpreter.instruction_result = InstructionResult::FatalExternalError;
Expand Down Expand Up @@ -377,6 +377,36 @@ pub fn call<H: Host, SPEC: Spec>(interpreter: &mut Interpreter, host: &mut H) {
pub fn call_code<H: Host, SPEC: Spec>(interpreter: &mut Interpreter, host: &mut H) {
pop!(interpreter, local_gas_limit);
pop_address!(interpreter, to);

let call_options = interpreter.call_options.clone().unwrap_or_else(||
CallOptions{
chain_id: interpreter.chain_id,
sandbox: false,
tx_origin: host.env().tx.caller,
msg_sender: interpreter.contract.address,
block_hash: None,
proof: Vec::new(),
}
);
// Consume the values
interpreter.call_options = None;

let to = ChainAddress(call_options.chain_id, to);
// Default to the code stored on L2
let mut code_address = ChainAddress(host.env().cfg.chain_id, to.1);

// load account and calculate gas cost.
let Some((is_cold, exist)) = host.load_account(to) else {
interpreter.instruction_result = InstructionResult::FatalExternalError;
return;
};
let is_new = !exist;

let l2_code_hash = host.code_hash(code_address);
if l2_code_hash.unwrap_or_else(|| (KECCAK_EMPTY, true)).0 == KECCAK_EMPTY {
code_address = ChainAddress(host.env().cfg.chain_id, to.1);
}

// max gas limit is not possible in real ethereum situation.
let local_gas_limit = u64::try_from(local_gas_limit).unwrap_or(u64::MAX);

Expand Down Expand Up @@ -516,6 +546,8 @@ pub fn static_call<H: Host, SPEC: Spec>(interpreter: &mut Interpreter, host: &mu
},
is_static: true,
return_memory_offset,
chain_id: call_options.chain_id,
is_sandboxed: call_options.sandbox,
}),
};
interpreter.instruction_result = InstructionResult::CallOrCreate;
Expand Down
4 changes: 2 additions & 2 deletions crates/interpreter/src/instructions/host_env.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ pub fn chainid<H: Host, SPEC: Spec>(interpreter: &mut Interpreter, host: &mut H)

pub fn coinbase<H: Host>(interpreter: &mut Interpreter, host: &mut H) {
gas!(interpreter, gas::BASE);
push_b256!(interpreter, host.env().block.coinbase.into_word());
push_b256!(interpreter, host.env().block.coinbase.1.into_word());
}

pub fn timestamp<H: Host>(interpreter: &mut Interpreter, host: &mut H) {
Expand Down Expand Up @@ -54,7 +54,7 @@ pub fn basefee<H: Host, SPEC: Spec>(interpreter: &mut Interpreter, host: &mut H)

pub fn origin<H: Host>(interpreter: &mut Interpreter, host: &mut H) {
gas!(interpreter, gas::BASE);
push_b256!(interpreter, host.env().tx.caller.into_word());
push_b256!(interpreter, host.env().tx.caller.1.into_word());
}

// EIP-4844: Shard Blob Transactions
Expand Down
Loading
Loading