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

Acp 77 PoS using sdk/validatorManager #2308

Open
wants to merge 27 commits into
base: acp-77
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
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
7 changes: 5 additions & 2 deletions .github/workflows/e2e-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ jobs:
"\\[Subnet Compatibility\\]",
"\\[Public Subnet non SOV\\]",
"\\[Etna Subnet SOV\\]",
"\\[Etna AddRemove Validator SOV\\]",
"\\[Etna AddRemove Validator SOV PoA\\]",
"\\[Etna AddRemove Validator SOV PoS\\]",
"\\[Subnet\\]",
"\\[Upgrade expect network failure\\]",
"\\[Upgrade public network\\]",
Expand All @@ -47,7 +48,9 @@ jobs:
- os: macos-14
suite: "\\[Public Subnet non SOV\\]"
- os: ubuntu-latest
suite: "\\[Etna AddRemove Validator SOV\\]"
suite: "\\[Etna AddRemove Validator SOV PoA\\]"
- os: ubuntu-latest
suite: "\\[Etna AddRemove Validator SOV PoS\\]"
steps:
- name: Checkout repository
uses: actions/checkout@v4
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -54,3 +54,4 @@ pkg/contract/contracts/cache/
pkg/contract/contracts/out/

osxcross/

48 changes: 44 additions & 4 deletions cmd/blockchaincmd/add_validator.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"encoding/hex"
"errors"
"fmt"
"math/big"
"time"

