From 6f26198da573bc5daeabb303ea4e3dc4b3e074e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Mon, 10 Aug 2026 19:14:27 +0200 Subject: [PATCH] test: Skip block reason checks for an unrecovered sender The gap was patched only in the state-root check's names, but the requests and blob-gas checks run before it, so a block whose bad signature the runner cannot see was judged against a rule it does not break. Skip those checks too, as for the unvalidated ommer headers. --- test/blockchaintest/blockchaintest_runner.cpp | 21 ++--- .../integration/blockchaintest/CMakeLists.txt | 10 ++ .../unrecovered_sender_blob_gas.json | 86 +++++++++++++++++ .../unrecovered_sender_deposit_log.json | 92 +++++++++++++++++++ 4 files changed, 198 insertions(+), 11 deletions(-) create mode 100644 test/integration/blockchaintest/unrecovered_sender_blob_gas.json create mode 100644 test/integration/blockchaintest/unrecovered_sender_deposit_log.json diff --git a/test/blockchaintest/blockchaintest_runner.cpp b/test/blockchaintest/blockchaintest_runner.cpp index c328e57368..aa821e822c 100644 --- a/test/blockchaintest/blockchaintest_runner.cpp +++ b/test/blockchaintest/blockchaintest_runner.cpp @@ -373,11 +373,14 @@ void run_blockchain_tests(std::span tests, evmc::VM& vm) } if (res.requests_error) { - // Requests collection failure; verify the reason the same way. - EXPECT_TRUE(is_expected_block_exception( - res.requests_error, test_block.expected_exception)) - << "Block invalidity reason mismatch: got " << res.requests_error.message() - << ", expected " << test_block.expected_exception; + if (!sender_not_recovered) + { + EXPECT_TRUE(is_expected_block_exception( + res.requests_error, test_block.expected_exception)) + << "Block invalidity reason mismatch: got " + << res.requests_error.message() << ", expected " + << test_block.expected_exception; + } continue; } // The block executed, so it is invalid only if it computes something other than @@ -392,7 +395,7 @@ void run_blockchain_tests(std::span tests, evmc::VM& vm) // Asserts the fixture names one of @p names, the exceptions the check that just // fired is the symptom of. Silent where the reason cannot be compared. const auto expect_fixture_names = [&](std::string_view names) { - if (!names_spec_exception || ommers_not_validated) + if (!names_spec_exception || ommers_not_validated || sender_not_recovered) return; EXPECT_TRUE(contains_any(test_block.expected_exception, names)) << "Block invalidity reason mismatch: the block failed the check for " @@ -410,11 +413,7 @@ void run_blockchain_tests(std::span tests, evmc::VM& vm) if (state::mpt_hash(res.block_state) != test_block.expected_block_header.state_root) { - // The state root is also where a sender that was not recovered surfaces, - // see the TODO above. - expect_fixture_names( - "BlockException.INVALID_STATE_ROOT|" - "TransactionException.INVALID_SIGNATURE_VRS"); + expect_fixture_names("BlockException.INVALID_STATE_ROOT"); continue; } diff --git a/test/integration/blockchaintest/CMakeLists.txt b/test/integration/blockchaintest/CMakeLists.txt index 5e187c0151..f15ee5363c 100644 --- a/test/integration/blockchaintest/CMakeLists.txt +++ b/test/integration/blockchaintest/CMakeLists.txt @@ -23,5 +23,15 @@ add_test( COMMAND evmone-blockchaintest ${TESTS1}/eip7778_block_gas.json ) +# A block invalid by its signature must not be judged by another check. +add_test( + NAME ${PREFIX}/unrecovered_sender_blob_gas + COMMAND evmone-blockchaintest ${TESTS1}/unrecovered_sender_blob_gas.json +) +add_test( + NAME ${PREFIX}/unrecovered_sender_deposit_log + COMMAND evmone-blockchaintest ${TESTS1}/unrecovered_sender_deposit_log.json +) + get_directory_property(ALL_TESTS TESTS) set_tests_properties(${ALL_TESTS} PROPERTIES ENVIRONMENT LLVM_PROFILE_FILE=${CMAKE_BINARY_DIR}/integration-%p.profraw) diff --git a/test/integration/blockchaintest/unrecovered_sender_blob_gas.json b/test/integration/blockchaintest/unrecovered_sender_blob_gas.json new file mode 100644 index 0000000000..3cae9b0ac4 --- /dev/null +++ b/test/integration/blockchaintest/unrecovered_sender_blob_gas.json @@ -0,0 +1,86 @@ +{ + "unrecovered_sender_blob_gas": { + "_info": { + "comment": "The runner takes the sender from the fixture, so it cannot see the broken signature; the transaction executes and the wrong blobGasUsed is the first header mismatch." + }, + "network": "Cancun", + "genesisBlockHeader": { + "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "coinbase": "0x0000000000000000000000000000000000000000", + "stateRoot": "0x0000000000000000000000000000000000000000000000000000000000000000", + "transactionsTrie": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "receiptTrie": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "bloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "number": "0x00", + "gasLimit": "0x01000000", + "gasUsed": "0x00", + "timestamp": "0x00", + "extraData": "0x00", + "baseFeePerGas": "0x10", + "withdrawalsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "blobGasUsed": "0x00", + "excessBlobGas": "0x00", + "hash": "0x0000000000000000000000000000000000000000000000000000000000000001" + }, + "pre": { + "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b": { + "code": "0x", + "nonce": "0x00", + "balance": "0x02540be400" + } + }, + "blocks": [ + { + "expectException": "TransactionException.INVALID_SIGNATURE_VRS", + "rlp": "0x", + "rlp_decoded": { + "blockHeader": { + "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000001", + "coinbase": "0x000000000000000000000000000000000000c014", + "stateRoot": "0x0000000000000000000000000000000000000000000000000000000000000000", + "transactionsTrie": "0x0000000000000000000000000000000000000000000000000000000000000000", + "receiptTrie": "0x0000000000000000000000000000000000000000000000000000000000000000", + "bloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "number": "0x01", + "gasLimit": "0x01000000", + "gasUsed": "0x00", + "timestamp": "0x0c", + "extraData": "0x", + "baseFeePerGas": "0x0e", + "blobGasUsed": "0x00", + "excessBlobGas": "0x00", + "hash": "0x0000000000000000000000000000000000000000000000000000000000000002" + }, + "transactions": [ + { + "type": "0x03", + "nonce": "0x00", + "to": "0x000000000000000000000000000000000000c0de", + "value": "0x00", + "input": "0x", + "gasLimit": "0x186a0", + "maxFeePerGas": "0x0e", + "maxPriorityFeePerGas": "0x00", + "maxFeePerBlobGas": "0x01", + "blobVersionedHashes": [ + "0x0100000000000000000000000000000000000000000000000000000000000001" + ], + "v": "0x00", + "r": "0x00", + "s": "0x01", + "sender": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b" + } + ] + } + } + ], + "lastblockhash": "0x0000000000000000000000000000000000000000000000000000000000000001", + "postState": { + "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b": { + "code": "0x", + "nonce": "0x00", + "balance": "0x02540be400" + } + } + } +} \ No newline at end of file diff --git a/test/integration/blockchaintest/unrecovered_sender_deposit_log.json b/test/integration/blockchaintest/unrecovered_sender_deposit_log.json new file mode 100644 index 0000000000..5af9cf9ee6 --- /dev/null +++ b/test/integration/blockchaintest/unrecovered_sender_deposit_log.json @@ -0,0 +1,92 @@ +{ + "unrecovered_sender_deposit_log": { + "_info": { + "comment": "As above, but the block reaches the requests check: the executed transaction makes the deposit contract emit a log with no data." + }, + "network": "Prague", + "genesisBlockHeader": { + "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "coinbase": "0x0000000000000000000000000000000000000000", + "stateRoot": "0x0000000000000000000000000000000000000000000000000000000000000000", + "transactionsTrie": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "receiptTrie": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "bloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "number": "0x00", + "gasLimit": "0x01000000", + "gasUsed": "0x00", + "timestamp": "0x00", + "extraData": "0x00", + "baseFeePerGas": "0x10", + "withdrawalsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "blobGasUsed": "0x00", + "excessBlobGas": "0x00", + "hash": "0x0000000000000000000000000000000000000000000000000000000000000001" + }, + "pre": { + "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b": { + "code": "0x", + "nonce": "0x00", + "balance": "0x02540be400" + }, + "0x00000000219ab540356cbb839cbe05303d7705fa": { + "code": "0x7f649bbc62d0e31342afea4e5cd82d4049e7e1ee912fc0889aa790803be39038c560006000a1", + "nonce": "0x01", + "balance": "0x00" + } + }, + "blocks": [ + { + "expectException": "TransactionException.INVALID_SIGNATURE_VRS", + "rlp": "0x", + "rlp_decoded": { + "blockHeader": { + "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000001", + "coinbase": "0x000000000000000000000000000000000000c014", + "stateRoot": "0x0000000000000000000000000000000000000000000000000000000000000000", + "transactionsTrie": "0x0000000000000000000000000000000000000000000000000000000000000000", + "receiptTrie": "0x0000000000000000000000000000000000000000000000000000000000000000", + "bloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "number": "0x01", + "gasLimit": "0x01000000", + "gasUsed": "0x00", + "timestamp": "0x0c", + "extraData": "0x", + "baseFeePerGas": "0x0e", + "blobGasUsed": "0x00", + "excessBlobGas": "0x00", + "hash": "0x0000000000000000000000000000000000000000000000000000000000000002" + }, + "transactions": [ + { + "type": "0x02", + "nonce": "0x00", + "to": "0x00000000219ab540356cbb839cbe05303d7705fa", + "value": "0x00", + "input": "0x", + "gasLimit": "0x186a0", + "maxFeePerGas": "0x0e", + "maxPriorityFeePerGas": "0x00", + "v": "0x00", + "r": "0x00", + "s": "0x01", + "sender": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b" + } + ] + } + } + ], + "lastblockhash": "0x0000000000000000000000000000000000000000000000000000000000000001", + "postState": { + "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b": { + "code": "0x", + "nonce": "0x00", + "balance": "0x02540be400" + }, + "0x00000000219ab540356cbb839cbe05303d7705fa": { + "code": "0x7f649bbc62d0e31342afea4e5cd82d4049e7e1ee912fc0889aa790803be39038c560006000a1", + "nonce": "0x01", + "balance": "0x00" + } + } + } +} \ No newline at end of file