Skip to content

Commit

Permalink
baseline: Implement EIP-663
Browse files Browse the repository at this point in the history
  • Loading branch information
rodiazet committed Nov 30, 2022
1 parent cce6ab9 commit c2c0237
Show file tree
Hide file tree
Showing 7 changed files with 65 additions and 3 deletions.
3 changes: 3 additions & 0 deletions lib/evmone/advanced_instructions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,9 @@ constexpr std::array<instruction_exec_fn, 256> instruction_implementations = [](
table[OP_CREATE2] = op_create<OP_CREATE2>;
table[OP_STATICCALL] = op_call<OP_STATICCALL>;

table[OP_DUPN] = op_undefined;
table[OP_SWAPN] = op_undefined;

return table;
}();
} // namespace
Expand Down
34 changes: 34 additions & 0 deletions lib/evmone/instructions.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -820,6 +820,40 @@ inline void swap(StackTop stack) noexcept
a[3] = t3;
}

inline code_iterator dupn(StackTop stack, ExecutionState& state, code_iterator pos) noexcept
{
const auto n = pos[1] + 17 - 1;

const auto stack_size = &stack.top() - state.stack_space.bottom();

if (stack_size <= n)
{
state.status = EVMC_STACK_UNDERFLOW;
return nullptr;
}

stack.push(stack[n]);

return pos + 2;
}

inline code_iterator swapn(StackTop stack, ExecutionState& state, code_iterator pos) noexcept
{
const auto n = pos[1] + 17;

const auto stack_size = &stack.top() - state.stack_space.bottom();

if (stack_size <= n)
{
state.status = EVMC_STACK_UNDERFLOW;
return nullptr;
}

std::swap(stack.top(), stack[n]);

return pos + 2;
}

template <size_t NumTopics>
inline evmc_status_code log(StackTop stack, ExecutionState& state) noexcept
{
Expand Down
3 changes: 3 additions & 0 deletions lib/evmone/instructions_opcodes.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,9 @@ enum Opcode
OP_LOG3 = 0xa3,
OP_LOG4 = 0xa4,

OP_DUPN = 0xb2,
OP_SWAPN = 0xb3,

OP_CREATE = 0xf0,
OP_CALL = 0xf1,
OP_CALLCODE = 0xf2,
Expand Down
5 changes: 5 additions & 0 deletions lib/evmone/instructions_traits.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,8 @@ constexpr inline GasCostTable gas_costs = []() noexcept {
table[EVMC_SHANGHAI][OP_PUSH0] = 2;

table[EVMC_CANCUN] = table[EVMC_SHANGHAI];
table[EVMC_CANCUN][OP_DUPN] = 3;
table[EVMC_CANCUN][OP_SWAPN] = 3;

return table;
}();
Expand Down Expand Up @@ -360,6 +362,9 @@ constexpr inline std::array<Traits, 256> traits = []() noexcept {
table[OP_LOG3] = {"LOG3", 0, false, 5, -5, EVMC_FRONTIER};
table[OP_LOG4] = {"LOG4", 0, false, 6, -6, EVMC_FRONTIER};

table[OP_DUPN] = {"DUPN", 1, false, 0, 1, EVMC_CANCUN};
table[OP_SWAPN] = {"SWAPN", 1, false, 0, 0, EVMC_CANCUN};

table[OP_CREATE] = {"CREATE", 0, false, 3, -2, EVMC_FRONTIER};
table[OP_CALL] = {"CALL", 0, false, 7, -6, EVMC_FRONTIER};
table[OP_CALLCODE] = {"CALLCODE", 0, false, 7, -6, EVMC_FRONTIER};
Expand Down
4 changes: 2 additions & 2 deletions lib/evmone/instructions_xmacro.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -221,8 +221,8 @@
\
ON_OPCODE_UNDEFINED(0xb0) \
ON_OPCODE_UNDEFINED(0xb1) \
ON_OPCODE_UNDEFINED(0xb2) \
ON_OPCODE_UNDEFINED(0xb3) \
ON_OPCODE_IDENTIFIER(OP_DUPN, dupn) \
ON_OPCODE_IDENTIFIER(OP_SWAPN, swapn) \
ON_OPCODE_UNDEFINED(0xb4) \
ON_OPCODE_UNDEFINED(0xb5) \
ON_OPCODE_UNDEFINED(0xb6) \
Expand Down
2 changes: 1 addition & 1 deletion test/unittests/eof_validation_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,6 @@ TEST(eof_validation, EOF1_terminating_instructions)
opcode == OP_INVALID || opcode == OP_SELFDESTRUCT) ?
EOFValidationError::success :
EOFValidationError::missing_terminating_instruction);
EXPECT_EQ(validate_eof(container), expected) << hex(code);
EXPECT_EQ(validate_eof(container, EVMC_CANCUN), expected) << hex(code);
}
}
17 changes: 17 additions & 0 deletions test/unittests/instructions_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ constexpr void validate_traits_of() noexcept
// immediate_size
if constexpr (Op >= OP_PUSH1 && Op <= OP_PUSH32)
static_assert(tr.immediate_size == Op - OP_PUSH1 + 1);
else if constexpr (Op == OP_DUPN || Op == OP_SWAPN)
static_assert(tr.immediate_size == 1);
else
static_assert(tr.immediate_size == 0);

Expand Down Expand Up @@ -101,6 +103,10 @@ TEST(instructions, compare_with_evmc_instruction_tables)

for (size_t i = 0; i < evmone_tbl.size(); ++i)
{
// Skip DUPN and SWAPN for Cancun. They are not defined in evmc
// TODO: Define DUPN and SWAPN in evmc
if (r == EVMC_CANCUN && (Opcode(i) == OP_DUPN || Opcode(i) == OP_SWAPN))
continue;
const auto gas_cost = (instr_tbl[i] != instr::undefined) ? instr_tbl[i] : 0;
const auto& metrics = evmone_tbl[i];
const auto& ref_metrics = evmc_tbl[i];
Expand Down Expand Up @@ -129,7 +135,13 @@ TEST(instructions, compare_undefined_instructions)
const auto* evmc_names_tbl = evmc_get_instruction_names_table(rev);

for (size_t i = 0; i < instr_tbl.size(); ++i)
{
// Skip DUPN and SWAPN for Cancun. They are not defined in evmc
// TODO: Define DUPN and SWAPN in evmc
if (r == EVMC_CANCUN && (Opcode(i) == OP_DUPN || Opcode(i) == OP_SWAPN))
continue;
EXPECT_EQ(instr_tbl[i] == instr::undefined, evmc_names_tbl[i] == nullptr) << i;
}
}
}

Expand All @@ -138,6 +150,11 @@ TEST(instructions, compare_with_evmc_instruction_names)
const auto* evmc_tbl = evmc_get_instruction_names_table(EVMC_MAX_REVISION);
for (size_t i = 0; i < instr::traits.size(); ++i)
{
// Skip DUPN and SWAPN for Cancun. They are not defined in evmc
// TODO: Define DUPN and SWAPN in evmc
if (instr::traits[i].since == EVMC_CANCUN &&
(Opcode(i) == OP_DUPN || Opcode(i) == OP_SWAPN))
continue;
EXPECT_STREQ(instr::traits[i].name, evmc_tbl[i]);
}
}

0 comments on commit c2c0237

Please sign in to comment.