Skip to content

Commit b95ac07

Browse files
committed
Reproduce scala's node buggy behaviour in complexity calculations after RideV5 and before RideV6.
1 parent ca3442e commit b95ac07

File tree

3 files changed

+38
-14
lines changed

3 files changed

+38
-14
lines changed

pkg/ride/environment.go

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,20 @@ import (
1010
"github.com/wavesplatform/gowaves/pkg/util/common"
1111
)
1212

13-
const invokeCallComplexityV5 = 75
14-
1513
var (
1614
errDeletedEntry = errors.New("entry has been deleted")
1715
)
1816

17+
type lastTwoInvokeComplexities [2]int
18+
19+
func (l *lastTwoInvokeComplexities) pushComplexity(complexity int) {
20+
l[0], l[1] = l[1], complexity
21+
}
22+
23+
func (l *lastTwoInvokeComplexities) sum() int {
24+
return l[0] + l[1]
25+
}
26+
1927
type WrappedState struct {
2028
diff diffState
2129
cle rideAddress
@@ -27,6 +35,7 @@ type WrappedState struct {
2735
dataEntriesSize int
2836
rootScriptLibVersion ast.LibraryVersion
2937
rootActionsCountValidator proto.ActionsCountValidator
38+
lastTwoInvokeComplexities lastTwoInvokeComplexities
3039
}
3140

3241
func newWrappedState(env *EvaluationEnvironment, rootScriptLibVersion ast.LibraryVersion) *WrappedState {

pkg/ride/functions_proto.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,8 @@ func performInvoke(invocation invocation, env environment, args ...rideType) (ri
239239
env.setInvocation(oldInvocationParam)
240240

241241
ws.totalComplexity += res.Complexity()
242+
// need to reproduce scala's node buggy behaviour in complexity calculations after RideV5 and before RideV6
243+
ws.lastTwoInvokeComplexities.pushComplexity(res.Complexity())
242244

243245
if res.userResult() == nil {
244246
return rideUnit{}, nil

pkg/ride/tree_evaluation.go

Lines changed: 25 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@ import (
66
"github.com/wavesplatform/gowaves/pkg/types"
77
)
88

9+
// invokeCallComplexityV5 is invoke() or reentrantInvoke() functions cost for RideV5
10+
const invokeCallComplexityV5 = 75
11+
912
func CallVerifier(env environment, tree *ast.Tree) (Result, error) {
1013
e, err := treeVerifierEvaluator(env, tree)
1114
if err != nil {
@@ -33,26 +36,17 @@ func CallFunction(env environment, tree *ast.Tree, name string, args proto.Argum
3336
// Evaluation failed we have to return a DAppResult that contains spent execution complexity
3437
// Produced actions are not stored for failed transactions, no need to return them here
3538
et := GetEvaluationErrorType(err)
39+
complexity := complexityInCaseOfEvaluationError(et, e, env)
3640
if et == Undefined {
37-
return nil, EvaluationErrorAddComplexity(
38-
et.Wrap(err, "unhandled error"),
39-
// Error was not handled in wrapped state properly,
40-
// so we need to add both complexity from current evaluation and from internal invokes
41-
e.complexity()+wrappedStateComplexity(env.state()),
42-
)
43-
}
44-
complexity := e.complexity() + wrappedStateComplexity(env.state())
45-
if env.rideV5Activated() && !env.rideV6Activated() && et == InternalInvocationError {
46-
ws := env.state().(*WrappedState)
47-
// TODO: this should be handled only when err == ride.InternalInvocationError
41+
return nil, EvaluationErrorAddComplexity(et.Wrap(err, "unhandled error"), complexity)
4842
}
4943
return nil, EvaluationErrorAddComplexity(err, complexity)
5044
}
5145
dAppResult, ok := rideResult.(DAppResult)
5246
if !ok { // Unexpected result type
5347
return nil, EvaluationErrorAddComplexity(
5448
EvaluationFailure.Errorf("invalid result of call function '%s'", name),
55-
// New error, both complexities should be added
49+
// New error, both complexities should be added (also see comment in complexityInCaseOfEvaluationError)
5650
e.complexity()+wrappedStateComplexity(env.state()),
5751
)
5852
}
@@ -93,3 +87,22 @@ func wrappedStateActions(state types.SmartState) []proto.ScriptAction {
9387
}
9488
return ws.act
9589
}
90+
91+
func complexityInCaseOfEvaluationError(et EvaluationError, e *treeEvaluator, env environment) int {
92+
// 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 nesting level is 2 or less ==> complexity should be set to 0
98+
// invCount() is calls count of invoke() or reentrantInvoke() functions ==> txNestingLevel = 1 + invCount()
99+
if txNestingLevel := 1 + ws.invCount(); txNestingLevel <= 2 {
100+
complexity = 0
101+
} else {
102+
// if nesting 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
105+
}
106+
}
107+
return complexity
108+
}

0 commit comments

Comments
 (0)