goevmlab icon indicating copy to clipboard operation
goevmlab copied to clipboard

Blockhash difference in state tests

Open MariusVanDerWijden opened this issue 4 years ago • 5 comments

So basically Geth, Besu and OE all return 0x0 on BLOCKHASH(0x831fc01b15af74fc30c) while Nethermind returns Keccak(0x831fc01b15af74fc30c).

Netherminds Blockhash provider: https://github.com/NethermindEth/nethermind/blob/master/src/Nethermind/Nethermind.Evm.Test/TestBlockhashProvider.cs https://github.com/NethermindEth/nethermind/blob/master/src/Nethermind/Ethereum.Test.Base/TestBlockhashProvider.cs

The state test documentation also states that " Since the data of the blockchain is not given, the opcode BLOCKHASH could not return the hashes of the corresponding blocks. Therefore we define the hash of block number n to be SHA256("n")." https://www.ethdocs.org/en/latest/contracts-and-transactions/ethereum-tests/state_tests/index.html (first paragraph)

Geth replaces the function correctly in state tests (https://github.com/ethereum/go-ethereum/blob/71c37d82adaa2b69ea98ce0c5505489d6b711c1e/tests/vm_test_util.go#L157) but I think it is not patched in the evm binary.

Test ``` { "nethermind-caller": { "env": { "currentCoinbase": "b94f5374fce5edbc8e2a8697c15331677e6ebf0b", "currentDifficulty": "0x20000", "currentGasLimit": "0x26e1f476fe1e22", "currentNumber": "0x1", "currentTimestamp": "0x3e8", "previousHash": "0x0000000000000000000000000000000000000000000000000000000000000000" }, "pre": { "0x00000000000000000000000000000000000000aa": { "code": "0x6000600060006000600060bb612d28f1", "storage": {}, "balance": "0x5", "nonce": "0x0" }, "0x00000000000000000000000000000000000000bb": { "code": "0x690831fc01b15af74fc30c40805260006000f3", "storage": {}, "balance": "0x5", "nonce": "0x0" }, "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b": { "code": "0x", "storage": {}, "balance": "0xffffffff", "nonce": "0x0" } }, "transaction": { "gasPrice": "0x1", "nonce": "0x0", "to": "0x00000000000000000000000000000000000000AA", "data": [ "0x" ], "gasLimit": [ "0x7a1200" ], "value": [ "0x01" ], "secretKey": "0x45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8" }, "out": "0x", "post": { "Istanbul": [ { "hash": "0000000000000000000000000000000000000000000000000000000000000000", "logs": "0000000000000000000000000000000000000000000000000000000000000000", "indexes": { "data": 0, "gas": 0, "value": 0 } } ] } } } ```
Geth output Geth:
~/go/src/github.com/ethereum/go-ethereum/build/bin/evm --json --nomemory statetest test.json
{"pc":0,"op":96,"gas":"0x79bff8","gasCost":"0x3","memory":"0x","memSize":0,"stack":[],"returnStack":[],"returnData":null,"depth":1,"refund":0,"opName":"PUSH1","error":""}
{"pc":2,"op":96,"gas":"0x79bff5","gasCost":"0x3","memory":"0x","memSize":0,"stack":["0x0"],"returnStack":[],"returnData":null,"depth":1,"refund":0,"opName":"PUSH1","error":""}
{"pc":4,"op":96,"gas":"0x79bff2","gasCost":"0x3","memory":"0x","memSize":0,"stack":["0x0","0x0"],"returnStack":[],"returnData":null,"depth":1,"refund":0,"opName":"PUSH1","error":""}
{"pc":6,"op":96,"gas":"0x79bfef","gasCost":"0x3","memory":"0x","memSize":0,"stack":["0x0","0x0","0x0"],"returnStack":[],"returnData":null,"depth":1,"refund":0,"opName":"PUSH1","error":""}
{"pc":8,"op":96,"gas":"0x79bfec","gasCost":"0x3","memory":"0x","memSize":0,"stack":["0x0","0x0","0x0","0x0"],"returnStack":[],"returnData":null,"depth":1,"refund":0,"opName":"PUSH1","error":""}
{"pc":10,"op":96,"gas":"0x79bfe9","gasCost":"0x3","memory":"0x","memSize":0,"stack":["0x0","0x0","0x0","0x0","0x0"],"returnStack":[],"returnData":null,"depth":1,"refund":0,"opName":"PUSH1","error":""}
{"pc":12,"op":97,"gas":"0x79bfe6","gasCost":"0x3","memory":"0x","memSize":0,"stack":["0x0","0x0","0x0","0x0","0x0","0xbb"],"returnStack":[],"returnData":null,"depth":1,"refund":0,"opName":"PUSH2","error":""}
{"pc":15,"op":241,"gas":"0x79bfe3","gasCost":"0x2fe4","memory":"0x","memSize":0,"stack":["0x0","0x0","0x0","0x0","0x0","0xbb","0x2d28"],"returnStack":[],"returnData":null,"depth":1,"refund":0,"opName":"CALL","error":""}
{"pc":0,"op":105,"gas":"0x2d28","gasCost":"0x3","memory":"0x","memSize":0,"stack":[],"returnStack":[],"returnData":null,"depth":2,"refund":0,"opName":"PUSH10","error":""}
{"pc":11,"op":64,"gas":"0x2d25","gasCost":"0x14","memory":"0x","memSize":0,"stack":["0x831fc01b15af74fc30c"],"returnStack":[],"returnData":null,"depth":2,"refund":0,"opName":"BLOCKHASH","error":""}
{"pc":12,"op":128,"gas":"0x2d11","gasCost":"0x3","memory":"0x","memSize":0,"stack":["0x0"],"returnStack":[],"returnData":null,"depth":2,"refund":0,"opName":"DUP1","error":""}
{"pc":13,"op":82,"gas":"0x2d0e","gasCost":"0x6","memory":"0x","memSize":32,"stack":["0x0","0x0"],"returnStack":[],"returnData":null,"depth":2,"refund":0,"opName":"MSTORE","error":""}
{"pc":14,"op":96,"gas":"0x2d08","gasCost":"0x3","memory":"0x","memSize":32,"stack":[],"returnStack":[],"returnData":null,"depth":2,"refund":0,"opName":"PUSH1","error":""}
{"pc":16,"op":96,"gas":"0x2d05","gasCost":"0x3","memory":"0x","memSize":32,"stack":["0x0"],"returnStack":[],"returnData":null,"depth":2,"refund":0,"opName":"PUSH1","error":""}
{"pc":18,"op":243,"gas":"0x2d02","gasCost":"0x0","memory":"0x","memSize":32,"stack":["0x0","0x0"],"returnStack":[],"returnData":null,"depth":2,"refund":0,"opName":"RETURN","error":""}
{"pc":16,"op":0,"gas":"0x79bd01","gasCost":"0x0","memory":"0x","memSize":0,"stack":["0x1"],"returnStack":[],"returnData":null,"depth":1,"refund":0,"opName":"STOP","error":""}
{"output":"","gasUsed":"0x2f7","time":234049}
{"stateRoot": "aeadb62508a708210e49bbde6840e63ea913fa65b566dd7fc3bf26157a5ee44f"}
[
  {
    "name": "nethermind-caller",
    "pass": false,
    "fork": "Istanbul",
    "error": "post state root mismatch: got aeadb62508a708210e49bbde6840e63ea913fa65b566dd7fc3bf26157a5ee44f, want 0000000000000000000000000000000000000000000000000000000000000000"
  }
]
Nethermind output Nethermind:
~/ethereum/nethermind/nethtest -i test.json
{"pc":0,"op":96,"gas":"0x79bff8","gasCost":"0x3","memory":"0x","memSize":0,"stack":[],"depth":1,"refund":0,"opname":"PUSH1","error":""}
{"pc":2,"op":96,"gas":"0x79bff5","gasCost":"0x3","memory":"0x","memSize":0,"stack":["0x0"],"depth":1,"refund":0,"opname":"PUSH1","error":""}
{"pc":4,"op":96,"gas":"0x79bff2","gasCost":"0x3","memory":"0x","memSize":0,"stack":["0x0","0x0"],"depth":1,"refund":0,"opname":"PUSH1","error":""}
{"pc":6,"op":96,"gas":"0x79bfef","gasCost":"0x3","memory":"0x","memSize":0,"stack":["0x0","0x0","0x0"],"depth":1,"refund":0,"opname":"PUSH1","error":""}
{"pc":8,"op":96,"gas":"0x79bfec","gasCost":"0x3","memory":"0x","memSize":0,"stack":["0x0","0x0","0x0","0x0"],"depth":1,"refund":0,"opname":"PUSH1","error":""}
{"pc":10,"op":96,"gas":"0x79bfe9","gasCost":"0x3","memory":"0x","memSize":0,"stack":["0x0","0x0","0x0","0x0","0x0"],"depth":1,"refund":0,"opname":"PUSH1","error":""}
{"pc":12,"op":97,"gas":"0x79bfe6","gasCost":"0x3","memory":"0x","memSize":0,"stack":["0x0","0x0","0x0","0x0","0x0","0xbb"],"depth":1,"refund":0,"opname":"PUSH2","error":""}
{"pc":15,"op":241,"gas":"0x79bfe3","gasCost":"0x2fe4","memory":"0x","memSize":0,"stack":["0x0","0x0","0x0","0x0","0x0","0xbb","0x2d28"],"depth":1,"refund":0,"opname":"CALL","error":""}
{"pc":0,"op":105,"gas":"0x2d28","gasCost":"0x3","memory":"0x","memSize":0,"stack":[],"depth":2,"refund":0,"opname":"PUSH10","error":""}
{"pc":11,"op":64,"gas":"0x2d25","gasCost":"0x14","memory":"0x","memSize":0,"stack":["0x831fc01b15af74fc30c"],"depth":2,"refund":0,"opname":"BLOCKHASH","error":""}
{"pc":12,"op":128,"gas":"0x2d11","gasCost":"0x3","memory":"0x","memSize":0,"stack":["0xc23afaf993bef633220c94fba7cf577103b120a2701d597660dfbab0720a8ab4"],"depth":2,"refund":0,"opname":"DUP1","error":""}
{"pc":13,"op":82,"gas":"0x2d0e","gasCost":"0x2d0e","memory":"0x","memSize":0,"stack":["0xc23afaf993bef633220c94fba7cf577103b120a2701d597660dfbab0720a8ab4","0xc23afaf993bef633220c94fba7cf577103b120a2701d597660dfbab0720a8ab4"],"depth":2,"refund":0,"opname":"MSTORE","error":"gas uint64 overflow"}
{"output":"0x","gasUsed":"0x2ff9","time":3}
{"stateRoot":"0xde9086cdde32b9293313af622ef8553330f85a7a955a4e4a5a7413c25ccf1c19"}
[
  {
    "name": "nethermind-caller_d0g0v0",
    "pass": false,
    "fork": "Istanbul"
  }
]

MariusVanDerWijden avatar Sep 14 '20 15:09 MariusVanDerWijden

Geth replaces the function correctly in state tests (https://github.com/ethereum/go-ethereum/blob/71c37d82adaa2b69ea98ce0c5505489d6b711c1e/tests/vm_test_util.go#L157) but I think it is not patched in the evm binary.

Nope, that's not statetests, it's for VM-tests.

holiman avatar Sep 14 '20 16:09 holiman

But let's try to properly change it for statestests too, and see if the tests still pass

holiman avatar Sep 14 '20 16:09 holiman

{"pc":0,"op":96,"gas":"0x130daf8","gasCost":"0x3","memSize":0,"stack":[],"depth":1,"refund":0,"opName":"PUSH1"}
{"pc":2,"op":96,"gas":"0x130daf5","gasCost":"0x3","memSize":0,"stack":["0x0"],"depth":1,"refund":0,"opName":"PUSH1"}
{"pc":4,"op":64,"gas":"0x130daf2","gasCost":"0x14","memSize":0,"stack":["0x0","0x0"],"depth":1,"refund":0,"opName":"BLOCKHASH"}
Requested blockhash 0. Scope for blockhash: 0 - 1
vmTestBlockHash(0)
{"pc":5,"op":85,"gas":"0x130dade","gasCost":"0x320","memSize":0,"stack":["0x0","0x44852b2a670ade5407e78fb2863c51de9fcb96542a07186fe3aeda6bb8a116d"],"depth":1,"refund":0,"opName":"SSTORE"}
{"pc":6,"op":96,"gas":"0x130d7be","gasCost":"0x3","memSize":0,"stack":[],"depth":1,"refund":0,"opName":"PUSH1"}
{"pc":8,"op":96,"gas":"0x130d7bb","gasCost":"0x3","memSize":0,"stack":["0x10"],"depth":1,"refund":0,"opName":"PUSH1"}
{"pc":10,"op":64,"gas":"0x130d7b8","gasCost":"0x14","memSize":0,"stack":["0x10","0x1"],"depth":1,"refund":0,"opName":"BLOCKHASH"}
Requested blockhash 1. Scope for blockhash: 0 - 1

So what happens is:

  • geth executes the statetest on blocknumber 1. So if you request blockhash 0, it will return the SHA256...
  • However, if you request blockhash(1) , it will error in the same way as if you request blockhash 10M at block 10M. So after having looked into it a bit more, I'd say geth is correct.

holiman avatar Dec 05 '22 15:12 holiman

The example trace from this issue report:

{"pc":11,"op":64,"gas":"0x2d25","gasCost":"0x14","memory":"0x","memSize":0,"stack":["0x831fc01b15af74fc30c"],"returnStack":[],"returnData":null,"depth":2,"refund":0,"opName":"BLOCKHASH","error":""}
{"pc":12,"op":128,"gas":"0x2d11","gasCost":"0x3","memory":"0x","memSize":0,"stack":["0x0"],"returnStack":[],"returnData":null,"depth":2,"refund":0,"opName":"DUP1","error":""}
BLOCKHASH(0x831fc01b15af74fc30c) -> 0x0

That is, BLOCKHASH(38700981312745718661900) is only "defined" if BLOCKNUM is somewhere within a 256 large window of that number. Otherwise, the correct returnvalue is 0x0.

holiman avatar Dec 05 '22 15:12 holiman

Also relevant: https://github.com/NethermindEth/nethermind/issues/3201

holiman avatar Dec 05 '22 15:12 holiman