From 51ccacb0f597f125601dc918d0704d84b061cfb1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Fri, 2 Jun 2023 08:42:05 +0200 Subject: [PATCH] state: Implement fake `BLOCKHASH` resolution for testing If explict block hashes are not provided, return predefined block hashes from `Host::get_block_hash()` as `keccak256(str(block_number))`. This is badly documented convention used in state tests. Note: the readability of block hash values from `BLOCKHASH` instruction still applies. I.e. you will get 0 if you ask for a block from the future or more than 256 blocks older than the current one. --- test/state/host.cpp | 5 ++++- test/unittests/evm_state_test.cpp | 2 +- test/unittests/state_transition_block_test.cpp | 16 ++++++++++++---- test/utils/bytecode.hpp | 5 +++++ 4 files changed, 22 insertions(+), 6 deletions(-) diff --git a/test/state/host.cpp b/test/state/host.cpp index 43707cda86..9a932515ab 100644 --- a/test/state/host.cpp +++ b/test/state/host.cpp @@ -326,7 +326,10 @@ bytes32 Host::get_block_hash(int64_t block_number) const noexcept it != m_block.known_block_hashes.end()) return it->second; - return {}; + // Convention for testing: if the block hash in unknown return the predefined "fake" value. + // https://github.com/ethereum/go-ethereum/blob/v1.12.2/tests/state_test_util.go#L432 + const auto s = std::to_string(block_number); + return keccak256({reinterpret_cast(s.data()), s.size()}); } void Host::emit_log(const address& addr, const uint8_t* data, size_t data_size, diff --git a/test/unittests/evm_state_test.cpp b/test/unittests/evm_state_test.cpp index 1ec330efdd..e019b79134 100644 --- a/test/unittests/evm_state_test.cpp +++ b/test/unittests/evm_state_test.cpp @@ -432,7 +432,7 @@ TEST_P(evm, blockhash) host.block_hash.bytes[13] = 0x13; host.tx_context.block_number = 0; - const auto code = push(0) + OP_BLOCKHASH + ret_top(); + const auto code = blockhash(0) + ret_top(); execute(code); EXPECT_EQ(result.status_code, EVMC_SUCCESS); EXPECT_EQ(gas_used, 38); diff --git a/test/unittests/state_transition_block_test.cpp b/test/unittests/state_transition_block_test.cpp index e30e1579e1..14d02c746c 100644 --- a/test/unittests/state_transition_block_test.cpp +++ b/test/unittests/state_transition_block_test.cpp @@ -24,17 +24,25 @@ TEST_F(state_transition, known_block_hash) {2, 0x0000000000000000000000000000000000000000000000000000000000000111_bytes32}}; block.number = 5; - const auto code = - push(1) + OP_BLOCKHASH + push(0) + OP_SSTORE + push(2) + OP_BLOCKHASH + push(1) + OP_SSTORE; - tx.to = To; - pre.insert(*tx.to, {.nonce = 1, .code = code}); + pre.insert(*tx.to, {.nonce = 1, .code = sstore(0, blockhash(1)) + sstore(1, blockhash(2))}); expect.post[To].storage[0x00_bytes32] = 0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421_bytes32; expect.post[To].storage[0x01_bytes32] = 0x0000000000000000000000000000000000000000000000000000000000000111_bytes32; } +TEST_F(state_transition, known_block_hash_fake) +{ + block.number = 2; + tx.to = To; + pre.insert(*tx.to, {.nonce = 1, .code = sstore(0, blockhash(0)) + sstore(1, blockhash(1))}); + expect.post[To].storage[0x00_bytes32] = + 0x044852b2a670ade5407e78fb2863c51de9fcb96542a07186fe3aeda6bb8a116d_bytes32; + expect.post[To].storage[0x01_bytes32] = + 0xc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc6_bytes32; +} + TEST_F(state_transition, block_apply_ommers_reward) { rev = EVMC_LONDON; diff --git a/test/utils/bytecode.hpp b/test/utils/bytecode.hpp index 9056d6378b..2351f922ae 100644 --- a/test/utils/bytecode.hpp +++ b/test/utils/bytecode.hpp @@ -348,6 +348,11 @@ inline bytecode tload(bytecode index) return index + OP_TLOAD; } +inline bytecode blockhash(bytecode number) +{ + return number + OP_BLOCKHASH; +} + template struct call_instruction {