evm v0.1.14 EVM.Memory

Functions to help us handle memory operations in the MachineState of the VM.

Link to this section Summary

Functions

When calling instructions, we may adjust the number of active words in the machine state. These functions provide a simple way to determine the number of words after an instruction would be called. This wraps anywhere you might see μ'_i in the Yellow Paper

Returns the highest active word from the given inputs

Reads a word out of memory, and also decides whether or not we should increment number of active words in our machine state

Read zeroed memory will read bytes from a certain offset in the memory binary. Any bytes extending beyond memory’s size will be defauled to zero

Writes data to memory, and also decides whether or not we should increment number of active words in our machine state

Link to this section Types

Link to this type t()
t() :: binary

Link to this section Functions

Link to this function active_words_after(instruction, state, machine_state, exec_env)

When calling instructions, we may adjust the number of active words in the machine state. These functions provide a simple way to determine the number of words after an instruction would be called. This wraps anywhere you might see μ'_i in the Yellow Paper.

Link to this function get_active_words(bytes)

Returns the highest active word from the given inputs.

Examples

iex> EVM.Memory.get_active_words(0) # TODO: We may actually want this to start at 1, even for zero bytes read
0

iex> EVM.Memory.get_active_words(80)
3

iex> EVM.Memory.get_active_words(321)
11
Link to this function read(machine_state, offset, bytes \\ EVM.word_size())

Reads a word out of memory, and also decides whether or not we should increment number of active words in our machine state.

Examples

iex> EVM.Memory.read(%EVM.MachineState{memory: <<1::256, 2::256, 3::256, 4::256>>, active_words: 0}, 0, 0)
{<<>>, %EVM.MachineState{memory: <<1::256, 2::256, 3::256, 4::256>>, active_words: 0}}

iex> EVM.Memory.read(%EVM.MachineState{memory: <<1::256, 2::256, 3::256, 4::256>>, active_words: 0}, 0, 30)
{<<0::240>>, %EVM.MachineState{memory: <<1::256, 2::256, 3::256, 4::256>>, active_words: 1}}

iex> EVM.Memory.read(%EVM.MachineState{memory: <<1::256, 2::256, 3::256, 4::256>>, active_words: 0}, 0, 35)
{<<1::256, 0::24>>, %EVM.MachineState{memory: <<1::256, 2::256, 3::256, 4::256>>, active_words: 2}}

iex> EVM.Memory.read(%EVM.MachineState{memory: <<1::256, 2::256, 3::256, 4::256>>, active_words: 0}, 32, 35)
{<<2::256, 0::24>>, %EVM.MachineState{memory: <<1::256, 2::256, 3::256, 4::256>>, active_words: 3}}

iex> EVM.Memory.read(%EVM.MachineState{memory: <<1::256>>, active_words: 0}, 0, 35)
{<<1::256, 0::24>>, %EVM.MachineState{memory: <<1::256>>, active_words: 2}}
Link to this function read_zeroed_memory(memory, offset, bytes)
read_zeroed_memory(binary, EVM.val, EVM.val) :: binary

Read zeroed memory will read bytes from a certain offset in the memory binary. Any bytes extending beyond memory’s size will be defauled to zero.

Examples

iex> EVM.Memory.read_zeroed_memory(nil, 1, 4)
<<0, 0, 0, 0>>

iex> EVM.Memory.read_zeroed_memory(<<1, 2, 3>>, 1, 4)
<<2, 3, 0, 0>>

iex> EVM.Memory.read_zeroed_memory(<<1, 2, 3>>, 1, 2)
<<2, 3>>

iex> EVM.Memory.read_zeroed_memory(<<16, 17, 18, 19>>, 100, 1)
<<0>>
Link to this function write(machine_state, offset_bytes, original_data, size \\ nil)
write(EVM.MachineState.t, EVM.val, binary, integer) :: EVM.MachineState.t

Writes data to memory, and also decides whether or not we should increment number of active words in our machine state.

Note: we will fill in zeros if the memory extends beyond our previous memory bounds. This could (very easily) overflow our memory by making a single byte write to a far-away location. The gas might be high, but it’s still not desirable to have a system crash. The easiest mitigation will likely be to load in pages of memory as needed. These pages could have an offset and thus a far away page will only add a few bytes of memory.

For now, we’ll simply extend our memory and perform a simple write operation.

Note: we also may just use a different data structure all-together for this.

Examples

iex> EVM.Memory.write(%EVM.MachineState{memory: <<>>, active_words: 0}, 5, <<1, 1>>)
%EVM.MachineState{memory: <<0, 0, 0, 0, 0, 1, 1>>, active_words: 1}

iex> EVM.Memory.write(%EVM.MachineState{memory: <<0, 1, 2, 3, 4>>, active_words: 0}, 1, <<6, 6>>)
%EVM.MachineState{memory: <<0, 6, 6, 3, 4>>, active_words: 1}

iex> EVM.Memory.write(%EVM.MachineState{memory: <<0, 1, 2, 3, 4>>, active_words: 0}, 0, <<10, 11, 12, 13, 14, 15>>)
%EVM.MachineState{memory: <<10, 11, 12, 13, 14, 15>>, active_words: 1}

iex> EVM.Memory.write(%EVM.MachineState{memory: <<1, 1, 1>>, active_words: 0}, 5, <<1::80>>)
%EVM.MachineState{memory: <<1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1>>, active_words: 1}