From 63cb85b83f69357d9c72f21a44668c3d05a1e9d7 Mon Sep 17 00:00:00 2001 From: Raymond Sukanto Date: Wed, 11 Sep 2024 10:09:24 -0400 Subject: [PATCH 01/64] prompt addresses --- cmd/blockchaincmd/create.go | 88 ++++++++++++++++++++++++++++++ cmd/blockchaincmd/prompt_owners.go | 33 ++++++++--- pkg/constants/constants.go | 3 + pkg/models/sidecar.go | 6 +- 4 files changed, 119 insertions(+), 11 deletions(-) diff --git a/cmd/blockchaincmd/create.go b/cmd/blockchaincmd/create.go index 842c356c6..79a7ac97f 100644 --- a/cmd/blockchaincmd/create.go +++ b/cmd/blockchaincmd/create.go @@ -49,6 +49,8 @@ type CreateFlags struct { useExternalGasToken bool proofOfStake bool proofOfAuthority bool + tokenMinterAddress []string + validatorManagerController []string } var ( @@ -108,6 +110,8 @@ configuration, pass the -f flag.`, cmd.Flags().BoolVar(&createFlags.useExternalGasToken, "external-gas-token", false, "use a gas token from another blockchain") cmd.Flags().BoolVar(&createFlags.proofOfAuthority, "proof-of-authority", false, "use proof of authority for validator management") cmd.Flags().BoolVar(&createFlags.proofOfStake, "proof-of-stake", false, "use proof of stake for validator management") + cmd.Flags().StringSliceVar(&createFlags.tokenMinterAddress, "token-minter-address", nil, "addresses that may make mint new native tokens") + cmd.Flags().StringSliceVar(&createFlags.validatorManagerController, "validator-manager-controller", nil, "addresses that will control Validator Manager contract") return cmd } @@ -358,6 +362,33 @@ func createBlockchainConfig(cmd *cobra.Command, args []string) error { if err = promptValidatorManagementType(app, sc); err != nil { return err } + if sc.ValidatorManagement == models.ProofOfAuthority { + if createFlags.tokenMinterAddress == nil { + createFlags.tokenMinterAddress, err = getTokenMinterAddr() + if err != nil { + return err + } + } + } + if len(createFlags.tokenMinterAddress) > 0 { + ux.Logger.GreenCheckmarkToUser("Addresses added as new native token minter", createFlags.tokenMinterAddress) + } else { + ux.Logger.GreenCheckmarkToUser("No additional addresses added as new native token minter") + } + sc.NewNativeTokenMinter = createFlags.tokenMinterAddress + if createFlags.validatorManagerController == nil { + var cancelled bool + createFlags.validatorManagerController, cancelled, err = getValidatorContractManagerAddr() + if err != nil { + return err + } + if cancelled { + return fmt.Errorf("user cancelled operation") + } + } + sc.ValidatorManagerController = createFlags.validatorManagerController + //TODO: add description of what Validator Manager Contract controller does + ux.Logger.GreenCheckmarkToUser("Validator Manager Contract controller %s", createFlags.validatorManagerController) if err = app.WriteGenesisFile(blockchainName, genesisBytes); err != nil { return err } @@ -375,6 +406,63 @@ func createBlockchainConfig(cmd *cobra.Command, args []string) error { return nil } +func getValidatorContractManagerAddr() ([]string, bool, error) { + controllerAddrPrompt := "Enter Validator Manager Contract controller address" + for { + // ask in a loop so that if some condition is not met we can keep asking + controlAddr, cancelled, err := getAddrLoop(controllerAddrPrompt, constants.ValidatorManagerController, models.UndefinedNetwork) + if err != nil { + return nil, false, err + } + if cancelled { + return nil, cancelled, nil + } + if len(controlAddr) != 0 { + return controlAddr, false, nil + } + ux.Logger.RedXToUser("An address to control Validator Manage Contract is required before proceeding") + } +} + +// Configure which addresses may make mint new native tokens +func getTokenMinterAddr() ([]string, error) { + addTokenMinterAddrPrompt := "Currently only Validator Manager Contract can mint new native tokens" + ux.Logger.PrintToUser(addTokenMinterAddrPrompt) + yes, err := app.Prompt.CaptureNoYes("Add additional addresses that can mint new native tokens?") + if err != nil { + return nil, err + } + if !yes { + return nil, nil + } + addr, cancelled, err := enterCustomAddr() + if err != nil { + return nil, err + } + if cancelled { + return nil, nil + } + return addr, nil +} + +func enterCustomAddr() ([]string, bool, error) { + addrPrompt := "Enter addresses that can mint new native tokens" + for { + addr, cancelled, err := getAddrLoop(addrPrompt, constants.TokenMinter, models.UndefinedNetwork) + if err != nil { + return nil, false, err + } + if cancelled { + return nil, cancelled, nil + } + //if len(addr) != 0 { + // return addr, false, nil + //} + //ux.Logger.PrintToUser("This tool does not allow to proceed without any control key set") + return addr, false, nil + } +} + func addSubnetEVMGenesisPrefundedAddress(genesisBytes []byte, address string, balance string) ([]byte, error) { var genesisMap map[string]interface{} if err := json.Unmarshal(genesisBytes, &genesisMap); err != nil { diff --git a/cmd/blockchaincmd/prompt_owners.go b/cmd/blockchaincmd/prompt_owners.go index 5233890af..ff97f7a59 100644 --- a/cmd/blockchaincmd/prompt_owners.go +++ b/cmd/blockchaincmd/prompt_owners.go @@ -217,7 +217,7 @@ func enterCustomKeys(network models.Network) ([]string, bool, error) { controlKeysPrompt := "Enter control keys" for { // ask in a loop so that if some condition is not met we can keep asking - controlKeys, cancelled, err := controlKeysLoop(controlKeysPrompt, network) + controlKeys, cancelled, err := getAddrLoop(controlKeysPrompt, constants.ControlKey, network) if err != nil { return nil, false, err } @@ -231,27 +231,42 @@ func enterCustomKeys(network models.Network) ([]string, bool, error) { } } -// controlKeysLoop asks as many controlkeys the user requires, until Done or Cancel is selected -func controlKeysLoop(controlKeysPrompt string, network models.Network) ([]string, bool, error) { - label := "Control key" - info := "Control keys are P-Chain addresses which have admin rights on the subnet.\n" + - "Only private keys which control such addresses are allowed to make changes on the subnet" +// getAddrLoop asks as many addresses the user requires, until Done or Cancel is selected +func getAddrLoop(prompt, label string, network models.Network) ([]string, bool, error) { + info := "" + goal := "" + switch label { + case constants.ControlKey: + info = "Control keys are P-Chain addresses which have admin rights on the subnet.\n" + + "Only private keys which control such addresses are allowed to make changes on the subnet" + goal = "be set as a subnet control key" + case constants.TokenMinter: + goal = "enable as new native token minter" + case constants.ValidatorManagerController: + goal = "enable as controller of ValidatorManager contract" + default: + } customPrompt := "Enter P-Chain address (Example: P-...)" + addressFormat := prompts.PChainFormat + if label != constants.ControlKey { + customPrompt = "Enter address" + addressFormat = prompts.EVMFormat + } return prompts.CaptureListDecision( // we need this to be able to mock test app.Prompt, // the main prompt for entering address keys - controlKeysPrompt, + prompt, // the Capture function to use func(_ string) (string, error) { return prompts.PromptAddress( app.Prompt, - "be set as a subnet control key", + goal, app.GetKeyDir(), app.GetKey, "", network, - prompts.PChainFormat, + addressFormat, customPrompt, ) }, diff --git a/pkg/constants/constants.go b/pkg/constants/constants.go index df1b76fe2..dd127aca2 100644 --- a/pkg/constants/constants.go +++ b/pkg/constants/constants.go @@ -27,6 +27,9 @@ const ( SidecarFileName = "sidecar.json" GenesisFileName = "genesis.json" AliasesFileName = "aliases.json" + ControlKey = "Control key" + TokenMinter = "Native token minter" + ValidatorManagerController = "Validator Manager Controller" SidecarSuffix = SuffixSeparator + SidecarFileName GenesisSuffix = SuffixSeparator + GenesisFileName NodeFileName = "node.json" diff --git a/pkg/models/sidecar.go b/pkg/models/sidecar.go index 63bfc3e49..ff09ed6e6 100644 --- a/pkg/models/sidecar.go +++ b/pkg/models/sidecar.go @@ -38,8 +38,10 @@ type Sidecar struct { TeleporterVersion string RunRelayer bool // SubnetEVM based VM's only - SubnetEVMMainnetChainID uint - ValidatorManagement ValidatorManagementType + SubnetEVMMainnetChainID uint + ValidatorManagement ValidatorManagementType + ValidatorManagerController []string + NewNativeTokenMinter []string } func (sc Sidecar) GetVMID() (string, error) { From 22c18e89ecdd78b94f0b35399e7604c22d59fd94 Mon Sep 17 00:00:00 2001 From: Raymond Sukanto Date: Wed, 11 Sep 2024 10:26:33 -0400 Subject: [PATCH 02/64] fix lint --- cmd/blockchaincmd/create.go | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/cmd/blockchaincmd/create.go b/cmd/blockchaincmd/create.go index 79a7ac97f..50b4628a9 100644 --- a/cmd/blockchaincmd/create.go +++ b/cmd/blockchaincmd/create.go @@ -387,7 +387,7 @@ func createBlockchainConfig(cmd *cobra.Command, args []string) error { } } sc.ValidatorManagerController = createFlags.validatorManagerController - //TODO: add description of what Validator Manager Contract controller does + // TODO: add description of what Validator Manager Contract controller does ux.Logger.GreenCheckmarkToUser("Validator Manager Contract controller %s", createFlags.validatorManagerController) if err = app.WriteGenesisFile(blockchainName, genesisBytes); err != nil { return err @@ -435,7 +435,7 @@ func getTokenMinterAddr() ([]string, error) { if !yes { return nil, nil } - addr, cancelled, err := enterCustomAddr() + addr, cancelled, err := getAddr() if err != nil { return nil, err } @@ -445,7 +445,7 @@ func getTokenMinterAddr() ([]string, error) { return addr, nil } -func enterCustomAddr() ([]string, bool, error) { +func getAddr() ([]string, bool, error) { addrPrompt := "Enter addresses that can mint new native tokens" for { addr, cancelled, err := getAddrLoop(addrPrompt, constants.TokenMinter, models.UndefinedNetwork) @@ -455,10 +455,6 @@ func enterCustomAddr() ([]string, bool, error) { if cancelled { return nil, cancelled, nil } - //if len(addr) != 0 { - // return addr, false, nil - //} - //ux.Logger.PrintToUser("This tool does not allow to proceed without any control key set") return addr, false, nil } } From ff53b0896e9464d4c56eba5b918e1f5c6acb021c Mon Sep 17 00:00:00 2001 From: Raymond Sukanto Date: Wed, 11 Sep 2024 10:35:52 -0400 Subject: [PATCH 03/64] fix lint --- cmd/blockchaincmd/create.go | 1 + 1 file changed, 1 insertion(+) diff --git a/cmd/blockchaincmd/create.go b/cmd/blockchaincmd/create.go index 50b4628a9..2869ac7eb 100644 --- a/cmd/blockchaincmd/create.go +++ b/cmd/blockchaincmd/create.go @@ -406,6 +406,7 @@ func createBlockchainConfig(cmd *cobra.Command, args []string) error { return nil } +// nolint: gocritic func getValidatorContractManagerAddr() ([]string, bool, error) { controllerAddrPrompt := "Enter Validator Manager Contract controller address" for { From 39f17e0ea9d638ec0136504d5bca640a99c65de9 Mon Sep 17 00:00:00 2001 From: Raymond Sukanto Date: Wed, 11 Sep 2024 10:39:59 -0400 Subject: [PATCH 04/64] fix lint --- cmd/blockchaincmd/create.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/blockchaincmd/create.go b/cmd/blockchaincmd/create.go index 2869ac7eb..735660cd3 100644 --- a/cmd/blockchaincmd/create.go +++ b/cmd/blockchaincmd/create.go @@ -406,7 +406,6 @@ func createBlockchainConfig(cmd *cobra.Command, args []string) error { return nil } -// nolint: gocritic func getValidatorContractManagerAddr() ([]string, bool, error) { controllerAddrPrompt := "Enter Validator Manager Contract controller address" for { @@ -446,6 +445,7 @@ func getTokenMinterAddr() ([]string, error) { return addr, nil } +//nolint: gocritic func getAddr() ([]string, bool, error) { addrPrompt := "Enter addresses that can mint new native tokens" for { From aef7fc1a50dcbb60b3998dcff727913b134105c0 Mon Sep 17 00:00:00 2001 From: Raymond Sukanto Date: Wed, 11 Sep 2024 10:59:24 -0400 Subject: [PATCH 05/64] fix lint --- cmd/blockchaincmd/create.go | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/cmd/blockchaincmd/create.go b/cmd/blockchaincmd/create.go index 735660cd3..d441dfc82 100644 --- a/cmd/blockchaincmd/create.go +++ b/cmd/blockchaincmd/create.go @@ -49,6 +49,7 @@ type CreateFlags struct { useExternalGasToken bool proofOfStake bool proofOfAuthority bool + validatorManagerMintOnly bool tokenMinterAddress []string validatorManagerController []string } @@ -110,7 +111,8 @@ configuration, pass the -f flag.`, cmd.Flags().BoolVar(&createFlags.useExternalGasToken, "external-gas-token", false, "use a gas token from another blockchain") cmd.Flags().BoolVar(&createFlags.proofOfAuthority, "proof-of-authority", false, "use proof of authority for validator management") cmd.Flags().BoolVar(&createFlags.proofOfStake, "proof-of-stake", false, "use proof of stake for validator management") - cmd.Flags().StringSliceVar(&createFlags.tokenMinterAddress, "token-minter-address", nil, "addresses that may make mint new native tokens") + cmd.Flags().BoolVar(&createFlags.validatorManagerMintOnly, "validator-manager-mint-only", false, "only enable validator manager contract to mint new native tokens") + cmd.Flags().StringSliceVar(&createFlags.tokenMinterAddress, "token-minter-address", nil, "addresses that can mint new native tokens (for proof of authority validator management only)") cmd.Flags().StringSliceVar(&createFlags.validatorManagerController, "validator-manager-controller", nil, "addresses that will control Validator Manager contract") return cmd } @@ -445,19 +447,16 @@ func getTokenMinterAddr() ([]string, error) { return addr, nil } -//nolint: gocritic func getAddr() ([]string, bool, error) { addrPrompt := "Enter addresses that can mint new native tokens" - for { - addr, cancelled, err := getAddrLoop(addrPrompt, constants.TokenMinter, models.UndefinedNetwork) - if err != nil { - return nil, false, err - } - if cancelled { - return nil, cancelled, nil - } - return addr, false, nil + addr, cancelled, err := getAddrLoop(addrPrompt, constants.TokenMinter, models.UndefinedNetwork) + if err != nil { + return nil, false, err + } + if cancelled { + return nil, cancelled, nil } + return addr, false, nil } func addSubnetEVMGenesisPrefundedAddress(genesisBytes []byte, address string, balance string) ([]byte, error) { From 2866231c3ee83fae3856f2384c61d613ee2f5533 Mon Sep 17 00:00:00 2001 From: Raymond Sukanto Date: Wed, 11 Sep 2024 17:32:38 -0400 Subject: [PATCH 06/64] add flags --- cmd/blockchaincmd/create.go | 27 ++++++++++++++++++++++----- cmd/blockchaincmd/prompt_owners.go | 1 + 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/cmd/blockchaincmd/create.go b/cmd/blockchaincmd/create.go index d441dfc82..760e6edd8 100644 --- a/cmd/blockchaincmd/create.go +++ b/cmd/blockchaincmd/create.go @@ -66,6 +66,8 @@ var ( errMutuallyExlusiveVersionOptions = errors.New("version flags --latest,--pre-release,vm-version are mutually exclusive") errMutuallyExclusiveVMConfigOptions = errors.New("--genesis flag disables --evm-chain-id,--evm-defaults,--production-defaults,--test-defaults") errMutuallyExlusiveValidatorManagementOptions = errors.New("validator management type flags --proof-of-authority,--proof-of-stake are mutually exclusive") + errTokenMinterAddressConflict = errors.New("--validator-manager-mint-only means that no additional addresses can be provided in --token-minter-address") + errTokenMinterAddressForPoS = errors.New("--token-minter-address is only applicable to proof of authority") ) // avalanche blockchain create @@ -203,6 +205,19 @@ func createBlockchainConfig(cmd *cobra.Command, args []string) error { return errMutuallyExlusiveValidatorManagementOptions } + if createFlags.proofOfAuthority { + return errMutuallyExlusiveValidatorManagementOptions + } + + if len(createFlags.tokenMinterAddress) > 0 { + if createFlags.proofOfStake { + return errTokenMinterAddressForPoS + } + if createFlags.validatorManagerMintOnly { + return errTokenMinterAddressConflict + } + } + // get vm kind vmType, err := vm.PromptVMType(app, createFlags.useSubnetEvm, createFlags.useCustomVM) if err != nil { @@ -365,17 +380,19 @@ func createBlockchainConfig(cmd *cobra.Command, args []string) error { return err } if sc.ValidatorManagement == models.ProofOfAuthority { - if createFlags.tokenMinterAddress == nil { + if !createFlags.validatorManagerMintOnly && createFlags.tokenMinterAddress == nil { createFlags.tokenMinterAddress, err = getTokenMinterAddr() if err != nil { return err } } } - if len(createFlags.tokenMinterAddress) > 0 { - ux.Logger.GreenCheckmarkToUser("Addresses added as new native token minter", createFlags.tokenMinterAddress) - } else { - ux.Logger.GreenCheckmarkToUser("No additional addresses added as new native token minter") + if !createFlags.validatorManagerMintOnly { + if len(createFlags.tokenMinterAddress) > 0 { + ux.Logger.GreenCheckmarkToUser("Addresses added as new native token minter %s", createFlags.tokenMinterAddress) + } else { + ux.Logger.GreenCheckmarkToUser("No additional addresses added as new native token minter") + } } sc.NewNativeTokenMinter = createFlags.tokenMinterAddress if createFlags.validatorManagerController == nil { diff --git a/cmd/blockchaincmd/prompt_owners.go b/cmd/blockchaincmd/prompt_owners.go index ff97f7a59..a5c87a905 100644 --- a/cmd/blockchaincmd/prompt_owners.go +++ b/cmd/blockchaincmd/prompt_owners.go @@ -232,6 +232,7 @@ func enterCustomKeys(network models.Network) ([]string, bool, error) { } // getAddrLoop asks as many addresses the user requires, until Done or Cancel is selected +// TODO: add info for TokenMinter and ValidatorManagerController func getAddrLoop(prompt, label string, network models.Network) ([]string, bool, error) { info := "" goal := "" From 6fd7726150f971bc40702b4b718e7f7f1271307f Mon Sep 17 00:00:00 2001 From: Felipe Madero Date: Wed, 11 Sep 2024 21:22:20 -0300 Subject: [PATCH 07/64] adding teleporter contract to genesis --- cmd/blockchaincmd/create.go | 1 + pkg/vm/create_evm.go | 54 +++++++++++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+) diff --git a/cmd/blockchaincmd/create.go b/cmd/blockchaincmd/create.go index 07ee0835d..30bcbbe40 100644 --- a/cmd/blockchaincmd/create.go +++ b/cmd/blockchaincmd/create.go @@ -276,6 +276,7 @@ func createBlockchainConfig(cmd *cobra.Command, args []string) error { deployTeleporter = params.UseTeleporter useExternalGasToken = params.UseExternalGasToken genesisBytes, err = vm.CreateEVMGenesis( + app, blockchainName, params, teleporterInfo, diff --git a/pkg/vm/create_evm.go b/pkg/vm/create_evm.go index 1d8f3ea05..ef7d44d11 100644 --- a/pkg/vm/create_evm.go +++ b/pkg/vm/create_evm.go @@ -4,10 +4,12 @@ package vm import ( "bytes" + "encoding/hex" "encoding/json" "errors" "fmt" "math/big" + "strings" "time" "github.com/ava-labs/avalanche-cli/pkg/application" @@ -16,6 +18,7 @@ import ( "github.com/ava-labs/avalanche-cli/pkg/teleporter" "github.com/ava-labs/avalanche-cli/pkg/ux" "github.com/ava-labs/subnet-evm/core" + "github.com/ava-labs/subnet-evm/core/types" subnetevmparams "github.com/ava-labs/subnet-evm/params" "github.com/ava-labs/subnet-evm/utils" "github.com/ethereum/go-ethereum/common" @@ -72,6 +75,7 @@ func CreateEvmSidecar( } func CreateEVMGenesis( + app *application.Avalanche, blockchainName string, params SubnetEVMGenesisParams, teleporterInfo *teleporter.Info, @@ -111,6 +115,28 @@ func CreateEVMGenesis( params.initialTokenAllocation[common.HexToAddress(teleporterInfo.FundedAddress)] = core.GenesisAccount{ Balance: balance, } + messengerContractAddress, deployedMessengerString, messengerDeployerAddress, err := getTeleporterMessengerParamsForGenesis( + app, + "v1.0.0", + ) + if err != nil { + return nil, err + } + deployedMessengerBytes := common.FromHex(deployedMessengerString) + storage := map[common.Hash]common.Hash{ + common.HexToHash("0x0"): common.HexToHash("0x1"), + common.HexToHash("0x1"): common.HexToHash("0x1"), + } + params.initialTokenAllocation[common.HexToAddress(messengerContractAddress)] = core.GenesisAccount{ + Balance: big.NewInt(0), + Code: deployedMessengerBytes, + Storage: storage, + Nonce: 1, + } + params.initialTokenAllocation[common.HexToAddress(messengerDeployerAddress)] = core.GenesisAccount{ + Balance: big.NewInt(0), + Nonce: 1, + } } if params.UseExternalGasToken { @@ -168,3 +194,31 @@ func someAllowedHasBalance(allowList AllowList, allocations core.GenesisAlloc) b } return false } + +func getTeleporterMessengerParamsForGenesis( + app *application.Avalanche, + teleporterVersion string, +) (string, string, string, error) { + td := teleporter.Deployer{} + messengerContractAddress, messengerDeployerAddress, messengerDeployerTxString, registryBytecode, err := td.GetAssets( + app.GetTeleporterBinDir(), + teleporterVersion, + ) + if err != nil { + return "", "", "", err + } + messengerDeployerTxBytes, err := hex.DecodeString(strings.TrimPrefix(messengerDeployerTxString, "0x")) + if err != nil { + return "", "", "", err + } + messengerDeployerTx := types.NewTx(&types.LegacyTx{}) + if err := messengerDeployerTx.UnmarshalBinary(messengerDeployerTxBytes); err != nil { + return "", "", "", err + } + messengerBytes := messengerDeployerTx.Data() + deployedMessengerBytes := messengerBytes[:19] + deployedMessengerBytes = append(deployedMessengerBytes, messengerBytes[19+41:]...) + deployedMessengerString := "0x" + hex.EncodeToString(deployedMessengerBytes) + _ = registryBytecode + return messengerContractAddress, deployedMessengerString, messengerDeployerAddress, nil +} From 4295956ba75b27e66ca439d08a1f2d04ef7f3dff Mon Sep 17 00:00:00 2001 From: Raymond Sukanto Date: Thu, 12 Sep 2024 15:16:57 -0400 Subject: [PATCH 08/64] validator prompt --- cmd/blockchaincmd/create.go | 39 +++++++++++++++++++++---------------- pkg/constants/constants.go | 13 +++++++------ pkg/prompts/prompts.go | 29 +++++++++++++++++++++++++++ pkg/prompts/validations.go | 11 +++++++++++ 4 files changed, 69 insertions(+), 23 deletions(-) diff --git a/cmd/blockchaincmd/create.go b/cmd/blockchaincmd/create.go index 760e6edd8..f2f306384 100644 --- a/cmd/blockchaincmd/create.go +++ b/cmd/blockchaincmd/create.go @@ -35,23 +35,24 @@ const ( ) type CreateFlags struct { - useSubnetEvm bool - useCustomVM bool - chainID uint64 - tokenSymbol string - useTestDefaults bool - useProductionDefaults bool - useWarp bool - useTeleporter bool - vmVersion string - useLatestReleasedVMVersion bool - useLatestPreReleasedVMVersion bool - useExternalGasToken bool - proofOfStake bool - proofOfAuthority bool - validatorManagerMintOnly bool - tokenMinterAddress []string - validatorManagerController []string + useSubnetEvm bool + useCustomVM bool + chainID uint64 + tokenSymbol string + useTestDefaults bool + useProductionDefaults bool + useWarp bool + useTeleporter bool + vmVersion string + useLatestReleasedVMVersion bool + useLatestPreReleasedVMVersion bool + useExternalGasToken bool + proofOfStake bool + proofOfAuthority bool + validatorManagerMintOnly bool + tokenMinterAddress []string + validatorManagerController []string + bootstrapValidatorInitialBalance []int } var ( @@ -116,6 +117,7 @@ configuration, pass the -f flag.`, cmd.Flags().BoolVar(&createFlags.validatorManagerMintOnly, "validator-manager-mint-only", false, "only enable validator manager contract to mint new native tokens") cmd.Flags().StringSliceVar(&createFlags.tokenMinterAddress, "token-minter-address", nil, "addresses that can mint new native tokens (for proof of authority validator management only)") cmd.Flags().StringSliceVar(&createFlags.validatorManagerController, "validator-manager-controller", nil, "addresses that will control Validator Manager contract") + cmd.Flags().IntSliceVar(&createFlags.bootstrapValidatorInitialBalance, "bootstrap-validators-balanche", []int{}, "starting P-Chain balance of each bootstrap validator (minimum of 5 AVAX)") return cmd } @@ -412,6 +414,9 @@ func createBlockchainConfig(cmd *cobra.Command, args []string) error { return err } + if createFlags.bootstrapValidatorInitialBalance == nil { + + } if err = app.CreateSidecar(sc); err != nil { return err } diff --git a/pkg/constants/constants.go b/pkg/constants/constants.go index dd127aca2..16bbb81df 100644 --- a/pkg/constants/constants.go +++ b/pkg/constants/constants.go @@ -154,12 +154,13 @@ const ( Disable = "disable" - TimeParseLayout = "2006-01-02 15:04:05" - MinStakeWeight = 1 - DefaultStakeWeight = 20 - AVAXSymbol = "AVAX" - DefaultFujiStakeDuration = "48h" - DefaultMainnetStakeDuration = "336h" + TimeParseLayout = "2006-01-02 15:04:05" + MinStakeWeight = 1 + MinInitialBalanceBootstrapValidator = 5 + DefaultStakeWeight = 20 + AVAXSymbol = "AVAX" + DefaultFujiStakeDuration = "48h" + DefaultMainnetStakeDuration = "336h" // The absolute minimum is 25 seconds, but set to 1 minute to allow for // time to go through the command DevnetStakingStartLeadTime = 30 * time.Second diff --git a/pkg/prompts/prompts.go b/pkg/prompts/prompts.go index 9ec6248d1..1a96374e8 100644 --- a/pkg/prompts/prompts.go +++ b/pkg/prompts/prompts.go @@ -483,6 +483,35 @@ func (*realPrompter) CaptureAddresses(promptStr string) ([]common.Address, error return addresses, nil } +func (*realPrompter) CaptureInitialBalances(promptStr string, minBalance int) ([]int, error) { + addressesStr := "" + validated := false + for !validated { + var err error + addressesStr, err = utils.ReadLongString(promptui.IconGood + " " + promptStr + " ") + if err != nil { + return nil, err + } + if err := validateAddresses(addressesStr); err != nil { + fmt.Println(err) + } else { + validated = true + } + } + + prompt := promptui.Prompt{ + Label: promptStr, + Validate: validateBootstrapBalance, + } + + addressStr, err := prompt.Run() + if err != nil { + return common.Address{}, err + } + initialBalances, err := strings.Split(addressesStr, ","), + return addresses, nil +} + func (*realPrompter) CaptureExistingFilepath(promptStr string) (string, error) { prompt := promptui.Prompt{ Label: promptStr, diff --git a/pkg/prompts/validations.go b/pkg/prompts/validations.go index 416b036d3..b901a9b03 100644 --- a/pkg/prompts/validations.go +++ b/pkg/prompts/validations.go @@ -129,6 +129,17 @@ func validateWeight(input string) error { return nil } +func validateBootstrapBalance(input string) error { + val, err := strconv.ParseUint(input, 10, 64) + if err != nil { + return err + } + if val < constants.MinInitialBalanceBootstrapValidator { + return fmt.Errorf("initial bootstrap validator balance must be at least %d", constants.MinInitialBalanceBootstrapValidator) + } + return nil +} + func validateBiggerThanZero(input string) error { val, err := strconv.ParseUint(input, 0, 64) if err != nil { From ee79685b3b75b6450ca823a2e6ad9e5fdbf7c8ec Mon Sep 17 00:00:00 2001 From: Raymond Sukanto Date: Thu, 12 Sep 2024 17:59:29 -0400 Subject: [PATCH 09/64] bootstrap validators --- cmd/blockchaincmd/create.go | 33 +++++++++++++++++++++++++--- pkg/prompts/prompts.go | 44 ++++++++++++++++++------------------- pkg/prompts/validations.go | 2 +- 3 files changed, 53 insertions(+), 26 deletions(-) diff --git a/cmd/blockchaincmd/create.go b/cmd/blockchaincmd/create.go index f2f306384..7a2892cae 100644 --- a/cmd/blockchaincmd/create.go +++ b/cmd/blockchaincmd/create.go @@ -117,7 +117,7 @@ configuration, pass the -f flag.`, cmd.Flags().BoolVar(&createFlags.validatorManagerMintOnly, "validator-manager-mint-only", false, "only enable validator manager contract to mint new native tokens") cmd.Flags().StringSliceVar(&createFlags.tokenMinterAddress, "token-minter-address", nil, "addresses that can mint new native tokens (for proof of authority validator management only)") cmd.Flags().StringSliceVar(&createFlags.validatorManagerController, "validator-manager-controller", nil, "addresses that will control Validator Manager contract") - cmd.Flags().IntSliceVar(&createFlags.bootstrapValidatorInitialBalance, "bootstrap-validators-balanche", []int{}, "starting P-Chain balance of each bootstrap validator (minimum of 5 AVAX)") + cmd.Flags().IntSliceVar(&createFlags.bootstrapValidatorInitialBalance, "bootstrap-validators-balance", []int{}, "starting P-Chain balance of each bootstrap validator (minimum of 5 AVAX)") return cmd } @@ -220,6 +220,14 @@ func createBlockchainConfig(cmd *cobra.Command, args []string) error { } } + if len(createFlags.bootstrapValidatorInitialBalance) > 0 { + for _, balance := range createFlags.bootstrapValidatorInitialBalance { + if balance < constants.MinInitialBalanceBootstrapValidator { + return fmt.Errorf("initial bootstrap validator balance must be at least %d AVAX", constants.MinInitialBalanceBootstrapValidator) + } + } + } + // get vm kind vmType, err := vm.PromptVMType(app, createFlags.useSubnetEvm, createFlags.useCustomVM) if err != nil { @@ -414,9 +422,16 @@ func createBlockchainConfig(cmd *cobra.Command, args []string) error { return err } - if createFlags.bootstrapValidatorInitialBalance == nil { - + if len(createFlags.bootstrapValidatorInitialBalance) == 0 { + createFlags.bootstrapValidatorInitialBalance, err = promptValidatorInitialBalance() + if err != nil { + return err + } } + + ux.Logger.GreenCheckmarkToUser("Number of initial bootstrap validators %d", len(createFlags.bootstrapValidatorInitialBalance)) + ux.Logger.GreenCheckmarkToUser("Initial bootstrap validator balances %d", createFlags.bootstrapValidatorInitialBalance) + if err = app.CreateSidecar(sc); err != nil { return err } @@ -542,6 +557,18 @@ func checkInvalidSubnetNames(name string) error { } return nil } +func promptValidatorInitialBalance() ([]int, error) { + numBootstrapValidators, err := app.Prompt.CaptureInt( + "How many bootstrap validators to set up?", + ) + if err != nil { + return nil, err + } + return app.Prompt.CaptureInitialBalances( + "What are the initial balances of the bootstrap validators (use comma separated values e.g. 5,5)?", + numBootstrapValidators, + ) +} // TODO: add explain the difference for different validator management type func promptValidatorManagementType( diff --git a/pkg/prompts/prompts.go b/pkg/prompts/prompts.go index 1a96374e8..91b2540e0 100644 --- a/pkg/prompts/prompts.go +++ b/pkg/prompts/prompts.go @@ -114,6 +114,7 @@ type Prompter interface { CaptureXChainAddress(promptStr string, network models.Network) (string, error) CaptureFutureDate(promptStr string, minDate time.Time) (time.Time, error) ChooseKeyOrLedger(goal string) (bool, error) + CaptureInitialBalances(promptStr string, numValidators int) ([]int, error) } type realPrompter struct{} @@ -483,33 +484,32 @@ func (*realPrompter) CaptureAddresses(promptStr string) ([]common.Address, error return addresses, nil } -func (*realPrompter) CaptureInitialBalances(promptStr string, minBalance int) ([]int, error) { - addressesStr := "" - validated := false - for !validated { - var err error - addressesStr, err = utils.ReadLongString(promptui.IconGood + " " + promptStr + " ") - if err != nil { - return nil, err - } - if err := validateAddresses(addressesStr); err != nil { - fmt.Println(err) - } else { - validated = true - } - } - +func (*realPrompter) CaptureInitialBalances(promptStr string, numValidators int) ([]int, error) { prompt := promptui.Prompt{ - Label: promptStr, - Validate: validateBootstrapBalance, + Label: promptStr, } - addressStr, err := prompt.Run() + balanceStr, err := prompt.Run() if err != nil { - return common.Address{}, err + return nil, err } - initialBalances, err := strings.Split(addressesStr, ","), - return addresses, nil + + initialBalances := strings.Split(balanceStr, ",") + if len(initialBalances) != numValidators { + return nil, fmt.Errorf("number of initial balances provided does not match number of bootstrap validators") + } + validatorBalances := []int{} + for _, balance := range initialBalances { + if err = validateBootstrapBalance(balance); err != nil { + return nil, err + } + balanceInt, err := strconv.Atoi(balance) + if err != nil { + return nil, err + } + validatorBalances = append(validatorBalances, balanceInt) + } + return validatorBalances, nil } func (*realPrompter) CaptureExistingFilepath(promptStr string) (string, error) { diff --git a/pkg/prompts/validations.go b/pkg/prompts/validations.go index b901a9b03..48438851b 100644 --- a/pkg/prompts/validations.go +++ b/pkg/prompts/validations.go @@ -135,7 +135,7 @@ func validateBootstrapBalance(input string) error { return err } if val < constants.MinInitialBalanceBootstrapValidator { - return fmt.Errorf("initial bootstrap validator balance must be at least %d", constants.MinInitialBalanceBootstrapValidator) + return fmt.Errorf("initial bootstrap validator balance must be at least %d AVAX", constants.MinInitialBalanceBootstrapValidator) } return nil } From f586cb639dbf6c1fc123bdb6a3500e36d28c1de2 Mon Sep 17 00:00:00 2001 From: Raymond Sukanto Date: Thu, 12 Sep 2024 18:52:08 -0400 Subject: [PATCH 10/64] add mock --- internal/mocks/prompter.go | 181 +++++++------------------------------ 1 file changed, 35 insertions(+), 146 deletions(-) diff --git a/internal/mocks/prompter.go b/internal/mocks/prompter.go index 0d38e7b05..6cb81ac1c 100644 --- a/internal/mocks/prompter.go +++ b/internal/mocks/prompter.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.1. DO NOT EDIT. +// Code generated by mockery v2.26.1. DO NOT EDIT. package mocks @@ -28,10 +28,6 @@ type Prompter struct { func (_m *Prompter) CaptureAddress(promptStr string) (common.Address, error) { ret := _m.Called(promptStr) - if len(ret) == 0 { - panic("no return value specified for CaptureAddress") - } - var r0 common.Address var r1 error if rf, ok := ret.Get(0).(func(string) (common.Address, error)); ok { @@ -58,10 +54,6 @@ func (_m *Prompter) CaptureAddress(promptStr string) (common.Address, error) { func (_m *Prompter) CaptureAddresses(promptStr string) ([]common.Address, error) { ret := _m.Called(promptStr) - if len(ret) == 0 { - panic("no return value specified for CaptureList") - } - var r0 []common.Address var r1 error if rf, ok := ret.Get(0).(func(string) ([]common.Address, error)); ok { @@ -70,7 +62,9 @@ func (_m *Prompter) CaptureAddresses(promptStr string) ([]common.Address, error) if rf, ok := ret.Get(0).(func(string) []common.Address); ok { r0 = rf(promptStr) } else { - r0 = ret.Get(0).([]common.Address) + if ret.Get(0) != nil { + r0 = ret.Get(0).([]common.Address) + } } if rf, ok := ret.Get(1).(func(string) error); ok { @@ -86,10 +80,6 @@ func (_m *Prompter) CaptureAddresses(promptStr string) ([]common.Address, error) func (_m *Prompter) CaptureDate(promptStr string) (time.Time, error) { ret := _m.Called(promptStr) - if len(ret) == 0 { - panic("no return value specified for CaptureDate") - } - var r0 time.Time var r1 error if rf, ok := ret.Get(0).(func(string) (time.Time, error)); ok { @@ -114,10 +104,6 @@ func (_m *Prompter) CaptureDate(promptStr string) (time.Time, error) { func (_m *Prompter) CaptureEmail(promptStr string) (string, error) { ret := _m.Called(promptStr) - if len(ret) == 0 { - panic("no return value specified for CaptureEmail") - } - var r0 string var r1 error if rf, ok := ret.Get(0).(func(string) (string, error)); ok { @@ -142,10 +128,6 @@ func (_m *Prompter) CaptureEmail(promptStr string) (string, error) { func (_m *Prompter) CaptureExistingFilepath(promptStr string) (string, error) { ret := _m.Called(promptStr) - if len(ret) == 0 { - panic("no return value specified for CaptureExistingFilepath") - } - var r0 string var r1 error if rf, ok := ret.Get(0).(func(string) (string, error)); ok { @@ -170,10 +152,6 @@ func (_m *Prompter) CaptureExistingFilepath(promptStr string) (string, error) { func (_m *Prompter) CaptureFloat(promptStr string, validator func(float64) error) (float64, error) { ret := _m.Called(promptStr, validator) - if len(ret) == 0 { - panic("no return value specified for CaptureFloat") - } - var r0 float64 var r1 error if rf, ok := ret.Get(0).(func(string, func(float64) error) (float64, error)); ok { @@ -198,10 +176,6 @@ func (_m *Prompter) CaptureFloat(promptStr string, validator func(float64) error func (_m *Prompter) CaptureFujiDuration(promptStr string) (time.Duration, error) { ret := _m.Called(promptStr) - if len(ret) == 0 { - panic("no return value specified for CaptureFujiDuration") - } - var r0 time.Duration var r1 error if rf, ok := ret.Get(0).(func(string) (time.Duration, error)); ok { @@ -226,10 +200,6 @@ func (_m *Prompter) CaptureFujiDuration(promptStr string) (time.Duration, error) func (_m *Prompter) CaptureFutureDate(promptStr string, minDate time.Time) (time.Time, error) { ret := _m.Called(promptStr, minDate) - if len(ret) == 0 { - panic("no return value specified for CaptureFutureDate") - } - var r0 time.Time var r1 error if rf, ok := ret.Get(0).(func(string, time.Time) (time.Time, error)); ok { @@ -254,10 +224,6 @@ func (_m *Prompter) CaptureFutureDate(promptStr string, minDate time.Time) (time func (_m *Prompter) CaptureGitURL(promptStr string) (*url.URL, error) { ret := _m.Called(promptStr) - if len(ret) == 0 { - panic("no return value specified for CaptureGitURL") - } - var r0 *url.URL var r1 error if rf, ok := ret.Get(0).(func(string) (*url.URL, error)); ok { @@ -284,10 +250,6 @@ func (_m *Prompter) CaptureGitURL(promptStr string) (*url.URL, error) { func (_m *Prompter) CaptureID(promptStr string) (ids.ID, error) { ret := _m.Called(promptStr) - if len(ret) == 0 { - panic("no return value specified for CaptureID") - } - var r0 ids.ID var r1 error if rf, ok := ret.Get(0).(func(string) (ids.ID, error)); ok { @@ -314,10 +276,6 @@ func (_m *Prompter) CaptureID(promptStr string) (ids.ID, error) { func (_m *Prompter) CaptureIndex(promptStr string, options []interface{}) (int, error) { ret := _m.Called(promptStr, options) - if len(ret) == 0 { - panic("no return value specified for CaptureIndex") - } - var r0 int var r1 error if rf, ok := ret.Get(0).(func(string, []interface{}) (int, error)); ok { @@ -338,14 +296,36 @@ func (_m *Prompter) CaptureIndex(promptStr string, options []interface{}) (int, return r0, r1 } +// CaptureInitialBalances provides a mock function with given fields: promptStr, numValidators +func (_m *Prompter) CaptureInitialBalances(promptStr string, numValidators int) ([]int, error) { + ret := _m.Called(promptStr, numValidators) + + var r0 []int + var r1 error + if rf, ok := ret.Get(0).(func(string, int) ([]int, error)); ok { + return rf(promptStr, numValidators) + } + if rf, ok := ret.Get(0).(func(string, int) []int); ok { + r0 = rf(promptStr, numValidators) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]int) + } + } + + if rf, ok := ret.Get(1).(func(string, int) error); ok { + r1 = rf(promptStr, numValidators) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + // CaptureInt provides a mock function with given fields: promptStr func (_m *Prompter) CaptureInt(promptStr string) (int, error) { ret := _m.Called(promptStr) - if len(ret) == 0 { - panic("no return value specified for CaptureInt") - } - var r0 int var r1 error if rf, ok := ret.Get(0).(func(string) (int, error)); ok { @@ -370,10 +350,6 @@ func (_m *Prompter) CaptureInt(promptStr string) (int, error) { func (_m *Prompter) CaptureList(promptStr string, options []string) (string, error) { ret := _m.Called(promptStr, options) - if len(ret) == 0 { - panic("no return value specified for CaptureList") - } - var r0 string var r1 error if rf, ok := ret.Get(0).(func(string, []string) (string, error)); ok { @@ -398,10 +374,6 @@ func (_m *Prompter) CaptureList(promptStr string, options []string) (string, err func (_m *Prompter) CaptureListWithSize(promptStr string, options []string, size int) (string, error) { ret := _m.Called(promptStr, options, size) - if len(ret) == 0 { - panic("no return value specified for CaptureListWithSize") - } - var r0 string var r1 error if rf, ok := ret.Get(0).(func(string, []string, int) (string, error)); ok { @@ -426,10 +398,6 @@ func (_m *Prompter) CaptureListWithSize(promptStr string, options []string, size func (_m *Prompter) CaptureMainnetDuration(promptStr string) (time.Duration, error) { ret := _m.Called(promptStr) - if len(ret) == 0 { - panic("no return value specified for CaptureMainnetDuration") - } - var r0 time.Duration var r1 error if rf, ok := ret.Get(0).(func(string) (time.Duration, error)); ok { @@ -454,10 +422,6 @@ func (_m *Prompter) CaptureMainnetDuration(promptStr string) (time.Duration, err func (_m *Prompter) CaptureNewFilepath(promptStr string) (string, error) { ret := _m.Called(promptStr) - if len(ret) == 0 { - panic("no return value specified for CaptureNewFilepath") - } - var r0 string var r1 error if rf, ok := ret.Get(0).(func(string) (string, error)); ok { @@ -482,10 +446,6 @@ func (_m *Prompter) CaptureNewFilepath(promptStr string) (string, error) { func (_m *Prompter) CaptureNoYes(promptStr string) (bool, error) { ret := _m.Called(promptStr) - if len(ret) == 0 { - panic("no return value specified for CaptureNoYes") - } - var r0 bool var r1 error if rf, ok := ret.Get(0).(func(string) (bool, error)); ok { @@ -510,10 +470,6 @@ func (_m *Prompter) CaptureNoYes(promptStr string) (bool, error) { func (_m *Prompter) CaptureNodeID(promptStr string) (ids.NodeID, error) { ret := _m.Called(promptStr) - if len(ret) == 0 { - panic("no return value specified for CaptureNodeID") - } - var r0 ids.NodeID var r1 error if rf, ok := ret.Get(0).(func(string) (ids.NodeID, error)); ok { @@ -540,10 +496,6 @@ func (_m *Prompter) CaptureNodeID(promptStr string) (ids.NodeID, error) { func (_m *Prompter) CapturePChainAddress(promptStr string, network models.Network) (string, error) { ret := _m.Called(promptStr, network) - if len(ret) == 0 { - panic("no return value specified for CapturePChainAddress") - } - var r0 string var r1 error if rf, ok := ret.Get(0).(func(string, models.Network) (string, error)); ok { @@ -568,10 +520,6 @@ func (_m *Prompter) CapturePChainAddress(promptStr string, network models.Networ func (_m *Prompter) CapturePositiveBigInt(promptStr string) (*big.Int, error) { ret := _m.Called(promptStr) - if len(ret) == 0 { - panic("no return value specified for CapturePositiveBigInt") - } - var r0 *big.Int var r1 error if rf, ok := ret.Get(0).(func(string) (*big.Int, error)); ok { @@ -598,10 +546,6 @@ func (_m *Prompter) CapturePositiveBigInt(promptStr string) (*big.Int, error) { func (_m *Prompter) CapturePositiveInt(promptStr string, comparators []prompts.Comparator) (int, error) { ret := _m.Called(promptStr, comparators) - if len(ret) == 0 { - panic("no return value specified for CapturePositiveInt") - } - var r0 int var r1 error if rf, ok := ret.Get(0).(func(string, []prompts.Comparator) (int, error)); ok { @@ -626,10 +570,6 @@ func (_m *Prompter) CapturePositiveInt(promptStr string, comparators []prompts.C func (_m *Prompter) CaptureRepoBranch(promptStr string, repo string) (string, error) { ret := _m.Called(promptStr, repo) - if len(ret) == 0 { - panic("no return value specified for CaptureRepoBranch") - } - var r0 string var r1 error if rf, ok := ret.Get(0).(func(string, string) (string, error)); ok { @@ -654,10 +594,6 @@ func (_m *Prompter) CaptureRepoBranch(promptStr string, repo string) (string, er func (_m *Prompter) CaptureRepoFile(promptStr string, repo string, branch string) (string, error) { ret := _m.Called(promptStr, repo, branch) - if len(ret) == 0 { - panic("no return value specified for CaptureRepoFile") - } - var r0 string var r1 error if rf, ok := ret.Get(0).(func(string, string, string) (string, error)); ok { @@ -682,10 +618,6 @@ func (_m *Prompter) CaptureRepoFile(promptStr string, repo string, branch string func (_m *Prompter) CaptureString(promptStr string) (string, error) { ret := _m.Called(promptStr) - if len(ret) == 0 { - panic("no return value specified for CaptureString") - } - var r0 string var r1 error if rf, ok := ret.Get(0).(func(string) (string, error)); ok { @@ -710,10 +642,6 @@ func (_m *Prompter) CaptureString(promptStr string) (string, error) { func (_m *Prompter) CaptureStringAllowEmpty(promptStr string) (string, error) { ret := _m.Called(promptStr) - if len(ret) == 0 { - panic("no return value specified for CaptureStringAllowEmpty") - } - var r0 string var r1 error if rf, ok := ret.Get(0).(func(string) (string, error)); ok { @@ -738,10 +666,6 @@ func (_m *Prompter) CaptureStringAllowEmpty(promptStr string) (string, error) { func (_m *Prompter) CaptureURL(promptStr string, validateConnection bool) (string, error) { ret := _m.Called(promptStr, validateConnection) - if len(ret) == 0 { - panic("no return value specified for CaptureURL") - } - var r0 string var r1 error if rf, ok := ret.Get(0).(func(string, bool) (string, error)); ok { @@ -766,10 +690,6 @@ func (_m *Prompter) CaptureURL(promptStr string, validateConnection bool) (strin func (_m *Prompter) CaptureUint32(promptStr string) (uint32, error) { ret := _m.Called(promptStr) - if len(ret) == 0 { - panic("no return value specified for CaptureUint32") - } - var r0 uint32 var r1 error if rf, ok := ret.Get(0).(func(string) (uint32, error)); ok { @@ -794,10 +714,6 @@ func (_m *Prompter) CaptureUint32(promptStr string) (uint32, error) { func (_m *Prompter) CaptureUint64(promptStr string) (uint64, error) { ret := _m.Called(promptStr) - if len(ret) == 0 { - panic("no return value specified for CaptureUint64") - } - var r0 uint64 var r1 error if rf, ok := ret.Get(0).(func(string) (uint64, error)); ok { @@ -822,10 +738,6 @@ func (_m *Prompter) CaptureUint64(promptStr string) (uint64, error) { func (_m *Prompter) CaptureUint64Compare(promptStr string, comparators []prompts.Comparator) (uint64, error) { ret := _m.Called(promptStr, comparators) - if len(ret) == 0 { - panic("no return value specified for CaptureUint64Compare") - } - var r0 uint64 var r1 error if rf, ok := ret.Get(0).(func(string, []prompts.Comparator) (uint64, error)); ok { @@ -850,10 +762,6 @@ func (_m *Prompter) CaptureUint64Compare(promptStr string, comparators []prompts func (_m *Prompter) CaptureValidatedString(promptStr string, validator func(string) error) (string, error) { ret := _m.Called(promptStr, validator) - if len(ret) == 0 { - panic("no return value specified for CaptureValidatedString") - } - var r0 string var r1 error if rf, ok := ret.Get(0).(func(string, func(string) error) (string, error)); ok { @@ -878,10 +786,6 @@ func (_m *Prompter) CaptureValidatedString(promptStr string, validator func(stri func (_m *Prompter) CaptureVersion(promptStr string) (string, error) { ret := _m.Called(promptStr) - if len(ret) == 0 { - panic("no return value specified for CaptureVersion") - } - var r0 string var r1 error if rf, ok := ret.Get(0).(func(string) (string, error)); ok { @@ -906,10 +810,6 @@ func (_m *Prompter) CaptureVersion(promptStr string) (string, error) { func (_m *Prompter) CaptureWeight(promptStr string) (uint64, error) { ret := _m.Called(promptStr) - if len(ret) == 0 { - panic("no return value specified for CaptureWeight") - } - var r0 uint64 var r1 error if rf, ok := ret.Get(0).(func(string) (uint64, error)); ok { @@ -934,10 +834,6 @@ func (_m *Prompter) CaptureWeight(promptStr string) (uint64, error) { func (_m *Prompter) CaptureXChainAddress(promptStr string, network models.Network) (string, error) { ret := _m.Called(promptStr, network) - if len(ret) == 0 { - panic("no return value specified for CaptureXChainAddress") - } - var r0 string var r1 error if rf, ok := ret.Get(0).(func(string, models.Network) (string, error)); ok { @@ -962,10 +858,6 @@ func (_m *Prompter) CaptureXChainAddress(promptStr string, network models.Networ func (_m *Prompter) CaptureYesNo(promptStr string) (bool, error) { ret := _m.Called(promptStr) - if len(ret) == 0 { - panic("no return value specified for CaptureYesNo") - } - var r0 bool var r1 error if rf, ok := ret.Get(0).(func(string) (bool, error)); ok { @@ -990,10 +882,6 @@ func (_m *Prompter) CaptureYesNo(promptStr string) (bool, error) { func (_m *Prompter) ChooseKeyOrLedger(goal string) (bool, error) { ret := _m.Called(goal) - if len(ret) == 0 { - panic("no return value specified for ChooseKeyOrLedger") - } - var r0 bool var r1 error if rf, ok := ret.Get(0).(func(string) (bool, error)); ok { @@ -1014,12 +902,13 @@ func (_m *Prompter) ChooseKeyOrLedger(goal string) (bool, error) { return r0, r1 } -// NewPrompter creates a new instance of Prompter. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -// The first argument is typically a *testing.T value. -func NewPrompter(t interface { +type mockConstructorTestingTNewPrompter interface { mock.TestingT Cleanup(func()) -}) *Prompter { +} + +// NewPrompter creates a new instance of Prompter. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +func NewPrompter(t mockConstructorTestingTNewPrompter) *Prompter { mock := &Prompter{} mock.Mock.Test(t) From d15757ccc64d8174ed2fcefc66d004a3ba093278 Mon Sep 17 00:00:00 2001 From: Raymond Sukanto Date: Thu, 12 Sep 2024 18:54:56 -0400 Subject: [PATCH 11/64] fix lint --- cmd/blockchaincmd/create.go | 1 + 1 file changed, 1 insertion(+) diff --git a/cmd/blockchaincmd/create.go b/cmd/blockchaincmd/create.go index 7a2892cae..0112187e6 100644 --- a/cmd/blockchaincmd/create.go +++ b/cmd/blockchaincmd/create.go @@ -557,6 +557,7 @@ func checkInvalidSubnetNames(name string) error { } return nil } + func promptValidatorInitialBalance() ([]int, error) { numBootstrapValidators, err := app.Prompt.CaptureInt( "How many bootstrap validators to set up?", From 059519d154a309090c0ba538d2de566cfb870c4a Mon Sep 17 00:00:00 2001 From: Raymond Sukanto Date: Fri, 13 Sep 2024 19:00:43 -0400 Subject: [PATCH 12/64] update prompt validator --- cmd/blockchaincmd/create.go | 91 +++++++++++++++++++++++++++++++++++++ 1 file changed, 91 insertions(+) diff --git a/cmd/blockchaincmd/create.go b/cmd/blockchaincmd/create.go index 0112187e6..31db2a631 100644 --- a/cmd/blockchaincmd/create.go +++ b/cmd/blockchaincmd/create.go @@ -6,6 +6,9 @@ import ( "encoding/json" "errors" "fmt" + "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/vms/platformvm/fx" + "github.com/ava-labs/avalanchego/vms/platformvm/signer" "os" "sort" "strconv" @@ -558,6 +561,94 @@ func checkInvalidSubnetNames(name string) error { return nil } +// TODO: replace this object with avalanchego struct SubnetValidator +type SubnetValidator struct { + // Must be Ed25519 NodeID + NodeID ids.NodeID + // Weight of this validator used when sampling + Weight uint64 + // Initial balance for this validator + Balance uint64 + // [Signer] is the BLS key for this validator. + // Note: We do not enforce that the BLS key is unique across all validators. + // This means that validators can share a key if they so choose. + // However, a NodeID + Subnet does uniquely map to a BLS key + Signer signer.Signer + // Leftover $AVAX from the [Balance] will be issued to this + // owner once it is removed from the validator set. + ChangeOwner fx.Owner +} + +func PromptWeightPrimaryNetwork(network models.Network) (uint64, error) { + defaultStake := network.GenesisParams().MinValidatorStake + defaultWeight := fmt.Sprintf("Default (%s)", convertNanoAvaxToAvaxString(defaultStake)) + txt := "What stake weight would you like to assign to the validator?" + weightOptions := []string{defaultWeight, "Custom"} + weightOption, err := app.Prompt.CaptureList(txt, weightOptions) + if err != nil { + return 0, err + } + + switch weightOption { + case defaultWeight: + return defaultStake, nil + default: + return app.Prompt.CaptureWeight(txt) + } +} + +func promptValidators() ([]int, error) { + subnetValidators := []SubnetValidator{} + numBootstrapValidators, err := app.Prompt.CaptureInt( + "How many bootstrap validators to set up?", + ) + for len(subnetValidators) < numBootstrapValidators { + nodeID, err := PromptNodeID() + if err != nil { + return err + } + weight, err := PromptWeightPrimaryNetwork(network) + if err != nil { + return err + } + balance, err := PromptBalance() + if err != nil { + return err + } + jsonPop, err := promptProofOfPossession() + if err != nil { + return err + } + popBytes, err := json.Marshal(jsonPop) + if err != nil { + return err + } + var proofOfPossession signer.Signer + pop := &signer.ProofOfPossession{} + err := pop.UnmarshalJSON(popBytes) + if err != nil { + return ids.Empty, err + } + proofOfPossession = pop + changeAddr, err := PromptChangeAddr() + if err != nil { + return err + } + subnetValidator := SubnetValidator{ + NodeID: nodeID, + Weight: weight, + Balance: balance, + Signer: proofOfPossession, + ChangeOwner: changeAddr, + } + subnetValidators = append(subnetValidators, subnetValidator) + } + if err != nil { + return nil, err + } + +} + func promptValidatorInitialBalance() ([]int, error) { numBootstrapValidators, err := app.Prompt.CaptureInt( "How many bootstrap validators to set up?", From 4809209e4611ae5f19ceddb894c2402cc1224fc1 Mon Sep 17 00:00:00 2001 From: Raymond Sukanto Date: Fri, 13 Sep 2024 19:02:42 -0400 Subject: [PATCH 13/64] update prompt validator --- cmd/blockchaincmd/create.go | 60 +++++++++++++------------------------ 1 file changed, 21 insertions(+), 39 deletions(-) diff --git a/cmd/blockchaincmd/create.go b/cmd/blockchaincmd/create.go index 31db2a631..7a832701e 100644 --- a/cmd/blockchaincmd/create.go +++ b/cmd/blockchaincmd/create.go @@ -38,24 +38,24 @@ const ( ) type CreateFlags struct { - useSubnetEvm bool - useCustomVM bool - chainID uint64 - tokenSymbol string - useTestDefaults bool - useProductionDefaults bool - useWarp bool - useTeleporter bool - vmVersion string - useLatestReleasedVMVersion bool - useLatestPreReleasedVMVersion bool - useExternalGasToken bool - proofOfStake bool - proofOfAuthority bool - validatorManagerMintOnly bool - tokenMinterAddress []string - validatorManagerController []string - bootstrapValidatorInitialBalance []int + useSubnetEvm bool + useCustomVM bool + chainID uint64 + tokenSymbol string + useTestDefaults bool + useProductionDefaults bool + useWarp bool + useTeleporter bool + vmVersion string + useLatestReleasedVMVersion bool + useLatestPreReleasedVMVersion bool + useExternalGasToken bool + proofOfStake bool + proofOfAuthority bool + validatorManagerMintOnly bool + tokenMinterAddress []string + validatorManagerController []string + bootstrapValidators []SubnetValidator } var ( @@ -120,7 +120,6 @@ configuration, pass the -f flag.`, cmd.Flags().BoolVar(&createFlags.validatorManagerMintOnly, "validator-manager-mint-only", false, "only enable validator manager contract to mint new native tokens") cmd.Flags().StringSliceVar(&createFlags.tokenMinterAddress, "token-minter-address", nil, "addresses that can mint new native tokens (for proof of authority validator management only)") cmd.Flags().StringSliceVar(&createFlags.validatorManagerController, "validator-manager-controller", nil, "addresses that will control Validator Manager contract") - cmd.Flags().IntSliceVar(&createFlags.bootstrapValidatorInitialBalance, "bootstrap-validators-balance", []int{}, "starting P-Chain balance of each bootstrap validator (minimum of 5 AVAX)") return cmd } @@ -425,12 +424,8 @@ func createBlockchainConfig(cmd *cobra.Command, args []string) error { return err } - if len(createFlags.bootstrapValidatorInitialBalance) == 0 { - createFlags.bootstrapValidatorInitialBalance, err = promptValidatorInitialBalance() - if err != nil { - return err - } - } + subnetValidators, err := promptValidators() + //TODO: update subnetvalidators in sidecar ux.Logger.GreenCheckmarkToUser("Number of initial bootstrap validators %d", len(createFlags.bootstrapValidatorInitialBalance)) ux.Logger.GreenCheckmarkToUser("Initial bootstrap validator balances %d", createFlags.bootstrapValidatorInitialBalance) @@ -597,7 +592,7 @@ func PromptWeightPrimaryNetwork(network models.Network) (uint64, error) { } } -func promptValidators() ([]int, error) { +func promptValidators() ([]SubnetValidator, error) { subnetValidators := []SubnetValidator{} numBootstrapValidators, err := app.Prompt.CaptureInt( "How many bootstrap validators to set up?", @@ -649,19 +644,6 @@ func promptValidators() ([]int, error) { } -func promptValidatorInitialBalance() ([]int, error) { - numBootstrapValidators, err := app.Prompt.CaptureInt( - "How many bootstrap validators to set up?", - ) - if err != nil { - return nil, err - } - return app.Prompt.CaptureInitialBalances( - "What are the initial balances of the bootstrap validators (use comma separated values e.g. 5,5)?", - numBootstrapValidators, - ) -} - // TODO: add explain the difference for different validator management type func promptValidatorManagementType( app *application.Avalanche, From 606c4fc58516167ee5dde159914bcf183ed68e40 Mon Sep 17 00:00:00 2001 From: Felipe Madero Date: Mon, 16 Sep 2024 11:52:12 -0400 Subject: [PATCH 14/64] fixes for icm on genesis --- cmd/blockchaincmd/deploy.go | 3 ++- cmd/teleportercmd/deploy.go | 2 ++ pkg/subnet/local.go | 11 +++++++---- pkg/teleporter/teleporter.go | 30 +++++++++++++++--------------- 4 files changed, 26 insertions(+), 20 deletions(-) diff --git a/cmd/blockchaincmd/deploy.go b/cmd/blockchaincmd/deploy.go index e892db32d..9b89088b1 100644 --- a/cmd/blockchaincmd/deploy.go +++ b/cmd/blockchaincmd/deploy.go @@ -96,7 +96,8 @@ so you can take your locally tested Subnet and deploy it on Fuji or Mainnet.`, cmd.Flags().BoolVar(&icmSpec.SkipICMDeploy, "skip-local-teleporter", false, "skip automatic teleporter deploy on local networks [to be deprecated]") cmd.Flags().BoolVar(&icmSpec.SkipICMDeploy, "skip-teleporter-deploy", false, "skip automatic teleporter deploy") cmd.Flags().BoolVar(&icmSpec.SkipRelayerDeploy, "skip-relayer", false, "skip relayer deploy") - cmd.Flags().StringVar(&icmSpec.Version, "teleporter-version", "latest", "teleporter version to deploy") + cmd.Flags().StringVar(&icmSpec.ICMVersion, "teleporter-version", "latest", "teleporter version to deploy") + cmd.Flags().StringVar(&icmSpec.RelayerVersion, "relayer-version", "latest", "relayer version to deploy") cmd.Flags().StringVar(&icmSpec.MessengerContractAddressPath, "teleporter-messenger-contract-address-path", "", "path to an interchain messenger contract address file") cmd.Flags().StringVar(&icmSpec.MessengerDeployerAddressPath, "teleporter-messenger-deployer-address-path", "", "path to an interchain messenger deployer address file") cmd.Flags().StringVar(&icmSpec.MessengerDeployerTxPath, "teleporter-messenger-deployer-tx-path", "", "path to an interchain messenger deployer tx file") diff --git a/cmd/teleportercmd/deploy.go b/cmd/teleportercmd/deploy.go index fef0f1061..e9b516860 100644 --- a/cmd/teleportercmd/deploy.go +++ b/cmd/teleportercmd/deploy.go @@ -188,6 +188,7 @@ func CallDeploy(_ []string, flags DeployFlags) error { privateKey, flags.DeployMessenger, flags.DeployRegistry, + false, ) if err != nil { return err @@ -224,6 +225,7 @@ func CallDeploy(_ []string, flags DeployFlags) error { ewoq.PrivKeyHex(), flags.DeployMessenger, flags.DeployRegistry, + false, ) if err != nil { return err diff --git a/pkg/subnet/local.go b/pkg/subnet/local.go index cd6efa2af..18b87fab6 100644 --- a/pkg/subnet/local.go +++ b/pkg/subnet/local.go @@ -81,11 +81,12 @@ type setDefaultSnapshotFunc func(string, bool, string, bool) (bool, error) type ICMSpec struct { SkipICMDeploy bool SkipRelayerDeploy bool - Version string + ICMVersion string MessengerContractAddressPath string MessengerDeployerAddressPath string MessengerDeployerTxPath string RegistryBydecodePath string + RelayerVersion string } type DeployInfo struct { @@ -384,8 +385,8 @@ func (d *LocalDeployer) doDeploy(chain string, genesisPath string, icmSpec ICMSp } else { icmVersion := "" switch { - case icmSpec.Version != "" && icmSpec.Version != "latest": - icmVersion = icmSpec.Version + case icmSpec.ICMVersion != "" && icmSpec.ICMVersion != "latest": + icmVersion = icmSpec.ICMVersion case sc.TeleporterVersion != "": icmVersion = sc.TeleporterVersion default: @@ -412,6 +413,7 @@ func (d *LocalDeployer) doDeploy(chain string, genesisPath string, icmSpec ICMSp cChainKey.PrivKeyHex(), true, true, + false, ) if err != nil { return nil, err @@ -448,6 +450,7 @@ func (d *LocalDeployer) doDeploy(chain string, genesisPath string, icmSpec ICMSp blockchainKey.PrivKeyHex(), true, true, + true, ) if err != nil { return nil, err @@ -502,7 +505,7 @@ func (d *LocalDeployer) doDeploy(chain string, genesisPath string, icmSpec ICMSp ux.Logger.PrintToUser("") // start relayer if err := teleporter.DeployRelayer( - "latest", + icmSpec.RelayerVersion, d.app.GetAWMRelayerBinDir(), relayerConfigPath, d.app.GetLocalRelayerLogPath(models.Local), diff --git a/pkg/teleporter/teleporter.go b/pkg/teleporter/teleporter.go index 05f5ab288..c4d73481b 100644 --- a/pkg/teleporter/teleporter.go +++ b/pkg/teleporter/teleporter.go @@ -240,6 +240,7 @@ func (t *Deployer) Deploy( privateKey string, deployMessenger bool, deployRegistry bool, + forceRegistryDeploy bool, ) (bool, string, string, error) { var ( messengerAddress string @@ -255,7 +256,7 @@ func (t *Deployer) Deploy( ) } if err == nil && deployRegistry { - if !deployMessenger || !alreadyDeployed { + if !deployMessenger || !alreadyDeployed || forceRegistryDeploy { registryAddress, err = t.DeployRegistry(subnetName, rpcURL, privateKey) } } @@ -404,24 +405,23 @@ func DeployAndFundRelayer( privKeyStr, true, true, + true, ) if err != nil { return false, "", "", err } - if !alreadyDeployed { - // get relayer address - relayerAddress, _, err := GetRelayerKeyInfo(app.GetKeyPath(constants.AWMRelayerKeyName)) - if err != nil { - return false, "", "", err - } - // fund relayer - if err := FundRelayer( - endpoint, - privKeyStr, - relayerAddress, - ); err != nil { - return false, "", "", err - } + // get relayer address + relayerAddress, _, err := GetRelayerKeyInfo(app.GetKeyPath(constants.AWMRelayerKeyName)) + if err != nil { + return false, "", "", err + } + // fund relayer + if err := FundRelayer( + endpoint, + privKeyStr, + relayerAddress, + ); err != nil { + return false, "", "", err } return alreadyDeployed, messengerAddress, registryAddress, err } From 29966df3b9007951924771f77b4348b46534f470 Mon Sep 17 00:00:00 2001 From: Felipe Madero Date: Mon, 16 Sep 2024 13:11:25 -0400 Subject: [PATCH 15/64] add icm from a given embedded file --- pkg/vm/create_evm.go | 54 +------------------------- pkg/vm/deployed_messenger_bytecode.txt | 1 + pkg/vm/deployed_registry_bytecode.txt | 1 + pkg/vm/icm.go | 40 +++++++++++++++++++ 4 files changed, 43 insertions(+), 53 deletions(-) create mode 100644 pkg/vm/deployed_messenger_bytecode.txt create mode 100644 pkg/vm/deployed_registry_bytecode.txt create mode 100644 pkg/vm/icm.go diff --git a/pkg/vm/create_evm.go b/pkg/vm/create_evm.go index ef7d44d11..5b62a7760 100644 --- a/pkg/vm/create_evm.go +++ b/pkg/vm/create_evm.go @@ -4,12 +4,10 @@ package vm import ( "bytes" - "encoding/hex" "encoding/json" "errors" "fmt" "math/big" - "strings" "time" "github.com/ava-labs/avalanche-cli/pkg/application" @@ -18,7 +16,6 @@ import ( "github.com/ava-labs/avalanche-cli/pkg/teleporter" "github.com/ava-labs/avalanche-cli/pkg/ux" "github.com/ava-labs/subnet-evm/core" - "github.com/ava-labs/subnet-evm/core/types" subnetevmparams "github.com/ava-labs/subnet-evm/params" "github.com/ava-labs/subnet-evm/utils" "github.com/ethereum/go-ethereum/common" @@ -115,28 +112,7 @@ func CreateEVMGenesis( params.initialTokenAllocation[common.HexToAddress(teleporterInfo.FundedAddress)] = core.GenesisAccount{ Balance: balance, } - messengerContractAddress, deployedMessengerString, messengerDeployerAddress, err := getTeleporterMessengerParamsForGenesis( - app, - "v1.0.0", - ) - if err != nil { - return nil, err - } - deployedMessengerBytes := common.FromHex(deployedMessengerString) - storage := map[common.Hash]common.Hash{ - common.HexToHash("0x0"): common.HexToHash("0x1"), - common.HexToHash("0x1"): common.HexToHash("0x1"), - } - params.initialTokenAllocation[common.HexToAddress(messengerContractAddress)] = core.GenesisAccount{ - Balance: big.NewInt(0), - Code: deployedMessengerBytes, - Storage: storage, - Nonce: 1, - } - params.initialTokenAllocation[common.HexToAddress(messengerDeployerAddress)] = core.GenesisAccount{ - Balance: big.NewInt(0), - Nonce: 1, - } + addICMContractToGenesisAllocations(params.initialTokenAllocation) } if params.UseExternalGasToken { @@ -194,31 +170,3 @@ func someAllowedHasBalance(allowList AllowList, allocations core.GenesisAlloc) b } return false } - -func getTeleporterMessengerParamsForGenesis( - app *application.Avalanche, - teleporterVersion string, -) (string, string, string, error) { - td := teleporter.Deployer{} - messengerContractAddress, messengerDeployerAddress, messengerDeployerTxString, registryBytecode, err := td.GetAssets( - app.GetTeleporterBinDir(), - teleporterVersion, - ) - if err != nil { - return "", "", "", err - } - messengerDeployerTxBytes, err := hex.DecodeString(strings.TrimPrefix(messengerDeployerTxString, "0x")) - if err != nil { - return "", "", "", err - } - messengerDeployerTx := types.NewTx(&types.LegacyTx{}) - if err := messengerDeployerTx.UnmarshalBinary(messengerDeployerTxBytes); err != nil { - return "", "", "", err - } - messengerBytes := messengerDeployerTx.Data() - deployedMessengerBytes := messengerBytes[:19] - deployedMessengerBytes = append(deployedMessengerBytes, messengerBytes[19+41:]...) - deployedMessengerString := "0x" + hex.EncodeToString(deployedMessengerBytes) - _ = registryBytecode - return messengerContractAddress, deployedMessengerString, messengerDeployerAddress, nil -} diff --git a/pkg/vm/deployed_messenger_bytecode.txt b/pkg/vm/deployed_messenger_bytecode.txt new file mode 100644 index 000000000..aa3ae3c6c --- /dev/null +++ b/pkg/vm/deployed_messenger_bytecode.txt @@ -0,0 +1 @@ +0x608060405234801561001057600080fd5b506004361061014d5760003560e01c8063a8898181116100c3578063df20e8bc1161007c578063df20e8bc1461033b578063e69d606a1461034e578063e6e67bd5146103b6578063ebc3b1ba146103f2578063ecc7042814610415578063fc2d61971461041e57600080fd5b8063a8898181146102b2578063a9a85614146102c5578063b771b3bc146102d8578063c473eef8146102e6578063ccb5f8091461031f578063d127dc9b1461033257600080fd5b8063399b77da11610115578063399b77da1461021957806362448850146102395780638245a1b01461024c578063860a3b061461025f578063892bf4121461027f5780638ac0fd041461029f57600080fd5b80630af5b4ff1461015257806322296c3a1461016d5780632bc8b0bf146101825780632ca40f55146101955780632e27c223146101ee575b600080fd5b61015a610431565b6040519081526020015b60405180910390f35b61018061017b366004612251565b610503565b005b61015a61019036600461226e565b6105f8565b6101e06101a336600461226e565b6005602090815260009182526040918290208054835180850190945260018201546001600160a01b03168452600290910154918301919091529082565b604051610164929190612287565b6102016101fc36600461226e565b610615565b6040516001600160a01b039091168152602001610164565b61015a61022736600461226e565b60009081526005602052604090205490565b61015a6102473660046122ae565b61069e565b61018061025a366004612301565b6106fc565b61015a61026d36600461226e565b60066020526000908152604090205481565b61029261028d366004612335565b6108a7565b6040516101649190612357565b6101806102ad366004612377565b6108da565b61015a6102c03660046123af565b610b19565b61015a6102d3366004612426565b610b5c565b6102016005600160991b0181565b61015a6102f43660046124be565b6001600160a01b03918216600090815260096020908152604080832093909416825291909152205490565b61018061032d3660046124f7565b610e03565b61015a60025481565b61015a61034936600461226e565b61123d565b61039761035c36600461226e565b600090815260056020908152604091829020825180840190935260018101546001600160a01b03168084526002909101549290910182905291565b604080516001600160a01b039093168352602083019190915201610164565b6103dd6103c436600461226e565b6004602052600090815260409020805460019091015482565b60408051928352602083019190915201610164565b61040561040036600461226e565b611286565b6040519015158152602001610164565b61015a60035481565b61018061042c36600461251e565b61129c565b600254600090806104fe576005600160991b016001600160a01b0316634213cf786040518163ffffffff1660e01b8152600401602060405180830381865afa158015610481573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104a59190612564565b9050806104cd5760405162461bcd60e51b81526004016104c49061257d565b60405180910390fd5b600281905560405181907f1eac640109dc937d2a9f42735a05f794b39a5e3759d681951d671aabbce4b10490600090a25b919050565b3360009081526009602090815260408083206001600160a01b0385168452909152902054806105855760405162461bcd60e51b815260206004820152602860248201527f54656c65706f727465724d657373656e6765723a206e6f2072657761726420746044820152676f2072656465656d60c01b60648201526084016104c4565b3360008181526009602090815260408083206001600160a01b03871680855290835281842093909355518481529192917f3294c84e5b0f29d9803655319087207bc94f4db29f7927846944822773780b88910160405180910390a36105f46001600160a01b03831633836114f7565b5050565b600081815260046020526040812061060f9061155f565b92915050565b6000818152600760205260408120546106825760405162461bcd60e51b815260206004820152602960248201527f54656c65706f727465724d657373656e6765723a206d657373616765206e6f74604482015268081c9958d95a5d995960ba1b60648201526084016104c4565b506000908152600860205260409020546001600160a01b031690565b60006001600054146106c25760405162461bcd60e51b81526004016104c4906125c4565b60026000556106f16106d383612804565b833560009081526004602052604090206106ec90611572565b61167c565b600160005592915050565b60016000541461071e5760405162461bcd60e51b81526004016104c4906125c4565b6002600081815590546107379060408401358435610b19565b6000818152600560209081526040918290208251808401845281548152835180850190945260018201546001600160a01b03168452600290910154838301529081019190915280519192509061079f5760405162461bcd60e51b81526004016104c4906128a7565b6000836040516020016107b29190612b42565b60408051601f19818403018152919052825181516020830120919250146107eb5760405162461bcd60e51b81526004016104c490612b55565b8360400135837f2a211ad4a59ab9d003852404f9c57c690704ee755f3c79d2c2812ad32da99df8868560200151604051610826929190612b9e565b60405180910390a360405163ee5b48eb60e01b81526005600160991b019063ee5b48eb90610858908490600401612c23565b6020604051808303816000875af1158015610877573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061089b9190612564565b50506001600055505050565b604080518082019091526000808252602082015260008381526004602052604090206108d390836118bc565b9392505050565b6001600054146108fc5760405162461bcd60e51b81526004016104c4906125c4565b600260005560018054146109225760405162461bcd60e51b81526004016104c490612c36565b60026001558061098c5760405162461bcd60e51b815260206004820152602f60248201527f54656c65706f727465724d657373656e6765723a207a65726f2061646469746960448201526e1bdb985b0819995948185b5bdd5b9d608a1b60648201526084016104c4565b6001600160a01b0382166109b25760405162461bcd60e51b81526004016104c490612c7b565b6000838152600560205260409020546109dd5760405162461bcd60e51b81526004016104c4906128a7565b6000838152600560205260409020600101546001600160a01b03838116911614610a6f5760405162461bcd60e51b815260206004820152603760248201527f54656c65706f727465724d657373656e6765723a20696e76616c69642066656560448201527f20617373657420636f6e7472616374206164647265737300000000000000000060648201526084016104c4565b6000610a7b8383611981565b600085815260056020526040812060020180549293508392909190610aa1908490612ce5565b909155505060008481526005602052604090819020905185917fc1bfd1f1208927dfbd414041dcb5256e6c9ad90dd61aec3249facbd34ff7b3e191610b03916001019081546001600160a01b0316815260019190910154602082015260400190565b60405180910390a2505060018080556000555050565b60408051306020820152908101849052606081018390526080810182905260009060a0016040516020818303038152906040528051906020012090509392505050565b6000600160005414610b805760405162461bcd60e51b81526004016104c4906125c4565b60026000818155905490866001600160401b03811115610ba257610ba2612607565b604051908082528060200260200182016040528015610be757816020015b6040805180820190915260008082526020820152815260200190600190039081610bc05790505b5090508660005b81811015610d6c5760008a8a83818110610c0a57610c0a612cf8565b90506020020135905060006007600083815260200190815260200160002054905080600003610c8a5760405162461bcd60e51b815260206004820152602660248201527f54656c65706f727465724d657373656e6765723a2072656365697074206e6f7460448201526508199bdd5b9960d21b60648201526084016104c4565b610c958d8783610b19565b8214610d095760405162461bcd60e51b815260206004820152603a60248201527f54656c65706f727465724d657373656e6765723a206d6573736167652049442060448201527f6e6f742066726f6d20736f7572636520626c6f636b636861696e00000000000060648201526084016104c4565b6000828152600860209081526040918290205482518084019093528383526001600160a01b03169082018190528651909190879086908110610d4d57610d4d612cf8565b602002602001018190525050505080610d6590612d0e565b9050610bee565b506040805160c0810182528b815260006020820152610df0918101610d96368b90038b018b612d27565b8152602001600081526020018888808060200260200160405190810160405280939291908181526020018383602002808284376000920182905250938552505060408051928352602080840190915290920152508361167c565b60016000559a9950505050505050505050565b6001805414610e245760405162461bcd60e51b81526004016104c490612c36565b60026001556040516306f8253560e41b815263ffffffff8316600482015260009081906005600160991b0190636f82535090602401600060405180830381865afa158015610e76573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610e9e9190810190612da3565b9150915080610f015760405162461bcd60e51b815260206004820152602960248201527f54656c65706f727465724d657373656e6765723a20696e76616c69642077617260448201526870206d65737361676560b81b60648201526084016104c4565b60208201516001600160a01b03163014610f785760405162461bcd60e51b815260206004820152603260248201527f54656c65706f727465724d657373656e6765723a20696e76616c6964206f726960448201527167696e2073656e646572206164647265737360701b60648201526084016104c4565b60008260400151806020019051810190610f929190612f40565b90506000610f9e610431565b90508082604001511461100d5760405162461bcd60e51b815260206004820152603160248201527f54656c65706f727465724d657373656e6765723a20696e76616c6964206465736044820152701d1a5b985d1a5bdb8818da185a5b881251607a1b60648201526084016104c4565b8351825160009161101f918490610b19565b600081815260076020526040902054909150156110945760405162461bcd60e51b815260206004820152602d60248201527f54656c65706f727465724d657373656e6765723a206d65737361676520616c7260448201526c1958591e481c9958d95a5d9959609a1b60648201526084016104c4565b6110a2338460a00151611ae9565b6111005760405162461bcd60e51b815260206004820152602960248201527f54656c65706f727465724d657373656e6765723a20756e617574686f72697a6560448201526832103932b630bcb2b960b91b60648201526084016104c4565b61110e818460000151611b61565b6001600160a01b0386161561114557600081815260086020526040902080546001600160a01b0319166001600160a01b0388161790555b60c08301515160005b81811015611192576111828488600001518760c00151848151811061117557611175612cf8565b6020026020010151611bd3565b61118b81612d0e565b905061114e565b50604080518082018252855181526001600160a01b038916602080830191909152885160009081526004909152919091206111cc91611cfb565b336001600160a01b03168660000151837f292ee90bbaf70b5d4936025e09d56ba08f3e421156b6a568cf3c2840d9343e348a8860405161120d929190613150565b60405180910390a460e0840151511561122f5761122f82876000015186611d57565b505060018055505050505050565b600254600090806112605760405162461bcd60e51b81526004016104c49061257d565b600060035460016112719190612ce5565b905061127e828583610b19565b949350505050565b600081815260076020526040812054151561060f565b60018054146112bd5760405162461bcd60e51b81526004016104c490612c36565b60026001819055546000906112d59084908435610b19565b600081815260066020526040902054909150806113045760405162461bcd60e51b81526004016104c4906128a7565b80836040516020016113169190612b42565b60405160208183030381529060405280519060200120146113495760405162461bcd60e51b81526004016104c490612b55565b600061135b6080850160608601612251565b6001600160a01b03163b116113cf5760405162461bcd60e51b815260206004820152603460248201527f54656c65706f727465724d657373656e6765723a2064657374696e6174696f6e604482015273206164647265737320686173206e6f20636f646560601b60648201526084016104c4565b604051849083907f34795cc6b122b9a0ae684946319f1e14a577b4e8f9b3dda9ac94c21a54d3188c90600090a360008281526006602090815260408083208390558691611420918701908701612251565b61142d60e0870187613174565b60405160240161144094939291906131ba565b60408051601f198184030181529190526020810180516001600160e01b031663643477d560e11b179052905060006114886114816080870160608801612251565b5a84611e8a565b9050806114eb5760405162461bcd60e51b815260206004820152602b60248201527f54656c65706f727465724d657373656e6765723a20726574727920657865637560448201526a1d1a5bdb8819985a5b195960aa1b60648201526084016104c4565b50506001805550505050565b6040516001600160a01b03831660248201526044810182905261155a90849063a9059cbb60e01b906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152611ea4565b505050565b8054600182015460009161060f916131e5565b6060600061158960056115848561155f565b611f76565b9050806000036115d85760408051600080825260208201909252906115d0565b60408051808201909152600080825260208201528152602001906001900390816115a95790505b509392505050565b6000816001600160401b038111156115f2576115f2612607565b60405190808252806020026020018201604052801561163757816020015b60408051808201909152600080825260208201528152602001906001900390816116105790505b50905060005b828110156115d05761164e85611f8c565b82828151811061166057611660612cf8565b60200260200101819052508061167590612d0e565b905061163d565b600080611687610431565b9050600060036000815461169a90612d0e565b919050819055905060006116b383876000015184610b19565b90506000604051806101000160405280848152602001336001600160a01b031681526020018860000151815260200188602001516001600160a01b0316815260200188606001518152602001886080015181526020018781526020018860a00151815250905060008160405160200161172c91906131f8565b60405160208183030381529060405290506000808960400151602001511115611794576040890151516001600160a01b031661177a5760405162461bcd60e51b81526004016104c490612c7b565b604089015180516020909101516117919190611981565b90505b6040805180820182528a820151516001600160a01b039081168252602080830185905283518085018552865187830120815280820184815260008a815260058452869020915182555180516001830180546001600160a01b03191691909516179093559101516002909101558a51915190919086907f2a211ad4a59ab9d003852404f9c57c690704ee755f3c79d2c2812ad32da99df890611838908890869061320b565b60405180910390a360405163ee5b48eb60e01b81526005600160991b019063ee5b48eb9061186a908690600401612c23565b6020604051808303816000875af1158015611889573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118ad9190612564565b50939998505050505050505050565b60408051808201909152600080825260208201526118d98361155f565b82106119315760405162461bcd60e51b815260206004820152602160248201527f5265636569707451756575653a20696e646578206f7574206f6620626f756e646044820152607360f81b60648201526084016104c4565b8260020160008385600001546119479190612ce5565b81526020808201929092526040908101600020815180830190925280548252600101546001600160a01b0316918101919091529392505050565b6040516370a0823160e01b815230600482015260009081906001600160a01b038516906370a0823190602401602060405180830381865afa1580156119ca573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119ee9190612564565b9050611a056001600160a01b038516333086612058565b6040516370a0823160e01b81523060048201526000906001600160a01b038616906370a0823190602401602060405180830381865afa158015611a4c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a709190612564565b9050818111611ad65760405162461bcd60e51b815260206004820152602c60248201527f5361666545524332305472616e7366657246726f6d3a2062616c616e6365206e60448201526b1bdd081a5b98dc99585cd95960a21b60648201526084016104c4565b611ae082826131e5565b95945050505050565b60008151600003611afc5750600161060f565b815160005b81811015611b5657846001600160a01b0316848281518110611b2557611b25612cf8565b60200260200101516001600160a01b031603611b465760019250505061060f565b611b4f81612d0e565b9050611b01565b506000949350505050565b80600003611bc15760405162461bcd60e51b815260206004820152602760248201527f54656c65706f727465724d657373656e6765723a207a65726f206d657373616760448201526665206e6f6e636560c81b60648201526084016104c4565b60009182526007602052604090912055565b6000611be484848460000151610b19565b6000818152600560209081526040918290208251808401845281548152835180850190945260018201546001600160a01b031684526002909101548383015290810191909152805191925090611c3b575050505050565b60008281526005602090815260408083208381556001810180546001600160a01b03191690556002018390558382018051830151878401516001600160a01b0390811686526009855283862092515116855292528220805491929091611ca2908490612ce5565b9250508190555082602001516001600160a01b031684837fd13a7935f29af029349bed0a2097455b91fd06190a30478c575db3f31e00bf578460200151604051611cec919061321e565b60405180910390a45050505050565b6001820180548291600285019160009182611d1583612d0e565b90915550815260208082019290925260400160002082518155910151600190910180546001600160a01b0319166001600160a01b039092169190911790555050565b80608001515a1015611db95760405162461bcd60e51b815260206004820152602560248201527f54656c65706f727465724d657373656e6765723a20696e73756666696369656e604482015264742067617360d81b60648201526084016104c4565b80606001516001600160a01b03163b600003611dda5761155a838383612096565b602081015160e0820151604051600092611df892869260240161323e565b60408051601f198184030181529190526020810180516001600160e01b031663643477d560e11b17905260608301516080840151919250600091611e3d919084611e8a565b905080611e5657611e4f858585612096565b5050505050565b604051849086907f34795cc6b122b9a0ae684946319f1e14a577b4e8f9b3dda9ac94c21a54d3188c90600090a35050505050565b60008060008084516020860160008989f195945050505050565b6000611ef9826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b031661210b9092919063ffffffff16565b80519091501561155a5780806020019051810190611f179190613268565b61155a5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b60648201526084016104c4565b6000818310611f8557816108d3565b5090919050565b604080518082019091526000808252602082015281546001830154819003611ff65760405162461bcd60e51b815260206004820152601960248201527f5265636569707451756575653a20656d7074792071756575650000000000000060448201526064016104c4565b60008181526002840160208181526040808420815180830190925280548252600180820180546001600160a01b03811685870152888852959094529490556001600160a01b031990921690559061204e908390612ce5565b9093555090919050565b6040516001600160a01b03808516602483015283166044820152606481018290526120909085906323b872dd60e01b90608401611523565b50505050565b806040516020016120a791906131f8565b60408051601f1981840301815282825280516020918201206000878152600690925291902055829084907f4619adc1017b82e02eaefac01a43d50d6d8de4460774bc370c3ff0210d40c985906120fe9085906131f8565b60405180910390a3505050565b606061127e848460008585600080866001600160a01b031685876040516121329190613283565b60006040518083038185875af1925050503d806000811461216f576040519150601f19603f3d011682016040523d82523d6000602084013e612174565b606091505b509150915061218587838387612190565b979650505050505050565b606083156121ff5782516000036121f8576001600160a01b0385163b6121f85760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016104c4565b508161127e565b61127e83838151156122145781518083602001fd5b8060405162461bcd60e51b81526004016104c49190612c23565b6001600160a01b038116811461224357600080fd5b50565b80356104fe8161222e565b60006020828403121561226357600080fd5b81356108d38161222e565b60006020828403121561228057600080fd5b5035919050565b828152606081016108d3602083018480516001600160a01b03168252602090810151910152565b6000602082840312156122c057600080fd5b81356001600160401b038111156122d657600080fd5b820160e081850312156108d357600080fd5b600061010082840312156122fb57600080fd5b50919050565b60006020828403121561231357600080fd5b81356001600160401b0381111561232957600080fd5b61127e848285016122e8565b6000806040838503121561234857600080fd5b50508035926020909101359150565b815181526020808301516001600160a01b0316908201526040810161060f565b60008060006060848603121561238c57600080fd5b83359250602084013561239e8161222e565b929592945050506040919091013590565b6000806000606084860312156123c457600080fd5b505081359360208301359350604090920135919050565b60008083601f8401126123ed57600080fd5b5081356001600160401b0381111561240457600080fd5b6020830191508360208260051b850101111561241f57600080fd5b9250929050565b60008060008060008086880360a081121561244057600080fd5b8735965060208801356001600160401b038082111561245e57600080fd5b61246a8b838c016123db565b90985096508691506040603f198401121561248457600080fd5b60408a01955060808a013592508083111561249e57600080fd5b50506124ac89828a016123db565b979a9699509497509295939492505050565b600080604083850312156124d157600080fd5b82356124dc8161222e565b915060208301356124ec8161222e565b809150509250929050565b6000806040838503121561250a57600080fd5b823563ffffffff811681146124dc57600080fd5b6000806040838503121561253157600080fd5b8235915060208301356001600160401b0381111561254e57600080fd5b61255a858286016122e8565b9150509250929050565b60006020828403121561257657600080fd5b5051919050565b60208082526027908201527f54656c65706f727465724d657373656e6765723a207a65726f20626c6f636b636040820152661a185a5b88125160ca1b606082015260800190565b60208082526023908201527f5265656e7472616e63794775617264733a2073656e646572207265656e7472616040820152626e637960e81b606082015260800190565b634e487b7160e01b600052604160045260246000fd5b604080519081016001600160401b038111828210171561263f5761263f612607565b60405290565b60405160c081016001600160401b038111828210171561263f5761263f612607565b60405161010081016001600160401b038111828210171561263f5761263f612607565b604051601f8201601f191681016001600160401b03811182821017156126b2576126b2612607565b604052919050565b6000604082840312156126cc57600080fd5b6126d461261d565b905081356126e18161222e565b808252506020820135602082015292915050565b60006001600160401b0382111561270e5761270e612607565b5060051b60200190565b600082601f83011261272957600080fd5b8135602061273e612739836126f5565b61268a565b82815260059290921b8401810191818101908684111561275d57600080fd5b8286015b848110156127815780356127748161222e565b8352918301918301612761565b509695505050505050565b60006001600160401b038211156127a5576127a5612607565b50601f01601f191660200190565b600082601f8301126127c457600080fd5b81356127d26127398261278c565b8181528460208386010111156127e757600080fd5b816020850160208301376000918101602001919091529392505050565b600060e0823603121561281657600080fd5b61281e612645565b8235815261282e60208401612246565b602082015261284036604085016126ba565b60408201526080830135606082015260a08301356001600160401b038082111561286957600080fd5b61287536838701612718565b608084015260c085013591508082111561288e57600080fd5b5061289b368286016127b3565b60a08301525092915050565b60208082526026908201527f54656c65706f727465724d657373656e6765723a206d657373616765206e6f7460408201526508199bdd5b9960d21b606082015260800190565b6000808335601e1984360301811261290457600080fd5b83016020810192503590506001600160401b0381111561292357600080fd5b8060051b360382131561241f57600080fd5b8183526000602080850194508260005b858110156129735781356129588161222e565b6001600160a01b031687529582019590820190600101612945565b509495945050505050565b6000808335601e1984360301811261299557600080fd5b83016020810192503590506001600160401b038111156129b457600080fd5b8060061b360382131561241f57600080fd5b8183526000602080850194508260005b858110156129735781358752828201356129ef8161222e565b6001600160a01b03168784015260409687019691909101906001016129d6565b6000808335601e19843603018112612a2657600080fd5b83016020810192503590506001600160401b03811115612a4557600080fd5b80360382131561241f57600080fd5b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b6000610100823584526020830135612a948161222e565b6001600160a01b0316602085015260408381013590850152612ab860608401612246565b6001600160a01b0316606085015260808381013590850152612add60a08401846128ed565b8260a0870152612af08387018284612935565b92505050612b0160c084018461297e565b85830360c0870152612b148382846129c6565b92505050612b2560e0840184612a0f565b85830360e0870152612b38838284612a54565b9695505050505050565b6020815260006108d36020830184612a7d565b60208082526029908201527f54656c65706f727465724d657373656e6765723a20696e76616c6964206d65736040820152680e6c2ceca40d0c2e6d60bb1b606082015260800190565b606081526000612bb16060830185612a7d565b90506108d3602083018480516001600160a01b03168252602090810151910152565b60005b83811015612bee578181015183820152602001612bd6565b50506000910152565b60008151808452612c0f816020860160208601612bd3565b601f01601f19169290920160200192915050565b6020815260006108d36020830184612bf7565b60208082526025908201527f5265656e7472616e63794775617264733a207265636569766572207265656e7460408201526472616e637960d81b606082015260800190565b60208082526034908201527f54656c65706f727465724d657373656e6765723a207a65726f2066656520617360408201527373657420636f6e7472616374206164647265737360601b606082015260800190565b634e487b7160e01b600052601160045260246000fd5b8082018082111561060f5761060f612ccf565b634e487b7160e01b600052603260045260246000fd5b600060018201612d2057612d20612ccf565b5060010190565b600060408284031215612d3957600080fd5b6108d383836126ba565b80516104fe8161222e565b600082601f830112612d5f57600080fd5b8151612d6d6127398261278c565b818152846020838601011115612d8257600080fd5b61127e826020830160208701612bd3565b805180151581146104fe57600080fd5b60008060408385031215612db657600080fd5b82516001600160401b0380821115612dcd57600080fd5b9084019060608287031215612de157600080fd5b604051606081018181108382111715612dfc57612dfc612607565b604052825181526020830151612e118161222e565b6020820152604083015182811115612e2857600080fd5b612e3488828601612d4e565b6040830152509350612e4b91505060208401612d93565b90509250929050565b600082601f830112612e6557600080fd5b81516020612e75612739836126f5565b82815260059290921b84018101918181019086841115612e9457600080fd5b8286015b84811015612781578051612eab8161222e565b8352918301918301612e98565b600082601f830112612ec957600080fd5b81516020612ed9612739836126f5565b82815260069290921b84018101918181019086841115612ef857600080fd5b8286015b848110156127815760408189031215612f155760008081fd5b612f1d61261d565b8151815284820151612f2e8161222e565b81860152835291830191604001612efc565b600060208284031215612f5257600080fd5b81516001600160401b0380821115612f6957600080fd5b908301906101008286031215612f7e57600080fd5b612f86612667565b82518152612f9660208401612d43565b602082015260408301516040820152612fb160608401612d43565b60608201526080830151608082015260a083015182811115612fd257600080fd5b612fde87828601612e54565b60a08301525060c083015182811115612ff657600080fd5b61300287828601612eb8565b60c08301525060e08301518281111561301a57600080fd5b61302687828601612d4e565b60e08301525095945050505050565b600081518084526020808501945080840160005b838110156129735781516001600160a01b031687529582019590820190600101613049565b600081518084526020808501945080840160005b83811015612973576130a8878351805182526020908101516001600160a01b0316910152565b6040969096019590820190600101613082565b60006101008251845260018060a01b0360208401511660208501526040830151604085015260608301516130fa60608601826001600160a01b03169052565b506080830151608085015260a08301518160a086015261311c82860182613035565b91505060c083015184820360c0860152613136828261306e565b91505060e083015184820360e0860152611ae08282612bf7565b6001600160a01b038316815260406020820181905260009061127e908301846130bb565b6000808335601e1984360301811261318b57600080fd5b8301803591506001600160401b038211156131a557600080fd5b60200191503681900382131561241f57600080fd5b8481526001600160a01b0384166020820152606060408201819052600090612b389083018486612a54565b8181038181111561060f5761060f612ccf565b6020815260006108d360208301846130bb565b606081526000612bb160608301856130bb565b81516001600160a01b03168152602080830151908201526040810161060f565b8381526001600160a01b0383166020820152606060408201819052600090611ae090830184612bf7565b60006020828403121561327a57600080fd5b6108d382612d93565b60008251613295818460208701612bd3565b919091019291505056fea2646970667358221220586881dd1413fe17197100ceb55646481dae802ef65d37df603c3915f51a4b6364736f6c63430008120033 diff --git a/pkg/vm/deployed_registry_bytecode.txt b/pkg/vm/deployed_registry_bytecode.txt new file mode 100644 index 000000000..7b1a0502b --- /dev/null +++ b/pkg/vm/deployed_registry_bytecode.txt @@ -0,0 +1 @@ +0x608060405234801561001057600080fd5b506004361061009e5760003560e01c8063ac473ac311610066578063ac473ac314610124578063b771b3bc1461012d578063c07f47d41461013b578063d127dc9b14610144578063d820e64f1461016b57600080fd5b80630731775d146100a3578063215abce9146100c857806341f34ed9146100db57806346f9ef49146100f05780634c1f08ce14610103575b600080fd5b6100ab600081565b6040516001600160a01b0390911681526020015b60405180910390f35b6100ab6100d63660046107c5565b610173565b6100ee6100e93660046107de565b610184565b005b6100ab6100fe3660046107c5565b6103f9565b610116610111366004610823565b6104be565b6040519081526020016100bf565b6101166101f481565b6100ab6005600160991b0181565b61011660005481565b6101167f000000000000000000000000000000000000000000000000000000000000000081565b6100ab610566565b600061017e826103f9565b92915050565b6040516306f8253560e41b815263ffffffff8216600482015260009081906005600160991b0190636f82535090602401600060405180830381865afa1580156101d1573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526101f991908101906108c5565b91509150806102605760405162461bcd60e51b815260206004820152602860248201527f54656c65706f7274657252656769737472793a20696e76616c69642077617270604482015267206d65737361676560c01b60648201526084015b60405180910390fd5b81517f0000000000000000000000000000000000000000000000000000000000000000146102e45760405162461bcd60e51b815260206004820152602b60248201527f54656c65706f7274657252656769737472793a20696e76616c696420736f757260448201526a18d94818da185a5b88125160aa1b6064820152608401610257565b60208201516001600160a01b0316156103595760405162461bcd60e51b815260206004820152603160248201527f54656c65706f7274657252656769737472793a20696e76616c6964206f726967604482015270696e2073656e646572206164647265737360781b6064820152608401610257565b600080836040015180602001905181019061037491906109cd565b90925090506001600160a01b03811630146103e95760405162461bcd60e51b815260206004820152602f60248201527f54656c65706f7274657252656769737472793a20696e76616c6964206465737460448201526e696e6174696f6e206164647265737360881b6064820152608401610257565b6103f282610578565b5050505050565b60008160000361044b5760405162461bcd60e51b815260206004820181905260248201527f54656c65706f7274657252656769737472793a207a65726f2076657273696f6e6044820152606401610257565b6000828152600160205260409020546001600160a01b03168061017e5760405162461bcd60e51b815260206004820152602560248201527f54656c65706f7274657252656769737472793a2076657273696f6e206e6f7420604482015264199bdd5b9960da1b6064820152608401610257565b60006001600160a01b0382166104e65760405162461bcd60e51b815260040161025790610a49565b6001600160a01b0382166000908152600260205260408120549081900361017e5760405162461bcd60e51b815260206004820152602e60248201527f54656c65706f7274657252656769737472793a2070726f746f636f6c2061646460448201526d1c995cdcc81b9bdd08199bdd5b9960921b6064820152608401610257565b60006105736000546103f9565b905090565b80516000036105c95760405162461bcd60e51b815260206004820181905260248201527f54656c65706f7274657252656769737472793a207a65726f2076657273696f6e6044820152606401610257565b80516000908152600160205260409020546001600160a01b0316156106435760405162461bcd60e51b815260206004820152602a60248201527f54656c65706f7274657252656769737472793a2076657273696f6e20616c72656044820152696164792065786973747360b01b6064820152608401610257565b60208101516001600160a01b031661066d5760405162461bcd60e51b815260040161025790610a49565b60005461067c6101f482610a92565b825111156106e35760405162461bcd60e51b815260206004820152602e60248201527f54656c65706f7274657252656769737472793a2076657273696f6e20696e637260448201526d0cadacadce840e8dede40d0d2ced60931b6064820152608401610257565b602082810180518451600090815260018452604080822080546001600160a01b0319166001600160a01b039485161790559251909116815260029092529020548251111561074c5781516020808401516001600160a01b03166000908152600290915260409020555b602082015182516040516001600160a01b03909216917fa5eed93d951a9603d5f7c0a57de79a299dd3dbd5e51429be209d8053a42ab43a90600090a381518110156107c1578151600081815560405183917f30623e953733f6474dabdfbef1103ce15ab73cdc77c6dfad0f9874d167e8a9b091a35b5050565b6000602082840312156107d757600080fd5b5035919050565b6000602082840312156107f057600080fd5b813563ffffffff8116811461080457600080fd5b9392505050565b6001600160a01b038116811461082057600080fd5b50565b60006020828403121561083557600080fd5b81356108048161080b565b634e487b7160e01b600052604160045260246000fd5b6040516060810167ffffffffffffffff8111828210171561087957610879610840565b60405290565b604051601f8201601f1916810167ffffffffffffffff811182821017156108a8576108a8610840565b604052919050565b805180151581146108c057600080fd5b919050565b600080604083850312156108d857600080fd5b825167ffffffffffffffff808211156108f057600080fd5b908401906060828703121561090457600080fd5b61090c610856565b8251815260208084015161091f8161080b565b8282015260408401518381111561093557600080fd5b80850194505087601f85011261094a57600080fd5b83518381111561095c5761095c610840565b61096e601f8201601f1916830161087f565b9350808452888282870101111561098457600080fd5b60005b818110156109a2578581018301518582018401528201610987565b506000828286010152508260408301528195506109c08188016108b0565b9450505050509250929050565b60008082840360608112156109e157600080fd5b60408112156109ef57600080fd5b506040516040810181811067ffffffffffffffff82111715610a1357610a13610840565b604052835181526020840151610a288161080b565b60208201526040840151909250610a3e8161080b565b809150509250929050565b60208082526029908201527f54656c65706f7274657252656769737472793a207a65726f2070726f746f636f6040820152686c206164647265737360b81b606082015260800190565b8082018082111561017e57634e487b7160e01b600052601160045260246000fdfea2646970667358221220147aa4bf673206f63959dca6bf01bb7ab5e23e6ff9c146a03a27caed9a8296ef64736f6c63430008120033 diff --git a/pkg/vm/icm.go b/pkg/vm/icm.go new file mode 100644 index 000000000..d284ce57a --- /dev/null +++ b/pkg/vm/icm.go @@ -0,0 +1,40 @@ +// Copyright (C) 2022, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. +package vm + +import ( + _ "embed" + "math/big" + "strings" + + "github.com/ava-labs/subnet-evm/core" + "github.com/ethereum/go-ethereum/common" +) + +const ( + messengerContractAddress = "0x253b2784c75e510dD0fF1da844684a1aC0aa5fcf" + messengerDeployerAddress = "0x618FEdD9A45a8C456812ecAAE70C671c6249DfaC" +) + +//go:embed deployed_messenger_bytecode.txt +var deployedMessengerBytecode []byte + +func addICMContractToGenesisAllocations( + allocs core.GenesisAlloc, +) { + storage := map[common.Hash]common.Hash{ + common.HexToHash("0x0"): common.HexToHash("0x1"), + common.HexToHash("0x1"): common.HexToHash("0x1"), + } + deployedMessengerBytes := common.FromHex(strings.TrimSpace(string(deployedMessengerBytecode))) + allocs[common.HexToAddress(messengerContractAddress)] = core.GenesisAccount{ + Balance: big.NewInt(0), + Code: deployedMessengerBytes, + Storage: storage, + Nonce: 1, + } + allocs[common.HexToAddress(messengerDeployerAddress)] = core.GenesisAccount{ + Balance: big.NewInt(0), + Nonce: 1, + } +} From dfa8bfa0f778f49ba05364fae7193098d02767ab Mon Sep 17 00:00:00 2001 From: Felipe Madero Date: Mon, 16 Sep 2024 14:14:39 -0400 Subject: [PATCH 16/64] add function to deploy ICM registry --- pkg/vm/icm.go | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/pkg/vm/icm.go b/pkg/vm/icm.go index d284ce57a..ba0b0ab16 100644 --- a/pkg/vm/icm.go +++ b/pkg/vm/icm.go @@ -14,11 +14,15 @@ import ( const ( messengerContractAddress = "0x253b2784c75e510dD0fF1da844684a1aC0aa5fcf" messengerDeployerAddress = "0x618FEdD9A45a8C456812ecAAE70C671c6249DfaC" + registryContractAddress = "0xF86Cb19Ad8405AEFa7d09C778215D2Cb6eBfB228" ) //go:embed deployed_messenger_bytecode.txt var deployedMessengerBytecode []byte +//go:embed deployed_registry_bytecode.txt +var deployedRegistryBytecode []byte + func addICMContractToGenesisAllocations( allocs core.GenesisAlloc, ) { @@ -38,3 +42,19 @@ func addICMContractToGenesisAllocations( Nonce: 1, } } + +func addICMRegistryContractToGenesisAllocations( + allocs core.GenesisAlloc, +) { + storage := map[common.Hash]common.Hash{ + common.HexToHash("0x0"): common.HexToHash("0x1"), + common.HexToHash("0x1"): common.HexToHash("0x1"), + } + deployedRegistryBytes := common.FromHex(strings.TrimSpace(string(deployedRegistryBytecode))) + allocs[common.HexToAddress(registryContractAddress)] = core.GenesisAccount{ + Balance: big.NewInt(0), + Code: deployedRegistryBytes, + Storage: storage, + Nonce: 1, + } +} From 26ef2fa869dd52fee001f8e8308fd9de15a02d15 Mon Sep 17 00:00:00 2001 From: Felipe Madero Date: Mon, 16 Sep 2024 15:58:23 -0400 Subject: [PATCH 17/64] creating mapping values --- pkg/vm/create_evm.go | 3 +++ pkg/vm/icm.go | 56 +++++++++++++++++++++++++++++++++++++------- 2 files changed, 51 insertions(+), 8 deletions(-) diff --git a/pkg/vm/create_evm.go b/pkg/vm/create_evm.go index 5b62a7760..dc2cca3c7 100644 --- a/pkg/vm/create_evm.go +++ b/pkg/vm/create_evm.go @@ -113,6 +113,9 @@ func CreateEVMGenesis( Balance: balance, } addICMContractToGenesisAllocations(params.initialTokenAllocation) + if err := addICMRegistryContractToGenesisAllocations(params.initialTokenAllocation); err != nil { + return nil, err + } } if params.UseExternalGasToken { diff --git a/pkg/vm/icm.go b/pkg/vm/icm.go index ba0b0ab16..e5f03a555 100644 --- a/pkg/vm/icm.go +++ b/pkg/vm/icm.go @@ -4,11 +4,14 @@ package vm import ( _ "embed" + "encoding/hex" + "fmt" "math/big" "strings" "github.com/ava-labs/subnet-evm/core" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/crypto" ) const ( @@ -23,13 +26,45 @@ var deployedMessengerBytecode []byte //go:embed deployed_registry_bytecode.txt var deployedRegistryBytecode []byte +func setSimpleStorageValue( + storage map[common.Hash]common.Hash, + slot string, + value string, +) { + storage[common.HexToHash(slot)] = common.HexToHash(value) +} + +func trimHexa(s string) string { + return strings.TrimPrefix(strings.TrimPrefix(s, "0x"), "0X") +} + +func hexFill32(s string) string { + return fmt.Sprintf("%064s", trimHexa(s)) +} + +func setMappingStorageValue( + storage map[common.Hash]common.Hash, + slot string, + key string, + value string, +) error { + slot = hexFill32(slot) + key = hexFill32(key) + storageKey := key + slot + storageKeyBytes, err := hex.DecodeString(storageKey) + if err != nil { + return err + } + storage[crypto.Keccak256Hash(storageKeyBytes)] = common.HexToHash(value) + return nil +} + func addICMContractToGenesisAllocations( allocs core.GenesisAlloc, ) { - storage := map[common.Hash]common.Hash{ - common.HexToHash("0x0"): common.HexToHash("0x1"), - common.HexToHash("0x1"): common.HexToHash("0x1"), - } + storage := map[common.Hash]common.Hash{} + setSimpleStorageValue(storage, "0", "1") + setSimpleStorageValue(storage, "1", "1") deployedMessengerBytes := common.FromHex(strings.TrimSpace(string(deployedMessengerBytecode))) allocs[common.HexToAddress(messengerContractAddress)] = core.GenesisAccount{ Balance: big.NewInt(0), @@ -45,10 +80,14 @@ func addICMContractToGenesisAllocations( func addICMRegistryContractToGenesisAllocations( allocs core.GenesisAlloc, -) { - storage := map[common.Hash]common.Hash{ - common.HexToHash("0x0"): common.HexToHash("0x1"), - common.HexToHash("0x1"): common.HexToHash("0x1"), +) error { + storage := map[common.Hash]common.Hash{} + setSimpleStorageValue(storage, "0", "1") + if err := setMappingStorageValue(storage, "1", "1", messengerContractAddress); err != nil { + return err + } + if err := setMappingStorageValue(storage, "2", messengerContractAddress, "2"); err != nil { + return err } deployedRegistryBytes := common.FromHex(strings.TrimSpace(string(deployedRegistryBytecode))) allocs[common.HexToAddress(registryContractAddress)] = core.GenesisAccount{ @@ -57,4 +96,5 @@ func addICMRegistryContractToGenesisAllocations( Storage: storage, Nonce: 1, } + return nil } From 78c58a6d759af2882885ab563c5621aa95233341 Mon Sep 17 00:00:00 2001 From: Felipe Madero Date: Mon, 16 Sep 2024 16:34:15 -0400 Subject: [PATCH 18/64] add consts --- pkg/vm/icm.go | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/pkg/vm/icm.go b/pkg/vm/icm.go index e5f03a555..b425c19ec 100644 --- a/pkg/vm/icm.go +++ b/pkg/vm/icm.go @@ -15,6 +15,7 @@ import ( ) const ( + messengerVersion = "0x1" messengerContractAddress = "0x253b2784c75e510dD0fF1da844684a1aC0aa5fcf" messengerDeployerAddress = "0x618FEdD9A45a8C456812ecAAE70C671c6249DfaC" registryContractAddress = "0xF86Cb19Ad8405AEFa7d09C778215D2Cb6eBfB228" @@ -62,9 +63,13 @@ func setMappingStorageValue( func addICMContractToGenesisAllocations( allocs core.GenesisAlloc, ) { + const ( + blockchainIDSlot = "0x0" + messageNonceSlot = "0x1" + ) storage := map[common.Hash]common.Hash{} - setSimpleStorageValue(storage, "0", "1") - setSimpleStorageValue(storage, "1", "1") + setSimpleStorageValue(storage, blockchainIDSlot, "0x1") + setSimpleStorageValue(storage, messageNonceSlot, "0x1") deployedMessengerBytes := common.FromHex(strings.TrimSpace(string(deployedMessengerBytecode))) allocs[common.HexToAddress(messengerContractAddress)] = core.GenesisAccount{ Balance: big.NewInt(0), @@ -81,12 +86,17 @@ func addICMContractToGenesisAllocations( func addICMRegistryContractToGenesisAllocations( allocs core.GenesisAlloc, ) error { + const ( + latestVersionSlot = "0x0" + versionToAddressSlot = "0x1" + addressToVersionSlot = "0x2" + ) storage := map[common.Hash]common.Hash{} - setSimpleStorageValue(storage, "0", "1") - if err := setMappingStorageValue(storage, "1", "1", messengerContractAddress); err != nil { + setSimpleStorageValue(storage, latestVersionSlot, messengerVersion) + if err := setMappingStorageValue(storage, versionToAddressSlot, messengerVersion, messengerContractAddress); err != nil { return err } - if err := setMappingStorageValue(storage, "2", messengerContractAddress, "2"); err != nil { + if err := setMappingStorageValue(storage, addressToVersionSlot, messengerContractAddress, messengerVersion); err != nil { return err } deployedRegistryBytes := common.FromHex(strings.TrimSpace(string(deployedRegistryBytecode))) From d39a8e87d4a2802f335b0ba56e96f9fdcf0094ad Mon Sep 17 00:00:00 2001 From: Felipe Madero Date: Mon, 16 Sep 2024 17:23:54 -0400 Subject: [PATCH 19/64] make local deploy to work --- pkg/subnet/local.go | 10 ++++++++-- pkg/vm/create_evm.go | 2 +- pkg/vm/icm.go | 14 +++++++------- 3 files changed, 16 insertions(+), 10 deletions(-) diff --git a/pkg/subnet/local.go b/pkg/subnet/local.go index 18b87fab6..b28d539fd 100644 --- a/pkg/subnet/local.go +++ b/pkg/subnet/local.go @@ -26,6 +26,7 @@ import ( "github.com/ava-labs/avalanche-cli/pkg/teleporter" "github.com/ava-labs/avalanche-cli/pkg/utils" "github.com/ava-labs/avalanche-cli/pkg/ux" + "github.com/ava-labs/avalanche-cli/pkg/vm" "github.com/ava-labs/avalanche-network-runner/client" "github.com/ava-labs/avalanche-network-runner/rpcpb" "github.com/ava-labs/avalanche-network-runner/server" @@ -444,17 +445,22 @@ func (d *LocalDeployer) doDeploy(chain string, genesisPath string, icmSpec ICMSp if err != nil { return nil, err } - _, icmMessengerAddress, icmRegistryAddress, err = icmd.Deploy( + var alreadyDeployed bool + alreadyDeployed, icmMessengerAddress, icmRegistryAddress, err = icmd.Deploy( chain, network.BlockchainEndpoint(blockchainID), blockchainKey.PrivKeyHex(), true, true, - true, + false, ) if err != nil { return nil, err } + if alreadyDeployed { + // included in genesis + icmRegistryAddress = vm.RegistryContractAddress + } if sc.RunRelayer && !icmSpec.SkipRelayerDeploy { if !cchainAlreadyDeployed { if err := teleporter.FundRelayer( diff --git a/pkg/vm/create_evm.go b/pkg/vm/create_evm.go index dc2cca3c7..3a559024c 100644 --- a/pkg/vm/create_evm.go +++ b/pkg/vm/create_evm.go @@ -112,7 +112,7 @@ func CreateEVMGenesis( params.initialTokenAllocation[common.HexToAddress(teleporterInfo.FundedAddress)] = core.GenesisAccount{ Balance: balance, } - addICMContractToGenesisAllocations(params.initialTokenAllocation) + addICMMessengerContractToGenesisAllocations(params.initialTokenAllocation) if err := addICMRegistryContractToGenesisAllocations(params.initialTokenAllocation); err != nil { return nil, err } diff --git a/pkg/vm/icm.go b/pkg/vm/icm.go index b425c19ec..7d89a01e9 100644 --- a/pkg/vm/icm.go +++ b/pkg/vm/icm.go @@ -16,9 +16,9 @@ import ( const ( messengerVersion = "0x1" - messengerContractAddress = "0x253b2784c75e510dD0fF1da844684a1aC0aa5fcf" messengerDeployerAddress = "0x618FEdD9A45a8C456812ecAAE70C671c6249DfaC" - registryContractAddress = "0xF86Cb19Ad8405AEFa7d09C778215D2Cb6eBfB228" + MessengerContractAddress = "0x253b2784c75e510dD0fF1da844684a1aC0aa5fcf" + RegistryContractAddress = "0xF86Cb19Ad8405AEFa7d09C778215D2Cb6eBfB228" ) //go:embed deployed_messenger_bytecode.txt @@ -60,7 +60,7 @@ func setMappingStorageValue( return nil } -func addICMContractToGenesisAllocations( +func addICMMessengerContractToGenesisAllocations( allocs core.GenesisAlloc, ) { const ( @@ -71,7 +71,7 @@ func addICMContractToGenesisAllocations( setSimpleStorageValue(storage, blockchainIDSlot, "0x1") setSimpleStorageValue(storage, messageNonceSlot, "0x1") deployedMessengerBytes := common.FromHex(strings.TrimSpace(string(deployedMessengerBytecode))) - allocs[common.HexToAddress(messengerContractAddress)] = core.GenesisAccount{ + allocs[common.HexToAddress(MessengerContractAddress)] = core.GenesisAccount{ Balance: big.NewInt(0), Code: deployedMessengerBytes, Storage: storage, @@ -93,14 +93,14 @@ func addICMRegistryContractToGenesisAllocations( ) storage := map[common.Hash]common.Hash{} setSimpleStorageValue(storage, latestVersionSlot, messengerVersion) - if err := setMappingStorageValue(storage, versionToAddressSlot, messengerVersion, messengerContractAddress); err != nil { + if err := setMappingStorageValue(storage, versionToAddressSlot, messengerVersion, MessengerContractAddress); err != nil { return err } - if err := setMappingStorageValue(storage, addressToVersionSlot, messengerContractAddress, messengerVersion); err != nil { + if err := setMappingStorageValue(storage, addressToVersionSlot, MessengerContractAddress, messengerVersion); err != nil { return err } deployedRegistryBytes := common.FromHex(strings.TrimSpace(string(deployedRegistryBytecode))) - allocs[common.HexToAddress(registryContractAddress)] = core.GenesisAccount{ + allocs[common.HexToAddress(RegistryContractAddress)] = core.GenesisAccount{ Balance: big.NewInt(0), Code: deployedRegistryBytes, Storage: storage, From 857f8157ba542c4b6a83c2a8711abd655687d9cc Mon Sep 17 00:00:00 2001 From: Felipe Madero Date: Mon, 16 Sep 2024 17:39:41 -0400 Subject: [PATCH 20/64] do not print info for icm support addrs --- cmd/blockchaincmd/describe.go | 7 +++++++ pkg/subnet/local.go | 4 ++-- .../genesis}/deployed_messenger_bytecode.txt | 0 .../genesis}/deployed_registry_bytecode.txt | 0 .../icm.go => teleporter/genesis/genesis.go} | 18 +++++++++--------- pkg/vm/create_evm.go | 5 +++-- 6 files changed, 21 insertions(+), 13 deletions(-) rename pkg/{vm => teleporter/genesis}/deployed_messenger_bytecode.txt (100%) rename pkg/{vm => teleporter/genesis}/deployed_registry_bytecode.txt (100%) rename pkg/{vm/icm.go => teleporter/genesis/genesis.go} (83%) diff --git a/cmd/blockchaincmd/describe.go b/cmd/blockchaincmd/describe.go index 83ac2a5b8..23b0943cf 100644 --- a/cmd/blockchaincmd/describe.go +++ b/cmd/blockchaincmd/describe.go @@ -17,6 +17,7 @@ import ( "github.com/ava-labs/avalanche-cli/pkg/models" "github.com/ava-labs/avalanche-cli/pkg/networkoptions" "github.com/ava-labs/avalanche-cli/pkg/subnet" + icmgenesis "github.com/ava-labs/avalanche-cli/pkg/teleporter/genesis" "github.com/ava-labs/avalanche-cli/pkg/txutils" "github.com/ava-labs/avalanche-cli/pkg/utils" "github.com/ava-labs/avalanche-cli/pkg/ux" @@ -276,6 +277,12 @@ func printAllocations(sc models.Sidecar, genesis core.Genesis) error { t.SetTitle("Initial Token Allocation") t.AppendHeader(table.Row{"Description", "Address and Private Key", "Amount (10^18)", "Amount (wei)"}) for address := range genesis.Alloc { + if len(genesis.Alloc[address].Code) > 0 { + continue + } + if address == common.HexToAddress(icmgenesis.MessengerDeployerAddress) { + continue + } amount := genesis.Alloc[address].Balance formattedAmount := new(big.Int).Div(amount, big.NewInt(params.Ether)) description := "" diff --git a/pkg/subnet/local.go b/pkg/subnet/local.go index b28d539fd..d3b0f6e39 100644 --- a/pkg/subnet/local.go +++ b/pkg/subnet/local.go @@ -24,9 +24,9 @@ import ( "github.com/ava-labs/avalanche-cli/pkg/localnet" "github.com/ava-labs/avalanche-cli/pkg/models" "github.com/ava-labs/avalanche-cli/pkg/teleporter" + icmgenesis "github.com/ava-labs/avalanche-cli/pkg/teleporter/genesis" "github.com/ava-labs/avalanche-cli/pkg/utils" "github.com/ava-labs/avalanche-cli/pkg/ux" - "github.com/ava-labs/avalanche-cli/pkg/vm" "github.com/ava-labs/avalanche-network-runner/client" "github.com/ava-labs/avalanche-network-runner/rpcpb" "github.com/ava-labs/avalanche-network-runner/server" @@ -459,7 +459,7 @@ func (d *LocalDeployer) doDeploy(chain string, genesisPath string, icmSpec ICMSp } if alreadyDeployed { // included in genesis - icmRegistryAddress = vm.RegistryContractAddress + icmRegistryAddress = icmgenesis.RegistryContractAddress } if sc.RunRelayer && !icmSpec.SkipRelayerDeploy { if !cchainAlreadyDeployed { diff --git a/pkg/vm/deployed_messenger_bytecode.txt b/pkg/teleporter/genesis/deployed_messenger_bytecode.txt similarity index 100% rename from pkg/vm/deployed_messenger_bytecode.txt rename to pkg/teleporter/genesis/deployed_messenger_bytecode.txt diff --git a/pkg/vm/deployed_registry_bytecode.txt b/pkg/teleporter/genesis/deployed_registry_bytecode.txt similarity index 100% rename from pkg/vm/deployed_registry_bytecode.txt rename to pkg/teleporter/genesis/deployed_registry_bytecode.txt diff --git a/pkg/vm/icm.go b/pkg/teleporter/genesis/genesis.go similarity index 83% rename from pkg/vm/icm.go rename to pkg/teleporter/genesis/genesis.go index 7d89a01e9..67e005549 100644 --- a/pkg/vm/icm.go +++ b/pkg/teleporter/genesis/genesis.go @@ -1,6 +1,6 @@ // Copyright (C) 2022, Ava Labs, Inc. All rights reserved. // See the file LICENSE for licensing terms. -package vm +package genesis import ( _ "embed" @@ -16,9 +16,9 @@ import ( const ( messengerVersion = "0x1" - messengerDeployerAddress = "0x618FEdD9A45a8C456812ecAAE70C671c6249DfaC" - MessengerContractAddress = "0x253b2784c75e510dD0fF1da844684a1aC0aa5fcf" + messengerContractAddress = "0x253b2784c75e510dD0fF1da844684a1aC0aa5fcf" RegistryContractAddress = "0xF86Cb19Ad8405AEFa7d09C778215D2Cb6eBfB228" + MessengerDeployerAddress = "0x618FEdD9A45a8C456812ecAAE70C671c6249DfaC" ) //go:embed deployed_messenger_bytecode.txt @@ -60,7 +60,7 @@ func setMappingStorageValue( return nil } -func addICMMessengerContractToGenesisAllocations( +func AddICMMessengerContractToAllocations( allocs core.GenesisAlloc, ) { const ( @@ -71,19 +71,19 @@ func addICMMessengerContractToGenesisAllocations( setSimpleStorageValue(storage, blockchainIDSlot, "0x1") setSimpleStorageValue(storage, messageNonceSlot, "0x1") deployedMessengerBytes := common.FromHex(strings.TrimSpace(string(deployedMessengerBytecode))) - allocs[common.HexToAddress(MessengerContractAddress)] = core.GenesisAccount{ + allocs[common.HexToAddress(messengerContractAddress)] = core.GenesisAccount{ Balance: big.NewInt(0), Code: deployedMessengerBytes, Storage: storage, Nonce: 1, } - allocs[common.HexToAddress(messengerDeployerAddress)] = core.GenesisAccount{ + allocs[common.HexToAddress(MessengerDeployerAddress)] = core.GenesisAccount{ Balance: big.NewInt(0), Nonce: 1, } } -func addICMRegistryContractToGenesisAllocations( +func AddICMRegistryContractToAllocations( allocs core.GenesisAlloc, ) error { const ( @@ -93,10 +93,10 @@ func addICMRegistryContractToGenesisAllocations( ) storage := map[common.Hash]common.Hash{} setSimpleStorageValue(storage, latestVersionSlot, messengerVersion) - if err := setMappingStorageValue(storage, versionToAddressSlot, messengerVersion, MessengerContractAddress); err != nil { + if err := setMappingStorageValue(storage, versionToAddressSlot, messengerVersion, messengerContractAddress); err != nil { return err } - if err := setMappingStorageValue(storage, addressToVersionSlot, MessengerContractAddress, messengerVersion); err != nil { + if err := setMappingStorageValue(storage, addressToVersionSlot, messengerContractAddress, messengerVersion); err != nil { return err } deployedRegistryBytes := common.FromHex(strings.TrimSpace(string(deployedRegistryBytecode))) diff --git a/pkg/vm/create_evm.go b/pkg/vm/create_evm.go index 3a559024c..230c19398 100644 --- a/pkg/vm/create_evm.go +++ b/pkg/vm/create_evm.go @@ -14,6 +14,7 @@ import ( "github.com/ava-labs/avalanche-cli/pkg/binutils" "github.com/ava-labs/avalanche-cli/pkg/models" "github.com/ava-labs/avalanche-cli/pkg/teleporter" + icmgenesis "github.com/ava-labs/avalanche-cli/pkg/teleporter/genesis" "github.com/ava-labs/avalanche-cli/pkg/ux" "github.com/ava-labs/subnet-evm/core" subnetevmparams "github.com/ava-labs/subnet-evm/params" @@ -112,8 +113,8 @@ func CreateEVMGenesis( params.initialTokenAllocation[common.HexToAddress(teleporterInfo.FundedAddress)] = core.GenesisAccount{ Balance: balance, } - addICMMessengerContractToGenesisAllocations(params.initialTokenAllocation) - if err := addICMRegistryContractToGenesisAllocations(params.initialTokenAllocation); err != nil { + icmgenesis.AddICMMessengerContractToAllocations(params.initialTokenAllocation) + if err := icmgenesis.AddICMRegistryContractToAllocations(params.initialTokenAllocation); err != nil { return nil, err } } From c868707f9573c81646285cfed6c1e60223b4838f Mon Sep 17 00:00:00 2001 From: Felipe Madero Date: Mon, 16 Sep 2024 17:54:19 -0400 Subject: [PATCH 21/64] nit --- cmd/blockchaincmd/create.go | 1 - pkg/vm/create_evm.go | 1 - 2 files changed, 2 deletions(-) diff --git a/cmd/blockchaincmd/create.go b/cmd/blockchaincmd/create.go index 30bcbbe40..07ee0835d 100644 --- a/cmd/blockchaincmd/create.go +++ b/cmd/blockchaincmd/create.go @@ -276,7 +276,6 @@ func createBlockchainConfig(cmd *cobra.Command, args []string) error { deployTeleporter = params.UseTeleporter useExternalGasToken = params.UseExternalGasToken genesisBytes, err = vm.CreateEVMGenesis( - app, blockchainName, params, teleporterInfo, diff --git a/pkg/vm/create_evm.go b/pkg/vm/create_evm.go index 230c19398..3be78433e 100644 --- a/pkg/vm/create_evm.go +++ b/pkg/vm/create_evm.go @@ -73,7 +73,6 @@ func CreateEvmSidecar( } func CreateEVMGenesis( - app *application.Avalanche, blockchainName string, params SubnetEVMGenesisParams, teleporterInfo *teleporter.Info, From e87b8f18488b1771cd3a97e8aba43ddddc162ba9 Mon Sep 17 00:00:00 2001 From: Raymond Sukanto Date: Mon, 16 Sep 2024 18:11:44 -0400 Subject: [PATCH 22/64] implement prompts --- cmd/blockchaincmd/create.go | 123 +++++++++++++++++--------- cmd/blockchaincmd/prompt_owners.go | 81 +++++++++++++++++ pkg/networkoptions/network_options.go | 29 +++++- pkg/prompts/prompts.go | 44 ++++----- 4 files changed, 205 insertions(+), 72 deletions(-) diff --git a/cmd/blockchaincmd/create.go b/cmd/blockchaincmd/create.go index 7a832701e..63b9c6c73 100644 --- a/cmd/blockchaincmd/create.go +++ b/cmd/blockchaincmd/create.go @@ -6,9 +6,12 @@ import ( "encoding/json" "errors" "fmt" + "github.com/ava-labs/avalanche-cli/pkg/prompts" "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/utils/formatting/address" "github.com/ava-labs/avalanchego/vms/platformvm/fx" "github.com/ava-labs/avalanchego/vms/platformvm/signer" + "github.com/ava-labs/avalanchego/vms/secp256k1fx" "os" "sort" "strconv" @@ -222,13 +225,13 @@ func createBlockchainConfig(cmd *cobra.Command, args []string) error { } } - if len(createFlags.bootstrapValidatorInitialBalance) > 0 { - for _, balance := range createFlags.bootstrapValidatorInitialBalance { - if balance < constants.MinInitialBalanceBootstrapValidator { - return fmt.Errorf("initial bootstrap validator balance must be at least %d AVAX", constants.MinInitialBalanceBootstrapValidator) - } - } - } + //if len(createFlags.bootstrapValidatorInitialBalance) > 0 { + // for _, balance := range createFlags.bootstrapValidatorInitialBalance { + // if balance < constants.MinInitialBalanceBootstrapValidator { + // return fmt.Errorf("initial bootstrap validator balance must be at least %d AVAX", constants.MinInitialBalanceBootstrapValidator) + // } + // } + //} // get vm kind vmType, err := vm.PromptVMType(app, createFlags.useSubnetEvm, createFlags.useCustomVM) @@ -424,12 +427,9 @@ func createBlockchainConfig(cmd *cobra.Command, args []string) error { return err } - subnetValidators, err := promptValidators() + _, err = promptValidators() //TODO: update subnetvalidators in sidecar - ux.Logger.GreenCheckmarkToUser("Number of initial bootstrap validators %d", len(createFlags.bootstrapValidatorInitialBalance)) - ux.Logger.GreenCheckmarkToUser("Initial bootstrap validator balances %d", createFlags.bootstrapValidatorInitialBalance) - if err = app.CreateSidecar(sc); err != nil { return err } @@ -574,74 +574,115 @@ type SubnetValidator struct { ChangeOwner fx.Owner } -func PromptWeightPrimaryNetwork(network models.Network) (uint64, error) { - defaultStake := network.GenesisParams().MinValidatorStake - defaultWeight := fmt.Sprintf("Default (%s)", convertNanoAvaxToAvaxString(defaultStake)) +// TODO: find the min weight for bootstrap validator +func PromptWeightBootstrapValidator() (uint64, error) { txt := "What stake weight would you like to assign to the validator?" - weightOptions := []string{defaultWeight, "Custom"} + return app.Prompt.CaptureWeight(txt) +} + +func PromptInitialBalance() (uint64, error) { + defaultInitialBalance := fmt.Sprintf("Default (%d) AVAX", constants.MinInitialBalanceBootstrapValidator) + txt := "What initial balance would you like to assign to the bootstrap validator (in AVAX)?" + weightOptions := []string{defaultInitialBalance, "Custom"} weightOption, err := app.Prompt.CaptureList(txt, weightOptions) if err != nil { return 0, err } switch weightOption { - case defaultWeight: - return defaultStake, nil + case defaultInitialBalance: + return constants.MinInitialBalanceBootstrapValidator, nil default: - return app.Prompt.CaptureWeight(txt) + return app.Prompt.CaptureBootstrapInitialBalance(txt) } } func promptValidators() ([]SubnetValidator, error) { - subnetValidators := []SubnetValidator{} + var subnetValidators []SubnetValidator numBootstrapValidators, err := app.Prompt.CaptureInt( - "How many bootstrap validators to set up?", + "How many bootstrap validators do you want to set up?", ) + if err != nil { + return nil, err + } + previousAddr := "" for len(subnetValidators) < numBootstrapValidators { nodeID, err := PromptNodeID() if err != nil { - return err + return nil, err } - weight, err := PromptWeightPrimaryNetwork(network) + weight, err := PromptWeightBootstrapValidator() if err != nil { - return err + return nil, err } - balance, err := PromptBalance() + balance, err := PromptInitialBalance() if err != nil { - return err + return nil, err } - jsonPop, err := promptProofOfPossession() + proofOfPossession, err := promptProofOfPossession() + changeAddr, err := getKeyForChangeOwner(previousAddr) if err != nil { - return err + return nil, err } - popBytes, err := json.Marshal(jsonPop) + addrs, err := address.ParseToIDs([]string{changeAddr}) if err != nil { - return err + return nil, fmt.Errorf("failure parsing change owner address: %w", err) } - var proofOfPossession signer.Signer - pop := &signer.ProofOfPossession{} - err := pop.UnmarshalJSON(popBytes) - if err != nil { - return ids.Empty, err - } - proofOfPossession = pop - changeAddr, err := PromptChangeAddr() - if err != nil { - return err + changeOwner := &secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: addrs, } + previousAddr = changeAddr subnetValidator := SubnetValidator{ NodeID: nodeID, Weight: weight, Balance: balance, Signer: proofOfPossession, - ChangeOwner: changeAddr, + ChangeOwner: changeOwner, } subnetValidators = append(subnetValidators, subnetValidator) } + return subnetValidators, nil +} + +func validateProofOfPossession(publicKey, pop string) { + if publicKey != "" { + err := prompts.ValidateHexa(publicKey) + if err != nil { + ux.Logger.PrintToUser("Format error in given public key: %s", err) + publicKey = "" + } + } + if pop != "" { + err := prompts.ValidateHexa(pop) + if err != nil { + ux.Logger.PrintToUser("Format error in given proof of possession: %s", err) + pop = "" + } + } +} + +func promptProofOfPossession() (signer.Signer, error) { + ux.Logger.PrintToUser("Next, we need the public key and proof of possession of the node's BLS") + ux.Logger.PrintToUser("Check https://docs.avax.network/api-reference/info-api#infogetnodeid for instructions on calling info.getNodeID API") + var err error + txt := "What is the public key of the node's BLS?" + publicKey, err := app.Prompt.CaptureValidatedString(txt, prompts.ValidateHexa) if err != nil { return nil, err } - + txt = "What is the proof of possession of the node's BLS?" + proofOfPossesion, err := app.Prompt.CaptureValidatedString(txt, prompts.ValidateHexa) + if err != nil { + return nil, err + } + var proofOfPossession signer.Signer + pop := &signer.ProofOfPossession{ + PublicKey: [48]byte([]byte(publicKey)), + ProofOfPossession: [96]byte([]byte(proofOfPossesion)), + } + proofOfPossession = pop + return proofOfPossession, nil } // TODO: add explain the difference for different validator management type diff --git a/cmd/blockchaincmd/prompt_owners.go b/cmd/blockchaincmd/prompt_owners.go index a5c87a905..64d7aefd5 100644 --- a/cmd/blockchaincmd/prompt_owners.go +++ b/cmd/blockchaincmd/prompt_owners.go @@ -4,6 +4,8 @@ package blockchaincmd import ( "fmt" + "github.com/ava-labs/avalanche-cli/pkg/networkoptions" + "github.com/ava-labs/avalanche-cli/pkg/utils" "os" "path/filepath" "strconv" @@ -305,3 +307,82 @@ func getThreshold(maxLen int) (uint32, error) { } return uint32(intTh), err } + +func getKeyForChangeOwner(previouslyUsedAddr string) (string, error) { + moreKeysPrompt := "Which key would you like to set as change owner for leftover AVAX if the node is removed from validator set?" + + const ( + getFromStored = "Get address from an existing stored key (created from avalanche key create or avalanche key import)" + custom = "Custom" + ) + previousAddres := fmt.Sprintf("Previously used address %s", previouslyUsedAddr) + + listOptions := []string{getFromStored, custom} + if previouslyUsedAddr != "" { + listOptions = []string{previousAddres, getFromStored, custom} + } + listDecision, err := app.Prompt.CaptureList(moreKeysPrompt, listOptions) + if err != nil { + return "", err + } + + var key string + + switch listDecision { + case previousAddres: + key = previouslyUsedAddr + case getFromStored: + network, err := promptNetwork() + if err != nil { + return "", err + } + key, err = prompts.CaptureKeyAddress( + app.Prompt, + "be set as a change owner for leftover AVAX", + app.GetKeyDir(), + app.GetKey, + network, + prompts.PChainFormat, + ) + if err != nil { + return "", err + } + case custom: + addrPrompt := "Enter change address (P-chain format)" + changeAddr, err := app.Prompt.CaptureAddress(addrPrompt) + if err != nil { + return "", err + } + key = changeAddr.String() + } + if err != nil { + return "", err + } + return key, nil +} + +func promptNetwork() (models.Network, error) { + promptStr := "Choose a network to get the key from" + supportedNetworkOptionsToPrompt := []networkoptions.NetworkOption{networkoptions.Local, networkoptions.Devnet, networkoptions.Fuji, networkoptions.Mainnet} + + networkOptionStr, err := app.Prompt.CaptureList( + promptStr, + utils.Map(supportedNetworkOptionsToPrompt, func(n networkoptions.NetworkOption) string { return n.String() }), + ) + if err != nil { + return models.UndefinedNetwork, err + } + networkOption := networkoptions.NetworkOptionFromString(networkOptionStr) + network := models.UndefinedNetwork + if networkOption == networkoptions.Devnet { + endpoint, err := app.Prompt.CaptureURL(fmt.Sprintf("%s Endpoint", networkOption.String()), false) + if err != nil { + return models.UndefinedNetwork, err + } + network, err = networkOption.ModelNetwork(endpoint) + if err != nil { + return models.UndefinedNetwork, err + } + } + return network, nil +} diff --git a/pkg/networkoptions/network_options.go b/pkg/networkoptions/network_options.go index 9cbef5ec2..3eeb9f394 100644 --- a/pkg/networkoptions/network_options.go +++ b/pkg/networkoptions/network_options.go @@ -46,7 +46,7 @@ func (n NetworkOption) String() string { return "invalid network" } -func networkOptionFromString(s string) NetworkOption { +func NetworkOptionFromString(s string) NetworkOption { switch s { case "Mainnet": return Mainnet @@ -62,6 +62,31 @@ func networkOptionFromString(s string) NetworkOption { return Undefined } +func (n NetworkOption) ModelNetwork(devnetEndpoint string) (models.Network, error) { + network := models.UndefinedNetwork + switch n { + case Local: + network = models.NewLocalNetwork() + case Devnet: + networkID := uint32(0) + if devnetEndpoint != "" { + infoClient := info.NewClient(devnetEndpoint) + ctx, cancel := utils.GetAPIContext() + defer cancel() + _, err := infoClient.GetNetworkID(ctx) + if err != nil { + return models.UndefinedNetwork, err + } + } + network = models.NewDevnetNetwork(devnetEndpoint, networkID) + case Fuji: + network = models.NewFujiNetwork() + case Mainnet: + network = models.NewMainnetNetwork() + } + return network, nil +} + type NetworkFlags struct { UseLocal bool UseDevnet bool @@ -283,7 +308,7 @@ func GetNetworkFromCmdLineFlags( if err != nil { return models.UndefinedNetwork, err } - networkOption = networkOptionFromString(networkOptionStr) + networkOption = NetworkOptionFromString(networkOptionStr) if networkOption == Devnet && !onlyEndpointBasedDevnets && len(clusterNames) != 0 { endpointOptions := []string{ "Get Devnet RPC endpoint from an existing node cluster (created from avalanche node create or avalanche devnet wiz)", diff --git a/pkg/prompts/prompts.go b/pkg/prompts/prompts.go index 91b2540e0..2006eecb5 100644 --- a/pkg/prompts/prompts.go +++ b/pkg/prompts/prompts.go @@ -104,6 +104,7 @@ type Prompter interface { CaptureNodeID(promptStr string) (ids.NodeID, error) CaptureID(promptStr string) (ids.ID, error) CaptureWeight(promptStr string) (uint64, error) + CaptureBootstrapInitialBalance(promptStr string) (uint64, error) CapturePositiveInt(promptStr string, comparators []Comparator) (int, error) CaptureInt(promptStr string) (int, error) CaptureUint32(promptStr string) (uint32, error) @@ -114,7 +115,6 @@ type Prompter interface { CaptureXChainAddress(promptStr string, network models.Network) (string, error) CaptureFutureDate(promptStr string, minDate time.Time) (time.Time, error) ChooseKeyOrLedger(goal string) (bool, error) - CaptureInitialBalances(promptStr string, numValidators int) ([]int, error) } type realPrompter struct{} @@ -266,6 +266,20 @@ func (*realPrompter) CaptureNodeID(promptStr string) (ids.NodeID, error) { return ids.NodeIDFromString(nodeIDStr) } +func (*realPrompter) CaptureBootstrapInitialBalance(promptStr string) (uint64, error) { + prompt := promptui.Prompt{ + Label: promptStr, + Validate: validateBootstrapBalance, + } + + amountStr, err := prompt.Run() + if err != nil { + return 0, err + } + + return strconv.ParseUint(amountStr, 10, 64) +} + func (*realPrompter) CaptureWeight(promptStr string) (uint64, error) { prompt := promptui.Prompt{ Label: promptStr, @@ -484,34 +498,6 @@ func (*realPrompter) CaptureAddresses(promptStr string) ([]common.Address, error return addresses, nil } -func (*realPrompter) CaptureInitialBalances(promptStr string, numValidators int) ([]int, error) { - prompt := promptui.Prompt{ - Label: promptStr, - } - - balanceStr, err := prompt.Run() - if err != nil { - return nil, err - } - - initialBalances := strings.Split(balanceStr, ",") - if len(initialBalances) != numValidators { - return nil, fmt.Errorf("number of initial balances provided does not match number of bootstrap validators") - } - validatorBalances := []int{} - for _, balance := range initialBalances { - if err = validateBootstrapBalance(balance); err != nil { - return nil, err - } - balanceInt, err := strconv.Atoi(balance) - if err != nil { - return nil, err - } - validatorBalances = append(validatorBalances, balanceInt) - } - return validatorBalances, nil -} - func (*realPrompter) CaptureExistingFilepath(promptStr string) (string, error) { prompt := promptui.Prompt{ Label: promptStr, From b12908d3926d16b7596900b663ec55a88853c592 Mon Sep 17 00:00:00 2001 From: Raymond Sukanto Date: Mon, 16 Sep 2024 18:27:16 -0400 Subject: [PATCH 23/64] fix prompt mock --- internal/mocks/prompter.go | 50 ++++++++++++++++++-------------------- 1 file changed, 24 insertions(+), 26 deletions(-) diff --git a/internal/mocks/prompter.go b/internal/mocks/prompter.go index 6cb81ac1c..4d43df3df 100644 --- a/internal/mocks/prompter.go +++ b/internal/mocks/prompter.go @@ -76,6 +76,30 @@ func (_m *Prompter) CaptureAddresses(promptStr string) ([]common.Address, error) return r0, r1 } +// CaptureBootstrapInitialBalance provides a mock function with given fields: promptStr +func (_m *Prompter) CaptureBootstrapInitialBalance(promptStr string) (uint64, error) { + ret := _m.Called(promptStr) + + var r0 uint64 + var r1 error + if rf, ok := ret.Get(0).(func(string) (uint64, error)); ok { + return rf(promptStr) + } + if rf, ok := ret.Get(0).(func(string) uint64); ok { + r0 = rf(promptStr) + } else { + r0 = ret.Get(0).(uint64) + } + + if rf, ok := ret.Get(1).(func(string) error); ok { + r1 = rf(promptStr) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + // CaptureDate provides a mock function with given fields: promptStr func (_m *Prompter) CaptureDate(promptStr string) (time.Time, error) { ret := _m.Called(promptStr) @@ -296,32 +320,6 @@ func (_m *Prompter) CaptureIndex(promptStr string, options []interface{}) (int, return r0, r1 } -// CaptureInitialBalances provides a mock function with given fields: promptStr, numValidators -func (_m *Prompter) CaptureInitialBalances(promptStr string, numValidators int) ([]int, error) { - ret := _m.Called(promptStr, numValidators) - - var r0 []int - var r1 error - if rf, ok := ret.Get(0).(func(string, int) ([]int, error)); ok { - return rf(promptStr, numValidators) - } - if rf, ok := ret.Get(0).(func(string, int) []int); ok { - r0 = rf(promptStr, numValidators) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).([]int) - } - } - - if rf, ok := ret.Get(1).(func(string, int) error); ok { - r1 = rf(promptStr, numValidators) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - // CaptureInt provides a mock function with given fields: promptStr func (_m *Prompter) CaptureInt(promptStr string) (int, error) { ret := _m.Called(promptStr) From 10a0377c3495afb41d5d13abb7841b37e5f6454a Mon Sep 17 00:00:00 2001 From: Raymond Sukanto Date: Mon, 16 Sep 2024 18:32:58 -0400 Subject: [PATCH 24/64] update sidecar --- cmd/blockchaincmd/create.go | 39 ++++++++---------------------- cmd/blockchaincmd/prompt_owners.go | 5 ++-- pkg/models/bootstrap_validator.go | 26 ++++++++++++++++++++ pkg/models/sidecar.go | 2 ++ 4 files changed, 41 insertions(+), 31 deletions(-) create mode 100644 pkg/models/bootstrap_validator.go diff --git a/cmd/blockchaincmd/create.go b/cmd/blockchaincmd/create.go index 63b9c6c73..ba788ef5f 100644 --- a/cmd/blockchaincmd/create.go +++ b/cmd/blockchaincmd/create.go @@ -6,18 +6,17 @@ import ( "encoding/json" "errors" "fmt" - "github.com/ava-labs/avalanche-cli/pkg/prompts" - "github.com/ava-labs/avalanchego/ids" - "github.com/ava-labs/avalanchego/utils/formatting/address" - "github.com/ava-labs/avalanchego/vms/platformvm/fx" - "github.com/ava-labs/avalanchego/vms/platformvm/signer" - "github.com/ava-labs/avalanchego/vms/secp256k1fx" "os" "sort" "strconv" "strings" "unicode" + "github.com/ava-labs/avalanche-cli/pkg/prompts" + "github.com/ava-labs/avalanchego/utils/formatting/address" + "github.com/ava-labs/avalanchego/vms/platformvm/signer" + "github.com/ava-labs/avalanchego/vms/secp256k1fx" + "github.com/ava-labs/avalanche-cli/pkg/application" "github.com/ava-labs/avalanche-cli/cmd/flags" @@ -58,7 +57,7 @@ type CreateFlags struct { validatorManagerMintOnly bool tokenMinterAddress []string validatorManagerController []string - bootstrapValidators []SubnetValidator + bootstrapValidators []models.SubnetValidator } var ( @@ -428,7 +427,7 @@ func createBlockchainConfig(cmd *cobra.Command, args []string) error { } _, err = promptValidators() - //TODO: update subnetvalidators in sidecar + // TODO: update subnetvalidators in sidecar if err = app.CreateSidecar(sc); err != nil { return err @@ -556,24 +555,6 @@ func checkInvalidSubnetNames(name string) error { return nil } -// TODO: replace this object with avalanchego struct SubnetValidator -type SubnetValidator struct { - // Must be Ed25519 NodeID - NodeID ids.NodeID - // Weight of this validator used when sampling - Weight uint64 - // Initial balance for this validator - Balance uint64 - // [Signer] is the BLS key for this validator. - // Note: We do not enforce that the BLS key is unique across all validators. - // This means that validators can share a key if they so choose. - // However, a NodeID + Subnet does uniquely map to a BLS key - Signer signer.Signer - // Leftover $AVAX from the [Balance] will be issued to this - // owner once it is removed from the validator set. - ChangeOwner fx.Owner -} - // TODO: find the min weight for bootstrap validator func PromptWeightBootstrapValidator() (uint64, error) { txt := "What stake weight would you like to assign to the validator?" @@ -597,8 +578,8 @@ func PromptInitialBalance() (uint64, error) { } } -func promptValidators() ([]SubnetValidator, error) { - var subnetValidators []SubnetValidator +func promptValidators() ([]models.SubnetValidator, error) { + var subnetValidators []models.SubnetValidator numBootstrapValidators, err := app.Prompt.CaptureInt( "How many bootstrap validators do you want to set up?", ) @@ -633,7 +614,7 @@ func promptValidators() ([]SubnetValidator, error) { Addrs: addrs, } previousAddr = changeAddr - subnetValidator := SubnetValidator{ + subnetValidator := models.SubnetValidator{ NodeID: nodeID, Weight: weight, Balance: balance, diff --git a/cmd/blockchaincmd/prompt_owners.go b/cmd/blockchaincmd/prompt_owners.go index 64d7aefd5..245f3b8a9 100644 --- a/cmd/blockchaincmd/prompt_owners.go +++ b/cmd/blockchaincmd/prompt_owners.go @@ -4,13 +4,14 @@ package blockchaincmd import ( "fmt" - "github.com/ava-labs/avalanche-cli/pkg/networkoptions" - "github.com/ava-labs/avalanche-cli/pkg/utils" "os" "path/filepath" "strconv" "strings" + "github.com/ava-labs/avalanche-cli/pkg/networkoptions" + "github.com/ava-labs/avalanche-cli/pkg/utils" + "github.com/ava-labs/avalanche-cli/pkg/constants" "github.com/ava-labs/avalanche-cli/pkg/key" "github.com/ava-labs/avalanche-cli/pkg/keychain" diff --git a/pkg/models/bootstrap_validator.go b/pkg/models/bootstrap_validator.go new file mode 100644 index 000000000..65f4fae19 --- /dev/null +++ b/pkg/models/bootstrap_validator.go @@ -0,0 +1,26 @@ +// Copyright (C) 2022, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. +package models + +import ( + "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/vms/platformvm/fx" + "github.com/ava-labs/avalanchego/vms/platformvm/signer" +) + +type SubnetValidator struct { + // Must be Ed25519 NodeID + NodeID ids.NodeID + // Weight of this validator used when sampling + Weight uint64 + // Initial balance for this validator + Balance uint64 + // [Signer] is the BLS key for this validator. + // Note: We do not enforce that the BLS key is unique across all validators. + // This means that validators can share a key if they so choose. + // However, a NodeID + Subnet does uniquely map to a BLS key + Signer signer.Signer + // Leftover $AVAX from the [Balance] will be issued to this + // owner once it is removed from the validator set. + ChangeOwner fx.Owner +} diff --git a/pkg/models/sidecar.go b/pkg/models/sidecar.go index ff09ed6e6..babba8605 100644 --- a/pkg/models/sidecar.go +++ b/pkg/models/sidecar.go @@ -42,6 +42,8 @@ type Sidecar struct { ValidatorManagement ValidatorManagementType ValidatorManagerController []string NewNativeTokenMinter []string + // TODO: replace this object with avalanchego struct SubnetValidator + BootstrapValidators []SubnetValidator } func (sc Sidecar) GetVMID() (string, error) { From 3d6ade0893a07d5f322308cc919668729b58b3ca Mon Sep 17 00:00:00 2001 From: Raymond Sukanto Date: Mon, 16 Sep 2024 19:14:03 -0400 Subject: [PATCH 25/64] update prompts --- cmd/blockchaincmd/add_validator.go | 7 +------ cmd/blockchaincmd/create.go | 9 +++++++++ 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/cmd/blockchaincmd/add_validator.go b/cmd/blockchaincmd/add_validator.go index 794368ed1..1df8f9473 100644 --- a/cmd/blockchaincmd/add_validator.go +++ b/cmd/blockchaincmd/add_validator.go @@ -402,12 +402,7 @@ func promptStart() (time.Time, error) { } func PromptNodeID() (ids.NodeID, error) { - ux.Logger.PrintToUser("Next, we need the NodeID of the validator you want to whitelist.") - ux.Logger.PrintToUser("") - ux.Logger.PrintToUser("Check https://docs.avax.network/apis/avalanchego/apis/info#infogetnodeid for instructions about how to query the NodeID from your node") - ux.Logger.PrintToUser("(Edit host IP address and port to match your deployment, if needed).") - - txt := "What is the NodeID of the validator you'd like to whitelist?" + txt := "What is the NodeID of the node you want to add as bootstrap validator?" return app.Prompt.CaptureNodeID(txt) } diff --git a/cmd/blockchaincmd/create.go b/cmd/blockchaincmd/create.go index ba788ef5f..8f9c31e38 100644 --- a/cmd/blockchaincmd/create.go +++ b/cmd/blockchaincmd/create.go @@ -427,6 +427,9 @@ func createBlockchainConfig(cmd *cobra.Command, args []string) error { } _, err = promptValidators() + if err != nil { + return err + } // TODO: update subnetvalidators in sidecar if err = app.CreateSidecar(sc); err != nil { @@ -588,6 +591,7 @@ func promptValidators() ([]models.SubnetValidator, error) { } previousAddr := "" for len(subnetValidators) < numBootstrapValidators { + ux.Logger.PrintToUser("Getting info for bootstrap validator %d", len(subnetValidators)+1) nodeID, err := PromptNodeID() if err != nil { return nil, err @@ -622,6 +626,11 @@ func promptValidators() ([]models.SubnetValidator, error) { ChangeOwner: changeOwner, } subnetValidators = append(subnetValidators, subnetValidator) + ux.Logger.GreenCheckmarkToUser("Bootstrap Validator %d:", len(subnetValidators)) + ux.Logger.PrintToUser("- Node ID: %s", nodeID) + ux.Logger.PrintToUser("- Weight: %d", weight) + ux.Logger.PrintToUser("- Initial Balance: %d AVAX", balance) + ux.Logger.PrintToUser("- Change Address: %s", changeAddr) } return subnetValidators, nil } From 13955117300648e7872ba33d6385a8264250c8b7 Mon Sep 17 00:00:00 2001 From: Raymond Sukanto Date: Tue, 17 Sep 2024 10:59:44 -0400 Subject: [PATCH 26/64] update prompts --- cmd/blockchaincmd/create.go | 8 ++++---- cmd/blockchaincmd/prompt_owners.go | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/cmd/blockchaincmd/create.go b/cmd/blockchaincmd/create.go index 8f9c31e38..7a00b10fb 100644 --- a/cmd/blockchaincmd/create.go +++ b/cmd/blockchaincmd/create.go @@ -426,11 +426,11 @@ func createBlockchainConfig(cmd *cobra.Command, args []string) error { return err } - _, err = promptValidators() + bootstrapValidators, err := promptBootstrapValidators() if err != nil { return err } - // TODO: update subnetvalidators in sidecar + sc.BootstrapValidators = bootstrapValidators if err = app.CreateSidecar(sc); err != nil { return err @@ -565,7 +565,7 @@ func PromptWeightBootstrapValidator() (uint64, error) { } func PromptInitialBalance() (uint64, error) { - defaultInitialBalance := fmt.Sprintf("Default (%d) AVAX", constants.MinInitialBalanceBootstrapValidator) + defaultInitialBalance := fmt.Sprintf("Default (%d AVAX)", constants.MinInitialBalanceBootstrapValidator) txt := "What initial balance would you like to assign to the bootstrap validator (in AVAX)?" weightOptions := []string{defaultInitialBalance, "Custom"} weightOption, err := app.Prompt.CaptureList(txt, weightOptions) @@ -581,7 +581,7 @@ func PromptInitialBalance() (uint64, error) { } } -func promptValidators() ([]models.SubnetValidator, error) { +func promptBootstrapValidators() ([]models.SubnetValidator, error) { var subnetValidators []models.SubnetValidator numBootstrapValidators, err := app.Prompt.CaptureInt( "How many bootstrap validators do you want to set up?", diff --git a/cmd/blockchaincmd/prompt_owners.go b/cmd/blockchaincmd/prompt_owners.go index 245f3b8a9..deecbb91c 100644 --- a/cmd/blockchaincmd/prompt_owners.go +++ b/cmd/blockchaincmd/prompt_owners.go @@ -363,7 +363,7 @@ func getKeyForChangeOwner(previouslyUsedAddr string) (string, error) { } func promptNetwork() (models.Network, error) { - promptStr := "Choose a network to get the key from" + promptStr := "Choose a network that the bootstrap validators will be validating" supportedNetworkOptionsToPrompt := []networkoptions.NetworkOption{networkoptions.Local, networkoptions.Devnet, networkoptions.Fuji, networkoptions.Mainnet} networkOptionStr, err := app.Prompt.CaptureList( From b8a0a88b3b851d7f503cd300a1f605578e8979a2 Mon Sep 17 00:00:00 2001 From: Raymond Sukanto Date: Tue, 17 Sep 2024 11:04:59 -0400 Subject: [PATCH 27/64] refactor --- cmd/blockchaincmd/create.go | 215 --------------------- cmd/blockchaincmd/prompt_genesis_input.go | 223 ++++++++++++++++++++++ 2 files changed, 223 insertions(+), 215 deletions(-) create mode 100644 cmd/blockchaincmd/prompt_genesis_input.go diff --git a/cmd/blockchaincmd/create.go b/cmd/blockchaincmd/create.go index 7a00b10fb..ec282c593 100644 --- a/cmd/blockchaincmd/create.go +++ b/cmd/blockchaincmd/create.go @@ -12,13 +12,6 @@ import ( "strings" "unicode" - "github.com/ava-labs/avalanche-cli/pkg/prompts" - "github.com/ava-labs/avalanchego/utils/formatting/address" - "github.com/ava-labs/avalanchego/vms/platformvm/signer" - "github.com/ava-labs/avalanchego/vms/secp256k1fx" - - "github.com/ava-labs/avalanche-cli/pkg/application" - "github.com/ava-labs/avalanche-cli/cmd/flags" "github.com/ava-labs/avalanche-cli/pkg/cobrautils" "github.com/ava-labs/avalanche-cli/pkg/constants" @@ -445,57 +438,6 @@ func createBlockchainConfig(cmd *cobra.Command, args []string) error { return nil } -func getValidatorContractManagerAddr() ([]string, bool, error) { - controllerAddrPrompt := "Enter Validator Manager Contract controller address" - for { - // ask in a loop so that if some condition is not met we can keep asking - controlAddr, cancelled, err := getAddrLoop(controllerAddrPrompt, constants.ValidatorManagerController, models.UndefinedNetwork) - if err != nil { - return nil, false, err - } - if cancelled { - return nil, cancelled, nil - } - if len(controlAddr) != 0 { - return controlAddr, false, nil - } - ux.Logger.RedXToUser("An address to control Validator Manage Contract is required before proceeding") - } -} - -// Configure which addresses may make mint new native tokens -func getTokenMinterAddr() ([]string, error) { - addTokenMinterAddrPrompt := "Currently only Validator Manager Contract can mint new native tokens" - ux.Logger.PrintToUser(addTokenMinterAddrPrompt) - yes, err := app.Prompt.CaptureNoYes("Add additional addresses that can mint new native tokens?") - if err != nil { - return nil, err - } - if !yes { - return nil, nil - } - addr, cancelled, err := getAddr() - if err != nil { - return nil, err - } - if cancelled { - return nil, nil - } - return addr, nil -} - -func getAddr() ([]string, bool, error) { - addrPrompt := "Enter addresses that can mint new native tokens" - addr, cancelled, err := getAddrLoop(addrPrompt, constants.TokenMinter, models.UndefinedNetwork) - if err != nil { - return nil, false, err - } - if cancelled { - return nil, cancelled, nil - } - return addr, false, nil -} - func addSubnetEVMGenesisPrefundedAddress(genesisBytes []byte, address string, balance string) ([]byte, error) { var genesisMap map[string]interface{} if err := json.Unmarshal(genesisBytes, &genesisMap); err != nil { @@ -557,160 +499,3 @@ func checkInvalidSubnetNames(name string) error { } return nil } - -// TODO: find the min weight for bootstrap validator -func PromptWeightBootstrapValidator() (uint64, error) { - txt := "What stake weight would you like to assign to the validator?" - return app.Prompt.CaptureWeight(txt) -} - -func PromptInitialBalance() (uint64, error) { - defaultInitialBalance := fmt.Sprintf("Default (%d AVAX)", constants.MinInitialBalanceBootstrapValidator) - txt := "What initial balance would you like to assign to the bootstrap validator (in AVAX)?" - weightOptions := []string{defaultInitialBalance, "Custom"} - weightOption, err := app.Prompt.CaptureList(txt, weightOptions) - if err != nil { - return 0, err - } - - switch weightOption { - case defaultInitialBalance: - return constants.MinInitialBalanceBootstrapValidator, nil - default: - return app.Prompt.CaptureBootstrapInitialBalance(txt) - } -} - -func promptBootstrapValidators() ([]models.SubnetValidator, error) { - var subnetValidators []models.SubnetValidator - numBootstrapValidators, err := app.Prompt.CaptureInt( - "How many bootstrap validators do you want to set up?", - ) - if err != nil { - return nil, err - } - previousAddr := "" - for len(subnetValidators) < numBootstrapValidators { - ux.Logger.PrintToUser("Getting info for bootstrap validator %d", len(subnetValidators)+1) - nodeID, err := PromptNodeID() - if err != nil { - return nil, err - } - weight, err := PromptWeightBootstrapValidator() - if err != nil { - return nil, err - } - balance, err := PromptInitialBalance() - if err != nil { - return nil, err - } - proofOfPossession, err := promptProofOfPossession() - changeAddr, err := getKeyForChangeOwner(previousAddr) - if err != nil { - return nil, err - } - addrs, err := address.ParseToIDs([]string{changeAddr}) - if err != nil { - return nil, fmt.Errorf("failure parsing change owner address: %w", err) - } - changeOwner := &secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: addrs, - } - previousAddr = changeAddr - subnetValidator := models.SubnetValidator{ - NodeID: nodeID, - Weight: weight, - Balance: balance, - Signer: proofOfPossession, - ChangeOwner: changeOwner, - } - subnetValidators = append(subnetValidators, subnetValidator) - ux.Logger.GreenCheckmarkToUser("Bootstrap Validator %d:", len(subnetValidators)) - ux.Logger.PrintToUser("- Node ID: %s", nodeID) - ux.Logger.PrintToUser("- Weight: %d", weight) - ux.Logger.PrintToUser("- Initial Balance: %d AVAX", balance) - ux.Logger.PrintToUser("- Change Address: %s", changeAddr) - } - return subnetValidators, nil -} - -func validateProofOfPossession(publicKey, pop string) { - if publicKey != "" { - err := prompts.ValidateHexa(publicKey) - if err != nil { - ux.Logger.PrintToUser("Format error in given public key: %s", err) - publicKey = "" - } - } - if pop != "" { - err := prompts.ValidateHexa(pop) - if err != nil { - ux.Logger.PrintToUser("Format error in given proof of possession: %s", err) - pop = "" - } - } -} - -func promptProofOfPossession() (signer.Signer, error) { - ux.Logger.PrintToUser("Next, we need the public key and proof of possession of the node's BLS") - ux.Logger.PrintToUser("Check https://docs.avax.network/api-reference/info-api#infogetnodeid for instructions on calling info.getNodeID API") - var err error - txt := "What is the public key of the node's BLS?" - publicKey, err := app.Prompt.CaptureValidatedString(txt, prompts.ValidateHexa) - if err != nil { - return nil, err - } - txt = "What is the proof of possession of the node's BLS?" - proofOfPossesion, err := app.Prompt.CaptureValidatedString(txt, prompts.ValidateHexa) - if err != nil { - return nil, err - } - var proofOfPossession signer.Signer - pop := &signer.ProofOfPossession{ - PublicKey: [48]byte([]byte(publicKey)), - ProofOfPossession: [96]byte([]byte(proofOfPossesion)), - } - proofOfPossession = pop - return proofOfPossession, nil -} - -// TODO: add explain the difference for different validator management type -func promptValidatorManagementType( - app *application.Avalanche, - sidecar *models.Sidecar, -) error { - proofOfAuthorityOption := "Proof of Authority" - proofOfStakeOption := "Proof of Stake" - explainOption := "Explain the difference" - if createFlags.proofOfStake { - sidecar.ValidatorManagement = models.ValidatorManagementTypeFromString(proofOfStakeOption) - return nil - } - if createFlags.proofOfAuthority { - sidecar.ValidatorManagement = models.ValidatorManagementTypeFromString(proofOfAuthorityOption) - return nil - } - options := []string{proofOfAuthorityOption, proofOfStakeOption, explainOption} - var subnetTypeStr string - for { - option, err := app.Prompt.CaptureList( - "Which validator management protocol would you like to use in your blockchain?", - options, - ) - if err != nil { - return err - } - switch option { - case proofOfAuthorityOption: - subnetTypeStr = models.ProofOfAuthority - case proofOfStakeOption: - subnetTypeStr = models.ProofOfStake - case explainOption: - continue - } - break - } - sidecar.ValidatorManagement = models.ValidatorManagementTypeFromString(subnetTypeStr) - return nil -} diff --git a/cmd/blockchaincmd/prompt_genesis_input.go b/cmd/blockchaincmd/prompt_genesis_input.go new file mode 100644 index 000000000..1df05c559 --- /dev/null +++ b/cmd/blockchaincmd/prompt_genesis_input.go @@ -0,0 +1,223 @@ +// Copyright (C) 2022, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. +package blockchaincmd + +import ( + "fmt" + "github.com/ava-labs/avalanche-cli/pkg/application" + "github.com/ava-labs/avalanche-cli/pkg/constants" + "github.com/ava-labs/avalanche-cli/pkg/models" + "github.com/ava-labs/avalanche-cli/pkg/prompts" + "github.com/ava-labs/avalanche-cli/pkg/ux" + "github.com/ava-labs/avalanchego/utils/formatting/address" + "github.com/ava-labs/avalanchego/vms/platformvm/signer" + "github.com/ava-labs/avalanchego/vms/secp256k1fx" +) + +func getValidatorContractManagerAddr() ([]string, bool, error) { + controllerAddrPrompt := "Enter Validator Manager Contract controller address" + for { + // ask in a loop so that if some condition is not met we can keep asking + controlAddr, cancelled, err := getAddrLoop(controllerAddrPrompt, constants.ValidatorManagerController, models.UndefinedNetwork) + if err != nil { + return nil, false, err + } + if cancelled { + return nil, cancelled, nil + } + if len(controlAddr) != 0 { + return controlAddr, false, nil + } + ux.Logger.RedXToUser("An address to control Validator Manage Contract is required before proceeding") + } +} + +// Configure which addresses may make mint new native tokens +func getTokenMinterAddr() ([]string, error) { + addTokenMinterAddrPrompt := "Currently only Validator Manager Contract can mint new native tokens" + ux.Logger.PrintToUser(addTokenMinterAddrPrompt) + yes, err := app.Prompt.CaptureNoYes("Add additional addresses that can mint new native tokens?") + if err != nil { + return nil, err + } + if !yes { + return nil, nil + } + addr, cancelled, err := getAddr() + if err != nil { + return nil, err + } + if cancelled { + return nil, nil + } + return addr, nil +} + +func getAddr() ([]string, bool, error) { + addrPrompt := "Enter addresses that can mint new native tokens" + addr, cancelled, err := getAddrLoop(addrPrompt, constants.TokenMinter, models.UndefinedNetwork) + if err != nil { + return nil, false, err + } + if cancelled { + return nil, cancelled, nil + } + return addr, false, nil +} + +func promptProofOfPossession() (signer.Signer, error) { + ux.Logger.PrintToUser("Next, we need the public key and proof of possession of the node's BLS") + ux.Logger.PrintToUser("Check https://docs.avax.network/api-reference/info-api#infogetnodeid for instructions on calling info.getNodeID API") + var err error + txt := "What is the public key of the node's BLS?" + publicKey, err := app.Prompt.CaptureValidatedString(txt, prompts.ValidateHexa) + if err != nil { + return nil, err + } + txt = "What is the proof of possession of the node's BLS?" + proofOfPossesion, err := app.Prompt.CaptureValidatedString(txt, prompts.ValidateHexa) + if err != nil { + return nil, err + } + var proofOfPossession signer.Signer + pop := &signer.ProofOfPossession{ + PublicKey: [48]byte([]byte(publicKey)), + ProofOfPossession: [96]byte([]byte(proofOfPossesion)), + } + proofOfPossession = pop + return proofOfPossession, nil +} + +// TODO: add explain the difference for different validator management type +func promptValidatorManagementType( + app *application.Avalanche, + sidecar *models.Sidecar, +) error { + proofOfAuthorityOption := "Proof of Authority" + proofOfStakeOption := "Proof of Stake" + explainOption := "Explain the difference" + if createFlags.proofOfStake { + sidecar.ValidatorManagement = models.ValidatorManagementTypeFromString(proofOfStakeOption) + return nil + } + if createFlags.proofOfAuthority { + sidecar.ValidatorManagement = models.ValidatorManagementTypeFromString(proofOfAuthorityOption) + return nil + } + options := []string{proofOfAuthorityOption, proofOfStakeOption, explainOption} + var subnetTypeStr string + for { + option, err := app.Prompt.CaptureList( + "Which validator management protocol would you like to use in your blockchain?", + options, + ) + if err != nil { + return err + } + switch option { + case proofOfAuthorityOption: + subnetTypeStr = models.ProofOfAuthority + case proofOfStakeOption: + subnetTypeStr = models.ProofOfStake + case explainOption: + continue + } + break + } + sidecar.ValidatorManagement = models.ValidatorManagementTypeFromString(subnetTypeStr) + return nil +} + +// TODO: find the min weight for bootstrap validator +func PromptWeightBootstrapValidator() (uint64, error) { + txt := "What stake weight would you like to assign to the validator?" + return app.Prompt.CaptureWeight(txt) +} + +func PromptInitialBalance() (uint64, error) { + defaultInitialBalance := fmt.Sprintf("Default (%d AVAX)", constants.MinInitialBalanceBootstrapValidator) + txt := "What initial balance would you like to assign to the bootstrap validator (in AVAX)?" + weightOptions := []string{defaultInitialBalance, "Custom"} + weightOption, err := app.Prompt.CaptureList(txt, weightOptions) + if err != nil { + return 0, err + } + + switch weightOption { + case defaultInitialBalance: + return constants.MinInitialBalanceBootstrapValidator, nil + default: + return app.Prompt.CaptureBootstrapInitialBalance(txt) + } +} + +func promptBootstrapValidators() ([]models.SubnetValidator, error) { + var subnetValidators []models.SubnetValidator + numBootstrapValidators, err := app.Prompt.CaptureInt( + "How many bootstrap validators do you want to set up?", + ) + if err != nil { + return nil, err + } + previousAddr := "" + for len(subnetValidators) < numBootstrapValidators { + ux.Logger.PrintToUser("Getting info for bootstrap validator %d", len(subnetValidators)+1) + nodeID, err := PromptNodeID() + if err != nil { + return nil, err + } + weight, err := PromptWeightBootstrapValidator() + if err != nil { + return nil, err + } + balance, err := PromptInitialBalance() + if err != nil { + return nil, err + } + proofOfPossession, err := promptProofOfPossession() + changeAddr, err := getKeyForChangeOwner(previousAddr) + if err != nil { + return nil, err + } + addrs, err := address.ParseToIDs([]string{changeAddr}) + if err != nil { + return nil, fmt.Errorf("failure parsing change owner address: %w", err) + } + changeOwner := &secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: addrs, + } + previousAddr = changeAddr + subnetValidator := models.SubnetValidator{ + NodeID: nodeID, + Weight: weight, + Balance: balance, + Signer: proofOfPossession, + ChangeOwner: changeOwner, + } + subnetValidators = append(subnetValidators, subnetValidator) + ux.Logger.GreenCheckmarkToUser("Bootstrap Validator %d:", len(subnetValidators)) + ux.Logger.PrintToUser("- Node ID: %s", nodeID) + ux.Logger.PrintToUser("- Weight: %d", weight) + ux.Logger.PrintToUser("- Initial Balance: %d AVAX", balance) + ux.Logger.PrintToUser("- Change Address: %s", changeAddr) + } + return subnetValidators, nil +} + +func validateProofOfPossession(publicKey, pop string) { + if publicKey != "" { + err := prompts.ValidateHexa(publicKey) + if err != nil { + ux.Logger.PrintToUser("Format error in given public key: %s", err) + publicKey = "" + } + } + if pop != "" { + err := prompts.ValidateHexa(pop) + if err != nil { + ux.Logger.PrintToUser("Format error in given proof of possession: %s", err) + pop = "" + } + } +} From e2757a74d3b9d5e72254964b0814e2c7a1f7eeee Mon Sep 17 00:00:00 2001 From: Felipe Madero Date: Tue, 17 Sep 2024 11:48:09 -0400 Subject: [PATCH 28/64] nit --- pkg/contract/allocations.go | 36 +++++++++++++++++ pkg/subnet/local.go | 67 ++++++++++++++++++------------- pkg/teleporter/genesis/genesis.go | 25 ++++++++++-- 3 files changed, 95 insertions(+), 33 deletions(-) diff --git a/pkg/contract/allocations.go b/pkg/contract/allocations.go index 84b810bc2..f4514628e 100644 --- a/pkg/contract/allocations.go +++ b/pkg/contract/allocations.go @@ -235,3 +235,39 @@ func GetEVMSubnetGenesisNativeMinterAdmin( } return getGenesisNativeMinterAdmin(app, network, genesisData) } + +func ContractAddressIsInBlockchainGenesis( + app *application.Avalanche, + network models.Network, + chainSpec ChainSpec, + contractAddress common.Address, +) (bool, error) { + genesisData, err := GetBlockchainGenesis( + app, + network, + chainSpec, + ) + if err != nil { + return false, err + } + if !utils.ByteSliceIsSubnetEvmGenesis(genesisData) { + return false, fmt.Errorf("checking for contract belonging to genesis is only supported on EVM based vms") + } + return ContractAddressIsInGenesisData(genesisData, contractAddress) +} + +func ContractAddressIsInGenesisData( + genesisData []byte, + contractAddress common.Address, +) (bool, error) { + genesis, err := utils.ByteSliceToSubnetEvmGenesis(genesisData) + if err != nil { + return false, err + } + for address, allocation := range genesis.Alloc { + if address == contractAddress { + return len(allocation.Code) > 0, nil + } + } + return false, nil +} diff --git a/pkg/subnet/local.go b/pkg/subnet/local.go index d3b0f6e39..832853f20 100644 --- a/pkg/subnet/local.go +++ b/pkg/subnet/local.go @@ -101,7 +101,7 @@ type DeployInfo struct { // * it checks the gRPC is running, if not, it starts it // * kicks off the actual deployment func (d *LocalDeployer) DeployToLocalNetwork( - chain string, + blockchainName string, genesisPath string, icmSpec ICMSpec, subnetIDStr string, @@ -109,7 +109,7 @@ func (d *LocalDeployer) DeployToLocalNetwork( if err := d.StartServer(); err != nil { return nil, err } - return d.doDeploy(chain, genesisPath, icmSpec, subnetIDStr) + return d.doDeploy(blockchainName, genesisPath, icmSpec, subnetIDStr) } func (d *LocalDeployer) StartServer() error { @@ -153,7 +153,7 @@ func (d *LocalDeployer) BackendStartedHere() bool { // - deploy a new blockchain for the given VM ID, genesis, and available subnet ID // - waits completion of operation // - show status -func (d *LocalDeployer) doDeploy(chain string, genesisPath string, icmSpec ICMSpec, subnetIDStr string) (*DeployInfo, error) { +func (d *LocalDeployer) doDeploy(blockchainName string, genesisPath string, icmSpec ICMSpec, subnetIDStr string) (*DeployInfo, error) { needsRestart, avalancheGoBinPath, err := d.SetupLocalEnv() if err != nil { return nil, err @@ -176,7 +176,7 @@ func (d *LocalDeployer) doDeploy(chain string, genesisPath string, icmSpec ICMSp defer cancel() // loading sidecar before it's needed so we catch any error early - sc, err := d.app.LoadSidecar(chain) + sc, err := d.app.LoadSidecar(blockchainName) if err != nil { return nil, fmt.Errorf("failed to load sidecar: %w", err) } @@ -194,9 +194,9 @@ func (d *LocalDeployer) doDeploy(chain string, genesisPath string, icmSpec ICMSp } } - chainVMID, err := anrutils.VMID(chain) + chainVMID, err := anrutils.VMID(blockchainName) if err != nil { - return nil, fmt.Errorf("failed to create VM ID from %s: %w", chain, err) + return nil, fmt.Errorf("failed to create VM ID from %s: %w", blockchainName, err) } d.app.Log.Debug("this VM will get ID", zap.String("vm-id", chainVMID.String())) @@ -255,7 +255,7 @@ func (d *LocalDeployer) doDeploy(chain string, genesisPath string, icmSpec ICMSp logRootDir = clusterInfo.GetLogRootDir() if alreadyDeployed(chainVMID, clusterInfo) { - return nil, fmt.Errorf("subnet %s has already been deployed", chain) + return nil, fmt.Errorf("subnet %s has already been deployed", blockchainName) } numBlockchains := len(clusterInfo.CustomChains) @@ -280,11 +280,11 @@ func (d *LocalDeployer) doDeploy(chain string, genesisPath string, icmSpec ICMSp // if a chainConfig has been configured var ( chainConfig string - chainConfigFile = filepath.Join(d.app.GetSubnetDir(), chain, constants.ChainConfigFileName) + chainConfigFile = filepath.Join(d.app.GetSubnetDir(), blockchainName, constants.ChainConfigFileName) perNodeChainConfig string - perNodeChainConfigFile = filepath.Join(d.app.GetSubnetDir(), chain, constants.PerNodeChainConfigFileName) + perNodeChainConfigFile = filepath.Join(d.app.GetSubnetDir(), blockchainName, constants.PerNodeChainConfigFileName) subnetConfig string - subnetConfigFile = filepath.Join(d.app.GetSubnetDir(), chain, constants.SubnetConfigFileName) + subnetConfigFile = filepath.Join(d.app.GetSubnetDir(), blockchainName, constants.SubnetConfigFileName) ) if _, err := os.Stat(chainConfigFile); err == nil { // currently the ANR only accepts the file as a path, not its content @@ -309,14 +309,14 @@ func (d *LocalDeployer) doDeploy(chain string, genesisPath string, icmSpec ICMSp // the given VM ID, genesis, and available subnet ID blockchainSpecs := []*rpcpb.BlockchainSpec{ { - VmName: chain, + VmName: blockchainName, Genesis: genesisPath, SubnetId: &subnetIDStr, SubnetSpec: &rpcpb.SubnetSpec{ SubnetConfig: subnetConfig, }, ChainConfig: chainConfig, - BlockchainAlias: chain, + BlockchainAlias: blockchainName, PerNodeChainConfig: perNodeChainConfig, }, } @@ -426,40 +426,49 @@ func (d *LocalDeployer) doDeploy(chain string, genesisPath string, icmSpec ICMSp } // deploy current blockchain ux.Logger.PrintToUser("") - subnetID, blockchainID, err := utils.GetChainIDs(network.Endpoint, chain) + subnetID, blockchainID, err := utils.GetChainIDs(network.Endpoint, blockchainName) if err != nil { return nil, err } - teleporterKeyName := sc.TeleporterKey - if teleporterKeyName == "" { - genesisData, err := d.app.LoadRawGenesis(chain) + blockchainKeyName := sc.TeleporterKey + if blockchainKeyName == "" { + genesisData, err := d.app.LoadRawGenesis(blockchainName) if err != nil { return nil, err } - teleporterKeyName, _, _, err = GetSubnetAirdropKeyInfo(d.app, network, chain, genesisData) + blockchainKeyName, _, _, err = GetSubnetAirdropKeyInfo(d.app, network, blockchainName, genesisData) if err != nil { return nil, err } } - blockchainKey, err := key.LoadSoft(network.ID, d.app.GetKeyPath(teleporterKeyName)) + blockchainKey, err := key.LoadSoft(network.ID, d.app.GetKeyPath(blockchainKeyName)) if err != nil { return nil, err } - var alreadyDeployed bool - alreadyDeployed, icmMessengerAddress, icmRegistryAddress, err = icmd.Deploy( - chain, - network.BlockchainEndpoint(blockchainID), - blockchainKey.PrivKeyHex(), - true, - true, - false, - ) + genesisData, err := os.ReadFile(genesisPath) + if err != nil { + return nil, err + } + includedInGenesis, err := icmgenesis.GenesisIsICMEnabled(genesisData) if err != nil { return nil, err } - if alreadyDeployed { - // included in genesis + if includedInGenesis { + ux.Logger.PrintToUser("Teleporter Messenger and Registry already included in %s's Genesis", blockchainName) + icmMessengerAddress = icmgenesis.MessengerContractAddress icmRegistryAddress = icmgenesis.RegistryContractAddress + } else { + _, icmMessengerAddress, icmRegistryAddress, err = icmd.Deploy( + blockchainName, + network.BlockchainEndpoint(blockchainID), + blockchainKey.PrivKeyHex(), + true, + true, + false, + ) + if err != nil { + return nil, err + } } if sc.RunRelayer && !icmSpec.SkipRelayerDeploy { if !cchainAlreadyDeployed { diff --git a/pkg/teleporter/genesis/genesis.go b/pkg/teleporter/genesis/genesis.go index 67e005549..173dce242 100644 --- a/pkg/teleporter/genesis/genesis.go +++ b/pkg/teleporter/genesis/genesis.go @@ -9,6 +9,9 @@ import ( "math/big" "strings" + "github.com/ava-labs/avalanche-cli/pkg/application" + "github.com/ava-labs/avalanche-cli/pkg/contract" + "github.com/ava-labs/avalanche-cli/pkg/models" "github.com/ava-labs/subnet-evm/core" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/crypto" @@ -16,7 +19,7 @@ import ( const ( messengerVersion = "0x1" - messengerContractAddress = "0x253b2784c75e510dD0fF1da844684a1aC0aa5fcf" + MessengerContractAddress = "0x253b2784c75e510dD0fF1da844684a1aC0aa5fcf" RegistryContractAddress = "0xF86Cb19Ad8405AEFa7d09C778215D2Cb6eBfB228" MessengerDeployerAddress = "0x618FEdD9A45a8C456812ecAAE70C671c6249DfaC" ) @@ -71,7 +74,7 @@ func AddICMMessengerContractToAllocations( setSimpleStorageValue(storage, blockchainIDSlot, "0x1") setSimpleStorageValue(storage, messageNonceSlot, "0x1") deployedMessengerBytes := common.FromHex(strings.TrimSpace(string(deployedMessengerBytecode))) - allocs[common.HexToAddress(messengerContractAddress)] = core.GenesisAccount{ + allocs[common.HexToAddress(MessengerContractAddress)] = core.GenesisAccount{ Balance: big.NewInt(0), Code: deployedMessengerBytes, Storage: storage, @@ -93,10 +96,10 @@ func AddICMRegistryContractToAllocations( ) storage := map[common.Hash]common.Hash{} setSimpleStorageValue(storage, latestVersionSlot, messengerVersion) - if err := setMappingStorageValue(storage, versionToAddressSlot, messengerVersion, messengerContractAddress); err != nil { + if err := setMappingStorageValue(storage, versionToAddressSlot, messengerVersion, MessengerContractAddress); err != nil { return err } - if err := setMappingStorageValue(storage, addressToVersionSlot, messengerContractAddress, messengerVersion); err != nil { + if err := setMappingStorageValue(storage, addressToVersionSlot, MessengerContractAddress, messengerVersion); err != nil { return err } deployedRegistryBytes := common.FromHex(strings.TrimSpace(string(deployedRegistryBytecode))) @@ -108,3 +111,17 @@ func AddICMRegistryContractToAllocations( } return nil } + +func BlockchainHasICMEnabledGenesis( + app *application.Avalanche, + network models.Network, + chainSpec contract.ChainSpec, +) (bool, error) { + return contract.ContractAddressIsInBlockchainGenesis(app, network, chainSpec, common.HexToAddress(MessengerContractAddress)) +} + +func GenesisIsICMEnabled( + genesisData []byte, +) (bool, error) { + return contract.ContractAddressIsInGenesisData(genesisData, common.HexToAddress(MessengerContractAddress)) +} From 7d829d77525e34a15e546f9e48e7c23a1e3f79f5 Mon Sep 17 00:00:00 2001 From: Raymond Sukanto Date: Wed, 18 Sep 2024 14:57:47 -0400 Subject: [PATCH 29/64] update prompts --- cmd/blockchaincmd/create.go | 51 +++++++---- cmd/blockchaincmd/prompt_genesis_input.go | 104 ++++++++++++++++++---- pkg/models/bootstrap_validator.go | 18 ++++ 3 files changed, 142 insertions(+), 31 deletions(-) diff --git a/cmd/blockchaincmd/create.go b/cmd/blockchaincmd/create.go index ec282c593..e42a402bd 100644 --- a/cmd/blockchaincmd/create.go +++ b/cmd/blockchaincmd/create.go @@ -54,11 +54,12 @@ type CreateFlags struct { } var ( - createFlags CreateFlags - forceCreate bool - genesisFile string - vmFile string - useRepo bool + createFlags CreateFlags + forceCreate bool + genesisFile string + vmFile string + useRepo bool + bootstrapValidatorsJSONFilePath string errIllegalNameCharacter = errors.New( "illegal name character: only letters, no special characters allowed") @@ -115,6 +116,7 @@ configuration, pass the -f flag.`, cmd.Flags().BoolVar(&createFlags.validatorManagerMintOnly, "validator-manager-mint-only", false, "only enable validator manager contract to mint new native tokens") cmd.Flags().StringSliceVar(&createFlags.tokenMinterAddress, "token-minter-address", nil, "addresses that can mint new native tokens (for proof of authority validator management only)") cmd.Flags().StringSliceVar(&createFlags.validatorManagerController, "validator-manager-controller", nil, "addresses that will control Validator Manager contract") + cmd.Flags().StringVar(&bootstrapValidatorsJSONFilePath, "bootstrap-filepath", "", "JSON file path that provides details about bootstrap validators") return cmd } @@ -217,13 +219,14 @@ func createBlockchainConfig(cmd *cobra.Command, args []string) error { } } - //if len(createFlags.bootstrapValidatorInitialBalance) > 0 { - // for _, balance := range createFlags.bootstrapValidatorInitialBalance { - // if balance < constants.MinInitialBalanceBootstrapValidator { - // return fmt.Errorf("initial bootstrap validator balance must be at least %d AVAX", constants.MinInitialBalanceBootstrapValidator) - // } - // } - //} + var bootstrapValidators []models.SubnetValidator + var err error + if bootstrapValidatorsJSONFilePath != "" { + bootstrapValidators, err = LoadBootstrapValidator(bootstrapValidatorsJSONFilePath) + if err != nil { + return err + } + } // get vm kind vmType, err := vm.PromptVMType(app, createFlags.useSubnetEvm, createFlags.useCustomVM) @@ -419,9 +422,11 @@ func createBlockchainConfig(cmd *cobra.Command, args []string) error { return err } - bootstrapValidators, err := promptBootstrapValidators() - if err != nil { - return err + if bootstrapValidatorsJSONFilePath == "" { + bootstrapValidators, err = promptBootstrapValidators() + if err != nil { + return err + } } sc.BootstrapValidators = bootstrapValidators @@ -499,3 +504,19 @@ func checkInvalidSubnetNames(name string) error { } return nil } + +func LoadBootstrapValidator(filepath string) ([]models.SubnetValidator, error) { + jsonBytes, err := os.ReadFile(filepath) + if err != nil { + return nil, err + } + var subnetValidatorsJSON []models.SubnetValidatorJSON + if err = json.Unmarshal(jsonBytes, &subnetValidatorsJSON); err != nil { + return nil, err + } + subnetValidators, err := convertToSubnetValidators(subnetValidatorsJSON) + if err != nil { + return nil, err + } + return subnetValidators, nil +} diff --git a/cmd/blockchaincmd/prompt_genesis_input.go b/cmd/blockchaincmd/prompt_genesis_input.go index 1df05c559..d49dec1dc 100644 --- a/cmd/blockchaincmd/prompt_genesis_input.go +++ b/cmd/blockchaincmd/prompt_genesis_input.go @@ -3,12 +3,14 @@ package blockchaincmd import ( + "encoding/json" "fmt" "github.com/ava-labs/avalanche-cli/pkg/application" "github.com/ava-labs/avalanche-cli/pkg/constants" "github.com/ava-labs/avalanche-cli/pkg/models" "github.com/ava-labs/avalanche-cli/pkg/prompts" "github.com/ava-labs/avalanche-cli/pkg/ux" + "github.com/ava-labs/avalanchego/ids" "github.com/ava-labs/avalanchego/utils/formatting/address" "github.com/ava-labs/avalanchego/vms/platformvm/signer" "github.com/ava-labs/avalanchego/vms/secp256k1fx" @@ -79,13 +81,11 @@ func promptProofOfPossession() (signer.Signer, error) { if err != nil { return nil, err } - var proofOfPossession signer.Signer - pop := &signer.ProofOfPossession{ - PublicKey: [48]byte([]byte(publicKey)), - ProofOfPossession: [96]byte([]byte(proofOfPossesion)), + pop, err := getBLSInfo(publicKey, proofOfPossesion) + if err != nil { + return nil, err } - proofOfPossession = pop - return proofOfPossession, nil + return pop, nil } // TODO: add explain the difference for different validator management type @@ -205,19 +205,91 @@ func promptBootstrapValidators() ([]models.SubnetValidator, error) { return subnetValidators, nil } -func validateProofOfPossession(publicKey, pop string) { - if publicKey != "" { - err := prompts.ValidateHexa(publicKey) +func validateBLS(publicKey, pop string) error { + if err := prompts.ValidateHexa(publicKey); err != nil { + return fmt.Errorf("format error in given public key: %s", err) + } + if err := prompts.ValidateHexa(pop); err != nil { + return fmt.Errorf("format error in given proof of possession: %s", err) + } + return nil +} + +func getBLSInfo(publicKey, proofOfPossesion string) (signer.Signer, error) { + type jsonProofOfPossession struct { + PublicKey string + ProofOfPossession string + } + jsonPop := jsonProofOfPossession{ + PublicKey: publicKey, + ProofOfPossession: proofOfPossesion, + } + popBytes, err := json.Marshal(jsonPop) + if err != nil { + return nil, err + } + pop := &signer.ProofOfPossession{} + err = pop.UnmarshalJSON(popBytes) + if err != nil { + return nil, err + } + return pop, nil +} + +func convertToSubnetValidators(validatorJSONS []models.SubnetValidatorJSON) ([]models.SubnetValidator, error) { + subnetValidators := []models.SubnetValidator{} + type jsonProofOfPossession struct { + PublicKey string + ProofOfPossession string + } + for _, validatorJSON := range validatorJSONS { + nodeID, err := ids.NodeIDFromString(validatorJSON.NodeID) if err != nil { - ux.Logger.PrintToUser("Format error in given public key: %s", err) - publicKey = "" + return nil, fmt.Errorf("invalid node id %s", validatorJSON.NodeID) } - } - if pop != "" { - err := prompts.ValidateHexa(pop) + if validatorJSON.Weight <= 0 { + return nil, fmt.Errorf("bootstrap validator weight has to be greater than 0") + } + if validatorJSON.Balance <= 0 { + return nil, fmt.Errorf("bootstrap validator balance has to be greater than 0") + } + if err = validateBLS(validatorJSON.BLSPublicKey, validatorJSON.BLSProofOfPossession); err != nil { + return nil, err + } + //jsonPop := jsonProofOfPossession{ + // PublicKey: validatorJSON.BLSPublicKey, + // ProofOfPossession: validatorJSON.BLSProofOfPossession, + //} + //popBytes, err := json.Marshal(jsonPop) + //if err != nil { + // return nil, err + //} + //pop := &signer.ProofOfPossession{} + //err = pop.UnmarshalJSON(popBytes) + //if err != nil { + // return nil, err + //} + pop, err := getBLSInfo(validatorJSON.BLSPublicKey, validatorJSON.BLSProofOfPossession) + if err != nil { + return nil, err + } + changeAddr, err := ids.ShortFromString(validatorJSON.ChangeOwnerAddr) if err != nil { - ux.Logger.PrintToUser("Format error in given proof of possession: %s", err) - pop = "" + return nil, err + } + changeOwner := &secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{changeAddr}, } + subnetValidators = append(subnetValidators, + models.SubnetValidator{ + NodeID: nodeID, + Weight: validatorJSON.Weight, + Balance: validatorJSON.Balance, + Signer: pop, + ChangeOwner: changeOwner, + }, + ) } + return subnetValidators, nil } diff --git a/pkg/models/bootstrap_validator.go b/pkg/models/bootstrap_validator.go index 65f4fae19..7f36417b8 100644 --- a/pkg/models/bootstrap_validator.go +++ b/pkg/models/bootstrap_validator.go @@ -11,16 +11,34 @@ import ( type SubnetValidator struct { // Must be Ed25519 NodeID NodeID ids.NodeID + // Weight of this validator used when sampling Weight uint64 + // Initial balance for this validator Balance uint64 + // [Signer] is the BLS key for this validator. // Note: We do not enforce that the BLS key is unique across all validators. // This means that validators can share a key if they so choose. // However, a NodeID + Subnet does uniquely map to a BLS key Signer signer.Signer + // Leftover $AVAX from the [Balance] will be issued to this // owner once it is removed from the validator set. ChangeOwner fx.Owner } + +type SubnetValidatorJSON struct { + NodeID string `json:"NodeID"` + + Weight uint64 `json:"Weight"` + + Balance uint64 `json:"Balance"` + + BLSPublicKey string `json:"BLSPublicKey"` + + BLSProofOfPossession string `json:"BLSProofOfPossession"` + + ChangeOwnerAddr string `json:"ChangeOwnerAddr"` +} From 5cd3e1633e5ea8f536e0869913b1ab10cecc0954 Mon Sep 17 00:00:00 2001 From: Felipe Madero Date: Wed, 18 Sep 2024 15:32:10 -0400 Subject: [PATCH 30/64] fix wiz stuff --- cmd/blockchaincmd/create.go | 6 ++++++ cmd/nodecmd/wiz.go | 1 + cmd/teleportercmd/deploy.go | 4 +++- pkg/subnet/local.go | 21 ++++++++++++++++++--- pkg/teleporter/genesis/genesis.go | 24 ++++++++++++++++++------ pkg/vm/create_evm.go | 12 +++++++++--- 6 files changed, 55 insertions(+), 13 deletions(-) diff --git a/cmd/blockchaincmd/create.go b/cmd/blockchaincmd/create.go index 07ee0835d..b4b325005 100644 --- a/cmd/blockchaincmd/create.go +++ b/cmd/blockchaincmd/create.go @@ -45,6 +45,8 @@ type CreateFlags struct { useLatestReleasedVMVersion bool useLatestPreReleasedVMVersion bool useExternalGasToken bool + addICMMessengerToGenesis bool + addICMRegistryToGenesis bool } var ( @@ -101,6 +103,8 @@ configuration, pass the -f flag.`, cmd.Flags().BoolVar(&createFlags.useWarp, "warp", true, "generate a vm with warp support (needed for teleporter)") cmd.Flags().BoolVar(&createFlags.useTeleporter, "teleporter", false, "interoperate with other blockchains using teleporter") cmd.Flags().BoolVar(&createFlags.useExternalGasToken, "external-gas-token", false, "use a gas token from another blockchain") + cmd.Flags().BoolVar(&createFlags.addICMMessengerToGenesis, "icm-messenger-at-genesis", false, "setup ICM messenger smart contract on genesis") + cmd.Flags().BoolVar(&createFlags.addICMRegistryToGenesis, "icm-registry-at-genesis", false, "setup ICM registry smart contract on genesis") return cmd } @@ -279,6 +283,8 @@ func createBlockchainConfig(cmd *cobra.Command, args []string) error { blockchainName, params, teleporterInfo, + createFlags.addICMMessengerToGenesis, + createFlags.addICMRegistryToGenesis, ) if err != nil { return err diff --git a/cmd/nodecmd/wiz.go b/cmd/nodecmd/wiz.go index d50ccf5db..2d42bf278 100644 --- a/cmd/nodecmd/wiz.go +++ b/cmd/nodecmd/wiz.go @@ -394,6 +394,7 @@ func wiz(cmd *cobra.Command, args []string) error { }, DeployMessenger: deployTeleporterMessenger, DeployRegistry: deployTeleporterRegistry, + ForceRegistryDeploy: true, Version: teleporterVersion, MessengerContractAddressPath: teleporterMessengerContractAddressPath, MessengerDeployerAddressPath: teleporterMessengerDeployerAddressPath, diff --git a/cmd/teleportercmd/deploy.go b/cmd/teleportercmd/deploy.go index e9b516860..2671b16a1 100644 --- a/cmd/teleportercmd/deploy.go +++ b/cmd/teleportercmd/deploy.go @@ -25,6 +25,7 @@ type DeployFlags struct { GenesisKey bool DeployMessenger bool DeployRegistry bool + ForceRegistryDeploy bool RPCURL string Version string MessengerContractAddressPath string @@ -62,6 +63,7 @@ func newDeployCmd() *cobra.Command { deployFlags.ChainFlags.AddToCmd(cmd, "deploy ICM", true) cmd.Flags().BoolVar(&deployFlags.DeployMessenger, "deploy-messenger", true, "deploy Teleporter Messenger") cmd.Flags().BoolVar(&deployFlags.DeployRegistry, "deploy-registry", true, "deploy Teleporter Registry") + cmd.Flags().BoolVar(&deployFlags.ForceRegistryDeploy, "force-registry-deploy", false, "deploy Teleporter Registry even if Messenger has already been deployed") cmd.Flags().StringVar(&deployFlags.RPCURL, "rpc-url", "", "use the given RPC URL to connect to the subnet") cmd.Flags().StringVar(&deployFlags.Version, "version", "latest", "version to deploy") cmd.Flags().StringVar(&deployFlags.MessengerContractAddressPath, "messenger-contract-address-path", "", "path to a messenger contract address file") @@ -188,7 +190,7 @@ func CallDeploy(_ []string, flags DeployFlags) error { privateKey, flags.DeployMessenger, flags.DeployRegistry, - false, + flags.ForceRegistryDeploy, ) if err != nil { return err diff --git a/pkg/subnet/local.go b/pkg/subnet/local.go index 832853f20..0e420d3c1 100644 --- a/pkg/subnet/local.go +++ b/pkg/subnet/local.go @@ -449,15 +449,30 @@ func (d *LocalDeployer) doDeploy(blockchainName string, genesisPath string, icmS if err != nil { return nil, err } - includedInGenesis, err := icmgenesis.GenesisIsICMEnabled(genesisData) + messengerAtGenesis, registryAtGenesis, err := icmgenesis.ICMAtGenesis(genesisData) if err != nil { return nil, err } - if includedInGenesis { + switch { + case registryAtGenesis: ux.Logger.PrintToUser("Teleporter Messenger and Registry already included in %s's Genesis", blockchainName) icmMessengerAddress = icmgenesis.MessengerContractAddress icmRegistryAddress = icmgenesis.RegistryContractAddress - } else { + case messengerAtGenesis: + ux.Logger.PrintToUser("Teleporter Messenger already included in %s's Genesis", blockchainName) + icmMessengerAddress = icmgenesis.MessengerContractAddress + _, _, icmRegistryAddress, err = icmd.Deploy( + blockchainName, + network.BlockchainEndpoint(blockchainID), + blockchainKey.PrivKeyHex(), + false, + true, + false, + ) + if err != nil { + return nil, err + } + default: _, icmMessengerAddress, icmRegistryAddress, err = icmd.Deploy( blockchainName, network.BlockchainEndpoint(blockchainID), diff --git a/pkg/teleporter/genesis/genesis.go b/pkg/teleporter/genesis/genesis.go index 173dce242..2ac58abf0 100644 --- a/pkg/teleporter/genesis/genesis.go +++ b/pkg/teleporter/genesis/genesis.go @@ -112,16 +112,28 @@ func AddICMRegistryContractToAllocations( return nil } -func BlockchainHasICMEnabledGenesis( +func ICMAtBlockchainGenesis( app *application.Avalanche, network models.Network, chainSpec contract.ChainSpec, -) (bool, error) { - return contract.ContractAddressIsInBlockchainGenesis(app, network, chainSpec, common.HexToAddress(MessengerContractAddress)) +) (bool, bool, error) { + genesisData, err := contract.GetBlockchainGenesis(app, network, chainSpec) + if err != nil { + return false, false, err + } + return ICMAtGenesis(genesisData) } -func GenesisIsICMEnabled( +func ICMAtGenesis( genesisData []byte, -) (bool, error) { - return contract.ContractAddressIsInGenesisData(genesisData, common.HexToAddress(MessengerContractAddress)) +) (bool, bool, error) { + messengerAtGenesis, err := contract.ContractAddressIsInGenesisData(genesisData, common.HexToAddress(MessengerContractAddress)) + if err != nil { + return false, false, err + } + registryAtGenesis, err := contract.ContractAddressIsInGenesisData(genesisData, common.HexToAddress(RegistryContractAddress)) + if err != nil { + return false, false, err + } + return messengerAtGenesis, registryAtGenesis, nil } diff --git a/pkg/vm/create_evm.go b/pkg/vm/create_evm.go index e7ee10d71..866d26432 100644 --- a/pkg/vm/create_evm.go +++ b/pkg/vm/create_evm.go @@ -76,6 +76,8 @@ func CreateEVMGenesis( blockchainName string, params SubnetEVMGenesisParams, teleporterInfo *teleporter.Info, + addICMMessengerToGenesis bool, + addICMRegistryToGenesis bool, ) ([]byte, error) { ux.Logger.PrintToUser("creating genesis for blockchain %s", blockchainName) @@ -104,9 +106,13 @@ func CreateEVMGenesis( params.initialTokenAllocation[common.HexToAddress(teleporterInfo.FundedAddress)] = core.GenesisAccount{ Balance: balance, } - icmgenesis.AddICMMessengerContractToAllocations(params.initialTokenAllocation) - if err := icmgenesis.AddICMRegistryContractToAllocations(params.initialTokenAllocation); err != nil { - return nil, err + if addICMMessengerToGenesis || addICMRegistryToGenesis { + icmgenesis.AddICMMessengerContractToAllocations(params.initialTokenAllocation) + if addICMRegistryToGenesis { + if err := icmgenesis.AddICMRegistryContractToAllocations(params.initialTokenAllocation); err != nil { + return nil, err + } + } } } From 4cbe6e74c8563d52b3a6056afbbec3892647efca Mon Sep 17 00:00:00 2001 From: Raymond Sukanto Date: Wed, 18 Sep 2024 15:33:11 -0400 Subject: [PATCH 31/64] update prompts --- cmd/blockchaincmd/create.go | 7 +- cmd/blockchaincmd/prompt_genesis_input.go | 90 +++++------------------ pkg/models/bootstrap_validator.go | 27 ------- 3 files changed, 23 insertions(+), 101 deletions(-) diff --git a/cmd/blockchaincmd/create.go b/cmd/blockchaincmd/create.go index e42a402bd..95c5e06d8 100644 --- a/cmd/blockchaincmd/create.go +++ b/cmd/blockchaincmd/create.go @@ -510,12 +510,11 @@ func LoadBootstrapValidator(filepath string) ([]models.SubnetValidator, error) { if err != nil { return nil, err } - var subnetValidatorsJSON []models.SubnetValidatorJSON - if err = json.Unmarshal(jsonBytes, &subnetValidatorsJSON); err != nil { + var subnetValidators []models.SubnetValidator + if err = json.Unmarshal(jsonBytes, &subnetValidators); err != nil { return nil, err } - subnetValidators, err := convertToSubnetValidators(subnetValidatorsJSON) - if err != nil { + if err = validateSubnetValidatorsJSON(subnetValidators); err != nil { return nil, err } return subnetValidators, nil diff --git a/cmd/blockchaincmd/prompt_genesis_input.go b/cmd/blockchaincmd/prompt_genesis_input.go index d49dec1dc..417c25c18 100644 --- a/cmd/blockchaincmd/prompt_genesis_input.go +++ b/cmd/blockchaincmd/prompt_genesis_input.go @@ -11,9 +11,7 @@ import ( "github.com/ava-labs/avalanche-cli/pkg/prompts" "github.com/ava-labs/avalanche-cli/pkg/ux" "github.com/ava-labs/avalanchego/ids" - "github.com/ava-labs/avalanchego/utils/formatting/address" "github.com/ava-labs/avalanchego/vms/platformvm/signer" - "github.com/ava-labs/avalanchego/vms/secp256k1fx" ) func getValidatorContractManagerAddr() ([]string, bool, error) { @@ -67,25 +65,21 @@ func getAddr() ([]string, bool, error) { return addr, false, nil } -func promptProofOfPossession() (signer.Signer, error) { +func promptProofOfPossession() (string, string, error) { ux.Logger.PrintToUser("Next, we need the public key and proof of possession of the node's BLS") ux.Logger.PrintToUser("Check https://docs.avax.network/api-reference/info-api#infogetnodeid for instructions on calling info.getNodeID API") var err error txt := "What is the public key of the node's BLS?" publicKey, err := app.Prompt.CaptureValidatedString(txt, prompts.ValidateHexa) if err != nil { - return nil, err + return "", "", err } txt = "What is the proof of possession of the node's BLS?" proofOfPossesion, err := app.Prompt.CaptureValidatedString(txt, prompts.ValidateHexa) if err != nil { - return nil, err + return "", "", err } - pop, err := getBLSInfo(publicKey, proofOfPossesion) - if err != nil { - return nil, err - } - return pop, nil + return publicKey, proofOfPossesion, nil } // TODO: add explain the difference for different validator management type @@ -128,7 +122,6 @@ func promptValidatorManagementType( return nil } -// TODO: find the min weight for bootstrap validator func PromptWeightBootstrapValidator() (uint64, error) { txt := "What stake weight would you like to assign to the validator?" return app.Prompt.CaptureWeight(txt) @@ -174,26 +167,22 @@ func promptBootstrapValidators() ([]models.SubnetValidator, error) { if err != nil { return nil, err } - proofOfPossession, err := promptProofOfPossession() - changeAddr, err := getKeyForChangeOwner(previousAddr) + publicKey, pop, err := promptProofOfPossession() if err != nil { return nil, err } - addrs, err := address.ParseToIDs([]string{changeAddr}) + changeAddr, err := getKeyForChangeOwner(previousAddr) if err != nil { - return nil, fmt.Errorf("failure parsing change owner address: %w", err) - } - changeOwner := &secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: addrs, + return nil, err } previousAddr = changeAddr subnetValidator := models.SubnetValidator{ - NodeID: nodeID, - Weight: weight, - Balance: balance, - Signer: proofOfPossession, - ChangeOwner: changeOwner, + NodeID: nodeID.String(), + Weight: weight, + Balance: balance, + BLSPublicKey: publicKey, + BLSProofOfPossession: pop, + ChangeOwnerAddr: changeAddr, } subnetValidators = append(subnetValidators, subnetValidator) ux.Logger.GreenCheckmarkToUser("Bootstrap Validator %d:", len(subnetValidators)) @@ -236,60 +225,21 @@ func getBLSInfo(publicKey, proofOfPossesion string) (signer.Signer, error) { return pop, nil } -func convertToSubnetValidators(validatorJSONS []models.SubnetValidatorJSON) ([]models.SubnetValidator, error) { - subnetValidators := []models.SubnetValidator{} - type jsonProofOfPossession struct { - PublicKey string - ProofOfPossession string - } +func validateSubnetValidatorsJSON(validatorJSONS []models.SubnetValidator) error { for _, validatorJSON := range validatorJSONS { - nodeID, err := ids.NodeIDFromString(validatorJSON.NodeID) + _, err := ids.NodeIDFromString(validatorJSON.NodeID) if err != nil { - return nil, fmt.Errorf("invalid node id %s", validatorJSON.NodeID) + return fmt.Errorf("invalid node id %s", validatorJSON.NodeID) } if validatorJSON.Weight <= 0 { - return nil, fmt.Errorf("bootstrap validator weight has to be greater than 0") + return fmt.Errorf("bootstrap validator weight has to be greater than 0") } if validatorJSON.Balance <= 0 { - return nil, fmt.Errorf("bootstrap validator balance has to be greater than 0") + return fmt.Errorf("bootstrap validator balance has to be greater than 0") } if err = validateBLS(validatorJSON.BLSPublicKey, validatorJSON.BLSProofOfPossession); err != nil { - return nil, err - } - //jsonPop := jsonProofOfPossession{ - // PublicKey: validatorJSON.BLSPublicKey, - // ProofOfPossession: validatorJSON.BLSProofOfPossession, - //} - //popBytes, err := json.Marshal(jsonPop) - //if err != nil { - // return nil, err - //} - //pop := &signer.ProofOfPossession{} - //err = pop.UnmarshalJSON(popBytes) - //if err != nil { - // return nil, err - //} - pop, err := getBLSInfo(validatorJSON.BLSPublicKey, validatorJSON.BLSProofOfPossession) - if err != nil { - return nil, err - } - changeAddr, err := ids.ShortFromString(validatorJSON.ChangeOwnerAddr) - if err != nil { - return nil, err - } - changeOwner := &secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{changeAddr}, + return err } - subnetValidators = append(subnetValidators, - models.SubnetValidator{ - NodeID: nodeID, - Weight: validatorJSON.Weight, - Balance: validatorJSON.Balance, - Signer: pop, - ChangeOwner: changeOwner, - }, - ) } - return subnetValidators, nil + return nil } diff --git a/pkg/models/bootstrap_validator.go b/pkg/models/bootstrap_validator.go index 7f36417b8..8072bf39a 100644 --- a/pkg/models/bootstrap_validator.go +++ b/pkg/models/bootstrap_validator.go @@ -2,34 +2,7 @@ // See the file LICENSE for licensing terms. package models -import ( - "github.com/ava-labs/avalanchego/ids" - "github.com/ava-labs/avalanchego/vms/platformvm/fx" - "github.com/ava-labs/avalanchego/vms/platformvm/signer" -) - type SubnetValidator struct { - // Must be Ed25519 NodeID - NodeID ids.NodeID - - // Weight of this validator used when sampling - Weight uint64 - - // Initial balance for this validator - Balance uint64 - - // [Signer] is the BLS key for this validator. - // Note: We do not enforce that the BLS key is unique across all validators. - // This means that validators can share a key if they so choose. - // However, a NodeID + Subnet does uniquely map to a BLS key - Signer signer.Signer - - // Leftover $AVAX from the [Balance] will be issued to this - // owner once it is removed from the validator set. - ChangeOwner fx.Owner -} - -type SubnetValidatorJSON struct { NodeID string `json:"NodeID"` Weight uint64 `json:"Weight"` From 3756c9d714d1e72cb74b0167b46233425ce98f0c Mon Sep 17 00:00:00 2001 From: Raymond Sukanto Date: Wed, 18 Sep 2024 15:37:02 -0400 Subject: [PATCH 32/64] use default balance and weight --- cmd/blockchaincmd/prompt_genesis_input.go | 36 ++--------------------- pkg/constants/constants.go | 15 +++++----- pkg/prompts/validations.go | 4 +-- 3 files changed, 12 insertions(+), 43 deletions(-) diff --git a/cmd/blockchaincmd/prompt_genesis_input.go b/cmd/blockchaincmd/prompt_genesis_input.go index 417c25c18..685e7d5ea 100644 --- a/cmd/blockchaincmd/prompt_genesis_input.go +++ b/cmd/blockchaincmd/prompt_genesis_input.go @@ -122,28 +122,6 @@ func promptValidatorManagementType( return nil } -func PromptWeightBootstrapValidator() (uint64, error) { - txt := "What stake weight would you like to assign to the validator?" - return app.Prompt.CaptureWeight(txt) -} - -func PromptInitialBalance() (uint64, error) { - defaultInitialBalance := fmt.Sprintf("Default (%d AVAX)", constants.MinInitialBalanceBootstrapValidator) - txt := "What initial balance would you like to assign to the bootstrap validator (in AVAX)?" - weightOptions := []string{defaultInitialBalance, "Custom"} - weightOption, err := app.Prompt.CaptureList(txt, weightOptions) - if err != nil { - return 0, err - } - - switch weightOption { - case defaultInitialBalance: - return constants.MinInitialBalanceBootstrapValidator, nil - default: - return app.Prompt.CaptureBootstrapInitialBalance(txt) - } -} - func promptBootstrapValidators() ([]models.SubnetValidator, error) { var subnetValidators []models.SubnetValidator numBootstrapValidators, err := app.Prompt.CaptureInt( @@ -159,14 +137,6 @@ func promptBootstrapValidators() ([]models.SubnetValidator, error) { if err != nil { return nil, err } - weight, err := PromptWeightBootstrapValidator() - if err != nil { - return nil, err - } - balance, err := PromptInitialBalance() - if err != nil { - return nil, err - } publicKey, pop, err := promptProofOfPossession() if err != nil { return nil, err @@ -178,8 +148,8 @@ func promptBootstrapValidators() ([]models.SubnetValidator, error) { previousAddr = changeAddr subnetValidator := models.SubnetValidator{ NodeID: nodeID.String(), - Weight: weight, - Balance: balance, + Weight: constants.DefaultWeightBootstrapValidator, + Balance: constants.InitialBalanceBootstrapValidator, BLSPublicKey: publicKey, BLSProofOfPossession: pop, ChangeOwnerAddr: changeAddr, @@ -187,8 +157,6 @@ func promptBootstrapValidators() ([]models.SubnetValidator, error) { subnetValidators = append(subnetValidators, subnetValidator) ux.Logger.GreenCheckmarkToUser("Bootstrap Validator %d:", len(subnetValidators)) ux.Logger.PrintToUser("- Node ID: %s", nodeID) - ux.Logger.PrintToUser("- Weight: %d", weight) - ux.Logger.PrintToUser("- Initial Balance: %d AVAX", balance) ux.Logger.PrintToUser("- Change Address: %s", changeAddr) } return subnetValidators, nil diff --git a/pkg/constants/constants.go b/pkg/constants/constants.go index 16bbb81df..6d28d8cff 100644 --- a/pkg/constants/constants.go +++ b/pkg/constants/constants.go @@ -154,13 +154,14 @@ const ( Disable = "disable" - TimeParseLayout = "2006-01-02 15:04:05" - MinStakeWeight = 1 - MinInitialBalanceBootstrapValidator = 5 - DefaultStakeWeight = 20 - AVAXSymbol = "AVAX" - DefaultFujiStakeDuration = "48h" - DefaultMainnetStakeDuration = "336h" + TimeParseLayout = "2006-01-02 15:04:05" + MinStakeWeight = 1 + InitialBalanceBootstrapValidator = 1 + DefaultWeightBootstrapValidator = 1000000 + DefaultStakeWeight = 20 + AVAXSymbol = "AVAX" + DefaultFujiStakeDuration = "48h" + DefaultMainnetStakeDuration = "336h" // The absolute minimum is 25 seconds, but set to 1 minute to allow for // time to go through the command DevnetStakingStartLeadTime = 30 * time.Second diff --git a/pkg/prompts/validations.go b/pkg/prompts/validations.go index 48438851b..ad9fd4326 100644 --- a/pkg/prompts/validations.go +++ b/pkg/prompts/validations.go @@ -134,8 +134,8 @@ func validateBootstrapBalance(input string) error { if err != nil { return err } - if val < constants.MinInitialBalanceBootstrapValidator { - return fmt.Errorf("initial bootstrap validator balance must be at least %d AVAX", constants.MinInitialBalanceBootstrapValidator) + if val < constants.InitialBalanceBootstrapValidator { + return fmt.Errorf("initial bootstrap validator balance must be at least %d AVAX", constants.InitialBalanceBootstrapValidator) } return nil } From 5042124bef26b7a966421ccfd41c2a619a139434 Mon Sep 17 00:00:00 2001 From: Raymond Sukanto Date: Wed, 18 Sep 2024 17:03:39 -0400 Subject: [PATCH 33/64] generate new node ids and bls --- cmd/blockchaincmd/create.go | 1 - cmd/blockchaincmd/prompt_genesis_input.go | 82 +++++++++++++++-------- 2 files changed, 53 insertions(+), 30 deletions(-) diff --git a/cmd/blockchaincmd/create.go b/cmd/blockchaincmd/create.go index 95c5e06d8..72fe2548e 100644 --- a/cmd/blockchaincmd/create.go +++ b/cmd/blockchaincmd/create.go @@ -50,7 +50,6 @@ type CreateFlags struct { validatorManagerMintOnly bool tokenMinterAddress []string validatorManagerController []string - bootstrapValidators []models.SubnetValidator } var ( diff --git a/cmd/blockchaincmd/prompt_genesis_input.go b/cmd/blockchaincmd/prompt_genesis_input.go index 685e7d5ea..0088f506a 100644 --- a/cmd/blockchaincmd/prompt_genesis_input.go +++ b/cmd/blockchaincmd/prompt_genesis_input.go @@ -3,14 +3,17 @@ package blockchaincmd import ( - "encoding/json" "fmt" "github.com/ava-labs/avalanche-cli/pkg/application" "github.com/ava-labs/avalanche-cli/pkg/constants" "github.com/ava-labs/avalanche-cli/pkg/models" "github.com/ava-labs/avalanche-cli/pkg/prompts" + "github.com/ava-labs/avalanche-cli/pkg/utils" "github.com/ava-labs/avalanche-cli/pkg/ux" "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/staking" + "github.com/ava-labs/avalanchego/utils/crypto/bls" + "github.com/ava-labs/avalanchego/utils/formatting" "github.com/ava-labs/avalanchego/vms/platformvm/signer" ) @@ -130,16 +133,46 @@ func promptBootstrapValidators() ([]models.SubnetValidator, error) { if err != nil { return nil, err } + setUpNodes, err := promptSetUpNodes() + if err != nil { + return nil, err + } previousAddr := "" for len(subnetValidators) < numBootstrapValidators { ux.Logger.PrintToUser("Getting info for bootstrap validator %d", len(subnetValidators)+1) - nodeID, err := PromptNodeID() - if err != nil { - return nil, err - } - publicKey, pop, err := promptProofOfPossession() - if err != nil { - return nil, err + var nodeID ids.NodeID + var publicKey, pop string + if setUpNodes { + nodeID, err = PromptNodeID() + if err != nil { + return nil, err + } + publicKey, pop, err = promptProofOfPossession() + if err != nil { + return nil, err + } + } else { + certBytes, _, err := staking.NewCertAndKeyBytes() + if err != nil { + return nil, err + } + nodeID, err = utils.ToNodeID(certBytes) + if err != nil { + return nil, err + } + blsSignerKey, err := bls.NewSecretKey() + if err != nil { + return nil, err + } + p := signer.NewProofOfPossession(blsSignerKey) + publicKey, err = formatting.Encode(formatting.HexNC, p.PublicKey[:]) + if err != nil { + return nil, err + } + pop, err = formatting.Encode(formatting.HexNC, p.ProofOfPossession[:]) + if err != nil { + return nil, err + } } changeAddr, err := getKeyForChangeOwner(previousAddr) if err != nil { @@ -172,27 +205,6 @@ func validateBLS(publicKey, pop string) error { return nil } -func getBLSInfo(publicKey, proofOfPossesion string) (signer.Signer, error) { - type jsonProofOfPossession struct { - PublicKey string - ProofOfPossession string - } - jsonPop := jsonProofOfPossession{ - PublicKey: publicKey, - ProofOfPossession: proofOfPossesion, - } - popBytes, err := json.Marshal(jsonPop) - if err != nil { - return nil, err - } - pop := &signer.ProofOfPossession{} - err = pop.UnmarshalJSON(popBytes) - if err != nil { - return nil, err - } - return pop, nil -} - func validateSubnetValidatorsJSON(validatorJSONS []models.SubnetValidator) error { for _, validatorJSON := range validatorJSONS { _, err := ids.NodeIDFromString(validatorJSON.NodeID) @@ -211,3 +223,15 @@ func validateSubnetValidatorsJSON(validatorJSONS []models.SubnetValidator) error } return nil } + +// promptProvideNodeID returns false if user doesn't have any Avalanche node set up yet to be +// bootstrap validators +func promptSetUpNodes() (bool, error) { + ux.Logger.PrintToUser("If you have set up your own Avalanche Nodes, you can provide the Node ID and BLS Key from those nodes in the next step.") + ux.Logger.PrintToUser("Otherwise, we will generate new Node IDs and BLS Key for you.") + setUpNodes, err := app.Prompt.CaptureYesNo("Have you set up your own Avalanche Nodes?") + if err != nil { + return false, err + } + return setUpNodes, nil +} From f2189392c75fcfdad4de044f3e317d2196b83e69 Mon Sep 17 00:00:00 2001 From: Raymond Sukanto Date: Wed, 18 Sep 2024 17:09:39 -0400 Subject: [PATCH 34/64] fix lint --- cmd/blockchaincmd/prompt_genesis_input.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/cmd/blockchaincmd/prompt_genesis_input.go b/cmd/blockchaincmd/prompt_genesis_input.go index 0088f506a..70fd0d656 100644 --- a/cmd/blockchaincmd/prompt_genesis_input.go +++ b/cmd/blockchaincmd/prompt_genesis_input.go @@ -4,6 +4,7 @@ package blockchaincmd import ( "fmt" + "github.com/ava-labs/avalanche-cli/pkg/application" "github.com/ava-labs/avalanche-cli/pkg/constants" "github.com/ava-labs/avalanche-cli/pkg/models" @@ -197,10 +198,10 @@ func promptBootstrapValidators() ([]models.SubnetValidator, error) { func validateBLS(publicKey, pop string) error { if err := prompts.ValidateHexa(publicKey); err != nil { - return fmt.Errorf("format error in given public key: %s", err) + return fmt.Errorf("format error in given public key: %w", err) } if err := prompts.ValidateHexa(pop); err != nil { - return fmt.Errorf("format error in given proof of possession: %s", err) + return fmt.Errorf("format error in given proof of possession: %w", err) } return nil } From 773f313b7d80da514567c5ec9e90c4117f56465c Mon Sep 17 00:00:00 2001 From: Raymond Sukanto Date: Wed, 18 Sep 2024 17:35:05 -0400 Subject: [PATCH 35/64] add flags --- cmd/blockchaincmd/create.go | 17 +++++- cmd/blockchaincmd/prompt_genesis_input.go | 70 +++++++++++++++-------- 2 files changed, 60 insertions(+), 27 deletions(-) diff --git a/cmd/blockchaincmd/create.go b/cmd/blockchaincmd/create.go index 72fe2548e..3cc31a1d5 100644 --- a/cmd/blockchaincmd/create.go +++ b/cmd/blockchaincmd/create.go @@ -50,6 +50,7 @@ type CreateFlags struct { validatorManagerMintOnly bool tokenMinterAddress []string validatorManagerController []string + generateNodeID bool } var ( @@ -115,7 +116,8 @@ configuration, pass the -f flag.`, cmd.Flags().BoolVar(&createFlags.validatorManagerMintOnly, "validator-manager-mint-only", false, "only enable validator manager contract to mint new native tokens") cmd.Flags().StringSliceVar(&createFlags.tokenMinterAddress, "token-minter-address", nil, "addresses that can mint new native tokens (for proof of authority validator management only)") cmd.Flags().StringSliceVar(&createFlags.validatorManagerController, "validator-manager-controller", nil, "addresses that will control Validator Manager contract") - cmd.Flags().StringVar(&bootstrapValidatorsJSONFilePath, "bootstrap-filepath", "", "JSON file path that provides details about bootstrap validators") + cmd.Flags().StringVar(&bootstrapValidatorsJSONFilePath, "bootstrap-filepath", "", "JSON file path that provides details about bootstrap validators, leave Node-ID and BLS values empty if using --generate-node-id=true") + cmd.Flags().BoolVar(&createFlags.generateNodeID, "generate-node-id", false, "whether to create new node id for bootstrap validators (Node-ID and BLS values in bootstrap JSON file will be overridden if --bootstrap-filepath flag is used)") return cmd } @@ -513,8 +515,19 @@ func LoadBootstrapValidator(filepath string) ([]models.SubnetValidator, error) { if err = json.Unmarshal(jsonBytes, &subnetValidators); err != nil { return nil, err } - if err = validateSubnetValidatorsJSON(subnetValidators); err != nil { + if err = validateSubnetValidatorsJSON(createFlags.generateNodeID, subnetValidators); err != nil { return nil, err } + if createFlags.generateNodeID { + for _, subnetValidator := range subnetValidators { + nodeID, publicKey, pop, err := generateNewNodeAndBLS() + if err != nil { + return nil, err + } + subnetValidator.NodeID = nodeID + subnetValidator.BLSPublicKey = publicKey + subnetValidator.BLSProofOfPossession = pop + } + } return subnetValidators, nil } diff --git a/cmd/blockchaincmd/prompt_genesis_input.go b/cmd/blockchaincmd/prompt_genesis_input.go index 70fd0d656..1c74cc430 100644 --- a/cmd/blockchaincmd/prompt_genesis_input.go +++ b/cmd/blockchaincmd/prompt_genesis_input.go @@ -126,6 +126,32 @@ func promptValidatorManagementType( return nil } +// generateNewNodeAndBLS returns node id, bls public key and bls pop +func generateNewNodeAndBLS() (string, string, string, error) { + certBytes, _, err := staking.NewCertAndKeyBytes() + if err != nil { + return "", "", "", err + } + nodeID, err := utils.ToNodeID(certBytes) + if err != nil { + return "", "", "", err + } + blsSignerKey, err := bls.NewSecretKey() + if err != nil { + return "", "", "", err + } + p := signer.NewProofOfPossession(blsSignerKey) + publicKey, err := formatting.Encode(formatting.HexNC, p.PublicKey[:]) + if err != nil { + return "", "", "", err + } + pop, err := formatting.Encode(formatting.HexNC, p.ProofOfPossession[:]) + if err != nil { + return "", "", "", err + } + return nodeID.String(), publicKey, pop, nil +} + func promptBootstrapValidators() ([]models.SubnetValidator, error) { var subnetValidators []models.SubnetValidator numBootstrapValidators, err := app.Prompt.CaptureInt( @@ -134,9 +160,14 @@ func promptBootstrapValidators() ([]models.SubnetValidator, error) { if err != nil { return nil, err } - setUpNodes, err := promptSetUpNodes() - if err != nil { - return nil, err + var setUpNodes bool + if createFlags.generateNodeID { + setUpNodes = true + } else { + setUpNodes, err = promptSetUpNodes() + if err != nil { + return nil, err + } } previousAddr := "" for len(subnetValidators) < numBootstrapValidators { @@ -153,24 +184,11 @@ func promptBootstrapValidators() ([]models.SubnetValidator, error) { return nil, err } } else { - certBytes, _, err := staking.NewCertAndKeyBytes() - if err != nil { - return nil, err - } - nodeID, err = utils.ToNodeID(certBytes) - if err != nil { - return nil, err - } - blsSignerKey, err := bls.NewSecretKey() - if err != nil { - return nil, err - } - p := signer.NewProofOfPossession(blsSignerKey) - publicKey, err = formatting.Encode(formatting.HexNC, p.PublicKey[:]) + nodeIDStr, publicKey, pop, err = generateNewNodeAndBLS() if err != nil { return nil, err } - pop, err = formatting.Encode(formatting.HexNC, p.ProofOfPossession[:]) + nodeID, err = ids.NodeIDFromString(nodeIDStr) if err != nil { return nil, err } @@ -206,11 +224,16 @@ func validateBLS(publicKey, pop string) error { return nil } -func validateSubnetValidatorsJSON(validatorJSONS []models.SubnetValidator) error { +func validateSubnetValidatorsJSON(generateNewNodeID bool, validatorJSONS []models.SubnetValidator) error { for _, validatorJSON := range validatorJSONS { - _, err := ids.NodeIDFromString(validatorJSON.NodeID) - if err != nil { - return fmt.Errorf("invalid node id %s", validatorJSON.NodeID) + if !generateNewNodeID { + _, err := ids.NodeIDFromString(validatorJSON.NodeID) + if err != nil { + return fmt.Errorf("invalid node id %s", validatorJSON.NodeID) + } + if err = validateBLS(validatorJSON.BLSPublicKey, validatorJSON.BLSProofOfPossession); err != nil { + return err + } } if validatorJSON.Weight <= 0 { return fmt.Errorf("bootstrap validator weight has to be greater than 0") @@ -218,9 +241,6 @@ func validateSubnetValidatorsJSON(validatorJSONS []models.SubnetValidator) error if validatorJSON.Balance <= 0 { return fmt.Errorf("bootstrap validator balance has to be greater than 0") } - if err = validateBLS(validatorJSON.BLSPublicKey, validatorJSON.BLSProofOfPossession); err != nil { - return err - } } return nil } From 1dcf24cd94904bd5c3016a84f59f348fbcc3957f Mon Sep 17 00:00:00 2001 From: Raymond Sukanto Date: Wed, 18 Sep 2024 17:38:19 -0400 Subject: [PATCH 36/64] add flags --- cmd/blockchaincmd/prompt_genesis_input.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cmd/blockchaincmd/prompt_genesis_input.go b/cmd/blockchaincmd/prompt_genesis_input.go index 1c74cc430..255e8a986 100644 --- a/cmd/blockchaincmd/prompt_genesis_input.go +++ b/cmd/blockchaincmd/prompt_genesis_input.go @@ -227,6 +227,9 @@ func validateBLS(publicKey, pop string) error { func validateSubnetValidatorsJSON(generateNewNodeID bool, validatorJSONS []models.SubnetValidator) error { for _, validatorJSON := range validatorJSONS { if !generateNewNodeID { + if validatorJSON.NodeID == "" || validatorJSON.BLSPublicKey == "" || validatorJSON.BLSProofOfPossession == "" { + return fmt.Errorf("no Node ID or BLS info provided, use --generate-node-id flag to generate new Node ID and BLS info") + } _, err := ids.NodeIDFromString(validatorJSON.NodeID) if err != nil { return fmt.Errorf("invalid node id %s", validatorJSON.NodeID) From fcda44c48dc8388cabf6e834373fcb585ba3c61c Mon Sep 17 00:00:00 2001 From: Felipe Madero Date: Wed, 18 Sep 2024 18:46:28 -0400 Subject: [PATCH 37/64] add a function to initialize PoA manager --- pkg/vm/create_evm.go | 6 ++++++ pkg/vm/evm_prompts.go | 1 + 2 files changed, 7 insertions(+) diff --git a/pkg/vm/create_evm.go b/pkg/vm/create_evm.go index 866d26432..8c2b58df4 100644 --- a/pkg/vm/create_evm.go +++ b/pkg/vm/create_evm.go @@ -16,6 +16,7 @@ import ( "github.com/ava-labs/avalanche-cli/pkg/teleporter" icmgenesis "github.com/ava-labs/avalanche-cli/pkg/teleporter/genesis" "github.com/ava-labs/avalanche-cli/pkg/ux" + "github.com/ava-labs/avalanche-cli/pkg/validatormanager" blockchainSDK "github.com/ava-labs/avalanche-cli/sdk/blockchain" "github.com/ava-labs/subnet-evm/core" "github.com/ava-labs/subnet-evm/utils" @@ -116,6 +117,11 @@ func CreateEVMGenesis( } } + params.SoVUsePoAValidatorManager = true + if params.SoVUsePoAValidatorManager { + validatormanager.AddPoAValidatorManagerContractToAllocations(params.initialTokenAllocation) + } + if params.UseExternalGasToken { params.enableNativeMinterPrecompile = true params.nativeMinterPrecompileAllowList.AdminAddresses = append( diff --git a/pkg/vm/evm_prompts.go b/pkg/vm/evm_prompts.go index c67750186..449b3d944 100644 --- a/pkg/vm/evm_prompts.go +++ b/pkg/vm/evm_prompts.go @@ -90,6 +90,7 @@ type SubnetEVMGenesisParams struct { enableContractDeployerPrecompile bool contractDeployerPrecompileAllowList AllowList enableWarpPrecompile bool + SoVUsePoAValidatorManager bool } func PromptTokenSymbol( From dc0b321cb06735672194cf05bc51dd4d4c9bf7c1 Mon Sep 17 00:00:00 2001 From: Felipe Madero Date: Thu, 19 Sep 2024 09:57:40 -0400 Subject: [PATCH 38/64] add lib folder --- ...eployed_poa_validator_manager_bytecode.txt | 1 + pkg/validatormanager/validatormanager.go | 66 +++++++++++++++++++ 2 files changed, 67 insertions(+) create mode 100644 pkg/validatormanager/deployed_poa_validator_manager_bytecode.txt create mode 100644 pkg/validatormanager/validatormanager.go diff --git a/pkg/validatormanager/deployed_poa_validator_manager_bytecode.txt b/pkg/validatormanager/deployed_poa_validator_manager_bytecode.txt new file mode 100644 index 000000000..7e19811ae --- /dev/null +++ b/pkg/validatormanager/deployed_poa_validator_manager_bytecode.txt @@ -0,0 +1 @@ +0x608060405234801561000f575f80fd5b506004361061011c575f3560e01c80638994ab49116100a9578063bee0a03f1161006e578063bee0a03f146102b4578063c974d1b6146102c7578063d5f20ff6146102cf578063df93d8de146102ef578063f2fde38b146102f9575f80fd5b80638994ab49146102295780638da5cb5b1461023c57806397fb70d414610280578063a3a65e4814610293578063b771b3bc146102a6575f80fd5b806360305d62116100ef57806360305d62146101ac57806361e2f490146101c957806366435abf146101dc578063715018a6146102075780638280a25a1461020f575f80fd5b80630322ed98146101205780630cdd098514610135578063467ef06f14610186578063580a400614610199575b5f80fd5b61013361012e366004612db8565b61030c565b005b610173610143366004612db8565b5f9081527fe92546d698950ddd38910d2e15ed1d923cd0a7b3dde9e2a6a3f380565559cb09602052604090205490565b6040519081526020015b60405180910390f35b610133610194366004612de7565b6104ca565b6101336101a7366004612e2a565b6104d8565b6101b4601481565b60405163ffffffff909116815260200161017d565b6101336101d7366004612e60565b6105e6565b6101ef6101ea366004612db8565b610c1a565b6040516001600160401b03909116815260200161017d565b610133610c2e565b610217603081565b60405160ff909116815260200161017d565b610173610237366004612ec0565b610c41565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b03165b6040516001600160a01b03909116815260200161017d565b61013361028e366004612db8565b610c5d565b6101336102a1366004612de7565b610c71565b6102686005600160991b0181565b6101336102c2366004612db8565b610e29565b610217601481565b6102e26102dd366004612db8565b610f38565b60405161017d9190612f19565b6101ef6202a30081565b610133610307366004612fcf565b61102b565b5f8181525f805160206137fa8339815191526020526040808220815160e0810190925280545f805160206137da83398151915293929190829060ff16600581111561035957610359612f05565b600581111561036a5761036a612f05565b81526001820154602082015260028201546001600160401b038082166040840152600160401b820481166060840152600160801b820481166080840152600160c01b909104811660a08301526003928301541660c090910152909150815160058111156103d9576103d9612f05565b146104435760405162461bcd60e51b815260206004820152602f60248201527f56616c696461746f724d616e616765723a2056616c696461746f72206e6f742060448201526e1c195b991a5b99c81c995b5bdd985b608a1b60648201526084015b60405180910390fd5b6005600160991b016001600160a01b031663ee5b48eb6104688584606001515f611065565b6040518263ffffffff1660e01b81526004016104849190613013565b6020604051808303815f875af11580156104a0573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104c49190613045565b50505050565b6104d38161128a565b505050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a008054600160401b810460ff1615906001600160401b03165f8115801561051c5750825b90505f826001600160401b031660011480156105375750303b155b905081158015610545575080155b156105635760405163f92ee8a960e01b815260040160405180910390fd5b845467ffffffffffffffff19166001178555831561058d57845460ff60401b1916600160401b1785555b6105978787611602565b83156105dd57845460ff60401b19168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b50505050505050565b7fe92546d698950ddd38910d2e15ed1d923cd0a7b3dde9e2a6a3f380565559cb0a545f805160206137da8339815191529060ff16156106835760405162461bcd60e51b815260206004820152603360248201527f56616c696461746f724d616e616765723a20616c726561647920696e697469616044820152721b1a5e9959081d985b1a59185d1bdc881cd95d606a1b606482015260840161043a565b6005600160991b016001600160a01b0316634213cf786040518163ffffffff1660e01b8152600401602060405180830381865afa1580156106c6573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906106ea9190613045565b83602001351461074c5760405162461bcd60e51b815260206004820152602760248201527f56616c696461746f724d616e616765723a20696e76616c696420626c6f636b636044820152661a185a5b88125160ca1b606482015260840161043a565b3061075d6060850160408601612fcf565b6001600160a01b0316146107cf5760405162461bcd60e51b815260206004820152603360248201527f56616c696461746f724d616e616765723a20696e76616c69642076616c696461604482015272746f72206d616e61676572206164647265737360681b606482015260840161043a565b5f6107dd606085018561305c565b91505f90508435602086013560146107fb6060890160408a01612fcf565b60408051602081019590955284019290925260e090811b6001600160e01b03199081166060808601919091529290921b6bffffffffffffffffffffffff1916606484015284901b166078820152607c0160405160208183030381529060405290505f805b838163ffffffff161015610b2a575f61087b606089018961305c565b8363ffffffff16818110610891576108916130a1565b90506020028101906108a391906130b5565b6108ac90613165565b80515f81815260098901602052604090205491925090156108df5760405162461bcd60e51b815260040161043a906131fc565b84825f0151836020015184604001516040516020016109019493929190613244565b60408051808303601f190181528282528b35602084015260e086901b6001600160e01b031916838301528151602481850301815260449093019182905296505f9160029161094f9190613293565b602060405180830381855afa15801561096a573d5f803e3d5ffd5b5050506040513d601f19601f8201168201806040525081019061098d9190613045565b5f83815260098a0160209081526040808320849055805160e0810182526002815287518184015287830180516001600160401b039081168385015260608301869052905181166080830152421660a082015260c0810184905284845260088d01909252909120815181549394509192909190829060ff19166001836005811115610a1957610a19612f05565b0217905550602082810151600183015560408301516002830180546060860151608087015160a08801516001600160401b039586166001600160801b031990941693909317600160401b92861692909202919091176001600160801b0316600160801b918516919091026001600160c01b031617600160c01b9184169190910217905560c0909301516003909201805467ffffffffffffffff191692841692909217909155840151610acc9116866132b8565b83516020808601516040516001600160401b039091168152929750909183917fb815f891730222788b3f8d66249b3a287ce680c3df13866fd9a4f37743ae1014910160405180910390a350505080610b23906132cb565b905061085f565b50600584018190555f610b3c86611620565b90505f610b4c82604001516117fa565b905080600285604051610b5f9190613293565b602060405180830381855afa158015610b7a573d5f803e3d5ffd5b5050506040513d601f19601f82011682018060405250810190610b9d9190613045565b14610c015760405162461bcd60e51b815260206004820152602e60248201527f56616c696461746f724d616e616765723a20696e76616c6964207375626e657460448201526d0818dbdb9d995c9cda5bdb88125160921b606482015260840161043a565b505050600a909201805460ff1916600117905550505050565b5f610c2482610f38565b6080015192915050565b610c36611963565b610c3f5f6119be565b565b5f610c4a611963565b610c548383611a2e565b90505b92915050565b610c65611963565b610c6e81611f93565b50565b5f805160206137da8339815191525f610c8983611620565b90505f80610c9a8360400151612204565b9150915080610cfc5760405162461bcd60e51b815260206004820152602860248201527f56616c696461746f724d616e616765723a20526567697374726174696f6e206e6044820152671bdd081d985b1a5960c21b606482015260840161043a565b5f82815260078501602052604081208054610d16906132ed565b9050118015610d48575060015f83815260088601602052604090205460ff166005811115610d4657610d46612f05565b145b610d645760405162461bcd60e51b815260040161043a9061331f565b5f8281526007850160205260408120610d7c91612d6e565b5f8281526008850160208181526040808420805460ff191660029081178255810180546001600160401b0342818116600160c01b026001600160c01b03909316929092178355600190930154875260098b0185528387208990559588905293835292548151600160801b90910490931683529082019290925283917ff8fd1c90fb9cfa2ca2358fdf5806b086ad43315d92b221c929efc7f105ce7568910160405180910390a25050505050565b5f8181527fe92546d698950ddd38910d2e15ed1d923cd0a7b3dde9e2a6a3f380565559cb076020526040812080545f805160206137da833981519152929190610e71906132ed565b9050118015610ea3575060015f83815260088301602052604090205460ff166005811115610ea157610ea1612f05565b145b610ebf5760405162461bcd60e51b815260040161043a9061331f565b5f82815260078201602052604090819020905163ee5b48eb60e01b81526005600160991b019163ee5b48eb91610ef89190600401613366565b6020604051808303815f875af1158015610f14573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104d39190613045565b6040805160e080820183525f8083526020808401829052838501829052606084018290526080840182905260a0840182905260c084018290528582525f805160206137fa83398151915290528390208351918201909352825491925f805160206137da83398151915292829060ff166005811115610fb857610fb8612f05565b6005811115610fc957610fc9612f05565b81526001820154602082015260028201546001600160401b038082166040840152600160401b820481166060840152600160801b820481166080840152600160c01b909104811660a083015260039092015490911660c0909101529392505050565b611033611963565b6001600160a01b03811661105c57604051631e4fbdf760e01b81525f600482015260240161043a565b610c6e816119be565b60408051603680825260608281019093525f91906020820181803683370190505090505f5b60028110156110de5761109e8160016133f0565b6110a9906008613403565b5081515f908390839081106110c0576110c06130a1565b60200101906001600160f81b03191690815f1a90535060010161108a565b505f5b6004811015611149576110f58160036133f0565b611100906008613403565b600263ffffffff16901c60f81b8282600261111b91906132b8565b8151811061112b5761112b6130a1565b60200101906001600160f81b03191690815f1a9053506001016110e1565b505f5b60208110156111ab5761116081601f6133f0565b61116b906008613403565b86901c60f81b8261117d8360066132b8565b8151811061118d5761118d6130a1565b60200101906001600160f81b03191690815f1a90535060010161114c565b505f5b6008811015611216576111c28160076133f0565b6111cd906008613403565b6001600160401b038616901c60f81b826111e88360266132b8565b815181106111f8576111f86130a1565b60200101906001600160f81b03191690815f1a9053506001016111ae565b505f5b60088110156112815761122d8160076133f0565b611238906008613403565b6001600160401b038516901c60f81b8261125383602e6132b8565b81518110611263576112636130a1565b60200101906001600160f81b03191690815f1a905350600101611219565b50949350505050565b6040805160e0810182525f80825260208201819052918101829052606081018290526080810182905260a0810182905260c081018290525f805160206137da8339815191525f6112d985611620565b90505f806112ea8360400151612204565b91509150801561134f5760405162461bcd60e51b815260206004820152602a60248201527f56616c696461746f724d616e616765723a20726567697374726174696f6e20736044820152691d1a5b1b081d985b1a5960b21b606482015260840161043a565b5f828152600885016020526040808220815160e081019092528054829060ff16600581111561138057611380612f05565b600581111561139157611391612f05565b81526001820154602082015260028201546001600160401b038082166040840152600160401b820481166060840152600160801b820481166080840152600160c01b909104811660a08301526003928301541660c0909101529091505f908251600581111561140257611402612f05565b1480611420575060018251600581111561141e5761141e612f05565b145b61147f5760405162461bcd60e51b815260206004820152602a60248201527f56616c696461746f724d616e616765723a20696e76616c69642076616c696461604482015269746f722073746174757360b01b606482015260840161043a565b60038251600581111561149457611494612f05565b036114a1575060046114a5565b5060055b6020808301515f908152600988019091526040812055818160058111156114ce576114ce612f05565b908160058111156114e1576114e1612f05565b9052505f84815260088701602052604090208251815484929190829060ff1916600183600581111561151557611515612f05565b02179055506020820151600182015560408201516002820180546060850151608086015160a08701516001600160401b039586166001600160801b031990941693909317600160401b92861692909202919091176001600160801b0316600160801b918516919091026001600160c01b031617600160c01b9184169190910217905560c0909201516003909101805467ffffffffffffffff191691909216179055815160058111156115c9576115c9612f05565b60405185907f1c08e59656f1a18dc2da76826cdc52805c43e897a17c50faefb8ab3c1526cc16905f90a350919791965090945050505050565b61160a6123a5565b611613826123ee565b61161c81612407565b5050565b60408051606080820183525f8083526020830181905292820152905f805160206137da8339815191526040516306f8253560e41b815263ffffffff851660048201529091505f9081906005600160991b0190636f825350906024015f60405180830381865afa158015611695573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526116bc9190810190613429565b915091508061171c5760405162461bcd60e51b815260206004820152602660248201527f56616c696461746f724d616e616765723a20696e76616c69642077617270206d60448201526565737361676560d01b606482015260840161043a565b825482511461177f5760405162461bcd60e51b815260206004820152602960248201527f56616c696461746f724d616e616765723a20696e76616c696420736f757263656044820152680818da185a5b88125160ba1b606482015260840161043a565b60208201516001600160a01b0316156117f25760405162461bcd60e51b815260206004820152602f60248201527f56616c696461746f724d616e616765723a20696e76616c6964206f726967696e60448201526e2073656e646572206164647265737360881b606482015260840161043a565b509392505050565b5f815160261461181c5760405162461bcd60e51b815260040161043a906134fb565b5f805b600281101561186b576118338160016133f0565b61183e906008613403565b61ffff16848281518110611854576118546130a1565b016020015160f81c901b919091179060010161181f565b5061ffff81161561188e5760405162461bcd60e51b815260040161043a90613544565b5f805b60048110156118e9576118a58160036133f0565b6118b0906008613403565b63ffffffff16856118c28360026132b8565b815181106118d2576118d26130a1565b016020015160f81c901b9190911790600101611891565b5063ffffffff81161561190e5760405162461bcd60e51b815260040161043a90613587565b5f805b60208110156112815761192581601f6133f0565b611930906008613403565b8661193c8360066132b8565b8151811061194c5761194c6130a1565b016020015160f81c901b9190911790600101611911565b336119957f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b031690565b6001600160a01b031614610c3f5760405163118cdaa760e01b815233600482015260240161043a565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930080546001600160a01b031981166001600160a01b03848116918217845560405192169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a3505050565b7fe92546d698950ddd38910d2e15ed1d923cd0a7b3dde9e2a6a3f380565559cb0a545f9060ff16611ab95760405162461bcd60e51b815260206004820152602f60248201527f56616c696461746f724d616e616765723a2076616c696461746f72207365742060448201526e1b9bdd081a5b9a5d1a585b1a5e9959608a1b606482015260840161043a565b5f805160206137da83398151915242611ad860408601602087016135ce565b6001600160401b031611611b4a5760405162461bcd60e51b815260206004820152603360248201527f56616c696461746f724d616e616765723a20726567697374726174696f6e20656044820152727870697279206e6f7420696e2066757475726560681b606482015260840161043a565b611b5a60408501602086016135ce565b6001600160401b0316611b706202a300426132b8565b11611be35760405162461bcd60e51b815260206004820152603760248201527f56616c696461746f724d616e616765723a20726567697374726174696f6e206560448201527f787069727920746f6f2066617220696e20667574757265000000000000000000606482015260840161043a565b8335611c3b5760405162461bcd60e51b815260206004820152602160248201527f56616c696461746f724d616e616765723a20696e76616c6964206e6f646520496044820152601160fa1b606482015260840161043a565b83355f90815260098201602052604090205415611c6a5760405162461bcd60e51b815260040161043a906131fc565b6030611c7960408601866135e7565b905014611cde5760405162461bcd60e51b815260206004820152602d60248201527f56616c696461746f724d616e616765723a20696e76616c696420626c7350756260448201526c0d8d2c696caf240d8cadccee8d609b1b606482015260840161043a565b611ce8835f612418565b5f80611d826040518060a0016040528085600101548152602001885f01358152602001876001600160401b03168152602001886020016020810190611d2d91906135ce565b6001600160401b03168152602001611d4860408a018a6135e7565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920191909152505050915250612626565b5f82815260078601602052604090209193509150611da08282613674565b5060405163ee5b48eb60e01b81525f906005600160991b019063ee5b48eb90611dcd908590600401613013565b6020604051808303815f875af1158015611de9573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611e0d9190613045565b6040805160e08101909152909150806001815288356020808301919091526001600160401b03891660408084018290525f60608501819052608085019290925260a0840182905260c0909301819052868152600888019091522081518154829060ff19166001836005811115611e8557611e85612f05565b021790555060208281015160018301556040808401516002840180546060870151608088015160a08901516001600160401b039586166001600160801b031990941693909317600160401b92861692909202919091176001600160801b0316600160801b918516919091026001600160c01b031617600160c01b9184169190910217905560c0909401516003909301805467ffffffffffffffff19169390941692909217909255829189359186917f79b81620b81daf2c08cd5bb3dbb79e75d2d7a87f52171fde5aadc8c47823026e918b91611f65918e01908e016135ce565b604080516001600160401b0393841681529290911660208301520160405180910390a4509095945050505050565b5f8181525f805160206137fa8339815191526020526040808220815160e0810190925280545f805160206137da83398151915293929190829060ff166005811115611fe057611fe0612f05565b6005811115611ff157611ff1612f05565b8152600182015460208201526002808301546001600160401b038082166040850152600160401b820481166060850152600160801b820481166080850152600160c01b909104811660a084015260039093015490921660c0909101529091508151600581111561206357612063612f05565b146120bf5760405162461bcd60e51b815260206004820152602660248201527f56616c696461746f724d616e616765723a2076616c696461746f72206e6f742060448201526561637469766560d01b606482015260840161043a565b60038152426001600160401b031660c08201525f83815260088301602052604090208151815483929190829060ff1916600183600581111561210357612103612f05565b02179055506020820151600182015560408201516002820180546060850151608086015160a08701516001600160401b039586166001600160801b031990941693909317600160401b92861692909202919091176001600160801b0316600160801b918516919091026001600160c01b031617600160c01b9184169190910217905560c0909201516003909101805467ffffffffffffffff1916919092161790555f6121af84826129d5565b6080840151604080516001600160401b03909216825242602083015291935083925086917f13d58394cf269d48bcf927959a29a5ffee7c9924dafff8927ecdf3c48ffa7c67910160405180910390a350505050565b5f8082516027146122275760405162461bcd60e51b815260040161043a906134fb565b5f805b60028110156122765761223e8160016133f0565b612249906008613403565b61ffff1685828151811061225f5761225f6130a1565b016020015160f81c901b919091179060010161222a565b5061ffff8116156122995760405162461bcd60e51b815260040161043a90613544565b5f805b60048110156122f4576122b08160036133f0565b6122bb906008613403565b63ffffffff16866122cd8360026132b8565b815181106122dd576122dd6130a1565b016020015160f81c901b919091179060010161229c565b5063ffffffff811660031461231b5760405162461bcd60e51b815260040161043a90613587565b5f805b60208110156123705761233281601f6133f0565b61233d906008613403565b876123498360066132b8565b81518110612359576123596130a1565b016020015160f81c901b919091179060010161231e565b505f86602681518110612385576123856130a1565b016020015191976001600160f81b03199092161515965090945050505050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0054600160401b900460ff16610c3f57604051631afcd79f60e31b815260040160405180910390fd5b6123f66123a5565b6123fe612b2c565b610c6e81612b34565b61240f6123a5565b610c6e81612cd6565b5f805160206137da8339815191525f6001600160401b03808416908516111561244c576124458385613733565b9050612459565b6124568484613733565b90505b6040805160808101825260038401548082526004850154602083015260058501549282019290925260068401546001600160401b03166060820152429115806124bb5750600284015481516124b7916001600160401b0316906132b8565b8210155b156124e1576001600160401b038316606082015281815260408101516020820152612500565b82816060018181516124f39190613753565b6001600160401b03169052505b6060810151612510906064613773565b602082015160028601546001600160401b03929092169161253b9190600160401b900460ff16613403565b101561259f5760405162461bcd60e51b815260206004820152602d60248201527f56616c696461746f724d616e616765723a206d6178696d756d20636875726e2060448201526c1c985d1948195e18d959591959609a1b606482015260840161043a565b856001600160401b0316816040018181516125ba91906132b8565b9052506040810180516001600160401b03871691906125da9083906133f0565b905250805160038501556020810151600485015560408101516005850155606001516006909301805467ffffffffffffffff19166001600160401b039094169390931790925550505050565b5f60608260800151516030146126905760405162461bcd60e51b815260206004820152602960248201527f5374616b696e674d657373616765733a20696e76616c6964207369676e6174756044820152680e4ca40d8cadccee8d60bb1b606482015260840161043a565b60408051608680825260c082019092525f916020820181803683370190505090505f5b6002811015612707576126c78160016133f0565b6126d2906008613403565b5081515f908390839081106126e9576126e96130a1565b60200101906001600160f81b03191690815f1a9053506001016126b3565b505f5b600481101561276f5761271e8160036133f0565b612729906008613403565b600160ff919091161c60f81b826127418360026132b8565b81518110612751576127516130a1565b60200101906001600160f81b03191690815f1a90535060010161270a565b505f5b60208110156127cc578451816020811061278e5761278e6130a1565b1a60f81b8261279e8360066132b8565b815181106127ae576127ae6130a1565b60200101906001600160f81b03191690815f1a905350600101612772565b505f5b602081101561282c57846020015181602081106127ee576127ee6130a1565b1a60f81b826127fe8360266132b8565b8151811061280e5761280e6130a1565b60200101906001600160f81b03191690815f1a9053506001016127cf565b505f5b60088110156128a0576128438160076133f0565b61284e906008613403565b60ff1685604001516001600160401b0316901c60f81b8282604661287291906132b8565b81518110612882576128826130a1565b60200101906001600160f81b03191690815f1a90535060010161282f565b505f5b603081101561290b57846080015181815181106128c2576128c26130a1565b01602001516001600160f81b031916826128dd83604e6132b8565b815181106128ed576128ed6130a1565b60200101906001600160f81b03191690815f1a9053506001016128a3565b505f5b600881101561297d576129228160076133f0565b61292d906008613403565b60608601516001600160401b0390811691161c60f81b8261294f83607e6132b8565b8151811061295f5761295f6130a1565b60200101906001600160f81b03191690815f1a90535060010161290e565b5060028160405161298e9190613293565b602060405180830381855afa1580156129a9573d5f803e3d5ffd5b5050506040513d601f19601f820116820180604052508101906129cc9190613045565b94909350915050565b5f8281525f805160206137fa833981519152602052604081206002015481905f805160206137da83398151915290600160801b90046001600160401b0316612a1d8582612418565b5f612a2787612cde565b5f8881526008850160205260408120600201805467ffffffffffffffff60801b1916600160801b6001600160401b038b16021790559091506005600160991b0163ee5b48eb612a778a858b611065565b6040518263ffffffff1660e01b8152600401612a939190613013565b6020604051808303815f875af1158015612aaf573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612ad39190613045565b604080516001600160401b038a811682526020820184905282519394508516928b927f07de5ff35a674a8005e661f3333c907ca6333462808762d19dc7b3abb1a8c1df928290030190a3909450925050505b9250929050565b610c3f6123a5565b612b3c6123a5565b80355f805160206137da83398151915290815560208201357fe92546d698950ddd38910d2e15ed1d923cd0a7b3dde9e2a6a3f380565559cb01556014612b88608084016060850161379e565b60ff161115612bf55760405162461bcd60e51b815260206004820152603360248201527f56616c696461746f724d616e616765723a206d6178696d756d20636875726e206044820152720e0cae4c6cadce8c2ceca40e8dede40d0d2ced606b1b606482015260840161043a565b5f612c06608084016060850161379e565b60ff1611612c6e5760405162461bcd60e51b815260206004820152602f60248201527f56616c696461746f724d616e616765723a207a65726f206d6178696d756d206360448201526e6875726e2070657263656e7461676560881b606482015260840161043a565b612c7e608083016060840161379e565b60028201805460ff92909216600160401b0260ff60401b19909216919091179055612caf60608301604084016135ce565b600291909101805467ffffffffffffffff19166001600160401b0390921691909117905550565b6110336123a5565b5f8181525f805160206137fa8339815191526020526040812060020180545f805160206137da83398151915291600160401b9091046001600160401b0316906008612d28836137be565b82546101009290920a6001600160401b038181021990931691831602179091555f94855260089290920160205250604090922060020154600160401b9004909116919050565b508054612d7a906132ed565b5f825580601f10612d89575050565b601f0160209004905f5260205f2090810190610c6e91905b80821115612db4575f8155600101612da1565b5090565b5f60208284031215612dc8575f80fd5b5035919050565b803563ffffffff81168114612de2575f80fd5b919050565b5f60208284031215612df7575f80fd5b610c5482612dcf565b5f60808284031215612e10575f80fd5b50919050565b6001600160a01b0381168114610c6e575f80fd5b5f8060a08385031215612e3b575f80fd5b612e458484612e00565b91506080830135612e5581612e16565b809150509250929050565b5f8060408385031215612e71575f80fd5b82356001600160401b03811115612e86575f80fd5b612e9285828601612e00565b925050612ea160208401612dcf565b90509250929050565b80356001600160401b0381168114612de2575f80fd5b5f8060408385031215612ed1575f80fd5b82356001600160401b03811115612ee6575f80fd5b830160608186031215612ef7575f80fd5b9150612ea160208401612eaa565b634e487b7160e01b5f52602160045260245ffd5b815160e082019060068110612f3c57634e487b7160e01b5f52602160045260245ffd5b80835250602083015160208301526001600160401b0360408401511660408301526060830151612f7760608401826001600160401b03169052565b506080830151612f9260808401826001600160401b03169052565b5060a0830151612fad60a08401826001600160401b03169052565b5060c0830151612fc860c08401826001600160401b03169052565b5092915050565b5f60208284031215612fdf575f80fd5b8135612fea81612e16565b9392505050565b5f5b8381101561300b578181015183820152602001612ff3565b50505f910152565b602081525f8251806020840152613031816040850160208701612ff1565b601f01601f19169190910160400192915050565b5f60208284031215613055575f80fd5b5051919050565b5f808335601e19843603018112613071575f80fd5b8301803591506001600160401b0382111561308a575f80fd5b6020019150600581901b3603821315612b25575f80fd5b634e487b7160e01b5f52603260045260245ffd5b5f8235605e198336030181126130c9575f80fd5b9190910192915050565b634e487b7160e01b5f52604160045260245ffd5b604051606081016001600160401b0381118282101715613109576131096130d3565b60405290565b604051601f8201601f191681016001600160401b0381118282101715613137576131376130d3565b604052919050565b5f6001600160401b03821115613157576131576130d3565b50601f01601f191660200190565b5f60608236031215613175575f80fd5b61317d6130e7565b82358152602061318e818501612eaa565b8183015260408401356001600160401b038111156131aa575f80fd5b840136601f8201126131ba575f80fd5b80356131cd6131c88261313f565b61310f565b81815236848385010111156131e0575f80fd5b81848401858301375f9181019093015250604082015292915050565b60208082526028908201527f56616c696461746f724d616e616765723a206e6f646520494420616c72656164604082015267792061637469766560c01b606082015260800190565b5f8551613255818460208a01612ff1565b80830190508581526001600160401b0360c01b8560c01b1660208201528351613285816028840160208801612ff1565b016028019695505050505050565b5f82516130c9818460208701612ff1565b634e487b7160e01b5f52601160045260245ffd5b80820180821115610c5757610c576132a4565b5f63ffffffff8083168181036132e3576132e36132a4565b6001019392505050565b600181811c9082168061330157607f821691505b602082108103612e1057634e487b7160e01b5f52602260045260245ffd5b60208082526027908201527f56616c696461746f724d616e616765723a20696e76616c69642076616c6964616040820152661d1a5bdb88125160ca1b606082015260800190565b5f60208083525f8454613378816132ed565b806020870152604060018084165f811461339957600181146133b5576133e2565b60ff19851660408a0152604084151560051b8a010195506133e2565b895f5260205f205f5b858110156133d95781548b82018601529083019088016133be565b8a016040019650505b509398975050505050505050565b81810381811115610c5757610c576132a4565b8082028115828204841417610c5757610c576132a4565b80518015158114612de2575f80fd5b5f806040838503121561343a575f80fd5b82516001600160401b0380821115613450575f80fd5b9084019060608287031215613463575f80fd5b61346b6130e7565b8251815260208084015161347e81612e16565b82820152604084015183811115613493575f80fd5b80850194505087601f8501126134a7575f80fd5b835192506134b76131c88461313f565b83815288828587010111156134ca575f80fd5b6134d984838301848801612ff1565b806040840152508195506134ee81880161341a565b9450505050509250929050565b60208082526029908201527f56616c696461746f724d657373616765733a20696e76616c6964206d657373616040820152680ceca40d8cadccee8d60bb1b606082015260800190565b60208082526023908201527f56616c696461746f724d657373616765733a20696e76616c696420636f64656360408201526208125160ea1b606082015260800190565b60208082526027908201527f56616c696461746f724d657373616765733a20696e76616c6964206d657373616040820152666765207479706560c81b606082015260800190565b5f602082840312156135de575f80fd5b610c5482612eaa565b5f808335601e198436030181126135fc575f80fd5b8301803591506001600160401b03821115613615575f80fd5b602001915036819003821315612b25575f80fd5b601f8211156104d357805f5260205f20601f840160051c8101602085101561364e5750805b601f840160051c820191505b8181101561366d575f815560010161365a565b5050505050565b81516001600160401b0381111561368d5761368d6130d3565b6136a18161369b84546132ed565b84613629565b602080601f8311600181146136d4575f84156136bd5750858301515b5f19600386901b1c1916600185901b17855561372b565b5f85815260208120601f198616915b82811015613702578886015182559484019460019091019084016136e3565b508582101561371f57878501515f19600388901b60f8161c191681555b505060018460011b0185555b505050505050565b6001600160401b03828116828216039080821115612fc857612fc86132a4565b6001600160401b03818116838216019080821115612fc857612fc86132a4565b6001600160401b03818116838216028082169190828114613796576137966132a4565b505092915050565b5f602082840312156137ae575f80fd5b813560ff81168114612fea575f80fd5b5f6001600160401b038083168181036132e3576132e36132a456fee92546d698950ddd38910d2e15ed1d923cd0a7b3dde9e2a6a3f380565559cb00e92546d698950ddd38910d2e15ed1d923cd0a7b3dde9e2a6a3f380565559cb08a164736f6c6343000819000a diff --git a/pkg/validatormanager/validatormanager.go b/pkg/validatormanager/validatormanager.go new file mode 100644 index 000000000..0d62904c1 --- /dev/null +++ b/pkg/validatormanager/validatormanager.go @@ -0,0 +1,66 @@ +// Copyright (C) 2022, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. +package validatormanager + +import ( + _ "embed" + "math/big" + "strings" + + "github.com/ava-labs/avalanche-cli/pkg/contract" + "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/subnet-evm/core" + "github.com/ethereum/go-ethereum/common" +) + +const ( + PoAValidarorMessengerContractAddress = "0x5F584C2D56B4c356e7d82EC6129349393dc5df17" +) + +//go:embed deployed_poa_validator_manager_bytecode.txt +var deployedPoAValidatorManagerBytecode []byte + +func AddPoAValidatorManagerContractToAllocations( + allocs core.GenesisAlloc, +) { + deployedPoaValidatorManagerBytes := common.FromHex(strings.TrimSpace(string(deployedPoAValidatorManagerBytecode))) + allocs[common.HexToAddress(PoAValidarorMessengerContractAddress)] = core.GenesisAccount{ + Balance: big.NewInt(0), + Code: deployedPoaValidatorManagerBytes, + Nonce: 1, + } +} + +func InitializePoAValidatorManager( + rpcURL string, + remoteAddress common.Address, + privateKey string, + subnetID ids.ID, + initialOwner common.Address, +) error { + pChainBlockchainID := ids.Empty + churnPeriodSeconds := uint64(0) + maximumChurnPercentage := uint8(20) + type Params struct { + PChainBlockchainID [32]byte + SubnetID [32]byte + ChurnPeriodSeconds uint64 + MaximumChurnPercentage uint8 + } + params := Params{ + PChainBlockchainID: pChainBlockchainID, + SubnetID: subnetID, + ChurnPeriodSeconds: churnPeriodSeconds, + MaximumChurnPercentage: maximumChurnPercentage, + } + _, _, err := contract.TxToMethod( + rpcURL, + privateKey, + remoteAddress, + nil, + "initialize((bytes32,bytes32,uint64,uint8),address)", + params, + initialOwner, + ) + return err +} From c8c4e5ce98981a3617802dd1ac4240f21ffba894 Mon Sep 17 00:00:00 2001 From: Raymond Sukanto Date: Thu, 19 Sep 2024 12:56:20 -0400 Subject: [PATCH 39/64] address comments --- cmd/blockchaincmd/add_validator.go | 6 +++--- cmd/blockchaincmd/prompt_genesis_input.go | 6 +++--- cmd/blockchaincmd/remove_validator.go | 2 +- cmd/primarycmd/add_validator.go | 2 +- pkg/prompts/prompts.go | 2 +- pkg/prompts/validations.go | 6 +++--- 6 files changed, 12 insertions(+), 12 deletions(-) diff --git a/cmd/blockchaincmd/add_validator.go b/cmd/blockchaincmd/add_validator.go index 1df8f9473..779d8bf48 100644 --- a/cmd/blockchaincmd/add_validator.go +++ b/cmd/blockchaincmd/add_validator.go @@ -204,7 +204,7 @@ func CallAddValidator( ux.Logger.PrintToUser("Your subnet auth keys for add validator tx creation: %s", subnetAuthKeys) if nodeIDStr == "" { - nodeID, err = PromptNodeID() + nodeID, err = PromptNodeID("add as validator") if err != nil { return err } @@ -401,8 +401,8 @@ func promptStart() (time.Time, error) { return app.Prompt.CaptureDate(txt) } -func PromptNodeID() (ids.NodeID, error) { - txt := "What is the NodeID of the node you want to add as bootstrap validator?" +func PromptNodeID(goal string) (ids.NodeID, error) { + txt := fmt.Sprintf("What is the NodeID of the node you want to %s?", goal) return app.Prompt.CaptureNodeID(txt) } diff --git a/cmd/blockchaincmd/prompt_genesis_input.go b/cmd/blockchaincmd/prompt_genesis_input.go index 255e8a986..4a6854058 100644 --- a/cmd/blockchaincmd/prompt_genesis_input.go +++ b/cmd/blockchaincmd/prompt_genesis_input.go @@ -91,8 +91,8 @@ func promptValidatorManagementType( app *application.Avalanche, sidecar *models.Sidecar, ) error { - proofOfAuthorityOption := "Proof of Authority" - proofOfStakeOption := "Proof of Stake" + proofOfAuthorityOption := models.ProofOfAuthority + proofOfStakeOption := models.ProofOfStake explainOption := "Explain the difference" if createFlags.proofOfStake { sidecar.ValidatorManagement = models.ValidatorManagementTypeFromString(proofOfStakeOption) @@ -175,7 +175,7 @@ func promptBootstrapValidators() ([]models.SubnetValidator, error) { var nodeID ids.NodeID var publicKey, pop string if setUpNodes { - nodeID, err = PromptNodeID() + nodeID, err = PromptNodeID("add as bootstrap validator") if err != nil { return nil, err } diff --git a/cmd/blockchaincmd/remove_validator.go b/cmd/blockchaincmd/remove_validator.go index d1f495627..cd815b9d7 100644 --- a/cmd/blockchaincmd/remove_validator.go +++ b/cmd/blockchaincmd/remove_validator.go @@ -156,7 +156,7 @@ func removeValidator(_ *cobra.Command, args []string) error { ux.Logger.PrintToUser("Your subnet auth keys for remove validator tx creation: %s", subnetAuthKeys) if nodeIDStr == "" { - nodeID, err = PromptNodeID() + nodeID, err = PromptNodeID("remove as validator") if err != nil { return err } diff --git a/cmd/primarycmd/add_validator.go b/cmd/primarycmd/add_validator.go index ba3a8aa04..85ddab637 100644 --- a/cmd/primarycmd/add_validator.go +++ b/cmd/primarycmd/add_validator.go @@ -154,7 +154,7 @@ func addValidator(_ *cobra.Command, _ []string) error { } if nodeIDStr == "" { - nodeID, err = blockchaincmd.PromptNodeID() + nodeID, err = blockchaincmd.PromptNodeID("add as Primary Network Validator") if err != nil { return err } diff --git a/pkg/prompts/prompts.go b/pkg/prompts/prompts.go index 2006eecb5..ef4967931 100644 --- a/pkg/prompts/prompts.go +++ b/pkg/prompts/prompts.go @@ -269,7 +269,7 @@ func (*realPrompter) CaptureNodeID(promptStr string) (ids.NodeID, error) { func (*realPrompter) CaptureBootstrapInitialBalance(promptStr string) (uint64, error) { prompt := promptui.Prompt{ Label: promptStr, - Validate: validateBootstrapBalance, + Validate: validateBootstrapValidatorBalance, } amountStr, err := prompt.Run() diff --git a/pkg/prompts/validations.go b/pkg/prompts/validations.go index ad9fd4326..2671eb051 100644 --- a/pkg/prompts/validations.go +++ b/pkg/prompts/validations.go @@ -129,13 +129,13 @@ func validateWeight(input string) error { return nil } -func validateBootstrapBalance(input string) error { +func validateBootstrapValidatorBalance(input string) error { val, err := strconv.ParseUint(input, 10, 64) if err != nil { return err } - if val < constants.InitialBalanceBootstrapValidator { - return fmt.Errorf("initial bootstrap validator balance must be at least %d AVAX", constants.InitialBalanceBootstrapValidator) + if val <= 0 { + return fmt.Errorf("initial bootstrap validator balance must be greater than 0 AVAX") } return nil } From a66cb3283b833df44fc1d7e2a1ada4d376c97e32 Mon Sep 17 00:00:00 2001 From: Raymond Sukanto Date: Thu, 19 Sep 2024 12:59:09 -0400 Subject: [PATCH 40/64] address comments --- cmd/blockchaincmd/prompt_genesis_input.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/cmd/blockchaincmd/prompt_genesis_input.go b/cmd/blockchaincmd/prompt_genesis_input.go index 4a6854058..618a5271d 100644 --- a/cmd/blockchaincmd/prompt_genesis_input.go +++ b/cmd/blockchaincmd/prompt_genesis_input.go @@ -47,14 +47,14 @@ func getTokenMinterAddr() ([]string, error) { if !yes { return nil, nil } - addr, cancelled, err := getAddr() + addresses, cancelled, err := getAddr() if err != nil { return nil, err } if cancelled { return nil, nil } - return addr, nil + return addresses, nil } func getAddr() ([]string, bool, error) { @@ -73,12 +73,12 @@ func promptProofOfPossession() (string, string, error) { ux.Logger.PrintToUser("Next, we need the public key and proof of possession of the node's BLS") ux.Logger.PrintToUser("Check https://docs.avax.network/api-reference/info-api#infogetnodeid for instructions on calling info.getNodeID API") var err error - txt := "What is the public key of the node's BLS?" + txt := "What is the node's BLS public key?" publicKey, err := app.Prompt.CaptureValidatedString(txt, prompts.ValidateHexa) if err != nil { return "", "", err } - txt = "What is the proof of possession of the node's BLS?" + txt = "What is the node's BLS proof of possession?" proofOfPossesion, err := app.Prompt.CaptureValidatedString(txt, prompts.ValidateHexa) if err != nil { return "", "", err From 890d6dbdf3050db101d39257c706fd26c4d4a63a Mon Sep 17 00:00:00 2001 From: Raymond Sukanto Date: Thu, 19 Sep 2024 14:08:29 -0400 Subject: [PATCH 41/64] address comments --- cmd/blockchaincmd/add_validator.go | 2 +- cmd/blockchaincmd/create.go | 3 +++ cmd/blockchaincmd/prompt_genesis_input.go | 2 +- pkg/constants/constants.go | 2 +- 4 files changed, 6 insertions(+), 3 deletions(-) diff --git a/cmd/blockchaincmd/add_validator.go b/cmd/blockchaincmd/add_validator.go index 779d8bf48..41209362b 100644 --- a/cmd/blockchaincmd/add_validator.go +++ b/cmd/blockchaincmd/add_validator.go @@ -220,7 +220,7 @@ func CallAddValidator( return err } if selectedWeight < constants.MinStakeWeight { - return fmt.Errorf("illegal weight, must be greater than or equal to %d: %d", constants.MinStakeWeight, selectedWeight) + return fmt.Errorf("invalid weight, must be greater than or equal to %d: %d", constants.MinStakeWeight, selectedWeight) } start, selectedDuration, err := getTimeParameters(network, nodeID, true) diff --git a/cmd/blockchaincmd/create.go b/cmd/blockchaincmd/create.go index 3cc31a1d5..97f930b8e 100644 --- a/cmd/blockchaincmd/create.go +++ b/cmd/blockchaincmd/create.go @@ -507,6 +507,9 @@ func checkInvalidSubnetNames(name string) error { } func LoadBootstrapValidator(filepath string) ([]models.SubnetValidator, error) { + if !utils.FileExists(filepath) { + return nil, fmt.Errorf("file path %q doesn't exist", filepath) + } jsonBytes, err := os.ReadFile(filepath) if err != nil { return nil, err diff --git a/cmd/blockchaincmd/prompt_genesis_input.go b/cmd/blockchaincmd/prompt_genesis_input.go index 618a5271d..25a5c3616 100644 --- a/cmd/blockchaincmd/prompt_genesis_input.go +++ b/cmd/blockchaincmd/prompt_genesis_input.go @@ -200,7 +200,7 @@ func promptBootstrapValidators() ([]models.SubnetValidator, error) { previousAddr = changeAddr subnetValidator := models.SubnetValidator{ NodeID: nodeID.String(), - Weight: constants.DefaultWeightBootstrapValidator, + Weight: constants.DefaultBootstrapValidatorWeight, Balance: constants.InitialBalanceBootstrapValidator, BLSPublicKey: publicKey, BLSProofOfPossession: pop, diff --git a/pkg/constants/constants.go b/pkg/constants/constants.go index 6d28d8cff..d6b2e1628 100644 --- a/pkg/constants/constants.go +++ b/pkg/constants/constants.go @@ -157,7 +157,7 @@ const ( TimeParseLayout = "2006-01-02 15:04:05" MinStakeWeight = 1 InitialBalanceBootstrapValidator = 1 - DefaultWeightBootstrapValidator = 1000000 + DefaultBootstrapValidatorWeight = 1000000 DefaultStakeWeight = 20 AVAXSymbol = "AVAX" DefaultFujiStakeDuration = "48h" From b55a7926f4b081dda0d8c289a3fd116246c141d8 Mon Sep 17 00:00:00 2001 From: Raymond Sukanto Date: Thu, 19 Sep 2024 14:57:51 -0400 Subject: [PATCH 42/64] move validator prompt to deploy --- cmd/blockchaincmd/create.go | 61 ++------------- cmd/blockchaincmd/deploy.go | 93 +++++++++++++++++------ cmd/blockchaincmd/prompt_genesis_input.go | 6 +- cmd/blockchaincmd/prompt_owners.go | 35 +-------- cmd/blockchaincmd/upgradecmd/apply.go | 4 +- cmd/transactioncmd/transaction_commit.go | 2 +- pkg/application/app.go | 2 + pkg/models/sidecar.go | 14 +++- pkg/networkoptions/network_options.go | 25 ------ 9 files changed, 97 insertions(+), 145 deletions(-) diff --git a/cmd/blockchaincmd/create.go b/cmd/blockchaincmd/create.go index 97f930b8e..8ef4f6009 100644 --- a/cmd/blockchaincmd/create.go +++ b/cmd/blockchaincmd/create.go @@ -50,17 +50,14 @@ type CreateFlags struct { validatorManagerMintOnly bool tokenMinterAddress []string validatorManagerController []string - generateNodeID bool } var ( - createFlags CreateFlags - forceCreate bool - genesisFile string - vmFile string - useRepo bool - bootstrapValidatorsJSONFilePath string - + createFlags CreateFlags + forceCreate bool + genesisFile string + vmFile string + useRepo bool errIllegalNameCharacter = errors.New( "illegal name character: only letters, no special characters allowed") errMutuallyExlusiveVersionOptions = errors.New("version flags --latest,--pre-release,vm-version are mutually exclusive") @@ -116,8 +113,6 @@ configuration, pass the -f flag.`, cmd.Flags().BoolVar(&createFlags.validatorManagerMintOnly, "validator-manager-mint-only", false, "only enable validator manager contract to mint new native tokens") cmd.Flags().StringSliceVar(&createFlags.tokenMinterAddress, "token-minter-address", nil, "addresses that can mint new native tokens (for proof of authority validator management only)") cmd.Flags().StringSliceVar(&createFlags.validatorManagerController, "validator-manager-controller", nil, "addresses that will control Validator Manager contract") - cmd.Flags().StringVar(&bootstrapValidatorsJSONFilePath, "bootstrap-filepath", "", "JSON file path that provides details about bootstrap validators, leave Node-ID and BLS values empty if using --generate-node-id=true") - cmd.Flags().BoolVar(&createFlags.generateNodeID, "generate-node-id", false, "whether to create new node id for bootstrap validators (Node-ID and BLS values in bootstrap JSON file will be overridden if --bootstrap-filepath flag is used)") return cmd } @@ -220,15 +215,6 @@ func createBlockchainConfig(cmd *cobra.Command, args []string) error { } } - var bootstrapValidators []models.SubnetValidator - var err error - if bootstrapValidatorsJSONFilePath != "" { - bootstrapValidators, err = LoadBootstrapValidator(bootstrapValidatorsJSONFilePath) - if err != nil { - return err - } - } - // get vm kind vmType, err := vm.PromptVMType(app, createFlags.useSubnetEvm, createFlags.useCustomVM) if err != nil { @@ -423,14 +409,6 @@ func createBlockchainConfig(cmd *cobra.Command, args []string) error { return err } - if bootstrapValidatorsJSONFilePath == "" { - bootstrapValidators, err = promptBootstrapValidators() - if err != nil { - return err - } - } - sc.BootstrapValidators = bootstrapValidators - if err = app.CreateSidecar(sc); err != nil { return err } @@ -505,32 +483,3 @@ func checkInvalidSubnetNames(name string) error { } return nil } - -func LoadBootstrapValidator(filepath string) ([]models.SubnetValidator, error) { - if !utils.FileExists(filepath) { - return nil, fmt.Errorf("file path %q doesn't exist", filepath) - } - jsonBytes, err := os.ReadFile(filepath) - if err != nil { - return nil, err - } - var subnetValidators []models.SubnetValidator - if err = json.Unmarshal(jsonBytes, &subnetValidators); err != nil { - return nil, err - } - if err = validateSubnetValidatorsJSON(createFlags.generateNodeID, subnetValidators); err != nil { - return nil, err - } - if createFlags.generateNodeID { - for _, subnetValidator := range subnetValidators { - nodeID, publicKey, pop, err := generateNewNodeAndBLS() - if err != nil { - return nil, err - } - subnetValidator.NodeID = nodeID - subnetValidator.BLSPublicKey = publicKey - subnetValidator.BLSProofOfPossession = pop - } - } - return subnetValidators, nil -} diff --git a/cmd/blockchaincmd/deploy.go b/cmd/blockchaincmd/deploy.go index 23f451bf6..119d7f6d0 100644 --- a/cmd/blockchaincmd/deploy.go +++ b/cmd/blockchaincmd/deploy.go @@ -6,6 +6,7 @@ import ( "encoding/json" "errors" "fmt" + "github.com/ava-labs/avalanche-cli/pkg/utils" "os" "path/filepath" "strings" @@ -36,27 +37,28 @@ import ( var deploySupportedNetworkOptions = []networkoptions.NetworkOption{networkoptions.Local, networkoptions.Devnet, networkoptions.Fuji, networkoptions.Mainnet} var ( - sameControlKey bool - keyName string - threshold uint32 - controlKeys []string - subnetAuthKeys []string - userProvidedAvagoVersion string - outputTxPath string - useLedger bool - useEwoq bool - ledgerAddresses []string - subnetIDStr string - mainnetChainID uint32 - skipCreatePrompt bool - avagoBinaryPath string - subnetOnly bool - teleporterEsp subnet.TeleporterEsp - - errMutuallyExlusiveControlKeys = errors.New("--control-keys and --same-control-key are mutually exclusive") - ErrMutuallyExlusiveKeyLedger = errors.New("key source flags --key, --ledger/--ledger-addrs are mutually exclusive") - ErrStoredKeyOnMainnet = errors.New("key --key is not available for mainnet operations") - errMutuallyExlusiveSubnetFlags = errors.New("--subnet-only and --subnet-id are mutually exclusive") + sameControlKey bool + keyName string + threshold uint32 + controlKeys []string + subnetAuthKeys []string + userProvidedAvagoVersion string + outputTxPath string + useLedger bool + useEwoq bool + ledgerAddresses []string + subnetIDStr string + mainnetChainID uint32 + skipCreatePrompt bool + avagoBinaryPath string + subnetOnly bool + generateNodeID bool + teleporterEsp subnet.TeleporterEsp + bootstrapValidatorsJSONFilePath string + errMutuallyExlusiveControlKeys = errors.New("--control-keys and --same-control-key are mutually exclusive") + ErrMutuallyExlusiveKeyLedger = errors.New("key source flags --key, --ledger/--ledger-addrs are mutually exclusive") + ErrStoredKeyOnMainnet = errors.New("key --key is not available for mainnet operations") + errMutuallyExlusiveSubnetFlags = errors.New("--subnet-only and --subnet-id are mutually exclusive") ) // avalanche blockchain deploy @@ -100,6 +102,8 @@ so you can take your locally tested Subnet and deploy it on Fuji or Mainnet.`, cmd.Flags().StringVar(&teleporterEsp.MessengerDeployerAddressPath, "teleporter-messenger-deployer-address-path", "", "path to a teleporter messenger deployer address file") cmd.Flags().StringVar(&teleporterEsp.MessengerDeployerTxPath, "teleporter-messenger-deployer-tx-path", "", "path to a teleporter messenger deployer tx file") cmd.Flags().StringVar(&teleporterEsp.RegistryBydecodePath, "teleporter-registry-bytecode-path", "", "path to a teleporter registry bytecode file") + cmd.Flags().StringVar(&bootstrapValidatorsJSONFilePath, "bootstrap-filepath", "", "JSON file path that provides details about bootstrap validators, leave Node-ID and BLS values empty if using --generate-node-id=true") + cmd.Flags().BoolVar(&generateNodeID, "generate-node-id", false, "whether to create new node id for bootstrap validators (Node-ID and BLS values in bootstrap JSON file will be overridden if --bootstrap-filepath flag is used)") return cmd } @@ -274,6 +278,14 @@ func deployBlockchain(cmd *cobra.Command, args []string) error { } } + var bootstrapValidators []models.SubnetValidator + if bootstrapValidatorsJSONFilePath != "" { + bootstrapValidators, err = LoadBootstrapValidator(bootstrapValidatorsJSONFilePath) + if err != nil { + return err + } + } + chain := chains[0] sidecar, err := app.LoadSidecar(chain) @@ -335,6 +347,13 @@ func deployBlockchain(cmd *cobra.Command, args []string) error { } } + if bootstrapValidatorsJSONFilePath == "" { + bootstrapValidators, err = promptBootstrapValidators(network) + if err != nil { + return err + } + } + ux.Logger.PrintToUser("Deploying %s to %s", chains, network.Name()) if network.Kind == models.Local { @@ -386,6 +405,7 @@ func deployBlockchain(cmd *cobra.Command, args []string) error { deployInfo.BlockchainID, deployInfo.TeleporterMessengerAddress, deployInfo.TeleporterRegistryAddress, + bootstrapValidators, ); err != nil { return err } @@ -552,7 +572,7 @@ func deployBlockchain(cmd *cobra.Command, args []string) error { // update sidecar // TODO: need to do something for backwards compatibility? - return app.UpdateSidecarNetworks(&sidecar, network, subnetID, blockchainID, "", "") + return app.UpdateSidecarNetworks(&sidecar, network, subnetID, blockchainID, "", "", bootstrapValidators) } func ValidateSubnetNameAndGetChains(args []string) ([]string, error) { @@ -725,3 +745,32 @@ func CheckForInvalidDeployAndGetAvagoVersion( } return desiredAvagoVersion, nil } + +func LoadBootstrapValidator(filepath string) ([]models.SubnetValidator, error) { + if !utils.FileExists(filepath) { + return nil, fmt.Errorf("file path %q doesn't exist", filepath) + } + jsonBytes, err := os.ReadFile(filepath) + if err != nil { + return nil, err + } + var subnetValidators []models.SubnetValidator + if err = json.Unmarshal(jsonBytes, &subnetValidators); err != nil { + return nil, err + } + if err = validateSubnetValidatorsJSON(generateNodeID, subnetValidators); err != nil { + return nil, err + } + if generateNodeID { + for _, subnetValidator := range subnetValidators { + nodeID, publicKey, pop, err := generateNewNodeAndBLS() + if err != nil { + return nil, err + } + subnetValidator.NodeID = nodeID + subnetValidator.BLSPublicKey = publicKey + subnetValidator.BLSProofOfPossession = pop + } + } + return subnetValidators, nil +} diff --git a/cmd/blockchaincmd/prompt_genesis_input.go b/cmd/blockchaincmd/prompt_genesis_input.go index 25a5c3616..9edc33d85 100644 --- a/cmd/blockchaincmd/prompt_genesis_input.go +++ b/cmd/blockchaincmd/prompt_genesis_input.go @@ -152,7 +152,7 @@ func generateNewNodeAndBLS() (string, string, string, error) { return nodeID.String(), publicKey, pop, nil } -func promptBootstrapValidators() ([]models.SubnetValidator, error) { +func promptBootstrapValidators(network models.Network) ([]models.SubnetValidator, error) { var subnetValidators []models.SubnetValidator numBootstrapValidators, err := app.Prompt.CaptureInt( "How many bootstrap validators do you want to set up?", @@ -161,7 +161,7 @@ func promptBootstrapValidators() ([]models.SubnetValidator, error) { return nil, err } var setUpNodes bool - if createFlags.generateNodeID { + if generateNodeID { setUpNodes = true } else { setUpNodes, err = promptSetUpNodes() @@ -193,7 +193,7 @@ func promptBootstrapValidators() ([]models.SubnetValidator, error) { return nil, err } } - changeAddr, err := getKeyForChangeOwner(previousAddr) + changeAddr, err := getKeyForChangeOwner(previousAddr, network) if err != nil { return nil, err } diff --git a/cmd/blockchaincmd/prompt_owners.go b/cmd/blockchaincmd/prompt_owners.go index deecbb91c..8eeca8ccc 100644 --- a/cmd/blockchaincmd/prompt_owners.go +++ b/cmd/blockchaincmd/prompt_owners.go @@ -9,9 +9,6 @@ import ( "strconv" "strings" - "github.com/ava-labs/avalanche-cli/pkg/networkoptions" - "github.com/ava-labs/avalanche-cli/pkg/utils" - "github.com/ava-labs/avalanche-cli/pkg/constants" "github.com/ava-labs/avalanche-cli/pkg/key" "github.com/ava-labs/avalanche-cli/pkg/keychain" @@ -309,7 +306,7 @@ func getThreshold(maxLen int) (uint32, error) { return uint32(intTh), err } -func getKeyForChangeOwner(previouslyUsedAddr string) (string, error) { +func getKeyForChangeOwner(previouslyUsedAddr string, network models.Network) (string, error) { moreKeysPrompt := "Which key would you like to set as change owner for leftover AVAX if the node is removed from validator set?" const ( @@ -333,10 +330,6 @@ func getKeyForChangeOwner(previouslyUsedAddr string) (string, error) { case previousAddres: key = previouslyUsedAddr case getFromStored: - network, err := promptNetwork() - if err != nil { - return "", err - } key, err = prompts.CaptureKeyAddress( app.Prompt, "be set as a change owner for leftover AVAX", @@ -361,29 +354,3 @@ func getKeyForChangeOwner(previouslyUsedAddr string) (string, error) { } return key, nil } - -func promptNetwork() (models.Network, error) { - promptStr := "Choose a network that the bootstrap validators will be validating" - supportedNetworkOptionsToPrompt := []networkoptions.NetworkOption{networkoptions.Local, networkoptions.Devnet, networkoptions.Fuji, networkoptions.Mainnet} - - networkOptionStr, err := app.Prompt.CaptureList( - promptStr, - utils.Map(supportedNetworkOptionsToPrompt, func(n networkoptions.NetworkOption) string { return n.String() }), - ) - if err != nil { - return models.UndefinedNetwork, err - } - networkOption := networkoptions.NetworkOptionFromString(networkOptionStr) - network := models.UndefinedNetwork - if networkOption == networkoptions.Devnet { - endpoint, err := app.Prompt.CaptureURL(fmt.Sprintf("%s Endpoint", networkOption.String()), false) - if err != nil { - return models.UndefinedNetwork, err - } - network, err = networkOption.ModelNetwork(endpoint) - if err != nil { - return models.UndefinedNetwork, err - } - } - return network, nil -} diff --git a/cmd/blockchaincmd/upgradecmd/apply.go b/cmd/blockchaincmd/upgradecmd/apply.go index 5208be1cf..744c348a6 100644 --- a/cmd/blockchaincmd/upgradecmd/apply.go +++ b/cmd/blockchaincmd/upgradecmd/apply.go @@ -254,7 +254,7 @@ func applyPublicNetworkUpgrade(blockchainName, networkKey string, sc *models.Sid if print { blockchainIDstr := "" if sc.Networks != nil && - sc.Networks[networkKey] != (models.NetworkData{}) && + !sc.NetworkDataIsEmpty(networkKey) && sc.Networks[networkKey].BlockchainID != ids.Empty { blockchainIDstr = sc.Networks[networkKey].BlockchainID.String() } @@ -319,7 +319,7 @@ func applyPublicNetworkUpgrade(blockchainName, networkKey string, sc *models.Sid func validateUpgrade(blockchainName, networkKey string, sc *models.Sidecar, skipPrompting bool) ([]params.PrecompileUpgrade, string, error) { // if there's no entry in the Sidecar, we assume there hasn't been a deploy yet - if sc.Networks[networkKey] == (models.NetworkData{}) { + if sc.NetworkDataIsEmpty(networkKey) { return nil, "", subnetNotYetDeployed() } chainID := sc.Networks[networkKey].BlockchainID diff --git a/cmd/transactioncmd/transaction_commit.go b/cmd/transactioncmd/transaction_commit.go index 21712c924..f1ff6568d 100644 --- a/cmd/transactioncmd/transaction_commit.go +++ b/cmd/transactioncmd/transaction_commit.go @@ -97,7 +97,7 @@ func commitTx(_ *cobra.Command, args []string) error { if err := blockchaincmd.PrintDeployResults(subnetName, subnetID, txID); err != nil { return err } - return app.UpdateSidecarNetworks(&sc, network, subnetID, txID, "", "") + return app.UpdateSidecarNetworks(&sc, network, subnetID, txID, "", "", sc.Networks[network.Name()].BootstrapValidators) } return nil diff --git a/pkg/application/app.go b/pkg/application/app.go index cc2b2f1fe..6e8147019 100644 --- a/pkg/application/app.go +++ b/pkg/application/app.go @@ -520,6 +520,7 @@ func (app *Avalanche) UpdateSidecarNetworks( blockchainID ids.ID, teleporterMessengerAddress string, teleporterRegistryAddress string, + bootstrapValidators []models.SubnetValidator, ) error { if sc.Networks == nil { sc.Networks = make(map[string]models.NetworkData) @@ -530,6 +531,7 @@ func (app *Avalanche) UpdateSidecarNetworks( RPCVersion: sc.RPCVersion, TeleporterMessengerAddress: teleporterMessengerAddress, TeleporterRegistryAddress: teleporterRegistryAddress, + BootstrapValidators: bootstrapValidators, } if err := app.UpdateSidecar(sc); err != nil { return fmt.Errorf("creation of chains and subnet was successful, but failed to update sidecar: %w", err) diff --git a/pkg/models/sidecar.go b/pkg/models/sidecar.go index babba8605..f58a2731d 100644 --- a/pkg/models/sidecar.go +++ b/pkg/models/sidecar.go @@ -13,6 +13,7 @@ type NetworkData struct { RPCVersion int TeleporterMessengerAddress string TeleporterRegistryAddress string + BootstrapValidators []SubnetValidator } type Sidecar struct { @@ -42,8 +43,6 @@ type Sidecar struct { ValidatorManagement ValidatorManagementType ValidatorManagerController []string NewNativeTokenMinter []string - // TODO: replace this object with avalanchego struct SubnetValidator - BootstrapValidators []SubnetValidator } func (sc Sidecar) GetVMID() (string, error) { @@ -60,3 +59,14 @@ func (sc Sidecar) GetVMID() (string, error) { } return vmid, nil } + +func (sc Sidecar) NetworkDataIsEmpty(network string) bool { + if sc.Networks[network].SubnetID == ids.Empty && + sc.Networks[network].BlockchainID == ids.Empty && + sc.Networks[network].RPCVersion == 0 && + sc.Networks[network].TeleporterMessengerAddress == "" && + sc.Networks[network].TeleporterRegistryAddress == "" { + return true + } + return false +} diff --git a/pkg/networkoptions/network_options.go b/pkg/networkoptions/network_options.go index 3eeb9f394..bc1afaf51 100644 --- a/pkg/networkoptions/network_options.go +++ b/pkg/networkoptions/network_options.go @@ -62,31 +62,6 @@ func NetworkOptionFromString(s string) NetworkOption { return Undefined } -func (n NetworkOption) ModelNetwork(devnetEndpoint string) (models.Network, error) { - network := models.UndefinedNetwork - switch n { - case Local: - network = models.NewLocalNetwork() - case Devnet: - networkID := uint32(0) - if devnetEndpoint != "" { - infoClient := info.NewClient(devnetEndpoint) - ctx, cancel := utils.GetAPIContext() - defer cancel() - _, err := infoClient.GetNetworkID(ctx) - if err != nil { - return models.UndefinedNetwork, err - } - } - network = models.NewDevnetNetwork(devnetEndpoint, networkID) - case Fuji: - network = models.NewFujiNetwork() - case Mainnet: - network = models.NewMainnetNetwork() - } - return network, nil -} - type NetworkFlags struct { UseLocal bool UseDevnet bool From 58bfdae6045f573ec709a76f07056380a0df8a76 Mon Sep 17 00:00:00 2001 From: Raymond Sukanto Date: Thu, 19 Sep 2024 15:19:28 -0400 Subject: [PATCH 43/64] address comments --- cmd/blockchaincmd/deploy.go | 3 ++- cmd/blockchaincmd/prompt_genesis_input.go | 26 ++++++++++++++++++++++- cmd/blockchaincmd/prompt_owners.go | 4 +--- pkg/constants/constants.go | 1 - 4 files changed, 28 insertions(+), 6 deletions(-) diff --git a/cmd/blockchaincmd/deploy.go b/cmd/blockchaincmd/deploy.go index 119d7f6d0..90d1b3487 100644 --- a/cmd/blockchaincmd/deploy.go +++ b/cmd/blockchaincmd/deploy.go @@ -6,11 +6,12 @@ import ( "encoding/json" "errors" "fmt" - "github.com/ava-labs/avalanche-cli/pkg/utils" "os" "path/filepath" "strings" + "github.com/ava-labs/avalanche-cli/pkg/utils" + "github.com/ava-labs/avalanche-cli/pkg/binutils" "github.com/ava-labs/avalanche-cli/pkg/cobrautils" "github.com/ava-labs/avalanche-cli/pkg/constants" diff --git a/cmd/blockchaincmd/prompt_genesis_input.go b/cmd/blockchaincmd/prompt_genesis_input.go index 9edc33d85..56724724e 100644 --- a/cmd/blockchaincmd/prompt_genesis_input.go +++ b/cmd/blockchaincmd/prompt_genesis_input.go @@ -22,7 +22,31 @@ func getValidatorContractManagerAddr() ([]string, bool, error) { controllerAddrPrompt := "Enter Validator Manager Contract controller address" for { // ask in a loop so that if some condition is not met we can keep asking - controlAddr, cancelled, err := getAddrLoop(controllerAddrPrompt, constants.ValidatorManagerController, models.UndefinedNetwork) + controlAddr, cancelled, err := prompts.CaptureListDecision( + // we need this to be able to mock test + app.Prompt, + // the main prompt for entering address keys + controllerAddrPrompt, + // the Capture function to use + func(_ string) (string, error) { + return prompts.PromptAddress( + app.Prompt, + "enable as controller of ValidatorManager contract", + app.GetKeyDir(), + app.GetKey, + "", + models.UndefinedNetwork, + prompts.EVMFormat, + "Enter address", + ) + }, + // the prompt for each address + "", + // label describes the entity we are prompting for (e.g. address, control key, etc.) + "Validator Manager Controller", + //TODO: add info here on what this validator manager controller is + "", + ) if err != nil { return nil, false, err } diff --git a/cmd/blockchaincmd/prompt_owners.go b/cmd/blockchaincmd/prompt_owners.go index 8eeca8ccc..04da2ff1f 100644 --- a/cmd/blockchaincmd/prompt_owners.go +++ b/cmd/blockchaincmd/prompt_owners.go @@ -232,7 +232,7 @@ func enterCustomKeys(network models.Network) ([]string, bool, error) { } // getAddrLoop asks as many addresses the user requires, until Done or Cancel is selected -// TODO: add info for TokenMinter and ValidatorManagerController +// TODO: add info for TokenMinter func getAddrLoop(prompt, label string, network models.Network) ([]string, bool, error) { info := "" goal := "" @@ -243,8 +243,6 @@ func getAddrLoop(prompt, label string, network models.Network) ([]string, bool, goal = "be set as a subnet control key" case constants.TokenMinter: goal = "enable as new native token minter" - case constants.ValidatorManagerController: - goal = "enable as controller of ValidatorManager contract" default: } customPrompt := "Enter P-Chain address (Example: P-...)" diff --git a/pkg/constants/constants.go b/pkg/constants/constants.go index d6b2e1628..a4dfc3d49 100644 --- a/pkg/constants/constants.go +++ b/pkg/constants/constants.go @@ -29,7 +29,6 @@ const ( AliasesFileName = "aliases.json" ControlKey = "Control key" TokenMinter = "Native token minter" - ValidatorManagerController = "Validator Manager Controller" SidecarSuffix = SuffixSeparator + SidecarFileName GenesisSuffix = SuffixSeparator + GenesisFileName NodeFileName = "node.json" From 9fe693e2277be052d500bfa40b2887cec36e2238 Mon Sep 17 00:00:00 2001 From: Raymond Sukanto Date: Thu, 19 Sep 2024 15:47:22 -0400 Subject: [PATCH 44/64] address comments --- cmd/blockchaincmd/deploy.go | 5 +---- cmd/blockchaincmd/prompt_genesis_input.go | 4 ++-- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/cmd/blockchaincmd/deploy.go b/cmd/blockchaincmd/deploy.go index 90d1b3487..09c4a16a9 100644 --- a/cmd/blockchaincmd/deploy.go +++ b/cmd/blockchaincmd/deploy.go @@ -764,13 +764,10 @@ func LoadBootstrapValidator(filepath string) ([]models.SubnetValidator, error) { } if generateNodeID { for _, subnetValidator := range subnetValidators { - nodeID, publicKey, pop, err := generateNewNodeAndBLS() + subnetValidator.NodeID, subnetValidator.BLSPublicKey, subnetValidator.BLSProofOfPossession, err = generateNewNodeAndBLS() if err != nil { return nil, err } - subnetValidator.NodeID = nodeID - subnetValidator.BLSPublicKey = publicKey - subnetValidator.BLSProofOfPossession = pop } } return subnetValidators, nil diff --git a/cmd/blockchaincmd/prompt_genesis_input.go b/cmd/blockchaincmd/prompt_genesis_input.go index 56724724e..6f84729cd 100644 --- a/cmd/blockchaincmd/prompt_genesis_input.go +++ b/cmd/blockchaincmd/prompt_genesis_input.go @@ -119,11 +119,11 @@ func promptValidatorManagementType( proofOfStakeOption := models.ProofOfStake explainOption := "Explain the difference" if createFlags.proofOfStake { - sidecar.ValidatorManagement = models.ValidatorManagementTypeFromString(proofOfStakeOption) + sidecar.ValidatorManagement = models.ProofOfStake return nil } if createFlags.proofOfAuthority { - sidecar.ValidatorManagement = models.ValidatorManagementTypeFromString(proofOfAuthorityOption) + sidecar.ValidatorManagement = models.ProofOfAuthority return nil } options := []string{proofOfAuthorityOption, proofOfStakeOption, explainOption} From bfb0c67191603702067b9527bd40eb55087a74d7 Mon Sep 17 00:00:00 2001 From: Raymond Sukanto Date: Thu, 19 Sep 2024 16:11:39 -0400 Subject: [PATCH 45/64] fix lint --- cmd/blockchaincmd/prompt_genesis_input.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/blockchaincmd/prompt_genesis_input.go b/cmd/blockchaincmd/prompt_genesis_input.go index 6f84729cd..4103564b3 100644 --- a/cmd/blockchaincmd/prompt_genesis_input.go +++ b/cmd/blockchaincmd/prompt_genesis_input.go @@ -44,7 +44,7 @@ func getValidatorContractManagerAddr() ([]string, bool, error) { "", // label describes the entity we are prompting for (e.g. address, control key, etc.) "Validator Manager Controller", - //TODO: add info here on what this validator manager controller is + // TODO: add info here on what this validator manager controller is "", ) if err != nil { From 9d7bac82a4a840e7670ed8352a958436cb310f82 Mon Sep 17 00:00:00 2001 From: Raymond Sukanto Date: Thu, 19 Sep 2024 16:35:37 -0400 Subject: [PATCH 46/64] address comments --- cmd/blockchaincmd/create.go | 81 +----------------------------- cmd/blockchaincmd/prompt_owners.go | 34 ++++--------- pkg/constants/constants.go | 3 -- pkg/models/sidecar.go | 4 +- 4 files changed, 13 insertions(+), 109 deletions(-) diff --git a/cmd/blockchaincmd/create.go b/cmd/blockchaincmd/create.go index 760e6edd8..4bf9593dd 100644 --- a/cmd/blockchaincmd/create.go +++ b/cmd/blockchaincmd/create.go @@ -49,8 +49,6 @@ type CreateFlags struct { useExternalGasToken bool proofOfStake bool proofOfAuthority bool - validatorManagerMintOnly bool - tokenMinterAddress []string validatorManagerController []string } @@ -66,8 +64,6 @@ var ( errMutuallyExlusiveVersionOptions = errors.New("version flags --latest,--pre-release,vm-version are mutually exclusive") errMutuallyExclusiveVMConfigOptions = errors.New("--genesis flag disables --evm-chain-id,--evm-defaults,--production-defaults,--test-defaults") errMutuallyExlusiveValidatorManagementOptions = errors.New("validator management type flags --proof-of-authority,--proof-of-stake are mutually exclusive") - errTokenMinterAddressConflict = errors.New("--validator-manager-mint-only means that no additional addresses can be provided in --token-minter-address") - errTokenMinterAddressForPoS = errors.New("--token-minter-address is only applicable to proof of authority") ) // avalanche blockchain create @@ -113,8 +109,6 @@ configuration, pass the -f flag.`, cmd.Flags().BoolVar(&createFlags.useExternalGasToken, "external-gas-token", false, "use a gas token from another blockchain") cmd.Flags().BoolVar(&createFlags.proofOfAuthority, "proof-of-authority", false, "use proof of authority for validator management") cmd.Flags().BoolVar(&createFlags.proofOfStake, "proof-of-stake", false, "use proof of stake for validator management") - cmd.Flags().BoolVar(&createFlags.validatorManagerMintOnly, "validator-manager-mint-only", false, "only enable validator manager contract to mint new native tokens") - cmd.Flags().StringSliceVar(&createFlags.tokenMinterAddress, "token-minter-address", nil, "addresses that can mint new native tokens (for proof of authority validator management only)") cmd.Flags().StringSliceVar(&createFlags.validatorManagerController, "validator-manager-controller", nil, "addresses that will control Validator Manager contract") return cmd } @@ -209,15 +203,6 @@ func createBlockchainConfig(cmd *cobra.Command, args []string) error { return errMutuallyExlusiveValidatorManagementOptions } - if len(createFlags.tokenMinterAddress) > 0 { - if createFlags.proofOfStake { - return errTokenMinterAddressForPoS - } - if createFlags.validatorManagerMintOnly { - return errTokenMinterAddressConflict - } - } - // get vm kind vmType, err := vm.PromptVMType(app, createFlags.useSubnetEvm, createFlags.useCustomVM) if err != nil { @@ -379,22 +364,6 @@ func createBlockchainConfig(cmd *cobra.Command, args []string) error { if err = promptValidatorManagementType(app, sc); err != nil { return err } - if sc.ValidatorManagement == models.ProofOfAuthority { - if !createFlags.validatorManagerMintOnly && createFlags.tokenMinterAddress == nil { - createFlags.tokenMinterAddress, err = getTokenMinterAddr() - if err != nil { - return err - } - } - } - if !createFlags.validatorManagerMintOnly { - if len(createFlags.tokenMinterAddress) > 0 { - ux.Logger.GreenCheckmarkToUser("Addresses added as new native token minter %s", createFlags.tokenMinterAddress) - } else { - ux.Logger.GreenCheckmarkToUser("No additional addresses added as new native token minter") - } - } - sc.NewNativeTokenMinter = createFlags.tokenMinterAddress if createFlags.validatorManagerController == nil { var cancelled bool createFlags.validatorManagerController, cancelled, err = getValidatorContractManagerAddr() @@ -426,54 +395,8 @@ func createBlockchainConfig(cmd *cobra.Command, args []string) error { } func getValidatorContractManagerAddr() ([]string, bool, error) { - controllerAddrPrompt := "Enter Validator Manager Contract controller address" - for { - // ask in a loop so that if some condition is not met we can keep asking - controlAddr, cancelled, err := getAddrLoop(controllerAddrPrompt, constants.ValidatorManagerController, models.UndefinedNetwork) - if err != nil { - return nil, false, err - } - if cancelled { - return nil, cancelled, nil - } - if len(controlAddr) != 0 { - return controlAddr, false, nil - } - ux.Logger.RedXToUser("An address to control Validator Manage Contract is required before proceeding") - } -} - -// Configure which addresses may make mint new native tokens -func getTokenMinterAddr() ([]string, error) { - addTokenMinterAddrPrompt := "Currently only Validator Manager Contract can mint new native tokens" - ux.Logger.PrintToUser(addTokenMinterAddrPrompt) - yes, err := app.Prompt.CaptureNoYes("Add additional addresses that can mint new native tokens?") - if err != nil { - return nil, err - } - if !yes { - return nil, nil - } - addr, cancelled, err := getAddr() - if err != nil { - return nil, err - } - if cancelled { - return nil, nil - } - return addr, nil -} - -func getAddr() ([]string, bool, error) { - addrPrompt := "Enter addresses that can mint new native tokens" - addr, cancelled, err := getAddrLoop(addrPrompt, constants.TokenMinter, models.UndefinedNetwork) - if err != nil { - return nil, false, err - } - if cancelled { - return nil, cancelled, nil - } - return addr, false, nil + // TODO: replace this with implementation in validator prompt PR + return nil, false, nil } func addSubnetEVMGenesisPrefundedAddress(genesisBytes []byte, address string, balance string) ([]byte, error) { diff --git a/cmd/blockchaincmd/prompt_owners.go b/cmd/blockchaincmd/prompt_owners.go index a5c87a905..5233890af 100644 --- a/cmd/blockchaincmd/prompt_owners.go +++ b/cmd/blockchaincmd/prompt_owners.go @@ -217,7 +217,7 @@ func enterCustomKeys(network models.Network) ([]string, bool, error) { controlKeysPrompt := "Enter control keys" for { // ask in a loop so that if some condition is not met we can keep asking - controlKeys, cancelled, err := getAddrLoop(controlKeysPrompt, constants.ControlKey, network) + controlKeys, cancelled, err := controlKeysLoop(controlKeysPrompt, network) if err != nil { return nil, false, err } @@ -231,43 +231,27 @@ func enterCustomKeys(network models.Network) ([]string, bool, error) { } } -// getAddrLoop asks as many addresses the user requires, until Done or Cancel is selected -// TODO: add info for TokenMinter and ValidatorManagerController -func getAddrLoop(prompt, label string, network models.Network) ([]string, bool, error) { - info := "" - goal := "" - switch label { - case constants.ControlKey: - info = "Control keys are P-Chain addresses which have admin rights on the subnet.\n" + - "Only private keys which control such addresses are allowed to make changes on the subnet" - goal = "be set as a subnet control key" - case constants.TokenMinter: - goal = "enable as new native token minter" - case constants.ValidatorManagerController: - goal = "enable as controller of ValidatorManager contract" - default: - } +// controlKeysLoop asks as many controlkeys the user requires, until Done or Cancel is selected +func controlKeysLoop(controlKeysPrompt string, network models.Network) ([]string, bool, error) { + label := "Control key" + info := "Control keys are P-Chain addresses which have admin rights on the subnet.\n" + + "Only private keys which control such addresses are allowed to make changes on the subnet" customPrompt := "Enter P-Chain address (Example: P-...)" - addressFormat := prompts.PChainFormat - if label != constants.ControlKey { - customPrompt = "Enter address" - addressFormat = prompts.EVMFormat - } return prompts.CaptureListDecision( // we need this to be able to mock test app.Prompt, // the main prompt for entering address keys - prompt, + controlKeysPrompt, // the Capture function to use func(_ string) (string, error) { return prompts.PromptAddress( app.Prompt, - goal, + "be set as a subnet control key", app.GetKeyDir(), app.GetKey, "", network, - addressFormat, + prompts.PChainFormat, customPrompt, ) }, diff --git a/pkg/constants/constants.go b/pkg/constants/constants.go index dd127aca2..df1b76fe2 100644 --- a/pkg/constants/constants.go +++ b/pkg/constants/constants.go @@ -27,9 +27,6 @@ const ( SidecarFileName = "sidecar.json" GenesisFileName = "genesis.json" AliasesFileName = "aliases.json" - ControlKey = "Control key" - TokenMinter = "Native token minter" - ValidatorManagerController = "Validator Manager Controller" SidecarSuffix = SuffixSeparator + SidecarFileName GenesisSuffix = SuffixSeparator + GenesisFileName NodeFileName = "node.json" diff --git a/pkg/models/sidecar.go b/pkg/models/sidecar.go index ff09ed6e6..3c962022a 100644 --- a/pkg/models/sidecar.go +++ b/pkg/models/sidecar.go @@ -38,10 +38,10 @@ type Sidecar struct { TeleporterVersion string RunRelayer bool // SubnetEVM based VM's only - SubnetEVMMainnetChainID uint + SubnetEVMMainnetChainID uint + // TODO: remove if not needed for subnet acp 77 create flow once avalnache go releases etna ValidatorManagement ValidatorManagementType ValidatorManagerController []string - NewNativeTokenMinter []string } func (sc Sidecar) GetVMID() (string, error) { From 9e2a87c6f3240ac78bc49cdb7d1a5e9f98b3eda9 Mon Sep 17 00:00:00 2001 From: Raymond Sukanto Date: Thu, 19 Sep 2024 16:42:14 -0400 Subject: [PATCH 47/64] address comments --- cmd/blockchaincmd/prompt_genesis_input.go | 33 ----------------------- 1 file changed, 33 deletions(-) diff --git a/cmd/blockchaincmd/prompt_genesis_input.go b/cmd/blockchaincmd/prompt_genesis_input.go index 4103564b3..27b2019ff 100644 --- a/cmd/blockchaincmd/prompt_genesis_input.go +++ b/cmd/blockchaincmd/prompt_genesis_input.go @@ -60,39 +60,6 @@ func getValidatorContractManagerAddr() ([]string, bool, error) { } } -// Configure which addresses may make mint new native tokens -func getTokenMinterAddr() ([]string, error) { - addTokenMinterAddrPrompt := "Currently only Validator Manager Contract can mint new native tokens" - ux.Logger.PrintToUser(addTokenMinterAddrPrompt) - yes, err := app.Prompt.CaptureNoYes("Add additional addresses that can mint new native tokens?") - if err != nil { - return nil, err - } - if !yes { - return nil, nil - } - addresses, cancelled, err := getAddr() - if err != nil { - return nil, err - } - if cancelled { - return nil, nil - } - return addresses, nil -} - -func getAddr() ([]string, bool, error) { - addrPrompt := "Enter addresses that can mint new native tokens" - addr, cancelled, err := getAddrLoop(addrPrompt, constants.TokenMinter, models.UndefinedNetwork) - if err != nil { - return nil, false, err - } - if cancelled { - return nil, cancelled, nil - } - return addr, false, nil -} - func promptProofOfPossession() (string, string, error) { ux.Logger.PrintToUser("Next, we need the public key and proof of possession of the node's BLS") ux.Logger.PrintToUser("Check https://docs.avax.network/api-reference/info-api#infogetnodeid for instructions on calling info.getNodeID API") From b7408b36b8d206477423e695348952c156e8a64d Mon Sep 17 00:00:00 2001 From: Raymond Sukanto Date: Thu, 19 Sep 2024 16:47:47 -0400 Subject: [PATCH 48/64] fix test --- cmd/blockchaincmd/create.go | 4 ---- 1 file changed, 4 deletions(-) diff --git a/cmd/blockchaincmd/create.go b/cmd/blockchaincmd/create.go index 91bb1a6a4..aa7f9bb47 100644 --- a/cmd/blockchaincmd/create.go +++ b/cmd/blockchaincmd/create.go @@ -198,10 +198,6 @@ func createBlockchainConfig(cmd *cobra.Command, args []string) error { return errMutuallyExlusiveValidatorManagementOptions } - if createFlags.proofOfAuthority { - return errMutuallyExlusiveValidatorManagementOptions - } - // get vm kind vmType, err := vm.PromptVMType(app, createFlags.useSubnetEvm, createFlags.useCustomVM) if err != nil { From 0659211f357a58230d187e24e9f3389a7a12e470 Mon Sep 17 00:00:00 2001 From: Felipe Madero Date: Thu, 19 Sep 2024 16:49:41 -0400 Subject: [PATCH 49/64] address PR comments --- cmd/blockchaincmd/create.go | 5 +---- cmd/blockchaincmd/describe.go | 6 +++--- pkg/contract/allocations.go | 2 +- pkg/teleporter/genesis/genesis.go | 7 ++----- pkg/utils/strings.go | 5 +++++ pkg/vm/create_evm.go | 12 +++++------- 6 files changed, 17 insertions(+), 20 deletions(-) diff --git a/cmd/blockchaincmd/create.go b/cmd/blockchaincmd/create.go index b4b325005..78396bcae 100644 --- a/cmd/blockchaincmd/create.go +++ b/cmd/blockchaincmd/create.go @@ -45,7 +45,6 @@ type CreateFlags struct { useLatestReleasedVMVersion bool useLatestPreReleasedVMVersion bool useExternalGasToken bool - addICMMessengerToGenesis bool addICMRegistryToGenesis bool } @@ -103,8 +102,7 @@ configuration, pass the -f flag.`, cmd.Flags().BoolVar(&createFlags.useWarp, "warp", true, "generate a vm with warp support (needed for teleporter)") cmd.Flags().BoolVar(&createFlags.useTeleporter, "teleporter", false, "interoperate with other blockchains using teleporter") cmd.Flags().BoolVar(&createFlags.useExternalGasToken, "external-gas-token", false, "use a gas token from another blockchain") - cmd.Flags().BoolVar(&createFlags.addICMMessengerToGenesis, "icm-messenger-at-genesis", false, "setup ICM messenger smart contract on genesis") - cmd.Flags().BoolVar(&createFlags.addICMRegistryToGenesis, "icm-registry-at-genesis", false, "setup ICM registry smart contract on genesis") + cmd.Flags().BoolVar(&createFlags.addICMRegistryToGenesis, "icm-registry-at-genesis", false, "setup ICM registry smart contract on genesis [experimental]") return cmd } @@ -283,7 +281,6 @@ func createBlockchainConfig(cmd *cobra.Command, args []string) error { blockchainName, params, teleporterInfo, - createFlags.addICMMessengerToGenesis, createFlags.addICMRegistryToGenesis, ) if err != nil { diff --git a/cmd/blockchaincmd/describe.go b/cmd/blockchaincmd/describe.go index 23b0943cf..d11e51265 100644 --- a/cmd/blockchaincmd/describe.go +++ b/cmd/blockchaincmd/describe.go @@ -276,14 +276,14 @@ func printAllocations(sc models.Sidecar, genesis core.Genesis) error { t.Style().Options.SeparateRows = true t.SetTitle("Initial Token Allocation") t.AppendHeader(table.Row{"Description", "Address and Private Key", "Amount (10^18)", "Amount (wei)"}) - for address := range genesis.Alloc { - if len(genesis.Alloc[address].Code) > 0 { + for address, allocation := range genesis.Alloc { + if len(allocation.Code) > 0 { continue } if address == common.HexToAddress(icmgenesis.MessengerDeployerAddress) { continue } - amount := genesis.Alloc[address].Balance + amount := allocation.Balance formattedAmount := new(big.Int).Div(amount, big.NewInt(params.Ether)) description := "" privKey := "" diff --git a/pkg/contract/allocations.go b/pkg/contract/allocations.go index f4514628e..b4f6d3092 100644 --- a/pkg/contract/allocations.go +++ b/pkg/contract/allocations.go @@ -251,7 +251,7 @@ func ContractAddressIsInBlockchainGenesis( return false, err } if !utils.ByteSliceIsSubnetEvmGenesis(genesisData) { - return false, fmt.Errorf("checking for contract belonging to genesis is only supported on EVM based vms") + return false, fmt.Errorf("only EVM based vms support genesis contract checks") } return ContractAddressIsInGenesisData(genesisData, contractAddress) } diff --git a/pkg/teleporter/genesis/genesis.go b/pkg/teleporter/genesis/genesis.go index 2ac58abf0..f6583a319 100644 --- a/pkg/teleporter/genesis/genesis.go +++ b/pkg/teleporter/genesis/genesis.go @@ -12,6 +12,7 @@ import ( "github.com/ava-labs/avalanche-cli/pkg/application" "github.com/ava-labs/avalanche-cli/pkg/contract" "github.com/ava-labs/avalanche-cli/pkg/models" + "github.com/ava-labs/avalanche-cli/pkg/utils" "github.com/ava-labs/subnet-evm/core" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/crypto" @@ -38,12 +39,8 @@ func setSimpleStorageValue( storage[common.HexToHash(slot)] = common.HexToHash(value) } -func trimHexa(s string) string { - return strings.TrimPrefix(strings.TrimPrefix(s, "0x"), "0X") -} - func hexFill32(s string) string { - return fmt.Sprintf("%064s", trimHexa(s)) + return fmt.Sprintf("%064s", utils.TrimHexa(s)) } func setMappingStorageValue( diff --git a/pkg/utils/strings.go b/pkg/utils/strings.go index a6ff8cb34..ad78d1377 100644 --- a/pkg/utils/strings.go +++ b/pkg/utils/strings.go @@ -71,3 +71,8 @@ func FormatAmount(amount *big.Int, decimals uint8) string { val := new(big.Float).Quo(amountFloat, divisor) return fmt.Sprintf("%.*f", decimals, val) } + +// Removes the leading 0x/0X part of a hexadecimal string representation +func TrimHexa(s string) string { + return strings.TrimPrefix(strings.TrimPrefix(s, "0x"), "0X") +} diff --git a/pkg/vm/create_evm.go b/pkg/vm/create_evm.go index 866d26432..5bddffefb 100644 --- a/pkg/vm/create_evm.go +++ b/pkg/vm/create_evm.go @@ -76,7 +76,6 @@ func CreateEVMGenesis( blockchainName string, params SubnetEVMGenesisParams, teleporterInfo *teleporter.Info, - addICMMessengerToGenesis bool, addICMRegistryToGenesis bool, ) ([]byte, error) { ux.Logger.PrintToUser("creating genesis for blockchain %s", blockchainName) @@ -106,12 +105,11 @@ func CreateEVMGenesis( params.initialTokenAllocation[common.HexToAddress(teleporterInfo.FundedAddress)] = core.GenesisAccount{ Balance: balance, } - if addICMMessengerToGenesis || addICMRegistryToGenesis { - icmgenesis.AddICMMessengerContractToAllocations(params.initialTokenAllocation) - if addICMRegistryToGenesis { - if err := icmgenesis.AddICMRegistryContractToAllocations(params.initialTokenAllocation); err != nil { - return nil, err - } + icmgenesis.AddICMMessengerContractToAllocations(params.initialTokenAllocation) + if addICMRegistryToGenesis { + // experimental + if err := icmgenesis.AddICMRegistryContractToAllocations(params.initialTokenAllocation); err != nil { + return nil, err } } } From 4bc4e5dee1333254e2e64177f3be186b3fd84e55 Mon Sep 17 00:00:00 2001 From: Felipe Madero Date: Fri, 20 Sep 2024 12:25:06 -0400 Subject: [PATCH 50/64] basic PoA manager setting --- cmd/blockchaincmd/upgradecmd/generate.go | 2 +- pkg/vm/allowlist.go | 9 +- pkg/vm/create_evm.go | 2 +- pkg/vm/evm_prompts.go | 169 +++++++++++++---------- pkg/vm/evm_settings.go | 1 + 5 files changed, 109 insertions(+), 74 deletions(-) diff --git a/cmd/blockchaincmd/upgradecmd/generate.go b/cmd/blockchaincmd/upgradecmd/generate.go index b4cd36dbd..da8052416 100644 --- a/cmd/blockchaincmd/upgradecmd/generate.go +++ b/cmd/blockchaincmd/upgradecmd/generate.go @@ -598,7 +598,7 @@ func promptAdminManagerAndEnabledAddresses( sc *models.Sidecar, action string, ) ([]common.Address, []common.Address, []common.Address, bool, error) { - allowList, cancelled, err := vm.GenerateAllowList(app, action, sc.VMVersion) + allowList, cancelled, err := vm.GenerateAllowList(app, vm.AllowList{}, action, sc.VMVersion) if cancelled || err != nil { return nil, nil, nil, cancelled, err } diff --git a/pkg/vm/allowlist.go b/pkg/vm/allowlist.go index 536c7ace1..53851a1bb 100644 --- a/pkg/vm/allowlist.go +++ b/pkg/vm/allowlist.go @@ -98,6 +98,7 @@ func removeAddress( func GenerateAllowList( app *application.Avalanche, + allowList AllowList, action string, evmVersion string, ) (AllowList, bool, error) { @@ -106,8 +107,6 @@ func GenerateAllowList( } managerRoleEnabled := semver.Compare(evmVersion, "v0.6.4") >= 0 - allowList := AllowList{} - promptTemplate := "Configure the addresses that are allowed to %s" prompt := fmt.Sprintf(promptTemplate, action) @@ -122,6 +121,12 @@ func GenerateAllowList( enabledOption := "Enabled" explainOption := "Explain the difference" + if len(allowList.AdminAddresses) != 0 || len(allowList.ManagerAddresses) != 0 || len(allowList.EnabledAddresses) != 0 { + fmt.Println() + fmt.Printf(logging.Bold.Wrap("Addresses automatically allowed to %s\n"), action) + preview(allowList) + } + for { options := []string{addOption, removeOption, previewOption, confirmOption, cancelOption} if len(allowList.AdminAddresses) == 0 && len(allowList.ManagerAddresses) == 0 && len(allowList.EnabledAddresses) == 0 { diff --git a/pkg/vm/create_evm.go b/pkg/vm/create_evm.go index c59f03d4f..0a12152ba 100644 --- a/pkg/vm/create_evm.go +++ b/pkg/vm/create_evm.go @@ -114,7 +114,7 @@ func CreateEVMGenesis( } } - if params.SoVUsePoAValidatorManager { + if params.UsePoAValidatorManager { validatormanager.AddPoAValidatorManagerContractToAllocations(params.initialTokenAllocation) } diff --git a/pkg/vm/evm_prompts.go b/pkg/vm/evm_prompts.go index cde03220e..d3322b0d1 100644 --- a/pkg/vm/evm_prompts.go +++ b/pkg/vm/evm_prompts.go @@ -13,6 +13,7 @@ import ( "github.com/ava-labs/avalanche-cli/pkg/models" "github.com/ava-labs/avalanche-cli/pkg/utils" "github.com/ava-labs/avalanche-cli/pkg/ux" + "github.com/ava-labs/avalanche-cli/pkg/validatormanager" "github.com/ava-labs/subnet-evm/core" "github.com/ava-labs/subnet-evm/plugin/evm" "github.com/ethereum/go-ethereum/common" @@ -52,12 +53,6 @@ const ( confirmAddressAllocationOption = "Confirm and finalize the initial token allocation" ) -var DefaultEwoqAllocation = core.GenesisAlloc{ - PrefundedEwoqAddress: { - Balance: defaultEVMAirdropAmount, - }, -} - type FeeConfig struct { lowThroughput bool mediumThroughput bool @@ -90,7 +85,7 @@ type SubnetEVMGenesisParams struct { enableContractDeployerPrecompile bool contractDeployerPrecompileAllowList AllowList enableWarpPrecompile bool - SoVUsePoAValidatorManager bool + UsePoAValidatorManager bool } func PromptTokenSymbol( @@ -175,8 +170,18 @@ func PromptSubnetEVMGenesisParams( err error params SubnetEVMGenesisParams ) + params.initialTokenAllocation = core.GenesisAlloc{} - params.SoVUsePoAValidatorManager = sc.ValidatorManagement == models.ProofOfAuthority + if sc.ValidatorManagement == models.ProofOfAuthority { + params.UsePoAValidatorManager = true + params.enableNativeMinterPrecompile = true + params.nativeMinterPrecompileAllowList.EnabledAddresses = []common.Address{ + common.HexToAddress(validatormanager.PoAValidarorMessengerContractAddress), + } + params.initialTokenAllocation[common.HexToAddress(sc.ValidatorManagerController)] = core.GenesisAccount{ + Balance: defaultPoAOwnerBalance, + } + } // Chain ID params.chainID = chainID @@ -325,47 +330,57 @@ func displayAllocations(alloc core.GenesisAlloc) { table.Render() } -func createNewKeyAllocation(app *application.Avalanche, subnetName string) (core.GenesisAlloc, error) { +func addNewKeyAllocation(allocations core.GenesisAlloc, app *application.Avalanche, subnetName string) error { keyName := utils.GetDefaultBlockchainAirdropKeyName(subnetName) k, err := app.GetKey(keyName, models.NewLocalNetwork(), true) if err != nil { - return core.GenesisAlloc{}, err + return err } ux.Logger.PrintToUser("prefunding address %s with balance %s", k.C(), defaultEVMAirdropAmount) + allocations[common.HexToAddress(k.C())] = core.GenesisAccount{ + Balance: defaultEVMAirdropAmount, + } + return nil +} - return core.GenesisAlloc{ - common.HexToAddress(k.C()): { - Balance: defaultEVMAirdropAmount, - }, - }, nil +func addEwoqAllocation(allocations core.GenesisAlloc) { + allocations[PrefundedEwoqAddress] = core.GenesisAccount{ + Balance: defaultEVMAirdropAmount, + } } func getNativeGasTokenAllocationConfig( + allocations core.GenesisAlloc, app *application.Avalanche, subnetName string, tokenSymbol string, -) (core.GenesisAlloc, error) { +) error { // Get the type of initial token allocation from the user prompt. allocOption, err := app.Prompt.CaptureList( "How should the initial token allocation be structured?", []string{allocateToNewKeyOption, allocateToEwoqOption, customAllocationOption}, ) if err != nil { - return core.GenesisAlloc{}, err + return err } // If the user chooses to allocate to a new key, generate a new key and allocate the default amount to it. if allocOption == allocateToNewKeyOption { - return createNewKeyAllocation(app, subnetName) + return addNewKeyAllocation(allocations, app, subnetName) } if allocOption == allocateToEwoqOption { ux.Logger.PrintToUser("prefunding address %s with balance %s", PrefundedEwoqAddress, defaultEVMAirdropAmount) - return DefaultEwoqAllocation, nil + addEwoqAllocation(allocations) + return nil } if allocOption == customAllocationOption { - res := core.GenesisAlloc{} + if len(allocations) != 0 { + fmt.Println() + fmt.Printf(logging.Bold.Wrap("Addresses automatically allocated\n")) + displayAllocations(allocations) + } for { // Prompt for the action the user wants to take on the allocation list. action, err := app.Prompt.CaptureList( @@ -379,108 +394,119 @@ func getNativeGasTokenAllocationConfig( }, ) if err != nil { - return core.GenesisAlloc{}, err + return err } switch action { case addAddressAllocationOption: address, err := app.Prompt.CaptureAddress("Address to allocate to") if err != nil { - return core.GenesisAlloc{}, err + return err } // Check if the address already has an allocation entry. - if _, ok := res[address]; ok { + if _, ok := allocations[address]; ok { ux.Logger.PrintToUser("Address already has an allocation entry. Use edit or remove to modify.") continue } balance, err := app.Prompt.CaptureUint64(fmt.Sprintf("Amount to allocate (in %s units)", tokenSymbol)) if err != nil { - return core.GenesisAlloc{}, err + return err } - res[address] = core.GenesisAccount{ + allocations[address] = core.GenesisAccount{ Balance: new(big.Int).Mul(new(big.Int).SetUint64(balance), OneAvax), } case changeAddressAllocationOption: address, err := app.Prompt.CaptureAddress("Address to update the allocation of") if err != nil { - return core.GenesisAlloc{}, err + return err } // Check the address has an existing allocation entry. - if _, ok := res[address]; !ok { + if _, ok := allocations[address]; !ok { ux.Logger.PrintToUser("Address not found in the allocation list") continue } balance, err := app.Prompt.CaptureUint64(fmt.Sprintf("Updated amount to allocate (in %s units)", tokenSymbol)) if err != nil { - return core.GenesisAlloc{}, err + return err } - res[address] = core.GenesisAccount{ + allocations[address] = core.GenesisAccount{ Balance: new(big.Int).Mul(new(big.Int).SetUint64(balance), OneAvax), } case removeAddressAllocationOption: address, err := app.Prompt.CaptureAddress("Address to remove from the allocation list") if err != nil { - return core.GenesisAlloc{}, err + return err } // Check the address has an existing allocation entry. - if _, ok := res[address]; !ok { + if _, ok := allocations[address]; !ok { ux.Logger.PrintToUser("Address not found in the allocation list") continue } - delete(res, address) + delete(allocations, address) case previewAddressAllocationOption: - displayAllocations(res) + displayAllocations(allocations) case confirmAddressAllocationOption: - displayAllocations(res) + displayAllocations(allocations) confirm, err := app.Prompt.CaptureYesNo("Are you sure you want to finalize this allocation list?") if err != nil { - return core.GenesisAlloc{}, err + return err } if confirm { - return res, nil + return nil } default: - return core.GenesisAlloc{}, fmt.Errorf("invalid allocation modification option") + return fmt.Errorf("invalid allocation modification option") } } } - return core.GenesisAlloc{}, fmt.Errorf("invalid allocation option") + return fmt.Errorf("invalid allocation option") } -func getNativeMinterPrecompileConfig(app *application.Avalanche, version string) (AllowList, bool, error) { - option, err := app.Prompt.CaptureList( - "Allow minting of new native tokens?", - []string{fixedSupplyOption, dynamicSupplyOption}, - ) - if err != nil { - return AllowList{}, false, err - } +func getNativeMinterPrecompileConfig( + app *application.Avalanche, + alreadyEnabled bool, + allowList AllowList, + version string, +) (AllowList, bool, error) { + if !alreadyEnabled { + option, err := app.Prompt.CaptureList( + "Allow minting of new native tokens?", + []string{fixedSupplyOption, dynamicSupplyOption}, + ) + if err != nil { + return AllowList{}, false, err + } + if option == fixedSupplyOption { + return AllowList{}, false, nil + } + } else { + confirm, err := app.Prompt.CaptureYesNo("Minting of native tokens automatically enabled. Do you want to configure allow list?") + if err != nil { + return AllowList{}, false, err + } + if !confirm { + return AllowList{}, false, nil + } - if option == fixedSupplyOption { - return AllowList{}, false, nil } - if option == dynamicSupplyOption { - for { - allowList, cancel, err := GenerateAllowList(app, "mint native tokens", version) - if err != nil { - return AllowList{}, false, err - } - if cancel { - continue - } - return allowList, true, nil + for { + allowList, cancel, err := GenerateAllowList(app, allowList, "mint native tokens", version) + if err != nil { + return AllowList{}, false, err } + if cancel { + continue + } + return allowList, true, nil } - - return AllowList{}, false, fmt.Errorf("invalid option") } // prompts for token symbol, initial token allocation, and native minter precompile @@ -505,27 +531,30 @@ func promptNativeGasToken( } if defaultsKind == TestDefaults { - params.initialTokenAllocation, err = createNewKeyAllocation(app, blockchainName) + err = addNewKeyAllocation(params.initialTokenAllocation, app, blockchainName) return params, tokenSymbol, err } if defaultsKind == ProductionDefaults { - params.initialTokenAllocation = DefaultEwoqAllocation + addEwoqAllocation(params.initialTokenAllocation) return params, tokenSymbol, nil } // No defaults case. Prompt for initial token allocation and native minter precompile options. - alloc, err := getNativeGasTokenAllocationConfig(app, blockchainName, tokenSymbol) - if err != nil { + if err := getNativeGasTokenAllocationConfig(params.initialTokenAllocation, app, blockchainName, tokenSymbol); err != nil { return SubnetEVMGenesisParams{}, "", err } - allowList, nativeMinterEnabled, err := getNativeMinterPrecompileConfig(app, version) + allowList, nativeMinterEnabled, err := getNativeMinterPrecompileConfig( + app, + params.enableNativeMinterPrecompile, + params.nativeMinterPrecompileAllowList, + version, + ) if err != nil { return SubnetEVMGenesisParams{}, "", err } - params.initialTokenAllocation = alloc params.enableNativeMinterPrecompile = nativeMinterEnabled params.nativeMinterPrecompileAllowList = allowList return params, tokenSymbol, nil @@ -659,7 +688,7 @@ func promptFeeConfig( switch option { case dontChangeFeeSettingsOption: case changeFeeSettingsOption: - params.feeManagerPrecompileAllowList, cancel, err = GenerateAllowList(app, "adjust the gas fees", version) + params.feeManagerPrecompileAllowList, cancel, err = GenerateAllowList(app, AllowList{}, "adjust the gas fees", version) if err != nil { return SubnetEVMGenesisParams{}, err } @@ -687,7 +716,7 @@ func promptFeeConfig( switch option { case burnFees: case distributeFees: - params.rewardManagerPrecompileAllowList, cancel, err = GenerateAllowList(app, "customize gas fees distribution", version) + params.rewardManagerPrecompileAllowList, cancel, err = GenerateAllowList(app, AllowList{}, "customize gas fees distribution", version) if err != nil { return SubnetEVMGenesisParams{}, err } @@ -782,7 +811,7 @@ func promptPermissioning( } switch option { case approvedCanSubmitTransactionsOption: - params.transactionPrecompileAllowList, cancel, err = GenerateAllowList(app, "issue transactions", version) + params.transactionPrecompileAllowList, cancel, err = GenerateAllowList(app, AllowList{}, "issue transactions", version) if err != nil { return SubnetEVMGenesisParams{}, err } @@ -811,7 +840,7 @@ func promptPermissioning( } switch option { case approvedCanDeployContractsOption: - params.contractDeployerPrecompileAllowList, cancel, err = GenerateAllowList(app, "deploy smart contracts", version) + params.contractDeployerPrecompileAllowList, cancel, err = GenerateAllowList(app, AllowList{}, "deploy smart contracts", version) if err != nil { return SubnetEVMGenesisParams{}, err } diff --git a/pkg/vm/evm_settings.go b/pkg/vm/evm_settings.go index f48bb0b28..b16422a9f 100644 --- a/pkg/vm/evm_settings.go +++ b/pkg/vm/evm_settings.go @@ -25,4 +25,5 @@ var ( OneAvax = new(big.Int).SetUint64(1000000000000000000) defaultEVMAirdropAmount = new(big.Int).Exp(big.NewInt(10), big.NewInt(24), nil) // 10^24 + defaultPoAOwnerBalance = new(big.Int).Mul(OneAvax, big.NewInt(10)) // 10 Native Tokens ) From 3f0eca7d49e125cb3e76f35b6db267b2069daf03 Mon Sep 17 00:00:00 2001 From: Felipe Madero Date: Fri, 20 Sep 2024 12:36:01 -0400 Subject: [PATCH 51/64] lint --- cmd/blockchaincmd/export_test.go | 5 ++++- pkg/vm/evm_prompts.go | 3 +-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/cmd/blockchaincmd/export_test.go b/cmd/blockchaincmd/export_test.go index c83e0552e..75c00e01c 100644 --- a/cmd/blockchaincmd/export_test.go +++ b/cmd/blockchaincmd/export_test.go @@ -12,6 +12,7 @@ import ( "github.com/ava-labs/avalanche-cli/internal/mocks" "github.com/ava-labs/avalanche-cli/pkg/application" "github.com/ava-labs/avalanche-cli/pkg/constants" + "github.com/ava-labs/avalanche-cli/pkg/models" "github.com/ava-labs/avalanche-cli/pkg/prompts" "github.com/ava-labs/avalanche-cli/pkg/ux" "github.com/ava-labs/avalanche-cli/pkg/vm" @@ -40,7 +41,9 @@ func TestExportImportSubnet(t *testing.T) { "../../"+utils.SubnetEvmGenesisPath, ) require.NoError(err) - sc, err := vm.CreateEvmSidecar( + sc := &models.Sidecar{} + err = vm.FillEvmSidecar( + sc, app, testSubnet, vmVersion, diff --git a/pkg/vm/evm_prompts.go b/pkg/vm/evm_prompts.go index d3322b0d1..acca57f6b 100644 --- a/pkg/vm/evm_prompts.go +++ b/pkg/vm/evm_prompts.go @@ -378,7 +378,7 @@ func getNativeGasTokenAllocationConfig( if allocOption == customAllocationOption { if len(allocations) != 0 { fmt.Println() - fmt.Printf(logging.Bold.Wrap("Addresses automatically allocated\n")) + fmt.Println(logging.Bold.Wrap("Addresses automatically allocated")) displayAllocations(allocations) } for { @@ -494,7 +494,6 @@ func getNativeMinterPrecompileConfig( if !confirm { return AllowList{}, false, nil } - } for { From 2a8c14d3f0d97a8b18273293404108dfd8b6c265 Mon Sep 17 00:00:00 2001 From: Raymond Sukanto Date: Fri, 20 Sep 2024 12:52:52 -0400 Subject: [PATCH 52/64] address comments --- cmd/blockchaincmd/create.go | 20 +------------------- cmd/blockchaincmd/deploy.go | 23 ++++++++++++++++++++++- cmd/transactioncmd/transaction_commit.go | 2 +- pkg/application/app.go | 2 ++ pkg/models/sidecar.go | 4 ++-- 5 files changed, 28 insertions(+), 23 deletions(-) diff --git a/cmd/blockchaincmd/create.go b/cmd/blockchaincmd/create.go index aa7f9bb47..164c674ba 100644 --- a/cmd/blockchaincmd/create.go +++ b/cmd/blockchaincmd/create.go @@ -49,7 +49,6 @@ type CreateFlags struct { useExternalGasToken bool proofOfStake bool proofOfAuthority bool - validatorManagerController []string } var ( @@ -359,19 +358,7 @@ func createBlockchainConfig(cmd *cobra.Command, args []string) error { if err = promptValidatorManagementType(app, sc); err != nil { return err } - if createFlags.validatorManagerController == nil { - var cancelled bool - createFlags.validatorManagerController, cancelled, err = getValidatorContractManagerAddr() - if err != nil { - return err - } - if cancelled { - return fmt.Errorf("user cancelled operation") - } - } - sc.ValidatorManagerController = createFlags.validatorManagerController - // TODO: add description of what Validator Manager Contract controller does - ux.Logger.GreenCheckmarkToUser("Validator Manager Contract controller %s", createFlags.validatorManagerController) + if err = app.WriteGenesisFile(blockchainName, genesisBytes); err != nil { return err } @@ -389,11 +376,6 @@ func createBlockchainConfig(cmd *cobra.Command, args []string) error { return nil } -func getValidatorContractManagerAddr() ([]string, bool, error) { - // TODO: replace this with implementation in validator prompt PR - return nil, false, nil -} - func addSubnetEVMGenesisPrefundedAddress(genesisBytes []byte, address string, balance string) ([]byte, error) { var genesisMap map[string]interface{} if err := json.Unmarshal(genesisBytes, &genesisMap); err != nil { diff --git a/cmd/blockchaincmd/deploy.go b/cmd/blockchaincmd/deploy.go index 23f451bf6..5665e4be0 100644 --- a/cmd/blockchaincmd/deploy.go +++ b/cmd/blockchaincmd/deploy.go @@ -6,6 +6,7 @@ import ( "encoding/json" "errors" "fmt" + "github.com/ethereum/go-ethereum/common" "os" "path/filepath" "strings" @@ -51,6 +52,7 @@ var ( skipCreatePrompt bool avagoBinaryPath string subnetOnly bool + validatorManagerOwner string teleporterEsp subnet.TeleporterEsp errMutuallyExlusiveControlKeys = errors.New("--control-keys and --same-control-key are mutually exclusive") @@ -100,6 +102,7 @@ so you can take your locally tested Subnet and deploy it on Fuji or Mainnet.`, cmd.Flags().StringVar(&teleporterEsp.MessengerDeployerAddressPath, "teleporter-messenger-deployer-address-path", "", "path to a teleporter messenger deployer address file") cmd.Flags().StringVar(&teleporterEsp.MessengerDeployerTxPath, "teleporter-messenger-deployer-tx-path", "", "path to a teleporter messenger deployer tx file") cmd.Flags().StringVar(&teleporterEsp.RegistryBydecodePath, "teleporter-registry-bytecode-path", "", "path to a teleporter registry bytecode file") + cmd.Flags().StringVar(&validatorManagerOwner, "validator-manager-owner", "", "EVM address that controls Validator Manager Controller (for Proof of Authority only)") return cmd } @@ -285,6 +288,10 @@ func deployBlockchain(cmd *cobra.Command, args []string) error { return errors.New("unable to deploy subnets imported from a repo") } + if sidecar.ValidatorManagement != models.ProofOfAuthority && validatorManagerOwner != "" { + return errors.New("--validator-manager-controller flag cannot be used when blockchain validator management type is not Proof of Authority") + } + if outputTxPath != "" { if _, err := os.Stat(outputTxPath); err == nil { return fmt.Errorf("outputTxPath %q already exists", outputTxPath) @@ -386,6 +393,7 @@ func deployBlockchain(cmd *cobra.Command, args []string) error { deployInfo.BlockchainID, deployInfo.TeleporterMessengerAddress, deployInfo.TeleporterRegistryAddress, + validatorManagerOwner, ); err != nil { return err } @@ -488,6 +496,15 @@ func deployBlockchain(cmd *cobra.Command, args []string) error { } ux.Logger.PrintToUser("Your subnet auth keys for chain creation: %s", subnetAuthKeys) + if validatorManagerOwner == "" { + validatorManagerOwnerEVMAddress, err := getValidatorContractOwnerAddr() + if err != nil { + return err + } + validatorManagerOwner = validatorManagerOwnerEVMAddress.String() + } + ux.Logger.PrintToUser("Validator Manager Contract controller address %s", validatorManagerOwner) + // deploy to public network deployer := subnet.NewPublicDeployer(app, kc, network) @@ -552,7 +569,11 @@ func deployBlockchain(cmd *cobra.Command, args []string) error { // update sidecar // TODO: need to do something for backwards compatibility? - return app.UpdateSidecarNetworks(&sidecar, network, subnetID, blockchainID, "", "") + return app.UpdateSidecarNetworks(&sidecar, network, subnetID, blockchainID, "", "", validatorManagerOwner) +} + +func getValidatorContractOwnerAddr() (common.Address, error) { + return app.Prompt.CaptureAddress("What is the EVM address that will control the Validator Manager Contract?") } func ValidateSubnetNameAndGetChains(args []string) ([]string, error) { diff --git a/cmd/transactioncmd/transaction_commit.go b/cmd/transactioncmd/transaction_commit.go index 21712c924..6f2d2c2ff 100644 --- a/cmd/transactioncmd/transaction_commit.go +++ b/cmd/transactioncmd/transaction_commit.go @@ -97,7 +97,7 @@ func commitTx(_ *cobra.Command, args []string) error { if err := blockchaincmd.PrintDeployResults(subnetName, subnetID, txID); err != nil { return err } - return app.UpdateSidecarNetworks(&sc, network, subnetID, txID, "", "") + return app.UpdateSidecarNetworks(&sc, network, subnetID, txID, "", "", sc.Networks[network.Name()].PoAValidatorManagerOwner) } return nil diff --git a/pkg/application/app.go b/pkg/application/app.go index cc2b2f1fe..2afef53c1 100644 --- a/pkg/application/app.go +++ b/pkg/application/app.go @@ -520,6 +520,7 @@ func (app *Avalanche) UpdateSidecarNetworks( blockchainID ids.ID, teleporterMessengerAddress string, teleporterRegistryAddress string, + validatorManagerController string, ) error { if sc.Networks == nil { sc.Networks = make(map[string]models.NetworkData) @@ -530,6 +531,7 @@ func (app *Avalanche) UpdateSidecarNetworks( RPCVersion: sc.RPCVersion, TeleporterMessengerAddress: teleporterMessengerAddress, TeleporterRegistryAddress: teleporterRegistryAddress, + PoAValidatorManagerOwner: validatorManagerController, } if err := app.UpdateSidecar(sc); err != nil { return fmt.Errorf("creation of chains and subnet was successful, but failed to update sidecar: %w", err) diff --git a/pkg/models/sidecar.go b/pkg/models/sidecar.go index 3c962022a..71245ed00 100644 --- a/pkg/models/sidecar.go +++ b/pkg/models/sidecar.go @@ -13,6 +13,7 @@ type NetworkData struct { RPCVersion int TeleporterMessengerAddress string TeleporterRegistryAddress string + PoAValidatorManagerOwner string } type Sidecar struct { @@ -40,8 +41,7 @@ type Sidecar struct { // SubnetEVM based VM's only SubnetEVMMainnetChainID uint // TODO: remove if not needed for subnet acp 77 create flow once avalnache go releases etna - ValidatorManagement ValidatorManagementType - ValidatorManagerController []string + ValidatorManagement ValidatorManagementType } func (sc Sidecar) GetVMID() (string, error) { From 1cc81465e29239b3659e2bcd61f41606923972ab Mon Sep 17 00:00:00 2001 From: Raymond Sukanto Date: Fri, 20 Sep 2024 13:02:04 -0400 Subject: [PATCH 53/64] fix lint --- cmd/blockchaincmd/deploy.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cmd/blockchaincmd/deploy.go b/cmd/blockchaincmd/deploy.go index 0c2f60c08..a23ebb2ff 100644 --- a/cmd/blockchaincmd/deploy.go +++ b/cmd/blockchaincmd/deploy.go @@ -6,11 +6,12 @@ import ( "encoding/json" "errors" "fmt" - "github.com/ethereum/go-ethereum/common" "os" "path/filepath" "strings" + "github.com/ethereum/go-ethereum/common" + "github.com/ava-labs/avalanche-cli/pkg/utils" "github.com/ava-labs/avalanche-cli/pkg/binutils" From 64580c982054b6508a59cc8a006e85a80679cb4a Mon Sep 17 00:00:00 2001 From: Felipe Madero Date: Sat, 21 Sep 2024 08:54:07 -0400 Subject: [PATCH 54/64] fix e2e --- tests/e2e/commands/subnet.go | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/tests/e2e/commands/subnet.go b/tests/e2e/commands/subnet.go index f0e1f7298..8f7798de4 100644 --- a/tests/e2e/commands/subnet.go +++ b/tests/e2e/commands/subnet.go @@ -16,7 +16,10 @@ import ( "github.com/onsi/gomega" ) -const subnetEVMMainnetChainID = 11 +const ( + subnetEVMMainnetChainID = 11 + poaValidatorManagerOwner = "0x2e6FcBb9d4E17eC4cF67eddfa7D32eabC4cdCFc6" +) /* #nosec G204 */ func CreateSubnetEvmConfig(subnetName string, genesisPath string) (string, string) { @@ -44,6 +47,8 @@ func CreateSubnetEvmConfigWithVersion(subnetName string, genesisPath string, ver "--evm", subnetName, "--proof-of-authority", + "--poa-manager-owner", + poaValidatorManagerOwner, "--" + constants.SkipUpdateFlag, "--teleporter=false", "--evm-token", @@ -124,6 +129,8 @@ func CreateCustomVMConfig(subnetName string, genesisPath string, vmPath string) "--genesis", genesisPath, "--proof-of-authority", + "--poa-manager-owner", + poaValidatorManagerOwner, "--custom", subnetName, "--custom-vm-path", From b6f65ca7151f6db7e08f5e7c7ddf3c98dcab6fb7 Mon Sep 17 00:00:00 2001 From: Raymond Sukanto Date: Mon, 23 Sep 2024 19:34:25 -0400 Subject: [PATCH 55/64] fix merge --- cmd/blockchaincmd/deploy.go | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/cmd/blockchaincmd/deploy.go b/cmd/blockchaincmd/deploy.go index 6e68e206e..17f599ec0 100644 --- a/cmd/blockchaincmd/deploy.go +++ b/cmd/blockchaincmd/deploy.go @@ -307,10 +307,6 @@ func deployBlockchain(cmd *cobra.Command, args []string) error { return errors.New("unable to deploy subnets imported from a repo") } - if sidecar.ValidatorManagement != models.ProofOfAuthority && validatorManagerOwner != "" { - return errors.New("--validator-manager-controller flag cannot be used when blockchain validator management type is not Proof of Authority") - } - if outputTxPath != "" { if _, err := os.Stat(outputTxPath); err == nil { return fmt.Errorf("outputTxPath %q already exists", outputTxPath) @@ -419,7 +415,7 @@ func deployBlockchain(cmd *cobra.Command, args []string) error { deployInfo.BlockchainID, deployInfo.ICMMessengerAddress, deployInfo.ICMRegistryAddress, - bootstrapValidators + bootstrapValidators, ); err != nil { return err } @@ -522,15 +518,6 @@ func deployBlockchain(cmd *cobra.Command, args []string) error { } ux.Logger.PrintToUser("Your subnet auth keys for chain creation: %s", subnetAuthKeys) - if validatorManagerOwner == "" { - validatorManagerOwnerEVMAddress, err := getValidatorContractOwnerAddr() - if err != nil { - return err - } - validatorManagerOwner = validatorManagerOwnerEVMAddress.String() - } - ux.Logger.PrintToUser("Validator Manager Contract controller address %s", validatorManagerOwner) - // deploy to public network deployer := subnet.NewPublicDeployer(app, kc, network) From 3962f8196b0f181983e029e00d6cf4ceaf69e37b Mon Sep 17 00:00:00 2001 From: Raymond Sukanto Date: Mon, 23 Sep 2024 19:41:46 -0400 Subject: [PATCH 56/64] fix merge --- cmd/blockchaincmd/deploy.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/cmd/blockchaincmd/deploy.go b/cmd/blockchaincmd/deploy.go index 9d6e7b8de..f512498f1 100644 --- a/cmd/blockchaincmd/deploy.go +++ b/cmd/blockchaincmd/deploy.go @@ -11,7 +11,6 @@ import ( "strings" "github.com/ava-labs/avalanche-cli/pkg/utils" - "github.com/ethereum/go-ethereum/common" "github.com/ava-labs/avalanche-cli/pkg/binutils" "github.com/ava-labs/avalanche-cli/pkg/cobrautils" @@ -585,7 +584,6 @@ func deployBlockchain(cmd *cobra.Command, args []string) error { return app.UpdateSidecarNetworks(&sidecar, network, subnetID, blockchainID, "", "", bootstrapValidators) } - func ValidateSubnetNameAndGetChains(args []string) ([]string, error) { // this should not be necessary but some bright guy might just be creating // the genesis by hand or something... From 4152f68a5d0dcd1b2e5f6b31ec1627444b4ed1d6 Mon Sep 17 00:00:00 2001 From: Felipe Madero Date: Wed, 25 Sep 2024 21:42:43 -0300 Subject: [PATCH 57/64] filter based on balance --- cmd/blockchaincmd/describe.go | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/cmd/blockchaincmd/describe.go b/cmd/blockchaincmd/describe.go index d11e51265..7da29a297 100644 --- a/cmd/blockchaincmd/describe.go +++ b/cmd/blockchaincmd/describe.go @@ -17,7 +17,6 @@ import ( "github.com/ava-labs/avalanche-cli/pkg/models" "github.com/ava-labs/avalanche-cli/pkg/networkoptions" "github.com/ava-labs/avalanche-cli/pkg/subnet" - icmgenesis "github.com/ava-labs/avalanche-cli/pkg/teleporter/genesis" "github.com/ava-labs/avalanche-cli/pkg/txutils" "github.com/ava-labs/avalanche-cli/pkg/utils" "github.com/ava-labs/avalanche-cli/pkg/ux" @@ -277,13 +276,11 @@ func printAllocations(sc models.Sidecar, genesis core.Genesis) error { t.SetTitle("Initial Token Allocation") t.AppendHeader(table.Row{"Description", "Address and Private Key", "Amount (10^18)", "Amount (wei)"}) for address, allocation := range genesis.Alloc { - if len(allocation.Code) > 0 { - continue - } - if address == common.HexToAddress(icmgenesis.MessengerDeployerAddress) { + amount := allocation.Balance + // we are only interested in supply distribution here + if amount == nil || big.NewInt(0).Cmp(amount) == 0 { continue } - amount := allocation.Balance formattedAmount := new(big.Int).Div(amount, big.NewInt(params.Ether)) description := "" privKey := "" From 0e054cb209d03089dbabe46d9ff04b7625e2629a Mon Sep 17 00:00:00 2001 From: Felipe Madero Date: Wed, 25 Sep 2024 23:01:06 -0300 Subject: [PATCH 58/64] add unit tests --- cmd/blockchaincmd/describe.go | 25 ++++ pkg/contract/allocations.go | 20 --- pkg/contract/allocations_test.go | 194 ++++++++++++++++++++++++++++++ pkg/teleporter/genesis/genesis.go | 21 ++-- 4 files changed, 226 insertions(+), 34 deletions(-) create mode 100644 pkg/contract/allocations_test.go diff --git a/cmd/blockchaincmd/describe.go b/cmd/blockchaincmd/describe.go index 7da29a297..288b5c10e 100644 --- a/cmd/blockchaincmd/describe.go +++ b/cmd/blockchaincmd/describe.go @@ -17,6 +17,7 @@ import ( "github.com/ava-labs/avalanche-cli/pkg/models" "github.com/ava-labs/avalanche-cli/pkg/networkoptions" "github.com/ava-labs/avalanche-cli/pkg/subnet" + icmgenesis "github.com/ava-labs/avalanche-cli/pkg/teleporter/genesis" "github.com/ava-labs/avalanche-cli/pkg/txutils" "github.com/ava-labs/avalanche-cli/pkg/utils" "github.com/ava-labs/avalanche-cli/pkg/ux" @@ -216,6 +217,7 @@ func PrintSubnetInfo(blockchainName string, onlyLocalnetInfo bool) error { if err := printAllocations(sc, genesis); err != nil { return err } + printSmartContracts(genesis) printPrecompiles(genesis) } @@ -302,6 +304,29 @@ func printAllocations(sc models.Sidecar, genesis core.Genesis) error { return nil } +func printSmartContracts(genesis core.Genesis) { + if len(genesis.Alloc) > 0 { + ux.Logger.PrintToUser("") + t := table.NewWriter() + t.Style().Title.Align = text.AlignCenter + t.Style().Title.Format = text.FormatUpper + t.Style().Options.SeparateRows = true + t.SetTitle("Smart Contracts") + t.AppendHeader(table.Row{"Description", "Address", "Deployer"}) + for address, allocation := range genesis.Alloc { + var description, deployer string + if len(allocation.Code) > 0 { + if address == common.HexToAddress(icmgenesis.MessengerContractAddress) { + description = "ICM Messenger" + deployer = icmgenesis.MessengerDeployerAddress + } + t.AppendRow(table.Row{description, address.Hex(), deployer}) + } + } + ux.Logger.PrintToUser(t.Render()) + } +} + func printPrecompiles(genesis core.Genesis) { ux.Logger.PrintToUser("") t := table.NewWriter() diff --git a/pkg/contract/allocations.go b/pkg/contract/allocations.go index b4f6d3092..9543ba227 100644 --- a/pkg/contract/allocations.go +++ b/pkg/contract/allocations.go @@ -236,26 +236,6 @@ func GetEVMSubnetGenesisNativeMinterAdmin( return getGenesisNativeMinterAdmin(app, network, genesisData) } -func ContractAddressIsInBlockchainGenesis( - app *application.Avalanche, - network models.Network, - chainSpec ChainSpec, - contractAddress common.Address, -) (bool, error) { - genesisData, err := GetBlockchainGenesis( - app, - network, - chainSpec, - ) - if err != nil { - return false, err - } - if !utils.ByteSliceIsSubnetEvmGenesis(genesisData) { - return false, fmt.Errorf("only EVM based vms support genesis contract checks") - } - return ContractAddressIsInGenesisData(genesisData, contractAddress) -} - func ContractAddressIsInGenesisData( genesisData []byte, contractAddress common.Address, diff --git a/pkg/contract/allocations_test.go b/pkg/contract/allocations_test.go new file mode 100644 index 000000000..07577ce94 --- /dev/null +++ b/pkg/contract/allocations_test.go @@ -0,0 +1,194 @@ +// Copyright (C) 2024, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. +package contract + +import ( + "testing" + + "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/require" +) + +func TestContractAddressIsInGenesisData(t *testing.T) { + require := require.New(t) + + type test struct { + desc string + genesisData []byte + contractAddress common.Address + expected bool + shouldErr bool + } + + tests := []test{ + { + desc: "nil data", + genesisData: nil, + contractAddress: common.Address{}, + expected: false, + shouldErr: true, + }, + { + desc: "not json", + genesisData: []byte("not json"), + contractAddress: common.Address{}, + expected: false, + shouldErr: true, + }, + { + desc: "not evm", + genesisData: []byte("{}"), + contractAddress: common.Address{}, + expected: false, + shouldErr: true, + }, + { + desc: "no allocs", + genesisData: []byte(` +{ + "config": { + "byzantiumBlock": 0, "chainId": 1, "constantinopleBlock": 0, "eip150Block": 0, + "eip155Block": 0, "eip158Block": 0, + "feeConfig": { + "gasLimit": 12000000, "targetBlockRate": 2, "minBaseFee": 25000000000, + "targetGas": 60000000, "baseFeeChangeDenominator": 36, "minBlockGasCost": 0, + "maxBlockGasCost": 1000000, "blockGasCostStep": 200000 + }, + "homesteadBlock": 0, "istanbulBlock": 0, "muirGlacierBlock": 0, "petersburgBlock": 0, + "warpConfig": { + "blockTimestamp": 1727309619, "quorumNumerator": 67 + } + }, + "nonce": "0x0", "timestamp": "0x66f4a733", "extraData": "0x", "gasLimit": "0xb71b00", "difficulty": "0x0", + "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "coinbase": "0x0000000000000000000000000000000000000000", + "airdropHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "airdropAmount": null, "number": "0x0", "gasUsed": "0x0", + "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "baseFeePerGas": null, "excessBlobGas": null, "blobGasUsed": null, + "alloc": {} +} + `), + contractAddress: common.Address{}, + expected: false, + shouldErr: false, + }, + { + desc: "good path", + genesisData: []byte(` +{ + "config": { + "byzantiumBlock": 0, "chainId": 1, "constantinopleBlock": 0, "eip150Block": 0, + "eip155Block": 0, "eip158Block": 0, + "feeConfig": { + "gasLimit": 12000000, "targetBlockRate": 2, "minBaseFee": 25000000000, + "targetGas": 60000000, "baseFeeChangeDenominator": 36, "minBlockGasCost": 0, + "maxBlockGasCost": 1000000, "blockGasCostStep": 200000 + }, + "homesteadBlock": 0, "istanbulBlock": 0, "muirGlacierBlock": 0, "petersburgBlock": 0, + "warpConfig": { + "blockTimestamp": 1727309619, "quorumNumerator": 67 + } + }, + "nonce": "0x0", "timestamp": "0x66f4a733", "extraData": "0x", "gasLimit": "0xb71b00", "difficulty": "0x0", + "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "coinbase": "0x0000000000000000000000000000000000000000", + "airdropHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "airdropAmount": null, "number": "0x0", "gasUsed": "0x0", + "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "baseFeePerGas": null, "excessBlobGas": null, "blobGasUsed": null, + "alloc": { + "253b2784c75e510dd0ff1da844684a1ac0aa5fcf": { + "code": "0xfe", + "balance": "0x2086ac351052600000" + } + } +} + `), + contractAddress: common.HexToAddress("0x253b2784c75e510dd0ff1da844684a1ac0aa5fcf"), + expected: true, + shouldErr: false, + }, + { + desc: "no code", + genesisData: []byte(` +{ + "config": { + "byzantiumBlock": 0, "chainId": 1, "constantinopleBlock": 0, "eip150Block": 0, + "eip155Block": 0, "eip158Block": 0, + "feeConfig": { + "gasLimit": 12000000, "targetBlockRate": 2, "minBaseFee": 25000000000, + "targetGas": 60000000, "baseFeeChangeDenominator": 36, "minBlockGasCost": 0, + "maxBlockGasCost": 1000000, "blockGasCostStep": 200000 + }, + "homesteadBlock": 0, "istanbulBlock": 0, "muirGlacierBlock": 0, "petersburgBlock": 0, + "warpConfig": { + "blockTimestamp": 1727309619, "quorumNumerator": 67 + } + }, + "nonce": "0x0", "timestamp": "0x66f4a733", "extraData": "0x", "gasLimit": "0xb71b00", "difficulty": "0x0", + "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "coinbase": "0x0000000000000000000000000000000000000000", + "airdropHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "airdropAmount": null, "number": "0x0", "gasUsed": "0x0", + "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "baseFeePerGas": null, "excessBlobGas": null, "blobGasUsed": null, + "alloc": { + "253b2784c75e510dd0ff1da844684a1ac0aa5fcf": { + "balance": "0x2086ac351052600000" + } + } +} + `), + contractAddress: common.HexToAddress("0x253b2784c75e510dd0ff1da844684a1ac0aa5fcf"), + expected: false, + shouldErr: false, + }, + { + desc: "diff addr", + genesisData: []byte(` +{ + "config": { + "byzantiumBlock": 0, "chainId": 1, "constantinopleBlock": 0, "eip150Block": 0, + "eip155Block": 0, "eip158Block": 0, + "feeConfig": { + "gasLimit": 12000000, "targetBlockRate": 2, "minBaseFee": 25000000000, + "targetGas": 60000000, "baseFeeChangeDenominator": 36, "minBlockGasCost": 0, + "maxBlockGasCost": 1000000, "blockGasCostStep": 200000 + }, + "homesteadBlock": 0, "istanbulBlock": 0, "muirGlacierBlock": 0, "petersburgBlock": 0, + "warpConfig": { + "blockTimestamp": 1727309619, "quorumNumerator": 67 + } + }, + "nonce": "0x0", "timestamp": "0x66f4a733", "extraData": "0x", "gasLimit": "0xb71b00", "difficulty": "0x0", + "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "coinbase": "0x0000000000000000000000000000000000000000", + "airdropHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "airdropAmount": null, "number": "0x0", "gasUsed": "0x0", + "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "baseFeePerGas": null, "excessBlobGas": null, "blobGasUsed": null, + "alloc": { + "253b2784c75e510dd0ff1da844684a1ac0aa5fcf": { + "code": "0xfe", + "balance": "0x2086ac351052600000" + } + } +} + `), + contractAddress: common.HexToAddress("0x253b2724c75e510dd0ff1da844684a1ac0aa5fcc"), + expected: false, + shouldErr: false, + }, + } + + for _, t := range tests { + b, err := ContractAddressIsInGenesisData(t.genesisData, t.contractAddress) + if t.shouldErr { + require.Error(err, t.desc) + } else { + require.NoError(err, t.desc) + } + require.Equal(t.expected, b, t.desc) + } +} diff --git a/pkg/teleporter/genesis/genesis.go b/pkg/teleporter/genesis/genesis.go index f6583a319..2afbc67f9 100644 --- a/pkg/teleporter/genesis/genesis.go +++ b/pkg/teleporter/genesis/genesis.go @@ -9,9 +9,7 @@ import ( "math/big" "strings" - "github.com/ava-labs/avalanche-cli/pkg/application" "github.com/ava-labs/avalanche-cli/pkg/contract" - "github.com/ava-labs/avalanche-cli/pkg/models" "github.com/ava-labs/avalanche-cli/pkg/utils" "github.com/ava-labs/subnet-evm/core" "github.com/ethereum/go-ethereum/common" @@ -109,18 +107,13 @@ func AddICMRegistryContractToAllocations( return nil } -func ICMAtBlockchainGenesis( - app *application.Avalanche, - network models.Network, - chainSpec contract.ChainSpec, -) (bool, bool, error) { - genesisData, err := contract.GetBlockchainGenesis(app, network, chainSpec) - if err != nil { - return false, false, err - } - return ICMAtGenesis(genesisData) -} - +// check if [genesisData] has +// smart contracts (len(alloc.Code)>0) allocated for +// ICM Messenger and ICM registry, +// based on their expected addresses [MessengerContractAddress] and +// [RegistryContractAddress] +// to be used by local blockchain deploy to determine if a teleporter deploy +// or a registry deploy is needed func ICMAtGenesis( genesisData []byte, ) (bool, bool, error) { From 03389e69d768ac0d8e79a337875afa87cc09c1bb Mon Sep 17 00:00:00 2001 From: Felipe Madero Date: Wed, 25 Sep 2024 23:15:51 -0300 Subject: [PATCH 59/64] nit --- cmd/blockchaincmd/describe.go | 4 ++++ pkg/vm/evm_prompts.go | 1 + 2 files changed, 5 insertions(+) diff --git a/cmd/blockchaincmd/describe.go b/cmd/blockchaincmd/describe.go index 288b5c10e..7c139123e 100644 --- a/cmd/blockchaincmd/describe.go +++ b/cmd/blockchaincmd/describe.go @@ -21,6 +21,7 @@ import ( "github.com/ava-labs/avalanche-cli/pkg/txutils" "github.com/ava-labs/avalanche-cli/pkg/utils" "github.com/ava-labs/avalanche-cli/pkg/ux" + "github.com/ava-labs/avalanche-cli/pkg/validatormanager" "github.com/ava-labs/avalanche-cli/pkg/vm" anr_utils "github.com/ava-labs/avalanche-network-runner/utils" "github.com/ava-labs/avalanchego/ids" @@ -320,6 +321,9 @@ func printSmartContracts(genesis core.Genesis) { description = "ICM Messenger" deployer = icmgenesis.MessengerDeployerAddress } + if address == common.HexToAddress(validatormanager.PoAValidarorMessengerContractAddress) { + description = "PoA Validator Manager" + } t.AppendRow(table.Row{description, address.Hex(), deployer}) } } diff --git a/pkg/vm/evm_prompts.go b/pkg/vm/evm_prompts.go index b85b5812d..39c5d53af 100644 --- a/pkg/vm/evm_prompts.go +++ b/pkg/vm/evm_prompts.go @@ -532,6 +532,7 @@ func promptNativeGasToken( if defaultsKind == TestDefaults { ux.Logger.PrintToUser("prefunding address %s with balance %s", PrefundedEwoqAddress, defaultEVMAirdropAmount) addEwoqAllocation(params.initialTokenAllocation) + return params, tokenSymbol, nil } if defaultsKind == ProductionDefaults { From e7bed9469fa0b900b97e2e7a2916f38c95f8088b Mon Sep 17 00:00:00 2001 From: Felipe Madero Date: Thu, 26 Sep 2024 10:00:21 -0300 Subject: [PATCH 60/64] address PR comments --- cmd/blockchaincmd/create.go | 2 +- pkg/validatormanager/validatormanager.go | 1 + pkg/vm/evm_prompts.go | 11 +++++++---- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/cmd/blockchaincmd/create.go b/cmd/blockchaincmd/create.go index 1f831693f..d6f417ac5 100644 --- a/cmd/blockchaincmd/create.go +++ b/cmd/blockchaincmd/create.go @@ -242,7 +242,7 @@ func createBlockchainConfig(cmd *cobra.Command, args []string) error { } } sc.PoAValidatorManagerOwner = createFlags.poaValidatorManagerOwner - ux.Logger.GreenCheckmarkToUser("PoA Validator Manager Contract owner %s", createFlags.poaValidatorManagerOwner) + ux.Logger.GreenCheckmarkToUser("Validator Manager Contract owner address %s", createFlags.poaValidatorManagerOwner) } if genesisFile == "" { diff --git a/pkg/validatormanager/validatormanager.go b/pkg/validatormanager/validatormanager.go index 0d62904c1..0a444cf4f 100644 --- a/pkg/validatormanager/validatormanager.go +++ b/pkg/validatormanager/validatormanager.go @@ -15,6 +15,7 @@ import ( const ( PoAValidarorMessengerContractAddress = "0x5F584C2D56B4c356e7d82EC6129349393dc5df17" + PoSValidarorMessengerContractAddress = "0x5F584C2D56B4c356e7d82EC6129349393dc5df17" ) //go:embed deployed_poa_validator_manager_bytecode.txt diff --git a/pkg/vm/evm_prompts.go b/pkg/vm/evm_prompts.go index 39c5d53af..ea74f41b0 100644 --- a/pkg/vm/evm_prompts.go +++ b/pkg/vm/evm_prompts.go @@ -174,15 +174,18 @@ func PromptSubnetEVMGenesisParams( if sc.ValidatorManagement == models.ProofOfAuthority { params.UsePoAValidatorManager = true - params.enableNativeMinterPrecompile = true - params.nativeMinterPrecompileAllowList.EnabledAddresses = []common.Address{ - common.HexToAddress(validatormanager.PoAValidarorMessengerContractAddress), - } params.initialTokenAllocation[common.HexToAddress(sc.PoAValidatorManagerOwner)] = core.GenesisAccount{ Balance: defaultPoAOwnerBalance, } } + if sc.ValidatorManagement == models.ProofOfStake { + params.enableNativeMinterPrecompile = true + params.nativeMinterPrecompileAllowList.EnabledAddresses = []common.Address{ + common.HexToAddress(validatormanager.PoSValidarorMessengerContractAddress), + } + } + // Chain ID params.chainID = chainID if params.chainID == 0 { From a24ae5baee3b3e69dd71b4bafe19fa261cfc885c Mon Sep 17 00:00:00 2001 From: felipemadero Date: Thu, 26 Sep 2024 09:29:52 -0400 Subject: [PATCH 61/64] Update cmd/blockchaincmd/describe.go Co-authored-by: Michael Kaplan <55204436+michaelkaplan13@users.noreply.github.com> Signed-off-by: felipemadero --- cmd/blockchaincmd/describe.go | 40 +++++++++++++++++++---------------- 1 file changed, 22 insertions(+), 18 deletions(-) diff --git a/cmd/blockchaincmd/describe.go b/cmd/blockchaincmd/describe.go index 288b5c10e..b9ab37905 100644 --- a/cmd/blockchaincmd/describe.go +++ b/cmd/blockchaincmd/describe.go @@ -305,26 +305,30 @@ func printAllocations(sc models.Sidecar, genesis core.Genesis) error { } func printSmartContracts(genesis core.Genesis) { - if len(genesis.Alloc) > 0 { - ux.Logger.PrintToUser("") - t := table.NewWriter() - t.Style().Title.Align = text.AlignCenter - t.Style().Title.Format = text.FormatUpper - t.Style().Options.SeparateRows = true - t.SetTitle("Smart Contracts") - t.AppendHeader(table.Row{"Description", "Address", "Deployer"}) - for address, allocation := range genesis.Alloc { - var description, deployer string - if len(allocation.Code) > 0 { - if address == common.HexToAddress(icmgenesis.MessengerContractAddress) { - description = "ICM Messenger" - deployer = icmgenesis.MessengerDeployerAddress - } - t.AppendRow(table.Row{description, address.Hex(), deployer}) - } + if len(genesis.Alloc) == 0 { + return + } + + ux.Logger.PrintToUser("") + t := table.NewWriter() + t.Style().Title.Align = text.AlignCenter + t.Style().Title.Format = text.FormatUpper + t.Style().Options.SeparateRows = true + t.SetTitle("Smart Contracts") + t.AppendHeader(table.Row{"Description", "Address", "Deployer"}) + for address, allocation := range genesis.Alloc { + if len(allocation.Code) == 0 { + continue } - ux.Logger.PrintToUser(t.Render()) + var description, deployer string + if address == common.HexToAddress(icmgenesis.MessengerContractAddress) { + description = "ICM Messenger" + deployer = icmgenesis.MessengerDeployerAddress + } + t.AppendRow(table.Row{description, address.Hex(), deployer}) + } + ux.Logger.PrintToUser(t.Render()) } func printPrecompiles(genesis core.Genesis) { From be54289918174474c8b8d34524dfa0f28d5d6b05 Mon Sep 17 00:00:00 2001 From: Felipe Madero Date: Thu, 26 Sep 2024 11:24:21 -0300 Subject: [PATCH 62/64] nit --- cmd/blockchaincmd/describe.go | 9 ++++----- pkg/validatormanager/validatormanager.go | 2 +- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/cmd/blockchaincmd/describe.go b/cmd/blockchaincmd/describe.go index 405dd4f5f..1d70777da 100644 --- a/cmd/blockchaincmd/describe.go +++ b/cmd/blockchaincmd/describe.go @@ -321,14 +321,13 @@ func printSmartContracts(genesis core.Genesis) { continue } var description, deployer string - if address == common.HexToAddress(icmgenesis.MessengerContractAddress) { + switch { + case address == common.HexToAddress(icmgenesis.MessengerContractAddress): description = "ICM Messenger" deployer = icmgenesis.MessengerDeployerAddress - } - if address == common.HexToAddress(validatormanager.PoAValidarorMessengerContractAddress) { + case address == common.HexToAddress(validatormanager.PoAValidarorMessengerContractAddress): description = "PoA Validator Manager" - } - if address == common.HexToAddress(validatormanager.PoSValidarorMessengerContractAddress) { + case address == common.HexToAddress(validatormanager.PoSValidarorMessengerContractAddress): description = "PoS Validator Manager" } t.AppendRow(table.Row{description, address.Hex(), deployer}) diff --git a/pkg/validatormanager/validatormanager.go b/pkg/validatormanager/validatormanager.go index 0a444cf4f..c08fdcc36 100644 --- a/pkg/validatormanager/validatormanager.go +++ b/pkg/validatormanager/validatormanager.go @@ -15,7 +15,7 @@ import ( const ( PoAValidarorMessengerContractAddress = "0x5F584C2D56B4c356e7d82EC6129349393dc5df17" - PoSValidarorMessengerContractAddress = "0x5F584C2D56B4c356e7d82EC6129349393dc5df17" + PoSValidarorMessengerContractAddress = "0x6E584C2D56B4c356e7d82EC6129349393dc5df17" ) //go:embed deployed_poa_validator_manager_bytecode.txt From 7426bddb0cfdb17224aeab6085edca28744a3078 Mon Sep 17 00:00:00 2001 From: Felipe Madero Date: Thu, 26 Sep 2024 18:22:02 -0300 Subject: [PATCH 63/64] address PR comments --- cmd/blockchaincmd/create.go | 9 +++-- cmd/blockchaincmd/describe.go | 49 ++++++++++++++++-------- pkg/contract/allocations.go | 8 ++-- pkg/models/sidecar.go | 8 ++++ pkg/validatormanager/validatormanager.go | 5 +-- pkg/vm/create_custom.go | 22 ++++++----- pkg/vm/create_evm.go | 19 ++++----- pkg/vm/evm_prompts.go | 6 +-- 8 files changed, 78 insertions(+), 48 deletions(-) diff --git a/cmd/blockchaincmd/create.go b/cmd/blockchaincmd/create.go index d6f417ac5..d013be3de 100644 --- a/cmd/blockchaincmd/create.go +++ b/cmd/blockchaincmd/create.go @@ -229,12 +229,12 @@ func createBlockchainConfig(cmd *cobra.Command, args []string) error { return err } - if sc.ValidatorManagement != models.ProofOfAuthority && createFlags.poaValidatorManagerOwner != "" { + if !sc.PoA() && createFlags.poaValidatorManagerOwner != "" { return errors.New("--poa-manager-owner flag cannot be used when blockchain validator management type is not Proof of Authority") } if vmType == models.SubnetEvm { - if sc.ValidatorManagement == models.ProofOfAuthority { + if sc.PoA() { if createFlags.poaValidatorManagerOwner == "" { createFlags.poaValidatorManagerOwner, err = getValidatorContractManagerAddr() if err != nil { @@ -319,7 +319,7 @@ func createBlockchainConfig(cmd *cobra.Command, args []string) error { return err } } - if err := vm.FillEvmSidecar( + if sc, err = vm.CreateEvmSidecar( sc, app, blockchainName, @@ -345,7 +345,7 @@ func createBlockchainConfig(cmd *cobra.Command, args []string) error { return err } } - if err := vm.FillCustomSidecar( + if sc, err = vm.CreateCustomSidecar( sc, app, blockchainName, @@ -393,6 +393,7 @@ func createBlockchainConfig(cmd *cobra.Command, args []string) error { } } ux.Logger.GreenCheckmarkToUser("Successfully created blockchain configuration") + ux.Logger.PrintToUser("Run 'avalanche blockchain describe' to view all created addresses and what their roles are") return nil } diff --git a/cmd/blockchaincmd/describe.go b/cmd/blockchaincmd/describe.go index 1d70777da..50470ba3e 100644 --- a/cmd/blockchaincmd/describe.go +++ b/cmd/blockchaincmd/describe.go @@ -108,6 +108,7 @@ func PrintSubnetInfo(blockchainName string, onlyLocalnetInfo bool) error { } t.AppendRow(table.Row{"VM ID", vmIDstr, vmIDstr}, rowConfig) t.AppendRow(table.Row{"VM Version", sc.VMVersion, sc.VMVersion}, rowConfig) + t.AppendRow(table.Row{"Validation", sc.ValidatorManagement, sc.ValidatorManagement}, rowConfig) locallyDeployed, err := localnet.Deployed(sc.Name) if err != nil { @@ -218,7 +219,7 @@ func PrintSubnetInfo(blockchainName string, onlyLocalnetInfo bool) error { if err := printAllocations(sc, genesis); err != nil { return err } - printSmartContracts(genesis) + printSmartContracts(sc, genesis) printPrecompiles(genesis) } @@ -257,16 +258,14 @@ func PrintSubnetInfo(blockchainName string, onlyLocalnetInfo bool) error { func printAllocations(sc models.Sidecar, genesis core.Genesis) error { teleporterKeyAddress := "" - teleporterPrivKey := "" if sc.TeleporterReady { k, err := key.LoadSoft(models.NewLocalNetwork().ID, app.GetKeyPath(sc.TeleporterKey)) if err != nil { return err } teleporterKeyAddress = k.C() - teleporterPrivKey = k.PrivKeyHex() } - subnetAirdropKeyName, subnetAirdropAddress, subnetAirdropPrivKey, err := subnet.GetDefaultSubnetAirdropKeyInfo(app, sc.Name) + _, subnetAirdropAddress, _, err := subnet.GetDefaultSubnetAirdropKeyInfo(app, sc.Name) if err != nil { return err } @@ -277,7 +276,12 @@ func printAllocations(sc models.Sidecar, genesis core.Genesis) error { t.Style().Title.Format = text.FormatUpper t.Style().Options.SeparateRows = true t.SetTitle("Initial Token Allocation") - t.AppendHeader(table.Row{"Description", "Address and Private Key", "Amount (10^18)", "Amount (wei)"}) + t.AppendHeader(table.Row{ + "Description", + "Address and Private Key", + fmt.Sprintf("Amount (%s)", sc.TokenSymbol), + "Amount (wei)", + }) for address, allocation := range genesis.Alloc { amount := allocation.Balance // we are only interested in supply distribution here @@ -289,14 +293,24 @@ func printAllocations(sc models.Sidecar, genesis core.Genesis) error { privKey := "" switch address.Hex() { case teleporterKeyAddress: - description = fmt.Sprintf("%s\n%s", sc.TeleporterKey, logging.Orange.Wrap("Teleporter Deploys")) - privKey = teleporterPrivKey + description = logging.Orange.Wrap("Used by ICM") case subnetAirdropAddress: - description = fmt.Sprintf("%s\n%s", subnetAirdropKeyName, logging.Orange.Wrap("Main funded account")) - privKey = subnetAirdropPrivKey + description = logging.Orange.Wrap("Main funded account") case vm.PrefundedEwoqAddress.Hex(): - description = "Main funded account EWOQ" - privKey = vm.PrefundedEwoqPrivate + description = logging.Orange.Wrap("Main funded account") + case sc.PoAValidatorManagerOwner: + description = logging.Orange.Wrap("PoA Validator Manager Owner") + } + var ( + found bool + name string + ) + found, name, _, privKey, err = contract.SearchForManagedKey(app, models.NewLocalNetwork(), address, true) + if err != nil { + return err + } + if found { + description = fmt.Sprintf("%s\n%s", description, name) } t.AppendRow(table.Row{description, address.Hex() + "\n" + privKey, formattedAmount.String(), amount.String()}) } @@ -305,7 +319,7 @@ func printAllocations(sc models.Sidecar, genesis core.Genesis) error { return nil } -func printSmartContracts(genesis core.Genesis) { +func printSmartContracts(sc models.Sidecar, genesis core.Genesis) { if len(genesis.Alloc) == 0 { return } @@ -325,10 +339,13 @@ func printSmartContracts(genesis core.Genesis) { case address == common.HexToAddress(icmgenesis.MessengerContractAddress): description = "ICM Messenger" deployer = icmgenesis.MessengerDeployerAddress - case address == common.HexToAddress(validatormanager.PoAValidarorMessengerContractAddress): - description = "PoA Validator Manager" - case address == common.HexToAddress(validatormanager.PoSValidarorMessengerContractAddress): - description = "PoS Validator Manager" + case address == common.HexToAddress(validatormanager.ValidatorContractAddress): + if sc.PoA() { + description = "PoA Validator Manager" + } else { + description = "PoS Validator Manager" + + } } t.AppendRow(table.Row{description, address.Hex(), deployer}) } diff --git a/pkg/contract/allocations.go b/pkg/contract/allocations.go index 9c756f222..8a097e930 100644 --- a/pkg/contract/allocations.go +++ b/pkg/contract/allocations.go @@ -71,7 +71,7 @@ func GetBlockchainAirdropKeyInfo( } } for address := range genesis.Alloc { - found, keyName, addressStr, privKey, err := searchForManagedKey(app, network, address, false) + found, keyName, addressStr, privKey, err := SearchForManagedKey(app, network, address, false) if err != nil { return "", "", "", err } @@ -82,7 +82,7 @@ func GetBlockchainAirdropKeyInfo( return "", "", "", nil } -func searchForManagedKey( +func SearchForManagedKey( app *application.Avalanche, network models.Network, address common.Address, @@ -204,7 +204,7 @@ func getGenesisNativeMinterAdmin( return false, false, "", "", "", nil } for _, admin := range allowListCfg.AllowListConfig.AdminAddresses { - found, keyName, addressStr, privKey, err := searchForManagedKey(app, network, admin, true) + found, keyName, addressStr, privKey, err := SearchForManagedKey(app, network, admin, true) if err != nil { return false, false, "", "", "", err } @@ -238,7 +238,7 @@ func getGenesisNativeMinterManager( return false, false, "", "", "", nil } for _, admin := range allowListCfg.AllowListConfig.ManagerAddresses { - found, keyName, addressStr, privKey, err := searchForManagedKey(app, network, admin, true) + found, keyName, addressStr, privKey, err := SearchForManagedKey(app, network, admin, true) if err != nil { return false, false, "", "", "", err } diff --git a/pkg/models/sidecar.go b/pkg/models/sidecar.go index c0b53a810..e165f3a39 100644 --- a/pkg/models/sidecar.go +++ b/pkg/models/sidecar.go @@ -66,3 +66,11 @@ func (sc Sidecar) NetworkDataIsEmpty(network string) bool { _, networkExists := sc.Networks[network] return !networkExists } + +func (sc Sidecar) PoA() bool { + return sc.ValidatorManagement == ProofOfAuthority +} + +func (sc Sidecar) PoS() bool { + return sc.ValidatorManagement == ProofOfStake +} diff --git a/pkg/validatormanager/validatormanager.go b/pkg/validatormanager/validatormanager.go index c08fdcc36..099d78d1f 100644 --- a/pkg/validatormanager/validatormanager.go +++ b/pkg/validatormanager/validatormanager.go @@ -14,8 +14,7 @@ import ( ) const ( - PoAValidarorMessengerContractAddress = "0x5F584C2D56B4c356e7d82EC6129349393dc5df17" - PoSValidarorMessengerContractAddress = "0x6E584C2D56B4c356e7d82EC6129349393dc5df17" + ValidatorContractAddress = "0x5F584C2D56B4c356e7d82EC6129349393dc5df17" ) //go:embed deployed_poa_validator_manager_bytecode.txt @@ -25,7 +24,7 @@ func AddPoAValidatorManagerContractToAllocations( allocs core.GenesisAlloc, ) { deployedPoaValidatorManagerBytes := common.FromHex(strings.TrimSpace(string(deployedPoAValidatorManagerBytecode))) - allocs[common.HexToAddress(PoAValidarorMessengerContractAddress)] = core.GenesisAccount{ + allocs[common.HexToAddress(ValidatorContractAddress)] = core.GenesisAccount{ Balance: big.NewInt(0), Code: deployedPoaValidatorManagerBytes, Nonce: 1, diff --git a/pkg/vm/create_custom.go b/pkg/vm/create_custom.go index 94d7d97b3..358820778 100644 --- a/pkg/vm/create_custom.go +++ b/pkg/vm/create_custom.go @@ -16,7 +16,7 @@ import ( "github.com/ava-labs/avalanche-cli/pkg/ux" ) -func FillCustomSidecar( +func CreateCustomSidecar( sc *models.Sidecar, app *application.Avalanche, subnetName string, @@ -26,9 +26,13 @@ func FillCustomSidecar( customVMBuildScript string, vmPath string, tokenSymbol string, -) error { +) (*models.Sidecar, error) { ux.Logger.PrintToUser("creating custom VM subnet %s", subnetName) + if sc == nil { + sc = &models.Sidecar{} + } + sc.Name = subnetName sc.VM = models.CustomVM sc.Subnet = subnetName @@ -47,39 +51,39 @@ func FillCustomSidecar( options := []string{githubOption, localOption} option, err := app.Prompt.CaptureList("How do you want to set up the VM binary?", options) if err != nil { - return err + return nil, err } if option == githubOption { useRepo = true } else { vmPath, err = app.Prompt.CaptureExistingFilepath("Enter path to VM binary") if err != nil { - return err + return nil, err } } } if useRepo { if err := SetCustomVMSourceCodeFields(app, sc, customVMRepoURL, customVMBranch, customVMBuildScript); err != nil { - return err + return nil, err } if err := BuildCustomVM(app, sc); err != nil { - return err + return nil, err } vmPath = app.GetCustomVMPath(subnetName) } else { if err := app.CopyVMBinary(vmPath, subnetName); err != nil { - return err + return nil, err } } rpcVersion, err := GetVMBinaryProtocolVersion(vmPath) if err != nil { - return fmt.Errorf("unable to get RPC version: %w", err) + return nil, fmt.Errorf("unable to get RPC version: %w", err) } sc.RPCVersion = rpcVersion - return nil + return sc, nil } func LoadCustomGenesis(app *application.Avalanche, genesisPath string) ([]byte, error) { diff --git a/pkg/vm/create_evm.go b/pkg/vm/create_evm.go index 68eecea54..0e75598ff 100644 --- a/pkg/vm/create_evm.go +++ b/pkg/vm/create_evm.go @@ -15,7 +15,6 @@ import ( "github.com/ava-labs/avalanche-cli/pkg/models" "github.com/ava-labs/avalanche-cli/pkg/teleporter" icmgenesis "github.com/ava-labs/avalanche-cli/pkg/teleporter/genesis" - "github.com/ava-labs/avalanche-cli/pkg/ux" "github.com/ava-labs/avalanche-cli/pkg/validatormanager" blockchainSDK "github.com/ava-labs/avalanche-cli/sdk/blockchain" "github.com/ava-labs/subnet-evm/core" @@ -32,32 +31,36 @@ var ( externalGasTokenBalance = big.NewInt(0).Mul(big.NewInt(1e18), big.NewInt(1000)) ) -func FillEvmSidecar( +func CreateEvmSidecar( sc *models.Sidecar, app *application.Avalanche, subnetName string, subnetEVMVersion string, tokenSymbol string, getRPCVersionFromBinary bool, -) error { +) (*models.Sidecar, error) { var ( err error rpcVersion int ) + if sc == nil { + sc = &models.Sidecar{} + } + if getRPCVersionFromBinary { _, vmBin, err := binutils.SetupSubnetEVM(app, subnetEVMVersion) if err != nil { - return fmt.Errorf("failed to install subnet-evm: %w", err) + return nil, fmt.Errorf("failed to install subnet-evm: %w", err) } rpcVersion, err = GetVMBinaryProtocolVersion(vmBin) if err != nil { - return fmt.Errorf("unable to get RPC version: %w", err) + return nil, fmt.Errorf("unable to get RPC version: %w", err) } } else { rpcVersion, err = GetRPCProtocolVersion(app, models.SubnetEvm, subnetEVMVersion) if err != nil { - return err + return nil, err } } @@ -69,7 +72,7 @@ func FillEvmSidecar( sc.TokenSymbol = tokenSymbol sc.TokenName = tokenSymbol + " Token" - return nil + return sc, nil } func CreateEVMGenesis( @@ -78,8 +81,6 @@ func CreateEVMGenesis( teleporterInfo *teleporter.Info, addICMRegistryToGenesis bool, ) ([]byte, error) { - ux.Logger.PrintToUser("creating genesis for blockchain %s", blockchainName) - feeConfig := getFeeConfig(params) // Validity checks on the parameter settings. diff --git a/pkg/vm/evm_prompts.go b/pkg/vm/evm_prompts.go index ea74f41b0..461cbf92e 100644 --- a/pkg/vm/evm_prompts.go +++ b/pkg/vm/evm_prompts.go @@ -172,17 +172,17 @@ func PromptSubnetEVMGenesisParams( ) params.initialTokenAllocation = core.GenesisAlloc{} - if sc.ValidatorManagement == models.ProofOfAuthority { + if sc.PoA() { params.UsePoAValidatorManager = true params.initialTokenAllocation[common.HexToAddress(sc.PoAValidatorManagerOwner)] = core.GenesisAccount{ Balance: defaultPoAOwnerBalance, } } - if sc.ValidatorManagement == models.ProofOfStake { + if sc.PoS() { params.enableNativeMinterPrecompile = true params.nativeMinterPrecompileAllowList.EnabledAddresses = []common.Address{ - common.HexToAddress(validatormanager.PoSValidarorMessengerContractAddress), + common.HexToAddress(validatormanager.ValidatorContractAddress), } } From f7d75732de46c2e6071da1c059fc3c88d2240148 Mon Sep 17 00:00:00 2001 From: Felipe Madero Date: Thu, 26 Sep 2024 18:28:01 -0300 Subject: [PATCH 64/64] lint --- cmd/blockchaincmd/create.go | 1 - cmd/blockchaincmd/describe.go | 1 - cmd/blockchaincmd/export_test.go | 6 ++---- pkg/vm/create_evm.go | 1 - 4 files changed, 2 insertions(+), 7 deletions(-) diff --git a/cmd/blockchaincmd/create.go b/cmd/blockchaincmd/create.go index d013be3de..e82a7fbc2 100644 --- a/cmd/blockchaincmd/create.go +++ b/cmd/blockchaincmd/create.go @@ -310,7 +310,6 @@ func createBlockchainConfig(cmd *cobra.Command, args []string) error { deployTeleporter = params.UseTeleporter useExternalGasToken = params.UseExternalGasToken genesisBytes, err = vm.CreateEVMGenesis( - blockchainName, params, teleporterInfo, createFlags.addICMRegistryToGenesis, diff --git a/cmd/blockchaincmd/describe.go b/cmd/blockchaincmd/describe.go index 50470ba3e..e62ab66f1 100644 --- a/cmd/blockchaincmd/describe.go +++ b/cmd/blockchaincmd/describe.go @@ -344,7 +344,6 @@ func printSmartContracts(sc models.Sidecar, genesis core.Genesis) { description = "PoA Validator Manager" } else { description = "PoS Validator Manager" - } } t.AppendRow(table.Row{description, address.Hex(), deployer}) diff --git a/cmd/blockchaincmd/export_test.go b/cmd/blockchaincmd/export_test.go index 75c00e01c..84a3a1188 100644 --- a/cmd/blockchaincmd/export_test.go +++ b/cmd/blockchaincmd/export_test.go @@ -12,7 +12,6 @@ import ( "github.com/ava-labs/avalanche-cli/internal/mocks" "github.com/ava-labs/avalanche-cli/pkg/application" "github.com/ava-labs/avalanche-cli/pkg/constants" - "github.com/ava-labs/avalanche-cli/pkg/models" "github.com/ava-labs/avalanche-cli/pkg/prompts" "github.com/ava-labs/avalanche-cli/pkg/ux" "github.com/ava-labs/avalanche-cli/pkg/vm" @@ -41,9 +40,8 @@ func TestExportImportSubnet(t *testing.T) { "../../"+utils.SubnetEvmGenesisPath, ) require.NoError(err) - sc := &models.Sidecar{} - err = vm.FillEvmSidecar( - sc, + sc, err := vm.CreateEvmSidecar( + nil, app, testSubnet, vmVersion, diff --git a/pkg/vm/create_evm.go b/pkg/vm/create_evm.go index 0e75598ff..68e0305c9 100644 --- a/pkg/vm/create_evm.go +++ b/pkg/vm/create_evm.go @@ -76,7 +76,6 @@ func CreateEvmSidecar( } func CreateEVMGenesis( - blockchainName string, params SubnetEVMGenesisParams, teleporterInfo *teleporter.Info, addICMRegistryToGenesis bool,