Skip to content

Commit

Permalink
refactor: Sync with original cosmos-sdk
Browse files Browse the repository at this point in the history
  • Loading branch information
dudong2 committed Jan 15, 2025
1 parent 3c1f7a0 commit 49a6b7c
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 102 deletions.
9 changes: 6 additions & 3 deletions baseapp/abci.go
Original file line number Diff line number Diff line change
Expand Up @@ -347,7 +347,7 @@ func (app *BaseApp) CheckTxSync(req *abci.RequestCheckTx) (*abci.ResponseCheckTx
return nil, fmt.Errorf("unknown RequestCheckTx type: %s", req.Type)
}

tx, err := app.preCheckTx(req.Tx)
tx, err := app.txDecoder(req.Tx)
if err != nil {
return sdkerrors.ResponseCheckTxWithEvents(err, 0, 0, nil, false), err
}
Expand All @@ -357,13 +357,16 @@ func (app *BaseApp) CheckTxSync(req *abci.RequestCheckTx) (*abci.ResponseCheckTx
waitWgs(waits)
defer app.checkAccountWGs.Done(signals)

gInfo, err := app.checkTx(mode, req.Tx, tx)
gInfo, result, anteEvents, err := app.runTx(mode, req.Tx)
if err != nil {
return sdkerrors.ResponseCheckTxWithEvents(err, gInfo.GasWanted, gInfo.GasUsed, nil, false), nil
return sdkerrors.ResponseCheckTxWithEvents(err, gInfo.GasWanted, gInfo.GasUsed, anteEvents, app.trace), nil
}
return &abci.ResponseCheckTx{
GasWanted: int64(gInfo.GasWanted), // TODO: Should type accept unsigned ints?
GasUsed: int64(gInfo.GasUsed), // TODO: Should type accept unsigned ints?
Log: result.Log,
Data: result.Data,
Events: sdk.MarkEventsToIndex(result.Events, app.indexEvents),
}, nil
}

Expand Down
142 changes: 46 additions & 96 deletions baseapp/baseapp.go
Original file line number Diff line number Diff line change
Expand Up @@ -748,84 +748,6 @@ func (app *BaseApp) cacheTxContext(ctx sdk.Context, txBytes []byte) (sdk.Context
return ctx.WithMultiStore(msCache), msCache
}

// stateless checkTx
func (app *BaseApp) preCheckTx(txBytes []byte) (tx sdk.Tx, err error) {
defer func() {
if r := recover(); r != nil {
recoveryMW := newDefaultRecoveryMiddleware()
err = processRecovery(r, recoveryMW)
}
}()

tx, err = app.txDecoder(txBytes)
if err != nil {
return tx, err
}

msgs := tx.GetMsgs()
err = validateBasicTxMsgs(msgs)

return tx, err
}

func (app *BaseApp) checkTx(mode execMode, txBytes []byte, tx sdk.Tx) (gInfo sdk.GasInfo, err error) {
ctx := app.getContextForTx(mode, txBytes, -1)
gasCtx := &ctx

defer func() {
if r := recover(); r != nil {
recoveryMW := newDefaultRecoveryMiddleware()
err = processRecovery(r, recoveryMW)
}
gInfo = sdk.GasInfo{GasWanted: gasCtx.GasMeter().Limit(), GasUsed: gasCtx.GasMeter().GasConsumed()}
}()

var anteCtx sdk.Context
anteCtx, err = app.anteTx(ctx, txBytes, tx, false)
if !anteCtx.IsZero() {
gasCtx = &anteCtx
}

if mode == execModeCheck {
err = app.mempool.Insert(ctx, tx)
if err != nil {
return gInfo, err
}
}

return gInfo, err
}

func (app *BaseApp) anteTx(ctx sdk.Context, txBytes []byte, tx sdk.Tx, simulate bool) (sdk.Context, error) {
if app.anteHandler == nil {
return ctx, nil
}

// Branch context before AnteHandler call in case it aborts.
// This is required for both CheckTx and DeliverTx.
// Ref: https://github.com/cosmos/cosmos-sdk/issues/2772
//
// NOTE: Alternatively, we could require that AnteHandler ensures that
// writes do not happen if aborted/failed. This may have some
// performance benefits, but it'll be more difficult to get right.
anteCtx, msCache := app.cacheTxContext(ctx, txBytes)
anteCtx = anteCtx.WithEventManager(sdk.NewEventManager())
newCtx, err := app.anteHandler(anteCtx, tx, simulate)

if err != nil {
if ctx.IsReCheckTx() {
// if the ante handler fails on recheck, we want to remove the tx from the mempool
if mempoolErr := app.mempool.Remove(tx); mempoolErr != nil {
return newCtx, errors.Join(err, mempoolErr)
}
}
return newCtx, err
}

msCache.Write()
return newCtx, nil
}

