github.com/cosmos/cosmos-sdk@v0.50.10/x/auth/ante/sigverify.go (about) 1 package ante 2 3 import ( 4 "bytes" 5 "encoding/base64" 6 "encoding/hex" 7 "fmt" 8 9 "google.golang.org/protobuf/types/known/anypb" 10 11 errorsmod "cosmossdk.io/errors" 12 storetypes "cosmossdk.io/store/types" 13 txsigning "cosmossdk.io/x/tx/signing" 14 15 codectypes "github.com/cosmos/cosmos-sdk/codec/types" 16 "github.com/cosmos/cosmos-sdk/crypto/keys/ed25519" 17 kmultisig "github.com/cosmos/cosmos-sdk/crypto/keys/multisig" 18 "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" 19 "github.com/cosmos/cosmos-sdk/crypto/keys/secp256r1" 20 cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" 21 "github.com/cosmos/cosmos-sdk/crypto/types/multisig" 22 sdk "github.com/cosmos/cosmos-sdk/types" 23 sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" 24 "github.com/cosmos/cosmos-sdk/types/tx/signing" 25 authsigning "github.com/cosmos/cosmos-sdk/x/auth/signing" 26 "github.com/cosmos/cosmos-sdk/x/auth/types" 27 ) 28 29 var ( 30 // simulation signature values used to estimate gas consumption 31 key = make([]byte, secp256k1.PubKeySize) 32 simSecp256k1Pubkey = &secp256k1.PubKey{Key: key} 33 simSecp256k1Sig [64]byte 34 ) 35 36 func init() { 37 // This decodes a valid hex string into a sepc256k1Pubkey for use in transaction simulation 38 bz, _ := hex.DecodeString("035AD6810A47F073553FF30D2FCC7E0D3B1C0B74B61A1AAA2582344037151E143A") 39 copy(key, bz) 40 simSecp256k1Pubkey.Key = key 41 } 42 43 // SignatureVerificationGasConsumer is the type of function that is used to both 44 // consume gas when verifying signatures and also to accept or reject different types of pubkeys 45 // This is where apps can define their own PubKey 46 type SignatureVerificationGasConsumer = func(meter storetypes.GasMeter, sig signing.SignatureV2, params types.Params) error 47 48 // SetPubKeyDecorator sets PubKeys in context for any signer which does not already have pubkey set 49 // PubKeys must be set in context for all signers before any other sigverify decorators run 50 // CONTRACT: Tx must implement SigVerifiableTx interface 51 type SetPubKeyDecorator struct { 52 ak AccountKeeper 53 } 54 55 func NewSetPubKeyDecorator(ak AccountKeeper) SetPubKeyDecorator { 56 return SetPubKeyDecorator{ 57 ak: ak, 58 } 59 } 60 61 func (spkd SetPubKeyDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (sdk.Context, error) { 62 sigTx, ok := tx.(authsigning.SigVerifiableTx) 63 if !ok { 64 return ctx, errorsmod.Wrap(sdkerrors.ErrTxDecode, "invalid tx type") 65 } 66 67 pubkeys, err := sigTx.GetPubKeys() 68 if err != nil { 69 return ctx, err 70 } 71 72 signers, err := sigTx.GetSigners() 73 if err != nil { 74 return sdk.Context{}, err 75 } 76 77 signerStrs := make([]string, len(signers)) 78 for i, pk := range pubkeys { 79 var err error 80 signerStrs[i], err = spkd.ak.AddressCodec().BytesToString(signers[i]) 81 if err != nil { 82 return sdk.Context{}, err 83 } 84 85 // PublicKey was omitted from slice since it has already been set in context 86 if pk == nil { 87 if !simulate { 88 continue 89 } 90 pk = simSecp256k1Pubkey 91 } 92 // Only make check if simulate=false 93 if !simulate && !bytes.Equal(pk.Address(), signers[i]) && ctx.IsSigverifyTx() { 94 return ctx, errorsmod.Wrapf(sdkerrors.ErrInvalidPubKey, 95 "pubKey does not match signer address %s with signer index: %d", signerStrs[i], i) 96 } 97 98 acc, err := GetSignerAcc(ctx, spkd.ak, signers[i]) 99 if err != nil { 100 return ctx, err 101 } 102 // account already has pubkey set,no need to reset 103 if acc.GetPubKey() != nil { 104 continue 105 } 106 err = acc.SetPubKey(pk) 107 if err != nil { 108 return ctx, errorsmod.Wrap(sdkerrors.ErrInvalidPubKey, err.Error()) 109 } 110 spkd.ak.SetAccount(ctx, acc) 111 } 112 113 // Also emit the following events, so that txs can be indexed by these 114 // indices: 115 // - signature (via `tx.signature='<sig_as_base64>'`), 116 // - concat(address,"/",sequence) (via `tx.acc_seq='cosmos1abc...def/42'`). 117 sigs, err := sigTx.GetSignaturesV2() 118 if err != nil { 119 return ctx, err 120 } 121 122 var events sdk.Events 123 for i, sig := range sigs { 124 events = append(events, sdk.NewEvent(sdk.EventTypeTx, 125 sdk.NewAttribute(sdk.AttributeKeyAccountSequence, fmt.Sprintf("%s/%d", signerStrs[i], sig.Sequence)), 126 )) 127 128 sigBzs, err := signatureDataToBz(sig.Data) 129 if err != nil { 130 return ctx, err 131 } 132 for _, sigBz := range sigBzs { 133 events = append(events, sdk.NewEvent(sdk.EventTypeTx, 134 sdk.NewAttribute(sdk.AttributeKeySignature, base64.StdEncoding.EncodeToString(sigBz)), 135 )) 136 } 137 } 138 139 ctx.EventManager().EmitEvents(events) 140 141 return next(ctx, tx, simulate) 142 } 143 144 // Consume parameter-defined amount of gas for each signature according to the passed-in SignatureVerificationGasConsumer function 145 // before calling the next AnteHandler 146 // CONTRACT: Pubkeys are set in context for all signers before this decorator runs 147 // CONTRACT: Tx must implement SigVerifiableTx interface 148 type SigGasConsumeDecorator struct { 149 ak AccountKeeper 150 sigGasConsumer SignatureVerificationGasConsumer 151 } 152 153 func NewSigGasConsumeDecorator(ak AccountKeeper, sigGasConsumer SignatureVerificationGasConsumer) SigGasConsumeDecorator { 154 if sigGasConsumer == nil { 155 sigGasConsumer = DefaultSigVerificationGasConsumer 156 } 157 158 return SigGasConsumeDecorator{ 159 ak: ak, 160 sigGasConsumer: sigGasConsumer, 161 } 162 } 163 164 func (sgcd SigGasConsumeDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) { 165 sigTx, ok := tx.(authsigning.SigVerifiableTx) 166 if !ok { 167 return ctx, errorsmod.Wrap(sdkerrors.ErrTxDecode, "invalid transaction type") 168 } 169 170 params := sgcd.ak.GetParams(ctx) 171 sigs, err := sigTx.GetSignaturesV2() 172 if err != nil { 173 return ctx, err 174 } 175 176 // stdSigs contains the sequence number, account number, and signatures. 177 // When simulating, this would just be a 0-length slice. 178 signers, err := sigTx.GetSigners() 179 if err != nil { 180 return ctx, err 181 } 182 183 for i, sig := range sigs { 184 signerAcc, err := GetSignerAcc(ctx, sgcd.ak, signers[i]) 185 if err != nil { 186 return ctx, err 187 } 188 189 pubKey := signerAcc.GetPubKey() 190 191 // In simulate mode the transaction comes with no signatures, thus if the 192 // account's pubkey is nil, both signature verification and gasKVStore.Set() 193 // shall consume the largest amount, i.e. it takes more gas to verify 194 // secp256k1 keys than ed25519 ones. 195 if simulate && pubKey == nil { 196 pubKey = simSecp256k1Pubkey 197 } 198 199 // make a SignatureV2 with PubKey filled in from above 200 sig = signing.SignatureV2{ 201 PubKey: pubKey, 202 Data: sig.Data, 203 Sequence: sig.Sequence, 204 } 205 206 err = sgcd.sigGasConsumer(ctx.GasMeter(), sig, params) 207 if err != nil { 208 return ctx, err 209 } 210 } 211 212 return next(ctx, tx, simulate) 213 } 214 215 // SigVerificationDecorator verifies all signatures for a tx and return an error if any are invalid. Note, 216 // the SigVerificationDecorator will not check signatures on ReCheck. 217 // 218 // CONTRACT: Pubkeys are set in context for all signers before this decorator runs 219 // CONTRACT: Tx must implement SigVerifiableTx interface 220 type SigVerificationDecorator struct { 221 ak AccountKeeper 222 signModeHandler *txsigning.HandlerMap 223 } 224 225 func NewSigVerificationDecorator(ak AccountKeeper, signModeHandler *txsigning.HandlerMap) SigVerificationDecorator { 226 return SigVerificationDecorator{ 227 ak: ak, 228 signModeHandler: signModeHandler, 229 } 230 } 231 232 // OnlyLegacyAminoSigners checks SignatureData to see if all 233 // signers are using SIGN_MODE_LEGACY_AMINO_JSON. If this is the case 234 // then the corresponding SignatureV2 struct will not have account sequence 235 // explicitly set, and we should skip the explicit verification of sig.Sequence 236 // in the SigVerificationDecorator's AnteHandler function. 237 func OnlyLegacyAminoSigners(sigData signing.SignatureData) bool { 238 switch v := sigData.(type) { 239 case *signing.SingleSignatureData: 240 return v.SignMode == signing.SignMode_SIGN_MODE_LEGACY_AMINO_JSON 241 case *signing.MultiSignatureData: 242 for _, s := range v.Signatures { 243 if !OnlyLegacyAminoSigners(s) { 244 return false 245 } 246 } 247 return true 248 default: 249 return false 250 } 251 } 252 253 func (svd SigVerificationDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) { 254 sigTx, ok := tx.(authsigning.Tx) 255 if !ok { 256 return ctx, errorsmod.Wrap(sdkerrors.ErrTxDecode, "invalid transaction type") 257 } 258 259 // stdSigs contains the sequence number, account number, and signatures. 260 // When simulating, this would just be a 0-length slice. 261 sigs, err := sigTx.GetSignaturesV2() 262 if err != nil { 263 return ctx, err 264 } 265 266 signers, err := sigTx.GetSigners() 267 if err != nil { 268 return ctx, err 269 } 270 271 // check that signer length and signature length are the same 272 if len(sigs) != len(signers) { 273 return ctx, errorsmod.Wrapf(sdkerrors.ErrUnauthorized, "invalid number of signer; expected: %d, got %d", len(signers), len(sigs)) 274 } 275 276 for i, sig := range sigs { 277 acc, err := GetSignerAcc(ctx, svd.ak, signers[i]) 278 if err != nil { 279 return ctx, err 280 } 281 282 // retrieve pubkey 283 pubKey := acc.GetPubKey() 284 if !simulate && pubKey == nil { 285 return ctx, errorsmod.Wrap(sdkerrors.ErrInvalidPubKey, "pubkey on account is not set") 286 } 287 288 // Check account sequence number. 289 if sig.Sequence != acc.GetSequence() { 290 return ctx, errorsmod.Wrapf( 291 sdkerrors.ErrWrongSequence, 292 "account sequence mismatch, expected %d, got %d", acc.GetSequence(), sig.Sequence, 293 ) 294 } 295 296 // retrieve signer data 297 genesis := ctx.BlockHeight() == 0 298 chainID := ctx.ChainID() 299 var accNum uint64 300 if !genesis { 301 accNum = acc.GetAccountNumber() 302 } 303 304 // no need to verify signatures on recheck tx 305 if !simulate && !ctx.IsReCheckTx() && ctx.IsSigverifyTx() { 306 anyPk, _ := codectypes.NewAnyWithValue(pubKey) 307 308 signerData := txsigning.SignerData{ 309 Address: acc.GetAddress().String(), 310 ChainID: chainID, 311 AccountNumber: accNum, 312 Sequence: acc.GetSequence(), 313 PubKey: &anypb.Any{ 314 TypeUrl: anyPk.TypeUrl, 315 Value: anyPk.Value, 316 }, 317 } 318 adaptableTx, ok := tx.(authsigning.V2AdaptableTx) 319 if !ok { 320 return ctx, fmt.Errorf("expected tx to implement V2AdaptableTx, got %T", tx) 321 } 322 txData := adaptableTx.GetSigningTxData() 323 err = authsigning.VerifySignature(ctx, pubKey, signerData, sig.Data, svd.signModeHandler, txData) 324 if err != nil { 325 var errMsg string 326 if OnlyLegacyAminoSigners(sig.Data) { 327 // If all signers are using SIGN_MODE_LEGACY_AMINO, we rely on VerifySignature to check account sequence number, 328 // and therefore communicate sequence number as a potential cause of error. 329 errMsg = fmt.Sprintf("signature verification failed; please verify account number (%d), sequence (%d) and chain-id (%s)", accNum, acc.GetSequence(), chainID) 330 } else { 331 errMsg = fmt.Sprintf("signature verification failed; please verify account number (%d) and chain-id (%s): (%s)", accNum, chainID, err.Error()) 332 } 333 return ctx, errorsmod.Wrap(sdkerrors.ErrUnauthorized, errMsg) 334 335 } 336 } 337 } 338 339 return next(ctx, tx, simulate) 340 } 341 342 // IncrementSequenceDecorator handles incrementing sequences of all signers. 343 // Use the IncrementSequenceDecorator decorator to prevent replay attacks. Note, 344 // there is need to execute IncrementSequenceDecorator on RecheckTx since 345 // BaseApp.Commit() will set the check state based on the latest header. 346 // 347 // NOTE: Since CheckTx and DeliverTx state are managed separately, subsequent and 348 // sequential txs orginating from the same account cannot be handled correctly in 349 // a reliable way unless sequence numbers are managed and tracked manually by a 350 // client. It is recommended to instead use multiple messages in a tx. 351 type IncrementSequenceDecorator struct { 352 ak AccountKeeper 353 } 354 355 func NewIncrementSequenceDecorator(ak AccountKeeper) IncrementSequenceDecorator { 356 return IncrementSequenceDecorator{ 357 ak: ak, 358 } 359 } 360 361 func (isd IncrementSequenceDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (sdk.Context, error) { 362 sigTx, ok := tx.(authsigning.SigVerifiableTx) 363 if !ok { 364 return ctx, errorsmod.Wrap(sdkerrors.ErrTxDecode, "invalid transaction type") 365 } 366 367 // increment sequence of all signers 368 signers, err := sigTx.GetSigners() 369 if err != nil { 370 return sdk.Context{}, err 371 } 372 373 for _, signer := range signers { 374 acc := isd.ak.GetAccount(ctx, signer) 375 if err := acc.SetSequence(acc.GetSequence() + 1); err != nil { 376 panic(err) 377 } 378 379 isd.ak.SetAccount(ctx, acc) 380 } 381 382 return next(ctx, tx, simulate) 383 } 384 385 // ValidateSigCountDecorator takes in Params and returns errors if there are too many signatures in the tx for the given params 386 // otherwise it calls next AnteHandler 387 // Use this decorator to set parameterized limit on number of signatures in tx 388 // CONTRACT: Tx must implement SigVerifiableTx interface 389 type ValidateSigCountDecorator struct { 390 ak AccountKeeper 391 } 392 393 func NewValidateSigCountDecorator(ak AccountKeeper) ValidateSigCountDecorator { 394 return ValidateSigCountDecorator{ 395 ak: ak, 396 } 397 } 398 399 func (vscd ValidateSigCountDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (sdk.Context, error) { 400 sigTx, ok := tx.(authsigning.SigVerifiableTx) 401 if !ok { 402 return ctx, errorsmod.Wrap(sdkerrors.ErrTxDecode, "Tx must be a sigTx") 403 } 404 405 params := vscd.ak.GetParams(ctx) 406 pubKeys, err := sigTx.GetPubKeys() 407 if err != nil { 408 return ctx, err 409 } 410 411 sigCount := 0 412 for _, pk := range pubKeys { 413 sigCount += CountSubKeys(pk) 414 if uint64(sigCount) > params.TxSigLimit { 415 return ctx, errorsmod.Wrapf(sdkerrors.ErrTooManySignatures, 416 "signatures: %d, limit: %d", sigCount, params.TxSigLimit) 417 } 418 } 419 420 return next(ctx, tx, simulate) 421 } 422 423 // DefaultSigVerificationGasConsumer is the default implementation of SignatureVerificationGasConsumer. It consumes gas 424 // for signature verification based upon the public key type. The cost is fetched from the given params and is matched 425 // by the concrete type. 426 func DefaultSigVerificationGasConsumer( 427 meter storetypes.GasMeter, sig signing.SignatureV2, params types.Params, 428 ) error { 429 pubkey := sig.PubKey 430 switch pubkey := pubkey.(type) { 431 case *ed25519.PubKey: 432 meter.ConsumeGas(params.SigVerifyCostED25519, "ante verify: ed25519") 433 return errorsmod.Wrap(sdkerrors.ErrInvalidPubKey, "ED25519 public keys are unsupported") 434 435 case *secp256k1.PubKey: 436 meter.ConsumeGas(params.SigVerifyCostSecp256k1, "ante verify: secp256k1") 437 return nil 438 439 case *secp256r1.PubKey: 440 meter.ConsumeGas(params.SigVerifyCostSecp256r1(), "ante verify: secp256r1") 441 return nil 442 443 case multisig.PubKey: 444 multisignature, ok := sig.Data.(*signing.MultiSignatureData) 445 if !ok { 446 return fmt.Errorf("expected %T, got, %T", &signing.MultiSignatureData{}, sig.Data) 447 } 448 err := ConsumeMultisignatureVerificationGas(meter, multisignature, pubkey, params, sig.Sequence) 449 if err != nil { 450 return err 451 } 452 return nil 453 454 default: 455 return errorsmod.Wrapf(sdkerrors.ErrInvalidPubKey, "unrecognized public key type: %T", pubkey) 456 } 457 } 458 459 // ConsumeMultisignatureVerificationGas consumes gas from a GasMeter for verifying a multisig pubkey signature 460 func ConsumeMultisignatureVerificationGas( 461 meter storetypes.GasMeter, sig *signing.MultiSignatureData, pubkey multisig.PubKey, 462 params types.Params, accSeq uint64, 463 ) error { 464 size := sig.BitArray.Count() 465 sigIndex := 0 466 467 for i := 0; i < size; i++ { 468 if !sig.BitArray.GetIndex(i) { 469 continue 470 } 471 sigV2 := signing.SignatureV2{ 472 PubKey: pubkey.GetPubKeys()[i], 473 Data: sig.Signatures[sigIndex], 474 Sequence: accSeq, 475 } 476 err := DefaultSigVerificationGasConsumer(meter, sigV2, params) 477 if err != nil { 478 return err 479 } 480 sigIndex++ 481 } 482 483 return nil 484 } 485 486 // GetSignerAcc returns an account for a given address that is expected to sign 487 // a transaction. 488 func GetSignerAcc(ctx sdk.Context, ak AccountKeeper, addr sdk.AccAddress) (sdk.AccountI, error) { 489 if acc := ak.GetAccount(ctx, addr); acc != nil { 490 return acc, nil 491 } 492 493 return nil, errorsmod.Wrapf(sdkerrors.ErrUnknownAddress, "account %s does not exist", addr) 494 } 495 496 // CountSubKeys counts the total number of keys for a multi-sig public key. 497 // A non-multisig, i.e. a regular signature, it naturally a count of 1. If it is a multisig, 498 // then it recursively calls it on its pubkeys. 499 func CountSubKeys(pub cryptotypes.PubKey) int { 500 if pub == nil { 501 return 0 502 } 503 v, ok := pub.(*kmultisig.LegacyAminoPubKey) 504 if !ok { 505 return 1 506 } 507 508 numKeys := 0 509 for _, subkey := range v.GetPubKeys() { 510 numKeys += CountSubKeys(subkey) 511 } 512 513 return numKeys 514 } 515 516 // signatureDataToBz converts a SignatureData into raw bytes signature. 517 // For SingleSignatureData, it returns the signature raw bytes. 518 // For MultiSignatureData, it returns an array of all individual signatures, 519 // as well as the aggregated signature. 520 func signatureDataToBz(data signing.SignatureData) ([][]byte, error) { 521 if data == nil { 522 return nil, fmt.Errorf("got empty SignatureData") 523 } 524 525 switch data := data.(type) { 526 case *signing.SingleSignatureData: 527 return [][]byte{data.Signature}, nil 528 case *signing.MultiSignatureData: 529 sigs := [][]byte{} 530 var err error 531 532 for _, d := range data.Signatures { 533 nestedSigs, err := signatureDataToBz(d) 534 if err != nil { 535 return nil, err 536 } 537 sigs = append(sigs, nestedSigs...) 538 } 539 540 multiSignature := cryptotypes.MultiSignature{ 541 Signatures: sigs, 542 } 543 aggregatedSig, err := multiSignature.Marshal() 544 if err != nil { 545 return nil, err 546 } 547 sigs = append(sigs, aggregatedSig) 548 549 return sigs, nil 550 default: 551 return nil, sdkerrors.ErrInvalidType.Wrapf("unexpected signature data type %T", data) 552 } 553 }