Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 37 additions & 1 deletion test/blockchaintest/blockchaintest_runner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include <test/state/errors.hpp>
#include <test/state/ethash_difficulty.hpp>
#include <test/state/requests.hpp>
#include <test/state/rlp_decode.hpp>
#include <test/utils/block_transition.hpp>
#include <test/utils/mpt_hash.hpp>
#include <test/utils/rlp.hpp>
Expand Down Expand Up @@ -119,12 +120,43 @@ std::error_code validate_block(evmc_revision rev, state::BlobParams blob_params,
if (!test_block.withdrawals_parse_success)
return make_error_code(INCORRECT_BLOCK_FORMAT);

if (rev >= EVMC_OSAKA && test_block.rlp_size > MAX_RLP_BLOCK_SIZE)
if (rev >= EVMC_OSAKA && test_block.rlp.size() > MAX_RLP_BLOCK_SIZE)
return make_error_code(RLP_BLOCK_LIMIT_EXCEEDED);

return {};
}

/// Checks the transaction codec against a block's own serialization: every transaction in it must
/// decode, and encode back to the very same bytes.
void expect_transactions_round_trip(bytes_view block_rlp)
{
bytes_view body; // A block is [header, transactions, ...].
ASSERT_TRUE(rlp::take_list_payload(block_rlp, body));
ASSERT_TRUE(block_rlp.empty()) << "trailing bytes after the block";
bytes_view block_header;
ASSERT_TRUE(rlp::take_list_payload(body, block_header)); // Skipped over.
bytes_view txs;
ASSERT_TRUE(rlp::take_list_payload(body, txs));

while (!txs.empty())
{
const auto item = txs;
rlp::Header h;
ASSERT_TRUE(rlp::decode_header(txs, h)); // Advances txs to the item's payload.
const auto header_size = item.size() - txs.size();
txs.remove_prefix(h.payload_length);

// A legacy transaction is an RLP list here, a typed one an RLP string wrapping the
// EIP-2718 envelope; the envelope alone is the transaction.
const auto tx_bytes = h.is_list ? item.substr(0, header_size + h.payload_length) :
item.substr(header_size, h.payload_length);

const auto tx = state::decode_transaction(tx_bytes);
ASSERT_TRUE(tx.has_value()) << hex(tx_bytes);
EXPECT_EQ(rlp::encode(*tx), tx_bytes);
}
}

std::optional<uint64_t> mining_reward(evmc_revision rev) noexcept
{
if (rev < EVMC_BYZANTIUM)
Expand Down Expand Up @@ -218,6 +250,10 @@ void run_blockchain_tests(std::span<const BlockchainTest> tests, evmc::VM& vm)
SCOPED_TRACE(std::string{evmc::to_string(rev)} + '/' + std::to_string(case_index) +
'/' + c.name + '/' + std::to_string(test_block.block_info.number));

// Invalid blocks are skipped: they may carry transactions that do not even decode.
if (test_block.expected_exception.empty())
expect_transactions_round_trip(test_block.rlp);

const auto block_error =
validate_block(rev, blob_params, test_block, parent_header, parent_has_ommers);

Expand Down
2 changes: 1 addition & 1 deletion test/integration/blockchaintest/eip7778_block_gas.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@
},
"blocks": [
{
"rlp": "0x00",
"rlp": "0xf90285f90259a00000000000000000000000000000000000000000000000000000000000000001a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794000000000000000000000000000000000000c014a09906207bb91a552f2c9036ff75ffebd15d6262fe1f1dc40afa6e047158ee25e5a06e1d1e299aa4bca4b32c05a8bd8cf631d97c7d9b54b1401c373860db01a38efea0c220348cfca03fd761c800a2af15752cee5ba04f836e61f798c4c6222c0cab02b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800184010000008265960c80a000000000000000000000000000000000000000000000000000000000000000008800000000000000000ea056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b4218080a00000000000000000000000000000000000000000000000000000000000000000a0e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855e6a502e30180800e830186a094000000000000000000000000000000000000c0de8080c0800101c0c0",
"blockHeader": {
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000001",
"uncleHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
Expand Down
6 changes: 6 additions & 0 deletions test/statetest/statetest_runner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include <gtest/gtest.h>
#include <test/utils/mpt_hash.hpp>
#include <test/utils/rlp.hpp>
#include <test/utils/rlp_encode.hpp>
#include <test/utils/statetest.hpp>

namespace evmone::test
Expand Down Expand Up @@ -34,7 +35,12 @@ void run_state_test(const StateTransitionTest& test, evmc::VM& vm, bool trace_su
{
tx = state::decode_transaction(*expected.txbytes);
if (tx.has_value())
{
// Decoding is the inverse of encoding: what decoded must encode back exactly.
EXPECT_EQ(rlp::encode(*tx), *expected.txbytes);

tx->sender = template_tx.sender; // No recovery yet, take sender from JSON.
}
}

const auto res =
Expand Down
2 changes: 1 addition & 1 deletion test/utils/blockchaintest.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ struct TestBlock
{
state::BlockInfo block_info;
std::vector<state::Transaction> transactions;
size_t rlp_size = 0;
bytes rlp; ///< The block's complete serialization.
bool withdrawals_parse_success = true;
std::string expected_exception; ///< Empty for valid blocks.

Expand Down
4 changes: 2 additions & 2 deletions test/utils/blockchaintest_loader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -198,13 +198,13 @@ BlockchainTest load_blockchain_test_case(const std::string& name, const json::js

auto test_block = load_test_block(el.at("rlp_decoded"), bt.network, bt.blob_schedule);
test_block.expected_exception = map_legacy_block_exception(it->get<std::string>());
test_block.rlp_size = from_json<bytes>(el.at("rlp")).size();
test_block.rlp = from_json<bytes>(el.at("rlp"));
bt.test_blocks.emplace_back(test_block);
}
else
{
auto test_block = load_test_block(el, bt.network, bt.blob_schedule);
test_block.rlp_size = from_json<bytes>(el.at("rlp")).size();
test_block.rlp = from_json<bytes>(el.at("rlp"));
bt.test_blocks.emplace_back(test_block);
}
}
Expand Down