github.com/onflow/flow-go@v0.35.7-crescendo-preview.23-atree-inlining/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/onflow/crypto"
    10  	"github.com/prometheus/client_golang/prometheus"
    11  	"github.com/rs/zerolog"
    12  	"github.com/spf13/pflag"
    13  
    14  	"github.com/onflow/flow-go/admin/commands"
    15  	"github.com/onflow/flow-go/config"
    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  	// DhtSystemEnabled configures whether the DHT system is enabled on Access and Execution nodes.
   177  	DhtSystemEnabled bool
   178  
   179  	// BitswapReprovideEnabled configures whether the Bitswap reprovide mechanism is enabled.
   180  	// This is only meaningful to Access and Execution nodes.
   181  	BitswapReprovideEnabled bool
   182  }
   183  
   184  // NodeConfig contains all the derived parameters such the NodeID, private keys etc. and initialized instances of
   185  // structs such as DB, Network etc. The NodeConfig is composed of the BaseConfig and is updated in the
   186  // NodeBuilder functions as a node is bootstrapped.
   187  type NodeConfig struct {
   188  	Cancel context.CancelFunc // cancel function for the context that is passed to the networking layer
   189  	BaseConfig
   190  	Logger            zerolog.Logger
   191  	NodeID            flow.Identifier
   192  	Me                module.Local
   193  	Tracer            module.Tracer
   194  	ConfigManager     *updatable_configs.Manager
   195  	MetricsRegisterer prometheus.Registerer
   196  	Metrics           Metrics
   197  	DB                *badger.DB
   198  	SecretsDB         *badger.DB
   199  	Storage           Storage
   200  	ProtocolEvents    *events.Distributor
   201  	State             protocol.State
   202  	Resolver          madns.BasicResolver
   203  	EngineRegistry    network.EngineRegistry
   204  	NetworkUnderlay   network.Underlay
   205  	ConduitFactory    network.ConduitFactory
   206  	PingService       network.PingService
   207  	MsgValidators     []network.MessageValidator
   208  	FvmOptions        []fvm.Option
   209  	StakingKey        crypto.PrivateKey
   210  	NetworkKey        crypto.PrivateKey
   211  
   212  	// list of dependencies for network peer manager startup
   213  	PeerManagerDependencies *DependencyList
   214  	// ReadyDoneAware implementation of the network middleware for DependableComponents
   215  	networkUnderlayDependable *module.ProxiedReadyDoneAware
   216  
   217  	// ID providers
   218  	IdentityProvider             module.IdentityProvider
   219  	IDTranslator                 p2p.IDTranslator
   220  	SyncEngineIdentifierProvider module.IdentifierProvider
   221  
   222  	// root state information
   223  	RootSnapshot protocol.Snapshot
   224  	// excerpt of root snapshot and latest finalized snapshot, when we boot up
   225  	StateExcerptAtBoot
   226  
   227  	// bootstrapping options
   228  	SkipNwAddressBasedValidations bool
   229  
   230  	// UnicastRateLimiterDistributor notifies consumers when a peer's unicast message is rate limited.
   231  	UnicastRateLimiterDistributor p2p.UnicastRateLimiterDistributor
   232  }
   233  
   234  // StateExcerptAtBoot stores information about the root snapshot and latest finalized block for use in bootstrapping.
   235  type StateExcerptAtBoot struct {
   236  	// properties of RootSnapshot for convenience
   237  	// For node bootstrapped with a root snapshot for the first block of a spork,
   238  	// 		FinalizedRootBlock and SealedRootBlock are the same block (special case of self-sealing block)
   239  	// For node bootstrapped with a root snapshot for a block above the first block of a spork (dynamically bootstrapped),
   240  	// 		FinalizedRootBlock.Height > SealedRootBlock.Height
   241  	FinalizedRootBlock  *flow.Block             // The last finalized block when bootstrapped.
   242  	SealedRootBlock     *flow.Block             // The last sealed block when bootstrapped.
   243  	RootQC              *flow.QuorumCertificate // QC for Finalized Root Block
   244  	RootResult          *flow.ExecutionResult   // Result for SealedRootBlock
   245  	RootSeal            *flow.Seal              // Seal for RootResult
   246  	RootChainID         flow.ChainID
   247  	SporkID             flow.Identifier
   248  	LastFinalizedHeader *flow.Header // last finalized header when the node boots up
   249  }
   250  
   251  func DefaultBaseConfig() *BaseConfig {
   252  	datadir := "/data/protocol"
   253  
   254  	// NOTE: if the codec used in the network component is ever changed any code relying on
   255  	// the message format specific to the codec must be updated. i.e: the AuthorizedSenderValidator.
   256  	codecFactory := func() network.Codec { return cbor.NewCodec() }
   257  
   258  	return &BaseConfig{
   259  		nodeIDHex:        NotSet,
   260  		AdminAddr:        NotSet,
   261  		AdminCert:        NotSet,
   262  		AdminKey:         NotSet,
   263  		AdminClientCAs:   NotSet,
   264  		AdminMaxMsgSize:  grpcutils.DefaultMaxMsgSize,
   265  		BindAddr:         NotSet,
   266  		ObserverMode:     false,
   267  		BootstrapDir:     "bootstrap",
   268  		datadir:          datadir,
   269  		secretsdir:       NotSet,
   270  		secretsDBEnabled: true,
   271  		level:            "info",
   272  		debugLogLimit:    2000,
   273  
   274  		metricsPort:         8080,
   275  		tracerEnabled:       false,
   276  		tracerSensitivity:   4,
   277  		MetricsEnabled:      true,
   278  		receiptsCacheSize:   bstorage.DefaultCacheSize,
   279  		guaranteesCacheSize: bstorage.DefaultCacheSize,
   280  
   281  		profilerConfig: profiler.ProfilerConfig{
   282  			Enabled:         false,
   283  			UploaderEnabled: false,
   284  
   285  			Dir:      "profiler",
   286  			Interval: 15 * time.Minute,
   287  			Duration: 10 * time.Second,
   288  		},
   289  
   290  		HeroCacheMetricsEnable:  false,
   291  		SyncCoreConfig:          chainsync.DefaultConfig(),
   292  		CodecFactory:            codecFactory,
   293  		ComplianceConfig:        compliance.DefaultConfig(),
   294  		DhtSystemEnabled:        true,
   295  		BitswapReprovideEnabled: true,
   296  	}
   297  }
   298  
   299  // DependencyList is a slice of ReadyDoneAware implementations that are used by DependableComponent
   300  // to define the list of dependencies that must be ready before starting the component.
   301  type DependencyList struct {
   302  	components []module.ReadyDoneAware
   303  }
   304  
   305  func NewDependencyList(components ...module.ReadyDoneAware) *DependencyList {
   306  	return &DependencyList{
   307  		components: components,
   308  	}
   309  }
   310  
   311  // Add adds a new ReadyDoneAware implementation to the list of dependencies.
   312  func (d *DependencyList) Add(component module.ReadyDoneAware) {
   313  	d.components = append(d.components, component)
   314  }