aboutsummaryrefslogtreecommitdiffstats
path: root/les/protocol.go
diff options
context:
space:
mode:
authorFelföldi Zsolt <zsfelfoldi@gmail.com>2017-10-24 21:19:09 +0800
committerFelix Lange <fjl@users.noreply.github.com>2017-10-24 21:19:09 +0800
commitca376ead88a5a26626a90abdb62f4de7f6313822 (patch)
tree71d11e3b6cd40d2bf29033b7e23d30d04e086558 /les/protocol.go
parent6d6a5a93370371a33fb815d7ae47b60c7021c86a (diff)
downloaddexon-ca376ead88a5a26626a90abdb62f4de7f6313822.tar
dexon-ca376ead88a5a26626a90abdb62f4de7f6313822.tar.gz
dexon-ca376ead88a5a26626a90abdb62f4de7f6313822.tar.bz2
dexon-ca376ead88a5a26626a90abdb62f4de7f6313822.tar.lz
dexon-ca376ead88a5a26626a90abdb62f4de7f6313822.tar.xz
dexon-ca376ead88a5a26626a90abdb62f4de7f6313822.tar.zst
dexon-ca376ead88a5a26626a90abdb62f4de7f6313822.zip
les, light: LES/2 protocol version (#14970)
This PR implements the new LES protocol version extensions: * new and more efficient Merkle proofs reply format (when replying to a multiple Merkle proofs request, we just send a single set of trie nodes containing all necessary nodes) * BBT (BloomBitsTrie) works similarly to the existing CHT and contains the bloombits search data to speed up log searches * GetTxStatusMsg returns the inclusion position or the pending/queued/unknown state of a transaction referenced by hash * an optional signature of new block data (number/hash/td) can be included in AnnounceMsg to provide an option for "very light clients" (mobile/embedded devices) to skip expensive Ethash check and accept multiple signatures of somewhat trusted servers (still a lot better than trusting a single server completely and retrieving everything through RPC). The new client mode is not implemented in this PR, just the protocol extension.
Diffstat (limited to 'les/protocol.go')
-rw-r--r--les/protocol.go64
1 files changed, 57 insertions, 7 deletions
diff --git a/les/protocol.go b/les/protocol.go
index 33d930ee0..146b02030 100644
--- a/les/protocol.go
+++ b/les/protocol.go
@@ -18,24 +18,34 @@
package les
import (
+ "bytes"
+ "crypto/ecdsa"
+ "crypto/elliptic"
+ "errors"
"fmt"
"io"
"math/big"
"github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/crypto"
+ "github.com/ethereum/go-ethereum/crypto/secp256k1"
"github.com/ethereum/go-ethereum/rlp"
)
// Constants to match up protocol versions and messages
const (
lpv1 = 1
+ lpv2 = 2
)
-// Supported versions of the les protocol (first is primary).
-var ProtocolVersions = []uint{lpv1}
+// Supported versions of the les protocol (first is primary)
+var (
+ ClientProtocolVersions = []uint{lpv2, lpv1}
+ ServerProtocolVersions = []uint{lpv2, lpv1}
+)
// Number of implemented message corresponding to different protocol versions.
-var ProtocolLengths = []uint64{15}
+var ProtocolLengths = map[uint]uint64{lpv1: 15, lpv2: 22}
const (
NetworkId = 1
@@ -53,13 +63,21 @@ const (
BlockBodiesMsg = 0x05
GetReceiptsMsg = 0x06
ReceiptsMsg = 0x07
- GetProofsMsg = 0x08
- ProofsMsg = 0x09
+ GetProofsV1Msg = 0x08
+ ProofsV1Msg = 0x09
GetCodeMsg = 0x0a
CodeMsg = 0x0b
SendTxMsg = 0x0c
GetHeaderProofsMsg = 0x0d
HeaderProofsMsg = 0x0e
+ // Protocol messages belonging to LPV2
+ GetProofsV2Msg = 0x0f
+ ProofsV2Msg = 0x10
+ GetHelperTrieProofsMsg = 0x11
+ HelperTrieProofsMsg = 0x12
+ SendTxV2Msg = 0x13
+ GetTxStatusMsg = 0x14
+ TxStatusMsg = 0x15
)
type errCode int
@@ -79,7 +97,7 @@ const (
ErrUnexpectedResponse
ErrInvalidResponse
ErrTooManyTimeouts
- ErrHandshakeMissingKey
+ ErrMissingKey
)
func (e errCode) String() string {
@@ -101,7 +119,13 @@ var errorToString = map[int]string{
ErrUnexpectedResponse: "Unexpected response",
ErrInvalidResponse: "Invalid response",
ErrTooManyTimeouts: "Too many request timeouts",
- ErrHandshakeMissingKey: "Key missing from handshake message",
+ ErrMissingKey: "Key missing from list",
+}
+
+type announceBlock 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
}
// announceData is the network packet for the block announcements.
@@ -113,6 +137,32 @@ type announceData struct {
Update keyValueList
}
+// sign adds a signature to the block announcement by the given privKey
+func (a *announceData) sign(privKey *ecdsa.PrivateKey) {
+ rlp, _ := rlp.EncodeToBytes(announceBlock{a.Hash, a.Number, a.Td})
+ sig, _ := crypto.Sign(crypto.Keccak256(rlp), privKey)
+ a.Update = a.Update.add("sign", sig)
+}
+
+// checkSignature verifies if the block announcement has a valid signature by the given pubKey
+func (a *announceData) checkSignature(pubKey *ecdsa.PublicKey) error {
+ var sig []byte
+ if err := a.Update.decode().get("sign", &sig); err != nil {
+ return err
+ }
+ rlp, _ := rlp.EncodeToBytes(announceBlock{a.Hash, a.Number, a.Td})
+ recPubkey, err := secp256k1.RecoverPubkey(crypto.Keccak256(rlp), sig)
+ if err != nil {
+ return err
+ }
+ pbytes := elliptic.Marshal(pubKey.Curve, pubKey.X, pubKey.Y)
+ if bytes.Equal(pbytes, recPubkey) {
+ return nil
+ } else {
+ return errors.New("Wrong signature")
+ }
+}
+
type blockInfo struct {
Hash common.Hash // Hash of one particular block being announced
Number uint64 // Number of one particular block being announced