Skip to content

Commit

Permalink
Disallow EOFCREATE and RETURNCONTRACT referencing the same container
Browse files Browse the repository at this point in the history
This allows to get rid of ContainerKind::initcode_runtime.
  • Loading branch information
gumb0 committed Jun 26, 2024
1 parent f36f6d4 commit 3e6cf42
Show file tree
Hide file tree
Showing 5 changed files with 25 additions and 91 deletions.
17 changes: 8 additions & 9 deletions lib/evmone/eof.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -329,7 +329,7 @@ std::variant<InstructionValidationResult, EOFValidationError> validate_instructi

if (op == OP_RETURNCONTRACT)
{
if (kind == ContainerKind::runtime || kind == ContainerKind::initcode_runtime)
if (kind == ContainerKind::runtime)
return EOFValidationError::incompatible_container_kind;
}

Expand All @@ -338,7 +338,7 @@ std::variant<InstructionValidationResult, EOFValidationError> validate_instructi
}
else if (op == OP_RETURN || op == OP_STOP)
{
if (kind == ContainerKind::initcode || kind == ContainerKind::initcode_runtime)
if (kind == ContainerKind::initcode)
return EOFValidationError::incompatible_container_kind;
}
else
Expand Down Expand Up @@ -683,8 +683,7 @@ EOFValidationError validate_eof1(
{
if (main_container == container)
return EOFValidationError::toplevel_container_truncated;
if (container_kind == ContainerKind::initcode ||
container_kind == ContainerKind::initcode_runtime)
if (container_kind == ContainerKind::initcode)
return EOFValidationError::eofcreate_with_truncated_container;
}

Expand All @@ -696,14 +695,14 @@ EOFValidationError validate_eof1(
const bool eofcreate = subcontainer_referenced_by_eofcreate[subcont_idx];
const bool returncontract = subcontainer_referenced_by_returncontract[subcont_idx];

if (eofcreate && returncontract)
return EOFValidationError::ambiguous_container_kind;
if (!eofcreate && !returncontract)
return EOFValidationError::unreferenced_subcontainer;

auto subcontainer_kind = ContainerKind::initcode_runtime;
if (!eofcreate)
subcontainer_kind = ContainerKind::runtime;
else if (!returncontract)
subcontainer_kind = ContainerKind::initcode;
const auto subcontainer_kind =
(eofcreate ? ContainerKind::initcode : ContainerKind::runtime);
assert(subcontainer_kind == ContainerKind::initcode || returncontract);

container_queue.push({subcontainer, subcontainer_kind});
}
Expand Down
3 changes: 0 additions & 3 deletions lib/evmone/eof.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -153,9 +153,6 @@ enum class ContainerKind : uint8_t
initcode,
/// Container that uses STOP/RETURN. Can be returned by RETURNCONTRACT.
runtime,
/// Container that uses only REVERT/INVALID or does not terminate execution.
/// Can be used in any context.
initcode_runtime,
};

/// Determines the EOF version of the container by inspecting container's EOF prefix.
Expand Down
2 changes: 0 additions & 2 deletions test/eoftest/eoftest_runner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,6 @@ ContainerKind container_kind_from_string(std::string_view s)
return ContainerKind::runtime;
else if (s == "initcode")
return ContainerKind::initcode;
else if (s == "initcode_runtime")
return ContainerKind::initcode_runtime;
else
throw std::invalid_argument{"unknown container kind"};
}
Expand Down
2 changes: 0 additions & 2 deletions test/unittests/eof_validation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -111,8 +111,6 @@ std::string_view to_string(ContainerKind container_kind) noexcept
return "runtime";
case (ContainerKind::initcode):
return "initcode";
case (ContainerKind::initcode_runtime):
return "initcode_runtime";
}
return "<unknown>";
}
Expand Down
92 changes: 17 additions & 75 deletions test/unittests/eof_validation_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1396,81 +1396,6 @@ TEST_F(eof_validation, runtime_container_returncontract)
add_test_case(factory_container, EOFValidationError::incompatible_container_kind);
}

