mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-20 10:52:25 +00:00
les: move protocol definition to separate package
This commit is contained in:
parent
86d503ab15
commit
81aeba2798
20 changed files with 1021 additions and 867 deletions
|
|
@ -38,6 +38,7 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/eth"
|
"github.com/ethereum/go-ethereum/eth"
|
||||||
"github.com/ethereum/go-ethereum/event"
|
"github.com/ethereum/go-ethereum/event"
|
||||||
"github.com/ethereum/go-ethereum/les"
|
"github.com/ethereum/go-ethereum/les"
|
||||||
|
lesproto "github.com/ethereum/go-ethereum/les/protocol"
|
||||||
"github.com/ethereum/go-ethereum/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
"github.com/ethereum/go-ethereum/p2p"
|
"github.com/ethereum/go-ethereum/p2p"
|
||||||
"github.com/ethereum/go-ethereum/rpc"
|
"github.com/ethereum/go-ethereum/rpc"
|
||||||
|
|
@ -378,7 +379,7 @@ func (s *Service) login(conn *websocket.Conn) error {
|
||||||
protocol = fmt.Sprintf("eth/%d", eth.ProtocolVersions[0])
|
protocol = fmt.Sprintf("eth/%d", eth.ProtocolVersions[0])
|
||||||
} else {
|
} else {
|
||||||
network = fmt.Sprintf("%d", infos.Protocols["les"].(*les.NodeInfo).Network)
|
network = fmt.Sprintf("%d", infos.Protocols["les"].(*les.NodeInfo).Network)
|
||||||
protocol = fmt.Sprintf("les/%d", les.ClientProtocolVersions[0])
|
protocol = fmt.Sprintf("les/%d", lesproto.ClientProtocolVersions[0])
|
||||||
}
|
}
|
||||||
auth := &authMsg{
|
auth := &authMsg{
|
||||||
ID: s.node,
|
ID: s.node,
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,7 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
"github.com/ethereum/go-ethereum/les/flowcontrol"
|
"github.com/ethereum/go-ethereum/les/flowcontrol"
|
||||||
|
"github.com/ethereum/go-ethereum/les/protocol"
|
||||||
"github.com/ethereum/go-ethereum/les/utilities"
|
"github.com/ethereum/go-ethereum/les/utilities"
|
||||||
"github.com/ethereum/go-ethereum/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
"github.com/ethereum/go-ethereum/p2p"
|
"github.com/ethereum/go-ethereum/p2p"
|
||||||
|
|
@ -119,9 +120,9 @@ func (b *benchmarkProofsOrCode) request(peer *peer, index int) error {
|
||||||
key := make([]byte, 32)
|
key := make([]byte, 32)
|
||||||
rand.Read(key)
|
rand.Read(key)
|
||||||
if b.code {
|
if b.code {
|
||||||
return peer.RequestCode(0, 0, []CodeReq{{BHash: b.headHash, AccKey: key}})
|
return peer.RequestCode(0, 0, []protocol.CodeRequest{{BlockHash: b.headHash, Account: key}})
|
||||||
} else {
|
} else {
|
||||||
return peer.RequestProofs(0, 0, []ProofReq{{BHash: b.headHash, Key: key}})
|
return peer.RequestProofs(0, 0, []protocol.TrieProofRequest{{BlockHash: b.headHash, Key: key}})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -146,7 +147,7 @@ func (b *benchmarkHelperTrie) init(h *serverHandler, count int) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *benchmarkHelperTrie) request(peer *peer, index int) error {
|
func (b *benchmarkHelperTrie) request(peer *peer, index int) error {
|
||||||
reqs := make([]HelperTrieReq, b.reqCount)
|
reqs := make([]protocol.HelperTrieRequest, b.reqCount)
|
||||||
|
|
||||||
if b.bloom {
|
if b.bloom {
|
||||||
bitIdx := uint16(rand.Intn(2048))
|
bitIdx := uint16(rand.Intn(2048))
|
||||||
|
|
@ -154,13 +155,22 @@ func (b *benchmarkHelperTrie) request(peer *peer, index int) error {
|
||||||
key := make([]byte, 10)
|
key := make([]byte, 10)
|
||||||
binary.BigEndian.PutUint16(key[:2], bitIdx)
|
binary.BigEndian.PutUint16(key[:2], bitIdx)
|
||||||
binary.BigEndian.PutUint64(key[2:], uint64(rand.Int63n(int64(b.sectionCount))))
|
binary.BigEndian.PutUint64(key[2:], uint64(rand.Int63n(int64(b.sectionCount))))
|
||||||
reqs[i] = HelperTrieReq{Type: htBloomBits, TrieIdx: b.sectionCount - 1, Key: key}
|
reqs[i] = protocol.HelperTrieRequest{
|
||||||
|
Type: protocol.HelperTrieBloomTrie,
|
||||||
|
TrieIndex: b.sectionCount - 1,
|
||||||
|
Key: key,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for i := range reqs {
|
for i := range reqs {
|
||||||
key := make([]byte, 8)
|
key := make([]byte, 8)
|
||||||
binary.BigEndian.PutUint64(key[:], uint64(rand.Int63n(int64(b.headNum))))
|
binary.BigEndian.PutUint64(key[:], uint64(rand.Int63n(int64(b.headNum))))
|
||||||
reqs[i] = HelperTrieReq{Type: htCanonical, TrieIdx: b.sectionCount - 1, Key: key, AuxReq: auxHeader}
|
reqs[i] = protocol.HelperTrieRequest{
|
||||||
|
Type: protocol.HelperTrieCHT,
|
||||||
|
TrieIndex: b.sectionCount - 1,
|
||||||
|
Key: key,
|
||||||
|
AuxType: protocol.AuxHeader,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -284,13 +294,13 @@ func (h *serverHandler) measure(setup *benchmarkSetup, count int) error {
|
||||||
var id enode.ID
|
var id enode.ID
|
||||||
rand.Read(id[:])
|
rand.Read(id[:])
|
||||||
|
|
||||||
clientPeer := newPeer(lpv2, NetworkId, false, p2p.NewPeer(id, "client", nil), clientMeteredPipe)
|
clientPeer := newPeer(protocol.Lpv2, protocol.NetworkId, false, p2p.NewPeer(id, "client", nil), clientMeteredPipe)
|
||||||
serverPeer := newPeer(lpv2, NetworkId, false, p2p.NewPeer(id, "server", nil), serverMeteredPipe)
|
serverPeer := newPeer(protocol.Lpv2, protocol.NetworkId, false, p2p.NewPeer(id, "server", nil), serverMeteredPipe)
|
||||||
serverPeer.sendQueue = utilities.NewExecQueue(count)
|
serverPeer.sendQueue = utilities.NewExecQueue(count)
|
||||||
serverPeer.announceType = announceTypeNone
|
serverPeer.announceType = announceTypeNone
|
||||||
serverPeer.fcCosts = make(requestCostTable)
|
serverPeer.fcCosts = make(protocol.RequestCostTable)
|
||||||
c := &requestCosts{}
|
c := &protocol.RequestCost{}
|
||||||
for code := range requests {
|
for code := range protocol.LesRequests {
|
||||||
serverPeer.fcCosts[code] = c
|
serverPeer.fcCosts[code] = c
|
||||||
}
|
}
|
||||||
serverPeer.fcParams = flowcontrol.ServerParams{BufLimit: 1, MinRecharge: 1}
|
serverPeer.fcParams = flowcontrol.ServerParams{BufLimit: 1, MinRecharge: 1}
|
||||||
|
|
|
||||||
|
|
@ -37,6 +37,7 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/event"
|
"github.com/ethereum/go-ethereum/event"
|
||||||
"github.com/ethereum/go-ethereum/internal/ethapi"
|
"github.com/ethereum/go-ethereum/internal/ethapi"
|
||||||
"github.com/ethereum/go-ethereum/les/checkpointoracle"
|
"github.com/ethereum/go-ethereum/les/checkpointoracle"
|
||||||
|
"github.com/ethereum/go-ethereum/les/protocol"
|
||||||
"github.com/ethereum/go-ethereum/light"
|
"github.com/ethereum/go-ethereum/light"
|
||||||
"github.com/ethereum/go-ethereum/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
"github.com/ethereum/go-ethereum/node"
|
"github.com/ethereum/go-ethereum/node"
|
||||||
|
|
@ -217,14 +218,14 @@ func (s *LightEthereum) ResetWithGenesisBlock(gb *types.Block) {
|
||||||
func (s *LightEthereum) BlockChain() *light.LightChain { return s.blockchain }
|
func (s *LightEthereum) BlockChain() *light.LightChain { return s.blockchain }
|
||||||
func (s *LightEthereum) TxPool() *light.TxPool { return s.txPool }
|
func (s *LightEthereum) TxPool() *light.TxPool { return s.txPool }
|
||||||
func (s *LightEthereum) Engine() consensus.Engine { return s.engine }
|
func (s *LightEthereum) Engine() consensus.Engine { return s.engine }
|
||||||
func (s *LightEthereum) LesVersion() int { return int(ClientProtocolVersions[0]) }
|
func (s *LightEthereum) LesVersion() int { return int(protocol.ClientProtocolVersions[0]) }
|
||||||
func (s *LightEthereum) Downloader() *downloader.Downloader { return s.handler.downloader }
|
func (s *LightEthereum) Downloader() *downloader.Downloader { return s.handler.downloader }
|
||||||
func (s *LightEthereum) EventMux() *event.TypeMux { return s.eventMux }
|
func (s *LightEthereum) EventMux() *event.TypeMux { return s.eventMux }
|
||||||
|
|
||||||
// Protocols implements node.Service, returning all the currently configured
|
// Protocols implements node.Service, returning all the currently configured
|
||||||
// network protocols to start.
|
// network protocols to start.
|
||||||
func (s *LightEthereum) Protocols() []p2p.Protocol {
|
func (s *LightEthereum) Protocols() []p2p.Protocol {
|
||||||
return s.makeProtocols(ClientProtocolVersions, s.handler.runPeer, func(id enode.ID) interface{} {
|
return s.makeProtocols(protocol.ClientProtocolVersions, s.handler.runPeer, func(id enode.ID) interface{} {
|
||||||
if p := s.peers.Peer(peerIdToString(id)); p != nil {
|
if p := s.peers.Peer(peerIdToString(id)); p != nil {
|
||||||
return p.Info()
|
return p.Info()
|
||||||
}
|
}
|
||||||
|
|
@ -244,8 +245,8 @@ func (s *LightEthereum) Start(srvr *p2p.Server) error {
|
||||||
s.netRPCService = ethapi.NewPublicNetAPI(srvr, s.config.NetworkId)
|
s.netRPCService = ethapi.NewPublicNetAPI(srvr, s.config.NetworkId)
|
||||||
|
|
||||||
// clients are searching for the first advertised protocol in the list
|
// clients are searching for the first advertised protocol in the list
|
||||||
protocolVersion := AdvertiseProtocolVersions[0]
|
protocolVersion := protocol.AdvertiseProtocolVersions[0]
|
||||||
s.serverPool.start(srvr, lesTopic(s.blockchain.Genesis().Hash(), protocolVersion))
|
s.serverPool.start(srvr, protocol.LesTopic(s.blockchain.Genesis().Hash(), protocolVersion))
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,7 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/common/mclock"
|
"github.com/ethereum/go-ethereum/common/mclock"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/eth/downloader"
|
"github.com/ethereum/go-ethereum/eth/downloader"
|
||||||
|
"github.com/ethereum/go-ethereum/les/protocol"
|
||||||
"github.com/ethereum/go-ethereum/light"
|
"github.com/ethereum/go-ethereum/light"
|
||||||
"github.com/ethereum/go-ethereum/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
"github.com/ethereum/go-ethereum/p2p"
|
"github.com/ethereum/go-ethereum/p2p"
|
||||||
|
|
@ -151,8 +152,8 @@ func (h *clientHandler) handleMsg(p *peer) error {
|
||||||
}
|
}
|
||||||
p.Log().Trace("Light Ethereum message arrived", "code", msg.Code, "bytes", msg.Size)
|
p.Log().Trace("Light Ethereum message arrived", "code", msg.Code, "bytes", msg.Size)
|
||||||
|
|
||||||
if msg.Size > ProtocolMaxMsgSize {
|
if msg.Size > protocol.ProtocolMaxMsgSize {
|
||||||
return errResp(ErrMsgTooLarge, "%v > %v", msg.Size, ProtocolMaxMsgSize)
|
return protocol.ErrResp(protocol.ErrMsgTooLarge, "%v > %v", msg.Size, protocol.ProtocolMaxMsgSize)
|
||||||
}
|
}
|
||||||
defer msg.Discard()
|
defer msg.Discard()
|
||||||
|
|
||||||
|
|
@ -160,43 +161,43 @@ func (h *clientHandler) handleMsg(p *peer) error {
|
||||||
|
|
||||||
// Handle the message depending on its contents
|
// Handle the message depending on its contents
|
||||||
switch msg.Code {
|
switch msg.Code {
|
||||||
case AnnounceMsg:
|
case protocol.AnnounceMsg:
|
||||||
p.Log().Trace("Received announce message")
|
p.Log().Trace("Received announce message")
|
||||||
var req announceData
|
var anno protocol.Announcement
|
||||||
if err := msg.Decode(&req); err != nil {
|
if err := msg.Decode(&anno); err != nil {
|
||||||
return errResp(ErrDecode, "%v: %v", msg, err)
|
return protocol.ErrResp(protocol.ErrDecode, "%v: %v", msg, err)
|
||||||
}
|
}
|
||||||
if err := req.sanityCheck(); err != nil {
|
if err := anno.SanityCheck(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
update, size := req.Update.decode()
|
update, size := anno.Update.ToMap()
|
||||||
if p.rejectUpdate(size) {
|
if p.rejectUpdate(size) {
|
||||||
return errResp(ErrRequestRejected, "")
|
return protocol.ErrResp(protocol.ErrRequestRejected, "")
|
||||||
}
|
}
|
||||||
p.updateFlowControl(update)
|
p.updateFlowControl(update)
|
||||||
|
|
||||||
if req.Hash != (common.Hash{}) {
|
if anno.Hash != (common.Hash{}) {
|
||||||
if p.announceType == announceTypeNone {
|
if p.announceType == announceTypeNone {
|
||||||
return errResp(ErrUnexpectedResponse, "")
|
return protocol.ErrResp(protocol.ErrUnexpectedResponse, "")
|
||||||
}
|
}
|
||||||
if p.announceType == announceTypeSigned {
|
if p.announceType == announceTypeSigned {
|
||||||
if err := req.checkSignature(p.ID(), update); err != nil {
|
if err := anno.CheckSignature(p.ID(), update); err != nil {
|
||||||
p.Log().Trace("Invalid announcement signature", "err", err)
|
p.Log().Trace("Invalid announcement signature", "err", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
p.Log().Trace("Valid announcement signature")
|
p.Log().Trace("Valid announcement signature")
|
||||||
}
|
}
|
||||||
p.Log().Trace("Announce message content", "number", req.Number, "hash", req.Hash, "td", req.Td, "reorg", req.ReorgDepth)
|
p.Log().Trace("Announce message content", "number", anno.Number, "hash", anno.Hash, "td", anno.Td, "reorg", anno.ReorgDepth)
|
||||||
h.fetcher.announce(p, &req)
|
h.fetcher.announce(p, &anno)
|
||||||
}
|
}
|
||||||
case BlockHeadersMsg:
|
case protocol.BlockHeadersMsg:
|
||||||
p.Log().Trace("Received block header response message")
|
p.Log().Trace("Received block header response message")
|
||||||
var resp struct {
|
var resp struct {
|
||||||
ReqID, BV uint64
|
ReqID, BV uint64
|
||||||
Headers []*types.Header
|
Headers []*types.Header
|
||||||
}
|
}
|
||||||
if err := msg.Decode(&resp); err != nil {
|
if err := msg.Decode(&resp); err != nil {
|
||||||
return errResp(ErrDecode, "msg %v: %v", msg, err)
|
return protocol.ErrResp(protocol.ErrDecode, "msg %v: %v", msg, err)
|
||||||
}
|
}
|
||||||
p.fcServer.ReceivedReply(resp.ReqID, resp.BV)
|
p.fcServer.ReceivedReply(resp.ReqID, resp.BV)
|
||||||
if h.fetcher.requestedID(resp.ReqID) {
|
if h.fetcher.requestedID(resp.ReqID) {
|
||||||
|
|
@ -206,14 +207,14 @@ func (h *clientHandler) handleMsg(p *peer) error {
|
||||||
log.Debug("Failed to deliver headers", "err", err)
|
log.Debug("Failed to deliver headers", "err", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case BlockBodiesMsg:
|
case protocol.BlockBodiesMsg:
|
||||||
p.Log().Trace("Received block bodies response")
|
p.Log().Trace("Received block bodies response")
|
||||||
var resp struct {
|
var resp struct {
|
||||||
ReqID, BV uint64
|
ReqID, BV uint64
|
||||||
Data []*types.Body
|
Data []*types.Body
|
||||||
}
|
}
|
||||||
if err := msg.Decode(&resp); err != nil {
|
if err := msg.Decode(&resp); err != nil {
|
||||||
return errResp(ErrDecode, "msg %v: %v", msg, err)
|
return protocol.ErrResp(protocol.ErrDecode, "msg %v: %v", msg, err)
|
||||||
}
|
}
|
||||||
p.fcServer.ReceivedReply(resp.ReqID, resp.BV)
|
p.fcServer.ReceivedReply(resp.ReqID, resp.BV)
|
||||||
deliverMsg = &Msg{
|
deliverMsg = &Msg{
|
||||||
|
|
@ -221,14 +222,14 @@ func (h *clientHandler) handleMsg(p *peer) error {
|
||||||
ReqID: resp.ReqID,
|
ReqID: resp.ReqID,
|
||||||
Obj: resp.Data,
|
Obj: resp.Data,
|
||||||
}
|
}
|
||||||
case CodeMsg:
|
case protocol.CodeMsg:
|
||||||
p.Log().Trace("Received code response")
|
p.Log().Trace("Received code response")
|
||||||
var resp struct {
|
var resp struct {
|
||||||
ReqID, BV uint64
|
ReqID, BV uint64
|
||||||
Data [][]byte
|
Data [][]byte
|
||||||
}
|
}
|
||||||
if err := msg.Decode(&resp); err != nil {
|
if err := msg.Decode(&resp); err != nil {
|
||||||
return errResp(ErrDecode, "msg %v: %v", msg, err)
|
return protocol.ErrResp(protocol.ErrDecode, "msg %v: %v", msg, err)
|
||||||
}
|
}
|
||||||
p.fcServer.ReceivedReply(resp.ReqID, resp.BV)
|
p.fcServer.ReceivedReply(resp.ReqID, resp.BV)
|
||||||
deliverMsg = &Msg{
|
deliverMsg = &Msg{
|
||||||
|
|
@ -236,14 +237,14 @@ func (h *clientHandler) handleMsg(p *peer) error {
|
||||||
ReqID: resp.ReqID,
|
ReqID: resp.ReqID,
|
||||||
Obj: resp.Data,
|
Obj: resp.Data,
|
||||||
}
|
}
|
||||||
case ReceiptsMsg:
|
case protocol.ReceiptsMsg:
|
||||||
p.Log().Trace("Received receipts response")
|
p.Log().Trace("Received receipts response")
|
||||||
var resp struct {
|
var resp struct {
|
||||||
ReqID, BV uint64
|
ReqID, BV uint64
|
||||||
Receipts []types.Receipts
|
Receipts []types.Receipts
|
||||||
}
|
}
|
||||||
if err := msg.Decode(&resp); err != nil {
|
if err := msg.Decode(&resp); err != nil {
|
||||||
return errResp(ErrDecode, "msg %v: %v", msg, err)
|
return protocol.ErrResp(protocol.ErrDecode, "msg %v: %v", msg, err)
|
||||||
}
|
}
|
||||||
p.fcServer.ReceivedReply(resp.ReqID, resp.BV)
|
p.fcServer.ReceivedReply(resp.ReqID, resp.BV)
|
||||||
deliverMsg = &Msg{
|
deliverMsg = &Msg{
|
||||||
|
|
@ -251,14 +252,14 @@ func (h *clientHandler) handleMsg(p *peer) error {
|
||||||
ReqID: resp.ReqID,
|
ReqID: resp.ReqID,
|
||||||
Obj: resp.Receipts,
|
Obj: resp.Receipts,
|
||||||
}
|
}
|
||||||
case ProofsV2Msg:
|
case protocol.ProofsV2Msg:
|
||||||
p.Log().Trace("Received les/2 proofs response")
|
p.Log().Trace("Received les/2 proofs response")
|
||||||
var resp struct {
|
var resp struct {
|
||||||
ReqID, BV uint64
|
ReqID, BV uint64
|
||||||
Data light.NodeList
|
Data light.NodeList
|
||||||
}
|
}
|
||||||
if err := msg.Decode(&resp); err != nil {
|
if err := msg.Decode(&resp); err != nil {
|
||||||
return errResp(ErrDecode, "msg %v: %v", msg, err)
|
return protocol.ErrResp(protocol.ErrDecode, "msg %v: %v", msg, err)
|
||||||
}
|
}
|
||||||
p.fcServer.ReceivedReply(resp.ReqID, resp.BV)
|
p.fcServer.ReceivedReply(resp.ReqID, resp.BV)
|
||||||
deliverMsg = &Msg{
|
deliverMsg = &Msg{
|
||||||
|
|
@ -266,14 +267,14 @@ func (h *clientHandler) handleMsg(p *peer) error {
|
||||||
ReqID: resp.ReqID,
|
ReqID: resp.ReqID,
|
||||||
Obj: resp.Data,
|
Obj: resp.Data,
|
||||||
}
|
}
|
||||||
case HelperTrieProofsMsg:
|
case protocol.HelperTrieProofsMsg:
|
||||||
p.Log().Trace("Received helper trie proof response")
|
p.Log().Trace("Received helper trie proof response")
|
||||||
var resp struct {
|
var resp struct {
|
||||||
ReqID, BV uint64
|
ReqID, BV uint64
|
||||||
Data HelperTrieResps
|
Data protocol.HelperTrieResponse
|
||||||
}
|
}
|
||||||
if err := msg.Decode(&resp); err != nil {
|
if err := msg.Decode(&resp); err != nil {
|
||||||
return errResp(ErrDecode, "msg %v: %v", msg, err)
|
return protocol.ErrResp(protocol.ErrDecode, "msg %v: %v", msg, err)
|
||||||
}
|
}
|
||||||
p.fcServer.ReceivedReply(resp.ReqID, resp.BV)
|
p.fcServer.ReceivedReply(resp.ReqID, resp.BV)
|
||||||
deliverMsg = &Msg{
|
deliverMsg = &Msg{
|
||||||
|
|
@ -281,14 +282,14 @@ func (h *clientHandler) handleMsg(p *peer) error {
|
||||||
ReqID: resp.ReqID,
|
ReqID: resp.ReqID,
|
||||||
Obj: resp.Data,
|
Obj: resp.Data,
|
||||||
}
|
}
|
||||||
case TxStatusMsg:
|
case protocol.TxStatusMsg:
|
||||||
p.Log().Trace("Received tx status response")
|
p.Log().Trace("Received tx status response")
|
||||||
var resp struct {
|
var resp struct {
|
||||||
ReqID, BV uint64
|
ReqID, BV uint64
|
||||||
Status []light.TxStatus
|
Status []light.TxStatus
|
||||||
}
|
}
|
||||||
if err := msg.Decode(&resp); err != nil {
|
if err := msg.Decode(&resp); err != nil {
|
||||||
return errResp(ErrDecode, "msg %v: %v", msg, err)
|
return protocol.ErrResp(protocol.ErrDecode, "msg %v: %v", msg, err)
|
||||||
}
|
}
|
||||||
p.fcServer.ReceivedReply(resp.ReqID, resp.BV)
|
p.fcServer.ReceivedReply(resp.ReqID, resp.BV)
|
||||||
deliverMsg = &Msg{
|
deliverMsg = &Msg{
|
||||||
|
|
@ -296,21 +297,21 @@ func (h *clientHandler) handleMsg(p *peer) error {
|
||||||
ReqID: resp.ReqID,
|
ReqID: resp.ReqID,
|
||||||
Obj: resp.Status,
|
Obj: resp.Status,
|
||||||
}
|
}
|
||||||
case StopMsg:
|
case protocol.StopMsg:
|
||||||
p.freezeServer(true)
|
p.freezeServer(true)
|
||||||
h.backend.retriever.frozen(p)
|
h.backend.retriever.frozen(p)
|
||||||
p.Log().Debug("Service stopped")
|
p.Log().Debug("Service stopped")
|
||||||
case ResumeMsg:
|
case protocol.ResumeMsg:
|
||||||
var bv uint64
|
var bv uint64
|
||||||
if err := msg.Decode(&bv); err != nil {
|
if err := msg.Decode(&bv); err != nil {
|
||||||
return errResp(ErrDecode, "msg %v: %v", msg, err)
|
return protocol.ErrResp(protocol.ErrDecode, "msg %v: %v", msg, err)
|
||||||
}
|
}
|
||||||
p.fcServer.ResumeFreeze(bv)
|
p.fcServer.ResumeFreeze(bv)
|
||||||
p.freezeServer(false)
|
p.freezeServer(false)
|
||||||
p.Log().Debug("Service resumed")
|
p.Log().Debug("Service resumed")
|
||||||
default:
|
default:
|
||||||
p.Log().Trace("Received invalid message", "code", msg.Code)
|
p.Log().Trace("Received invalid message", "code", msg.Code)
|
||||||
return errResp(ErrInvalidMsgCode, "%v", msg.Code)
|
return protocol.ErrResp(protocol.ErrInvalidMsgCode, "%v", msg.Code)
|
||||||
}
|
}
|
||||||
// Deliver the received response to retriever.
|
// Deliver the received response to retriever.
|
||||||
if deliverMsg != nil {
|
if deliverMsg != nil {
|
||||||
|
|
@ -341,7 +342,7 @@ func (pc *peerConnection) RequestHeadersByHash(origin common.Hash, amount int, s
|
||||||
rq := &distReq{
|
rq := &distReq{
|
||||||
getCost: func(dp distPeer) uint64 {
|
getCost: func(dp distPeer) uint64 {
|
||||||
peer := dp.(*peer)
|
peer := dp.(*peer)
|
||||||
return peer.GetRequestCost(GetBlockHeadersMsg, amount)
|
return peer.GetRequestCost(protocol.GetBlockHeadersMsg, amount)
|
||||||
},
|
},
|
||||||
canSend: func(dp distPeer) bool {
|
canSend: func(dp distPeer) bool {
|
||||||
return dp.(*peer) == pc.peer
|
return dp.(*peer) == pc.peer
|
||||||
|
|
@ -349,7 +350,7 @@ func (pc *peerConnection) RequestHeadersByHash(origin common.Hash, amount int, s
|
||||||
request: func(dp distPeer) func() {
|
request: func(dp distPeer) func() {
|
||||||
reqID := genReqID()
|
reqID := genReqID()
|
||||||
peer := dp.(*peer)
|
peer := dp.(*peer)
|
||||||
cost := peer.GetRequestCost(GetBlockHeadersMsg, amount)
|
cost := peer.GetRequestCost(protocol.GetBlockHeadersMsg, amount)
|
||||||
peer.fcServer.QueuedRequest(reqID, cost)
|
peer.fcServer.QueuedRequest(reqID, cost)
|
||||||
return func() { peer.RequestHeadersByHash(reqID, cost, origin, amount, skip, reverse) }
|
return func() { peer.RequestHeadersByHash(reqID, cost, origin, amount, skip, reverse) }
|
||||||
},
|
},
|
||||||
|
|
@ -365,7 +366,7 @@ func (pc *peerConnection) RequestHeadersByNumber(origin uint64, amount int, skip
|
||||||
rq := &distReq{
|
rq := &distReq{
|
||||||
getCost: func(dp distPeer) uint64 {
|
getCost: func(dp distPeer) uint64 {
|
||||||
peer := dp.(*peer)
|
peer := dp.(*peer)
|
||||||
return peer.GetRequestCost(GetBlockHeadersMsg, amount)
|
return peer.GetRequestCost(protocol.GetBlockHeadersMsg, amount)
|
||||||
},
|
},
|
||||||
canSend: func(dp distPeer) bool {
|
canSend: func(dp distPeer) bool {
|
||||||
return dp.(*peer) == pc.peer
|
return dp.(*peer) == pc.peer
|
||||||
|
|
@ -373,7 +374,7 @@ func (pc *peerConnection) RequestHeadersByNumber(origin uint64, amount int, skip
|
||||||
request: func(dp distPeer) func() {
|
request: func(dp distPeer) func() {
|
||||||
reqID := genReqID()
|
reqID := genReqID()
|
||||||
peer := dp.(*peer)
|
peer := dp.(*peer)
|
||||||
cost := peer.GetRequestCost(GetBlockHeadersMsg, amount)
|
cost := peer.GetRequestCost(protocol.GetBlockHeadersMsg, amount)
|
||||||
peer.fcServer.QueuedRequest(reqID, cost)
|
peer.fcServer.QueuedRequest(reqID, cost)
|
||||||
return func() { peer.RequestHeadersByNumber(reqID, cost, origin, amount, skip, reverse) }
|
return func() { peer.RequestHeadersByNumber(reqID, cost, origin, amount, skip, reverse) }
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,6 @@
|
||||||
package les
|
package les
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"math/big"
|
"math/big"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
|
|
@ -28,28 +27,13 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/eth"
|
"github.com/ethereum/go-ethereum/eth"
|
||||||
"github.com/ethereum/go-ethereum/ethdb"
|
"github.com/ethereum/go-ethereum/ethdb"
|
||||||
"github.com/ethereum/go-ethereum/les/checkpointoracle"
|
"github.com/ethereum/go-ethereum/les/checkpointoracle"
|
||||||
|
"github.com/ethereum/go-ethereum/les/protocol"
|
||||||
"github.com/ethereum/go-ethereum/light"
|
"github.com/ethereum/go-ethereum/light"
|
||||||
"github.com/ethereum/go-ethereum/p2p"
|
"github.com/ethereum/go-ethereum/p2p"
|
||||||
"github.com/ethereum/go-ethereum/p2p/discv5"
|
|
||||||
"github.com/ethereum/go-ethereum/p2p/enode"
|
"github.com/ethereum/go-ethereum/p2p/enode"
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
)
|
)
|
||||||
|
|
||||||
func errResp(code errCode, format string, v ...interface{}) error {
|
|
||||||
return fmt.Errorf("%v - %v", code, fmt.Sprintf(format, v...))
|
|
||||||
}
|
|
||||||
|
|
||||||
func lesTopic(genesisHash common.Hash, protocolVersion uint) discv5.Topic {
|
|
||||||
var name string
|
|
||||||
switch protocolVersion {
|
|
||||||
case lpv2:
|
|
||||||
name = "LES2"
|
|
||||||
default:
|
|
||||||
panic(nil)
|
|
||||||
}
|
|
||||||
return discv5.Topic(name + "@" + common.Bytes2Hex(genesisHash.Bytes()[0:8]))
|
|
||||||
}
|
|
||||||
|
|
||||||
type chainReader interface {
|
type chainReader interface {
|
||||||
CurrentHeader() *types.Header
|
CurrentHeader() *types.Header
|
||||||
}
|
}
|
||||||
|
|
@ -89,7 +73,7 @@ func (c *lesCommons) makeProtocols(versions []uint, runPeer func(version uint, p
|
||||||
protos[i] = p2p.Protocol{
|
protos[i] = p2p.Protocol{
|
||||||
Name: "les",
|
Name: "les",
|
||||||
Version: version,
|
Version: version,
|
||||||
Length: ProtocolLengths[version],
|
Length: protocol.ProtocolLengths[version],
|
||||||
NodeInfo: c.nodeInfo,
|
NodeInfo: c.nodeInfo,
|
||||||
Run: func(peer *p2p.Peer, rw p2p.MsgReadWriter) error {
|
Run: func(peer *p2p.Peer, rw p2p.MsgReadWriter) error {
|
||||||
return runPeer(version, peer, rw)
|
return runPeer(version, peer, rw)
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,7 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/eth"
|
"github.com/ethereum/go-ethereum/eth"
|
||||||
"github.com/ethereum/go-ethereum/ethdb"
|
"github.com/ethereum/go-ethereum/ethdb"
|
||||||
"github.com/ethereum/go-ethereum/les/flowcontrol"
|
"github.com/ethereum/go-ethereum/les/flowcontrol"
|
||||||
|
"github.com/ethereum/go-ethereum/les/protocol"
|
||||||
"github.com/ethereum/go-ethereum/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
"github.com/ethereum/go-ethereum/metrics"
|
"github.com/ethereum/go-ethereum/metrics"
|
||||||
)
|
)
|
||||||
|
|
@ -35,48 +36,48 @@ const makeCostStats = false // make request cost statistics during operation
|
||||||
|
|
||||||
var (
|
var (
|
||||||
// average request cost estimates based on serving time
|
// average request cost estimates based on serving time
|
||||||
reqAvgTimeCost = requestCostTable{
|
reqAvgTimeCost = protocol.RequestCostTable{
|
||||||
GetBlockHeadersMsg: {150000, 30000},
|
protocol.GetBlockHeadersMsg: {150000, 30000},
|
||||||
GetBlockBodiesMsg: {0, 700000},
|
protocol.GetBlockBodiesMsg: {0, 700000},
|
||||||
GetReceiptsMsg: {0, 1000000},
|
protocol.GetReceiptsMsg: {0, 1000000},
|
||||||
GetCodeMsg: {0, 450000},
|
protocol.GetCodeMsg: {0, 450000},
|
||||||
GetProofsV2Msg: {0, 600000},
|
protocol.GetProofsV2Msg: {0, 600000},
|
||||||
GetHelperTrieProofsMsg: {0, 1000000},
|
protocol.GetHelperTrieProofsMsg: {0, 1000000},
|
||||||
SendTxV2Msg: {0, 450000},
|
protocol.SendTxV2Msg: {0, 450000},
|
||||||
GetTxStatusMsg: {0, 250000},
|
protocol.GetTxStatusMsg: {0, 250000},
|
||||||
}
|
}
|
||||||
// maximum incoming message size estimates
|
// maximum incoming message size estimates
|
||||||
reqMaxInSize = requestCostTable{
|
reqMaxInSize = protocol.RequestCostTable{
|
||||||
GetBlockHeadersMsg: {40, 0},
|
protocol.GetBlockHeadersMsg: {40, 0},
|
||||||
GetBlockBodiesMsg: {0, 40},
|
protocol.GetBlockBodiesMsg: {0, 40},
|
||||||
GetReceiptsMsg: {0, 40},
|
protocol.GetReceiptsMsg: {0, 40},
|
||||||
GetCodeMsg: {0, 80},
|
protocol.GetCodeMsg: {0, 80},
|
||||||
GetProofsV2Msg: {0, 80},
|
protocol.GetProofsV2Msg: {0, 80},
|
||||||
GetHelperTrieProofsMsg: {0, 20},
|
protocol.GetHelperTrieProofsMsg: {0, 20},
|
||||||
SendTxV2Msg: {0, 16500},
|
protocol.SendTxV2Msg: {0, 16500},
|
||||||
GetTxStatusMsg: {0, 50},
|
protocol.GetTxStatusMsg: {0, 50},
|
||||||
}
|
}
|
||||||
// maximum outgoing message size estimates
|
// maximum outgoing message size estimates
|
||||||
reqMaxOutSize = requestCostTable{
|
reqMaxOutSize = protocol.RequestCostTable{
|
||||||
GetBlockHeadersMsg: {0, 556},
|
protocol.GetBlockHeadersMsg: {0, 556},
|
||||||
GetBlockBodiesMsg: {0, 100000},
|
protocol.GetBlockBodiesMsg: {0, 100000},
|
||||||
GetReceiptsMsg: {0, 200000},
|
protocol.GetReceiptsMsg: {0, 200000},
|
||||||
GetCodeMsg: {0, 50000},
|
protocol.GetCodeMsg: {0, 50000},
|
||||||
GetProofsV2Msg: {0, 4000},
|
protocol.GetProofsV2Msg: {0, 4000},
|
||||||
GetHelperTrieProofsMsg: {0, 4000},
|
protocol.GetHelperTrieProofsMsg: {0, 4000},
|
||||||
SendTxV2Msg: {0, 100},
|
protocol.SendTxV2Msg: {0, 100},
|
||||||
GetTxStatusMsg: {0, 100},
|
protocol.GetTxStatusMsg: {0, 100},
|
||||||
}
|
}
|
||||||
// request amounts that have to fit into the minimum buffer size minBufferMultiplier times
|
// request amounts that have to fit into the minimum buffer size minBufferMultiplier times
|
||||||
minBufferReqAmount = map[uint64]uint64{
|
minBufferReqAmount = map[uint64]uint64{
|
||||||
GetBlockHeadersMsg: 192,
|
protocol.GetBlockHeadersMsg: 192,
|
||||||
GetBlockBodiesMsg: 1,
|
protocol.GetBlockBodiesMsg: 1,
|
||||||
GetReceiptsMsg: 1,
|
protocol.GetReceiptsMsg: 1,
|
||||||
GetCodeMsg: 1,
|
protocol.GetCodeMsg: 1,
|
||||||
GetProofsV2Msg: 1,
|
protocol.GetProofsV2Msg: 1,
|
||||||
GetHelperTrieProofsMsg: 16,
|
protocol.GetHelperTrieProofsMsg: 16,
|
||||||
SendTxV2Msg: 8,
|
protocol.SendTxV2Msg: 8,
|
||||||
GetTxStatusMsg: 64,
|
protocol.GetTxStatusMsg: 64,
|
||||||
}
|
}
|
||||||
minBufferMultiplier = 3
|
minBufferMultiplier = 3
|
||||||
)
|
)
|
||||||
|
|
@ -131,8 +132,8 @@ type costTracker struct {
|
||||||
stats map[uint64][]uint64 // Used for testing purpose.
|
stats map[uint64][]uint64 // Used for testing purpose.
|
||||||
|
|
||||||
// TestHooks
|
// TestHooks
|
||||||
testing bool // Disable real cost evaluation for testing purpose.
|
testing bool // Disable real cost evaluation for testing purpose.
|
||||||
testCostList RequestCostList // Customized cost table for testing purpose.
|
testCostList protocol.RequestCostList // Customized cost table for testing purpose.
|
||||||
}
|
}
|
||||||
|
|
||||||
// newCostTracker creates a cost tracker and loads the cost factor statistics from the database.
|
// newCostTracker creates a cost tracker and loads the cost factor statistics from the database.
|
||||||
|
|
@ -182,7 +183,7 @@ func (ct *costTracker) stop() {
|
||||||
|
|
||||||
// makeCostList returns upper cost estimates based on the hardcoded cost estimate
|
// makeCostList returns upper cost estimates based on the hardcoded cost estimate
|
||||||
// tables and the optionally specified incoming/outgoing bandwidth limits
|
// tables and the optionally specified incoming/outgoing bandwidth limits
|
||||||
func (ct *costTracker) makeCostList(globalFactor float64) RequestCostList {
|
func (ct *costTracker) makeCostList(globalFactor float64) protocol.RequestCostList {
|
||||||
maxCost := func(avgTimeCost, inSize, outSize uint64) uint64 {
|
maxCost := func(avgTimeCost, inSize, outSize uint64) uint64 {
|
||||||
cost := avgTimeCost * maxCostFactor
|
cost := avgTimeCost * maxCostFactor
|
||||||
inSizeCost := uint64(float64(inSize) * ct.inSizeFactor * globalFactor)
|
inSizeCost := uint64(float64(inSize) * ct.inSizeFactor * globalFactor)
|
||||||
|
|
@ -195,10 +196,10 @@ func (ct *costTracker) makeCostList(globalFactor float64) RequestCostList {
|
||||||
}
|
}
|
||||||
return cost
|
return cost
|
||||||
}
|
}
|
||||||
var list RequestCostList
|
var list protocol.RequestCostList
|
||||||
for code, data := range reqAvgTimeCost {
|
for code, data := range reqAvgTimeCost {
|
||||||
baseCost := maxCost(data.baseCost, reqMaxInSize[code].baseCost, reqMaxOutSize[code].baseCost)
|
baseCost := maxCost(data.BaseCost, reqMaxInSize[code].BaseCost, reqMaxOutSize[code].BaseCost)
|
||||||
reqCost := maxCost(data.reqCost, reqMaxInSize[code].reqCost, reqMaxOutSize[code].reqCost)
|
reqCost := maxCost(data.ReqCost, reqMaxInSize[code].ReqCost, reqMaxOutSize[code].ReqCost)
|
||||||
if ct.minBufLimit != 0 {
|
if ct.minBufLimit != 0 {
|
||||||
// if minBufLimit is set then always enforce maximum request cost <= minBufLimit
|
// if minBufLimit is set then always enforce maximum request cost <= minBufLimit
|
||||||
maxCost := baseCost + reqCost*minBufferReqAmount[code]
|
maxCost := baseCost + reqCost*minBufferReqAmount[code]
|
||||||
|
|
@ -209,7 +210,7 @@ func (ct *costTracker) makeCostList(globalFactor float64) RequestCostList {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
list = append(list, requestCostListItem{
|
list = append(list, protocol.RequestCostListItem{
|
||||||
MsgCode: code,
|
MsgCode: code,
|
||||||
BaseCost: baseCost,
|
BaseCost: baseCost,
|
||||||
ReqCost: reqCost,
|
ReqCost: reqCost,
|
||||||
|
|
@ -278,21 +279,21 @@ func (ct *costTracker) gfLoop() {
|
||||||
// Record more metrics if we are debugging
|
// Record more metrics if we are debugging
|
||||||
if metrics.EnabledExpensive {
|
if metrics.EnabledExpensive {
|
||||||
switch r.msgCode {
|
switch r.msgCode {
|
||||||
case GetBlockHeadersMsg:
|
case protocol.GetBlockHeadersMsg:
|
||||||
relativeCostHeaderHistogram.Update(relCost)
|
relativeCostHeaderHistogram.Update(relCost)
|
||||||
case GetBlockBodiesMsg:
|
case protocol.GetBlockBodiesMsg:
|
||||||
relativeCostBodyHistogram.Update(relCost)
|
relativeCostBodyHistogram.Update(relCost)
|
||||||
case GetReceiptsMsg:
|
case protocol.GetReceiptsMsg:
|
||||||
relativeCostReceiptHistogram.Update(relCost)
|
relativeCostReceiptHistogram.Update(relCost)
|
||||||
case GetCodeMsg:
|
case protocol.GetCodeMsg:
|
||||||
relativeCostCodeHistogram.Update(relCost)
|
relativeCostCodeHistogram.Update(relCost)
|
||||||
case GetProofsV2Msg:
|
case protocol.GetProofsV2Msg:
|
||||||
relativeCostProofHistogram.Update(relCost)
|
relativeCostProofHistogram.Update(relCost)
|
||||||
case GetHelperTrieProofsMsg:
|
case protocol.GetHelperTrieProofsMsg:
|
||||||
relativeCostHelperProofHistogram.Update(relCost)
|
relativeCostHelperProofHistogram.Update(relCost)
|
||||||
case SendTxV2Msg:
|
case protocol.SendTxV2Msg:
|
||||||
relativeCostSendTxHistogram.Update(relCost)
|
relativeCostSendTxHistogram.Update(relCost)
|
||||||
case GetTxStatusMsg:
|
case protocol.GetTxStatusMsg:
|
||||||
relativeCostTxStatusHistogram.Update(relCost)
|
relativeCostTxStatusHistogram.Update(relCost)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -302,7 +303,7 @@ func (ct *costTracker) gfLoop() {
|
||||||
// requests involve txpool query, which is usually unstable.
|
// requests involve txpool query, which is usually unstable.
|
||||||
//
|
//
|
||||||
// TODO(rjl493456442) fixes this.
|
// TODO(rjl493456442) fixes this.
|
||||||
if r.msgCode == SendTxV2Msg || r.msgCode == GetTxStatusMsg {
|
if r.msgCode == protocol.SendTxV2Msg || r.msgCode == protocol.GetTxStatusMsg {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
requestServedMeter.Mark(int64(r.servingTime))
|
requestServedMeter.Mark(int64(r.servingTime))
|
||||||
|
|
@ -410,7 +411,7 @@ func (ct *costTracker) subscribeTotalRecharge(ch chan uint64) uint64 {
|
||||||
// average estimate statistics
|
// average estimate statistics
|
||||||
func (ct *costTracker) updateStats(code, amount, servingTime, realCost uint64) {
|
func (ct *costTracker) updateStats(code, amount, servingTime, realCost uint64) {
|
||||||
avg := reqAvgTimeCost[code]
|
avg := reqAvgTimeCost[code]
|
||||||
avgTimeCost := avg.baseCost + amount*avg.reqCost
|
avgTimeCost := avg.BaseCost + amount*avg.ReqCost
|
||||||
select {
|
select {
|
||||||
case ct.reqInfoCh <- reqInfo{float64(avgTimeCost), float64(servingTime), code}:
|
case ct.reqInfoCh <- reqInfo{float64(avgTimeCost), float64(servingTime), code}:
|
||||||
default:
|
default:
|
||||||
|
|
@ -457,46 +458,9 @@ func (ct *costTracker) printStats() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type (
|
|
||||||
// requestCostTable assigns a cost estimate function to each request type
|
|
||||||
// which is a linear function of the requested amount
|
|
||||||
// (cost = baseCost + reqCost * amount)
|
|
||||||
requestCostTable map[uint64]*requestCosts
|
|
||||||
requestCosts struct {
|
|
||||||
baseCost, reqCost uint64
|
|
||||||
}
|
|
||||||
|
|
||||||
// RequestCostList is a list representation of request costs which is used for
|
|
||||||
// database storage and communication through the network
|
|
||||||
RequestCostList []requestCostListItem
|
|
||||||
requestCostListItem struct {
|
|
||||||
MsgCode, BaseCost, ReqCost uint64
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
// getMaxCost calculates the estimated cost for a given request type and amount
|
|
||||||
func (table requestCostTable) getMaxCost(code, amount uint64) uint64 {
|
|
||||||
costs := table[code]
|
|
||||||
return costs.baseCost + amount*costs.reqCost
|
|
||||||
}
|
|
||||||
|
|
||||||
// decode converts a cost list to a cost table
|
|
||||||
func (list RequestCostList) decode(protocolLength uint64) requestCostTable {
|
|
||||||
table := make(requestCostTable)
|
|
||||||
for _, e := range list {
|
|
||||||
if e.MsgCode < protocolLength {
|
|
||||||
table[e.MsgCode] = &requestCosts{
|
|
||||||
baseCost: e.BaseCost,
|
|
||||||
reqCost: e.ReqCost,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return table
|
|
||||||
}
|
|
||||||
|
|
||||||
// testCostList returns a dummy request cost list used by tests
|
// testCostList returns a dummy request cost list used by tests
|
||||||
func testCostList(testCost uint64) RequestCostList {
|
func testCostList(testCost uint64) protocol.RequestCostList {
|
||||||
cl := make(RequestCostList, len(reqAvgTimeCost))
|
cl := make(protocol.RequestCostList, len(reqAvgTimeCost))
|
||||||
var max uint64
|
var max uint64
|
||||||
for code := range reqAvgTimeCost {
|
for code := range reqAvgTimeCost {
|
||||||
if code > max {
|
if code > max {
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,7 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/consensus"
|
"github.com/ethereum/go-ethereum/consensus"
|
||||||
"github.com/ethereum/go-ethereum/core/rawdb"
|
"github.com/ethereum/go-ethereum/core/rawdb"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
|
"github.com/ethereum/go-ethereum/les/protocol"
|
||||||
"github.com/ethereum/go-ethereum/light"
|
"github.com/ethereum/go-ethereum/light"
|
||||||
"github.com/ethereum/go-ethereum/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
)
|
)
|
||||||
|
|
@ -250,7 +251,7 @@ func (f *lightFetcher) unregisterPeer(p *peer) {
|
||||||
|
|
||||||
// announce processes a new announcement message received from a peer, adding new
|
// announce processes a new announcement message received from a peer, adding new
|
||||||
// nodes to the peer's block tree and removing old nodes if necessary
|
// nodes to the peer's block tree and removing old nodes if necessary
|
||||||
func (f *lightFetcher) announce(p *peer, head *announceData) {
|
func (f *lightFetcher) announce(p *peer, head *protocol.Announcement) {
|
||||||
f.lock.Lock()
|
f.lock.Lock()
|
||||||
defer f.lock.Unlock()
|
defer f.lock.Unlock()
|
||||||
p.Log().Debug("Received new announcement", "number", head.Number, "hash", head.Hash, "reorg", head.ReorgDepth)
|
p.Log().Debug("Received new announcement", "number", head.Number, "hash", head.Hash, "reorg", head.ReorgDepth)
|
||||||
|
|
@ -519,7 +520,7 @@ func (f *lightFetcher) newFetcherDistReq(bestHash common.Hash, reqID uint64, bes
|
||||||
return &distReq{
|
return &distReq{
|
||||||
getCost: func(dp distPeer) uint64 {
|
getCost: func(dp distPeer) uint64 {
|
||||||
p := dp.(*peer)
|
p := dp.(*peer)
|
||||||
return p.GetRequestCost(GetBlockHeadersMsg, int(bestAmount))
|
return p.GetRequestCost(protocol.GetBlockHeadersMsg, int(bestAmount))
|
||||||
},
|
},
|
||||||
canSend: func(dp distPeer) bool {
|
canSend: func(dp distPeer) bool {
|
||||||
p := dp.(*peer)
|
p := dp.(*peer)
|
||||||
|
|
@ -548,7 +549,7 @@ func (f *lightFetcher) newFetcherDistReq(bestHash common.Hash, reqID uint64, bes
|
||||||
}
|
}
|
||||||
f.lock.Unlock()
|
f.lock.Unlock()
|
||||||
|
|
||||||
cost := p.GetRequestCost(GetBlockHeadersMsg, int(bestAmount))
|
cost := p.GetRequestCost(protocol.GetBlockHeadersMsg, int(bestAmount))
|
||||||
p.fcServer.QueuedRequest(reqID, cost)
|
p.fcServer.QueuedRequest(reqID, cost)
|
||||||
f.reqMu.Lock()
|
f.reqMu.Lock()
|
||||||
f.requested[reqID] = fetchRequest{hash: bestHash, amount: bestAmount, peer: p, sent: mclock.Now()}
|
f.requested[reqID] = fetchRequest{hash: bestHash, amount: bestAmount, peer: p, sent: mclock.Now()}
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,7 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
"github.com/ethereum/go-ethereum/eth/downloader"
|
"github.com/ethereum/go-ethereum/eth/downloader"
|
||||||
|
"github.com/ethereum/go-ethereum/les/protocol"
|
||||||
"github.com/ethereum/go-ethereum/light"
|
"github.com/ethereum/go-ethereum/light"
|
||||||
"github.com/ethereum/go-ethereum/p2p"
|
"github.com/ethereum/go-ethereum/p2p"
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
|
|
@ -50,8 +51,8 @@ func expectResponse(r p2p.MsgReader, msgcode, reqID, bv uint64, data interface{}
|
||||||
func TestGetBlockHeadersLes2(t *testing.T) { testGetBlockHeaders(t, 2) }
|
func TestGetBlockHeadersLes2(t *testing.T) { testGetBlockHeaders(t, 2) }
|
||||||
func TestGetBlockHeadersLes3(t *testing.T) { testGetBlockHeaders(t, 3) }
|
func TestGetBlockHeadersLes3(t *testing.T) { testGetBlockHeaders(t, 3) }
|
||||||
|
|
||||||
func testGetBlockHeaders(t *testing.T, protocol int) {
|
func testGetBlockHeaders(t *testing.T, p int) {
|
||||||
server, tearDown := newServerEnv(t, downloader.MaxHashFetch+15, protocol, nil, false, true, 0)
|
server, tearDown := newServerEnv(t, downloader.MaxHashFetch+15, p, nil, false, true, 0)
|
||||||
defer tearDown()
|
defer tearDown()
|
||||||
|
|
||||||
bc := server.handler.blockchain
|
bc := server.handler.blockchain
|
||||||
|
|
@ -62,29 +63,29 @@ func testGetBlockHeaders(t *testing.T, protocol int) {
|
||||||
unknown[i] = byte(i)
|
unknown[i] = byte(i)
|
||||||
}
|
}
|
||||||
// Create a batch of tests for various scenarios
|
// Create a batch of tests for various scenarios
|
||||||
limit := uint64(MaxHeaderFetch)
|
limit := uint64(protocol.MaxHeaderFetch)
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
query *getBlockHeadersData // The query to execute for header retrieval
|
query *protocol.GetBlockHeadersRequest // The query to execute for header retrieval
|
||||||
expect []common.Hash // The hashes of the block whose headers are expected
|
expect []common.Hash // The hashes of the block whose headers are expected
|
||||||
}{
|
}{
|
||||||
// A single random block should be retrievable by hash and number too
|
// A single random block should be retrievable by hash and number too
|
||||||
{
|
{
|
||||||
&getBlockHeadersData{Origin: hashOrNumber{Hash: bc.GetBlockByNumber(limit / 2).Hash()}, Amount: 1},
|
&protocol.GetBlockHeadersRequest{Origin: protocol.HashOrNumber{Hash: bc.GetBlockByNumber(limit / 2).Hash()}, Amount: 1},
|
||||||
[]common.Hash{bc.GetBlockByNumber(limit / 2).Hash()},
|
[]common.Hash{bc.GetBlockByNumber(limit / 2).Hash()},
|
||||||
}, {
|
}, {
|
||||||
&getBlockHeadersData{Origin: hashOrNumber{Number: limit / 2}, Amount: 1},
|
&protocol.GetBlockHeadersRequest{Origin: protocol.HashOrNumber{Number: limit / 2}, Amount: 1},
|
||||||
[]common.Hash{bc.GetBlockByNumber(limit / 2).Hash()},
|
[]common.Hash{bc.GetBlockByNumber(limit / 2).Hash()},
|
||||||
},
|
},
|
||||||
// Multiple headers should be retrievable in both directions
|
// Multiple headers should be retrievable in both directions
|
||||||
{
|
{
|
||||||
&getBlockHeadersData{Origin: hashOrNumber{Number: limit / 2}, Amount: 3},
|
&protocol.GetBlockHeadersRequest{Origin: protocol.HashOrNumber{Number: limit / 2}, Amount: 3},
|
||||||
[]common.Hash{
|
[]common.Hash{
|
||||||
bc.GetBlockByNumber(limit / 2).Hash(),
|
bc.GetBlockByNumber(limit / 2).Hash(),
|
||||||
bc.GetBlockByNumber(limit/2 + 1).Hash(),
|
bc.GetBlockByNumber(limit/2 + 1).Hash(),
|
||||||
bc.GetBlockByNumber(limit/2 + 2).Hash(),
|
bc.GetBlockByNumber(limit/2 + 2).Hash(),
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
&getBlockHeadersData{Origin: hashOrNumber{Number: limit / 2}, Amount: 3, Reverse: true},
|
&protocol.GetBlockHeadersRequest{Origin: protocol.HashOrNumber{Number: limit / 2}, Amount: 3, Reverse: true},
|
||||||
[]common.Hash{
|
[]common.Hash{
|
||||||
bc.GetBlockByNumber(limit / 2).Hash(),
|
bc.GetBlockByNumber(limit / 2).Hash(),
|
||||||
bc.GetBlockByNumber(limit/2 - 1).Hash(),
|
bc.GetBlockByNumber(limit/2 - 1).Hash(),
|
||||||
|
|
@ -93,14 +94,14 @@ func testGetBlockHeaders(t *testing.T, protocol int) {
|
||||||
},
|
},
|
||||||
// Multiple headers with skip lists should be retrievable
|
// Multiple headers with skip lists should be retrievable
|
||||||
{
|
{
|
||||||
&getBlockHeadersData{Origin: hashOrNumber{Number: limit / 2}, Skip: 3, Amount: 3},
|
&protocol.GetBlockHeadersRequest{Origin: protocol.HashOrNumber{Number: limit / 2}, Skip: 3, Amount: 3},
|
||||||
[]common.Hash{
|
[]common.Hash{
|
||||||
bc.GetBlockByNumber(limit / 2).Hash(),
|
bc.GetBlockByNumber(limit / 2).Hash(),
|
||||||
bc.GetBlockByNumber(limit/2 + 4).Hash(),
|
bc.GetBlockByNumber(limit/2 + 4).Hash(),
|
||||||
bc.GetBlockByNumber(limit/2 + 8).Hash(),
|
bc.GetBlockByNumber(limit/2 + 8).Hash(),
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
&getBlockHeadersData{Origin: hashOrNumber{Number: limit / 2}, Skip: 3, Amount: 3, Reverse: true},
|
&protocol.GetBlockHeadersRequest{Origin: protocol.HashOrNumber{Number: limit / 2}, Skip: 3, Amount: 3, Reverse: true},
|
||||||
[]common.Hash{
|
[]common.Hash{
|
||||||
bc.GetBlockByNumber(limit / 2).Hash(),
|
bc.GetBlockByNumber(limit / 2).Hash(),
|
||||||
bc.GetBlockByNumber(limit/2 - 4).Hash(),
|
bc.GetBlockByNumber(limit/2 - 4).Hash(),
|
||||||
|
|
@ -109,26 +110,26 @@ func testGetBlockHeaders(t *testing.T, protocol int) {
|
||||||
},
|
},
|
||||||
// The chain endpoints should be retrievable
|
// The chain endpoints should be retrievable
|
||||||
{
|
{
|
||||||
&getBlockHeadersData{Origin: hashOrNumber{Number: 0}, Amount: 1},
|
&protocol.GetBlockHeadersRequest{Origin: protocol.HashOrNumber{Number: 0}, Amount: 1},
|
||||||
[]common.Hash{bc.GetBlockByNumber(0).Hash()},
|
[]common.Hash{bc.GetBlockByNumber(0).Hash()},
|
||||||
}, {
|
}, {
|
||||||
&getBlockHeadersData{Origin: hashOrNumber{Number: bc.CurrentBlock().NumberU64()}, Amount: 1},
|
&protocol.GetBlockHeadersRequest{Origin: protocol.HashOrNumber{Number: bc.CurrentBlock().NumberU64()}, Amount: 1},
|
||||||
[]common.Hash{bc.CurrentBlock().Hash()},
|
[]common.Hash{bc.CurrentBlock().Hash()},
|
||||||
},
|
},
|
||||||
// Ensure protocol limits are honored
|
// Ensure p limits are honored
|
||||||
//{
|
//{
|
||||||
// &getBlockHeadersData{Origin: hashOrNumber{Number: bc.CurrentBlock().NumberU64() - 1}, Amount: limit + 10, Reverse: true},
|
// &protocol.GetBlockHeadersRequest{Origin: protocol.HashOrNumber{Number: bc.CurrentBlock().NumberU64() - 1}, Amount: limit + 10, Reverse: true},
|
||||||
// []common.Hash{},
|
// []common.Hash{},
|
||||||
//},
|
//},
|
||||||
// Check that requesting more than available is handled gracefully
|
// Check that requesting more than available is handled gracefully
|
||||||
{
|
{
|
||||||
&getBlockHeadersData{Origin: hashOrNumber{Number: bc.CurrentBlock().NumberU64() - 4}, Skip: 3, Amount: 3},
|
&protocol.GetBlockHeadersRequest{Origin: protocol.HashOrNumber{Number: bc.CurrentBlock().NumberU64() - 4}, Skip: 3, Amount: 3},
|
||||||
[]common.Hash{
|
[]common.Hash{
|
||||||
bc.GetBlockByNumber(bc.CurrentBlock().NumberU64() - 4).Hash(),
|
bc.GetBlockByNumber(bc.CurrentBlock().NumberU64() - 4).Hash(),
|
||||||
bc.GetBlockByNumber(bc.CurrentBlock().NumberU64()).Hash(),
|
bc.GetBlockByNumber(bc.CurrentBlock().NumberU64()).Hash(),
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
&getBlockHeadersData{Origin: hashOrNumber{Number: 4}, Skip: 3, Amount: 3, Reverse: true},
|
&protocol.GetBlockHeadersRequest{Origin: protocol.HashOrNumber{Number: 4}, Skip: 3, Amount: 3, Reverse: true},
|
||||||
[]common.Hash{
|
[]common.Hash{
|
||||||
bc.GetBlockByNumber(4).Hash(),
|
bc.GetBlockByNumber(4).Hash(),
|
||||||
bc.GetBlockByNumber(0).Hash(),
|
bc.GetBlockByNumber(0).Hash(),
|
||||||
|
|
@ -136,13 +137,13 @@ func testGetBlockHeaders(t *testing.T, protocol int) {
|
||||||
},
|
},
|
||||||
// Check that requesting more than available is handled gracefully, even if mid skip
|
// Check that requesting more than available is handled gracefully, even if mid skip
|
||||||
{
|
{
|
||||||
&getBlockHeadersData{Origin: hashOrNumber{Number: bc.CurrentBlock().NumberU64() - 4}, Skip: 2, Amount: 3},
|
&protocol.GetBlockHeadersRequest{Origin: protocol.HashOrNumber{Number: bc.CurrentBlock().NumberU64() - 4}, Skip: 2, Amount: 3},
|
||||||
[]common.Hash{
|
[]common.Hash{
|
||||||
bc.GetBlockByNumber(bc.CurrentBlock().NumberU64() - 4).Hash(),
|
bc.GetBlockByNumber(bc.CurrentBlock().NumberU64() - 4).Hash(),
|
||||||
bc.GetBlockByNumber(bc.CurrentBlock().NumberU64() - 1).Hash(),
|
bc.GetBlockByNumber(bc.CurrentBlock().NumberU64() - 1).Hash(),
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
&getBlockHeadersData{Origin: hashOrNumber{Number: 4}, Skip: 2, Amount: 3, Reverse: true},
|
&protocol.GetBlockHeadersRequest{Origin: protocol.HashOrNumber{Number: 4}, Skip: 2, Amount: 3, Reverse: true},
|
||||||
[]common.Hash{
|
[]common.Hash{
|
||||||
bc.GetBlockByNumber(4).Hash(),
|
bc.GetBlockByNumber(4).Hash(),
|
||||||
bc.GetBlockByNumber(1).Hash(),
|
bc.GetBlockByNumber(1).Hash(),
|
||||||
|
|
@ -150,10 +151,10 @@ func testGetBlockHeaders(t *testing.T, protocol int) {
|
||||||
},
|
},
|
||||||
// Check that non existing headers aren't returned
|
// Check that non existing headers aren't returned
|
||||||
{
|
{
|
||||||
&getBlockHeadersData{Origin: hashOrNumber{Hash: unknown}, Amount: 1},
|
&protocol.GetBlockHeadersRequest{Origin: protocol.HashOrNumber{Hash: unknown}, Amount: 1},
|
||||||
[]common.Hash{},
|
[]common.Hash{},
|
||||||
}, {
|
}, {
|
||||||
&getBlockHeadersData{Origin: hashOrNumber{Number: bc.CurrentBlock().NumberU64() + 1}, Amount: 1},
|
&protocol.GetBlockHeadersRequest{Origin: protocol.HashOrNumber{Number: bc.CurrentBlock().NumberU64() + 1}, Amount: 1},
|
||||||
[]common.Hash{},
|
[]common.Hash{},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
@ -168,9 +169,9 @@ func testGetBlockHeaders(t *testing.T, protocol int) {
|
||||||
// Send the hash request and verify the response
|
// Send the hash request and verify the response
|
||||||
reqID++
|
reqID++
|
||||||
|
|
||||||
cost := server.peer.peer.GetRequestCost(GetBlockHeadersMsg, int(tt.query.Amount))
|
cost := server.peer.peer.GetRequestCost(protocol.GetBlockHeadersMsg, int(tt.query.Amount))
|
||||||
sendRequest(server.peer.app, GetBlockHeadersMsg, reqID, cost, tt.query)
|
sendRequest(server.peer.app, protocol.GetBlockHeadersMsg, reqID, cost, tt.query)
|
||||||
if err := expectResponse(server.peer.app, BlockHeadersMsg, reqID, testBufLimit, headers); err != nil {
|
if err := expectResponse(server.peer.app, protocol.BlockHeadersMsg, reqID, testBufLimit, headers); err != nil {
|
||||||
t.Errorf("test %d: headers mismatch: %v", i, err)
|
t.Errorf("test %d: headers mismatch: %v", i, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -180,14 +181,14 @@ func testGetBlockHeaders(t *testing.T, protocol int) {
|
||||||
func TestGetBlockBodiesLes2(t *testing.T) { testGetBlockBodies(t, 2) }
|
func TestGetBlockBodiesLes2(t *testing.T) { testGetBlockBodies(t, 2) }
|
||||||
func TestGetBlockBodiesLes3(t *testing.T) { testGetBlockBodies(t, 3) }
|
func TestGetBlockBodiesLes3(t *testing.T) { testGetBlockBodies(t, 3) }
|
||||||
|
|
||||||
func testGetBlockBodies(t *testing.T, protocol int) {
|
func testGetBlockBodies(t *testing.T, p int) {
|
||||||
server, tearDown := newServerEnv(t, downloader.MaxBlockFetch+15, protocol, nil, false, true, 0)
|
server, tearDown := newServerEnv(t, downloader.MaxBlockFetch+15, p, nil, false, true, 0)
|
||||||
defer tearDown()
|
defer tearDown()
|
||||||
|
|
||||||
bc := server.handler.blockchain
|
bc := server.handler.blockchain
|
||||||
|
|
||||||
// Create a batch of tests for various scenarios
|
// Create a batch of tests for various scenarios
|
||||||
limit := MaxBodyFetch
|
limit := protocol.MaxBodyFetch
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
random int // Number of blocks to fetch randomly from the chain
|
random int // Number of blocks to fetch randomly from the chain
|
||||||
explicit []common.Hash // Explicitly requested blocks
|
explicit []common.Hash // Explicitly requested blocks
|
||||||
|
|
@ -246,9 +247,9 @@ func testGetBlockBodies(t *testing.T, protocol int) {
|
||||||
reqID++
|
reqID++
|
||||||
|
|
||||||
// Send the hash request and verify the response
|
// Send the hash request and verify the response
|
||||||
cost := server.peer.peer.GetRequestCost(GetBlockBodiesMsg, len(hashes))
|
cost := server.peer.peer.GetRequestCost(protocol.GetBlockBodiesMsg, len(hashes))
|
||||||
sendRequest(server.peer.app, GetBlockBodiesMsg, reqID, cost, hashes)
|
sendRequest(server.peer.app, protocol.GetBlockBodiesMsg, reqID, cost, hashes)
|
||||||
if err := expectResponse(server.peer.app, BlockBodiesMsg, reqID, testBufLimit, bodies); err != nil {
|
if err := expectResponse(server.peer.app, protocol.BlockBodiesMsg, reqID, testBufLimit, bodies); err != nil {
|
||||||
t.Errorf("test %d: bodies mismatch: %v", i, err)
|
t.Errorf("test %d: bodies mismatch: %v", i, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -258,19 +259,19 @@ func testGetBlockBodies(t *testing.T, protocol int) {
|
||||||
func TestGetCodeLes2(t *testing.T) { testGetCode(t, 2) }
|
func TestGetCodeLes2(t *testing.T) { testGetCode(t, 2) }
|
||||||
func TestGetCodeLes3(t *testing.T) { testGetCode(t, 3) }
|
func TestGetCodeLes3(t *testing.T) { testGetCode(t, 3) }
|
||||||
|
|
||||||
func testGetCode(t *testing.T, protocol int) {
|
func testGetCode(t *testing.T, p int) {
|
||||||
// Assemble the test environment
|
// Assemble the test environment
|
||||||
server, tearDown := newServerEnv(t, 4, protocol, nil, false, true, 0)
|
server, tearDown := newServerEnv(t, 4, p, nil, false, true, 0)
|
||||||
defer tearDown()
|
defer tearDown()
|
||||||
bc := server.handler.blockchain
|
bc := server.handler.blockchain
|
||||||
|
|
||||||
var codereqs []*CodeReq
|
var codereqs []protocol.CodeRequest
|
||||||
var codes [][]byte
|
var codes [][]byte
|
||||||
for i := uint64(0); i <= bc.CurrentBlock().NumberU64(); i++ {
|
for i := uint64(0); i <= bc.CurrentBlock().NumberU64(); i++ {
|
||||||
header := bc.GetHeaderByNumber(i)
|
header := bc.GetHeaderByNumber(i)
|
||||||
req := &CodeReq{
|
req := protocol.CodeRequest{
|
||||||
BHash: header.Hash(),
|
BlockHash: header.Hash(),
|
||||||
AccKey: crypto.Keccak256(testContractAddr[:]),
|
Account: crypto.Keccak256(testContractAddr[:]),
|
||||||
}
|
}
|
||||||
codereqs = append(codereqs, req)
|
codereqs = append(codereqs, req)
|
||||||
if i >= testContractDeployed {
|
if i >= testContractDeployed {
|
||||||
|
|
@ -278,9 +279,9 @@ func testGetCode(t *testing.T, protocol int) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cost := server.peer.peer.GetRequestCost(GetCodeMsg, len(codereqs))
|
cost := server.peer.peer.GetRequestCost(protocol.GetCodeMsg, len(codereqs))
|
||||||
sendRequest(server.peer.app, GetCodeMsg, 42, cost, codereqs)
|
sendRequest(server.peer.app, protocol.GetCodeMsg, 42, cost, codereqs)
|
||||||
if err := expectResponse(server.peer.app, CodeMsg, 42, testBufLimit, codes); err != nil {
|
if err := expectResponse(server.peer.app, protocol.CodeMsg, 42, testBufLimit, codes); err != nil {
|
||||||
t.Errorf("codes mismatch: %v", err)
|
t.Errorf("codes mismatch: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -289,19 +290,19 @@ func testGetCode(t *testing.T, protocol int) {
|
||||||
func TestGetStaleCodeLes2(t *testing.T) { testGetStaleCode(t, 2) }
|
func TestGetStaleCodeLes2(t *testing.T) { testGetStaleCode(t, 2) }
|
||||||
func TestGetStaleCodeLes3(t *testing.T) { testGetStaleCode(t, 3) }
|
func TestGetStaleCodeLes3(t *testing.T) { testGetStaleCode(t, 3) }
|
||||||
|
|
||||||
func testGetStaleCode(t *testing.T, protocol int) {
|
func testGetStaleCode(t *testing.T, p int) {
|
||||||
server, tearDown := newServerEnv(t, core.TriesInMemory+4, protocol, nil, false, true, 0)
|
server, tearDown := newServerEnv(t, core.TriesInMemory+4, p, nil, false, true, 0)
|
||||||
defer tearDown()
|
defer tearDown()
|
||||||
bc := server.handler.blockchain
|
bc := server.handler.blockchain
|
||||||
|
|
||||||
check := func(number uint64, expected [][]byte) {
|
check := func(number uint64, expected [][]byte) {
|
||||||
req := &CodeReq{
|
req := protocol.CodeRequest{
|
||||||
BHash: bc.GetHeaderByNumber(number).Hash(),
|
BlockHash: bc.GetHeaderByNumber(number).Hash(),
|
||||||
AccKey: crypto.Keccak256(testContractAddr[:]),
|
Account: crypto.Keccak256(testContractAddr[:]),
|
||||||
}
|
}
|
||||||
cost := server.peer.peer.GetRequestCost(GetCodeMsg, 1)
|
cost := server.peer.peer.GetRequestCost(protocol.GetCodeMsg, 1)
|
||||||
sendRequest(server.peer.app, GetCodeMsg, 42, cost, []*CodeReq{req})
|
sendRequest(server.peer.app, protocol.GetCodeMsg, 42, cost, []protocol.CodeRequest{req})
|
||||||
if err := expectResponse(server.peer.app, CodeMsg, 42, testBufLimit, expected); err != nil {
|
if err := expectResponse(server.peer.app, protocol.CodeMsg, 42, testBufLimit, expected); err != nil {
|
||||||
t.Errorf("codes mismatch: %v", err)
|
t.Errorf("codes mismatch: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -314,9 +315,9 @@ func testGetStaleCode(t *testing.T, protocol int) {
|
||||||
func TestGetReceiptLes2(t *testing.T) { testGetReceipt(t, 2) }
|
func TestGetReceiptLes2(t *testing.T) { testGetReceipt(t, 2) }
|
||||||
func TestGetReceiptLes3(t *testing.T) { testGetReceipt(t, 3) }
|
func TestGetReceiptLes3(t *testing.T) { testGetReceipt(t, 3) }
|
||||||
|
|
||||||
func testGetReceipt(t *testing.T, protocol int) {
|
func testGetReceipt(t *testing.T, p int) {
|
||||||
// Assemble the test environment
|
// Assemble the test environment
|
||||||
server, tearDown := newServerEnv(t, 4, protocol, nil, false, true, 0)
|
server, tearDown := newServerEnv(t, 4, p, nil, false, true, 0)
|
||||||
defer tearDown()
|
defer tearDown()
|
||||||
|
|
||||||
bc := server.handler.blockchain
|
bc := server.handler.blockchain
|
||||||
|
|
@ -331,9 +332,9 @@ func testGetReceipt(t *testing.T, protocol int) {
|
||||||
receipts = append(receipts, rawdb.ReadRawReceipts(server.db, block.Hash(), block.NumberU64()))
|
receipts = append(receipts, rawdb.ReadRawReceipts(server.db, block.Hash(), block.NumberU64()))
|
||||||
}
|
}
|
||||||
// Send the hash request and verify the response
|
// Send the hash request and verify the response
|
||||||
cost := server.peer.peer.GetRequestCost(GetReceiptsMsg, len(hashes))
|
cost := server.peer.peer.GetRequestCost(protocol.GetReceiptsMsg, len(hashes))
|
||||||
sendRequest(server.peer.app, GetReceiptsMsg, 42, cost, hashes)
|
sendRequest(server.peer.app, protocol.GetReceiptsMsg, 42, cost, hashes)
|
||||||
if err := expectResponse(server.peer.app, ReceiptsMsg, 42, testBufLimit, receipts); err != nil {
|
if err := expectResponse(server.peer.app, protocol.ReceiptsMsg, 42, testBufLimit, receipts); err != nil {
|
||||||
t.Errorf("receipts mismatch: %v", err)
|
t.Errorf("receipts mismatch: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -342,14 +343,14 @@ func testGetReceipt(t *testing.T, protocol int) {
|
||||||
func TestGetProofsLes2(t *testing.T) { testGetProofs(t, 2) }
|
func TestGetProofsLes2(t *testing.T) { testGetProofs(t, 2) }
|
||||||
func TestGetProofsLes3(t *testing.T) { testGetProofs(t, 3) }
|
func TestGetProofsLes3(t *testing.T) { testGetProofs(t, 3) }
|
||||||
|
|
||||||
func testGetProofs(t *testing.T, protocol int) {
|
func testGetProofs(t *testing.T, p int) {
|
||||||
// Assemble the test environment
|
// Assemble the test environment
|
||||||
server, tearDown := newServerEnv(t, 4, protocol, nil, false, true, 0)
|
server, tearDown := newServerEnv(t, 4, p, nil, false, true, 0)
|
||||||
defer tearDown()
|
defer tearDown()
|
||||||
|
|
||||||
bc := server.handler.blockchain
|
bc := server.handler.blockchain
|
||||||
|
|
||||||
var proofreqs []ProofReq
|
var proofreqs []protocol.TrieProofRequest
|
||||||
proofsV2 := light.NewNodeSet()
|
proofsV2 := light.NewNodeSet()
|
||||||
|
|
||||||
accounts := []common.Address{bankAddr, userAddr1, userAddr2, signerAddr, {}}
|
accounts := []common.Address{bankAddr, userAddr1, userAddr2, signerAddr, {}}
|
||||||
|
|
@ -358,18 +359,18 @@ func testGetProofs(t *testing.T, protocol int) {
|
||||||
trie, _ := trie.New(header.Root, trie.NewDatabase(server.db))
|
trie, _ := trie.New(header.Root, trie.NewDatabase(server.db))
|
||||||
|
|
||||||
for _, acc := range accounts {
|
for _, acc := range accounts {
|
||||||
req := ProofReq{
|
req := protocol.TrieProofRequest{
|
||||||
BHash: header.Hash(),
|
BlockHash: header.Hash(),
|
||||||
Key: crypto.Keccak256(acc[:]),
|
Key: crypto.Keccak256(acc[:]),
|
||||||
}
|
}
|
||||||
proofreqs = append(proofreqs, req)
|
proofreqs = append(proofreqs, req)
|
||||||
trie.Prove(crypto.Keccak256(acc[:]), 0, proofsV2)
|
trie.Prove(crypto.Keccak256(acc[:]), 0, proofsV2)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Send the proof request and verify the response
|
// Send the proof request and verify the response
|
||||||
cost := server.peer.peer.GetRequestCost(GetProofsV2Msg, len(proofreqs))
|
cost := server.peer.peer.GetRequestCost(protocol.GetProofsV2Msg, len(proofreqs))
|
||||||
sendRequest(server.peer.app, GetProofsV2Msg, 42, cost, proofreqs)
|
sendRequest(server.peer.app, protocol.GetProofsV2Msg, 42, cost, proofreqs)
|
||||||
if err := expectResponse(server.peer.app, ProofsV2Msg, 42, testBufLimit, proofsV2.NodeList()); err != nil {
|
if err := expectResponse(server.peer.app, protocol.ProofsV2Msg, 42, testBufLimit, proofsV2.NodeList()); err != nil {
|
||||||
t.Errorf("proofs mismatch: %v", err)
|
t.Errorf("proofs mismatch: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -378,8 +379,8 @@ func testGetProofs(t *testing.T, protocol int) {
|
||||||
func TestGetStaleProofLes2(t *testing.T) { testGetStaleProof(t, 2) }
|
func TestGetStaleProofLes2(t *testing.T) { testGetStaleProof(t, 2) }
|
||||||
func TestGetStaleProofLes3(t *testing.T) { testGetStaleProof(t, 3) }
|
func TestGetStaleProofLes3(t *testing.T) { testGetStaleProof(t, 3) }
|
||||||
|
|
||||||
func testGetStaleProof(t *testing.T, protocol int) {
|
func testGetStaleProof(t *testing.T, p int) {
|
||||||
server, tearDown := newServerEnv(t, core.TriesInMemory+4, protocol, nil, false, true, 0)
|
server, tearDown := newServerEnv(t, core.TriesInMemory+4, p, nil, false, true, 0)
|
||||||
defer tearDown()
|
defer tearDown()
|
||||||
bc := server.handler.blockchain
|
bc := server.handler.blockchain
|
||||||
|
|
||||||
|
|
@ -388,12 +389,12 @@ func testGetStaleProof(t *testing.T, protocol int) {
|
||||||
header = bc.GetHeaderByNumber(number)
|
header = bc.GetHeaderByNumber(number)
|
||||||
account = crypto.Keccak256(userAddr1.Bytes())
|
account = crypto.Keccak256(userAddr1.Bytes())
|
||||||
)
|
)
|
||||||
req := &ProofReq{
|
req := &protocol.TrieProofRequest{
|
||||||
BHash: header.Hash(),
|
BlockHash: header.Hash(),
|
||||||
Key: account,
|
Key: account,
|
||||||
}
|
}
|
||||||
cost := server.peer.peer.GetRequestCost(GetProofsV2Msg, 1)
|
cost := server.peer.peer.GetRequestCost(protocol.GetProofsV2Msg, 1)
|
||||||
sendRequest(server.peer.app, GetProofsV2Msg, 42, cost, []*ProofReq{req})
|
sendRequest(server.peer.app, protocol.GetProofsV2Msg, 42, cost, []*protocol.TrieProofRequest{req})
|
||||||
|
|
||||||
var expected []rlp.RawValue
|
var expected []rlp.RawValue
|
||||||
if wantOK {
|
if wantOK {
|
||||||
|
|
@ -402,7 +403,7 @@ func testGetStaleProof(t *testing.T, protocol int) {
|
||||||
t.Prove(account, 0, proofsV2)
|
t.Prove(account, 0, proofsV2)
|
||||||
expected = proofsV2.NodeList()
|
expected = proofsV2.NodeList()
|
||||||
}
|
}
|
||||||
if err := expectResponse(server.peer.app, ProofsV2Msg, 42, testBufLimit, expected); err != nil {
|
if err := expectResponse(server.peer.app, protocol.ProofsV2Msg, 42, testBufLimit, expected); err != nil {
|
||||||
t.Errorf("codes mismatch: %v", err)
|
t.Errorf("codes mismatch: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -415,7 +416,7 @@ func testGetStaleProof(t *testing.T, protocol int) {
|
||||||
func TestGetCHTProofsLes2(t *testing.T) { testGetCHTProofs(t, 2) }
|
func TestGetCHTProofsLes2(t *testing.T) { testGetCHTProofs(t, 2) }
|
||||||
func TestGetCHTProofsLes3(t *testing.T) { testGetCHTProofs(t, 3) }
|
func TestGetCHTProofsLes3(t *testing.T) { testGetCHTProofs(t, 3) }
|
||||||
|
|
||||||
func testGetCHTProofs(t *testing.T, protocol int) {
|
func testGetCHTProofs(t *testing.T, p int) {
|
||||||
config := light.TestServerIndexerConfig
|
config := light.TestServerIndexerConfig
|
||||||
|
|
||||||
waitIndexers := func(cIndexer, bIndexer, btIndexer *core.ChainIndexer) {
|
waitIndexers := func(cIndexer, bIndexer, btIndexer *core.ChainIndexer) {
|
||||||
|
|
@ -427,7 +428,7 @@ func testGetCHTProofs(t *testing.T, protocol int) {
|
||||||
time.Sleep(10 * time.Millisecond)
|
time.Sleep(10 * time.Millisecond)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
server, tearDown := newServerEnv(t, int(config.ChtSize+config.ChtConfirms), protocol, waitIndexers, false, true, 0)
|
server, tearDown := newServerEnv(t, int(config.ChtSize+config.ChtConfirms), p, waitIndexers, false, true, 0)
|
||||||
defer tearDown()
|
defer tearDown()
|
||||||
|
|
||||||
bc := server.handler.blockchain
|
bc := server.handler.blockchain
|
||||||
|
|
@ -439,23 +440,23 @@ func testGetCHTProofs(t *testing.T, protocol int) {
|
||||||
key := make([]byte, 8)
|
key := make([]byte, 8)
|
||||||
binary.BigEndian.PutUint64(key, config.ChtSize-1)
|
binary.BigEndian.PutUint64(key, config.ChtSize-1)
|
||||||
|
|
||||||
proofsV2 := HelperTrieResps{
|
proofsV2 := protocol.HelperTrieResponse{
|
||||||
AuxData: [][]byte{rlp},
|
AuxData: [][]byte{rlp},
|
||||||
}
|
}
|
||||||
root := light.GetChtRoot(server.db, 0, bc.GetHeaderByNumber(config.ChtSize-1).Hash())
|
root := light.GetChtRoot(server.db, 0, bc.GetHeaderByNumber(config.ChtSize-1).Hash())
|
||||||
trie, _ := trie.New(root, trie.NewDatabase(rawdb.NewTable(server.db, light.ChtTablePrefix)))
|
trie, _ := trie.New(root, trie.NewDatabase(rawdb.NewTable(server.db, light.ChtTablePrefix)))
|
||||||
trie.Prove(key, 0, &proofsV2.Proofs)
|
trie.Prove(key, 0, &proofsV2.Proofs)
|
||||||
// Assemble the requests for the different protocols
|
// Assemble the requests for the different protocols
|
||||||
requestsV2 := []HelperTrieReq{{
|
requestsV2 := []protocol.HelperTrieRequest{{
|
||||||
Type: htCanonical,
|
Type: protocol.HelperTrieCHT,
|
||||||
TrieIdx: 0,
|
TrieIndex: 0,
|
||||||
Key: key,
|
Key: key,
|
||||||
AuxReq: auxHeader,
|
AuxType: protocol.AuxHeader,
|
||||||
}}
|
}}
|
||||||
// Send the proof request and verify the response
|
// Send the proof request and verify the response
|
||||||
cost := server.peer.peer.GetRequestCost(GetHelperTrieProofsMsg, len(requestsV2))
|
cost := server.peer.peer.GetRequestCost(protocol.GetHelperTrieProofsMsg, len(requestsV2))
|
||||||
sendRequest(server.peer.app, GetHelperTrieProofsMsg, 42, cost, requestsV2)
|
sendRequest(server.peer.app, protocol.GetHelperTrieProofsMsg, 42, cost, requestsV2)
|
||||||
if err := expectResponse(server.peer.app, HelperTrieProofsMsg, 42, testBufLimit, proofsV2); err != nil {
|
if err := expectResponse(server.peer.app, protocol.HelperTrieProofsMsg, 42, testBufLimit, proofsV2); err != nil {
|
||||||
t.Errorf("proofs mismatch: %v", err)
|
t.Errorf("proofs mismatch: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -464,7 +465,7 @@ func TestGetBloombitsProofsLes2(t *testing.T) { testGetBloombitsProofs(t, 2) }
|
||||||
func TestGetBloombitsProofsLes3(t *testing.T) { testGetBloombitsProofs(t, 3) }
|
func TestGetBloombitsProofsLes3(t *testing.T) { testGetBloombitsProofs(t, 3) }
|
||||||
|
|
||||||
// Tests that bloombits proofs can be correctly retrieved.
|
// Tests that bloombits proofs can be correctly retrieved.
|
||||||
func testGetBloombitsProofs(t *testing.T, protocol int) {
|
func testGetBloombitsProofs(t *testing.T, p int) {
|
||||||
config := light.TestServerIndexerConfig
|
config := light.TestServerIndexerConfig
|
||||||
|
|
||||||
waitIndexers := func(cIndexer, bIndexer, btIndexer *core.ChainIndexer) {
|
waitIndexers := func(cIndexer, bIndexer, btIndexer *core.ChainIndexer) {
|
||||||
|
|
@ -476,7 +477,7 @@ func testGetBloombitsProofs(t *testing.T, protocol int) {
|
||||||
time.Sleep(10 * time.Millisecond)
|
time.Sleep(10 * time.Millisecond)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
server, tearDown := newServerEnv(t, int(config.BloomTrieSize+config.BloomTrieConfirms), protocol, waitIndexers, false, true, 0)
|
server, tearDown := newServerEnv(t, int(config.BloomTrieSize+config.BloomTrieConfirms), p, waitIndexers, false, true, 0)
|
||||||
defer tearDown()
|
defer tearDown()
|
||||||
|
|
||||||
bc := server.handler.blockchain
|
bc := server.handler.blockchain
|
||||||
|
|
@ -490,21 +491,21 @@ func testGetBloombitsProofs(t *testing.T, protocol int) {
|
||||||
// Only the first bloom section has data.
|
// Only the first bloom section has data.
|
||||||
binary.BigEndian.PutUint64(key[2:], 0)
|
binary.BigEndian.PutUint64(key[2:], 0)
|
||||||
|
|
||||||
requests := []HelperTrieReq{{
|
requests := []protocol.HelperTrieRequest{{
|
||||||
Type: htBloomBits,
|
Type: protocol.HelperTrieBloomTrie,
|
||||||
TrieIdx: 0,
|
TrieIndex: 0,
|
||||||
Key: key,
|
Key: key,
|
||||||
}}
|
}}
|
||||||
var proofs HelperTrieResps
|
var proofs protocol.HelperTrieResponse
|
||||||
|
|
||||||
root := light.GetBloomTrieRoot(server.db, 0, bc.GetHeaderByNumber(config.BloomTrieSize-1).Hash())
|
root := light.GetBloomTrieRoot(server.db, 0, bc.GetHeaderByNumber(config.BloomTrieSize-1).Hash())
|
||||||
trie, _ := trie.New(root, trie.NewDatabase(rawdb.NewTable(server.db, light.BloomTrieTablePrefix)))
|
trie, _ := trie.New(root, trie.NewDatabase(rawdb.NewTable(server.db, light.BloomTrieTablePrefix)))
|
||||||
trie.Prove(key, 0, &proofs.Proofs)
|
trie.Prove(key, 0, &proofs.Proofs)
|
||||||
|
|
||||||
// Send the proof request and verify the response
|
// Send the proof request and verify the response
|
||||||
cost := server.peer.peer.GetRequestCost(GetHelperTrieProofsMsg, len(requests))
|
cost := server.peer.peer.GetRequestCost(protocol.GetHelperTrieProofsMsg, len(requests))
|
||||||
sendRequest(server.peer.app, GetHelperTrieProofsMsg, 42, cost, requests)
|
sendRequest(server.peer.app, protocol.GetHelperTrieProofsMsg, 42, cost, requests)
|
||||||
if err := expectResponse(server.peer.app, HelperTrieProofsMsg, 42, testBufLimit, proofs); err != nil {
|
if err := expectResponse(server.peer.app, protocol.HelperTrieProofsMsg, 42, testBufLimit, proofs); err != nil {
|
||||||
t.Errorf("bit %d: proofs mismatch: %v", bit, err)
|
t.Errorf("bit %d: proofs mismatch: %v", bit, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -513,8 +514,8 @@ func testGetBloombitsProofs(t *testing.T, protocol int) {
|
||||||
func TestTransactionStatusLes2(t *testing.T) { testTransactionStatus(t, 2) }
|
func TestTransactionStatusLes2(t *testing.T) { testTransactionStatus(t, 2) }
|
||||||
func TestTransactionStatusLes3(t *testing.T) { testTransactionStatus(t, 3) }
|
func TestTransactionStatusLes3(t *testing.T) { testTransactionStatus(t, 3) }
|
||||||
|
|
||||||
func testTransactionStatus(t *testing.T, protocol int) {
|
func testTransactionStatus(t *testing.T, p int) {
|
||||||
server, tearDown := newServerEnv(t, 0, protocol, nil, false, true, 0)
|
server, tearDown := newServerEnv(t, 0, p, nil, false, true, 0)
|
||||||
defer tearDown()
|
defer tearDown()
|
||||||
server.handler.addTxsSync = true
|
server.handler.addTxsSync = true
|
||||||
|
|
||||||
|
|
@ -525,13 +526,13 @@ func testTransactionStatus(t *testing.T, protocol int) {
|
||||||
test := func(tx *types.Transaction, send bool, expStatus light.TxStatus) {
|
test := func(tx *types.Transaction, send bool, expStatus light.TxStatus) {
|
||||||
reqID++
|
reqID++
|
||||||
if send {
|
if send {
|
||||||
cost := server.peer.peer.GetRequestCost(SendTxV2Msg, 1)
|
cost := server.peer.peer.GetRequestCost(protocol.SendTxV2Msg, 1)
|
||||||
sendRequest(server.peer.app, SendTxV2Msg, reqID, cost, types.Transactions{tx})
|
sendRequest(server.peer.app, protocol.SendTxV2Msg, reqID, cost, types.Transactions{tx})
|
||||||
} else {
|
} else {
|
||||||
cost := server.peer.peer.GetRequestCost(GetTxStatusMsg, 1)
|
cost := server.peer.peer.GetRequestCost(protocol.GetTxStatusMsg, 1)
|
||||||
sendRequest(server.peer.app, GetTxStatusMsg, reqID, cost, []common.Hash{tx.Hash()})
|
sendRequest(server.peer.app, protocol.GetTxStatusMsg, reqID, cost, []common.Hash{tx.Hash()})
|
||||||
}
|
}
|
||||||
if err := expectResponse(server.peer.app, TxStatusMsg, reqID, testBufLimit, []light.TxStatus{expStatus}); err != nil {
|
if err := expectResponse(server.peer.app, protocol.TxStatusMsg, reqID, testBufLimit, []light.TxStatus{expStatus}); err != nil {
|
||||||
t.Errorf("transaction status mismatch")
|
t.Errorf("transaction status mismatch")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -620,14 +621,14 @@ func TestStopResumeLes3(t *testing.T) {
|
||||||
header := server.handler.blockchain.CurrentHeader()
|
header := server.handler.blockchain.CurrentHeader()
|
||||||
req := func() {
|
req := func() {
|
||||||
reqID++
|
reqID++
|
||||||
sendRequest(server.peer.app, GetBlockHeadersMsg, reqID, testCost, &getBlockHeadersData{Origin: hashOrNumber{Hash: header.Hash()}, Amount: 1})
|
sendRequest(server.peer.app, protocol.GetBlockHeadersMsg, reqID, testCost, &protocol.GetBlockHeadersRequest{Origin: protocol.HashOrNumber{Hash: header.Hash()}, Amount: 1})
|
||||||
}
|
}
|
||||||
for i := 1; i <= 5; i++ {
|
for i := 1; i <= 5; i++ {
|
||||||
// send requests while we still have enough buffer and expect a response
|
// send requests while we still have enough buffer and expect a response
|
||||||
for expBuf >= testCost {
|
for expBuf >= testCost {
|
||||||
req()
|
req()
|
||||||
expBuf -= testCost
|
expBuf -= testCost
|
||||||
if err := expectResponse(server.peer.app, BlockHeadersMsg, reqID, expBuf, []*types.Header{header}); err != nil {
|
if err := expectResponse(server.peer.app, protocol.BlockHeadersMsg, reqID, expBuf, []*types.Header{header}); err != nil {
|
||||||
t.Errorf("expected response and failed: %v", err)
|
t.Errorf("expected response and failed: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -637,7 +638,7 @@ func TestStopResumeLes3(t *testing.T) {
|
||||||
req()
|
req()
|
||||||
c--
|
c--
|
||||||
}
|
}
|
||||||
if err := p2p.ExpectMsg(server.peer.app, StopMsg, nil); err != nil {
|
if err := p2p.ExpectMsg(server.peer.app, protocol.StopMsg, nil); err != nil {
|
||||||
t.Errorf("expected StopMsg and failed: %v", err)
|
t.Errorf("expected StopMsg and failed: %v", err)
|
||||||
}
|
}
|
||||||
// wait until the buffer is recharged by half of the limit
|
// wait until the buffer is recharged by half of the limit
|
||||||
|
|
@ -646,7 +647,7 @@ func TestStopResumeLes3(t *testing.T) {
|
||||||
|
|
||||||
// expect a ResumeMsg with the partially recharged buffer value
|
// expect a ResumeMsg with the partially recharged buffer value
|
||||||
expBuf += testBufRecharge * wait
|
expBuf += testBufRecharge * wait
|
||||||
if err := p2p.ExpectMsg(server.peer.app, ResumeMsg, expBuf); err != nil {
|
if err := p2p.ExpectMsg(server.peer.app, protocol.ResumeMsg, expBuf); err != nil {
|
||||||
t.Errorf("expected ResumeMsg and failed: %v", err)
|
t.Errorf("expected ResumeMsg and failed: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,7 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
"github.com/ethereum/go-ethereum/ethdb"
|
"github.com/ethereum/go-ethereum/ethdb"
|
||||||
|
"github.com/ethereum/go-ethereum/les/protocol"
|
||||||
"github.com/ethereum/go-ethereum/light"
|
"github.com/ethereum/go-ethereum/light"
|
||||||
"github.com/ethereum/go-ethereum/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
"github.com/ethereum/go-ethereum/rlp"
|
"github.com/ethereum/go-ethereum/rlp"
|
||||||
|
|
@ -79,7 +80,7 @@ type BlockRequest light.BlockRequest
|
||||||
// GetCost returns the cost of the given ODR request according to the serving
|
// GetCost returns the cost of the given ODR request according to the serving
|
||||||
// peer's cost table (implementation of LesOdrRequest)
|
// peer's cost table (implementation of LesOdrRequest)
|
||||||
func (r *BlockRequest) GetCost(peer *peer) uint64 {
|
func (r *BlockRequest) GetCost(peer *peer) uint64 {
|
||||||
return peer.GetRequestCost(GetBlockBodiesMsg, 1)
|
return peer.GetRequestCost(protocol.GetBlockBodiesMsg, 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
// CanSend tells if a certain peer is suitable for serving the given request
|
// CanSend tells if a certain peer is suitable for serving the given request
|
||||||
|
|
@ -135,7 +136,7 @@ type ReceiptsRequest light.ReceiptsRequest
|
||||||
// GetCost returns the cost of the given ODR request according to the serving
|
// GetCost returns the cost of the given ODR request according to the serving
|
||||||
// peer's cost table (implementation of LesOdrRequest)
|
// peer's cost table (implementation of LesOdrRequest)
|
||||||
func (r *ReceiptsRequest) GetCost(peer *peer) uint64 {
|
func (r *ReceiptsRequest) GetCost(peer *peer) uint64 {
|
||||||
return peer.GetRequestCost(GetReceiptsMsg, 1)
|
return peer.GetRequestCost(protocol.GetReceiptsMsg, 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
// CanSend tells if a certain peer is suitable for serving the given request
|
// CanSend tells if a certain peer is suitable for serving the given request
|
||||||
|
|
@ -180,19 +181,13 @@ func (r *ReceiptsRequest) Validate(db ethdb.Database, msg *Msg) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type ProofReq struct {
|
|
||||||
BHash common.Hash
|
|
||||||
AccKey, Key []byte
|
|
||||||
FromLevel uint
|
|
||||||
}
|
|
||||||
|
|
||||||
// ODR request type for state/storage trie entries, see LesOdrRequest interface
|
// ODR request type for state/storage trie entries, see LesOdrRequest interface
|
||||||
type TrieRequest light.TrieRequest
|
type TrieRequest light.TrieRequest
|
||||||
|
|
||||||
// GetCost returns the cost of the given ODR request according to the serving
|
// GetCost returns the cost of the given ODR request according to the serving
|
||||||
// peer's cost table (implementation of LesOdrRequest)
|
// peer's cost table (implementation of LesOdrRequest)
|
||||||
func (r *TrieRequest) GetCost(peer *peer) uint64 {
|
func (r *TrieRequest) GetCost(peer *peer) uint64 {
|
||||||
return peer.GetRequestCost(GetProofsV2Msg, 1)
|
return peer.GetRequestCost(protocol.GetProofsV2Msg, 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
// CanSend tells if a certain peer is suitable for serving the given request
|
// CanSend tells if a certain peer is suitable for serving the given request
|
||||||
|
|
@ -203,12 +198,12 @@ func (r *TrieRequest) CanSend(peer *peer) bool {
|
||||||
// Request sends an ODR request to the LES network (implementation of LesOdrRequest)
|
// Request sends an ODR request to the LES network (implementation of LesOdrRequest)
|
||||||
func (r *TrieRequest) Request(reqID uint64, peer *peer) error {
|
func (r *TrieRequest) Request(reqID uint64, peer *peer) error {
|
||||||
peer.Log().Debug("Requesting trie proof", "root", r.Id.Root, "key", r.Key)
|
peer.Log().Debug("Requesting trie proof", "root", r.Id.Root, "key", r.Key)
|
||||||
req := ProofReq{
|
req := protocol.TrieProofRequest{
|
||||||
BHash: r.Id.BlockHash,
|
BlockHash: r.Id.BlockHash,
|
||||||
AccKey: r.Id.AccKey,
|
Account: r.Id.AccKey,
|
||||||
Key: r.Key,
|
Key: r.Key,
|
||||||
}
|
}
|
||||||
return peer.RequestProofs(reqID, r.GetCost(peer), []ProofReq{req})
|
return peer.RequestProofs(reqID, r.GetCost(peer), []protocol.TrieProofRequest{req})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Valid processes an ODR request reply message from the LES network
|
// Valid processes an ODR request reply message from the LES network
|
||||||
|
|
@ -235,18 +230,13 @@ func (r *TrieRequest) Validate(db ethdb.Database, msg *Msg) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type CodeReq struct {
|
|
||||||
BHash common.Hash
|
|
||||||
AccKey []byte
|
|
||||||
}
|
|
||||||
|
|
||||||
// ODR request type for node data (used for retrieving contract code), see LesOdrRequest interface
|
// ODR request type for node data (used for retrieving contract code), see LesOdrRequest interface
|
||||||
type CodeRequest light.CodeRequest
|
type CodeRequest light.CodeRequest
|
||||||
|
|
||||||
// GetCost returns the cost of the given ODR request according to the serving
|
// GetCost returns the cost of the given ODR request according to the serving
|
||||||
// peer's cost table (implementation of LesOdrRequest)
|
// peer's cost table (implementation of LesOdrRequest)
|
||||||
func (r *CodeRequest) GetCost(peer *peer) uint64 {
|
func (r *CodeRequest) GetCost(peer *peer) uint64 {
|
||||||
return peer.GetRequestCost(GetCodeMsg, 1)
|
return peer.GetRequestCost(protocol.GetCodeMsg, 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
// CanSend tells if a certain peer is suitable for serving the given request
|
// CanSend tells if a certain peer is suitable for serving the given request
|
||||||
|
|
@ -257,11 +247,11 @@ func (r *CodeRequest) CanSend(peer *peer) bool {
|
||||||
// Request sends an ODR request to the LES network (implementation of LesOdrRequest)
|
// Request sends an ODR request to the LES network (implementation of LesOdrRequest)
|
||||||
func (r *CodeRequest) Request(reqID uint64, peer *peer) error {
|
func (r *CodeRequest) Request(reqID uint64, peer *peer) error {
|
||||||
peer.Log().Debug("Requesting code data", "hash", r.Hash)
|
peer.Log().Debug("Requesting code data", "hash", r.Hash)
|
||||||
req := CodeReq{
|
req := protocol.CodeRequest{
|
||||||
BHash: r.Id.BlockHash,
|
BlockHash: r.Id.BlockHash,
|
||||||
AccKey: r.Id.AccKey,
|
Account: r.Id.AccKey,
|
||||||
}
|
}
|
||||||
return peer.RequestCode(reqID, r.GetCost(peer), []CodeReq{req})
|
return peer.RequestCode(reqID, r.GetCost(peer), []protocol.CodeRequest{req})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Valid processes an ODR request reply message from the LES network
|
// Valid processes an ODR request reply message from the LES network
|
||||||
|
|
@ -288,36 +278,13 @@ func (r *CodeRequest) Validate(db ethdb.Database, msg *Msg) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
|
||||||
// helper trie type constants
|
|
||||||
htCanonical = iota // Canonical hash trie
|
|
||||||
htBloomBits // BloomBits trie
|
|
||||||
|
|
||||||
// applicable for all helper trie requests
|
|
||||||
auxRoot = 1
|
|
||||||
// applicable for htCanonical
|
|
||||||
auxHeader = 2
|
|
||||||
)
|
|
||||||
|
|
||||||
type HelperTrieReq struct {
|
|
||||||
Type uint
|
|
||||||
TrieIdx uint64
|
|
||||||
Key []byte
|
|
||||||
FromLevel, AuxReq uint
|
|
||||||
}
|
|
||||||
|
|
||||||
type HelperTrieResps struct { // describes all responses, not just a single one
|
|
||||||
Proofs light.NodeList
|
|
||||||
AuxData [][]byte
|
|
||||||
}
|
|
||||||
|
|
||||||
// ODR request type for requesting headers by Canonical Hash Trie, see LesOdrRequest interface
|
// ODR request type for requesting headers by Canonical Hash Trie, see LesOdrRequest interface
|
||||||
type ChtRequest light.ChtRequest
|
type ChtRequest light.ChtRequest
|
||||||
|
|
||||||
// GetCost returns the cost of the given ODR request according to the serving
|
// GetCost returns the cost of the given ODR request according to the serving
|
||||||
// peer's cost table (implementation of LesOdrRequest)
|
// peer's cost table (implementation of LesOdrRequest)
|
||||||
func (r *ChtRequest) GetCost(peer *peer) uint64 {
|
func (r *ChtRequest) GetCost(peer *peer) uint64 {
|
||||||
return peer.GetRequestCost(GetHelperTrieProofsMsg, 1)
|
return peer.GetRequestCost(protocol.GetHelperTrieProofsMsg, 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
// CanSend tells if a certain peer is suitable for serving the given request
|
// CanSend tells if a certain peer is suitable for serving the given request
|
||||||
|
|
@ -337,13 +304,13 @@ func (r *ChtRequest) Request(reqID uint64, peer *peer) error {
|
||||||
peer.Log().Debug("Requesting CHT", "cht", r.ChtNum, "block", r.BlockNum)
|
peer.Log().Debug("Requesting CHT", "cht", r.ChtNum, "block", r.BlockNum)
|
||||||
var encNum [8]byte
|
var encNum [8]byte
|
||||||
binary.BigEndian.PutUint64(encNum[:], r.BlockNum)
|
binary.BigEndian.PutUint64(encNum[:], r.BlockNum)
|
||||||
req := HelperTrieReq{
|
req := protocol.HelperTrieRequest{
|
||||||
Type: htCanonical,
|
Type: protocol.HelperTrieCHT,
|
||||||
TrieIdx: r.ChtNum,
|
TrieIndex: r.ChtNum,
|
||||||
Key: encNum[:],
|
Key: encNum[:],
|
||||||
AuxReq: auxHeader,
|
AuxType: protocol.AuxHeader,
|
||||||
}
|
}
|
||||||
return peer.RequestHelperTrieProofs(reqID, r.GetCost(peer), []HelperTrieReq{req})
|
return peer.RequestHelperTrieProofs(reqID, r.GetCost(peer), []protocol.HelperTrieRequest{req})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Valid processes an ODR request reply message from the LES network
|
// Valid processes an ODR request reply message from the LES network
|
||||||
|
|
@ -355,7 +322,7 @@ func (r *ChtRequest) Validate(db ethdb.Database, msg *Msg) error {
|
||||||
if msg.MsgType != MsgHelperTrieProofs {
|
if msg.MsgType != MsgHelperTrieProofs {
|
||||||
return errInvalidMessageType
|
return errInvalidMessageType
|
||||||
}
|
}
|
||||||
resp := msg.Obj.(HelperTrieResps)
|
resp := msg.Obj.(protocol.HelperTrieResponse)
|
||||||
if len(resp.AuxData) != 1 {
|
if len(resp.AuxData) != 1 {
|
||||||
return errInvalidEntryCount
|
return errInvalidEntryCount
|
||||||
}
|
}
|
||||||
|
|
@ -404,17 +371,13 @@ func (r *ChtRequest) Validate(db ethdb.Database, msg *Msg) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type BloomReq struct {
|
|
||||||
BloomTrieNum, BitIdx, SectionIndex, FromLevel uint64
|
|
||||||
}
|
|
||||||
|
|
||||||
// ODR request type for requesting headers by Canonical Hash Trie, see LesOdrRequest interface
|
// ODR request type for requesting headers by Canonical Hash Trie, see LesOdrRequest interface
|
||||||
type BloomRequest light.BloomRequest
|
type BloomRequest light.BloomRequest
|
||||||
|
|
||||||
// GetCost returns the cost of the given ODR request according to the serving
|
// GetCost returns the cost of the given ODR request according to the serving
|
||||||
// peer's cost table (implementation of LesOdrRequest)
|
// peer's cost table (implementation of LesOdrRequest)
|
||||||
func (r *BloomRequest) GetCost(peer *peer) uint64 {
|
func (r *BloomRequest) GetCost(peer *peer) uint64 {
|
||||||
return peer.GetRequestCost(GetHelperTrieProofsMsg, len(r.SectionIndexList))
|
return peer.GetRequestCost(protocol.GetHelperTrieProofsMsg, len(r.SectionIndexList))
|
||||||
}
|
}
|
||||||
|
|
||||||
// CanSend tells if a certain peer is suitable for serving the given request
|
// CanSend tells if a certain peer is suitable for serving the given request
|
||||||
|
|
@ -422,7 +385,7 @@ func (r *BloomRequest) CanSend(peer *peer) bool {
|
||||||
peer.lock.RLock()
|
peer.lock.RLock()
|
||||||
defer peer.lock.RUnlock()
|
defer peer.lock.RUnlock()
|
||||||
|
|
||||||
if peer.version < lpv2 {
|
if peer.version < protocol.Lpv2 {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return peer.headInfo.Number >= r.Config.BloomTrieConfirms && r.BloomTrieNum <= (peer.headInfo.Number-r.Config.BloomTrieConfirms)/r.Config.BloomTrieSize
|
return peer.headInfo.Number >= r.Config.BloomTrieConfirms && r.BloomTrieNum <= (peer.headInfo.Number-r.Config.BloomTrieConfirms)/r.Config.BloomTrieSize
|
||||||
|
|
@ -431,17 +394,17 @@ func (r *BloomRequest) CanSend(peer *peer) bool {
|
||||||
// Request sends an ODR request to the LES network (implementation of LesOdrRequest)
|
// Request sends an ODR request to the LES network (implementation of LesOdrRequest)
|
||||||
func (r *BloomRequest) Request(reqID uint64, peer *peer) error {
|
func (r *BloomRequest) Request(reqID uint64, peer *peer) error {
|
||||||
peer.Log().Debug("Requesting BloomBits", "bloomTrie", r.BloomTrieNum, "bitIdx", r.BitIdx, "sections", r.SectionIndexList)
|
peer.Log().Debug("Requesting BloomBits", "bloomTrie", r.BloomTrieNum, "bitIdx", r.BitIdx, "sections", r.SectionIndexList)
|
||||||
reqs := make([]HelperTrieReq, len(r.SectionIndexList))
|
reqs := make([]protocol.HelperTrieRequest, len(r.SectionIndexList))
|
||||||
|
|
||||||
var encNumber [10]byte
|
var encNumber [10]byte
|
||||||
binary.BigEndian.PutUint16(encNumber[:2], uint16(r.BitIdx))
|
binary.BigEndian.PutUint16(encNumber[:2], uint16(r.BitIdx))
|
||||||
|
|
||||||
for i, sectionIdx := range r.SectionIndexList {
|
for i, sectionIdx := range r.SectionIndexList {
|
||||||
binary.BigEndian.PutUint64(encNumber[2:], sectionIdx)
|
binary.BigEndian.PutUint64(encNumber[2:], sectionIdx)
|
||||||
reqs[i] = HelperTrieReq{
|
reqs[i] = protocol.HelperTrieRequest{
|
||||||
Type: htBloomBits,
|
Type: protocol.HelperTrieBloomTrie,
|
||||||
TrieIdx: r.BloomTrieNum,
|
TrieIndex: r.BloomTrieNum,
|
||||||
Key: common.CopyBytes(encNumber[:]),
|
Key: common.CopyBytes(encNumber[:]),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return peer.RequestHelperTrieProofs(reqID, r.GetCost(peer), reqs)
|
return peer.RequestHelperTrieProofs(reqID, r.GetCost(peer), reqs)
|
||||||
|
|
@ -457,7 +420,7 @@ func (r *BloomRequest) Validate(db ethdb.Database, msg *Msg) error {
|
||||||
if msg.MsgType != MsgHelperTrieProofs {
|
if msg.MsgType != MsgHelperTrieProofs {
|
||||||
return errInvalidMessageType
|
return errInvalidMessageType
|
||||||
}
|
}
|
||||||
resps := msg.Obj.(HelperTrieResps)
|
resps := msg.Obj.(protocol.HelperTrieResponse)
|
||||||
proofs := resps.Proofs
|
proofs := resps.Proofs
|
||||||
nodeSet := proofs.NodeSet()
|
nodeSet := proofs.NodeSet()
|
||||||
reads := &readTraceDB{db: nodeSet}
|
reads := &readTraceDB{db: nodeSet}
|
||||||
|
|
@ -490,12 +453,12 @@ type TxStatusRequest light.TxStatusRequest
|
||||||
// GetCost returns the cost of the given ODR request according to the serving
|
// GetCost returns the cost of the given ODR request according to the serving
|
||||||
// peer's cost table (implementation of LesOdrRequest)
|
// peer's cost table (implementation of LesOdrRequest)
|
||||||
func (r *TxStatusRequest) GetCost(peer *peer) uint64 {
|
func (r *TxStatusRequest) GetCost(peer *peer) uint64 {
|
||||||
return peer.GetRequestCost(GetTxStatusMsg, len(r.Hashes))
|
return peer.GetRequestCost(protocol.GetTxStatusMsg, len(r.Hashes))
|
||||||
}
|
}
|
||||||
|
|
||||||
// CanSend tells if a certain peer is suitable for serving the given request
|
// CanSend tells if a certain peer is suitable for serving the given request
|
||||||
func (r *TxStatusRequest) CanSend(peer *peer) bool {
|
func (r *TxStatusRequest) CanSend(peer *peer) bool {
|
||||||
return peer.version >= lpv2
|
return peer.version >= protocol.Lpv2
|
||||||
}
|
}
|
||||||
|
|
||||||
// Request sends an ODR request to the LES network (implementation of LesOdrRequest)
|
// Request sends an ODR request to the LES network (implementation of LesOdrRequest)
|
||||||
|
|
|
||||||
244
les/peer.go
244
les/peer.go
|
|
@ -32,6 +32,7 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/eth"
|
"github.com/ethereum/go-ethereum/eth"
|
||||||
"github.com/ethereum/go-ethereum/les/flowcontrol"
|
"github.com/ethereum/go-ethereum/les/flowcontrol"
|
||||||
|
"github.com/ethereum/go-ethereum/les/protocol"
|
||||||
"github.com/ethereum/go-ethereum/les/utilities"
|
"github.com/ethereum/go-ethereum/les/utilities"
|
||||||
"github.com/ethereum/go-ethereum/light"
|
"github.com/ethereum/go-ethereum/light"
|
||||||
"github.com/ethereum/go-ethereum/p2p"
|
"github.com/ethereum/go-ethereum/p2p"
|
||||||
|
|
@ -89,7 +90,7 @@ type peer struct {
|
||||||
|
|
||||||
id string
|
id string
|
||||||
|
|
||||||
headInfo *announceData
|
headInfo *protocol.Announcement
|
||||||
lock sync.RWMutex
|
lock sync.RWMutex
|
||||||
|
|
||||||
sendQueue *utilities.ExecQueue
|
sendQueue *utilities.ExecQueue
|
||||||
|
|
@ -112,7 +113,7 @@ type peer struct {
|
||||||
fcClient *flowcontrol.ClientNode // nil if the peer is server only
|
fcClient *flowcontrol.ClientNode // nil if the peer is server only
|
||||||
fcServer *flowcontrol.ServerNode // nil if the peer is client only
|
fcServer *flowcontrol.ServerNode // nil if the peer is client only
|
||||||
fcParams flowcontrol.ServerParams
|
fcParams flowcontrol.ServerParams
|
||||||
fcCosts requestCostTable
|
fcCosts protocol.RequestCostTable
|
||||||
|
|
||||||
trusted, server bool
|
trusted, server bool
|
||||||
onlyAnnounce bool
|
onlyAnnounce bool
|
||||||
|
|
@ -179,7 +180,7 @@ func (p *peer) rejectUpdate(size uint64) bool {
|
||||||
// region. The client is also notified about being frozen/unfrozen with a Stop/Resume
|
// region. The client is also notified about being frozen/unfrozen with a Stop/Resume
|
||||||
// message.
|
// message.
|
||||||
func (p *peer) freezeClient() {
|
func (p *peer) freezeClient() {
|
||||||
if p.version < lpv3 {
|
if p.version < protocol.Lpv3 {
|
||||||
// if Stop/Resume is not supported then just drop the peer after setting
|
// if Stop/Resume is not supported then just drop the peer after setting
|
||||||
// its frozen status permanently
|
// its frozen status permanently
|
||||||
atomic.StoreUint32(&p.frozen, 1)
|
atomic.StoreUint32(&p.frozen, 1)
|
||||||
|
|
@ -258,11 +259,11 @@ func (p *peer) HeadAndTd() (hash common.Hash, td *big.Int) {
|
||||||
return hash, p.headInfo.Td
|
return hash, p.headInfo.Td
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *peer) headBlockInfo() blockInfo {
|
func (p *peer) headBlockInfo() protocol.HeadHeader {
|
||||||
p.lock.RLock()
|
p.lock.RLock()
|
||||||
defer p.lock.RUnlock()
|
defer p.lock.RUnlock()
|
||||||
|
|
||||||
return blockInfo{Hash: p.headInfo.Hash, Number: p.headInfo.Number, Td: p.headInfo.Td}
|
return protocol.HeadHeader{Hash: p.headInfo.Hash, Number: p.headInfo.Number, Td: p.headInfo.Td}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Td retrieves the current total difficulty of a peer.
|
// Td retrieves the current total difficulty of a peer.
|
||||||
|
|
@ -286,10 +287,10 @@ func (p *peer) updateCapacity(cap uint64) {
|
||||||
|
|
||||||
p.fcParams = flowcontrol.ServerParams{MinRecharge: cap, BufLimit: cap * bufLimitRatio}
|
p.fcParams = flowcontrol.ServerParams{MinRecharge: cap, BufLimit: cap * bufLimitRatio}
|
||||||
p.fcClient.UpdateParams(p.fcParams)
|
p.fcClient.UpdateParams(p.fcParams)
|
||||||
var kvList keyValueList
|
var kvList protocol.KeyValueList
|
||||||
kvList = kvList.add("flowControl/MRR", cap)
|
kvList = kvList.Add("flowControl/MRR", cap)
|
||||||
kvList = kvList.add("flowControl/BL", cap*bufLimitRatio)
|
kvList = kvList.Add("flowControl/BL", cap*bufLimitRatio)
|
||||||
p.queueSend(func() { p.SendAnnounce(announceData{Update: kvList}) })
|
p.queueSend(func() { p.SendAnnounce(protocol.Announcement{Update: kvList}) })
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *peer) responseID() uint64 {
|
func (p *peer) responseID() uint64 {
|
||||||
|
|
@ -336,7 +337,7 @@ func (p *peer) GetRequestCost(msgcode uint64, amount int) uint64 {
|
||||||
if costs == nil {
|
if costs == nil {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
cost := costs.baseCost + costs.reqCost*uint64(amount)
|
cost := costs.BaseCost + costs.ReqCost*uint64(amount)
|
||||||
if cost > p.fcParams.BufLimit {
|
if cost > p.fcParams.BufLimit {
|
||||||
cost = p.fcParams.BufLimit
|
cost = p.fcParams.BufLimit
|
||||||
}
|
}
|
||||||
|
|
@ -347,12 +348,12 @@ func (p *peer) GetTxRelayCost(amount, size int) uint64 {
|
||||||
p.lock.RLock()
|
p.lock.RLock()
|
||||||
defer p.lock.RUnlock()
|
defer p.lock.RUnlock()
|
||||||
|
|
||||||
costs := p.fcCosts[SendTxV2Msg]
|
costs := p.fcCosts[protocol.SendTxV2Msg]
|
||||||
if costs == nil {
|
if costs == nil {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
cost := costs.baseCost + costs.reqCost*uint64(amount)
|
cost := costs.BaseCost + costs.ReqCost*uint64(amount)
|
||||||
sizeCost := costs.baseCost + costs.reqCost*uint64(size)/txSizeCostLimit
|
sizeCost := costs.BaseCost + costs.ReqCost*uint64(size)/txSizeCostLimit
|
||||||
if sizeCost > cost {
|
if sizeCost > cost {
|
||||||
cost = sizeCost
|
cost = sizeCost
|
||||||
}
|
}
|
||||||
|
|
@ -385,185 +386,144 @@ func (p *peer) HasBlock(hash common.Hash, number uint64, hasState bool) bool {
|
||||||
|
|
||||||
// SendAnnounce announces the availability of a number of blocks through
|
// SendAnnounce announces the availability of a number of blocks through
|
||||||
// a hash notification.
|
// a hash notification.
|
||||||
func (p *peer) SendAnnounce(request announceData) error {
|
func (p *peer) SendAnnounce(request protocol.Announcement) error {
|
||||||
return p2p.Send(p.rw, AnnounceMsg, request)
|
return p2p.Send(p.rw, protocol.AnnounceMsg, request)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SendStop notifies the client about being in frozen state
|
// SendStop notifies the client about being in frozen state
|
||||||
func (p *peer) SendStop() error {
|
func (p *peer) SendStop() error {
|
||||||
return p2p.Send(p.rw, StopMsg, struct{}{})
|
return p2p.Send(p.rw, protocol.StopMsg, struct{}{})
|
||||||
}
|
}
|
||||||
|
|
||||||
// SendResume notifies the client about getting out of frozen state
|
// SendResume notifies the client about getting out of frozen state
|
||||||
func (p *peer) SendResume(bv uint64) error {
|
func (p *peer) SendResume(bv uint64) error {
|
||||||
return p2p.Send(p.rw, ResumeMsg, bv)
|
return p2p.Send(p.rw, protocol.ResumeMsg, bv)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ReplyBlockHeaders creates a reply with a batch of block headers
|
// ReplyBlockHeaders creates a reply with a batch of block headers
|
||||||
func (p *peer) ReplyBlockHeaders(reqID uint64, headers []*types.Header) *reply {
|
func (p *peer) ReplyBlockHeaders(reqID uint64, headers []*types.Header) *reply {
|
||||||
data, _ := rlp.EncodeToBytes(headers)
|
data, _ := rlp.EncodeToBytes(headers)
|
||||||
return &reply{p.rw, BlockHeadersMsg, reqID, data}
|
return &reply{p.rw, protocol.BlockHeadersMsg, reqID, data}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ReplyBlockBodiesRLP creates a reply with a batch of block contents from
|
// ReplyBlockBodiesRLP creates a reply with a batch of block contents from
|
||||||
// an already RLP encoded format.
|
// an already RLP encoded format.
|
||||||
func (p *peer) ReplyBlockBodiesRLP(reqID uint64, bodies []rlp.RawValue) *reply {
|
func (p *peer) ReplyBlockBodiesRLP(reqID uint64, bodies []rlp.RawValue) *reply {
|
||||||
data, _ := rlp.EncodeToBytes(bodies)
|
data, _ := rlp.EncodeToBytes(bodies)
|
||||||
return &reply{p.rw, BlockBodiesMsg, reqID, data}
|
return &reply{p.rw, protocol.BlockBodiesMsg, reqID, data}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ReplyCode creates a reply with a batch of arbitrary internal data, corresponding to the
|
// ReplyCode creates a reply with a batch of arbitrary internal data, corresponding to the
|
||||||
// hashes requested.
|
// hashes requested.
|
||||||
func (p *peer) ReplyCode(reqID uint64, codes [][]byte) *reply {
|
func (p *peer) ReplyCode(reqID uint64, codes [][]byte) *reply {
|
||||||
data, _ := rlp.EncodeToBytes(codes)
|
data, _ := rlp.EncodeToBytes(codes)
|
||||||
return &reply{p.rw, CodeMsg, reqID, data}
|
return &reply{p.rw, protocol.CodeMsg, reqID, data}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ReplyReceiptsRLP creates a reply with a batch of transaction receipts, corresponding to the
|
// ReplyReceiptsRLP creates a reply with a batch of transaction receipts, corresponding to the
|
||||||
// ones requested from an already RLP encoded format.
|
// ones requested from an already RLP encoded format.
|
||||||
func (p *peer) ReplyReceiptsRLP(reqID uint64, receipts []rlp.RawValue) *reply {
|
func (p *peer) ReplyReceiptsRLP(reqID uint64, receipts []rlp.RawValue) *reply {
|
||||||
data, _ := rlp.EncodeToBytes(receipts)
|
data, _ := rlp.EncodeToBytes(receipts)
|
||||||
return &reply{p.rw, ReceiptsMsg, reqID, data}
|
return &reply{p.rw, protocol.ReceiptsMsg, reqID, data}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ReplyProofsV2 creates a reply with a batch of merkle proofs, corresponding to the ones requested.
|
// ReplyProofsV2 creates a reply with a batch of merkle proofs, corresponding to the ones requested.
|
||||||
func (p *peer) ReplyProofsV2(reqID uint64, proofs light.NodeList) *reply {
|
func (p *peer) ReplyProofsV2(reqID uint64, proofs light.NodeList) *reply {
|
||||||
data, _ := rlp.EncodeToBytes(proofs)
|
data, _ := rlp.EncodeToBytes(proofs)
|
||||||
return &reply{p.rw, ProofsV2Msg, reqID, data}
|
return &reply{p.rw, protocol.ProofsV2Msg, reqID, data}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ReplyHelperTrieProofs creates a reply with a batch of HelperTrie proofs, corresponding to the ones requested.
|
// ReplyHelperTrieProofs creates a reply with a batch of HelperTrie proofs, corresponding to the ones requested.
|
||||||
func (p *peer) ReplyHelperTrieProofs(reqID uint64, resp HelperTrieResps) *reply {
|
func (p *peer) ReplyHelperTrieProofs(reqID uint64, resp protocol.HelperTrieResponse) *reply {
|
||||||
data, _ := rlp.EncodeToBytes(resp)
|
data, _ := rlp.EncodeToBytes(resp)
|
||||||
return &reply{p.rw, HelperTrieProofsMsg, reqID, data}
|
return &reply{p.rw, protocol.HelperTrieProofsMsg, reqID, data}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ReplyTxStatus creates a reply with a batch of transaction status records, corresponding to the ones requested.
|
// ReplyTxStatus creates a reply with a batch of transaction status records, corresponding to the ones requested.
|
||||||
func (p *peer) ReplyTxStatus(reqID uint64, stats []light.TxStatus) *reply {
|
func (p *peer) ReplyTxStatus(reqID uint64, stats []light.TxStatus) *reply {
|
||||||
data, _ := rlp.EncodeToBytes(stats)
|
data, _ := rlp.EncodeToBytes(stats)
|
||||||
return &reply{p.rw, TxStatusMsg, reqID, data}
|
return &reply{p.rw, protocol.TxStatusMsg, reqID, data}
|
||||||
}
|
}
|
||||||
|
|
||||||
// RequestHeadersByHash fetches a batch of blocks' headers corresponding to the
|
// RequestHeadersByHash fetches a batch of blocks' headers corresponding to the
|
||||||
// specified header query, based on the hash of an origin block.
|
// specified header query, based on the hash of an origin block.
|
||||||
func (p *peer) RequestHeadersByHash(reqID, cost uint64, origin common.Hash, amount int, skip int, reverse bool) error {
|
func (p *peer) RequestHeadersByHash(reqID, cost uint64, origin common.Hash, amount int, skip int, reverse bool) error {
|
||||||
p.Log().Debug("Fetching batch of headers", "count", amount, "fromhash", origin, "skip", skip, "reverse", reverse)
|
p.Log().Debug("Fetching batch of headers", "count", amount, "fromhash", origin, "skip", skip, "reverse", reverse)
|
||||||
return sendRequest(p.rw, GetBlockHeadersMsg, reqID, cost, &getBlockHeadersData{Origin: hashOrNumber{Hash: origin}, Amount: uint64(amount), Skip: uint64(skip), Reverse: reverse})
|
return sendRequest(p.rw, protocol.GetBlockHeadersMsg, reqID, cost, &protocol.GetBlockHeadersRequest{Origin: protocol.HashOrNumber{Hash: origin}, Amount: uint64(amount), Skip: uint64(skip), Reverse: reverse})
|
||||||
}
|
}
|
||||||
|
|
||||||
// RequestHeadersByNumber fetches a batch of blocks' headers corresponding to the
|
// RequestHeadersByNumber fetches a batch of blocks' headers corresponding to the
|
||||||
// specified header query, based on the number of an origin block.
|
// specified header query, based on the number of an origin block.
|
||||||
func (p *peer) RequestHeadersByNumber(reqID, cost, origin uint64, amount int, skip int, reverse bool) error {
|
func (p *peer) RequestHeadersByNumber(reqID, cost, origin uint64, amount int, skip int, reverse bool) error {
|
||||||
p.Log().Debug("Fetching batch of headers", "count", amount, "fromnum", origin, "skip", skip, "reverse", reverse)
|
p.Log().Debug("Fetching batch of headers", "count", amount, "fromnum", origin, "skip", skip, "reverse", reverse)
|
||||||
return sendRequest(p.rw, GetBlockHeadersMsg, reqID, cost, &getBlockHeadersData{Origin: hashOrNumber{Number: origin}, Amount: uint64(amount), Skip: uint64(skip), Reverse: reverse})
|
return sendRequest(p.rw, protocol.GetBlockHeadersMsg, reqID, cost, &protocol.GetBlockHeadersRequest{Origin: protocol.HashOrNumber{Number: origin}, Amount: uint64(amount), Skip: uint64(skip), Reverse: reverse})
|
||||||
}
|
}
|
||||||
|
|
||||||
// RequestBodies fetches a batch of blocks' bodies corresponding to the hashes
|
// RequestBodies fetches a batch of blocks' bodies corresponding to the hashes
|
||||||
// specified.
|
// specified.
|
||||||
func (p *peer) RequestBodies(reqID, cost uint64, hashes []common.Hash) error {
|
func (p *peer) RequestBodies(reqID, cost uint64, hashes []common.Hash) error {
|
||||||
p.Log().Debug("Fetching batch of block bodies", "count", len(hashes))
|
p.Log().Debug("Fetching batch of block bodies", "count", len(hashes))
|
||||||
return sendRequest(p.rw, GetBlockBodiesMsg, reqID, cost, hashes)
|
return sendRequest(p.rw, protocol.GetBlockBodiesMsg, reqID, cost, hashes)
|
||||||
}
|
}
|
||||||
|
|
||||||
// RequestCode fetches a batch of arbitrary data from a node's known state
|
// RequestCode fetches a batch of arbitrary data from a node's known state
|
||||||
// data, corresponding to the specified hashes.
|
// data, corresponding to the specified hashes.
|
||||||
func (p *peer) RequestCode(reqID, cost uint64, reqs []CodeReq) error {
|
func (p *peer) RequestCode(reqID, cost uint64, reqs []protocol.CodeRequest) error {
|
||||||
p.Log().Debug("Fetching batch of codes", "count", len(reqs))
|
p.Log().Debug("Fetching batch of codes", "count", len(reqs))
|
||||||
return sendRequest(p.rw, GetCodeMsg, reqID, cost, reqs)
|
return sendRequest(p.rw, protocol.GetCodeMsg, reqID, cost, reqs)
|
||||||
}
|
}
|
||||||
|
|
||||||
// RequestReceipts fetches a batch of transaction receipts from a remote node.
|
// RequestReceipts fetches a batch of transaction receipts from a remote node.
|
||||||
func (p *peer) RequestReceipts(reqID, cost uint64, hashes []common.Hash) error {
|
func (p *peer) RequestReceipts(reqID, cost uint64, hashes []common.Hash) error {
|
||||||
p.Log().Debug("Fetching batch of receipts", "count", len(hashes))
|
p.Log().Debug("Fetching batch of receipts", "count", len(hashes))
|
||||||
return sendRequest(p.rw, GetReceiptsMsg, reqID, cost, hashes)
|
return sendRequest(p.rw, protocol.GetReceiptsMsg, reqID, cost, hashes)
|
||||||
}
|
}
|
||||||
|
|
||||||
// RequestProofs fetches a batch of merkle proofs from a remote node.
|
// RequestProofs fetches a batch of merkle proofs from a remote node.
|
||||||
func (p *peer) RequestProofs(reqID, cost uint64, reqs []ProofReq) error {
|
func (p *peer) RequestProofs(reqID, cost uint64, reqs []protocol.TrieProofRequest) error {
|
||||||
p.Log().Debug("Fetching batch of proofs", "count", len(reqs))
|
p.Log().Debug("Fetching batch of proofs", "count", len(reqs))
|
||||||
return sendRequest(p.rw, GetProofsV2Msg, reqID, cost, reqs)
|
return sendRequest(p.rw, protocol.GetProofsV2Msg, reqID, cost, reqs)
|
||||||
}
|
}
|
||||||
|
|
||||||
// RequestHelperTrieProofs fetches a batch of HelperTrie merkle proofs from a remote node.
|
// RequestHelperTrieProofs fetches a batch of HelperTrie merkle proofs from a remote node.
|
||||||
func (p *peer) RequestHelperTrieProofs(reqID, cost uint64, reqs []HelperTrieReq) error {
|
func (p *peer) RequestHelperTrieProofs(reqID, cost uint64, reqs []protocol.HelperTrieRequest) error {
|
||||||
p.Log().Debug("Fetching batch of HelperTrie proofs", "count", len(reqs))
|
p.Log().Debug("Fetching batch of HelperTrie proofs", "count", len(reqs))
|
||||||
return sendRequest(p.rw, GetHelperTrieProofsMsg, reqID, cost, reqs)
|
return sendRequest(p.rw, protocol.GetHelperTrieProofsMsg, reqID, cost, reqs)
|
||||||
}
|
}
|
||||||
|
|
||||||
// RequestTxStatus fetches a batch of transaction status records from a remote node.
|
// RequestTxStatus fetches a batch of transaction status records from a remote node.
|
||||||
func (p *peer) RequestTxStatus(reqID, cost uint64, txHashes []common.Hash) error {
|
func (p *peer) RequestTxStatus(reqID, cost uint64, txHashes []common.Hash) error {
|
||||||
p.Log().Debug("Requesting transaction status", "count", len(txHashes))
|
p.Log().Debug("Requesting transaction status", "count", len(txHashes))
|
||||||
return sendRequest(p.rw, GetTxStatusMsg, reqID, cost, txHashes)
|
return sendRequest(p.rw, protocol.GetTxStatusMsg, reqID, cost, txHashes)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SendTxStatus creates a reply with a batch of transactions to be added to the remote transaction pool.
|
// SendTxStatus creates a reply with a batch of transactions to be added to the remote transaction pool.
|
||||||
func (p *peer) SendTxs(reqID, cost uint64, txs rlp.RawValue) error {
|
func (p *peer) SendTxs(reqID, cost uint64, txs rlp.RawValue) error {
|
||||||
p.Log().Debug("Sending batch of transactions", "size", len(txs))
|
p.Log().Debug("Sending batch of transactions", "size", len(txs))
|
||||||
return sendRequest(p.rw, SendTxV2Msg, reqID, cost, txs)
|
return sendRequest(p.rw, protocol.SendTxV2Msg, reqID, cost, txs)
|
||||||
}
|
}
|
||||||
|
|
||||||
type keyValueEntry struct {
|
func (p *peer) sendReceiveHandshake(sendList protocol.KeyValueList) (protocol.KeyValueList, error) {
|
||||||
Key string
|
|
||||||
Value rlp.RawValue
|
|
||||||
}
|
|
||||||
type keyValueList []keyValueEntry
|
|
||||||
type keyValueMap map[string]rlp.RawValue
|
|
||||||
|
|
||||||
func (l keyValueList) add(key string, val interface{}) keyValueList {
|
|
||||||
var entry keyValueEntry
|
|
||||||
entry.Key = key
|
|
||||||
if val == nil {
|
|
||||||
val = uint64(0)
|
|
||||||
}
|
|
||||||
enc, err := rlp.EncodeToBytes(val)
|
|
||||||
if err == nil {
|
|
||||||
entry.Value = enc
|
|
||||||
}
|
|
||||||
return append(l, entry)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (l keyValueList) decode() (keyValueMap, uint64) {
|
|
||||||
m := make(keyValueMap)
|
|
||||||
var size uint64
|
|
||||||
for _, entry := range l {
|
|
||||||
m[entry.Key] = entry.Value
|
|
||||||
size += uint64(len(entry.Key)) + uint64(len(entry.Value)) + 8
|
|
||||||
}
|
|
||||||
return m, size
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m keyValueMap) get(key string, val interface{}) error {
|
|
||||||
enc, ok := m[key]
|
|
||||||
if !ok {
|
|
||||||
return errResp(ErrMissingKey, "%s", key)
|
|
||||||
}
|
|
||||||
if val == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return rlp.DecodeBytes(enc, val)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *peer) sendReceiveHandshake(sendList keyValueList) (keyValueList, error) {
|
|
||||||
// Send out own handshake in a new thread
|
// Send out own handshake in a new thread
|
||||||
errc := make(chan error, 1)
|
errc := make(chan error, 1)
|
||||||
go func() {
|
go func() {
|
||||||
errc <- p2p.Send(p.rw, StatusMsg, sendList)
|
errc <- p2p.Send(p.rw, protocol.StatusMsg, sendList)
|
||||||
}()
|
}()
|
||||||
// In the mean time retrieve the remote status message
|
// In the mean time retrieve the remote status message
|
||||||
msg, err := p.rw.ReadMsg()
|
msg, err := p.rw.ReadMsg()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if msg.Code != StatusMsg {
|
if msg.Code != protocol.StatusMsg {
|
||||||
return nil, errResp(ErrNoStatusMsg, "first msg has code %x (!= %x)", msg.Code, StatusMsg)
|
return nil, protocol.ErrResp(protocol.ErrNoStatusMsg, "first msg has code %x (!= %x)", msg.Code, protocol.StatusMsg)
|
||||||
}
|
}
|
||||||
if msg.Size > ProtocolMaxMsgSize {
|
if msg.Size > protocol.ProtocolMaxMsgSize {
|
||||||
return nil, errResp(ErrMsgTooLarge, "%v > %v", msg.Size, ProtocolMaxMsgSize)
|
return nil, protocol.ErrResp(protocol.ErrMsgTooLarge, "%v > %v", msg.Size, protocol.ProtocolMaxMsgSize)
|
||||||
}
|
}
|
||||||
// Decode the handshake
|
// Decode the handshake
|
||||||
var recvList keyValueList
|
var recvList protocol.KeyValueList
|
||||||
if err := msg.Decode(&recvList); err != nil {
|
if err := msg.Decode(&recvList); err != nil {
|
||||||
return nil, errResp(ErrDecode, "msg %v: %v", msg, err)
|
return nil, protocol.ErrResp(protocol.ErrDecode, "msg %v: %v", msg, err)
|
||||||
}
|
}
|
||||||
if err := <-errc; err != nil {
|
if err := <-errc; err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
@ -577,21 +537,21 @@ func (p *peer) Handshake(td *big.Int, head common.Hash, headNum uint64, genesis
|
||||||
p.lock.Lock()
|
p.lock.Lock()
|
||||||
defer p.lock.Unlock()
|
defer p.lock.Unlock()
|
||||||
|
|
||||||
var send keyValueList
|
var send protocol.KeyValueList
|
||||||
|
|
||||||
// Add some basic handshake fields
|
// Add some basic handshake fields
|
||||||
send = send.add("protocolVersion", uint64(p.version))
|
send = send.Add("protocolVersion", uint64(p.version))
|
||||||
send = send.add("networkId", p.network)
|
send = send.Add("networkId", p.network)
|
||||||
send = send.add("headTd", td)
|
send = send.Add("headTd", td)
|
||||||
send = send.add("headHash", head)
|
send = send.Add("headHash", head)
|
||||||
send = send.add("headNum", headNum)
|
send = send.Add("headNum", headNum)
|
||||||
send = send.add("genesisHash", genesis)
|
send = send.Add("genesisHash", genesis)
|
||||||
if server != nil {
|
if server != nil {
|
||||||
// Add some information which services server can offer.
|
// Add some information which services server can offer.
|
||||||
if !server.config.UltraLightOnlyAnnounce {
|
if !server.config.UltraLightOnlyAnnounce {
|
||||||
send = send.add("serveHeaders", nil)
|
send = send.Add("serveHeaders", nil)
|
||||||
send = send.add("serveChainSince", uint64(0))
|
send = send.Add("serveChainSince", uint64(0))
|
||||||
send = send.add("serveStateSince", uint64(0))
|
send = send.Add("serveStateSince", uint64(0))
|
||||||
|
|
||||||
// If local ethereum node is running in archive mode, advertise ourselves we have
|
// If local ethereum node is running in archive mode, advertise ourselves we have
|
||||||
// all version state data. Otherwise only recent state is available.
|
// all version state data. Otherwise only recent state is available.
|
||||||
|
|
@ -599,20 +559,20 @@ func (p *peer) Handshake(td *big.Int, head common.Hash, headNum uint64, genesis
|
||||||
if server.archiveMode {
|
if server.archiveMode {
|
||||||
stateRecent = 0
|
stateRecent = 0
|
||||||
}
|
}
|
||||||
send = send.add("serveRecentState", stateRecent)
|
send = send.Add("serveRecentState", stateRecent)
|
||||||
send = send.add("txRelay", nil)
|
send = send.Add("txRelay", nil)
|
||||||
}
|
}
|
||||||
send = send.add("flowControl/BL", server.defParams.BufLimit)
|
send = send.Add("flowControl/BL", server.defParams.BufLimit)
|
||||||
send = send.add("flowControl/MRR", server.defParams.MinRecharge)
|
send = send.Add("flowControl/MRR", server.defParams.MinRecharge)
|
||||||
|
|
||||||
var costList RequestCostList
|
var costList protocol.RequestCostList
|
||||||
if server.costTracker.testCostList != nil {
|
if server.costTracker.testCostList != nil {
|
||||||
costList = server.costTracker.testCostList
|
costList = server.costTracker.testCostList
|
||||||
} else {
|
} else {
|
||||||
costList = server.costTracker.makeCostList(server.costTracker.globalFactor())
|
costList = server.costTracker.makeCostList(server.costTracker.globalFactor())
|
||||||
}
|
}
|
||||||
send = send.add("flowControl/MRC", costList)
|
send = send.Add("flowControl/MRC", costList)
|
||||||
p.fcCosts = costList.decode(ProtocolLengths[uint(p.version)])
|
p.fcCosts = costList.ToTable(protocol.ProtocolLengths[uint(p.version)])
|
||||||
p.fcParams = server.defParams
|
p.fcParams = server.defParams
|
||||||
|
|
||||||
// Add advertised checkpoint and register block height which
|
// Add advertised checkpoint and register block height which
|
||||||
|
|
@ -620,8 +580,8 @@ func (p *peer) Handshake(td *big.Int, head common.Hash, headNum uint64, genesis
|
||||||
if server.oracle != nil && server.oracle.IsRunning() {
|
if server.oracle != nil && server.oracle.IsRunning() {
|
||||||
cp, height := server.oracle.StableCheckpoint()
|
cp, height := server.oracle.StableCheckpoint()
|
||||||
if cp != nil {
|
if cp != nil {
|
||||||
send = send.add("checkpoint/value", cp)
|
send = send.Add("checkpoint/value", cp)
|
||||||
send = send.add("checkpoint/registerHeight", height)
|
send = send.Add("checkpoint/registerHeight", height)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -630,130 +590,136 @@ func (p *peer) Handshake(td *big.Int, head common.Hash, headNum uint64, genesis
|
||||||
if p.trusted {
|
if p.trusted {
|
||||||
p.announceType = announceTypeSigned
|
p.announceType = announceTypeSigned
|
||||||
}
|
}
|
||||||
send = send.add("announceType", p.announceType)
|
send = send.Add("announceType", p.announceType)
|
||||||
}
|
}
|
||||||
|
|
||||||
recvList, err := p.sendReceiveHandshake(send)
|
recvList, err := p.sendReceiveHandshake(send)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
recv, size := recvList.decode()
|
recv, size := recvList.ToMap()
|
||||||
if p.rejectUpdate(size) {
|
if p.rejectUpdate(size) {
|
||||||
return errResp(ErrRequestRejected, "")
|
return protocol.ErrResp(protocol.ErrRequestRejected, "")
|
||||||
}
|
}
|
||||||
|
|
||||||
var rGenesis, rHash common.Hash
|
var rGenesis, rHash common.Hash
|
||||||
var rVersion, rNetwork, rNum uint64
|
var rVersion, rNetwork, rNum uint64
|
||||||
var rTd *big.Int
|
var rTd *big.Int
|
||||||
|
|
||||||
if err := recv.get("protocolVersion", &rVersion); err != nil {
|
if err := recv.Get("protocolVersion", &rVersion); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := recv.get("networkId", &rNetwork); err != nil {
|
if err := recv.Get("networkId", &rNetwork); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := recv.get("headTd", &rTd); err != nil {
|
if err := recv.Get("headTd", &rTd); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := recv.get("headHash", &rHash); err != nil {
|
if err := recv.Get("headHash", &rHash); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := recv.get("headNum", &rNum); err != nil {
|
if err := recv.Get("headNum", &rNum); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := recv.get("genesisHash", &rGenesis); err != nil {
|
if err := recv.Get("genesisHash", &rGenesis); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if rGenesis != genesis {
|
if rGenesis != genesis {
|
||||||
return errResp(ErrGenesisBlockMismatch, "%x (!= %x)", rGenesis[:8], genesis[:8])
|
return protocol.ErrResp(protocol.ErrGenesisBlockMismatch, "%x (!= %x)", rGenesis[:8], genesis[:8])
|
||||||
}
|
}
|
||||||
if rNetwork != p.network {
|
if rNetwork != p.network {
|
||||||
return errResp(ErrNetworkIdMismatch, "%d (!= %d)", rNetwork, p.network)
|
return protocol.ErrResp(protocol.ErrNetworkIdMismatch, "%d (!= %d)", rNetwork, p.network)
|
||||||
}
|
}
|
||||||
if int(rVersion) != p.version {
|
if int(rVersion) != p.version {
|
||||||
return errResp(ErrProtocolVersionMismatch, "%d (!= %d)", rVersion, p.version)
|
return protocol.ErrResp(protocol.ErrProtocolVersionMismatch, "%d (!= %d)", rVersion, p.version)
|
||||||
}
|
}
|
||||||
|
|
||||||
if server != nil {
|
if server != nil {
|
||||||
p.server = recv.get("flowControl/MRR", nil) == nil
|
p.server = recv.Get("flowControl/MRR", nil) == nil
|
||||||
if p.server {
|
if p.server {
|
||||||
p.announceType = announceTypeNone // connected to another server, send no messages
|
p.announceType = announceTypeNone // connected to another server, send no messages
|
||||||
} else {
|
} else {
|
||||||
if recv.get("announceType", &p.announceType) != nil {
|
if recv.Get("announceType", &p.announceType) != nil {
|
||||||
// set default announceType on server side
|
// set default announceType on server side
|
||||||
p.announceType = announceTypeSimple
|
p.announceType = announceTypeSimple
|
||||||
}
|
}
|
||||||
p.fcClient = flowcontrol.NewClientNode(server.fcManager, server.defParams)
|
p.fcClient = flowcontrol.NewClientNode(server.fcManager, server.defParams)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if recv.get("serveChainSince", &p.chainSince) != nil {
|
if recv.Get("serveChainSince", &p.chainSince) != nil {
|
||||||
p.onlyAnnounce = true
|
p.onlyAnnounce = true
|
||||||
}
|
}
|
||||||
if recv.get("serveRecentChain", &p.chainRecent) != nil {
|
if recv.Get("serveRecentChain", &p.chainRecent) != nil {
|
||||||
p.chainRecent = 0
|
p.chainRecent = 0
|
||||||
}
|
}
|
||||||
if recv.get("serveStateSince", &p.stateSince) != nil {
|
if recv.Get("serveStateSince", &p.stateSince) != nil {
|
||||||
p.onlyAnnounce = true
|
p.onlyAnnounce = true
|
||||||
}
|
}
|
||||||
if recv.get("serveRecentState", &p.stateRecent) != nil {
|
if recv.Get("serveRecentState", &p.stateRecent) != nil {
|
||||||
p.stateRecent = 0
|
p.stateRecent = 0
|
||||||
}
|
}
|
||||||
if recv.get("txRelay", nil) != nil {
|
if recv.Get("txRelay", nil) != nil {
|
||||||
p.onlyAnnounce = true
|
p.onlyAnnounce = true
|
||||||
}
|
}
|
||||||
|
|
||||||
if p.onlyAnnounce && !p.trusted {
|
if p.onlyAnnounce && !p.trusted {
|
||||||
return errResp(ErrUselessPeer, "peer cannot serve requests")
|
return protocol.ErrResp(protocol.ErrUselessPeer, "peer cannot serve requests")
|
||||||
}
|
}
|
||||||
|
|
||||||
var sParams flowcontrol.ServerParams
|
var sParams flowcontrol.ServerParams
|
||||||
if err := recv.get("flowControl/BL", &sParams.BufLimit); err != nil {
|
if err := recv.Get("flowControl/BL", &sParams.BufLimit); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := recv.get("flowControl/MRR", &sParams.MinRecharge); err != nil {
|
if err := recv.Get("flowControl/MRR", &sParams.MinRecharge); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
var MRC RequestCostList
|
var MRC protocol.RequestCostList
|
||||||
if err := recv.get("flowControl/MRC", &MRC); err != nil {
|
if err := recv.Get("flowControl/MRC", &MRC); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
p.fcParams = sParams
|
p.fcParams = sParams
|
||||||
p.fcServer = flowcontrol.NewServerNode(sParams, &mclock.System{})
|
p.fcServer = flowcontrol.NewServerNode(sParams, &mclock.System{})
|
||||||
p.fcCosts = MRC.decode(ProtocolLengths[uint(p.version)])
|
p.fcCosts = MRC.ToTable(protocol.ProtocolLengths[uint(p.version)])
|
||||||
|
|
||||||
recv.get("checkpoint/value", &p.checkpoint)
|
recv.Get("checkpoint/value", &p.checkpoint)
|
||||||
recv.get("checkpoint/registerHeight", &p.checkpointNumber)
|
recv.Get("checkpoint/registerHeight", &p.checkpointNumber)
|
||||||
|
|
||||||
if !p.onlyAnnounce {
|
if !p.onlyAnnounce {
|
||||||
for msgCode := range reqAvgTimeCost {
|
for msgCode := range reqAvgTimeCost {
|
||||||
if p.fcCosts[msgCode] == nil {
|
if p.fcCosts[msgCode] == nil {
|
||||||
return errResp(ErrUselessPeer, "peer does not support message %d", msgCode)
|
return protocol.ErrResp(protocol.ErrUselessPeer, "peer does not support message %d", msgCode)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
p.server = true
|
p.server = true
|
||||||
}
|
}
|
||||||
p.headInfo = &announceData{Td: rTd, Hash: rHash, Number: rNum}
|
p.headInfo = &protocol.Announcement{
|
||||||
|
HeadHeader: protocol.HeadHeader{
|
||||||
|
Td: rTd,
|
||||||
|
Hash: rHash,
|
||||||
|
Number: rNum,
|
||||||
|
},
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// updateFlowControl updates the flow control parameters belonging to the server
|
// updateFlowControl updates the flow control parameters belonging to the server
|
||||||
// node if the announced key/value set contains relevant fields
|
// node if the announced key/value set contains relevant fields
|
||||||
func (p *peer) updateFlowControl(update keyValueMap) {
|
func (p *peer) updateFlowControl(update protocol.KeyValueMap) {
|
||||||
if p.fcServer == nil {
|
if p.fcServer == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// If any of the flow control params is nil, refuse to update.
|
// If any of the flow control params is nil, refuse to update.
|
||||||
var params flowcontrol.ServerParams
|
var params flowcontrol.ServerParams
|
||||||
if update.get("flowControl/BL", ¶ms.BufLimit) == nil && update.get("flowControl/MRR", ¶ms.MinRecharge) == nil {
|
if update.Get("flowControl/BL", ¶ms.BufLimit) == nil && update.Get("flowControl/MRR", ¶ms.MinRecharge) == nil {
|
||||||
// todo can light client set a minimal acceptable flow control params?
|
// todo can light client set a minimal acceptable flow control params?
|
||||||
p.fcParams = params
|
p.fcParams = params
|
||||||
p.fcServer.UpdateParams(params)
|
p.fcServer.UpdateParams(params)
|
||||||
}
|
}
|
||||||
var MRC RequestCostList
|
var MRC protocol.RequestCostList
|
||||||
if update.get("flowControl/MRC", &MRC) == nil {
|
if update.Get("flowControl/MRC", &MRC) == nil {
|
||||||
costUpdate := MRC.decode(ProtocolLengths[uint(p.version)])
|
costUpdate := MRC.ToTable(protocol.ProtocolLengths[uint(p.version)])
|
||||||
for code, cost := range costUpdate {
|
for code, cost := range costUpdate {
|
||||||
p.fcCosts[code] = cost
|
p.fcCosts[code] = cost
|
||||||
}
|
}
|
||||||
|
|
|
||||||
111
les/peer_test.go
111
les/peer_test.go
|
|
@ -27,12 +27,13 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
"github.com/ethereum/go-ethereum/eth"
|
"github.com/ethereum/go-ethereum/eth"
|
||||||
"github.com/ethereum/go-ethereum/les/flowcontrol"
|
"github.com/ethereum/go-ethereum/les/flowcontrol"
|
||||||
|
"github.com/ethereum/go-ethereum/les/protocol"
|
||||||
"github.com/ethereum/go-ethereum/p2p"
|
"github.com/ethereum/go-ethereum/p2p"
|
||||||
"github.com/ethereum/go-ethereum/p2p/enode"
|
"github.com/ethereum/go-ethereum/p2p/enode"
|
||||||
"github.com/ethereum/go-ethereum/rlp"
|
"github.com/ethereum/go-ethereum/rlp"
|
||||||
)
|
)
|
||||||
|
|
||||||
const protocolVersion = lpv2
|
const protocolVersion = protocol.Lpv2
|
||||||
|
|
||||||
var (
|
var (
|
||||||
hash = common.HexToHash("deadbeef")
|
hash = common.HexToHash("deadbeef")
|
||||||
|
|
@ -59,10 +60,10 @@ func TestPeerHandshakeSetAnnounceTypeToAnnounceTypeSignedForTrustedPeer(t *testi
|
||||||
version: protocolVersion,
|
version: protocolVersion,
|
||||||
trusted: true,
|
trusted: true,
|
||||||
rw: &rwStub{
|
rw: &rwStub{
|
||||||
WriteHook: func(recvList keyValueList) {
|
WriteHook: func(recvList protocol.KeyValueList) {
|
||||||
recv, _ := recvList.decode()
|
recv, _ := recvList.ToMap()
|
||||||
var reqType uint64
|
var reqType uint64
|
||||||
err := recv.get("announceType", &reqType)
|
err := recv.Get("announceType", &reqType)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
@ -70,18 +71,18 @@ func TestPeerHandshakeSetAnnounceTypeToAnnounceTypeSignedForTrustedPeer(t *testi
|
||||||
t.Fatal("Expected announceTypeSigned")
|
t.Fatal("Expected announceTypeSigned")
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
ReadHook: func(l keyValueList) keyValueList {
|
ReadHook: func(l protocol.KeyValueList) protocol.KeyValueList {
|
||||||
l = l.add("serveHeaders", nil)
|
l = l.Add("serveHeaders", nil)
|
||||||
l = l.add("serveChainSince", uint64(0))
|
l = l.Add("serveChainSince", uint64(0))
|
||||||
l = l.add("serveStateSince", uint64(0))
|
l = l.Add("serveStateSince", uint64(0))
|
||||||
l = l.add("txRelay", nil)
|
l = l.Add("txRelay", nil)
|
||||||
l = l.add("flowControl/BL", uint64(0))
|
l = l.Add("flowControl/BL", uint64(0))
|
||||||
l = l.add("flowControl/MRR", uint64(0))
|
l = l.Add("flowControl/MRR", uint64(0))
|
||||||
l = l.add("flowControl/MRC", testCostList(0))
|
l = l.Add("flowControl/MRC", testCostList(0))
|
||||||
return l
|
return l
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
network: NetworkId,
|
network: protocol.NetworkId,
|
||||||
}
|
}
|
||||||
err := p.Handshake(td, hash, headNum, genesis, nil)
|
err := p.Handshake(td, hash, headNum, genesis, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -98,11 +99,11 @@ func TestPeerHandshakeAnnounceTypeSignedForTrustedPeersPeerNotInTrusted(t *testi
|
||||||
Peer: p2p.NewPeer(id, "test peer", []p2p.Cap{}),
|
Peer: p2p.NewPeer(id, "test peer", []p2p.Cap{}),
|
||||||
version: protocolVersion,
|
version: protocolVersion,
|
||||||
rw: &rwStub{
|
rw: &rwStub{
|
||||||
WriteHook: func(recvList keyValueList) {
|
WriteHook: func(recvList protocol.KeyValueList) {
|
||||||
// checking that ulc sends to peer allowedRequests=noRequests and announceType != announceTypeSigned
|
// checking that ulc sends to peer allowedRequests=noRequests and announceType != announceTypeSigned
|
||||||
recv, _ := recvList.decode()
|
recv, _ := recvList.ToMap()
|
||||||
var reqType uint64
|
var reqType uint64
|
||||||
err := recv.get("announceType", &reqType)
|
err := recv.Get("announceType", &reqType)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
@ -110,18 +111,18 @@ func TestPeerHandshakeAnnounceTypeSignedForTrustedPeersPeerNotInTrusted(t *testi
|
||||||
t.Fatal("Expected not announceTypeSigned")
|
t.Fatal("Expected not announceTypeSigned")
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
ReadHook: func(l keyValueList) keyValueList {
|
ReadHook: func(l protocol.KeyValueList) protocol.KeyValueList {
|
||||||
l = l.add("serveHeaders", nil)
|
l = l.Add("serveHeaders", nil)
|
||||||
l = l.add("serveChainSince", uint64(0))
|
l = l.Add("serveChainSince", uint64(0))
|
||||||
l = l.add("serveStateSince", uint64(0))
|
l = l.Add("serveStateSince", uint64(0))
|
||||||
l = l.add("txRelay", nil)
|
l = l.Add("txRelay", nil)
|
||||||
l = l.add("flowControl/BL", uint64(0))
|
l = l.Add("flowControl/BL", uint64(0))
|
||||||
l = l.add("flowControl/MRR", uint64(0))
|
l = l.Add("flowControl/MRR", uint64(0))
|
||||||
l = l.add("flowControl/MRC", testCostList(0))
|
l = l.Add("flowControl/MRC", testCostList(0))
|
||||||
return l
|
return l
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
network: NetworkId,
|
network: protocol.NetworkId,
|
||||||
}
|
}
|
||||||
err := p.Handshake(td, hash, headNum, genesis, nil)
|
err := p.Handshake(td, hash, headNum, genesis, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -141,13 +142,13 @@ func TestPeerHandshakeDefaultAllRequests(t *testing.T) {
|
||||||
Peer: p2p.NewPeer(id, "test peer", []p2p.Cap{}),
|
Peer: p2p.NewPeer(id, "test peer", []p2p.Cap{}),
|
||||||
version: protocolVersion,
|
version: protocolVersion,
|
||||||
rw: &rwStub{
|
rw: &rwStub{
|
||||||
ReadHook: func(l keyValueList) keyValueList {
|
ReadHook: func(l protocol.KeyValueList) protocol.KeyValueList {
|
||||||
l = l.add("announceType", uint64(announceTypeSigned))
|
l = l.Add("announceType", uint64(announceTypeSigned))
|
||||||
l = l.add("allowedRequests", uint64(0))
|
l = l.Add("allowedRequests", uint64(0))
|
||||||
return l
|
return l
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
network: NetworkId,
|
network: protocol.NetworkId,
|
||||||
}
|
}
|
||||||
|
|
||||||
err := p.Handshake(td, hash, headNum, genesis, s)
|
err := p.Handshake(td, hash, headNum, genesis, s)
|
||||||
|
|
@ -170,11 +171,11 @@ func TestPeerHandshakeServerSendOnlyAnnounceRequestsHeaders(t *testing.T) {
|
||||||
Peer: p2p.NewPeer(id, "test peer", []p2p.Cap{}),
|
Peer: p2p.NewPeer(id, "test peer", []p2p.Cap{}),
|
||||||
version: protocolVersion,
|
version: protocolVersion,
|
||||||
rw: &rwStub{
|
rw: &rwStub{
|
||||||
ReadHook: func(l keyValueList) keyValueList {
|
ReadHook: func(l protocol.KeyValueList) protocol.KeyValueList {
|
||||||
l = l.add("announceType", uint64(announceTypeSigned))
|
l = l.Add("announceType", uint64(announceTypeSigned))
|
||||||
return l
|
return l
|
||||||
},
|
},
|
||||||
WriteHook: func(l keyValueList) {
|
WriteHook: func(l protocol.KeyValueList) {
|
||||||
for _, v := range l {
|
for _, v := range l {
|
||||||
if v.Key == "serveHeaders" ||
|
if v.Key == "serveHeaders" ||
|
||||||
v.Key == "serveChainSince" ||
|
v.Key == "serveChainSince" ||
|
||||||
|
|
@ -185,7 +186,7 @@ func TestPeerHandshakeServerSendOnlyAnnounceRequestsHeaders(t *testing.T) {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
network: NetworkId,
|
network: protocol.NetworkId,
|
||||||
}
|
}
|
||||||
|
|
||||||
err := p.Handshake(td, hash, headNum, genesis, s)
|
err := p.Handshake(td, hash, headNum, genesis, s)
|
||||||
|
|
@ -200,17 +201,17 @@ func TestPeerHandshakeClientReceiveOnlyAnnounceRequestsHeaders(t *testing.T) {
|
||||||
Peer: p2p.NewPeer(id, "test peer", []p2p.Cap{}),
|
Peer: p2p.NewPeer(id, "test peer", []p2p.Cap{}),
|
||||||
version: protocolVersion,
|
version: protocolVersion,
|
||||||
rw: &rwStub{
|
rw: &rwStub{
|
||||||
ReadHook: func(l keyValueList) keyValueList {
|
ReadHook: func(l protocol.KeyValueList) protocol.KeyValueList {
|
||||||
l = l.add("flowControl/BL", uint64(0))
|
l = l.Add("flowControl/BL", uint64(0))
|
||||||
l = l.add("flowControl/MRR", uint64(0))
|
l = l.Add("flowControl/MRR", uint64(0))
|
||||||
l = l.add("flowControl/MRC", RequestCostList{})
|
l = l.Add("flowControl/MRC", protocol.RequestCostList{})
|
||||||
|
|
||||||
l = l.add("announceType", uint64(announceTypeSigned))
|
l = l.Add("announceType", uint64(announceTypeSigned))
|
||||||
|
|
||||||
return l
|
return l
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
network: NetworkId,
|
network: protocol.NetworkId,
|
||||||
trusted: true,
|
trusted: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -231,15 +232,15 @@ func TestPeerHandshakeClientReturnErrorOnUselessPeer(t *testing.T) {
|
||||||
Peer: p2p.NewPeer(id, "test peer", []p2p.Cap{}),
|
Peer: p2p.NewPeer(id, "test peer", []p2p.Cap{}),
|
||||||
version: protocolVersion,
|
version: protocolVersion,
|
||||||
rw: &rwStub{
|
rw: &rwStub{
|
||||||
ReadHook: func(l keyValueList) keyValueList {
|
ReadHook: func(l protocol.KeyValueList) protocol.KeyValueList {
|
||||||
l = l.add("flowControl/BL", uint64(0))
|
l = l.Add("flowControl/BL", uint64(0))
|
||||||
l = l.add("flowControl/MRR", uint64(0))
|
l = l.Add("flowControl/MRR", uint64(0))
|
||||||
l = l.add("flowControl/MRC", RequestCostList{})
|
l = l.Add("flowControl/MRC", protocol.RequestCostList{})
|
||||||
l = l.add("announceType", uint64(announceTypeSigned))
|
l = l.Add("announceType", uint64(announceTypeSigned))
|
||||||
return l
|
return l
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
network: NetworkId,
|
network: protocol.NetworkId,
|
||||||
}
|
}
|
||||||
|
|
||||||
err := p.Handshake(td, hash, headNum, genesis, nil)
|
err := p.Handshake(td, hash, headNum, genesis, nil)
|
||||||
|
|
@ -264,18 +265,18 @@ func generateLesServer() *LesServer {
|
||||||
}
|
}
|
||||||
|
|
||||||
type rwStub struct {
|
type rwStub struct {
|
||||||
ReadHook func(l keyValueList) keyValueList
|
ReadHook func(l protocol.KeyValueList) protocol.KeyValueList
|
||||||
WriteHook func(l keyValueList)
|
WriteHook func(l protocol.KeyValueList)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *rwStub) ReadMsg() (p2p.Msg, error) {
|
func (s *rwStub) ReadMsg() (p2p.Msg, error) {
|
||||||
payload := keyValueList{}
|
payload := protocol.KeyValueList{}
|
||||||
payload = payload.add("protocolVersion", uint64(protocolVersion))
|
payload = payload.Add("protocolVersion", uint64(protocolVersion))
|
||||||
payload = payload.add("networkId", uint64(NetworkId))
|
payload = payload.Add("networkId", uint64(protocol.NetworkId))
|
||||||
payload = payload.add("headTd", td)
|
payload = payload.Add("headTd", td)
|
||||||
payload = payload.add("headHash", hash)
|
payload = payload.Add("headHash", hash)
|
||||||
payload = payload.add("headNum", headNum)
|
payload = payload.Add("headNum", headNum)
|
||||||
payload = payload.add("genesisHash", genesis)
|
payload = payload.Add("genesisHash", genesis)
|
||||||
|
|
||||||
if s.ReadHook != nil {
|
if s.ReadHook != nil {
|
||||||
payload = s.ReadHook(payload)
|
payload = s.ReadHook(payload)
|
||||||
|
|
@ -291,7 +292,7 @@ func (s *rwStub) ReadMsg() (p2p.Msg, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *rwStub) WriteMsg(m p2p.Msg) error {
|
func (s *rwStub) WriteMsg(m p2p.Msg) error {
|
||||||
recvList := keyValueList{}
|
recvList := protocol.KeyValueList{}
|
||||||
if err := m.Decode(&recvList); err != nil {
|
if err := m.Decode(&recvList); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
237
les/protocol.go
237
les/protocol.go
|
|
@ -1,237 +0,0 @@
|
||||||
// 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
|
|
||||||
|
|
||||||
import (
|
|
||||||
"crypto/ecdsa"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"math/big"
|
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
|
||||||
"github.com/ethereum/go-ethereum/p2p/enode"
|
|
||||||
"github.com/ethereum/go-ethereum/rlp"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Constants to match up protocol versions and messages
|
|
||||||
const (
|
|
||||||
lpv2 = 2
|
|
||||||
lpv3 = 3
|
|
||||||
)
|
|
||||||
|
|
||||||
// Supported versions of the les protocol (first is primary)
|
|
||||||
var (
|
|
||||||
ClientProtocolVersions = []uint{lpv2, lpv3}
|
|
||||||
ServerProtocolVersions = []uint{lpv2, lpv3}
|
|
||||||
AdvertiseProtocolVersions = []uint{lpv2} // clients are searching for the first advertised protocol in the list
|
|
||||||
)
|
|
||||||
|
|
||||||
// Number of implemented message corresponding to different protocol versions.
|
|
||||||
var ProtocolLengths = map[uint]uint64{lpv2: 22, lpv3: 24}
|
|
||||||
|
|
||||||
const (
|
|
||||||
NetworkId = 1
|
|
||||||
ProtocolMaxMsgSize = 10 * 1024 * 1024 // Maximum cap on the size of a protocol message
|
|
||||||
)
|
|
||||||
|
|
||||||
// les protocol message codes
|
|
||||||
const (
|
|
||||||
// Protocol messages inherited from LPV1
|
|
||||||
StatusMsg = 0x00
|
|
||||||
AnnounceMsg = 0x01
|
|
||||||
GetBlockHeadersMsg = 0x02
|
|
||||||
BlockHeadersMsg = 0x03
|
|
||||||
GetBlockBodiesMsg = 0x04
|
|
||||||
BlockBodiesMsg = 0x05
|
|
||||||
GetReceiptsMsg = 0x06
|
|
||||||
ReceiptsMsg = 0x07
|
|
||||||
GetCodeMsg = 0x0a
|
|
||||||
CodeMsg = 0x0b
|
|
||||||
// Protocol messages introduced in LPV2
|
|
||||||
GetProofsV2Msg = 0x0f
|
|
||||||
ProofsV2Msg = 0x10
|
|
||||||
GetHelperTrieProofsMsg = 0x11
|
|
||||||
HelperTrieProofsMsg = 0x12
|
|
||||||
SendTxV2Msg = 0x13
|
|
||||||
GetTxStatusMsg = 0x14
|
|
||||||
TxStatusMsg = 0x15
|
|
||||||
// Protocol messages introduced in LPV3
|
|
||||||
StopMsg = 0x16
|
|
||||||
ResumeMsg = 0x17
|
|
||||||
)
|
|
||||||
|
|
||||||
type requestInfo struct {
|
|
||||||
name string
|
|
||||||
maxCount uint64
|
|
||||||
}
|
|
||||||
|
|
||||||
var requests = map[uint64]requestInfo{
|
|
||||||
GetBlockHeadersMsg: {"GetBlockHeaders", MaxHeaderFetch},
|
|
||||||
GetBlockBodiesMsg: {"GetBlockBodies", MaxBodyFetch},
|
|
||||||
GetReceiptsMsg: {"GetReceipts", MaxReceiptFetch},
|
|
||||||
GetCodeMsg: {"GetCode", MaxCodeFetch},
|
|
||||||
GetProofsV2Msg: {"GetProofsV2", MaxProofsFetch},
|
|
||||||
GetHelperTrieProofsMsg: {"GetHelperTrieProofs", MaxHelperTrieProofsFetch},
|
|
||||||
SendTxV2Msg: {"SendTxV2", MaxTxSend},
|
|
||||||
GetTxStatusMsg: {"GetTxStatus", MaxTxStatus},
|
|
||||||
}
|
|
||||||
|
|
||||||
type errCode int
|
|
||||||
|
|
||||||
const (
|
|
||||||
ErrMsgTooLarge = iota
|
|
||||||
ErrDecode
|
|
||||||
ErrInvalidMsgCode
|
|
||||||
ErrProtocolVersionMismatch
|
|
||||||
ErrNetworkIdMismatch
|
|
||||||
ErrGenesisBlockMismatch
|
|
||||||
ErrNoStatusMsg
|
|
||||||
ErrExtraStatusMsg
|
|
||||||
ErrSuspendedPeer
|
|
||||||
ErrUselessPeer
|
|
||||||
ErrRequestRejected
|
|
||||||
ErrUnexpectedResponse
|
|
||||||
ErrInvalidResponse
|
|
||||||
ErrTooManyTimeouts
|
|
||||||
ErrMissingKey
|
|
||||||
)
|
|
||||||
|
|
||||||
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",
|
|
||||||
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.
|
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
||||||
// sanityCheck verifies that the values are reasonable, as a DoS protection
|
|
||||||
func (a *announceData) sanityCheck() error {
|
|
||||||
if tdlen := a.Td.BitLen(); tdlen > 100 {
|
|
||||||
return fmt.Errorf("too large block TD: bitlen %d", tdlen)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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(id enode.ID, update keyValueMap) error {
|
|
||||||
var sig []byte
|
|
||||||
if err := update.get("sign", &sig); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
rlp, _ := rlp.EncodeToBytes(announceBlock{a.Hash, a.Number, a.Td})
|
|
||||||
recPubkey, err := crypto.SigToPub(crypto.Keccak256(rlp), sig)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if id == enode.PubkeyToIDV4(recPubkey) {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
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
|
|
||||||
Td *big.Int // Total difficulty 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
|
|
||||||
}
|
|
||||||
|
|
||||||
// CodeData is the network response packet for a node data retrieval.
|
|
||||||
type CodeData []struct {
|
|
||||||
Value []byte
|
|
||||||
}
|
|
||||||
86
les/protocol/keyvalueset.go
Normal file
86
les/protocol/keyvalueset.go
Normal file
|
|
@ -0,0 +1,86 @@
|
||||||
|
// Copyright 2020 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 protocol
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/rlp"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ErrNonexistentEntry is returned if the specified key is non-existent.
|
||||||
|
var ErrNonexistentEntry = errors.New("the entry is non-existent")
|
||||||
|
|
||||||
|
// KeyValueEntry is the entry contained in a List or Map
|
||||||
|
// which can be extended with no limitaion.
|
||||||
|
type KeyValueEntry struct {
|
||||||
|
Key string
|
||||||
|
Value rlp.RawValue
|
||||||
|
}
|
||||||
|
|
||||||
|
// KeyValueList is a set of entries in list format.
|
||||||
|
//
|
||||||
|
// Usually KeyValueList is used as the container for
|
||||||
|
// protocol handshake.
|
||||||
|
type KeyValueList []KeyValueEntry
|
||||||
|
|
||||||
|
// KeyValueMap is a set of entires in map format.
|
||||||
|
// All entires is identified with its key and saved
|
||||||
|
// in RLP-encoded format.
|
||||||
|
//
|
||||||
|
// Usually KeyValueMap is used as the container for
|
||||||
|
// protocol handshake.
|
||||||
|
type KeyValueMap map[string]rlp.RawValue
|
||||||
|
|
||||||
|
// Add adds a new entry with specified key and value into list.
|
||||||
|
func (l KeyValueList) Add(key string, val interface{}) KeyValueList {
|
||||||
|
var entry KeyValueEntry
|
||||||
|
entry.Key = key
|
||||||
|
if val == nil {
|
||||||
|
val = uint64(0) // Use empty uint64 as default value
|
||||||
|
}
|
||||||
|
enc, err := rlp.EncodeToBytes(val)
|
||||||
|
if err == nil {
|
||||||
|
entry.Value = enc
|
||||||
|
}
|
||||||
|
return append(l, entry)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToMap converts list format to map format. Also returns
|
||||||
|
// the total size of converted map.
|
||||||
|
func (l KeyValueList) ToMap() (KeyValueMap, uint64) {
|
||||||
|
m := make(KeyValueMap)
|
||||||
|
var size uint64
|
||||||
|
for _, entry := range l {
|
||||||
|
m[entry.Key] = entry.Value
|
||||||
|
size += uint64(len(entry.Key)) + uint64(len(entry.Value)) + 8
|
||||||
|
}
|
||||||
|
return m, size
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get retrieves contained entry with specified key, decode the
|
||||||
|
// retrieved data in the provided container(interface).
|
||||||
|
func (m KeyValueMap) Get(key string, val interface{}) error {
|
||||||
|
enc, ok := m[key]
|
||||||
|
if !ok {
|
||||||
|
return ErrNonexistentEntry
|
||||||
|
}
|
||||||
|
if val == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return rlp.DecodeBytes(enc, val)
|
||||||
|
}
|
||||||
47
les/protocol/keyvalueset_test.go
Normal file
47
les/protocol/keyvalueset_test.go
Normal file
|
|
@ -0,0 +1,47 @@
|
||||||
|
// Copyright 2020 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 protocol
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/rlp"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestKeyValueSet(t *testing.T) {
|
||||||
|
var cases = []struct {
|
||||||
|
key string
|
||||||
|
value interface{}
|
||||||
|
}{
|
||||||
|
// {"key1", uint64(10)},
|
||||||
|
{"key2", false},
|
||||||
|
{"key3", nil},
|
||||||
|
}
|
||||||
|
var list KeyValueList
|
||||||
|
for _, c := range cases {
|
||||||
|
list = list.Add(c.key, c.value)
|
||||||
|
}
|
||||||
|
blob, err := rlp.EncodeToBytes(list)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to encode keyvalue list: %v", err)
|
||||||
|
}
|
||||||
|
var dec KeyValueList
|
||||||
|
err = rlp.DecodeBytes(blob, &dec)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to decode keyvalue list: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
362
les/protocol/protocol.go
Normal file
362
les/protocol/protocol.go
Normal file
|
|
@ -0,0 +1,362 @@
|
||||||
|
// 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 protocol defines all protocol related structures which will be
|
||||||
|
// used in both server side and client side.
|
||||||
|
package protocol
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/ecdsa"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"math/big"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
|
"github.com/ethereum/go-ethereum/light"
|
||||||
|
"github.com/ethereum/go-ethereum/p2p/discv5"
|
||||||
|
"github.com/ethereum/go-ethereum/p2p/enode"
|
||||||
|
"github.com/ethereum/go-ethereum/rlp"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Constants to match up protocol versions and messages
|
||||||
|
const (
|
||||||
|
Lpv2 = 2
|
||||||
|
Lpv3 = 3
|
||||||
|
)
|
||||||
|
|
||||||
|
// Supported versions of the les protocol (first is primary)
|
||||||
|
var (
|
||||||
|
ClientProtocolVersions = []uint{Lpv2, Lpv3}
|
||||||
|
ServerProtocolVersions = []uint{Lpv2, Lpv3}
|
||||||
|
AdvertiseProtocolVersions = []uint{Lpv2} // clients are searching for the first advertised protocol in the list
|
||||||
|
)
|
||||||
|
|
||||||
|
// Number of implemented message corresponding to different protocol versions.
|
||||||
|
var ProtocolLengths = map[uint]uint64{Lpv2: 22, Lpv3: 24}
|
||||||
|
|
||||||
|
const (
|
||||||
|
NetworkId = 1 // Default ethereum mainnet network ID
|
||||||
|
ProtocolMaxMsgSize = 10 * 1024 * 1024 // Maximum cap on the size of a protocol message
|
||||||
|
)
|
||||||
|
|
||||||
|
// les protocol message codes
|
||||||
|
const (
|
||||||
|
// Protocol messages inherited from LPV1
|
||||||
|
StatusMsg = 0x00
|
||||||
|
AnnounceMsg = 0x01
|
||||||
|
GetBlockHeadersMsg = 0x02
|
||||||
|
BlockHeadersMsg = 0x03
|
||||||
|
GetBlockBodiesMsg = 0x04
|
||||||
|
BlockBodiesMsg = 0x05
|
||||||
|
GetReceiptsMsg = 0x06
|
||||||
|
ReceiptsMsg = 0x07
|
||||||
|
GetCodeMsg = 0x0a
|
||||||
|
CodeMsg = 0x0b
|
||||||
|
|
||||||
|
// Protocol messages introduced in LPV2
|
||||||
|
GetProofsV2Msg = 0x0f
|
||||||
|
ProofsV2Msg = 0x10
|
||||||
|
GetHelperTrieProofsMsg = 0x11
|
||||||
|
HelperTrieProofsMsg = 0x12
|
||||||
|
SendTxV2Msg = 0x13
|
||||||
|
GetTxStatusMsg = 0x14
|
||||||
|
TxStatusMsg = 0x15
|
||||||
|
|
||||||
|
// Protocol messages introduced in LPV3
|
||||||
|
StopMsg = 0x16
|
||||||
|
ResumeMsg = 0x17
|
||||||
|
)
|
||||||
|
|
||||||
|
// The maxmium amount of data requested per retrieval request.
|
||||||
|
const (
|
||||||
|
MaxHeaderFetch = 192 // Amount of block headers to be fetched per retrieval request
|
||||||
|
MaxBodyFetch = 32 // Amount of block bodies to be fetched per retrieval request
|
||||||
|
MaxReceiptFetch = 128 // Amount of transaction receipts to allow fetching per request
|
||||||
|
MaxCodeFetch = 64 // Amount of contract codes to allow fetching per request
|
||||||
|
MaxProofsFetch = 64 // Amount of merkle proofs to be fetched per retrieval request
|
||||||
|
MaxHelperTrieProofsFetch = 64 // Amount of helper tries to be fetched per retrieval request
|
||||||
|
MaxTxSend = 64 // Amount of transactions to be send per request
|
||||||
|
MaxTxStatus = 256 // Amount of transactions to queried per request
|
||||||
|
)
|
||||||
|
|
||||||
|
type RequestInfo struct {
|
||||||
|
Name string
|
||||||
|
MaxCount uint64
|
||||||
|
}
|
||||||
|
|
||||||
|
var LesRequests = map[uint64]RequestInfo{
|
||||||
|
GetBlockHeadersMsg: {"GetBlockHeaders", MaxHeaderFetch},
|
||||||
|
GetBlockBodiesMsg: {"GetBlockBodies", MaxBodyFetch},
|
||||||
|
GetReceiptsMsg: {"GetReceipts", MaxReceiptFetch},
|
||||||
|
GetCodeMsg: {"GetCode", MaxCodeFetch},
|
||||||
|
GetProofsV2Msg: {"GetProofsV2", MaxProofsFetch},
|
||||||
|
GetHelperTrieProofsMsg: {"GetHelperTrieProofs", MaxHelperTrieProofsFetch},
|
||||||
|
SendTxV2Msg: {"SendTxV2", MaxTxSend},
|
||||||
|
GetTxStatusMsg: {"GetTxStatus", MaxTxStatus},
|
||||||
|
}
|
||||||
|
|
||||||
|
type ErrCode int
|
||||||
|
|
||||||
|
const (
|
||||||
|
ErrMsgTooLarge = iota
|
||||||
|
ErrDecode
|
||||||
|
ErrInvalidMsgCode
|
||||||
|
ErrProtocolVersionMismatch
|
||||||
|
ErrNetworkIdMismatch
|
||||||
|
ErrGenesisBlockMismatch
|
||||||
|
ErrNoStatusMsg
|
||||||
|
ErrExtraStatusMsg
|
||||||
|
ErrSuspendedPeer
|
||||||
|
ErrUselessPeer
|
||||||
|
ErrRequestRejected
|
||||||
|
ErrUnexpectedResponse
|
||||||
|
ErrInvalidResponse
|
||||||
|
ErrTooManyTimeouts
|
||||||
|
ErrMissingKey
|
||||||
|
)
|
||||||
|
|
||||||
|
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",
|
||||||
|
ErrMissingKey: "Key missing from list",
|
||||||
|
}
|
||||||
|
|
||||||
|
// HeadHeader is the a part of announcement sent by the LES server to the
|
||||||
|
// LES client when a new block is generated in the network.
|
||||||
|
//
|
||||||
|
// HeadHeader can also be used to represent the head info of peer(both server
|
||||||
|
// and client).
|
||||||
|
type HeadHeader 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
|
||||||
|
}
|
||||||
|
|
||||||
|
// Announcement is a network packet sent by the LES server to the LES client
|
||||||
|
// when a new block is generated in the network or the server has protocol
|
||||||
|
// parameters that need to be updated.
|
||||||
|
type Announcement struct {
|
||||||
|
HeadHeader // The data of new arrival header
|
||||||
|
ReorgDepth uint64 // The reorg depth of new arrival header
|
||||||
|
Update KeyValueList // Updated protocol parameters
|
||||||
|
}
|
||||||
|
|
||||||
|
// SanityCheck verifies that the values are reasonable, as a DoS protection
|
||||||
|
func (a *Announcement) SanityCheck() error {
|
||||||
|
if tdlen := a.Td.BitLen(); tdlen > 100 {
|
||||||
|
return fmt.Errorf("too large block TD: bitlen %d", tdlen)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sign adds a signature to the block announcement by the given privKey
|
||||||
|
func (a *Announcement) Sign(privKey *ecdsa.PrivateKey) {
|
||||||
|
rlp, _ := rlp.EncodeToBytes(HeadHeader{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 *Announcement) CheckSignature(id enode.ID, update KeyValueMap) error {
|
||||||
|
var sig []byte
|
||||||
|
if err := update.Get("sign", &sig); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
rlp, _ := rlp.EncodeToBytes(HeadHeader{a.Hash, a.Number, a.Td})
|
||||||
|
recPubkey, err := crypto.SigToPub(crypto.Keccak256(rlp), sig)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if id == enode.PubkeyToIDV4(recPubkey) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return errors.New("wrong signature")
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetBlockHeadersRequest represents a block header query sent by les client.
|
||||||
|
type GetBlockHeadersRequest 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
|
||||||
|
}
|
||||||
|
|
||||||
|
// TrieProofRequest represents a state/storage trie proof query
|
||||||
|
// sent by les client.
|
||||||
|
type TrieProofRequest struct {
|
||||||
|
BlockHash common.Hash // The corresponding block hash of state
|
||||||
|
Account []byte // The address of target account, nil if it's a global state trie proof request
|
||||||
|
Key []byte // The key of target storage slot or account
|
||||||
|
FromLevel uint // The node level beyond which all trie nodes are contained in the proof
|
||||||
|
}
|
||||||
|
|
||||||
|
// CodeRequest represents a contract code query sent by les client.
|
||||||
|
type CodeRequest struct {
|
||||||
|
BlockHash common.Hash // The corresponding block hash of state
|
||||||
|
Account []byte // The address of target account
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
// HelperTrieCHT is the indicator of canonical hash trie, check
|
||||||
|
// https://github.com/ethereum/devp2p/blob/master/caps/les.md#canonical-hash-trie
|
||||||
|
// for more details.
|
||||||
|
HelperTrieCHT = iota
|
||||||
|
|
||||||
|
// HelperTrieBloomTrie is the indicator of bloom trie, check
|
||||||
|
// https://github.com/ethereum/devp2p/blob/master/caps/les.md#bloombits-trie
|
||||||
|
// for more details
|
||||||
|
HelperTrieBloomTrie
|
||||||
|
|
||||||
|
// The auxiliary data type of helperTrie request which is available for
|
||||||
|
// all helperTrie request.
|
||||||
|
AuxRoot = 1
|
||||||
|
|
||||||
|
// The auxiliary data type of CHT request - corresponding block header
|
||||||
|
// which is only avaiable for CHT request.
|
||||||
|
AuxHeader = 2
|
||||||
|
)
|
||||||
|
|
||||||
|
// HelperTrieRequest represents a helper trie query sent by les client.
|
||||||
|
// HelperTrie includes: CHT and bloom trie. It's a shared structure between
|
||||||
|
// these two kinds of request.
|
||||||
|
//
|
||||||
|
// Except the helperTrie proof of requested entry will be returned, caller
|
||||||
|
// can specify more additional auxiliary data to be returned via `AuxType`.
|
||||||
|
type HelperTrieRequest struct {
|
||||||
|
Type uint // Indicator of request type, 0 represents CHT, 1 represents Bloom trie
|
||||||
|
TrieIndex uint64 // The index(section index) of requested trie
|
||||||
|
Key []byte // The list of entry keys, caller can request a batch of entries in a single request.
|
||||||
|
FromLevel uint // The node level beyond which all trie nodes are contained in the proof
|
||||||
|
AuxType uint // The type of auxiliary data requested
|
||||||
|
}
|
||||||
|
|
||||||
|
// HelperTrieResponse represents the response of corresponding helperTrie
|
||||||
|
// request. A single response contains a batch of requested proofs and
|
||||||
|
// corresponding auxiliary data.
|
||||||
|
type HelperTrieResponse struct {
|
||||||
|
Proofs light.NodeList // The container for storing all requested proofs
|
||||||
|
AuxData [][]byte // The batch of requested auxiliary data
|
||||||
|
}
|
||||||
|
|
||||||
|
// ErrResp returns an protocol error with given error code and additional
|
||||||
|
// error message.
|
||||||
|
func ErrResp(code ErrCode, format string, v ...interface{}) error {
|
||||||
|
return fmt.Errorf("%v - %v", code, fmt.Sprintf(format, v...))
|
||||||
|
}
|
||||||
|
|
||||||
|
// LesTopic constructs the discovery v5 topic for LES protocol.
|
||||||
|
func LesTopic(genesisHash common.Hash, protocolVersion uint) discv5.Topic {
|
||||||
|
var name string
|
||||||
|
switch protocolVersion {
|
||||||
|
case Lpv2:
|
||||||
|
name = "LES2"
|
||||||
|
default:
|
||||||
|
panic(nil)
|
||||||
|
}
|
||||||
|
return discv5.Topic(name + "@" + common.Bytes2Hex(genesisHash.Bytes()[0:8]))
|
||||||
|
}
|
||||||
|
|
||||||
|
type (
|
||||||
|
// RequestCost represents a cost policy of a specified request type.
|
||||||
|
RequestCost struct {
|
||||||
|
BaseCost, ReqCost uint64
|
||||||
|
}
|
||||||
|
// RequestCostTable assigns a cost estimate function to each request type
|
||||||
|
// which is a linear function of the requested amount
|
||||||
|
// (cost = BaseCost + ReqCost * amount)
|
||||||
|
RequestCostTable map[uint64]*RequestCost
|
||||||
|
// RequestCostList is a list representation of request costs which is used for
|
||||||
|
// database storage and communication through the network
|
||||||
|
RequestCostList []RequestCostListItem
|
||||||
|
RequestCostListItem struct {
|
||||||
|
MsgCode, BaseCost, ReqCost uint64
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
// GetMaxCost calculates the estimated cost for a given request type and amount
|
||||||
|
func (table RequestCostTable) GetMaxCost(code, amount uint64) uint64 {
|
||||||
|
costs := table[code]
|
||||||
|
return costs.BaseCost + amount*costs.ReqCost
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToTable converts a cost list to a cost table
|
||||||
|
func (list RequestCostList) ToTable(protocolLength uint64) RequestCostTable {
|
||||||
|
table := make(RequestCostTable)
|
||||||
|
for _, e := range list {
|
||||||
|
if e.MsgCode < protocolLength {
|
||||||
|
table[e.MsgCode] = &RequestCost{
|
||||||
|
BaseCost: e.BaseCost,
|
||||||
|
ReqCost: e.ReqCost,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return table
|
||||||
|
}
|
||||||
|
|
@ -25,6 +25,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common/mclock"
|
"github.com/ethereum/go-ethereum/common/mclock"
|
||||||
|
"github.com/ethereum/go-ethereum/les/protocol"
|
||||||
"github.com/ethereum/go-ethereum/light"
|
"github.com/ethereum/go-ethereum/light"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -171,7 +172,7 @@ func (rm *retrieveManager) deliver(peer distPeer, msg *Msg) error {
|
||||||
if ok {
|
if ok {
|
||||||
return req.deliver(peer, msg)
|
return req.deliver(peer, msg)
|
||||||
}
|
}
|
||||||
return errResp(ErrUnexpectedResponse, "reqID = %v", msg.ReqID)
|
return protocol.ErrResp(protocol.ErrUnexpectedResponse, "reqID = %v", msg.ReqID)
|
||||||
}
|
}
|
||||||
|
|
||||||
// frozen is called by the LES protocol manager when a server has suspended its service and we
|
// frozen is called by the LES protocol manager when a server has suspended its service and we
|
||||||
|
|
@ -389,7 +390,7 @@ func (r *sentReq) deliver(peer distPeer, msg *Msg) error {
|
||||||
|
|
||||||
s, ok := r.sentTo[peer]
|
s, ok := r.sentTo[peer]
|
||||||
if !ok || s.delivered {
|
if !ok || s.delivered {
|
||||||
return errResp(ErrUnexpectedResponse, "reqID = %v", msg.ReqID)
|
return protocol.ErrResp(protocol.ErrUnexpectedResponse, "reqID = %v", msg.ReqID)
|
||||||
}
|
}
|
||||||
if s.frozen {
|
if s.frozen {
|
||||||
return nil
|
return nil
|
||||||
|
|
@ -402,7 +403,7 @@ func (r *sentReq) deliver(peer distPeer, msg *Msg) error {
|
||||||
s.event <- rpDeliveredInvalid
|
s.event <- rpDeliveredInvalid
|
||||||
}
|
}
|
||||||
if !valid {
|
if !valid {
|
||||||
return errResp(ErrInvalidResponse, "reqID = %v", msg.ReqID)
|
return protocol.ErrResp(protocol.ErrInvalidResponse, "reqID = %v", msg.ReqID)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,7 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/eth"
|
"github.com/ethereum/go-ethereum/eth"
|
||||||
"github.com/ethereum/go-ethereum/les/checkpointoracle"
|
"github.com/ethereum/go-ethereum/les/checkpointoracle"
|
||||||
"github.com/ethereum/go-ethereum/les/flowcontrol"
|
"github.com/ethereum/go-ethereum/les/flowcontrol"
|
||||||
|
"github.com/ethereum/go-ethereum/les/protocol"
|
||||||
"github.com/ethereum/go-ethereum/light"
|
"github.com/ethereum/go-ethereum/light"
|
||||||
"github.com/ethereum/go-ethereum/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
"github.com/ethereum/go-ethereum/p2p"
|
"github.com/ethereum/go-ethereum/p2p"
|
||||||
|
|
@ -58,9 +59,9 @@ type LesServer struct {
|
||||||
|
|
||||||
func NewLesServer(e *eth.Ethereum, config *eth.Config) (*LesServer, error) {
|
func NewLesServer(e *eth.Ethereum, config *eth.Config) (*LesServer, error) {
|
||||||
// Collect les protocol version information supported by local node.
|
// Collect les protocol version information supported by local node.
|
||||||
lesTopics := make([]discv5.Topic, len(AdvertiseProtocolVersions))
|
lesTopics := make([]discv5.Topic, len(protocol.AdvertiseProtocolVersions))
|
||||||
for i, pv := range AdvertiseProtocolVersions {
|
for i, pv := range protocol.AdvertiseProtocolVersions {
|
||||||
lesTopics[i] = lesTopic(e.BlockChain().Genesis().Hash(), pv)
|
lesTopics[i] = protocol.LesTopic(e.BlockChain().Genesis().Hash(), pv)
|
||||||
}
|
}
|
||||||
// Calculate the number of threads used to service the light client
|
// Calculate the number of threads used to service the light client
|
||||||
// requests based on the user-specified value.
|
// requests based on the user-specified value.
|
||||||
|
|
@ -151,7 +152,7 @@ func (s *LesServer) APIs() []rpc.API {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *LesServer) Protocols() []p2p.Protocol {
|
func (s *LesServer) Protocols() []p2p.Protocol {
|
||||||
ps := s.makeProtocols(ServerProtocolVersions, s.handler.runPeer, func(id enode.ID) interface{} {
|
ps := s.makeProtocols(protocol.ServerProtocolVersions, s.handler.runPeer, func(id enode.ID) interface{} {
|
||||||
if p := s.peers.Peer(peerIdToString(id)); p != nil {
|
if p := s.peers.Peer(peerIdToString(id)); p != nil {
|
||||||
return p.Info()
|
return p.Info()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,7 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/core/state"
|
"github.com/ethereum/go-ethereum/core/state"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/ethdb"
|
"github.com/ethereum/go-ethereum/ethdb"
|
||||||
|
"github.com/ethereum/go-ethereum/les/protocol"
|
||||||
"github.com/ethereum/go-ethereum/light"
|
"github.com/ethereum/go-ethereum/light"
|
||||||
"github.com/ethereum/go-ethereum/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
"github.com/ethereum/go-ethereum/metrics"
|
"github.com/ethereum/go-ethereum/metrics"
|
||||||
|
|
@ -43,15 +44,6 @@ const (
|
||||||
softResponseLimit = 2 * 1024 * 1024 // Target maximum size of returned blocks, headers or node data.
|
softResponseLimit = 2 * 1024 * 1024 // Target maximum size of returned blocks, headers or node data.
|
||||||
estHeaderRlpSize = 500 // Approximate size of an RLP encoded block header
|
estHeaderRlpSize = 500 // Approximate size of an RLP encoded block header
|
||||||
ethVersion = 63 // equivalent eth version for the downloader
|
ethVersion = 63 // equivalent eth version for the downloader
|
||||||
|
|
||||||
MaxHeaderFetch = 192 // Amount of block headers to be fetched per retrieval request
|
|
||||||
MaxBodyFetch = 32 // Amount of block bodies to be fetched per retrieval request
|
|
||||||
MaxReceiptFetch = 128 // Amount of transaction receipts to allow fetching per request
|
|
||||||
MaxCodeFetch = 64 // Amount of contract codes to allow fetching per request
|
|
||||||
MaxProofsFetch = 64 // Amount of merkle proofs to be fetched per retrieval request
|
|
||||||
MaxHelperTrieProofsFetch = 64 // Amount of helper tries to be fetched per retrieval request
|
|
||||||
MaxTxSend = 64 // Amount of transactions to be send per request
|
|
||||||
MaxTxStatus = 256 // Amount of transactions to queried per request
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|
@ -182,9 +174,9 @@ func (h *serverHandler) handleMsg(p *peer, wg *sync.WaitGroup) error {
|
||||||
p.Log().Trace("Light Ethereum message arrived", "code", msg.Code, "bytes", msg.Size)
|
p.Log().Trace("Light Ethereum message arrived", "code", msg.Code, "bytes", msg.Size)
|
||||||
|
|
||||||
// Discard large message which exceeds the limitation.
|
// Discard large message which exceeds the limitation.
|
||||||
if msg.Size > ProtocolMaxMsgSize {
|
if msg.Size > protocol.ProtocolMaxMsgSize {
|
||||||
clientErrorMeter.Mark(1)
|
clientErrorMeter.Mark(1)
|
||||||
return errResp(ErrMsgTooLarge, "%v > %v", msg.Size, ProtocolMaxMsgSize)
|
return protocol.ErrResp(protocol.ErrMsgTooLarge, "%v > %v", msg.Size, protocol.ProtocolMaxMsgSize)
|
||||||
}
|
}
|
||||||
defer msg.Discard()
|
defer msg.Discard()
|
||||||
|
|
||||||
|
|
@ -204,7 +196,7 @@ func (h *serverHandler) handleMsg(p *peer, wg *sync.WaitGroup) error {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
// Prepaid max cost units before request been serving.
|
// Prepaid max cost units before request been serving.
|
||||||
maxCost = p.fcCosts.getMaxCost(msg.Code, reqCnt)
|
maxCost = p.fcCosts.GetMaxCost(msg.Code, reqCnt)
|
||||||
accepted, bufShort, priority := p.fcClient.AcceptRequest(reqID, responseCount, maxCost)
|
accepted, bufShort, priority := p.fcClient.AcceptRequest(reqID, responseCount, maxCost)
|
||||||
if !accepted {
|
if !accepted {
|
||||||
p.freezeClient()
|
p.freezeClient()
|
||||||
|
|
@ -268,7 +260,7 @@ func (h *serverHandler) handleMsg(p *peer, wg *sync.WaitGroup) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
switch msg.Code {
|
switch msg.Code {
|
||||||
case GetBlockHeadersMsg:
|
case protocol.GetBlockHeadersMsg:
|
||||||
p.Log().Trace("Received block header request")
|
p.Log().Trace("Received block header request")
|
||||||
if metrics.EnabledExpensive {
|
if metrics.EnabledExpensive {
|
||||||
miscInHeaderPacketsMeter.Mark(1)
|
miscInHeaderPacketsMeter.Mark(1)
|
||||||
|
|
@ -277,14 +269,14 @@ func (h *serverHandler) handleMsg(p *peer, wg *sync.WaitGroup) error {
|
||||||
}
|
}
|
||||||
var req struct {
|
var req struct {
|
||||||
ReqID uint64
|
ReqID uint64
|
||||||
Query getBlockHeadersData
|
Query protocol.GetBlockHeadersRequest
|
||||||
}
|
}
|
||||||
if err := msg.Decode(&req); err != nil {
|
if err := msg.Decode(&req); err != nil {
|
||||||
clientErrorMeter.Mark(1)
|
clientErrorMeter.Mark(1)
|
||||||
return errResp(ErrDecode, "%v: %v", msg, err)
|
return protocol.ErrResp(protocol.ErrDecode, "%v: %v", msg, err)
|
||||||
}
|
}
|
||||||
query := req.Query
|
query := req.Query
|
||||||
if accept(req.ReqID, query.Amount, MaxHeaderFetch) {
|
if accept(req.ReqID, query.Amount, protocol.MaxHeaderFetch) {
|
||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
go func() {
|
go func() {
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
|
|
@ -381,7 +373,7 @@ func (h *serverHandler) handleMsg(p *peer, wg *sync.WaitGroup) error {
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
case GetBlockBodiesMsg:
|
case protocol.GetBlockBodiesMsg:
|
||||||
p.Log().Trace("Received block bodies request")
|
p.Log().Trace("Received block bodies request")
|
||||||
if metrics.EnabledExpensive {
|
if metrics.EnabledExpensive {
|
||||||
miscInBodyPacketsMeter.Mark(1)
|
miscInBodyPacketsMeter.Mark(1)
|
||||||
|
|
@ -394,14 +386,14 @@ func (h *serverHandler) handleMsg(p *peer, wg *sync.WaitGroup) error {
|
||||||
}
|
}
|
||||||
if err := msg.Decode(&req); err != nil {
|
if err := msg.Decode(&req); err != nil {
|
||||||
clientErrorMeter.Mark(1)
|
clientErrorMeter.Mark(1)
|
||||||
return errResp(ErrDecode, "msg %v: %v", msg, err)
|
return protocol.ErrResp(protocol.ErrDecode, "msg %v: %v", msg, err)
|
||||||
}
|
}
|
||||||
var (
|
var (
|
||||||
bytes int
|
bytes int
|
||||||
bodies []rlp.RawValue
|
bodies []rlp.RawValue
|
||||||
)
|
)
|
||||||
reqCnt := len(req.Hashes)
|
reqCnt := len(req.Hashes)
|
||||||
if accept(req.ReqID, uint64(reqCnt), MaxBodyFetch) {
|
if accept(req.ReqID, uint64(reqCnt), protocol.MaxBodyFetch) {
|
||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
go func() {
|
go func() {
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
|
|
@ -430,7 +422,7 @@ func (h *serverHandler) handleMsg(p *peer, wg *sync.WaitGroup) error {
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
case GetCodeMsg:
|
case protocol.GetCodeMsg:
|
||||||
p.Log().Trace("Received code request")
|
p.Log().Trace("Received code request")
|
||||||
if metrics.EnabledExpensive {
|
if metrics.EnabledExpensive {
|
||||||
miscInCodePacketsMeter.Mark(1)
|
miscInCodePacketsMeter.Mark(1)
|
||||||
|
|
@ -439,18 +431,18 @@ func (h *serverHandler) handleMsg(p *peer, wg *sync.WaitGroup) error {
|
||||||
}
|
}
|
||||||
var req struct {
|
var req struct {
|
||||||
ReqID uint64
|
ReqID uint64
|
||||||
Reqs []CodeReq
|
Reqs []protocol.CodeRequest
|
||||||
}
|
}
|
||||||
if err := msg.Decode(&req); err != nil {
|
if err := msg.Decode(&req); err != nil {
|
||||||
clientErrorMeter.Mark(1)
|
clientErrorMeter.Mark(1)
|
||||||
return errResp(ErrDecode, "msg %v: %v", msg, err)
|
return protocol.ErrResp(protocol.ErrDecode, "msg %v: %v", msg, err)
|
||||||
}
|
}
|
||||||
var (
|
var (
|
||||||
bytes int
|
bytes int
|
||||||
data [][]byte
|
data [][]byte
|
||||||
)
|
)
|
||||||
reqCnt := len(req.Reqs)
|
reqCnt := len(req.Reqs)
|
||||||
if accept(req.ReqID, uint64(reqCnt), MaxCodeFetch) {
|
if accept(req.ReqID, uint64(reqCnt), protocol.MaxCodeFetch) {
|
||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
go func() {
|
go func() {
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
|
|
@ -460,9 +452,9 @@ func (h *serverHandler) handleMsg(p *peer, wg *sync.WaitGroup) error {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// Look up the root hash belonging to the request
|
// Look up the root hash belonging to the request
|
||||||
header := h.blockchain.GetHeaderByHash(request.BHash)
|
header := h.blockchain.GetHeaderByHash(request.BlockHash)
|
||||||
if header == nil {
|
if header == nil {
|
||||||
p.Log().Warn("Failed to retrieve associate header for code", "hash", request.BHash)
|
p.Log().Warn("Failed to retrieve associate header for code", "hash", request.BlockHash)
|
||||||
atomic.AddUint32(&p.invalidCount, 1)
|
atomic.AddUint32(&p.invalidCount, 1)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
@ -476,15 +468,15 @@ func (h *serverHandler) handleMsg(p *peer, wg *sync.WaitGroup) error {
|
||||||
}
|
}
|
||||||
triedb := h.blockchain.StateCache().TrieDB()
|
triedb := h.blockchain.StateCache().TrieDB()
|
||||||
|
|
||||||
account, err := h.getAccount(triedb, header.Root, common.BytesToHash(request.AccKey))
|
account, err := h.getAccount(triedb, header.Root, common.BytesToHash(request.Account))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
p.Log().Warn("Failed to retrieve account for code", "block", header.Number, "hash", header.Hash(), "account", common.BytesToHash(request.AccKey), "err", err)
|
p.Log().Warn("Failed to retrieve account for code", "block", header.Number, "hash", header.Hash(), "account", common.BytesToHash(request.Account), "err", err)
|
||||||
atomic.AddUint32(&p.invalidCount, 1)
|
atomic.AddUint32(&p.invalidCount, 1)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
code, err := triedb.Node(common.BytesToHash(account.CodeHash))
|
code, err := triedb.Node(common.BytesToHash(account.CodeHash))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
p.Log().Warn("Failed to retrieve account code", "block", header.Number, "hash", header.Hash(), "account", common.BytesToHash(request.AccKey), "codehash", common.BytesToHash(account.CodeHash), "err", err)
|
p.Log().Warn("Failed to retrieve account code", "block", header.Number, "hash", header.Hash(), "account", common.BytesToHash(request.Account), "codehash", common.BytesToHash(account.CodeHash), "err", err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
// Accumulate the code and abort if enough data was retrieved
|
// Accumulate the code and abort if enough data was retrieved
|
||||||
|
|
@ -502,7 +494,7 @@ func (h *serverHandler) handleMsg(p *peer, wg *sync.WaitGroup) error {
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
case GetReceiptsMsg:
|
case protocol.GetReceiptsMsg:
|
||||||
p.Log().Trace("Received receipts request")
|
p.Log().Trace("Received receipts request")
|
||||||
if metrics.EnabledExpensive {
|
if metrics.EnabledExpensive {
|
||||||
miscInReceiptPacketsMeter.Mark(1)
|
miscInReceiptPacketsMeter.Mark(1)
|
||||||
|
|
@ -515,14 +507,14 @@ func (h *serverHandler) handleMsg(p *peer, wg *sync.WaitGroup) error {
|
||||||
}
|
}
|
||||||
if err := msg.Decode(&req); err != nil {
|
if err := msg.Decode(&req); err != nil {
|
||||||
clientErrorMeter.Mark(1)
|
clientErrorMeter.Mark(1)
|
||||||
return errResp(ErrDecode, "msg %v: %v", msg, err)
|
return protocol.ErrResp(protocol.ErrDecode, "msg %v: %v", msg, err)
|
||||||
}
|
}
|
||||||
var (
|
var (
|
||||||
bytes int
|
bytes int
|
||||||
receipts []rlp.RawValue
|
receipts []rlp.RawValue
|
||||||
)
|
)
|
||||||
reqCnt := len(req.Hashes)
|
reqCnt := len(req.Hashes)
|
||||||
if accept(req.ReqID, uint64(reqCnt), MaxReceiptFetch) {
|
if accept(req.ReqID, uint64(reqCnt), protocol.MaxReceiptFetch) {
|
||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
go func() {
|
go func() {
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
|
|
@ -559,7 +551,7 @@ func (h *serverHandler) handleMsg(p *peer, wg *sync.WaitGroup) error {
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
case GetProofsV2Msg:
|
case protocol.GetProofsV2Msg:
|
||||||
p.Log().Trace("Received les/2 proofs request")
|
p.Log().Trace("Received les/2 proofs request")
|
||||||
if metrics.EnabledExpensive {
|
if metrics.EnabledExpensive {
|
||||||
miscInTrieProofPacketsMeter.Mark(1)
|
miscInTrieProofPacketsMeter.Mark(1)
|
||||||
|
|
@ -568,11 +560,11 @@ func (h *serverHandler) handleMsg(p *peer, wg *sync.WaitGroup) error {
|
||||||
}
|
}
|
||||||
var req struct {
|
var req struct {
|
||||||
ReqID uint64
|
ReqID uint64
|
||||||
Reqs []ProofReq
|
Reqs []protocol.TrieProofRequest
|
||||||
}
|
}
|
||||||
if err := msg.Decode(&req); err != nil {
|
if err := msg.Decode(&req); err != nil {
|
||||||
clientErrorMeter.Mark(1)
|
clientErrorMeter.Mark(1)
|
||||||
return errResp(ErrDecode, "msg %v: %v", msg, err)
|
return protocol.ErrResp(protocol.ErrDecode, "msg %v: %v", msg, err)
|
||||||
}
|
}
|
||||||
// Gather state data until the fetch or network limits is reached
|
// Gather state data until the fetch or network limits is reached
|
||||||
var (
|
var (
|
||||||
|
|
@ -580,7 +572,7 @@ func (h *serverHandler) handleMsg(p *peer, wg *sync.WaitGroup) error {
|
||||||
root common.Hash
|
root common.Hash
|
||||||
)
|
)
|
||||||
reqCnt := len(req.Reqs)
|
reqCnt := len(req.Reqs)
|
||||||
if accept(req.ReqID, uint64(reqCnt), MaxProofsFetch) {
|
if accept(req.ReqID, uint64(reqCnt), protocol.MaxProofsFetch) {
|
||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
go func() {
|
go func() {
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
|
|
@ -596,11 +588,11 @@ func (h *serverHandler) handleMsg(p *peer, wg *sync.WaitGroup) error {
|
||||||
header *types.Header
|
header *types.Header
|
||||||
trie state.Trie
|
trie state.Trie
|
||||||
)
|
)
|
||||||
if request.BHash != lastBHash {
|
if request.BlockHash != lastBHash {
|
||||||
root, lastBHash = common.Hash{}, request.BHash
|
root, lastBHash = common.Hash{}, request.BlockHash
|
||||||
|
|
||||||
if header = h.blockchain.GetHeaderByHash(request.BHash); header == nil {
|
if header = h.blockchain.GetHeaderByHash(request.BlockHash); header == nil {
|
||||||
p.Log().Warn("Failed to retrieve header for proof", "hash", request.BHash)
|
p.Log().Warn("Failed to retrieve header for proof", "hash", request.BlockHash)
|
||||||
atomic.AddUint32(&p.invalidCount, 1)
|
atomic.AddUint32(&p.invalidCount, 1)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
@ -622,7 +614,7 @@ func (h *serverHandler) handleMsg(p *peer, wg *sync.WaitGroup) error {
|
||||||
// Open the account or storage trie for the request
|
// Open the account or storage trie for the request
|
||||||
statedb := h.blockchain.StateCache()
|
statedb := h.blockchain.StateCache()
|
||||||
|
|
||||||
switch len(request.AccKey) {
|
switch len(request.Account) {
|
||||||
case 0:
|
case 0:
|
||||||
// No account key specified, open an account trie
|
// No account key specified, open an account trie
|
||||||
trie, err = statedb.OpenTrie(root)
|
trie, err = statedb.OpenTrie(root)
|
||||||
|
|
@ -632,15 +624,15 @@ func (h *serverHandler) handleMsg(p *peer, wg *sync.WaitGroup) error {
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
// Account key specified, open a storage trie
|
// Account key specified, open a storage trie
|
||||||
account, err := h.getAccount(statedb.TrieDB(), root, common.BytesToHash(request.AccKey))
|
account, err := h.getAccount(statedb.TrieDB(), root, common.BytesToHash(request.Account))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
p.Log().Warn("Failed to retrieve account for proof", "block", header.Number, "hash", header.Hash(), "account", common.BytesToHash(request.AccKey), "err", err)
|
p.Log().Warn("Failed to retrieve account for proof", "block", header.Number, "hash", header.Hash(), "account", common.BytesToHash(request.Account), "err", err)
|
||||||
atomic.AddUint32(&p.invalidCount, 1)
|
atomic.AddUint32(&p.invalidCount, 1)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
trie, err = statedb.OpenStorageTrie(common.BytesToHash(request.AccKey), account.Root)
|
trie, err = statedb.OpenStorageTrie(common.BytesToHash(request.Account), account.Root)
|
||||||
if trie == nil || err != nil {
|
if trie == nil || err != nil {
|
||||||
p.Log().Warn("Failed to open storage trie for proof", "block", header.Number, "hash", header.Hash(), "account", common.BytesToHash(request.AccKey), "root", account.Root, "err", err)
|
p.Log().Warn("Failed to open storage trie for proof", "block", header.Number, "hash", header.Hash(), "account", common.BytesToHash(request.Account), "root", account.Root, "err", err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -662,7 +654,7 @@ func (h *serverHandler) handleMsg(p *peer, wg *sync.WaitGroup) error {
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
case GetHelperTrieProofsMsg:
|
case protocol.GetHelperTrieProofsMsg:
|
||||||
p.Log().Trace("Received helper trie proof request")
|
p.Log().Trace("Received helper trie proof request")
|
||||||
if metrics.EnabledExpensive {
|
if metrics.EnabledExpensive {
|
||||||
miscInHelperTriePacketsMeter.Mark(1)
|
miscInHelperTriePacketsMeter.Mark(1)
|
||||||
|
|
@ -671,11 +663,11 @@ func (h *serverHandler) handleMsg(p *peer, wg *sync.WaitGroup) error {
|
||||||
}
|
}
|
||||||
var req struct {
|
var req struct {
|
||||||
ReqID uint64
|
ReqID uint64
|
||||||
Reqs []HelperTrieReq
|
Reqs []protocol.HelperTrieRequest
|
||||||
}
|
}
|
||||||
if err := msg.Decode(&req); err != nil {
|
if err := msg.Decode(&req); err != nil {
|
||||||
clientErrorMeter.Mark(1)
|
clientErrorMeter.Mark(1)
|
||||||
return errResp(ErrDecode, "msg %v: %v", msg, err)
|
return protocol.ErrResp(protocol.ErrDecode, "msg %v: %v", msg, err)
|
||||||
}
|
}
|
||||||
// Gather state data until the fetch or network limits is reached
|
// Gather state data until the fetch or network limits is reached
|
||||||
var (
|
var (
|
||||||
|
|
@ -683,7 +675,7 @@ func (h *serverHandler) handleMsg(p *peer, wg *sync.WaitGroup) error {
|
||||||
auxData [][]byte
|
auxData [][]byte
|
||||||
)
|
)
|
||||||
reqCnt := len(req.Reqs)
|
reqCnt := len(req.Reqs)
|
||||||
if accept(req.ReqID, uint64(reqCnt), MaxHelperTrieProofsFetch) {
|
if accept(req.ReqID, uint64(reqCnt), protocol.MaxHelperTrieProofsFetch) {
|
||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
go func() {
|
go func() {
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
|
|
@ -699,15 +691,15 @@ func (h *serverHandler) handleMsg(p *peer, wg *sync.WaitGroup) error {
|
||||||
sendResponse(req.ReqID, 0, nil, task.servingTime)
|
sendResponse(req.ReqID, 0, nil, task.servingTime)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if auxTrie == nil || request.Type != lastType || request.TrieIdx != lastIdx {
|
if auxTrie == nil || request.Type != lastType || request.TrieIndex != lastIdx {
|
||||||
auxTrie, lastType, lastIdx = nil, request.Type, request.TrieIdx
|
auxTrie, lastType, lastIdx = nil, request.Type, request.TrieIndex
|
||||||
|
|
||||||
var prefix string
|
var prefix string
|
||||||
if root, prefix = h.getHelperTrie(request.Type, request.TrieIdx); root != (common.Hash{}) {
|
if root, prefix = h.getHelperTrie(request.Type, request.TrieIndex); root != (common.Hash{}) {
|
||||||
auxTrie, _ = trie.New(root, trie.NewDatabase(rawdb.NewTable(h.chainDb, prefix)))
|
auxTrie, _ = trie.New(root, trie.NewDatabase(rawdb.NewTable(h.chainDb, prefix)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if request.AuxReq == auxRoot {
|
if request.AuxType == protocol.AuxRoot {
|
||||||
var data []byte
|
var data []byte
|
||||||
if root != (common.Hash{}) {
|
if root != (common.Hash{}) {
|
||||||
data = root[:]
|
data = root[:]
|
||||||
|
|
@ -718,7 +710,7 @@ func (h *serverHandler) handleMsg(p *peer, wg *sync.WaitGroup) error {
|
||||||
if auxTrie != nil {
|
if auxTrie != nil {
|
||||||
auxTrie.Prove(request.Key, request.FromLevel, nodes)
|
auxTrie.Prove(request.Key, request.FromLevel, nodes)
|
||||||
}
|
}
|
||||||
if request.AuxReq != 0 {
|
if request.AuxType != 0 {
|
||||||
data := h.getAuxiliaryHeaders(request)
|
data := h.getAuxiliaryHeaders(request)
|
||||||
auxData = append(auxData, data)
|
auxData = append(auxData, data)
|
||||||
auxBytes += len(data)
|
auxBytes += len(data)
|
||||||
|
|
@ -728,7 +720,7 @@ func (h *serverHandler) handleMsg(p *peer, wg *sync.WaitGroup) error {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
reply := p.ReplyHelperTrieProofs(req.ReqID, HelperTrieResps{Proofs: nodes.NodeList(), AuxData: auxData})
|
reply := p.ReplyHelperTrieProofs(req.ReqID, protocol.HelperTrieResponse{Proofs: nodes.NodeList(), AuxData: auxData})
|
||||||
sendResponse(req.ReqID, uint64(reqCnt), reply, task.done())
|
sendResponse(req.ReqID, uint64(reqCnt), reply, task.done())
|
||||||
if metrics.EnabledExpensive {
|
if metrics.EnabledExpensive {
|
||||||
miscOutHelperTriePacketsMeter.Mark(1)
|
miscOutHelperTriePacketsMeter.Mark(1)
|
||||||
|
|
@ -737,7 +729,7 @@ func (h *serverHandler) handleMsg(p *peer, wg *sync.WaitGroup) error {
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
case SendTxV2Msg:
|
case protocol.SendTxV2Msg:
|
||||||
p.Log().Trace("Received new transactions")
|
p.Log().Trace("Received new transactions")
|
||||||
if metrics.EnabledExpensive {
|
if metrics.EnabledExpensive {
|
||||||
miscInTxsPacketsMeter.Mark(1)
|
miscInTxsPacketsMeter.Mark(1)
|
||||||
|
|
@ -750,10 +742,10 @@ func (h *serverHandler) handleMsg(p *peer, wg *sync.WaitGroup) error {
|
||||||
}
|
}
|
||||||
if err := msg.Decode(&req); err != nil {
|
if err := msg.Decode(&req); err != nil {
|
||||||
clientErrorMeter.Mark(1)
|
clientErrorMeter.Mark(1)
|
||||||
return errResp(ErrDecode, "msg %v: %v", msg, err)
|
return protocol.ErrResp(protocol.ErrDecode, "msg %v: %v", msg, err)
|
||||||
}
|
}
|
||||||
reqCnt := len(req.Txs)
|
reqCnt := len(req.Txs)
|
||||||
if accept(req.ReqID, uint64(reqCnt), MaxTxSend) {
|
if accept(req.ReqID, uint64(reqCnt), protocol.MaxTxSend) {
|
||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
go func() {
|
go func() {
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
|
|
@ -786,7 +778,7 @@ func (h *serverHandler) handleMsg(p *peer, wg *sync.WaitGroup) error {
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
case GetTxStatusMsg:
|
case protocol.GetTxStatusMsg:
|
||||||
p.Log().Trace("Received transaction status query request")
|
p.Log().Trace("Received transaction status query request")
|
||||||
if metrics.EnabledExpensive {
|
if metrics.EnabledExpensive {
|
||||||
miscInTxStatusPacketsMeter.Mark(1)
|
miscInTxStatusPacketsMeter.Mark(1)
|
||||||
|
|
@ -799,10 +791,10 @@ func (h *serverHandler) handleMsg(p *peer, wg *sync.WaitGroup) error {
|
||||||
}
|
}
|
||||||
if err := msg.Decode(&req); err != nil {
|
if err := msg.Decode(&req); err != nil {
|
||||||
clientErrorMeter.Mark(1)
|
clientErrorMeter.Mark(1)
|
||||||
return errResp(ErrDecode, "msg %v: %v", msg, err)
|
return protocol.ErrResp(protocol.ErrDecode, "msg %v: %v", msg, err)
|
||||||
}
|
}
|
||||||
reqCnt := len(req.Hashes)
|
reqCnt := len(req.Hashes)
|
||||||
if accept(req.ReqID, uint64(reqCnt), MaxTxStatus) {
|
if accept(req.ReqID, uint64(reqCnt), protocol.MaxTxStatus) {
|
||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
go func() {
|
go func() {
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
|
|
@ -826,7 +818,7 @@ func (h *serverHandler) handleMsg(p *peer, wg *sync.WaitGroup) error {
|
||||||
default:
|
default:
|
||||||
p.Log().Trace("Received invalid message", "code", msg.Code)
|
p.Log().Trace("Received invalid message", "code", msg.Code)
|
||||||
clientErrorMeter.Mark(1)
|
clientErrorMeter.Mark(1)
|
||||||
return errResp(ErrInvalidMsgCode, "%v", msg.Code)
|
return protocol.ErrResp(protocol.ErrInvalidMsgCode, "%v", msg.Code)
|
||||||
}
|
}
|
||||||
// If the client has made too much invalid request(e.g. request a non-exist data),
|
// If the client has made too much invalid request(e.g. request a non-exist data),
|
||||||
// reject them to prevent SPAM attack.
|
// reject them to prevent SPAM attack.
|
||||||
|
|
@ -857,10 +849,10 @@ func (h *serverHandler) getAccount(triedb *trie.Database, root, hash common.Hash
|
||||||
// getHelperTrie returns the post-processed trie root for the given trie ID and section index
|
// getHelperTrie returns the post-processed trie root for the given trie ID and section index
|
||||||
func (h *serverHandler) getHelperTrie(typ uint, index uint64) (common.Hash, string) {
|
func (h *serverHandler) getHelperTrie(typ uint, index uint64) (common.Hash, string) {
|
||||||
switch typ {
|
switch typ {
|
||||||
case htCanonical:
|
case protocol.HelperTrieCHT:
|
||||||
sectionHead := rawdb.ReadCanonicalHash(h.chainDb, (index+1)*h.server.iConfig.ChtSize-1)
|
sectionHead := rawdb.ReadCanonicalHash(h.chainDb, (index+1)*h.server.iConfig.ChtSize-1)
|
||||||
return light.GetChtRoot(h.chainDb, index, sectionHead), light.ChtTablePrefix
|
return light.GetChtRoot(h.chainDb, index, sectionHead), light.ChtTablePrefix
|
||||||
case htBloomBits:
|
case protocol.HelperTrieBloomTrie:
|
||||||
sectionHead := rawdb.ReadCanonicalHash(h.chainDb, (index+1)*h.server.iConfig.BloomTrieSize-1)
|
sectionHead := rawdb.ReadCanonicalHash(h.chainDb, (index+1)*h.server.iConfig.BloomTrieSize-1)
|
||||||
return light.GetBloomTrieRoot(h.chainDb, index, sectionHead), light.BloomTrieTablePrefix
|
return light.GetBloomTrieRoot(h.chainDb, index, sectionHead), light.BloomTrieTablePrefix
|
||||||
}
|
}
|
||||||
|
|
@ -868,8 +860,8 @@ func (h *serverHandler) getHelperTrie(typ uint, index uint64) (common.Hash, stri
|
||||||
}
|
}
|
||||||
|
|
||||||
// getAuxiliaryHeaders returns requested auxiliary headers for the CHT request.
|
// getAuxiliaryHeaders returns requested auxiliary headers for the CHT request.
|
||||||
func (h *serverHandler) getAuxiliaryHeaders(req HelperTrieReq) []byte {
|
func (h *serverHandler) getAuxiliaryHeaders(req protocol.HelperTrieRequest) []byte {
|
||||||
if req.Type == htCanonical && req.AuxReq == auxHeader && len(req.Key) == 8 {
|
if req.Type == protocol.HelperTrieCHT && req.AuxType == protocol.AuxHeader && len(req.Key) == 8 {
|
||||||
blockNum := binary.BigEndian.Uint64(req.Key)
|
blockNum := binary.BigEndian.Uint64(req.Key)
|
||||||
hash := rawdb.ReadCanonicalHash(h.chainDb, blockNum)
|
hash := rawdb.ReadCanonicalHash(h.chainDb, blockNum)
|
||||||
return rawdb.ReadHeaderRLP(h.chainDb, hash, blockNum)
|
return rawdb.ReadHeaderRLP(h.chainDb, hash, blockNum)
|
||||||
|
|
@ -931,9 +923,16 @@ func (h *serverHandler) broadcastHeaders() {
|
||||||
log.Debug("Announcing block to peers", "number", number, "hash", hash, "td", td, "reorg", reorg)
|
log.Debug("Announcing block to peers", "number", number, "hash", hash, "td", td, "reorg", reorg)
|
||||||
var (
|
var (
|
||||||
signed bool
|
signed bool
|
||||||
signedAnnounce announceData
|
signedAnnounce protocol.Announcement
|
||||||
)
|
)
|
||||||
announce := announceData{Hash: hash, Number: number, Td: td, ReorgDepth: reorg}
|
announce := protocol.Announcement{
|
||||||
|
HeadHeader: protocol.HeadHeader{
|
||||||
|
Hash: hash,
|
||||||
|
Number: number,
|
||||||
|
Td: td,
|
||||||
|
},
|
||||||
|
ReorgDepth: reorg,
|
||||||
|
}
|
||||||
for _, p := range peers {
|
for _, p := range peers {
|
||||||
p := p
|
p := p
|
||||||
switch p.announceType {
|
switch p.announceType {
|
||||||
|
|
@ -942,7 +941,7 @@ func (h *serverHandler) broadcastHeaders() {
|
||||||
case announceTypeSigned:
|
case announceTypeSigned:
|
||||||
if !signed {
|
if !signed {
|
||||||
signedAnnounce = announce
|
signedAnnounce = announce
|
||||||
signedAnnounce.sign(h.server.privateKey)
|
signedAnnounce.Sign(h.server.privateKey)
|
||||||
signed = true
|
signed = true
|
||||||
}
|
}
|
||||||
p.queueSend(func() { p.SendAnnounce(signedAnnounce) })
|
p.queueSend(func() { p.SendAnnounce(signedAnnounce) })
|
||||||
|
|
|
||||||
|
|
@ -41,6 +41,7 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/event"
|
"github.com/ethereum/go-ethereum/event"
|
||||||
"github.com/ethereum/go-ethereum/les/checkpointoracle"
|
"github.com/ethereum/go-ethereum/les/checkpointoracle"
|
||||||
"github.com/ethereum/go-ethereum/les/flowcontrol"
|
"github.com/ethereum/go-ethereum/les/flowcontrol"
|
||||||
|
"github.com/ethereum/go-ethereum/les/protocol"
|
||||||
"github.com/ethereum/go-ethereum/light"
|
"github.com/ethereum/go-ethereum/light"
|
||||||
"github.com/ethereum/go-ethereum/p2p"
|
"github.com/ethereum/go-ethereum/p2p"
|
||||||
"github.com/ethereum/go-ethereum/p2p/enode"
|
"github.com/ethereum/go-ethereum/p2p/enode"
|
||||||
|
|
@ -200,7 +201,7 @@ func newTestClientHandler(backend *backends.SimulatedBackend, odr *LesOdr, index
|
||||||
client := &LightEthereum{
|
client := &LightEthereum{
|
||||||
lesCommons: lesCommons{
|
lesCommons: lesCommons{
|
||||||
genesis: genesis.Hash(),
|
genesis: genesis.Hash(),
|
||||||
config: ð.Config{LightPeers: 100, NetworkId: NetworkId},
|
config: ð.Config{LightPeers: 100, NetworkId: protocol.NetworkId},
|
||||||
chainConfig: params.AllEthashProtocolChanges,
|
chainConfig: params.AllEthashProtocolChanges,
|
||||||
iConfig: light.TestClientIndexerConfig,
|
iConfig: light.TestClientIndexerConfig,
|
||||||
chainDb: db,
|
chainDb: db,
|
||||||
|
|
@ -263,7 +264,7 @@ func newTestServerHandler(blocks int, indexers []*core.ChainIndexer, db ethdb.Da
|
||||||
server := &LesServer{
|
server := &LesServer{
|
||||||
lesCommons: lesCommons{
|
lesCommons: lesCommons{
|
||||||
genesis: genesis.Hash(),
|
genesis: genesis.Hash(),
|
||||||
config: ð.Config{LightPeers: 100, NetworkId: NetworkId},
|
config: ð.Config{LightPeers: 100, NetworkId: protocol.NetworkId},
|
||||||
chainConfig: params.AllEthashProtocolChanges,
|
chainConfig: params.AllEthashProtocolChanges,
|
||||||
iConfig: light.TestServerIndexerConfig,
|
iConfig: light.TestServerIndexerConfig,
|
||||||
chainDb: db,
|
chainDb: db,
|
||||||
|
|
@ -308,7 +309,7 @@ func newTestPeer(t *testing.T, name string, version int, handler *serverHandler,
|
||||||
// Generate a random id and create the peer
|
// Generate a random id and create the peer
|
||||||
var id enode.ID
|
var id enode.ID
|
||||||
rand.Read(id[:])
|
rand.Read(id[:])
|
||||||
peer := newPeer(version, NetworkId, false, p2p.NewPeer(id, name, nil), net)
|
peer := newPeer(version, protocol.NetworkId, false, p2p.NewPeer(id, name, nil), net)
|
||||||
|
|
||||||
// Start the peer on a new thread
|
// Start the peer on a new thread
|
||||||
errCh := make(chan error, 1)
|
errCh := make(chan error, 1)
|
||||||
|
|
@ -354,8 +355,8 @@ func newTestPeerPair(name string, version int, server *serverHandler, client *cl
|
||||||
var id enode.ID
|
var id enode.ID
|
||||||
rand.Read(id[:])
|
rand.Read(id[:])
|
||||||
|
|
||||||
peer1 := newPeer(version, NetworkId, false, p2p.NewPeer(id, name, nil), net)
|
peer1 := newPeer(version, protocol.NetworkId, false, p2p.NewPeer(id, name, nil), net)
|
||||||
peer2 := newPeer(version, NetworkId, false, p2p.NewPeer(id, name, nil), app)
|
peer2 := newPeer(version, protocol.NetworkId, false, p2p.NewPeer(id, name, nil), app)
|
||||||
|
|
||||||
// Start the peer on a new thread
|
// Start the peer on a new thread
|
||||||
errc1 := make(chan error, 1)
|
errc1 := make(chan error, 1)
|
||||||
|
|
@ -379,29 +380,29 @@ func newTestPeerPair(name string, version int, server *serverHandler, client *cl
|
||||||
|
|
||||||
// handshake simulates a trivial handshake that expects the same state from the
|
// handshake simulates a trivial handshake that expects the same state from the
|
||||||
// remote side as we are simulating locally.
|
// remote side as we are simulating locally.
|
||||||
func (p *testPeer) handshake(t *testing.T, td *big.Int, head common.Hash, headNum uint64, genesis common.Hash, costList RequestCostList) {
|
func (p *testPeer) handshake(t *testing.T, td *big.Int, head common.Hash, headNum uint64, genesis common.Hash, costList protocol.RequestCostList) {
|
||||||
var expList keyValueList
|
var expList protocol.KeyValueList
|
||||||
expList = expList.add("protocolVersion", uint64(p.peer.version))
|
expList = expList.Add("protocolVersion", uint64(p.peer.version))
|
||||||
expList = expList.add("networkId", uint64(NetworkId))
|
expList = expList.Add("networkId", uint64(protocol.NetworkId))
|
||||||
expList = expList.add("headTd", td)
|
expList = expList.Add("headTd", td)
|
||||||
expList = expList.add("headHash", head)
|
expList = expList.Add("headHash", head)
|
||||||
expList = expList.add("headNum", headNum)
|
expList = expList.Add("headNum", headNum)
|
||||||
expList = expList.add("genesisHash", genesis)
|
expList = expList.Add("genesisHash", genesis)
|
||||||
sendList := make(keyValueList, len(expList))
|
sendList := make(protocol.KeyValueList, len(expList))
|
||||||
copy(sendList, expList)
|
copy(sendList, expList)
|
||||||
expList = expList.add("serveHeaders", nil)
|
expList = expList.Add("serveHeaders", nil)
|
||||||
expList = expList.add("serveChainSince", uint64(0))
|
expList = expList.Add("serveChainSince", uint64(0))
|
||||||
expList = expList.add("serveStateSince", uint64(0))
|
expList = expList.Add("serveStateSince", uint64(0))
|
||||||
expList = expList.add("serveRecentState", uint64(core.TriesInMemory-4))
|
expList = expList.Add("serveRecentState", uint64(core.TriesInMemory-4))
|
||||||
expList = expList.add("txRelay", nil)
|
expList = expList.Add("txRelay", nil)
|
||||||
expList = expList.add("flowControl/BL", testBufLimit)
|
expList = expList.Add("flowControl/BL", testBufLimit)
|
||||||
expList = expList.add("flowControl/MRR", testBufRecharge)
|
expList = expList.Add("flowControl/MRR", testBufRecharge)
|
||||||
expList = expList.add("flowControl/MRC", costList)
|
expList = expList.Add("flowControl/MRC", costList)
|
||||||
|
|
||||||
if err := p2p.ExpectMsg(p.app, StatusMsg, expList); err != nil {
|
if err := p2p.ExpectMsg(p.app, protocol.StatusMsg, expList); err != nil {
|
||||||
t.Fatalf("status recv: %v", err)
|
t.Fatalf("status recv: %v", err)
|
||||||
}
|
}
|
||||||
if err := p2p.Send(p.app, StatusMsg, sendList); err != nil {
|
if err := p2p.Send(p.app, protocol.StatusMsg, sendList); err != nil {
|
||||||
t.Fatalf("status send: %v", err)
|
t.Fatalf("status send: %v", err)
|
||||||
}
|
}
|
||||||
p.peer.fcParams = flowcontrol.ServerParams{
|
p.peer.fcParams = flowcontrol.ServerParams{
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
|
"github.com/ethereum/go-ethereum/les/protocol"
|
||||||
"github.com/ethereum/go-ethereum/p2p"
|
"github.com/ethereum/go-ethereum/p2p"
|
||||||
"github.com/ethereum/go-ethereum/p2p/enode"
|
"github.com/ethereum/go-ethereum/p2p/enode"
|
||||||
)
|
)
|
||||||
|
|
@ -86,15 +87,15 @@ func testULCAnnounceThreshold(t *testing.T, protocol int) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func connect(server *serverHandler, serverId enode.ID, client *clientHandler, protocol int) (*peer, *peer, error) {
|
func connect(server *serverHandler, serverId enode.ID, client *clientHandler, p int) (*peer, *peer, error) {
|
||||||
// Create a message pipe to communicate through
|
// Create a message pipe to communicate through
|
||||||
app, net := p2p.MsgPipe()
|
app, net := p2p.MsgPipe()
|
||||||
|
|
||||||
var id enode.ID
|
var id enode.ID
|
||||||
rand.Read(id[:])
|
rand.Read(id[:])
|
||||||
|
|
||||||
peer1 := newPeer(protocol, NetworkId, true, p2p.NewPeer(serverId, "", nil), net) // Mark server as trusted
|
peer1 := newPeer(p, protocol.NetworkId, true, p2p.NewPeer(serverId, "", nil), net) // Mark server as trusted
|
||||||
peer2 := newPeer(protocol, NetworkId, false, p2p.NewPeer(id, "", nil), app)
|
peer2 := newPeer(p, protocol.NetworkId, false, p2p.NewPeer(id, "", nil), app)
|
||||||
|
|
||||||
// Start the peerLight on a new thread
|
// Start the peerLight on a new thread
|
||||||
errc1 := make(chan error, 1)
|
errc1 := make(chan error, 1)
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue