github.com/arieschain/arieschain@v0.0.0-20191023063405-37c074544356/les/backend.go (about) 1 // Package les implements the Light Ethereum Subprotocol. 2 package les 3 4 import ( 5 "fmt" 6 "sync" 7 "time" 8 9 "github.com/quickchainproject/quickchain/accounts" 10 "github.com/quickchainproject/quickchain/common" 11 "github.com/quickchainproject/quickchain/common/hexutil" 12 "github.com/quickchainproject/quickchain/consensus" 13 "github.com/quickchainproject/quickchain/core" 14 "github.com/quickchainproject/quickchain/core/bloombits" 15 "github.com/quickchainproject/quickchain/core/types" 16 "github.com/quickchainproject/quickchain/event" 17 "github.com/quickchainproject/quickchain/internal/qctapi" 18 "github.com/quickchainproject/quickchain/qct" 19 "github.com/quickchainproject/quickchain/qct/downloader" 20 "github.com/quickchainproject/quickchain/qct/filters" 21 "github.com/quickchainproject/quickchain/qct/gasprice" 22 "github.com/quickchainproject/quickchain/qctdb" 23 "github.com/quickchainproject/quickchain/light" 24 "github.com/quickchainproject/quickchain/log" 25 "github.com/quickchainproject/quickchain/node" 26 "github.com/quickchainproject/quickchain/p2p" 27 "github.com/quickchainproject/quickchain/p2p/discv5" 28 "github.com/quickchainproject/quickchain/params" 29 rpc "github.com/quickchainproject/quickchain/rpc" 30 ) 31 32 type LightEthereum struct { 33 config *qct.Config 34 35 odr *LesOdr 36 relay *LesTxRelay 37 chainConfig *params.ChainConfig 38 // Channel for shutting down the service 39 shutdownChan chan bool 40 // Handlers 41 peers *peerSet 42 txPool *light.TxPool 43 blockchain *light.LightChain 44 protocolManager *ProtocolManager 45 serverPool *serverPool 46 reqDist *requestDistributor 47 retriever *retrieveManager 48 // DB interfaces 49 chainDb qctdb.Database // Block chain database 50 51 bloomRequests chan chan *bloombits.Retrieval // Channel receiving bloom data retrieval requests 52 bloomIndexer, chtIndexer, bloomTrieIndexer *core.ChainIndexer 53 54 ApiBackend *LesApiBackend 55 56 eventMux *event.TypeMux 57 engine consensus.Engine 58 accountManager *accounts.Manager 59 60 networkId uint64 61 netRPCService *qctapi.PublicNetAPI 62 63 wg sync.WaitGroup 64 } 65 66 func New(ctx *node.ServiceContext, config *qct.Config) (*LightEthereum, error) { 67 chainDb, err := qct.CreateDB(ctx, config, "lightchaindata") 68 if err != nil { 69 return nil, err 70 } 71 chainConfig, genesisHash, genesisErr := core.SetupGenesisBlock(chainDb, config.Genesis) 72 if _, isCompat := genesisErr.(*params.ConfigCompatError); genesisErr != nil && !isCompat { 73 return nil, genesisErr 74 } 75 log.Info("Initialised chain configuration", "config", chainConfig) 76 77 peers := newPeerSet() 78 quitSync := make(chan struct{}) 79 80 leth := &LightEthereum{ 81 config: config, 82 chainConfig: chainConfig, 83 chainDb: chainDb, 84 eventMux: ctx.EventMux, 85 peers: peers, 86 reqDist: newRequestDistributor(peers, quitSync), 87 accountManager: ctx.AccountManager, 88 engine: qct.CreateConsensusEngine(ctx, config, chainConfig, chainDb), 89 shutdownChan: make(chan bool), 90 networkId: config.NetworkId, 91 bloomRequests: make(chan chan *bloombits.Retrieval), 92 bloomIndexer: qct.NewBloomIndexer(chainDb, light.BloomTrieFrequency), 93 chtIndexer: light.NewChtIndexer(chainDb, true), 94 bloomTrieIndexer: light.NewBloomTrieIndexer(chainDb, true), 95 } 96 97 leth.relay = NewLesTxRelay(peers, leth.reqDist) 98 leth.serverPool = newServerPool(chainDb, quitSync, &leth.wg) 99 leth.retriever = newRetrieveManager(peers, leth.reqDist, leth.serverPool) 100 leth.odr = NewLesOdr(chainDb, leth.chtIndexer, leth.bloomTrieIndexer, leth.bloomIndexer, leth.retriever) 101 if leth.blockchain, err = light.NewLightChain(leth.odr, leth.chainConfig, leth.engine); err != nil { 102 return nil, err 103 } 104 leth.bloomIndexer.Start(leth.blockchain) 105 // Rewind the chain in case of an incompatible config upgrade. 106 if compat, ok := genesisErr.(*params.ConfigCompatError); ok { 107 log.Warn("Rewinding chain to upgrade configuration", "err", compat) 108 leth.blockchain.SetHead(compat.RewindTo) 109 core.WriteChainConfig(chainDb, genesisHash, chainConfig) 110 } 111 112 leth.txPool = light.NewTxPool(leth.chainConfig, leth.blockchain, leth.relay) 113 if leth.protocolManager, err = NewProtocolManager(leth.chainConfig, true, ClientProtocolVersions, config.NetworkId, leth.eventMux, leth.engine, leth.peers, leth.blockchain, nil, chainDb, leth.odr, leth.relay, quitSync, &leth.wg); err != nil { 114 return nil, err 115 } 116 leth.ApiBackend = &LesApiBackend{leth, nil} 117 gpoParams := config.GPO 118 if gpoParams.Default == nil { 119 gpoParams.Default = config.GasPrice 120 } 121 leth.ApiBackend.gpo = gasprice.NewOracle(leth.ApiBackend, gpoParams) 122 return leth, nil 123 } 124 125 func lesTopic(genesisHash common.Hash, protocolVersion uint) discv5.Topic { 126 var name string 127 switch protocolVersion { 128 case lpv1: 129 name = "LES" 130 case lpv2: 131 name = "LES2" 132 default: 133 panic(nil) 134 } 135 return discv5.Topic(name + "@" + common.Bytes2Hex(genesisHash.Bytes()[0:8])) 136 } 137 138 type LightDummyAPI struct{} 139 140 // Etherbase is the address that mining rewards will be send to 141 func (s *LightDummyAPI) Etherbase() (common.Address, error) { 142 return common.Address{}, fmt.Errorf("not supported") 143 } 144 145 // Coinbase is the address that mining rewards will be send to (alias for Etherbase) 146 func (s *LightDummyAPI) Coinbase() (common.Address, error) { 147 return common.Address{}, fmt.Errorf("not supported") 148 } 149 150 // Hashrate returns the POW hashrate 151 func (s *LightDummyAPI) Hashrate() hexutil.Uint { 152 return 0 153 } 154 155 // Mining returns an indication if this node is currently mining. 156 func (s *LightDummyAPI) Mining() bool { 157 return false 158 } 159 160 // APIs returns the collection of RPC services the quickchain package offers. 161 // NOTE, some of these services probably need to be moved to somewhere else. 162 func (s *LightEthereum) APIs() []rpc.API { 163 return append(qctapi.GetAPIs(s.ApiBackend), []rpc.API{ 164 { 165 Namespace: "eth", 166 Version: "1.0", 167 Service: &LightDummyAPI{}, 168 Public: true, 169 }, { 170 Namespace: "eth", 171 Version: "1.0", 172 Service: downloader.NewPublicDownloaderAPI(s.protocolManager.downloader, s.eventMux), 173 Public: true, 174 }, { 175 Namespace: "eth", 176 Version: "1.0", 177 Service: filters.NewPublicFilterAPI(s.ApiBackend, true), 178 Public: true, 179 }, { 180 Namespace: "net", 181 Version: "1.0", 182 Service: s.netRPCService, 183 Public: true, 184 }, 185 }...) 186 } 187 188 func (s *LightEthereum) ResetWithGenesisBlock(gb *types.Block) { 189 s.blockchain.ResetWithGenesisBlock(gb) 190 } 191 192 func (s *LightEthereum) BlockChain() *light.LightChain { return s.blockchain } 193 func (s *LightEthereum) TxPool() *light.TxPool { return s.txPool } 194 func (s *LightEthereum) Engine() consensus.Engine { return s.engine } 195 func (s *LightEthereum) LesVersion() int { return int(s.protocolManager.SubProtocols[0].Version) } 196 func (s *LightEthereum) Downloader() *downloader.Downloader { return s.protocolManager.downloader } 197 func (s *LightEthereum) EventMux() *event.TypeMux { return s.eventMux } 198 199 // Protocols implements node.Service, returning all the currently configured 200 // network protocols to start. 201 func (s *LightEthereum) Protocols() []p2p.Protocol { 202 return s.protocolManager.SubProtocols 203 } 204 205 // Start implements node.Service, starting all internal goroutines needed by the 206 // Ethereum protocol implementation. 207 func (s *LightEthereum) Start(srvr *p2p.Server) error { 208 s.startBloomHandlers() 209 log.Warn("Light client mode is an experimental feature") 210 s.netRPCService = qctapi.NewPublicNetAPI(srvr, s.networkId) 211 // clients are searching for the first advertised protocol in the list 212 protocolVersion := AdvertiseProtocolVersions[0] 213 s.serverPool.start(srvr, lesTopic(s.blockchain.Genesis().Hash(), protocolVersion)) 214 s.protocolManager.Start(s.config.LightPeers) 215 return nil 216 } 217 218 // Stop implements node.Service, terminating all internal goroutines used by the 219 // Ethereum protocol. 220 func (s *LightEthereum) Stop() error { 221 s.odr.Stop() 222 if s.bloomIndexer != nil { 223 s.bloomIndexer.Close() 224 } 225 if s.chtIndexer != nil { 226 s.chtIndexer.Close() 227 } 228 if s.bloomTrieIndexer != nil { 229 s.bloomTrieIndexer.Close() 230 } 231 s.blockchain.Stop() 232 s.protocolManager.Stop() 233 s.txPool.Stop() 234 235 s.eventMux.Stop() 236 237 time.Sleep(time.Millisecond * 200) 238 s.chainDb.Close() 239 close(s.shutdownChan) 240 241 return nil 242 }