github.com/platonnetwork/platon-go@v0.7.6/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 "sync" 25 "sync/atomic" 26 27 "github.com/PlatONnetwork/PlatON-Go/x/gov" 28 29 "github.com/PlatONnetwork/PlatON-Go/x/handler" 30 31 "github.com/PlatONnetwork/PlatON-Go/core/snapshotdb" 32 33 "github.com/PlatONnetwork/PlatON-Go/consensus/cbft/evidence" 34 35 "github.com/PlatONnetwork/PlatON-Go/accounts" 36 "github.com/PlatONnetwork/PlatON-Go/common" 37 "github.com/PlatONnetwork/PlatON-Go/consensus" 38 "github.com/PlatONnetwork/PlatON-Go/consensus/cbft" 39 ctypes "github.com/PlatONnetwork/PlatON-Go/consensus/cbft/types" 40 "github.com/PlatONnetwork/PlatON-Go/consensus/cbft/validator" 41 "github.com/PlatONnetwork/PlatON-Go/core" 42 "github.com/PlatONnetwork/PlatON-Go/core/bloombits" 43 "github.com/PlatONnetwork/PlatON-Go/core/rawdb" 44 "github.com/PlatONnetwork/PlatON-Go/core/types" 45 "github.com/PlatONnetwork/PlatON-Go/core/vm" 46 "github.com/PlatONnetwork/PlatON-Go/eth/downloader" 47 "github.com/PlatONnetwork/PlatON-Go/eth/filters" 48 "github.com/PlatONnetwork/PlatON-Go/eth/gasprice" 49 "github.com/PlatONnetwork/PlatON-Go/ethdb" 50 "github.com/PlatONnetwork/PlatON-Go/event" 51 "github.com/PlatONnetwork/PlatON-Go/internal/ethapi" 52 "github.com/PlatONnetwork/PlatON-Go/log" 53 "github.com/PlatONnetwork/PlatON-Go/miner" 54 "github.com/PlatONnetwork/PlatON-Go/node" 55 "github.com/PlatONnetwork/PlatON-Go/p2p" 56 "github.com/PlatONnetwork/PlatON-Go/p2p/discover" 57 "github.com/PlatONnetwork/PlatON-Go/params" 58 "github.com/PlatONnetwork/PlatON-Go/rpc" 59 xplugin "github.com/PlatONnetwork/PlatON-Go/x/plugin" 60 "github.com/PlatONnetwork/PlatON-Go/x/xcom" 61 ) 62 63 type LesServer interface { 64 Start(srvr *p2p.Server) 65 Stop() 66 Protocols() []p2p.Protocol 67 SetBloomBitsIndexer(bbIndexer *core.ChainIndexer) 68 } 69 70 // Ethereum implements the Ethereum full node service. 71 type Ethereum struct { 72 config *Config 73 chainConfig *params.ChainConfig 74 75 // Channel for shutting down the service 76 shutdownChan chan bool // Channel for shutting down the Ethereum 77 78 // Handlers 79 txPool *core.TxPool 80 blockchain *core.BlockChain 81 protocolManager *ProtocolManager 82 lesServer LesServer 83 // modify 84 //mpcPool *core.MPCPool 85 //vcPool *core.VCPool 86 87 // DB interfaces 88 chainDb ethdb.Database // Block chain database 89 90 eventMux *event.TypeMux 91 engine consensus.Engine 92 accountManager *accounts.Manager 93 94 bloomRequests chan chan *bloombits.Retrieval // Channel receiving bloom data retrieval requests 95 bloomIndexer *core.ChainIndexer // Bloom indexer operating during block imports 96 97 APIBackend *EthAPIBackend 98 99 miner *miner.Miner 100 gasPrice *big.Int 101 networkID uint64 102 netRPCService *ethapi.PublicNetAPI 103 104 lock sync.RWMutex // Protects the variadic fields (e.g. gas price and etherbase) 105 } 106 107 func (s *Ethereum) AddLesServer(ls LesServer) { 108 s.lesServer = ls 109 ls.SetBloomBitsIndexer(s.bloomIndexer) 110 } 111 112 // New creates a new Ethereum object (including the 113 // initialisation of the common Ethereum object) 114 func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) { 115 // Ensure configuration values are compatible and sane 116 if config.SyncMode == downloader.LightSync { 117 return nil, errors.New("can't run eth.PlatON in light sync mode, use les.LightPlatON") 118 } 119 if !config.SyncMode.IsValid() { 120 return nil, fmt.Errorf("invalid sync mode %d", config.SyncMode) 121 } 122 if config.MinerGasPrice == nil || config.MinerGasPrice.Cmp(common.Big0) <= 0 { 123 log.Warn("Sanitizing invalid miner gas price", "provided", config.MinerGasPrice, "updated", DefaultConfig.MinerGasPrice) 124 config.MinerGasPrice = new(big.Int).Set(DefaultConfig.MinerGasPrice) 125 } 126 // Assemble the Ethereum object 127 chainDb, err := CreateDB(ctx, config, "chaindata") 128 if err != nil { 129 return nil, err 130 } 131 snapshotdb.SetDBOptions(config.DatabaseCache, config.DatabaseHandles) 132 133 chainConfig, _, genesisErr := core.SetupGenesisBlock(chainDb, ctx.ResolvePath(snapshotdb.DBPath), config.Genesis) 134 135 if _, ok := genesisErr.(*params.ConfigCompatError); genesisErr != nil && !ok { 136 return nil, genesisErr 137 } 138 139 if chainConfig.Cbft.Period == 0 || chainConfig.Cbft.Amount == 0 { 140 chainConfig.Cbft.Period = config.CbftConfig.Period 141 chainConfig.Cbft.Amount = config.CbftConfig.Amount 142 } 143 144 log.Info("Initialised chain configuration", "config", chainConfig) 145 146 eth := &Ethereum{ 147 config: config, 148 chainDb: chainDb, 149 chainConfig: chainConfig, 150 eventMux: ctx.EventMux, 151 accountManager: ctx.AccountManager, 152 engine: CreateConsensusEngine(ctx, chainConfig, config.MinerNoverify, chainDb, &config.CbftConfig, ctx.EventMux), 153 shutdownChan: make(chan bool), 154 networkID: config.NetworkId, 155 gasPrice: config.MinerGasPrice, 156 bloomRequests: make(chan chan *bloombits.Retrieval), 157 bloomIndexer: NewBloomIndexer(chainDb, params.BloomBitsBlocks, params.BloomConfirms), 158 } 159 160 log.Info("Initialising PlatON protocol", "versions", ProtocolVersions, "network", config.NetworkId) 161 162 if !config.SkipBcVersionCheck { 163 bcVersion := rawdb.ReadDatabaseVersion(chainDb) 164 if bcVersion != config.BlockChainVersion && bcVersion != 0 { 165 return nil, fmt.Errorf("Blockchain DB version mismatch (%d / %d).\n", bcVersion, config.BlockChainVersion) 166 } 167 rawdb.WriteDatabaseVersion(chainDb, config.BlockChainVersion) 168 } 169 var ( 170 vmConfig = vm.Config{ 171 ConsoleOutput: config.Debug, 172 } 173 cacheConfig = &core.CacheConfig{Disabled: config.NoPruning, TrieNodeLimit: config.TrieCache, TrieTimeLimit: config.TrieTimeout, 174 BodyCacheLimit: config.BodyCacheLimit, BlockCacheLimit: config.BlockCacheLimit, 175 MaxFutureBlocks: config.MaxFutureBlocks, BadBlockLimit: config.BadBlockLimit, 176 TriesInMemory: config.TriesInMemory, TrieDBCache: config.TrieDBCache, 177 DBGCInterval: config.DBGCInterval, DBGCTimeout: config.DBGCTimeout, 178 DBGCMpt: config.DBGCMpt, DBGCBlock: config.DBGCBlock, 179 } 180 181 minningConfig = &core.MiningConfig{MiningLogAtDepth: config.MiningLogAtDepth, TxChanSize: config.TxChanSize, 182 ChainHeadChanSize: config.ChainHeadChanSize, ChainSideChanSize: config.ChainSideChanSize, 183 ResultQueueSize: config.ResultQueueSize, ResubmitAdjustChanSize: config.ResubmitAdjustChanSize, 184 MinRecommitInterval: config.MinRecommitInterval, MaxRecommitInterval: config.MaxRecommitInterval, 185 IntervalAdjustRatio: config.IntervalAdjustRatio, IntervalAdjustBias: config.IntervalAdjustBias, 186 StaleThreshold: config.StaleThreshold, DefaultCommitRatio: config.DefaultCommitRatio, 187 } 188 ) 189 cacheConfig.DBDisabledGC.Set(config.DBDisabledGC) 190 191 eth.blockchain, err = core.NewBlockChain(chainDb, cacheConfig, eth.chainConfig, eth.engine, vmConfig, eth.shouldPreserve) 192 if err != nil { 193 return nil, err 194 } 195 snapshotdb.SetDBBlockChain(eth.blockchain) 196 197 blockChainCache := core.NewBlockChainCache(eth.blockchain) 198 199 // Rewind the chain in case of an incompatible config upgrade. 200 if compat, ok := genesisErr.(*params.ConfigCompatError); ok { 201 log.Warn("Rewinding chain to upgrade configuration", "err", compat) 202 return nil, compat 203 //eth.blockchain.SetHead(compat.RewindTo) 204 //rawdb.WriteChainConfig(chainDb, genesisHash, chainConfig) 205 } 206 eth.bloomIndexer.Start(eth.blockchain) 207 208 if config.TxPool.Journal != "" { 209 config.TxPool.Journal = ctx.ResolvePath(config.TxPool.Journal) 210 } 211 //eth.txPool = core.NewTxPool(config.TxPool, eth.chainConfig, eth.blockchain) 212 eth.txPool = core.NewTxPool(config.TxPool, eth.chainConfig, blockChainCache) 213 214 // mpcPool deal with mpc transactions 215 // modify By J 216 //if config.MPCPool.Journal != "" { 217 // config.MPCPool.Journal = ctx.ResolvePath(config.MPCPool.Journal) 218 //} else { 219 // config.MPCPool.Journal = ctx.ResolvePath(core.DefaultMPCPoolConfig.Journal) 220 //} 221 //if config.MPCPool.Rejournal == 0 { 222 // config.MPCPool.Rejournal = core.DefaultMPCPoolConfig.Rejournal 223 //} 224 //if config.MPCPool.Lifetime == 0 { 225 // config.MPCPool.Lifetime = core.DefaultMPCPoolConfig.Lifetime 226 //} 227 //eth.mpcPool = core.NewMPCPool(config.MPCPool, eth.chainConfig, eth.blockchain) 228 //eth.vcPool = core.NewVCPool(config.VCPool, eth.chainConfig, eth.blockchain) 229 230 // modify by platon remove consensusCache 231 //var consensusCache *cbft.Cache = cbft.NewCache(eth.blockchain) 232 233 currentBlock := eth.blockchain.CurrentBlock() 234 currentNumber := currentBlock.NumberU64() 235 currentHash := currentBlock.Hash() 236 gasCeil, err := gov.GovernMaxBlockGasLimit(currentNumber, currentHash) 237 if nil != err { 238 log.Error("Failed to query gasCeil from snapshotdb", "err", err) 239 return nil, err 240 } 241 if config.MinerGasFloor > uint64(gasCeil) { 242 log.Error("The gasFloor must be less than gasCeil", "gasFloor", config.MinerGasFloor, "gasCeil", gasCeil) 243 return nil, fmt.Errorf("The gasFloor must be less than gasCeil, got: %d, expect range (0, %d]", config.MinerGasFloor, gasCeil) 244 } 245 246 eth.miner = miner.New(eth, eth.chainConfig, minningConfig, eth.EventMux(), eth.engine, config.MinerRecommit, 247 config.MinerGasFloor /*config.MinerGasCeil,*/, eth.isLocalBlock, blockChainCache) 248 249 //extra data for each block will be set by worker.go 250 //eth.miner.SetExtra(makeExtraData(eth.blockchain, config.MinerExtraData)) 251 252 reactor := core.NewBlockChainReactor(eth.EventMux()) 253 node.GetCryptoHandler().SetPrivateKey(config.CbftConfig.NodePriKey) 254 255 if engine, ok := eth.engine.(consensus.Bft); ok { 256 257 var agency consensus.Agency 258 // validatorMode: 259 // - static (default) 260 // - inner (via inner contract)eth/handler.go 261 // - ppos 262 263 log.Debug("Validator mode", "mode", chainConfig.Cbft.ValidatorMode) 264 if chainConfig.Cbft.ValidatorMode == "" || chainConfig.Cbft.ValidatorMode == common.STATIC_VALIDATOR_MODE { 265 agency = validator.NewStaticAgency(chainConfig.Cbft.InitialNodes) 266 reactor.Start(common.STATIC_VALIDATOR_MODE) 267 } else if chainConfig.Cbft.ValidatorMode == common.INNER_VALIDATOR_MODE { 268 blocksPerNode := int(chainConfig.Cbft.Amount) 269 offset := blocksPerNode * 2 270 agency = validator.NewInnerAgency(chainConfig.Cbft.InitialNodes, eth.blockchain, blocksPerNode, offset) 271 reactor.Start(common.INNER_VALIDATOR_MODE) 272 } else if chainConfig.Cbft.ValidatorMode == common.PPOS_VALIDATOR_MODE { 273 reactor.Start(common.PPOS_VALIDATOR_MODE) 274 reactor.SetVRFhandler(handler.NewVrfHandler(eth.blockchain.Genesis().Nonce())) 275 reactor.SetPluginEventMux() 276 reactor.SetPrivateKey(ctx.NodePriKey()) 277 handlePlugin(reactor) 278 agency = reactor 279 280 //register Govern parameter verifiers 281 gov.RegisterGovernParamVerifiers() 282 } 283 284 if err := recoverSnapshotDB(blockChainCache); err != nil { 285 log.Error("recover SnapshotDB fail", "error", err) 286 return nil, errors.New("Failed to recover SnapshotDB") 287 } 288 289 if err := engine.Start(eth.blockchain, blockChainCache, eth.txPool, agency); err != nil { 290 log.Error("Init cbft consensus engine fail", "error", err) 291 return nil, errors.New("Failed to init cbft consensus engine") 292 } 293 } 294 295 if eth.protocolManager, err = NewProtocolManager(eth.chainConfig, config.SyncMode, config.NetworkId, eth.eventMux, eth.txPool, eth.engine, eth.blockchain, chainDb); err != nil { 296 return nil, err 297 } 298 299 eth.APIBackend = &EthAPIBackend{eth, nil} 300 gpoParams := config.GPO 301 if gpoParams.Default == nil { 302 gpoParams.Default = config.MinerGasPrice 303 } 304 eth.APIBackend.gpo = gasprice.NewOracle(eth.APIBackend, gpoParams) 305 306 return eth, nil 307 } 308 309 func recoverSnapshotDB(blockChainCache *core.BlockChainCache) error { 310 sdb := snapshotdb.Instance() 311 ch := sdb.GetCurrent().GetHighest(false).Num.Uint64() 312 blockChanHegiht := blockChainCache.CurrentHeader().Number.Uint64() 313 if ch < blockChanHegiht { 314 for i := ch + 1; i <= blockChanHegiht; i++ { 315 block, parentBlock := blockChainCache.GetBlockByNumber(i), blockChainCache.GetBlockByNumber(i-1) 316 log.Debug("snapshotdb recover block from blockchain", "num", block.Number(), "hash", block.Hash()) 317 if err := blockChainCache.Execute(block, parentBlock); err != nil { 318 log.Error("snapshotdb recover block from blockchain execute fail", "error", err) 319 return err 320 } 321 if err := sdb.Commit(block.Hash()); err != nil { 322 log.Error("snapshotdb recover block from blockchain Commit fail", "error", err) 323 return err 324 } 325 } 326 } 327 return nil 328 } 329 330 // CreateDB creates the chain database. 331 func CreateDB(ctx *node.ServiceContext, config *Config, name string) (ethdb.Database, error) { 332 db, err := ctx.OpenDatabase(name, config.DatabaseCache, config.DatabaseHandles) 333 if err != nil { 334 return nil, err 335 } 336 if db, ok := db.(*ethdb.LDBDatabase); ok { 337 db.Meter("eth/db/chaindata/") 338 } 339 return db, nil 340 } 341 342 // CreateConsensusEngine creates the required type of consensus engine instance for an Ethereum service 343 func CreateConsensusEngine(ctx *node.ServiceContext, chainConfig *params.ChainConfig, noverify bool, db ethdb.Database, 344 cbftConfig *ctypes.OptionsConfig, eventMux *event.TypeMux) consensus.Engine { 345 // If proof-of-authority is requested, set it up 346 engine := cbft.New(chainConfig.Cbft, cbftConfig, eventMux, ctx) 347 if engine == nil { 348 panic("create consensus engine fail") 349 } 350 return engine 351 } 352 353 // APIs return the collection of RPC services the ethereum package offers. 354 // NOTE, some of these services probably need to be moved to somewhere else. 355 func (s *Ethereum) APIs() []rpc.API { 356 apis := ethapi.GetAPIs(s.APIBackend) 357 358 // Append any APIs exposed explicitly by the consensus engine 359 apis = append(apis, s.engine.APIs(s.BlockChain())...) 360 361 // Append all the local APIs and return 362 return append(apis, []rpc.API{ 363 { 364 Namespace: "platon", 365 Version: "1.0", 366 Service: downloader.NewPublicDownloaderAPI(s.protocolManager.downloader, s.eventMux), 367 Public: true, 368 }, { 369 Namespace: "miner", 370 Version: "1.0", 371 Service: NewPrivateMinerAPI(s), 372 Public: false, 373 }, { 374 Namespace: "platon", 375 Version: "1.0", 376 Service: filters.NewPublicFilterAPI(s.APIBackend, false), 377 Public: true, 378 }, { 379 Namespace: "admin", 380 Version: "1.0", 381 Service: NewPrivateAdminAPI(s), 382 }, { 383 Namespace: "debug", 384 Version: "1.0", 385 Service: NewPublicDebugAPI(s), 386 Public: true, 387 }, { 388 Namespace: "debug", 389 Version: "1.0", 390 Service: NewPrivateDebugAPI(s.chainConfig, s), 391 }, { 392 Namespace: "net", 393 Version: "1.0", 394 Service: s.netRPCService, 395 Public: true, 396 }, 397 }...) 398 } 399 400 //func (s *Ethereum) ResetWithGenesisBlock(gb *types.Block) { 401 // s.blockchain.ResetWithGenesisBlock(gb) 402 //} 403 404 // isLocalBlock checks whether the specified block is mined 405 // by local miner accounts. 406 // 407 // We regard two types of accounts as local miner account: etherbase 408 // and accounts specified via `txpool.locals` flag. 409 func (s *Ethereum) isLocalBlock(block *types.Block) bool { 410 author, err := s.engine.Author(block.Header()) 411 if err != nil { 412 log.Warn("Failed to retrieve block author", "number", block.NumberU64(), "hash", block.Hash(), "err", err) 413 return false 414 } 415 // Check whether the given address is etherbase. 416 s.lock.RLock() 417 etherbase := common.Address{} 418 s.lock.RUnlock() 419 if author == etherbase { 420 return true 421 } 422 // Check whether the given address is specified by `txpool.local` 423 // CLI flag. 424 for _, account := range s.config.TxPool.Locals { 425 if account == author { 426 return true 427 } 428 } 429 return false 430 } 431 432 // shouldPreserve checks whether we should preserve the given block 433 // during the chain reorg depending on whether the author of block 434 // is a local account. 435 func (s *Ethereum) shouldPreserve(block *types.Block) bool { 436 // The reason we need to disable the self-reorg preserving for clique 437 // is it can be probable to introduce a deadlock. 438 // 439 // e.g. If there are 7 available signers 440 // 441 // r1 A 442 // r2 B 443 // r3 C 444 // r4 D 445 // r5 A [X] F G 446 // r6 [X] 447 // 448 // In the round5, the inturn signer E is offline, so the worst case 449 // is A, F and G sign the block of round5 and reject the block of opponents 450 // and in the round6, the last available signer B is offline, the whole 451 // network is stuck. 452 return s.isLocalBlock(block) 453 } 454 455 //start mining 456 func (s *Ethereum) StartMining() error { 457 // If the miner was not running, initialize it 458 if !s.IsMining() { 459 // Propagate the initial price point to the transaction pool 460 s.lock.RLock() 461 price := s.gasPrice 462 s.lock.RUnlock() 463 s.txPool.SetGasPrice(price) 464 465 // If mining is started, we can disable the transaction rejection mechanism 466 // introduced to speed sync times. 467 atomic.StoreUint32(&s.protocolManager.acceptTxs, 1) 468 469 go s.miner.Start() 470 } 471 return nil 472 } 473 474 // StopMining terminates the miner, both at the consensus engine level as well as 475 // at the block creation level. 476 func (s *Ethereum) StopMining() { 477 s.miner.Stop() 478 } 479 480 func (s *Ethereum) IsMining() bool { return s.miner.Mining() } 481 func (s *Ethereum) Miner() *miner.Miner { return s.miner } 482 483 func (s *Ethereum) AccountManager() *accounts.Manager { return s.accountManager } 484 func (s *Ethereum) BlockChain() *core.BlockChain { return s.blockchain } 485 func (s *Ethereum) TxPool() *core.TxPool { return s.txPool } 486 func (s *Ethereum) EventMux() *event.TypeMux { return s.eventMux } 487 func (s *Ethereum) Engine() consensus.Engine { return s.engine } 488 func (s *Ethereum) ChainDb() ethdb.Database { return s.chainDb } 489 func (s *Ethereum) IsListening() bool { return true } // Always listening 490 func (s *Ethereum) EthVersion() int { return int(s.protocolManager.SubProtocols[0].Version) } 491 func (s *Ethereum) NetVersion() uint64 { return s.networkID } 492 func (s *Ethereum) Downloader() *downloader.Downloader { return s.protocolManager.downloader } 493 494 // Protocols implements node.Service, returning all the currently configured 495 // network protocols to start. 496 func (s *Ethereum) Protocols() []p2p.Protocol { 497 protocols := make([]p2p.Protocol, 0) 498 protocols = append(protocols, s.protocolManager.SubProtocols...) 499 protocols = append(protocols, s.engine.Protocols()...) 500 501 if s.lesServer == nil { 502 return protocols 503 } 504 protocols = append(protocols, s.lesServer.Protocols()...) 505 return protocols 506 } 507 508 // Start implements node.Service, starting all internal goroutines needed by the 509 // Ethereum protocol implementation. 510 func (s *Ethereum) Start(srvr *p2p.Server) error { 511 // Start the bloom bits servicing goroutines 512 s.startBloomHandlers(params.BloomBitsBlocks) 513 514 // Start the RPC service 515 s.netRPCService = ethapi.NewPublicNetAPI(srvr, s.NetVersion()) 516 517 // Figure out a max peers count based on the server limits 518 maxPeers := srvr.MaxPeers 519 if s.config.LightServ > 0 { 520 if s.config.LightPeers >= srvr.MaxPeers { 521 return fmt.Errorf("invalid peer config: light peer count (%d) >= total peer count (%d)", s.config.LightPeers, srvr.MaxPeers) 522 } 523 maxPeers -= s.config.LightPeers 524 } 525 // Start the networking layer and the light server if requested 526 s.protocolManager.Start(maxPeers) 527 528 //log.Debug("node start", "srvr.Config.PrivateKey", srvr.Config.PrivateKey) 529 if cbftEngine, ok := s.engine.(consensus.Bft); ok { 530 if flag := cbftEngine.IsConsensusNode(); flag { 531 for _, n := range s.chainConfig.Cbft.InitialNodes { 532 // todo: Mock point. 533 if !node.FakeNetEnable { 534 srvr.AddConsensusPeer(discover.NewNode(n.Node.ID, n.Node.IP, n.Node.UDP, n.Node.TCP)) 535 } 536 } 537 } 538 s.StartMining() 539 } 540 srvr.StartWatching(s.eventMux) 541 542 if s.lesServer != nil { 543 s.lesServer.Start(srvr) 544 } 545 return nil 546 } 547 548 // Stop implements node.Service, terminating all internal goroutines used by the 549 // Ethereum protocol. 550 func (s *Ethereum) Stop() error { 551 s.bloomIndexer.Close() 552 s.blockchain.Stop() 553 s.protocolManager.Stop() 554 s.engine.Close() 555 if s.lesServer != nil { 556 s.lesServer.Stop() 557 } 558 s.txPool.Stop() 559 s.miner.Stop() 560 s.eventMux.Stop() 561 562 core.GetReactorInstance().Close() 563 s.chainDb.Close() 564 close(s.shutdownChan) 565 return nil 566 } 567 568 // RegisterPlugin one by one 569 func handlePlugin(reactor *core.BlockChainReactor) { 570 xplugin.RewardMgrInstance().SetCurrentNodeID(reactor.NodeId) 571 572 reactor.RegisterPlugin(xcom.SlashingRule, xplugin.SlashInstance()) 573 xplugin.SlashInstance().SetDecodeEvidenceFun(evidence.NewEvidence) 574 reactor.RegisterPlugin(xcom.StakingRule, xplugin.StakingInstance()) 575 reactor.RegisterPlugin(xcom.RestrictingRule, xplugin.RestrictingInstance()) 576 reactor.RegisterPlugin(xcom.RewardRule, xplugin.RewardMgrInstance()) 577 reactor.RegisterPlugin(xcom.GovernanceRule, xplugin.GovPluginInstance()) 578 579 // set rule order 580 reactor.SetBeginRule([]int{xcom.StakingRule, xcom.SlashingRule, xcom.GovernanceRule}) 581 reactor.SetEndRule([]int{xcom.RestrictingRule, xcom.RewardRule, xcom.GovernanceRule, xcom.StakingRule}) 582 583 }