mirror of https://github.com/ethereum/go-ethereum
cmd, core, eth, les, light: track deleted nodes (#25757)
* cmd, core, eth, les, light: track deleted nodes * trie: add docs * trie: address comments * cmd, core, eth, les, light, trie: trie id * trie: add tests * trie, core: updates * trie: fix imports * trie: add utility print-method for nodeset * trie: import err * trie: fix go vet warnings Co-authored-by: Martin Holst Swende <martin@swende.se>pull/25743/head
parent
fc3e6d0162
commit
bff84a99fe
@ -0,0 +1,55 @@ |
||||
// Copyright 2022 The go-ethereum Authors
|
||||
// This file is part of the go-ethereum library.
|
||||
//
|
||||
// The go-ethereum library is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// The go-ethereum library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>
|
||||
|
||||
package trie |
||||
|
||||
import "github.com/ethereum/go-ethereum/common" |
||||
|
||||
// ID is the identifier for uniquely identifying a trie.
|
||||
type ID struct { |
||||
StateRoot common.Hash // The root of the corresponding state(block.root)
|
||||
Owner common.Hash // The contract address hash which the trie belongs to
|
||||
Root common.Hash // The root hash of trie
|
||||
} |
||||
|
||||
// StateTrieID constructs an identifier for state trie with the provided state root.
|
||||
func StateTrieID(root common.Hash) *ID { |
||||
return &ID{ |
||||
StateRoot: root, |
||||
Owner: common.Hash{}, |
||||
Root: root, |
||||
} |
||||
} |
||||
|
||||
// StorageTrieID constructs an identifier for storage trie which belongs to a certain
|
||||
// state and contract specified by the stateRoot and owner.
|
||||
func StorageTrieID(stateRoot common.Hash, owner common.Hash, root common.Hash) *ID { |
||||
return &ID{ |
||||
StateRoot: stateRoot, |
||||
Owner: owner, |
||||
Root: root, |
||||
} |
||||
} |
||||
|
||||
// TrieID constructs an identifier for a standard trie(not a second-layer trie)
|
||||
// with provided root. It's mostly used in tests and some other tries like CHT trie.
|
||||
func TrieID(root common.Hash) *ID { |
||||
return &ID{ |
||||
StateRoot: root, |
||||
Owner: common.Hash{}, |
||||
Root: root, |
||||
} |
||||
} |
@ -0,0 +1,106 @@ |
||||
// Copyright 2022 The go-ethereum Authors
|
||||
// This file is part of the go-ethereum library.
|
||||
//
|
||||
// The go-ethereum library is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// The go-ethereum library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package trie |
||||
|
||||
import ( |
||||
"fmt" |
||||
|
||||
"github.com/ethereum/go-ethereum/common" |
||||
) |
||||
|
||||
// Reader wraps the Node and NodeBlob method of a backing trie store.
|
||||
type Reader interface { |
||||
// Node retrieves the trie node with the provided trie identifier, hexary
|
||||
// node path and the corresponding node hash.
|
||||
// No error will be returned if the node is not found.
|
||||
Node(owner common.Hash, path []byte, hash common.Hash) (node, error) |
||||
|
||||
// NodeBlob retrieves the RLP-encoded trie node blob with the provided trie
|
||||
// identifier, hexary node path and the corresponding node hash.
|
||||
// No error will be returned if the node is not found.
|
||||
NodeBlob(owner common.Hash, path []byte, hash common.Hash) ([]byte, error) |
||||
} |
||||
|
||||
// NodeReader wraps all the necessary functions for accessing trie node.
|
||||
type NodeReader interface { |
||||
// GetReader returns a reader for accessing all trie nodes with provided
|
||||
// state root. Nil is returned in case the state is not available.
|
||||
GetReader(root common.Hash) Reader |
||||
} |
||||
|
||||
// trieReader is a wrapper of the underlying node reader. It's not safe
|
||||
// for concurrent usage.
|
||||
type trieReader struct { |
||||
owner common.Hash |
||||
reader Reader |
||||
banned map[string]struct{} // Marker to prevent node from being accessed, for tests
|
||||
} |
||||
|
||||
// newTrieReader initializes the trie reader with the given node reader.
|
||||
func newTrieReader(stateRoot, owner common.Hash, db NodeReader) (*trieReader, error) { |
||||
reader := db.GetReader(stateRoot) |
||||
if reader == nil { |
||||
return nil, fmt.Errorf("state not found #%x", stateRoot) |
||||
} |
||||
return &trieReader{owner: owner, reader: reader}, nil |
||||
} |
||||
|
||||
// newEmptyReader initializes the pure in-memory reader. All read operations
|
||||
// should be forbidden and returns the MissingNodeError.
|
||||
func newEmptyReader() *trieReader { |
||||
return &trieReader{} |
||||
} |
||||
|
||||
// node retrieves the trie node with the provided trie node information.
|
||||
// An MissingNodeError will be returned in case the node is not found or
|
||||
// any error is encountered.
|
||||
func (r *trieReader) node(path []byte, hash common.Hash) (node, error) { |
||||
// Perform the logics in tests for preventing trie node access.
|
||||
if r.banned != nil { |
||||
if _, ok := r.banned[string(path)]; ok { |
||||
return nil, &MissingNodeError{Owner: r.owner, NodeHash: hash, Path: path} |
||||
} |
||||
} |
||||
if r.reader == nil { |
||||
return nil, &MissingNodeError{Owner: r.owner, NodeHash: hash, Path: path} |
||||
} |
||||
node, err := r.reader.Node(r.owner, path, hash) |
||||
if err != nil || node == nil { |
||||
return nil, &MissingNodeError{Owner: r.owner, NodeHash: hash, Path: path, err: err} |
||||
} |
||||
return node, nil |
||||
} |
||||
|
||||
// node retrieves the rlp-encoded trie node with the provided trie node
|
||||
// information. An MissingNodeError will be returned in case the node is
|
||||
// not found or any error is encountered.
|
||||
func (r *trieReader) nodeBlob(path []byte, hash common.Hash) ([]byte, error) { |
||||
// Perform the logics in tests for preventing trie node access.
|
||||
if r.banned != nil { |
||||
if _, ok := r.banned[string(path)]; ok { |
||||
return nil, &MissingNodeError{Owner: r.owner, NodeHash: hash, Path: path} |
||||
} |
||||
} |
||||
if r.reader == nil { |
||||
return nil, &MissingNodeError{Owner: r.owner, NodeHash: hash, Path: path} |
||||
} |
||||
blob, err := r.reader.NodeBlob(r.owner, path, hash) |
||||
if err != nil || len(blob) == 0 { |
||||
return nil, &MissingNodeError{Owner: r.owner, NodeHash: hash, Path: path, err: err} |
||||
} |
||||
return blob, nil |
||||
} |
Loading…
Reference in new issue