Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

EIP-3607: Reject transactions from senders with deployed code #423

Merged
merged 5 commits into from Sep 9, 2021
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion .circleci/config.yml
Expand Up @@ -100,7 +100,7 @@ jobs:
- run:
name: "Ethereum consensus tests"
working_directory: ~/build
no_output_timeout: 15m
no_output_timeout: 20m
command: |
cmd/consensus
mv default.profraw consensus.profraw
Expand Down
29 changes: 15 additions & 14 deletions core/silkworm/chain/validity.hpp
Expand Up @@ -48,27 +48,28 @@ enum class [[nodiscard]] ValidationResult{

// See [YP] Section 6.2 "Execution", Eq (58)
kMissingSender = 15, // S(T) = ∅
kWrongNonce = 16, // Tn ≠ σ[S(T)]n
kIntrinsicGas = 17, // g0 > Tg
kInsufficientFunds = 18, // v0 > σ[S(T)]b
kBlockGasLimitExceeded = 19, // Tg > BHl - l(BR)u
kMaxFeeLessThanBase = 20, // max_fee_per_gas < base_fee_per_gas (EIP-1559)
kMaxPriorityFeeGreaterThanMax = 21, // max_priority_fee_per_gas > max_fee_per_gas (EIP-1559)
kSenderNoEOA = 16, // EIP-3607: σ[S(T)]c ≠ KEC( () )
kWrongNonce = 17, // Tn ≠ σ[S(T)]n
kIntrinsicGas = 18, // g0 > Tg
kInsufficientFunds = 19, // v0 > σ[S(T)]b
kBlockGasLimitExceeded = 20, // Tg > BHl - l(BR)u
kMaxFeeLessThanBase = 21, // max_fee_per_gas < base_fee_per_gas (EIP-1559)
kMaxPriorityFeeGreaterThanMax = 22, // max_priority_fee_per_gas > max_fee_per_gas (EIP-1559)

// See [YP] Section 11.1 "Ommer Validation", Eq (157)
kTooManyOmmers = 22, // ‖BU‖ > 2
kInvalidOmmerHeader = 23, // ¬V(U)
kNotAnOmmer = 24, // ¬k(U, P(BH)H, 6)
kDuplicateOmmer = 25, // not well covered by the YP actually
kTooManyOmmers = 23, // ‖BU‖ > 2
kInvalidOmmerHeader = 24, // ¬V(U)
kNotAnOmmer = 25, // ¬k(U, P(BH)H, 6)
kDuplicateOmmer = 26, // not well covered by the YP actually

// See [YP] Section 11.2 "Transaction Validation", Eq (160)
kWrongBlockGas = 26, // BHg ≠ l(BR)u
kWrongBlockGas = 27, // BHg ≠ l(BR)u

kInvalidSignature = 27, // EIP-2
kInvalidSignature = 28, // EIP-2

kWrongChainId = 28, // EIP-155
kWrongChainId = 29, // EIP-155

kUnsupportedTransactionType = 29, // EIP-2718
kUnsupportedTransactionType = 30, // EIP-2718
};

// Performs validation of a transaction that can be done prior to sender recovery and block execution.
Expand Down
File renamed without changes.
File renamed without changes.
4 changes: 4 additions & 0 deletions core/silkworm/execution/processor.cpp
Expand Up @@ -36,6 +36,10 @@ ValidationResult ExecutionProcessor::validate_transaction(const Transaction& txn
return ValidationResult::kMissingSender;
}

if (state_.get_code_hash(*txn.from) != kEmptyHash) {
return ValidationResult::kSenderNoEOA; // EIP-3607
}

const uint64_t nonce{state_.get_nonce(*txn.from)};
if (nonce != txn.nonce) {
return ValidationResult::kWrongNonce;
Expand Down
33 changes: 27 additions & 6 deletions core/silkworm/execution/processor_test.cpp
Expand Up @@ -20,6 +20,7 @@
#include <evmc/evmc.hpp>

#include <silkworm/chain/protocol_param.hpp>
#include <silkworm/common/test_util.hpp>
#include <silkworm/state/in_memory_state.hpp>

#include "address.hpp"
Expand All @@ -28,8 +29,6 @@
namespace silkworm {

TEST_CASE("Zero gas price") {
using Catch::Message;

Block block{};
block.header.number = 2'687'232;
block.header.gas_limit = 3'303'221;
Expand Down Expand Up @@ -63,6 +62,26 @@ TEST_CASE("Zero gas price") {
CHECK(receipt.success);
}

TEST_CASE("EIP-3607: Reject transactions from senders with deployed code") {
Block block{};
block.header.number = 1;
block.header.gas_limit = 3'000'000;

const evmc::address sender{0x71562b71999873DB5b286dF957af199Ec94617F7_address};

Transaction txn{test_util::sample_transactions()[0]};
txn.nonce = 0;
txn.from = sender;

InMemoryState state;
ExecutionProcessor processor{block, state, kMainnetConfig};

processor.evm().state().add_to_balance(sender, 10 * kEther);
processor.evm().state().set_code(sender, *from_hex("B0B0FACE"));

CHECK(processor.validate_transaction(txn) == ValidationResult::kSenderNoEOA);
}

TEST_CASE("No refund on error") {
Block block{};
block.header.number = 10'050'107;
Expand Down Expand Up @@ -139,8 +158,10 @@ TEST_CASE("Self-destruct") {
block.header.number = 1'487'375;
block.header.gas_limit = 4'712'388;
block.header.beneficiary = 0x61c808d82a3ac53231750dadc13c777b59310bd9_address;
evmc::address suicidal_address{0x6d20c1c07e56b7098eb8c50ee03ba0f6f498a91d_address};
evmc::address caller_address{0x4bf2054ffae7a454a35fd8cf4be21b23b1f25a6f_address};

const evmc::address suicidal_address{0x6d20c1c07e56b7098eb8c50ee03ba0f6f498a91d_address};
const evmc::address caller_address{0x4bf2054ffae7a454a35fd8cf4be21b23b1f25a6f_address};
const evmc::address originator{0x5a0b54d5dc17e0aadc383d2db43b0a0d3e029c4c_address};

// The contract self-destructs if called with zero value.
Bytes suicidal_code{*from_hex("346007576000ff5b")};
Expand Down Expand Up @@ -191,7 +212,7 @@ TEST_CASE("Self-destruct") {
InMemoryState state;
ExecutionProcessor processor{block, state, kMainnetConfig};

processor.evm().state().add_to_balance(caller_address, kEther);
processor.evm().state().add_to_balance(originator, kEther);
processor.evm().state().set_code(caller_address, caller_code);
processor.evm().state().set_code(suicidal_address, suicidal_code);

Expand All @@ -209,7 +230,7 @@ TEST_CASE("Self-destruct") {
1, // r
1, // s
};
txn.from = caller_address;
txn.from = originator;

evmc::bytes32 address_as_hash{to_bytes32(full_view(suicidal_address))};
txn.data = full_view(address_as_hash);
Expand Down
2 changes: 0 additions & 2 deletions core/silkworm/rlp/decode_test.cpp
Expand Up @@ -51,8 +51,6 @@ static std::vector<T> decode_vector_success(std::string_view hex) {
}

TEST_CASE("RLP decoding") {
using Catch::Message;

SECTION("strings") {
CHECK(to_hex(decode_success<Bytes>("00")) == "00");
CHECK(to_hex(decode_success<Bytes>("8D6F62636465666768696A6B6C6D")) == "6f62636465666768696a6b6c6d");
Expand Down
2 changes: 1 addition & 1 deletion tests
Submodule tests updated 215 files