github.com/onflow/flow-go@v0.33.17/cmd/node_builder.go (about)

     1  package cmd
     2  
     3  import (
     4  	"context"
     5  	"time"
     6  
     7  	"github.com/dgraph-io/badger/v2"
     8  	madns "github.com/multiformats/go-multiaddr-dns"
     9  	"github.com/prometheus/client_golang/prometheus"
    10  	"github.com/rs/zerolog"
    11  	"github.com/spf13/pflag"
    12  
    13  	"github.com/onflow/flow-go/admin/commands"
    14  	"github.com/onflow/flow-go/config"
    15  	"github.com/onflow/flow-go/crypto"
    16  	"github.com/onflow/flow-go/fvm"
    17  	"github.com/onflow/flow-go/model/flow"
    18  	"github.com/onflow/flow-go/module"
    19  	"github.com/onflow/flow-go/module/chainsync"
    20  	"github.com/onflow/flow-go/module/compliance"
    21  	"github.com/onflow/flow-go/module/component"
    22  	"github.com/onflow/flow-go/module/profiler"
    23  	"github.com/onflow/flow-go/module/updatable_configs"
    24  	"github.com/onflow/flow-go/network"
    25  	"github.com/onflow/flow-go/network/codec/cbor"
    26  	"github.com/onflow/flow-go/network/p2p"
    27  	"github.com/onflow/flow-go/state/protocol"
    28  	"github.com/onflow/flow-go/state/protocol/events"
    29  	bstorage "github.com/onflow/flow-go/storage/badger"
    30  	"github.com/onflow/flow-go/utils/grpcutils"
    31  )
    32  
    33  const NotSet = "not set"
    34  
    35  type BuilderFunc func(nodeConfig *NodeConfig) error
    36  type ReadyDoneFactory func(node *NodeConfig) (module.ReadyDoneAware, error)
    37  
    38  // NodeBuilder declares the initialization methods needed to bootstrap up a Flow node
    39  type NodeBuilder interface {
    40  	// BaseFlags reads the command line arguments common to all nodes
    41  	BaseFlags()
    42  
    43  	// ExtraFlags reads the node specific command line arguments and adds it to the FlagSet
    44  	ExtraFlags(f func(*pflag.FlagSet)) NodeBuilder
    45  
    46  	// ParseAndPrintFlags parses and validates all the command line arguments
    47  	ParseAndPrintFlags() error
    48  
    49  	// Initialize performs all the initialization needed at the very start of a node
    50  	Initialize() error
    51  
    52  	// PrintBuildVersionDetails prints the node software build version
    53  	PrintBuildVersionDetails()
    54  
    55  	// InitIDProviders initializes the ID providers needed by various components
    56  	InitIDProviders()
    57  
    58  	// EnqueueNetworkInit enqueues the default networking layer.
    59  	EnqueueNetworkInit()
    60  
    61  	// EnqueueMetricsServerInit enqueues the metrics component.
    62  	EnqueueMetricsServerInit()
    63  
    64  	// EnqueueTracer enqueues the Tracer component.
    65  	EnqueueTracer()
    66  
    67  	// Module enables setting up dependencies of the engine with the builder context
    68  	Module(name string, f BuilderFunc) NodeBuilder
    69  
    70  	// Component adds a new component to the node that conforms to the ReadyDoneAware
    71  	// interface, and throws a Fatal() when an irrecoverable error is encountered.
    72  	//
    73  	// The ReadyDoneFactory may return either a `Component` or `ReadyDoneAware` instance.
    74  	// In both cases, the object is started according to its interface when the node is run,
    75  	// and the node will wait for the component to exit gracefully.
    76  	Component(name string, f ReadyDoneFactory) NodeBuilder
    77  
    78  	// DependableComponent adds a new component to the node that conforms to the ReadyDoneAware
    79  	// interface. The builder will wait until all of the components in the dependencies list are ready
    80  	// before constructing the component.
    81  	//
    82  	// The ReadyDoneFactory may return either a `Component` or `ReadyDoneAware` instance.
    83  	// In both cases, the object is started when the node is run, and the node will wait for the
    84  	// component to exit gracefully.
    85  	//
    86  	// IMPORTANT: Dependable components are started in parallel with no guaranteed run order, so all
    87  	// dependencies must be initialized outside of the ReadyDoneFactory, and their `Ready()` method
    88  	// MUST be idempotent.
    89  	DependableComponent(name string, f ReadyDoneFactory, dependencies *DependencyList) NodeBuilder
    90  
    91  	// RestartableComponent adds a new component to the node that conforms to the ReadyDoneAware
    92  	// interface, and calls the provided error handler when an irrecoverable error is encountered.
    93  	// Use RestartableComponent if the component is not critical to the node's safe operation and
    94  	// can/should be independently restarted when an irrecoverable error is encountered.
    95  	//
    96  	// Any irrecoverable errors thrown by the component will be passed to the provided error handler.
    97  	RestartableComponent(name string, f ReadyDoneFactory, errorHandler component.OnError) NodeBuilder
    98  
    99  	// ShutdownFunc adds a callback function that is called after all components have exited.
   100  	// All shutdown functions are called regardless of errors returned by previous callbacks. Any
   101  	// errors returned are captured and passed to the caller.
   102  	ShutdownFunc(fn func() error) NodeBuilder
   103  
   104  	// AdminCommand registers a new admin command with the admin server
   105  	AdminCommand(command string, f func(config *NodeConfig) commands.AdminCommand) NodeBuilder
   106  
   107  	// Build finalizes the node configuration in preparation for start and returns a Node
   108  	// object that can be run
   109  	Build() (Node, error)
   110  
   111  	// PreInit registers a new PreInit function.
   112  	// PreInit functions run before the protocol state is initialized or any other modules or components are initialized
   113  	PreInit(f BuilderFunc) NodeBuilder
   114  
   115  	// PostInit registers a new PreInit function.
   116  	// PostInit functions run after the protocol state has been initialized but before any other modules or components
   117  	// are initialized
   118  	PostInit(f BuilderFunc) NodeBuilder
   119  
   120  	// RegisterBadgerMetrics registers all badger related metrics
   121  	RegisterBadgerMetrics() error
   122  
   123  	// ValidateFlags sets any custom validation rules for the command line flags,
   124  	// for example where certain combinations aren't allowed
   125  	ValidateFlags(func() error) NodeBuilder
   126  
   127  	// ValidateRootSnapshot sets any custom validation rules for the root snapshot.
   128  	// This check is executed after other checks but before applying any data from root snapshot.
   129  	ValidateRootSnapshot(f func(protocol.Snapshot) error) NodeBuilder
   130  }
   131  
   132  // BaseConfig is the general config for the NodeBuilder and the command line params
   133  // For a node running as a standalone process, the config fields will be populated from the command line params,
   134  // while for a node running as a library, the config fields are expected to be initialized by the caller.
   135  type BaseConfig struct {
   136  	nodeIDHex                   string
   137  	AdminAddr                   string
   138  	AdminCert                   string
   139  	AdminKey                    string
   140  	AdminClientCAs              string
   141  	AdminMaxMsgSize             uint
   142  	BindAddr                    string
   143  	NodeRole                    string
   144  	ObserverMode                bool
   145  	DynamicStartupANAddress     string
   146  	DynamicStartupANPubkey      string
   147  	DynamicStartupEpochPhase    string
   148  	DynamicStartupEpoch         string
   149  	DynamicStartupSleepInterval time.Duration
   150  	datadir                     string
   151  	secretsdir                  string
   152  	secretsDBEnabled            bool
   153  	InsecureSecretsDB           bool
   154  	level                       string
   155  	debugLogLimit               uint32
   156  	metricsPort                 uint
   157  	BootstrapDir                string
   158  	profilerConfig              profiler.ProfilerConfig
   159  	tracerEnabled               bool
   160  	tracerSensitivity           uint
   161  	MetricsEnabled              bool
   162  	guaranteesCacheSize         uint
   163  	receiptsCacheSize           uint
   164  	db                          *badger.DB
   165  	HeroCacheMetricsEnable      bool
   166  	SyncCoreConfig              chainsync.Config
   167  	CodecFactory                func() network.Codec
   168  	LibP2PNode                  p2p.LibP2PNode
   169  	// ComplianceConfig configures either the compliance engine (consensus nodes)
   170  	// or the follower engine (all other node roles)
   171  	ComplianceConfig compliance.Config
   172  
   173  	// FlowConfig Flow configuration.
   174  	FlowConfig config.FlowConfig
   175  }
   176  
   177  // NodeConfig contains all the derived parameters such the NodeID, private keys etc. and initialized instances of
   178  // structs such as DB, Network etc. The NodeConfig is composed of the BaseConfig and is updated in the
   179  // NodeBuilder functions as a node is bootstrapped.
   180  type NodeConfig struct {
   181  	Cancel context.CancelFunc // cancel function for the context that is passed to the networking layer
   182  	BaseConfig
   183  	Logger            zerolog.Logger
   184  	NodeID            flow.Identifier
   185  	Me                module.Local
   186  	Tracer            module.Tracer
   187  	ConfigManager     *updatable_configs.Manager
   188  	MetricsRegisterer prometheus.Registerer
   189  	Metrics           Metrics
   190  	DB                *badger.DB
   191  	SecretsDB         *badger.DB
   192  	Storage           Storage
   193  	ProtocolEvents    *events.Distributor
   194  	State             protocol.State
   195  	Resolver          madns.BasicResolver
   196  	EngineRegistry    network.EngineRegistry
   197  	NetworkUnderlay   network.Underlay
   198  	ConduitFactory    network.ConduitFactory
   199  	PingService       network.PingService
   200  	MsgValidators     []network.MessageValidator
   201  	FvmOptions        []fvm.Option
   202  	StakingKey        crypto.PrivateKey
   203  	NetworkKey        crypto.PrivateKey
   204  
   205  	// list of dependencies for network peer manager startup
   206  	PeerManagerDependencies *DependencyList
   207  	// ReadyDoneAware implementation of the network middleware for DependableComponents
   208  	networkUnderlayDependable *module.ProxiedReadyDoneAware
   209  
   210  	// ID providers
   211  	IdentityProvider             module.IdentityProvider
   212  	IDTranslator                 p2p.IDTranslator
   213  	SyncEngineIdentifierProvider module.IdentifierProvider
   214  
   215  	// root state information
   216  	RootSnapshot protocol.Snapshot
   217  	// excerpt of root snapshot and latest finalized snapshot, when we boot up
   218  	StateExcerptAtBoot
   219  
   220  	// bootstrapping options
   221  	SkipNwAddressBasedValidations bool
   222  
   223  	// UnicastRateLimiterDistributor notifies consumers when a peer's unicast message is rate limited.
   224  	UnicastRateLimiterDistributor p2p.UnicastRateLimiterDistributor
   225  }
   226  
   227  // StateExcerptAtBoot stores information about the root snapshot and latest finalized block for use in bootstrapping.
   228  type StateExcerptAtBoot struct {
   229  	// properties of RootSnapshot for convenience
   230  	// For node bootstrapped with a root snapshot for the first block of a spork,
   231  	// 		FinalizedRootBlock and SealedRootBlock are the same block (special case of self-sealing block)
   232  	// For node bootstrapped with a root snapshot for a block above the first block of a spork (dynamically bootstrapped),
   233  	// 		FinalizedRootBlock.Height > SealedRootBlock.Height
   234  	FinalizedRootBlock  *flow.Block             // The last finalized block when bootstrapped.
   235  	SealedRootBlock     *flow.Block             // The last sealed block when bootstrapped.
   236  	RootQC              *flow.QuorumCertificate // QC for Finalized Root Block
   237  	RootResult          *flow.ExecutionResult   // Result for SealedRootBlock
   238  	RootSeal            *flow.Seal              //Seal for RootResult
   239  	RootChainID         flow.ChainID
   240  	SporkID             flow.Identifier
   241  	LastFinalizedHeader *flow.Header // last finalized header when the node boots up
   242  }
   243  
   244  func DefaultBaseConfig() *BaseConfig {
   245  	datadir := "/data/protocol"
   246  
   247  	// NOTE: if the codec used in the network component is ever changed any code relying on
   248  	// the message format specific to the codec must be updated. i.e: the AuthorizedSenderValidator.
   249  	codecFactory := func() network.Codec { return cbor.NewCodec() }
   250  
   251  	return &BaseConfig{
   252  		nodeIDHex:        NotSet,
   253  		AdminAddr:        NotSet,
   254  		AdminCert:        NotSet,
   255  		AdminKey:         NotSet,
   256  		AdminClientCAs:   NotSet,
   257  		AdminMaxMsgSize:  grpcutils.DefaultMaxMsgSize,
   258  		BindAddr:         NotSet,
   259  		ObserverMode:     false,
   260  		BootstrapDir:     "bootstrap",
   261  		datadir:          datadir,
   262  		secretsdir:       NotSet,
   263  		secretsDBEnabled: true,
   264  		level:            "info",
   265  		debugLogLimit:    2000,
   266  
   267  		metricsPort:         8080,
   268  		tracerEnabled:       false,
   269  		tracerSensitivity:   4,
   270  		MetricsEnabled:      true,
   271  		receiptsCacheSize:   bstorage.DefaultCacheSize,
   272  		guaranteesCacheSize: bstorage.DefaultCacheSize,
   273  
   274  		profilerConfig: profiler.ProfilerConfig{
   275  			Enabled:         false,
   276  			UploaderEnabled: false,
   277  
   278  			Dir:      "profiler",
   279  			Interval: 15 * time.Minute,
   280  			Duration: 10 * time.Second,
   281  		},
   282  
   283  		HeroCacheMetricsEnable: false,
   284  		SyncCoreConfig:         chainsync.DefaultConfig(),
   285  		CodecFactory:           codecFactory,
   286  		ComplianceConfig:       compliance.DefaultConfig(),
   287  	}
   288  }
   289  
   290  // DependencyList is a slice of ReadyDoneAware implementations that are used by DependableComponent
   291  // to define the list of dependencies that must be ready before starting the component.
   292  type DependencyList struct {
   293  	components []module.ReadyDoneAware
   294  }
   295  
   296  func NewDependencyList(components ...module.ReadyDoneAware) *DependencyList {
   297  	return &DependencyList{
   298  		components: components,
   299  	}
   300  }
   301  
   302  // Add adds a new ReadyDoneAware implementation to the list of dependencies.
   303  func (d *DependencyList) Add(component module.ReadyDoneAware) {
   304  	d.components = append(d.components, component)
   305  }