Skip to content

Commit f12f8a6

Browse files
committed
les, light: add block availability check for ODR requests
1 parent c57c54c commit f12f8a6

File tree

7 files changed

+71
-14
lines changed

7 files changed

+71
-14
lines changed

les/fetcher.go

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,12 @@ func (f *lightFetcher) syncLoop() {
200200

201201
// addPeer adds a new peer to the fetcher's peer set
202202
func (f *lightFetcher) addPeer(p *peer) {
203+
p.lock.Lock()
204+
p.hasBlock = func(hash common.Hash, number uint64) bool {
205+
return f.peerHasBlock(p, hash, number)
206+
}
207+
p.lock.Unlock()
208+
203209
f.lock.Lock()
204210
defer f.lock.Unlock()
205211

@@ -208,6 +214,10 @@ func (f *lightFetcher) addPeer(p *peer) {
208214

209215
// removePeer removes a new peer from the fetcher's peer set
210216
func (f *lightFetcher) removePeer(p *peer) {
217+
p.lock.Lock()
218+
p.hasBlock = nil
219+
p.lock.Unlock()
220+
211221
f.lock.Lock()
212222
defer f.lock.Unlock()
213223

@@ -315,7 +325,7 @@ func (f *lightFetcher) announce(p *peer, head *announceData) {
315325
// based on its announcements
316326
func (f *lightFetcher) peerHasBlock(p *peer, hash common.Hash, number uint64) bool {
317327
f.lock.Lock()
318-
defer f.lock.Lock()
328+
defer f.lock.Unlock()
319329

320330
fp := f.peers[p]
321331
if fp == nil || fp.root == nil {

les/odr.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,9 @@ func (self *LesOdr) networkRequest(ctx context.Context, lreq LesOdrRequest) erro
188188
var p *peer
189189
if self.serverPool != nil {
190190
p = self.serverPool.selectPeer(func(p *peer) (bool, uint64) {
191+
if !lreq.CanSend(p) {
192+
return false, 0
193+
}
191194
return true, p.fcServer.CanSend(lreq.GetCost(p))
192195
})
193196
}

les/odr_requests.go

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ import (
3636

3737
type LesOdrRequest interface {
3838
GetCost(*peer) uint64
39+
CanSend(*peer) bool
3940
Request(uint64, *peer) error
4041
Valid(ethdb.Database, *Msg) bool // if true, keeps the retrieved object
4142
}
@@ -66,6 +67,11 @@ func (self *BlockRequest) GetCost(peer *peer) uint64 {
6667
return peer.GetRequestCost(GetBlockBodiesMsg, 1)
6768
}
6869

70+
// CanSend tells if a certain peer is suitable for serving the given request
71+
func (self *BlockRequest) CanSend(peer *peer) bool {
72+
return peer.HasBlock(self.Hash, self.Number)
73+
}
74+
6975
// Request sends an ODR request to the LES network (implementation of LesOdrRequest)
7076
func (self *BlockRequest) Request(reqID uint64, peer *peer) error {
7177
glog.V(logger.Debug).Infof("ODR: requesting body of block %08x from peer %v", self.Hash[:4], peer.id)
@@ -121,6 +127,11 @@ func (self *ReceiptsRequest) GetCost(peer *peer) uint64 {
121127
return peer.GetRequestCost(GetReceiptsMsg, 1)
122128
}
123129

130+
// CanSend tells if a certain peer is suitable for serving the given request
131+
func (self *ReceiptsRequest) CanSend(peer *peer) bool {
132+
return peer.HasBlock(self.Hash, self.Number)
133+
}
134+
124135
// Request sends an ODR request to the LES network (implementation of LesOdrRequest)
125136
func (self *ReceiptsRequest) Request(reqID uint64, peer *peer) error {
126137
glog.V(logger.Debug).Infof("ODR: requesting receipts for block %08x from peer %v", self.Hash[:4], peer.id)
@@ -171,6 +182,11 @@ func (self *TrieRequest) GetCost(peer *peer) uint64 {
171182
return peer.GetRequestCost(GetProofsMsg, 1)
172183
}
173184

185+
// CanSend tells if a certain peer is suitable for serving the given request
186+
func (self *TrieRequest) CanSend(peer *peer) bool {
187+
return peer.HasBlock(self.Id.BlockHash, self.Id.BlockNumber)
188+
}
189+
174190
// Request sends an ODR request to the LES network (implementation of LesOdrRequest)
175191
func (self *TrieRequest) Request(reqID uint64, peer *peer) error {
176192
glog.V(logger.Debug).Infof("ODR: requesting trie root %08x key %08x from peer %v", self.Id.Root[:4], self.Key[:4], peer.id)
@@ -221,6 +237,11 @@ func (self *CodeRequest) GetCost(peer *peer) uint64 {
221237
return peer.GetRequestCost(GetCodeMsg, 1)
222238
}
223239

240+
// CanSend tells if a certain peer is suitable for serving the given request
241+
func (self *CodeRequest) CanSend(peer *peer) bool {
242+
return peer.HasBlock(self.Id.BlockHash, self.Id.BlockNumber)
243+
}
244+
224245
// Request sends an ODR request to the LES network (implementation of LesOdrRequest)
225246
func (self *CodeRequest) Request(reqID uint64, peer *peer) error {
226247
glog.V(logger.Debug).Infof("ODR: requesting node data for hash %08x from peer %v", self.Hash[:4], peer.id)
@@ -274,6 +295,14 @@ func (self *ChtRequest) GetCost(peer *peer) uint64 {
274295
return peer.GetRequestCost(GetHeaderProofsMsg, 1)
275296
}
276297

298+
// CanSend tells if a certain peer is suitable for serving the given request
299+
func (self *ChtRequest) CanSend(peer *peer) bool {
300+
peer.lock.RLock()
301+
defer peer.lock.RUnlock()
302+
303+
return self.ChtNum <= (peer.headInfo.Number-light.ChtConfirmations)/light.ChtFrequency
304+
}
305+
277306
// Request sends an ODR request to the LES network (implementation of LesOdrRequest)
278307
func (self *ChtRequest) Request(reqID uint64, peer *peer) error {
279308
glog.V(logger.Debug).Infof("ODR: requesting CHT #%d block #%d from peer %v", self.ChtNum, self.BlockNum, peer.id)

les/peer.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ type peer struct {
5757
announceChn chan announceData
5858

5959
poolEntry *poolEntry
60+
hasBlock func(common.Hash, uint64) bool
6061

6162
fcClient *flowcontrol.ClientNode // nil if the peer is server only
6263
fcServer *flowcontrol.ServerNode // nil if the peer is client only
@@ -135,13 +136,24 @@ func sendResponse(w p2p.MsgWriter, msgcode, reqID, bv uint64, data interface{})
135136
}
136137

137138
func (p *peer) GetRequestCost(msgcode uint64, amount int) uint64 {
139+
p.lock.RLock()
140+
defer p.lock.RUnlock()
141+
138142
cost := p.fcCosts[msgcode].baseCost + p.fcCosts[msgcode].reqCost*uint64(amount)
139143
if cost > p.fcServerParams.BufLimit {
140144
cost = p.fcServerParams.BufLimit
141145
}
142146
return cost
143147
}
144148

149+
// HasBlock checks if the peer has a given block
150+
func (p *peer) HasBlock(hash common.Hash, number uint64) bool {
151+
p.lock.RLock()
152+
hashBlock := p.hasBlock
153+
p.lock.RUnlock()
154+
return hashBlock != nil && hashBlock(hash, number)
155+
}
156+
145157
// SendAnnounce announces the availability of a number of blocks through
146158
// a hash notification.
147159
func (p *peer) SendAnnounce(request announceData) error {

les/server.go

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -349,9 +349,8 @@ func (pm *ProtocolManager) blockLoop() {
349349
}
350350

351351
var (
352-
lastChtKey = []byte("LastChtNumber") // chtNum (uint64 big endian)
353-
chtPrefix = []byte("cht") // chtPrefix + chtNum (uint64 big endian) -> trie root hash
354-
chtConfirmations = light.ChtFrequency / 2
352+
lastChtKey = []byte("LastChtNumber") // chtNum (uint64 big endian)
353+
chtPrefix = []byte("cht") // chtPrefix + chtNum (uint64 big endian) -> trie root hash
355354
)
356355

357356
func getChtRoot(db ethdb.Database, num uint64) common.Hash {
@@ -372,8 +371,8 @@ func makeCht(db ethdb.Database) bool {
372371
headNum := core.GetBlockNumber(db, headHash)
373372

374373
var newChtNum uint64
375-
if headNum > chtConfirmations {
376-
newChtNum = (headNum - chtConfirmations) / light.ChtFrequency
374+
if headNum > light.ChtConfirmations {
375+
newChtNum = (headNum - light.ChtConfirmations) / light.ChtFrequency
377376
}
378377

379378
var lastChtNum uint64

light/odr.go

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -48,16 +48,18 @@ type OdrRequest interface {
4848
// TrieID identifies a state or account storage trie
4949
type TrieID struct {
5050
BlockHash, Root common.Hash
51+
BlockNumber uint64
5152
AccKey []byte
5253
}
5354

5455
// StateTrieID returns a TrieID for a state trie belonging to a certain block
5556
// header.
5657
func StateTrieID(header *types.Header) *TrieID {
5758
return &TrieID{
58-
BlockHash: header.Hash(),
59-
AccKey: nil,
60-
Root: header.Root,
59+
BlockHash: header.Hash(),
60+
BlockNumber: header.Number.Uint64(),
61+
AccKey: nil,
62+
Root: header.Root,
6163
}
6264
}
6365

@@ -66,9 +68,10 @@ func StateTrieID(header *types.Header) *TrieID {
6668
// checking Merkle proofs.
6769
func StorageTrieID(state *TrieID, addr common.Address, root common.Hash) *TrieID {
6870
return &TrieID{
69-
BlockHash: state.BlockHash,
70-
AccKey: crypto.Keccak256(addr[:]),
71-
Root: root,
71+
BlockHash: state.BlockHash,
72+
BlockNumber: state.BlockNumber,
73+
AccKey: crypto.Keccak256(addr[:]),
74+
Root: root,
7275
}
7376
}
7477

light/odr_util.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,9 @@ var (
3838
ErrNoTrustedCht = errors.New("No trusted canonical hash trie")
3939
ErrNoHeader = errors.New("Header not found")
4040

41-
ChtFrequency = uint64(4096)
42-
trustedChtKey = []byte("TrustedCHT")
41+
ChtFrequency = uint64(4096)
42+
ChtConfirmations = uint64(2048)
43+
trustedChtKey = []byte("TrustedCHT")
4344
)
4445

4546
type ChtNode struct {

0 commit comments

Comments
 (0)