Skip to content

Commit

Permalink
disable clob ante
Browse files Browse the repository at this point in the history
  • Loading branch information
roy-dydx committed Apr 25, 2024
1 parent 2cd68a9 commit d288eba
Showing 1 changed file with 281 additions and 0 deletions.
281 changes: 281 additions & 0 deletions protocol/app/ante.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,4 +130,285 @@ func NewAnteDecoratorChain(options HandlerOptions) []sdk.AnteDecorator {
clobante.NewRateLimitDecorator(options.ClobKeeper),
clobante.NewClobDecorator(options.ClobKeeper),
}
<<<<<<< Updated upstream
=======
return h.AnteHandle, nil
}

// An ante handler that returns the context.
func noOpAnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool) (sdk.Context, error) {
return ctx, nil
}

type lockingAnteHandler struct {
globalLock sync.Mutex
authStoreKey storetypes.StoreKey

setupContextDecorator ante.SetUpContextDecorator
freeInfiniteGasDecorator customante.FreeInfiniteGasDecorator
extensionOptionsChecker sdk.AnteDecorator
validateMsgType customante.ValidateMsgTypeDecorator
txTimeoutHeight ante.TxTimeoutHeightDecorator
validateMemo ante.ValidateMemoDecorator
validateBasic ante.ValidateBasicDecorator
validateSigCount ante.ValidateSigCountDecorator
incrementSequence ante.IncrementSequenceDecorator
sigVerification customante.SigVerificationDecorator
consumeTxSizeGas ante.ConsumeTxSizeGasDecorator
deductFee ante.DeductFeeDecorator
setPubKey ante.SetPubKeyDecorator
sigGasConsume ante.SigGasConsumeDecorator
clobRateLimit clobante.ClobRateLimitDecorator
clob clobante.ClobDecorator
}

func (h *lockingAnteHandler) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool) (sdk.Context, error) {
ctx = log.AddPersistentTagsToLogger(ctx,
log.Callback, lib.TxMode(ctx),
log.BlockHeight, ctx.BlockHeight()+1,
)

isClob, err := clobante.IsSingleClobMsgTx(tx)
if err != nil {
return ctx, err
} else if isClob {
return h.clobAnteHandle(ctx, tx, simulate)
}
if libante.IsSingleAppInjectedMsg(tx.GetMsgs()) {
return h.appInjectedMsgAnteHandle(ctx, tx, simulate)
}

return h.otherMsgAnteHandle(ctx, tx, simulate)
}

