Skip to content

Commit

Permalink
Refactor 'invokeApplier.handleInvokeScriptInvocationError' method.
Browse files Browse the repository at this point in the history
  • Loading branch information
nickeskov committed Jul 1, 2022
1 parent 65c7a05 commit a1481c9
Showing 1 changed file with 21 additions and 32 deletions.
53 changes: 21 additions & 32 deletions pkg/state/invoke_applier.go
Original file line number Diff line number Diff line change
Expand Up @@ -902,60 +902,49 @@ func (ia *invokeApplier) applyInvokeScript(tx proto.Transaction, info *fallibleV
}

func (ia *invokeApplier) handleInvokeScriptInvocationError(
err error,
invErr error,
txID crypto.Digest,
failedChanges txBalanceChanges,
info *fallibleValidationParams,
) (*applicationResult, error) {
// Script returned error, it's OK, but we have to decide is it failed or rejected transaction.
// After activation of RideV6 feature transactions are failed if they are not cheap regardless the error kind.
isCheap := int(ia.sc.recentTxComplexity) <= FailFreeInvokeComplexity
if info.rideV6Activated {
if !info.acceptFailed || isCheap {
handleError := func(rejectTx bool) (*applicationResult, error) {
if rejectTx {
return nil, errors.Wrapf(
err, "transaction rejected with spent complexity %d and following call stack:\n%s",
ride.EvaluationErrorSpentComplexity(err),
strings.Join(ride.EvaluationErrorCallStack(err), "\n"),
invErr, "transaction rejected with spent complexity %d and following call stack:\n%s",
ride.EvaluationErrorSpentComplexity(invErr),
strings.Join(ride.EvaluationErrorCallStack(invErr), "\n"),
)
}
res := &invocationResult{failed: true, code: proto.DAppError, text: err.Error(), changes: failedChanges}
res := &invocationResult{failed: true, code: proto.DAppError, text: invErr.Error(), changes: failedChanges}
return ia.handleInvocationResult(txID, info, res)
}
// Script returned error, it's OK, but we have to decide is it failed or rejected transaction.
// After activation of RideV6 feature transactions are failed if they are not cheap regardless the error kind.
var (
isCheap = int(ia.sc.recentTxComplexity) <= FailFreeInvokeComplexity
rejectTx = !info.acceptFailed || isCheap // Reject transaction if no failed transactions or the transaction is cheap
)
if info.rideV6Activated {
return handleError(rejectTx)
}
// Before RideV6 activation in the following cases the transaction is rejected:
// 1) Failing of transactions is not activated yet, reject everything
// 2) The error is ride.InternalInvocationError and correct fail/reject behaviour is activated
// 3) The spent complexity is less than limit
switch ride.GetEvaluationErrorType(err) {
switch et := ride.GetEvaluationErrorType(invErr); et {
case ride.UserError, ride.RuntimeError:
// Usual script error produced by user code or system functions.
// We reject transaction if spent complexity is less than limit.
if !info.acceptFailed || isCheap { // Reject transaction if no failed transactions or the transaction is cheap
return nil, errors.Wrapf(
err, "transaction rejected with spent complexity %d and following call stack:\n%s",
ride.EvaluationErrorSpentComplexity(err),
strings.Join(ride.EvaluationErrorCallStack(err), "\n"),
)
}
res := &invocationResult{failed: true, code: proto.DAppError, text: err.Error(), changes: failedChanges}
return ia.handleInvocationResult(txID, info, res)
case ride.InternalInvocationError:
// Special script error produced by internal script invocation or application of results.
// Reject transaction after certain height
rejectOnInvocationError := info.checkerInfo.height >= ia.settings.InternalInvokeCorrectFailRejectBehaviourAfterHeight
if !info.acceptFailed || rejectOnInvocationError || isCheap {
return nil, errors.Wrapf(
err, "transaction rejected with spent complexity %d and following call stack:\n%s",
ride.EvaluationErrorSpentComplexity(err),
strings.Join(ride.EvaluationErrorCallStack(err), "\n"),
)
}
res := &invocationResult{failed: true, code: proto.DAppError, text: err.Error(), changes: failedChanges}
return ia.handleInvocationResult(txID, info, res)
rejectTx = rejectTx || info.checkerInfo.height >= ia.settings.InternalInvokeCorrectFailRejectBehaviourAfterHeight
case ride.Undefined, ride.EvaluationFailure: // Unhandled or evaluator error
return nil, errors.Wrapf(err, "invocation of transaction '%s' failed", txID.String())
return nil, errors.Wrapf(invErr, "invocation of transaction '%s' failed with error type (%T)", txID.String(), et)
default:
return nil, errors.Wrapf(err, "invocation of transaction '%s' failed", txID.String())
return nil, errors.Wrapf(invErr, "invocation of transaction '%s' failed with unknown error type (%T)", txID.String(), et)
}
return handleError(rejectTx)
}

type invocationResult struct {
Expand Down

0 comments on commit a1481c9

Please sign in to comment.