github.com/aswedchain/aswed@v1.0.1/eth/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 eth
    18  
    19  import (
    20  	"fmt"
    21  	"io"
    22  	"math/big"
    23  
    24  	"github.com/aswedchain/aswed/common"
    25  	"github.com/aswedchain/aswed/core"
    26  	"github.com/aswedchain/aswed/core/forkid"
    27  	"github.com/aswedchain/aswed/core/types"
    28  	"github.com/aswedchain/aswed/event"
    29  	"github.com/aswedchain/aswed/rlp"
    30  )
    31  
    32  // Constants to match up protocol versions and messages
    33  const (
    34  	eth63 = 63
    35  	eth64 = 64
    36  	eth65 = 65
    37  )
    38  
    39  // protocolName is the official short name of the protocol used during capability negotiation.
    40  const protocolName = "eth"
    41  
    42  // ProtocolVersions are the supported versions of the eth protocol (first is primary).
    43  var ProtocolVersions = []uint{eth65, eth64, eth63}
    44  
    45  // protocolLengths are the number of implemented message corresponding to different protocol versions.
    46  var protocolLengths = map[uint]uint64{eth65: 17, eth64: 17, eth63: 17}
    47  
    48  const protocolMaxMsgSize = 10 * 1024 * 1024 // Maximum cap on the size of a protocol message
    49  
    50  // eth protocol message codes
    51  const (
    52  	StatusMsg          = 0x00
    53  	NewBlockHashesMsg  = 0x01
    54  	TransactionMsg     = 0x02
    55  	GetBlockHeadersMsg = 0x03
    56  	BlockHeadersMsg    = 0x04
    57  	GetBlockBodiesMsg  = 0x05
    58  	BlockBodiesMsg     = 0x06
    59  	NewBlockMsg        = 0x07
    60  	GetNodeDataMsg     = 0x0d
    61  	NodeDataMsg        = 0x0e
    62  	GetReceiptsMsg     = 0x0f
    63  	ReceiptsMsg        = 0x10
    64  
    65  	// New protocol message codes introduced in eth65
    66  	//
    67  	// Previously these message ids were used by some legacy and unsupported
    68  	// eth protocols, reown them here.
    69  	NewPooledTransactionHashesMsg = 0x08
    70  	GetPooledTransactionsMsg      = 0x09
    71  	PooledTransactionsMsg         = 0x0a
    72  )
    73  
    74  type errCode int
    75  
    76  const (
    77  	ErrMsgTooLarge = iota
    78  	ErrDecode
    79  	ErrInvalidMsgCode
    80  	ErrProtocolVersionMismatch
    81  	ErrNetworkIDMismatch
    82  	ErrGenesisMismatch
    83  	ErrForkIDRejected
    84  	ErrNoStatusMsg
    85  	ErrExtraStatusMsg
    86  )
    87  
    88  func (e errCode) String() string {
    89  	return errorToString[int(e)]
    90  }
    91  
    92  // XXX change once legacy code is out
    93  var errorToString = map[int]string{
    94  	ErrMsgTooLarge:             "Message too long",
    95  	ErrDecode:                  "Invalid message",
    96  	ErrInvalidMsgCode:          "Invalid message code",
    97  	ErrProtocolVersionMismatch: "Protocol version mismatch",
    98  	ErrNetworkIDMismatch:       "Network ID mismatch",
    99  	ErrGenesisMismatch:         "Genesis mismatch",
   100  	ErrForkIDRejected:          "Fork ID rejected",
   101  	ErrNoStatusMsg:             "No status message",
   102  	ErrExtraStatusMsg:          "Extra status message",
   103  }
   104  
   105  type txPool interface {
   106  	// Has returns an indicator whether txpool has a transaction
   107  	// cached with the given hash.
   108  	Has(hash common.Hash) bool
   109  
   110  	// Get retrieves the transaction from local txpool with given
   111  	// tx hash.
   112  	Get(hash common.Hash) *types.Transaction
   113  
   114  	// AddRemotes should add the given transactions to the pool.
   115  	AddRemotes([]*types.Transaction) []error
   116  
   117  	// Pending should return pending transactions.
   118  	// The slice should be modifiable by the caller.
   119  	Pending() (map[common.Address]types.Transactions, error)
   120  
   121  	// SubscribeNewTxsEvent should return an event subscription of
   122  	// NewTxsEvent and send events to the given channel.
   123  	SubscribeNewTxsEvent(chan<- core.NewTxsEvent) event.Subscription
   124  }
   125  
   126  // statusData63 is the network packet for the status message for eth/63.
   127  type statusData63 struct {
   128  	ProtocolVersion uint32
   129  	NetworkId       uint64
   130  	TD              *big.Int
   131  	CurrentBlock    common.Hash
   132  	GenesisBlock    common.Hash
   133  }
   134  
   135  // statusData is the network packet for the status message for eth/64 and later.
   136  type statusData struct {
   137  	ProtocolVersion uint32
   138  	NetworkID       uint64
   139  	TD              *big.Int
   140  	Head            common.Hash
   141  	Genesis         common.Hash
   142  	ForkID          forkid.ID
   143  }
   144  
   145  // newBlockHashesData is the network packet for the block announcements.
   146  type newBlockHashesData []struct {
   147  	Hash   common.Hash // Hash of one particular block being announced
   148  	Number uint64      // Number of one particular block being announced
   149  }
   150  
   151  // getBlockHeadersData represents a block header query.
   152  type getBlockHeadersData struct {
   153  	Origin  hashOrNumber // Block from which to retrieve headers
   154  	Amount  uint64       // Maximum number of headers to retrieve
   155  	Skip    uint64       // Blocks to skip between consecutive headers
   156  	Reverse bool         // Query direction (false = rising towards latest, true = falling towards genesis)
   157  }
   158  
   159  // hashOrNumber is a combined field for specifying an origin block.
   160  type hashOrNumber struct {
   161  	Hash   common.Hash // Block hash from which to retrieve headers (excludes Number)
   162  	Number uint64      // Block hash from which to retrieve headers (excludes Hash)
   163  }
   164  
   165  // EncodeRLP is a specialized encoder for hashOrNumber to encode only one of the
   166  // two contained union fields.
   167  func (hn *hashOrNumber) EncodeRLP(w io.Writer) error {
   168  	if hn.Hash == (common.Hash{}) {
   169  		return rlp.Encode(w, hn.Number)
   170  	}
   171  	if hn.Number != 0 {
   172  		return fmt.Errorf("both origin hash (%x) and number (%d) provided", hn.Hash, hn.Number)
   173  	}
   174  	return rlp.Encode(w, hn.Hash)
   175  }
   176  
   177  // DecodeRLP is a specialized decoder for hashOrNumber to decode the contents
   178  // into either a block hash or a block number.
   179  func (hn *hashOrNumber) DecodeRLP(s *rlp.Stream) error {
   180  	_, size, _ := s.Kind()
   181  	origin, err := s.Raw()
   182  	if err == nil {
   183  		switch {
   184  		case size == 32:
   185  			err = rlp.DecodeBytes(origin, &hn.Hash)
   186  		case size <= 8:
   187  			err = rlp.DecodeBytes(origin, &hn.Number)
   188  		default:
   189  			err = fmt.Errorf("invalid input size %d for origin", size)
   190  		}
   191  	}
   192  	return err
   193  }
   194  
   195  // newBlockData is the network packet for the block propagation message.
   196  type newBlockData struct {
   197  	Block *types.Block
   198  	TD    *big.Int
   199  }
   200  
   201  // sanityCheck verifies that the values are reasonable, as a DoS protection
   202  func (request *newBlockData) sanityCheck() error {
   203  	if err := request.Block.SanityCheck(); err != nil {
   204  		return err
   205  	}
   206  	//TD at mainnet block #7753254 is 76 bits. If it becomes 100 million times
   207  	// larger, it will still fit within 100 bits
   208  	if tdlen := request.TD.BitLen(); tdlen > 100 {
   209  		return fmt.Errorf("too large block TD: bitlen %d", tdlen)
   210  	}
   211  	return nil
   212  }
   213  
   214  // blockBody represents the data content of a single block.
   215  type blockBody struct {
   216  	Transactions []*types.Transaction // Transactions contained within a block
   217  	Uncles       []*types.Header      // Uncles contained within a block
   218  }
   219  
   220  // blockBodiesData is the network packet for block content distribution.
   221  type blockBodiesData []*blockBody