func (h *lockingAnteHandler) clobAnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool) (
newCtx sdk.Context,
err error,
) {
// These ante decorators access state but only state that is mutated during `deliverTx`. The Cosmos SDK
// is responsible for linearizing the reads and writes during `deliverTx`.
if ctx, err = h.freeInfiniteGasDecorator.AnteHandle(ctx, tx, simulate, noOpAnteHandle); err != nil {
return ctx, err
}
if ctx, err = h.extensionOptionsChecker.AnteHandle(ctx, tx, simulate, noOpAnteHandle); err != nil {
return ctx, err
}
if ctx, err = h.validateMsgType.AnteHandle(ctx, tx, simulate, noOpAnteHandle); err != nil {
return ctx, err
}
if ctx, err = h.validateBasic.AnteHandle(ctx, tx, simulate, noOpAnteHandle); err != nil {
return ctx, err
}
if ctx, err = h.txTimeoutHeight.AnteHandle(ctx, tx, simulate, noOpAnteHandle); err != nil {
return ctx, err
}
if ctx, err = h.validateMemo.AnteHandle(ctx, tx, simulate, noOpAnteHandle); err != nil {
return ctx, err
}

// During `deliverTx` and simulation the Cosmos SDK is responsible for branching and writing the state store.
// During `checkTx` we acquire a per account lock to prevent stale reads of state that can be mutated during
// `checkTx`. Note that these messages are common so we use a row level like lock for each account and branch
// the state store to support writes in the ante decorators that follow.
var cacheMs storetypes.CacheMultiStore
if !simulate && (ctx.IsCheckTx() || ctx.IsReCheckTx()) {
sigTx, ok := tx.(authsigning.SigVerifiableTx)
if !ok {
return ctx, errorsmod.Wrap(sdkerrors.ErrTxDecode, "Tx must be a sigTx")
}
var signers [][]byte
signers, err = sigTx.GetSigners()
if err != nil {
return ctx, err
}

cacheMs = ctx.MultiStore().(cachemulti.Store).CacheMultiStoreWithLocking(map[storetypes.StoreKey][][]byte{
h.authStoreKey: signers,
})
defer cacheMs.(storetypes.LockingStore).Unlock()
ctx = ctx.WithMultiStore(cacheMs)
}

if ctx, err = h.consumeTxSizeGas.AnteHandle(ctx, tx, simulate, noOpAnteHandle); err != nil {
return ctx, err
}
if ctx, err = h.setPubKey.AnteHandle(ctx, tx, simulate, noOpAnteHandle); err != nil {
return ctx, err
}
if ctx, err = h.validateSigCount.AnteHandle(ctx, tx, simulate, noOpAnteHandle); err != nil {
return ctx, err
}
if ctx, err = h.sigGasConsume.AnteHandle(ctx, tx, simulate, noOpAnteHandle); err != nil {
return ctx, err
}
if ctx, err = h.sigVerification.AnteHandle(ctx, tx, simulate, noOpAnteHandle); err != nil {
return ctx, err
}

var isShortTerm bool
if isShortTerm, err = clobante.IsShortTermClobMsgTx(ctx, tx); err != nil {
return ctx, err
}
if !isShortTerm {
if ctx, err = h.incrementSequence.AnteHandle(ctx, tx, simulate, noOpAnteHandle); err != nil {
return ctx, err
}
}

// We now acquire the global ante handler since the clob decorator is not thread safe and performs
// several reads and writes across many stores.
if !simulate && (ctx.IsCheckTx() || ctx.IsReCheckTx()) {
h.globalLock.Lock()
defer h.globalLock.Unlock()
}

if ctx, err = h.clobRateLimit.AnteHandle(ctx, tx, simulate, noOpAnteHandle); err != nil {
return ctx, err
}

// During non-simulated `checkTx` we must write the store since we own branching and writing.
// During `deliverTx` and simulation the Cosmos SDK is responsible for branching and writing.
if err == nil && !simulate && (ctx.IsCheckTx() || ctx.IsReCheckTx()) {
cacheMs.Write()
}

return ctx, err
}

// appInjectedMsgAnteHandle processes app injected messages through the necessary and sufficient set
// of ante decorators.
//
// Note that app injected messages do not require gas and are unsigned thus we do not need to:
// - setup context to install a gas meter.
// - validate basic for the signature check.
// - set the pub key on the account.
// - verify the signature.
// - consume gas.
// - deduct fees.
// - increment the sequence number.
// - rate limit or handle through the clob decorator since this isn't a clob message.
func (h *lockingAnteHandler) appInjectedMsgAnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool) (
newCtx sdk.Context,
err error,
) {
// Note that app injected messages are only sent during `deliverTx` (checked by validateMsgType)
// and hence we do not require any additional locking beyond what the Cosmos SDK already provides.
if ctx, err = h.freeInfiniteGasDecorator.AnteHandle(ctx, tx, simulate, noOpAnteHandle); err != nil {
return ctx, err
}
if ctx, err = h.extensionOptionsChecker.AnteHandle(ctx, tx, simulate, noOpAnteHandle); err != nil {
return ctx, err
}
if ctx, err = h.validateMsgType.AnteHandle(ctx, tx, simulate, noOpAnteHandle); err != nil {
return ctx, err
}
if ctx, err = h.txTimeoutHeight.AnteHandle(ctx, tx, simulate, noOpAnteHandle); err != nil {
return ctx, err
}
if ctx, err = h.validateMemo.AnteHandle(ctx, tx, simulate, noOpAnteHandle); err != nil {
return ctx, err
}
if ctx, err = h.consumeTxSizeGas.AnteHandle(ctx, tx, simulate, noOpAnteHandle); err != nil {
return ctx, err
}
if ctx, err = h.validateSigCount.AnteHandle(ctx, tx, simulate, noOpAnteHandle); err != nil {
return ctx, err
}

return ctx, err
}

