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

NODE-2611 Forbidden RIDE V1-V3 #3880

Merged
merged 8 commits into from
Oct 6, 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
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ class TestCompiler(version: StdLibVersion) {
(baseCompilerContext |+|
WavesContext.build(Global, DirectiveSet(version, Account, DAppType).explicitGet(), fixBigScriptField = true)).compilerContext

lazy val expressionContext: CTX[Environment] =
private lazy val expressionContext: CTX[Environment] =
WavesContext.build(Global, DirectiveSet(version, Account, Expression).explicitGet(), fixBigScriptField = true)

private lazy val expressionCompilerContext =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package com.wavesplatform.state.diffs
import cats.implicits.toBifunctorOps
import com.wavesplatform.account.{Address, AddressScheme}
import com.wavesplatform.database.patch.DisableHijackedAliases
import com.wavesplatform.features.BlockchainFeatures.TransactionStateSnapshot
import com.wavesplatform.features.OverdraftValidationProvider.*
import com.wavesplatform.features.{BlockchainFeature, BlockchainFeatures, RideVersionProvider}
import com.wavesplatform.lang.ValidationError
Expand Down Expand Up @@ -144,13 +145,21 @@ object CommonValidation {
case v => barrierByVersion(v)
}

def oldScriptVersionDeactivation(sc: Script): Either[ActivationError, Unit] = sc.stdLibVersion match {
case V1 | V2 | V3 if blockchain.isFeatureActivated(TransactionStateSnapshot) =>
Left(ActivationError(s"Script version below V4 is not allowed after ${TransactionStateSnapshot.description} feature activation"))
case _ =>
Right(())
}

def scriptTypeActivation(sc: Script): Either[ActivationError, T] = (sc: @unchecked) match {
case _: ExprScript => Right(tx)
case _: ContractScript.ContractScriptImpl => barrierByVersion(V3)
}

for {
_ <- scriptVersionActivation(sc)
_ <- oldScriptVersionDeactivation(sc)
_ <- scriptTypeActivation(sc)
} yield tx

Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -6,26 +6,28 @@ import com.wavesplatform.db.WithDomain
import com.wavesplatform.features.BlockchainFeatures
import com.wavesplatform.lagonaki.mocks.TestBlock
import com.wavesplatform.lang.directives.DirectiveDictionary
import com.wavesplatform.lang.directives.values.{StdLibVersion, V3, V4}
import com.wavesplatform.lang.directives.values.{StdLibVersion, V3, V4, V8}
import com.wavesplatform.lang.script.Script
import com.wavesplatform.lang.v1.ContractLimits
import com.wavesplatform.lang.v1.compiler.TestCompiler
import com.wavesplatform.settings.FunctionalitySettings
import com.wavesplatform.state.diffs.FeeValidation
import com.wavesplatform.state.diffs.FeeValidation.FeeConstants
import com.wavesplatform.test.*
import com.wavesplatform.transaction.{GenesisTransaction, TransactionType, TxHelpers, TxVersion}
import com.wavesplatform.transaction.Asset.IssuedAsset
import com.wavesplatform.transaction.assets.IssueTransaction
import com.wavesplatform.transaction.smart.{InvokeScriptTransaction, SetScriptTransaction}
import com.wavesplatform.transaction.smart.InvokeScriptTransaction.Payment
import com.wavesplatform.transaction.smart.{InvokeScriptTransaction, SetScriptTransaction}
import com.wavesplatform.transaction.{GenesisTransaction, TransactionType, TxHelpers, TxVersion}

import scala.math.Ordering.Implicits.infixOrderingOps

class OverdraftTest extends PropSpec with WithDomain {
import DomainPresets.*

private val InvokeFee = FeeConstants(TransactionType.InvokeScript) * FeeValidation.FeeUnit
private val InvokeFee = FeeConstants(TransactionType.InvokeScript) * FeeValidation.FeeUnit
private val SetScriptFee = FeeConstants(TransactionType.SetScript) * FeeValidation.FeeUnit
private val IssueFee = FeeConstants(TransactionType.Issue) * FeeValidation.FeeUnit
private val IssueFee = FeeConstants(TransactionType.Issue) * FeeValidation.FeeUnit

private val dAppVersions: List[StdLibVersion] =
DirectiveDictionary[StdLibVersion].all
Expand All @@ -41,40 +43,37 @@ class OverdraftTest extends PropSpec with WithDomain {
settingsForRide(DirectiveDictionary[StdLibVersion].all.last).blockchainSettings.functionalitySettings

property("insufficient fee") {
dAppVersionWithSettings.foreach {
case (version, settings) =>
val (genesis, setDApp, ci, _) = paymentPreconditions(withEnoughFee = false, withPayment = false, emptyResultDApp(version))

assertDiffEi(Seq(TestBlock.create(genesis :+ setDApp)), TestBlock.create(Seq(ci)), settings) { r =>
r should produce(
s"Fee for InvokeScriptTransaction (1 in WAVES) does not exceed minimal value of $InvokeFee WAVES"
)
dAppVersionWithSettings.foreach { case (version, settings) =>
val (genesis, setDApp, ci, _) = paymentPreconditions(withEnoughFee = false, withPayment = false, emptyResultDApp(version))

assertDiffEi(Seq(TestBlock.create(genesis :+ setDApp)), TestBlock.create(Seq(ci)), settings) { r =>
r should produce(
s"Fee for InvokeScriptTransaction (1 in WAVES) does not exceed minimal value of $InvokeFee WAVES"
)
}
}
}

property("overdraft") {
dAppVersionWithSettings.foreach {
case (version, settings) =>
val (genesis, setDApp, ci, _) = paymentPreconditions(withEnoughFee = true, withPayment = false, payingDApp(version))

assertDiffEi(Seq(TestBlock.create(genesis :+ setDApp)), TestBlock.create(Seq(ci)), settings) { r =>
if (settings.preActivatedFeatures.contains(BlockchainFeatures.BlockV5.id))
r should produce("AccountBalanceError")
else
r.explicitGet()
}
dAppVersionWithSettings.foreach { case (version, settings) =>
val (genesis, setDApp, ci, _) = paymentPreconditions(withEnoughFee = true, withPayment = false, payingDApp(version))

assertDiffEi(Seq(TestBlock.create(genesis :+ setDApp)), TestBlock.create(Seq(ci)), settings) { r =>
if (settings.preActivatedFeatures.contains(BlockchainFeatures.BlockV5.id))
r should produce("AccountBalanceError")
else
r.explicitGet()
}
}
}

property("overdraft with payment V3") {
dAppVersionWithSettings.foreach {
case (_, settings) =>
val (genesis, setDApp, ci, issue) = paymentPreconditions(withEnoughFee = true, withPayment = true, payingDApp(V3))
dAppVersionWithSettings.filter(_._1 < V8).foreach { case (_, settings) =>
val (genesis, setDApp, ci, issue) = paymentPreconditions(withEnoughFee = true, withPayment = true, payingDApp(V3))

assertDiffEi(Seq(TestBlock.create(genesis ++ List(setDApp, issue))), TestBlock.create(Seq(ci)), settings) {
_ should produce("leads to negative waves balance to (at least) temporary negative state")
}
assertDiffEi(Seq(TestBlock.create(genesis ++ List(setDApp, issue))), TestBlock.create(Seq(ci)), settings) {
_ should produce("leads to negative waves balance to (at least) temporary negative state")
}
}
}

Expand Down Expand Up @@ -104,7 +103,8 @@ class OverdraftTest extends PropSpec with WithDomain {
val payments = (1 to count).map(_ => Payment(issue.quantity.value / count + 1, IssuedAsset(issue.id())))
val invoke = TxHelpers.invoke(master.toAddress, func = None, invoker = invoker, payments = payments)

assertDiffEi(Seq(TestBlock.create(genesis ++ List(setDApp, issue))), TestBlock.create(Seq(invoke)), allActivatedSettings) {
val settings = settingsForRide(version.max(V4)).blockchainSettings.functionalitySettings
assertDiffEi(Seq(TestBlock.create(genesis ++ List(setDApp, issue))), TestBlock.create(Seq(invoke)), settings) {
_ should produce("Attempt to transfer unavailable funds: Transaction application leads to negative asset")
}
}
Expand Down Expand Up @@ -155,12 +155,12 @@ class OverdraftTest extends PropSpec with WithDomain {
}

private def dApp(body: String, version: StdLibVersion): Script = TestCompiler(version).compileContract(s"""
| {-# STDLIB_VERSION $version #-}
| {-# CONTENT_TYPE DAPP #-}
| {-# SCRIPT_TYPE ACCOUNT #-}
|
| @Callable(i)
| func default() = $body
|
|""".stripMargin)
| {-# STDLIB_VERSION $version #-}
| {-# CONTENT_TYPE DAPP #-}
| {-# SCRIPT_TYPE ACCOUNT #-}
|
| @Callable(i)
| func default() = $body
|
|""".stripMargin)
}
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.WithDomain
import com.wavesplatform.lang.directives.DirectiveDictionary
import com.wavesplatform.lang.directives.values.{StdLibVersion, V3, V5, V8}
import com.wavesplatform.lang.directives.values.*
import com.wavesplatform.lang.script.Script
import com.wavesplatform.lang.script.v1.ExprScript
import com.wavesplatform.lang.v1.compiler.{Terms, TestCompiler}
Expand All @@ -22,7 +22,7 @@ import com.wavesplatform.transaction.Asset.{IssuedAsset, Waves}
import com.wavesplatform.transaction.assets.{IssueTransaction, SetAssetScriptTransaction}
import com.wavesplatform.transaction.smart.SetScriptTransaction
import com.wavesplatform.transaction.transfer.TransferTransaction
import com.wavesplatform.transaction.{EthABIConverter, Asset, EthereumTransaction, GenesisTransaction}
import com.wavesplatform.transaction.{Asset, EthABIConverter, EthereumTransaction, GenesisTransaction}
import com.wavesplatform.utils.EthHelpers
import org.scalatest.Inside

Expand Down Expand Up @@ -115,7 +115,7 @@ class EthereumInvokeTest extends PropSpec with WithDomain with EthHelpers with I
val invoker = dummyEthInvoke.senderAddress()
val invokerPk = dummyEthInvoke.signerPublicKey()

val emptyScript = Some(ExprScript(Terms.TRUE).explicitGet())
val emptyScript = Some(ExprScript(V4, Terms.TRUE).explicitGet())
val issues =
(1 to paymentCount).map(_ =>
IssueTransaction.selfSigned(2.toByte, dApp, "Asset", "", ENOUGH_AMT, 8, true, emptyScript, 1.waves, ts).explicitGet()
Expand Down Expand Up @@ -172,13 +172,14 @@ class EthereumInvokeTest extends PropSpec with WithDomain with EthHelpers with I
property("invoke with scripted payments") {
val allVersions = DirectiveDictionary[StdLibVersion].all
val lastVersion = allVersions.last
val dAppVersions = allVersions.filter(_ >= V3)
val dAppVersions = allVersions.filter(_ > V3)

dAppVersions.foreach { v =>
assert(dAppVersion = v, assetScriptVersion = lastVersion, v.maxPayments, syncCall = v >= V5)
assert(dAppVersion = v, assetScriptVersion = lastVersion, 0)
assert(dAppVersion = lastVersion, assetScriptVersion = v, v.maxPayments)
assert(dAppVersion = lastVersion, assetScriptVersion = v, 0)
}
assert(V3, V3, V3.maxPayments)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -159,37 +159,43 @@ class BrokenUnicodeTest extends PropSpec with WithDomain with EitherValues {
allowIllFormedStrings = true
)

private val versionsBeforeActivation = DirectiveDictionary[StdLibVersion].all.filter(_ < V5)
private val dAppVersionsBeforeActivation = versionsBeforeActivation.filter(_ >= V3)

private def allVersions(lastVersion: StdLibVersion) = DirectiveDictionary[StdLibVersion].all.filter(_ <= lastVersion)
private def allDAppVersions(lastVersion: StdLibVersion) = allVersions(lastVersion).filter(_ >= V3)

private def scenario(lastVersion: StdLibVersion) = {
val recipient = TxHelpers.signer(0)
val invoker = TxHelpers.signer(1)
val invoker = TxHelpers.signer(1)

val availableVersions = allVersions(lastVersion)
val availableDAppVersions = allDAppVersions(lastVersion)
val availableVersions = if (lastVersion < V8) allVersions(lastVersion) else allVersions(lastVersion).filter(_ > V3)
val availableDAppVersions = if (lastVersion < V8) allDAppVersions(lastVersion) else allDAppVersions(lastVersion).filter(_ > V3)
val versionsBeforeActivation = if (lastVersion < V8) DirectiveDictionary[StdLibVersion].all.filter(_ < V5) else Seq(V4)
val dAppVersionsBeforeActivation = versionsBeforeActivation.filter(_ >= V3)

val accWithFix = (1 to availableVersions.size).map(idx => TxHelpers.signer(idx + 1)).zip(availableVersions).toList
val accWithNoFix = (1 to versionsBeforeActivation.size).map(idx => TxHelpers.signer(idx + availableVersions.size + 1)).zip(versionsBeforeActivation).toList
val dAppWithFix = (1 to availableDAppVersions.size).map(idx => TxHelpers.signer(idx + availableVersions.size + versionsBeforeActivation.size + 1)).zip(availableDAppVersions).toList
val dAppWithNoFix = (1 to dAppVersionsBeforeActivation.size).map(idx => TxHelpers.signer(idx + availableVersions.size + versionsBeforeActivation.size + availableDAppVersions.size + 1)).zip(dAppVersionsBeforeActivation).toList
val accWithNoFix =
(1 to versionsBeforeActivation.size).map(idx => TxHelpers.signer(idx + availableVersions.size + 1)).zip(versionsBeforeActivation).toList
val dAppWithFix = (1 to availableDAppVersions.size)
.map(idx => TxHelpers.signer(idx + availableVersions.size + versionsBeforeActivation.size + 1))
.zip(availableDAppVersions)
.toList
val dAppWithNoFix = (1 to dAppVersionsBeforeActivation.size)
.map(idx => TxHelpers.signer(idx + availableVersions.size + versionsBeforeActivation.size + availableDAppVersions.size + 1))
.zip(dAppVersionsBeforeActivation)
.toList

val genesis = (accWithFix ::: accWithNoFix ::: dAppWithFix ::: dAppWithNoFix)
.map { case (acc, _) => TxHelpers.genesis(acc.toAddress) }
val invokerGenesis = TxHelpers.genesis(invoker.toAddress)

val setNoFixVerifier = accWithNoFix.map { case (acc, v) => TxHelpers.setScript(acc, checkNoFixScript(v)) }
val setFixVerifier = accWithFix.map { case (acc, v) => TxHelpers.setScript(acc, checkFixScript(v)) }
val setNoFixDApp = dAppWithNoFix.map { case (acc, v) => TxHelpers.setScript(acc, checkNoFixDAppScript(v)) }
val setFixDApp = dAppWithFix.map { case (acc, v) => TxHelpers.setScript(acc, checkFixDAppScript(v)) }
val setNoFixVerifier = accWithNoFix.map { case (acc, v) => TxHelpers.setScript(acc, checkNoFixScript(v)) }
val setFixVerifier = accWithFix.map { case (acc, v) => TxHelpers.setScript(acc, checkFixScript(v)) }
val setNoFixDApp = dAppWithNoFix.map { case (acc, v) => TxHelpers.setScript(acc, checkNoFixDAppScript(v)) }
val setFixDApp = dAppWithFix.map { case (acc, v) => TxHelpers.setScript(acc, checkFixDAppScript(v)) }

val checkFixVerifier = accWithFix.map { case (acc, _) => TxHelpers.transfer(acc, recipient.toAddress, 1) }
val checkNoFixVerifier = accWithNoFix.map { case (acc, _) => TxHelpers.transfer(acc, recipient.toAddress, 1) }
val checkFixDApp = dAppWithFix.map { case (acc, _) => TxHelpers.invoke(acc.toAddress, func = None, invoker = invoker) }
val checkNoFixDApp = dAppWithNoFix.map { case (acc, _) => TxHelpers.invoke(acc.toAddress, func = None, invoker = invoker) }
val checkFixVerifier = accWithFix.map { case (acc, _) => TxHelpers.transfer(acc, recipient.toAddress, 1) }
val checkNoFixVerifier = accWithNoFix.map { case (acc, _) => TxHelpers.transfer(acc, recipient.toAddress, 1) }
val checkFixDApp = dAppWithFix.map { case (acc, _) => TxHelpers.invoke(acc.toAddress, func = None, invoker = invoker) }
val checkNoFixDApp = dAppWithNoFix.map { case (acc, _) => TxHelpers.invoke(acc.toAddress, func = None, invoker = invoker) }

(
invokerGenesis :: genesis,
Expand Down
Loading