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