x/auth: in-process test refactor (#6573)

* remove unused functions

* create helper func to send tx

* refactor to use test help to send tx by client

* Commit before getting backend.

* Temporal commit

* temp commit

* remove the creation of txbuilder from cli

* fix imports

* update changelog

* Remove unused function.

* Add flag home into tx sign command.

* migrade TestCLIValidateSignatures to use new test suite

* migrate test one

* Add changes to make sign batch.

* make test pass

* refactor common logic

* First part of cli sign.

* Add test for sign batch.

* refactor a little and improve the test

* migrate broadcast command

* fix linter

* Remove printf for debug in bank module.

* Fix unused err var.

* fix linter

* fix test

* fix tests client

* Fix linter.

* Temp commit signature.

* encode tx

* migrate tests

* Fix imports.

* Remove changelog

* fix tests

* Fix tests.

* Update x/bank/client/testutil/cli_helpers.go

* Remove alias.

* Remove wait for N block func.

* export callCmd function into its own file.

* fix imports

* bring back to inner functions

* apply mock io

* the helpers use mockio

* fix bug

* Add Helpers.

* return to put the function in testutil package

* return BufferWriter in ExecTestCLICmd

Co-authored-by: Alessio Treglia <alessio@tendermint.com>
Co-authored-by: Federico Kunze <31522760+fedekunze@users.noreply.github.com>
Co-authored-by: Alexander Bezobchuk <alexanderbez@users.noreply.github.com>
This commit is contained in:
Jonathan Gimeno
2020-07-14 18:37:14 +00:00
committed by GitHub
co-authored by Alessio Treglia Federico Kunze Alexander Bezobchuk
parent 5656e8647b
commit 351192aa0b
20 changed files with 754 additions and 531 deletions
+2 -2
View File
@@ -12,7 +12,7 @@ import (
)
// GetBroadcastCommand returns the tx broadcast command.
func GetBroadcastCommand(clientCtx client.Context) *cobra.Command {
func GetBroadcastCommand() *cobra.Command {
cmd := &cobra.Command{
Use: "broadcast [file_path]",
Short: "Broadcast transactions generated offline",
@@ -25,7 +25,7 @@ $ <appcli> tx broadcast ./mytxn.json
`),
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx = clientCtx.Init()
clientCtx := client.GetClientContextFromCmd(cmd)
if offline, _ := cmd.Flags().GetBool(flags.FlagOffline); offline {
return errors.New("cannot broadcast tx during offline mode")
-46
View File
@@ -1,46 +0,0 @@
package cli
import (
"fmt"
"io/ioutil"
"path/filepath"
"testing"
"github.com/stretchr/testify/require"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/flags"
simappparams "github.com/cosmos/cosmos-sdk/simapp/params"
"github.com/cosmos/cosmos-sdk/testutil"
)
func TestGetBroadcastCommand_OfflineFlag(t *testing.T) {
clientCtx := client.Context{}.WithOffline(true)
clientCtx = clientCtx.WithTxGenerator(simappparams.MakeEncodingConfig().TxGenerator)
cmd := GetBroadcastCommand(clientCtx)
_ = testutil.ApplyMockIODiscardOutErr(cmd)
cmd.SetArgs([]string{fmt.Sprintf("--%s=true", flags.FlagOffline), ""})
require.EqualError(t, cmd.Execute(), "cannot broadcast tx during offline mode")
}
func TestGetBroadcastCommand_WithoutOfflineFlag(t *testing.T) {
clientCtx := client.Context{}
clientCtx = clientCtx.WithTxGenerator(simappparams.MakeEncodingConfig().TxGenerator)
cmd := GetBroadcastCommand(clientCtx)
testDir, cleanFunc := testutil.NewTestCaseDir(t)
t.Cleanup(cleanFunc)
// Create new file with tx
txContents := []byte("{\"type\":\"cosmos-sdk/StdTx\",\"value\":{\"msg\":[{\"type\":\"cosmos-sdk/MsgSend\",\"value\":{\"from_address\":\"cosmos1cxlt8kznps92fwu3j6npahx4mjfutydyene2qw\",\"to_address\":\"cosmos1wc8mpr8m3sy3ap3j7fsgqfzx36um05pystems4\",\"amount\":[{\"denom\":\"stake\",\"amount\":\"10000\"}]}}],\"fee\":{\"amount\":[],\"gas\":\"200000\"},\"signatures\":null,\"memo\":\"\"}}")
txFileName := filepath.Join(testDir, "tx.json")
err := ioutil.WriteFile(txFileName, txContents, 0644)
require.NoError(t, err)
err = cmd.RunE(cmd, []string{txFileName})
// We test it tries to broadcast but we set unsupported tx to get the error.
require.EqualError(t, err, "unsupported return type ; supported types: sync, async, block")
}
+547 -322
View File
@@ -1,452 +1,677 @@
// +build cli_test
package cli_test
import (
"context"
"fmt"
"io/ioutil"
"path/filepath"
"strings"
"testing"
"time"
"github.com/stretchr/testify/require"
"github.com/stretchr/testify/suite"
tmcrypto "github.com/tendermint/tendermint/crypto"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/flags"
"github.com/cosmos/cosmos-sdk/tests"
codec2 "github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/crypto/hd"
"github.com/cosmos/cosmos-sdk/crypto/keyring"
"github.com/cosmos/cosmos-sdk/crypto/types/multisig"
simappparams "github.com/cosmos/cosmos-sdk/simapp/params"
"github.com/cosmos/cosmos-sdk/tests/cli"
sdktestutil "github.com/cosmos/cosmos-sdk/testutil"
"github.com/cosmos/cosmos-sdk/testutil"
"github.com/cosmos/cosmos-sdk/testutil/network"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/auth/client/testutil"
cli2 "github.com/cosmos/cosmos-sdk/x/auth/client/cli"
authtest "github.com/cosmos/cosmos-sdk/x/auth/client/testutil"
"github.com/cosmos/cosmos-sdk/x/auth/types"
bankcli "github.com/cosmos/cosmos-sdk/x/bank/client/testutil"
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
)
func TestCLIValidateSignatures(t *testing.T) {
t.SkipNow()
t.Parallel()
f := cli.InitFixtures(t)
type IntegrationTestSuite struct {
suite.Suite
// start simd server
proc := f.SDStart()
t.Cleanup(func() { proc.Stop(false) })
cfg network.Config
network *network.Network
}
f.ValidateGenesis()
func (s *IntegrationTestSuite) SetupSuite() {
s.T().Log("setting up integration test suite")
fooAddr := f.KeyAddress(cli.KeyFoo)
barAddr := f.KeyAddress(cli.KeyBar)
cfg := network.DefaultConfig()
cfg.NumValidators = 1
// generate sendTx with default gas
success, stdout, stderr := bankcli.TxSend(f, fooAddr.String(), barAddr, sdk.NewInt64Coin("stake", 10), "--generate-only")
require.True(t, success)
require.Empty(t, stderr)
s.cfg = cfg
s.network = network.New(s.T(), cfg)
_, err := s.network.WaitForHeight(1)
s.Require().NoError(err)
}
func (s *IntegrationTestSuite) TearDownSuite() {
s.T().Log("tearing down integration test suite")
s.network.Cleanup()
}
func (s *IntegrationTestSuite) TestCLIValidateSignatures() {
val := s.network.Validators[0]
res, err := bankcli.MsgSendExec(
val.ClientCtx,
val.Address,
val.Address,
sdk.NewCoins(
sdk.NewCoin(fmt.Sprintf("%stoken", val.Moniker), sdk.NewInt(10)),
sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10)),
),
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
fmt.Sprintf("--%s=true", flags.FlagGenerateOnly),
)
s.Require().NoError(err)
var tx types.StdTx
err = val.ClientCtx.JSONMarshaler.UnmarshalJSON(res.Bytes(), &tx)
s.Require().NoError(err)
// write unsigned tx to file
unsignedTxFile, cleanup := sdktestutil.WriteToNewTempFile(t, stdout)
t.Cleanup(cleanup)
unsignedTx, cleanup := testutil.WriteToNewTempFile(s.T(), res.String())
defer cleanup()
// validate we can successfully sign
success, stdout, _ = testutil.TxSign(f, cli.KeyFoo, unsignedTxFile.Name())
require.True(t, success)
res, err = authtest.TxSignExec(val.ClientCtx, val.Address, unsignedTx.Name())
s.Require().NoError(err)
stdTx := cli.UnmarshalStdTx(t, f.Cdc, stdout)
var signedTx types.StdTx
err = val.ClientCtx.JSONMarshaler.UnmarshalJSON(res.Bytes(), &signedTx)
s.Require().NoError(err)
require.Equal(t, len(stdTx.Msgs), 1)
require.Equal(t, 1, len(stdTx.GetSignatures()))
require.Equal(t, fooAddr.String(), stdTx.GetSigners()[0].String())
signedTxFile, cleanup := testutil.WriteToNewTempFile(s.T(), res.String())
defer cleanup()
// write signed tx to file
signedTxFile, cleanup := sdktestutil.WriteToNewTempFile(t, stdout)
t.Cleanup(cleanup)
res, err = authtest.TxValidateSignaturesExec(val.ClientCtx, signedTxFile.Name())
s.Require().NoError(err)
// validate signatures
success, _, _ = testutil.TxValidateSignatures(f, signedTxFile.Name())
require.True(t, success)
signedTx.Memo = "MODIFIED STD TX"
bz, err := val.ClientCtx.JSONMarshaler.MarshalJSON(signedTx)
s.Require().NoError(err)
// modify the transaction
stdTx.Memo = "MODIFIED-ORIGINAL-TX-BAD"
bz := cli.MarshalStdTx(t, f.Cdc, stdTx)
modSignedTxFile, cleanup := sdktestutil.WriteToNewTempFile(t, string(bz))
t.Cleanup(cleanup)
modifiedTxFile, cleanup := testutil.WriteToNewTempFile(s.T(), string(bz))
defer cleanup()
// validate signature validation failure due to different transaction sig bytes
success, _, _ = testutil.TxValidateSignatures(f, modSignedTxFile.Name())
require.False(t, success)
// Cleanup testing directories
f.Cleanup()
res, err = authtest.TxValidateSignaturesExec(val.ClientCtx, modifiedTxFile.Name())
s.Require().EqualError(err, "signatures validation failed")
}
func TestCLISignBatch(t *testing.T) {
t.SkipNow()
t.Parallel()
f := cli.InitFixtures(t)
func (s *IntegrationTestSuite) TestCLISignBatch() {
val := s.network.Validators[0]
generatedStd, err := bankcli.MsgSendExec(
val.ClientCtx,
val.Address,
val.Address,
sdk.NewCoins(
sdk.NewCoin(fmt.Sprintf("%stoken", val.Moniker), sdk.NewInt(10)),
sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10)),
),
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
fmt.Sprintf("--%s=true", flags.FlagGenerateOnly),
)
fooAddr := f.KeyAddress(cli.KeyFoo)
barAddr := f.KeyAddress(cli.KeyBar)
sendTokens := sdk.TokensFromConsensusPower(10)
success, generatedStdTx, stderr := bankcli.TxSend(f, fooAddr.String(), barAddr, sdk.NewCoin(cli.Denom, sendTokens), "--generate-only")
require.True(t, success)
require.Empty(t, stderr)
s.Require().NoError(err)
// Write the output to disk
batchfile, cleanup1 := sdktestutil.WriteToNewTempFile(t, strings.Repeat(generatedStdTx, 3))
t.Cleanup(cleanup1)
filename, cleanup1 := testutil.WriteToNewTempFile(s.T(), strings.Repeat(generatedStd.String(), 3))
defer cleanup1()
// sign-batch file - offline is set but account-number and sequence are not
success, _, stderr = testutil.TxSignBatch(f, cli.KeyFoo, batchfile.Name(), "--offline")
require.Contains(t, stderr, "required flag(s) \"account-number\", \"sequence\" not set")
require.False(t, success)
val.ClientCtx.HomeDir = strings.Replace(val.ClientCtx.HomeDir, "simd", "simcli", 1)
res, err := authtest.TxSignBatchExec(val.ClientCtx, val.Address, filename.Name(), fmt.Sprintf("--%s=%s", flags.FlagChainID, val.ClientCtx.ChainID), "--offline")
s.Require().EqualError(err, "required flag(s) \"account-number\", \"sequence\" not set")
// sign-batch file
success, stdout, stderr := testutil.TxSignBatch(f, cli.KeyFoo, batchfile.Name())
require.True(t, success)
require.Empty(t, stderr)
require.Equal(t, 3, len(strings.Split(strings.Trim(stdout, "\n"), "\n")))
res, err = authtest.TxSignBatchExec(val.ClientCtx, val.Address, filename.Name(), fmt.Sprintf("--%s=%s", flags.FlagChainID, val.ClientCtx.ChainID))
s.Require().NoError(err)
s.Require().Equal(3, len(strings.Split(strings.Trim(res.String(), "\n"), "\n")))
// sign-batch file
success, stdout, stderr = testutil.TxSignBatch(f, cli.KeyFoo, batchfile.Name(), "--signature-only")
require.True(t, success)
require.Empty(t, stderr)
require.Equal(t, 3, len(strings.Split(strings.Trim(stdout, "\n"), "\n")))
res, err = authtest.TxSignBatchExec(val.ClientCtx, val.Address, filename.Name(), fmt.Sprintf("--%s=%s", flags.FlagChainID, val.ClientCtx.ChainID), "--signature-only")
s.Require().NoError(err)
s.Require().Equal(3, len(strings.Split(strings.Trim(res.String(), "\n"), "\n")))
malformedFile, cleanup2 := sdktestutil.WriteToNewTempFile(t, fmt.Sprintf("%smalformed", generatedStdTx))
t.Cleanup(cleanup2)
// Sign batch malformed tx file.
malformedFile, cleanup2 := testutil.WriteToNewTempFile(s.T(), fmt.Sprintf("%smalformed", generatedStd))
defer cleanup2()
// sign-batch file
success, stdout, stderr = testutil.TxSignBatch(f, cli.KeyFoo, malformedFile.Name())
require.False(t, success)
require.Equal(t, 1, len(strings.Split(strings.Trim(stdout, "\n"), "\n")))
require.Equal(t, "ERROR: cannot parse disfix JSON wrapper: invalid character 'm' looking for beginning of value\n", stderr)
res, err = authtest.TxSignBatchExec(val.ClientCtx, val.Address, malformedFile.Name(), fmt.Sprintf("--%s=%s", flags.FlagChainID, val.ClientCtx.ChainID))
s.Require().EqualError(err, "cannot parse disfix JSON wrapper: invalid character 'm' looking for beginning of value")
// sign-batch file
success, stdout, _ = testutil.TxSignBatch(f, cli.KeyFoo, malformedFile.Name(), "--signature-only")
require.False(t, success)
require.Equal(t, 1, len(strings.Split(strings.Trim(stdout, "\n"), "\n")))
f.Cleanup()
// Sign batch malformed tx file signature only.
res, err = authtest.TxSignBatchExec(val.ClientCtx, val.Address, malformedFile.Name(), fmt.Sprintf("--%s=%s", flags.FlagChainID, val.ClientCtx.ChainID), "--signature-only")
s.Require().EqualError(err, "cannot parse disfix JSON wrapper: invalid character 'm' looking for beginning of value")
}
func TestCLISendGenerateSignAndBroadcast(t *testing.T) {
t.SkipNow()
t.Parallel()
f := cli.InitFixtures(t)
func (s *IntegrationTestSuite) TestCLISendGenerateSignAndBroadcast() {
val1 := s.network.Validators[0]
// start simd server
proc := f.SDStart()
t.Cleanup(func() { proc.Stop(false) })
account, _, err := val1.ClientCtx.Keyring.NewMnemonic("newAccount", keyring.English, sdk.FullFundraiserPath, hd.Secp256k1)
s.Require().NoError(err)
fooAddr := f.KeyAddress(cli.KeyFoo)
barAddr := f.KeyAddress(cli.KeyBar)
// Test generate sendTx with default gas
sendTokens := sdk.TokensFromConsensusPower(10)
success, stdout, stderr := bankcli.TxSend(f, fooAddr.String(), barAddr, sdk.NewCoin(cli.Denom, sendTokens), "--generate-only")
require.True(t, success)
require.Empty(t, stderr)
msg := cli.UnmarshalStdTx(t, f.Cdc, stdout)
require.Equal(t, msg.Fee.Gas, uint64(flags.DefaultGasLimit))
require.Equal(t, len(msg.Msgs), 1)
require.Equal(t, 0, len(msg.GetSignatures()))
normalGeneratedTx, err := bankcli.MsgSendExec(
val1.ClientCtx,
val1.Address,
account.GetAddress(),
sdk.NewCoins(
sdk.NewCoin(s.cfg.BondDenom, sendTokens),
),
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
fmt.Sprintf("--%s=true", flags.FlagGenerateOnly),
)
s.Require().NoError(err)
normalGeneratedStdTx := cli.UnmarshalStdTx(s.T(), val1.ClientCtx.JSONMarshaler, normalGeneratedTx.String())
s.Require().Equal(normalGeneratedStdTx.Fee.Gas, uint64(flags.DefaultGasLimit))
s.Require().Equal(len(normalGeneratedStdTx.Msgs), 1)
s.Require().Equal(0, len(normalGeneratedStdTx.GetSignatures()))
// Test generate sendTx with --gas=$amount
success, stdout, stderr = bankcli.TxSend(f, fooAddr.String(), barAddr, sdk.NewCoin(cli.Denom, sendTokens), "--gas=100", "--generate-only")
require.True(t, success)
require.Empty(t, stderr)
limitedGasGeneratedTx, err := bankcli.MsgSendExec(
val1.ClientCtx,
val1.Address,
account.GetAddress(),
sdk.NewCoins(
sdk.NewCoin(s.cfg.BondDenom, sendTokens),
),
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
fmt.Sprintf("--gas=%d", 100),
fmt.Sprintf("--%s=true", flags.FlagGenerateOnly),
)
s.Require().NoError(err)
msg = cli.UnmarshalStdTx(t, f.Cdc, stdout)
require.Equal(t, msg.Fee.Gas, uint64(100))
require.Equal(t, len(msg.Msgs), 1)
require.Equal(t, 0, len(msg.GetSignatures()))
limitedGasStdTx := cli.UnmarshalStdTx(s.T(), val1.ClientCtx.JSONMarshaler, limitedGasGeneratedTx.String())
s.Require().Equal(limitedGasStdTx.Fee.Gas, uint64(100))
s.Require().Equal(len(limitedGasStdTx.Msgs), 1)
s.Require().Equal(0, len(limitedGasStdTx.GetSignatures()))
// Test generate sendTx, estimate gas
success, stdout, stderr = bankcli.TxSend(f, fooAddr.String(), barAddr, sdk.NewCoin(cli.Denom, sendTokens), "--generate-only")
require.True(t, success)
require.Empty(t, stderr)
msg = cli.UnmarshalStdTx(t, f.Cdc, stdout)
require.True(t, msg.Fee.Gas > 0)
require.Equal(t, len(msg.Msgs), 1)
finalGeneratedTx, err := bankcli.MsgSendExec(
val1.ClientCtx,
val1.Address,
account.GetAddress(),
sdk.NewCoins(
sdk.NewCoin(s.cfg.BondDenom, sendTokens),
),
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
fmt.Sprintf("--gas=%d", flags.DefaultGasLimit),
fmt.Sprintf("--%s=true", flags.FlagGenerateOnly),
)
s.Require().NoError(err)
finalStdTx := cli.UnmarshalStdTx(s.T(), val1.ClientCtx.JSONMarshaler, finalGeneratedTx.String())
s.Require().Equal(uint64(flags.DefaultGasLimit), finalStdTx.Fee.Gas)
s.Require().Equal(len(finalStdTx.Msgs), 1)
// Write the output to disk
unsignedTxFile, cleanup := sdktestutil.WriteToNewTempFile(t, stdout)
t.Cleanup(cleanup)
unsignedTxFile, cleanup := testutil.WriteToNewTempFile(s.T(), finalGeneratedTx.String())
defer cleanup()
// Test validate-signatures
success, stdout, _ = testutil.TxValidateSignatures(f, unsignedTxFile.Name())
require.False(t, success)
require.Equal(t, fmt.Sprintf("Signers:\n 0: %v\n\nSignatures:\n\n", fooAddr.String()), stdout)
res, err := authtest.TxValidateSignaturesExec(val1.ClientCtx, unsignedTxFile.Name())
s.Require().EqualError(err, "signatures validation failed")
s.Require().True(strings.Contains(res.String(), fmt.Sprintf("Signers:\n 0: %v\n\nSignatures:\n\n", val1.Address.String())))
// Test sign
// Does not work in offline mode
success, stdout, stderr = testutil.TxSign(f, cli.KeyFoo, unsignedTxFile.Name(), "--offline")
require.Contains(t, stderr, "required flag(s) \"account-number\", \"sequence\" not set")
require.False(t, success)
res, err = authtest.TxSignExec(val1.ClientCtx, val1.Address, unsignedTxFile.Name(), "--offline")
s.Require().EqualError(err, "required flag(s) \"account-number\", \"sequence\" not set")
// But works offline if we set account number and sequence
success, _, _ = testutil.TxSign(f, cli.KeyFoo, unsignedTxFile.Name(), "--offline", "--account-number", "1", "--sequence", "1")
require.True(t, success)
val1.ClientCtx.HomeDir = strings.Replace(val1.ClientCtx.HomeDir, "simd", "simcli", 1)
res, err = authtest.TxSignExec(val1.ClientCtx, val1.Address, unsignedTxFile.Name(), "--offline", "--account-number", "1", "--sequence", "1")
s.Require().NoError(err)
// Sign transaction
success, stdout, _ = testutil.TxSign(f, cli.KeyFoo, unsignedTxFile.Name())
require.True(t, success)
msg = cli.UnmarshalStdTx(t, f.Cdc, stdout)
require.Equal(t, len(msg.Msgs), 1)
require.Equal(t, 1, len(msg.GetSignatures()))
require.Equal(t, fooAddr.String(), msg.GetSigners()[0].String())
signedTx, err := authtest.TxSignExec(val1.ClientCtx, val1.Address, unsignedTxFile.Name())
s.Require().NoError(err)
signedFinalTx := cli.UnmarshalStdTx(s.T(), val1.ClientCtx.JSONMarshaler, signedTx.String())
s.Require().Equal(len(signedFinalTx.Msgs), 1)
s.Require().Equal(1, len(signedFinalTx.GetSignatures()))
s.Require().Equal(val1.Address.String(), signedFinalTx.GetSigners()[0].String())
// Write the output to disk
signedTxFile, cleanup := sdktestutil.WriteToNewTempFile(t, stdout)
t.Cleanup(cleanup)
signedTxFile, cleanup2 := testutil.WriteToNewTempFile(s.T(), signedTx.String())
defer cleanup2()
// Test validate-signatures
success, stdout, _ = testutil.TxValidateSignatures(f, signedTxFile.Name())
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)
// Validate Signature
res, err = authtest.TxValidateSignaturesExec(val1.ClientCtx, signedTxFile.Name())
s.Require().NoError(err)
s.Require().True(strings.Contains(res.String(), "[OK]"))
// Ensure foo has right amount of funds
startTokens := sdk.TokensFromConsensusPower(50)
require.Equal(t, startTokens, bankcli.QueryBalances(f, fooAddr).AmountOf(cli.Denom))
startTokens := sdk.TokensFromConsensusPower(400)
resp, err := bankcli.QueryBalancesExec(val1.ClientCtx, val1.Address)
s.Require().NoError(err)
var coins sdk.Coins
err = val1.ClientCtx.JSONMarshaler.UnmarshalJSON(resp.Bytes(), &coins)
s.Require().NoError(err)
s.Require().Equal(startTokens, coins.AmountOf(cli.Denom))
// Test broadcast
// Does not work in offline mode
success, _, stderr = testutil.TxBroadcast(f, signedTxFile.Name(), "--offline")
require.Contains(t, stderr, "cannot broadcast tx during offline mode")
require.False(t, success)
tests.WaitForNextNBlocksTM(1, f.Port)
res, err = authtest.TxBroadcastExec(val1.ClientCtx, signedTxFile.Name(), "--offline")
s.Require().EqualError(err, "cannot broadcast tx during offline mode")
success, stdout, _ = testutil.TxBroadcast(f, signedTxFile.Name())
require.True(t, success)
tests.WaitForNextNBlocksTM(1, f.Port)
err = waitForNextBlock(s.network)
s.Require().NoError(err)
// Ensure account state
require.Equal(t, sendTokens, bankcli.QueryBalances(f, barAddr).AmountOf(cli.Denom))
require.Equal(t, startTokens.Sub(sendTokens), bankcli.QueryBalances(f, fooAddr).AmountOf(cli.Denom))
// Broadcast correct transaction.
val1.ClientCtx.BroadcastMode = flags.BroadcastBlock
res, err = authtest.TxBroadcastExec(val1.ClientCtx, signedTxFile.Name())
s.Require().NoError(err)
f.Cleanup()
err = waitForNextBlock(s.network)
s.Require().NoError(err)
// Ensure destiny account state
resp, err = bankcli.QueryBalancesExec(val1.ClientCtx, account.GetAddress())
s.Require().NoError(err)
err = val1.ClientCtx.JSONMarshaler.UnmarshalJSON(resp.Bytes(), &coins)
s.Require().NoError(err)
s.Require().Equal(sendTokens, coins.AmountOf(cli.Denom))
// Ensure origin account state
resp, err = bankcli.QueryBalancesExec(val1.ClientCtx, val1.Address)
s.Require().NoError(err)
err = val1.ClientCtx.JSONMarshaler.UnmarshalJSON(resp.Bytes(), &coins)
s.Require().NoError(err)
s.Require().Equal(sdk.NewInt(389999990), coins.AmountOf(cli.Denom))
}
func TestCLIMultisignInsufficientCosigners(t *testing.T) {
t.SkipNow()
t.Parallel()
f := cli.InitFixtures(t)
func (s *IntegrationTestSuite) TestCLIMultisignInsufficientCosigners() {
s.T().SkipNow() // TODO check encoding.
val1 := s.network.Validators[0]
// start simd server with minimum fees
proc := f.SDStart()
t.Cleanup(func() { proc.Stop(false) })
codec := codec2.New()
sdk.RegisterCodec(codec)
banktypes.RegisterCodec(codec)
val1.ClientCtx.Codec = codec
fooBarBazAddr := f.KeyAddress(cli.KeyFooBarBaz)
barAddr := f.KeyAddress(cli.KeyBar)
// Generate 2 accounts and a multisig.
account1, _, err := val1.ClientCtx.Keyring.NewMnemonic("newAccount1", keyring.English, sdk.FullFundraiserPath, hd.Secp256k1)
s.Require().NoError(err)
// Send some tokens from one account to the other
success, _, _ := bankcli.TxSend(f, cli.KeyFoo, fooBarBazAddr, sdk.NewInt64Coin(cli.Denom, 10), "-y")
require.True(t, success)
tests.WaitForNextNBlocksTM(1, f.Port)
account2, _, err := val1.ClientCtx.Keyring.NewMnemonic("newAccount2", keyring.English, sdk.FullFundraiserPath, hd.Secp256k1)
s.Require().NoError(err)
// Test generate sendTx with multisig
success, stdout, _ := bankcli.TxSend(f, fooBarBazAddr.String(), barAddr, sdk.NewInt64Coin(cli.Denom, 5), "--generate-only")
require.True(t, success)
multi := multisig.NewPubKeyMultisigThreshold(2, []tmcrypto.PubKey{account1.GetPubKey(), account2.GetPubKey()})
multisigInfo, err := val1.ClientCtx.Keyring.SaveMultisig("multi", multi)
s.Require().NoError(err)
// Write the output to disk
unsignedTxFile, cleanup := sdktestutil.WriteToNewTempFile(t, stdout)
t.Cleanup(cleanup)
// Send coins from validator to multisig.
_, err = bankcli.MsgSendExec(
val1.ClientCtx,
val1.Address,
multisigInfo.GetAddress(),
sdk.NewCoins(
sdk.NewInt64Coin(cli.Denom, 10),
),
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
fmt.Sprintf("--gas=%d", flags.DefaultGasLimit),
)
s.Require().NoError(err)
// Sign with foo's key
success, stdout, _ = testutil.TxSign(f, cli.KeyFoo, unsignedTxFile.Name(), "--multisig", fooBarBazAddr.String(), "-y")
require.True(t, success)
err = waitForNextBlock(s.network)
s.Require().NoError(err)
// Write the output to disk
fooSignatureFile, cleanup := sdktestutil.WriteToNewTempFile(t, stdout)
t.Cleanup(cleanup)
// Generate multisig transaction.
multiGeneratedTx, err := bankcli.MsgSendExec(
val1.ClientCtx,
multisigInfo.GetAddress(),
val1.Address,
sdk.NewCoins(
sdk.NewInt64Coin(cli.Denom, 5),
),
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
fmt.Sprintf("--%s=true", flags.FlagGenerateOnly),
)
s.Require().NoError(err)
// Multisign, not enough signatures
success, stdout, _ = testutil.TxMultisign(f, unsignedTxFile.Name(), cli.KeyFooBarBaz, []string{fooSignatureFile.Name()})
require.True(t, success)
// Save tx to file
multiGeneratedTxFile, cleanup := testutil.WriteToNewTempFile(s.T(), multiGeneratedTx.String())
defer cleanup()
// Write the output to disk
signedTxFile, cleanup := sdktestutil.WriteToNewTempFile(t, stdout)
t.Cleanup(cleanup)
// Multisign, sign with one signature
val1.ClientCtx.HomeDir = strings.Replace(val1.ClientCtx.HomeDir, "simd", "simcli", 1)
account1Signature, err := authtest.TxSignExec(val1.ClientCtx, account1.GetAddress(), multiGeneratedTxFile.Name(), "--multisig", multisigInfo.GetAddress().String())
s.Require().NoError(err)
// Validate the multisignature
success, _, _ = testutil.TxValidateSignatures(f, signedTxFile.Name())
require.False(t, success)
sign1File, cleanup2 := testutil.WriteToNewTempFile(s.T(), account1Signature.String())
defer cleanup2()
// Broadcast the transaction
success, stdOut, _ := testutil.TxBroadcast(f, signedTxFile.Name())
require.Contains(t, stdOut, "signature verification failed")
require.True(t, success)
multiSigWith1Signature, err := authtest.TxMultiSignExec(val1.ClientCtx, multisigInfo.GetName(), multiGeneratedTxFile.Name(), sign1File.Name())
s.Require().NoError(err)
// Cleanup testing directories
f.Cleanup()
// Save tx to file
multiSigWith1SignatureFile, cleanup3 := testutil.WriteToNewTempFile(s.T(), multiSigWith1Signature.String())
defer cleanup3()
exec, err := authtest.TxValidateSignaturesExec(val1.ClientCtx, multiSigWith1SignatureFile.Name())
s.Require().NoError(err)
fmt.Printf("%s", exec)
}
func TestCLIEncode(t *testing.T) {
t.SkipNow()
t.Parallel()
f := cli.InitFixtures(t)
// start simd server
proc := f.SDStart()
t.Cleanup(func() { proc.Stop(false) })
// Build a testing transaction and write it to disk
barAddr := f.KeyAddress(cli.KeyBar)
keyAddr := f.KeyAddress(cli.KeyFoo)
func (s *IntegrationTestSuite) TestCLIEncode() {
val1 := s.network.Validators[0]
sendTokens := sdk.TokensFromConsensusPower(10)
success, stdout, stderr := bankcli.TxSend(f, keyAddr.String(), barAddr, sdk.NewCoin(cli.Denom, sendTokens), "--generate-only", "--memo", "deadbeef")
require.True(t, success)
require.Empty(t, stderr)
// Write it to disk
jsonTxFile, cleanup := sdktestutil.WriteToNewTempFile(t, stdout)
t.Cleanup(cleanup)
normalGeneratedTx, err := bankcli.MsgSendExec(
val1.ClientCtx,
val1.Address,
val1.Address,
sdk.NewCoins(
sdk.NewCoin(s.cfg.BondDenom, sendTokens),
),
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
fmt.Sprintf("--%s=true", flags.FlagGenerateOnly), "--memo", "deadbeef",
)
s.Require().NoError(err)
// Run the encode command
success, base64Encoded, _ := testutil.TxEncode(f, jsonTxFile.Name())
require.True(t, success)
trimmedBase64 := strings.Trim(base64Encoded, "\"\n")
// Save tx to file
savedTxFile, cleanup := testutil.WriteToNewTempFile(s.T(), normalGeneratedTx.String())
defer cleanup()
// Enconde
encodeExec, err := authtest.TxEncodeExec(val1.ClientCtx, savedTxFile.Name())
s.Require().NoError(err)
trimmedBase64 := strings.Trim(encodeExec.String(), "\"\n")
// Check that the transaction decodes as expected
success, stdout, stderr = testutil.TxDecode(f, trimmedBase64)
decodedTx := cli.UnmarshalStdTx(t, f.Cdc, stdout)
require.Equal(t, "deadbeef", decodedTx.Memo)
decodedTx, err := authtest.TxDecodeExec(val1.ClientCtx, trimmedBase64)
s.Require().NoError(err)
theTx := cli.UnmarshalStdTx(s.T(), val1.ClientCtx.JSONMarshaler, decodedTx.String())
s.Require().Equal("deadbeef", theTx.Memo)
}
func TestCLIMultisignSortSignatures(t *testing.T) {
t.SkipNow()
t.Parallel()
f := cli.InitFixtures(t)
func (s *IntegrationTestSuite) TestCLIMultisignSortSignatures() {
s.T().SkipNow()
val1 := s.network.Validators[0]
// start simd server with minimum fees
proc := f.SDStart()
t.Cleanup(func() { proc.Stop(false) })
codec := codec2.New()
sdk.RegisterCodec(codec)
banktypes.RegisterCodec(codec)
val1.ClientCtx.Codec = codec
fooBarBazAddr := f.KeyAddress(cli.KeyFooBarBaz)
barAddr := f.KeyAddress(cli.KeyBar)
// Generate 2 accounts and a multisig.
account1, _, err := val1.ClientCtx.Keyring.NewMnemonic("newAccount1", keyring.English, sdk.FullFundraiserPath, hd.Secp256k1)
s.Require().NoError(err)
// Send some tokens from one account to the other
success, _, _ := bankcli.TxSend(f, cli.KeyFoo, fooBarBazAddr, sdk.NewInt64Coin(cli.Denom, 10), "-y")
require.True(t, success)
tests.WaitForNextNBlocksTM(1, f.Port)
account2, _, err := val1.ClientCtx.Keyring.NewMnemonic("newAccount2", keyring.English, sdk.FullFundraiserPath, hd.Secp256k1)
s.Require().NoError(err)
// Ensure account balances match expected
require.Equal(t, int64(10), bankcli.QueryBalances(f, fooBarBazAddr).AmountOf(cli.Denom).Int64())
multi := multisig.NewPubKeyMultisigThreshold(2, []tmcrypto.PubKey{account1.GetPubKey(), account2.GetPubKey()})
multisigInfo, err := val1.ClientCtx.Keyring.SaveMultisig("multi", multi)
s.Require().NoError(err)
// Test generate sendTx with multisig
success, stdout, _ := bankcli.TxSend(f, fooBarBazAddr.String(), barAddr, sdk.NewInt64Coin(cli.Denom, 5), "--generate-only")
require.True(t, success)
// Send coins from validator to multisig.
sendTokens := sdk.NewInt64Coin(cli.Denom, 10)
_, err = bankcli.MsgSendExec(
val1.ClientCtx,
val1.Address,
multisigInfo.GetAddress(),
sdk.NewCoins(
sendTokens,
),
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
fmt.Sprintf("--gas=%d", flags.DefaultGasLimit),
)
s.Require().NoError(err)
err = waitForNextBlock(s.network)
s.Require().NoError(err)
resp, err := bankcli.QueryBalancesExec(val1.ClientCtx, multisigInfo.GetAddress())
s.Require().NoError(err)
var coins sdk.Coins
err = val1.ClientCtx.JSONMarshaler.UnmarshalJSON(resp.Bytes(), &coins)
s.Require().NoError(err)
s.Require().Equal(sendTokens.Amount, coins.AmountOf(cli.Denom))
// Generate multisig transaction.
multiGeneratedTx, err := bankcli.MsgSendExec(
val1.ClientCtx,
multisigInfo.GetAddress(),
val1.Address,
sdk.NewCoins(
sdk.NewInt64Coin(cli.Denom, 5),
),
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
fmt.Sprintf("--%s=true", flags.FlagGenerateOnly),
)
s.Require().NoError(err)
// Save tx to file
multiGeneratedTxFile, cleanup := testutil.WriteToNewTempFile(s.T(), multiGeneratedTx.String())
defer cleanup()
// Sign with account1
val1.ClientCtx.HomeDir = strings.Replace(val1.ClientCtx.HomeDir, "simd", "simcli", 1)
account1Signature, err := authtest.TxSignExec(val1.ClientCtx, account1.GetAddress(), multiGeneratedTxFile.Name(), "--multisig", multisigInfo.GetAddress().String())
s.Require().NoError(err)
sign1File, cleanup2 := testutil.WriteToNewTempFile(s.T(), account1Signature.String())
defer cleanup2()
// Sign with account1
account2Signature, err := authtest.TxSignExec(val1.ClientCtx, account2.GetAddress(), multiGeneratedTxFile.Name(), "--multisig", multisigInfo.GetAddress().String())
s.Require().NoError(err)
sign2File, cleanup3 := testutil.WriteToNewTempFile(s.T(), account2Signature.String())
defer cleanup3()
multiSigWith2Signatures, err := authtest.TxMultiSignExec(val1.ClientCtx, multisigInfo.GetName(), multiGeneratedTxFile.Name(), sign1File.Name(), sign2File.Name())
s.Require().NoError(err)
// Write the output to disk
unsignedTxFile, cleanup := sdktestutil.WriteToNewTempFile(t, stdout)
t.Cleanup(cleanup)
signedTxFile, cleanup4 := testutil.WriteToNewTempFile(s.T(), multiSigWith2Signatures.String())
defer cleanup4()
// Sign with foo's key
success, stdout, _ = testutil.TxSign(f, cli.KeyFoo, unsignedTxFile.Name(), "--multisig", fooBarBazAddr.String())
require.True(t, success)
_, err = authtest.TxValidateSignaturesExec(val1.ClientCtx, signedTxFile.Name())
s.Require().NoError(err)
// Write the output to disk
fooSignatureFile, cleanup := sdktestutil.WriteToNewTempFile(t, stdout)
t.Cleanup(cleanup)
val1.ClientCtx.BroadcastMode = flags.BroadcastBlock
_, err = authtest.TxBroadcastExec(val1.ClientCtx, signedTxFile.Name())
s.Require().NoError(err)
// Sign with baz's key
success, stdout, _ = testutil.TxSign(f, cli.KeyBaz, unsignedTxFile.Name(), "--multisig", fooBarBazAddr.String())
require.True(t, success)
// Write the output to disk
bazSignatureFile, cleanup := sdktestutil.WriteToNewTempFile(t, stdout)
t.Cleanup(cleanup)
// Multisign, keys in different order
success, stdout, _ = testutil.TxMultisign(f, unsignedTxFile.Name(), cli.KeyFooBarBaz, []string{
bazSignatureFile.Name(), fooSignatureFile.Name()})
require.True(t, success)
// Write the output to disk
signedTxFile, cleanup := sdktestutil.WriteToNewTempFile(t, stdout)
t.Cleanup(cleanup)
// Validate the multisignature
success, _, _ = testutil.TxValidateSignatures(f, signedTxFile.Name())
require.True(t, success)
// Broadcast the transaction
success, _, _ = testutil.TxBroadcast(f, signedTxFile.Name())
require.True(t, success)
// Cleanup testing directories
f.Cleanup()
err = waitForNextBlock(s.network)
s.Require().NoError(err)
}
func TestCLIMultisign(t *testing.T) {
t.SkipNow()
t.Parallel()
f := cli.InitFixtures(t)
func (s *IntegrationTestSuite) TestCLIMultisign() {
s.T().SkipNow()
val1 := s.network.Validators[0]
// start simd server with minimum fees
proc := f.SDStart()
t.Cleanup(func() { proc.Stop(false) })
codec := codec2.New()
sdk.RegisterCodec(codec)
banktypes.RegisterCodec(codec)
val1.ClientCtx.Codec = codec
fooBarBazAddr := f.KeyAddress(cli.KeyFooBarBaz)
bazAddr := f.KeyAddress(cli.KeyBaz)
// Generate 2 accounts and a multisig.
account1, _, err := val1.ClientCtx.Keyring.NewMnemonic("newAccount1", keyring.English, sdk.FullFundraiserPath, hd.Secp256k1)
s.Require().NoError(err)
// Send some tokens from one account to the other
success, _, _ := bankcli.TxSend(f, cli.KeyFoo, fooBarBazAddr, sdk.NewInt64Coin(cli.Denom, 10), "-y")
require.True(t, success)
tests.WaitForNextNBlocksTM(1, f.Port)
account2, _, err := val1.ClientCtx.Keyring.NewMnemonic("newAccount2", keyring.English, sdk.FullFundraiserPath, hd.Secp256k1)
s.Require().NoError(err)
// Ensure account balances match expected
require.Equal(t, int64(10), bankcli.QueryBalances(f, fooBarBazAddr).AmountOf(cli.Denom).Int64())
multi := multisig.NewPubKeyMultisigThreshold(2, []tmcrypto.PubKey{account1.GetPubKey(), account2.GetPubKey()})
multisigInfo, err := val1.ClientCtx.Keyring.SaveMultisig("multi", multi)
s.Require().NoError(err)
// Test generate sendTx with multisig
success, stdout, stderr := bankcli.TxSend(f, fooBarBazAddr.String(), bazAddr, sdk.NewInt64Coin(cli.Denom, 10), "--generate-only")
require.True(t, success)
require.Empty(t, stderr)
// Send coins from validator to multisig.
sendTokens := sdk.NewInt64Coin(cli.Denom, 10)
_, err = bankcli.MsgSendExec(
val1.ClientCtx,
val1.Address,
multisigInfo.GetAddress(),
sdk.NewCoins(
sendTokens,
),
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
fmt.Sprintf("--gas=%d", flags.DefaultGasLimit),
)
err = waitForNextBlock(s.network)
s.Require().NoError(err)
resp, err := bankcli.QueryBalancesExec(val1.ClientCtx, multisigInfo.GetAddress())
s.Require().NoError(err)
var coins sdk.Coins
err = val1.ClientCtx.JSONMarshaler.UnmarshalJSON(resp.Bytes(), &coins)
s.Require().NoError(err)
s.Require().Equal(sendTokens.Amount, coins.AmountOf(cli.Denom))
// Generate multisig transaction.
multiGeneratedTx, err := bankcli.MsgSendExec(
val1.ClientCtx,
multisigInfo.GetAddress(),
val1.Address,
sdk.NewCoins(
sdk.NewInt64Coin(cli.Denom, 5),
),
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
fmt.Sprintf("--%s=true", flags.FlagGenerateOnly),
)
s.Require().NoError(err)
// Save tx to file
multiGeneratedTxFile, cleanup := testutil.WriteToNewTempFile(s.T(), multiGeneratedTx.String())
defer cleanup()
// Sign with account1
val1.ClientCtx.HomeDir = strings.Replace(val1.ClientCtx.HomeDir, "simd", "simcli", 1)
account1Signature, err := authtest.TxSignExec(val1.ClientCtx, account1.GetAddress(), multiGeneratedTxFile.Name(), "--multisig", multisigInfo.GetAddress().String())
s.Require().NoError(err)
sign1File, cleanup2 := testutil.WriteToNewTempFile(s.T(), account1Signature.String())
defer cleanup2()
// Sign with account1
account2Signature, err := authtest.TxSignExec(val1.ClientCtx, account2.GetAddress(), multiGeneratedTxFile.Name(), "--multisig", multisigInfo.GetAddress().String())
s.Require().NoError(err)
sign2File, cleanup3 := testutil.WriteToNewTempFile(s.T(), account2Signature.String())
defer cleanup3()
// Does not work in offline mode.
val1.ClientCtx.Offline = true
_, err = authtest.TxMultiSignExec(val1.ClientCtx, multisigInfo.GetName(), multiGeneratedTxFile.Name(), sign1File.Name(), sign2File.Name())
s.Require().EqualError(err, "couldn't verify signature")
val1.ClientCtx.Offline = false
multiSigWith2Signatures, err := authtest.TxMultiSignExec(val1.ClientCtx, multisigInfo.GetName(), multiGeneratedTxFile.Name(), sign1File.Name(), sign2File.Name())
s.Require().NoError(err)
// Write the output to disk
unsignedTxFile, cleanup := sdktestutil.WriteToNewTempFile(t, stdout)
t.Cleanup(cleanup)
signedTxFile, cleanup4 := testutil.WriteToNewTempFile(s.T(), multiSigWith2Signatures.String())
defer cleanup4()
// Sign with foo's key
success, stdout, _ = testutil.TxSign(f, cli.KeyFoo, unsignedTxFile.Name(), "--multisig", fooBarBazAddr.String(), "-y")
require.True(t, success)
_, err = authtest.TxValidateSignaturesExec(val1.ClientCtx, signedTxFile.Name())
s.Require().NoError(err)
// Write the output to disk
fooSignatureFile, cleanup := sdktestutil.WriteToNewTempFile(t, stdout)
t.Cleanup(cleanup)
val1.ClientCtx.BroadcastMode = flags.BroadcastBlock
_, err = authtest.TxBroadcastExec(val1.ClientCtx, signedTxFile.Name())
s.Require().NoError(err)
// Sign with bar's key
success, stdout, _ = testutil.TxSign(f, cli.KeyBar, unsignedTxFile.Name(), "--multisig", fooBarBazAddr.String(), "-y")
require.True(t, success)
err = waitForNextBlock(s.network)
s.Require().NoError(err)
}
// Write the output to disk
barSignatureFile, cleanup := sdktestutil.WriteToNewTempFile(t, stdout)
t.Cleanup(cleanup)
func TestGetBroadcastCommand_OfflineFlag(t *testing.T) {
clientCtx := client.Context{}.WithOffline(true)
clientCtx = clientCtx.WithTxGenerator(simappparams.MakeEncodingConfig().TxGenerator)
// Multisign
cmd := cli2.GetBroadcastCommand()
_ = testutil.ApplyMockIODiscardOutErr(cmd)
cmd.SetArgs([]string{fmt.Sprintf("--%s=true", flags.FlagOffline), ""})
// Does not work in offline mode
success, stdout, _ = testutil.TxMultisign(f, unsignedTxFile.Name(), cli.KeyFooBarBaz, []string{
fooSignatureFile.Name(), barSignatureFile.Name()}, "--offline")
require.Contains(t, "couldn't verify signature", stdout)
require.False(t, success)
require.EqualError(t, cmd.Execute(), "cannot broadcast tx during offline mode")
}
// Success multisign
success, stdout, _ = testutil.TxMultisign(f, unsignedTxFile.Name(), cli.KeyFooBarBaz, []string{
fooSignatureFile.Name(), barSignatureFile.Name()})
require.True(t, success)
func TestGetBroadcastCommand_WithoutOfflineFlag(t *testing.T) {
clientCtx := client.Context{}
clientCtx = clientCtx.WithTxGenerator(simappparams.MakeEncodingConfig().TxGenerator)
// Write the output to disk
signedTxFile, cleanup := sdktestutil.WriteToNewTempFile(t, stdout)
t.Cleanup(cleanup)
ctx := context.Background()
ctx = context.WithValue(ctx, client.ClientContextKey, &clientCtx)
// Validate the multisignature
success, _, _ = testutil.TxValidateSignatures(f, signedTxFile.Name())
require.True(t, success)
cmd := cli2.GetBroadcastCommand()
// Broadcast the transaction
success, _, _ = testutil.TxBroadcast(f, signedTxFile.Name())
require.True(t, success)
testDir, cleanFunc := testutil.NewTestCaseDir(t)
t.Cleanup(cleanFunc)
// Cleanup testing directories
f.Cleanup()
// Create new file with tx
txContents := []byte("{\"type\":\"cosmos-sdk/StdTx\",\"value\":{\"msg\":[{\"type\":\"cosmos-sdk/MsgSend\",\"value\":{\"from_address\":\"cosmos1cxlt8kznps92fwu3j6npahx4mjfutydyene2qw\",\"to_address\":\"cosmos1wc8mpr8m3sy3ap3j7fsgqfzx36um05pystems4\",\"amount\":[{\"denom\":\"stake\",\"amount\":\"10000\"}]}}],\"fee\":{\"amount\":[],\"gas\":\"200000\"},\"signatures\":null,\"memo\":\"\"}}")
txFileName := filepath.Join(testDir, "tx.json")
err := ioutil.WriteFile(txFileName, txContents, 0644)
require.NoError(t, err)
cmd.SetArgs([]string{txFileName})
err = cmd.ExecuteContext(ctx)
// We test it tries to broadcast but we set unsupported tx to get the error.
require.EqualError(t, err, "unsupported return type ; supported types: sync, async, block")
}
func TestIntegrationTestSuite(t *testing.T) {
suite.Run(t, new(IntegrationTestSuite))
}
func waitForNextBlock(network *network.Network) error {
lastBlock, err := network.LatestHeight()
if err != nil {
return err
}
_, err = network.WaitForHeightWithTimeout(lastBlock+1, 10*time.Second)
if err != nil {
return err
}
return err
}
+2 -2
View File
@@ -14,13 +14,13 @@ const flagHex = "hex"
// GetDecodeCommand returns the decode command to take serialized bytes and turn
// it into a JSON-encoded transaction.
func GetDecodeCommand(clientCtx client.Context) *cobra.Command {
func GetDecodeCommand() *cobra.Command {
cmd := &cobra.Command{
Use: "decode [amino-byte-string]",
Short: "Decode an binary encoded transaction string.",
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) (err error) {
clientCtx = clientCtx.Init().WithOutput(cmd.OutOrStdout())
clientCtx := client.GetClientContextFromCmd(cmd)
var txBytes []byte
if useHex, _ := cmd.Flags().GetBool(flagHex); useHex {
+4 -4
View File
@@ -19,7 +19,7 @@ func (txr txEncodeRespStr) String() string {
// GetEncodeCommand returns the encode command to take a JSONified transaction and turn it into
// Amino-serialized bytes
func GetEncodeCommand(clientCtx client.Context) *cobra.Command {
func GetEncodeCommand() *cobra.Command {
cmd := &cobra.Command{
Use: "encode [file]",
Short: "Encode transactions generated offline",
@@ -28,15 +28,15 @@ Read a transaction from <file>, serialize it to the Amino wire protocol, and out
If you supply a dash (-) argument in place of an input filename, the command reads from standard input.`,
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
cliCtx := clientCtx.Init()
clientCtx := client.GetClientContextFromCmd(cmd)
tx, err := authclient.ReadTxFromFile(cliCtx, args[0])
tx, err := authclient.ReadTxFromFile(clientCtx, args[0])
if err != nil {
return err
}
// re-encode it
txBytes, err := cliCtx.TxGenerator.TxEncoder()(tx)
txBytes, err := clientCtx.TxGenerator.TxEncoder()(tx)
if err != nil {
return err
}
+15 -7
View File
@@ -1,6 +1,7 @@
package cli
import (
"context"
"encoding/base64"
"testing"
@@ -15,11 +16,8 @@ import (
func TestGetCommandEncode(t *testing.T) {
encodingConfig := simappparams.MakeEncodingConfig()
clientCtx := client.Context{}.
WithTxGenerator(encodingConfig.TxGenerator).
WithJSONMarshaler(encodingConfig.Marshaler)
cmd := GetEncodeCommand(clientCtx)
cmd := GetEncodeCommand()
_ = testutil.ApplyMockIODiscardOutErr(cmd)
authtypes.RegisterCodec(encodingConfig.Amino)
@@ -37,7 +35,14 @@ func TestGetCommandEncode(t *testing.T) {
txFileName := txFile.Name()
t.Cleanup(cleanup)
err = cmd.RunE(cmd, []string{txFileName})
ctx := context.Background()
clientCtx := client.Context{}.
WithTxGenerator(encodingConfig.TxGenerator).
WithJSONMarshaler(encodingConfig.Marshaler)
ctx = context.WithValue(ctx, client.ClientContextKey, &clientCtx)
cmd.SetArgs([]string{txFileName})
err = cmd.ExecuteContext(ctx)
require.NoError(t, err)
}
@@ -48,7 +53,7 @@ func TestGetCommandDecode(t *testing.T) {
WithTxGenerator(encodingConfig.TxGenerator).
WithJSONMarshaler(encodingConfig.Marshaler)
cmd := GetDecodeCommand(clientCtx)
cmd := GetDecodeCommand()
_ = testutil.ApplyMockIODiscardOutErr(cmd)
sdk.RegisterCodec(encodingConfig.Amino)
@@ -67,7 +72,10 @@ func TestGetCommandDecode(t *testing.T) {
// Convert the transaction into base64 encoded string
base64Encoded := base64.StdEncoding.EncodeToString(txBytes)
ctx := context.Background()
ctx = context.WithValue(ctx, client.ClientContextKey, &clientCtx)
// Execute the command
cmd.SetArgs([]string{base64Encoded})
require.NoError(t, cmd.Execute())
require.NoError(t, cmd.ExecuteContext(ctx))
}
+5 -5
View File
@@ -8,7 +8,7 @@ import (
)
// GetTxCmd returns the transaction commands for this module
func GetTxCmd(clientCtx client.Context) *cobra.Command {
func GetTxCmd() *cobra.Command {
txCmd := &cobra.Command{
Use: types.ModuleName,
Short: "Auth transaction subcommands",
@@ -17,10 +17,10 @@ func GetTxCmd(clientCtx client.Context) *cobra.Command {
RunE: client.ValidateCmd,
}
txCmd.AddCommand(
GetMultiSignCommand(clientCtx),
GetSignCommand(clientCtx),
GetValidateSignaturesCommand(clientCtx),
GetSignBatchCommand(clientCtx.Codec),
GetMultiSignCommand(),
GetSignCommand(),
GetValidateSignaturesCommand(),
GetSignBatchCommand(),
)
return txCmd
}
+9 -9
View File
@@ -22,7 +22,7 @@ import (
)
// GetSignCommand returns the sign command
func GetMultiSignCommand(clientCtx client.Context) *cobra.Command {
func GetMultiSignCommand() *cobra.Command {
cmd := &cobra.Command{
Use: "multisign [file] [name] [[signature]...]",
Short: "Generate multisig signatures for transactions generated offline",
@@ -45,20 +45,21 @@ recommended to set such parameters manually.
version.AppName,
),
),
RunE: makeMultiSignCmd(clientCtx),
RunE: makeMultiSignCmd(),
Args: cobra.MinimumNArgs(3),
}
cmd.Flags().Bool(flagSigOnly, false, "Print only the generated signature, then exit")
cmd.Flags().String(flags.FlagOutputDocument, "", "The document will be written to the given file instead of STDOUT")
flags.AddTxFlagsToCmd(cmd)
cmd.Flags().String(flags.FlagChainID, "", "network chain ID")
return cmd
}
func makeMultiSignCmd(clientCtx client.Context) func(cmd *cobra.Command, args []string) error {
func makeMultiSignCmd() func(cmd *cobra.Command, args []string) error {
return func(cmd *cobra.Command, args []string) (err error) {
clientCtx = clientCtx.Init()
clientCtx := client.GetClientContextFromCmd(cmd)
cdc := clientCtx.Codec
tx, err := authclient.ReadTxFromFile(clientCtx, args[0])
stdTx := tx.(types.StdTx)
@@ -67,10 +68,9 @@ func makeMultiSignCmd(clientCtx client.Context) func(cmd *cobra.Command, args []
}
backend, _ := cmd.Flags().GetString(flags.FlagKeyringBackend)
homeDir, _ := cmd.Flags().GetString(flags.FlagHome)
inBuf := bufio.NewReader(cmd.InOrStdin())
kb, err := keyring.New(sdk.KeyringServiceName(), backend, homeDir, inBuf)
kb, err := keyring.New(sdk.KeyringServiceName(), backend, clientCtx.HomeDir, inBuf)
if err != nil {
return
}
@@ -85,13 +85,13 @@ func makeMultiSignCmd(clientCtx client.Context) func(cmd *cobra.Command, args []
multisigPub := multisigInfo.GetPubKey().(multisig.PubKeyMultisigThreshold)
multisigSig := multisig.NewMultisig(len(multisigPub.PubKeys))
txBldr, err := types.NewTxBuilderFromFlags(inBuf, cmd.Flags(), homeDir)
txBldr, err := types.NewTxBuilderFromFlags(inBuf, cmd.Flags(), clientCtx.HomeDir)
if err != nil {
return errors.Wrap(err, "error creating tx builder from flags")
}
if !clientCtx.Offline {
accnum, seq, err := types.NewAccountRetriever(authclient.Codec).GetAccountNumberSequence(clientCtx, multisigInfo.GetAddress())
accnum, seq, err := types.NewAccountRetriever(clientCtx.JSONMarshaler).GetAccountNumberSequence(clientCtx, multisigInfo.GetAddress())
if err != nil {
return err
}
@@ -148,7 +148,7 @@ func makeMultiSignCmd(clientCtx client.Context) func(cmd *cobra.Command, args []
outputDoc, _ := cmd.Flags().GetString(flags.FlagOutputDocument)
if outputDoc == "" {
fmt.Printf("%s\n", json)
cmd.Printf("%s\n", json)
return
}
+41 -22
View File
@@ -22,7 +22,7 @@ const (
)
// GetSignBatchCommand returns the transaction sign-batch command.
func GetSignBatchCommand(codec *codec.Codec) *cobra.Command {
func GetSignBatchCommand() *cobra.Command {
cmd := &cobra.Command{
Use: "sign-batch [file]",
Short: "Sign transaction batch files",
@@ -44,25 +44,25 @@ The --multisig=<multisig_key> flag generates a signature on behalf of a multisig
account key. It implies --signature-only.
`,
PreRun: preSignCmd,
RunE: makeSignBatchCmd(codec),
RunE: makeSignBatchCmd(),
Args: cobra.ExactArgs(1),
}
cmd.Flags().String(flagMultisig, "", "Address of the multisig account on behalf of which the transaction shall be signed")
cmd.Flags().String(flags.FlagOutputDocument, "", "The document will be written to the given file instead of STDOUT")
cmd.Flags().Bool(flagSigOnly, true, "Print only the generated signature, then exit")
cmd.Flags().String(flags.FlagChainID, "", "network chain ID")
cmd.MarkFlagRequired(flags.FlagFrom)
flags.AddTxFlagsToCmd(cmd)
return cmd
}
func makeSignBatchCmd(cdc *codec.Codec) func(cmd *cobra.Command, args []string) error {
func makeSignBatchCmd() func(cmd *cobra.Command, args []string) error {
return func(cmd *cobra.Command, args []string) error {
inBuf := bufio.NewReader(cmd.InOrStdin())
clientCtx := client.GetClientContextFromCmd(cmd)
txBldr, err := types.NewTxBuilderFromFlags(inBuf, cmd.Flags(), clientCtx.HomeDir)
txBldr, err := types.NewTxBuilderFromFlags(bufio.NewReader(cmd.InOrStdin()), cmd.Flags(), clientCtx.HomeDir)
if err != nil {
return err
}
@@ -98,7 +98,7 @@ func makeSignBatchCmd(cdc *codec.Codec) func(cmd *cobra.Command, args []string)
}
}
scanner := authclient.NewBatchScanner(cdc, infile)
scanner := authclient.NewBatchScanner(clientCtx.JSONMarshaler, infile)
for sequence := txBldr.Sequence(); scanner.Scan(); sequence++ {
var stdTx types.StdTx
@@ -107,17 +107,24 @@ func makeSignBatchCmd(cdc *codec.Codec) func(cmd *cobra.Command, args []string)
txBldr = txBldr.WithSequence(sequence)
if multisigAddr.Empty() {
homeDir, _ := cmd.Flags().GetString(flags.FlagFrom)
stdTx, err = authclient.SignStdTx(txBldr, clientCtx, homeDir, unsignedStdTx, false, true)
from, _ := cmd.Flags().GetString(flags.FlagFrom)
_, fromName, err := client.GetFromFields(txBldr.Keybase(), from, clientCtx.GenerateOnly)
if err != nil {
return fmt.Errorf("error getting account from keybase: %w", err)
}
stdTx, err = authclient.SignStdTx(txBldr, clientCtx, fromName, unsignedStdTx, false, true)
if err != nil {
return err
}
} else {
stdTx, err = authclient.SignStdTxWithSignerAddress(txBldr, clientCtx, multisigAddr, clientCtx.GetFromName(), unsignedStdTx, true)
if err != nil {
return err
}
}
if err != nil {
return err
}
json, err := getSignatureJSON(cdc, stdTx, generateSignatureOnly)
json, err := getSignatureJSON(clientCtx.JSONMarshaler, stdTx, generateSignatureOnly)
if err != nil {
return err
}
@@ -151,7 +158,7 @@ func setOutputFile(cmd *cobra.Command) (func(), error) {
}
// GetSignCommand returns the transaction sign command.
func GetSignCommand(clientCtx client.Context) *cobra.Command {
func GetSignCommand() *cobra.Command {
cmd := &cobra.Command{
Use: "sign [file]",
Short: "Sign transactions generated offline",
@@ -171,7 +178,7 @@ key. It implies --signature-only. Full multisig signed transactions may eventual
be generated via the 'multisign' command.
`,
PreRun: preSignCmd,
RunE: makeSignCmd(clientCtx),
RunE: makeSignCmd(),
Args: cobra.ExactArgs(1),
}
@@ -180,6 +187,7 @@ be generated via the 'multisign' command.
cmd.Flags().Bool(flagSigOnly, false, "Print only the generated signature, then exit")
cmd.Flags().String(flags.FlagOutputDocument, "", "The document will be written to the given file instead of STDOUT")
cmd.Flags().String(flags.FlagHome, "", "The application home directory")
cmd.Flags().String(flags.FlagChainID, "", "The network chain ID")
cmd.MarkFlagRequired(flags.FlagFrom)
flags.AddTxFlagsToCmd(cmd)
@@ -195,8 +203,10 @@ func preSignCmd(cmd *cobra.Command, _ []string) {
}
}
func makeSignCmd(clientCtx client.Context) func(cmd *cobra.Command, args []string) error {
func makeSignCmd() func(cmd *cobra.Command, args []string) error {
return func(cmd *cobra.Command, args []string) error {
clientCtx := client.GetClientContextFromCmd(cmd)
clientCtx, txBldr, tx, err := readStdTxAndInitContexts(clientCtx, cmd, args[0])
if err != nil {
return err
@@ -208,6 +218,12 @@ func makeSignCmd(clientCtx client.Context) func(cmd *cobra.Command, args []strin
generateSignatureOnly, _ := cmd.Flags().GetBool(flagSigOnly)
multisigAddrStr, _ := cmd.Flags().GetString(flagMultisig)
from, _ := cmd.Flags().GetString(flags.FlagFrom)
_, fromName, err := client.GetFromFields(txBldr.Keybase(), from, clientCtx.GenerateOnly)
if err != nil {
return fmt.Errorf("error getting account from keybase: %w", err)
}
if multisigAddrStr != "" {
var multisigAddr sdk.AccAddress
@@ -215,28 +231,31 @@ func makeSignCmd(clientCtx client.Context) func(cmd *cobra.Command, args []strin
if err != nil {
return err
}
newTx, err = authclient.SignStdTxWithSignerAddress(
txBldr, clientCtx, multisigAddr, clientCtx.GetFromName(), stdTx, clientCtx.Offline,
txBldr, clientCtx, multisigAddr, fromName, stdTx, clientCtx.Offline,
)
generateSignatureOnly = true
} else {
append, _ := cmd.Flags().GetBool(flagAppend)
appendSig := append && !generateSignatureOnly
newTx, err = authclient.SignStdTx(txBldr, clientCtx, clientCtx.GetFromName(), stdTx, appendSig, clientCtx.Offline)
newTx, err = authclient.SignStdTx(txBldr, clientCtx, fromName, stdTx, appendSig, clientCtx.Offline)
if err != nil {
return err
}
}
if err != nil {
return err
}
json, err := getSignatureJSON(clientCtx.Codec, newTx, generateSignatureOnly)
json, err := getSignatureJSON(clientCtx.JSONMarshaler, newTx, generateSignatureOnly)
if err != nil {
return err
}
outputDoc, _ := cmd.Flags().GetString(flags.FlagOutputDocument)
if outputDoc == "" {
fmt.Printf("%s\n", json)
cmd.Printf("%s\n", json)
return nil
}
@@ -251,7 +270,7 @@ func makeSignCmd(clientCtx client.Context) func(cmd *cobra.Command, args []strin
}
}
func getSignatureJSON(cdc *codec.Codec, newTx types.StdTx, generateSignatureOnly bool) ([]byte, error) {
func getSignatureJSON(cdc codec.JSONMarshaler, newTx types.StdTx, generateSignatureOnly bool) ([]byte, error) {
if generateSignatureOnly {
return cdc.MarshalJSON(newTx.Signatures[0])
}
+6 -4
View File
@@ -15,7 +15,7 @@ import (
"github.com/cosmos/cosmos-sdk/x/auth/types"
)
func GetValidateSignaturesCommand(clientCtx client.Context) *cobra.Command {
func GetValidateSignaturesCommand() *cobra.Command {
cmd := &cobra.Command{
Use: "validate-signatures [file]",
Short: "Validate transactions signatures",
@@ -28,17 +28,19 @@ given transaction. If the --offline flag is also set, signature validation over
transaction will be not be performed as that will require RPC communication with a full node.
`,
PreRun: preSignCmd,
RunE: makeValidateSignaturesCmd(clientCtx),
RunE: makeValidateSignaturesCmd(),
Args: cobra.ExactArgs(1),
}
cmd.Flags().String(flags.FlagChainID, "", "The network chain ID")
flags.AddTxFlagsToCmd(cmd)
return cmd
}
func makeValidateSignaturesCmd(clientCtx client.Context) func(cmd *cobra.Command, args []string) error {
func makeValidateSignaturesCmd() func(cmd *cobra.Command, args []string) error {
return func(cmd *cobra.Command, args []string) error {
clientCtx := client.GetClientContextFromCmd(cmd)
clientCtx, txBldr, tx, err := readStdTxAndInitContexts(clientCtx, cmd, args[0])
if err != nil {
return err
@@ -91,7 +93,7 @@ func printAndValidateSigs(
// Validate the actual signature over the transaction bytes since we can
// reach out to a full node to query accounts.
if !offline && success {
acc, err := types.NewAccountRetriever(authclient.Codec).GetAccount(clientCtx, sigAddr)
acc, err := types.NewAccountRetriever(clientCtx.JSONMarshaler).GetAccount(clientCtx, sigAddr)
if err != nil {
cmd.Printf("failed to get account: %s\n", sigAddr)
return false