From f99a64a4012ed07455e69e25d987d891e74505a6 Mon Sep 17 00:00:00 2001 From: Stephen Buttolph Date: Fri, 14 Jun 2024 12:10:23 -0400 Subject: [PATCH] Update C-chain wallet context (#3118) --- tests/e2e/c/interchain_workflow.go | 6 +- tests/e2e/p/interchain_workflow.go | 4 +- tests/e2e/x/interchain_workflow.go | 4 +- wallet/chain/c/backend.go | 13 ++-- wallet/chain/c/builder.go | 37 +++++---- wallet/chain/c/context.go | 77 ++++++------------- wallet/chain/c/signer.go | 13 ++-- wallet/chain/c/wallet.go | 2 - wallet/subnet/primary/api.go | 4 +- .../primary/examples/c-chain-export/main.go | 2 +- .../primary/examples/c-chain-import/main.go | 5 +- wallet/subnet/primary/wallet.go | 6 +- 12 files changed, 75 insertions(+), 98 deletions(-) diff --git a/tests/e2e/c/interchain_workflow.go b/tests/e2e/c/interchain_workflow.go index f5afc4abe059..bfb342818a5f 100644 --- a/tests/e2e/c/interchain_workflow.go +++ b/tests/e2e/c/interchain_workflow.go @@ -86,6 +86,8 @@ var _ = e2e.DescribeCChain("[Interchain Workflow]", func() { ginkgo.By("defining common configuration") xBuilder := xWallet.Builder() xContext := xBuilder.Context() + cBuilder := cWallet.Builder() + cContext := cBuilder.Context() avaxAssetID := xContext.AVAXAssetID // Use the same owner for import funds to X-Chain and P-Chain recipientOwner := secp256k1fx.OutputOwners{ @@ -119,7 +121,7 @@ var _ = e2e.DescribeCChain("[Interchain Workflow]", func() { ginkgo.By("importing AVAX from the C-Chain to the X-Chain", func() { _, err := xWallet.IssueImportTx( - cWallet.BlockchainID(), + cContext.BlockchainID, &recipientOwner, e2e.WithDefaultContext(), ) @@ -146,7 +148,7 @@ var _ = e2e.DescribeCChain("[Interchain Workflow]", func() { ginkgo.By("importing AVAX from the C-Chain to the P-Chain", func() { _, err = pWallet.IssueImportTx( - cWallet.BlockchainID(), + cContext.BlockchainID, &recipientOwner, e2e.WithDefaultContext(), ) diff --git a/tests/e2e/p/interchain_workflow.go b/tests/e2e/p/interchain_workflow.go index d27d080d9c00..548c82ac1211 100644 --- a/tests/e2e/p/interchain_workflow.go +++ b/tests/e2e/p/interchain_workflow.go @@ -60,6 +60,8 @@ var _ = e2e.DescribePChain("[Interchain Workflow]", ginkgo.Label(e2e.UsesCChainL xContext := xBuilder.Context() pBuilder := pWallet.Builder() pContext := pBuilder.Context() + cBuilder := cWallet.Builder() + cContext := cBuilder.Context() ginkgo.By("defining common configuration") recipientEthAddress := evm.GetEthAddress(recipientKey) @@ -186,7 +188,7 @@ var _ = e2e.DescribePChain("[Interchain Workflow]", ginkgo.Label(e2e.UsesCChainL ginkgo.By("exporting AVAX from the P-Chain to the C-Chain", func() { _, err := pWallet.IssueExportTx( - cWallet.BlockchainID(), + cContext.BlockchainID, exportOutputs, e2e.WithDefaultContext(), ) diff --git a/tests/e2e/x/interchain_workflow.go b/tests/e2e/x/interchain_workflow.go index 838c6d11773d..ecc52f41f032 100644 --- a/tests/e2e/x/interchain_workflow.go +++ b/tests/e2e/x/interchain_workflow.go @@ -44,6 +44,8 @@ var _ = e2e.DescribeXChain("[Interchain Workflow]", ginkgo.Label(e2e.UsesCChainL recipientEthAddress := evm.GetEthAddress(recipientKey) xBuilder := xWallet.Builder() xContext := xBuilder.Context() + cBuilder := cWallet.Builder() + cContext := cBuilder.Context() avaxAssetID := xContext.AVAXAssetID // Use the same owner for sending to X-Chain and importing funds to P-Chain recipientOwner := secp256k1fx.OutputOwners{ @@ -96,7 +98,7 @@ var _ = e2e.DescribeXChain("[Interchain Workflow]", ginkgo.Label(e2e.UsesCChainL ginkgo.By("exporting AVAX from the X-Chain to the C-Chain", func() { _, err := xWallet.IssueExportTx( - cWallet.BlockchainID(), + cContext.BlockchainID, exportOutputs, e2e.WithDefaultContext(), ) diff --git a/wallet/chain/c/backend.go b/wallet/chain/c/backend.go index 3301015f0eeb..8d1ea6f34f07 100644 --- a/wallet/chain/c/backend.go +++ b/wallet/chain/c/backend.go @@ -4,6 +4,7 @@ package c import ( + "context" "errors" "fmt" "math/big" @@ -16,7 +17,6 @@ import ( "github.com/ava-labs/avalanchego/vms/components/avax" "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" - stdcontext "context" ethcommon "github.com/ethereum/go-ethereum/common" ) @@ -32,11 +32,10 @@ type Backend interface { BuilderBackend SignerBackend - AcceptAtomicTx(ctx stdcontext.Context, tx *evm.Tx) error + AcceptAtomicTx(ctx context.Context, tx *evm.Tx) error } type backend struct { - Context common.ChainUTXOs accountsLock sync.RWMutex @@ -49,18 +48,16 @@ type Account struct { } func NewBackend( - ctx Context, utxos common.ChainUTXOs, accounts map[ethcommon.Address]*Account, ) Backend { return &backend{ - Context: ctx, ChainUTXOs: utxos, accounts: accounts, } } -func (b *backend) AcceptAtomicTx(ctx stdcontext.Context, tx *evm.Tx) error { +func (b *backend) AcceptAtomicTx(ctx context.Context, tx *evm.Tx) error { switch tx := tx.UnsignedAtomicTx.(type) { case *evm.UnsignedImportTx: for _, input := range tx.ImportedInputs { @@ -131,7 +128,7 @@ func (b *backend) AcceptAtomicTx(ctx stdcontext.Context, tx *evm.Tx) error { return nil } -func (b *backend) Balance(_ stdcontext.Context, addr ethcommon.Address) (*big.Int, error) { +func (b *backend) Balance(_ context.Context, addr ethcommon.Address) (*big.Int, error) { b.accountsLock.RLock() defer b.accountsLock.RUnlock() @@ -142,7 +139,7 @@ func (b *backend) Balance(_ stdcontext.Context, addr ethcommon.Address) (*big.In return account.Balance, nil } -func (b *backend) Nonce(_ stdcontext.Context, addr ethcommon.Address) (uint64, error) { +func (b *backend) Nonce(_ context.Context, addr ethcommon.Address) (uint64, error) { b.accountsLock.RLock() defer b.accountsLock.RUnlock() diff --git a/wallet/chain/c/builder.go b/wallet/chain/c/builder.go index 28e1eccc2d54..0554cb39ba95 100644 --- a/wallet/chain/c/builder.go +++ b/wallet/chain/c/builder.go @@ -4,6 +4,7 @@ package c import ( + "context" "errors" "math/big" @@ -17,7 +18,6 @@ import ( "github.com/ava-labs/avalanchego/vms/secp256k1fx" "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" - stdcontext "context" ethcommon "github.com/ethereum/go-ethereum/common" ) @@ -41,6 +41,10 @@ var ( // Builder provides a convenient interface for building unsigned C-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 AVAX that this builder has control // over. GetBalance( @@ -86,16 +90,15 @@ type Builder interface { // BuilderBackend specifies the required information needed to build unsigned // C-chain transactions. type BuilderBackend interface { - Context - - UTXOs(ctx stdcontext.Context, sourceChainID ids.ID) ([]*avax.UTXO, error) - Balance(ctx stdcontext.Context, addr ethcommon.Address) (*big.Int, error) - Nonce(ctx stdcontext.Context, addr ethcommon.Address) (uint64, error) + UTXOs(ctx context.Context, sourceChainID ids.ID) ([]*avax.UTXO, error) + Balance(ctx context.Context, addr ethcommon.Address) (*big.Int, error) + Nonce(ctx context.Context, addr ethcommon.Address) (uint64, error) } type builder struct { avaxAddrs set.Set[ids.ShortID] ethAddrs set.Set[ethcommon.Address] + context *Context backend BuilderBackend } @@ -110,15 +113,21 @@ type builder struct { func NewBuilder( avaxAddrs set.Set[ids.ShortID], ethAddrs set.Set[ethcommon.Address], + context *Context, backend BuilderBackend, ) Builder { return &builder{ avaxAddrs: avaxAddrs, ethAddrs: ethAddrs, + context: context, backend: backend, } } +func (b *builder) Context() *Context { + return b.context +} + func (b *builder) GetBalance( options ...common.Option, ) (*big.Int, error) { @@ -152,7 +161,7 @@ func (b *builder) GetImportableBalance( var ( addrs = ops.Addresses(b.avaxAddrs) minIssuanceTime = ops.MinIssuanceTime() - avaxAssetID = b.backend.AVAXAssetID() + avaxAssetID = b.context.AVAXAssetID balance uint64 ) for _, utxo := range utxos { @@ -186,7 +195,7 @@ func (b *builder) NewImportTx( var ( addrs = ops.Addresses(b.avaxAddrs) minIssuanceTime = ops.MinIssuanceTime() - avaxAssetID = b.backend.AVAXAssetID() + avaxAssetID = b.context.AVAXAssetID importedInputs = make([]*avax.TransferableInput, 0, len(utxos)) importedAmount uint64 @@ -218,8 +227,8 @@ func (b *builder) NewImportTx( utils.Sort(importedInputs) tx := &evm.UnsignedImportTx{ - NetworkID: b.backend.NetworkID(), - BlockchainID: b.backend.BlockchainID(), + NetworkID: b.context.NetworkID, + BlockchainID: b.context.BlockchainID, SourceChain: chainID, ImportedInputs: importedInputs, } @@ -260,7 +269,7 @@ func (b *builder) NewExportTx( options ...common.Option, ) (*evm.UnsignedExportTx, error) { var ( - avaxAssetID = b.backend.AVAXAssetID() + avaxAssetID = b.context.AVAXAssetID exportedOutputs = make([]*avax.TransferableOutput, len(outputs)) exportedAmount uint64 ) @@ -280,8 +289,8 @@ func (b *builder) NewExportTx( avax.SortTransferableOutputs(exportedOutputs, evm.Codec) tx := &evm.UnsignedExportTx{ - NetworkID: b.backend.NetworkID(), - BlockchainID: b.backend.BlockchainID(), + NetworkID: b.context.NetworkID, + BlockchainID: b.context.BlockchainID, DestinationChain: chainID, ExportedOutputs: exportedOutputs, } @@ -378,7 +387,7 @@ func (b *builder) NewExportTx( utils.Sort(inputs) tx.Ins = inputs - snowCtx, err := newSnowContext(b.backend) + snowCtx, err := newSnowContext(b.context) if err != nil { return nil, err } diff --git a/wallet/chain/c/context.go b/wallet/chain/c/context.go index dc0537e23069..d56a75a0070b 100644 --- a/wallet/chain/c/context.go +++ b/wallet/chain/c/context.go @@ -4,99 +4,66 @@ package c 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" - - stdcontext "context" ) const Alias = "C" -var _ Context = (*context)(nil) - -type Context interface { - NetworkID() uint32 - BlockchainID() ids.ID - AVAXAssetID() ids.ID +type Context struct { + NetworkID uint32 + BlockchainID ids.ID + AVAXAssetID ids.ID } -type context struct { - networkID uint32 - blockchainID ids.ID - avaxAssetID ids.ID -} - -func NewContextFromURI(ctx stdcontext.Context, uri string) (Context, error) { +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 stdcontext.Context, + ctx context.Context, infoClient info.Client, xChainClient avm.Client, -) (Context, error) { +) (*Context, error) { networkID, err := infoClient.GetNetworkID(ctx) if err != nil { return nil, err } - chainID, err := infoClient.GetBlockchainID(ctx, Alias) + blockchainID, err := infoClient.GetBlockchainID(ctx, Alias) if err != nil { return nil, err } - asset, err := xChainClient.GetAssetDescription(ctx, "AVAX") + avaxAsset, err := xChainClient.GetAssetDescription(ctx, "AVAX") if err != nil { return nil, err } - return NewContext( - networkID, - chainID, - asset.AssetID, - ), nil -} - -func NewContext( - networkID uint32, - blockchainID ids.ID, - avaxAssetID ids.ID, -) Context { - return &context{ - networkID: networkID, - blockchainID: blockchainID, - avaxAssetID: avaxAssetID, - } -} - -func (c *context) NetworkID() uint32 { - return c.networkID -} - -func (c *context) BlockchainID() ids.ID { - return c.blockchainID -} - -func (c *context) AVAXAssetID() ids.ID { - return c.avaxAssetID + return &Context{ + NetworkID: networkID, + BlockchainID: blockchainID, + AVAXAssetID: avaxAsset.AssetID, + }, nil } -func newSnowContext(c Context) (*snow.Context, error) { - chainID := c.BlockchainID() +func newSnowContext(c *Context) (*snow.Context, error) { lookup := ids.NewAliaser() return &snow.Context{ - NetworkID: c.NetworkID(), + NetworkID: c.NetworkID, SubnetID: constants.PrimaryNetworkID, - ChainID: chainID, - CChainID: chainID, - AVAXAssetID: c.AVAXAssetID(), + ChainID: c.BlockchainID, + CChainID: c.BlockchainID, + AVAXAssetID: c.AVAXAssetID, Log: logging.NoLog{}, BCLookup: lookup, - }, lookup.Alias(chainID, Alias) + }, lookup.Alias(c.BlockchainID, Alias) } diff --git a/wallet/chain/c/signer.go b/wallet/chain/c/signer.go index 24de72c13941..1e69db75be19 100644 --- a/wallet/chain/c/signer.go +++ b/wallet/chain/c/signer.go @@ -4,6 +4,7 @@ package c import ( + "context" "errors" "fmt" @@ -19,8 +20,6 @@ import ( "github.com/ava-labs/avalanchego/vms/components/avax" "github.com/ava-labs/avalanchego/vms/components/verify" "github.com/ava-labs/avalanchego/vms/secp256k1fx" - - stdcontext "context" ) const version = 0 @@ -45,7 +44,7 @@ type Signer interface { // // If the signer doesn't have the ability to provide a required signature, // the signature slot will be skipped without reporting an error. - SignAtomic(ctx stdcontext.Context, tx *evm.Tx) error + SignAtomic(ctx context.Context, tx *evm.Tx) error } type EthKeychain interface { @@ -57,7 +56,7 @@ type EthKeychain interface { } type SignerBackend interface { - GetUTXO(ctx stdcontext.Context, chainID, utxoID ids.ID) (*avax.UTXO, error) + GetUTXO(ctx context.Context, chainID, utxoID ids.ID) (*avax.UTXO, error) } type txSigner struct { @@ -74,7 +73,7 @@ func NewSigner(avaxKC keychain.Keychain, ethKC EthKeychain, backend SignerBacken } } -func (s *txSigner) SignAtomic(ctx stdcontext.Context, tx *evm.Tx) error { +func (s *txSigner) SignAtomic(ctx context.Context, tx *evm.Tx) error { switch utx := tx.UnsignedAtomicTx.(type) { case *evm.UnsignedImportTx: signers, err := s.getImportSigners(ctx, utx.SourceChain, utx.ImportedInputs) @@ -90,7 +89,7 @@ func (s *txSigner) SignAtomic(ctx stdcontext.Context, tx *evm.Tx) error { } } -func (s *txSigner) getImportSigners(ctx stdcontext.Context, sourceChainID ids.ID, ins []*avax.TransferableInput) ([][]keychain.Signer, error) { +func (s *txSigner) getImportSigners(ctx context.Context, sourceChainID ids.ID, ins []*avax.TransferableInput) ([][]keychain.Signer, error) { txSigners := make([][]keychain.Signer, len(ins)) for credIndex, transferInput := range ins { input, ok := transferInput.In.(*secp256k1fx.TransferInput) @@ -152,7 +151,7 @@ func (s *txSigner) getExportSigners(ins []evm.EVMInput) [][]keychain.Signer { return txSigners } -func SignUnsignedAtomic(ctx stdcontext.Context, signer Signer, utx evm.UnsignedAtomicTx) (*evm.Tx, error) { +func SignUnsignedAtomic(ctx context.Context, signer Signer, utx evm.UnsignedAtomicTx) (*evm.Tx, error) { tx := &evm.Tx{UnsignedAtomicTx: utx} return tx, signer.SignAtomic(ctx, tx) } diff --git a/wallet/chain/c/wallet.go b/wallet/chain/c/wallet.go index 1f8d6d251748..1eeb77e830cb 100644 --- a/wallet/chain/c/wallet.go +++ b/wallet/chain/c/wallet.go @@ -25,8 +25,6 @@ var ( ) type Wallet interface { - Context - // Builder returns the builder that will be used to create the transactions. Builder() Builder diff --git a/wallet/subnet/primary/api.go b/wallet/subnet/primary/api.go index a7c271b385bf..2aedc5c476c9 100644 --- a/wallet/subnet/primary/api.go +++ b/wallet/subnet/primary/api.go @@ -62,7 +62,7 @@ type AVAXState struct { XClient avm.Client XCTX *xbuilder.Context CClient evm.Client - CCTX c.Context + CCTX *c.Context UTXOs walletcommon.UTXOs } @@ -112,7 +112,7 @@ func FetchState( codec: xbuilder.Parser.Codec(), }, { - id: cCTX.BlockchainID(), + id: cCTX.BlockchainID, client: cClient, codec: evm.Codec, }, diff --git a/wallet/subnet/primary/examples/c-chain-export/main.go b/wallet/subnet/primary/examples/c-chain-export/main.go index 41ecb5ca814e..a9a4c61773b8 100644 --- a/wallet/subnet/primary/examples/c-chain-export/main.go +++ b/wallet/subnet/primary/examples/c-chain-export/main.go @@ -42,7 +42,7 @@ func main() { cWallet := wallet.C() // Pull out useful constants to use when issuing transactions. - cChainID := cWallet.BlockchainID() + cChainID := cWallet.Builder().Context().BlockchainID owner := secp256k1fx.OutputOwners{ Threshold: 1, Addrs: []ids.ShortID{ diff --git a/wallet/subnet/primary/examples/c-chain-import/main.go b/wallet/subnet/primary/examples/c-chain-import/main.go index 387d435db4df..2f257fe6fd11 100644 --- a/wallet/subnet/primary/examples/c-chain-import/main.go +++ b/wallet/subnet/primary/examples/c-chain-import/main.go @@ -46,8 +46,9 @@ func main() { cWallet := wallet.C() // Pull out useful constants to use when issuing transactions. - cChainID := cWallet.BlockchainID() - avaxAssetID := cWallet.AVAXAssetID() + cContext := cWallet.Builder().Context() + cChainID := cContext.BlockchainID + avaxAssetID := cContext.AVAXAssetID owner := secp256k1fx.OutputOwners{ Threshold: 1, Addrs: []ids.ShortID{ diff --git a/wallet/subnet/primary/wallet.go b/wallet/subnet/primary/wallet.go index 382a042a6bee..179e9351ccca 100644 --- a/wallet/subnet/primary/wallet.go +++ b/wallet/subnet/primary/wallet.go @@ -132,10 +132,10 @@ func MakeWallet(ctx context.Context, config *WalletConfig) (Wallet, error) { xBuilder := xbuilder.New(avaxAddrs, avaxState.XCTX, xBackend) xSigner := xsigner.New(config.AVAXKeychain, xBackend) - cChainID := avaxState.CCTX.BlockchainID() + cChainID := avaxState.CCTX.BlockchainID cUTXOs := common.NewChainUTXOs(cChainID, avaxState.UTXOs) - cBackend := c.NewBackend(avaxState.CCTX, cUTXOs, ethState.Accounts) - cBuilder := c.NewBuilder(avaxAddrs, ethAddrs, cBackend) + cBackend := c.NewBackend(cUTXOs, ethState.Accounts) + cBuilder := c.NewBuilder(avaxAddrs, ethAddrs, avaxState.CCTX, cBackend) cSigner := c.NewSigner(config.AVAXKeychain, config.EthKeychain, cBackend) return NewWallet(