les: implement ultralight client (#16904)

For more information about this light client mode, read
https://hackmd.io/s/HJy7jjZpm
This commit is contained in:
b00ris
2019-01-24 14:18:26 +03:00
committed by Felix Lange
parent b8f9b3779f
commit 769657060e
23 changed files with 1288 additions and 179 deletions

View File

@ -33,6 +33,7 @@ import (
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/eth"
"github.com/ethereum/go-ethereum/eth/downloader"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/event"
@ -119,12 +120,29 @@ type ProtocolManager struct {
// wait group is used for graceful shutdowns during downloading
// and processing
wg *sync.WaitGroup
wg *sync.WaitGroup
ulc *ulc
}
// NewProtocolManager returns a new ethereum sub protocol manager. The Ethereum sub protocol manages peers capable
// with the ethereum network.
func NewProtocolManager(chainConfig *params.ChainConfig, indexerConfig *light.IndexerConfig, lightSync bool, networkId uint64, mux *event.TypeMux, engine consensus.Engine, peers *peerSet, blockchain BlockChain, txpool txPool, chainDb ethdb.Database, odr *LesOdr, txrelay *LesTxRelay, serverPool *serverPool, quitSync chan struct{}, wg *sync.WaitGroup) (*ProtocolManager, error) {
func NewProtocolManager(
chainConfig *params.ChainConfig,
indexerConfig *light.IndexerConfig,
lightSync bool,
networkId uint64,
mux *event.TypeMux,
engine consensus.Engine,
peers *peerSet,
blockchain BlockChain,
txpool txPool,
chainDb ethdb.Database,
odr *LesOdr,
txrelay *LesTxRelay,
serverPool *serverPool,
quitSync chan struct{},
wg *sync.WaitGroup,
ulcConfig *eth.ULCConfig) (*ProtocolManager, error) {
// Create the protocol manager with the base fields
manager := &ProtocolManager{
lightSync: lightSync,
@ -149,6 +167,10 @@ func NewProtocolManager(chainConfig *params.ChainConfig, indexerConfig *light.In
manager.reqDist = odr.retriever.dist
}
if ulcConfig != nil {
manager.ulc = newULC(ulcConfig)
}
removePeer := manager.removePeer
if disableClientRemovePeer {
removePeer = func(id string) {}
@ -234,7 +256,11 @@ func (pm *ProtocolManager) runPeer(version uint, p *p2p.Peer, rw p2p.MsgReadWrit
}
func (pm *ProtocolManager) newPeer(pv int, nv uint64, p *p2p.Peer, rw p2p.MsgReadWriter) *peer {
return newPeer(pv, nv, p, newMeteredMsgWriter(rw))
var isTrusted bool
if pm.isULCEnabled() {
isTrusted = pm.ulc.isTrusted(p.ID())
}
return newPeer(pv, nv, isTrusted, p, newMeteredMsgWriter(rw))
}
// handle is the callback invoked to manage the life cycle of a les peer. When
@ -276,6 +302,7 @@ func (pm *ProtocolManager) handle(p *peer) error {
if rw, ok := p.rw.(*meteredMsgReadWriter); ok {
rw.Init(p.version)
}
// Register the peer locally
if err := pm.peers.Register(p); err != nil {
p.Log().Error("Light Ethereum peer registration failed", "err", err)
@ -287,6 +314,7 @@ func (pm *ProtocolManager) handle(p *peer) error {
}
pm.removePeer(p.id)
}()
// Register the peer in the downloader. If the downloader considers it banned, we disconnect
if pm.lightSync {
p.lock.Lock()
@ -371,16 +399,15 @@ func (pm *ProtocolManager) handleMsg(p *peer) error {
// Block header query, collect the requested headers and reply
case AnnounceMsg:
p.Log().Trace("Received announce message")
if p.requestAnnounceType == announceTypeNone {
if p.announceType == announceTypeNone {
return errResp(ErrUnexpectedResponse, "")
}
var req announceData
if err := msg.Decode(&req); err != nil {
return errResp(ErrDecode, "%v: %v", msg, err)
}
if p.requestAnnounceType == announceTypeSigned {
if p.announceType == announceTypeSigned {
if err := req.checkSignature(p.ID()); err != nil {
p.Log().Trace("Invalid announcement signature", "err", err)
return err
@ -1175,6 +1202,14 @@ func (pm *ProtocolManager) txStatus(hashes []common.Hash) []txStatus {
return stats
}
// isULCEnabled returns true if we can use ULC
func (pm *ProtocolManager) isULCEnabled() bool {
if pm.ulc == nil || len(pm.ulc.trustedKeys) == 0 {
return false
}
return true
}
// downloaderPeerNotify implements peerSetNotify
type downloaderPeerNotify ProtocolManager