github.com/devfans/go-ethereum@v1.5.10-0.20170326212234-7419d0c38291/les/backend.go (about)

     1  // Copyright 2016 The go-ethereum Authors
     2  // This file is part of the go-ethereum library.
     3  //
     4  // The go-ethereum library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The go-ethereum library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  // Package les implements the Light Ethereum Subprotocol.
    18  package les
    19  
    20  import (
    21  	"fmt"
    22  	"time"
    23  
    24  	"github.com/ethereum/go-ethereum/accounts"
    25  	"github.com/ethereum/go-ethereum/common"
    26  	"github.com/ethereum/go-ethereum/common/compiler"
    27  	"github.com/ethereum/go-ethereum/common/hexutil"
    28  	"github.com/ethereum/go-ethereum/core"
    29  	"github.com/ethereum/go-ethereum/core/types"
    30  	"github.com/ethereum/go-ethereum/eth"
    31  	"github.com/ethereum/go-ethereum/eth/downloader"
    32  	"github.com/ethereum/go-ethereum/eth/filters"
    33  	"github.com/ethereum/go-ethereum/eth/gasprice"
    34  	"github.com/ethereum/go-ethereum/ethdb"
    35  	"github.com/ethereum/go-ethereum/event"
    36  	"github.com/ethereum/go-ethereum/internal/ethapi"
    37  	"github.com/ethereum/go-ethereum/light"
    38  	"github.com/ethereum/go-ethereum/log"
    39  	"github.com/ethereum/go-ethereum/node"
    40  	"github.com/ethereum/go-ethereum/p2p"
    41  	"github.com/ethereum/go-ethereum/params"
    42  	"github.com/ethereum/go-ethereum/pow"
    43  	rpc "github.com/ethereum/go-ethereum/rpc"
    44  )
    45  
    46  type LightEthereum struct {
    47  	odr         *LesOdr
    48  	relay       *LesTxRelay
    49  	chainConfig *params.ChainConfig
    50  	// Channel for shutting down the service
    51  	shutdownChan chan bool
    52  	// Handlers
    53  	txPool          *light.TxPool
    54  	blockchain      *light.LightChain
    55  	protocolManager *ProtocolManager
    56  	// DB interfaces
    57  	chainDb ethdb.Database // Block chain database
    58  
    59  	ApiBackend *LesApiBackend
    60  
    61  	eventMux       *event.TypeMux
    62  	pow            pow.PoW
    63  	accountManager *accounts.Manager
    64  	solcPath       string
    65  	solc           *compiler.Solidity
    66  
    67  	netVersionId  int
    68  	netRPCService *ethapi.PublicNetAPI
    69  }
    70  
    71  func New(ctx *node.ServiceContext, config *eth.Config) (*LightEthereum, error) {
    72  	chainDb, err := eth.CreateDB(ctx, config, "lightchaindata")
    73  	if err != nil {
    74  		return nil, err
    75  	}
    76  	chainConfig, genesisHash, genesisErr := core.SetupGenesisBlock(chainDb, config.Genesis)
    77  	if _, isCompat := genesisErr.(*params.ConfigCompatError); genesisErr != nil && !isCompat {
    78  		return nil, genesisErr
    79  	}
    80  	log.Info("Initialised chain configuration", "config", chainConfig)
    81  
    82  	odr := NewLesOdr(chainDb)
    83  	relay := NewLesTxRelay()
    84  	eth := &LightEthereum{
    85  		odr:            odr,
    86  		relay:          relay,
    87  		chainDb:        chainDb,
    88  		chainConfig:    chainConfig,
    89  		eventMux:       ctx.EventMux,
    90  		accountManager: ctx.AccountManager,
    91  		pow:            eth.CreatePoW(ctx, config),
    92  		shutdownChan:   make(chan bool),
    93  		netVersionId:   config.NetworkId,
    94  		solcPath:       config.SolcPath,
    95  	}
    96  
    97  	eth.blockchain, err = light.NewLightChain(odr, eth.chainConfig, eth.pow, eth.eventMux)
    98  	if err != nil {
    99  		return nil, err
   100  	}
   101  	// Rewind the chain in case of an incompatible config upgrade.
   102  	if compat, ok := genesisErr.(*params.ConfigCompatError); ok {
   103  		log.Warn("Rewinding chain to upgrade configuration", "err", compat)
   104  		eth.blockchain.SetHead(compat.RewindTo)
   105  		core.WriteChainConfig(chainDb, genesisHash, chainConfig)
   106  	}
   107  
   108  	eth.txPool = light.NewTxPool(eth.chainConfig, eth.eventMux, eth.blockchain, eth.relay)
   109  	if eth.protocolManager, err = NewProtocolManager(eth.chainConfig, config.LightMode, config.NetworkId, eth.eventMux, eth.pow, eth.blockchain, nil, chainDb, odr, relay); err != nil {
   110  		return nil, err
   111  	}
   112  	relay.ps = eth.protocolManager.peers
   113  	relay.reqDist = eth.protocolManager.reqDist
   114  
   115  	eth.ApiBackend = &LesApiBackend{eth, nil}
   116  	eth.ApiBackend.gpo = gasprice.NewLightPriceOracle(eth.ApiBackend)
   117  	return eth, nil
   118  }
   119  
   120  type LightDummyAPI struct{}
   121  
   122  // Etherbase is the address that mining rewards will be send to
   123  func (s *LightDummyAPI) Etherbase() (common.Address, error) {
   124  	return common.Address{}, fmt.Errorf("not supported")
   125  }
   126  
   127  // Coinbase is the address that mining rewards will be send to (alias for Etherbase)
   128  func (s *LightDummyAPI) Coinbase() (common.Address, error) {
   129  	return common.Address{}, fmt.Errorf("not supported")
   130  }
   131  
   132  // Hashrate returns the POW hashrate
   133  func (s *LightDummyAPI) Hashrate() hexutil.Uint {
   134  	return 0
   135  }
   136  
   137  // Mining returns an indication if this node is currently mining.
   138  func (s *LightDummyAPI) Mining() bool {
   139  	return false
   140  }
   141  
   142  // APIs returns the collection of RPC services the ethereum package offers.
   143  // NOTE, some of these services probably need to be moved to somewhere else.
   144  func (s *LightEthereum) APIs() []rpc.API {
   145  	return append(ethapi.GetAPIs(s.ApiBackend, s.solcPath), []rpc.API{
   146  		{
   147  			Namespace: "eth",
   148  			Version:   "1.0",
   149  			Service:   &LightDummyAPI{},
   150  			Public:    true,
   151  		}, {
   152  			Namespace: "eth",
   153  			Version:   "1.0",
   154  			Service:   downloader.NewPublicDownloaderAPI(s.protocolManager.downloader, s.eventMux),
   155  			Public:    true,
   156  		}, {
   157  			Namespace: "eth",
   158  			Version:   "1.0",
   159  			Service:   filters.NewPublicFilterAPI(s.ApiBackend, true),
   160  			Public:    true,
   161  		}, {
   162  			Namespace: "net",
   163  			Version:   "1.0",
   164  			Service:   s.netRPCService,
   165  			Public:    true,
   166  		},
   167  	}...)
   168  }
   169  
   170  func (s *LightEthereum) ResetWithGenesisBlock(gb *types.Block) {
   171  	s.blockchain.ResetWithGenesisBlock(gb)
   172  }
   173  
   174  func (s *LightEthereum) BlockChain() *light.LightChain      { return s.blockchain }
   175  func (s *LightEthereum) TxPool() *light.TxPool              { return s.txPool }
   176  func (s *LightEthereum) LesVersion() int                    { return int(s.protocolManager.SubProtocols[0].Version) }
   177  func (s *LightEthereum) Downloader() *downloader.Downloader { return s.protocolManager.downloader }
   178  func (s *LightEthereum) EventMux() *event.TypeMux           { return s.eventMux }
   179  
   180  // Protocols implements node.Service, returning all the currently configured
   181  // network protocols to start.
   182  func (s *LightEthereum) Protocols() []p2p.Protocol {
   183  	return s.protocolManager.SubProtocols
   184  }
   185  
   186  // Start implements node.Service, starting all internal goroutines needed by the
   187  // Ethereum protocol implementation.
   188  func (s *LightEthereum) Start(srvr *p2p.Server) error {
   189  	log.Warn("Light client mode is an experimental feature")
   190  	s.netRPCService = ethapi.NewPublicNetAPI(srvr, s.netVersionId)
   191  	s.protocolManager.Start(srvr)
   192  	return nil
   193  }
   194  
   195  // Stop implements node.Service, terminating all internal goroutines used by the
   196  // Ethereum protocol.
   197  func (s *LightEthereum) Stop() error {
   198  	s.odr.Stop()
   199  	s.blockchain.Stop()
   200  	s.protocolManager.Stop()
   201  	s.txPool.Stop()
   202  
   203  	s.eventMux.Stop()
   204  
   205  	time.Sleep(time.Millisecond * 200)
   206  	s.chainDb.Close()
   207  	close(s.shutdownChan)
   208  
   209  	return nil
   210  }