diff --git a/node-it/src/test/scala/com/wavesplatform/it/sync/activation/AcceptFailedScriptActivationSuite.scala b/node-it/src/test/scala/com/wavesplatform/it/sync/activation/AcceptFailedScriptActivationSuite.scala index e1c4026784..78100e76a0 100644 --- a/node-it/src/test/scala/com/wavesplatform/it/sync/activation/AcceptFailedScriptActivationSuite.scala +++ b/node-it/src/test/scala/com/wavesplatform/it/sync/activation/AcceptFailedScriptActivationSuite.scala @@ -300,7 +300,7 @@ class AcceptFailedScriptActivationSuite extends BaseTransactionSuite with NTPTim smartMatcherFee, 100L, ts, - ts + Order.MaxLiveTime, + ts + 2.days.toMillis, smartMatcherFee ) .explicitGet() @@ -314,7 +314,7 @@ class AcceptFailedScriptActivationSuite extends BaseTransactionSuite with NTPTim smartMatcherFee, 100L, ts, - ts + Order.MaxLiveTime, + ts + 2.days.toMillis, smartMatcherFee ) .explicitGet() @@ -375,7 +375,7 @@ class AcceptFailedScriptActivationSuite extends BaseTransactionSuite with NTPTim 10L, 100L, ts, - ts + Order.MaxLiveTime, + ts + 2.days.toMillis, smartMatcherFee, matcherFeeAssetId = IssuedAsset(ByteStr.decodeBase58(feeAsset).get) ) @@ -390,7 +390,7 @@ class AcceptFailedScriptActivationSuite extends BaseTransactionSuite with NTPTim 10L, 100L, ts, - ts + Order.MaxLiveTime, + ts + 2.days.toMillis, smartMatcherFee, matcherFeeAssetId = IssuedAsset(ByteStr.decodeBase58(feeAsset).get) ) diff --git a/node-it/src/test/scala/com/wavesplatform/it/sync/grpc/FailedTransactionGrpcSuite.scala b/node-it/src/test/scala/com/wavesplatform/it/sync/grpc/FailedTransactionGrpcSuite.scala index dbc782c9b1..f659f1e99c 100644 --- a/node-it/src/test/scala/com/wavesplatform/it/sync/grpc/FailedTransactionGrpcSuite.scala +++ b/node-it/src/test/scala/com/wavesplatform/it/sync/grpc/FailedTransactionGrpcSuite.scala @@ -121,31 +121,6 @@ class FailedTransactionGrpcSuite extends GrpcBaseTransactionSuite with FailedTra sender.setScript(contract, Right(Some(script)), setScriptFee, waitForTx = true) } - test("InvokeScriptTransaction: insufficient action fees propagates failed transaction") { - val invokeFee = 0.005.waves - val setAssetScriptMinFee = setAssetScriptFee + smartFee * 2 - val priorityFee = setAssetScriptMinFee + invokeFee - - updateAssetScript(result = true, smartAsset, contract, setAssetScriptMinFee) - - for (typeName <- Seq("transfer", "issue", "reissue", "burn")) { - updateTikTok("unknown", setAssetScriptMinFee) - - overflowBlock() - sendTxsAndThenPriorityTx( - _ => - sender - .broadcastInvokeScript( - caller, - Recipient().withPublicKeyHash(contractAddr), - Some(FUNCTION_CALL(FunctionHeader.User("tikTok"), List.empty)), - fee = invokeFee - ), - () => updateTikTok(typeName, priorityFee, waitForTx = false) - )((txs, _) => assertFailedTxs(txs)) - } - } - test("InvokeScriptTransaction: invoke script error in payment asset propagates failed transaction") { val invokeFee = 0.005.waves + smartFee val setAssetScriptMinFee = setAssetScriptFee + smartFee diff --git a/node-it/src/test/scala/com/wavesplatform/it/sync/transactions/FailedTransactionSuite.scala b/node-it/src/test/scala/com/wavesplatform/it/sync/transactions/FailedTransactionSuite.scala index 067c5d1237..1c086beb23 100644 --- a/node-it/src/test/scala/com/wavesplatform/it/sync/transactions/FailedTransactionSuite.scala +++ b/node-it/src/test/scala/com/wavesplatform/it/sync/transactions/FailedTransactionSuite.scala @@ -3,15 +3,12 @@ package com.wavesplatform.it.sync.transactions import com.typesafe.config.Config import com.wavesplatform.api.http.ApiError.TransactionNotAllowedByAssetScript import com.wavesplatform.api.http.DebugMessage -import com.wavesplatform.common.state.ByteStr import com.wavesplatform.common.utils.EitherExt2 import com.wavesplatform.it.api.SyncHttpApi.* -import com.wavesplatform.it.api.{StateChanges, TransactionStatus} import com.wavesplatform.it.sync.* import com.wavesplatform.it.transactions.BaseTransactionSuite -import com.wavesplatform.lang.v1.compiler.Terms import com.wavesplatform.lang.v1.estimator.v3.ScriptEstimatorV3 -import com.wavesplatform.state.{BooleanDataEntry, StringDataEntry} +import com.wavesplatform.state.StringDataEntry import com.wavesplatform.test.* import com.wavesplatform.transaction.assets.exchange.AssetPair import com.wavesplatform.transaction.smart.script.ScriptCompiler @@ -118,52 +115,6 @@ class FailedTransactionSuite extends BaseTransactionSuite with CancelAfterFailur sender.setScript(contract, Some(script), setScriptFee, waitForTx = true).id } - test("InvokeScriptTransaction: insufficient action fees propagates failed transaction") { - val invokeFee = 0.005.waves - val setAssetScriptMinFee = setAssetScriptFee + smartFee - val priorityFee = setAssetScriptMinFee + invokeFee - - updateAssetScript(result = true, smartAsset, contract, setAssetScriptMinFee) - - for (typeName <- Seq("transfer", "issue", "reissue", "burn")) { - updateTikTok("unknown", setAssetScriptMinFee) - - val prevBalance = sender.balance(caller.toAddress.toString).balance - val prevAssetBalance = sender.assetBalance(contractAddress, smartAsset) - val prevAssets = sender.assetsBalance(contractAddress) - - overflowBlock() - sendTxsAndThenPriorityTx( - _ => sender.invokeScript(caller, contractAddress, Some("tikTok"), fee = invokeFee)._1.id, - () => updateTikTok(typeName, priorityFee, waitForTx = false) - ) { (txs, priorityTx) => - logPriorityTx(priorityTx) - - val failed = assertFailedTxs(txs) - - sender.balance(caller.toAddress.toString).balance shouldBe prevBalance - txs.size * invokeFee - sender.assetBalance(contractAddress, smartAsset) shouldBe prevAssetBalance - sender.assetsBalance(contractAddress).balances should contain theSameElementsAs prevAssets.balances - - val (scriptInvokedInfo, issuedInfo) = - if (typeName == "issue") - ("", " with 1 assets issued") - else - (" with 1 total scripts invoked", "") - - val minFee = if (typeName == "issue") invokeFee + issueFee else invokeFee + smartFee - val text = s"Fee in WAVES for InvokeScriptTransaction ($invokeFee in WAVES)" + - s"$scriptInvokedInfo$issuedInfo does not exceed minimal value of $minFee WAVES." - - failed.foreach { s => - checkStateChange(sender.stateChanges(s.id), 2, text) - } - - failed - } - } - } - test("InvokeScriptTransaction: reject transactions if account script failed") { val invokeFee = 0.005.waves val setAssetScriptMinFee = setAssetScriptFee + smartFee @@ -212,50 +163,6 @@ class FailedTransactionSuite extends BaseTransactionSuite with CancelAfterFailur } } - test("InvokeScriptTransaction: transactionHeightById returns only succeed transactions") { - val invokeFee = 0.005.waves + smartFee - val setAssetScriptMinFee = setAssetScriptFee + smartFee - val priorityFee = setAssetScriptMinFee + invokeFee - - updateAccountScript(None, caller, setScriptFee + smartFee) - updateTikTok("reissue", setAssetScriptMinFee) - updateAssetScript(result = true, smartAsset, contract, setAssetScriptMinFee) - waitForEmptyUtx() - overflowBlock() - - val failedTxs = sendTxsAndThenPriorityTx( - _ => sender.invokeScript(caller, contractAddress, Some("tikTok"), fee = invokeFee)._1.id, - () => updateAssetScript(result = false, smartAsset, contract, priorityFee) - ) { (txs, priorityTx) => - logPriorityTx(priorityTx) - assertFailedTxs(txs) - } - - checkTransactionHeightById(failedTxs) - } - - test("ExchangeTransaction: transaction validates as failed when asset script fails") { - val Precondition(amountAsset, priceAsset, buyFeeAsset, sellFeeAsset) = - exchangePreconditions( - Some(ScriptCompiler.compile("true", ScriptEstimatorV3(fixOverflow = true, overhead = false)).explicitGet()._1.bytes().base64) - ) - - val assetPair = AssetPair.createAssetPair(amountAsset, priceAsset).get - val fee = 0.003.waves + 4 * smartFee - val sellMatcherFee = fee / 100000L - val buyMatcherFee = fee / 100000L - - val (assetScript, _) = - ScriptCompiler.compile("if true then throw(\"error\") else false", ScriptEstimatorV3(fixOverflow = true, overhead = false)).explicitGet() - val scriptTx = sender.setAssetScript(priceAsset, buyerAddress, script = Some(assetScript.bytes().base64)) - nodes.waitForHeightAriseAndTxPresent(scriptTx.id) - - val tx = mkExchange(buyer, seller, matcher, assetPair, fee, buyFeeAsset, sellFeeAsset, buyMatcherFee, sellMatcherFee) - val result = sender.signedValidate(tx.json()) - (result \ "valid").as[Boolean] shouldBe false - (result \ "error").as[String] should include("not allowed by script of the asset") - } - test("ExchangeTransaction: invalid exchange tx when asset script fails on broadcast") { val init = Seq( sender.setScript(firstKeyPair, None, setScriptFee + smartFee).id, @@ -309,38 +216,6 @@ class FailedTransactionSuite extends BaseTransactionSuite with CancelAfterFailur private def waitForTxs(txs: Seq[String]): Unit = nodes.waitFor("preconditions", 500.millis)(_.transactionStatus(txs).forall(_.status == "confirmed"))(_.forall(identity)) - private def checkStateChange(info: StateChanges, code: Int, text: String, strict: Boolean = false): Unit = { - info.stateChanges shouldBe defined - info.stateChanges.get.issues.size shouldBe 0 - info.stateChanges.get.reissues.size shouldBe 0 - info.stateChanges.get.burns.size shouldBe 0 - info.stateChanges.get.error shouldBe defined - info.stateChanges.get.error.get.code shouldBe code - if (strict) - info.stateChanges.get.error.get.text shouldBe text - else - info.stateChanges.get.error.get.text should include(text) - } - - private def checkTransactionHeightById(failedTxs: Seq[TransactionStatus]): Unit = { - val defineTxs = failedTxs.map { status => - sender - .invokeScript( - caller, - contractAddress, - Some("defineTxHeight"), - List(Terms.CONST_BYTESTR(ByteStr.decodeBase58(status.id).get).explicitGet()), - fee = invokeFee - ) - ._1 - .id - } - - waitForTxs(defineTxs) - - failedTxs.foreach(status => sender.getDataByKey(contractAddress, status.id) shouldBe BooleanDataEntry(status.id, value = false)) - } - private def exchangePreconditions(initScript: Option[String]): Precondition = { val transfers = Seq( sender.transfer(sender.keyPair, sellerAddress.toAddress.toString, 100.waves).id, diff --git a/node/src/test/scala/com/wavesplatform/RxScheduler.scala b/node/src/test/scala/com/wavesplatform/RxScheduler.scala index efbc6c0ca7..af54b50af8 100644 --- a/node/src/test/scala/com/wavesplatform/RxScheduler.scala +++ b/node/src/test/scala/com/wavesplatform/RxScheduler.scala @@ -24,10 +24,10 @@ trait RxScheduler extends BeforeAndAfterAll { _: Suite => def test[A](f: => Future[A]): A = Await.result(f, 10.seconds) - def send[A](p: Observer[A])(a: A): Future[Ack] = + def send[A](p: Observer[A], timeout: Int = 500)(a: A): Future[Ack] = p.onNext(a) .map(ack => { - Thread.sleep(500) + Thread.sleep(timeout) ack }) diff --git a/node/src/test/scala/com/wavesplatform/network/RxExtensionLoaderSpec.scala b/node/src/test/scala/com/wavesplatform/network/RxExtensionLoaderSpec.scala index 5c27d1c005..846e27b5a8 100644 --- a/node/src/test/scala/com/wavesplatform/network/RxExtensionLoaderSpec.scala +++ b/node/src/test/scala/com/wavesplatform/network/RxExtensionLoaderSpec.scala @@ -92,7 +92,7 @@ class RxExtensionLoaderSpec extends FreeSpec with RxScheduler with BlockGen { "should blacklist GetSignatures timeout" in withExtensionLoader(Seq.tabulate(100)(byteStr), 1.millis) { (_, _, _, ccsw, _) => val ch = new EmbeddedChannel() test(for { - _ <- send(ccsw)(ChannelClosedAndSyncWith(None, Some(BestChannel(ch, 1: BigInt)))) + _ <- send(ccsw, timeout = 1000)(ChannelClosedAndSyncWith(None, Some(BestChannel(ch, 1: BigInt)))) } yield { ch.isOpen shouldBe false }) diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/ci/InvokeActionsFeeTest.scala b/node/src/test/scala/com/wavesplatform/state/diffs/ci/InvokeActionsFeeTest.scala index 2d4973fcba..2f9298528d 100644 --- a/node/src/test/scala/com/wavesplatform/state/diffs/ci/InvokeActionsFeeTest.scala +++ b/node/src/test/scala/com/wavesplatform/state/diffs/ci/InvokeActionsFeeTest.scala @@ -10,8 +10,9 @@ import com.wavesplatform.lang.v1.compiler.TestCompiler import com.wavesplatform.state.diffs.FeeValidation.{FeeConstants, FeeUnit} import com.wavesplatform.test.* import com.wavesplatform.transaction.Asset.IssuedAsset -import com.wavesplatform.transaction.smart.InvokeScriptTransaction.Payment +import com.wavesplatform.transaction.TxHelpers.* import com.wavesplatform.transaction.smart.InvokeScriptTransaction +import com.wavesplatform.transaction.smart.InvokeScriptTransaction.Payment import com.wavesplatform.transaction.{Transaction, TransactionType, TxHelpers} import org.scalatest.{EitherValues, Inside} @@ -26,10 +27,7 @@ class InvokeActionsFeeTest extends PropSpec with Inside with WithState with DBCa private val verifier: Script = TestCompiler(V4).compileExpression( - s""" {-# STDLIB_VERSION 4 #-} - | {-# SCRIPT_TYPE ASSET #-} - | {-# CONTENT_TYPE EXPRESSION #-} - | + s""" | !(sigVerify_32Kb(base58'', base58'', base58'') || | sigVerify_32Kb(base58'', base58'', base58'') || | sigVerify_32Kb(base58'', base58'', base58'')) @@ -38,13 +36,13 @@ class InvokeActionsFeeTest extends PropSpec with Inside with WithState with DBCa private def dApp(asset: IssuedAsset): Script = TestCompiler(V4).compileContract(s""" - | @Callable(i) - | func default() = - | [ - | ScriptTransfer(i.caller, 1, base58'$asset'), - | Burn(base58'$asset', 1), - | Reissue(base58'$asset', 1, false) - | ] + | @Callable(i) + | func default() = + | [ + | ScriptTransfer(i.caller, 1, base58'$asset'), + | Burn(base58'$asset', 1), + | Reissue(base58'$asset', 1, false) + | ] """.stripMargin) private val paymentPreconditions: (Seq[AddrWithBalance], List[Transaction], () => InvokeScriptTransaction, () => InvokeScriptTransaction) = { @@ -64,6 +62,33 @@ class InvokeActionsFeeTest extends PropSpec with Inside with WithState with DBCa (balances, List(issue, transfer1, transfer2, setVerifier, setDApp), invokeFromScripted, invokeFromNonScripted) } + property("insufficient action fees propagates failed transaction before RIDE V5 activation") { + withDomain(RideV4, AddrWithBalance.enoughBalances(secondSigner)) { d => + val issueTx = issue(script = Some(TestCompiler(V4).compileExpression("true"))) + val asset = IssuedAsset(issueTx.id()) + val dApp = TestCompiler(V4).compileContract( + s""" + | @Callable(i) + | func transfer() = [ScriptTransfer(i.caller, 1, base58'$asset')] + | + | @Callable(i) + | func reissue() = [Reissue(base58'$asset', 1, true)] + | + | @Callable(i) + | func burn() = [Burn(base58'$asset', 1)] + | + | @Callable(i) + | func issue() = [Issue("name", "", 1000, 4, true, unit, 0)] + """.stripMargin + ) + d.appendBlock(issueTx, setScript(secondSigner, dApp)) + d.appendAndAssertFailed(invoke(func = Some("transfer")), "with 1 total scripts invoked does not exceed minimal value of 900000 WAVES") + d.appendAndAssertFailed(invoke(func = Some("reissue")), "with 1 total scripts invoked does not exceed minimal value of 900000 WAVES") + d.appendAndAssertFailed(invoke(func = Some("burn")), "with 1 total scripts invoked does not exceed minimal value of 900000 WAVES") + d.appendAndAssertFailed(invoke(func = Some("issue")), "with 1 assets issued does not exceed minimal value of 100500000 WAVES") + } + } + property(s"fee for asset scripts is not required after activation ${BlockchainFeatures.SynchronousCalls}") { val (balances, preparingTxs, invokeFromScripted, invokeFromNonScripted) = paymentPreconditions withDomain(fsWithV5, balances) { d =>