diff --git a/data/shared/src/main/scala/sigma/ast/SigmaPredef.scala b/data/shared/src/main/scala/sigma/ast/SigmaPredef.scala index 631f7f2d75..716b167e2b 100644 --- a/data/shared/src/main/scala/sigma/ast/SigmaPredef.scala +++ b/data/shared/src/main/scala/sigma/ast/SigmaPredef.scala @@ -136,17 +136,6 @@ object SigmaPredef { Seq(ArgInfo("condition", "boolean value to embed in SigmaProp value"))) ) - val GetVarFunc = PredefinedFunc("getVar", - Lambda(Array(paramT), Array("varId" -> SByte), SOption(tT), None), - PredefFuncInfo( - { case (Ident(_, SFunc(_, SOption(rtpe), _)), Seq(id: Constant[SNumericType]@unchecked)) => - mkGetVar(SByte.downcast(id.value.asInstanceOf[AnyVal]), rtpe) - }), - OperationInfo(GetVar, - "Get context variable with given \\lst{varId} and type.", - Seq(ArgInfo("varId", "\\lst{Byte} identifier of context variable"))) - ) - def PKFunc(networkPrefix: NetworkPrefix) = PredefinedFunc("PK", Lambda(Array("input" -> SString), SSigmaProp, None), PredefFuncInfo( @@ -366,13 +355,23 @@ object SigmaPredef { ArgInfo("newValues", "new values to be injected into the corresponding positions in ErgoTree.constants array"))) ) + val GetVarFunc = PredefinedFunc("getVar", + Lambda(Array(paramT), Array("varId" -> SByte), SOption(tT), None), + PredefFuncInfo( + { case (Ident(_, SFunc(_, SOption(rtpe), _)), Seq(id: Constant[SNumericType]@unchecked)) => + mkGetVar(SByte.downcast(id.value.asInstanceOf[AnyVal]), rtpe) + }), + OperationInfo(GetVar, + "Get context variable with given \\lst{varId} and type.", + Seq(ArgInfo("varId", "\\lst{Byte} identifier of context variable"))) + ) + val ExecuteFromVarFunc = PredefinedFunc("executeFromVar", - Lambda( - Seq(paramT), - Array("id" -> SByte), - tT, None - ), - PredefFuncInfo(undefined), + Lambda(Array(paramT), Array("id" -> SByte), tT, None), + PredefFuncInfo( + { case (Ident(_, SFunc(_, rtpe, _)), Seq(id: Constant[SNumericType]@unchecked)) => + mkDeserializeContext(SByte.downcast(id.value.asInstanceOf[AnyVal]), rtpe) + }), OperationInfo(DeserializeContext, """Extracts context variable as \lst{Coll[Byte]}, deserializes it to script | and then executes this script in the current context. diff --git a/interpreter/shared/src/main/scala/sigmastate/interpreter/Interpreter.scala b/interpreter/shared/src/main/scala/sigmastate/interpreter/Interpreter.scala index 9a1ab11f0e..8e8da22462 100644 --- a/interpreter/shared/src/main/scala/sigmastate/interpreter/Interpreter.scala +++ b/interpreter/shared/src/main/scala/sigmastate/interpreter/Interpreter.scala @@ -126,7 +126,7 @@ trait Interpreter { case _ => None } - /** Extracts proposition for ErgoTree handing soft-fork condition. + /** Extracts proposition for ErgoTree handling soft-fork condition. * @note soft-fork handler */ protected def propositionFromErgoTree(ergoTree: ErgoTree, context: CTX): SigmaPropValue = { val validationSettings = context.validationSettings diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/Base.scala b/sc/shared/src/main/scala/sigma/compiler/ir/Base.scala index 48e3e5d09e..54df41af53 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/Base.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/Base.scala @@ -2,8 +2,9 @@ package sigma.compiler.ir import debox.{cfor, Buffer => DBuffer} import sigma.compiler.ir.core.MutableLazy -import sigma.data.OverloadHack.Overloaded1 +import sigma.ast.{DeserializeContext, SType} import sigma.data.{AVHashMap, Nullable, RType} +import sigma.data.OverloadHack.Overloaded1 import sigma.reflection.RConstructor import sigma.util.StringUtil @@ -169,7 +170,7 @@ abstract class Base { thisIR: IRContext => /** Create a copy of this definition applying the given transformer to all `syms`. */ def transform(t: Transformer): Def[T] = - !!!(s"Cannot transfrom definition using transform($this)", self) + !!!(s"Cannot transform definition using transform($this)", self) /** Clone this definition transforming all symbols using `t`. * If new Def[A] is created, it is added to the graph with collapsing and rewriting. @@ -203,10 +204,11 @@ abstract class Base { thisIR: IRContext => } } - /** Logical AND between two pattern matches of the save value `x`. - * Can be used to construct patterns like `case P1 && P2 => ...` */ - object && { - def unapply[T](x: T): Option[(T,T)] = Some((x, x)) + /** + * Def done in order to carry on DeserializeContext through stages of compilation intact + */ + case class DeserializeContextDef[V <: SType](d: DeserializeContext[V], e: Elem[V]) extends Def[V] { + override def resultType: Elem[V] = e } /** Base class for virtualized instances of type companions. @@ -383,7 +385,6 @@ abstract class Base { thisIR: IRContext => /** Returns the string like `x45: Int = Const(10)` */ def toStringWithDefinition: String def varNameWithType = varName + ":" + elem.name - } /** Untyped shortcut sinonim of Ref, which is used as untyped reference to graph nodes (definitions). diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/GraphBuilding.scala b/sc/shared/src/main/scala/sigma/compiler/ir/GraphBuilding.scala index 7c7b80d39a..99285814cb 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/GraphBuilding.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/GraphBuilding.scala @@ -549,6 +549,10 @@ trait GraphBuilding extends Base with DefRewriting { IR: IRContext => val e = stypeToElem(optTpe.elemType) ctx.getVar(id)(e) + case d: DeserializeContext[T] => + val e = stypeToElem(d.tpe).asInstanceOf[Elem[T]] + DeserializeContextDef(d, e) + case ValUse(valId, _) => env.getOrElse(valId, !!!(s"ValUse $valId not found in environment $env")) diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/TreeBuilding.scala b/sc/shared/src/main/scala/sigma/compiler/ir/TreeBuilding.scala index 725e3b1d19..000f1d16bc 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/TreeBuilding.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/TreeBuilding.scala @@ -189,6 +189,9 @@ trait TreeBuilding extends Base { IR: IRContext => val tpe = elemToSType(s.elem) mkConstant[tpe.type](wc.constValue.asInstanceOf[tpe.WrappedType], tpe) + case Def(DeserializeContextDef(d, _)) => + d + case Def(IsContextProperty(v)) => v case s if s == sigmaDslBuilder => Global diff --git a/sc/shared/src/main/scala/sigma/compiler/phases/SigmaTyper.scala b/sc/shared/src/main/scala/sigma/compiler/phases/SigmaTyper.scala index 679d98a18f..f6477ea3b2 100644 --- a/sc/shared/src/main/scala/sigma/compiler/phases/SigmaTyper.scala +++ b/sc/shared/src/main/scala/sigma/compiler/phases/SigmaTyper.scala @@ -37,7 +37,7 @@ class SigmaTyper(val builder: SigmaBuilder, private def processGlobalMethod(srcCtx: Nullable[SourceContext], method: SMethod, - args: IndexedSeq[SValue]) = { + args: IndexedSeq[SValue]): SValue = { val global = Global.withPropagatedSrcCtx(srcCtx) val node = for { pf <- method.irInfo.irBuilder if lowerMethodCalls diff --git a/sc/shared/src/test/scala/sigma/SigmaDslTesting.scala b/sc/shared/src/test/scala/sigma/SigmaDslTesting.scala index 31e873699b..ed6d380cf2 100644 --- a/sc/shared/src/test/scala/sigma/SigmaDslTesting.scala +++ b/sc/shared/src/test/scala/sigma/SigmaDslTesting.scala @@ -323,7 +323,7 @@ class SigmaDslTesting extends AnyPropSpec // Compile script the same way it is performed by applications (i.e. via Ergo Appkit) val prop = compile(env, code)(IR).asSigmaProp - // Add additional oparations which are not yet implemented in ErgoScript compiler + // Add additional operations which are not yet implemented in ErgoScript compiler val multisig = AtLeast( IntConstant(2), Array( diff --git a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala index 79701d6e07..8c75544af3 100644 --- a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala @@ -2,6 +2,7 @@ package sigmastate.utxo import org.ergoplatform.ErgoBox.{AdditionalRegisters, R6, R8} import org.ergoplatform._ +import sigma.Colls import sigma.Extensions.ArrayOps import sigma.ast.SCollection.SByteArray import sigma.ast.SType.AnyOps @@ -19,6 +20,7 @@ import sigmastate.interpreter.Interpreter._ import sigma.ast.Apply import sigma.eval.EvalSettings import sigma.exceptions.InvalidType +import sigma.serialization.ValueSerializer import sigmastate.utils.Helpers._ import java.math.BigInteger @@ -157,6 +159,50 @@ class BasicOpsSpecification extends CompilerTestingCommons ) } + property("executeFromVar - SigmaProp") { + val script = GT(Height, IntConstant(-1)).toSigmaProp + val scriptBytes = ValueSerializer.serialize(script) + val customExt = Seq(21.toByte -> ByteArrayConstant(scriptBytes)) + test("executeFromVar", env, customExt, + "executeFromVar[SigmaProp](21)", + null, + true + ) + } + + property("executeFromVar - Int") { + val valueBytes = ValueSerializer.serialize(Plus(IntConstant(2), IntConstant(3))) + val customExt = Seq(21.toByte -> ByteArrayConstant(valueBytes)) + test("executeFromVar", env, customExt, + "{ executeFromVar[Int](21) == 5 }", + null, + true + ) + } + + property("executeFromVar - Coll[Byte]") { + val bytes = Slice(ByteArrayConstant(Colls.fromArray(Array.fill(5)(1.toByte))), IntConstant(1), IntConstant(3)) + val valueBytes = ValueSerializer.serialize(bytes) + val customExt = Seq(21.toByte -> ByteArrayConstant(valueBytes)) + test("executeFromVar", env, customExt, + "{val ba = executeFromVar[Coll[Byte]](21); ba.size == 2 }", + null, + true + ) + } + + // test which is showing impossibility of nested Deserialize* + property("executeFromVar - deserialize") { + val script = DeserializeContext(21.toByte, SSigmaProp) + val scriptBytes = ValueSerializer.serialize(script) + val customExt = Seq(21.toByte -> ByteArrayConstant(scriptBytes)) + an [Exception] should be thrownBy test("executeFromVar", env, customExt, + "executeFromVar[SigmaProp](21)", + null, + true + ) + } + property("Relation operations") { test("R1", env, ext, "{ allOf(Coll(getVar[Boolean](trueVar).get, true, true)) }", diff --git a/sc/shared/src/test/scala/sigmastate/utxo/examples/ExecuteFromExamplesSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/examples/ExecuteFromExamplesSpecification.scala index b75b404aed..741b4829cf 100644 --- a/sc/shared/src/test/scala/sigmastate/utxo/examples/ExecuteFromExamplesSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/utxo/examples/ExecuteFromExamplesSpecification.scala @@ -9,8 +9,6 @@ import sigma.ast.ByteArrayConstant class ExecuteFromExamplesSpecification extends CompilerTestingCommons { suite => implicit lazy val IR = new TestingIRContext - private val reg1 = ErgoBox.nonMandatoryRegisters(0) - case class OracleContract[Spec <: ContractSpec] (alice: Spec#ProvingParty) (implicit val spec: Spec) extends SigmaContractSyntax with StdContracts @@ -40,8 +38,7 @@ class ExecuteFromExamplesSpecification extends CompilerTestingCommons { suite => lazy val alice = spec.ProvingParty("Alice") - // TODO soft-fork: related to https://github.com/ScorexFoundation/sigmastate-interpreter/issues/443 - ignore("Execute from var example (ErgoDsl)") { + property("Execute from var example (ErgoDsl)") { val contract = OracleContract[spec.type](alice)(spec) import contract.spec._