@@ -68,7 +68,7 @@ type BaseApp struct {
6868 name string // application name from abci.BlockInfo
6969 db dbm.DB // common DB backend
7070 cms storetypes.CommitMultiStore // Main (uncached) state
71- qms storetypes.MultiStore // Optional alternative multistore for querying only.
71+ qms storetypes.RootMultiStore // Optional alternative multistore for querying only.
7272 storeLoader StoreLoader // function to handle store loading, may be overridden with SetStoreLoader()
7373 grpcQueryRouter * GRPCQueryRouter // router for redirecting gRPC query calls
7474 msgServiceRouter * MsgServiceRouter // router for redirecting Msg service messages
@@ -198,6 +198,9 @@ type BaseApp struct {
198198 //
199199 // SAFETY: it's safe to do if validators validate the total gas wanted in the `ProcessProposal`, which is the case in the default handler.
200200 disableBlockGasMeter bool
201+
202+ // Optional alternative tx executor, used for block-stm parallel transaction execution.
203+ txExecutor TxExecutor
201204}
202205
203206// NewBaseApp returns a reference to an initialized BaseApp. It accepts a
@@ -318,6 +321,9 @@ func (app *BaseApp) MountStores(keys ...storetypes.StoreKey) {
318321 case * storetypes.MemoryStoreKey :
319322 app .MountStore (key , storetypes .StoreTypeMemory )
320323
324+ case * storetypes.ObjectStoreKey :
325+ app .MountStore (key , storetypes .StoreTypeObject )
326+
321327 default :
322328 panic (fmt .Sprintf ("Unrecognized store key type :%T" , key ))
323329 }
@@ -356,6 +362,16 @@ func (app *BaseApp) MountMemoryStores(keys map[string]*storetypes.MemoryStoreKey
356362 }
357363}
358364
365+ // MountObjectStores mounts all transient object stores with the BaseApp's internal
366+ // commit multi-store.
367+ func (app * BaseApp ) MountObjectStores (keys map [string ]* storetypes.ObjectStoreKey ) {
368+ skeys := slices .Sorted (maps .Keys (keys ))
369+ for _ , key := range skeys {
370+ memKey := keys [key ]
371+ app .MountStore (memKey , storetypes .StoreTypeObject )
372+ }
373+ }
374+
359375// MountStore mounts a store to the provided key in the BaseApp multistore,
360376// using the default DB.
361377func (app * BaseApp ) MountStore (key storetypes.StoreKey , typ storetypes.StoreType ) {
@@ -674,7 +690,7 @@ func (app *BaseApp) getBlockGasMeter(ctx sdk.Context) storetypes.GasMeter {
674690}
675691
676692// retrieve the context for the tx w/ txBytes and other memoized values.
677- func (app * BaseApp ) getContextForTx (mode execMode , txBytes []byte ) sdk.Context {
693+ func (app * BaseApp ) getContextForTx (mode execMode , txBytes []byte , txIndex int ) sdk.Context {
678694 app .mu .Lock ()
679695 defer app .mu .Unlock ()
680696
@@ -684,7 +700,8 @@ func (app *BaseApp) getContextForTx(mode execMode, txBytes []byte) sdk.Context {
684700 }
685701 ctx := modeState .Context ().
686702 WithTxBytes (txBytes ).
687- WithGasMeter (storetypes .NewInfiniteGasMeter ())
703+ WithGasMeter (storetypes .NewInfiniteGasMeter ()).
704+ WithTxIndex (txIndex )
688705 // WithVoteInfos(app.voteInfos) // TODO: identify if this is needed
689706
690707 ctx = ctx .WithIsSigverifyTx (app .sigverifyTx )
@@ -769,7 +786,11 @@ func (app *BaseApp) beginBlock(_ *abci.RequestFinalizeBlock) (sdk.BeginBlock, er
769786 return resp , nil
770787}
771788
772- func (app * BaseApp ) deliverTx (tx []byte ) * abci.ExecTxResult {
789+ func (app * BaseApp ) deliverTx (tx []byte , memTx sdk.Tx , txIndex int ) * abci.ExecTxResult {
790+ return app .deliverTxWithMultiStore (tx , memTx , txIndex , nil , nil )
791+ }
792+
793+ func (app * BaseApp ) deliverTxWithMultiStore (tx []byte , memTx sdk.Tx , txIndex int , txMultiStore storetypes.MultiStore , incarnationCache map [string ]any ) * abci.ExecTxResult {
773794 gInfo := sdk.GasInfo {}
774795 resultStr := "successful"
775796
@@ -782,7 +803,7 @@ func (app *BaseApp) deliverTx(tx []byte) *abci.ExecTxResult {
782803 telemetry .SetGauge (float32 (gInfo .GasWanted ), "tx" , "gas" , "wanted" )
783804 }()
784805
785- gInfo , result , anteEvents , err := app .runTx (execModeFinalize , tx , nil )
806+ gInfo , result , anteEvents , err := app .runTxWithMultiStore (execModeFinalize , tx , memTx , txIndex , txMultiStore , incarnationCache )
786807 if err != nil {
787808 resultStr = "failed"
788809 resp = sdkerrors .ResponseExecTxResultWithEvents (
@@ -842,12 +863,20 @@ func (app *BaseApp) endBlock(_ context.Context) (sdk.EndBlock, error) {
842863// both txbytes and the decoded tx are passed to runTx to avoid the state machine encoding the tx and decoding the transaction twice
843864// passing the decoded tx to runTX is optional, it will be decoded if the tx is nil
844865func (app * BaseApp ) runTx (mode execMode , txBytes []byte , tx sdk.Tx ) (gInfo sdk.GasInfo , result * sdk.Result , anteEvents []abci.Event , err error ) {
866+ return app .runTxWithMultiStore (mode , txBytes , tx , - 1 , nil , nil )
867+ }
868+
869+ func (app * BaseApp ) runTxWithMultiStore (mode execMode , txBytes []byte , tx sdk.Tx , txIndex int , txMultiStore storetypes.MultiStore , incarnationCache map [string ]any ) (gInfo sdk.GasInfo , result * sdk.Result , anteEvents []abci.Event , err error ) {
845870 // NOTE: GasWanted should be returned by the AnteHandler. GasUsed is
846871 // determined by the GasMeter. We need access to the context to get the gas
847872 // meter, so we initialize upfront.
848873 var gasWanted uint64
849874
850- ctx := app .getContextForTx (mode , txBytes )
875+ ctx := app .getContextForTx (mode , txBytes , txIndex )
876+ ctx = ctx .WithIncarnationCache (incarnationCache )
877+ if txMultiStore != nil {
878+ ctx = ctx .WithMultiStore (txMultiStore )
879+ }
851880 ms := ctx .MultiStore ()
852881
853882 // only run the tx if there is block gas remaining
@@ -957,7 +986,7 @@ func (app *BaseApp) runTx(mode execMode, txBytes []byte, tx sdk.Tx) (gInfo sdk.G
957986
958987 switch mode {
959988 case execModeCheck :
960- err = app .mempool .Insert (ctx , tx )
989+ err = app .mempool .InsertWithGasWanted (ctx , tx , gasWanted )
961990 if err != nil {
962991 return gInfo , nil , anteEvents , err
963992 }
@@ -1040,6 +1069,8 @@ func (app *BaseApp) runMsgs(ctx sdk.Context, msgs []sdk.Msg, msgsV2 []protov2.Me
10401069 break
10411070 }
10421071
1072+ ctx = ctx .WithMsgIndex (i )
1073+
10431074 handler := app .msgServiceRouter .Handler (msg )
10441075 if handler == nil {
10451076 return nil , errorsmod .Wrapf (sdkerrors .ErrUnknownRequest , "no message handler found for %T" , msg )
@@ -1151,18 +1182,18 @@ func (app *BaseApp) PrepareProposalVerifyTx(tx sdk.Tx) ([]byte, error) {
11511182// ProcessProposal state internally will be discarded. <nil, err> will be
11521183// returned if the transaction cannot be decoded. <Tx, nil> will be returned if
11531184// the transaction is valid, otherwise <Tx, err> will be returned.
1154- func (app * BaseApp ) ProcessProposalVerifyTx (txBz []byte ) (sdk.Tx , error ) {
1185+ func (app * BaseApp ) ProcessProposalVerifyTx (txBz []byte ) (sdk.Tx , uint64 , error ) {
11551186 tx , err := app .txDecoder (txBz )
11561187 if err != nil {
1157- return nil , err
1188+ return nil , 0 , err
11581189 }
11591190
1160- _ , _ , _ , err = app .runTx (execModeProcessProposal , txBz , tx )
1191+ gInfo , _ , _ , err : = app .runTx (execModeProcessProposal , txBz , tx )
11611192 if err != nil {
1162- return nil , err
1193+ return nil , 0 , err
11631194 }
11641195
1165- return tx , nil
1196+ return tx , gInfo . GasWanted , nil
11661197}
11671198
11681199func (app * BaseApp ) TxDecode (txBytes []byte ) (sdk.Tx , error ) {
0 commit comments