From dfc19a63434fab48612c74b1b70251dc10eb585a Mon Sep 17 00:00:00 2001 From: peartes Date: Fri, 3 Jan 2025 20:41:37 +0100 Subject: [PATCH] WIP: sign wasm update config with AA --- Makefile | 3 + .../update_treasury_configs_test.go | 196 ++++++++++++++++++ x/xion/client/cli/tx.go | 7 +- 3 files changed, 200 insertions(+), 6 deletions(-) diff --git a/Makefile b/Makefile index 40b1f31b..7afa5a01 100644 --- a/Makefile +++ b/Makefile @@ -297,6 +297,9 @@ test-integration-xion-treasury-grants: compile_integration_tests test-integration-xion-update-treasury-configs: compile_integration_tests @XION_TEST_IMAGE=$(XION_TEST_IMAGE) ./integration_tests/integration_tests.test -test.failfast -test.v -test.run TestUpdateTreasuryConfigsWithCLI +test-integration-xion-update-treasury-configs-aa: compile_integration_tests + @XION_TEST_IMAGE=$(XION_TEST_IMAGE) ./integration_tests/integration_tests.test -test.failfast -test.v -test.run TestUpdateTreasuryConfigsWithAA + test-integration-xion-treasury-multi: compile_integration_tests @XION_TEST_IMAGE=$(XION_TEST_IMAGE) ./integration_tests/integration_tests.test -test.failfast -test.v -test.run TestTreasuryMulti diff --git a/integration_tests/update_treasury_configs_test.go b/integration_tests/update_treasury_configs_test.go index fca76318..81b75d64 100644 --- a/integration_tests/update_treasury_configs_test.go +++ b/integration_tests/update_treasury_configs_test.go @@ -1,13 +1,16 @@ package integration_tests import ( + "encoding/base64" "encoding/json" + "fmt" "os" "path" "strings" "testing" "cosmossdk.io/math" + "github.com/cosmos/cosmos-sdk/crypto/keyring" "github.com/cosmos/cosmos-sdk/types" ibctest "github.com/strangelove-ventures/interchaintest/v8" "github.com/strangelove-ventures/interchaintest/v8/testutil" @@ -142,3 +145,196 @@ func TestUpdateTreasuryConfigsWithCLI(t *testing.T) { require.Equal(t, "Fee allowance for user1", queriedFeeConfig.Description) require.Equal(t, "/cosmos.feegrant.v1.BasicAllowance", queriedFeeConfig.Allowance.TypeURL) } + +func TestUpdateTreasuryConfigsWithAA(t *testing.T) { + // Setup Xion chain + td := BuildXionChain(t, "0.0uxion", nil) + xion, ctx := td.xionChain, td.ctx + + config := types.GetConfig() + config.SetBech32PrefixForAccount("xion", "xionpub") + + fp, err := os.Getwd() + require.NoError(t, err) + + // Create and fund test user + t.Log("Creating and funding user accounts") + fundAmount := math.NewInt(10_000_000) + users := ibctest.GetAndFundTestUsers(t, ctx, "default", fundAmount, xion) + xionUser := users[0] + + err = testutil.WaitForBlocks(ctx, 2, xion) + require.NoError(t, err) + + // Create a Secondary Key For Rotation + recipientKeyName := "recipient-key" + err = xion.CreateKey(ctx, recipientKeyName) + require.NoError(t, err) + receipientKeyAddressBytes, err := xion.GetAddress(ctx, recipientKeyName) + require.NoError(t, err) + _, err = types.Bech32ifyAddressBytes(xion.Config().Bech32Prefix, receipientKeyAddressBytes) + require.NoError(t, err) + + account, err := ExecBin(t, ctx, xion.GetNode(), + "keys", "show", + xionUser.KeyName(), + "--keyring-backend", keyring.BackendTest, + "-p", + ) + + // Store AA Wasm Contract + codeID, err := xion.StoreContract(ctx, xionUser.FormattedAddress(), path.Join(fp, + "integration_tests", "testdata", "contracts", "account_updatable-aarch64.wasm")) + require.NoError(t, err) + + depositedFunds := fmt.Sprintf("%d%s", 100000, xion.Config().Denom) + + registeredTxHash, err := ExecTx(t, ctx, xion.GetNode(), + xionUser.KeyName(), + "xion", "register", + codeID, + xionUser.KeyName(), + "--funds", depositedFunds, + "--salt", "0", + "--authenticator", "Secp256K1", + "--chain-id", xion.Config().ChainID, + ) + require.NoError(t, err) + t.Logf("tx hash: %s", registeredTxHash) + + txDetails, err := ExecQuery(t, ctx, xion.GetNode(), "tx", registeredTxHash) + require.NoError(t, err) + aaContractAddr := GetAAContractAddress(t, txDetails) + + contractBalance, err := xion.GetBalance(ctx, aaContractAddr, xion.Config().Denom) + require.NoError(t, err) + require.Equal(t, math.NewInt(100000), contractBalance) + + contractState, err := ExecQuery(t, ctx, xion.GetNode(), "wasm", "contract-state", "smart", aaContractAddr, `{"authenticator_by_i_d":{ "id": 0 }}`) + require.NoError(t, err) + + pubkey64, ok := contractState["data"].(string) + require.True(t, ok) + pubkeyRawJSON, err := base64.StdEncoding.DecodeString(pubkey64) + require.NoError(t, err) + var pubKeyMap jsonAuthenticator + json.Unmarshal(pubkeyRawJSON, &pubKeyMap) + require.Equal(t, account["key"], pubKeyMap["Secp256K1"]["pubkey"]) + + // Deploy contract + t.Log("Deploying contract") + codeIDStr, err := xion.StoreContract(ctx, xionUser.FormattedAddress(), + path.Join(fp, "integration_tests", "testdata", "contracts", "treasury-aarch64.wasm")) + require.NoError(t, err) + + // Instantiate contract + t.Log("Instantiating contract") + instantiateMsg := TreasuryInstantiateMsg{ + TypeUrls: []string{}, + GrantConfigs: []GrantConfig{}, + FeeConfig: &FeeConfig{ + Description: "test fee grant", + }, + } + instantiateMsgStr, err := json.Marshal(instantiateMsg) + require.NoError(t, err) + + treasuryAddr, err := xion.InstantiateContract(ctx, xionUser.KeyName(), codeIDStr, string(instantiateMsgStr), true) + require.NoError(t, err) + t.Logf("Deployed and instantiated contract at address: %s", treasuryAddr) + + // Prepare JSON files for grants and fee configs + t.Log("Preparing JSON files for grants and fee configs") + grantsFile, err := os.CreateTemp("", "*-grants.json") + require.NoError(t, err) + feeConfigsFile, err := os.CreateTemp("", "*-fee_configs.json") + require.NoError(t, err) + + grantsData, err := os.ReadFile(path.Join(fp, "integration_tests", "testdata", "unsigned_msgs", "grants.json")) + require.NoError(t, err) + + feeConfigsData, err := os.ReadFile(path.Join(fp, "integration_tests", "testdata", "unsigned_msgs", "fee_configs.json")) + require.NoError(t, err) + + _, err = grantsFile.Write(grantsData) + require.NoError(t, err) + + _, err = feeConfigsFile.Write(feeConfigsData) + require.NoError(t, err) + + err = UploadFileToContainer(t, ctx, xion.GetNode(), grantsFile) + require.NoError(t, err) + err = UploadFileToContainer(t, ctx, xion.GetNode(), feeConfigsFile) + require.NoError(t, err) + // Execute CLI command to submit transaction + grantsFilePath := strings.Split(grantsFile.Name(), "/") + feeConfigFilePath := strings.Split(feeConfigsFile.Name(), "/") + t.Log("Executing CLI command to update configs") + _ = path.Join(fp, "integration_tests", "testdata", "unsigned_tx.json") + cmd := []string{ + "tx", "xion", "update-configs", treasuryAddr, path.Join(xion.GetNode().HomeDir(), grantsFilePath[len(grantsFilePath)-1]), path.Join(xion.GetNode().HomeDir(), feeConfigFilePath[len(grantsFilePath)-1]), + "--chain-id", xion.Config().ChainID, + "--from", xionUser.FormattedAddress(), + "--gas", "auto", + "--fees", "1000uxion", + "--generate-only", + "--dry-run", + } + + unsignedTx, err := ExecBin(t, ctx, xion.GetNode(), cmd...) + require.NoError(t, err) + // Write the unsigned transaction to a file + // err = os.WriteFile(unsignedTxFile, []byte(unsignedTx), 0644) + require.NoError(t, err) + t.Log("unsigned tx file created ", unsignedTx) + + // TODO: sign the unsigned transaction + + // Wait for the transaction to be included in a block + err = testutil.WaitForBlocks(ctx, 2, xion) + require.NoError(t, err) + + // Query and validate Grant Config URLs + t.Log("Querying grant config type URLs") + grantQueryMsg := map[string]interface{}{ + "grant_config_type_urls": struct{}{}, + } + grantQueryMsgStr, err := json.Marshal(grantQueryMsg) + require.NoError(t, err) + + grantQueryRaw, err := ExecQuery(t, ctx, xion.GetNode(), "wasm", "contract-state", "smart", treasuryAddr, string(grantQueryMsgStr)) + require.NoError(t, err) + + grantQueryBytes, err := json.Marshal(grantQueryRaw["data"]) + require.NoError(t, err) + + var queriedGrantConfigUrls []string + err = json.Unmarshal(grantQueryBytes, &queriedGrantConfigUrls) + require.NoError(t, err) + + // Validate that all grants are in the contract state + require.Equal(t, 2, len(queriedGrantConfigUrls)) + require.Equal(t, "/cosmos.bank.v1.MsgSend", queriedGrantConfigUrls[0]) + + // Query and validate Fee Config + t.Log("Querying fee config") + feeQueryMsg := map[string]interface{}{ + "fee_config": struct{}{}, + } + feeQueryMsgStr, err := json.Marshal(feeQueryMsg) + require.NoError(t, err) + + feeQueryRaw, err := ExecQuery(t, ctx, xion.GetNode(), "wasm", "contract-state", "smart", treasuryAddr, string(feeQueryMsgStr)) + require.NoError(t, err) + + feeQueryBytes, err := json.Marshal(feeQueryRaw["data"]) + require.NoError(t, err) + + var queriedFeeConfig FeeConfig + err = json.Unmarshal(feeQueryBytes, &queriedFeeConfig) + require.NoError(t, err) + + // Validate Fee Config + require.Equal(t, "Fee allowance for user1", queriedFeeConfig.Description) + require.Equal(t, "/cosmos.feegrant.v1.BasicAllowance", queriedFeeConfig.Allowance.TypeURL) +} diff --git a/x/xion/client/cli/tx.go b/x/xion/client/cli/tx.go index 232964e8..a75ac5e7 100644 --- a/x/xion/client/cli/tx.go +++ b/x/xion/client/cli/tx.go @@ -608,12 +608,7 @@ func NewUpdateConfigsCmd() *cobra.Command { } msgs = append(msgs, feeMsg) - err = tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msgs...) - if err != nil { - return fmt.Errorf("failed to broadcast transaction: %w", err) - } - - return nil + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msgs...) }, }