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

Extend 0.39.1 with Dencun opcodes #1

Open
wants to merge 4 commits into
base: sp-release-039-1
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
22 changes: 22 additions & 0 deletions core/src/eval/misc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,28 @@ pub fn mstore8(state: &mut Machine) -> Control {
}
}

#[inline]
pub fn mcopy(state: &mut Machine) -> Control {
pop_u256!(state, dst, src, len);

try_or_fail!(state.memory.resize_offset(dst, len));

if len == U256::zero() {
return Control::Continue(1);
}

let src_usize = as_usize_or_fail!(src);
let len_usize = as_usize_or_fail!(len);
let data = state.memory.get(src_usize, len_usize);

// NB: using `set` would be more straighforward but it lacks
// of internal checks.
match state.memory.copy_large(dst, U256::zero(), len, &data) {
Ok(()) => Control::Continue(1),
Err(e) => Control::Exit(e.into()),
}
}

#[inline]
pub fn jump(state: &mut Machine) -> Control {
pop_u256!(state, dest);
Expand Down
5 changes: 5 additions & 0 deletions core/src/eval/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,10 @@ fn eval_mstore8(state: &mut Machine, _opcode: Opcode, _position: usize) -> Contr
self::misc::mstore8(state)
}

fn eval_mcopy(state: &mut Machine, _opcode: Opcode, _position: usize) -> Control {
self::misc::mcopy(state)
}

