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