github.com/cosmos/cosmos-sdk@v0.50.10/x/auth/ante/sigverify_test.go (about)

     1  package ante_test
     2  
     3  import (
     4  	"fmt"
     5  	"testing"
     6  
     7  	"github.com/golang/mock/gomock"
     8  	"github.com/stretchr/testify/require"
     9  
    10  	storetypes "cosmossdk.io/store/types"
    11  
    12  	"github.com/cosmos/cosmos-sdk/codec"
    13  	"github.com/cosmos/cosmos-sdk/crypto/keys/ed25519"
    14  	kmultisig "github.com/cosmos/cosmos-sdk/crypto/keys/multisig"
    15  	"github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1"
    16  	"github.com/cosmos/cosmos-sdk/crypto/keys/secp256r1"
    17  	cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
    18  	"github.com/cosmos/cosmos-sdk/crypto/types/multisig"
    19  	"github.com/cosmos/cosmos-sdk/testutil/testdata"
    20  	sdk "github.com/cosmos/cosmos-sdk/types"
    21  	"github.com/cosmos/cosmos-sdk/types/tx/signing"
    22  	"github.com/cosmos/cosmos-sdk/x/auth/ante"
    23  	"github.com/cosmos/cosmos-sdk/x/auth/migrations/legacytx"
    24  	authsign "github.com/cosmos/cosmos-sdk/x/auth/signing"
    25  	authtx "github.com/cosmos/cosmos-sdk/x/auth/tx"
    26  	txmodule "github.com/cosmos/cosmos-sdk/x/auth/tx/config"
    27  	"github.com/cosmos/cosmos-sdk/x/auth/types"
    28  	banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
    29  )
    30  
    31  func TestSetPubKey(t *testing.T) {
    32  	suite := SetupTestSuite(t, true)
    33  	suite.txBuilder = suite.clientCtx.TxConfig.NewTxBuilder()
    34  
    35  	// keys and addresses
    36  	priv1, pub1, addr1 := testdata.KeyTestPubAddr()
    37  	priv2, pub2, addr2 := testdata.KeyTestPubAddr()
    38  	priv3, pub3, addr3 := testdata.KeyTestPubAddrSecp256R1(t)
    39  
    40  	addrs := []sdk.AccAddress{addr1, addr2, addr3}
    41  	pubs := []cryptotypes.PubKey{pub1, pub2, pub3}
    42  
    43  	msgs := make([]sdk.Msg, len(addrs))
    44  	// set accounts and create msg for each address
    45  	for i, addr := range addrs {
    46  		acc := suite.accountKeeper.NewAccountWithAddress(suite.ctx, addr)
    47  		require.NoError(t, acc.SetAccountNumber(uint64(i+1000)))
    48  		suite.accountKeeper.SetAccount(suite.ctx, acc)
    49  		msgs[i] = testdata.NewTestMsg(addr)
    50  	}
    51  	require.NoError(t, suite.txBuilder.SetMsgs(msgs...))
    52  	suite.txBuilder.SetFeeAmount(testdata.NewTestFeeAmount())
    53  	suite.txBuilder.SetGasLimit(testdata.NewTestGasLimit())
    54  
    55  	privs, accNums, accSeqs := []cryptotypes.PrivKey{priv1, priv2, priv3}, []uint64{0, 1, 2}, []uint64{0, 0, 0}
    56  	tx, err := suite.CreateTestTx(suite.ctx, privs, accNums, accSeqs, suite.ctx.ChainID(), signing.SignMode_SIGN_MODE_DIRECT)
    57  	require.NoError(t, err)
    58  
    59  	spkd := ante.NewSetPubKeyDecorator(suite.accountKeeper)
    60  	antehandler := sdk.ChainAnteDecorators(spkd)
    61  
    62  	ctx, err := antehandler(suite.ctx, tx, false)
    63  	require.NoError(t, err)
    64  
    65  	// Require that all accounts have pubkey set after Decorator runs
    66  	for i, addr := range addrs {
    67  		pk, err := suite.accountKeeper.GetPubKey(ctx, addr)
    68  		require.NoError(t, err, "Error on retrieving pubkey from account")
    69  		require.True(t, pubs[i].Equals(pk),
    70  			"Wrong Pubkey retrieved from AccountKeeper, idx=%d\nexpected=%s\n     got=%s", i, pubs[i], pk)
    71  	}
    72  }
    73  
    74  func TestConsumeSignatureVerificationGas(t *testing.T) {
    75  	suite := SetupTestSuite(t, true)
    76  	params := types.DefaultParams()
    77  	msg := []byte{1, 2, 3, 4}
    78  
    79  	p := types.DefaultParams()
    80  	skR1, _ := secp256r1.GenPrivKey()
    81  	pkSet1, sigSet1 := generatePubKeysAndSignatures(5, msg, false)
    82  	multisigKey1 := kmultisig.NewLegacyAminoPubKey(2, pkSet1)
    83  	multisignature1 := multisig.NewMultisig(len(pkSet1))
    84  	expectedCost1 := expectedGasCostByKeys(pkSet1)
    85  	for i := 0; i < len(pkSet1); i++ {
    86  		stdSig := legacytx.StdSignature{PubKey: pkSet1[i], Signature: sigSet1[i]} //nolint:staticcheck // SA1019: legacytx.StdSignature is deprecated
    87  		sigV2, err := legacytx.StdSignatureToSignatureV2(suite.clientCtx.LegacyAmino, stdSig)
    88  		require.NoError(t, err)
    89  		err = multisig.AddSignatureV2(multisignature1, sigV2, pkSet1)
    90  		require.NoError(t, err)
    91  	}
    92  
    93  	type args struct {
    94  		meter  storetypes.GasMeter
    95  		sig    signing.SignatureData
    96  		pubkey cryptotypes.PubKey
    97  		params types.Params
    98  	}
    99  	tests := []struct {
   100  		name        string
   101  		args        args
   102  		gasConsumed uint64
   103  		shouldErr   bool
   104  	}{
   105  		{"PubKeyEd25519", args{storetypes.NewInfiniteGasMeter(), nil, ed25519.GenPrivKey().PubKey(), params}, p.SigVerifyCostED25519, true},
   106  		{"PubKeySecp256k1", args{storetypes.NewInfiniteGasMeter(), nil, secp256k1.GenPrivKey().PubKey(), params}, p.SigVerifyCostSecp256k1, false},
   107  		{"PubKeySecp256r1", args{storetypes.NewInfiniteGasMeter(), nil, skR1.PubKey(), params}, p.SigVerifyCostSecp256r1(), false},
   108  		{"Multisig", args{storetypes.NewInfiniteGasMeter(), multisignature1, multisigKey1, params}, expectedCost1, false},
   109  		{"unknown key", args{storetypes.NewInfiniteGasMeter(), nil, nil, params}, 0, true},
   110  	}
   111  	for _, tt := range tests {
   112  		sigV2 := signing.SignatureV2{
   113  			PubKey:   tt.args.pubkey,
   114  			Data:     tt.args.sig,
   115  			Sequence: 0, // Arbitrary account sequence
   116  		}
   117  		err := ante.DefaultSigVerificationGasConsumer(tt.args.meter, sigV2, tt.args.params)
   118  
   119  		if tt.shouldErr {
   120  			require.NotNil(t, err)
   121  		} else {
   122  			require.Nil(t, err)
   123  			require.Equal(t, tt.gasConsumed, tt.args.meter.GasConsumed(), fmt.Sprintf("%d != %d", tt.gasConsumed, tt.args.meter.GasConsumed()))
   124  		}
   125  	}
   126  }
   127  
   128  func TestSigVerification(t *testing.T) {
   129  	suite := SetupTestSuite(t, true)
   130  	suite.txBankKeeper.EXPECT().DenomMetadata(gomock.Any(), gomock.Any()).Return(&banktypes.QueryDenomMetadataResponse{}, nil).AnyTimes()
   131  
   132  	enabledSignModes := []signing.SignMode{signing.SignMode_SIGN_MODE_DIRECT, signing.SignMode_SIGN_MODE_TEXTUAL, signing.SignMode_SIGN_MODE_LEGACY_AMINO_JSON}
   133  	// Since TEXTUAL is not enabled by default, we create a custom TxConfig
   134  	// here which includes it.
   135  	txConfigOpts := authtx.ConfigOptions{
   136  		TextualCoinMetadataQueryFn: txmodule.NewGRPCCoinMetadataQueryFn(suite.clientCtx),
   137  		EnabledSignModes:           enabledSignModes,
   138  	}
   139  	var err error
   140  	suite.clientCtx.TxConfig, err = authtx.NewTxConfigWithOptions(
   141  		codec.NewProtoCodec(suite.encCfg.InterfaceRegistry),
   142  		txConfigOpts,
   143  	)
   144  	require.NoError(t, err)
   145  	suite.txBuilder = suite.clientCtx.TxConfig.NewTxBuilder()
   146  
   147  	// make block height non-zero to ensure account numbers part of signBytes
   148  	suite.ctx = suite.ctx.WithBlockHeight(1)
   149  
   150  	// keys and addresses
   151  	priv1, _, addr1 := testdata.KeyTestPubAddr()
   152  	priv2, _, addr2 := testdata.KeyTestPubAddr()
   153  	priv3, _, addr3 := testdata.KeyTestPubAddr()
   154  
   155  	addrs := []sdk.AccAddress{addr1, addr2, addr3}
   156  
   157  	msgs := make([]sdk.Msg, len(addrs))
   158  	accs := make([]sdk.AccountI, len(addrs))
   159  	// set accounts and create msg for each address
   160  	for i, addr := range addrs {
   161  		acc := suite.accountKeeper.NewAccountWithAddress(suite.ctx, addr)
   162  		require.NoError(t, acc.SetAccountNumber(uint64(i)+1000))
   163  		suite.accountKeeper.SetAccount(suite.ctx, acc)
   164  		msgs[i] = testdata.NewTestMsg(addr)
   165  		accs[i] = acc
   166  	}
   167  
   168  	feeAmount := testdata.NewTestFeeAmount()
   169  	gasLimit := testdata.NewTestGasLimit()
   170  
   171  	spkd := ante.NewSetPubKeyDecorator(suite.accountKeeper)
   172  	txConfigOpts = authtx.ConfigOptions{
   173  		TextualCoinMetadataQueryFn: txmodule.NewBankKeeperCoinMetadataQueryFn(suite.txBankKeeper),
   174  		EnabledSignModes:           enabledSignModes,
   175  	}
   176  	anteTxConfig, err := authtx.NewTxConfigWithOptions(
   177  		codec.NewProtoCodec(suite.encCfg.InterfaceRegistry),
   178  		txConfigOpts,
   179  	)
   180  	require.NoError(t, err)
   181  	svd := ante.NewSigVerificationDecorator(suite.accountKeeper, anteTxConfig.SignModeHandler())
   182  	antehandler := sdk.ChainAnteDecorators(spkd, svd)
   183  	defaultSignMode, err := authsign.APISignModeToInternal(anteTxConfig.SignModeHandler().DefaultMode())
   184  	require.NoError(t, err)
   185  
   186  	type testCase struct {
   187  		name        string
   188  		privs       []cryptotypes.PrivKey
   189  		accNums     []uint64
   190  		accSeqs     []uint64
   191  		invalidSigs bool // used for testing sigverify on RecheckTx
   192  		recheck     bool
   193  		sigverify   bool
   194  		shouldErr   bool
   195  	}
   196  	validSigs := false
   197  	testCases := []testCase{
   198  		{"no signers", []cryptotypes.PrivKey{}, []uint64{}, []uint64{}, validSigs, false, true, true},
   199  		{"not enough signers", []cryptotypes.PrivKey{priv1, priv2}, []uint64{accs[0].GetAccountNumber(), accs[1].GetAccountNumber()}, []uint64{0, 0}, validSigs, false, true, true},
   200  		{"wrong order signers", []cryptotypes.PrivKey{priv3, priv2, priv1}, []uint64{accs[2].GetAccountNumber(), accs[1].GetAccountNumber(), accs[0].GetAccountNumber()}, []uint64{0, 0, 0}, validSigs, false, true, true},
   201  		{"wrong accnums", []cryptotypes.PrivKey{priv1, priv2, priv3}, []uint64{7, 8, 9}, []uint64{0, 0, 0}, validSigs, false, true, true},
   202  		{"wrong sequences", []cryptotypes.PrivKey{priv1, priv2, priv3}, []uint64{accs[0].GetAccountNumber(), accs[1].GetAccountNumber(), accs[2].GetAccountNumber()}, []uint64{3, 4, 5}, validSigs, false, true, true},
   203  		{"valid tx", []cryptotypes.PrivKey{priv1, priv2, priv3}, []uint64{accs[0].GetAccountNumber(), accs[1].GetAccountNumber(), accs[2].GetAccountNumber()}, []uint64{0, 0, 0}, validSigs, false, true, false},
   204  		{"sigverify tx with wrong order signers", []cryptotypes.PrivKey{priv3, priv2, priv1}, []uint64{accs[0].GetAccountNumber(), accs[1].GetAccountNumber(), accs[2].GetAccountNumber()}, []uint64{0, 0, 0}, validSigs, false, true, true},
   205  		{"skip sigverify tx with wrong order signers", []cryptotypes.PrivKey{priv3, priv2, priv1}, []uint64{accs[0].GetAccountNumber(), accs[1].GetAccountNumber(), accs[2].GetAccountNumber()}, []uint64{0, 0, 0}, validSigs, false, false, false},
   206  		{"no err on recheck", []cryptotypes.PrivKey{priv1, priv2, priv3}, []uint64{0, 0, 0}, []uint64{0, 0, 0}, !validSigs, true, true, false},
   207  	}
   208  
   209  	for i, tc := range testCases {
   210  		for _, signMode := range enabledSignModes {
   211  			t.Run(fmt.Sprintf("%s with %s", tc.name, signMode), func(t *testing.T) {
   212  				suite.ctx = suite.ctx.WithIsReCheckTx(tc.recheck).WithIsSigverifyTx(tc.sigverify)
   213  				suite.txBuilder = suite.clientCtx.TxConfig.NewTxBuilder() // Create new txBuilder for each test
   214  
   215  				require.NoError(t, suite.txBuilder.SetMsgs(msgs...))
   216  				suite.txBuilder.SetFeeAmount(feeAmount)
   217  				suite.txBuilder.SetGasLimit(gasLimit)
   218  
   219  				tx, err := suite.CreateTestTx(suite.ctx, tc.privs, tc.accNums, tc.accSeqs, suite.ctx.ChainID(), signMode)
   220  				require.NoError(t, err)
   221  				if tc.invalidSigs {
   222  					txSigs, _ := tx.GetSignaturesV2()
   223  					badSig, _ := tc.privs[0].Sign([]byte("unrelated message"))
   224  					txSigs[0] = signing.SignatureV2{
   225  						PubKey: tc.privs[0].PubKey(),
   226  						Data: &signing.SingleSignatureData{
   227  							SignMode:  defaultSignMode,
   228  							Signature: badSig,
   229  						},
   230  						Sequence: tc.accSeqs[0],
   231  					}
   232  					suite.txBuilder.SetSignatures(txSigs...)
   233  					tx = suite.txBuilder.GetTx()
   234  				}
   235  
   236  				txBytes, err := suite.clientCtx.TxConfig.TxEncoder()(tx)
   237  				require.NoError(t, err)
   238  				byteCtx := suite.ctx.WithTxBytes(txBytes)
   239  				_, err = antehandler(byteCtx, tx, false)
   240  				if tc.shouldErr {
   241  					require.NotNil(t, err, "TestCase %d: %s did not error as expected", i, tc.name)
   242  				} else {
   243  					require.Nil(t, err, "TestCase %d: %s errored unexpectedly. Err: %v", i, tc.name, err)
   244  				}
   245  			})
   246  		}
   247  	}
   248  }
   249  
   250  func TestSigIntegration(t *testing.T) {
   251  	// generate private keys
   252  	privs := []cryptotypes.PrivKey{
   253  		secp256k1.GenPrivKey(),
   254  		secp256k1.GenPrivKey(),
   255  		secp256k1.GenPrivKey(),
   256  	}
   257  
   258  	params := types.DefaultParams()
   259  	initialSigCost := params.SigVerifyCostSecp256k1
   260  	initialCost, err := runSigDecorators(t, params, false, privs...)
   261  	require.Nil(t, err)
   262  
   263  	params.SigVerifyCostSecp256k1 *= 2
   264  	doubleCost, err := runSigDecorators(t, params, false, privs...)
   265  	require.Nil(t, err)
   266  
   267  	require.Equal(t, initialSigCost*uint64(len(privs)), doubleCost-initialCost)
   268  }
   269  
   270  func runSigDecorators(t *testing.T, params types.Params, _ bool, privs ...cryptotypes.PrivKey) (storetypes.Gas, error) {
   271  	suite := SetupTestSuite(t, true)
   272  	suite.txBuilder = suite.clientCtx.TxConfig.NewTxBuilder()
   273  
   274  	// Make block-height non-zero to include accNum in SignBytes
   275  	suite.ctx = suite.ctx.WithBlockHeight(1)
   276  	err := suite.accountKeeper.Params.Set(suite.ctx, params)
   277  	require.NoError(t, err)
   278  
   279  	msgs := make([]sdk.Msg, len(privs))
   280  	accNums := make([]uint64, len(privs))
   281  	accSeqs := make([]uint64, len(privs))
   282  	// set accounts and create msg for each address
   283  	for i, priv := range privs {
   284  		addr := sdk.AccAddress(priv.PubKey().Address())
   285  		acc := suite.accountKeeper.NewAccountWithAddress(suite.ctx, addr)
   286  		require.NoError(t, acc.SetAccountNumber(uint64(i)+1000))
   287  		suite.accountKeeper.SetAccount(suite.ctx, acc)
   288  		msgs[i] = testdata.NewTestMsg(addr)
   289  		accNums[i] = acc.GetAccountNumber()
   290  		accSeqs[i] = uint64(0)
   291  	}
   292  	require.NoError(t, suite.txBuilder.SetMsgs(msgs...))
   293  
   294  	feeAmount := testdata.NewTestFeeAmount()
   295  	gasLimit := testdata.NewTestGasLimit()
   296  	suite.txBuilder.SetFeeAmount(feeAmount)
   297  	suite.txBuilder.SetGasLimit(gasLimit)
   298  
   299  	tx, err := suite.CreateTestTx(suite.ctx, privs, accNums, accSeqs, suite.ctx.ChainID(), signing.SignMode_SIGN_MODE_DIRECT)
   300  	require.NoError(t, err)
   301  
   302  	spkd := ante.NewSetPubKeyDecorator(suite.accountKeeper)
   303  	svgc := ante.NewSigGasConsumeDecorator(suite.accountKeeper, ante.DefaultSigVerificationGasConsumer)
   304  	svd := ante.NewSigVerificationDecorator(suite.accountKeeper, suite.clientCtx.TxConfig.SignModeHandler())
   305  	antehandler := sdk.ChainAnteDecorators(spkd, svgc, svd)
   306  
   307  	txBytes, err := suite.clientCtx.TxConfig.TxEncoder()(tx)
   308  	require.NoError(t, err)
   309  	suite.ctx = suite.ctx.WithTxBytes(txBytes)
   310  
   311  	// Determine gas consumption of antehandler with default params
   312  	before := suite.ctx.GasMeter().GasConsumed()
   313  	ctx, err := antehandler(suite.ctx, tx, false)
   314  	after := ctx.GasMeter().GasConsumed()
   315  
   316  	return after - before, err
   317  }
   318  
   319  func TestIncrementSequenceDecorator(t *testing.T) {
   320  	suite := SetupTestSuite(t, true)
   321  	suite.txBuilder = suite.clientCtx.TxConfig.NewTxBuilder()
   322  
   323  	priv, _, addr := testdata.KeyTestPubAddr()
   324  	acc := suite.accountKeeper.NewAccountWithAddress(suite.ctx, addr)
   325  	require.NoError(t, acc.SetAccountNumber(uint64(50)))
   326  	suite.accountKeeper.SetAccount(suite.ctx, acc)
   327  
   328  	msgs := []sdk.Msg{testdata.NewTestMsg(addr)}
   329  	require.NoError(t, suite.txBuilder.SetMsgs(msgs...))
   330  	privs := []cryptotypes.PrivKey{priv}
   331  	accNums := []uint64{suite.accountKeeper.GetAccount(suite.ctx, addr).GetAccountNumber()}
   332  	accSeqs := []uint64{suite.accountKeeper.GetAccount(suite.ctx, addr).GetSequence()}
   333  	feeAmount := testdata.NewTestFeeAmount()
   334  	gasLimit := testdata.NewTestGasLimit()
   335  	suite.txBuilder.SetFeeAmount(feeAmount)
   336  	suite.txBuilder.SetGasLimit(gasLimit)
   337  
   338  	tx, err := suite.CreateTestTx(suite.ctx, privs, accNums, accSeqs, suite.ctx.ChainID(), signing.SignMode_SIGN_MODE_DIRECT)
   339  	require.NoError(t, err)
   340  
   341  	isd := ante.NewIncrementSequenceDecorator(suite.accountKeeper)
   342  	antehandler := sdk.ChainAnteDecorators(isd)
   343  
   344  	testCases := []struct {
   345  		ctx         sdk.Context
   346  		simulate    bool
   347  		expectedSeq uint64
   348  	}{
   349  		{suite.ctx.WithIsReCheckTx(true), false, 1},
   350  		{suite.ctx.WithIsCheckTx(true).WithIsReCheckTx(false), false, 2},
   351  		{suite.ctx.WithIsReCheckTx(true), false, 3},
   352  		{suite.ctx.WithIsReCheckTx(true), false, 4},
   353  		{suite.ctx.WithIsReCheckTx(true), true, 5},
   354  	}
   355  
   356  	for i, tc := range testCases {
   357  		_, err := antehandler(tc.ctx, tx, tc.simulate)
   358  		require.NoError(t, err, "unexpected error; tc #%d, %v", i, tc)
   359  		require.Equal(t, tc.expectedSeq, suite.accountKeeper.GetAccount(suite.ctx, addr).GetSequence())
   360  	}
   361  }