github.com/sberex/go-sberex@v1.8.2-0.20181113200658-ed96ac38f7d7/eth/protocol.go (about)

     1  // This file is part of the go-sberex library. The go-sberex library is 
     2  // free software: you can redistribute it and/or modify it under the terms 
     3  // of the GNU Lesser General Public License as published by the Free 
     4  // Software Foundation, either version 3 of the License, or (at your option)
     5  // any later version.
     6  //
     7  // The go-sberex library is distributed in the hope that it will be useful, 
     8  // but WITHOUT ANY WARRANTY; without even the implied warranty of
     9  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser 
    10  // General Public License <http://www.gnu.org/licenses/> for more details.
    11  
    12  package eth
    13  
    14  import (
    15  	"fmt"
    16  	"io"
    17  	"math/big"
    18  
    19  	"github.com/Sberex/go-sberex/common"
    20  	"github.com/Sberex/go-sberex/core"
    21  	"github.com/Sberex/go-sberex/core/types"
    22  	"github.com/Sberex/go-sberex/event"
    23  	"github.com/Sberex/go-sberex/rlp"
    24  )
    25  
    26  // Constants to match up protocol versions and messages
    27  const (
    28  	eth62 = 62
    29  	eth63 = 63
    30  )
    31  
    32  // Official short name of the protocol used during capability negotiation.
    33  var ProtocolName = "eth"
    34  
    35  // Supported versions of the eth protocol (first is primary).
    36  var ProtocolVersions = []uint{eth63, eth62}
    37  
    38  // Number of implemented message corresponding to different protocol versions.
    39  var ProtocolLengths = []uint64{17, 8}
    40  
    41  const ProtocolMaxMsgSize = 10 * 1024 * 1024 // Maximum cap on the size of a protocol message
    42  
    43  // eth protocol message codes
    44  const (
    45  	// Protocol messages belonging to eth/62
    46  	StatusMsg          = 0x00
    47  	NewBlockHashesMsg  = 0x01
    48  	TxMsg              = 0x02
    49  	GetBlockHeadersMsg = 0x03
    50  	BlockHeadersMsg    = 0x04
    51  	GetBlockBodiesMsg  = 0x05
    52  	BlockBodiesMsg     = 0x06
    53  	NewBlockMsg        = 0x07
    54  
    55  	// Protocol messages belonging to eth/63
    56  	GetNodeDataMsg = 0x0d
    57  	NodeDataMsg    = 0x0e
    58  	GetReceiptsMsg = 0x0f
    59  	ReceiptsMsg    = 0x10
    60  )
    61  
    62  type errCode int
    63  
    64  const (
    65  	ErrMsgTooLarge = iota
    66  	ErrDecode
    67  	ErrInvalidMsgCode
    68  	ErrProtocolVersionMismatch
    69  	ErrNetworkIdMismatch
    70  	ErrGenesisBlockMismatch
    71  	ErrNoStatusMsg
    72  	ErrExtraStatusMsg
    73  	ErrSuspendedPeer
    74  )
    75  
    76  func (e errCode) String() string {
    77  	return errorToString[int(e)]
    78  }
    79  
    80  // XXX change once legacy code is out
    81  var errorToString = map[int]string{
    82  	ErrMsgTooLarge:             "Message too long",
    83  	ErrDecode:                  "Invalid message",
    84  	ErrInvalidMsgCode:          "Invalid message code",
    85  	ErrProtocolVersionMismatch: "Protocol version mismatch",
    86  	ErrNetworkIdMismatch:       "NetworkId mismatch",
    87  	ErrGenesisBlockMismatch:    "Genesis block mismatch",
    88  	ErrNoStatusMsg:             "No status message",
    89  	ErrExtraStatusMsg:          "Extra status message",
    90  	ErrSuspendedPeer:           "Suspended peer",
    91  }
    92  
    93  type txPool interface {
    94  	// AddRemotes should add the given transactions to the pool.
    95  	AddRemotes([]*types.Transaction) []error
    96  
    97  	// Pending should return pending transactions.
    98  	// The slice should be modifiable by the caller.
    99  	Pending() (map[common.Address]types.Transactions, error)
   100  
   101  	// SubscribeTxPreEvent should return an event subscription of
   102  	// TxPreEvent and send events to the given channel.
   103  	SubscribeTxPreEvent(chan<- core.TxPreEvent) event.Subscription
   104  }
   105  
   106  // statusData is the network packet for the status message.
   107  type statusData struct {
   108  	ProtocolVersion uint32
   109  	NetworkId       uint64
   110  	TD              *big.Int
   111  	CurrentBlock    common.Hash
   112  	GenesisBlock    common.Hash
   113  }
   114  
   115  // newBlockHashesData is the network packet for the block announcements.
   116  type newBlockHashesData []struct {
   117  	Hash   common.Hash // Hash of one particular block being announced
   118  	Number uint64      // Number of one particular block being announced
   119  }
   120  
   121  // getBlockHeadersData represents a block header query.
   122  type getBlockHeadersData struct {
   123  	Origin  hashOrNumber // Block from which to retrieve headers
   124  	Amount  uint64       // Maximum number of headers to retrieve
   125  	Skip    uint64       // Blocks to skip between consecutive headers
   126  	Reverse bool         // Query direction (false = rising towards latest, true = falling towards genesis)
   127  }
   128  
   129  // hashOrNumber is a combined field for specifying an origin block.
   130  type hashOrNumber struct {
   131  	Hash   common.Hash // Block hash from which to retrieve headers (excludes Number)
   132  	Number uint64      // Block hash from which to retrieve headers (excludes Hash)
   133  }
   134  
   135  // EncodeRLP is a specialized encoder for hashOrNumber to encode only one of the
   136  // two contained union fields.
   137  func (hn *hashOrNumber) EncodeRLP(w io.Writer) error {
   138  	if hn.Hash == (common.Hash{}) {
   139  		return rlp.Encode(w, hn.Number)
   140  	}
   141  	if hn.Number != 0 {
   142  		return fmt.Errorf("both origin hash (%x) and number (%d) provided", hn.Hash, hn.Number)
   143  	}
   144  	return rlp.Encode(w, hn.Hash)
   145  }
   146  
   147  // DecodeRLP is a specialized decoder for hashOrNumber to decode the contents
   148  // into either a block hash or a block number.
   149  func (hn *hashOrNumber) DecodeRLP(s *rlp.Stream) error {
   150  	_, size, _ := s.Kind()
   151  	origin, err := s.Raw()
   152  	if err == nil {
   153  		switch {
   154  		case size == 32:
   155  			err = rlp.DecodeBytes(origin, &hn.Hash)
   156  		case size <= 8:
   157  			err = rlp.DecodeBytes(origin, &hn.Number)
   158  		default:
   159  			err = fmt.Errorf("invalid input size %d for origin", size)
   160  		}
   161  	}
   162  	return err
   163  }
   164  
   165  // newBlockData is the network packet for the block propagation message.
   166  type newBlockData struct {
   167  	Block *types.Block
   168  	TD    *big.Int
   169  }
   170  
   171  // blockBody represents the data content of a single block.
   172  type blockBody struct {
   173  	Transactions []*types.Transaction // Transactions contained within a block
   174  	Uncles       []*types.Header      // Uncles contained within a block
   175  }
   176  
   177  // blockBodiesData is the network packet for block content distribution.
   178  type blockBodiesData []*blockBody