node: change package interface (#6540)

This commit is contained in:
Sam Kleinman
2021-06-04 11:36:30 -04:00
committed by GitHub
parent 08b134ddbc
commit 00c284d9d7
11 changed files with 227 additions and 343 deletions
+59 -127
View File
@@ -10,12 +10,10 @@ import (
"strconv"
"time"
_ "github.com/lib/pq" // provide the psql db driver
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promhttp"
"github.com/rs/cors"
dbm "github.com/tendermint/tm-db"
_ "github.com/lib/pq" // provide the psql db driver
abci "github.com/tendermint/tendermint/abci/types"
cfg "github.com/tendermint/tendermint/config"
cs "github.com/tendermint/tendermint/consensus"
@@ -43,11 +41,12 @@ import (
"github.com/tendermint/tendermint/store"
"github.com/tendermint/tendermint/types"
tmtime "github.com/tendermint/tendermint/types/time"
dbm "github.com/tendermint/tm-db"
)
// Node is the highest level interface to a full Tendermint node.
// nodeImpl is the highest level interface to a full Tendermint node.
// It includes all configuration information and running services.
type Node struct {
type nodeImpl struct {
service.BaseService
// config
@@ -89,19 +88,19 @@ type Node struct {
prometheusSrv *http.Server
}
// DefaultNewNode returns a Tendermint node with default settings for the
// newDefaultNode returns a Tendermint node with default settings for the
// PrivValidator, ClientCreator, GenesisDoc, and DBProvider.
// It implements NodeProvider.
func DefaultNewNode(config *cfg.Config, logger log.Logger) (*Node, error) {
func newDefaultNode(config *cfg.Config, logger log.Logger) (service.Service, error) {
nodeKey, err := p2p.LoadOrGenNodeKey(config.NodeKeyFile())
if err != nil {
return nil, fmt.Errorf("failed to load or gen node key %s: %w", config.NodeKeyFile(), err)
}
if config.Mode == cfg.ModeSeed {
return NewSeedNode(config,
DefaultDBProvider,
return makeSeedNode(config,
cfg.DefaultDBProvider,
nodeKey,
DefaultGenesisDocProviderFunc(config),
defaultGenesisDocProviderFunc(config),
logger,
)
}
@@ -117,27 +116,24 @@ func DefaultNewNode(config *cfg.Config, logger log.Logger) (*Node, error) {
}
appClient, _ := proxy.DefaultClientCreator(config.ProxyApp, config.ABCI, config.DBDir())
return NewNode(config,
return makeNode(config,
pval,
nodeKey,
appClient,
DefaultGenesisDocProviderFunc(config),
DefaultDBProvider,
DefaultMetricsProvider(config.Instrumentation),
defaultGenesisDocProviderFunc(config),
cfg.DefaultDBProvider,
logger,
)
}
// NewNode returns a new, ready to go, Tendermint Node.
func NewNode(config *cfg.Config,
// makeNode returns a new, ready to go, Tendermint Node.
func makeNode(config *cfg.Config,
privValidator types.PrivValidator,
nodeKey p2p.NodeKey,
clientCreator proxy.ClientCreator,
genesisDocProvider GenesisDocProvider,
dbProvider DBProvider,
metricsProvider MetricsProvider,
logger log.Logger,
options ...Option) (*Node, error) {
genesisDocProvider genesisDocProvider,
dbProvider cfg.DBProvider,
logger log.Logger) (service.Service, error) {
blockStore, stateDB, err := initDBs(config, dbProvider)
if err != nil {
@@ -146,7 +142,7 @@ func NewNode(config *cfg.Config,
stateStore := sm.NewStore(stateDB)
state, genDoc, err := LoadStateFromDBOrGenesisDocProvider(stateDB, genesisDocProvider)
state, genDoc, err := loadStateFromDBOrGenesisDocProvider(stateDB, genesisDocProvider)
if err != nil {
return nil, err
}
@@ -245,7 +241,7 @@ func NewNode(config *cfg.Config,
return nil, fmt.Errorf("failed to create peer manager: %w", err)
}
csMetrics, p2pMetrics, memplMetrics, smMetrics := metricsProvider(genDoc.ChainID)
csMetrics, p2pMetrics, memplMetrics, smMetrics := defaultMetricsProvider(config.Instrumentation)(genDoc.ChainID)
router, err := createRouter(p2pLogger, p2pMetrics, nodeInfo, nodeKey.PrivKey,
peerManager, transport, getRouterConfig(config, proxyApp))
@@ -412,7 +408,7 @@ func NewNode(config *cfg.Config,
}()
}
node := &Node{
node := &nodeImpl{
config: config,
genesisDoc: genDoc,
privValidator: privValidator,
@@ -446,20 +442,16 @@ func NewNode(config *cfg.Config,
}
node.BaseService = *service.NewBaseService(logger, "Node", node)
for _, option := range options {
option(node)
}
return node, nil
}
// NewSeedNode returns a new seed node, containing only p2p, pex reactor
func NewSeedNode(config *cfg.Config,
dbProvider DBProvider,
// makeSeedNode returns a new seed node, containing only p2p, pex reactor
func makeSeedNode(config *cfg.Config,
dbProvider cfg.DBProvider,
nodeKey p2p.NodeKey,
genesisDocProvider GenesisDocProvider,
genesisDocProvider genesisDocProvider,
logger log.Logger,
options ...Option) (*Node, error) {
) (service.Service, error) {
genDoc, err := genesisDocProvider()
if err != nil {
@@ -538,7 +530,7 @@ func NewSeedNode(config *cfg.Config,
}()
}
node := &Node{
node := &nodeImpl{
config: config,
genesisDoc: genDoc,
@@ -555,58 +547,17 @@ func NewSeedNode(config *cfg.Config,
}
node.BaseService = *service.NewBaseService(logger, "SeedNode", node)
for _, option := range options {
option(node)
}
return node, nil
}
// Option sets a parameter for the node.
type Option func(*Node)
// Temporary interface for switching to fast sync, we should get rid of v0.
// See: https://github.com/tendermint/tendermint/issues/4595
type fastSyncReactor interface {
SwitchToFastSync(sm.State) error
}
// CustomReactors allows you to add custom reactors (name -> p2p.Reactor) to
// the node's Switch.
//
// WARNING: using any name from the below list of the existing reactors will
// result in replacing it with the custom one.
//
// - MEMPOOL
// - BLOCKCHAIN
// - CONSENSUS
// - EVIDENCE
// - PEX
// - STATESYNC
func CustomReactors(reactors map[string]p2p.Reactor) Option {
return func(n *Node) {
for name, reactor := range reactors {
if existingReactor := n.sw.Reactor(name); existingReactor != nil {
n.sw.Logger.Info("Replacing existing reactor with a custom one",
"name", name, "existing", existingReactor, "custom", reactor)
n.sw.RemoveReactor(name, existingReactor)
}
n.sw.AddReactor(name, reactor)
}
}
}
// StateProvider overrides the state provider used by state sync to retrieve trusted app hashes and
// build a State object for bootstrapping the node.
// WARNING: this interface is considered unstable and subject to change.
func StateProvider(stateProvider statesync.StateProvider) Option {
return func(n *Node) {
n.stateSyncProvider = stateProvider
}
}
// OnStart starts the Node. It implements service.Service.
func (n *Node) OnStart() error {
func (n *nodeImpl) OnStart() error {
now := tmtime.Now()
genTime := n.genesisDoc.GenesisTime
if genTime.After(now) {
@@ -712,7 +663,7 @@ func (n *Node) OnStart() error {
}
// OnStop stops the Node. It implements service.Service.
func (n *Node) OnStop() {
func (n *nodeImpl) OnStop() {
n.Logger.Info("Stopping Node")
@@ -799,7 +750,7 @@ func (n *Node) OnStop() {
}
// ConfigureRPC makes sure RPC has all the objects it needs to operate.
func (n *Node) ConfigureRPC() (*rpccore.Environment, error) {
func (n *nodeImpl) ConfigureRPC() (*rpccore.Environment, error) {
rpcCoreEnv := rpccore.Environment{
ProxyAppQuery: n.proxyApp.Query(),
ProxyAppMempool: n.proxyApp.Mempool(),
@@ -835,7 +786,7 @@ func (n *Node) ConfigureRPC() (*rpccore.Environment, error) {
return &rpcCoreEnv, nil
}
func (n *Node) startRPC() ([]net.Listener, error) {
func (n *nodeImpl) startRPC() ([]net.Listener, error) {
env, err := n.ConfigureRPC()
if err != nil {
return nil, err
@@ -956,7 +907,7 @@ func (n *Node) startRPC() ([]net.Listener, error) {
// startPrometheusServer starts a Prometheus HTTP server, listening for metrics
// collectors on addr.
func (n *Node) startPrometheusServer(addr string) *http.Server {
func (n *nodeImpl) startPrometheusServer(addr string) *http.Server {
srv := &http.Server{
Addr: addr,
Handler: promhttp.InstrumentMetricHandler(
@@ -976,90 +927,90 @@ func (n *Node) startPrometheusServer(addr string) *http.Server {
}
// Switch returns the Node's Switch.
func (n *Node) Switch() *p2p.Switch {
func (n *nodeImpl) Switch() *p2p.Switch {
return n.sw
}
// BlockStore returns the Node's BlockStore.
func (n *Node) BlockStore() *store.BlockStore {
func (n *nodeImpl) BlockStore() *store.BlockStore {
return n.blockStore
}
// ConsensusState returns the Node's ConsensusState.
func (n *Node) ConsensusState() *cs.State {
func (n *nodeImpl) ConsensusState() *cs.State {
return n.consensusState
}
// ConsensusReactor returns the Node's ConsensusReactor.
func (n *Node) ConsensusReactor() *cs.Reactor {
func (n *nodeImpl) ConsensusReactor() *cs.Reactor {
return n.consensusReactor
}
// MempoolReactor returns the Node's mempool reactor.
func (n *Node) MempoolReactor() service.Service {
func (n *nodeImpl) MempoolReactor() service.Service {
return n.mempoolReactor
}
// Mempool returns the Node's mempool.
func (n *Node) Mempool() mempool.Mempool {
func (n *nodeImpl) Mempool() mempool.Mempool {
return n.mempool
}
// PEXReactor returns the Node's PEXReactor. It returns nil if PEX is disabled.
func (n *Node) PEXReactor() *pex.Reactor {
func (n *nodeImpl) PEXReactor() *pex.Reactor {
return n.pexReactor
}
// EvidencePool returns the Node's EvidencePool.
func (n *Node) EvidencePool() *evidence.Pool {
func (n *nodeImpl) EvidencePool() *evidence.Pool {
return n.evidencePool
}
// EventBus returns the Node's EventBus.
func (n *Node) EventBus() *types.EventBus {
func (n *nodeImpl) EventBus() *types.EventBus {
return n.eventBus
}
// PrivValidator returns the Node's PrivValidator.
// XXX: for convenience only!
func (n *Node) PrivValidator() types.PrivValidator {
func (n *nodeImpl) PrivValidator() types.PrivValidator {
return n.privValidator
}
// GenesisDoc returns the Node's GenesisDoc.
func (n *Node) GenesisDoc() *types.GenesisDoc {
func (n *nodeImpl) GenesisDoc() *types.GenesisDoc {
return n.genesisDoc
}
// ProxyApp returns the Node's AppConns, representing its connections to the ABCI application.
func (n *Node) ProxyApp() proxy.AppConns {
func (n *nodeImpl) ProxyApp() proxy.AppConns {
return n.proxyApp
}
// Config returns the Node's config.
func (n *Node) Config() *cfg.Config {
func (n *nodeImpl) Config() *cfg.Config {
return n.config
}
// EventSinks returns the Node's event indexing sinks.
func (n *Node) EventSinks() []indexer.EventSink {
func (n *nodeImpl) EventSinks() []indexer.EventSink {
return n.eventSinks
}
//------------------------------------------------------------------------------
func (n *Node) Listeners() []string {
func (n *nodeImpl) Listeners() []string {
return []string{
fmt.Sprintf("Listener(@%v)", n.config.P2P.ExternalAddress),
}
}
func (n *Node) IsListening() bool {
func (n *nodeImpl) IsListening() bool {
return n.isListening
}
// NodeInfo returns the Node's Info from the Switch.
func (n *Node) NodeInfo() p2p.NodeInfo {
func (n *nodeImpl) NodeInfo() p2p.NodeInfo {
return n.nodeInfo
}
@@ -1119,44 +1070,25 @@ func startStateSync(ssR *statesync.Reactor, bcR fastSyncReactor, conR *cs.Reacto
return nil
}
// DBContext specifies config information for loading a new DB.
type DBContext struct {
ID string
Config *cfg.Config
}
// DBProvider takes a DBContext and returns an instantiated DB.
type DBProvider func(*DBContext) (dbm.DB, error)
// DefaultDBProvider returns a database using the DBBackend and DBDir
// specified in the ctx.Config.
func DefaultDBProvider(ctx *DBContext) (dbm.DB, error) {
dbType := dbm.BackendType(ctx.Config.DBBackend)
return dbm.NewDB(ctx.ID, dbType, ctx.Config.DBDir())
}
// GenesisDocProvider returns a GenesisDoc.
// genesisDocProvider returns a GenesisDoc.
// It allows the GenesisDoc to be pulled from sources other than the
// filesystem, for instance from a distributed key-value store cluster.
type GenesisDocProvider func() (*types.GenesisDoc, error)
type genesisDocProvider func() (*types.GenesisDoc, error)
// DefaultGenesisDocProviderFunc returns a GenesisDocProvider that loads
// defaultGenesisDocProviderFunc returns a GenesisDocProvider that loads
// the GenesisDoc from the config.GenesisFile() on the filesystem.
func DefaultGenesisDocProviderFunc(config *cfg.Config) GenesisDocProvider {
func defaultGenesisDocProviderFunc(config *cfg.Config) genesisDocProvider {
return func() (*types.GenesisDoc, error) {
return types.GenesisDocFromFile(config.GenesisFile())
}
}
// Provider takes a config and a logger and returns a ready to go Node.
type Provider func(*cfg.Config, log.Logger) (*Node, error)
// metricsProvider returns a consensus, p2p and mempool Metrics.
type metricsProvider func(chainID string) (*cs.Metrics, *p2p.Metrics, *mempool.Metrics, *sm.Metrics)
// MetricsProvider returns a consensus, p2p and mempool Metrics.
type MetricsProvider func(chainID string) (*cs.Metrics, *p2p.Metrics, *mempool.Metrics, *sm.Metrics)
// DefaultMetricsProvider returns Metrics build using Prometheus client library
// defaultMetricsProvider returns Metrics build using Prometheus client library
// if Prometheus is enabled. Otherwise, it returns no-op Metrics.
func DefaultMetricsProvider(config *cfg.InstrumentationConfig) MetricsProvider {
func defaultMetricsProvider(config *cfg.InstrumentationConfig) metricsProvider {
return func(chainID string) (*cs.Metrics, *p2p.Metrics, *mempool.Metrics, *sm.Metrics) {
if config.Prometheus {
return cs.PrometheusMetrics(config.Namespace, "chain_id", chainID),
@@ -1174,12 +1106,12 @@ var (
genesisDocKey = []byte("genesisDoc")
)
// LoadStateFromDBOrGenesisDocProvider attempts to load the state from the
// loadStateFromDBOrGenesisDocProvider attempts to load the state from the
// database, or creates one using the given genesisDocProvider. On success this also
// returns the genesis doc loaded through the given provider.
func LoadStateFromDBOrGenesisDocProvider(
func loadStateFromDBOrGenesisDocProvider(
stateDB dbm.DB,
genesisDocProvider GenesisDocProvider,
genesisDocProvider genesisDocProvider,
) (sm.State, *types.GenesisDoc, error) {
// Get genesis doc
genDoc, err := loadGenesisDoc(stateDB)