Skip to content

Commit

Permalink
feat: replace DIFFICULTY with PREVRANDAO since merge (EIP-4399)
Browse files Browse the repository at this point in the history
  • Loading branch information
vimpunk committed May 3, 2023
1 parent e7138f7 commit d19423b
Show file tree
Hide file tree
Showing 10 changed files with 63 additions and 5 deletions.
1 change: 1 addition & 0 deletions benches/loop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ fn run_loop_contract() {
block_gas_limit: Default::default(),
chain_id: U256::one(),
block_base_fee_per_gas: U256::zero(),
block_randomness: None,
};

let mut state = BTreeMap::new();
Expand Down
7 changes: 4 additions & 3 deletions core/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -127,9 +127,6 @@ pub enum ExitError {
/// Create init code exceeds limit (runtime).
#[cfg_attr(feature = "with-codec", codec(index = 7))]
CreateContractLimit,
/// Invalid opcode during execution or starting byte is 0xef. See [EIP-3541](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-3541.md).
#[cfg_attr(feature = "with-codec", codec(index = 15))]
InvalidCode(Opcode),

/// An opcode accesses external information, but the request is off offset
/// limit (runtime).
Expand All @@ -154,6 +151,10 @@ pub enum ExitError {
/// Other normal errors.
#[cfg_attr(feature = "with-codec", codec(index = 13))]
Other(Cow<'static, str>),

/// Invalid opcode during execution or starting byte is 0xef. See [EIP-3541](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-3541.md).
#[cfg_attr(feature = "with-codec", codec(index = 15))]
InvalidCode(Opcode),
}

impl From<ExitError> for ExitReason {
Expand Down
2 changes: 1 addition & 1 deletion runtime/src/eval/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ pub fn eval<H: Handler>(state: &mut Runtime, opcode: Opcode, handler: &mut H) ->
Opcode::COINBASE => system::coinbase(state, handler),
Opcode::TIMESTAMP => system::timestamp(state, handler),
Opcode::NUMBER => system::number(state, handler),
Opcode::DIFFICULTY => system::difficulty(state, handler),
Opcode::DIFFICULTY => system::prevrandao_or_difficulty(state, handler),
Opcode::GASLIMIT => system::gaslimit(state, handler),
Opcode::SLOAD => system::sload(state, handler),
Opcode::SSTORE => system::sstore(state, handler),
Expand Down
19 changes: 19 additions & 0 deletions runtime/src/eval/system.rs
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,25 @@ pub fn difficulty<H: Handler>(runtime: &mut Runtime, handler: &H) -> Control<H>
Control::Continue
}

pub fn prevrandao_or_difficulty<H: Handler>(runtime: &mut Runtime, handler: &H) -> Control<H> {
match handler.block_randomness() {
Some(rand) => {
// Convert between U256 and H256. U256 is in little-endian but since H256 is just
// a string-like byte array, it's big endian (MSB is the first element of the array).
//
// Byte order here is important because this opcode has the same value as DIFFICULTY
// (0x44), and so for older forks of Ethereum, the threshold value of 2^64 is used to
// distinguish between the two: if it's below, the value corresponds to the DIFFICULTY
// opcode, otherwise to the PREVRANDAO opcode.
let mut buf = [0u8; 32];
rand.to_big_endian(&mut buf);
push!(runtime, H256(buf));
Control::Continue
}
None => difficulty(runtime, handler),
}
}

pub fn gaslimit<H: Handler>(runtime: &mut Runtime, handler: &H) -> Control<H> {
push_u256!(runtime, handler.block_gas_limit());
Control::Continue
Expand Down
2 changes: 2 additions & 0 deletions runtime/src/handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ pub trait Handler {
fn block_timestamp(&self) -> U256;
/// Get environmental block difficulty.
fn block_difficulty(&self) -> U256;
/// Get environmental block randomness.
fn block_randomness(&self) -> Option<U256>;
/// Get environmental gas limit.
fn block_gas_limit(&self) -> U256;
/// Environmental block base fee.
Expand Down
19 changes: 19 additions & 0 deletions runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -409,6 +409,11 @@ impl Config {
Self::config_with_derived_values(DerivedConfigInputs::london())
}

/// The Merge (Paris) hard fork configuration.
pub const fn merge() -> Config {
Self::config_with_derived_values(DerivedConfigInputs::merge())
}

/// Shanghai hard fork configuration.
pub const fn shanghai() -> Config {
Self::config_with_derived_values(DerivedConfigInputs::shanghai())
Expand Down Expand Up @@ -535,6 +540,20 @@ impl DerivedConfigInputs {
}
}

const fn merge() -> Self {
Self {
gas_storage_read_warm: 100,
gas_sload_cold: 2100,
gas_access_list_storage_key: 1900,
decrease_clears_refund: true,
has_base_fee: true,
has_push0: false,
disallow_executable_format: true,
warm_coinbase_address: false,
max_initcode_size: None,
}
}

const fn shanghai() -> Self {
Self {
gas_storage_read_warm: 100,
Expand Down
8 changes: 8 additions & 0 deletions src/backend/memory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,11 @@ pub struct MemoryVicinity {
pub block_gas_limit: U256,
/// Environmental base fee per gas.
pub block_base_fee_per_gas: U256,
/// Environmental randomness.
///
/// In Ethereum, this is the randomness beacon provided by the beacon
/// chain and is only enabled post Merge.
pub block_randomness: Option<U256>,
}

/// Account information of a memory backend.
Expand Down Expand Up @@ -110,6 +115,9 @@ impl<'vicinity> Backend for MemoryBackend<'vicinity> {
fn block_difficulty(&self) -> U256 {
self.vicinity.block_difficulty
}
fn block_randomness(&self) -> Option<U256> {
self.vicinity.block_randomness
}
fn block_gas_limit(&self) -> U256 {
self.vicinity.block_gas_limit
}
Expand Down
2 changes: 2 additions & 0 deletions src/backend/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@ pub trait Backend {
fn block_timestamp(&self) -> U256;
/// Environmental block difficulty.
fn block_difficulty(&self) -> U256;
/// Get environmental block randomness.
fn block_randomness(&self) -> Option<U256>;
/// Environmental block gas limit.
fn block_gas_limit(&self) -> U256;
/// Environmental block base fee.
Expand Down
5 changes: 4 additions & 1 deletion src/executor/stack/executor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -304,7 +304,7 @@ impl<'config, 'precompiles, S: StackState<'config>, P: PrecompileSet>
/// Execute using Runtimes on the call_stack until it returns.
fn execute_with_call_stack(
&mut self,
call_stack: &mut Vec<TaggedRuntime>,
call_stack: &mut Vec<TaggedRuntime<'_>>,
) -> (ExitReason, Option<H160>, Vec<u8>) {
// This `interrupt_runtime` is used to pass the runtime obtained from the
// `Capture::Trap` branch in the match below back to the top of the call stack.
Expand Down Expand Up @@ -1108,6 +1108,9 @@ impl<'config, 'precompiles, S: StackState<'config>, P: PrecompileSet> Handler
fn block_difficulty(&self) -> U256 {
self.state.block_difficulty()
}
fn block_randomness(&self) -> Option<U256> {
self.state.block_randomness()
}
fn block_gas_limit(&self) -> U256 {
self.state.block_gas_limit()
}
Expand Down
3 changes: 3 additions & 0 deletions src/executor/stack/memory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -421,6 +421,9 @@ impl<'backend, 'config, B: Backend> Backend for MemoryStackState<'backend, 'conf
fn block_difficulty(&self) -> U256 {
self.backend.block_difficulty()
}
fn block_randomness(&self) -> Option<U256> {
self.backend.block_randomness()
}
fn block_gas_limit(&self) -> U256 {
self.backend.block_gas_limit()
}
Expand Down

0 comments on commit d19423b

Please sign in to comment.