github.com/klaytn/klaytn@v1.12.1/node/cn/protocol.go (about)

     1  // Modifications Copyright 2018 The klaytn Authors
     2  // Copyright 2014 The go-ethereum Authors
     3  // This file is part of go-ethereum.
     4  //
     5  // The go-ethereum library is free software: you can redistribute it and/or modify
     6  // it under the terms of the GNU Lesser General Public License as published by
     7  // the Free Software Foundation, either version 3 of the License, or
     8  // (at your option) any later version.
     9  //
    10  // The go-ethereum library is distributed in the hope that it will be useful,
    11  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    12  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    13  // GNU Lesser General Public License for more details.
    14  //
    15  // You should have received a copy of the GNU Lesser General Public License
    16  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    17  //
    18  // This file is derived from eth/protocol.go (2018/06/04).
    19  // Modified and improved for the klaytn development.
    20  
    21  package cn
    22  
    23  import (
    24  	"fmt"
    25  	"io"
    26  	"math/big"
    27  	"time"
    28  
    29  	"github.com/klaytn/klaytn"
    30  	"github.com/klaytn/klaytn/blockchain/types"
    31  	"github.com/klaytn/klaytn/common"
    32  	"github.com/klaytn/klaytn/datasync/downloader"
    33  	"github.com/klaytn/klaytn/datasync/fetcher"
    34  	"github.com/klaytn/klaytn/node/cn/snap"
    35  	"github.com/klaytn/klaytn/reward"
    36  	"github.com/klaytn/klaytn/rlp"
    37  )
    38  
    39  // Constants to match up protocol versions and messages
    40  const (
    41  	klay62 = 62
    42  	klay63 = 63
    43  	klay64 = 64
    44  	klay65 = 65
    45  )
    46  
    47  // ProtocolName is the official short name of the protocol used during capability negotiation.
    48  var ProtocolName = "klay"
    49  
    50  // ProtocolVersions are the upported versions of the klay protocol (first is primary).
    51  var ProtocolVersions = []uint{klay65, klay64, klay63, klay62}
    52  
    53  // ProtocolLengths are the number of implemented message corresponding to different protocol versions.
    54  var ProtocolLengths = []uint64{21, 19, 17, 8}
    55  
    56  const ProtocolMaxMsgSize = 12 * 1024 * 1024 // Maximum cap on the size of a protocol message
    57  
    58  // Klaytn protocol message codes
    59  // TODO-Klaytn-Issue751 Protocol message should be refactored. Present code is not used.
    60  const (
    61  	// Protocol messages belonging to klay/62
    62  	StatusMsg                   = 0x00
    63  	NewBlockHashesMsg           = 0x01
    64  	BlockHeaderFetchRequestMsg  = 0x02
    65  	BlockHeaderFetchResponseMsg = 0x03
    66  	BlockBodiesFetchRequestMsg  = 0x04
    67  	BlockBodiesFetchResponseMsg = 0x05
    68  	TxMsg                       = 0x06
    69  	BlockHeadersRequestMsg      = 0x07
    70  	BlockHeadersMsg             = 0x08
    71  	BlockBodiesRequestMsg       = 0x09
    72  	BlockBodiesMsg              = 0x0a
    73  	NewBlockMsg                 = 0x0b
    74  
    75  	// Protocol messages belonging to klay/63
    76  	NodeDataRequestMsg = 0x0c
    77  	NodeDataMsg        = 0x0d
    78  	ReceiptsRequestMsg = 0x0e
    79  	ReceiptsMsg        = 0x0f
    80  
    81  	// Protocol messages belonging to klay/64
    82  	Unused10 = 0x10 // Skipped a number because 0x11 is already taken
    83  	Unused11 = 0x11 // Already used by consensus (IstanbulMsg)
    84  
    85  	// Protocol messages belonging to klay/65
    86  	StakingInfoRequestMsg = 0x12
    87  	StakingInfoMsg        = 0x13
    88  
    89  	MsgCodeEnd = 0x14
    90  )
    91  
    92  type errCode int
    93  
    94  const (
    95  	ErrMsgTooLarge = iota
    96  	ErrDecode
    97  	ErrInvalidMsgCode
    98  	ErrProtocolVersionMismatch
    99  	ErrNetworkIdMismatch
   100  	ErrGenesisBlockMismatch
   101  	ErrChainIDMismatch
   102  	ErrNoStatusMsg
   103  	ErrExtraStatusMsg
   104  	ErrSuspendedPeer
   105  	ErrUnexpectedTxType
   106  	ErrFailedToGetStateDB
   107  	ErrUnsupportedEnginePolicy
   108  )
   109  
   110  func (e errCode) String() string {
   111  	return errorToString[int(e)]
   112  }
   113  
   114  // XXX change once legacy code is out
   115  var errorToString = map[int]string{
   116  	ErrMsgTooLarge:             "Message too long",
   117  	ErrDecode:                  "Invalid message",
   118  	ErrInvalidMsgCode:          "Invalid message code",
   119  	ErrProtocolVersionMismatch: "Protocol version mismatch",
   120  	ErrNetworkIdMismatch:       "NetworkId mismatch",
   121  	ErrGenesisBlockMismatch:    "Genesis block mismatch",
   122  	ErrChainIDMismatch:         "ChainID mismatch",
   123  	ErrNoStatusMsg:             "No status message",
   124  	ErrExtraStatusMsg:          "Extra status message",
   125  	ErrSuspendedPeer:           "Suspended peer",
   126  	ErrUnexpectedTxType:        "Unexpected tx type",
   127  	ErrFailedToGetStateDB:      "Failed to get stateDB",
   128  	ErrUnsupportedEnginePolicy: "Unsupported engine or policy",
   129  }
   130  
   131  //go:generate mockgen -destination=node/cn/mocks/downloader_mock.go -package=mocks github.com/klaytn/klaytn/node/cn ProtocolManagerDownloader
   132  // ProtocolManagerDownloader is an interface of downloader.Downloader used by ProtocolManager.
   133  type ProtocolManagerDownloader interface {
   134  	RegisterPeer(id string, version int, peer downloader.Peer) error
   135  	UnregisterPeer(id string) error
   136  
   137  	DeliverBodies(id string, transactions [][]*types.Transaction) error
   138  	DeliverHeaders(id string, headers []*types.Header) error
   139  	DeliverNodeData(id string, data [][]byte) error
   140  	DeliverReceipts(id string, receipts [][]*types.Receipt) error
   141  	DeliverStakingInfos(id string, stakingInfos []*reward.StakingInfo) error
   142  	DeliverSnapPacket(peer *snap.Peer, packet snap.Packet) error
   143  
   144  	Terminate()
   145  	Synchronise(id string, head common.Hash, td *big.Int, mode downloader.SyncMode) error
   146  	Progress() klaytn.SyncProgress
   147  	Cancel()
   148  
   149  	GetSnapSyncer() *snap.Syncer
   150  	SyncStakingInfo(id string, from, to uint64) error
   151  	SyncStakingInfoStatus() *downloader.SyncingStatus
   152  }
   153  
   154  //go:generate mockgen -destination=node/cn/mocks/fetcher_mock.go -package=mocks github.com/klaytn/klaytn/node/cn ProtocolManagerFetcher
   155  // ProtocolManagerFetcher is an interface of fetcher.Fetcher used by ProtocolManager.
   156  type ProtocolManagerFetcher interface {
   157  	Enqueue(peer string, block *types.Block) error
   158  	FilterBodies(peer string, transactions [][]*types.Transaction, time time.Time) [][]*types.Transaction
   159  	FilterHeaders(peer string, headers []*types.Header, time time.Time) []*types.Header
   160  	Notify(peer string, hash common.Hash, number uint64, time time.Time, headerFetcher fetcher.HeaderRequesterFn, bodyFetcher fetcher.BodyRequesterFn) error
   161  	Start()
   162  	Stop()
   163  }
   164  
   165  // statusData is the network packet for the status message.
   166  type statusData struct {
   167  	ProtocolVersion uint32
   168  	NetworkId       uint64
   169  	TD              *big.Int
   170  	CurrentBlock    common.Hash
   171  	GenesisBlock    common.Hash
   172  	ChainID         *big.Int // ChainID to sign a transaction.
   173  }
   174  
   175  // newBlockHashesData is the network packet for the block announcements.
   176  type newBlockHashesData []struct {
   177  	Hash   common.Hash // Hash of one particular block being announced
   178  	Number uint64      // Number of one particular block being announced
   179  }
   180  
   181  // getBlockHeadersData represents a block header query.
   182  type getBlockHeadersData struct {
   183  	Origin  hashOrNumber // Block from which to retrieve headers
   184  	Amount  uint64       // Maximum number of headers to retrieve
   185  	Skip    uint64       // Blocks to skip between consecutive headers
   186  	Reverse bool         // Query direction (false = rising towards latest, true = falling towards genesis)
   187  }
   188  
   189  // hashOrNumber is a combined field for specifying an origin block.
   190  type hashOrNumber struct {
   191  	Hash   common.Hash // Block hash from which to retrieve headers (excludes Number)
   192  	Number uint64      // Block hash from which to retrieve headers (excludes Hash)
   193  }
   194  
   195  // EncodeRLP is a specialized encoder for hashOrNumber to encode only one of the
   196  // two contained union fields.
   197  func (hn *hashOrNumber) EncodeRLP(w io.Writer) error {
   198  	if hn.Hash == (common.Hash{}) {
   199  		return rlp.Encode(w, hn.Number)
   200  	}
   201  	if hn.Number != 0 {
   202  		return fmt.Errorf("both origin hash (%x) and number (%d) provided", hn.Hash, hn.Number)
   203  	}
   204  	return rlp.Encode(w, hn.Hash)
   205  }
   206  
   207  // DecodeRLP is a specialized decoder for hashOrNumber to decode the contents
   208  // into either a block hash or a block number.
   209  func (hn *hashOrNumber) DecodeRLP(s *rlp.Stream) error {
   210  	_, size, _ := s.Kind()
   211  	origin, err := s.Raw()
   212  	if err == nil {
   213  		switch {
   214  		case size == 32:
   215  			err = rlp.DecodeBytes(origin, &hn.Hash)
   216  		case size <= 8:
   217  			err = rlp.DecodeBytes(origin, &hn.Number)
   218  		default:
   219  			err = fmt.Errorf("invalid input size %d for origin", size)
   220  		}
   221  	}
   222  	return err
   223  }
   224  
   225  // newBlockData is the network packet for the block propagation message.
   226  type newBlockData struct {
   227  	Block *types.Block
   228  	TD    *big.Int
   229  }
   230  
   231  // blockBody represents the data content of a single block.
   232  type blockBody struct {
   233  	Transactions []*types.Transaction // Transactions contained within a block
   234  }
   235  
   236  // blockBodiesData is the network packet for block content distribution.
   237  type blockBodiesData []*blockBody