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 evaluation complexity of throw functions added #3788

Draft
wants to merge 3 commits into
base: version-1.4.x
Choose a base branch
from
Draft
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
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package com.wavesplatform.lang.evaluator

import cats.syntax.either.*
import com.wavesplatform.common.utils.EitherExt2
import com.wavesplatform.lang.Common
import com.wavesplatform.lang.{Common, CommonError}
import com.wavesplatform.lang.directives.DirectiveSet
import com.wavesplatform.lang.directives.values.*
import com.wavesplatform.lang.utils.lazyContexts
Expand Down Expand Up @@ -1251,4 +1251,59 @@ class EvaluatorV2Test extends PropSpec with Inside {
evalOld(script2, 100) shouldBe ((TRUE, "true", 5)) // 3 conditions + ref twice
evalNew(script2, 100) shouldBe ((TRUE, "true", 3)) // 3 function call
}

property("throw with message complexity") {
val script =
"""
|func a() = throw("xxx") # 1
|
|func f() =
| if (1 == 1) # 1
| then a()
| else false
|
|f()
""".stripMargin

var r = EvaluatorV2
.applyLimitedCoeval(
compile(script),
LogExtraInfo(),
10,
ctx.evaluationContext(environment),
V6,
correctFunctionCallScope = true,
newMode = true
)
.value()
r shouldBe Left(_: CommonError, 8, _: List[Any])
}

property("throw without message complexity") {
val script =
"""
|func a() = throw() # 1
|
|func f() =
| if (1 == 1) # 1
| then a()
| else false
|
|f()
""".stripMargin

var r = EvaluatorV2
.applyLimitedCoeval(
compile(script),
LogExtraInfo(),
10,
ctx.evaluationContext(environment),
V6,
correctFunctionCallScope = true,
newMode = true
)
.value()
r shouldBe Left(_: CommonError, 8, _: List[Any])
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import com.wavesplatform.common.state.ByteStr
import com.wavesplatform.common.utils.EitherExt2
import com.wavesplatform.db.{DBCacheSettings, WithDomain}
import com.wavesplatform.lagonaki.mocks.TestBlock
import com.wavesplatform.lang.directives.values.V5
import com.wavesplatform.lang.directives.values.{V5, V6}
import com.wavesplatform.lang.script.Script
import com.wavesplatform.lang.v1.compiler.TestCompiler
import com.wavesplatform.lang.v1.estimator.v3.ScriptEstimatorV3
Expand All @@ -25,6 +25,7 @@ class SyncInvokeDiffTest extends PropSpec with WithDomain with DBCacheSettings w
import DomainPresets._

private val fsWithV5 = RideV5.blockchainSettings.functionalitySettings
private val fsWithV6 = RideV6.blockchainSettings.functionalitySettings

private val invoker = TxHelpers.signer(0)
private val dApp = TxHelpers.signer(1)
Expand Down Expand Up @@ -1313,4 +1314,128 @@ class SyncInvokeDiffTest extends PropSpec with WithDomain with DBCacheSettings w
bc.balance(thirdAcc.toAddress, IssuedAsset(paymentIssue.id())) shouldBe paymentAssetAmount
}
}

property("Throw with message inside invoke") {
val script =
TestCompiler(V6).compileContract(
s"""
| @Callable(i)
| func bar() = throw("fail") # 1 (throw)
""".stripMargin
)

val script1 =
TestCompiler(V6).compileContract(
s"""
| @Callable(i)
| func foo() = {
| strict a = 1${" + 1" * 1000} # 1001 = 1000 (+) + 1 (strict)
| strict r = invoke(Alias("alias"), "bar", [], []) # 77 = 75 (invoke) + 1 (Alias) + 1 (strict)
| []
| }
""".stripMargin
)

val gTx1 = TxHelpers.genesis(dAppAddress)
val gTx2 = TxHelpers.genesis(invokerAddress)
val gTx3 = TxHelpers.genesis(thirdAcc.toAddress)

val aliasTx1 = TxHelpers.createAlias("alias", thirdAcc)
val ssTx = TxHelpers.setScript(dApp, script1)
val ssTx1 = TxHelpers.setScript(thirdAcc, script)
val invoke = TxHelpers.invoke(dAppAddress, Some("foo"), Nil, Nil, fee = TestValues.invokeFee(issues = 0))
val genesisTxs = Seq(gTx1, gTx2, gTx3, aliasTx1, ssTx1, ssTx)

assertDiffAndState(Seq(TestBlock.create(genesisTxs)), TestBlock.create(Seq(invoke), Block.ProtoBlockVersion), fsWithV6) {
case (diff, _) =>
diff.scriptsComplexity shouldBe 1079
}
}

