diff --git a/app/ante/ante.go b/app/ante/ante.go index 6cfc7309e8..a6e1f0eeed 100644 --- a/app/ante/ante.go +++ b/app/ante/ante.go @@ -21,24 +21,48 @@ func NewAnteHandler( channelKeeper *ibckeeper.Keeper, ) sdk.AnteHandler { return sdk.ChainAnteDecorators( - ante.NewSetUpContextDecorator(), // outermost AnteDecorator. SetUpContext must be called first - // reject all tx extensions + // Set up the context with a gas meter. + // Contract: must be called first. + ante.NewSetUpContextDecorator(), + // Ensure the tx does not contain any extension options. ante.NewExtensionOptionsDecorator(nil), + // Ensure the tx passes ValidateBasic. ante.NewValidateBasicDecorator(), + // Ensure the tx has not reached a height timeout. ante.NewTxTimeoutHeightDecorator(), + // Ensure the tx memo <= max memo characters. ante.NewValidateMemoDecorator(accountKeeper), + // Ensure the tx's gas limit is > the gas consumed based on the tx size. + // Side effect: consumes gas from the gas meter. ante.NewConsumeGasForTxSizeDecorator(accountKeeper), - // check that the fee matches the gas and the local minimum gas price - // of the validator + // Ensure the feepayer (fee granter or first signer) has enough funds to pay for the tx. + // Side effect: deducts fees from the fee payer. Sets the tx priority in context. ante.NewDeductFeeDecorator(accountKeeper, bankKeeper, feegrantKeeper, checkTxFeeWithValidatorMinGasPrices), - ante.NewSetPubKeyDecorator(accountKeeper), // SetPubKeyDecorator must be called before all signature verification decorators + // Set public keys in the context for fee-payer and all signers. + // Contract: must be called before all signature verification decorators. + ante.NewSetPubKeyDecorator(accountKeeper), + // Ensure that the tx's count of signatures is <= the tx signature limit. ante.NewValidateSigCountDecorator(accountKeeper), + // Ensure that the tx's gas limit is > the gas consumed based on signature verification. + // Side effect: consumes gas from the gas meter. ante.NewSigGasConsumeDecorator(accountKeeper, sigGasConsumer), + // Ensure that the tx's signatures are valid. For each signature, ensure + // that the signature's sequence number (a.k.a nonce) matches the + // account sequence number of the signer. + // Note: does not consume gas from the gas meter. ante.NewSigVerificationDecorator(accountKeeper, signModeHandler), + // Ensure that the tx's gas limit is > the gas consumed based on the blob size(s). + // Contract: must be called after all decorators that consume gas. + // Note: does not consume gas from the gas meter. blobante.NewMinGasPFBDecorator(blobKeeper), + // Ensure that the tx's total blob size is <= the max blob size. blobante.NewMaxBlobSizeDecorator(blobKeeper), + // Ensure that tx's with a MsgSubmitProposal have atleast one proposal + // message. NewGovProposalDecorator(), + // Side effect: increment the nonce for all tx signers. ante.NewIncrementSequenceDecorator(accountKeeper), + // Ensure that the tx is not a IBC packet or update message that has already been processed. ibcante.NewRedundantRelayDecorator(channelKeeper), ) } diff --git a/app/ante/fee_checker.go b/app/ante/fee_checker.go index c1bc9baa99..1e39d14fe2 100644 --- a/app/ante/fee_checker.go +++ b/app/ante/fee_checker.go @@ -12,7 +12,7 @@ const ( ) // checkTxFeeWithValidatorMinGasPrices implements the default fee logic, where the minimum price per -// unit of gas is fixed and set by each validator, can the tx priority is computed from the gas price. +// unit of gas is fixed and set by each validator, and the tx priority is computed from the gas price. func checkTxFeeWithValidatorMinGasPrices(ctx sdk.Context, tx sdk.Tx) (sdk.Coins, int64, error) { feeTx, ok := tx.(sdk.FeeTx) if !ok { diff --git a/app/ante/gov.go b/app/ante/gov.go index e94923c0f6..be5c29b66e 100644 --- a/app/ante/gov.go +++ b/app/ante/gov.go @@ -7,6 +7,8 @@ import ( govv1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1" ) +// GovProposalDecorator ensures that a tx with a MsgSubmitProposal has at least +// one message in the proposal. type GovProposalDecorator struct{} func NewGovProposalDecorator() GovProposalDecorator { diff --git a/app/check_tx.go b/app/check_tx.go index 50141de811..1cb54c52c5 100644 --- a/app/check_tx.go +++ b/app/check_tx.go @@ -18,6 +18,7 @@ func (app *App) CheckTx(req abci.RequestCheckTx) abci.ResponseCheckTx { btx, isBlob := coretypes.UnmarshalBlobTx(tx) if !isBlob { + // reject transactions that can't be decoded sdkTx, err := app.txConfig.TxDecoder()(tx) if err != nil { return sdkerrors.ResponseCheckTxWithEvents(err, 0, 0, []abci.Event{}, false) diff --git a/specs/src/README.md b/specs/src/README.md index 23ea8c2167..5beafa5eb9 100644 --- a/specs/src/README.md +++ b/specs/src/README.md @@ -8,6 +8,7 @@ - [CAT Pool](./specs/cat_pool.md) - [Block Proposer](./specs/block_proposer.md) - [Block Validity Rules](./specs/block_validity_rules.md) + - [AnteHandler](./specs/ante_handler.md) - [Fraud Proofs](./specs/fraud_proofs.md) - [Networking](./specs/networking.md) - [Public-Key Cryptography](./specs/public_key_cryptography.md) diff --git a/specs/src/SUMMARY.md b/specs/src/SUMMARY.md index b903aaaff2..43c7d8fd30 100644 --- a/specs/src/SUMMARY.md +++ b/specs/src/SUMMARY.md @@ -10,6 +10,7 @@ - [CAT Pool](./specs/cat_pool.md) - [Block Proposer](./specs/block_proposer.md) - [Block Validity Rules](./specs/block_validity_rules.md) + - [AnteHandler](./specs/ante_handler.md) - [Fraud Proofs](./specs/fraud_proofs.md) - [Networking](./specs/networking.md) - [Public-Key Cryptography](./specs/public_key_cryptography.md) diff --git a/specs/src/specs/ante_handler.md b/specs/src/specs/ante_handler.md new file mode 100644 index 0000000000..6c919aebee --- /dev/null +++ b/specs/src/specs/ante_handler.md @@ -0,0 +1,30 @@ +# AnteHandler + +Celestia makes use of a Cosmos SDK [AnteHandler](https://docs.cosmos.network/v0.46/modules/auth/03_antehandlers.html#antehandlers) in order to reject decodable sdk.Txs that do not meet certain criteria. The AnteHandler is defined in [app/ante/ante.go](https://github.com/celestiaorg/celestia-app/blob/7f97788a64af7fe0fce00959753d6dd81663e98f/app/ante/ante.go) and is invoked at multiple times during the transaction lifecycle: + +1. `CheckTx` prior to the transaction entering the mempool +1. `PrepareProposal` when the block proposer includes the transaction in a block proposal +1. `ProcessProposal` when validators validate the transaction in a block proposal +1. `DeliverTx` when full nodes execute the transaction in a decided block + +The AnteHandler chains together several decorators to ensure the following criteria are met: + +- The tx does not contain any [extension options](https://github.com/cosmos/cosmos-sdk/blob/22c28366466e64ebf0df1ce5bec8b1130523552c/proto/cosmos/tx/v1beta1/tx.proto#L119-L122). +- The tx passes `ValidateBasic()`. +- The tx's [timeout_height](https://github.com/cosmos/cosmos-sdk/blob/22c28366466e64ebf0df1ce5bec8b1130523552c/proto/cosmos/tx/v1beta1/tx.proto#L115-L117) has not been reached if one is specified. +- The tx's [memo](https://github.com/cosmos/cosmos-sdk/blob/22c28366466e64ebf0df1ce5bec8b1130523552c/proto/cosmos/tx/v1beta1/tx.proto#L110-L113) is <= the max memo characters where [`MaxMemoCharacters = 256`](). +- The tx's [gas_limit](https://github.com/cosmos/cosmos-sdk/blob/22c28366466e64ebf0df1ce5bec8b1130523552c/proto/cosmos/tx/v1beta1/tx.proto#L211-L213) is > the gas consumed based on the tx's size where [`TxSizeCostPerByte = 10`](https://github.com/cosmos/cosmos-sdk/blob/a429238fc267da88a8548bfebe0ba7fb28b82a13/x/auth/README.md?plain=1#L232). +- The tx's feepayer has enough funds to pay fees for the tx. The tx's feepayer is the feegranter (if specified) or the tx's first signer. Note the [feegrant](https://docs.cosmos.network/v0.46/) module is enabled. +- The tx's count of signatures <= the max number of signatures. The max number of signatures is [`TxSigLimit = 7`](https://github.com/cosmos/cosmos-sdk/blob/a429238fc267da88a8548bfebe0ba7fb28b82a13/x/auth/README.md?plain=1#L231). +- The tx's [gas_limit](https://github.com/cosmos/cosmos-sdk/blob/22c28366466e64ebf0df1ce5bec8b1130523552c/proto/cosmos/tx/v1beta1/tx.proto#L211-L213) is > the gas consumed based on the tx's signatures. +- The tx's [signatures](https://github.com/cosmos/cosmos-sdk/blob/22c28366466e64ebf0df1ce5bec8b1130523552c/types/tx/signing/signature.go#L10-L26) are valid. For each signature, ensure that the signature's sequence number (a.k.a nonce) matches the account sequence number of the signer. +- The tx's [gas_limit](https://github.com/cosmos/cosmos-sdk/blob/22c28366466e64ebf0df1ce5bec8b1130523552c/proto/cosmos/tx/v1beta1/tx.proto#L211-L213) is > the gas consumed based on the blob size(s). Since blobs are charged based on the number of shares they occupy, the gas consumed is calculated as follows: `gasToConsume = sharesNeeded(blob) * bytesPerShare * gasPerBlobByte`. Where `bytesPerShare` is a a global constant (an alias for [`ShareSize = 512`](https://github.com/celestiaorg/celestia-app/blob/c90e61d5a2d0c0bd0e123df4ab416f6f0d141b7f/pkg/appconsts/global_consts.go#L27-L28)) and `gasPerBlobByte` is a governance parameter that can be modified (the [`DefaultGasPerBlobByte = 8`](https://github.com/celestiaorg/celestia-app/blob/c90e61d5a2d0c0bd0e123df4ab416f6f0d141b7f/pkg/appconsts/initial_consts.go#L16-L18)). +- The tx's total blob size is <= the max blob size. The max blob size is derived from the maximum valid square size. The max valid square size is the minimum of: `GovMaxSquareSize` and `SquareSizeUpperBound`. +- The tx does not contain a message of type [MsgSubmitProposal](https://github.com/cosmos/cosmos-sdk/blob/d6d929843bbd331b885467475bcb3050788e30ca/proto/cosmos/gov/v1/tx.proto#L33-L43) with zero proposal messages. +- The tx is not an IBC packet or update message that has already been processed. + +In addition to the above criteria, the AnteHandler also has a number of side-effects: + +- Tx fees are deducted from the tx's feepayer and added to the fee collector module account. +- Tx priority is calculated based on the the smallest denomination of gas price in the tx and set in context. +- The nonce of all tx signers is incremented by 1. diff --git a/specs/src/specs/block_validity_rules.md b/specs/src/specs/block_validity_rules.md index 4b0b97f32c..6a620c95dd 100644 --- a/specs/src/specs/block_validity_rules.md +++ b/specs/src/specs/block_validity_rules.md @@ -39,9 +39,11 @@ Celestia specifc validity rules can be categorized into two groups: ### Transaction Validity Rules -All `BlobTx` transactions must be valid according to the [BlobTx validity rules](../../../x/blob/README.md#validity-rules) +All `BlobTx` transactions must be valid according to the [BlobTx validity rules](../../../x/blob/README.md#validity-rules). -All remaining transaction types do not have to by valid if included in a block. For a complete list of modules see [state machine modules](./state_machine_modules.md). +All remaining transactions must be decodable and pass all [AnteHandler](./ante_handler.md) checks. + +For a complete list of modules see [state machine modules](./state_machine_modules.md). ### Data Root Construction