Skip to content

Commit

Permalink
evmzero: Add check for range in blockHash op (#461)
Browse files Browse the repository at this point in the history
* Add range and overflow checks in BlockHash and edge cases unit test
  • Loading branch information
facuMH authored May 27, 2024
1 parent 07963e1 commit 7051d20
Show file tree
Hide file tree
Showing 3 changed files with 121 additions and 4 deletions.
21 changes: 20 additions & 1 deletion cpp/vm/evmzero/interpreter.cc
Original file line number Diff line number Diff line change
Expand Up @@ -864,8 +864,27 @@ struct Impl<OpCode::BLOCKHASH> {
constexpr static OpInfo kInfo = UnaryOp(20);

static OpResult Run(uint256_t* top, Context& ctx) noexcept {
if (top[0] > std::numeric_limits<int64_t>::max()) {
top[0] = 0;
return {};
}

int64_t number = static_cast<int64_t>(top[0]);
top[0] = ToUint256(ctx.host->get_block_hash(number));
int64_t upper, lower;
upper = int64_t(ctx.host->get_tx_context().block_number);
// BLOCKHASH description states that it gets the hash of a block not older
// than 256 in comparison with the current block. and in case the current
// block number is less than 256, then the lower boundary is 0.
if (upper < 257) {
lower = 0;
} else {
lower = upper - 256;
}
if (number >= lower && number < upper) {
top[0] = ToUint256(ctx.host->get_block_hash(number));
} else {
top[0] = 0;
}
return {};
}
};
Expand Down
81 changes: 78 additions & 3 deletions cpp/vm/evmzero/interpreter_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2834,9 +2834,13 @@ TEST(InterpreterTest, EXTCODEHASH_StackError) {

///////////////////////////////////////////////////////////
// BLOCKHASH
TEST(InterpreterTest, BLOCKHASH) {
TEST(InterpreterTest, BLOCKHASH_inRange) {
const uint64_t block_number = 1000;
MockHost host;
EXPECT_CALL(host, get_block_hash(21)) //
EXPECT_CALL(host, get_tx_context()) //
.Times(1)
.WillOnce(Return(evmc_tx_context{.block_number = block_number}));
EXPECT_CALL(host, get_block_hash(block_number - 1)) //
.Times(1)
.WillOnce(Return(evmc::bytes32(0x0a0b0c0d)));

Expand All @@ -2845,12 +2849,83 @@ TEST(InterpreterTest, BLOCKHASH) {
.state_after = RunState::kDone,
.gas_before = 40,
.gas_after = 20,
.stack_before = {21},
.stack_before = {block_number - 1},
.stack_after = {0x0a0b0c0d},
.host = &host,
});
}

TEST(InterpreterTest, BLOCKHASH_firstInRange) {
const uint64_t block_number = 1000;
MockHost host;
EXPECT_CALL(host, get_tx_context()) //
.Times(1)
.WillOnce(Return(evmc_tx_context{.block_number = block_number}));
EXPECT_CALL(host, get_block_hash(block_number - 256)) //
.Times(1)
.WillOnce(Return(evmc::bytes32(0x0a0b0c0d)));

RunInterpreterTest({
.code = {op::BLOCKHASH},
.state_after = RunState::kDone,
.gas_before = 40,
.gas_after = 20,
.stack_before = {block_number - 256},
.stack_after = {0x0a0b0c0d},
.host = &host,
});
}

TEST(InterpreterTest, BLOCKHASH_outOfRange) {
const uint64_t block_number = 1000;
MockHost host;
EXPECT_CALL(host, get_tx_context()) //
.Times(1)
.WillOnce(Return(evmc_tx_context{.block_number = block_number}));

RunInterpreterTest({
.code = {op::BLOCKHASH},
.state_after = RunState::kDone,
.gas_before = 40,
.gas_after = 20,
.stack_before = {block_number - 257},
.stack_after = {0},
.host = &host,
});
}

TEST(InterpreterTest, BLOCKHASH_sameAsCurrent) {
const uint64_t block_number = 1000;
MockHost host;
EXPECT_CALL(host, get_tx_context()) //
.Times(1)
.WillOnce(Return(evmc_tx_context{.block_number = block_number}));

RunInterpreterTest({
.code = {op::BLOCKHASH},
.state_after = RunState::kDone,
.gas_before = 40,
.gas_after = 20,
.stack_before = {block_number},
.stack_after = {0},
.host = &host,
});
}

TEST(InterpreterTest, BLOCKHASH_overflow) {
MockHost host;

RunInterpreterTest({
.code = {op::BLOCKHASH},
.state_after = RunState::kDone,
.gas_before = 40,
.gas_after = 20,
.stack_before = {uint256_t{0x0000000000000001, 0x0000000000000384}},
.stack_after = {0},
.host = &host,
});
}

TEST(InterpreterTest, BLOCKHASH_OutOfGas) {
RunInterpreterTest({
.code = {op::BLOCKHASH},
Expand Down
23 changes: 23 additions & 0 deletions regression_inputs/blockhash_#461.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"Status": "running",
"Revision": "Istanbul",
"ReadOnly": true,
"Pc": 8,
"Gas": 20,
"GasRefund": -227234023154315042,
"Code": "66750be9068df1f6408bbef5686da975769e56d9c234c26308561e54671ef3bf29a5c7dfa0be5587f58ba5cdae3ecb7423edccae610551c586da8a405f51a3a946ad926b095fd2626dc2bfb119899d3838b041a1ee2f52a00d71302f93562cc2",
"Stack": [
"4ae34574e9825110 de832ae81b410c8b dba36e64a329105c 32bb930fbfeafc82",
"0000000000000000 0000000000000000 0000000000000000 0000000000000004"
],
"BlockContext": {
"BaseFee": "ddb99751cdafe03b db1282bd243a8724 f8020d59eb04c225 74f9aaa2fbcd2aa8",
"BlockNumber": 0,
"ChainID": "1af9d83701ad0e63 4de99a69a7ccb803 4a5005c9bf10e0a7 af17726db99a2e08",
"CoinBase": "0xd774bd9070705b43cc0e869b651027f2e1d5a4a0",
"GasLimit": 452038407889421009,
"GasPrice": "7769b4568916bcdc 95f45a0b8e86a9cc 84a2c7aac56289ae 0929506dcb3ed222",
"Difficulty": "4712f1af585ea1d8 7f6e4125fbe56924 21ae13d6e2d673e2 f57beecfb640f15b",
"TimeStamp": 4864479995436506094
}
}

0 comments on commit 7051d20

Please sign in to comment.