github.com/gnolang/gno@v0.0.0-20240520182011-228e9d0192ce/tm2/pkg/bft/node/node.go (about)

     1  package node
     2  
     3  // Ignore pprof import for gosec, as profiling
     4  // is enabled by the user by setting a profiling address
     5  
     6  import (
     7  	"fmt"
     8  	"log/slog"
     9  	"net"
    10  	"net/http"
    11  	"strings"
    12  	"sync"
    13  	"time"
    14  
    15  	"github.com/gnolang/gno/tm2/pkg/bft/appconn"
    16  	"github.com/gnolang/gno/tm2/pkg/bft/state/eventstore/file"
    17  	"github.com/rs/cors"
    18  
    19  	"github.com/gnolang/gno/tm2/pkg/amino"
    20  	abci "github.com/gnolang/gno/tm2/pkg/bft/abci/types"
    21  	bc "github.com/gnolang/gno/tm2/pkg/bft/blockchain"
    22  	cfg "github.com/gnolang/gno/tm2/pkg/bft/config"
    23  	cs "github.com/gnolang/gno/tm2/pkg/bft/consensus"
    24  	mempl "github.com/gnolang/gno/tm2/pkg/bft/mempool"
    25  	"github.com/gnolang/gno/tm2/pkg/bft/privval"
    26  	"github.com/gnolang/gno/tm2/pkg/bft/proxy"
    27  	rpccore "github.com/gnolang/gno/tm2/pkg/bft/rpc/core"
    28  	_ "github.com/gnolang/gno/tm2/pkg/bft/rpc/core/types"
    29  	rpcserver "github.com/gnolang/gno/tm2/pkg/bft/rpc/lib/server"
    30  	sm "github.com/gnolang/gno/tm2/pkg/bft/state"
    31  	"github.com/gnolang/gno/tm2/pkg/bft/state/eventstore"
    32  	"github.com/gnolang/gno/tm2/pkg/bft/state/eventstore/null"
    33  	"github.com/gnolang/gno/tm2/pkg/bft/store"
    34  	"github.com/gnolang/gno/tm2/pkg/bft/types"
    35  	tmtime "github.com/gnolang/gno/tm2/pkg/bft/types/time"
    36  	"github.com/gnolang/gno/tm2/pkg/bft/version"
    37  	"github.com/gnolang/gno/tm2/pkg/crypto"
    38  	dbm "github.com/gnolang/gno/tm2/pkg/db"
    39  	"github.com/gnolang/gno/tm2/pkg/errors"
    40  	"github.com/gnolang/gno/tm2/pkg/events"
    41  	"github.com/gnolang/gno/tm2/pkg/p2p"
    42  	"github.com/gnolang/gno/tm2/pkg/service"
    43  	verset "github.com/gnolang/gno/tm2/pkg/versionset"
    44  )
    45  
    46  // ------------------------------------------------------------------------------
    47  
    48  // DBContext specifies config information for loading a new DB.
    49  type DBContext struct {
    50  	ID     string
    51  	Config *cfg.Config
    52  }
    53  
    54  // DBProvider takes a DBContext and returns an instantiated DB.
    55  type DBProvider func(*DBContext) (dbm.DB, error)
    56  
    57  // DefaultDBProvider returns a database using the db.Backend and DBDir
    58  // specified in the ctx.Config.
    59  func DefaultDBProvider(ctx *DBContext) (dbm.DB, error) {
    60  	dbType := dbm.BackendType(ctx.Config.DBBackend)
    61  	return dbm.NewDB(ctx.ID, dbType, ctx.Config.DBDir())
    62  }
    63  
    64  // GenesisDocProvider returns a GenesisDoc.
    65  // It allows the GenesisDoc to be pulled from sources other than the
    66  // filesystem, for instance from a distributed key-value store cluster.
    67  type GenesisDocProvider func() (*types.GenesisDoc, error)
    68  
    69  // DefaultGenesisDocProviderFunc returns a GenesisDocProvider that loads
    70  // the GenesisDoc from the genesis path on the filesystem.
    71  func DefaultGenesisDocProviderFunc(genesisFile string) GenesisDocProvider {
    72  	return func() (*types.GenesisDoc, error) {
    73  		return types.GenesisDocFromFile(genesisFile)
    74  	}
    75  }
    76  
    77  // NodeProvider takes a config and a logger and returns a ready to go Node.
    78  type NodeProvider func(*cfg.Config, *slog.Logger) (*Node, error)
    79  
    80  // DefaultNewNode returns a Tendermint node with default settings for the
    81  // PrivValidator, ClientCreator, GenesisDoc, and DBProvider.
    82  // It implements NodeProvider.
    83  func DefaultNewNode(config *cfg.Config, genesisFile string, logger *slog.Logger) (*Node, error) {
    84  	// Generate node PrivKey
    85  	nodeKey, err := p2p.LoadOrGenNodeKey(config.NodeKeyFile())
    86  	if err != nil {
    87  		return nil, err
    88  	}
    89  
    90  	// Get privValKeys.
    91  	newPrivValKey := config.PrivValidatorKeyFile()
    92  	newPrivValState := config.PrivValidatorStateFile()
    93  
    94  	// Get app client creator.
    95  	appClientCreator := proxy.DefaultClientCreator(
    96  		config.LocalApp,
    97  		config.ProxyApp,
    98  		config.ABCI,
    99  		config.DBDir(),
   100  	)
   101  
   102  	return NewNode(config,
   103  		privval.LoadOrGenFilePV(newPrivValKey, newPrivValState),
   104  		nodeKey,
   105  		appClientCreator,
   106  		DefaultGenesisDocProviderFunc(genesisFile),
   107  		DefaultDBProvider,
   108  		logger,
   109  	)
   110  }
   111  
   112  // Option sets a parameter for the node.
   113  type Option func(*Node)
   114  
   115  // CustomReactors allows you to add custom reactors (name -> p2p.Reactor) to
   116  // the node's Switch.
   117  //
   118  // WARNING: using any name from the below list of the existing reactors will
   119  // result in replacing it with the custom one.
   120  //
   121  //   - MEMPOOL
   122  //   - BLOCKCHAIN
   123  //   - CONSENSUS
   124  //   - EVIDENCE
   125  //   - PEX
   126  func CustomReactors(reactors map[string]p2p.Reactor) Option {
   127  	return func(n *Node) {
   128  		for name, reactor := range reactors {
   129  			if existingReactor := n.sw.Reactor(name); existingReactor != nil {
   130  				n.sw.Logger.Info("Replacing existing reactor with a custom one",
   131  					"name", name, "existing", existingReactor, "custom", reactor)
   132  				n.sw.RemoveReactor(name, existingReactor)
   133  			}
   134  			n.sw.AddReactor(name, reactor)
   135  		}
   136  	}
   137  }
   138  
   139  // ------------------------------------------------------------------------------
   140  
   141  // Node is the highest level interface to a full Tendermint node.
   142  // It includes all configuration information and running services.
   143  type Node struct {
   144  	service.BaseService
   145  
   146  	// config
   147  	config        *cfg.Config
   148  	genesisDoc    *types.GenesisDoc   // initial validator set
   149  	privValidator types.PrivValidator // local node's validator key
   150  
   151  	// network
   152  	transport   *p2p.MultiplexTransport
   153  	sw          *p2p.Switch // p2p connections
   154  	nodeInfo    p2p.NodeInfo
   155  	nodeKey     *p2p.NodeKey // our node privkey
   156  	isListening bool
   157  
   158  	// services
   159  	evsw              events.EventSwitch
   160  	stateDB           dbm.DB
   161  	blockStore        *store.BlockStore // store the blockchain to disk
   162  	bcReactor         p2p.Reactor       // for fast-syncing
   163  	mempoolReactor    *mempl.Reactor    // for gossipping transactions
   164  	mempool           mempl.Mempool
   165  	consensusState    *cs.ConsensusState   // latest consensus state
   166  	consensusReactor  *cs.ConsensusReactor // for participating in the consensus
   167  	proxyApp          appconn.AppConns     // connection to the application
   168  	rpcListeners      []net.Listener       // rpc servers
   169  	txEventStore      eventstore.TxEventStore
   170  	eventStoreService *eventstore.Service
   171  	firstBlockSignal  <-chan struct{}
   172  }
   173  
   174  func initDBs(config *cfg.Config, dbProvider DBProvider) (blockStore *store.BlockStore, stateDB dbm.DB, err error) {
   175  	var blockStoreDB dbm.DB
   176  	blockStoreDB, err = dbProvider(&DBContext{"blockstore", config})
   177  	if err != nil {
   178  		return
   179  	}
   180  	blockStore = store.NewBlockStore(blockStoreDB)
   181  
   182  	stateDB, err = dbProvider(&DBContext{"state", config})
   183  	if err != nil {
   184  		return
   185  	}
   186  
   187  	return
   188  }
   189  
   190  func createAndStartProxyAppConns(clientCreator proxy.ClientCreator, logger *slog.Logger) (appconn.AppConns, error) {
   191  	proxyApp := appconn.NewAppConns(clientCreator)
   192  	proxyApp.SetLogger(logger.With("module", "proxy"))
   193  	if err := proxyApp.Start(); err != nil {
   194  		return nil, fmt.Errorf("error starting proxy app connections: %w", err)
   195  	}
   196  	return proxyApp, nil
   197  }
   198  
   199  func createAndStartEventStoreService(
   200  	cfg *cfg.Config,
   201  	evsw events.EventSwitch,
   202  	logger *slog.Logger,
   203  ) (*eventstore.Service, eventstore.TxEventStore, error) {
   204  	var (
   205  		err          error
   206  		txEventStore eventstore.TxEventStore
   207  	)
   208  
   209  	// Instantiate the event store based on the configuration
   210  	switch cfg.TxEventStore.EventStoreType {
   211  	case file.EventStoreType:
   212  		// Transaction events should be logged to files
   213  		txEventStore, err = file.NewTxEventStore(cfg.TxEventStore)
   214  		if err != nil {
   215  			return nil, nil, fmt.Errorf("unable to create file tx event store, %w", err)
   216  		}
   217  	default:
   218  		// Transaction event storing should be omitted
   219  		txEventStore = null.NewNullEventStore()
   220  	}
   221  
   222  	indexerService := eventstore.NewEventStoreService(txEventStore, evsw)
   223  	indexerService.SetLogger(logger.With("module", "eventstore"))
   224  	if err := indexerService.Start(); err != nil {
   225  		return nil, nil, err
   226  	}
   227  
   228  	return indexerService, txEventStore, nil
   229  }
   230  
   231  func doHandshake(stateDB dbm.DB, state sm.State, blockStore sm.BlockStore,
   232  	genDoc *types.GenesisDoc, evsw events.EventSwitch, proxyApp appconn.AppConns, consensusLogger *slog.Logger,
   233  ) error {
   234  	handshaker := cs.NewHandshaker(stateDB, state, blockStore, genDoc)
   235  	handshaker.SetLogger(consensusLogger)
   236  	handshaker.SetEventSwitch(evsw)
   237  	if err := handshaker.Handshake(proxyApp); err != nil {
   238  		return fmt.Errorf("error during handshake: %w", err)
   239  	}
   240  	return nil
   241  }
   242  
   243  func logNodeStartupInfo(state sm.State, pubKey crypto.PubKey, logger, consensusLogger *slog.Logger) {
   244  	// Log the version info.
   245  	logger.Info("Version info",
   246  		"version", version.Version,
   247  	)
   248  
   249  	addr := pubKey.Address()
   250  	// Log whether this node is a validator or an observer
   251  	if state.Validators.HasAddress(addr) {
   252  		consensusLogger.Info("This node is a validator", "addr", addr, "pubKey", pubKey)
   253  	} else {
   254  		consensusLogger.Info("This node is not a validator", "addr", addr, "pubKey", pubKey)
   255  	}
   256  }
   257  
   258  func onlyValidatorIsUs(state sm.State, privVal types.PrivValidator) bool {
   259  	if state.Validators.Size() > 1 {
   260  		return false
   261  	}
   262  	addr, _ := state.Validators.GetByIndex(0)
   263  	return privVal.GetPubKey().Address() == addr
   264  }
   265  
   266  func createMempoolAndMempoolReactor(config *cfg.Config, proxyApp appconn.AppConns,
   267  	state sm.State, logger *slog.Logger,
   268  ) (*mempl.Reactor, *mempl.CListMempool) {
   269  	mempool := mempl.NewCListMempool(
   270  		config.Mempool,
   271  		proxyApp.Mempool(),
   272  		state.LastBlockHeight,
   273  		state.ConsensusParams.Block.MaxTxBytes,
   274  		mempl.WithPreCheck(sm.TxPreCheck(state)),
   275  	)
   276  	mempoolLogger := logger.With("module", "mempool")
   277  	mempoolReactor := mempl.NewReactor(config.Mempool, mempool)
   278  	mempoolReactor.SetLogger(mempoolLogger)
   279  
   280  	if config.Consensus.WaitForTxs() {
   281  		mempool.EnableTxsAvailable()
   282  	}
   283  	return mempoolReactor, mempool
   284  }
   285  
   286  func createBlockchainReactor(config *cfg.Config,
   287  	state sm.State,
   288  	blockExec *sm.BlockExecutor,
   289  	blockStore *store.BlockStore,
   290  	fastSync bool,
   291  	logger *slog.Logger,
   292  ) (bcReactor p2p.Reactor, err error) {
   293  	bcReactor = bc.NewBlockchainReactor(state.Copy(), blockExec, blockStore, fastSync)
   294  
   295  	bcReactor.SetLogger(logger.With("module", "blockchain"))
   296  	return bcReactor, nil
   297  }
   298  
   299  func createConsensusReactor(config *cfg.Config,
   300  	state sm.State,
   301  	blockExec *sm.BlockExecutor,
   302  	blockStore sm.BlockStore,
   303  	mempool *mempl.CListMempool,
   304  	privValidator types.PrivValidator,
   305  	fastSync bool,
   306  	evsw events.EventSwitch,
   307  	consensusLogger *slog.Logger,
   308  ) (*cs.ConsensusReactor, *cs.ConsensusState) {
   309  	consensusState := cs.NewConsensusState(
   310  		config.Consensus,
   311  		state.Copy(),
   312  		blockExec,
   313  		blockStore,
   314  		mempool,
   315  	)
   316  	consensusState.SetLogger(consensusLogger)
   317  	if privValidator != nil {
   318  		consensusState.SetPrivValidator(privValidator)
   319  	}
   320  	consensusReactor := cs.NewConsensusReactor(consensusState, fastSync)
   321  	consensusReactor.SetLogger(consensusLogger)
   322  	consensusReactor.SetEventSwitch(evsw)
   323  	// services which will be publishing and/or subscribing for messages (events)
   324  	// consensusReactor will set it on consensusState and blockExecutor
   325  	return consensusReactor, consensusState
   326  }
   327  
   328  func createTransport(config *cfg.Config, nodeInfo p2p.NodeInfo, nodeKey *p2p.NodeKey, proxyApp appconn.AppConns) (*p2p.MultiplexTransport, []p2p.PeerFilterFunc) {
   329  	var (
   330  		mConnConfig = p2p.MConnConfig(config.P2P)
   331  		transport   = p2p.NewMultiplexTransport(nodeInfo, *nodeKey, mConnConfig)
   332  		connFilters = []p2p.ConnFilterFunc{}
   333  		peerFilters = []p2p.PeerFilterFunc{}
   334  	)
   335  
   336  	if !config.P2P.AllowDuplicateIP {
   337  		connFilters = append(connFilters, p2p.ConnDuplicateIPFilter())
   338  	}
   339  
   340  	// Filter peers by addr or pubkey with an ABCI query.
   341  	// If the query return code is OK, add peer.
   342  	if config.FilterPeers {
   343  		connFilters = append(
   344  			connFilters,
   345  			// ABCI query for address filtering.
   346  			func(_ p2p.ConnSet, c net.Conn, _ []net.IP) error {
   347  				res, err := proxyApp.Query().QuerySync(abci.RequestQuery{
   348  					Path: fmt.Sprintf("/p2p/filter/addr/%s", c.RemoteAddr().String()),
   349  				})
   350  				if err != nil {
   351  					return err
   352  				}
   353  				if res.IsErr() {
   354  					return fmt.Errorf("error querying abci app: %v", res)
   355  				}
   356  
   357  				return nil
   358  			},
   359  		)
   360  
   361  		peerFilters = append(
   362  			peerFilters,
   363  			// ABCI query for ID filtering.
   364  			func(_ p2p.IPeerSet, p p2p.Peer) error {
   365  				res, err := proxyApp.Query().QuerySync(abci.RequestQuery{
   366  					Path: fmt.Sprintf("/p2p/filter/id/%s", p.ID()),
   367  				})
   368  				if err != nil {
   369  					return err
   370  				}
   371  				if res.IsErr() {
   372  					return fmt.Errorf("error querying abci app: %v", res)
   373  				}
   374  
   375  				return nil
   376  			},
   377  		)
   378  	}
   379  
   380  	p2p.MultiplexTransportConnFilters(connFilters...)(transport)
   381  	return transport, peerFilters
   382  }
   383  
   384  func createSwitch(config *cfg.Config,
   385  	transport *p2p.MultiplexTransport,
   386  	peerFilters []p2p.PeerFilterFunc,
   387  	mempoolReactor *mempl.Reactor,
   388  	bcReactor p2p.Reactor,
   389  	consensusReactor *cs.ConsensusReactor,
   390  	nodeInfo p2p.NodeInfo,
   391  	nodeKey *p2p.NodeKey,
   392  	p2pLogger *slog.Logger,
   393  ) *p2p.Switch {
   394  	sw := p2p.NewSwitch(
   395  		config.P2P,
   396  		transport,
   397  		p2p.SwitchPeerFilters(peerFilters...),
   398  	)
   399  	sw.SetLogger(p2pLogger)
   400  	sw.AddReactor("MEMPOOL", mempoolReactor)
   401  	sw.AddReactor("BLOCKCHAIN", bcReactor)
   402  	sw.AddReactor("CONSENSUS", consensusReactor)
   403  
   404  	sw.SetNodeInfo(nodeInfo)
   405  	sw.SetNodeKey(nodeKey)
   406  
   407  	p2pLogger.Info("P2P Node ID", "ID", nodeKey.ID(), "file", config.NodeKeyFile())
   408  	return sw
   409  }
   410  
   411  // NewNode returns a new, ready to go, Tendermint Node.
   412  func NewNode(config *cfg.Config,
   413  	privValidator types.PrivValidator,
   414  	nodeKey *p2p.NodeKey,
   415  	clientCreator appconn.ClientCreator,
   416  	genesisDocProvider GenesisDocProvider,
   417  	dbProvider DBProvider,
   418  	logger *slog.Logger,
   419  	options ...Option,
   420  ) (*Node, error) {
   421  	blockStore, stateDB, err := initDBs(config, dbProvider)
   422  	if err != nil {
   423  		return nil, err
   424  	}
   425  
   426  	state, genDoc, err := LoadStateFromDBOrGenesisDocProvider(stateDB, genesisDocProvider)
   427  	if err != nil {
   428  		return nil, err
   429  	}
   430  
   431  	// Create the proxyApp and establish connections to the ABCI app (consensus, mempool, query).
   432  	proxyApp, err := createAndStartProxyAppConns(clientCreator, logger)
   433  	if err != nil {
   434  		return nil, err
   435  	}
   436  
   437  	// EventSwitch and EventStoreService must be started before the handshake because
   438  	// we might need to store the txs of the replayed block as this might not have happened
   439  	// when the node stopped last time (i.e. the node stopped after it saved the block
   440  	// but before it indexed the txs, or, endblocker panicked)
   441  	evsw := events.NewEventSwitch()
   442  
   443  	// Signal readiness when receiving the first block.
   444  	const readinessListenerID = "first_block_listener"
   445  
   446  	cFirstBlock := make(chan struct{})
   447  	var once sync.Once
   448  	evsw.AddListener(readinessListenerID, func(ev events.Event) {
   449  		if _, ok := ev.(types.EventNewBlock); ok {
   450  			once.Do(func() {
   451  				close(cFirstBlock)
   452  				evsw.RemoveListener(readinessListenerID)
   453  			})
   454  		}
   455  	})
   456  
   457  	// Transaction event storing
   458  	eventStoreService, txEventStore, err := createAndStartEventStoreService(config, evsw, logger)
   459  	if err != nil {
   460  		return nil, err
   461  	}
   462  
   463  	// Create the handshaker, which calls RequestInfo, sets the AppVersion on the state,
   464  	// and replays any blocks as necessary to sync tendermint with the app.
   465  	consensusLogger := logger.With("module", "consensus")
   466  	if err := doHandshake(stateDB, state, blockStore, genDoc, evsw, proxyApp, consensusLogger); err != nil {
   467  		return nil, err
   468  	}
   469  
   470  	// Reload the state. It will have the Version.Consensus.App set by the
   471  	// Handshake, and may have other modifications as well (ie. depending on
   472  	// what happened during block replay).
   473  	state = sm.LoadState(stateDB)
   474  
   475  	// If an address is provided, listen on the socket for a connection from an
   476  	// external signing process.
   477  	if config.PrivValidatorListenAddr != "" {
   478  		// FIXME: we should start services inside OnStart
   479  		privValidator, err = createAndStartPrivValidatorSocketClient(config.PrivValidatorListenAddr, logger)
   480  		if err != nil {
   481  			return nil, errors.Wrap(err, "error with private validator socket client")
   482  		}
   483  	}
   484  
   485  	pubKey := privValidator.GetPubKey()
   486  	if pubKey == nil {
   487  		// TODO: GetPubKey should return errors - https://github.com/gnolang/gno/tm2/pkg/bft/issues/3602
   488  		return nil, errors.New("could not retrieve public key from private validator")
   489  	}
   490  
   491  	logNodeStartupInfo(state, pubKey, logger, consensusLogger)
   492  
   493  	// Decide whether to fast-sync or not
   494  	// We don't fast-sync when the only validator is us.
   495  	fastSync := config.FastSyncMode && !onlyValidatorIsUs(state, privValidator)
   496  
   497  	// Make MempoolReactor
   498  	mempoolReactor, mempool := createMempoolAndMempoolReactor(config, proxyApp, state, logger)
   499  
   500  	// make block executor for consensus and blockchain reactors to execute blocks
   501  	blockExec := sm.NewBlockExecutor(
   502  		stateDB,
   503  		logger.With("module", "state"),
   504  		proxyApp.Consensus(),
   505  		mempool,
   506  	)
   507  
   508  	// Make BlockchainReactor
   509  	bcReactor, err := createBlockchainReactor(config, state, blockExec, blockStore, fastSync, logger)
   510  	if err != nil {
   511  		return nil, errors.Wrap(err, "could not create blockchain reactor")
   512  	}
   513  
   514  	// Make ConsensusReactor
   515  	consensusReactor, consensusState := createConsensusReactor(
   516  		config, state, blockExec, blockStore, mempool,
   517  		privValidator, fastSync, evsw, consensusLogger,
   518  	)
   519  
   520  	nodeInfo, err := makeNodeInfo(config, nodeKey, txEventStore, genDoc, state)
   521  	if err != nil {
   522  		return nil, errors.Wrap(err, "error making NodeInfo")
   523  	}
   524  
   525  	// Setup Transport.
   526  	transport, peerFilters := createTransport(config, nodeInfo, nodeKey, proxyApp)
   527  
   528  	// Setup Switch.
   529  	p2pLogger := logger.With("module", "p2p")
   530  	sw := createSwitch(
   531  		config, transport, peerFilters, mempoolReactor, bcReactor,
   532  		consensusReactor, nodeInfo, nodeKey, p2pLogger,
   533  	)
   534  
   535  	err = sw.AddPersistentPeers(splitAndTrimEmpty(config.P2P.PersistentPeers, ",", " "))
   536  	if err != nil {
   537  		return nil, errors.Wrap(err, "could not add peers from persistent_peers field")
   538  	}
   539  
   540  	if config.ProfListenAddress != "" {
   541  		server := &http.Server{
   542  			Addr:              config.ProfListenAddress,
   543  			ReadHeaderTimeout: 60 * time.Second,
   544  		}
   545  
   546  		go func() {
   547  			logger.Error("Profile server", "err", server.ListenAndServe())
   548  		}()
   549  	}
   550  
   551  	node := &Node{
   552  		config:        config,
   553  		genesisDoc:    genDoc,
   554  		privValidator: privValidator,
   555  
   556  		transport: transport,
   557  		sw:        sw,
   558  		nodeInfo:  nodeInfo,
   559  		nodeKey:   nodeKey,
   560  
   561  		evsw:              evsw,
   562  		stateDB:           stateDB,
   563  		blockStore:        blockStore,
   564  		bcReactor:         bcReactor,
   565  		mempoolReactor:    mempoolReactor,
   566  		mempool:           mempool,
   567  		consensusState:    consensusState,
   568  		consensusReactor:  consensusReactor,
   569  		proxyApp:          proxyApp,
   570  		txEventStore:      txEventStore,
   571  		eventStoreService: eventStoreService,
   572  		firstBlockSignal:  cFirstBlock,
   573  	}
   574  	node.BaseService = *service.NewBaseService(logger, "Node", node)
   575  
   576  	for _, option := range options {
   577  		option(node)
   578  	}
   579  
   580  	return node, nil
   581  }
   582  
   583  // OnStart starts the Node. It implements service.Service.
   584  func (n *Node) OnStart() error {
   585  	now := tmtime.Now()
   586  	genTime := n.genesisDoc.GenesisTime
   587  	if genTime.After(now) {
   588  		n.Logger.Info("Genesis time is in the future. Sleeping until then...", "genTime", genTime)
   589  		time.Sleep(genTime.Sub(now))
   590  	}
   591  
   592  	// Set up the GLOBAL variables in rpc/core which refer to this node.
   593  	// This is done separately from startRPC(), as the values in rpc/core are used,
   594  	// for instance, to set up Local clients (rpc/client) which work without
   595  	// a network connection.
   596  	n.configureRPC()
   597  	if n.config.RPC.Unsafe {
   598  		rpccore.AddUnsafeRoutes()
   599  	}
   600  	rpccore.Start()
   601  
   602  	// Start the RPC server before the P2P server
   603  	// so we can eg. receive txs for the first block
   604  	if n.config.RPC.ListenAddress != "" {
   605  		listeners, err := n.startRPC()
   606  		if err != nil {
   607  			return err
   608  		}
   609  		n.rpcListeners = listeners
   610  	}
   611  
   612  	// Start the transport.
   613  	addr, err := p2p.NewNetAddressFromString(p2p.NetAddressString(n.nodeKey.ID(), n.config.P2P.ListenAddress))
   614  	if err != nil {
   615  		return err
   616  	}
   617  	if err := n.transport.Listen(*addr); err != nil {
   618  		return err
   619  	}
   620  	if addr.Port == 0 {
   621  		// if the port we have from config.P2p.ListenAdress is 0,
   622  		// it means the port was selected when doing net.Listen (using autoselect on the kernel).
   623  		// fix the config variable using the correct address
   624  		na := n.transport.NetAddress()
   625  		n.config.P2P.ListenAddress = na.DialString()
   626  	}
   627  
   628  	n.isListening = true
   629  
   630  	if n.config.Mempool.WalEnabled() {
   631  		n.mempool.InitWAL() // no need to have the mempool wal during tests
   632  	}
   633  
   634  	// Start the switch (the P2P server).
   635  	err = n.sw.Start()
   636  	if err != nil {
   637  		return err
   638  	}
   639  
   640  	// Always connect to persistent peers
   641  	err = n.sw.DialPeersAsync(splitAndTrimEmpty(n.config.P2P.PersistentPeers, ",", " "))
   642  	if err != nil {
   643  		return errors.Wrap(err, "could not dial peers from persistent_peers field")
   644  	}
   645  
   646  	return nil
   647  }
   648  
   649  // OnStop stops the Node. It implements service.Service.
   650  func (n *Node) OnStop() {
   651  	n.BaseService.OnStop()
   652  
   653  	n.Logger.Info("Stopping Node")
   654  
   655  	// first stop the non-reactor services
   656  	n.evsw.Stop()
   657  	n.eventStoreService.Stop()
   658  
   659  	// now stop the reactors
   660  	n.sw.Stop()
   661  
   662  	// stop mempool WAL
   663  	if n.config.Mempool.WalEnabled() {
   664  		n.mempool.CloseWAL()
   665  	}
   666  
   667  	n.isListening = false
   668  
   669  	// finally stop the listeners / external services
   670  	for _, l := range n.rpcListeners {
   671  		n.Logger.Info("Closing rpc listener", "listener", l)
   672  		if err := l.Close(); err != nil {
   673  			n.Logger.Error("Error closing listener", "listener", l, "err", err)
   674  		}
   675  	}
   676  
   677  	if pvsc, ok := n.privValidator.(service.Service); ok {
   678  		pvsc.Stop()
   679  	}
   680  }
   681  
   682  // Ready signals that the node is ready by returning a blocking channel. This channel is closed when the node receives its first block.
   683  func (n *Node) Ready() <-chan struct{} {
   684  	return n.firstBlockSignal
   685  }
   686  
   687  // configureRPC sets all variables in rpccore so they will serve
   688  // rpc calls from this node
   689  func (n *Node) configureRPC() {
   690  	rpccore.SetStateDB(n.stateDB)
   691  	rpccore.SetBlockStore(n.blockStore)
   692  	rpccore.SetConsensusState(n.consensusState)
   693  	rpccore.SetMempool(n.mempool)
   694  	rpccore.SetP2PPeers(n.sw)
   695  	rpccore.SetP2PTransport(n)
   696  	pubKey := n.privValidator.GetPubKey()
   697  	rpccore.SetPubKey(pubKey)
   698  	rpccore.SetGenesisDoc(n.genesisDoc)
   699  	rpccore.SetProxyAppQuery(n.proxyApp.Query())
   700  	rpccore.SetGetFastSync(n.consensusReactor.FastSync)
   701  	rpccore.SetLogger(n.Logger.With("module", "rpc"))
   702  	rpccore.SetEventSwitch(n.evsw)
   703  	rpccore.SetConfig(*n.config.RPC)
   704  }
   705  
   706  func (n *Node) startRPC() ([]net.Listener, error) {
   707  	listenAddrs := splitAndTrimEmpty(n.config.RPC.ListenAddress, ",", " ")
   708  
   709  	config := rpcserver.DefaultConfig()
   710  	config.MaxBodyBytes = n.config.RPC.MaxBodyBytes
   711  	config.MaxHeaderBytes = n.config.RPC.MaxHeaderBytes
   712  	config.MaxOpenConnections = n.config.RPC.MaxOpenConnections
   713  	// If necessary adjust global WriteTimeout to ensure it's greater than
   714  	// TimeoutBroadcastTxCommit.
   715  	// See https://github.com/gnolang/gno/tm2/pkg/bft/issues/3435
   716  	if config.WriteTimeout <= n.config.RPC.TimeoutBroadcastTxCommit {
   717  		config.WriteTimeout = n.config.RPC.TimeoutBroadcastTxCommit + 1*time.Second
   718  	}
   719  
   720  	// we may expose the rpc over both a unix and tcp socket
   721  	var rebuildAddresses bool
   722  	listeners := make([]net.Listener, len(listenAddrs))
   723  	for i, listenAddr := range listenAddrs {
   724  		mux := http.NewServeMux()
   725  		rpcLogger := n.Logger.With("module", "rpc-server")
   726  		wmLogger := rpcLogger.With("protocol", "websocket")
   727  		wm := rpcserver.NewWebsocketManager(rpccore.Routes,
   728  			rpcserver.OnDisconnect(func(remoteAddr string) {
   729  				// any cleanup...
   730  				// (we used to unsubscribe from all event subscriptions)
   731  			}),
   732  			rpcserver.ReadLimit(config.MaxBodyBytes),
   733  		)
   734  		wm.SetLogger(wmLogger)
   735  		mux.HandleFunc("/websocket", wm.WebsocketHandler)
   736  		rpcserver.RegisterRPCFuncs(mux, rpccore.Routes, rpcLogger)
   737  		if strings.HasPrefix(listenAddr, "tcp://") && strings.HasSuffix(listenAddr, ":0") {
   738  			rebuildAddresses = true
   739  		}
   740  		listener, err := rpcserver.Listen(
   741  			listenAddr,
   742  			config,
   743  		)
   744  		if err != nil {
   745  			return nil, err
   746  		}
   747  
   748  		var rootHandler http.Handler = mux
   749  		if n.config.RPC.IsCorsEnabled() {
   750  			corsMiddleware := cors.New(cors.Options{
   751  				AllowedOrigins: n.config.RPC.CORSAllowedOrigins,
   752  				AllowedMethods: n.config.RPC.CORSAllowedMethods,
   753  				AllowedHeaders: n.config.RPC.CORSAllowedHeaders,
   754  			})
   755  			rootHandler = corsMiddleware.Handler(mux)
   756  		}
   757  		if n.config.RPC.IsTLSEnabled() {
   758  			go rpcserver.StartHTTPAndTLSServer(
   759  				listener,
   760  				rootHandler,
   761  				n.config.RPC.CertFile(),
   762  				n.config.RPC.KeyFile(),
   763  				rpcLogger,
   764  				config,
   765  			)
   766  		} else {
   767  			go rpcserver.StartHTTPServer(
   768  				listener,
   769  				rootHandler,
   770  				rpcLogger,
   771  				config,
   772  			)
   773  		}
   774  
   775  		listeners[i] = listener
   776  	}
   777  	if rebuildAddresses {
   778  		n.config.RPC.ListenAddress = joinListenerAddresses(listeners)
   779  	}
   780  
   781  	return listeners, nil
   782  }
   783  
   784  func joinListenerAddresses(ll []net.Listener) string {
   785  	sl := make([]string, len(ll))
   786  	for i, l := range ll {
   787  		sl[i] = l.Addr().Network() + "://" + l.Addr().String()
   788  	}
   789  	return strings.Join(sl, ",")
   790  }
   791  
   792  // Switch returns the Node's Switch.
   793  func (n *Node) Switch() *p2p.Switch {
   794  	return n.sw
   795  }
   796  
   797  // EventSwitch returns the node's EventSwitch.
   798  func (n *Node) EventSwitch() events.EventSwitch {
   799  	return n.evsw
   800  }
   801  
   802  // BlockStore returns the Node's BlockStore.
   803  func (n *Node) BlockStore() *store.BlockStore {
   804  	return n.blockStore
   805  }
   806  
   807  // ConsensusState returns the Node's ConsensusState.
   808  func (n *Node) ConsensusState() *cs.ConsensusState {
   809  	return n.consensusState
   810  }
   811  
   812  // ConsensusReactor returns the Node's ConsensusReactor.
   813  func (n *Node) ConsensusReactor() *cs.ConsensusReactor {
   814  	return n.consensusReactor
   815  }
   816  
   817  // MempoolReactor returns the Node's mempool reactor.
   818  func (n *Node) MempoolReactor() *mempl.Reactor {
   819  	return n.mempoolReactor
   820  }
   821  
   822  // Mempool returns the Node's mempool.
   823  func (n *Node) Mempool() mempl.Mempool {
   824  	return n.mempool
   825  }
   826  
   827  // PrivValidator returns the Node's PrivValidator.
   828  // XXX: for convenience only!
   829  func (n *Node) PrivValidator() types.PrivValidator {
   830  	return n.privValidator
   831  }
   832  
   833  // GenesisDoc returns the Node's GenesisDoc.
   834  func (n *Node) GenesisDoc() *types.GenesisDoc {
   835  	return n.genesisDoc
   836  }
   837  
   838  // ProxyApp returns the Node's AppConns, representing its connections to the ABCI application.
   839  func (n *Node) ProxyApp() appconn.AppConns {
   840  	return n.proxyApp
   841  }
   842  
   843  // Config returns the Node's config.
   844  func (n *Node) Config() *cfg.Config {
   845  	return n.config
   846  }
   847  
   848  // ------------------------------------------------------------------------------
   849  
   850  func (n *Node) Listeners() []string {
   851  	return []string{
   852  		fmt.Sprintf("Listener(@%v)", n.config.P2P.ExternalAddress),
   853  	}
   854  }
   855  
   856  func (n *Node) IsListening() bool {
   857  	return n.isListening
   858  }
   859  
   860  // NodeInfo returns the Node's Info from the Switch.
   861  func (n *Node) NodeInfo() p2p.NodeInfo {
   862  	return n.nodeInfo
   863  }
   864  
   865  func makeNodeInfo(
   866  	config *cfg.Config,
   867  	nodeKey *p2p.NodeKey,
   868  	txEventStore eventstore.TxEventStore,
   869  	genDoc *types.GenesisDoc,
   870  	state sm.State,
   871  ) (p2p.NodeInfo, error) {
   872  	txIndexerStatus := eventstore.StatusOff
   873  	if txEventStore.GetType() != null.EventStoreType {
   874  		txIndexerStatus = eventstore.StatusOn
   875  	}
   876  
   877  	bcChannel := bc.BlockchainChannel
   878  	vset := version.VersionSet
   879  	vset.Set(verset.VersionInfo{
   880  		Name:    "app",
   881  		Version: state.AppVersion,
   882  	})
   883  
   884  	nodeInfo := p2p.NodeInfo{
   885  		VersionSet: vset,
   886  		Network:    genDoc.ChainID,
   887  		Version:    version.Version,
   888  		Channels: []byte{
   889  			bcChannel,
   890  			cs.StateChannel, cs.DataChannel, cs.VoteChannel, cs.VoteSetBitsChannel,
   891  			mempl.MempoolChannel,
   892  		},
   893  		Moniker: config.Moniker,
   894  		Other: p2p.NodeInfoOther{
   895  			TxIndex:    txIndexerStatus,
   896  			RPCAddress: config.RPC.ListenAddress,
   897  		},
   898  	}
   899  
   900  	lAddr := config.P2P.ExternalAddress
   901  	if lAddr == "" {
   902  		lAddr = config.P2P.ListenAddress
   903  	}
   904  	addr, err := p2p.NewNetAddressFromString(p2p.NetAddressString(nodeKey.ID(), lAddr))
   905  	if err != nil {
   906  		return nodeInfo, errors.Wrap(err, "invalid (local) node net address")
   907  	}
   908  	nodeInfo.NetAddress = addr
   909  
   910  	err = nodeInfo.Validate()
   911  	return nodeInfo, err
   912  }
   913  
   914  // ------------------------------------------------------------------------------
   915  
   916  var genesisDocKey = []byte("genesisDoc")
   917  
   918  // LoadStateFromDBOrGenesisDocProvider attempts to load the state from the
   919  // database, or creates one using the given genesisDocProvider and persists the
   920  // result to the database. On success this also returns the genesis doc loaded
   921  // through the given provider.
   922  func LoadStateFromDBOrGenesisDocProvider(stateDB dbm.DB, genesisDocProvider GenesisDocProvider) (sm.State, *types.GenesisDoc, error) {
   923  	// Get genesis doc
   924  	genDoc, err := loadGenesisDoc(stateDB)
   925  	if err != nil {
   926  		genDoc, err = genesisDocProvider()
   927  		if err != nil {
   928  			return sm.State{}, nil, err
   929  		}
   930  		// save genesis doc to prevent a certain class of user errors (e.g. when it
   931  		// was changed, accidentally or not). Also good for audit trail.
   932  		saveGenesisDoc(stateDB, genDoc)
   933  	}
   934  	state, err := sm.LoadStateFromDBOrGenesisDoc(stateDB, genDoc)
   935  	if err != nil {
   936  		return sm.State{}, nil, err
   937  	}
   938  	return state, genDoc, nil
   939  }
   940  
   941  // panics if failed to unmarshal bytes
   942  func loadGenesisDoc(db dbm.DB) (*types.GenesisDoc, error) {
   943  	b := db.Get(genesisDocKey)
   944  	if len(b) == 0 {
   945  		return nil, errors.New("Genesis doc not found")
   946  	}
   947  	var genDoc *types.GenesisDoc
   948  	err := amino.UnmarshalJSON(b, &genDoc)
   949  	if err != nil {
   950  		panic(fmt.Sprintf("Failed to load genesis doc due to unmarshaling error: %v (bytes: %X)", err, b))
   951  	}
   952  	return genDoc, nil
   953  }
   954  
   955  // panics if failed to marshal the given genesis document
   956  func saveGenesisDoc(db dbm.DB, genDoc *types.GenesisDoc) {
   957  	b, err := amino.MarshalJSON(genDoc)
   958  	if err != nil {
   959  		panic(fmt.Sprintf("Failed to save genesis doc due to marshaling error: %v", err))
   960  	}
   961  	db.SetSync(genesisDocKey, b)
   962  }
   963  
   964  func createAndStartPrivValidatorSocketClient(
   965  	listenAddr string,
   966  	logger *slog.Logger,
   967  ) (types.PrivValidator, error) {
   968  	pve, err := privval.NewSignerListener(listenAddr, logger)
   969  	if err != nil {
   970  		return nil, errors.Wrap(err, "failed to start private validator")
   971  	}
   972  
   973  	pvsc, err := privval.NewSignerClient(pve)
   974  	if err != nil {
   975  		return nil, errors.Wrap(err, "failed to start private validator")
   976  	}
   977  
   978  	return pvsc, nil
   979  }
   980  
   981  // splitAndTrimEmpty slices s into all subslices separated by sep and returns a
   982  // slice of the string s with all leading and trailing Unicode code points
   983  // contained in cutset removed. If sep is empty, SplitAndTrim splits after each
   984  // UTF-8 sequence. First part is equivalent to strings.SplitN with a count of
   985  // -1.  also filter out empty strings, only return non-empty strings.
   986  func splitAndTrimEmpty(s, sep, cutset string) []string {
   987  	if s == "" {
   988  		return []string{}
   989  	}
   990  
   991  	spl := strings.Split(s, sep)
   992  	nonEmptyStrings := make([]string, 0, len(spl))
   993  	for i := 0; i < len(spl); i++ {
   994  		element := strings.Trim(spl[i], cutset)
   995  		if element != "" {
   996  			nonEmptyStrings = append(nonEmptyStrings, element)
   997  		}
   998  	}
   999  	return nonEmptyStrings
  1000  }