diff --git a/protocol/app/ante.go b/protocol/app/ante.go
index 735318f0af4..38cf2bab265 100644
--- a/protocol/app/ante.go
+++ b/protocol/app/ante.go
@@ -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
 }