github.com/Finschia/finschia-proxy/v2@v2.0.1/cli_test/cli_test.go (about)

     1  //go:build cli_test
     2  
     3  package clitest
     4  
     5  import (
     6  	"encoding/base64"
     7  	"encoding/hex"
     8  	"errors"
     9  	"fmt"
    10  	"os"
    11  	"path"
    12  	"path/filepath"
    13  	"strconv"
    14  	"strings"
    15  	"testing"
    16  	"time"
    17  
    18  	"github.com/Finschia/finschia-sdk/client/flags"
    19  	"github.com/Finschia/finschia-sdk/crypto/keys/ed25519"
    20  	sdk "github.com/Finschia/finschia-sdk/types"
    21  	"github.com/Finschia/finschia-sdk/types/tx"
    22  	gov "github.com/Finschia/finschia-sdk/x/gov/types"
    23  	minttypes "github.com/Finschia/finschia-sdk/x/mint/types"
    24  	osttypes "github.com/Finschia/ostracon/types"
    25  	"github.com/stretchr/testify/require"
    26  
    27  	"github.com/Finschia/finschia-proxy/v2/app"
    28  )
    29  
    30  func TestFnsadKeysAddMultisig(t *testing.T) {
    31  	t.Parallel()
    32  	f := InitFixtures(t)
    33  	defer f.Cleanup()
    34  
    35  	// key names order does not matter
    36  	f.KeysAdd("msig1", "--multisig-threshold=2",
    37  		fmt.Sprintf("--multisig=%s,%s", keyBar, keyBaz))
    38  
    39  	// err : trying to save same pubkey
    40  	msig1Addr := f.KeysShow("msig1").Address
    41  	f.KeysDelete("msig1")
    42  
    43  	f.KeysAdd("msig2", "--multisig-threshold=2",
    44  		fmt.Sprintf("--multisig=%s,%s", keyBaz, keyBar))
    45  	require.Equal(t, msig1Addr, f.KeysShow("msig2").Address)
    46  
    47  	f.KeysAdd("msig3", "--multisig-threshold=2",
    48  		fmt.Sprintf("--multisig=%s,%s", keyBar, keyBaz),
    49  		"--nosort")
    50  	f.KeysAdd("msig4", "--multisig-threshold=2",
    51  		fmt.Sprintf("--multisig=%s,%s", keyBaz, keyBar),
    52  		"--nosort")
    53  	require.NotEqual(t, f.KeysShow("msig3").Address, f.KeysShow("msig4").Address)
    54  }
    55  
    56  func TestFnsadMinimumFees(t *testing.T) {
    57  	t.Parallel()
    58  	f := InitFixtures(t)
    59  	defer f.Cleanup()
    60  
    61  	// start fnsad server with minimum fees
    62  	minGasPrice, err := sdk.NewDecFromStr("0.000006")
    63  	require.NoError(t, err)
    64  
    65  	fees := fmt.Sprintf(
    66  		"%s,%s",
    67  		sdk.NewDecCoinFromDec(feeDenom, minGasPrice),
    68  		sdk.NewDecCoinFromDec(fee2Denom, minGasPrice),
    69  	)
    70  
    71  	n := f.FnsadStart(fees)
    72  	defer n.Cleanup()
    73  
    74  	barAddr := f.KeyAddress(keyBar)
    75  
    76  	// Send a transaction that will get rejected
    77  	out, err := f.TxSend(keyFoo, barAddr, sdk.NewInt64Coin(fee2Denom, 10), "-y")
    78  	require.NoError(t, err)
    79  	require.Contains(t, out.String(), "insufficient fees")
    80  
    81  	err = n.WaitForNextBlock()
    82  	require.NoError(t, err)
    83  
    84  	// Ensure tx w/ correct fees pass
    85  	txFees := fmt.Sprintf("--fees=%s", sdk.NewInt64Coin(feeDenom, 2))
    86  	_, err = f.TxSend(keyFoo, barAddr, sdk.NewInt64Coin(fee2Denom, 10), txFees, "-y")
    87  	require.NoError(t, err)
    88  
    89  	err = n.WaitForNextBlock()
    90  	require.NoError(t, err)
    91  
    92  	// Ensure tx w/ improper fees fails
    93  	txFees = fmt.Sprintf("--fees=%s", sdk.NewInt64Coin(feeDenom, 1))
    94  	out, err = f.TxSend(keyFoo, barAddr, sdk.NewInt64Coin(fooDenom, 10), txFees, "-y")
    95  	require.NoError(t, err)
    96  	require.Contains(t, out.String(), "insufficient fees")
    97  }
    98  
    99  func TestFnsadGasPrices(t *testing.T) {
   100  	t.Parallel()
   101  	f := InitFixtures(t)
   102  	defer f.Cleanup()
   103  
   104  	// start fnsad server with minimum fees
   105  	minGasPrice, err := sdk.NewDecFromStr("0.000006")
   106  	require.NoError(t, err)
   107  
   108  	n := f.FnsadStart(sdk.NewDecCoinFromDec(feeDenom, minGasPrice).String())
   109  	defer n.Cleanup()
   110  
   111  	barAddr := f.KeyAddress(keyBar)
   112  
   113  	// insufficient gas prices (tx fails)
   114  	badGasPrice, err := sdk.NewDecFromStr("0.000003")
   115  	require.NoError(t, err)
   116  
   117  	out, err := f.TxSend(
   118  		keyFoo, barAddr, sdk.NewInt64Coin(fooDenom, 50),
   119  		fmt.Sprintf("--gas-prices=%s", sdk.NewDecCoinFromDec(feeDenom, badGasPrice)), "-y")
   120  	require.NoError(t, err)
   121  	require.Contains(t, out.String(), "insufficient fees")
   122  
   123  	// wait for a block confirmation
   124  	require.NoError(t, n.WaitForNextBlock())
   125  
   126  	// sufficient gas prices (tx passes)
   127  	_, err = f.TxSend(
   128  		keyFoo, barAddr, sdk.NewInt64Coin(fooDenom, 50),
   129  		fmt.Sprintf("--gas-prices=%s", sdk.NewDecCoinFromDec(feeDenom, minGasPrice)), "-y")
   130  	require.NoError(t, err)
   131  
   132  	// wait for a block confirmation
   133  	require.NoError(t, n.WaitForNextBlock())
   134  }
   135  
   136  func TestFnsadFeesDeduction(t *testing.T) {
   137  	t.Parallel()
   138  	f := InitFixtures(t)
   139  	defer f.Cleanup()
   140  
   141  	// start fnsad server with minimum fees
   142  	minGasPrice, err := sdk.NewDecFromStr("0.000006")
   143  	require.NoError(t, err)
   144  
   145  	n := f.FnsadStart(sdk.NewDecCoinFromDec(feeDenom, minGasPrice).String())
   146  	defer n.Cleanup()
   147  
   148  	// Save key addresses for later use
   149  	fooAddr := f.KeyAddress(keyFoo)
   150  	barAddr := f.KeyAddress(keyBar)
   151  
   152  	fooBal := f.QueryBalances(fooAddr)
   153  	fooAmt := fooBal.GetBalances().AmountOf(fooDenom)
   154  
   155  	// test simulation
   156  	// _, err = f.TxSend(
   157  	// 	fooAddr.String(), barAddr, sdk.NewInt64Coin(fooDenom, 1000),
   158  	// 	fmt.Sprintf("--fees=%s", sdk.NewInt64Coin(feeDenom, 2)), "--dry-run")
   159  	// require.NoError(t, err)
   160  
   161  	// Wait for a block
   162  	err = n.WaitForNextBlock()
   163  	require.NoError(t, err)
   164  
   165  	// ensure state didn't change
   166  	fooBal = f.QueryBalances(fooAddr)
   167  	require.Equal(t, fooAmt.Int64(), fooBal.GetBalances().AmountOf(fooDenom).Int64())
   168  
   169  	// insufficient funds (coins + fees) tx fails
   170  	largeCoins := sdk.TokensFromConsensusPower(10000000, sdk.DefaultPowerReduction)
   171  	out, err := f.TxSend(
   172  		keyFoo, barAddr, sdk.NewCoin(fooDenom, largeCoins),
   173  		fmt.Sprintf("--fees=%s", sdk.NewInt64Coin(feeDenom, 2)), "-y")
   174  	require.NoError(t, err)
   175  
   176  	// Wait for a block
   177  	err = n.WaitForNextBlock()
   178  	require.NoError(t, err)
   179  
   180  	resp := UnmarshalTxResponse(t, out.Bytes())
   181  	out2 := f.QueryTx(resp.TxHash)
   182  	require.Contains(t, out2.String(), "insufficient funds")
   183  
   184  	// ensure state didn't change
   185  	fooBal = f.QueryBalances(fooAddr)
   186  	require.Equal(t, fooAmt.Int64(), fooBal.GetBalances().AmountOf(fooDenom).Int64())
   187  
   188  	// test success (transfer = coins + fees)
   189  	_, err = f.TxSend(
   190  		keyFoo, barAddr, sdk.NewInt64Coin(fooDenom, 500),
   191  		fmt.Sprintf("--fees=%s", sdk.NewInt64Coin(feeDenom, 2)), "-y")
   192  	require.NoError(t, err)
   193  }
   194  
   195  func TestFnsadSend(t *testing.T) {
   196  	t.Parallel()
   197  	f := InitFixtures(t)
   198  	defer f.Cleanup()
   199  
   200  	// start fnsad server
   201  	n := f.FnsadStart(minGasPrice.String())
   202  	defer n.Cleanup()
   203  
   204  	// Save key addresses for later use
   205  	fooAddr := f.KeyAddress(keyFoo)
   206  	barAddr := f.KeyAddress(keyBar)
   207  
   208  	fooBal := f.QueryBalances(fooAddr)
   209  
   210  	fmt.Println(fooBal)
   211  
   212  	startTokens := sdk.TokensFromConsensusPower(50, sdk.DefaultPowerReduction)
   213  	fmt.Println(startTokens.Uint64())
   214  	require.Equal(t, startTokens, fooBal.GetBalances().AmountOf(denom))
   215  
   216  	// Send some tokens from one account to the other
   217  	sendTokens := sdk.TokensFromConsensusPower(10, sdk.DefaultPowerReduction)
   218  	_, err := f.TxSend(keyFoo, barAddr, sdk.NewCoin(denom, sendTokens), "-y")
   219  	require.NoError(t, err)
   220  
   221  	err = n.WaitForNextBlock()
   222  	require.NoError(t, err)
   223  
   224  	// Ensure account balances match expected
   225  	barBal := f.QueryBalances(barAddr)
   226  	require.Equal(t, sendTokens, barBal.GetBalances().AmountOf(denom))
   227  	fooBal = f.QueryBalances(fooAddr)
   228  	require.Equal(t, startTokens.Sub(sendTokens), fooBal.GetBalances().AmountOf(denom))
   229  
   230  	// Test --dry-run
   231  	// _, err = f.TxSend(fooAddr.String(), barAddr, sdk.NewCoin(denom, sendTokens), "--dry-run")
   232  	// require.NoError(t, err)
   233  
   234  	// Test --generate-only
   235  	out, err := f.TxSend(
   236  		fooAddr.String(), barAddr, sdk.NewCoin(denom, sendTokens), "--generate-only=true",
   237  	)
   238  	require.NoError(t, err)
   239  	msg := UnmarshalTx(t, out.Bytes())
   240  	require.NotZero(t, msg.GetAuthInfo().GetFee().GetGasLimit())
   241  	require.Len(t, msg.GetMsgs(), 1)
   242  	require.Len(t, msg.GetSignatures(), 0)
   243  
   244  	// Check state didn't change
   245  	fooBal = f.QueryBalances(fooAddr)
   246  	require.Equal(t, startTokens.Sub(sendTokens), fooBal.GetBalances().AmountOf(denom))
   247  
   248  	// test autosequencing
   249  	_, err = f.TxSend(keyFoo, barAddr, sdk.NewCoin(denom, sendTokens), "-y")
   250  	require.NoError(t, err)
   251  
   252  	err = n.WaitForNextBlock()
   253  	require.NoError(t, err)
   254  
   255  	// Ensure account balances match expected
   256  	barBal = f.QueryBalances(barAddr)
   257  	require.Equal(t, sendTokens.MulRaw(2), barBal.GetBalances().AmountOf(denom))
   258  	fooBal = f.QueryBalances(fooAddr)
   259  	require.Equal(t, startTokens.Sub(sendTokens.MulRaw(2)), fooBal.GetBalances().AmountOf(denom))
   260  
   261  	// test memo
   262  	_, err = f.TxSend(keyFoo, barAddr, sdk.NewCoin(denom, sendTokens), fmt.Sprintf("--%s=%s", flags.FlagNote, "testnote"), "-y")
   263  	require.NoError(t, err)
   264  
   265  	err = n.WaitForNextBlock()
   266  	require.NoError(t, err)
   267  
   268  	// Ensure account balances match expected
   269  	barBal = f.QueryBalances(barAddr)
   270  	require.Equal(t, sendTokens.MulRaw(3), barBal.GetBalances().AmountOf(denom))
   271  	fooBal = f.QueryBalances(fooAddr)
   272  	require.Equal(t, startTokens.Sub(sendTokens.MulRaw(3)), fooBal.GetBalances().AmountOf(denom))
   273  }
   274  
   275  func TestFnsadGasAuto(t *testing.T) {
   276  	t.Parallel()
   277  	f := InitFixtures(t)
   278  	defer f.Cleanup()
   279  
   280  	// start fnsad server
   281  	n := f.FnsadStart(minGasPrice.String())
   282  	defer n.Cleanup()
   283  
   284  	fooAddr := f.KeyAddress(keyFoo)
   285  	barAddr := f.KeyAddress(keyBar)
   286  
   287  	fooBal := f.QueryBalances(fooAddr)
   288  	startTokens := sdk.TokensFromConsensusPower(50, sdk.DefaultPowerReduction)
   289  	require.Equal(t, startTokens, fooBal.GetBalances().AmountOf(denom))
   290  
   291  	// Test failure with auto gas disabled and very little gas set by hand
   292  	sendTokens := sdk.TokensFromConsensusPower(10, sdk.DefaultPowerReduction)
   293  	out, err := f.TxSend(keyFoo, barAddr, sdk.NewCoin(denom, sendTokens), "--gas=10", "-y")
   294  	require.NoError(t, err)
   295  	require.Contains(t, out.String(), "out of gas in location")
   296  
   297  	// Check state didn't change
   298  	fooBal = f.QueryBalances(fooAddr)
   299  	require.Equal(t, startTokens, fooBal.GetBalances().AmountOf(denom))
   300  
   301  	// Test failure with negative gas
   302  	_, err = f.TxSend(keyFoo, barAddr, sdk.NewCoin(denom, sendTokens), "--gas=-100", "-y")
   303  	require.NoError(t, err)
   304  
   305  	// Check state didn't change
   306  	fooBal = f.QueryBalances(fooAddr)
   307  	require.Equal(t, startTokens, fooBal.GetBalances().AmountOf(denom))
   308  
   309  	// Test failure with 0 gas
   310  	out, err = f.TxSend(keyFoo, barAddr, sdk.NewCoin(denom, sendTokens), "--gas=0", "-y")
   311  	require.NoError(t, err)
   312  	require.Contains(t, out.String(), "out of gas in location")
   313  
   314  	// Check state didn't change
   315  	fooBal = f.QueryBalances(fooAddr)
   316  	require.Equal(t, startTokens, fooBal.GetBalances().AmountOf(denom))
   317  
   318  	// Enable auto gas
   319  	out, err = f.TxSend(keyFoo, barAddr, sdk.NewCoin(denom, sendTokens), "--gas=auto", "-y")
   320  	require.NoError(t, err)
   321  	cdc, _ := app.MakeCodecs()
   322  	sendResp := sdk.TxResponse{}
   323  	err = cdc.UnmarshalJSON(out.Bytes(), &sendResp)
   324  	require.Nil(t, err)
   325  	require.True(t, sendResp.GasWanted >= sendResp.GasUsed)
   326  
   327  	err = n.WaitForNextBlock()
   328  	require.NoError(t, err)
   329  
   330  	// Check state has changed accordingly
   331  	fooBal = f.QueryBalances(fooAddr)
   332  	require.Equal(t, startTokens.Sub(sendTokens), fooBal.GetBalances().AmountOf(denom))
   333  }
   334  
   335  func TestFnsadCreateValidator(t *testing.T) {
   336  	t.Parallel()
   337  	f := InitFixtures(t)
   338  	defer f.Cleanup()
   339  
   340  	// start fnsad server
   341  	n := f.FnsadStart(minGasPrice.String())
   342  	defer n.Cleanup()
   343  
   344  	barAddr := f.KeyAddress(keyBar)
   345  	barVal := sdk.ValAddress(barAddr)
   346  
   347  	cdc, _ := app.MakeCodecs()
   348  	pubKeyJSON, err := cdc.MarshalInterfaceJSON(ed25519.GenPrivKey().PubKey())
   349  	require.NoError(t, err)
   350  	consPubKey := string(pubKeyJSON)
   351  
   352  	sendTokens := sdk.TokensFromConsensusPower(10, sdk.DefaultPowerReduction)
   353  	_, err = f.TxSend(keyFoo, barAddr, sdk.NewCoin(denom, sendTokens), "-y")
   354  	require.NoError(t, err)
   355  
   356  	err = n.WaitForNextBlock()
   357  	require.NoError(t, err)
   358  
   359  	barBal := f.QueryBalances(barAddr)
   360  	require.Equal(t, sendTokens, barBal.GetBalances().AmountOf(denom))
   361  
   362  	// Generate a create validator transaction and ensure correctness
   363  	out, err := f.TxStakingCreateValidator(barAddr.String(), consPubKey, sdk.NewInt64Coin(denom, 2), "--generate-only")
   364  
   365  	require.NoError(t, err)
   366  	fmt.Println(out.String())
   367  	msg := UnmarshalTx(t, out.Bytes())
   368  	require.NotZero(t, msg.GetAuthInfo().GetFee().GetGasLimit())
   369  	require.Equal(t, len(msg.GetMsgs()), 1)
   370  	require.Equal(t, 0, len(msg.GetSignatures()))
   371  
   372  	// Test --dry-run
   373  	newValTokens := sdk.TokensFromConsensusPower(2, sdk.DefaultPowerReduction)
   374  	// _, err = f.TxStakingCreateValidator(barAddr.String(), consPubKey, sdk.NewCoin(denom, newValTokens), "--dry-run")
   375  	// require.NoError(t, err)
   376  
   377  	// grant bar to create validator
   378  	member := f.KeyAddress(keyFoo)
   379  	_, err = f.TxFoundationGrantCreateValidator([]sdk.AccAddress{member}, barAddr, "-y")
   380  	require.NoError(t, err)
   381  
   382  	err = n.WaitForNextBlock()
   383  	require.NoError(t, err)
   384  
   385  	// Create the validator
   386  	_, err = f.TxStakingCreateValidator(keyBar, consPubKey, sdk.NewCoin(denom, newValTokens), "-y")
   387  	require.NoError(t, err)
   388  
   389  	err = n.WaitForNextBlock()
   390  	require.NoError(t, err)
   391  
   392  	// Ensure funds were deducted properly
   393  	barBal = f.QueryBalances(barAddr)
   394  	require.Equal(t, sendTokens.Sub(newValTokens), barBal.GetBalances().AmountOf(denom))
   395  
   396  	// Ensure that validator state is as expected
   397  	validator := f.QueryStakingValidator(barVal)
   398  	require.Equal(t, validator.OperatorAddress, barVal.String())
   399  	require.True(sdk.IntEq(t, newValTokens, validator.Tokens))
   400  
   401  	// Query delegations to the validator
   402  	validatorDelegations := f.QueryStakingDelegationsTo(barVal)
   403  	require.Len(t, validatorDelegations.DelegationResponses, 1)
   404  	require.NotZero(t, validatorDelegations.GetDelegationResponses()[0].GetDelegation().GetShares())
   405  
   406  	// unbond a single share
   407  	unbondAmt := sdk.NewCoin(sdk.DefaultBondDenom, sdk.TokensFromConsensusPower(1, sdk.DefaultPowerReduction))
   408  	_, err = f.TxStakingUnbond(keyBar, unbondAmt.String(), barVal, "-y")
   409  	require.NoError(t, err)
   410  
   411  	err = n.WaitForNextBlock()
   412  	require.NoError(t, err)
   413  
   414  	// Ensure bonded staking is correct
   415  	remainingTokens := newValTokens.Sub(unbondAmt.Amount)
   416  	validator = f.QueryStakingValidator(barVal)
   417  	require.Equal(t, remainingTokens, validator.Tokens)
   418  
   419  	// Get unbonding delegations from the validator
   420  	validatorUbds := f.QueryStakingUnbondingDelegationsFrom(barVal)
   421  	require.Len(t, validatorUbds.GetUnbondingResponses(), 1)
   422  	require.Len(t, validatorUbds.GetUnbondingResponses()[0].Entries, 1)
   423  	require.Equal(t, remainingTokens.String(), validatorUbds.GetUnbondingResponses()[0].Entries[0].Balance.String())
   424  }
   425  
   426  func TestFnsadQuerySupply(t *testing.T) {
   427  	t.Parallel()
   428  	f := InitFixtures(t)
   429  	defer f.Cleanup()
   430  
   431  	// start fnsad server
   432  	n := f.FnsadStart(minGasPrice.String())
   433  	defer n.Cleanup()
   434  
   435  	totalSupplyOf := f.QueryTotalSupplyOf(fooDenom)
   436  
   437  	require.True(sdk.IntEq(t, TotalCoins.AmountOf(fooDenom), totalSupplyOf.Amount))
   438  }
   439  
   440  func TestFnsadSubmitProposal(t *testing.T) {
   441  	t.Parallel()
   442  	f := InitFixtures(t)
   443  	defer f.Cleanup()
   444  
   445  	// start fnsad server
   446  	n := f.FnsadStart(minGasPrice.String())
   447  	defer n.Cleanup()
   448  
   449  	f.QueryGovParamDeposit()
   450  	f.QueryGovParamVoting()
   451  	f.QueryGovParamTallying()
   452  
   453  	fooAddr := f.KeyAddress(keyFoo)
   454  
   455  	fooBal := f.QueryBalances(fooAddr)
   456  	startTokens := sdk.TokensFromConsensusPower(50, sdk.DefaultPowerReduction)
   457  	require.Equal(t, startTokens, fooBal.GetBalances().AmountOf(sdk.DefaultBondDenom))
   458  
   459  	proposalsQuery := f.QueryGovProposals()
   460  	require.Empty(t, proposalsQuery)
   461  
   462  	// Test submit generate only for submit proposal
   463  	proposalTokens := sdk.TokensFromConsensusPower(5, sdk.DefaultPowerReduction)
   464  	out, err := f.TxGovSubmitProposal(
   465  		fooAddr.String(), "Text", "Test", "test", sdk.NewCoin(denom, proposalTokens), "--generate-only", "-y")
   466  	require.NoError(t, err)
   467  	msg := UnmarshalTx(t, out.Bytes())
   468  	require.NotZero(t, msg.GetAuthInfo().GetFee().GetGasLimit())
   469  	require.Equal(t, len(msg.GetMsgs()), 1)
   470  	require.Equal(t, 0, len(msg.GetSignatures()))
   471  
   472  	// Test --dry-run
   473  	// _, err = f.TxGovSubmitProposal(fooAddr.String(), "Text", "Test", "test", sdk.NewCoin(denom, proposalTokens), "--dry-run")
   474  	// require.NoError(t, err)
   475  
   476  	// Create the proposal
   477  	_, err = f.TxGovSubmitProposal(keyFoo, "Text", "Test", "test", sdk.NewCoin(denom, proposalTokens), "-y")
   478  	require.NoError(t, err)
   479  
   480  	err = n.WaitForNextBlock()
   481  	require.NoError(t, err)
   482  
   483  	// Ensure transaction tags can be queried
   484  	searchResult := f.QueryTxs(1, 50, fmt.Sprintf("--events='message.action=%s&message.sender=%s'", sdk.MsgTypeURL(&gov.MsgSubmitProposal{}), fooAddr))
   485  	require.Len(t, searchResult.Txs, 1)
   486  
   487  	// Ensure deposit was deducted
   488  	fooBal = f.QueryBalances(fooAddr)
   489  	require.Equal(t, startTokens.Sub(proposalTokens), fooBal.GetBalances().AmountOf(denom))
   490  
   491  	// Ensure propsal is directly queryable
   492  	proposal1 := f.QueryGovProposal(1)
   493  	require.Equal(t, uint64(1), proposal1.ProposalId)
   494  	require.Equal(t, gov.StatusDepositPeriod, proposal1.Status)
   495  
   496  	// Ensure query proposals returns properly
   497  	proposalsQuery = f.QueryGovProposals()
   498  	require.Equal(t, uint64(1), proposalsQuery.GetProposals()[0].ProposalId)
   499  
   500  	// Query the deposits on the proposal
   501  	deposit := f.QueryGovDeposit(1, fooAddr)
   502  	require.Equal(t, proposalTokens, deposit.Amount.AmountOf(denom))
   503  
   504  	// Test deposit generate only
   505  	depositTokens := sdk.TokensFromConsensusPower(10, sdk.DefaultPowerReduction)
   506  	out, err = f.TxGovDeposit(1, fooAddr.String(), sdk.NewCoin(denom, depositTokens), "--generate-only")
   507  	require.NoError(t, err)
   508  	msg = UnmarshalTx(t, out.Bytes())
   509  	require.NotZero(t, msg.GetAuthInfo().GetFee().GetGasLimit())
   510  	require.Equal(t, len(msg.GetMsgs()), 1)
   511  	require.Equal(t, 0, len(msg.GetSignatures()))
   512  
   513  	// Run the deposit transaction
   514  	_, err = f.TxGovDeposit(1, keyFoo, sdk.NewCoin(denom, depositTokens), "-y")
   515  	require.NoError(t, err)
   516  
   517  	err = n.WaitForNextBlock()
   518  	require.NoError(t, err)
   519  
   520  	// test query deposit
   521  	deposits := f.QueryGovDeposits(1)
   522  	require.Len(t, deposits.GetDeposits(), 1)
   523  	require.Equal(t, proposalTokens.Add(depositTokens), deposits.GetDeposits()[0].Amount.AmountOf(denom))
   524  
   525  	// Ensure querying the deposit returns the proper amount
   526  	deposit = f.QueryGovDeposit(1, fooAddr)
   527  	require.Equal(t, proposalTokens.Add(depositTokens), deposit.Amount.AmountOf(denom))
   528  
   529  	// Ensure tags are set on the transaction
   530  	searchResult = f.QueryTxs(1, 50, fmt.Sprintf("--events='message.action=%s&message.sender=%s'", sdk.MsgTypeURL(&gov.MsgDeposit{}), fooAddr))
   531  	require.Len(t, searchResult.Txs, 1)
   532  
   533  	// Ensure account has expected amount of funds
   534  	fooBal = f.QueryBalances(fooAddr)
   535  	require.Equal(t, startTokens.Sub(proposalTokens.Add(depositTokens)), fooBal.GetBalances().AmountOf(denom))
   536  
   537  	// Fetch the proposal and ensure it is now in the voting period
   538  	proposal1 = f.QueryGovProposal(1)
   539  	require.Equal(t, uint64(1), proposal1.ProposalId)
   540  	require.Equal(t, gov.StatusVotingPeriod, proposal1.Status)
   541  
   542  	// Test vote generate only
   543  	out, err = f.TxGovVote(1, gov.OptionYes, fooAddr.String(), "--generate-only")
   544  	require.NoError(t, err)
   545  	msg = UnmarshalTx(t, out.Bytes())
   546  	require.NotZero(t, msg.GetAuthInfo().GetFee().GetGasLimit())
   547  	require.Equal(t, len(msg.GetMsgs()), 1)
   548  	require.Equal(t, 0, len(msg.GetSignatures()))
   549  
   550  	// Vote on the proposal
   551  	_, err = f.TxGovVote(1, gov.OptionYes, keyFoo, "-y")
   552  	require.NoError(t, err)
   553  
   554  	err = n.WaitForNextBlock()
   555  	require.NoError(t, err)
   556  
   557  	// Query the vote
   558  	vote := f.QueryGovVote(1, fooAddr)
   559  	require.Equal(t, uint64(1), vote.ProposalId)
   560  	require.Equal(t, 1, len(vote.Options))
   561  	require.Equal(t, gov.OptionYes, vote.Options[0].Option)
   562  
   563  	// Query the votes
   564  	votes := f.QueryGovVotes(1)
   565  	require.Len(t, votes.GetVotes(), 1)
   566  	require.Equal(t, uint64(1), votes.GetVotes()[0].ProposalId)
   567  	require.Equal(t, 1, len(votes.GetVotes()[0].Options))
   568  	require.Equal(t, gov.OptionYes, votes.GetVotes()[0].Options[0].Option)
   569  
   570  	// Ensure tags are applied to voting transaction properly
   571  	searchResult = f.QueryTxs(1, 50, fmt.Sprintf("--events='message.action=%s&message.sender=%s'", sdk.MsgTypeURL(&gov.MsgVote{}), fooAddr))
   572  	require.Len(t, searchResult.Txs, 1)
   573  
   574  	// Ensure no proposals in deposit period
   575  	proposalsQuery = f.QueryGovProposals("--status=DepositPeriod")
   576  	require.Empty(t, proposalsQuery)
   577  
   578  	// Ensure the proposal returns as in the voting period
   579  	proposalsQuery = f.QueryGovProposals("--status=VotingPeriod")
   580  	require.Equal(t, uint64(1), proposalsQuery.GetProposals()[0].ProposalId)
   581  
   582  	// submit a second test proposal
   583  	_, err = f.TxGovSubmitProposal(keyFoo, "Text", "Apples", "test", sdk.NewCoin(denom, proposalTokens), "-y")
   584  	require.NoError(t, err)
   585  
   586  	err = n.WaitForNextBlock()
   587  	require.NoError(t, err)
   588  
   589  	// Test limit on proposals query
   590  	proposalsQuery = f.QueryGovProposals("--limit=2")
   591  	require.Equal(t, uint64(2), proposalsQuery.GetProposals()[1].ProposalId)
   592  }
   593  
   594  func TestFnsadSubmitParamChangeProposal(t *testing.T) {
   595  	t.Parallel()
   596  	f := InitFixtures(t)
   597  	defer f.Cleanup()
   598  
   599  	n := f.FnsadStart(minGasPrice.String())
   600  	defer n.Cleanup()
   601  
   602  	fooAddr := f.KeyAddress(keyFoo)
   603  	fooBal := f.QueryBalances(fooAddr)
   604  	startTokens := sdk.TokensFromConsensusPower(50, sdk.DefaultPowerReduction)
   605  	require.Equal(t, startTokens, fooBal.GetBalances().AmountOf(sdk.DefaultBondDenom))
   606  
   607  	// write proposal to file
   608  	proposalTokens := sdk.TokensFromConsensusPower(5, sdk.DefaultPowerReduction)
   609  
   610  	proposal := fmt.Sprintf(`{
   611  "title": "Param Change",
   612  "description": "Update max validators",
   613  "type": "Text",
   614  "deposit": "%sstake"
   615  }`, proposalTokens.String())
   616  
   617  	proposalFile := WriteToNewTempFile(t, proposal)
   618  
   619  	// create the param change proposal
   620  	out, err := f.TxGovSubmitParamChangeProposal(keyFoo, proposalFile.Name(), "-y")
   621  	fmt.Println(out.String())
   622  	require.NoError(t, err)
   623  
   624  	err = n.WaitForNextBlock()
   625  	require.NoError(t, err)
   626  
   627  	// ensure transaction tags can be queried
   628  	txsPage := f.QueryTxs(1, 50, fmt.Sprintf("--events='message.action=%s&message.sender=%s'", sdk.MsgTypeURL(&gov.MsgSubmitProposal{}), fooAddr))
   629  	require.Len(t, txsPage.Txs, 1)
   630  
   631  	// ensure deposit was deducted
   632  	fooBal = f.QueryBalances(fooAddr)
   633  	require.Equal(t, startTokens.Sub(proposalTokens).String(), fooBal.GetBalances().AmountOf(sdk.DefaultBondDenom).String())
   634  
   635  	// ensure proposal is directly queryable
   636  	proposal1 := f.QueryGovProposal(1)
   637  	require.Equal(t, uint64(1), proposal1.ProposalId)
   638  	require.Equal(t, gov.StatusDepositPeriod, proposal1.Status)
   639  
   640  	// ensure correct query proposals result
   641  	proposalsQuery := f.QueryGovProposals()
   642  	require.Equal(t, uint64(1), proposalsQuery.GetProposals()[0].ProposalId)
   643  
   644  	// ensure the correct deposit amount on the proposal
   645  	deposit := f.QueryGovDeposit(1, fooAddr)
   646  	require.Equal(t, proposalTokens, deposit.Amount.AmountOf(denom))
   647  }
   648  
   649  func TestFnsadSubmitCommunityPoolSpendProposal(t *testing.T) {
   650  	t.Skip("Due to removing mint module")
   651  	t.Parallel()
   652  	f := InitFixtures(t)
   653  	defer f.Cleanup()
   654  
   655  	// create some inflation
   656  	var cdc, amino = app.MakeCodecs()
   657  	genesisState := f.GenesisState()
   658  	inflationMin := sdk.MustNewDecFromStr("10000.0")
   659  	var mintData minttypes.GenesisState
   660  	err := cdc.UnmarshalJSON(genesisState[minttypes.ModuleName], &mintData)
   661  	require.NoError(t, err)
   662  
   663  	mintData.Minter.Inflation = inflationMin
   664  	mintData.Params.InflationMin = inflationMin
   665  	mintData.Params.InflationMax = sdk.MustNewDecFromStr("15000.0")
   666  	mintDataBz, err := cdc.MarshalJSON(&mintData)
   667  	require.NoError(t, err)
   668  	genesisState[minttypes.ModuleName] = mintDataBz
   669  
   670  	genFile := filepath.Join(f.Home, "config", "genesis.json")
   671  	genDoc, err := osttypes.GenesisDocFromFile(genFile)
   672  	require.NoError(t, err)
   673  	genDoc.AppState, err = amino.MarshalJSON(genesisState)
   674  	require.NoError(t, err)
   675  	require.NoError(t, genDoc.SaveAs(genFile))
   676  
   677  	n := f.FnsadStart("")
   678  	defer n.Cleanup()
   679  
   680  	fooAddr := f.KeyAddress(keyFoo)
   681  	fooBal := f.QueryBalances(fooAddr)
   682  	startTokens := sdk.TokensFromConsensusPower(50, sdk.DefaultPowerReduction)
   683  	require.Equal(t, startTokens, fooBal.GetBalances().AmountOf(sdk.DefaultBondDenom))
   684  
   685  	err = n.WaitForNextBlock()
   686  	require.NoError(t, err)
   687  
   688  	// write proposal to file
   689  	proposalTokens := sdk.TokensFromConsensusPower(5, sdk.DefaultPowerReduction)
   690  
   691  	proposal := fmt.Sprintf(`{
   692  "title": "Community Pool Spend",
   693  "description": "Spend from community pool",
   694  "type": "Text"
   695  "deposit": "%s%s"
   696  }
   697  `, sdk.DefaultBondDenom, proposalTokens.String())
   698  
   699  	proposalFile := WriteToNewTempFile(t, proposal)
   700  
   701  	// create the param change proposal
   702  	_, err = f.TxGovSubmitCommunityPoolSpendProposal(keyFoo, proposalFile.Name(), sdk.NewCoin(denom, proposalTokens), "-y")
   703  	require.NoError(t, err)
   704  
   705  	err = n.WaitForNextBlock()
   706  	require.NoError(t, err)
   707  
   708  	// ensure transaction tags can be queried
   709  	txsPage := f.QueryTxs(1, 50, fmt.Sprintf("--events='message.action=%s&message.sender=%s'", sdk.MsgTypeURL(&gov.MsgSubmitProposal{}), fooAddr))
   710  	require.Len(t, txsPage.Txs, 1)
   711  
   712  	// ensure deposit was deducted
   713  	fooBal = f.QueryBalances(fooAddr)
   714  	require.Equal(t, startTokens.Sub(proposalTokens).String(), fooBal.GetBalances().AmountOf(sdk.DefaultBondDenom).String())
   715  
   716  	// ensure proposal is directly queryable
   717  	proposal1 := f.QueryGovProposal(1)
   718  	require.Equal(t, uint64(1), proposal1.ProposalId)
   719  	require.Equal(t, gov.StatusDepositPeriod, proposal1.Status)
   720  
   721  	// ensure correct query proposals result
   722  	proposalsQuery := f.QueryGovProposals()
   723  	require.Equal(t, uint64(1), proposalsQuery.GetProposals()[0].ProposalId)
   724  
   725  	// ensure the correct deposit amount on the proposal
   726  	deposit := f.QueryGovDeposit(1, fooAddr)
   727  	require.Equal(t, proposalTokens, deposit.Amount.AmountOf(denom))
   728  }
   729  
   730  func TestFnsadQueryTxPagination(t *testing.T) {
   731  	t.Parallel()
   732  	f := InitFixtures(t)
   733  	defer f.Cleanup()
   734  
   735  	// start fnsad server
   736  	n := f.FnsadStart(minGasPrice.String())
   737  	defer n.Cleanup()
   738  
   739  	fooAddr := f.KeyAddress(keyFoo)
   740  	barAddr := f.KeyAddress(keyBar)
   741  
   742  	accFoo := f.QueryAccount(fooAddr)
   743  	seq := accFoo.GetSequence()
   744  
   745  	for i := 1; i <= 4; i++ {
   746  		_, err := f.TxSend(keyFoo, barAddr, sdk.NewInt64Coin(fooDenom, int64(i)), fmt.Sprintf("--sequence=%d", seq), "-y")
   747  		require.NoError(t, err)
   748  		seq++
   749  	}
   750  	err := n.WaitForNextBlock()
   751  	require.NoError(t, err)
   752  
   753  	// perPage = 15, 2 pages
   754  	txsPage1 := f.QueryTxs(1, 2, fmt.Sprintf("--events='message.sender=%s'", fooAddr))
   755  	require.Len(t, txsPage1.Txs, 2)
   756  	require.Equal(t, txsPage1.Count, uint64(2))
   757  	txsPage2 := f.QueryTxs(2, 2, fmt.Sprintf("--events='message.sender=%s'", fooAddr))
   758  	require.Len(t, txsPage2.Txs, 2)
   759  	require.NotEqual(t, txsPage1.Txs, txsPage2.Txs)
   760  
   761  	// perPage = 16, 2 pages
   762  	txsPage1 = f.QueryTxs(1, 3, fmt.Sprintf("--events='message.sender=%s'", fooAddr))
   763  	require.Len(t, txsPage1.Txs, 3)
   764  	txsPage2 = f.QueryTxs(2, 3, fmt.Sprintf("--events='message.sender=%s'", fooAddr))
   765  	require.Len(t, txsPage2.Txs, 1)
   766  	require.NotEqual(t, txsPage1.Txs, txsPage2.Txs)
   767  
   768  	// perPage = 50
   769  	txsPageFull := f.QueryTxs(1, 50, fmt.Sprintf("--events='message.sender=%s'", fooAddr))
   770  	require.Len(t, txsPageFull.Txs, 4)
   771  	require.Equal(t, txsPageFull.Txs, append(txsPage1.Txs, txsPage2.Txs...))
   772  
   773  	// perPage = 0
   774  	f.QueryTxsInvalid(errors.New("page must greater than 0"), 0, 50, fmt.Sprintf("--events='message.sender=%s'", fooAddr))
   775  
   776  	// limit = 0
   777  	f.QueryTxsInvalid(errors.New("limit must greater than 0"), 1, 0, fmt.Sprintf("--events='message.sender=%s'", fooAddr))
   778  
   779  	// no events
   780  	f.QueryTxsInvalid(errors.New("required flag(s) \"events\" not set"), 1, 30)
   781  }
   782  
   783  func TestFnsadValidateSignatures(t *testing.T) {
   784  	t.Skip("no flag validate-signatures")
   785  	t.Parallel()
   786  	f := InitFixtures(t)
   787  	defer f.Cleanup()
   788  
   789  	// start fnsad server
   790  	n := f.FnsadStart("")
   791  	defer n.Cleanup()
   792  
   793  	fooAddr := f.KeyAddress(keyFoo)
   794  	barAddr := f.KeyAddress(keyBar)
   795  
   796  	// generate sendTx with default gas
   797  	out, err := f.TxSend(fooAddr.String(), barAddr, sdk.NewInt64Coin(denom, 10), "--generate-only")
   798  	require.NoError(t, err)
   799  
   800  	// write  unsigned tx to file
   801  	unsignedTxFile := WriteToNewTempFile(t, out.String())
   802  	defer os.Remove(unsignedTxFile.Name())
   803  
   804  	// validate we can successfully sign
   805  	out, err = f.TxSign(keyFoo, unsignedTxFile.Name())
   806  	require.NoError(t, err)
   807  	stdTx := UnmarshalTx(t, out.Bytes())
   808  	require.Equal(t, len(stdTx.GetMsgs()), 1)
   809  	require.Equal(t, 1, len(stdTx.GetSignatures()))
   810  	require.Equal(t, fooAddr.String(), stdTx.GetSigners()[0].String())
   811  
   812  	// write signed tx to file
   813  	signedTxFile := WriteToNewTempFile(t, out.String())
   814  	defer os.Remove(signedTxFile.Name())
   815  
   816  	// validate signatures
   817  	_, err = f.TxSign(keyFoo, signedTxFile.Name(), "--validate-signatures")
   818  	require.NoError(t, err)
   819  
   820  	// modify the transaction
   821  	stdTx.Body.Memo = "MODIFIED-ORIGINAL-TX-BAD"
   822  	bz := MarshalTx(t, stdTx)
   823  	modSignedTxFile := WriteToNewTempFile(t, string(bz))
   824  	defer os.Remove(modSignedTxFile.Name())
   825  
   826  	// validate signature validation failure due to different transaction sig bytes
   827  	_, err = f.TxSign(keyFoo, modSignedTxFile.Name(), "--validate-signatures")
   828  	require.Error(t, err)
   829  }
   830  
   831  func TestFnsadSendGenerateSignAndBroadcast(t *testing.T) {
   832  	t.Parallel()
   833  	f := InitFixtures(t)
   834  	defer f.Cleanup()
   835  
   836  	// start fnsad server
   837  	n := f.FnsadStart(minGasPrice.String())
   838  	defer n.Cleanup()
   839  
   840  	fooAddr := f.KeyAddress(keyFoo)
   841  	barAddr := f.KeyAddress(keyBar)
   842  
   843  	// Test generate sendTx with default gas
   844  	sendTokens := sdk.TokensFromConsensusPower(10, sdk.DefaultPowerReduction)
   845  	out, err := f.TxSend(fooAddr.String(), barAddr, sdk.NewCoin(denom, sendTokens), "--generate-only")
   846  	require.NoError(t, err)
   847  	msg := UnmarshalTx(t, out.Bytes())
   848  	require.Equal(t, msg.GetAuthInfo().GetFee().GetGasLimit(), uint64(flags.DefaultGasLimit))
   849  	require.Equal(t, len(msg.GetMsgs()), 1)
   850  	require.Equal(t, 0, len(msg.GetSignatures()))
   851  
   852  	// Test generate sendTx with --gas=$amount
   853  	out, err = f.TxSend(fooAddr.String(), barAddr, sdk.NewCoin(denom, sendTokens), "--gas=100", "--generate-only")
   854  	require.NoError(t, err)
   855  	msg = UnmarshalTx(t, out.Bytes())
   856  	require.Equal(t, msg.GetAuthInfo().GetFee().GetGasLimit(), uint64(100))
   857  	require.Equal(t, len(msg.GetMsgs()), 1)
   858  	require.Equal(t, 0, len(msg.GetSignatures()))
   859  
   860  	// Test generate sendTx, estimate gas
   861  	out, err = f.TxSend(fooAddr.String(), barAddr, sdk.NewCoin(denom, sendTokens), "--generate-only")
   862  	require.NoError(t, err)
   863  	msg = UnmarshalTx(t, out.Bytes())
   864  	require.True(t, msg.GetAuthInfo().GetFee().GetGasLimit() > 0)
   865  	require.Equal(t, len(msg.GetMsgs()), 1)
   866  
   867  	// Write the output to disk
   868  	unsignedTxFile := WriteToNewTempFile(t, out.String())
   869  	defer os.Remove(unsignedTxFile.Name())
   870  
   871  	// Test sign
   872  	out, err = f.TxSign(keyFoo, unsignedTxFile.Name())
   873  	require.NoError(t, err)
   874  	msg = UnmarshalTx(t, out.Bytes())
   875  	require.Equal(t, len(msg.GetMsgs()), 1)
   876  	require.Equal(t, 1, len(msg.GetSignatures()))
   877  	require.Equal(t, fooAddr.String(), msg.GetSigners()[0].String())
   878  
   879  	// Write the output to disk
   880  	signedTxFile := WriteToNewTempFile(t, out.String())
   881  	defer os.Remove(signedTxFile.Name())
   882  
   883  	// Ensure foo has right amount of funds
   884  	fooBal := f.QueryBalances(fooAddr)
   885  	startTokens := sdk.TokensFromConsensusPower(50, sdk.DefaultPowerReduction)
   886  	require.Equal(t, startTokens, fooBal.GetBalances().AmountOf(denom))
   887  
   888  	// Test broadcast
   889  	_, err = f.TxBroadcast(signedTxFile.Name())
   890  	require.NoError(t, err)
   891  
   892  	err = n.WaitForNextBlock()
   893  	require.NoError(t, err)
   894  
   895  	// Ensure account state
   896  	barBal := f.QueryBalances(barAddr)
   897  	fooBal = f.QueryBalances(fooAddr)
   898  	require.Equal(t, sendTokens, barBal.GetBalances().AmountOf(denom))
   899  	require.Equal(t, startTokens.Sub(sendTokens), fooBal.GetBalances().AmountOf(denom))
   900  }
   901  
   902  func TestFnsadMultisignInsufficientCosigners(t *testing.T) {
   903  	t.Parallel()
   904  	f := InitFixtures(t)
   905  	defer f.Cleanup()
   906  
   907  	// start fnsad server with minimum fees
   908  	n := f.FnsadStart(minGasPrice.String())
   909  	defer n.Cleanup()
   910  
   911  	fooBarBazAddr := f.KeyAddress(keyFooBarBaz)
   912  	barAddr := f.KeyAddress(keyBar)
   913  
   914  	// Send some tokens from one account to the other
   915  	_, err := f.TxSend(keyFoo, fooBarBazAddr, sdk.NewInt64Coin(denom, 10), "-y")
   916  	require.NoError(t, err)
   917  
   918  	err = n.WaitForNextBlock()
   919  	require.NoError(t, err)
   920  
   921  	// Test generate sendTx with multisig
   922  	out, err := f.TxSend(fooBarBazAddr.String(), barAddr, sdk.NewInt64Coin(denom, 5), "--generate-only")
   923  	require.NoError(t, err)
   924  
   925  	// Write the output to disk
   926  	unsignedTxFile := WriteToNewTempFile(t, out.String())
   927  	defer os.Remove(unsignedTxFile.Name())
   928  
   929  	// Sign with foo's key
   930  	out, err = f.TxSign(keyFoo, unsignedTxFile.Name(), "--multisig", fooBarBazAddr.String(), "-y")
   931  	require.NoError(t, err)
   932  
   933  	// Write the output to disk
   934  	fooSignatureFile := WriteToNewTempFile(t, out.String())
   935  	defer os.Remove(fooSignatureFile.Name())
   936  
   937  	// Multisign, not enough signatures
   938  	out, err = f.TxMultisign(unsignedTxFile.Name(), keyFooBarBaz, []string{fooSignatureFile.Name()})
   939  	require.NoError(t, err)
   940  
   941  	// Write the output to disk
   942  	signedTxFile := WriteToNewTempFile(t, out.String())
   943  	defer os.Remove(signedTxFile.Name())
   944  
   945  	// Validate the multisignature
   946  	_, err = f.TxSign(keyFooBarBaz, signedTxFile.Name(), "--validate-signatures")
   947  	require.Error(t, err)
   948  
   949  	// Broadcast the transaction
   950  	out, err = f.TxBroadcast(signedTxFile.Name())
   951  	require.NoError(t, err)
   952  	require.NotNil(t, out)
   953  	require.Contains(t, out.String(), "signature verification failed")
   954  }
   955  
   956  func TestFnsadEncode(t *testing.T) {
   957  	t.Parallel()
   958  	f := InitFixtures(t)
   959  	defer f.Cleanup()
   960  
   961  	// start fnsad server
   962  	n := f.FnsadStart(minGasPrice.String())
   963  	defer n.Cleanup()
   964  
   965  	cdc, _ := app.MakeCodecs()
   966  
   967  	// Build a testing transaction and write it to disk
   968  	barAddr := f.KeyAddress(keyBar)
   969  	keyAddr := f.KeyAddress(keyFoo)
   970  
   971  	sendTokens := sdk.TokensFromConsensusPower(10, sdk.DefaultPowerReduction)
   972  	out, err := f.TxSend(keyAddr.String(), barAddr, sdk.NewCoin(denom, sendTokens), "--generate-only", fmt.Sprintf("--%s=%s", flags.FlagNote, "deadbeef"))
   973  	require.NoError(t, err)
   974  
   975  	// Write it to disk
   976  	jsonTxFile := WriteToNewTempFile(t, out.String())
   977  	defer os.Remove(jsonTxFile.Name())
   978  
   979  	// Run the encode command, and trim the extras from the stdout capture
   980  	base64Encoded, err := f.TxEncode(jsonTxFile.Name())
   981  	require.NoError(t, err)
   982  	trimmedBase64 := strings.Trim(base64Encoded.String(), "\"\n")
   983  	// Decode the base64
   984  	decodedBytes, err := base64.StdEncoding.DecodeString(trimmedBase64)
   985  	require.Nil(t, err)
   986  
   987  	// Check that the transaction decodes as expected
   988  	var decodedTx tx.Tx
   989  	require.Nil(t, cdc.Unmarshal(decodedBytes, &decodedTx))
   990  	require.Equal(t, "deadbeef", decodedTx.GetBody().GetMemo())
   991  }
   992  
   993  func TestFnsadMultisignSortSignatures(t *testing.T) {
   994  	t.Parallel()
   995  	f := InitFixtures(t)
   996  	defer f.Cleanup()
   997  
   998  	// start fnsad server with minimum fees
   999  	n := f.FnsadStart(minGasPrice.String())
  1000  	defer n.Cleanup()
  1001  
  1002  	fooBarBazAddr := f.KeyAddress(keyFooBarBaz)
  1003  	barAddr := f.KeyAddress(keyBar)
  1004  
  1005  	// Send some tokens from one account to the other
  1006  	_, err := f.TxSend(keyFoo, fooBarBazAddr, sdk.NewInt64Coin(denom, 10), "-y")
  1007  	require.NoError(t, err)
  1008  
  1009  	err = n.WaitForNextBlock()
  1010  	require.NoError(t, err)
  1011  
  1012  	// Ensure account balances match expected
  1013  	fooBarBazBal := f.QueryBalances(fooBarBazAddr)
  1014  	require.Equal(t, int64(10), fooBarBazBal.GetBalances().AmountOf(denom).Int64())
  1015  
  1016  	// Test generate sendTx with multisig
  1017  	out, err := f.TxSend(fooBarBazAddr.String(), barAddr, sdk.NewInt64Coin(denom, 5), "--generate-only")
  1018  	require.NoError(t, err)
  1019  
  1020  	// Write the output to disk
  1021  	unsignedTxFile := WriteToNewTempFile(t, out.String())
  1022  	defer os.Remove(unsignedTxFile.Name())
  1023  
  1024  	// Sign with foo's key
  1025  	out, err = f.TxSign(keyFoo, unsignedTxFile.Name(), "--multisig", fooBarBazAddr.String())
  1026  	require.NoError(t, err)
  1027  
  1028  	// Write the output to disk
  1029  	fooSignatureFile := WriteToNewTempFile(t, out.String())
  1030  	defer os.Remove(fooSignatureFile.Name())
  1031  
  1032  	// Sign with baz's key
  1033  	out, err = f.TxSign(keyBaz, unsignedTxFile.Name(), "--multisig", fooBarBazAddr.String())
  1034  	require.NoError(t, err)
  1035  
  1036  	// Write the output to disk
  1037  	bazSignatureFile := WriteToNewTempFile(t, out.String())
  1038  	defer os.Remove(bazSignatureFile.Name())
  1039  
  1040  	// Multisign, keys in different order
  1041  	out, err = f.TxMultisign(unsignedTxFile.Name(), keyFooBarBaz, []string{
  1042  		bazSignatureFile.Name(), fooSignatureFile.Name()})
  1043  	require.NoError(t, err)
  1044  
  1045  	// Write the output to disk
  1046  	signedTxFile := WriteToNewTempFile(t, out.String())
  1047  	defer os.Remove(signedTxFile.Name())
  1048  
  1049  	// Broadcast the transaction
  1050  	_, err = f.TxBroadcast(signedTxFile.Name())
  1051  	require.NoError(t, err)
  1052  }
  1053  
  1054  func TestFnsadMultisign(t *testing.T) {
  1055  	t.Parallel()
  1056  	f := InitFixtures(t)
  1057  	defer f.Cleanup()
  1058  
  1059  	// start fnsad server with minimum fees
  1060  	n := f.FnsadStart(minGasPrice.String())
  1061  	defer n.Cleanup()
  1062  
  1063  	fooBarBazAddr := f.KeyAddress(keyFooBarBaz)
  1064  	bazAddr := f.KeyAddress(keyBaz)
  1065  
  1066  	// Send some tokens from one account to the other
  1067  	_, err := f.TxSend(keyFoo, fooBarBazAddr, sdk.NewInt64Coin(denom, 10), "-y")
  1068  	require.NoError(t, err)
  1069  
  1070  	err = n.WaitForNextBlock()
  1071  	require.NoError(t, err)
  1072  
  1073  	// Ensure account balances match expected
  1074  	fooBarBazBal := f.QueryBalances(fooBarBazAddr)
  1075  	require.Equal(t, int64(10), fooBarBazBal.GetBalances().AmountOf(denom).Int64())
  1076  
  1077  	// Test generate sendTx with multisig
  1078  	out, err := f.TxSend(fooBarBazAddr.String(), bazAddr, sdk.NewInt64Coin(denom, 10), "--generate-only")
  1079  	require.NoError(t, err)
  1080  
  1081  	// Write the output to disk
  1082  	unsignedTxFile := WriteToNewTempFile(t, out.String())
  1083  	defer os.Remove(unsignedTxFile.Name())
  1084  
  1085  	// Sign with foo's key
  1086  	out, err = f.TxSign(keyFoo, unsignedTxFile.Name(), "--multisig", fooBarBazAddr.String(), "-y")
  1087  	require.NoError(t, err)
  1088  
  1089  	// Write the output to disk
  1090  	fooSignatureFile := WriteToNewTempFile(t, out.String())
  1091  	defer os.Remove(fooSignatureFile.Name())
  1092  
  1093  	// Sign with bar's key
  1094  	out, err = f.TxSign(keyBar, unsignedTxFile.Name(), "--multisig", fooBarBazAddr.String(), "-y")
  1095  	require.NoError(t, err)
  1096  
  1097  	// Write the output to disk
  1098  	barSignatureFile := WriteToNewTempFile(t, out.String())
  1099  	defer os.Remove(barSignatureFile.Name())
  1100  
  1101  	// Multisign
  1102  	out, err = f.TxMultisign(unsignedTxFile.Name(), keyFooBarBaz, []string{
  1103  		fooSignatureFile.Name(), barSignatureFile.Name()})
  1104  	require.NoError(t, err)
  1105  
  1106  	// Write the output to disk
  1107  	signedTxFile := WriteToNewTempFile(t, out.String())
  1108  	defer os.Remove(signedTxFile.Name())
  1109  
  1110  	// Broadcast the transaction
  1111  	_, err = f.TxBroadcast(signedTxFile.Name())
  1112  	require.NoError(t, err)
  1113  }
  1114  
  1115  func TestFnsadCollectGentxs(t *testing.T) {
  1116  	t.Parallel()
  1117  	var customMaxBytes, customMaxGas int64 = 99999999, 1234567
  1118  	f := NewFixtures(t, getHomeDir(t))
  1119  
  1120  	// Initialize temporary directories
  1121  	gentxDir, err := os.MkdirTemp("", "")
  1122  	gentxDoc := filepath.Join(gentxDir, "gentx.json")
  1123  	require.NoError(t, err)
  1124  
  1125  	defer f.Cleanup(gentxDir)
  1126  
  1127  	// Initialize keys
  1128  	f.KeysAdd(keyFoo)
  1129  
  1130  	// Run init
  1131  	f.FnsadInit(keyFoo)
  1132  
  1133  	// Customize genesis.json
  1134  	genFile := f.GenesisFile()
  1135  	genDoc, err := osttypes.GenesisDocFromFile(genFile)
  1136  	require.NoError(t, err)
  1137  	genDoc.ConsensusParams.Block.MaxBytes = customMaxBytes
  1138  	genDoc.ConsensusParams.Block.MaxGas = customMaxGas
  1139  	err = genDoc.SaveAs(genFile)
  1140  	require.NoError(t, err)
  1141  
  1142  	// Add account to genesis.json
  1143  	f.AddGenesisAccount(f.KeyAddress(keyFoo), startCoins)
  1144  
  1145  	// Write gentx file
  1146  	f.GenTx(keyFoo, fmt.Sprintf("--output-document=%s", gentxDoc))
  1147  
  1148  	// Collect gentxs from a custom directory
  1149  	f.CollectGenTxs(fmt.Sprintf("--gentx-dir=%s", gentxDir))
  1150  
  1151  	genDoc, err = osttypes.GenesisDocFromFile(genFile)
  1152  	require.NoError(t, err)
  1153  	require.Equal(t, genDoc.ConsensusParams.Block.MaxBytes, customMaxBytes)
  1154  	require.Equal(t, genDoc.ConsensusParams.Block.MaxGas, customMaxGas)
  1155  }
  1156  
  1157  func TestValidateGenesis(t *testing.T) {
  1158  	t.Parallel()
  1159  	f := InitFixtures(t)
  1160  	defer f.Cleanup()
  1161  
  1162  	// start fnsad server
  1163  	n := f.FnsadStart(minGasPrice.String())
  1164  	defer n.Cleanup()
  1165  
  1166  	f.ValidateGenesis(filepath.Join(f.Home, "config", "genesis.json"))
  1167  }
  1168  
  1169  func TestFnsadIncrementSequenceDecorator(t *testing.T) {
  1170  	t.Parallel()
  1171  	f := InitFixtures(t)
  1172  	defer f.Cleanup()
  1173  
  1174  	// start fnsad server
  1175  	n := f.FnsadStart(minGasPrice.String())
  1176  	defer n.Cleanup()
  1177  
  1178  	fooAddr := f.KeyAddress(keyFoo)
  1179  	barAddr := f.KeyAddress(keyBar)
  1180  
  1181  	sendTokens := sdk.TokensFromConsensusPower(1, sdk.DefaultPowerReduction)
  1182  
  1183  	time.Sleep(3 * time.Second)
  1184  
  1185  	fooAcc := f.QueryAccount(fooAddr)
  1186  
  1187  	// Prepare signed Tx
  1188  	signedTxFiles := make([]*os.File, 0)
  1189  	for idx := 0; idx < 3; idx++ {
  1190  		// Test generate sendTx, estimate gas
  1191  		out, err := f.TxSend(fooAddr.String(), barAddr, sdk.NewCoin(denom, sendTokens), "--generate-only")
  1192  		require.NoError(t, err)
  1193  
  1194  		// Write the output to disk
  1195  		unsignedTxFile := WriteToNewTempFile(t, out.String())
  1196  		defer os.Remove(unsignedTxFile.Name())
  1197  
  1198  		// Test sign
  1199  		out, err = f.TxSign(keyFoo, unsignedTxFile.Name(), "--offline", fmt.Sprintf("--%s=%d", flags.FlagAccountNumber, fooAcc.AccountNumber), "--sequence", strconv.Itoa(int(fooAcc.Sequence)+idx))
  1200  		require.NoError(t, err)
  1201  
  1202  		// Write the output to disk
  1203  		signedTxFile := WriteToNewTempFile(t, out.String())
  1204  		signedTxFiles = append(signedTxFiles, signedTxFile)
  1205  		defer os.Remove(signedTxFile.Name())
  1206  	}
  1207  	// Wait for a new block
  1208  	err := n.WaitForNextBlock()
  1209  	require.NoError(t, err)
  1210  
  1211  	txHashes := make([]string, 0)
  1212  	// Broadcast the signed Txs
  1213  	for _, signedTxFile := range signedTxFiles {
  1214  		// Test broadcast
  1215  		out, err := f.TxBroadcast(signedTxFile.Name(), "--broadcast-mode", "sync")
  1216  		require.NoError(t, err)
  1217  		sendResp := UnmarshalTxResponse(t, out.Bytes())
  1218  		txHashes = append(txHashes, sendResp.TxHash)
  1219  	}
  1220  
  1221  	// Wait for a new block
  1222  	err = n.WaitForNextBlock()
  1223  	require.NoError(t, err)
  1224  
  1225  	// All Txs are in one block
  1226  	height := f.QueryTx(txHashes[0]).Height
  1227  	for _, txHash := range txHashes {
  1228  		require.Equal(t, height, f.QueryTx(txHash).Height)
  1229  	}
  1230  }
  1231  
  1232  func TestFnsadWasmContract(t *testing.T) {
  1233  	t.Parallel()
  1234  	f := InitFixtures(t)
  1235  	defer f.Cleanup()
  1236  
  1237  	// start fnsad server with minimum fees
  1238  	n := f.FnsadStart(minGasPrice.String())
  1239  	defer n.Cleanup()
  1240  
  1241  	fooAddr := f.KeyAddress(keyFoo)
  1242  
  1243  	flagFromFoo := fmt.Sprintf("--from=%s", fooAddr)
  1244  	flagGas := "--gas=auto"
  1245  	flagGasAdjustment := "--gas-adjustment=1.2"
  1246  	workDir, err := os.Getwd()
  1247  	require.NoError(t, err)
  1248  	dirContract := path.Join(workDir, "contracts", "queue")
  1249  	hashFile := path.Join(dirContract, "hash.txt")
  1250  	wasmQueue := path.Join(dirContract, "contract.wasm")
  1251  	codeID := uint64(1)
  1252  	amountSend := uint64(10)
  1253  	denomSend := fooDenom
  1254  
  1255  	var contractAddress string
  1256  	count := 0
  1257  	initValue := 0
  1258  	enqueueValue := 2
  1259  
  1260  	// make tmpDir
  1261  	tmpDir, err := os.MkdirTemp("", "")
  1262  	require.NoError(t, err)
  1263  	defer func() {
  1264  		require.NoError(t, os.RemoveAll(tmpDir))
  1265  	}()
  1266  	err = os.Chdir(tmpDir)
  1267  	require.NoError(t, err)
  1268  
  1269  	// validate that there are no code in the chain
  1270  	{
  1271  		listCode := f.QueryListCodeWasm()
  1272  		require.Len(t, listCode.CodeInfos, 0)
  1273  	}
  1274  
  1275  	// store the contract queue
  1276  	{
  1277  		_, err := f.TxStoreWasm(wasmQueue, flagFromFoo, flagGasAdjustment, flagGas, "-y")
  1278  		require.NoError(t, err)
  1279  		// Wait for a new block
  1280  		err = n.WaitForNextBlock()
  1281  		require.NoError(t, err)
  1282  	}
  1283  
  1284  	// validate the code is stored
  1285  	{
  1286  		queryCodesResponse := f.QueryListCodeWasm()
  1287  		require.Len(t, queryCodesResponse.CodeInfos, 1)
  1288  
  1289  		// validate the hash is the same
  1290  		expectedRow, err := os.ReadFile(hashFile)
  1291  		require.NoError(t, err)
  1292  		expected, err := hex.DecodeString(string(expectedRow[:64]))
  1293  		require.NoError(t, err)
  1294  		actual := queryCodesResponse.CodeInfos[0].DataHash.Bytes()
  1295  		require.Equal(t, expected, actual)
  1296  	}
  1297  
  1298  	// validate getCode get the exact same wasm
  1299  	{
  1300  		outputPath := fmt.Sprintf("contract-%s.wasm", strconv.FormatUint(codeID, 10))
  1301  		f.QueryCodeWasm(codeID)
  1302  		fLocal, err := os.Open(wasmQueue)
  1303  		require.NoError(t, err)
  1304  		fChain, err := os.Open(outputPath)
  1305  		require.NoError(t, err)
  1306  
  1307  		// 2000000 is enough length
  1308  		dataLocal := make([]byte, 2000000)
  1309  		dataChain := make([]byte, 2000000)
  1310  		_, err = fLocal.Read(dataLocal)
  1311  		require.NoError(t, err)
  1312  		_, err = fChain.Read(dataChain)
  1313  		require.NoError(t, err)
  1314  		require.Equal(t, dataLocal, dataChain)
  1315  	}
  1316  
  1317  	// validate that there are no contract using the code (id=1)
  1318  	{
  1319  		listContract := f.QueryListContractByCodeWasm(codeID)
  1320  		require.Len(t, listContract.Contracts, 0)
  1321  	}
  1322  
  1323  	// instantiate a contract with the code queue
  1324  	{
  1325  		msgJSON := "{}"
  1326  		flagLabel := "--label=queue-test"
  1327  		flagAmount := fmt.Sprintf("--amount=%d%s", amountSend, denomSend)
  1328  		_, err := f.TxInstantiateWasm(codeID, msgJSON, flagFromFoo, flagGasAdjustment, flagGas, flagLabel, flagAmount, flagFromFoo, "-y", "--no-admin")
  1329  		require.NoError(t, err)
  1330  		// Wait for a new block
  1331  		err = n.WaitForNextBlock()
  1332  		require.NoError(t, err)
  1333  	}
  1334  
  1335  	// validate there is only one contract using codeID=1 and get contractAddress
  1336  	{
  1337  		listContract := f.QueryListContractByCodeWasm(codeID)
  1338  		require.Len(t, listContract.Contracts, 1)
  1339  		contractAddress = listContract.Contracts[0]
  1340  	}
  1341  
  1342  	// check queue count and sum
  1343  	{
  1344  		res := f.QueryContractStateSmartWasm(contractAddress, "{\"count\":{}}")
  1345  		require.Equal(t, fmt.Sprintf("{\"data\":{\"count\":%d}}", count), strings.TrimRight(res, "\n"))
  1346  
  1347  		res = f.QueryContractStateSmartWasm(contractAddress, "{\"sum\":{}}")
  1348  		require.Equal(t, fmt.Sprintf("{\"data\":{\"sum\":%d}}", initValue), strings.TrimRight(res, "\n"))
  1349  	}
  1350  
  1351  	// execute contract(enqueue function)
  1352  	{
  1353  		msgJSON := fmt.Sprintf("{\"enqueue\":{\"value\":%d}}", enqueueValue)
  1354  		_, err := f.TxExecuteWasm(contractAddress, msgJSON, flagFromFoo, flagGasAdjustment, flagGas, "-y")
  1355  		require.NoError(t, err)
  1356  		// Wait for a new block
  1357  		err = n.WaitForNextBlock()
  1358  		require.NoError(t, err)
  1359  		count++
  1360  	}
  1361  
  1362  	// check queue count and sum
  1363  	{
  1364  		res := f.QueryContractStateSmartWasm(contractAddress, "{\"count\":{}}")
  1365  		require.Equal(t, fmt.Sprintf("{\"data\":{\"count\":%d}}", count), strings.TrimRight(res, "\n"))
  1366  
  1367  		res = f.QueryContractStateSmartWasm(contractAddress, "{\"sum\":{}}")
  1368  		require.Equal(t, fmt.Sprintf("{\"data\":{\"sum\":%d}}", initValue+enqueueValue), strings.TrimRight(res, "\n"))
  1369  	}
  1370  }