TEST_F(eof_validation, initcode_runtime_container_stop)
{
const auto runtime_container = eof_bytecode(OP_STOP);

add_test_case(runtime_container, ContainerKind::initcode_runtime,
EOFValidationError::incompatible_container_kind);

const auto initcontainer =
eof_bytecode(eofcreate() + returncontract(0, 0, 0), 4).container(runtime_container);

add_test_case(
initcontainer, ContainerKind::initcode, EOFValidationError::incompatible_container_kind);

const auto factory_code = eofcreate() + OP_STOP;
const bytecode factory_container = eof_bytecode(factory_code, 4).container(initcontainer);

add_test_case(factory_container, EOFValidationError::incompatible_container_kind);
}

TEST_F(eof_validation, initcode_runtime_container_return)
{
const auto runtime_container = eof_bytecode(ret(0, 0), 2);

add_test_case(runtime_container, ContainerKind::initcode_runtime,
EOFValidationError::incompatible_container_kind);

const auto initcontainer =
eof_bytecode(eofcreate() + returncontract(0, 0, 0), 4).container(runtime_container);

add_test_case(
initcontainer, ContainerKind::initcode, EOFValidationError::incompatible_container_kind);

const auto factory_code = eofcreate() + OP_STOP;
const bytecode factory_container = eof_bytecode(factory_code, 4).container(initcontainer);

add_test_case(factory_container, EOFValidationError::incompatible_container_kind);
}

TEST_F(eof_validation, initcode_runtime_container_revert)
{
const auto runtime_container =
eof_bytecode(returncontract(0, 0, 0), 2).container(eof_bytecode(OP_INVALID));

add_test_case(runtime_container, ContainerKind::initcode_runtime,
EOFValidationError::incompatible_container_kind);

const auto initcontainer =
eof_bytecode(eofcreate() + returncontract(0, 0, 0), 4).container(runtime_container);

add_test_case(
initcontainer, ContainerKind::initcode, EOFValidationError::incompatible_container_kind);

const auto factory_code = eofcreate() + OP_STOP;
const bytecode factory_container = eof_bytecode(factory_code, 4).container(initcontainer);

add_test_case(factory_container, EOFValidationError::incompatible_container_kind);
}

TEST_F(eof_validation, initcode_runtime_container_returncontract)
{
const auto runtime_container = eof_bytecode(revert(0, 0), 2);

add_test_case(runtime_container, ContainerKind::initcode_runtime, EOFValidationError::success);

const auto initcontainer =
eof_bytecode(eofcreate() + returncontract(0, 0, 0), 4).container(runtime_container);

add_test_case(initcontainer, ContainerKind::initcode, EOFValidationError::success);

const auto factory_code = eofcreate() + OP_STOP;
const bytecode factory_container = eof_bytecode(factory_code, 4).container(initcontainer);

add_test_case(factory_container, EOFValidationError::success);
}

TEST_F(eof_validation, eofcreate_stop_and_returncontract)
{
const auto runtime_container = eof_bytecode(OP_INVALID);
Expand All @@ -1492,3 +1417,20 @@ TEST_F(eof_validation, eofcreate_return_and_returncontract)

add_test_case(factory_container, EOFValidationError::incompatible_container_kind);
}

TEST_F(eof_validation, eofcreate_and_returncontract_targeting_same_container)
{
const auto runtime_container = eof_bytecode(OP_INVALID);
const auto initcode = eofcreate() + returncontract(0, 0, 0);
const auto initcontainer = eof_bytecode(initcode, 4).container(runtime_container);

add_test_case(
initcontainer, ContainerKind::initcode, EOFValidationError::ambiguous_container_kind);

const auto initcode2 = eofcreate() + eofcreate().container(1) + returncontract(1, 0, 0);
const auto initcontainer2 =
eof_bytecode(initcode, 4).container(runtime_container).container(runtime_container);

add_test_case(
initcontainer2, ContainerKind::initcode, EOFValidationError::ambiguous_container_kind);
}

0 comments on commit 3e6cf42

Please sign in to comment.