diff --git a/category/execution/ethereum/execute_block_header.cpp b/category/execution/ethereum/execute_block_header.cpp index e7c2c108ef..94aaa0f8e0 100644 --- a/category/execution/ethereum/execute_block_header.cpp +++ b/category/execution/ethereum/execute_block_header.cpp @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -79,7 +80,8 @@ void execute_block_header( staking::execute_block_prelude(state); } - MONAD_ASSERT(block_state.can_merge(state)); + MONAD_ASSERT_THROW( + block_state.can_merge(state), "block state cannot be merged"); block_state.merge(state); record_account_access_events( exec_recorder, MONAD_ACCT_ACCESS_BLOCK_PROLOGUE, state); diff --git a/category/rpc/monad_executor_test.cpp b/category/rpc/monad_executor_test.cpp index 75be8b3750..5cb5c9e8b8 100644 --- a/category/rpc/monad_executor_test.cpp +++ b/category/rpc/monad_executor_test.cpp @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -8254,3 +8255,117 @@ TEST_F(EthCallFixture, eth_simulate_v1_beacon_roots) monad_state_override_vec_destroy(state_overrides); monad_executor_destroy(executor); } + +TEST_F(EthCallFixture, eth_simulate_v1_block_history_state_override) +{ + static constexpr uint64_t base_block_number = 255; + static constexpr Address sender = + 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266_address; + + commit_sequential( + tdb, + StateDeltas{ + {sender, + StateDelta{ + .account = + {std::nullopt, + Account{.balance = uint256_t{1'000'000}, .nonce = 0}}}}}, + {}, + BlockHeader{.number = 0}); + + for (uint64_t i = 1; i <= base_block_number; ++i) { + commit_sequential(tdb, {}, {}, BlockHeader{.number = i}); + } + + auto *executor = create_executor(dbname.string()); + auto *const state_overrides = monad_state_override_vec_create(1); + auto *const block_overrides = monad_block_override_vec_create(1); + + uint8_t const code = 0; + bytes32_t const base = store_be_as(uint256_t{base_block_number}); + bytes32_t const slot_value = + 0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee_bytes32; + + add_override_address_at( + state_overrides, + 0, + BLOCK_HISTORY_ADDRESS.bytes, + sizeof(BLOCK_HISTORY_ADDRESS.bytes)); + set_override_code_at( + state_overrides, + 0, + BLOCK_HISTORY_ADDRESS.bytes, + sizeof(BLOCK_HISTORY_ADDRESS.bytes), + &code, + 0); + set_override_nonce_at( + state_overrides, + 0, + BLOCK_HISTORY_ADDRESS.bytes, + sizeof(BLOCK_HISTORY_ADDRESS.bytes), + 0); + set_override_state_diff_at( + state_overrides, + 0, + BLOCK_HISTORY_ADDRESS.bytes, + sizeof(BLOCK_HISTORY_ADDRESS.bytes), + base.bytes, + sizeof(base.bytes), + slot_value.bytes, + sizeof(slot_value.bytes)); + + auto const rlp_senders = to_vec(rlp::encode_list2( + rlp::encode_list2(rlp::encode_address(std::make_optional(sender))))); + + Transaction const tx{ + .max_fee_per_gas = 1, + .gas_limit = 200'000'000, + .to = BLOCK_HISTORY_ADDRESS, + .type = TransactionType::eip1559, + .max_priority_fee_per_gas = 0, + }; + auto const encoded_tx = rlp::encode_transaction(tx); + auto const rlp_calls = to_vec(rlp::encode_list2( + rlp::encode_list2(rlp::encode_string2(byte_string_view(encoded_tx))))); + + BlockHeader const header{ + .number = base_block_number, + .gas_limit = 200'000'000, + }; + auto const rlp_header = to_vec(rlp::encode_block_header(header)); + auto const rlp_block_id = to_vec(rlp_finalized_id); + + struct callback_context ctx; + boost::fibers::future f = ctx.promise.get_future(); + + monad_executor_eth_simulate_submit( + executor, + CHAIN_CONFIG_MONAD_DEVNET, + rlp_senders.data(), + rlp_senders.size(), + rlp_calls.data(), + rlp_calls.size(), + base_block_number, + rlp_header.data(), + rlp_header.size(), + rlp_block_id.data(), + rlp_block_id.size(), + rlp_finalized_id.data(), + rlp_finalized_id.size(), + simulate_gas_limit, + simulate_max_calls, + state_overrides, + block_overrides, + false, + complete_callback, + (void *)&ctx); + f.get(); + + ASSERT_EQ(ctx.result->status_code, EVMC_INTERNAL_ERROR); + ASSERT_NE(ctx.result->message, nullptr); + EXPECT_STREQ(ctx.result->message, "block state cannot be merged"); + + monad_block_override_vec_destroy(block_overrides); + monad_state_override_vec_destroy(state_overrides); + monad_executor_destroy(executor); +}