Skip to content

Commit eac728f

Browse files
committed
Handler/Opcode: extend interface to introduce transient storage (EIP-1153)
https://eips.ethereum.org/EIPS/eip-1153
1 parent 8eff41c commit eac728f

9 files changed

Lines changed: 93 additions & 1 deletion

File tree

core/src/opcode.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,10 @@ impl Opcode {
227227
pub const SLOAD: Opcode = Opcode(0x54);
228228
/// `SSTORE`
229229
pub const SSTORE: Opcode = Opcode(0x55);
230+
/// `TLOAD`
231+
pub const TLOAD: Opcode = Opcode(0x5c);
232+
/// `TSTORE`
233+
pub const TSTORE: Opcode = Opcode(0x5d);
230234
/// `GAS`
231235
pub const GAS: Opcode = Opcode(0x5a);
232236
/// `LOGn`

runtime/src/eval/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ pub fn eval<H: Handler>(state: &mut Runtime, opcode: Opcode, handler: &mut H) ->
4444
Opcode::GASLIMIT => system::gaslimit(state, handler),
4545
Opcode::SLOAD => system::sload(state, handler),
4646
Opcode::SSTORE => system::sstore(state, handler),
47+
Opcode::TLOAD => system::tload(state, handler),
48+
Opcode::TSTORE => system::tstore(state, handler),
4749
Opcode::GAS => system::gas(state, handler),
4850
Opcode::LOG0 => system::log(state, 0, handler),
4951
Opcode::LOG1 => system::log(state, 1, handler),

runtime/src/eval/system.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,27 @@ pub fn sstore<H: Handler>(runtime: &mut Runtime, handler: &mut H) -> Control<H>
236236
}
237237
}
238238

