mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-20 10:52:25 +00:00
core/evm: less iteration in blockhash
This commit is contained in:
parent
4df46d86d6
commit
8d05c598fd
3 changed files with 25 additions and 23 deletions
36
core/evm.go
36
core/evm.go
|
|
@ -60,24 +60,32 @@ func NewEVMContext(msg Message, header *types.Header, chain ChainContext, author
|
||||||
|
|
||||||
// GetHashFn returns a GetHashFunc which retrieves header hashes by number
|
// GetHashFn returns a GetHashFunc which retrieves header hashes by number
|
||||||
func GetHashFn(ref *types.Header, chain ChainContext) func(n uint64) common.Hash {
|
func GetHashFn(ref *types.Header, chain ChainContext) func(n uint64) common.Hash {
|
||||||
var cache map[uint64]common.Hash
|
// Cache will initially contain [refHash.parent],
|
||||||
|
// Then fill up with [refHash.p, refHash.pp, refHash.ppp, ...]
|
||||||
|
var cache []common.Hash
|
||||||
|
|
||||||
return func(n uint64) common.Hash {
|
return func(n uint64) common.Hash {
|
||||||
// If there's no hash cache yet, make one
|
// If there's no hash cache yet, make one
|
||||||
if cache == nil {
|
if len(cache) == 0 {
|
||||||
cache = map[uint64]common.Hash{
|
cache = append(cache, ref.ParentHash)
|
||||||
ref.Number.Uint64() - 1: ref.ParentHash,
|
}
|
||||||
|
if idx := ref.Number.Uint64() - n - 1; idx < uint64(len(cache)) {
|
||||||
|
return cache[idx]
|
||||||
|
}
|
||||||
|
// No luck in the cache, but we can start iterating from the last element we already know
|
||||||
|
lastKnownHash := cache[len(cache)-1]
|
||||||
|
lastKnownNumber := ref.Number.Uint64() - uint64(len(cache))
|
||||||
|
|
||||||
|
for {
|
||||||
|
header := chain.GetHeader(lastKnownHash, lastKnownNumber)
|
||||||
|
if header == nil {
|
||||||
|
break
|
||||||
}
|
}
|
||||||
}
|
cache = append(cache, header.ParentHash)
|
||||||
// Try to fulfill the request from the cache
|
lastKnownHash = header.ParentHash
|
||||||
if hash, ok := cache[n]; ok {
|
lastKnownNumber = header.Number.Uint64() - 1
|
||||||
return hash
|
if n == lastKnownNumber {
|
||||||
}
|
return lastKnownHash
|
||||||
// Not cached, iterate the blocks and cache the hashes
|
|
||||||
for header := chain.GetHeader(ref.ParentHash, ref.Number.Uint64()-1); header != nil; header = chain.GetHeader(header.ParentHash, header.Number.Uint64()-1) {
|
|
||||||
cache[header.Number.Uint64()-1] = header.ParentHash
|
|
||||||
if n == header.Number.Uint64()-1 {
|
|
||||||
return header.ParentHash
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return common.Hash{}
|
return common.Hash{}
|
||||||
|
|
|
||||||
|
|
@ -17,21 +17,15 @@
|
||||||
package runtime
|
package runtime
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/ethereum/go-ethereum/common"
|
|
||||||
"github.com/ethereum/go-ethereum/core"
|
"github.com/ethereum/go-ethereum/core"
|
||||||
"github.com/ethereum/go-ethereum/core/vm"
|
"github.com/ethereum/go-ethereum/core/vm"
|
||||||
)
|
)
|
||||||
|
|
||||||
func NewEnv(cfg *Config) *vm.EVM {
|
func NewEnv(cfg *Config) *vm.EVM {
|
||||||
getHash := cfg.GetHashFn
|
|
||||||
if getHash == nil {
|
|
||||||
getHash = func(uint64) common.Hash { return common.Hash{} }
|
|
||||||
}
|
|
||||||
|
|
||||||
context := vm.Context{
|
context := vm.Context{
|
||||||
CanTransfer: core.CanTransfer,
|
CanTransfer: core.CanTransfer,
|
||||||
Transfer: core.Transfer,
|
Transfer: core.Transfer,
|
||||||
GetHash: getHash,
|
GetHash: cfg.GetHashFn,
|
||||||
Origin: cfg.Origin,
|
Origin: cfg.Origin,
|
||||||
Coinbase: cfg.Coinbase,
|
Coinbase: cfg.Coinbase,
|
||||||
BlockNumber: cfg.BlockNumber,
|
BlockNumber: cfg.BlockNumber,
|
||||||
|
|
|
||||||
|
|
@ -312,7 +312,7 @@ func TestBlockhash(t *testing.T) {
|
||||||
if last.Uint64() != 744 {
|
if last.Uint64() != 744 {
|
||||||
t.Fatalf("last block should be 744, got %d (%x)", last, ret[64:96])
|
t.Fatalf("last block should be 744, got %d (%x)", last, ret[64:96])
|
||||||
}
|
}
|
||||||
if chain.counter != 255 {
|
if exp, got := 255, chain.counter; exp != got {
|
||||||
t.Logf("Suboptimal; too much chain iteration, expected 255, got %d", chain.counter)
|
t.Errorf("suboptimal; too much chain iteration, expected %d, got %d", exp, got)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue