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 })