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 }