Skip to content
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

add poa setup to blockchain deploy #2219

Merged
merged 22 commits into from
Oct 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
105 changes: 102 additions & 3 deletions cmd/blockchaincmd/deploy.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,12 @@ import (
"os"
"path/filepath"
"strings"
"time"

"github.com/ava-labs/avalanchego/vms/platformvm/warp/message"
"github.com/ethereum/go-ethereum/common"

"github.com/ava-labs/avalanche-cli/pkg/contract"
"github.com/ava-labs/avalanche-cli/pkg/utils"
"github.com/ava-labs/avalanchego/utils/formatting/address"
"github.com/ava-labs/avalanchego/vms/platformvm/fx"
Expand All @@ -29,6 +32,7 @@ import (
"github.com/ava-labs/avalanche-cli/pkg/subnet"
"github.com/ava-labs/avalanche-cli/pkg/txutils"
"github.com/ava-labs/avalanche-cli/pkg/ux"
"github.com/ava-labs/avalanche-cli/pkg/validatormanager"
"github.com/ava-labs/avalanche-cli/pkg/vm"
anrutils "github.com/ava-labs/avalanche-network-runner/utils"
"github.com/ava-labs/avalanchego/ids"
Expand Down Expand Up @@ -67,6 +71,7 @@ var (
icmSpec subnet.ICMSpec
generateNodeID bool
bootstrapValidatorsJSONFilePath string
privateKeyFlags contract.PrivateKeyFlags

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")
Expand Down Expand Up @@ -94,6 +99,8 @@ so you can take your locally tested Subnet and deploy it on Fuji or Mainnet.`,
Args: cobrautils.ExactArgs(1),
}
networkoptions.AddNetworkFlagsToCmd(cmd, &globalNetworkFlags, true, deploySupportedNetworkOptions)
privateKeyFlags.SetFlagNames("blockchain-private-key", "blockchain-key", "blockchain-genesis-key")
privateKeyFlags.AddToCmd(cmd, "to fund validator manager initialization")
felipemadero marked this conversation as resolved.
Show resolved Hide resolved
cmd.Flags().StringVar(&userProvidedAvagoVersion, "avalanchego-version", "latest", "use this version of avalanchego (ex: v1.17.12)")
cmd.Flags().StringVarP(&keyName, "key", "k", "", "select the key to use [fuji/devnet deploy only]")
cmd.Flags().BoolVarP(&sameControlKey, "same-control-key", "s", false, "use the fee-paying key as control key")
Expand Down Expand Up @@ -559,6 +566,7 @@ func deployBlockchain(cmd *cobra.Command, args []string) error {
if err != nil {
return err
}
deployer.CleanCacheWallet()
// get the control keys in the same order as the tx
_, controlKeys, threshold, err = txutils.GetOwners(network, subnetID)
if err != nil {
Expand Down Expand Up @@ -610,21 +618,25 @@ func deployBlockchain(cmd *cobra.Command, args []string) error {
}

if sidecar.Sovereign {
avaGoBootstrapValidators, err := convertToAvalancheGoSubnetValidator(bootstrapValidators)
avaGoBootstrapValidators, err := ConvertToAvalancheGoSubnetValidator(bootstrapValidators)
if err != nil {
return err
}
deployer.CleanCacheWallet()
managerAddress := common.HexToAddress(validatormanager.ValidatorContractAddress)
isFullySigned, ConvertL1TxID, tx, remainingSubnetAuthKeys, err := deployer.ConvertL1(
controlKeys,
subnetAuthKeys,
subnetID,
blockchainID,
managerAddress,
avaGoBootstrapValidators,
)
if err != nil {
ux.Logger.PrintToUser(logging.Red.Wrap(
fmt.Sprintf("error converting blockchain: %s. fix the issue and try again with a new convert cmd", err),
))
return err
}

savePartialTx = !isFullySigned && err == nil
Expand All @@ -643,6 +655,93 @@ func deployBlockchain(cmd *cobra.Command, args []string) error {
return err
}
}

bar, err := ux.TimedProgressBar(
30*time.Second,
"Waiting for Blockchain to be converted into Subnet Only Validator (SOV) Blockchain ...",
2,
)
if err != nil {
return err
}

// Issue random transaction >30s after ConverSubnetTx to evict its block from the block map
_, _, err = deployer.PChainTransfer(kc.Addresses().List()[0], 1)
if err != nil {
return err
}
if err := ux.ExtraStepExecuted(bar); err != nil {
return err
}
// Issue random transaction to advance the p-chain height now that the
// ConvertSubnetTx block isn't in the block map
_, _, err = deployer.PChainTransfer(kc.Addresses().List()[0], 1)
if err != nil {
return err
}
if err := ux.ExtraStepExecuted(bar); err != nil {
return err
}
fmt.Println()

felipemadero marked this conversation as resolved.
Show resolved Hide resolved
if err := app.UpdateSidecarNetworks(&sidecar, network, subnetID, blockchainID, "", "", bootstrapValidators); err != nil {
felipemadero marked this conversation as resolved.
Show resolved Hide resolved
return err
}

if false {
felipemadero marked this conversation as resolved.
Show resolved Hide resolved
chainSpec := contract.ChainSpec{
BlockchainName: blockchainName,
}
genesisAddress, genesisPrivateKey, err := contract.GetEVMSubnetPrefundedKey(
app,
network,
chainSpec,
)
if err != nil {
return err
}
felipemadero marked this conversation as resolved.
Show resolved Hide resolved
privateKey, err := privateKeyFlags.GetPrivateKey(app, genesisPrivateKey)
if err != nil {
return err
}
if privateKey == "" {
privateKey, err = prompts.PromptPrivateKey(
app.Prompt,
"Which key to you want to use to pay for initializing Validator Manager contract? (Uses Blockchain gas token)",
app.GetKeyDir(),
app.GetKey,
genesisAddress,
genesisPrivateKey,
)
if err != nil {
return err
}
}
rpcURL, _, err := contract.GetBlockchainEndpoints(
app,
network,
chainSpec,
true,
false,
)
if err != nil {
return err
}
if err := validatormanager.SetupPoA(
app,
network,
rpcURL,
contract.ChainSpec{
BlockchainName: blockchainName,
},
privateKey,
common.HexToAddress(sidecar.PoAValidatorManagerOwner),
avaGoBootstrapValidators,
); err != nil {
return err
}
ux.Logger.GreenCheckmarkToUser("Subnet is successfully converted into Subnet Only Validator")
}
}

flags := make(map[string]string)
Expand All @@ -651,7 +750,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, "", "", bootstrapValidators)
return nil
}

func getBLSInfo(publicKey, proofOfPossesion string) (signer.ProofOfPossession, error) {
Expand All @@ -676,7 +775,7 @@ func getBLSInfo(publicKey, proofOfPossesion string) (signer.ProofOfPossession, e
}

// TODO: add deactivation owner?
func convertToAvalancheGoSubnetValidator(subnetValidators []models.SubnetValidator) ([]*txs.ConvertSubnetValidator, error) {
func ConvertToAvalancheGoSubnetValidator(subnetValidators []models.SubnetValidator) ([]*txs.ConvertSubnetValidator, error) {
bootstrapValidators := []*txs.ConvertSubnetValidator{}
for _, validator := range subnetValidators {
nodeID, err := ids.NodeIDFromString(validator.NodeID)
Expand Down
13 changes: 13 additions & 0 deletions cmd/blockchaincmd/describe.go
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,19 @@ func PrintSubnetInfo(blockchainName string, onlyLocalnetInfo bool) error {
t.AppendRow(table.Row{net, "BlockchainID (CB58)", data.BlockchainID.String()})
t.AppendRow(table.Row{net, "BlockchainID (HEX)", hexEncoding})
}
endpoint, _, err := contract.GetBlockchainEndpoints(
app,
network,
contract.ChainSpec{
BlockchainName: sc.Name,
},
false,
false,
)
if err != nil {
return err
}
t.AppendRow(table.Row{net, "RPC Endpoint", endpoint})
}
ux.Logger.PrintToUser(t.Render())

Expand Down
1 change: 1 addition & 0 deletions cmd/blockchaincmd/prompt_genesis_input.go
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ func promptBootstrapValidators(network models.Network) ([]models.SubnetValidator
var subnetValidators []models.SubnetValidator
numBootstrapValidators, err := app.Prompt.CaptureInt(
"How many bootstrap validators do you want to set up?",
prompts.ValidatePositiveInt,
)
if err != nil {
return nil, err
Expand Down
2 changes: 1 addition & 1 deletion cmd/blockchaincmd/upgradecmd/apply.go
Original file line number Diff line number Diff line change
Expand Up @@ -305,7 +305,7 @@ func applyPublicNetworkUpgrade(blockchainName, networkKey string, sc *models.Sid

ux.Logger.PrintToUser("Trying to install the upgrade files at the provided %s path", avalanchegoChainConfigDir)
chainDir := filepath.Join(avalanchegoChainConfigDir, sc.Networks[networkKey].BlockchainID.String())
destPath := filepath.Join(chainDir, constants.UpgradeBytesFileName)
destPath := filepath.Join(chainDir, constants.UpgradeFileName)
if err = os.Mkdir(chainDir, constants.DefaultPerms755); err != nil && !os.IsExist(err) {
return fmt.Errorf("failed to create blockchain directory: %w", err)
}
Expand Down
2 changes: 2 additions & 0 deletions cmd/contractcmd/contract.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,7 @@ and interacting with smart contracts.`,
app = injectedApp
// contract deploy
cmd.AddCommand(newDeployCmd())
// contract initpoamanager
cmd.AddCommand(newInitPOAManagerCmd())
felipemadero marked this conversation as resolved.
Show resolved Hide resolved
return cmd
}
132 changes: 132 additions & 0 deletions cmd/contractcmd/init_poa_validator_manager.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
// Copyright (C) 2024, Ava Labs, Inc. All rights reserved.
// See the file LICENSE for licensing terms.
package contractcmd

import (
"fmt"

"github.com/ava-labs/avalanche-cli/cmd/blockchaincmd"
"github.com/ava-labs/avalanche-cli/pkg/cobrautils"
"github.com/ava-labs/avalanche-cli/pkg/contract"
"github.com/ava-labs/avalanche-cli/pkg/networkoptions"
"github.com/ava-labs/avalanche-cli/pkg/prompts"
"github.com/ava-labs/avalanche-cli/pkg/ux"
"github.com/ava-labs/avalanche-cli/pkg/validatormanager"
"github.com/ava-labs/avalanchego/ids"
"github.com/ava-labs/avalanchego/utils/logging"
"github.com/ethereum/go-ethereum/common"

"github.com/spf13/cobra"
)

type InitPOAManagerFlags struct {
Network networkoptions.NetworkFlags
PrivateKeyFlags contract.PrivateKeyFlags
rpcEndpoint string
}

var (
initPOAManagerSupportedNetworkOptions = []networkoptions.NetworkOption{
networkoptions.Local,
networkoptions.Devnet,
networkoptions.Fuji,
}
initPOAManagerFlags InitPOAManagerFlags
)

// avalanche contract initpoamanager
func newInitPOAManagerCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "initPoaManager",
Short: "Initializes a Proof of Authority Validator Manager on a given Network and Blockchain",
Long: "Initializes Proof of Authority Validator Manager contract on a Blockchain and sets up initial validator set on the Blockchain. For more info on Validator Manager, please head to https://github.com/ava-labs/teleporter/tree/staking-contract/contracts/validator-manager",
RunE: initPOAManager,
Args: cobrautils.ExactArgs(1),
}
networkoptions.AddNetworkFlagsToCmd(cmd, &initPOAManagerFlags.Network, true, initPOAManagerSupportedNetworkOptions)
initPOAManagerFlags.PrivateKeyFlags.AddToCmd(cmd, "as contract deployer")
cmd.Flags().StringVar(&initPOAManagerFlags.rpcEndpoint, "rpc", "", "deploy the contract into the given rpc endpoint")
return cmd
}

