gitee.com/liu-zhao234568/cntest@v1.0.0/eth/backend.go (about) 1 // Copyright 2014 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 eth implements the Ethereum protocol. 18 package eth 19 20 import ( 21 "errors" 22 "fmt" 23 "math/big" 24 "runtime" 25 "sync" 26 "sync/atomic" 27 "time" 28 29 "gitee.com/liu-zhao234568/cntest/accounts" 30 "gitee.com/liu-zhao234568/cntest/common" 31 "gitee.com/liu-zhao234568/cntest/common/hexutil" 32 "gitee.com/liu-zhao234568/cntest/consensus" 33 "gitee.com/liu-zhao234568/cntest/consensus/clique" 34 "gitee.com/liu-zhao234568/cntest/core" 35 "gitee.com/liu-zhao234568/cntest/core/bloombits" 36 "gitee.com/liu-zhao234568/cntest/core/rawdb" 37 "gitee.com/liu-zhao234568/cntest/core/state/pruner" 38 "gitee.com/liu-zhao234568/cntest/core/types" 39 "gitee.com/liu-zhao234568/cntest/core/vm" 40 "gitee.com/liu-zhao234568/cntest/eth/downloader" 41 "gitee.com/liu-zhao234568/cntest/eth/ethconfig" 42 "gitee.com/liu-zhao234568/cntest/eth/filters" 43 "gitee.com/liu-zhao234568/cntest/eth/gasprice" 44 "gitee.com/liu-zhao234568/cntest/eth/protocols/eth" 45 "gitee.com/liu-zhao234568/cntest/eth/protocols/snap" 46 "gitee.com/liu-zhao234568/cntest/ethdb" 47 "gitee.com/liu-zhao234568/cntest/event" 48 "gitee.com/liu-zhao234568/cntest/internal/ethapi" 49 "gitee.com/liu-zhao234568/cntest/log" 50 "gitee.com/liu-zhao234568/cntest/miner" 51 "gitee.com/liu-zhao234568/cntest/node" 52 "gitee.com/liu-zhao234568/cntest/p2p" 53 "gitee.com/liu-zhao234568/cntest/p2p/dnsdisc" 54 "gitee.com/liu-zhao234568/cntest/p2p/enode" 55 "gitee.com/liu-zhao234568/cntest/params" 56 "gitee.com/liu-zhao234568/cntest/rlp" 57 "gitee.com/liu-zhao234568/cntest/rpc" 58 ) 59 60 // Config contains the configuration options of the ETH protocol. 61 // Deprecated: use ethconfig.Config instead. 62 type Config = ethconfig.Config 63 64 // Ethereum implements the Ethereum full node service. 65 type Ethereum struct { 66 config *ethconfig.Config 67 68 // Handlers 69 txPool *core.TxPool 70 blockchain *core.BlockChain 71 handler *handler 72 ethDialCandidates enode.Iterator 73 snapDialCandidates enode.Iterator 74 75 // DB interfaces 76 chainDb ethdb.Database // Block chain database 77 78 eventMux *event.TypeMux 79 engine consensus.Engine 80 accountManager *accounts.Manager 81 82 bloomRequests chan chan *bloombits.Retrieval // Channel receiving bloom data retrieval requests 83 bloomIndexer *core.ChainIndexer // Bloom indexer operating during block imports 84 closeBloomHandler chan struct{} 85 86 APIBackend *EthAPIBackend 87 88 miner *miner.Miner 89 gasPrice *big.Int 90 etherbase common.Address 91 92 networkID uint64 93 netRPCService *ethapi.PublicNetAPI 94 95 p2pServer *p2p.Server 96 97 lock sync.RWMutex // Protects the variadic fields (e.g. gas price and etherbase) 98 } 99 100 // New creates a new Ethereum object (including the 101 // initialisation of the common Ethereum object) 102 func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) { 103 // Ensure configuration values are compatible and sane 104 if config.SyncMode == downloader.LightSync { 105 return nil, errors.New("can't run eth.Ethereum in light sync mode, use les.LightEthereum") 106 } 107 if !config.SyncMode.IsValid() { 108 return nil, fmt.Errorf("invalid sync mode %d", config.SyncMode) 109 } 110 if config.Miner.GasPrice == nil || config.Miner.GasPrice.Cmp(common.Big0) <= 0 { 111 log.Warn("Sanitizing invalid miner gas price", "provided", config.Miner.GasPrice, "updated", ethconfig.Defaults.Miner.GasPrice) 112 config.Miner.GasPrice = new(big.Int).Set(ethconfig.Defaults.Miner.GasPrice) 113 } 114 if config.NoPruning && config.TrieDirtyCache > 0 { 115 if config.SnapshotCache > 0 { 116 config.TrieCleanCache += config.TrieDirtyCache * 3 / 5 117 config.SnapshotCache += config.TrieDirtyCache * 2 / 5 118 } else { 119 config.TrieCleanCache += config.TrieDirtyCache 120 } 121 config.TrieDirtyCache = 0 122 } 123 log.Info("Allocated trie memory caches", "clean", common.StorageSize(config.TrieCleanCache)*1024*1024, "dirty", common.StorageSize(config.TrieDirtyCache)*1024*1024) 124 125 // Transfer mining-related config to the ethash config. 126 ethashConfig := config.Ethash 127 ethashConfig.NotifyFull = config.Miner.NotifyFull 128 129 // Assemble the Ethereum object 130 chainDb, err := stack.OpenDatabaseWithFreezer("chaindata", config.DatabaseCache, config.DatabaseHandles, config.DatabaseFreezer, "eth/db/chaindata/", false) 131 if err != nil { 132 return nil, err 133 } 134 chainConfig, genesisHash, genesisErr := core.SetupGenesisBlockWithOverride(chainDb, config.Genesis, config.OverrideLondon) 135 if _, ok := genesisErr.(*params.ConfigCompatError); genesisErr != nil && !ok { 136 return nil, genesisErr 137 } 138 log.Info("Initialised chain configuration", "config", chainConfig) 139 140 if err := pruner.RecoverPruning(stack.ResolvePath(""), chainDb, stack.ResolvePath(config.TrieCleanCacheJournal)); err != nil { 141 log.Error("Failed to recover state", "error", err) 142 } 143 eth := &Ethereum{ 144 config: config, 145 chainDb: chainDb, 146 eventMux: stack.EventMux(), 147 accountManager: stack.AccountManager(), 148 engine: ethconfig.CreateConsensusEngine(stack, chainConfig, ðashConfig, config.Miner.Notify, config.Miner.Noverify, chainDb), 149 closeBloomHandler: make(chan struct{}), 150 networkID: config.NetworkId, 151 gasPrice: config.Miner.GasPrice, 152 etherbase: config.Miner.Etherbase, 153 bloomRequests: make(chan chan *bloombits.Retrieval), 154 bloomIndexer: core.NewBloomIndexer(chainDb, params.BloomBitsBlocks, params.BloomConfirms), 155 p2pServer: stack.Server(), 156 } 157 158 bcVersion := rawdb.ReadDatabaseVersion(chainDb) 159 var dbVer = "<nil>" 160 if bcVersion != nil { 161 dbVer = fmt.Sprintf("%d", *bcVersion) 162 } 163 log.Info("Initialising Ethereum protocol", "network", config.NetworkId, "dbversion", dbVer) 164 165 if !config.SkipBcVersionCheck { 166 if bcVersion != nil && *bcVersion > core.BlockChainVersion { 167 return nil, fmt.Errorf("database version is v%d, Geth %s only supports v%d", *bcVersion, params.VersionWithMeta, core.BlockChainVersion) 168 } else if bcVersion == nil || *bcVersion < core.BlockChainVersion { 169 if bcVersion != nil { // only print warning on upgrade, not on init 170 log.Warn("Upgrade blockchain database version", "from", dbVer, "to", core.BlockChainVersion) 171 } 172 rawdb.WriteDatabaseVersion(chainDb, core.BlockChainVersion) 173 } 174 } 175 var ( 176 vmConfig = vm.Config{ 177 EnablePreimageRecording: config.EnablePreimageRecording, 178 } 179 cacheConfig = &core.CacheConfig{ 180 TrieCleanLimit: config.TrieCleanCache, 181 TrieCleanJournal: stack.ResolvePath(config.TrieCleanCacheJournal), 182 TrieCleanRejournal: config.TrieCleanCacheRejournal, 183 TrieCleanNoPrefetch: config.NoPrefetch, 184 TrieDirtyLimit: config.TrieDirtyCache, 185 TrieDirtyDisabled: config.NoPruning, 186 TrieTimeLimit: config.TrieTimeout, 187 SnapshotLimit: config.SnapshotCache, 188 Preimages: config.Preimages, 189 } 190 ) 191 eth.blockchain, err = core.NewBlockChain(chainDb, cacheConfig, chainConfig, eth.engine, vmConfig, eth.shouldPreserve, &config.TxLookupLimit) 192 if err != nil { 193 return nil, err 194 } 195 // Rewind the chain in case of an incompatible config upgrade. 196 if compat, ok := genesisErr.(*params.ConfigCompatError); ok { 197 log.Warn("Rewinding chain to upgrade configuration", "err", compat) 198 eth.blockchain.SetHead(compat.RewindTo) 199 rawdb.WriteChainConfig(chainDb, genesisHash, chainConfig) 200 } 201 eth.bloomIndexer.Start(eth.blockchain) 202 203 if config.TxPool.Journal != "" { 204 config.TxPool.Journal = stack.ResolvePath(config.TxPool.Journal) 205 } 206 eth.txPool = core.NewTxPool(config.TxPool, chainConfig, eth.blockchain) 207 208 // Permit the downloader to use the trie cache allowance during fast sync 209 cacheLimit := cacheConfig.TrieCleanLimit + cacheConfig.TrieDirtyLimit + cacheConfig.SnapshotLimit 210 checkpoint := config.Checkpoint 211 if checkpoint == nil { 212 checkpoint = params.TrustedCheckpoints[genesisHash] 213 } 214 if eth.handler, err = newHandler(&handlerConfig{ 215 Database: chainDb, 216 Chain: eth.blockchain, 217 TxPool: eth.txPool, 218 Network: config.NetworkId, 219 Sync: config.SyncMode, 220 BloomCache: uint64(cacheLimit), 221 EventMux: eth.eventMux, 222 Checkpoint: checkpoint, 223 Whitelist: config.Whitelist, 224 }); err != nil { 225 return nil, err 226 } 227 228 eth.miner = miner.New(eth, &config.Miner, chainConfig, eth.EventMux(), eth.engine, eth.isLocalBlock) 229 eth.miner.SetExtra(makeExtraData(config.Miner.ExtraData)) 230 231 eth.APIBackend = &EthAPIBackend{stack.Config().ExtRPCEnabled(), stack.Config().AllowUnprotectedTxs, eth, nil} 232 if eth.APIBackend.allowUnprotectedTxs { 233 log.Info("Unprotected transactions allowed") 234 } 235 gpoParams := config.GPO 236 if gpoParams.Default == nil { 237 gpoParams.Default = config.Miner.GasPrice 238 } 239 eth.APIBackend.gpo = gasprice.NewOracle(eth.APIBackend, gpoParams) 240 241 // Setup DNS discovery iterators. 242 dnsclient := dnsdisc.NewClient(dnsdisc.Config{}) 243 eth.ethDialCandidates, err = dnsclient.NewIterator(eth.config.EthDiscoveryURLs...) 244 if err != nil { 245 return nil, err 246 } 247 eth.snapDialCandidates, err = dnsclient.NewIterator(eth.config.SnapDiscoveryURLs...) 248 if err != nil { 249 return nil, err 250 } 251 252 // Start the RPC service 253 eth.netRPCService = ethapi.NewPublicNetAPI(eth.p2pServer, config.NetworkId) 254 255 // Register the backend on the node 256 stack.RegisterAPIs(eth.APIs()) 257 stack.RegisterProtocols(eth.Protocols()) 258 stack.RegisterLifecycle(eth) 259 // Check for unclean shutdown 260 if uncleanShutdowns, discards, err := rawdb.PushUncleanShutdownMarker(chainDb); err != nil { 261 log.Error("Could not update unclean-shutdown-marker list", "error", err) 262 } else { 263 if discards > 0 { 264 log.Warn("Old unclean shutdowns found", "count", discards) 265 } 266 for _, tstamp := range uncleanShutdowns { 267 t := time.Unix(int64(tstamp), 0) 268 log.Warn("Unclean shutdown detected", "booted", t, 269 "age", common.PrettyAge(t)) 270 } 271 } 272 return eth, nil 273 } 274 275 func makeExtraData(extra []byte) []byte { 276 if len(extra) == 0 { 277 // create default extradata 278 extra, _ = rlp.EncodeToBytes([]interface{}{ 279 uint(params.VersionMajor<<16 | params.VersionMinor<<8 | params.VersionPatch), 280 "geth", 281 runtime.Version(), 282 runtime.GOOS, 283 }) 284 } 285 if uint64(len(extra)) > params.MaximumExtraDataSize { 286 log.Warn("Miner extra data exceed limit", "extra", hexutil.Bytes(extra), "limit", params.MaximumExtraDataSize) 287 extra = nil 288 } 289 return extra 290 } 291 292 // APIs return the collection of RPC services the ethereum package offers. 293 // NOTE, some of these services probably need to be moved to somewhere else. 294 func (s *Ethereum) APIs() []rpc.API { 295 apis := ethapi.GetAPIs(s.APIBackend) 296 297 // Append any APIs exposed explicitly by the consensus engine 298 apis = append(apis, s.engine.APIs(s.BlockChain())...) 299 300 // Append all the local APIs and return 301 return append(apis, []rpc.API{ 302 { 303 Namespace: "eth", 304 Version: "1.0", 305 Service: NewPublicEthereumAPI(s), 306 Public: true, 307 }, { 308 Namespace: "eth", 309 Version: "1.0", 310 Service: NewPublicMinerAPI(s), 311 Public: true, 312 }, { 313 Namespace: "eth", 314 Version: "1.0", 315 Service: downloader.NewPublicDownloaderAPI(s.handler.downloader, s.eventMux), 316 Public: true, 317 }, { 318 Namespace: "miner", 319 Version: "1.0", 320 Service: NewPrivateMinerAPI(s), 321 Public: false, 322 }, { 323 Namespace: "eth", 324 Version: "1.0", 325 Service: filters.NewPublicFilterAPI(s.APIBackend, false, 5*time.Minute), 326 Public: true, 327 }, { 328 Namespace: "admin", 329 Version: "1.0", 330 Service: NewPrivateAdminAPI(s), 331 }, { 332 Namespace: "debug", 333 Version: "1.0", 334 Service: NewPublicDebugAPI(s), 335 Public: true, 336 }, { 337 Namespace: "debug", 338 Version: "1.0", 339 Service: NewPrivateDebugAPI(s), 340 }, { 341 Namespace: "net", 342 Version: "1.0", 343 Service: s.netRPCService, 344 Public: true, 345 }, 346 }...) 347 } 348 349 func (s *Ethereum) ResetWithGenesisBlock(gb *types.Block) { 350 s.blockchain.ResetWithGenesisBlock(gb) 351 } 352 353 func (s *Ethereum) Etherbase() (eb common.Address, err error) { 354 s.lock.RLock() 355 etherbase := s.etherbase 356 s.lock.RUnlock() 357 358 if etherbase != (common.Address{}) { 359 return etherbase, nil 360 } 361 if wallets := s.AccountManager().Wallets(); len(wallets) > 0 { 362 if accounts := wallets[0].Accounts(); len(accounts) > 0 { 363 etherbase := accounts[0].Address 364 365 s.lock.Lock() 366 s.etherbase = etherbase 367 s.lock.Unlock() 368 369 log.Info("Etherbase automatically configured", "address", etherbase) 370 return etherbase, nil 371 } 372 } 373 return common.Address{}, fmt.Errorf("etherbase must be explicitly specified") 374 } 375 376 // isLocalBlock checks whether the specified block is mined 377 // by local miner accounts. 378 // 379 // We regard two types of accounts as local miner account: etherbase 380 // and accounts specified via `txpool.locals` flag. 381 func (s *Ethereum) isLocalBlock(block *types.Block) bool { 382 author, err := s.engine.Author(block.Header()) 383 if err != nil { 384 log.Warn("Failed to retrieve block author", "number", block.NumberU64(), "hash", block.Hash(), "err", err) 385 return false 386 } 387 // Check whether the given address is etherbase. 388 s.lock.RLock() 389 etherbase := s.etherbase 390 s.lock.RUnlock() 391 if author == etherbase { 392 return true 393 } 394 // Check whether the given address is specified by `txpool.local` 395 // CLI flag. 396 for _, account := range s.config.TxPool.Locals { 397 if account == author { 398 return true 399 } 400 } 401 return false 402 } 403 404 // shouldPreserve checks whether we should preserve the given block 405 // during the chain reorg depending on whether the author of block 406 // is a local account. 407 func (s *Ethereum) shouldPreserve(block *types.Block) bool { 408 // The reason we need to disable the self-reorg preserving for clique 409 // is it can be probable to introduce a deadlock. 410 // 411 // e.g. If there are 7 available signers 412 // 413 // r1 A 414 // r2 B 415 // r3 C 416 // r4 D 417 // r5 A [X] F G 418 // r6 [X] 419 // 420 // In the round5, the inturn signer E is offline, so the worst case 421 // is A, F and G sign the block of round5 and reject the block of opponents 422 // and in the round6, the last available signer B is offline, the whole 423 // network is stuck. 424 if _, ok := s.engine.(*clique.Clique); ok { 425 return false 426 } 427 return s.isLocalBlock(block) 428 } 429 430 // SetEtherbase sets the mining reward address. 431 func (s *Ethereum) SetEtherbase(etherbase common.Address) { 432 s.lock.Lock() 433 s.etherbase = etherbase 434 s.lock.Unlock() 435 436 s.miner.SetEtherbase(etherbase) 437 } 438 439 // StartMining starts the miner with the given number of CPU threads. If mining 440 // is already running, this method adjust the number of threads allowed to use 441 // and updates the minimum price required by the transaction pool. 442 func (s *Ethereum) StartMining(threads int) error { 443 // Update the thread count within the consensus engine 444 type threaded interface { 445 SetThreads(threads int) 446 } 447 if th, ok := s.engine.(threaded); ok { 448 log.Info("Updated mining threads", "threads", threads) 449 if threads == 0 { 450 threads = -1 // Disable the miner from within 451 } 452 th.SetThreads(threads) 453 } 454 // If the miner was not running, initialize it 455 if !s.IsMining() { 456 // Propagate the initial price point to the transaction pool 457 s.lock.RLock() 458 price := s.gasPrice 459 s.lock.RUnlock() 460 s.txPool.SetGasPrice(price) 461 462 // Configure the local mining address 463 eb, err := s.Etherbase() 464 if err != nil { 465 log.Error("Cannot start mining without etherbase", "err", err) 466 return fmt.Errorf("etherbase missing: %v", err) 467 } 468 if clique, ok := s.engine.(*clique.Clique); ok { 469 wallet, err := s.accountManager.Find(accounts.Account{Address: eb}) 470 if wallet == nil || err != nil { 471 log.Error("Etherbase account unavailable locally", "err", err) 472 return fmt.Errorf("signer missing: %v", err) 473 } 474 clique.Authorize(eb, wallet.SignData) 475 } 476 // If mining is started, we can disable the transaction rejection mechanism 477 // introduced to speed sync times. 478 atomic.StoreUint32(&s.handler.acceptTxs, 1) 479 480 go s.miner.Start(eb) 481 } 482 return nil 483 } 484 485 // StopMining terminates the miner, both at the consensus engine level as well as 486 // at the block creation level. 487 func (s *Ethereum) StopMining() { 488 // Update the thread count within the consensus engine 489 type threaded interface { 490 SetThreads(threads int) 491 } 492 if th, ok := s.engine.(threaded); ok { 493 th.SetThreads(-1) 494 } 495 // Stop the block creating itself 496 s.miner.Stop() 497 } 498 499 func (s *Ethereum) IsMining() bool { return s.miner.Mining() } 500 func (s *Ethereum) Miner() *miner.Miner { return s.miner } 501 502 func (s *Ethereum) AccountManager() *accounts.Manager { return s.accountManager } 503 func (s *Ethereum) BlockChain() *core.BlockChain { return s.blockchain } 504 func (s *Ethereum) TxPool() *core.TxPool { return s.txPool } 505 func (s *Ethereum) EventMux() *event.TypeMux { return s.eventMux } 506 func (s *Ethereum) Engine() consensus.Engine { return s.engine } 507 func (s *Ethereum) ChainDb() ethdb.Database { return s.chainDb } 508 func (s *Ethereum) IsListening() bool { return true } // Always listening 509 func (s *Ethereum) Downloader() *downloader.Downloader { return s.handler.downloader } 510 func (s *Ethereum) Synced() bool { return atomic.LoadUint32(&s.handler.acceptTxs) == 1 } 511 func (s *Ethereum) ArchiveMode() bool { return s.config.NoPruning } 512 func (s *Ethereum) BloomIndexer() *core.ChainIndexer { return s.bloomIndexer } 513 514 // Protocols returns all the currently configured 515 // network protocols to start. 516 func (s *Ethereum) Protocols() []p2p.Protocol { 517 protos := eth.MakeProtocols((*ethHandler)(s.handler), s.networkID, s.ethDialCandidates) 518 if s.config.SnapshotCache > 0 { 519 protos = append(protos, snap.MakeProtocols((*snapHandler)(s.handler), s.snapDialCandidates)...) 520 } 521 return protos 522 } 523 524 // Start implements node.Lifecycle, starting all internal goroutines needed by the 525 // Ethereum protocol implementation. 526 func (s *Ethereum) Start() error { 527 eth.StartENRUpdater(s.blockchain, s.p2pServer.LocalNode()) 528 529 // Start the bloom bits servicing goroutines 530 s.startBloomHandlers(params.BloomBitsBlocks) 531 532 // Figure out a max peers count based on the server limits 533 maxPeers := s.p2pServer.MaxPeers 534 if s.config.LightServ > 0 { 535 if s.config.LightPeers >= s.p2pServer.MaxPeers { 536 return fmt.Errorf("invalid peer config: light peer count (%d) >= total peer count (%d)", s.config.LightPeers, s.p2pServer.MaxPeers) 537 } 538 maxPeers -= s.config.LightPeers 539 } 540 // Start the networking layer and the light server if requested 541 s.handler.Start(maxPeers) 542 return nil 543 } 544 545 // Stop implements node.Lifecycle, terminating all internal goroutines used by the 546 // Ethereum protocol. 547 func (s *Ethereum) Stop() error { 548 // Stop all the peer-related stuff first. 549 s.ethDialCandidates.Close() 550 s.snapDialCandidates.Close() 551 s.handler.Stop() 552 553 // Then stop everything else. 554 s.bloomIndexer.Close() 555 close(s.closeBloomHandler) 556 s.txPool.Stop() 557 s.miner.Stop() 558 s.blockchain.Stop() 559 s.engine.Close() 560 rawdb.PopUncleanShutdownMarker(s.chainDb) 561 s.chainDb.Close() 562 s.eventMux.Stop() 563 564 return nil 565 }