mirror of
https://github.com/tendermint/tendermint.git
synced 2026-01-08 06:15:33 +00:00
node: change package interface (#6540)
This commit is contained in:
40
node/doc.go
40
node/doc.go
@@ -1,40 +1,6 @@
|
||||
/*
|
||||
Package node is the main entry point, where the Node struct, which
|
||||
represents a full node, is defined.
|
||||
|
||||
Adding new p2p.Reactor(s)
|
||||
|
||||
To add a new p2p.Reactor, use the CustomReactors option:
|
||||
|
||||
node, err := NewNode(
|
||||
config,
|
||||
privVal,
|
||||
nodeKey,
|
||||
clientCreator,
|
||||
genesisDocProvider,
|
||||
dbProvider,
|
||||
metricsProvider,
|
||||
logger,
|
||||
CustomReactors(map[string]p2p.Reactor{"CUSTOM": customReactor}),
|
||||
)
|
||||
|
||||
Replacing existing p2p.Reactor(s)
|
||||
|
||||
To replace the built-in p2p.Reactor, use the CustomReactors option:
|
||||
|
||||
node, err := NewNode(
|
||||
config,
|
||||
privVal,
|
||||
nodeKey,
|
||||
clientCreator,
|
||||
genesisDocProvider,
|
||||
dbProvider,
|
||||
metricsProvider,
|
||||
logger,
|
||||
CustomReactors(map[string]p2p.Reactor{"BLOCKCHAIN": customBlockchainReactor}),
|
||||
)
|
||||
|
||||
The list of existing reactors can be found in CustomReactors documentation.
|
||||
|
||||
Package node is the main entry point, where the tendermint node
|
||||
service is constructed and the implementation of that service is
|
||||
defined.
|
||||
*/
|
||||
package node
|
||||
|
||||
35
node/id.go
35
node/id.go
@@ -1,35 +0,0 @@
|
||||
package node
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/tendermint/tendermint/crypto"
|
||||
)
|
||||
|
||||
type ID struct {
|
||||
Name string
|
||||
PubKey crypto.PubKey
|
||||
}
|
||||
|
||||
type PrivNodeID struct {
|
||||
ID
|
||||
PrivKey crypto.PrivKey
|
||||
}
|
||||
|
||||
type Greeting struct {
|
||||
ID
|
||||
Version string
|
||||
ChainID string
|
||||
Message string
|
||||
Time time.Time
|
||||
}
|
||||
|
||||
type SignedNodeGreeting struct {
|
||||
Greeting
|
||||
Signature []byte
|
||||
}
|
||||
|
||||
func (pnid *PrivNodeID) SignGreeting() *SignedNodeGreeting {
|
||||
// greeting := NodeGreeting{}
|
||||
return nil
|
||||
}
|
||||
186
node/node.go
186
node/node.go
@@ -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)
|
||||
|
||||
@@ -27,7 +27,6 @@ import (
|
||||
"github.com/tendermint/tendermint/mempool"
|
||||
mempoolv0 "github.com/tendermint/tendermint/mempool/v0"
|
||||
"github.com/tendermint/tendermint/p2p"
|
||||
p2pmock "github.com/tendermint/tendermint/p2p/mock"
|
||||
"github.com/tendermint/tendermint/privval"
|
||||
"github.com/tendermint/tendermint/proxy"
|
||||
sm "github.com/tendermint/tendermint/state"
|
||||
@@ -42,10 +41,12 @@ func TestNodeStartStop(t *testing.T) {
|
||||
defer os.RemoveAll(config.RootDir)
|
||||
|
||||
// create & start node
|
||||
n, err := DefaultNewNode(config, log.TestingLogger())
|
||||
require.NoError(t, err)
|
||||
err = n.Start()
|
||||
ns, err := newDefaultNode(config, log.TestingLogger())
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, ns.Start())
|
||||
|
||||
n, ok := ns.(*nodeImpl)
|
||||
require.True(t, ok)
|
||||
|
||||
t.Logf("Started node %v", n.sw.NodeInfo())
|
||||
|
||||
@@ -80,18 +81,26 @@ func TestNodeStartStop(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func getTestNode(t *testing.T, conf *cfg.Config, logger log.Logger) *nodeImpl {
|
||||
t.Helper()
|
||||
ns, err := newDefaultNode(conf, logger)
|
||||
require.NoError(t, err)
|
||||
|
||||
n, ok := ns.(*nodeImpl)
|
||||
require.True(t, ok)
|
||||
return n
|
||||
}
|
||||
|
||||
func TestNodeDelayedStart(t *testing.T) {
|
||||
config := cfg.ResetTestRoot("node_delayed_start_test")
|
||||
defer os.RemoveAll(config.RootDir)
|
||||
now := tmtime.Now()
|
||||
|
||||
// create & start node
|
||||
n, err := DefaultNewNode(config, log.TestingLogger())
|
||||
n := getTestNode(t, config, log.TestingLogger())
|
||||
n.GenesisDoc().GenesisTime = now.Add(2 * time.Second)
|
||||
require.NoError(t, err)
|
||||
|
||||
err = n.Start()
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, n.Start())
|
||||
defer n.Stop() //nolint:errcheck // ignore for tests
|
||||
|
||||
startTime := tmtime.Now()
|
||||
@@ -102,9 +111,8 @@ func TestNodeSetAppVersion(t *testing.T) {
|
||||
config := cfg.ResetTestRoot("node_app_version_test")
|
||||
defer os.RemoveAll(config.RootDir)
|
||||
|
||||
// create & start node
|
||||
n, err := DefaultNewNode(config, log.TestingLogger())
|
||||
require.NoError(t, err)
|
||||
// create node
|
||||
n := getTestNode(t, config, log.TestingLogger())
|
||||
|
||||
// default config uses the kvstore app
|
||||
var appVersion uint64 = kvstore.ProtocolVersion
|
||||
@@ -146,8 +154,7 @@ func TestNodeSetPrivValTCP(t *testing.T) {
|
||||
}()
|
||||
defer signerServer.Stop() //nolint:errcheck // ignore for tests
|
||||
|
||||
n, err := DefaultNewNode(config, log.TestingLogger())
|
||||
require.NoError(t, err)
|
||||
n := getTestNode(t, config, log.TestingLogger())
|
||||
assert.IsType(t, &privval.RetrySignerClient{}, n.PrivValidator())
|
||||
}
|
||||
|
||||
@@ -159,7 +166,7 @@ func TestPrivValidatorListenAddrNoProtocol(t *testing.T) {
|
||||
defer os.RemoveAll(config.RootDir)
|
||||
config.PrivValidator.ListenAddr = addrNoPrefix
|
||||
|
||||
_, err := DefaultNewNode(config, log.TestingLogger())
|
||||
_, err := newDefaultNode(config, log.TestingLogger())
|
||||
assert.Error(t, err)
|
||||
}
|
||||
|
||||
@@ -189,9 +196,7 @@ func TestNodeSetPrivValIPC(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
}()
|
||||
defer pvsc.Stop() //nolint:errcheck // ignore for tests
|
||||
|
||||
n, err := DefaultNewNode(config, log.TestingLogger())
|
||||
require.NoError(t, err)
|
||||
n := getTestNode(t, config, log.TestingLogger())
|
||||
assert.IsType(t, &privval.RetrySignerClient{}, n.PrivValidator())
|
||||
}
|
||||
|
||||
@@ -470,43 +475,6 @@ func TestMaxProposalBlockSize(t *testing.T) {
|
||||
|
||||
}
|
||||
|
||||
func TestNodeNewNodeCustomReactors(t *testing.T) {
|
||||
config := cfg.ResetTestRoot("node_new_node_custom_reactors_test")
|
||||
defer os.RemoveAll(config.RootDir)
|
||||
|
||||
cr := p2pmock.NewReactor()
|
||||
customBlockchainReactor := p2pmock.NewReactor()
|
||||
|
||||
nodeKey, err := p2p.LoadOrGenNodeKey(config.NodeKeyFile())
|
||||
require.NoError(t, err)
|
||||
pval, err := privval.LoadOrGenFilePV(config.PrivValidatorKeyFile(), config.PrivValidatorStateFile())
|
||||
require.NoError(t, err)
|
||||
|
||||
appClient, closer := proxy.DefaultClientCreator(config.ProxyApp, config.ABCI, config.DBDir())
|
||||
t.Cleanup(func() { closer.Close() })
|
||||
n, err := NewNode(config,
|
||||
pval,
|
||||
nodeKey,
|
||||
appClient,
|
||||
DefaultGenesisDocProviderFunc(config),
|
||||
DefaultDBProvider,
|
||||
DefaultMetricsProvider(config.Instrumentation),
|
||||
log.TestingLogger(),
|
||||
CustomReactors(map[string]p2p.Reactor{"FOO": cr, "BLOCKCHAIN": customBlockchainReactor}),
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
err = n.Start()
|
||||
require.NoError(t, err)
|
||||
defer n.Stop() //nolint:errcheck // ignore for tests
|
||||
|
||||
assert.True(t, cr.IsRunning())
|
||||
assert.Equal(t, cr, n.Switch().Reactor("FOO"))
|
||||
|
||||
assert.True(t, customBlockchainReactor.IsRunning())
|
||||
assert.Equal(t, customBlockchainReactor, n.Switch().Reactor("BLOCKCHAIN"))
|
||||
}
|
||||
|
||||
func TestNodeNewSeedNode(t *testing.T) {
|
||||
config := cfg.ResetTestRoot("node_new_node_custom_reactors_test")
|
||||
config.Mode = cfg.ModeSeed
|
||||
@@ -515,13 +483,15 @@ func TestNodeNewSeedNode(t *testing.T) {
|
||||
nodeKey, err := p2p.LoadOrGenNodeKey(config.NodeKeyFile())
|
||||
require.NoError(t, err)
|
||||
|
||||
n, err := NewSeedNode(config,
|
||||
DefaultDBProvider,
|
||||
ns, err := makeSeedNode(config,
|
||||
cfg.DefaultDBProvider,
|
||||
nodeKey,
|
||||
DefaultGenesisDocProviderFunc(config),
|
||||
defaultGenesisDocProviderFunc(config),
|
||||
log.TestingLogger(),
|
||||
)
|
||||
require.NoError(t, err)
|
||||
n, ok := ns.(*nodeImpl)
|
||||
require.True(t, ok)
|
||||
|
||||
err = n.Start()
|
||||
require.NoError(t, err)
|
||||
@@ -533,58 +503,51 @@ func TestNodeSetEventSink(t *testing.T) {
|
||||
config := cfg.ResetTestRoot("node_app_version_test")
|
||||
defer os.RemoveAll(config.RootDir)
|
||||
|
||||
// create & start node
|
||||
n, err := DefaultNewNode(config, log.TestingLogger())
|
||||
require.NoError(t, err)
|
||||
n := getTestNode(t, config, log.TestingLogger())
|
||||
|
||||
assert.Equal(t, 1, len(n.eventSinks))
|
||||
assert.Equal(t, indexer.KV, n.eventSinks[0].Type())
|
||||
|
||||
config.TxIndex.Indexer = []string{"null"}
|
||||
n, err = DefaultNewNode(config, log.TestingLogger())
|
||||
require.NoError(t, err)
|
||||
n = getTestNode(t, config, log.TestingLogger())
|
||||
|
||||
assert.Equal(t, 1, len(n.eventSinks))
|
||||
assert.Equal(t, indexer.NULL, n.eventSinks[0].Type())
|
||||
|
||||
config.TxIndex.Indexer = []string{"null", "kv"}
|
||||
n, err = DefaultNewNode(config, log.TestingLogger())
|
||||
require.NoError(t, err)
|
||||
n = getTestNode(t, config, log.TestingLogger())
|
||||
|
||||
assert.Equal(t, 1, len(n.eventSinks))
|
||||
assert.Equal(t, indexer.NULL, n.eventSinks[0].Type())
|
||||
|
||||
config.TxIndex.Indexer = []string{"kvv"}
|
||||
n, err = DefaultNewNode(config, log.TestingLogger())
|
||||
assert.Nil(t, n)
|
||||
ns, err := newDefaultNode(config, log.TestingLogger())
|
||||
assert.Nil(t, ns)
|
||||
assert.Equal(t, errors.New("unsupported event sink type"), err)
|
||||
|
||||
config.TxIndex.Indexer = []string{}
|
||||
n, err = DefaultNewNode(config, log.TestingLogger())
|
||||
require.NoError(t, err)
|
||||
n = getTestNode(t, config, log.TestingLogger())
|
||||
|
||||
assert.Equal(t, 1, len(n.eventSinks))
|
||||
assert.Equal(t, indexer.NULL, n.eventSinks[0].Type())
|
||||
|
||||
config.TxIndex.Indexer = []string{"psql"}
|
||||
n, err = DefaultNewNode(config, log.TestingLogger())
|
||||
assert.Nil(t, n)
|
||||
ns, err = newDefaultNode(config, log.TestingLogger())
|
||||
assert.Nil(t, ns)
|
||||
assert.Equal(t, errors.New("the psql connection settings cannot be empty"), err)
|
||||
|
||||
var psqlConn = "test"
|
||||
|
||||
config.TxIndex.Indexer = []string{"psql"}
|
||||
config.TxIndex.PsqlConn = psqlConn
|
||||
n, err = DefaultNewNode(config, log.TestingLogger())
|
||||
require.NoError(t, err)
|
||||
n = getTestNode(t, config, log.TestingLogger())
|
||||
assert.Equal(t, 1, len(n.eventSinks))
|
||||
assert.Equal(t, indexer.PSQL, n.eventSinks[0].Type())
|
||||
n.OnStop()
|
||||
|
||||
config.TxIndex.Indexer = []string{"psql", "kv"}
|
||||
config.TxIndex.PsqlConn = psqlConn
|
||||
n, err = DefaultNewNode(config, log.TestingLogger())
|
||||
require.NoError(t, err)
|
||||
n = getTestNode(t, config, log.TestingLogger())
|
||||
assert.Equal(t, 2, len(n.eventSinks))
|
||||
// we use map to filter the duplicated sinks, so it's not guarantee the order when append sinks.
|
||||
if n.eventSinks[0].Type() == indexer.KV {
|
||||
@@ -597,8 +560,7 @@ func TestNodeSetEventSink(t *testing.T) {
|
||||
|
||||
config.TxIndex.Indexer = []string{"kv", "psql"}
|
||||
config.TxIndex.PsqlConn = psqlConn
|
||||
n, err = DefaultNewNode(config, log.TestingLogger())
|
||||
require.NoError(t, err)
|
||||
n = getTestNode(t, config, log.TestingLogger())
|
||||
assert.Equal(t, 2, len(n.eventSinks))
|
||||
if n.eventSinks[0].Type() == indexer.KV {
|
||||
assert.Equal(t, indexer.PSQL, n.eventSinks[1].Type())
|
||||
@@ -611,13 +573,13 @@ func TestNodeSetEventSink(t *testing.T) {
|
||||
var e = errors.New("found duplicated sinks, please check the tx-index section in the config.toml")
|
||||
config.TxIndex.Indexer = []string{"psql", "kv", "Kv"}
|
||||
config.TxIndex.PsqlConn = psqlConn
|
||||
_, err = DefaultNewNode(config, log.TestingLogger())
|
||||
_, err = newDefaultNode(config, log.TestingLogger())
|
||||
require.Error(t, err)
|
||||
assert.Equal(t, e, err)
|
||||
|
||||
config.TxIndex.Indexer = []string{"Psql", "kV", "kv", "pSql"}
|
||||
config.TxIndex.PsqlConn = psqlConn
|
||||
_, err = DefaultNewNode(config, log.TestingLogger())
|
||||
_, err = newDefaultNode(config, log.TestingLogger())
|
||||
require.Error(t, err)
|
||||
assert.Equal(t, e, err)
|
||||
}
|
||||
|
||||
67
node/public.go
Normal file
67
node/public.go
Normal file
@@ -0,0 +1,67 @@
|
||||
// Package node provides a high level wrapper around tendermint services.
|
||||
package node
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/tendermint/tendermint/config"
|
||||
"github.com/tendermint/tendermint/libs/log"
|
||||
"github.com/tendermint/tendermint/libs/service"
|
||||
"github.com/tendermint/tendermint/p2p"
|
||||
"github.com/tendermint/tendermint/privval"
|
||||
"github.com/tendermint/tendermint/proxy"
|
||||
"github.com/tendermint/tendermint/types"
|
||||
)
|
||||
|
||||
// NewDefault constructs a tendermint node service for use in go
|
||||
// process that host their own process-local tendermint node. This is
|
||||
// equivalent to running tendermint in it's own process communicating
|
||||
// to an external ABCI application.
|
||||
func NewDefault(conf *config.Config, logger log.Logger) (service.Service, error) {
|
||||
return newDefaultNode(conf, logger)
|
||||
}
|
||||
|
||||
// New constructs a tendermint node. The ClientCreator makes it
|
||||
// possible to construct an ABCI application that runs in the same
|
||||
// process as the tendermint node. The final option is a pointer to a
|
||||
// Genesis document: if the value is nil, the genesis document is read
|
||||
// from the file specified in the config, and otherwise the node uses
|
||||
// value of the final argument.
|
||||
func New(conf *config.Config,
|
||||
logger log.Logger,
|
||||
cf proxy.ClientCreator,
|
||||
gen *types.GenesisDoc,
|
||||
) (service.Service, error) {
|
||||
nodeKey, err := p2p.LoadOrGenNodeKey(conf.NodeKeyFile())
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to load or gen node key %s: %w", conf.NodeKeyFile(), err)
|
||||
}
|
||||
|
||||
var genProvider genesisDocProvider
|
||||
switch gen {
|
||||
case nil:
|
||||
genProvider = defaultGenesisDocProviderFunc(conf)
|
||||
default:
|
||||
genProvider = func() (*types.GenesisDoc, error) { return gen, nil }
|
||||
}
|
||||
|
||||
switch conf.Mode {
|
||||
case config.ModeFull, config.ModeValidator:
|
||||
pval, err := privval.LoadOrGenFilePV(conf.PrivValidatorKeyFile(), conf.PrivValidatorStateFile())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return makeNode(conf,
|
||||
pval,
|
||||
nodeKey,
|
||||
cf,
|
||||
genProvider,
|
||||
config.DefaultDBProvider,
|
||||
logger)
|
||||
case config.ModeSeed:
|
||||
return makeSeedNode(conf, config.DefaultDBProvider, nodeKey, genProvider, logger)
|
||||
default:
|
||||
return nil, fmt.Errorf("%q is not a valid mode", conf.Mode)
|
||||
}
|
||||
}
|
||||
@@ -41,15 +41,15 @@ import (
|
||||
"github.com/tendermint/tendermint/version"
|
||||
)
|
||||
|
||||
func initDBs(config *cfg.Config, dbProvider DBProvider) (blockStore *store.BlockStore, stateDB dbm.DB, err error) {
|
||||
func initDBs(config *cfg.Config, dbProvider cfg.DBProvider) (blockStore *store.BlockStore, stateDB dbm.DB, err error) {
|
||||
var blockStoreDB dbm.DB
|
||||
blockStoreDB, err = dbProvider(&DBContext{"blockstore", config})
|
||||
blockStoreDB, err = dbProvider(&cfg.DBContext{ID: "blockstore", Config: config})
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
blockStore = store.NewBlockStore(blockStoreDB)
|
||||
|
||||
stateDB, err = dbProvider(&DBContext{"state", config})
|
||||
stateDB, err = dbProvider(&cfg.DBContext{ID: "state", Config: config})
|
||||
return
|
||||
}
|
||||
|
||||
@@ -73,7 +73,7 @@ func createAndStartEventBus(logger log.Logger) (*types.EventBus, error) {
|
||||
|
||||
func createAndStartIndexerService(
|
||||
config *cfg.Config,
|
||||
dbProvider DBProvider,
|
||||
dbProvider cfg.DBProvider,
|
||||
eventBus *types.EventBus,
|
||||
logger log.Logger,
|
||||
chainID string,
|
||||
@@ -99,7 +99,7 @@ loop:
|
||||
eventSinks = []indexer.EventSink{null.NewEventSink()}
|
||||
break loop
|
||||
case string(indexer.KV):
|
||||
store, err := dbProvider(&DBContext{"tx_index", config})
|
||||
store, err := dbProvider(&cfg.DBContext{ID: "tx_index", Config: config})
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
@@ -278,14 +278,14 @@ func createMempoolReactor(
|
||||
|
||||
func createEvidenceReactor(
|
||||
config *cfg.Config,
|
||||
dbProvider DBProvider,
|
||||
dbProvider cfg.DBProvider,
|
||||
stateDB dbm.DB,
|
||||
blockStore *store.BlockStore,
|
||||
peerManager *p2p.PeerManager,
|
||||
router *p2p.Router,
|
||||
logger log.Logger,
|
||||
) (*p2p.ReactorShim, *evidence.Reactor, *evidence.Pool, error) {
|
||||
evidenceDB, err := dbProvider(&DBContext{"evidence", config})
|
||||
evidenceDB, err := dbProvider(&cfg.DBContext{ID: "evidence", Config: config})
|
||||
if err != nil {
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
@@ -450,7 +450,7 @@ func createTransport(logger log.Logger, config *cfg.Config) *p2p.MConnTransport
|
||||
|
||||
func createPeerManager(
|
||||
config *cfg.Config,
|
||||
dbProvider DBProvider,
|
||||
dbProvider cfg.DBProvider,
|
||||
p2pLogger log.Logger,
|
||||
nodeID p2p.NodeID,
|
||||
) (*p2p.PeerManager, error) {
|
||||
@@ -513,7 +513,7 @@ func createPeerManager(
|
||||
peers = append(peers, address)
|
||||
}
|
||||
|
||||
peerDB, err := dbProvider(&DBContext{"peerstore", config})
|
||||
peerDB, err := dbProvider(&cfg.DBContext{ID: "peerstore", Config: config})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user