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 }