github.com/aergoio/aergo@v1.3.1/chain/chainservice.go (about)

     1  /**
     2   *  @file
     3   *  @copyright defined in aergo/LICENSE.txt
     4   */
     5  
     6  package chain
     7  
     8  import (
     9  	"encoding/json"
    10  	"errors"
    11  	"fmt"
    12  	"math/big"
    13  	"reflect"
    14  	"runtime"
    15  	"strings"
    16  	"sync/atomic"
    17  
    18  	"github.com/aergoio/aergo-actor/actor"
    19  	"github.com/aergoio/aergo-lib/log"
    20  	cfg "github.com/aergoio/aergo/config"
    21  	"github.com/aergoio/aergo/consensus"
    22  	"github.com/aergoio/aergo/contract"
    23  	"github.com/aergoio/aergo/contract/enterprise"
    24  	"github.com/aergoio/aergo/contract/name"
    25  	"github.com/aergoio/aergo/contract/system"
    26  	"github.com/aergoio/aergo/fee"
    27  	"github.com/aergoio/aergo/internal/enc"
    28  	"github.com/aergoio/aergo/message"
    29  	"github.com/aergoio/aergo/pkg/component"
    30  	"github.com/aergoio/aergo/state"
    31  	"github.com/aergoio/aergo/types"
    32  	lru "github.com/hashicorp/golang-lru"
    33  )
    34  
    35  var (
    36  	logger = log.NewLogger("chain")
    37  
    38  	dfltErrBlocks = 128
    39  
    40  	ErrNotSupportedConsensus = errors.New("not supported by this consensus")
    41  	ErrRecoNoBestStateRoot   = errors.New("state root of best block is not exist")
    42  	ErrRecoInvalidSdbRoot    = errors.New("state root of sdb is invalid")
    43  
    44  	TestDebugger *Debugger
    45  )
    46  
    47  // Core represents a storage layer of a blockchain (chain & state DB).
    48  type Core struct {
    49  	cdb *ChainDB
    50  	sdb *state.ChainStateDB
    51  }
    52  
    53  // NewCore returns an instance of Core.
    54  func NewCore(dbType string, dataDir string, testModeOn bool, forceResetHeight types.BlockNo) (*Core, error) {
    55  	core := &Core{
    56  		cdb: NewChainDB(),
    57  		sdb: state.NewChainStateDB(),
    58  	}
    59  
    60  	err := core.init(dbType, dataDir, testModeOn, forceResetHeight)
    61  	if err != nil {
    62  		return nil, err
    63  	}
    64  
    65  	return core, nil
    66  }
    67  
    68  // Init prepares Core (chain & state DB).
    69  func (core *Core) init(dbType string, dataDir string, testModeOn bool, forceResetHeight types.BlockNo) error {
    70  	// init chaindb
    71  	if err := core.cdb.Init(dbType, dataDir); err != nil {
    72  		logger.Fatal().Err(err).Msg("failed to initialize chaindb")
    73  		return err
    74  	}
    75  
    76  	if forceResetHeight > 0 {
    77  		if err := core.cdb.ResetBest(forceResetHeight); err != nil {
    78  			logger.Fatal().Err(err).Uint64("height", forceResetHeight).Msg("failed to reset chaindb")
    79  			return err
    80  		}
    81  	}
    82  
    83  	// init statedb
    84  	bestBlock, err := core.cdb.GetBestBlock()
    85  	if err != nil {
    86  		return err
    87  	}
    88  
    89  	if err := core.sdb.Init(dbType, dataDir, bestBlock, testModeOn); err != nil {
    90  		logger.Fatal().Err(err).Msg("failed to initialize statedb")
    91  		return err
    92  	}
    93  
    94  	contract.LoadDatabase(dataDir)
    95  
    96  	return nil
    97  }
    98  
    99  func (core *Core) initGenesis(genesis *types.Genesis, mainnet bool, testmode bool) (*types.Block, error) {
   100  
   101  	gen := core.cdb.GetGenesisInfo()
   102  	if gen == nil {
   103  		logger.Info().Msg("generating genesis block..")
   104  		if testmode {
   105  			if !mainnet {
   106  				logger.Warn().Msg("--testnet opt will ignored due to testmode")
   107  			}
   108  			genesis = types.GetTestGenesis()
   109  		} else {
   110  			if genesis == nil {
   111  				if mainnet {
   112  					//return nil, errors.New("to use mainnet, create genesis manually (visit http://docs.aergo.io)")
   113  					genesis = types.GetMainNetGenesis()
   114  				} else {
   115  					genesis = types.GetTestNetGenesis()
   116  				}
   117  			}
   118  		}
   119  
   120  		err := core.sdb.SetGenesis(genesis, InitGenesisBPs)
   121  		if err != nil {
   122  			logger.Fatal().Err(err).Msg("cannot set statedb of genesisblock")
   123  			return nil, err
   124  		}
   125  
   126  		err = core.cdb.addGenesisBlock(genesis)
   127  		if err != nil {
   128  			logger.Fatal().Err(err).Msg("cannot add genesisblock")
   129  			return nil, err
   130  		}
   131  		gen = genesis
   132  	} else {
   133  		if !mainnet {
   134  			logger.Warn().Msg("--testnet option will be ignored")
   135  		}
   136  		if testmode && !gen.HasDevChainID() {
   137  			logger.Info().Str("chain id", gen.ID.ToJSON()).Msg("current genesis info")
   138  			return nil, errors.New("do not run testmode on non dev-chain")
   139  		}
   140  	}
   141  
   142  	initChainParams(gen)
   143  
   144  	genesisBlock, _ := core.cdb.GetBlockByNo(0)
   145  
   146  	logger.Info().Str("chain id", gen.ID.ToJSON()).
   147  		Str("hash", enc.ToString(genesisBlock.GetHash())).Msg("chain initialized")
   148  	return genesisBlock, nil
   149  }
   150  
   151  func (core *Core) GetGenesisInfo() *types.Genesis {
   152  	return core.cdb.GetGenesisInfo()
   153  }
   154  
   155  // Close closes chain & state DB.
   156  func (core *Core) Close() {
   157  	if core.sdb != nil {
   158  		core.sdb.Close()
   159  	}
   160  	if core.cdb != nil {
   161  		core.cdb.Close()
   162  	}
   163  	contract.CloseDatabase()
   164  }
   165  
   166  // InitGenesisBlock initialize chain database and generate specified genesis block if necessary
   167  func (core *Core) InitGenesisBlock(gb *types.Genesis, useTestnet bool) error {
   168  	_, err := core.initGenesis(gb, useTestnet, false)
   169  	if err != nil {
   170  		logger.Fatal().Err(err).Msg("cannot initialize genesis block")
   171  		return err
   172  	}
   173  	return nil
   174  }
   175  
   176  type IChainHandler interface {
   177  	getBlock(blockHash []byte) (*types.Block, error)
   178  	getBlockByNo(blockNo types.BlockNo) (*types.Block, error)
   179  	getTx(txHash []byte) (*types.Tx, *types.TxIdx, error)
   180  	getReceipt(txHash []byte) (*types.Receipt, error)
   181  	getAccountVote(id []string, addr []byte) (*types.AccountVoteInfo, error)
   182  	getVotes(id string, n uint32) (*types.VoteList, error)
   183  	getStaking(addr []byte) (*types.Staking, error)
   184  	getNameInfo(name string, blockNo types.BlockNo) (*types.NameInfo, error)
   185  	getEnterpriseConf(key string) (*types.EnterpriseConfig, error)
   186  	addBlock(newBlock *types.Block, usedBstate *state.BlockState, peerID types.PeerID) error
   187  	getAnchorsNew() (ChainAnchor, types.BlockNo, error)
   188  	findAncestor(Hashes [][]byte) (*types.BlockInfo, error)
   189  	setSkipMempool(val bool)
   190  	listEvents(filter *types.FilterInfo) ([]*types.Event, error)
   191  	verifyBlock(block *types.Block) error
   192  }
   193  
   194  // ChainService manage connectivity of blocks
   195  type ChainService struct {
   196  	*component.BaseComponent
   197  	consensus.ChainConsensus
   198  	*Core
   199  
   200  	cfg       *cfg.Config
   201  	op        *OrphanPool
   202  	errBlocks *lru.Cache
   203  
   204  	validator *BlockValidator
   205  
   206  	chainWorker   *ChainWorker
   207  	chainManager  *ChainManager
   208  	chainVerifier *ChainVerifier
   209  
   210  	stat stats
   211  
   212  	recovered  atomic.Value
   213  	debuggable bool
   214  }
   215  
   216  // NewChainService creates an instance of ChainService.
   217  func NewChainService(cfg *cfg.Config) *ChainService {
   218  	cs := &ChainService{
   219  		cfg:  cfg,
   220  		op:   NewOrphanPool(DfltOrphanPoolSize),
   221  		stat: newStats(),
   222  	}
   223  
   224  	cs.setRecovered(false)
   225  
   226  	var err error
   227  	if cs.Core, err = NewCore(cfg.DbType, cfg.DataDir, cfg.EnableTestmode, types.BlockNo(cfg.Blockchain.ForceResetHeight)); err != nil {
   228  		logger.Fatal().Err(err).Msg("failed to initialize DB")
   229  		panic(err)
   230  	}
   231  
   232  	if err = Init(cfg.Blockchain.MaxBlockSize,
   233  		cfg.Blockchain.CoinbaseAccount,
   234  		cfg.Consensus.EnableBp,
   235  		cfg.Blockchain.MaxAnchorCount,
   236  		cfg.Blockchain.VerifierCount); err != nil {
   237  		logger.Error().Err(err).Msg("failed to init chainservice")
   238  		panic("invalid config: blockchain")
   239  	}
   240  
   241  	cs.validator = NewBlockValidator(cs, cs.sdb)
   242  	cs.BaseComponent = component.NewBaseComponent(message.ChainSvc, cs, logger)
   243  	cs.chainManager = newChainManager(cs, cs.Core)
   244  	cs.chainWorker = newChainWorker(cs, defaultChainWorkerCount, cs.Core)
   245  	if cs.cfg.Blockchain.VerifyOnly {
   246  		if cs.cfg.Consensus.EnableBp {
   247  			logger.Fatal().Err(err).Msg("can't be enableBp at verifyOnly mode")
   248  		}
   249  		cs.chainVerifier = newChainVerifier(cs, cs.Core)
   250  	}
   251  
   252  	cs.errBlocks, err = lru.New(dfltErrBlocks)
   253  	if err != nil {
   254  		logger.Fatal().Err(err).Msg("failed to init lru")
   255  		return nil
   256  	}
   257  
   258  	// init genesis block
   259  	if _, err := cs.initGenesis(nil, !cfg.UseTestnet, cfg.EnableTestmode); err != nil {
   260  		logger.Fatal().Err(err).Msg("failed to create a genesis block")
   261  		panic("failed to init genesis block")
   262  	}
   263  
   264  	if ConsensusName() == consensus.ConsensusName[consensus.ConsensusDPOS] {
   265  		top, err := cs.getVotes(types.VoteBP[2:], 1)
   266  		if err != nil {
   267  			logger.Debug().Err(err).Msg("failed to get elected BPs")
   268  		} else {
   269  			for _, res := range top.Votes {
   270  				logger.Debug().Str("BP", enc.ToString(res.Candidate)).
   271  					Str("votes", new(big.Int).SetBytes(res.Amount).String()).Msgf("BP vote stat")
   272  			}
   273  		}
   274  	}
   275  
   276  	// init related modules
   277  	if !pubNet && cfg.Blockchain.ZeroFee {
   278  		fee.EnableZeroFee()
   279  	}
   280  	logger.Info().Bool("enablezerofee", fee.IsZeroFee()).Msg("fee")
   281  	contract.PubNet = pubNet
   282  	contract.TraceBlockNo = cfg.Blockchain.StateTrace
   283  	contract.SetStateSQLMaxDBSize(cfg.SQL.MaxDbSize)
   284  	contract.StartLStateFactory()
   285  
   286  	// For a strict governance transaction validation.
   287  	types.InitGovernance(cs.ConsensusType(), cs.IsPublic())
   288  	system.InitGovernance(cs.ConsensusType())
   289  
   290  	// init Debugger
   291  	cs.initDebugger()
   292  
   293  	cs.startChilds()
   294  
   295  	return cs
   296  }
   297  
   298  func (cs *ChainService) startChilds() {
   299  	if !cs.cfg.Blockchain.VerifyOnly {
   300  		cs.chainManager.Start()
   301  		cs.chainWorker.Start()
   302  	} else {
   303  		cs.chainVerifier.Start()
   304  	}
   305  }
   306  
   307  func (cs *ChainService) initDebugger() {
   308  	TestDebugger = newDebugger()
   309  }
   310  
   311  // SDB returns cs.sdb.
   312  func (cs *ChainService) SDB() *state.ChainStateDB {
   313  	return cs.sdb
   314  }
   315  
   316  // CDB returns cs.sdb as a consensus.ChainDbReader.
   317  func (cs *ChainService) CDB() consensus.ChainDB {
   318  	return cs.cdb
   319  }
   320  
   321  // CDB returns cs.sdb as a consensus.ChainDbReader.
   322  func (cs *ChainService) WalDB() consensus.ChainWAL {
   323  	return cs.cdb
   324  }
   325  
   326  // GetConsensusInfo returns consensus-related information, which is different
   327  // from consensus to consensus.
   328  func (cs *ChainService) GetConsensusInfo() string {
   329  	if cs.ChainConsensus == nil {
   330  		return ""
   331  	}
   332  
   333  	return cs.Info()
   334  }
   335  
   336  func (cs *ChainService) GetChainStats() string {
   337  	return cs.stat.JSON()
   338  }
   339  
   340  //GetEnterpriseConfig return EnterpiseConfig. if the given key does not exist, fill EnterpriseConfig with only the key and return
   341  func (cs *ChainService) GetEnterpriseConfig(key string) (*types.EnterpriseConfig, error) {
   342  	return cs.getEnterpriseConf(key)
   343  }
   344  
   345  func (cs *ChainService) GetSystemValue(key types.SystemValue) (*big.Int, error) {
   346  	return cs.getSystemValue(key)
   347  }
   348  
   349  // SetChainConsensus sets cs.cc to cc.
   350  func (cs *ChainService) SetChainConsensus(cc consensus.ChainConsensus) {
   351  	cs.ChainConsensus = cc
   352  	cs.cdb.cc = cc
   353  }
   354  
   355  // BeforeStart initialize chain database and generate empty genesis block if necessary
   356  func (cs *ChainService) BeforeStart() {
   357  }
   358  
   359  // AfterStart ... do nothing
   360  func (cs *ChainService) AfterStart() {
   361  }
   362  
   363  // BeforeStop close chain database and stop BlockValidator
   364  func (cs *ChainService) BeforeStop() {
   365  	cs.Close()
   366  
   367  	cs.chainManager.Stop()
   368  	cs.chainWorker.Stop()
   369  
   370  	cs.validator.Stop()
   371  }
   372  
   373  func (cs *ChainService) notifyBlock(block *types.Block, isByBP bool) {
   374  	cs.BaseComponent.RequestTo(message.P2PSvc,
   375  		&message.NotifyNewBlock{
   376  			Produced: isByBP,
   377  			BlockNo:  block.Header.BlockNo,
   378  			Block:    block,
   379  		})
   380  }
   381  
   382  func (cs *ChainService) setRecovered(val bool) {
   383  	cs.recovered.Store(val)
   384  	return
   385  }
   386  
   387  func (cs *ChainService) isRecovered() bool {
   388  	var val bool
   389  	aopv := cs.recovered.Load()
   390  	if aopv != nil {
   391  		val = aopv.(bool)
   392  	} else {
   393  		panic("ChainService: recovered is nil")
   394  	}
   395  	return val
   396  }
   397  
   398  // Receive actor message
   399  func (cs *ChainService) Receive(context actor.Context) {
   400  	if !cs.isRecovered() {
   401  		err := cs.Recover()
   402  		if err != nil {
   403  			logger.Fatal().Err(err).Msg("CHAIN DATA IS CRASHED, BUT CAN'T BE RECOVERED")
   404  		}
   405  
   406  		cs.setRecovered(true)
   407  	}
   408  
   409  	switch msg := context.Message().(type) {
   410  	case *message.AddBlock,
   411  		*message.GetAnchors, //TODO move to ChainWorker (need chain lock)
   412  		*message.GetAncestor:
   413  		cs.chainManager.Request(msg, context.Sender())
   414  
   415  		//pass to chainWorker
   416  	case *message.GetBlock,
   417  		*message.GetBlockByNo,
   418  		*message.GetState,
   419  		*message.GetStateAndProof,
   420  		*message.GetTx,
   421  		*message.GetReceipt,
   422  		*message.GetABI,
   423  		*message.GetQuery,
   424  		*message.GetStateQuery,
   425  		*message.GetElected,
   426  		*message.GetVote,
   427  		*message.GetStaking,
   428  		*message.GetNameInfo,
   429  		*message.GetEnterpriseConf,
   430  		*message.ListEvents:
   431  		cs.chainWorker.Request(msg, context.Sender())
   432  
   433  		//handle directly
   434  	case *message.GetBestBlockNo:
   435  		context.Respond(message.GetBestBlockNoRsp{
   436  			BlockNo: cs.getBestBlockNo(),
   437  		})
   438  	case *message.GetBestBlock:
   439  		block, err := cs.GetBestBlock()
   440  		if err != nil {
   441  			logger.Error().Err(err).Msg("failed to get best block")
   442  		}
   443  		context.Respond(message.GetBestBlockRsp{
   444  			Block: block,
   445  			Err:   err,
   446  		})
   447  	case *message.MemPoolDelRsp:
   448  		err := msg.Err
   449  		if err != nil {
   450  			logger.Error().Err(err).Msg("failed to remove txs from mempool")
   451  		}
   452  	case actor.SystemMessage,
   453  		actor.AutoReceiveMessage,
   454  		actor.NotInfluenceReceiveTimeout:
   455  		//logger.Debugf("Received message. (%v) %s", reflect.TypeOf(msg), msg)
   456  
   457  	default:
   458  		//logger.Debugf("Missed message. (%v) %s", reflect.TypeOf(msg), msg)
   459  	}
   460  }
   461  
   462  func (cs *ChainService) Statistics() *map[string]interface{} {
   463  	if cs.chainVerifier != nil {
   464  		return cs.chainVerifier.Statistics()
   465  	}
   466  	return &map[string]interface{}{
   467  		"testmode": cs.cfg.EnableTestmode,
   468  		"testnet":  cs.cfg.UseTestnet,
   469  		"orphan":   cs.op.curCnt,
   470  		"config":   cs.cfg.Blockchain,
   471  	}
   472  }
   473  
   474  func (cs *ChainService) GetChainTree() ([]byte, error) {
   475  	return cs.cdb.GetChainTree()
   476  }
   477  
   478  func (cs *ChainService) getVotes(id string, n uint32) (*types.VoteList, error) {
   479  	switch ConsensusName() {
   480  	case consensus.ConsensusName[consensus.ConsensusDPOS]:
   481  		return system.GetVoteResult(cs.sdb, []byte(id), int(n))
   482  	case consensus.ConsensusName[consensus.ConsensusRAFT]:
   483  		//return cs.GetBPs()
   484  		return nil, ErrNotSupportedConsensus
   485  	default:
   486  		return nil, ErrNotSupportedConsensus
   487  	}
   488  }
   489  
   490  func (cs *ChainService) getAccountVote(ids []string, addr []byte) (*types.AccountVoteInfo, error) {
   491  	if cs.GetType() != consensus.ConsensusDPOS {
   492  		return nil, ErrNotSupportedConsensus
   493  	}
   494  
   495  	scs, err := cs.sdb.GetSystemAccountState()
   496  	if err != nil {
   497  		return nil, err
   498  	}
   499  
   500  	var voteInfo types.AccountVoteInfo
   501  
   502  	for _, id := range ids {
   503  		vote, err := system.GetVote(scs, addr, []byte(id))
   504  		if err != nil {
   505  			return nil, err
   506  		}
   507  		var candidates []string
   508  		to := vote.GetCandidate()
   509  		if len(to) == 0 {
   510  			continue
   511  		}
   512  		if id == types.VoteBP[2:] {
   513  			for offset := 0; offset < len(to); offset += system.PeerIDLength {
   514  				candidates = append(candidates, types.EncodeB58(to[offset:offset+system.PeerIDLength]))
   515  			}
   516  		} else {
   517  			err := json.Unmarshal(to, &candidates)
   518  			if err != nil {
   519  				return nil, err
   520  			}
   521  		}
   522  		voteInfo.Voting = append(voteInfo.Voting, &types.VoteInfo{Id: id, Candidates: candidates})
   523  	}
   524  
   525  	return &voteInfo, nil
   526  }
   527  
   528  func (cs *ChainService) getStaking(addr []byte) (*types.Staking, error) {
   529  	if cs.GetType() != consensus.ConsensusDPOS {
   530  		return nil, ErrNotSupportedConsensus
   531  	}
   532  
   533  	scs, err := cs.sdb.GetStateDB().OpenContractStateAccount(types.ToAccountID([]byte(types.AergoSystem)))
   534  	if err != nil {
   535  		return nil, err
   536  	}
   537  	namescs, err := cs.sdb.GetStateDB().OpenContractStateAccount(types.ToAccountID([]byte(types.AergoName)))
   538  	if err != nil {
   539  		return nil, err
   540  	}
   541  	staking, err := system.GetStaking(scs, name.GetAddress(namescs, addr))
   542  	if err != nil {
   543  		return nil, err
   544  	}
   545  	return staking, nil
   546  }
   547  
   548  func (cs *ChainService) getNameInfo(qname string, blockNo types.BlockNo) (*types.NameInfo, error) {
   549  	var stateDB *state.StateDB
   550  	if blockNo != 0 {
   551  		block, err := cs.cdb.GetBlockByNo(blockNo)
   552  		if err != nil {
   553  			return nil, err
   554  		}
   555  		stateDB = cs.sdb.OpenNewStateDB(block.GetHeader().GetBlocksRootHash())
   556  	} else {
   557  		stateDB = cs.sdb.GetStateDB()
   558  	}
   559  	return name.GetNameInfo(stateDB, qname)
   560  }
   561  
   562  func (cs *ChainService) getEnterpriseConf(key string) (*types.EnterpriseConfig, error) {
   563  	stateDB := cs.sdb.GetStateDB()
   564  	if strings.ToUpper(key) != enterprise.AdminsKey {
   565  		return enterprise.GetConf(stateDB, key)
   566  	}
   567  	return enterprise.GetAdmin(stateDB)
   568  }
   569  
   570  func (cs *ChainService) getSystemValue(key types.SystemValue) (*big.Int, error) {
   571  	stateDB := cs.sdb.GetStateDB()
   572  	switch key {
   573  	case types.StakingTotal:
   574  		return system.GetStakingTotal(stateDB)
   575  	}
   576  	return nil, fmt.Errorf("unsupported system value : %s", key)
   577  }
   578  
   579  type ChainManager struct {
   580  	*SubComponent
   581  	IChainHandler //to use chain APIs
   582  	*Core         // TODO remove after moving GetQuery to ChainWorker
   583  }
   584  
   585  type ChainWorker struct {
   586  	*SubComponent
   587  	IChainHandler //to use chain APIs
   588  	*Core
   589  }
   590  
   591  var (
   592  	chainManagerName  = "Chain Manager"
   593  	chainWorkerName   = "Chain Worker"
   594  	chainVerifierName = "Chain Verifier"
   595  )
   596  
   597  func newChainManager(cs *ChainService, core *Core) *ChainManager {
   598  	chainManager := &ChainManager{IChainHandler: cs, Core: core}
   599  	chainManager.SubComponent = NewSubComponent(chainManager, cs.BaseComponent, chainManagerName, 1)
   600  
   601  	return chainManager
   602  }
   603  
   604  func newChainWorker(cs *ChainService, cntWorker int, core *Core) *ChainWorker {
   605  	chainWorker := &ChainWorker{IChainHandler: cs, Core: core}
   606  	chainWorker.SubComponent = NewSubComponent(chainWorker, cs.BaseComponent, chainWorkerName, cntWorker)
   607  
   608  	return chainWorker
   609  }
   610  
   611  func (cm *ChainManager) Receive(context actor.Context) {
   612  	defer RecoverExit()
   613  
   614  	switch msg := context.Message().(type) {
   615  
   616  	case *message.AddBlock:
   617  		runtime.LockOSThread()
   618  		defer runtime.UnlockOSThread()
   619  
   620  		block := msg.Block
   621  		logger.Info().Str("hash", block.ID()).Str("prev", block.PrevID()).Uint64("bestno", cm.cdb.getBestBlockNo()).
   622  			Uint64("no", block.GetHeader().GetBlockNo()).Bool("syncer", msg.IsSync).Msg("add block chainservice")
   623  
   624  		var bstate *state.BlockState
   625  		if msg.Bstate != nil {
   626  			bstate = msg.Bstate.(*state.BlockState)
   627  		}
   628  		err := cm.addBlock(block, bstate, msg.PeerID)
   629  		if err != nil {
   630  			logger.Error().Err(err).Uint64("no", block.GetHeader().BlockNo).Str("hash", block.ID()).Msg("failed to add block")
   631  		}
   632  		blkNo := block.GetHeader().GetBlockNo()
   633  		blkHash := block.BlockHash()
   634  
   635  		rsp := message.AddBlockRsp{
   636  			BlockNo:   blkNo,
   637  			BlockHash: blkHash,
   638  			Err:       err,
   639  		}
   640  
   641  		context.Respond(&rsp)
   642  	case *message.GetAnchors:
   643  		anchor, lastNo, err := cm.getAnchorsNew()
   644  		context.Respond(message.GetAnchorsRsp{
   645  			Seq:    msg.Seq,
   646  			Hashes: anchor,
   647  			LastNo: lastNo,
   648  			Err:    err,
   649  		})
   650  	case *message.GetAncestor:
   651  		hashes := msg.Hashes
   652  		ancestor, err := cm.findAncestor(hashes)
   653  		context.Respond(message.GetAncestorRsp{
   654  			Ancestor: ancestor,
   655  			Err:      err,
   656  		})
   657  	case *actor.Started, *actor.Stopping, *actor.Stopped, *component.CompStatReq: // donothing
   658  	default:
   659  		debug := fmt.Sprintf("[%s] Missed message. (%v) %s", cm.name, reflect.TypeOf(msg), msg)
   660  		logger.Debug().Msg(debug)
   661  	}
   662  }
   663  
   664  func getAddressNameResolved(sdb *state.ChainStateDB, account []byte) ([]byte, error) {
   665  	if len(account) == types.NameLength {
   666  		scs, err := sdb.GetStateDB().OpenContractStateAccount(types.ToAccountID([]byte(types.AergoName)))
   667  		if err != nil {
   668  			logger.Error().Str("hash", enc.ToString(account)).Err(err).Msg("failed to get state for account")
   669  			return nil, err
   670  		}
   671  		return name.GetAddress(scs, account), nil
   672  	}
   673  	return account, nil
   674  }
   675  
   676  func (cw *ChainWorker) Receive(context actor.Context) {
   677  	switch msg := context.Message().(type) {
   678  	case *message.GetBlock:
   679  		bid := types.ToBlockID(msg.BlockHash)
   680  		block, err := cw.getBlock(bid[:])
   681  		if err != nil {
   682  			logger.Debug().Err(err).Str("hash", enc.ToString(msg.BlockHash)).Msg("block not found")
   683  		}
   684  		context.Respond(message.GetBlockRsp{
   685  			Block: block,
   686  			Err:   err,
   687  		})
   688  	case *message.GetBlockByNo:
   689  		block, err := cw.getBlockByNo(msg.BlockNo)
   690  		if err != nil {
   691  			logger.Error().Err(err).Uint64("blockNo", msg.BlockNo).Msg("failed to get block by no")
   692  		}
   693  		context.Respond(message.GetBlockByNoRsp{
   694  			Block: block,
   695  			Err:   err,
   696  		})
   697  	case *message.GetState:
   698  		address, err := getAddressNameResolved(cw.sdb, msg.Account)
   699  		if err != nil {
   700  			context.Respond(message.GetStateRsp{
   701  				Account: msg.Account,
   702  				State:   nil,
   703  				Err:     err,
   704  			})
   705  			return
   706  		}
   707  		id := types.ToAccountID(address)
   708  		accState, err := cw.sdb.GetStateDB().GetAccountState(id)
   709  		if err != nil {
   710  			logger.Error().Str("hash", enc.ToString(address)).Err(err).Msg("failed to get state for account")
   711  		}
   712  		context.Respond(message.GetStateRsp{
   713  			Account: address,
   714  			State:   accState,
   715  			Err:     err,
   716  		})
   717  	case *message.GetStateAndProof:
   718  		address, err := getAddressNameResolved(cw.sdb, msg.Account)
   719  		if err != nil {
   720  			context.Respond(message.GetStateAndProofRsp{
   721  				StateProof: nil,
   722  				Err:        err,
   723  			})
   724  			break
   725  		}
   726  		id := types.ToAccountID(address)
   727  		stateProof, err := cw.sdb.GetStateDB().GetAccountAndProof(id[:], msg.Root, msg.Compressed)
   728  		if err != nil {
   729  			logger.Error().Str("hash", enc.ToString(address)).Err(err).Msg("failed to get state for account")
   730  		}
   731  		stateProof.Key = address
   732  		context.Respond(message.GetStateAndProofRsp{
   733  			StateProof: stateProof,
   734  			Err:        err,
   735  		})
   736  	case *message.GetTx:
   737  		tx, txIdx, err := cw.getTx(msg.TxHash)
   738  		context.Respond(message.GetTxRsp{
   739  			Tx:    tx,
   740  			TxIds: txIdx,
   741  			Err:   err,
   742  		})
   743  	case *message.GetReceipt:
   744  		receipt, err := cw.getReceipt(msg.TxHash)
   745  		context.Respond(message.GetReceiptRsp{
   746  			Receipt: receipt,
   747  			Err:     err,
   748  		})
   749  	case *message.GetABI:
   750  		address, err := getAddressNameResolved(cw.sdb, msg.Contract)
   751  		if err != nil {
   752  			context.Respond(message.GetABIRsp{
   753  				ABI: nil,
   754  				Err: err,
   755  			})
   756  			break
   757  		}
   758  		contractState, err := cw.sdb.GetStateDB().OpenContractStateAccount(types.ToAccountID(address))
   759  		if err == nil {
   760  			abi, err := contract.GetABI(contractState)
   761  			context.Respond(message.GetABIRsp{
   762  				ABI: abi,
   763  				Err: err,
   764  			})
   765  		} else {
   766  			context.Respond(message.GetABIRsp{
   767  				ABI: nil,
   768  				Err: err,
   769  			})
   770  		}
   771  	case *message.GetQuery:
   772  		runtime.LockOSThread()
   773  		defer runtime.UnlockOSThread()
   774  		address, err := getAddressNameResolved(cw.sdb, msg.Contract)
   775  		if err != nil {
   776  			context.Respond(message.GetQueryRsp{Result: nil, Err: err})
   777  			break
   778  		}
   779  		ctrState, err := cw.sdb.GetStateDB().OpenContractStateAccount(types.ToAccountID(address))
   780  		if err != nil {
   781  			logger.Error().Str("hash", enc.ToString(address)).Err(err).Msg("failed to get state for contract")
   782  			context.Respond(message.GetQueryRsp{Result: nil, Err: err})
   783  		} else {
   784  			bs := state.NewBlockState(cw.sdb.OpenNewStateDB(cw.sdb.GetRoot()))
   785  			ret, err := contract.Query(address, bs, cw.cdb, ctrState, msg.Queryinfo)
   786  			context.Respond(message.GetQueryRsp{Result: ret, Err: err})
   787  		}
   788  	case *message.GetStateQuery:
   789  		var varProofs []*types.ContractVarProof
   790  		var contractProof *types.AccountProof
   791  		var err error
   792  
   793  		address, err := getAddressNameResolved(cw.sdb, msg.ContractAddress)
   794  		if err != nil {
   795  			context.Respond(message.GetStateQueryRsp{
   796  				Result: nil,
   797  				Err:    err,
   798  			})
   799  			break
   800  		}
   801  		id := types.ToAccountID(address)
   802  		contractProof, err = cw.sdb.GetStateDB().GetAccountAndProof(id[:], msg.Root, msg.Compressed)
   803  		if err != nil {
   804  			logger.Error().Str("hash", enc.ToString(address)).Err(err).Msg("failed to get state for account")
   805  		} else if contractProof.Inclusion {
   806  			contractTrieRoot := contractProof.State.StorageRoot
   807  			for _, storageKey := range msg.StorageKeys {
   808  				varProof, err := cw.sdb.GetStateDB().GetVarAndProof(storageKey, contractTrieRoot, msg.Compressed)
   809  				varProof.Key = storageKey
   810  				varProofs = append(varProofs, varProof)
   811  				if err != nil {
   812  					logger.Error().Str("hash", enc.ToString(address)).Err(err).Msg("failed to get state variable in contract")
   813  				}
   814  			}
   815  		}
   816  		contractProof.Key = address
   817  		stateQuery := &types.StateQueryProof{
   818  			ContractProof: contractProof,
   819  			VarProofs:     varProofs,
   820  		}
   821  		context.Respond(message.GetStateQueryRsp{
   822  			Result: stateQuery,
   823  			Err:    err,
   824  		})
   825  	case *message.GetElected:
   826  		top, err := cw.getVotes(msg.Id, msg.N)
   827  		context.Respond(&message.GetVoteRsp{
   828  			Top: top,
   829  			Err: err,
   830  		})
   831  	case *message.GetVote:
   832  		info, err := cw.getAccountVote(msg.Ids, msg.Addr)
   833  		context.Respond(&message.GetAccountVoteRsp{
   834  			Info: info,
   835  			Err:  err,
   836  		})
   837  	case *message.GetStaking:
   838  		staking, err := cw.getStaking(msg.Addr)
   839  		context.Respond(&message.GetStakingRsp{
   840  			Staking: staking,
   841  			Err:     err,
   842  		})
   843  	case *message.GetNameInfo:
   844  		owner, err := cw.getNameInfo(msg.Name, msg.BlockNo)
   845  		context.Respond(&message.GetNameInfoRsp{
   846  			Owner: owner,
   847  			Err:   err,
   848  		})
   849  	case *message.GetEnterpriseConf:
   850  		conf, err := cw.getEnterpriseConf(msg.Key)
   851  		context.Respond(&message.GetEnterpriseConfRsp{
   852  			Conf: conf,
   853  			Err:  err,
   854  		})
   855  	case *message.ListEvents:
   856  		events, err := cw.listEvents(msg.Filter)
   857  		context.Respond(&message.ListEventsRsp{
   858  			Events: events,
   859  			Err:    err,
   860  		})
   861  
   862  	case *actor.Started, *actor.Stopping, *actor.Stopped, *component.CompStatReq: // donothing
   863  	default:
   864  		debug := fmt.Sprintf("[%s] Missed message. (%v) %s", cw.name, reflect.TypeOf(msg), msg)
   865  		logger.Debug().Msg(debug)
   866  	}
   867  }
   868  
   869  func (cs *ChainService) ConsensusType() string {
   870  	return cs.GetGenesisInfo().ConsensusType()
   871  }
   872  
   873  func (cs *ChainService) IsPublic() bool {
   874  	return cs.GetGenesisInfo().PublicNet()
   875  }