Files
cli/cmd/flags/bootstrap_validator.go
2026-01-08 20:36:16 -08:00

114 lines
5.0 KiB
Go

// Copyright (C) 2022-2025, Lux Industries Inc. All rights reserved.
// See the file LICENSE for licensing terms.
package flags
import (
"fmt"
"github.com/luxfi/constants"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
)
const (
bootstrapFilepathFlag = "bootstrap-filepath"
generateNodeIDFlag = "generate-node-id"
bootstrapEndpointsFlag = "bootstrap-endpoints"
numBootstrapValidatorsFlag = "num-bootstrap-validators"
balanceFlag = "balance"
changeOwnerAddressFlag = "change-owner-address"
localBootstrapFlag = "local-bootstrap"
noLocalBootstrapFlag = "no-local-bootstrap"
)
type BootstrapValidatorFlags struct {
BootstrapValidatorsJSONFilePath string
GenerateNodeID bool
BootstrapEndpoints []string
NumBootstrapValidators int
DeployBalanceLUX float64
ChangeOwnerAddress string
LocalBootstrap bool
NoLocalBootstrap bool
}
func validateBootstrapFilepathFlag(cmd *cobra.Command, bootstrapValidatorFlags BootstrapValidatorFlags) error {
if bootstrapValidatorFlags.BootstrapValidatorsJSONFilePath != "" {
if bootstrapValidatorFlags.GenerateNodeID {
return fmt.Errorf("cannot use --generate-node-id=true and a non-empty --bootstrap-filepath at the same time")
}
if cmd.Flags().Changed(numBootstrapValidatorsFlag) {
return fmt.Errorf("cannot use a non-empty --num-bootstrap-validators and a non-empty --bootstrap-filepath at the same time")
}
if cmd.Flags().Changed(balanceFlag) {
return fmt.Errorf("cannot use a non-empty --balance and a non-empty --bootstrap-filepath at the same time")
}
if bootstrapValidatorFlags.BootstrapEndpoints != nil {
return fmt.Errorf("cannot use a non-empty --bootstrap-endpoints and a non-empty --bootstrap-filepath at the same time")
}
}
return nil
}
func validateBootstrapEndpointFlag(cmd *cobra.Command, bootstrapValidatorFlags BootstrapValidatorFlags) error {
if bootstrapValidatorFlags.BootstrapEndpoints != nil {
if bootstrapValidatorFlags.GenerateNodeID {
return fmt.Errorf("cannot use --generate-node-id=true and a non-empty --bootstrap-endpoints at the same time")
}
if cmd.Flags().Changed(numBootstrapValidatorsFlag) {
return fmt.Errorf("cannot use a non-empty --num-bootstrap-validators and a non-empty --bootstrap-endpoints at the same time")
}
}
return nil
}
func validateBootstrapValidatorFlags(cmd *cobra.Command, bootstrapValidatorFlags BootstrapValidatorFlags) error {
if err := validateBootstrapFilepathFlag(cmd, bootstrapValidatorFlags); err != nil {
return err
}
return validateBootstrapEndpointFlag(cmd, bootstrapValidatorFlags)
}
func AddBootstrapValidatorFlagsToCmd(cmd *cobra.Command, bootstrapFlags *BootstrapValidatorFlags) GroupedFlags {
return RegisterFlagGroup(cmd, "Bootstrap Validators Flags", "show-bootstrap-validators-flags", true, func(set *pflag.FlagSet) {
set.StringVar(&bootstrapFlags.BootstrapValidatorsJSONFilePath, bootstrapFilepathFlag, "", "JSON file path that provides details about bootstrap validators")
set.BoolVar(&bootstrapFlags.GenerateNodeID, generateNodeIDFlag, false, "set to true to generate Node IDs for bootstrap validators when none are set up. Use these Node IDs to set up your Lux Nodes.")
set.StringSliceVar(&bootstrapFlags.BootstrapEndpoints, bootstrapEndpointsFlag, nil, "take validator node info from the given endpoints")
set.IntVar(&bootstrapFlags.NumBootstrapValidators, numBootstrapValidatorsFlag, 0, "number of bootstrap validators to set up in sovereign L1 validator")
set.Float64Var(
&bootstrapFlags.DeployBalanceLUX,
balanceFlag,
float64(constants.BootstrapValidatorBalanceNanoLUX)/float64(constants.Lux),
"set the LUX balance of each bootstrap validator that will be used for continuous fee on P-Chain (setting balance=1 equals to 1 LUX for each bootstrap validator)",
)
set.StringVar(&bootstrapFlags.ChangeOwnerAddress, changeOwnerAddressFlag, "", "address that will receive change if node is no longer L1 validator")
set.BoolVar(&bootstrapFlags.LocalBootstrap, localBootstrapFlag, true, "auto-detect running nodes on localhost (ports 9630,9632,9634,9636,9638) as bootstrap validators (default: true)")
set.BoolVar(&bootstrapFlags.NoLocalBootstrap, noLocalBootstrapFlag, false, "disable auto-detection of local bootstrap validators")
bootstrapValidatorPreRun := func(cmd *cobra.Command, _ []string) error {
// Handle --no-local-bootstrap flag overriding --local-bootstrap
if bootstrapFlags.NoLocalBootstrap {
bootstrapFlags.LocalBootstrap = false
}
if err := validateBootstrapValidatorFlags(cmd, *bootstrapFlags); err != nil {
return err
}
if bootstrapFlags.DeployBalanceLUX <= 0 {
return fmt.Errorf("bootstrap validator balance must be greater than 0 LUX")
}
return nil
}
existingPreRunE := cmd.PreRunE
cmd.PreRunE = func(cmd *cobra.Command, args []string) error {
if existingPreRunE != nil {
if err := existingPreRunE(cmd, args); err != nil {
return err
}
}
return bootstrapValidatorPreRun(cmd, args)
}
})
}