Skip to content

Commit aefb67e

Browse files
committed
Implement DATALOAD instruction
1 parent 4c03243 commit aefb67e

11 files changed

+54
-14
lines changed

lib/evmone/advanced_analysis.hpp

+3-3
Original file line numberDiff line numberDiff line change
@@ -90,9 +90,9 @@ struct AdvancedExecutionState : ExecutionState
9090
AdvancedExecutionState() noexcept : stack{stack_space.bottom()} {}
9191

9292
AdvancedExecutionState(const evmc_message& message, evmc_revision revision,
93-
const evmc_host_interface& host_interface, evmc_host_context* host_ctx,
94-
bytes_view _code) noexcept
95-
: ExecutionState{message, revision, host_interface, host_ctx, _code},
93+
const evmc_host_interface& host_interface, evmc_host_context* host_ctx, bytes_view _code,
94+
bytes_view _data) noexcept
95+
: ExecutionState{message, revision, host_interface, host_ctx, _code, _data},
9696
stack{stack_space.bottom()}
9797
{}
9898

lib/evmone/advanced_execution.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,8 @@ evmc_result execute(evmc_vm* /*unused*/, const evmc_host_interface* host, evmc_h
4545
}
4646
else
4747
analysis = analyze(rev, container);
48-
auto state = std::make_unique<AdvancedExecutionState>(*msg, rev, *host, ctx, container);
48+
auto state =
49+
std::make_unique<AdvancedExecutionState>(*msg, rev, *host, ctx, container, bytes_view{});
4950
return execute(*state, analysis);
5051
}
5152
} // namespace evmone::advanced

lib/evmone/baseline.cpp

+5-3
Original file line numberDiff line numberDiff line change
@@ -87,9 +87,11 @@ CodeAnalysis analyze_eof1(bytes_view container)
8787
for (const auto offset : header.code_offsets)
8888
relative_offsets.push_back(offset - code_sections_offset);
8989

90+
const auto data_section = container.substr(code_sections_end);
91+
9092
// FIXME: Better way of getting EOF version.
9193
const auto eof_version = container[2];
92-
return CodeAnalysis{executable_code, {}, eof_version, relative_offsets};
94+
return CodeAnalysis{executable_code, {}, eof_version, relative_offsets, data_section};
9395
}
9496
} // namespace
9597

@@ -375,8 +377,8 @@ evmc_result execute(evmc_vm* c_vm, const evmc_host_interface* host, evmc_host_co
375377
{
376378
auto vm = static_cast<VM*>(c_vm);
377379
const auto jumpdest_map = analyze(rev, {code, code_size});
378-
auto state =
379-
std::make_unique<ExecutionState>(*msg, rev, *host, ctx, bytes_view{code, code_size});
380+
auto state = std::make_unique<ExecutionState>(
381+
*msg, rev, *host, ctx, bytes_view{code, code_size}, jumpdest_map.data);
380382
return execute(*vm, *state, jumpdest_map);
381383
}
382384
} // namespace evmone::baseline

lib/evmone/baseline.hpp

+6-2
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ class CodeAnalysis
3131
/// section. We flatten the sections for cheap execution.
3232
CodeOffsets code_offsets;
3333

34+
bytes_view data; ///< Data section.
35+
3436
private:
3537
/// Padded code for faster legacy code execution.
3638
/// If not nullptr the executable_code must point to it.
@@ -43,11 +45,13 @@ class CodeAnalysis
4345
m_padded_code{std::move(padded_code)}
4446
{}
4547

46-
CodeAnalysis(bytes_view code, JumpdestMap map, uint8_t version, CodeOffsets offsets)
48+
CodeAnalysis(bytes_view code, JumpdestMap map, uint8_t version, CodeOffsets offsets,
49+
bytes_view data_section)
4750
: executable_code{code},
4851
jumpdest_map{std::move(map)},
4952
eof_version{version},
50-
code_offsets{std::move(offsets)}
53+
code_offsets{std::move(offsets)},
54+
data{data_section}
5155
{}
5256
};
5357
static_assert(std::is_move_constructible_v<CodeAnalysis>);

lib/evmone/execution_state.hpp

+6-3
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,8 @@ class ExecutionState
138138
/// For EOF-formatted code this is a reference to entire container.
139139
bytes_view original_code;
140140

141+
bytes_view data;
142+
141143
evmc_status_code status = EVMC_SUCCESS;
142144
size_t output_offset = 0;
143145
size_t output_size = 0;
@@ -164,13 +166,14 @@ class ExecutionState
164166
ExecutionState() noexcept = default;
165167