func (app *BaseApp) preBlock(req *abci.RequestFinalizeBlock) ([]abci.Event, error) {
var events []abci.Event
if app.preBlocker != nil {
Expand Down Expand Up @@ -1030,30 +952,58 @@ func (app *BaseApp) runTxWithMultiStore(
}
}

var newCtx sdk.Context
newCtx, err = app.anteTx(ctx, txBytes, tx, mode == execModeSimulate)
if !newCtx.IsZero() {
// At this point, newCtx.MultiStore() is a store branch, or something else
// replaced by the AnteHandler. We want the original multistore.
if app.anteHandler != nil {
var (
anteCtx sdk.Context
msCache storetypes.CacheMultiStore
)

// Branch context before AnteHandler call in case it aborts.
// This is required for both CheckTx and DeliverTx.
// Ref: https://github.com/cosmos/cosmos-sdk/issues/2772
//
// Also, in the case of the tx aborting, we need to track gas consumed via
// the instantiated gas meter in the AnteHandler, so we update the context
// prior to returning.
ctx = newCtx.WithMultiStore(ms)
}
// NOTE: Alternatively, we could require that AnteHandler ensures that
// writes do not happen if aborted/failed. This may have some
// performance benefits, but it'll be more difficult to get right.
anteCtx, msCache = app.cacheTxContext(ctx, txBytes)
anteCtx = anteCtx.WithEventManager(sdk.NewEventManager())
newCtx, err := app.anteHandler(anteCtx, tx, mode == execModeSimulate)

if !newCtx.IsZero() {
// At this point, newCtx.MultiStore() is a store branch, or something else
// replaced by the AnteHandler. We want the original multistore.
//
// Also, in the case of the tx aborting, we need to track gas consumed via
// the instantiated gas meter in the AnteHandler, so we update the context
// prior to returning.
ctx = newCtx.WithMultiStore(ms)
}

events := ctx.EventManager().Events()
events := ctx.EventManager().Events()

// GasMeter expected to be set in AnteHandler
gasWanted = ctx.GasMeter().Limit()
// GasMeter expected to be set in AnteHandler
gasWanted = ctx.GasMeter().Limit()

if err != nil {
return gInfo, nil, nil, err
}
if err != nil {
if mode == execModeReCheck {
// if the ante handler fails on recheck, we want to remove the tx from the mempool
if mempoolErr := app.mempool.Remove(tx); mempoolErr != nil {
return gInfo, nil, anteEvents, errors.Join(err, mempoolErr)
}
}
return gInfo, nil, nil, err
}

anteEvents = events.ToABCIEvents()
msCache.Write()
anteEvents = events.ToABCIEvents()
}

if mode == execModeFinalize {
if mode == execModeCheck {
err = app.mempool.Insert(ctx, tx)
if err != nil {
return gInfo, nil, anteEvents, err
}
} else if mode == execModeFinalize {
err = app.mempool.Remove(tx)
if err != nil && !errors.Is(err, mempool.ErrTxNotFound) {
return gInfo, nil, anteEvents,
Expand Down
9 changes: 6 additions & 3 deletions baseapp/reactor.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ func (app *BaseApp) checkTxAsyncReactor() {

func (app *BaseApp) prepareCheckTx(req *RequestCheckTxAsync) {
defer req.prepare.Done()
req.tx, req.err = app.preCheckTx(req.txBytes)
req.tx, req.err = app.txDecoder(req.txBytes)
}

func (app *BaseApp) checkTxAsync(req *RequestCheckTxAsync, waits []*sync.WaitGroup, signals []*AccountWG) {
Expand All @@ -62,14 +62,17 @@ func (app *BaseApp) checkTxAsync(req *RequestCheckTxAsync, waits []*sync.WaitGro
panic(fmt.Sprintf("unknown RequestCheckTx type: %s", req.txType))
}

gInfo, err := app.checkTx(mode, req.txBytes, req.tx)
gInfo, result, anteEvents, err := app.runTx(mode, req.txBytes)
if err != nil {
req.callback(sdkerrors.ResponseCheckTxWithEvents(err, gInfo.GasWanted, gInfo.GasUsed, nil, false))
req.callback(sdkerrors.ResponseCheckTxWithEvents(err, gInfo.GasWanted, gInfo.GasUsed, anteEvents, app.trace))
return
}

req.callback(&abci.ResponseCheckTx{
GasWanted: int64(gInfo.GasWanted), // TODO: Should type accept unsigned ints?
GasUsed: int64(gInfo.GasUsed), // TODO: Should type accept unsigned ints?
Log: result.Log,
Data: result.Data,
Events: sdk.MarkEventsToIndex(result.Events, app.indexEvents),
})
}

0 comments on commit 49a6b7c

Please sign in to comment.