"github.com/ava-labs/avalanchego/utils/units"
Expand Down Expand Up @@ -59,6 +60,9 @@ var (
disableOwnerAddr string
rpcURL string
aggregatorLogLevel string
forcePoS bool
delegationFee uint16
stakeDuration uint64

errNoSubnetID = errors.New("failed to find the subnet ID for this subnet, has it been deployed/created on this network?")
errMutuallyExclusiveDurationOptions = errors.New("--use-default-duration/--use-default-validator-params and --staking-period are mutually exclusive")
Expand Down Expand Up @@ -112,6 +116,11 @@ Testnet or Mainnet.`,
cmd.Flags().StringSliceVar(&subnetAuthKeys, "subnet-auth-keys", nil, "(for non sovereign blockchain) control keys that will be used to authenticate add validator tx")
cmd.Flags().StringVar(&outputTxPath, "output-tx-path", "", "(for non sovereign blockchain) file path of the add validator tx")
cmd.Flags().BoolVar(&waitForTxAcceptance, "wait-for-tx-acceptance", true, "(for non sovereign blockchain) just issue the add validator tx, without waiting for its acceptance")
cmd.Flags().BoolVar(&forcePoS, "pos", false, "force validator initialization as PoS validator")
cmd.Flags().Uint64Var(&stakeAmount, "stake-amount", 0, "amount of tokens to stake")
cmd.Flags().Uint16Var(&delegationFee, "delegation-fee", 0, "delegation fee (in bips)")
cmd.Flags().Uint64Var(&stakeDuration, "stake-duration", 0, "stake duration in seconds")

return cmd
}

Expand Down Expand Up @@ -238,16 +247,40 @@ func CallAddValidator(
ownerPrivateKeyFound, _, _, ownerPrivateKey, err := contract.SearchForManagedKey(
app,
network,
common.HexToAddress(sc.PoAValidatorManagerOwner),
common.HexToAddress(sc.ValidatorManagerOwner),
true,
)
if err != nil {
return err
}
if !ownerPrivateKeyFound {
return fmt.Errorf("private key for PoA manager owner %s is not found", sc.PoAValidatorManagerOwner)
return fmt.Errorf("private key for Validator manager owner %s is not found", sc.ValidatorManagerOwner)
}

pos := sc.PoS() || forcePoS

if pos {
// should take input prior to here for stake amount, delegation fee, and min stake duration
if stakeAmount == 0 {
stakeAmount, err = app.Prompt.CaptureUint64(fmt.Sprintf("Enter the amount of tokens to stake (in %s)", blockchainName))
if err != nil {
return err
}
}
if delegationFee == 0 {
delegationFee, err = app.Prompt.CaptureUint16("Enter the delegation fee (in bips)")
if err != nil {
return nil
}
}
if stakeDuration == 0 {
stakeDuration, err = app.Prompt.CaptureUint64("Enter the stake duration (in seconds)")
if err != nil {
return nil
}
}
}
ux.Logger.PrintToUser(logging.Yellow.Wrap("PoA manager owner %s pays for the initialization of the validator's registration (Blockchain gas token)"), sc.PoAValidatorManagerOwner)
ux.Logger.PrintToUser(logging.Yellow.Wrap("Validation manager owner %s pays for the initialization of the validator's registration (Blockchain gas token)"), sc.ValidatorManagerOwner)

if rpcURL == "" {
rpcURL, _, err = contract.GetBlockchainEndpoints(
Expand Down Expand Up @@ -338,6 +371,10 @@ func CallAddValidator(
weight,
extraAggregatorPeers,
aggregatorLogLevel,
pos,
delegationFee,
stakeDuration,
big.NewInt(int64(stakeAmount)),
)
if err != nil {
return err
Expand Down Expand Up @@ -371,7 +408,10 @@ func CallAddValidator(

ux.Logger.PrintToUser(" NodeID: %s", nodeID)
ux.Logger.PrintToUser(" Network: %s", network.Name())
ux.Logger.PrintToUser(" Weight: %d", weight)
// weight is inaccurate for PoS as it's fetched during registration
if !pos {
ux.Logger.PrintToUser(" Weight: %d", weight)
}
ux.Logger.PrintToUser(" Balance: %d", balance/units.Avax)
ux.Logger.GreenCheckmarkToUser("Validator successfully added to the Subnet")

Expand Down
50 changes: 37 additions & 13 deletions cmd/blockchaincmd/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,9 @@ type CreateFlags struct {
addICMRegistryToGenesis bool
proofOfStake bool
proofOfAuthority bool
poaValidatorManagerOwner string
rewardBasisPoints uint64
validatorManagerOwner string
proxyContractOwner string
enableDebugging bool
}

Expand All @@ -64,7 +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")
errSOVFlagsOnly = errors.New("flags --proof-of-authority, --proof-of-stake, --poa-manager-owner are only applicable to Subnet Only Validator (SOV) blockchains")
errSOVFlagsOnly = errors.New("flags --proof-of-authority, --proof-of-stake, --poa-manager-owner --proxy-contract-owner are only applicable to Subnet Only Validator (SOV) blockchains")
errPOSFlagsOnly = errors.New("flags --reward-basis-points are only applicable to Proof of Stake (PoS) blockchains")
)

// avalanche blockchain create
Expand Down Expand Up @@ -110,9 +113,11 @@ 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.addICMRegistryToGenesis, "icm-registry-at-genesis", false, "setup ICM registry smart contract on genesis [experimental]")
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, "(coming soon) use proof of stake for validator management")
cmd.Flags().StringVar(&createFlags.poaValidatorManagerOwner, "poa-manager-owner", "", "EVM address that controls Validator Manager Owner (for Proof of Authority only)")
cmd.Flags().BoolVar(&createFlags.proofOfStake, "proof-of-stake", false, "use proof of stake for validator management")
cmd.Flags().StringVar(&createFlags.validatorManagerOwner, "validator-manager-owner", "", "EVM address that controls Validator Manager Owner")
cmd.Flags().StringVar(&createFlags.proxyContractOwner, "proxy-contract-owner", "", "EVM address that controls ProxyAdmin for TransparentProxy of ValidatorManager contract")
cmd.Flags().BoolVar(&sovereign, "sovereign", true, "set to false if creating non-sovereign blockchain")
cmd.Flags().Uint64Var(&createFlags.rewardBasisPoints, "reward-basis-points", 0, "reward basis points for PoS Reward Calculator")
cmd.Flags().BoolVar(&createFlags.enableDebugging, "debug", true, "enable blockchain debugging")
return cmd
}
Expand Down Expand Up @@ -199,7 +204,7 @@ func createBlockchainConfig(cmd *cobra.Command, args []string) error {
}

if !sovereign {
if createFlags.proofOfAuthority || createFlags.proofOfStake || createFlags.poaValidatorManagerOwner != "" {
if createFlags.proofOfAuthority || createFlags.proofOfStake || createFlags.validatorManagerOwner != "" {
return errSOVFlagsOnly
}
}
Expand All @@ -208,6 +213,10 @@ func createBlockchainConfig(cmd *cobra.Command, args []string) error {
return errMutuallyExlusiveValidatorManagementOptions
}

if createFlags.rewardBasisPoints > 0 && !createFlags.proofOfStake {
return errPOSFlagsOnly
}

// get vm kind
vmType, err := vm.PromptVMType(app, createFlags.useSubnetEvm, createFlags.useCustomVM)
if err != nil {
Expand Down Expand Up @@ -239,22 +248,35 @@ func createBlockchainConfig(cmd *cobra.Command, args []string) error {
if err = promptValidatorManagementType(app, sc); err != nil {
return err
}
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 sovereign {
if sc.PoA() {
if createFlags.poaValidatorManagerOwner == "" {
createFlags.poaValidatorManagerOwner, err = getValidatorContractManagerAddr()
if createFlags.validatorManagerOwner == "" {
createFlags.validatorManagerOwner, err = getValidatorContractManagerAddr()
if err != nil {
return err
}
}
sc.ValidatorManagerOwner = createFlags.validatorManagerOwner
ux.Logger.GreenCheckmarkToUser("Validator Manager Contract owner address %s", createFlags.validatorManagerOwner)

if createFlags.proxyContractOwner == "" {
createFlags.proxyContractOwner, err = getProxyAdminOwnerAddr()
if err != nil {
return err
}
ux.Logger.GreenCheckmarkToUser("Proxy Admin Contract owner address %s", createFlags.proxyContractOwner)
}
sc.ProxyContractOwner = createFlags.proxyContractOwner
ux.Logger.GreenCheckmarkToUser("Proxy Admin Contract owner address %s", createFlags.proxyContractOwner)
if sc.PoS() {
if createFlags.rewardBasisPoints == 0 {
createFlags.rewardBasisPoints, err = app.Prompt.CaptureUint64("Enter reward basis points for PoS Reward Calculator")
if err != nil {
return err
}
}
sc.PoAValidatorManagerOwner = createFlags.poaValidatorManagerOwner
ux.Logger.GreenCheckmarkToUser("Validator Manager Contract owner address %s", createFlags.poaValidatorManagerOwner)
}
}

Expand Down Expand Up @@ -326,6 +348,8 @@ func createBlockchainConfig(cmd *cobra.Command, args []string) error {
params,
teleporterInfo,
createFlags.addICMRegistryToGenesis,
sc.ProxyContractOwner,
createFlags.rewardBasisPoints,
)
if err != nil {
return err
Expand Down
49 changes: 43 additions & 6 deletions cmd/blockchaincmd/deploy.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"encoding/json"
"errors"
"fmt"
"math/big"
"os"
"path/filepath"
"strings"
Expand Down Expand Up @@ -42,8 +43,8 @@ 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"
validatorManagerSDK "github.com/ava-labs/avalanche-cli/sdk/validatormanager"
anrutils "github.com/ava-labs/avalanche-network-runner/utils"
"github.com/ava-labs/avalanchego/ids"
"github.com/ava-labs/avalanchego/utils/logging"
Expand Down Expand Up @@ -90,6 +91,13 @@ var (
bootstrapEndpoints []string
convertOnly bool

poSMinimumStakeAmount uint64 // big.Int
poSMaximumStakeAmount uint64 // big.Int
poSMinimumStakeDuration uint64
poSMinimumDelegationFee uint16
poSMaximumStakeMultiplier uint8
poSWeightToValueFactor uint64 // big.Int

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")
Expand Down Expand Up @@ -151,6 +159,14 @@ so you can take your locally tested Subnet and deploy it on Fuji or Mainnet.`,
cmd.Flags().IntVar(&numBootstrapValidators, "num-bootstrap-validators", 0, "(only if --generate-node-id is true) number of bootstrap validators to set up in sovereign L1 validator)")
cmd.Flags().IntVar(&numLocalNodes, "num-local-nodes", 5, "number of nodes to be created on local machine")
cmd.Flags().StringVar(&changeOwnerAddress, "change-owner-address", "", "address that will receive change if node is no longer L1 validator")

cmd.Flags().Uint64Var(&poSMinimumStakeAmount, "pos-minimum-stake-amount", 1, "minimum stake amount")
cmd.Flags().Uint64Var(&poSMaximumStakeAmount, "pos-maximum-stake-amount", 1000, "maximum stake amount")
cmd.Flags().Uint64Var(&poSMinimumStakeDuration, "pos-minimum-stake-duration", 100, "minimum stake duration")
cmd.Flags().Uint16Var(&poSMinimumDelegationFee, "pos-minimum-delegation-fee", 1, "minimum delegation fee")
cmd.Flags().Uint8Var(&poSMaximumStakeMultiplier, "pos-maximum-stake-multiplier", 1, "maximum stake multiplier")
cmd.Flags().Uint64Var(&poSWeightToValueFactor, "pos-weight-to-value-factor", 1, "weight to value factor")

return cmd
}

