diff --git a/tests/antithesis/main.go b/tests/antithesis/main.go index 24f766133309..d33a8808e0f4 100644 --- a/tests/antithesis/main.go +++ b/tests/antithesis/main.go @@ -408,7 +408,9 @@ func (w *workload) issueXToPTransfer(ctx context.Context) { avaxAssetID = xWallet.AVAXAssetID() avaxBalance = balances[avaxAssetID] xBaseTxFee = xWallet.BaseTxFee() - pBaseTxFee = pWallet.BaseTxFee() + pBuilder = pWallet.Builder() + pContext = pBuilder.Context() + pBaseTxFee = pContext.BaseTxFee txFees = xBaseTxFee + pBaseTxFee neededBalance = txFees + units.Avax ) @@ -471,9 +473,10 @@ func (w *workload) issuePToXTransfer(ctx context.Context) { } var ( - avaxAssetID = pWallet.AVAXAssetID() + pContext = pBuilder.Context() + avaxAssetID = pContext.AVAXAssetID avaxBalance = balances[avaxAssetID] - pBaseTxFee = pWallet.BaseTxFee() + pBaseTxFee = pContext.BaseTxFee xBaseTxFee = xWallet.BaseTxFee() txFees = pBaseTxFee + xBaseTxFee neededBalance = txFees + units.Schmeckle diff --git a/tests/e2e/p/interchain_workflow.go b/tests/e2e/p/interchain_workflow.go index a9c70beacbf0..f45a1f8c6669 100644 --- a/tests/e2e/p/interchain_workflow.go +++ b/tests/e2e/p/interchain_workflow.go @@ -56,6 +56,9 @@ var _ = e2e.DescribePChain("[Interchain Workflow]", ginkgo.Label(e2e.UsesCChainL cWallet := baseWallet.C() pWallet := baseWallet.P() + pBuilder := pWallet.Builder() + pContext := pBuilder.Context() + ginkgo.By("defining common configuration") recipientEthAddress := evm.GetEthAddress(recipientKey) avaxAssetID := xWallet.AVAXAssetID() @@ -114,7 +117,7 @@ var _ = e2e.DescribePChain("[Interchain Workflow]", ginkgo.Label(e2e.UsesCChainL Subnet: constants.PrimaryNetworkID, }, nodePOP, - pWallet.AVAXAssetID(), + pContext.AVAXAssetID, &secp256k1fx.OutputOwners{ Threshold: 1, Addrs: []ids.ShortID{rewardKey.Address()}, @@ -143,7 +146,7 @@ var _ = e2e.DescribePChain("[Interchain Workflow]", ginkgo.Label(e2e.UsesCChainL }, Subnet: constants.PrimaryNetworkID, }, - pWallet.AVAXAssetID(), + pContext.AVAXAssetID, &secp256k1fx.OutputOwners{ Threshold: 1, Addrs: []ids.ShortID{rewardKey.Address()}, diff --git a/tests/e2e/p/staking_rewards.go b/tests/e2e/p/staking_rewards.go index 436d89675bc5..e988cf43c2c4 100644 --- a/tests/e2e/p/staking_rewards.go +++ b/tests/e2e/p/staking_rewards.go @@ -104,6 +104,9 @@ var _ = ginkgo.Describe("[Staking Rewards]", func() { baseWallet := e2e.NewWallet(keychain, nodeURI) pWallet := baseWallet.P() + pBuilder := pWallet.Builder() + pContext := pBuilder.Context() + const ( delegationPercent = 0.10 // 10% delegationShare = reward.PercentDenominator * delegationPercent @@ -130,7 +133,7 @@ var _ = ginkgo.Describe("[Staking Rewards]", func() { Subnet: constants.PrimaryNetworkID, }, alphaPOP, - pWallet.AVAXAssetID(), + pContext.AVAXAssetID, &secp256k1fx.OutputOwners{ Threshold: 1, Addrs: []ids.ShortID{alphaValidationRewardKey.Address()}, @@ -159,7 +162,7 @@ var _ = ginkgo.Describe("[Staking Rewards]", func() { Subnet: constants.PrimaryNetworkID, }, betaPOP, - pWallet.AVAXAssetID(), + pContext.AVAXAssetID, &secp256k1fx.OutputOwners{ Threshold: 1, Addrs: []ids.ShortID{betaValidationRewardKey.Address()}, @@ -191,7 +194,7 @@ var _ = ginkgo.Describe("[Staking Rewards]", func() { }, Subnet: constants.PrimaryNetworkID, }, - pWallet.AVAXAssetID(), + pContext.AVAXAssetID, &secp256k1fx.OutputOwners{ Threshold: 1, Addrs: []ids.ShortID{gammaDelegationRewardKey.Address()}, @@ -214,7 +217,7 @@ var _ = ginkgo.Describe("[Staking Rewards]", func() { }, Subnet: constants.PrimaryNetworkID, }, - pWallet.AVAXAssetID(), + pContext.AVAXAssetID, &secp256k1fx.OutputOwners{ Threshold: 1, Addrs: []ids.ShortID{deltaDelegationRewardKey.Address()}, @@ -276,7 +279,7 @@ var _ = ginkgo.Describe("[Staking Rewards]", func() { pWallet := baseWallet.P() balances, err := pWallet.Builder().GetBalance() require.NoError(err) - rewardBalances[rewardKey.Address()] = balances[pWallet.AVAXAssetID()] + rewardBalances[rewardKey.Address()] = balances[pContext.AVAXAssetID] } require.Len(rewardBalances, len(rewardKeys)) diff --git a/tests/e2e/p/validator_sets.go b/tests/e2e/p/validator_sets.go index 36072e327a21..a3f3e1e9f075 100644 --- a/tests/e2e/p/validator_sets.go +++ b/tests/e2e/p/validator_sets.go @@ -36,11 +36,14 @@ var _ = e2e.DescribePChain("[Validator Sets]", func() { baseWallet := e2e.NewWallet(keychain, nodeURI) pWallet := baseWallet.P() + pBuilder := pWallet.Builder() + pContext := pBuilder.Context() + const delegatorCount = 15 ginkgo.By(fmt.Sprintf("adding %d delegators", delegatorCount), func() { rewardKey, err := secp256k1.NewPrivateKey() require.NoError(err) - avaxAssetID := pWallet.AVAXAssetID() + avaxAssetID := pContext.AVAXAssetID startTime := time.Now().Add(tmpnet.DefaultValidatorStartTimeDiff) endTime := startTime.Add(time.Second * 360) // This is the default flag value for MinDelegatorStake. diff --git a/tests/e2e/p/workflow.go b/tests/e2e/p/workflow.go index 1819df448568..7b9e213acaa5 100644 --- a/tests/e2e/p/workflow.go +++ b/tests/e2e/p/workflow.go @@ -41,7 +41,9 @@ var _ = e2e.DescribePChain("[Workflow]", func() { baseWallet := e2e.NewWallet(keychain, nodeURI) pWallet := baseWallet.P() - avaxAssetID := baseWallet.P().AVAXAssetID() + pBuilder := pWallet.Builder() + pContext := pBuilder.Context() + avaxAssetID := pContext.AVAXAssetID xWallet := baseWallet.X() pChainClient := platformvm.NewClient(nodeURI.URI) diff --git a/wallet/chain/p/backend.go b/wallet/chain/p/backend.go index 5b8001808ceb..ed8e6a4f8830 100644 --- a/wallet/chain/p/backend.go +++ b/wallet/chain/p/backend.go @@ -4,6 +4,7 @@ package p import ( + "context" "sync" "github.com/ava-labs/avalanchego/database" @@ -13,31 +14,31 @@ import ( "github.com/ava-labs/avalanchego/vms/components/avax" "github.com/ava-labs/avalanchego/vms/platformvm/fx" "github.com/ava-labs/avalanchego/vms/platformvm/txs" + "github.com/ava-labs/avalanchego/wallet/chain/p/builder" + "github.com/ava-labs/avalanchego/wallet/chain/p/signer" "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" - - stdcontext "context" ) var _ Backend = (*backend)(nil) // Backend defines the full interface required to support a P-chain wallet. type Backend interface { - common.ChainUTXOs - BuilderBackend - SignerBackend + builder.Backend + signer.Backend - AcceptTx(ctx stdcontext.Context, tx *txs.Tx) error + AcceptTx(ctx context.Context, tx *txs.Tx) error } type backend struct { - Context common.ChainUTXOs + context *builder.Context + subnetOwnerLock sync.RWMutex subnetOwner map[ids.ID]fx.Owner // subnetID -> owner } -func NewBackend(ctx Context, utxos common.ChainUTXOs, subnetTxs map[ids.ID]*txs.Tx) Backend { +func NewBackend(context *builder.Context, utxos common.ChainUTXOs, subnetTxs map[ids.ID]*txs.Tx) Backend { subnetOwner := make(map[ids.ID]fx.Owner) for txID, tx := range subnetTxs { // first get owners from the CreateSubnetTx createSubnetTx, ok := tx.Unsigned.(*txs.CreateSubnetTx) @@ -54,13 +55,13 @@ func NewBackend(ctx Context, utxos common.ChainUTXOs, subnetTxs map[ids.ID]*txs. subnetOwner[transferSubnetOwnershipTx.Subnet] = transferSubnetOwnershipTx.Owner } return &backend{ - Context: ctx, ChainUTXOs: utxos, + context: context, subnetOwner: subnetOwner, } } -func (b *backend) AcceptTx(ctx stdcontext.Context, tx *txs.Tx) error { +func (b *backend) AcceptTx(ctx context.Context, tx *txs.Tx) error { txID := tx.ID() err := tx.Unsigned.Visit(&backendVisitor{ b: b, @@ -75,7 +76,7 @@ func (b *backend) AcceptTx(ctx stdcontext.Context, tx *txs.Tx) error { return b.addUTXOs(ctx, constants.PlatformChainID, producedUTXOSlice) } -func (b *backend) addUTXOs(ctx stdcontext.Context, destinationChainID ids.ID, utxos []*avax.UTXO) error { +func (b *backend) addUTXOs(ctx context.Context, destinationChainID ids.ID, utxos []*avax.UTXO) error { for _, utxo := range utxos { if err := b.AddUTXO(ctx, destinationChainID, utxo); err != nil { return err @@ -84,7 +85,7 @@ func (b *backend) addUTXOs(ctx stdcontext.Context, destinationChainID ids.ID, ut return nil } -func (b *backend) removeUTXOs(ctx stdcontext.Context, sourceChain ids.ID, utxoIDs set.Set[ids.ID]) error { +func (b *backend) removeUTXOs(ctx context.Context, sourceChain ids.ID, utxoIDs set.Set[ids.ID]) error { for utxoID := range utxoIDs { if err := b.RemoveUTXO(ctx, sourceChain, utxoID); err != nil { return err @@ -93,7 +94,7 @@ func (b *backend) removeUTXOs(ctx stdcontext.Context, sourceChain ids.ID, utxoID return nil } -func (b *backend) GetSubnetOwner(_ stdcontext.Context, subnetID ids.ID) (fx.Owner, error) { +func (b *backend) GetSubnetOwner(_ context.Context, subnetID ids.ID) (fx.Owner, error) { b.subnetOwnerLock.RLock() defer b.subnetOwnerLock.RUnlock() diff --git a/wallet/chain/p/backend_visitor.go b/wallet/chain/p/backend_visitor.go index d8b118fa21b7..c7cec9544da1 100644 --- a/wallet/chain/p/backend_visitor.go +++ b/wallet/chain/p/backend_visitor.go @@ -4,29 +4,34 @@ package p import ( + "context" + "errors" + "github.com/ava-labs/avalanchego/ids" "github.com/ava-labs/avalanchego/utils/constants" "github.com/ava-labs/avalanchego/vms/components/avax" "github.com/ava-labs/avalanchego/vms/platformvm/txs" - - stdcontext "context" ) -var _ txs.Visitor = (*backendVisitor)(nil) +var ( + _ txs.Visitor = (*backendVisitor)(nil) + + ErrUnsupportedTxType = errors.New("unsupported tx type") +) // backendVisitor handles accepting of transactions for the backend type backendVisitor struct { b *backend - ctx stdcontext.Context + ctx context.Context txID ids.ID } func (*backendVisitor) AdvanceTimeTx(*txs.AdvanceTimeTx) error { - return errUnsupportedTxType + return ErrUnsupportedTxType } func (*backendVisitor) RewardValidatorTx(*txs.RewardValidatorTx) error { - return errUnsupportedTxType + return ErrUnsupportedTxType } func (b *backendVisitor) AddValidatorTx(tx *txs.AddValidatorTx) error { diff --git a/wallet/chain/p/builder.go b/wallet/chain/p/builder/builder.go similarity index 91% rename from wallet/chain/p/builder.go rename to wallet/chain/p/builder/builder.go index fff2b5860201..e142342dc483 100644 --- a/wallet/chain/p/builder.go +++ b/wallet/chain/p/builder/builder.go @@ -1,9 +1,10 @@ // Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved. // See the file LICENSE for licensing terms. -package p +package builder import ( + "context" "errors" "fmt" "time" @@ -20,15 +21,14 @@ import ( "github.com/ava-labs/avalanchego/vms/platformvm/txs" "github.com/ava-labs/avalanchego/vms/secp256k1fx" "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" - - stdcontext "context" ) var ( - errNoChangeAddress = errors.New("no possible change address") - errUnknownOwnerType = errors.New("unknown owner type") - errInsufficientAuthorization = errors.New("insufficient authorization") - errInsufficientFunds = errors.New("insufficient funds") + ErrNoChangeAddress = errors.New("no possible change address") + ErrUnknownOutputType = errors.New("unknown output type") + ErrUnknownOwnerType = errors.New("unknown owner type") + ErrInsufficientAuthorization = errors.New("insufficient authorization") + ErrInsufficientFunds = errors.New("insufficient funds") _ Builder = (*builder)(nil) ) @@ -36,6 +36,10 @@ var ( // Builder provides a convenient interface for building unsigned P-chain // transactions. type Builder interface { + // Context returns the configuration of the chain that this builder uses to + // create transactions. + Context() *Context + // GetBalance calculates the amount of each asset that this builder has // control over. GetBalance( @@ -254,32 +258,39 @@ type Builder interface { ) (*txs.AddPermissionlessDelegatorTx, error) } -// BuilderBackend specifies the required information needed to build unsigned -// P-chain transactions. -type BuilderBackend interface { - Context - UTXOs(ctx stdcontext.Context, sourceChainID ids.ID) ([]*avax.UTXO, error) - GetSubnetOwner(ctx stdcontext.Context, subnetID ids.ID) (fx.Owner, error) +type Backend interface { + UTXOs(ctx context.Context, sourceChainID ids.ID) ([]*avax.UTXO, error) + GetSubnetOwner(ctx context.Context, subnetID ids.ID) (fx.Owner, error) } type builder struct { addrs set.Set[ids.ShortID] - backend BuilderBackend + context *Context + backend Backend } -// NewBuilder returns a new transaction builder. +// New returns a new transaction builder. // // - [addrs] is the set of addresses that the builder assumes can be used when // signing the transactions in the future. -// - [backend] provides the required access to the chain's context and state -// to build out the transactions. -func NewBuilder(addrs set.Set[ids.ShortID], backend BuilderBackend) Builder { +// - [context] provides the chain's configuration. +// - [backend] provides the chain's state. +func New( + addrs set.Set[ids.ShortID], + context *Context, + backend Backend, +) Builder { return &builder{ addrs: addrs, + context: context, backend: backend, } } +func (b *builder) Context() *Context { + return b.context +} + func (b *builder) GetBalance( options ...common.Option, ) (map[ids.ID]uint64, error) { @@ -300,7 +311,7 @@ func (b *builder) NewBaseTx( options ...common.Option, ) (*txs.BaseTx, error) { toBurn := map[ids.ID]uint64{ - b.backend.AVAXAssetID(): b.backend.BaseTxFee(), + b.context.AVAXAssetID: b.context.BaseTxFee, } for _, out := range outputs { assetID := out.AssetID() @@ -321,7 +332,7 @@ func (b *builder) NewBaseTx( avax.SortTransferableOutputs(outputs, txs.Codec) // sort the outputs tx := &txs.BaseTx{BaseTx: avax.BaseTx{ - NetworkID: b.backend.NetworkID(), + NetworkID: b.context.NetworkID, BlockchainID: constants.PlatformChainID, Ins: inputs, Outs: outputs, @@ -336,9 +347,9 @@ func (b *builder) NewAddValidatorTx( shares uint32, options ...common.Option, ) (*txs.AddValidatorTx, error) { - avaxAssetID := b.backend.AVAXAssetID() + avaxAssetID := b.context.AVAXAssetID toBurn := map[ids.ID]uint64{ - avaxAssetID: b.backend.AddPrimaryNetworkValidatorFee(), + avaxAssetID: b.context.AddPrimaryNetworkValidatorFee, } toStake := map[ids.ID]uint64{ avaxAssetID: vdr.Wght, @@ -352,7 +363,7 @@ func (b *builder) NewAddValidatorTx( utils.Sort(rewardsOwner.Addrs) tx := &txs.AddValidatorTx{ BaseTx: txs.BaseTx{BaseTx: avax.BaseTx{ - NetworkID: b.backend.NetworkID(), + NetworkID: b.context.NetworkID, BlockchainID: constants.PlatformChainID, Ins: inputs, Outs: baseOutputs, @@ -371,7 +382,7 @@ func (b *builder) NewAddSubnetValidatorTx( options ...common.Option, ) (*txs.AddSubnetValidatorTx, error) { toBurn := map[ids.ID]uint64{ - b.backend.AVAXAssetID(): b.backend.AddSubnetValidatorFee(), + b.context.AVAXAssetID: b.context.AddSubnetValidatorFee, } toStake := map[ids.ID]uint64{} ops := common.NewOptions(options) @@ -387,7 +398,7 @@ func (b *builder) NewAddSubnetValidatorTx( tx := &txs.AddSubnetValidatorTx{ BaseTx: txs.BaseTx{BaseTx: avax.BaseTx{ - NetworkID: b.backend.NetworkID(), + NetworkID: b.context.NetworkID, BlockchainID: constants.PlatformChainID, Ins: inputs, Outs: outputs, @@ -405,7 +416,7 @@ func (b *builder) NewRemoveSubnetValidatorTx( options ...common.Option, ) (*txs.RemoveSubnetValidatorTx, error) { toBurn := map[ids.ID]uint64{ - b.backend.AVAXAssetID(): b.backend.BaseTxFee(), + b.context.AVAXAssetID: b.context.BaseTxFee, } toStake := map[ids.ID]uint64{} ops := common.NewOptions(options) @@ -421,7 +432,7 @@ func (b *builder) NewRemoveSubnetValidatorTx( tx := &txs.RemoveSubnetValidatorTx{ BaseTx: txs.BaseTx{BaseTx: avax.BaseTx{ - NetworkID: b.backend.NetworkID(), + NetworkID: b.context.NetworkID, BlockchainID: constants.PlatformChainID, Ins: inputs, Outs: outputs, @@ -439,12 +450,12 @@ func (b *builder) NewAddDelegatorTx( rewardsOwner *secp256k1fx.OutputOwners, options ...common.Option, ) (*txs.AddDelegatorTx, error) { - avaxAssetID := b.backend.AVAXAssetID() + avaxAssetID := b.context.AVAXAssetID toBurn := map[ids.ID]uint64{ - avaxAssetID: b.backend.AddPrimaryNetworkDelegatorFee(), + avaxAssetID: b.context.AddPrimaryNetworkDelegatorFee, } toStake := map[ids.ID]uint64{ - b.backend.AVAXAssetID(): vdr.Wght, + avaxAssetID: vdr.Wght, } ops := common.NewOptions(options) inputs, baseOutputs, stakeOutputs, err := b.spend(toBurn, toStake, ops) @@ -455,7 +466,7 @@ func (b *builder) NewAddDelegatorTx( utils.Sort(rewardsOwner.Addrs) tx := &txs.AddDelegatorTx{ BaseTx: txs.BaseTx{BaseTx: avax.BaseTx{ - NetworkID: b.backend.NetworkID(), + NetworkID: b.context.NetworkID, BlockchainID: constants.PlatformChainID, Ins: inputs, Outs: baseOutputs, @@ -477,7 +488,7 @@ func (b *builder) NewCreateChainTx( options ...common.Option, ) (*txs.CreateChainTx, error) { toBurn := map[ids.ID]uint64{ - b.backend.AVAXAssetID(): b.backend.CreateBlockchainTxFee(), + b.context.AVAXAssetID: b.context.CreateBlockchainTxFee, } toStake := map[ids.ID]uint64{} ops := common.NewOptions(options) @@ -494,7 +505,7 @@ func (b *builder) NewCreateChainTx( utils.Sort(fxIDs) tx := &txs.CreateChainTx{ BaseTx: txs.BaseTx{BaseTx: avax.BaseTx{ - NetworkID: b.backend.NetworkID(), + NetworkID: b.context.NetworkID, BlockchainID: constants.PlatformChainID, Ins: inputs, Outs: outputs, @@ -515,7 +526,7 @@ func (b *builder) NewCreateSubnetTx( options ...common.Option, ) (*txs.CreateSubnetTx, error) { toBurn := map[ids.ID]uint64{ - b.backend.AVAXAssetID(): b.backend.CreateSubnetTxFee(), + b.context.AVAXAssetID: b.context.CreateSubnetTxFee, } toStake := map[ids.ID]uint64{} ops := common.NewOptions(options) @@ -527,7 +538,7 @@ func (b *builder) NewCreateSubnetTx( utils.Sort(owner.Addrs) tx := &txs.CreateSubnetTx{ BaseTx: txs.BaseTx{BaseTx: avax.BaseTx{ - NetworkID: b.backend.NetworkID(), + NetworkID: b.context.NetworkID, BlockchainID: constants.PlatformChainID, Ins: inputs, Outs: outputs, @@ -544,7 +555,7 @@ func (b *builder) NewTransferSubnetOwnershipTx( options ...common.Option, ) (*txs.TransferSubnetOwnershipTx, error) { toBurn := map[ids.ID]uint64{ - b.backend.AVAXAssetID(): b.backend.BaseTxFee(), + b.context.AVAXAssetID: b.context.BaseTxFee, } toStake := map[ids.ID]uint64{} ops := common.NewOptions(options) @@ -561,7 +572,7 @@ func (b *builder) NewTransferSubnetOwnershipTx( utils.Sort(owner.Addrs) tx := &txs.TransferSubnetOwnershipTx{ BaseTx: txs.BaseTx{BaseTx: avax.BaseTx{ - NetworkID: b.backend.NetworkID(), + NetworkID: b.context.NetworkID, BlockchainID: constants.PlatformChainID, Ins: inputs, Outs: outputs, @@ -588,8 +599,8 @@ func (b *builder) NewImportTx( var ( addrs = ops.Addresses(b.addrs) minIssuanceTime = ops.MinIssuanceTime() - avaxAssetID = b.backend.AVAXAssetID() - txFee = b.backend.BaseTxFee() + avaxAssetID = b.context.AVAXAssetID + txFee = b.context.BaseTxFee importedInputs = make([]*avax.TransferableInput, 0, len(utxos)) importedAmounts = make(map[ids.ID]uint64) @@ -630,7 +641,7 @@ func (b *builder) NewImportTx( if len(importedInputs) == 0 { return nil, fmt.Errorf( "%w: no UTXOs available to import", - errInsufficientFunds, + ErrInsufficientFunds, ) } @@ -669,7 +680,7 @@ func (b *builder) NewImportTx( avax.SortTransferableOutputs(outputs, txs.Codec) // sort imported outputs tx := &txs.ImportTx{ BaseTx: txs.BaseTx{BaseTx: avax.BaseTx{ - NetworkID: b.backend.NetworkID(), + NetworkID: b.context.NetworkID, BlockchainID: constants.PlatformChainID, Ins: inputs, Outs: outputs, @@ -687,7 +698,7 @@ func (b *builder) NewExportTx( options ...common.Option, ) (*txs.ExportTx, error) { toBurn := map[ids.ID]uint64{ - b.backend.AVAXAssetID(): b.backend.BaseTxFee(), + b.context.AVAXAssetID: b.context.BaseTxFee, } for _, out := range outputs { assetID := out.AssetID() @@ -708,7 +719,7 @@ func (b *builder) NewExportTx( avax.SortTransferableOutputs(outputs, txs.Codec) // sort exported outputs tx := &txs.ExportTx{ BaseTx: txs.BaseTx{BaseTx: avax.BaseTx{ - NetworkID: b.backend.NetworkID(), + NetworkID: b.context.NetworkID, BlockchainID: constants.PlatformChainID, Ins: inputs, Outs: changeOutputs, @@ -738,8 +749,8 @@ func (b *builder) NewTransformSubnetTx( options ...common.Option, ) (*txs.TransformSubnetTx, error) { toBurn := map[ids.ID]uint64{ - b.backend.AVAXAssetID(): b.backend.TransformSubnetTxFee(), - assetID: maxSupply - initialSupply, + b.context.AVAXAssetID: b.context.TransformSubnetTxFee, + assetID: maxSupply - initialSupply, } toStake := map[ids.ID]uint64{} ops := common.NewOptions(options) @@ -755,7 +766,7 @@ func (b *builder) NewTransformSubnetTx( tx := &txs.TransformSubnetTx{ BaseTx: txs.BaseTx{BaseTx: avax.BaseTx{ - NetworkID: b.backend.NetworkID(), + NetworkID: b.context.NetworkID, BlockchainID: constants.PlatformChainID, Ins: inputs, Outs: outputs, @@ -789,12 +800,12 @@ func (b *builder) NewAddPermissionlessValidatorTx( shares uint32, options ...common.Option, ) (*txs.AddPermissionlessValidatorTx, error) { - avaxAssetID := b.backend.AVAXAssetID() + avaxAssetID := b.context.AVAXAssetID toBurn := map[ids.ID]uint64{} if vdr.Subnet == constants.PrimaryNetworkID { - toBurn[avaxAssetID] = b.backend.AddPrimaryNetworkValidatorFee() + toBurn[avaxAssetID] = b.context.AddPrimaryNetworkValidatorFee } else { - toBurn[avaxAssetID] = b.backend.AddSubnetValidatorFee() + toBurn[avaxAssetID] = b.context.AddSubnetValidatorFee } toStake := map[ids.ID]uint64{ assetID: vdr.Wght, @@ -809,7 +820,7 @@ func (b *builder) NewAddPermissionlessValidatorTx( utils.Sort(delegationRewardsOwner.Addrs) tx := &txs.AddPermissionlessValidatorTx{ BaseTx: txs.BaseTx{BaseTx: avax.BaseTx{ - NetworkID: b.backend.NetworkID(), + NetworkID: b.context.NetworkID, BlockchainID: constants.PlatformChainID, Ins: inputs, Outs: baseOutputs, @@ -832,12 +843,12 @@ func (b *builder) NewAddPermissionlessDelegatorTx( rewardsOwner *secp256k1fx.OutputOwners, options ...common.Option, ) (*txs.AddPermissionlessDelegatorTx, error) { - avaxAssetID := b.backend.AVAXAssetID() + avaxAssetID := b.context.AVAXAssetID toBurn := map[ids.ID]uint64{} if vdr.Subnet == constants.PrimaryNetworkID { - toBurn[avaxAssetID] = b.backend.AddPrimaryNetworkDelegatorFee() + toBurn[avaxAssetID] = b.context.AddPrimaryNetworkDelegatorFee } else { - toBurn[avaxAssetID] = b.backend.AddSubnetDelegatorFee() + toBurn[avaxAssetID] = b.context.AddSubnetDelegatorFee } toStake := map[ids.ID]uint64{ assetID: vdr.Wght, @@ -851,7 +862,7 @@ func (b *builder) NewAddPermissionlessDelegatorTx( utils.Sort(rewardsOwner.Addrs) tx := &txs.AddPermissionlessDelegatorTx{ BaseTx: txs.BaseTx{BaseTx: avax.BaseTx{ - NetworkID: b.backend.NetworkID(), + NetworkID: b.context.NetworkID, BlockchainID: constants.PlatformChainID, Ins: inputs, Outs: baseOutputs, @@ -895,7 +906,7 @@ func (b *builder) getBalance( out, ok := outIntf.(*secp256k1fx.TransferOutput) if !ok { - return nil, errUnknownOutputType + return nil, ErrUnknownOutputType } _, ok = common.MatchOwners(&out.OutputOwners, addrs, minIssuanceTime) @@ -944,7 +955,7 @@ func (b *builder) spend( addr, ok := addrs.Peek() if !ok { - return nil, nil, nil, errNoChangeAddress + return nil, nil, nil, ErrNoChangeAddress } changeOwner := options.ChangeOwner(&secp256k1fx.OutputOwners{ Threshold: 1, @@ -977,7 +988,7 @@ func (b *builder) spend( out, ok := lockedOut.TransferableOut.(*secp256k1fx.TransferOutput) if !ok { - return nil, nil, nil, errUnknownOutputType + return nil, nil, nil, ErrUnknownOutputType } inputSigIndices, ok := common.MatchOwners(&out.OutputOwners, addrs, minIssuanceTime) @@ -1058,7 +1069,7 @@ func (b *builder) spend( out, ok := outIntf.(*secp256k1fx.TransferOutput) if !ok { - return nil, nil, nil, errUnknownOutputType + return nil, nil, nil, ErrUnknownOutputType } inputSigIndices, ok := common.MatchOwners(&out.OutputOwners, addrs, minIssuanceTime) @@ -1118,7 +1129,7 @@ func (b *builder) spend( if amount != 0 { return nil, nil, nil, fmt.Errorf( "%w: provided UTXOs need %d more units of asset %q to stake", - errInsufficientFunds, + ErrInsufficientFunds, amount, assetID, ) @@ -1128,7 +1139,7 @@ func (b *builder) spend( if amount != 0 { return nil, nil, nil, fmt.Errorf( "%w: provided UTXOs need %d more units of asset %q", - errInsufficientFunds, + ErrInsufficientFunds, amount, assetID, ) @@ -1152,7 +1163,7 @@ func (b *builder) authorizeSubnet(subnetID ids.ID, options *common.Options) (*se } owner, ok := ownerIntf.(*secp256k1fx.OutputOwners) if !ok { - return nil, errUnknownOwnerType + return nil, ErrUnknownOwnerType } addrs := options.Addresses(b.addrs) @@ -1160,7 +1171,7 @@ func (b *builder) authorizeSubnet(subnetID ids.ID, options *common.Options) (*se inputSigIndices, ok := common.MatchOwners(owner, addrs, minIssuanceTime) if !ok { // We can't authorize the subnet - return nil, errInsufficientAuthorization + return nil, ErrInsufficientAuthorization } return &secp256k1fx.Input{ SigIndices: inputSigIndices, @@ -1168,7 +1179,7 @@ func (b *builder) authorizeSubnet(subnetID ids.ID, options *common.Options) (*se } func (b *builder) initCtx(tx txs.UnsignedTx) error { - ctx, err := newSnowContext(b.backend) + ctx, err := NewSnowContext(b.context.NetworkID, b.context.AVAXAssetID) if err != nil { return err } diff --git a/wallet/chain/p/builder_with_options.go b/wallet/chain/p/builder/builder_with_options.go similarity index 81% rename from wallet/chain/p/builder_with_options.go rename to wallet/chain/p/builder/builder_with_options.go index a402355b9e01..d831e0c76daa 100644 --- a/wallet/chain/p/builder_with_options.go +++ b/wallet/chain/p/builder/builder_with_options.go @@ -1,7 +1,7 @@ // Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved. // See the file LICENSE for licensing terms. -package p +package builder import ( "time" @@ -17,28 +17,32 @@ import ( var _ Builder = (*builderWithOptions)(nil) type builderWithOptions struct { - Builder + builder Builder options []common.Option } -// NewBuilderWithOptions returns a new transaction builder that will use the -// given options by default. +// NewWithOptions returns a new builder that will use the given options by +// default. // // - [builder] is the builder that will be called to perform the underlying // operations. // - [options] will be provided to the builder in addition to the options // provided in the method calls. -func NewBuilderWithOptions(builder Builder, options ...common.Option) Builder { +func NewWithOptions(builder Builder, options ...common.Option) Builder { return &builderWithOptions{ - Builder: builder, + builder: builder, options: options, } } +func (b *builderWithOptions) Context() *Context { + return b.builder.Context() +} + func (b *builderWithOptions) GetBalance( options ...common.Option, ) (map[ids.ID]uint64, error) { - return b.Builder.GetBalance( + return b.builder.GetBalance( common.UnionOptions(b.options, options)..., ) } @@ -47,19 +51,29 @@ func (b *builderWithOptions) GetImportableBalance( chainID ids.ID, options ...common.Option, ) (map[ids.ID]uint64, error) { - return b.Builder.GetImportableBalance( + return b.builder.GetImportableBalance( chainID, common.UnionOptions(b.options, options)..., ) } +func (b *builderWithOptions) NewBaseTx( + outputs []*avax.TransferableOutput, + options ...common.Option, +) (*txs.BaseTx, error) { + return b.builder.NewBaseTx( + outputs, + common.UnionOptions(b.options, options)..., + ) +} + func (b *builderWithOptions) NewAddValidatorTx( vdr *txs.Validator, rewardsOwner *secp256k1fx.OutputOwners, shares uint32, options ...common.Option, ) (*txs.AddValidatorTx, error) { - return b.Builder.NewAddValidatorTx( + return b.builder.NewAddValidatorTx( vdr, rewardsOwner, shares, @@ -71,18 +85,18 @@ func (b *builderWithOptions) NewAddSubnetValidatorTx( vdr *txs.SubnetValidator, options ...common.Option, ) (*txs.AddSubnetValidatorTx, error) { - return b.Builder.NewAddSubnetValidatorTx( + return b.builder.NewAddSubnetValidatorTx( vdr, common.UnionOptions(b.options, options)..., ) } -func (b *builderWithOptions) RemoveSubnetValidatorTx( +func (b *builderWithOptions) NewRemoveSubnetValidatorTx( nodeID ids.NodeID, subnetID ids.ID, options ...common.Option, ) (*txs.RemoveSubnetValidatorTx, error) { - return b.Builder.NewRemoveSubnetValidatorTx( + return b.builder.NewRemoveSubnetValidatorTx( nodeID, subnetID, common.UnionOptions(b.options, options)..., @@ -94,7 +108,7 @@ func (b *builderWithOptions) NewAddDelegatorTx( rewardsOwner *secp256k1fx.OutputOwners, options ...common.Option, ) (*txs.AddDelegatorTx, error) { - return b.Builder.NewAddDelegatorTx( + return b.builder.NewAddDelegatorTx( vdr, rewardsOwner, common.UnionOptions(b.options, options)..., @@ -109,7 +123,7 @@ func (b *builderWithOptions) NewCreateChainTx( chainName string, options ...common.Option, ) (*txs.CreateChainTx, error) { - return b.Builder.NewCreateChainTx( + return b.builder.NewCreateChainTx( subnetID, genesis, vmID, @@ -123,7 +137,7 @@ func (b *builderWithOptions) NewCreateSubnetTx( owner *secp256k1fx.OutputOwners, options ...common.Option, ) (*txs.CreateSubnetTx, error) { - return b.Builder.NewCreateSubnetTx( + return b.builder.NewCreateSubnetTx( owner, common.UnionOptions(b.options, options)..., ) @@ -134,7 +148,7 @@ func (b *builderWithOptions) NewTransferSubnetOwnershipTx( owner *secp256k1fx.OutputOwners, options ...common.Option, ) (*txs.TransferSubnetOwnershipTx, error) { - return b.Builder.NewTransferSubnetOwnershipTx( + return b.builder.NewTransferSubnetOwnershipTx( subnetID, owner, common.UnionOptions(b.options, options)..., @@ -146,7 +160,7 @@ func (b *builderWithOptions) NewImportTx( to *secp256k1fx.OutputOwners, options ...common.Option, ) (*txs.ImportTx, error) { - return b.Builder.NewImportTx( + return b.builder.NewImportTx( sourceChainID, to, common.UnionOptions(b.options, options)..., @@ -158,7 +172,7 @@ func (b *builderWithOptions) NewExportTx( outputs []*avax.TransferableOutput, options ...common.Option, ) (*txs.ExportTx, error) { - return b.Builder.NewExportTx( + return b.builder.NewExportTx( chainID, outputs, common.UnionOptions(b.options, options)..., @@ -182,7 +196,7 @@ func (b *builderWithOptions) NewTransformSubnetTx( uptimeRequirement uint32, options ...common.Option, ) (*txs.TransformSubnetTx, error) { - return b.Builder.NewTransformSubnetTx( + return b.builder.NewTransformSubnetTx( subnetID, assetID, initialSupply, @@ -210,7 +224,7 @@ func (b *builderWithOptions) NewAddPermissionlessValidatorTx( shares uint32, options ...common.Option, ) (*txs.AddPermissionlessValidatorTx, error) { - return b.Builder.NewAddPermissionlessValidatorTx( + return b.builder.NewAddPermissionlessValidatorTx( vdr, signer, assetID, @@ -227,7 +241,7 @@ func (b *builderWithOptions) NewAddPermissionlessDelegatorTx( rewardsOwner *secp256k1fx.OutputOwners, options ...common.Option, ) (*txs.AddPermissionlessDelegatorTx, error) { - return b.Builder.NewAddPermissionlessDelegatorTx( + return b.builder.NewAddPermissionlessDelegatorTx( vdr, assetID, rewardsOwner, diff --git a/wallet/chain/p/builder/context.go b/wallet/chain/p/builder/context.go new file mode 100644 index 000000000000..f0da23fdc5f9 --- /dev/null +++ b/wallet/chain/p/builder/context.go @@ -0,0 +1,82 @@ +// Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. + +package builder + +import ( + "context" + + "github.com/ava-labs/avalanchego/api/info" + "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/snow" + "github.com/ava-labs/avalanchego/utils/constants" + "github.com/ava-labs/avalanchego/utils/logging" + "github.com/ava-labs/avalanchego/vms/avm" +) + +const Alias = "P" + +type Context struct { + NetworkID uint32 + AVAXAssetID ids.ID + BaseTxFee uint64 + CreateSubnetTxFee uint64 + TransformSubnetTxFee uint64 + CreateBlockchainTxFee uint64 + AddPrimaryNetworkValidatorFee uint64 + AddPrimaryNetworkDelegatorFee uint64 + AddSubnetValidatorFee uint64 + AddSubnetDelegatorFee uint64 +} + +func NewContextFromURI(ctx context.Context, uri string) (*Context, error) { + infoClient := info.NewClient(uri) + xChainClient := avm.NewClient(uri, "X") + return NewContextFromClients(ctx, infoClient, xChainClient) +} + +func NewContextFromClients( + ctx context.Context, + infoClient info.Client, + xChainClient avm.Client, +) (*Context, error) { + networkID, err := infoClient.GetNetworkID(ctx) + if err != nil { + return nil, err + } + + asset, err := xChainClient.GetAssetDescription(ctx, "AVAX") + if err != nil { + return nil, err + } + + txFees, err := infoClient.GetTxFee(ctx) + if err != nil { + return nil, err + } + + return &Context{ + NetworkID: networkID, + AVAXAssetID: asset.AssetID, + BaseTxFee: uint64(txFees.TxFee), + CreateSubnetTxFee: uint64(txFees.CreateSubnetTxFee), + TransformSubnetTxFee: uint64(txFees.TransformSubnetTxFee), + CreateBlockchainTxFee: uint64(txFees.CreateBlockchainTxFee), + AddPrimaryNetworkValidatorFee: uint64(txFees.AddPrimaryNetworkValidatorFee), + AddPrimaryNetworkDelegatorFee: uint64(txFees.AddPrimaryNetworkDelegatorFee), + AddSubnetValidatorFee: uint64(txFees.AddSubnetValidatorFee), + AddSubnetDelegatorFee: uint64(txFees.AddSubnetDelegatorFee), + }, nil +} + +func NewSnowContext(networkID uint32, avaxAssetID ids.ID) (*snow.Context, error) { + lookup := ids.NewAliaser() + return &snow.Context{ + NetworkID: networkID, + SubnetID: constants.PrimaryNetworkID, + ChainID: constants.PlatformChainID, + AVAXAssetID: avaxAssetID, + Log: logging.NoLog{}, + BCLookup: lookup, + }, lookup.Alias(constants.PlatformChainID, Alias) +} diff --git a/wallet/chain/p/builder_test.go b/wallet/chain/p/builder_test.go index 409c524ba938..9f73b9e399b9 100644 --- a/wallet/chain/p/builder_test.go +++ b/wallet/chain/p/builder_test.go @@ -21,6 +21,7 @@ import ( "github.com/ava-labs/avalanchego/vms/platformvm/stakeable" "github.com/ava-labs/avalanchego/vms/platformvm/txs" "github.com/ava-labs/avalanchego/vms/secp256k1fx" + "github.com/ava-labs/avalanchego/wallet/chain/p/builder" "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" ) @@ -32,22 +33,22 @@ var ( avaxAssetID = ids.Empty.Prefix(1789) subnetAssetID = ids.Empty.Prefix(2024) - testCtx = NewContext( - constants.UnitTestID, - avaxAssetID, - units.MicroAvax, // BaseTxFee - 19*units.MicroAvax, // CreateSubnetTxFee - 789*units.MicroAvax, // TransformSubnetTxFee - 1234*units.MicroAvax, // CreateBlockchainTxFee - 19*units.MilliAvax, // AddPrimaryNetworkValidatorFee - 765*units.MilliAvax, // AddPrimaryNetworkDelegatorFee - 1010*units.MilliAvax, // AddSubnetValidatorFee - 9*units.Avax, // AddSubnetDelegatorFee - ) + testContext = &builder.Context{ + NetworkID: constants.UnitTestID, + AVAXAssetID: avaxAssetID, + BaseTxFee: units.MicroAvax, + CreateSubnetTxFee: 19 * units.MicroAvax, + TransformSubnetTxFee: 789 * units.MicroAvax, + CreateBlockchainTxFee: 1234 * units.MicroAvax, + AddPrimaryNetworkValidatorFee: 19 * units.MilliAvax, + AddPrimaryNetworkDelegatorFee: 765 * units.MilliAvax, + AddSubnetValidatorFee: 1010 * units.MilliAvax, + AddSubnetDelegatorFee: 9 * units.Avax, + } ) -// These tests create and sign a tx, then verify that utxos included -// in the tx are exactly necessary to pay fees for it +// These tests create a tx, then verify that utxos included in the tx are +// exactly necessary to pay fees for it. func TestBaseTx(t *testing.T) { var ( @@ -59,11 +60,11 @@ func TestBaseTx(t *testing.T) { chainUTXOs = common.NewDeterministicChainUTXOs(require, map[ids.ID][]*avax.UTXO{ constants.PlatformChainID: utxos, }) - backend = NewBackend(testCtx, chainUTXOs, nil) + backend = NewBackend(testContext, chainUTXOs, nil) // builder utxoAddr = utxosKey.Address() - builder = NewBuilder(set.Of(utxoAddr), backend) + builder = builder.New(set.Of(utxoAddr), testContext, backend) // data to build the transaction outputsToMove = []*avax.TransferableOutput{{ @@ -87,7 +88,7 @@ func TestBaseTx(t *testing.T) { require.Len(ins, 2) require.Len(outs, 2) - expectedConsumed := testCtx.BaseTxFee() + outputsToMove[0].Out.Amount() + expectedConsumed := testContext.BaseTxFee + outputsToMove[0].Out.Amount() consumed := ins[0].In.Amount() + ins[1].In.Amount() - outs[0].Out.Amount() require.Equal(expectedConsumed, consumed) require.Equal(outputsToMove[0], outs[1]) @@ -119,11 +120,11 @@ func TestAddSubnetValidatorTx(t *testing.T) { }, } - backend = NewBackend(testCtx, chainUTXOs, subnets) + backend = NewBackend(testContext, chainUTXOs, subnets) // builder utxoAddr = utxosKey.Address() - builder = NewBuilder(set.Of(utxoAddr, subnetAuthAddr), backend) + builder = builder.New(set.Of(utxoAddr, subnetAuthAddr), testContext, backend) // data to build the transaction subnetValidator = &txs.SubnetValidator{ @@ -145,7 +146,7 @@ func TestAddSubnetValidatorTx(t *testing.T) { require.Len(ins, 2) require.Len(outs, 1) - expectedConsumed := testCtx.AddSubnetValidatorFee() + expectedConsumed := testContext.AddSubnetValidatorFee consumed := ins[0].In.Amount() + ins[1].In.Amount() - outs[0].Out.Amount() require.Equal(expectedConsumed, consumed) } @@ -176,11 +177,11 @@ func TestRemoveSubnetValidatorTx(t *testing.T) { }, } - backend = NewBackend(testCtx, chainUTXOs, subnets) + backend = NewBackend(testContext, chainUTXOs, subnets) // builder utxoAddr = utxosKey.Address() - builder = NewBuilder(set.Of(utxoAddr, subnetAuthAddr), backend) + builder = builder.New(set.Of(utxoAddr, subnetAuthAddr), testContext, backend) ) // build the transaction @@ -196,7 +197,7 @@ func TestRemoveSubnetValidatorTx(t *testing.T) { require.Len(ins, 1) require.Len(outs, 1) - expectedConsumed := testCtx.BaseTxFee() + expectedConsumed := testContext.BaseTxFee consumed := ins[0].In.Amount() - outs[0].Out.Amount() require.Equal(expectedConsumed, consumed) } @@ -227,10 +228,10 @@ func TestCreateChainTx(t *testing.T) { }, } - backend = NewBackend(testCtx, chainUTXOs, subnets) + backend = NewBackend(testContext, chainUTXOs, subnets) utxoAddr = utxosKey.Address() - builder = NewBuilder(set.Of(utxoAddr, subnetAuthAddr), backend) + builder = builder.New(set.Of(utxoAddr, subnetAuthAddr), testContext, backend) // data to build the transaction genesisBytes = []byte{'a', 'b', 'c'} @@ -255,7 +256,7 @@ func TestCreateChainTx(t *testing.T) { require.Len(ins, 1) require.Len(outs, 1) - expectedConsumed := testCtx.CreateBlockchainTxFee() + expectedConsumed := testContext.CreateBlockchainTxFee consumed := ins[0].In.Amount() - outs[0].Out.Amount() require.Equal(expectedConsumed, consumed) } @@ -286,11 +287,11 @@ func TestCreateSubnetTx(t *testing.T) { }, } - backend = NewBackend(testCtx, chainUTXOs, subnets) + backend = NewBackend(testContext, chainUTXOs, subnets) // builder utxoAddr = utxosKey.Address() - builder = NewBuilder(set.Of(utxoAddr, subnetAuthAddr), backend) + builder = builder.New(set.Of(utxoAddr, subnetAuthAddr), testContext, backend) ) // build the transaction @@ -303,7 +304,7 @@ func TestCreateSubnetTx(t *testing.T) { require.Len(ins, 1) require.Len(outs, 1) - expectedConsumed := testCtx.CreateSubnetTxFee() + expectedConsumed := testContext.CreateSubnetTxFee consumed := ins[0].In.Amount() - outs[0].Out.Amount() require.Equal(expectedConsumed, consumed) } @@ -334,11 +335,11 @@ func TestTransferSubnetOwnershipTx(t *testing.T) { }, } - backend = NewBackend(testCtx, chainUTXOs, subnets) + backend = NewBackend(testContext, chainUTXOs, subnets) // builder utxoAddr = utxosKey.Address() - builder = NewBuilder(set.Of(utxoAddr, subnetAuthAddr), backend) + builder = builder.New(set.Of(utxoAddr, subnetAuthAddr), testContext, backend) ) // build the transaction @@ -354,7 +355,7 @@ func TestTransferSubnetOwnershipTx(t *testing.T) { require.Len(ins, 1) require.Len(outs, 1) - expectedConsumed := testCtx.BaseTxFee() + expectedConsumed := testContext.BaseTxFee consumed := ins[0].In.Amount() - outs[0].Out.Amount() require.Equal(expectedConsumed, consumed) } @@ -373,11 +374,11 @@ func TestImportTx(t *testing.T) { sourceChainID: importedUTXOs, }) - backend = NewBackend(testCtx, chainUTXOs, nil) + backend = NewBackend(testContext, chainUTXOs, nil) // builder utxoAddr = utxosKey.Address() - builder = NewBuilder(set.Of(utxoAddr), backend) + builder = builder.New(set.Of(utxoAddr), testContext, backend) // data to build the transaction importKey = testKeys[0] @@ -404,7 +405,7 @@ func TestImportTx(t *testing.T) { require.Len(importedIns, 1) require.Len(outs, 1) - expectedConsumed := testCtx.BaseTxFee() + expectedConsumed := testContext.BaseTxFee consumed := importedIns[0].In.Amount() - outs[0].Out.Amount() require.Equal(expectedConsumed, consumed) } @@ -419,11 +420,11 @@ func TestExportTx(t *testing.T) { chainUTXOs = common.NewDeterministicChainUTXOs(require, map[ids.ID][]*avax.UTXO{ constants.PlatformChainID: utxos, }) - backend = NewBackend(testCtx, chainUTXOs, nil) + backend = NewBackend(testContext, chainUTXOs, nil) // builder utxoAddr = utxosKey.Address() - builder = NewBuilder(set.Of(utxoAddr), backend) + builder = builder.New(set.Of(utxoAddr), testContext, backend) // data to build the transaction subnetID = ids.GenerateTestID() @@ -452,7 +453,7 @@ func TestExportTx(t *testing.T) { require.Len(ins, 2) require.Len(outs, 1) - expectedConsumed := testCtx.BaseTxFee() + exportedOutputs[0].Out.Amount() + expectedConsumed := testContext.BaseTxFee + exportedOutputs[0].Out.Amount() consumed := ins[0].In.Amount() + ins[1].In.Amount() - outs[0].Out.Amount() require.Equal(expectedConsumed, consumed) require.Equal(utx.ExportedOutputs, exportedOutputs) @@ -484,11 +485,11 @@ func TestTransformSubnetTx(t *testing.T) { }, } - backend = NewBackend(testCtx, chainUTXOs, subnets) + backend = NewBackend(testContext, chainUTXOs, subnets) // builder utxoAddr = utxosKey.Address() - builder = NewBuilder(set.Of(utxoAddr, subnetAuthAddr), backend) + builder = builder.New(set.Of(utxoAddr, subnetAuthAddr), testContext, backend) // data to build the transaction initialSupply = 40 * units.MegaAvax @@ -523,7 +524,7 @@ func TestTransformSubnetTx(t *testing.T) { expectedConsumedSubnetAsset := maxSupply - initialSupply consumedSubnetAsset := ins[0].In.Amount() - outs[1].Out.Amount() require.Equal(expectedConsumedSubnetAsset, consumedSubnetAsset) - expectedConsumed := testCtx.TransformSubnetTxFee() + expectedConsumed := testContext.TransformSubnetTxFee consumed := ins[1].In.Amount() - outs[0].Out.Amount() require.Equal(expectedConsumed, consumed) } @@ -538,13 +539,13 @@ func TestAddPermissionlessValidatorTx(t *testing.T) { chainUTXOs = common.NewDeterministicChainUTXOs(require, map[ids.ID][]*avax.UTXO{ constants.PlatformChainID: utxos, }) - backend = NewBackend(testCtx, chainUTXOs, nil) + backend = NewBackend(testContext, chainUTXOs, nil) // builder utxoAddr = utxosKey.Address() rewardKey = testKeys[0] rewardAddr = rewardKey.Address() - builder = NewBuilder(set.Of(utxoAddr, rewardAddr), backend) + builder = builder.New(set.Of(utxoAddr, rewardAddr), testContext, backend) // data to build the transaction validationRewardsOwner = &secp256k1fx.OutputOwners{ @@ -593,7 +594,7 @@ func TestAddPermissionlessValidatorTx(t *testing.T) { expectedConsumedSubnetAsset := utx.Validator.Weight() consumedSubnetAsset := staked[0].Out.Amount() + staked[1].Out.Amount() require.Equal(expectedConsumedSubnetAsset, consumedSubnetAsset) - expectedConsumed := testCtx.AddPrimaryNetworkValidatorFee() + expectedConsumed := testContext.AddPrimaryNetworkValidatorFee consumed := ins[1].In.Amount() + ins[3].In.Amount() - outs[0].Out.Amount() require.Equal(expectedConsumed, consumed) } @@ -608,13 +609,13 @@ func TestAddPermissionlessDelegatorTx(t *testing.T) { chainUTXOs = common.NewDeterministicChainUTXOs(require, map[ids.ID][]*avax.UTXO{ constants.PlatformChainID: utxos, }) - backend = NewBackend(testCtx, chainUTXOs, nil) + backend = NewBackend(testContext, chainUTXOs, nil) // builder utxoAddr = utxosKey.Address() rewardKey = testKeys[0] rewardAddr = rewardKey.Address() - builder = NewBuilder(set.Of(utxoAddr, rewardAddr), backend) + builder = builder.New(set.Of(utxoAddr, rewardAddr), testContext, backend) // data to build the transaction rewardsOwner = &secp256k1fx.OutputOwners{ @@ -651,7 +652,7 @@ func TestAddPermissionlessDelegatorTx(t *testing.T) { expectedConsumedSubnetAsset := utx.Validator.Weight() consumedSubnetAsset := staked[0].Out.Amount() + staked[1].Out.Amount() require.Equal(expectedConsumedSubnetAsset, consumedSubnetAsset) - expectedConsumed := testCtx.AddPrimaryNetworkDelegatorFee() + expectedConsumed := testContext.AddPrimaryNetworkDelegatorFee consumed := ins[1].In.Amount() + ins[3].In.Amount() - outs[0].Out.Amount() require.Equal(expectedConsumed, consumed) } diff --git a/wallet/chain/p/context.go b/wallet/chain/p/context.go deleted file mode 100644 index 2511a19a9dbf..000000000000 --- a/wallet/chain/p/context.go +++ /dev/null @@ -1,163 +0,0 @@ -// Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved. -// See the file LICENSE for licensing terms. - -package p - -import ( - "github.com/ava-labs/avalanchego/api/info" - "github.com/ava-labs/avalanchego/ids" - "github.com/ava-labs/avalanchego/snow" - "github.com/ava-labs/avalanchego/utils/constants" - "github.com/ava-labs/avalanchego/utils/logging" - "github.com/ava-labs/avalanchego/vms/avm" - - stdcontext "context" -) - -const Alias = "P" - -var _ Context = (*context)(nil) - -type Context interface { - NetworkID() uint32 - AVAXAssetID() ids.ID - BaseTxFee() uint64 - CreateSubnetTxFee() uint64 - TransformSubnetTxFee() uint64 - CreateBlockchainTxFee() uint64 - AddPrimaryNetworkValidatorFee() uint64 - AddPrimaryNetworkDelegatorFee() uint64 - AddSubnetValidatorFee() uint64 - AddSubnetDelegatorFee() uint64 -} - -type context struct { - networkID uint32 - avaxAssetID ids.ID - baseTxFee uint64 - createSubnetTxFee uint64 - transformSubnetTxFee uint64 - createBlockchainTxFee uint64 - addPrimaryNetworkValidatorFee uint64 - addPrimaryNetworkDelegatorFee uint64 - addSubnetValidatorFee uint64 - addSubnetDelegatorFee uint64 -} - -func NewContextFromURI(ctx stdcontext.Context, uri string) (Context, error) { - infoClient := info.NewClient(uri) - xChainClient := avm.NewClient(uri, "X") - return NewContextFromClients(ctx, infoClient, xChainClient) -} - -func NewContextFromClients( - ctx stdcontext.Context, - infoClient info.Client, - xChainClient avm.Client, -) (Context, error) { - networkID, err := infoClient.GetNetworkID(ctx) - if err != nil { - return nil, err - } - - asset, err := xChainClient.GetAssetDescription(ctx, "AVAX") - if err != nil { - return nil, err - } - - txFees, err := infoClient.GetTxFee(ctx) - if err != nil { - return nil, err - } - - return NewContext( - networkID, - asset.AssetID, - uint64(txFees.TxFee), - uint64(txFees.CreateSubnetTxFee), - uint64(txFees.TransformSubnetTxFee), - uint64(txFees.CreateBlockchainTxFee), - uint64(txFees.AddPrimaryNetworkValidatorFee), - uint64(txFees.AddPrimaryNetworkDelegatorFee), - uint64(txFees.AddSubnetValidatorFee), - uint64(txFees.AddSubnetDelegatorFee), - ), nil -} - -func NewContext( - networkID uint32, - avaxAssetID ids.ID, - baseTxFee uint64, - createSubnetTxFee uint64, - transformSubnetTxFee uint64, - createBlockchainTxFee uint64, - addPrimaryNetworkValidatorFee uint64, - addPrimaryNetworkDelegatorFee uint64, - addSubnetValidatorFee uint64, - addSubnetDelegatorFee uint64, -) Context { - return &context{ - networkID: networkID, - avaxAssetID: avaxAssetID, - baseTxFee: baseTxFee, - createSubnetTxFee: createSubnetTxFee, - transformSubnetTxFee: transformSubnetTxFee, - createBlockchainTxFee: createBlockchainTxFee, - addPrimaryNetworkValidatorFee: addPrimaryNetworkValidatorFee, - addPrimaryNetworkDelegatorFee: addPrimaryNetworkDelegatorFee, - addSubnetValidatorFee: addSubnetValidatorFee, - addSubnetDelegatorFee: addSubnetDelegatorFee, - } -} - -func (c *context) NetworkID() uint32 { - return c.networkID -} - -func (c *context) AVAXAssetID() ids.ID { - return c.avaxAssetID -} - -func (c *context) BaseTxFee() uint64 { - return c.baseTxFee -} - -func (c *context) CreateSubnetTxFee() uint64 { - return c.createSubnetTxFee -} - -func (c *context) TransformSubnetTxFee() uint64 { - return c.transformSubnetTxFee -} - -func (c *context) CreateBlockchainTxFee() uint64 { - return c.createBlockchainTxFee -} - -func (c *context) AddPrimaryNetworkValidatorFee() uint64 { - return c.addPrimaryNetworkValidatorFee -} - -func (c *context) AddPrimaryNetworkDelegatorFee() uint64 { - return c.addPrimaryNetworkDelegatorFee -} - -func (c *context) AddSubnetValidatorFee() uint64 { - return c.addSubnetValidatorFee -} - -func (c *context) AddSubnetDelegatorFee() uint64 { - return c.addSubnetDelegatorFee -} - -func newSnowContext(c Context) (*snow.Context, error) { - lookup := ids.NewAliaser() - return &snow.Context{ - NetworkID: c.NetworkID(), - SubnetID: constants.PrimaryNetworkID, - ChainID: constants.PlatformChainID, - AVAXAssetID: c.AVAXAssetID(), - Log: logging.NoLog{}, - BCLookup: lookup, - }, lookup.Alias(constants.PlatformChainID, Alias) -} diff --git a/wallet/chain/p/signer.go b/wallet/chain/p/signer/signer.go similarity index 89% rename from wallet/chain/p/signer.go rename to wallet/chain/p/signer/signer.go index bedbbdbf562a..08b3a9d9963b 100644 --- a/wallet/chain/p/signer.go +++ b/wallet/chain/p/signer/signer.go @@ -1,7 +1,7 @@ // Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved. // See the file LICENSE for licensing terms. -package p +package signer import ( "github.com/ava-labs/avalanchego/ids" @@ -27,17 +27,17 @@ type Signer interface { Sign(ctx stdcontext.Context, tx *txs.Tx) error } -type SignerBackend interface { +type Backend interface { GetUTXO(ctx stdcontext.Context, chainID, utxoID ids.ID) (*avax.UTXO, error) GetSubnetOwner(ctx stdcontext.Context, subnetID ids.ID) (fx.Owner, error) } type txSigner struct { kc keychain.Keychain - backend SignerBackend + backend Backend } -func NewSigner(kc keychain.Keychain, backend SignerBackend) Signer { +func New(kc keychain.Keychain, backend Backend) Signer { return &txSigner{ kc: kc, backend: backend, @@ -45,7 +45,7 @@ func NewSigner(kc keychain.Keychain, backend SignerBackend) Signer { } func (s *txSigner) Sign(ctx stdcontext.Context, tx *txs.Tx) error { - return tx.Unsigned.Visit(&signerVisitor{ + return tx.Unsigned.Visit(&visitor{ kc: s.kc, backend: s.backend, ctx: ctx, diff --git a/wallet/chain/p/signer_visitor.go b/wallet/chain/p/signer/visitor.go similarity index 77% rename from wallet/chain/p/signer_visitor.go rename to wallet/chain/p/signer/visitor.go index 7c9dd4cb95ca..5dd4abe2b7d2 100644 --- a/wallet/chain/p/signer_visitor.go +++ b/wallet/chain/p/signer/visitor.go @@ -1,9 +1,10 @@ // Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved. // See the file LICENSE for licensing terms. -package p +package signer import ( + "context" "errors" "fmt" @@ -18,40 +19,39 @@ import ( "github.com/ava-labs/avalanchego/vms/platformvm/stakeable" "github.com/ava-labs/avalanchego/vms/platformvm/txs" "github.com/ava-labs/avalanchego/vms/secp256k1fx" - - stdcontext "context" ) var ( - _ txs.Visitor = (*signerVisitor)(nil) + _ txs.Visitor = (*visitor)(nil) - errUnsupportedTxType = errors.New("unsupported tx type") - errUnknownInputType = errors.New("unknown input type") - errUnknownCredentialType = errors.New("unknown credential type") - errUnknownOutputType = errors.New("unknown output type") - errUnknownSubnetAuthType = errors.New("unknown subnet auth type") - errInvalidUTXOSigIndex = errors.New("invalid UTXO signature index") + ErrUnsupportedTxType = errors.New("unsupported tx type") + ErrUnknownInputType = errors.New("unknown input type") + ErrUnknownOutputType = errors.New("unknown output type") + ErrInvalidUTXOSigIndex = errors.New("invalid UTXO signature index") + ErrUnknownSubnetAuthType = errors.New("unknown subnet auth type") + ErrUnknownOwnerType = errors.New("unknown owner type") + ErrUnknownCredentialType = errors.New("unknown credential type") emptySig [secp256k1.SignatureLen]byte ) -// signerVisitor handles signing transactions for the signer -type signerVisitor struct { +// visitor handles signing transactions for the signer +type visitor struct { kc keychain.Keychain - backend SignerBackend - ctx stdcontext.Context + backend Backend + ctx context.Context tx *txs.Tx } -func (*signerVisitor) AdvanceTimeTx(*txs.AdvanceTimeTx) error { - return errUnsupportedTxType +func (*visitor) AdvanceTimeTx(*txs.AdvanceTimeTx) error { + return ErrUnsupportedTxType } -func (*signerVisitor) RewardValidatorTx(*txs.RewardValidatorTx) error { - return errUnsupportedTxType +func (*visitor) RewardValidatorTx(*txs.RewardValidatorTx) error { + return ErrUnsupportedTxType } -func (s *signerVisitor) BaseTx(tx *txs.BaseTx) error { +func (s *visitor) BaseTx(tx *txs.BaseTx) error { txSigners, err := s.getSigners(constants.PlatformChainID, tx.Ins) if err != nil { return err @@ -59,7 +59,7 @@ func (s *signerVisitor) BaseTx(tx *txs.BaseTx) error { return sign(s.tx, false, txSigners) } -func (s *signerVisitor) AddValidatorTx(tx *txs.AddValidatorTx) error { +func (s *visitor) AddValidatorTx(tx *txs.AddValidatorTx) error { txSigners, err := s.getSigners(constants.PlatformChainID, tx.Ins) if err != nil { return err @@ -67,7 +67,7 @@ func (s *signerVisitor) AddValidatorTx(tx *txs.AddValidatorTx) error { return sign(s.tx, false, txSigners) } -func (s *signerVisitor) AddSubnetValidatorTx(tx *txs.AddSubnetValidatorTx) error { +func (s *visitor) AddSubnetValidatorTx(tx *txs.AddSubnetValidatorTx) error { txSigners, err := s.getSigners(constants.PlatformChainID, tx.Ins) if err != nil { return err @@ -80,7 +80,7 @@ func (s *signerVisitor) AddSubnetValidatorTx(tx *txs.AddSubnetValidatorTx) error return sign(s.tx, false, txSigners) } -func (s *signerVisitor) AddDelegatorTx(tx *txs.AddDelegatorTx) error { +func (s *visitor) AddDelegatorTx(tx *txs.AddDelegatorTx) error { txSigners, err := s.getSigners(constants.PlatformChainID, tx.Ins) if err != nil { return err @@ -88,7 +88,7 @@ func (s *signerVisitor) AddDelegatorTx(tx *txs.AddDelegatorTx) error { return sign(s.tx, false, txSigners) } -func (s *signerVisitor) CreateChainTx(tx *txs.CreateChainTx) error { +func (s *visitor) CreateChainTx(tx *txs.CreateChainTx) error { txSigners, err := s.getSigners(constants.PlatformChainID, tx.Ins) if err != nil { return err @@ -101,7 +101,7 @@ func (s *signerVisitor) CreateChainTx(tx *txs.CreateChainTx) error { return sign(s.tx, false, txSigners) } -func (s *signerVisitor) CreateSubnetTx(tx *txs.CreateSubnetTx) error { +func (s *visitor) CreateSubnetTx(tx *txs.CreateSubnetTx) error { txSigners, err := s.getSigners(constants.PlatformChainID, tx.Ins) if err != nil { return err @@ -109,7 +109,7 @@ func (s *signerVisitor) CreateSubnetTx(tx *txs.CreateSubnetTx) error { return sign(s.tx, false, txSigners) } -func (s *signerVisitor) ImportTx(tx *txs.ImportTx) error { +func (s *visitor) ImportTx(tx *txs.ImportTx) error { txSigners, err := s.getSigners(constants.PlatformChainID, tx.Ins) if err != nil { return err @@ -122,7 +122,7 @@ func (s *signerVisitor) ImportTx(tx *txs.ImportTx) error { return sign(s.tx, false, txSigners) } -func (s *signerVisitor) ExportTx(tx *txs.ExportTx) error { +func (s *visitor) ExportTx(tx *txs.ExportTx) error { txSigners, err := s.getSigners(constants.PlatformChainID, tx.Ins) if err != nil { return err @@ -130,7 +130,7 @@ func (s *signerVisitor) ExportTx(tx *txs.ExportTx) error { return sign(s.tx, false, txSigners) } -func (s *signerVisitor) RemoveSubnetValidatorTx(tx *txs.RemoveSubnetValidatorTx) error { +func (s *visitor) RemoveSubnetValidatorTx(tx *txs.RemoveSubnetValidatorTx) error { txSigners, err := s.getSigners(constants.PlatformChainID, tx.Ins) if err != nil { return err @@ -143,7 +143,7 @@ func (s *signerVisitor) RemoveSubnetValidatorTx(tx *txs.RemoveSubnetValidatorTx) return sign(s.tx, true, txSigners) } -func (s *signerVisitor) TransferSubnetOwnershipTx(tx *txs.TransferSubnetOwnershipTx) error { +func (s *visitor) TransferSubnetOwnershipTx(tx *txs.TransferSubnetOwnershipTx) error { txSigners, err := s.getSigners(constants.PlatformChainID, tx.Ins) if err != nil { return err @@ -156,7 +156,7 @@ func (s *signerVisitor) TransferSubnetOwnershipTx(tx *txs.TransferSubnetOwnershi return sign(s.tx, true, txSigners) } -func (s *signerVisitor) TransformSubnetTx(tx *txs.TransformSubnetTx) error { +func (s *visitor) TransformSubnetTx(tx *txs.TransformSubnetTx) error { txSigners, err := s.getSigners(constants.PlatformChainID, tx.Ins) if err != nil { return err @@ -169,7 +169,7 @@ func (s *signerVisitor) TransformSubnetTx(tx *txs.TransformSubnetTx) error { return sign(s.tx, true, txSigners) } -func (s *signerVisitor) AddPermissionlessValidatorTx(tx *txs.AddPermissionlessValidatorTx) error { +func (s *visitor) AddPermissionlessValidatorTx(tx *txs.AddPermissionlessValidatorTx) error { txSigners, err := s.getSigners(constants.PlatformChainID, tx.Ins) if err != nil { return err @@ -177,7 +177,7 @@ func (s *signerVisitor) AddPermissionlessValidatorTx(tx *txs.AddPermissionlessVa return sign(s.tx, true, txSigners) } -func (s *signerVisitor) AddPermissionlessDelegatorTx(tx *txs.AddPermissionlessDelegatorTx) error { +func (s *visitor) AddPermissionlessDelegatorTx(tx *txs.AddPermissionlessDelegatorTx) error { txSigners, err := s.getSigners(constants.PlatformChainID, tx.Ins) if err != nil { return err @@ -185,7 +185,7 @@ func (s *signerVisitor) AddPermissionlessDelegatorTx(tx *txs.AddPermissionlessDe return sign(s.tx, true, txSigners) } -func (s *signerVisitor) getSigners(sourceChainID ids.ID, ins []*avax.TransferableInput) ([][]keychain.Signer, error) { +func (s *visitor) getSigners(sourceChainID ids.ID, ins []*avax.TransferableInput) ([][]keychain.Signer, error) { txSigners := make([][]keychain.Signer, len(ins)) for credIndex, transferInput := range ins { inIntf := transferInput.In @@ -195,7 +195,7 @@ func (s *signerVisitor) getSigners(sourceChainID ids.ID, ins []*avax.Transferabl input, ok := inIntf.(*secp256k1fx.TransferInput) if !ok { - return nil, errUnknownInputType + return nil, ErrUnknownInputType } inputSigners := make([]keychain.Signer, len(input.SigIndices)) @@ -219,12 +219,12 @@ func (s *signerVisitor) getSigners(sourceChainID ids.ID, ins []*avax.Transferabl out, ok := outIntf.(*secp256k1fx.TransferOutput) if !ok { - return nil, errUnknownOutputType + return nil, ErrUnknownOutputType } for sigIndex, addrIndex := range input.SigIndices { if addrIndex >= uint32(len(out.Addrs)) { - return nil, errInvalidUTXOSigIndex + return nil, ErrInvalidUTXOSigIndex } addr := out.Addrs[addrIndex] @@ -240,10 +240,10 @@ func (s *signerVisitor) getSigners(sourceChainID ids.ID, ins []*avax.Transferabl return txSigners, nil } -func (s *signerVisitor) getSubnetSigners(subnetID ids.ID, subnetAuth verify.Verifiable) ([]keychain.Signer, error) { +func (s *visitor) getSubnetSigners(subnetID ids.ID, subnetAuth verify.Verifiable) ([]keychain.Signer, error) { subnetInput, ok := subnetAuth.(*secp256k1fx.Input) if !ok { - return nil, errUnknownSubnetAuthType + return nil, ErrUnknownSubnetAuthType } ownerIntf, err := s.backend.GetSubnetOwner(s.ctx, subnetID) @@ -256,13 +256,13 @@ func (s *signerVisitor) getSubnetSigners(subnetID ids.ID, subnetAuth verify.Veri } owner, ok := ownerIntf.(*secp256k1fx.OutputOwners) if !ok { - return nil, errUnknownOwnerType + return nil, ErrUnknownOwnerType } authSigners := make([]keychain.Signer, len(subnetInput.SigIndices)) for sigIndex, addrIndex := range subnetInput.SigIndices { if addrIndex >= uint32(len(owner.Addrs)) { - return nil, errInvalidUTXOSigIndex + return nil, ErrInvalidUTXOSigIndex } addr := owner.Addrs[addrIndex] @@ -299,7 +299,7 @@ func sign(tx *txs.Tx, signHash bool, txSigners [][]keychain.Signer) error { cred, ok := credIntf.(*secp256k1fx.Credential) if !ok { - return errUnknownCredentialType + return ErrUnknownCredentialType } if expectedLen := len(inputSigners); expectedLen != len(cred.Sigs) { cred.Sigs = make([][secp256k1.SignatureLen]byte, expectedLen) diff --git a/wallet/chain/p/wallet.go b/wallet/chain/p/wallet.go index 61655e0d157f..b96e6f3723e9 100644 --- a/wallet/chain/p/wallet.go +++ b/wallet/chain/p/wallet.go @@ -11,27 +11,28 @@ import ( "github.com/ava-labs/avalanchego/ids" "github.com/ava-labs/avalanchego/vms/components/avax" "github.com/ava-labs/avalanchego/vms/platformvm" - "github.com/ava-labs/avalanchego/vms/platformvm/signer" "github.com/ava-labs/avalanchego/vms/platformvm/status" "github.com/ava-labs/avalanchego/vms/platformvm/txs" "github.com/ava-labs/avalanchego/vms/secp256k1fx" + "github.com/ava-labs/avalanchego/wallet/chain/p/builder" "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" + + vmsigner "github.com/ava-labs/avalanchego/vms/platformvm/signer" + walletsigner "github.com/ava-labs/avalanchego/wallet/chain/p/signer" ) var ( - errNotCommitted = errors.New("not committed") + ErrNotCommitted = errors.New("not committed") _ Wallet = (*wallet)(nil) ) type Wallet interface { - Context - // Builder returns the builder that will be used to create the transactions. - Builder() Builder + Builder() builder.Builder // Signer returns the signer that will be used to sign the transactions. - Signer() Signer + Signer() walletsigner.Signer // IssueBaseTx creates, signs, and issues a new simple value transfer. // @@ -219,7 +220,7 @@ type Wallet interface { // the delegation reward will be sent to the validator's [rewardsOwner]. IssueAddPermissionlessValidatorTx( vdr *txs.SubnetValidator, - signer signer.Signer, + signer vmsigner.Signer, assetID ids.ID, validationRewardsOwner *secp256k1fx.OutputOwners, delegationRewardsOwner *secp256k1fx.OutputOwners, @@ -256,8 +257,8 @@ type Wallet interface { } func NewWallet( - builder Builder, - signer Signer, + builder builder.Builder, + signer walletsigner.Signer, client platformvm.Client, backend Backend, ) Wallet { @@ -271,16 +272,16 @@ func NewWallet( type wallet struct { Backend - builder Builder - signer Signer + builder builder.Builder + signer walletsigner.Signer client platformvm.Client } -func (w *wallet) Builder() Builder { +func (w *wallet) Builder() builder.Builder { return w.builder } -func (w *wallet) Signer() Signer { +func (w *wallet) Signer() walletsigner.Signer { return w.signer } @@ -447,7 +448,7 @@ func (w *wallet) IssueTransformSubnetTx( func (w *wallet) IssueAddPermissionlessValidatorTx( vdr *txs.SubnetValidator, - signer signer.Signer, + signer vmsigner.Signer, assetID ids.ID, validationRewardsOwner *secp256k1fx.OutputOwners, delegationRewardsOwner *secp256k1fx.OutputOwners, @@ -493,7 +494,7 @@ func (w *wallet) IssueUnsignedTx( ) (*txs.Tx, error) { ops := common.NewOptions(options) ctx := ops.Context() - tx, err := SignUnsigned(ctx, w.signer, utx) + tx, err := walletsigner.SignUnsigned(ctx, w.signer, utx) if err != nil { return nil, err } @@ -530,7 +531,7 @@ func (w *wallet) IssueTx( } if txStatus.Status != status.Committed { - return fmt.Errorf("%w: %s", errNotCommitted, txStatus.Reason) + return fmt.Errorf("%w: %s", ErrNotCommitted, txStatus.Reason) } return nil } diff --git a/wallet/chain/p/wallet_with_options.go b/wallet/chain/p/wallet_with_options.go index 4982e77f8a51..92965f2e4f1f 100644 --- a/wallet/chain/p/wallet_with_options.go +++ b/wallet/chain/p/wallet_with_options.go @@ -8,10 +8,13 @@ import ( "github.com/ava-labs/avalanchego/ids" "github.com/ava-labs/avalanchego/vms/components/avax" - "github.com/ava-labs/avalanchego/vms/platformvm/signer" "github.com/ava-labs/avalanchego/vms/platformvm/txs" "github.com/ava-labs/avalanchego/vms/secp256k1fx" + "github.com/ava-labs/avalanchego/wallet/chain/p/builder" "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" + + vmsigner "github.com/ava-labs/avalanchego/vms/platformvm/signer" + walletsigner "github.com/ava-labs/avalanchego/wallet/chain/p/signer" ) var _ Wallet = (*walletWithOptions)(nil) @@ -21,28 +24,32 @@ func NewWalletWithOptions( options ...common.Option, ) Wallet { return &walletWithOptions{ - Wallet: wallet, + wallet: wallet, options: options, } } type walletWithOptions struct { - Wallet + wallet Wallet options []common.Option } -func (w *walletWithOptions) Builder() Builder { - return NewBuilderWithOptions( - w.Wallet.Builder(), +func (w *walletWithOptions) Builder() builder.Builder { + return builder.NewWithOptions( + w.wallet.Builder(), w.options..., ) } +func (w *walletWithOptions) Signer() walletsigner.Signer { + return w.wallet.Signer() +} + func (w *walletWithOptions) IssueBaseTx( outputs []*avax.TransferableOutput, options ...common.Option, ) (*txs.Tx, error) { - return w.Wallet.IssueBaseTx( + return w.wallet.IssueBaseTx( outputs, common.UnionOptions(w.options, options)..., ) @@ -54,7 +61,7 @@ func (w *walletWithOptions) IssueAddValidatorTx( shares uint32, options ...common.Option, ) (*txs.Tx, error) { - return w.Wallet.IssueAddValidatorTx( + return w.wallet.IssueAddValidatorTx( vdr, rewardsOwner, shares, @@ -66,7 +73,7 @@ func (w *walletWithOptions) IssueAddSubnetValidatorTx( vdr *txs.SubnetValidator, options ...common.Option, ) (*txs.Tx, error) { - return w.Wallet.IssueAddSubnetValidatorTx( + return w.wallet.IssueAddSubnetValidatorTx( vdr, common.UnionOptions(w.options, options)..., ) @@ -77,7 +84,7 @@ func (w *walletWithOptions) IssueRemoveSubnetValidatorTx( subnetID ids.ID, options ...common.Option, ) (*txs.Tx, error) { - return w.Wallet.IssueRemoveSubnetValidatorTx( + return w.wallet.IssueRemoveSubnetValidatorTx( nodeID, subnetID, common.UnionOptions(w.options, options)..., @@ -89,7 +96,7 @@ func (w *walletWithOptions) IssueAddDelegatorTx( rewardsOwner *secp256k1fx.OutputOwners, options ...common.Option, ) (*txs.Tx, error) { - return w.Wallet.IssueAddDelegatorTx( + return w.wallet.IssueAddDelegatorTx( vdr, rewardsOwner, common.UnionOptions(w.options, options)..., @@ -104,7 +111,7 @@ func (w *walletWithOptions) IssueCreateChainTx( chainName string, options ...common.Option, ) (*txs.Tx, error) { - return w.Wallet.IssueCreateChainTx( + return w.wallet.IssueCreateChainTx( subnetID, genesis, vmID, @@ -118,7 +125,7 @@ func (w *walletWithOptions) IssueCreateSubnetTx( owner *secp256k1fx.OutputOwners, options ...common.Option, ) (*txs.Tx, error) { - return w.Wallet.IssueCreateSubnetTx( + return w.wallet.IssueCreateSubnetTx( owner, common.UnionOptions(w.options, options)..., ) @@ -129,7 +136,7 @@ func (w *walletWithOptions) IssueTransferSubnetOwnershipTx( owner *secp256k1fx.OutputOwners, options ...common.Option, ) (*txs.Tx, error) { - return w.Wallet.IssueTransferSubnetOwnershipTx( + return w.wallet.IssueTransferSubnetOwnershipTx( subnetID, owner, common.UnionOptions(w.options, options)..., @@ -141,7 +148,7 @@ func (w *walletWithOptions) IssueImportTx( to *secp256k1fx.OutputOwners, options ...common.Option, ) (*txs.Tx, error) { - return w.Wallet.IssueImportTx( + return w.wallet.IssueImportTx( sourceChainID, to, common.UnionOptions(w.options, options)..., @@ -153,7 +160,7 @@ func (w *walletWithOptions) IssueExportTx( outputs []*avax.TransferableOutput, options ...common.Option, ) (*txs.Tx, error) { - return w.Wallet.IssueExportTx( + return w.wallet.IssueExportTx( chainID, outputs, common.UnionOptions(w.options, options)..., @@ -177,7 +184,7 @@ func (w *walletWithOptions) IssueTransformSubnetTx( uptimeRequirement uint32, options ...common.Option, ) (*txs.Tx, error) { - return w.Wallet.IssueTransformSubnetTx( + return w.wallet.IssueTransformSubnetTx( subnetID, assetID, initialSupply, @@ -198,14 +205,14 @@ func (w *walletWithOptions) IssueTransformSubnetTx( func (w *walletWithOptions) IssueAddPermissionlessValidatorTx( vdr *txs.SubnetValidator, - signer signer.Signer, + signer vmsigner.Signer, assetID ids.ID, validationRewardsOwner *secp256k1fx.OutputOwners, delegationRewardsOwner *secp256k1fx.OutputOwners, shares uint32, options ...common.Option, ) (*txs.Tx, error) { - return w.Wallet.IssueAddPermissionlessValidatorTx( + return w.wallet.IssueAddPermissionlessValidatorTx( vdr, signer, assetID, @@ -222,7 +229,7 @@ func (w *walletWithOptions) IssueAddPermissionlessDelegatorTx( rewardsOwner *secp256k1fx.OutputOwners, options ...common.Option, ) (*txs.Tx, error) { - return w.Wallet.IssueAddPermissionlessDelegatorTx( + return w.wallet.IssueAddPermissionlessDelegatorTx( vdr, assetID, rewardsOwner, @@ -234,7 +241,7 @@ func (w *walletWithOptions) IssueUnsignedTx( utx txs.UnsignedTx, options ...common.Option, ) (*txs.Tx, error) { - return w.Wallet.IssueUnsignedTx( + return w.wallet.IssueUnsignedTx( utx, common.UnionOptions(w.options, options)..., ) @@ -244,7 +251,7 @@ func (w *walletWithOptions) IssueTx( tx *txs.Tx, options ...common.Option, ) error { - return w.Wallet.IssueTx( + return w.wallet.IssueTx( tx, common.UnionOptions(w.options, options)..., ) diff --git a/wallet/subnet/primary/api.go b/wallet/subnet/primary/api.go index 3c30b60d81c2..7486cde263e9 100644 --- a/wallet/subnet/primary/api.go +++ b/wallet/subnet/primary/api.go @@ -21,7 +21,7 @@ import ( "github.com/ava-labs/avalanchego/vms/platformvm" "github.com/ava-labs/avalanchego/vms/platformvm/txs" "github.com/ava-labs/avalanchego/wallet/chain/c" - "github.com/ava-labs/avalanchego/wallet/chain/p" + "github.com/ava-labs/avalanchego/wallet/chain/p/builder" "github.com/ava-labs/avalanchego/wallet/chain/x" walletcommon "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" @@ -57,7 +57,7 @@ type UTXOClient interface { type AVAXState struct { PClient platformvm.Client - PCTX p.Context + PCTX *builder.Context XClient avm.Client XCTX x.Context CClient evm.Client @@ -78,7 +78,7 @@ func FetchState( xClient := avm.NewClient(uri, "X") cClient := evm.NewCChainClient(uri) - pCTX, err := p.NewContextFromClients(ctx, infoClient, xClient) + pCTX, err := builder.NewContextFromClients(ctx, infoClient, xClient) if err != nil { return nil, err } diff --git a/wallet/subnet/primary/examples/add-primary-validator/main.go b/wallet/subnet/primary/examples/add-primary-validator/main.go index 987229d1ec22..7c2b6c055855 100644 --- a/wallet/subnet/primary/examples/add-primary-validator/main.go +++ b/wallet/subnet/primary/examples/add-primary-validator/main.go @@ -54,7 +54,9 @@ func main() { // Get the P-chain wallet pWallet := wallet.P() - avaxAssetID := pWallet.AVAXAssetID() + pBuilder := pWallet.Builder() + pContext := pBuilder.Context() + avaxAssetID := pContext.AVAXAssetID addValidatorStartTime := time.Now() addValidatorTx, err := pWallet.IssueAddPermissionlessValidatorTx( diff --git a/wallet/subnet/primary/examples/create-locked-stakeable/main.go b/wallet/subnet/primary/examples/create-locked-stakeable/main.go index 32cdcf983ba0..a6cf5c78604e 100644 --- a/wallet/subnet/primary/examples/create-locked-stakeable/main.go +++ b/wallet/subnet/primary/examples/create-locked-stakeable/main.go @@ -48,7 +48,9 @@ func main() { // Get the P-chain wallet pWallet := wallet.P() - avaxAssetID := pWallet.AVAXAssetID() + pBuilder := pWallet.Builder() + pContext := pBuilder.Context() + avaxAssetID := pContext.AVAXAssetID issueTxStartTime := time.Now() tx, err := pWallet.IssueBaseTx([]*avax.TransferableOutput{ diff --git a/wallet/subnet/primary/examples/get-p-chain-balance/main.go b/wallet/subnet/primary/examples/get-p-chain-balance/main.go index 08f2cd538c29..e190247515bf 100644 --- a/wallet/subnet/primary/examples/get-p-chain-balance/main.go +++ b/wallet/subnet/primary/examples/get-p-chain-balance/main.go @@ -12,6 +12,7 @@ import ( "github.com/ava-labs/avalanchego/utils/formatting/address" "github.com/ava-labs/avalanchego/utils/set" "github.com/ava-labs/avalanchego/wallet/chain/p" + "github.com/ava-labs/avalanchego/wallet/chain/p/builder" "github.com/ava-labs/avalanchego/wallet/subnet/primary" "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" ) @@ -38,14 +39,14 @@ func main() { pUTXOs := common.NewChainUTXOs(constants.PlatformChainID, state.UTXOs) pBackend := p.NewBackend(state.PCTX, pUTXOs, nil) - pBuilder := p.NewBuilder(addresses, pBackend) + pBuilder := builder.New(addresses, state.PCTX, pBackend) currentBalances, err := pBuilder.GetBalance() if err != nil { log.Fatalf("failed to get the balance: %s\n", err) } - avaxID := state.PCTX.AVAXAssetID() + avaxID := state.PCTX.AVAXAssetID avaxBalance := currentBalances[avaxID] log.Printf("current AVAX balance of %s is %d nAVAX\n", addrStr, avaxBalance) } diff --git a/wallet/subnet/primary/wallet.go b/wallet/subnet/primary/wallet.go index 9aabf651cff7..6a9e9d3124b0 100644 --- a/wallet/subnet/primary/wallet.go +++ b/wallet/subnet/primary/wallet.go @@ -15,6 +15,9 @@ import ( "github.com/ava-labs/avalanchego/wallet/chain/p" "github.com/ava-labs/avalanchego/wallet/chain/x" "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" + + pbuilder "github.com/ava-labs/avalanchego/wallet/chain/p/builder" + psigner "github.com/ava-labs/avalanchego/wallet/chain/p/signer" ) var _ Wallet = (*wallet)(nil) @@ -118,8 +121,8 @@ func MakeWallet(ctx context.Context, config *WalletConfig) (Wallet, error) { pUTXOs := common.NewChainUTXOs(constants.PlatformChainID, avaxState.UTXOs) pBackend := p.NewBackend(avaxState.PCTX, pUTXOs, pChainTxs) - pBuilder := p.NewBuilder(avaxAddrs, pBackend) - pSigner := p.NewSigner(config.AVAXKeychain, pBackend) + pBuilder := pbuilder.New(avaxAddrs, avaxState.PCTX, pBackend) + pSigner := psigner.New(config.AVAXKeychain, pBackend) xChainID := avaxState.XCTX.BlockchainID() xUTXOs := common.NewChainUTXOs(xChainID, avaxState.UTXOs)