github.com/theQRL/go-zond@v0.1.1/les/client_handler.go (about) 1 // Copyright 2019 The go-ethereum Authors 2 // This file is part of the go-ethereum library. 3 // 4 // The go-ethereum library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The go-ethereum library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 16 17 package les 18 19 import ( 20 "sync" 21 "time" 22 23 "github.com/theQRL/go-zond/common" 24 "github.com/theQRL/go-zond/common/mclock" 25 "github.com/theQRL/go-zond/core/forkid" 26 "github.com/theQRL/go-zond/core/types" 27 "github.com/theQRL/go-zond/light" 28 "github.com/theQRL/go-zond/p2p" 29 ) 30 31 // clientHandler is responsible for receiving and processing all incoming server 32 // responses. 33 type clientHandler struct { 34 forkFilter forkid.Filter 35 backend *LightEthereum 36 37 closeCh chan struct{} 38 wg sync.WaitGroup // WaitGroup used to track all connected peers. 39 } 40 41 func newClientHandler(backend *LightEthereum) *clientHandler { 42 handler := &clientHandler{ 43 forkFilter: forkid.NewFilter(backend.blockchain), 44 backend: backend, 45 closeCh: make(chan struct{}), 46 } 47 return handler 48 } 49 50 func (h *clientHandler) stop() { 51 close(h.closeCh) 52 h.wg.Wait() 53 } 54 55 // runPeer is the p2p protocol run function for the given version. 56 func (h *clientHandler) runPeer(version uint, p *p2p.Peer, rw p2p.MsgReadWriter) error { 57 peer := newServerPeer(int(version), h.backend.config.NetworkId, false, p, newMeteredMsgWriter(rw, int(version))) 58 defer peer.close() 59 h.wg.Add(1) 60 defer h.wg.Done() 61 err := h.handle(peer, false) 62 return err 63 } 64 65 func (h *clientHandler) handle(p *serverPeer, noInitAnnounce bool) error { 66 if h.backend.peers.len() >= h.backend.config.LightPeers && !p.Peer.Info().Network.Trusted { 67 return p2p.DiscTooManyPeers 68 } 69 p.Log().Debug("Light Ethereum peer connected", "name", p.Name()) 70 71 // Execute the LES handshake 72 forkid := forkid.NewID(h.backend.blockchain.Config(), h.backend.BlockChain().Genesis(), h.backend.blockchain.CurrentHeader().Number.Uint64(), h.backend.blockchain.CurrentHeader().Time) 73 if err := p.Handshake(h.backend.blockchain.Genesis().Hash(), forkid, h.forkFilter); err != nil { 74 p.Log().Debug("Light Ethereum handshake failed", "err", err) 75 return err 76 } 77 // Register peer with the server pool 78 if h.backend.serverPool != nil { 79 if nvt, err := h.backend.serverPool.RegisterNode(p.Node()); err == nil { 80 p.setValueTracker(nvt) 81 p.updateVtParams() 82 defer func() { 83 p.setValueTracker(nil) 84 h.backend.serverPool.UnregisterNode(p.Node()) 85 }() 86 } else { 87 return err 88 } 89 } 90 // Register the peer locally 91 if err := h.backend.peers.register(p); err != nil { 92 p.Log().Error("Light Ethereum peer registration failed", "err", err) 93 return err 94 } 95 96 serverConnectionGauge.Update(int64(h.backend.peers.len())) 97 98 connectedAt := mclock.Now() 99 defer func() { 100 h.backend.peers.unregister(p.id) 101 connectionTimer.Update(time.Duration(mclock.Now() - connectedAt)) 102 serverConnectionGauge.Update(int64(h.backend.peers.len())) 103 }() 104 105 // Mark the peer starts to be served. 106 p.serving.Store(true) 107 defer p.serving.Store(false) 108 109 // Spawn a main loop to handle all incoming messages. 110 for { 111 if err := h.handleMsg(p); err != nil { 112 p.Log().Debug("Light Ethereum message handling failed", "err", err) 113 p.fcServer.DumpLogs() 114 return err 115 } 116 } 117 } 118 119 // handleMsg is invoked whenever an inbound message is received from a remote 120 // peer. The remote connection is torn down upon returning any error. 121 func (h *clientHandler) handleMsg(p *serverPeer) error { 122 // Read the next message from the remote peer, and ensure it's fully consumed 123 msg, err := p.rw.ReadMsg() 124 if err != nil { 125 return err 126 } 127 p.Log().Trace("Light Ethereum message arrived", "code", msg.Code, "bytes", msg.Size) 128 129 if msg.Size > ProtocolMaxMsgSize { 130 return errResp(ErrMsgTooLarge, "%v > %v", msg.Size, ProtocolMaxMsgSize) 131 } 132 defer msg.Discard() 133 134 var deliverMsg *Msg 135 136 // Handle the message depending on its contents 137 switch { 138 case msg.Code == AnnounceMsg: 139 p.Log().Trace("Received announce message") 140 var req announceData 141 if err := msg.Decode(&req); err != nil { 142 return errResp(ErrDecode, "%v: %v", msg, err) 143 } 144 if err := req.sanityCheck(); err != nil { 145 return err 146 } 147 update, size := req.Update.decode() 148 if p.rejectUpdate(size) { 149 return errResp(ErrRequestRejected, "") 150 } 151 p.updateFlowControl(update) 152 p.updateVtParams() 153 154 if req.Hash != (common.Hash{}) { 155 if p.announceType == announceTypeNone { 156 return errResp(ErrUnexpectedResponse, "") 157 } 158 if p.announceType == announceTypeSigned { 159 if err := req.checkSignature(p.ID(), update); err != nil { 160 p.Log().Trace("Invalid announcement signature", "err", err) 161 return err 162 } 163 p.Log().Trace("Valid announcement signature") 164 } 165 p.Log().Trace("Announce message content", "number", req.Number, "hash", req.Hash, "td", req.Td, "reorg", req.ReorgDepth) 166 167 // Update peer head information first and then notify the announcement 168 p.updateHead(req.Hash, req.Number, req.Td) 169 } 170 case msg.Code == BlockHeadersMsg: 171 p.Log().Trace("Received block header response message") 172 var resp struct { 173 ReqID, BV uint64 174 Headers []*types.Header 175 } 176 if err := msg.Decode(&resp); err != nil { 177 return errResp(ErrDecode, "msg %v: %v", msg, err) 178 } 179 p.fcServer.ReceivedReply(resp.ReqID, resp.BV) 180 p.answeredRequest(resp.ReqID) 181 182 deliverMsg = &Msg{ 183 MsgType: MsgBlockHeaders, 184 ReqID: resp.ReqID, 185 Obj: resp.Headers, 186 } 187 case msg.Code == BlockBodiesMsg: 188 p.Log().Trace("Received block bodies response") 189 var resp struct { 190 ReqID, BV uint64 191 Data []*types.Body 192 } 193 if err := msg.Decode(&resp); err != nil { 194 return errResp(ErrDecode, "msg %v: %v", msg, err) 195 } 196 p.fcServer.ReceivedReply(resp.ReqID, resp.BV) 197 p.answeredRequest(resp.ReqID) 198 deliverMsg = &Msg{ 199 MsgType: MsgBlockBodies, 200 ReqID: resp.ReqID, 201 Obj: resp.Data, 202 } 203 case msg.Code == CodeMsg: 204 p.Log().Trace("Received code response") 205 var resp struct { 206 ReqID, BV uint64 207 Data [][]byte 208 } 209 if err := msg.Decode(&resp); err != nil { 210 return errResp(ErrDecode, "msg %v: %v", msg, err) 211 } 212 p.fcServer.ReceivedReply(resp.ReqID, resp.BV) 213 p.answeredRequest(resp.ReqID) 214 deliverMsg = &Msg{ 215 MsgType: MsgCode, 216 ReqID: resp.ReqID, 217 Obj: resp.Data, 218 } 219 case msg.Code == ReceiptsMsg: 220 p.Log().Trace("Received receipts response") 221 var resp struct { 222 ReqID, BV uint64 223 Receipts []types.Receipts 224 } 225 if err := msg.Decode(&resp); err != nil { 226 return errResp(ErrDecode, "msg %v: %v", msg, err) 227 } 228 p.fcServer.ReceivedReply(resp.ReqID, resp.BV) 229 p.answeredRequest(resp.ReqID) 230 deliverMsg = &Msg{ 231 MsgType: MsgReceipts, 232 ReqID: resp.ReqID, 233 Obj: resp.Receipts, 234 } 235 case msg.Code == ProofsV2Msg: 236 p.Log().Trace("Received les/2 proofs response") 237 var resp struct { 238 ReqID, BV uint64 239 Data light.NodeList 240 } 241 if err := msg.Decode(&resp); err != nil { 242 return errResp(ErrDecode, "msg %v: %v", msg, err) 243 } 244 p.fcServer.ReceivedReply(resp.ReqID, resp.BV) 245 p.answeredRequest(resp.ReqID) 246 deliverMsg = &Msg{ 247 MsgType: MsgProofsV2, 248 ReqID: resp.ReqID, 249 Obj: resp.Data, 250 } 251 case msg.Code == HelperTrieProofsMsg: 252 p.Log().Trace("Received helper trie proof response") 253 var resp struct { 254 ReqID, BV uint64 255 Data HelperTrieResps 256 } 257 if err := msg.Decode(&resp); err != nil { 258 return errResp(ErrDecode, "msg %v: %v", msg, err) 259 } 260 p.fcServer.ReceivedReply(resp.ReqID, resp.BV) 261 p.answeredRequest(resp.ReqID) 262 deliverMsg = &Msg{ 263 MsgType: MsgHelperTrieProofs, 264 ReqID: resp.ReqID, 265 Obj: resp.Data, 266 } 267 case msg.Code == TxStatusMsg: 268 p.Log().Trace("Received tx status response") 269 var resp struct { 270 ReqID, BV uint64 271 Status []light.TxStatus 272 } 273 if err := msg.Decode(&resp); err != nil { 274 return errResp(ErrDecode, "msg %v: %v", msg, err) 275 } 276 p.fcServer.ReceivedReply(resp.ReqID, resp.BV) 277 p.answeredRequest(resp.ReqID) 278 deliverMsg = &Msg{ 279 MsgType: MsgTxStatus, 280 ReqID: resp.ReqID, 281 Obj: resp.Status, 282 } 283 case msg.Code == StopMsg && p.version >= lpv3: 284 p.freeze() 285 h.backend.retriever.frozen(p) 286 p.Log().Debug("Service stopped") 287 case msg.Code == ResumeMsg && p.version >= lpv3: 288 var bv uint64 289 if err := msg.Decode(&bv); err != nil { 290 return errResp(ErrDecode, "msg %v: %v", msg, err) 291 } 292 p.fcServer.ResumeFreeze(bv) 293 p.unfreeze() 294 p.Log().Debug("Service resumed") 295 default: 296 p.Log().Trace("Received invalid message", "code", msg.Code) 297 return errResp(ErrInvalidMsgCode, "%v", msg.Code) 298 } 299 // Deliver the received response to retriever. 300 if deliverMsg != nil { 301 if err := h.backend.retriever.deliver(p, deliverMsg); err != nil { 302 if val := p.errCount.Add(1, mclock.Now()); val > maxResponseErrors { 303 return err 304 } 305 } 306 } 307 return nil 308 }