Fixes for account selective snapshot
This commit is contained in:
parent
9856419371
commit
e7db137011
@ -87,7 +87,7 @@ type SnapshotParams struct {
|
|||||||
func (s *Service) CreateSnapshot(params SnapshotParams) error {
|
func (s *Service) CreateSnapshot(params SnapshotParams) error {
|
||||||
paths := make([][]byte, 0, len(params.WatchedAddresses))
|
paths := make([][]byte, 0, len(params.WatchedAddresses))
|
||||||
for addr := range params.WatchedAddresses {
|
for addr := range params.WatchedAddresses {
|
||||||
paths = append(paths, crypto.Keccak256(addr.Bytes()))
|
paths = append(paths, keybytesToHex(crypto.Keccak256(addr.Bytes())))
|
||||||
}
|
}
|
||||||
s.watchingAddresses = len(paths) > 0
|
s.watchingAddresses = len(paths) > 0
|
||||||
// extract header from lvldb and publish to PG-IPFS
|
// extract header from lvldb and publish to PG-IPFS
|
||||||
@ -173,7 +173,7 @@ type nodeResult struct {
|
|||||||
elements []interface{}
|
elements []interface{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func resolveNode(it trie.NodeIterator, trieDB *trie.Database) (*nodeResult, error) {
|
func resolveNode(nodePath []byte, it trie.NodeIterator, trieDB *trie.Database) (*nodeResult, error) {
|
||||||
// "leaf" nodes are actually "value" nodes, whose parents are the actual leaves
|
// "leaf" nodes are actually "value" nodes, whose parents are the actual leaves
|
||||||
if it.Leaf() {
|
if it.Leaf() {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
@ -182,8 +182,8 @@ func resolveNode(it trie.NodeIterator, trieDB *trie.Database) (*nodeResult, erro
|
|||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
path := make([]byte, len(it.Path()))
|
path := make([]byte, len(nodePath))
|
||||||
copy(path, it.Path())
|
copy(path, nodePath)
|
||||||
n, err := trieDB.Node(it.Hash())
|
n, err := trieDB.Node(it.Hash())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -227,59 +227,91 @@ func (s *Service) createSnapshot(it trie.NodeIterator, headerID string, height *
|
|||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
// if path is nil
|
||||||
|
// (occurs before reaching state trie root)
|
||||||
|
// (when the iterator is created using tree.NodeIterator(nil))
|
||||||
|
// move on to next node (root)
|
||||||
|
if it.Path() == nil {
|
||||||
|
it.Next(true)
|
||||||
|
// process root node
|
||||||
|
// create snapshot of node, if it is a leaf this will also create snapshot of entire storage trie
|
||||||
|
if err := s.createNodeSnapshot(tx, it.Path(), it, headerID, height, seekingPaths); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// iterate all the nodes at this level
|
// iterate all the nodes at this level
|
||||||
for it.Next(false) {
|
// if iterator is at an empty path (in case of root node or just before subtrie root in case of some concurrent iterators),
|
||||||
|
// descend in the first loop iteration to reach first child node
|
||||||
|
var descend bool
|
||||||
|
if bytes.Equal(it.Path(), []byte{}) {
|
||||||
|
descend = true
|
||||||
|
}
|
||||||
|
for it.Next(descend) {
|
||||||
|
// to avoid descending further
|
||||||
|
descend = false
|
||||||
|
|
||||||
// ignore node if it is not along paths of interest
|
// ignore node if it is not along paths of interest
|
||||||
if s.watchingAddresses && !validPath(it.Path(), seekingPaths) {
|
if s.watchingAddresses && !validPath(it.Path(), seekingPaths) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// if the node is along paths of interest
|
// if the node is along paths of interest
|
||||||
// create snapshot of node, if it is a leaf this will also create snapshot of entire storage trie
|
// create snapshot of node, if it is a leaf this will also create snapshot of entire storage trie
|
||||||
if err := s.createNodeSnapshot(tx, it, headerID, height, seekingPaths); err != nil {
|
if err := s.createNodeSnapshot(tx, it.Path(), it, headerID, height, seekingPaths); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// traverse and process the next level of this subTrie
|
||||||
|
if err := s.createSubTrieSnapshot(tx, it.Path(), it.Hash(), headerID, height, seekingPaths); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return it.Error()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Service) createSubTrieSnapshot(tx Tx, prefixPath []byte, hash common.Hash, headerID string, height *big.Int, seekingPaths [][]byte) error {
|
||||||
// create subTrie iterator for this node
|
// create subTrie iterator for this node
|
||||||
subTrie, err := s.stateDB.OpenTrie(it.Hash())
|
subTrie, err := s.stateDB.OpenTrie(hash)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
subTrieIt := subTrie.NodeIterator(nil)
|
subTrieIt := subTrie.NodeIterator(nil)
|
||||||
// traverse and process the next level of this subTrie
|
// move on to the subtrie root node
|
||||||
if err := s.createSubTrieSnapshot(tx, subTrieIt, headerID, height, seekingPaths); err != nil {
|
// subtrie root node assumed to be already indexed at a higher level
|
||||||
return err
|
subTrieIt.Next(true)
|
||||||
}
|
|
||||||
}
|
|
||||||
return it.Error()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Service) createSubTrieSnapshot(tx Tx, it trie.NodeIterator, headerID string, height *big.Int, seekingPaths [][]byte) error {
|
// descend in the first loop iteration to reach first child node
|
||||||
// iterate all the nodes at this level
|
descend := true
|
||||||
for it.Next(false) {
|
for subTrieIt.Next(descend) {
|
||||||
|
// to avoid descending further
|
||||||
|
descend = false
|
||||||
|
|
||||||
|
// create the full node path as it.Path() doesn't include the path before subtrie root
|
||||||
|
nodePath := append(prefixPath, subTrieIt.Path()...)
|
||||||
// ignore node if it is not along paths of interest
|
// ignore node if it is not along paths of interest
|
||||||
if s.watchingAddresses && !validPath(it.Path(), seekingPaths) {
|
if s.watchingAddresses && !validPath(nodePath, seekingPaths) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// if the node is along paths of interest
|
// if the node is along paths of interest
|
||||||
// create snapshot of node, if it is a leaf this will also create snapshot of entire storage trie
|
// create snapshot of node, if it is a leaf this will also create snapshot of entire storage trie
|
||||||
if err := s.createNodeSnapshot(tx, it, headerID, height, seekingPaths); err != nil {
|
if err := s.createNodeSnapshot(tx, nodePath, subTrieIt, headerID, height, seekingPaths); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
// create subTrie iterator for this node
|
|
||||||
subTrie, err := s.stateDB.OpenTrie(it.Hash())
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
subTrieIt := subTrie.NodeIterator(nil)
|
|
||||||
// traverse and process the next level of this subTrie
|
// traverse and process the next level of this subTrie
|
||||||
if err := s.createSubTrieSnapshot(tx, subTrieIt, headerID, height, seekingPaths); err != nil {
|
if err := s.createSubTrieSnapshot(tx, nodePath, subTrieIt.Hash(), headerID, height, seekingPaths); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return it.Error()
|
|
||||||
|
return subTrieIt.Error()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Service) createNodeSnapshot(tx Tx, it trie.NodeIterator, headerID string, height *big.Int, seekingPaths [][]byte) error {
|
func (s *Service) createNodeSnapshot(tx Tx, path []byte, it trie.NodeIterator, headerID string, height *big.Int, seekingPaths [][]byte) error {
|
||||||
res, err := resolveNode(it, s.stateDB.TrieDB())
|
res, err := resolveNode(path, it, s.stateDB.TrieDB())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -380,7 +412,7 @@ func (s *Service) storageSnapshot(sr common.Hash, headerID string, height *big.I
|
|||||||
|
|
||||||
it := sTrie.NodeIterator(make([]byte, 0))
|
it := sTrie.NodeIterator(make([]byte, 0))
|
||||||
for it.Next(true) {
|
for it.Next(true) {
|
||||||
res, err := resolveNode(it, s.stateDB.TrieDB())
|
res, err := resolveNode(it.Path(), it, s.stateDB.TrieDB())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user