Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tests on correct scopes handling by estimator and evaluator added. #1264

Merged
merged 4 commits into from
Dec 18, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 15 additions & 6 deletions pkg/ride/compiler/ast_parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ func (p *astParser) addError(token token32, format string, args ...any) {
}

func (p *astParser) loadBuildInVarsToStackByVersion() {
resVars := make(map[string]s.Variable, 0)
resVars := make(map[string]s.Variable)
ver := int(p.tree.LibVersion)
for i := 0; i < ver; i++ {
for _, v := range s.Vars().Vars[i].Append {
Expand Down Expand Up @@ -912,6 +912,8 @@ func (p *astParser) ruleListGroupOpAtomHandler(node *node32) (ast.Node, s.Type)
p.addError(curNode.token32, "Unexpected types for '++' operator '%s' and '%s'", varType, nextVarType)
return nil, nil
}
default:
panic("unhandled default case")
}
expr = ast.NewFunctionCallNode(funcId, []ast.Node{expr, nextExpr})
curNode = curNode.next
Expand Down Expand Up @@ -2357,12 +2359,19 @@ func (p *astParser) ruleFoldMacroHandler(node *node32) (ast.Node, s.Type) {
}
curNode = skipToNextRule(curNode.next)
arr, arrVarType := p.ruleExprHandler(curNode)
var elemType s.Type
if l, ok := arrVarType.(s.ListType); !ok {
p.addError(curNode.token32, "First argument of fold must be List, but '%s' found", arrVarType.String())
if arr == nil {
p.addError(curNode.token32, "Undefined first argument of FOLD macros")
return nil, nil
} else {
elemType = l.Type
}
l, ok := arrVarType.(s.ListType)
if !ok {
p.addError(curNode.token32, "First argument of FOLD macros must be List, but '%s' found",
arrVarType.String())
return nil, nil
}
elemType := l.Type
if elemType == nil { // If the type of elements is unknown, set it to Any.
elemType = s.AnyType
}
curNode = skipToNextRule(curNode.next)
start, startVarType := p.ruleExprHandler(curNode)
Expand Down
10 changes: 9 additions & 1 deletion pkg/ride/compiler/ast_parser_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -260,9 +260,17 @@ let arr = [1,2,3,4,5]
let a = FOLD<5>(arr, [], filterEven)
`, false, "BgICCAIDAQpmaWx0ZXJFdmVuAgVhY2N1bQRuZXh0AwkAAAIJAGoCBQRuZXh0AAIAAAkAzQgCBQVhY2N1bQUEbmV4dAUFYWNjdW0AA2FycgkAzAgCAAEJAMwIAgACCQDMCAIAAwkAzAgCAAQJAMwIAgAFBQNuaWwAAWEKAAIkbAUDYXJyCgACJHMJAJADAQUCJGwKAAUkYWNjMAUDbmlsCgEFJGYwXzECAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAQpmaWx0ZXJFdmVuAgUCJGEJAJEDAgUCJGwFAiRpCgEFJGYwXzICAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAAIBAhNMaXN0IHNpemUgZXhjZWVkcyA1CQEFJGYwXzICCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECBQUkYWNjMAAAAAEAAgADAAQABQAAWwkCmw=="},
{`
func sum(accum: Int, next: Int) = accum + next
let arr = []
let a = FOLD<5>(arr, 0, sum)
`, false, "BgICCAIDAQNzdW0CBWFjY3VtBG5leHQJAGQCBQVhY2N1bQUEbmV4dAADYXJyBQNuaWwAAWEKAAIkbAUDYXJyCg" +
"ACJHMJAJADAQUCJGwKAAUkYWNjMAAACgEFJGYwXzECAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAQNzdW0CBQIkYQkAkQMCBQIkbA" +
"UCJGkKAQUkZjBfMgICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkAAgECE0xpc3Qgc2l6ZSBleGNlZWRzIDUJAQUkZjBfMgIJAQUkZj" +
"BfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIFBSRhY2MwAAAAAQACAAMABAAFAABmy6Xs"},
{`
func sum(a:Int, b:Int) = a + b
let a = FOLD<5>(1, 9, sum)
`, true, "(6:17, 6:18): First argument of fold must be List, but 'Int' found"},
`, true, "(6:17, 6:18): First argument of FOLD macros must be List, but 'Int' found"},
{`
func sum(a:Int, b:String) = a
let b = FOLD<5>([1], 0, sum)
Expand Down
2 changes: 1 addition & 1 deletion pkg/ride/compiler/stdlib/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,7 @@ func (t SimpleType) Equal(other Type) bool {
if o, ok := other.(SimpleType); ok {
return t.Type == o.Type
}
return false
return other.Equal(AnyType)
}

func (t SimpleType) String() string {
Expand Down
129 changes: 112 additions & 17 deletions pkg/ride/tree_estimation_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -389,29 +389,124 @@ func TestFailOnInvocationInVerifier(t *testing.T) {
}

func TestScope(t *testing.T) {
src := `
{-# STDLIB_VERSION 5 #-}
for _, test := range []struct {
source string
estimation int
estimations map[string]int
}{
{`
{-# STDLIB_VERSION 6 #-}
{-# CONTENT_TYPE DAPP #-}
{-# SCRIPT_TYPE ACCOUNT #-}

let a = {
func bar(i: Int) = i
bar(1)
func bar(i: Int) = i
bar(1)
}
let b = {
func bar(i: Int) = i
bar(a)
}
@Callable(i)
func empty() = [IntegerEntry("empty", 0)]
@Callable(i)
func aa() = [IntegerEntry("a", a)]
@Callable(i)
func bb() = [IntegerEntry("b", b)]
`,
0, map[string]int{"empty": 3, "aa": 3 + 1, "bb": 3 + 2},
},
{`
{-# STDLIB_VERSION 6 #-}
{-# CONTENT_TYPE DAPP #-}
{-# SCRIPT_TYPE ACCOUNT #-}
let a = {
func bar(i: Int) = i
bar(1)
}
let b = {
let c = {
let d = {
func bar(i: Int) = i
bar(a)
}
func bar(i: Int) = i
bar(d)
}
func bar(i: Int) = i
bar(c)
}
let e = {
func bar(i: Int) = i
bar(b)
}
@Callable(i)
func aa() = [IntegerEntry("a", a)]
@Callable(i)
func bb() = [IntegerEntry("b", b)]
@Callable(i)
func ee() = [IntegerEntry("e", e)]
`,
0, map[string]int{"aa": 3 + 1, "bb": 3 + 4, "ee": 3 + 5},
},
{`
{-# STDLIB_VERSION 6 #-}
{-# CONTENT_TYPE DAPP #-}
{-# SCRIPT_TYPE ACCOUNT #-}
let l = []
let a = {
func foo(fooAcc: Int, i: Int) = fooAcc + i
FOLD<1>(l, 0, foo)
}
let b = {
func bar(i: Int) = i
bar(a)
func bar(barAcc: Int, i: Int) = barAcc + i
FOLD<1>(l, a, bar)
}
@Callable(i)
func aa() = [IntegerEntry("a", a)]
@Callable(i)
func bb() = [IntegerEntry("b", b)]
`,
0, map[string]int{"aa": 3 + 8, "bb": 3 + 16},
},
{`
{-# STDLIB_VERSION 6 #-}
{-# CONTENT_TYPE DAPP #-}
{-# SCRIPT_TYPE ACCOUNT #-}
let a = 1 + 1 + 1
let b = a + 1 + 1
let c = b + a + 1

@Callable(i)
func aa() = [IntegerEntry("a", a)]
@Callable(i)
func bb() = [IntegerEntry("b", b)]
@Callable(i)
func cc() = [IntegerEntry("c", c)]
`,
0, map[string]int{"aa": 3 + 2, "bb": 3 + 4, "cc": 3 + 6},
},
{`{-# STDLIB_VERSION 6 #-}
{-# CONTENT_TYPE DAPP #-}
{-# SCRIPT_TYPE ACCOUNT #-}
let a = groth16Verify(base58'', base58'', base58'')
func f(a: Boolean) = a
@Verifier(tx)
func verify() = a == b
`
tree, errs := ridec.CompileToTree(src)
require.Empty(t, errs)
func verify() = f(true)`,
2701, nil,
},
} {
tree, errs := ridec.CompileToTree(test.source)
require.Empty(t, errs, test.source)

est, err := EstimateTree(tree, 3)
assert.NoError(t, err)
assert.Equal(t, 7, est.Estimation)
est, err = EstimateTree(tree, 4)
assert.NoError(t, err)
assert.Equal(t, 3, est.Estimation)
est, err := EstimateTree(tree, 4)
assert.NoError(t, err, test.source)
if test.estimation > 0 {
assert.Equal(t, test.estimation, est.Estimation)
}
for fn, ee := range test.estimations {
ae, ok := est.Functions[fn]
require.True(t, ok)
assert.Equal(t, ee, ae, test.source)
}
}
}
62 changes: 62 additions & 0 deletions pkg/ride/tree_evaluation_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5795,3 +5795,65 @@ func TestHitInDeepInvocationsLimit(t *testing.T) {
_, err := CallFunction(env.toEnv(), tree1, proto.NewFunctionCall("foo", proto.Arguments{}))
assert.EqualError(t, err, "invoke: too many internal invocations")
}

func TestGlobalDeclarationScopesEvaluation(t *testing.T) {
dApp1 := newTestAccount(t, "DAPP1") // 3MzDtgL5yw73C2xVLnLJCrT5gCL4357a4sz
sender := newTestAccount(t, "SENDER") // 3N8CkZAyS4XcDoJTJoKNuNk2xmNKmQj7myW

src := `
{-# STDLIB_VERSION 6 #-}
{-# CONTENT_TYPE DAPP #-}
{-# SCRIPT_TYPE ACCOUNT #-}

let a = {
func bar(i: Int) = i
bar(1)
}
let b = {
let c = {
let d = {
func bar(i: Int) = i + 1
bar(a)
}
func bar(i: Int) = i * 2
bar(d)
}
func bar(i: Int) = i + 1
bar(c)
}

@Callable(i)
func foo() = {
[IntegerEntry("key", b)]
}
`
tree, errs := ridec.CompileToTree(src)
require.Empty(t, errs)

env := newTestEnv(t).withLibVersion(ast.LibV6).withComplexityLimit(ast.LibV6, 52000).
withBlockV5Activated().withProtobufTx().withRideV6Activated().
withDataEntriesSizeV2().withMessageLengthV3().withValidateInternalPayments().
withThis(dApp1).withDApp(dApp1).withSender(sender).
withInvocation("foo", withTransactionID(crypto.Digest{})).withTree(dApp1, tree).
withWrappedState()
res, err := CallFunction(env.toEnv(), tree, proto.NewFunctionCall("foo", proto.Arguments{}))
require.NoError(t, err)
assert.Equal(t, 1, len(res.ScriptActions()))
r, ok := res.(DAppResult)
require.True(t, ok)

sr, _, err := proto.NewScriptResult(r.actions, proto.ScriptErrorMessage{})
require.NoError(t, err)
expectedResult := &proto.ScriptResult{
DataEntries: []*proto.DataEntryScriptAction{{Entry: &proto.IntegerDataEntry{Key: "key", Value: 5}}},
Transfers: make([]*proto.TransferScriptAction, 0),
Issues: make([]*proto.IssueScriptAction, 0),
Reissues: make([]*proto.ReissueScriptAction, 0),
Burns: make([]*proto.BurnScriptAction, 0),
Sponsorships: make([]*proto.SponsorshipScriptAction, 0),
Leases: make([]*proto.LeaseScriptAction, 0),
LeaseCancels: make([]*proto.LeaseCancelScriptAction, 0),
ErrorMsg: proto.ScriptErrorMessage{},
}
assert.Equal(t, expectedResult, sr)
}
Loading