les: limit state ODR retrievals to the last 100 blocks (#17744)
This commit is contained in:
parent
96fd50be10
commit
b7bbe66b19
|
@ -34,6 +34,7 @@ import (
|
||||||
const (
|
const (
|
||||||
blockDelayTimeout = time.Second * 10 // timeout for a peer to announce a head that has already been confirmed by others
|
blockDelayTimeout = time.Second * 10 // timeout for a peer to announce a head that has already been confirmed by others
|
||||||
maxNodeCount = 20 // maximum number of fetcherTreeNode entries remembered for each peer
|
maxNodeCount = 20 // maximum number of fetcherTreeNode entries remembered for each peer
|
||||||
|
serverStateAvailable = 100 // number of recent blocks where state availability is assumed
|
||||||
)
|
)
|
||||||
|
|
||||||
// lightFetcher implements retrieval of newly announced headers. It also provides a peerHasBlock function for the
|
// lightFetcher implements retrieval of newly announced headers. It also provides a peerHasBlock function for the
|
||||||
|
@ -215,8 +216,8 @@ func (f *lightFetcher) syncLoop() {
|
||||||
// registerPeer adds a new peer to the fetcher's peer set
|
// registerPeer adds a new peer to the fetcher's peer set
|
||||||
func (f *lightFetcher) registerPeer(p *peer) {
|
func (f *lightFetcher) registerPeer(p *peer) {
|
||||||
p.lock.Lock()
|
p.lock.Lock()
|
||||||
p.hasBlock = func(hash common.Hash, number uint64) bool {
|
p.hasBlock = func(hash common.Hash, number uint64, hasState bool) bool {
|
||||||
return f.peerHasBlock(p, hash, number)
|
return f.peerHasBlock(p, hash, number, hasState)
|
||||||
}
|
}
|
||||||
p.lock.Unlock()
|
p.lock.Unlock()
|
||||||
|
|
||||||
|
@ -344,21 +345,27 @@ func (f *lightFetcher) announce(p *peer, head *announceData) {
|
||||||
|
|
||||||
// peerHasBlock returns true if we can assume the peer knows the given block
|
// peerHasBlock returns true if we can assume the peer knows the given block
|
||||||
// based on its announcements
|
// based on its announcements
|
||||||
func (f *lightFetcher) peerHasBlock(p *peer, hash common.Hash, number uint64) bool {
|
func (f *lightFetcher) peerHasBlock(p *peer, hash common.Hash, number uint64, hasState bool) bool {
|
||||||
f.lock.Lock()
|
f.lock.Lock()
|
||||||
defer f.lock.Unlock()
|
defer f.lock.Unlock()
|
||||||
|
|
||||||
|
fp := f.peers[p]
|
||||||
|
if fp == nil || fp.root == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if hasState {
|
||||||
|
if fp.lastAnnounced == nil || fp.lastAnnounced.number > number+serverStateAvailable {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if f.syncing {
|
if f.syncing {
|
||||||
// always return true when syncing
|
// always return true when syncing
|
||||||
// false positives are acceptable, a more sophisticated condition can be implemented later
|
// false positives are acceptable, a more sophisticated condition can be implemented later
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
fp := f.peers[p]
|
|
||||||
if fp == nil || fp.root == nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
if number >= fp.root.number {
|
if number >= fp.root.number {
|
||||||
// it is recent enough that if it is known, is should be in the peer's block tree
|
// it is recent enough that if it is known, is should be in the peer's block tree
|
||||||
return fp.nodeByHash[hash] != nil
|
return fp.nodeByHash[hash] != nil
|
||||||
|
|
|
@ -84,7 +84,7 @@ func (r *BlockRequest) GetCost(peer *peer) uint64 {
|
||||||
|
|
||||||
// CanSend tells if a certain peer is suitable for serving the given request
|
// CanSend tells if a certain peer is suitable for serving the given request
|
||||||
func (r *BlockRequest) CanSend(peer *peer) bool {
|
func (r *BlockRequest) CanSend(peer *peer) bool {
|
||||||
return peer.HasBlock(r.Hash, r.Number)
|
return peer.HasBlock(r.Hash, r.Number, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Request sends an ODR request to the LES network (implementation of LesOdrRequest)
|
// Request sends an ODR request to the LES network (implementation of LesOdrRequest)
|
||||||
|
@ -140,7 +140,7 @@ func (r *ReceiptsRequest) GetCost(peer *peer) uint64 {
|
||||||
|
|
||||||
// CanSend tells if a certain peer is suitable for serving the given request
|
// CanSend tells if a certain peer is suitable for serving the given request
|
||||||
func (r *ReceiptsRequest) CanSend(peer *peer) bool {
|
func (r *ReceiptsRequest) CanSend(peer *peer) bool {
|
||||||
return peer.HasBlock(r.Hash, r.Number)
|
return peer.HasBlock(r.Hash, r.Number, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Request sends an ODR request to the LES network (implementation of LesOdrRequest)
|
// Request sends an ODR request to the LES network (implementation of LesOdrRequest)
|
||||||
|
@ -202,7 +202,7 @@ func (r *TrieRequest) GetCost(peer *peer) uint64 {
|
||||||
|
|
||||||
// CanSend tells if a certain peer is suitable for serving the given request
|
// CanSend tells if a certain peer is suitable for serving the given request
|
||||||
func (r *TrieRequest) CanSend(peer *peer) bool {
|
func (r *TrieRequest) CanSend(peer *peer) bool {
|
||||||
return peer.HasBlock(r.Id.BlockHash, r.Id.BlockNumber)
|
return peer.HasBlock(r.Id.BlockHash, r.Id.BlockNumber, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Request sends an ODR request to the LES network (implementation of LesOdrRequest)
|
// Request sends an ODR request to the LES network (implementation of LesOdrRequest)
|
||||||
|
@ -272,7 +272,7 @@ func (r *CodeRequest) GetCost(peer *peer) uint64 {
|
||||||
|
|
||||||
// CanSend tells if a certain peer is suitable for serving the given request
|
// CanSend tells if a certain peer is suitable for serving the given request
|
||||||
func (r *CodeRequest) CanSend(peer *peer) bool {
|
func (r *CodeRequest) CanSend(peer *peer) bool {
|
||||||
return peer.HasBlock(r.Id.BlockHash, r.Id.BlockNumber)
|
return peer.HasBlock(r.Id.BlockHash, r.Id.BlockNumber, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Request sends an ODR request to the LES network (implementation of LesOdrRequest)
|
// Request sends an ODR request to the LES network (implementation of LesOdrRequest)
|
||||||
|
|
|
@ -194,7 +194,7 @@ func testOdr(t *testing.T, protocol int, expFail uint64, fn odrTestFn) {
|
||||||
client.peers.Register(client.rPeer)
|
client.peers.Register(client.rPeer)
|
||||||
time.Sleep(time.Millisecond * 10) // ensure that all peerSetNotify callbacks are executed
|
time.Sleep(time.Millisecond * 10) // ensure that all peerSetNotify callbacks are executed
|
||||||
client.peers.lock.Lock()
|
client.peers.lock.Lock()
|
||||||
client.rPeer.hasBlock = func(common.Hash, uint64) bool { return true }
|
client.rPeer.hasBlock = func(common.Hash, uint64, bool) bool { return true }
|
||||||
client.peers.lock.Unlock()
|
client.peers.lock.Unlock()
|
||||||
test(5)
|
test(5)
|
||||||
// still expect all retrievals to pass, now data should be cached locally
|
// still expect all retrievals to pass, now data should be cached locally
|
||||||
|
|
|
@ -67,7 +67,7 @@ type peer struct {
|
||||||
sendQueue *execQueue
|
sendQueue *execQueue
|
||||||
|
|
||||||
poolEntry *poolEntry
|
poolEntry *poolEntry
|
||||||
hasBlock func(common.Hash, uint64) bool
|
hasBlock func(common.Hash, uint64, bool) bool
|
||||||
responseErrors int
|
responseErrors int
|
||||||
|
|
||||||
fcClient *flowcontrol.ClientNode // nil if the peer is server only
|
fcClient *flowcontrol.ClientNode // nil if the peer is server only
|
||||||
|
@ -171,11 +171,11 @@ func (p *peer) GetRequestCost(msgcode uint64, amount int) uint64 {
|
||||||
}
|
}
|
||||||
|
|
||||||
// HasBlock checks if the peer has a given block
|
// HasBlock checks if the peer has a given block
|
||||||
func (p *peer) HasBlock(hash common.Hash, number uint64) bool {
|
func (p *peer) HasBlock(hash common.Hash, number uint64, hasState bool) bool {
|
||||||
p.lock.RLock()
|
p.lock.RLock()
|
||||||
hasBlock := p.hasBlock
|
hasBlock := p.hasBlock
|
||||||
p.lock.RUnlock()
|
p.lock.RUnlock()
|
||||||
return hasBlock != nil && hasBlock(hash, number)
|
return hasBlock != nil && hasBlock(hash, number, hasState)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SendAnnounce announces the availability of a number of blocks through
|
// SendAnnounce announces the availability of a number of blocks through
|
||||||
|
|
|
@ -115,7 +115,7 @@ func testAccess(t *testing.T, protocol int, fn accessTestFn) {
|
||||||
client.peers.Register(client.rPeer)
|
client.peers.Register(client.rPeer)
|
||||||
time.Sleep(time.Millisecond * 10) // ensure that all peerSetNotify callbacks are executed
|
time.Sleep(time.Millisecond * 10) // ensure that all peerSetNotify callbacks are executed
|
||||||
client.rPeer.lock.Lock()
|
client.rPeer.lock.Lock()
|
||||||
client.rPeer.hasBlock = func(common.Hash, uint64) bool { return true }
|
client.rPeer.hasBlock = func(common.Hash, uint64, bool) bool { return true }
|
||||||
client.rPeer.lock.Unlock()
|
client.rPeer.lock.Unlock()
|
||||||
// expect all retrievals to pass
|
// expect all retrievals to pass
|
||||||
test(5)
|
test(5)
|
||||||
|
|
Loading…
Reference in New Issue