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 0b394ba5b0..fccb86003d 100644 --- a/specs/src/README.md +++ b/specs/src/README.md @@ -7,6 +7,7 @@ - [Consensus](./specs/consensus.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 c877c6cb28..17c44766de 100644 --- a/specs/src/SUMMARY.md +++ b/specs/src/SUMMARY.md @@ -9,6 +9,7 @@ - [Consensus](./specs/consensus.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 diff --git a/specs/src/specs/fraud_proofs.md b/specs/src/specs/fraud_proofs.md index 8dde0d33f5..2ec0802b00 100644 --- a/specs/src/specs/fraud_proofs.md +++ b/specs/src/specs/fraud_proofs.md @@ -22,4 +22,4 @@ State fraud proofs allow light clients to avoid making an honest majority assump state validity. While these are not incorporated into the protocol as of v1.0.0, there are example implementations that can be found in [Rollkit](https://github.com/rollkit/rollkit). More info in -[rollkit-ADR009](https://github.com/rollkit/rollkit/blob/4fd97ba8b8352771f2e66454099785d06fd0c31b/docs/lazy-adr/adr-009-state-fraud-proofs.md). \ No newline at end of file +[rollkit-ADR009](https://github.com/rollkit/rollkit/blob/4fd97ba8b8352771f2e66454099785d06fd0c31b/docs/lazy-adr/adr-009-state-fraud-proofs.md).