-
Notifications
You must be signed in to change notification settings - Fork 117
make public import to support SOV L1s #2746
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 5 commits
f415cbb
ab219b3
6fad984
de52a0e
486ead2
34606a1
81eb798
7c46fd0
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -32,9 +32,10 @@ import ( | |
| var ( | ||
| blockchainIDStr string | ||
| subnetIDstr string | ||
| nodeURL string | ||
| useSubnetEvm bool | ||
| useCustomVM bool | ||
| rpcURL string | ||
| noRPCAvailable bool | ||
| ) | ||
|
|
||
| // avalanche blockchain import public | ||
|
|
@@ -48,12 +49,12 @@ func newImportPublicCmd() *cobra.Command { | |
|
|
||
| By default, an imported Blockchain | ||
| doesn't overwrite an existing Blockchain with the same name. To allow overwrites, provide the --force | ||
| flag.`, | ||
| plag.`, | ||
| } | ||
|
|
||
| networkoptions.AddNetworkFlagsToCmd(cmd, &globalNetworkFlags, false, networkoptions.DefaultSupportedNetworkOptions) | ||
|
|
||
| cmd.Flags().StringVar(&nodeURL, "node-url", "", "[optional] URL of an already running validator") | ||
| cmd.Flags().StringVar(&nodeEndpoint, "node-endpoint", "", "[optional] URL of an already running validator") | ||
|
|
||
| cmd.Flags().BoolVar(&useSubnetEvm, "evm", false, "import a subnet-evm") | ||
| cmd.Flags().BoolVar(&useCustomVM, "custom", false, "use a custom VM template") | ||
|
|
@@ -69,6 +70,8 @@ flag.`, | |
| "", | ||
| "the blockchain ID", | ||
| ) | ||
| cmd.Flags().StringVar(&rpcURL, "rpc", "", "rpc endpoint for the blockchain") | ||
sukantoraymond marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| cmd.Flags().BoolVar(&noRPCAvailable, "no-rpc-available", false, "use this when an RPC if offline and can't be accesed") | ||
felipemadero marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| return cmd | ||
| } | ||
|
|
||
|
|
@@ -86,133 +89,89 @@ func importPublic(*cobra.Command, []string) error { | |
| return err | ||
| } | ||
|
|
||
| var reply *info.GetNodeVersionReply | ||
| var blockchainID ids.ID | ||
| if blockchainIDStr != "" { | ||
| blockchainID, err = ids.FromString(blockchainIDStr) | ||
| if err != nil { | ||
| return err | ||
| } | ||
| } | ||
|
|
||
| if nodeURL == "" { | ||
| sc, genBytes, err := importBlockchain(network, rpcURL, !noRPCAvailable, blockchainID, ux.Logger.PrintToUser) | ||
| if err != nil { | ||
| return err | ||
| } | ||
|
|
||
| sc.TokenName = constants.DefaultTokenName | ||
| sc.TokenSymbol = constants.DefaultTokenSymbol | ||
|
|
||
| sc.VM, err = vm.PromptVMType(app, useSubnetEvm, useCustomVM) | ||
| if err != nil { | ||
| return err | ||
| } | ||
|
|
||
| var nodeVersionReply *info.GetNodeVersionReply | ||
| if nodeEndpoint == "" { | ||
| yes, err := app.Prompt.CaptureNoYes("Have validator nodes already been deployed to this blockchain?") | ||
| if err != nil { | ||
| return err | ||
| } | ||
| if yes { | ||
| nodeURL, err = app.Prompt.CaptureString( | ||
| nodeEndpoint, err = app.Prompt.CaptureString( | ||
| "Please provide an API URL of such a node so we can query its VM version (e.g. http://111.22.33.44:5555)") | ||
| if err != nil { | ||
| return err | ||
| } | ||
| ctx, cancel := utils.GetAPIContext() | ||
| defer cancel() | ||
| infoAPI := info.NewClient(nodeURL) | ||
| infoAPI := info.NewClient(nodeEndpoint) | ||
| options := []rpc.Option{} | ||
| reply, err = infoAPI.GetNodeVersion(ctx, options...) | ||
| nodeVersionReply, err = infoAPI.GetNodeVersion(ctx, options...) | ||
| if err != nil { | ||
| return fmt.Errorf("failed to query node - is it running and reachable? %w", err) | ||
| } | ||
| } | ||
| } | ||
|
|
||
| var blockchainID ids.ID | ||
| if blockchainIDStr == "" { | ||
| blockchainID, err = app.Prompt.CaptureID("What is the ID of the blockchain?") | ||
| if err != nil { | ||
| return err | ||
| } | ||
| } else { | ||
| blockchainID, err = ids.FromString(blockchainIDStr) | ||
| if err != nil { | ||
| return err | ||
| } | ||
| } | ||
|
|
||
| ux.Logger.PrintToUser("Getting information from the %s network...", network.Name()) | ||
|
|
||
| createChainTx, err := utils.GetBlockchainTx(network.Endpoint, blockchainID) | ||
| if err != nil { | ||
| return err | ||
| } | ||
|
|
||
| vmID := createChainTx.VMID | ||
| subnetID := createChainTx.SubnetID | ||
| blockchainName := createChainTx.ChainName | ||
| genBytes := createChainTx.GenesisData | ||
|
|
||
| ux.Logger.PrintToUser("Retrieved information. BlockchainID: %s, SubnetID: %s, Name: %s, VMID: %s", | ||
| blockchainID.String(), | ||
| subnetID.String(), | ||
| blockchainName, | ||
| vmID.String(), | ||
| ) | ||
| // TODO: it's probably possible to deploy VMs with the same name on a public network | ||
| // In this case, an import could clash because the tool supports unique names only | ||
|
|
||
| vmType, err := vm.PromptVMType(app, useSubnetEvm, useCustomVM) | ||
| if err != nil { | ||
| return err | ||
| } | ||
|
|
||
| vmIDstr := vmID.String() | ||
|
|
||
| sc := &models.Sidecar{ | ||
| Name: blockchainName, | ||
| VM: vmType, | ||
| Networks: map[string]models.NetworkData{ | ||
| network.Name(): { | ||
| SubnetID: subnetID, | ||
| BlockchainID: blockchainID, | ||
| }, | ||
| }, | ||
| Subnet: blockchainName, | ||
| Version: constants.SidecarVersion, | ||
| TokenName: constants.DefaultTokenName, | ||
| TokenSymbol: constants.DefaultTokenSymbol, | ||
| ImportedVMID: vmIDstr, | ||
| } | ||
|
|
||
| var versions []string | ||
|
|
||
| if reply != nil { | ||
| if nodeVersionReply != nil { | ||
| // a node was queried | ||
| for _, v := range reply.VMVersions { | ||
| if v == vmIDstr { | ||
| for _, v := range nodeVersionReply.VMVersions { | ||
| if v == sc.ImportedVMID { | ||
| sc.VMVersion = v | ||
| break | ||
| } | ||
| } | ||
| sc.RPCVersion = int(reply.RPCProtocolVersion) | ||
| } else { | ||
| sc.RPCVersion = int(nodeVersionReply.RPCProtocolVersion) | ||
| } else if sc.VM == models.SubnetEvm { | ||
| // no node was queried, ask the user | ||
| switch vmType { | ||
| case models.SubnetEvm: | ||
| versions, err = app.Downloader.GetAllReleasesForRepo(constants.AvaLabsOrg, constants.SubnetEVMRepoName, "", application.All) | ||
| if err != nil { | ||
| return err | ||
| } | ||
| sc.VMVersion, err = app.Prompt.CaptureList("Pick the version for this VM", versions) | ||
| case models.CustomVM: | ||
| return fmt.Errorf("importing custom VMs is not yet implemented, but will be available soon") | ||
| default: | ||
| return fmt.Errorf("unexpected VM type: %v", vmType) | ||
| versions, err = app.Downloader.GetAllReleasesForRepo(constants.AvaLabsOrg, constants.SubnetEVMRepoName, "", application.All) | ||
| if err != nil { | ||
| return err | ||
| } | ||
| sc.VMVersion, err = app.Prompt.CaptureList("Pick the version for this VM", versions) | ||
| if err != nil { | ||
| return err | ||
| } | ||
| sc.RPCVersion, err = vm.GetRPCProtocolVersion(app, vmType, sc.VMVersion) | ||
| sc.RPCVersion, err = vm.GetRPCProtocolVersion(app, sc.VM, sc.VMVersion) | ||
| if err != nil { | ||
| return fmt.Errorf("failed getting RPCVersion for VM type %s with version %s", vmType, sc.VMVersion) | ||
| return fmt.Errorf("failed getting RPCVersion for VM type %s with version %s", sc.VM, sc.VMVersion) | ||
| } | ||
| } | ||
| if vmType == models.SubnetEvm { | ||
|
|
||
| if sc.VM == models.SubnetEvm { | ||
| var genesis core.Genesis | ||
| if err := json.Unmarshal(genBytes, &genesis); err != nil { | ||
| return err | ||
| } | ||
| sc.ChainID = genesis.Config.ChainID.String() | ||
| } | ||
|
|
||
| if err := app.CreateSidecar(sc); err != nil { | ||
| if err := app.CreateSidecar(&sc); err != nil { | ||
| return fmt.Errorf("failed creating the sidecar for import: %w", err) | ||
| } | ||
|
|
||
| if err = app.WriteGenesisFile(blockchainName, genBytes); err != nil { | ||
| if err = app.WriteGenesisFile(sc.Name, genBytes); err != nil { | ||
| return err | ||
| } | ||
|
|
||
|
|
@@ -221,62 +180,99 @@ func importPublic(*cobra.Command, []string) error { | |
| return nil | ||
| } | ||
|
|
||
| func importL1(blockchainIDStr string, rpcURL string, network models.Network) (models.Sidecar, error) { | ||
| var sc models.Sidecar | ||
| func importBlockchain( | ||
| network models.Network, | ||
| rpcURL string, | ||
| rpcIsAvailable bool, | ||
| blockchainID ids.ID, | ||
| printFunc func(msg string, args ...interface{}), | ||
| ) (models.Sidecar, []byte, error) { | ||
| var err error | ||
|
|
||
| if rpcIsAvailable && rpcURL == "" { | ||
| rpcURL, err = app.Prompt.CaptureURL("What is the RPC endpoint?", false) | ||
| if err != nil { | ||
| return models.Sidecar{}, nil, err | ||
| } | ||
| } | ||
|
|
||
| blockchainID, err := precompiles.WarpPrecompileGetBlockchainID(rpcURL) | ||
| if err != nil { | ||
| if blockchainIDStr == "" { | ||
| if blockchainID == ids.Empty { | ||
| var err error | ||
| if rpcIsAvailable { | ||
| blockchainID, _ = precompiles.WarpPrecompileGetBlockchainID(rpcURL) | ||
| } | ||
| if blockchainID == ids.Empty { | ||
| blockchainID, err = app.Prompt.CaptureID("What is the Blockchain ID?") | ||
| if err != nil { | ||
| return models.Sidecar{}, err | ||
| } | ||
| } else { | ||
| blockchainID, err = ids.FromString(blockchainIDStr) | ||
| if err != nil { | ||
| return models.Sidecar{}, err | ||
| return models.Sidecar{}, nil, err | ||
| } | ||
| } | ||
| } | ||
| subnetID, err := blockchain.GetSubnetIDFromBlockchainID(blockchainID, network) | ||
|
|
||
| createChainTx, err := utils.GetBlockchainTx(network.Endpoint, blockchainID) | ||
| if err != nil { | ||
| return models.Sidecar{}, err | ||
| return models.Sidecar{}, nil, err | ||
| } | ||
|
|
||
| subnetID := createChainTx.SubnetID | ||
| vmID := createChainTx.VMID | ||
| blockchainName := createChainTx.ChainName | ||
| genBytes := createChainTx.GenesisData | ||
|
|
||
| printFunc("Retrieved information:") | ||
| printFunc(" Name: %s", blockchainName) | ||
| printFunc(" BlockchainID: %s", blockchainID.String()) | ||
| printFunc(" SubnetID: %s", subnetID.String()) | ||
| printFunc(" VMID: %s", vmID.String()) | ||
|
|
||
| subnetInfo, err := blockchain.GetSubnet(subnetID, network) | ||
| if err != nil { | ||
| return models.Sidecar{}, err | ||
| } | ||
| if subnetInfo.IsPermissioned { | ||
| return models.Sidecar{}, fmt.Errorf("unable to import non sovereign Subnets") | ||
| return models.Sidecar{}, nil, err | ||
| } | ||
| validatorManagerAddress = "0x" + hex.EncodeToString(subnetInfo.ManagerAddress) | ||
|
|
||
| // add validator without blockchain arg is only for l1s | ||
| sc = models.Sidecar{ | ||
| Sovereign: true, | ||
| sc := models.Sidecar{ | ||
| Name: blockchainName, | ||
| Networks: map[string]models.NetworkData{ | ||
| network.Name(): { | ||
| SubnetID: subnetID, | ||
| BlockchainID: blockchainID, | ||
| }, | ||
| }, | ||
| Subnet: blockchainName, | ||
| Version: constants.SidecarVersion, | ||
| ImportedVMID: vmID.String(), | ||
| ImportedFromAPM: true, | ||
| } | ||
|
|
||
| sc.ValidatorManagement, err = validatorManagerSDK.GetValidatorManagerType(rpcURL, common.HexToAddress(validatorManagerAddress)) | ||
| if err != nil { | ||
| return models.Sidecar{}, fmt.Errorf("could not obtain validator manager type: %w", err) | ||
| if rpcIsAvailable { | ||
| e := sc.Networks[network.Name()] | ||
| e.RPCEndpoints = []string{rpcURL} | ||
| sc.Networks[network.Name()] = e | ||
| } | ||
|
|
||
| if sc.ValidatorManagement == validatormanagertypes.ProofOfAuthority { | ||
| owner, err := contract.GetContractOwner(rpcURL, common.HexToAddress(validatorManagerAddress)) | ||
| if err != nil { | ||
| return models.Sidecar{}, err | ||
| if !subnetInfo.IsPermissioned { | ||
| sc.Sovereign = true | ||
| validatorManagerAddress = "0x" + hex.EncodeToString(subnetInfo.ManagerAddress) | ||
| e := sc.Networks[network.Name()] | ||
| e.ValidatorManagerAddress = validatorManagerAddress | ||
| sc.Networks[network.Name()] = e | ||
| printFunc(" Validator Manager Address: %s", validatorManagerAddress) | ||
| if rpcIsAvailable { | ||
| sc.ValidatorManagement, err = validatorManagerSDK.GetValidatorManagerType(rpcURL, common.HexToAddress(validatorManagerAddress)) | ||
| if err != nil { | ||
| return models.Sidecar{}, nil, fmt.Errorf("could not obtain validator manager type: %w", err) | ||
| } | ||
| printFunc(" Validation Kind: %s", sc.ValidatorManagement) | ||
| if sc.ValidatorManagement == validatormanagertypes.ProofOfAuthority { | ||
| owner, err := contract.GetContractOwner(rpcURL, common.HexToAddress(validatorManagerAddress)) | ||
| if err != nil { | ||
| return models.Sidecar{}, nil, err | ||
| } | ||
| sc.ValidatorManagerOwner = owner.String() | ||
| printFunc(" Validator Manager Owner: %s", sc.ValidatorManagerOwner) | ||
felipemadero marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| } | ||
| } | ||
| sc.ValidatorManagerOwner = owner.String() | ||
| } | ||
|
|
||
| sc.Networks = make(map[string]models.NetworkData) | ||
|
|
||
| sc.Networks[network.Name()] = models.NetworkData{ | ||
| SubnetID: subnetID, | ||
| BlockchainID: blockchainID, | ||
| ValidatorManagerAddress: validatorManagerAddress, | ||
| RPCEndpoints: []string{rpcURL}, | ||
| } | ||
| return sc, err | ||
| return sc, genBytes, err | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.