aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorZsolt Felfoldi <zsfelfoldi@gmail.com>2016-12-10 13:50:36 +0800
committerZsolt Felfoldi <zsfelfoldi@gmail.com>2016-12-10 16:53:25 +0800
commitf12f8a6c14dbaf6e6531cea1b0cf169b851e1894 (patch)
tree41f0d7dd9f5fe21cbb8615a59cc08b9594f83770
parentc57c54ce96628aeb6345776310123a80593f0143 (diff)
downloaddexon-f12f8a6c14dbaf6e6531cea1b0cf169b851e1894.tar.gz
dexon-f12f8a6c14dbaf6e6531cea1b0cf169b851e1894.tar.zst
dexon-f12f8a6c14dbaf6e6531cea1b0cf169b851e1894.zip
les, light: add block availability check for ODR requests
-rw-r--r--les/fetcher.go12
-rw-r--r--les/odr.go3
-rw-r--r--les/odr_requests.go29
-rw-r--r--les/peer.go12
-rw-r--r--les/server.go9
-rw-r--r--light/odr.go15
-rw-r--r--light/odr_util.go5
7 files changed, 71 insertions, 14 deletions
diff --git a/les/fetcher.go b/les/fetcher.go
index 00cb31dfb..c23af8da3 100644
--- a/les/fetcher.go
+++ b/les/fetcher.go
@@ -200,6 +200,12 @@ func (f *lightFetcher) syncLoop() {
// addPeer adds a new peer to the fetcher's peer set
func (f *lightFetcher) addPeer(p *peer) {
+ p.lock.Lock()
+ p.hasBlock = func(hash common.Hash, number uint64) bool {
+ return f.peerHasBlock(p, hash, number)
+ }
+ p.lock.Unlock()
+
f.lock.Lock()
defer f.lock.Unlock()
@@ -208,6 +214,10 @@ func (f *lightFetcher) addPeer(p *peer) {
// removePeer removes a new peer from the fetcher's peer set
func (f *lightFetcher) removePeer(p *peer) {
+ p.lock.Lock()
+ p.hasBlock = nil
+ p.lock.Unlock()
+
f.lock.Lock()
defer f.lock.Unlock()
@@ -315,7 +325,7 @@ func (f *lightFetcher) announce(p *peer, head *announceData) {
// based on its announcements
func (f *lightFetcher) peerHasBlock(p *peer, hash common.Hash, number uint64) bool {
f.lock.Lock()
- defer f.lock.Lock()
+ defer f.lock.Unlock()
fp := f.peers[p]
if fp == nil || fp.root == nil {
diff --git a/les/odr.go b/les/odr.go
index 4bfbdcb4d..8878508c4 100644
--- a/les/odr.go
+++ b/les/odr.go
@@ -188,6 +188,9 @@ func (self *LesOdr) networkRequest(ctx context.Context, lreq LesOdrRequest) erro
var p *peer
if self.serverPool != nil {
p = self.serverPool.selectPeer(func(p *peer) (bool, uint64) {
+ if !lreq.CanSend(p) {
+ return false, 0
+ }
return true, p.fcServer.CanSend(lreq.GetCost(p))
})
}
diff --git a/les/odr_requests.go b/les/odr_requests.go
index f4bd51888..a4fbd79f6 100644
--- a/les/odr_requests.go
+++ b/les/odr_requests.go
@@ -36,6 +36,7 @@ import (
type LesOdrRequest interface {
GetCost(*peer) uint64
+ CanSend(*peer) bool
Request(uint64, *peer) error
Valid(ethdb.Database, *Msg) bool // if true, keeps the retrieved object
}
@@ -66,6 +67,11 @@ func (self *BlockRequest) GetCost(peer *peer) uint64 {
return peer.GetRequestCost(GetBlockBodiesMsg, 1)
}
+// CanSend tells if a certain peer is suitable for serving the given request
+func (self *BlockRequest) CanSend(peer *peer) bool {
+ return peer.HasBlock(self.Hash, self.Number)
+}
+
// Request sends an ODR request to the LES network (implementation of LesOdrRequest)
func (self *BlockRequest) Request(reqID uint64, peer *peer) error {
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 {
return peer.GetRequestCost(GetReceiptsMsg, 1)
}
+// CanSend tells if a certain peer is suitable for serving the given request
+func (self *ReceiptsRequest) CanSend(peer *peer) bool {
+ return peer.HasBlock(self.Hash, self.Number)
+}
+
// Request sends an ODR request to the LES network (implementation of LesOdrRequest)
func (self *ReceiptsRequest) Request(reqID uint64, peer *peer) error {
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 {
return peer.GetRequestCost(GetProofsMsg, 1)
}
+// CanSend tells if a certain peer is suitable for serving the given request
+func (self *TrieRequest) CanSend(peer *peer) bool {
+ return peer.HasBlock(self.Id.BlockHash, self.Id.BlockNumber)
+}
+
// Request sends an ODR request to the LES network (implementation of LesOdrRequest)
func (self *TrieRequest) Request(reqID uint64, peer *peer) error {
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 {
return peer.GetRequestCost(GetCodeMsg, 1)
}
+// CanSend tells if a certain peer is suitable for serving the given request
+func (self *CodeRequest) CanSend(peer *peer) bool {
+ return peer.HasBlock(self.Id.BlockHash, self.Id.BlockNumber)
+}
+
// Request sends an ODR request to the LES network (implementation of LesOdrRequest)
func (self *CodeRequest) Request(reqID uint64, peer *peer) error {
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 {
return peer.GetRequestCost(GetHeaderProofsMsg, 1)
}
+// CanSend tells if a certain peer is suitable for serving the given request
+func (self *ChtRequest) CanSend(peer *peer) bool {
+ peer.lock.RLock()
+ defer peer.lock.RUnlock()
+
+ return self.ChtNum <= (peer.headInfo.Number-light.ChtConfirmations)/light.ChtFrequency
+}
+
// Request sends an ODR request to the LES network (implementation of LesOdrRequest)
func (self *ChtRequest) Request(reqID uint64, peer *peer) error {
glog.V(logger.Debug).Infof("ODR: requesting CHT #%d block #%d from peer %v", self.ChtNum, self.BlockNum, peer.id)
diff --git a/les/peer.go b/les/peer.go
index 8ebbe3511..0a8db4975 100644
--- a/les/peer.go
+++ b/les/peer.go
@@ -57,6 +57,7 @@ type peer struct {
announceChn chan announceData
poolEntry *poolEntry
+ hasBlock func(common.Hash, uint64) bool
fcClient *flowcontrol.ClientNode // nil if the peer is server only
fcServer *flowcontrol.ServerNode // nil if the peer is client only
@@ -135,6 +136,9 @@ func sendResponse(w p2p.MsgWriter, msgcode, reqID, bv uint64, data interface{})
}
func (p *peer) GetRequestCost(msgcode uint64, amount int) uint64 {
+ p.lock.RLock()
+ defer p.lock.RUnlock()
+
cost := p.fcCosts[msgcode].baseCost + p.fcCosts[msgcode].reqCost*uint64(amount)
if cost > p.fcServerParams.BufLimit {
cost = p.fcServerParams.BufLimit
@@ -142,6 +146,14 @@ func (p *peer) GetRequestCost(msgcode uint64, amount int) uint64 {
return cost
}
+// HasBlock checks if the peer has a given block
+func (p *peer) HasBlock(hash common.Hash, number uint64) bool {
+ p.lock.RLock()
+ hashBlock := p.hasBlock
+ p.lock.RUnlock()
+ return hashBlock != nil && hashBlock(hash, number)
+}
+
// SendAnnounce announces the availability of a number of blocks through
// a hash notification.
func (p *peer) SendAnnounce(request announceData) error {
diff --git a/les/server.go b/les/server.go
index 03cc2bb5e..e55616a44 100644
--- a/les/server.go
+++ b/les/server.go
@@ -349,9 +349,8 @@ func (pm *ProtocolManager) blockLoop() {
}
var (
- lastChtKey = []byte("LastChtNumber") // chtNum (uint64 big endian)
- chtPrefix = []byte("cht") // chtPrefix + chtNum (uint64 big endian) -> trie root hash
- chtConfirmations = light.ChtFrequency / 2
+ lastChtKey = []byte("LastChtNumber") // chtNum (uint64 big endian)
+ chtPrefix = []byte("cht") // chtPrefix + chtNum (uint64 big endian) -> trie root hash
)
func getChtRoot(db ethdb.Database, num uint64) common.Hash {
@@ -372,8 +371,8 @@ func makeCht(db ethdb.Database) bool {
headNum := core.GetBlockNumber(db, headHash)
var newChtNum uint64
- if headNum > chtConfirmations {
- newChtNum = (headNum - chtConfirmations) / light.ChtFrequency
+ if headNum > light.ChtConfirmations {
+ newChtNum = (headNum - light.ChtConfirmations) / light.ChtFrequency
}
var lastChtNum uint64
diff --git a/light/odr.go b/light/odr.go
index 679569bf9..4f6ef6b9e 100644
--- a/light/odr.go
+++ b/light/odr.go
@@ -48,6 +48,7 @@ type OdrRequest interface {
// TrieID identifies a state or account storage trie
type TrieID struct {
BlockHash, Root common.Hash
+ BlockNumber uint64
AccKey []byte
}
@@ -55,9 +56,10 @@ type TrieID struct {
// header.
func StateTrieID(header *types.Header) *TrieID {
return &TrieID{
- BlockHash: header.Hash(),
- AccKey: nil,
- Root: header.Root,
+ BlockHash: header.Hash(),
+ BlockNumber: header.Number.Uint64(),
+ AccKey: nil,
+ Root: header.Root,
}
}
@@ -66,9 +68,10 @@ func StateTrieID(header *types.Header) *TrieID {
// checking Merkle proofs.
func StorageTrieID(state *TrieID, addr common.Address, root common.Hash) *TrieID {
return &TrieID{
- BlockHash: state.BlockHash,
- AccKey: crypto.Keccak256(addr[:]),
- Root: root,
+ BlockHash: state.BlockHash,
+ BlockNumber: state.BlockNumber,
+ AccKey: crypto.Keccak256(addr[:]),
+ Root: root,
}
}
diff --git a/light/odr_util.go b/light/odr_util.go
index 5c72f90e9..761711621 100644
--- a/light/odr_util.go
+++ b/light/odr_util.go
@@ -38,8 +38,9 @@ var (
ErrNoTrustedCht = errors.New("No trusted canonical hash trie")
ErrNoHeader = errors.New("Header not found")
- ChtFrequency = uint64(4096)
- trustedChtKey = []byte("TrustedCHT")
+ ChtFrequency = uint64(4096)
+ ChtConfirmations = uint64(2048)
+ trustedChtKey = []byte("TrustedCHT")
)
type ChtNode struct {