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  }