network: request unknown MPT nodes
In this commit: 1. Request unknown MPT nodes from peers. Note, that StateSync module itself shouldn't be responsible for nodes requests, that's a server duty. 2. Do not request the same node twice, check if it is in storage already. If so, then the only thing remaining is to update refcounter.
This commit is contained in:
parent
6a04880b49
commit
3b7807e897
7 changed files with 203 additions and 22 deletions
|
@ -328,24 +328,10 @@ func (s *Module) AddMPTNodes(nodes [][]byte) error {
|
|||
if r.Err != nil {
|
||||
return fmt.Errorf("failed to decode MPT node: %w", r.Err)
|
||||
}
|
||||
nPaths, ok := s.mptpool.TryGet(n.Hash())
|
||||
if !ok {
|
||||
// it can easily happen after receiving the same data from different peers.
|
||||
return nil
|
||||
err := s.restoreNode(n.Node)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var childrenPaths = make(map[util.Uint256][][]byte)
|
||||
for _, path := range nPaths {
|
||||
err := s.billet.RestoreHashNode(path, n.Node)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to add MPT node with hash %s and path %s: %w", n.Hash().StringBE(), hex.EncodeToString(path), err)
|
||||
}
|
||||
for h, paths := range mpt.GetChildrenPaths(path, n.Node) {
|
||||
childrenPaths[h] = append(childrenPaths[h], paths...) // it's OK to have duplicates, they'll be handled by mempool
|
||||
}
|
||||
}
|
||||
|
||||
s.mptpool.Update(map[util.Uint256][][]byte{n.Hash(): nPaths}, childrenPaths)
|
||||
}
|
||||
if s.mptpool.Count() == 0 {
|
||||
s.syncStage |= mptSynced
|
||||
|
@ -356,6 +342,37 @@ func (s *Module) AddMPTNodes(nodes [][]byte) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (s *Module) restoreNode(n mpt.Node) error {
|
||||
nPaths, ok := s.mptpool.TryGet(n.Hash())
|
||||
if !ok {
|
||||
// it can easily happen after receiving the same data from different peers.
|
||||
return nil
|
||||
}
|
||||
var childrenPaths = make(map[util.Uint256][][]byte)
|
||||
for _, path := range nPaths {
|
||||
err := s.billet.RestoreHashNode(path, n)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to restore MPT node with hash %s and path %s: %w", n.Hash().StringBE(), hex.EncodeToString(path), err)
|
||||
}
|
||||
for h, paths := range mpt.GetChildrenPaths(path, n) {
|
||||
childrenPaths[h] = append(childrenPaths[h], paths...) // it's OK to have duplicates, they'll be handled by mempool
|
||||
}
|
||||
}
|
||||
|
||||
s.mptpool.Update(map[util.Uint256][][]byte{n.Hash(): nPaths}, childrenPaths)
|
||||
|
||||
for h := range childrenPaths {
|
||||
if child, err := s.billet.GetFromStore(h); err == nil {
|
||||
// child is already in the storage, so we don't need to request it one more time.
|
||||
err = s.restoreNode(child)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to restore saved children: %w", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// checkSyncIsCompleted checks whether state sync process is completed, i.e. headers up to P+1
|
||||
// height are fetched, blocks up to P height are stored and MPT nodes for P height are stored.
|
||||
// If so, then jumping to P state sync point occurs. It is not protected by lock, thus caller
|
||||
|
@ -438,3 +455,11 @@ func (s *Module) GetJumpHeight() (uint32, error) {
|
|||
}
|
||||
return s.syncPoint, nil
|
||||
}
|
||||
|
||||
// GetUnknownMPTNodesBatch returns set of currently unknown MPT nodes (`limit` at max).
|
||||
func (s *Module) GetUnknownMPTNodesBatch(limit int) []util.Uint256 {
|
||||
s.lock.RLock()
|
||||
defer s.lock.RUnlock()
|
||||
|
||||
return s.mptpool.GetBatch(limit)
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue