Skip to content

Commit

Permalink
les: implement PPTProofsMsg
Browse files Browse the repository at this point in the history
  • Loading branch information
zsfelfoldi committed Aug 19, 2017
1 parent cf97294 commit 0d0c3ae
Show file tree
Hide file tree
Showing 5 changed files with 276 additions and 42 deletions.
100 changes: 96 additions & 4 deletions les/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -826,22 +826,90 @@ func (pm *ProtocolManager) handleMsg(p *peer) error {
pm.server.fcCostStats.update(msg.Code, uint64(reqCnt), rcost)
return p.SendHeaderProofs(req.ReqID, bv, proofs)

case HeaderProofsMsg:
case GetPPTProofsMsg:
p.Log().Trace("Received PPT proof request")
// Decode the retrieval message
var req struct {
ReqID uint64
Reqs []PPTReq
}
if err := msg.Decode(&req); err != nil {
return errResp(ErrDecode, "msg %v: %v", msg, err)
}
// Gather state data until the fetch or network limits is reached
var (
auxBytes int
auxData [][]byte
)
reqCnt := len(req.Reqs)
if reject(uint64(reqCnt), MaxPPTProofsFetch) {
return errResp(ErrRequestRejected, "")
}

var (
lastIdx uint64
lastPPTId uint
root common.Hash
tr *trie.Trie
)

nodes := light.NewNodeSet()

for _, req := range req.Reqs {
if nodes.DataSize()+auxBytes >= softResponseLimit {
break
}
if tr == nil || req.PPTId != lastPPTId || req.TrieIdx != lastIdx {
var prefix string
root, prefix = pm.getPPT(req.PPTId, req.TrieIdx)
if root != (common.Hash{}) {
if t, err := trie.New(root, ethdb.NewTable(pm.chainDb, prefix)); err == nil {
tr = t
}
}
lastPPTId = req.PPTId
lastIdx = req.TrieIdx
}
if req.AuxReq == PPTAuxRoot {
var data []byte
if root != (common.Hash{}) {
data = root[:]
}
auxData = append(auxData, data)
auxBytes += len(data)
} else {
if tr != nil {
tr.Prove(req.Key, req.FromLevel, nodes)
}
if req.AuxReq != 0 {
data := pm.getPPTAuxData(req)
auxData = append(auxData, data)
auxBytes += len(data)
}
}
}
proofs := nodes.NodeList()
bv, rcost := p.fcClient.RequestProcessed(costs.baseCost + uint64(reqCnt)*costs.reqCost)
pm.server.fcCostStats.update(msg.Code, uint64(reqCnt), rcost)
return p.SendPPTProofs(req.ReqID, bv, PPTResps{Proofs: proofs, AuxData: auxData})

case PPTProofsMsg:
if pm.odr == nil {
return errResp(ErrUnexpectedResponse, "")
}

p.Log().Trace("Received headers proof response")
p.Log().Trace("Received PPT proof response")
var resp struct {
ReqID, BV uint64
Data []ChtResp
Data PPTResps
}
if err := msg.Decode(&resp); err != nil {
return errResp(ErrDecode, "msg %v: %v", msg, err)
}

p.fcServer.GotReply(resp.ReqID, resp.BV)
deliverMsg = &Msg{
MsgType: MsgHeaderProofs,
MsgType: MsgPPTProofs,
ReqID: resp.ReqID,
Obj: resp.Data,
}
Expand Down Expand Up @@ -884,6 +952,30 @@ func (pm *ProtocolManager) handleMsg(p *peer) error {
return nil
}

// getPPT returns the post-processed trie root for the given trie ID and section index
func (pm *ProtocolManager) getPPT(id uint, idx uint64) (common.Hash, string) {
switch id {
case PPTChain:
return light.GetChtRoot(pm.chainDb, idx), light.ChtTablePrefix
case PPTBloomBits:
return light.GetBloomTrieRoot(pm.chainDb, idx), light.BloomTrieTablePrefix
}
return common.Hash{}, ""
}

// getPPTAuxData returns requested auxiliary data for the given PPT request
func (pm *ProtocolManager) getPPTAuxData(req PPTReq) []byte {
if req.PPTId == PPTChain && req.AuxReq == PPTChainAuxHeader {
if len(req.Key) != 8 {
return nil
}
blockNum := binary.BigEndian.Uint64(req.Key)
hash := core.GetCanonicalHash(pm.chainDb, blockNum)
return core.GetHeaderRLP(pm.chainDb, hash, blockNum)
}
return nil
}

// NodeInfo retrieves some protocol metadata about the running host node.
func (self *ProtocolManager) NodeInfo() *eth.EthNodeInfo {
return &eth.EthNodeInfo{
Expand Down
2 changes: 1 addition & 1 deletion les/odr.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ const (
MsgCode
MsgReceipts
MsgProofs
MsgHeaderProofs
MsgPPTProofs
)

// Msg encodes a LES message that delivers reply data for a request
Expand Down
Loading

0 comments on commit 0d0c3ae

Please sign in to comment.