Skip to content

Commit

Permalink
Handler/Opcode: extend interface to introduce transient storage (EIP-…
Browse files Browse the repository at this point in the history
  • Loading branch information
rodibozman committed Mar 1, 2024
1 parent 8eff41c commit eac728f
Show file tree
Hide file tree
Showing 9 changed files with 93 additions and 1 deletion.
4 changes: 4 additions & 0 deletions core/src/opcode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -227,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
2 changes: 2 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 Down
21 changes: 21 additions & 0 deletions runtime/src/eval/system.rs
Original file line number Diff line number Diff line change
Expand Up @@ -236,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
4 changes: 4 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 Down Expand Up @@ -79,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
15 changes: 14 additions & 1 deletion src/backend/memory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,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 @@ -163,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
2 changes: 2 additions & 0 deletions src/backend/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,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
10 changes: 10 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 @@ -1137,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
28 changes: 28 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 @@ -465,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 @@ -529,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

0 comments on commit eac728f

Please sign in to comment.