protocol.go 5.61 KB
Newer Older
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 6 7 8
// 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.
//
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 13 14
// GNU Lesser General Public License for more details.
//
// 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 18 19
package eth

import (
20 21
	"fmt"
	"io"
22 23
	"math/big"

obscuren's avatar
obscuren committed
24
	"github.com/ethereum/go-ethereum/common"
25
	"github.com/ethereum/go-ethereum/core"
26
	"github.com/ethereum/go-ethereum/core/types"
27
	"github.com/ethereum/go-ethereum/event"
28 29 30 31 32 33 34
	"github.com/ethereum/go-ethereum/rlp"
)

// Constants to match up protocol versions and messages
const (
	eth62 = 62
	eth63 = 63
35 36
)

37 38 39
// Official short name of the protocol used during capability negotiation.
var ProtocolName = "eth"

40
// Supported versions of the eth protocol (first is primary).
41
var ProtocolVersions = []uint{eth63, eth62}
42 43

// Number of implemented message corresponding to different protocol versions.
44
var ProtocolLengths = []uint64{17, 8}
45

46
const ProtocolMaxMsgSize = 10 * 1024 * 1024 // Maximum cap on the size of a protocol message
47 48 49

// eth protocol message codes
const (
50 51 52 53
	// Protocol messages belonging to eth/62
	StatusMsg          = 0x00
	NewBlockHashesMsg  = 0x01
	TxMsg              = 0x02
54 55 56 57
	GetBlockHeadersMsg = 0x03
	BlockHeadersMsg    = 0x04
	GetBlockBodiesMsg  = 0x05
	BlockBodiesMsg     = 0x06
58
	NewBlockMsg        = 0x07
59 60 61 62 63 64

	// Protocol messages belonging to eth/63
	GetNodeDataMsg = 0x0d
	NodeDataMsg    = 0x0e
	GetReceiptsMsg = 0x0f
	ReceiptsMsg    = 0x10
65 66
)

67 68
type errCode int

zelig's avatar
zelig committed
69 70 71 72 73 74 75 76 77
const (
	ErrMsgTooLarge = iota
	ErrDecode
	ErrInvalidMsgCode
	ErrProtocolVersionMismatch
	ErrNetworkIdMismatch
	ErrGenesisBlockMismatch
	ErrNoStatusMsg
	ErrExtraStatusMsg
78
	ErrSuspendedPeer
zelig's avatar
zelig committed
79 80
)

81 82 83 84 85
func (e errCode) String() string {
	return errorToString[int(e)]
}

// XXX change once legacy code is out
zelig's avatar
zelig committed
86 87 88 89 90 91 92 93 94
var errorToString = map[int]string{
	ErrMsgTooLarge:             "Message too long",
	ErrDecode:                  "Invalid message",
	ErrInvalidMsgCode:          "Invalid message code",
	ErrProtocolVersionMismatch: "Protocol version mismatch",
	ErrNetworkIdMismatch:       "NetworkId mismatch",
	ErrGenesisBlockMismatch:    "Genesis block mismatch",
	ErrNoStatusMsg:             "No status message",
	ErrExtraStatusMsg:          "Extra status message",
95
	ErrSuspendedPeer:           "Suspended peer",
zelig's avatar
zelig committed
96 97
}

zelig's avatar
zelig committed
98
type txPool interface {
99
	// AddRemotes should add the given transactions to the pool.
100
	AddRemotes([]*types.Transaction) []error
101

102
	// Pending should return pending transactions.
103
	// The slice should be modifiable by the caller.
104
	Pending() (map[common.Address]types.Transactions, error)
105 106 107 108

	// SubscribeTxPreEvent should return an event subscription of
	// TxPreEvent and send events to the given channel.
	SubscribeTxPreEvent(chan<- core.TxPreEvent) event.Subscription
zelig's avatar
zelig committed
109 110
}

111 112 113
// statusData is the network packet for the status message.
type statusData struct {
	ProtocolVersion uint32
114
	NetworkId       uint64
115 116 117 118 119
	TD              *big.Int
	CurrentBlock    common.Hash
	GenesisBlock    common.Hash
}

120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169
// 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
}

170 171
// newBlockData is the network packet for the block propagation message.
type newBlockData struct {
172 173 174
	Block *types.Block
	TD    *big.Int
}
175

176 177 178 179 180 181 182 183
// 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