Skip to content

Commit c1574c3

Browse files
committed
feat: replace DIFFICULTY with PREVRANDAO since merge/EIP-4399
1 parent faeb242 commit c1574c3

File tree

10 files changed

+85
-3
lines changed

10 files changed

+85
-3
lines changed

core/src/error.rs

+4
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,10 @@ pub enum ExitError {
158158
/// Init code exceeds limit (runtime).
159159
#[cfg_attr(feature = "with-codec", codec(index = 7))]
160160
InitCodeLimit,
161+
162+
/// Randomness was not configured for the PREVRANDAO opcode
163+
#[cfg_attr(feature = "with-codec", codec(index = 7))]
164+
MissingRandomness,
161165
}
162166

163167
impl From<ExitError> for ExitReason {

core/src/opcode.rs

+2
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,8 @@ impl Opcode {
217217
pub const NUMBER: Opcode = Opcode(0x43);
218218
/// `DIFFICULTY`
219219
pub const DIFFICULTY: Opcode = Opcode(0x44);
220+
/// `PREVRANDAO` replaces `DIFFICULTY` since the Merge
221+
pub const PREVRANDAO: Opcode = Self::DIFFICULTY;
220222
/// `GASLIMIT`
221223
pub const GASLIMIT: Opcode = Opcode(0x45);
222224
/// `SLOAD`

runtime/src/eval/mod.rs

+7-1
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,13 @@ pub fn eval<H: Handler>(state: &mut Runtime, opcode: Opcode, handler: &mut H) ->
4040
Opcode::COINBASE => system::coinbase(state, handler),
4141
Opcode::TIMESTAMP => system::timestamp(state, handler),
4242
Opcode::NUMBER => system::number(state, handler),
43-
Opcode::DIFFICULTY => system::difficulty(state, handler),
43+
Opcode::DIFFICULTY => {
44+
if state.config().has_prevrandao {
45+
system::prevrandao(state, handler)
46+
} else {
47+
system::difficulty(state, handler)
48+
}
49+
}
4450
Opcode::GASLIMIT => system::gaslimit(state, handler),
4551
Opcode::SLOAD => system::sload(state, handler),
4652
Opcode::SSTORE => system::sstore(state, handler),

runtime/src/eval/system.rs

+16
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,22 @@ pub fn difficulty<H: Handler>(runtime: &mut Runtime, handler: &H) -> Control<H>
185185
Control::Continue
186186
}
187187

188+
pub fn prevrandao<H: Handler>(runtime: &mut Runtime, handler: &H) -> Control<H> {
189+
match handler.block_randomness() {
190+
Some(rand) => {
191+
// TODO: clean this up
192+
// convert between u256 and h256
193+
let mut buf = [0u8; 32];
194+
for (i, word) in rand.0.iter().rev().enumerate() {
195+
buf[i * 8..(i + 1) * 8].copy_from_slice(&word.to_be_bytes());
196+
}
197+
push!(runtime, H256(buf));
198+
Control::Continue
199+
}
200+
None => Control::Exit(ExitError::MissingRandomness.into()),
201+
}
202+
}
203+
188204
pub fn gaslimit<H: Handler>(runtime: &mut Runtime, handler: &H) -> Control<H> {
189205
push_u256!(runtime, handler.block_gas_limit());
190206
Control::Continue

runtime/src/handler.rs

+2
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,8 @@ pub trait Handler {
5454
fn block_timestamp(&self) -> U256;
5555
/// Get environmental block difficulty.
5656
fn block_difficulty(&self) -> U256;
57+
/// Get environmental block randomness.
58+
fn block_randomness(&self) -> Option<U256>;
5759
/// Get environmental gas limit.
5860
fn block_gas_limit(&self) -> U256;
5961
/// Environmental block base fee.

runtime/src/lib.rs

+38-2
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ pub struct Runtime<'config> {
114114
return_data_len: U256,
115115
return_data_offset: U256,
116116
context: Context,
117-
_config: &'config Config,
117+
config: &'config Config,
118118
}
119119

120120
impl<'config> Runtime<'config> {
@@ -132,7 +132,7 @@ impl<'config> Runtime<'config> {
132132
return_data_len: U256::zero(),
133133
return_data_offset: U256::zero(),
134134
context,
135-
_config: config,
135+
config,
136136
}
137137
}
138138

@@ -146,6 +146,11 @@ impl<'config> Runtime<'config> {
146146
&self.context
147147
}
148148

149+
/// Get a reference to the runtime config.
150+
pub fn config(&self) -> &'config Config {
151+
self.config
152+
}
153+
149154
/// Step the runtime.
150155
pub fn step<'a, H: Handler>(
151156
&'a mut self,
@@ -287,6 +292,9 @@ pub struct Config {
287292
pub has_base_fee: bool,
288293
/// Has PUSH0 opcode. See [EIP-3855](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-3855.md)
289294
pub has_push0: bool,
295+
/// Has PREVRANDAO opcode, replacing the DIFFICULTY opcode.
296+
/// See [EIP-4399](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-4399.md)
297+
pub has_prevrandao: bool,
290298
/// Whether the gasometer is running in estimate mode.
291299
pub estimate: bool,
292300
}
@@ -342,6 +350,7 @@ impl Config {
342350
has_ext_code_hash: false,
343351
has_base_fee: false,
344352
has_push0: false,
353+
has_prevrandao: false,
345354
estimate: false,
346355
}
347356
}
@@ -396,6 +405,7 @@ impl Config {
396405
has_ext_code_hash: true,
397406
has_base_fee: false,
398407
has_push0: false,
408+
has_prevrandao: false,
399409
estimate: false,
400410
}
401411
}
@@ -410,6 +420,11 @@ impl Config {
410420
Self::config_with_derived_values(DerivedConfigInputs::london())
411421
}
412422

