github.com/intfoundation/intchain@v0.0.0-20220727031208-4316ad31ca73/intprotocol/protocol.go (about)

     1  // Copyright 2014 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 intprotocol
    18  
    19  import (
    20  	"fmt"
    21  	"io"
    22  	"math/big"
    23  
    24  	"github.com/intfoundation/intchain/common"
    25  	"github.com/intfoundation/intchain/core"
    26  	"github.com/intfoundation/intchain/core/types"
    27  	"github.com/intfoundation/intchain/event"
    28  	"github.com/intfoundation/intchain/rlp"
    29  )
    30  
    31  // Constants to match up protocol versions and messages
    32  const (
    33  	intprotocol63 = 63
    34  	intprotocol64 = 64
    35  	intprotocol65 = 65
    36  )
    37  
    38  // protocolName is the official short name of the protocol used during capability negotiation.
    39  const protocolName = "intprotocol"
    40  
    41  // ProtocolVersions are the supported versions of the eth protocol (first is primary).
    42  var ProtocolVersions = []uint{intprotocol65, intprotocol64, intprotocol63}
    43  
    44  // protocolLengths are the number of implemented message corresponding to different protocol versions.
    45  var protocolLengths = map[uint]uint64{intprotocol65: 17, intprotocol64: 17, intprotocol63: 17}
    46  
    47  const ProtocolMaxMsgSize = 10 * 1024 * 1024 // Maximum cap on the size of a protocol message
    48  
    49  // intprotocol protocol message codes
    50  const (
    51  	// Protocol messages belonging to intprotocol/62
    52  	StatusMsg          = 0x00
    53  	NewBlockHashesMsg  = 0x01
    54  	TxMsg              = 0x02
    55  	GetBlockHeadersMsg = 0x03
    56  	BlockHeadersMsg    = 0x04
    57  	GetBlockBodiesMsg  = 0x05
    58  	BlockBodiesMsg     = 0x06
    59  	NewBlockMsg        = 0x07
    60  
    61  	// Protocol messages belonging to intprotocol/63
    62  	GetNodeDataMsg = 0x0d
    63  	NodeDataMsg    = 0x0e
    64  	GetReceiptsMsg = 0x0f
    65  	ReceiptsMsg    = 0x10
    66  
    67  	// Protocol messages belonging to intchain
    68  	TX3ProofDataMsg = 0x18
    69  
    70  	GetPreImagesMsg = 0x19
    71  	PreImagesMsg    = 0x1a
    72  	TrieNodeDataMsg = 0x1b
    73  )
    74  
    75  type errCode int
    76  
    77  const (
    78  	ErrMsgTooLarge = iota
    79  	ErrDecode
    80  	ErrInvalidMsgCode
    81  	ErrProtocolVersionMismatch
    82  	ErrNetworkIdMismatch
    83  	ErrGenesisBlockMismatch
    84  	ErrNoStatusMsg
    85  	ErrExtraStatusMsg
    86  	ErrSuspendedPeer
    87  	ErrTX3ValidateFail
    88  )
    89  
    90  func (e errCode) String() string {
    91  	return errorToString[int(e)]
    92  }
    93  
    94  // XXX change once legacy code is out
    95  var errorToString = map[int]string{
    96  	ErrMsgTooLarge:             "Message too long",
    97  	ErrDecode:                  "Invalid message",
    98  	ErrInvalidMsgCode:          "Invalid message code",
    99  	ErrProtocolVersionMismatch: "Protocol version mismatch",
   100  	ErrNetworkIdMismatch:       "NetworkId mismatch",
   101  	ErrGenesisBlockMismatch:    "Genesis block mismatch",
   102  	ErrNoStatusMsg:             "No status message",
   103  	ErrExtraStatusMsg:          "Extra status message",
   104  	ErrSuspendedPeer:           "Suspended peer",
   105  	ErrTX3ValidateFail:         "TX3 validate fail",
   106  }
   107  
   108  type txPool interface {
   109  	// AddRemotes should add the given transactions to the pool.
   110  	AddRemotes([]*types.Transaction) []error
   111  
   112  	// Pending should return pending transactions.
   113  	// The slice should be modifiable by the caller.
   114  	Pending() (map[common.Address]types.Transactions, error)
   115  
   116  	// SubscribeTxPreEvent should return an event subscription of
   117  	// TxPreEvent and send events to the given channel.
   118  	SubscribeTxPreEvent(chan<- core.TxPreEvent) event.Subscription
   119  }
   120  
   121  // statusData is the network packet for the status message.
   122  type statusData struct {
   123  	ProtocolVersion uint32
   124  	NetworkId       uint64
   125  	TD              *big.Int
   126  	CurrentBlock    common.Hash
   127  	GenesisBlock    common.Hash
   128  }
   129  
   130  // newBlockHashesData is the network packet for the block announcements.
   131  type newBlockHashesData []struct {
   132  	Hash   common.Hash // Hash of one particular block being announced
   133  	Number uint64      // Number of one particular block being announced
   134  }
   135  
   136  // getBlockHeadersData represents a block header query.
   137  type getBlockHeadersData struct {
   138  	Origin  hashOrNumber // Block from which to retrieve headers
   139  	Amount  uint64       // Maximum number of headers to retrieve
   140  	Skip    uint64       // Blocks to skip between consecutive headers
   141  	Reverse bool         // Query direction (false = rising towards latest, true = falling towards genesis)
   142  }
   143  
   144  // hashOrNumber is a combined field for specifying an origin block.
   145  type hashOrNumber struct {
   146  	Hash   common.Hash // Block hash from which to retrieve headers (excludes Number)
   147  	Number uint64      // Block hash from which to retrieve headers (excludes Hash)
   148  }
   149  
   150  // EncodeRLP is a specialized encoder for hashOrNumber to encode only one of the
   151  // two contained union fields.
   152  func (hn *hashOrNumber) EncodeRLP(w io.Writer) error {
   153  	if hn.Hash == (common.Hash{}) {
   154  		return rlp.Encode(w, hn.Number)
   155  	}
   156  	if hn.Number != 0 {
   157  		return fmt.Errorf("both origin hash (%x) and number (%d) provided", hn.Hash, hn.Number)
   158  	}
   159  	return rlp.Encode(w, hn.Hash)
   160  }
   161  
   162  // DecodeRLP is a specialized decoder for hashOrNumber to decode the contents
   163  // into either a block hash or a block number.
   164  func (hn *hashOrNumber) DecodeRLP(s *rlp.Stream) error {
   165  	_, size, _ := s.Kind()
   166  	origin, err := s.Raw()
   167  	if err == nil {
   168  		switch {
   169  		case size == 32:
   170  			err = rlp.DecodeBytes(origin, &hn.Hash)
   171  		case size <= 8:
   172  			err = rlp.DecodeBytes(origin, &hn.Number)
   173  		default:
   174  			err = fmt.Errorf("invalid input size %d for origin", size)
   175  		}
   176  	}
   177  	return err
   178  }
   179  
   180  // newBlockData is the network packet for the block propagation message.
   181  type newBlockData struct {
   182  	Block *types.Block
   183  	TD    *big.Int
   184  }
   185  
   186  // blockBody represents the data content of a single block.
   187  type blockBody struct {
   188  	Transactions []*types.Transaction // Transactions contained within a block
   189  	Uncles       []*types.Header      // Uncles contained within a block
   190  }
   191  
   192  // blockBodiesData is the network packet for block content distribution.
   193  type blockBodiesData []*blockBody