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