fn eval_jump(state: &mut Machine, _opcode: Opcode, _position: usize) -> Control {
self::misc::jump(state)
}
Expand Down Expand Up @@ -492,6 +496,7 @@ pub fn eval(state: &mut Machine, opcode: Opcode, position: usize) -> Control {
table[Opcode::MLOAD.as_usize()] = eval_mload as _;
table[Opcode::MSTORE.as_usize()] = eval_mstore as _;
table[Opcode::MSTORE8.as_usize()] = eval_mstore8 as _;
table[Opcode::MCOPY.as_usize()] = eval_mcopy as _;
table[Opcode::JUMP.as_usize()] = eval_jump as _;
table[Opcode::JUMPI.as_usize()] = eval_jumpi as _;
table[Opcode::PC.as_usize()] = eval_pc as _;
Expand Down
8 changes: 8 additions & 0 deletions core/src/opcode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,8 @@ impl Opcode {
pub const MSTORE: Opcode = Opcode(0x52);
/// `MSTORE8`
pub const MSTORE8: Opcode = Opcode(0x53);
/// `MCOPY`
pub const MCOPY: Opcode = Opcode(0x5e);
/// `JUMP`
pub const JUMP: Opcode = Opcode(0x56);
/// `JUMPI`
Expand Down Expand Up @@ -189,6 +191,8 @@ impl Opcode {
pub const SELFBALANCE: Opcode = Opcode(0x47);
/// `BASEFEE`
pub const BASEFEE: Opcode = Opcode(0x48);
/// `BLOBBASEFEE`
pub const BLOBBASEFEE: Opcode = Opcode(0x4a);
/// `ORIGIN`
pub const ORIGIN: Opcode = Opcode(0x32);
/// `CALLER`
Expand Down Expand Up @@ -223,6 +227,10 @@ impl Opcode {
pub const SLOAD: Opcode = Opcode(0x54);
/// `SSTORE`
pub const SSTORE: Opcode = Opcode(0x55);
/// `TLOAD`
pub const TLOAD: Opcode = Opcode(0x5c);
/// `TSTORE`
pub const TSTORE: Opcode = Opcode(0x5d);
/// `GAS`
pub const GAS: Opcode = Opcode(0x5a);
/// `LOGn`
Expand Down
3 changes: 3 additions & 0 deletions runtime/src/eval/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ pub fn eval<H: Handler>(state: &mut Runtime, opcode: Opcode, handler: &mut H) ->
Opcode::GASLIMIT => system::gaslimit(state, handler),
Opcode::SLOAD => system::sload(state, handler),
Opcode::SSTORE => system::sstore(state, handler),
Opcode::TLOAD => system::tload(state, handler),
Opcode::TSTORE => system::tstore(state, handler),
Opcode::GAS => system::gas(state, handler),
Opcode::LOG0 => system::log(state, 0, handler),
Opcode::LOG1 => system::log(state, 1, handler),
Expand All @@ -59,6 +61,7 @@ pub fn eval<H: Handler>(state: &mut Runtime, opcode: Opcode, handler: &mut H) ->
Opcode::STATICCALL => system::call(state, CallScheme::StaticCall, handler),
Opcode::CHAINID => system::chainid(state, handler),
Opcode::BASEFEE => system::base_fee(state, handler),
Opcode::BLOBBASEFEE => system::blob_base_fee(state, handler),
_ => handle_other(state, opcode, handler),
}
}
Expand Down
29 changes: 29 additions & 0 deletions runtime/src/eval/system.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,14 @@ pub fn base_fee<H: Handler>(runtime: &mut Runtime, handler: &H) -> Control<H> {
Control::Continue
}

pub fn blob_base_fee<H: Handler>(runtime: &mut Runtime, handler: &H) -> Control<H> {
let mut ret = H256::default();
handler.block_blob_base_fee().to_big_endian(&mut ret[..]);
push!(runtime, ret);

Control::Continue
}

pub fn extcodesize<H: Handler>(runtime: &mut Runtime, handler: &H) -> Control<H> {
pop!(runtime, address);
push_u256!(runtime, handler.code_size(address.into()));
Expand Down Expand Up @@ -228,6 +236,27 @@ pub fn sstore<H: Handler>(runtime: &mut Runtime, handler: &mut H) -> Control<H>
}
}

pub fn tload<H: Handler>(runtime: &mut Runtime, handler: &H) -> Control<H> {
pop!(runtime, index);
let value = handler.transient_storage(index);
push!(runtime, value);

event!(TLoad { index, value });

Control::Continue
}

pub fn tstore<H: Handler>(runtime: &mut Runtime, handler: &mut H) -> Control<H> {
pop!(runtime, index, value);

event!(TStore { index, value });

match handler.set_transient_storage(index, value) {
Ok(()) => Control::Continue,
Err(e) => Control::Exit(e.into()),
}
}

pub fn gas<H: Handler>(runtime: &mut Runtime, handler: &H) -> Control<H> {
push_u256!(runtime, handler.gas_left());

Expand Down
6 changes: 6 additions & 0 deletions runtime/src/handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ pub trait Handler {
fn code(&self, address: H160) -> Vec<u8>;
/// Get storage value of address at index.
fn storage(&self, address: H160, index: H256) -> H256;
/// Get transient storage value at index.
fn transient_storage(&self, index: H256) -> H256;
/// Get original storage value of address at index.
fn original_storage(&self, address: H160, index: H256) -> H256;

Expand All @@ -60,6 +62,8 @@ pub trait Handler {
fn block_gas_limit(&self) -> U256;
/// Environmental block base fee.
fn block_base_fee_per_gas(&self) -> U256;
/// Returns the value of the blob base-fee of the current block it is executing in.
fn block_blob_base_fee(&self) -> U256;
/// Get environmental chain ID.
fn chain_id(&self) -> U256;

Expand All @@ -77,6 +81,8 @@ pub trait Handler {

/// Set storage value of address at index.
fn set_storage(&mut self, address: H160, index: H256, value: H256) -> Result<(), ExitError>;
/// Set transient storage value at index.
fn set_transient_storage(&mut self, index: H256, value: H256) -> Result<(), ExitError>;
/// Create a log owned by address with given topics and data.
fn log(&mut self, address: H160, topics: Vec<H256>, data: Vec<u8>) -> Result<(), ExitError>;
/// Mark an address to be deleted, with funds transferred to target.
Expand Down
8 changes: 8 additions & 0 deletions runtime/src/tracing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,14 @@ pub enum Event<'a> {
index: H256,
value: H256,
},
TLoad {
index: H256,
value: H256,
},
TStore {
index: H256,
value: H256,
},
}

// Expose `listener::with` to the crate only.
Expand Down
4 changes: 2 additions & 2 deletions rust-toolchain.toml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
[toolchain]
channel = "1.68.2"
channel = "1.70.0"
profile = "minimal"
components = [ "rustfmt", "clippy" ]
components = ["rustfmt", "clippy"]
21 changes: 20 additions & 1 deletion src/backend/memory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ pub struct MemoryVicinity {
pub block_gas_limit: U256,
/// Environmental base fee per gas.
pub block_base_fee_per_gas: U256,
/// Environmental blob base fee.
pub block_blob_base_fee: U256,
/// Environmental randomness.
///
/// In Ethereum, this is the randomness beacon provided by the beacon
Expand Down Expand Up @@ -61,15 +63,21 @@ pub struct MemoryAccount {
pub struct MemoryBackend<'vicinity> {
vicinity: &'vicinity MemoryVicinity,
state: BTreeMap<H160, MemoryAccount>,
transient_state: BTreeMap<H256, H256>,
logs: Vec<Log>,
}

impl<'vicinity> MemoryBackend<'vicinity> {
/// Create a new memory backend.
pub fn new(vicinity: &'vicinity MemoryVicinity, state: BTreeMap<H160, MemoryAccount>) -> Self {
pub fn new(
vicinity: &'vicinity MemoryVicinity,
state: BTreeMap<H160, MemoryAccount>,
transient_state: BTreeMap<H256, H256>,
) -> Self {
Self {
vicinity,
state,
transient_state,
logs: Vec::new(),
}
}
Expand Down Expand Up @@ -125,6 +133,10 @@ impl<'vicinity> Backend for MemoryBackend<'vicinity> {
self.vicinity.block_base_fee_per_gas
}

fn block_blob_base_fee(&self) -> U256 {
self.vicinity.block_blob_base_fee
}

fn chain_id(&self) -> U256 {
self.vicinity.chain_id
}
Expand Down Expand Up @@ -157,6 +169,13 @@ impl<'vicinity> Backend for MemoryBackend<'vicinity> {
.unwrap_or_default()
}

fn transient_storage(&self, index: H256) -> H256 {
self.transient_state
.get(&index)
.cloned()
.unwrap_or_default()
}

fn original_storage(&self, address: H160, index: H256) -> Option<H256> {
Some(self.storage(address, index))
}
Expand Down
4 changes: 4 additions & 0 deletions src/backend/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@ pub trait Backend {
fn block_gas_limit(&self) -> U256;
/// Environmental block base fee.
fn block_base_fee_per_gas(&self) -> U256;
/// Returns the value of the blob base-fee of the current block it is executing in.
fn block_blob_base_fee(&self) -> U256;
/// Environmental chain ID.
fn chain_id(&self) -> U256;

Expand All @@ -83,6 +85,8 @@ pub trait Backend {
fn code(&self, address: H160) -> Vec<u8>;
/// Get storage value of address at index.
fn storage(&self, address: H160, index: H256) -> H256;
/// Get storage value at index.
fn transient_storage(&self, index: H256) -> H256;
/// Get original storage value of address at index, if available.
fn original_storage(&self, address: H160, index: H256) -> Option<H256>;
}
Expand Down
13 changes: 13 additions & 0 deletions src/executor/stack/executor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,7 @@ pub trait StackState<'config>: Backend {

fn inc_nonce(&mut self, address: H160) -> Result<(), ExitError>;
fn set_storage(&mut self, address: H160, key: H256, value: H256);
fn set_transient_storage(&mut self, key: H256, value: H256);
fn reset_storage(&mut self, address: H160);
fn log(&mut self, address: H160, topics: Vec<H256>, data: Vec<u8>);
fn set_deleted(&mut self, address: H160);
Expand Down Expand Up @@ -1047,6 +1048,10 @@ impl<'config, 'precompiles, S: StackState<'config>, P: PrecompileSet> Handler
self.state.storage(address, index)
}

fn transient_storage(&self, index: H256) -> H256 {
self.state.transient_storage(index)
}

fn original_storage(&self, address: H160, index: H256) -> H256 {
self.state
.original_storage(address, index)
Expand Down Expand Up @@ -1121,6 +1126,9 @@ impl<'config, 'precompiles, S: StackState<'config>, P: PrecompileSet> Handler
fn block_base_fee_per_gas(&self) -> U256 {
self.state.block_base_fee_per_gas()
}
fn block_blob_base_fee(&self) -> U256 {
self.state.block_blob_base_fee()
}
fn chain_id(&self) -> U256 {
self.state.chain_id()
}
Expand All @@ -1134,6 +1142,11 @@ impl<'config, 'precompiles, S: StackState<'config>, P: PrecompileSet> Handler
Ok(())
}

fn set_transient_storage(&mut self, index: H256, value: H256) -> Result<(), ExitError> {
self.state.set_transient_storage(index, value);
Ok(())
}

fn log(&mut self, address: H160, topics: Vec<H256>, data: Vec<u8>) -> Result<(), ExitError> {
self.state.log(address, topics, data);
Ok(())
Expand Down
31 changes: 31 additions & 0 deletions src/executor/stack/memory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ pub struct MemoryStackSubstate<'config> {
logs: Vec<Log>,
accounts: BTreeMap<H160, MemoryStackAccount>,
storages: BTreeMap<(H160, H256), H256>,
transient_storages: BTreeMap<H256, H256>,
deletes: BTreeSet<H160>,
}

Expand All @@ -34,6 +35,7 @@ impl<'config> MemoryStackSubstate<'config> {
logs: Vec::new(),
accounts: BTreeMap::new(),
storages: BTreeMap::new(),
transient_storages: BTreeMap::new(),
deletes: BTreeSet::new(),
}
}
Expand Down Expand Up @@ -119,6 +121,7 @@ impl<'config> MemoryStackSubstate<'config> {
logs: Vec::new(),
accounts: BTreeMap::new(),
storages: BTreeMap::new(),
transient_storages: BTreeMap::new(),
deletes: BTreeSet::new(),
};
mem::swap(&mut entering, self);
Expand Down Expand Up @@ -231,6 +234,17 @@ impl<'config> MemoryStackSubstate<'config> {

None
}
pub fn known_transient_storage(&self, key: H256) -> Option<H256> {
if let Some(value) = self.transient_storages.get(&key) {
return Some(*value);
}

if let Some(parent) = self.parent.as_ref() {
return parent.known_transient_storage(key);
}

None
}

pub fn known_original_storage(&self, address: H160) -> Option<H256> {
if let Some(account) = self.accounts.get(&address) {
Expand Down Expand Up @@ -314,6 +328,10 @@ impl<'config> MemoryStackSubstate<'config> {
self.storages.insert((address, key), value);
}

pub fn set_transient_storage(&mut self, key: H256, value: H256) {
self.transient_storages.insert(key, value);
}

pub fn reset_storage<B: Backend>(&mut self, address: H160, backend: &B) {
let mut removing = Vec::new();

Expand Down Expand Up @@ -435,6 +453,9 @@ impl<'backend, 'config, B: Backend> Backend for MemoryStackState<'backend, 'conf
fn block_base_fee_per_gas(&self) -> U256 {
self.backend.block_base_fee_per_gas()
}
fn block_blob_base_fee(&self) -> U256 {
self.backend.block_blob_base_fee()
}

fn chain_id(&self) -> U256 {
self.backend.chain_id()
Expand Down Expand Up @@ -462,6 +483,12 @@ impl<'backend, 'config, B: Backend> Backend for MemoryStackState<'backend, 'conf
.unwrap_or_else(|| self.backend.storage(address, key))
}

fn transient_storage(&self, key: H256) -> H256 {
self.substate
.known_transient_storage(key)
.unwrap_or_else(|| self.backend.transient_storage(key))
}

fn original_storage(&self, address: H160, key: H256) -> Option<H256> {
if let Some(value) = self.substate.known_original_storage(address) {
return Some(value);
Expand Down Expand Up @@ -526,6 +553,10 @@ impl<'backend, 'config, B: Backend> StackState<'config> for MemoryStackState<'ba
self.substate.set_storage(address, key, value)
}

fn set_transient_storage(&mut self, key: H256, value: H256) {
self.substate.set_transient_storage(key, value)
}

fn reset_storage(&mut self, address: H160) {
self.substate.reset_storage(address, self.backend);
}
Expand Down