-
Notifications
You must be signed in to change notification settings - Fork 631
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
feat(cancun): EIP-5656: MCOPY - Memory copying instruction #528
Conversation
InstructionResult::InvalidOperandOOG | ||
); | ||
let (data_end, overflow) = dest.overflowing_add(len); | ||
if overflow || data_end > interpreter.return_data_buffer.len() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
wait silly question but isn't mcopy just copying data from memory to memory and not from return data buffer.
You should have memory_resize
somewhere here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah this is correct.
interpreter.instruction_result = InstructionResult::OutOfOffset; | ||
return; | ||
} | ||
interpreter.memory.set_data(src, dest, len, &interpreter.contract.input); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And here we are coping the contract.input
that is different from the thing we check above
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep this is right, i read the memory from slice to pass the right data here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
left few comments
Awesome thanks for the comments. Will work some more on this today |
InstructionResult::InvalidOperandOOG | ||
); | ||
// Read data with length len from src | ||
let data = interpreter.memory.clone(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cloning memory is a no go, it is expensive.
You could probably add copy
function to memory that would done copying. Just figure out how to do in in place with vec
dest, | ||
InstructionResult::InvalidOperandOOG | ||
); | ||
memory_resize!(interpreter, dest, len); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would assume that both dest and src can increment memory. So you need to find what is bigger and increment memory by a bigger value
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I made a function to check and handle this memory_copy_resize
that was inspired by the geth pr's implementation in the memory_table.go
/// Copies memory inplace to a returns a [u8] | ||
#[inline(always)] | ||
pub fn copy(&self, offset: usize, size: usize) -> [u8; 32] { | ||
let mut copy = [0u8; 32]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks like copy_word
because copy
is only 32
, it should be size
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
addressed this with returning a vec of bytes and then passing as a slice to the data
So the thing i want to try and fix now is that the |
In the geth implementation they validate the stack length in the interpreter here Where as we are doing it in the |
interpreter.memory.set_data(src, dest, len, data); | ||
} | ||
|
||
pub fn memory_copy_resize(interpreter: &mut Interpreter, _host: &mut dyn Host) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is faulty, and you already have dest,src, len
in fn mcopy
so this fn is not needed. What is needed is to memory_resize
|
||
let src = as_usize_or_fail!(interpreter, src, InstructionResult::InvalidOperandOOG); | ||
// Read data with length len from src | ||
let binding = interpreter.memory.copy_to_vec(src, len); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is not optimal to create temporary vec. There is a memory operation from C
that does copying of overlapping data so I assume there is something similar in rust. Make memory.copy
that does internal copying of data.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I found and used copy_within
https://doc.rust-lang.org/std/ptr/fn.copy.html
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This works perfectly
pub fn mcopy<SPEC: Spec>(interpreter: &mut Interpreter, host: &mut dyn Host) { | ||
check!(interpreter, SPEC::enabled(CANCUN)); | ||
pop!(interpreter, dest, src, len); | ||
if len == U256::ZERO { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is not correct, even if len is zero, some gas needs to be deduced.
maybe it is best to check if len == 0
after [gas_or_fail](gas::verylowcopy_cost)
is added.
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: add new line here.
I think we are close! |
Co-authored-by: rakita <[email protected]>
Co-authored-by: rakita <[email protected]>
Co-authored-by: rakita <[email protected]>
Co-authored-by: rakita <[email protected]>
Awesome, thanks for all the feedback! it's been really helpful in learning all the details here. Let me know if there are any more problems you see here. |
Can you check why eth tests are failing? And can you write some tests for this |
914a46c
to
8fd3de5
Compare
Wrote some tests and got CI passing! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
gj!
Started working on this. Still needs work.
Will Close #523