github.com/klaytn/klaytn@v1.10.2/node/cn/backend.go (about) 1 // Modifications Copyright 2018 The klaytn Authors 2 // Copyright 2014 The go-ethereum Authors 3 // This file is part of go-ethereum. 4 // 5 // The go-ethereum library is free software: you can redistribute it and/or modify 6 // it under the terms of the GNU Lesser General Public License as published by 7 // the Free Software Foundation, either version 3 of the License, or 8 // (at your option) any later version. 9 // 10 // The go-ethereum library is distributed in the hope that it will be useful, 11 // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 // GNU Lesser General Public License for more details. 14 // 15 // You should have received a copy of the GNU Lesser General Public License 16 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 17 // 18 // This file is derived from eth/backend.go (2018/06/04). 19 // Modified and improved for the klaytn development. 20 21 package cn 22 23 import ( 24 "errors" 25 "fmt" 26 "math/big" 27 "os/exec" 28 "runtime" 29 "sync" 30 "time" 31 32 "github.com/klaytn/klaytn" 33 "github.com/klaytn/klaytn/accounts" 34 "github.com/klaytn/klaytn/api" 35 "github.com/klaytn/klaytn/blockchain" 36 "github.com/klaytn/klaytn/blockchain/bloombits" 37 "github.com/klaytn/klaytn/blockchain/state" 38 "github.com/klaytn/klaytn/blockchain/types" 39 "github.com/klaytn/klaytn/common" 40 "github.com/klaytn/klaytn/common/hexutil" 41 "github.com/klaytn/klaytn/consensus" 42 "github.com/klaytn/klaytn/consensus/istanbul" 43 istanbulBackend "github.com/klaytn/klaytn/consensus/istanbul/backend" 44 "github.com/klaytn/klaytn/crypto" 45 "github.com/klaytn/klaytn/datasync/downloader" 46 "github.com/klaytn/klaytn/event" 47 "github.com/klaytn/klaytn/governance" 48 "github.com/klaytn/klaytn/networks/p2p" 49 "github.com/klaytn/klaytn/networks/rpc" 50 "github.com/klaytn/klaytn/node" 51 "github.com/klaytn/klaytn/node/cn/filters" 52 "github.com/klaytn/klaytn/node/cn/gasprice" 53 "github.com/klaytn/klaytn/node/cn/tracers" 54 "github.com/klaytn/klaytn/params" 55 "github.com/klaytn/klaytn/reward" 56 "github.com/klaytn/klaytn/rlp" 57 "github.com/klaytn/klaytn/storage/database" 58 "github.com/klaytn/klaytn/work" 59 ) 60 61 var errCNLightSync = errors.New("can't run cn.CN in light sync mode") 62 63 //go:generate mockgen -destination=node/cn/mocks/lesserver_mock.go -package=mocks github.com/klaytn/klaytn/node/cn LesServer 64 type LesServer interface { 65 Start(srvr p2p.Server) 66 Stop() 67 Protocols() []p2p.Protocol 68 SetBloomBitsIndexer(bbIndexer *blockchain.ChainIndexer) 69 } 70 71 // Miner is an interface of work.Miner used by ServiceChain. 72 // 73 //go:generate mockgen -destination=node/cn/mocks/miner_mock.go -package=mocks github.com/klaytn/klaytn/node/cn Miner 74 type Miner interface { 75 Start() 76 Stop() 77 Register(agent work.Agent) 78 Mining() bool 79 HashRate() (tot int64) 80 SetExtra(extra []byte) error 81 Pending() (*types.Block, *state.StateDB) 82 PendingBlock() *types.Block 83 } 84 85 // BackendProtocolManager is an interface of cn.ProtocolManager used from cn.CN and cn.ServiceChain. 86 // 87 //go:generate mockgen -destination=node/cn/protocolmanager_mock_test.go github.com/klaytn/klaytn/node/cn BackendProtocolManager 88 type BackendProtocolManager interface { 89 Downloader() ProtocolManagerDownloader 90 SetWsEndPoint(wsep string) 91 GetSubProtocols() []p2p.Protocol 92 ProtocolVersion() int 93 ReBroadcastTxs(transactions types.Transactions) 94 SetAcceptTxs() 95 SetRewardbase(addr common.Address) 96 SetRewardbaseWallet(wallet accounts.Wallet) 97 NodeType() common.ConnType 98 Start(maxPeers int) 99 Stop() 100 SetSyncStop(flag bool) 101 } 102 103 // CN implements the Klaytn consensus node service. 104 type CN struct { 105 config *Config 106 chainConfig *params.ChainConfig 107 108 // Handlers 109 txPool work.TxPool 110 blockchain work.BlockChain 111 protocolManager BackendProtocolManager 112 lesServer LesServer 113 114 // DB interfaces 115 chainDB database.DBManager // Block chain database 116 117 eventMux *event.TypeMux 118 engine consensus.Engine 119 accountManager accounts.AccountManager 120 121 bloomRequests chan chan *bloombits.Retrieval // Channel receiving bloom data retrieval requests 122 bloomIndexer *blockchain.ChainIndexer // Bloom indexer operating during block imports 123 closeBloomHandler chan struct{} 124 125 APIBackend *CNAPIBackend 126 127 miner Miner 128 gasPrice *big.Int 129 130 rewardbase common.Address 131 132 networkId uint64 133 netRPCService *api.PublicNetAPI 134 135 lock sync.RWMutex // Protects the variadic fields (e.g. gas price) 136 137 components []interface{} 138 139 governance governance.Engine 140 } 141 142 func (s *CN) AddLesServer(ls LesServer) { 143 s.lesServer = ls 144 ls.SetBloomBitsIndexer(s.bloomIndexer) 145 } 146 147 // senderTxHashIndexer subscribes chainEvent and stores senderTxHash to txHash mapping information. 148 func senderTxHashIndexer(db database.DBManager, chainEvent <-chan blockchain.ChainEvent, subscription event.Subscription) { 149 defer subscription.Unsubscribe() 150 151 for { 152 select { 153 case event := <-chainEvent: 154 var err error 155 batch := db.NewSenderTxHashToTxHashBatch() 156 for _, tx := range event.Block.Transactions() { 157 senderTxHash, ok := tx.SenderTxHash() 158 159 // senderTxHash and txHash are the same if tx is not a fee-delegated tx. 160 // Do not store mapping between senderTxHash and txHash in this case. 161 if !ok { 162 continue 163 } 164 165 txHash := tx.Hash() 166 167 if err = db.PutSenderTxHashToTxHashToBatch(batch, senderTxHash, txHash); err != nil { 168 logger.Error("Failed to store senderTxHash to txHash mapping to database", 169 "blockNum", event.Block.Number(), "senderTxHash", senderTxHash, "txHash", txHash, "err", err) 170 break 171 } 172 } 173 174 if err == nil { 175 batch.Write() 176 } 177 178 case <-subscription.Err(): 179 return 180 } 181 } 182 } 183 184 func checkSyncMode(config *Config) error { 185 if !config.SyncMode.IsValid() { 186 return fmt.Errorf("invalid sync mode %d", config.SyncMode) 187 } 188 if config.SyncMode == downloader.LightSync { 189 return errCNLightSync 190 } 191 return nil 192 } 193 194 func setEngineType(chainConfig *params.ChainConfig) { 195 if chainConfig.Clique != nil { 196 types.EngineType = types.Engine_Clique 197 } 198 if chainConfig.Istanbul != nil { 199 types.EngineType = types.Engine_IBFT 200 } 201 } 202 203 // New creates a new CN object (including the 204 // initialisation of the common CN object) 205 func New(ctx *node.ServiceContext, config *Config) (*CN, error) { 206 if err := checkSyncMode(config); err != nil { 207 return nil, err 208 } 209 210 chainDB := CreateDB(ctx, config, "chaindata") 211 212 chainConfig, genesisHash, genesisErr := blockchain.SetupGenesisBlock(chainDB, config.Genesis, config.NetworkId, config.IsPrivate, false) 213 if _, ok := genesisErr.(*params.ConfigCompatError); genesisErr != nil && !ok { 214 return nil, genesisErr 215 } 216 217 setEngineType(chainConfig) 218 219 // load governance state 220 chainConfig.SetDefaults() 221 // latest values will be applied to chainConfig after NewMixedEngine call 222 governance := governance.NewMixedEngine(chainConfig, chainDB) 223 logger.Info("Initialised chain configuration", "config", chainConfig) 224 225 config.GasPrice = new(big.Int).SetUint64(chainConfig.UnitPrice) 226 227 cn := &CN{ 228 config: config, 229 chainDB: chainDB, 230 chainConfig: chainConfig, 231 eventMux: ctx.EventMux, 232 accountManager: ctx.AccountManager, 233 engine: CreateConsensusEngine(ctx, config, chainConfig, chainDB, governance, ctx.NodeType()), 234 networkId: config.NetworkId, 235 gasPrice: config.GasPrice, 236 rewardbase: config.Rewardbase, 237 bloomRequests: make(chan chan *bloombits.Retrieval), 238 bloomIndexer: NewBloomIndexer(chainDB, params.BloomBitsBlocks), 239 closeBloomHandler: make(chan struct{}), 240 governance: governance, 241 } 242 243 // istanbul BFT. Derive and set node's address using nodekey 244 if cn.chainConfig.Istanbul != nil { 245 governance.SetNodeAddress(crypto.PubkeyToAddress(ctx.NodeKey().PublicKey)) 246 } 247 248 logger.Info("Initialising Klaytn protocol", "versions", cn.engine.Protocol().Versions, "network", config.NetworkId) 249 250 if !config.SkipBcVersionCheck { 251 if err := blockchain.CheckBlockChainVersion(chainDB); err != nil { 252 return nil, err 253 } 254 } 255 var ( 256 vmConfig = config.getVMConfig() 257 cacheConfig = &blockchain.CacheConfig{ 258 ArchiveMode: config.NoPruning, CacheSize: config.TrieCacheSize, 259 BlockInterval: config.TrieBlockInterval, TriesInMemory: config.TriesInMemory, 260 TrieNodeCacheConfig: &config.TrieNodeCacheConfig, SenderTxHashIndexing: config.SenderTxHashIndexing, SnapshotCacheSize: config.SnapshotCacheSize, SnapshotAsyncGen: config.SnapshotAsyncGen, 261 } 262 ) 263 264 bc, err := blockchain.NewBlockChain(chainDB, cacheConfig, cn.chainConfig, cn.engine, vmConfig) 265 if err != nil { 266 return nil, err 267 } 268 bc.SetCanonicalBlock(config.StartBlockNumber) 269 270 cn.blockchain = bc 271 governance.SetBlockchain(cn.blockchain) 272 if err := governance.UpdateParams(cn.blockchain.CurrentBlock().NumberU64()); err != nil { 273 return nil, err 274 } 275 blockchain.InitDeriveShaWithGov(cn.chainConfig, governance) 276 277 // Synchronize proposerpolicy & useGiniCoeff 278 pset, err := governance.EffectiveParams(bc.CurrentBlock().NumberU64() + 1) 279 if err != nil { 280 return nil, err 281 } 282 if cn.blockchain.Config().Istanbul != nil { 283 cn.blockchain.Config().Istanbul.ProposerPolicy = pset.Policy() 284 } 285 if cn.blockchain.Config().Governance.Reward != nil { 286 cn.blockchain.Config().Governance.Reward.UseGiniCoeff = pset.UseGiniCoeff() 287 } 288 289 if config.SenderTxHashIndexing { 290 ch := make(chan blockchain.ChainEvent, 255) 291 chainEventSubscription := cn.blockchain.SubscribeChainEvent(ch) 292 go senderTxHashIndexer(chainDB, ch, chainEventSubscription) 293 } 294 295 // Rewind the chain in case of an incompatible config upgrade. 296 if compat, ok := genesisErr.(*params.ConfigCompatError); ok { 297 logger.Error("Rewinding chain to upgrade configuration", "err", compat) 298 cn.blockchain.SetHead(compat.RewindTo) 299 chainDB.WriteChainConfig(genesisHash, cn.chainConfig) 300 } 301 cn.bloomIndexer.Start(cn.blockchain) 302 303 if config.TxPool.Journal != "" { 304 config.TxPool.Journal = ctx.ResolvePath(config.TxPool.Journal) 305 } 306 // TODO-Klaytn-ServiceChain: add account creation prevention in the txPool if TxTypeAccountCreation is supported. 307 config.TxPool.NoAccountCreation = config.NoAccountCreation 308 cn.txPool = blockchain.NewTxPool(config.TxPool, cn.chainConfig, bc) 309 governance.SetTxPool(cn.txPool) 310 311 // Permit the downloader to use the trie cache allowance during fast sync 312 cacheLimit := cacheConfig.TrieNodeCacheConfig.LocalCacheSizeMiB 313 if cn.protocolManager, err = NewProtocolManager(cn.chainConfig, config.SyncMode, config.NetworkId, cn.eventMux, cn.txPool, cn.engine, cn.blockchain, chainDB, cacheLimit, ctx.NodeType(), config); err != nil { 314 return nil, err 315 } 316 317 if err := cn.setAcceptTxs(); err != nil { 318 logger.Error("Failed to decode IstanbulExtra", "err", err) 319 } 320 321 cn.protocolManager.SetWsEndPoint(config.WsEndpoint) 322 323 if err := cn.setRewardWallet(); err != nil { 324 logger.Error("Error happened while setting the reward wallet", "err", err) 325 } 326 327 if pset.Policy() == uint64(istanbul.WeightedRandom) { 328 // NewStakingManager is called with proper non-nil parameters 329 reward.NewStakingManager(cn.blockchain, governance, cn.chainDB) 330 } 331 332 // set worker 333 if config.WorkerDisable { 334 cn.miner = work.NewFakeWorker() 335 // Istanbul backend can be accessed by APIs to call its methods even though the core of the 336 // consensus engine doesn't run. 337 istBackend, ok := cn.engine.(consensus.Istanbul) 338 if ok { 339 istBackend.SetChain(cn.blockchain) 340 } 341 } else { 342 // TODO-Klaytn improve to handle drop transaction on network traffic in PN and EN 343 cn.miner = work.New(cn, cn.chainConfig, cn.EventMux(), cn.engine, ctx.NodeType(), crypto.PubkeyToAddress(ctx.NodeKey().PublicKey), cn.config.TxResendUseLegacy) 344 } 345 346 // istanbul BFT 347 cn.miner.SetExtra(makeExtraData(config.ExtraData)) 348 349 cn.APIBackend = &CNAPIBackend{cn, nil} 350 351 gpoParams := config.GPO 352 353 // NOTE-Klaytn Now we use latest unitPrice 354 // So let's override gpoParams.Default with config.GasPrice 355 gpoParams.Default = config.GasPrice 356 357 cn.APIBackend.gpo = gasprice.NewOracle(cn.APIBackend, gpoParams, cn.txPool) 358 //@TODO Klaytn add core component 359 cn.addComponent(cn.blockchain) 360 cn.addComponent(cn.txPool) 361 cn.addComponent(cn.APIs()) 362 cn.addComponent(cn.ChainDB()) 363 cn.addComponent(cn.engine) 364 365 if config.AutoRestartFlag { 366 daemonPath := config.DaemonPathFlag 367 restartInterval := config.RestartTimeOutFlag 368 if restartInterval <= time.Second { 369 logger.Crit("Invalid auto-restart timeout", "timeout", restartInterval) 370 } 371 372 // Restarts the node with the same configuration if blockNumber is not changed for a specific time. 373 restartTimer := time.AfterFunc(restartInterval, func() { 374 logger.Warn("Restart node", "command", daemonPath+" restart") 375 cmd := exec.Command(daemonPath, "restart") 376 cmd.Run() 377 }) 378 logger.Info("Initialize auto-restart feature", "timeout", restartInterval, "daemonPath", daemonPath) 379 380 go func() { 381 blockChecker := time.NewTicker(time.Second) 382 prevBlockNum := cn.blockchain.CurrentBlock().NumberU64() 383 384 for range blockChecker.C { 385 currentBlockNum := cn.blockchain.CurrentBlock().NumberU64() 386 387 if prevBlockNum != currentBlockNum { 388 prevBlockNum = currentBlockNum 389 restartTimer.Reset(restartInterval) 390 } 391 } 392 }() 393 } 394 395 // Only for KES nodes 396 if config.TrieNodeCacheConfig.RedisSubscribeBlockEnable { 397 go cn.blockchain.BlockSubscriptionLoop(cn.txPool.(*blockchain.TxPool)) 398 } 399 400 return cn, nil 401 } 402 403 // setAcceptTxs sets AcceptTxs flag in 1CN case to receive tx propagation. 404 func (s *CN) setAcceptTxs() error { 405 if s.chainConfig.Istanbul != nil { 406 istanbulExtra, err := types.ExtractIstanbulExtra(s.blockchain.Genesis().Header()) 407 if err != nil { 408 return err 409 } else { 410 if len(istanbulExtra.Validators) == 1 { 411 s.protocolManager.SetAcceptTxs() 412 } 413 } 414 } 415 return nil 416 } 417 418 // setRewardWallet sets reward base and reward base wallet if the node is CN. 419 func (s *CN) setRewardWallet() error { 420 if s.protocolManager.NodeType() == common.CONSENSUSNODE { 421 wallet, err := s.RewardbaseWallet() 422 if err != nil { 423 return err 424 } else { 425 s.protocolManager.SetRewardbaseWallet(wallet) 426 } 427 s.protocolManager.SetRewardbase(s.rewardbase) 428 } 429 return nil 430 } 431 432 // add component which may be used in another service component 433 func (s *CN) addComponent(component interface{}) { 434 s.components = append(s.components, component) 435 } 436 437 func (s *CN) Components() []interface{} { 438 return s.components 439 } 440 441 func (s *CN) SetComponents(component []interface{}) { 442 // do nothing 443 } 444 445 // istanbul BFT 446 func makeExtraData(extra []byte) []byte { 447 if len(extra) == 0 { 448 // create default extradata 449 extra, _ = rlp.EncodeToBytes([]interface{}{ 450 uint(params.VersionMajor<<16 | params.VersionMinor<<8 | params.VersionPatch), 451 "klay", 452 runtime.Version(), 453 runtime.GOOS, 454 }) 455 } 456 if uint64(len(extra)) > params.GetMaximumExtraDataSize() { 457 logger.Warn("Miner extra data exceed limit", "extra", hexutil.Bytes(extra), "limit", params.GetMaximumExtraDataSize()) 458 extra = nil 459 } 460 return extra 461 } 462 463 // CreateDB creates the chain database. 464 func CreateDB(ctx *node.ServiceContext, config *Config, name string) database.DBManager { 465 dbc := &database.DBConfig{ 466 Dir: name, DBType: config.DBType, ParallelDBWrite: config.ParallelDBWrite, SingleDB: config.SingleDB, NumStateTrieShards: config.NumStateTrieShards, 467 LevelDBCacheSize: config.LevelDBCacheSize, OpenFilesLimit: database.GetOpenFilesLimit(), LevelDBCompression: config.LevelDBCompression, 468 LevelDBBufferPool: config.LevelDBBufferPool, EnableDBPerfMetrics: config.EnableDBPerfMetrics, DynamoDBConfig: &config.DynamoDBConfig, 469 } 470 return ctx.OpenDatabase(dbc) 471 } 472 473 // CreateConsensusEngine creates the required type of consensus engine instance for a Klaytn service 474 func CreateConsensusEngine(ctx *node.ServiceContext, config *Config, chainConfig *params.ChainConfig, db database.DBManager, gov governance.Engine, nodetype common.ConnType) consensus.Engine { 475 // Only istanbul BFT is allowed in the main net. PoA is supported by service chain 476 if chainConfig.Governance == nil { 477 chainConfig.Governance = params.GetDefaultGovernanceConfig() 478 } 479 return istanbulBackend.New(config.Rewardbase, &config.Istanbul, ctx.NodeKey(), db, gov, nodetype) 480 } 481 482 // APIs returns the collection of RPC services the ethereum package offers. 483 // NOTE, some of these services probably need to be moved to somewhere else. 484 func (s *CN) APIs() []rpc.API { 485 apis, ethAPI := api.GetAPIs(s.APIBackend, s.config.DisableUnsafeDebug) 486 487 // Append any APIs exposed explicitly by the consensus engine 488 apis = append(apis, s.engine.APIs(s.BlockChain())...) 489 490 publicFilterAPI := filters.NewPublicFilterAPI(s.APIBackend, false) 491 governanceKlayAPI := governance.NewGovernanceKlayAPI(s.governance, s.blockchain) 492 publicGovernanceAPI := governance.NewGovernanceAPI(s.governance) 493 publicDownloaderAPI := downloader.NewPublicDownloaderAPI(s.protocolManager.Downloader(), s.eventMux) 494 privateDownloaderAPI := downloader.NewPrivateDownloaderAPI(s.protocolManager.Downloader()) 495 496 ethAPI.SetPublicFilterAPI(publicFilterAPI) 497 ethAPI.SetGovernanceKlayAPI(governanceKlayAPI) 498 ethAPI.SetPublicGovernanceAPI(publicGovernanceAPI) 499 500 var tracerAPI *tracers.API 501 if s.config.DisableUnsafeDebug { 502 tracerAPI = tracers.NewAPIUnsafeDisabled(s.APIBackend) 503 } else { 504 tracerAPI = tracers.NewAPI(s.APIBackend) 505 apis = append(apis, []rpc.API{ 506 { 507 Namespace: "debug", 508 Version: "1.0", 509 Service: NewPrivateDebugAPI(s.chainConfig, s), 510 Public: false, 511 }, 512 }...) 513 } 514 515 // Append all the local APIs and return 516 return append(apis, []rpc.API{ 517 { 518 Namespace: "klay", 519 Version: "1.0", 520 Service: NewPublicKlayAPI(s), 521 Public: true, 522 }, { 523 Namespace: "klay", 524 Version: "1.0", 525 Service: publicDownloaderAPI, 526 Public: true, 527 }, { 528 Namespace: "klay", 529 Version: "1.0", 530 Service: publicFilterAPI, 531 Public: true, 532 }, { 533 Namespace: "eth", 534 Version: "1.0", 535 Service: publicDownloaderAPI, 536 Public: true, 537 }, { 538 Namespace: "admin", 539 Version: "1.0", 540 Service: privateDownloaderAPI, 541 }, { 542 Namespace: "admin", 543 Version: "1.0", 544 Service: NewPrivateAdminAPI(s), 545 }, { 546 Namespace: "debug", 547 Version: "1.0", 548 Service: NewPublicDebugAPI(s), 549 Public: false, 550 }, { 551 Namespace: "debug", 552 Version: "1.0", 553 Service: tracerAPI, 554 Public: false, 555 }, { 556 Namespace: "net", 557 Version: "1.0", 558 Service: s.netRPCService, 559 Public: true, 560 }, { 561 Namespace: "governance", 562 Version: "1.0", 563 Service: governance.NewGovernanceAPI(s.governance), 564 Public: true, 565 }, { 566 Namespace: "klay", 567 Version: "1.0", 568 Service: governanceKlayAPI, 569 Public: true, 570 }, { 571 Namespace: "eth", 572 Version: "1.0", 573 Service: ethAPI, 574 Public: true, 575 }, 576 }...) 577 } 578 579 func (s *CN) ResetWithGenesisBlock(gb *types.Block) { 580 s.blockchain.ResetWithGenesisBlock(gb) 581 } 582 583 func (s *CN) Rewardbase() (eb common.Address, err error) { 584 s.lock.RLock() 585 rewardbase := s.rewardbase 586 s.lock.RUnlock() 587 588 if rewardbase != (common.Address{}) { 589 return rewardbase, nil 590 } 591 if wallets := s.AccountManager().Wallets(); len(wallets) > 0 { 592 if accounts := wallets[0].Accounts(); len(accounts) > 0 { 593 rewardbase := accounts[0].Address 594 595 s.lock.Lock() 596 s.rewardbase = rewardbase 597 s.lock.Unlock() 598 599 logger.Info("Rewardbase automatically configured", "address", rewardbase) 600 return rewardbase, nil 601 } 602 } 603 604 return common.Address{}, fmt.Errorf("rewardbase must be explicitly specified") 605 } 606 607 func (s *CN) RewardbaseWallet() (accounts.Wallet, error) { 608 rewardBase, err := s.Rewardbase() 609 if err != nil { 610 return nil, err 611 } 612 613 account := accounts.Account{Address: rewardBase} 614 wallet, err := s.AccountManager().Find(account) 615 if err != nil { 616 logger.Error("find err", "err", err) 617 return nil, err 618 } 619 return wallet, nil 620 } 621 622 func (s *CN) SetRewardbase(rewardbase common.Address) { 623 s.lock.Lock() 624 s.rewardbase = rewardbase 625 s.lock.Unlock() 626 wallet, err := s.RewardbaseWallet() 627 if err != nil { 628 logger.Error("find err", "err", err) 629 } 630 s.protocolManager.SetRewardbase(rewardbase) 631 s.protocolManager.SetRewardbaseWallet(wallet) 632 } 633 634 func (s *CN) StartMining(local bool) error { 635 if local { 636 // If local (CPU) mining is started, we can disable the transaction rejection 637 // mechanism introduced to speed sync times. CPU mining on mainnet is ludicrous 638 // so none will ever hit this path, whereas marking sync done on CPU mining 639 // will ensure that private networks work in single miner mode too. 640 s.protocolManager.SetAcceptTxs() 641 } 642 go s.miner.Start() 643 return nil 644 } 645 646 func (s *CN) StopMining() { s.miner.Stop() } 647 func (s *CN) IsMining() bool { return s.miner.Mining() } 648 func (s *CN) Miner() Miner { return s.miner } 649 650 func (s *CN) AccountManager() accounts.AccountManager { return s.accountManager } 651 func (s *CN) BlockChain() work.BlockChain { return s.blockchain } 652 func (s *CN) TxPool() work.TxPool { return s.txPool } 653 func (s *CN) EventMux() *event.TypeMux { return s.eventMux } 654 func (s *CN) Engine() consensus.Engine { return s.engine } 655 func (s *CN) ChainDB() database.DBManager { return s.chainDB } 656 func (s *CN) IsListening() bool { return true } // Always listening 657 func (s *CN) ProtocolVersion() int { return s.protocolManager.ProtocolVersion() } 658 func (s *CN) NetVersion() uint64 { return s.networkId } 659 func (s *CN) Progress() klaytn.SyncProgress { return s.protocolManager.Downloader().Progress() } 660 func (s *CN) Governance() governance.Engine { return s.governance } 661 662 func (s *CN) ReBroadcastTxs(transactions types.Transactions) { 663 s.protocolManager.ReBroadcastTxs(transactions) 664 } 665 666 // Protocols implements node.Service, returning all the currently configured 667 // network protocols to start. 668 func (s *CN) Protocols() []p2p.Protocol { 669 if s.lesServer == nil { 670 return s.protocolManager.GetSubProtocols() 671 } 672 return append(s.protocolManager.GetSubProtocols(), s.lesServer.Protocols()...) 673 } 674 675 // Start implements node.Service, starting all internal goroutines needed by the 676 // Klaytn protocol implementation. 677 func (s *CN) Start(srvr p2p.Server) error { 678 // Start the bloom bits servicing goroutines 679 s.startBloomHandlers() 680 681 // Start the RPC service 682 s.netRPCService = api.NewPublicNetAPI(srvr, s.NetVersion()) 683 684 // Figure out a max peers count based on the server limits 685 maxPeers := srvr.MaxPeers() 686 // Start the networking layer and the light server if requested 687 s.protocolManager.Start(maxPeers) 688 if s.lesServer != nil { 689 s.lesServer.Start(srvr) 690 } 691 692 reward.StakingManagerSubscribe() 693 694 return nil 695 } 696 697 // Stop implements node.Service, terminating all internal goroutines used by the 698 // Klaytn protocol. 699 func (s *CN) Stop() error { 700 // Stop all the peer-related stuff first. 701 s.protocolManager.Stop() 702 if s.lesServer != nil { 703 s.lesServer.Stop() 704 } 705 706 // Then stop everything else. 707 s.bloomIndexer.Close() 708 close(s.closeBloomHandler) 709 s.txPool.Stop() 710 s.miner.Stop() 711 reward.StakingManagerUnsubscribe() 712 s.blockchain.Stop() 713 s.chainDB.Close() 714 s.eventMux.Stop() 715 716 return nil 717 }