mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-20 10:52:25 +00:00
more
This commit is contained in:
parent
100d2e34e1
commit
d6d48f3713
8 changed files with 31 additions and 99 deletions
|
|
@ -38,7 +38,6 @@ var (
|
|||
type triePrefetcher struct {
|
||||
db Database // Database to fetch trie nodes through
|
||||
root common.Hash // Root hash of the account trie for metrics
|
||||
fetches map[string]Trie // Partially or fully fetched tries. Only populated for inactive copies.
|
||||
fetchers map[string]*subfetcher // Subfetchers for each trie
|
||||
|
||||
deliveryMissMeter metrics.Meter
|
||||
|
|
@ -71,16 +70,14 @@ func newTriePrefetcher(db Database, root common.Hash, namespace string) *triePre
|
|||
}
|
||||
return p
|
||||
}
|
||||
func (p *triePrefetcher) wait() {
|
||||
for _, fetcher := range p.fetchers {
|
||||
fetcher.wait()
|
||||
}
|
||||
}
|
||||
|
||||
// close iterates over all the subfetchers, aborts any that were left spinning
|
||||
// and reports the stats to the metrics subsystem.
|
||||
// close iterates over all the subfetchers, waits on any that were left spinning
|
||||
// and reports the stats to the metrics subsystem. close should not be called
|
||||
// more than once on a triePrefetcher instance.
|
||||
func (p *triePrefetcher) close() {
|
||||
for _, fetcher := range p.fetchers {
|
||||
fetcher.wait() // safe to do multiple times
|
||||
|
||||
if metrics.Enabled {
|
||||
if fetcher.root == p.root {
|
||||
p.accountLoadMeter.Mark(int64(len(fetcher.seen)))
|
||||
|
|
@ -103,34 +100,10 @@ func (p *triePrefetcher) close() {
|
|||
}
|
||||
}
|
||||
}
|
||||
// Clear out all fetchers (will crash on a second call, deliberate)
|
||||
p.fetchers = nil
|
||||
}
|
||||
|
||||
// copy creates a deep-but-inactive copy of the trie prefetcher. Any trie data
|
||||
// already loaded will be copied over, but no goroutines will be started. This
|
||||
// is mostly used in the miner which creates a copy of it's actively mutated
|
||||
// state to be sealed while it may further mutate the state.
|
||||
func (p *triePrefetcher) copy() *triePrefetcher {
|
||||
copy := &triePrefetcher{
|
||||
db: p.db,
|
||||
root: p.root,
|
||||
fetches: make(map[string]Trie), // Active prefetchers use the fetches map
|
||||
|
||||
deliveryMissMeter: p.deliveryMissMeter,
|
||||
accountLoadMeter: p.accountLoadMeter,
|
||||
accountDupMeter: p.accountDupMeter,
|
||||
accountSkipMeter: p.accountSkipMeter,
|
||||
accountWasteMeter: p.accountWasteMeter,
|
||||
storageLoadMeter: p.storageLoadMeter,
|
||||
storageDupMeter: p.storageDupMeter,
|
||||
storageSkipMeter: p.storageSkipMeter,
|
||||
storageWasteMeter: p.storageWasteMeter,
|
||||
}
|
||||
return copy
|
||||
}
|
||||
|
||||
// prefetch schedules a batch of trie items to prefetch.
|
||||
//
|
||||
// prefetch is called from two locations:
|
||||
// 1. Finalize of the state-objects storage roots. This happens at the end
|
||||
// of every transaction, meaning that if several transactions touches
|
||||
|
|
@ -138,12 +111,6 @@ func (p *triePrefetcher) copy() *triePrefetcher {
|
|||
// repeated.
|
||||
// 2. Finalize of the main account trie. This happens only once per block.
|
||||
func (p *triePrefetcher) prefetch(owner common.Hash, root common.Hash, addr common.Address, keys [][]byte) {
|
||||
// If the prefetcher is an inactive one, bail out
|
||||
if p.fetches != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Active fetcher, schedule the retrievals
|
||||
id := p.trieID(owner, root)
|
||||
fetcher := p.fetchers[id]
|
||||
if fetcher == nil {
|
||||
|
|
@ -156,18 +123,8 @@ func (p *triePrefetcher) prefetch(owner common.Hash, root common.Hash, addr comm
|
|||
// trie returns the trie matching the root hash, or nil if the prefetcher doesn't
|
||||
// have it.
|
||||
func (p *triePrefetcher) trie(owner common.Hash, root common.Hash) Trie {
|
||||
// If the prefetcher is inactive, return from existing deep copies
|
||||
id := p.trieID(owner, root)
|
||||
if p.fetches != nil {
|
||||
trie := p.fetches[id]
|
||||
if trie == nil {
|
||||
p.deliveryMissMeter.Mark(1)
|
||||
return nil
|
||||
}
|
||||
return p.db.CopyTrie(trie)
|
||||
}
|
||||
// Otherwise the prefetcher is active, bail if no trie was prefetched for this root
|
||||
fetcher := p.fetchers[id]
|
||||
// Bail if no trie was prefetched for this root
|
||||
fetcher := p.fetchers[p.trieID(owner, root)]
|
||||
if fetcher == nil {
|
||||
p.deliveryMissMeter.Mark(1)
|
||||
return nil
|
||||
|
|
|
|||
|
|
@ -319,18 +319,6 @@ func (b *Block) DecodeRLP(s *rlp.Stream) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// EncodeRLPWithZeroRoot encodes a block (with header state root set to 0x00...0) to RLP
|
||||
func (b *Block) EncodeRLPWithZeroRoot(w io.Writer) error {
|
||||
old := b.header.Root
|
||||
b.header.Root = common.Hash{}
|
||||
err := b.EncodeRLP(w)
|
||||
b.header.Root = old
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// EncodeRLP serializes a block as RLP.
|
||||
func (b *Block) EncodeRLP(w io.Writer) error {
|
||||
return rlp.Encode(w, &extblock{
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ import (
|
|||
"github.com/ethereum/go-ethereum/crypto"
|
||||
"github.com/ethereum/go-ethereum/params"
|
||||
"github.com/holiman/uint256"
|
||||
"math"
|
||||
)
|
||||
|
||||
func opAdd(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
|
|
@ -365,7 +366,7 @@ func opCodeCopy(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([
|
|||
)
|
||||
uint64CodeOffset, overflow := codeOffset.Uint64WithOverflow()
|
||||
if overflow {
|
||||
uint64CodeOffset = 0xffffffffffffffff
|
||||
uint64CodeOffset = math.MaxUint64
|
||||
}
|
||||
codeCopy := getData(scope.Contract.Code, uint64CodeOffset, length.Uint64())
|
||||
scope.Memory.Set(memOffset.Uint64(), length.Uint64(), codeCopy)
|
||||
|
|
@ -383,7 +384,7 @@ func opExtCodeCopy(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext)
|
|||
)
|
||||
uint64CodeOffset, overflow := codeOffset.Uint64WithOverflow()
|
||||
if overflow {
|
||||
uint64CodeOffset = 0xffffffffffffffff
|
||||
uint64CodeOffset = math.MaxUint64
|
||||
}
|
||||
addr := common.Address(a.Bytes20())
|
||||
if witness := interpreter.evm.StateDB.Witness(); witness != nil {
|
||||
|
|
@ -428,8 +429,8 @@ func opExtCodeHash(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext)
|
|||
if interpreter.evm.StateDB.Empty(address) {
|
||||
slot.Clear()
|
||||
} else {
|
||||
_ = interpreter.evm.StateDB.GetCode(address) // ensure the account leaf is fetched and included in the witness
|
||||
if witness := interpreter.evm.StateDB.Witness(); witness != nil {
|
||||
_ = interpreter.evm.StateDB.GetCode(address) // ensure the account leaf is fetched and included in the witness
|
||||
witness.AddCodeHash(interpreter.evm.StateDB.GetCodeHash(address))
|
||||
}
|
||||
slot.SetBytes(interpreter.evm.StateDB.GetCodeHash(address).Bytes())
|
||||
|
|
|
|||
|
|
@ -20,8 +20,6 @@ import (
|
|||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/ethereum/go-ethereum/eth/tracers/logger"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/ethereum/go-ethereum/core"
|
||||
|
|
@ -449,7 +447,9 @@ func (api *DebugAPI) GetTrieFlushInterval() (string, error) {
|
|||
return api.eth.blockchain.GetTrieFlushInterval().String(), nil
|
||||
}
|
||||
|
||||
func BuildProof(number uint64, bc *core.BlockChain) ([]byte, error) {
|
||||
// BuildStatelessProof executes a block, collecting the accessed pre-state into
|
||||
// a Witness. The RLP-encoded witness is returned.
|
||||
func BuildStatelessProof(number uint64, bc *core.BlockChain) ([]byte, error) {
|
||||
if number == 0 {
|
||||
panic("cannot build genesis block proof")
|
||||
}
|
||||
|
|
@ -459,19 +459,8 @@ func BuildProof(number uint64, bc *core.BlockChain) ([]byte, error) {
|
|||
return nil, err
|
||||
}
|
||||
db.EnableWitnessRecording()
|
||||
db.StartPrefetcher("apidebug")
|
||||
db.StartPrefetcher("debug_buildStatelessProof")
|
||||
block := bc.GetBlockByNumber(number)
|
||||
|
||||
logconfig := &logger.Config{
|
||||
EnableMemory: false,
|
||||
DisableStack: false,
|
||||
DisableStorage: false,
|
||||
EnableReturnData: true,
|
||||
Debug: true,
|
||||
}
|
||||
tracer := logger.NewJSONLogger(logconfig, os.Stdout)
|
||||
_ = tracer
|
||||
|
||||
stateProcessor := core.NewStateProcessor(bc.Config(), bc, bc.Engine())
|
||||
_, _, _, err = stateProcessor.Process(block, db, vm.Config{})
|
||||
if err != nil {
|
||||
|
|
@ -489,6 +478,8 @@ func BuildProof(number uint64, bc *core.BlockChain) ([]byte, error) {
|
|||
return enc, nil
|
||||
}
|
||||
|
||||
func (api *DebugAPI) BuildProof(num rpc.BlockNumber) ([]byte, error) {
|
||||
return BuildProof(uint64(num), api.eth.blockchain)
|
||||
// BuildStatelessProof executes a block, collecting the accessed pre-state into
|
||||
// a Witness. The RLP-encoded witness is returned.
|
||||
func (api *DebugAPI) BuildStatelessProof(num rpc.BlockNumber) ([]byte, error) {
|
||||
return BuildStatelessProof(uint64(num), api.eth.blockchain)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -502,8 +502,8 @@ web3._extend({
|
|||
params: 0
|
||||
}),
|
||||
new web3._extend.Method({
|
||||
name: 'buildProof',
|
||||
call: 'debug_buildProof',
|
||||
name: 'buildStatelessProof',
|
||||
call: 'debug_buildStatelessProof',
|
||||
params: 1
|
||||
}),
|
||||
],
|
||||
|
|
|
|||
|
|
@ -59,8 +59,8 @@ func (t *BlockTest) UnmarshalJSON(in []byte) error {
|
|||
type btJSON struct {
|
||||
Blocks []btBlock `json:"blocks"`
|
||||
Genesis btHeader `json:"genesisBlockHeader"`
|
||||
Pre core.GenesisAlloc `json:"pre"`
|
||||
Post core.GenesisAlloc `json:"postState"`
|
||||
Pre types.GenesisAlloc `json:"pre"`
|
||||
Post types.GenesisAlloc `json:"postState"`
|
||||
BestBlock common.UnprefixedHash `json:"lastblockhash"`
|
||||
Network string `json:"network"`
|
||||
SealEngine string `json:"sealEngine"`
|
||||
|
|
@ -155,7 +155,7 @@ func (t *BlockTest) run(stateless bool, snapshotter bool, scheme string, tracer
|
|||
// Wrap the original engine within the beacon-engine
|
||||
engine := beacon.New(ethash.NewFaker())
|
||||
|
||||
cache := &core.CacheConfig{TrieCleanLimit: 0, StateScheme: scheme, Preimages: true, TrieDirtyDisabled: true}
|
||||
cache := &core.CacheConfig{TrieCleanLimit: 0, StateScheme: scheme, Preimages: true}
|
||||
if snapshotter {
|
||||
cache.SnapshotLimit = 1
|
||||
cache.SnapshotWait = true
|
||||
|
|
@ -197,7 +197,7 @@ func (t *BlockTest) run(stateless bool, snapshotter bool, scheme string, tracer
|
|||
|
||||
if stateless {
|
||||
for _, blk := range validBlocks {
|
||||
proof, err := eth.BuildProof(blk.BlockHeader.Number.Uint64(), chain)
|
||||
proof, err := eth.BuildStatelessProof(blk.BlockHeader.Number.Uint64(), chain)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to build proof: %v", err)
|
||||
}
|
||||
|
|
|
|||
10
trie/trie.go
10
trie/trie.go
|
|
@ -107,7 +107,7 @@ func NewEmpty(db database.Database) *Trie {
|
|||
}
|
||||
|
||||
// MustNodeIterator is a wrapper of NodeIterator and will omit any encountered
|
||||
// error but just printg out an error message.
|
||||
// error but just print out an error message.
|
||||
func (t *Trie) MustNodeIterator(start []byte) NodeIterator {
|
||||
it, err := t.NodeIterator(start)
|
||||
if err != nil {
|
||||
|
|
@ -581,10 +581,6 @@ func (t *Trie) resolve(n node, prefix []byte) (node, error) {
|
|||
return n, nil
|
||||
}
|
||||
|
||||
// TODO: for resolveAndTrack, differentiate between hash node resolve failure in stateless
|
||||
// vs normal execution. In normal mode, it represents an error with database
|
||||
// consistency. In stateless execution, it means that the witness is incomplete.
|
||||
|
||||
// resolveAndTrack loads node from the underlying store with the given node hash
|
||||
// and path prefix and also tracks the loaded node blob in tracer treated as the
|
||||
// node's original value. The rlp-encoded blob is preferred to be loaded from
|
||||
|
|
@ -606,10 +602,14 @@ func (t *Trie) Hash() common.Hash {
|
|||
return common.BytesToHash(hash.(hashNode))
|
||||
}
|
||||
|
||||
// AccessList returns a map of path->blob containing all trie nodes that have
|
||||
// been accessed.
|
||||
func (t *Trie) AccessList() map[string][]byte {
|
||||
return t.tracer.accessList
|
||||
}
|
||||
|
||||
// CommitAndObtainAccessList does the same thing as Commit, but also returns
|
||||
// the access list of the trie.
|
||||
func (t *Trie) CommitAndObtainAccessList(collectLeaf bool) (common.Hash, *trienode.NodeSet, map[string][]byte, error) {
|
||||
accessList := t.tracer.accessList
|
||||
// Commit will reset the tracer accessList, so after this
|
||||
|
|
|
|||
|
|
@ -45,11 +45,6 @@ var HashDefaults = &Config{
|
|||
HashDB: hashdb.Defaults,
|
||||
}
|
||||
|
||||
var PathDefaults = &Config{
|
||||
Preimages: false,
|
||||
PathDB: pathdb.Defaults,
|
||||
}
|
||||
|
||||
// backend defines the methods needed to access/update trie nodes in different
|
||||
// state scheme.
|
||||
type backend interface {
|
||||
|
|
|
|||
Loading…
Reference in a new issue