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