github.com/iotexproject/iotex-core@v1.14.1-rc1/chainservice/chainservice.go (about)

     1  // Copyright (c) 2019 IoTeX Foundation
     2  // This source code is provided 'as is' and no warranties are given as to title or non-infringement, merchantability
     3  // or fitness for purpose and, to the extent permitted by law, all liability for your use of the code is disclaimed.
     4  // This source code is governed by Apache License 2.0 that can be found in the LICENSE file.
     5  
     6  package chainservice
     7  
     8  import (
     9  	"context"
    10  
    11  	"github.com/libp2p/go-libp2p-core/peer"
    12  	"github.com/pkg/errors"
    13  	"github.com/prometheus/client_golang/prometheus"
    14  	"google.golang.org/protobuf/proto"
    15  
    16  	"github.com/iotexproject/iotex-election/committee"
    17  	"github.com/iotexproject/iotex-proto/golang/iotexrpc"
    18  	"github.com/iotexproject/iotex-proto/golang/iotextypes"
    19  
    20  	"github.com/iotexproject/iotex-core/action"
    21  	"github.com/iotexproject/iotex-core/action/protocol"
    22  	"github.com/iotexproject/iotex-core/action/protocol/poll"
    23  	"github.com/iotexproject/iotex-core/action/protocol/staking"
    24  	"github.com/iotexproject/iotex-core/actpool"
    25  	"github.com/iotexproject/iotex-core/api"
    26  	"github.com/iotexproject/iotex-core/blockchain"
    27  	"github.com/iotexproject/iotex-core/blockchain/block"
    28  	"github.com/iotexproject/iotex-core/blockchain/blockdao"
    29  	"github.com/iotexproject/iotex-core/blockindex"
    30  	"github.com/iotexproject/iotex-core/blockindex/contractstaking"
    31  	"github.com/iotexproject/iotex-core/blocksync"
    32  	"github.com/iotexproject/iotex-core/consensus"
    33  	"github.com/iotexproject/iotex-core/nodeinfo"
    34  	"github.com/iotexproject/iotex-core/p2p"
    35  	"github.com/iotexproject/iotex-core/pkg/lifecycle"
    36  	"github.com/iotexproject/iotex-core/pkg/log"
    37  	"github.com/iotexproject/iotex-core/pkg/util/blockutil"
    38  	"github.com/iotexproject/iotex-core/server/itx/nodestats"
    39  	"github.com/iotexproject/iotex-core/state/factory"
    40  )
    41  
    42  var (
    43  	_blockchainFullnessMtc = prometheus.NewGaugeVec(
    44  		prometheus.GaugeOpts{
    45  			Name: "iotex_blockchain_fullness",
    46  			Help: "Blockchain fullness statistics",
    47  		},
    48  		[]string{"message_type"},
    49  	)
    50  )
    51  
    52  func init() {
    53  	prometheus.MustRegister(_blockchainFullnessMtc)
    54  }
    55  
    56  // ChainService is a blockchain service with all blockchain components.
    57  type ChainService struct {
    58  	lifecycle         lifecycle.Lifecycle
    59  	actpool           actpool.ActPool
    60  	blocksync         blocksync.BlockSync
    61  	consensus         consensus.Consensus
    62  	chain             blockchain.Blockchain
    63  	factory           factory.Factory
    64  	blockdao          blockdao.BlockDAO
    65  	p2pAgent          p2p.Agent
    66  	electionCommittee committee.Committee
    67  	// TODO: explorer dependency deleted at #1085, need to api related params
    68  	indexer                blockindex.Indexer
    69  	bfIndexer              blockindex.BloomFilterIndexer
    70  	candidateIndexer       *poll.CandidateIndexer
    71  	candBucketsIndexer     *staking.CandidatesBucketsIndexer
    72  	sgdIndexer             blockindex.SGDRegistry
    73  	contractStakingIndexer *contractstaking.Indexer
    74  	registry               *protocol.Registry
    75  	nodeInfoManager        *nodeinfo.InfoManager
    76  	apiStats               *nodestats.APILocalStats
    77  	blockTimeCalculator    *blockutil.BlockTimeCalculator
    78  }
    79  
    80  // Start starts the server
    81  func (cs *ChainService) Start(ctx context.Context) error {
    82  	return cs.lifecycle.OnStartSequentially(ctx)
    83  }
    84  
    85  // Stop stops the server
    86  func (cs *ChainService) Stop(ctx context.Context) error {
    87  	return cs.lifecycle.OnStopSequentially(ctx)
    88  }
    89  
    90  // ReportFullness switch on or off block sync
    91  func (cs *ChainService) ReportFullness(_ context.Context, messageType iotexrpc.MessageType, fullness float32) {
    92  	_blockchainFullnessMtc.WithLabelValues(iotexrpc.MessageType_name[int32(messageType)]).Set(float64(fullness))
    93  }
    94  
    95  // HandleAction handles incoming action request.
    96  func (cs *ChainService) HandleAction(ctx context.Context, actPb *iotextypes.Action) error {
    97  	act, err := (&action.Deserializer{}).SetEvmNetworkID(cs.chain.EvmNetworkID()).ActionToSealedEnvelope(actPb)
    98  	if err != nil {
    99  		return err
   100  	}
   101  	ctx = protocol.WithRegistry(ctx, cs.registry)
   102  	err = cs.actpool.Add(ctx, act)
   103  	if err != nil {
   104  		log.L().Debug(err.Error())
   105  	}
   106  	return err
   107  }
   108  
   109  // HandleBlock handles incoming block request.
   110  func (cs *ChainService) HandleBlock(ctx context.Context, peer string, pbBlock *iotextypes.Block) error {
   111  	blk, err := block.NewDeserializer(cs.chain.EvmNetworkID()).FromBlockProto(pbBlock)
   112  	if err != nil {
   113  		return err
   114  	}
   115  	ctx, err = cs.chain.Context(ctx)
   116  	if err != nil {
   117  		return err
   118  	}
   119  	return cs.blocksync.ProcessBlock(ctx, peer, blk)
   120  }
   121  
   122  // HandleSyncRequest handles incoming sync request.
   123  func (cs *ChainService) HandleSyncRequest(ctx context.Context, peer peer.AddrInfo, sync *iotexrpc.BlockSync) error {
   124  	return cs.blocksync.ProcessSyncRequest(ctx, peer, sync.Start, sync.End)
   125  }
   126  
   127  // HandleConsensusMsg handles incoming consensus message.
   128  func (cs *ChainService) HandleConsensusMsg(msg *iotextypes.ConsensusMessage) error {
   129  	return cs.consensus.HandleConsensusMsg(msg)
   130  }
   131  
   132  // HandleNodeInfo handles nodeinfo message.
   133  func (cs *ChainService) HandleNodeInfo(ctx context.Context, peer string, msg *iotextypes.NodeInfo) error {
   134  	cs.nodeInfoManager.HandleNodeInfo(ctx, peer, msg)
   135  	return nil
   136  }
   137  
   138  // HandleNodeInfoRequest handles request node info message
   139  func (cs *ChainService) HandleNodeInfoRequest(ctx context.Context, peer peer.AddrInfo, msg *iotextypes.NodeInfoRequest) error {
   140  	return cs.nodeInfoManager.HandleNodeInfoRequest(ctx, peer)
   141  }
   142  
   143  // ChainID returns ChainID.
   144  func (cs *ChainService) ChainID() uint32 { return cs.chain.ChainID() }
   145  
   146  // Blockchain returns the Blockchain
   147  func (cs *ChainService) Blockchain() blockchain.Blockchain {
   148  	return cs.chain
   149  }
   150  
   151  // StateFactory returns the state factory
   152  func (cs *ChainService) StateFactory() factory.Factory {
   153  	return cs.factory
   154  }
   155  
   156  // BlockDAO returns the blockdao
   157  func (cs *ChainService) BlockDAO() blockdao.BlockDAO {
   158  	return cs.blockdao
   159  }
   160  
   161  // ActionPool returns the Action pool
   162  func (cs *ChainService) ActionPool() actpool.ActPool {
   163  	return cs.actpool
   164  }
   165  
   166  // Consensus returns the consensus instance
   167  func (cs *ChainService) Consensus() consensus.Consensus {
   168  	return cs.consensus
   169  }
   170  
   171  // BlockSync returns the block syncer
   172  func (cs *ChainService) BlockSync() blocksync.BlockSync {
   173  	return cs.blocksync
   174  }
   175  
   176  // NodeInfoManager returns the delegate manager
   177  func (cs *ChainService) NodeInfoManager() *nodeinfo.InfoManager {
   178  	return cs.nodeInfoManager
   179  }
   180  
   181  // Registry returns a pointer to the registry
   182  func (cs *ChainService) Registry() *protocol.Registry { return cs.registry }
   183  
   184  // NewAPIServer creates a new api server
   185  func (cs *ChainService) NewAPIServer(cfg api.Config, plugins map[int]interface{}) (*api.ServerV2, error) {
   186  	if cfg.GRPCPort == 0 && cfg.HTTPPort == 0 {
   187  		return nil, nil
   188  	}
   189  	p2pAgent := cs.p2pAgent
   190  	apiServerOptions := []api.Option{
   191  		api.WithBroadcastOutbound(func(ctx context.Context, chainID uint32, msg proto.Message) error {
   192  			return p2pAgent.BroadcastOutbound(ctx, msg)
   193  		}),
   194  		api.WithNativeElection(cs.electionCommittee),
   195  		api.WithAPIStats(cs.apiStats),
   196  		api.WithSGDIndexer(cs.sgdIndexer),
   197  	}
   198  
   199  	svr, err := api.NewServerV2(
   200  		cfg,
   201  		cs.chain,
   202  		cs.blocksync,
   203  		cs.factory,
   204  		cs.blockdao,
   205  		cs.indexer,
   206  		cs.bfIndexer,
   207  		cs.actpool,
   208  		cs.registry,
   209  		cs.blockTimeCalculator.CalculateBlockTime,
   210  		apiServerOptions...,
   211  	)
   212  	if err != nil {
   213  		return nil, errors.Wrap(err, "failed to create API server")
   214  	}
   215  
   216  	return svr, nil
   217  }