-
Notifications
You must be signed in to change notification settings - Fork 1.2k
pallet_revive: Fix EVM tests to pass data as part of code
#10214
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 3 commits
4a4a56e
c4656a9
e0d2cd5
e4caeb3
5f80b81
80724d9
334208f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -84,28 +84,16 @@ pub fn caller<E: Ext>(interpreter: &mut Interpreter<E>) -> ControlFlow<Halt> { | |
| /// Pushes the size of running contract's bytecode onto the stack. | ||
| pub fn codesize<E: Ext>(interpreter: &mut Interpreter<E>) -> ControlFlow<Halt> { | ||
| interpreter.ext.charge_or_halt(EVMGas(BASE))?; | ||
| interpreter.stack.push(U256::from(interpreter.bytecode.len())) | ||
| let len = in_data_size(interpreter, true); | ||
| interpreter.stack.push(len) | ||
| } | ||
|
|
||
| /// Implements the CODECOPY instruction. | ||
| /// | ||
| /// Copies running contract's bytecode to memory. | ||
| pub fn codecopy<E: Ext>(interpreter: &mut Interpreter<E>) -> ControlFlow<Halt> { | ||
| let [memory_offset, code_offset, len] = interpreter.stack.popn()?; | ||
| let len = as_usize_or_halt::<E::T>(len)?; | ||
| let Some(memory_offset) = memory_resize(interpreter, memory_offset, len)? else { | ||
| return ControlFlow::Continue(()) | ||
| }; | ||
| let code_offset = as_usize_saturated(code_offset); | ||
|
|
||
| // Note: This can't panic because we resized memory. | ||
| interpreter.memory.set_data( | ||
| memory_offset, | ||
| code_offset, | ||
| len, | ||
| interpreter.bytecode.bytecode_slice(), | ||
| ); | ||
| ControlFlow::Continue(()) | ||
| in_data_copy(interpreter, memory_offset, code_offset, len, true) | ||
| } | ||
|
|
||
| /// Implements the CALLDATALOAD instruction. | ||
|
|
@@ -116,7 +104,11 @@ pub fn calldataload<E: Ext>(interpreter: &mut Interpreter<E>) -> ControlFlow<Hal | |
| let ([], offset_ptr) = interpreter.stack.popn_top()?; | ||
| let mut word = [0u8; 32]; | ||
| let offset = as_usize_saturated(*offset_ptr); | ||
| let input = &interpreter.input; | ||
| let is_constructor = interpreter.ext.entry_point().is_evm_constructor(); | ||
| let input = interpreter.input.as_slice(); | ||
|
|
||
| let input = if is_constructor { &[] } else { input }; | ||
|
|
||
| let input_len = input.len(); | ||
| if offset < input_len { | ||
| let count = 32.min(input_len - offset); | ||
|
|
@@ -131,7 +123,8 @@ pub fn calldataload<E: Ext>(interpreter: &mut Interpreter<E>) -> ControlFlow<Hal | |
| /// Pushes the size of input data onto the stack. | ||
| pub fn calldatasize<E: Ext>(interpreter: &mut Interpreter<E>) -> ControlFlow<Halt> { | ||
| interpreter.ext.charge_or_halt(EVMGas(BASE))?; | ||
| interpreter.stack.push(U256::from(interpreter.input.len())) | ||
| let len = in_data_size(interpreter, false); | ||
| interpreter.stack.push(len) | ||
| } | ||
|
|
||
| /// Implements the CALLVALUE instruction. | ||
|
|
@@ -148,17 +141,7 @@ pub fn callvalue<E: Ext>(interpreter: &mut Interpreter<E>) -> ControlFlow<Halt> | |
| /// Copies input data to memory. | ||
| pub fn calldatacopy<E: Ext>(interpreter: &mut Interpreter<E>) -> ControlFlow<Halt> { | ||
| let [memory_offset, data_offset, len] = interpreter.stack.popn()?; | ||
| let len = as_usize_or_halt::<E::T>(len)?; | ||
|
|
||
| let Some(memory_offset) = memory_resize(interpreter, memory_offset, len)? else { | ||
| return ControlFlow::Continue(()); | ||
| }; | ||
|
|
||
| let data_offset = as_usize_saturated(data_offset); | ||
|
|
||
| // Note: This can't panic because we resized memory. | ||
| interpreter.memory.set_data(memory_offset, data_offset, len, &interpreter.input); | ||
| ControlFlow::Continue(()) | ||
| in_data_copy(interpreter, memory_offset, data_offset, len, false) | ||
| } | ||
|
|
||
| /// EIP-211: New opcodes: RETURNDATASIZE and RETURNDATACOPY | ||
|
|
@@ -207,7 +190,7 @@ pub fn gas<E: Ext>(interpreter: &mut Interpreter<E>) -> ControlFlow<Halt> { | |
| /// Common logic for copying data from a source buffer to the EVM's memory. | ||
| /// | ||
| /// Handles memory expansion and gas calculation for data copy operations. | ||
| pub fn memory_resize<'a, E: Ext>( | ||
| fn memory_resize<'a, E: Ext>( | ||
| interpreter: &mut Interpreter<'a, E>, | ||
| memory_offset: U256, | ||
| len: usize, | ||
|
|
@@ -221,3 +204,70 @@ pub fn memory_resize<'a, E: Ext>( | |
| interpreter.memory.resize(memory_offset, len)?; | ||
| ControlFlow::Continue(Some(memory_offset)) | ||
| } | ||
|
|
||
| /// The shared logic for CODECOPY and CALLDATACOPY. | ||
| fn in_data_copy<E: Ext>( | ||
| interpreter: &mut Interpreter<E>, | ||
| memory_offset: U256, | ||
| data_offset: U256, | ||
| len: U256, | ||
| is_codecopy: bool, | ||
| ) -> ControlFlow<Halt> { | ||
| let len = as_usize_or_halt::<E::T>(len)?; | ||
| let Some(memory_offset) = memory_resize(interpreter, memory_offset, len)? else { | ||
| return ControlFlow::Continue(()) | ||
| }; | ||
| let data_offset = as_usize_saturated(data_offset); | ||
| let is_constructor = interpreter.ext.entry_point().is_evm_constructor(); | ||
|
||
| let bytecode = interpreter.bytecode.bytecode_slice(); | ||
| let input = interpreter.input.as_slice(); | ||
|
|
||
| struct Write<'a> { | ||
| memory_offset: usize, | ||
| data_offset: usize, | ||
| len: usize, | ||
| slice: &'a [u8], | ||
| } | ||
|
|
||
| let writes = match (is_constructor, is_codecopy) { | ||
| (true, true) => { | ||
| let bytes_written = bytecode.len().saturating_sub(data_offset).min(len); | ||
| &[ | ||
| Write { memory_offset, data_offset, len: bytes_written, slice: bytecode }, | ||
| Write { | ||
| memory_offset: memory_offset.saturating_add(bytes_written), | ||
| data_offset: data_offset.saturating_sub(bytecode.len()), | ||
| len: len.saturating_sub(bytes_written), | ||
| slice: input, | ||
| }, | ||
| ][..] | ||
| }, | ||
| (true, false) => &[Write { memory_offset, data_offset, len, slice: &[] }], | ||
| (false, true) => &[Write { memory_offset, data_offset, len, slice: bytecode }], | ||
| (false, false) => &[Write { memory_offset, data_offset, len, slice: input }], | ||
| }; | ||
|
|
||
| for write in writes.into_iter().filter(|w| w.len != 0) { | ||
| // Note: This can't panic because we resized memory. | ||
| interpreter | ||
| .memory | ||
| .set_data(write.memory_offset, write.data_offset, write.len, write.slice); | ||
| } | ||
|
|
||
| ControlFlow::Continue(()) | ||
| } | ||
|
|
||
| /// The shared logic for CODESIZE and CALLDATASIZE | ||
| fn in_data_size<E: Ext>(interpreter: &mut Interpreter<E>, is_codecopy: bool) -> U256 { | ||
| let bytecode_len = interpreter.bytecode.len(); | ||
| let input_len = interpreter.input.len(); | ||
| let is_constructor = interpreter.ext.entry_point().is_evm_constructor(); | ||
|
|
||
| match (is_constructor, is_codecopy) { | ||
| (true, true) => bytecode_len.saturating_add(input_len), | ||
| (true, false) => 0, | ||
| (false, true) => bytecode_len, | ||
| (false, false) => input_len, | ||
| } | ||
| .into() | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.