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