239+
pub fn tload<H: Handler>(runtime: &mut Runtime, handler: &H) -> Control<H> {
240+
pop!(runtime, index);
241+
let value = handler.transient_storage(index);
242+
push!(runtime, value);
243+
244+
event!(TLoad { index, value });
245+
246+
Control::Continue
247+
}
248+
249+
pub fn tstore<H: Handler>(runtime: &mut Runtime, handler: &mut H) -> Control<H> {
250+
pop!(runtime, index, value);
251+
252+
event!(TStore { index, value });
253+
254+
match handler.set_transient_storage(index, value) {
255+
Ok(()) => Control::Continue,
256+
Err(e) => Control::Exit(e.into()),
257+
}
258+
}
259+
239260
pub fn gas<H: Handler>(runtime: &mut Runtime, handler: &H) -> Control<H> {
240261
push_u256!(runtime, handler.gas_left());
241262

runtime/src/handler.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ pub trait Handler {
3535
fn code(&self, address: H160) -> Vec<u8>;
3636
/// Get storage value of address at index.
3737
fn storage(&self, address: H160, index: H256) -> H256;
38+
/// Get transient storage value at index.
39+
fn transient_storage(&self, index: H256) -> H256;
3840
/// Get original storage value of address at index.
3941
fn original_storage(&self, address: H160, index: H256) -> H256;
4042

@@ -79,6 +81,8 @@ pub trait Handler {
7981

8082
/// Set storage value of address at index.
8183
fn set_storage(&mut self, address: H160, index: H256, value: H256) -> Result<(), ExitError>;
84+
/// Set transient storage value at index.
85+
fn set_transient_storage(&mut self, index: H256, value: H256) -> Result<(), ExitError>;
8286
/// Create a log owned by address with given topics and data.
8387
fn log(&mut self, address: H160, topics: Vec<H256>, data: Vec<u8>) -> Result<(), ExitError>;
8488
/// Mark an address to be deleted, with funds transferred to target.

runtime/src/tracing.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,14 @@ pub enum Event<'a> {
3232
index: H256,
3333
value: H256,
3434
},
35+
TLoad {
36+
index: H256,
37+
value: H256,
38+
},
39+
TStore {
40+
index: H256,
41+
value: H256,
42+
},
3543
}
3644

3745
// Expose `listener::with` to the crate only.

src/backend/memory.rs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,15 +63,21 @@ pub struct MemoryAccount {
6363
pub struct MemoryBackend<'vicinity> {
6464
vicinity: &'vicinity MemoryVicinity,
6565
state: BTreeMap<H160, MemoryAccount>,
66+
transient_state: BTreeMap<H256, H256>,
6667
logs: Vec<Log>,
6768
}
6869

6970
impl<'vicinity> MemoryBackend<'vicinity> {
7071
/// Create a new memory backend.
71-
pub fn new(vicinity: &'vicinity MemoryVicinity, state: BTreeMap<H160, MemoryAccount>) -> Self {
72+
pub fn new(
73+
vicinity: &'vicinity MemoryVicinity,
74+
state: BTreeMap<H160, MemoryAccount>,
75+
transient_state: BTreeMap<H256, H256>,
76+
) -> Self {
7277
Self {
7378
vicinity,
7479
state,
80+
transient_state,
7581
logs: Vec::new(),
7682
}
7783
}
@@ -163,6 +169,13 @@ impl<'vicinity> Backend for MemoryBackend<'vicinity> {
163169
.unwrap_or_default()
164170
}
165171

172+
fn transient_storage(&self, index: H256) -> H256 {
173+
self.transient_state
174+
.get(&index)
175+
.cloned()
176+
.unwrap_or_default()
177+
}
178+
166179
fn original_storage(&self, address: H160, index: H256) -> Option<H256> {
167180
Some(self.storage(address, index))
168181
}

src/backend/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,8 @@ pub trait Backend {
8585
fn code(&self, address: H160) -> Vec<u8>;
8686
/// Get storage value of address at index.
8787
fn storage(&self, address: H160, index: H256) -> H256;
88+
/// Get storage value at index.
89+
fn transient_storage(&self, index: H256) -> H256;
8890
/// Get original storage value of address at index, if available.
8991
fn original_storage(&self, address: H160, index: H256) -> Option<H256>;
9092
}

src/executor/stack/executor.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,7 @@ pub trait StackState<'config>: Backend {
206206

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

1051+
fn transient_storage(&self, index: H256) -> H256 {
1052+
self.state.transient_storage(index)
1053+
}
1054+
10501055
fn original_storage(&self, address: H160, index: H256) -> H256 {
10511056
self.state
10521057
.original_storage(address, index)
@@ -1137,6 +1142,11 @@ impl<'config, 'precompiles, S: StackState<'config>, P: PrecompileSet> Handler
11371142
Ok(())
11381143
}
11391144

1145+
fn set_transient_storage(&mut self, index: H256, value: H256) -> Result<(), ExitError> {
1146+
self.state.set_transient_storage(index, value);
1147+
Ok(())
1148+
}
1149+
11401150
fn log(&mut self, address: H160, topics: Vec<H256>, data: Vec<u8>) -> Result<(), ExitError> {
11411151
self.state.log(address, topics, data);
11421152
Ok(())

src/executor/stack/memory.rs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ pub struct MemoryStackSubstate<'config> {
2323
logs: Vec<Log>,
2424
accounts: BTreeMap<H160, MemoryStackAccount>,
2525
storages: BTreeMap<(H160, H256), H256>,
26+
transient_storages: BTreeMap<H256, H256>,
2627
deletes: BTreeSet<H160>,
2728
}
2829

@@ -34,6 +35,7 @@ impl<'config> MemoryStackSubstate<'config> {
3435
logs: Vec::new(),
3536
accounts: BTreeMap::new(),
3637
storages: BTreeMap::new(),
38+
transient_storages: BTreeMap::new(),
3739
deletes: BTreeSet::new(),
3840
}
3941
}
@@ -119,6 +121,7 @@ impl<'config> MemoryStackSubstate<'config> {
119121
logs: Vec::new(),
120122
accounts: BTreeMap::new(),
121123
storages: BTreeMap::new(),
124+
transient_storages: BTreeMap::new(),
122125
deletes: BTreeSet::new(),
123126
};
124127
mem::swap(&mut entering, self);
@@ -231,6 +234,17 @@ impl<'config> MemoryStackSubstate<'config> {
231234

232235
None
233236
}
237+
pub fn known_transient_storage(&self, key: H256) -> Option<H256> {
238+
if let Some(value) = self.transient_storages.get(&key) {
239+
return Some(*value);
240+
}
241+
242+
if let Some(parent) = self.parent.as_ref() {
243+
return parent.known_transient_storage(key);
244+
}
245+
246+
None
247+
}
234248

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

331+
pub fn set_transient_storage(&mut self, key: H256, value: H256) {
332+
self.transient_storages.insert(key, value);
333+
}
334+
317335
pub fn reset_storage<B: Backend>(&mut self, address: H160, backend: &B) {
318336
let mut removing = Vec::new();
319337

@@ -465,6 +483,12 @@ impl<'backend, 'config, B: Backend> Backend for MemoryStackState<'backend, 'conf
465483
.unwrap_or_else(|| self.backend.storage(address, key))
466484
}
467485

486+
fn transient_storage(&self, key: H256) -> H256 {
487+
self.substate
488+
.known_transient_storage(key)
489+
.unwrap_or_else(|| self.backend.transient_storage(key))
490+
}
491+
468492
fn original_storage(&self, address: H160, key: H256) -> Option<H256> {
469493
if let Some(value) = self.substate.known_original_storage(address) {
470494
return Some(value);
@@ -529,6 +553,10 @@ impl<'backend, 'config, B: Backend> StackState<'config> for MemoryStackState<'ba
529553
self.substate.set_storage(address, key, value)
530554
}
531555

556+
fn set_transient_storage(&mut self, key: H256, value: H256) {
557+
self.substate.set_transient_storage(key, value)
558+
}
559+
532560
fn reset_storage(&mut self, address: H160) {
533561
self.substate.reset_storage(address, self.backend);
534562
}

0 commit comments

Comments
 (0)