423+
/// The Merge (Paris) hard fork configuration.
424+
pub const fn merge() -> Config {
425+
Self::config_with_derived_values(DerivedConfigInputs::merge())
426+
}
427+
413428
/// Shanghai hard fork configuration.
414429
pub const fn shanghai() -> Config {
415430
Self::config_with_derived_values(DerivedConfigInputs::shanghai())
@@ -423,6 +438,7 @@ impl Config {
423438
decrease_clears_refund,
424439
has_base_fee,
425440
has_push0,
441+
has_prevrandao,
426442
disallow_executable_format,
427443
warm_coinbase_address,
428444
max_initcode_size,
@@ -488,6 +504,7 @@ impl Config {
488504
has_ext_code_hash: true,
489505
has_base_fee,
490506
has_push0,
507+
has_prevrandao,
491508
estimate: false,
492509
}
493510
}
@@ -502,6 +519,7 @@ struct DerivedConfigInputs {
502519
decrease_clears_refund: bool,
503520
has_base_fee: bool,
504521
has_push0: bool,
522+
has_prevrandao: bool,
505523
disallow_executable_format: bool,
506524
warm_coinbase_address: bool,
507525
max_initcode_size: Option<usize>,
@@ -516,6 +534,7 @@ impl DerivedConfigInputs {
516534
decrease_clears_refund: false,
517535
has_base_fee: false,
518536
has_push0: false,
537+
has_prevrandao: false,
519538
disallow_executable_format: false,
520539
warm_coinbase_address: false,
521540
max_initcode_size: None,
@@ -530,6 +549,22 @@ impl DerivedConfigInputs {
530549
decrease_clears_refund: true,
531550
has_base_fee: true,
532551
has_push0: false,
552+
has_prevrandao: false,
553+
disallow_executable_format: true,
554+
warm_coinbase_address: false,
555+
max_initcode_size: None,
556+
}
557+
}
558+
559+
const fn merge() -> Self {
560+
Self {
561+
gas_storage_read_warm: 100,
562+
gas_sload_cold: 2100,
563+
gas_access_list_storage_key: 1900,
564+
decrease_clears_refund: true,
565+
has_base_fee: true,
566+
has_push0: false,
567+
has_prevrandao: true,
533568
disallow_executable_format: true,
534569
warm_coinbase_address: false,
535570
max_initcode_size: None,
@@ -544,6 +579,7 @@ impl DerivedConfigInputs {
544579
decrease_clears_refund: true,
545580
has_base_fee: true,
546581
has_push0: true,
582+
has_prevrandao: true,
547583
disallow_executable_format: true,
548584
warm_coinbase_address: true,
549585
max_initcode_size: Some(0xC000),

src/backend/memory.rs

+8
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,11 @@ pub struct MemoryVicinity {
3131
pub block_gas_limit: U256,
3232
/// Environmental base fee per gas.
3333
pub block_base_fee_per_gas: U256,
34+
/// Environmental randomness.
35+
///
36+
/// In Ethereum, this is the randomness beacon provided by the beacon
37+
/// chain and is only enabled post Merge.
38+
pub randomness: Option<U256>,
3439
}
3540

3641
/// Account information of a memory backend.
@@ -110,6 +115,9 @@ impl<'vicinity> Backend for MemoryBackend<'vicinity> {
110115
fn block_difficulty(&self) -> U256 {
111116
self.vicinity.block_difficulty
112117
}
118+
fn block_randomness(&self) -> Option<U256> {
119+
self.vicinity.randomness
120+
}
113121
fn block_gas_limit(&self) -> U256 {
114122
self.vicinity.block_gas_limit
115123
}

src/backend/mod.rs

+2
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,8 @@ pub trait Backend {
6666
fn block_timestamp(&self) -> U256;
6767
/// Environmental block difficulty.
6868
fn block_difficulty(&self) -> U256;
69+
/// Get environmental block randomness.
70+
fn block_randomness(&self) -> Option<U256>;
6971
/// Environmental block gas limit.
7072
fn block_gas_limit(&self) -> U256;
7173
/// Environmental block base fee.

src/executor/stack/executor.rs

+3
Original file line numberDiff line numberDiff line change
@@ -1102,6 +1102,9 @@ impl<'config, 'precompiles, S: StackState<'config>, P: PrecompileSet> Handler
11021102
fn block_difficulty(&self) -> U256 {
11031103
self.state.block_difficulty()
11041104
}
1105+
fn block_randomness(&self) -> Option<U256> {
1106+
self.state.block_randomness()
1107+
}
11051108
fn block_gas_limit(&self) -> U256 {
11061109
self.state.block_gas_limit()
11071110
}

src/executor/stack/memory.rs

+3
Original file line numberDiff line numberDiff line change
@@ -421,6 +421,9 @@ impl<'backend, 'config, B: Backend> Backend for MemoryStackState<'backend, 'conf
421421
fn block_difficulty(&self) -> U256 {
422422
self.backend.block_difficulty()
423423
}
424+
fn block_randomness(&self) -> Option<U256> {
425+
self.backend.block_randomness()
426+
}
424427
fn block_gas_limit(&self) -> U256 {
425428
self.backend.block_gas_limit()
426429
}

0 commit comments

Comments
 (0)