Skip to content

Commit ec4c8bf

Browse files
committed
Nullify failed invoke complexity in case of 'InternalInvocationError' and tx depth level is 2 or less.
1 parent 7549046 commit ec4c8bf

File tree

1 file changed

+30
-20
lines changed

1 file changed

+30
-20
lines changed

pkg/ride/tree_evaluation.go

Lines changed: 30 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,7 @@ func CallFunction(env environment, tree *ast.Tree, name string, args proto.Argum
3535
if err != nil {
3636
// Evaluation failed we have to return a DAppResult that contains spent execution complexity
3737
// Produced actions are not stored for failed transactions, no need to return them here
38-
et := GetEvaluationErrorType(err)
39-
complexity := complexityInCaseOfEvaluationError(et, e, env)
40-
if et == Undefined {
41-
return nil, EvaluationErrorAddComplexity(et.Wrap(err, "unhandled error"), complexity)
42-
}
43-
return nil, EvaluationErrorAddComplexity(err, complexity)
38+
return nil, handleComplexityInCaseOfEvaluationError(err, e, env)
4439
}
4540
dAppResult, ok := rideResult.(DAppResult)
4641
if !ok { // Unexpected result type
@@ -88,21 +83,36 @@ func wrappedStateActions(state types.SmartState) []proto.ScriptAction {
8883
return ws.act
8984
}
9085

91-
func complexityInCaseOfEvaluationError(et EvaluationError, e *treeEvaluator, env environment) int {
86+
func evaluationErrorSetComplexity(err error, complexity int) error {
87+
if ee, ok := err.(evaluationError); ok {
88+
ee.spentComplexity = complexity
89+
return ee
90+
}
91+
return err
92+
}
93+
94+
func handleComplexityInCaseOfEvaluationError(err error, e *treeEvaluator, env environment) error {
9295
// Error was not handled in wrapped state properly,
93-
// so we need to add both complexity from current evaluation and from internal invokes
94-
complexity := e.complexity() + wrappedStateComplexity(env.state())
95-
// reproduce scala's node buggy behaviour
96-
if ws, ok := env.state().(*WrappedState); ok && env.rideV5Activated() && !env.rideV6Activated() && et == InternalInvocationError {
97-
// if invoke script tx depth level is 2 or less ==> complexity should be set to 0
98-
// invCount() is calls count of invoke() or reentrantInvoke() functions ==> txDepthLevel = 1 + invCount()
99-
if txDepthLevel := 1 + ws.invCount(); txDepthLevel <= 2 {
100-
complexity = 0
101-
} else {
102-
// if depth level is 3 or greater, then we should sub last two invoke complexities plus
103-
// cost of the last invoke() or reentrantInvoke() function call
104-
complexity -= ws.lastTwoInvokeComplexities.sum() + invokeCallComplexityV5
96+
// so we need to add complexities from current evaluation, from internal invokes and from internal failed invoke
97+
totalComplexity := e.complexity() + wrappedStateComplexity(env.state()) + EvaluationErrorSpentComplexity(err)
98+
switch et := GetEvaluationErrorType(err); et {
99+
case Undefined:
100+
return evaluationErrorSetComplexity(et.Wrap(err, "unhandled error"), totalComplexity)
101+
case InternalInvocationError:
102+
// reproduce scala's node buggy behaviour
103+
if ws, ok := env.state().(*WrappedState); ok && env.rideV5Activated() && !env.rideV6Activated() {
104+
// if invoke script tx depth level is 2 or less ==> complexity should be set to 0
105+
// invCount() is calls count of invoke() or reentrantInvoke() functions ==> txDepthLevel = 1 + invCount()
106+
if txDepthLevel := 1 + ws.invCount(); txDepthLevel <= 2 {
107+
totalComplexity = 0
108+
} else {
109+
// if depth level is 3 or greater, then we should sub last two invoke complexities plus
110+
// cost of the last invoke() or reentrantInvoke() function call
111+
totalComplexity -= ws.lastTwoInvokeComplexities.sum() + invokeCallComplexityV5
112+
}
105113
}
114+
return evaluationErrorSetComplexity(err, totalComplexity)
115+
default:
116+
return evaluationErrorSetComplexity(err, totalComplexity)
106117
}
107-
return complexity
108118
}

0 commit comments

Comments
 (0)