// otherMsgAnteHandle processes all non-clob and non-app injected messages through the necessary and sufficient
// set of ante decorators.
//
// Note that these messages will never need to use the clob ante decorators so they are omitted.
func (h *lockingAnteHandler) otherMsgAnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool) (
newCtx sdk.Context,
err error,
) {
// During `deliverTx` we hold an exclusive lock on `app.mtx` and have a context with a branched state store
// allowing us to not have to perform any further locking or state store branching.
//
// For `checkTx`, these ante decorators access state but only state that is mutated during `deliverTx`
// and hence since we already hold a read lock on `app.mtx` we can be certain that no state writes will occur.
if ctx, err = h.setupContextDecorator.AnteHandle(ctx, tx, simulate, noOpAnteHandle); err != nil {
return ctx, err
}
if ctx, err = h.freeInfiniteGasDecorator.AnteHandle(ctx, tx, simulate, noOpAnteHandle); err != nil {
return ctx, err
}
if ctx, err = h.extensionOptionsChecker.AnteHandle(ctx, tx, simulate, noOpAnteHandle); err != nil {
return ctx, err
}
if ctx, err = h.validateMsgType.AnteHandle(ctx, tx, simulate, noOpAnteHandle); err != nil {
return ctx, err
}
if ctx, err = h.validateBasic.AnteHandle(ctx, tx, simulate, noOpAnteHandle); err != nil {
return ctx, err
}
if ctx, err = h.txTimeoutHeight.AnteHandle(ctx, tx, simulate, noOpAnteHandle); err != nil {
return ctx, err
}
if ctx, err = h.validateMemo.AnteHandle(ctx, tx, simulate, noOpAnteHandle); err != nil {
return ctx, err
}

// During `deliverTx` and simulation the Cosmos SDK is responsible for branching and writing the state store.
// During `checkTx` we acquire a per account lock to prevent stale reads of state that can be mutated during
// `checkTx`. Note that we acquire row level like locks per account and also acquire the global lock to ensure
// that we linearize reads and writes for accounts with the clobAnteHandle and the global lock ensures that
// we linearize reads and writes to other stores since the deduct fees decorator mutates state outside of the
// account keeper and those stores are currently not safe for concurrent use.
var cacheMs storetypes.CacheMultiStore
if !simulate && (ctx.IsCheckTx() || ctx.IsReCheckTx()) {
sigTx, ok := tx.(authsigning.SigVerifiableTx)
if !ok {
return ctx, errorsmod.Wrap(sdkerrors.ErrTxDecode, "Tx must be a sigTx")
}
var signers [][]byte
signers, err = sigTx.GetSigners()
if err != nil {
return ctx, err
}

cacheMs = ctx.MultiStore().(cachemulti.Store).CacheMultiStoreWithLocking(map[storetypes.StoreKey][][]byte{
h.authStoreKey: signers,
})
defer cacheMs.(storetypes.LockingStore).Unlock()
ctx = ctx.WithMultiStore(cacheMs)

h.globalLock.Lock()
defer h.globalLock.Unlock()
}

if ctx, err = h.consumeTxSizeGas.AnteHandle(ctx, tx, simulate, noOpAnteHandle); err != nil {
return ctx, err
}
if ctx, err = h.deductFee.AnteHandle(ctx, tx, simulate, noOpAnteHandle); err != nil {
return ctx, err
}
if ctx, err = h.setPubKey.AnteHandle(ctx, tx, simulate, noOpAnteHandle); err != nil {
return ctx, err
}
if ctx, err = h.validateSigCount.AnteHandle(ctx, tx, simulate, noOpAnteHandle); err != nil {
return ctx, err
}
if ctx, err = h.sigGasConsume.AnteHandle(ctx, tx, simulate, noOpAnteHandle); err != nil {
return ctx, err
}
if ctx, err = h.sigVerification.AnteHandle(ctx, tx, simulate, noOpAnteHandle); err != nil {
return ctx, err
}
if ctx, err = h.incrementSequence.AnteHandle(ctx, tx, simulate, noOpAnteHandle); err != nil {
return ctx, err
}

// During non-simulated `checkTx` we must write the store since we own branching and writing.
// During `deliverTx` and simulation the Cosmos SDK is responsible for branching and writing.
if err == nil && !simulate && (ctx.IsCheckTx() || ctx.IsReCheckTx()) {
cacheMs.Write()
}

return ctx, err
>>>>>>> Stashed changes
}

0 comments on commit d288eba

Please sign in to comment.