github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/libs/cosmos-sdk/x/auth/ante/sigverify.go (about) 1 package ante 2 3 import ( 4 "bytes" 5 "encoding/hex" 6 "github.com/fibonacci-chain/fbc/app/crypto/ethsecp256k1" 7 "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/codec" 8 sdk "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types" 9 sdkerrors "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types/errors" 10 "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/x/auth/exported" 11 "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/x/auth/keeper" 12 "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/x/auth/types" 13 "github.com/fibonacci-chain/fbc/libs/tendermint/crypto" 14 "github.com/fibonacci-chain/fbc/libs/tendermint/crypto/ed25519" 15 "github.com/fibonacci-chain/fbc/libs/tendermint/crypto/multisig" 16 "github.com/fibonacci-chain/fbc/libs/tendermint/crypto/secp256k1" 17 types2 "github.com/fibonacci-chain/fbc/libs/tendermint/types" 18 ) 19 20 var ( 21 // simulation signature values used to estimate gas consumption 22 simSecp256k1Pubkey secp256k1.PubKeySecp256k1 23 simSecp256k1Sig [64]byte 24 25 _ SigVerifiableTx = (*types.StdTx)(nil) // assert StdTx implements SigVerifiableTx 26 _ SigVerifiableTx = (*types.IbcTx)(nil) 27 ) 28 29 func init() { 30 // This decodes a valid hex string into a sepc256k1Pubkey for use in transaction simulation 31 bz, _ := hex.DecodeString("035AD6810A47F073553FF30D2FCC7E0D3B1C0B74B61A1AAA2582344037151E143A") 32 copy(simSecp256k1Pubkey[:], bz) 33 } 34 35 // SignatureVerificationGasConsumer is the type of function that is used to both 36 // consume gas when verifying signatures and also to accept or reject different types of pubkeys 37 // This is where apps can define their own PubKey 38 type SignatureVerificationGasConsumer = func(meter sdk.GasMeter, sig []byte, pubkey crypto.PubKey, params types.Params) error 39 40 // SigVerifiableTx defines a Tx interface for all signature verification decorators 41 type SigVerifiableTx interface { 42 sdk.Tx 43 GetSignatures() [][]byte 44 GetSigners() []sdk.AccAddress 45 GetPubKeys() []crypto.PubKey // If signer already has pubkey in context, this list will have nil in its place 46 GetSignBytes(ctx sdk.Context, index int, acc exported.Account) []byte 47 //for ibc tx sign direct 48 VerifySequence(index int, acc exported.Account) error 49 } 50 51 // SetPubKeyDecorator sets PubKeys in context for any signer which does not already have pubkey set 52 // PubKeys must be set in context for all signers before any other sigverify decorators run 53 // CONTRACT: Tx must implement SigVerifiableTx interface 54 type SetPubKeyDecorator struct { 55 ak keeper.AccountKeeper 56 } 57 58 func NewSetPubKeyDecorator(ak keeper.AccountKeeper) SetPubKeyDecorator { 59 return SetPubKeyDecorator{ 60 ak: ak, 61 } 62 } 63 64 func (spkd SetPubKeyDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (sdk.Context, error) { 65 sigTx, ok := tx.(SigVerifiableTx) 66 if !ok { 67 return ctx, sdkerrors.Wrap(sdkerrors.ErrTxDecode, "invalid tx type") 68 } 69 70 pubkeys := sigTx.GetPubKeys() 71 signers := sigTx.GetSigners() 72 73 for i, pk := range pubkeys { 74 // PublicKey was omitted from slice since it has already been set in context 75 if pk == nil { 76 if !simulate { 77 continue 78 } 79 pk = simSecp256k1Pubkey 80 } 81 // Only make check if simulate=false 82 if !simulate && !bytes.Equal(pk.Address(), signers[i]) { 83 switch ppk := pk.(type) { 84 case *secp256k1.PubKeySecp256k1: 85 // In case that tx is created by CosmWasmJS with pubKey type of `secp256k1` 86 // and the signer address is derived by the pubKey of `ethsecp256k1` type. 87 // Let it pass after Earth height. 88 if types2.HigherThanEarth(ctx.BlockHeight()) && bytes.Equal(ethsecp256k1.PubKey(ppk[:]).Address(), signers[i]) { 89 break 90 } 91 return ctx, sdkerrors.Wrapf(sdkerrors.ErrInvalidPubKey, 92 "pubKey does not match signer address %s derived by eth pubKey, with signer index: %d", signers[i], i) 93 94 default: 95 //old logic 96 return ctx, sdkerrors.Wrapf(sdkerrors.ErrInvalidPubKey, 97 "pubKey does not match signer address %s with signer index: %d", signers[i], i) 98 } 99 } 100 101 acc, err := GetSignerAcc(ctx, spkd.ak, signers[i]) 102 if err != nil { 103 return ctx, err 104 } 105 // account already has pubkey set,no need to reset 106 if acc.GetPubKey() != nil { 107 continue 108 } 109 err = acc.SetPubKey(pk) 110 if err != nil { 111 return ctx, sdkerrors.Wrap(sdkerrors.ErrInvalidPubKey, err.Error()) 112 } 113 spkd.ak.SetAccount(ctx, acc) 114 } 115 116 return next(ctx, tx, simulate) 117 } 118 119 // Consume parameter-defined amount of gas for each signature according to the passed-in SignatureVerificationGasConsumer function 120 // before calling the next AnteHandler 121 // CONTRACT: Pubkeys are set in context for all signers before this decorator runs 122 // CONTRACT: Tx must implement SigVerifiableTx interface 123 type SigGasConsumeDecorator struct { 124 ak keeper.AccountKeeper 125 sigGasConsumer SignatureVerificationGasConsumer 126 } 127 128 func NewSigGasConsumeDecorator(ak keeper.AccountKeeper, sigGasConsumer SignatureVerificationGasConsumer) SigGasConsumeDecorator { 129 return SigGasConsumeDecorator{ 130 ak: ak, 131 sigGasConsumer: sigGasConsumer, 132 } 133 } 134 135 func (sgcd SigGasConsumeDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) { 136 sigTx, ok := tx.(SigVerifiableTx) 137 if !ok { 138 return ctx, sdkerrors.Wrap(sdkerrors.ErrTxDecode, "invalid transaction type") 139 } 140 141 params := sgcd.ak.GetParams(ctx) 142 sigs := sigTx.GetSignatures() 143 144 // stdSigs contains the sequence number, account number, and signatures. 145 // When simulating, this would just be a 0-length slice. 146 signerAddrs := sigTx.GetSigners() 147 148 for i, sig := range sigs { 149 signerAcc, err := GetSignerAcc(ctx, sgcd.ak, signerAddrs[i]) 150 if err != nil { 151 return ctx, err 152 } 153 pubKey := signerAcc.GetPubKey() 154 155 if simulate && pubKey == nil { 156 // In simulate mode the transaction comes with no signatures, thus if the 157 // account's pubkey is nil, both signature verification and gasKVStore.Set() 158 // shall consume the largest amount, i.e. it takes more gas to verify 159 // secp256k1 keys than ed25519 ones. 160 if pubKey == nil { 161 pubKey = simSecp256k1Pubkey 162 } 163 } 164 err = sgcd.sigGasConsumer(ctx.GasMeter(), sig, pubKey, params) 165 if err != nil { 166 return ctx, err 167 } 168 } 169 170 return next(ctx, tx, simulate) 171 } 172 173 // Verify all signatures for a tx and return an error if any are invalid. Note, 174 // the SigVerificationDecorator decorator will not get executed on ReCheck. 175 // 176 // CONTRACT: Pubkeys are set in context for all signers before this decorator runs 177 // CONTRACT: Tx must implement SigVerifiableTx interface 178 type SigVerificationDecorator struct { 179 ak keeper.AccountKeeper 180 } 181 182 func NewSigVerificationDecorator(ak keeper.AccountKeeper) SigVerificationDecorator { 183 return SigVerificationDecorator{ 184 ak: ak, 185 } 186 } 187 188 func (svd SigVerificationDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) { 189 // no need to verify signatures on recheck tx 190 if ctx.IsReCheckTx() { 191 return next(ctx, tx, simulate) 192 } 193 sigTx, ok := tx.(SigVerifiableTx) 194 if !ok { 195 return ctx, sdkerrors.Wrap(sdkerrors.ErrTxDecode, "invalid transaction type") 196 } 197 198 // stdSigs contains the sequence number, account number, and signatures. 199 // When simulating, this would just be a 0-length slice. 200 sigs := sigTx.GetSignatures() 201 202 // stdSigs contains the sequence number, account number, and signatures. 203 // When simulating, this would just be a 0-length slice. 204 signerAddrs := sigTx.GetSigners() 205 signerAccs := make([]exported.Account, len(signerAddrs)) 206 207 // check that signer length and signature length are the same 208 if len(sigs) != len(signerAddrs) { 209 return ctx, sdkerrors.Wrapf(sdkerrors.ErrUnauthorized, "invalid number of signer; expected: %d, got %d", len(signerAddrs), len(sigs)) 210 } 211 212 for i, sig := range sigs { 213 signerAccs[i], err = GetSignerAcc(ctx, svd.ak, signerAddrs[i]) 214 if err != nil { 215 return ctx, err 216 } 217 218 // retrieve signBytes of tx 219 signBytes := sigTx.GetSignBytes(ctx, i, signerAccs[i]) 220 err = sigTx.VerifySequence(i, signerAccs[i]) 221 if err != nil { 222 return ctx, sdkerrors.Wrap(sdkerrors.ErrInvalidSequence, "signature verification sequence failed:"+err.Error()) 223 } 224 225 // retrieve pubkey 226 pubKey := signerAccs[i].GetPubKey() 227 if !simulate && pubKey == nil { 228 return ctx, sdkerrors.Wrap(sdkerrors.ErrInvalidPubKey, "pubkey on account is not set") 229 } 230 231 // verify signature 232 if !simulate && (len(signBytes) == 0 || !pubKey.VerifyBytes(signBytes, sig)) { 233 return ctx, sdkerrors.Wrap(sdkerrors.ErrUnauthorized, "signature verification failed; verify correct account sequence and chain-id, sign msg:"+string(signBytes)) 234 } 235 } 236 237 return next(ctx, tx, simulate) 238 } 239 240 // IncrementSequenceDecorator handles incrementing sequences of all signers. 241 // Use the IncrementSequenceDecorator decorator to prevent replay attacks. Note, 242 // there is no need to execute IncrementSequenceDecorator on RecheckTX since 243 // CheckTx would already bump the sequence number. 244 // 245 // NOTE: Since CheckTx and DeliverTx state are managed separately, subsequent and 246 // sequential txs orginating from the same account cannot be handled correctly in 247 // a reliable way unless sequence numbers are managed and tracked manually by a 248 // client. It is recommended to instead use multiple messages in a tx. 249 type IncrementSequenceDecorator struct { 250 ak keeper.AccountKeeper 251 } 252 253 func NewIncrementSequenceDecorator(ak keeper.AccountKeeper) IncrementSequenceDecorator { 254 return IncrementSequenceDecorator{ 255 ak: ak, 256 } 257 } 258 259 func (isd IncrementSequenceDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (sdk.Context, error) { 260 sigTx, ok := tx.(SigVerifiableTx) 261 if !ok { 262 return ctx, sdkerrors.Wrap(sdkerrors.ErrTxDecode, "invalid transaction type") 263 } 264 265 // increment sequence of all signers 266 for index, addr := range sigTx.GetSigners() { 267 acc := isd.ak.GetAccount(ctx, addr) 268 if ctx.IsCheckTx() && index == 0 { // context with the nonce of fee payer 269 ctx.SetAccountNonce(acc.GetSequence()) 270 } 271 if err := acc.SetSequence(acc.GetSequence() + 1); err != nil { 272 panic(err) 273 } 274 275 isd.ak.SetAccount(ctx, acc) 276 } 277 278 return next(ctx, tx, simulate) 279 } 280 281 // ValidateSigCountDecorator takes in Params and returns errors if there are too many signatures in the tx for the given params 282 // otherwise it calls next AnteHandler 283 // Use this decorator to set parameterized limit on number of signatures in tx 284 // CONTRACT: Tx must implement SigVerifiableTx interface 285 type ValidateSigCountDecorator struct { 286 ak keeper.AccountKeeper 287 } 288 289 func NewValidateSigCountDecorator(ak keeper.AccountKeeper) ValidateSigCountDecorator { 290 return ValidateSigCountDecorator{ 291 ak: ak, 292 } 293 } 294 295 func (vscd ValidateSigCountDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (sdk.Context, error) { 296 sigTx, ok := tx.(SigVerifiableTx) 297 if !ok { 298 return ctx, sdkerrors.Wrap(sdkerrors.ErrTxDecode, "Tx must be a sigTx") 299 } 300 301 params := vscd.ak.GetParams(ctx) 302 pubKeys := sigTx.GetPubKeys() 303 304 sigCount := 0 305 for _, pk := range pubKeys { 306 sigCount += types.CountSubKeys(pk) 307 if uint64(sigCount) > params.TxSigLimit { 308 return ctx, sdkerrors.Wrapf(sdkerrors.ErrTooManySignatures, 309 "signatures: %d, limit: %d", sigCount, params.TxSigLimit) 310 } 311 } 312 313 return next(ctx, tx, simulate) 314 } 315 316 // DefaultSigVerificationGasConsumer is the default implementation of SignatureVerificationGasConsumer. It consumes gas 317 // for signature verification based upon the public key type. The cost is fetched from the given params and is matched 318 // by the concrete type. 319 func DefaultSigVerificationGasConsumer( 320 meter sdk.GasMeter, sig []byte, pubkey crypto.PubKey, params types.Params, 321 ) error { 322 switch pubkey := pubkey.(type) { 323 case ed25519.PubKeyEd25519: 324 meter.ConsumeGas(params.SigVerifyCostED25519, "ante verify: ed25519") 325 return sdkerrors.Wrap(sdkerrors.ErrInvalidPubKey, "ED25519 public keys are unsupported") 326 327 case secp256k1.PubKeySecp256k1: 328 meter.ConsumeGas(params.SigVerifyCostSecp256k1, "ante verify: secp256k1") 329 return nil 330 331 case multisig.PubKeyMultisigThreshold: 332 var multisignature multisig.Multisignature 333 codec.Cdc.MustUnmarshalBinaryBare(sig, &multisignature) 334 335 ConsumeMultisignatureVerificationGas(meter, multisignature, pubkey, params) 336 return nil 337 338 default: 339 return sdkerrors.Wrapf(sdkerrors.ErrInvalidPubKey, "unrecognized public key type: %T", pubkey) 340 } 341 } 342 343 // ConsumeMultisignatureVerificationGas consumes gas from a GasMeter for verifying a multisig pubkey signature 344 func ConsumeMultisignatureVerificationGas(meter sdk.GasMeter, 345 sig multisig.Multisignature, pubkey multisig.PubKeyMultisigThreshold, 346 params types.Params) { 347 size := sig.BitArray.Size() 348 sigIndex := 0 349 for i := 0; i < size; i++ { 350 if sig.BitArray.GetIndex(i) { 351 DefaultSigVerificationGasConsumer(meter, sig.Sigs[sigIndex], pubkey.PubKeys[i], params) 352 sigIndex++ 353 } 354 } 355 } 356 357 // GetSignerAcc returns an account for a given address that is expected to sign 358 // a transaction. 359 func GetSignerAcc(ctx sdk.Context, ak keeper.AccountKeeper, addr sdk.AccAddress) (exported.Account, error) { 360 if acc := ak.GetAccount(ctx, addr); acc != nil { 361 return acc, nil 362 } 363 return nil, sdkerrors.Wrapf(sdkerrors.ErrUnknownAddress, "account %s does not exist", addr) 364 }