good morning!!!!

Skip to content
Snippets Groups Projects
protocol.go 6.93 KiB
Newer Older
  • Learn to ignore specific revisions
  • // Copyright 2014 The go-ethereum Authors
    
    // This file is part of the go-ethereum library.
    
    // The go-ethereum library is free software: you can redistribute it and/or modify
    
    // it under the terms of the GNU Lesser General Public License as published by
    // the Free Software Foundation, either version 3 of the License, or
    // (at your option) any later version.
    //
    
    // The go-ethereum library is distributed in the hope that it will be useful,
    
    // but WITHOUT ANY WARRANTY; without even the implied warranty of
    
    // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    
    // GNU Lesser General Public License for more details.
    //
    // You should have received a copy of the GNU Lesser General Public License
    
    // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    
    package eth
    
    import (
    
    	"github.com/ethereum/go-ethereum/common"
    
    	"github.com/ethereum/go-ethereum/core"
    
    	"github.com/ethereum/go-ethereum/core/forkid"
    
    	"github.com/ethereum/go-ethereum/core/types"
    
    	"github.com/ethereum/go-ethereum/event"
    
    	"github.com/ethereum/go-ethereum/rlp"
    )
    
    // Constants to match up protocol versions and messages
    const (
    	eth63 = 63
    
    // protocolName is the official short name of the protocol used during capability negotiation.
    const protocolName = "eth"
    
    // ProtocolVersions are the supported versions of the eth protocol (first is primary).
    
    var ProtocolVersions = []uint{eth65, eth64, eth63}
    
    // protocolLengths are the number of implemented message corresponding to different protocol versions.
    
    var protocolLengths = map[uint]uint64{eth65: 17, eth64: 17, eth63: 17}
    
    const protocolMaxMsgSize = 10 * 1024 * 1024 // Maximum cap on the size of a protocol message
    
    
    // eth protocol message codes
    const (
    
    	StatusMsg          = 0x00
    	NewBlockHashesMsg  = 0x01
    
    	GetBlockHeadersMsg = 0x03
    	BlockHeadersMsg    = 0x04
    	GetBlockBodiesMsg  = 0x05
    	BlockBodiesMsg     = 0x06
    
    	GetNodeDataMsg     = 0x0d
    	NodeDataMsg        = 0x0e
    	GetReceiptsMsg     = 0x0f
    	ReceiptsMsg        = 0x10
    
    
    	// New protocol message codes introduced in eth65
    	//
    
    	// Previously these message ids were used by some legacy and unsupported
    	// eth protocols, reown them here.
    
    	NewPooledTransactionHashesMsg = 0x08
    	GetPooledTransactionsMsg      = 0x09
    
    const (
    	ErrMsgTooLarge = iota
    	ErrDecode
    	ErrInvalidMsgCode
    	ErrProtocolVersionMismatch
    
    	ErrNetworkIDMismatch
    	ErrGenesisMismatch
    	ErrForkIDRejected
    
    	ErrNoStatusMsg
    	ErrExtraStatusMsg
    )
    
    
    func (e errCode) String() string {
    	return errorToString[int(e)]
    }
    
    // XXX change once legacy code is out
    
    var errorToString = map[int]string{
    	ErrMsgTooLarge:             "Message too long",
    	ErrDecode:                  "Invalid message",
    	ErrInvalidMsgCode:          "Invalid message code",
    	ErrProtocolVersionMismatch: "Protocol version mismatch",
    
    	ErrNetworkIDMismatch:       "Network ID mismatch",
    	ErrGenesisMismatch:         "Genesis mismatch",
    	ErrForkIDRejected:          "Fork ID rejected",
    
    	ErrNoStatusMsg:             "No status message",
    	ErrExtraStatusMsg:          "Extra status message",
    }
    
    
    Viktor Trón's avatar
    Viktor Trón committed
    type txPool interface {
    
    	// Has returns an indicator whether txpool has a transaction
    	// cached with the given hash.
    	Has(hash common.Hash) bool
    
    	// Get retrieves the transaction from local txpool with given
    	// tx hash.
    	Get(hash common.Hash) *types.Transaction
    
    
    	// AddRemotes should add the given transactions to the pool.
    
    	AddRemotes([]*types.Transaction) []error
    
    	// Pending should return pending transactions.
    
    	// The slice should be modifiable by the caller.
    
    	Pending() (map[common.Address]types.Transactions, error)
    
    	// SubscribeNewTxsEvent should return an event subscription of
    	// NewTxsEvent and send events to the given channel.
    	SubscribeNewTxsEvent(chan<- core.NewTxsEvent) event.Subscription
    
    Viktor Trón's avatar
    Viktor Trón committed
    }
    
    
    // statusData63 is the network packet for the status message for eth/63.
    type statusData63 struct {
    
    	ProtocolVersion uint32
    
    	TD              *big.Int
    	CurrentBlock    common.Hash
    	GenesisBlock    common.Hash
    }
    
    
    // statusData is the network packet for the status message for eth/64 and later.
    type statusData struct {
    	ProtocolVersion uint32
    	NetworkID       uint64
    	TD              *big.Int
    	Head            common.Hash
    	Genesis         common.Hash
    	ForkID          forkid.ID
    }
    
    
    // newBlockHashesData is the network packet for the block announcements.
    type newBlockHashesData []struct {
    	Hash   common.Hash // Hash of one particular block being announced
    	Number uint64      // Number of one particular block being announced
    }
    
    // getBlockHeadersData represents a block header query.
    type getBlockHeadersData struct {
    	Origin  hashOrNumber // Block from which to retrieve headers
    	Amount  uint64       // Maximum number of headers to retrieve
    	Skip    uint64       // Blocks to skip between consecutive headers
    	Reverse bool         // Query direction (false = rising towards latest, true = falling towards genesis)
    }
    
    // hashOrNumber is a combined field for specifying an origin block.
    type hashOrNumber struct {
    	Hash   common.Hash // Block hash from which to retrieve headers (excludes Number)
    	Number uint64      // Block hash from which to retrieve headers (excludes Hash)
    }
    
    // EncodeRLP is a specialized encoder for hashOrNumber to encode only one of the
    // two contained union fields.
    func (hn *hashOrNumber) EncodeRLP(w io.Writer) error {
    	if hn.Hash == (common.Hash{}) {
    		return rlp.Encode(w, hn.Number)
    	}
    	if hn.Number != 0 {
    		return fmt.Errorf("both origin hash (%x) and number (%d) provided", hn.Hash, hn.Number)
    	}
    	return rlp.Encode(w, hn.Hash)
    }
    
    // DecodeRLP is a specialized decoder for hashOrNumber to decode the contents
    // into either a block hash or a block number.
    func (hn *hashOrNumber) DecodeRLP(s *rlp.Stream) error {
    	_, size, _ := s.Kind()
    	origin, err := s.Raw()
    	if err == nil {
    		switch {
    		case size == 32:
    			err = rlp.DecodeBytes(origin, &hn.Hash)
    		case size <= 8:
    			err = rlp.DecodeBytes(origin, &hn.Number)
    		default:
    			err = fmt.Errorf("invalid input size %d for origin", size)
    		}
    	}
    	return err
    }
    
    
    // newBlockData is the network packet for the block propagation message.
    type newBlockData struct {
    
    	Block *types.Block
    	TD    *big.Int
    }
    
    // sanityCheck verifies that the values are reasonable, as a DoS protection
    func (request *newBlockData) sanityCheck() error {
    	if err := request.Block.SanityCheck(); err != nil {
    		return err
    	}
    	//TD at mainnet block #7753254 is 76 bits. If it becomes 100 million times
    	// larger, it will still fit within 100 bits
    	if tdlen := request.TD.BitLen(); tdlen > 100 {
    		return fmt.Errorf("too large block TD: bitlen %d", tdlen)
    	}
    	return nil
    }
    
    
    // blockBody represents the data content of a single block.
    type blockBody struct {
    	Transactions []*types.Transaction // Transactions contained within a block
    	Uncles       []*types.Header      // Uncles contained within a block
    }
    
    // blockBodiesData is the network packet for block content distribution.
    type blockBodiesData []*blockBody