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