mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-20 10:52:25 +00:00
Further LES cleanup
This commit is contained in:
parent
a7eaf583eb
commit
3712581a00
18 changed files with 319 additions and 184 deletions
|
|
@ -20,6 +20,7 @@ package utils
|
||||||
import (
|
import (
|
||||||
"crypto/ecdsa"
|
"crypto/ecdsa"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"math/big"
|
"math/big"
|
||||||
|
|
@ -1470,26 +1471,51 @@ func SetDashboardConfig(ctx *cli.Context, cfg *dashboard.Config) {
|
||||||
cfg.Refresh = ctx.GlobalDuration(DashboardRefreshFlag.Name)
|
cfg.Refresh = ctx.GlobalDuration(DashboardRefreshFlag.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
// RegisterEthService adds an Ethereum client to the stack.
|
// RegisterLesClientService adds a Light Client service to the stack if the config permits
|
||||||
func RegisterEthService(stack *node.Node, cfg *eth.Config) {
|
func RegisterLesClientService(stack *node.Node, cfg *eth.Config) {
|
||||||
var err error
|
|
||||||
|
//if the light client is requested
|
||||||
if cfg.SyncMode == downloader.LightSync {
|
if cfg.SyncMode == downloader.LightSync {
|
||||||
err = stack.Register(func(ctx *node.ServiceContext) (node.Service, error) {
|
//register a light client
|
||||||
|
if err := stack.Register(func(ctx *node.ServiceContext) (node.Service, error) {
|
||||||
return les.New(ctx, cfg)
|
return les.New(ctx, cfg)
|
||||||
})
|
}); err != nil {
|
||||||
} else {
|
Fatalf("Failed to register the Light Client service: %v", err)
|
||||||
err = stack.Register(func(ctx *node.ServiceContext) (node.Service, error) {
|
|
||||||
fullNode, err := eth.New(ctx, cfg)
|
|
||||||
if fullNode != nil && cfg.LightServ > 0 {
|
|
||||||
ls, _ := les.NewLesServer(fullNode, cfg)
|
|
||||||
fullNode.AddLesServer(ls)
|
|
||||||
}
|
}
|
||||||
return fullNode, err
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
if err != nil {
|
}
|
||||||
|
|
||||||
|
// RegisterLesServerService adds a Light Server service to the stack if the config permits
|
||||||
|
func RegisterLesServerService(stack *node.Node, cfg *eth.Config) {
|
||||||
|
|
||||||
|
//if the light client is not requested and the light server is requested
|
||||||
|
if cfg.SyncMode != downloader.LightSync && cfg.LightServ > 0 {
|
||||||
|
//register a light server service
|
||||||
|
if err := stack.Register(func(ctx *node.ServiceContext) (node.Service, error) {
|
||||||
|
//check if the main Eth protocol service is running
|
||||||
|
var ethService *eth.Ethereum
|
||||||
|
if ctx.Service(ðService) != nil {
|
||||||
|
return nil, errors.New("Failed to start the Les Server service because Ethereum service is not running")
|
||||||
|
}
|
||||||
|
return les.NewLesServer(ethService, cfg)
|
||||||
|
}); err != nil {
|
||||||
|
Fatalf("Failed to register the Light Server service: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// RegisterEthService adds an Ethereum client to the stack if the config permits
|
||||||
|
func RegisterEthService(stack *node.Node, cfg *eth.Config) {
|
||||||
|
|
||||||
|
//if the light client is not requested
|
||||||
|
if cfg.SyncMode != downloader.LightSync {
|
||||||
|
//register a service for the Eth protocol
|
||||||
|
if err := stack.Register(func(ctx *node.ServiceContext) (node.Service, error) {
|
||||||
|
return eth.New(ctx, cfg)
|
||||||
|
}); err != nil {
|
||||||
Fatalf("Failed to register the Ethereum service: %v", err)
|
Fatalf("Failed to register the Ethereum service: %v", err)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// RegisterDashboardService adds a dashboard to the stack.
|
// RegisterDashboardService adds a dashboard to the stack.
|
||||||
|
|
|
||||||
|
|
@ -51,14 +51,6 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/rpc"
|
"github.com/ethereum/go-ethereum/rpc"
|
||||||
)
|
)
|
||||||
|
|
||||||
type LesServer interface {
|
|
||||||
Start(srvr *p2p.Server)
|
|
||||||
Stop()
|
|
||||||
APIs() []rpc.API
|
|
||||||
Protocols() []p2p.Protocol
|
|
||||||
SetBloomBitsIndexer(bbIndexer *core.ChainIndexer)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ethereum implements the Ethereum full node service.
|
// Ethereum implements the Ethereum full node service.
|
||||||
type Ethereum struct {
|
type Ethereum struct {
|
||||||
config *Config
|
config *Config
|
||||||
|
|
@ -70,7 +62,6 @@ type Ethereum struct {
|
||||||
txPool *core.TxPool
|
txPool *core.TxPool
|
||||||
blockchain *core.BlockChain
|
blockchain *core.BlockChain
|
||||||
protocolManager *ProtocolManager
|
protocolManager *ProtocolManager
|
||||||
lesServer LesServer
|
|
||||||
|
|
||||||
// DB interfaces
|
// DB interfaces
|
||||||
chainDb ethdb.Database // Block chain database
|
chainDb ethdb.Database // Block chain database
|
||||||
|
|
@ -94,11 +85,6 @@ type Ethereum struct {
|
||||||
lock sync.RWMutex // Protects the variadic fields (e.g. gas price and etherbase)
|
lock sync.RWMutex // Protects the variadic fields (e.g. gas price and etherbase)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Ethereum) AddLesServer(ls LesServer) {
|
|
||||||
s.lesServer = ls
|
|
||||||
ls.SetBloomBitsIndexer(s.bloomIndexer)
|
|
||||||
}
|
|
||||||
|
|
||||||
// New creates a new Ethereum object (including the
|
// New creates a new Ethereum object (including the
|
||||||
// initialisation of the common Ethereum object)
|
// initialisation of the common Ethereum object)
|
||||||
func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) {
|
func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) {
|
||||||
|
|
@ -256,15 +242,13 @@ func CreateConsensusEngine(ctx *node.ServiceContext, chainConfig *params.ChainCo
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// APIs return the collection of RPC services the ethereum package offers.
|
// APIs return the collection of RPC services the ethereum package offers.
|
||||||
// NOTE, some of these services probably need to be moved to somewhere else.
|
// NOTE, some of these services probably need to be moved to somewhere else.
|
||||||
func (s *Ethereum) APIs() []rpc.API {
|
func (s *Ethereum) APIs() []rpc.API {
|
||||||
apis := ethapi.GetAPIs(s.APIBackend)
|
apis := ethapi.GetAPIs(s.APIBackend)
|
||||||
|
|
||||||
// Append any APIs exposed explicitly by the les server
|
|
||||||
if s.lesServer != nil {
|
|
||||||
apis = append(apis, s.lesServer.APIs()...)
|
|
||||||
}
|
|
||||||
// Append any APIs exposed explicitly by the consensus engine
|
// Append any APIs exposed explicitly by the consensus engine
|
||||||
apis = append(apis, s.engine.APIs(s.BlockChain())...)
|
apis = append(apis, s.engine.APIs(s.BlockChain())...)
|
||||||
|
|
||||||
|
|
@ -316,6 +300,11 @@ func (s *Ethereum) APIs() []rpc.API {
|
||||||
},
|
},
|
||||||
}...)
|
}...)
|
||||||
}
|
}
|
||||||
|
// GetBloomIndexer returns the bloombits indexer, primarily
|
||||||
|
// so that the Les Server service can re-use it
|
||||||
|
func (s *Ethereum) GetBloomIndexer() *core.ChainIndexer {
|
||||||
|
return s.bloomIndexer
|
||||||
|
}
|
||||||
|
|
||||||
func (s *Ethereum) ResetWithGenesisBlock(gb *types.Block) {
|
func (s *Ethereum) ResetWithGenesisBlock(gb *types.Block) {
|
||||||
s.blockchain.ResetWithGenesisBlock(gb)
|
s.blockchain.ResetWithGenesisBlock(gb)
|
||||||
|
|
@ -485,10 +474,7 @@ func (s *Ethereum) Synced() bool { return atomic.LoadUint3
|
||||||
// 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 *Ethereum) Protocols() []p2p.Protocol {
|
func (s *Ethereum) Protocols() []p2p.Protocol {
|
||||||
if s.lesServer == nil {
|
|
||||||
return s.protocolManager.SubProtocols
|
return s.protocolManager.SubProtocols
|
||||||
}
|
|
||||||
return append(s.protocolManager.SubProtocols, s.lesServer.Protocols()...)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start implements node.Service, starting all internal goroutines needed by the
|
// Start implements node.Service, starting all internal goroutines needed by the
|
||||||
|
|
@ -508,11 +494,10 @@ func (s *Ethereum) Start(srvr *p2p.Server) error {
|
||||||
}
|
}
|
||||||
maxPeers -= s.config.LightPeers
|
maxPeers -= s.config.LightPeers
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start the networking layer and the light server if requested
|
// Start the networking layer and the light server if requested
|
||||||
s.protocolManager.Start(maxPeers)
|
s.protocolManager.Start(maxPeers)
|
||||||
if s.lesServer != nil {
|
|
||||||
s.lesServer.Start(srvr)
|
|
||||||
}
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -523,13 +508,9 @@ func (s *Ethereum) Stop() error {
|
||||||
s.blockchain.Stop()
|
s.blockchain.Stop()
|
||||||
s.engine.Close()
|
s.engine.Close()
|
||||||
s.protocolManager.Stop()
|
s.protocolManager.Stop()
|
||||||
if s.lesServer != nil {
|
|
||||||
s.lesServer.Stop()
|
|
||||||
}
|
|
||||||
s.txPool.Stop()
|
s.txPool.Stop()
|
||||||
s.miner.Stop()
|
s.miner.Stop()
|
||||||
s.eventMux.Stop()
|
s.eventMux.Stop()
|
||||||
|
|
||||||
s.chainDb.Close()
|
s.chainDb.Close()
|
||||||
close(s.shutdownChan)
|
close(s.shutdownChan)
|
||||||
return nil
|
return nil
|
||||||
|
|
|
||||||
8
go-ethereum.code-workspace
Normal file
8
go-ethereum.code-workspace
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
{
|
||||||
|
"folders": [
|
||||||
|
{
|
||||||
|
"path": "."
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"settings": {}
|
||||||
|
}
|
||||||
|
|
@ -29,8 +29,11 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
// ErrMinCap capacity too small
|
||||||
ErrMinCap = errors.New("capacity too small")
|
ErrMinCap = errors.New("capacity too small")
|
||||||
|
// ErrTotalCap total capacity exceeded
|
||||||
ErrTotalCap = errors.New("total capacity exceeded")
|
ErrTotalCap = errors.New("total capacity exceeded")
|
||||||
|
// ErrUnknownBenchmarkType unknown benchmark type
|
||||||
ErrUnknownBenchmarkType = errors.New("unknown benchmark type")
|
ErrUnknownBenchmarkType = errors.New("unknown benchmark type")
|
||||||
|
|
||||||
dropCapacityDelay = time.Second // delay applied to decreasing capacity changes
|
dropCapacityDelay = time.Second // delay applied to decreasing capacity changes
|
||||||
|
|
|
||||||
|
|
@ -39,37 +39,44 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/rpc"
|
"github.com/ethereum/go-ethereum/rpc"
|
||||||
)
|
)
|
||||||
|
|
||||||
type LesApiBackend struct {
|
// ClientBackend is a backend implementation for the light Client only
|
||||||
|
type ClientBackend struct {
|
||||||
extRPCEnabled bool
|
extRPCEnabled bool
|
||||||
eth *LightEthereum
|
eth *LightEthereum
|
||||||
gpo *gasprice.Oracle
|
gpo *gasprice.Oracle
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *LesApiBackend) ChainConfig() *params.ChainConfig {
|
// ChainConfig returns the LightEthereum service config
|
||||||
|
func (b *ClientBackend) ChainConfig() *params.ChainConfig {
|
||||||
return b.eth.chainConfig
|
return b.eth.chainConfig
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *LesApiBackend) CurrentBlock() *types.Block {
|
// CurrentBlock returns the LightEthereum service chain current header block
|
||||||
|
func (b *ClientBackend) CurrentBlock() *types.Block {
|
||||||
return types.NewBlockWithHeader(b.eth.BlockChain().CurrentHeader())
|
return types.NewBlockWithHeader(b.eth.BlockChain().CurrentHeader())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *LesApiBackend) SetHead(number uint64) {
|
// SetHead cancels the downloader and sets the head to a certain number
|
||||||
|
func (b *ClientBackend) SetHead(number uint64) {
|
||||||
b.eth.protocolManager.downloader.Cancel()
|
b.eth.protocolManager.downloader.Cancel()
|
||||||
b.eth.blockchain.SetHead(number)
|
b.eth.blockchain.SetHead(number)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *LesApiBackend) HeaderByNumber(ctx context.Context, blockNr rpc.BlockNumber) (*types.Header, error) {
|
// HeaderByNumber returns either the chain's current header or an on-demand-requested header, given a block number
|
||||||
|
func (b *ClientBackend) HeaderByNumber(ctx context.Context, blockNr rpc.BlockNumber) (*types.Header, error) {
|
||||||
if blockNr == rpc.LatestBlockNumber || blockNr == rpc.PendingBlockNumber {
|
if blockNr == rpc.LatestBlockNumber || blockNr == rpc.PendingBlockNumber {
|
||||||
return b.eth.blockchain.CurrentHeader(), nil
|
return b.eth.blockchain.CurrentHeader(), nil
|
||||||
}
|
}
|
||||||
return b.eth.blockchain.GetHeaderByNumberOdr(ctx, uint64(blockNr))
|
return b.eth.blockchain.GetHeaderByNumberOdr(ctx, uint64(blockNr))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *LesApiBackend) HeaderByHash(ctx context.Context, hash common.Hash) (*types.Header, error) {
|
// HeaderByHash returns a block header for the given block hash
|
||||||
|
func (b *ClientBackend) HeaderByHash(ctx context.Context, hash common.Hash) (*types.Header, error) {
|
||||||
return b.eth.blockchain.GetHeaderByHash(hash), nil
|
return b.eth.blockchain.GetHeaderByHash(hash), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *LesApiBackend) BlockByNumber(ctx context.Context, blockNr rpc.BlockNumber) (*types.Block, error) {
|
// BlockByNumber identifies a header by number and then returns the block with the corresponding block hash
|
||||||
|
func (b *ClientBackend) BlockByNumber(ctx context.Context, blockNr rpc.BlockNumber) (*types.Block, error) {
|
||||||
header, err := b.HeaderByNumber(ctx, blockNr)
|
header, err := b.HeaderByNumber(ctx, blockNr)
|
||||||
if header == nil || err != nil {
|
if header == nil || err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
@ -77,7 +84,8 @@ func (b *LesApiBackend) BlockByNumber(ctx context.Context, blockNr rpc.BlockNumb
|
||||||
return b.GetBlock(ctx, header.Hash())
|
return b.GetBlock(ctx, header.Hash())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *LesApiBackend) StateAndHeaderByNumber(ctx context.Context, blockNr rpc.BlockNumber) (*state.StateDB, *types.Header, error) {
|
// StateAndHeaderByNumber identifies a block header by the supplied number, then returns that header's associated state and the header itself
|
||||||
|
func (b *ClientBackend) StateAndHeaderByNumber(ctx context.Context, blockNr rpc.BlockNumber) (*state.StateDB, *types.Header, error) {
|
||||||
header, err := b.HeaderByNumber(ctx, blockNr)
|
header, err := b.HeaderByNumber(ctx, blockNr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
|
|
@ -88,123 +96,157 @@ func (b *LesApiBackend) StateAndHeaderByNumber(ctx context.Context, blockNr rpc.
|
||||||
return light.NewState(ctx, header, b.eth.odr), header, nil
|
return light.NewState(ctx, header, b.eth.odr), header, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *LesApiBackend) GetBlock(ctx context.Context, blockHash common.Hash) (*types.Block, error) {
|
// GetBlock returns a block identified by block hash
|
||||||
|
func (b *ClientBackend) GetBlock(ctx context.Context, blockHash common.Hash) (*types.Block, error) {
|
||||||
return b.eth.blockchain.GetBlockByHash(ctx, blockHash)
|
return b.eth.blockchain.GetBlockByHash(ctx, blockHash)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *LesApiBackend) GetReceipts(ctx context.Context, hash common.Hash) (types.Receipts, error) {
|
// GetReceipts returns a set of receipts for a block, identified by the supplied hash
|
||||||
|
func (b *ClientBackend) GetReceipts(ctx context.Context, hash common.Hash) (types.Receipts, error) {
|
||||||
if number := rawdb.ReadHeaderNumber(b.eth.chainDb, hash); number != nil {
|
if number := rawdb.ReadHeaderNumber(b.eth.chainDb, hash); number != nil {
|
||||||
return light.GetBlockReceipts(ctx, b.eth.odr, hash, *number)
|
return light.GetBlockReceipts(ctx, b.eth.odr, hash, *number)
|
||||||
}
|
}
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *LesApiBackend) GetLogs(ctx context.Context, hash common.Hash) ([][]*types.Log, error) {
|
// GetLogs identifies the block header number given the supplied hash and then returns the block logs
|
||||||
|
func (b *ClientBackend) GetLogs(ctx context.Context, hash common.Hash) ([][]*types.Log, error) {
|
||||||
if number := rawdb.ReadHeaderNumber(b.eth.chainDb, hash); number != nil {
|
if number := rawdb.ReadHeaderNumber(b.eth.chainDb, hash); number != nil {
|
||||||
return light.GetBlockLogs(ctx, b.eth.odr, hash, *number)
|
return light.GetBlockLogs(ctx, b.eth.odr, hash, *number)
|
||||||
}
|
}
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *LesApiBackend) GetTd(hash common.Hash) *big.Int {
|
// GetTd retrieves a block's total difficulty in the canonical chain by hash
|
||||||
|
func (b *ClientBackend) GetTd(hash common.Hash) *big.Int {
|
||||||
return b.eth.blockchain.GetTdByHash(hash)
|
return b.eth.blockchain.GetTdByHash(hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *LesApiBackend) GetEVM(ctx context.Context, msg core.Message, state *state.StateDB, header *types.Header) (*vm.EVM, func() error, error) {
|
// GetEVM creates an EVM initialised with an account and balance from the supplied message
|
||||||
|
func (b *ClientBackend) GetEVM(ctx context.Context, msg core.Message, state *state.StateDB, header *types.Header) (*vm.EVM, func() error, error) {
|
||||||
state.SetBalance(msg.From(), math.MaxBig256)
|
state.SetBalance(msg.From(), math.MaxBig256)
|
||||||
context := core.NewEVMContext(msg, header, b.eth.blockchain, nil)
|
context := core.NewEVMContext(msg, header, b.eth.blockchain, nil)
|
||||||
return vm.NewEVM(context, state, b.eth.chainConfig, vm.Config{}), state.Error, nil
|
return vm.NewEVM(context, state, b.eth.chainConfig, vm.Config{}), state.Error, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *LesApiBackend) SendTx(ctx context.Context, signedTx *types.Transaction) error {
|
// SendTx add the transaction to the local transaction pool
|
||||||
|
func (b *ClientBackend) SendTx(ctx context.Context, signedTx *types.Transaction) error {
|
||||||
return b.eth.txPool.Add(ctx, signedTx)
|
return b.eth.txPool.Add(ctx, signedTx)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *LesApiBackend) RemoveTx(txHash common.Hash) {
|
// RemoveTx removes a transaction from the local transaction pool
|
||||||
|
func (b *ClientBackend) RemoveTx(txHash common.Hash) {
|
||||||
b.eth.txPool.RemoveTx(txHash)
|
b.eth.txPool.RemoveTx(txHash)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *LesApiBackend) GetPoolTransactions() (types.Transactions, error) {
|
// GetPoolTransactions returns all currently processable transactions.
|
||||||
|
func (b *ClientBackend) GetPoolTransactions() (types.Transactions, error) {
|
||||||
return b.eth.txPool.GetTransactions()
|
return b.eth.txPool.GetTransactions()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *LesApiBackend) GetPoolTransaction(txHash common.Hash) *types.Transaction {
|
// GetPoolTransaction returns a transaction if it is contained in the pool and nil otherwise.
|
||||||
|
func (b *ClientBackend) GetPoolTransaction(txHash common.Hash) *types.Transaction {
|
||||||
return b.eth.txPool.GetTransaction(txHash)
|
return b.eth.txPool.GetTransaction(txHash)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *LesApiBackend) GetTransaction(ctx context.Context, txHash common.Hash) (*types.Transaction, common.Hash, uint64, uint64, error) {
|
// GetTransaction retrieves a canonical transaction by hash and also returns its position in the chain
|
||||||
|
func (b *ClientBackend) GetTransaction(ctx context.Context, txHash common.Hash) (*types.Transaction, common.Hash, uint64, uint64, error) {
|
||||||
return light.GetTransaction(ctx, b.eth.odr, txHash)
|
return light.GetTransaction(ctx, b.eth.odr, txHash)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *LesApiBackend) GetPoolNonce(ctx context.Context, addr common.Address) (uint64, error) {
|
// GetPoolNonce returns the "pending" nonce of a given address. It always queries
|
||||||
|
// the nonce belonging to the latest header too in order to detect if another
|
||||||
|
// client using the same key sent a transaction.
|
||||||
|
func (b *ClientBackend) GetPoolNonce(ctx context.Context, addr common.Address) (uint64, error) {
|
||||||
return b.eth.txPool.GetNonce(ctx, addr)
|
return b.eth.txPool.GetNonce(ctx, addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *LesApiBackend) Stats() (pending int, queued int) {
|
// Stats returns the number of currently pending (locally created) transactions
|
||||||
|
func (b *ClientBackend) Stats() (pending int, queued int) {
|
||||||
return b.eth.txPool.Stats(), 0
|
return b.eth.txPool.Stats(), 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *LesApiBackend) TxPoolContent() (map[common.Address]types.Transactions, map[common.Address]types.Transactions) {
|
// TxPoolContent retrieves the data content of the transaction pool, returning all the
|
||||||
|
// pending as well as queued transactions, grouped by account and nonce.
|
||||||
|
func (b *ClientBackend) TxPoolContent() (map[common.Address]types.Transactions, map[common.Address]types.Transactions) {
|
||||||
return b.eth.txPool.Content()
|
return b.eth.txPool.Content()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *LesApiBackend) SubscribeNewTxsEvent(ch chan<- core.NewTxsEvent) event.Subscription {
|
// SubscribeNewTxsEvent registers a subscription of core.NewTxsEvent and
|
||||||
|
// starts sending event to the given channel.
|
||||||
|
func (b *ClientBackend) SubscribeNewTxsEvent(ch chan<- core.NewTxsEvent) event.Subscription {
|
||||||
return b.eth.txPool.SubscribeNewTxsEvent(ch)
|
return b.eth.txPool.SubscribeNewTxsEvent(ch)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *LesApiBackend) SubscribeChainEvent(ch chan<- core.ChainEvent) event.Subscription {
|
// SubscribeChainEvent registers a subscription of ChainEvent.
|
||||||
|
func (b *ClientBackend) SubscribeChainEvent(ch chan<- core.ChainEvent) event.Subscription {
|
||||||
return b.eth.blockchain.SubscribeChainEvent(ch)
|
return b.eth.blockchain.SubscribeChainEvent(ch)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *LesApiBackend) SubscribeChainHeadEvent(ch chan<- core.ChainHeadEvent) event.Subscription {
|
// SubscribeChainHeadEvent registers a subscription of ChainHeadEvent.
|
||||||
|
func (b *ClientBackend) SubscribeChainHeadEvent(ch chan<- core.ChainHeadEvent) event.Subscription {
|
||||||
return b.eth.blockchain.SubscribeChainHeadEvent(ch)
|
return b.eth.blockchain.SubscribeChainHeadEvent(ch)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *LesApiBackend) SubscribeChainSideEvent(ch chan<- core.ChainSideEvent) event.Subscription {
|
// SubscribeChainSideEvent registers a subscription of ChainSideEvent.
|
||||||
|
func (b *ClientBackend) SubscribeChainSideEvent(ch chan<- core.ChainSideEvent) event.Subscription {
|
||||||
return b.eth.blockchain.SubscribeChainSideEvent(ch)
|
return b.eth.blockchain.SubscribeChainSideEvent(ch)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *LesApiBackend) SubscribeLogsEvent(ch chan<- []*types.Log) event.Subscription {
|
// SubscribeLogsEvent implements the interface of filters.Backend
|
||||||
|
// LightChain does not send logs events, so return an empty subscription.
|
||||||
|
func (b *ClientBackend) SubscribeLogsEvent(ch chan<- []*types.Log) event.Subscription {
|
||||||
return b.eth.blockchain.SubscribeLogsEvent(ch)
|
return b.eth.blockchain.SubscribeLogsEvent(ch)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *LesApiBackend) SubscribeRemovedLogsEvent(ch chan<- core.RemovedLogsEvent) event.Subscription {
|
// SubscribeRemovedLogsEvent implements the interface of filters.Backend
|
||||||
|
// LightChain does not send core.RemovedLogsEvent, so return an empty subscription.
|
||||||
|
func (b *ClientBackend) SubscribeRemovedLogsEvent(ch chan<- core.RemovedLogsEvent) event.Subscription {
|
||||||
return b.eth.blockchain.SubscribeRemovedLogsEvent(ch)
|
return b.eth.blockchain.SubscribeRemovedLogsEvent(ch)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *LesApiBackend) Downloader() *downloader.Downloader {
|
// Downloader returns the LightEthereum downloader
|
||||||
|
func (b *ClientBackend) Downloader() *downloader.Downloader {
|
||||||
return b.eth.Downloader()
|
return b.eth.Downloader()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *LesApiBackend) ProtocolVersion() int {
|
// ProtocolVersion return the Les version number offset by 10000
|
||||||
|
func (b *ClientBackend) ProtocolVersion() int {
|
||||||
return b.eth.LesVersion() + 10000
|
return b.eth.LesVersion() + 10000
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *LesApiBackend) SuggestPrice(ctx context.Context) (*big.Int, error) {
|
// SuggestPrice returns the gas price oracle price suggestion
|
||||||
|
func (b *ClientBackend) SuggestPrice(ctx context.Context) (*big.Int, error) {
|
||||||
return b.gpo.SuggestPrice(ctx)
|
return b.gpo.SuggestPrice(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *LesApiBackend) ChainDb() ethdb.Database {
|
// ChainDb returns the ClientBackend db representation
|
||||||
|
func (b *ClientBackend) ChainDb() ethdb.Database {
|
||||||
return b.eth.chainDb
|
return b.eth.chainDb
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *LesApiBackend) EventMux() *event.TypeMux {
|
// EventMux ...
|
||||||
|
func (b *ClientBackend) EventMux() *event.TypeMux {
|
||||||
return b.eth.eventMux
|
return b.eth.eventMux
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *LesApiBackend) AccountManager() *accounts.Manager {
|
// AccountManager returns an overarching account manager needed for signing transactions
|
||||||
|
func (b *ClientBackend) AccountManager() *accounts.Manager {
|
||||||
return b.eth.accountManager
|
return b.eth.accountManager
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *LesApiBackend) ExtRPCEnabled() bool {
|
// ExtRPCEnabled indicates if the external RPC API is enabled
|
||||||
|
func (b *ClientBackend) ExtRPCEnabled() bool {
|
||||||
return b.extRPCEnabled
|
return b.extRPCEnabled
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *LesApiBackend) RPCGasCap() *big.Int {
|
// RPCGasCap - return the global gas cap for eth_call over rpc (DoS protection)
|
||||||
|
func (b *ClientBackend) RPCGasCap() *big.Int {
|
||||||
return b.eth.config.RPCGasCap
|
return b.eth.config.RPCGasCap
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *LesApiBackend) BloomStatus() (uint64, uint64) {
|
// BloomStatus ..
|
||||||
|
func (b *ClientBackend) BloomStatus() (uint64, uint64) {
|
||||||
if b.eth.bloomIndexer == nil {
|
if b.eth.bloomIndexer == nil {
|
||||||
return 0, 0
|
return 0, 0
|
||||||
}
|
}
|
||||||
|
|
@ -212,7 +254,8 @@ func (b *LesApiBackend) BloomStatus() (uint64, uint64) {
|
||||||
return params.BloomBitsBlocksClient, sections
|
return params.BloomBitsBlocksClient, sections
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *LesApiBackend) ServiceFilter(ctx context.Context, session *bloombits.MatcherSession) {
|
// ServiceFilter ...
|
||||||
|
func (b *ClientBackend) ServiceFilter(ctx context.Context, session *bloombits.MatcherSession) {
|
||||||
for i := 0; i < bloomFilterThreads; i++ {
|
for i := 0; i < bloomFilterThreads; i++ {
|
||||||
go session.Multiplex(bloomRetrievalBatch, bloomRetrievalWait, b.eth.bloomRequests)
|
go session.Multiplex(bloomRetrievalBatch, bloomRetrievalWait, b.eth.bloomRequests)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -90,15 +90,15 @@ func testCapacityAPI(t *testing.T, clientCount int) {
|
||||||
}
|
}
|
||||||
server := servers[0]
|
server := servers[0]
|
||||||
|
|
||||||
clientRpcClients := make([]*rpc.Client, len(clients))
|
clientRPCClients := make([]*rpc.Client, len(clients))
|
||||||
|
|
||||||
serverRpcClient, err := server.Client()
|
serverRPCClient, err := server.Client()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to obtain rpc client: %v", err)
|
t.Fatalf("Failed to obtain rpc client: %v", err)
|
||||||
}
|
}
|
||||||
headNum, headHash := getHead(ctx, t, serverRpcClient)
|
headNum, headHash := getHead(ctx, t, serverRPCClient)
|
||||||
totalCap := getTotalCap(ctx, t, serverRpcClient)
|
totalCap := getTotalCap(ctx, t, serverRPCClient)
|
||||||
minCap := getMinCap(ctx, t, serverRpcClient)
|
minCap := getMinCap(ctx, t, serverRPCClient)
|
||||||
testCap := totalCap * 3 / 4
|
testCap := totalCap * 3 / 4
|
||||||
fmt.Printf("Server testCap: %d minCap: %d head number: %d head hash: %064x\n", testCap, minCap, headNum, headHash)
|
fmt.Printf("Server testCap: %d minCap: %d head number: %d head hash: %064x\n", testCap, minCap, headNum, headHash)
|
||||||
reqMinCap := uint64(float64(testCap) * minRelCap / (minRelCap + float64(len(clients)-1)))
|
reqMinCap := uint64(float64(testCap) * minRelCap / (minRelCap + float64(len(clients)-1)))
|
||||||
|
|
@ -107,18 +107,18 @@ func testCapacityAPI(t *testing.T, clientCount int) {
|
||||||
}
|
}
|
||||||
|
|
||||||
freeIdx := rand.Intn(len(clients))
|
freeIdx := rand.Intn(len(clients))
|
||||||
freeCap := getFreeCap(ctx, t, serverRpcClient)
|
freeCap := getFreeCap(ctx, t, serverRPCClient)
|
||||||
|
|
||||||
for i, client := range clients {
|
for i, client := range clients {
|
||||||
var err error
|
var err error
|
||||||
clientRpcClients[i], err = client.Client()
|
clientRPCClients[i], err = client.Client()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to obtain rpc client: %v", err)
|
t.Fatalf("Failed to obtain rpc client: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Println("connecting client", i)
|
fmt.Println("connecting client", i)
|
||||||
if i != freeIdx {
|
if i != freeIdx {
|
||||||
setCapacity(ctx, t, serverRpcClient, client.ID(), testCap/uint64(len(clients)))
|
setCapacity(ctx, t, serverRPCClient, client.ID(), testCap/uint64(len(clients)))
|
||||||
}
|
}
|
||||||
net.Connect(client.ID(), server.ID())
|
net.Connect(client.ID(), server.ID())
|
||||||
|
|
||||||
|
|
@ -128,7 +128,7 @@ func testCapacityAPI(t *testing.T, clientCount int) {
|
||||||
t.Fatalf("Timeout")
|
t.Fatalf("Timeout")
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
num, hash := getHead(ctx, t, clientRpcClients[i])
|
num, hash := getHead(ctx, t, clientRPCClients[i])
|
||||||
if num == headNum && hash == headHash {
|
if num == headNum && hash == headHash {
|
||||||
fmt.Println("client", i, "synced")
|
fmt.Println("client", i, "synced")
|
||||||
break
|
break
|
||||||
|
|
@ -140,9 +140,9 @@ func testCapacityAPI(t *testing.T, clientCount int) {
|
||||||
var wg sync.WaitGroup
|
var wg sync.WaitGroup
|
||||||
stop := make(chan struct{})
|
stop := make(chan struct{})
|
||||||
|
|
||||||
reqCount := make([]uint64, len(clientRpcClients))
|
reqCount := make([]uint64, len(clientRPCClients))
|
||||||
|
|
||||||
for i, c := range clientRpcClients {
|
for i, c := range clientRPCClients {
|
||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
i, c := i, c
|
i, c := i, c
|
||||||
go func() {
|
go func() {
|
||||||
|
|
@ -194,7 +194,7 @@ func testCapacityAPI(t *testing.T, clientCount int) {
|
||||||
|
|
||||||
weights := make([]float64, len(clients))
|
weights := make([]float64, len(clients))
|
||||||
for c := 0; c < 5; c++ {
|
for c := 0; c < 5; c++ {
|
||||||
setCapacity(ctx, t, serverRpcClient, clients[freeIdx].ID(), freeCap)
|
setCapacity(ctx, t, serverRPCClient, clients[freeIdx].ID(), freeCap)
|
||||||
freeIdx = rand.Intn(len(clients))
|
freeIdx = rand.Intn(len(clients))
|
||||||
var sum float64
|
var sum float64
|
||||||
for i := range clients {
|
for i := range clients {
|
||||||
|
|
@ -208,15 +208,15 @@ func testCapacityAPI(t *testing.T, clientCount int) {
|
||||||
for i, client := range clients {
|
for i, client := range clients {
|
||||||
weights[i] *= float64(testCap-freeCap-100) / sum
|
weights[i] *= float64(testCap-freeCap-100) / sum
|
||||||
capacity := uint64(weights[i])
|
capacity := uint64(weights[i])
|
||||||
if i != freeIdx && capacity < getCapacity(ctx, t, serverRpcClient, client.ID()) {
|
if i != freeIdx && capacity < getCapacity(ctx, t, serverRPCClient, client.ID()) {
|
||||||
setCapacity(ctx, t, serverRpcClient, client.ID(), capacity)
|
setCapacity(ctx, t, serverRPCClient, client.ID(), capacity)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
setCapacity(ctx, t, serverRpcClient, clients[freeIdx].ID(), 0)
|
setCapacity(ctx, t, serverRPCClient, clients[freeIdx].ID(), 0)
|
||||||
for i, client := range clients {
|
for i, client := range clients {
|
||||||
capacity := uint64(weights[i])
|
capacity := uint64(weights[i])
|
||||||
if i != freeIdx && capacity > getCapacity(ctx, t, serverRpcClient, client.ID()) {
|
if i != freeIdx && capacity > getCapacity(ctx, t, serverRPCClient, client.ID()) {
|
||||||
setCapacity(ctx, t, serverRpcClient, client.ID(), capacity)
|
setCapacity(ctx, t, serverRPCClient, client.ID(), capacity)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
weights[freeIdx] = float64(freeCap)
|
weights[freeIdx] = float64(freeCap)
|
||||||
|
|
@ -239,7 +239,7 @@ func testCapacityAPI(t *testing.T, clientCount int) {
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
|
|
||||||
totalCap = getTotalCap(ctx, t, serverRpcClient)
|
totalCap = getTotalCap(ctx, t, serverRPCClient)
|
||||||
if totalCap < testCap {
|
if totalCap < testCap {
|
||||||
fmt.Println("Total capacity underrun")
|
fmt.Println("Total capacity underrun")
|
||||||
close(stop)
|
close(stop)
|
||||||
|
|
@ -520,6 +520,6 @@ func newLesServerService(ctx *adapters.ServiceContext) (node.Service, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
ethereum.AddLesServer(server)
|
|
||||||
return ethereum, nil
|
return server, nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -46,6 +46,7 @@ import (
|
||||||
rpc "github.com/ethereum/go-ethereum/rpc"
|
rpc "github.com/ethereum/go-ethereum/rpc"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// LightEthereum is a light client service
|
||||||
type LightEthereum struct {
|
type LightEthereum struct {
|
||||||
lesCommons
|
lesCommons
|
||||||
|
|
||||||
|
|
@ -66,18 +67,19 @@ type LightEthereum struct {
|
||||||
bloomRequests chan chan *bloombits.Retrieval // Channel receiving bloom data retrieval requests
|
bloomRequests chan chan *bloombits.Retrieval // Channel receiving bloom data retrieval requests
|
||||||
bloomIndexer *core.ChainIndexer
|
bloomIndexer *core.ChainIndexer
|
||||||
|
|
||||||
ApiBackend *LesApiBackend
|
APIBackend *ClientBackend
|
||||||
|
|
||||||
eventMux *event.TypeMux
|
eventMux *event.TypeMux
|
||||||
engine consensus.Engine
|
engine consensus.Engine
|
||||||
accountManager *accounts.Manager
|
accountManager *accounts.Manager
|
||||||
|
|
||||||
networkId uint64
|
networkID uint64
|
||||||
netRPCService *ethapi.PublicNetAPI
|
netRPCService *ethapi.PublicNetAPI
|
||||||
|
|
||||||
wg sync.WaitGroup
|
wg sync.WaitGroup
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// New constructs a LightEthereum client
|
||||||
func New(ctx *node.ServiceContext, config *eth.Config) (*LightEthereum, error) {
|
func New(ctx *node.ServiceContext, config *eth.Config) (*LightEthereum, error) {
|
||||||
chainDb, err := ctx.OpenDatabase("lightchaindata", config.DatabaseCache, config.DatabaseHandles, "eth/db/chaindata/")
|
chainDb, err := ctx.OpenDatabase("lightchaindata", config.DatabaseCache, config.DatabaseHandles, "eth/db/chaindata/")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -105,7 +107,7 @@ func New(ctx *node.ServiceContext, config *eth.Config) (*LightEthereum, error) {
|
||||||
accountManager: ctx.AccountManager,
|
accountManager: ctx.AccountManager,
|
||||||
engine: eth.CreateConsensusEngine(ctx, chainConfig, &config.Ethash, nil, false, chainDb),
|
engine: eth.CreateConsensusEngine(ctx, chainConfig, &config.Ethash, nil, false, chainDb),
|
||||||
shutdownChan: make(chan bool),
|
shutdownChan: make(chan bool),
|
||||||
networkId: config.NetworkId,
|
networkID: config.NetworkId,
|
||||||
bloomRequests: make(chan chan *bloombits.Retrieval),
|
bloomRequests: make(chan chan *bloombits.Retrieval),
|
||||||
bloomIndexer: eth.NewBloomIndexer(chainDb, params.BloomBitsBlocksClient, params.HelperTrieConfirmations),
|
bloomIndexer: eth.NewBloomIndexer(chainDb, params.BloomBitsBlocksClient, params.HelperTrieConfirmations),
|
||||||
}
|
}
|
||||||
|
|
@ -167,13 +169,13 @@ func New(ctx *node.ServiceContext, config *eth.Config) (*LightEthereum, error) {
|
||||||
log.Warn("Ultra light client is enabled", "trustedNodes", len(leth.protocolManager.ulc.trustedKeys), "minTrustedFraction", leth.protocolManager.ulc.minTrustedFraction)
|
log.Warn("Ultra light client is enabled", "trustedNodes", len(leth.protocolManager.ulc.trustedKeys), "minTrustedFraction", leth.protocolManager.ulc.minTrustedFraction)
|
||||||
leth.blockchain.DisableCheckFreq()
|
leth.blockchain.DisableCheckFreq()
|
||||||
}
|
}
|
||||||
leth.ApiBackend = &LesApiBackend{ctx.ExtRPCEnabled(), leth, nil}
|
leth.APIBackend = &ClientBackend{ctx.ExtRPCEnabled(), leth, nil}
|
||||||
|
|
||||||
gpoParams := config.GPO
|
gpoParams := config.GPO
|
||||||
if gpoParams.Default == nil {
|
if gpoParams.Default == nil {
|
||||||
gpoParams.Default = config.Miner.GasPrice
|
gpoParams.Default = config.Miner.GasPrice
|
||||||
}
|
}
|
||||||
leth.ApiBackend.gpo = gasprice.NewOracle(leth.ApiBackend, gpoParams)
|
leth.APIBackend.gpo = gasprice.NewOracle(leth.APIBackend, gpoParams)
|
||||||
return leth, nil
|
return leth, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -188,6 +190,7 @@ func lesTopic(genesisHash common.Hash, protocolVersion uint) discv5.Topic {
|
||||||
return discv5.Topic(name + "@" + common.Bytes2Hex(genesisHash.Bytes()[0:8]))
|
return discv5.Topic(name + "@" + common.Bytes2Hex(genesisHash.Bytes()[0:8]))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// LightDummyAPI is a fake api that serves default values in the role of a light client
|
||||||
type LightDummyAPI struct{}
|
type LightDummyAPI struct{}
|
||||||
|
|
||||||
// Etherbase is the address that mining rewards will be send to
|
// Etherbase is the address that mining rewards will be send to
|
||||||
|
|
@ -213,7 +216,7 @@ func (s *LightDummyAPI) Mining() bool {
|
||||||
// APIs returns the collection of RPC services the ethereum package offers.
|
// APIs returns the collection of RPC services the ethereum package offers.
|
||||||
// NOTE, some of these services probably need to be moved to somewhere else.
|
// NOTE, some of these services probably need to be moved to somewhere else.
|
||||||
func (s *LightEthereum) APIs() []rpc.API {
|
func (s *LightEthereum) APIs() []rpc.API {
|
||||||
return append(ethapi.GetAPIs(s.ApiBackend), []rpc.API{
|
return append(ethapi.GetAPIs(s.APIBackend), []rpc.API{
|
||||||
{
|
{
|
||||||
Namespace: "eth",
|
Namespace: "eth",
|
||||||
Version: "1.0",
|
Version: "1.0",
|
||||||
|
|
@ -227,7 +230,7 @@ func (s *LightEthereum) APIs() []rpc.API {
|
||||||
}, {
|
}, {
|
||||||
Namespace: "eth",
|
Namespace: "eth",
|
||||||
Version: "1.0",
|
Version: "1.0",
|
||||||
Service: filters.NewPublicFilterAPI(s.ApiBackend, true),
|
Service: filters.NewPublicFilterAPI(s.APIBackend, true),
|
||||||
Public: true,
|
Public: true,
|
||||||
}, {
|
}, {
|
||||||
Namespace: "net",
|
Namespace: "net",
|
||||||
|
|
@ -238,15 +241,28 @@ func (s *LightEthereum) APIs() []rpc.API {
|
||||||
}...)
|
}...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ResetWithGenesisBlock purges the entire blockchain, restoring it to the
|
||||||
|
// specified genesis state.
|
||||||
func (s *LightEthereum) ResetWithGenesisBlock(gb *types.Block) {
|
func (s *LightEthereum) ResetWithGenesisBlock(gb *types.Block) {
|
||||||
s.blockchain.ResetWithGenesisBlock(gb)
|
s.blockchain.ResetWithGenesisBlock(gb)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// BlockChain returns the light client's blockchain
|
||||||
func (s *LightEthereum) BlockChain() *light.LightChain { return s.blockchain }
|
func (s *LightEthereum) BlockChain() *light.LightChain { return s.blockchain }
|
||||||
|
|
||||||
|
// TxPool the pool of locally created transactions
|
||||||
func (s *LightEthereum) TxPool() *light.TxPool { return s.txPool }
|
func (s *LightEthereum) TxPool() *light.TxPool { return s.txPool }
|
||||||
|
|
||||||
|
// Engine is the employed consensus engine
|
||||||
func (s *LightEthereum) Engine() consensus.Engine { return s.engine }
|
func (s *LightEthereum) Engine() consensus.Engine { return s.engine }
|
||||||
|
|
||||||
|
// LesVersion is the current version of Les used by this light client
|
||||||
func (s *LightEthereum) LesVersion() int { return int(ClientProtocolVersions[0]) }
|
func (s *LightEthereum) LesVersion() int { return int(ClientProtocolVersions[0]) }
|
||||||
|
|
||||||
|
// Downloader is the employed downloader
|
||||||
func (s *LightEthereum) Downloader() *downloader.Downloader { return s.protocolManager.downloader }
|
func (s *LightEthereum) Downloader() *downloader.Downloader { return s.protocolManager.downloader }
|
||||||
|
|
||||||
|
// EventMux is an event subscription notifier
|
||||||
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
|
||||||
|
|
@ -260,7 +276,7 @@ func (s *LightEthereum) Protocols() []p2p.Protocol {
|
||||||
func (s *LightEthereum) Start(srvr *p2p.Server) error {
|
func (s *LightEthereum) Start(srvr *p2p.Server) error {
|
||||||
log.Warn("Light client mode is an experimental feature")
|
log.Warn("Light client mode is an experimental feature")
|
||||||
s.startBloomHandlers(params.BloomBitsBlocksClient)
|
s.startBloomHandlers(params.BloomBitsBlocksClient)
|
||||||
s.netRPCService = ethapi.NewPublicNetAPI(srvr, s.networkId)
|
s.netRPCService = ethapi.NewPublicNetAPI(srvr, s.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 := AdvertiseProtocolVersions[0]
|
||||||
s.serverPool.start(srvr, lesTopic(s.blockchain.Genesis().Hash(), protocolVersion))
|
s.serverPool.start(srvr, lesTopic(s.blockchain.Genesis().Hash(), protocolVersion))
|
||||||
|
|
|
||||||
|
|
@ -74,9 +74,9 @@ func (b *benchmarkBlockHeaders) init(pm *ProtocolManager, count int) error {
|
||||||
func (b *benchmarkBlockHeaders) request(peer *peer, index int) error {
|
func (b *benchmarkBlockHeaders) request(peer *peer, index int) error {
|
||||||
if b.byHash {
|
if b.byHash {
|
||||||
return peer.RequestHeadersByHash(0, 0, b.hashes[index], b.amount, b.skip, b.reverse)
|
return peer.RequestHeadersByHash(0, 0, b.hashes[index], b.amount, b.skip, b.reverse)
|
||||||
} else {
|
|
||||||
return peer.RequestHeadersByNumber(0, 0, uint64(b.offset+rand.Int63n(b.randMax)), b.amount, b.skip, b.reverse)
|
|
||||||
}
|
}
|
||||||
|
return peer.RequestHeadersByNumber(0, 0, uint64(b.offset+rand.Int63n(b.randMax)), b.amount, b.skip, b.reverse)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// benchmarkBodiesOrReceipts implements requestBenchmark
|
// benchmarkBodiesOrReceipts implements requestBenchmark
|
||||||
|
|
@ -97,9 +97,9 @@ func (b *benchmarkBodiesOrReceipts) init(pm *ProtocolManager, count int) error {
|
||||||
func (b *benchmarkBodiesOrReceipts) request(peer *peer, index int) error {
|
func (b *benchmarkBodiesOrReceipts) request(peer *peer, index int) error {
|
||||||
if b.receipts {
|
if b.receipts {
|
||||||
return peer.RequestReceipts(0, 0, []common.Hash{b.hashes[index]})
|
return peer.RequestReceipts(0, 0, []common.Hash{b.hashes[index]})
|
||||||
} else {
|
|
||||||
return peer.RequestBodies(0, 0, []common.Hash{b.hashes[index]})
|
|
||||||
}
|
}
|
||||||
|
return peer.RequestBodies(0, 0, []common.Hash{b.hashes[index]})
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// benchmarkProofsOrCode implements requestBenchmark
|
// benchmarkProofsOrCode implements requestBenchmark
|
||||||
|
|
@ -118,9 +118,9 @@ func (b *benchmarkProofsOrCode) request(peer *peer, index int) error {
|
||||||
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, []CodeReq{{BHash: b.headHash, AccKey: key}})
|
||||||
} else {
|
|
||||||
return peer.RequestProofs(0, 0, []ProofReq{{BHash: b.headHash, Key: key}})
|
|
||||||
}
|
}
|
||||||
|
return peer.RequestProofs(0, 0, []ProofReq{{BHash: b.headHash, Key: key}})
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// benchmarkHelperTrie implements requestBenchmark
|
// benchmarkHelperTrie implements requestBenchmark
|
||||||
|
|
@ -281,8 +281,8 @@ func (pm *ProtocolManager) measure(setup *benchmarkSetup, count int) error {
|
||||||
serverMeteredPipe := &meteredPipe{rw: serverPipe}
|
serverMeteredPipe := &meteredPipe{rw: serverPipe}
|
||||||
var id enode.ID
|
var id enode.ID
|
||||||
rand.Read(id[:])
|
rand.Read(id[:])
|
||||||
clientPeer := pm.newPeer(lpv2, NetworkId, p2p.NewPeer(id, "client", nil), clientMeteredPipe)
|
clientPeer := pm.newPeer(lpv2, NetworkID, p2p.NewPeer(id, "client", nil), clientMeteredPipe)
|
||||||
serverPeer := pm.newPeer(lpv2, NetworkId, p2p.NewPeer(id, "server", nil), serverMeteredPipe)
|
serverPeer := pm.newPeer(lpv2, NetworkID, p2p.NewPeer(id, "server", nil), serverMeteredPipe)
|
||||||
serverPeer.sendQueue = newExecQueue(count)
|
serverPeer.sendQueue = newExecQueue(count)
|
||||||
serverPeer.announceType = announceTypeNone
|
serverPeer.announceType = announceTypeNone
|
||||||
serverPeer.fcCosts = make(requestCostTable)
|
serverPeer.fcCosts = make(requestCostTable)
|
||||||
|
|
|
||||||
|
|
@ -51,7 +51,7 @@ func testFreeClientPool(t *testing.T, connLimit, clientCount int) {
|
||||||
peerAddress = func(i int) string {
|
peerAddress = func(i int) string {
|
||||||
return fmt.Sprintf("addr #%d", i)
|
return fmt.Sprintf("addr #%d", i)
|
||||||
}
|
}
|
||||||
peerId = func(i int) string {
|
peerID = func(i int) string {
|
||||||
return fmt.Sprintf("id #%d", i)
|
return fmt.Sprintf("id #%d", i)
|
||||||
}
|
}
|
||||||
disconnFn = func(id string) {
|
disconnFn = func(id string) {
|
||||||
|
|
@ -67,14 +67,14 @@ func testFreeClientPool(t *testing.T, connLimit, clientCount int) {
|
||||||
|
|
||||||
// pool should accept new peers up to its connected limit
|
// pool should accept new peers up to its connected limit
|
||||||
for i := 0; i < connLimit; i++ {
|
for i := 0; i < connLimit; i++ {
|
||||||
if pool.connect(peerAddress(i), peerId(i)) {
|
if pool.connect(peerAddress(i), peerID(i)) {
|
||||||
connected[i] = true
|
connected[i] = true
|
||||||
} else {
|
} else {
|
||||||
t.Fatalf("Test peer #%d rejected", i)
|
t.Fatalf("Test peer #%d rejected", i)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// since all accepted peers are new and should not be kicked out, the next one should be rejected
|
// since all accepted peers are new and should not be kicked out, the next one should be rejected
|
||||||
if pool.connect(peerAddress(connLimit), peerId(connLimit)) {
|
if pool.connect(peerAddress(connLimit), peerID(connLimit)) {
|
||||||
connected[connLimit] = true
|
connected[connLimit] = true
|
||||||
t.Fatalf("Peer accepted over connected limit")
|
t.Fatalf("Peer accepted over connected limit")
|
||||||
}
|
}
|
||||||
|
|
@ -89,7 +89,7 @@ func testFreeClientPool(t *testing.T, connLimit, clientCount int) {
|
||||||
connected[i] = false
|
connected[i] = false
|
||||||
connTicks[i] += tickCounter
|
connTicks[i] += tickCounter
|
||||||
} else {
|
} else {
|
||||||
if pool.connect(peerAddress(i), peerId(i)) {
|
if pool.connect(peerAddress(i), peerID(i)) {
|
||||||
connected[i] = true
|
connected[i] = true
|
||||||
connTicks[i] -= tickCounter
|
connTicks[i] -= tickCounter
|
||||||
}
|
}
|
||||||
|
|
@ -135,7 +135,7 @@ func testFreeClientPool(t *testing.T, connLimit, clientCount int) {
|
||||||
|
|
||||||
// try connecting all known peers (connLimit should be filled up)
|
// try connecting all known peers (connLimit should be filled up)
|
||||||
for i := 0; i < clientCount; i++ {
|
for i := 0; i < clientCount; i++ {
|
||||||
pool.connect(peerAddress(i), peerId(i))
|
pool.connect(peerAddress(i), peerID(i))
|
||||||
}
|
}
|
||||||
// expect pool to remember known nodes and kick out one of them to accept a new one
|
// expect pool to remember known nodes and kick out one of them to accept a new one
|
||||||
if !pool.connect("newAddr2", "newId2") {
|
if !pool.connect("newAddr2", "newId2") {
|
||||||
|
|
|
||||||
|
|
@ -49,14 +49,22 @@ const (
|
||||||
|
|
||||||
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
|
// MaxHeaderFetch - Amount of block headers to be fetched per retrieval request
|
||||||
MaxBodyFetch = 32 // Amount of block bodies to be fetched per retrieval request
|
MaxHeaderFetch = 192
|
||||||
MaxReceiptFetch = 128 // Amount of transaction receipts to allow fetching per request
|
// MaxBodyFetch - Amount of block bodies to be fetched per retrieval request
|
||||||
MaxCodeFetch = 64 // Amount of contract codes to allow fetching per request
|
MaxBodyFetch = 32
|
||||||
MaxProofsFetch = 64 // Amount of merkle proofs to be fetched per retrieval request
|
// MaxReceiptFetch - Amount of transaction receipts to allow fetching per request
|
||||||
MaxHelperTrieProofsFetch = 64 // Amount of merkle proofs to be fetched per retrieval request
|
MaxReceiptFetch = 128
|
||||||
MaxTxSend = 64 // Amount of transactions to be send per request
|
// MaxCodeFetch - Amount of contract codes to allow fetching per request
|
||||||
MaxTxStatus = 256 // Amount of transactions to queried per request
|
MaxCodeFetch = 64
|
||||||
|
// MaxProofsFetch - Amount of merkle proofs to be fetched per retrieval request
|
||||||
|
MaxProofsFetch = 64
|
||||||
|
// MaxHelperTrieProofsFetch - Amount of merkle proofs to be fetched per retrieval request
|
||||||
|
MaxHelperTrieProofsFetch = 64
|
||||||
|
// MaxTxSend - Amount of transactions to be send per request
|
||||||
|
MaxTxSend = 64
|
||||||
|
// MaxTxStatus - Amount of transactions to queried per request
|
||||||
|
MaxTxStatus = 256
|
||||||
|
|
||||||
disableClientRemovePeer = false
|
disableClientRemovePeer = false
|
||||||
)
|
)
|
||||||
|
|
@ -65,6 +73,7 @@ func errResp(code errCode, format string, v ...interface{}) error {
|
||||||
return fmt.Errorf("%v - %v", code, fmt.Sprintf(format, v...))
|
return fmt.Errorf("%v - %v", code, fmt.Sprintf(format, v...))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// BlockChain - a blockchain
|
||||||
type BlockChain interface {
|
type BlockChain interface {
|
||||||
Config() *params.ChainConfig
|
Config() *params.ChainConfig
|
||||||
HasHeader(hash common.Hash, number uint64) bool
|
HasHeader(hash common.Hash, number uint64) bool
|
||||||
|
|
@ -86,6 +95,7 @@ type txPool interface {
|
||||||
Status(hashes []common.Hash) []core.TxStatus
|
Status(hashes []common.Hash) []core.TxStatus
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ProtocolManager handles protocol messages and other protocol-specific tasks
|
||||||
type ProtocolManager struct {
|
type ProtocolManager struct {
|
||||||
// Configs
|
// Configs
|
||||||
chainConfig *params.ChainConfig
|
chainConfig *params.ChainConfig
|
||||||
|
|
@ -93,7 +103,7 @@ type ProtocolManager struct {
|
||||||
|
|
||||||
client bool // The indicator whether the node is light client
|
client bool // The indicator whether the node is light client
|
||||||
maxPeers int // The maximum number peers allowed to connect.
|
maxPeers int // The maximum number peers allowed to connect.
|
||||||
networkId uint64 // The identity of network.
|
networkID uint64 // The identity of network.
|
||||||
|
|
||||||
txpool txPool
|
txpool txPool
|
||||||
txrelay *LesTxRelay
|
txrelay *LesTxRelay
|
||||||
|
|
@ -129,7 +139,7 @@ func NewProtocolManager(
|
||||||
chainConfig *params.ChainConfig,
|
chainConfig *params.ChainConfig,
|
||||||
indexerConfig *light.IndexerConfig,
|
indexerConfig *light.IndexerConfig,
|
||||||
client bool,
|
client bool,
|
||||||
networkId uint64,
|
networkID uint64,
|
||||||
mux *event.TypeMux,
|
mux *event.TypeMux,
|
||||||
engine consensus.Engine,
|
engine consensus.Engine,
|
||||||
peers *peerSet,
|
peers *peerSet,
|
||||||
|
|
@ -151,7 +161,7 @@ func NewProtocolManager(
|
||||||
iConfig: indexerConfig,
|
iConfig: indexerConfig,
|
||||||
chainDb: chainDb,
|
chainDb: chainDb,
|
||||||
odr: odr,
|
odr: odr,
|
||||||
networkId: networkId,
|
networkID: networkID,
|
||||||
txpool: txpool,
|
txpool: txpool,
|
||||||
txrelay: txrelay,
|
txrelay: txrelay,
|
||||||
serverPool: serverPool,
|
serverPool: serverPool,
|
||||||
|
|
@ -194,6 +204,7 @@ func (pm *ProtocolManager) removePeer(id string) {
|
||||||
pm.peers.Unregister(id)
|
pm.peers.Unregister(id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Start starts the protocol manager and is called during node startup only
|
||||||
func (pm *ProtocolManager) Start(maxPeers int) {
|
func (pm *ProtocolManager) Start(maxPeers int) {
|
||||||
pm.maxPeers = maxPeers
|
pm.maxPeers = maxPeers
|
||||||
if pm.client {
|
if pm.client {
|
||||||
|
|
@ -206,6 +217,7 @@ func (pm *ProtocolManager) Start(maxPeers int) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Stop stops the protocol manager and is called during node shutdown only
|
||||||
func (pm *ProtocolManager) Stop() {
|
func (pm *ProtocolManager) Stop() {
|
||||||
// Showing a log message. During download / process this could actually
|
// Showing a log message. During download / process this could actually
|
||||||
// take between 5 to 10 seconds and therefor feedback is required.
|
// take between 5 to 10 seconds and therefor feedback is required.
|
||||||
|
|
@ -236,7 +248,7 @@ func (pm *ProtocolManager) Stop() {
|
||||||
// runPeer is the p2p protocol run function for the given version.
|
// runPeer is the p2p protocol run function for the given version.
|
||||||
func (pm *ProtocolManager) runPeer(version uint, p *p2p.Peer, rw p2p.MsgReadWriter) error {
|
func (pm *ProtocolManager) runPeer(version uint, p *p2p.Peer, rw p2p.MsgReadWriter) error {
|
||||||
var entry *poolEntry
|
var entry *poolEntry
|
||||||
peer := pm.newPeer(int(version), pm.networkId, p, rw)
|
peer := pm.newPeer(int(version), pm.networkID, p, rw)
|
||||||
if pm.serverPool != nil {
|
if pm.serverPool != nil {
|
||||||
entry = pm.serverPool.connect(peer, peer.Node())
|
entry = pm.serverPool.connect(peer, peer.Node())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -170,7 +170,7 @@ func newTestProtocolManager(lightSync bool, blocks int, generator func(int, *cor
|
||||||
if lightSync {
|
if lightSync {
|
||||||
indexConfig = light.TestClientIndexerConfig
|
indexConfig = light.TestClientIndexerConfig
|
||||||
}
|
}
|
||||||
pm, err := NewProtocolManager(gspec.Config, indexConfig, lightSync, NetworkId, evmux, engine, peers, chain, pool, db, odr, nil, nil, make(chan struct{}), new(sync.WaitGroup), ulcConfig, func() bool { return true })
|
pm, err := NewProtocolManager(gspec.Config, indexConfig, lightSync, NetworkID, evmux, engine, peers, chain, pool, db, odr, nil, nil, make(chan struct{}), new(sync.WaitGroup), ulcConfig, func() bool { return true })
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
@ -218,7 +218,7 @@ func newTestPeer(t *testing.T, name string, version int, pm *ProtocolManager, sh
|
||||||
var id enode.ID
|
var id enode.ID
|
||||||
rand.Read(id[:])
|
rand.Read(id[:])
|
||||||
|
|
||||||
peer := pm.newPeer(version, NetworkId, p2p.NewPeer(id, name, nil), net)
|
peer := pm.newPeer(version, NetworkID, p2p.NewPeer(id, name, nil), net)
|
||||||
|
|
||||||
// Start the peer on a new thread
|
// Start the peer on a new thread
|
||||||
errc := make(chan error, 1)
|
errc := make(chan error, 1)
|
||||||
|
|
@ -255,8 +255,8 @@ func newTestPeerPair(name string, version int, pm, pm2 *ProtocolManager) (*peer,
|
||||||
var id enode.ID
|
var id enode.ID
|
||||||
rand.Read(id[:])
|
rand.Read(id[:])
|
||||||
|
|
||||||
peer := pm.newPeer(version, NetworkId, p2p.NewPeer(id, name, nil), net)
|
peer := pm.newPeer(version, NetworkID, p2p.NewPeer(id, name, nil), net)
|
||||||
peer2 := pm2.newPeer(version, NetworkId, p2p.NewPeer(id, name, nil), app)
|
peer2 := pm2.newPeer(version, NetworkID, p2p.NewPeer(id, name, nil), app)
|
||||||
|
|
||||||
// Start the peer on a new thread
|
// Start the peer on a new thread
|
||||||
errc := make(chan error, 1)
|
errc := make(chan error, 1)
|
||||||
|
|
@ -285,7 +285,7 @@ func newTestPeerPair(name string, version int, pm, pm2 *ProtocolManager) (*peer,
|
||||||
func (p *testPeer) handshake(t *testing.T, td *big.Int, head common.Hash, headNum uint64, genesis common.Hash) {
|
func (p *testPeer) handshake(t *testing.T, td *big.Int, head common.Hash, headNum uint64, genesis common.Hash) {
|
||||||
var expList keyValueList
|
var expList keyValueList
|
||||||
expList = expList.add("protocolVersion", uint64(p.version))
|
expList = expList.add("protocolVersion", uint64(p.version))
|
||||||
expList = expList.add("networkId", uint64(NetworkId))
|
expList = expList.add("networkId", uint64(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)
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,7 @@ type LesOdr struct {
|
||||||
stop chan struct{}
|
stop chan struct{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewLesOdr - construct a new LES on demand request
|
||||||
func NewLesOdr(db ethdb.Database, config *light.IndexerConfig, retriever *retrieveManager) *LesOdr {
|
func NewLesOdr(db ethdb.Database, config *light.IndexerConfig, retriever *retrieveManager) *LesOdr {
|
||||||
return &LesOdr{
|
return &LesOdr{
|
||||||
db: db,
|
db: db,
|
||||||
|
|
@ -81,11 +82,17 @@ func (odr *LesOdr) IndexerConfig() *light.IndexerConfig {
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
// MsgBlockBodies - block bodies request
|
||||||
MsgBlockBodies = iota
|
MsgBlockBodies = iota
|
||||||
|
// MsgCode - code request
|
||||||
MsgCode
|
MsgCode
|
||||||
|
// MsgReceipts - receipts request
|
||||||
MsgReceipts
|
MsgReceipts
|
||||||
|
// MsgProofsV2 - proofs request
|
||||||
MsgProofsV2
|
MsgProofsV2
|
||||||
|
// MsgHelperTrieProofs - helper trie proofs request
|
||||||
MsgHelperTrieProofs
|
MsgHelperTrieProofs
|
||||||
|
// MsgTxStatus - transaction status request
|
||||||
MsgTxStatus
|
MsgTxStatus
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -45,6 +45,7 @@ var (
|
||||||
errUselessNodes = errors.New("useless nodes in merkle proof nodeset")
|
errUselessNodes = errors.New("useless nodes in merkle proof nodeset")
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// LesOdrRequest - an on-demand request
|
||||||
type LesOdrRequest interface {
|
type LesOdrRequest interface {
|
||||||
GetCost(*peer) uint64
|
GetCost(*peer) uint64
|
||||||
CanSend(*peer) bool
|
CanSend(*peer) bool
|
||||||
|
|
@ -52,6 +53,7 @@ type LesOdrRequest interface {
|
||||||
Validate(ethdb.Database, *Msg) error
|
Validate(ethdb.Database, *Msg) error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// LesRequest - generate a LES on demand request from a light one
|
||||||
func LesRequest(req light.OdrRequest) LesOdrRequest {
|
func LesRequest(req light.OdrRequest) LesOdrRequest {
|
||||||
switch r := req.(type) {
|
switch r := req.(type) {
|
||||||
case *light.BlockRequest:
|
case *light.BlockRequest:
|
||||||
|
|
@ -93,7 +95,7 @@ func (r *BlockRequest) Request(reqID uint64, peer *peer) error {
|
||||||
return peer.RequestBodies(reqID, r.GetCost(peer), []common.Hash{r.Hash})
|
return peer.RequestBodies(reqID, r.GetCost(peer), []common.Hash{r.Hash})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Valid processes an ODR request reply message from the LES network
|
// Validate processes an ODR request reply message from the LES network
|
||||||
// returns true and stores results in memory if the message was a valid reply
|
// returns true and stores results in memory if the message was a valid reply
|
||||||
// to the request (implementation of LesOdrRequest)
|
// to the request (implementation of LesOdrRequest)
|
||||||
func (r *BlockRequest) Validate(db ethdb.Database, msg *Msg) error {
|
func (r *BlockRequest) Validate(db ethdb.Database, msg *Msg) error {
|
||||||
|
|
@ -149,7 +151,7 @@ func (r *ReceiptsRequest) Request(reqID uint64, peer *peer) error {
|
||||||
return peer.RequestReceipts(reqID, r.GetCost(peer), []common.Hash{r.Hash})
|
return peer.RequestReceipts(reqID, r.GetCost(peer), []common.Hash{r.Hash})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Valid processes an ODR request reply message from the LES network
|
// Validate processes an ODR request reply message from the LES network
|
||||||
// returns true and stores results in memory if the message was a valid reply
|
// returns true and stores results in memory if the message was a valid reply
|
||||||
// to the request (implementation of LesOdrRequest)
|
// to the request (implementation of LesOdrRequest)
|
||||||
func (r *ReceiptsRequest) Validate(db ethdb.Database, msg *Msg) error {
|
func (r *ReceiptsRequest) Validate(db ethdb.Database, msg *Msg) error {
|
||||||
|
|
@ -178,13 +180,14 @@ func (r *ReceiptsRequest) Validate(db ethdb.Database, msg *Msg) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ProofReq - a request for a proof
|
||||||
type ProofReq struct {
|
type ProofReq struct {
|
||||||
BHash common.Hash
|
BHash common.Hash
|
||||||
AccKey, Key []byte
|
AccKey, Key []byte
|
||||||
FromLevel uint
|
FromLevel uint
|
||||||
}
|
}
|
||||||
|
|
||||||
// ODR request type for state/storage trie entries, see LesOdrRequest interface
|
// TrieRequest - 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
|
||||||
|
|
@ -209,7 +212,7 @@ func (r *TrieRequest) Request(reqID uint64, peer *peer) error {
|
||||||
return peer.RequestProofs(reqID, r.GetCost(peer), []ProofReq{req})
|
return peer.RequestProofs(reqID, r.GetCost(peer), []ProofReq{req})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Valid processes an ODR request reply message from the LES network
|
// Validate processes an ODR request reply message from the LES network
|
||||||
// returns true and stores results in memory if the message was a valid reply
|
// returns true and stores results in memory if the message was a valid reply
|
||||||
// to the request (implementation of LesOdrRequest)
|
// to the request (implementation of LesOdrRequest)
|
||||||
func (r *TrieRequest) Validate(db ethdb.Database, msg *Msg) error {
|
func (r *TrieRequest) Validate(db ethdb.Database, msg *Msg) error {
|
||||||
|
|
@ -233,12 +236,13 @@ func (r *TrieRequest) Validate(db ethdb.Database, msg *Msg) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CodeReq - a request for contract code
|
||||||
type CodeReq struct {
|
type CodeReq struct {
|
||||||
BHash common.Hash
|
BHash common.Hash
|
||||||
AccKey []byte
|
AccKey []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
// ODR request type for node data (used for retrieving contract code), see LesOdrRequest interface
|
// CodeRequest - 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
|
||||||
|
|
@ -262,7 +266,7 @@ func (r *CodeRequest) Request(reqID uint64, peer *peer) error {
|
||||||
return peer.RequestCode(reqID, r.GetCost(peer), []CodeReq{req})
|
return peer.RequestCode(reqID, r.GetCost(peer), []CodeReq{req})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Valid processes an ODR request reply message from the LES network
|
// Validate processes an ODR request reply message from the LES network
|
||||||
// returns true and stores results in memory if the message was a valid reply
|
// returns true and stores results in memory if the message was a valid reply
|
||||||
// to the request (implementation of LesOdrRequest)
|
// to the request (implementation of LesOdrRequest)
|
||||||
func (r *CodeRequest) Validate(db ethdb.Database, msg *Msg) error {
|
func (r *CodeRequest) Validate(db ethdb.Database, msg *Msg) error {
|
||||||
|
|
@ -297,6 +301,7 @@ const (
|
||||||
auxHeader = 2
|
auxHeader = 2
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// HelperTrieReq - a request for part of a trie
|
||||||
type HelperTrieReq struct {
|
type HelperTrieReq struct {
|
||||||
Type uint
|
Type uint
|
||||||
TrieIdx uint64
|
TrieIdx uint64
|
||||||
|
|
@ -304,12 +309,13 @@ type HelperTrieReq struct {
|
||||||
FromLevel, AuxReq uint
|
FromLevel, AuxReq uint
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// HelperTrieResps - response to HelperTrieReq, providing merkle proofs
|
||||||
type HelperTrieResps struct { // describes all responses, not just a single one
|
type HelperTrieResps struct { // describes all responses, not just a single one
|
||||||
Proofs light.NodeList
|
Proofs light.NodeList
|
||||||
AuxData [][]byte
|
AuxData [][]byte
|
||||||
}
|
}
|
||||||
|
|
||||||
// ODR request type for requesting headers by Canonical Hash Trie, see LesOdrRequest interface
|
// ChtRequest - 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
|
||||||
|
|
@ -340,7 +346,7 @@ func (r *ChtRequest) Request(reqID uint64, peer *peer) error {
|
||||||
return peer.RequestHelperTrieProofs(reqID, r.GetCost(peer), []HelperTrieReq{req})
|
return peer.RequestHelperTrieProofs(reqID, r.GetCost(peer), []HelperTrieReq{req})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Valid processes an ODR request reply message from the LES network
|
// Validate processes an ODR request reply message from the LES network
|
||||||
// returns true and stores results in memory if the message was a valid reply
|
// returns true and stores results in memory if the message was a valid reply
|
||||||
// to the request (implementation of LesOdrRequest)
|
// to the request (implementation of LesOdrRequest)
|
||||||
func (r *ChtRequest) Validate(db ethdb.Database, msg *Msg) error {
|
func (r *ChtRequest) Validate(db ethdb.Database, msg *Msg) error {
|
||||||
|
|
@ -393,11 +399,12 @@ func (r *ChtRequest) Validate(db ethdb.Database, msg *Msg) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// BloomReq -
|
||||||
type BloomReq struct {
|
type BloomReq struct {
|
||||||
BloomTrieNum, BitIdx, SectionIndex, FromLevel uint64
|
BloomTrieNum, BitIdx, SectionIndex, FromLevel uint64
|
||||||
}
|
}
|
||||||
|
|
||||||
// ODR request type for requesting headers by Canonical Hash Trie, see LesOdrRequest interface
|
// BloomRequest - 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
|
||||||
|
|
@ -436,7 +443,7 @@ func (r *BloomRequest) Request(reqID uint64, peer *peer) error {
|
||||||
return peer.RequestHelperTrieProofs(reqID, r.GetCost(peer), reqs)
|
return peer.RequestHelperTrieProofs(reqID, r.GetCost(peer), reqs)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Valid processes an ODR request reply message from the LES network
|
// Validate processes an ODR request reply message from the LES network
|
||||||
// returns true and stores results in memory if the message was a valid reply
|
// returns true and stores results in memory if the message was a valid reply
|
||||||
// to the request (implementation of LesOdrRequest)
|
// to the request (implementation of LesOdrRequest)
|
||||||
func (r *BloomRequest) Validate(db ethdb.Database, msg *Msg) error {
|
func (r *BloomRequest) Validate(db ethdb.Database, msg *Msg) error {
|
||||||
|
|
@ -493,7 +500,7 @@ func (r *TxStatusRequest) Request(reqID uint64, peer *peer) error {
|
||||||
return peer.RequestTxStatus(reqID, r.GetCost(peer), r.Hashes)
|
return peer.RequestTxStatus(reqID, r.GetCost(peer), r.Hashes)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Valid processes an ODR request reply message from the LES network
|
// Validate processes an ODR request reply message from the LES network
|
||||||
// returns true and stores results in memory if the message was a valid reply
|
// returns true and stores results in memory if the message was a valid reply
|
||||||
// to the request (implementation of LesOdrRequest)
|
// to the request (implementation of LesOdrRequest)
|
||||||
func (r *TxStatusRequest) Validate(db ethdb.Database, msg *Msg) error {
|
func (r *TxStatusRequest) Validate(db ethdb.Database, msg *Msg) error {
|
||||||
|
|
|
||||||
|
|
@ -526,7 +526,7 @@ func (p *peer) Handshake(td *big.Int, head common.Hash, headNum uint64, genesis
|
||||||
return errResp(ErrGenesisBlockMismatch, "%x (!= %x)", rGenesis[:8], genesis[:8])
|
return errResp(ErrGenesisBlockMismatch, "%x (!= %x)", rGenesis[:8], genesis[:8])
|
||||||
}
|
}
|
||||||
if rNetwork != p.network {
|
if rNetwork != p.network {
|
||||||
return errResp(ErrNetworkIdMismatch, "%d (!= %d)", rNetwork, p.network)
|
return errResp(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 errResp(ErrProtocolVersionMismatch, "%d (!= %d)", rVersion, p.version)
|
||||||
|
|
|
||||||
|
|
@ -12,8 +12,8 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
test_networkid = 10
|
testNetworkID = 10
|
||||||
protocol_version = lpv2
|
protocolVersion = lpv2
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|
@ -30,7 +30,7 @@ func TestPeerHandshakeSetAnnounceTypeToAnnounceTypeSignedForTrustedPeer(t *testi
|
||||||
//peer to connect(on ulc side)
|
//peer to connect(on ulc side)
|
||||||
p := peer{
|
p := peer{
|
||||||
Peer: p2p.NewPeer(id, "test peer", []p2p.Cap{}),
|
Peer: p2p.NewPeer(id, "test peer", []p2p.Cap{}),
|
||||||
version: protocol_version,
|
version: protocolVersion,
|
||||||
isTrusted: true,
|
isTrusted: true,
|
||||||
rw: &rwStub{
|
rw: &rwStub{
|
||||||
WriteHook: func(recvList keyValueList) {
|
WriteHook: func(recvList keyValueList) {
|
||||||
|
|
@ -59,7 +59,7 @@ func TestPeerHandshakeSetAnnounceTypeToAnnounceTypeSignedForTrustedPeer(t *testi
|
||||||
return l
|
return l
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
network: test_networkid,
|
network: testNetworkID,
|
||||||
}
|
}
|
||||||
|
|
||||||
err := p.Handshake(td, hash, headNum, genesis, nil)
|
err := p.Handshake(td, hash, headNum, genesis, nil)
|
||||||
|
|
@ -76,7 +76,7 @@ func TestPeerHandshakeAnnounceTypeSignedForTrustedPeersPeerNotInTrusted(t *testi
|
||||||
id := newNodeID(t).ID()
|
id := newNodeID(t).ID()
|
||||||
p := peer{
|
p := peer{
|
||||||
Peer: p2p.NewPeer(id, "test peer", []p2p.Cap{}),
|
Peer: p2p.NewPeer(id, "test peer", []p2p.Cap{}),
|
||||||
version: protocol_version,
|
version: protocolVersion,
|
||||||
rw: &rwStub{
|
rw: &rwStub{
|
||||||
WriteHook: func(recvList keyValueList) {
|
WriteHook: func(recvList keyValueList) {
|
||||||
//checking that ulc sends to peer allowedRequests=noRequests and announceType != announceTypeSigned
|
//checking that ulc sends to peer allowedRequests=noRequests and announceType != announceTypeSigned
|
||||||
|
|
@ -104,7 +104,7 @@ func TestPeerHandshakeAnnounceTypeSignedForTrustedPeersPeerNotInTrusted(t *testi
|
||||||
return l
|
return l
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
network: test_networkid,
|
network: testNetworkID,
|
||||||
}
|
}
|
||||||
|
|
||||||
err := p.Handshake(td, hash, headNum, genesis, nil)
|
err := p.Handshake(td, hash, headNum, genesis, nil)
|
||||||
|
|
@ -123,7 +123,7 @@ func TestPeerHandshakeDefaultAllRequests(t *testing.T) {
|
||||||
|
|
||||||
p := peer{
|
p := peer{
|
||||||
Peer: p2p.NewPeer(id, "test peer", []p2p.Cap{}),
|
Peer: p2p.NewPeer(id, "test peer", []p2p.Cap{}),
|
||||||
version: protocol_version,
|
version: protocolVersion,
|
||||||
rw: &rwStub{
|
rw: &rwStub{
|
||||||
ReadHook: func(l keyValueList) keyValueList {
|
ReadHook: func(l keyValueList) keyValueList {
|
||||||
l = l.add("announceType", uint64(announceTypeSigned))
|
l = l.add("announceType", uint64(announceTypeSigned))
|
||||||
|
|
@ -132,7 +132,7 @@ func TestPeerHandshakeDefaultAllRequests(t *testing.T) {
|
||||||
return l
|
return l
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
network: test_networkid,
|
network: testNetworkID,
|
||||||
}
|
}
|
||||||
|
|
||||||
err := p.Handshake(td, hash, headNum, genesis, s)
|
err := p.Handshake(td, hash, headNum, genesis, s)
|
||||||
|
|
@ -153,7 +153,7 @@ func TestPeerHandshakeServerSendOnlyAnnounceRequestsHeaders(t *testing.T) {
|
||||||
|
|
||||||
p := peer{
|
p := peer{
|
||||||
Peer: p2p.NewPeer(id, "test peer", []p2p.Cap{}),
|
Peer: p2p.NewPeer(id, "test peer", []p2p.Cap{}),
|
||||||
version: protocol_version,
|
version: protocolVersion,
|
||||||
rw: &rwStub{
|
rw: &rwStub{
|
||||||
ReadHook: func(l keyValueList) keyValueList {
|
ReadHook: func(l keyValueList) keyValueList {
|
||||||
l = l.add("announceType", uint64(announceTypeSigned))
|
l = l.add("announceType", uint64(announceTypeSigned))
|
||||||
|
|
@ -171,7 +171,7 @@ func TestPeerHandshakeServerSendOnlyAnnounceRequestsHeaders(t *testing.T) {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
network: test_networkid,
|
network: testNetworkID,
|
||||||
}
|
}
|
||||||
|
|
||||||
err := p.Handshake(td, hash, headNum, genesis, s)
|
err := p.Handshake(td, hash, headNum, genesis, s)
|
||||||
|
|
@ -184,7 +184,7 @@ func TestPeerHandshakeClientReceiveOnlyAnnounceRequestsHeaders(t *testing.T) {
|
||||||
|
|
||||||
p := peer{
|
p := peer{
|
||||||
Peer: p2p.NewPeer(id, "test peer", []p2p.Cap{}),
|
Peer: p2p.NewPeer(id, "test peer", []p2p.Cap{}),
|
||||||
version: protocol_version,
|
version: protocolVersion,
|
||||||
rw: &rwStub{
|
rw: &rwStub{
|
||||||
ReadHook: func(l keyValueList) keyValueList {
|
ReadHook: func(l keyValueList) keyValueList {
|
||||||
l = l.add("flowControl/BL", uint64(0))
|
l = l.add("flowControl/BL", uint64(0))
|
||||||
|
|
@ -196,7 +196,7 @@ func TestPeerHandshakeClientReceiveOnlyAnnounceRequestsHeaders(t *testing.T) {
|
||||||
return l
|
return l
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
network: test_networkid,
|
network: testNetworkID,
|
||||||
isTrusted: true,
|
isTrusted: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -215,7 +215,7 @@ func TestPeerHandshakeClientReturnErrorOnUselessPeer(t *testing.T) {
|
||||||
|
|
||||||
p := peer{
|
p := peer{
|
||||||
Peer: p2p.NewPeer(id, "test peer", []p2p.Cap{}),
|
Peer: p2p.NewPeer(id, "test peer", []p2p.Cap{}),
|
||||||
version: protocol_version,
|
version: protocolVersion,
|
||||||
rw: &rwStub{
|
rw: &rwStub{
|
||||||
ReadHook: func(l keyValueList) keyValueList {
|
ReadHook: func(l keyValueList) keyValueList {
|
||||||
l = l.add("flowControl/BL", uint64(0))
|
l = l.add("flowControl/BL", uint64(0))
|
||||||
|
|
@ -227,7 +227,7 @@ func TestPeerHandshakeClientReturnErrorOnUselessPeer(t *testing.T) {
|
||||||
return l
|
return l
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
network: test_networkid,
|
network: testNetworkID,
|
||||||
}
|
}
|
||||||
|
|
||||||
err := p.Handshake(td, hash, headNum, genesis, nil)
|
err := p.Handshake(td, hash, headNum, genesis, nil)
|
||||||
|
|
@ -254,8 +254,8 @@ type rwStub struct {
|
||||||
|
|
||||||
func (s *rwStub) ReadMsg() (p2p.Msg, error) {
|
func (s *rwStub) ReadMsg() (p2p.Msg, error) {
|
||||||
payload := keyValueList{}
|
payload := keyValueList{}
|
||||||
payload = payload.add("protocolVersion", uint64(protocol_version))
|
payload = payload.add("protocolVersion", uint64(protocolVersion))
|
||||||
payload = payload.add("networkId", uint64(test_networkid))
|
payload = payload.add("networkId", uint64(testNetworkID))
|
||||||
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)
|
||||||
|
|
|
||||||
|
|
@ -41,12 +41,14 @@ var (
|
||||||
AdvertiseProtocolVersions = []uint{lpv2} // clients are searching for the first advertised protocol in the list
|
AdvertiseProtocolVersions = []uint{lpv2} // clients are searching for the first advertised protocol in the list
|
||||||
)
|
)
|
||||||
|
|
||||||
// Number of implemented message corresponding to different protocol versions.
|
// ProtocolLengths - Number of implemented message corresponding to different protocol versions.
|
||||||
var ProtocolLengths = map[uint]uint64{lpv2: 22}
|
var ProtocolLengths = map[uint]uint64{lpv2: 22}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
NetworkId = 1
|
// NetworkID - the network id
|
||||||
ProtocolMaxMsgSize = 10 * 1024 * 1024 // Maximum cap on the size of a protocol message
|
NetworkID = 1
|
||||||
|
// ProtocolMaxMsgSize - Maximum cap on the size of a protocol message
|
||||||
|
ProtocolMaxMsgSize = 10 * 1024 * 1024
|
||||||
)
|
)
|
||||||
|
|
||||||
// les protocol message codes
|
// les protocol message codes
|
||||||
|
|
@ -91,20 +93,35 @@ var requests = map[uint64]requestInfo{
|
||||||
type errCode int
|
type errCode int
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
// ErrMsgTooLarge - message too large
|
||||||
ErrMsgTooLarge = iota
|
ErrMsgTooLarge = iota
|
||||||
|
// ErrDecode - decode error
|
||||||
ErrDecode
|
ErrDecode
|
||||||
|
// ErrInvalidMsgCode - invalid message error
|
||||||
ErrInvalidMsgCode
|
ErrInvalidMsgCode
|
||||||
|
// ErrProtocolVersionMismatch - mismatched protocol version
|
||||||
ErrProtocolVersionMismatch
|
ErrProtocolVersionMismatch
|
||||||
ErrNetworkIdMismatch
|
// ErrNetworkIDMismatch - wrong network id
|
||||||
|
ErrNetworkIDMismatch
|
||||||
|
// ErrGenesisBlockMismatch - incompatible genesis blocks
|
||||||
ErrGenesisBlockMismatch
|
ErrGenesisBlockMismatch
|
||||||
|
// ErrNoStatusMsg -
|
||||||
ErrNoStatusMsg
|
ErrNoStatusMsg
|
||||||
|
// ErrExtraStatusMsg -
|
||||||
ErrExtraStatusMsg
|
ErrExtraStatusMsg
|
||||||
|
// ErrSuspendedPeer -
|
||||||
ErrSuspendedPeer
|
ErrSuspendedPeer
|
||||||
|
// ErrUselessPeer -
|
||||||
ErrUselessPeer
|
ErrUselessPeer
|
||||||
|
// ErrRequestRejected -
|
||||||
ErrRequestRejected
|
ErrRequestRejected
|
||||||
|
// ErrUnexpectedResponse -
|
||||||
ErrUnexpectedResponse
|
ErrUnexpectedResponse
|
||||||
|
// ErrInvalidResponse -
|
||||||
ErrInvalidResponse
|
ErrInvalidResponse
|
||||||
|
// ErrTooManyTimeouts -
|
||||||
ErrTooManyTimeouts
|
ErrTooManyTimeouts
|
||||||
|
// ErrMissingKey -
|
||||||
ErrMissingKey
|
ErrMissingKey
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -118,7 +135,7 @@ var errorToString = map[int]string{
|
||||||
ErrDecode: "Invalid message",
|
ErrDecode: "Invalid message",
|
||||||
ErrInvalidMsgCode: "Invalid message code",
|
ErrInvalidMsgCode: "Invalid message code",
|
||||||
ErrProtocolVersionMismatch: "Protocol version mismatch",
|
ErrProtocolVersionMismatch: "Protocol version mismatch",
|
||||||
ErrNetworkIdMismatch: "NetworkId mismatch",
|
ErrNetworkIDMismatch: "NetworkId mismatch",
|
||||||
ErrGenesisBlockMismatch: "Genesis block mismatch",
|
ErrGenesisBlockMismatch: "Genesis block mismatch",
|
||||||
ErrNoStatusMsg: "No status message",
|
ErrNoStatusMsg: "No status message",
|
||||||
ErrExtraStatusMsg: "Extra status message",
|
ErrExtraStatusMsg: "Extra status message",
|
||||||
|
|
|
||||||
|
|
@ -37,6 +37,7 @@ import (
|
||||||
|
|
||||||
const bufLimitRatio = 6000 // fixed bufLimit/MRR ratio
|
const bufLimitRatio = 6000 // fixed bufLimit/MRR ratio
|
||||||
|
|
||||||
|
// LesServer - a node service running a LES server
|
||||||
type LesServer struct {
|
type LesServer struct {
|
||||||
lesCommons
|
lesCommons
|
||||||
|
|
||||||
|
|
@ -56,6 +57,7 @@ type LesServer struct {
|
||||||
priorityClientPool *priorityClientPool
|
priorityClientPool *priorityClientPool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewLesServer - ctor creating a LES server node service
|
||||||
func NewLesServer(eth *eth.Ethereum, config *eth.Config) (*LesServer, error) {
|
func NewLesServer(eth *eth.Ethereum, config *eth.Config) (*LesServer, error) {
|
||||||
quitSync := make(chan struct{})
|
quitSync := make(chan struct{})
|
||||||
pm, err := NewProtocolManager(
|
pm, err := NewProtocolManager(
|
||||||
|
|
@ -124,9 +126,13 @@ func NewLesServer(eth *eth.Ethereum, config *eth.Config) (*LesServer, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
srv.chtIndexer.Start(eth.BlockChain())
|
srv.chtIndexer.Start(eth.BlockChain())
|
||||||
|
|
||||||
|
eth.GetBloomIndexer().AddChildIndexer(srv.bloomTrieIndexer)
|
||||||
|
|
||||||
return srv, nil
|
return srv, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// APIs - the RPC APIs offered by this server
|
||||||
func (s *LesServer) APIs() []rpc.API {
|
func (s *LesServer) APIs() []rpc.API {
|
||||||
return []rpc.API{
|
return []rpc.API{
|
||||||
{
|
{
|
||||||
|
|
@ -180,12 +186,13 @@ func (s *LesServer) startEventLoop() {
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Protocols - rlpx capabilities offered by this LES server
|
||||||
func (s *LesServer) Protocols() []p2p.Protocol {
|
func (s *LesServer) Protocols() []p2p.Protocol {
|
||||||
return s.makeProtocols(ServerProtocolVersions)
|
return s.makeProtocols(ServerProtocolVersions)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start starts the LES server
|
// Start starts the LES server
|
||||||
func (s *LesServer) Start(srvr *p2p.Server) {
|
func (s *LesServer) Start(srvr *p2p.Server) error {
|
||||||
s.maxPeers = s.config.LightPeers
|
s.maxPeers = s.config.LightPeers
|
||||||
totalRecharge := s.costTracker.totalRecharge()
|
totalRecharge := s.costTracker.totalRecharge()
|
||||||
if s.maxPeers > 0 {
|
if s.maxPeers > 0 {
|
||||||
|
|
@ -225,22 +232,30 @@ func (s *LesServer) Start(srvr *p2p.Server) {
|
||||||
}
|
}
|
||||||
s.privateKey = srvr.PrivateKey
|
s.privateKey = srvr.PrivateKey
|
||||||
s.protocolManager.blockLoop()
|
s.protocolManager.blockLoop()
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetBloomBitsIndexer - adds the bloombits indexer as a child indexer to the bloomtrie indexer
|
||||||
func (s *LesServer) SetBloomBitsIndexer(bloomIndexer *core.ChainIndexer) {
|
func (s *LesServer) SetBloomBitsIndexer(bloomIndexer *core.ChainIndexer) {
|
||||||
bloomIndexer.AddChildIndexer(s.bloomTrieIndexer)
|
bloomIndexer.AddChildIndexer(s.bloomTrieIndexer)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stop stops the LES service
|
// Stop stops the LES service
|
||||||
func (s *LesServer) Stop() {
|
func (s *LesServer) Stop() error {
|
||||||
s.chtIndexer.Close()
|
|
||||||
|
err := s.chtIndexer.Close()
|
||||||
|
|
||||||
// bloom trie indexer is closed by parent bloombits indexer
|
// bloom trie indexer is closed by parent bloombits indexer
|
||||||
go func() {
|
go func() {
|
||||||
<-s.protocolManager.noMorePeers
|
<-s.protocolManager.noMorePeers
|
||||||
}()
|
}()
|
||||||
|
|
||||||
s.freeClientPool.stop()
|
s.freeClientPool.stop()
|
||||||
|
|
||||||
s.costTracker.stop()
|
s.costTracker.stop()
|
||||||
|
|
||||||
s.protocolManager.Stop()
|
s.protocolManager.Stop()
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// todo(rjl493456442) separate client and server implementation.
|
// todo(rjl493456442) separate client and server implementation.
|
||||||
|
|
|
||||||
|
|
@ -176,8 +176,8 @@ func connectPeers(full, light pairPeer, version 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()
|
||||||
|
|
||||||
peerLight := full.PM.newPeer(version, NetworkId, p2p.NewPeer(light.Node.ID(), light.Name, nil), net)
|
peerLight := full.PM.newPeer(version, NetworkID, p2p.NewPeer(light.Node.ID(), light.Name, nil), net)
|
||||||
peerFull := light.PM.newPeer(version, NetworkId, p2p.NewPeer(full.Node.ID(), full.Name, nil), app)
|
peerFull := light.PM.newPeer(version, NetworkID, p2p.NewPeer(full.Node.ID(), full.Name, 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