feat: return keccak(chainId || height) for BLOCKHASH opcode (#359)

* changed blockhash behavior

* added patch version

* Update core/vm/runtime/runtime_test.go

Co-authored-by: Péter Garamvölgyi <th307q@gmail.com>

* Update core/vm/runtime/runtime_test.go

Co-authored-by: Péter Garamvölgyi <th307q@gmail.com>

* lint fix

* changed wording

* used interpreter.hasher and padded chainId to uint64

* used interpreter.hasher and padded chainId to uint64

* undo changes

* bump version

---------

Co-authored-by: Péter Garamvölgyi <th307q@gmail.com>
Co-authored-by: Péter Garamvölgyi <peter@scroll.io>
This commit is contained in:
Richord 2023-06-14 13:11:31 -07:00 committed by GitHub
parent f055f50f9d
commit b5e8d12c06
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 29 additions and 8 deletions

View file

@ -17,6 +17,8 @@
package vm
import (
"encoding/binary"
"github.com/holiman/uint256"
"golang.org/x/crypto/sha3"
@ -440,13 +442,28 @@ func opBlockhash(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) (
}
var upper, lower uint64
upper = interpreter.evm.Context.BlockNumber.Uint64()
if upper < 2 {
if upper < 257 {
lower = 0
} else {
lower = upper - 1
lower = upper - 256
}
if num64 >= lower && num64 < upper {
num.SetBytes(interpreter.evm.Context.GetHash(num64).Bytes())
chainId := interpreter.evm.ChainConfig().ChainID
chainIdBuf := make([]byte, 8)
binary.BigEndian.PutUint64(chainIdBuf, chainId.Uint64())
num64Buf := make([]byte, 8)
binary.BigEndian.PutUint64(num64Buf, num64)
if interpreter.hasher == nil {
interpreter.hasher = sha3.NewLegacyKeccak256().(keccakState)
} else {
interpreter.hasher.Reset()
}
interpreter.hasher.Write(chainIdBuf)
interpreter.hasher.Write(num64Buf)
interpreter.hasher.Read(interpreter.hasherBuf[:])
num.SetBytes(interpreter.hasherBuf[:])
} else {
num.Clear()
}

View file

@ -334,11 +334,15 @@ func TestBlockhash(t *testing.T) {
if zero.BitLen() != 0 {
t.Fatalf("expected zeroes, got %x", ret[0:32])
}
if first.Uint64() != 999 {
t.Fatalf("second block should be 999, got %d (%x)", first, ret[32:64])
firstExpectedHash := new(big.Int)
firstExpectedHash.SetString("13215081625009140218242111988507489764601005198286886925088730931502473149599", 10)
if first.Uint64() != firstExpectedHash.Uint64() {
t.Fatalf("first hash should be 13215081625009140218242111988507489764601005198286886925088730931502473149599, got %d (%x)", first, ret[32:64])
}
if last.Uint64() != 0 {
t.Fatalf("last block should be 0, got %d (%x)", last, ret[64:96])
lastExpectedHash := new(big.Int)
lastExpectedHash.SetString("2851160567348483005169712516804956111111231427377973738952179767509712807467", 10)
if last.Uint64() != lastExpectedHash.Uint64() {
t.Fatalf("last hash should be 2851160567348483005169712516804956111111231427377973738952179767509712807467, got %d (%x)", last, ret[64:96])
}
if exp, got := 0, chain.counter; exp != got {
t.Errorf("suboptimal; too much chain iteration, expected %d, got %d", exp, got)

View file

@ -24,7 +24,7 @@ import (
const (
VersionMajor = 4 // Major version component of the current release
VersionMinor = 2 // Minor version component of the current release
VersionPatch = 0 // Patch version component of the current release
VersionPatch = 1 // Patch version component of the current release
VersionMeta = "sepolia" // Version metadata to append to the version string
)