aboutsummaryrefslogtreecommitdiffstats
path: root/les/backend.go
diff options
context:
space:
mode:
authorFelföldi Zsolt <zsfelfoldi@gmail.com>2017-10-24 21:19:09 +0800
committerFelix Lange <fjl@users.noreply.github.com>2017-10-24 21:19:09 +0800
commitca376ead88a5a26626a90abdb62f4de7f6313822 (patch)
tree71d11e3b6cd40d2bf29033b7e23d30d04e086558 /les/backend.go
parent6d6a5a93370371a33fb815d7ae47b60c7021c86a (diff)
downloadgo-tangerine-ca376ead88a5a26626a90abdb62f4de7f6313822.tar
go-tangerine-ca376ead88a5a26626a90abdb62f4de7f6313822.tar.gz
go-tangerine-ca376ead88a5a26626a90abdb62f4de7f6313822.tar.bz2
go-tangerine-ca376ead88a5a26626a90abdb62f4de7f6313822.tar.lz
go-tangerine-ca376ead88a5a26626a90abdb62f4de7f6313822.tar.xz
go-tangerine-ca376ead88a5a26626a90abdb62f4de7f6313822.tar.zst
go-tangerine-ca376ead88a5a26626a90abdb62f4de7f6313822.zip
les, light: LES/2 protocol version (#14970)
This PR implements the new LES protocol version extensions: * new and more efficient Merkle proofs reply format (when replying to a multiple Merkle proofs request, we just send a single set of trie nodes containing all necessary nodes) * BBT (BloomBitsTrie) works similarly to the existing CHT and contains the bloombits search data to speed up log searches * GetTxStatusMsg returns the inclusion position or the pending/queued/unknown state of a transaction referenced by hash * an optional signature of new block data (number/hash/td) can be included in AnnounceMsg to provide an option for "very light clients" (mobile/embedded devices) to skip expensive Ethash check and accept multiple signatures of somewhat trusted servers (still a lot better than trusting a single server completely and retrieving everything through RPC). The new client mode is not implemented in this PR, just the protocol extension.
Diffstat (limited to 'les/backend.go')
-rw-r--r--les/backend.go79
1 files changed, 55 insertions, 24 deletions
diff --git a/les/backend.go b/les/backend.go
index 4c33417c0..3a68d13eb 100644
--- a/les/backend.go
+++ b/les/backend.go
@@ -27,6 +27,7 @@ import (
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/consensus"
"github.com/ethereum/go-ethereum/core"
+ "github.com/ethereum/go-ethereum/core/bloombits"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/eth"
"github.com/ethereum/go-ethereum/eth/downloader"
@@ -61,6 +62,9 @@ type LightEthereum struct {
// DB interfaces
chainDb ethdb.Database // Block chain database
+ bloomRequests chan chan *bloombits.Retrieval // Channel receiving bloom data retrieval requests
+ bloomIndexer, chtIndexer, bloomTrieIndexer *core.ChainIndexer
+
ApiBackend *LesApiBackend
eventMux *event.TypeMux
@@ -87,47 +91,61 @@ func New(ctx *node.ServiceContext, config *eth.Config) (*LightEthereum, error) {
peers := newPeerSet()
quitSync := make(chan struct{})
- eth := &LightEthereum{
- chainConfig: chainConfig,
- chainDb: chainDb,
- eventMux: ctx.EventMux,
- peers: peers,
- reqDist: newRequestDistributor(peers, quitSync),
- accountManager: ctx.AccountManager,
- engine: eth.CreateConsensusEngine(ctx, config, chainConfig, chainDb),
- shutdownChan: make(chan bool),
- networkId: config.NetworkId,
+ leth := &LightEthereum{
+ chainConfig: chainConfig,
+ chainDb: chainDb,
+ eventMux: ctx.EventMux,
+ peers: peers,
+ reqDist: newRequestDistributor(peers, quitSync),
+ accountManager: ctx.AccountManager,
+ engine: eth.CreateConsensusEngine(ctx, config, chainConfig, chainDb),
+ shutdownChan: make(chan bool),
+ networkId: config.NetworkId,
+ bloomRequests: make(chan chan *bloombits.Retrieval),
+ bloomIndexer: eth.NewBloomIndexer(chainDb, light.BloomTrieFrequency),
+ chtIndexer: light.NewChtIndexer(chainDb, true),
+ bloomTrieIndexer: light.NewBloomTrieIndexer(chainDb, true),
}
- eth.relay = NewLesTxRelay(peers, eth.reqDist)
- eth.serverPool = newServerPool(chainDb, quitSync, &eth.wg)
- eth.retriever = newRetrieveManager(peers, eth.reqDist, eth.serverPool)
- eth.odr = NewLesOdr(chainDb, eth.retriever)
- if eth.blockchain, err = light.NewLightChain(eth.odr, eth.chainConfig, eth.engine); err != nil {
+ leth.relay = NewLesTxRelay(peers, leth.reqDist)
+ leth.serverPool = newServerPool(chainDb, quitSync, &leth.wg)
+ leth.retriever = newRetrieveManager(peers, leth.reqDist, leth.serverPool)
+ leth.odr = NewLesOdr(chainDb, leth.chtIndexer, leth.bloomTrieIndexer, leth.bloomIndexer, leth.retriever)
+ if leth.blockchain, err = light.NewLightChain(leth.odr, leth.chainConfig, leth.engine); err != nil {
return nil, err
}
+ leth.bloomIndexer.Start(leth.blockchain)
// Rewind the chain in case of an incompatible config upgrade.
if compat, ok := genesisErr.(*params.ConfigCompatError); ok {
log.Warn("Rewinding chain to upgrade configuration", "err", compat)
- eth.blockchain.SetHead(compat.RewindTo)
+ leth.blockchain.SetHead(compat.RewindTo)
core.WriteChainConfig(chainDb, genesisHash, chainConfig)
}
- eth.txPool = light.NewTxPool(eth.chainConfig, eth.blockchain, eth.relay)
- if eth.protocolManager, err = NewProtocolManager(eth.chainConfig, true, config.NetworkId, eth.eventMux, eth.engine, eth.peers, eth.blockchain, nil, chainDb, eth.odr, eth.relay, quitSync, &eth.wg); err != nil {
+ leth.txPool = light.NewTxPool(leth.chainConfig, leth.blockchain, leth.relay)
+ if leth.protocolManager, err = NewProtocolManager(leth.chainConfig, true, ClientProtocolVersions, config.NetworkId, leth.eventMux, leth.engine, leth.peers, leth.blockchain, nil, chainDb, leth.odr, leth.relay, quitSync, &leth.wg); err != nil {
return nil, err
}
- eth.ApiBackend = &LesApiBackend{eth, nil}
+ leth.ApiBackend = &LesApiBackend{leth, nil}
gpoParams := config.GPO
if gpoParams.Default == nil {
gpoParams.Default = config.GasPrice
}
- eth.ApiBackend.gpo = gasprice.NewOracle(eth.ApiBackend, gpoParams)
- return eth, nil
+ leth.ApiBackend.gpo = gasprice.NewOracle(leth.ApiBackend, gpoParams)
+ return leth, nil
}
-func lesTopic(genesisHash common.Hash) discv5.Topic {
- return discv5.Topic("LES@" + common.Bytes2Hex(genesisHash.Bytes()[0:8]))
+func lesTopic(genesisHash common.Hash, protocolVersion uint) discv5.Topic {
+ var name string
+ switch protocolVersion {
+ case lpv1:
+ name = "LES"
+ case lpv2:
+ name = "LES2"
+ default:
+ panic(nil)
+ }
+ return discv5.Topic(name + common.Bytes2Hex(genesisHash.Bytes()[0:8]))
}
type LightDummyAPI struct{}
@@ -200,9 +218,13 @@ func (s *LightEthereum) Protocols() []p2p.Protocol {
// Start implements node.Service, starting all internal goroutines needed by the
// Ethereum protocol implementation.
func (s *LightEthereum) Start(srvr *p2p.Server) error {
+ s.startBloomHandlers()
log.Warn("Light client mode is an experimental feature")
s.netRPCService = ethapi.NewPublicNetAPI(srvr, s.networkId)
- s.serverPool.start(srvr, lesTopic(s.blockchain.Genesis().Hash()))
+ // search the topic belonging to the oldest supported protocol because
+ // servers always advertise all supported protocols
+ protocolVersion := ClientProtocolVersions[len(ClientProtocolVersions)-1]
+ s.serverPool.start(srvr, lesTopic(s.blockchain.Genesis().Hash(), protocolVersion))
s.protocolManager.Start()
return nil
}
@@ -211,6 +233,15 @@ func (s *LightEthereum) Start(srvr *p2p.Server) error {
// Ethereum protocol.
func (s *LightEthereum) Stop() error {
s.odr.Stop()
+ if s.bloomIndexer != nil {
+ s.bloomIndexer.Close()
+ }
+ if s.chtIndexer != nil {
+ s.chtIndexer.Close()
+ }
+ if s.bloomTrieIndexer != nil {
+ s.bloomTrieIndexer.Close()
+ }
s.blockchain.Stop()
s.protocolManager.Stop()
s.txPool.Stop()