Skip to content

Commit

Permalink
NODE-2611 Forbid RIDE V1-V3 (#3880)
Browse files Browse the repository at this point in the history
  • Loading branch information
xrtm000 authored Oct 6, 2023
1 parent a659a53 commit 15bb32e
Show file tree
Hide file tree
Showing 9 changed files with 594 additions and 530 deletions.
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

0 comments on commit 15bb32e

Please sign in to comment.