-
Notifications
You must be signed in to change notification settings - Fork 47
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
fix writing to memory #497
Changes from all commits
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 |
---|---|---|
|
@@ -21,14 +21,11 @@ defmodule Blockchain.StateTest do | |
"stReturnDataTest/returndatacopy_following_call", | ||
"stReturnDataTest/returndatacopy_following_revert", | ||
"stReturnDataTest/returndatacopy_following_revert_in_create", | ||
"stRevertTest/PythonRevertTestTue201814-1430", | ||
"stRevertTest/RevertInCallCode", | ||
"stRevertTest/RevertInCreateInInit", | ||
"stRevertTest/RevertInDelegateCall", | ||
"stRevertTest/RevertOpcodeInCreateReturns", | ||
"stRevertTest/RevertOpcodeMultipleSubCalls", | ||
"stSpecialTest/failed_tx_xcf416c53", | ||
"stStaticCall/static_Call1024PreCalls2" | ||
"stSpecialTest/failed_tx_xcf416c53" | ||
], | ||
"Constantinople" => [ | ||
"stCreate2/CREATE2_ContractSuicideDuringInit_ThenStoreThenReturn", | ||
|
@@ -58,16 +55,12 @@ defmodule Blockchain.StateTest do | |
"stCreate2/returndatacopy_0_0_following_successful_create", | ||
"stCreate2/returndatacopy_afterFailing_create", | ||
"stCreate2/returndatacopy_following_revert_in_create", | ||
"stCreate2/returndatasize_following_successful_create", | ||
"stRevertTest/RevertOpcodeMultipleSubCalls" | ||
"stCreate2/returndatasize_following_successful_create" | ||
], | ||
"Frontier" => [], | ||
"Homestead" => ["stRevertTest/RevertOpcodeMultipleSubCalls"], | ||
"SpuriousDragon" => [ | ||
"stRevertTest/RevertOpcodeMultipleSubCalls", | ||
"stSpecialTest/failed_tx_xcf416c53" | ||
], | ||
"TangerineWhistle" => ["stRevertTest/RevertOpcodeMultipleSubCalls"] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes! Opcode multiple subcalls 🔥 |
||
"Homestead" => [], | ||
"SpuriousDragon" => ["stSpecialTest/failed_tx_xcf416c53"], | ||
"TangerineWhistle" => [] | ||
} | ||
|
||
@fifteen_minutes 1000 * 60 * 15 | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -79,13 +79,17 @@ defmodule EVM.Memory do | |
|
||
def write(machine_state = %MachineState{}, offset_bytes, original_data, size) do | ||
data = | ||
if size do | ||
original_data | ||
|> :binary.decode_unsigned() | ||
|> rem(size * EVM.word_size()) | ||
|> :binary.encode_unsigned() | ||
else | ||
original_data | ||
cond do | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is more clear what's going on here too 👍 |
||
is_nil(size) -> | ||
original_data | ||
|
||
size > byte_size(original_data) -> | ||
original_data | ||
|
||
true -> | ||
<<data::binary-size(size), _tail::bitstring>> = original_data | ||
|
||
data | ||
end | ||
|
||
memory_size = byte_size(machine_state.memory) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -200,7 +200,7 @@ defmodule EVM.MessageCall do | |
%{machine_state | last_return_data: output} | ||
|
||
true -> | ||
machine_state = Memory.write(machine_state, out_offset, output) | ||
machine_state = Memory.write(machine_state, out_offset, output, out_size) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is there a test that we could add for this? It seems like this was an important piece that was overlooked, and in terms of making sure we don't re-introduce this bug in the future, it would be nice to have a test that covers this. What do you think? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @germsvel done |
||
|
||
%{machine_state | last_return_data: output} | ||
end | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -65,7 +65,12 @@ defmodule EVM.Operation.StackMemoryStorageAndFlow do | |
""" | ||
@spec mstore8(Operation.stack_args(), Operation.vm_map()) :: Operation.op_result() | ||
def mstore8([offset, value], %{machine_state: machine_state}) do | ||
machine_state = Memory.write(machine_state, offset, value, EVM.byte_size()) | ||
byte_value = | ||
value | ||
|> rem(8 * EVM.word_size()) | ||
|> :binary.encode_unsigned() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This was added since the last time I reviewed this. Just curious, did this fix more things? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @germsvel this logic was moved from |
||
|
||
machine_state = Memory.write(machine_state, offset, byte_value) | ||
|
||
%{machine_state: machine_state} | ||
end | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,9 +3,31 @@ defmodule EVM.MemoryTest do | |
use ExUnit.Case, async: true | ||
doctest EVM.Memory | ||
|
||
test "returns the machine_state unchanged if data size is zero" do | ||
machine_state = %MachineState{} | ||
updated_machine_state = Memory.write(machine_state, 256, <<>>, 0) | ||
assert machine_state == updated_machine_state | ||
describe "write/4" do | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 I like these tests! |
||
test "returns the machine_state unchanged if data size is zero" do | ||
machine_state = %MachineState{} | ||
updated_machine_state = Memory.write(machine_state, 256, <<>>, 0) | ||
assert machine_state == updated_machine_state | ||
end | ||
|
||
test "truncates input if the size parameter is smaller than input's size" do | ||
machine_state = %MachineState{} | ||
input = Enum.reduce(1..60, <<>>, fn i, acc -> <<i>> <> acc end) | ||
|
||
updated_machine_state = Memory.write(machine_state, 0, input, 2) | ||
|
||
assert updated_machine_state.memory == <<60, 59>> | ||
assert updated_machine_state.active_words == 1 | ||
end | ||
|
||
test "does not truncate input if the size parameter is bigger than input's size" do | ||
machine_state = %MachineState{} | ||
input = Enum.reduce(1..60, <<>>, fn i, acc -> <<i>> <> acc end) | ||
|
||
updated_machine_state = Memory.write(machine_state, 0, input, 61) | ||
|
||
assert updated_machine_state.memory == input | ||
assert updated_machine_state.active_words == 2 | ||
end | ||
end | ||
end |
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.
🎉