property("Throw with message inside callable") {
val script =
TestCompiler(V6).compileContract(
s"""
| @Callable(i)
| func foo() = {
| let a = 1${" + 1" * 1000} # 1000 (+)
| if (a == 1) then [] else throw("xxx") # 2 = 1 (==) + 1 (throw)
| }
""".stripMargin
)

val gTx1 = TxHelpers.genesis(dAppAddress)
val gTx2 = TxHelpers.genesis(invokerAddress)

val ssTx = TxHelpers.setScript(dApp, script)
val invoke = TxHelpers.invoke(dAppAddress, Some("foo"), Nil, Nil, fee = TestValues.invokeFee(issues = 0))
val genesisTxs = Seq(gTx1, gTx2, ssTx)

assertDiffAndState(Seq(TestBlock.create(genesisTxs)), TestBlock.create(Seq(invoke), Block.ProtoBlockVersion), fsWithV6) {
case (diff, _) =>
diff.scriptsComplexity shouldBe 1002
}
}

property("Throw without message inside invoke") {
val script =
TestCompiler(V6).compileContract(
s"""
| @Callable(i)
| func bar() = throw() # 1 (throw)
""".stripMargin
)

val script1 =
TestCompiler(V6).compileContract(
s"""
| @Callable(i)
| func foo() = {
| strict a = 1${" + 1" * 1000} # 1001 = 1000 (+) + 1 (strict)
| strict r = invoke(Alias("alias"), "bar", [], []) # 77 = 75 (invoke) + 1 (Alias) + 1 (strict)
| []
| }
""".stripMargin
)

val gTx1 = TxHelpers.genesis(dAppAddress)
val gTx2 = TxHelpers.genesis(invokerAddress)
val gTx3 = TxHelpers.genesis(thirdAcc.toAddress)

val aliasTx1 = TxHelpers.createAlias("alias", thirdAcc)
val ssTx = TxHelpers.setScript(dApp, script1)
val ssTx1 = TxHelpers.setScript(thirdAcc, script)
val invoke = TxHelpers.invoke(dAppAddress, Some("foo"), Nil, Nil, fee = TestValues.invokeFee(issues = 0))
val genesisTxs = Seq(gTx1, gTx2, gTx3, aliasTx1, ssTx1, ssTx)

assertDiffAndState(Seq(TestBlock.create(genesisTxs)), TestBlock.create(Seq(invoke), Block.ProtoBlockVersion), fsWithV6) {
case (diff, _) =>
diff.scriptsComplexity shouldBe 1079
}
}

property("Throw without message inside callable") {
val script =
TestCompiler(V6).compileContract(
s"""
| @Callable(i)
| func foo() = {
| let a = 1${" + 1" * 1000} # 1000 (+)
| if (a == 1) then [] else throw() # 2 = 1 (==) + 1 (throw)
| }
""".stripMargin
)

val gTx1 = TxHelpers.genesis(dAppAddress)
val gTx2 = TxHelpers.genesis(invokerAddress)

val ssTx = TxHelpers.setScript(dApp, script)
val invoke = TxHelpers.invoke(dAppAddress, Some("foo"), Nil, Nil, fee = TestValues.invokeFee(issues = 0))
val genesisTxs = Seq(gTx1, gTx2, ssTx)

assertDiffAndState(Seq(TestBlock.create(genesisTxs)), TestBlock.create(Seq(invoke), Block.ProtoBlockVersion), fsWithV6) {
case (diff, _) =>
diff.scriptsComplexity shouldBe 1002
}
}
}