Skip to content

The choice of peer to pull block from in fast sync mode might not be optimal #1734

@milosevic

Description

@milosevic

The relevant code is here:

func (pool *BlockPool) pickIncrAvailablePeer(minHeight int64) *bpPeer {
pool.mtx.Lock()
defer pool.mtx.Unlock()
for _, peer := range pool.peers {
if peer.didTimeout {
pool.removePeer(peer.id)
continue
}
if peer.numPending >= maxPendingRequestsPerPeer {
continue
}
if peer.height < minHeight {
continue
}
peer.incrPending()
return peer
}
return nil
}

Note that the algorithm for selecting a peer from whom next block is pulled is chosen by iterating over peers and picking a first peer that satisfies the following condition:
peer.numPending < maxPendingRequestsPerPeer and peer.height >= height, where height is the height of the block we are missing and want to pull in.

This algorithm might lead to the request placement that is not optimal. In case iteration over map is deterministic and always returns the same sequence, it will send request to the first peer from the list (if peer's height is greater than height) until maxPendingRequestsPerPeer - 1 requests are sent, and no request will be sent to other peers. Then it will start sending requests to a second peer, etc.

There are several different approaches how the problem of request for block placement can be made that might lead to better fast sync time, for example, randomly picking peer, or ensuring that requests are sent uniformly to all peers that have blocks, or taking into account how fast we are getting blocks from our peers and giving preference to faster peers, or sending one request at a time to each peer initially and then based on response tine adapting, etc.

Metadata

Metadata

Assignees

No one assigned

    Labels

    C:consensusComponent: ConsensusC:syncComponent: Fast Sync, State SyncT:enhancementType: Enhancement

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions