Add RejectExtensionOptionsDecorator (#6988)
* Add RejectExtensionOptionsDecorator * Fix error code * Fix lint * Add ExtensionOptionsTxBuilder * Add tests * Add tests * Update tests * Docs Co-authored-by: sahith-narahari <sahithnarahari@gmail.com> Co-authored-by: Alexander Bezobchuk <alexanderbez@users.noreply.github.com>
This commit is contained in:
parent
7f0c3f0093
commit
94b3cc50b4
|
@ -110,6 +110,9 @@ var (
|
|||
// explicitly set timeout height.
|
||||
ErrTxTimeoutHeight = Register(RootCodespace, 30, "tx timeout height")
|
||||
|
||||
// ErrUnknownExtensionOptions defines an error for unknown extension options.
|
||||
ErrUnknownExtensionOptions = Register(RootCodespace, 31, "unknown extension options")
|
||||
|
||||
// ErrPanic is only set when we recover from a panic, so we know to
|
||||
// redact potentially sensitive system info
|
||||
ErrPanic = Register(UndefinedCodespace, 111222, "panic")
|
||||
|
|
|
@ -16,6 +16,7 @@ func NewAnteHandler(
|
|||
) sdk.AnteHandler {
|
||||
return sdk.ChainAnteDecorators(
|
||||
NewSetUpContextDecorator(), // outermost AnteDecorator. SetUpContext must be called first
|
||||
NewRejectExtensionOptionsDecorator(),
|
||||
NewMempoolFeeDecorator(),
|
||||
NewValidateBasicDecorator(),
|
||||
TxTimeoutHeightDecorator{},
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
package ante
|
||||
|
||||
import (
|
||||
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
|
||||
"github.com/cosmos/cosmos-sdk/types"
|
||||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
||||
)
|
||||
|
||||
type HasExtensionOptionsTx interface {
|
||||
GetExtensionOptions() []*codectypes.Any
|
||||
GetNonCriticalExtensionOptions() []*codectypes.Any
|
||||
}
|
||||
|
||||
// RejectExtensionOptionsDecorator is an AnteDecorator that rejects all extension
|
||||
// options which can optionally be included in protobuf transactions. Users that
|
||||
// need extension options should create a custom AnteHandler chain that handles
|
||||
// needed extension options properly and rejects unknown ones.
|
||||
type RejectExtensionOptionsDecorator struct{}
|
||||
|
||||
// NewRejectExtensionOptionsDecorator creates a new RejectExtensionOptionsDecorator
|
||||
func NewRejectExtensionOptionsDecorator() RejectExtensionOptionsDecorator {
|
||||
return RejectExtensionOptionsDecorator{}
|
||||
}
|
||||
|
||||
var _ types.AnteDecorator = RejectExtensionOptionsDecorator{}
|
||||
|
||||
// AnteHandle implements the AnteDecorator.AnteHandle method
|
||||
func (r RejectExtensionOptionsDecorator) AnteHandle(ctx types.Context, tx types.Tx, simulate bool, next types.AnteHandler) (newCtx types.Context, err error) {
|
||||
if hasExtOptsTx, ok := tx.(HasExtensionOptionsTx); ok {
|
||||
if len(hasExtOptsTx.GetExtensionOptions()) != 0 {
|
||||
return ctx, sdkerrors.ErrUnknownExtensionOptions
|
||||
}
|
||||
}
|
||||
|
||||
return next(ctx, tx, simulate)
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
package ante_test
|
||||
|
||||
import (
|
||||
"github.com/cosmos/cosmos-sdk/codec/types"
|
||||
"github.com/cosmos/cosmos-sdk/testutil/testdata"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/auth/ante"
|
||||
"github.com/cosmos/cosmos-sdk/x/auth/tx"
|
||||
)
|
||||
|
||||
func (suite *AnteTestSuite) TestRejectExtensionOptionsDecorator() {
|
||||
suite.SetupTest(true) // setup
|
||||
suite.txBuilder = suite.clientCtx.TxConfig.NewTxBuilder()
|
||||
|
||||
reod := ante.NewRejectExtensionOptionsDecorator()
|
||||
antehandler := sdk.ChainAnteDecorators(reod)
|
||||
|
||||
// no extension options should not trigger an error
|
||||
theTx := suite.txBuilder.GetTx()
|
||||
_, err := antehandler(suite.ctx, theTx, false)
|
||||
suite.Require().NoError(err)
|
||||
|
||||
extOptsTxBldr, ok := suite.txBuilder.(tx.ExtensionOptionsTxBuilder)
|
||||
if !ok {
|
||||
// if we can't set extension options, this decorator doesn't apply and we're done
|
||||
return
|
||||
}
|
||||
|
||||
// setting any extension option should cause an error
|
||||
any, err := types.NewAnyWithValue(testdata.NewTestMsg())
|
||||
suite.Require().NoError(err)
|
||||
extOptsTxBldr.SetExtensionOptions(any)
|
||||
theTx = suite.txBuilder.GetTx()
|
||||
_, err = antehandler(suite.ctx, theTx, false)
|
||||
suite.Require().EqualError(err, "unknown extension options")
|
||||
}
|
|
@ -14,6 +14,7 @@ import (
|
|||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
||||
"github.com/cosmos/cosmos-sdk/types/tx"
|
||||
"github.com/cosmos/cosmos-sdk/types/tx/signing"
|
||||
"github.com/cosmos/cosmos-sdk/x/auth/ante"
|
||||
authsigning "github.com/cosmos/cosmos-sdk/x/auth/signing"
|
||||
)
|
||||
|
||||
|
@ -38,10 +39,19 @@ type builder struct {
|
|||
}
|
||||
|
||||
var (
|
||||
_ authsigning.Tx = &builder{}
|
||||
_ client.TxBuilder = &builder{}
|
||||
_ authsigning.Tx = &builder{}
|
||||
_ client.TxBuilder = &builder{}
|
||||
_ ante.HasExtensionOptionsTx = &builder{}
|
||||
_ ExtensionOptionsTxBuilder = &builder{}
|
||||
)
|
||||
|
||||
type ExtensionOptionsTxBuilder interface {
|
||||
client.TxBuilder
|
||||
|
||||
SetExtensionOptions(...*codectypes.Any)
|
||||
SetNonCriticalExtensionOptions(...*codectypes.Any)
|
||||
}
|
||||
|
||||
func newBuilder(pubkeyCodec types.PublicKeyCodec) *builder {
|
||||
return &builder{
|
||||
tx: &tx.Tx{
|
||||
|
@ -391,3 +401,21 @@ func (t *builder) setSignatures(sigs [][]byte) {
|
|||
func (t *builder) GetTx() authsigning.Tx {
|
||||
return t
|
||||
}
|
||||
|
||||
func (t *builder) GetExtensionOptions() []*codectypes.Any {
|
||||
return t.tx.Body.ExtensionOptions
|
||||
}
|
||||
|
||||
func (t *builder) GetNonCriticalExtensionOptions() []*codectypes.Any {
|
||||
return t.tx.Body.NonCriticalExtensionOptions
|
||||
}
|
||||
|
||||
func (t *builder) SetExtensionOptions(extOpts ...*codectypes.Any) {
|
||||
t.tx.Body.ExtensionOptions = extOpts
|
||||
t.bodyBz = nil
|
||||
}
|
||||
|
||||
func (t *builder) SetNonCriticalExtensionOptions(extOpts ...*codectypes.Any) {
|
||||
t.tx.Body.NonCriticalExtensionOptions = extOpts
|
||||
t.bodyBz = nil
|
||||
}
|
||||
|
|
|
@ -109,6 +109,13 @@ func TestTxBuilder(t *testing.T) {
|
|||
require.Equal(t, 1, len(txBuilder.GetPubKeys()))
|
||||
require.Equal(t, legacy.Cdc.MustMarshalBinaryBare(pubkey), legacy.Cdc.MustMarshalBinaryBare(txBuilder.GetPubKeys()[0]))
|
||||
|
||||
any, err := codectypes.NewAnyWithValue(testdata.NewTestMsg())
|
||||
require.NoError(t, err)
|
||||
txBuilder.SetExtensionOptions(any)
|
||||
require.Equal(t, []*codectypes.Any{any}, txBuilder.GetExtensionOptions())
|
||||
txBuilder.SetNonCriticalExtensionOptions(any)
|
||||
require.Equal(t, []*codectypes.Any{any}, txBuilder.GetNonCriticalExtensionOptions())
|
||||
|
||||
txBuilder = &builder{}
|
||||
require.NotPanics(t, func() {
|
||||
_ = txBuilder.GetMsgs()
|
||||
|
|
Loading…
Reference in New Issue