From 144b2293a2b166899ace077a41450b0e96c9b345 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jochen=20M=C3=BCller?= Date: Mon, 31 May 2021 14:37:23 +0200 Subject: [PATCH] EIP 3541 (#422) * Add EIP-3541 transition block parameter * Implement EIP-3541 * Add a unit test for EIP-3541 * Add error type for attempt to deploy invalid code * fmt --- crates/ethcore/src/executive.rs | 1 + crates/ethcore/src/externalities.rs | 48 +++++++++++++++++++++++++ crates/ethcore/src/spec/spec.rs | 7 ++++ crates/ethcore/src/trace/types/error.rs | 6 ++++ crates/ethjson/src/spec/params.rs | 2 ++ crates/vm/vm/src/error.rs | 3 ++ crates/vm/vm/src/schedule.rs | 6 ++++ 7 files changed, 73 insertions(+) diff --git a/crates/ethcore/src/executive.rs b/crates/ethcore/src/executive.rs index f0df8c289..76306b5a7 100644 --- a/crates/ethcore/src/executive.rs +++ b/crates/ethcore/src/executive.rs @@ -444,6 +444,7 @@ impl<'a> CallCreateExecutive<'a> { | Err(vm::Error::SubStackUnderflow { .. }) | Err(vm::Error::OutOfSubStack { .. }) | Err(vm::Error::InvalidSubEntry) + | Err(vm::Error::InvalidCode) | Ok(FinalizationResult { apply_state: false, .. }) => { diff --git a/crates/ethcore/src/externalities.rs b/crates/ethcore/src/externalities.rs index 41c722e8f..b13bbf109 100644 --- a/crates/ethcore/src/externalities.rs +++ b/crates/ethcore/src/externalities.rs @@ -431,6 +431,12 @@ where false => Ok(*gas), }; } + if self.schedule.eip3541 && data.get(0) == Some(&0xefu8) { + return match self.schedule.exceptional_failed_code_deposit { + true => Err(vm::Error::InvalidCode), + false => Ok(*gas), + }; + } self.state .init_code(&self.origin_info.address, data.to_vec())?; Ok(*gas - return_cost) @@ -913,4 +919,46 @@ mod tests { Address::from_str("e33c0c7f7df4809055c3eba6c09cfe4baf1bd9e0").unwrap() ); } + + #[test] + fn eip_3541() { + let call_ret = |schedule: Schedule, data: &ReturnData| { + let mut setup = TestSetup::default(); + setup.schedule = schedule; + let mut tracer = NoopTracer; + let mut vm_tracer = NoopVMTracer; + let origin = get_test_origin(); + let ext = Externalities::new( + &mut setup.state, + &setup.env_info, + &setup.machine, + &setup.schedule, + 0, + 0, + &origin, + &mut setup.sub_state, + OutputPolicy::InitContract, + &mut tracer, + &mut vm_tracer, + false, + ); + ext.ret(&U256::from(10000), &data, true) + }; + + let data = ReturnData::new(vec![0xefu8], 0, 1); + + let result = call_ret(Schedule::new_berlin(), &data); + assert!(result.is_ok()); + + let result = call_ret(Schedule::new_london(), &data); + assert!(result.is_err()); + + let data = ReturnData::new(vec![0xefu8, 0x00u8, 0x00u8], 0, 3); + let result = call_ret(Schedule::new_london(), &data); + assert!(result.is_err()); + + let data = ReturnData::new(vec![0xee], 0, 1); + let result = call_ret(Schedule::new_london(), &data); + assert!(result.is_ok()); + } } diff --git a/crates/ethcore/src/spec/spec.rs b/crates/ethcore/src/spec/spec.rs index 12a9dbbe3..3bdfe291b 100644 --- a/crates/ethcore/src/spec/spec.rs +++ b/crates/ethcore/src/spec/spec.rs @@ -141,6 +141,8 @@ pub struct CommonParams { pub eip2930_transition: BlockNumber, /// Number of first block where EIP-3529 rules begin. pub eip3529_transition: BlockNumber, + /// Number of first block where EIP-3541 rule begins. + pub eip3541_transition: BlockNumber, /// Number of first block where dust cleanup rules (EIP-168 and EIP169) begin. pub dust_protection_transition: BlockNumber, /// Nonce cap increase per block. Nonce cap is only checked if dust protection is enabled. @@ -217,6 +219,7 @@ impl CommonParams { schedule.have_subs = block_number >= self.eip2315_transition; schedule.eip2929 = block_number >= self.eip2929_transition; schedule.eip2930 = block_number >= self.eip2930_transition; + schedule.eip3541 = block_number >= self.eip3541_transition; if block_number >= self.eip1884_transition { schedule.have_selfbalance = true; @@ -388,6 +391,9 @@ impl From for CommonParams { eip3529_transition: p .eip3529_transition .map_or_else(BlockNumber::max_value, Into::into), + eip3541_transition: p + .eip3541_transition + .map_or_else(BlockNumber::max_value, Into::into), dust_protection_transition: p .dust_protection_transition .map_or_else(BlockNumber::max_value, Into::into), @@ -678,6 +684,7 @@ impl Spec { params.eip2929_transition, params.eip2930_transition, params.eip3529_transition, + params.eip3541_transition, params.dust_protection_transition, params.wasm_activation_transition, params.wasm_disable_transition, diff --git a/crates/ethcore/src/trace/types/error.rs b/crates/ethcore/src/trace/types/error.rs index 01e636510..508f02249 100644 --- a/crates/ethcore/src/trace/types/error.rs +++ b/crates/ethcore/src/trace/types/error.rs @@ -48,6 +48,8 @@ pub enum Error { Internal, /// When execution tries to modify the state in static context MutableCallInStaticContext, + /// When invalid code was attempted to deploy + InvalidCode, /// Wasm error Wasm, /// Contract tried to access past the return data buffer. @@ -68,6 +70,7 @@ impl<'a> From<&'a VmError> for Error { VmError::OutOfSubStack { .. } => Error::OutOfSubStack, VmError::InvalidSubEntry { .. } => Error::InvalidSubEntry, VmError::BuiltIn { .. } => Error::BuiltIn, + VmError::InvalidCode => Error::InvalidCode, VmError::Wasm { .. } => Error::Wasm, VmError::Internal(_) => Error::Internal, VmError::MutableCallInStaticContext => Error::MutableCallInStaticContext, @@ -96,6 +99,7 @@ impl fmt::Display for Error { OutOfSubStack => "Subroutine stack overflow", BuiltIn => "Built-in failed", InvalidSubEntry => "Invalid subroutine entry", + InvalidCode => "Invalid code", Wasm => "Wasm runtime error", Internal => "Internal error", MutableCallInStaticContext => "Mutable Call In Static Context", @@ -124,6 +128,7 @@ impl Encodable for Error { SubStackUnderflow => 11, OutOfSubStack => 12, InvalidSubEntry => 13, + InvalidCode => 14, }; s.append_internal(&value); @@ -149,6 +154,7 @@ impl Decodable for Error { 11 => Ok(SubStackUnderflow), 12 => Ok(OutOfSubStack), 13 => Ok(InvalidSubEntry), + 14 => Ok(InvalidCode), _ => Err(DecoderError::Custom("Invalid error type")), } } diff --git a/crates/ethjson/src/spec/params.rs b/crates/ethjson/src/spec/params.rs index 6fb26241c..54407ae6a 100644 --- a/crates/ethjson/src/spec/params.rs +++ b/crates/ethjson/src/spec/params.rs @@ -114,6 +114,8 @@ pub struct Params { /// See `CommonParams` docs. pub eip3529_transition: Option, /// See `CommonParams` docs. + pub eip3541_transition: Option, + /// See `CommonParams` docs. pub dust_protection_transition: Option, /// See `CommonParams` docs. pub nonce_cap_increment: Option, diff --git a/crates/vm/vm/src/error.rs b/crates/vm/vm/src/error.rs index 627b73cfe..bb1b8355f 100644 --- a/crates/vm/vm/src/error.rs +++ b/crates/vm/vm/src/error.rs @@ -92,6 +92,8 @@ pub enum Error { BuiltIn(&'static str), /// When execution tries to modify the state in static context MutableCallInStaticContext, + /// Invalid code to deploy as a contract + InvalidCode, /// Likely to cause consensus issues. Internal(String), /// Wasm runtime error @@ -145,6 +147,7 @@ impl fmt::Display for Error { BuiltIn(name) => write!(f, "Built-in failed: {}", name), Internal(ref msg) => write!(f, "Internal error: {}", msg), MutableCallInStaticContext => write!(f, "Mutable call in static context"), + InvalidCode => write!(f, "Invalid code to deploy as a contract"), Wasm(ref msg) => write!(f, "Internal error: {}", msg), OutOfBounds => write!(f, "Out of bounds"), Reverted => write!(f, "Reverted"), diff --git a/crates/vm/vm/src/schedule.rs b/crates/vm/vm/src/schedule.rs index c6ba27e7d..1273e5854 100644 --- a/crates/vm/vm/src/schedule.rs +++ b/crates/vm/vm/src/schedule.rs @@ -163,6 +163,8 @@ pub struct Schedule { pub eip2930: bool, /// Gas used in transaction divided by this number is the maximum refundable amount. pub max_refund_quotient: usize, + // Enable EIP-3541 rule + pub eip3541: bool, } /// Wasm cost table @@ -311,6 +313,7 @@ impl Schedule { eip2929: false, eip2930: false, max_refund_quotient: MAX_REFUND_QUOTIENT, + eip3541: false, } } @@ -376,6 +379,8 @@ impl Schedule { schedule.sstore_refund_gas = EIP3529_SSTORE_CLEARS_SCHEDULE; schedule.max_refund_quotient = EIP3529_MAX_REFUND_QUOTIENT; + schedule.eip3541 = true; + schedule } @@ -443,6 +448,7 @@ impl Schedule { eip2929: false, eip2930: false, max_refund_quotient: MAX_REFUND_QUOTIENT, + eip3541: false, } }