cosmos-sdk/cmd/gaia/cli_test/cli_test.go

948 lines
29 KiB
Go

package clitest
import (
"errors"
"fmt"
"io/ioutil"
"os"
"path"
"path/filepath"
"testing"
"time"
"github.com/tendermint/tendermint/crypto/ed25519"
"github.com/stretchr/testify/require"
abci "github.com/tendermint/tendermint/abci/types"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/cmd/gaia/app"
"github.com/cosmos/cosmos-sdk/tests"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/gov"
"github.com/cosmos/cosmos-sdk/x/staking"
stakingTypes "github.com/cosmos/cosmos-sdk/x/staking/types"
)
func TestGaiaCLIKeysAddMultisig(t *testing.T) {
t.Parallel()
f := InitFixtures(t)
// key names order does not matter
f.KeysAdd("msig1", "--multisig-threshold=2",
fmt.Sprintf("--multisig=%s,%s", keyBar, keyBaz))
f.KeysAdd("msig2", "--multisig-threshold=2",
fmt.Sprintf("--multisig=%s,%s", keyBaz, keyBar))
require.Equal(t, f.KeysShow("msig1").Address, f.KeysShow("msig2").Address)
f.KeysAdd("msig3", "--multisig-threshold=2",
fmt.Sprintf("--multisig=%s,%s", keyBar, keyBaz),
"--nosort")
f.KeysAdd("msig4", "--multisig-threshold=2",
fmt.Sprintf("--multisig=%s,%s", keyBaz, keyBar),
"--nosort")
require.NotEqual(t, f.KeysShow("msig3").Address, f.KeysShow("msig4").Address)
}
func TestGaiaCLIMinimumFees(t *testing.T) {
t.Parallel()
f := InitFixtures(t)
// start gaiad server with minimum fees
minGasPrice, _ := sdk.NewDecFromStr("0.000006")
fees := fmt.Sprintf(
"--minimum_gas_prices=%s,%s",
sdk.NewDecCoinFromDec(feeDenom, minGasPrice),
sdk.NewDecCoinFromDec(fee2Denom, minGasPrice),
)
proc := f.GDStart(fees)
defer proc.Stop(false)
barAddr := f.KeyAddress(keyBar)
// Send a transaction that will get rejected
success, _, _ := f.TxSend(keyFoo, barAddr, sdk.NewInt64Coin(fee2Denom, 10))
require.False(f.T, success)
tests.WaitForNextNBlocksTM(1, f.Port)
// Ensure tx w/ correct fees pass
txFees := fmt.Sprintf("--fees=%s,%s", sdk.NewInt64Coin(feeDenom, 2), sdk.NewInt64Coin(fee2Denom, 2))
success, _, _ = f.TxSend(keyFoo, barAddr, sdk.NewInt64Coin(fee2Denom, 10), txFees)
require.True(f.T, success)
tests.WaitForNextNBlocksTM(1, f.Port)
// Ensure tx w/ improper fees fails
txFees = fmt.Sprintf("--fees=%s", sdk.NewInt64Coin(feeDenom, 5))
success, _, _ = f.TxSend(keyFoo, barAddr, sdk.NewInt64Coin(fooDenom, 10), txFees)
require.False(f.T, success)
// Cleanup testing directories
f.Cleanup()
}
func TestGaiaCLIGasPrices(t *testing.T) {
t.Parallel()
f := InitFixtures(t)
// start gaiad server with minimum fees
minGasPrice, _ := sdk.NewDecFromStr("0.000006")
proc := f.GDStart(fmt.Sprintf("--minimum_gas_prices=%s", sdk.NewDecCoinFromDec(feeDenom, minGasPrice)))
defer proc.Stop(false)
barAddr := f.KeyAddress(keyBar)
// insufficient gas prices (tx fails)
badGasPrice, _ := sdk.NewDecFromStr("0.000003")
success, _, _ := f.TxSend(
keyFoo, barAddr, sdk.NewInt64Coin(fooDenom, 50),
fmt.Sprintf("--gas-prices=%s", sdk.NewDecCoinFromDec(feeDenom, badGasPrice)))
require.False(t, success)
// wait for a block confirmation
tests.WaitForNextNBlocksTM(1, f.Port)
// sufficient gas prices (tx passes)
success, _, _ = f.TxSend(
keyFoo, barAddr, sdk.NewInt64Coin(fooDenom, 50),
fmt.Sprintf("--gas-prices=%s", sdk.NewDecCoinFromDec(feeDenom, minGasPrice)))
require.True(t, success)
// wait for a block confirmation
tests.WaitForNextNBlocksTM(1, f.Port)
f.Cleanup()
}
func TestGaiaCLIFeesDeduction(t *testing.T) {
t.Parallel()
f := InitFixtures(t)
// start gaiad server with minimum fees
minGasPrice, _ := sdk.NewDecFromStr("0.000006")
proc := f.GDStart(fmt.Sprintf("--minimum_gas_prices=%s", sdk.NewDecCoinFromDec(feeDenom, minGasPrice)))
defer proc.Stop(false)
// Save key addresses for later use
fooAddr := f.KeyAddress(keyFoo)
barAddr := f.KeyAddress(keyBar)
fooAcc := f.QueryAccount(fooAddr)
fooAmt := fooAcc.GetCoins().AmountOf(fooDenom)
// test simulation
success, _, _ := f.TxSend(
keyFoo, barAddr, sdk.NewInt64Coin(fooDenom, 1000),
fmt.Sprintf("--fees=%s", sdk.NewInt64Coin(feeDenom, 2)), "--dry-run")
require.True(t, success)
// Wait for a block
tests.WaitForNextNBlocksTM(1, f.Port)
// ensure state didn't change
fooAcc = f.QueryAccount(fooAddr)
require.Equal(t, fooAmt.Int64(), fooAcc.GetCoins().AmountOf(fooDenom).Int64())
// insufficient funds (coins + fees) tx fails
success, _, _ = f.TxSend(
keyFoo, barAddr, sdk.NewInt64Coin(fooDenom, 10000000),
fmt.Sprintf("--fees=%s", sdk.NewInt64Coin(feeDenom, 2)))
require.False(t, success)
// Wait for a block
tests.WaitForNextNBlocksTM(1, f.Port)
// ensure state didn't change
fooAcc = f.QueryAccount(fooAddr)
require.Equal(t, fooAmt.Int64(), fooAcc.GetCoins().AmountOf(fooDenom).Int64())
// test success (transfer = coins + fees)
success, _, _ = f.TxSend(
keyFoo, barAddr, sdk.NewInt64Coin(fooDenom, 500),
fmt.Sprintf("--fees=%s", sdk.NewInt64Coin(feeDenom, 2)))
require.True(t, success)
f.Cleanup()
}
func TestGaiaCLISend(t *testing.T) {
t.Parallel()
f := InitFixtures(t)
// start gaiad server
proc := f.GDStart()
defer proc.Stop(false)
// Save key addresses for later use
fooAddr := f.KeyAddress(keyFoo)
barAddr := f.KeyAddress(keyBar)
fooAcc := f.QueryAccount(fooAddr)
require.Equal(t, int64(50), fooAcc.GetCoins().AmountOf(denom).Int64())
// Send some tokens from one account to the other
f.TxSend(keyFoo, barAddr, sdk.NewInt64Coin(denom, 10))
tests.WaitForNextNBlocksTM(1, f.Port)
// Ensure account balances match expected
barAcc := f.QueryAccount(barAddr)
require.Equal(t, int64(10), barAcc.GetCoins().AmountOf(denom).Int64())
fooAcc = f.QueryAccount(fooAddr)
require.Equal(t, int64(40), fooAcc.GetCoins().AmountOf(denom).Int64())
// Test --dry-run
success, _, _ := f.TxSend(keyFoo, barAddr, sdk.NewInt64Coin(denom, 10), "--dry-run")
require.True(t, success)
// Check state didn't change
fooAcc = f.QueryAccount(fooAddr)
require.Equal(t, int64(40), fooAcc.GetCoins().AmountOf(denom).Int64())
// test autosequencing
f.TxSend(keyFoo, barAddr, sdk.NewInt64Coin(denom, 10))
tests.WaitForNextNBlocksTM(1, f.Port)
// Ensure account balances match expected
barAcc = f.QueryAccount(barAddr)
require.Equal(t, int64(20), barAcc.GetCoins().AmountOf(denom).Int64())
fooAcc = f.QueryAccount(fooAddr)
require.Equal(t, int64(30), fooAcc.GetCoins().AmountOf(denom).Int64())
// test memo
f.TxSend(keyFoo, barAddr, sdk.NewInt64Coin(denom, 10), "--memo='testmemo'")
tests.WaitForNextNBlocksTM(1, f.Port)
// Ensure account balances match expected
barAcc = f.QueryAccount(barAddr)
require.Equal(t, int64(30), barAcc.GetCoins().AmountOf(denom).Int64())
fooAcc = f.QueryAccount(fooAddr)
require.Equal(t, int64(20), fooAcc.GetCoins().AmountOf(denom).Int64())
f.Cleanup()
}
func TestGaiaCLIGasAuto(t *testing.T) {
t.Parallel()
f := InitFixtures(t)
// start gaiad server
proc := f.GDStart()
defer proc.Stop(false)
fooAddr := f.KeyAddress(keyFoo)
barAddr := f.KeyAddress(keyBar)
fooAcc := f.QueryAccount(fooAddr)
require.Equal(t, int64(50), fooAcc.GetCoins().AmountOf(denom).Int64())
// Test failure with auto gas disabled and very little gas set by hand
success, _, _ := f.TxSend(keyFoo, barAddr, sdk.NewInt64Coin(denom, 10), "--gas=10")
require.False(t, success)
// Check state didn't change
fooAcc = f.QueryAccount(fooAddr)
require.Equal(t, int64(50), fooAcc.GetCoins().AmountOf(denom).Int64())
// Test failure with negative gas
success, _, _ = f.TxSend(keyFoo, barAddr, sdk.NewInt64Coin(denom, 10), "--gas=-100")
require.False(t, success)
// Check state didn't change
fooAcc = f.QueryAccount(fooAddr)
require.Equal(t, int64(50), fooAcc.GetCoins().AmountOf(denom).Int64())
// Test failure with 0 gas
success, _, _ = f.TxSend(keyFoo, barAddr, sdk.NewInt64Coin(denom, 10), "--gas=0")
require.False(t, success)
// Check state didn't change
fooAcc = f.QueryAccount(fooAddr)
require.Equal(t, int64(50), fooAcc.GetCoins().AmountOf(denom).Int64())
// Enable auto gas
success, stdout, stderr := f.TxSend(keyFoo, barAddr, sdk.NewInt64Coin(denom, 10), "--gas=auto", "--json")
require.NotEmpty(t, stderr)
require.True(t, success)
cdc := app.MakeCodec()
sendResp := struct {
Height int64
TxHash string
Response abci.ResponseDeliverTx
}{}
err := cdc.UnmarshalJSON([]byte(stdout), &sendResp)
require.Nil(t, err)
require.Equal(t, sendResp.Response.GasWanted, sendResp.Response.GasUsed)
tests.WaitForNextNBlocksTM(1, f.Port)
// Check state has changed accordingly
fooAcc = f.QueryAccount(fooAddr)
require.Equal(t, int64(40), fooAcc.GetCoins().AmountOf(denom).Int64())
f.Cleanup()
}
func TestGaiaCLICreateValidator(t *testing.T) {
t.Parallel()
f := InitFixtures(t)
// start gaiad server
proc := f.GDStart()
defer proc.Stop(false)
fooAddr := f.KeyAddress(keyFoo)
barAddr := f.KeyAddress(keyBar)
barVal := sdk.ValAddress(barAddr)
consPubKey := sdk.MustBech32ifyConsPub(ed25519.GenPrivKey().PubKey())
f.TxSend(keyFoo, barAddr, sdk.NewInt64Coin(denom, 10))
tests.WaitForNextNBlocksTM(1, f.Port)
barAcc := f.QueryAccount(barAddr)
require.Equal(t, int64(10), barAcc.GetCoins().AmountOf(denom).Int64())
fooAcc := f.QueryAccount(fooAddr)
require.Equal(t, int64(40), fooAcc.GetCoins().AmountOf(denom).Int64())
defaultParams := staking.DefaultParams()
initialPool := staking.InitialPool()
initialPool.BondedTokens = initialPool.BondedTokens.Add(sdk.NewInt(101)) // Delegate tx on GaiaAppGenState
// Generate a create validator transaction and ensure correctness
success, stdout, stderr := f.TxStakingCreateValidator(keyBar, consPubKey, sdk.NewInt64Coin(denom, 2), "--generate-only")
require.True(f.T, success)
require.Empty(f.T, stderr)
msg := unmarshalStdTx(f.T, stdout)
require.NotZero(t, msg.Fee.Gas)
require.Equal(t, len(msg.Msgs), 1)
require.Equal(t, 0, len(msg.GetSignatures()))
// Test --dry-run
success, _, _ = f.TxStakingCreateValidator(keyBar, consPubKey, sdk.NewInt64Coin(denom, 2), "--dry-run")
require.True(t, success)
// Create the validator
f.TxStakingCreateValidator(keyBar, consPubKey, sdk.NewInt64Coin(denom, 2))
tests.WaitForNextNBlocksTM(1, f.Port)
// Ensure funds were deducted properly
barAcc = f.QueryAccount(barAddr)
require.Equal(t, int64(8), barAcc.GetCoins().AmountOf(denom).Int64())
// Ensure that validator state is as expected
validator := f.QueryStakingValidator(barVal)
require.Equal(t, validator.OperatorAddr, barVal)
require.True(sdk.IntEq(t, sdk.NewInt(2), validator.Tokens))
// Query delegations to the validator
validatorDelegations := f.QueryStakingDelegationsTo(barVal)
require.Len(t, validatorDelegations, 1)
require.NotZero(t, validatorDelegations[0].Shares)
// unbond a single share
success = f.TxStakingUnbond(keyBar, "1", barVal)
require.True(t, success)
tests.WaitForNextNBlocksTM(1, f.Port)
// Ensure bonded staking is correct
validator = f.QueryStakingValidator(barVal)
require.Equal(t, "1", validator.Tokens.String())
// Get unbonding delegations from the validator
validatorUbds := f.QueryStakingUnbondingDelegationsFrom(barVal)
require.Len(t, validatorUbds, 1)
require.Len(t, validatorUbds[0].Entries, 1)
require.Equal(t, "1", validatorUbds[0].Entries[0].Balance.Amount.String())
// Query staking parameters
params := f.QueryStakingParameters()
require.True(t, defaultParams.Equal(params))
// Query staking pool
pool := f.QueryStakingPool()
require.Equal(t, initialPool.BondedTokens, pool.BondedTokens)
f.Cleanup()
}
func TestGaiaCLISubmitProposal(t *testing.T) {
t.Parallel()
f := InitFixtures(t)
// start gaiad server
proc := f.GDStart()
defer proc.Stop(false)
f.QueryGovParamDeposit()
f.QueryGovParamVoting()
f.QueryGovParamTallying()
fooAddr := f.KeyAddress(keyFoo)
fooAcc := f.QueryAccount(fooAddr)
require.Equal(t, int64(50), fooAcc.GetCoins().AmountOf(stakingTypes.DefaultBondDenom).Int64())
proposalsQuery := f.QueryGovProposals()
require.Empty(t, proposalsQuery)
// Test submit generate only for submit proposal
success, stdout, stderr := f.TxGovSubmitProposal(
keyFoo, "Text", "Test", "test", sdk.NewInt64Coin(denom, 5), "--generate-only")
require.True(t, success)
require.Empty(t, stderr)
msg := unmarshalStdTx(t, stdout)
require.NotZero(t, msg.Fee.Gas)
require.Equal(t, len(msg.Msgs), 1)
require.Equal(t, 0, len(msg.GetSignatures()))
// Test --dry-run
success, _, _ = f.TxGovSubmitProposal(keyFoo, "Text", "Test", "test", sdk.NewInt64Coin(denom, 5), "--dry-run")
require.True(t, success)
// Create the proposal
f.TxGovSubmitProposal(keyFoo, "Text", "Test", "test", sdk.NewInt64Coin(denom, 5))
tests.WaitForNextNBlocksTM(1, f.Port)
// Ensure transaction tags can be queried
txs := f.QueryTxs(1, 50, "action:submit_proposal", fmt.Sprintf("proposer:%s", fooAddr))
require.Len(t, txs, 1)
// Ensure deposit was deducted
fooAcc = f.QueryAccount(fooAddr)
require.Equal(t, int64(45), fooAcc.GetCoins().AmountOf(denom).Int64())
// Ensure propsal is directly queryable
proposal1 := f.QueryGovProposal(1)
require.Equal(t, uint64(1), proposal1.GetProposalID())
require.Equal(t, gov.StatusDepositPeriod, proposal1.GetStatus())
// Ensure query proposals returns properly
proposalsQuery = f.QueryGovProposals()
require.Equal(t, uint64(1), proposalsQuery[0].GetProposalID())
// Query the deposits on the proposal
deposit := f.QueryGovDeposit(1, fooAddr)
require.Equal(t, int64(5), deposit.Amount.AmountOf(denom).Int64())
// Test deposit generate only
success, stdout, stderr = f.TxGovDeposit(1, keyFoo, sdk.NewInt64Coin(denom, 10), "--generate-only")
require.True(t, success)
require.Empty(t, stderr)
msg = unmarshalStdTx(t, stdout)
require.NotZero(t, msg.Fee.Gas)
require.Equal(t, len(msg.Msgs), 1)
require.Equal(t, 0, len(msg.GetSignatures()))
// Run the deposit transaction
f.TxGovDeposit(1, keyFoo, sdk.NewInt64Coin(denom, 10))
tests.WaitForNextNBlocksTM(1, f.Port)
// test query deposit
deposits := f.QueryGovDeposits(1)
require.Len(t, deposits, 1)
require.Equal(t, int64(15), deposits[0].Amount.AmountOf(denom).Int64())
// Ensure querying the deposit returns the proper amount
deposit = f.QueryGovDeposit(1, fooAddr)
require.Equal(t, int64(15), deposit.Amount.AmountOf(denom).Int64())
// Ensure tags are set on the transaction
txs = f.QueryTxs(1, 50, "action:deposit", fmt.Sprintf("depositor:%s", fooAddr))
require.Len(t, txs, 1)
// Ensure account has expected amount of funds
fooAcc = f.QueryAccount(fooAddr)
require.Equal(t, int64(35), fooAcc.GetCoins().AmountOf(denom).Int64())
// Fetch the proposal and ensure it is now in the voting period
proposal1 = f.QueryGovProposal(1)
require.Equal(t, uint64(1), proposal1.GetProposalID())
require.Equal(t, gov.StatusVotingPeriod, proposal1.GetStatus())
// Test vote generate only
success, stdout, stderr = f.TxGovVote(1, gov.OptionYes, keyFoo, "--generate-only")
require.True(t, success)
require.Empty(t, stderr)
msg = unmarshalStdTx(t, stdout)
require.NotZero(t, msg.Fee.Gas)
require.Equal(t, len(msg.Msgs), 1)
require.Equal(t, 0, len(msg.GetSignatures()))
// Vote on the proposal
f.TxGovVote(1, gov.OptionYes, keyFoo)
tests.WaitForNextNBlocksTM(1, f.Port)
// Query the vote
vote := f.QueryGovVote(1, fooAddr)
require.Equal(t, uint64(1), vote.ProposalID)
require.Equal(t, gov.OptionYes, vote.Option)
// Query the votes
votes := f.QueryGovVotes(1)
require.Len(t, votes, 1)
require.Equal(t, uint64(1), votes[0].ProposalID)
require.Equal(t, gov.OptionYes, votes[0].Option)
// Ensure tags are applied to voting transaction properly
txs = f.QueryTxs(1, 50, "action:vote", fmt.Sprintf("voter:%s", fooAddr))
require.Len(t, txs, 1)
// Ensure no proposals in deposit period
proposalsQuery = f.QueryGovProposals("--status=DepositPeriod")
require.Empty(t, proposalsQuery)
// Ensure the proposal returns as in the voting period
proposalsQuery = f.QueryGovProposals("--status=VotingPeriod")
require.Equal(t, uint64(1), proposalsQuery[0].GetProposalID())
// submit a second test proposal
f.TxGovSubmitProposal(keyFoo, "Text", "Apples", "test", sdk.NewInt64Coin(denom, 5))
tests.WaitForNextNBlocksTM(1, f.Port)
// Test limit on proposals query
proposalsQuery = f.QueryGovProposals("--limit=1")
require.Equal(t, uint64(2), proposalsQuery[0].GetProposalID())
f.Cleanup()
}
func TestGaiaCLIQueryTxPagination(t *testing.T) {
t.Parallel()
f := InitFixtures(t)
// start gaiad server
proc := f.GDStart()
defer proc.Stop(false)
fooAddr := f.KeyAddress(keyFoo)
barAddr := f.KeyAddress(keyBar)
for i := 1; i <= 30; i++ {
success := executeWrite(t, fmt.Sprintf(
"gaiacli tx send %s --amount=%dfootoken --to=%s --from=foo",
f.Flags(), i, barAddr), app.DefaultKeyPass)
require.True(t, success)
tests.WaitForNextNBlocksTM(1, f.Port)
}
// perPage = 15, 2 pages
txsPage1 := f.QueryTxs(1, 15, fmt.Sprintf("sender:%s", fooAddr))
require.Len(t, txsPage1, 15)
txsPage2 := f.QueryTxs(2, 15, fmt.Sprintf("sender:%s", fooAddr))
require.Len(t, txsPage2, 15)
require.NotEqual(t, txsPage1, txsPage2)
txsPage3 := f.QueryTxs(3, 15, fmt.Sprintf("sender:%s", fooAddr))
require.Len(t, txsPage3, 15)
require.Equal(t, txsPage2, txsPage3)
// perPage = 16, 2 pages
txsPage1 = f.QueryTxs(1, 16, fmt.Sprintf("sender:%s", fooAddr))
require.Len(t, txsPage1, 16)
txsPage2 = f.QueryTxs(2, 16, fmt.Sprintf("sender:%s", fooAddr))
require.Len(t, txsPage2, 14)
require.NotEqual(t, txsPage1, txsPage2)
// perPage = 50
txsPageFull := f.QueryTxs(1, 50, fmt.Sprintf("sender:%s", fooAddr))
require.Len(t, txsPageFull, 30)
require.Equal(t, txsPageFull, append(txsPage1, txsPage2...))
// perPage = 0
f.QueryTxsInvalid(errors.New("ERROR: page must greater than 0"), 0, 50, fmt.Sprintf("sender:%s", fooAddr))
// limit = 0
f.QueryTxsInvalid(errors.New("ERROR: limit must greater than 0"), 1, 0, fmt.Sprintf("sender:%s", fooAddr))
}
func TestGaiaCLIValidateSignatures(t *testing.T) {
t.Parallel()
f := InitFixtures(t)
// start gaiad server
proc := f.GDStart()
defer proc.Stop(false)
fooAddr := f.KeyAddress(keyFoo)
barAddr := f.KeyAddress(keyBar)
// generate sendTx with default gas
success, stdout, stderr := f.TxSend(keyFoo, barAddr, sdk.NewInt64Coin(denom, 10), "--generate-only")
require.True(t, success)
require.Empty(t, stderr)
// write unsigned tx to file
unsignedTxFile := writeToNewTempFile(t, stdout)
defer os.Remove(unsignedTxFile.Name())
// validate we can successfully sign
success, stdout, stderr = f.TxSign(keyFoo, unsignedTxFile.Name())
require.True(t, success)
require.Empty(t, stderr)
stdTx := unmarshalStdTx(t, stdout)
require.Equal(t, len(stdTx.Msgs), 1)
require.Equal(t, 1, len(stdTx.GetSignatures()))
require.Equal(t, fooAddr.String(), stdTx.GetSigners()[0].String())
// write signed tx to file
signedTxFile := writeToNewTempFile(t, stdout)
defer os.Remove(signedTxFile.Name())
// validate signatures
success, _, _ = f.TxSign(keyFoo, signedTxFile.Name(), "--validate-signatures")
require.True(t, success)
// modify the transaction
stdTx.Memo = "MODIFIED-ORIGINAL-TX-BAD"
bz := marshalStdTx(t, stdTx)
modSignedTxFile := writeToNewTempFile(t, string(bz))
defer os.Remove(modSignedTxFile.Name())
// validate signature validation failure due to different transaction sig bytes
success, _, _ = f.TxSign(keyFoo, modSignedTxFile.Name(), "--validate-signatures")
require.False(t, success)
f.Cleanup()
}
func TestGaiaCLISendGenerateSignAndBroadcast(t *testing.T) {
t.Parallel()
f := InitFixtures(t)
// start gaiad server
proc := f.GDStart()
defer proc.Stop(false)
fooAddr := f.KeyAddress(keyFoo)
barAddr := f.KeyAddress(keyBar)
// Test generate sendTx with default gas
success, stdout, stderr := f.TxSend(keyFoo, barAddr, sdk.NewInt64Coin(denom, 10), "--generate-only")
require.True(t, success)
require.Empty(t, stderr)
msg := unmarshalStdTx(t, stdout)
require.Equal(t, msg.Fee.Gas, uint64(client.DefaultGasLimit))
require.Equal(t, len(msg.Msgs), 1)
require.Equal(t, 0, len(msg.GetSignatures()))
// Test generate sendTx with --gas=$amount
success, stdout, stderr = f.TxSend(keyFoo, barAddr, sdk.NewInt64Coin(denom, 10), "--gas=100", "--generate-only")
require.True(t, success)
require.Empty(t, stderr)
msg = unmarshalStdTx(t, stdout)
require.Equal(t, msg.Fee.Gas, uint64(100))
require.Equal(t, len(msg.Msgs), 1)
require.Equal(t, 0, len(msg.GetSignatures()))
// Test generate sendTx, estimate gas
success, stdout, stderr = f.TxSend(keyFoo, barAddr, sdk.NewInt64Coin(denom, 10), "--gas=auto", "--generate-only")
require.True(t, success)
require.NotEmpty(t, stderr)
msg = unmarshalStdTx(t, stdout)
require.True(t, msg.Fee.Gas > 0)
require.Equal(t, len(msg.Msgs), 1)
// Write the output to disk
unsignedTxFile := writeToNewTempFile(t, stdout)
defer os.Remove(unsignedTxFile.Name())
// Test sign --validate-signatures
success, stdout, _ = f.TxSign(keyFoo, unsignedTxFile.Name(), "--validate-signatures", "--json")
require.False(t, success)
require.Equal(t, fmt.Sprintf("Signers:\n 0: %v\n\nSignatures:\n\n", fooAddr.String()), stdout)
// Test sign
success, stdout, _ = f.TxSign(keyFoo, unsignedTxFile.Name())
require.True(t, success)
msg = unmarshalStdTx(t, stdout)
require.Equal(t, len(msg.Msgs), 1)
require.Equal(t, 1, len(msg.GetSignatures()))
require.Equal(t, fooAddr.String(), msg.GetSigners()[0].String())
// Write the output to disk
signedTxFile := writeToNewTempFile(t, stdout)
defer os.Remove(signedTxFile.Name())
// Test sign --validate-signatures
success, stdout, _ = f.TxSign(keyFoo, signedTxFile.Name(), "--validate-signatures", "--json")
require.True(t, success)
require.Equal(t, fmt.Sprintf("Signers:\n 0: %v\n\nSignatures:\n 0: %v\t[OK]\n\n", fooAddr.String(),
fooAddr.String()), stdout)
// Ensure foo has right amount of funds
fooAcc := f.QueryAccount(fooAddr)
require.Equal(t, int64(50), fooAcc.GetCoins().AmountOf(denom).Int64())
// Test broadcast
success, stdout, _ = f.TxBroadcast(signedTxFile.Name())
require.True(t, success)
var result struct {
Response abci.ResponseDeliverTx
}
// Unmarshal the response and ensure that gas was properly used
require.Nil(t, app.MakeCodec().UnmarshalJSON([]byte(stdout), &result))
require.Equal(t, msg.Fee.Gas, uint64(result.Response.GasUsed))
require.Equal(t, msg.Fee.Gas, uint64(result.Response.GasWanted))
tests.WaitForNextNBlocksTM(1, f.Port)
// Ensure account state
barAcc := f.QueryAccount(barAddr)
fooAcc = f.QueryAccount(fooAddr)
require.Equal(t, int64(10), barAcc.GetCoins().AmountOf(denom).Int64())
require.Equal(t, int64(40), fooAcc.GetCoins().AmountOf(denom).Int64())
f.Cleanup()
}
func TestGaiaCLIMultisignInsufficientCosigners(t *testing.T) {
t.Parallel()
f := InitFixtures(t)
// start gaiad server with minimum fees
proc := f.GDStart()
defer proc.Stop(false)
fooBarBazAddr := f.KeyAddress(keyFooBarBaz)
barAddr := f.KeyAddress(keyBar)
// Send some tokens from one account to the other
success, _, _ := f.TxSend(keyFoo, fooBarBazAddr, sdk.NewInt64Coin(denom, 10))
require.True(t, success)
tests.WaitForNextNBlocksTM(1, f.Port)
// Test generate sendTx with multisig
success, stdout, _ := f.TxSend(keyFooBarBaz, barAddr, sdk.NewInt64Coin(denom, 5), "--generate-only")
require.True(t, success)
// Write the output to disk
unsignedTxFile := writeToNewTempFile(t, stdout)
defer os.Remove(unsignedTxFile.Name())
// Sign with foo's key
success, stdout, _ = f.TxSign(keyFoo, unsignedTxFile.Name(), "--multisig", fooBarBazAddr.String())
require.True(t, success)
// Write the output to disk
fooSignatureFile := writeToNewTempFile(t, stdout)
defer os.Remove(fooSignatureFile.Name())
// Multisign, not enough signatures
success, stdout, _ = f.TxMultisign(unsignedTxFile.Name(), keyFooBarBaz, []string{fooSignatureFile.Name()})
require.True(t, success)
// Write the output to disk
signedTxFile := writeToNewTempFile(t, stdout)
defer os.Remove(signedTxFile.Name())
// Validate the multisignature
success, _, _ = f.TxSign(keyFooBarBaz, signedTxFile.Name(), "--validate-signatures", "--json")
require.False(t, success)
// Broadcast the transaction
success, _, _ = f.TxBroadcast(signedTxFile.Name())
require.False(t, success)
}
func TestGaiaCLIMultisignSortSignatures(t *testing.T) {
t.Parallel()
f := InitFixtures(t)
// start gaiad server with minimum fees
proc := f.GDStart()
defer proc.Stop(false)
fooBarBazAddr := f.KeyAddress(keyFooBarBaz)
barAddr := f.KeyAddress(keyBar)
// Send some tokens from one account to the other
success, _, _ := f.TxSend(keyFoo, fooBarBazAddr, sdk.NewInt64Coin(denom, 10))
require.True(t, success)
tests.WaitForNextNBlocksTM(1, f.Port)
// Ensure account balances match expected
fooBarBazAcc := f.QueryAccount(fooBarBazAddr)
require.Equal(t, int64(10), fooBarBazAcc.GetCoins().AmountOf(denom).Int64())
// Test generate sendTx with multisig
success, stdout, _ := f.TxSend(keyFooBarBaz, barAddr, sdk.NewInt64Coin(denom, 5), "--generate-only")
require.True(t, success)
// Write the output to disk
unsignedTxFile := writeToNewTempFile(t, stdout)
defer os.Remove(unsignedTxFile.Name())
// Sign with foo's key
success, stdout, _ = f.TxSign(keyFoo, unsignedTxFile.Name(), "--multisig", fooBarBazAddr.String())
require.True(t, success)
// Write the output to disk
fooSignatureFile := writeToNewTempFile(t, stdout)
defer os.Remove(fooSignatureFile.Name())
// Sign with baz's key
success, stdout, _ = f.TxSign(keyBaz, unsignedTxFile.Name(), "--multisig", fooBarBazAddr.String())
require.True(t, success)
// Write the output to disk
bazSignatureFile := writeToNewTempFile(t, stdout)
defer os.Remove(bazSignatureFile.Name())
// Multisign, keys in different order
success, stdout, _ = f.TxMultisign(unsignedTxFile.Name(), keyFooBarBaz, []string{
bazSignatureFile.Name(), fooSignatureFile.Name()})
require.True(t, success)
// Write the output to disk
signedTxFile := writeToNewTempFile(t, stdout)
defer os.Remove(signedTxFile.Name())
// Validate the multisignature
success, _, _ = f.TxSign(keyFooBarBaz, signedTxFile.Name(), "--validate-signatures", "--json")
require.True(t, success)
// Broadcast the transaction
success, _, _ = f.TxBroadcast(signedTxFile.Name())
require.True(t, success)
}
func TestGaiaCLIMultisign(t *testing.T) {
t.Parallel()
f := InitFixtures(t)
// start gaiad server with minimum fees
proc := f.GDStart()
defer proc.Stop(false)
fooBarBazAddr := f.KeyAddress(keyFooBarBaz)
bazAddr := f.KeyAddress(keyBaz)
// Send some tokens from one account to the other
success, _, _ := f.TxSend(keyFoo, fooBarBazAddr, sdk.NewInt64Coin(denom, 10))
require.True(t, success)
tests.WaitForNextNBlocksTM(1, f.Port)
// Ensure account balances match expected
fooBarBazAcc := f.QueryAccount(fooBarBazAddr)
require.Equal(t, int64(10), fooBarBazAcc.GetCoins().AmountOf(denom).Int64())
// Test generate sendTx with multisig
success, stdout, stderr := f.TxSend(keyFooBarBaz, bazAddr, sdk.NewInt64Coin(denom, 10), "--generate-only")
require.True(t, success)
require.Empty(t, stderr)
// Write the output to disk
unsignedTxFile := writeToNewTempFile(t, stdout)
defer os.Remove(unsignedTxFile.Name())
// Sign with foo's key
success, stdout, _ = f.TxSign(keyFoo, unsignedTxFile.Name(), "--multisig", fooBarBazAddr.String())
require.True(t, success)
// Write the output to disk
fooSignatureFile := writeToNewTempFile(t, stdout)
defer os.Remove(fooSignatureFile.Name())
// Sign with bar's key
success, stdout, _ = f.TxSign(keyBar, unsignedTxFile.Name(), "--multisig", fooBarBazAddr.String())
require.True(t, success)
// Write the output to disk
barSignatureFile := writeToNewTempFile(t, stdout)
defer os.Remove(barSignatureFile.Name())
// Multisign
success, stdout, _ = f.TxMultisign(unsignedTxFile.Name(), keyFooBarBaz, []string{
fooSignatureFile.Name(), barSignatureFile.Name()})
require.True(t, success)
// Write the output to disk
signedTxFile := writeToNewTempFile(t, stdout)
defer os.Remove(signedTxFile.Name())
// Validate the multisignature
success, _, _ = f.TxSign(keyFooBarBaz, signedTxFile.Name(), "--validate-signatures", "--json")
require.True(t, success)
// Broadcast the transaction
success, _, _ = f.TxBroadcast(signedTxFile.Name())
require.True(t, success)
}
func TestGaiaCLIConfig(t *testing.T) {
t.Parallel()
f := InitFixtures(t)
node := fmt.Sprintf("%s:%s", f.RPCAddr, f.Port)
// Set available configuration options
f.CLIConfig("node", node)
f.CLIConfig("output", "text")
f.CLIConfig("trust-node", "true")
f.CLIConfig("chain-id", f.ChainID)
f.CLIConfig("trace", "false")
f.CLIConfig("indent", "true")
config, err := ioutil.ReadFile(path.Join(f.GCLIHome, "config", "config.toml"))
require.NoError(t, err)
expectedConfig := fmt.Sprintf(`chain-id = "%s"
indent = true
node = "%s"
output = "text"
trace = false
trust-node = true
`, f.ChainID, node)
require.Equal(t, expectedConfig, string(config))
f.Cleanup()
}
func TestGaiadCollectGentxs(t *testing.T) {
t.Parallel()
f := NewFixtures(t)
// Initialise temporary directories
gentxDir, err := ioutil.TempDir("", "")
gentxDoc := filepath.Join(gentxDir, "gentx.json")
require.NoError(t, err)
// Reset testing path
f.UnsafeResetAll()
// Initialize keys
f.KeysDelete(keyFoo)
f.KeysDelete(keyBar)
f.KeysAdd(keyFoo)
f.KeysAdd(keyBar)
// Configure json output
f.CLIConfig("output", "json")
// Run init
f.GDInit(keyFoo)
// Add account to genesis.json
f.AddGenesisAccount(f.KeyAddress(keyFoo), startCoins)
// Write gentx file
f.GenTx(keyFoo, fmt.Sprintf("--output-document=%s", gentxDoc))
// Collect gentxs from a custom directory
f.CollectGenTxs(fmt.Sprintf("--gentx-dir=%s", gentxDir))
f.Cleanup(gentxDir)
}
func TestSlashingGetParams(t *testing.T) {
t.Parallel()
f := InitFixtures(t)
// start gaiad server
proc := f.GDStart()
defer proc.Stop(false)
params := f.QuerySlashingParams()
require.Equal(t, time.Duration(120000000000), params.MaxEvidenceAge)
require.Equal(t, int64(100), params.SignedBlocksWindow)
require.Equal(t, sdk.NewDecWithPrec(5, 1), params.MinSignedPerWindow)
}