Skip to content

Commit

Permalink
eof: Disallow EOFCREATE and RETURNCONTRACT referencing the same conta…
Browse files Browse the repository at this point in the history
…iner

This allows to get rid of ContainerKind::initcode_runtime.
  • Loading branch information
gumb0 authored and chfast committed Jun 28, 2024
1 parent cb6a50f commit df592fe
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 df592fe

Please sign in to comment.