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  }