Navigation Menu

Skip to content

Commit

Permalink
NODE-2517 Fixed mapping 'script' field of SetScriptTransaction (#3802)
Browse files Browse the repository at this point in the history
  • Loading branch information
xrtm000 committed Jan 12, 2023
1 parent 11ddc25 commit ef76fd7
Show file tree
Hide file tree
Showing 51 changed files with 223 additions and 138 deletions.
Expand Up @@ -29,7 +29,7 @@ class AddressFromPublicKeyBenchmark {
@State(Scope.Benchmark)
class PkSt extends EthHelpers {
val ds = DirectiveSet(V6, Account, Expression).fold(null, identity)
val ctx = lazyContexts((ds, true)).value().evaluationContext(EnvironmentFunctionsBenchmark.environment)
val ctx = lazyContexts((ds, true, true)).value().evaluationContext(EnvironmentFunctionsBenchmark.environment)

val wavesPk = ByteStr(curve25519.generateKeypair._2)
val exprWaves = TestCompiler(V6).compileExpression(s"addressFromPublicKey(base58'$wavesPk')").expr.asInstanceOf[EXPR]
Expand Down
Expand Up @@ -27,7 +27,7 @@ class BigIntToStringBenchmark {
@State(Scope.Benchmark)
class BigIntToStringSt {
val ds = DirectiveSet(V5, Account, Expression).fold(null, identity)
val ctx = lazyContexts((ds, true)).value().evaluationContext(Common.emptyBlockchainEnvironment())
val ctx = lazyContexts((ds, true, true)).value().evaluationContext(Common.emptyBlockchainEnvironment())

val expr = FUNCTION_CALL(
Native(BIGINT_TO_STRING),
Expand Down
Expand Up @@ -169,7 +169,7 @@ object EnvironmentFunctionsBenchmark {
class AddressFromString {
val ctx: EvaluationContext[Environment, Id] =
WavesContext
.build(Global, DirectiveSet(V4, Account, DApp).explicitGet())
.build(Global, DirectiveSet(V4, Account, DApp).explicitGet(), true)
.evaluationContext(environment)

val expr: Array[EXPR] =
Expand Down
Expand Up @@ -46,7 +46,7 @@ class FoldBenchmark {
@State(Scope.Benchmark)
class FoldSt {
val ds = DirectiveSet(V5, Account, Expression).fold(null, identity)
val ctx = lazyContexts((ds, true)).value().evaluationContext(Common.emptyBlockchainEnvironment())
val ctx = lazyContexts((ds, true, true)).value().evaluationContext(Common.emptyBlockchainEnvironment())

val function = "func f(acc: Boolean, elem: ByteVector) = acc && sigVerify(elem, base58'', base58'')"

Expand Down
Expand Up @@ -42,7 +42,7 @@ class FractionBigIntBenchmark {
@State(Scope.Benchmark)
class FractionBigIntSt {
val ds = DirectiveSet(V5, Account, Expression).fold(null, identity)
val ctx = lazyContexts(ds -> true).value().evaluationContext(Common.emptyBlockchainEnvironment())
val ctx = lazyContexts((ds, true, true)).value().evaluationContext(Common.emptyBlockchainEnvironment())

val max = CONST_BIGINT(PureContext.BigIntMax)
val halfMax = CONST_BIGINT(PureContext.BigIntMax / 2)
Expand Down
Expand Up @@ -41,7 +41,7 @@ class FractionIntBenchmark {
@State(Scope.Benchmark)
class St {
val ds = DirectiveSet(V6, Account, Expression).fold(null, identity)
val ctx = lazyContexts((ds, true)).value().evaluationContext(Common.emptyBlockchainEnvironment())
val ctx = lazyContexts((ds, true, true)).value().evaluationContext(Common.emptyBlockchainEnvironment())

val max = Long.MaxValue
val maxSqrt = 3037000499L
Expand Down
Expand Up @@ -51,7 +51,7 @@ class PowBigIntBenchmark {
@State(Scope.Benchmark)
class PowBigIntSt {
val ds = DirectiveSet(V5, Account, Expression).fold(null, identity)
val ctx = lazyContexts(ds -> true).value().evaluationContext(Common.emptyBlockchainEnvironment())
val ctx = lazyContexts((ds, true, true)).value().evaluationContext(Common.emptyBlockchainEnvironment())

val max = PureContext.BigIntMax
val min = PureContext.BigIntMin
Expand Down
Expand Up @@ -52,7 +52,7 @@ class PowIntBenchmark {
@State(Scope.Benchmark)
class PowIntSt {
val ds = DirectiveSet(V5, Account, Expression).fold(null, identity)
val ctx = lazyContexts((ds, true)).value().evaluationContext(Common.emptyBlockchainEnvironment())
val ctx = lazyContexts((ds, true, true)).value().evaluationContext(Common.emptyBlockchainEnvironment())

val max = Long.MaxValue

Expand Down
Expand Up @@ -218,7 +218,7 @@ class PureFunctionsRebenchmark {

object PureFunctionsRebenchmark {
val context: EvaluationContext[Environment, Id] =
lazyContexts(DirectiveSet(V5, Account, Expression).explicitGet() -> true)()
lazyContexts((DirectiveSet(V5, Account, Expression).explicitGet(), true, true))()
.evaluationContext(Common.emptyBlockchainEnvironment())

val eval: EXPR => (Log[Id], Int, Either[ExecutionError, EVALUATED]) =
Expand Down
Expand Up @@ -33,7 +33,7 @@ class SqrtCbrtBigIntBenchmark {
@State(Scope.Benchmark)
class SqrtBigIntSt {
val ds = DirectiveSet(V5, Account, Expression).fold(null, identity)
val ctx = lazyContexts(ds -> true).value().evaluationContext(Common.emptyBlockchainEnvironment())
val ctx = lazyContexts((ds, true, true)).value().evaluationContext(Common.emptyBlockchainEnvironment())

val max = PureContext.BigIntMax
val min = PureContext.BigIntMin
Expand Down
Expand Up @@ -28,7 +28,7 @@ class SqrtIntBenchmark {
@State(Scope.Benchmark)
class SqrtIntSt {
val ds = DirectiveSet(V5, Account, Expression).fold(null, identity)
val ctx = lazyContexts(ds -> true).value().evaluationContext(Common.emptyBlockchainEnvironment())
val ctx = lazyContexts((ds, true, true)).value().evaluationContext(Common.emptyBlockchainEnvironment())

val expr1 = compile(s"pow(${Long.MaxValue}, 0, 5, 1, 8, DOWN)")
val expr2 = compile(s"pow(${Long.MaxValue}, 8, 5, 1, 8, DOWN)")
Expand Down
Expand Up @@ -49,7 +49,8 @@ object VerifierLoggerBenchmark {
private val dataTxObj: Terms.CaseObj = Bindings.transactionObject(
RealTransactionWrapper(dataTx, ???, ???, ???).explicitGet(),
proofsEnabled = true,
V4
V4,
fixBigScriptField = true
)

val value: (Log[Id], Either[String, EVALUATED]) =
Expand Down
Expand Up @@ -63,20 +63,21 @@ package object utils {
): Coeval[(Either[ValidationError, (EVALUATED, Log[Id])], Int)] = ???
}

val lazyContexts: Map[(DirectiveSet, Boolean), Coeval[CTX[Environment]]] =
val lazyContexts: Map[(DirectiveSet, Boolean, Boolean), Coeval[CTX[Environment]]] =
(for {
version <- DirectiveDictionary[StdLibVersion].all
scriptType <- DirectiveDictionary[ScriptType].all
contentType <- DirectiveDictionary[ContentType].all if contentType != DApp || (contentType == DApp && version >= V3 && scriptType == Account)
useNewPowPrecision <- Seq(false, true)
fixBigScriptField <- Seq(false, true)
} yield {
val ds = DirectiveSet(version, scriptType, contentType).explicitGet()
val ctx = Coeval.evalOnce(
PureContext.build(version, useNewPowPrecision).withEnvironment[Environment] |+|
CryptoContext.build(Global, version).withEnvironment[Environment] |+|
WavesContext.build(Global, ds)
WavesContext.build(Global, ds, fixBigScriptField)
)
(ds, useNewPowPrecision) -> ctx
(ds, useNewPowPrecision, fixBigScriptField) -> ctx
}).toMap

private val lazyFunctionCosts: Map[DirectiveSet, Coeval[Map[FunctionHeader, Coeval[Long]]]] =
Expand Down Expand Up @@ -163,7 +164,7 @@ package object utils {
ScriptType.isAssetScript(isTokenContext),
if (isContract) DApp else Expression
)
lazyContexts((ds.explicitGet(), true)).value()
lazyContexts((ds.explicitGet(), true, true)).value()
}

def compilerContext(version: StdLibVersion, cType: ContentType, isAssetScript: Boolean): CompilerContext = {
Expand All @@ -172,7 +173,7 @@ package object utils {
}

def compilerContext(ds: DirectiveSet): CompilerContext =
lazyContexts((ds.copy(imports = Imports()), true))().compilerContext
lazyContexts((ds.copy(imports = Imports()), true, true))().compilerContext

def getDecompilerContext(v: StdLibVersion, cType: ContentType): DecompilerContext =
combinedContext((v, cType)).decompilerContext
Expand Down
Expand Up @@ -30,5 +30,5 @@ package object converters {
implicit def pureEval[F[_], A <: EVALUATED](
v: Eval[Either[ExecutionError, A]]
)(implicit m: Monad[F]): Eval[F[Either[ExecutionError, EVALUATED]]] =
v.map(ei => pure(ei)(m).asInstanceOf[F[Either[ExecutionError, EVALUATED]]])
v.map(ei => pure(ei)(m))
}
Expand Up @@ -3,12 +3,13 @@ package com.wavesplatform.lang.v1.evaluator.ctx.impl.waves
import com.wavesplatform.common.state.ByteStr
import com.wavesplatform.common.utils.EitherExt2
import com.wavesplatform.lang.directives.values.{StdLibVersion, V3, V4, V5}
import com.wavesplatform.lang.v1.compiler.Terms._
import com.wavesplatform.lang.v1.compiler.Terms.*
import com.wavesplatform.lang.v1.compiler.Terms.CONST_BYTESTR.{DataEntrySize, NoLimit}
import com.wavesplatform.lang.v1.compiler.Types.CASETYPEREF
import com.wavesplatform.lang.v1.evaluator.ContractEvaluator.Invocation
import com.wavesplatform.lang.v1.evaluator.ctx.impl.{converters, unit}
import com.wavesplatform.lang.v1.traits.domain.Tx._
import com.wavesplatform.lang.v1.traits.domain._
import com.wavesplatform.lang.v1.traits.domain.Tx.*
import com.wavesplatform.lang.v1.traits.domain.*

object Bindings {

Expand Down Expand Up @@ -217,7 +218,7 @@ object Bindings {
version = version
)

def transactionObject(tx: Tx, proofsEnabled: Boolean, version: StdLibVersion): CaseObj =
def transactionObject(tx: Tx, proofsEnabled: Boolean, version: StdLibVersion, fixBigScriptField: Boolean): CaseObj =
tx match {
case Tx.Genesis(h, amount, recipient) =>
CaseObj(genesisTransactionType, Map("amount" -> CONST_LONG(amount)) ++ headerPart(h) + mapRecipient(recipient))
Expand All @@ -237,7 +238,7 @@ object Bindings {
"description" -> (if (version >= V4) description.toUTF8String else description),
"reissuable" -> reissuable,
"decimals" -> decimals,
"script" -> scriptOpt
"script" -> mapScript(scriptOpt, fixBigScriptField)
),
provenTxPart(p, proofsEnabled, version)
)
Expand Down Expand Up @@ -289,11 +290,14 @@ object Bindings {
)
)
case SetScript(p, scriptOpt) =>
CaseObj(buildSetScriptTransactionType(proofsEnabled), Map("script" -> fromOptionBV(scriptOpt)) ++ provenTxPart(p, proofsEnabled, version))
CaseObj(
buildSetScriptTransactionType(proofsEnabled),
Map("script" -> mapScript(scriptOpt, fixBigScriptField)) ++ provenTxPart(p, proofsEnabled, version)
)
case SetAssetScript(p, assetId, scriptOpt) =>
CaseObj(
buildSetAssetScriptTransactionType(proofsEnabled),
combine(Map("script" -> fromOptionBV(scriptOpt), "assetId" -> assetId), provenTxPart(p, proofsEnabled, version))
combine(Map("script" -> mapScript(scriptOpt, fixBigScriptField), "assetId" -> assetId), provenTxPart(p, proofsEnabled, version))
)
case Sponsorship(p, assetId, minSponsoredAssetFee) =>
sponsorshipTransactionObject(proofsEnabled, p, assetId, minSponsoredAssetFee, version)
Expand Down Expand Up @@ -366,6 +370,11 @@ object Bindings {
)
}

private def mapScript(script: Option[ByteStr], fixBigScriptField: Boolean): EVALUATED = {
val limit = if (fixBigScriptField) NoLimit else DataEntrySize
script.flatMap(CONST_BYTESTR(_, limit).toOption).getOrElse(unit)
}

private def reissueTransactionObject(
proofsEnabled: Boolean,
p: Proven,
Expand Down
Expand Up @@ -701,7 +701,7 @@ object Functions {
case CONST_BYTESTR(id: ByteStr) :: Nil =>
env
.transactionById(id.arr)
.map(_.map(transactionObject(_, proofsEnabled, version)))
.map(_.map(transactionObject(_, proofsEnabled, version, fixBigScriptField = false)))
.map(fromOptionCO)
.map(_.asRight[ExecutionError])
case xs =>
Expand Down Expand Up @@ -729,7 +729,7 @@ object Functions {
case CONST_BYTESTR(id: ByteStr) :: Nil =>
env
.transferTransactionById(id.arr)
.map(_.filter(version >= V6 || _.p.h.version > 0).map(transactionObject(_, proofsEnabled, version)))
.map(_.filter(version >= V6 || _.p.h.version > 0).map(transactionObject(_, proofsEnabled, version, fixBigScriptField = false)))
.map(fromOptionCO)
.map(_.asRight[ExecutionError])
case xs =>
Expand Down Expand Up @@ -801,7 +801,7 @@ object Functions {
env
.transferTransactionFromProto(bytes.arr)
.map(tx =>
(tx.map(transactionObject(_, proofsEnabled, version)): EVALUATED)
(tx.map(transactionObject(_, proofsEnabled, version, fixBigScriptField = false)): EVALUATED)
.asRight[ExecutionError]
)

Expand Down
Expand Up @@ -18,23 +18,24 @@ object Vals {
def tx(
isTokenContext: Boolean,
version: StdLibVersion,
proofsEnabled: Boolean
proofsEnabled: Boolean,
fixBigScriptField: Boolean
): (String, (UNION, ContextfulVal[Environment])) =
("tx", (scriptInputType(isTokenContext, version, proofsEnabled), inputEntityVal(version, proofsEnabled)))
("tx", (scriptInputType(isTokenContext, version, proofsEnabled), inputEntityVal(version, proofsEnabled, fixBigScriptField)))

private def scriptInputType(isTokenContext: Boolean, version: StdLibVersion, proofsEnabled: Boolean) =
if (isTokenContext)
UNION(buildAssetSupportedTransactions(proofsEnabled, version))
else
UNION(buildOrderType(proofsEnabled) :: buildActiveTransactionTypes(proofsEnabled, version))

private def inputEntityVal(version: StdLibVersion, proofsEnabled: Boolean): ContextfulVal[Environment] =
private def inputEntityVal(version: StdLibVersion, proofsEnabled: Boolean, fixBigScriptField: Boolean): ContextfulVal[Environment] =
new ContextfulVal.Lifted[Environment] {
override def liftF[F[_]: Monad](env: Environment[F]): Eval[Either[ExecutionError, EVALUATED]] =
Eval.later(
env.inputEntity
.eliminate(
tx => transactionObject(tx, proofsEnabled, version).asRight[ExecutionError],
tx => transactionObject(tx, proofsEnabled, version, fixBigScriptField).asRight[ExecutionError],
_.eliminate(
o => orderObject(o, proofsEnabled, version).asRight[ExecutionError],
_.eliminate(
Expand Down
Expand Up @@ -13,8 +13,8 @@ import com.wavesplatform.lang.v1.traits.*
import com.wavesplatform.lang.v1.{BaseGlobal, CTX}

object WavesContext {
def build(global: BaseGlobal, ds: DirectiveSet): CTX[Environment] =
invariableCtx |+| variableCtxCache(global, ds)
def build(global: BaseGlobal, ds: DirectiveSet, fixBigScriptField: Boolean): CTX[Environment] =
invariableCtx |+| variableCtx(global, ds, fixBigScriptField)

private val commonFunctions =
Array(
Expand All @@ -41,25 +41,15 @@ object WavesContext {
private val invariableCtx =
CTX(Seq(), Map(height), commonFunctions)

private val ctxCache = scala.collection.mutable.AnyRefMap.empty[(BaseGlobal, DirectiveSet), CTX[Environment]]

private def variableCtxCache(global: BaseGlobal, ds: DirectiveSet) =
ctxCache.getOrElse(
(global, ds),
ctxCache.synchronized {
ctxCache.getOrElseUpdate((global, ds), variableCtx(global, ds))
}
)

private def variableCtx(global: BaseGlobal, ds: DirectiveSet): CTX[Environment] = {
private def variableCtx(global: BaseGlobal, ds: DirectiveSet, fixBigScriptField: Boolean): CTX[Environment] = {
val isTokenContext = ds.scriptType == Asset
val proofsEnabled = !isTokenContext
val version = ds.stdLibVersion
val types = variableTypes(version, proofsEnabled)
val typeDefs = types.view.map(t => t.name -> t).toMap
CTX(
types,
variableVars(isTokenContext, version, ds.contentType, proofsEnabled),
variableVars(isTokenContext, version, ds.contentType, proofsEnabled, fixBigScriptField),
variableFuncs(global, ds, typeDefs, proofsEnabled)
)
}
Expand Down Expand Up @@ -142,9 +132,10 @@ object WavesContext {
isTokenContext: Boolean,
version: StdLibVersion,
contentType: ContentType,
proofsEnabled: Boolean
proofsEnabled: Boolean,
fixBigScriptField: Boolean
): Map[String, (FINAL, ContextfulVal[Environment])] = {
val txVal = tx(isTokenContext, version, proofsEnabled)
val txVal = tx(isTokenContext, version, proofsEnabled, fixBigScriptField)
version match {
case V1 => Map(txVal)
case V2 => Map(sell, buy, txVal)
Expand Down
Expand Up @@ -23,16 +23,18 @@ class TestCompiler(version: StdLibVersion) {

private lazy val compilerContext =
(baseCompilerContext |+|
WavesContext.build(Global, DirectiveSet(version, Account, DAppType).explicitGet())).compilerContext
WavesContext.build(Global, DirectiveSet(version, Account, DAppType).explicitGet(), fixBigScriptField = true)).compilerContext

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

lazy val expressionContext: CTX[Environment] = WavesContext.build(Global, DirectiveSet(version, Account, Expression).explicitGet())
private lazy val expressionCompilerContext =
(baseCompilerContext |+|
expressionContext).compilerContext

private lazy val assetCompilerContext =
(baseCompilerContext |+|
WavesContext.build(Global, DirectiveSet(version, Asset, Expression).explicitGet())).compilerContext
WavesContext.build(Global, DirectiveSet(version, Asset, Expression).explicitGet(), fixBigScriptField = true)).compilerContext

def compile(
script: String,
Expand Down
Expand Up @@ -28,7 +28,8 @@ class ContractIntegrationTest extends PropSpec with Inside {
CTX[Environment](sampleTypes, Map.empty, Array.empty) |+|
WavesContext.build(
Global,
DirectiveSet(V3, Account, DApp).explicitGet()
DirectiveSet(V3, Account, DApp).explicitGet(),
fixBigScriptField = true
)

private val environment: Environment[Id] =
Expand Down Expand Up @@ -182,7 +183,7 @@ class ContractIntegrationTest extends PropSpec with Inside {
def parseCompileAndVerify(script: String, tx: Tx): Either[ExecutionError, EVALUATED] = {
val parsed = Parser.parseContract(script).get.value
val compiled = ContractCompiler(ctx.compilerContext, parsed, V3).explicitGet()
val txObject = Bindings.transactionObject(tx, proofsEnabled = true, V3)
val txObject = Bindings.transactionObject(tx, proofsEnabled = true, V3, fixBigScriptField = true)
ContractEvaluator
.verify(
compiled.decs,
Expand Down

0 comments on commit ef76fd7

Please sign in to comment.