Expand Down Expand Up @@ -773,7 +789,7 @@ func deployBlockchain(cmd *cobra.Command, args []string) error {
return err
}
deployer.CleanCacheWallet()
managerAddress := common.HexToAddress(validatormanager.ValidatorContractAddress)
managerAddress := common.HexToAddress(validatorManagerSDK.ProxyContractAddress)
isFullySigned, convertL1TxID, tx, remainingSubnetAuthKeys, err := deployer.ConvertL1(
controlKeys,
subnetAuthKeys,
Expand Down Expand Up @@ -874,7 +890,6 @@ func deployBlockchain(cmd *cobra.Command, args []string) error {
if err != nil {
return err
}
ux.Logger.PrintToUser("Initializing Proof of Authority Validator Manager contract on blockchain %s ...", blockchainName)
subnetID, err := contract.GetSubnetID(
app,
network,
Expand All @@ -891,7 +906,7 @@ func deployBlockchain(cmd *cobra.Command, args []string) error {
if err != nil {
return err
}
ownerAddress := common.HexToAddress(sidecar.PoAValidatorManagerOwner)
ownerAddress := common.HexToAddress(sidecar.ValidatorManagerOwner)
subnetSDK := blockchainSDK.Subnet{
SubnetID: subnetID,
BlockchainID: blockchainID,
Expand All @@ -903,9 +918,31 @@ func deployBlockchain(cmd *cobra.Command, args []string) error {
if err != nil {
logLvl = logging.Off
}
if err := subnetSDK.InitializeProofOfAuthority(network, genesisPrivateKey, extraAggregatorPeers, logLvl); err != nil {
return err
if sidecar.ValidatorManagement == models.ProofOfStake {
ux.Logger.PrintToUser("Initializing Native Token Proof of Stake Validator Manager contract on blockchain %s ...", blockchainName)
if err := subnetSDK.InitializeProofOfStake(
network,
genesisPrivateKey,
extraAggregatorPeers,
logLvl,
big.NewInt(int64(poSMinimumStakeAmount)),
big.NewInt(int64(poSMaximumStakeAmount)),
poSMinimumStakeDuration,
poSMinimumDelegationFee,
poSMaximumStakeMultiplier,
big.NewInt(int64(poSWeightToValueFactor)),
validatorManagerSDK.RewardCalculatorAddress,
); err != nil {
return err
}
} else {
ux.Logger.PrintToUser("Initializing Proof of Authority Validator Manager contract on blockchain %s ...", blockchainName)
if err := subnetSDK.InitializeProofOfAuthority(network, genesisPrivateKey, extraAggregatorPeers, logLvl); err != nil {
return err
}
ux.Logger.GreenCheckmarkToUser("Proof of Authority Validator Manager contract successfully initialized on blockchain %s", blockchainName)
}

ux.Logger.GreenCheckmarkToUser("Proof of Authority Validator Manager contract successfully initialized on blockchain %s", blockchainName)
} else {
ux.Logger.GreenCheckmarkToUser("Converted subnet successfully generated")
Expand Down
19 changes: 14 additions & 5 deletions cmd/blockchaincmd/describe.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ 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"
validatorManagerSDK "github.com/ava-labs/avalanche-cli/sdk/validatormanager"
anr_utils "github.com/ava-labs/avalanche-network-runner/utils"
"github.com/ava-labs/avalanchego/ids"
"github.com/ava-labs/avalanchego/utils/logging"
Expand Down Expand Up @@ -314,8 +314,10 @@ func printAllocations(sc models.Sidecar, genesis core.Genesis) error {
description = logging.Orange.Wrap("Main funded account")
case vm.PrefundedEwoqAddress.Hex():
description = logging.Orange.Wrap("Main funded account")
case sc.PoAValidatorManagerOwner:
description = logging.Orange.Wrap("PoA Validator Manager Owner")
case sc.ValidatorManagerOwner:
description = logging.Orange.Wrap("Validator Manager Owner")
case sc.ProxyContractOwner:
description = logging.Orange.Wrap("Proxy Admin Owner")
}
var (
found bool
Expand Down Expand Up @@ -355,12 +357,19 @@ func printSmartContracts(sc models.Sidecar, genesis core.Genesis) {
case address == common.HexToAddress(icmgenesis.MessengerContractAddress):
description = "ICM Messenger"
deployer = icmgenesis.MessengerDeployerAddress
case address == common.HexToAddress(validatormanager.ValidatorContractAddress):
case address == common.HexToAddress(validatorManagerSDK.ValidatorContractAddress):
if sc.PoA() {
description = "PoA Validator Manager"
} else {
description = "PoS Validator Manager"
description = "Native Token Staking Manager"
}
case address == common.HexToAddress(validatorManagerSDK.ProxyContractAddress):
description = "Transparent Proxy"
case address == common.HexToAddress(validatorManagerSDK.ProxyAdminContractAddress):
description = "Proxy Admin"
deployer = sc.ProxyContractOwner
case address == common.HexToAddress(validatorManagerSDK.RewardCalculatorAddress):
description = "Reward Calculator"
}
t.AppendRow(table.Row{description, address.Hex(), deployer})
}
Expand Down
Loading
Loading