2019-06-05 16:26:17 -07:00
|
|
|
package types
|
2018-03-17 13:54:21 -07:00
|
|
|
|
|
|
|
import (
|
2018-07-06 16:26:22 -07:00
|
|
|
"fmt"
|
2018-03-17 13:54:21 -07:00
|
|
|
"testing"
|
|
|
|
|
2018-06-29 18:10:15 -07:00
|
|
|
"github.com/stretchr/testify/require"
|
2018-11-21 02:16:56 -08:00
|
|
|
abci "github.com/tendermint/tendermint/abci/types"
|
|
|
|
"github.com/tendermint/tendermint/crypto"
|
2018-07-25 13:43:37 -07:00
|
|
|
"github.com/tendermint/tendermint/crypto/ed25519"
|
2018-11-21 02:16:56 -08:00
|
|
|
"github.com/tendermint/tendermint/libs/log"
|
2019-07-05 16:25:56 -07:00
|
|
|
yaml "gopkg.in/yaml.v2"
|
2018-12-10 06:27:25 -08:00
|
|
|
|
2018-12-20 11:09:43 -08:00
|
|
|
"github.com/cosmos/cosmos-sdk/codec"
|
2020-08-07 16:32:22 -07:00
|
|
|
"github.com/cosmos/cosmos-sdk/crypto/types"
|
|
|
|
"github.com/cosmos/cosmos-sdk/crypto/types/multisig"
|
|
|
|
"github.com/cosmos/cosmos-sdk/testutil/testdata"
|
2018-12-10 06:27:25 -08:00
|
|
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
2019-12-27 09:57:54 -08:00
|
|
|
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
2020-08-07 16:32:22 -07:00
|
|
|
"github.com/cosmos/cosmos-sdk/types/tx/signing"
|
2018-09-26 06:39:05 -07:00
|
|
|
)
|
2018-05-23 22:09:01 -07:00
|
|
|
|
2018-09-26 06:39:05 -07:00
|
|
|
var (
|
|
|
|
priv = ed25519.GenPrivKey()
|
|
|
|
addr = sdk.AccAddress(priv.PubKey().Address())
|
2018-03-17 13:54:21 -07:00
|
|
|
)
|
|
|
|
|
2020-07-20 05:30:12 -07:00
|
|
|
// Deprecated, use fee amount and gas limit separately on TxBuilder.
|
|
|
|
func NewTestStdFee() StdFee {
|
|
|
|
return NewStdFee(100000,
|
|
|
|
sdk.NewCoins(sdk.NewInt64Coin("atom", 150)),
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Deprecated, use TxBuilder.
|
2020-08-07 16:32:22 -07:00
|
|
|
func NewTestTx(ctx sdk.Context, msgs []sdk.Msg, privs []crypto.PrivKey, accNums []uint64, seqs []uint64, timeout uint64, fee StdFee) sdk.Tx {
|
2020-07-20 05:30:12 -07:00
|
|
|
sigs := make([]StdSignature, len(privs))
|
|
|
|
for i, priv := range privs {
|
2020-08-07 16:32:22 -07:00
|
|
|
signBytes := StdSignBytes(ctx.ChainID(), accNums[i], seqs[i], timeout, fee, msgs, "")
|
2020-07-20 05:30:12 -07:00
|
|
|
|
|
|
|
sig, err := priv.Sign(signBytes)
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
|
2020-07-30 02:29:43 -07:00
|
|
|
sigs[i] = StdSignature{PubKey: priv.PubKey(), Signature: sig}
|
2020-07-20 05:30:12 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
tx := NewStdTx(msgs, fee, sigs, "")
|
|
|
|
return tx
|
|
|
|
}
|
|
|
|
|
2018-03-17 13:54:21 -07:00
|
|
|
func TestStdTx(t *testing.T) {
|
2020-07-06 10:03:45 -07:00
|
|
|
msgs := []sdk.Msg{testdata.NewTestMsg(addr)}
|
2019-06-05 16:26:17 -07:00
|
|
|
fee := NewTestStdFee()
|
2019-06-08 03:04:52 -07:00
|
|
|
sigs := []StdSignature{}
|
2018-03-17 13:54:21 -07:00
|
|
|
|
2018-06-21 15:05:25 -07:00
|
|
|
tx := NewStdTx(msgs, fee, sigs, "")
|
2018-06-29 18:10:15 -07:00
|
|
|
require.Equal(t, msgs, tx.GetMsgs())
|
2019-10-10 05:46:09 -07:00
|
|
|
require.Equal(t, sigs, tx.Signatures)
|
2018-03-17 13:54:21 -07:00
|
|
|
|
2018-09-26 11:34:01 -07:00
|
|
|
feePayer := tx.GetSigners()[0]
|
2018-06-29 18:10:15 -07:00
|
|
|
require.Equal(t, addr, feePayer)
|
2018-03-17 13:54:21 -07:00
|
|
|
}
|
2018-07-06 16:26:22 -07:00
|
|
|
|
|
|
|
func TestStdSignBytes(t *testing.T) {
|
2018-09-26 06:39:05 -07:00
|
|
|
type args struct {
|
2020-08-07 16:32:22 -07:00
|
|
|
chainID string
|
|
|
|
accnum uint64
|
|
|
|
sequence uint64
|
|
|
|
timeoutHeight uint64
|
|
|
|
fee StdFee
|
|
|
|
msgs []sdk.Msg
|
|
|
|
memo string
|
2018-09-26 06:39:05 -07:00
|
|
|
}
|
2019-06-05 16:26:17 -07:00
|
|
|
defaultFee := NewTestStdFee()
|
2018-09-26 06:39:05 -07:00
|
|
|
tests := []struct {
|
|
|
|
args args
|
|
|
|
want string
|
|
|
|
}{
|
|
|
|
{
|
2020-08-07 16:32:22 -07:00
|
|
|
args{"1234", 3, 6, 10, defaultFee, []sdk.Msg{testdata.NewTestMsg(addr)}, "memo"},
|
|
|
|
fmt.Sprintf("{\"account_number\":\"3\",\"chain_id\":\"1234\",\"fee\":{\"amount\":[{\"amount\":\"150\",\"denom\":\"atom\"}],\"gas\":\"100000\"},\"memo\":\"memo\",\"msgs\":[[\"%s\"]],\"sequence\":\"6\",\"timeout_height\":\"10\"}", addr),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
args{"1234", 3, 6, 0, defaultFee, []sdk.Msg{testdata.NewTestMsg(addr)}, "memo"},
|
2019-10-10 05:46:09 -07:00
|
|
|
fmt.Sprintf("{\"account_number\":\"3\",\"chain_id\":\"1234\",\"fee\":{\"amount\":[{\"amount\":\"150\",\"denom\":\"atom\"}],\"gas\":\"100000\"},\"memo\":\"memo\",\"msgs\":[[\"%s\"]],\"sequence\":\"6\"}", addr),
|
2018-09-26 06:39:05 -07:00
|
|
|
},
|
|
|
|
}
|
|
|
|
for i, tc := range tests {
|
2020-08-07 16:32:22 -07:00
|
|
|
got := string(StdSignBytes(tc.args.chainID, tc.args.accnum, tc.args.sequence, tc.args.timeoutHeight, tc.args.fee, tc.args.msgs, tc.args.memo))
|
2018-09-26 06:39:05 -07:00
|
|
|
require.Equal(t, tc.want, got, "Got unexpected result on test case i: %d", i)
|
2018-07-06 16:26:22 -07:00
|
|
|
}
|
|
|
|
}
|
2018-11-21 02:16:56 -08:00
|
|
|
|
|
|
|
func TestTxValidateBasic(t *testing.T) {
|
|
|
|
ctx := sdk.NewContext(nil, abci.Header{ChainID: "mychainid"}, false, log.NewNopLogger())
|
|
|
|
|
|
|
|
// keys and addresses
|
2020-07-20 05:30:12 -07:00
|
|
|
priv1, _, addr1 := testdata.KeyTestPubAddr()
|
|
|
|
priv2, _, addr2 := testdata.KeyTestPubAddr()
|
2018-11-21 02:16:56 -08:00
|
|
|
|
|
|
|
// msg and signatures
|
2020-07-06 10:03:45 -07:00
|
|
|
msg1 := testdata.NewTestMsg(addr1, addr2)
|
2019-06-05 16:26:17 -07:00
|
|
|
fee := NewTestStdFee()
|
2018-11-21 02:16:56 -08:00
|
|
|
|
|
|
|
msgs := []sdk.Msg{msg1}
|
|
|
|
|
|
|
|
// require to fail validation upon invalid fee
|
2019-06-05 16:26:17 -07:00
|
|
|
badFee := NewTestStdFee()
|
2018-11-21 02:16:56 -08:00
|
|
|
badFee.Amount[0].Amount = sdk.NewInt(-5)
|
2020-08-07 16:32:22 -07:00
|
|
|
tx := NewTestTx(ctx, nil, nil, nil, nil, 0, badFee)
|
2018-11-21 02:16:56 -08:00
|
|
|
|
|
|
|
err := tx.ValidateBasic()
|
|
|
|
require.Error(t, err)
|
2019-12-27 09:57:54 -08:00
|
|
|
_, code, _ := sdkerrors.ABCIInfo(err, false)
|
|
|
|
require.Equal(t, sdkerrors.ErrInsufficientFee.ABCICode(), code)
|
2018-11-21 02:16:56 -08:00
|
|
|
|
|
|
|
// require to fail validation when no signatures exist
|
2018-11-26 03:29:21 -08:00
|
|
|
privs, accNums, seqs := []crypto.PrivKey{}, []uint64{}, []uint64{}
|
2020-08-07 16:32:22 -07:00
|
|
|
tx = NewTestTx(ctx, msgs, privs, accNums, seqs, 0, fee)
|
2018-11-21 02:16:56 -08:00
|
|
|
|
|
|
|
err = tx.ValidateBasic()
|
|
|
|
require.Error(t, err)
|
2019-12-27 09:57:54 -08:00
|
|
|
_, code, _ = sdkerrors.ABCIInfo(err, false)
|
|
|
|
require.Equal(t, sdkerrors.ErrNoSignatures.ABCICode(), code)
|
2018-11-21 02:16:56 -08:00
|
|
|
|
|
|
|
// require to fail validation when signatures do not match expected signers
|
2018-11-26 03:29:21 -08:00
|
|
|
privs, accNums, seqs = []crypto.PrivKey{priv1}, []uint64{0, 1}, []uint64{0, 0}
|
2020-08-07 16:32:22 -07:00
|
|
|
tx = NewTestTx(ctx, msgs, privs, accNums, seqs, 0, fee)
|
2018-11-21 02:16:56 -08:00
|
|
|
|
|
|
|
err = tx.ValidateBasic()
|
|
|
|
require.Error(t, err)
|
2019-12-27 09:57:54 -08:00
|
|
|
_, code, _ = sdkerrors.ABCIInfo(err, false)
|
|
|
|
require.Equal(t, sdkerrors.ErrUnauthorized.ABCICode(), code)
|
2018-11-21 02:16:56 -08:00
|
|
|
|
2018-12-10 11:24:57 -08:00
|
|
|
// require to fail with invalid gas supplied
|
2019-06-05 16:26:17 -07:00
|
|
|
badFee = NewTestStdFee()
|
2018-12-10 11:24:57 -08:00
|
|
|
badFee.Gas = 9223372036854775808
|
2020-08-07 16:32:22 -07:00
|
|
|
tx = NewTestTx(ctx, nil, nil, nil, nil, 0, badFee)
|
2018-12-10 11:24:57 -08:00
|
|
|
|
|
|
|
err = tx.ValidateBasic()
|
|
|
|
require.Error(t, err)
|
2019-12-27 09:57:54 -08:00
|
|
|
_, code, _ = sdkerrors.ABCIInfo(err, false)
|
|
|
|
require.Equal(t, sdkerrors.ErrInvalidRequest.ABCICode(), code)
|
2018-12-10 11:24:57 -08:00
|
|
|
|
2018-11-21 02:16:56 -08:00
|
|
|
// require to pass when above criteria are matched
|
2018-11-26 03:29:21 -08:00
|
|
|
privs, accNums, seqs = []crypto.PrivKey{priv1, priv2}, []uint64{0, 1}, []uint64{0, 0}
|
2020-08-07 16:32:22 -07:00
|
|
|
tx = NewTestTx(ctx, msgs, privs, accNums, seqs, 0, fee)
|
2018-11-21 02:16:56 -08:00
|
|
|
|
|
|
|
err = tx.ValidateBasic()
|
|
|
|
require.NoError(t, err)
|
|
|
|
}
|
2018-12-12 13:29:42 -08:00
|
|
|
|
|
|
|
func TestDefaultTxEncoder(t *testing.T) {
|
|
|
|
cdc := codec.New()
|
|
|
|
sdk.RegisterCodec(cdc)
|
|
|
|
RegisterCodec(cdc)
|
2020-07-06 10:03:45 -07:00
|
|
|
cdc.RegisterConcrete(testdata.TestMsg{}, "cosmos-sdk/Test", nil)
|
2018-12-12 13:29:42 -08:00
|
|
|
encoder := DefaultTxEncoder(cdc)
|
|
|
|
|
2020-07-06 10:03:45 -07:00
|
|
|
msgs := []sdk.Msg{testdata.NewTestMsg(addr)}
|
2019-06-05 16:26:17 -07:00
|
|
|
fee := NewTestStdFee()
|
2019-06-08 03:04:52 -07:00
|
|
|
sigs := []StdSignature{}
|
2018-12-12 13:29:42 -08:00
|
|
|
|
|
|
|
tx := NewStdTx(msgs, fee, sigs, "")
|
|
|
|
|
2020-03-13 12:58:43 -07:00
|
|
|
cdcBytes, err := cdc.MarshalBinaryBare(tx)
|
2018-12-12 13:29:42 -08:00
|
|
|
|
|
|
|
require.NoError(t, err)
|
|
|
|
encoderBytes, err := encoder(tx)
|
|
|
|
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.Equal(t, cdcBytes, encoderBytes)
|
|
|
|
}
|
2019-07-05 16:25:56 -07:00
|
|
|
|
|
|
|
func TestStdSignatureMarshalYAML(t *testing.T) {
|
2020-07-20 05:30:12 -07:00
|
|
|
_, pubKey, _ := testdata.KeyTestPubAddr()
|
2019-07-05 16:25:56 -07:00
|
|
|
|
|
|
|
testCases := []struct {
|
|
|
|
sig StdSignature
|
|
|
|
output string
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
StdSignature{},
|
|
|
|
"|\n pubkey: \"\"\n signature: \"\"\n",
|
|
|
|
},
|
|
|
|
{
|
2020-07-30 02:29:43 -07:00
|
|
|
StdSignature{PubKey: pubKey, Signature: []byte("dummySig")},
|
2020-03-12 10:52:55 -07:00
|
|
|
fmt.Sprintf("|\n pubkey: %s\n signature: 64756D6D79536967\n", sdk.MustBech32ifyPubKey(sdk.Bech32PubKeyTypeAccPub, pubKey)),
|
2019-07-05 16:25:56 -07:00
|
|
|
},
|
|
|
|
{
|
2020-07-30 02:29:43 -07:00
|
|
|
StdSignature{PubKey: pubKey, Signature: nil},
|
2020-01-09 06:04:28 -08:00
|
|
|
fmt.Sprintf("|\n pubkey: %s\n signature: \"\"\n", sdk.MustBech32ifyPubKey(sdk.Bech32PubKeyTypeAccPub, pubKey)),
|
2019-07-05 16:25:56 -07:00
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
for i, tc := range testCases {
|
|
|
|
bz, err := yaml.Marshal(tc.sig)
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.Equal(t, tc.output, string(bz), "test case #%d", i)
|
|
|
|
}
|
|
|
|
}
|
2020-06-12 11:13:20 -07:00
|
|
|
|
|
|
|
func TestSignatureV2Conversions(t *testing.T) {
|
2020-07-20 05:30:12 -07:00
|
|
|
_, pubKey, _ := testdata.KeyTestPubAddr()
|
2020-06-12 11:13:20 -07:00
|
|
|
cdc := codec.New()
|
|
|
|
sdk.RegisterCodec(cdc)
|
|
|
|
RegisterCodec(cdc)
|
|
|
|
dummy := []byte("dummySig")
|
2020-07-30 02:29:43 -07:00
|
|
|
sig := StdSignature{PubKey: pubKey, Signature: dummy}
|
2020-06-12 11:13:20 -07:00
|
|
|
|
|
|
|
sigV2, err := StdSignatureToSignatureV2(cdc, sig)
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.Equal(t, pubKey, sigV2.PubKey)
|
|
|
|
require.Equal(t, &signing.SingleSignatureData{
|
|
|
|
SignMode: signing.SignMode_SIGN_MODE_LEGACY_AMINO_JSON,
|
|
|
|
Signature: dummy,
|
|
|
|
}, sigV2.Data)
|
|
|
|
|
|
|
|
sigBz, err := SignatureDataToAminoSignature(cdc, sigV2.Data)
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.Equal(t, dummy, sigBz)
|
|
|
|
|
|
|
|
// multisigs
|
2020-07-20 05:30:12 -07:00
|
|
|
_, pubKey2, _ := testdata.KeyTestPubAddr()
|
2020-06-12 11:13:20 -07:00
|
|
|
multiPK := multisig.NewPubKeyMultisigThreshold(1, []crypto.PubKey{
|
|
|
|
pubKey, pubKey2,
|
|
|
|
})
|
|
|
|
dummy2 := []byte("dummySig2")
|
|
|
|
bitArray := types.NewCompactBitArray(2)
|
|
|
|
bitArray.SetIndex(0, true)
|
|
|
|
bitArray.SetIndex(1, true)
|
|
|
|
msigData := &signing.MultiSignatureData{
|
|
|
|
BitArray: bitArray,
|
|
|
|
Signatures: []signing.SignatureData{
|
|
|
|
&signing.SingleSignatureData{
|
|
|
|
SignMode: signing.SignMode_SIGN_MODE_LEGACY_AMINO_JSON,
|
|
|
|
Signature: dummy,
|
|
|
|
},
|
|
|
|
&signing.SingleSignatureData{
|
|
|
|
SignMode: signing.SignMode_SIGN_MODE_LEGACY_AMINO_JSON,
|
|
|
|
Signature: dummy2,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
msig, err := SignatureDataToAminoSignature(cdc, msigData)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
sigV2, err = StdSignatureToSignatureV2(cdc, StdSignature{
|
2020-07-30 02:29:43 -07:00
|
|
|
PubKey: multiPK,
|
2020-06-12 11:13:20 -07:00
|
|
|
Signature: msig,
|
|
|
|
})
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.Equal(t, multiPK, sigV2.PubKey)
|
|
|
|
require.Equal(t, msigData, sigV2.Data)
|
|
|
|
}
|
2020-06-29 13:48:41 -07:00
|
|
|
|
|
|
|
func TestGetSignaturesV2(t *testing.T) {
|
2020-07-20 05:30:12 -07:00
|
|
|
_, pubKey, _ := testdata.KeyTestPubAddr()
|
2020-06-29 13:48:41 -07:00
|
|
|
dummy := []byte("dummySig")
|
|
|
|
|
|
|
|
cdc := codec.New()
|
|
|
|
sdk.RegisterCodec(cdc)
|
|
|
|
RegisterCodec(cdc)
|
|
|
|
|
|
|
|
fee := NewStdFee(50000, sdk.Coins{sdk.NewInt64Coin("atom", 150)})
|
2020-07-30 02:29:43 -07:00
|
|
|
sig := StdSignature{PubKey: pubKey, Signature: dummy}
|
2020-07-06 10:03:45 -07:00
|
|
|
stdTx := NewStdTx([]sdk.Msg{testdata.NewTestMsg()}, fee, []StdSignature{sig}, "testsigs")
|
2020-06-29 13:48:41 -07:00
|
|
|
|
|
|
|
sigs, err := stdTx.GetSignaturesV2()
|
|
|
|
require.Nil(t, err)
|
|
|
|
require.Equal(t, len(sigs), 1)
|
|
|
|
|
|
|
|
require.Equal(t, sigs[0].PubKey.Bytes(), sig.GetPubKey().Bytes())
|
|
|
|
require.Equal(t, sigs[0].Data, &signing.SingleSignatureData{
|
|
|
|
SignMode: signing.SignMode_SIGN_MODE_LEGACY_AMINO_JSON,
|
|
|
|
Signature: sig.GetSignature(),
|
|
|
|
})
|
|
|
|
}
|