github.com/bigzoro/my_simplechain@v0.0.0-20240315012955-8ad0a2a29bb9/les/client.go (about) 1 // Copyright 2016 The go-simplechain Authors 2 // This file is part of the go-simplechain library. 3 // 4 // The go-simplechain 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-simplechain 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-simplechain library. If not, see <http://www.gnu.org/licenses/>. 16 17 // Package les implements the Light SimpleService Subprotocol. 18 package les 19 20 import ( 21 "fmt" 22 23 "github.com/bigzoro/my_simplechain/accounts" 24 "github.com/bigzoro/my_simplechain/accounts/abi/bind" 25 "github.com/bigzoro/my_simplechain/common" 26 "github.com/bigzoro/my_simplechain/common/hexutil" 27 "github.com/bigzoro/my_simplechain/common/mclock" 28 "github.com/bigzoro/my_simplechain/consensus" 29 "github.com/bigzoro/my_simplechain/core" 30 "github.com/bigzoro/my_simplechain/core/bloombits" 31 "github.com/bigzoro/my_simplechain/core/rawdb" 32 "github.com/bigzoro/my_simplechain/core/types" 33 "github.com/bigzoro/my_simplechain/eth" 34 "github.com/bigzoro/my_simplechain/eth/downloader" 35 "github.com/bigzoro/my_simplechain/eth/filters" 36 "github.com/bigzoro/my_simplechain/eth/gasprice" 37 "github.com/bigzoro/my_simplechain/event" 38 "github.com/bigzoro/my_simplechain/internal/ethapi" 39 "github.com/bigzoro/my_simplechain/light" 40 "github.com/bigzoro/my_simplechain/log" 41 "github.com/bigzoro/my_simplechain/node" 42 "github.com/bigzoro/my_simplechain/p2p" 43 "github.com/bigzoro/my_simplechain/p2p/enode" 44 "github.com/bigzoro/my_simplechain/params" 45 "github.com/bigzoro/my_simplechain/rpc" 46 ) 47 48 type LightEthereum struct { 49 lesCommons 50 51 reqDist *requestDistributor 52 retriever *retrieveManager 53 odr *LesOdr 54 relay *lesTxRelay 55 handler *clientHandler 56 txPool *light.TxPool 57 blockchain *light.LightChain 58 serverPool *serverPool 59 60 bloomRequests chan chan *bloombits.Retrieval // Channel receiving bloom data retrieval requests 61 bloomIndexer *core.ChainIndexer // Bloom indexer operating during block imports 62 63 ApiBackend *LesApiBackend 64 eventMux *event.TypeMux 65 engine consensus.Engine 66 accountManager *accounts.Manager 67 netRPCService *ethapi.PublicNetAPI 68 } 69 70 func New(ctx *node.ServiceContext, config *eth.Config) (*LightEthereum, error) { 71 chainDb, err := ctx.OpenDatabase("lightchaindata", config.DatabaseCache, config.DatabaseHandles, "eth/db/chaindata/") 72 if err != nil { 73 return nil, err 74 } 75 chainConfig, genesisHash, genesisErr := core.SetupGenesisBlockWithOverride(chainDb, config.Genesis, config.OverrideSingularity) 76 if _, isCompat := genesisErr.(*params.ConfigCompatError); genesisErr != nil && !isCompat { 77 return nil, genesisErr 78 } 79 log.Info("Initialised chain configuration", "config", chainConfig) 80 81 peers := newPeerSet() 82 leth := &LightEthereum{ 83 lesCommons: lesCommons{ 84 genesis: genesisHash, 85 config: config, 86 chainConfig: chainConfig, 87 iConfig: light.DefaultClientIndexerConfig, 88 chainDb: chainDb, 89 peers: peers, 90 closeCh: make(chan struct{}), 91 }, 92 eventMux: ctx.EventMux, 93 reqDist: newRequestDistributor(peers, &mclock.System{}), 94 accountManager: ctx.AccountManager, 95 engine: eth.CreateConsensusEngine(ctx, chainConfig, config, nil, false, chainDb), 96 bloomRequests: make(chan chan *bloombits.Retrieval), 97 bloomIndexer: eth.NewBloomIndexer(chainDb, params.BloomBitsBlocksClient, params.HelperTrieConfirmations), 98 serverPool: newServerPool(chainDb, config.UltraLightServers), 99 } 100 leth.retriever = newRetrieveManager(peers, leth.reqDist, leth.serverPool) 101 leth.relay = newLesTxRelay(peers, leth.retriever) 102 103 leth.odr = NewLesOdr(chainDb, light.DefaultClientIndexerConfig, leth.retriever) 104 leth.chtIndexer = light.NewChtIndexer(chainDb, leth.odr, params.CHTFrequency, params.HelperTrieConfirmations) 105 leth.bloomTrieIndexer = light.NewBloomTrieIndexer(chainDb, leth.odr, params.BloomBitsBlocksClient, params.BloomTrieFrequency) 106 leth.odr.SetIndexers(leth.chtIndexer, leth.bloomTrieIndexer, leth.bloomIndexer) 107 108 checkpoint := config.Checkpoint 109 if checkpoint == nil { 110 checkpoint = params.TrustedCheckpoints[genesisHash] 111 } 112 // Note: NewLightChain adds the trusted checkpoint so it needs an ODR with 113 // indexers already set but not started yet 114 if leth.blockchain, err = light.NewLightChain(leth.odr, leth.chainConfig, leth.engine, checkpoint); err != nil { 115 return nil, err 116 } 117 leth.chainReader = leth.blockchain 118 leth.txPool = light.NewTxPool(leth.chainConfig, leth.blockchain, leth.relay) 119 120 // Set up checkpoint oracle. 121 oracle := config.CheckpointOracle 122 if oracle == nil { 123 oracle = params.CheckpointOracles[genesisHash] 124 } 125 leth.oracle = newCheckpointOracle(oracle, leth.localCheckpoint) 126 127 // Note: AddChildIndexer starts the update process for the child 128 leth.bloomIndexer.AddChildIndexer(leth.bloomTrieIndexer) 129 leth.chtIndexer.Start(leth.blockchain) 130 leth.bloomIndexer.Start(leth.blockchain) 131 132 leth.handler = newClientHandler(config.UltraLightServers, config.UltraLightFraction, checkpoint, leth) 133 if leth.handler.ulc != nil { 134 log.Warn("Ultra light client is enabled", "trustedNodes", len(leth.handler.ulc.keys), "minTrustedFraction", leth.handler.ulc.fraction) 135 leth.blockchain.DisableCheckFreq() 136 } 137 // Rewind the chain in case of an incompatible config upgrade. 138 if compat, ok := genesisErr.(*params.ConfigCompatError); ok { 139 log.Warn("Rewinding chain to upgrade configuration", "err", compat) 140 leth.blockchain.SetHead(compat.RewindTo) 141 rawdb.WriteChainConfig(chainDb, genesisHash, chainConfig) 142 } 143 144 leth.ApiBackend = &LesApiBackend{ctx.ExtRPCEnabled(), leth, nil} 145 gpoParams := config.GPO 146 if gpoParams.Default == nil { 147 gpoParams.Default = config.Miner.GasPrice 148 } 149 leth.ApiBackend.gpo = gasprice.NewOracle(leth.ApiBackend, gpoParams) 150 151 return leth, nil 152 } 153 154 type LightDummyAPI struct{} 155 156 // Etherbase is the address that mining rewards will be send to 157 func (s *LightDummyAPI) Etherbase() (common.Address, error) { 158 return common.Address{}, fmt.Errorf("mining is not supported in light mode") 159 } 160 161 // Coinbase is the address that mining rewards will be send to (alias for Etherbase) 162 func (s *LightDummyAPI) Coinbase() (common.Address, error) { 163 return common.Address{}, fmt.Errorf("mining is not supported in light mode") 164 } 165 166 // Hashrate returns the POW hashrate 167 func (s *LightDummyAPI) Hashrate() hexutil.Uint { 168 return 0 169 } 170 171 // Mining returns an indication if this node is currently mining. 172 func (s *LightDummyAPI) Mining() bool { 173 return false 174 } 175 176 // APIs returns the collection of RPC services the ethereum package offers. 177 // NOTE, some of these services probably need to be moved to somewhere else. 178 func (s *LightEthereum) APIs() []rpc.API { 179 apis := ethapi.GetAPIs(s.ApiBackend) 180 apis = append(apis, s.engine.APIs(s.BlockChain().HeaderChain())...) 181 return append(apis, []rpc.API{ 182 { 183 Namespace: "eth", 184 Version: "1.0", 185 Service: &LightDummyAPI{}, 186 Public: true, 187 }, { 188 Namespace: "eth", 189 Version: "1.0", 190 Service: downloader.NewPublicDownloaderAPI(s.handler.downloader, s.eventMux), 191 Public: true, 192 }, { 193 Namespace: "eth", 194 Version: "1.0", 195 Service: filters.NewPublicFilterAPI(s.ApiBackend, true), 196 Public: true, 197 }, { 198 Namespace: "net", 199 Version: "1.0", 200 Service: s.netRPCService, 201 Public: true, 202 }, { 203 Namespace: "les", 204 Version: "1.0", 205 Service: NewPrivateLightAPI(&s.lesCommons), 206 Public: false, 207 }, 208 }...) 209 } 210 211 func (s *LightEthereum) ResetWithGenesisBlock(gb *types.Block) { 212 s.blockchain.ResetWithGenesisBlock(gb) 213 } 214 215 func (s *LightEthereum) BlockChain() *light.LightChain { return s.blockchain } 216 func (s *LightEthereum) TxPool() *light.TxPool { return s.txPool } 217 func (s *LightEthereum) Engine() consensus.Engine { return s.engine } 218 func (s *LightEthereum) LesVersion() int { return int(ClientProtocolVersions[0]) } 219 func (s *LightEthereum) Downloader() *downloader.Downloader { return s.handler.downloader } 220 func (s *LightEthereum) EventMux() *event.TypeMux { return s.eventMux } 221 222 // Protocols implements node.Service, returning all the currently configured 223 // network protocols to start. 224 func (s *LightEthereum) Protocols() []p2p.Protocol { 225 return s.makeProtocols(ClientProtocolVersions, s.handler.runPeer, func(id enode.ID) interface{} { 226 if p := s.peers.Peer(peerIdToString(id)); p != nil { 227 return p.Info() 228 } 229 return nil 230 }) 231 } 232 233 // Start implements node.Service, starting all internal goroutines needed by the 234 // light ethereum protocol implementation. 235 func (s *LightEthereum) Start(srvr *p2p.Server) error { 236 log.Warn("Light client mode is an experimental feature") 237 238 // Start bloom request workers. 239 s.wg.Add(bloomServiceThreads) 240 s.startBloomHandlers(params.BloomBitsBlocksClient) 241 242 s.netRPCService = ethapi.NewPublicNetAPI(srvr, s.config.NetworkId) 243 244 // clients are searching for the first advertised protocol in the list 245 protocolVersion := AdvertiseProtocolVersions[0] 246 s.serverPool.start(srvr, lesTopic(s.blockchain.Genesis().Hash(), protocolVersion)) 247 return nil 248 } 249 250 // Stop implements node.Service, terminating all internal goroutines used by the 251 // SimpleService protocol. 252 func (s *LightEthereum) Stop() error { 253 close(s.closeCh) 254 s.peers.Close() 255 s.reqDist.close() 256 s.odr.Stop() 257 s.relay.Stop() 258 s.bloomIndexer.Close() 259 s.chtIndexer.Close() 260 s.blockchain.Stop() 261 s.handler.stop() 262 s.txPool.Stop() 263 s.engine.Close() 264 s.eventMux.Stop() 265 s.serverPool.stop() 266 s.chainDb.Close() 267 s.wg.Wait() 268 log.Info("Light ethereum stopped") 269 return nil 270 } 271 272 // SetClient sets the rpc client and binds the registrar contract. 273 func (s *LightEthereum) SetContractBackend(backend bind.ContractBackend) { 274 if s.oracle == nil { 275 return 276 } 277 s.oracle.start(backend) 278 }