github.com/MetalBlockchain/metalgo@v1.11.9/tests/e2e/p/workflow.go (about)

     1  // Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved.
     2  // See the file LICENSE for licensing terms.
     3  
     4  package p
     5  
     6  import (
     7  	"time"
     8  
     9  	"github.com/stretchr/testify/require"
    10  
    11  	"github.com/MetalBlockchain/metalgo/api/info"
    12  	"github.com/MetalBlockchain/metalgo/ids"
    13  	"github.com/MetalBlockchain/metalgo/tests"
    14  	"github.com/MetalBlockchain/metalgo/tests/fixture/e2e"
    15  	"github.com/MetalBlockchain/metalgo/utils"
    16  	"github.com/MetalBlockchain/metalgo/utils/constants"
    17  	"github.com/MetalBlockchain/metalgo/utils/crypto/bls"
    18  	"github.com/MetalBlockchain/metalgo/utils/units"
    19  	"github.com/MetalBlockchain/metalgo/vms/components/avax"
    20  	"github.com/MetalBlockchain/metalgo/vms/platformvm"
    21  	"github.com/MetalBlockchain/metalgo/vms/platformvm/signer"
    22  	"github.com/MetalBlockchain/metalgo/vms/platformvm/txs"
    23  	"github.com/MetalBlockchain/metalgo/vms/secp256k1fx"
    24  
    25  	ginkgo "github.com/onsi/ginkgo/v2"
    26  )
    27  
    28  // PChainWorkflow is an integration test for normal P-Chain operations
    29  // - Issues an Add Validator and an Add Delegator using the funding address
    30  // - Exports AVAX from the P-Chain funding address to the X-Chain created address
    31  // - Exports AVAX from the X-Chain created address to the P-Chain created address
    32  // - Checks the expected value of the funding address
    33  
    34  var _ = e2e.DescribePChain("[Workflow]", func() {
    35  	require := require.New(ginkgo.GinkgoT())
    36  
    37  	ginkgo.It("P-chain main operations",
    38  		func() {
    39  			nodeURI := e2e.Env.GetRandomNodeURI()
    40  			keychain := e2e.Env.NewKeychain(2)
    41  			baseWallet := e2e.NewWallet(keychain, nodeURI)
    42  
    43  			pWallet := baseWallet.P()
    44  			pBuilder := pWallet.Builder()
    45  			pContext := pBuilder.Context()
    46  			avaxAssetID := pContext.AVAXAssetID
    47  			xWallet := baseWallet.X()
    48  			xBuilder := xWallet.Builder()
    49  			xContext := xBuilder.Context()
    50  			pChainClient := platformvm.NewClient(nodeURI.URI)
    51  
    52  			tests.Outf("{{blue}} fetching minimal stake amounts {{/}}\n")
    53  			minValStake, minDelStake, err := pChainClient.GetMinStake(e2e.DefaultContext(), constants.PlatformChainID)
    54  			require.NoError(err)
    55  			tests.Outf("{{green}} minimal validator stake: %d {{/}}\n", minValStake)
    56  			tests.Outf("{{green}} minimal delegator stake: %d {{/}}\n", minDelStake)
    57  
    58  			tests.Outf("{{blue}} fetching tx fee {{/}}\n")
    59  			infoClient := info.NewClient(nodeURI.URI)
    60  			fees, err := infoClient.GetTxFee(e2e.DefaultContext())
    61  			require.NoError(err)
    62  			txFees := uint64(fees.TxFee)
    63  			tests.Outf("{{green}} txFee: %d {{/}}\n", txFees)
    64  
    65  			// amount to transfer from P to X chain
    66  			toTransfer := 1 * units.Avax
    67  
    68  			pShortAddr := keychain.Keys[0].Address()
    69  			xTargetAddr := keychain.Keys[1].Address()
    70  			ginkgo.By("check selected keys have sufficient funds", func() {
    71  				pBalances, err := pWallet.Builder().GetBalance()
    72  				pBalance := pBalances[avaxAssetID]
    73  				minBalance := minValStake + txFees + minDelStake + txFees + toTransfer + txFees
    74  				require.NoError(err)
    75  				require.GreaterOrEqual(pBalance, minBalance)
    76  			})
    77  
    78  			// Use a random node ID to ensure that repeated test runs
    79  			// will succeed against a network that persists across runs.
    80  			validatorID, err := ids.ToNodeID(utils.RandomBytes(ids.NodeIDLen))
    81  			require.NoError(err)
    82  
    83  			vdr := &txs.SubnetValidator{
    84  				Validator: txs.Validator{
    85  					NodeID: validatorID,
    86  					End:    uint64(time.Now().Add(72 * time.Hour).Unix()),
    87  					Wght:   minValStake,
    88  				},
    89  				Subnet: constants.PrimaryNetworkID,
    90  			}
    91  			rewardOwner := &secp256k1fx.OutputOwners{
    92  				Threshold: 1,
    93  				Addrs:     []ids.ShortID{pShortAddr},
    94  			}
    95  			shares := uint32(20000) // TODO: retrieve programmatically
    96  
    97  			sk, err := bls.NewSecretKey()
    98  			require.NoError(err)
    99  			pop := signer.NewProofOfPossession(sk)
   100  
   101  			ginkgo.By("issue add validator tx", func() {
   102  				_, err := pWallet.IssueAddPermissionlessValidatorTx(
   103  					vdr,
   104  					pop,
   105  					avaxAssetID,
   106  					rewardOwner,
   107  					rewardOwner,
   108  					shares,
   109  					e2e.WithDefaultContext(),
   110  				)
   111  				require.NoError(err)
   112  			})
   113  
   114  			ginkgo.By("issue add delegator tx", func() {
   115  				_, err := pWallet.IssueAddPermissionlessDelegatorTx(
   116  					vdr,
   117  					avaxAssetID,
   118  					rewardOwner,
   119  					e2e.WithDefaultContext(),
   120  				)
   121  				require.NoError(err)
   122  			})
   123  
   124  			// retrieve initial balances
   125  			pBalances, err := pWallet.Builder().GetBalance()
   126  			require.NoError(err)
   127  			pStartBalance := pBalances[avaxAssetID]
   128  			tests.Outf("{{blue}} P-chain balance before P->X export: %d {{/}}\n", pStartBalance)
   129  
   130  			xBalances, err := xWallet.Builder().GetFTBalance()
   131  			require.NoError(err)
   132  			xStartBalance := xBalances[avaxAssetID]
   133  			tests.Outf("{{blue}} X-chain balance before P->X export: %d {{/}}\n", xStartBalance)
   134  
   135  			outputOwner := secp256k1fx.OutputOwners{
   136  				Threshold: 1,
   137  				Addrs: []ids.ShortID{
   138  					xTargetAddr,
   139  				},
   140  			}
   141  			output := &secp256k1fx.TransferOutput{
   142  				Amt:          toTransfer,
   143  				OutputOwners: outputOwner,
   144  			}
   145  
   146  			ginkgo.By("export avax from P to X chain", func() {
   147  				_, err := pWallet.IssueExportTx(
   148  					xContext.BlockchainID,
   149  					[]*avax.TransferableOutput{
   150  						{
   151  							Asset: avax.Asset{
   152  								ID: avaxAssetID,
   153  							},
   154  							Out: output,
   155  						},
   156  					},
   157  					e2e.WithDefaultContext(),
   158  				)
   159  				require.NoError(err)
   160  			})
   161  
   162  			// check balances post export
   163  			pBalances, err = pWallet.Builder().GetBalance()
   164  			require.NoError(err)
   165  			pPreImportBalance := pBalances[avaxAssetID]
   166  			tests.Outf("{{blue}} P-chain balance after P->X export: %d {{/}}\n", pPreImportBalance)
   167  
   168  			xBalances, err = xWallet.Builder().GetFTBalance()
   169  			require.NoError(err)
   170  			xPreImportBalance := xBalances[avaxAssetID]
   171  			tests.Outf("{{blue}} X-chain balance after P->X export: %d {{/}}\n", xPreImportBalance)
   172  
   173  			require.Equal(xPreImportBalance, xStartBalance) // import not performed yet
   174  			require.Equal(pPreImportBalance, pStartBalance-toTransfer-txFees)
   175  
   176  			ginkgo.By("import avax from P into X chain", func() {
   177  				_, err := xWallet.IssueImportTx(
   178  					constants.PlatformChainID,
   179  					&outputOwner,
   180  					e2e.WithDefaultContext(),
   181  				)
   182  				require.NoError(err)
   183  			})
   184  
   185  			// check balances post import
   186  			pBalances, err = pWallet.Builder().GetBalance()
   187  			require.NoError(err)
   188  			pFinalBalance := pBalances[avaxAssetID]
   189  			tests.Outf("{{blue}} P-chain balance after P->X import: %d {{/}}\n", pFinalBalance)
   190  
   191  			xBalances, err = xWallet.Builder().GetFTBalance()
   192  			require.NoError(err)
   193  			xFinalBalance := xBalances[avaxAssetID]
   194  			tests.Outf("{{blue}} X-chain balance after P->X import: %d {{/}}\n", xFinalBalance)
   195  
   196  			require.Equal(xFinalBalance, xPreImportBalance+toTransfer-txFees) // import not performed yet
   197  			require.Equal(pFinalBalance, pPreImportBalance)
   198  		})
   199  })