aboutsummaryrefslogtreecommitdiffstats
path: root/les/protocol.go
diff options
context:
space:
mode:
Diffstat (limited to 'les/protocol.go')
-rw-r--r--les/protocol.go198
1 files changed, 198 insertions, 0 deletions
diff --git a/les/protocol.go b/les/protocol.go
new file mode 100644
index 000000000..46da2b8c8
--- /dev/null
+++ b/les/protocol.go
@@ -0,0 +1,198 @@
+// Copyright 2016 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 les implements the Light Ethereum Subprotocol.
+package les
+
+import (
+ "fmt"
+ "io"
+ "math/big"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/rlp"
+)
+
+// Constants to match up protocol versions and messages
+const (
+ lpv1 = 1
+)
+
+// Supported versions of the les protocol (first is primary).
+var ProtocolVersions = []uint{lpv1}
+
+// Number of implemented message corresponding to different protocol versions.
+var ProtocolLengths = []uint64{15}
+
+const (
+ NetworkId = 1
+ ProtocolMaxMsgSize = 10 * 1024 * 1024 // Maximum cap on the size of a protocol message
+)
+
+// les protocol message codes
+const (
+ // Protocol messages belonging to LPV1
+ StatusMsg = 0x00
+ AnnounceMsg = 0x01
+ GetBlockHeadersMsg = 0x02
+ BlockHeadersMsg = 0x03
+ GetBlockBodiesMsg = 0x04
+ BlockBodiesMsg = 0x05
+ GetReceiptsMsg = 0x06
+ ReceiptsMsg = 0x07
+ GetProofsMsg = 0x08
+ ProofsMsg = 0x09
+ GetCodeMsg = 0x0a
+ CodeMsg = 0x0b
+ SendTxMsg = 0x0c
+ GetHeaderProofsMsg = 0x0d
+ HeaderProofsMsg = 0x0e
+)
+
+type errCode int
+
+const (
+ ErrMsgTooLarge = iota
+ ErrDecode
+ ErrInvalidMsgCode
+ ErrProtocolVersionMismatch
+ ErrNetworkIdMismatch
+ ErrGenesisBlockMismatch
+ ErrNoStatusMsg
+ ErrExtraStatusMsg
+ ErrSuspendedPeer
+ ErrUselessPeer
+ ErrRequestRejected
+ ErrUnexpectedResponse
+ ErrInvalidResponse
+ ErrTooManyTimeouts
+ ErrHandshakeMissingKey
+)
+
+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: "NetworkId mismatch",
+ ErrGenesisBlockMismatch: "Genesis block mismatch",
+ ErrNoStatusMsg: "No status message",
+ ErrExtraStatusMsg: "Extra status message",
+ ErrSuspendedPeer: "Suspended peer",
+ ErrRequestRejected: "Request rejected",
+ ErrUnexpectedResponse: "Unexpected response",
+ ErrInvalidResponse: "Invalid response",
+ ErrTooManyTimeouts: "Too many request timeouts",
+ ErrHandshakeMissingKey: "Key missing from handshake message",
+}
+
+type chainManager interface {
+ GetBlockHashesFromHash(hash common.Hash, amount uint64) (hashes []common.Hash)
+ GetBlock(hash common.Hash) (block *types.Block)
+ Status() (td *big.Int, currentBlock common.Hash, genesisBlock common.Hash)
+}
+
+// announceData is the network packet for the block announcements.
+type announceData struct {
+ Hash common.Hash // Hash of one particular block being announced
+ Number uint64 // Number of one particular block being announced
+ Td *big.Int // Total difficulty of one particular block being announced
+ ReorgDepth uint64
+ Update keyValueList
+
+ haveHeaders uint64 // we have the headers of the remote peer's chain up to this number
+ headKnown bool
+ requested bool
+ next *announceData
+}
+
+type blockInfo struct {
+ Hash common.Hash // Hash of one particular block being announced
+ Number uint64 // Number of one particular block being announced
+ Td *big.Int // Total difficulty of one particular block being announced
+}
+
+// getBlockHashesData is the network packet for the hash based hash retrieval.
+type getBlockHashesData struct {
+ Hash common.Hash
+ Amount uint64
+}
+
+// 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
+}
+
+// blockBodiesData is the network packet for block content distribution.
+type blockBodiesData []*types.Body
+
+// CodeData is the network response packet for a node data retrieval.
+type CodeData []struct {
+ Value []byte
+}
+
+type proofsData [][]rlp.RawValue