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  }