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 }