func initPOAManager(_ *cobra.Command, args []string) error {
blockchainName := args[0]
chainSpec := contract.ChainSpec{
BlockchainName: blockchainName,
}
network, err := networkoptions.GetNetworkFromCmdLineFlags(
app,
"",
initPOAManagerFlags.Network,
true,
false,
initPOAManagerSupportedNetworkOptions,
"",
)
if err != nil {
return err
}
if initPOAManagerFlags.rpcEndpoint == "" {
initPOAManagerFlags.rpcEndpoint, _, err = contract.GetBlockchainEndpoints(
app,
network,
chainSpec,
true,
false,
)
if err != nil {
return err
}
}
ux.Logger.PrintToUser(logging.Yellow.Wrap("RPC Endpoint: %s"), initPOAManagerFlags.rpcEndpoint)
genesisAddress, genesisPrivateKey, err := contract.GetEVMSubnetPrefundedKey(
app,
network,
chainSpec,
)
if err != nil {
return err
}
privateKey, err := initPOAManagerFlags.PrivateKeyFlags.GetPrivateKey(app, genesisPrivateKey)
if err != nil {
return err
}
if privateKey == "" {
privateKey, err = prompts.PromptPrivateKey(
app.Prompt,
"Which key to you want to use to pay for initializing Proof of Authority Validator Manager contract? (Uses Blockchain gas token)",
app.GetKeyDir(),
app.GetKey,
genesisAddress,
genesisPrivateKey,
)
if err != nil {
return err
}
}
sc, err := app.LoadSidecar(chainSpec.BlockchainName)
if err != nil {
return fmt.Errorf("failed to load sidecar: %w", err)
}
if sc.Networks[network.Name()].BlockchainID == ids.Empty {
felipemadero marked this conversation as resolved.
Show resolved Hide resolved
return fmt.Errorf("blockchain has not been deployed to %s", network.Name())
}
bootstrapValidators := sc.Networks[network.Name()].BootstrapValidators
felipemadero marked this conversation as resolved.
Show resolved Hide resolved
avaGoBootstrapValidators, err := blockchaincmd.ConvertToAvalancheGoSubnetValidator(bootstrapValidators)
if err != nil {
return err
}
if err := validatormanager.SetupPoA(
app,
network,
initPOAManagerFlags.rpcEndpoint,
chainSpec,
privateKey,
common.HexToAddress(sc.PoAValidatorManagerOwner),
avaGoBootstrapValidators,
); err != nil {
return err
}
felipemadero marked this conversation as resolved.
Show resolved Hide resolved
ux.Logger.GreenCheckmarkToUser("Proof of Authority Validator Manager contract successfully initialized on blockchain %s", blockchainName)
return nil
}
Loading
Loading