les: limit state ODR retrievals to the last 100 blocks (#17744)
This commit is contained in:
		
							parent
							
								
									96fd50be10
								
							
						
					
					
						commit
						b7bbe66b19
					
				| @ -32,8 +32,9 @@ import ( | ||||
| ) | ||||
| 
 | ||||
| const ( | ||||
| 	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
 | ||||
| 	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
 | ||||
| 	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
 | ||||
| @ -215,8 +216,8 @@ func (f *lightFetcher) syncLoop() { | ||||
| // registerPeer adds a new peer to the fetcher's peer set
 | ||||
| func (f *lightFetcher) registerPeer(p *peer) { | ||||
| 	p.lock.Lock() | ||||
| 	p.hasBlock = func(hash common.Hash, number uint64) bool { | ||||
| 		return f.peerHasBlock(p, hash, number) | ||||
| 	p.hasBlock = func(hash common.Hash, number uint64, hasState bool) bool { | ||||
| 		return f.peerHasBlock(p, hash, number, hasState) | ||||
| 	} | ||||
| 	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
 | ||||
| // 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() | ||||
| 	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 { | ||||
| 		// always return true when syncing
 | ||||
| 		// false positives are acceptable, a more sophisticated condition can be implemented later
 | ||||
| 		return true | ||||
| 	} | ||||
| 
 | ||||
| 	fp := f.peers[p] | ||||
| 	if fp == nil || fp.root == nil { | ||||
| 		return false | ||||
| 	} | ||||
| 
 | ||||
| 	if number >= fp.root.number { | ||||
| 		// it is recent enough that if it is known, is should be in the peer's block tree
 | ||||
| 		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
 | ||||
| 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)
 | ||||
| @ -140,7 +140,7 @@ func (r *ReceiptsRequest) GetCost(peer *peer) uint64 { | ||||
| 
 | ||||
| // CanSend tells if a certain peer is suitable for serving the given request
 | ||||
| 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)
 | ||||
| @ -202,7 +202,7 @@ func (r *TrieRequest) GetCost(peer *peer) uint64 { | ||||
| 
 | ||||
| // CanSend tells if a certain peer is suitable for serving the given request
 | ||||
| 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)
 | ||||
| @ -272,7 +272,7 @@ func (r *CodeRequest) GetCost(peer *peer) uint64 { | ||||
| 
 | ||||
| // CanSend tells if a certain peer is suitable for serving the given request
 | ||||
| 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)
 | ||||
|  | ||||
| @ -194,7 +194,7 @@ func testOdr(t *testing.T, protocol int, expFail uint64, fn odrTestFn) { | ||||
| 	client.peers.Register(client.rPeer) | ||||
| 	time.Sleep(time.Millisecond * 10) // ensure that all peerSetNotify callbacks are executed
 | ||||
| 	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() | ||||
| 	test(5) | ||||
| 	// still expect all retrievals to pass, now data should be cached locally
 | ||||
|  | ||||
| @ -67,7 +67,7 @@ type peer struct { | ||||
| 	sendQueue   *execQueue | ||||
| 
 | ||||
| 	poolEntry      *poolEntry | ||||
| 	hasBlock       func(common.Hash, uint64) bool | ||||
| 	hasBlock       func(common.Hash, uint64, bool) bool | ||||
| 	responseErrors int | ||||
| 
 | ||||
| 	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
 | ||||
| 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() | ||||
| 	hasBlock := p.hasBlock | ||||
| 	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
 | ||||
|  | ||||
| @ -115,7 +115,7 @@ func testAccess(t *testing.T, protocol int, fn accessTestFn) { | ||||
| 	client.peers.Register(client.rPeer) | ||||
| 	time.Sleep(time.Millisecond * 10) // ensure that all peerSetNotify callbacks are executed
 | ||||
| 	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() | ||||
| 	// expect all retrievals to pass
 | ||||
| 	test(5) | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user