Skip to content

Commit

Permalink
Fix bug at block #116524
Browse files Browse the repository at this point in the history
What Changed
============

When `size` was 0 on callcode we were returning 0. Instead we should be
returning the machine state unchanged. This didn't cause an error until
block #116524 where callcode was called with `size = 0`.

Other changes
-----------
* Added a script to run raw EVM code. I used this while debugging this
issue.
* Minor EVM README fix
  • Loading branch information
masonforest committed Aug 23, 2018
1 parent f9a4ad5 commit 8279808
Show file tree
Hide file tree
Showing 4 changed files with 84 additions and 8 deletions.
65 changes: 65 additions & 0 deletions apps/blockchain/scripts/evm_runner.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
defmodule EVMRunner do
@moduledoc """
Allows you to run raw evm code.
Eg.
$ mix run apps/blockchain/scripts/evm_runner.ex --code 600360050160005260206000f3 --gas-limit 27
10:11:11.929 [debug] Gas Remaining: 3
10:11:11.936 [debug] Result: <<0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8>>
"""
require Logger
alias EVM.{VM, ExecEnv}
alias EVM.Interface.Mock.MockAccountInterface
alias EVM.Interface.Mock.MockBlockInterface

def run() do
{
args,
_
} = OptionParser.parse!(System.argv(),
switches: [
code: :string,
address: :string,
originator: :string,
timestamp: :integer,
gas_limit: :integer,
])
account_interface = MockAccountInterface.new()
block_interface = MockBlockInterface.new(%{
timestamp: Keyword.get(args, :timestamp, 0),
})

gas_limit = Keyword.get(args, :gas_limit, 2_000_000)
code_hex = Keyword.get(args, :code, "")
machine_code = Base.decode16!(code_hex, case: :mixed)
address = args
|> Keyword.get(:address, "")
|> Base.decode16,
originator = args
|> Keyword.get(:originator, "")
|> Base.decode16,

exec_env = %ExecEnv{
machine_code: machine_code,
address: Keyword.get(args, :address, "") |> Base.decode16,
originator: Keyword.get(args, :originator, "") |> Base.decode16,
account_interface: account_interface,
block_interface: block_interface,
}

{gas_remaining, _sub_state, _exec_env, result} = VM.run(gas_limit, exec_env)
Logger.debug fn ->
"Gas Remaining: #{gas_remaining}"
end

Logger.debug fn ->
"Result: #{inspect result}"
end
end
end

EVMRunner.run()
2 changes: 1 addition & 1 deletion apps/evm/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ As discussed in the paper, we define a few data structures.
Here is an example of a simple program running on the VM:

```elixir
EVM.VM.run(%{}, 5, %EVM.ExecEnv{machine_code: EVM.MachineCode.compile([:push1, 3, :push1, 5, :add, :push1, 0x00, :mstore, :push1, 0, :push1, 32, :return])})
EVM.VM.run(%{}, 5, %EVM.ExecEnv{machine_code: EVM.MachineCode.compile([:push1, 3, :push1, 5, :add, :push1, 0x00, :mstore, :push1, 32, :push1, 0, :return])})
{%{}, 5, [], [], 0, <<0x08::256>>}
```

Expand Down
10 changes: 3 additions & 7 deletions apps/evm/lib/evm/operation/environmental_information.ex
Original file line number Diff line number Diff line change
Expand Up @@ -205,14 +205,10 @@ defmodule EVM.Operation.EnvironmentalInformation do
exec_env: exec_env,
machine_state: machine_state
}) do
if size == 0 do
0
else
data = Memory.read_zeroed_memory(exec_env.machine_code, code_offset, size)
machine_state = Memory.write(machine_state, mem_offset, data)
data = Memory.read_zeroed_memory(exec_env.machine_code, code_offset, size)
machine_state = Memory.write(machine_state, mem_offset, data)

%{machine_state: machine_state}
end
%{machine_state: machine_state}
end

@doc """
Expand Down
15 changes: 15 additions & 0 deletions apps/evm/test/evm/operation/environmental_information_test.exs
Original file line number Diff line number Diff line change
@@ -1,4 +1,19 @@
defmodule EVM.Operation.EnvironmentalInformationTest do
use ExUnit.Case, async: true
doctest EVM.Operation.EnvironmentalInformation

test "returns the vm_map unchanged if `size` is equal to `0`" do
code = <<54>>
mem_offset = 0
code_offset = 0
size = 0
exec_env = %EVM.ExecEnv{machine_code: code}
machine_state = %EVM.MachineState{}
vm_map = %{exec_env: exec_env, machine_state: machine_state}

result =
EVM.Operation.EnvironmentalInformation.codecopy([mem_offset, code_offset, size], vm_map)

assert result == %{machine_state: machine_state}
end
end

0 comments on commit 8279808

Please sign in to comment.