gitee.com/liu-zhao234568/cntest@v1.0.0/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 "context" 21 "math/big" 22 "math/rand" 23 "sync" 24 "sync/atomic" 25 "time" 26 27 "gitee.com/liu-zhao234568/cntest/common" 28 "gitee.com/liu-zhao234568/cntest/common/mclock" 29 "gitee.com/liu-zhao234568/cntest/core/forkid" 30 "gitee.com/liu-zhao234568/cntest/core/types" 31 "gitee.com/liu-zhao234568/cntest/eth/downloader" 32 "gitee.com/liu-zhao234568/cntest/eth/protocols/eth" 33 "gitee.com/liu-zhao234568/cntest/light" 34 "gitee.com/liu-zhao234568/cntest/log" 35 "gitee.com/liu-zhao234568/cntest/p2p" 36 "gitee.com/liu-zhao234568/cntest/params" 37 ) 38 39 // clientHandler is responsible for receiving and processing all incoming server 40 // responses. 41 type clientHandler struct { 42 ulc *ulc 43 forkFilter forkid.Filter 44 checkpoint *params.TrustedCheckpoint 45 fetcher *lightFetcher 46 downloader *downloader.Downloader 47 backend *LightEthereum 48 49 closeCh chan struct{} 50 wg sync.WaitGroup // WaitGroup used to track all connected peers. 51 52 // Hooks used in the testing 53 syncStart func(header *types.Header) // Hook called when the syncing is started 54 syncEnd func(header *types.Header) // Hook called when the syncing is done 55 } 56 57 func newClientHandler(ulcServers []string, ulcFraction int, checkpoint *params.TrustedCheckpoint, backend *LightEthereum) *clientHandler { 58 handler := &clientHandler{ 59 forkFilter: forkid.NewFilter(backend.blockchain), 60 checkpoint: checkpoint, 61 backend: backend, 62 closeCh: make(chan struct{}), 63 } 64 if ulcServers != nil { 65 ulc, err := newULC(ulcServers, ulcFraction) 66 if err != nil { 67 log.Error("Failed to initialize ultra light client") 68 } 69 handler.ulc = ulc 70 log.Info("Enable ultra light client mode") 71 } 72 var height uint64 73 if checkpoint != nil { 74 height = (checkpoint.SectionIndex+1)*params.CHTFrequency - 1 75 } 76 handler.fetcher = newLightFetcher(backend.blockchain, backend.engine, backend.peers, handler.ulc, backend.chainDb, backend.reqDist, handler.synchronise) 77 handler.downloader = downloader.New(height, backend.chainDb, nil, backend.eventMux, nil, backend.blockchain, handler.removePeer) 78 handler.backend.peers.subscribe((*downloaderPeerNotify)(handler)) 79 return handler 80 } 81 82 func (h *clientHandler) start() { 83 h.fetcher.start() 84 } 85 86 func (h *clientHandler) stop() { 87 close(h.closeCh) 88 h.downloader.Terminate() 89 h.fetcher.stop() 90 h.wg.Wait() 91 } 92 93 // runPeer is the p2p protocol run function for the given version. 94 func (h *clientHandler) runPeer(version uint, p *p2p.Peer, rw p2p.MsgReadWriter) error { 95 trusted := false 96 if h.ulc != nil { 97 trusted = h.ulc.trusted(p.ID()) 98 } 99 peer := newServerPeer(int(version), h.backend.config.NetworkId, trusted, p, newMeteredMsgWriter(rw, int(version))) 100 defer peer.close() 101 h.wg.Add(1) 102 defer h.wg.Done() 103 err := h.handle(peer) 104 return err 105 } 106 107 func (h *clientHandler) handle(p *serverPeer) error { 108 if h.backend.peers.len() >= h.backend.config.LightPeers && !p.Peer.Info().Network.Trusted { 109 return p2p.DiscTooManyPeers 110 } 111 p.Log().Debug("Light Ethereum peer connected", "name", p.Name()) 112 113 // Execute the LES handshake 114 forkid := forkid.NewID(h.backend.blockchain.Config(), h.backend.genesis, h.backend.blockchain.CurrentHeader().Number.Uint64()) 115 if err := p.Handshake(h.backend.blockchain.Genesis().Hash(), forkid, h.forkFilter); err != nil { 116 p.Log().Debug("Light Ethereum handshake failed", "err", err) 117 return err 118 } 119 // Register peer with the server pool 120 if h.backend.serverPool != nil { 121 if nvt, err := h.backend.serverPool.RegisterNode(p.Node()); err == nil { 122 p.setValueTracker(nvt) 123 p.updateVtParams() 124 defer func() { 125 p.setValueTracker(nil) 126 h.backend.serverPool.UnregisterNode(p.Node()) 127 }() 128 } else { 129 return err 130 } 131 } 132 // Register the peer locally 133 if err := h.backend.peers.register(p); err != nil { 134 p.Log().Error("Light Ethereum peer registration failed", "err", err) 135 return err 136 } 137 138 serverConnectionGauge.Update(int64(h.backend.peers.len())) 139 140 connectedAt := mclock.Now() 141 defer func() { 142 h.backend.peers.unregister(p.id) 143 connectionTimer.Update(time.Duration(mclock.Now() - connectedAt)) 144 serverConnectionGauge.Update(int64(h.backend.peers.len())) 145 }() 146 h.fetcher.announce(p, &announceData{Hash: p.headInfo.Hash, Number: p.headInfo.Number, Td: p.headInfo.Td}) 147 148 // Mark the peer starts to be served. 149 atomic.StoreUint32(&p.serving, 1) 150 defer atomic.StoreUint32(&p.serving, 0) 151 152 // Spawn a main loop to handle all incoming messages. 153 for { 154 if err := h.handleMsg(p); err != nil { 155 p.Log().Debug("Light Ethereum message handling failed", "err", err) 156 p.fcServer.DumpLogs() 157 return err 158 } 159 } 160 } 161 162 // handleMsg is invoked whenever an inbound message is received from a remote 163 // peer. The remote connection is torn down upon returning any error. 164 func (h *clientHandler) handleMsg(p *serverPeer) error { 165 // Read the next message from the remote peer, and ensure it's fully consumed 166 msg, err := p.rw.ReadMsg() 167 if err != nil { 168 return err 169 } 170 p.Log().Trace("Light Ethereum message arrived", "code", msg.Code, "bytes", msg.Size) 171 172 if msg.Size > ProtocolMaxMsgSize { 173 return errResp(ErrMsgTooLarge, "%v > %v", msg.Size, ProtocolMaxMsgSize) 174 } 175 defer msg.Discard() 176 177 var deliverMsg *Msg 178 179 // Handle the message depending on its contents 180 switch { 181 case msg.Code == AnnounceMsg: 182 p.Log().Trace("Received announce message") 183 var req announceData 184 if err := msg.Decode(&req); err != nil { 185 return errResp(ErrDecode, "%v: %v", msg, err) 186 } 187 if err := req.sanityCheck(); err != nil { 188 return err 189 } 190 update, size := req.Update.decode() 191 if p.rejectUpdate(size) { 192 return errResp(ErrRequestRejected, "") 193 } 194 p.updateFlowControl(update) 195 p.updateVtParams() 196 197 if req.Hash != (common.Hash{}) { 198 if p.announceType == announceTypeNone { 199 return errResp(ErrUnexpectedResponse, "") 200 } 201 if p.announceType == announceTypeSigned { 202 if err := req.checkSignature(p.ID(), update); err != nil { 203 p.Log().Trace("Invalid announcement signature", "err", err) 204 return err 205 } 206 p.Log().Trace("Valid announcement signature") 207 } 208 p.Log().Trace("Announce message content", "number", req.Number, "hash", req.Hash, "td", req.Td, "reorg", req.ReorgDepth) 209 210 // Update peer head information first and then notify the announcement 211 p.updateHead(req.Hash, req.Number, req.Td) 212 h.fetcher.announce(p, &req) 213 } 214 case msg.Code == BlockHeadersMsg: 215 p.Log().Trace("Received block header response message") 216 var resp struct { 217 ReqID, BV uint64 218 Headers []*types.Header 219 } 220 if err := msg.Decode(&resp); err != nil { 221 return errResp(ErrDecode, "msg %v: %v", msg, err) 222 } 223 headers := resp.Headers 224 p.fcServer.ReceivedReply(resp.ReqID, resp.BV) 225 p.answeredRequest(resp.ReqID) 226 227 // Filter out the explicitly requested header by the retriever 228 if h.backend.retriever.requested(resp.ReqID) { 229 deliverMsg = &Msg{ 230 MsgType: MsgBlockHeaders, 231 ReqID: resp.ReqID, 232 Obj: resp.Headers, 233 } 234 } else { 235 // Filter out any explicitly requested headers, deliver the rest to the downloader 236 filter := len(headers) == 1 237 if filter { 238 headers = h.fetcher.deliverHeaders(p, resp.ReqID, resp.Headers) 239 } 240 if len(headers) != 0 || !filter { 241 if err := h.downloader.DeliverHeaders(p.id, headers); err != nil { 242 log.Debug("Failed to deliver headers", "err", err) 243 } 244 } 245 } 246 case msg.Code == BlockBodiesMsg: 247 p.Log().Trace("Received block bodies response") 248 var resp struct { 249 ReqID, BV uint64 250 Data []*types.Body 251 } 252 if err := msg.Decode(&resp); err != nil { 253 return errResp(ErrDecode, "msg %v: %v", msg, err) 254 } 255 p.fcServer.ReceivedReply(resp.ReqID, resp.BV) 256 p.answeredRequest(resp.ReqID) 257 deliverMsg = &Msg{ 258 MsgType: MsgBlockBodies, 259 ReqID: resp.ReqID, 260 Obj: resp.Data, 261 } 262 case msg.Code == CodeMsg: 263 p.Log().Trace("Received code response") 264 var resp struct { 265 ReqID, BV uint64 266 Data [][]byte 267 } 268 if err := msg.Decode(&resp); err != nil { 269 return errResp(ErrDecode, "msg %v: %v", msg, err) 270 } 271 p.fcServer.ReceivedReply(resp.ReqID, resp.BV) 272 p.answeredRequest(resp.ReqID) 273 deliverMsg = &Msg{ 274 MsgType: MsgCode, 275 ReqID: resp.ReqID, 276 Obj: resp.Data, 277 } 278 case msg.Code == ReceiptsMsg: 279 p.Log().Trace("Received receipts response") 280 var resp struct { 281 ReqID, BV uint64 282 Receipts []types.Receipts 283 } 284 if err := msg.Decode(&resp); err != nil { 285 return errResp(ErrDecode, "msg %v: %v", msg, err) 286 } 287 p.fcServer.ReceivedReply(resp.ReqID, resp.BV) 288 p.answeredRequest(resp.ReqID) 289 deliverMsg = &Msg{ 290 MsgType: MsgReceipts, 291 ReqID: resp.ReqID, 292 Obj: resp.Receipts, 293 } 294 case msg.Code == ProofsV2Msg: 295 p.Log().Trace("Received les/2 proofs response") 296 var resp struct { 297 ReqID, BV uint64 298 Data light.NodeList 299 } 300 if err := msg.Decode(&resp); err != nil { 301 return errResp(ErrDecode, "msg %v: %v", msg, err) 302 } 303 p.fcServer.ReceivedReply(resp.ReqID, resp.BV) 304 p.answeredRequest(resp.ReqID) 305 deliverMsg = &Msg{ 306 MsgType: MsgProofsV2, 307 ReqID: resp.ReqID, 308 Obj: resp.Data, 309 } 310 case msg.Code == HelperTrieProofsMsg: 311 p.Log().Trace("Received helper trie proof response") 312 var resp struct { 313 ReqID, BV uint64 314 Data HelperTrieResps 315 } 316 if err := msg.Decode(&resp); err != nil { 317 return errResp(ErrDecode, "msg %v: %v", msg, err) 318 } 319 p.fcServer.ReceivedReply(resp.ReqID, resp.BV) 320 p.answeredRequest(resp.ReqID) 321 deliverMsg = &Msg{ 322 MsgType: MsgHelperTrieProofs, 323 ReqID: resp.ReqID, 324 Obj: resp.Data, 325 } 326 case msg.Code == TxStatusMsg: 327 p.Log().Trace("Received tx status response") 328 var resp struct { 329 ReqID, BV uint64 330 Status []light.TxStatus 331 } 332 if err := msg.Decode(&resp); err != nil { 333 return errResp(ErrDecode, "msg %v: %v", msg, err) 334 } 335 p.fcServer.ReceivedReply(resp.ReqID, resp.BV) 336 p.answeredRequest(resp.ReqID) 337 deliverMsg = &Msg{ 338 MsgType: MsgTxStatus, 339 ReqID: resp.ReqID, 340 Obj: resp.Status, 341 } 342 case msg.Code == StopMsg && p.version >= lpv3: 343 p.freeze() 344 h.backend.retriever.frozen(p) 345 p.Log().Debug("Service stopped") 346 case msg.Code == ResumeMsg && p.version >= lpv3: 347 var bv uint64 348 if err := msg.Decode(&bv); err != nil { 349 return errResp(ErrDecode, "msg %v: %v", msg, err) 350 } 351 p.fcServer.ResumeFreeze(bv) 352 p.unfreeze() 353 p.Log().Debug("Service resumed") 354 default: 355 p.Log().Trace("Received invalid message", "code", msg.Code) 356 return errResp(ErrInvalidMsgCode, "%v", msg.Code) 357 } 358 // Deliver the received response to retriever. 359 if deliverMsg != nil { 360 if err := h.backend.retriever.deliver(p, deliverMsg); err != nil { 361 if val := p.errCount.Add(1, mclock.Now()); val > maxResponseErrors { 362 return err 363 } 364 } 365 } 366 return nil 367 } 368 369 func (h *clientHandler) removePeer(id string) { 370 h.backend.peers.unregister(id) 371 } 372 373 type peerConnection struct { 374 handler *clientHandler 375 peer *serverPeer 376 } 377 378 func (pc *peerConnection) Head() (common.Hash, *big.Int) { 379 return pc.peer.HeadAndTd() 380 } 381 382 func (pc *peerConnection) RequestHeadersByHash(origin common.Hash, amount int, skip int, reverse bool) error { 383 rq := &distReq{ 384 getCost: func(dp distPeer) uint64 { 385 peer := dp.(*serverPeer) 386 return peer.getRequestCost(GetBlockHeadersMsg, amount) 387 }, 388 canSend: func(dp distPeer) bool { 389 return dp.(*serverPeer) == pc.peer 390 }, 391 request: func(dp distPeer) func() { 392 reqID := rand.Uint64() 393 peer := dp.(*serverPeer) 394 cost := peer.getRequestCost(GetBlockHeadersMsg, amount) 395 peer.fcServer.QueuedRequest(reqID, cost) 396 return func() { peer.requestHeadersByHash(reqID, origin, amount, skip, reverse) } 397 }, 398 } 399 _, ok := <-pc.handler.backend.reqDist.queue(rq) 400 if !ok { 401 return light.ErrNoPeers 402 } 403 return nil 404 } 405 406 func (pc *peerConnection) RequestHeadersByNumber(origin uint64, amount int, skip int, reverse bool) error { 407 rq := &distReq{ 408 getCost: func(dp distPeer) uint64 { 409 peer := dp.(*serverPeer) 410 return peer.getRequestCost(GetBlockHeadersMsg, amount) 411 }, 412 canSend: func(dp distPeer) bool { 413 return dp.(*serverPeer) == pc.peer 414 }, 415 request: func(dp distPeer) func() { 416 reqID := rand.Uint64() 417 peer := dp.(*serverPeer) 418 cost := peer.getRequestCost(GetBlockHeadersMsg, amount) 419 peer.fcServer.QueuedRequest(reqID, cost) 420 return func() { peer.requestHeadersByNumber(reqID, origin, amount, skip, reverse) } 421 }, 422 } 423 _, ok := <-pc.handler.backend.reqDist.queue(rq) 424 if !ok { 425 return light.ErrNoPeers 426 } 427 return nil 428 } 429 430 // RetrieveSingleHeaderByNumber requests a single header by the specified block 431 // number. This function will wait the response until it's timeout or delivered. 432 func (pc *peerConnection) RetrieveSingleHeaderByNumber(context context.Context, number uint64) (*types.Header, error) { 433 reqID := rand.Uint64() 434 rq := &distReq{ 435 getCost: func(dp distPeer) uint64 { 436 peer := dp.(*serverPeer) 437 return peer.getRequestCost(GetBlockHeadersMsg, 1) 438 }, 439 canSend: func(dp distPeer) bool { 440 return dp.(*serverPeer) == pc.peer 441 }, 442 request: func(dp distPeer) func() { 443 peer := dp.(*serverPeer) 444 cost := peer.getRequestCost(GetBlockHeadersMsg, 1) 445 peer.fcServer.QueuedRequest(reqID, cost) 446 return func() { peer.requestHeadersByNumber(reqID, number, 1, 0, false) } 447 }, 448 } 449 var header *types.Header 450 if err := pc.handler.backend.retriever.retrieve(context, reqID, rq, func(peer distPeer, msg *Msg) error { 451 if msg.MsgType != MsgBlockHeaders { 452 return errInvalidMessageType 453 } 454 headers := msg.Obj.([]*types.Header) 455 if len(headers) != 1 { 456 return errInvalidEntryCount 457 } 458 header = headers[0] 459 return nil 460 }, nil); err != nil { 461 return nil, err 462 } 463 return header, nil 464 } 465 466 // downloaderPeerNotify implements peerSetNotify 467 type downloaderPeerNotify clientHandler 468 469 func (d *downloaderPeerNotify) registerPeer(p *serverPeer) { 470 h := (*clientHandler)(d) 471 pc := &peerConnection{ 472 handler: h, 473 peer: p, 474 } 475 h.downloader.RegisterLightPeer(p.id, eth.ETH65, pc) 476 } 477 478 func (d *downloaderPeerNotify) unregisterPeer(p *serverPeer) { 479 h := (*clientHandler)(d) 480 h.downloader.UnregisterPeer(p.id) 481 }