diff --git a/action/const.go b/action/const.go index 4742216401..37ed32d4c6 100644 --- a/action/const.go +++ b/action/const.go @@ -44,6 +44,7 @@ var ( ErrGasTipOverFeeCap = errors.New("tip cap is greater than fee cap") ErrMissRequiredField = errors.New("missing required field") ErrValueVeryHigh = errors.New("value is very high") + ErrPanicButReverted = errors.New("panic but reverted") ) // LoadErrorDescription loads corresponding description related to the error diff --git a/state/factory/workingset.go b/state/factory/workingset.go index cb28cf880a..c3d7d92d7e 100644 --- a/state/factory/workingset.go +++ b/state/factory/workingset.go @@ -168,7 +168,7 @@ func withActionCtx(ctx context.Context, selp *action.SealedEnvelope) (context.Co func (ws *workingSet) runAction( ctx context.Context, selp *action.SealedEnvelope, -) (*action.Receipt, error) { +) (receipt *action.Receipt, err error) { actCtx := protocol.MustGetActionCtx(ctx) if protocol.MustGetBlockCtx(ctx).GasLimit < actCtx.IntrinsicGas { return nil, action.ErrGasLimit @@ -207,6 +207,17 @@ func (ws *workingSet) runAction( return nil, errors.Wrapf(err, "Failed to get hash") } defer ws.ResetSnapshots() + sn := ws.Snapshot() + defer func() { + if r := recover(); r != nil { + receipt = nil + if e := ws.Revert(sn); e != nil { + err = errors.Wrapf(e, "panic and recovered but failed to revert when running action: %v", r) + return + } + err = errors.Wrapf(action.ErrPanicButReverted, "panic and reverted when running action: %v", r) + } + }() if err := ws.freshAccountConversion(ctx, &actCtx); err != nil { return nil, err } @@ -736,6 +747,8 @@ func (ws *workingSet) pickAndRunActions( actionIterator.PopAccount() continue } + actCtx := protocol.MustGetActionCtx(actionCtx) + l := log.L().With(log.Hex("actHash", actCtx.ActionHash[:]), zap.Uint64("height", ws.height)) receipt, err := ws.runAction(actionCtx, nextAction) switch errors.Cause(err) { case nil: @@ -744,7 +757,12 @@ func (ws *workingSet) pickAndRunActions( actionIterator.PopAccount() continue case action.ErrChainID, errUnfoldTxContainer, errDeployerNotWhitelisted: - log.L().Debug("runAction() failed", zap.Uint64("height", ws.height), zap.Error(err)) + l.Debug("runAction() failed", zap.Error(err)) + ap.DeleteAction(caller) + actionIterator.PopAccount() + continue + case action.ErrPanicButReverted: + l.Warn("runAction() panic but reverted", zap.Error(err)) ap.DeleteAction(caller) actionIterator.PopAccount() continue