From 5e1a7c66dded87c59a82d3672ca3e9e5ce7ae8f2 Mon Sep 17 00:00:00 2001 From: Raymond Sukanto Date: Wed, 29 May 2024 19:13:22 -0400 Subject: [PATCH] address comments --- keychain/keychain.go | 106 +++++++++++++++++++-------------- subnet/add_validator_subnet.go | 20 +++---- wallet/wallet.go | 22 +++---- 3 files changed, 83 insertions(+), 65 deletions(-) diff --git a/keychain/keychain.go b/keychain/keychain.go index 3cd761c..0401172 100644 --- a/keychain/keychain.go +++ b/keychain/keychain.go @@ -4,6 +4,7 @@ package keychain import ( "fmt" + "github.com/ava-labs/avalanchego/utils/formatting/address" "avalanche-tooling-sdk-go/avalanche" "avalanche-tooling-sdk-go/key" @@ -22,50 +23,6 @@ type Keychain struct { ledgerIndices []uint32 } -func (kc *Keychain) P() ([]string, error) { - return utils.P(kc.network.HRP(), kc.Addresses().List()) -} - -func (kc *Keychain) LedgerEnabled() bool { - return kc.ledgerDevice != nil -} - -func (kc *Keychain) AddLedgerIndices(indices []uint32) error { - if kc.LedgerEnabled() { - kc.ledgerIndices = utils.Unique(append(kc.ledgerIndices, indices...)) - utils.Uint32Sort(kc.ledgerIndices) - newKc, err := keychain.NewLedgerKeychainFromIndices(kc.ledgerDevice, kc.ledgerIndices) - if err != nil { - return err - } - kc.Keychain = newKc - return nil - } - return fmt.Errorf("keychain is not ledger enabled") -} - -func (kc *Keychain) AddLedgerAddresses(addresses []string) error { - if kc.LedgerEnabled() { - indices, err := kc.ledgerDevice.FindAddresses(addresses, 0) - if err != nil { - return err - } - return kc.AddLedgerIndices(maps.Values(indices)) - } - return fmt.Errorf("keychain is not ledger enabled") -} - -func (kc *Keychain) AddLedgerFunds(amount uint64) error { - if kc.LedgerEnabled() { - indices, err := kc.ledgerDevice.FindFunds(kc.network, amount, 0) - if err != nil { - return err - } - return kc.AddLedgerIndices(indices) - } - return fmt.Errorf("keychain is not ledger enabled") -} - func NewKeychain( network avalanche.Network, keyPath string, @@ -123,3 +80,64 @@ func NewKeychain( } return nil, fmt.Errorf("not keychain option defined") } + +func (kc *Keychain) P() ([]string, error) { + return utils.P(kc.network.HRP(), kc.Addresses().List()) +} + +func (kc *Keychain) LedgerEnabled() bool { + return kc.ledgerDevice != nil +} + +func (kc *Keychain) AddLedgerIndices(indices []uint32) error { + if kc.LedgerEnabled() { + kc.ledgerIndices = utils.Unique(append(kc.ledgerIndices, indices...)) + utils.Uint32Sort(kc.ledgerIndices) + newKc, err := keychain.NewLedgerKeychainFromIndices(kc.ledgerDevice, kc.ledgerIndices) + if err != nil { + return err + } + kc.Keychain = newKc + return nil + } + return fmt.Errorf("keychain is not ledger enabled") +} + +func (kc *Keychain) AddLedgerAddresses(addresses []string) error { + if kc.LedgerEnabled() { + indices, err := kc.ledgerDevice.FindAddresses(addresses, 0) + if err != nil { + return err + } + return kc.AddLedgerIndices(maps.Values(indices)) + } + return fmt.Errorf("keychain is not ledger enabled") +} + +func (kc *Keychain) AddLedgerFunds(amount uint64) error { + if kc.LedgerEnabled() { + indices, err := kc.ledgerDevice.FindFunds(kc.network, amount, 0) + if err != nil { + return err + } + return kc.AddLedgerIndices(indices) + } + return fmt.Errorf("keychain is not ledger enabled") +} + +func (kc *Keychain) PChainFormattedStrAddresses() ([]string, error) { + addrs := kc.Addresses().List() + if len(addrs) == 0 { + return nil, fmt.Errorf("no addresses in keychain") + } + hrp := kc.network.HRP() + addrsStr := []string{} + for _, addr := range addrs { + addrStr, err := address.Format("P", hrp, addr[:]) + if err != nil { + return nil, err + } + addrsStr = append(addrsStr, addrStr) + } + return addrsStr, nil +} diff --git a/subnet/add_validator_subnet.go b/subnet/add_validator_subnet.go index 8b12296..0f5542b 100644 --- a/subnet/add_validator_subnet.go +++ b/subnet/add_validator_subnet.go @@ -6,6 +6,7 @@ package subnet import "C" import ( "avalanche-tooling-sdk-go/avalanche" + "avalanche-tooling-sdk-go/multisig" "avalanche-tooling-sdk-go/wallet" "fmt" "github.com/ava-labs/avalanchego/ids" @@ -29,18 +30,17 @@ type ValidatorParams struct { } // AddValidator adds validator to subnet -func (c *Subnet) AddValidator(wallet wallet.Wallet, validatorInput ValidatorParams) error { - controlKeys, threshold, err := getOwners(network, c.SubnetID, c.DeployInfo.TransferSubnetOwnershipTxID) +func (c *Subnet) AddValidator(wallet wallet.Wallet, validatorInput ValidatorParams) (*multisig.Multisig, error) { + controlKeys, threshold, err := GetOwners(network, c.SubnetID, c.DeployInfo.TransferSubnetOwnershipTxID) if err != nil { return err } - if err := CheckSubnetAuthKeys(kcKeys, c.DeployInfo.SubnetAuthKeys, controlKeys, threshold); err != nil { - return err + if err := checkSubnetAuthKeys(wallet.Keychain, c.DeployInfo.SubnetAuthKeys, controlKeys, threshold); err != nil { + return nil, err } validator := &txs.SubnetValidator{ Validator: txs.Validator{ NodeID: validatorInput.NodeID, - Start: uint64(validatorInput.StartTime.Unix()), End: uint64(validatorInput.StartTime.Add(validatorInput.Duration).Unix()), Wght: validatorInput.Weight, }, @@ -50,16 +50,16 @@ func (c *Subnet) AddValidator(wallet wallet.Wallet, validatorInput ValidatorPara wallet.SetSubnetAuthMultisig(c.DeployInfo.SubnetAuthKeys) unsignedTx, err := wallet.P().Builder().NewAddSubnetValidatorTx(validator) if err != nil { - return fmt.Errorf("error building tx: %w", err) + return nil, fmt.Errorf("error building tx: %w", err) } tx := txs.Tx{Unsigned: unsignedTx} if err := wallet.P().Signer().Sign(context.Background(), &tx); err != nil { - return fmt.Errorf("error signing tx: %w", err) + return nil, fmt.Errorf("error signing tx: %w", err) } - return nil + return multisig.New(&tx), nil } -func CheckSubnetAuthKeys(walletKeys []string, subnetAuthKeys []string, controlKeys []string, threshold uint32) error { +func checkSubnetAuthKeys(walletKeys []string, subnetAuthKeys []string, controlKeys []string, threshold uint32) error { for _, walletKey := range walletKeys { if slices.Contains(controlKeys, walletKey) && !slices.Contains(subnetAuthKeys, walletKey) { return fmt.Errorf("wallet key %s is a subnet control key so it must be included in subnet auth keys", walletKey) @@ -83,7 +83,7 @@ func CheckSubnetAuthKeys(walletKeys []string, subnetAuthKeys []string, controlKe return nil } -func getOwners(network avalanche.Network, subnetID ids.ID, transferSubnetOwnershipTxID ids.ID) ([]string, uint32, error) { +func GetOwners(network avalanche.Network, subnetID ids.ID, transferSubnetOwnershipTxID ids.ID) ([]string, uint32, error) { pClient := platformvm.NewClient(network.Endpoint) ctx := context.Background() var owner *secp256k1fx.OutputOwners diff --git a/wallet/wallet.go b/wallet/wallet.go index 00ad87c..54761af 100644 --- a/wallet/wallet.go +++ b/wallet/wallet.go @@ -15,8 +15,8 @@ import ( type Wallet struct { primary.Wallet - keychain keychain.Keychain - options []common.Option + Keychain keychain.Keychain + Options []common.Option } func New(ctx context.Context, config *primary.WalletConfig) (Wallet, error) { @@ -26,35 +26,35 @@ func New(ctx context.Context, config *primary.WalletConfig) (Wallet, error) { ) return Wallet{ Wallet: wallet, - keychain: keychain.Keychain{ + Keychain: keychain.Keychain{ Keychain: config.AVAXKeychain, }, }, err } -// SecureWalletIsChangeOwner ensures that a fee paying address (wallet's keychain) will receive +// SecureWalletIsChangeOwner ensures that a fee paying address (wallet's Keychain) will receive // the change UTXO and not a randomly selected auth key that may not be paying fees func (w *Wallet) SecureWalletIsChangeOwner() { - addrs := w.keychain.Addresses().List() + addrs := w.Keychain.Addresses().List() changeAddr := addrs[0] // sets change to go to wallet addr (instead of any other subnet auth key) changeOwner := &secp256k1fx.OutputOwners{ Threshold: 1, Addrs: []ids.ShortID{changeAddr}, } - w.options = append(w.options, common.WithChangeOwner(changeOwner)) - w.Wallet = primary.NewWalletWithOptions(w.Wallet, w.options...) + w.Options = append(w.Options, common.WithChangeOwner(changeOwner)) + w.Wallet = primary.NewWalletWithOptions(w.Wallet, w.Options...) } -// SetAuthKeys sets auth keys that will be used when signing txs, besides the wallet's keychain fee +// SetAuthKeys sets auth keys that will be used when signing txs, besides the wallet's Keychain fee // paying ones func (w *Wallet) SetAuthKeys(authKeys []ids.ShortID) { - addrs := w.keychain.Addresses().List() + addrs := w.Keychain.Addresses().List() addrsSet := set.Set[ids.ShortID]{} addrsSet.Add(addrs...) addrsSet.Add(authKeys...) - w.options = append(w.options, common.WithCustomAddresses(addrsSet)) - w.Wallet = primary.NewWalletWithOptions(w.Wallet, w.options...) + w.Options = append(w.Options, common.WithCustomAddresses(addrsSet)) + w.Wallet = primary.NewWalletWithOptions(w.Wallet, w.Options...) } func (w *Wallet) SetSubnetAuthMultisig(authKeys []ids.ShortID) {