github.com/DxChainNetwork/dxc@v0.8.1-0.20220824085222-1162e304b6e7/eth/protocols/eth/handlers.go (about) 1 // Copyright 2020 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 eth 18 19 import ( 20 "encoding/json" 21 "fmt" 22 23 "github.com/DxChainNetwork/dxc/common" 24 "github.com/DxChainNetwork/dxc/core/types" 25 "github.com/DxChainNetwork/dxc/log" 26 "github.com/DxChainNetwork/dxc/rlp" 27 "github.com/DxChainNetwork/dxc/trie" 28 ) 29 30 // handleGetBlockHeaders handles Block header query, collect the requested headers and reply 31 func handleGetBlockHeaders(backend Backend, msg Decoder, peer *Peer) error { 32 // Decode the complex header query 33 var query GetBlockHeadersPacket 34 if err := msg.Decode(&query); err != nil { 35 return fmt.Errorf("%w: message %v: %v", errDecode, msg, err) 36 } 37 response := answerGetBlockHeadersQuery(backend, &query, peer) 38 return peer.SendBlockHeaders(response) 39 } 40 41 // handleGetBlockHeaders66 is the eth/66 version of handleGetBlockHeaders 42 func handleGetBlockHeaders66(backend Backend, msg Decoder, peer *Peer) error { 43 // Decode the complex header query 44 var query GetBlockHeadersPacket66 45 if err := msg.Decode(&query); err != nil { 46 return fmt.Errorf("%w: message %v: %v", errDecode, msg, err) 47 } 48 response := answerGetBlockHeadersQuery(backend, query.GetBlockHeadersPacket, peer) 49 return peer.ReplyBlockHeaders(query.RequestId, response) 50 } 51 52 func answerGetBlockHeadersQuery(backend Backend, query *GetBlockHeadersPacket, peer *Peer) []*types.Header { 53 hashMode := query.Origin.Hash != (common.Hash{}) 54 first := true 55 maxNonCanonical := uint64(100) 56 57 // Gather headers until the fetch or network limits is reached 58 var ( 59 bytes common.StorageSize 60 headers []*types.Header 61 unknown bool 62 lookups int 63 ) 64 for !unknown && len(headers) < int(query.Amount) && bytes < softResponseLimit && 65 len(headers) < maxHeadersServe && lookups < 2*maxHeadersServe { 66 lookups++ 67 // Retrieve the next header satisfying the query 68 var origin *types.Header 69 if hashMode { 70 if first { 71 first = false 72 origin = backend.Chain().GetHeaderByHash(query.Origin.Hash) 73 if origin != nil { 74 query.Origin.Number = origin.Number.Uint64() 75 } 76 } else { 77 origin = backend.Chain().GetHeader(query.Origin.Hash, query.Origin.Number) 78 } 79 } else { 80 origin = backend.Chain().GetHeaderByNumber(query.Origin.Number) 81 } 82 if origin == nil { 83 break 84 } 85 headers = append(headers, origin) 86 bytes += estHeaderSize 87 88 // Advance to the next header of the query 89 switch { 90 case hashMode && query.Reverse: 91 // Hash based traversal towards the genesis block 92 ancestor := query.Skip + 1 93 if ancestor == 0 { 94 unknown = true 95 } else { 96 query.Origin.Hash, query.Origin.Number = backend.Chain().GetAncestor(query.Origin.Hash, query.Origin.Number, ancestor, &maxNonCanonical) 97 unknown = (query.Origin.Hash == common.Hash{}) 98 } 99 case hashMode && !query.Reverse: 100 // Hash based traversal towards the leaf block 101 var ( 102 current = origin.Number.Uint64() 103 next = current + query.Skip + 1 104 ) 105 if next <= current { 106 infos, _ := json.MarshalIndent(peer.Peer.Info(), "", " ") 107 peer.Log().Warn("GetBlockHeaders skip overflow attack", "current", current, "skip", query.Skip, "next", next, "attacker", infos) 108 unknown = true 109 } else { 110 if header := backend.Chain().GetHeaderByNumber(next); header != nil { 111 nextHash := header.Hash() 112 expOldHash, _ := backend.Chain().GetAncestor(nextHash, next, query.Skip+1, &maxNonCanonical) 113 if expOldHash == query.Origin.Hash { 114 query.Origin.Hash, query.Origin.Number = nextHash, next 115 } else { 116 unknown = true 117 } 118 } else { 119 unknown = true 120 } 121 } 122 case query.Reverse: 123 // Number based traversal towards the genesis block 124 if query.Origin.Number >= query.Skip+1 { 125 query.Origin.Number -= query.Skip + 1 126 } else { 127 unknown = true 128 } 129 130 case !query.Reverse: 131 // Number based traversal towards the leaf block 132 query.Origin.Number += query.Skip + 1 133 } 134 } 135 return headers 136 } 137 138 func handleGetBlockBodies(backend Backend, msg Decoder, peer *Peer) error { 139 // Decode the block body retrieval message 140 var query GetBlockBodiesPacket 141 if err := msg.Decode(&query); err != nil { 142 return fmt.Errorf("%w: message %v: %v", errDecode, msg, err) 143 } 144 response := answerGetBlockBodiesQuery(backend, query, peer) 145 return peer.SendBlockBodiesRLP(response) 146 } 147 148 func handleGetBlockBodies66(backend Backend, msg Decoder, peer *Peer) error { 149 // Decode the block body retrieval message 150 var query GetBlockBodiesPacket66 151 if err := msg.Decode(&query); err != nil { 152 return fmt.Errorf("%w: message %v: %v", errDecode, msg, err) 153 } 154 response := answerGetBlockBodiesQuery(backend, query.GetBlockBodiesPacket, peer) 155 return peer.ReplyBlockBodiesRLP(query.RequestId, response) 156 } 157 158 func answerGetBlockBodiesQuery(backend Backend, query GetBlockBodiesPacket, peer *Peer) []rlp.RawValue { 159 // Gather blocks until the fetch or network limits is reached 160 var ( 161 bytes int 162 bodies []rlp.RawValue 163 ) 164 for lookups, hash := range query { 165 if bytes >= softResponseLimit || len(bodies) >= maxBodiesServe || 166 lookups >= 2*maxBodiesServe { 167 break 168 } 169 if data := backend.Chain().GetBodyRLP(hash); len(data) != 0 { 170 bodies = append(bodies, data) 171 bytes += len(data) 172 } 173 } 174 return bodies 175 } 176 177 func handleGetNodeData(backend Backend, msg Decoder, peer *Peer) error { 178 // Decode the trie node data retrieval message 179 var query GetNodeDataPacket 180 if err := msg.Decode(&query); err != nil { 181 return fmt.Errorf("%w: message %v: %v", errDecode, msg, err) 182 } 183 response := answerGetNodeDataQuery(backend, query, peer) 184 return peer.SendNodeData(response) 185 } 186 187 func handleGetNodeData66(backend Backend, msg Decoder, peer *Peer) error { 188 // Decode the trie node data retrieval message 189 var query GetNodeDataPacket66 190 if err := msg.Decode(&query); err != nil { 191 return fmt.Errorf("%w: message %v: %v", errDecode, msg, err) 192 } 193 response := answerGetNodeDataQuery(backend, query.GetNodeDataPacket, peer) 194 return peer.ReplyNodeData(query.RequestId, response) 195 } 196 197 func answerGetNodeDataQuery(backend Backend, query GetNodeDataPacket, peer *Peer) [][]byte { 198 // Gather state data until the fetch or network limits is reached 199 var ( 200 bytes int 201 nodes [][]byte 202 ) 203 for lookups, hash := range query { 204 if bytes >= softResponseLimit || len(nodes) >= maxNodeDataServe || 205 lookups >= 2*maxNodeDataServe { 206 break 207 } 208 // Retrieve the requested state entry 209 if bloom := backend.StateBloom(); bloom != nil && !bloom.Contains(hash[:]) { 210 // Only lookup the trie node if there's chance that we actually have it 211 continue 212 } 213 entry, err := backend.Chain().TrieNode(hash) 214 if len(entry) == 0 || err != nil { 215 // Read the contract code with prefix only to save unnecessary lookups. 216 entry, err = backend.Chain().ContractCodeWithPrefix(hash) 217 } 218 if err == nil && len(entry) > 0 { 219 nodes = append(nodes, entry) 220 bytes += len(entry) 221 } 222 } 223 return nodes 224 } 225 226 func handleGetReceipts(backend Backend, msg Decoder, peer *Peer) error { 227 // Decode the block receipts retrieval message 228 var query GetReceiptsPacket 229 if err := msg.Decode(&query); err != nil { 230 return fmt.Errorf("%w: message %v: %v", errDecode, msg, err) 231 } 232 response := answerGetReceiptsQuery(backend, query, peer) 233 return peer.SendReceiptsRLP(response) 234 } 235 236 func handleGetReceipts66(backend Backend, msg Decoder, peer *Peer) error { 237 // Decode the block receipts retrieval message 238 var query GetReceiptsPacket66 239 if err := msg.Decode(&query); err != nil { 240 return fmt.Errorf("%w: message %v: %v", errDecode, msg, err) 241 } 242 response := answerGetReceiptsQuery(backend, query.GetReceiptsPacket, peer) 243 return peer.ReplyReceiptsRLP(query.RequestId, response) 244 } 245 246 func answerGetReceiptsQuery(backend Backend, query GetReceiptsPacket, peer *Peer) []rlp.RawValue { 247 // Gather state data until the fetch or network limits is reached 248 var ( 249 bytes int 250 receipts []rlp.RawValue 251 ) 252 for lookups, hash := range query { 253 if bytes >= softResponseLimit || len(receipts) >= maxReceiptsServe || 254 lookups >= 2*maxReceiptsServe { 255 break 256 } 257 // Retrieve the requested block's receipts 258 results := backend.Chain().GetReceiptsByHash(hash) 259 if results == nil { 260 if header := backend.Chain().GetHeaderByHash(hash); header == nil || header.ReceiptHash != types.EmptyRootHash { 261 continue 262 } 263 } 264 // If known, encode and queue for response packet 265 if encoded, err := rlp.EncodeToBytes(results); err != nil { 266 log.Error("Failed to encode receipt", "err", err) 267 } else { 268 receipts = append(receipts, encoded) 269 bytes += len(encoded) 270 } 271 } 272 return receipts 273 } 274 275 func handleNewBlockhashes(backend Backend, msg Decoder, peer *Peer) error { 276 // A batch of new block announcements just arrived 277 ann := new(NewBlockHashesPacket) 278 if err := msg.Decode(ann); err != nil { 279 return fmt.Errorf("%w: message %v: %v", errDecode, msg, err) 280 } 281 // Mark the hashes as present at the remote node 282 for _, block := range *ann { 283 peer.markBlock(block.Hash) 284 } 285 // Deliver them all to the backend for queuing 286 return backend.Handle(peer, ann) 287 } 288 289 func handleNewBlock(backend Backend, msg Decoder, peer *Peer) error { 290 // Retrieve and decode the propagated block 291 ann := new(NewBlockPacket) 292 if err := msg.Decode(ann); err != nil { 293 return fmt.Errorf("%w: message %v: %v", errDecode, msg, err) 294 } 295 if err := ann.sanityCheck(); err != nil { 296 return err 297 } 298 if hash := types.CalcUncleHash(ann.Block.Uncles()); hash != ann.Block.UncleHash() { 299 log.Warn("Propagated block has invalid uncles", "have", hash, "exp", ann.Block.UncleHash()) 300 return nil // TODO(karalabe): return error eventually, but wait a few releases 301 } 302 if hash := types.DeriveSha(ann.Block.Transactions(), trie.NewStackTrie(nil)); hash != ann.Block.TxHash() { 303 log.Warn("Propagated block has invalid body", "have", hash, "exp", ann.Block.TxHash()) 304 return nil // TODO(karalabe): return error eventually, but wait a few releases 305 } 306 ann.Block.ReceivedAt = msg.Time() 307 ann.Block.ReceivedFrom = peer 308 309 // Mark the peer as owning the block 310 peer.markBlock(ann.Block.Hash()) 311 312 return backend.Handle(peer, ann) 313 } 314 315 func handleBlockHeaders(backend Backend, msg Decoder, peer *Peer) error { 316 // A batch of headers arrived to one of our previous requests 317 res := new(BlockHeadersPacket) 318 if err := msg.Decode(res); err != nil { 319 return fmt.Errorf("%w: message %v: %v", errDecode, msg, err) 320 } 321 return backend.Handle(peer, res) 322 } 323 324 func handleBlockHeaders66(backend Backend, msg Decoder, peer *Peer) error { 325 // A batch of headers arrived to one of our previous requests 326 res := new(BlockHeadersPacket66) 327 if err := msg.Decode(res); err != nil { 328 return fmt.Errorf("%w: message %v: %v", errDecode, msg, err) 329 } 330 requestTracker.Fulfil(peer.id, peer.version, BlockHeadersMsg, res.RequestId) 331 332 return backend.Handle(peer, &res.BlockHeadersPacket) 333 } 334 335 func handleBlockBodies(backend Backend, msg Decoder, peer *Peer) error { 336 // A batch of block bodies arrived to one of our previous requests 337 res := new(BlockBodiesPacket) 338 if err := msg.Decode(res); err != nil { 339 return fmt.Errorf("%w: message %v: %v", errDecode, msg, err) 340 } 341 return backend.Handle(peer, res) 342 } 343 344 func handleBlockBodies66(backend Backend, msg Decoder, peer *Peer) error { 345 // A batch of block bodies arrived to one of our previous requests 346 res := new(BlockBodiesPacket66) 347 if err := msg.Decode(res); err != nil { 348 return fmt.Errorf("%w: message %v: %v", errDecode, msg, err) 349 } 350 requestTracker.Fulfil(peer.id, peer.version, BlockBodiesMsg, res.RequestId) 351 352 return backend.Handle(peer, &res.BlockBodiesPacket) 353 } 354 355 func handleNodeData(backend Backend, msg Decoder, peer *Peer) error { 356 // A batch of node state data arrived to one of our previous requests 357 res := new(NodeDataPacket) 358 if err := msg.Decode(res); err != nil { 359 return fmt.Errorf("%w: message %v: %v", errDecode, msg, err) 360 } 361 return backend.Handle(peer, res) 362 } 363 364 func handleNodeData66(backend Backend, msg Decoder, peer *Peer) error { 365 // A batch of node state data arrived to one of our previous requests 366 res := new(NodeDataPacket66) 367 if err := msg.Decode(res); err != nil { 368 return fmt.Errorf("%w: message %v: %v", errDecode, msg, err) 369 } 370 requestTracker.Fulfil(peer.id, peer.version, NodeDataMsg, res.RequestId) 371 372 return backend.Handle(peer, &res.NodeDataPacket) 373 } 374 375 func handleReceipts(backend Backend, msg Decoder, peer *Peer) error { 376 // A batch of receipts arrived to one of our previous requests 377 res := new(ReceiptsPacket) 378 if err := msg.Decode(res); err != nil { 379 return fmt.Errorf("%w: message %v: %v", errDecode, msg, err) 380 } 381 return backend.Handle(peer, res) 382 } 383 384 func handleReceipts66(backend Backend, msg Decoder, peer *Peer) error { 385 // A batch of receipts arrived to one of our previous requests 386 res := new(ReceiptsPacket66) 387 if err := msg.Decode(res); err != nil { 388 return fmt.Errorf("%w: message %v: %v", errDecode, msg, err) 389 } 390 requestTracker.Fulfil(peer.id, peer.version, ReceiptsMsg, res.RequestId) 391 392 return backend.Handle(peer, &res.ReceiptsPacket) 393 } 394 395 func handleNewPooledTransactionHashes(backend Backend, msg Decoder, peer *Peer) error { 396 // New transaction announcement arrived, make sure we have 397 // a valid and fresh chain to handle them 398 if !backend.AcceptTxs() { 399 return nil 400 } 401 ann := new(NewPooledTransactionHashesPacket) 402 if err := msg.Decode(ann); err != nil { 403 return fmt.Errorf("%w: message %v: %v", errDecode, msg, err) 404 } 405 // Schedule all the unknown hashes for retrieval 406 for _, hash := range *ann { 407 peer.markTransaction(hash) 408 } 409 return backend.Handle(peer, ann) 410 } 411 412 func handleGetPooledTransactions(backend Backend, msg Decoder, peer *Peer) error { 413 // Decode the pooled transactions retrieval message 414 var query GetPooledTransactionsPacket 415 if err := msg.Decode(&query); err != nil { 416 return fmt.Errorf("%w: message %v: %v", errDecode, msg, err) 417 } 418 hashes, txs := answerGetPooledTransactions(backend, query, peer) 419 return peer.SendPooledTransactionsRLP(hashes, txs) 420 } 421 422 func handleGetPooledTransactions66(backend Backend, msg Decoder, peer *Peer) error { 423 // Decode the pooled transactions retrieval message 424 var query GetPooledTransactionsPacket66 425 if err := msg.Decode(&query); err != nil { 426 return fmt.Errorf("%w: message %v: %v", errDecode, msg, err) 427 } 428 hashes, txs := answerGetPooledTransactions(backend, query.GetPooledTransactionsPacket, peer) 429 return peer.ReplyPooledTransactionsRLP(query.RequestId, hashes, txs) 430 } 431 432 func answerGetPooledTransactions(backend Backend, query GetPooledTransactionsPacket, peer *Peer) ([]common.Hash, []rlp.RawValue) { 433 // Gather transactions until the fetch or network limits is reached 434 var ( 435 bytes int 436 hashes []common.Hash 437 txs []rlp.RawValue 438 ) 439 for _, hash := range query { 440 if bytes >= softResponseLimit { 441 break 442 } 443 // Retrieve the requested transaction, skipping if unknown to us 444 tx := backend.TxPool().Get(hash) 445 if tx == nil { 446 continue 447 } 448 // If known, encode and queue for response packet 449 if encoded, err := rlp.EncodeToBytes(tx); err != nil { 450 log.Error("Failed to encode transaction", "err", err) 451 } else { 452 hashes = append(hashes, hash) 453 txs = append(txs, encoded) 454 bytes += len(encoded) 455 } 456 } 457 return hashes, txs 458 } 459 460 func handleTransactions(backend Backend, msg Decoder, peer *Peer) error { 461 // Transactions arrived, make sure we have a valid and fresh chain to handle them 462 if !backend.AcceptTxs() { 463 return nil 464 } 465 // Transactions can be processed, parse all of them and deliver to the pool 466 var txs TransactionsPacket 467 if err := msg.Decode(&txs); err != nil { 468 return fmt.Errorf("%w: message %v: %v", errDecode, msg, err) 469 } 470 for i, tx := range txs { 471 // Validate and mark the remote transaction 472 if tx == nil { 473 return fmt.Errorf("%w: transaction %d is nil", errDecode, i) 474 } 475 peer.markTransaction(tx.Hash()) 476 } 477 return backend.Handle(peer, &txs) 478 } 479 480 func handlePooledTransactions(backend Backend, msg Decoder, peer *Peer) error { 481 // Transactions arrived, make sure we have a valid and fresh chain to handle them 482 if !backend.AcceptTxs() { 483 return nil 484 } 485 // Transactions can be processed, parse all of them and deliver to the pool 486 var txs PooledTransactionsPacket 487 if err := msg.Decode(&txs); err != nil { 488 return fmt.Errorf("%w: message %v: %v", errDecode, msg, err) 489 } 490 for i, tx := range txs { 491 // Validate and mark the remote transaction 492 if tx == nil { 493 return fmt.Errorf("%w: transaction %d is nil", errDecode, i) 494 } 495 peer.markTransaction(tx.Hash()) 496 } 497 return backend.Handle(peer, &txs) 498 } 499 500 func handlePooledTransactions66(backend Backend, msg Decoder, peer *Peer) error { 501 // Transactions arrived, make sure we have a valid and fresh chain to handle them 502 if !backend.AcceptTxs() { 503 return nil 504 } 505 // Transactions can be processed, parse all of them and deliver to the pool 506 var txs PooledTransactionsPacket66 507 if err := msg.Decode(&txs); err != nil { 508 return fmt.Errorf("%w: message %v: %v", errDecode, msg, err) 509 } 510 for i, tx := range txs.PooledTransactionsPacket { 511 // Validate and mark the remote transaction 512 if tx == nil { 513 return fmt.Errorf("%w: transaction %d is nil", errDecode, i) 514 } 515 peer.markTransaction(tx.Hash()) 516 } 517 requestTracker.Fulfil(peer.id, peer.version, PooledTransactionsMsg, txs.RequestId) 518 519 return backend.Handle(peer, &txs.PooledTransactionsPacket) 520 }