166168
ExecutionState(const evmc_message& message, evmc_revision revision,
167-
const evmc_host_interface& host_interface, evmc_host_context* host_ctx,
168-
bytes_view _code) noexcept
169+
const evmc_host_interface& host_interface, evmc_host_context* host_ctx, bytes_view _code,
170+
bytes_view _data) noexcept
169171
: gas_left{message.gas},
170172
msg{&message},
171173
host{host_interface, host_ctx},
172174
rev{revision},
173-
original_code{_code}
175+
original_code{_code},
176+
data{_data}
174177
{}
175178

176179
/// Resets the contents of the ExecutionState so that it could be reused.

lib/evmone/instructions.hpp

+25
Original file line numberDiff line numberDiff line change
@@ -890,6 +890,31 @@ inline code_iterator swapn(StackTop stack, ExecutionState& state, code_iterator
890890
return pos + 2;
891891
}
892892

893+
inline evmc_status_code dataload(StackTop stack, ExecutionState& state) noexcept
894+
{
895+
auto& index = stack.top();
896+
897+
if (state.msg->input_size < index)
898+
index = 0;
899+
else
900+
{
901+
if (state.data.size() < index)
902+
return EVMC_INVALID_MEMORY_ACCESS; // TODO better error
903+
const auto begin = static_cast<size_t>(index);
904+
905+
const auto end = begin + 32;
906+
if (end > state.data.size())
907+
return EVMC_INVALID_MEMORY_ACCESS; // TODO better error
908+
909+
uint8_t data[32] = {};
910+
for (size_t i = 0; i < 32; ++i)
911+
data[i] = state.data[begin + i];
912+
913+
index = intx::be::load<uint256>(data);
914+
}
915+
return EVMC_SUCCESS;
916+
}
917+
893918
template <size_t NumTopics>
894919
inline evmc_status_code log(StackTop stack, ExecutionState& state) noexcept
895920
{

lib/evmone/instructions_opcodes.hpp

+2
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,8 @@ enum Opcode : uint8_t
163163
OP_DUPN = 0xb5,
164164
OP_SWAPN = 0xb6,
165165

166+
OP_DATALOAD = 0xb7,
167+
166168
OP_CREATE = 0xf0,
167169
OP_CALL = 0xf1,
168170
OP_CALLCODE = 0xf2,

lib/evmone/instructions_traits.hpp

+2
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,7 @@ constexpr inline GasCostTable gas_costs = []() noexcept {
171171
table[EVMC_CANCUN][OP_RJUMPV] = 4;
172172
table[EVMC_CANCUN][OP_CALLF] = 5;
173173
table[EVMC_CANCUN][OP_RETF] = 3;
174+
table[EVMC_CANCUN][OP_DATALOAD] = 3;
174175

175176
table[EVMC_PRAGUE] = table[EVMC_CANCUN];
176177

@@ -375,6 +376,7 @@ constexpr inline std::array<Traits, 256> traits = []() noexcept {
375376

376377
table[OP_DUPN] = {"DUPN", 1, false, 0, 1, EVMC_CANCUN};
377378
table[OP_SWAPN] = {"SWAPN", 1, false, 0, 0, EVMC_CANCUN};
379+
table[OP_DATALOAD] = {"DATALOAD", 0, false, 1, 0, EVMC_CANCUN};
378380

379381
table[OP_CREATE] = {"CREATE", 0, false, 3, -2, EVMC_FRONTIER};
380382
table[OP_CALL] = {"CALL", 0, false, 7, -6, EVMC_FRONTIER};

lib/evmone/instructions_xmacro.hpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,7 @@
226226
ON_OPCODE_UNDEFINED(0xb4) \
227227
ON_OPCODE_IDENTIFIER(OP_DUPN, dupn) \
228228
ON_OPCODE_IDENTIFIER(OP_SWAPN, swapn) \
229-
ON_OPCODE_UNDEFINED(0xb7) \
229+
ON_OPCODE_IDENTIFIER(OP_DATALOAD, dataload) \
230230
ON_OPCODE_UNDEFINED(0xb8) \
231231
ON_OPCODE_UNDEFINED(0xb9) \
232232
ON_OPCODE_UNDEFINED(0xba) \

test/unittests/execution_state_test.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ TEST(execution_state, construct)
2626
const evmc_host_interface host_interface{};
2727
const uint8_t code[]{0x0f};
2828
const evmone::ExecutionState st{
29-
msg, EVMC_MAX_REVISION, host_interface, nullptr, {code, std::size(code)}};
29+
msg, EVMC_MAX_REVISION, host_interface, nullptr, {code, std::size(code)}, {}};
3030

3131
EXPECT_EQ(st.gas_left, -1);
3232
EXPECT_EQ(st.memory.size(), 0);

test/unittests/instructions_test.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ constexpr bool instruction_only_in_evmone(evmc_revision rev, Opcode op) noexcept
110110
case OP_RETF:
111111
case OP_DUPN:
112112
case OP_SWAPN:
113+
case OP_DATALOAD:
113114
return true;
114115
default:
115116
return false;

0 commit comments

Comments
 (0)