mirror of
https://github.com/0glabs/0g-chain.git
synced 2024-11-20 15:05:21 +00:00
1392 lines
44 KiB
Go
1392 lines
44 KiB
Go
//go:build cli_test
|
|
// +build cli_test
|
|
|
|
package clitest
|
|
|
|
import (
|
|
"encoding/base64"
|
|
"errors"
|
|
"fmt"
|
|
"io/ioutil"
|
|
"os"
|
|
"path"
|
|
"path/filepath"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/cometbft/cometbft/crypto/ed25519"
|
|
tmtypes "github.com/cometbft/cometbft/types"
|
|
"github.com/stretchr/testify/require"
|
|
|
|
"github.com/cosmos/cosmos-sdk/client/flags"
|
|
"github.com/cosmos/cosmos-sdk/tests"
|
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
|
"github.com/cosmos/cosmos-sdk/x/auth"
|
|
"github.com/cosmos/cosmos-sdk/x/gov"
|
|
"github.com/cosmos/cosmos-sdk/x/mint"
|
|
)
|
|
|
|
func TestKvCLIKeysAddMultisig(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))
|
|
ke1Address1 := f.KeysShow("msig1").Address
|
|
f.KeysDelete("msig1")
|
|
|
|
f.KeysAdd("msig2", "--multisig-threshold=2",
|
|
fmt.Sprintf("--multisig=%s,%s", keyBaz, keyBar))
|
|
require.Equal(t, ke1Address1, f.KeysShow("msig2").Address)
|
|
f.KeysDelete("msig2")
|
|
|
|
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)
|
|
|
|
// Cleanup testing directories
|
|
f.Cleanup()
|
|
}
|
|
|
|
func TestKvCLIKeysAddRecover(t *testing.T) {
|
|
t.Parallel()
|
|
f := InitFixtures(t)
|
|
|
|
exitSuccess, _, _ := f.KeysAddRecover("empty-mnemonic", "")
|
|
require.False(t, exitSuccess)
|
|
|
|
exitSuccess, _, _ = f.KeysAddRecover("test-recover", "dentist task convince chimney quality leave banana trade firm crawl eternal easily")
|
|
require.True(t, exitSuccess)
|
|
require.Equal(t, "0g1rsjxn2e4dfl3a2qzuzzjvvgjmmate383g9q4cz", f.KeyAddress("test-recover").String())
|
|
|
|
// test old bip44 coin type
|
|
exitSuccess, _, _ = f.KeysAddRecover("test-recover-legacy", "dentist task convince chimney quality leave banana trade firm crawl eternal easily", "--legacy-hd-path")
|
|
require.True(t, exitSuccess)
|
|
require.Equal(t, "0g1qcfdf69js922qrdr4yaww3ax7gjml6pd39p8lj", f.KeyAddress("test-recover-legacy").String())
|
|
|
|
// Cleanup testing directories
|
|
f.Cleanup()
|
|
}
|
|
|
|
func TestZgChainCLIKeysAddRecoverHDPath(t *testing.T) {
|
|
t.Parallel()
|
|
f := InitFixtures(t)
|
|
|
|
f.KeysAddRecoverHDPath("test-recoverHD1", "dentist task convince chimney quality leave banana trade firm crawl eternal easily", 0, 0)
|
|
require.Equal(t, "0g1rsjxn2e4dfl3a2qzuzzjvvgjmmate383g9q4cz", f.KeyAddress("test-recoverHD1").String())
|
|
|
|
f.KeysAddRecoverHDPath("test-recoverH2", "dentist task convince chimney quality leave banana trade firm crawl eternal easily", 1, 5)
|
|
require.Equal(t, "0g1qpj6nstqn0n5gzcsaezspuhulje6msjq5t8cq5", f.KeyAddress("test-recoverH2").String())
|
|
|
|
f.KeysAddRecoverHDPath("test-recoverH3", "dentist task convince chimney quality leave banana trade firm crawl eternal easily", 1, 17)
|
|
require.Equal(t, "0g1vayfpstgapt7dmv7074kc3ll8xpf0rlzvh4k08", f.KeyAddress("test-recoverH3").String())
|
|
|
|
f.KeysAddRecoverHDPath("test-recoverH4", "dentist task convince chimney quality leave banana trade firm crawl eternal easily", 2, 17)
|
|
require.Equal(t, "0g1xvsfnksmhr887skcfrm4pe3va54tkmrtw7wyer", f.KeyAddress("test-recoverH4").String())
|
|
|
|
// test old bip44 coin type
|
|
f.KeysAddRecoverHDPath("test-recoverH5", "dentist task convince chimney quality leave banana trade firm crawl eternal easily", 2, 17, "--legacy-hd-path")
|
|
require.Equal(t, "0g1v9plmhvyhgxk3th9ydacm7j4z357s3nhhmy0tv", f.KeyAddress("test-recoverH5").String())
|
|
|
|
exitSuccess, _, _ := f.KeysAddRecover("test-recover-fail", "dentist task convince chimney quality leave banana trade firm crawl eternal easily", "--legacy-hd-path --hd-path 44'/459'/0'/0/0")
|
|
require.False(t, exitSuccess)
|
|
|
|
// test -hd-path flag
|
|
exitSuccess, _, _ = f.KeysAddRecover("test-recoverH6", "dentist task convince chimney quality leave banana trade firm crawl eternal easily", "--hd-path 44'/459'/0'/0/0")
|
|
require.True(t, exitSuccess)
|
|
require.Equal(t, "0g1rsjxn2e4dfl3a2qzuzzjvvgjmmate383g9q4cz", f.KeyAddress("test-recoverH6").String())
|
|
|
|
exitSuccess, _, _ = f.KeysAddRecover("test-recoverH7", "dentist task convince chimney quality leave banana trade firm crawl eternal easily", "--hd-path 44'/459'/2'/0/17")
|
|
require.True(t, exitSuccess)
|
|
require.Equal(t, "0g1xvsfnksmhr887skcfrm4pe3va54tkmrtw7wyer", f.KeyAddress("test-recoverH7").String())
|
|
|
|
// Cleanup testing directories
|
|
f.Cleanup()
|
|
}
|
|
|
|
func TestKvCLIMinimumFees(t *testing.T) {
|
|
t.Parallel()
|
|
f := InitFixtures(t)
|
|
|
|
// start kvd 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, stdOut, _ := f.TxSend(keyFoo, barAddr, sdk.NewInt64Coin(fee2Denom, 10), "-y")
|
|
require.Contains(t, stdOut, "insufficient fees")
|
|
require.True(f.T, success)
|
|
tests.WaitForNextNBlocksTM(1, f.Port)
|
|
|
|
// Ensure tx w/ correct fees pass
|
|
txFees := fmt.Sprintf("--fees=%s", sdk.NewInt64Coin(feeDenom, 2))
|
|
success, _, _ = f.TxSend(keyFoo, barAddr, sdk.NewInt64Coin(fee2Denom, 10), txFees, "-y")
|
|
require.True(f.T, success)
|
|
tests.WaitForNextNBlocksTM(1, f.Port)
|
|
|
|
// Ensure tx w/ improper fees fails
|
|
txFees = fmt.Sprintf("--fees=%s", sdk.NewInt64Coin(feeDenom, 1))
|
|
success, stdOut, _ = f.TxSend(keyFoo, barAddr, sdk.NewInt64Coin(fooDenom, 10), txFees, "-y")
|
|
require.Contains(t, stdOut, "insufficient fees")
|
|
require.True(f.T, success)
|
|
|
|
// Cleanup testing directories
|
|
f.Cleanup()
|
|
}
|
|
|
|
func TestKvCLIGasPrices(t *testing.T) {
|
|
t.Parallel()
|
|
f := InitFixtures(t)
|
|
|
|
// start kvd 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, stdOut, _ := f.TxSend(
|
|
keyFoo, barAddr, sdk.NewInt64Coin(fooDenom, 50),
|
|
fmt.Sprintf("--gas-prices=%s", sdk.NewDecCoinFromDec(feeDenom, badGasPrice)), "-y")
|
|
require.Contains(t, stdOut, "insufficient fees")
|
|
require.True(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)), "-y")
|
|
require.True(t, success)
|
|
|
|
// wait for a block confirmation
|
|
tests.WaitForNextNBlocksTM(1, f.Port)
|
|
|
|
f.Cleanup()
|
|
}
|
|
|
|
func TestKvCLIFeesDeduction(t *testing.T) {
|
|
t.Parallel()
|
|
f := InitFixtures(t)
|
|
|
|
// start kvd 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
|
|
largeCoins := sdk.TokensFromConsensusPower(10000000)
|
|
success, stdOut, _ := f.TxSend(
|
|
keyFoo, barAddr, sdk.NewCoin(fooDenom, largeCoins),
|
|
fmt.Sprintf("--fees=%s", sdk.NewInt64Coin(feeDenom, 2)), "-y")
|
|
require.Contains(t, stdOut, "insufficient account funds")
|
|
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())
|
|
|
|
// test success (transfer = coins + fees)
|
|
success, _, _ = f.TxSend(
|
|
keyFoo, barAddr, sdk.NewInt64Coin(fooDenom, 500),
|
|
fmt.Sprintf("--fees=%s", sdk.NewInt64Coin(feeDenom, 2)), "-y")
|
|
require.True(t, success)
|
|
|
|
f.Cleanup()
|
|
}
|
|
|
|
func TestKvCLISend(t *testing.T) {
|
|
t.Parallel()
|
|
f := InitFixtures(t)
|
|
|
|
// start kvd 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)
|
|
startTokens := sdk.TokensFromConsensusPower(50)
|
|
require.Equal(t, startTokens, fooAcc.GetCoins().AmountOf(denom))
|
|
|
|
sendTokens := sdk.TokensFromConsensusPower(10)
|
|
|
|
f.TxSend(keyFoo, barAddr, sdk.NewCoin(denom, sendTokens), "-y")
|
|
tests.WaitForNextNBlocksTM(1, f.Port)
|
|
|
|
// Ensure account balances match expected
|
|
barAcc := f.QueryAccount(barAddr)
|
|
require.Equal(t, sendTokens, barAcc.GetCoins().AmountOf(denom))
|
|
fooAcc = f.QueryAccount(fooAddr)
|
|
require.Equal(t, startTokens.Sub(sendTokens), fooAcc.GetCoins().AmountOf(denom))
|
|
|
|
// Test --dry-run
|
|
success, _, _ := f.TxSend(keyFoo, barAddr, sdk.NewCoin(denom, sendTokens), "--dry-run")
|
|
require.True(t, success)
|
|
|
|
// Test --generate-only
|
|
success, stdout, stderr := f.TxSend(
|
|
fooAddr.String(), barAddr, sdk.NewCoin(denom, sendTokens), "--generate-only=true",
|
|
)
|
|
require.Empty(t, stderr)
|
|
require.True(t, success)
|
|
msg := f.unmarshalStdTx(f.T, stdout)
|
|
require.NotZero(t, msg.Fee.Gas)
|
|
require.Len(t, msg.Msgs, 1)
|
|
require.Len(t, msg.GetSignatures(), 0)
|
|
|
|
// Check state didn't change
|
|
fooAcc = f.QueryAccount(fooAddr)
|
|
require.Equal(t, startTokens.Sub(sendTokens), fooAcc.GetCoins().AmountOf(denom))
|
|
|
|
// test autosequencing
|
|
f.TxSend(keyFoo, barAddr, sdk.NewCoin(denom, sendTokens), "-y")
|
|
tests.WaitForNextNBlocksTM(1, f.Port)
|
|
|
|
// Ensure account balances match expected
|
|
barAcc = f.QueryAccount(barAddr)
|
|
require.Equal(t, sendTokens.MulRaw(2), barAcc.GetCoins().AmountOf(denom))
|
|
fooAcc = f.QueryAccount(fooAddr)
|
|
require.Equal(t, startTokens.Sub(sendTokens.MulRaw(2)), fooAcc.GetCoins().AmountOf(denom))
|
|
|
|
// test memo
|
|
f.TxSend(keyFoo, barAddr, sdk.NewCoin(denom, sendTokens), "--memo='testmemo'", "-y")
|
|
tests.WaitForNextNBlocksTM(1, f.Port)
|
|
|
|
// Ensure account balances match expected
|
|
barAcc = f.QueryAccount(barAddr)
|
|
require.Equal(t, sendTokens.MulRaw(3), barAcc.GetCoins().AmountOf(denom))
|
|
fooAcc = f.QueryAccount(fooAddr)
|
|
require.Equal(t, startTokens.Sub(sendTokens.MulRaw(3)), fooAcc.GetCoins().AmountOf(denom))
|
|
|
|
f.Cleanup()
|
|
}
|
|
|
|
func TestKvCLISendMultiplePerBlock(t *testing.T) {
|
|
t.Parallel()
|
|
f := InitFixtures(t)
|
|
|
|
// start kvd 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)
|
|
startTokens := fooAcc.GetCoins().AmountOf(fooDenom)
|
|
|
|
sendTokens := sdk.TokensFromConsensusPower(1)
|
|
|
|
numTxsToSend := 30
|
|
for i := 0; i < numTxsToSend; i++ {
|
|
seq := fooAcc.GetSequence() + uint64(i)
|
|
f.TxSend(keyFoo, barAddr, sdk.NewCoin(fooDenom, sendTokens), "-y", fmt.Sprintf("--sequence=%d", seq), "--broadcast-mode=sync")
|
|
}
|
|
tests.WaitForNextNBlocksTM(1, f.Port)
|
|
|
|
// Ensure account balances match expected
|
|
totalSent := sendTokens.MulRaw(int64(numTxsToSend))
|
|
barAcc := f.QueryAccount(barAddr)
|
|
require.Equal(t, totalSent, barAcc.GetCoins().AmountOf(fooDenom))
|
|
fooAcc = f.QueryAccount(fooAddr)
|
|
require.Equal(t, startTokens.Sub(totalSent), fooAcc.GetCoins().AmountOf(fooDenom))
|
|
|
|
f.Cleanup()
|
|
}
|
|
|
|
func TestKvCLIGasAuto(t *testing.T) {
|
|
// https://github.com/cosmos/cosmos-sdk/pull/5179
|
|
t.Skip()
|
|
t.Parallel()
|
|
f := InitFixtures(t)
|
|
|
|
// start kvd server
|
|
proc := f.GDStart()
|
|
defer proc.Stop(false)
|
|
|
|
fooAddr := f.KeyAddress(keyFoo)
|
|
barAddr := f.KeyAddress(keyBar)
|
|
|
|
fooAcc := f.QueryAccount(fooAddr)
|
|
startTokens := sdk.TokensFromConsensusPower(50)
|
|
require.Equal(t, startTokens, fooAcc.GetCoins().AmountOf(denom))
|
|
|
|
// Test failure with auto gas disabled and very little gas set by hand
|
|
sendTokens := sdk.TokensFromConsensusPower(10)
|
|
success, stdOut, _ := f.TxSend(keyFoo, barAddr, sdk.NewCoin(denom, sendTokens), "--gas=10", "-y")
|
|
require.Contains(t, stdOut, "out of gas in location")
|
|
require.True(t, success)
|
|
|
|
// Check state didn't change
|
|
fooAcc = f.QueryAccount(fooAddr)
|
|
require.Equal(t, startTokens, fooAcc.GetCoins().AmountOf(denom))
|
|
|
|
// Test failure with negative gas
|
|
success, _, _ = f.TxSend(keyFoo, barAddr, sdk.NewCoin(denom, sendTokens), "--gas=-100", "-y")
|
|
require.False(t, success)
|
|
|
|
// Check state didn't change
|
|
fooAcc = f.QueryAccount(fooAddr)
|
|
require.Equal(t, startTokens, fooAcc.GetCoins().AmountOf(denom))
|
|
|
|
// Test failure with 0 gas
|
|
success, stdOut, _ = f.TxSend(keyFoo, barAddr, sdk.NewCoin(denom, sendTokens), "--gas=0", "-y")
|
|
require.Contains(t, stdOut, "out of gas in location")
|
|
require.True(t, success)
|
|
|
|
// Check state didn't change
|
|
fooAcc = f.QueryAccount(fooAddr)
|
|
require.Equal(t, startTokens, fooAcc.GetCoins().AmountOf(denom))
|
|
|
|
// Enable auto gas
|
|
success, stdout, stderr := f.TxSend(keyFoo, barAddr, sdk.NewCoin(denom, sendTokens), "--gas=auto", "-y")
|
|
require.NotEmpty(t, stderr)
|
|
require.True(t, success)
|
|
sendResp := sdk.TxResponse{}
|
|
err := f.cdc.UnmarshalJSON([]byte(stdout), &sendResp)
|
|
require.Nil(t, err)
|
|
require.True(t, sendResp.GasWanted >= sendResp.GasUsed)
|
|
tests.WaitForNextNBlocksTM(1, f.Port)
|
|
|
|
// Check state has changed accordingly
|
|
fooAcc = f.QueryAccount(fooAddr)
|
|
require.Equal(t, startTokens.Sub(sendTokens), fooAcc.GetCoins().AmountOf(denom))
|
|
|
|
f.Cleanup()
|
|
}
|
|
|
|
func TestKvCLICreateValidator(t *testing.T) {
|
|
t.Parallel()
|
|
f := InitFixtures(t)
|
|
|
|
// start kvd server
|
|
proc := f.GDStart()
|
|
defer proc.Stop(false)
|
|
|
|
barAddr := f.KeyAddress(keyBar)
|
|
barVal := sdk.ValAddress(barAddr)
|
|
|
|
consPubKey := sdk.MustBech32ifyPubKey(sdk.Bech32PubKeyTypeConsPub, ed25519.GenPrivKey().PubKey())
|
|
|
|
sendTokens := sdk.TokensFromConsensusPower(10)
|
|
f.TxSend(keyFoo, barAddr, sdk.NewCoin(denom, sendTokens), "-y")
|
|
tests.WaitForNextNBlocksTM(1, f.Port)
|
|
|
|
barAcc := f.QueryAccount(barAddr)
|
|
require.Equal(t, sendTokens, barAcc.GetCoins().AmountOf(denom))
|
|
|
|
// Generate a create validator transaction and ensure correctness
|
|
success, stdout, stderr := f.TxStakingCreateValidator(barAddr.String(), consPubKey, sdk.NewInt64Coin(denom, 2), "--generate-only")
|
|
require.True(f.T, success)
|
|
require.Empty(f.T, stderr)
|
|
|
|
msg := f.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
|
|
newValTokens := sdk.TokensFromConsensusPower(2)
|
|
success, _, _ = f.TxStakingCreateValidator(barAddr.String(), consPubKey, sdk.NewCoin(denom, newValTokens), "--dry-run")
|
|
require.True(t, success)
|
|
|
|
// Create the validator
|
|
f.TxStakingCreateValidator(keyBar, consPubKey, sdk.NewCoin(denom, newValTokens), "-y")
|
|
tests.WaitForNextNBlocksTM(1, f.Port)
|
|
|
|
// Ensure funds were deducted properly
|
|
barAcc = f.QueryAccount(barAddr)
|
|
require.Equal(t, sendTokens.Sub(newValTokens), barAcc.GetCoins().AmountOf(denom))
|
|
|
|
// Ensure that validator state is as expected
|
|
validator := f.QueryStakingValidator(barVal)
|
|
require.Equal(t, validator.OperatorAddress, barVal)
|
|
require.True(sdk.IntEq(t, newValTokens, 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
|
|
unbondAmt := sdk.NewCoin(sdk.DefaultBondDenom, sdk.TokensFromConsensusPower(1))
|
|
success = f.TxStakingUnbond(keyBar, unbondAmt.String(), barVal, "-y")
|
|
require.True(t, success)
|
|
tests.WaitForNextNBlocksTM(1, f.Port)
|
|
|
|
// Ensure bonded staking is correct
|
|
remainingTokens := newValTokens.Sub(unbondAmt.Amount)
|
|
validator = f.QueryStakingValidator(barVal)
|
|
require.Equal(t, remainingTokens, validator.Tokens)
|
|
|
|
// 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, remainingTokens.String(), validatorUbds[0].Entries[0].Balance.String())
|
|
|
|
f.Cleanup()
|
|
}
|
|
|
|
func TestKvCLIQueryRewards(t *testing.T) {
|
|
t.Parallel()
|
|
f := InitFixtures(t)
|
|
|
|
genesisState := f.GenesisState()
|
|
inflationMin := sdk.MustNewDecFromStr("1.0")
|
|
var mintData mint.GenesisState
|
|
f.cdc.UnmarshalJSON(genesisState[mint.ModuleName], &mintData)
|
|
mintData.Minter.Inflation = inflationMin
|
|
mintData.Params.InflationMin = inflationMin
|
|
mintData.Params.InflationMax = sdk.MustNewDecFromStr("1.0")
|
|
mintDataBz, err := f.cdc.MarshalJSON(mintData)
|
|
require.NoError(t, err)
|
|
genesisState[mint.ModuleName] = mintDataBz
|
|
|
|
genFile := filepath.Join(f.KvdHome, "config", "genesis.json")
|
|
genDoc, err := tmtypes.GenesisDocFromFile(genFile)
|
|
require.NoError(t, err)
|
|
genDoc.AppState, err = f.cdc.MarshalJSON(genesisState)
|
|
require.NoError(t, genDoc.SaveAs(genFile))
|
|
|
|
// start kvd server
|
|
proc := f.GDStart()
|
|
defer proc.Stop(false)
|
|
|
|
fooAddr := f.KeyAddress(keyFoo)
|
|
rewards := f.QueryRewards(fooAddr)
|
|
require.Equal(t, 1, len(rewards.Rewards))
|
|
|
|
f.Cleanup()
|
|
}
|
|
|
|
func TestKvCLIQuerySupply(t *testing.T) {
|
|
t.Parallel()
|
|
f := InitFixtures(t)
|
|
|
|
// start kvd server
|
|
proc := f.GDStart()
|
|
defer proc.Stop(false)
|
|
|
|
totalSupply := f.QueryTotalSupply()
|
|
totalSupplyOf := f.QueryTotalSupplyOf(fooDenom)
|
|
|
|
require.Equal(t, totalCoins, totalSupply)
|
|
require.True(sdk.IntEq(t, totalCoins.AmountOf(fooDenom), totalSupplyOf))
|
|
|
|
f.Cleanup()
|
|
}
|
|
|
|
func TestKvCLISubmitProposal(t *testing.T) {
|
|
t.Parallel()
|
|
f := InitFixtures(t)
|
|
|
|
// start kvd server
|
|
proc := f.GDStart()
|
|
defer proc.Stop(false)
|
|
|
|
f.QueryGovParamDeposit()
|
|
f.QueryGovParamVoting()
|
|
f.QueryGovParamTallying()
|
|
|
|
fooAddr := f.KeyAddress(keyFoo)
|
|
|
|
fooAcc := f.QueryAccount(fooAddr)
|
|
startTokens := sdk.TokensFromConsensusPower(50)
|
|
require.Equal(t, startTokens, fooAcc.GetCoins().AmountOf(sdk.DefaultBondDenom))
|
|
|
|
proposalsQuery := f.QueryGovProposals()
|
|
require.Empty(t, proposalsQuery)
|
|
|
|
// Test submit generate only for submit proposal
|
|
proposalTokens := sdk.TokensFromConsensusPower(5)
|
|
success, stdout, stderr := f.TxGovSubmitProposal(
|
|
fooAddr.String(), "Text", "Test", "test", sdk.NewCoin(denom, proposalTokens), "--generate-only", "-y")
|
|
require.True(t, success)
|
|
require.Empty(t, stderr)
|
|
msg := f.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.NewCoin(denom, proposalTokens), "--dry-run")
|
|
require.True(t, success)
|
|
|
|
// Create the proposal
|
|
f.TxGovSubmitProposal(keyFoo, "Text", "Test", "test", sdk.NewCoin(denom, proposalTokens), "-y")
|
|
tests.WaitForNextNBlocksTM(1, f.Port)
|
|
|
|
// Ensure transaction events can be queried
|
|
searchResult := f.QueryTxs(1, 50, "message.action=submit_proposal", fmt.Sprintf("message.sender=%s", fooAddr))
|
|
require.Len(t, searchResult.Txs, 1)
|
|
|
|
// Ensure deposit was deducted
|
|
fooAcc = f.QueryAccount(fooAddr)
|
|
require.Equal(t, startTokens.Sub(proposalTokens), fooAcc.GetCoins().AmountOf(denom))
|
|
|
|
// Ensure propsal is directly queryable
|
|
proposal1 := f.QueryGovProposal(1)
|
|
require.Equal(t, uint64(1), proposal1.ProposalID)
|
|
require.Equal(t, gov.StatusDepositPeriod, proposal1.Status)
|
|
|
|
// Ensure query proposals returns properly
|
|
proposalsQuery = f.QueryGovProposals()
|
|
require.Equal(t, uint64(1), proposalsQuery[0].ProposalID)
|
|
|
|
// Query the deposits on the proposal
|
|
deposit := f.QueryGovDeposit(1, fooAddr)
|
|
require.Equal(t, proposalTokens, deposit.Amount.AmountOf(denom))
|
|
|
|
// Test deposit generate only
|
|
depositTokens := sdk.TokensFromConsensusPower(10)
|
|
success, stdout, stderr = f.TxGovDeposit(1, fooAddr.String(), sdk.NewCoin(denom, depositTokens), "--generate-only")
|
|
require.True(t, success)
|
|
require.Empty(t, stderr)
|
|
msg = f.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.NewCoin(denom, depositTokens), "-y")
|
|
tests.WaitForNextNBlocksTM(1, f.Port)
|
|
|
|
// test query deposit
|
|
deposits := f.QueryGovDeposits(1)
|
|
require.Len(t, deposits, 1)
|
|
require.Equal(t, proposalTokens.Add(depositTokens), deposits[0].Amount.AmountOf(denom))
|
|
|
|
// Ensure querying the deposit returns the proper amount
|
|
deposit = f.QueryGovDeposit(1, fooAddr)
|
|
require.Equal(t, proposalTokens.Add(depositTokens), deposit.Amount.AmountOf(denom))
|
|
|
|
// Ensure events are set on the transaction
|
|
searchResult = f.QueryTxs(1, 50, "message.action=deposit", fmt.Sprintf("message.sender=%s", fooAddr))
|
|
require.Len(t, searchResult.Txs, 1)
|
|
|
|
// Ensure account has expected amount of funds
|
|
fooAcc = f.QueryAccount(fooAddr)
|
|
require.Equal(t, startTokens.Sub(proposalTokens.Add(depositTokens)), fooAcc.GetCoins().AmountOf(denom))
|
|
|
|
// Fetch the proposal and ensure it is now in the voting period
|
|
proposal1 = f.QueryGovProposal(1)
|
|
require.Equal(t, uint64(1), proposal1.ProposalID)
|
|
require.Equal(t, gov.StatusVotingPeriod, proposal1.Status)
|
|
|
|
// Test vote generate only
|
|
success, stdout, stderr = f.TxGovVote(1, gov.OptionYes, fooAddr.String(), "--generate-only")
|
|
require.True(t, success)
|
|
require.Empty(t, stderr)
|
|
msg = f.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, "-y")
|
|
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 events are applied to voting transaction properly
|
|
searchResult = f.QueryTxs(1, 50, "message.action=vote", fmt.Sprintf("message.sender=%s", fooAddr))
|
|
require.Len(t, searchResult.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].ProposalID)
|
|
|
|
// submit a second test proposal
|
|
f.TxGovSubmitProposal(keyFoo, "Text", "Apples", "test", sdk.NewCoin(denom, proposalTokens), "-y")
|
|
tests.WaitForNextNBlocksTM(1, f.Port)
|
|
|
|
// Test limit on proposals query
|
|
proposalsQuery = f.QueryGovProposals("--limit=2")
|
|
require.Len(t, proposalsQuery, 2)
|
|
require.Equal(t, uint64(1), proposalsQuery[0].ProposalID)
|
|
|
|
f.Cleanup()
|
|
}
|
|
|
|
func TestKvCLISubmitParamChangeProposal(t *testing.T) {
|
|
t.Parallel()
|
|
f := InitFixtures(t)
|
|
|
|
proc := f.GDStart()
|
|
defer proc.Stop(false)
|
|
|
|
fooAddr := f.KeyAddress(keyFoo)
|
|
fooAcc := f.QueryAccount(fooAddr)
|
|
startTokens := sdk.TokensFromConsensusPower(50)
|
|
require.Equal(t, startTokens, fooAcc.GetCoins().AmountOf(sdk.DefaultBondDenom))
|
|
|
|
// write proposal to file
|
|
proposalTokens := sdk.TokensFromConsensusPower(5)
|
|
proposal := fmt.Sprintf(`{
|
|
"title": "Param Change",
|
|
"description": "Update max validators",
|
|
"changes": [
|
|
{
|
|
"subspace": "staking",
|
|
"key": "MaxValidators",
|
|
"value": 105
|
|
}
|
|
],
|
|
"deposit": [
|
|
{
|
|
"denom": "%s",
|
|
"amount": "%s"
|
|
}
|
|
]
|
|
}
|
|
`, sdk.DefaultBondDenom, proposalTokens.String())
|
|
|
|
proposalFile := WriteToNewTempFile(t, proposal)
|
|
|
|
// create the param change proposal
|
|
f.TxGovSubmitParamChangeProposal(keyFoo, proposalFile.Name(), sdk.NewCoin(denom, proposalTokens), "-y")
|
|
tests.WaitForNextNBlocksTM(1, f.Port)
|
|
|
|
// ensure transaction events can be queried
|
|
txsPage := f.QueryTxs(1, 50, "message.action=submit_proposal", fmt.Sprintf("message.sender=%s", fooAddr))
|
|
require.Len(t, txsPage.Txs, 1)
|
|
|
|
// ensure deposit was deducted
|
|
fooAcc = f.QueryAccount(fooAddr)
|
|
require.Equal(t, startTokens.Sub(proposalTokens).String(), fooAcc.GetCoins().AmountOf(sdk.DefaultBondDenom).String())
|
|
|
|
// ensure proposal is directly queryable
|
|
proposal1 := f.QueryGovProposal(1)
|
|
require.Equal(t, uint64(1), proposal1.ProposalID)
|
|
require.Equal(t, gov.StatusDepositPeriod, proposal1.Status)
|
|
|
|
// ensure correct query proposals result
|
|
proposalsQuery := f.QueryGovProposals()
|
|
require.Equal(t, uint64(1), proposalsQuery[0].ProposalID)
|
|
|
|
// ensure the correct deposit amount on the proposal
|
|
deposit := f.QueryGovDeposit(1, fooAddr)
|
|
require.Equal(t, proposalTokens, deposit.Amount.AmountOf(denom))
|
|
|
|
// Cleanup testing directories
|
|
f.Cleanup()
|
|
}
|
|
|
|
func TestKvCLISubmitCommunityPoolSpendProposal(t *testing.T) {
|
|
t.Parallel()
|
|
f := InitFixtures(t)
|
|
|
|
// create some inflation
|
|
genesisState := f.GenesisState()
|
|
inflationMin := sdk.MustNewDecFromStr("1.0")
|
|
var mintData mint.GenesisState
|
|
f.cdc.UnmarshalJSON(genesisState[mint.ModuleName], &mintData)
|
|
mintData.Minter.Inflation = inflationMin
|
|
mintData.Params.InflationMin = inflationMin
|
|
mintData.Params.InflationMax = sdk.MustNewDecFromStr("1.0")
|
|
mintDataBz, err := f.cdc.MarshalJSON(mintData)
|
|
require.NoError(t, err)
|
|
genesisState[mint.ModuleName] = mintDataBz
|
|
|
|
genFile := filepath.Join(f.KvdHome, "config", "genesis.json")
|
|
genDoc, err := tmtypes.GenesisDocFromFile(genFile)
|
|
require.NoError(t, err)
|
|
genDoc.AppState, err = f.cdc.MarshalJSON(genesisState)
|
|
require.NoError(t, genDoc.SaveAs(genFile))
|
|
|
|
proc := f.GDStart()
|
|
defer proc.Stop(false)
|
|
|
|
fooAddr := f.KeyAddress(keyFoo)
|
|
fooAcc := f.QueryAccount(fooAddr)
|
|
startTokens := sdk.TokensFromConsensusPower(50)
|
|
require.Equal(t, startTokens, fooAcc.GetCoins().AmountOf(sdk.DefaultBondDenom))
|
|
|
|
tests.WaitForNextNBlocksTM(3, f.Port)
|
|
|
|
// write proposal to file
|
|
proposalTokens := sdk.TokensFromConsensusPower(5)
|
|
proposal := fmt.Sprintf(`{
|
|
"title": "Community Pool Spend",
|
|
"description": "Spend from community pool",
|
|
"recipient": "%s",
|
|
"amount": [
|
|
{
|
|
"denom": "%s",
|
|
"amount": "1"
|
|
}
|
|
],
|
|
"deposit": [
|
|
{
|
|
"denom": "%s",
|
|
"amount": "%s"
|
|
}
|
|
]
|
|
}
|
|
`, fooAddr, sdk.DefaultBondDenom, sdk.DefaultBondDenom, proposalTokens.String())
|
|
proposalFile := WriteToNewTempFile(t, proposal)
|
|
|
|
// create the param change proposal
|
|
f.TxGovSubmitCommunityPoolSpendProposal(keyFoo, proposalFile.Name(), sdk.NewCoin(denom, proposalTokens), "-y")
|
|
tests.WaitForNextNBlocksTM(1, f.Port)
|
|
|
|
// ensure transaction events can be queried
|
|
txsPage := f.QueryTxs(1, 50, "message.action=submit_proposal", fmt.Sprintf("message.sender=%s", fooAddr))
|
|
require.Len(t, txsPage.Txs, 1)
|
|
|
|
// ensure deposit was deducted
|
|
fooAcc = f.QueryAccount(fooAddr)
|
|
require.Equal(t, startTokens.Sub(proposalTokens).String(), fooAcc.GetCoins().AmountOf(sdk.DefaultBondDenom).String())
|
|
|
|
// ensure proposal is directly queryable
|
|
proposal1 := f.QueryGovProposal(1)
|
|
require.Equal(t, uint64(1), proposal1.ProposalID)
|
|
require.Equal(t, gov.StatusDepositPeriod, proposal1.Status)
|
|
|
|
// ensure correct query proposals result
|
|
proposalsQuery := f.QueryGovProposals()
|
|
require.Equal(t, uint64(1), proposalsQuery[0].ProposalID)
|
|
|
|
// ensure the correct deposit amount on the proposal
|
|
deposit := f.QueryGovDeposit(1, fooAddr)
|
|
require.Equal(t, proposalTokens, deposit.Amount.AmountOf(denom))
|
|
|
|
// Cleanup testing directories
|
|
f.Cleanup()
|
|
}
|
|
|
|
func TestKvCLIQueryTxPagination(t *testing.T) {
|
|
// Skip until https://github.com/cometbft/cometbft/issues/4432 has been
|
|
// resolved and included in a release.
|
|
t.SkipNow()
|
|
|
|
t.Parallel()
|
|
f := InitFixtures(t)
|
|
|
|
// start kvd server
|
|
proc := f.GDStart()
|
|
defer proc.Stop(false)
|
|
|
|
fooAddr := f.KeyAddress(keyFoo)
|
|
barAddr := f.KeyAddress(keyBar)
|
|
|
|
accFoo := f.QueryAccount(fooAddr)
|
|
seq := accFoo.GetSequence()
|
|
|
|
for i := 1; i <= 30; i++ {
|
|
success, _, _ := f.TxSend(keyFoo, barAddr, sdk.NewInt64Coin(fooDenom, int64(i)), fmt.Sprintf("--sequence=%d", seq), "-y")
|
|
require.True(t, success)
|
|
seq++
|
|
}
|
|
|
|
// perPage = 15, 2 pages
|
|
txsPage1 := f.QueryTxs(1, 15, fmt.Sprintf("message.sender=%s", fooAddr))
|
|
require.Len(t, txsPage1.Txs, 15)
|
|
require.Equal(t, txsPage1.Count, 15)
|
|
txsPage2 := f.QueryTxs(2, 15, fmt.Sprintf("message.sender=%s", fooAddr))
|
|
require.Len(t, txsPage2.Txs, 15)
|
|
require.NotEqual(t, txsPage1.Txs, txsPage2.Txs)
|
|
|
|
// perPage = 16, 2 pages
|
|
txsPage1 = f.QueryTxs(1, 16, fmt.Sprintf("message.sender=%s", fooAddr))
|
|
require.Len(t, txsPage1.Txs, 16)
|
|
txsPage2 = f.QueryTxs(2, 16, fmt.Sprintf("message.sender=%s", fooAddr))
|
|
require.Len(t, txsPage2.Txs, 14)
|
|
require.NotEqual(t, txsPage1.Txs, txsPage2.Txs)
|
|
|
|
// perPage = 50
|
|
txsPageFull := f.QueryTxs(1, 50, fmt.Sprintf("message.sender=%s", fooAddr))
|
|
require.Len(t, txsPageFull.Txs, 30)
|
|
|
|
expected := txsPageFull.Txs
|
|
got := append(txsPage1.Txs, txsPage2.Txs...)
|
|
|
|
require.Equal(t, expected, got)
|
|
|
|
// perPage = 0
|
|
f.QueryTxsInvalid(errors.New("ERROR: page must greater than 0"), 0, 50, fmt.Sprintf("message.sender=%s", fooAddr))
|
|
|
|
// limit = 0
|
|
f.QueryTxsInvalid(errors.New("ERROR: limit must greater than 0"), 1, 0, fmt.Sprintf("message.sender=%s", fooAddr))
|
|
|
|
// Cleanup testing directories
|
|
f.Cleanup()
|
|
}
|
|
|
|
func TestKvCLIValidateSignatures(t *testing.T) {
|
|
t.Parallel()
|
|
f := InitFixtures(t)
|
|
|
|
// start kvd 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(fooAddr.String(), 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, _ = f.TxSign(keyFoo, unsignedTxFile.Name())
|
|
require.True(t, success)
|
|
stdTx := f.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 := f.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 TestKvCLISendGenerateSignAndBroadcast(t *testing.T) {
|
|
t.Parallel()
|
|
f := InitFixtures(t)
|
|
|
|
// start kvd server
|
|
proc := f.GDStart()
|
|
defer proc.Stop(false)
|
|
|
|
fooAddr := f.KeyAddress(keyFoo)
|
|
barAddr := f.KeyAddress(keyBar)
|
|
|
|
// Test generate sendTx with default gas
|
|
sendTokens := sdk.TokensFromConsensusPower(10)
|
|
success, stdout, stderr := f.TxSend(fooAddr.String(), barAddr, sdk.NewCoin(denom, sendTokens), "--generate-only")
|
|
require.True(t, success)
|
|
require.Empty(t, stderr)
|
|
msg := f.unmarshalStdTx(t, stdout)
|
|
require.Equal(t, msg.Fee.Gas, uint64(flags.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(fooAddr.String(), barAddr, sdk.NewCoin(denom, sendTokens), "--gas=100", "--generate-only")
|
|
require.True(t, success)
|
|
require.Empty(t, stderr)
|
|
msg = f.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(fooAddr.String(), barAddr, sdk.NewCoin(denom, sendTokens), "--generate-only")
|
|
require.True(t, success)
|
|
require.Empty(t, stderr)
|
|
msg = f.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")
|
|
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 = f.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")
|
|
require.True(t, success)
|
|
require.Equal(t, fmt.Sprintf("Signers:\n 0: %v\n\nSignatures:\n 0: %v\t\t\t[OK]\n\n", fooAddr.String(),
|
|
fooAddr.String()), stdout)
|
|
|
|
// Ensure foo has right amount of funds
|
|
fooAcc := f.QueryAccount(fooAddr)
|
|
startTokens := sdk.TokensFromConsensusPower(50)
|
|
require.Equal(t, startTokens, fooAcc.GetCoins().AmountOf(denom))
|
|
|
|
// Test broadcast
|
|
success, stdout, _ = f.TxBroadcast(signedTxFile.Name())
|
|
require.True(t, success)
|
|
tests.WaitForNextNBlocksTM(1, f.Port)
|
|
|
|
// Ensure account state
|
|
barAcc := f.QueryAccount(barAddr)
|
|
fooAcc = f.QueryAccount(fooAddr)
|
|
require.Equal(t, sendTokens, barAcc.GetCoins().AmountOf(denom))
|
|
require.Equal(t, startTokens.Sub(sendTokens), fooAcc.GetCoins().AmountOf(denom))
|
|
|
|
f.Cleanup()
|
|
}
|
|
|
|
func TestKvCLIMultisignInsufficientCosigners(t *testing.T) {
|
|
t.Parallel()
|
|
f := InitFixtures(t)
|
|
|
|
// start kvd 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), "-y")
|
|
require.True(t, success)
|
|
tests.WaitForNextNBlocksTM(1, f.Port)
|
|
|
|
// Test generate sendTx with multisig
|
|
success, stdout, _ := f.TxSend(fooBarBazAddr.String(), 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(), "-y")
|
|
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")
|
|
require.False(t, success)
|
|
|
|
// Broadcast the transaction
|
|
success, stdOut, _ := f.TxBroadcast(signedTxFile.Name())
|
|
require.Contains(t, stdOut, "signature verification failed")
|
|
require.True(t, success)
|
|
|
|
// Cleanup testing directories
|
|
f.Cleanup()
|
|
}
|
|
|
|
func TestKvCLIEncode(t *testing.T) {
|
|
t.Parallel()
|
|
f := InitFixtures(t)
|
|
|
|
// start kvd server
|
|
proc := f.GDStart()
|
|
defer proc.Stop(false)
|
|
|
|
// Build a testing transaction and write it to disk
|
|
barAddr := f.KeyAddress(keyBar)
|
|
keyAddr := f.KeyAddress(keyFoo)
|
|
|
|
sendTokens := sdk.TokensFromConsensusPower(10)
|
|
success, stdout, stderr := f.TxSend(keyAddr.String(), barAddr, sdk.NewCoin(denom, sendTokens), "--generate-only", "--memo", "deadbeef")
|
|
require.True(t, success)
|
|
require.Empty(t, stderr)
|
|
|
|
// Write it to disk
|
|
jsonTxFile := WriteToNewTempFile(t, stdout)
|
|
defer os.Remove(jsonTxFile.Name())
|
|
|
|
// Run the encode command, and trim the extras from the stdout capture
|
|
success, base64Encoded, _ := f.TxEncode(jsonTxFile.Name())
|
|
require.True(t, success)
|
|
trimmedBase64 := strings.Trim(base64Encoded, "\"\n")
|
|
|
|
// Decode the base64
|
|
decodedBytes, err := base64.StdEncoding.DecodeString(trimmedBase64)
|
|
require.Nil(t, err)
|
|
|
|
// Check that the transaction decodes as epxceted
|
|
var decodedTx auth.StdTx
|
|
require.Nil(t, f.cdc.UnmarshalBinaryLengthPrefixed(decodedBytes, &decodedTx))
|
|
require.Equal(t, "deadbeef", decodedTx.Memo)
|
|
}
|
|
|
|
func TestKvCLIMultisignSortSignatures(t *testing.T) {
|
|
t.Parallel()
|
|
f := InitFixtures(t)
|
|
|
|
// start kvd 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), "-y")
|
|
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(fooBarBazAddr.String(), 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")
|
|
require.True(t, success)
|
|
|
|
// Broadcast the transaction
|
|
success, _, _ = f.TxBroadcast(signedTxFile.Name())
|
|
require.True(t, success)
|
|
|
|
// Cleanup testing directories
|
|
f.Cleanup()
|
|
}
|
|
|
|
func TestKvCLIMultisign(t *testing.T) {
|
|
t.Parallel()
|
|
f := InitFixtures(t)
|
|
|
|
// start kvd 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), "-y")
|
|
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(fooBarBazAddr.String(), 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(), "-y")
|
|
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(), "-y")
|
|
require.True(t, success)
|
|
|
|
// Write the output to disk
|
|
barSignatureFile := WriteToNewTempFile(t, stdout)
|
|
defer os.Remove(barSignatureFile.Name())
|
|
|
|
// Multisign
|
|
|
|
// Does not work in offline mode
|
|
success, stdout, _ = f.TxMultisign(unsignedTxFile.Name(), keyFooBarBaz, []string{
|
|
fooSignatureFile.Name(), barSignatureFile.Name(),
|
|
}, "--offline")
|
|
require.Contains(t, "couldn't verify signature", stdout)
|
|
require.False(t, success)
|
|
|
|
// Success 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", "-y")
|
|
require.True(t, success)
|
|
|
|
// Broadcast the transaction
|
|
success, _, _ = f.TxBroadcast(signedTxFile.Name())
|
|
require.True(t, success)
|
|
|
|
// Cleanup testing directories
|
|
f.Cleanup()
|
|
}
|
|
|
|
func TestKvCLIConfig(t *testing.T) {
|
|
t.Parallel()
|
|
f := InitFixtures(t)
|
|
node := fmt.Sprintf("%s:%s", f.RPCAddr, f.Port)
|
|
|
|
// Set available configuration options
|
|
f.CLIConfig("broadcast-mode", "block")
|
|
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")
|
|
f.CLIConfig("keyring-backend", "test")
|
|
|
|
config, err := ioutil.ReadFile(path.Join(f.KvcliHome, "config", "config.toml"))
|
|
require.NoError(t, err)
|
|
expectedConfig := fmt.Sprintf(`broadcast-mode = "block"
|
|
chain-id = "%s"
|
|
indent = true
|
|
keyring-backend = "test"
|
|
node = "%s"
|
|
output = "text"
|
|
trace = false
|
|
trust-node = true
|
|
`, f.ChainID, node)
|
|
require.Equal(t, expectedConfig, string(config))
|
|
|
|
f.Cleanup()
|
|
}
|
|
|
|
func TestKvdCollectGentxs(t *testing.T) {
|
|
t.Parallel()
|
|
var customMaxBytes, customMaxGas int64 = 99999999, 1234567
|
|
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.KeysAdd(keyFoo)
|
|
|
|
// Configure json output
|
|
f.CLIConfig("output", "json")
|
|
|
|
// Run init
|
|
f.KvInit(keyFoo)
|
|
|
|
// Customise genesis.json
|
|
|
|
genFile := f.GenesisFile()
|
|
genDoc, err := tmtypes.GenesisDocFromFile(genFile)
|
|
require.NoError(t, err)
|
|
genDoc.ConsensusParams.Block.MaxBytes = customMaxBytes
|
|
genDoc.ConsensusParams.Block.MaxGas = customMaxGas
|
|
genDoc.SaveAs(genFile)
|
|
|
|
// 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))
|
|
|
|
genDoc, err = tmtypes.GenesisDocFromFile(genFile)
|
|
require.NoError(t, err)
|
|
require.Equal(t, genDoc.ConsensusParams.Block.MaxBytes, customMaxBytes)
|
|
require.Equal(t, genDoc.ConsensusParams.Block.MaxGas, customMaxGas)
|
|
|
|
f.Cleanup(gentxDir)
|
|
}
|
|
|
|
func TestKvdAddGenesisAccount(t *testing.T) {
|
|
t.Parallel()
|
|
f := NewFixtures(t)
|
|
|
|
// Reset testing path
|
|
f.UnsafeResetAll()
|
|
|
|
// Initialize keys
|
|
f.KeysDelete(keyFoo)
|
|
f.KeysDelete(keyBar)
|
|
f.KeysDelete(keyBaz)
|
|
f.KeysAdd(keyFoo)
|
|
f.KeysAdd(keyBar)
|
|
f.KeysAdd(keyBaz)
|
|
|
|
// Configure json output
|
|
f.CLIConfig("output", "json")
|
|
|
|
// Run init
|
|
f.KvInit(keyFoo)
|
|
|
|
// Add account to genesis.json
|
|
bazCoins := sdk.Coins{
|
|
sdk.NewInt64Coin("acoin", 1000000),
|
|
sdk.NewInt64Coin("bcoin", 1000000),
|
|
}
|
|
|
|
f.AddGenesisAccount(f.KeyAddress(keyFoo), startCoins)
|
|
f.AddGenesisAccount(f.KeyAddress(keyBar), bazCoins)
|
|
genesisState := f.GenesisState()
|
|
|
|
authGenState := auth.GetGenesisStateFromAppState(f.cdc, genesisState)
|
|
accounts := authGenState.Accounts
|
|
|
|
require.Equal(t, accounts[0].GetAddress(), f.KeyAddress(keyFoo))
|
|
require.Equal(t, accounts[1].GetAddress(), f.KeyAddress(keyBar))
|
|
require.True(t, accounts[0].GetCoins().IsEqual(startCoins))
|
|
require.True(t, accounts[1].GetCoins().IsEqual(bazCoins))
|
|
|
|
// Cleanup testing directories
|
|
f.Cleanup()
|
|
}
|
|
|
|
func TestSlashingGetParams(t *testing.T) {
|
|
t.Parallel()
|
|
f := InitFixtures(t)
|
|
|
|
// start kvd server
|
|
proc := f.GDStart()
|
|
defer proc.Stop(false)
|
|
|
|
params := f.QuerySlashingParams()
|
|
require.Equal(t, int64(100), params.SignedBlocksWindow)
|
|
require.Equal(t, sdk.NewDecWithPrec(5, 1), params.MinSignedPerWindow)
|
|
|
|
sinfo := f.QuerySigningInfo(f.GDTendermint("show-validator"))
|
|
require.Equal(t, int64(0), sinfo.StartHeight)
|
|
require.False(t, sinfo.Tombstoned)
|
|
|
|
// Cleanup testing directories
|
|
f.Cleanup()
|
|
}
|
|
|
|
func TestValidateGenesis(t *testing.T) {
|
|
t.Parallel()
|
|
f := InitFixtures(t)
|
|
|
|
// start kvd server
|
|
proc := f.GDStart()
|
|
defer proc.Stop(false)
|
|
|
|
f.ValidateGenesis()
|
|
|
|
// Cleanup testing directories
|
|
f.Cleanup()
|
|
}
|