From bc667757711b0ffd06dcff45b64d612a568eb334 Mon Sep 17 00:00:00 2001 From: Alexey Kiselev Date: Tue, 8 Nov 2022 15:52:16 +0400 Subject: [PATCH 1/3] Tests on evaluation complexity of throw functions added --- .../lang/evaluator/EvaluatorV2Test.scala | 57 +++++++++++++- .../diffs/ci/sync/SyncInvokeDiffTest.scala | 77 ++++++++++++++++++- 2 files changed, 132 insertions(+), 2 deletions(-) diff --git a/lang/tests/src/test/scala/com/wavesplatform/lang/evaluator/EvaluatorV2Test.scala b/lang/tests/src/test/scala/com/wavesplatform/lang/evaluator/EvaluatorV2Test.scala index 32372cc06db..96a4488e641 100644 --- a/lang/tests/src/test/scala/com/wavesplatform/lang/evaluator/EvaluatorV2Test.scala +++ b/lang/tests/src/test/scala/com/wavesplatform/lang/evaluator/EvaluatorV2Test.scala @@ -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 @@ -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), + version, + 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), + version, + correctFunctionCallScope = true, + newMode = true + ) + .value() + r shouldBe Left(_: CommonError, 8, _: List[Any]) + } } + diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/ci/sync/SyncInvokeDiffTest.scala b/node/src/test/scala/com/wavesplatform/state/diffs/ci/sync/SyncInvokeDiffTest.scala index 0c355a040c3..7056f329587 100644 --- a/node/src/test/scala/com/wavesplatform/state/diffs/ci/sync/SyncInvokeDiffTest.scala +++ b/node/src/test/scala/com/wavesplatform/state/diffs/ci/sync/SyncInvokeDiffTest.scala @@ -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 @@ -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) @@ -1313,4 +1314,78 @@ 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 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 + } + } } From 92287db0e233836f438becf6c2103e481449a971 Mon Sep 17 00:00:00 2001 From: Alexey Kiselev Date: Tue, 8 Nov 2022 16:07:09 +0400 Subject: [PATCH 2/3] Set context version in new tests to V6 --- .../com/wavesplatform/lang/evaluator/EvaluatorV2Test.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lang/tests/src/test/scala/com/wavesplatform/lang/evaluator/EvaluatorV2Test.scala b/lang/tests/src/test/scala/com/wavesplatform/lang/evaluator/EvaluatorV2Test.scala index 96a4488e641..839504d7c00 100644 --- a/lang/tests/src/test/scala/com/wavesplatform/lang/evaluator/EvaluatorV2Test.scala +++ b/lang/tests/src/test/scala/com/wavesplatform/lang/evaluator/EvaluatorV2Test.scala @@ -1271,7 +1271,7 @@ class EvaluatorV2Test extends PropSpec with Inside { LogExtraInfo(), 10, ctx.evaluationContext(environment), - version, + V6, correctFunctionCallScope = true, newMode = true ) @@ -1298,7 +1298,7 @@ class EvaluatorV2Test extends PropSpec with Inside { LogExtraInfo(), 10, ctx.evaluationContext(environment), - version, + V6, correctFunctionCallScope = true, newMode = true ) From 4fb1b85ee79ae3a2dd49542beb53412a706ca7cf Mon Sep 17 00:00:00 2001 From: Alexey Kiselev Date: Wed, 9 Nov 2022 12:11:31 +0400 Subject: [PATCH 3/3] Added tests on throw functions complexity inside callable functions. --- .../diffs/ci/sync/SyncInvokeDiffTest.scala | 50 +++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/ci/sync/SyncInvokeDiffTest.scala b/node/src/test/scala/com/wavesplatform/state/diffs/ci/sync/SyncInvokeDiffTest.scala index 7056f329587..7bba251439e 100644 --- a/node/src/test/scala/com/wavesplatform/state/diffs/ci/sync/SyncInvokeDiffTest.scala +++ b/node/src/test/scala/com/wavesplatform/state/diffs/ci/sync/SyncInvokeDiffTest.scala @@ -1352,6 +1352,31 @@ class SyncInvokeDiffTest extends PropSpec with WithDomain with DBCacheSettings w } } + 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( @@ -1388,4 +1413,29 @@ class SyncInvokeDiffTest extends PropSpec with WithDomain with DBCacheSettings w 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 + } + } }