Update auth cli commands (#6717)
* add utils * update sign cmd * update multisign cmd * update sign batch cmd * update genutil cmd * add wrap tx builder * update gentx cli * update validate sigs cmd * fix lint * add flag reader to cli * update marshaler for batchscan * add register query server * update to master * remove depricated methods * fix keyring issue * update wraptx * Fix batch scan * fix register interfaces issue * update printOutput * Update Validate Sigs test * WIP on signature JSON * Cleanup * Cleanup * Test fixes * Test fixes * Fixes * WIP on tests * Fix gov tests * fix lint * fix MultiSign tests * fix tests * refactor tests * Cleanup * Address review comments * Update encode * Test fix * Rename SignData func * Fix lint * Fix lint * Revert ReadTxCommandFlags Co-authored-by: Aaron Craelius <aaron@regen.network> Co-authored-by: Aaron Craelius <aaronc@users.noreply.github.com>
This commit is contained in:
co-authored by
Aaron Craelius
Aaron Craelius
parent
cf078c0c88
commit
72ebafeeca
+111
-94
@@ -14,19 +14,16 @@ import (
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
"github.com/cosmos/cosmos-sdk/client/flags"
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
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/simapp"
|
||||
"github.com/cosmos/cosmos-sdk/testutil"
|
||||
"github.com/cosmos/cosmos-sdk/testutil/network"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
authcli "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"
|
||||
authtypes "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"
|
||||
)
|
||||
@@ -47,7 +44,21 @@ func (s *IntegrationTestSuite) SetupSuite() {
|
||||
s.cfg = cfg
|
||||
s.network = network.New(s.T(), cfg)
|
||||
|
||||
_, err := s.network.WaitForHeight(1)
|
||||
kb := s.network.Validators[0].ClientCtx.Keyring
|
||||
_, _, err := kb.NewMnemonic("newAccount", keyring.English, sdk.FullFundraiserPath, hd.Secp256k1)
|
||||
s.Require().NoError(err)
|
||||
|
||||
account1, _, err := kb.NewMnemonic("newAccount1", keyring.English, sdk.FullFundraiserPath, hd.Secp256k1)
|
||||
s.Require().NoError(err)
|
||||
|
||||
account2, _, err := kb.NewMnemonic("newAccount2", keyring.English, sdk.FullFundraiserPath, hd.Secp256k1)
|
||||
s.Require().NoError(err)
|
||||
|
||||
multi := multisig.NewPubKeyMultisigThreshold(2, []tmcrypto.PubKey{account1.GetPubKey(), account2.GetPubKey()})
|
||||
_, err = kb.SaveMultisig("multi", multi)
|
||||
s.Require().NoError(err)
|
||||
|
||||
_, err = s.network.WaitForHeight(1)
|
||||
s.Require().NoError(err)
|
||||
}
|
||||
|
||||
@@ -73,29 +84,23 @@ func (s *IntegrationTestSuite) TestCLIValidateSignatures() {
|
||||
)
|
||||
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
|
||||
unsignedTx, cleanup := testutil.WriteToNewTempFile(s.T(), res.String())
|
||||
defer cleanup()
|
||||
|
||||
res, err = authtest.TxSignExec(val.ClientCtx, val.Address, unsignedTx.Name())
|
||||
s.Require().NoError(err)
|
||||
|
||||
var signedTx types.StdTx
|
||||
err = val.ClientCtx.JSONMarshaler.UnmarshalJSON(res.Bytes(), &signedTx)
|
||||
signedTx, err := val.ClientCtx.TxConfig.TxJSONDecoder()(res.Bytes())
|
||||
s.Require().NoError(err)
|
||||
|
||||
signedTxFile, cleanup := testutil.WriteToNewTempFile(s.T(), res.String())
|
||||
defer cleanup()
|
||||
|
||||
txBuilder, err := val.ClientCtx.TxConfig.WrapTxBuilder(signedTx)
|
||||
res, err = authtest.TxValidateSignaturesExec(val.ClientCtx, signedTxFile.Name())
|
||||
s.Require().NoError(err)
|
||||
|
||||
signedTx.Memo = "MODIFIED STD TX"
|
||||
bz, err := val.ClientCtx.JSONMarshaler.MarshalJSON(signedTx)
|
||||
txBuilder.SetMemo("MODIFIED TX")
|
||||
bz, err := val.ClientCtx.TxConfig.TxJSONEncoder()(txBuilder.GetTx())
|
||||
s.Require().NoError(err)
|
||||
|
||||
modifiedTxFile, cleanup := testutil.WriteToNewTempFile(s.T(), string(bz))
|
||||
@@ -147,28 +152,26 @@ func (s *IntegrationTestSuite) TestCLISignBatch() {
|
||||
defer cleanup2()
|
||||
|
||||
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")
|
||||
s.Require().Error(err)
|
||||
|
||||
// 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")
|
||||
s.Require().Error(err)
|
||||
}
|
||||
|
||||
func (s *IntegrationTestSuite) TestCLISendGenerateSignAndBroadcast() {
|
||||
val1 := s.network.Validators[0]
|
||||
|
||||
account, _, err := val1.ClientCtx.Keyring.NewMnemonic("newAccount", keyring.English, sdk.FullFundraiserPath, hd.Secp256k1)
|
||||
account, err := val1.ClientCtx.Keyring.Key("newAccount")
|
||||
s.Require().NoError(err)
|
||||
|
||||
sendTokens := sdk.TokensFromConsensusPower(10)
|
||||
sendTokens := sdk.NewCoin(s.cfg.BondDenom, sdk.TokensFromConsensusPower(10))
|
||||
|
||||
normalGeneratedTx, err := bankcli.MsgSendExec(
|
||||
val1.ClientCtx,
|
||||
val1.Address,
|
||||
account.GetAddress(),
|
||||
sdk.NewCoins(
|
||||
sdk.NewCoin(s.cfg.BondDenom, sendTokens),
|
||||
),
|
||||
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()),
|
||||
@@ -176,19 +179,22 @@ func (s *IntegrationTestSuite) TestCLISendGenerateSignAndBroadcast() {
|
||||
)
|
||||
s.Require().NoError(err)
|
||||
|
||||
normalGeneratedStdTx := 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()))
|
||||
txCfg := val1.ClientCtx.TxConfig
|
||||
|
||||
normalGeneratedStdTx, err := txCfg.TxJSONDecoder()(normalGeneratedTx.Bytes())
|
||||
s.Require().NoError(err)
|
||||
txBuilder, err := txCfg.WrapTxBuilder(normalGeneratedStdTx)
|
||||
s.Require().NoError(err)
|
||||
s.Require().Equal(txBuilder.GetTx().GetGas(), uint64(flags.DefaultGasLimit))
|
||||
s.Require().Equal(len(txBuilder.GetTx().GetMsgs()), 1)
|
||||
s.Require().Equal(0, len(txBuilder.GetTx().GetSignatures()))
|
||||
|
||||
// Test generate sendTx with --gas=$amount
|
||||
limitedGasGeneratedTx, err := bankcli.MsgSendExec(
|
||||
val1.ClientCtx,
|
||||
val1.Address,
|
||||
account.GetAddress(),
|
||||
sdk.NewCoins(
|
||||
sdk.NewCoin(s.cfg.BondDenom, sendTokens),
|
||||
),
|
||||
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()),
|
||||
@@ -197,19 +203,28 @@ func (s *IntegrationTestSuite) TestCLISendGenerateSignAndBroadcast() {
|
||||
)
|
||||
s.Require().NoError(err)
|
||||
|
||||
limitedGasStdTx := 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()))
|
||||
limitedGasStdTx, err := txCfg.TxJSONDecoder()(limitedGasGeneratedTx.Bytes())
|
||||
s.Require().NoError(err)
|
||||
txBuilder, err = txCfg.WrapTxBuilder(limitedGasStdTx)
|
||||
s.Require().NoError(err)
|
||||
s.Require().Equal(txBuilder.GetTx().GetGas(), uint64(100))
|
||||
s.Require().Equal(len(txBuilder.GetTx().GetMsgs()), 1)
|
||||
s.Require().Equal(0, len(txBuilder.GetTx().GetSignatures()))
|
||||
|
||||
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)
|
||||
startTokens := coins.AmountOf(s.cfg.BondDenom)
|
||||
|
||||
// Test generate sendTx, estimate gas
|
||||
finalGeneratedTx, err := bankcli.MsgSendExec(
|
||||
val1.ClientCtx,
|
||||
val1.Address,
|
||||
account.GetAddress(),
|
||||
sdk.NewCoins(
|
||||
sdk.NewCoin(s.cfg.BondDenom, sendTokens),
|
||||
),
|
||||
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()),
|
||||
@@ -218,9 +233,12 @@ func (s *IntegrationTestSuite) TestCLISendGenerateSignAndBroadcast() {
|
||||
)
|
||||
s.Require().NoError(err)
|
||||
|
||||
finalStdTx := unmarshalStdTx(s.T(), val1.ClientCtx.JSONMarshaler, finalGeneratedTx.String())
|
||||
s.Require().Equal(uint64(flags.DefaultGasLimit), finalStdTx.Fee.Gas)
|
||||
s.Require().Equal(len(finalStdTx.Msgs), 1)
|
||||
finalStdTx, err := txCfg.TxJSONDecoder()(finalGeneratedTx.Bytes())
|
||||
s.Require().NoError(err)
|
||||
txBuilder, err = txCfg.WrapTxBuilder(finalStdTx)
|
||||
s.Require().NoError(err)
|
||||
s.Require().Equal(uint64(flags.DefaultGasLimit), txBuilder.GetTx().GetGas())
|
||||
s.Require().Equal(len(finalStdTx.GetMsgs()), 1)
|
||||
|
||||
// Write the output to disk
|
||||
unsignedTxFile, cleanup := testutil.WriteToNewTempFile(s.T(), finalGeneratedTx.String())
|
||||
@@ -245,11 +263,13 @@ func (s *IntegrationTestSuite) TestCLISendGenerateSignAndBroadcast() {
|
||||
// Sign transaction
|
||||
signedTx, err := authtest.TxSignExec(val1.ClientCtx, val1.Address, unsignedTxFile.Name())
|
||||
s.Require().NoError(err)
|
||||
|
||||
signedFinalTx := 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())
|
||||
signedFinalTx, err := txCfg.TxJSONDecoder()(signedTx.Bytes())
|
||||
s.Require().NoError(err)
|
||||
txBuilder, err = val1.ClientCtx.TxConfig.WrapTxBuilder(signedFinalTx)
|
||||
s.Require().NoError(err)
|
||||
s.Require().Equal(len(txBuilder.GetTx().GetMsgs()), 1)
|
||||
s.Require().Equal(1, len(txBuilder.GetTx().GetSignatures()))
|
||||
s.Require().Equal(val1.Address.String(), txBuilder.GetTx().GetSigners()[0].String())
|
||||
|
||||
// Write the output to disk
|
||||
signedTxFile, cleanup2 := testutil.WriteToNewTempFile(s.T(), signedTx.String())
|
||||
@@ -261,11 +281,9 @@ func (s *IntegrationTestSuite) TestCLISendGenerateSignAndBroadcast() {
|
||||
s.Require().True(strings.Contains(res.String(), "[OK]"))
|
||||
|
||||
// Ensure foo has right amount of funds
|
||||
startTokens := sdk.TokensFromConsensusPower(400)
|
||||
resp, err := bankcli.QueryBalancesExec(val1.ClientCtx, val1.Address)
|
||||
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(s.cfg.BondDenom))
|
||||
@@ -291,7 +309,7 @@ func (s *IntegrationTestSuite) TestCLISendGenerateSignAndBroadcast() {
|
||||
|
||||
err = val1.ClientCtx.JSONMarshaler.UnmarshalJSON(resp.Bytes(), &coins)
|
||||
s.Require().NoError(err)
|
||||
s.Require().Equal(sendTokens, coins.AmountOf(s.cfg.BondDenom))
|
||||
s.Require().Equal(sendTokens.Amount, coins.AmountOf(s.cfg.BondDenom))
|
||||
|
||||
// Ensure origin account state
|
||||
resp, err = bankcli.QueryBalancesExec(val1.ClientCtx, val1.Address)
|
||||
@@ -299,11 +317,9 @@ func (s *IntegrationTestSuite) TestCLISendGenerateSignAndBroadcast() {
|
||||
|
||||
err = val1.ClientCtx.JSONMarshaler.UnmarshalJSON(resp.Bytes(), &coins)
|
||||
s.Require().NoError(err)
|
||||
s.Require().Equal(sdk.NewInt(389999990), coins.AmountOf(s.cfg.BondDenom))
|
||||
}
|
||||
|
||||
func (s *IntegrationTestSuite) TestCLIMultisignInsufficientCosigners() {
|
||||
s.T().SkipNow() // TODO check encoding.
|
||||
val1 := s.network.Validators[0]
|
||||
|
||||
codec := codec2.New()
|
||||
@@ -312,14 +328,10 @@ func (s *IntegrationTestSuite) TestCLIMultisignInsufficientCosigners() {
|
||||
val1.ClientCtx.Codec = codec
|
||||
|
||||
// Generate 2 accounts and a multisig.
|
||||
account1, _, err := val1.ClientCtx.Keyring.NewMnemonic("newAccount1", keyring.English, sdk.FullFundraiserPath, hd.Secp256k1)
|
||||
account1, err := val1.ClientCtx.Keyring.Key("newAccount1")
|
||||
s.Require().NoError(err)
|
||||
|
||||
account2, _, err := val1.ClientCtx.Keyring.NewMnemonic("newAccount2", keyring.English, sdk.FullFundraiserPath, hd.Secp256k1)
|
||||
s.Require().NoError(err)
|
||||
|
||||
multi := multisig.NewPubKeyMultisigThreshold(2, []tmcrypto.PubKey{account1.GetPubKey(), account2.GetPubKey()})
|
||||
multisigInfo, err := val1.ClientCtx.Keyring.SaveMultisig("multi", multi)
|
||||
multisigInfo, err := val1.ClientCtx.Keyring.Key("multi")
|
||||
s.Require().NoError(err)
|
||||
|
||||
// Send coins from validator to multisig.
|
||||
@@ -374,7 +386,7 @@ func (s *IntegrationTestSuite) TestCLIMultisignInsufficientCosigners() {
|
||||
defer cleanup3()
|
||||
|
||||
exec, err := authtest.TxValidateSignaturesExec(val1.ClientCtx, multiSigWith1SignatureFile.Name())
|
||||
s.Require().NoError(err)
|
||||
s.Require().Error(err)
|
||||
|
||||
fmt.Printf("%s", exec)
|
||||
}
|
||||
@@ -382,15 +394,13 @@ func (s *IntegrationTestSuite) TestCLIMultisignInsufficientCosigners() {
|
||||
func (s *IntegrationTestSuite) TestCLIEncode() {
|
||||
val1 := s.network.Validators[0]
|
||||
|
||||
sendTokens := sdk.TokensFromConsensusPower(10)
|
||||
sendTokens := sdk.NewCoin(s.cfg.BondDenom, sdk.TokensFromConsensusPower(10))
|
||||
|
||||
normalGeneratedTx, err := bankcli.MsgSendExec(
|
||||
val1.ClientCtx,
|
||||
val1.Address,
|
||||
val1.Address,
|
||||
sdk.NewCoins(
|
||||
sdk.NewCoin(s.cfg.BondDenom, sendTokens),
|
||||
),
|
||||
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()),
|
||||
@@ -402,7 +412,7 @@ func (s *IntegrationTestSuite) TestCLIEncode() {
|
||||
savedTxFile, cleanup := testutil.WriteToNewTempFile(s.T(), normalGeneratedTx.String())
|
||||
defer cleanup()
|
||||
|
||||
// Enconde
|
||||
// Encode
|
||||
encodeExec, err := authtest.TxEncodeExec(val1.ClientCtx, savedTxFile.Name())
|
||||
s.Require().NoError(err)
|
||||
|
||||
@@ -412,12 +422,15 @@ func (s *IntegrationTestSuite) TestCLIEncode() {
|
||||
decodedTx, err := authtest.TxDecodeExec(val1.ClientCtx, trimmedBase64)
|
||||
s.Require().NoError(err)
|
||||
|
||||
theTx := unmarshalStdTx(s.T(), val1.ClientCtx.JSONMarshaler, decodedTx.String())
|
||||
s.Require().Equal("deadbeef", theTx.Memo)
|
||||
txCfg := val1.ClientCtx.TxConfig
|
||||
theTx, err := txCfg.TxJSONDecoder()(decodedTx.Bytes())
|
||||
s.Require().NoError(err)
|
||||
txBuilder, err := val1.ClientCtx.TxConfig.WrapTxBuilder(theTx)
|
||||
s.Require().NoError(err)
|
||||
s.Require().Equal("deadbeef", txBuilder.GetTx().GetMemo())
|
||||
}
|
||||
|
||||
func (s *IntegrationTestSuite) TestCLIMultisignSortSignatures() {
|
||||
s.T().SkipNow()
|
||||
val1 := s.network.Validators[0]
|
||||
|
||||
codec := codec2.New()
|
||||
@@ -426,25 +439,30 @@ func (s *IntegrationTestSuite) TestCLIMultisignSortSignatures() {
|
||||
val1.ClientCtx.Codec = codec
|
||||
|
||||
// Generate 2 accounts and a multisig.
|
||||
account1, _, err := val1.ClientCtx.Keyring.NewMnemonic("newAccount1", keyring.English, sdk.FullFundraiserPath, hd.Secp256k1)
|
||||
account1, err := val1.ClientCtx.Keyring.Key("newAccount1")
|
||||
s.Require().NoError(err)
|
||||
|
||||
account2, _, err := val1.ClientCtx.Keyring.NewMnemonic("newAccount2", keyring.English, sdk.FullFundraiserPath, hd.Secp256k1)
|
||||
account2, err := val1.ClientCtx.Keyring.Key("newAccount2")
|
||||
s.Require().NoError(err)
|
||||
|
||||
multi := multisig.NewPubKeyMultisigThreshold(2, []tmcrypto.PubKey{account1.GetPubKey(), account2.GetPubKey()})
|
||||
multisigInfo, err := val1.ClientCtx.Keyring.SaveMultisig("multi", multi)
|
||||
multisigInfo, err := val1.ClientCtx.Keyring.Key("multi")
|
||||
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)
|
||||
intialCoins := coins
|
||||
|
||||
// Send coins from validator to multisig.
|
||||
sendTokens := sdk.NewInt64Coin(s.cfg.BondDenom, 10)
|
||||
_, err = bankcli.MsgSendExec(
|
||||
val1.ClientCtx,
|
||||
val1.Address,
|
||||
multisigInfo.GetAddress(),
|
||||
sdk.NewCoins(
|
||||
sendTokens,
|
||||
),
|
||||
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()),
|
||||
@@ -454,13 +472,13 @@ func (s *IntegrationTestSuite) TestCLIMultisignSortSignatures() {
|
||||
|
||||
s.Require().NoError(s.network.WaitForNextBlock())
|
||||
|
||||
resp, err := bankcli.QueryBalancesExec(val1.ClientCtx, multisigInfo.GetAddress())
|
||||
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(s.cfg.BondDenom))
|
||||
diff, _ := coins.SafeSub(intialCoins)
|
||||
s.Require().Equal(sendTokens.Amount, diff.AmountOf(s.cfg.BondDenom))
|
||||
|
||||
// Generate multisig transaction.
|
||||
multiGeneratedTx, err := bankcli.MsgSendExec(
|
||||
@@ -514,7 +532,6 @@ func (s *IntegrationTestSuite) TestCLIMultisignSortSignatures() {
|
||||
}
|
||||
|
||||
func (s *IntegrationTestSuite) TestCLIMultisign() {
|
||||
s.T().SkipNow()
|
||||
val1 := s.network.Validators[0]
|
||||
|
||||
codec := codec2.New()
|
||||
@@ -523,14 +540,13 @@ func (s *IntegrationTestSuite) TestCLIMultisign() {
|
||||
val1.ClientCtx.Codec = codec
|
||||
|
||||
// Generate 2 accounts and a multisig.
|
||||
account1, _, err := val1.ClientCtx.Keyring.NewMnemonic("newAccount1", keyring.English, sdk.FullFundraiserPath, hd.Secp256k1)
|
||||
account1, err := val1.ClientCtx.Keyring.Key("newAccount1")
|
||||
s.Require().NoError(err)
|
||||
|
||||
account2, _, err := val1.ClientCtx.Keyring.NewMnemonic("newAccount2", keyring.English, sdk.FullFundraiserPath, hd.Secp256k1)
|
||||
account2, err := val1.ClientCtx.Keyring.Key("newAccount2")
|
||||
s.Require().NoError(err)
|
||||
|
||||
multi := multisig.NewPubKeyMultisigThreshold(2, []tmcrypto.PubKey{account1.GetPubKey(), account2.GetPubKey()})
|
||||
multisigInfo, err := val1.ClientCtx.Keyring.SaveMultisig("multi", multi)
|
||||
multisigInfo, err := val1.ClientCtx.Keyring.Key("multi")
|
||||
s.Require().NoError(err)
|
||||
|
||||
// Send coins from validator to multisig.
|
||||
@@ -539,9 +555,7 @@ func (s *IntegrationTestSuite) TestCLIMultisign() {
|
||||
val1.ClientCtx,
|
||||
val1.Address,
|
||||
multisigInfo.GetAddress(),
|
||||
sdk.NewCoins(
|
||||
sendTokens,
|
||||
),
|
||||
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()),
|
||||
@@ -593,8 +607,7 @@ func (s *IntegrationTestSuite) TestCLIMultisign() {
|
||||
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())
|
||||
_, err = authtest.TxMultiSignExec(val1.ClientCtx, multisigInfo.GetName(), multiGeneratedTxFile.Name(), "--offline", sign1File.Name(), sign2File.Name())
|
||||
s.Require().EqualError(err, "couldn't verify signature")
|
||||
|
||||
val1.ClientCtx.Offline = false
|
||||
@@ -617,7 +630,7 @@ func (s *IntegrationTestSuite) TestCLIMultisign() {
|
||||
|
||||
func TestGetBroadcastCommand_OfflineFlag(t *testing.T) {
|
||||
clientCtx := client.Context{}.WithOffline(true)
|
||||
clientCtx = clientCtx.WithTxConfig(simappparams.MakeEncodingConfig().TxConfig)
|
||||
clientCtx = clientCtx.WithTxConfig(simapp.MakeEncodingConfig().TxConfig)
|
||||
|
||||
cmd := authcli.GetBroadcastCommand()
|
||||
_ = testutil.ApplyMockIODiscardOutErr(cmd)
|
||||
@@ -628,7 +641,8 @@ func TestGetBroadcastCommand_OfflineFlag(t *testing.T) {
|
||||
|
||||
func TestGetBroadcastCommand_WithoutOfflineFlag(t *testing.T) {
|
||||
clientCtx := client.Context{}
|
||||
clientCtx = clientCtx.WithTxConfig(simappparams.MakeEncodingConfig().TxConfig)
|
||||
txCfg := simapp.MakeEncodingConfig().TxConfig
|
||||
clientCtx = clientCtx.WithTxConfig(txCfg)
|
||||
|
||||
ctx := context.Background()
|
||||
ctx = context.WithValue(ctx, client.ClientContextKey, &clientCtx)
|
||||
@@ -639,9 +653,17 @@ func TestGetBroadcastCommand_WithoutOfflineFlag(t *testing.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\":\"\"}}")
|
||||
builder := txCfg.NewTxBuilder()
|
||||
builder.SetGasLimit(200000)
|
||||
from, err := sdk.AccAddressFromBech32("cosmos1cxlt8kznps92fwu3j6npahx4mjfutydyene2qw")
|
||||
require.NoError(t, err)
|
||||
to, err := sdk.AccAddressFromBech32("cosmos1cxlt8kznps92fwu3j6npahx4mjfutydyene2qw")
|
||||
require.NoError(t, err)
|
||||
err = builder.SetMsgs(banktypes.NewMsgSend(from, to, sdk.Coins{sdk.NewInt64Coin("stake", 10000)}))
|
||||
require.NoError(t, err)
|
||||
txContents, err := txCfg.TxJSONEncoder()(builder.GetTx())
|
||||
txFileName := filepath.Join(testDir, "tx.json")
|
||||
err := ioutil.WriteFile(txFileName, txContents, 0644)
|
||||
err = ioutil.WriteFile(txFileName, txContents, 0644)
|
||||
require.NoError(t, err)
|
||||
|
||||
cmd.SetArgs([]string{txFileName})
|
||||
@@ -654,8 +676,3 @@ func TestGetBroadcastCommand_WithoutOfflineFlag(t *testing.T) {
|
||||
func TestIntegrationTestSuite(t *testing.T) {
|
||||
suite.Run(t, new(IntegrationTestSuite))
|
||||
}
|
||||
|
||||
func unmarshalStdTx(t require.TestingT, c codec.JSONMarshaler, s string) (stdTx authtypes.StdTx) {
|
||||
require.Nil(t, c.UnmarshalJSON([]byte(s), &stdTx))
|
||||
return stdTx
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package cli
|
||||
import (
|
||||
"encoding/base64"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
@@ -37,7 +38,12 @@ func GetDecodeCommand() *cobra.Command {
|
||||
return err
|
||||
}
|
||||
|
||||
return clientCtx.PrintOutput(tx)
|
||||
json, err := clientCtx.TxConfig.TxJSONEncoder()(tx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return clientCtx.PrintString(fmt.Sprintf("%s\n", json))
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ package cli
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
@@ -10,13 +11,6 @@ import (
|
||||
authclient "github.com/cosmos/cosmos-sdk/x/auth/client"
|
||||
)
|
||||
|
||||
// txEncodeRespStr implements a simple Stringer wrapper for a encoded tx.
|
||||
type txEncodeRespStr string
|
||||
|
||||
func (txr txEncodeRespStr) String() string {
|
||||
return string(txr)
|
||||
}
|
||||
|
||||
// GetEncodeCommand returns the encode command to take a JSONified transaction and turn it into
|
||||
// Amino-serialized bytes
|
||||
func GetEncodeCommand() *cobra.Command {
|
||||
@@ -44,8 +38,7 @@ If you supply a dash (-) argument in place of an input filename, the command rea
|
||||
// base64 encode the encoded tx bytes
|
||||
txBytesBase64 := base64.StdEncoding.EncodeToString(txBytes)
|
||||
|
||||
response := txEncodeRespStr(txBytesBase64)
|
||||
return clientCtx.PrintOutput(response)
|
||||
return clientCtx.PrintString(fmt.Sprintf("%s\n", txBytesBase64))
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -23,15 +23,17 @@ func TestGetCommandEncode(t *testing.T) {
|
||||
authtypes.RegisterCodec(encodingConfig.Amino)
|
||||
sdk.RegisterCodec(encodingConfig.Amino)
|
||||
|
||||
txGen := encodingConfig.TxConfig
|
||||
txCfg := encodingConfig.TxConfig
|
||||
|
||||
// Build a test transaction
|
||||
fee := authtypes.NewStdFee(50000, sdk.Coins{sdk.NewInt64Coin("atom", 150)})
|
||||
stdTx := authtypes.NewStdTx([]sdk.Msg{}, fee, []authtypes.StdSignature{}, "foomemo")
|
||||
JSONEncoded, err := txGen.TxJSONEncoder()(stdTx)
|
||||
builder := txCfg.NewTxBuilder()
|
||||
builder.SetGasLimit(50000)
|
||||
builder.SetFeeAmount(sdk.Coins{sdk.NewInt64Coin("atom", 150)})
|
||||
builder.SetMemo("foomemo")
|
||||
jsonEncoded, err := txCfg.TxJSONEncoder()(builder.GetTx())
|
||||
require.NoError(t, err)
|
||||
|
||||
txFile, cleanup := testutil.WriteToNewTempFile(t, string(JSONEncoded))
|
||||
txFile, cleanup := testutil.WriteToNewTempFile(t, string(jsonEncoded))
|
||||
txFileName := txFile.Name()
|
||||
t.Cleanup(cleanup)
|
||||
|
||||
@@ -58,15 +60,17 @@ func TestGetCommandDecode(t *testing.T) {
|
||||
|
||||
sdk.RegisterCodec(encodingConfig.Amino)
|
||||
|
||||
txGen := encodingConfig.TxConfig
|
||||
clientCtx = clientCtx.WithTxConfig(txGen)
|
||||
txCfg := encodingConfig.TxConfig
|
||||
clientCtx = clientCtx.WithTxConfig(txCfg)
|
||||
|
||||
// Build a test transaction
|
||||
fee := authtypes.NewStdFee(50000, sdk.Coins{sdk.NewInt64Coin("atom", 150)})
|
||||
stdTx := authtypes.NewStdTx([]sdk.Msg{}, fee, []authtypes.StdSignature{}, "foomemo")
|
||||
builder := txCfg.NewTxBuilder()
|
||||
builder.SetGasLimit(50000)
|
||||
builder.SetFeeAmount(sdk.Coins{sdk.NewInt64Coin("atom", 150)})
|
||||
builder.SetMemo("foomemo")
|
||||
|
||||
// Encode transaction
|
||||
txBytes, err := clientCtx.TxConfig.TxEncoder()(stdTx)
|
||||
txBytes, err := clientCtx.TxConfig.TxEncoder()(builder.GetTx())
|
||||
require.NoError(t, err)
|
||||
|
||||
// Convert the transaction into base64 encoded string
|
||||
|
||||
@@ -11,13 +11,14 @@ import (
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
"github.com/cosmos/cosmos-sdk/client/flags"
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
"github.com/cosmos/cosmos-sdk/client/tx"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/keyring"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/types/multisig"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/types/errors"
|
||||
signingtypes "github.com/cosmos/cosmos-sdk/types/tx/signing"
|
||||
"github.com/cosmos/cosmos-sdk/version"
|
||||
authclient "github.com/cosmos/cosmos-sdk/x/auth/client"
|
||||
"github.com/cosmos/cosmos-sdk/x/auth/signing"
|
||||
"github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||
)
|
||||
|
||||
@@ -60,13 +61,27 @@ recommended to set such parameters manually.
|
||||
func makeMultiSignCmd() func(cmd *cobra.Command, args []string) error {
|
||||
return func(cmd *cobra.Command, args []string) (err error) {
|
||||
clientCtx := client.GetClientContextFromCmd(cmd)
|
||||
cdc := clientCtx.Codec
|
||||
tx, err := authclient.ReadTxFromFile(clientCtx, args[0])
|
||||
stdTx := tx.(types.StdTx)
|
||||
clientCtx, err = client.ReadTxCommandFlags(clientCtx, cmd.Flags())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
parsedTx, err := authclient.ReadTxFromFile(clientCtx, args[0])
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
txFactory := tx.NewFactoryCLI(clientCtx, cmd.Flags())
|
||||
if txFactory.SignMode() == signingtypes.SignMode_SIGN_MODE_UNSPECIFIED {
|
||||
txFactory = txFactory.WithSignMode(signingtypes.SignMode_SIGN_MODE_LEGACY_AMINO_JSON)
|
||||
}
|
||||
|
||||
txCfg := clientCtx.TxConfig
|
||||
txBuilder, err := txCfg.WrapTxBuilder(parsedTx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
backend, _ := cmd.Flags().GetString(flags.FlagKeyringBackend)
|
||||
|
||||
inBuf := bufio.NewReader(cmd.InOrStdin())
|
||||
@@ -85,63 +100,53 @@ func makeMultiSignCmd() func(cmd *cobra.Command, args []string) error {
|
||||
|
||||
multisigPub := multisigInfo.GetPubKey().(multisig.PubKeyMultisigThreshold)
|
||||
multisigSig := multisig.NewMultisig(len(multisigPub.PubKeys))
|
||||
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(clientCtx.JSONMarshaler).GetAccountNumberSequence(clientCtx, multisigInfo.GetAddress())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
txBldr = txBldr.WithAccountNumber(accnum).WithSequence(seq)
|
||||
txFactory = txFactory.WithAccountNumber(accnum).WithSequence(seq)
|
||||
}
|
||||
|
||||
// read each signature and add it to the multisig if valid
|
||||
for i := 2; i < len(args); i++ {
|
||||
stdSig, err := readAndUnmarshalStdSignature(cdc, args[i])
|
||||
sigs, err := unmarshalSignatureJSON(clientCtx, args[i])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Validate each signature
|
||||
sigBytes := types.StdSignBytes(
|
||||
txBldr.ChainID(), txBldr.AccountNumber(), txBldr.Sequence(),
|
||||
stdTx.Fee, stdTx.GetMsgs(), stdTx.GetMemo(),
|
||||
)
|
||||
if ok := stdSig.GetPubKey().VerifyBytes(sigBytes, stdSig.Signature); !ok {
|
||||
return fmt.Errorf("couldn't verify signature")
|
||||
signingData := signing.SignerData{
|
||||
ChainID: txFactory.ChainID(),
|
||||
AccountNumber: txFactory.AccountNumber(),
|
||||
AccountSequence: txFactory.Sequence(),
|
||||
}
|
||||
|
||||
sigV2, err := types.StdSignatureToSignatureV2(cdc, stdSig)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
for _, sig := range sigs {
|
||||
err = signing.VerifySignature(sig.PubKey, signingData, sig.Data, txCfg.SignModeHandler(), txBuilder.GetTx())
|
||||
if err != nil {
|
||||
return fmt.Errorf("couldn't verify signature")
|
||||
}
|
||||
|
||||
if err := multisig.AddSignatureV2(multisigSig, sigV2, multisigPub.PubKeys); err != nil {
|
||||
return err
|
||||
if err := multisig.AddSignatureV2(multisigSig, sig, multisigPub.PubKeys); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sigBz, err := types.SignatureDataToAminoSignature(cdc, multisigSig)
|
||||
sigV2 := signingtypes.SignatureV2{
|
||||
PubKey: multisigPub,
|
||||
Data: multisigSig,
|
||||
}
|
||||
|
||||
err = txBuilder.SetSignatures(sigV2)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
newStdSig := types.StdSignature{Signature: sigBz, PubKey: multisigPub.Bytes()} //nolint:staticcheck
|
||||
newTx := types.NewStdTx(stdTx.GetMsgs(), stdTx.Fee, []types.StdSignature{newStdSig}, stdTx.GetMemo()) //nolint:staticcheck
|
||||
|
||||
var json []byte
|
||||
|
||||
sigOnly, _ := cmd.Flags().GetBool(flagSigOnly)
|
||||
if sigOnly {
|
||||
json, err = cdc.MarshalJSON(newTx.Signatures[0])
|
||||
} else {
|
||||
json, err = cdc.MarshalJSON(newTx)
|
||||
}
|
||||
|
||||
json, err := marshalSignatureJSON(txCfg, txBuilder, sigOnly)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -158,18 +163,14 @@ func makeMultiSignCmd() func(cmd *cobra.Command, args []string) error {
|
||||
}
|
||||
defer fp.Close()
|
||||
|
||||
fmt.Fprintf(fp, "%s\n", json)
|
||||
return
|
||||
return clientCtx.PrintString(fmt.Sprintf("%s\n", json))
|
||||
}
|
||||
}
|
||||
|
||||
func readAndUnmarshalStdSignature(cdc *codec.Codec, filename string) (stdSig types.StdSignature, err error) { //nolint:staticcheck
|
||||
func unmarshalSignatureJSON(clientCtx client.Context, filename string) (sigs []signingtypes.SignatureV2, err error) {
|
||||
var bytes []byte
|
||||
if bytes, err = ioutil.ReadFile(filename); err != nil {
|
||||
return
|
||||
}
|
||||
if err = cdc.UnmarshalJSON(bytes, &stdSig); err != nil {
|
||||
return
|
||||
}
|
||||
return
|
||||
return clientCtx.TxConfig.UnmarshalSignatureJSON(bytes)
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package cli
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
@@ -9,10 +8,10 @@ import (
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
"github.com/cosmos/cosmos-sdk/client/flags"
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
"github.com/cosmos/cosmos-sdk/client/tx"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/types/tx/signing"
|
||||
authclient "github.com/cosmos/cosmos-sdk/x/auth/client"
|
||||
"github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -61,12 +60,13 @@ account key. It implies --signature-only.
|
||||
func makeSignBatchCmd() func(cmd *cobra.Command, args []string) error {
|
||||
return func(cmd *cobra.Command, args []string) error {
|
||||
clientCtx := client.GetClientContextFromCmd(cmd)
|
||||
|
||||
txBldr, err := types.NewTxBuilderFromFlags(bufio.NewReader(cmd.InOrStdin()), cmd.Flags(), clientCtx.HomeDir)
|
||||
clientCtx, err := client.ReadTxCommandFlags(clientCtx, cmd.Flags())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
txFactory := tx.NewFactoryCLI(clientCtx, cmd.Flags())
|
||||
|
||||
txCfg := clientCtx.TxConfig
|
||||
generateSignatureOnly, _ := cmd.Flags().GetBool(flagSigOnly)
|
||||
|
||||
var (
|
||||
@@ -97,34 +97,34 @@ func makeSignBatchCmd() func(cmd *cobra.Command, args []string) error {
|
||||
return err
|
||||
}
|
||||
}
|
||||
scanner := authclient.NewBatchScanner(txCfg, infile)
|
||||
|
||||
scanner := authclient.NewBatchScanner(clientCtx.JSONMarshaler, infile)
|
||||
|
||||
for sequence := txBldr.Sequence(); scanner.Scan(); sequence++ {
|
||||
var stdTx types.StdTx
|
||||
|
||||
unsignedStdTx := scanner.StdTx()
|
||||
txBldr = txBldr.WithSequence(sequence)
|
||||
|
||||
for sequence := txFactory.Sequence(); scanner.Scan(); sequence++ {
|
||||
unsignedStdTx := scanner.Tx()
|
||||
txFactory = txFactory.WithSequence(sequence)
|
||||
txBuilder, err := txCfg.WrapTxBuilder(unsignedStdTx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if multisigAddr.Empty() {
|
||||
from, _ := cmd.Flags().GetString(flags.FlagFrom)
|
||||
_, fromName, err := client.GetFromFields(txBldr.Keybase(), from, clientCtx.GenerateOnly)
|
||||
_, fromName, err := client.GetFromFields(txFactory.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)
|
||||
err = authclient.SignTx(txFactory, clientCtx, fromName, txBuilder, true)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
stdTx, err = authclient.SignStdTxWithSignerAddress(txBldr, clientCtx, multisigAddr, clientCtx.GetFromName(), unsignedStdTx, true)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = authclient.SignTxWithSignerAddress(txFactory, clientCtx, multisigAddr, clientCtx.GetFromName(), txBuilder, true)
|
||||
}
|
||||
|
||||
json, err := getSignatureJSON(clientCtx.JSONMarshaler, stdTx, generateSignatureOnly)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
json, err := marshalSignatureJSON(txCfg, txBuilder, generateSignatureOnly)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -206,20 +206,31 @@ func preSignCmd(cmd *cobra.Command, _ []string) {
|
||||
func makeSignCmd() func(cmd *cobra.Command, args []string) error {
|
||||
return func(cmd *cobra.Command, args []string) error {
|
||||
clientCtx := client.GetClientContextFromCmd(cmd)
|
||||
clientCtx, err := client.ReadTxCommandFlags(clientCtx, cmd.Flags())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
txFactory := tx.NewFactoryCLI(clientCtx, cmd.Flags())
|
||||
|
||||
clientCtx, txBldr, tx, err := readStdTxAndInitContexts(clientCtx, cmd, args[0])
|
||||
clientCtx, txF, newTx, err := readTxAndInitContexts(clientCtx, cmd, args[0])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if txF.SignMode() == signing.SignMode_SIGN_MODE_UNSPECIFIED {
|
||||
txF = txF.WithSignMode(signing.SignMode_SIGN_MODE_LEGACY_AMINO_JSON)
|
||||
}
|
||||
txCfg := clientCtx.TxConfig
|
||||
txBuilder, err := txCfg.WrapTxBuilder(newTx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
stdTx := tx.(types.StdTx)
|
||||
|
||||
// if --signature-only is on, then override --append
|
||||
var newTx types.StdTx
|
||||
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)
|
||||
_, fromName, err := client.GetFromFields(txFactory.Keybase(), from, clientCtx.GenerateOnly)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error getting account from keybase: %w", err)
|
||||
}
|
||||
@@ -232,23 +243,22 @@ func makeSignCmd() func(cmd *cobra.Command, args []string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
newTx, err = authclient.SignStdTxWithSignerAddress(
|
||||
txBldr, clientCtx, multisigAddr, fromName, stdTx, clientCtx.Offline,
|
||||
err = authclient.SignTxWithSignerAddress(
|
||||
txF, clientCtx, multisigAddr, fromName, txBuilder, clientCtx.Offline,
|
||||
)
|
||||
generateSignatureOnly = true
|
||||
} else {
|
||||
append, _ := cmd.Flags().GetBool(flagAppend)
|
||||
appendSig := append && !generateSignatureOnly
|
||||
newTx, err = authclient.SignStdTx(txBldr, clientCtx, fromName, stdTx, appendSig, clientCtx.Offline)
|
||||
if err != nil {
|
||||
return err
|
||||
flagAppend, _ := cmd.Flags().GetBool(flagAppend)
|
||||
appendSig := flagAppend && !generateSignatureOnly
|
||||
if appendSig {
|
||||
err = authclient.SignTx(txF, clientCtx, clientCtx.GetFromName(), txBuilder, clientCtx.Offline)
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
json, err := getSignatureJSON(clientCtx.JSONMarshaler, newTx, generateSignatureOnly)
|
||||
json, err := marshalSignatureJSON(txCfg, txBuilder, generateSignatureOnly)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -265,15 +275,20 @@ func makeSignCmd() func(cmd *cobra.Command, args []string) error {
|
||||
}
|
||||
defer fp.Close()
|
||||
|
||||
fmt.Fprintf(fp, "%s\n", json)
|
||||
return nil
|
||||
return clientCtx.PrintString(fmt.Sprintf("%s\n", json))
|
||||
}
|
||||
}
|
||||
|
||||
func getSignatureJSON(cdc codec.JSONMarshaler, newTx types.StdTx, generateSignatureOnly bool) ([]byte, error) {
|
||||
func marshalSignatureJSON(txConfig client.TxConfig, txBldr client.TxBuilder, generateSignatureOnly bool) ([]byte, error) {
|
||||
parsedTx := txBldr.GetTx()
|
||||
|
||||
if generateSignatureOnly {
|
||||
return cdc.MarshalJSON(newTx.Signatures[0])
|
||||
sigs, err := parsedTx.GetSignaturesV2()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return txConfig.MarshalSignatureJSON(sigs)
|
||||
}
|
||||
|
||||
return cdc.MarshalJSON(newTx)
|
||||
return txConfig.TxJSONEncoder()(parsedTx)
|
||||
}
|
||||
|
||||
@@ -1,18 +1,16 @@
|
||||
package cli
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
"github.com/cosmos/cosmos-sdk/client/flags"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/types/multisig"
|
||||
"github.com/cosmos/cosmos-sdk/client/tx"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
authclient "github.com/cosmos/cosmos-sdk/x/auth/client"
|
||||
"github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||
authsigning "github.com/cosmos/cosmos-sdk/x/auth/signing"
|
||||
)
|
||||
|
||||
func GetValidateSignaturesCommand() *cobra.Command {
|
||||
@@ -41,11 +39,15 @@ transaction will be not be performed as that will require RPC communication with
|
||||
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])
|
||||
clientCtx, err := client.ReadTxCommandFlags(clientCtx, cmd.Flags())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
clientCtx, txBldr, stdTx, err := readTxAndInitContexts(clientCtx, cmd, args[0])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
stdTx := tx.(types.StdTx)
|
||||
|
||||
if !printAndValidateSigs(cmd, clientCtx, txBldr.ChainID(), stdTx, clientCtx.Offline) {
|
||||
return fmt.Errorf("signatures validation failed")
|
||||
@@ -59,17 +61,22 @@ func makeValidateSignaturesCmd() func(cmd *cobra.Command, args []string) error {
|
||||
// expected signers. In addition, if offline has not been supplied, the signature is
|
||||
// verified over the transaction sign bytes. Returns false if the validation fails.
|
||||
func printAndValidateSigs(
|
||||
cmd *cobra.Command, clientCtx client.Context, chainID string, stdTx types.StdTx, offline bool,
|
||||
cmd *cobra.Command, clientCtx client.Context, chainID string, tx sdk.Tx, offline bool,
|
||||
) bool {
|
||||
cmd.Println("Signers:")
|
||||
signers := stdTx.GetSigners()
|
||||
sigTx := tx.(authsigning.SigVerifiableTx)
|
||||
signModeHandler := clientCtx.TxConfig.SignModeHandler()
|
||||
|
||||
cmd.Println("Signers:")
|
||||
signers := sigTx.GetSigners()
|
||||
for i, signer := range signers {
|
||||
cmd.Printf(" %v: %v\n", i, signer.String())
|
||||
}
|
||||
|
||||
success := true
|
||||
sigs := stdTx.Signatures
|
||||
sigs, err := sigTx.GetSignaturesV2()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
cmd.Println("")
|
||||
cmd.Println("Signatures:")
|
||||
|
||||
@@ -79,9 +86,10 @@ func printAndValidateSigs(
|
||||
|
||||
for i, sig := range sigs {
|
||||
var (
|
||||
pubKey = sig.PubKey
|
||||
multiSigHeader string
|
||||
multiSigMsg string
|
||||
sigAddr = sdk.AccAddress(sig.GetPubKey().Address())
|
||||
sigAddr = sdk.AccAddress(pubKey.Address())
|
||||
sigSanity = "OK"
|
||||
)
|
||||
|
||||
@@ -93,40 +101,21 @@ 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(clientCtx.JSONMarshaler).GetAccount(clientCtx, sigAddr)
|
||||
accNum, accSeq, err := clientCtx.AccountRetriever.GetAccountNumberSequence(clientCtx, sigAddr)
|
||||
if err != nil {
|
||||
cmd.Printf("failed to get account: %s\n", sigAddr)
|
||||
return false
|
||||
}
|
||||
|
||||
sigBytes := types.StdSignBytes(
|
||||
chainID, acc.GetAccountNumber(), acc.GetSequence(),
|
||||
stdTx.Fee, stdTx.GetMsgs(), stdTx.GetMemo(),
|
||||
)
|
||||
|
||||
if ok := sig.GetPubKey().VerifyBytes(sigBytes, sig.Signature); !ok {
|
||||
sigSanity = "ERROR: signature invalid"
|
||||
success = false
|
||||
signingData := authsigning.SignerData{
|
||||
ChainID: chainID,
|
||||
AccountNumber: accNum,
|
||||
AccountSequence: accSeq,
|
||||
}
|
||||
}
|
||||
|
||||
multiPK, ok := sig.GetPubKey().(multisig.PubKeyMultisigThreshold)
|
||||
if ok {
|
||||
var multiSig multisig.AminoMultisignature
|
||||
clientCtx.Codec.MustUnmarshalBinaryBare(sig.Signature, &multiSig)
|
||||
|
||||
var b strings.Builder
|
||||
b.WriteString("\n MultiSig Signatures:\n")
|
||||
|
||||
for i := 0; i < multiSig.BitArray.Count(); i++ {
|
||||
if multiSig.BitArray.GetIndex(i) {
|
||||
addr := sdk.AccAddress(multiPK.PubKeys[i].Address().Bytes())
|
||||
b.WriteString(fmt.Sprintf(" %d: %s (weight: %d)\n", i, addr, 1))
|
||||
}
|
||||
err = authsigning.VerifySignature(pubKey, signingData, sig.Data, signModeHandler, sigTx)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
multiSigHeader = fmt.Sprintf(" [multisig threshold: %d/%d]", multiPK.K, len(multiPK.PubKeys))
|
||||
multiSigMsg = b.String()
|
||||
}
|
||||
|
||||
cmd.Printf(" %d: %s\t\t\t[%s]%s%s\n", i, sigAddr.String(), sigSanity, multiSigHeader, multiSigMsg)
|
||||
@@ -137,21 +126,13 @@ func printAndValidateSigs(
|
||||
return success
|
||||
}
|
||||
|
||||
func readStdTxAndInitContexts(clientCtx client.Context, cmd *cobra.Command, filename string) (
|
||||
client.Context, types.TxBuilder, sdk.Tx, error,
|
||||
) {
|
||||
func readTxAndInitContexts(clientCtx client.Context, cmd *cobra.Command, filename string) (client.Context, tx.Factory, sdk.Tx, error) {
|
||||
stdTx, err := authclient.ReadTxFromFile(clientCtx, filename)
|
||||
if err != nil {
|
||||
return client.Context{}, types.TxBuilder{}, types.StdTx{}, err
|
||||
return clientCtx, tx.Factory{}, nil, err
|
||||
}
|
||||
|
||||
inBuf := bufio.NewReader(cmd.InOrStdin())
|
||||
clientCtx = clientCtx.WithInput(inBuf)
|
||||
txFactory := tx.NewFactoryCLI(clientCtx, cmd.Flags())
|
||||
|
||||
txBldr, err := types.NewTxBuilderFromFlags(inBuf, cmd.Flags(), clientCtx.HomeDir)
|
||||
if err != nil {
|
||||
return client.Context{}, types.TxBuilder{}, types.StdTx{}, err
|
||||
}
|
||||
|
||||
return clientCtx, txBldr, stdTx, nil
|
||||
return clientCtx, txFactory, stdTx, nil
|
||||
}
|
||||
|
||||
+33
-179
@@ -10,10 +10,9 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/gogo/protobuf/jsonpb"
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
"github.com/cosmos/cosmos-sdk/client/input"
|
||||
"github.com/cosmos/cosmos-sdk/client/tx"
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
||||
@@ -38,81 +37,6 @@ func (gr GasEstimateResponse) String() string {
|
||||
return fmt.Sprintf("gas estimate: %d", gr.GasEstimate)
|
||||
}
|
||||
|
||||
// GenerateOrBroadcastMsgs creates a StdTx given a series of messages. If
|
||||
// the provided context has generate-only enabled, the tx will only be printed
|
||||
// to STDOUT in a fully offline manner. Otherwise, the tx will be signed and
|
||||
// broadcasted.
|
||||
func GenerateOrBroadcastMsgs(clientCtx client.Context, txBldr authtypes.TxBuilder, msgs []sdk.Msg) error {
|
||||
if clientCtx.GenerateOnly {
|
||||
return PrintUnsignedStdTx(txBldr, clientCtx, msgs)
|
||||
}
|
||||
|
||||
return CompleteAndBroadcastTxCLI(txBldr, clientCtx, msgs)
|
||||
}
|
||||
|
||||
// CompleteAndBroadcastTxCLI implements a utility function that facilitates
|
||||
// sending a series of messages in a signed transaction given a TxBuilder and a
|
||||
// QueryContext. It ensures that the account exists, has a proper number and
|
||||
// sequence set. In addition, it builds and signs a transaction with the
|
||||
// supplied messages. Finally, it broadcasts the signed transaction to a node.
|
||||
func CompleteAndBroadcastTxCLI(txBldr authtypes.TxBuilder, clientCtx client.Context, msgs []sdk.Msg) error {
|
||||
txBldr, err := PrepareTxBuilder(txBldr, clientCtx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fromName := clientCtx.GetFromName()
|
||||
|
||||
if txBldr.SimulateAndExecute() || clientCtx.Simulate {
|
||||
txBldr, err = EnrichWithGas(txBldr, clientCtx, msgs)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
gasEst := GasEstimateResponse{GasEstimate: txBldr.Gas()}
|
||||
_, _ = fmt.Fprintf(os.Stderr, "%s\n", gasEst.String())
|
||||
}
|
||||
|
||||
if clientCtx.Simulate {
|
||||
return nil
|
||||
}
|
||||
|
||||
if !clientCtx.SkipConfirm {
|
||||
stdSignMsg, err := txBldr.BuildSignMsg(msgs)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
json, err := clientCtx.JSONMarshaler.MarshalJSON(stdSignMsg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, _ = fmt.Fprintf(os.Stderr, "%s\n\n", json)
|
||||
|
||||
buf := bufio.NewReader(os.Stdin)
|
||||
ok, err := input.GetConfirmation("confirm transaction before signing and broadcasting", buf, os.Stderr)
|
||||
if err != nil || !ok {
|
||||
_, _ = fmt.Fprintf(os.Stderr, "%s\n", "cancelled transaction")
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// build and sign the transaction
|
||||
txBytes, err := txBldr.BuildAndSign(fromName, msgs)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// broadcast to a Tendermint node
|
||||
res, err := clientCtx.BroadcastTx(txBytes)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return clientCtx.PrintOutput(res)
|
||||
}
|
||||
|
||||
// EnrichWithGas calculates the gas estimate that would be consumed by the
|
||||
// transaction and set the transaction's respective value accordingly.
|
||||
func EnrichWithGas(txBldr authtypes.TxBuilder, clientCtx client.Context, msgs []sdk.Msg) (authtypes.TxBuilder, error) {
|
||||
@@ -148,74 +72,52 @@ func CalculateGas(
|
||||
}
|
||||
|
||||
// PrintUnsignedStdTx builds an unsigned StdTx and prints it to os.Stdout.
|
||||
func PrintUnsignedStdTx(txBldr authtypes.TxBuilder, clientCtx client.Context, msgs []sdk.Msg) error {
|
||||
stdTx, err := buildUnsignedStdTxOffline(txBldr, clientCtx, msgs)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
json, err := clientCtx.JSONMarshaler.MarshalJSON(stdTx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, _ = fmt.Fprintf(clientCtx.Output, "%s\n", json)
|
||||
return nil
|
||||
func PrintUnsignedStdTx(txBldr tx.Factory, clientCtx client.Context, msgs []sdk.Msg) error {
|
||||
err := tx.GenerateOrBroadcastTxWithFactory(clientCtx, txBldr, msgs...)
|
||||
return err
|
||||
}
|
||||
|
||||
// SignStdTx appends a signature to a StdTx and returns a copy of it. If appendSig
|
||||
// SignTx appends a signature to a transaction. If appendSig
|
||||
// is false, it replaces the signatures already attached with the new signature.
|
||||
// Don't perform online validation or lookups if offline is true.
|
||||
func SignStdTx(
|
||||
txBldr authtypes.TxBuilder, clientCtx client.Context, name string,
|
||||
stdTx authtypes.StdTx, appendSig bool, offline bool,
|
||||
) (authtypes.StdTx, error) {
|
||||
|
||||
var signedStdTx authtypes.StdTx
|
||||
|
||||
info, err := txBldr.Keybase().Key(name)
|
||||
func SignTx(txFactory tx.Factory, clientCtx client.Context, name string, stdTx client.TxBuilder, offline bool) error {
|
||||
info, err := txFactory.Keybase().Key(name)
|
||||
if err != nil {
|
||||
return signedStdTx, err
|
||||
return err
|
||||
}
|
||||
|
||||
addr := info.GetPubKey().Address()
|
||||
|
||||
// check whether the address is a signer
|
||||
if !isTxSigner(sdk.AccAddress(addr), stdTx.GetSigners()) {
|
||||
return signedStdTx, fmt.Errorf("%s: %s", sdkerrors.ErrorInvalidSigner, name)
|
||||
addr := sdk.AccAddress(info.GetPubKey().Address())
|
||||
if !isTxSigner(addr, stdTx.GetTx().GetSigners()) {
|
||||
return fmt.Errorf("%s: %s", sdkerrors.ErrorInvalidSigner, name)
|
||||
}
|
||||
|
||||
if !offline {
|
||||
txBldr, err = populateAccountFromState(txBldr, clientCtx, sdk.AccAddress(addr))
|
||||
txFactory, err = populateAccountFromState(txFactory, clientCtx, addr)
|
||||
if err != nil {
|
||||
return signedStdTx, err
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return txBldr.SignStdTx(name, stdTx, appendSig)
|
||||
return tx.Sign(txFactory, name, stdTx)
|
||||
}
|
||||
|
||||
// SignStdTxWithSignerAddress attaches a signature to a StdTx and returns a copy of a it.
|
||||
// SignTxWithSignerAddress attaches a signature to a transaction.
|
||||
// Don't perform online validation or lookups if offline is true, else
|
||||
// populate account and sequence numbers from a foreign account.
|
||||
func SignStdTxWithSignerAddress(
|
||||
txBldr authtypes.TxBuilder, clientCtx client.Context,
|
||||
addr sdk.AccAddress, name string, stdTx authtypes.StdTx, offline bool,
|
||||
) (signedStdTx authtypes.StdTx, err error) {
|
||||
func SignTxWithSignerAddress(txFactory tx.Factory, clientCtx client.Context, addr sdk.AccAddress,
|
||||
name string, txBuilder client.TxBuilder, offline bool) (err error) {
|
||||
|
||||
// check whether the address is a signer
|
||||
if !isTxSigner(addr, stdTx.GetSigners()) {
|
||||
return signedStdTx, fmt.Errorf("%s: %s", sdkerrors.ErrorInvalidSigner, name)
|
||||
if !isTxSigner(addr, txBuilder.GetTx().GetSigners()) {
|
||||
return fmt.Errorf("%s: %s", sdkerrors.ErrorInvalidSigner, name)
|
||||
}
|
||||
|
||||
if !offline {
|
||||
txBldr, err = populateAccountFromState(txBldr, clientCtx, addr)
|
||||
txFactory, err = populateAccountFromState(txFactory, clientCtx, addr)
|
||||
if err != nil {
|
||||
return signedStdTx, err
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return txBldr.SignStdTx(name, stdTx, false)
|
||||
return tx.Sign(txFactory, name, txBuilder)
|
||||
}
|
||||
|
||||
// Read and decode a StdTx from the given filename. Can pass "-" to read from stdin.
|
||||
@@ -236,21 +138,21 @@ func ReadTxFromFile(ctx client.Context, filename string) (tx sdk.Tx, err error)
|
||||
}
|
||||
|
||||
// NewBatchScanner returns a new BatchScanner to read newline-delimited StdTx transactions from r.
|
||||
func NewBatchScanner(cdc codec.JSONMarshaler, r io.Reader) *BatchScanner {
|
||||
return &BatchScanner{Scanner: bufio.NewScanner(r), cdc: cdc}
|
||||
func NewBatchScanner(cfg client.TxConfig, r io.Reader) *BatchScanner {
|
||||
return &BatchScanner{Scanner: bufio.NewScanner(r), cfg: cfg}
|
||||
}
|
||||
|
||||
// BatchScanner provides a convenient interface for reading batch data such as a file
|
||||
// of newline-delimited JSON encoded StdTx.
|
||||
type BatchScanner struct {
|
||||
*bufio.Scanner
|
||||
stdTx authtypes.StdTx
|
||||
cdc codec.JSONMarshaler
|
||||
theTx sdk.Tx
|
||||
cfg client.TxConfig
|
||||
unmarshalErr error
|
||||
}
|
||||
|
||||
// StdTx returns the most recent StdTx unmarshalled by a call to Scan.
|
||||
func (bs BatchScanner) StdTx() authtypes.StdTx { return bs.stdTx }
|
||||
// Tx returns the most recent Tx unmarshalled by a call to Scan.
|
||||
func (bs BatchScanner) Tx() sdk.Tx { return bs.theTx }
|
||||
|
||||
// UnmarshalErr returns the first unmarshalling error that was encountered by the scanner.
|
||||
func (bs BatchScanner) UnmarshalErr() error { return bs.unmarshalErr }
|
||||
@@ -261,7 +163,9 @@ func (bs *BatchScanner) Scan() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
if err := bs.cdc.UnmarshalJSON(bs.Bytes(), &bs.stdTx); err != nil && bs.unmarshalErr == nil {
|
||||
tx, err := bs.cfg.TxJSONDecoder()(bs.Bytes())
|
||||
bs.theTx = tx
|
||||
if err != nil && bs.unmarshalErr == nil {
|
||||
bs.unmarshalErr = err
|
||||
return false
|
||||
}
|
||||
@@ -270,8 +174,8 @@ func (bs *BatchScanner) Scan() bool {
|
||||
}
|
||||
|
||||
func populateAccountFromState(
|
||||
txBldr authtypes.TxBuilder, clientCtx client.Context, addr sdk.AccAddress,
|
||||
) (authtypes.TxBuilder, error) {
|
||||
txBldr tx.Factory, clientCtx client.Context, addr sdk.AccAddress,
|
||||
) (tx.Factory, error) {
|
||||
|
||||
num, seq, err := clientCtx.AccountRetriever.GetAccountNumberSequence(clientCtx, addr)
|
||||
if err != nil {
|
||||
@@ -316,56 +220,6 @@ func parseQueryResponse(bz []byte) (sdk.SimulationResponse, error) {
|
||||
return simRes, nil
|
||||
}
|
||||
|
||||
// PrepareTxBuilder populates a TxBuilder in preparation for the build of a Tx.
|
||||
func PrepareTxBuilder(txBldr authtypes.TxBuilder, clientCtx client.Context) (authtypes.TxBuilder, error) {
|
||||
from := clientCtx.GetFromAddress()
|
||||
accGetter := clientCtx.AccountRetriever
|
||||
if err := accGetter.EnsureExists(clientCtx, from); err != nil {
|
||||
return txBldr, err
|
||||
}
|
||||
|
||||
txbldrAccNum, txbldrAccSeq := txBldr.AccountNumber(), txBldr.Sequence()
|
||||
// TODO: (ref #1903) Allow for user supplied account number without
|
||||
// automatically doing a manual lookup.
|
||||
if txbldrAccNum == 0 || txbldrAccSeq == 0 {
|
||||
num, seq, err := accGetter.GetAccountNumberSequence(clientCtx, from)
|
||||
if err != nil {
|
||||
return txBldr, err
|
||||
}
|
||||
|
||||
if txbldrAccNum == 0 {
|
||||
txBldr = txBldr.WithAccountNumber(num)
|
||||
}
|
||||
if txbldrAccSeq == 0 {
|
||||
txBldr = txBldr.WithSequence(seq)
|
||||
}
|
||||
}
|
||||
|
||||
return txBldr, nil
|
||||
}
|
||||
|
||||
func buildUnsignedStdTxOffline(txBldr authtypes.TxBuilder, clientCtx client.Context, msgs []sdk.Msg) (stdTx authtypes.StdTx, err error) {
|
||||
if txBldr.SimulateAndExecute() {
|
||||
if clientCtx.Offline {
|
||||
return stdTx, errors.New("cannot estimate gas in offline mode")
|
||||
}
|
||||
|
||||
txBldr, err = EnrichWithGas(txBldr, clientCtx, msgs)
|
||||
if err != nil {
|
||||
return stdTx, err
|
||||
}
|
||||
|
||||
_, _ = fmt.Fprintf(os.Stderr, "estimated gas = %v\n", txBldr.Gas())
|
||||
}
|
||||
|
||||
stdSignMsg, err := txBldr.BuildSignMsg(msgs)
|
||||
if err != nil {
|
||||
return stdTx, err
|
||||
}
|
||||
|
||||
return authtypes.NewStdTx(stdSignMsg.Msgs, stdSignMsg.Fee, nil, stdSignMsg.Memo), nil
|
||||
}
|
||||
|
||||
func isTxSigner(user sdk.AccAddress, signers []sdk.AccAddress) bool {
|
||||
for _, s := range signers {
|
||||
if bytes.Equal(user.Bytes(), s.Bytes()) {
|
||||
|
||||
+10
-47
@@ -6,6 +6,7 @@ import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/std"
|
||||
"github.com/cosmos/cosmos-sdk/testutil"
|
||||
"github.com/cosmos/cosmos-sdk/testutil/testdata"
|
||||
|
||||
@@ -149,8 +150,12 @@ func TestReadStdTxFromFile(t *testing.T) {
|
||||
|
||||
func TestBatchScanner_Scan(t *testing.T) {
|
||||
t.Parallel()
|
||||
cdc := codec.New()
|
||||
sdk.RegisterCodec(cdc)
|
||||
encodingConfig := simappparams.MakeEncodingConfig()
|
||||
std.RegisterCodec(encodingConfig.Amino)
|
||||
|
||||
txGen := encodingConfig.TxConfig
|
||||
clientCtx := client.Context{}
|
||||
clientCtx = clientCtx.WithTxConfig(txGen)
|
||||
|
||||
batch1 := `{"msg":[],"fee":{"amount":[{"denom":"atom","amount":"150"}],"gas":"50000"},"signatures":[],"memo":"foomemo"}
|
||||
{"msg":[],"fee":{"amount":[{"denom":"atom","amount":"150"}],"gas":"10000"},"signatures":[],"memo":"foomemo"}
|
||||
@@ -182,12 +187,12 @@ malformed
|
||||
for _, tt := range tests {
|
||||
tt := tt
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
scanner, i := NewBatchScanner(cdc, strings.NewReader(tt.batch)), 0
|
||||
scanner, i := NewBatchScanner(clientCtx.TxConfig, strings.NewReader(tt.batch)), 0
|
||||
for scanner.Scan() {
|
||||
_ = scanner.StdTx()
|
||||
_ = scanner.Tx()
|
||||
i++
|
||||
}
|
||||
|
||||
t.Log(scanner.theTx)
|
||||
require.Equal(t, tt.wantScannerError, scanner.Err() != nil)
|
||||
require.Equal(t, tt.wantUnmarshalError, scanner.UnmarshalErr() != nil)
|
||||
require.Equal(t, tt.numTxs, i)
|
||||
@@ -206,48 +211,6 @@ func compareEncoders(t *testing.T, expected sdk.TxEncoder, actual sdk.TxEncoder)
|
||||
require.Equal(t, defaultEncoderBytes, encoderBytes)
|
||||
}
|
||||
|
||||
func TestPrepareTxBuilder(t *testing.T) {
|
||||
cdc := makeCodec()
|
||||
|
||||
encodingConfig := simappparams.MakeEncodingConfig()
|
||||
sdk.RegisterCodec(encodingConfig.Amino)
|
||||
|
||||
fromAddr := sdk.AccAddress("test-addr0000000000")
|
||||
fromAddrStr := fromAddr.String()
|
||||
|
||||
var accNum uint64 = 10
|
||||
var accSeq uint64 = 17
|
||||
|
||||
txGen := encodingConfig.TxConfig
|
||||
clientCtx := client.Context{}
|
||||
clientCtx = clientCtx.
|
||||
WithTxConfig(txGen).
|
||||
WithJSONMarshaler(encodingConfig.Marshaler).
|
||||
WithAccountRetriever(client.TestAccountRetriever{Accounts: map[string]struct {
|
||||
Address sdk.AccAddress
|
||||
Num uint64
|
||||
Seq uint64
|
||||
}{
|
||||
fromAddrStr: {
|
||||
Address: fromAddr,
|
||||
Num: accNum,
|
||||
Seq: accSeq,
|
||||
},
|
||||
}}).
|
||||
WithFromAddress(fromAddr)
|
||||
|
||||
bldr := authtypes.NewTxBuilder(
|
||||
authtypes.DefaultTxEncoder(cdc), 0, 0,
|
||||
200000, 1.1, false, "test-chain",
|
||||
"test-builder", sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(1))),
|
||||
sdk.DecCoins{sdk.NewDecCoinFromDec(sdk.DefaultBondDenom, sdk.NewDecWithPrec(10000, sdk.Precision))})
|
||||
|
||||
bldr, err := PrepareTxBuilder(bldr, clientCtx)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, accNum, bldr.AccountNumber())
|
||||
require.Equal(t, accSeq, bldr.Sequence())
|
||||
}
|
||||
|
||||
func makeCodec() *codec.Codec {
|
||||
var cdc = codec.New()
|
||||
sdk.RegisterCodec(cdc)
|
||||
|
||||
Reference in New Issue
Block a user