diff --git a/README.md b/README.md
index 64f08f0277..6003daf55a 100644
--- a/README.md
+++ b/README.md
@@ -16,6 +16,10 @@ For development of Ergo applications using JVM languages (Java/Scala/Kotlin/etc)
a better alternative is to use
[Appkit](https://github.com/ergoplatform/ergo-appkit).
+The library is cross-compiled to JS using Scala.js and the main abstractions can be used
+from JS directly by importing [NPM module](https://www.npmjs.com/package/sigmastate-js).
+See [README](sigma-js/README.md) for details.
+
## Sigma Language Background
Every coin in Bitcoin is protected by a program in the stack-based Script
@@ -93,19 +97,21 @@ This library is
on Maven repository and can be added to the SBT configuration of Scala project.
```scala
-libraryDependencies += "org.scorexfoundation" %% "sigma-state" % "5.0.6"
+libraryDependencies += "org.scorexfoundation" %% "sigma-state" % "5.0.14"
```
## Repository Organization
-| sub-module | description |
-|-------------|-------------------------------------------------------------------------------------------|
-| common | Used in all other submodules and contain basic utility classes |
-| core-lib | Contains core classes such as Coll, BigInt used by interpreter |
-| docs | Collection of documents |
-| graph-ir | Implementation of graph-based intermediate representation of ErgoTree, which is used in by ErgoScript compiler |
-| interpreter | Implementation of ErgoTree Interpreter |
-| sc | Implementation of ErgoScript compiler |
+| sub-module | description |
+|-------------|------------------------------------------------------------------------------------|
+| core | contains core classes of Sigma library |
+| data | contains classes for working with ErgoTree, addresses and all related serializers |
+| docs | Collection of documents |
+| interpreter | contains an implementation of ErgoTree Interpreter |
+| sdk | contains and implementation of transaction reduction and signing |
+| parsers | contains an implementation of ErgoScript parsers using FastParse library |
+| sc | contains an implementation of ErgoScript compiler |
+| sigma-js | root directory of sigmastate-js JS module (see [package.json](sigma-js/README.md)) |
## Contributing
@@ -151,12 +157,13 @@ innovative and intelligent tools for profiling Java and .NET applications.
- [Ergo Site](https://ergoplatform.org/en/)
- [Ergo Sources](https://github.com/ergoplatform/ergo)
+- [Sigma-js](https://www.npmjs.com/package/sigmastate-js)
- [Ergo Appkit](https://github.com/ergoplatform/ergo-appkit)
- [Ergo Appkit Examples](https://github.com/aslesarenko/ergo-appkit-examples)
- [ergo-android](https://github.com/aslesarenko/ergo-android)
- [ergo-wallet-android](https://github.com/MrStahlfelge/ergo-wallet-android)
- [ErgoTree Specification](https://ergoplatform.org/docs/ErgoTree.pdf)
-- [Ergo Documents](https://ergoplatform.org/en/documents/)
+- [Ergo Documents](https://docs.ergoplatform.org/)
diff --git a/build.sbt b/build.sbt
index a76c73d885..85c59512d6 100644
--- a/build.sbt
+++ b/build.sbt
@@ -1,6 +1,6 @@
import scala.language.postfixOps
-import scala.sys.process._
-import org.scalajs.linker.interface.CheckedBehavior
+import scala.sys.process.*
+import org.scalajs.linker.interface.{CheckedBehavior, ModuleSplitStyle}
organization := "org.scorexfoundation"
@@ -196,7 +196,12 @@ lazy val core = crossProject(JVMPlatform, JSPlatform)
scorexUtilDependency,
publish / skip := true
)
- .jvmSettings( crossScalaSettings )
+ .jvmSettings(
+ crossScalaSettings,
+ libraryDependencies ++= Seq(
+ bouncycastleBcprov
+ )
+ )
.jsSettings(
crossScalaSettingsJS,
scalacOptions ++= Seq(
@@ -212,10 +217,40 @@ lazy val core = crossProject(JVMPlatform, JSPlatform)
)
lazy val coreJS = core.js
.enablePlugins(ScalaJSBundlerPlugin)
+ .enablePlugins(ScalablyTypedConverterGenSourcePlugin)
+ .settings(
+ stOutputPackage := "sigmastate",
+ scalaJSLinkerConfig ~= { conf =>
+ conf.withSourceMap(false)
+ .withModuleKind(ModuleKind.CommonJSModule)
+ },
+ Compile / npmDependencies ++= Seq(
+ "sigmajs-crypto-facade" -> sigmajsCryptoFacadeVersion,
+ "@fleet-sdk/common" -> "0.1.3"
+ )
+ )
+
+lazy val data = crossProject(JVMPlatform, JSPlatform)
+ .in(file("data"))
+ .dependsOn(core % allConfigDependency)
+ .settings(
+ commonSettings ++ testSettings2,
+ commonDependenies2,
+ testingDependencies2,
+ scorexUtilDependency, fastparseDependency, circeDependency, scryptoDependency,
+ publish / skip := true
+ )
+ .jvmSettings( crossScalaSettings )
+ .jsSettings(
+ crossScalaSettingsJS,
+ useYarn := true
+ )
+lazy val dataJS = data.js
+ .enablePlugins(ScalaJSBundlerPlugin)
lazy val interpreter = crossProject(JVMPlatform, JSPlatform)
.in(file("interpreter"))
- .dependsOn(core % allConfigDependency)
+ .dependsOn(core % allConfigDependency, data % allConfigDependency)
.settings(
commonSettings ++ testSettings2,
commonDependenies2,
@@ -226,24 +261,10 @@ lazy val interpreter = crossProject(JVMPlatform, JSPlatform)
.jvmSettings( crossScalaSettings )
.jsSettings(
crossScalaSettingsJS,
- libraryDependencies ++= Seq (
- "org.scala-js" %%% "scala-js-macrotask-executor" % "1.0.0"
- ),
useYarn := true
)
lazy val interpreterJS = interpreter.js
.enablePlugins(ScalaJSBundlerPlugin)
- .enablePlugins(ScalablyTypedConverterGenSourcePlugin)
- .settings(
- stOutputPackage := "sigmastate",
- scalaJSLinkerConfig ~= { conf =>
- conf.withSourceMap(false)
- },
- Compile / npmDependencies ++= Seq(
- "sigmajs-crypto-facade" -> sigmajsCryptoFacadeVersion,
- "@fleet-sdk/common" -> "0.1.3"
- )
- )
lazy val parsers = crossProject(JVMPlatform, JSPlatform)
.in(file("parsers"))
@@ -260,9 +281,6 @@ lazy val parsers = crossProject(JVMPlatform, JSPlatform)
)
.jsSettings(
crossScalaSettingsJS,
- libraryDependencies ++= Seq(
- "org.scala-js" %%% "scala-js-macrotask-executor" % "1.0.0"
- ),
useYarn := true
)
lazy val parsersJS = parsers.js
@@ -271,18 +289,16 @@ lazy val parsersJS = parsers.js
scalaJSLinkerConfig ~= { conf =>
conf.withSourceMap(false)
},
- Compile / npmDependencies ++= Seq(
- "sigmajs-crypto-facade" -> sigmajsCryptoFacadeVersion
- )
)
lazy val sdk = crossProject(JVMPlatform, JSPlatform)
.in(file("sdk"))
- .dependsOn(core % allConfigDependency, interpreter % allConfigDependency, parsers % allConfigDependency)
+ .dependsOn(core % allConfigDependency, data % allConfigDependency, interpreter % allConfigDependency, parsers % allConfigDependency)
.settings(commonSettings ++ testSettings2,
commonDependenies2,
testingDependencies2,
scodecBitsDependency,
+ circeDependency,
publish / skip := true
)
.jvmSettings(
@@ -290,9 +306,6 @@ lazy val sdk = crossProject(JVMPlatform, JSPlatform)
)
.jsSettings(
crossScalaSettingsJS,
- libraryDependencies ++= Seq(
- "org.scala-js" %%% "scala-js-macrotask-executor" % "1.0.0"
- ),
useYarn := true
)
lazy val sdkJS = sdk.js
@@ -302,9 +315,6 @@ lazy val sdkJS = sdk.js
conf.withSourceMap(false)
.withModuleKind(ModuleKind.CommonJSModule)
},
- Compile / npmDependencies ++= Seq(
- "sigmajs-crypto-facade" -> sigmajsCryptoFacadeVersion
- )
)
lazy val sc = crossProject(JVMPlatform, JSPlatform)
@@ -348,20 +358,17 @@ lazy val scJS = sc.js
.withArrayIndexOutOfBounds(CheckedBehavior.Compliant)
)
},
- Compile / npmDependencies ++= Seq(
- "sigmajs-crypto-facade" -> sigmajsCryptoFacadeVersion
- )
)
lazy val sigma = (project in file("."))
- .aggregate(core.jvm, interpreter.jvm, parsers.jvm, sdk.jvm, sc.jvm)
+ .aggregate(core.jvm, data.jvm, interpreter.jvm, parsers.jvm, sdk.jvm, sc.jvm)
.settings(libraryDefSettings, rootSettings)
.settings(publish / aggregate := false)
.settings(publishLocal / aggregate := false)
lazy val aggregateCompile = ScopeFilter(
- inProjects(core.jvm, interpreter.jvm, parsers.jvm, sdk.jvm, sc.jvm),
+ inProjects(core.jvm, data.jvm, interpreter.jvm, parsers.jvm, sdk.jvm, sc.jvm),
inConfigurations(Compile))
lazy val rootSettings = Seq(
diff --git a/interpreter/js/src/main/scala/sigmastate/crypto/Platform.scala b/core/js/src/main/scala/sigma/crypto/Platform.scala
similarity index 96%
rename from interpreter/js/src/main/scala/sigmastate/crypto/Platform.scala
rename to core/js/src/main/scala/sigma/crypto/Platform.scala
index fdb3b128fd..88001ba140 100644
--- a/interpreter/js/src/main/scala/sigmastate/crypto/Platform.scala
+++ b/core/js/src/main/scala/sigma/crypto/Platform.scala
@@ -1,10 +1,10 @@
-package sigmastate.crypto
+package sigma.crypto
import sigma.data.RType
import scorex.util.encode.Base16
-import sigmastate._
import sigma.Coll
import sigma._
+import sigma.ast._
import java.math.BigInteger
import scala.scalajs.js
@@ -128,7 +128,7 @@ object Platform {
class Curve
// TODO JS: Use JS library for secure source of randomness
- type SecureRandom = sigmastate.crypto.SecureRandomJS
+ type SecureRandom = sigma.crypto.SecureRandomJS
/** Opaque point type. */
@js.native
@@ -184,28 +184,28 @@ object Platform {
private val ctx = new CryptoContextJs
/** The underlying elliptic curve descriptor. */
- override def curve: crypto.Curve = ???
+ override def curve: Curve = ???
override def fieldCharacteristic: BigInteger = Convert.bigIntToBigInteger(ctx.getModulus())
override def order: BigInteger = Convert.bigIntToBigInteger(ctx.getOrder())
- override def validatePoint(x: BigInteger, y: BigInteger): crypto.Ecp = {
+ override def validatePoint(x: BigInteger, y: BigInteger): Ecp = {
val point = ctx.validatePoint(Convert.bigIntegerToBigInt(x), Convert.bigIntegerToBigInt(y))
new Ecp(point)
}
- override def infinity(): crypto.Ecp =
+ override def infinity(): Ecp =
new Ecp(ctx.getInfinity())
- override def decodePoint(encoded: Array[Byte]): crypto.Ecp = {
+ override def decodePoint(encoded: Array[Byte]): Ecp = {
if (encoded(0) == 0) {
return infinity()
}
new Ecp(ctx.decodePoint(Base16.encode(encoded)))
}
- override def generator: crypto.Ecp =
+ override def generator: Ecp =
new Ecp(ctx.getGenerator())
}
diff --git a/interpreter/js/src/main/scala/sigmastate/crypto/SigmaJsCryptoFacade.scala b/core/js/src/main/scala/sigma/crypto/SigmaJsCryptoFacade.scala
similarity index 99%
rename from interpreter/js/src/main/scala/sigmastate/crypto/SigmaJsCryptoFacade.scala
rename to core/js/src/main/scala/sigma/crypto/SigmaJsCryptoFacade.scala
index fa60015ed2..4d269534cc 100644
--- a/interpreter/js/src/main/scala/sigmastate/crypto/SigmaJsCryptoFacade.scala
+++ b/core/js/src/main/scala/sigma/crypto/SigmaJsCryptoFacade.scala
@@ -1,4 +1,4 @@
-package sigmastate.crypto
+package sigma.crypto
import debox.cfor
diff --git a/core/js/src/main/scala/sigma/js/AvlTree.scala b/core/js/src/main/scala/sigma/js/AvlTree.scala
new file mode 100644
index 0000000000..f882ef0863
--- /dev/null
+++ b/core/js/src/main/scala/sigma/js/AvlTree.scala
@@ -0,0 +1,50 @@
+package sigma.js
+
+import sigma.Extensions.ArrayOps
+import sigma.data.Iso.{isoStringToArray, isoStringToColl}
+import sigma.data.{AvlTreeData, AvlTreeFlags, CAvlTree, Iso}
+
+import scala.scalajs.js
+import scala.scalajs.js.UndefOr
+import scala.scalajs.js.annotation.JSExportTopLevel
+
+/** Equivalent of [[sigma.AvlTree]] available from JS. */
+@JSExportTopLevel("AvlTree")
+class AvlTree(
+ val digest: String,
+ val insertAllowed: Boolean,
+ val updateAllowed: Boolean,
+ val removeAllowed: Boolean,
+ val keyLength: Int,
+ val valueLengthOpt: UndefOr[Int]
+) extends js.Object
+
+object AvlTree {
+
+ implicit val isoAvlTree: Iso[AvlTree, sigma.AvlTree] = new Iso[AvlTree, sigma.AvlTree] {
+ override def to(x: AvlTree): sigma.AvlTree = {
+ CAvlTree(
+ AvlTreeData(
+ digest = isoStringToArray.to(x.digest).toColl,
+ treeFlags = AvlTreeFlags(x.insertAllowed, x.updateAllowed, x.removeAllowed),
+ x.keyLength,
+ valueLengthOpt = sigma.js.Isos.isoUndefOr(Iso.identityIso[Int]).to(x.valueLengthOpt),
+ ),
+ )
+ }
+
+ override def from(x: sigma.AvlTree): AvlTree = {
+ val tree = x.asInstanceOf[CAvlTree]
+ val data = tree.treeData
+ new AvlTree(
+ digest = isoStringToColl.from(tree.digest),
+ insertAllowed = data.treeFlags.insertAllowed,
+ updateAllowed = data.treeFlags.updateAllowed,
+ removeAllowed = data.treeFlags.removeAllowed,
+ keyLength = data.keyLength,
+ valueLengthOpt = sigma.js.Isos.isoUndefOr(Iso.identityIso[Int]).from(data.valueLengthOpt),
+ )
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/sdk/js/src/main/scala/org/ergoplatform/sdk/js/GroupElement.scala b/core/js/src/main/scala/sigma/js/GroupElement.scala
similarity index 81%
rename from sdk/js/src/main/scala/org/ergoplatform/sdk/js/GroupElement.scala
rename to core/js/src/main/scala/sigma/js/GroupElement.scala
index 857592d4a2..21b53b265d 100644
--- a/sdk/js/src/main/scala/org/ergoplatform/sdk/js/GroupElement.scala
+++ b/core/js/src/main/scala/sigma/js/GroupElement.scala
@@ -1,7 +1,7 @@
-package org.ergoplatform.sdk.js
+package sigma.js
-import sigmastate.crypto.{CryptoFacade, CryptoFacadeJs, Ecp, Platform}
-import sigmastate.eval.Extensions.ArrayByteOps
+import sigma.Extensions.CoreArrayByteOps
+import sigma.crypto.{CryptoFacade, CryptoFacadeJs, Ecp, Platform}
import scala.scalajs.js
import scala.scalajs.js.annotation.JSExportTopLevel
@@ -17,7 +17,7 @@ class GroupElement(val point: Ecp) extends js.Object {
}
}
-@JSExportTopLevel("GroupElementObj")
+@JSExportTopLevel("GroupElement$")
object GroupElement extends js.Object {
/** Creates a new [[GroupElement]] from the given hex string (ASN.1 encoding)
* representation of the underlying [[sigmastate.crypto.Platform.Point]].
diff --git a/core/js/src/main/scala/sigma/js/Isos.scala b/core/js/src/main/scala/sigma/js/Isos.scala
new file mode 100644
index 0000000000..b28a3337b8
--- /dev/null
+++ b/core/js/src/main/scala/sigma/js/Isos.scala
@@ -0,0 +1,47 @@
+package sigma.js
+
+import sigma.{Coll, Colls}
+import sigma.data.{CBigInt, Iso, RType}
+
+import java.math.BigInteger
+import scala.reflect.ClassTag
+import scala.scalajs.js
+import scala.scalajs.js.JSConverters.JSRichOption
+
+object Isos {
+
+ implicit def isoUndefOr[A, B](implicit iso: Iso[A, B]): Iso[js.UndefOr[A], Option[B]] = new Iso[js.UndefOr[A], Option[B]] {
+ override def to(x: js.UndefOr[A]): Option[B] = x.toOption.map(iso.to)
+ override def from(x: Option[B]): js.UndefOr[A] = x.map(iso.from).orUndefined
+ }
+
+ implicit def isoArrayToColl[A, B](iso: Iso[A, B])
+ (implicit ctA: ClassTag[A], tB: RType[B]): Iso[js.Array[A], Coll[B]] = new Iso[js.Array[A], Coll[B]] {
+ override def to(x: js.Array[A]): Coll[B] = Colls.fromArray(x.map(iso.to).toArray(tB.classTag))
+ override def from(x: Coll[B]): js.Array[A] = js.Array(x.toArray.map(iso.from): _*)
+ }
+
+ implicit def isoArrayToIndexed[A, B](iso: Iso[A, B])
+ (implicit cB: ClassTag[B]): Iso[js.Array[A], IndexedSeq[B]] = new Iso[js.Array[A], IndexedSeq[B]] {
+ override def to(x: js.Array[A]): IndexedSeq[B] = x.map(iso.to).toArray(cB).toIndexedSeq
+ override def from(x: IndexedSeq[B]): js.Array[A] = js.Array(x.map(iso.from): _*)
+ }
+
+ implicit val isoBigInt: Iso[js.BigInt, sigma.BigInt] = new Iso[js.BigInt, sigma.BigInt] {
+ override def to(x: js.BigInt): sigma.BigInt = {
+ CBigInt(new BigInteger(x.toString(10)))
+ }
+
+ override def from(x: sigma.BigInt): js.BigInt = {
+ val bi = x.asInstanceOf[CBigInt].wrappedValue
+ val s = bi.toString(10)
+ js.BigInt(s)
+ }
+ }
+
+ implicit val isoBigIntToLong: Iso[js.BigInt, Long] = new Iso[js.BigInt, Long] {
+ override def to(x: js.BigInt): Long = java.lang.Long.parseLong(x.toString(10))
+
+ override def from(x: Long): js.BigInt = js.BigInt(x.toString)
+ }
+}
diff --git a/core/js/src/main/scala/sigma/js/JsWrapper.scala b/core/js/src/main/scala/sigma/js/JsWrapper.scala
new file mode 100644
index 0000000000..e62cb70c11
--- /dev/null
+++ b/core/js/src/main/scala/sigma/js/JsWrapper.scala
@@ -0,0 +1,8 @@
+package sigma.js
+
+import scala.scalajs.js
+
+/** Base trait for all JS wrappers over some Scala type T. */
+trait JsWrapper[T] extends js.Object {
+ def wrappedValue: T
+}
diff --git a/core/js/src/main/scala/sigma/js/SigmaProp.scala b/core/js/src/main/scala/sigma/js/SigmaProp.scala
new file mode 100644
index 0000000000..40d311717d
--- /dev/null
+++ b/core/js/src/main/scala/sigma/js/SigmaProp.scala
@@ -0,0 +1,35 @@
+package sigma.js
+
+import sigma.data.{ProveDHTuple, ProveDlog, SigmaBoolean}
+
+import scala.scalajs.js
+import scala.scalajs.js.annotation.JSExportTopLevel
+
+/** Equivalent of [[sigma.SigmaProp]] available from JS. */
+@JSExportTopLevel("SigmaProp")
+class SigmaProp(val sigmaBoolean: SigmaBoolean) extends js.Object {
+}
+
+@JSExportTopLevel("SigmaProp$")
+object SigmaProp extends js.Object {
+ /** Creates a new [[SigmaProp]] from the given hex string of public key.
+ * @param pointHex hex representation of elliptic curve point (ASN.1 encoded)
+ * @see CryptoFacade.getASN1Encoding, GroupElement.fromPointHex, Point
+ */
+ def fromPointHex(pointHex: String): SigmaProp = {
+ val ge = GroupElement.fromPointHex(pointHex)
+ dlog(ge)
+ }
+
+ /** @param publicKey a [[GroupElement]] representing public key of discrete logarithm signature protocol
+ * @return a new [[SigmaProp]] value representing public key of discrete logarithm signature protocol.
+ */
+ def dlog(publicKey: GroupElement): SigmaProp = {
+ new SigmaProp(ProveDlog(publicKey.point))
+ }
+
+ /** Construct a new [[SigmaProp]] value representing public key of Diffie Hellman signature protocol. */
+ def dht(g: GroupElement, h: GroupElement, u: GroupElement, v: GroupElement): SigmaProp = {
+ new SigmaProp(ProveDHTuple(g.point, h.point, u.point, v.point))
+ }
+}
diff --git a/sdk/js/src/main/scala/org/ergoplatform/sdk/js/Type.scala b/core/js/src/main/scala/sigma/js/Type.scala
similarity index 83%
rename from sdk/js/src/main/scala/org/ergoplatform/sdk/js/Type.scala
rename to core/js/src/main/scala/sigma/js/Type.scala
index a0930cc99a..b323273a0c 100644
--- a/sdk/js/src/main/scala/org/ergoplatform/sdk/js/Type.scala
+++ b/core/js/src/main/scala/sigma/js/Type.scala
@@ -1,6 +1,7 @@
-package org.ergoplatform.sdk.js
+package sigma.js
-import sigma.data.RType
+import sigma.Evaluation
+import sigma.data.{Iso, RType}
import scala.scalajs.js
import scala.scalajs.js.annotation.JSExportTopLevel
@@ -10,14 +11,14 @@ import scala.scalajs.js.annotation.JSExportTopLevel
* wrapper around {@link RType} type descriptor.
*/
@JSExportTopLevel("Type")
-class Type(private[js] final val rtype: RType[_]) extends js.Object {
+class Type(final val rtype: RType[_]) extends js.Object {
/** Syntactically correct type name (type expression as String) */
def name: String = rtype.name
override def toString = s"Type($rtype)"
}
-@JSExportTopLevel("TypeObj")
+@JSExportTopLevel("Type$")
object Type extends js.Object {
/** Descriptor of ErgoScript type Byte. */
val Byte = new Type(sigma.ByteType)
@@ -75,4 +76,9 @@ object Type extends js.Object {
def collType(elemType: Type): Type = {
new Type(sigma.collRType(elemType.rtype))
}
+
+ implicit val isoToSType: Iso[Type, sigma.ast.SType] = new Iso[Type, sigma.ast.SType] {
+ override def to(x: Type): sigma.ast.SType = Evaluation.rtypeToSType(x.rtype)
+ override def from(x: sigma.ast.SType): Type = new Type(Evaluation.stypeToRType(x))
+ }
}
\ No newline at end of file
diff --git a/core/js/src/main/scala/sigma/js/Utils.scala b/core/js/src/main/scala/sigma/js/Utils.scala
new file mode 100644
index 0000000000..d19ef68d92
--- /dev/null
+++ b/core/js/src/main/scala/sigma/js/Utils.scala
@@ -0,0 +1,15 @@
+package sigma.js
+
+import scorex.util.encode.Base16
+
+import scala.scalajs.js
+import scala.scalajs.js.annotation.JSExportTopLevel
+import scala.scalajs.js.typedarray.Int8Array
+
+@JSExportTopLevel("Utils")
+object Utils extends js.Object {
+ /** Convert an Int8Array to a hex string. */
+ def int8ArrayToHex(arr: Int8Array): String = {
+ Base16.encode(arr.toArray)
+ }
+}
diff --git a/sdk/js/src/main/scala/org/ergoplatform/sdk/js/Value.scala b/core/js/src/main/scala/sigma/js/Value.scala
similarity index 79%
rename from sdk/js/src/main/scala/org/ergoplatform/sdk/js/Value.scala
rename to core/js/src/main/scala/sigma/js/Value.scala
index e3a3d15b9a..13b63c2abc 100644
--- a/sdk/js/src/main/scala/org/ergoplatform/sdk/js/Value.scala
+++ b/core/js/src/main/scala/sigma/js/Value.scala
@@ -1,19 +1,15 @@
-package org.ergoplatform.sdk.js
+package sigma
+package js
-import org.ergoplatform.sdk.js.Value.toRuntimeData
-import sigma.data.{CollType, RType}
-import sigma.data.PairType
import scorex.util.Extensions.{IntOps, LongOps}
import scorex.util.encode.Base16
-import sigmastate.SType
-import sigmastate.crypto.Platform
-import sigmastate.eval.{CAvlTree, CGroupElement, CSigmaProp, CostingBox, Evaluation, SigmaDsl}
-import sigmastate.fleetSdkCommon.distEsmTypesBoxesMod.Box
-import sigmastate.fleetSdkCommon.distEsmTypesCommonMod
-import sigmastate.fleetSdkCommon.distEsmTypesRegistersMod.NonMandatoryRegisters
-import sigmastate.lang.DeserializationSigmaBuilder
-import sigmastate.serialization.{ConstantSerializer, DataSerializer, SigmaSerializer}
-import sigma.{Coll, Colls}
+import sigma.ast.SType
+import sigma.crypto.Platform
+import sigma.data._
+import sigma.js.Value.toRuntimeData
+import sigma.serialization.{CoreDataSerializer, CoreSerializer}
+import sigma.util.Extensions.BigIntOps
+import sigma.{Coll, Colls, Evaluation}
import java.math.BigInteger
import scala.scalajs.js
@@ -44,33 +40,29 @@ import scala.scalajs.js.annotation.JSExportTopLevel
class Value(val data: Any, val tpe: Type) extends js.Object {
/** Get Sigma runtime value which can be passed to interpreter, saved in register and
- * [[sigmastate.Values.Constant]] nodes.
+ * [[sigma.ast.Constant]] nodes.
*/
- final private[js] def runtimeData: Any = toRuntimeData(data, tpe.rtype)
+ final def runtimeData: Any = toRuntimeData(data, tpe.rtype)
/**
* Encode this value as Base16 hex string.
- * 1) it transforms this value into {@link sigmastate.Values.ConstantNode} of sigma.
+ * 1) it transforms this value into {@link sigma.ast.ConstantNode} of sigma.
* 2) it serializes the constant into byte array using {@link sigmastate.serialization.ConstantSerializer}
* 3) the bytes are encoded using Base16 encoder into string
*
* @return hex string of serialized bytes
*/
def toHex(): String = {
- // this can be implemented using ConstantSerializer and isoValueToConstant, but this
- // will add dependence on Constant and Values, which we want to avoid facilitate
- // module splitting
- // TODO simplify if module splitting fails
val stype = Evaluation.rtypeToSType(tpe.rtype)
val value = runtimeData.asInstanceOf[SType#WrappedType]
- val w = SigmaSerializer.startWriter()
+ val w = CoreSerializer.startWriter()
w.putType(stype)
- DataSerializer.serialize(value, stype, w)
+ CoreDataSerializer.serialize(value, stype, w)
Base16.encode(w.toBytes)
}
}
-@JSExportTopLevel("ValueObj")
+@JSExportTopLevel("Value$")
object Value extends js.Object {
/** Maximal positive value of ES type Long */
val MaxLong = js.BigInt("0x7fffffffffffffff")
@@ -79,7 +71,7 @@ object Value extends js.Object {
val MinLong = -js.BigInt("0x8000000000000000")
/** Helper method to get Sigma runtime value which can be passed to interpreter, saved
- * in register and [[sigmastate.Values.Constant]] nodes.
+ * in register and [[sigma.ast.Constant]] nodes.
*/
final private[js] def toRuntimeData(data: Any, rtype: RType[_]): Any = rtype match {
case sigma.BooleanType => data
@@ -87,19 +79,16 @@ object Value extends js.Object {
case sigma.LongType => java.lang.Long.parseLong(data.asInstanceOf[js.BigInt].toString(10))
case sigma.BigIntRType =>
val v = data.asInstanceOf[js.BigInt]
- SigmaDsl.BigInt(new BigInteger(v.toString(16), 16))
+ CBigInt(new BigInteger(v.toString(16), 16))
case sigma.GroupElementRType =>
val ge = data.asInstanceOf[GroupElement]
- SigmaDsl.GroupElement(ge.point)
+ CGroupElement(ge.point)
case sigma.SigmaPropRType =>
val p = data.asInstanceOf[SigmaProp]
- SigmaDsl.SigmaProp(p.sigmaBoolean)
+ CSigmaProp(p.sigmaBoolean)
case sigma.AvlTreeRType =>
val t = data.asInstanceOf[AvlTree]
- Isos.isoAvlTree.to(t)
- case sigma.BoxRType =>
- val t = data.asInstanceOf[Box[distEsmTypesCommonMod.Amount, NonMandatoryRegisters]]
- SigmaDsl.Box(Isos.isoBox.to(t))
+ AvlTree.isoAvlTree.to(t)
case ct: CollType[a] =>
val xs = data.asInstanceOf[js.Array[Any]]
implicit val cT = ct.tItem.classTag
@@ -121,12 +110,12 @@ object Value extends js.Object {
* @param value runtime value of type given by `rtype`
* @param rtype type descriptor of Sigma runtime value
*/
- final private[js] def fromRuntimeData(value: Any, rtype: RType[_]): Any = rtype match {
+ final def fromRuntimeData(value: Any, rtype: RType[_]): Any = rtype match {
case sigma.BooleanType => value
case sigma.ByteType | sigma.ShortType | sigma.IntType => value
case sigma.LongType => js.BigInt(value.asInstanceOf[Long].toString)
case sigma.BigIntRType =>
- val hex = SigmaDsl.toBigInteger(value.asInstanceOf[sigma.BigInt]).toString(10)
+ val hex = value.asInstanceOf[sigma.BigInt].toBigInteger.toString(10)
js.BigInt(hex)
case sigma.GroupElementRType =>
val point = value.asInstanceOf[CGroupElement].wrappedValue.asInstanceOf[Platform.Ecp]
@@ -134,9 +123,7 @@ object Value extends js.Object {
case sigma.SigmaPropRType =>
new SigmaProp(value.asInstanceOf[CSigmaProp].wrappedValue)
case sigma.AvlTreeRType =>
- Isos.isoAvlTree.from(value.asInstanceOf[CAvlTree])
- case sigma.BoxRType =>
- Isos.isoBox.from(value.asInstanceOf[CostingBox].wrappedValue)
+ AvlTree.isoAvlTree.from(value.asInstanceOf[CAvlTree])
case ct: CollType[a] =>
val arr = value.asInstanceOf[Coll[a]].toArray
js.Array(arr.map(x => fromRuntimeData(x, ct.tItem)):_*)
@@ -263,9 +250,12 @@ object Value extends js.Object {
* - and [[Type]] descriptor in its `tpe` field
*/
def fromHex(hex: String): Value = {
- val bytes = Base16.decode(hex).fold(t => throw t, identity)
- val S = ConstantSerializer(DeserializationSigmaBuilder)
- val c = S.deserialize(SigmaSerializer.startReader(bytes))
- Isos.isoValueToConstant.from(c)
+ val bytes = Base16.decode(hex).fold(t => throw t, identity)
+ val r = CoreSerializer.startReader(bytes)
+ val stype = r.getType()
+ val value = CoreDataSerializer.deserialize(stype, r)
+ val rtype = Evaluation.stypeToRType(stype)
+ val jsvalue = Value.fromRuntimeData(value, rtype)
+ new Value(jsvalue, new Type(rtype))
}
}
diff --git a/interpreter/jvm/src/main/scala/sigmastate/crypto/CryptoContextJvm.scala b/core/jvm/src/main/scala/sigma/crypto/CryptoContextJvm.scala
similarity index 97%
rename from interpreter/jvm/src/main/scala/sigmastate/crypto/CryptoContextJvm.scala
rename to core/jvm/src/main/scala/sigma/crypto/CryptoContextJvm.scala
index 7b789f1db6..939e43619e 100644
--- a/interpreter/jvm/src/main/scala/sigmastate/crypto/CryptoContextJvm.scala
+++ b/core/jvm/src/main/scala/sigma/crypto/CryptoContextJvm.scala
@@ -1,4 +1,4 @@
-package sigmastate.crypto
+package sigma.crypto
import org.bouncycastle.asn1.x9.X9ECParameters
diff --git a/interpreter/jvm/src/main/scala/sigmastate/crypto/HmacSHA512.scala b/core/jvm/src/main/scala/sigma/crypto/HmacSHA512.scala
similarity index 96%
rename from interpreter/jvm/src/main/scala/sigmastate/crypto/HmacSHA512.scala
rename to core/jvm/src/main/scala/sigma/crypto/HmacSHA512.scala
index 237ca9e176..c0c699921d 100644
--- a/interpreter/jvm/src/main/scala/sigmastate/crypto/HmacSHA512.scala
+++ b/core/jvm/src/main/scala/sigma/crypto/HmacSHA512.scala
@@ -1,4 +1,4 @@
-package sigmastate.crypto
+package sigma.crypto
import javax.crypto.Mac
import javax.crypto.spec.SecretKeySpec
diff --git a/interpreter/jvm/src/main/scala/sigmastate/crypto/Platform.scala b/core/jvm/src/main/scala/sigma/crypto/Platform.scala
similarity index 96%
rename from interpreter/jvm/src/main/scala/sigmastate/crypto/Platform.scala
rename to core/jvm/src/main/scala/sigma/crypto/Platform.scala
index 1c5c63b197..b71694e81b 100644
--- a/interpreter/jvm/src/main/scala/sigmastate/crypto/Platform.scala
+++ b/core/jvm/src/main/scala/sigma/crypto/Platform.scala
@@ -1,4 +1,4 @@
-package sigmastate.crypto
+package sigma.crypto
import org.bouncycastle.crypto.digests.SHA512Digest
import org.bouncycastle.crypto.ec.CustomNamedCurves
@@ -7,9 +7,9 @@ import org.bouncycastle.crypto.params.KeyParameter
import org.bouncycastle.math.ec.{ECCurve, ECFieldElement, ECPoint}
import java.math.BigInteger
-import sigmastate._
import sigma.Coll
import sigma._
+import sigma.ast._
import java.text.Normalizer.Form.NFKD
import java.text.Normalizer
@@ -206,8 +206,4 @@ object Platform {
def multiply(n: BigInteger): Ecp = CryptoFacade.exponentiatePoint(p, n)
}
- /** This JVM specific methods are used in Ergo node which won't be JS cross-compiled. */
- implicit class BcDlogGroupOps(val group: BcDlogGroup) extends AnyVal {
- def curve: Curve = group.ctx.asInstanceOf[CryptoContextJvm].curve
- }
}
diff --git a/interpreter/shared/src/main/scala/sigmastate/eval/Evaluation.scala b/core/shared/src/main/scala/sigma/Evaluation.scala
similarity index 56%
rename from interpreter/shared/src/main/scala/sigmastate/eval/Evaluation.scala
rename to core/shared/src/main/scala/sigma/Evaluation.scala
index 8771fe2b32..d86b7c1650 100644
--- a/interpreter/shared/src/main/scala/sigmastate/eval/Evaluation.scala
+++ b/core/shared/src/main/scala/sigma/Evaluation.scala
@@ -1,48 +1,16 @@
-package sigmastate.eval
+package sigma
-import org.ergoplatform._
-import sigma.data._
-import sigma.data.RType._
-import sigmastate.SType._
-import sigmastate.Values.SigmaBoolean
-import sigmastate._
import debox.cfor
-import sigmastate.exceptions.CostLimitException
+import sigma.ast.SType
+import sigma.data.RType._
+import sigma.data._
+import sigma.ast._
-import scala.reflect.ClassTag
-import scala.util.Try
// TODO refactor: find better place for this methods after code cleanup and repo reorganization
/** Helper methods used as part of ErgoTree evaluation. */
object Evaluation {
- import sigma._
- import sigma._
-
- def msgCostLimitError(cost: Long, limit: Long) = s"Estimated execution cost $cost exceeds the limit $limit"
-
- /** Helper method to accumulate cost while checking limit.
- *
- * @param current current cost value
- * @param delta additional cost to add to the current value
- * @param limit total cost limit
- * @param msgSuffix use case-specific error message suffix
- * @return new increased cost when it doesn't exceed the limit
- * @throws CostLimitException
- */
- def addCostChecked(current: Long, delta: Long, limit: Long, msgSuffix: => String = ""): Long = {
- val newCost = java7.compat.Math.addExact(current, delta)
- if (newCost > limit) {
- throw new CostLimitException(
- estimatedCost = newCost,
- message = {
- val suffix = if (msgSuffix.isEmpty) "" else s": $msgSuffix"
- msgCostLimitError(newCost, limit) + suffix
- },
- cause = None)
- }
- newCost
- }
/** Transforms a serializable ErgoTree type descriptor to the corresponding RType descriptor of SigmaDsl,
* which is used during evaluation.
@@ -101,14 +69,14 @@ object Evaluation {
case BigIntRType => SBigInt
case GroupElementRType => SGroupElement
case AvlTreeRType => SAvlTree
- case ot: OptionType[_] => sigmastate.SOption(rtypeToSType(ot.tA))
+ case ot: OptionType[_] => SOption(rtypeToSType(ot.tA))
case BoxRType => SBox
case ContextRType => SContext
case SigmaDslBuilderRType => SGlobal
case HeaderRType => SHeader
case PreHeaderRType => SPreHeader
case SigmaPropRType => SSigmaProp
- case SigmaBooleanRType => SSigmaProp
+ case SigmaBooleanRType => SSigmaProp // TODO remove: this is not used in consensus code
case tup: TupleType => STuple(tup.items.map(t => rtypeToSType(t)))
case at: ArrayType[_] => SCollection(rtypeToSType(at.tA))
case ct: CollType[_] => SCollection(rtypeToSType(ct.tItem))
@@ -117,47 +85,6 @@ object Evaluation {
case _ => sys.error(s"Don't know how to convert RType $t to SType")
}
- /** Tries to reconstruct RType of the given value.
- * If not successfull returns failure.
- * NOTE, this method is NOT used in consensus. */
- def rtypeOf(value: Any): Try[RType[_]] = Try { value match {
- case arr if arr.getClass.isArray =>
- val itemClass = arr.getClass.getComponentType
- if (itemClass.isPrimitive) {
- val itemTag = ClassTag[Any](itemClass)
- RType.fromClassTag(itemTag)
- } else
- sys.error(s"Cannot compute rtypeOf($value): non-primitive type of array items")
-
- case coll: Coll[_] => collRType(coll.tItem)
-
- // all primitive types
- case _: Boolean => BooleanType
- case _: Byte => ByteType
- case _: Short => ShortType
- case _: Int => IntType
- case _: Long => LongType
- case _: String => StringType
- case _: Unit => UnitType
- case _: sigma.BigInt => BigIntRType
- case _: GroupElement => GroupElementRType
- // TODO remove this case to allow removing of RType instances
- // for ErgoBox, AvlTreeData, SigmaBoolean.
- // RType describes only the types that can be put into registers, context variables and
- // used as ErgoTree evaluation intermediate values.
- case _: ErgoBox => ErgoBoxRType
- case _: Box => BoxRType
-
- case _: AvlTreeData => AvlTreeDataRType // TODO remove this RType
- case _: AvlTree => AvlTreeRType
-
- case _: SigmaBoolean => SigmaBooleanRType // TODO remove this RType
- case _: SigmaProp => SigmaPropRType
- case _: Context => ContextRType
- case _ =>
- sys.error(s"Don't know how to compute typeOf($value)")
- }}
-
/** Convert SigmaDsl representation of tuple to ErgoTree serializable representation. */
def fromDslTuple(value: Any, tupleTpe: STuple): Coll[Any] = value match {
case t: Tuple2[_,_] => TupleColl(t._1, t._2)
diff --git a/core/shared/src/main/scala/sigma/Extensions.scala b/core/shared/src/main/scala/sigma/Extensions.scala
index 08087eced0..81976a3c12 100644
--- a/core/shared/src/main/scala/sigma/Extensions.scala
+++ b/core/shared/src/main/scala/sigma/Extensions.scala
@@ -3,8 +3,26 @@ package sigma
import debox.cfor
import scorex.util.encode.Base16
import scorex.util.{ModifierId, bytesToId}
+import sigma.data.RType
+/** Declaration of extension methods introduced in `sigma-core` module.
+ * See `implicit class ...` wrappers below.
+ */
object Extensions {
+ /** Extension methods for `Array[Byte]` not available for generic `Array[T]`. */
+ implicit class CoreArrayByteOps(val arr: Array[Byte]) extends AnyVal {
+ /** Encodes array into hex string */
+ @inline def toHex: String = Base16.encode(arr)
+ }
+
+ /** Extension methods for `Array[T]` where implicit descriptor `RType[T]` is also
+ * required.
+ */
+ implicit class ArrayOps[T: RType](arr: Array[T]) {
+ /** Wraps array into Coll instance. The source array in not cloned. */
+ @inline def toColl: Coll[T] = Colls.fromArray(arr)
+ }
+
/** Extension methods for `Coll[T]`. */
implicit class CollOps[T](val source: Coll[T]) extends AnyVal {
/** Applies a function `f` to each element of the `source` collection. */
diff --git a/core/shared/src/main/scala/sigma/SigmaDsl.scala b/core/shared/src/main/scala/sigma/SigmaDsl.scala
index 7609d38356..df2b419273 100644
--- a/core/shared/src/main/scala/sigma/SigmaDsl.scala
+++ b/core/shared/src/main/scala/sigma/SigmaDsl.scala
@@ -37,12 +37,6 @@ trait BigInt {
*/
def toBytes: Coll[Byte]
- /** Returns a big-endian representation of this BigInt in a collection of Booleans.
- * Each boolean corresponds to one bit of the representation.
- * @since 2.0
- */
- def toBits: Coll[Boolean]
-
/** Absolute value of this numeric value.
* @since 2.0
*/
@@ -53,31 +47,6 @@ trait BigInt {
*/
def compareTo(that: BigInt): Int
- /** Returns this `mod` Q, i.e. remainder of division by Q, where Q is an order of the cryprographic group.
- * @since 2.0
- */
- def modQ: BigInt
-
- /** Adds this number with `other` by module Q.
- * @since 2.0
- */
- def plusModQ(other: BigInt): BigInt
-
- /** Subtracts this number with `other` by module Q.
- * @since 2.0
- */
- def minusModQ(other: BigInt): BigInt
-
- /** Multiply this number with `other` by module Q.
- * @since 2.0
- */
- def multModQ(other: BigInt): BigInt
-
- /** Multiply this number with `other` by module Q.
- * @since Mainnet
- */
- def inverseModQ: BigInt // ??? @kushti do we need it
-
/** Returns the signum function of this BigInt.
*
* @return -1, 0 or 1 as the value of this BigInt is negative, zero or
@@ -414,79 +383,6 @@ trait AvlTree {
* replaced by `newOperations`
*/
def updateOperations(newOperations: Byte): AvlTree
-
- /** Checks if an entry with key `key` exists in this tree using proof `proof`.
- * Throws exception if proof is incorrect
- *
- * @note CAUTION! Does not support multiple keys check, use [[getMany]] instead.
- * Return `true` if a leaf with the key `key` exists
- * Return `false` if leaf with provided key does not exist.
- * @param key a key of an element of this authenticated dictionary.
- * @param proof data to reconstruct part of the tree enough to perform the check
- */
- def contains(key: Coll[Byte], proof: Coll[Byte]): Boolean
-
- /** Perform a lookup of key `key` in this tree using proof `proof`.
- * Throws exception if proof is incorrect
- *
- * @note CAUTION! Does not support multiple keys check, use [[getMany]] instead.
- * Return Some(bytes) of leaf with key `key` if it exists
- * Return None if leaf with provided key does not exist.
- * @param key a key of an element of this authenticated dictionary.
- * @param proof data to reconstruct part of the tree enough to get the value
- * by the key
- */
- def get(key: Coll[Byte], proof: Coll[Byte]): Option[Coll[Byte]]
-
- /** Perform a lookup of many keys `keys` in this tree using proof `proof`.
- *
- * @note CAUTION! Keys must be ordered the same way they were in lookup before proof was generated.
- * For each key return Some(bytes) of leaf if it exists and None if is doesn't.
- * @param keys keys of elements of this authenticated dictionary.
- * @param proof
- */
- def getMany(keys: Coll[Coll[Byte]], proof: Coll[Byte]): Coll[Option[Coll[Byte]]]
-
- /** Perform insertions of key-value entries into this tree using proof `proof`.
- * Throws exception if proof is incorrect
- *
- * @note CAUTION! Pairs must be ordered the same way they were in insert ops before proof was generated.
- * Return Some(newTree) if successful
- * Return None if operations were not performed.
- * @param operations collection of key-value pairs to insert in this authenticated dictionary.
- * @param proof data to reconstruct part of the tree
- */
- def insert(operations: Coll[(Coll[Byte], Coll[Byte])], proof: Coll[Byte]): Option[AvlTree]
-
- /** Perform updates of key-value entries into this tree using proof `proof`.
- * Throws exception if proof is incorrect
- *
- * @note CAUTION! Pairs must be ordered the same way they were in update ops before proof was generated.
- * Return Some(newTree) if successful
- * Return None if operations were not performed.
- * @param operations collection of key-value pairs to update in this authenticated dictionary.
- * @param proof data to reconstruct part of the tree
- */
- def update(operations: Coll[(Coll[Byte], Coll[Byte])], proof: Coll[Byte]): Option[AvlTree]
-
- /** Perform removal of entries into this tree using proof `proof`.
- * Throws exception if proof is incorrect
- * Return Some(newTree) if successful
- * Return None if operations were not performed.
- *
- * @note CAUTION! Keys must be ordered the same way they were in remove ops before proof was generated.
- * @param operations collection of keys to remove from this authenticated dictionary.
- * @param proof data to reconstruct part of the tree
- */
- def remove(operations: Coll[Coll[Byte]], proof: Coll[Byte]): Option[AvlTree]
-
-// /** Creates a new instance of [[AvlTreeVerifier]] with the given `proof` and using
-// * properties of this AvlTree (digest, keyLength, valueLengthOpt) for constructor
-// * arguments.
-// *
-// * @param proof bytes of the serialized proof which is used to represent the tree.
-// */
-// def createVerifier(proof: Coll[Byte]): AvlTreeVerifier
}
/** Only header fields that can be predicted by a miner. */
diff --git a/core/shared/src/main/scala/sigma/SigmaException.scala b/core/shared/src/main/scala/sigma/SigmaException.scala
new file mode 100644
index 0000000000..146844b583
--- /dev/null
+++ b/core/shared/src/main/scala/sigma/SigmaException.scala
@@ -0,0 +1,17 @@
+package sigma
+
+import scala.collection.compat.immutable.ArraySeq
+
+/** Base class for Sigma-related exceptions.
+ *
+ * @param message the error message
+ * @param cause an optional cause for the exception
+ * @param args an optional sequence of arguments to be passed with the exception
+ */
+class SigmaException(
+ val message: String,
+ val cause: Option[Throwable] = None,
+ val args: Seq[Any] = ArraySeq.empty) extends Exception(message, cause.orNull)
+
+
+
diff --git a/core/shared/src/main/scala/sigma/VersionContext.scala b/core/shared/src/main/scala/sigma/VersionContext.scala
index a7928cd513..67b7079fea 100644
--- a/core/shared/src/main/scala/sigma/VersionContext.scala
+++ b/core/shared/src/main/scala/sigma/VersionContext.scala
@@ -39,8 +39,8 @@ object VersionContext {
val JitActivationVersion: Byte = 2
private val _defaultContext = VersionContext(
- activatedVersion = 1/* v4.x */,
- ergoTreeVersion = 1
+ activatedVersion = 1 /* v4.x */,
+ ergoTreeVersion = 1
)
/** Universally accessible version context which is used to version the code
diff --git a/core/shared/src/main/scala/sigma/ast/SType.scala b/core/shared/src/main/scala/sigma/ast/SType.scala
new file mode 100644
index 0000000000..e9ea0d43f0
--- /dev/null
+++ b/core/shared/src/main/scala/sigma/ast/SType.scala
@@ -0,0 +1,838 @@
+package sigma.ast
+
+import sigma.Evaluation.stypeToRType
+import sigma.ast.SCollection.SByteArray
+import sigma.ast.SType.TypeCode
+import sigma.data.OverloadHack.Overloaded1
+import sigma.data.{CBigInt, Nullable, SigmaConstants}
+import sigma.reflection.{RClass, RMethod, ReflectionData}
+import sigma.util.Extensions.{IntOps, LongOps, ShortOps}
+import sigma.{AvlTree, BigInt, Box, Coll, Context, Evaluation, GroupElement, Header, PreHeader, SigmaDslBuilder, SigmaProp}
+
+import java.math.BigInteger
+
+/** Base type for all AST nodes of ErgoTree. */
+trait SigmaNode extends Product
+
+/** Every type descriptor is a tree represented by nodes in SType hierarchy.
+ * In order to extend type family:
+ * - Implement concrete class derived from SType
+ * - Implement serializer (see SCollectionSerializer) and register it in STypeSerializer.table
+ * Each SType is serialized to array of bytes by:
+ * - emitting typeCode of each node (see special case for collections below)
+ * - then recursively serializing subtrees from left to right on each level
+ * - for each collection of primitive type there is special type code to emit single byte instead of two bytes
+ * Types code intervals
+ * - (1 .. MaxPrimTypeCode) // primitive types
+ * - (CollectionTypeCode .. CollectionTypeCode + MaxPrimTypeCode) // collections of primitive types
+ * - (MaxCollectionTypeCode ..) // Other types
+ * Collection of non-primitive type is serialized as (CollectionTypeCode, serialize(elementType))
+ * */
+sealed trait SType extends SigmaNode {
+ /** The underlying Scala type of data values described by this type descriptor.
+ * E.g. scala.Int for SInt descriptor.
+ */
+ type WrappedType
+
+ /** Type code used in serialization of SType values.
+ * @see TypeSerializer
+ */
+ val typeCode: SType.TypeCode
+
+ /** Returns true if this type embeddable, i.e. a type that can be combined with type
+ * constructor for optimized encoding. For each embeddable type `T`, and type
+ * constructor `C`, the type `C[T]` can be represented by a single byte.
+ * @see [[sigmastate.serialization.TypeSerializer]]
+ */
+ def isEmbeddable: Boolean = false
+
+ /** Elvis operator for types. See https://en.wikipedia.org/wiki/Elvis_operator*/
+ def ?:(whenNoType: => SType): SType = if (this == NoType) whenNoType else this
+
+
+ /** Returns parsable type term string of the type described by this type descriptor.
+ * For every type it should be inverse to SigmaTyper.parseType.
+ * This is default fallback implementation, should be overriden if it
+ * is not correct for a particular type. */
+ def toTermString: String = {
+ val t = Evaluation.stypeToRType(this)
+ t.name
+ }
+}
+
+object SType {
+ /** Representation of type codes used in serialization. */
+ type TypeCode = Byte
+
+ /** Named type variables and parameters used in generic types and method signatures.
+ * Generic type terms like `(Coll[IV],(IV) => Boolean) => Boolean` are used to represent
+ * method types of `Coll`` and `Option`` types. Each such type is an instance of [[SFunc]].
+ * To represent variables (such as `IV` in the example above) [[STypeVar]] instances
+ * are used.
+ *
+ * Generic types are not supported by ErgoTree serialization format and STypeVars are
+ * used internally and never serialized (there is no serializer for STypeVar).
+ * Thus the usage of type variables is limited.
+ *
+ * All necessary type variables can be declared in advance and reused across all code
+ * base. This allows to avoid allocation of many duplicates and also improve
+ * performance of SType values.
+ */
+ val tT = STypeVar("T")
+ val tR = STypeVar("R")
+ val tK = STypeVar("K")
+ val tL = STypeVar("L")
+ val tO = STypeVar("O")
+ val tD = STypeVar("D")
+ val tV = STypeVar("V")
+ val tIV = STypeVar("IV")
+ val tOV = STypeVar("OV")
+
+ val paramT = STypeParam(tT)
+ val paramR = STypeParam(tR)
+ val paramIV = STypeParam(tIV)
+ val paramOV = STypeParam(tOV)
+ val paramIVSeq: Seq[STypeParam] = Array(paramIV)
+
+ val IndexedSeqOfT1: IndexedSeq[SType] = Array(SType.tT)
+ val IndexedSeqOfT2: IndexedSeq[SType] = Array(SType.tT, SType.tT)
+
+ /** Immutable empty array, can be used to avoid repeated allocations. */
+ val EmptyArray = Array.empty[SType]
+
+ /** Immutable empty IndexedSeq, can be used to avoid repeated allocations. */
+ val EmptySeq: IndexedSeq[SType] = EmptyArray
+
+ /** All pre-defined types should be listed here. Note, NoType is not listed.
+ * Should be in sync with sigmastate.lang.Types.predefTypes. */
+ val allPredefTypes: Seq[SType] = Array[SType](
+ SBoolean, SByte, SShort, SInt, SLong, SBigInt, SContext,
+ SGlobal, SHeader, SPreHeader, SAvlTree, SGroupElement, SSigmaProp, SString, SBox,
+ SUnit, SAny)
+
+ /** A mapping of object types supporting MethodCall operations. For each serialized
+ * typeId this map contains a companion object which can be used to access the list of
+ * corresponding methods.
+ *
+ * NOTE: in the current implementation only monomorphic methods are supported (without
+ * type parameters)
+ *
+ * NOTE2: in v3.x SNumericType.typeId is silently shadowed by SGlobal.typeId as part of
+ * `toMap` operation. As a result, the methods collected into SByte.methods cannot be
+ * resolved (using SMethod.fromIds()) for all numeric types (SByte, SShort, SInt,
+ * SLong, SBigInt). See the corresponding regression `property("MethodCall on numerics")`.
+ * However, this "shadowing" is not a problem since all casting methods are implemented
+ * via Downcast, Upcast opcodes and the remaining `toBytes`, `toBits` methods are not
+ * implemented at all.
+ * In order to allow MethodCalls on numeric types in future versions the SNumericType.typeId
+ * should be changed and SGlobal.typeId should be preserved. The regression tests in
+ * `property("MethodCall Codes")` should pass.
+ */
+ // TODO v6.0: should contain all numeric types (including also SNumericType)
+ // to support method calls like 10.toByte which encoded as MethodCall with typeId = 4, methodId = 1
+ // see https://github.com/ScorexFoundation/sigmastate-interpreter/issues/667
+ lazy val types: Map[Byte, STypeCompanion] = Seq(
+ SBoolean, SNumericType, SString, STuple, SGroupElement, SSigmaProp, SContext, SGlobal, SHeader, SPreHeader,
+ SAvlTree, SBox, SOption, SCollection, SBigInt
+ ).map { t => (t.typeId, t) }.toMap
+
+ /** Checks that the type of the value corresponds to the descriptor `tpe`.
+ * If the value has complex structure only root type constructor is checked.
+ * NOTE, this method is used in ErgoTree evaluation to systematically check that each
+ * tree node evaluates to a value of the expected type.
+ * Shallow runtime checks are enough if:
+ * 1) ErgoTree is well-typed, i.e. each sub-expression has correct types (agree with
+ * the argument type).
+ * 2) `isValueOfType == true` for each tree leaf
+ * 3) `isValueOfType == true` for each sub-expression
+ *
+ * @param value value to check type
+ * @param tpe type descriptor to check value against
+ * @return true if the given `value` is of type tpe`
+ */
+ def isValueOfType[T <: SType](x: Any, tpe: T): Boolean = tpe match {
+ case SBoolean => x.isInstanceOf[Boolean]
+ case SByte => x.isInstanceOf[Byte]
+ case SShort => x.isInstanceOf[Short]
+ case SInt => x.isInstanceOf[Int]
+ case SLong => x.isInstanceOf[Long]
+ case SBigInt => x.isInstanceOf[BigInt]
+ case SGroupElement => x.isInstanceOf[GroupElement]
+ case SSigmaProp => x.isInstanceOf[SigmaProp]
+ case SBox => x.isInstanceOf[Box]
+ case _: SCollectionType[_] => x.isInstanceOf[Coll[_]]
+ case _: SOption[_] => x.isInstanceOf[Option[_]]
+ case t: STuple =>
+ if (t.items.length == 2) x.isInstanceOf[Tuple2[_,_]]
+ else sys.error(s"Unsupported tuple type $t")
+ case tF: SFunc =>
+ if (tF.tDom.length == 1) x.isInstanceOf[Function1[_,_]]
+ else sys.error(s"Unsupported function type $tF")
+ case SContext => x.isInstanceOf[Context]
+ case SAvlTree => x.isInstanceOf[AvlTree]
+ case SGlobal => x.isInstanceOf[SigmaDslBuilder]
+ case SHeader => x.isInstanceOf[Header]
+ case SPreHeader => x.isInstanceOf[PreHeader]
+ case SUnit => x.isInstanceOf[Unit]
+ case _ => sys.error(s"Unknown type $tpe")
+ }
+
+
+ implicit class AnyOps(val x: Any) extends AnyVal {
+ /** Helper method to simplify type casts. */
+ def asWrappedType: SType#WrappedType = x.asInstanceOf[SType#WrappedType]
+ }
+}
+
+/** Basic interface for all type companions.
+ * This is necessary to make distinction between concrete type descriptor of a type like Coll[Int]
+ * and generic descriptor of Coll[T] type constructor.
+ * Some simple types like Int, GroupElement inherit from both SType and STypeCompanion.
+ * @see SInt, SGroupElement, SType
+ */
+trait STypeCompanion {
+ /** Force initialization of reflection. */
+ val reflection = ReflectionData
+
+ /** Type identifier to use in method serialization */
+ def typeId: Byte
+
+ /** If this is SType instance then returns the name of the corresponding RType.
+ * Otherwise returns the name of type companion object (e.g. SCollection).
+ */
+ def typeName: String = {
+ this match {
+ case t: SType =>
+ val rtype = stypeToRType(t)
+ rtype.name
+ case _ => this.getClass.getSimpleName.replace("$", "")
+ }
+ }
+
+ /** Class which represents values of this type. When method call is executed, the corresponding method
+ * of this class is invoked via [[RMethod]].invoke(). */
+ def reprClass: RClass[_]
+
+ /** Represents class of `this`. */
+ lazy val thisRClass: RClass[_] = RClass(this.getClass)
+}
+
+
+/** Special type to represent untyped values.
+ * Interpreter raises an error when encounter a Value with this type.
+ * All Value nodes with this type should be elimitanted during typing.
+ * If no specific type can be assigned statically during typing,
+ * then either error should be raised or type SAny should be assigned
+ * which is interpreted as dynamic typing. */
+case object NoType extends SType {
+ type WrappedType = Nothing
+ override val typeCode = 0: Byte
+}
+
+/** Type variable which is used in generic method/func signatures.
+ * Used by ErgoScript compiler IR and eliminated during compilation.
+ * It is not used in ErgoTree.
+ */
+case class STypeVar(name: String) extends SType {
+ require(name.length <= 255, "name is too long")
+ override type WrappedType = Any
+ override val typeCode = STypeVar.TypeCode
+ override def toString = name
+ override def toTermString: String = name
+}
+object STypeVar {
+ val TypeCode: TypeCode = 103: Byte
+ implicit def liftString(n: String): STypeVar = STypeVar(n)
+
+ /** Immutable empty array, can be used to avoid repeated allocations. */
+ val EmptyArray = Array.empty[STypeVar]
+
+ /** Immutable empty IndexedSeq, can be used to avoid repeated allocations. */
+ val EmptySeq: IndexedSeq[STypeVar] = EmptyArray
+}
+
+/** Base trait for all pre-defined types which are not necessary primitive (e.g. Box, AvlTree).
+ */
+trait SPredefType extends SType {
+}
+
+/** Base type for SBoolean and SSigmaProp. */
+trait SLogical extends SType {
+}
+
+/** Base trait implemented by all generic types (those which has type parameters,
+ * e.g. Coll[T], Option[T], etc.)*/
+trait SGenericType {
+ /** Type parameters of this generic type. */
+ def typeParams: Seq[STypeParam]
+}
+
+/** Base trait for all embeddable types.
+ */
+trait SEmbeddable extends SType {
+ override def isEmbeddable: Boolean = true
+ /** Type code of embeddable type can be combined with code of type constructor.
+ * Resulting code can be serialized. This simple convention allows to save space for most frequently used types.
+ * See TypeSerializer */
+ @inline final def embedIn(typeConstrId: Byte): Byte = (typeConstrId + this.typeCode).toByte
+}
+
+/** Base trait for all primitive types (aka atoms) which don't have internal type items.
+ * All primitive types can occupy a reserved interval of codes from 1 to MaxPrimTypeCode. */
+trait SPrimType extends SType with SPredefType {
+}
+
+/** Primitive type recognizer to pattern match on TypeCode */
+object SPrimType {
+ def unapply(t: SType): Option[SType] = SType.allPredefTypes.find(_ == t)
+
+ /** Type code of the last valid prim type so that (1 to LastPrimTypeCode) is a range of valid codes. */
+ final val LastPrimTypeCode: Byte = 8: Byte
+
+ /** Upper limit of the interval of valid type codes for primitive types */
+ final val MaxPrimTypeCode: Byte = 11: Byte
+
+ /** Max possible number of primitive types. */
+ final val PrimRange: Byte = (MaxPrimTypeCode + 1).toByte
+}
+
+/** Base trait for all types which have methods (and properties) */
+trait SProduct extends SType {
+}
+
+/** Monomorphic type descriptor i.e. a type without generic parameters.
+ * @see `SGenericType`
+ */
+trait SMonoType extends SType with STypeCompanion {
+}
+
+/** Marker trait for all numeric types. */
+trait SNumericType extends SProduct with STypeCompanion {
+ /** Upcasts the given value of a smaller type to this larger type.
+ * Corresponds to section 5.1.2 Widening Primitive Conversion of Java Language Spec.
+ * @param n numeric value to be converted
+ * @return a value of WrappedType of this type descriptor's instance.
+ * @throw exception if `n` has actual type which is larger than this type.
+ */
+ def upcast(n: AnyVal): WrappedType
+
+ /** Downcasts the given value of a larger type to this smaller type.
+ * Corresponds to section 5.1.3 Narrowing Primitive Conversion of Java Language Spec.
+ * @param n numeric value to be converted
+ * @return a value of WrappedType of this type descriptor's instance.
+ * @throw exception if the actual value of `i` cannot fit into this type.
+ */
+ def downcast(n: AnyVal): WrappedType
+
+ /** Returns a type which is larger. */
+ @inline def max(that: SNumericType): SNumericType =
+ if (this.numericTypeIndex > that.numericTypeIndex) this else that
+
+ /** Returns true if this numeric type is larger than that. */
+ @inline final def >(that: SNumericType): Boolean = this.numericTypeIndex > that.numericTypeIndex
+
+ /** Numeric types are ordered by the number of bytes to store the numeric values.
+ * @return index in the array of all numeric types. */
+ def numericTypeIndex: Int
+
+ override def toString: String = this.getClass.getSimpleName
+}
+
+object SNumericType extends STypeCompanion {
+ /** Array of all numeric types ordered by number of bytes in the representation. */
+ final val allNumericTypes = Array(SByte, SShort, SInt, SLong, SBigInt)
+
+ // TODO v6.0: this typeId is now shadowed by SGlobal.typeId
+ // see https://github.com/ScorexFoundation/sigmastate-interpreter/issues/667
+ override def typeId: TypeCode = 106: Byte
+
+ /** Since this object is not used in SMethod instances. */
+ override def reprClass: RClass[_] = sys.error(s"Shouldn't be called.")
+}
+
+/** Descriptor of ErgoTree type `Boolean` holding `true` or `false` values. */
+case object SBoolean extends SPrimType with SEmbeddable with SLogical with SProduct with SMonoType {
+ override type WrappedType = Boolean
+ override val typeCode: TypeCode = 1: Byte
+ override val reprClass: RClass[_] = RClass(classOf[Boolean])
+ override def typeId = typeCode
+ implicit def typeBoolean: SBoolean.type = this
+}
+
+/** Descriptor of ErgoTree type `Byte` - 8-bit signed integer. */
+case object SByte extends SPrimType with SEmbeddable with SNumericType with SMonoType {
+ override type WrappedType = Byte
+ override val typeCode: TypeCode = 2: Byte
+ override val reprClass: RClass[_] = RClass(classOf[Byte])
+ implicit def typeByte: SByte.type = this
+ override def typeId = typeCode
+ override def numericTypeIndex: Int = 0
+ override def upcast(v: AnyVal): Byte = v match {
+ case b: Byte => b
+ case _ => sys.error(s"Cannot upcast value $v to the type $this")
+ }
+ override def downcast(v: AnyVal): Byte = v match {
+ case b: Byte => b
+ case s: Short => s.toByteExact
+ case i: Int => i.toByteExact
+ case l: Long => l.toByteExact
+ case _ => sys.error(s"Cannot downcast value $v to the type $this")
+ }
+}
+
+/** Descriptor of ErgoTree type `Short` - 16-bit signed integer. */
+case object SShort extends SPrimType with SEmbeddable with SNumericType with SMonoType {
+ override type WrappedType = Short
+ override val typeCode: TypeCode = 3: Byte
+ override val reprClass: RClass[_] = RClass(classOf[Short])
+ implicit val typeShort: SShort.type = this
+ override def typeId = typeCode
+ override def numericTypeIndex: Int = 1
+ override def upcast(v: AnyVal): Short = v match {
+ case x: Byte => x.toShort
+ case x: Short => x
+ case _ => sys.error(s"Cannot upcast value $v to the type $this")
+ }
+ override def downcast(v: AnyVal): Short = v match {
+ case s: Short => s
+ case i: Int => i.toShortExact
+ case l: Long => l.toShortExact
+ case _ => sys.error(s"Cannot downcast value $v to the type $this")
+ }
+}
+
+/** Descriptor of ErgoTree type `Int` - 32-bit signed integer. */
+case object SInt extends SPrimType with SEmbeddable with SNumericType with SMonoType {
+ override type WrappedType = Int
+ override val typeCode: TypeCode = 4: Byte
+ override val reprClass: RClass[_] = RClass(classOf[Int])
+ override def typeId = typeCode
+ override def numericTypeIndex: Int = 2
+ implicit def typeInt: SInt.type = this
+ override def upcast(v: AnyVal): Int = v match {
+ case x: Byte => x.toInt
+ case x: Short => x.toInt
+ case x: Int => x
+ case _ => sys.error(s"Cannot upcast value $v to the type $this")
+ }
+ override def downcast(v: AnyVal): Int = v match {
+ case b: Byte => b.toInt
+ case s: Short => s.toInt
+ case i: Int => i
+ case l: Long => l.toIntExact
+ case _ => sys.error(s"Cannot downcast value $v to the type $this")
+ }
+}
+
+/** Descriptor of ErgoTree type `Long` - 64-bit signed integer. */
+case object SLong extends SPrimType with SEmbeddable with SNumericType with SMonoType {
+ override type WrappedType = Long
+ override val typeCode: TypeCode = 5: Byte
+ override val reprClass: RClass[_] = RClass(classOf[Long])
+ override def typeId = typeCode
+ override def numericTypeIndex: Int = 3
+ implicit def typeLong: SLong.type = this
+
+ override def upcast(v: AnyVal): Long = v match {
+ case x: Byte => x.toLong
+ case x: Short => x.toLong
+ case x: Int => x.toLong
+ case x: Long => x
+ case _ => sys.error(s"Cannot upcast value $v to the type $this")
+ }
+ override def downcast(v: AnyVal): Long = v match {
+ case b: Byte => b.toLong
+ case s: Short => s.toLong
+ case i: Int => i.toLong
+ case l: Long => l
+ case _ => sys.error(s"Cannot downcast value $v to the type $this")
+ }
+}
+
+/** Type of 256 bit integet values. Implemented using [[java.math.BigInteger]]. */
+case object SBigInt extends SPrimType with SEmbeddable with SNumericType with SMonoType {
+ override type WrappedType = BigInt
+ override val typeCode: TypeCode = 6: Byte
+ override val reprClass: RClass[_] = RClass(classOf[BigInt])
+ override def typeId = typeCode
+ implicit def typeBigInt: SBigInt.type = this
+
+ /** Type of Relation binary op like GE, LE, etc. */
+ val RelationOpType = SFunc(Array(SBigInt, SBigInt), SBoolean)
+
+ /** The maximum size of BigInteger value in byte array representation. */
+ val MaxSizeInBytes: Long = SigmaConstants.MaxBigIntSizeInBytes.value
+
+ override def numericTypeIndex: Int = 4
+
+ override def upcast(v: AnyVal): BigInt = {
+ val bi = v match {
+ case x: Byte => BigInteger.valueOf(x.toLong)
+ case x: Short => BigInteger.valueOf(x.toLong)
+ case x: Int => BigInteger.valueOf(x.toLong)
+ case x: Long => BigInteger.valueOf(x)
+ case _ => sys.error(s"Cannot upcast value $v to the type $this")
+ }
+ CBigInt(bi)
+ }
+ override def downcast(v: AnyVal): BigInt = {
+ val bi = v match {
+ case x: Byte => BigInteger.valueOf(x.toLong)
+ case x: Short => BigInteger.valueOf(x.toLong)
+ case x: Int => BigInteger.valueOf(x.toLong)
+ case x: Long => BigInteger.valueOf(x)
+ case _ => sys.error(s"Cannot downcast value $v to the type $this")
+ }
+ CBigInt(bi)
+ }
+}
+
+/** Descriptor of type `String` which is not used in ErgoTree, but used in ErgoScript.
+ * NOTE: this descriptor both type and type companion */
+case object SString extends SProduct with SMonoType {
+ override type WrappedType = String
+ override val typeCode: TypeCode = 102: Byte
+ override def typeId = typeCode
+ override def reprClass: RClass[_] = RClass(classOf[String])
+}
+
+/** Descriptor of ErgoTree type `GroupElement`.
+ * NOTE: this descriptor both type and type companion */
+case object SGroupElement extends SProduct with SPrimType with SEmbeddable with SMonoType {
+ override type WrappedType = GroupElement
+ override val typeCode: TypeCode = 7: Byte
+ override val reprClass: RClass[_] = RClass(classOf[GroupElement])
+ override def typeId = typeCode
+ implicit def typeGroupElement: SGroupElement.type = this
+}
+
+/** Descriptor of ErgoTree type `SigmaProp` which represent sigma-protocol propositions. */
+case object SSigmaProp extends SProduct with SPrimType with SEmbeddable with SLogical with SMonoType {
+ import SType._
+ override type WrappedType = SigmaProp
+ override val typeCode: TypeCode = 8: Byte
+ override val reprClass: RClass[_] = RClass(classOf[SigmaProp])
+ override def typeId = typeCode
+ implicit def typeSigmaProp: SSigmaProp.type = this
+
+ /** The maximum size of SigmaProp value in serialized byte array representation. */
+ val MaxSizeInBytes: Long = SigmaConstants.MaxSigmaPropSizeInBytes.value
+}
+
+/** Any other type is implicitly subtype of this type. */
+case object SAny extends SPrimType with SMonoType {
+ override type WrappedType = Any
+ override val typeCode: TypeCode = 97: Byte
+
+ /** Type identifier to use in method serialization */
+ override def typeId: TypeCode = typeCode
+
+ /** Class which represents values of this type. When method call is executed, the corresponding method
+ * of this class is invoked via [[RMethod]].invoke(). */
+ override def reprClass: RClass[_] = RClass(classOf[Any])
+}
+
+/** The type with single inhabitant value `()` */
+case object SUnit extends SPrimType with SMonoType {
+ override type WrappedType = Unit
+ override val typeCode: TypeCode = 98: Byte
+ /** Type identifier to use in method serialization */
+ override def typeId: TypeCode = typeCode
+
+ /** Class which represents values of this type. When method call is executed, the corresponding method
+ * of this class is invoked via [[RMethod]].invoke(). */
+ override def reprClass: RClass[_] = RClass(classOf[Unit])
+}
+
+/** Helper constuctor/extractor for tuples of two types. */
+object SPair {
+ def apply(l: SType, r: SType) = STuple(Array(l, r))
+ def unapply(t: STuple): Nullable[(SType, SType)] = t match {
+ case STuple(IndexedSeq(l, r)) => Nullable((l, r))
+ case _ => Nullable.None
+ }
+}
+
+/** Type descriptor of lambda types. */
+case class SFunc(tDom: IndexedSeq[SType], tRange: SType, tpeParams: Seq[STypeParam] = Nil)
+ extends SType with SGenericType
+{
+ override type WrappedType = Any => tRange.WrappedType
+ override val typeCode = SFunc.FuncTypeCode
+ override def toString = {
+ val args = if (tpeParams.isEmpty) "" else tpeParams.mkString("[", ",", "]")
+ s"$args(${tDom.mkString(",")}) => $tRange"
+ }
+ override def toTermString = {
+ val args = if (tpeParams.isEmpty) "" else tpeParams.mkString("[", ",", "]")
+ s"$args(${tDom.map(_.toTermString).mkString(",")}) => ${tRange.toTermString}"
+ }
+ override val typeParams: Seq[STypeParam] = tpeParams
+
+ /** Generalize this type and return a new descriptor. */
+ def getGenericType: SFunc = {
+ val typeParams: Seq[STypeParam] = tDom.zipWithIndex
+ .map { case (_, i) => STypeParam(SType.tD.name + (i + 1)) } :+ STypeParam(SType.tR.name)
+ val ts = typeParams.map(_.ident)
+ SFunc(ts.init.toIndexedSeq, ts.last, Nil)
+ }
+
+ /** Transform function into method type by adding the given `objType` as the first
+ * argument type (aka method receiver type).
+ */
+ def withReceiverType(objType: SType) = this.copy(tDom = objType +: tDom)
+}
+
+object SFunc {
+ final val FuncTypeCode: TypeCode = TypeCodes.FirstFuncType
+ def apply(tDom: SType, tRange: SType): SFunc = SFunc(Array(tDom), tRange) // HOTSPOT:
+ val identity = { x: Any => x }
+}
+
+/** Used by ErgoScript compiler IR and eliminated during compilation.
+ * It is not used in ErgoTree.
+ */
+case class STypeApply(name: String, args: IndexedSeq[SType] = IndexedSeq()) extends SType {
+ override type WrappedType = Any
+ override val typeCode = STypeApply.TypeCode
+}
+object STypeApply {
+ val TypeCode = 94: Byte
+}
+
+/** Type description of optional values. Instances of `Option`
+ * are either constructed by `Some` or by `None` constructors. */
+case class SOption[ElemType <: SType](elemType: ElemType) extends SProduct with SGenericType {
+ override type WrappedType = Option[ElemType#WrappedType]
+ override val typeCode: TypeCode = SOption.OptionTypeCode
+ override def toString = s"Option[$elemType]"
+ override def toTermString: String = s"Option[${elemType.toTermString}]"
+ override lazy val typeParams: Seq[STypeParam] = Array(SType.paramT)
+}
+
+object SOption extends STypeCompanion {
+ /** Code of `Option[_]` type constructor. */
+ val OptionTypeConstrId = 3
+ /** Type code for `Option[T] for some T` type used in TypeSerializer. */
+ val OptionTypeCode: TypeCode = ((SPrimType.MaxPrimTypeCode + 1) * OptionTypeConstrId).toByte
+ /** Code of `Option[Coll[_]]` type constructor. */
+ val OptionCollectionTypeConstrId = 4
+ /** Type code for `Option[Coll[T]] for some T` type used in TypeSerializer. */
+ val OptionCollectionTypeCode: TypeCode = ((SPrimType.MaxPrimTypeCode + 1) * OptionCollectionTypeConstrId).toByte
+
+ override def typeId = OptionTypeCode
+
+ override val reprClass: RClass[_] = RClass(classOf[Option[_]])
+
+ type SBooleanOption = SOption[SBoolean.type]
+ type SByteOption = SOption[SByte.type]
+ type SShortOption = SOption[SShort.type]
+ type SIntOption = SOption[SInt.type]
+ type SLongOption = SOption[SLong.type]
+ type SBigIntOption = SOption[SBigInt.type]
+ type SGroupElementOption = SOption[SGroupElement.type]
+ type SBoxOption = SOption[SBox.type]
+ type SAvlTreeOption = SOption[SAvlTree.type]
+
+ /** This descriptors are instantiated once here and then reused. */
+ implicit val SByteOption = SOption(SByte)
+ implicit val SByteArrayOption = SOption(SByteArray)
+ implicit val SShortOption = SOption(SShort)
+ implicit val SIntOption = SOption(SInt)
+ implicit val SLongOption = SOption(SLong)
+ implicit val SBigIntOption = SOption(SBigInt)
+ implicit val SBooleanOption = SOption(SBoolean)
+ implicit val SAvlTreeOption = SOption(SAvlTree)
+ implicit val SGroupElementOption = SOption(SGroupElement)
+ implicit val SSigmaPropOption = SOption(SSigmaProp)
+ implicit val SBoxOption = SOption(SBox)
+
+ def apply[T <: SType](implicit elemType: T, ov: Overloaded1): SOption[T] = SOption(elemType)
+}
+
+
+/** Base class for descriptors of `Coll[T]` ErgoTree type for some elemType T. */
+trait SCollection[T <: SType] extends SProduct with SGenericType {
+ def elemType: T
+ override type WrappedType = Coll[T#WrappedType]
+}
+
+/** Descriptor of `Coll[T]` ErgoTree type for some elemType T. */
+case class SCollectionType[T <: SType](elemType: T) extends SCollection[T] {
+ override val typeCode: TypeCode = SCollectionType.CollectionTypeCode
+ override def typeParams: Seq[STypeParam] = SCollectionType.typeParams
+ override def toString = s"Coll[$elemType]"
+ override def toTermString = s"Coll[${elemType.toTermString}]"
+}
+
+object SCollectionType {
+ /** Code of `Coll[_]` type constructor. */
+ val CollectionTypeConstrId = 1
+
+ /** Type code for `Coll[T] for some T` type used in TypeSerializer. */
+ val CollectionTypeCode: TypeCode = ((SPrimType.MaxPrimTypeCode + 1) * CollectionTypeConstrId).toByte
+
+ /** Code of `Coll[Coll[_]]` type constructor. */
+ val NestedCollectionTypeConstrId = 2
+
+ /** Type code for `Coll[Coll[T]] for some T` type used in TypeSerializer. */
+ val NestedCollectionTypeCode: TypeCode = ((SPrimType.MaxPrimTypeCode + 1) * NestedCollectionTypeConstrId).toByte
+
+ /** Array of generic type parameters reused in all SCollectionType instances. */
+ val typeParams: Seq[STypeParam] = Array(SType.paramIV)
+}
+
+object SCollection extends STypeCompanion {
+ override val reprClass: RClass[_] = RClass(classOf[Coll[_]])
+ override def typeId = SCollectionType.CollectionTypeCode
+
+ /** Costructs a collection type with the given type of elements. */
+ implicit def typeCollection[V <: SType](implicit tV: V): SCollection[V] = SCollection[V](tV)
+
+ /** Helper descriptors reused across different method descriptors. */
+ def tIV = SType.tIV
+ def tOV = SType.tOV
+
+ /** This descriptors are instantiated once here and then reused. */
+ val ThisType = SCollection(tIV)
+ val tOVColl = SCollection(tOV)
+ val tPredicate = SFunc(tIV, SBoolean)
+
+ /** Helper constructors. */
+ def apply[T <: SType](elemType: T): SCollection[T] = SCollectionType(elemType)
+ def apply[T <: SType](implicit elemType: T, ov: Overloaded1): SCollection[T] = SCollectionType(elemType)
+
+ type SBooleanArray = SCollection[SBoolean.type]
+ type SByteArray = SCollection[SByte.type]
+ type SShortArray = SCollection[SShort.type]
+ type SIntArray = SCollection[SInt.type]
+ type SLongArray = SCollection[SLong.type]
+ type SBigIntArray = SCollection[SBigInt.type]
+ type SGroupElementArray = SCollection[SGroupElement.type]
+ type SBoxArray = SCollection[SBox.type]
+ type SAvlTreeArray = SCollection[SAvlTree.type]
+
+ /** This descriptors are instantiated once here and then reused. */
+ val SBooleanArray = SCollection(SBoolean)
+ val SByteArray = SCollection(SByte)
+ val SByteArray2 = SCollection(SCollection(SByte))
+ val SShortArray = SCollection(SShort)
+ val SIntArray = SCollection(SInt)
+ val SLongArray = SCollection(SLong)
+ val SBigIntArray = SCollection(SBigInt)
+ val SGroupElementArray = SCollection(SGroupElement)
+ val SSigmaPropArray = SCollection(SSigmaProp)
+ val SBoxArray = SCollection(SBox)
+ val SAvlTreeArray = SCollection(SAvlTree)
+ val SHeaderArray = SCollection(SHeader)
+}
+
+/** Type descriptor of tuple type. */
+case class STuple(items: IndexedSeq[SType]) extends SCollection[SAny.type] {
+ override val typeCode = STuple.TupleTypeCode
+
+ override def elemType: SAny.type = SAny
+
+ override val typeParams = Nil
+
+ override def toTermString = s"(${items.map(_.toTermString).mkString(",")})"
+ override def toString = s"(${items.mkString(",")})"
+}
+
+object STuple extends STypeCompanion {
+ /** Code of `(_, T) for some embeddable T` type constructor. */
+ val Pair1TypeConstrId = 5
+ /** Type code for `(E, T) for some embeddable T` type used in TypeSerializer. */
+ val Pair1TypeCode: TypeCode = ((SPrimType.MaxPrimTypeCode + 1) * Pair1TypeConstrId).toByte
+
+ /** Code of `(T, _) for some embeddable T` type constructor. */
+ val Pair2TypeConstrId = 6
+ /** Type code for `(T, E) for some embeddable T` type used in TypeSerializer. */
+ val Pair2TypeCode: TypeCode = ((SPrimType.MaxPrimTypeCode + 1) * Pair2TypeConstrId).toByte
+ val TripleTypeCode: TypeCode = Pair2TypeCode
+
+ /** Type constructor code of symmetric pair `(T, T)` for some embeddable T. */
+ val PairSymmetricTypeConstrId = 7
+ /** Type code of symmetric pair `(T, T)` for some embeddable T. */
+ val PairSymmetricTypeCode: TypeCode = ((SPrimType.MaxPrimTypeCode + 1) * PairSymmetricTypeConstrId).toByte
+ val QuadrupleTypeCode: TypeCode = PairSymmetricTypeCode
+
+ /** Type code of generic tuple type. */
+ val TupleTypeCode = ((SPrimType.MaxPrimTypeCode + 1) * 8).toByte
+
+ override def typeId = TupleTypeCode
+
+ override val reprClass: RClass[_] = RClass(classOf[Product2[_,_]])
+
+ /** Helper factory method. */
+ def apply(items: SType*): STuple = STuple(items.toArray)
+
+}
+
+/** Type descriptor of `Box` type of ErgoTree. */
+case object SBox extends SProduct with SPredefType with SMonoType {
+ override type WrappedType = Box
+ override val typeCode: TypeCode = 99: Byte
+ override val reprClass: RClass[_] = RClass(classOf[Box])
+ override def typeId = typeCode
+ implicit def typeBox: SBox.type = this
+}
+
+/** Type descriptor of `AvlTree` type of ErgoTree. */
+case object SAvlTree extends SProduct with SPredefType with SMonoType {
+ override type WrappedType = AvlTree
+ override val typeCode: TypeCode = 100: Byte
+ override val reprClass: RClass[_] = RClass(classOf[AvlTree])
+ override def typeId = typeCode
+ implicit def typeAvlTree: SAvlTree.type = this
+
+ import SOption._
+ lazy val TCollOptionCollByte = SCollection(SByteArrayOption)
+ lazy val CollKeyValue = SCollection(STuple(SByteArray, SByteArray))
+}
+
+/** Type descriptor of `Context` type of ErgoTree. */
+case object SContext extends SProduct with SPredefType with SMonoType {
+ override type WrappedType = Context
+ override val typeCode: TypeCode = 101: Byte
+ override def reprClass: RClass[_] = RClass(classOf[Context])
+ override def typeId = typeCode
+}
+
+/** Type descriptor of `Header` type of ErgoTree. */
+case object SHeader extends SProduct with SPredefType with SMonoType {
+ override type WrappedType = Header
+ override val typeCode: TypeCode = 104: Byte
+ override val reprClass: RClass[_] = RClass(classOf[Header])
+ override def typeId = typeCode
+}
+
+/** Type descriptor of `PreHeader` type of ErgoTree. */
+case object SPreHeader extends SProduct with SPredefType with SMonoType {
+ override type WrappedType = PreHeader
+ override val typeCode: TypeCode = 105: Byte
+ override val reprClass: RClass[_] = RClass(classOf[PreHeader])
+ override def typeId = typeCode
+}
+
+/** This type is introduced to unify handling of global and non-global (i.e. methods) operations.
+ * It unifies implementation of global operation with implementation of methods and avoids code
+ * duplication (following DRY principle https://en.wikipedia.org/wiki/Don%27t_repeat_yourself).
+ * The WrappedType is `sigma.SigmaDslBuilder`, which is an interface implemented by
+ * the singleton sigmastate.eval.CostingSigmaDslBuilder
+ *
+ * The Constant(...) tree node of this type are not allowed, as well as using it in register and
+ * context variables (aka ContextExtension)
+ *
+ * When new methods are added to this type via a soft-fork, they will be serialized as part
+ * of ErgoTree using MethodCallSerializer, where SGlobal.typeCode will be used.
+ *
+ * @see sigmastate.lang.SigmaPredef
+ * */
+case object SGlobal extends SProduct with SPredefType with SMonoType {
+ override type WrappedType = SigmaDslBuilder
+ override val typeCode: TypeCode = 106: Byte
+ override val reprClass: RClass[_] = RClass(classOf[SigmaDslBuilder])
+ override def typeId = typeCode
+}
+
diff --git a/core/shared/src/main/scala/sigma/ast/STypeParam.scala b/core/shared/src/main/scala/sigma/ast/STypeParam.scala
new file mode 100644
index 0000000000..56d89d01f8
--- /dev/null
+++ b/core/shared/src/main/scala/sigma/ast/STypeParam.scala
@@ -0,0 +1,26 @@
+package sigma.ast
+
+/** Represents a type parameter in a type system.
+ *
+ * @param ident The identifier for this type parameter.
+ * @param upperBound The upper bound of this type parameter, if exists.
+ * @param lowerBound The lower bound of this type parameter, if exists.
+ * @note Type parameters with bounds are currently not supported.
+ */
+case class STypeParam(
+ ident: STypeVar,
+ upperBound: Option[SType] = None,
+ lowerBound: Option[SType] = None) {
+ assert(upperBound.isEmpty && lowerBound.isEmpty, s"Type parameters with bounds are not supported, but found $this")
+
+ override def toString = ident.toString + upperBound.fold("")(u => s" <: $u") + lowerBound.fold("")(l => s" >: $l")
+}
+
+object STypeParam {
+ /** Enables implicit conversion from [[STypeVar]] to [[STypeParam]].
+ *
+ * @param id The type variable to convert.
+ * @return A type parameter constructed from the provided type variable.
+ */
+ implicit def typeIdentToTypeParam(id: STypeVar): STypeParam = STypeParam(id)
+}
\ No newline at end of file
diff --git a/core/shared/src/main/scala/sigma/ast/TypeCodes.scala b/core/shared/src/main/scala/sigma/ast/TypeCodes.scala
new file mode 100644
index 0000000000..1b7b6121d6
--- /dev/null
+++ b/core/shared/src/main/scala/sigma/ast/TypeCodes.scala
@@ -0,0 +1,36 @@
+package sigma.ast
+
+import supertagged.TaggedType
+
+/** Encoding of types for serialization. */
+object TypeCodes {
+ object TypeCode extends TaggedType[Byte]
+ type TypeCode = TypeCode.Type
+
+ /** Decoding of types depends on the first byte and in general is a recursive procedure
+ * consuming some number of bytes from Reader.
+ * All data types are recognized by the first byte falling in the region [FirstDataType .. LastDataType] */
+ val FirstDataType: TypeCode = TypeCode @@ 1.toByte
+
+ val LastDataType : TypeCode = TypeCode @@ 111.toByte
+
+ /** SFunc types occupy remaining space of byte values [FirstFuncType .. 255] */
+ val FirstFuncType: TypeCode = TypeCode @@ (LastDataType + 1).toByte
+
+ val LastFuncType : TypeCode = TypeCode @@ 255.toByte
+
+ /** We use optimized encoding of constant values to save space in serialization.
+ * Since Box registers are stored as Constant nodes we save 1 byte for each register.
+ * This is due to convention that Value.opCode falling in [1..LastDataType] region is a constant.
+ * Thus, we can just decode an instance of SType and then decode data using DataSerializer.
+ *
+ * Decoding of constants depends on the first byte and in general is a recursive procedure
+ * consuming some number of bytes from Reader.
+ * */
+ val ConstantCode: Byte = 0.toByte
+
+ /** The last constant code is equal to FirstFuncType which represent generic function type.
+ * We use this single code to represent all functional constants, since we don't have enough space in single byte.
+ * Subsequent bytes have to be read from Reader in order to decode the type of the function and the corresponding data. */
+ val LastConstantCode: Byte = (TypeCodes.LastDataType + 1).toByte
+}
diff --git a/core/shared/src/main/scala/sigma/ast/package.scala b/core/shared/src/main/scala/sigma/ast/package.scala
new file mode 100644
index 0000000000..63a2cfbcba
--- /dev/null
+++ b/core/shared/src/main/scala/sigma/ast/package.scala
@@ -0,0 +1,162 @@
+package sigma
+
+import sigma.kiama.rewriting.Rewriter.{everywherebu, rewrite, rule}
+
+package object ast {
+
+ /** Type alias for a substitution of type variables with their corresponding types. */
+ type STypeSubst = Map[STypeVar, SType]
+
+ /** Immutable and sharable empty substitution. */
+ val EmptySubst = Map.empty[STypeVar, SType]
+
+ /** Performs pairwise type unification making sure each type variable is equally
+ * substituted in all items. */
+ def unifyTypeLists(items1: Seq[SType], items2: Seq[SType]): Option[STypeSubst] = {
+ // unify items pairwise independently
+ val itemsUni = (items1, items2).zipped.map((t1, t2) => unifyTypes(t1, t2))
+ if (itemsUni.forall(_.isDefined)) {
+ // merge substitutions making sure the same id is equally substituted in all items
+ val merged = itemsUni.foldLeft(EmptySubst)((acc, subst) => {
+ var res = acc
+ for ( (id, t) <- subst.get ) {
+ if (res.contains(id) && res(id) != t) return None
+ res = res + (id -> t)
+ }
+ res
+ })
+ Some(merged)
+ } else
+ None
+ }
+
+ private val unifiedWithoutSubst = Some(EmptySubst)
+
+ /** Finds a substitution `subst` of type variables such that unifyTypes(applySubst(t1, subst), t2) shouldBe Some(emptySubst) */
+ def unifyTypes(t1: SType, t2: SType): Option[STypeSubst] = (t1, t2) match {
+ case (_ @ STypeVar(n1), _ @ STypeVar(n2)) =>
+ if (n1 == n2) unifiedWithoutSubst else None
+ case (id1 @ STypeVar(_), _) =>
+ Some(Map(id1 -> t2))
+ case (e1: SCollectionType[_], e2: SCollectionType[_]) =>
+ unifyTypes(e1.elemType, e2.elemType)
+ case (e1: SCollectionType[_], _: STuple) =>
+ unifyTypes(e1.elemType, SAny)
+ case (e1: SOption[_], e2: SOption[_]) =>
+ unifyTypes(e1.elemType, e2.elemType)
+ case (e1: STuple, e2: STuple) if e1.items.length == e2.items.length =>
+ unifyTypeLists(e1.items, e2.items)
+ case (e1: SFunc, e2: SFunc) if e1.tDom.length == e2.tDom.length =>
+ unifyTypeLists(e1.tDom :+ e1.tRange, e2.tDom :+ e2.tRange)
+ case (STypeApply(name1, args1), STypeApply(name2, args2))
+ if name1 == name2 && args1.length == args2.length =>
+ unifyTypeLists(args1, args2)
+ case (SBoolean, SSigmaProp) => // it is necessary for implicit conversion in Coll(bool, prop, bool)
+ unifiedWithoutSubst
+ case (SPrimType(e1), SPrimType(e2)) if e1 == e2 =>
+ unifiedWithoutSubst
+ case (SAny, _) =>
+ unifiedWithoutSubst
+ case _ => None
+ }
+
+ /** Applies a type substitution to a given type.
+ *
+ * @param tpe the type to apply the substitution to
+ * @param subst the type substitution to apply
+ * @return the type after applying the substitution
+ */
+ def applySubst(tpe: SType, subst: STypeSubst): SType = tpe match {
+ case SFunc(args, res, tparams) =>
+ val remainingVars = tparams.filterNot { p => subst.contains(p.ident) }
+ SFunc(args.map(applySubst(_, subst)), applySubst(res, subst), remainingVars)
+ case _ =>
+ val substRule = rule[Any] {
+ case id: STypeVar if subst.contains(id) => subst(id)
+ }
+ rewrite(everywherebu(substRule))(tpe)
+ }
+
+ /** Computes the most general type given two types.
+ *
+ * @param t1 the first type
+ * @param t2 the second type
+ * @return the most general type if it exists, otherwise None
+ */
+ def msgType(t1: SType, t2: SType): Option[SType] = unifyTypes(t1, t2) match {
+ case Some(_) => Some(t1)
+ case None => unifyTypes(t2, t1).map(_ => t2)
+ }
+
+ /** Most Specific Generalized (MSG) type of ts.
+ * Currently just the type of the first element as long as all the elements have the same type. */
+ def msgTypeOf(ts: Seq[SType]): Option[SType] = {
+ if (ts.isEmpty) None
+ else {
+ var res: SType = ts.head
+ for ( t <- ts.iterator.drop(1) ) {
+ msgType(t, res) match {
+ case Some(msg) => res = msg //assign new
+ case None => return None
+ }
+ }
+ Some(res)
+ }
+ }
+
+ implicit class STypeOps(val tpe: SType) extends AnyVal {
+ def isCollectionLike: Boolean = tpe.isInstanceOf[SCollection[_]]
+
+ def isCollection: Boolean = tpe.isInstanceOf[SCollectionType[_]]
+
+ def isOption: Boolean = tpe.isInstanceOf[SOption[_]]
+
+ def isBox: Boolean = tpe.isInstanceOf[SBox.type]
+
+ def isGroupElement: Boolean = tpe.isInstanceOf[SGroupElement.type]
+
+ def isSigmaProp: Boolean = tpe.isInstanceOf[SSigmaProp.type]
+
+ def isAvlTree: Boolean = tpe.isInstanceOf[SAvlTree.type]
+
+ def isFunc: Boolean = tpe.isInstanceOf[SFunc]
+
+ def isTuple: Boolean = tpe.isInstanceOf[STuple]
+
+ /** Returns true if this type is numeric (Byte, Short, etc.)
+ *
+ * @see [[sigmastate.SNumericType]]
+ */
+ def isNumType: Boolean = tpe.isInstanceOf[SNumericType]
+
+ /** Returns true if this type is either numeric (Byte, Short, etc.) or is NoType.
+ *
+ * @see [[sigmastate.SNumericType]]
+ */
+ def isNumTypeOrNoType: Boolean = isNumType || tpe == NoType
+
+ def asNumType: SNumericType = tpe.asInstanceOf[SNumericType]
+
+ def asFunc: SFunc = tpe.asInstanceOf[SFunc]
+
+ def asProduct: SProduct = tpe.asInstanceOf[SProduct]
+
+ def asTuple: STuple = tpe.asInstanceOf[STuple]
+
+ def asOption[T <: SType]: SOption[T] = tpe.asInstanceOf[SOption[T]]
+
+ def whenFunc[T](action: SFunc => Unit) = if (tpe.isInstanceOf[SFunc]) action(tpe.asFunc)
+
+ def asCollection[T <: SType] = tpe.asInstanceOf[SCollection[T]]
+
+ /** Applies a type substitution to this type.
+ *
+ * @param subst the type substitution to apply
+ * @return the type after applying the substitution
+ */
+ def withSubstTypes(subst: Map[STypeVar, SType]): SType =
+ if (subst.isEmpty) tpe
+ else
+ applySubst(tpe, subst)
+ }
+}
diff --git a/interpreter/shared/src/main/scala/sigmastate/crypto/CryptoContext.scala b/core/shared/src/main/scala/sigma/crypto/CryptoContext.scala
similarity index 85%
rename from interpreter/shared/src/main/scala/sigmastate/crypto/CryptoContext.scala
rename to core/shared/src/main/scala/sigma/crypto/CryptoContext.scala
index c0190ba093..988a8e9283 100644
--- a/interpreter/shared/src/main/scala/sigmastate/crypto/CryptoContext.scala
+++ b/core/shared/src/main/scala/sigma/crypto/CryptoContext.scala
@@ -1,4 +1,4 @@
-package sigmastate.crypto
+package sigma.crypto
import java.math.BigInteger
@@ -31,3 +31,8 @@ abstract class CryptoContext {
def generator: Ecp
}
+object CryptoContext {
+ /** Default context for cryptographic operations. */
+ val default: CryptoContext = Platform.createContext()
+}
+
diff --git a/interpreter/shared/src/main/scala/sigmastate/crypto/CryptoFacade.scala b/core/shared/src/main/scala/sigma/crypto/CryptoFacade.scala
similarity index 99%
rename from interpreter/shared/src/main/scala/sigmastate/crypto/CryptoFacade.scala
rename to core/shared/src/main/scala/sigma/crypto/CryptoFacade.scala
index 3ce337d695..683ec3f1b7 100644
--- a/interpreter/shared/src/main/scala/sigmastate/crypto/CryptoFacade.scala
+++ b/core/shared/src/main/scala/sigma/crypto/CryptoFacade.scala
@@ -1,4 +1,4 @@
-package sigmastate.crypto
+package sigma.crypto
import java.math.BigInteger
diff --git a/core/shared/src/main/scala/sigma/crypto/package.scala b/core/shared/src/main/scala/sigma/crypto/package.scala
new file mode 100644
index 0000000000..cc2598f62a
--- /dev/null
+++ b/core/shared/src/main/scala/sigma/crypto/package.scala
@@ -0,0 +1,27 @@
+package sigma
+
+package object crypto {
+ /** Length of hash function used in the signature scheme. Blake2b hash function is used. */
+ val hashLengthBits = 256
+
+ /** Length of hash in bytes. */
+ val hashLength: Int = hashLengthBits / 8
+
+ /** Number of bytes to represent any group element as byte array */
+ val groupSize: Int = 256 / 8 //32 bytes
+
+ /** Instance of Elliptic Curve descriptor. */
+ type Curve = Platform.Curve
+
+ /** Instance of Elliptic Curve point. */
+ type Ecp = Platform.Ecp
+
+ /** Instance of Elliptic Curve field element. */
+ type ECFieldElem = Platform.ECFieldElem
+
+ /** A cryptographically strong random number generator. */
+ type SecureRandom = Platform.SecureRandom
+
+ /** Type of group elements used in the signature scheme. */
+ type EcPointType = Ecp
+}
diff --git a/interpreter/shared/src/main/scala/sigmastate/AvlTreeData.scala b/core/shared/src/main/scala/sigma/data/AvlTreeData.scala
similarity index 85%
rename from interpreter/shared/src/main/scala/sigmastate/AvlTreeData.scala
rename to core/shared/src/main/scala/sigma/data/AvlTreeData.scala
index 83f9b756c7..bddb0e5c44 100644
--- a/interpreter/shared/src/main/scala/sigmastate/AvlTreeData.scala
+++ b/core/shared/src/main/scala/sigma/data/AvlTreeData.scala
@@ -1,9 +1,7 @@
-package sigmastate
+package sigma.data
-import sigmastate.crypto.CryptoConstants
-import sigmastate.serialization.SigmaSerializer
-import sigmastate.utils.{SigmaByteReader, SigmaByteWriter}
-import sigma.{Coll, Colls}
+import sigma.serialization.{CoreByteReader, CoreByteWriter, CoreSerializer}
+import sigma.{Coll, Colls, crypto}
case class AvlTreeFlags(insertAllowed: Boolean, updateAllowed: Boolean, removeAllowed: Boolean) {
@@ -56,7 +54,7 @@ case class AvlTreeData(digest: Coll[Byte],
valueLengthOpt: Option[Int] = None)
object AvlTreeData {
- val DigestSize: Int = CryptoConstants.hashLength + 1 //please read class comments above for details
+ val DigestSize: Int = crypto.hashLength + 1 //please read class comments above for details
val TreeDataSize = DigestSize + 3 + 4 + 4
val dummy = new AvlTreeData(
@@ -67,12 +65,12 @@ object AvlTreeData {
/** Create [[AvlTreeData]] with the given digest and all operations enabled. */
def avlTreeFromDigest(digest: Coll[Byte]): AvlTreeData = {
val flags = AvlTreeFlags(insertAllowed = true, updateAllowed = true, removeAllowed = true)
- AvlTreeData(digest, flags, CryptoConstants.hashLength)
+ AvlTreeData(digest, flags, crypto.hashLength)
}
- object serializer extends SigmaSerializer[AvlTreeData, AvlTreeData] {
+ object serializer extends CoreSerializer[AvlTreeData, AvlTreeData] {
- override def serialize(data: AvlTreeData, w: SigmaByteWriter): Unit = {
+ override def serialize(data: AvlTreeData, w: CoreByteWriter): Unit = {
val tf = AvlTreeFlags.serializeFlags(data.treeFlags)
w.putBytes(data.digest.toArray)
.putUByte(tf)
@@ -80,7 +78,7 @@ object AvlTreeData {
.putOption(data.valueLengthOpt)(_.putUInt(_))
}
- override def parse(r: SigmaByteReader): AvlTreeData = {
+ override def parse(r: CoreByteReader): AvlTreeData = {
val digest = r.getBytes(DigestSize)
val tf = AvlTreeFlags(r.getByte())
val keyLength = r.getUInt().toInt
diff --git a/core/shared/src/main/scala/sigma/data/CAnyValue.scala b/core/shared/src/main/scala/sigma/data/CAnyValue.scala
new file mode 100644
index 0000000000..9c10dfbbe2
--- /dev/null
+++ b/core/shared/src/main/scala/sigma/data/CAnyValue.scala
@@ -0,0 +1,18 @@
+package sigma.data
+
+import sigma.AnyValue
+import sigma.data.OverloadHack.Overloaded1
+
+import scala.annotation.unused
+
+/** Default implementation of AnyValue interface. */
+case class CAnyValue[A](value: A, tVal: RType[Any]) extends AnyValue {
+ def tA: RType[A] = tVal.asInstanceOf[RType[A]]
+
+ override def toString = s"TestValue($value)"
+}
+
+object CAnyValue {
+ def apply[A](value: A)(implicit t: RType[A], @unused o: Overloaded1): CAnyValue[A] =
+ new CAnyValue(value, t.asInstanceOf[RType[Any]])
+}
\ No newline at end of file
diff --git a/core/shared/src/main/scala/sigma/data/CAvlTree.scala b/core/shared/src/main/scala/sigma/data/CAvlTree.scala
new file mode 100644
index 0000000000..a37e5096bb
--- /dev/null
+++ b/core/shared/src/main/scala/sigma/data/CAvlTree.scala
@@ -0,0 +1,36 @@
+package sigma.data
+
+import sigma.{AvlTree, Coll}
+
+/** A default implementation of [[AvlTree]] interface.
+ *
+ * @see [[AvlTree]] for detailed descriptions
+ */
+case class CAvlTree(treeData: AvlTreeData) extends AvlTree with WrapperOf[AvlTreeData] {
+ override def wrappedValue: AvlTreeData = treeData
+
+ override def keyLength: Int = treeData.keyLength
+
+ override def enabledOperations = treeData.treeFlags.serializeToByte
+
+ override def isInsertAllowed: Boolean = treeData.treeFlags.insertAllowed
+
+ override def isUpdateAllowed: Boolean = treeData.treeFlags.updateAllowed
+
+ override def isRemoveAllowed: Boolean = treeData.treeFlags.removeAllowed
+
+ override def updateOperations(newOperations: Byte): AvlTree = {
+ val td = treeData.copy(treeFlags = AvlTreeFlags(newOperations))
+ this.copy(treeData = td)
+ }
+
+ override def valueLengthOpt: Option[Int] = treeData.valueLengthOpt
+
+ override def digest: Coll[Byte] = treeData.digest
+
+ override def updateDigest(newDigest: Coll[Byte]): AvlTree = {
+ val td = treeData.copy(digest = newDigest)
+ this.copy(treeData = td)
+ }
+}
+
diff --git a/core/shared/src/main/scala/sigma/data/CBigInt.scala b/core/shared/src/main/scala/sigma/data/CBigInt.scala
new file mode 100644
index 0000000000..bbf1a85e46
--- /dev/null
+++ b/core/shared/src/main/scala/sigma/data/CBigInt.scala
@@ -0,0 +1,52 @@
+package sigma.data
+
+import sigma.util.Extensions.BigIntegerOps
+import sigma.{BigInt, Coll, Colls}
+
+import java.math.BigInteger
+
+/** A default implementation of [[BigInt]] interface.
+ *
+ * @see [[BigInt]] for detailed descriptions
+ */
+case class CBigInt(override val wrappedValue: BigInteger) extends BigInt with WrapperOf[BigInteger] {
+
+ override def toByte: Byte = wrappedValue.toByteExact
+
+ override def toShort: Short = wrappedValue.toShortExact
+
+ override def toInt: Int = wrappedValue.toIntExact
+
+ override def toLong: Long = wrappedValue.toLongExact
+
+ override def toBytes: Coll[Byte] = Colls.fromArray(wrappedValue.toByteArray)
+
+ override def toAbs: BigInt = CBigInt(wrappedValue.abs())
+
+ override def compareTo(that: BigInt): Int =
+ wrappedValue.compareTo(that.asInstanceOf[CBigInt].wrappedValue)
+
+ override def signum: Int = wrappedValue.signum()
+
+ override def add(that: BigInt): BigInt = CBigInt(wrappedValue.add(that.asInstanceOf[CBigInt].wrappedValue).to256BitValueExact)
+
+ override def subtract(that: BigInt): BigInt = CBigInt(wrappedValue.subtract(that.asInstanceOf[CBigInt].wrappedValue).to256BitValueExact)
+
+ override def multiply(that: BigInt): BigInt = CBigInt(wrappedValue.multiply(that.asInstanceOf[CBigInt].wrappedValue).to256BitValueExact)
+
+ override def divide(that: BigInt): BigInt = CBigInt(wrappedValue.divide(that.asInstanceOf[CBigInt].wrappedValue))
+
+ override def mod(m: BigInt): BigInt = CBigInt(wrappedValue.mod(m.asInstanceOf[CBigInt].wrappedValue))
+
+ override def remainder(that: BigInt): BigInt = CBigInt(wrappedValue.remainder(that.asInstanceOf[CBigInt].wrappedValue))
+
+ override def min(that: BigInt): BigInt = CBigInt(wrappedValue.min(that.asInstanceOf[CBigInt].wrappedValue))
+
+ override def max(that: BigInt): BigInt = CBigInt(wrappedValue.max(that.asInstanceOf[CBigInt].wrappedValue))
+
+ override def negate(): BigInt = CBigInt(wrappedValue.negate().to256BitValueExact)
+
+ override def and(that: BigInt): BigInt = CBigInt(wrappedValue.and(that.asInstanceOf[CBigInt].wrappedValue))
+
+ override def or(that: BigInt): BigInt = CBigInt(wrappedValue.or(that.asInstanceOf[CBigInt].wrappedValue))
+}
diff --git a/core/shared/src/main/scala/sigma/data/CGroupElement.scala b/core/shared/src/main/scala/sigma/data/CGroupElement.scala
new file mode 100644
index 0000000000..ed4849f0d7
--- /dev/null
+++ b/core/shared/src/main/scala/sigma/data/CGroupElement.scala
@@ -0,0 +1,29 @@
+package sigma.data
+
+import sigma.crypto.{CryptoFacade, Ecp}
+import sigma.serialization.GroupElementSerializer
+import sigma.util.Extensions.EcpOps
+import sigma.{BigInt, Coll, Colls, GroupElement}
+
+/** A default implementation of [[GroupElement]] interface.
+ *
+ * @see [[GroupElement]] for detailed descriptions
+ */
+case class CGroupElement(override val wrappedValue: Ecp) extends GroupElement with WrapperOf[Ecp] {
+
+ override def toString: String = s"GroupElement(${wrappedValue.showECPoint})"
+
+ override def getEncoded: Coll[Byte] =
+ Colls.fromArray(GroupElementSerializer.toBytes(wrappedValue))
+
+ override def isIdentity: Boolean = CryptoFacade.isInfinityPoint(wrappedValue)
+
+ override def exp(k: BigInt): GroupElement =
+ CGroupElement(CryptoFacade.exponentiatePoint(wrappedValue, k.asInstanceOf[CBigInt].wrappedValue))
+
+ override def multiply(that: GroupElement): GroupElement =
+ CGroupElement(CryptoFacade.multiplyPoints(wrappedValue, that.asInstanceOf[CGroupElement].wrappedValue))
+
+ override def negate: GroupElement =
+ CGroupElement(CryptoFacade.negatePoint(wrappedValue))
+}
diff --git a/core/shared/src/main/scala/sigma/data/CSigmaProp.scala b/core/shared/src/main/scala/sigma/data/CSigmaProp.scala
new file mode 100644
index 0000000000..d8a472424c
--- /dev/null
+++ b/core/shared/src/main/scala/sigma/data/CSigmaProp.scala
@@ -0,0 +1,61 @@
+package sigma.data
+
+import sigma.ast.SSigmaProp
+import sigma.serialization.CoreSerializer
+import sigma.util.Extensions.SigmaBooleanOps
+import sigma.{Coll, Colls, GroupElement, SigmaProp}
+
+/** A default implementation of [[SigmaProp]] interface.
+ *
+ * @see [[SigmaProp]] for detailed descriptions
+ */
+case class CSigmaProp(sigmaTree: SigmaBoolean) extends SigmaProp with WrapperOf[SigmaBoolean] {
+ override def wrappedValue: SigmaBoolean = sigmaTree
+
+ // TODO refactor: remove this (it shouldn't be used in interpreter)
+ override def isValid: Boolean = sigmaTree match {
+ case p: TrivialProp => p.condition
+ case _ => sys.error(s"Method CostingSigmaProp.isValid is not defined for $sigmaTree")
+ }
+
+ override def propBytes: Coll[Byte] = {
+ // in order to have comparisons like `box.propositionBytes == pk.propBytes` we need to make sure
+ // the same serialization method is used in both cases
+ // TODO v6.0: add `pk.propBytes(version)` (see https://github.com/ScorexFoundation/sigmastate-interpreter/issues/903)
+ val w = CoreSerializer.startWriter()
+ w.put(0) // ErgoTree.header
+ w.putType(SSigmaProp)
+ SigmaBoolean.serializer.serialize(wrappedValue, w)
+ Colls.fromArray(w.toBytes)
+ }
+
+ override def &&(other: SigmaProp): SigmaProp = other match {
+ case other: CSigmaProp =>
+ CSigmaProp(CAND.normalized(Array(sigmaTree, other.sigmaTree)))
+ }
+
+ override def ||(other: SigmaProp): SigmaProp = other match {
+ case other: CSigmaProp =>
+ CSigmaProp(COR.normalized(Array(sigmaTree, other.sigmaTree)))
+ }
+
+ override def toString: String = s"SigmaProp(${wrappedValue.showToString})"
+}
+
+object CSigmaProp {
+ /** Create trivial sigma proposition with given boolean value. */
+ def apply(b: Boolean): CSigmaProp =
+ CSigmaProp(TrivialProp(b))
+
+ /** Create SigmaProp value with underlying ProveDlog proposition. */
+ def withProveDlog(ge: GroupElement) =
+ CSigmaProp(ProveDlog(ge.asInstanceOf[CGroupElement].wrappedValue))
+
+ /** Create SigmaProp value with underlying ProveDHTuple proposition. */
+ def withProveDHTuple(g: GroupElement, h: GroupElement, u: GroupElement, v: GroupElement) =
+ CSigmaProp(ProveDHTuple(
+ g.asInstanceOf[CGroupElement].wrappedValue,
+ h.asInstanceOf[CGroupElement].wrappedValue,
+ u.asInstanceOf[CGroupElement].wrappedValue,
+ v.asInstanceOf[CGroupElement].wrappedValue))
+}
diff --git a/core/shared/src/main/scala/sigma/data/CollsOverArrays.scala b/core/shared/src/main/scala/sigma/data/CollsOverArrays.scala
index a5bb543e1b..2413f7f427 100644
--- a/core/shared/src/main/scala/sigma/data/CollsOverArrays.scala
+++ b/core/shared/src/main/scala/sigma/data/CollsOverArrays.scala
@@ -45,7 +45,7 @@ class CollOverArray[@specialized A](val toArray: Array[A], val builder: CollBuil
// in v5.0 and above this fixes the ClassCastException problem
safeConcatArrays_v5(toArray, other.toArray)(tA.classTag)
} else {
- CollectionUtil.concatArrays(toArray, other.toArray)
+ CollectionUtil.concatArrays_v4(toArray, other.toArray)
}
builder.fromArray(result)
}
diff --git a/core/shared/src/main/scala/sigma/data/Iso.scala b/core/shared/src/main/scala/sigma/data/Iso.scala
new file mode 100644
index 0000000000..9b90d63bb0
--- /dev/null
+++ b/core/shared/src/main/scala/sigma/data/Iso.scala
@@ -0,0 +1,52 @@
+package sigma.data
+
+import scorex.util.encode.Base16
+import sigma.Extensions.CollBytesOps
+import sigma.{Coll, Colls}
+
+/** Type-class of isomorphisms between types.
+ * Isomorphism between two types `A` and `B` essentially say that both types
+ * represents the same information (entity) but in a different way.
+ *
+ * The information is not lost so that both are true:
+ * 1) a == from(to(a))
+ * 2) b == to(from(b))
+ *
+ * It is used to define type-full conversions:
+ * - different conversions between Java and Scala data types.
+ * - conversion between Ergo representations and generated API representations
+ */
+abstract class Iso[A, B] {
+ def to(a: A): B
+ def from(b: B): A
+ def andThen[C](iso: Iso[B,C]): Iso[A,C] = ComposeIso(iso, this)
+ def inverse: Iso[B, A] = InverseIso(this)
+}
+final case class InverseIso[A,B](iso: Iso[A,B]) extends Iso[B,A] {
+ override def to(a: B): A = iso.from(a)
+ override def from(b: A): B = iso.to(b)
+}
+final case class ComposeIso[A, B, C](iso2: Iso[B, C], iso1: Iso[A, B]) extends Iso[A, C] {
+ def from(c: C): A = iso1.from(iso2.from(c))
+ def to(a: A): C = iso2.to(iso1.to(a))
+}
+
+object Iso {
+ implicit def identityIso[A]: Iso[A, A] = new Iso[A, A] {
+ override def to(a: A): A = a
+ override def from(b: A): A = b
+ }
+
+ implicit def inverseIso[A, B](implicit iso: Iso[A, B]): Iso[B, A] = InverseIso[A, B](iso)
+
+ val isoStringToArray: Iso[String, Array[Byte]] = new Iso[String, Array[Byte]] {
+ override def to(x: String): Array[Byte] = Base16.decode(x).get
+ override def from(x: Array[Byte]): String = Base16.encode(x)
+ }
+
+ val isoStringToColl: Iso[String, Coll[Byte]] = new Iso[String, Coll[Byte]] {
+ override def to(x: String): Coll[Byte] = Colls.fromArray(Base16.decode(x).get)
+ override def from(x: Coll[Byte]): String = x.toHex
+ }
+
+}
\ No newline at end of file
diff --git a/core/shared/src/main/scala/sigma/data/RType.scala b/core/shared/src/main/scala/sigma/data/RType.scala
index 281e032aa4..54402f1254 100644
--- a/core/shared/src/main/scala/sigma/data/RType.scala
+++ b/core/shared/src/main/scala/sigma/data/RType.scala
@@ -48,12 +48,6 @@ case class PrimitiveType[A](
override def name: String = classTag.toString()
}
-case class StringType() extends RType[String] {
- override def classTag: ClassTag[String] = ClassTag[String](classOf[String])
-
- override def name: String = "String"
-}
-
/** Descriptor of descriptor to represent type of RType[_] instances.
* This describes any possible descriptor, disregarding its underlying type.
* Thus the underlying type is assumed to be Any. */
diff --git a/core/shared/src/main/scala/sigma/data/SigmaBoolean.scala b/core/shared/src/main/scala/sigma/data/SigmaBoolean.scala
new file mode 100644
index 0000000000..681a7d40d2
--- /dev/null
+++ b/core/shared/src/main/scala/sigma/data/SigmaBoolean.scala
@@ -0,0 +1,257 @@
+package sigma.data
+
+import debox.cfor
+import sigma.crypto.EcPointType
+import sigma.data.SigmaPropCodes.{AndCode, AtLeastCode, OrCode, ProveDiffieHellmanTupleCode, ProveDlogCode, SPCode}
+import sigma.data.TrivialProp.{FalseProp, TrueProp}
+import sigma.serialization.{CoreByteReader, CoreByteWriter, CoreSerializer, GroupElementSerializer, ProveDHTupleSerializer, ProveDlogSerializer}
+import sigma.util.safeNewArray
+
+import scala.collection.mutable.ArrayBuffer
+
+/** Algebraic data type of sigma proposition expressions.
+ * Values of this type are used as values of SigmaProp type of SigmaScript and SigmaDsl
+ */
+sealed trait SigmaBoolean {
+ /** Unique id of the node class used in serialization of SigmaBoolean. */
+ val opCode: SPCode
+
+ /** Size of the proposition tree (number of nodes). */
+ def size: Int
+}
+
+object SigmaBoolean {
+ /** Compute total size of the trees in the collection of children. */
+ def totalSize(children: Seq[SigmaBoolean]): Int = {
+ var res = 0
+ val len = children.length
+ cfor(0)(_ < len, _ + 1) { i =>
+ res += children(i).size
+ }
+ res
+ }
+
+ /** HOTSPOT: don't beautify this code */
+ object serializer extends CoreSerializer[SigmaBoolean, SigmaBoolean] {
+ val dhtSerializer = ProveDHTupleSerializer(ProveDHTuple.apply)
+
+ val dlogSerializer = ProveDlogSerializer(ProveDlog.apply)
+
+ override def serialize(data: SigmaBoolean, w: CoreByteWriter): Unit = {
+ w.put(data.opCode)
+ data match {
+ case dlog: ProveDlog => dlogSerializer.serialize(dlog, w)
+ case dht: ProveDHTuple => dhtSerializer.serialize(dht, w)
+ case _: TrivialProp => // besides opCode no additional bytes
+ case and: CAND =>
+ val nChildren = and.children.length
+ w.putUShort(nChildren)
+ cfor(0)(_ < nChildren, _ + 1) { i =>
+ val c = and.children(i)
+ serializer.serialize(c, w)
+ }
+ case or: COR =>
+ val nChildren = or.children.length
+ w.putUShort(nChildren)
+ cfor(0)(_ < nChildren, _ + 1) { i =>
+ val c = or.children(i)
+ serializer.serialize(c, w)
+ }
+ case th: CTHRESHOLD =>
+ w.putUShort(th.k)
+ val nChildren = th.children.length
+ w.putUShort(nChildren)
+ cfor(0)(_ < nChildren, _ + 1) { i =>
+ val c = th.children(i)
+ serializer.serialize(c, w)
+ }
+ }
+ }
+
+ override def parse(r: CoreByteReader): SigmaBoolean = {
+ val depth = r.level
+ r.level = depth + 1
+ val opCode = r.getByte()
+ val res = opCode match {
+ case FalseProp.opCode => FalseProp
+ case TrueProp.opCode => TrueProp
+ case ProveDlogCode => dlogSerializer.parse(r)
+ case ProveDiffieHellmanTupleCode => dhtSerializer.parse(r)
+ case AndCode =>
+ val n = r.getUShort()
+ val children = safeNewArray[SigmaBoolean](n)
+ cfor(0)(_ < n, _ + 1) { i =>
+ children(i) = serializer.parse(r)
+ }
+ CAND(children)
+ case OrCode =>
+ val n = r.getUShort()
+ val children = safeNewArray[SigmaBoolean](n)
+ cfor(0)(_ < n, _ + 1) { i =>
+ children(i) = serializer.parse(r)
+ }
+ COR(children)
+ case AtLeastCode =>
+ val k = r.getUShort()
+ val n = r.getUShort()
+ val children = safeNewArray[SigmaBoolean](n)
+ cfor(0)(_ < n, _ + 1) { i =>
+ children(i) = serializer.parse(r)
+ }
+ CTHRESHOLD(k, children)
+ }
+ r.level = r.level - 1
+ res
+ }
+ }
+}
+
+/**
+ * Basic trait for inner nodes of crypto-trees, so AND/OR/THRESHOLD sigma-protocol connectives
+ */
+trait SigmaConjecture extends SigmaBoolean {
+ def children: Seq[SigmaBoolean]
+}
+
+/**
+ * Basic trait for leafs of crypto-trees, such as
+ * [[sigmastate.crypto.DLogProtocol.ProveDlog]] and [[sigmastate.crypto.ProveDHTuple]]
+ * instances.
+ * It plays the same role as [[SigmaConjecture]]. It used in prover to distinguish leafs from
+ * other nodes and have logic common to leaves regardless of the concrete leaf type.
+ */
+trait SigmaLeaf extends SigmaBoolean
+
+/** Construct a new SigmaBoolean value representing public key of discrete logarithm signature protocol. */
+case class ProveDlog(value: EcPointType) extends SigmaLeaf {
+ override def size: Int = 1
+ override val opCode : SPCode = SigmaPropCodes.ProveDlogCode
+
+ /** Serialized bytes of the elliptic curve point (using GroupElementSerializer). */
+ lazy val pkBytes: Array[Byte] = GroupElementSerializer.toBytes(value)
+}
+
+/** Construct a new SigmaProp value representing public key of Diffie Hellman signature protocol.
+ * Common input: (g,h,u,v) */
+case class ProveDHTuple(gv: EcPointType, hv: EcPointType, uv: EcPointType, vv: EcPointType)
+ extends SigmaLeaf {
+ override val opCode: SPCode = SigmaPropCodes.ProveDiffieHellmanTupleCode
+ override def size: Int = 4 // one node for each EcPoint
+ lazy val g = gv
+ lazy val h = hv
+ lazy val u = uv
+ lazy val v = vv
+}
+
+/**
+ * AND conjunction for sigma propositions
+ */
+case class CAND(override val children: Seq[SigmaBoolean]) extends SigmaConjecture {
+ /** The same code is used for AND operation, but they belong to different type hierarchies. */
+ override val opCode: SPCode = SigmaPropCodes.AndCode
+ override val size: Int = SigmaBoolean.totalSize(children) + 1
+}
+
+object CAND {
+ import TrivialProp._
+
+ /** Connects the given sigma propositions into CAND proposition performing
+ * partial evaluation when some of them are trivial propositioins.
+ *
+ * @param items propositions to combine into CAND
+ * @return CAND, TrueProp, FalseProp or even one of the items depending on partial evaluation
+ */
+ def normalized(items: Seq[SigmaBoolean]): SigmaBoolean = {
+ require(items.nonEmpty)
+ val res = new ArrayBuffer[SigmaBoolean]()
+ val nItems = items.length
+ cfor(0)(_ < nItems, _ + 1) { i =>
+ val x = items(i)
+ x match {
+ case FalseProp => return FalseProp
+ case TrueProp => // skip
+ case _ => res += x
+ }
+ }
+ if (res.isEmpty) TrueProp
+ else if (res.length == 1) res(0)
+ else CAND(res.toSeq)
+ }
+}
+
+/**
+ * OR disjunction for sigma propositions
+ */
+case class COR(children: Seq[SigmaBoolean]) extends SigmaConjecture {
+ /** The same code is also used for OR operation, but they belong to different type hierarchies. */
+ override val opCode: SPCode = SigmaPropCodes.OrCode
+ override val size: Int = SigmaBoolean.totalSize(children) + 1
+}
+
+object COR {
+ import TrivialProp._
+
+ /** Connects the given sigma propositions into COR proposition performing
+ * partial evaluation when some of them are trivial propositioins.
+ *
+ * @param items propositions to combine into COR
+ * @return COR, TrueProp, FalseProp or even one of the items depending on partial evaluation
+ */
+ def normalized(items: Seq[SigmaBoolean]): SigmaBoolean = {
+ require(items.nonEmpty)
+ val res = new ArrayBuffer[SigmaBoolean]()
+ val nItems = items.length
+ cfor(0)(_ < nItems, _ + 1) { i =>
+ val x = items(i)
+ x match {
+ case FalseProp => // skip
+ case TrueProp => return TrueProp
+ case _ => res += x
+ }
+ }
+ if (res.isEmpty) FalseProp
+ else if (res.length == 1) res(0)
+ else COR(res.toSeq)
+ }
+}
+
+/**
+ * THRESHOLD connector for sigma propositions
+ */
+case class CTHRESHOLD(k: Int, children: Seq[SigmaBoolean]) extends SigmaConjecture {
+ // Our polynomial arithmetic can take only byte inputs
+ require(k >= 0 && k <= children.length && children.length <= 255)
+
+ override val opCode: SPCode = SigmaPropCodes.AtLeastCode
+ override val size: Int = SigmaBoolean.totalSize(children) + 1
+}
+
+
+/** Represents boolean values (true/false) in SigmaBoolean tree.
+ * Participates in evaluation of CAND, COR, THRESHOLD connectives over SigmaBoolean values.
+ * See CAND.normalized, COR.normalized and AtLeast.reduce. */
+abstract class TrivialProp(val condition: Boolean) extends SigmaBoolean with Product1[Boolean] {
+ override def _1: Boolean = condition
+ override def canEqual(that: Any): Boolean = that != null && that.isInstanceOf[TrivialProp]
+}
+object TrivialProp {
+ // NOTE: the corresponding unapply is missing because any implementation (even using Nullable)
+ // will lead to Boolean boxing, which we want to avoid
+ // So, instead of `case TrivialProp(b) => ... b ...` use more efficient
+ // `case p: TrivialProp => ... p.condition ...
+
+ def apply(b: Boolean): TrivialProp = if (b) TrueProp else FalseProp
+
+ val FalseProp = new TrivialProp(false) {
+ override val opCode: SPCode = SigmaPropCodes.TrivialPropFalseCode
+ override def size: Int = 1
+ override def toString = "FalseProp"
+ }
+ val TrueProp = new TrivialProp(true) {
+ override val opCode: SPCode = SigmaPropCodes.TrivialPropTrueCode
+ override def size: Int = 1
+ override def toString = "TrueProp"
+ }
+}
+
+
diff --git a/interpreter/shared/src/main/scala/org/ergoplatform/SigmaConstants.scala b/core/shared/src/main/scala/sigma/data/SigmaConstants.scala
similarity index 94%
rename from interpreter/shared/src/main/scala/org/ergoplatform/SigmaConstants.scala
rename to core/shared/src/main/scala/sigma/data/SigmaConstants.scala
index 74dc98ade9..7198d5dc09 100644
--- a/interpreter/shared/src/main/scala/org/ergoplatform/SigmaConstants.scala
+++ b/core/shared/src/main/scala/sigma/data/SigmaConstants.scala
@@ -1,7 +1,6 @@
-package org.ergoplatform
+package sigma.data
import sigma.util.CollectionUtil.TraversableOps // used in Scala 2.11
-import sigmastate.crypto.CryptoConstants
/** Descriptor of a constant which represents some size value.
* @tparam T type of the constant value
@@ -42,7 +41,8 @@ object SigmaConstants {
"Max length of Box.propositionBytes collection") {
}
- object MaxBoxSizeWithoutRefs extends SizeConstant[Int](MaxBoxSize.value - (CryptoConstants.hashLength + 2/*size of Short*/), 6,
+ object MaxBoxSizeWithoutRefs extends SizeConstant[Int](
+ MaxBoxSize.value - (32/*CryptoConstants.hashLength*/ + 2/*size of Short*/), 6,
"Box size should not be greater than provided value") {
}
diff --git a/core/shared/src/main/scala/sigma/data/SigmaPropCodes.scala b/core/shared/src/main/scala/sigma/data/SigmaPropCodes.scala
new file mode 100644
index 0000000000..fafd24ffdd
--- /dev/null
+++ b/core/shared/src/main/scala/sigma/data/SigmaPropCodes.scala
@@ -0,0 +1,23 @@
+package sigma.data
+
+import sigma.ast.TypeCodes.LastConstantCode
+import supertagged.TaggedType
+
+/** Opcodes of sigma proposition nodes.
+ *
+ * @see SigmaBoolean.opCode
+ */
+object SigmaPropCodes {
+ object SPCode extends TaggedType[Byte]
+ type SPCode = SPCode.Type
+ private def newOpCode(shift: Short): SPCode = SPCode @@ (LastConstantCode + shift).toByte
+
+ val AndCode : SPCode = newOpCode(38)
+ val OrCode : SPCode = newOpCode(39)
+ val AtLeastCode : SPCode = newOpCode(40)
+ val ProveDlogCode : SPCode = newOpCode(93)
+ val ProveDiffieHellmanTupleCode: SPCode = newOpCode(94)
+ val TrivialPropFalseCode : SPCode = newOpCode(98)
+ val TrivialPropTrueCode : SPCode = newOpCode(99)
+}
+
diff --git a/core/shared/src/main/scala/sigma/data/WrapperOf.scala b/core/shared/src/main/scala/sigma/data/WrapperOf.scala
new file mode 100644
index 0000000000..7a6a98c217
--- /dev/null
+++ b/core/shared/src/main/scala/sigma/data/WrapperOf.scala
@@ -0,0 +1,7 @@
+package sigma.data
+
+/** Interface implmented by wrappers to provide access to the underlying wrapped value. */
+trait WrapperOf[T] {
+ /** The data value wrapped by this wrapper. */
+ def wrappedValue: T
+}
diff --git a/core/shared/src/main/scala/sigma/data/package.scala b/core/shared/src/main/scala/sigma/data/package.scala
index 8c34f7e9b9..c5a35f7b5f 100644
--- a/core/shared/src/main/scala/sigma/data/package.scala
+++ b/core/shared/src/main/scala/sigma/data/package.scala
@@ -1,5 +1,7 @@
package sigma
+import supertagged.TaggedType
+
import scala.annotation.nowarn
import scala.reflect.classTag
@@ -10,9 +12,11 @@ package object data {
*/
@nowarn private def rtypeToClassTag = ???
+ val StringClassTag = classTag[String]
val BigIntClassTag = classTag[BigInt]
val GroupElementClassTag = classTag[GroupElement]
val SigmaPropClassTag = classTag[SigmaProp]
+ val SigmaBooleanClassTag = classTag[SigmaBoolean]
val AvlTreeClassTag = classTag[AvlTree]
val BoxClassTag = classTag[Box]
val ContextClassTag = classTag[Context]
@@ -38,4 +42,19 @@ package object data {
*/
def emptyDBufferOfInt: debox.Buffer[Int] = debox.Buffer.unsafe(EmptyArrayOfInt)
+ /** Constructor of tuple value with more than 2 items.
+ * Such long tuples are represented as Coll[Any].
+ * This representaion of tuples is different from representation of pairs (x, y),
+ * where Tuple2 type is used instead of Coll. */
+ def TupleColl(items: Any*): Coll[Any] = Colls.fromItems(items: _*)(sigma.AnyType)
+
+ type KeyValueColl = Coll[(Coll[Byte], Coll[Byte])]
+
+ trait BaseDigestColl extends TaggedType[Coll[Byte]]
+
+ object Digest32Coll extends BaseDigestColl
+
+ type Digest32Coll = Digest32Coll.Type
+
+ implicit val Digest32CollRType: RType[data.Digest32Coll] = RType[Coll[Byte]].asInstanceOf[RType[data.Digest32Coll]]
}
diff --git a/core/shared/src/main/scala/sigma/package.scala b/core/shared/src/main/scala/sigma/package.scala
index f7f2321096..89b883f52d 100644
--- a/core/shared/src/main/scala/sigma/package.scala
+++ b/core/shared/src/main/scala/sigma/package.scala
@@ -23,11 +23,14 @@ package object sigma {
implicit val UnitType : RType[Unit] = PrimitiveType[Unit](ClassTag.Unit, Array[Unit]()(ClassTag.Unit))
- implicit val StringType : RType[String] = sigma.data.StringType()
+ implicit val StringType : RType[String] = GeneralType(StringClassTag)
- implicit val BigIntRType: RType[BigInt] = GeneralType(BigIntClassTag)
+ implicit val BigIntRType : RType[BigInt] = GeneralType(BigIntClassTag)
implicit val GroupElementRType: RType[GroupElement] = GeneralType(GroupElementClassTag)
- implicit val SigmaPropRType: RType[SigmaProp] = GeneralType(SigmaPropClassTag)
+ implicit val SigmaPropRType : RType[SigmaProp] = GeneralType(SigmaPropClassTag)
+ implicit val SigmaBooleanRType: RType[SigmaBoolean] = GeneralType(SigmaBooleanClassTag)
+
+
implicit val AvlTreeRType: RType[AvlTree] = GeneralType(AvlTreeClassTag)
implicit val BoxRType: RType[Box] = GeneralType(BoxClassTag)
diff --git a/core/shared/src/main/scala/sigma/reflection/ReflectionData.scala b/core/shared/src/main/scala/sigma/reflection/ReflectionData.scala
index cdab5d5be7..028e68bf72 100644
--- a/core/shared/src/main/scala/sigma/reflection/ReflectionData.scala
+++ b/core/shared/src/main/scala/sigma/reflection/ReflectionData.scala
@@ -1,6 +1,7 @@
package sigma.reflection
import sigma._
+import sigma.ast.{SCollectionType, SOption, STuple, SType}
import sigma.data.RType
import scala.collection.compat.immutable.ArraySeq
@@ -8,9 +9,15 @@ import scala.collection.mutable
import scala.collection.immutable
/** Reflection metadata and global dictionaries to access it.
- * For each class of this module that needs reflection metadata,
- * we register a class entry with the necessary information.
+ * Such metadata is only used on JS platform to support reflection-like interfaces of
+ * RClass, RMethod, RConstructor. These interfaces implemented on JVM using Java
+ * reflection.
+ *
+ * For each class that needs reflection metadata, we register a class entry using
+ * `registerClassEntry` method with the necessary information such as constructors and
+ * methods.
* Only information that is needed at runtime is registered.
+ * @see mkConstructor, mkMethod
*/
object ReflectionData {
/** Descriptors of classes. */
@@ -174,14 +181,6 @@ object ReflectionData {
mkMethod(clazz, "updateOperations", Array[Class[_]](classOf[Byte])) { (obj, args) =>
obj.asInstanceOf[AvlTree].updateOperations(args(0).asInstanceOf[Byte])
},
- mkMethod(clazz, "getMany", Array[Class[_]](classOf[Coll[_]], classOf[Coll[_]])) { (obj, args) =>
- obj.asInstanceOf[AvlTree].getMany(args(0).asInstanceOf[Coll[Coll[Byte]]],
- args(1).asInstanceOf[Coll[Byte]])
- },
- mkMethod(clazz, "update", Array[Class[_]](classOf[Coll[_]], classOf[Coll[_]])) { (obj, args) =>
- obj.asInstanceOf[AvlTree].update(args(0).asInstanceOf[Coll[(Coll[Byte], Coll[Byte])]],
- args(1).asInstanceOf[Coll[Byte]])
- },
mkMethod(clazz, "keyLength", Array[Class[_]]()) { (obj, _) =>
obj.asInstanceOf[AvlTree].keyLength
},
@@ -194,27 +193,12 @@ object ReflectionData {
mkMethod(clazz, "digest", Array[Class[_]]()) { (obj, _) =>
obj.asInstanceOf[AvlTree].digest
},
- mkMethod(clazz, "insert", Array[Class[_]](classOf[Coll[_]], classOf[Coll[_]])) { (obj, args) =>
- obj.asInstanceOf[AvlTree].insert(args(0).asInstanceOf[Coll[(Coll[Byte], Coll[Byte])]],
- args(1).asInstanceOf[Coll[Byte]])
- },
mkMethod(clazz, "isRemoveAllowed", Array[Class[_]]()) { (obj, _) =>
obj.asInstanceOf[AvlTree].isRemoveAllowed
},
mkMethod(clazz, "valueLengthOpt", Array[Class[_]]()) { (obj, _) =>
obj.asInstanceOf[AvlTree].valueLengthOpt
},
- mkMethod(clazz, "get", Array[Class[_]](classOf[Coll[_]], classOf[Coll[_]])) { (obj, args) =>
- obj.asInstanceOf[AvlTree].get(args(0).asInstanceOf[Coll[Byte]],
- args(1).asInstanceOf[Coll[Byte]])
- },
- mkMethod(clazz, "remove", Array[Class[_]](classOf[Coll[_]], classOf[Coll[_]])) { (obj, args) =>
- obj.asInstanceOf[AvlTree].remove(args(0).asInstanceOf[Coll[Coll[Byte]]], args(1).asInstanceOf[Coll[Byte]])
- },
- mkMethod(clazz, "contains", Array[Class[_]](classOf[Coll[_]], classOf[Coll[_]])) { (obj, args) =>
- obj.asInstanceOf[AvlTree].contains(args(0).asInstanceOf[Coll[Byte]],
- args(1).asInstanceOf[Coll[Byte]])
- },
mkMethod(clazz, "isUpdateAllowed", Array[Class[_]]()) { (obj, _) =>
obj.asInstanceOf[AvlTree].isUpdateAllowed
},
@@ -463,4 +447,28 @@ object ReflectionData {
)
)
}
+
+ registerClassEntry(classOf[SCollectionType[_]],
+ constructors = Array(
+ mkConstructor(Array(classOf[SType])) { args =>
+ new SCollectionType(args(0).asInstanceOf[SType])
+ }
+ )
+ )
+
+ registerClassEntry(classOf[SOption[_]],
+ constructors = Array(
+ mkConstructor(Array(classOf[SType])) { args =>
+ new SOption(args(0).asInstanceOf[SType])
+ }
+ )
+ )
+
+ registerClassEntry(classOf[STuple],
+ constructors = Array(
+ mkConstructor(Array(classOf[IndexedSeq[_]])) { args =>
+ new STuple(args(0).asInstanceOf[IndexedSeq[SType]])
+ }
+ )
+ )
}
diff --git a/interpreter/shared/src/main/scala/sigmastate/utils/SigmaByteReader.scala b/core/shared/src/main/scala/sigma/serialization/CoreByteReader.scala
similarity index 66%
rename from interpreter/shared/src/main/scala/sigmastate/utils/SigmaByteReader.scala
rename to core/shared/src/main/scala/sigma/serialization/CoreByteReader.scala
index 00f900c741..34ed74ac6a 100644
--- a/interpreter/shared/src/main/scala/sigmastate/utils/SigmaByteReader.scala
+++ b/core/shared/src/main/scala/sigma/serialization/CoreByteReader.scala
@@ -1,14 +1,9 @@
-package sigmastate.utils
+package sigma.serialization
-import org.ergoplatform.validation.ValidationRules.CheckPositionLimit
import scorex.util.Extensions._
import scorex.util.serialization.Reader
-import sigmastate.SType
-import sigmastate.Values.{SValue, Value}
-import sigmastate.serialization._
-import sigma.util.safeNewArray
-import debox.cfor
-import sigmastate.exceptions.DeserializeCallDepthExceeded
+import sigma.ast.SType
+import sigma.validation.ValidationRules.CheckPositionLimit
/** Reader used in the concrete implementations of [[SigmaSerializer]].
* It decorates the given reader, delegates most of the methods to it, but also adds new
@@ -16,16 +11,13 @@ import sigmastate.exceptions.DeserializeCallDepthExceeded
*
* @param r the underlying reader this reader reads from
* @param constantStore the store of constants which is used to resolve
- * [[sigmastate.Values.ConstantPlaceholder]]
+ * [[sigma.ast.ConstantPlaceholder]]
* @param resolvePlaceholdersToConstants if true then resolved constants will be
* substituted in the tree instead of the placeholder.
* @param maxTreeDepth limit on the tree depth (recursive invocations)
* of the deserializer
*/
-class SigmaByteReader(val r: Reader,
- var constantStore: ConstantStore,
- var resolvePlaceholdersToConstants: Boolean,
- val maxTreeDepth: Int = SigmaSerializer.MaxTreeDepth)
+class CoreByteReader(val r: Reader, val maxTreeDepth: Int = CoreSerializer.MaxTreeDepth)
extends Reader {
/** Checks that the current reader position is <= positionLimit.
@@ -34,17 +26,10 @@ class SigmaByteReader(val r: Reader,
* other than that both v4.x and v5.x will work and fail at the same time, so the
* change is consensus-safe.
*/
- @inline private def checkPositionLimit(): Unit = {
+ @inline protected def checkPositionLimit(): Unit = {
CheckPositionLimit(position, positionLimit)
}
- /** The reader should be lightweight to create. In most cases ErgoTrees don't have
- * ValDef nodes hence the store is not necessary and it's initialization dominates the
- * reader instantiation time. Hence it's lazy.
- * HOTSPOT:
- */
- lazy val valDefTypeStore: ValDefTypeStore = new ValDefTypeStore()
-
override type CH = r.CH
@inline
@@ -116,15 +101,6 @@ class SigmaByteReader(val r: Reader,
r.getBytes(bytesToRead)
}
- /** Returns all bytes of the underlying ByteBuffer. */
- private[sigmastate] def getAllBufferBytes: Array[Byte] = {
- val savedPos = position
- position = 0
- val res = getBytesUnsafe(remaining)
- position = savedPos
- res
- }
-
@inline override def getBits(size: Int): Array[Boolean] = {
checkPositionLimit()
r.getBits(size)
@@ -149,7 +125,6 @@ class SigmaByteReader(val r: Reader,
}
@inline def getType(): SType = TypeSerializer.deserialize(this)
- @inline def getValue(): SValue = ValueSerializer.deserialize(this)
private var lvl: Int = 0
@inline def level: Int = lvl
@@ -159,44 +134,24 @@ class SigmaByteReader(val r: Reader,
lvl = v
}
- /** Read sequence of values from this reader.
- * It first reads the number of values and then reads each value using `getValue` method.
- *
- * @return a sequence of zero of more values read
- */
- @inline def getValues(): IndexedSeq[SValue] = {
- val size = getUIntExact
- if (size == 0) Value.EmptySeq // quick short-cut when there is nothing to read
- else {
- val xs = safeNewArray[SValue](size)
- cfor(0)(_ < size, _ + 1) { i =>
- xs(i) = getValue()
- }
- xs
- }
- }
-
private var positionLmt: Int = r.position + r.remaining
@inline final def positionLimit: Int = positionLmt
@inline final def positionLimit_=(v: Int): Unit = {
positionLmt = v
}
- private var _complexity: Int = 0
- /** Helper property which is used to accumulate complexity during parsing. */
- @inline final def complexity: Int = _complexity
- @inline final def complexity_=(v: Int): Unit = {
- _complexity = v
- }
-
- @inline final def addComplexity(delta: Int): Unit = {
- _complexity += delta
- }
-
private var _wasDeserialize: Boolean = false
/** Helper property which is used to track deserialization operations during parsing. */
@inline final def wasDeserialize: Boolean = _wasDeserialize
@inline final def wasDeserialize_=(v: Boolean): Unit = {
_wasDeserialize = v
}
+
+ private var _wasUsingBlockchainContext: Boolean = false
+ /** Helper property which is used to track operations using the blockchain context during parsing. */
+ @inline final def wasUsingBlockchainContext: Boolean = _wasUsingBlockchainContext
+
+ @inline final def wasUsingBlockchainContext_=(v: Boolean): Unit = {
+ _wasUsingBlockchainContext = v
+ }
}
diff --git a/interpreter/shared/src/main/scala/sigmastate/utils/SigmaByteWriter.scala b/core/shared/src/main/scala/sigma/serialization/CoreByteWriter.scala
similarity index 77%
rename from interpreter/shared/src/main/scala/sigmastate/utils/SigmaByteWriter.scala
rename to core/shared/src/main/scala/sigma/serialization/CoreByteWriter.scala
index 4c3ef03610..aa4255449c 100644
--- a/interpreter/shared/src/main/scala/sigmastate/utils/SigmaByteWriter.scala
+++ b/core/shared/src/main/scala/sigma/serialization/CoreByteWriter.scala
@@ -1,15 +1,14 @@
-package sigmastate.utils
+package sigma.serialization
-import scorex.util.serialization.{VLQByteBufferWriter, Writer}
import scorex.util.serialization.Writer.Aux
-import sigmastate.{ArgInfo, SType}
-import sigmastate.Values.{Value, SValue}
-import sigmastate.serialization.{TypeSerializer, ValueSerializer, ConstantStore}
-
-class SigmaByteWriter(val w: Writer,
- val constantExtractionStore: Option[ConstantStore]) extends Writer {
- import SigmaByteWriter._
- import ValueSerializer._
+import scorex.util.serialization.{VLQByteBufferWriter, Writer}
+import sigma.ast.SType
+import sigma.serialization.CoreByteWriter.{Bits, DataInfo, U, Vlq, ZigZag}
+
+/** Implementation of [[Writer]] provided by `sigma-core` module.
+ * @param w destination [[Writer]] to which all the call got delegated.
+ */
+class CoreByteWriter(val w: Writer) extends Writer {
type CH = w.CH
@inline override def length(): Int = w.length()
@@ -22,7 +21,6 @@ class SigmaByteWriter(val w: Writer,
@inline def put(x: Byte): this.type = { w.put(x); this }
@inline def put(x: Byte, info: DataInfo[Byte]): this.type = {
- ValueSerializer.addArgInfo(info)
w.put(x); this
}
@@ -30,49 +28,41 @@ class SigmaByteWriter(val w: Writer,
super.putUByte(x)
}
def putUByte(x: Int, info: DataInfo[U[Byte]]): this.type = {
- ValueSerializer.addArgInfo(info)
super.putUByte(x)
}
@inline def putBoolean(x: Boolean): this.type = { w.putBoolean(x); this }
@inline def putBoolean(x: Boolean, info: DataInfo[Boolean]): this.type = {
- ValueSerializer.addArgInfo(info)
w.putBoolean(x); this
}
@inline def putShort(x: Short): this.type = { w.putShort(x); this }
@inline def putShort(x: Short, info: DataInfo[Short]): this.type = {
- ValueSerializer.addArgInfo(info)
w.putShort(x); this
}
@inline def putUShort(x: Int): this.type = { w.putUShort(x); this }
@inline def putUShort(x: Int, info: DataInfo[Vlq[U[Short]]]): this.type = {
- ValueSerializer.addArgInfo(info)
w.putUShort(x); this
}
@inline def putInt(x: Int): this.type = { w.putInt(x); this }
@inline def putInt(x: Int, info: DataInfo[Int]): this.type = {
- ValueSerializer.addArgInfo(info)
w.putInt(x); this
}
@inline def putUInt(x: Long): this.type = { w.putUInt(x); this }
@inline def putUInt(x: Long, info: DataInfo[Vlq[U[Int]]]): this.type = {
- ValueSerializer.addArgInfo(info)
w.putUInt(x); this
}
@inline def putLong(x: Long): this.type = { w.putLong(x); this }
@inline def putLong(x: Long, info: DataInfo[Vlq[ZigZag[Long]]]): this.type = {
- ValueSerializer.addArgInfo(info)
w.putLong(x); this
}
@inline def putULong(x: Long): this.type = { w.putULong(x); this }
@inline def putULong(x: Long, info: DataInfo[Vlq[U[Long]]]): this.type = {
- ValueSerializer.addArgInfo(info)
w.putULong(x); this
}
@@ -83,7 +73,6 @@ class SigmaByteWriter(val w: Writer,
}
@inline def putBytes(xs: Array[Byte]): this.type = { w.putBytes(xs); this }
@inline def putBytes(xs: Array[Byte], info: DataInfo[Array[Byte]]): this.type = {
- ValueSerializer.addArgInfo(info)
w.putBytes(xs); this
}
@@ -97,7 +86,6 @@ class SigmaByteWriter(val w: Writer,
@inline def putBits(xs: Array[Boolean]): this.type = { w.putBits(xs); this }
@inline def putBits(xs: Array[Boolean], info: DataInfo[Bits]): this.type = {
- ValueSerializer.addArgInfo(info)
w.putBits(xs);
this
}
@@ -118,30 +106,12 @@ class SigmaByteWriter(val w: Writer,
@inline def putType[T <: SType](x: T): this.type = { TypeSerializer.serialize(x, this); this }
@inline def putType[T <: SType](x: T, info: DataInfo[SType]): this.type = {
- ValueSerializer.addArgInfo(info)
TypeSerializer.serialize(x, this); this
}
- @inline def putValue[T <: SType](x: Value[T]): this.type = { ValueSerializer.serialize(x, this); this }
- @inline def putValue[T <: SType](x: Value[T], info: DataInfo[SValue]): this.type = {
- ValueSerializer.addArgInfo(info)
- ValueSerializer.serialize(x, this); this
- }
- @inline def putValues[T <: SType](xs: Seq[Value[T]]): this.type = {
- putUInt(xs.length)
- xs.foreach(putValue(_))
- this
- }
- @inline def putValues[T <: SType](xs: Seq[Value[T]], info: DataInfo[Seq[SValue]], itemInfo: DataInfo[SValue]): this.type = {
- putUInt(xs.length, valuesLengthInfo)
- foreach("\\#items", xs) { x =>
- putValue(x, itemInfo)
- }
- this
- }
}
-object SigmaByteWriter {
+object CoreByteWriter {
import scala.language.implicitConversions
/** Format descriptor type family. */
@@ -171,10 +141,6 @@ object SigmaByteWriter {
*/
trait Bits
- implicit case object ValueFmt extends FormatDescriptor[SValue] {
- override def size: String = "[1, *]"
- override def toString: String = "Expr"
- }
implicit case object TypeFmt extends FormatDescriptor[SType] {
override def size: String = "[1, *]"
override def toString: String = "Type"
@@ -253,21 +219,26 @@ object SigmaByteWriter {
implicit def toUVlqFmt[T](implicit fmt: FormatDescriptor[U[T]]): FormatDescriptor[Vlq[U[T]]] = UVlqFmt(fmt)
implicit def toZigZagVlqFmt[T](implicit fmt: FormatDescriptor[ZigZag[T]]): FormatDescriptor[Vlq[ZigZag[T]]] = ZigZagVlqFmt(fmt)
implicit def toSeqFmt[T](implicit fmt: FormatDescriptor[T]): FormatDescriptor[Seq[T]] = SeqFmt(fmt)
- case class DataInfo[T](info: ArgInfo, format: FormatDescriptor[T])
- def bitsInfo(name: String, desc: String = ""): DataInfo[Bits] = DataInfo(ArgInfo(name, desc), BitsFmt)
- def maxBitsInfo(name: String, maxBits: Int, desc: String = ""): DataInfo[Bits] = DataInfo(ArgInfo(name, desc), MaxBitsFmt(maxBits))
+ /** Meta information which can be attached to each argument of SMethod.
+ *
+ * @param name name of the argument
+ * @param description argument description. */
+ case class ArgInfo(name: String, description: String)
- val valuesLengthInfo: DataInfo[Vlq[U[Int]]] = ArgInfo("\\#items", "number of items in the collection")
+ case class DataInfo[T](info: ArgInfo, format: FormatDescriptor[T])
+
+ object DataInfo {
+ implicit def argnfoToDataInfo[T](arg: ArgInfo)(implicit fmt: FormatDescriptor[T]): DataInfo[T] = DataInfo(arg, fmt)
- def valuesItemInfo(info: DataInfo[Seq[SValue]]): DataInfo[SValue] = {
- val itemFmt = info.format.asInstanceOf[SeqFmt[SValue]].fmt
- DataInfo(ArgInfo(info.info.name+"_i", s"i-th item in the ${info.info.description}"), itemFmt)
+ // TODO refactor: remove this conversion and make it explicit
+ /** Helper conversion */
+ implicit def nameToDataInfo[T](name: String)
+ (implicit fmt: FormatDescriptor[T]): DataInfo[T] = ArgInfo(name, "")
}
- implicit def argInfoToDataInfo[T](arg: ArgInfo)(implicit fmt: FormatDescriptor[T]): DataInfo[T] = DataInfo(arg, fmt)
+ def bitsInfo(name: String, desc: String = ""): DataInfo[Bits] = DataInfo(ArgInfo(name, desc), BitsFmt)
+ def maxBitsInfo(name: String, maxBits: Int, desc: String = ""): DataInfo[Bits] = DataInfo(ArgInfo(name, desc), MaxBitsFmt(maxBits))
- // TODO refactor: remove this conversion and make it explicit
- /**Helper conversion */
- implicit def nameToDataInfo[T](name: String)(implicit fmt: FormatDescriptor[T]): DataInfo[T] = ArgInfo(name, "")
+ val valuesLengthInfo: DataInfo[Vlq[U[Int]]] = ArgInfo("\\#items", "number of items in the collection")
}
diff --git a/interpreter/shared/src/main/scala/sigmastate/serialization/DataSerializer.scala b/core/shared/src/main/scala/sigma/serialization/CoreDataSerializer.scala
similarity index 77%
rename from interpreter/shared/src/main/scala/sigmastate/serialization/DataSerializer.scala
rename to core/shared/src/main/scala/sigma/serialization/CoreDataSerializer.scala
index 65fb2cc0c7..479b199da5 100644
--- a/interpreter/shared/src/main/scala/sigmastate/serialization/DataSerializer.scala
+++ b/core/shared/src/main/scala/sigma/serialization/CoreDataSerializer.scala
@@ -1,28 +1,24 @@
-package sigmastate.serialization
+package sigma.serialization
+
+import debox.cfor
+import sigma.ast._
+import sigma.data._
+import sigma.util.Extensions.{CoreAvlTreeOps, BigIntOps, GroupElementOps, SigmaPropOps}
+import sigma.validation.ValidationRules.CheckSerializableTypeCode
+import sigma.{Evaluation, _}
import java.math.BigInteger
import java.nio.charset.StandardCharsets
-
-import org.ergoplatform.ErgoBox
-import org.ergoplatform.validation.ValidationRules.CheckSerializableTypeCode
-import sigma.data.RType
-import sigmastate.Values.SigmaBoolean
-import sigmastate.utils.{SigmaByteReader, SigmaByteWriter}
-import sigmastate._
-import sigmastate.eval.{Evaluation, _}
-import sigma._
-import debox.cfor
-import sigmastate.exceptions.SerializerException
import scala.collection.mutable
/** This works in tandem with ConstantSerializer, if you change one make sure to check the other.*/
-object DataSerializer {
+class CoreDataSerializer {
/** Use type descriptor `tpe` to deconstruct type structure and recursively serialize subcomponents.
* Primitive types are leaves of the type tree, and they are served as basis of recursion.
* The data value `v` is expected to conform to the type described by `tpe`.
*/
- def serialize[T <: SType](v: T#WrappedType, tpe: T, w: SigmaByteWriter): Unit = tpe match {
+ def serialize[T <: SType](v: T#WrappedType, tpe: T, w: CoreByteWriter): Unit = tpe match {
case SUnit => // don't need to save anything
case SBoolean => w.putBoolean(v.asInstanceOf[Boolean])
case SByte => w.put(v.asInstanceOf[Byte])
@@ -34,19 +30,16 @@ object DataSerializer {
w.putUInt(bytes.length)
w.putBytes(bytes)
case SBigInt =>
- val data = SigmaDsl.toBigInteger(v.asInstanceOf[BigInt]).toByteArray
+ val data = v.asInstanceOf[BigInt].toBigInteger.toByteArray
w.putUShort(data.length)
w.putBytes(data)
case SGroupElement =>
- GroupElementSerializer.serialize(groupElementToECPoint(v.asInstanceOf[GroupElement]), w)
+ GroupElementSerializer.serialize(v.asInstanceOf[GroupElement].toECPoint, w)
case SSigmaProp =>
val p = v.asInstanceOf[SigmaProp]
- SigmaBoolean.serializer.serialize(sigmaPropToSigmaBoolean(p), w)
- case SBox =>
- val b = v.asInstanceOf[Box]
- ErgoBox.sigmaSerializer.serialize(boxToErgoBox(b), w)
+ SigmaBoolean.serializer.serialize(p.toSigmaBoolean, w)
case SAvlTree =>
- AvlTreeData.serializer.serialize(avlTreeToAvlTreeData(v.asInstanceOf[AvlTree]), w)
+ AvlTreeData.serializer.serialize(v.asInstanceOf[AvlTree].toAvlTreeData, w)
case tColl: SCollectionType[a] =>
val coll = v.asInstanceOf[tColl.WrappedType]
w.putUShort(coll.length)
@@ -86,7 +79,7 @@ object DataSerializer {
* The data structure depth is limited by r.maxTreeDepth which is
* SigmaSerializer.MaxTreeDepth by default.
*/
- def deserialize[T <: SType](tpe: T, r: SigmaByteReader): T#WrappedType = {
+ def deserialize[T <: SType](tpe: T, r: CoreByteReader): T#WrappedType = {
val depth = r.level
r.level = depth + 1
val res = (tpe match {
@@ -109,15 +102,13 @@ object DataSerializer {
throw new SerializerException(s"BigInt value doesn't not fit into ${SBigInt.MaxSizeInBytes} bytes: $size")
}
val valueBytes = r.getBytes(size)
- SigmaDsl.BigInt(new BigInteger(valueBytes))
+ CBigInt(new BigInteger(valueBytes))
case SGroupElement =>
- SigmaDsl.GroupElement(GroupElementSerializer.parse(r))
+ CGroupElement(GroupElementSerializer.parse(r))
case SSigmaProp =>
- SigmaDsl.SigmaProp(SigmaBoolean.serializer.parse(r))
- case SBox =>
- SigmaDsl.Box(ErgoBox.sigmaSerializer.parse(r))
+ CSigmaProp(SigmaBoolean.serializer.parse(r))
case SAvlTree =>
- SigmaDsl.avlTree(AvlTreeData.serializer.parse(r))
+ CAvlTree(AvlTreeData.serializer.parse(r))
case tColl: SCollectionType[a] =>
val len = r.getUShort()
deserializeColl(len, tColl.elemType, r)
@@ -135,7 +126,7 @@ object DataSerializer {
res
}
- def deserializeColl[T <: SType](len: Int, tpeElem: T, r: SigmaByteReader): Coll[T#WrappedType] =
+ def deserializeColl[T <: SType](len: Int, tpeElem: T, r: CoreByteReader): Coll[T#WrappedType] =
tpeElem match {
case SBoolean =>
Colls.fromArray(r.getBits(len)).asInstanceOf[Coll[T#WrappedType]]
@@ -160,3 +151,5 @@ object DataSerializer {
Colls.fromArray(b.result())
}
}
+
+object CoreDataSerializer extends CoreDataSerializer
\ No newline at end of file
diff --git a/core/shared/src/main/scala/sigma/serialization/CoreSerializer.scala b/core/shared/src/main/scala/sigma/serialization/CoreSerializer.scala
new file mode 100644
index 0000000000..938d3f22c1
--- /dev/null
+++ b/core/shared/src/main/scala/sigma/serialization/CoreSerializer.scala
@@ -0,0 +1,74 @@
+package sigma.serialization
+
+import scorex.util.ByteArrayBuilder
+import scorex.util.serialization.{Serializer, VLQByteBufferReader, VLQByteBufferWriter}
+import sigma.data.SigmaConstants
+
+import java.nio.ByteBuffer
+
+/** Implementation of [[Serializer]] provided by `sigma-core` module. */
+abstract class CoreSerializer[TFamily, T <: TFamily] extends Serializer[TFamily, T, CoreByteReader, CoreByteWriter] {
+
+ def error(msg: String) = throw SerializerException(msg, None)
+
+ /** Serializes the given 'obj' to a new array of bytes using this serializer. */
+ final def toBytes(obj: T): Array[Byte] = {
+ val w = CoreSerializer.startWriter()
+ serialize(obj, w)
+ w.toBytes
+ }
+
+ /** Deserializes `bytes` to an object of this [[TFamily]] using this serializer.
+ * The actual class of the returned object is expected to be descendant of [[TFamily]].
+ */
+ final def fromBytes(bytes: Array[Byte]): TFamily = {
+ parse(CoreSerializer.startReader(bytes))
+ }
+}
+
+object CoreSerializer {
+ /** Max length of Box.propositionBytes collection */
+ val MaxPropositionSize: Int = SigmaConstants.MaxPropositionBytes.value
+
+ /** Max tree depth should not be greater then provided value */
+ val MaxTreeDepth: Int = SigmaConstants.MaxTreeDepth.value
+
+ /** Helper function to be use in serializers.
+ * Starting position is marked and then used to compute number of consumed bytes.
+ * val r = Serializer.startReader(bytes, pos)
+ * val obj = r.getValue()
+ * obj -> r.consumed
+ */
+ def startReader(bytes: Array[Byte],
+ pos: Int = 0): CoreByteReader = {
+ val buf = ByteBuffer.wrap(bytes)
+ buf.position(pos)
+ val r = new CoreByteReader(
+ new VLQByteBufferReader(buf),
+ maxTreeDepth = MaxTreeDepth
+ ).mark()
+ r
+ }
+
+ /** Helper function to be use in serializers. */
+ def startReader(bytes: Array[Byte]): CoreByteReader = {
+ val buf = ByteBuffer.wrap(bytes)
+ val r = new CoreByteReader(new VLQByteBufferReader(buf),
+ maxTreeDepth = MaxTreeDepth).mark()
+ r
+ }
+
+ /** Helper function to be use in serializers.
+ * val w = Serializer.startWriter()
+ * w.putLong(l)
+ * val res = w.toBytes
+ * res */
+ def startWriter(): CoreByteWriter = {
+ val b = new ByteArrayBuilder()
+ val wi = new VLQByteBufferWriter(b)
+ val w = new CoreByteWriter(wi)
+ w
+ }
+
+}
+
diff --git a/interpreter/shared/src/main/scala/sigmastate/serialization/GroupElementSerializer.scala b/core/shared/src/main/scala/sigma/serialization/GroupElementSerializer.scala
similarity index 65%
rename from interpreter/shared/src/main/scala/sigmastate/serialization/GroupElementSerializer.scala
rename to core/shared/src/main/scala/sigma/serialization/GroupElementSerializer.scala
index e54c41e426..4fd826ace1 100644
--- a/interpreter/shared/src/main/scala/sigmastate/serialization/GroupElementSerializer.scala
+++ b/core/shared/src/main/scala/sigma/serialization/GroupElementSerializer.scala
@@ -1,10 +1,7 @@
-package sigmastate.serialization
+package sigma.serialization
-import sigmastate.crypto.CryptoConstants
-import sigmastate.crypto.CryptoFacade
-import CryptoConstants.EcPointType
+import sigma.crypto.{CryptoContext, CryptoFacade, EcPointType}
import sigma.util.safeNewArray
-import sigmastate.utils.{SigmaByteReader, SigmaByteWriter}
/**
* A serializer which encodes group elements, so elliptic curve points in our case, to bytes, and decodes points
@@ -15,13 +12,12 @@ import sigmastate.utils.{SigmaByteReader, SigmaByteWriter}
* Special case is infinity point, which is encoded by 33 zeroes.
* Thus elliptic curve point is always encoded with 33 bytes.
*/
-object GroupElementSerializer extends SigmaSerializer[EcPointType, EcPointType] {
+object GroupElementSerializer extends CoreSerializer[EcPointType, EcPointType] {
- private val curve = CryptoConstants.dlogGroup
- private val encodingSize = 1 + CryptoConstants.groupSize
+ private val encodingSize = 1 + sigma.crypto.groupSize
private lazy val identityPointEncoding = Array.fill(encodingSize)(0: Byte)
- override def serialize(point: EcPointType, w: SigmaByteWriter): Unit = {
+ override def serialize(point: EcPointType, w: CoreByteWriter): Unit = {
val bytes = if (CryptoFacade.isInfinityPoint(point)) {
identityPointEncoding
} else {
@@ -36,15 +32,13 @@ object GroupElementSerializer extends SigmaSerializer[EcPointType, EcPointType]
w.putBytes(bytes)
}
- override def parse(r: SigmaByteReader): EcPointType = {
+ override def parse(r: CoreByteReader): EcPointType = {
val encoded = r.getBytes(encodingSize)
if (encoded(0) != 0) {
- curve.ctx.decodePoint(encoded)
+ CryptoContext.default.decodePoint(encoded)
} else {
- curve.identity
+ CryptoContext.default.infinity // identity point of multiplicative group
}
}
- def parse(bytes: Array[Byte]): EcPointType = parse(SigmaSerializer.startReader(bytes))
-
}
diff --git a/core/shared/src/main/scala/sigma/serialization/ProveDHTupleSerializer.scala b/core/shared/src/main/scala/sigma/serialization/ProveDHTupleSerializer.scala
new file mode 100644
index 0000000000..3211e90b76
--- /dev/null
+++ b/core/shared/src/main/scala/sigma/serialization/ProveDHTupleSerializer.scala
@@ -0,0 +1,25 @@
+package sigma.serialization
+
+import sigma.crypto.EcPointType
+import sigma.data.ProveDHTuple
+
+case class ProveDHTupleSerializer(
+ cons: (EcPointType, EcPointType, EcPointType, EcPointType) => ProveDHTuple
+ ) extends CoreSerializer[ProveDHTuple, ProveDHTuple] {
+
+ override def serialize(obj: ProveDHTuple, w: CoreByteWriter): Unit = {
+ GroupElementSerializer.serialize(obj.gv, w)
+ GroupElementSerializer.serialize(obj.hv, w)
+ GroupElementSerializer.serialize(obj.uv, w)
+ GroupElementSerializer.serialize(obj.vv, w)
+ }
+
+ override def parse(r: CoreByteReader) = {
+ val gv = GroupElementSerializer.parse(r)
+ val hv = GroupElementSerializer.parse(r)
+ val uv = GroupElementSerializer.parse(r)
+ val vv = GroupElementSerializer.parse(r)
+ cons(gv, hv, uv, vv)
+ }
+}
+
diff --git a/core/shared/src/main/scala/sigma/serialization/ProveDlogSerializer.scala b/core/shared/src/main/scala/sigma/serialization/ProveDlogSerializer.scala
new file mode 100644
index 0000000000..af849e8eed
--- /dev/null
+++ b/core/shared/src/main/scala/sigma/serialization/ProveDlogSerializer.scala
@@ -0,0 +1,20 @@
+package sigma.serialization
+
+import sigma.crypto.EcPointType
+import sigma.data.ProveDlog
+
+case class ProveDlogSerializer(cons: EcPointType => ProveDlog)
+ extends CoreSerializer[ProveDlog, ProveDlog] {
+
+ override def serialize(obj: ProveDlog, w: CoreByteWriter): Unit =
+ GroupElementSerializer.serialize(obj.value, w)
+
+ override def parse(r: CoreByteReader) = {
+ val res = GroupElementSerializer.parse(r)
+ cons(res)
+ }
+}
+
+
+
+
diff --git a/core/shared/src/main/scala/sigma/serialization/SerializerException.scala b/core/shared/src/main/scala/sigma/serialization/SerializerException.scala
new file mode 100644
index 0000000000..7373bf5ce1
--- /dev/null
+++ b/core/shared/src/main/scala/sigma/serialization/SerializerException.scala
@@ -0,0 +1,39 @@
+package sigma.serialization
+
+import sigma.SigmaException
+
+import scala.collection.compat.immutable.ArraySeq
+
+/** Exception thrown during serialization.
+ *
+ * @param message the error message
+ * @param cause an optional cause for the exception
+ */
+case class SerializerException(
+ override val message: String,
+ override val cause: Option[Throwable] = None,
+ override val args: Seq[Any] = ArraySeq.empty
+)
+ extends SigmaException(message, cause, args)
+
+/** Thrown by TypeSerializer when type prefix <= 0. */
+final class InvalidTypePrefix(message: String, cause: Option[Throwable] = None)
+ extends SerializerException(message, cause)
+
+/** Thrown when the current reader position > positionLimit which is set in the Reader.
+ * @see [[org.ergoplatform.validation.ValidationRules.CheckPositionLimit]]
+ */
+final class ReaderPositionLimitExceeded(
+ message: String,
+ val position: Int,
+ val positionLimit: Int,
+ cause: Option[Throwable] = None)
+ extends SerializerException(message, cause)
+
+/** Thrown when the current depth level > maxDepthLevel which is set in the Reader. */
+final class DeserializeCallDepthExceeded(message: String, cause: Option[Throwable] = None)
+ extends SerializerException(message, cause)
+
+/** Thrown by [[org.ergoplatform.validation.ValidationRules.CheckValidOpCode]] validation rule. */
+final class InvalidOpCode(message: String, cause: Option[Throwable] = None)
+ extends SerializerException(message, cause)
diff --git a/interpreter/shared/src/main/scala/sigmastate/serialization/TypeSerializer.scala b/core/shared/src/main/scala/sigma/serialization/TypeSerializer.scala
similarity index 90%
rename from interpreter/shared/src/main/scala/sigmastate/serialization/TypeSerializer.scala
rename to core/shared/src/main/scala/sigma/serialization/TypeSerializer.scala
index 4dc9335ff3..9c84de0944 100644
--- a/interpreter/shared/src/main/scala/sigmastate/serialization/TypeSerializer.scala
+++ b/core/shared/src/main/scala/sigma/serialization/TypeSerializer.scala
@@ -1,29 +1,24 @@
-package sigmastate.serialization
+package sigma.serialization
-import java.nio.charset.StandardCharsets
-import org.ergoplatform.validation.ValidationRules.{CheckPrimitiveTypeCode, CheckTypeCode}
-import sigmastate._
-import sigma.util.safeNewArray
-import sigmastate.utils.{SigmaByteReader, SigmaByteWriter}
import debox.cfor
-import sigmastate.exceptions.InvalidTypePrefix
-
-/** Serialization of types according to specification in TypeSerialization.md. */
-object TypeSerializer {
-
- import sigmastate.SCollectionType._
+import sigma.ast.SCollectionType.{CollectionTypeCode, NestedCollectionTypeCode}
+import sigma.ast._
+import sigma.serialization.{CoreByteReader, CoreByteWriter, InvalidTypePrefix}
+import sigma.util.safeNewArray
+import sigma.validation.ValidationRules.{CheckPrimitiveTypeCode, CheckTypeCode}
- /** The list of embeddable types, i.e. types that can be combined with type constructor for optimized encoding.
- * For each embeddable type `T`, and type constructor `C`, the type `C[T]` can be represented by single byte. */
- val embeddableIdToType = Array[SType](null, SBoolean, SByte, SShort, SInt, SLong, SBigInt, SGroupElement, SSigmaProp)
+import java.nio.charset.StandardCharsets
+/** Serialization of types according to specification in TypeSerialization.md. */
+class TypeSerializer {
+ import TypeSerializer._
def getEmbeddableType(code: Int): SType = {
CheckPrimitiveTypeCode(code.toByte)
embeddableIdToType(code)
}
- def serialize(tpe: SType, w: SigmaByteWriter): Unit = tpe match {
+ def serialize(tpe: SType, w: CoreByteWriter): Unit = tpe match {
case p: SEmbeddable => w.put(p.typeCode)
case SString => w.put(SString.typeCode)
case SAny => w.put(SAny.typeCode)
@@ -114,9 +109,9 @@ object TypeSerializer {
}
}
- def deserialize(r: SigmaByteReader): SType = deserialize(r, 0)
+ def deserialize(r: CoreByteReader): SType = deserialize(r, 0)
- private def deserialize(r: SigmaByteReader, depth: Int): SType = {
+ private def deserialize(r: CoreByteReader, depth: Int): SType = {
val c = r.getUByte()
if (c <= 0)
throw new InvalidTypePrefix(s"Cannot deserialize type prefix $c. Unexpected buffer $r with bytes ${r.getBytes(r.remaining)}")
@@ -202,13 +197,13 @@ object TypeSerializer {
tpe
}
- private def getArgType(r: SigmaByteReader, primId: Int, depth: Int) =
+ private def getArgType(r: CoreByteReader, primId: Int, depth: Int) =
if (primId == 0)
deserialize(r, depth + 1)
else
getEmbeddableType(primId)
- private def serializeTuple(t: STuple, w: SigmaByteWriter) = {
+ private def serializeTuple(t: STuple, w: CoreByteWriter) = {
assert(t.items.length <= 255)
w.put(STuple.TupleTypeCode)
w.putUByte(t.items.length)
@@ -217,3 +212,9 @@ object TypeSerializer {
}
}
+object TypeSerializer extends TypeSerializer {
+ /** The list of embeddable types, i.e. types that can be combined with type constructor for optimized encoding.
+ * For each embeddable type `T`, and type constructor `C`, the type `C[T]` can be represented by single byte. */
+ val embeddableIdToType = Array[SType](null, SBoolean, SByte, SShort, SInt, SLong, SBigInt, SGroupElement, SSigmaProp)
+
+}
\ No newline at end of file
diff --git a/core/shared/src/main/scala/sigma/util/CollectionUtil.scala b/core/shared/src/main/scala/sigma/util/CollectionUtil.scala
index d6bcd69767..ba506dec09 100644
--- a/core/shared/src/main/scala/sigma/util/CollectionUtil.scala
+++ b/core/shared/src/main/scala/sigma/util/CollectionUtil.scala
@@ -8,7 +8,7 @@ import scala.collection.compat._
object CollectionUtil {
/** @deprecated shouldn't be used other than for backwards compatibility with v3.x, v4.x. */
- def concatArrays[T](xs: Array[T], ys: Array[T]): Array[T] = {
+ def concatArrays_v4[T](xs: Array[T], ys: Array[T]): Array[T] = {
val len = xs.length + ys.length
val result = (xs match {
case _: Array[AnyRef] => new Array[AnyRef](len) // creates an array with invalid type descriptor (i.e. when T == Tuple2)
@@ -31,7 +31,7 @@ object CollectionUtil {
* This method takes ClassTag to create proper resulting array.
* Can be used in v5.0 and above.
*/
- def concatArrays_v5[T:ClassTag](arr1: Array[T], arr2: Array[T]): Array[T] = {
+ def concatArrays[T:ClassTag](arr1: Array[T], arr2: Array[T]): Array[T] = {
val l1 = arr1.length
val l2 = arr2.length
val length: Int = l1 + l2
@@ -41,6 +41,13 @@ object CollectionUtil {
result
}
+ /** Casts the array of `A`s into array of `B`s, where B is a superclass of A. */
+ def castArray[A, B >: A : ClassTag](array: Array[A]): Array[B] = {
+ val result: Array[B] = new Array[B](array.length)
+ System.arraycopy(array, 0, result, 0, array.length)
+ result
+ }
+
/** Computes the deep hash code for the given array.
*
* This method calculates the hash code based on the array's elements and type, taking nested arrays
diff --git a/core/shared/src/main/scala/sigma/util/Extensions.scala b/core/shared/src/main/scala/sigma/util/Extensions.scala
index 1d38173e1f..624b3f5d6b 100644
--- a/core/shared/src/main/scala/sigma/util/Extensions.scala
+++ b/core/shared/src/main/scala/sigma/util/Extensions.scala
@@ -1,5 +1,10 @@
package sigma.util
+import debox.{cfor, Buffer => DBuffer}
+import sigma.crypto.{CryptoFacade, Ecp}
+import sigma.data._
+import sigma.{AvlTree, GroupElement, SigmaProp}
+
import java.math.BigInteger
import java.nio.ByteBuffer
@@ -211,6 +216,14 @@ object Extensions {
else
throw new ArithmeticException("BigInteger out of 256 bit range");
}
+
+ /** Converts `x` to [[sigma.BigInt]] */
+ def toBigInt: sigma.BigInt = CBigInt(x)
+ }
+
+ implicit class BigIntOps(val x: sigma.BigInt) extends AnyVal {
+ /** Converts `x` to [[java.math.BigInteger]] */
+ def toBigInteger: BigInteger = x.asInstanceOf[CBigInt].wrappedValue
}
implicit class OptionOps[T](val opt: Option[T]) extends AnyVal {
@@ -269,4 +282,66 @@ object Extensions {
self
}
}
+
+ implicit class EcpOps(val source: Ecp) extends AnyVal {
+ /** Extracts [[sigma.GroupElement]] from the Ecp instance. */
+ def toGroupElement: GroupElement = CGroupElement(source)
+
+ /** Shortened String representation of `source` GroupElement. */
+ def showECPoint: String = {
+ if (source.toGroupElement.isIdentity) {
+ "IDENTITY"
+ }
+ else {
+ CryptoFacade.showPoint(source)
+ }
+ }
+ }
+
+ implicit class GroupElementOps(val source: GroupElement) extends AnyVal {
+ def toECPoint: Ecp = source.asInstanceOf[CGroupElement].wrappedValue
+ /** Shortened String representation of `source` GroupElement. */
+ def showToString: String = toECPoint.showECPoint
+ }
+
+ implicit class DBufferOps[A](val buf: DBuffer[A]) extends AnyVal {
+ /** Sum all values in `buf` using the given Numeric. */
+ def sumAll(implicit n: Numeric[A]): A = {
+ val limit = buf.length
+ var result: A = n.zero
+ cfor(0)(_ < limit, _ + 1) { i =>
+ result = n.plus(result, buf.elems(i))
+ }
+ result
+ }
+ }
+
+ implicit class SigmaBooleanOps(val sb: SigmaBoolean) extends AnyVal {
+ /** Wraps SigmaBoolean into SigmaProp. */
+ def toSigmaProp: SigmaProp = CSigmaProp(sb)
+
+ /** Human readable string representation of the proposition. */
+ def showToString: String = sb match {
+ case ProveDlog(v) =>
+ s"ProveDlog(${v.showECPoint})"
+ case ProveDHTuple(gv, hv, uv, vv) =>
+ s"ProveDHTuple(${gv.showECPoint}, ${hv.showECPoint}, ${uv.showECPoint}, ${vv.showECPoint})"
+ case _ => sb.toString
+ }
+ }
+
+ implicit class SigmaPropOps(val sb: SigmaProp) extends AnyVal {
+ /** Extracts [[sigma.SigmaBoolean]] from the SigmaProp instance. */
+ def toSigmaBoolean: SigmaBoolean = sb.asInstanceOf[CSigmaProp].wrappedValue
+ }
+
+ implicit class AvlTreeDataOps(val treeData: AvlTreeData) extends AnyVal {
+ /** Wrap [[sigma.AvlTreeData]] to [[sigma.AvlTree]]. */
+ def toAvlTree: AvlTree= CAvlTree(treeData)
+ }
+
+ implicit class CoreAvlTreeOps(val tree: AvlTree) extends AnyVal {
+ /** Extracts [[sigma.AvlTreeData]] from the AvlTree instance. */
+ def toAvlTreeData: AvlTreeData = tree.asInstanceOf[CAvlTree].wrappedValue
+ }
}
diff --git a/core/shared/src/main/scala/sigma/util/package.scala b/core/shared/src/main/scala/sigma/util/package.scala
index 87b3b6a805..a2a5a73472 100644
--- a/core/shared/src/main/scala/sigma/util/package.scala
+++ b/core/shared/src/main/scala/sigma/util/package.scala
@@ -25,6 +25,6 @@ package object util {
final def safeConcatArrays_v5[A](arr1: Array[A], arr2: Array[A])
(implicit tA: ClassTag[A]): Array[A] = {
checkLength[A](arr1.length + arr2.length)
- CollectionUtil.concatArrays_v5(arr1, arr2)
+ CollectionUtil.concatArrays(arr1, arr2)
}
}
diff --git a/interpreter/shared/src/main/scala/org/ergoplatform/validation/RuleStatus.scala b/core/shared/src/main/scala/sigma/validation/RuleStatus.scala
similarity index 97%
rename from interpreter/shared/src/main/scala/org/ergoplatform/validation/RuleStatus.scala
rename to core/shared/src/main/scala/sigma/validation/RuleStatus.scala
index 789016abfb..3d0451b240 100644
--- a/interpreter/shared/src/main/scala/org/ergoplatform/validation/RuleStatus.scala
+++ b/core/shared/src/main/scala/sigma/validation/RuleStatus.scala
@@ -1,6 +1,4 @@
-package org.ergoplatform.validation
-
-import java.util
+package sigma.validation
/** Base trait for rule status information. */
sealed trait RuleStatus {
diff --git a/interpreter/shared/src/main/scala/org/ergoplatform/validation/SigmaValidationSettings.scala b/core/shared/src/main/scala/sigma/validation/SigmaValidationSettings.scala
similarity index 99%
rename from interpreter/shared/src/main/scala/org/ergoplatform/validation/SigmaValidationSettings.scala
rename to core/shared/src/main/scala/sigma/validation/SigmaValidationSettings.scala
index e59575a272..51fb97c8ad 100644
--- a/interpreter/shared/src/main/scala/org/ergoplatform/validation/SigmaValidationSettings.scala
+++ b/core/shared/src/main/scala/sigma/validation/SigmaValidationSettings.scala
@@ -1,4 +1,4 @@
-package org.ergoplatform.validation
+package sigma.validation
/**
* Configuration of validation. Each `ValidationRule` instance should be
diff --git a/interpreter/shared/src/main/scala/org/ergoplatform/validation/SoftForkChecker.scala b/core/shared/src/main/scala/sigma/validation/SoftForkChecker.scala
similarity index 98%
rename from interpreter/shared/src/main/scala/org/ergoplatform/validation/SoftForkChecker.scala
rename to core/shared/src/main/scala/sigma/validation/SoftForkChecker.scala
index 3af05c6f6d..e26926ae9b 100644
--- a/interpreter/shared/src/main/scala/org/ergoplatform/validation/SoftForkChecker.scala
+++ b/core/shared/src/main/scala/sigma/validation/SoftForkChecker.scala
@@ -1,4 +1,4 @@
-package org.ergoplatform.validation
+package sigma.validation
/** Interface implemented by objects capable of checking soft-fork conditions. */
trait SoftForkChecker {
diff --git a/interpreter/shared/src/main/scala/org/ergoplatform/validation/ValidationRules.scala b/core/shared/src/main/scala/sigma/validation/ValidationRules.scala
similarity index 62%
rename from interpreter/shared/src/main/scala/org/ergoplatform/validation/ValidationRules.scala
rename to core/shared/src/main/scala/sigma/validation/ValidationRules.scala
index 442faed890..249e2fce0a 100644
--- a/interpreter/shared/src/main/scala/org/ergoplatform/validation/ValidationRules.scala
+++ b/core/shared/src/main/scala/sigma/validation/ValidationRules.scala
@@ -1,23 +1,23 @@
-package org.ergoplatform.validation
+package sigma.validation
+import sigma.SigmaException
+import sigma.ast.{SGlobal, SOption, TypeCodes}
+import sigma.serialization.{ReaderPositionLimitExceeded, SerializerException}
import sigma.util.Extensions.toUByte
-import sigmastate.Values.{ErgoTree, SValue}
-import sigmastate._
-import sigmastate.exceptions.{InterpreterException, InvalidOpCode, ReaderPositionLimitExceeded, SerializerException, SigmaException}
-import sigmastate.serialization.OpCodes.OpCode
-import sigmastate.serialization.TypeSerializer.embeddableIdToType
-import sigmastate.serialization.{OpCodes, ValueSerializer}
-import sigmastate.utxo.DeserializeContext
+import sigma.serialization.TypeSerializer.embeddableIdToType
/** Base class for different validation rules registered in ValidationRules.currentSettings.
* Each rule is identified by `id` and have a description.
* Validation logic is implemented by `apply` methods of derived classes.
*/
-case class ValidationRule(
+abstract case class ValidationRule(
id: Short,
description: String
) extends SoftForkChecker {
-
+ /** Validation settings defining the status of this rule.
+ * @see checkRule()
+ */
+ protected def settings: SigmaValidationSettings
/** Whether the status of this rule was checked on first invocation. */
private var _checked: Boolean = false
@@ -28,7 +28,7 @@ case class ValidationRule(
*/
@inline protected final def checkRule(): Unit = {
if (!_checked) {
- if (ValidationRules.currentSettings.getStatus(this.id).isEmpty) {
+ if (settings.getStatus(this.id).isEmpty) {
throw new SigmaException(s"ValidationRule $this not found in validation settings")
}
_checked = true // prevent this check on every call (only first call is checked)
@@ -77,76 +77,11 @@ object ValidationRules {
/** The id of the first validation rule. Can be used as the beginning of the rules id range. */
val FirstRuleId = 1000.toShort
- object CheckDeserializedScriptType extends ValidationRule(FirstRuleId,
- "Deserialized script should have expected type") {
- final def apply[T](d: DeserializeContext[_], script: SValue): Unit = {
- checkRule()
- if (d.tpe != script.tpe) {
- throwValidationException(
- new InterpreterException(s"Failed context deserialization of $d: \n" +
- s"expected deserialized script to have type ${d.tpe}; got ${script.tpe}"),
- Array[Any](d, script))
- }
- }
- }
-
- object CheckDeserializedScriptIsSigmaProp extends ValidationRule(1001,
- "Deserialized script should have SigmaProp type") {
- /** @param root candidate node before it is added as a root of ErgoTree */
- final def apply[T](root: SValue): Unit = {
- checkRule()
- if (!root.tpe.isSigmaProp) {
- throwValidationException(
- new SerializerException(s"Failed deserialization, expected deserialized script to have type SigmaProp; got ${root.tpe}"),
- Array[Any](root))
- }
- }
- }
-
- object CheckValidOpCode extends ValidationRule(1002,
- "Check the opcode is supported by registered serializer or is added via soft-fork")
- with SoftForkWhenCodeAdded {
- final def apply[T](ser: ValueSerializer[_], opCode: OpCode): Unit = {
- checkRule()
- if (ser == null || ser.opCode != opCode) {
- throwValidationException(
- new InvalidOpCode(s"Cannot find serializer for Value with opCode = LastConstantCode + ${toUByte(opCode) - OpCodes.LastConstantCode}"),
- Array(opCode))
- }
- }
- }
-
- /** Not used since v5.0.1. */
- object CheckIsSupportedIndexExpression extends ValidationRule(1003,
- "Check the index expression for accessing collection element is supported.")
-
- /** Not used since v5.0.3 */
- object CheckCostFunc extends ValidationRule(1004,
- "Cost function should contain only operations from specified list.")
-
- object CheckCalcFunc extends ValidationRule(1005,
- "If SigmaProp.isProven method calls exists in the given function,\n then it is the last operation")
-
- /** This rule is not use in v5.x, keep the commented code below as a precise
- * documentation of its semantics.
- */
- object CheckTupleType extends ValidationRule(1006,
- "Supported tuple type.") with SoftForkWhenReplaced {
-// final def apply[Ctx <: IRContext, T](ctx: Ctx)(e: ctx.Elem[_]): Unit = {
-// checkRule()
-// val condition = e match {
-// case _: ctx.PairElem[_,_] => true
-// case _ => false
-// }
-// if (!condition) {
-// throwValidationException(new SigmaException(s"Invalid tuple type $e"), Array[ctx.Elem[_]](e))
-// }
-// }
- }
-
object CheckPrimitiveTypeCode extends ValidationRule(1007,
"Check the primitive type code is supported or is added via soft-fork")
with SoftForkWhenCodeAdded {
+ override protected lazy val settings: SigmaValidationSettings = coreSettings
+
final def apply[T](code: Byte): Unit = {
checkRule()
val ucode = toUByte(code)
@@ -161,6 +96,8 @@ object ValidationRules {
object CheckTypeCode extends ValidationRule(1008,
"Check the non-primitive type code is supported or is added via soft-fork")
with SoftForkWhenCodeAdded {
+ override protected lazy val settings: SigmaValidationSettings = coreSettings
+
final def apply[T](typeCode: Byte): Unit = {
checkRule()
val ucode = toUByte(typeCode)
@@ -175,6 +112,7 @@ object ValidationRules {
object CheckSerializableTypeCode extends ValidationRule(1009,
"Check the data values of the type (given by type code) can be serialized")
with SoftForkWhenReplaced {
+ override protected lazy val settings: SigmaValidationSettings = coreSettings
/** Creates an exception which is used as a cause when throwing a ValidationException. */
def throwValidationException(typeCode: Byte): Nothing = {
@@ -186,7 +124,7 @@ object ValidationRules {
final def apply[T](typeCode: Byte): Unit = {
checkRule()
val ucode = toUByte(typeCode)
- if (typeCode == SOption.OptionTypeCode || ucode > toUByte(OpCodes.LastDataType)) {
+ if (typeCode == SOption.OptionTypeCode || ucode > toUByte(TypeCodes.LastDataType)) {
// the `typeCode == SOption.OptionTypeCode` condition is added in v5.0 and we
// throw ValidationException for Option type as well in order to be able to
// interpret it as soft-fork condition.
@@ -203,6 +141,8 @@ object ValidationRules {
object CheckTypeWithMethods extends ValidationRule(1010,
"Check the type (given by type code) supports methods")
with SoftForkWhenCodeAdded {
+ override protected lazy val settings: SigmaValidationSettings = coreSettings
+
final def apply[T](typeCode: Byte, cond: Boolean): Unit = {
checkRule()
val ucode = toUByte(typeCode)
@@ -214,53 +154,13 @@ object ValidationRules {
}
}
- object CheckAndGetMethod extends ValidationRule(1011,
- "Check the type has the declared method.") {
- final def apply[T](objType: STypeCompanion, methodId: Byte): SMethod = {
- checkRule()
- val methodOpt = objType.getMethodById(methodId)
- if (methodOpt.isDefined) methodOpt.get
- else {
- throwValidationException(
- new SerializerException(s"The method with code $methodId doesn't declared in the type $objType."),
- Array[Any](objType, methodId))
- }
- }
-
- override def isSoftFork(vs: SigmaValidationSettings,
- ruleId: Short,
- status: RuleStatus,
- args: Seq[Any]): Boolean = (status, args) match {
- case (ChangedRule(newValue), Seq(objType: STypeCompanion, methodId: Byte)) =>
- val key = Array(objType.typeId, methodId)
- newValue.grouped(2).exists(java.util.Arrays.equals(_, key))
- case _ => false
- }
- }
-
- object CheckHeaderSizeBit extends ValidationRule(1012,
- "For version greater then 0, size bit should be set.") with SoftForkWhenReplaced {
- final def apply(header: Byte): Unit = {
- checkRule()
- val version = ErgoTree.getVersion(header)
- if (version != 0 && !ErgoTree.hasSize(header)) {
- throwValidationException(
- new SigmaException(s"Invalid ErgoTreeHeader $header, size bit is expected for version $version"),
- Array(header))
- }
- }
- }
-
- /** Not used since v5.0.3 */
- object CheckCostFuncOperation extends ValidationRule(1013,
- "Check the opcode is allowed in cost function")
-
/** Introduced in v5.0, this rule it is used in creation of ValidationExceptions, which
* in turn can be checked for soft-fork condition using `this.isSoftFork`. Thus, this
* rule can be replaced with a new rule and the limit can be increased.
*/
object CheckPositionLimit extends ValidationRule(1014,
"Check that the Reader has not exceeded the position limit.") with SoftForkWhenReplaced {
+ override protected lazy val settings: SigmaValidationSettings = coreSettings
/** Wraps the given cause into [[ValidationException]] and throws it. */
def throwValidationException(cause: ReaderPositionLimitExceeded): Nothing = {
@@ -283,27 +183,12 @@ object ValidationRules {
}
}
- /** Not used since v5.0.1 */
- object CheckLoopLevelInCostFunction extends ValidationRule(1015,
- "Check that loop level is not exceeded.")
-
- val ruleSpecs: Seq[ValidationRule] = Seq(
- CheckDeserializedScriptType,
- CheckDeserializedScriptIsSigmaProp,
- CheckValidOpCode,
- CheckIsSupportedIndexExpression,
- CheckCostFunc,
- CheckCalcFunc,
- CheckTupleType,
+ private val ruleSpecs: Seq[ValidationRule] = Seq(
CheckPrimitiveTypeCode,
CheckTypeCode,
CheckSerializableTypeCode,
CheckTypeWithMethods,
- CheckAndGetMethod,
- CheckHeaderSizeBit,
- CheckCostFuncOperation,
- CheckPositionLimit,
- CheckLoopLevelInCostFunction
+ CheckPositionLimit
)
/** Validation settings that correspond to the current version of the ErgoScript implementation.
@@ -312,7 +197,7 @@ object ValidationRules {
* This is immutable data structure, it can be augmented with RuleStates from block extension
* sections of the blockchain, but that augmentation is only available in stateful context.
*/
- val currentSettings: SigmaValidationSettings = new MapSigmaValidationSettings({
+ val coreSettings: SigmaValidationSettings = new MapSigmaValidationSettings({
val map = ruleSpecs.map(r => r.id -> (r, EnabledRule)).toMap
assert(map.size == ruleSpecs.size, s"Duplicate ruleIds ${ruleSpecs.groupBy(_.id).filter(g => g._2.length > 1)}")
map
diff --git a/core/shared/src/test/scala/sigma/util/CollectionUtilTests.scala b/core/shared/src/test/scala/sigma/util/CollectionUtilTests.scala
index 24b03f9d88..f273568193 100644
--- a/core/shared/src/test/scala/sigma/util/CollectionUtilTests.scala
+++ b/core/shared/src/test/scala/sigma/util/CollectionUtilTests.scala
@@ -21,18 +21,18 @@ class CollectionUtilTests extends BaseTests {
test("concatArrays") {
val xs = Array[Byte](1,2,3)
val ys = Array[Byte](4,5,6)
- val zs = concatArrays(xs, ys)
+ val zs = concatArrays_v4(xs, ys)
assertResult(Array[Byte](1, 2, 3, 4, 5, 6))(zs)
val pairs = xs.zip(ys)
// this reproduces the problem which takes place in v3.x, v4.x (ErgoTree v0, v1)
- an[Throwable] should be thrownBy(concatArrays(pairs, pairs))
+ an[Throwable] should be thrownBy(concatArrays_v4(pairs, pairs))
// and this is the fix in v5.0
- concatArrays_v5(pairs, pairs) shouldBe Array((1, 4), (2, 5), (3, 6), (1, 4), (2, 5), (3, 6))
+ concatArrays(pairs, pairs) shouldBe Array((1, 4), (2, 5), (3, 6), (1, 4), (2, 5), (3, 6))
val xOpts = xs.map(Option(_))
- concatArrays_v5(xOpts, xOpts) shouldBe Array(Some(1), Some(2), Some(3), Some(1), Some(2), Some(3))
+ concatArrays(xOpts, xOpts) shouldBe Array(Some(1), Some(2), Some(3), Some(1), Some(2), Some(3))
}
def joinSeqs(l: Seq[Int], r: Seq[Int]) =
diff --git a/data/js/src/main/scala/org/ergoplatform/js/Address.scala b/data/js/src/main/scala/org/ergoplatform/js/Address.scala
new file mode 100644
index 0000000000..0978db5494
--- /dev/null
+++ b/data/js/src/main/scala/org/ergoplatform/js/Address.scala
@@ -0,0 +1,208 @@
+package org.ergoplatform.js
+
+import org.ergoplatform.ErgoAddressEncoder.NetworkPrefix
+import org.ergoplatform.ErgoAddressEncoder
+import scorex.util.encode.Base58
+import sigma.ast.js.ErgoTree
+import sigma.js.{GroupElement, SigmaProp}
+
+import scala.scalajs.js
+import scala.scalajs.js.annotation.JSExportTopLevel
+import scala.scalajs.js.{UndefOr, undefined}
+import scala.util.{Failure, Success}
+
+/** An exported JavaScript class wrapping the Scala `ErgoAddress` type. */
+@JSExportTopLevel("Address")
+abstract class Address extends js.Object {
+ def ergoAddress: org.ergoplatform.ErgoAddress
+
+ private lazy val _addressBytes: Array[Byte] = {
+ ErgoAddressEncoder(ergoAddress.networkPrefix).toBytes(ergoAddress)
+ }
+
+ /** Serialize this address to bytes.
+ * @see ErgoAddressEncoder.toBytes()
+ */
+ def addressBytes(): Array[Byte] = _addressBytes
+
+ /** Address type code used to differentiate between pay-to-public-key, pay-to-script,
+ * pay-to-script-hash addresses.
+ *
+ * @see [[P2PKAddress]], [[P2SAddress]], [[P2SHAddress]]
+ */
+ def addressTypePrefix(): Byte = ergoAddress.addressTypePrefix
+
+ /** First byte is used to encode network type and address type.
+ *
+ * @see ErgoAddressEncoder
+ */
+ private def headByte: Byte = _addressBytes(0)
+
+ /** @return true if this address from Ergo mainnet. */
+ def isMainnet(): Boolean = Address.isMainnet(headByte)
+
+ /** @return true if this address has Pay-To-Public-Key type. */
+ def isP2PK(): Boolean = ergoAddress.isInstanceOf[org.ergoplatform.P2PKAddress]
+
+ /** @return underlying {@link P2PKAddress}.
+ * @throws IllegalArgumentException if this instance is not P2PK address
+ */
+ def asP2PK(): P2PKAddress = {
+ require(isP2PK(), s"This instance $this is not P2PKAddress")
+ new P2PKAddress(ergoAddress.asInstanceOf[org.ergoplatform.P2PKAddress])
+ }
+
+ /** @return true if this address has Pay-To-Script type. */
+ def isP2S(): Boolean = ergoAddress.isInstanceOf[org.ergoplatform.Pay2SAddress]
+
+ /** @return underlying {@link P2SAddress}.
+ * @throws IllegalArgumentException if this instance is not P2S address
+ */
+ def asP2S(): P2SAddress = {
+ require(isP2S(), s"This instance $this is not P2SAddress")
+ new P2SAddress(ergoAddress.asInstanceOf[org.ergoplatform.Pay2SAddress])
+ }
+
+ /** @return true if this address has Pay-To-Script-Hash type. */
+ def isP2SH(): Boolean = ergoAddress.isInstanceOf[org.ergoplatform.Pay2SHAddress]
+
+ /** @return underlying {@link P2SHAddress}.
+ * @throws IllegalArgumentException if this instance is not P2SH address
+ */
+ def asP2SH(): P2SHAddress = {
+ require(isP2SH(), s"This instance $this is not P2SHAddress")
+ new P2SHAddress(ergoAddress.asInstanceOf[org.ergoplatform.Pay2SHAddress])
+ }
+
+ /** Extracts a [[sigma.js.SigmaProp]] from this address of the underlying ErgoTree if of
+ * specific form.
+ * @see ErgoTree.toSigmaBooleanOpt()
+ */
+ def toSigmaPropOpt(): UndefOr[sigma.js.SigmaProp] = {
+ ergoAddress.script.toSigmaBooleanOpt match {
+ case Some(sb) => new SigmaProp(sb)
+ case _ => undefined
+ }
+ }
+
+ /** ErgoTree which corresponds to the address (depending on the address type).
+ *
+ * @see [[P2PKAddress]], [[P2SAddress]], [[P2SHAddress]]
+ */
+ def toErgoTree(): ErgoTree = new ErgoTree(ergoAddress.script)
+
+ /** @return this addresses ErgoTree's proposition bytes. Use this to store this address
+ * on Box registers.
+ */
+ def toPropositionBytes(): Array[Byte] = ergoAddress.script.bytes
+
+ /** Converts the given [[Address]] to Base58 string. */
+ override def toString() = ergoAddress.toString
+}
+
+/** An exported JavaScript object providing utility methods for working with Address instances. */
+@JSExportTopLevel("Address$")
+object Address extends js.Object {
+ /** Creates JS wrapper over given [[ErgoAddress]]. */
+ def fromErgoAddress(ergoAddress: org.ergoplatform.ErgoAddress): Address = {
+ ergoAddress match {
+ case p2pk: org.ergoplatform.P2PKAddress =>
+ new P2PKAddress(p2pk)
+ case p2s: org.ergoplatform.Pay2SAddress =>
+ new P2SAddress(p2s)
+ case p2sh: org.ergoplatform.Pay2SHAddress =>
+ new P2SHAddress(p2sh)
+ }
+ }
+
+ /** @return true if this address from Ergo mainnet. */
+ private def isMainnet(headByte: Byte): Boolean = headByte < ErgoAddressEncoder.TestnetNetworkPrefix
+
+ private def getNetworkType(headByte: Byte): NetworkPrefix = {
+ if (isMainnet(headByte)) ErgoAddressEncoder.MainnetNetworkPrefix else ErgoAddressEncoder.TestnetNetworkPrefix
+ }
+
+ /** Deserializes an ErgoTree instance from an address string.
+ *
+ * @param base58String a Base58 string representing the serialized ErgoTree
+ */
+ def fromString(base58String: String): Address = {
+ Base58.decode(base58String) match {
+ case Success(bytes) =>
+ val headByte = bytes(0)
+ val encoder = ErgoAddressEncoder(getNetworkType(headByte))
+ encoder.fromBytes(bytes, base58String) match {
+ case Success(ergoAddress) =>
+ Address.fromErgoAddress(ergoAddress)
+ case Failure(t) =>
+ throw new RuntimeException(
+ "Invalid address encoding, expected base58 string: " + base58String, t)
+ }
+ case Failure(t) =>
+ throw new RuntimeException(
+ "Invalid address encoding, expected base58 string: " + base58String, t)
+ }
+ }
+
+ /** Creates an `Address` instance from an `ErgoTree` and a network prefix.
+ *
+ * @param ergoTree The `ErgoTree` instance to be converted into an `Address`.
+ * @param networkPrefix The network prefix indicating the network for which the address is valid.
+ * @return An `Address` instance corresponding to the given `ErgoTree` and network prefix.
+ */
+ def fromErgoTree(ergoTree: ErgoTree, networkPrefix: NetworkPrefix): Address = {
+ val encoder = ErgoAddressEncoder(networkPrefix)
+ val ergoAddress = encoder.fromProposition(ergoTree.tree).get
+ Address.fromErgoAddress(ergoAddress)
+ }
+
+ /**
+ * Creates an `Address` from a `SigmaProp` and a network prefix.
+ *
+ * @param sigmaProp The `SigmaProp` to be converted into an `Address`.
+ * @param networkPrefix The network prefix indicating the network for which the address is valid.
+ * @return An `Address` instance corresponding to the given `SigmaProp` and network prefix.
+ */
+ def fromSigmaProp(
+ sigmaProp: SigmaProp,
+ networkPrefix: NetworkPrefix): Address = {
+ val ergoTree = sigma.ast.ErgoTree.fromSigmaBoolean(sigmaProp.sigmaBoolean)
+ fromErgoTree(new ErgoTree(ergoTree), networkPrefix)
+ }
+
+ /** Creates address from given ergovalue containing an ErgoTree proposition bytes.
+ * Use this to convert a box register containing an ErgoTree into its address.
+ *
+ * @param networkPrefix mainnet or testnet network
+ * @param propositionBytes ErgoTree proposition bytes
+ */
+ def fromPropositionBytes(networkPrefix: NetworkPrefix, propositionBytes: Array[Byte]): Address = {
+ fromErgoTree(ErgoTree.fromBytes(propositionBytes), networkPrefix)
+ }
+
+}
+
+/** An exported JavaScript class wrapping the Scala `P2PKAddress` type. */
+@JSExportTopLevel("P2PKAddress")
+class P2PKAddress(
+ override val ergoAddress: org.ergoplatform.P2PKAddress
+) extends Address {
+
+ /** Converts this address to the underlying ProveDlog sigma proposition wrapped in SigmaProp. */
+ def toSigmaProp(): sigma.js.SigmaProp = new SigmaProp(ergoAddress.pubkey)
+
+ /** Extract the underlying [[sigma.js.GroupElement]] of this address. */
+ def getPublicKeyGE(): sigma.js.GroupElement = new GroupElement(ergoAddress.pubkey.value)
+}
+
+/** An exported JavaScript class wrapping the Scala `P2SAddress` type. */
+@JSExportTopLevel("P2SAddress")
+class P2SAddress(
+ override val ergoAddress: org.ergoplatform.Pay2SAddress
+) extends Address
+
+/** An exported JavaScript class wrapping the Scala `P2SHAddress` type. */
+@JSExportTopLevel("P2SHAddress")
+class P2SHAddress(
+ override val ergoAddress: org.ergoplatform.Pay2SHAddress
+) extends Address
diff --git a/interpreter/js/src/main/scala/sigmastate/Platform.scala b/data/js/src/main/scala/sigma/Platform.scala
similarity index 80%
rename from interpreter/js/src/main/scala/sigmastate/Platform.scala
rename to data/js/src/main/scala/sigma/Platform.scala
index bff11b53a8..29c761c3f1 100644
--- a/interpreter/js/src/main/scala/sigmastate/Platform.scala
+++ b/data/js/src/main/scala/sigma/Platform.scala
@@ -1,13 +1,8 @@
-package sigmastate
+package sigma
import org.ergoplatform.ErgoBox
-import sigma.data.Nullable
-import sigma.VersionContext
-import sigmastate.Values.{Constant, FalseLeaf, SigmaBoolean, TrueLeaf}
-import sigmastate.eval.{Evaluation, SigmaDsl}
-import sigmastate.lang.SigmaBuilder
-import sigma.Coll
-import sigma.{AnyValue, AvlTree, GroupElement, SigmaProp}
+import sigma.ast._
+import sigma.data._
import java.math.BigInteger
@@ -16,7 +11,7 @@ object Platform {
* Uses scalan.Nullable instead of scala.Option to avoid allocation on consensus hot path.
* This method is part of consensus and is used in [[SubstConstants]] operation.
*/
- private [sigmastate] def liftToConstant(obj: Any, builder: SigmaBuilder): Nullable[Constant[SType]] = {
+ private[sigma] def liftToConstant(obj: Any, builder: SigmaBuilder): Nullable[Constant[SType]] = {
import builder._
obj match {
case arr: Array[Boolean] => Nullable(mkCollectionConstant[SBoolean.type](arr, SBoolean))
@@ -24,14 +19,14 @@ object Platform {
case arr: Array[Short] => Nullable(mkCollectionConstant[SShort.type](arr, SShort))
case arr: Array[Int] => Nullable(mkCollectionConstant[SInt.type](arr, SInt))
case arr: Array[Long] => Nullable(mkCollectionConstant[SLong.type](arr, SLong))
- case arr: Array[BigInteger] => Nullable(mkCollectionConstant[SBigInt.type](arr.map(SigmaDsl.BigInt(_)), SBigInt))
+ case arr: Array[BigInteger] => Nullable(mkCollectionConstant[SBigInt.type](arr.map[BigInt](n => CBigInt(n)), SBigInt))
case arr: Array[String] => Nullable(mkCollectionConstant[SString.type](arr, SString))
case v: AnyValue =>
val tpe = Evaluation.rtypeToSType(v.tVal)
Nullable(mkConstant[tpe.type](v.value.asInstanceOf[tpe.WrappedType], tpe))
case v: Int => Nullable(mkConstant[SInt.type](v, SInt))
case v: Long => Nullable(mkConstant[SLong.type](v, SLong))
- case v: BigInteger => Nullable(mkConstant[SBigInt.type](SigmaDsl.BigInt(v), SBigInt))
+ case v: BigInteger => Nullable(mkConstant[SBigInt.type](CBigInt(v), SBigInt))
case n: sigma.BigInt => Nullable(mkConstant[SBigInt.type](n, SBigInt))
case ge: GroupElement => Nullable(mkConstant[SGroupElement.type](ge, SGroupElement))
case b: Boolean => Nullable(if (b) TrueLeaf else FalseLeaf)
@@ -43,7 +38,7 @@ object Platform {
// ErgoBox cannot be passed as argument as it is never valid value during evaluation.
// Thus we can use activation-based versioning and fix this code when v5.0 is activated.
case b: ErgoBox =>
- Nullable(mkConstant[SBox.type](SigmaDsl.Box(b), SBox)) // fixed in v5.0
+ Nullable(mkConstant[SBox.type](CBox(b), SBox)) // fixed in v5.0
// this case is added in v5.0 and it can be useful when the box value comes from a
// register or a context variable is passed to SubstConstants.
@@ -52,9 +47,9 @@ object Platform {
Nullable(mkConstant[SBox.type](b, SBox))
else
Nullable.None // return the same result as in v4.x when there was no this case
- case avl: AvlTreeData => Nullable(mkConstant[SAvlTree.type](SigmaDsl.avlTree(avl), SAvlTree))
+ case avl: AvlTreeData => Nullable(mkConstant[SAvlTree.type](CAvlTree(avl), SAvlTree))
case avl: AvlTree => Nullable(mkConstant[SAvlTree.type](avl, SAvlTree))
- case sb: SigmaBoolean => Nullable(mkConstant[SSigmaProp.type](SigmaDsl.SigmaProp(sb), SSigmaProp))
+ case sb: SigmaBoolean => Nullable(mkConstant[SSigmaProp.type](CSigmaProp(sb), SSigmaProp))
case p: SigmaProp => Nullable(mkConstant[SSigmaProp.type](p, SSigmaProp))
case coll: Coll[a] =>
val tpeItem = Evaluation.rtypeToSType(coll.tItem)
diff --git a/sdk/js/src/main/scala/org/ergoplatform/sdk/js/ErgoTree.scala b/data/js/src/main/scala/sigma/ast/js/ErgoTree.scala
similarity index 70%
rename from sdk/js/src/main/scala/org/ergoplatform/sdk/js/ErgoTree.scala
rename to data/js/src/main/scala/sigma/ast/js/ErgoTree.scala
index 8469545d95..73b8fbfb00 100644
--- a/sdk/js/src/main/scala/org/ergoplatform/sdk/js/ErgoTree.scala
+++ b/data/js/src/main/scala/sigma/ast/js/ErgoTree.scala
@@ -1,21 +1,28 @@
-package org.ergoplatform.sdk.js
+package sigma.ast.js
-import sigmastate.Values
+import sigma.ast
+import sigma.js.Value
import scala.scalajs.js
import scala.scalajs.js.JSConverters.JSRichIterableOnce
import scala.scalajs.js.annotation.JSExportTopLevel
-/** An exported JavaScript class wrapping the Scala `Values.ErgoTree` type. */
+/** An exported JavaScript class wrapping the Scala `ErgoTree` type. */
@JSExportTopLevel("ErgoTree")
-class ErgoTree(tree: Values.ErgoTree) extends js.Object {
+class ErgoTree(val tree: ast.ErgoTree) extends js.Object {
+ /** Root of the contract which is a valid expression of `SigmaProp` type. */
+ val root: Expr = new Expr(tree.root.toOption.get)
+
/** The first byte of serialized byte array which determines interpretation of the rest of the array. */
def header(): Byte = tree.header
+ /** Version of this tree (== BlockVersion - 1). */
def version(): Byte = tree.version
+ /** @return true, if constant segregation bit is set in the header. */
def isConstantSegregation(): Boolean = tree.isConstantSegregation
+ /** @return true, if size bit is set in the header. */
def hasSize(): Boolean = tree.hasSize
/** Serializes the ErgoTree instance to an array of bytes. */
@@ -35,13 +42,13 @@ class ErgoTree(tree: Values.ErgoTree) extends js.Object {
/** Returns segregated constants of this tree as [[js.Array]]. */
def constants(): js.Array[Value] = {
val constants = tree.constants
- val values = constants.map(Isos.isoValueToConstant.from)
+ val values = constants.map(isoValueToConstant.from)
values.toJSArray
}
}
/** An exported JavaScript object providing utility methods for working with ErgoTree instances. */
-@JSExportTopLevel("ErgoTreeObj")
+@JSExportTopLevel("ErgoTree$")
object ErgoTree extends js.Object {
/** Deserializes an ErgoTree instance from a hexadecimal string.
@@ -49,13 +56,13 @@ object ErgoTree extends js.Object {
* @param hex a hexadecimal string representing the serialized ErgoTree
*/
def fromHex(hex: String): ErgoTree =
- new ErgoTree(Values.ErgoTree.fromHex(hex))
+ new ErgoTree(ast.ErgoTree.fromHex(hex))
/** Deserializes an ErgoTree instance from an array of bytes.
*
* @param bytes an array of bytes representing the serialized ErgoTree
*/
def fromBytes(bytes: Array[Byte]): ErgoTree = {
- new ErgoTree(Values.ErgoTree.fromBytes(bytes))
+ new ErgoTree(ast.ErgoTree.fromBytes(bytes))
}
}
diff --git a/data/js/src/main/scala/sigma/ast/js/Expr.scala b/data/js/src/main/scala/sigma/ast/js/Expr.scala
new file mode 100644
index 0000000000..54a78f4025
--- /dev/null
+++ b/data/js/src/main/scala/sigma/ast/js/Expr.scala
@@ -0,0 +1,30 @@
+package sigma.ast.js
+
+import sigma.ast.syntax.SValue
+import sigma.js.JsWrapper
+import sigma.serialization.ValueSerializer
+
+import scala.scalajs.js
+import scala.scalajs.js.annotation.JSExportTopLevel
+import scala.scalajs.js.typedarray.Int8Array
+
+/** Represents a node of ErgoTree.
+ * An exported JavaScript class wrapping the Scala [[sigma.ast.Value]].
+ */
+@JSExportTopLevel("Expr")
+class Expr(override val wrappedValue: SValue) extends JsWrapper[SValue]{
+ /** Serialize this expression using sigma serializer [[ValueSerializer]]. */
+ def toBytes: Int8Array = {
+ val bytes = ValueSerializer.serialize(wrappedValue)
+ Int8Array.of(bytes:_*)
+ }
+}
+
+@JSExportTopLevel("Expr$")
+object Expr extends js.Object {
+ /** Deserialize an expression from bytes using sigma serializer [[ValueSerializer]]. */
+ def fromBytes(bytes: Int8Array): Expr = {
+ val value = ValueSerializer.deserialize(bytes.toArray)
+ new Expr(value)
+ }
+}
diff --git a/data/js/src/main/scala/sigma/ast/js/package.scala b/data/js/src/main/scala/sigma/ast/js/package.scala
new file mode 100644
index 0000000000..7af2a48ab0
--- /dev/null
+++ b/data/js/src/main/scala/sigma/ast/js/package.scala
@@ -0,0 +1,19 @@
+package sigma.ast
+
+import sigma.Evaluation
+import sigma.data.Iso
+import sigma.js.{Type, Value}
+
+package object js {
+ /** Conversion between `Value` and `Constant[SType]`. */
+ implicit val isoValueToConstant: Iso[Value, Constant[SType]] = new Iso[Value, Constant[SType]] {
+ override def to(x: Value): Constant[SType] =
+ Constant(x.runtimeData.asInstanceOf[SType#WrappedType], Evaluation.rtypeToSType(x.tpe.rtype))
+
+ override def from(x: Constant[SType]): Value = {
+ val rtype = Evaluation.stypeToRType(x.tpe)
+ val jsvalue = Value.fromRuntimeData(x.value, rtype)
+ new Value(jsvalue, new Type(rtype))
+ }
+ }
+}
diff --git a/interpreter/jvm/src/main/scala/sigmastate/Platform.scala b/data/jvm/src/main/scala/sigma/Platform.scala
similarity index 89%
rename from interpreter/jvm/src/main/scala/sigmastate/Platform.scala
rename to data/jvm/src/main/scala/sigma/Platform.scala
index fa44f9a16f..bd39d75ab9 100644
--- a/interpreter/jvm/src/main/scala/sigmastate/Platform.scala
+++ b/data/jvm/src/main/scala/sigma/Platform.scala
@@ -1,13 +1,9 @@
-package sigmastate
+package sigma
import org.ergoplatform.ErgoBox
-import sigma.data.Nullable
-import sigma.VersionContext
-import sigmastate.Values.{Constant, FalseLeaf, SigmaBoolean, TrueLeaf}
-import sigmastate.eval.{Evaluation, SigmaDsl}
-import sigmastate.lang.SigmaBuilder
-import sigma.Coll
-import sigma.{AvlTree, GroupElement, SigmaProp}
+import sigma.ast._
+import sigma.data.{AvlTreeData, Nullable, SigmaBoolean}
+import sigma.eval.SigmaDsl
import java.math.BigInteger
@@ -17,7 +13,7 @@ object Platform {
* Uses scalan.Nullable instead of scala.Option to avoid allocation on consensus hot path.
* This method is part of consensus and is used in [[SubstConstants]] operation.
*/
- private [sigmastate] def liftToConstant(obj: Any, builder: SigmaBuilder): Nullable[Constant[SType]] = {
+ private[sigma] def liftToConstant(obj: Any, builder: SigmaBuilder): Nullable[Constant[SType]] = {
import builder._
obj match {
case arr: Array[Boolean] => Nullable(mkCollectionConstant[SBoolean.type](arr, SBoolean))
diff --git a/interpreter/shared/src/main/scala/org/ergoplatform/ErgoAddress.scala b/data/shared/src/main/scala/org/ergoplatform/ErgoAddress.scala
similarity index 92%
rename from interpreter/shared/src/main/scala/org/ergoplatform/ErgoAddress.scala
rename to data/shared/src/main/scala/org/ergoplatform/ErgoAddress.scala
index 5813ff99e7..59eb8df5c5 100644
--- a/interpreter/shared/src/main/scala/org/ergoplatform/ErgoAddress.scala
+++ b/data/shared/src/main/scala/org/ergoplatform/ErgoAddress.scala
@@ -1,16 +1,18 @@
package org.ergoplatform
-import scorex.utils.Ints
import org.ergoplatform.ErgoAddressEncoder.NetworkPrefix
import scorex.crypto.hash.{Blake2b256, Digest32}
import scorex.util.encode.Base58
-import sigmastate.Values._
-import sigmastate._
-import sigmastate.crypto.DLogProtocol.{ProveDlog, ProveDlogProp}
-import sigmastate.exceptions.SigmaException
-import sigmastate.serialization._
-import sigmastate.utxo.{DeserializeContext, Slice}
-import sigma.Coll
+import scorex.utils.Ints
+import sigma.ast.{DeserializeContext, SInt, SSigmaProp, Slice}
+import sigma.data.{CSigmaProp, ProveDlog}
+import sigma.serialization.GroupElementSerializer
+import sigma.{Coll, SigmaException, VersionContext}
+import sigma.ast.ErgoTree.{ZeroHeader, setVersionBits}
+import sigma.ast._
+import sigma.ast.syntax._
+import sigma.serialization._
+import sigma.util.CollectionUtil
import scala.util.Try
@@ -163,7 +165,7 @@ class Pay2SHAddress(val scriptHash: Array[Byte])(implicit val encoder: ErgoAddre
ByteArrayConstant(scriptHash)
)
val scriptIsCorrect = DeserializeContext(scriptId, SSigmaProp)
- ErgoTree.withoutSegregation(SigmaAnd(hashEquals.toSigmaProp, scriptIsCorrect))
+ ErgoTree.withoutSegregation(ZeroHeader, SigmaAnd(hashEquals.toSigmaProp, scriptIsCorrect))
}
override def equals(obj: Any): Boolean = obj match {
@@ -265,12 +267,17 @@ case class ErgoAddressEncoder(networkPrefix: NetworkPrefix) {
/** This value is be used implicitly in the methods below. */
implicit private def ergoAddressEncoder: ErgoAddressEncoder = this
+ /** Converts the given [[ErgoAddress]] to array of bytes. */
+ def toBytes(address: ErgoAddress): Array[Byte] = {
+ val prefixByte = (networkPrefix + address.addressTypePrefix).toByte
+ val withNetworkByte = prefixByte +: address.contentBytes
+ val checksum = hash256(withNetworkByte).take(ChecksumLength)
+ CollectionUtil.concatArrays(withNetworkByte,checksum)
+ }
+
/** Converts the given [[ErgoAddress]] to Base58 string. */
def toString(address: ErgoAddress): String = {
- val withNetworkByte = (networkPrefix + address.addressTypePrefix).toByte +: address.contentBytes
-
- val checksum = hash256(withNetworkByte).take(ChecksumLength)
- Base58.encode(withNetworkByte ++ checksum)
+ Base58.encode(toBytes(address))
}
/** Returns true if the given `addrHeadByte` is a header byte of a testnet address, false otherwise. */
@@ -281,6 +288,11 @@ case class ErgoAddressEncoder(networkPrefix: NetworkPrefix) {
/** Converts the given Base58 string to [[ErgoAddress]] or an error packed in Try. */
def fromString(addrBase58Str: String): Try[ErgoAddress] = Base58.decode(addrBase58Str).flatMap { bytes =>
+ fromBytes(bytes, addrBase58Str)
+ }
+
+ /** Converts the given Base58 string to [[ErgoAddress]] or an error packed in Try. */
+ private [ergoplatform] def fromBytes(bytes: Array[Byte], addrBase58Str: String): Try[ErgoAddress] = {
Try {
val headByte = bytes.head
networkPrefix match {
@@ -338,7 +350,7 @@ case class ErgoAddressEncoder(networkPrefix: NetworkPrefix) {
*/
def fromProposition(proposition: ErgoTree): Try[ErgoAddress] = Try {
proposition.root match {
- case Right(SigmaPropConstant(ProveDlogProp(d))) => P2PKAddress(d)
+ case Right(SigmaPropConstant(CSigmaProp(d: ProveDlog))) => P2PKAddress(d)
case Right(IsPay2SHAddress(scriptHash)) => new Pay2SHAddress(scriptHash.toArray)
case Right(b: Value[SSigmaProp.type]@unchecked) if b.tpe == SSigmaProp => Pay2SAddress(proposition)
case Left(unparsedErgoTree) =>
diff --git a/interpreter/shared/src/main/scala/org/ergoplatform/ErgoBox.scala b/data/shared/src/main/scala/org/ergoplatform/ErgoBox.scala
similarity index 90%
rename from interpreter/shared/src/main/scala/org/ergoplatform/ErgoBox.scala
rename to data/shared/src/main/scala/org/ergoplatform/ErgoBox.scala
index 670d51d123..4c240267c4 100644
--- a/interpreter/shared/src/main/scala/org/ergoplatform/ErgoBox.scala
+++ b/data/shared/src/main/scala/org/ergoplatform/ErgoBox.scala
@@ -1,21 +1,19 @@
package org.ergoplatform
import org.ergoplatform.ErgoBox.{AdditionalRegisters, Token}
-import org.ergoplatform.settings.ErgoAlgos
import scorex.crypto.authds.ADKey
import scorex.crypto.hash.Blake2b256
import scorex.util._
+import scorex.util.encode.Base16
import scorex.utils.{Ints, Shorts}
-import sigmastate.SCollection.SByteArray
-import sigmastate.SType.AnyOps
-import sigmastate.Values._
-import sigmastate._
-import sigmastate.eval.Extensions._
-import sigmastate.eval._
-import sigmastate.serialization.SigmaSerializer
-import sigmastate.utils.{Helpers, SigmaByteReader, SigmaByteWriter}
-import sigmastate.utxo.ExtractCreationInfo
-import sigma.{Colls, _}
+import sigma.Extensions.ArrayOps
+import sigma.ast.SCollection.SByteArray
+import sigma.ast.SType.AnyOps
+import sigma.data.{Digest32Coll, SigmaConstants}
+import sigma.ast._
+import sigma.serialization.{SigmaByteReader, SigmaByteWriter, SigmaSerializer}
+import sigma._
+import sigma.util.CollectionUtil
/**
* Box (aka coin, or an unspent output) is a basic concept of a UTXO-based cryptocurrency. In Bitcoin, such an object
@@ -77,7 +75,7 @@ class ErgoBox private (
override def get(identifier: RegisterId): Option[Value[SType]] = {
identifier match {
case ReferenceRegId =>
- val tupleVal = (creationHeight, Helpers.concatArrays(transactionId.toBytes, Shorts.toByteArray(index)).toColl)
+ val tupleVal = (creationHeight, CollectionUtil.concatArrays(transactionId.toBytes, Shorts.toByteArray(index)).toColl)
Some(Constant(tupleVal.asWrappedType, SReferenceRegType))
case _ => super.get(identifier)
}
@@ -106,8 +104,8 @@ class ErgoBox private (
def toCandidate: ErgoBoxCandidate =
new ErgoBoxCandidate(value, ergoTree, creationHeight, additionalTokens, additionalRegisters)
- override def toString: String = s"ErgoBox(${ErgoAlgos.encode(id)},$value,$ergoTree," +
- s"tokens: (${additionalTokens.map(t => ErgoAlgos.encode(t._1) + ":" + t._2)}), $transactionId, " +
+ override def toString: String = s"ErgoBox(${Base16.encode(id)},$value,$ergoTree," +
+ s"tokens: (${additionalTokens.map(t => Base16.encode(t._1.toArray) + ":" + t._2)}), $transactionId, " +
s"$index, $additionalRegisters, $creationHeight)"
}
@@ -184,9 +182,9 @@ object ErgoBox {
.ensuring(_ == mandatoryRegisters.last.number + 1)
val allRegisters: Seq[RegisterId] =
- Helpers.concatArrays[RegisterId](
- Helpers.castArray(_mandatoryRegisters): Array[RegisterId],
- Helpers.castArray(_nonMandatoryRegisters): Array[RegisterId]).ensuring(_.length == maxRegisters)
+ CollectionUtil.concatArrays[RegisterId](
+ CollectionUtil.castArray(_mandatoryRegisters): Array[RegisterId],
+ CollectionUtil.castArray(_nonMandatoryRegisters): Array[RegisterId]).ensuring(_.length == maxRegisters)
val mandatoryRegistersCount: Byte = mandatoryRegisters.size.toByte
val nonMandatoryRegistersCount: Byte = nonMandatoryRegisters.size.toByte
diff --git a/interpreter/shared/src/main/scala/org/ergoplatform/ErgoBoxAssets.scala b/data/shared/src/main/scala/org/ergoplatform/ErgoBoxAssets.scala
similarity index 100%
rename from interpreter/shared/src/main/scala/org/ergoplatform/ErgoBoxAssets.scala
rename to data/shared/src/main/scala/org/ergoplatform/ErgoBoxAssets.scala
diff --git a/interpreter/shared/src/main/scala/org/ergoplatform/ErgoBoxCandidate.scala b/data/shared/src/main/scala/org/ergoplatform/ErgoBoxCandidate.scala
similarity index 94%
rename from interpreter/shared/src/main/scala/org/ergoplatform/ErgoBoxCandidate.scala
rename to data/shared/src/main/scala/org/ergoplatform/ErgoBoxCandidate.scala
index a167b95143..ba306159d4 100644
--- a/interpreter/shared/src/main/scala/org/ergoplatform/ErgoBoxCandidate.scala
+++ b/data/shared/src/main/scala/org/ergoplatform/ErgoBoxCandidate.scala
@@ -2,19 +2,18 @@ package org.ergoplatform
import debox.cfor
import org.ergoplatform.ErgoBox._
-import org.ergoplatform.settings.ErgoAlgos
+import scorex.util.encode.Base16
import scorex.util.{ModifierId, bytesToId}
-import sigma.Extensions.CollOps
+import sigma.Extensions.{ArrayOps, CollOps}
+import sigma.ast.{ErgoTree, SType}
+import sigma.ast.SType.AnyOps
+import sigma.data.Digest32Coll
import sigma.util.safeNewArray
import sigma.{Coll, Colls}
-import sigmastate.SType.AnyOps
-import sigmastate.Values._
-import sigmastate._
-import sigmastate.eval.Extensions._
-import sigmastate.eval._
-import sigmastate.serialization.ErgoTreeSerializer.DefaultSerializer
-import sigmastate.serialization.SigmaSerializer
-import sigmastate.utils.{SigmaByteReader, SigmaByteWriter}
+import sigma.ast._
+import sigma.ast.syntax._
+import sigma.serialization.ErgoTreeSerializer.DefaultSerializer
+import sigma.serialization.{SigmaByteReader, SigmaByteWriter, SigmaSerializer}
import scala.collection.{immutable, mutable}
import scala.runtime.ScalaRunTime
@@ -97,7 +96,7 @@ class ErgoBoxCandidate(val value: Long,
}
override def toString: String = s"ErgoBoxCandidate($value, $ergoTree," +
- s"tokens: (${additionalTokens.map(t => ErgoAlgos.encode(t._1) + ":" + t._2).toArray.mkString(", ")}), " +
+ s"tokens: (${additionalTokens.map(t => Base16.encode(t._1.toArray) + ":" + t._2).toArray.mkString(", ")}), " +
s"$additionalRegisters, creationHeight: $creationHeight)"
/** Additional tokens stored in the box, merged into a Map.
@@ -216,7 +215,7 @@ object ErgoBoxCandidate {
} else {
val tokenIdSize = TokenId.size // optimization: access the value once
cfor(0)(_ < nTokens, _ + 1) { i =>
- tokenIds(i) = Digest32Coll @@@ Colls.fromArray(r.getBytes(tokenIdSize)) // READ
+ tokenIds(i) = Digest32Coll @@ Colls.fromArray(r.getBytes(tokenIdSize)) // READ
tokenAmounts(i) = r.getULong() // READ
}
}
diff --git a/interpreter/shared/src/main/scala/org/ergoplatform/ErgoLikeTransaction.scala b/data/shared/src/main/scala/org/ergoplatform/ErgoLikeTransaction.scala
similarity index 96%
rename from interpreter/shared/src/main/scala/org/ergoplatform/ErgoLikeTransaction.scala
rename to data/shared/src/main/scala/org/ergoplatform/ErgoLikeTransaction.scala
index fcfdbc922b..eb36d60317 100644
--- a/interpreter/shared/src/main/scala/org/ergoplatform/ErgoLikeTransaction.scala
+++ b/data/shared/src/main/scala/org/ergoplatform/ErgoLikeTransaction.scala
@@ -6,13 +6,12 @@ import scorex.crypto.authds.ADKey
import scorex.crypto.hash.Blake2b256
import scorex.util._
import sigma.Colls
+import sigma.ast.syntax.ErgoBoxCandidateRType
+import sigma.data.Digest32Coll
+import sigma.eval.Extensions.EvalIterableOps
+import sigma.interpreter.ProverResult
import sigma.util.safeNewArray
-import sigmastate._
-import sigmastate.eval.Extensions._
-import sigmastate.eval._
-import sigmastate.interpreter.ProverResult
-import sigmastate.serialization.SigmaSerializer
-import sigmastate.utils.{SigmaByteReader, SigmaByteWriter}
+import sigma.serialization.{SigmaByteReader, SigmaByteWriter, SigmaSerializer}
import scala.util.Try
diff --git a/interpreter/shared/src/main/scala/org/ergoplatform/Input.scala b/data/shared/src/main/scala/org/ergoplatform/Input.scala
similarity index 80%
rename from interpreter/shared/src/main/scala/org/ergoplatform/Input.scala
rename to data/shared/src/main/scala/org/ergoplatform/Input.scala
index e0b4830797..4d15532ad2 100644
--- a/interpreter/shared/src/main/scala/org/ergoplatform/Input.scala
+++ b/data/shared/src/main/scala/org/ergoplatform/Input.scala
@@ -1,13 +1,11 @@
package org.ergoplatform
-import java.util
-
import org.ergoplatform.ErgoBox.BoxId
-import org.ergoplatform.settings.ErgoAlgos
import scorex.crypto.authds.ADKey
-import sigmastate.interpreter.{ContextExtension, ProverResult}
-import sigmastate.serialization.SigmaSerializer
-import sigmastate.utils.{Helpers, SigmaByteReader, SigmaByteWriter}
+import scorex.util.encode.Base16
+import sigma.interpreter.{ContextExtension, ProverResult}
+import sigma.serialization.{SigmaByteReader, SigmaByteWriter, SigmaSerializer}
+import sigma.util.CollectionUtil
/**
* Inputs, that are used to enrich script context, but won't be spent by the transaction
@@ -15,14 +13,14 @@ import sigmastate.utils.{Helpers, SigmaByteReader, SigmaByteWriter}
* @param boxId - id of a box to add into context (should be in UTXO)
*/
case class DataInput(boxId: BoxId) {
- override def toString: String = s"DataInput(${ErgoAlgos.encode(boxId)})"
+ override def toString: String = s"DataInput(${Base16.encode(boxId)})"
override def equals(obj: Any): Boolean = obj match {
case x: DataInput => java.util.Arrays.equals(boxId, x.boxId)
case _ => false
}
- override def hashCode(): Int = Helpers.deepHashCode(boxId)
+ override def hashCode(): Int = CollectionUtil.deepHashCode(boxId)
}
/**
@@ -43,7 +41,7 @@ class UnsignedInput(val boxId: BoxId, val extension: ContextExtension) {
case _ => false
}
- override def hashCode(): Int = Helpers.deepHashCode(boxId)
+ override def hashCode(): Int = CollectionUtil.deepHashCode(boxId)
/**
* Input, that should be signed by prover and verified by verifier.
@@ -60,7 +58,7 @@ class UnsignedInput(val boxId: BoxId, val extension: ContextExtension) {
*/
case class Input(override val boxId: BoxId, spendingProof: ProverResult)
extends UnsignedInput(boxId, spendingProof.extension) {
- override def toString: String = s"Input(${ErgoAlgos.encode(boxId)},$spendingProof)"
+ override def toString: String = s"Input(${Base16.encode(boxId)},$spendingProof)"
}
object Input {
diff --git a/data/shared/src/main/scala/org/ergoplatform/validation/ValidationRules.scala b/data/shared/src/main/scala/org/ergoplatform/validation/ValidationRules.scala
new file mode 100644
index 0000000000..9d4de47a99
--- /dev/null
+++ b/data/shared/src/main/scala/org/ergoplatform/validation/ValidationRules.scala
@@ -0,0 +1,189 @@
+package org.ergoplatform.validation
+
+import sigma.SigmaException
+import sigma.ast.{DeserializeContext, ErgoTree, MethodsContainer, SMethod}
+import sigma.ast.TypeCodes.LastConstantCode
+import sigma.serialization.{InvalidOpCode, SerializerException}
+import sigma.util.Extensions.toUByte
+import sigma.validation.ValidationRules._
+import sigma.validation._
+import sigma.ast.ErgoTree.HeaderType
+import sigma.ast.syntax._
+import sigma.exceptions.InterpreterException
+import sigma.serialization.ValueCodes.OpCode
+import sigma.serialization.ValueSerializer
+
+/** All validation rules which are used to check soft-forkable conditions. Each validation
+ * rule throws a [[org.ergoplatform.validation.ValidationException]]. Each
+ * ValidationException can be caught and handled with respect to
+ * [[SigmaValidationSettings]], which can be changed by miners via voting.
+ * Thus, the behavior of the rules can be overridden without breaking consensus.
+ */
+object ValidationRules {
+
+ object CheckDeserializedScriptType extends ValidationRule(FirstRuleId,
+ "Deserialized script should have expected type") {
+ override protected lazy val settings: SigmaValidationSettings = currentSettings
+
+ final def apply[T](d: DeserializeContext[_], script: SValue): Unit = {
+ checkRule()
+ if (d.tpe != script.tpe) {
+ throwValidationException(
+ new InterpreterException(s"Failed context deserialization of $d: \n" +
+ s"expected deserialized script to have type ${d.tpe}; got ${script.tpe}"),
+ Array[Any](d, script))
+ }
+ }
+ }
+
+ object CheckDeserializedScriptIsSigmaProp extends ValidationRule(1001,
+ "Deserialized script should have SigmaProp type") {
+ override protected lazy val settings: SigmaValidationSettings = currentSettings
+
+ /** @param root candidate node before it is added as a root of ErgoTree */
+ final def apply[T](root: SValue): Unit = {
+ checkRule()
+ if (!root.tpe.isSigmaProp) {
+ throwValidationException(
+ new SerializerException(s"Failed deserialization, expected deserialized script to have type SigmaProp; got ${root.tpe}"),
+ Array[Any](root))
+ }
+ }
+ }
+
+ object CheckValidOpCode extends ValidationRule(1002,
+ "Check the opcode is supported by registered serializer or is added via soft-fork")
+ with SoftForkWhenCodeAdded {
+ override protected lazy val settings: SigmaValidationSettings = currentSettings
+
+ final def apply[T](ser: ValueSerializer[_], opCode: OpCode): Unit = {
+ checkRule()
+ if (ser == null || ser.opCode != opCode) {
+ throwValidationException(
+ new InvalidOpCode(s"Cannot find serializer for Value with opCode = LastConstantCode + ${toUByte(opCode) - LastConstantCode}"),
+ Array(opCode))
+ }
+ }
+ }
+
+ /** Not used since v5.0.1. */
+ object CheckIsSupportedIndexExpression extends ValidationRule(1003,
+ "Check the index expression for accessing collection element is supported.") {
+ override protected lazy val settings: SigmaValidationSettings = currentSettings
+ }
+
+ /** Not used since v5.0.3 */
+ object CheckCostFunc extends ValidationRule(1004,
+ "Cost function should contain only operations from specified list.") {
+ override protected lazy val settings: SigmaValidationSettings = currentSettings
+ }
+
+ object CheckCalcFunc extends ValidationRule(1005,
+ "If SigmaProp.isProven method calls exists in the given function,\n then it is the last operation") {
+ override protected lazy val settings: SigmaValidationSettings = currentSettings
+ }
+
+ /** This rule is not use in v5.x, keep the commented code below as a precise
+ * documentation of its semantics.
+ */
+ object CheckTupleType extends ValidationRule(1006,
+ "Supported tuple type.") with SoftForkWhenReplaced {
+ override protected lazy val settings: SigmaValidationSettings = currentSettings
+
+// final def apply[Ctx <: IRContext, T](ctx: Ctx)(e: ctx.Elem[_]): Unit = {
+// checkRule()
+// val condition = e match {
+// case _: ctx.PairElem[_,_] => true
+// case _ => false
+// }
+// if (!condition) {
+// throwValidationException(new SigmaException(s"Invalid tuple type $e"), Array[ctx.Elem[_]](e))
+// }
+// }
+ }
+
+ object CheckAndGetMethod extends ValidationRule(1011,
+ "Check the type has the declared method.") {
+ override protected lazy val settings: SigmaValidationSettings = currentSettings
+
+ final def apply[T](objType: MethodsContainer, methodId: Byte): SMethod = {
+ checkRule()
+ val methodOpt = objType.getMethodById(methodId)
+ if (methodOpt.isDefined) methodOpt.get
+ else {
+ throwValidationException(
+ new SerializerException(s"The method with code $methodId doesn't declared in the type $objType."),
+ Array[Any](objType, methodId))
+ }
+ }
+
+ override def isSoftFork(vs: SigmaValidationSettings,
+ ruleId: Short,
+ status: RuleStatus,
+ args: Seq[Any]): Boolean = (status, args) match {
+ case (ChangedRule(newValue), Seq(objType: MethodsContainer, methodId: Byte)) =>
+ val key = Array(objType.ownerType.typeId, methodId)
+ newValue.grouped(2).exists(java.util.Arrays.equals(_, key))
+ case _ => false
+ }
+ }
+
+ object CheckHeaderSizeBit extends ValidationRule(1012,
+ "For version greater then 0, size bit should be set.") with SoftForkWhenReplaced {
+ override protected lazy val settings: SigmaValidationSettings = currentSettings
+
+ final def apply(header: HeaderType): Unit = {
+ checkRule()
+ val version = ErgoTree.getVersion(header)
+ if (version != 0 && !ErgoTree.hasSize(header)) {
+ throwValidationException(
+ new SigmaException(s"Invalid ErgoTreeHeader $header, size bit is expected for version $version"),
+ Array(header))
+ }
+ }
+ }
+
+ /** Not used since v5.0.3 */
+ object CheckCostFuncOperation extends ValidationRule(1013,
+ "Check the opcode is allowed in cost function") {
+ override protected lazy val settings: SigmaValidationSettings = currentSettings
+ }
+
+ /** Not used since v5.0.1 */
+ object CheckLoopLevelInCostFunction extends ValidationRule(1015,
+ "Check that loop level is not exceeded.") {
+ override protected lazy val settings: SigmaValidationSettings = currentSettings
+ }
+
+ val ruleSpecs: Seq[ValidationRule] = Seq(
+ CheckDeserializedScriptType,
+ CheckDeserializedScriptIsSigmaProp,
+ CheckValidOpCode,
+ CheckIsSupportedIndexExpression,
+ CheckCostFunc,
+ CheckCalcFunc,
+ CheckTupleType,
+ CheckPrimitiveTypeCode,
+ CheckTypeCode,
+ CheckSerializableTypeCode,
+ CheckTypeWithMethods,
+ CheckAndGetMethod,
+ CheckHeaderSizeBit,
+ CheckCostFuncOperation,
+ CheckPositionLimit,
+ CheckLoopLevelInCostFunction
+ )
+
+ /** Validation settings that correspond to the current version of the ErgoScript implementation.
+ * Different version of the code will have a different set of rules here.
+ * This variable is globally available and can be use wherever checking of the rules is necessary.
+ * This is immutable data structure, it can be augmented with RuleStates from block extension
+ * sections of the blockchain, but that augmentation is only available in stateful context.
+ */
+ val currentSettings: SigmaValidationSettings = new MapSigmaValidationSettings({
+ val map = ruleSpecs.map(r => r.id -> (r, EnabledRule)).toMap
+ assert(map.size == ruleSpecs.size, s"Duplicate ruleIds ${ruleSpecs.groupBy(_.id).filter(g => g._2.length > 1)}")
+ map
+ })
+
+}
diff --git a/data/shared/src/main/scala/sigma/SigmaDataReflection.scala b/data/shared/src/main/scala/sigma/SigmaDataReflection.scala
new file mode 100644
index 0000000000..48939b1460
--- /dev/null
+++ b/data/shared/src/main/scala/sigma/SigmaDataReflection.scala
@@ -0,0 +1,639 @@
+package sigma
+
+import org.ergoplatform.ErgoBox.RegisterId
+import sigma.ast.SCollection.{SBooleanArray, SByteArray, SIntArray}
+import sigma.ast._
+import sigma.ast.syntax._
+import sigma.data.KeyValueColl
+import sigma.eval.ErgoTreeEvaluator
+import sigma.reflection.ReflectionData.registerClassEntry
+import sigma.reflection.{ReflectionData, mkConstructor, mkMethod}
+import sigma.serialization.ValueCodes.OpCode
+
+/** Reflection metadata for `interpreter` module.
+ * Such metadata is only used on JS platform to support reflection-like interfaces of
+ * RClass, RMethod, RConstructor. These interfaces implemented on JVM using Java
+ * reflection.
+ *
+ * For each class of this module that needs reflection metadata,
+ * we register a class entry with the necessary information.
+ * Only information that is needed at runtime is registered.
+ */
+object SigmaDataReflection {
+ val reflection = ReflectionData
+
+ registerClassEntry(classOf[AND],
+ constructors = Array(
+ mkConstructor(Array(classOf[Value[_]])) { args =>
+ new AND(args(0).asInstanceOf[Value[SBooleanArray]])
+ }
+ )
+ )
+
+ registerClassEntry(classOf[ArithOp[_]],
+ constructors = Array(
+ mkConstructor(Array(classOf[Value[_]], classOf[Value[_]], classOf[Byte])) { args =>
+ new ArithOp(args(0).asInstanceOf[SValue], args(1).asInstanceOf[SValue], args(2).asInstanceOf[OpCode])
+ }
+ )
+ )
+
+ registerClassEntry(classOf[AtLeast],
+ constructors = Array(
+ mkConstructor(Array(classOf[Value[_]], classOf[Value[_]])) { args =>
+ new AtLeast(args(0).asInstanceOf[IntValue], args(1).asInstanceOf[CollectionValue[SSigmaProp.type]])
+ }
+ )
+ )
+
+ registerClassEntry(classOf[BinAnd],
+ constructors = Array(
+ mkConstructor(Array(classOf[Value[_]], classOf[Value[_]])) { args =>
+ new BinAnd(args(0).asInstanceOf[BoolValue], args(1).asInstanceOf[BoolValue])
+ }
+ )
+ )
+
+ registerClassEntry(classOf[BinOr],
+ constructors = Array(
+ mkConstructor(Array(classOf[Value[_]], classOf[Value[_]])) { args =>
+ new BinOr(args(0).asInstanceOf[BoolValue], args(1).asInstanceOf[BoolValue])
+ }
+ )
+ )
+
+ registerClassEntry(classOf[BinXor],
+ constructors = Array(
+ mkConstructor(Array(classOf[Value[_]], classOf[Value[_]])) { args =>
+ new BinXor(args(0).asInstanceOf[BoolValue], args(1).asInstanceOf[BoolValue])
+ }
+ )
+ )
+
+ registerClassEntry(classOf[BoolToSigmaProp],
+ constructors = Array(
+ mkConstructor(Array(classOf[Value[_]])) { args =>
+ new BoolToSigmaProp(args(0).asInstanceOf[BoolValue])
+ }
+ )
+ )
+
+ registerClassEntry(classOf[ByteArrayToBigInt],
+ constructors = Array(
+ mkConstructor(Array(classOf[Value[_]])) { args =>
+ new ByteArrayToBigInt(args(0).asInstanceOf[Value[SByteArray]])
+ }
+ )
+ )
+
+ registerClassEntry(classOf[CalcBlake2b256],
+ constructors = Array(
+ mkConstructor(Array(classOf[Value[_]])) { args =>
+ new CalcBlake2b256(args(0).asInstanceOf[Value[SByteArray]])
+ }
+ )
+ )
+
+ registerClassEntry(classOf[CalcSha256],
+ constructors = Array(
+ mkConstructor(Array(classOf[Value[_]])) { args =>
+ new CalcSha256(args(0).asInstanceOf[Value[SByteArray]])
+ }
+ )
+ )
+
+ registerClassEntry(classOf[CreateProveDHTuple],
+ constructors = Array(
+ mkConstructor(Array(classOf[Value[_]], classOf[Value[_]], classOf[Value[_]], classOf[Value[_]])) { args =>
+ new CreateProveDHTuple(args(0).asInstanceOf[GroupElementValue],
+ args(1).asInstanceOf[GroupElementValue],
+ args(2).asInstanceOf[GroupElementValue],
+ args(3).asInstanceOf[GroupElementValue])
+ }
+ )
+ )
+
+ registerClassEntry(classOf[Downcast[_,_]],
+ constructors = Array(
+ mkConstructor(Array(classOf[Value[_]], classOf[SNumericType])) { args =>
+ new Downcast(args(0).asInstanceOf[Value[SNumericType]], args(1).asInstanceOf[SNumericType])
+ }
+ )
+ )
+
+ registerClassEntry(classOf[EQ[_]],
+ constructors = Array(
+ mkConstructor(Array(classOf[Value[_]], classOf[Value[_]])) { args =>
+ new EQ(args(0).asInstanceOf[SAnyValue], args(1).asInstanceOf[SAnyValue])
+ }
+ )
+ )
+
+ registerClassEntry(classOf[Exponentiate],
+ constructors = Array(
+ mkConstructor(Array(classOf[Value[_]], classOf[Value[_]])) { args =>
+ new Exponentiate(args(0).asInstanceOf[GroupElementValue], args(1).asInstanceOf[BigIntValue])
+ }
+ )
+ )
+
+ registerClassEntry(classOf[GE[_]],
+ constructors = Array(
+ mkConstructor(Array(classOf[Value[_]], classOf[Value[_]])) { args =>
+ new GE(args(0).asInstanceOf[SAnyValue], args(1).asInstanceOf[SAnyValue])
+ }
+ )
+ )
+
+ registerClassEntry(classOf[GT[_]],
+ constructors = Array(
+ mkConstructor(Array(classOf[Value[_]], classOf[Value[_]])) { args =>
+ new GT(args(0).asInstanceOf[SAnyValue], args(1).asInstanceOf[SAnyValue])
+ }
+ )
+ )
+
+ registerClassEntry(classOf[If[_]],
+ constructors = Array(
+ mkConstructor(Array(classOf[Value[_]], classOf[Value[_]], classOf[Value[_]])) { args =>
+ new If(args(0).asInstanceOf[BoolValue], args(1).asInstanceOf[SAnyValue], args(2).asInstanceOf[SAnyValue])
+ }
+ )
+ )
+
+ registerClassEntry(classOf[LE[_]],
+ constructors = Array(
+ mkConstructor(Array(classOf[Value[_]], classOf[Value[_]])) { args =>
+ new LE(args(0).asInstanceOf[SAnyValue], args(1).asInstanceOf[SAnyValue])
+ }
+ )
+ )
+
+ registerClassEntry(classOf[LT[_]],
+ constructors = Array(
+ mkConstructor(Array(classOf[Value[_]], classOf[Value[_]])) { args =>
+ new LT(args(0).asInstanceOf[SAnyValue], args(1).asInstanceOf[SAnyValue])
+ }
+ )
+ )
+
+ registerClassEntry(classOf[LogicalNot],
+ constructors = Array(
+ mkConstructor(Array(classOf[Value[_]])) { args =>
+ new LogicalNot(args(0).asInstanceOf[BoolValue])
+ }
+ )
+ )
+
+ registerClassEntry(classOf[MultiplyGroup],
+ constructors = Array(
+ mkConstructor(Array(classOf[Value[_]], classOf[Value[_]])) { args =>
+ new MultiplyGroup(args(0).asInstanceOf[GroupElementValue], args(1).asInstanceOf[GroupElementValue])
+ }
+ )
+ )
+
+ registerClassEntry(classOf[NEQ[_]],
+ constructors = Array(
+ mkConstructor(Array(classOf[Value[_]], classOf[Value[_]])) { args =>
+ new NEQ(args(0).asInstanceOf[SAnyValue], args(1).asInstanceOf[SAnyValue])
+ }
+ )
+ )
+
+ registerClassEntry(classOf[Negation[_]],
+ constructors = Array(
+ mkConstructor(Array(classOf[Value[_]])) { args =>
+ new Negation(args(0).asInstanceOf[SAnyValue])
+ }
+ )
+ )
+
+ registerClassEntry(classOf[OR],
+ constructors = Array(
+ mkConstructor(Array(classOf[Value[_]])) { args =>
+ new OR(args(0).asInstanceOf[Value[SBooleanArray]])
+ }
+ )
+ )
+
+ { val clazz = SAvlTreeMethods.getClass
+ registerClassEntry(clazz,
+ methods = Map(
+ mkMethod(clazz, "update_eval", Array[Class[_]](classOf[MethodCall], classOf[AvlTree], classOf[Coll[_]], classOf[Coll[_]], classOf[ErgoTreeEvaluator])) { (obj, args) =>
+ obj.asInstanceOf[SAvlTreeMethods.type].update_eval(args(0).asInstanceOf[MethodCall],
+ args(1).asInstanceOf[AvlTree],
+ args(2).asInstanceOf[KeyValueColl],
+ args(3).asInstanceOf[Coll[Byte]])(args(4).asInstanceOf[ErgoTreeEvaluator])
+ },
+ mkMethod(clazz, "contains_eval", Array[Class[_]](classOf[MethodCall], classOf[AvlTree], classOf[Coll[_]], classOf[Coll[_]], classOf[ErgoTreeEvaluator])) { (obj, args) =>
+ obj.asInstanceOf[SAvlTreeMethods.type].contains_eval(args(0).asInstanceOf[MethodCall],
+ args(1).asInstanceOf[AvlTree],
+ args(2).asInstanceOf[Coll[Byte]],
+ args(3).asInstanceOf[Coll[Byte]])(args(4).asInstanceOf[ErgoTreeEvaluator])
+ },
+ mkMethod(clazz, "get_eval", Array[Class[_]](classOf[MethodCall], classOf[AvlTree], classOf[Coll[_]], classOf[Coll[_]], classOf[ErgoTreeEvaluator])) { (obj, args) =>
+ obj.asInstanceOf[SAvlTreeMethods.type].get_eval(args(0).asInstanceOf[MethodCall],
+ args(1).asInstanceOf[AvlTree],
+ args(2).asInstanceOf[Coll[Byte]],
+ args(3).asInstanceOf[Coll[Byte]])(args(4).asInstanceOf[ErgoTreeEvaluator])
+ },
+ mkMethod(clazz, "getMany_eval", Array[Class[_]](classOf[MethodCall], classOf[AvlTree], classOf[Coll[_]], classOf[Coll[_]], classOf[ErgoTreeEvaluator])) { (obj, args) =>
+ obj.asInstanceOf[SAvlTreeMethods.type].getMany_eval(args(0).asInstanceOf[MethodCall],
+ args(1).asInstanceOf[AvlTree],
+ args(2).asInstanceOf[Coll[Coll[Byte]]],
+ args(3).asInstanceOf[Coll[Byte]])(args(4).asInstanceOf[ErgoTreeEvaluator])
+ },
+ mkMethod(clazz, "remove_eval", Array[Class[_]](classOf[MethodCall], classOf[AvlTree], classOf[Coll[_]], classOf[Coll[_]], classOf[ErgoTreeEvaluator])) { (obj, args) =>
+ obj.asInstanceOf[SAvlTreeMethods.type].remove_eval(args(0).asInstanceOf[MethodCall],
+ args(1).asInstanceOf[AvlTree],
+ args(2).asInstanceOf[Coll[Coll[Byte]]],
+ args(3).asInstanceOf[Coll[Byte]])(args(4).asInstanceOf[ErgoTreeEvaluator])
+ },
+ mkMethod(clazz, "insert_eval", Array[Class[_]](classOf[MethodCall], classOf[AvlTree], classOf[Coll[_]], classOf[Coll[_]], classOf[ErgoTreeEvaluator])) { (obj, args) =>
+ obj.asInstanceOf[SAvlTreeMethods.type].insert_eval(args(0).asInstanceOf[MethodCall],
+ args(1).asInstanceOf[AvlTree],
+ args(2).asInstanceOf[KeyValueColl],
+ args(3).asInstanceOf[Coll[Byte]])(args(4).asInstanceOf[ErgoTreeEvaluator])
+ }
+ )
+ )
+ }
+
+ { val clazz = SCollectionMethods.getClass
+ registerClassEntry(clazz,
+ methods = Map(
+ mkMethod(clazz, "zip_eval", Array[Class[_]](classOf[MethodCall], classOf[Coll[_]], classOf[Coll[_]], classOf[ErgoTreeEvaluator])) { (obj, args) =>
+ obj.asInstanceOf[SCollectionMethods.type].zip_eval(args(0).asInstanceOf[MethodCall],
+ args(1).asInstanceOf[Coll[Any]],
+ args(2).asInstanceOf[Coll[Any]])(args(3).asInstanceOf[ErgoTreeEvaluator])
+ },
+ mkMethod(clazz, "getOrElse_eval", Array[Class[_]](classOf[MethodCall], classOf[Coll[_]], classOf[Int], classOf[java.lang.Object], classOf[ErgoTreeEvaluator])) { (obj, args) =>
+ obj.asInstanceOf[SCollectionMethods.type].getOrElse_eval(args(0).asInstanceOf[MethodCall],
+ args(1).asInstanceOf[Coll[Any]],
+ args(2).asInstanceOf[Int],
+ args(3).asInstanceOf[Any])(args(4).asInstanceOf[ErgoTreeEvaluator])
+ },
+ mkMethod(clazz, "patch_eval", Array[Class[_]](classOf[MethodCall], classOf[Coll[_]], classOf[Int], classOf[Coll[_]], classOf[Int], classOf[ErgoTreeEvaluator])) { (obj, args) =>
+ obj.asInstanceOf[SCollectionMethods.type].patch_eval(args(0).asInstanceOf[MethodCall],
+ args(1).asInstanceOf[Coll[Any]],
+ args(2).asInstanceOf[Int],
+ args(3).asInstanceOf[Coll[Any]],
+ args(4).asInstanceOf[Int])(args(5).asInstanceOf[ErgoTreeEvaluator])
+ },
+ mkMethod(clazz, "map_eval", Array[Class[_]](classOf[MethodCall], classOf[Coll[_]], classOf[Function1[_,_]], classOf[ErgoTreeEvaluator])) { (obj, args) =>
+ obj.asInstanceOf[SCollectionMethods.type].map_eval(args(0).asInstanceOf[MethodCall],
+ args(1).asInstanceOf[Coll[Any]],
+ args(2).asInstanceOf[Any => Any])(args(3).asInstanceOf[ErgoTreeEvaluator])
+ },
+ mkMethod(clazz, "updated_eval", Array[Class[_]](classOf[MethodCall], classOf[Coll[_]], classOf[Int], classOf[java.lang.Object], classOf[ErgoTreeEvaluator])) { (obj, args) =>
+ obj.asInstanceOf[SCollectionMethods.type].updated_eval(args(0).asInstanceOf[MethodCall],
+ args(1).asInstanceOf[Coll[Any]],
+ args(2).asInstanceOf[Int],
+ args(3))(args(4).asInstanceOf[ErgoTreeEvaluator])
+ },
+ mkMethod(clazz, "indexOf_eval", Array[Class[_]](classOf[MethodCall], classOf[Coll[_]], classOf[java.lang.Object], classOf[Int], classOf[ErgoTreeEvaluator])) { (obj, args) =>
+ obj.asInstanceOf[SCollectionMethods.type].indexOf_eval(args(0).asInstanceOf[MethodCall],
+ args(1).asInstanceOf[Coll[Any]], args(2), args(3).asInstanceOf[Int])(args(4).asInstanceOf[ErgoTreeEvaluator])
+ },
+ mkMethod(clazz, "updateMany_eval", Array[Class[_]](classOf[MethodCall], classOf[Coll[_]], classOf[Coll[_]], classOf[Coll[_]], classOf[ErgoTreeEvaluator])) { (obj, args) =>
+ obj.asInstanceOf[SCollectionMethods.type].updateMany_eval(args(0).asInstanceOf[MethodCall],
+ args(1).asInstanceOf[Coll[Any]],
+ args(2).asInstanceOf[Coll[Int]],
+ args(3).asInstanceOf[Coll[Any]])(args(4).asInstanceOf[ErgoTreeEvaluator])
+ },
+ mkMethod(clazz, "indices_eval", Array[Class[_]](classOf[MethodCall], classOf[Coll[_]], classOf[ErgoTreeEvaluator])) { (obj, args) =>
+ obj.asInstanceOf[SCollectionMethods.type].indices_eval(args(0).asInstanceOf[MethodCall],
+ args(1).asInstanceOf[Coll[Any]])(args(2).asInstanceOf[ErgoTreeEvaluator])
+ },
+ mkMethod(clazz, "flatMap_eval", Array[Class[_]](classOf[MethodCall], classOf[Coll[_]], classOf[Function1[_,_]], classOf[ErgoTreeEvaluator])) { (obj, args) =>
+ obj.asInstanceOf[SCollectionMethods.type].flatMap_eval(args(0).asInstanceOf[MethodCall],
+ args(1).asInstanceOf[Coll[Any]], args(2).asInstanceOf[Any => Coll[Any]])(args(3).asInstanceOf[ErgoTreeEvaluator])
+ }
+ )
+ )
+ }
+
+ { val clazz = SGlobalMethods.getClass
+ registerClassEntry(clazz,
+ methods = Map(
+ mkMethod(clazz, "xor_eval", Array[Class[_]](classOf[MethodCall], classOf[SigmaDslBuilder], classOf[Coll[_]], classOf[Coll[_]], classOf[ErgoTreeEvaluator])) { (obj, args) =>
+ obj.asInstanceOf[SGlobalMethods.type].xor_eval(args(0).asInstanceOf[MethodCall],
+ args(1).asInstanceOf[SigmaDslBuilder],
+ args(2).asInstanceOf[Coll[Byte]],
+ args(3).asInstanceOf[Coll[Byte]])(args(4).asInstanceOf[ErgoTreeEvaluator])
+ }
+ )
+ )
+ }
+
+ registerClassEntry(classOf[SigmaAnd],
+ constructors = Array(
+ mkConstructor(Array(classOf[Seq[_]])) { args =>
+ new SigmaAnd(args(0).asInstanceOf[Seq[SigmaPropValue]])
+ }
+ )
+ )
+
+ registerClassEntry(classOf[SigmaOr],
+ constructors = Array(
+ mkConstructor(Array(classOf[Seq[_]])) { args =>
+ new SigmaOr(args(0).asInstanceOf[Seq[SigmaPropValue]])
+ }
+ )
+ )
+
+ registerClassEntry(classOf[SubstConstants[_]],
+ constructors = Array(
+ mkConstructor(Array(classOf[Value[_]], classOf[Value[_]], classOf[Value[_]])) { args =>
+ new SubstConstants(args(0).asInstanceOf[Value[SByteArray]],
+ args(1).asInstanceOf[Value[SIntArray]],
+ args(2).asInstanceOf[CollectionValue[SType]])
+ }
+ )
+ )
+
+ registerClassEntry(classOf[Upcast[_,_]],
+ constructors = Array(
+ mkConstructor(Array(classOf[Value[_]], classOf[SNumericType])) { args =>
+ new Upcast(args(0).asInstanceOf[Value[SNumericType]], args(1).asInstanceOf[SNumericType])
+ }
+ )
+ )
+
+ registerClassEntry(classOf[BlockValue],
+ constructors = Array(
+ mkConstructor(Array(classOf[IndexedSeq[_]], classOf[Value[_]])) { args =>
+ new BlockValue(args(0).asInstanceOf[IndexedSeq[BlockItem]], args(1).asInstanceOf[SValue])
+ }
+ )
+ )
+
+ registerClassEntry(classOf[ConcreteCollection[_]],
+ constructors = Array(
+ mkConstructor(Array(classOf[Seq[_]], classOf[SType])) { args =>
+ new ConcreteCollection(args(0).asInstanceOf[Seq[SValue]], args(1).asInstanceOf[SType])
+ }
+ )
+ )
+
+ registerClassEntry(classOf[FuncValue],
+ constructors = Array(
+ mkConstructor(Array(classOf[IndexedSeq[_]], classOf[Value[_]])) { args =>
+ new FuncValue(args(0).asInstanceOf[IndexedSeq[(Int, SType)]], args(1).asInstanceOf[SValue])
+ }
+ )
+ )
+
+ registerClassEntry(classOf[Tuple],
+ constructors = Array(
+ mkConstructor(Array(classOf[IndexedSeq[_]])) { args =>
+ new Tuple(args(0).asInstanceOf[IndexedSeq[SValue]])
+ }
+ )
+ )
+
+ registerClassEntry(classOf[ValDef],
+ constructors = Array(
+ mkConstructor(Array(classOf[Int], classOf[Seq[_]], classOf[Value[_]])) { args =>
+ new ValDef(args(0).asInstanceOf[Int], args(1).asInstanceOf[Seq[STypeVar]], args(2).asInstanceOf[SValue])
+ }
+ )
+ )
+
+ registerClassEntry(classOf[Apply],
+ constructors = Array(
+ mkConstructor(Array(classOf[Value[_]], classOf[IndexedSeq[_]])) { args =>
+ new Apply(args(0).asInstanceOf[SValue], args(1).asInstanceOf[IndexedSeq[SValue]])
+ }
+ )
+ )
+
+ registerClassEntry(classOf[ApplyTypes],
+ constructors = Array(
+ mkConstructor(Array(classOf[Value[_]], classOf[Seq[_]])) { args =>
+ new ApplyTypes(args(0).asInstanceOf[SValue], args(1).asInstanceOf[Seq[SType]])
+ }
+ )
+ )
+
+ registerClassEntry(classOf[Block],
+ constructors = Array(
+ mkConstructor(Array(classOf[Seq[_]], classOf[Value[_]])) { args =>
+ new Block(args(0).asInstanceOf[Seq[Val]], args(1).asInstanceOf[SValue])
+ }
+ )
+ )
+
+ registerClassEntry(classOf[Lambda],
+ constructors = Array(
+ mkConstructor(Array(classOf[Seq[_]], classOf[IndexedSeq[_]], classOf[SType], classOf[Option[_]])) { args =>
+ new Lambda(args(0).asInstanceOf[Seq[STypeParam]],
+ args(1).asInstanceOf[IndexedSeq[(String, SType)]],
+ args(2).asInstanceOf[SType],
+ args(3).asInstanceOf[Option[SValue]])
+ }
+ )
+ )
+
+ registerClassEntry(classOf[MethodCall],
+ constructors = Array(
+ mkConstructor(Array(classOf[Value[_]], classOf[SMethod], classOf[IndexedSeq[_]], classOf[scala.collection.immutable.Map[_,_]])) { args =>
+ new MethodCall(args(0).asInstanceOf[SValue],
+ args(1).asInstanceOf[SMethod],
+ args(2).asInstanceOf[IndexedSeq[SValue]],
+ args(3).asInstanceOf[Map[STypeVar,SType]])
+ }
+ )
+ )
+
+ registerClassEntry(classOf[MethodCallLike],
+ constructors = Array(
+ mkConstructor(Array(classOf[Value[_]], classOf[java.lang.String], classOf[IndexedSeq[_]], classOf[SType])) { args =>
+ new MethodCallLike(args(0).asInstanceOf[SValue],
+ args(1).asInstanceOf[String],
+ args(2).asInstanceOf[IndexedSeq[SValue]],
+ args(3).asInstanceOf[SType])
+ }
+ )
+ )
+
+ registerClassEntry(classOf[Select],
+ constructors = Array(
+ mkConstructor(Array(classOf[Value[_]], classOf[java.lang.String], classOf[Option[_]])) { args =>
+ new Select(args(0).asInstanceOf[SValue], args(1).asInstanceOf[String], args(2).asInstanceOf[Option[SType]])
+ }
+ )
+ )
+
+ registerClassEntry(classOf[ValNode],
+ constructors = Array(
+ mkConstructor(Array(classOf[java.lang.String], classOf[SType], classOf[Value[_]])) { args =>
+ new ValNode(args(0).asInstanceOf[String], args(1).asInstanceOf[SType], args(2).asInstanceOf[SValue])
+ }
+ )
+ )
+
+ registerClassEntry(classOf[Append[_]],
+ constructors = Array(
+ mkConstructor(Array(classOf[Value[_]], classOf[Value[_]])) { args =>
+ new Append(args(0).asInstanceOf[CollectionValue[SType]], args(1).asInstanceOf[CollectionValue[SType]])
+ }
+ )
+ )
+
+ registerClassEntry(classOf[ByIndex[_]],
+ constructors = Array(
+ mkConstructor(Array(classOf[Value[_]], classOf[Value[_]], classOf[Option[_]])) { args =>
+ new ByIndex(args(0).asInstanceOf[CollectionValue[SType]],
+ args(1).asInstanceOf[IntValue], args(2).asInstanceOf[Option[SValue]])
+ }
+ )
+ )
+
+ registerClassEntry(classOf[Exists[_]],
+ constructors = Array(
+ mkConstructor(Array(classOf[Value[_]], classOf[Value[_]])) { args =>
+ new Exists(args(0).asInstanceOf[CollectionValue[SType]], args(1).asInstanceOf[Value[SFunc]])
+ }
+ )
+ )
+
+ registerClassEntry(classOf[ExtractAmount],
+ constructors = Array(
+ mkConstructor(Array(classOf[Value[_]])) { args =>
+ new ExtractAmount(args(0).asInstanceOf[BoxValue])
+ }
+ )
+ )
+
+ registerClassEntry(classOf[ExtractBytesWithNoRef],
+ constructors = Array(
+ mkConstructor(Array(classOf[Value[_]])) { args =>
+ new ExtractBytesWithNoRef(args(0).asInstanceOf[BoxValue])
+ }
+ )
+ )
+
+ registerClassEntry(classOf[ExtractCreationInfo],
+ constructors = Array(
+ mkConstructor(Array(classOf[Value[_]])) { args =>
+ new ExtractCreationInfo(args(0).asInstanceOf[BoxValue])
+ }
+ )
+ )
+
+ registerClassEntry(classOf[ExtractId],
+ constructors = Array(
+ mkConstructor(Array(classOf[Value[_]])) { args =>
+ new ExtractId(args(0).asInstanceOf[BoxValue])
+ }
+ )
+ )
+
+ registerClassEntry(classOf[ExtractRegisterAs[_]],
+ constructors = Array(
+ mkConstructor(Array(classOf[Value[_]], classOf[org.ergoplatform.ErgoBox.RegisterId], classOf[SOption[_]])) { args =>
+ new ExtractRegisterAs(args(0).asInstanceOf[BoxValue], args(1).asInstanceOf[RegisterId], args(2).asInstanceOf[SOption[SAny.type]])
+ }
+ )
+ )
+
+ registerClassEntry(classOf[ExtractScriptBytes],
+ constructors = Array(
+ mkConstructor(Array(classOf[Value[_]])) { args =>
+ new ExtractScriptBytes(args(0).asInstanceOf[BoxValue])
+ }
+ )
+ )
+
+ registerClassEntry(classOf[Filter[_]],
+ constructors = Array(
+ mkConstructor(Array(classOf[Value[_]], classOf[Value[_]])) { args =>
+ new Filter(args(0).asInstanceOf[CollectionValue[SType]], args(1).asInstanceOf[Value[SFunc]])
+ }
+ )
+ )
+
+ registerClassEntry(classOf[Fold[_,_]],
+ constructors = Array(
+ mkConstructor(Array(classOf[Value[_]], classOf[Value[_]], classOf[Value[_]])) { args =>
+ new Fold(args(0).asInstanceOf[CollectionValue[SType]],
+ args(1).asInstanceOf[SValue], args(2).asInstanceOf[Value[SFunc]])
+ }
+ )
+ )
+
+ registerClassEntry(classOf[ForAll[_]],
+ constructors = Array(
+ mkConstructor(Array(classOf[Value[_]], classOf[Value[_]])) { args =>
+ new ForAll(args(0).asInstanceOf[CollectionValue[SType]], args(1).asInstanceOf[Value[SFunc]])
+ }
+ )
+ )
+
+ registerClassEntry(classOf[MapCollection[_,_]],
+ constructors = Array(
+ mkConstructor(Array(classOf[Value[_]], classOf[Value[_]])) { args =>
+ new MapCollection(args(0).asInstanceOf[CollectionValue[SType]], args(1).asInstanceOf[Value[SFunc]])
+ }
+ )
+ )
+
+ registerClassEntry(classOf[OptionGet[_]],
+ constructors = Array(
+ mkConstructor(Array(classOf[Value[_]])) { args =>
+ new OptionGet(args(0).asInstanceOf[Value[SOption[SType]]])
+ }
+ )
+ )
+
+ registerClassEntry(classOf[OptionGetOrElse[_]],
+ constructors = Array(
+ mkConstructor(Array(classOf[Value[_]], classOf[Value[_]])) { args =>
+ new OptionGetOrElse(args(0).asInstanceOf[Value[SOption[SType]]], args(1).asInstanceOf[SValue])
+ }
+ )
+ )
+
+ registerClassEntry(classOf[OptionIsDefined[_]],
+ constructors = Array(
+ mkConstructor(Array(classOf[Value[_]])) { args =>
+ new OptionIsDefined(args(0).asInstanceOf[Value[SOption[SType]]])
+ }
+ )
+ )
+
+ registerClassEntry(classOf[SelectField],
+ constructors = Array(
+ mkConstructor(Array(classOf[Value[_]], classOf[Byte])) { args =>
+ new SelectField(args(0).asInstanceOf[Value[STuple]], args(1).asInstanceOf[Byte])
+ }
+ )
+ )
+
+ registerClassEntry(classOf[SigmaPropBytes],
+ constructors = Array(
+ mkConstructor(Array(classOf[Value[_]])) { args =>
+ new SigmaPropBytes(args(0).asInstanceOf[SigmaPropValue])
+ }
+ )
+ )
+
+ registerClassEntry(classOf[SizeOf[_]],
+ constructors = Array(
+ mkConstructor(Array(classOf[Value[_]])) { args =>
+ new SizeOf(args(0).asInstanceOf[CollectionValue[SType]])
+ }
+ )
+ )
+
+ registerClassEntry(classOf[Slice[_]],
+ constructors = Array(
+ mkConstructor(Array(classOf[Value[_]], classOf[Value[_]], classOf[Value[_]])) { args =>
+ new Slice(args(0).asInstanceOf[CollectionValue[SType]],
+ args(1).asInstanceOf[IntValue], args(2).asInstanceOf[IntValue])
+ }
+ )
+ )
+}
diff --git a/interpreter/shared/src/main/scala/sigmastate/interpreter/CostItem.scala b/data/shared/src/main/scala/sigma/ast/CostItem.scala
similarity index 71%
rename from interpreter/shared/src/main/scala/sigmastate/interpreter/CostItem.scala
rename to data/shared/src/main/scala/sigma/ast/CostItem.scala
index 27b50779cf..c69c81daa3 100644
--- a/interpreter/shared/src/main/scala/sigmastate/interpreter/CostItem.scala
+++ b/data/shared/src/main/scala/sigma/ast/CostItem.scala
@@ -1,16 +1,12 @@
-package sigmastate.interpreter
+package sigma.ast
-import sigmastate.{FixedCost, JitCost, PerItemCost, SMethod, SType, TypeBasedCost}
-import sigmastate.Values.{FixedCostValueCompanion, PerItemCostValueCompanion, ValueCompanion}
-import sigmastate.lang.Terms.MethodCall
-
-/** An item in the cost accumulation trace of a [[sigmastate.Values.ErgoTree]] evaluation. */
+/** An item in the cost accumulation trace of a [[sigma.ast.ErgoTree]] evaluation. */
abstract class CostItem {
def opName: String
def cost: JitCost
}
-/** An item in the cost accumulation trace of a [[sigmastate.Values.ErgoTree]] evaluation.
+/** An item in the cost accumulation trace of a [[sigma.ast.ErgoTree]] evaluation.
* Represents cost of simple operation.
* Used for debugging, testing and profiling of costing.
* @param opDesc descriptor of the ErgoTree operation
@@ -29,13 +25,13 @@ object FixedCostItem {
}
}
-/** An item in the cost accumulation trace of a [[sigmastate.Values.ErgoTree]] evaluation.
+/** An item in the cost accumulation trace of a [[sigma.ast.ErgoTree]] evaluation.
* Represents cost of an operation which depends on type (e.g. type of arguments).
* Used for debugging, testing and profiling of costing.
* @param opDesc descriptor of the ErgoTree operation
* @param costKind type based cost descriptor added to accumulator
* @param tpe concrete type on this the operation is executed
- * @see [[sigmastate.LE]], [[sigmastate.GT]]
+ * @see [[LE]], [[GT]]
*/
case class TypeBasedCostItem(
opDesc: OperationDesc,
@@ -60,7 +56,7 @@ object TypeBasedCostItem {
}
}
-/** An item in the cost accumulation trace of a [[sigmastate.Values.ErgoTree]] evaluation.
+/** An item in the cost accumulation trace of a [[sigma.ast.ErgoTree]] evaluation.
* Represents cost of a sequence of operation.
* Used for debugging, testing and profiling of costing.
*
@@ -80,15 +76,4 @@ object SeqCostItem {
SeqCostItem(companion.opDesc, companion.costKind, nItems)
}
-/** An item in the cost accumulation trace of a [[sigmastate.Values.ErgoTree]] evaluation.
- * Represents cost of MethodCall operation.
- * Used for debugging, testing and profiling of costing.
- *
- * @param items cost details obtained as part of MethodCall evaluation
- */
-case class MethodCallCostItem(items: CostDetails) extends CostItem {
- override def opName: String = MethodCall.typeName
- override def cost: JitCost = items.cost
-}
-
diff --git a/interpreter/shared/src/main/scala/sigmastate/CostKind.scala b/data/shared/src/main/scala/sigma/ast/CostKind.scala
similarity index 96%
rename from interpreter/shared/src/main/scala/sigmastate/CostKind.scala
rename to data/shared/src/main/scala/sigma/ast/CostKind.scala
index 0730bb4ec0..1fda6018ec 100644
--- a/interpreter/shared/src/main/scala/sigmastate/CostKind.scala
+++ b/data/shared/src/main/scala/sigma/ast/CostKind.scala
@@ -1,9 +1,9 @@
-package sigmastate
+package sigma.ast
import scala.runtime.Statics
/** Cost descriptor of a single operation, usually associated with
- * [[sigmastate.interpreter.OperationDesc]].
+ * [[OperationDesc]].
*/
sealed abstract class CostKind
diff --git a/data/shared/src/main/scala/sigma/ast/ErgoTree.scala b/data/shared/src/main/scala/sigma/ast/ErgoTree.scala
new file mode 100644
index 0000000000..d6ed6118dc
--- /dev/null
+++ b/data/shared/src/main/scala/sigma/ast/ErgoTree.scala
@@ -0,0 +1,414 @@
+package sigma.ast
+
+import scorex.util.encode.Base16
+import sigma.VersionContext
+import sigma.ast.ErgoTree.{HeaderType, substConstants}
+import sigma.ast.syntax._
+import sigma.data.{CSigmaProp, SigmaBoolean}
+import sigma.kiama.rewriting.Rewriter.{everywherebu, strategy}
+import sigma.validation.ValidationException
+import sigma.ast.syntax.ValueOps
+import sigma.eval.Extensions.SigmaBooleanOps
+import sigma.serialization.ErgoTreeSerializer.DefaultSerializer
+import sigma.serialization.{ConstantStore, ErgoTreeSerializer, SigmaSerializer, ValueSerializer}
+import supertagged.TaggedType
+
+import java.util.Objects
+import scala.collection.mutable
+
+/** This is alternative representation of ErgoTree expression when it cannot be parsed
+ * due to `error`. This is used by the nodes running old versions of code to recognize
+ * soft-fork conditions and skip validation of box propositions which are unparsable. */
+case class UnparsedErgoTree(bytes: mutable.WrappedArray[Byte], error: ValidationException)
+
+/** The root of ErgoScript IR. Serialized instances of this class are self sufficient and can be passed around.
+ * ErgoTreeSerializer defines top-level serialization format of the scripts.
+ * The interpretation of the byte array depend on the first `header` byte, which uses VLQ encoding up to 30 bits.
+ * Currently we define meaning for only first byte, which may be extended in future versions.
+ * 7 6 5 4 3 2 1 0
+ * -------------------------
+ * | | | | | | | | |
+ * -------------------------
+ * Bit 7 == 1 if the header contains more than 1 byte (default == 0)
+ * Bit 6 - reserved for GZIP compression (should be 0)
+ * Bit 5 == 1 - reserved for context dependent costing (should be = 0)
+ * Bit 4 == 1 if constant segregation is used for this ErgoTree (default = 0)
+ * (see https://github.com/ScorexFoundation/sigmastate-interpreter/issues/264)
+ * Bit 3 == 1 if size of the whole tree is serialized after the header byte (default = 0)
+ * Bits 2-0 - language version (current version == 0)
+ *
+ * Currently we don't specify interpretation for the second and other bytes of the header.
+ * We reserve the possibility to extend header by using Bit 7 == 1 and chain additional bytes as in VLQ.
+ * Once the new bytes are required, a new version of the language should be created and implemented.
+ * That new language will give an interpretation for the new bytes.
+ *
+ * Consistency between fields is ensured by private constructor and factory methods in `ErgoTree` object.
+ * For performance reasons, ErgoTreeSerializer can be configured to perform additional constant segregation.
+ * In such a case after deserialization there may be more constants segregated. This is done for example to
+ * support caching optimization described in #264 mentioned above.
+ *
+ * The default behavior of ErgoTreeSerializer is to preserve original structure of ErgoTree and check
+ * consistency. In case of any inconsistency the serializer throws exception.
+ *
+ * @param header the first byte of serialized byte array which determines interpretation of the rest of the array
+ * @param constants If isConstantSegregation == true contains the constants for which there may be
+ * ConstantPlaceholders in the tree.
+ * If isConstantSegregation == false this array should be empty and any placeholder in
+ * the tree will lead to exception.
+ * @param root On the right side it has valid expression of `SigmaProp` type. Or alternatively,
+ * on the left side, it has unparsed bytes along with the ValidationException,
+ * which caused the deserializer to fail.
+ * `Right(tree)` if isConstantSegregation == true contains ConstantPlaceholder
+ * instead of some Constant nodes. Otherwise, it may not contain placeholders.
+ * It is possible to have both constants and placeholders in the tree, but for every placeholder
+ * there should be a constant in `constants` array.
+ * @param propositionBytes original bytes of this tree from which it has been deserialized.
+ * If null then the bytes are not provided, and will be lazily generated when `bytes`
+ * method is called.
+ * These bytes are obtained in two ways:
+ * 1) in the ErgoTreeSerializer from Reader
+ * 2) in the alternative constructor using ErgoTreeSerializer.serializeErgoTree
+ * @param givenDeserialize optional flag, which contains information about presence of
+ * deserialization operations in the tree. If it is None, the information is not
+ * available. If Some(true) then there are deserialization operations, otherwise
+ * the tree doesn't contain deserialization and is eligible
+ * for optimized execution.
+ * ErgoTreeSerializer parsing method computes the value of
+ * this flag and provides it to the constructor.
+ */
+case class ErgoTree private[sigma](
+ header: HeaderType,
+ constants: IndexedSeq[Constant[SType]],
+ root: Either[UnparsedErgoTree, SigmaPropValue],
+ private val propositionBytes: Array[Byte],
+ private val givenDeserialize: Option[Boolean],
+ private val givenIsUsingBlockchainContext: Option[Boolean]
+) {
+ def this(
+ header: HeaderType,
+ constants: IndexedSeq[Constant[SType]],
+ root: Either[UnparsedErgoTree, SigmaPropValue]) =
+ this(
+ header, constants, root,
+ propositionBytes = DefaultSerializer.serializeErgoTree(
+ ErgoTree(header, constants, root, null, None, None)
+ ),
+ givenDeserialize = None,
+ givenIsUsingBlockchainContext = None
+ )
+
+ require(isConstantSegregation || constants.isEmpty)
+
+ require(version == 0 || hasSize, s"For newer version the size bit is required: $this")
+
+ /** Then it throws the error from UnparsedErgoTree.
+ * It does so on every usage of `proposition` because the lazy value remains uninitialized.
+ */
+ @deprecated("Use toProposition instead", "v2.1")
+ lazy val proposition: SigmaPropValue = toProposition(isConstantSegregation)
+
+ /** Version of this tree (== BlockVersion - 1). */
+ @inline final def version: Byte = ErgoTree.getVersion(header)
+
+ @inline final def isRightParsed: Boolean = root.isRight
+
+ /** @return true, if constant segregation bit is set in the header. */
+ @inline final def isConstantSegregation: Boolean = ErgoTree.isConstantSegregation(header)
+
+ /** @return true, if size bit is set in the header. */
+ @inline final def hasSize: Boolean = ErgoTree.hasSize(header)
+
+ private[sigma] var _bytes: Array[Byte] = propositionBytes
+
+ /** Serialized bytes of this tree. */
+ final def bytes: Array[Byte] = {
+ if (_bytes == null) {
+ _bytes = DefaultSerializer.serializeErgoTree(this)
+ }
+ _bytes
+ }
+
+ /** Hexadecimal encoded string of ErgoTree.bytes. */
+ final def bytesHex: String = Base16.encode(bytes)
+
+ private[sigma] var _hasDeserialize: Option[Boolean] = givenDeserialize
+
+ /** Returns true if the tree contains at least one deserialization operation,
+ * false otherwise.
+ */
+ lazy val hasDeserialize: Boolean = {
+ if (_hasDeserialize.isEmpty) {
+ _hasDeserialize = Some(root match {
+ case Right(p) => Value.hasDeserialize(p)
+ case _ => false
+ })
+ }
+ _hasDeserialize.get
+ }
+
+ private[sigma] var _isUsingBlockchainContext: Option[Boolean] = givenIsUsingBlockchainContext
+
+ /** Returns true if the tree depends on the blockchain context.
+ */
+ lazy val isUsingBlockchainContext: Boolean = {
+ if (_isUsingBlockchainContext.isEmpty) {
+ _isUsingBlockchainContext = Some(root match {
+ case Right(p) => Value.isUsingBlockchainContext(p)
+ case _ => false
+ })
+ }
+ _isUsingBlockchainContext.get
+ }
+
+ /** Serialized proposition expression of SigmaProp type with
+ * ConstantPlaceholder nodes not replaced by Constant nodes.
+ */
+ lazy val template: Array[Byte] = {
+ val r = SigmaSerializer.startReader(bytes)
+ DefaultSerializer.deserializeHeaderWithTreeBytes(r)._4
+ }
+
+ /** Base16 encoding of `template` bytes. */
+ def templateHex: String = Base16.encode(template)
+
+ /** Get proposition expression from this contract.
+ * When root.isRight then
+ * if replaceConstants == false this is the same as `root.right.get`.
+ * Otherwise, it is equivalent to `root.right.get` where all placeholders are replaced by Constants.
+ * When root.isLeft then
+ * throws the error from UnparsedErgoTree.
+ * It does so on every usage of `proposition` because the lazy value remains uninitialized.
+ */
+ def toProposition(replaceConstants: Boolean): SigmaPropValue = root match {
+ case Right(tree) =>
+ val prop = if (replaceConstants)
+ substConstants(tree, constants).asSigmaProp
+ else
+ tree
+ prop
+ case Left(UnparsedErgoTree(_, error)) =>
+ throw error
+ }
+
+ /** This method attempts to convert the current instance into a `SigmaBoolean`.
+ * It does so by first converting the instance to a `SigmaPropValue` using the
+ * `toProposition` method, and then checks if the resulting expression is a
+ * `SigmaPropConstant`. If it is, the method extracts the `SigmaBoolean` from the
+ * `SigmaPropConstant`. Otherwise, the method returns `None`.
+ *
+ * @note This method relies on constant segregation flag in the header to determine the
+ * behavior of `toProposition` method.
+ *
+ * @return `Some(SigmaBoolean)` if conversion is successful, `None` otherwise.
+ */
+ def toSigmaBooleanOpt: Option[SigmaBoolean] = {
+ val prop = this.toProposition(this.isConstantSegregation)
+ prop match {
+ case SigmaPropConstant(p) => Some(p.asInstanceOf[CSigmaProp].wrappedValue)
+ case _ => None
+ }
+ }
+
+ /** The default equality of case class is overridden to exclude `complexity`. */
+ override def canEqual(that: Any): Boolean = that.isInstanceOf[ErgoTree]
+
+ override def hashCode(): Int = header * 31 + Objects.hash(constants, root)
+
+ override def equals(obj: Any): Boolean = (this eq obj.asInstanceOf[AnyRef]) ||
+ ((obj.asInstanceOf[AnyRef] != null) && (obj match {
+ case other: ErgoTree =>
+ other.header == header && other.constants == constants && other.root == root
+ case _ => false
+ }))
+}
+
+object ErgoTree {
+ /** Represents information in ErgoTree header. */
+ object HeaderType extends TaggedType[Byte]
+
+ type HeaderType = HeaderType.Type
+
+ /** Current version of ErgoTree serialization format (aka bite-code language version) */
+ val VersionFlag: Byte = VersionContext.MaxSupportedScriptVersion
+
+ /** Header flag to indicate that constant segregation should be applied. */
+ val ConstantSegregationFlag: Byte = 0x10
+
+ /** Header flag to indicate that whole size of ErgoTree should be saved before tree content. */
+ val SizeFlag: Byte = 0x08
+
+ /** Header mask to extract version bits. */
+ val VersionMask: Byte = 0x07
+
+ /** Header with all the flags set to 0 and version 0. */
+ val ZeroHeader: HeaderType = HeaderType @@ 0.toByte
+
+ /** Default value of ErgoTree.header byte */
+ val DefaultHeader: HeaderType = ZeroHeader //HeaderType @@ (VersionFlag | SizeFlag).toByte
+
+ /** Default header with constant segregation enabled. */
+ val ConstantSegregationHeader: HeaderType = HeaderType @@ (DefaultHeader | ConstantSegregationFlag).toByte
+
+ /** @return true if the constant segregation flag is set to 1 in the given header byte. */
+ @inline final def isConstantSegregation(header: HeaderType): Boolean = (header & ConstantSegregationFlag) != 0
+
+ /** @return true if the size flag is set to 1 in the given header byte. */
+ @inline final def hasSize(header: HeaderType): Boolean = (header & SizeFlag) != 0
+
+ /** @return a value of the version bits from the given header byte. */
+ @inline final def getVersion(header: HeaderType): Byte = (header & VersionMask).toByte
+
+ /** Update the version bits of the given header byte with the given version value,
+ * leaving all other bits unchanged.
+ */
+ @inline final def setVersionBits(header: HeaderType, version: Byte): HeaderType = {
+ require(version < 8, s"ErgoTree.version should be < 8: $version")
+ val h = header & (~VersionMask) // clear version bits
+ HeaderType @@ (h | version).toByte
+ }
+
+ /** Sets the required bit in the given header:
+ * - The SizeFlag is set if version > 0
+ */
+ @inline final def setRequiredBits(header: HeaderType): HeaderType = {
+ if (getVersion(header) > 0) {
+ // set SizeFlag if version is greater then 0 (see require() in ErgoTree constructor)
+ HeaderType @@ (header | ErgoTree.SizeFlag).toByte
+ } else
+ header
+ }
+
+ /** Sets the ConstantSegregationFlag in the given header */
+ @inline final def setConstantSegregation(header: HeaderType): HeaderType = {
+ HeaderType @@ (header | ConstantSegregationFlag).toByte
+ }
+
+ /** Sets the ConstantSegregationFlag in the given header */
+ @inline final def setSizeBit(header: HeaderType): HeaderType = {
+ HeaderType @@ (header | SizeFlag).toByte
+ }
+
+ /** Creates valid header byte with the given version.
+ * The SizeFlag is set if version > 0 */
+ @inline final def defaultHeaderWithVersion(version: Byte): HeaderType = {
+ headerWithVersion(DefaultHeader, version)
+ }
+
+ /** Creates valid header byte with the given version.
+ * The SizeFlag is set if version > 0 */
+ @inline final def headerWithVersion(header: HeaderType, version: Byte): HeaderType = {
+ // take the header and embedd the given version in it
+ val h = setVersionBits(header, version)
+ setRequiredBits(h)
+ }
+
+ /** Substitute [[ConstantPlaceholder]] nodes in the given expression with the constants
+ * taken from the given collection.
+ *
+ * @param root expression to transform
+ * @param constants collection of constants to replace placeholders
+ * @return new expression without placeholders
+ */
+ def substConstants(root: SValue, constants: IndexedSeq[Constant[SType]]): SValue = {
+ val store = new ConstantStore(constants)
+ val substRule = strategy[Any] {
+ case ph: ConstantPlaceholder[_] =>
+ Some(store.get(ph.id))
+ case _ => None
+ }
+ everywherebu(substRule)(root).fold(root)(_.asInstanceOf[SValue])
+ }
+
+ /** Create an ErgoTree with the given parameters. */
+ def apply(
+ header: HeaderType,
+ constants: IndexedSeq[Constant[SType]],
+ root: SigmaPropValue): ErgoTree = {
+ new ErgoTree(setRequiredBits(header), constants, Right(root))
+ }
+
+ val EmptyConstants: IndexedSeq[Constant[SType]] = Array[Constant[SType]]()
+
+ /** Create new ErgoTree for the given proposition using default header.
+ * If the property is not a simple constant, then constant segregation is performed.
+ */
+ def fromProposition(prop: SigmaPropValue): ErgoTree = {
+ fromProposition(ErgoTree.ZeroHeader, prop)
+ }
+
+ /** Create new ErgoTree for the given proposition using the given header flags.
+ * If the property is not a simple constant, then constant segregation is performed.
+ */
+ def fromProposition(header: HeaderType, prop: SigmaPropValue): ErgoTree = {
+ prop match {
+ case SigmaPropConstant(_) => withoutSegregation(header, prop)
+ case _ => withSegregation(header, prop)
+ }
+ }
+
+ /** Create new ErgoTree for the given sigma proposition using default header and
+ * without performing constant segregation.
+ */
+ def fromSigmaBoolean(pk: SigmaBoolean): ErgoTree = {
+ withoutSegregation(ZeroHeader, pk.toSigmaPropValue)
+ }
+
+ /** Create new ErgoTree for the given sigma proposition using the given header flags
+ * and without performing constant segregation.
+ */
+ def fromSigmaBoolean(header: HeaderType, pk: SigmaBoolean): ErgoTree = {
+ withoutSegregation(header, pk.toSigmaPropValue)
+ }
+
+ /** Create new ErgoTree for the given proposition using the given header flags and
+ * without performing constant segregation.
+ */
+ def withoutSegregation(header: HeaderType, root: SigmaPropValue): ErgoTree =
+ ErgoTree(setRequiredBits(header), EmptyConstants, root)
+
+ /** Build ErgoTree via serialization of the value with ConstantSegregationHeader, constants segregated
+ * from the tree and ConstantPlaceholders referring to the segregated constants.
+ *
+ * This method uses single traverse of the tree to:
+ * 1) find and segregate all constants;
+ * 2) replace constants with ConstantPlaceholders in the `tree`;
+ * 3) write the `tree` to the Writer's buffer obtaining `treeBytes`;
+ * 4) deserialize `tree` with ConstantPlaceholders.
+ *
+ * @param headerFlags additional header flags to combine with
+ * ConstantSegregationHeader flag.
+ * @param prop expression to be transformed into ErgoTree
+ * */
+ def withSegregation(header: HeaderType, prop: SigmaPropValue): ErgoTree = {
+ val constantStore = new ConstantStore()
+ val w = SigmaSerializer.startWriter(constantStore)
+ // serialize value and segregate constants into constantStore
+ ValueSerializer.serialize(prop, w)
+ val extractedConstants = constantStore.getAll
+ val r = SigmaSerializer.startReader(w.toBytes)
+ r.constantStore = new ConstantStore(extractedConstants)
+ // deserialize value with placeholders
+ val valueWithPlaceholders = ValueSerializer.deserialize(r).asSigmaProp
+ new ErgoTree(
+ header = setRequiredBits(setConstantSegregation(header)),
+ constants = extractedConstants,
+ root = Right(valueWithPlaceholders))
+ }
+
+ /** Deserializes an ErgoTree instance from a hexadecimal string.
+ *
+ * @param hex a hexadecimal string representing the serialized ErgoTree
+ */
+ def fromHex(hex: String): ErgoTree = {
+ val bytes = Base16.decode(hex).get
+ fromBytes(bytes)
+ }
+
+ /** Deserializes an ErgoTree instance from an array of bytes.
+ *
+ * @param bytes an array of bytes representing the serialized ErgoTree
+ */
+ def fromBytes(bytes: Array[Byte]): ErgoTree = {
+ ErgoTreeSerializer.DefaultSerializer.deserializeErgoTree(bytes)
+ }
+}
diff --git a/interpreter/shared/src/main/scala/sigmastate/JitCost.scala b/data/shared/src/main/scala/sigma/ast/JitCost.scala
similarity index 87%
rename from interpreter/shared/src/main/scala/sigmastate/JitCost.scala
rename to data/shared/src/main/scala/sigma/ast/JitCost.scala
index dd6d57fe9f..0b84dc21e2 100644
--- a/interpreter/shared/src/main/scala/sigmastate/JitCost.scala
+++ b/data/shared/src/main/scala/sigma/ast/JitCost.scala
@@ -1,11 +1,12 @@
-package sigmastate
+package sigma.ast
/** Represents cost estimation computed by JITC interpreter.
* The JITC costs use 10x more accurate scale comparing to block cost values.
*
* @see toBlockCost
*/
-case class JitCost private[sigmastate](private[sigmastate] val value: Int) extends AnyVal {
+// TODO make 'value` private[sigma] after code moved from sigmastate package
+case class JitCost private[sigma](val value: Int) extends AnyVal {
/** Adds two cost values. */
def +(y: JitCost): JitCost =
new JitCost(java7.compat.Math.addExact(value, y.value))
diff --git a/interpreter/shared/src/main/scala/sigmastate/interpreter/OperationDesc.scala b/data/shared/src/main/scala/sigma/ast/OperationDesc.scala
similarity index 93%
rename from interpreter/shared/src/main/scala/sigmastate/interpreter/OperationDesc.scala
rename to data/shared/src/main/scala/sigma/ast/OperationDesc.scala
index ca7fc9b217..06ba3391a8 100644
--- a/interpreter/shared/src/main/scala/sigmastate/interpreter/OperationDesc.scala
+++ b/data/shared/src/main/scala/sigma/ast/OperationDesc.scala
@@ -1,7 +1,4 @@
-package sigmastate.interpreter
-
-import sigmastate.{CostKind, SMethod}
-import sigmastate.Values.ValueCompanion
+package sigma.ast
/** Each costable operation is described in one of the following ways:
* 1) using [[ValueCompanion]] - operation with separate node class
diff --git a/interpreter/shared/src/main/scala/sigmastate/Operations.scala b/data/shared/src/main/scala/sigma/ast/Operations.scala
similarity index 99%
rename from interpreter/shared/src/main/scala/sigmastate/Operations.scala
rename to data/shared/src/main/scala/sigma/ast/Operations.scala
index 51ae277757..44804de84e 100644
--- a/interpreter/shared/src/main/scala/sigmastate/Operations.scala
+++ b/data/shared/src/main/scala/sigma/ast/Operations.scala
@@ -1,7 +1,7 @@
-package sigmastate
+package sigma.ast
-import sigmastate.lang.SigmaPredef.PredefinedFuncRegistry
-import sigmastate.lang.StdSigmaBuilder
+import sigma.serialization.CoreByteWriter.ArgInfo
+import SigmaPredef.PredefinedFuncRegistry
/** WARNING: This file is generated by GenInfoObjects tool.
* Don't edit it directly, use the tool instead to regenerate.
diff --git a/data/shared/src/main/scala/sigma/ast/SMethod.scala b/data/shared/src/main/scala/sigma/ast/SMethod.scala
new file mode 100644
index 0000000000..2d306d8948
--- /dev/null
+++ b/data/shared/src/main/scala/sigma/ast/SMethod.scala
@@ -0,0 +1,311 @@
+package sigma.ast
+
+import debox.cfor
+import sigma.ast.SMethod.{InvokeDescBuilder, MethodCostFunc}
+import sigma.ast.syntax._
+import sigma.data.RType
+import sigma.eval.{CostDetails, ErgoTreeEvaluator, GivenCost, TracedCost}
+import sigma.reflection.{RClass, RMethod}
+import sigma.serialization.CoreByteWriter.ArgInfo
+import sigma.validation.ValidationRules.CheckTypeWithMethods
+import sigma.{Coll, Evaluation}
+
+import scala.collection.compat.immutable.ArraySeq
+import scala.reflect.ClassTag
+
+/** Meta information which can be attached to SMethod.
+ * @param opDesc optional operation descriptor
+ * @param description human readable description of the method
+ * @param args one item for each argument */
+case class OperationInfo(opDesc: Option[ValueCompanion], description: String, args: Seq[ArgInfo]) {
+ def isFrontendOnly: Boolean = opDesc.isEmpty
+ def opTypeName: String = opDesc.map(_.typeName).getOrElse("(FRONTEND ONLY)")
+}
+
+object OperationInfo {
+ /** Convenience factory method. */
+ def apply(opDesc: ValueCompanion, description: String, args: Seq[ArgInfo]): OperationInfo =
+ OperationInfo(Some(opDesc), description, args)
+}
+
+/** Meta information connecting SMethod with ErgoTree.
+ * The optional builder is used by front-end ErgoScript compiler to replace method calls
+ * with ErgoTree nodes. In many cases [[SMethod.MethodCallIrBuilder]] builder is used.
+ * However there are specific cases where more complex builders are used, see for example
+ * usage of `withIRInfo` in the declaration of [[SCollection.GetOrElseMethod]].
+ * @param irBuilder optional method call recognizer and ErgoTree node builder.
+ * When the partial function is defined on a tuple
+ * (builder, obj, m, args, subst) it transforms it to a new ErgoTree
+ * node, which is then used in the resuting ErgoTree coming out of
+ * the ErgoScript compiler.
+ * @param javaMethod Java [[Method]] which should be used to evaluate
+ * [[sigmastate.lang.Terms.MethodCall]] node of ErgoTree.
+ * @param invokeDescsBuilder optional builder of additional type descriptors (see extraDescriptors)
+ */
+case class MethodIRInfo(
+ irBuilder: Option[PartialFunction[(SigmaBuilder, SValue, SMethod, Seq[SValue], STypeSubst), SValue]],
+ javaMethod: Option[RMethod],
+ invokeDescsBuilder: Option[InvokeDescBuilder]
+)
+
+/** Represents method descriptor.
+ *
+ * @param objType type or type constructor descriptor
+ * @param name method name
+ * @param stype method signature type,
+ * where `stype.tDom`` - argument type and
+ * `stype.tRange` - method result type.
+ * @param methodId method code, it should be unique among methods of the same objType.
+ * @param costKind cost descriptor for this method
+ * @param irInfo meta information connecting SMethod with ErgoTree (see [[MethodIRInfo]])
+ * @param docInfo optional human readable method description data
+ * @param costFunc optional specification of how the cost should be computed for the
+ * given method call (See ErgoTreeEvaluator.calcCost method).
+ */
+case class SMethod(
+ objType: MethodsContainer,
+ name: String,
+ stype: SFunc,
+ methodId: Byte,
+ costKind: CostKind,
+ irInfo: MethodIRInfo,
+ docInfo: Option[OperationInfo],
+ costFunc: Option[MethodCostFunc]) {
+
+ /** Operation descriptor of this method. */
+ lazy val opDesc = MethodDesc(this)
+
+ /** Finds and keeps the [[RMethod]] instance which corresponds to this method descriptor.
+ * The lazy value is forced only if irInfo.javaMethod == None
+ */
+ lazy val javaMethod: RMethod = {
+ irInfo.javaMethod.getOrElse {
+ val paramTypes = stype.tDom.drop(1).map(t => t match {
+ case _: STypeVar => classOf[AnyRef]
+ case _: SFunc => classOf[_ => _]
+ case _ => Evaluation.stypeToRType(t).classTag.runtimeClass
+ }).toArray
+ val m = objType.ownerType.reprClass.getMethod(name, paramTypes:_*)
+ m
+ }
+ }
+
+ /** Additional type descriptors, which are necessary to perform invocation of Method
+ * associated with this instance.
+ * @see MethodCall.eval
+ */
+ lazy val extraDescriptors: Seq[RType[_]] = {
+ irInfo.invokeDescsBuilder match {
+ case Some(builder) =>
+ builder(stype).map(Evaluation.stypeToRType)
+ case None =>
+ ArraySeq.empty[RType[_]]
+ }
+ }
+
+ /** Invoke this method on the given object with the arguments.
+ * This is used for methods with FixedCost costKind. */
+ def invokeFixed(obj: Any, args: Array[Any])(implicit E: ErgoTreeEvaluator): Any = {
+ javaMethod.invoke(obj, args.asInstanceOf[Array[AnyRef]]:_*)
+ }
+
+ // TODO optimize: avoid lookup when this SMethod is created via `specializeFor`
+ /** Return generic template of this method. */
+ @inline final def genericMethod: SMethod = {
+ objType.getMethodById(methodId).get
+ }
+
+ /** Returns refection [[RMethod]] which must be invoked to evaluate this method.
+ * The method is resolved by its name using `name + "_eval"` naming convention.
+ * @see `map_eval`, `flatMap_eval` and other `*_eval` methods.
+ * @hotspot don't beautify the code */
+ lazy val evalMethod: RMethod = {
+ val argTypes = stype.tDom
+ val nArgs = argTypes.length
+ val paramTypes = new Array[Class[_]](nArgs + 2)
+ paramTypes(0) = classOf[MethodCall]
+ cfor(0)(_ < nArgs, _ + 1) { i =>
+ paramTypes(i + 1) = argTypes(i) match {
+ case _: STypeVar => classOf[AnyRef]
+ case _: SFunc => classOf[_ => _]
+ case _: SCollectionType[_] => classOf[Coll[_]]
+ case _: SOption[_] => classOf[Option[_]]
+ case t =>
+ Evaluation.stypeToRType(t).classTag.runtimeClass
+ }
+ }
+ paramTypes(paramTypes.length - 1) = classOf[ErgoTreeEvaluator]
+
+ val methodName = name + "_eval"
+ val m = try {
+ objType.thisRClass.getMethod(methodName, paramTypes:_*)
+ }
+ catch { case e: NoSuchMethodException =>
+ throw new RuntimeException(s"Cannot find eval method def $methodName(${Seq(paramTypes:_*)})", e)
+ }
+ m
+ }
+
+ /** Create a new instance with the given stype. */
+ def withSType(newSType: SFunc): SMethod = copy(stype = newSType)
+
+ /** Create a new instance with the given cost function. */
+ def withCost(costFunc: MethodCostFunc): SMethod = copy(costFunc = Some(costFunc))
+
+ /** Create a new instance in which the `stype` field transformed using
+ * the given substitution. */
+ def withConcreteTypes(subst: Map[STypeVar, SType]): SMethod =
+ withSType(stype.withSubstTypes(subst).asFunc)
+
+ /** Name of a language operation represented by this method. */
+ def opName = objType.getClass.getSimpleName + "." + name
+
+ /** Specializes this instance by creating a new [[SMethod]] instance where signature
+ * is specialized with respect to the given object and args types. It is used in
+ * [[sigmastate.serialization.MethodCallSerializer]] `parse` method, so it is part of
+ * consensus protocol.
+ *
+ * @param objTpe specific type of method receiver (aka object)
+ * @param args specific types of method arguments
+ * @return new instance of method descriptor with specialized signature
+ * @consensus
+ */
+ def specializeFor(objTpe: SType, args: Seq[SType]): SMethod = {
+ unifyTypeLists(stype.tDom, objTpe +: args) match {
+ case Some(subst) if subst.nonEmpty =>
+ withConcreteTypes(subst)
+ case _ => this
+ }
+ }
+
+ /** Create a new instance with the given [[OperationInfo]] parameters. */
+ def withInfo(opDesc: ValueCompanion, desc: String, args: ArgInfo*): SMethod = {
+ this.copy(docInfo = Some(OperationInfo(opDesc, desc, ArgInfo("this", "this instance") +: args.toSeq)))
+ }
+
+ /** Create a new instance with the given [[OperationInfo]] parameters.
+ * NOTE: opDesc parameter is not defined and falls back to None.
+ */
+ def withInfo(desc: String, args: ArgInfo*): SMethod = {
+ this.copy(docInfo = Some(OperationInfo(None, desc, ArgInfo("this", "this instance") +: args.toSeq)))
+ }
+
+ /** Create a new instance with the given IR builder (aka MethodCall rewriter) parameter. */
+ def withIRInfo(
+ irBuilder: PartialFunction[(SigmaBuilder, SValue, SMethod, Seq[SValue], STypeSubst), SValue],
+ javaMethod: RMethod = null,
+ invokeHandler: InvokeDescBuilder = null): SMethod = {
+ this.copy(irInfo = MethodIRInfo(Some(irBuilder), Option(javaMethod), Option(invokeHandler)))
+ }
+
+ /** Lookup [[ArgInfo]] for the given argName or throw an exception. */
+ def argInfo(argName: String): ArgInfo =
+ docInfo.get.args.find(_.name == argName).get
+}
+
+
+object SMethod {
+ /** Type of functions used to assign cost to method call nodes.
+ * For a function `f: (mc, obj, args) => cost` it is called before the evaluation of
+ * the `mc` node with the given `obj` as method receiver and `args` as method
+ * arguments.
+ */
+ abstract class MethodCostFunc extends Function4[ErgoTreeEvaluator, MethodCall, Any, Array[Any], CostDetails] {
+ /**
+ * The function returns an estimated cost of evaluation BEFORE actual evaluation of
+ * the method. For this reason [[MethodCostFunc]] is not used for higher-order
+ * operations like `Coll.map`, `Coll.filter` etc.
+ */
+ def apply(E: ErgoTreeEvaluator, mc: MethodCall, obj: Any, args: Array[Any]): CostDetails
+ }
+
+ /** Returns a cost function which always returs the given cost. */
+ def givenCost(costKind: FixedCost): MethodCostFunc = new MethodCostFunc {
+ override def apply(E: ErgoTreeEvaluator,
+ mc: MethodCall,
+ obj: Any, args: Array[Any]): CostDetails = {
+ if (E.settings.costTracingEnabled)
+ TracedCost(Array(FixedCostItem(MethodDesc(mc.method), costKind)))
+ else
+ GivenCost(costKind.cost)
+ }
+ }
+
+ /** Returns a cost function which expects `obj` to be of `Coll[T]` type and
+ * uses its length to compute SeqCostItem */
+ def perItemCost(costKind: PerItemCost): MethodCostFunc = new MethodCostFunc {
+ override def apply(E: ErgoTreeEvaluator,
+ mc: MethodCall,
+ obj: Any, args: Array[Any]): CostDetails = obj match {
+ case coll: Coll[a] =>
+ if (E.settings.costTracingEnabled) {
+ val desc = MethodDesc(mc.method)
+ TracedCost(Array(SeqCostItem(desc, costKind, coll.length)))
+ }
+ else
+ GivenCost(costKind.cost(coll.length))
+ case _ =>
+ sys.error(
+ s"Invalid object $obj of method call $mc: Coll type is expected")
+ }
+ }
+
+ /** Some runtime methods (like Coll.map, Coll.flatMap) require additional RType descriptors.
+ * The builder can extract those descriptors from the given type of the method signature.
+ */
+ type InvokeDescBuilder = SFunc => Seq[SType]
+
+ /** Return [[Method]] descriptor for the given `methodName` on the given `cT` type.
+ * @param methodName the name of the method to lookup
+ * @param cT the class where to search the methodName
+ * @param cA1 the class of the method argument
+ */
+ def javaMethodOf[T, A1](methodName: String)
+ (implicit cT: ClassTag[T], cA1: ClassTag[A1]): RMethod =
+ RClass(cT.runtimeClass).getMethod(methodName, cA1.runtimeClass)
+
+ /** Return [[Method]] descriptor for the given `methodName` on the given `cT` type.
+ * @param methodName the name of the method to lookup
+ * @param cT the class where to search the methodName
+ * @param cA1 the class of the method's first argument
+ * @param cA2 the class of the method's second argument
+ */
+ def javaMethodOf[T, A1, A2]
+ (methodName: String)
+ (implicit cT: ClassTag[T], cA1: ClassTag[A1], cA2: ClassTag[A2]): RMethod =
+ RClass(cT.runtimeClass).getMethod(methodName, cA1.runtimeClass, cA2.runtimeClass)
+
+ /** Default fallback method call recognizer which builds MethodCall ErgoTree nodes. */
+ val MethodCallIrBuilder: PartialFunction[(SigmaBuilder, SValue, SMethod, Seq[SValue], STypeSubst), SValue] = {
+ case (builder, obj, method, args, tparamSubst) =>
+ builder.mkMethodCall(obj, method, args.toIndexedSeq, tparamSubst)
+ }
+
+ /** Convenience factory method. */
+ def apply(objType: MethodsContainer, name: String, stype: SFunc,
+ methodId: Byte,
+ costKind: CostKind): SMethod = {
+ SMethod(
+ objType, name, stype, methodId, costKind,
+ MethodIRInfo(None, None, None), None, None)
+ }
+
+
+ /** Looks up [[SMethod]] instance for the given type and method ids.
+ *
+ * @param typeId id of a type which can contain methods
+ * @param methodId id of a method of the type given by `typeId`
+ * @return an instance of [[SMethod]] which may contain generic type variables in the
+ * signature (see SMethod.stype). As a result `specializeFor` is called by
+ * deserializer to obtain monomorphic method descriptor.
+ * @consensus this is method is used in [[sigmastate.serialization.MethodCallSerializer]]
+ * `parse` method and hence it is part of consensus protocol
+ */
+ def fromIds(typeId: Byte, methodId: Byte): SMethod = {
+ CheckTypeWithMethods(typeId, MethodsContainer.contains(typeId))
+ val container = MethodsContainer(typeId)
+ val method = container.methodById(methodId)
+ method
+ }
+}
+
diff --git a/interpreter/shared/src/main/scala/sigmastate/lang/SigmaBuilder.scala b/data/shared/src/main/scala/sigma/ast/SigmaBuilder.scala
similarity index 98%
rename from interpreter/shared/src/main/scala/sigmastate/lang/SigmaBuilder.scala
rename to data/shared/src/main/scala/sigma/ast/SigmaBuilder.scala
index 8d87d8ffce..cafba5f6b6 100644
--- a/interpreter/shared/src/main/scala/sigmastate/lang/SigmaBuilder.scala
+++ b/data/shared/src/main/scala/sigma/ast/SigmaBuilder.scala
@@ -1,20 +1,16 @@
-package sigmastate.lang
+package sigma.ast
import debox.cfor
import org.ergoplatform.ErgoBox.RegisterId
+import sigma.ast.Constraints._
+import sigma.ast.SCollection.{SByteArray, SIntArray}
+import sigma.ast.SOption.SIntOption
+import sigma.ast.syntax._
import sigma.data.Nullable
-import sigma.{AnyValue, Coll, Colls, Environment}
-import sigmastate.SCollection.{SByteArray, SIntArray}
-import sigmastate.SOption.SIntOption
-import sigmastate.Values._
-import sigmastate._
-import sigmastate.eval._
-import sigmastate.exceptions.ConstraintFailed
-import sigmastate.lang.Constraints._
-import sigmastate.lang.Terms.{STypeSubst, _}
-import sigmastate.serialization.OpCodes
-import sigmastate.serialization.OpCodes.OpCode
-import sigmastate.utxo._
+import sigma.exceptions.ConstraintFailed
+import sigma.serialization.OpCodes
+import sigma.serialization.ValueCodes.OpCode
+import sigma.{AnyValue, Coll, Colls, Environment, Evaluation, Platform}
import scala.util.DynamicVariable
diff --git a/interpreter/shared/src/main/scala/sigmastate/lang/SigmaPredef.scala b/data/shared/src/main/scala/sigma/ast/SigmaPredef.scala
similarity index 97%
rename from interpreter/shared/src/main/scala/sigmastate/lang/SigmaPredef.scala
rename to data/shared/src/main/scala/sigma/ast/SigmaPredef.scala
index 5b1d3dc2ca..5cdbdedaa8 100644
--- a/interpreter/shared/src/main/scala/sigmastate/lang/SigmaPredef.scala
+++ b/data/shared/src/main/scala/sigma/ast/SigmaPredef.scala
@@ -1,17 +1,16 @@
-package sigmastate.lang
+package sigma.ast
import org.ergoplatform.ErgoAddressEncoder.NetworkPrefix
import org.ergoplatform.{ErgoAddressEncoder, P2PKAddress}
+import scorex.util.encode.{Base16, Base58, Base64}
+import sigma.ast.SCollection.{SByteArray, SIntArray}
+import sigma.ast.SOption.SIntOption
+import sigma.ast.SigmaPropConstant
+import sigma.ast.syntax._
import sigma.data.Nullable
-import scorex.util.encode.{Base64, Base58, Base16}
-import sigmastate.SCollection.{SIntArray, SByteArray}
-import sigmastate.SOption._
-import sigmastate.Values.{StringConstant, SValue, IntValue, SigmaPropConstant, Value, ByteArrayConstant, SigmaPropValue, ValueCompanion, Constant, EvaluatedValue, ConstantPlaceholder, BoolValue}
-import sigmastate._
-import sigmastate.lang.Terms._
-import sigmastate.exceptions.InvalidArguments
-import sigmastate.serialization.ValueSerializer
-import sigmastate.utxo.{DeserializeRegister, SelectField, DeserializeContext, GetVar}
+import sigma.exceptions.InvalidArguments
+import sigma.serialization.CoreByteWriter.ArgInfo
+import sigma.serialization.ValueSerializer
object SigmaPredef {
@@ -44,7 +43,7 @@ object SigmaPredef {
import builder._
/** Type variable used in the signatures of global functions below. */
- import SType.{tT, tO, tR, tL, paramR, paramT, tK}
+ import SType.{paramR, paramT, tK, tL, tO, tR, tT}
private val undefined: IrBuilderFunc =
PartialFunction.empty[(SValue, Seq[SValue]), SValue]
@@ -152,7 +151,7 @@ object SigmaPredef {
{ case (_, Seq(arg: EvaluatedValue[SString.type]@unchecked)) =>
ErgoAddressEncoder(networkPrefix).fromString(arg.value).get match {
case a: P2PKAddress => SigmaPropConstant(a.pubkey)
- case a@_ => sys.error(s"unsupported address $a")
+ case a => sys.error(s"unsupported address $a")
}
}),
OperationInfo(Constant, "",
diff --git a/interpreter/shared/src/main/scala/sigmastate/lang/SourceContext.scala b/data/shared/src/main/scala/sigma/ast/SourceContext.scala
similarity index 97%
rename from interpreter/shared/src/main/scala/sigmastate/lang/SourceContext.scala
rename to data/shared/src/main/scala/sigma/ast/SourceContext.scala
index 2c814bdbdb..f9441e1a52 100644
--- a/interpreter/shared/src/main/scala/sigmastate/lang/SourceContext.scala
+++ b/data/shared/src/main/scala/sigma/ast/SourceContext.scala
@@ -1,4 +1,4 @@
-package sigmastate.lang
+package sigma.ast
import fastparse.Parsed.Failure
diff --git a/data/shared/src/main/scala/sigma/ast/methods.scala b/data/shared/src/main/scala/sigma/ast/methods.scala
new file mode 100644
index 0000000000..b637acf792
--- /dev/null
+++ b/data/shared/src/main/scala/sigma/ast/methods.scala
@@ -0,0 +1,1508 @@
+package sigma.ast
+
+import org.ergoplatform._
+import org.ergoplatform.validation._
+import sigma._
+import sigma.ast.SCollection.{SBooleanArray, SBoxArray, SByteArray, SByteArray2, SHeaderArray}
+import sigma.ast.SMethod.{MethodCallIrBuilder, MethodCostFunc, javaMethodOf}
+import sigma.ast.SType.TypeCode
+import sigma.ast.syntax.{SValue, ValueOps}
+import sigma.data.OverloadHack.Overloaded1
+import sigma.data.{DataValueComparer, KeyValueColl, Nullable, RType, SigmaConstants}
+import sigma.eval.{CostDetails, ErgoTreeEvaluator, TracedCost}
+import sigma.reflection.RClass
+import sigma.serialization.CoreByteWriter.ArgInfo
+import sigma.utils.SparseArrayContainer
+
+import scala.annotation.unused
+import scala.language.implicitConversions
+
+/** Base type for all companions of AST nodes of sigma lang. */
+trait SigmaNodeCompanion
+
+/** Defines recognizer method which allows the derived object to be used in patterns
+ * to recognize method descriptors by method name.
+ * @see SCollecton
+ */
+trait MethodByNameUnapply extends MethodsContainer {
+ def unapply(methodName: String): Option[SMethod] = methods.find(_.name == methodName)
+}
+
+/** Base trait for all method containers (which store methods and properties) */
+sealed trait MethodsContainer {
+ /** Type for which this container defines methods. */
+ def ownerType: STypeCompanion
+
+ override def toString: String =
+ getClass.getSimpleName.stripSuffix("$") // e.g. SInt, SCollection, etc
+
+ /** Represents class of `this`. */
+ lazy val thisRClass: RClass[_] = RClass(this.getClass)
+ def typeId: Byte = ownerType.typeId
+ def typeName: String = ownerType.typeName
+
+ /** Returns -1 if `method` is not found. */
+ def methodIndex(name: String): Int = methods.indexWhere(_.name == name)
+
+ /** Returns true if this type has a method with the given name. */
+ def hasMethod(name: String): Boolean = methodIndex(name) != -1
+
+ /** This method should be overriden in derived classes to add new methods in addition to inherited.
+ * Typical override: `super.getMethods() ++ Seq(m1, m2, m3)`
+ */
+ protected def getMethods(): Seq[SMethod] = Nil
+
+ /** Returns all the methods of this type. */
+ lazy val methods: Seq[SMethod] = {
+ val ms = getMethods().toArray
+ assert(ms.map(_.name).distinct.length == ms.length, s"Duplicate method names in $this")
+ ms.groupBy(_.objType).foreach { case (comp, ms) =>
+ assert(ms.map(_.methodId).distinct.length == ms.length, s"Duplicate method ids in $comp: $ms")
+ }
+ ms
+ }
+ private lazy val _methodsMap: Map[Byte, Map[Byte, SMethod]] = methods
+ .groupBy(_.objType.typeId)
+ .map { case (typeId, ms) => (typeId -> ms.map(m => m.methodId -> m).toMap) }
+
+ /** Lookup method by its id in this type. */
+ @inline def getMethodById(methodId: Byte): Option[SMethod] =
+ _methodsMap.get(typeId) match {
+ case Some(ms) => ms.get(methodId)
+ case None => None
+ }
+
+ /** Lookup method in this type by method's id or throw ValidationException.
+ * This method can be used in trySoftForkable section to either obtain valid method
+ * or catch ValidatioinException which can be checked for soft-fork condition.
+ * It delegate to getMethodById to lookup method.
+ *
+ * @see getMethodById
+ */
+ def methodById(methodId: Byte): SMethod = {
+ ValidationRules.CheckAndGetMethod(this, methodId)
+ }
+
+ /** Finds a method descriptor [[SMethod]] for the given name. */
+ def method(methodName: String): Option[SMethod] = methods.find(_.name == methodName)
+
+ /** Looks up the method descriptor by the method name. */
+ def getMethodByName(name: String): SMethod = methods.find(_.name == name).get
+
+}
+object MethodsContainer {
+ private val containers = new SparseArrayContainer[MethodsContainer](Array(
+ SByteMethods,
+ SShortMethods,
+ SIntMethods,
+ SLongMethods,
+ SBigIntMethods,
+ SBooleanMethods,
+ SStringMethods,
+ SGroupElementMethods,
+ SSigmaPropMethods,
+ SBoxMethods,
+ SAvlTreeMethods,
+ SHeaderMethods,
+ SPreHeaderMethods,
+ SGlobalMethods,
+ SContextMethods,
+ SCollectionMethods,
+ SOptionMethods,
+ STupleMethods,
+ SUnitMethods,
+ SAnyMethods
+ ).map(m => (m.typeId, m)))
+
+ def contains(typeId: TypeCode): Boolean = containers.contains(typeId)
+
+ def apply(typeId: TypeCode): MethodsContainer = containers(typeId)
+
+ /** Finds the method of the give type.
+ *
+ * @param tpe type of the object for which the method is looked up
+ * @param methodName name of the method
+ * @return method descriptor or None if not found
+ */
+ def getMethod(tpe: SType, methodName: String): Option[SMethod] = tpe match {
+ case tup: STuple =>
+ STupleMethods.getTupleMethod(tup, methodName)
+ case _ =>
+ containers.get(tpe.typeCode).flatMap(_.method(methodName))
+ }
+}
+
+trait MonoTypeMethods extends MethodsContainer {
+ def ownerType: SMonoType
+ /** Helper method to create method descriptors for properties (i.e. methods without args). */
+ protected def propertyCall(
+ name: String,
+ tpeRes: SType,
+ id: Byte,
+ costKind: CostKind): SMethod =
+ SMethod(this, name, SFunc(this.ownerType, tpeRes), id, costKind)
+ .withIRInfo(MethodCallIrBuilder)
+ .withInfo(PropertyCall, "")
+
+ /** Helper method to create method descriptors for properties (i.e. methods without args). */
+ protected def property(
+ name: String,
+ tpeRes: SType,
+ id: Byte,
+ valueCompanion: ValueCompanion): SMethod =
+ SMethod(this, name, SFunc(this.ownerType, tpeRes), id, valueCompanion.costKind)
+ .withIRInfo(MethodCallIrBuilder)
+ .withInfo(valueCompanion, "")
+}
+
+trait SNumericTypeMethods extends MonoTypeMethods {
+ import SNumericTypeMethods.tNum
+ protected override def getMethods(): Seq[SMethod] = {
+ super.getMethods() ++ SNumericTypeMethods.methods.map {
+ m => m.copy(stype = applySubst(m.stype, Map(tNum -> this.ownerType)).asFunc)
+ }
+ }
+}
+
+object SNumericTypeMethods extends MethodsContainer {
+ /** Type for which this container defines methods. */
+ override def ownerType: STypeCompanion = SNumericType
+
+ /** Type variable used in generic signatures of method descriptors. */
+ val tNum = STypeVar("TNum")
+
+ /** Cost function which is assigned for numeric cast MethodCall nodes in ErgoTree.
+ * It is called as part of MethodCall.eval method. */
+ val costOfNumericCast: MethodCostFunc = new MethodCostFunc {
+ override def apply(
+ E: ErgoTreeEvaluator,
+ mc: MethodCall,
+ obj: Any,
+ args: Array[Any]): CostDetails = {
+ val targetTpe = mc.method.stype.tRange
+ val cast = getNumericCast(mc.obj.tpe, mc.method.name, targetTpe).get
+ val costKind = if (cast == Downcast) Downcast.costKind else Upcast.costKind
+ TracedCost(Array(TypeBasedCostItem(MethodDesc(mc.method), costKind, targetTpe)))
+ }
+ }
+
+ /** The following SMethod instances are descriptors of methods available on all numeric
+ * types.
+ *
+ * @see `val methods` below
+ * */
+ val ToByteMethod : SMethod = SMethod(this, "toByte", SFunc(tNum, SByte), 1, null)
+ .withCost(costOfNumericCast)
+ .withInfo(PropertyCall, "Converts this numeric value to \\lst{Byte}, throwing exception if overflow.")
+
+ val ToShortMethod : SMethod = SMethod(this, "toShort", SFunc(tNum, SShort), 2, null)
+ .withCost(costOfNumericCast)
+ .withInfo(PropertyCall, "Converts this numeric value to \\lst{Short}, throwing exception if overflow.")
+
+ val ToIntMethod : SMethod = SMethod(this, "toInt", SFunc(tNum, SInt), 3, null)
+ .withCost(costOfNumericCast)
+ .withInfo(PropertyCall, "Converts this numeric value to \\lst{Int}, throwing exception if overflow.")
+
+ val ToLongMethod : SMethod = SMethod(this, "toLong", SFunc(tNum, SLong), 4, null)
+ .withCost(costOfNumericCast)
+ .withInfo(PropertyCall, "Converts this numeric value to \\lst{Long}, throwing exception if overflow.")
+
+ val ToBigIntMethod: SMethod = SMethod(this, "toBigInt", SFunc(tNum, SBigInt), 5, null)
+ .withCost(costOfNumericCast)
+ .withInfo(PropertyCall, "Converts this numeric value to \\lst{BigInt}")
+
+ /** Cost of: 1) creating Byte collection from a numeric value */
+ val ToBytes_CostKind = FixedCost(JitCost(5))
+
+ val ToBytesMethod: SMethod = SMethod(
+ this, "toBytes", SFunc(tNum, SByteArray), 6, ToBytes_CostKind)
+ .withIRInfo(MethodCallIrBuilder)
+ .withInfo(PropertyCall,
+ """ Returns a big-endian representation of this numeric value in a collection of bytes.
+ | For example, the \lst{Int} value \lst{0x12131415} would yield the
+ | collection of bytes \lst{[0x12, 0x13, 0x14, 0x15]}.
+ """.stripMargin)
+
+ /** Cost of: 1) creating Boolean collection (one bool for each bit) from a numeric
+ * value. */
+ val ToBits_CostKind = FixedCost(JitCost(5))
+
+ val ToBitsMethod: SMethod = SMethod(
+ this, "toBits", SFunc(tNum, SBooleanArray), 7, ToBits_CostKind)
+ .withIRInfo(MethodCallIrBuilder)
+ .withInfo(PropertyCall,
+ """ Returns a big-endian representation of this numeric in a collection of Booleans.
+ | Each boolean corresponds to one bit.
+ """.stripMargin)
+
+ protected override def getMethods: Seq[SMethod] = Array(
+ ToByteMethod, // see Downcast
+ ToShortMethod, // see Downcast
+ ToIntMethod, // see Downcast
+ ToLongMethod, // see Downcast
+ ToBigIntMethod, // see Downcast
+ ToBytesMethod,
+ ToBitsMethod
+ )
+
+ /** Collection of names of numeric casting methods (like `toByte`, `toInt`, etc). */
+ val castMethods: Array[String] =
+ Array(ToByteMethod, ToShortMethod, ToIntMethod, ToLongMethod, ToBigIntMethod)
+ .map(_.name)
+
+ /** Checks the given name is numeric type cast method (like toByte, toInt, etc.). */
+ def isCastMethod(name: String): Boolean = castMethods.contains(name)
+
+ /** Convert the given method to a cast operation from fromTpe to resTpe. */
+ def getNumericCast(
+ fromTpe: SType,
+ methodName: String,
+ resTpe: SType): Option[NumericCastCompanion] = (fromTpe, resTpe) match {
+ case (from: SNumericType, to: SNumericType) if isCastMethod(methodName) =>
+ val op = if (to > from) Upcast else Downcast
+ Some(op)
+ case _ => None // the method in not numeric type cast
+ }
+
+}
+
+/** Methods of ErgoTree type `Boolean`. */
+case object SBooleanMethods extends MonoTypeMethods {
+ /** Type for which this container defines methods. */
+ override def ownerType: SMonoType = SBoolean
+
+ val ToByte = "toByte"
+ protected override def getMethods() = super.getMethods()
+ /* TODO soft-fork: https://github.com/ScorexFoundation/sigmastate-interpreter/issues/479
+ ++ Seq(
+ SMethod(this, ToByte, SFunc(this, SByte), 1)
+ .withInfo(PropertyCall, "Convert true to 1 and false to 0"),
+ )
+ */
+}
+
+/** Methods of ErgoTree type `Byte`. */
+case object SByteMethods extends SNumericTypeMethods {
+ /** Type for which this container defines methods. */
+ override def ownerType: SMonoType = SByte
+}
+
+/** Methods of ErgoTree type `Short`. */
+case object SShortMethods extends SNumericTypeMethods {
+ /** Type for which this container defines methods. */
+ override def ownerType: SMonoType = ast.SShort
+}
+
+/** Descriptor of ErgoTree type `Int`. */
+case object SIntMethods extends SNumericTypeMethods {
+ /** Type for which this container defines methods. */
+ override def ownerType: SMonoType = SInt
+}
+
+/** Descriptor of ErgoTree type `Long`. */
+case object SLongMethods extends SNumericTypeMethods {
+ /** Type for which this container defines methods. */
+ override def ownerType: SMonoType = SLong
+}
+
+/** Methods of BigInt type. Implemented using [[java.math.BigInteger]]. */
+case object SBigIntMethods extends SNumericTypeMethods {
+ /** Type for which this container defines methods. */
+ override def ownerType: SMonoType = SBigInt
+
+ /** The following `modQ` methods are not fully implemented in v4.x and this descriptors.
+ * This descritors are remain here in the code and are waiting for full implementation
+ * is upcoming soft-forks at which point the cost parameters should be calculated and
+ * changed.
+ */
+ val ModQMethod = SMethod(this, "modQ", SFunc(this.ownerType, SBigInt), 1, FixedCost(JitCost(1)))
+ .withInfo(ModQ, "Returns this \\lst{mod} Q, i.e. remainder of division by Q, where Q is an order of the cryprographic group.")
+ val PlusModQMethod = SMethod(this, "plusModQ", SFunc(IndexedSeq(this.ownerType, SBigInt), SBigInt), 2, FixedCost(JitCost(1)))
+ .withInfo(ModQArithOp.PlusModQ, "Adds this number with \\lst{other} by module Q.", ArgInfo("other", "Number to add to this."))
+ val MinusModQMethod = SMethod(this, "minusModQ", SFunc(IndexedSeq(this.ownerType, SBigInt), SBigInt), 3, FixedCost(JitCost(1)))
+ .withInfo(ModQArithOp.MinusModQ, "Subtracts \\lst{other} number from this by module Q.", ArgInfo("other", "Number to subtract from this."))
+ val MultModQMethod = SMethod(this, "multModQ", SFunc(IndexedSeq(this.ownerType, SBigInt), SBigInt), 4, FixedCost(JitCost(1)))
+ .withIRInfo(MethodCallIrBuilder)
+ .withInfo(MethodCall, "Multiply this number with \\lst{other} by module Q.", ArgInfo("other", "Number to multiply with this."))
+
+ protected override def getMethods() = super.getMethods() ++ Seq(
+// ModQMethod,
+// PlusModQMethod,
+// MinusModQMethod,
+ // TODO soft-fork: https://github.com/ScorexFoundation/sigmastate-interpreter/issues/479
+ // MultModQMethod,
+ )
+}
+
+/** Methods of type `String`. */
+case object SStringMethods extends MonoTypeMethods {
+ /** Type for which this container defines methods. */
+ override def ownerType: SMonoType = SString
+}
+
+/** Methods of type `GroupElement`. */
+case object SGroupElementMethods extends MonoTypeMethods {
+ /** Type for which this container defines methods. */
+ override def ownerType: SMonoType = SGroupElement
+
+ /** Cost of: 1) serializing EcPointType to bytes 2) packing them in Coll. */
+ val GetEncodedCostKind = FixedCost(JitCost(250))
+
+ /** The following SMethod instances are descriptors of methods defined in `GroupElement` type. */
+ lazy val GetEncodedMethod: SMethod = SMethod(
+ this, "getEncoded", SFunc(Array(this.ownerType), SByteArray), 2, GetEncodedCostKind)
+ .withIRInfo(MethodCallIrBuilder)
+ .withInfo(PropertyCall, "Get an encoding of the point value.")
+
+ lazy val ExponentiateMethod: SMethod = SMethod(
+ this, "exp", SFunc(Array(this.ownerType, SBigInt), this.ownerType), 3, Exponentiate.costKind)
+ .withIRInfo({ case (builder, obj, _, Seq(arg), _) =>
+ builder.mkExponentiate(obj.asGroupElement, arg.asBigInt)
+ })
+ .withInfo(Exponentiate,
+ "Exponentiate this \\lst{GroupElement} to the given number. Returns this to the power of k",
+ ArgInfo("k", "The power"))
+
+ lazy val MultiplyMethod: SMethod = SMethod(
+ this, "multiply", SFunc(Array(this.ownerType, SGroupElement), this.ownerType), 4, MultiplyGroup.costKind)
+ .withIRInfo({ case (builder, obj, _, Seq(arg), _) =>
+ builder.mkMultiplyGroup(obj.asGroupElement, arg.asGroupElement)
+ })
+ .withInfo(MultiplyGroup, "Group operation.", ArgInfo("other", "other element of the group"))
+
+ /** Cost of: 1) calling EcPoint.negate 2) wrapping in GroupElement. */
+ val Negate_CostKind = FixedCost(JitCost(45))
+
+ lazy val NegateMethod: SMethod = SMethod(
+ this, "negate", SFunc(this.ownerType, this.ownerType), 5, Negate_CostKind)
+ .withIRInfo(MethodCallIrBuilder)
+ .withInfo(PropertyCall, "Inverse element of the group.")
+
+ protected override def getMethods(): Seq[SMethod] = super.getMethods() ++ Seq(
+ /* TODO soft-fork: https://github.com/ScorexFoundation/sigmastate-interpreter/issues/479
+ SMethod(this, "isIdentity", SFunc(this, SBoolean), 1)
+ .withInfo(PropertyCall, "Checks if this value is identity element of the eliptic curve group."),
+ */
+ GetEncodedMethod,
+ ExponentiateMethod,
+ MultiplyMethod,
+ NegateMethod
+ )
+}
+
+/** Methods of type `SigmaProp` which represent sigma-protocol propositions. */
+case object SSigmaPropMethods extends MonoTypeMethods {
+ /** Type for which this container defines methods. */
+ override def ownerType: SMonoType = SSigmaProp
+
+ /** The maximum size of SigmaProp value in serialized byte array representation. */
+ val MaxSizeInBytes: Long = SigmaConstants.MaxSigmaPropSizeInBytes.value
+
+ val PropBytes = "propBytes"
+ val IsProven = "isProven"
+ lazy val PropBytesMethod = SMethod(
+ this, PropBytes, SFunc(this.ownerType, SByteArray), 1, SigmaPropBytes.costKind)
+ .withInfo(SigmaPropBytes, "Serialized bytes of this sigma proposition taken as ErgoTree.")
+
+ lazy val IsProvenMethod = SMethod(this, IsProven, SFunc(this.ownerType, SBoolean), 2, null)
+ .withInfo(// available only at frontend of ErgoScript
+ "Verify that sigma proposition is proven.")
+
+ protected override def getMethods() = super.getMethods() ++ Seq(
+ PropBytesMethod, IsProvenMethod
+ )
+}
+
+/** Any other type is implicitly subtype of this type. */
+case object SAnyMethods extends MonoTypeMethods {
+ override def ownerType: SMonoType = SAny
+}
+
+/** The type with single inhabitant value `()` */
+case object SUnitMethods extends MonoTypeMethods {
+ /** Type for which this container defines methods. */
+ override def ownerType = SUnit
+}
+
+object SOptionMethods extends MethodsContainer {
+ /** Type for which this container defines methods. */
+ override def ownerType: STypeCompanion = SOption
+
+ /** Code of `Option[_]` type constructor. */
+ val OptionTypeConstrId = 3
+ /** Type code for `Option[T] for some T` type used in TypeSerializer. */
+ val OptionTypeCode: TypeCode = ((SPrimType.MaxPrimTypeCode + 1) * OptionTypeConstrId).toByte
+ /** Code of `Option[Coll[_]]` type constructor. */
+ val OptionCollectionTypeConstrId = 4
+ /** Type code for `Option[Coll[T]] for some T` type used in TypeSerializer. */
+ val OptionCollectionTypeCode: TypeCode = ((SPrimType.MaxPrimTypeCode + 1) * OptionCollectionTypeConstrId).toByte
+
+ val IsDefined = "isDefined"
+ val Get = "get"
+ val GetOrElse = "getOrElse"
+
+ import SType.{paramR, paramT, tR, tT}
+
+ /** Type descriptor of `this` argument used in the methods below. */
+ val ThisType = SOption(tT)
+
+ /** The following SMethod instances are descriptors of methods defined in `Option` type. */
+ val IsDefinedMethod = SMethod(
+ this, IsDefined, SFunc(ThisType, SBoolean), 2, OptionIsDefined.costKind)
+ .withIRInfo({
+ case (builder, obj, _, args, _) if args.isEmpty => builder.mkOptionIsDefined(obj.asValue[SOption[SType]])
+ })
+ .withInfo(OptionIsDefined,
+ "Returns \\lst{true} if the option is an instance of \\lst{Some}, \\lst{false} otherwise.")
+
+ val GetMethod = SMethod(this, Get, SFunc(ThisType, tT), 3, OptionGet.costKind)
+ .withIRInfo({
+ case (builder, obj, _, args, _) if args.isEmpty => builder.mkOptionGet(obj.asValue[SOption[SType]])
+ })
+ .withInfo(OptionGet,
+ """Returns the option's value. The option must be nonempty. Throws exception if the option is empty.""")
+
+ lazy val GetOrElseMethod = SMethod(
+ this, GetOrElse, SFunc(Array(ThisType, tT), tT, Array[STypeParam](tT)), 4, OptionGetOrElse.costKind)
+ .withIRInfo(irBuilder = {
+ case (builder, obj, _, Seq(d), _) => builder.mkOptionGetOrElse(obj.asValue[SOption[SType]], d)
+ })
+ .withInfo(OptionGetOrElse,
+ """Returns the option's value if the option is nonempty, otherwise
+ |return the result of evaluating \lst{default}.
+ """.stripMargin, ArgInfo("default", "the default value"))
+
+// TODO soft-fork: https://github.com/ScorexFoundation/sigmastate-interpreter/issues/479
+// val FoldMethod = SMethod(
+// this, Fold, SFunc(Array(ThisType, tR, SFunc(tT, tR)), tR, Array[STypeParam](tT, tR)), 5, FixedCost(JitCost(1)))
+// .withInfo(MethodCall,
+// """Returns the result of applying \lst{f} to this option's
+// | value if the option is nonempty. Otherwise, evaluates
+// | expression \lst{ifEmpty}.
+// | This is equivalent to \lst{option map f getOrElse ifEmpty}.
+// """.stripMargin,
+// ArgInfo("ifEmpty", "the expression to evaluate if empty"),
+// ArgInfo("f", "the function to apply if nonempty"))
+
+ val MapMethod = SMethod(this, "map",
+ SFunc(Array(ThisType, SFunc(tT, tR)), SOption(tR), Array(paramT, paramR)), 7, FixedCost(JitCost(20)))
+ .withIRInfo(MethodCallIrBuilder)
+ .withInfo(MethodCall,
+ """Returns a \lst{Some} containing the result of applying \lst{f} to this option's
+ | value if this option is nonempty.
+ | Otherwise return \lst{None}.
+ """.stripMargin, ArgInfo("f", "the function to apply"))
+
+ val FilterMethod = SMethod(this, "filter",
+ SFunc(Array(ThisType, SFunc(tT, SBoolean)), ThisType, Array(paramT)), 8, FixedCost(JitCost(20)))
+ .withIRInfo(MethodCallIrBuilder)
+ .withInfo(MethodCall,
+ """Returns this option if it is nonempty and applying the predicate \lst{p} to
+ | this option's value returns true. Otherwise, return \lst{None}.
+ """.stripMargin, ArgInfo("p", "the predicate used for testing"))
+
+ override protected def getMethods(): Seq[SMethod] = super.getMethods() ++
+ Seq(
+ IsDefinedMethod,
+ GetMethod,
+ GetOrElseMethod,
+ /* TODO soft-fork: https://github.com/ScorexFoundation/sigmastate-interpreter/issues/479
+ FoldMethod,
+ */
+ MapMethod,
+ FilterMethod
+ )
+
+ /** Creates a descriptor of `Option[T]` type for the given element type `T`. */
+ def apply[T <: SType](implicit elemType: T, @unused ov: Overloaded1): SOption[T] = SOption(elemType)
+}
+
+object SCollectionMethods extends MethodsContainer with MethodByNameUnapply {
+ import SType.{paramIV, paramIVSeq, paramOV}
+
+ /** Type for which this container defines methods. */
+ override def ownerType: STypeCompanion = SCollection
+
+ /** Helper descriptors reused across different method descriptors. */
+ def tIV = SType.tIV
+ def tOV = SType.tOV
+
+ /** This descriptors are instantiated once here and then reused. */
+ val ThisType = SCollection(tIV)
+ val tOVColl = SCollection(tOV)
+ val tPredicate = SFunc(tIV, SBoolean)
+
+ /** The following SMethod instances are descriptors of methods defined in `Coll` type. */
+ val SizeMethod = SMethod(this, "size", SFunc(ThisType, SInt), 1, SizeOf.costKind)
+ .withInfo(SizeOf, "The size of the collection in elements.")
+
+ val GetOrElseMethod = SMethod(
+ this, "getOrElse", SFunc(Array(ThisType, SInt, tIV), tIV, paramIVSeq), 2, DynamicCost)
+ .withIRInfo({ case (builder, obj, _, Seq(index, defaultValue), _) =>
+ val index1 = index.asValue[SInt.type]
+ val defaultValue1 = defaultValue.asValue[SType]
+ builder.mkByIndex(obj.asValue[SCollection[SType]], index1, Some(defaultValue1))
+ })
+ .withInfo(ByIndex, "Return the element of collection if \\lst{index} is in range \\lst{0 .. size-1}",
+ ArgInfo("index", "index of the element of this collection"),
+ ArgInfo("default", "value to return when \\lst{index} is out of range"))
+
+ /** Implements evaluation of Coll.getOrElse method call ErgoTree node.
+ * Called via reflection based on naming convention.
+ * @see SMethod.evalMethod
+ */
+ def getOrElse_eval[A](mc: MethodCall, xs: Coll[A], i: Int, default: A)(implicit E: ErgoTreeEvaluator): A = {
+ E.addCost(ByIndex.costKind, mc.method.opDesc)
+ // the following lines should be semantically the same as in ByIndex.eval
+ Value.checkType(mc.args.last.tpe, default)
+ xs.getOrElse(i, default)
+ }
+
+ val MapMethod = SMethod(this, "map",
+ SFunc(Array(ThisType, SFunc(tIV, tOV)), tOVColl, Array(paramIV, paramOV)), 3, MapCollection.costKind)
+ .withIRInfo({
+ case (builder, obj, _, Seq(mapper), _) => builder.mkMapCollection(obj.asValue[SCollection[SType]], mapper.asFunc)
+ })
+ .withInfo(MapCollection,
+ """ Builds a new collection by applying a function to all elements of this collection.
+ | Returns a new collection of type \lst{Coll[B]} resulting from applying the given function
+ | \lst{f} to each element of this collection and collecting the results.
+ """.stripMargin,
+ ArgInfo("f", "the function to apply to each element"))
+
+ /** Implements evaluation of Coll.map method call ErgoTree node.
+ * Called via reflection based on naming convention.
+ * @see SMethod.evalMethod
+ */
+ def map_eval[A,B](mc: MethodCall, xs: Coll[A], f: A => B)(implicit E: ErgoTreeEvaluator): Coll[B] = {
+ val tpeB = mc.tpe.asInstanceOf[SCollection[SType]].elemType
+ val tB = Evaluation.stypeToRType(tpeB).asInstanceOf[RType[B]]
+ E.addSeqCostNoOp(MapCollection.costKind, xs.length, mc.method.opDesc)
+ xs.map(f)(tB)
+ }
+
+ val ExistsMethod = SMethod(this, "exists",
+ SFunc(Array(ThisType, tPredicate), SBoolean, paramIVSeq), 4, Exists.costKind)
+ .withIRInfo({
+ case (builder, obj, _, Seq(c), _) => builder.mkExists(obj.asValue[SCollection[SType]], c.asFunc)
+ })
+ .withInfo(Exists,
+ """Tests whether a predicate holds for at least one element of this collection.
+ |Returns \lst{true} if the given predicate \lst{p} is satisfied by at least one element of this collection, otherwise \lst{false}
+ """.stripMargin,
+ ArgInfo("p", "the predicate used to test elements"))
+
+ val FoldMethod = SMethod(
+ this, "fold",
+ SFunc(Array(ThisType, tOV, SFunc(Array(tOV, tIV), tOV)), tOV, Array(paramIV, paramOV)),
+ 5, Fold.costKind)
+ .withIRInfo({
+ case (builder, obj, _, Seq(z, op), _) => builder.mkFold(obj.asValue[SCollection[SType]], z, op.asFunc)
+ })
+ .withInfo(Fold, "Applies a binary operator to a start value and all elements of this collection, going left to right.",
+ ArgInfo("zero", "a starting value"),
+ ArgInfo("op", "the binary operator"))
+
+ val ForallMethod = SMethod(this, "forall",
+ SFunc(Array(ThisType, tPredicate), SBoolean, paramIVSeq), 6, ForAll.costKind)
+ .withIRInfo({
+ case (builder, obj, _, Seq(c), _) => builder.mkForAll(obj.asValue[SCollection[SType]], c.asFunc)
+ })
+ .withInfo(ForAll,
+ """Tests whether a predicate holds for all elements of this collection.
+ |Returns \lst{true} if this collection is empty or the given predicate \lst{p}
+ |holds for all elements of this collection, otherwise \lst{false}.
+ """.stripMargin,
+ ArgInfo("p", "the predicate used to test elements"))
+
+ val SliceMethod = SMethod(this, "slice",
+ SFunc(Array(ThisType, SInt, SInt), ThisType, paramIVSeq), 7, Slice.costKind)
+ .withIRInfo({
+ case (builder, obj, _, Seq(from, until), _) =>
+ builder.mkSlice(obj.asCollection[SType], from.asIntValue, until.asIntValue)
+ })
+ .withInfo(Slice,
+ """Selects an interval of elements. The returned collection is made up
+ | of all elements \lst{x} which satisfy the invariant:
+ | \lst{
+ | from <= indexOf(x) < until
+ | }
+ """.stripMargin,
+ ArgInfo("from", "the lowest index to include from this collection"),
+ ArgInfo("until", "the lowest index to EXCLUDE from this collection"))
+
+ val FilterMethod = SMethod(this, "filter",
+ SFunc(Array(ThisType, tPredicate), ThisType, paramIVSeq), 8, Filter.costKind)
+ .withIRInfo({
+ case (builder, obj, _, Seq(l), _) => builder.mkFilter(obj.asValue[SCollection[SType]], l.asFunc)
+ })
+ .withInfo(Filter,
+ """Selects all elements of this collection which satisfy a predicate.
+ | Returns a new collection consisting of all elements of this collection that satisfy the given
+ | predicate \lst{p}. The order of the elements is preserved.
+ """.stripMargin,
+ ArgInfo("p", "the predicate used to test elements."))
+
+ val AppendMethod = SMethod(this, "append",
+ SFunc(Array(ThisType, ThisType), ThisType, paramIVSeq), 9, Append.costKind)
+ .withIRInfo({
+ case (builder, obj, _, Seq(xs), _) =>
+ builder.mkAppend(obj.asCollection[SType], xs.asCollection[SType])
+ })
+ .withInfo(Append, "Puts the elements of other collection after the elements of this collection (concatenation of 2 collections)",
+ ArgInfo("other", "the collection to append at the end of this"))
+
+ val ApplyMethod = SMethod(this, "apply",
+ SFunc(Array(ThisType, SInt), tIV, Array[STypeParam](tIV)), 10, ByIndex.costKind)
+ .withInfo(ByIndex,
+ """The element at given index.
+ | Indices start at \lst{0}; \lst{xs.apply(0)} is the first element of collection \lst{xs}.
+ | Note the indexing syntax \lst{xs(i)} is a shorthand for \lst{xs.apply(i)}.
+ | Returns the element at the given index.
+ | Throws an exception if \lst{i < 0} or \lst{length <= i}
+ """.stripMargin, ArgInfo("i", "the index"))
+
+ /** Cost of creating a collection of indices */
+ val IndicesMethod_CostKind = PerItemCost(
+ baseCost = JitCost(20), perChunkCost = JitCost(2), chunkSize = 16)
+
+ val IndicesMethod = SMethod(
+ this, "indices", SFunc(ThisType, SCollection(SInt)), 14, IndicesMethod_CostKind)
+ .withIRInfo(MethodCallIrBuilder)
+ .withInfo(PropertyCall,
+ """Produces the range of all indices of this collection as a new collection
+ | containing [0 .. length-1] values.
+ """.stripMargin)
+
+ /** Implements evaluation of Coll.indices method call ErgoTree node.
+ * Called via reflection based on naming convention.
+ * @see SMethod.evalMethod
+ */
+ def indices_eval[A, B](mc: MethodCall, xs: Coll[A])
+ (implicit E: ErgoTreeEvaluator): Coll[Int] = {
+ val m = mc.method
+ E.addSeqCost(m.costKind.asInstanceOf[PerItemCost], xs.length, m.opDesc) { () =>
+ xs.indices
+ }
+ }
+ /** BaseCost:
+ * 1) base cost of Coll.flatMap
+ * PerChunkCost:
+ * 1) cost of Coll.flatMap (per item)
+ * 2) new collection is allocated for each item
+ * 3) each collection is then appended to the resulting collection */
+ val FlatMapMethod_CostKind = PerItemCost(
+ baseCost = JitCost(60), perChunkCost = JitCost(10), chunkSize = 8)
+
+ val FlatMapMethod = SMethod(this, "flatMap",
+ SFunc(Array(ThisType, SFunc(tIV, tOVColl)), tOVColl, Array(paramIV, paramOV)),
+ 15, FlatMapMethod_CostKind)
+ .withIRInfo(
+ MethodCallIrBuilder,
+ javaMethodOf[Coll[_], Function1[_,_], RType[_]]("flatMap"),
+ { mtype => Array(mtype.tRange.asCollection[SType].elemType) })
+ .withInfo(MethodCall,
+ """ Builds a new collection by applying a function to all elements of this collection
+ | and using the elements of the resulting collections.
+ | Function \lst{f} is constrained to be of the form \lst{x => x.someProperty}, otherwise
+ | it is illegal.
+ | Returns a new collection of type \lst{Coll[B]} resulting from applying the given collection-valued function
+ | \lst{f} to each element of this collection and concatenating the results.
+ """.stripMargin, ArgInfo("f", "the function to apply to each element."))
+
+ /** We assume all flatMap body patterns have similar executon cost. */
+ final val CheckFlatmapBody_Info = OperationCostInfo(
+ PerItemCost(baseCost = JitCost(20), perChunkCost = JitCost(20), chunkSize = 1),
+ NamedDesc("CheckFlatmapBody"))
+
+
+ /** This patterns recognize all expressions, which are allowed as lambda body
+ * of flatMap. Other bodies are rejected with throwing exception.
+ */
+ val flatMap_BodyPatterns = Array[PartialFunction[SValue, Int]](
+ { case MethodCall(ValUse(id, tpe), m, args, _) if args.isEmpty => id },
+ { case ExtractScriptBytes(ValUse(id, _)) => id },
+ { case ExtractId(ValUse(id, _)) => id },
+ { case SigmaPropBytes(ValUse(id, _)) => id },
+ { case ExtractBytes(ValUse(id, _)) => id },
+ { case ExtractBytesWithNoRef(ValUse(id, _)) => id }
+ )
+
+ /** Check the given expression is valid body of flatMap argument lambda.
+ * @param varId id of lambda variable (see [[FuncValue]].args)
+ * @param expr expression with is expected to use varId in ValUse node.
+ * @return true if the body is allowed
+ */
+ def isValidPropertyAccess(varId: Int, expr: SValue)
+ (implicit E: ErgoTreeEvaluator): Boolean = {
+ var found = false
+ // NOTE: the cost depends on the position of the pattern since
+ // we are checking until the first matching pattern found.
+ E.addSeqCost(CheckFlatmapBody_Info) { () =>
+ // the loop is bounded because flatMap_BodyPatterns is fixed
+ var i = 0
+ val nPatterns = flatMap_BodyPatterns.length
+ while (i < nPatterns && !found) {
+ val p = flatMap_BodyPatterns(i)
+ found = p.lift(expr) match {
+ case Some(id) => id == varId // `id` in the pattern is equal to lambda `varId`
+ case None => false
+ }
+ i += 1
+ }
+ i // how many patterns checked
+ }
+ found
+ }
+
+ /** Operation descriptor for matching `flatMap` method calls with valid lambdas. */
+ final val MatchSingleArgMethodCall_Info = OperationCostInfo(
+ FixedCost(JitCost(30)), NamedDesc("MatchSingleArgMethodCall"))
+
+ /** Recognizer of `flatMap` method calls with valid lambdas. */
+ object IsSingleArgMethodCall {
+ def unapply(mc:MethodCall)
+ (implicit E: ErgoTreeEvaluator): Nullable[(Int, SValue)] = {
+ var res: Nullable[(Int, SValue)] = Nullable.None
+ E.addFixedCost(MatchSingleArgMethodCall_Info) {
+ res = mc match {
+ case MethodCall(_, m, Seq(FuncValue(args, body)), _) if args.length == 1 =>
+ val id = args(0)._1
+ Nullable((id, body))
+ case _ =>
+ Nullable.None
+ }
+ }
+ res
+ }
+ }
+
+ /** Checks that the given [[MethodCall]] operation is valid flatMap. */
+ def checkValidFlatmap(mc: MethodCall)(implicit E: ErgoTreeEvaluator) = {
+ mc match {
+ case IsSingleArgMethodCall(varId, lambdaBody)
+ if isValidPropertyAccess(varId, lambdaBody) =>
+ // ok, do nothing
+ case _ =>
+ throwInvalidFlatmap(mc)
+ }
+ }
+
+ def throwInvalidFlatmap(mc: MethodCall) = {
+ sys.error(
+ s"Unsupported lambda in flatMap: allowed usage `xs.flatMap(x => x.property)`: $mc")
+ }
+
+ /** Implements evaluation of Coll.flatMap method call ErgoTree node.
+ * Called via reflection based on naming convention.
+ * @see SMethod.evalMethod
+ */
+ def flatMap_eval[A, B](mc: MethodCall, xs: Coll[A], f: A => Coll[B])
+ (implicit E: ErgoTreeEvaluator): Coll[B] = {
+ val m = mc.method
+ var res: Coll[B] = null
+ E.addSeqCost(m.costKind.asInstanceOf[PerItemCost], m.opDesc) { () =>
+ val tpeB = mc.tpe.asInstanceOf[SCollection[SType]].elemType
+ val tB = Evaluation.stypeToRType(tpeB).asInstanceOf[RType[B]]
+ res = xs.flatMap(f)(tB)
+ res.length
+ }
+ res
+ }
+
+ val PatchMethod = SMethod(this, "patch",
+ SFunc(Array(ThisType, SInt, ThisType, SInt), ThisType, paramIVSeq),
+ 19, PerItemCost(baseCost = JitCost(30), perChunkCost = JitCost(2), chunkSize = 10))
+ .withIRInfo(MethodCallIrBuilder)
+ .withInfo(MethodCall,
+ "Produces a new Coll where a slice of elements in this Coll is replaced by another Coll.")
+
+ /** Implements evaluation of Coll.patch method call ErgoTree node.
+ * Called via reflection based on naming convention.
+ * @see SMethod.evalMethod
+ */
+ def patch_eval[A](mc: MethodCall, xs: Coll[A], from: Int, patch: Coll[A], replaced: Int)
+ (implicit E: ErgoTreeEvaluator): Coll[A] = {
+ val m = mc.method
+ val nItems = xs.length + patch.length
+ E.addSeqCost(m.costKind.asInstanceOf[PerItemCost], nItems, m.opDesc) { () =>
+ xs.patch(from, patch, replaced)
+ }
+ }
+
+ val UpdatedMethod = SMethod(this, "updated",
+ SFunc(Array(ThisType, SInt, tIV), ThisType, paramIVSeq),
+ 20, PerItemCost(baseCost = JitCost(20), perChunkCost = JitCost(1), chunkSize = 10))
+ .withIRInfo(MethodCallIrBuilder, javaMethodOf[Coll[_], Int, Any]("updated"))
+ .withInfo(MethodCall,
+ "A copy of this Coll with one single replaced element.")
+
+ /** Implements evaluation of Coll.updated method call ErgoTree node.
+ * Called via reflection based on naming convention.
+ * @see SMethod.evalMethod
+ */
+ def updated_eval[A](mc: MethodCall, coll: Coll[A], index: Int, elem: A)
+ (implicit E: ErgoTreeEvaluator): Coll[A] = {
+ val m = mc.method
+ val costKind = m.costKind.asInstanceOf[PerItemCost]
+ E.addSeqCost(costKind, coll.length, m.opDesc) { () =>
+ coll.updated(index, elem)
+ }
+ }
+
+ val UpdateManyMethod = SMethod(this, "updateMany",
+ SFunc(Array(ThisType, SCollection(SInt), ThisType), ThisType, paramIVSeq),
+ 21, PerItemCost(baseCost = JitCost(20), perChunkCost = JitCost(2), chunkSize = 10))
+ .withIRInfo(MethodCallIrBuilder).withInfo(MethodCall, "")
+
+ /** Implements evaluation of Coll.updateMany method call ErgoTree node.
+ * Called via reflection based on naming convention.
+ * @see SMethod.evalMethod
+ */
+ def updateMany_eval[A](mc: MethodCall, coll: Coll[A], indexes: Coll[Int], values: Coll[A])
+ (implicit E: ErgoTreeEvaluator): Coll[A] = {
+ val costKind = mc.method.costKind.asInstanceOf[PerItemCost]
+ E.addSeqCost(costKind, coll.length, mc.method.opDesc) { () =>
+ coll.updateMany(indexes, values)
+ }
+ }
+
+ val IndexOfMethod = SMethod(this, "indexOf",
+ SFunc(Array(ThisType, tIV, SInt), SInt, paramIVSeq),
+ 26, PerItemCost(baseCost = JitCost(20), perChunkCost = JitCost(10), chunkSize = 2))
+ .withIRInfo(MethodCallIrBuilder, javaMethodOf[Coll[_], Any, Int]("indexOf"))
+ .withInfo(MethodCall, "")
+
+ /** Implements evaluation of Coll.indexOf method call ErgoTree node.
+ * Called via reflection based on naming convention.
+ * @see SMethod.evalMethod
+ */
+ def indexOf_eval[A](mc: MethodCall, xs: Coll[A], elem: A, from: Int)
+ (implicit E: ErgoTreeEvaluator): Int = {
+ val costKind = mc.method.costKind.asInstanceOf[PerItemCost]
+ var res: Int = -1
+ E.addSeqCost(costKind, mc.method.opDesc) { () =>
+ // this loop is bounded because MaxArrayLength limit is enforced
+ val len = xs.length
+ val start = math.max(from, 0)
+ var i = start
+ var different = true
+ while (i < len && different) {
+ different = !DataValueComparer.equalDataValues(xs(i), elem)
+ i += 1
+ }
+ if (!different)
+ res = i - 1
+ i - start // return number of performed iterations
+ }
+ res
+ }
+
+ /** Cost descriptor of Coll.zip operation. */
+ val Zip_CostKind = PerItemCost(
+ baseCost = JitCost(10), perChunkCost = JitCost(1), chunkSize = 10)
+
+ val ZipMethod = SMethod(this, "zip",
+ SFunc(Array(ThisType, tOVColl), SCollection(STuple(tIV, tOV)), Array[STypeParam](tIV, tOV)),
+ 29, Zip_CostKind)
+ .withIRInfo(MethodCallIrBuilder)
+ .withInfo(MethodCall, "")
+
+ /** Implements evaluation of Coll.zip method call ErgoTree node.
+ * Called via reflection based on naming convention.
+ * @see SMethod.evalMethod
+ */
+ def zip_eval[A, B](mc: MethodCall, xs: Coll[A], ys: Coll[B])
+ (implicit E: ErgoTreeEvaluator): Coll[(A,B)] = {
+ val m = mc.method
+ E.addSeqCost(m.costKind.asInstanceOf[PerItemCost], xs.length, m.opDesc) { () =>
+ xs.zip(ys)
+ }
+ }
+
+ /** This method should be overriden in derived classes to add new methods in addition to inherited.
+ * Typical override: `super.getMethods() ++ Seq(m1, m2, m3)`
+ */
+ override protected def getMethods(): Seq[SMethod] = super.getMethods() ++
+ Seq(
+ SizeMethod,
+ GetOrElseMethod,
+ MapMethod,
+ ExistsMethod,
+ FoldMethod,
+ ForallMethod,
+ SliceMethod,
+ FilterMethod,
+ AppendMethod,
+ ApplyMethod,
+ IndicesMethod,
+ FlatMapMethod,
+ PatchMethod,
+ UpdatedMethod,
+ UpdateManyMethod,
+ IndexOfMethod,
+ ZipMethod
+ )
+}
+
+object STupleMethods extends MethodsContainer {
+ /** Type for which this container defines methods. */
+ override def ownerType: STypeCompanion = STuple
+
+ private val MaxTupleLength: Int = SigmaConstants.MaxTupleLength.value
+
+ private val componentNames = Array.tabulate(MaxTupleLength) { i => s"_${i + 1}" }
+
+ /** A list of Coll methods inherited from Coll type and available as method of tuple. */
+ lazy val colMethods: Seq[SMethod] = {
+ val subst = Map(SType.tIV -> SAny)
+ // TODO: implement other methods
+ val activeMethods = Set(1.toByte /*Coll.size*/, 10.toByte /*Coll.apply*/)
+ SCollectionMethods.methods.filter(m => activeMethods.contains(m.methodId)).map { m =>
+ m.copy(stype = applySubst(m.stype, subst).asFunc)
+ }
+ }
+
+ def getTupleMethod(tup: STuple, name: String): Option[SMethod] = {
+ colMethods.find(_.name == name).orElse {
+ val iComponent = componentNames.lastIndexOf(name, end = tup.items.length - 1)
+ if (iComponent == -1) None
+ else
+ Some(SMethod(
+ STupleMethods, name, SFunc(tup, tup.items(iComponent)),
+ (iComponent + 1).toByte, SelectField.costKind))
+ }
+ }
+
+ override protected def getMethods(): Seq[SMethod] = super.getMethods()
+}
+
+/** Type descriptor of `Box` type of ErgoTree. */
+case object SBoxMethods extends MonoTypeMethods {
+ import ErgoBox._
+ import SType.{paramT, tT}
+
+ override def ownerType: SMonoType = SBox
+
+ /** Defined once here and then reused in SMethod descriptors. */
+ lazy val GetRegFuncType = SFunc(Array(SBox), SOption(tT), Array(paramT))
+
+ /** Creates a descriptor for the given register method. (i.e. R1, R2, etc) */
+ def registers(idOfs: Int): Seq[SMethod] = {
+ allRegisters.map { i =>
+ i match {
+ case r: MandatoryRegisterId =>
+ SMethod(this, s"R${i.asIndex}",
+ GetRegFuncType, (idOfs + i.asIndex + 1).toByte, ExtractRegisterAs.costKind)
+ .withInfo(ExtractRegisterAs, r.purpose)
+ case _ =>
+ SMethod(this, s"R${i.asIndex}",
+ GetRegFuncType, (idOfs + i.asIndex + 1).toByte, ExtractRegisterAs.costKind)
+ .withInfo(ExtractRegisterAs, "Non-mandatory register")
+ }
+ }
+ }
+
+ val PropositionBytes = "propositionBytes"
+ val Value = "value"
+ val Id = "id"
+ val Bytes = "bytes"
+ val BytesWithoutRef = "bytesWithoutRef"
+ val CreationInfo = "creationInfo"
+ val GetReg = "getReg"
+
+ // should be lazy, otherwise lead to initialization error
+ lazy val ValueMethod = SMethod(
+ this, Value, SFunc(SBox, SLong), 1, ExtractAmount.costKind)
+ .withInfo(ExtractAmount,
+ "Mandatory: Monetary value, in Ergo tokens (NanoErg unit of measure)")
+
+ lazy val PropositionBytesMethod = SMethod(
+ this, PropositionBytes, SFunc(SBox, SByteArray), 2, ExtractScriptBytes.costKind)
+ .withInfo(ExtractScriptBytes,
+ "Serialized bytes of guarding script, which should be evaluated to true in order to\n" +
+ " open this box. (aka spend it in a transaction)")
+
+ lazy val BytesMethod = SMethod(
+ this, Bytes, SFunc(SBox, SByteArray), 3, ExtractBytes.costKind)
+ .withInfo(ExtractBytes, "Serialized bytes of this box's content, including proposition bytes.")
+
+ lazy val BytesWithoutRefMethod = SMethod(
+ this, BytesWithoutRef, SFunc(SBox, SByteArray), 4, ExtractBytesWithNoRef.costKind)
+ .withInfo(ExtractBytesWithNoRef,
+ "Serialized bytes of this box's content, excluding transactionId and index of output.")
+
+ lazy val IdMethod = SMethod(this, Id, SFunc(SBox, SByteArray), 5, ExtractId.costKind)
+ .withInfo(ExtractId,
+ "Blake2b256 hash of this box's content, basically equals to \\lst{blake2b256(bytes)}")
+
+ lazy val creationInfoMethod = SMethod(
+ this, CreationInfo, ExtractCreationInfo.OpType, 6, ExtractCreationInfo.costKind)
+ .withInfo(ExtractCreationInfo,
+ """ If \lst{tx} is a transaction which generated this box, then \lst{creationInfo._1}
+ | is a height of the tx's block. The \lst{creationInfo._2} is a serialized transaction
+ | identifier followed by box index in the transaction outputs.
+ """.stripMargin ) // see ExtractCreationInfo
+
+ lazy val getRegMethod = SMethod(this, "getReg",
+ SFunc(Array(SBox, SInt), SOption(tT), Array(paramT)), 7, ExtractRegisterAs.costKind)
+ .withInfo(ExtractRegisterAs,
+ """ Extracts register by id and type.
+ | Type param \lst{T} expected type of the register.
+ | Returns \lst{Some(value)} if the register is defined and has given type and \lst{None} otherwise
+ """.stripMargin,
+ ArgInfo("regId", "zero-based identifier of the register."))
+
+ lazy val tokensMethod = SMethod(
+ this, "tokens", SFunc(SBox, ErgoBox.STokensRegType), 8, FixedCost(JitCost(15)))
+ .withIRInfo(MethodCallIrBuilder)
+ .withInfo(PropertyCall, "Secondary tokens")
+
+
+ // should be lazy to solve recursive initialization
+ protected override def getMethods() = super.getMethods() ++ Array(
+ ValueMethod, // see ExtractAmount
+ PropositionBytesMethod, // see ExtractScriptBytes
+ BytesMethod, // see ExtractBytes
+ BytesWithoutRefMethod, // see ExtractBytesWithNoRef
+ IdMethod, // see ExtractId
+ creationInfoMethod,
+ getRegMethod,
+ tokensMethod
+ ) ++ registers(8)
+}
+
+/** Type descriptor of `AvlTree` type of ErgoTree. */
+case object SAvlTreeMethods extends MonoTypeMethods {
+ import SOption._
+
+ override def ownerType: SMonoType = SAvlTree
+
+ lazy val TCollOptionCollByte = SCollection(SByteArrayOption)
+ lazy val CollKeyValue = SCollection(STuple(SByteArray, SByteArray))
+
+ lazy val digestMethod = SMethod(this, "digest", SFunc(SAvlTree, SByteArray), 1, FixedCost(JitCost(15)))
+ .withIRInfo(MethodCallIrBuilder)
+ .withInfo(PropertyCall,
+ """Returns digest of the state represented by this tree.
+ | Authenticated tree \lst{digest} = \lst{root hash bytes} ++ \lst{tree height}
+ """.stripMargin)
+
+ /** Cost descriptor of `digest` method. */
+ lazy val digest_Info = {
+ val m = digestMethod
+ OperationCostInfo(m.costKind.asInstanceOf[FixedCost], m.opDesc)
+ }
+
+ lazy val enabledOperationsMethod = SMethod(
+ this, "enabledOperations", SFunc(SAvlTree, SByte), 2, FixedCost(JitCost(15)))
+ .withIRInfo(MethodCallIrBuilder)
+ .withInfo(PropertyCall,
+ """ Flags of enabled operations packed in single byte.
+ | \lst{isInsertAllowed == (enabledOperations & 0x01) != 0}\newline
+ | \lst{isUpdateAllowed == (enabledOperations & 0x02) != 0}\newline
+ | \lst{isRemoveAllowed == (enabledOperations & 0x04) != 0}
+ """.stripMargin)
+
+ lazy val keyLengthMethod = SMethod(
+ this, "keyLength", SFunc(SAvlTree, SInt), 3, FixedCost(JitCost(15)))
+ .withIRInfo(MethodCallIrBuilder)
+ .withInfo(PropertyCall,
+ """
+ |
+ """.stripMargin)
+
+ lazy val valueLengthOptMethod = SMethod(
+ this, "valueLengthOpt", SFunc(SAvlTree, SIntOption), 4, FixedCost(JitCost(15)))
+ .withIRInfo(MethodCallIrBuilder)
+ .withInfo(PropertyCall,
+ """
+ |
+ """.stripMargin)
+
+ lazy val isInsertAllowedMethod = SMethod(
+ this, "isInsertAllowed", SFunc(SAvlTree, SBoolean), 5, FixedCost(JitCost(15)))
+ .withIRInfo(MethodCallIrBuilder)
+ .withInfo(PropertyCall,
+ """
+ |
+ """.stripMargin)
+
+ lazy val isInsertAllowed_Info = {
+ val m = isInsertAllowedMethod
+ OperationCostInfo(m.costKind.asInstanceOf[FixedCost], m.opDesc)
+ }
+
+ lazy val isUpdateAllowedMethod = SMethod(
+ this, "isUpdateAllowed", SFunc(SAvlTree, SBoolean), 6, FixedCost(JitCost(15)))
+ .withIRInfo(MethodCallIrBuilder)
+ .withInfo(PropertyCall,
+ """
+ |
+ """.stripMargin)
+
+ lazy val isUpdateAllowed_Info = {
+ val m = isUpdateAllowedMethod
+ OperationCostInfo(m.costKind.asInstanceOf[FixedCost], m.opDesc)
+ }
+
+ lazy val isRemoveAllowedMethod = SMethod(
+ this, "isRemoveAllowed", SFunc(SAvlTree, SBoolean), 7, FixedCost(JitCost(15)))
+ .withIRInfo(MethodCallIrBuilder)
+ .withInfo(PropertyCall,
+ """
+ |
+ """.stripMargin)
+
+ lazy val isRemoveAllowed_Info = {
+ val m = isRemoveAllowedMethod
+ OperationCostInfo(m.costKind.asInstanceOf[FixedCost], m.opDesc)
+ }
+
+ lazy val updateOperationsMethod = SMethod(this, "updateOperations",
+ SFunc(Array(SAvlTree, SByte), SAvlTree), 8, FixedCost(JitCost(45)))
+ .withIRInfo(MethodCallIrBuilder)
+ .withInfo(MethodCall,
+ """
+ |
+ """.stripMargin)
+
+ lazy val containsMethod = SMethod(this, "contains",
+ SFunc(Array(SAvlTree, SByteArray, SByteArray), SBoolean), 9, DynamicCost)
+ .withIRInfo(MethodCallIrBuilder)
+ .withInfo(MethodCall,
+ """
+ | /** Checks if an entry with key `key` exists in this tree using proof `proof`.
+ | * Throws exception if proof is incorrect
+ |
+ | * @note CAUTION! Does not support multiple keys check, use [[getMany]] instead.
+ | * Return `true` if a leaf with the key `key` exists
+ | * Return `false` if leaf with provided key does not exist.
+ | * @param key a key of an element of this authenticated dictionary.
+ | * @param proof
+ | */
+ |
+ """.stripMargin)
+
+ /** The proof may contain keys, labels and values, we don't know for sure how many,
+ * but we assume the cost is O(proof.length).
+ * So the following is an approximation of the proof parsing cost.
+ */
+ final val CreateAvlVerifier_Info = OperationCostInfo(
+ PerItemCost(baseCost = JitCost(110), perChunkCost = JitCost(20), chunkSize = 64),
+ NamedDesc("CreateAvlVerifier"))
+
+ final val LookupAvlTree_Info = OperationCostInfo(
+ PerItemCost(baseCost = JitCost(40), perChunkCost = JitCost(10), chunkSize = 1),
+ NamedDesc("LookupAvlTree"))
+
+ final val InsertIntoAvlTree_Info = OperationCostInfo(
+ PerItemCost(baseCost = JitCost(40), perChunkCost = JitCost(10), chunkSize = 1),
+ NamedDesc("InsertIntoAvlTree"))
+
+ final val UpdateAvlTree_Info = OperationCostInfo(
+ PerItemCost(baseCost = JitCost(120), perChunkCost = JitCost(20), chunkSize = 1),
+ NamedDesc("UpdateAvlTree"))
+
+ final val RemoveAvlTree_Info = OperationCostInfo(
+ PerItemCost(baseCost = JitCost(100), perChunkCost = JitCost(15), chunkSize = 1),
+ NamedDesc("RemoveAvlTree"))
+
+ /** Implements evaluation of AvlTree.contains method call ErgoTree node.
+ * Called via reflection based on naming convention.
+ * @see SMethod.evalMethod
+ */
+ def contains_eval(mc: MethodCall, tree: AvlTree, key: Coll[Byte], proof: Coll[Byte])
+ (implicit E: ErgoTreeEvaluator): Boolean = {
+ E.contains_eval(mc, tree, key, proof)
+ }
+
+ lazy val getMethod = SMethod(this, "get",
+ SFunc(Array(SAvlTree, SByteArray, SByteArray), SByteArrayOption), 10, DynamicCost)
+ .withIRInfo(MethodCallIrBuilder)
+ .withInfo(MethodCall,
+ """
+ | /** Perform a lookup of key `key` in this tree using proof `proof`.
+ | * Throws exception if proof is incorrect
+ | *
+ | * @note CAUTION! Does not support multiple keys check, use [[getMany]] instead.
+ | * Return Some(bytes) of leaf with key `key` if it exists
+ | * Return None if leaf with provided key does not exist.
+ | * @param key a key of an element of this authenticated dictionary.
+ | * @param proof
+ | */
+ |
+ """.stripMargin)
+
+ /** Implements evaluation of AvlTree.get method call ErgoTree node.
+ * Called via reflection based on naming convention.
+ * @see SMethod.evalMethod
+ */
+ def get_eval(mc: MethodCall, tree: AvlTree, key: Coll[Byte], proof: Coll[Byte])
+ (implicit E: ErgoTreeEvaluator): Option[Coll[Byte]] = {
+ E.get_eval(mc, tree, key, proof)
+ }
+
+ lazy val getManyMethod = SMethod(this, "getMany",
+ SFunc(Array(SAvlTree, SByteArray2, SByteArray), TCollOptionCollByte), 11, DynamicCost)
+ .withIRInfo(MethodCallIrBuilder)
+ .withInfo(MethodCall,
+ """
+ | /** Perform a lookup of many keys `keys` in this tree using proof `proof`.
+ | *
+ | * @note CAUTION! Keys must be ordered the same way they were in lookup before proof was generated.
+ | * For each key return Some(bytes) of leaf if it exists and None if is doesn't.
+ | * @param keys keys of elements of this authenticated dictionary.
+ | * @param proof
+ | */
+ |
+ """.stripMargin)
+
+ /** Implements evaluation of AvlTree.getMany method call ErgoTree node.
+ * Called via reflection based on naming convention.
+ * @see SMethod.evalMethod
+ */
+ def getMany_eval(mc: MethodCall, tree: AvlTree, keys: Coll[Coll[Byte]], proof: Coll[Byte])
+ (implicit E: ErgoTreeEvaluator): Coll[Option[Coll[Byte]]] = {
+ E.getMany_eval(mc, tree, keys, proof)
+ }
+
+ lazy val insertMethod = SMethod(this, "insert",
+ SFunc(Array(SAvlTree, CollKeyValue, SByteArray), SAvlTreeOption), 12, DynamicCost)
+ .withIRInfo(MethodCallIrBuilder)
+ .withInfo(MethodCall,
+ """
+ | /** Perform insertions of key-value entries into this tree using proof `proof`.
+ | * Throws exception if proof is incorrect
+ | *
+ | * @note CAUTION! Pairs must be ordered the same way they were in insert ops before proof was generated.
+ | * Return Some(newTree) if successful
+ | * Return None if operations were not performed.
+ | * @param operations collection of key-value pairs to insert in this authenticated dictionary.
+ | * @param proof
+ | */
+ |
+ """.stripMargin)
+
+ /** Implements evaluation of AvlTree.insert method call ErgoTree node.
+ * Called via reflection based on naming convention.
+ * @see SMethod.evalMethod
+ */
+ def insert_eval(mc: MethodCall, tree: AvlTree, entries: KeyValueColl, proof: Coll[Byte])
+ (implicit E: ErgoTreeEvaluator): Option[AvlTree] = {
+ E.insert_eval(mc, tree, entries, proof)
+ }
+
+ lazy val updateMethod = SMethod(this, "update",
+ SFunc(Array(SAvlTree, CollKeyValue, SByteArray), SAvlTreeOption), 13, DynamicCost)
+ .withIRInfo(MethodCallIrBuilder)
+ .withInfo(MethodCall,
+ """
+ | /** Perform updates of key-value entries into this tree using proof `proof`.
+ | * Throws exception if proof is incorrect
+ | *
+ | * @note CAUTION! Pairs must be ordered the same way they were in update ops before proof was generated.
+ | * Return Some(newTree) if successful
+ | * Return None if operations were not performed.
+ | * @param operations collection of key-value pairs to update in this authenticated dictionary.
+ | * @param proof
+ | */
+ |
+ """.stripMargin)
+
+ /** Implements evaluation of AvlTree.update method call ErgoTree node.
+ * Called via reflection based on naming convention.
+ * @see SMethod.evalMethod
+ */
+ def update_eval(mc: MethodCall, tree: AvlTree,
+ operations: KeyValueColl, proof: Coll[Byte])
+ (implicit E: ErgoTreeEvaluator): Option[AvlTree] = {
+ E.update_eval(mc, tree, operations, proof)
+ }
+
+ lazy val removeMethod = SMethod(this, "remove",
+ SFunc(Array(SAvlTree, SByteArray2, SByteArray), SAvlTreeOption), 14, DynamicCost)
+ .withIRInfo(MethodCallIrBuilder)
+ .withInfo(MethodCall,
+ """
+ | /** Perform removal of entries into this tree using proof `proof`.
+ | * Throws exception if proof is incorrect
+ | * Return Some(newTree) if successful
+ | * Return None if operations were not performed.
+ | *
+ | * @note CAUTION! Keys must be ordered the same way they were in remove ops before proof was generated.
+ | * @param operations collection of keys to remove from this authenticated dictionary.
+ | * @param proof
+ | */
+ |
+ """.stripMargin)
+
+ /** Implements evaluation of AvlTree.remove method call ErgoTree node.
+ * Called via reflection based on naming convention.
+ * @see SMethod.evalMethod
+ */
+ def remove_eval(mc: MethodCall, tree: AvlTree,
+ operations: Coll[Coll[Byte]], proof: Coll[Byte])
+ (implicit E: ErgoTreeEvaluator): Option[AvlTree] = {
+ E.remove_eval(mc, tree, operations, proof)
+ }
+
+ lazy val updateDigestMethod = SMethod(this, "updateDigest",
+ SFunc(Array(SAvlTree, SByteArray), SAvlTree), 15, FixedCost(JitCost(40)))
+ .withIRInfo(MethodCallIrBuilder)
+ .withInfo(MethodCall,
+ """
+ |
+ """.stripMargin)
+
+ lazy val updateDigest_Info = {
+ val m = updateDigestMethod
+ OperationCostInfo(m.costKind.asInstanceOf[FixedCost], m.opDesc)
+ }
+
+ protected override def getMethods(): Seq[SMethod] = super.getMethods() ++ Seq(
+ digestMethod,
+ enabledOperationsMethod,
+ keyLengthMethod,
+ valueLengthOptMethod,
+ isInsertAllowedMethod,
+ isUpdateAllowedMethod,
+ isRemoveAllowedMethod,
+ updateOperationsMethod,
+ containsMethod,
+ getMethod,
+ getManyMethod,
+ insertMethod,
+ updateMethod,
+ removeMethod,
+ updateDigestMethod
+ )
+}
+
+/** Type descriptor of `Context` type of ErgoTree. */
+case object SContextMethods extends MonoTypeMethods {
+ override def ownerType: SMonoType = SContext
+
+ /** Arguments on context operation such as getVar, DeserializeContext etc.
+ * This value can be reused where necessary to avoid allocations. */
+ val ContextFuncDom: IndexedSeq[SType] = Array(SContext, SByte)
+
+ import SType.{paramT, tT}
+
+ lazy val dataInputsMethod = propertyCall("dataInputs", SBoxArray, 1, FixedCost(JitCost(15)))
+ lazy val headersMethod = propertyCall("headers", SHeaderArray, 2, FixedCost(JitCost(15)))
+ lazy val preHeaderMethod = propertyCall("preHeader", SPreHeader, 3, FixedCost(JitCost(15)))
+ lazy val inputsMethod = property("INPUTS", SBoxArray, 4, Inputs)
+ lazy val outputsMethod = property("OUTPUTS", SBoxArray, 5, Outputs)
+ lazy val heightMethod = property("HEIGHT", SInt, 6, Height)
+ lazy val selfMethod = property("SELF", SBox, 7, Self)
+ lazy val selfBoxIndexMethod = propertyCall("selfBoxIndex", SInt, 8, FixedCost(JitCost(20)))
+ lazy val lastBlockUtxoRootHashMethod = property("LastBlockUtxoRootHash", SAvlTree, 9, LastBlockUtxoRootHash)
+ lazy val minerPubKeyMethod = property("minerPubKey", SByteArray, 10, MinerPubkey)
+ lazy val getVarMethod = SMethod(
+ this, "getVar", SFunc(ContextFuncDom, SOption(tT), Array(paramT)), 11, GetVar.costKind)
+ .withInfo(GetVar, "Get context variable with given \\lst{varId} and type.",
+ ArgInfo("varId", "\\lst{Byte} identifier of context variable"))
+
+ protected override def getMethods() = super.getMethods() ++ Seq(
+ dataInputsMethod, headersMethod, preHeaderMethod, inputsMethod, outputsMethod, heightMethod, selfMethod,
+ selfBoxIndexMethod, lastBlockUtxoRootHashMethod, minerPubKeyMethod, getVarMethod
+ )
+
+ /** Names of methods which provide blockchain context.
+ * This value can be reused where necessary to avoid allocations. */
+ val BlockchainContextMethodNames: IndexedSeq[String] = Array(
+ headersMethod.name, preHeaderMethod.name, heightMethod.name,
+ lastBlockUtxoRootHashMethod.name, minerPubKeyMethod.name
+ )
+}
+
+/** Type descriptor of `Header` type of ErgoTree. */
+case object SHeaderMethods extends MonoTypeMethods {
+ override def ownerType: SMonoType = SHeader
+
+ lazy val idMethod = propertyCall("id", SByteArray, 1, FixedCost(JitCost(10)))
+ lazy val versionMethod = propertyCall("version", SByte, 2, FixedCost(JitCost(10)))
+ lazy val parentIdMethod = propertyCall("parentId", SByteArray, 3, FixedCost(JitCost(10)))
+ lazy val ADProofsRootMethod = propertyCall("ADProofsRoot", SByteArray, 4, FixedCost(JitCost(10)))
+ lazy val stateRootMethod = propertyCall("stateRoot", SAvlTree, 5, FixedCost(JitCost(10)))
+ lazy val transactionsRootMethod = propertyCall("transactionsRoot", SByteArray, 6, FixedCost(JitCost(10)))
+ lazy val timestampMethod = propertyCall("timestamp", SLong, 7, FixedCost(JitCost(10)))
+ lazy val nBitsMethod = propertyCall("nBits", SLong, 8, FixedCost(JitCost(10)))
+ lazy val heightMethod = propertyCall("height", SInt, 9, FixedCost(JitCost(10)))
+ lazy val extensionRootMethod = propertyCall("extensionRoot", SByteArray, 10, FixedCost(JitCost(10)))
+ lazy val minerPkMethod = propertyCall("minerPk", SGroupElement, 11, FixedCost(JitCost(10)))
+ lazy val powOnetimePkMethod = propertyCall("powOnetimePk", SGroupElement, 12, FixedCost(JitCost(10)))
+ lazy val powNonceMethod = propertyCall("powNonce", SByteArray, 13, FixedCost(JitCost(10)))
+ lazy val powDistanceMethod = propertyCall("powDistance", SBigInt, 14, FixedCost(JitCost(10)))
+ lazy val votesMethod = propertyCall("votes", SByteArray, 15, FixedCost(JitCost(10)))
+
+ protected override def getMethods() = super.getMethods() ++ Seq(
+ idMethod, versionMethod, parentIdMethod, ADProofsRootMethod, stateRootMethod, transactionsRootMethod,
+ timestampMethod, nBitsMethod, heightMethod, extensionRootMethod, minerPkMethod, powOnetimePkMethod,
+ powNonceMethod, powDistanceMethod, votesMethod
+ )
+}
+
+/** Type descriptor of `PreHeader` type of ErgoTree. */
+case object SPreHeaderMethods extends MonoTypeMethods {
+ override def ownerType: SMonoType = SPreHeader
+
+ lazy val versionMethod = propertyCall("version", SByte, 1, FixedCost(JitCost(10)))
+ lazy val parentIdMethod = propertyCall("parentId", SByteArray, 2, FixedCost(JitCost(10)))
+ lazy val timestampMethod = propertyCall("timestamp", SLong, 3, FixedCost(JitCost(10)))
+ lazy val nBitsMethod = propertyCall("nBits", SLong, 4, FixedCost(JitCost(10)))
+ lazy val heightMethod = propertyCall("height", SInt, 5, FixedCost(JitCost(10)))
+ lazy val minerPkMethod = propertyCall("minerPk", SGroupElement, 6, FixedCost(JitCost(10)))
+ lazy val votesMethod = propertyCall("votes", SByteArray, 7, FixedCost(JitCost(10)))
+
+ protected override def getMethods() = super.getMethods() ++ Seq(
+ versionMethod, parentIdMethod, timestampMethod, nBitsMethod, heightMethod, minerPkMethod, votesMethod
+ )
+}
+
+/** This type is introduced to unify handling of global and non-global (i.e. methods) operations.
+ * It unifies implementation of global operation with implementation of methods and avoids code
+ * duplication (following DRY principle https://en.wikipedia.org/wiki/Don%27t_repeat_yourself).
+ * The WrappedType is `sigma.SigmaDslBuilder`, which is an interface implemented by
+ * the singleton sigmastate.eval.CostingSigmaDslBuilder
+ *
+ * The Constant(...) tree node of this type are not allowed, as well as using it in register and
+ * context variables (aka ContextExtension)
+ *
+ * When new methods are added to this type via a soft-fork, they will be serialized as part
+ * of ErgoTree using MethodCallSerializer, where SGlobal.typeCode will be used.
+ *
+ * @see sigmastate.lang.SigmaPredef
+ * */
+case object SGlobalMethods extends MonoTypeMethods {
+ override def ownerType: SMonoType = SGlobal
+
+ lazy val groupGeneratorMethod = SMethod(
+ this, "groupGenerator", SFunc(SGlobal, SGroupElement), 1, GroupGenerator.costKind)
+ .withIRInfo({ case (builder, obj, method, args, tparamSubst) => GroupGenerator })
+ .withInfo(GroupGenerator, "")
+
+ lazy val xorMethod = SMethod(
+ this, "xor", SFunc(Array(SGlobal, SByteArray, SByteArray), SByteArray), 2, Xor.costKind)
+ .withIRInfo({
+ case (_, _, _, Seq(l, r), _) => Xor(l.asByteArray, r.asByteArray)
+ })
+ .withInfo(Xor, "Byte-wise XOR of two collections of bytes",
+ ArgInfo("left", "left operand"), ArgInfo("right", "right operand"))
+
+ /** Implements evaluation of Global.xor method call ErgoTree node.
+ * Called via reflection based on naming convention.
+ * @see SMethod.evalMethod, Xor.eval, Xor.xorWithCosting
+ */
+ def xor_eval(mc: MethodCall, G: SigmaDslBuilder, ls: Coll[Byte], rs: Coll[Byte])
+ (implicit E: ErgoTreeEvaluator): Coll[Byte] = {
+ Xor.xorWithCosting(ls, rs)
+ }
+
+ protected override def getMethods() = super.getMethods() ++ Seq(
+ groupGeneratorMethod,
+ xorMethod
+ )
+}
+
diff --git a/data/shared/src/main/scala/sigma/ast/syntax.scala b/data/shared/src/main/scala/sigma/ast/syntax.scala
new file mode 100644
index 0000000000..5a257481cb
--- /dev/null
+++ b/data/shared/src/main/scala/sigma/ast/syntax.scala
@@ -0,0 +1,211 @@
+package sigma.ast
+
+import sigma.ast.SCollection.{SByteArray, SIntArray}
+import sigma.data.{AvlTreeData, CSigmaProp, GeneralType, Nullable, RType, SigmaBoolean, TrivialProp}
+import org.ergoplatform.{ErgoBox, ErgoBoxCandidate}
+import sigma.kiama.rewriting.Rewriter.{everywherebu, rewrite, rule}
+import StdSigmaBuilder.mkUpcast
+import sigma.SigmaDataReflection
+import sigma.exceptions.InterpreterException
+
+import scala.annotation.nowarn
+import scala.reflect.classTag
+
+/** Contains global definitions which define syntactic extensions for working with classes
+ * of sigma.ast package.
+ */
+object syntax {
+ /** Force initialization of reflection. */
+ val reflection = SigmaDataReflection
+
+ /** The following type synonyms are used throughout the codebase to simplify type annotations. */
+ type SValue = Value[SType]
+ type BoolValue = Value[SBoolean.type]
+ type ByteValue = Value[SByte.type]
+ type ShortValue = Value[SShort.type]
+ type IntValue = Value[SInt.type]
+ type LongValue = Value[SLong.type]
+ type BigIntValue = Value[SBigInt.type]
+ type BoxValue = Value[SBox.type]
+ type GroupElementValue = Value[SGroupElement.type]
+ type SigmaPropValue = Value[SSigmaProp.type]
+ type AvlTreeValue = Value[SAvlTree.type]
+ type SAnyValue = Value[SAny.type]
+ type CollectionValue[T <: SType] = Value[SCollection[T]]
+
+ type BooleanConstant = Constant[SBoolean.type]
+ type ByteConstant = Constant[SByte.type]
+ type ShortConstant = Constant[SShort.type]
+ type IntConstant = Constant[SInt.type]
+ type LongConstant = Constant[SLong.type]
+ type StringConstant = Constant[SString.type]
+ type BigIntConstant = Constant[SBigInt.type]
+ type BoxConstant = Constant[SBox.type]
+ type GroupElementConstant = Constant[SGroupElement.type]
+ type SigmaPropConstant = Constant[SSigmaProp.type]
+ type AvlTreeConstant = Constant[SAvlTree.type]
+ type CollectionConstant[T <: SType] = Constant[SCollection[T]]
+
+ /** Sigma proposition with trivial false proposition. */
+ val FalseSigmaProp = SigmaPropConstant(CSigmaProp(TrivialProp.FalseProp))
+
+ /** Sigma proposition with trivial true proposition. */
+ val TrueSigmaProp = SigmaPropConstant(CSigmaProp(TrivialProp.TrueProp))
+
+ /** Methods to work with tree nodes of [[SCollection]] type. */
+ implicit class CollectionOps[T <: SType](val coll: Value[SCollection[T]]) extends AnyVal {
+ /** Returns number of items in the collection expression. */
+ def length: Int = matchCase(_.items.length, _.value.length, _.items.length)
+
+ /** Returns a sequence of items in the collection expression. */
+ def items: Seq[Value[SType]] = matchCase(_.items, _ => sys.error(s"Cannot get 'items' property of node $coll"), _.items)
+
+ /** Abstracts from details of pattern matching collection expressions.
+ * Folds over given `coll` structure.
+ */
+ def matchCase[R](
+ whenConcrete: ConcreteCollection[T] => R,
+ whenConstant: CollectionConstant[T] => R,
+ whenTuple: Tuple => R
+ ): R = coll match {
+ case cc: ConcreteCollection[T]@unchecked => whenConcrete(cc)
+ case const: CollectionConstant[T]@unchecked => whenConstant(const)
+ case tuple: Tuple => whenTuple(tuple)
+ case _ => sys.error(s"Unexpected node $coll")
+ }
+ }
+
+ /** Methods to work with tree nodes of [[SSigmaProp]] type. */
+ implicit class SigmaPropValueOps(val p: Value[SSigmaProp.type]) extends AnyVal {
+ def propBytes: Value[SByteArray] = SigmaPropBytes(p)
+ }
+
+ /** Methods to work with tree nodes of [[SSigmaProp]] type. */
+ implicit class OptionValueOps[T <: SType](val p: Value[SOption[T]]) extends AnyVal {
+ def get: Value[T] = OptionGet(p)
+
+ def getOrElse(default: Value[T]): Value[T] = OptionGetOrElse(p, default)
+
+ def isDefined: Value[SBoolean.type] = OptionIsDefined(p)
+ }
+
+
+ def GetVarBoolean(varId: Byte): GetVar[SBoolean.type] = GetVar(varId, SBoolean)
+
+ def GetVarByte(varId: Byte): GetVar[SByte.type] = GetVar(varId, SByte)
+
+ def GetVarShort(varId: Byte): GetVar[SShort.type] = GetVar(varId, SShort)
+
+ def GetVarInt(varId: Byte): GetVar[SInt.type] = GetVar(varId, SInt)
+
+ def GetVarLong(varId: Byte): GetVar[SLong.type] = GetVar(varId, SLong)
+
+ def GetVarBigInt(varId: Byte): GetVar[SBigInt.type] = GetVar(varId, SBigInt)
+
+ def GetVarBox(varId: Byte): GetVar[SBox.type] = GetVar(varId, SBox)
+
+ def GetVarSigmaProp(varId: Byte): GetVar[SSigmaProp.type] = GetVar(varId, SSigmaProp)
+
+ def GetVarByteArray(varId: Byte): GetVar[SCollection[SByte.type]] = GetVar(varId, SByteArray)
+
+ def GetVarIntArray(varId: Byte): GetVar[SCollection[SInt.type]] = GetVar(varId, SIntArray)
+
+ implicit def boolToSigmaProp(b: BoolValue): SigmaPropValue = BoolToSigmaProp(b)
+
+ /** Shadow the implicit from sigma package so it doesn't interfere with the resolution
+ * of ClassTags below.
+ */
+ @nowarn private def rtypeToClassTag = ???
+
+ /** RType descriptors for predefined types used in AOTC-based interpreter. */
+ implicit val ErgoBoxRType: RType[ErgoBox] = RType.fromClassTag(classTag[ErgoBox])
+
+ implicit val ErgoBoxCandidateRType: RType[ErgoBoxCandidate] = RType.fromClassTag(classTag[ErgoBoxCandidate])
+
+ implicit val AvlTreeDataRType: RType[AvlTreeData] = GeneralType(classTag[AvlTreeData])
+
+ /** Type casting methods for [[Value]] nodes.
+ * Each `asX` method casts the value to the corresponding `X` type of node.
+ * No runtime checks are performed, so the caller should ensure that the value has the
+ * expected type.
+ * */
+ implicit class ValueOps(val v: Value[SType]) extends AnyVal {
+ def asValue[T <: SType]: Value[T] = v.asInstanceOf[Value[T]]
+
+ def asNumValue: Value[SNumericType] = v.asInstanceOf[Value[SNumericType]]
+
+ def asBoolValue: Value[SBoolean.type] = v.asInstanceOf[Value[SBoolean.type]]
+
+ def asByteValue: Value[SByte.type] = v.asInstanceOf[Value[SByte.type]]
+
+ def asIntValue: Value[SInt.type] = v.asInstanceOf[Value[SInt.type]]
+
+ def asBigInt: Value[SBigInt.type] = v.asInstanceOf[Value[SBigInt.type]]
+
+ def asBox: Value[SBox.type] = v.asInstanceOf[Value[SBox.type]]
+
+ def asGroupElement: Value[SGroupElement.type] = v.asInstanceOf[Value[SGroupElement.type]]
+
+ def asSigmaProp: Value[SSigmaProp.type] = v.asInstanceOf[Value[SSigmaProp.type]]
+
+ def asByteArray: Value[SByteArray] = v.asInstanceOf[Value[SByteArray]]
+
+ def asIntArray: Value[SIntArray] = v.asInstanceOf[Value[SIntArray]]
+
+ def asCollection[T <: SType]: Value[SCollection[T]] = v.asInstanceOf[Value[SCollection[T]]]
+
+ def asOption[T <: SType]: Value[SOption[T]] = v.asInstanceOf[Value[SOption[T]]]
+
+ def asTuple: Value[STuple] = v.asInstanceOf[Value[STuple]]
+
+ def asFunc: Value[SFunc] = v.asInstanceOf[Value[SFunc]]
+
+ /** Upcast the value `v` to the given type checking that `v` if of a numeric type.
+ * @param targetType type to upcast to
+ * @return upcasted value
+ */
+ def upcastTo[T <: SNumericType](targetType: T): Value[T] = {
+ assert(v.tpe.isInstanceOf[SNumericType],
+ s"Cannot upcast value of type ${v.tpe} to $targetType: only numeric types can be upcasted.")
+ val tV = v.asValue[SNumericType]
+ assert(targetType.max(tV.tpe) == targetType,
+ s"Invalid upcast from $tV to $targetType: target type should be larger than source type.")
+ if (targetType == tV.tpe) v.asValue[T]
+ else
+ mkUpcast(tV, targetType).withSrcCtx(v.sourceContext)
+ }
+
+ /** Assigns optional [[SourceContext]] to the value `v`.
+ * The is effectful operation changing state of `v`.
+ * @return the same instance of `v` with the given source context assigned
+ */
+ def withSrcCtx[T <: SType](sourceContext: Nullable[SourceContext]): Value[T] = {
+ v.sourceContext = sourceContext
+ v.asValue[T]
+ }
+
+ /**
+ * Sets the source context of the `v` instance only if it's empty (i.e. not set yet).
+ */
+ def withEnsuredSrcCtx[T <: SType](sourceContext: Nullable[SourceContext]): Value[T] = {
+ if (v.sourceContext.isEmpty) v.sourceContext = sourceContext
+ v.asValue[T]
+ }
+
+ /**
+ * Set source context to all nodes missing source context in the given tree.
+ *
+ * @param srcCtx source context to set
+ * @return AST where all nodes with missing source context are set to the given srcCtx
+ */
+ def withPropagatedSrcCtx[T <: SType](srcCtx: Nullable[SourceContext]): Value[T] = {
+ rewrite(everywherebu(rule[Any] {
+ case node: SValue if node != null && node.sourceContext.isEmpty =>
+ node.withSrcCtx(srcCtx)
+ }))(v).asValue[T]
+ }
+ }
+
+ /** Helper method to throw errors from Interpreter. */
+ def error(msg: String) = throw new InterpreterException(msg)
+}
diff --git a/interpreter/shared/src/main/scala/sigmastate/utxo/transformers.scala b/data/shared/src/main/scala/sigma/ast/transformers.scala
similarity index 94%
rename from interpreter/shared/src/main/scala/sigmastate/utxo/transformers.scala
rename to data/shared/src/main/scala/sigma/ast/transformers.scala
index 3d1ec92872..939da79d98 100644
--- a/interpreter/shared/src/main/scala/sigmastate/utxo/transformers.scala
+++ b/data/shared/src/main/scala/sigma/ast/transformers.scala
@@ -1,20 +1,16 @@
-package sigmastate.utxo
-
-import sigmastate.SCollection.SByteArray
-import sigmastate.Values._
-import sigmastate.lang.Terms._
-import sigmastate._
-import sigmastate.serialization.OpCodes.OpCode
-import sigmastate.serialization.OpCodes
+package sigma.ast
+
import org.ergoplatform.ErgoBox.RegisterId
-import sigma.data.RType
-import sigmastate.Operations._
-import sigmastate.eval.{Evaluation, SigmaDsl}
-import sigmastate.exceptions.InterpreterException
-import sigmastate.interpreter.ErgoTreeEvaluator
-import sigmastate.interpreter.ErgoTreeEvaluator.{DataEnv, error}
-import sigma.Coll
-import sigma.{Box, SigmaProp}
+import sigma.ast.Operations._
+import sigma.ast.SCollection.SByteArray
+import sigma.ast.syntax.SValue
+import sigma.data.{CSigmaProp, RType}
+import sigma.eval.ErgoTreeEvaluator
+import sigma.eval.ErgoTreeEvaluator.DataEnv
+import sigma.serialization.CoreByteWriter.ArgInfo
+import sigma.serialization.OpCodes
+import sigma.serialization.ValueCodes.OpCode
+import sigma.{Box, Coll, Evaluation}
// TODO refactor: remove this trait as it doesn't have semantic meaning
@@ -40,7 +36,7 @@ case class MapCollection[IV <: SType, OV <: SType](
extends Transformer[SCollection[IV], SCollection[OV]] {
override def companion = MapCollection
override val tpe = SCollection[OV](mapper.tpe.tRange.asInstanceOf[OV])
- override val opType = SCollection.MapMethod.stype.asFunc
+ override val opType = SCollectionMethods.MapMethod.stype.asFunc
protected final override def eval(env: DataEnv)(implicit E: ErgoTreeEvaluator): Any = {
val inputV = input.evalTo[Coll[Any]](env)
val mapperV = mapper.evalTo[Any => Any](env)
@@ -64,7 +60,7 @@ case class Append[IV <: SType](input: Value[SCollection[IV]], col2: Value[SColle
extends Transformer[SCollection[IV], SCollection[IV]] {
override def companion = Append
override val tpe = input.tpe
- override val opType = SCollection.AppendMethod.stype
+ override val opType = SCollectionMethods.AppendMethod.stype
protected final override def eval(env: DataEnv)(implicit E: ErgoTreeEvaluator): Any = {
val inputV = input.evalTo[Coll[IV#WrappedType]](env)
val col2V = col2.evalTo[Coll[IV#WrappedType]](env)
@@ -123,7 +119,7 @@ case class Filter[IV <: SType](input: Value[SCollection[IV]],
extends Transformer[SCollection[IV], SCollection[IV]] {
override def companion = Filter
override def tpe: SCollection[IV] = input.tpe
- override val opType = SCollection.FilterMethod.stype
+ override val opType = SCollectionMethods.FilterMethod.stype
protected final override def eval(env: DataEnv)(implicit E: ErgoTreeEvaluator): Any = {
val inputV = input.evalTo[Coll[Any]](env)
val conditionV = condition.evalTo[Any => Boolean](env)
@@ -160,7 +156,7 @@ case class Exists[IV <: SType](override val input: Value[SCollection[IV]],
override val condition: Value[SFunc])
extends BooleanTransformer[IV] {
override def companion = Exists
- override val opType = SCollection.ExistsMethod.stype
+ override val opType = SCollectionMethods.ExistsMethod.stype
protected final override def eval(env: DataEnv)(implicit E: ErgoTreeEvaluator): Any = {
val inputV = input.evalTo[Coll[Any]](env)
val conditionV = condition.evalTo[Any => Boolean](env)
@@ -187,7 +183,7 @@ case class ForAll[IV <: SType](override val input: Value[SCollection[IV]],
override val condition: Value[SFunc])
extends BooleanTransformer[IV] {
override def companion = ForAll
- override val opType = SCollection.ForallMethod.stype
+ override val opType = SCollectionMethods.ForallMethod.stype
protected final override def eval(env: DataEnv)(implicit E: ErgoTreeEvaluator): Any = {
val inputV = input.evalTo[Coll[Any]](env)
val conditionV = condition.evalTo[Any => Boolean](env)
@@ -224,7 +220,7 @@ case class Fold[IV <: SType, OV <: SType](input: Value[SCollection[IV]],
extends Transformer[SCollection[IV], OV] {
override def companion = Fold
implicit override def tpe: OV = zero.tpe
- val opType: SFunc = SCollection.FoldMethod.stype
+ val opType: SFunc = SCollectionMethods.FoldMethod.stype
protected final override def eval(env: DataEnv)(implicit E: ErgoTreeEvaluator): Any = {
val inputV = input.evalTo[Coll[IV#WrappedType]](env)
val zeroV = zero.evalTo[OV#WrappedType](env)
@@ -239,14 +235,6 @@ object Fold extends ValueCompanion {
override def opCode: OpCode = OpCodes.FoldCode
override val costKind = PerItemCost(
baseCost = JitCost(3), perChunkCost = JitCost(1), chunkSize = 10)
- def sum[T <: SNumericType](input: Value[SCollection[T]], varId: Int)(implicit tT: T) =
- Fold(input,
- Constant(tT.upcast(0.toByte), tT),
- FuncValue(Array((varId, STuple(tT, tT))),
- Plus(
- SelectField(ValUse(varId, STuple(tT, tT)), 1).asNumValue,
- SelectField(ValUse(varId, STuple(tT, tT)), 2).asNumValue))
- )
}
/** The element of the collection or default value.
@@ -264,7 +252,7 @@ case class ByIndex[V <: SType](input: Value[SCollection[V]],
extends Transformer[SCollection[V], V] with NotReadyValue[V] {
override def companion = ByIndex
override val tpe = input.tpe.elemType
- override val opType = SCollection.ApplyMethod.stype.asFunc
+ override val opType = SCollectionMethods.ApplyMethod.stype.asFunc
protected final override def eval(env: DataEnv)(implicit E: ErgoTreeEvaluator): Any = {
val inputV = input.evalTo[Coll[V#WrappedType]](env)
val indexV = index.evalTo[Int](env)
@@ -301,7 +289,7 @@ case class SelectField(input: Value[STuple], fieldIndex: Byte)
case p: Tuple2[_,_] =>
if (fieldIndex == 1) p._1
else if (fieldIndex == 2) p._2
- else error(s"Unknown fieldIndex $fieldIndex to select from $p: evaluating tree $this")
+ else sys.error(s"Unknown fieldIndex $fieldIndex to select from $p: evaluating tree $this")
case _ =>
Value.typeError(input, inputV)
}
@@ -335,8 +323,8 @@ case class SigmaPropBytes(input: Value[SSigmaProp.type])
override def tpe = SByteArray
override val opType = SFunc(input.tpe, tpe)
protected final override def eval(env: DataEnv)(implicit E: ErgoTreeEvaluator): Any = {
- val inputV = input.evalTo[SigmaProp](env)
- val numNodes = SigmaDsl.toSigmaBoolean(inputV).size
+ val inputV = input.evalTo[CSigmaProp](env)
+ val numNodes = inputV.wrappedValue.size
addSeqCost(SigmaPropBytes.costKind, numNodes) { () =>
inputV.propBytes
}
@@ -551,7 +539,7 @@ trait Deserialize[V <: SType] extends NotReadyValue[V]
*/
case class DeserializeContext[V <: SType](id: Byte, tpe: V) extends Deserialize[V] {
override def companion = DeserializeContext
- override val opType = SFunc(SContext.ContextFuncDom, tpe)
+ override val opType = SFunc(SContextMethods.ContextFuncDom, tpe)
}
object DeserializeContext extends ValueCompanion {
override def opCode: OpCode = OpCodes.DeserializeContextCode
@@ -575,7 +563,7 @@ object DeserializeRegister extends ValueCompanion {
/** See [[sigma.Context.getVar()]] for detailed description. */
case class GetVar[V <: SType](varId: Byte, override val tpe: SOption[V]) extends NotReadyValue[SOption[V]] {
override def companion = GetVar
- override val opType = SFunc(SContext.ContextFuncDom, tpe)
+ override val opType = SFunc(SContextMethods.ContextFuncDom, tpe)
protected final override def eval(env: DataEnv)(implicit E: ErgoTreeEvaluator): Any = {
val t = Evaluation.stypeToRType(tpe.elemType)
addCost(GetVar.costKind)
diff --git a/interpreter/shared/src/main/scala/sigmastate/trees.scala b/data/shared/src/main/scala/sigma/ast/trees.scala
similarity index 90%
rename from interpreter/shared/src/main/scala/sigmastate/trees.scala
rename to data/shared/src/main/scala/sigma/ast/trees.scala
index 2346ccd9e6..38d4565f30 100644
--- a/interpreter/shared/src/main/scala/sigmastate/trees.scala
+++ b/data/shared/src/main/scala/sigma/ast/trees.scala
@@ -1,158 +1,28 @@
-package sigmastate
+package sigma.ast
import debox.{cfor, Map => DMap}
-import org.ergoplatform.SigmaConstants
-import org.ergoplatform.validation.SigmaValidationSettings
+import scorex.crypto.hash.{Blake2b256, CryptographicHash32, Sha256}
+import sigma.ast.ArithOp.OperationImpl
+import sigma.ast.Operations._
+import sigma.ast.SCollection.{SByteArray, SIntArray}
+import sigma.ast.SOption.SIntOption
+import sigma.ast.syntax._
import sigma.data.ExactIntegral._
import sigma.data.ExactOrdering._
import sigma.data.OverloadHack.Overloaded1
-import sigma.data.{ExactIntegral, ExactOrdering}
-import scorex.crypto.hash.{Blake2b256, CryptographicHash32, Sha256}
+import sigma.data._
+import sigma.serialization.CoreByteWriter.ArgInfo
+import sigma.validation.SigmaValidationSettings
import sigma.{Coll, Colls, GroupElement, SigmaProp, VersionContext}
-import sigmastate.ArithOp.OperationImpl
-import sigmastate.Operations._
-import sigmastate.SCollection.{SByteArray, SIntArray}
-import sigmastate.SOption.SIntOption
-import sigmastate.Values._
-import sigmastate.eval.Extensions.EvalCollOps
-import sigmastate.eval.NumericOps.{BigIntIsExactIntegral, BigIntIsExactOrdering}
-import sigmastate.eval.SigmaDsl
-import sigmastate.interpreter.ErgoTreeEvaluator
-import sigmastate.interpreter.ErgoTreeEvaluator.DataEnv
-import sigmastate.serialization.OpCodes._
-import sigmastate.serialization._
-import sigmastate.utxo.{SimpleTransformerCompanion, Transformer}
+import NumericOps.{BigIntIsExactIntegral, BigIntIsExactOrdering}
+import sigma.eval.ErgoTreeEvaluator.DataEnv
+import sigma.eval.Extensions.EvalCollOps
+import sigma.eval.{ErgoTreeEvaluator, SigmaDsl}
+import sigma.serialization.OpCodes._
+import sigma.serialization.ValueCodes.OpCode
+import sigma.serialization._
import scala.collection.mutable
-import scala.collection.mutable.ArrayBuffer
-
-/**
- * Basic trait for inner nodes of crypto-trees, so AND/OR/THRESHOLD sigma-protocol connectives
- */
-trait SigmaConjecture extends SigmaBoolean {
- def children: Seq[SigmaBoolean]
-}
-
-/**
- * Basic trait for leafs of crypto-trees, such as
- * [[sigmastate.crypto.DLogProtocol.ProveDlog]] and [[sigmastate.crypto.ProveDHTuple]]
- * instances.
- * It plays the same role as [[SigmaConjecture]]. It used in prover to distinguish leafs from
- * other nodes and have logic common to leaves regardless of the concrete leaf type.
- */
-trait SigmaLeaf extends SigmaBoolean
-
-
-/**
- * AND conjunction for sigma propositions
- */
-case class CAND(override val children: Seq[SigmaBoolean]) extends SigmaConjecture {
- /** The same code is used for AND operation, but they belong to different type hierarchies. */
- override val opCode: OpCode = OpCodes.AndCode
- override val size: Int = SigmaBoolean.totalSize(children) + 1
-}
-
-object CAND {
- import TrivialProp._
-
- /** Connects the given sigma propositions into CAND proposition performing
- * partial evaluation when some of them are trivial propositioins.
- *
- * @param items propositions to combine into CAND
- * @return CAND, TrueProp, FalseProp or even one of the items depending on partial evaluation
- */
- def normalized(items: Seq[SigmaBoolean]): SigmaBoolean = {
- require(items.nonEmpty)
- val res = new ArrayBuffer[SigmaBoolean]()
- val nItems = items.length
- cfor(0)(_ < nItems, _ + 1) { i =>
- val x = items(i)
- x match {
- case FalseProp => return FalseProp
- case TrueProp => // skip
- case _ => res += x
- }
- }
- if (res.isEmpty) TrueProp
- else if (res.length == 1) res(0)
- else CAND(res.toSeq)
- }
-}
-
-/**
- * OR disjunction for sigma propositions
- */
-case class COR(children: Seq[SigmaBoolean]) extends SigmaConjecture {
- /** The same code is also used for OR operation, but they belong to different type hierarchies. */
- override val opCode: OpCode = OpCodes.OrCode
- override val size: Int = SigmaBoolean.totalSize(children) + 1
-}
-
-object COR {
- import TrivialProp._
-
- /** Connects the given sigma propositions into COR proposition performing
- * partial evaluation when some of them are trivial propositioins.
- *
- * @param items propositions to combine into COR
- * @return COR, TrueProp, FalseProp or even one of the items depending on partial evaluation
- */
- def normalized(items: Seq[SigmaBoolean]): SigmaBoolean = {
- require(items.nonEmpty)
- val res = new ArrayBuffer[SigmaBoolean]()
- val nItems = items.length
- cfor(0)(_ < nItems, _ + 1) { i =>
- val x = items(i)
- x match {
- case FalseProp => // skip
- case TrueProp => return TrueProp
- case _ => res += x
- }
- }
- if (res.isEmpty) FalseProp
- else if (res.length == 1) res(0)
- else COR(res.toSeq)
- }
-}
-
-/**
- * THRESHOLD connector for sigma propositions
- */
-case class CTHRESHOLD(k: Int, children: Seq[SigmaBoolean]) extends SigmaConjecture {
- // Our polynomial arithmetic can take only byte inputs
- require(k >= 0 && k <= children.length && children.length <= 255)
-
- override val opCode: OpCode = OpCodes.AtLeastCode
- override val size: Int = SigmaBoolean.totalSize(children) + 1
-}
-
-
-/** Represents boolean values (true/false) in SigmaBoolean tree.
- * Participates in evaluation of CAND, COR, THRESHOLD connectives over SigmaBoolean values.
- * See CAND.normalized, COR.normalized and AtLeast.reduce. */
-abstract class TrivialProp(val condition: Boolean) extends SigmaBoolean with Product1[Boolean] {
- override def _1: Boolean = condition
- override def canEqual(that: Any): Boolean = that != null && that.isInstanceOf[TrivialProp]
-}
-object TrivialProp {
- // NOTE: the corresponding unapply is missing because any implementation (even using Nullable)
- // will lead to Boolean boxing, which we want to avoid
- // So, instead of `case TrivialProp(b) => ... b ...` use more efficient
- // `case p: TrivialProp => ... p.condition ...
-
- def apply(b: Boolean): TrivialProp = if (b) TrueProp else FalseProp
-
- val FalseProp = new TrivialProp(false) {
- override val opCode: OpCode = OpCodes.TrivialPropFalseCode
- override def size: Int = 1
- override def toString = "FalseProp"
- }
- val TrueProp = new TrivialProp(true) {
- override val opCode: OpCode = OpCodes.TrivialPropTrueCode
- override def size: Int = 1
- override def toString = "TrueProp"
- }
-}
/** Embedding of Boolean values to SigmaProp values. As an example, this operation allows boolean experesions
* to be used as arguments of `atLeast(..., sigmaProp(boolExpr), ...)` operation.
@@ -166,7 +36,7 @@ case class BoolToSigmaProp(value: BoolValue) extends SigmaPropValue {
val v = value.evalTo[Any](env)
addCost(BoolToSigmaProp.costKind)
if (VersionContext.current.isJitActivated) {
- SigmaDsl.sigmaProp(v.asInstanceOf[Boolean])
+ CSigmaProp(v.asInstanceOf[Boolean])
} else {
// before v5.0 is activated we follow the old v4.x semantics to handle cases
// when the value is not a boolean. There are historical transactions with such
@@ -174,7 +44,7 @@ case class BoolToSigmaProp(value: BoolValue) extends SigmaPropValue {
v match {
case sp: SigmaProp => sp
case _ =>
- SigmaDsl.sigmaProp(v.asInstanceOf[Boolean])
+ CSigmaProp(v.asInstanceOf[Boolean])
}
}
}
@@ -194,7 +64,7 @@ case class CreateProveDlog(value: Value[SGroupElement.type]) extends SigmaPropVa
protected final override def eval(env: DataEnv)(implicit E: ErgoTreeEvaluator): Any = {
val v = value.evalTo[GroupElement](env)
addCost(CreateProveDlog.costKind)
- SigmaDsl.proveDlog(v)
+ CSigmaProp.withProveDlog(v)
}
}
object CreateProveDlog extends FixedCostValueCompanion {
@@ -235,7 +105,7 @@ case class CreateProveDHTuple(gv: Value[SGroupElement.type],
val u = uv.evalTo[GroupElement](env)
val v = vv.evalTo[GroupElement](env)
addCost(CreateProveDHTuple.costKind)
- SigmaDsl.proveDHTuple(g, h, u, v)
+ CSigmaProp.withProveDHTuple(g, h, u, v)
}
}
object CreateProveDHTuple extends FixedCostValueCompanion {
@@ -468,7 +338,7 @@ object AtLeast extends ValueCompanion {
/** HOTSPOT: don't beautify this code */
def reduce(bound: Int, children: Seq[SigmaBoolean]): SigmaBoolean = {
- import sigmastate.TrivialProp._
+ import sigma.data.TrivialProp._
if (bound <= 0) return TrueProp
val nChildren = children.length
if (bound > nChildren) return FalseProp
@@ -802,7 +672,7 @@ object SubstConstants extends ValueCompanion {
/** Transforms serialized bytes of ErgoTree with segregated constants by
* replacing constants at given positions with new values. This operation
* allow to use serialized scripts as pre-defined templates.
- * See [[sigmastate.SubstConstants]] for details.
+ * See [[SubstConstants]] for details.
*
* @param scriptBytes serialized ErgoTree with ConstantSegregationFlag set to 1.
* @param positions zero based indexes in ErgoTree.constants array which
@@ -991,7 +861,7 @@ object ArithOp {
}
}
- private[sigmastate] val operations: DMap[Byte, ArithOpCompanion] =
+ private[sigma] val operations: DMap[Byte, ArithOpCompanion] =
DMap.fromIterable(Seq(Plus, Minus, Multiply, Division, Modulo, Min, Max).map(o => (o.opCode, o)))
/** Represents implementation of numeric Arith operations for the given type argTpe. */
@@ -1000,7 +870,7 @@ object ArithOp {
val o = _o.asInstanceOf[ExactOrdering[Any]]
}
- private[sigmastate] val impls: DMap[SType.TypeCode, OperationImpl] =
+ private[sigma] val impls: DMap[SType.TypeCode, OperationImpl] =
DMap.fromIterable(Seq(
SByte -> new OperationImpl(ByteIsExactIntegral, ByteIsExactOrdering, SByte),
SShort -> new OperationImpl(ShortIsExactIntegral, ShortIsExactOrdering, SShort),
@@ -1464,7 +1334,7 @@ case class TreeLookup(tree: Value[SAvlTree.type],
key: Value[SByteArray],
proof: Value[SByteArray]) extends Quadruple[SAvlTree.type, SByteArray, SByteArray, SOption[SByteArray]] {
override def companion = TreeLookup
- override def tpe = SOption[SByteArray]
+ override def tpe = SOption[SByteArray](SByteArray)
override lazy val first = tree
override lazy val second = key
override lazy val third = proof
diff --git a/data/shared/src/main/scala/sigma/ast/values.scala b/data/shared/src/main/scala/sigma/ast/values.scala
new file mode 100644
index 0000000000..87c661a00a
--- /dev/null
+++ b/data/shared/src/main/scala/sigma/ast/values.scala
@@ -0,0 +1,1530 @@
+package sigma.ast
+
+import debox.cfor
+import sigma.Extensions.ArrayOps
+import sigma._
+import sigma.ast.SCollection.SByteArray
+import sigma.ast.TypeCodes.ConstantCode
+import sigma.ast.syntax._
+import sigma.crypto.{CryptoConstants, EcPointType}
+import sigma.data.OverloadHack.Overloaded1
+import sigma.data.{CSigmaDslBuilder, CSigmaProp, Nullable, RType, SigmaBoolean}
+import sigma.eval.ErgoTreeEvaluator.DataEnv
+import sigma.eval.{ErgoTreeEvaluator, SigmaDsl}
+import sigma.exceptions.InterpreterException
+import sigma.kiama.rewriting.Rewriter.count
+import sigma.serialization.OpCodes._
+import sigma.serialization.ValueCodes.OpCode
+import sigma.serialization._
+import sigma.util.CollectionUtil._
+import sigma.util.Extensions._
+
+import java.math.BigInteger
+import java.util.{Arrays, Objects}
+import scala.annotation.unused
+import scala.collection.compat.immutable.ArraySeq
+import scala.collection.mutable
+import scala.language.implicitConversions
+
+/** Base class for all ErgoTree expression nodes.
+ *
+ * @see [[ErgoTree]]
+ */
+abstract class Value[+S <: SType] extends SigmaNode {
+ /** The companion node descriptor with opCode, cost and other metadata. */
+ def companion: ValueCompanion
+
+ /** Unique id of the node class used in serialization of ErgoTree. */
+ def opCode: OpCode = companion.opCode
+
+ /** The type of the value represented by this node. If the value is an operation it is
+ * the type of operation result. */
+ def tpe: S
+
+ /** Every value represents an operation and that operation can be associated with a function type,
+ * describing functional meaning of the operation, kind of operation signature.
+ * Thus, we can obtain global operation identifiers by combining Value.opName with Value.opType,
+ * so that if (v1.opName == v2.opName) && (v1.opType == v2.opType) then v1 and v2 are functionally
+ * point-wise equivalent.
+ * This in particular means that if two _different_ ops have the same opType they _should_ have
+ * different opNames.
+ * Thus defined op ids are used in a v4.x Cost Model - a table of all existing primitives coupled with
+ * performance parameters.
+ * */
+ def opType: SFunc
+
+ /** Name of the operation. */
+ def opName: String = this.getClass.getSimpleName
+
+ /** Transforms this expression to SigmaProp expression or throws an exception. */
+ def toSigmaProp: SigmaPropValue = this match {
+ case b if b.tpe == SBoolean => BoolToSigmaProp(this.asBoolValue)
+ case p if p.tpe == SSigmaProp => p.asSigmaProp
+ case _ => sys.error(s"Expected SBoolean or SSigmaProp typed value, but was: $this")
+ }
+
+ /** Parser has some source information like line,column in the text. We need to keep it up until RuntimeCosting.
+ * The way to do this is to add Nullable property to every Value. Since Parser is always using SigmaBuilder
+ * to create nodes,
+ * Adding additional (implicit source: SourceContext) parameter to every builder method would pollute its API
+ * and also doesn't make sence during deserialization, where Builder is also used.
+ * We can assume some indirect mechanism to pass current source context into every mkXXX method of Builder.
+ * We can pass it using `scala.util.DynamicVariable` by wrapping each mkXXX call into `withValue { }` calls.
+ * The same will happen in Typer.
+ * We can take sourceContext from untyped nodes and use it while creating typed nodes.
+ * And we can make sourceContext of every Value writeOnce value, i.e. it will be Nullable.Null by default,
+ * but can be set afterwards, but only once.
+ * This property will not participate in equality and other operations, so will be invisible for existing code.
+ * But Builder can use it to set sourceContext if it is present.
+ */
+ private[ast] var _sourceContext: Nullable[SourceContext] = Nullable.None
+
+ def sourceContext: Nullable[SourceContext] = _sourceContext
+
+ def sourceContext_=(srcCtx: Nullable[SourceContext]): Unit =
+ if (_sourceContext.isEmpty) {
+ _sourceContext = srcCtx
+ } else {
+ sys.error("_sourceContext can be set only once")
+ }
+
+ /** Defines an evaluation semantics of this tree node (aka Value or expression) in the given data environment.
+ * Should be implemented by all the ErgoTree nodes (aka operations).
+ * Thus, the ErgoTree interpreter implementation consists of combined implementations of this method.
+ * NOTE, this method shouldn't be called directly, instead use `evalTo` method.
+ *
+ * @param E Evaluator which defines evaluation context, cost accumulator, settings etc.
+ * @param env immutable map, which binds variables (given by ids) to the values
+ * @return the data value which is the result of evaluation
+ */
+ protected def eval(env: DataEnv)(implicit E: ErgoTreeEvaluator): Any =
+ sys.error(s"Should be overriden in ${this.getClass}: $this")
+
+ /** Evaluates this node to the value of the given expected type.
+ * This method should called from all `eval` implementations.
+ *
+ * @tparam T expected type of the resulting value
+ * @param E Evaluator which defines evaluation context, cost accumulator, settings etc.
+ * @param env immutable map, which binds variables (given by ids) to the values
+ * @return the data value which is the result of evaluation
+ */
+ @inline
+ final def evalTo[T](env: DataEnv)(implicit E: ErgoTreeEvaluator): T = {
+ if (E.settings.isMeasureOperationTime) E.profiler.onBeforeNode(this)
+ val v = eval(env)
+ if (E.settings.isMeasureOperationTime) E.profiler.onAfterNode(this)
+ v.asInstanceOf[T]
+ }
+
+ /** Add the cost given by the kind to the accumulator and associate it with this operation
+ * node.
+ */
+ @inline
+ final def addCost(costKind: FixedCost)(implicit E: ErgoTreeEvaluator): Unit = {
+ E.addCost(costKind, this.companion.opDesc)
+ }
+
+ /** Add the cost given by the descriptor to the accumulator and associate it with this operation
+ * node.
+ */
+ @inline
+ final def addCost[R](costKind: TypeBasedCost, tpe: SType)
+ (block: () => R)
+ (implicit E: ErgoTreeEvaluator): R = {
+ E.addTypeBasedCost(costKind, tpe, this.companion.opDesc)(block)
+ }
+
+ /** Add the cost of a repeated operation to the accumulator and associate it with this
+ * operation. The number of items (loop iterations) is known in advance (like in
+ * Coll.map operation)
+ *
+ * @param costKind cost descriptor of the operation
+ * @param nItems number of operations known in advance (before loop execution)
+ */
+ @inline
+ final def addSeqCostNoOp(costKind: PerItemCost, nItems: Int)
+ (implicit E: ErgoTreeEvaluator): Unit = {
+ E.addSeqCostNoOp(costKind, nItems, this.companion.opDesc)
+ }
+
+ /** Add the cost of a repeated operation to the accumulator and associate it with this
+ * operation. The number of items (loop iterations) is known in advance (like in
+ * Coll.map operation)
+ *
+ * @param costKind cost descriptor of the operation
+ * @param nItems number of operations known in advance (before loop execution)
+ * @param block operation executed under the given cost
+ * @tparam R result type of the operation
+ */
+ @inline
+ final def addSeqCost[R](costKind: PerItemCost, nItems: Int)
+ (block: () => R)(implicit E: ErgoTreeEvaluator): R = {
+ E.addSeqCost(costKind, nItems, this.companion.opDesc)(block)
+ }
+}
+
+object Value {
+ type PropositionCode = Byte
+
+ implicit def liftByte(n: Byte): Value[SByte.type] = ByteConstant(n)
+
+ implicit def liftShort(n: Short): Value[SShort.type] = ShortConstant(n)
+
+ implicit def liftInt(n: Int): Value[SInt.type] = IntConstant(n)
+
+ implicit def liftLong(n: Long): Value[SLong.type] = LongConstant(n)
+
+ implicit def liftByteArray(arr: Array[Byte]): Value[SByteArray] = ByteArrayConstant(arr)
+
+ implicit def liftBigInt(arr: BigInt): Value[SBigInt.type] = BigIntConstant(arr)
+
+ implicit def liftGroupElement(g: GroupElement): Value[SGroupElement.type] = GroupElementConstant(g)
+
+ implicit def liftECPoint(g: EcPointType): Value[SGroupElement.type] = GroupElementConstant(g)
+
+ implicit def liftSigmaProp(g: SigmaProp): Value[SSigmaProp.type] = SigmaPropConstant(g)
+
+ implicit def liftSigmaBoolean(sb: SigmaBoolean): Value[SSigmaProp.type] = SigmaPropConstant(SigmaDsl.SigmaProp(sb))
+
+ object Typed {
+ def unapply(v: SValue): Option[(SValue, SType)] = Some((v, v.tpe))
+ }
+
+ def notSupportedError(v: Any, opName: String) =
+ throw new IllegalArgumentException(s"Method $opName is not supported for node $v")
+
+ /** Immutable empty array of values. Can be used to avoid allocation. */
+ val EmptyArray = Array.empty[SValue]
+
+ /** Immutable empty Seq of values. Can be used to avoid allocation. */
+ val EmptySeq: IndexedSeq[SValue] = EmptyArray
+
+ /** Traverses the given expression tree and counts the number of deserialization
+ * operations. If it is non-zero, returns true. */
+ def hasDeserialize(exp: SValue): Boolean = {
+ val deserializeNode: PartialFunction[Any, Int] = {
+ case _: DeserializeContext[_] => 1
+ case _: DeserializeRegister[_] => 1
+ }
+ val c = count(deserializeNode)(exp)
+ c > 0
+ }
+
+ /** Traverses the given expression tree and counts the number of operations
+ * which read the blockchain context. If it is non-zero, returns true. */
+ def isUsingBlockchainContext(exp: SValue): Boolean = {
+ val blockchainContextNode: PartialFunction[Any, Int] = {
+ case Height => 1
+ case LastBlockUtxoRootHash => 1
+ case MinerPubkey => 1
+ case MethodCall(_, method, _, _) =>
+ method.objType match {
+ case SContextMethods =>
+ if (SContextMethods.BlockchainContextMethodNames.contains(method.name)) 1 else 0
+ case _ => 0
+ }
+ case _ => 0
+ }
+ val c = count(blockchainContextNode)(exp)
+ c > 0
+ }
+
+ def typeError(node: SValue, evalResult: Any) = {
+ val tpe = node.tpe
+ throw new InterpreterException(
+ s"""Invalid type returned by evaluator:
+ | expression: $node
+ | expected type: $tpe
+ | resulting value: $evalResult
+ """.stripMargin)
+ }
+
+ def typeError(tpe: SType, evalResult: Any) = {
+ throw new InterpreterException(
+ s"""Invalid type returned by evaluator:
+ | expected type: $tpe
+ | resulting value: $evalResult
+ """.stripMargin)
+ }
+
+ def checkType(node: SValue, evalResult: Any) = {
+ val tpe = node.tpe
+ if (!SType.isValueOfType(evalResult, tpe))
+ typeError(node, evalResult)
+ }
+
+ def checkType(tpe: SType, evalResult: Any) = {
+ if (!SType.isValueOfType(evalResult, tpe))
+ typeError(tpe, evalResult)
+ }
+}
+
+/** Base class for all companion objects which are used as operation descriptors. */
+trait ValueCompanion extends SigmaNodeCompanion {
+ import ValueCompanion._
+
+ /** Unique id of the node class used in serialization of ErgoTree. */
+ def opCode: OpCode
+
+ /** Returns cost descriptor of this operation. */
+ def costKind: CostKind
+
+ override def toString: String = s"${this.getClass.getSimpleName}(${opCode.toUByte})"
+
+ def typeName: String = this.getClass.getSimpleName.replace("$", "")
+
+ def init() {
+ if (this.opCode != 0 && _allOperations.contains(this.opCode))
+ throw sys.error(s"Operation $this already defined")
+ _allOperations += (this.opCode -> this)
+ }
+
+ init()
+ val opDesc = CompanionDesc(this)
+}
+
+object ValueCompanion {
+ private val _allOperations: mutable.HashMap[Byte, ValueCompanion] = mutable.HashMap.empty
+
+ lazy val allOperations = _allOperations.toMap
+}
+
+/** Should be inherited by companion objects of operations with fixed cost kind. */
+trait FixedCostValueCompanion extends ValueCompanion {
+ /** Returns cost descriptor of this operation. */
+ override def costKind: FixedCost
+}
+
+/** Should be inherited by companion objects of operations with per-item cost kind. */
+trait PerItemCostValueCompanion extends ValueCompanion {
+ /** Returns cost descriptor of this operation. */
+ override def costKind: PerItemCost
+}
+
+/** Base class for ErgoTree nodes which represents a data value which has already been
+ * evaluated and no further evaluation (aka reduction) is necessary by the interpreter.
+ *
+ * @see Constant, ConcreteCollection, Tuple
+ */
+abstract class EvaluatedValue[+S <: SType] extends Value[S] {
+ /** The evaluated data value of the corresponding underlying data type. */
+ val value: S#WrappedType
+
+ override def opType: SFunc = {
+ val resType = tpe match {
+ case ct: SCollection[_] =>
+ SCollection(ct.typeParams.head.ident)
+ case ft @ SFunc(_, _, _) =>
+ ft.getGenericType
+ case _ => tpe
+ }
+ SFunc(ArraySeq.empty, resType)
+ }
+}
+
+/** Base class for all constant literals whose data value is already known and never
+ * changes.
+ *
+ * @see ConstantNode
+ */
+abstract class Constant[+S <: SType] extends EvaluatedValue[S]
+
+/** ErgoTree node which represents data literals, i.e. data values embedded in an
+ * expression.
+ *
+ * @param value data value of the underlying Scala type
+ * @param tpe type descriptor of the data value and also the type of the value
+ * represented by this node.
+ * @see Constant
+ */
+case class ConstantNode[S <: SType](value: S#WrappedType, tpe: S) extends Constant[S] {
+ require(sigma.crypto.Platform.isCorrectType(value, tpe),
+ s"Invalid type of constant value $value, expected type $tpe")
+
+ override def companion: ValueCompanion = Constant
+
+ override def opCode: OpCode = companion.opCode
+
+ override def opName: String = s"Const"
+
+ protected final override def eval(env: DataEnv)(implicit E: ErgoTreeEvaluator): Any = {
+ addCost(Constant.costKind)
+ value
+ }
+
+ override def equals(obj: scala.Any): Boolean = (obj != null) && (this.eq(obj.asInstanceOf[AnyRef]) || (obj match {
+ case c: Constant[_] => tpe == c.tpe && Objects.deepEquals(value, c.value)
+ case _ => false
+ }))
+
+ override def hashCode(): Int = Arrays.deepHashCode(Array(value.asInstanceOf[AnyRef], tpe))
+
+ override def toString: String = tpe.asInstanceOf[SType] match {
+ case SGroupElement if value.isInstanceOf[GroupElement] =>
+ s"ConstantNode(${value.asInstanceOf[GroupElement].showToString},$tpe)"
+ case SGroupElement =>
+ sys.error(s"Invalid value in Constant($value, $tpe)")
+ case SInt => s"IntConstant($value)"
+ case SLong => s"LongConstant($value)"
+ case SBoolean if value == true => "TrueLeaf"
+ case SBoolean if value == false => "FalseLeaf"
+ case _ => s"ConstantNode($value,$tpe)"
+ }
+}
+
+object Constant extends FixedCostValueCompanion {
+ override def opCode: OpCode = OpCode @@ ConstantCode
+
+ /** Cost of: returning value from Constant node. */
+ override val costKind = FixedCost(JitCost(5))
+
+ /** Immutable empty array, can be used to save allocations in many places. */
+ val EmptyArray = Array.empty[Constant[SType]]
+
+ /** Immutable empty IndexedSeq, can be used to save allocations in many places. */
+ val EmptySeq: IndexedSeq[Constant[SType]] = Array.empty[Constant[SType]]
+
+ /** Helper factory method. */
+ def apply[S <: SType](
+ value: S#WrappedType,
+ tpe: S): Constant[S] = ConstantNode(value, tpe)
+
+ /** Recognizer of Constant tree nodes used in patterns. */
+ def unapply[S <: SType](v: EvaluatedValue[S]): Option[(S#WrappedType, S)] = v match {
+ case ConstantNode(value, tpe) => Some((value, tpe))
+ case _ => None
+ }
+}
+
+/** Placeholder for a constant in ErgoTree. Zero based index in ErgoTree.constants array. */
+case class ConstantPlaceholder[S <: SType](
+ id: Int,
+ override val tpe: S) extends Value[S] {
+ def opType = SFunc(SInt, tpe)
+
+ override def companion: ValueCompanion = ConstantPlaceholder
+
+ override protected def eval(env: DataEnv)(implicit E: ErgoTreeEvaluator): Any = {
+ val c = E.constants(id)
+ addCost(ConstantPlaceholder.costKind)
+ val res = c.value
+ Value.checkType(c, res)
+ res
+ }
+}
+
+object ConstantPlaceholder extends ValueCompanion {
+ override def opCode: OpCode = ConstantPlaceholderCode
+
+ /** Cost of: accessing Constant in array by index. */
+ override val costKind = FixedCost(JitCost(1))
+}
+
+trait NotReadyValue[S <: SType] extends Value[S] {
+}
+
+// TODO v6.0: remove these TaggedVariable and TaggedVariableNode (https://github.com/ScorexFoundation/sigmastate-interpreter/issues/584)
+
+/** Reference a context variable by id. */
+trait TaggedVariable[T <: SType] extends NotReadyValue[T] {
+ val varId: Byte
+}
+
+case class TaggedVariableNode[T <: SType](varId: Byte, override val tpe: T)
+ extends TaggedVariable[T] {
+ override def companion = TaggedVariable
+
+ def opType: SFunc = Value.notSupportedError(this, "opType")
+}
+
+object TaggedVariable extends ValueCompanion {
+ override def opCode: OpCode = TaggedVariableCode
+
+ override def costKind: CostKind = FixedCost(JitCost(1))
+
+ def apply[T <: SType](varId: Byte, tpe: T): TaggedVariable[T] =
+ TaggedVariableNode(varId, tpe)
+}
+
+/** High-level interface to internal representation of Unit constants in ErgoTree. */
+object UnitConstant {
+ /** ErgoTree node that represent a literal of Unit type. It is global immutable value
+ * which should be reused wherever necessary to avoid allocations.
+ */
+ val instance = apply()
+
+ /** Constucts a fresh new instance of Unit literal node. */
+ def apply() = Constant[SUnit.type]((), SUnit)
+
+ /** Recognizer to pattern match on Unit constant literal nodes (aka Unit constants). */
+ def unapply(node: SValue): Boolean = node match {
+ case ConstantNode(_, SUnit) => true
+ case _ => false
+ }
+}
+
+object ByteConstant {
+ def apply(value: Byte): Constant[SByte.type] = Constant[SByte.type](value, SByte)
+}
+
+object ShortConstant {
+ def apply(value: Short): Constant[SShort.type] = Constant[SShort.type](value, SShort)
+}
+
+object IntConstant {
+ def apply(value: Int): Constant[SInt.type] = Constant[SInt.type](value, SInt)
+
+ def unapply(v: SValue): Option[Int] = v match {
+ case Constant(value: Int, SInt) => Some(value)
+ case _ => None
+ }
+
+ def Zero = IntConstant(0)
+}
+
+object LongConstant {
+ def apply(value: Long): Constant[SLong.type] = Constant[SLong.type](value, SLong)
+
+ def unapply(v: SValue): Option[Long] = v match {
+ case Constant(value: Long, SLong) => Some(value)
+ case _ => None
+ }
+}
+
+object BigIntConstant {
+ def apply(value: BigInt): Constant[SBigInt.type] = Constant[SBigInt.type](value, SBigInt)
+
+ def apply(value: BigInteger): Constant[SBigInt.type] = Constant[SBigInt.type](SigmaDsl.BigInt(value), SBigInt)
+
+ def apply(value: Long): Constant[SBigInt.type] = Constant[SBigInt.type](SigmaDsl.BigInt(BigInteger.valueOf(value)), SBigInt)
+}
+
+object StringConstant {
+ def apply(value: String): Constant[SString.type] = Constant[SString.type](value, SString)
+
+ def unapply(v: SValue): Option[String] = v match {
+ case Constant(value: String, SString) => Some(value)
+ case _ => None
+ }
+}
+
+object BoxConstant {
+ def apply(value: Box): Constant[SBox.type] = Constant[SBox.type](value, SBox)
+}
+
+object GroupElementConstant {
+ def apply(value: EcPointType): Constant[SGroupElement.type] = apply(SigmaDsl.GroupElement(value))
+
+ def apply(value: GroupElement): Constant[SGroupElement.type] = Constant[SGroupElement.type](value, SGroupElement)
+
+ def unapply(v: SValue): Option[GroupElement] = v match {
+ case Constant(value: GroupElement, SGroupElement) => Some(value)
+ case _ => None
+ }
+}
+
+object SigmaPropConstant {
+ def apply(value: SigmaProp): Constant[SSigmaProp.type] = Constant[SSigmaProp.type](value, SSigmaProp)
+
+ def apply(value: SigmaBoolean): Constant[SSigmaProp.type] = Constant[SSigmaProp.type](CSigmaProp(value), SSigmaProp)
+
+ def unapply(v: SValue): Option[SigmaProp] = v match {
+ case Constant(value: SigmaProp, SSigmaProp) => Some(value)
+ case _ => None
+ }
+}
+
+object AvlTreeConstant {
+ def apply(value: AvlTree): Constant[SAvlTree.type] = Constant[SAvlTree.type](value, SAvlTree)
+}
+
+object PreHeaderConstant {
+ def apply(value: PreHeader): Constant[SPreHeader.type] = Constant[SPreHeader.type](value, SPreHeader)
+
+ def unapply(v: SValue): Option[PreHeader] = v match {
+ case Constant(value: PreHeader, SPreHeader) => Some(value)
+ case _ => None
+ }
+}
+
+object HeaderConstant {
+ def apply(value: Header): Constant[SHeader.type] = Constant[SHeader.type](value, SHeader)
+
+ def unapply(v: SValue): Option[Header] = v match {
+ case Constant(value: Header, SHeader) => Some(value)
+ case _ => None
+ }
+}
+
+trait NotReadyValueInt extends NotReadyValue[SInt.type] {
+ override def tpe = SInt
+}
+
+trait NotReadyValueLong extends NotReadyValue[SLong.type] {
+ override def tpe = SLong
+}
+
+trait NotReadyValueBigInt extends NotReadyValue[SBigInt.type] {
+ override def tpe = SBigInt
+}
+
+/** Base type for evaluated tree nodes of Coll type. */
+trait EvaluatedCollection[T <: SType, C <: SCollection[T]] extends EvaluatedValue[C] {
+ /** Type descriptor of the collection elements. */
+ def elementType: T
+}
+
+object CollectionConstant {
+ def apply[T <: SType](
+ value: Coll[T#WrappedType],
+ elementType: T): Constant[SCollection[T]] =
+ Constant[SCollection[T]](value, SCollection(elementType))
+
+ def unapply[T <: SType](node: Value[SCollection[T]]): Option[(Coll[T#WrappedType], T)] = node match {
+ case c: Constant[SCollection[a]]@unchecked if c.tpe.isCollection =>
+ val v = c.value.asInstanceOf[Coll[T#WrappedType]]
+ val t = c.tpe.elemType
+ Some((v, t))
+ case _ => None
+ }
+}
+
+object ByteArrayConstant {
+ val ByteArrayTypeCode = (SCollectionType.CollectionTypeCode + SByte.typeCode).toByte
+
+ def apply(value: Coll[Byte]): CollectionConstant[SByte.type] = CollectionConstant[SByte.type](value, SByte)
+
+ def apply(value: Array[Byte]): CollectionConstant[SByte.type] = CollectionConstant[SByte.type](value.toColl, SByte)
+
+ def unapply(node: SValue): Option[Coll[Byte]] = node match {
+ case coll: CollectionConstant[SByte.type]@unchecked => coll match {
+ case CollectionConstant(arr, SByte) => Some(arr)
+ case _ => None
+ }
+ case _ => None
+ }
+}
+
+object ShortArrayConstant {
+ def apply(value: Coll[Short]): CollectionConstant[SShort.type] = CollectionConstant[SShort.type](value, SShort)
+
+ def apply(value: Array[Short]): CollectionConstant[SShort.type] = CollectionConstant[SShort.type](value.toColl, SShort)
+
+ def unapply(node: SValue): Option[Coll[Short]] = node match {
+ case coll: CollectionConstant[SShort.type]@unchecked => coll match {
+ case CollectionConstant(arr, SShort) => Some(arr)
+ case _ => None
+ }
+ case _ => None
+ }
+}
+
+object IntArrayConstant {
+ def apply(value: Coll[Int]): CollectionConstant[SInt.type] = CollectionConstant[SInt.type](value, SInt)
+
+ def apply(value: Array[Int]): CollectionConstant[SInt.type] = CollectionConstant[SInt.type](value.toColl, SInt)
+
+ def unapply(node: SValue): Option[Coll[Int]] = node match {
+ case coll: CollectionConstant[SInt.type]@unchecked => coll match {
+ case CollectionConstant(arr, SInt) => Some(arr)
+ case _ => None
+ }
+ case _ => None
+ }
+}
+
+object LongArrayConstant {
+ def apply(value: Coll[Long]): CollectionConstant[SLong.type] = CollectionConstant[SLong.type](value, SLong)
+
+ def apply(value: Array[Long]): CollectionConstant[SLong.type] = CollectionConstant[SLong.type](value.toColl, SLong)
+
+ def unapply(node: SValue): Option[Coll[Long]] = node match {
+ case coll: CollectionConstant[SLong.type]@unchecked => coll match {
+ case CollectionConstant(arr, SLong) => Some(arr)
+ case _ => None
+ }
+ case _ => None
+ }
+}
+
+object BigIntArrayConstant {
+ def apply(value: Coll[BigInt]): CollectionConstant[SBigInt.type] = CollectionConstant[SBigInt.type](value, SBigInt)
+
+ def apply(value: Array[BigInt]): CollectionConstant[SBigInt.type] = CollectionConstant[SBigInt.type](value.toColl, SBigInt)
+
+ def unapply(node: SValue): Option[Coll[BigInt]] = node match {
+ case coll: CollectionConstant[SBigInt.type]@unchecked => coll match {
+ case CollectionConstant(arr, SBigInt) => Some(arr)
+ case _ => None
+ }
+ case _ => None
+ }
+}
+
+object BoolArrayConstant {
+ val BoolArrayTypeCode = (SCollectionType.CollectionTypeCode + SBoolean.typeCode).toByte
+
+ def apply(value: Coll[Boolean]): CollectionConstant[SBoolean.type] = CollectionConstant[SBoolean.type](value, SBoolean)
+
+ def apply(value: Array[Boolean]): CollectionConstant[SBoolean.type] = apply(value.toColl)
+
+ def unapply(node: SValue): Option[Coll[Boolean]] = node match {
+ case coll: CollectionConstant[SBoolean.type]@unchecked => coll match {
+ case CollectionConstant(arr, SBoolean) => Some(arr)
+ case _ => None
+ }
+ case _ => None
+ }
+}
+
+trait NotReadyValueByteArray extends NotReadyValue[SByteArray] {
+ override def tpe = SByteArray
+}
+
+trait NotReadyValueAvlTree extends NotReadyValue[SAvlTree.type] {
+ override def tpe = SAvlTree
+}
+
+/** ErgoTree node that represents the operation of obtaining the generator of elliptic curve group.
+ * The generator g of the group is an element of the group such that, when written
+ * multiplicative form, every element of the group is a power of g.
+ */
+case object GroupGenerator extends EvaluatedValue[SGroupElement.type] with ValueCompanion {
+ override def opCode: OpCode = OpCodes.GroupGeneratorCode
+
+ override val costKind = FixedCost(JitCost(10))
+
+ override def tpe = SGroupElement
+
+ override val value = SigmaDsl.GroupElement(CryptoConstants.dlogGroup.generator)
+
+ override def companion = this
+
+ protected final override def eval(env: DataEnv)(implicit E: ErgoTreeEvaluator): Any = {
+ addCost(costKind)
+ SigmaDsl.groupGenerator
+ }
+}
+
+trait NotReadyValueGroupElement extends NotReadyValue[SGroupElement.type] {
+ override def tpe = SGroupElement
+}
+
+object BooleanConstant {
+ def fromBoolean(v: Boolean): BooleanConstant = if (v) TrueLeaf else FalseLeaf
+
+ def apply(value: Boolean): BooleanConstant = Constant[SBoolean.type](value, SBoolean)
+
+ def unapply(v: SValue): Option[Boolean] = v match {
+ case Constant(value: Boolean, SBoolean) => Some(value)
+ case _ => None
+ }
+}
+
+/** ErgoTree node which represents `true` literal. */
+object TrueLeaf extends ConstantNode[SBoolean.type](true, SBoolean) with ValueCompanion {
+ override def companion = this
+
+ override def opCode: OpCode = TrueCode
+
+ override def costKind: FixedCost = Constant.costKind
+
+ override def toString: String = "TrueLeaf"
+}
+
+/** ErgoTree node which represents `false` literal. */
+object FalseLeaf extends ConstantNode[SBoolean.type](false, SBoolean) with ValueCompanion {
+ override def companion = this
+
+ override def opCode: OpCode = FalseCode
+
+ override def costKind: FixedCost = Constant.costKind
+
+ override def toString: String = "FalseLeaf"
+}
+
+trait NotReadyValueBoolean extends NotReadyValue[SBoolean.type] {
+ override def tpe = SBoolean
+}
+
+trait NotReadyValueBox extends NotReadyValue[SBox.type] {
+ def tpe = SBox
+}
+
+/** ErgoTree node which converts a collection of expressions into a tuple of data values
+ * of different types. Each data value of the resulting collection is obtained by
+ * evaluating the corresponding expression in `items`. All items may have different
+ * types.
+ *
+ * @param items source collection of expressions
+ */
+case class Tuple(items: IndexedSeq[Value[SType]])
+ extends EvaluatedValue[STuple] // note, this superclass is required as Tuple can be in a register
+ with EvaluatedCollection[SAny.type, STuple] {
+ override def companion = Tuple
+
+ override lazy val tpe = STuple(items.map(_.tpe))
+
+ override def opType: SFunc = ???
+
+ override def elementType: SAny.type = SAny
+
+ override lazy val value = {
+ val xs = items.cast[EvaluatedValue[SAny.type]].map(_.value)
+ implicit val tAny: RType[Any] = sigma.AnyType
+ Colls.fromArray(xs.toArray)
+ }
+
+ protected final override def eval(env: DataEnv)(implicit E: ErgoTreeEvaluator): Any = {
+ // in v5.0 version we support only tuples of 2 elements to be equivalent with v4.x
+ if (items.length != 2)
+ syntax.error(s"Invalid tuple $this")
+ val item0 = items(0)
+ val x = item0.evalTo[Any](env)
+ Value.checkType(item0, x)
+ val item1 = items(1)
+ val y = item1.evalTo[Any](env)
+ Value.checkType(item1, y)
+ val res = (x, y) // special representation for pairs (to pass directly to Coll primitives)
+ addCost(Tuple.costKind)
+ res
+ }
+}
+
+object Tuple extends FixedCostValueCompanion {
+ override def opCode: OpCode = TupleCode
+
+ /** Cost of: 1) allocating a new tuple (of limited max size) */
+ override val costKind = FixedCost(JitCost(15))
+
+ def apply(items: Value[SType]*): Tuple = Tuple(items.toIndexedSeq)
+}
+
+/** ErgoTree node which converts a collection of expressions into a collection of data
+ * values. Each data value of the resulting collection is obtained by evaluating the
+ * corresponding expression in `items`. All items must have the same type.
+ *
+ * @param items source collection of expressions
+ * @param elementType type descriptor of elements in the resulting collection
+ */
+case class ConcreteCollection[V <: SType](items: Seq[Value[V]], elementType: V)
+ extends EvaluatedCollection[V, SCollection[V]] {
+ // TODO uncomment and make sure Ergo works with it, i.e. complex data types are never used for `items`.
+ // There is nothing wrong in using List, Vector and other fancy types as a concrete representation
+ // of `items`, but these types have sub-optimal performance (2-3x overhead comparing to WrappedArray)
+ // which is immediately visible in profile.
+ // NOTE, the assert below should be commented before production release.
+ // Is it there for debuging only, basically to catch call stacks where the fancy types may
+ // occasionally be used.
+ // assert(
+ // items.isInstanceOf[mutable.WrappedArray[_]] ||
+ // items.isInstanceOf[ArrayBuffer[_]] ||
+ // items.isInstanceOf[mutable.ArraySeq[_]],
+ // s"Invalid types of items ${items.getClass}")
+
+ private val isBooleanConstants = elementType == SBoolean && items.forall(_.isInstanceOf[Constant[_]])
+
+ override def companion =
+ if (isBooleanConstants) ConcreteCollectionBooleanConstant
+ else ConcreteCollection
+
+ val tpe = SCollection[V](elementType)
+
+ implicit lazy val tElement: RType[V#WrappedType] = Evaluation.stypeToRType(elementType)
+
+ // TODO refactor: this method is not used and can be removed
+ lazy val value = {
+ val xs = items.cast[EvaluatedValue[V]].map(_.value)
+ Colls.fromArray(xs.toArray(tElement.classTag))
+ }
+
+ protected final override def eval(env: DataEnv)(implicit E: ErgoTreeEvaluator): Any = {
+ val len = items.length
+ addCost(ConcreteCollection.costKind)
+ val is = Array.ofDim[V#WrappedType](len)(tElement.classTag)
+ cfor(0)(_ < len, _ + 1) { i =>
+ val item = items(i)
+ val itemV = item.evalTo[V#WrappedType](env)
+ Value.checkType(item, itemV) // necessary because cast to V#WrappedType is erased
+ is(i) = itemV
+ }
+ Colls.fromArray(is)
+ }
+}
+
+object ConcreteCollection extends FixedCostValueCompanion {
+ override def opCode: OpCode = ConcreteCollectionCode
+
+ /** Cost of: allocating new collection
+ *
+ * @see ConcreteCollection_PerItem */
+ override val costKind = FixedCost(JitCost(20))
+
+ def fromSeq[V <: SType](items: Seq[Value[V]])(implicit tV: V): ConcreteCollection[V] =
+ ConcreteCollection(items, tV)
+
+ def fromItems[V <: SType](items: Value[V]*)(implicit tV: V): ConcreteCollection[V] =
+ ConcreteCollection(items, tV)
+}
+
+object ConcreteCollectionBooleanConstant extends ValueCompanion {
+ override def opCode: OpCode = ConcreteCollectionBooleanConstantCode
+
+ override def costKind = ConcreteCollection.costKind
+}
+
+trait LazyCollection[V <: SType] extends NotReadyValue[SCollection[V]]
+
+sealed trait BlockItem extends NotReadyValue[SType] {
+ def id: Int
+
+ def rhs: SValue
+
+ def isValDef: Boolean
+}
+
+object BlockItem {
+ /** Immutable empty array, can be used to save allocations in many places. */
+ val EmptyArray = Array.empty[BlockItem]
+
+ /** Immutable empty IndexedSeq to save allocations in many places. */
+ val EmptySeq: IndexedSeq[BlockItem] = EmptyArray
+}
+
+/** IR node for let-bound expressions `let x = rhs` which is ValDef, or `let f[T] = rhs` which is FunDef.
+ * These nodes are used to represent ErgoTrees after common sub-expression elimination.
+ * This representation is more compact in serialized form.
+ *
+ * @param id unique identifier of the variable in the current scope. */
+case class ValDef(
+ override val id: Int,
+ tpeArgs: Seq[STypeVar],
+ override val rhs: SValue) extends BlockItem {
+ require(id >= 0, "id must be >= 0")
+
+ override def companion = if (tpeArgs.isEmpty) ValDef else FunDef
+
+ override def tpe: SType = rhs.tpe
+
+ override def isValDef: Boolean = tpeArgs.isEmpty
+
+ /** This is not used as operation, but rather to form a program structure */
+ override def opType: SFunc = Value.notSupportedError(this, "opType")
+}
+
+object ValDef extends ValueCompanion {
+ override def opCode: OpCode = ValDefCode
+
+ override def costKind = Value.notSupportedError(this, "costKind")
+
+ def apply(id: Int, rhs: SValue): ValDef = ValDef(id, Nil, rhs)
+}
+
+object FunDef extends ValueCompanion {
+ override def opCode: OpCode = FunDefCode
+
+ override def costKind = Value.notSupportedError(this, "costKind")
+
+ def unapply(d: BlockItem): Option[(Int, Seq[STypeVar], SValue)] = d match {
+ case ValDef(id, targs, rhs) if !d.isValDef => Some((id, targs, rhs))
+ case _ => None
+ }
+}
+
+/** Special node which represents a reference to ValDef it was introduced as result of
+ * CSE. */
+case class ValUse[T <: SType](valId: Int, tpe: T) extends NotReadyValue[T] {
+ override def companion = ValUse
+
+ /** This is not used as operation, but rather to form a program structure */
+ def opType: SFunc = Value.notSupportedError(this, "opType")
+
+ protected final override def eval(env: DataEnv)(implicit E: ErgoTreeEvaluator): Any = {
+ addCost(ValUse.costKind)
+ val res = env.getOrElse(valId, syntax.error(s"cannot resolve $this"))
+ Value.checkType(this, res)
+ res
+ }
+}
+
+object ValUse extends FixedCostValueCompanion {
+ override def opCode: OpCode = ValUseCode
+
+ /** Cost of: 1) Lookup in immutable HashMap by valId: Int 2) alloc of Some(v) */
+ override val costKind = FixedCost(JitCost(5))
+}
+
+/** The order of ValDefs in the block is used to assign ids to ValUse(id) nodes
+ * For all i: items(i).id == {number of ValDefs preceded in a graph} with respect to topological order.
+ * Specific topological order doesn't really matter, what is important is to preserve semantic linkage
+ * between ValUse(id) and ValDef with the corresponding id.
+ * This convention allow to valid serializing ids because we always serializing and deserializing
+ * in a fixed well defined order.
+ */
+case class BlockValue(
+ items: IndexedSeq[BlockItem],
+ result: SValue) extends NotReadyValue[SType] {
+ override def companion = BlockValue
+
+ def tpe: SType = result.tpe
+
+ /** This is not used as operation, but rather to form a program structure */
+ def opType: SFunc = Value.notSupportedError(this, "opType")
+
+ protected final override def eval(env: DataEnv)(implicit E: ErgoTreeEvaluator): Any = {
+ var curEnv = env
+ val len = items.length
+ addSeqCostNoOp(BlockValue.costKind, len)
+ cfor(0)(_ < len, _ + 1) { i =>
+ val vd = items(i).asInstanceOf[ValDef]
+ val v = vd.rhs.evalTo[Any](curEnv)
+ Value.checkType(vd, v)
+ E.addFixedCost(FuncValue.AddToEnvironmentDesc_CostKind,
+ FuncValue.AddToEnvironmentDesc) {
+ curEnv = curEnv + (vd.id -> v)
+ }
+ }
+ val res = result.evalTo[Any](curEnv)
+ Value.checkType(result, res)
+ res
+ }
+}
+
+object BlockValue extends ValueCompanion {
+ override def opCode: OpCode = BlockValueCode
+
+ override val costKind = PerItemCost(
+ baseCost = JitCost(1), perChunkCost = JitCost(1), chunkSize = 10)
+}
+
+/**
+ * @param args parameters list, where each parameter has an id and a type.
+ * @param body expression, which refers function parameters with ValUse.
+ */
+case class FuncValue(
+ args: IndexedSeq[(Int, SType)],
+ body: Value[SType]) extends NotReadyValue[SFunc] {
+ import FuncValue._
+
+ override def companion = FuncValue
+
+ lazy val tpe: SFunc = {
+ val nArgs = args.length
+ val argTypes = new Array[SType](nArgs)
+ cfor(0)(_ < nArgs, _ + 1) { i =>
+ argTypes(i) = args(i)._2
+ }
+ SFunc(argTypes, body.tpe)
+ }
+
+ /** This is not used as operation, but rather to form a program structure */
+ override def opType: SFunc = SFunc(ArraySeq.empty, tpe)
+
+ protected final override def eval(env: DataEnv)(implicit E: ErgoTreeEvaluator): Any = {
+ addCost(FuncValue.costKind)
+ if (args.length == 1) {
+ val arg0 = args(0)
+ (vArg: Any) => {
+ Value.checkType(arg0._2, vArg)
+ var env1: DataEnv = null
+ E.addFixedCost(AddToEnvironmentDesc_CostKind, AddToEnvironmentDesc) {
+ env1 = env + (arg0._1 -> vArg)
+ }
+ val res = body.evalTo[Any](env1)
+ Value.checkType(body, res)
+ res
+ }
+ } else {
+ syntax.error(s"Function must have 1 argument, but was: $this")
+ }
+ }
+}
+
+object FuncValue extends FixedCostValueCompanion {
+ val AddToEnvironmentDesc = NamedDesc("AddToEnvironment")
+
+ /** Cost of: adding value to evaluator environment */
+ val AddToEnvironmentDesc_CostKind = FixedCost(JitCost(5))
+
+ override def opCode: OpCode = FuncValueCode
+
+ /** Cost of: 1) switch on the number of args 2) allocating a new Scala closure
+ * Old cost: ("Lambda", "() => (D1) => R", lambdaCost), */
+ override val costKind = FixedCost(JitCost(5))
+
+ def apply(argId: Int, tArg: SType, body: SValue): FuncValue =
+ FuncValue(IndexedSeq((argId, tArg)), body)
+}
+
+/** Frontend representation of a block of Val definitions.
+ * { val x = ...; val y = ... }
+ * This node is not part of ErgoTree and hence have Undefined opCode. */
+case class Block(bindings: Seq[Val], result: SValue) extends Value[SType] {
+ override def companion = Block
+
+ override def tpe: SType = result.tpe
+
+ /** This is not used as operation, but rather to form a program structure */
+ override def opType: SFunc = Value.notSupportedError(this, "opType")
+}
+
+object Block extends ValueCompanion {
+ override def opCode: OpCode = OpCodes.Undefined
+
+ override def costKind: CostKind = Value.notSupportedError(this, "costKind")
+
+ /** Create a Block node with a single Val definition. */
+ def apply(let: Val, result: SValue)(implicit @unused o1: Overloaded1): Block =
+ Block(Seq(let), result)
+}
+
+/** IR node to represent explicit Zero Knowledge scope in ErgoTree.
+ * Compiler checks Zero Knowledge properties and issue error message is case of violations.
+ * ZK-scoping is optional, it can be used when the user want to ensure Zero Knowledge of
+ * specific set of operations.
+ * Usually it will require simple restructuring of the code to make the scope body explicit.
+ * Invariants checked by the compiler:
+ * - single ZKProof in ErgoTree in a root position
+ * - no boolean operations in the body, because otherwise the result may be disclosed
+ * - all the operations are over SigmaProp values
+ *
+ * For motivation and details see https://github.com/ScorexFoundation/sigmastate-interpreter/issues/236
+ * */
+case class ZKProofBlock(body: SigmaPropValue) extends BoolValue {
+ override def companion = ZKProofBlock
+
+ override def tpe = SBoolean
+
+ override def opType: SFunc = ZKProofBlock.OpType
+}
+
+object ZKProofBlock extends ValueCompanion {
+ override def opCode: OpCode = OpCodes.Undefined
+
+ override def costKind: CostKind = Value.notSupportedError(this, "costKind")
+
+ val OpType = SFunc(SSigmaProp, SBoolean)
+}
+
+trait Val extends Value[SType] {
+ val name : String
+ val givenType: SType
+ val body : SValue
+}
+
+object Val {
+ def apply(name: String, body: SValue): Val = ValNode(name, NoType, body)
+
+ def apply(
+ name: String,
+ givenType: SType,
+ body: SValue): Val = ValNode(name, givenType, body)
+
+ def unapply(v: SValue): Option[(String, SType, SValue)] = v match {
+ case ValNode(name, givenType, body) => Some((name, givenType, body))
+ case _ => None
+ }
+}
+
+case class ValNode(
+ name: String,
+ givenType: SType,
+ body: SValue) extends Val {
+ override def companion = ValNode
+
+ override def tpe: SType = givenType ?: body.tpe
+
+ /** This is not used as operation, but rather to form a program structure */
+ override def opType: SFunc = Value.notSupportedError(this, "opType")
+}
+
+object ValNode extends ValueCompanion {
+ override def opCode: OpCode = OpCodes.Undefined
+
+ override def costKind: CostKind = Value.notSupportedError(this, "costKind")
+}
+
+/** Frontend node to select a field from an object. Should be transformed to SelectField */
+case class Select(
+ obj: Value[SType],
+ field: String,
+ resType: Option[SType] = None) extends Value[SType] {
+ override def companion = Select
+
+ override val tpe: SType = resType.getOrElse(obj.tpe match {
+ case p: SProduct =>
+ MethodsContainer.getMethod(p, field) match {
+ case Some(m) => m.stype
+ case None => NoType
+ }
+ case _ => NoType
+ })
+
+ override def opType: SFunc = SFunc(obj.tpe, tpe)
+}
+
+object Select extends ValueCompanion {
+ override def opCode: OpCode = OpCodes.Undefined
+
+ override def costKind: CostKind = Value.notSupportedError(this, "costKind")
+}
+
+/** Frontend node to represent variable names parsed in a source code.
+ * Should be resolved during compilation to lambda argument, Val definition or
+ * compilation environment value. */
+case class Ident(name: String, tpe: SType = NoType) extends Value[SType] {
+ override def companion = Ident
+
+ override def opType: SFunc = SFunc(ArraySeq.empty, tpe)
+}
+
+object Ident extends ValueCompanion {
+ override def opCode: OpCode = OpCodes.Undefined
+
+ override def costKind: CostKind = Value.notSupportedError(this, "costKind")
+
+ def apply(name: String): Ident = Ident(name, NoType)
+}
+
+// TODO refactor: move to sigma.ast
+
+/** ErgoTree node which represents application of function `func` to the given arguments.
+ *
+ * @param func expression which evaluates to a function
+ * @param args arguments of the function application
+ */
+case class Apply(
+ func: Value[SType],
+ args: IndexedSeq[Value[SType]]) extends Value[SType] {
+ override def companion = Apply
+
+ override lazy val tpe : SType = func.tpe match {
+ case SFunc(_, r, _) => r
+ case tColl: SCollectionType[_] => tColl.elemType
+ case _ => NoType
+ }
+
+ override lazy val opType: SFunc = {
+ val nArgs = args.length
+ val argTypes = new Array[SType](nArgs + 1)
+ argTypes(0) = func.tpe
+ cfor(0)(_ < nArgs, _ + 1) { i =>
+ argTypes(i + 1) = args(i).tpe
+ }
+ SFunc(argTypes, tpe)
+ }
+
+ protected final override def eval(env: DataEnv)(implicit E: ErgoTreeEvaluator): Any = {
+ addCost(Apply.costKind)
+ if (args.length == 1) {
+ val fV = func.evalTo[Any => Any](env)
+ val argV = args(0).evalTo[Any](env)
+ fV(argV)
+ } else {
+ // zero or more than 1 argument functions are not supported in v4.x, v5.0
+ // see `case Terms.Apply(f, Seq(x))` in RuntimeCosting which means other cases are not supported.
+ syntax.error(s"Function application must have 1 argument, but was: $this")
+ }
+ }
+}
+
+object Apply extends FixedCostValueCompanion {
+ override def opCode: OpCode = OpCodes.FuncApplyCode
+
+ /** Cost of: 1) switch on the number of args 2) Scala method call 3) add args to env
+ * Old cost: lambdaInvoke == 30 */
+ override val costKind = FixedCost(JitCost(30))
+}
+
+/** Apply types for type parameters of input value. */
+case class ApplyTypes(
+ input: Value[SType],
+ tpeArgs: Seq[SType]) extends Value[SType] { node =>
+ override def companion = ApplyTypes
+
+ override lazy val tpe: SType = input.tpe match {
+ case funcType: SFunc =>
+ val subst = funcType.tpeParams.map(_.ident).zip(tpeArgs).toMap
+ applySubst(input.tpe, subst)
+ case _ => input.tpe
+ }
+
+ /** This is not used as operation, but rather to form a program structure */
+ override def opType: SFunc = Value.notSupportedError(this, "opType")
+}
+
+object ApplyTypes extends ValueCompanion {
+ override def opCode: OpCode = OpCodes.Undefined
+
+ override def costKind: CostKind = Value.notSupportedError(this, "costKind")
+}
+
+/** Frontend node to represent potential method call in a source code.
+ * Should be resolved during compilation to MethodCall.
+ * Cannot be serialized to ErgoTree. */
+case class MethodCallLike(
+ obj: Value[SType],
+ name: String,
+ args: IndexedSeq[Value[SType]],
+ tpe: SType = NoType) extends Value[SType] {
+ override def companion = MethodCallLike
+
+ override def opType: SFunc = SFunc(obj.tpe +: args.map(_.tpe), tpe)
+}
+
+object MethodCallLike extends ValueCompanion {
+ override def opCode: OpCode = OpCodes.Undefined
+
+ override def costKind: CostKind = Value.notSupportedError(this, "costKind")
+}
+
+/** Represents in ErgoTree an invocation of method of the object `obj` with arguments `args`.
+ * The SMethod instances in STypeCompanions may have type STypeIdent in methods types,
+ * but valid ErgoTree should have SMethod instances specialized for specific types of
+ * obj and args using `specializeFor`.
+ * This means, if we save typeId, methodId, and we save all the arguments,
+ * we can restore the specialized SMethod instance.
+ * This work by induction, if we assume all arguments are monomorphic,
+ * then we can make MethodCall monomorphic.
+ * Thus, all ErgoTree instances are monomorphic by construction.
+ *
+ * @param obj object on which method will be invoked
+ * @param method method to be invoked
+ * @param args arguments passed to the method on invocation
+ * @param typeSubst a map of concrete type for each generic type parameter
+ */
+case class MethodCall(
+ obj: Value[SType],
+ method: SMethod,
+ args: IndexedSeq[Value[SType]],
+ typeSubst: Map[STypeVar, SType]) extends Value[SType] {
+ override def companion = if (args.isEmpty) PropertyCall else MethodCall
+
+ override def opType: SFunc = SFunc(obj.tpe +: args.map(_.tpe), tpe)
+
+ override val tpe: SType = method.stype match {
+ case f: SFunc => f.tRange.withSubstTypes(typeSubst)
+ case t => t.withSubstTypes(typeSubst)
+ }
+
+ /** @hotspot don't beautify this code */
+ protected final override def eval(env: DataEnv)(implicit E: ErgoTreeEvaluator): Any = {
+ val objV = obj.evalTo[Any](env)
+ addCost(MethodCall.costKind) // MethodCall overhead
+ method.costKind match {
+ case fixed: FixedCost =>
+ val extra = method.extraDescriptors
+ val extraLen = extra.length
+ val len = args.length
+ val argsBuf = new Array[Any](len + extraLen)
+ cfor(0)(_ < len, _ + 1) { i =>
+ argsBuf(i) = args(i).evalTo[Any](env)
+ }
+ cfor(0)(_ < extraLen, _ + 1) { i =>
+ argsBuf(len + i) = extra(i)
+ }
+ var res: Any = null
+ E.addFixedCost(fixed, method.opDesc) {
+ res = method.invokeFixed(objV, argsBuf)
+ }
+ res
+ case _ =>
+ val len = args.length
+ val argsBuf = new Array[Any](len + 3)
+ argsBuf(0) = this
+ argsBuf(1) = objV
+ cfor(0)(_ < len, _ + 1) { i =>
+ argsBuf(i + 2) = args(i).evalTo[Any](env)
+ }
+ argsBuf(argsBuf.length - 1) = E
+ val evalMethod = method.genericMethod.evalMethod
+ evalMethod.invoke(method.objType, argsBuf.asInstanceOf[Array[AnyRef]]: _*)
+ }
+ }
+}
+
+object MethodCall extends FixedCostValueCompanion {
+ override def opCode: OpCode = OpCodes.MethodCallCode
+
+ /** Cost of: 1) packing args into Array 2) RMethod.invoke */
+ override val costKind = FixedCost(JitCost(4))
+
+ /** Helper constructor which allows to cast the resulting node to the specified
+ * [[sigma.ast.Value]] type `T`.
+ *
+ * @see [[sigmastate.lang.Terms.MethodCall]]
+ */
+ def typed[T <: SValue](
+ obj: Value[SType],
+ method: SMethod,
+ args: IndexedSeq[Value[SType]],
+ typeSubst: Map[STypeVar, SType]): T = {
+ MethodCall(obj, method, args, typeSubst).asInstanceOf[T]
+ }
+}
+
+object PropertyCall extends FixedCostValueCompanion {
+ override def opCode: OpCode = OpCodes.PropertyCallCode
+
+ /** Cost of: 1) packing args into Array 2) RMethod.invoke */
+ override val costKind = FixedCost(JitCost(4))
+}
+
+/** Frontend implementation of lambdas. Should be transformed to FuncValue. */
+case class Lambda(
+ tpeParams: Seq[STypeParam],
+ args: IndexedSeq[(String, SType)],
+ givenResType: SType,
+ body: Option[Value[SType]]) extends Value[SFunc] {
+ require(!(tpeParams.nonEmpty && body.nonEmpty), s"Generic function definitions are not supported, but found $this")
+
+ override def companion = Lambda
+
+ override lazy val tpe: SFunc = {
+ val sRange = givenResType ?: body.fold(NoType: SType)(_.tpe)
+ SFunc(args.map(_._2), sRange, tpeParams)
+ }
+
+ /** This is not used as operation, but rather to form a program structure */
+ override def opType: SFunc = SFunc(Vector(), tpe)
+}
+
+object Lambda extends ValueCompanion {
+ override def opCode: OpCode = OpCodes.Undefined
+
+ override def costKind: CostKind = Value.notSupportedError(this, "costKind")
+
+ def apply(
+ args: IndexedSeq[(String, SType)],
+ resTpe: SType,
+ body: Value[SType]): Lambda =
+ Lambda(Nil, args, resTpe, Some(body))
+
+ def apply(
+ args: IndexedSeq[(String, SType)],
+ resTpe: SType,
+ body: Option[Value[SType]]): Lambda =
+ Lambda(Nil, args, resTpe, body)
+
+ def apply(
+ args: IndexedSeq[(String, SType)],
+ body: Value[SType]): Lambda = Lambda(Nil, args, NoType, Some(body))
+}
+
+/** When interpreted evaluates to a ByteArrayConstant built from Context.minerPubkey */
+case object MinerPubkey extends NotReadyValueByteArray with ValueCompanion {
+ override def opCode: OpCode = OpCodes.MinerPubkeyCode
+ /** Cost of calling Context.minerPubkey Scala method. */
+ override val costKind = FixedCost(JitCost(20))
+ override val opType = SFunc(SContext, SCollection.SByteArray)
+ override def companion = this
+ protected final override def eval(env: DataEnv)(implicit E: ErgoTreeEvaluator): Any = {
+ addCost(this.costKind)
+ E.context.minerPubKey
+ }
+}
+
+/** When interpreted evaluates to a IntConstant built from Context.currentHeight */
+case object Height extends NotReadyValueInt with FixedCostValueCompanion {
+ override def companion = this
+ override def opCode: OpCode = OpCodes.HeightCode
+ /** Cost of: 1) Calling Context.HEIGHT Scala method. */
+ override val costKind = FixedCost(JitCost(26))
+ override val opType = SFunc(SContext, SInt)
+ protected final override def eval(env: DataEnv)(implicit E: ErgoTreeEvaluator): Any = {
+ addCost(this.costKind)
+ E.context.HEIGHT
+ }
+}
+
+/** When interpreted evaluates to a collection of BoxConstant built from Context.boxesToSpend */
+case object Inputs extends LazyCollection[SBox.type] with FixedCostValueCompanion {
+ override def companion = this
+ override def opCode: OpCode = OpCodes.InputsCode
+ /** Cost of: 1) Calling Context.INPUTS Scala method. */
+ override val costKind = FixedCost(JitCost(10))
+ override def tpe = SCollection.SBoxArray
+ override val opType = SFunc(SContext, tpe)
+ protected final override def eval(env: DataEnv)(implicit E: ErgoTreeEvaluator): Any = {
+ addCost(this.costKind)
+ E.context.INPUTS
+ }
+}
+
+/** When interpreted evaluates to a collection of BoxConstant built from Context.spendingTransaction.outputs */
+case object Outputs extends LazyCollection[SBox.type] with FixedCostValueCompanion {
+ override def companion = this
+ override def opCode: OpCode = OpCodes.OutputsCode
+ /** Cost of: 1) Calling Context.OUTPUTS Scala method. */
+ override val costKind = FixedCost(JitCost(10))
+ override def tpe = SCollection.SBoxArray
+ override val opType = SFunc(SContext, tpe)
+ protected final override def eval(env: DataEnv)(implicit E: ErgoTreeEvaluator): Any = {
+ addCost(this.costKind)
+ E.context.OUTPUTS
+ }
+}
+
+/** When interpreted evaluates to a AvlTreeConstant built from Context.lastBlockUtxoRoot */
+case object LastBlockUtxoRootHash extends NotReadyValueAvlTree with ValueCompanion {
+ override def companion = this
+ override def opCode: OpCode = OpCodes.LastBlockUtxoRootHashCode
+
+ /** Cost of: 1) Calling Context.LastBlockUtxoRootHash Scala method. */
+ override val costKind = FixedCost(JitCost(15))
+
+ override val opType = SFunc(SContext, tpe)
+ protected final override def eval(env: DataEnv)(implicit E: ErgoTreeEvaluator): Any = {
+ addCost(this.costKind)
+ E.context.LastBlockUtxoRootHash
+ }
+}
+
+/** When interpreted evaluates to a BoxConstant built from context.boxesToSpend(context.selfIndex) */
+case object Self extends NotReadyValueBox with FixedCostValueCompanion {
+ override def companion = this
+ override def opCode: OpCode = OpCodes.SelfCode
+ /** Cost of: 1) Calling Context.SELF Scala method. */
+ override val costKind = FixedCost(JitCost(10))
+ override val opType = SFunc(SContext, SBox)
+ protected final override def eval(env: DataEnv)(implicit E: ErgoTreeEvaluator): Any = {
+ addCost(this.costKind)
+ E.context.SELF
+ }
+}
+
+/** When interpreted evaluates to the singleton instance of [[sigma.Context]].
+ * Corresponds to `CONTEXT` variable in ErgoScript which can be used like `CONTEXT.headers`.
+ */
+case object Context extends NotReadyValue[SContext.type] with ValueCompanion {
+ override def companion = this
+ override def opCode: OpCode = OpCodes.ContextCode
+
+ /** Cost of: 1) accessing global Context instance. */
+ override val costKind = FixedCost(JitCost(1))
+
+ override def tpe: SContext.type = SContext
+ override val opType: SFunc = SFunc(SUnit, SContext)
+ protected final override def eval(env: DataEnv)(implicit E: ErgoTreeEvaluator): Any = {
+ addCost(this.costKind)
+ E.context
+ }
+}
+
+/** When interpreted evaluates to the singleton instance of [[sigma.SigmaDslBuilder]].
+ * Corresponds to `Global` variable in ErgoScript which can be used like `Global.groupGenerator`.
+ */
+case object Global extends NotReadyValue[SGlobal.type] with FixedCostValueCompanion {
+ override def companion = this
+ override def opCode: OpCode = OpCodes.GlobalCode
+ /** Cost of: 1) accessing Global instance. */
+ override val costKind = FixedCost(JitCost(5))
+ override def tpe: SGlobal.type = SGlobal
+ override val opType: SFunc = SFunc(SUnit, SGlobal)
+ protected final override def eval(env: DataEnv)(implicit E: ErgoTreeEvaluator): Any = {
+ addCost(this.costKind)
+ CSigmaDslBuilder
+ }
+}
+
+
diff --git a/interpreter/shared/src/main/scala/sigmastate/crypto/BcDlogGroup.scala b/data/shared/src/main/scala/sigma/crypto/BcDlogGroup.scala
similarity index 98%
rename from interpreter/shared/src/main/scala/sigmastate/crypto/BcDlogGroup.scala
rename to data/shared/src/main/scala/sigma/crypto/BcDlogGroup.scala
index 030b333032..721cd74f5e 100644
--- a/interpreter/shared/src/main/scala/sigmastate/crypto/BcDlogGroup.scala
+++ b/data/shared/src/main/scala/sigma/crypto/BcDlogGroup.scala
@@ -1,10 +1,7 @@
-package sigmastate.crypto
+package sigma.crypto
-import java.math.BigInteger
-import sigmastate.crypto.BigIntegers
import debox.cfor
-import sigmastate.crypto.{CryptoContext, CryptoFacade}
-
+import java.math.BigInteger
import scala.collection.mutable
diff --git a/interpreter/shared/src/main/scala/sigmastate/crypto/BigIntegers.scala b/data/shared/src/main/scala/sigma/crypto/BigIntegers.scala
similarity index 98%
rename from interpreter/shared/src/main/scala/sigmastate/crypto/BigIntegers.scala
rename to data/shared/src/main/scala/sigma/crypto/BigIntegers.scala
index 43bded8e09..4465184580 100644
--- a/interpreter/shared/src/main/scala/sigmastate/crypto/BigIntegers.scala
+++ b/data/shared/src/main/scala/sigma/crypto/BigIntegers.scala
@@ -1,7 +1,6 @@
-package sigmastate.crypto
+package sigma.crypto
import java.math.BigInteger
-import sigmastate.crypto.SecureRandom
/** Re-implementation in Scala of select set of utility methods from
* org.bouncycastle.util.BigIntegers.
diff --git a/interpreter/shared/src/main/scala/sigmastate/crypto/CryptoConstants.scala b/data/shared/src/main/scala/sigma/crypto/CryptoConstants.scala
similarity index 74%
rename from interpreter/shared/src/main/scala/sigmastate/crypto/CryptoConstants.scala
rename to data/shared/src/main/scala/sigma/crypto/CryptoConstants.scala
index 59525bec7e..682ef83076 100644
--- a/interpreter/shared/src/main/scala/sigmastate/crypto/CryptoConstants.scala
+++ b/data/shared/src/main/scala/sigma/crypto/CryptoConstants.scala
@@ -1,12 +1,9 @@
-package sigmastate.crypto
+package sigma.crypto
import java.math.BigInteger
/** Constants used in crypto operations implementation. */
object CryptoConstants {
- /** Type of group elements used in the signature scheme. */
- type EcPointType = Ecp
-
/** Length of encoded group element in bytes. */
val EncodedGroupElementLength: Byte = 33
@@ -14,23 +11,15 @@ object CryptoConstants {
val dlogGroup: BcDlogGroup = SecP256K1Group
/** Secure random generator used in the signature scheme. */
- val secureRandom: sigmastate.crypto.SecureRandom = dlogGroup.secureRandom
+ val secureRandom: sigma.crypto.SecureRandom = dlogGroup.secureRandom
/** Size of the binary representation of any group element (2 ^ groupSizeBits == ) */
val groupSizeBits: Int = 256
- /** Number of bytes to represent any group element as byte array */
- val groupSize: Int = 256 / 8 //32 bytes
/** Group order, i.e. number of elements in the group */
val groupOrder: BigInteger = dlogGroup.order
- /** Length of hash function used in the signature scheme. Blake2b hash function is used. */
- val hashLengthBits = 256
-
- /** Length of hash in bytes. */
- val hashLength: Int = hashLengthBits / 8
-
/** A size of challenge in Sigma protocols, in bits.
* If this anything but 192, threshold won't work, because we have polynomials over GF(2^192) and no others.
* So DO NOT change the value without implementing polynomials over GF(2^soundnessBits) first
diff --git a/interpreter/shared/src/main/scala/sigmastate/crypto/DlogGroup.scala b/data/shared/src/main/scala/sigma/crypto/DlogGroup.scala
similarity index 99%
rename from interpreter/shared/src/main/scala/sigmastate/crypto/DlogGroup.scala
rename to data/shared/src/main/scala/sigma/crypto/DlogGroup.scala
index 80ab2e372d..5c8c94ddd2 100644
--- a/interpreter/shared/src/main/scala/sigmastate/crypto/DlogGroup.scala
+++ b/data/shared/src/main/scala/sigma/crypto/DlogGroup.scala
@@ -1,4 +1,4 @@
-package sigmastate.crypto
+package sigma.crypto
import java.math.BigInteger
diff --git a/interpreter/shared/src/main/scala/sigmastate/eval/BigIntegerOps.scala b/data/shared/src/main/scala/sigma/data/BigIntegerOps.scala
similarity index 93%
rename from interpreter/shared/src/main/scala/sigmastate/eval/BigIntegerOps.scala
rename to data/shared/src/main/scala/sigma/data/BigIntegerOps.scala
index 058676b0fe..168b2f8266 100644
--- a/interpreter/shared/src/main/scala/sigmastate/eval/BigIntegerOps.scala
+++ b/data/shared/src/main/scala/sigma/data/BigIntegerOps.scala
@@ -1,10 +1,9 @@
-package sigmastate.eval
+package sigma.data
-import sigma.data.{ExactOrderingImpl, ExactIntegral}
+import sigma._
+import sigma.eval.Extensions.IntExt
import scala.math.{Integral, Ordering}
-import sigma._
-import sigmastate.eval.Extensions._
object OrderingOps {
def apply[T](implicit ord: Ordering[T]) = ord
@@ -47,8 +46,8 @@ object NumericOps {
def fromInt(x: Int): BigInt = x.toBigInt
def toInt(x: BigInt): Int = x.toInt
def toLong(x: BigInt): Long = x.toLong
- def toFloat(x: BigInt): Float = CostingSigmaDslBuilder.toBigInteger(x).floatValue()
- def toDouble(x: BigInt): Double = CostingSigmaDslBuilder.toBigInteger(x).doubleValue()
+ def toFloat(x: BigInt): Float = CSigmaDslBuilder.toBigInteger(x).floatValue()
+ def toDouble(x: BigInt): Double = CSigmaDslBuilder.toBigInteger(x).doubleValue()
}
/** The instance of Integral for BigInt.
diff --git a/data/shared/src/main/scala/sigma/data/CBox.scala b/data/shared/src/main/scala/sigma/data/CBox.scala
new file mode 100644
index 0000000000..9d350c5c6b
--- /dev/null
+++ b/data/shared/src/main/scala/sigma/data/CBox.scala
@@ -0,0 +1,95 @@
+package sigma.data
+
+import org.ergoplatform.ErgoBox
+import scorex.utils.Ints
+import sigma.Evaluation.stypeToRType
+import sigma.ast.SCollection.SByteArray
+import sigma.ast.syntax._
+import sigma.ast.{ConstantNode, EvaluatedValue, SInt, STuple, SType}
+import sigma.data.CBox.regs
+import sigma.eval.Extensions.toAnyValue
+import sigma.exceptions.InvalidType
+import sigma.{AnyValue, Box, Coll, Colls}
+
+import java.util.Arrays
+
+/** A default implementation of [[Box]] interface.
+ *
+ * @see [[Box]] for detailed descriptions
+ */
+case class CBox(ebox: ErgoBox) extends Box with WrapperOf[ErgoBox] {
+ val builder = CSigmaDslBuilder
+
+ val value = ebox.value
+ lazy val id : Coll[Byte] = Colls.fromArray(ebox.id)
+ lazy val bytes : Coll[Byte] = Colls.fromArray(ebox.bytes)
+ lazy val bytesWithoutRef : Coll[Byte] = Colls.fromArray(ebox.bytesWithNoRef)
+ lazy val propositionBytes: Coll[Byte] = Colls.fromArray(ebox.propositionBytes)
+ lazy val registers : Coll[AnyValue] = regs(ebox)
+
+ override def wrappedValue: ErgoBox = ebox
+
+ override def getReg[T](i: Int)(implicit tT: RType[T]): Option[T] = {
+ if (i < 0 || i >= registers.length) return None
+ val value = registers(i)
+ if (value != null) {
+ // once the value is not null it should be of the right type
+ value match {
+ case value: CAnyValue[_] if value.value != null && value.tA == tT =>
+ Some(value.value.asInstanceOf[T])
+ case _ =>
+ throw new InvalidType(s"Cannot getReg[${tT.name}]($i): invalid type of value $value at id=$i")
+ }
+ } else None
+ }
+
+ override def creationInfo: (Int, Coll[Byte]) = {
+ this.getReg[(Int, Coll[Byte])](3).get.asInstanceOf[Any] match {
+ case info: Tuple2[Int, Coll[Byte]]@unchecked => info
+ case ConstantNode(arr: Array[Any], STuple(IndexedSeq(SInt, SByteArray))) if arr.length == 2 =>
+ (arr(0).asInstanceOf[Int], builder.Colls.fromArray(arr(1).asInstanceOf[Array[Byte]]))
+ case v =>
+ sys.error(s"Invalid value $v of creationInfo register R3")
+ }
+ }
+
+ override def tokens: Coll[(Coll[Byte], Long)] = {
+ this.getReg[Coll[(Coll[Byte], Long)]](ErgoBox.R2.asIndex).get
+ }
+
+ override def executeFromRegister[T](regId: Byte)
+ (implicit cT: RType[T]): T = ??? // TODO implement
+
+ override def hashCode(): Int = Ints.fromByteArray(id.toArray)
+
+ override def equals(obj: Any): Boolean = (this eq obj.asInstanceOf[AnyRef]) || (obj != null && {
+ obj match {
+ case obj: Box => Arrays.equals(id.toArray, obj.id.toArray)
+ case _ =>
+ // this case was missing in v4.x, however has never been a problem
+ // Thus, v5.0 interpreter will not fail (while v4.x would fail here)
+ false
+ }
+ })
+}
+
+object CBox {
+ def regs(ebox: ErgoBox): Coll[AnyValue] = {
+ val res = new Array[AnyValue](ErgoBox.maxRegisters)
+
+ def checkNotYetDefined(id: Int, newValue: SValue) =
+ require(res(id) == null, s"register $id is defined more then once: previous value ${res(id)}, new value $newValue")
+
+ for ( (k, v: EvaluatedValue[t]) <- ebox.additionalRegisters ) {
+ checkNotYetDefined(k.number, v)
+ res(k.number) = toAnyValue(v.value)(stypeToRType(v.tpe))
+ }
+ for ( r <- ErgoBox.mandatoryRegisters ) {
+ val regId = r.number
+ val v = ebox.get(r).get.asInstanceOf[EvaluatedValue[SType]]
+ checkNotYetDefined(regId, v)
+ res(regId) = toAnyValue(v.value)(stypeToRType(v.tpe))
+ }
+ Colls.fromArray(res)
+ }
+}
\ No newline at end of file
diff --git a/data/shared/src/main/scala/sigma/data/CSigmaDslBuilder.scala b/data/shared/src/main/scala/sigma/data/CSigmaDslBuilder.scala
new file mode 100644
index 0000000000..3938feacd3
--- /dev/null
+++ b/data/shared/src/main/scala/sigma/data/CSigmaDslBuilder.scala
@@ -0,0 +1,206 @@
+package sigma.data
+
+import debox.cfor
+import org.ergoplatform.ErgoBox
+import org.ergoplatform.validation.ValidationRules
+import scorex.crypto.hash.{Blake2b256, Sha256}
+import scorex.utils.Longs
+import sigma.ast.{AtLeast, SubstConstants}
+import sigma.crypto.{CryptoConstants, EcPointType, Ecp}
+import sigma.eval.Extensions.EvalCollOps
+import sigma.serialization.{GroupElementSerializer, SigmaSerializer}
+import sigma.util.Extensions.BigIntegerOps
+import sigma.validation.SigmaValidationSettings
+import sigma.{AvlTree, BigInt, Box, Coll, CollBuilder, GroupElement, SigmaDslBuilder, SigmaProp, VersionContext}
+
+import java.math.BigInteger
+
+/** A default implementation of [[SigmaDslBuilder]] interface.
+ *
+ * @see [[SigmaDslBuilder]] for detailed descriptions
+ */
+class CSigmaDslBuilder extends SigmaDslBuilder { dsl =>
+ implicit val validationSettings: SigmaValidationSettings = ValidationRules.currentSettings
+
+ override val Colls: CollBuilder = sigma.Colls
+
+ override def BigInt(n: BigInteger): BigInt = CBigInt(n)
+
+ override def toBigInteger(n: BigInt): BigInteger = n.asInstanceOf[CBigInt].wrappedValue
+
+ /** Wraps the given elliptic curve point into GroupElement type. */
+ def GroupElement(p: Ecp): GroupElement = p match {
+ case ept: EcPointType => CGroupElement(ept)
+ case m => sys.error(s"Point of type ${m.getClass} is not supported")
+ }
+
+ /** Wraps the given sigma proposition into SigmaDsl value of type SigmaProp. */
+ def SigmaProp(sigmaTree: SigmaBoolean): SigmaProp = new CSigmaProp(sigmaTree)
+
+ /** Extract `sigma.data.SigmaBoolean` from DSL's `SigmaProp` type. */
+ @inline def toSigmaBoolean(p: SigmaProp): SigmaBoolean = p.asInstanceOf[CSigmaProp].sigmaTree
+
+ /** Extract `sigmastate.AvlTreeData` from DSL's `AvlTree` type. */
+ def toAvlTreeData(p: AvlTree): AvlTreeData = p.asInstanceOf[CAvlTree].treeData
+
+ /** Extract `sigmastate.crypto.Ecp` from DSL's `GroupElement` type. */
+ def toECPoint(ge: GroupElement): Ecp = ge.asInstanceOf[CGroupElement].wrappedValue
+
+ /** Creates a new AvlTree instance with the given parameters.
+ *
+ * @see AvlTreeData for details
+ */
+ override def avlTree(
+ operationFlags: Byte,
+ digest: Coll[Byte],
+ keyLength: Int,
+ valueLengthOpt: Option[Int]): CAvlTree = {
+ val treeData = AvlTreeData(digest, AvlTreeFlags(operationFlags), keyLength, valueLengthOpt)
+ CAvlTree(treeData)
+ }
+
+ /** Wraps the given tree data into SigmaDsl value of type [[AvlTree]]. */
+ def avlTree(treeData: AvlTreeData): AvlTree = {
+ CAvlTree(treeData)
+ }
+
+ /** Wraps the given [[ErgoBox]] into SigmaDsl value of type [[Box]].
+ *
+ * @param ebox the value to be wrapped
+ * @see [[sigmastate.SBox]], [[sigma.Box]]
+ */
+ def Box(ebox: ErgoBox): Box = CBox(ebox)
+
+ /** Extracts [[ErgoBox]] from the given [[Box]] instance. This is inverse to the Box method. */
+ def toErgoBox(b: Box): ErgoBox = b.asInstanceOf[CBox].ebox
+
+ /** HOTSPOT: don't beautify this code */
+ private def toSigmaTrees(props: Array[SigmaProp]): Array[SigmaBoolean] = {
+ val len = props.length
+ val res = new Array[SigmaBoolean](len)
+ cfor(0)(_ < len, _ + 1) { i =>
+ res(i) = toSigmaBoolean(props(i))
+ }
+ res
+ }
+
+ @inline private def toEcPointType(ge: GroupElement): EcPointType =
+ toECPoint(ge).asInstanceOf[EcPointType]
+
+ override def atLeast(bound: Int, props: Coll[SigmaProp]): SigmaProp = {
+ if (props.length > AtLeast.MaxChildrenCount)
+ throw new IllegalArgumentException(s"Expected input elements count should not exceed ${AtLeast.MaxChildrenCount}, actual: ${props.length}")
+ val sigmaTrees = toSigmaTrees(props.toArray)
+ val tree = AtLeast.reduce(bound, sigmaTrees)
+ CSigmaProp(tree)
+ }
+
+ override def allOf(conditions: Coll[Boolean]): Boolean =
+ conditions.forall(c => c)
+
+ override def anyOf(conditions: Coll[Boolean]): Boolean =
+ conditions.exists(c => c)
+
+ override def xorOf(conditions: Coll[Boolean]): Boolean = {
+ if (VersionContext.current.isJitActivated) {
+ val len = conditions.length
+ if (len == 0) false
+ else if (len == 1) conditions(0)
+ else {
+ var res = conditions(0)
+ cfor(1)(_ < len, _ + 1) { i =>
+ res ^= conditions(i)
+ }
+ res
+ }
+ } else {
+ // This is buggy version used in v4.x interpreter (for ErgoTrees v0, v1)
+ conditions.toArray.distinct.length == 2
+ }
+ }
+
+ override def allZK(props: Coll[SigmaProp]): SigmaProp = {
+ val sigmaTrees = toSigmaTrees(props.toArray)
+ val tree = CAND.normalized(sigmaTrees)
+ CSigmaProp(tree)
+ }
+
+ override def anyZK(props: Coll[SigmaProp]): SigmaProp = {
+ val sigmaTrees = toSigmaTrees(props.toArray)
+ val tree = COR.normalized(sigmaTrees)
+ CSigmaProp(tree)
+ }
+
+ override def xor(l: Coll[Byte], r: Coll[Byte]): Coll[Byte] =
+ Colls.xor(l, r)
+
+ override def sigmaProp(b: Boolean): SigmaProp = {
+ CSigmaProp(TrivialProp(b))
+ }
+
+ override def blake2b256(bytes: Coll[Byte]): Coll[Byte] = {
+ val h = Blake2b256.hash(bytes.toArray)
+ Colls.fromArray(h)
+ }
+
+ override def sha256(bytes: Coll[Byte]): Coll[Byte] = {
+ val h = Sha256.hash(bytes.toArray)
+ Colls.fromArray(h)
+ }
+
+ override def byteArrayToBigInt(bytes: Coll[Byte]): BigInt = {
+ val bi = new BigInteger(bytes.toArray).to256BitValueExact
+ this.BigInt(bi)
+ }
+
+ override def longToByteArray(l: Long): Coll[Byte] =
+ Colls.fromArray(Longs.toByteArray(l))
+
+ override def byteArrayToLong(bytes: Coll[Byte]): Long =
+ Longs.fromByteArray(bytes.toArray)
+
+ override def proveDlog(ge: GroupElement): SigmaProp =
+ CSigmaProp(ProveDlog(toECPoint(ge).asInstanceOf[EcPointType]))
+
+ override def proveDHTuple(
+ g: GroupElement,
+ h: GroupElement,
+ u: GroupElement,
+ v: GroupElement): SigmaProp = {
+ val dht = ProveDHTuple(toEcPointType(g), toEcPointType(h), toEcPointType(u), toEcPointType(v))
+ CSigmaProp(dht)
+ }
+
+ private lazy val _generatorElement = this.GroupElement(CryptoConstants.dlogGroup.generator)
+
+ override def groupGenerator: GroupElement = _generatorElement
+
+ /**
+ * @return the identity of the Dlog group used in ErgoTree
+ */
+ def groupIdentity: GroupElement = {
+ this.GroupElement(CryptoConstants.dlogGroup.identity)
+ }
+
+ override def substConstants[T](
+ scriptBytes: Coll[Byte],
+ positions: Coll[Int],
+ newValues: Coll[T]): Coll[Byte] = {
+ val constants = try newValues.toArrayOfConstants
+ catch {
+ case e: Throwable =>
+ throw new RuntimeException(s"Cannot evaluate substConstants($scriptBytes, $positions, $newValues)", e)
+ }
+ val (res, _) = SubstConstants.eval(scriptBytes.toArray, positions.toArray, constants)(validationSettings)
+ Colls.fromArray(res)
+ }
+
+ override def decodePoint(encoded: Coll[Byte]): GroupElement = {
+ val r = SigmaSerializer.startReader(encoded.toArray)
+ val p = GroupElementSerializer.parse(r)
+ this.GroupElement(p)
+ }
+}
+
+/** Default singleton instance of Global object, which implements global ErgoTree functions. */
+object CSigmaDslBuilder extends CSigmaDslBuilder
\ No newline at end of file
diff --git a/interpreter/shared/src/main/scala/sigmastate/DataValueComparer.scala b/data/shared/src/main/scala/sigma/data/DataValueComparer.scala
similarity index 97%
rename from interpreter/shared/src/main/scala/sigmastate/DataValueComparer.scala
rename to data/shared/src/main/scala/sigma/data/DataValueComparer.scala
index 0bba6c0dc4..21ca85012f 100644
--- a/interpreter/shared/src/main/scala/sigmastate/DataValueComparer.scala
+++ b/data/shared/src/main/scala/sigma/data/DataValueComparer.scala
@@ -1,14 +1,10 @@
-package sigmastate
+package sigma.data
-import sigma.data.{AVHashMap, CollOverArray, Nullable, PairOfCols, RType}
import debox.{cfor, sp}
-import sigmastate.Values.SigmaBoolean
-import sigmastate.crypto.DLogProtocol.ProveDlog
-import sigmastate.crypto.ProveDHTuple
-import sigmastate.eval.SigmaDsl
-import sigmastate.crypto.CryptoConstants.EcPointType
-import sigmastate.interpreter.{ErgoTreeEvaluator, NamedDesc, OperationCostInfo}
import sigma._
+import sigma.ast.{FixedCost, JitCost, NamedDesc, OperationCostInfo, PerItemCost}
+import sigma.crypto.EcPointType
+import sigma.eval.{ErgoTreeEvaluator, SigmaDsl}
/** Implementation of data equality for two arbitrary ErgoTree data types.
* @see [[DataValueComparer.equalDataValues]]
@@ -279,7 +275,7 @@ object DataValueComparer {
val sb2 = r.asInstanceOf[CTHRESHOLD]
k == sb2.k && equalSigmaBooleans(children, sb2.children)
case _ =>
- ErgoTreeEvaluator.error(
+ sys.error(
s"Cannot compare SigmaBoolean values $l and $r: unknown type")
}
}
@@ -408,7 +404,7 @@ object DataValueComparer {
okEqual = r.isInstanceOf[Unit]
case _ =>
- ErgoTreeEvaluator.error(s"Cannot compare $l and $r: unknown type")
+ sys.error(s"Cannot compare $l and $r: unknown type")
}
okEqual
}
diff --git a/interpreter/shared/src/main/scala/sigmastate/eval/ExactIntegral.scala b/data/shared/src/main/scala/sigma/data/ExactIntegral.scala
similarity index 100%
rename from interpreter/shared/src/main/scala/sigmastate/eval/ExactIntegral.scala
rename to data/shared/src/main/scala/sigma/data/ExactIntegral.scala
diff --git a/interpreter/shared/src/main/scala/sigmastate/eval/ExactNumeric.scala b/data/shared/src/main/scala/sigma/data/ExactNumeric.scala
similarity index 100%
rename from interpreter/shared/src/main/scala/sigmastate/eval/ExactNumeric.scala
rename to data/shared/src/main/scala/sigma/data/ExactNumeric.scala
diff --git a/interpreter/shared/src/main/scala/sigmastate/eval/ExactOrdering.scala b/data/shared/src/main/scala/sigma/data/ExactOrdering.scala
similarity index 90%
rename from interpreter/shared/src/main/scala/sigmastate/eval/ExactOrdering.scala
rename to data/shared/src/main/scala/sigma/data/ExactOrdering.scala
index 7c65b53075..a7b002cb80 100644
--- a/interpreter/shared/src/main/scala/sigmastate/eval/ExactOrdering.scala
+++ b/data/shared/src/main/scala/sigma/data/ExactOrdering.scala
@@ -1,6 +1,6 @@
package sigma.data
-import scala.math.Numeric.{ByteIsIntegral, LongIsIntegral, ShortIsIntegral, IntIsIntegral}
+import scala.math.Numeric.{ByteIsIntegral, IntIsIntegral, LongIsIntegral, ShortIsIntegral}
/** Ordering operations to be used with other Exact traits.
* All methods are implemented by delegating to the corresponding Ordering instance from
diff --git a/data/shared/src/main/scala/sigma/eval/AvlTreeVerifier.scala b/data/shared/src/main/scala/sigma/eval/AvlTreeVerifier.scala
new file mode 100644
index 0000000000..bc4a625458
--- /dev/null
+++ b/data/shared/src/main/scala/sigma/eval/AvlTreeVerifier.scala
@@ -0,0 +1,76 @@
+package sigma.eval
+
+import scala.util.Try
+
+/** Represents a verifier of authenticated AVL+ tree created from a proof.
+ * The verifier holds the tree data parsed from the proof.
+ */
+trait AvlTreeVerifier {
+ /** Height of the tree. */
+ def treeHeight: Int
+
+ /** Looks up a key in the tree.
+ * If `key` exists in the tree and the operation succeeds,
+ * returns `Success(Some(v))`, where v is the value associated with `key`.
+ * If `key` does not exists in the tree and the operation succeeds, returns Success(None).
+ * Returns Failure if the operation fails or the proof does not verify.
+ * After one failure, all subsequent operations with this verifier will fail and digest
+ * is None.
+ *
+ * @param key key to look up
+ * @return Success(Some(value)), Success(None), or Failure
+ */
+ def performLookup(key: Array[Byte]): Try[Option[Array[Byte]]]
+
+ /** Check the key-value pair has been inserted in the tree.
+ * If `key` exists in the tree and the operation succeeds,
+ * returns `Success(Some(value))`, where value is associated with `key`.
+ * If `key` does not exists in the tree and the operation succeeds, returns Success(None).
+ * Returns Failure if the operation fails or the proof does not verify.
+ * After one failure, all subsequent operations with this verifier will fail and digest
+ * is None.
+ *
+ * @param key key to look up
+ * @param value value to check it was inserted
+ * @return Success(Some(inserted value)), Success(None), or Failure
+ */
+ def performInsert(key: Array[Byte], value: Array[Byte]): Try[Option[Array[Byte]]]
+
+ /** Check the key-value pair has been updated in the tree.
+ * If `key` exists in the tree and the operation succeeds,
+ * returns `Success(Some(value))`, where value is associated with `key`.
+ * If `key` does not exists in the tree and the operation succeeds, returns Success(None).
+ * Returns Failure if the operation fails or the proof does not verify.
+ * After one failure, all subsequent operations with this verifier will fail and digest
+ * is None.
+ *
+ * @param key key to look up
+ * @param value value to check it was updated
+ * @return Success(Some(value)), Success(None), or Failure
+ */
+ def performUpdate(key: Array[Byte], value: Array[Byte]): Try[Option[Array[Byte]]]
+
+ /** Check the key has been removed in the tree.
+ * If `key` exists in the tree and the operation succeeds,
+ * returns `Success(Some(v))`, where v is old value associated with `key`.
+ * If `key` does not exists in the tree and the operation succeeds, returns Success(None).
+ * Returns Failure if the operation fails or the proof does not verify.
+ * After one failure, all subsequent operations with this verifier will fail and digest
+ * is None.
+ *
+ * @param key key to look up
+ * @return Success(Some(old value)), Success(None), or Failure
+ */
+ def performRemove(key: Array[Byte]): Try[Option[Array[Byte]]]
+
+ /**
+ * Returns Some(d), where d - the current digest of the authenticated data structure.
+ * The digest contains the root hash and the root height.
+ *
+ * Returns None if the proof verification failed at construction
+ * or during any of the operations with this verifier.
+ *
+ * @return - Some[digest] or None
+ */
+ def digest: Option[Array[Byte]]
+}
diff --git a/interpreter/shared/src/main/scala/sigmastate/interpreter/CostDetails.scala b/data/shared/src/main/scala/sigma/eval/CostDetails.scala
similarity index 97%
rename from interpreter/shared/src/main/scala/sigmastate/interpreter/CostDetails.scala
rename to data/shared/src/main/scala/sigma/eval/CostDetails.scala
index 6bffb8ff8e..89d522833b 100644
--- a/interpreter/shared/src/main/scala/sigmastate/interpreter/CostDetails.scala
+++ b/data/shared/src/main/scala/sigma/eval/CostDetails.scala
@@ -1,8 +1,7 @@
-package sigmastate.interpreter
+package sigma.eval
-import sigmastate.JitCost
import debox.cfor
-
+import sigma.ast.{CostItem, JitCost}
import scala.collection.compat.immutable.ArraySeq
/** Abstract representation of cost results obtained during evaluation. */
diff --git a/data/shared/src/main/scala/sigma/eval/ErgoTreeEvaluator.scala b/data/shared/src/main/scala/sigma/eval/ErgoTreeEvaluator.scala
new file mode 100644
index 0000000000..52f839354c
--- /dev/null
+++ b/data/shared/src/main/scala/sigma/eval/ErgoTreeEvaluator.scala
@@ -0,0 +1,146 @@
+package sigma.eval
+
+import sigma.{AvlTree, Coll, Context}
+import sigma.ast.{Constant, FixedCost, MethodCall, OperationCostInfo, OperationDesc, PerItemCost, SType, TypeBasedCost}
+import sigma.data.KeyValueColl
+
+abstract class ErgoTreeEvaluator {
+ /** Adds the given cost to the `coster`. If tracing is enabled, creates a new cost item
+ * with the given operation.
+ *
+ * @param costKind the cost to be added to `coster` for each item
+ * @param nItems the number of items
+ * @param opDesc the operation to associate the cost with (when costTracingEnabled)
+ * @param block operation executed under the given cost
+ * @tparam R result type of the operation
+ * @hotspot don't beautify the code
+ */
+ def addSeqCost[R](costKind: PerItemCost, nItems: Int, opDesc: OperationDesc)
+ (block: () => R): R
+
+ /** Adds the cost to the `coster`. See the other overload for details. */
+ def addSeqCost[R](costInfo: OperationCostInfo[PerItemCost], nItems: Int)
+ (block: () => R): R
+
+ /** Adds the cost to the `coster`. If tracing is enabled, creates a new cost item with
+ * the given operation descriptor and cost kind. If time measuring is enabled also
+ * performs profiling.
+ *
+ * WARNING: The cost is accumulated AFTER the block is executed.
+ * Each usage of this method should be accompanied with a proof of why this cannot lead
+ * to unbounded execution (see all usages).
+ *
+ * @param costKind the cost descriptor to be used to compute the cost based on the
+ * actual number of items returned by the `block`
+ * @param opDesc the operation to associate the cost with (when costTracingEnabled)
+ * @param block operation executed under the given cost descriptors, returns the
+ * actual number of items processed
+ * @hotspot don't beautify the code
+ */
+ def addSeqCost(costKind: PerItemCost, opDesc: OperationDesc)(block: () => Int): Unit
+
+ /** Adds the cost to the `coster`. See the other overload for details. */
+ def addSeqCost(costInfo: OperationCostInfo[PerItemCost])(block: () => Int): Unit
+
+ /** Adds the given cost to the `coster`. If tracing is enabled, associates the cost with
+ * the given operation.
+ *
+ * @param costKind kind of the cost to be added to `coster`
+ * @param opDesc operation descriptor to associate the cost with (when costTracingEnabled)
+ */
+ def addCost(costKind: FixedCost, opDesc: OperationDesc): Unit
+
+ def addCost(costInfo: OperationCostInfo[FixedCost]): Unit
+
+ /** Adds the given cost to the `coster`. If tracing is enabled, associates the cost with
+ * the given operation.
+ *
+ * @param costKind kind of the cost to be added to `coster`
+ * @param opDesc the operation descriptor to associate the cost with (when costTracingEnabled)
+ * @param block operation executed under the given cost
+ */
+ def addFixedCost(costKind: FixedCost, opDesc: OperationDesc)(block: => Unit): Unit
+
+ def addFixedCost(costInfo: OperationCostInfo[FixedCost])(block: => Unit): Unit
+
+ /** Adds the given cost to the `coster`. If tracing is enabled, creates a new cost item
+ * with the given operation.
+ *
+ * @param costKind the cost to be added to `coster` for each item
+ * @param nItems the number of items
+ * @param opDesc the operation to associate the cost with (when costTracingEnabled)
+ */
+ def addSeqCostNoOp(costKind: PerItemCost, nItems: Int, opDesc: OperationDesc): Unit
+
+ /** Add the cost given by the cost descriptor and the type to the accumulator and
+ * associate it with this operation descriptor.
+ *
+ * @param costKind descriptor of the cost
+ * @param tpe specific type for which the cost should be computed by this descriptor
+ * (see costFunc method)
+ * @param opDesc operation which is associated with this cost
+ */
+ def addTypeBasedCost[R](
+ costKind: TypeBasedCost,
+ tpe: SType, opDesc: OperationDesc)(block: () => R): R
+
+ /** Settings to be used during evaluation. */
+ def settings: EvalSettings
+
+ /** Performs operations profiling and time measurements (if enabled in settings). */
+ def profiler: Profiler
+
+ /** Segregated constants from ErgoTree, to lookup them from
+ * [[ConstantPlaceholder]] evaluation.
+ */
+ def constants: Seq[Constant[SType]]
+
+ /** Represents blockchain data context for ErgoTree evaluation. */
+ def context: Context
+
+ /** Create an instance of [[AvlTreeVerifier]] for the given tree and proof. */
+ def createTreeVerifier(tree: AvlTree, proof: Coll[Byte]): AvlTreeVerifier
+
+ /** Implements evaluation of AvlTree.contains method call ErgoTree node. */
+ def contains_eval(
+ mc: MethodCall,
+ tree: AvlTree,
+ key: Coll[Byte],
+ proof: Coll[Byte]): Boolean
+
+ /** Implements evaluation of AvlTree.get method call ErgoTree node. */
+ def get_eval(
+ mc: MethodCall,
+ tree: AvlTree,
+ key: Coll[Byte],
+ proof: Coll[Byte]): Option[Coll[Byte]]
+
+ /** Implements evaluation of AvlTree.getMany method call ErgoTree node. */
+ def getMany_eval(
+ mc: MethodCall,
+ tree: AvlTree,
+ keys: Coll[Coll[Byte]],
+ proof: Coll[Byte]): Coll[Option[Coll[Byte]]]
+
+ /** Implements evaluation of AvlTree.insert method call ErgoTree node. */
+ def insert_eval(
+ mc: MethodCall,
+ tree: AvlTree,
+ entries: KeyValueColl,
+ proof: Coll[Byte]): Option[AvlTree]
+
+ /** Implements evaluation of AvlTree.update method call ErgoTree node. */
+ def update_eval(
+ mc: MethodCall, tree: AvlTree,
+ operations: KeyValueColl, proof: Coll[Byte]): Option[AvlTree]
+
+ /** Implements evaluation of AvlTree.remove method call ErgoTree node. */
+ def remove_eval(
+ mc: MethodCall, tree: AvlTree,
+ operations: Coll[Coll[Byte]], proof: Coll[Byte]): Option[AvlTree]
+}
+
+object ErgoTreeEvaluator {
+ /** Immutable data environment used to assign data values to graph nodes. */
+ type DataEnv = Map[Int, Any]
+}
\ No newline at end of file
diff --git a/data/shared/src/main/scala/sigma/eval/EvalSettings.scala b/data/shared/src/main/scala/sigma/eval/EvalSettings.scala
new file mode 100644
index 0000000000..6567d0cdec
--- /dev/null
+++ b/data/shared/src/main/scala/sigma/eval/EvalSettings.scala
@@ -0,0 +1,83 @@
+package sigma.eval
+
+import sigma.eval.EvalSettings.EvaluationMode
+import supertagged.TaggedType
+
+/** Configuration parameters of the evaluation run. */
+case class EvalSettings(
+ /** Used together with [[ErgoTreeEvaluator.profiler]] to measure individual operations timings. */
+ isMeasureOperationTime: Boolean,
+
+ /** Used together with [[ErgoTreeEvaluator.profiler]] to measure script timings. */
+ isMeasureScriptTime: Boolean,
+
+ /** Used by [[ErgoTreeEvaluator]] to conditionally perform debug mode operations. */
+ isDebug: Boolean = false,
+
+ /** Used by [[ErgoTreeEvaluator]] to conditionally emit log messages. */
+ isLogEnabled: Boolean = false,
+
+ /** Used by [[ErgoTreeEvaluator]] to conditionally build a trace of added costs.
+ *
+ * @see Value.addCost
+ */
+ costTracingEnabled: Boolean = false,
+
+ /** Profiler which, when defined, should be used in [[ErgoTreeEvaluator]] constructor. */
+ profilerOpt: Option[Profiler] = None,
+
+ /** Should be set to true, if evaluation is performed as part of test suite.
+ * In such a case, additional operations may be performed (such as sanity checks). */
+ isTestRun: Boolean = false,
+
+ /** If true, then expected test vectors are pretty-printed. */
+ printTestVectors: Boolean = false,
+
+ /** When Some(mode) is specified then it defines which version of the Interpreter.verify
+ * and Interpreter.prove methods should use.
+ * The default value is None, which means the version is defined by ErgoTree.version
+ * and Context.activatedScriptVersion.
+ */
+ evaluationMode: Option[EvaluationMode] = None,
+
+ /** Maximum execution cost of a script used by profiler.
+ *
+ * @see ErgoTreeEvaluator
+ */
+ scriptCostLimitInEvaluator: Int = 1000000
+)
+
+object EvalSettings {
+ /** Enumeration type of evaluation modes of [[Interpreter]].
+ * This type can be removed in v5.x releases together with AOT implementation once v5.0
+ * protocol is activated.
+ */
+ object EvaluationMode extends TaggedType[Int] {
+ implicit class EvaluationModeOps(val x: EvaluationMode) extends AnyVal {
+ def name: String = x match {
+ case AotEvaluationMode => "AotEvaluationMode"
+ case JitEvaluationMode => "JitEvaluationMode"
+ }
+
+ /** Returns true if AOT interpreter should be evaluated. */
+ def okEvaluateAot: Boolean = {
+ x == AotEvaluationMode
+ }
+
+ /** Returns true if JIT interpreter should be evaluated. */
+ def okEvaluateJit: Boolean = {
+ x == JitEvaluationMode
+ }
+ }
+ }
+
+ type EvaluationMode = EvaluationMode.Type
+
+ /** Evaluation mode when the interpreter is executing using AOT costing implementation
+ * of v4.x protocol. */
+ val AotEvaluationMode: EvaluationMode = EvaluationMode @@ 1 // first bit
+
+ /** Evaluation mode when the interpreter is executing using JIT costing implementation
+ * of v5.x protocol. */
+ val JitEvaluationMode: EvaluationMode = EvaluationMode @@ 2 // second bit
+}
\ No newline at end of file
diff --git a/data/shared/src/main/scala/sigma/eval/Extensions.scala b/data/shared/src/main/scala/sigma/eval/Extensions.scala
new file mode 100644
index 0000000000..def9086e02
--- /dev/null
+++ b/data/shared/src/main/scala/sigma/eval/Extensions.scala
@@ -0,0 +1,75 @@
+package sigma.eval
+
+import sigma.ast.syntax.SigmaPropValue
+import sigma.data.{CAnyValue, CSigmaDslBuilder, Nullable, RType, SigmaBoolean}
+import sigma.{BigInt, Coll, Colls, Evaluation, Platform}
+import sigma.ast.{Constant, ConstantNode, SBoolean, SCollection, SCollectionType, SType, SigmaPropConstant, SigmaPropIsProven, TransformingSigmaBuilder, Value}
+
+import java.math.BigInteger
+
+object Extensions {
+ implicit class ByteExt(val b: Byte) extends AnyVal {
+ @inline def toBigInt: BigInt = CSigmaDslBuilder.BigInt(BigInteger.valueOf(b.toLong))
+ }
+
+ implicit class ShortExt(val b: Short) extends AnyVal {
+ @inline def toBigInt: BigInt = CSigmaDslBuilder.BigInt(BigInteger.valueOf(b.toLong))
+ }
+
+ implicit class IntExt(val x: Int) extends AnyVal {
+ /** Convert this value to BigInt. */
+ @inline def toBigInt: BigInt = CSigmaDslBuilder.BigInt(BigInteger.valueOf(x.toLong))
+ }
+
+ implicit class LongExt(val x: Long) extends AnyVal {
+ /** Convert this value to BigInt. */
+ @inline def toBigInt: BigInt = CSigmaDslBuilder.BigInt(BigInteger.valueOf(x))
+ }
+
+ def toAnyValue[A: RType](x: A) = new CAnyValue(x, RType[A].asInstanceOf[RType[Any]])
+
+ implicit class EvalCollOps[T](val coll: Coll[T]) extends AnyVal {
+ /** Helper type synonym. */
+ type ElemTpe = SType {type WrappedType = T}
+
+ /** Wraps the collection into ConstantNode using collection's element type. */
+ def toConstant: Constant[SCollection[ElemTpe]] = {
+ val elemTpe = Evaluation.rtypeToSType(coll.tItem).asInstanceOf[ElemTpe]
+ ConstantNode[SCollection[ElemTpe]](coll, SCollectionType(elemTpe))
+ }
+
+ /** Transforms this collection into array of constants.
+ *
+ * This method have exactly the same semantics on JS and JVM IF `coll.tItem`
+ * precisely describes the type of elements in `call`. (Which is the case for all
+ * collections created by ErgoTree interpreter).
+ *
+ * However, if it is not the case, then JVM and JS will have different semantics for Byte and Short.
+ *
+ * The JVM version preserves v5.0 consensus protocol semantics.
+ * The JS version is a reasonable approximation of the JVM version.
+ */
+ def toArrayOfConstants: Array[Constant[SType]] = {
+ val constants = coll.toArray.map { v =>
+ // see ScalaDoc for ensureTypeCarringValue
+ val valToLift = ensureTypeCarringValue(v, coll.tItem.asInstanceOf[RType[Any]])
+ // call platform-specific method to transform the value to a Constant
+ Platform.liftToConstant(valToLift, TransformingSigmaBuilder) match {
+ case Nullable(c) => c
+ case _ => sys.error(s"Cannot liftToConstant($valToLift)")
+ }
+ }
+ constants
+ }
+ }
+
+ implicit class SigmaBooleanOps(val sb: SigmaBoolean) extends AnyVal {
+ def toSigmaPropValue: SigmaPropValue = SigmaPropConstant(sb)
+
+ def isProven: Value[SBoolean.type] = SigmaPropIsProven(SigmaPropConstant(sb))
+ }
+
+ implicit class EvalIterableOps[T: RType](seq: Iterable[T]) {
+ @inline def toColl: Coll[T] = Colls.fromArray[T](seq.toArray(RType[T].classTag))
+ }
+}
diff --git a/data/shared/src/main/scala/sigma/eval/Profiler.scala b/data/shared/src/main/scala/sigma/eval/Profiler.scala
new file mode 100644
index 0000000000..ac4c7a299d
--- /dev/null
+++ b/data/shared/src/main/scala/sigma/eval/Profiler.scala
@@ -0,0 +1,28 @@
+package sigma.eval
+
+import sigma.ast.{CostItem, JitCost}
+import sigma.ast.syntax.SValue
+
+abstract class Profiler {
+ /** Called from evaluator immediately before the evaluator start recursive evaluation of
+ * the given node.
+ */
+ def onBeforeNode(node: SValue): Unit
+
+ /** Called from evaluator immediately after the evaluator finishes recursive evaluation
+ * of the given node.
+ */
+ def onAfterNode(node: SValue): Unit
+
+ /** Add new measurement point to the stats of this profiler.
+ *
+ * @param costItem executed cost item
+ * @param time time spent to execute this cost item
+ */
+ def addCostItem(costItem: CostItem, time: Long): Unit
+
+ /** Adds estimated cost and actual measured time data point to the StatCollection for
+ * the given script.
+ */
+ def addJitEstimation(script: String, cost: JitCost, actualTimeNano: Long): Unit
+}
diff --git a/data/shared/src/main/scala/sigma/eval/package.scala b/data/shared/src/main/scala/sigma/eval/package.scala
new file mode 100644
index 0000000000..d2c6415fde
--- /dev/null
+++ b/data/shared/src/main/scala/sigma/eval/package.scala
@@ -0,0 +1,30 @@
+package sigma
+
+import sigma.data.{CAnyValue, CSigmaDslBuilder, OverloadHack, RType}
+
+package object eval {
+ /** The primary reference to Global instance of SigmaDsl.
+ * Besides operations of SigmaDslBuilder class, this instance also contains methods,
+ * which are not available in Dsl code, and which are not in SigmaDslBuilder interface.
+ * For example methods like `Box`, `toErgoBox` are available here, but not available in Dsl.
+ *
+ * @see SigmaDslBuilder
+ */
+ val SigmaDsl = CSigmaDslBuilder
+
+ /** Encapsulate platform-specific logic of ensuring the value carries its precise type.
+ * For JVM this is identity function.
+ * For JS it can transform to AnyValue, if the type is numeric
+ */
+ def ensureTypeCarringValue(v: Any, tT: RType[Any]): Any =
+ if (Environment.current.isJVM) v
+ else { // JS
+ v match {
+ case _: Byte | _: Short | _: Int =>
+ // this is necessary for JS where Byte, Short, Int have the same runtime class
+ // and hence we need to pass the type information explicitly
+ CAnyValue(v)(tT, OverloadHack.overloaded1)
+ case _ => v
+ }
+ }
+}
diff --git a/interpreter/shared/src/main/scala/sigmastate/exceptions/CompilerExceptions.scala b/data/shared/src/main/scala/sigma/exceptions/CompilerExceptions.scala
similarity index 95%
rename from interpreter/shared/src/main/scala/sigmastate/exceptions/CompilerExceptions.scala
rename to data/shared/src/main/scala/sigma/exceptions/CompilerExceptions.scala
index 8c331766af..8b650256a9 100644
--- a/interpreter/shared/src/main/scala/sigmastate/exceptions/CompilerExceptions.scala
+++ b/data/shared/src/main/scala/sigma/exceptions/CompilerExceptions.scala
@@ -1,6 +1,7 @@
-package sigmastate.exceptions
+package sigma.exceptions
-import sigmastate.lang.SourceContext
+import sigma.SigmaException
+import sigma.ast.SourceContext
/** Base class for exceptions thrown by the compiler.
*
diff --git a/interpreter/shared/src/main/scala/sigmastate/exceptions/ConstraintFailed.scala b/data/shared/src/main/scala/sigma/exceptions/ConstraintFailed.scala
similarity index 66%
rename from interpreter/shared/src/main/scala/sigmastate/exceptions/ConstraintFailed.scala
rename to data/shared/src/main/scala/sigma/exceptions/ConstraintFailed.scala
index bddd2a6951..eb77f8c31b 100644
--- a/interpreter/shared/src/main/scala/sigmastate/exceptions/ConstraintFailed.scala
+++ b/data/shared/src/main/scala/sigma/exceptions/ConstraintFailed.scala
@@ -1,6 +1,6 @@
-package sigmastate.exceptions
+package sigma.exceptions
-import sigmastate.lang.SourceContext
+import sigma.ast.SourceContext
final class ConstraintFailed(message: String, source: Option[SourceContext] = None)
extends BuilderException(message, source)
diff --git a/interpreter/shared/src/main/scala/sigmastate/eval/Exceptions.scala b/data/shared/src/main/scala/sigma/exceptions/Exceptions.scala
similarity index 73%
rename from interpreter/shared/src/main/scala/sigmastate/eval/Exceptions.scala
rename to data/shared/src/main/scala/sigma/exceptions/Exceptions.scala
index 2949fb6815..a1584d8d71 100644
--- a/interpreter/shared/src/main/scala/sigmastate/eval/Exceptions.scala
+++ b/data/shared/src/main/scala/sigma/exceptions/Exceptions.scala
@@ -1,4 +1,4 @@
-package sigmastate.eval
+package sigma.exceptions
final class InvalidType(message: String) extends Exception(message)
diff --git a/interpreter/shared/src/main/scala/sigmastate/exceptions/InvalidArguments.scala b/data/shared/src/main/scala/sigma/exceptions/InvalidArguments.scala
similarity index 65%
rename from interpreter/shared/src/main/scala/sigmastate/exceptions/InvalidArguments.scala
rename to data/shared/src/main/scala/sigma/exceptions/InvalidArguments.scala
index b154fdb6d4..38db5ceeec 100644
--- a/interpreter/shared/src/main/scala/sigmastate/exceptions/InvalidArguments.scala
+++ b/data/shared/src/main/scala/sigma/exceptions/InvalidArguments.scala
@@ -1,6 +1,6 @@
-package sigmastate.exceptions
+package sigma.exceptions
-import sigmastate.lang.SourceContext
+import sigma.ast.SourceContext
final class InvalidArguments(message: String, source: Option[SourceContext] = None)
extends BinderException(message, source)
diff --git a/interpreter/shared/src/main/scala/sigmastate/exceptions/SigmaExceptions.scala b/data/shared/src/main/scala/sigma/exceptions/SigmaExceptions.scala
similarity index 61%
rename from interpreter/shared/src/main/scala/sigmastate/exceptions/SigmaExceptions.scala
rename to data/shared/src/main/scala/sigma/exceptions/SigmaExceptions.scala
index 8014fccda9..befb497dde 100644
--- a/interpreter/shared/src/main/scala/sigmastate/exceptions/SigmaExceptions.scala
+++ b/data/shared/src/main/scala/sigma/exceptions/SigmaExceptions.scala
@@ -1,24 +1,7 @@
-package sigmastate.exceptions
+package sigma.exceptions
-import sigmastate.JitCost
-
-/** Base class for Sigma-related exceptions.
- *
- * @param message the error message
- * @param cause an optional cause for the exception
- */
-class SigmaException(val message: String, val cause: Option[Throwable] = None)
- extends Exception(message, cause.orNull)
-
-/** Exception thrown during serialization.
- *
- * @param message the error message
- * @param cause an optional cause for the exception
- */
-case class SerializerException(
- override val message: String,
- override val cause: Option[Throwable] = None)
- extends SigmaException(message, cause)
+import sigma.SigmaException
+import sigma.ast.JitCost
/** Exception thrown by [[sigmastate.interpreter.Interpreter]].
*
diff --git a/data/shared/src/main/scala/sigma/interpreter/ContextExtension.scala b/data/shared/src/main/scala/sigma/interpreter/ContextExtension.scala
new file mode 100644
index 0000000000..e8cdb7d709
--- /dev/null
+++ b/data/shared/src/main/scala/sigma/interpreter/ContextExtension.scala
@@ -0,0 +1,49 @@
+package sigma.interpreter
+
+import sigma.ast.{EvaluatedValue, SType}
+import sigma.interpreter.ContextExtension.VarBinding
+import sigma.serialization.{SigmaByteReader, SigmaByteWriter, SigmaSerializer}
+
+/**
+ * User-defined variables to be put into context.
+ * Each variable is identified by `id: Byte` and can be accessed from a script
+ * using `getVar[T](id)` operation.
+ * The value of the variable is represented by [[sigma.ast.Constant]] instance,
+ * which contains both data value and [[SType]] descriptor. The descriptor is checked
+ * against the type `T` expected in the script operation. If the types don't match,
+ * exception is thrown and the box spending (protected by the script) fails.
+ *
+ * @param values internal container of the key-value pairs
+ */
+case class ContextExtension(values: scala.collection.Map[Byte, EvaluatedValue[_ <: SType]]) {
+ def add(bindings: VarBinding*): ContextExtension =
+ ContextExtension(values ++ bindings)
+}
+
+object ContextExtension {
+ /** Immutable instance of empty ContextExtension, which can be shared to avoid
+ * allocations. */
+ val empty = ContextExtension(Map())
+
+ /** Type of context variable binding. */
+ type VarBinding = (Byte, EvaluatedValue[_ <: SType])
+
+ object serializer extends SigmaSerializer[ContextExtension, ContextExtension] {
+ override def serialize(obj: ContextExtension, w: SigmaByteWriter): Unit = {
+ val size = obj.values.size
+ if (size > Byte.MaxValue)
+ error(s"Number of ContextExtension values $size exceeds ${Byte.MaxValue}.")
+ w.putUByte(size)
+ obj.values.foreach { case (id, v) => w.put(id).putValue(v) }
+ }
+
+ override def parse(r: SigmaByteReader): ContextExtension = {
+ val extSize = r.getByte()
+ if (extSize < 0)
+ error(s"Negative amount of context extension values: $extSize")
+ val values = (0 until extSize)
+ .map(_ => (r.getByte(), r.getValue().asInstanceOf[EvaluatedValue[_ <: SType]]))
+ ContextExtension(values.toMap)
+ }
+ }
+}
\ No newline at end of file
diff --git a/interpreter/shared/src/main/scala/sigmastate/interpreter/ProverResult.scala b/data/shared/src/main/scala/sigma/interpreter/ProverResult.scala
similarity index 92%
rename from interpreter/shared/src/main/scala/sigmastate/interpreter/ProverResult.scala
rename to data/shared/src/main/scala/sigma/interpreter/ProverResult.scala
index 45d6159d8c..f04b972cb5 100644
--- a/interpreter/shared/src/main/scala/sigmastate/interpreter/ProverResult.scala
+++ b/data/shared/src/main/scala/sigma/interpreter/ProverResult.scala
@@ -1,10 +1,7 @@
-package sigmastate.interpreter
-
-import java.util
+package sigma.interpreter
import scorex.util.encode.Base16
-import sigmastate.serialization.SigmaSerializer
-import sigmastate.utils.{SigmaByteReader, SigmaByteWriter}
+import sigma.serialization.{SigmaByteReader, SigmaByteWriter, SigmaSerializer}
/**
* Proof of correctness of tx spending
diff --git a/interpreter/shared/src/main/scala/sigmastate/serialization/ApplySerializer.scala b/data/shared/src/main/scala/sigma/serialization/ApplySerializer.scala
similarity index 70%
rename from interpreter/shared/src/main/scala/sigmastate/serialization/ApplySerializer.scala
rename to data/shared/src/main/scala/sigma/serialization/ApplySerializer.scala
index 89daeb0713..5a76f56298 100644
--- a/interpreter/shared/src/main/scala/sigmastate/serialization/ApplySerializer.scala
+++ b/data/shared/src/main/scala/sigma/serialization/ApplySerializer.scala
@@ -1,14 +1,14 @@
-package sigmastate.serialization
+package sigma.serialization
-import sigmastate.Values._
-import sigmastate._
-import sigmastate.lang.Terms.Apply
-import sigmastate.utils.SigmaByteWriter._
-import sigmastate.utils.{SigmaByteReader, SigmaByteWriter}
+import sigma.ast.{SType, Value}
+import sigma.ast.syntax._
+import sigma.ast.Apply
+import sigma.serialization.CoreByteWriter._
+import SigmaByteWriter._
case class ApplySerializer(cons: (Value[SType], IndexedSeq[Value[SType]]) => Value[SType])
extends ValueSerializer[Apply] {
- import sigmastate.Operations.ApplyInfo._
+ import sigma.ast.Operations.ApplyInfo._
override def opDesc = Apply
val funcInfo: DataInfo[SValue] = funcArg
val argsInfo: DataInfo[Seq[SValue]] = argsArg
diff --git a/interpreter/shared/src/main/scala/sigmastate/serialization/BlockValueSerializer.scala b/data/shared/src/main/scala/sigma/serialization/BlockValueSerializer.scala
similarity index 88%
rename from interpreter/shared/src/main/scala/sigmastate/serialization/BlockValueSerializer.scala
rename to data/shared/src/main/scala/sigma/serialization/BlockValueSerializer.scala
index 6e4056e275..a8a2ac359c 100644
--- a/interpreter/shared/src/main/scala/sigmastate/serialization/BlockValueSerializer.scala
+++ b/data/shared/src/main/scala/sigma/serialization/BlockValueSerializer.scala
@@ -1,12 +1,13 @@
-package sigmastate.serialization
+package sigma.serialization
-import sigmastate.Values._
-import sigmastate._
-import sigmastate.utils.{SigmaByteReader, SigmaByteWriter}
+import sigma.ast._
+import sigma.ast.syntax._
import ValueSerializer._
import sigma.util.safeNewArray
-import sigmastate.utils.SigmaByteWriter.{DataInfo, U, Vlq}
+import sigma.serialization.CoreByteWriter.{ArgInfo, DataInfo, U, Vlq}
+import SigmaByteWriter._
import debox.cfor
+import sigma.ast.SType
case class BlockValueSerializer(cons: (IndexedSeq[BlockItem], Value[SType]) => Value[SType])
extends ValueSerializer[BlockValue] {
diff --git a/data/shared/src/main/scala/sigma/serialization/BoolToSigmaPropSerializer.scala b/data/shared/src/main/scala/sigma/serialization/BoolToSigmaPropSerializer.scala
new file mode 100644
index 0000000000..4032157a02
--- /dev/null
+++ b/data/shared/src/main/scala/sigma/serialization/BoolToSigmaPropSerializer.scala
@@ -0,0 +1,21 @@
+package sigma.serialization
+
+import sigma.ast._
+import sigma.ast.syntax._
+import sigma.serialization.CoreByteWriter.DataInfo
+import SigmaByteWriter._
+
+case class BoolToSigmaPropSerializer(cons: BoolValue => SigmaPropValue) extends ValueSerializer[BoolToSigmaProp] {
+ import Operations.BoolToSigmaPropInfo._
+ override def opDesc = BoolToSigmaProp
+ val conditionInfo: DataInfo[SValue] = conditionArg
+
+ def serialize(obj: BoolToSigmaProp, w: SigmaByteWriter): Unit = {
+ w.putValue(obj.value, conditionInfo)
+ }
+
+ def parse(r: SigmaByteReader): Value[SType] = {
+ val p = r.getValue().asBoolValue
+ cons(p)
+ }
+}
diff --git a/data/shared/src/main/scala/sigma/serialization/CaseObjectSerialization.scala b/data/shared/src/main/scala/sigma/serialization/CaseObjectSerialization.scala
new file mode 100644
index 0000000000..f1a8047922
--- /dev/null
+++ b/data/shared/src/main/scala/sigma/serialization/CaseObjectSerialization.scala
@@ -0,0 +1,20 @@
+package sigma.serialization
+
+import sigma.ast.{Height, LastBlockUtxoRootHash, MinerPubkey, SType, Value, ValueCompanion}
+
+case class CaseObjectSerialization[V <: Value[SType]](override val opDesc: ValueCompanion, obj: V)
+ extends ValueSerializer[V] {
+
+ override def serialize(obj: V, w: SigmaByteWriter): Unit = ()
+
+ override def parse(r: SigmaByteReader): V = {
+ opDesc match {
+ case Height => r.wasUsingBlockchainContext = true
+ case LastBlockUtxoRootHash => r.wasUsingBlockchainContext = true
+ case MinerPubkey => r.wasUsingBlockchainContext = true
+ case _ =>
+ }
+
+ obj
+ }
+}
diff --git a/interpreter/shared/src/main/scala/sigmastate/serialization/ConcreteCollectionBooleanConstantSerializer.scala b/data/shared/src/main/scala/sigma/serialization/ConcreteCollectionBooleanConstantSerializer.scala
similarity index 89%
rename from interpreter/shared/src/main/scala/sigmastate/serialization/ConcreteCollectionBooleanConstantSerializer.scala
rename to data/shared/src/main/scala/sigma/serialization/ConcreteCollectionBooleanConstantSerializer.scala
index 0419fd6e04..6d747f627f 100644
--- a/interpreter/shared/src/main/scala/sigmastate/serialization/ConcreteCollectionBooleanConstantSerializer.scala
+++ b/data/shared/src/main/scala/sigma/serialization/ConcreteCollectionBooleanConstantSerializer.scala
@@ -1,11 +1,11 @@
-package sigmastate.serialization
+package sigma.serialization
-import sigmastate.{SCollection, SBoolean, ArgInfo}
-import sigmastate.Values._
-import sigmastate.utils.{SigmaByteReader, SigmaByteWriter}
-import SigmaByteWriter._
+import sigma.ast._
+import sigma.ast.syntax._
import sigma.util.safeNewArray
import debox.cfor
+import sigma.ast.{SBoolean, SCollection}
+import sigma.serialization.CoreByteWriter.{ArgInfo, Bits, DataInfo, U, Vlq, maxBitsInfo}
case class ConcreteCollectionBooleanConstantSerializer(cons: (IndexedSeq[Value[SBoolean.type]], SBoolean.type) => Value[SCollection[SBoolean.type]])
extends ValueSerializer[ConcreteCollection[SBoolean.type]] {
diff --git a/interpreter/shared/src/main/scala/sigmastate/serialization/ConcreteCollectionSerializer.scala b/data/shared/src/main/scala/sigma/serialization/ConcreteCollectionSerializer.scala
similarity index 86%
rename from interpreter/shared/src/main/scala/sigmastate/serialization/ConcreteCollectionSerializer.scala
rename to data/shared/src/main/scala/sigma/serialization/ConcreteCollectionSerializer.scala
index c11452dde8..a415b4a567 100644
--- a/interpreter/shared/src/main/scala/sigmastate/serialization/ConcreteCollectionSerializer.scala
+++ b/data/shared/src/main/scala/sigma/serialization/ConcreteCollectionSerializer.scala
@@ -1,12 +1,13 @@
-package sigmastate.serialization
+package sigma.serialization
-import sigmastate.{SCollection, ArgInfo, SType}
-import sigmastate.Values._
-import sigmastate.utils.{SigmaByteReader, SigmaByteWriter}
+import sigma.ast._
+import sigma.ast.syntax._
import ValueSerializer._
import sigma.util.safeNewArray
-import sigmastate.utils.SigmaByteWriter.{DataInfo, U, Vlq}
+import SigmaByteWriter._
import debox.cfor
+import sigma.ast.{SCollection, SType}
+import sigma.serialization.CoreByteWriter.{ArgInfo, DataInfo, U, Vlq}
case class ConcreteCollectionSerializer(cons: (IndexedSeq[Value[SType]], SType) => Value[SCollection[SType]])
extends ValueSerializer[ConcreteCollection[_ <: SType]] {
diff --git a/interpreter/shared/src/main/scala/sigmastate/serialization/ConstantPlaceholderSerializer.scala b/data/shared/src/main/scala/sigma/serialization/ConstantPlaceholderSerializer.scala
similarity index 80%
rename from interpreter/shared/src/main/scala/sigmastate/serialization/ConstantPlaceholderSerializer.scala
rename to data/shared/src/main/scala/sigma/serialization/ConstantPlaceholderSerializer.scala
index 803f17079f..7cda3713a4 100644
--- a/interpreter/shared/src/main/scala/sigmastate/serialization/ConstantPlaceholderSerializer.scala
+++ b/data/shared/src/main/scala/sigma/serialization/ConstantPlaceholderSerializer.scala
@@ -1,12 +1,11 @@
-package sigmastate.serialization
+package sigma.serialization
-import sigmastate.Values._
-import sigmastate._
-import sigmastate.utils.{SigmaByteReader, SigmaByteWriter}
+import sigma.ast.SType
+import sigma.ast._
case class ConstantPlaceholderSerializer(cons: (Int, SType) => Value[SType])
extends ValueSerializer[ConstantPlaceholder[SType]] {
- import sigmastate.Operations.ConstantPlaceholderInfo._
+ import Operations.ConstantPlaceholderInfo._
override def opDesc = ConstantPlaceholder
override def serialize(obj: ConstantPlaceholder[SType], w: SigmaByteWriter): Unit = {
diff --git a/interpreter/shared/src/main/scala/sigmastate/serialization/ConstantSerializer.scala b/data/shared/src/main/scala/sigma/serialization/ConstantSerializer.scala
similarity index 77%
rename from interpreter/shared/src/main/scala/sigmastate/serialization/ConstantSerializer.scala
rename to data/shared/src/main/scala/sigma/serialization/ConstantSerializer.scala
index 8e97117467..eccc2d79ca 100644
--- a/interpreter/shared/src/main/scala/sigmastate/serialization/ConstantSerializer.scala
+++ b/data/shared/src/main/scala/sigma/serialization/ConstantSerializer.scala
@@ -1,9 +1,7 @@
-package sigmastate.serialization
+package sigma.serialization
-import sigmastate.SType
-import sigmastate.Values._
-import sigmastate.lang.SigmaBuilder
-import sigmastate.utils.{SigmaByteReader, SigmaByteWriter}
+import sigma.ast.{SType, SigmaBuilder}
+import sigma.ast._
/** This works in tandem with DataSerializer, if you change one make sure to check the other.*/
case class ConstantSerializer(builder: SigmaBuilder)
diff --git a/interpreter/shared/src/main/scala/sigmastate/serialization/ConstantStore.scala b/data/shared/src/main/scala/sigma/serialization/ConstantStore.scala
similarity index 74%
rename from interpreter/shared/src/main/scala/sigmastate/serialization/ConstantStore.scala
rename to data/shared/src/main/scala/sigma/serialization/ConstantStore.scala
index dfa7dbb30a..dd91c9a7b1 100644
--- a/interpreter/shared/src/main/scala/sigmastate/serialization/ConstantStore.scala
+++ b/data/shared/src/main/scala/sigma/serialization/ConstantStore.scala
@@ -1,9 +1,8 @@
-package sigmastate.serialization
+package sigma.serialization
-import sigmastate.SType
-import sigmastate.Values.{Constant, ConstantNode, ConstantPlaceholder}
-import sigmastate.lang.SigmaBuilder
+import sigma.ast.{Constant, ConstantNode, ConstantPlaceholder, SigmaBuilder}
import debox.Buffer
+import sigma.ast.SType
/** HOTSPOT: used in deserialization (don't beautify this code) */
class ConstantStore(private val constants: IndexedSeq[Constant[SType]] = Constant.EmptySeq) {
@@ -14,7 +13,7 @@ class ConstantStore(private val constants: IndexedSeq[Constant[SType]] = Constan
store += c.asInstanceOf[Constant[SType]]
val tpe = c.asInstanceOf[ConstantNode[T]].tpe
builder.mkConstantPlaceholder[tpe.type](store.length - 1, tpe)
- .asInstanceOf[sigmastate.Values.ConstantPlaceholder[T]]
+ .asInstanceOf[sigma.ast.ConstantPlaceholder[T]]
}
@inline final def get(index: Int): Constant[SType] = store(index)
diff --git a/interpreter/shared/src/main/scala/sigmastate/serialization/CreateAvlTreeSerializer.scala b/data/shared/src/main/scala/sigma/serialization/CreateAvlTreeSerializer.scala
similarity index 74%
rename from interpreter/shared/src/main/scala/sigmastate/serialization/CreateAvlTreeSerializer.scala
rename to data/shared/src/main/scala/sigma/serialization/CreateAvlTreeSerializer.scala
index efd84f38b6..018b63376b 100644
--- a/interpreter/shared/src/main/scala/sigmastate/serialization/CreateAvlTreeSerializer.scala
+++ b/data/shared/src/main/scala/sigma/serialization/CreateAvlTreeSerializer.scala
@@ -1,19 +1,20 @@
-package sigmastate.serialization
+package sigma.serialization
-import sigmastate.SCollection._
-import sigmastate.SOption.SIntOption
-import sigmastate.utils.{SigmaByteReader, SigmaByteWriter}
-import sigmastate._
-import sigmastate.Values._
-import sigmastate.lang.Terms.ValueOps
-import sigmastate.utils.SigmaByteWriter.DataInfo
+import sigma.ast.SCollection.SByteArray
+import sigma.ast.SInt
+import sigma.ast.SOption.SIntOption
+import sigma.serialization.CoreByteWriter.DataInfo
+import sigma.ast._
+import sigma.ast.syntax._
+import sigma.ast.syntax.ValueOps
+import SigmaByteWriter._
case class CreateAvlTreeSerializer(
cons: (ByteValue, Value[SByteArray], IntValue, Value[SIntOption]) => AvlTreeValue
)
extends ValueSerializer[CreateAvlTree]
{
- import sigmastate.Operations.CreateAvlTreeInfo._
+ import Operations.CreateAvlTreeInfo._
override def opDesc = CreateAvlTree
val operationFlagsInfo: DataInfo[SValue] = operationFlagsArg
val digestInfo: DataInfo[SValue] = digestArg
diff --git a/data/shared/src/main/scala/sigma/serialization/CreateProveDlogSerializer.scala b/data/shared/src/main/scala/sigma/serialization/CreateProveDlogSerializer.scala
new file mode 100644
index 0000000000..5135cd1e37
--- /dev/null
+++ b/data/shared/src/main/scala/sigma/serialization/CreateProveDlogSerializer.scala
@@ -0,0 +1,26 @@
+package sigma.serialization
+
+import sigma.ast.{CreateProveDlog, SGroupElement}
+import sigma.serialization.CoreByteWriter._
+import sigma.ast.Value
+import sigma.ast.syntax._
+import sigma.ast.syntax.ValueOps
+import SigmaByteWriter._
+
+case class CreateProveDlogSerializer(cons: Value[SGroupElement.type] => SigmaPropValue)
+ extends ValueSerializer[CreateProveDlog] {
+ import sigma.ast.Operations.CreateProveDlogInfo._
+
+ override def opDesc = CreateProveDlog
+
+ val valueInfo: DataInfo[SValue] = valueArg
+
+ override def serialize(obj: CreateProveDlog, w: SigmaByteWriter): Unit = {
+ w.putValue(obj.value, valueInfo)
+ }
+
+ override def parse(r: SigmaByteReader) = {
+ val v = r.getValue().asValue[SGroupElement.type]
+ cons(v)
+ }
+}
diff --git a/data/shared/src/main/scala/sigma/serialization/DataSerializer.scala b/data/shared/src/main/scala/sigma/serialization/DataSerializer.scala
new file mode 100644
index 0000000000..5f554e96a1
--- /dev/null
+++ b/data/shared/src/main/scala/sigma/serialization/DataSerializer.scala
@@ -0,0 +1,41 @@
+package sigma.serialization
+
+import org.ergoplatform.ErgoBox
+import sigma.ast._
+import sigma.data.CBox
+
+/** This works in tandem with ConstantSerializer, if you change one make sure to check the other.*/
+object DataSerializer extends CoreDataSerializer {
+
+ /** Use type descriptor `tpe` to deconstruct type structure and recursively serialize subcomponents.
+ * Primitive types are leaves of the type tree, and they are served as basis of recursion.
+ * The data value `v` is expected to conform to the type described by `tpe`.
+ */
+ override def serialize[T <: SType](v: T#WrappedType, tpe: T, w: CoreByteWriter): Unit = tpe match {
+ case SBox =>
+ val b = v.asInstanceOf[CBox]
+ ErgoBox.sigmaSerializer.serialize(b.ebox, w.asInstanceOf[SigmaByteWriter])
+ case _ =>
+ super.serialize(v, tpe, w)
+ }
+
+ /** Reads a data value from Reader. The data value bytes is expected to confirm
+ * to the type descriptor `tpe`.
+ * The data structure depth is limited by r.maxTreeDepth which is
+ * SigmaSerializer.MaxTreeDepth by default.
+ */
+ override def deserialize[T <: SType](tpe: T, r: CoreByteReader): T#WrappedType = {
+ val res = (tpe match {
+ case SBox =>
+ val depth = r.level
+ r.level = depth + 1
+ val res = CBox(ErgoBox.sigmaSerializer.parse(r.asInstanceOf[SigmaByteReader]))
+ r.level = r.level - 1
+ res
+ case t =>
+ super.deserialize(t, r)
+ }).asInstanceOf[T#WrappedType]
+ res
+ }
+
+}
diff --git a/interpreter/shared/src/main/scala/sigmastate/serialization/ErgoTreeSerializer.scala b/data/shared/src/main/scala/sigma/serialization/ErgoTreeSerializer.scala
similarity index 90%
rename from interpreter/shared/src/main/scala/sigmastate/serialization/ErgoTreeSerializer.scala
rename to data/shared/src/main/scala/sigma/serialization/ErgoTreeSerializer.scala
index f8c5221945..3d1061d774 100644
--- a/interpreter/shared/src/main/scala/sigmastate/serialization/ErgoTreeSerializer.scala
+++ b/data/shared/src/main/scala/sigma/serialization/ErgoTreeSerializer.scala
@@ -1,19 +1,14 @@
-package sigmastate.serialization
+package sigma.serialization
-import org.ergoplatform.validation.ValidationRules.{CheckDeserializedScriptIsSigmaProp, CheckHeaderSizeBit, CheckPositionLimit}
-import org.ergoplatform.validation.{SigmaValidationSettings, ValidationException}
-import sigmastate.{SType}
-import sigmastate.Values.{Constant, ErgoTree, UnparsedErgoTree}
-import sigmastate.lang.DeserializationSigmaBuilder
-import sigmastate.lang.Terms.ValueOps
-import sigmastate.utils.{SigmaByteReader, SigmaByteWriter}
-import sigmastate.Values.ErgoTree.EmptyConstants
+import org.ergoplatform.validation.ValidationRules.{CheckDeserializedScriptIsSigmaProp, CheckHeaderSizeBit}
+import sigma.ast.{Constant, DeserializationSigmaBuilder, ErgoTree, SType, SubstConstants, UnparsedErgoTree}
+import sigma.ast.syntax.ValueOps
+import sigma.ast.ErgoTree.{EmptyConstants, HeaderType}
import sigma.util.safeNewArray
-import sigmastate.utxo.ComplexityTable
import debox.cfor
import sigma.VersionContext
-import sigmastate.exceptions.{SerializerException, ReaderPositionLimitExceeded}
-import java.util
+import sigma.validation.{SigmaValidationSettings, ValidationException}
+import sigma.validation.ValidationRules.CheckPositionLimit
/**
* Rationale for soft-forkable ErgoTree serialization.
@@ -137,12 +132,10 @@ class ErgoTreeSerializer {
deserializeErgoTree(r, maxTreeSizeBytes, true)
}
- private[sigmastate] def deserializeErgoTree(r: SigmaByteReader, maxTreeSizeBytes: Int, checkType: Boolean): ErgoTree = {
+ private[sigma] def deserializeErgoTree(r: SigmaByteReader, maxTreeSizeBytes: Int, checkType: Boolean): ErgoTree = {
val startPos = r.position
val previousPositionLimit = r.positionLimit
- val previousComplexity = r.complexity
r.positionLimit = r.position + maxTreeSizeBytes
- r.complexity = 0
val (h, sizeOpt) = deserializeHeaderAndSize(r)
val bodyPos = r.position
val tree = try {
@@ -155,25 +148,29 @@ class ErgoTreeSerializer {
val wasDeserialize_saved = r.wasDeserialize
r.wasDeserialize = false
+ val wasUsingBlockchainContext_saved = r.wasUsingBlockchainContext
+ r.wasUsingBlockchainContext = false
+
val root = ValueSerializer.deserialize(r)
val hasDeserialize = r.wasDeserialize // == true if there was deserialization node
r.wasDeserialize = wasDeserialize_saved
+ val isUsingBlockchainContext = r.wasUsingBlockchainContext // == true if there was a node using the blockchain context
+ r.wasUsingBlockchainContext = wasUsingBlockchainContext_saved
+
if (checkType) {
CheckDeserializedScriptIsSigmaProp(root)
}
r.constantStore = previousConstantStore
- val complexity = r.complexity
-
// now we know the end position of propositionBytes, read them all at once into array
val treeSize = r.position - startPos
r.position = startPos
val propositionBytes = r.getBytes(treeSize)
new ErgoTree(
- h, cs, Right(root.asSigmaProp), complexity,
- propositionBytes, Some(hasDeserialize))
+ h, cs, Right(root.asSigmaProp),
+ propositionBytes, Some(hasDeserialize), Some(isUsingBlockchainContext))
}
catch {
case e: ReaderPositionLimitExceeded =>
@@ -187,8 +184,7 @@ class ErgoTreeSerializer {
val numBytes = bodyPos - startPos + treeSize
r.position = startPos
val bytes = r.getBytes(numBytes)
- val complexity = ComplexityTable.OpCodeComplexity(Constant.opCode)
- new ErgoTree(ErgoTree.DefaultHeader, EmptyConstants, Left(UnparsedErgoTree(bytes, ve)), complexity, bytes, None)
+ new ErgoTree(ErgoTree.DefaultHeader, EmptyConstants, Left(UnparsedErgoTree(bytes, ve)), bytes, None, None)
case None =>
throw new SerializerException(
s"Cannot handle ValidationException, ErgoTree serialized without size bit.", Some(ve))
@@ -196,14 +192,13 @@ class ErgoTreeSerializer {
}
finally {
r.positionLimit = previousPositionLimit
- r.complexity = previousComplexity
}
tree
}
/** Deserialize `header` and optional `size` slots only. */
- private def deserializeHeaderAndSize(r: SigmaByteReader): (Byte, Option[Int]) = {
- val header = r.getByte()
+ private def deserializeHeaderAndSize(r: SigmaByteReader): (HeaderType, Option[Int]) = {
+ val header = HeaderType @@ r.getByte()
CheckHeaderSizeBit(header)
val sizeOpt = if (ErgoTree.hasSize(header)) {
val size = r.getUInt().toInt
@@ -230,7 +225,7 @@ class ErgoTreeSerializer {
/** Deserialize constants section only.
* HOTSPOT: don't beautify this code
*/
- private def deserializeConstants(header: Byte, r: SigmaByteReader): IndexedSeq[Constant[SType]] = {
+ private def deserializeConstants(header: HeaderType, r: SigmaByteReader): IndexedSeq[Constant[SType]] = {
val constants: IndexedSeq[Constant[SType]] =
if (ErgoTree.isConstantSegregation(header)) {
val nConsts = r.getUInt().toInt
@@ -254,7 +249,7 @@ class ErgoTreeSerializer {
}
/** Deserialize header and constant sections, but output the rest of the bytes as separate array. */
- def deserializeHeaderWithTreeBytes(r: SigmaByteReader): (Byte, Option[Int], IndexedSeq[Constant[SType]], Array[Byte]) = {
+ def deserializeHeaderWithTreeBytes(r: SigmaByteReader): (HeaderType, Option[Int], IndexedSeq[Constant[SType]], Array[Byte]) = {
val (header, sizeOpt) = deserializeHeaderAndSize(r)
val constants = deserializeConstants(header, r)
val treeBytes = r.getBytes(r.remaining)
@@ -271,7 +266,7 @@ class ErgoTreeSerializer {
* positions(r(i)) == i whenever r(i) != -1. When r(i) == -1 then backreference
* is not defined (which means the constant with the index `i` is not substituted.
*/
- private[sigmastate] def getPositionsBackref(positions: Array[Int], positionsRange: Int): Array[Int] = {
+ private[sigma] def getPositionsBackref(positions: Array[Int], positionsRange: Int): Array[Int] = {
// allocate array of back references: forall i: positionsBackref(i) is index in `positions`
val positionsBackref = safeNewArray[Int](positionsRange)
// mark all positions are not assigned
@@ -290,7 +285,7 @@ class ErgoTreeSerializer {
/** Transforms serialized bytes of ErgoTree with segregated constants by
* replacing constants at given positions with new values. This operation
* allow to use serialized scripts as pre-defined templates.
- * See [[sigmastate.SubstConstants]] for details.
+ * See [[SubstConstants]] for details.
*
* @param scriptBytes serialized ErgoTree with ConstantSegregationFlag set to 1.
* @param positions zero based indexes in ErgoTree.constants array which
diff --git a/interpreter/shared/src/main/scala/sigmastate/serialization/FuncValueSerializer.scala b/data/shared/src/main/scala/sigma/serialization/FuncValueSerializer.scala
similarity index 89%
rename from interpreter/shared/src/main/scala/sigmastate/serialization/FuncValueSerializer.scala
rename to data/shared/src/main/scala/sigma/serialization/FuncValueSerializer.scala
index d9f9ea752d..7f9b8cc927 100644
--- a/interpreter/shared/src/main/scala/sigmastate/serialization/FuncValueSerializer.scala
+++ b/data/shared/src/main/scala/sigma/serialization/FuncValueSerializer.scala
@@ -1,12 +1,13 @@
-package sigmastate.serialization
+package sigma.serialization
-import sigmastate.Values._
-import sigmastate._
-import sigmastate.utils.{SigmaByteReader, SigmaByteWriter}
+import sigma.ast._
+import sigma.ast.syntax._
import ValueSerializer._
import sigma.util.safeNewArray
-import sigmastate.utils.SigmaByteWriter.{DataInfo, U, Vlq}
+import SigmaByteWriter._
import debox.cfor
+import sigma.ast.SType
+import sigma.serialization.CoreByteWriter.{ArgInfo, DataInfo, U, Vlq}
case class FuncValueSerializer(cons: (IndexedSeq[(Int, SType)], Value[SType]) => Value[SType])
extends ValueSerializer[FuncValue] {
diff --git a/interpreter/shared/src/main/scala/sigmastate/serialization/GetVarSerializer.scala b/data/shared/src/main/scala/sigma/serialization/GetVarSerializer.scala
similarity index 68%
rename from interpreter/shared/src/main/scala/sigmastate/serialization/GetVarSerializer.scala
rename to data/shared/src/main/scala/sigma/serialization/GetVarSerializer.scala
index cd9e9872c4..c3618ac0bf 100644
--- a/interpreter/shared/src/main/scala/sigmastate/serialization/GetVarSerializer.scala
+++ b/data/shared/src/main/scala/sigma/serialization/GetVarSerializer.scala
@@ -1,14 +1,11 @@
-package sigmastate.serialization
+package sigma.serialization
-import sigmastate.Values._
-import sigmastate._
-import sigmastate.utils.SigmaByteWriter.DataInfo
-import sigmastate.utils.{SigmaByteReader, SigmaByteWriter}
-import sigmastate.utxo.GetVar
+import sigma.ast._
+import sigma.serialization.CoreByteWriter.{ArgInfo, DataInfo}
case class GetVarSerializer(cons: (Byte, SType) => Value[SOption[SType]])
extends ValueSerializer[GetVar[_ <: SType]] {
- import sigmastate.Operations.GetVarInfo._
+ import Operations.GetVarInfo._
override def opDesc = GetVar
val typeInfo: DataInfo[SType] = ArgInfo("type", "expected type of context variable")
val varIdInfo: DataInfo[Byte] = varIdArg
diff --git a/interpreter/shared/src/main/scala/sigmastate/serialization/LogicalNotSerializer.scala b/data/shared/src/main/scala/sigma/serialization/LogicalNotSerializer.scala
similarity index 56%
rename from interpreter/shared/src/main/scala/sigmastate/serialization/LogicalNotSerializer.scala
rename to data/shared/src/main/scala/sigma/serialization/LogicalNotSerializer.scala
index 667e8a699f..0130d58d83 100644
--- a/interpreter/shared/src/main/scala/sigmastate/serialization/LogicalNotSerializer.scala
+++ b/data/shared/src/main/scala/sigma/serialization/LogicalNotSerializer.scala
@@ -1,11 +1,10 @@
-package sigmastate.serialization
+package sigma.serialization
-import sigmastate.LogicalNot
-import sigmastate.Operations.LogicalNotInfo.inputArg
-import sigmastate.Values.{BoolValue, SValue}
-import sigmastate.lang.Terms._
-import sigmastate.utils.SigmaByteWriter.DataInfo
-import sigmastate.utils.{SigmaByteReader, SigmaByteWriter}
+import sigma.ast.LogicalNot
+import sigma.serialization.CoreByteWriter.DataInfo
+import sigma.ast.Operations.LogicalNotInfo.inputArg
+import sigma.ast.syntax._
+import SigmaByteWriter._
case class LogicalNotSerializer(cons: BoolValue => BoolValue)
extends ValueSerializer[LogicalNot] {
diff --git a/interpreter/shared/src/main/scala/sigmastate/serialization/MethodCallSerializer.scala b/data/shared/src/main/scala/sigma/serialization/MethodCallSerializer.scala
similarity index 81%
rename from interpreter/shared/src/main/scala/sigmastate/serialization/MethodCallSerializer.scala
rename to data/shared/src/main/scala/sigma/serialization/MethodCallSerializer.scala
index e474d8a7c2..319a4284e2 100644
--- a/interpreter/shared/src/main/scala/sigmastate/serialization/MethodCallSerializer.scala
+++ b/data/shared/src/main/scala/sigma/serialization/MethodCallSerializer.scala
@@ -1,14 +1,12 @@
-package sigmastate.serialization
+package sigma.serialization
-import sigmastate.Values._
-import sigmastate._
-import sigmastate.lang.Terms.STypeSubst
-import sigmastate.lang.Terms.MethodCall
+import sigma.ast.syntax._
+import sigma.ast.{MethodCall, SContextMethods, SMethod, SType, STypeSubst, Value, ValueCompanion}
import sigma.util.safeNewArray
-import sigmastate.utils.SigmaByteWriter.{DataInfo, valuesItemInfo}
-import sigmastate.utils.{SigmaByteReader, SigmaByteWriter}
-import sigmastate.utxo.ComplexityTable
+import SigmaByteWriter._
import debox.cfor
+import sigma.ast.SContextMethods.BlockchainContextMethodNames
+import sigma.serialization.CoreByteWriter.{ArgInfo, DataInfo}
case class MethodCallSerializer(cons: (Value[SType], SMethod, IndexedSeq[Value[SType]], STypeSubst) => Value[SType])
extends ValueSerializer[MethodCall] {
@@ -27,8 +25,6 @@ case class MethodCallSerializer(cons: (Value[SType], SMethod, IndexedSeq[Value[S
w.putValues(mc.args, argsInfo, argsItemInfo)
}
- override def getComplexity: Int = 0 // because we add it explicitly in parse below
-
/** The SMethod instances in STypeCompanions may have type STypeIdent in methods types,
* but a valid ErgoTree should have SMethod instances specialized for specific types
* of `obj` and `args` using `specializeFor`.
@@ -47,8 +43,6 @@ case class MethodCallSerializer(cons: (Value[SType], SMethod, IndexedSeq[Value[S
val obj = r.getValue()
val args = r.getValues()
val method = SMethod.fromIds(typeId, methodId)
- val complexity = ComplexityTable.MethodCallComplexity.getOrElse((typeId, methodId), ComplexityTable.MinimalComplexity)
- r.addComplexity(complexity)
val nArgs = args.length
val types: Seq[SType] =
@@ -62,6 +56,11 @@ case class MethodCallSerializer(cons: (Value[SType], SMethod, IndexedSeq[Value[S
}
val specMethod = method.specializeFor(obj.tpe, types)
+
+ var isUsingBlockchainContext = specMethod.objType == SContextMethods &&
+ BlockchainContextMethodNames.contains(method.name)
+ r.wasUsingBlockchainContext ||= isUsingBlockchainContext
+
cons(obj, specMethod, args, Map.empty)
}
}
diff --git a/interpreter/shared/src/main/scala/sigmastate/serialization/ModQArithOpSerializer.scala b/data/shared/src/main/scala/sigma/serialization/ModQArithOpSerializer.scala
similarity index 71%
rename from interpreter/shared/src/main/scala/sigmastate/serialization/ModQArithOpSerializer.scala
rename to data/shared/src/main/scala/sigma/serialization/ModQArithOpSerializer.scala
index 765aaeb7b4..181c3f7c5e 100644
--- a/interpreter/shared/src/main/scala/sigmastate/serialization/ModQArithOpSerializer.scala
+++ b/data/shared/src/main/scala/sigma/serialization/ModQArithOpSerializer.scala
@@ -1,10 +1,10 @@
-package sigmastate.serialization
+package sigma.serialization
-import sigmastate.Values.{BigIntValue, Value, SValue}
-import sigmastate.lang.Terms._
-import sigmastate.utils.SigmaByteWriter.DataInfo
-import sigmastate.utils.{SigmaByteReader, SigmaByteWriter}
-import sigmastate.{ModQArithOpCompanion, SType, ModQArithOp}
+import sigma.ast.{ModQArithOp, ModQArithOpCompanion, SType}
+import sigma.ast.syntax.{BigIntValue, SValue, ValueOps}
+import sigma.serialization.CoreByteWriter.DataInfo
+import sigma.ast.Value
+import SigmaByteWriter._
// TODO v6.0: make sure it is covered with tests (see https://github.com/ScorexFoundation/sigmastate-interpreter/issues/327)
case class ModQArithOpSerializer(override val opDesc: ModQArithOpCompanion, cons: (BigIntValue, BigIntValue) => BigIntValue)
diff --git a/interpreter/shared/src/main/scala/sigmastate/serialization/ModQSerializer.scala b/data/shared/src/main/scala/sigma/serialization/ModQSerializer.scala
similarity index 68%
rename from interpreter/shared/src/main/scala/sigmastate/serialization/ModQSerializer.scala
rename to data/shared/src/main/scala/sigma/serialization/ModQSerializer.scala
index 335c12c1af..346f1ef6e2 100644
--- a/interpreter/shared/src/main/scala/sigmastate/serialization/ModQSerializer.scala
+++ b/data/shared/src/main/scala/sigma/serialization/ModQSerializer.scala
@@ -1,9 +1,9 @@
-package sigmastate.serialization
+package sigma.serialization
-import sigmastate.Values.Value
-import sigmastate.lang.Terms._
-import sigmastate.utils.{SigmaByteReader, SigmaByteWriter}
-import sigmastate.{ModQ, SType}
+import sigma.ast.{ModQ, SType}
+import sigma.ast.Value
+import SigmaByteWriter._
+import sigma.ast.syntax.ValueOps
// TODO v6.0: make sure it is covered with tests (see https://github.com/ScorexFoundation/sigmastate-interpreter/issues/327)
object ModQSerializer extends ValueSerializer[ModQ] {
diff --git a/interpreter/shared/src/main/scala/sigmastate/serialization/OneArgumentOperationSerializer.scala b/data/shared/src/main/scala/sigma/serialization/OneArgumentOperationSerializer.scala
similarity index 60%
rename from interpreter/shared/src/main/scala/sigmastate/serialization/OneArgumentOperationSerializer.scala
rename to data/shared/src/main/scala/sigma/serialization/OneArgumentOperationSerializer.scala
index fd3fd8c2ea..15b5d89cb5 100644
--- a/interpreter/shared/src/main/scala/sigmastate/serialization/OneArgumentOperationSerializer.scala
+++ b/data/shared/src/main/scala/sigma/serialization/OneArgumentOperationSerializer.scala
@@ -1,10 +1,10 @@
-package sigmastate.serialization
+package sigma.serialization
-import sigmastate.Values.{Value, SValue}
-import sigmastate.lang.Terms._
-import sigmastate.utils.SigmaByteWriter.DataInfo
-import sigmastate.utils.{SigmaByteReader, SigmaByteWriter}
-import sigmastate.{OneArgumentOperation, OneArgumentOperationCompanion, SType}
+import sigma.ast.{OneArgumentOperation, OneArgumentOperationCompanion, SType}
+import sigma.serialization.CoreByteWriter.DataInfo
+import sigma.ast.Value
+import sigma.ast.syntax._
+import SigmaByteWriter._
case class OneArgumentOperationSerializer[T <: SType](opDesc: OneArgumentOperationCompanion, cons: Value[T] => SValue)
extends ValueSerializer[OneArgumentOperation[T, SType]] {
diff --git a/interpreter/shared/src/main/scala/sigmastate/serialization/OpCodes.scala b/data/shared/src/main/scala/sigma/serialization/OpCodes.scala
similarity index 81%
rename from interpreter/shared/src/main/scala/sigmastate/serialization/OpCodes.scala
rename to data/shared/src/main/scala/sigma/serialization/OpCodes.scala
index 74ec9bd58e..70050d00ba 100644
--- a/interpreter/shared/src/main/scala/sigmastate/serialization/OpCodes.scala
+++ b/data/shared/src/main/scala/sigma/serialization/OpCodes.scala
@@ -1,37 +1,13 @@
-package sigmastate.serialization
+package sigma.serialization
-import sigmastate.serialization.OpCodes.OpCode
+import sigma.ast.TypeCodes.LastConstantCode
import supertagged.TaggedType
-/** Encoding of types for serialization. */
-trait TypeCodes {
- /** Decoding of types depends on the first byte and in general is a recursive procedure
- * consuming some number of bytes from Reader.
- * All data types are recognized by the first byte falling in the region [FirstDataType .. LastDataType] */
- val FirstDataType: OpCode = OpCode @@ 1.toByte
- val LastDataType : OpCode = OpCode @@ 111.toByte
-
- /** SFunc types occupy remaining space of byte values [FirstFuncType .. 255] */
- val FirstFuncType: OpCode = OpCode @@ (LastDataType + 1).toByte
- val LastFuncType : OpCode = OpCode @@ 255.toByte
-}
-
/** Encoding of values for serialization. */
-trait ValueCodes extends TypeCodes {
- /** We use optimized encoding of constant values to save space in serialization.
- * Since Box registers are stored as Constant nodes we save 1 byte for each register.
- * This is due to convention that Value.opCode falling in [1..LastDataType] region is a constant.
- * Thus, we can just decode an instance of SType and then decode data using DataSerializer.
- *
- * Decoding of constants depends on the first byte and in general is a recursive procedure
- * consuming some number of bytes from Reader.
- * */
- val ConstantCode: OpCode = OpCode @@ 0.toByte
-
- /** The last constant code is equal to FirstFuncType which represent generic function type.
- * We use this single code to represent all functional constants, since we don't have enough space in single byte.
- * Subsequent bytes have to be read from Reader in order to decode the type of the function and the corresponding data. */
- val LastConstantCode: OpCode = OpCode @@ (LastDataType + 1).toByte
+object ValueCodes {
+ object OpCode extends TaggedType[Byte]
+ type OpCode = OpCode.Type
+
}
/** The set of all possible IR graph nodes can be split in two subsets:
@@ -52,10 +28,8 @@ trait ValueCodes extends TypeCodes {
* 1) For validation rule CheckValidOpCode we use OpCodes range, so we use single byte encoding.
* 2) For CheckCostFuncOperation we use 1-511 range and extended encoding (see docs)
*/
-object OpCodes extends ValueCodes {
-
- object OpCode extends TaggedType[Byte]
- type OpCode = OpCode.Type
+object OpCodes {
+ import ValueCodes._
private def newOpCode(shift: Short): OpCode = OpCode @@ (LastConstantCode + shift).toByte
diff --git a/interpreter/shared/src/main/scala/sigmastate/serialization/OptionGetOrElseSerializer.scala b/data/shared/src/main/scala/sigma/serialization/OptionGetOrElseSerializer.scala
similarity index 66%
rename from interpreter/shared/src/main/scala/sigmastate/serialization/OptionGetOrElseSerializer.scala
rename to data/shared/src/main/scala/sigma/serialization/OptionGetOrElseSerializer.scala
index bc0fe694e6..ef00ad48ff 100644
--- a/interpreter/shared/src/main/scala/sigmastate/serialization/OptionGetOrElseSerializer.scala
+++ b/data/shared/src/main/scala/sigma/serialization/OptionGetOrElseSerializer.scala
@@ -1,15 +1,13 @@
-package sigmastate.serialization
+package sigma.serialization
-import sigmastate.Values._
-import sigmastate._
-import sigmastate.lang.Terms._
-import sigmastate.utils.SigmaByteWriter.DataInfo
-import sigmastate.utils.{SigmaByteReader, SigmaByteWriter}
-import sigmastate.utxo.OptionGetOrElse
+import sigma.ast._
+import sigma.serialization.CoreByteWriter.DataInfo
+import sigma.ast.syntax._
+import SigmaByteWriter._
case class OptionGetOrElseSerializer(cons: (Value[SOption[SType]], Value[SType]) => Value[SType])
extends ValueSerializer[OptionGetOrElse[_ <: SType]] {
- import sigmastate.Operations.OptionGetOrElseInfo._
+ import Operations.OptionGetOrElseInfo._
override def opDesc = OptionGetOrElse
val thisInfo: DataInfo[SValue] = thisArg
val defaultInfo: DataInfo[SValue] = defaultArg
diff --git a/interpreter/shared/src/main/scala/sigmastate/serialization/PropertyCallSerializer.scala b/data/shared/src/main/scala/sigma/serialization/PropertyCallSerializer.scala
similarity index 60%
rename from interpreter/shared/src/main/scala/sigmastate/serialization/PropertyCallSerializer.scala
rename to data/shared/src/main/scala/sigma/serialization/PropertyCallSerializer.scala
index 0c4b15aaf5..10411e21ce 100644
--- a/interpreter/shared/src/main/scala/sigmastate/serialization/PropertyCallSerializer.scala
+++ b/data/shared/src/main/scala/sigma/serialization/PropertyCallSerializer.scala
@@ -1,18 +1,14 @@
-package sigmastate.serialization
+package sigma.serialization
-import sigmastate.Values._
-import sigmastate._
-import sigmastate.lang.Terms
-import sigmastate.lang.Terms.STypeSubst
-import sigmastate.lang.Terms.{MethodCall, PropertyCall}
-import sigmastate.utils.SigmaByteWriter.DataInfo
-import sigmastate.utils.{SigmaByteWriter, SigmaByteReader}
-import sigmastate.utxo.ComplexityTable
+import sigma.ast.{EmptySubst, SType, STypeSubst}
+import sigma.serialization.CoreByteWriter.{ArgInfo, DataInfo}
+import sigma.ast._
+import sigma.ast.syntax.SValue
+import SigmaByteWriter._
case class PropertyCallSerializer(cons: (Value[SType], SMethod, IndexedSeq[Value[SType]], STypeSubst) => Value[SType])
extends ValueSerializer[MethodCall] {
override def opDesc: ValueCompanion = PropertyCall
- override def getComplexity: Int = 0 // because we add it explicitly in parse below
val typeCodeInfo: DataInfo[Byte] = ArgInfo("typeCode", "type of the method (see Table~\\ref{table:predeftypes})")
val methodCodeInfo: DataInfo[Byte] = ArgInfo("methodCode", "a code of the property")
val objInfo: DataInfo[SValue] = ArgInfo("obj", "receiver object of this property call")
@@ -28,9 +24,7 @@ case class PropertyCallSerializer(cons: (Value[SType], SMethod, IndexedSeq[Value
val methodId = r.getByte()
val obj = r.getValue()
val method = SMethod.fromIds(typeId, methodId)
- val complexity = ComplexityTable.MethodCallComplexity.getOrElse((typeId, methodId), ComplexityTable.MinimalComplexity)
- r.addComplexity(complexity)
val specMethod = method.specializeFor(obj.tpe, SType.EmptySeq)
- cons(obj, specMethod, Value.EmptySeq, Terms.EmptySubst)
+ cons(obj, specMethod, Value.EmptySeq, EmptySubst)
}
}
diff --git a/interpreter/shared/src/main/scala/sigmastate/serialization/SelectFieldSerializer.scala b/data/shared/src/main/scala/sigma/serialization/SelectFieldSerializer.scala
similarity index 64%
rename from interpreter/shared/src/main/scala/sigmastate/serialization/SelectFieldSerializer.scala
rename to data/shared/src/main/scala/sigma/serialization/SelectFieldSerializer.scala
index 6abf691f8d..95e692c85a 100644
--- a/interpreter/shared/src/main/scala/sigmastate/serialization/SelectFieldSerializer.scala
+++ b/data/shared/src/main/scala/sigma/serialization/SelectFieldSerializer.scala
@@ -1,13 +1,12 @@
-package sigmastate.serialization
+package sigma.serialization
-import sigmastate.Operations.SelectFieldInfo
-import sigmastate.Values.{Value, SValue}
-import sigmastate.lang.Terms._
-import sigmastate.utils.{SigmaByteReader, SigmaByteWriter}
-import sigmastate.utxo.SelectField
-import sigmastate.{STuple, SType}
+import sigma.ast.Operations.SelectFieldInfo
+import sigma.ast.{SelectField, Value}
+import sigma.ast.syntax._
import SelectFieldInfo._
-import sigmastate.utils.SigmaByteWriter.DataInfo
+import sigma.ast.{STuple, SType}
+import sigma.serialization.CoreByteWriter.DataInfo
+import SigmaByteWriter._
case class SelectFieldSerializer(cons: (Value[STuple], Byte) => Value[SType]) extends ValueSerializer[SelectField] {
override def opDesc = SelectField
diff --git a/data/shared/src/main/scala/sigma/serialization/SigmaByteReader.scala b/data/shared/src/main/scala/sigma/serialization/SigmaByteReader.scala
new file mode 100644
index 0000000000..8cbeeb1cc1
--- /dev/null
+++ b/data/shared/src/main/scala/sigma/serialization/SigmaByteReader.scala
@@ -0,0 +1,65 @@
+package sigma.serialization
+
+import debox.cfor
+import scorex.util.serialization.Reader
+import sigma.ast._
+import sigma.ast.syntax._
+import sigma.util.safeNewArray
+
+/** Reader used in the concrete implementations of [[SigmaSerializer]].
+ * It decorates the given reader, delegates most of the methods to it, but also adds new
+ * methods.
+ *
+ * @param r the underlying reader this reader reads from
+ * @param constantStore the store of constants which is used to resolve
+ * [[sigma.ast.ConstantPlaceholder]]
+ * @param resolvePlaceholdersToConstants if true then resolved constants will be
+ * substituted in the tree instead of the placeholder.
+ * @param maxTreeDepth limit on the tree depth (recursive invocations)
+ * of the deserializer
+ */
+class SigmaByteReader(override val r: Reader,
+ var constantStore: ConstantStore,
+ var resolvePlaceholdersToConstants: Boolean,
+ override val maxTreeDepth: Int = SigmaSerializer.MaxTreeDepth)
+ extends CoreByteReader(r, maxTreeDepth) {
+
+ /** The reader should be lightweight to create. In most cases ErgoTrees don't have
+ * ValDef nodes hence the store is not necessary and it's initialization dominates the
+ * reader instantiation time. Hence it's lazy.
+ * HOTSPOT:
+ */
+ lazy val valDefTypeStore: ValDefTypeStore = new ValDefTypeStore()
+
+ override type CH = r.CH
+
+
+ /** Returns all bytes of the underlying ByteBuffer. */
+ private[sigma] def getAllBufferBytes: Array[Byte] = {
+ val savedPos = position
+ position = 0
+ val res = getBytesUnsafe(remaining)
+ position = savedPos
+ res
+ }
+
+ @inline def getValue(): SValue = ValueSerializer.deserialize(this)
+
+ /** Read sequence of values from this reader.
+ * It first reads the number of values and then reads each value using `getValue` method.
+ *
+ * @return a sequence of zero of more values read
+ */
+ @inline def getValues(): IndexedSeq[SValue] = {
+ val size = getUIntExact
+ if (size == 0) Value.EmptySeq // quick short-cut when there is nothing to read
+ else {
+ val xs = safeNewArray[SValue](size)
+ cfor(0)(_ < size, _ + 1) { i =>
+ xs(i) = getValue()
+ }
+ xs
+ }
+ }
+
+}
diff --git a/data/shared/src/main/scala/sigma/serialization/SigmaByteWriter.scala b/data/shared/src/main/scala/sigma/serialization/SigmaByteWriter.scala
new file mode 100644
index 0000000000..35d5e0c9b9
--- /dev/null
+++ b/data/shared/src/main/scala/sigma/serialization/SigmaByteWriter.scala
@@ -0,0 +1,104 @@
+package sigma.serialization
+
+import scorex.util.serialization.Writer
+import sigma.ast.syntax._
+import sigma.ast._
+import sigma.serialization.CoreByteWriter.{ArgInfo, DataInfo, FormatDescriptor, SeqFmt}
+
+class SigmaByteWriter(override val w: Writer,
+ val constantExtractionStore: Option[ConstantStore])
+ extends CoreByteWriter(w) {
+ import CoreByteWriter._
+ import ValueSerializer._
+
+ override def put(x: Byte, info: DataInfo[Byte]): this.type = {
+ ValueSerializer.addArgInfo(info)
+ w.put(x); this
+ }
+
+ override def putUByte(x: Int, info: DataInfo[U[Byte]]): this.type = {
+ ValueSerializer.addArgInfo(info)
+ super.putUByte(x)
+ }
+
+ @inline override def putBoolean(x: Boolean, info: DataInfo[Boolean]): this.type = {
+ ValueSerializer.addArgInfo(info)
+ w.putBoolean(x); this
+ }
+
+ @inline override def putShort(x: Short, info: DataInfo[Short]): this.type = {
+ ValueSerializer.addArgInfo(info)
+ w.putShort(x); this
+ }
+
+ @inline override def putUShort(x: Int, info: DataInfo[Vlq[U[Short]]]): this.type = {
+ ValueSerializer.addArgInfo(info)
+ w.putUShort(x); this
+ }
+
+ @inline override def putInt(x: Int, info: DataInfo[Int]): this.type = {
+ ValueSerializer.addArgInfo(info)
+ w.putInt(x); this
+ }
+
+ @inline override def putUInt(x: Long, info: DataInfo[Vlq[U[Int]]]): this.type = {
+ ValueSerializer.addArgInfo(info)
+ w.putUInt(x); this
+ }
+
+ @inline override def putLong(x: Long, info: DataInfo[Vlq[ZigZag[Long]]]): this.type = {
+ ValueSerializer.addArgInfo(info)
+ w.putLong(x); this
+ }
+
+ @inline override def putULong(x: Long, info: DataInfo[Vlq[U[Long]]]): this.type = {
+ ValueSerializer.addArgInfo(info)
+ w.putULong(x); this
+ }
+
+ @inline override def putBytes(xs: Array[Byte], info: DataInfo[Array[Byte]]): this.type = {
+ ValueSerializer.addArgInfo(info)
+ w.putBytes(xs); this
+ }
+
+ @inline override def putBits(xs: Array[Boolean], info: DataInfo[Bits]): this.type = {
+ ValueSerializer.addArgInfo(info)
+ w.putBits(xs);
+ this
+ }
+
+ @inline override def putType[T <: SType](x: T, info: DataInfo[SType]): this.type = {
+ ValueSerializer.addArgInfo(info)
+ TypeSerializer.serialize(x, this); this
+ }
+
+ @inline def putValue[T <: SType](x: Value[T]): this.type = { ValueSerializer.serialize(x, this); this }
+ @inline def putValue[T <: SType](x: Value[T], info: DataInfo[SValue]): this.type = {
+ ValueSerializer.addArgInfo(info)
+ ValueSerializer.serialize(x, this); this
+ }
+ @inline def putValues[T <: SType](xs: Seq[Value[T]]): this.type = {
+ putUInt(xs.length)
+ xs.foreach(putValue(_))
+ this
+ }
+ @inline def putValues[T <: SType](xs: Seq[Value[T]], info: DataInfo[Seq[SValue]], itemInfo: DataInfo[SValue]): this.type = {
+ putUInt(xs.length, valuesLengthInfo)
+ foreach("\\#items", xs) { x =>
+ putValue(x, itemInfo)
+ }
+ this
+ }
+}
+
+object SigmaByteWriter {
+ implicit case object ValueFmt extends FormatDescriptor[SValue] {
+ override def size: String = "[1, *]"
+ override def toString: String = "Expr"
+ }
+
+ def valuesItemInfo(info: DataInfo[Seq[SValue]]): DataInfo[SValue] = {
+ val itemFmt = info.format.asInstanceOf[SeqFmt[SValue]].fmt
+ DataInfo(ArgInfo(info.info.name + "_i", s"i-th item in the ${info.info.description}"), itemFmt)
+ }
+}
\ No newline at end of file
diff --git a/data/shared/src/main/scala/sigma/serialization/SigmaPropBytesSerializer.scala b/data/shared/src/main/scala/sigma/serialization/SigmaPropBytesSerializer.scala
new file mode 100644
index 0000000000..fc55e7b5ca
--- /dev/null
+++ b/data/shared/src/main/scala/sigma/serialization/SigmaPropBytesSerializer.scala
@@ -0,0 +1,21 @@
+package sigma.serialization
+
+import sigma.ast.{SType, SigmaPropBytes, Value}
+import sigma.serialization.CoreByteWriter.DataInfo
+import sigma.ast.syntax._
+import SigmaByteWriter._
+
+object SigmaPropBytesSerializer extends ValueSerializer[SigmaPropBytes] {
+ import sigma.ast.Operations.SigmaPropBytesInfo._
+ override def opDesc = SigmaPropBytes
+ val thisInfo: DataInfo[SValue] = thisArg
+
+ def serialize(obj: SigmaPropBytes, w: SigmaByteWriter): Unit = {
+ w.putValue(obj.input, thisInfo)
+ }
+
+ def parse(r: SigmaByteReader): Value[SType] = {
+ val p = r.getValue().asSigmaProp
+ SigmaPropBytes(p)
+ }
+}
diff --git a/interpreter/shared/src/main/scala/sigmastate/serialization/SigmaPropIsProvenSerializer.scala b/data/shared/src/main/scala/sigma/serialization/SigmaPropIsProvenSerializer.scala
similarity index 53%
rename from interpreter/shared/src/main/scala/sigmastate/serialization/SigmaPropIsProvenSerializer.scala
rename to data/shared/src/main/scala/sigma/serialization/SigmaPropIsProvenSerializer.scala
index 0350f582bb..66e7491dfd 100644
--- a/interpreter/shared/src/main/scala/sigmastate/serialization/SigmaPropIsProvenSerializer.scala
+++ b/data/shared/src/main/scala/sigma/serialization/SigmaPropIsProvenSerializer.scala
@@ -1,9 +1,7 @@
-package sigmastate.serialization
+package sigma.serialization
-import sigmastate.{Values, SType}
-import sigmastate.lang.Terms._
-import sigmastate.utils.{SigmaByteReader, SigmaByteWriter}
-import sigmastate.utxo.SigmaPropIsProven
+import sigma.ast.{SType, SigmaPropIsProven, Value}
+import sigma.ast.syntax._
object SigmaPropIsProvenSerializer extends ValueSerializer[SigmaPropIsProven] {
override def opDesc = SigmaPropIsProven
@@ -12,7 +10,7 @@ object SigmaPropIsProvenSerializer extends ValueSerializer[SigmaPropIsProven] {
w.putValue(obj.input)
}
- def parse(r: SigmaByteReader): Values.Value[SType] = {
+ def parse(r: SigmaByteReader): Value[SType] = {
val p = r.getValue().asSigmaProp
SigmaPropIsProven(p)
}
diff --git a/interpreter/shared/src/main/scala/sigmastate/serialization/SigmaSerializer.scala b/data/shared/src/main/scala/sigma/serialization/SigmaSerializer.scala
similarity index 91%
rename from interpreter/shared/src/main/scala/sigmastate/serialization/SigmaSerializer.scala
rename to data/shared/src/main/scala/sigma/serialization/SigmaSerializer.scala
index eea880521a..cdb28d724b 100644
--- a/interpreter/shared/src/main/scala/sigmastate/serialization/SigmaSerializer.scala
+++ b/data/shared/src/main/scala/sigma/serialization/SigmaSerializer.scala
@@ -1,14 +1,11 @@
-package sigmastate.serialization
+package sigma.serialization
import java.nio.ByteBuffer
-
-import org.ergoplatform.SigmaConstants
-import org.ergoplatform.validation.SigmaValidationSettings
import scorex.util.ByteArrayBuilder
-import sigmastate.utils._
import scorex.util.serialization._
-import sigmastate.exceptions.SerializerException
-import sigmastate.serialization.OpCodes.OpCode
+import sigma.data.SigmaConstants
+import sigma.validation.SigmaValidationSettings
+import sigma.serialization.ValueCodes.OpCode
object SigmaSerializer {
type Position = Int
diff --git a/interpreter/shared/src/main/scala/sigmastate/serialization/SubstConstantsSerializer.scala b/data/shared/src/main/scala/sigma/serialization/SubstConstantsSerializer.scala
similarity index 67%
rename from interpreter/shared/src/main/scala/sigmastate/serialization/SubstConstantsSerializer.scala
rename to data/shared/src/main/scala/sigma/serialization/SubstConstantsSerializer.scala
index 2c55458280..f019d35b59 100644
--- a/interpreter/shared/src/main/scala/sigmastate/serialization/SubstConstantsSerializer.scala
+++ b/data/shared/src/main/scala/sigma/serialization/SubstConstantsSerializer.scala
@@ -1,14 +1,14 @@
-package sigmastate.serialization
+package sigma.serialization
-import sigmastate.SCollection.{SIntArray, SByteArray}
-import sigmastate.Values.{Value, SValue}
-import sigmastate.lang.Terms._
-import sigmastate.utils.SigmaByteWriter.DataInfo
-import sigmastate.utils.{SigmaByteReader, SigmaByteWriter}
-import sigmastate.{SCollection, SubstConstants, SType}
+import sigma.ast.SCollection.{SByteArray, SIntArray}
+import sigma.ast.{SubstConstants, Value}
+import sigma.ast.syntax._
+import SigmaByteWriter._
+import sigma.ast.{SCollection, SType}
+import sigma.serialization.CoreByteWriter.DataInfo
object SubstConstantsSerializer extends ValueSerializer[SubstConstants[SType]] {
- import sigmastate.Operations.SubstConstantsInfo._
+ import sigma.ast.Operations.SubstConstantsInfo._
override def opDesc = SubstConstants
val scriptBytesInfo: DataInfo[SValue] = scriptBytesArg
val positionsInfo: DataInfo[SValue] = positionsArg
diff --git a/interpreter/shared/src/main/scala/sigmastate/serialization/TaggedVariableSerializer.scala b/data/shared/src/main/scala/sigma/serialization/TaggedVariableSerializer.scala
similarity index 71%
rename from interpreter/shared/src/main/scala/sigmastate/serialization/TaggedVariableSerializer.scala
rename to data/shared/src/main/scala/sigma/serialization/TaggedVariableSerializer.scala
index bc99becd19..cd6f33eacb 100644
--- a/interpreter/shared/src/main/scala/sigmastate/serialization/TaggedVariableSerializer.scala
+++ b/data/shared/src/main/scala/sigma/serialization/TaggedVariableSerializer.scala
@@ -1,9 +1,9 @@
-package sigmastate.serialization
+package sigma.serialization
-import sigmastate.Values._
-import sigmastate._
-import sigmastate.utils.{SigmaByteReader, SigmaByteWriter}
+import sigma.ast.SType
+import sigma.ast._
+// TODO v6.0: remove this class (https://github.com/ScorexFoundation/sigmastate-interpreter/issues/584)
case class TaggedVariableSerializer(cons: (Byte, SType) => Value[SType])
extends ValueSerializer[TaggedVariable[_ <: SType]] {
override def opDesc = TaggedVariable
diff --git a/interpreter/shared/src/main/scala/sigmastate/serialization/TupleSerializer.scala b/data/shared/src/main/scala/sigma/serialization/TupleSerializer.scala
similarity index 79%
rename from interpreter/shared/src/main/scala/sigmastate/serialization/TupleSerializer.scala
rename to data/shared/src/main/scala/sigma/serialization/TupleSerializer.scala
index a88a17fa5f..89a7ea457c 100644
--- a/interpreter/shared/src/main/scala/sigmastate/serialization/TupleSerializer.scala
+++ b/data/shared/src/main/scala/sigma/serialization/TupleSerializer.scala
@@ -1,12 +1,13 @@
-package sigmastate.serialization
+package sigma.serialization
-import sigmastate.{SType, ArgInfo}
-import sigmastate.Values._
-import sigmastate.utils.{SigmaByteWriter, SigmaByteReader}
-import sigmastate.serialization.ValueSerializer._
+import sigma.ast._
+import sigma.serialization.ValueSerializer._
import sigma.util.safeNewArray
-import sigmastate.utils.SigmaByteWriter.{DataInfo, U}
+import SigmaByteWriter._
import debox.cfor
+import sigma.ast.SType
+import sigma.ast.syntax.{CollectionOps, SValue}
+import sigma.serialization.CoreByteWriter.{ArgInfo, DataInfo, U}
case class TupleSerializer(cons: Seq[Value[SType]] => Value[SType])
extends ValueSerializer[Tuple] {
diff --git a/interpreter/shared/src/main/scala/sigmastate/serialization/TwoArgumentsSerializer.scala b/data/shared/src/main/scala/sigma/serialization/TwoArgumentsSerializer.scala
similarity index 71%
rename from interpreter/shared/src/main/scala/sigmastate/serialization/TwoArgumentsSerializer.scala
rename to data/shared/src/main/scala/sigma/serialization/TwoArgumentsSerializer.scala
index a4bb89fa29..b6f4561ba0 100644
--- a/interpreter/shared/src/main/scala/sigmastate/serialization/TwoArgumentsSerializer.scala
+++ b/data/shared/src/main/scala/sigma/serialization/TwoArgumentsSerializer.scala
@@ -1,10 +1,10 @@
-package sigmastate.serialization
+package sigma.serialization
-import sigmastate.Values.{Value, SValue}
-import sigmastate.lang.Terms._
-import sigmastate.utils.SigmaByteWriter.DataInfo
-import sigmastate.utils.{SigmaByteReader, SigmaByteWriter}
-import sigmastate.{TwoArgumentsOperation, SType, TwoArgumentOperationCompanion}
+import sigma.ast.{SType, TwoArgumentOperationCompanion, TwoArgumentsOperation}
+import sigma.serialization.CoreByteWriter.DataInfo
+import sigma.ast.Value
+import sigma.ast.syntax._
+import SigmaByteWriter._
case class TwoArgumentsSerializer[LIV <: SType, RIV <: SType, OV <: Value[SType]]
(override val opDesc: TwoArgumentOperationCompanion, constructor: (Value[LIV], Value[RIV]) => Value[SType])
diff --git a/interpreter/shared/src/main/scala/sigmastate/serialization/ValDefSerializer.scala b/data/shared/src/main/scala/sigma/serialization/ValDefSerializer.scala
similarity index 88%
rename from interpreter/shared/src/main/scala/sigmastate/serialization/ValDefSerializer.scala
rename to data/shared/src/main/scala/sigma/serialization/ValDefSerializer.scala
index cdac6309f8..b775c14327 100644
--- a/interpreter/shared/src/main/scala/sigmastate/serialization/ValDefSerializer.scala
+++ b/data/shared/src/main/scala/sigma/serialization/ValDefSerializer.scala
@@ -1,13 +1,11 @@
-package sigmastate.serialization
+package sigma.serialization
-import sigmastate.Values._
-import sigmastate._
-import sigmastate.serialization.OpCodes._
+import debox.cfor
import scorex.util.Extensions._
-import sigmastate.utils.{SigmaByteReader, SigmaByteWriter}
-import ValueSerializer._
+import sigma.ast._
import sigma.util.safeNewArray
-import debox.cfor
+import sigma.serialization.OpCodes._
+import sigma.serialization.ValueSerializer._
case class ValDefSerializer(override val opDesc: ValueCompanion) extends ValueSerializer[ValDef] {
diff --git a/interpreter/shared/src/main/scala/sigmastate/serialization/ValDefTypeStore.scala b/data/shared/src/main/scala/sigma/serialization/ValDefTypeStore.scala
similarity index 78%
rename from interpreter/shared/src/main/scala/sigmastate/serialization/ValDefTypeStore.scala
rename to data/shared/src/main/scala/sigma/serialization/ValDefTypeStore.scala
index 62c72317d5..8ae41ebb99 100644
--- a/interpreter/shared/src/main/scala/sigmastate/serialization/ValDefTypeStore.scala
+++ b/data/shared/src/main/scala/sigma/serialization/ValDefTypeStore.scala
@@ -1,6 +1,6 @@
-package sigmastate.serialization
+package sigma.serialization
-import sigmastate.SType
+import sigma.ast.SType
import scala.collection.mutable
diff --git a/interpreter/shared/src/main/scala/sigmastate/serialization/ValUseSerializer.scala b/data/shared/src/main/scala/sigma/serialization/ValUseSerializer.scala
similarity index 84%
rename from interpreter/shared/src/main/scala/sigmastate/serialization/ValUseSerializer.scala
rename to data/shared/src/main/scala/sigma/serialization/ValUseSerializer.scala
index 523139c3ab..49aae39843 100644
--- a/interpreter/shared/src/main/scala/sigmastate/serialization/ValUseSerializer.scala
+++ b/data/shared/src/main/scala/sigma/serialization/ValUseSerializer.scala
@@ -1,8 +1,6 @@
-package sigmastate.serialization
+package sigma.serialization
-import sigmastate.Values._
-import sigmastate._
-import sigmastate.utils.{SigmaByteReader, SigmaByteWriter}
+import sigma.ast._
case class ValUseSerializer(cons: (Int, SType) => Value[SType]) extends ValueSerializer[ValUse[SType]] {
override def opDesc = ValUse
diff --git a/interpreter/shared/src/main/scala/sigmastate/serialization/ValueSerializer.scala b/data/shared/src/main/scala/sigma/serialization/ValueSerializer.scala
similarity index 94%
rename from interpreter/shared/src/main/scala/sigmastate/serialization/ValueSerializer.scala
rename to data/shared/src/main/scala/sigma/serialization/ValueSerializer.scala
index 056da7587b..3eb6c75713 100644
--- a/interpreter/shared/src/main/scala/sigmastate/serialization/ValueSerializer.scala
+++ b/data/shared/src/main/scala/sigma/serialization/ValueSerializer.scala
@@ -1,30 +1,19 @@
-package sigmastate.serialization
+package sigma.serialization
import org.ergoplatform.validation.ValidationRules.CheckValidOpCode
-import org.ergoplatform._
+import sigma.ast.SCollection.SByteArray
+import sigma.ast.TypeCodes.LastConstantCode
+import sigma.ast._
+import sigma.serialization.CoreByteWriter.DataInfo
import sigma.util.Extensions.toUByte
-import sigmastate.SCollection.SByteArray
-import sigmastate.Values._
-import sigmastate._
-import sigmastate.lang.DeserializationSigmaBuilder
-import sigmastate.serialization.OpCodes._
-import sigmastate.serialization.transformers._
-import sigmastate.serialization.trees.{QuadrupleSerializer, Relation2Serializer}
-import sigmastate.utils.SigmaByteWriter.DataInfo
-import sigmastate.utils._
-import sigmastate.utxo.ComplexityTable._
-import sigmastate.utxo._
-
-import scala.collection.compat.immutable.ArraySeq
+import sigma.serialization.ValueCodes.OpCode
+import sigma.serialization.transformers._
+import sigma.serialization.trees.{QuadrupleSerializer, Relation2Serializer}
+import sigma.utils.SparseArrayContainer
+
import scala.collection.mutable
-import scala.collection.mutable.{HashMap, Map}
abstract class ValueSerializer[V <: Value[SType]] extends SigmaSerializer[Value[SType], V] {
- import scala.language.implicitConversions
- private val companion = ValueSerializer
-
- def getComplexity: Int = OpCodeComplexity.getOrElse(opCode, MinimalComplexity)
- lazy val complexity: Int = getComplexity
def opDesc: ValueCompanion
/** Code of the corresponding tree node (Value.opCode) which is used to lookup this serizalizer
@@ -101,7 +90,7 @@ object ValueSerializer extends SigmaSerializerCompanion[Value[SType]] {
LogicalTransformerSerializer(AND, mkAND),
LogicalTransformerSerializer(OR, mkOR),
LogicalTransformerSerializer(XorOf, mkXorOf),
- TaggedVariableSerializer(mkTaggedVariable),
+ TaggedVariableSerializer(mkTaggedVariable), // TODO v6.0: remove this serializer https://github.com/ScorexFoundation/sigmastate-interpreter/issues/584
GetVarSerializer(mkGetVar),
MapCollectionSerializer(mkMapCollection),
BooleanTransformerSerializer[SType](Exists, mkExists),
@@ -256,7 +245,7 @@ object ValueSerializer extends SigmaSerializerCompanion[Value[SType]] {
def printSerInfo(): String = {
serializerInfo.map { case (_, s) =>
- val ser = getSerializer(s.opCode)
+ getSerializer(s.opCode) // sanity check to make sure only resolvable serializers got printed
s.toString
}.mkString("\n")
}
@@ -398,13 +387,11 @@ object ValueSerializer extends SigmaSerializerCompanion[Value[SType]] {
val firstByte = toUByte(r.peekByte())
val v = if (firstByte <= LastConstantCode) {
// look ahead byte tell us this is going to be a Constant
- r.addComplexity(constantSerializer.complexity)
constantSerializer.deserialize(r)
}
else {
val opCode = r.getByte().asInstanceOf[OpCode]
val ser = getSerializer(opCode)
- r.addComplexity(ser.complexity)
ser.parse(r)
}
r.level = r.level - 1
diff --git a/interpreter/shared/src/main/scala/sigmastate/serialization/transformers/AppendSerializer.scala b/data/shared/src/main/scala/sigma/serialization/transformers/AppendSerializer.scala
similarity index 63%
rename from interpreter/shared/src/main/scala/sigmastate/serialization/transformers/AppendSerializer.scala
rename to data/shared/src/main/scala/sigma/serialization/transformers/AppendSerializer.scala
index 970c1b66d0..c5995cfe7d 100644
--- a/interpreter/shared/src/main/scala/sigmastate/serialization/transformers/AppendSerializer.scala
+++ b/data/shared/src/main/scala/sigma/serialization/transformers/AppendSerializer.scala
@@ -1,12 +1,11 @@
-package sigmastate.serialization.transformers
+package sigma.serialization.transformers
-import sigmastate.Operations.AppendInfo
-import sigmastate.Values.Value
-import sigmastate.lang.Terms._
-import sigmastate.serialization.ValueSerializer
-import sigmastate.utils.{SigmaByteReader, SigmaByteWriter}
-import sigmastate.utxo.Append
-import sigmastate.{SCollection, SType}
+import sigma.ast.Operations.AppendInfo
+import sigma.ast.{Append, Value}
+import sigma.ast.syntax._
+import sigma.serialization.{SigmaByteReader, SigmaByteWriter, ValueSerializer}
+import sigma.serialization.SigmaByteWriter._
+import sigma.ast.{SCollection, SType}
case class AppendSerializer(cons: (Value[SCollection[SType]], Value[SCollection[SType]]) => Value[SCollection[SType]])
extends ValueSerializer[Append[SType]] {
diff --git a/interpreter/shared/src/main/scala/sigmastate/serialization/transformers/AtLeastSerializer.scala b/data/shared/src/main/scala/sigma/serialization/transformers/AtLeastSerializer.scala
similarity index 61%
rename from interpreter/shared/src/main/scala/sigmastate/serialization/transformers/AtLeastSerializer.scala
rename to data/shared/src/main/scala/sigma/serialization/transformers/AtLeastSerializer.scala
index a401921fed..876f83f2d1 100644
--- a/interpreter/shared/src/main/scala/sigmastate/serialization/transformers/AtLeastSerializer.scala
+++ b/data/shared/src/main/scala/sigma/serialization/transformers/AtLeastSerializer.scala
@@ -1,11 +1,11 @@
-package sigmastate.serialization.transformers
+package sigma.serialization.transformers
-import sigmastate.Operations.AtLeastInfo
-import sigmastate.Values.{Value, SigmaPropValue}
-import sigmastate.lang.Terms._
-import sigmastate._
-import sigmastate.serialization.ValueSerializer
-import sigmastate.utils.{SigmaByteReader, SigmaByteWriter}
+import sigma.ast.syntax.SigmaPropValue
+import sigma.ast.{AtLeast, SCollection, SInt, SSigmaProp, Value}
+import sigma.ast.Operations.AtLeastInfo
+import sigma.ast.syntax._
+import sigma.serialization.{SigmaByteReader, SigmaByteWriter, ValueSerializer}
+import sigma.serialization.SigmaByteWriter._
case class AtLeastSerializer(cons: (Value[SInt.type], Value[SCollection[SSigmaProp.type]]) => SigmaPropValue)
extends ValueSerializer[AtLeast] {
diff --git a/interpreter/shared/src/main/scala/sigmastate/serialization/transformers/BooleanTransformerSerializer.scala b/data/shared/src/main/scala/sigma/serialization/transformers/BooleanTransformerSerializer.scala
similarity index 62%
rename from interpreter/shared/src/main/scala/sigmastate/serialization/transformers/BooleanTransformerSerializer.scala
rename to data/shared/src/main/scala/sigma/serialization/transformers/BooleanTransformerSerializer.scala
index 8c5975cf8a..be3b91dcca 100644
--- a/interpreter/shared/src/main/scala/sigmastate/serialization/transformers/BooleanTransformerSerializer.scala
+++ b/data/shared/src/main/scala/sigma/serialization/transformers/BooleanTransformerSerializer.scala
@@ -1,12 +1,12 @@
-package sigmastate.serialization.transformers
+package sigma.serialization.transformers
-import sigmastate.Values.{Value, SValue}
-import sigmastate.lang.Terms._
-import sigmastate.serialization.ValueSerializer
-import sigmastate.utils.SigmaByteWriter.DataInfo
-import sigmastate.utils.{SigmaByteReader, SigmaByteWriter}
-import sigmastate.utxo.{BooleanTransformer, BooleanTransformerCompanion}
-import sigmastate.{SCollection, SBoolean, SType, SFunc}
+import sigma.ast.syntax.SValue
+import sigma.ast.{BooleanTransformer, BooleanTransformerCompanion, Value}
+import sigma.ast.syntax._
+import sigma.serialization.{SigmaByteReader, SigmaByteWriter, ValueSerializer}
+import sigma.serialization.SigmaByteWriter._
+import sigma.ast.{SBoolean, SCollection, SFunc, SType}
+import sigma.serialization.CoreByteWriter.DataInfo
case class BooleanTransformerSerializer[T <: SType]
(opDesc: BooleanTransformerCompanion,
diff --git a/interpreter/shared/src/main/scala/sigmastate/serialization/transformers/ByIndexSerializer.scala b/data/shared/src/main/scala/sigma/serialization/transformers/ByIndexSerializer.scala
similarity index 67%
rename from interpreter/shared/src/main/scala/sigmastate/serialization/transformers/ByIndexSerializer.scala
rename to data/shared/src/main/scala/sigma/serialization/transformers/ByIndexSerializer.scala
index 15ea23db30..e0c43d1cc5 100644
--- a/interpreter/shared/src/main/scala/sigmastate/serialization/transformers/ByIndexSerializer.scala
+++ b/data/shared/src/main/scala/sigma/serialization/transformers/ByIndexSerializer.scala
@@ -1,14 +1,14 @@
-package sigmastate.serialization.transformers
+package sigma.serialization.transformers
-import sigmastate.Values.{Value, SValue}
-import sigmastate.lang.Terms._
-import sigmastate.serialization.ValueSerializer
+import sigma.ast.{ByIndex, Value}
+import sigma.ast.syntax._
+import sigma.serialization.{SigmaByteReader, SigmaByteWriter, ValueSerializer}
import ValueSerializer._
-import sigmastate.Operations.ByIndexInfo._
-import sigmastate.utils.SigmaByteWriter.DataInfo
-import sigmastate.utils.{SigmaByteReader, SigmaByteWriter}
-import sigmastate.utxo.ByIndex
-import sigmastate.{SInt, SCollection, SType}
+import sigma.ast.syntax.SValue
+import sigma.ast.Operations.ByIndexInfo._
+import sigma.serialization.SigmaByteWriter._
+import sigma.ast.{SCollection, SInt, SType}
+import sigma.serialization.CoreByteWriter.DataInfo
case class ByIndexSerializer(cons: (Value[SCollection[SType]], Value[SInt.type], Option[Value[SType]]) => Value[SType])
extends ValueSerializer[ByIndex[SType]] {
diff --git a/data/shared/src/main/scala/sigma/serialization/transformers/CreateProveDHTupleSerializer.scala b/data/shared/src/main/scala/sigma/serialization/transformers/CreateProveDHTupleSerializer.scala
new file mode 100644
index 0000000000..5a16d35365
--- /dev/null
+++ b/data/shared/src/main/scala/sigma/serialization/transformers/CreateProveDHTupleSerializer.scala
@@ -0,0 +1,32 @@
+package sigma.serialization.transformers
+
+import sigma.ast.{CreateProveDHTuple, SGroupElement}
+import sigma.ast.syntax.SigmaPropValue
+import sigma.ast.Value
+import sigma.ast.syntax._
+import sigma.serialization._
+import SigmaByteWriter._
+
+case class CreateProveDHTupleSerializer(cons: (Value[SGroupElement.type],
+ Value[SGroupElement.type],
+ Value[SGroupElement.type],
+ Value[SGroupElement.type]) => SigmaPropValue)
+ extends ValueSerializer[CreateProveDHTuple] {
+ import sigma.ast.Operations.CreateProveDHTupleInfo._
+ override def opDesc = CreateProveDHTuple
+
+ override def serialize(obj: CreateProveDHTuple, w: SigmaByteWriter): Unit = {
+ w.putValue(obj.gv, gArg)
+ w.putValue(obj.hv, hArg)
+ w.putValue(obj.uv, uArg)
+ w.putValue(obj.vv, vArg)
+ }
+
+ override def parse(r: SigmaByteReader) = {
+ val gv = r.getValue().asValue[SGroupElement.type]
+ val hv = r.getValue().asValue[SGroupElement.type]
+ val uv = r.getValue().asValue[SGroupElement.type]
+ val vv = r.getValue().asValue[SGroupElement.type]
+ cons(gv, hv, uv, vv)
+ }
+}
diff --git a/interpreter/shared/src/main/scala/sigmastate/serialization/transformers/DeserializeContextSerializer.scala b/data/shared/src/main/scala/sigma/serialization/transformers/DeserializeContextSerializer.scala
similarity index 66%
rename from interpreter/shared/src/main/scala/sigmastate/serialization/transformers/DeserializeContextSerializer.scala
rename to data/shared/src/main/scala/sigma/serialization/transformers/DeserializeContextSerializer.scala
index f2fe92434d..9058617601 100644
--- a/interpreter/shared/src/main/scala/sigmastate/serialization/transformers/DeserializeContextSerializer.scala
+++ b/data/shared/src/main/scala/sigma/serialization/transformers/DeserializeContextSerializer.scala
@@ -1,12 +1,10 @@
-package sigmastate.serialization.transformers
+package sigma.serialization.transformers
-import sigmastate.{SType, ArgInfo}
-import sigmastate.Values._
-import sigmastate.serialization.ValueSerializer
-import sigmastate.utils.{SigmaByteReader, SigmaByteWriter}
-import sigmastate.utxo.DeserializeContext
-import SigmaByteWriter._
-import sigmastate.Operations.DeserializeContextInfo
+import sigma.ast._
+import sigma.serialization.{SigmaByteReader, SigmaByteWriter, ValueSerializer}
+import sigma.ast.SType
+import sigma.serialization.CoreByteWriter.{ArgInfo, DataInfo}
+import Operations.DeserializeContextInfo
case class DeserializeContextSerializer(cons: (Byte, SType) => Value[SType])
extends ValueSerializer[DeserializeContext[SType]] {
diff --git a/interpreter/shared/src/main/scala/sigmastate/serialization/transformers/DeserializeRegisterSerializer.scala b/data/shared/src/main/scala/sigma/serialization/transformers/DeserializeRegisterSerializer.scala
similarity index 72%
rename from interpreter/shared/src/main/scala/sigmastate/serialization/transformers/DeserializeRegisterSerializer.scala
rename to data/shared/src/main/scala/sigma/serialization/transformers/DeserializeRegisterSerializer.scala
index 47c1ead8e4..05d5f7b4db 100644
--- a/interpreter/shared/src/main/scala/sigmastate/serialization/transformers/DeserializeRegisterSerializer.scala
+++ b/data/shared/src/main/scala/sigma/serialization/transformers/DeserializeRegisterSerializer.scala
@@ -1,15 +1,15 @@
-package sigmastate.serialization.transformers
+package sigma.serialization.transformers
import org.ergoplatform.ErgoBox
import org.ergoplatform.ErgoBox.RegisterId
-import sigmastate.{ArgInfo, SType}
-import sigmastate.Values.{Value, SValue}
-import sigmastate.serialization.ValueSerializer
+import sigma.ast.{DeserializeRegister, Value}
+import sigma.serialization.{SigmaByteReader, SigmaByteWriter, ValueSerializer}
import ValueSerializer._
-import sigmastate.Operations.DeserializeRegisterInfo._
-import sigmastate.utils.SigmaByteWriter.DataInfo
-import sigmastate.utils.{SigmaByteReader, SigmaByteWriter}
-import sigmastate.utxo.DeserializeRegister
+import sigma.ast.SType
+import sigma.ast.syntax.SValue
+import sigma.serialization.CoreByteWriter.{ArgInfo, DataInfo}
+import sigma.ast.Operations.DeserializeRegisterInfo._
+import sigma.serialization.SigmaByteWriter._
case class DeserializeRegisterSerializer(cons: (RegisterId, SType, Option[Value[SType]]) => Value[SType])
extends ValueSerializer[DeserializeRegister[SType]] {
diff --git a/interpreter/shared/src/main/scala/sigmastate/serialization/transformers/ExtractRegisterAsSerializer.scala b/data/shared/src/main/scala/sigma/serialization/transformers/ExtractRegisterAsSerializer.scala
similarity index 70%
rename from interpreter/shared/src/main/scala/sigmastate/serialization/transformers/ExtractRegisterAsSerializer.scala
rename to data/shared/src/main/scala/sigma/serialization/transformers/ExtractRegisterAsSerializer.scala
index f84933b332..e2b09e2a84 100644
--- a/interpreter/shared/src/main/scala/sigmastate/serialization/transformers/ExtractRegisterAsSerializer.scala
+++ b/data/shared/src/main/scala/sigma/serialization/transformers/ExtractRegisterAsSerializer.scala
@@ -1,17 +1,17 @@
-package sigmastate.serialization.transformers
+package sigma.serialization.transformers
import org.ergoplatform.ErgoBox
import org.ergoplatform.ErgoBox.RegisterId
-import sigmastate.Values.{Value, SValue}
-import sigmastate.serialization.ValueSerializer
-import sigmastate.utils.SigmaByteWriter.DataInfo
-import sigmastate.utils.{SigmaByteReader, SigmaByteWriter}
-import sigmastate.utxo.ExtractRegisterAs
-import sigmastate.{SBox, SOption, ArgInfo, SType}
+import sigma.ast.syntax.SValue
+import sigma.ast.{ExtractRegisterAs, Value}
+import sigma.serialization.{SigmaByteReader, SigmaByteWriter, ValueSerializer}
+import sigma.serialization.SigmaByteWriter._
+import sigma.ast.{SBox, SOption, SType}
+import sigma.serialization.CoreByteWriter.{ArgInfo, DataInfo}
case class ExtractRegisterAsSerializer(cons: (Value[SBox.type], RegisterId, SOption[SType]) => Value[SType])
extends ValueSerializer[ExtractRegisterAs[SType]] {
- import sigmastate.Operations.ExtractRegisterAsInfo._
+ import sigma.ast.Operations.ExtractRegisterAsInfo._
override def opDesc = ExtractRegisterAs
val thisInfo: DataInfo[SValue] = thisArg
val regIdInfo: DataInfo[Byte] = regIdArg
diff --git a/interpreter/shared/src/main/scala/sigmastate/serialization/transformers/FilterSerializer.scala b/data/shared/src/main/scala/sigma/serialization/transformers/FilterSerializer.scala
similarity index 63%
rename from interpreter/shared/src/main/scala/sigmastate/serialization/transformers/FilterSerializer.scala
rename to data/shared/src/main/scala/sigma/serialization/transformers/FilterSerializer.scala
index 1c16a9d932..ba8c82a56e 100644
--- a/interpreter/shared/src/main/scala/sigmastate/serialization/transformers/FilterSerializer.scala
+++ b/data/shared/src/main/scala/sigma/serialization/transformers/FilterSerializer.scala
@@ -1,11 +1,9 @@
-package sigmastate.serialization.transformers
+package sigma.serialization.transformers
-import sigmastate.Values.Value
-import sigmastate.lang.Terms._
-import sigmastate.serialization.ValueSerializer
-import sigmastate.utils.{SigmaByteReader, SigmaByteWriter}
-import sigmastate.utxo.Filter
-import sigmastate.{SCollection, SType, SFunc}
+import sigma.ast.{Filter, Value}
+import sigma.ast.syntax._
+import sigma.serialization.{SigmaByteReader, SigmaByteWriter, ValueSerializer}
+import sigma.ast.{SCollection, SType, SFunc}
case class FilterSerializer(cons: (Value[SCollection[SType]], Value[SFunc]) => Value[SCollection[SType]]) extends ValueSerializer[Filter[SType]] {
override def opDesc = Filter
diff --git a/interpreter/shared/src/main/scala/sigmastate/serialization/transformers/FoldSerializer.scala b/data/shared/src/main/scala/sigma/serialization/transformers/FoldSerializer.scala
similarity index 64%
rename from interpreter/shared/src/main/scala/sigmastate/serialization/transformers/FoldSerializer.scala
rename to data/shared/src/main/scala/sigma/serialization/transformers/FoldSerializer.scala
index 0159e10a0a..a1f59f04d3 100644
--- a/interpreter/shared/src/main/scala/sigmastate/serialization/transformers/FoldSerializer.scala
+++ b/data/shared/src/main/scala/sigma/serialization/transformers/FoldSerializer.scala
@@ -1,17 +1,17 @@
-package sigmastate.serialization.transformers
+package sigma.serialization.transformers
-import sigmastate.Values.{Value, SValue}
-import sigmastate.lang.Terms._
-import sigmastate.serialization.ValueSerializer
-import sigmastate.utils.SigmaByteWriter.DataInfo
-import sigmastate.utils.{SigmaByteReader, SigmaByteWriter}
-import sigmastate.utxo.Fold
-import sigmastate.{SCollection, SType, SFunc}
+import sigma.ast.syntax.SValue
+import sigma.ast.{Fold, Value}
+import sigma.ast.syntax._
+import sigma.serialization.{SigmaByteReader, SigmaByteWriter, ValueSerializer}
+import sigma.serialization.SigmaByteWriter._
+import sigma.ast.{SCollection, SFunc, SType}
+import sigma.serialization.CoreByteWriter.DataInfo
case class FoldSerializer(cons: (Value[SCollection[SType]], Value[SType], Value[SFunc]) => Value[SType])
extends ValueSerializer[Fold[SType, SType]] {
override def opDesc = Fold
- import sigmastate.Operations.FoldInfo._
+ import sigma.ast.Operations.FoldInfo._
val thisInfo: DataInfo[SValue] = thisArg
val zeroInfo: DataInfo[SValue] = zeroArg
val opInfo: DataInfo[SValue] = opArg
diff --git a/interpreter/shared/src/main/scala/sigmastate/serialization/transformers/LogicalTransformerSerializer.scala b/data/shared/src/main/scala/sigma/serialization/transformers/LogicalTransformerSerializer.scala
similarity index 58%
rename from interpreter/shared/src/main/scala/sigmastate/serialization/transformers/LogicalTransformerSerializer.scala
rename to data/shared/src/main/scala/sigma/serialization/transformers/LogicalTransformerSerializer.scala
index 18b251f483..29c323341d 100644
--- a/interpreter/shared/src/main/scala/sigmastate/serialization/transformers/LogicalTransformerSerializer.scala
+++ b/data/shared/src/main/scala/sigma/serialization/transformers/LogicalTransformerSerializer.scala
@@ -1,12 +1,12 @@
-package sigmastate.serialization.transformers
+package sigma.serialization.transformers
-import sigmastate.Values.{Value, SValue}
-import sigmastate.lang.Terms._
-import sigmastate.serialization.ValueSerializer
-import sigmastate.utils.SigmaByteWriter.DataInfo
-import sigmastate.utils.{SigmaByteReader, SigmaByteWriter}
-import sigmastate.utxo.Transformer
-import sigmastate.{SCollection, SBoolean, LogicalTransformerCompanion}
+import sigma.ast.syntax.SValue
+import sigma.ast.{LogicalTransformerCompanion, SBoolean, SCollection, Transformer}
+import sigma.serialization.CoreByteWriter.DataInfo
+import sigma.ast.Value
+import sigma.ast.syntax._
+import sigma.serialization.{SigmaByteReader, SigmaByteWriter, ValueSerializer}
+import sigma.serialization.SigmaByteWriter._
case class LogicalTransformerSerializer[I <: SCollection[SBoolean.type], O <: SBoolean.type]
(opDesc: LogicalTransformerCompanion,
diff --git a/interpreter/shared/src/main/scala/sigmastate/serialization/transformers/MapCollectionSerializer.scala b/data/shared/src/main/scala/sigma/serialization/transformers/MapCollectionSerializer.scala
similarity index 60%
rename from interpreter/shared/src/main/scala/sigmastate/serialization/transformers/MapCollectionSerializer.scala
rename to data/shared/src/main/scala/sigma/serialization/transformers/MapCollectionSerializer.scala
index 3e6fab5949..de289b6f64 100644
--- a/interpreter/shared/src/main/scala/sigmastate/serialization/transformers/MapCollectionSerializer.scala
+++ b/data/shared/src/main/scala/sigma/serialization/transformers/MapCollectionSerializer.scala
@@ -1,16 +1,16 @@
-package sigmastate.serialization.transformers
+package sigma.serialization.transformers
-import sigmastate.Values.{Value, SValue}
-import sigmastate.lang.Terms._
-import sigmastate.serialization.ValueSerializer
-import sigmastate.utils.SigmaByteWriter.DataInfo
-import sigmastate.utils.{SigmaByteReader, SigmaByteWriter}
-import sigmastate.utxo.MapCollection
-import sigmastate.{SCollection, SType, SFunc}
+import sigma.ast.syntax.SValue
+import sigma.ast.{MapCollection, Value}
+import sigma.ast.syntax._
+import sigma.serialization.{SigmaByteReader, SigmaByteWriter, ValueSerializer}
+import sigma.serialization.SigmaByteWriter._
+import sigma.ast.{SCollection, SFunc, SType}
+import sigma.serialization.CoreByteWriter.DataInfo
case class MapCollectionSerializer(cons: (Value[SCollection[SType]], Value[SFunc]) => Value[SType])
extends ValueSerializer[MapCollection[SType, SType]] {
- import sigmastate.Operations.MapCollectionInfo._
+ import sigma.ast.Operations.MapCollectionInfo._
override def opDesc = MapCollection
val thisInfo: DataInfo[SValue] = thisArg
val fInfo: DataInfo[SValue] = fArg
diff --git a/interpreter/shared/src/main/scala/sigmastate/serialization/transformers/NumericCastSerializer.scala b/data/shared/src/main/scala/sigma/serialization/transformers/NumericCastSerializer.scala
similarity index 66%
rename from interpreter/shared/src/main/scala/sigmastate/serialization/transformers/NumericCastSerializer.scala
rename to data/shared/src/main/scala/sigma/serialization/transformers/NumericCastSerializer.scala
index 88d521ae09..34730c1a39 100644
--- a/interpreter/shared/src/main/scala/sigmastate/serialization/transformers/NumericCastSerializer.scala
+++ b/data/shared/src/main/scala/sigma/serialization/transformers/NumericCastSerializer.scala
@@ -1,12 +1,11 @@
-package sigmastate.serialization.transformers
+package sigma.serialization.transformers
-import sigmastate.Values.{Value, SValue}
-import sigmastate._
-import sigmastate.lang.Terms._
-import sigmastate.serialization.ValueSerializer
-import sigmastate.utils.SigmaByteWriter.DataInfo
-import sigmastate.utils.{SigmaByteReader, SigmaByteWriter}
-import sigmastate.utxo.Transformer
+import sigma.ast.syntax.SValue
+import sigma.ast.{NumericCastCompanion, SNumericType, SType, Transformer, Value}
+import sigma.serialization.CoreByteWriter.{ArgInfo, DataInfo}
+import sigma.ast.syntax._
+import sigma.serialization.{SigmaByteReader, SigmaByteWriter, ValueSerializer}
+import sigma.serialization.SigmaByteWriter._
case class NumericCastSerializer(opDesc: NumericCastCompanion,
cons: (Value[SNumericType], SNumericType) => Value[SNumericType])
diff --git a/interpreter/shared/src/main/scala/sigmastate/serialization/transformers/SigmaTransformerSerializer.scala b/data/shared/src/main/scala/sigma/serialization/transformers/SigmaTransformerSerializer.scala
similarity index 75%
rename from interpreter/shared/src/main/scala/sigmastate/serialization/transformers/SigmaTransformerSerializer.scala
rename to data/shared/src/main/scala/sigma/serialization/transformers/SigmaTransformerSerializer.scala
index e7981bb725..afcbec4a4a 100644
--- a/interpreter/shared/src/main/scala/sigmastate/serialization/transformers/SigmaTransformerSerializer.scala
+++ b/data/shared/src/main/scala/sigma/serialization/transformers/SigmaTransformerSerializer.scala
@@ -1,12 +1,12 @@
-package sigmastate.serialization.transformers
+package sigma.serialization.transformers
-import sigmastate.{SigmaTransformerCompanion, SigmaTransformer}
-import sigmastate.Values.{SigmaPropValue, SValue}
-import sigmastate.serialization.ValueSerializer
+import sigma.ast.syntax.{SValue, SigmaPropValue}
+import sigma.serialization.{SigmaByteReader, SigmaByteWriter, ValueSerializer}
import sigma.util.safeNewArray
-import sigmastate.utils.SigmaByteWriter.{DataInfo, valuesItemInfo}
-import sigmastate.utils.{SigmaByteReader, SigmaByteWriter}
+import sigma.serialization.SigmaByteWriter._
import debox.cfor
+import sigma.ast.{SigmaTransformer, SigmaTransformerCompanion}
+import sigma.serialization.CoreByteWriter.DataInfo
case class SigmaTransformerSerializer[I <: SigmaPropValue, O <: SigmaPropValue]
(opDesc: SigmaTransformerCompanion, cons: Seq[SigmaPropValue] => SigmaPropValue)
diff --git a/interpreter/shared/src/main/scala/sigmastate/serialization/transformers/SimpleTransformerSerializer.scala b/data/shared/src/main/scala/sigma/serialization/transformers/SimpleTransformerSerializer.scala
similarity index 54%
rename from interpreter/shared/src/main/scala/sigmastate/serialization/transformers/SimpleTransformerSerializer.scala
rename to data/shared/src/main/scala/sigma/serialization/transformers/SimpleTransformerSerializer.scala
index f01ae8fd20..38fb571a41 100644
--- a/interpreter/shared/src/main/scala/sigmastate/serialization/transformers/SimpleTransformerSerializer.scala
+++ b/data/shared/src/main/scala/sigma/serialization/transformers/SimpleTransformerSerializer.scala
@@ -1,12 +1,11 @@
-package sigmastate.serialization.transformers
+package sigma.serialization.transformers
-import sigmastate.SType
-import sigmastate.Values.{Value, SValue}
-import sigmastate.lang.Terms._
-import sigmastate.serialization.ValueSerializer
-import sigmastate.utils.SigmaByteWriter.DataInfo
-import sigmastate.utils.{SigmaByteReader, SigmaByteWriter}
-import sigmastate.utxo.{Transformer, SimpleTransformerCompanion}
+import sigma.ast.{SType, SimpleTransformerCompanion, Transformer}
+import sigma.serialization.CoreByteWriter.DataInfo
+import sigma.ast.Value
+import sigma.ast.syntax._
+import sigma.serialization.{SigmaByteReader, SigmaByteWriter, ValueSerializer}
+import sigma.serialization.SigmaByteWriter._
case class SimpleTransformerSerializer[I <: SType, O <: SType]
(opDesc: SimpleTransformerCompanion,
diff --git a/interpreter/shared/src/main/scala/sigmastate/serialization/transformers/SliceSerializer.scala b/data/shared/src/main/scala/sigma/serialization/transformers/SliceSerializer.scala
similarity index 66%
rename from interpreter/shared/src/main/scala/sigmastate/serialization/transformers/SliceSerializer.scala
rename to data/shared/src/main/scala/sigma/serialization/transformers/SliceSerializer.scala
index ed4f2a15b7..3b159788ba 100644
--- a/interpreter/shared/src/main/scala/sigmastate/serialization/transformers/SliceSerializer.scala
+++ b/data/shared/src/main/scala/sigma/serialization/transformers/SliceSerializer.scala
@@ -1,16 +1,15 @@
-package sigmastate.serialization.transformers
+package sigma.serialization.transformers
-import sigmastate.Values.{Value, SValue}
-import sigmastate.lang.Terms._
-import sigmastate.serialization.ValueSerializer
-import sigmastate.utils.SigmaByteWriter.DataInfo
-import sigmastate.utils.{SigmaByteReader, SigmaByteWriter}
-import sigmastate.utxo.Slice
-import sigmastate.{SInt, SCollection, SType}
+import sigma.ast.{Slice, Value}
+import sigma.ast.syntax._
+import sigma.serialization.{SigmaByteReader, SigmaByteWriter, ValueSerializer}
+import sigma.serialization.SigmaByteWriter._
+import sigma.ast.{SCollection, SInt, SType}
+import sigma.serialization.CoreByteWriter.DataInfo
case class SliceSerializer(cons: (Value[SCollection[SType]], Value[SInt.type], Value[SInt.type]) => Value[SCollection[SType]])
extends ValueSerializer[Slice[SType]] {
- import sigmastate.Operations.SliceInfo._
+ import sigma.ast.Operations.SliceInfo._
override def opDesc = Slice
val thisInfo: DataInfo[SValue] = thisArg
val fromInfo: DataInfo[SValue] = fromArg
diff --git a/interpreter/shared/src/main/scala/sigmastate/serialization/trees/QuadrupleSerializer.scala b/data/shared/src/main/scala/sigma/serialization/trees/QuadrupleSerializer.scala
similarity index 74%
rename from interpreter/shared/src/main/scala/sigmastate/serialization/trees/QuadrupleSerializer.scala
rename to data/shared/src/main/scala/sigma/serialization/trees/QuadrupleSerializer.scala
index f6d3f91ff1..d3bdf580a0 100644
--- a/interpreter/shared/src/main/scala/sigmastate/serialization/trees/QuadrupleSerializer.scala
+++ b/data/shared/src/main/scala/sigma/serialization/trees/QuadrupleSerializer.scala
@@ -1,11 +1,10 @@
-package sigmastate.serialization.trees
+package sigma.serialization.trees
-import sigmastate.Values._
-import sigmastate.lang.Terms._
-import sigmastate.serialization.ValueSerializer
-import sigmastate.utils.SigmaByteWriter.DataInfo
-import sigmastate.utils.{SigmaByteReader, SigmaByteWriter}
-import sigmastate.{Quadruple, _}
+import sigma.serialization.CoreByteWriter.DataInfo
+import sigma.ast._
+import sigma.ast.syntax._
+import sigma.serialization.{SigmaByteReader, SigmaByteWriter, ValueSerializer}
+import sigma.serialization.SigmaByteWriter._
case class QuadrupleSerializer[S1 <: SType, S2 <: SType, S3 <: SType, S4 <: SType]
(override val opDesc: QuadrupleCompanion,
diff --git a/interpreter/shared/src/main/scala/sigmastate/serialization/trees/Relation2Serializer.scala b/data/shared/src/main/scala/sigma/serialization/trees/Relation2Serializer.scala
similarity index 84%
rename from interpreter/shared/src/main/scala/sigmastate/serialization/trees/Relation2Serializer.scala
rename to data/shared/src/main/scala/sigma/serialization/trees/Relation2Serializer.scala
index 655fa8f2d2..6b7bca6426 100644
--- a/interpreter/shared/src/main/scala/sigmastate/serialization/trees/Relation2Serializer.scala
+++ b/data/shared/src/main/scala/sigma/serialization/trees/Relation2Serializer.scala
@@ -1,11 +1,12 @@
-package sigmastate.serialization.trees
+package sigma.serialization.trees
-import sigmastate.Values._
-import sigmastate._
-import sigmastate.serialization.OpCodes._
-import sigmastate.serialization.ValueSerializer
-import sigmastate.utils.{SigmaByteReader, SigmaByteWriter}
-import sigmastate.serialization.ValueSerializer._
+import sigma.ast.{SBoolean, SType}
+import sigma.serialization.CoreByteWriter.{ArgInfo, Bits, DataInfo, maxBitsInfo}
+import sigma.ast._
+import sigma.ast.syntax.SValue
+import sigma.serialization.OpCodes._
+import sigma.serialization.{SigmaByteReader, SigmaByteWriter, ValueSerializer}
+import sigma.serialization.ValueSerializer._
import sigma.util.Extensions._
case class Relation2Serializer[S1 <: SType, S2 <: SType, R <: Value[SBoolean.type]]
diff --git a/interpreter/shared/src/main/scala/sigmastate/utils/SparseArrayContainer.scala b/data/shared/src/main/scala/sigma/utils/SparseArrayContainer.scala
similarity index 79%
rename from interpreter/shared/src/main/scala/sigmastate/utils/SparseArrayContainer.scala
rename to data/shared/src/main/scala/sigma/utils/SparseArrayContainer.scala
index dad6437f5d..dd65676687 100644
--- a/interpreter/shared/src/main/scala/sigmastate/utils/SparseArrayContainer.scala
+++ b/data/shared/src/main/scala/sigma/utils/SparseArrayContainer.scala
@@ -1,8 +1,7 @@
-package sigmastate.utils
+package sigma.utils
-import sigmastate.SType
-import sigmastate.Values.Value
-import sigmastate.serialization.ValueSerializer
+import sigma.ast.{SType, Value}
+import sigma.serialization.ValueSerializer
import scala.reflect.ClassTag
@@ -20,15 +19,20 @@ class SparseArrayContainer[T: ClassTag](values: Seq[(Byte, T)]) {
val dupGroups = sers.groupBy { case (b, _) => b }.filter { case (_, g) => g.size > 1 }.toList
s"expected distinct codes, got duplicated: $dupGroups"
})
- val array = Array.fill[T](256)(null.asInstanceOf[T]) // one item for each OpCode
+ val array = Array.fill[T](256)(null.asInstanceOf[T]) // one item for each code
sers.foreach { case (code, value) =>
- array(codeToIndex(code)) = value
+ array(codeToIndex(code)) = value
}
array
}
@inline
- private def codeToIndex(code: Byte): Int = code + 128
+ private def codeToIndex(code: Byte): Int = code + 128 // -128..127 -> 0..255
+
+ /** @return true if value for the given code is defined
+ * @param code of a value
+ */
+ @inline def contains(code: Byte): Boolean = sparseArray(codeToIndex(code)) != null
/**
* Returns value for the given code
@@ -62,7 +66,7 @@ class SparseArrayContainer[T: ClassTag](values: Seq[(Byte, T)]) {
}
object SparseArrayContainer {
-
+ /** Build a container for the given serializers. */
def buildForSerializers(sers: Seq[ValueSerializer[_ <: Value[SType]]]): SparseArrayContainer[ValueSerializer[_ <: Value[SType]]] = {
new SparseArrayContainer(sers.map(s => (s.opCode, s)))
}
diff --git a/interpreter/js/src/main/scala/sigma/interpreter/js/ProverHints.scala b/interpreter/js/src/main/scala/sigma/interpreter/js/ProverHints.scala
new file mode 100644
index 0000000000..45047d4ec8
--- /dev/null
+++ b/interpreter/js/src/main/scala/sigma/interpreter/js/ProverHints.scala
@@ -0,0 +1,23 @@
+package sigma.interpreter.js
+
+import sigma.js.JsWrapper
+import sigmastate.interpreter.HintsBag
+
+import scala.scalajs.js
+import scala.scalajs.js.annotation.JSExportTopLevel
+
+/** Represents hints used by [[SigmaPropProver]] to perform operations as part of
+ * multi-signature scheme. See [EIP-11](https://github.com/ergoplatform/eips/pull/8).
+ */
+@JSExportTopLevel("ProverHints")
+class ProverHints(override val wrappedValue: HintsBag)
+ extends JsWrapper[HintsBag] {
+}
+
+@JSExportTopLevel("ProverHints$")
+object ProverHints extends js.Object {
+ private lazy val _empty = new ProverHints(HintsBag.empty)
+
+ /** Empty bag of hints. Immutable value can be reused where necessary. */
+ def empty(): ProverHints = _empty
+}
diff --git a/interpreter/js/src/main/scala/sigma/interpreter/js/ProverSecret.scala b/interpreter/js/src/main/scala/sigma/interpreter/js/ProverSecret.scala
new file mode 100644
index 0000000000..176341587c
--- /dev/null
+++ b/interpreter/js/src/main/scala/sigma/interpreter/js/ProverSecret.scala
@@ -0,0 +1,50 @@
+package sigma.interpreter.js
+
+import sigma.data.{CBigInt, ProveDHTuple}
+import sigma.js.{Isos, JsWrapper, SigmaProp}
+import sigma.util.Extensions.BigIntOps
+import sigmastate.crypto.DLogProtocol.DLogProverInput
+import sigmastate.crypto.{DiffieHellmanTupleProverInput, SigmaProtocolPrivateInput}
+
+import scala.scalajs.js
+import scala.scalajs.js.annotation.JSExportTopLevel
+
+/** Represents one secret (aka SigmaProtocolPrivateInput) used by [[SigmaPropProver]]. */
+@JSExportTopLevel("ProverSecret")
+class ProverSecret(
+ override val wrappedValue: SigmaProtocolPrivateInput[sigma.data.SigmaLeaf]
+) extends JsWrapper[SigmaProtocolPrivateInput[sigma.data.SigmaLeaf]] {
+ /** Public key generated from the secret.
+ * Represents proof of knowledge sigma proposition.
+ */
+ def publicKey(): SigmaProp = new SigmaProp(wrappedValue.publicImage)
+
+ /** Secret random number stored in this instance. */
+ def secret(): js.BigInt = Isos.isoBigInt.from(CBigInt(wrappedValue.w))
+}
+
+@JSExportTopLevel("ProverSecret$")
+object ProverSecret extends js.Object {
+ /** Creates a new [[ProverSecret]] instance for the given secret of descrete logarithm
+ * sigma protocol.
+ * @param w secret exponent value
+ */
+ def dlog(w: js.BigInt): ProverSecret = {
+ val input = DLogProverInput(Isos.isoBigInt.to(w).toBigInteger)
+ new ProverSecret(input)
+ }
+
+ /** Creates a new [[ProverSecret]] instance for the given secret of Diffie Hellman tuple
+ * sigma protocol.
+ * @param w secret exponent value used to compute `u = g^w` and `v = h^w`, where `g` and `h` are generators
+ * @param dhtProp a [[SigmaProp]] representing public key of Diffie Hellman tuple sigma protocol, should be created using `w`
+ */
+ def dht(w: js.BigInt, dhtProp: SigmaProp): ProverSecret = {
+ dhtProp.sigmaBoolean match {
+ case dht: ProveDHTuple =>
+ val input = DiffieHellmanTupleProverInput(Isos.isoBigInt.to(w).toBigInteger, dht)
+ new ProverSecret(input)
+ case _ => throw new Exception("Expected ProveDHTuple sigma proposition")
+ }
+ }
+}
\ No newline at end of file
diff --git a/interpreter/js/src/main/scala/sigma/interpreter/js/SigmaPropProver.scala b/interpreter/js/src/main/scala/sigma/interpreter/js/SigmaPropProver.scala
new file mode 100644
index 0000000000..a04d32fa54
--- /dev/null
+++ b/interpreter/js/src/main/scala/sigma/interpreter/js/SigmaPropProver.scala
@@ -0,0 +1,108 @@
+package sigma.interpreter.js
+
+import sigma.data.{Iso, SigmaBoolean}
+import sigma.exceptions.InterpreterException
+import sigma.js.{Isos, JsWrapper, SigmaProp}
+
+import scala.scalajs.js
+import scala.scalajs.js.annotation.JSExportTopLevel
+import scala.scalajs.js.typedarray.Int8Array
+import scala.util.{Failure, Success}
+
+/** Prover which can sign messages (generate proofs) for arbitrary sigma propositions
+ * represented by [[SigmaProp]] values.
+ *
+ * See [EIP-11](https://github.com/ergoplatform/eips/pull/8) for details of multi-signature scheme.
+ *
+ * @see SigmaPropVerifier
+ */
+@JSExportTopLevel("SigmaPropProver")
+class SigmaPropProver(override val wrappedValue: org.ergoplatform.SigmaPropProver)
+ extends JsWrapper[org.ergoplatform.SigmaPropProver] {
+ private val isoSP = Isos.isoArrayToIndexed(Iso.identityIso[SigmaProp])
+
+ private def toSigmaBooleanSeq(sps: js.Array[SigmaProp]): Seq[SigmaBoolean] = {
+ isoSP.to(sps).map(_.sigmaBoolean)
+ }
+
+ /**
+ * A method which is generating commitments for all the public keys provided.
+ * This is used as part of multi-signature scheme.
+ *
+ * Currently only keys in form of ProveDlog and ProveDiffieHellman are supported, not more complex subtrees.
+ *
+ * @param sigmaTree - crypto-tree which is being signed
+ * @param generateFor - public keys for which commitments should be generated
+ * @return generated commitments in a form of prover hints
+ * - private, containing secret randomness
+ * - public, containing only commitments
+ */
+ def generateCommitmentsFor(
+ sigmaTree: SigmaProp,
+ generateFor: js.Array[SigmaProp]): ProverHints = {
+ val pks = toSigmaBooleanSeq(generateFor)
+ val reduced = wrappedValue.generateCommitmentsFor(sigmaTree.sigmaBoolean, pks)
+ new ProverHints(reduced)
+ }
+
+ /**
+ * A method which is extracting partial proofs of secret knowledge for particular secrets with their
+ * respective public images given. Useful for distributed signature applications.
+ *
+ * See DistributedSigSpecification for examples of usage.
+ *
+ * @param sigmaTree - public key (in form of a sigma-tree)
+ * @param proof - signature for the key
+ * @param realSecretsToExtract - public keys of secrets with real proofs
+ * @param simulatedSecretsToExtract - public keys of secrets with simulated proofs
+ * @return - bag of OtherSecretProven and OtherCommitment hints
+ */
+ def hintsForMultisig(
+ sigmaTree: SigmaProp,
+ proof: Int8Array,
+ realSecretsToExtract: js.Array[SigmaProp],
+ simulatedSecretsToExtract: js.Array[SigmaProp]): ProverHints = {
+ val realsToExtract = toSigmaBooleanSeq(realSecretsToExtract)
+ val simsToExtract = toSigmaBooleanSeq(simulatedSecretsToExtract)
+ val hints = wrappedValue.bagForMultisig(
+ context = null,
+ sigmaTree = sigmaTree.sigmaBoolean, proof.toArray,
+ realSecretsToExtract = realsToExtract,
+ simulatedSecretsToExtract = simsToExtract)
+ new ProverHints(hints)
+ }
+
+ /**
+ * Generate commitments for given crypto-tree (sigma-tree) for prover's secrets.
+ */
+ def generateCommitments(sigmaTree: SigmaProp): ProverHints = {
+ val hints = wrappedValue.generateCommitments(sigmaTree.sigmaBoolean)
+ new ProverHints(hints)
+ }
+
+ /** Sign arbitrary message under a key representing a statement provable via a sigma-protocol.
+ *
+ * @param sigmaProp - public key
+ * @param message - message to sign
+ * @param hintsBag - additional hints for a signer (useful for distributed signing)
+ * @return - signature or error
+ */
+ def signMessage(
+ sigmaProp: SigmaProp,
+ message: Int8Array,
+ hintsBag: ProverHints): Int8Array = {
+ wrappedValue.signMessage(sigmaProp.sigmaBoolean, message.toArray, hintsBag.wrappedValue) match {
+ case Success(signature) => Int8Array.of(signature:_*)
+ case Failure(t) => throw new InterpreterException("Failed to sign message", Some(t))
+ }
+ }
+}
+
+@JSExportTopLevel("SigmaPropProver$")
+object SigmaPropProver extends js.Object {
+ /** Creates a new [[SigmaPropProver]] with the given secrets. */
+ def withSecrets(secrets: js.Array[ProverSecret]): SigmaPropProver = {
+ val privateInputs = Isos.isoArrayToIndexed(Iso.identityIso[ProverSecret]).to(secrets).map(_.wrappedValue)
+ new SigmaPropProver(new org.ergoplatform.SigmaPropProver(privateInputs))
+ }
+}
\ No newline at end of file
diff --git a/interpreter/js/src/main/scala/sigma/interpreter/js/SigmaPropVerifier.scala b/interpreter/js/src/main/scala/sigma/interpreter/js/SigmaPropVerifier.scala
new file mode 100644
index 0000000000..caddc37e1a
--- /dev/null
+++ b/interpreter/js/src/main/scala/sigma/interpreter/js/SigmaPropVerifier.scala
@@ -0,0 +1,43 @@
+package sigma.interpreter.js
+
+import sigma.js.{JsWrapper, SigmaProp}
+
+import scala.scalajs.js
+import scala.scalajs.js.annotation.JSExportTopLevel
+import scala.scalajs.js.typedarray.Int8Array
+
+/** Verifier which can verify signature (proof) for arbitrary sigma propositions
+ * represented by [[SigmaProp]] values.
+ *
+ * See [EIP-11](https://github.com/ergoplatform/eips/pull/8) for details of multi-signature scheme.
+ *
+ * @see SigmaPropProver
+ */
+@JSExportTopLevel("SigmaPropVerifier")
+class SigmaPropVerifier(override val wrappedValue: org.ergoplatform.SigmaPropVerifier)
+ extends JsWrapper[org.ergoplatform.SigmaPropVerifier] {
+ /**
+ * Verify a signature on given (arbitrary) message for a given sigma proposition (public key).
+ *
+ * @param sigmaProp public key (represented as a sigma proposition)
+ * @param message message
+ * @param signature signature for the message
+ * @return whether signature is valid or not (valid signature contains proofs for the sigma proposition)
+ */
+ def verifySignature(
+ sigmaProp: SigmaProp,
+ message: Int8Array,
+ signature: Int8Array): Boolean = {
+ val ok = wrappedValue.verifySignature(sigmaProp.sigmaBoolean, message.toArray, signature.toArray)(null)
+ ok
+ }
+}
+
+@JSExportTopLevel("SigmaPropVerifier$")
+object SigmaPropVerifier extends js.Object {
+ /** Create a new instance of SigmaPropVerifier. */
+ def create(): SigmaPropVerifier = {
+ new SigmaPropVerifier(new org.ergoplatform.SigmaPropVerifier())
+ }
+}
+
diff --git a/interpreter/js/src/test/scala/sigmastate/crypto/CryptoContextJsSpec.scala b/interpreter/js/src/test/scala/sigmastate/crypto/CryptoContextJsSpec.scala
index e6d8c93009..4fe1e23726 100644
--- a/interpreter/js/src/test/scala/sigmastate/crypto/CryptoContextJsSpec.scala
+++ b/interpreter/js/src/test/scala/sigmastate/crypto/CryptoContextJsSpec.scala
@@ -2,6 +2,7 @@ package sigmastate.crypto
import org.scalatest.matchers.should.Matchers
import org.scalatest.propspec.AnyPropSpec
+import sigma.crypto.CryptoContextJs
import scala.scalajs.js
diff --git a/interpreter/js/src/test/scala/sigmastate/crypto/CryptoFacadeJsSpec.scala b/interpreter/js/src/test/scala/sigmastate/crypto/CryptoFacadeJsSpec.scala
index 63839e67ef..d80e4fec51 100644
--- a/interpreter/js/src/test/scala/sigmastate/crypto/CryptoFacadeJsSpec.scala
+++ b/interpreter/js/src/test/scala/sigmastate/crypto/CryptoFacadeJsSpec.scala
@@ -2,6 +2,9 @@ package sigmastate.crypto
import org.scalatest.matchers.should.Matchers
import org.scalatest.propspec.AnyPropSpec
+import sigma.crypto.Platform.Ecp
+import sigma.crypto.utils.bytesToHex
+import sigma.crypto.{CryptoFacade, CryptoFacadeJs, Point}
import scala.scalajs.js
import scala.scalajs.js.typedarray.Uint8Array
@@ -68,9 +71,9 @@ class CryptoFacadeJsSpec extends AnyPropSpec with Matchers with CryptoTesting {
}
property("CryptoFacade.getEncodedOfFieldElem") {
- utils.bytesToHex(CryptoFacadeJs.getEncodedOfFieldElem(p1.x)) shouldEqual
+ bytesToHex(CryptoFacadeJs.getEncodedOfFieldElem(p1.x)) shouldEqual
"81c5275b1d50c39a0c36c4561c3a37bff1d87e37a9ad69eab029e426c0b1a8ac"
- utils.bytesToHex(CryptoFacadeJs.getEncodedOfFieldElem(p1.y)) shouldBe
+ bytesToHex(CryptoFacadeJs.getEncodedOfFieldElem(p1.y)) shouldBe
"db5d999704ec84b62962f3e35889901d04a619cd6d81d251c69d0f625c2dc4f3"
}
@@ -87,14 +90,14 @@ class CryptoFacadeJsSpec extends AnyPropSpec with Matchers with CryptoTesting {
property("CryptoFacade.hashHmacSHA512") {
val key = Uint8Array.from(bytesToJsShorts(CryptoFacade.BitcoinSeed))
val data = Uint8Array.from(bytesToJsShorts("abc".getBytes(CryptoFacade.Encoding)))
- val res = utils.bytesToHex(CryptoFacadeJs.hashHmacSHA512(key, data))
+ val res = bytesToHex(CryptoFacadeJs.hashHmacSHA512(key, data))
res shouldBe "2c15e87cde0f876fd8f060993748330cbe5f37c8bb3355e8ef44cea57890ec1d9b3274ef2b67bbe046cf8a012fba69796ec7803b1cc227521b9f5191e80a7da2"
}
property("CryptoFacade.generatePbkdf2Key") {
val mnemonic = "slow silly start wash bundle suffer bulb ancient height spin express remind today effort helmet"
val password = "pwd"
- val res = utils.bytesToHex(CryptoFacadeJs.generatePbkdf2Key(mnemonic, password))
+ val res = bytesToHex(CryptoFacadeJs.generatePbkdf2Key(mnemonic, password))
res shouldBe "0a8ea2ea0c4c12a9df88b005bda00c4de51ff36834b5fcd6a83667c371ad1da94bca1798690d87f2603b8f51d5ae025209e31f6cf81e12b84e4c543d236e58d0"
}
}
diff --git a/interpreter/shared/src/main/scala/org/ergoplatform/ErgoLikeContext.scala b/interpreter/shared/src/main/scala/org/ergoplatform/ErgoLikeContext.scala
index 05b5bde4e2..8468175631 100644
--- a/interpreter/shared/src/main/scala/org/ergoplatform/ErgoLikeContext.scala
+++ b/interpreter/shared/src/main/scala/org/ergoplatform/ErgoLikeContext.scala
@@ -1,19 +1,18 @@
package org.ergoplatform
-import org.ergoplatform.validation.SigmaValidationSettings
-import sigmastate.SType._
-import sigmastate.Values._
-import sigmastate._
+import debox.cfor
+import sigma.Extensions.ArrayOps
+import sigma.ast.SType.{AnyOps, TypeCode}
+import sigma.ast._
+import sigma.data.{AvlTreeData, CAvlTree, CSigmaDslBuilder, SigmaConstants}
+import sigma.eval.Extensions.toAnyValue
+import sigma.exceptions.InterpreterException
+import sigma.interpreter.ContextExtension
+import sigma.validation.SigmaValidationSettings
+import sigma.{AnyValue, Coll, Header, PreHeader}
import sigmastate.eval.Extensions._
import sigmastate.eval._
-import sigmastate.interpreter.ErgoTreeEvaluator.DataEnv
-import sigmastate.interpreter.{ContextExtension, ErgoTreeEvaluator, Interpreter, InterpreterContext}
-import sigmastate.exceptions.InterpreterException
-import sigmastate.serialization.OpCodes
-import sigmastate.serialization.OpCodes.OpCode
-import sigma.Coll
-import sigma.{AnyValue, Header, PreHeader}
-import debox.cfor
+import sigmastate.interpreter.InterpreterContext
/** Represents a script evaluation context to be passed to a prover and a verifier to execute and
* validate guarding proposition of input boxes of a transaction.
@@ -136,8 +135,8 @@ class ErgoLikeContext(val lastBlockUtxoRoot: AvlTreeData,
def withTransaction(newSpendingTransaction: ErgoLikeTransactionTemplate[_ <: UnsignedInput]): ErgoLikeContext =
ErgoLikeContext.copy(this)(spendingTransaction = newSpendingTransaction)
- override def toSigmaContext(extensions: Map[Byte, AnyValue] = Map()): sigma.Context = {
- import Evaluation._
+ override def toSigmaContext(): sigma.Context = {
+ import sigma.Evaluation._
def contextVars(m: Map[Byte, AnyValue]): Coll[AnyValue] = {
val maxKey = if (m.keys.isEmpty) 0 else m.keys.max // TODO optimize: max takes 90% of this method
@@ -145,7 +144,7 @@ class ErgoLikeContext(val lastBlockUtxoRoot: AvlTreeData,
for ((id, v) <- m) {
res(id) = v
}
- CostingSigmaDslBuilder.Colls.fromArray(res)
+ CSigmaDslBuilder.Colls.fromArray(res)
}
val dataInputs = this.dataBoxes.toArray.map(_.toTestBox).toColl
@@ -161,14 +160,14 @@ class ErgoLikeContext(val lastBlockUtxoRoot: AvlTreeData,
val tVal = stypeToRType[SType](v.tpe)
k -> toAnyValue(v.value.asWrappedType)(tVal)
}.toMap
- val vars = contextVars(varMap ++ extensions)
+ val vars = contextVars(varMap)
val avlTree = CAvlTree(lastBlockUtxoRoot)
// so selfBox is never one of the `inputs` instances
// as result selfBoxIndex is always (erroneously) returns -1 in ErgoTree v0, v1
val selfBox = boxesToSpend(selfIndex).toTestBox
val ergoTreeVersion = currentErgoTreeVersion.getOrElse(
- Interpreter.error(s"Undefined context property: currentErgoTreeVersion"))
- CostingDataContext(
+ syntax.error(s"Undefined context property: currentErgoTreeVersion"))
+ CContext(
dataInputs, headers, preHeader, inputs, outputs, preHeader.height, selfBox, selfIndex, avlTree,
preHeader.minerPk.getEncoded, vars, activatedScriptVersion, ergoTreeVersion)
}
@@ -243,119 +242,4 @@ object ErgoLikeContext {
}
}
-/** When interpreted evaluates to a ByteArrayConstant built from Context.minerPubkey */
-case object MinerPubkey extends NotReadyValueByteArray with ValueCompanion {
- override def opCode: OpCode = OpCodes.MinerPubkeyCode
- /** Cost of calling Context.minerPubkey Scala method. */
- override val costKind = FixedCost(JitCost(20))
- override val opType = SFunc(SContext, SCollection.SByteArray)
- override def companion = this
- protected final override def eval(env: DataEnv)(implicit E: ErgoTreeEvaluator): Any = {
- addCost(this.costKind)
- E.context.minerPubKey
- }
-}
-
-/** When interpreted evaluates to a IntConstant built from Context.currentHeight */
-case object Height extends NotReadyValueInt with FixedCostValueCompanion {
- override def companion = this
- override def opCode: OpCode = OpCodes.HeightCode
- /** Cost of: 1) Calling Context.HEIGHT Scala method. */
- override val costKind = FixedCost(JitCost(26))
- override val opType = SFunc(SContext, SInt)
- protected final override def eval(env: DataEnv)(implicit E: ErgoTreeEvaluator): Any = {
- addCost(this.costKind)
- E.context.HEIGHT
- }
-}
-
-/** When interpreted evaluates to a collection of BoxConstant built from Context.boxesToSpend */
-case object Inputs extends LazyCollection[SBox.type] with FixedCostValueCompanion {
- override def companion = this
- override def opCode: OpCode = OpCodes.InputsCode
- /** Cost of: 1) Calling Context.INPUTS Scala method. */
- override val costKind = FixedCost(JitCost(10))
- override def tpe = SCollection.SBoxArray
- override val opType = SFunc(SContext, tpe)
- protected final override def eval(env: DataEnv)(implicit E: ErgoTreeEvaluator): Any = {
- addCost(this.costKind)
- E.context.INPUTS
- }
-}
-
-/** When interpreted evaluates to a collection of BoxConstant built from Context.spendingTransaction.outputs */
-case object Outputs extends LazyCollection[SBox.type] with FixedCostValueCompanion {
- override def companion = this
- override def opCode: OpCode = OpCodes.OutputsCode
- /** Cost of: 1) Calling Context.OUTPUTS Scala method. */
- override val costKind = FixedCost(JitCost(10))
- override def tpe = SCollection.SBoxArray
- override val opType = SFunc(SContext, tpe)
- protected final override def eval(env: DataEnv)(implicit E: ErgoTreeEvaluator): Any = {
- addCost(this.costKind)
- E.context.OUTPUTS
- }
-}
-
-/** When interpreted evaluates to a AvlTreeConstant built from Context.lastBlockUtxoRoot */
-case object LastBlockUtxoRootHash extends NotReadyValueAvlTree with ValueCompanion {
- override def companion = this
- override def opCode: OpCode = OpCodes.LastBlockUtxoRootHashCode
- /** Cost of: 1) Calling Context.LastBlockUtxoRootHash Scala method. */
- override val costKind = FixedCost(JitCost(15))
-
- override val opType = SFunc(SContext, tpe)
- protected final override def eval(env: DataEnv)(implicit E: ErgoTreeEvaluator): Any = {
- addCost(this.costKind)
- E.context.LastBlockUtxoRootHash
- }
-}
-
-
-/** When interpreted evaluates to a BoxConstant built from context.boxesToSpend(context.selfIndex) */
-case object Self extends NotReadyValueBox with FixedCostValueCompanion {
- override def companion = this
- override def opCode: OpCode = OpCodes.SelfCode
- /** Cost of: 1) Calling Context.SELF Scala method. */
- override val costKind = FixedCost(JitCost(10))
- override val opType = SFunc(SContext, SBox)
- protected final override def eval(env: DataEnv)(implicit E: ErgoTreeEvaluator): Any = {
- addCost(this.costKind)
- E.context.SELF
- }
-}
-
-/** When interpreted evaluates to the singleton instance of [[sigma.Context]].
- * Corresponds to `CONTEXT` variable in ErgoScript which can be used like `CONTEXT.headers`.
- */
-case object Context extends NotReadyValue[SContext.type] with ValueCompanion {
- override def companion = this
- override def opCode: OpCode = OpCodes.ContextCode
-
- /** Cost of: 1) accessing global Context instance. */
- override val costKind = FixedCost(JitCost(1))
-
- override def tpe: SContext.type = SContext
- override val opType: SFunc = SFunc(SUnit, SContext)
- protected final override def eval(env: DataEnv)(implicit E: ErgoTreeEvaluator): Any = {
- addCost(this.costKind)
- E.context
- }
-}
-
-/** When interpreted evaluates to the singleton instance of [[sigma.SigmaDslBuilder]].
- * Corresponds to `Global` variable in ErgoScript which can be used like `Global.groupGenerator`.
- */
-case object Global extends NotReadyValue[SGlobal.type] with FixedCostValueCompanion {
- override def companion = this
- override def opCode: OpCode = OpCodes.GlobalCode
- /** Cost of: 1) accessing Global instance. */
- override val costKind = FixedCost(JitCost(5))
- override def tpe: SGlobal.type = SGlobal
- override val opType: SFunc = SFunc(SUnit, SGlobal)
- protected final override def eval(env: DataEnv)(implicit E: ErgoTreeEvaluator): Any = {
- addCost(this.costKind)
- CostingSigmaDslBuilder
- }
-}
diff --git a/interpreter/shared/src/main/scala/org/ergoplatform/ErgoLikeInterpreter.scala b/interpreter/shared/src/main/scala/org/ergoplatform/ErgoLikeInterpreter.scala
index 1730bed277..e986905fb0 100644
--- a/interpreter/shared/src/main/scala/org/ergoplatform/ErgoLikeInterpreter.scala
+++ b/interpreter/shared/src/main/scala/org/ergoplatform/ErgoLikeInterpreter.scala
@@ -1,9 +1,9 @@
package org.ergoplatform
-import sigmastate.SCollection.SByteArray
-import sigmastate.Values._
+import sigma.ast.SCollection.SByteArray
+import sigma.ast._
+import sigma.ast.syntax._
import sigmastate.interpreter.Interpreter
-import sigmastate.utxo._
/** Base class of verifying interpreter which expects ErgoLikeContext as input of
diff --git a/interpreter/shared/src/main/scala/org/ergoplatform/ErgoTreePredef.scala b/interpreter/shared/src/main/scala/org/ergoplatform/ErgoTreePredef.scala
index 8f01a46864..8bba479745 100644
--- a/interpreter/shared/src/main/scala/org/ergoplatform/ErgoTreePredef.scala
+++ b/interpreter/shared/src/main/scala/org/ergoplatform/ErgoTreePredef.scala
@@ -1,29 +1,29 @@
package org.ergoplatform
import org.ergoplatform.settings.MonetarySettings
-import sigmastate.crypto.DLogProtocol.ProveDlog
-import sigmastate.crypto.CryptoConstants
-import sigmastate.serialization.ErgoTreeSerializer.DefaultSerializer
-import sigmastate.SCollection.SByteArray
-import sigmastate.Values.{LongConstant, SigmaPropConstant, IntArrayConstant, TrueSigmaProp, Value, FalseSigmaProp, SigmaPropValue, IntConstant, ErgoTree}
-import sigmastate.utxo._
+import sigma.ast.SCollection.SByteArray
+import sigma.ast._
+import sigma.ast.syntax._
+import sigma.data.ProveDlog
+import ErgoTree.{HeaderType, ZeroHeader}
+import sigma.crypto.CryptoConstants
+import sigma.serialization.ErgoTreeSerializer.DefaultSerializer
import sigmastate._
-import sigmastate.lang.Terms.ValueOps
object ErgoTreePredef {
/** Create ErgoTree with `false` proposition, which is never true.
*
- * @param headerFlags ErgoTree header flags to be combined with default header
+ * @param header ErgoTree header to be used in the tree
* @see ErgoTree.headerWithVersion()
*/
- def FalseProp(headerFlags: Byte): ErgoTree = ErgoTree.withoutSegregation(headerFlags, FalseSigmaProp)
+ def FalseProp(header: HeaderType): ErgoTree = ErgoTree.withoutSegregation(header, FalseSigmaProp)
/** Create ErgoTree with `true` proposition, which is always true.
*
- * @param headerFlags ErgoTree header flags to be combined with default header
+ * @param header ErgoTree header to be used in the tree
* @see ErgoTree.headerWithVersion()
*/
- def TrueProp(headerFlags: Byte): ErgoTree = ErgoTree.withoutSegregation(headerFlags, TrueSigmaProp)
+ def TrueProp(header: HeaderType): ErgoTree = ErgoTree.withoutSegregation(header, TrueSigmaProp)
/**
* Byte array value of the serialized reward output script proposition with pk being substituted
@@ -41,7 +41,7 @@ object ErgoTreePredef {
// first segregated constant is delta, so key is second constant
val positions = IntArrayConstant(Array[Int](1))
val minerPubkeySigmaProp = CreateProveDlog(DecodePoint(minerPkBytesVal))
- val newVals = Values.ConcreteCollection(Array[SigmaPropValue](minerPubkeySigmaProp), SSigmaProp)
+ val newVals = ConcreteCollection(Array[SigmaPropValue](minerPubkeySigmaProp), SSigmaProp)
SubstConstants(genericMinerPropBytes, positions, newVals)
}
@@ -49,10 +49,10 @@ object ErgoTreePredef {
* Required script of the box, that collects mining rewards
*/
def rewardOutputScript(delta: Int, minerPk: ProveDlog): ErgoTree = {
- SigmaAnd(
+ ErgoTree.withSegregation(ZeroHeader, SigmaAnd(
GE(Height, Plus(boxCreationHeight(Self), IntConstant(delta))).toSigmaProp,
SigmaPropConstant(minerPk)
- ).treeWithSegregation
+ ))
}
/**
@@ -61,11 +61,11 @@ object ErgoTreePredef {
*/
def feeProposition(delta: Int = 720): ErgoTree = {
val out = ByIndex(Outputs, IntConstant(0))
- AND(
+ ErgoTree.withSegregation(ZeroHeader, AND(
EQ(Height, boxCreationHeight(out)),
EQ(ExtractScriptBytes(out), expectedMinerOutScriptBytesVal(delta, MinerPubkey)),
EQ(SizeOf(Outputs), 1)
- ).toSigmaProp.treeWithSegregation
+ ).toSigmaProp)
}
/**
@@ -91,11 +91,13 @@ object ErgoTreePredef {
EQ(ExtractScriptBytes(minerOut), expectedMinerOutScriptBytesVal(s.minerRewardDelay, MinerPubkey)),
EQ(Height, boxCreationHeight(minerOut))
)
- AND(
- heightIncreased,
- correctMinerOutput,
- OR(AND(outputsNum, sameScriptRule, correctCoinsConsumed, heightCorrect), lastCoins)
- ).toSigmaProp.treeWithSegregation
+ ErgoTree.withSegregation(ZeroHeader,
+ AND(
+ heightIncreased,
+ correctMinerOutput,
+ OR(AND(outputsNum, sameScriptRule, correctCoinsConsumed, heightCorrect), lastCoins)
+ ).toSigmaProp
+ )
}
/**
@@ -152,7 +154,7 @@ object ErgoTreePredef {
// check, that additional rules defined by foundation members are satisfied
val customProposition = DeserializeRegister(ErgoBox.R4, SSigmaProp)
// combine 3 conditions above with AND conjunction
- SigmaAnd(amountCorrect.toSigmaProp, sameScriptRule.toSigmaProp, customProposition).treeWithSegregation
+ ErgoTree.withSegregation(ZeroHeader, SigmaAnd(amountCorrect.toSigmaProp, sameScriptRule.toSigmaProp, customProposition))
}
/**
diff --git a/interpreter/shared/src/main/scala/org/ergoplatform/SigmaPropProver.scala b/interpreter/shared/src/main/scala/org/ergoplatform/SigmaPropProver.scala
new file mode 100644
index 0000000000..09843554fb
--- /dev/null
+++ b/interpreter/shared/src/main/scala/org/ergoplatform/SigmaPropProver.scala
@@ -0,0 +1,14 @@
+package org.ergoplatform
+
+import sigmastate.crypto.SigmaProtocolPrivateInput
+import sigmastate.interpreter.ProverInterpreter
+
+/** Prover which can reduce ErgoTrees and prove sigma propositions using provided secrets.
+ *
+ * @param secrets All secrets available for this prover.
+ */
+class SigmaPropProver(override val secrets: Seq[SigmaProtocolPrivateInput[_]])
+ extends ErgoLikeInterpreter
+ with ProverInterpreter {
+ override type CTX = ErgoLikeContext
+}
diff --git a/interpreter/shared/src/main/scala/org/ergoplatform/SigmaPropVerifier.scala b/interpreter/shared/src/main/scala/org/ergoplatform/SigmaPropVerifier.scala
new file mode 100644
index 0000000000..382dd9a470
--- /dev/null
+++ b/interpreter/shared/src/main/scala/org/ergoplatform/SigmaPropVerifier.scala
@@ -0,0 +1,6 @@
+package org.ergoplatform
+
+/** Verifier which can verify proofs generated by [[SigmaPropProver]]. */
+class SigmaPropVerifier
+ extends ErgoLikeInterpreter {
+}
diff --git a/interpreter/shared/src/main/scala/org/ergoplatform/dsl/AvlTreeHelpers.scala b/interpreter/shared/src/main/scala/org/ergoplatform/dsl/AvlTreeHelpers.scala
index 627b0a3f54..8acb51403e 100644
--- a/interpreter/shared/src/main/scala/org/ergoplatform/dsl/AvlTreeHelpers.scala
+++ b/interpreter/shared/src/main/scala/org/ergoplatform/dsl/AvlTreeHelpers.scala
@@ -1,13 +1,12 @@
package org.ergoplatform.dsl
import sigma.Coll
-import sigmastate.eval.{CAvlTree, CostingSigmaDslBuilder}
import scorex.crypto.authds.{ADKey, ADValue}
-import scorex.crypto.hash.{Digest32, Blake2b256}
-import sigmastate.{AvlTreeData, AvlTreeFlags}
+import scorex.crypto.hash.{Blake2b256, Digest32}
import sigma.AvlTree
import scorex.crypto.authds.avltree.batch.{BatchAVLProver, Insert}
-import CostingSigmaDslBuilder.Colls
+import sigma.data.CSigmaDslBuilder.Colls
+import sigma.data.{AvlTreeData, AvlTreeFlags, CAvlTree}
object AvlTreeHelpers {
diff --git a/interpreter/shared/src/main/scala/org/ergoplatform/settings/MonetarySettings.scala b/interpreter/shared/src/main/scala/org/ergoplatform/settings/MonetarySettings.scala
index 15f7b9edbb..60ced82c88 100644
--- a/interpreter/shared/src/main/scala/org/ergoplatform/settings/MonetarySettings.scala
+++ b/interpreter/shared/src/main/scala/org/ergoplatform/settings/MonetarySettings.scala
@@ -1,8 +1,8 @@
package org.ergoplatform.settings
-import sigmastate.Values.ErgoTree
import org.ergoplatform.ErgoTreePredef
import org.ergoplatform.mining.emission.EmissionRules
+import sigma.ast.ErgoTree
/**
* Configuration file for monetary settings of Ergo chain
diff --git a/interpreter/shared/src/main/scala/org/ergoplatform/validation/RuleStatusSerializer.scala b/interpreter/shared/src/main/scala/org/ergoplatform/validation/RuleStatusSerializer.scala
index e032f0f647..081d573cf1 100644
--- a/interpreter/shared/src/main/scala/org/ergoplatform/validation/RuleStatusSerializer.scala
+++ b/interpreter/shared/src/main/scala/org/ergoplatform/validation/RuleStatusSerializer.scala
@@ -1,7 +1,7 @@
package org.ergoplatform.validation
-import sigmastate.serialization.SigmaSerializer
-import sigmastate.utils.{SigmaByteReader, SigmaByteWriter}
+import sigma.validation.{ChangedRule, DisabledRule, EnabledRule, ReplacedRule, RuleStatus}
+import sigma.serialization.{SigmaByteReader, SigmaByteWriter, SigmaSerializer}
object RuleStatusSerializer extends SigmaSerializer[RuleStatus, RuleStatus] {
import RuleStatus._
diff --git a/interpreter/shared/src/main/scala/org/ergoplatform/validation/SigmaValidationSettingsSerializer.scala b/interpreter/shared/src/main/scala/org/ergoplatform/validation/SigmaValidationSettingsSerializer.scala
index 2c5156ccae..23c18a7b05 100644
--- a/interpreter/shared/src/main/scala/org/ergoplatform/validation/SigmaValidationSettingsSerializer.scala
+++ b/interpreter/shared/src/main/scala/org/ergoplatform/validation/SigmaValidationSettingsSerializer.scala
@@ -1,9 +1,9 @@
package org.ergoplatform.validation
-import sigmastate.serialization.SigmaSerializer
-import sigmastate.utils.{SigmaByteReader, SigmaByteWriter}
+import sigma.serialization.{SerializerException, SigmaByteReader, SigmaByteWriter}
+import sigma.serialization.SigmaSerializer
import sigma.util.Extensions.IntOps
-import sigmastate.exceptions.SerializerException
+import sigma.validation.{MapSigmaValidationSettings, SigmaValidationSettings}
/** The rules are serialized ordered by ruleId.
* This serializer preserves roundtrip identity `deserialize(serialize(_)) = identity`
diff --git a/interpreter/shared/src/main/scala/sigmastate/InterpreterReflection.scala b/interpreter/shared/src/main/scala/sigmastate/InterpreterReflection.scala
index c6cec6c3da..9a06322166 100644
--- a/interpreter/shared/src/main/scala/sigmastate/InterpreterReflection.scala
+++ b/interpreter/shared/src/main/scala/sigmastate/InterpreterReflection.scala
@@ -1,91 +1,23 @@
package sigmastate
-import org.ergoplatform.ErgoBox.RegisterId
+import sigma.SigmaDataReflection
+import sigma.data.{CAND, COR, CTHRESHOLD}
+import sigma.reflection.mkConstructor
import sigma.reflection.ReflectionData.registerClassEntry
-import sigma.reflection.{ReflectionData, mkConstructor, mkMethod}
-import sigma.Coll
-import sigma.{AvlTree, SigmaDslBuilder}
-import sigmastate.SAvlTree.KeyValueColl
-import sigmastate.SCollection.{SBooleanArray, SByteArray, SIntArray}
-import sigmastate.Values._
-import sigmastate.crypto.VerifierMessage.Challenge
import sigmastate.crypto.GF2_192_Poly
-import sigmastate.interpreter.ErgoTreeEvaluator
-import sigmastate.lang.Terms._
-import sigmastate.serialization.OpCodes.OpCode
-import sigmastate.utxo._
+import sigmastate.crypto.VerifierMessage.Challenge
/** Reflection metadata for `interpreter` module.
+ * Such metadata is only used on JS platform to support reflection-like interfaces of
+ * RClass, RMethod, RConstructor. These interfaces implemented on JVM using Java
+ * reflection.
+ *
* For each class of this module that needs reflection metadata,
* we register a class entry with the necessary information.
* Only information that is needed at runtime is registered.
*/
object InterpreterReflection {
- val reflection = ReflectionData
-
- registerClassEntry(classOf[AND],
- constructors = Array(
- mkConstructor(Array(classOf[Value[_]])) { args =>
- new AND(args(0).asInstanceOf[Value[SBooleanArray]])
- }
- )
- )
-
- registerClassEntry(classOf[ArithOp[_]],
- constructors = Array(
- mkConstructor(Array(classOf[Value[_]], classOf[Value[_]], classOf[Byte])) { args =>
- new ArithOp(args(0).asInstanceOf[SValue], args(1).asInstanceOf[SValue], args(2).asInstanceOf[OpCode])
- }
- )
- )
-
- registerClassEntry(classOf[AtLeast],
- constructors = Array(
- mkConstructor(Array(classOf[Value[_]], classOf[Value[_]])) { args =>
- new AtLeast(args(0).asInstanceOf[IntValue], args(1).asInstanceOf[CollectionValue[SSigmaProp.type]])
- }
- )
- )
-
- registerClassEntry(classOf[BinAnd],
- constructors = Array(
- mkConstructor(Array(classOf[Value[_]], classOf[Value[_]])) { args =>
- new BinAnd(args(0).asInstanceOf[BoolValue], args(1).asInstanceOf[BoolValue])
- }
- )
- )
-
- registerClassEntry(classOf[BinOr],
- constructors = Array(
- mkConstructor(Array(classOf[Value[_]], classOf[Value[_]])) { args =>
- new BinOr(args(0).asInstanceOf[BoolValue], args(1).asInstanceOf[BoolValue])
- }
- )
- )
-
- registerClassEntry(classOf[BinXor],
- constructors = Array(
- mkConstructor(Array(classOf[Value[_]], classOf[Value[_]])) { args =>
- new BinXor(args(0).asInstanceOf[BoolValue], args(1).asInstanceOf[BoolValue])
- }
- )
- )
-
- registerClassEntry(classOf[BoolToSigmaProp],
- constructors = Array(
- mkConstructor(Array(classOf[Value[_]])) { args =>
- new BoolToSigmaProp(args(0).asInstanceOf[BoolValue])
- }
- )
- )
-
- registerClassEntry(classOf[ByteArrayToBigInt],
- constructors = Array(
- mkConstructor(Array(classOf[Value[_]])) { args =>
- new ByteArrayToBigInt(args(0).asInstanceOf[Value[SByteArray]])
- }
- )
- )
+ val reflection = SigmaDataReflection
registerClassEntry(classOf[CAndUncheckedNode],
constructors = Array(
@@ -151,579 +83,4 @@ object InterpreterReflection {
}
)
)
-
- registerClassEntry(classOf[CalcBlake2b256],
- constructors = Array(
- mkConstructor(Array(classOf[Value[_]])) { args =>
- new CalcBlake2b256(args(0).asInstanceOf[Value[SByteArray]])
- }
- )
- )
-
- registerClassEntry(classOf[CalcSha256],
- constructors = Array(
- mkConstructor(Array(classOf[Value[_]])) { args =>
- new CalcSha256(args(0).asInstanceOf[Value[SByteArray]])
- }
- )
- )
-
- registerClassEntry(classOf[CreateProveDHTuple],
- constructors = Array(
- mkConstructor(Array(classOf[Value[_]], classOf[Value[_]], classOf[Value[_]], classOf[Value[_]])) { args =>
- new CreateProveDHTuple(args(0).asInstanceOf[GroupElementValue],
- args(1).asInstanceOf[GroupElementValue],
- args(2).asInstanceOf[GroupElementValue],
- args(3).asInstanceOf[GroupElementValue])
- }
- )
- )
-
- registerClassEntry(classOf[Downcast[_,_]],
- constructors = Array(
- mkConstructor(Array(classOf[Value[_]], classOf[SNumericType])) { args =>
- new Downcast(args(0).asInstanceOf[Value[SNumericType]], args(1).asInstanceOf[SNumericType])
- }
- )
- )
-
- registerClassEntry(classOf[EQ[_]],
- constructors = Array(
- mkConstructor(Array(classOf[Value[_]], classOf[Value[_]])) { args =>
- new EQ(args(0).asInstanceOf[SAnyValue], args(1).asInstanceOf[SAnyValue])
- }
- )
- )
-
- registerClassEntry(classOf[Exponentiate],
- constructors = Array(
- mkConstructor(Array(classOf[Value[_]], classOf[Value[_]])) { args =>
- new Exponentiate(args(0).asInstanceOf[GroupElementValue], args(1).asInstanceOf[BigIntValue])
- }
- )
- )
-
- registerClassEntry(classOf[GE[_]],
- constructors = Array(
- mkConstructor(Array(classOf[Value[_]], classOf[Value[_]])) { args =>
- new GE(args(0).asInstanceOf[SAnyValue], args(1).asInstanceOf[SAnyValue])
- }
- )
- )
-
- registerClassEntry(classOf[GT[_]],
- constructors = Array(
- mkConstructor(Array(classOf[Value[_]], classOf[Value[_]])) { args =>
- new GT(args(0).asInstanceOf[SAnyValue], args(1).asInstanceOf[SAnyValue])
- }
- )
- )
-
- registerClassEntry(classOf[If[_]],
- constructors = Array(
- mkConstructor(Array(classOf[Value[_]], classOf[Value[_]], classOf[Value[_]])) { args =>
- new If(args(0).asInstanceOf[BoolValue], args(1).asInstanceOf[SAnyValue], args(2).asInstanceOf[SAnyValue])
- }
- )
- )
-
- registerClassEntry(classOf[LE[_]],
- constructors = Array(
- mkConstructor(Array(classOf[Value[_]], classOf[Value[_]])) { args =>
- new LE(args(0).asInstanceOf[SAnyValue], args(1).asInstanceOf[SAnyValue])
- }
- )
- )
-
- registerClassEntry(classOf[LT[_]],
- constructors = Array(
- mkConstructor(Array(classOf[Value[_]], classOf[Value[_]])) { args =>
- new LT(args(0).asInstanceOf[SAnyValue], args(1).asInstanceOf[SAnyValue])
- }
- )
- )
-
- registerClassEntry(classOf[LogicalNot],
- constructors = Array(
- mkConstructor(Array(classOf[Value[_]])) { args =>
- new LogicalNot(args(0).asInstanceOf[BoolValue])
- }
- )
- )
-
- registerClassEntry(classOf[MultiplyGroup],
- constructors = Array(
- mkConstructor(Array(classOf[Value[_]], classOf[Value[_]])) { args =>
- new MultiplyGroup(args(0).asInstanceOf[GroupElementValue], args(1).asInstanceOf[GroupElementValue])
- }
- )
- )
-
- registerClassEntry(classOf[NEQ[_]],
- constructors = Array(
- mkConstructor(Array(classOf[Value[_]], classOf[Value[_]])) { args =>
- new NEQ(args(0).asInstanceOf[SAnyValue], args(1).asInstanceOf[SAnyValue])
- }
- )
- )
-
- registerClassEntry(classOf[Negation[_]],
- constructors = Array(
- mkConstructor(Array(classOf[Value[_]])) { args =>
- new Negation(args(0).asInstanceOf[SAnyValue])
- }
- )
- )
-
- registerClassEntry(classOf[OR],
- constructors = Array(
- mkConstructor(Array(classOf[Value[_]])) { args =>
- new OR(args(0).asInstanceOf[Value[SBooleanArray]])
- }
- )
- )
-
- { val clazz = SAvlTree.getClass
- registerClassEntry(clazz,
- methods = Map(
- mkMethod(clazz, "update_eval", Array[Class[_]](classOf[MethodCall], classOf[AvlTree], classOf[Coll[_]], classOf[Coll[_]], classOf[ErgoTreeEvaluator])) { (obj, args) =>
- obj.asInstanceOf[SAvlTree.type].update_eval(args(0).asInstanceOf[MethodCall],
- args(1).asInstanceOf[AvlTree],
- args(2).asInstanceOf[KeyValueColl],
- args(3).asInstanceOf[Coll[Byte]])(args(4).asInstanceOf[ErgoTreeEvaluator])
- },
- mkMethod(clazz, "contains_eval", Array[Class[_]](classOf[MethodCall], classOf[AvlTree], classOf[Coll[_]], classOf[Coll[_]], classOf[ErgoTreeEvaluator])) { (obj, args) =>
- obj.asInstanceOf[SAvlTree.type].contains_eval(args(0).asInstanceOf[MethodCall],
- args(1).asInstanceOf[AvlTree],
- args(2).asInstanceOf[Coll[Byte]],
- args(3).asInstanceOf[Coll[Byte]])(args(4).asInstanceOf[ErgoTreeEvaluator])
- },
- mkMethod(clazz, "get_eval", Array[Class[_]](classOf[MethodCall], classOf[AvlTree], classOf[Coll[_]], classOf[Coll[_]], classOf[ErgoTreeEvaluator])) { (obj, args) =>
- obj.asInstanceOf[SAvlTree.type].get_eval(args(0).asInstanceOf[MethodCall],
- args(1).asInstanceOf[AvlTree],
- args(2).asInstanceOf[Coll[Byte]],
- args(3).asInstanceOf[Coll[Byte]])(args(4).asInstanceOf[ErgoTreeEvaluator])
- },
- mkMethod(clazz, "getMany_eval", Array[Class[_]](classOf[MethodCall], classOf[AvlTree], classOf[Coll[_]], classOf[Coll[_]], classOf[ErgoTreeEvaluator])) { (obj, args) =>
- obj.asInstanceOf[SAvlTree.type].getMany_eval(args(0).asInstanceOf[MethodCall],
- args(1).asInstanceOf[AvlTree],
- args(2).asInstanceOf[Coll[Coll[Byte]]],
- args(3).asInstanceOf[Coll[Byte]])(args(4).asInstanceOf[ErgoTreeEvaluator])
- },
- mkMethod(clazz, "remove_eval", Array[Class[_]](classOf[MethodCall], classOf[AvlTree], classOf[Coll[_]], classOf[Coll[_]], classOf[ErgoTreeEvaluator])) { (obj, args) =>
- obj.asInstanceOf[SAvlTree.type].remove_eval(args(0).asInstanceOf[MethodCall],
- args(1).asInstanceOf[AvlTree],
- args(2).asInstanceOf[Coll[Coll[Byte]]],
- args(3).asInstanceOf[Coll[Byte]])(args(4).asInstanceOf[ErgoTreeEvaluator])
- },
- mkMethod(clazz, "insert_eval", Array[Class[_]](classOf[MethodCall], classOf[AvlTree], classOf[Coll[_]], classOf[Coll[_]], classOf[ErgoTreeEvaluator])) { (obj, args) =>
- obj.asInstanceOf[SAvlTree.type].insert_eval(args(0).asInstanceOf[MethodCall],
- args(1).asInstanceOf[AvlTree],
- args(2).asInstanceOf[KeyValueColl],
- args(3).asInstanceOf[Coll[Byte]])(args(4).asInstanceOf[ErgoTreeEvaluator])
- }
- )
- )
- }
-
- { val clazz = SCollection.getClass
- registerClassEntry(clazz,
- methods = Map(
- mkMethod(clazz, "zip_eval", Array[Class[_]](classOf[MethodCall], classOf[Coll[_]], classOf[Coll[_]], classOf[ErgoTreeEvaluator])) { (obj, args) =>
- obj.asInstanceOf[SCollection.type].zip_eval(args(0).asInstanceOf[MethodCall],
- args(1).asInstanceOf[Coll[Any]],
- args(2).asInstanceOf[Coll[Any]])(args(3).asInstanceOf[ErgoTreeEvaluator])
- },
- mkMethod(clazz, "getOrElse_eval", Array[Class[_]](classOf[MethodCall], classOf[Coll[_]], classOf[Int], classOf[java.lang.Object], classOf[ErgoTreeEvaluator])) { (obj, args) =>
- obj.asInstanceOf[SCollection.type].getOrElse_eval(args(0).asInstanceOf[MethodCall],
- args(1).asInstanceOf[Coll[Any]],
- args(2).asInstanceOf[Int],
- args(3).asInstanceOf[Any])(args(4).asInstanceOf[ErgoTreeEvaluator])
- },
- mkMethod(clazz, "patch_eval", Array[Class[_]](classOf[MethodCall], classOf[Coll[_]], classOf[Int], classOf[Coll[_]], classOf[Int], classOf[ErgoTreeEvaluator])) { (obj, args) =>
- obj.asInstanceOf[SCollection.type].patch_eval(args(0).asInstanceOf[MethodCall],
- args(1).asInstanceOf[Coll[Any]],
- args(2).asInstanceOf[Int],
- args(3).asInstanceOf[Coll[Any]],
- args(4).asInstanceOf[Int])(args(5).asInstanceOf[ErgoTreeEvaluator])
- },
- mkMethod(clazz, "map_eval", Array[Class[_]](classOf[MethodCall], classOf[Coll[_]], classOf[Function1[_,_]], classOf[ErgoTreeEvaluator])) { (obj, args) =>
- obj.asInstanceOf[SCollection.type].map_eval(args(0).asInstanceOf[MethodCall],
- args(1).asInstanceOf[Coll[Any]],
- args(2).asInstanceOf[Any => Any])(args(3).asInstanceOf[ErgoTreeEvaluator])
- },
- mkMethod(clazz, "updated_eval", Array[Class[_]](classOf[MethodCall], classOf[Coll[_]], classOf[Int], classOf[java.lang.Object], classOf[ErgoTreeEvaluator])) { (obj, args) =>
- obj.asInstanceOf[SCollection.type].updated_eval(args(0).asInstanceOf[MethodCall],
- args(1).asInstanceOf[Coll[Any]],
- args(2).asInstanceOf[Int],
- args(3))(args(4).asInstanceOf[ErgoTreeEvaluator])
- },
- mkMethod(clazz, "indexOf_eval", Array[Class[_]](classOf[MethodCall], classOf[Coll[_]], classOf[java.lang.Object], classOf[Int], classOf[ErgoTreeEvaluator])) { (obj, args) =>
- obj.asInstanceOf[SCollection.type].indexOf_eval(args(0).asInstanceOf[MethodCall],
- args(1).asInstanceOf[Coll[Any]], args(2), args(3).asInstanceOf[Int])(args(4).asInstanceOf[ErgoTreeEvaluator])
- },
- mkMethod(clazz, "updateMany_eval", Array[Class[_]](classOf[MethodCall], classOf[Coll[_]], classOf[Coll[_]], classOf[Coll[_]], classOf[ErgoTreeEvaluator])) { (obj, args) =>
- obj.asInstanceOf[SCollection.type].updateMany_eval(args(0).asInstanceOf[MethodCall],
- args(1).asInstanceOf[Coll[Any]],
- args(2).asInstanceOf[Coll[Int]],
- args(3).asInstanceOf[Coll[Any]])(args(4).asInstanceOf[ErgoTreeEvaluator])
- },
- mkMethod(clazz, "indices_eval", Array[Class[_]](classOf[MethodCall], classOf[Coll[_]], classOf[ErgoTreeEvaluator])) { (obj, args) =>
- obj.asInstanceOf[SCollection.type].indices_eval(args(0).asInstanceOf[MethodCall],
- args(1).asInstanceOf[Coll[Any]])(args(2).asInstanceOf[ErgoTreeEvaluator])
- },
- mkMethod(clazz, "flatMap_eval", Array[Class[_]](classOf[MethodCall], classOf[Coll[_]], classOf[Function1[_,_]], classOf[ErgoTreeEvaluator])) { (obj, args) =>
- obj.asInstanceOf[SCollection.type].flatMap_eval(args(0).asInstanceOf[MethodCall],
- args(1).asInstanceOf[Coll[Any]], args(2).asInstanceOf[Any => Coll[Any]])(args(3).asInstanceOf[ErgoTreeEvaluator])
- }
- )
- )
- }
-
- registerClassEntry(classOf[SCollectionType[_]],
- constructors = Array(
- mkConstructor(Array(classOf[SType])) { args =>
- new SCollectionType(args(0).asInstanceOf[SType])
- }
- )
- )
-
- { val clazz = SGlobal.getClass
- registerClassEntry(clazz,
- methods = Map(
- mkMethod(clazz, "xor_eval", Array[Class[_]](classOf[MethodCall], classOf[SigmaDslBuilder], classOf[Coll[_]], classOf[Coll[_]], classOf[ErgoTreeEvaluator])) { (obj, args) =>
- obj.asInstanceOf[SGlobal.type].xor_eval(args(0).asInstanceOf[MethodCall],
- args(1).asInstanceOf[SigmaDslBuilder],
- args(2).asInstanceOf[Coll[Byte]],
- args(3).asInstanceOf[Coll[Byte]])(args(4).asInstanceOf[ErgoTreeEvaluator])
- }
- )
- )
- }
-
- registerClassEntry(classOf[SOption[_]],
- constructors = Array(
- mkConstructor(Array(classOf[SType])) { args =>
- new SOption(args(0).asInstanceOf[SType])
- }
- )
- )
-
- registerClassEntry(classOf[STuple],
- constructors = Array(
- mkConstructor(Array(classOf[IndexedSeq[_]])) { args =>
- new STuple(args(0).asInstanceOf[IndexedSeq[SType]])
- }
- )
- )
-
- registerClassEntry(classOf[SigmaAnd],
- constructors = Array(
- mkConstructor(Array(classOf[Seq[_]])) { args =>
- new SigmaAnd(args(0).asInstanceOf[Seq[SigmaPropValue]])
- }
- )
- )
-
- registerClassEntry(classOf[SigmaOr],
- constructors = Array(
- mkConstructor(Array(classOf[Seq[_]])) { args =>
- new SigmaOr(args(0).asInstanceOf[Seq[SigmaPropValue]])
- }
- )
- )
-
- registerClassEntry(classOf[SubstConstants[_]],
- constructors = Array(
- mkConstructor(Array(classOf[Value[_]], classOf[Value[_]], classOf[Value[_]])) { args =>
- new SubstConstants(args(0).asInstanceOf[Value[SByteArray]],
- args(1).asInstanceOf[Value[SIntArray]],
- args(2).asInstanceOf[CollectionValue[SType]])
- }
- )
- )
-
- registerClassEntry(classOf[Upcast[_,_]],
- constructors = Array(
- mkConstructor(Array(classOf[Value[_]], classOf[SNumericType])) { args =>
- new Upcast(args(0).asInstanceOf[Value[SNumericType]], args(1).asInstanceOf[SNumericType])
- }
- )
- )
-
- registerClassEntry(classOf[BlockValue],
- constructors = Array(
- mkConstructor(Array(classOf[IndexedSeq[_]], classOf[Value[_]])) { args =>
- new BlockValue(args(0).asInstanceOf[IndexedSeq[BlockItem]], args(1).asInstanceOf[SValue])
- }
- )
- )
-
- registerClassEntry(classOf[ConcreteCollection[_]],
- constructors = Array(
- mkConstructor(Array(classOf[Seq[_]], classOf[SType])) { args =>
- new ConcreteCollection(args(0).asInstanceOf[Seq[SValue]], args(1).asInstanceOf[SType])
- }
- )
- )
-
- registerClassEntry(classOf[FuncValue],
- constructors = Array(
- mkConstructor(Array(classOf[IndexedSeq[_]], classOf[Value[_]])) { args =>
- new FuncValue(args(0).asInstanceOf[IndexedSeq[(Int, SType)]], args(1).asInstanceOf[SValue])
- }
- )
- )
-
- registerClassEntry(classOf[Tuple],
- constructors = Array(
- mkConstructor(Array(classOf[IndexedSeq[_]])) { args =>
- new Tuple(args(0).asInstanceOf[IndexedSeq[SValue]])
- }
- )
- )
-
- registerClassEntry(classOf[ValDef],
- constructors = Array(
- mkConstructor(Array(classOf[Int], classOf[Seq[_]], classOf[Value[_]])) { args =>
- new ValDef(args(0).asInstanceOf[Int], args(1).asInstanceOf[Seq[STypeVar]], args(2).asInstanceOf[SValue])
- }
- )
- )
-
- registerClassEntry(classOf[Apply],
- constructors = Array(
- mkConstructor(Array(classOf[Value[_]], classOf[IndexedSeq[_]])) { args =>
- new Apply(args(0).asInstanceOf[SValue], args(1).asInstanceOf[IndexedSeq[SValue]])
- }
- )
- )
-
- registerClassEntry(classOf[ApplyTypes],
- constructors = Array(
- mkConstructor(Array(classOf[Value[_]], classOf[Seq[_]])) { args =>
- new ApplyTypes(args(0).asInstanceOf[SValue], args(1).asInstanceOf[Seq[SType]])
- }
- )
- )
-
- registerClassEntry(classOf[Block],
- constructors = Array(
- mkConstructor(Array(classOf[Seq[_]], classOf[Value[_]])) { args =>
- new Block(args(0).asInstanceOf[Seq[Val]], args(1).asInstanceOf[SValue])
- }
- )
- )
-
- registerClassEntry(classOf[Lambda],
- constructors = Array(
- mkConstructor(Array(classOf[Seq[_]], classOf[IndexedSeq[_]], classOf[SType], classOf[Option[_]])) { args =>
- new Lambda(args(0).asInstanceOf[Seq[STypeParam]],
- args(1).asInstanceOf[IndexedSeq[(String, SType)]],
- args(2).asInstanceOf[SType],
- args(3).asInstanceOf[Option[SValue]])
- }
- )
- )
-
- registerClassEntry(classOf[MethodCall],
- constructors = Array(
- mkConstructor(Array(classOf[Value[_]], classOf[SMethod], classOf[IndexedSeq[_]], classOf[scala.collection.immutable.Map[_,_]])) { args =>
- new MethodCall(args(0).asInstanceOf[SValue],
- args(1).asInstanceOf[SMethod],
- args(2).asInstanceOf[IndexedSeq[SValue]],
- args(3).asInstanceOf[Map[STypeVar,SType]])
- }
- )
- )
-
- registerClassEntry(classOf[MethodCallLike],
- constructors = Array(
- mkConstructor(Array(classOf[Value[_]], classOf[java.lang.String], classOf[IndexedSeq[_]], classOf[SType])) { args =>
- new MethodCallLike(args(0).asInstanceOf[SValue],
- args(1).asInstanceOf[String],
- args(2).asInstanceOf[IndexedSeq[SValue]],
- args(3).asInstanceOf[SType])
- }
- )
- )
-
- registerClassEntry(classOf[Select],
- constructors = Array(
- mkConstructor(Array(classOf[Value[_]], classOf[java.lang.String], classOf[Option[_]])) { args =>
- new Select(args(0).asInstanceOf[SValue], args(1).asInstanceOf[String], args(2).asInstanceOf[Option[SType]])
- }
- )
- )
-
- registerClassEntry(classOf[ValNode],
- constructors = Array(
- mkConstructor(Array(classOf[java.lang.String], classOf[SType], classOf[Value[_]])) { args =>
- new ValNode(args(0).asInstanceOf[String], args(1).asInstanceOf[SType], args(2).asInstanceOf[SValue])
- }
- )
- )
-
- registerClassEntry(classOf[Append[_]],
- constructors = Array(
- mkConstructor(Array(classOf[Value[_]], classOf[Value[_]])) { args =>
- new Append(args(0).asInstanceOf[CollectionValue[SType]], args(1).asInstanceOf[CollectionValue[SType]])
- }
- )
- )
-
- registerClassEntry(classOf[ByIndex[_]],
- constructors = Array(
- mkConstructor(Array(classOf[Value[_]], classOf[Value[_]], classOf[Option[_]])) { args =>
- new ByIndex(args(0).asInstanceOf[CollectionValue[SType]],
- args(1).asInstanceOf[IntValue], args(2).asInstanceOf[Option[SValue]])
- }
- )
- )
-
- registerClassEntry(classOf[Exists[_]],
- constructors = Array(
- mkConstructor(Array(classOf[Value[_]], classOf[Value[_]])) { args =>
- new Exists(args(0).asInstanceOf[CollectionValue[SType]], args(1).asInstanceOf[Value[SFunc]])
- }
- )
- )
-
- registerClassEntry(classOf[ExtractAmount],
- constructors = Array(
- mkConstructor(Array(classOf[Value[_]])) { args =>
- new ExtractAmount(args(0).asInstanceOf[BoxValue])
- }
- )
- )
-
- registerClassEntry(classOf[ExtractBytesWithNoRef],
- constructors = Array(
- mkConstructor(Array(classOf[Value[_]])) { args =>
- new ExtractBytesWithNoRef(args(0).asInstanceOf[BoxValue])
- }
- )
- )
-
- registerClassEntry(classOf[ExtractCreationInfo],
- constructors = Array(
- mkConstructor(Array(classOf[Value[_]])) { args =>
- new ExtractCreationInfo(args(0).asInstanceOf[BoxValue])
- }
- )
- )
-
- registerClassEntry(classOf[ExtractId],
- constructors = Array(
- mkConstructor(Array(classOf[Value[_]])) { args =>
- new ExtractId(args(0).asInstanceOf[BoxValue])
- }
- )
- )
-
- registerClassEntry(classOf[ExtractRegisterAs[_]],
- constructors = Array(
- mkConstructor(Array(classOf[Value[_]], classOf[org.ergoplatform.ErgoBox.RegisterId], classOf[SOption[_]])) { args =>
- new ExtractRegisterAs(args(0).asInstanceOf[BoxValue], args(1).asInstanceOf[RegisterId], args(2).asInstanceOf[SOption[SAny.type]])
- }
- )
- )
-
- registerClassEntry(classOf[ExtractScriptBytes],
- constructors = Array(
- mkConstructor(Array(classOf[Value[_]])) { args =>
- new ExtractScriptBytes(args(0).asInstanceOf[BoxValue])
- }
- )
- )
-
- registerClassEntry(classOf[Filter[_]],
- constructors = Array(
- mkConstructor(Array(classOf[Value[_]], classOf[Value[_]])) { args =>
- new Filter(args(0).asInstanceOf[CollectionValue[SType]], args(1).asInstanceOf[Value[SFunc]])
- }
- )
- )
-
- registerClassEntry(classOf[Fold[_,_]],
- constructors = Array(
- mkConstructor(Array(classOf[Value[_]], classOf[Value[_]], classOf[Value[_]])) { args =>
- new Fold(args(0).asInstanceOf[CollectionValue[SType]],
- args(1).asInstanceOf[SValue], args(2).asInstanceOf[Value[SFunc]])
- }
- )
- )
-
- registerClassEntry(classOf[ForAll[_]],
- constructors = Array(
- mkConstructor(Array(classOf[Value[_]], classOf[Value[_]])) { args =>
- new ForAll(args(0).asInstanceOf[CollectionValue[SType]], args(1).asInstanceOf[Value[SFunc]])
- }
- )
- )
-
- registerClassEntry(classOf[MapCollection[_,_]],
- constructors = Array(
- mkConstructor(Array(classOf[Value[_]], classOf[Value[_]])) { args =>
- new MapCollection(args(0).asInstanceOf[CollectionValue[SType]], args(1).asInstanceOf[Value[SFunc]])
- }
- )
- )
-
- registerClassEntry(classOf[OptionGet[_]],
- constructors = Array(
- mkConstructor(Array(classOf[Value[_]])) { args =>
- new OptionGet(args(0).asInstanceOf[Value[SOption[SType]]])
- }
- )
- )
-
- registerClassEntry(classOf[OptionGetOrElse[_]],
- constructors = Array(
- mkConstructor(Array(classOf[Value[_]], classOf[Value[_]])) { args =>
- new OptionGetOrElse(args(0).asInstanceOf[Value[SOption[SType]]], args(1).asInstanceOf[SValue])
- }
- )
- )
-
- registerClassEntry(classOf[OptionIsDefined[_]],
- constructors = Array(
- mkConstructor(Array(classOf[Value[_]])) { args =>
- new OptionIsDefined(args(0).asInstanceOf[Value[SOption[SType]]])
- }
- )
- )
-
- registerClassEntry(classOf[SelectField],
- constructors = Array(
- mkConstructor(Array(classOf[Value[_]], classOf[Byte])) { args =>
- new SelectField(args(0).asInstanceOf[Value[STuple]], args(1).asInstanceOf[Byte])
- }
- )
- )
-
- registerClassEntry(classOf[SigmaPropBytes],
- constructors = Array(
- mkConstructor(Array(classOf[Value[_]])) { args =>
- new SigmaPropBytes(args(0).asInstanceOf[SigmaPropValue])
- }
- )
- )
-
- registerClassEntry(classOf[SizeOf[_]],
- constructors = Array(
- mkConstructor(Array(classOf[Value[_]])) { args =>
- new SizeOf(args(0).asInstanceOf[CollectionValue[SType]])
- }
- )
- )
-
- registerClassEntry(classOf[Slice[_]],
- constructors = Array(
- mkConstructor(Array(classOf[Value[_]], classOf[Value[_]], classOf[Value[_]])) { args =>
- new Slice(args(0).asInstanceOf[CollectionValue[SType]],
- args(1).asInstanceOf[IntValue], args(2).asInstanceOf[IntValue])
- }
- )
- )
}
diff --git a/interpreter/shared/src/main/scala/sigmastate/SigSerializer.scala b/interpreter/shared/src/main/scala/sigmastate/SigSerializer.scala
index 20341cbcc6..fabd120d1c 100644
--- a/interpreter/shared/src/main/scala/sigmastate/SigSerializer.scala
+++ b/interpreter/shared/src/main/scala/sigmastate/SigSerializer.scala
@@ -1,19 +1,19 @@
-package sigmastate
+package sigma.serialization
-import sigmastate.crypto.{BigIntegers, GF2_192_Poly}
+import debox.cfor
import scorex.util.encode.Base16
-import sigmastate.Values.SigmaBoolean
-import sigmastate.crypto.DLogProtocol.{ProveDlog, SecondDLogProverMessage}
-import sigmastate.crypto.VerifierMessage.Challenge
-import sigmastate.crypto.{CryptoConstants, ProveDHTuple, SecondDHTupleProverMessage}
-import sigmastate.interpreter.ErgoTreeEvaluator.{fixedCostOp, perItemCostOp}
-import sigmastate.interpreter.{ErgoTreeEvaluator, NamedDesc, OperationCostInfo}
-import sigmastate.serialization.SigmaSerializer
+import sigma.Extensions.ArrayOps
+import sigma.ast.{FixedCost, JitCost, NamedDesc, OperationCostInfo, PerItemCost}
+import sigma.crypto.{BigIntegers, CryptoConstants}
+import sigma.data.{CAND, COR, CTHRESHOLD, ProveDHTuple, ProveDlog, SigmaBoolean}
import sigma.util.safeNewArray
-import sigmastate.utils.{Helpers, SigmaByteReader, SigmaByteWriter}
-import debox.cfor
-import sigmastate.eval.Extensions.ArrayOps
-import sigmastate.exceptions.SerializerException
+import sigmastate.{CAndUncheckedNode, COrUncheckedNode, CThresholdUncheckedNode, NoProof, UncheckedDiffieHellmanTuple, UncheckedSchnorr, UncheckedSigmaTree, UncheckedTree}
+import sigmastate.crypto.DLogProtocol.SecondDLogProverMessage
+import sigmastate.crypto.VerifierMessage.Challenge
+import sigmastate.crypto.{GF2_192_Poly, SecondDHTupleProverMessage}
+import sigmastate.interpreter.CErgoTreeEvaluator.{fixedCostOp, perItemCostOp}
+import sigmastate.interpreter.CErgoTreeEvaluator
+import sigmastate.utils.Helpers
/** Contains implementation of signature (aka proof) serialization.
*
@@ -27,7 +27,7 @@ class SigSerializer {
val hashSize = CryptoConstants.soundnessBits / 8
/** Number of bytes to represent any group element as byte array */
- val order = CryptoConstants.groupSize
+ val order = sigma.crypto.groupSize
/** Recursively traverses the given node and serializes challenges and prover messages
* to the given writer.
@@ -119,7 +119,7 @@ class SigSerializer {
* the execution.
* @return An instance of [[UncheckedTree]] i.e. either [[NoProof]] or [[UncheckedSigmaTree]]
*/
- def parseAndComputeChallenges(exp: SigmaBoolean, proof: Array[Byte])(implicit E: ErgoTreeEvaluator): UncheckedTree = {
+ def parseAndComputeChallenges(exp: SigmaBoolean, proof: Array[Byte])(implicit E: CErgoTreeEvaluator): UncheckedTree = {
if (proof.isEmpty)
NoProof
else {
@@ -181,7 +181,7 @@ class SigSerializer {
def parseAndComputeChallenges(
exp: SigmaBoolean,
r: SigmaByteReader,
- challengeOpt: Challenge = null)(implicit E: ErgoTreeEvaluator): UncheckedSigmaTree = {
+ challengeOpt: Challenge = null)(implicit E: CErgoTreeEvaluator): UncheckedSigmaTree = {
// Verifier Step 2: Let e_0 be the challenge in the node here (e_0 is called "challenge" in the code)
val challenge = if (challengeOpt == null) {
Challenge @@ readBytesChecked(r, hashSize,
diff --git a/interpreter/shared/src/main/scala/sigmastate/UncheckedTree.scala b/interpreter/shared/src/main/scala/sigmastate/UncheckedTree.scala
index a8b9bf4faf..2072b2e647 100644
--- a/interpreter/shared/src/main/scala/sigmastate/UncheckedTree.scala
+++ b/interpreter/shared/src/main/scala/sigmastate/UncheckedTree.scala
@@ -1,9 +1,9 @@
package sigmastate
-import sigmastate.crypto.DLogProtocol.{FirstDLogProverMessage, ProveDlog, SecondDLogProverMessage}
+import sigma.data.{ProveDHTuple, ProveDlog}
+import sigmastate.crypto.DLogProtocol.{FirstDLogProverMessage, SecondDLogProverMessage}
import sigmastate.crypto.VerifierMessage.Challenge
-import sigmastate.crypto.{FirstDHTupleProverMessage, ProveDHTuple, SecondDHTupleProverMessage}
-import sigmastate.crypto.GF2_192_Poly
+import sigmastate.crypto.{FirstDHTupleProverMessage, GF2_192_Poly, SecondDHTupleProverMessage}
sealed trait UncheckedTree extends ProofTree
diff --git a/interpreter/shared/src/main/scala/sigmastate/UnprovenTree.scala b/interpreter/shared/src/main/scala/sigmastate/UnprovenTree.scala
index 4e45c230f2..4324dfdd09 100644
--- a/interpreter/shared/src/main/scala/sigmastate/UnprovenTree.scala
+++ b/interpreter/shared/src/main/scala/sigmastate/UnprovenTree.scala
@@ -1,18 +1,18 @@
package sigmastate
-import java.math.BigInteger
-import sigmastate.Values.{ErgoTree, SigmaBoolean, SigmaPropConstant}
-import sigmastate.crypto.DLogProtocol.{FirstDLogProverMessage, ProveDlog}
-import sigmastate.crypto.VerifierMessage.Challenge
-import sigmastate.crypto.{FirstDHTupleProverMessage, FirstProverMessage, ProveDHTuple}
-import sigmastate.interpreter.{ErgoTreeEvaluator, NamedDesc, OperationCostInfo}
-import sigmastate.interpreter.ErgoTreeEvaluator.fixedCostOp
-import sigmastate.serialization.ErgoTreeSerializer.DefaultSerializer
-import sigmastate.serialization.SigmaSerializer
-import sigmastate.utils.SigmaByteWriter
import debox.cfor
-import sigmastate.crypto.GF2_192_Poly
-import scala.language.existentials
+import sigma.data.{CAND, COR, CTHRESHOLD, ProveDHTuple, ProveDlog, SigmaBoolean, SigmaLeaf}
+import sigma.ast.ErgoTree.ZeroHeader
+import sigma.ast.{ErgoTree, FixedCost, JitCost, NamedDesc, OperationCostInfo, SigmaPropConstant}
+import sigma.eval.ErgoTreeEvaluator
+import sigmastate.crypto.DLogProtocol.FirstDLogProverMessage
+import sigmastate.crypto.VerifierMessage.Challenge
+import sigmastate.crypto.{FirstDHTupleProverMessage, FirstProverMessage, GF2_192_Poly}
+import sigmastate.interpreter.CErgoTreeEvaluator.fixedCostOp
+import sigma.serialization.ErgoTreeSerializer.DefaultSerializer
+import sigma.serialization.{SigmaByteWriter, SigmaSerializer}
+
+import java.math.BigInteger
object ConjectureType extends Enumeration {
val AndConjecture = Value(0)
@@ -255,7 +255,7 @@ object FiatShamirTree {
case _: UncheckedDiffieHellmanTuple | _: UnprovenDiffieHellmanTuple => ToBytes_DHT
}
fixedCostOp(costInfo) {
- val propTree = ErgoTree.withSegregation(SigmaPropConstant(l.proposition))
+ val propTree = ErgoTree.withSegregation(ZeroHeader, SigmaPropConstant(l.proposition))
val propBytes = DefaultSerializer.serializeErgoTree(propTree)
val commitmentBytes = l.commitmentOpt.get.bytes
w.put(leafPrefix)
diff --git a/interpreter/shared/src/main/scala/sigmastate/Values.scala b/interpreter/shared/src/main/scala/sigmastate/Values.scala
deleted file mode 100644
index df79471ee8..0000000000
--- a/interpreter/shared/src/main/scala/sigmastate/Values.scala
+++ /dev/null
@@ -1,1497 +0,0 @@
-package sigmastate
-
-import java.math.BigInteger
-import java.util.{Arrays, Objects}
-import sigma.kiama.rewriting.Rewriter.{count, everywherebu, strategy}
-import org.ergoplatform.settings.ErgoAlgos
-import org.ergoplatform.validation.ValidationException
-import sigma.data.{Nullable, RType}
-import sigma.util.CollectionUtil._
-import sigmastate.SCollection.{SByteArray, SIntArray}
-import sigmastate.crypto.CryptoConstants.EcPointType
-import sigmastate.interpreter.{CompanionDesc, ErgoTreeEvaluator, Interpreter, NamedDesc}
-import sigmastate.serialization._
-import sigmastate.serialization.OpCodes._
-import sigmastate.TrivialProp.{FalseProp, TrueProp}
-import sigmastate.Values.ErgoTree.substConstants
-import sigmastate.crypto.DLogProtocol.ProveDlog
-import sigmastate.crypto.{CryptoConstants, ProveDHTuple}
-import sigmastate.lang.Terms._
-import sigmastate.utxo._
-import sigmastate.eval._
-import sigmastate.eval.Extensions._
-import sigma.util.Extensions.ByteOps
-import sigmastate.interpreter.ErgoTreeEvaluator._
-import debox.cfor
-import scorex.util.encode.Base16
-import sigmastate.exceptions.InterpreterException
-
-import scala.language.implicitConversions
-import scala.reflect.ClassTag
-import sigmastate.lang.CheckingSigmaBuilder._
-import sigmastate.serialization.ErgoTreeSerializer.DefaultSerializer
-import sigmastate.serialization.transformers.ProveDHTupleSerializer
-import sigmastate.utils.{SigmaByteReader, SigmaByteWriter}
-import sigma.{AvlTree, Coll, Colls, Header, PreHeader, _}
-import sigmastate.lang.SourceContext
-import sigma.util.safeNewArray
-
-import scala.collection.compat.immutable.ArraySeq
-import scala.collection.mutable
-
-object Values {
- /** Force initialization of reflection. */
- val reflection = InterpreterReflection
-
- type SValue = Value[SType]
-
- /** Base class for all ErgoTree expression nodes.
- * @see [[sigmastate.Values.ErgoTree]]
- */
- abstract class Value[+S <: SType] extends SigmaNode {
- /** The companion node descriptor with opCode, cost and other metadata. */
- def companion: ValueCompanion
-
- /** Unique id of the node class used in serialization of ErgoTree. */
- def opCode: OpCode = companion.opCode
-
- /** The type of the value represented by this node. If the value is an operation it is
- * the type of operation result. */
- def tpe: S
-
- /** Every value represents an operation and that operation can be associated with a function type,
- * describing functional meaning of the operation, kind of operation signature.
- * Thus, we can obtain global operation identifiers by combining Value.opName with Value.opType,
- * so that if (v1.opName == v2.opName) && (v1.opType == v2.opType) then v1 and v2 are functionally
- * point-wise equivalent.
- * This in particular means that if two _different_ ops have the same opType they _should_ have
- * different opNames.
- * Thus defined op ids are used in a v4.x Cost Model - a table of all existing primitives coupled with
- * performance parameters.
- * */
- def opType: SFunc
-
- /** Name of the operation. */
- def opName: String = this.getClass.getSimpleName
-
- /** Transforms this expression to SigmaProp expression or throws an exception. */
- def toSigmaProp: SigmaPropValue = this match {
- case b if b.tpe == SBoolean => BoolToSigmaProp(this.asBoolValue)
- case p if p.tpe == SSigmaProp => p.asSigmaProp
- case _ => sys.error(s"Expected SBoolean or SSigmaProp typed value, but was: $this")
- }
-
- /** Parser has some source information like line,column in the text. We need to keep it up until RuntimeCosting.
- * The way to do this is to add Nullable property to every Value. Since Parser is always using SigmaBuilder
- * to create nodes,
- * Adding additional (implicit source: SourceContext) parameter to every builder method would pollute its API
- * and also doesn't make sence during deserialization, where Builder is also used.
- * We can assume some indirect mechanism to pass current source context into every mkXXX method of Builder.
- * We can pass it using `scala.util.DynamicVariable` by wrapping each mkXXX call into `withValue { }` calls.
- * The same will happen in Typer.
- * We can take sourceContext from untyped nodes and use it while creating typed nodes.
- * And we can make sourceContext of every Value writeOnce value, i.e. it will be Nullable.Null by default,
- * but can be set afterwards, but only once.
- * This property will not participate in equality and other operations, so will be invisible for existing code.
- * But Builder can use it to set sourceContext if it is present.
- */
- private[sigmastate] var _sourceContext: Nullable[SourceContext] = Nullable.None
- def sourceContext: Nullable[SourceContext] = _sourceContext
- def sourceContext_=(srcCtx: Nullable[SourceContext]): Unit =
- if (_sourceContext.isEmpty) {
- _sourceContext = srcCtx
- } else {
- sys.error("_sourceContext can be set only once")
- }
-
- /** Defines an evaluation semantics of this tree node (aka Value or expression) in the given data environment.
- * Should be implemented by all the ErgoTree nodes (aka operations).
- * Thus, the ErgoTree interpreter implementation consists of combined implementations of this method.
- * NOTE, this method shouldn't be called directly, instead use `evalTo` method.
- *
- * @param E Evaluator which defines evaluation context, cost accumulator, settings etc.
- * @param env immutable map, which binds variables (given by ids) to the values
- * @return the data value which is the result of evaluation
- */
- protected def eval(env: DataEnv)(implicit E: ErgoTreeEvaluator): Any =
- sys.error(s"Should be overriden in ${this.getClass}: $this")
-
- /** Evaluates this node to the value of the given expected type.
- * This method should called from all `eval` implementations.
- *
- * @tparam T expected type of the resulting value
- * @param E Evaluator which defines evaluation context, cost accumulator, settings etc.
- * @param env immutable map, which binds variables (given by ids) to the values
- * @return the data value which is the result of evaluation
- */
- @inline
- final def evalTo[T](env: DataEnv)(implicit E: ErgoTreeEvaluator): T = {
- if (E.settings.isMeasureOperationTime) E.profiler.onBeforeNode(this)
- val v = eval(env)
- if (E.settings.isMeasureOperationTime) E.profiler.onAfterNode(this)
- v.asInstanceOf[T]
- }
-
- /** Add the cost given by the kind to the accumulator and associate it with this operation
- * node.
- */
- @inline
- final def addCost(costKind: FixedCost)(implicit E: ErgoTreeEvaluator): Unit = {
- E.addCost(costKind, this.companion.opDesc)
- }
-
- /** Add the cost given by the descriptor to the accumulator and associate it with this operation
- * node.
- */
- @inline
- final def addCost[R](costKind: TypeBasedCost, tpe: SType)(block: () => R)(implicit E: ErgoTreeEvaluator): R = {
- E.addTypeBasedCost(costKind, tpe, this.companion.opDesc)(block)
- }
-
- /** Add the cost of a repeated operation to the accumulator and associate it with this
- * operation. The number of items (loop iterations) is known in advance (like in
- * Coll.map operation)
- *
- * @param costKind cost descriptor of the operation
- * @param nItems number of operations known in advance (before loop execution)
- */
- @inline
- final def addSeqCostNoOp(costKind: PerItemCost, nItems: Int)
- (implicit E: ErgoTreeEvaluator): Unit = {
- E.addSeqCostNoOp(costKind, nItems, this.companion.opDesc)
- }
-
- /** Add the cost of a repeated operation to the accumulator and associate it with this
- * operation. The number of items (loop iterations) is known in advance (like in
- * Coll.map operation)
- *
- * @param costKind cost descriptor of the operation
- * @param nItems number of operations known in advance (before loop execution)
- * @param block operation executed under the given cost
- * @tparam R result type of the operation
- */
- @inline
- final def addSeqCost[R](costKind: PerItemCost, nItems: Int)
- (block: () => R)(implicit E: ErgoTreeEvaluator): R = {
- E.addSeqCost(costKind, nItems, this.companion.opDesc)(block)
- }
- }
-
- object Value {
- type PropositionCode = Byte
-
- implicit def liftByte (n: Byte) : Value[SByte.type] = ByteConstant(n)
- implicit def liftShort(n: Short): Value[SShort.type] = ShortConstant(n)
- implicit def liftInt (n: Int) : Value[SInt.type] = IntConstant(n)
- implicit def liftLong (n: Long) : Value[SLong.type] = LongConstant(n)
-
- implicit def liftByteArray(arr: Array[Byte]): Value[SByteArray] = ByteArrayConstant(arr)
-
- implicit def liftBigInt(arr: BigInt): Value[SBigInt.type] = BigIntConstant(arr)
-
- implicit def liftGroupElement(g: GroupElement): Value[SGroupElement.type] = GroupElementConstant(g)
- implicit def liftECPoint(g: EcPointType): Value[SGroupElement.type] = GroupElementConstant(g)
-
- implicit def liftSigmaProp(g: SigmaProp): Value[SSigmaProp.type] = SigmaPropConstant(g)
- implicit def liftSigmaBoolean(sb: SigmaBoolean): Value[SSigmaProp.type] = SigmaPropConstant(SigmaDsl.SigmaProp(sb))
-
- object Typed {
- def unapply(v: SValue): Option[(SValue, SType)] = Some((v, v.tpe))
- }
- def notSupportedError(v: Any, opName: String) =
- throw new IllegalArgumentException(s"Method $opName is not supported for node $v")
-
- /** Immutable empty array of values. Can be used to avoid allocation. */
- val EmptyArray = Array.empty[SValue]
-
- /** Immutable empty Seq of values. Can be used to avoid allocation. */
- val EmptySeq: IndexedSeq[SValue] = EmptyArray
-
- /** Traverses the given expression tree and counts the number of deserialization
- * operations. If it is non-zero, returns true. */
- def hasDeserialize(exp: SValue): Boolean = {
- val deserializeNode: PartialFunction[Any, Int] = {
- case _: DeserializeContext[_] => 1
- case _: DeserializeRegister[_] => 1
- }
- val c = count(deserializeNode)(exp)
- c > 0
- }
-
- def typeError(node: SValue, evalResult: Any) = {
- val tpe = node.tpe
- throw new InterpreterException(
- s"""Invalid type returned by evaluator:
- | expression: $node
- | expected type: $tpe
- | resulting value: $evalResult
- """.stripMargin)
- }
-
- def typeError(tpe: SType, evalResult: Any) = {
- throw new InterpreterException(
- s"""Invalid type returned by evaluator:
- | expected type: $tpe
- | resulting value: $evalResult
- """.stripMargin)
- }
-
- def checkType(node: SValue, evalResult: Any) = {
- val tpe = node.tpe
- if (!SType.isValueOfType(evalResult, tpe))
- typeError(node, evalResult)
- }
-
- def checkType(tpe: SType, evalResult: Any) = {
- if (!SType.isValueOfType(evalResult, tpe))
- typeError(tpe, evalResult)
- }
- }
-
- /** Base class for all companion objects which are used as operation descriptors. */
- trait ValueCompanion extends SigmaNodeCompanion {
- import ValueCompanion._
- /** Unique id of the node class used in serialization of ErgoTree. */
- def opCode: OpCode
-
- /** Returns cost descriptor of this operation. */
- def costKind: CostKind
-
- override def toString: String = s"${this.getClass.getSimpleName}(${opCode.toUByte})"
-
- def typeName: String = this.getClass.getSimpleName.replace("$", "")
-
- def init() {
- if (this.opCode != 0 && _allOperations.contains(this.opCode))
- throw sys.error(s"Operation $this already defined")
- _allOperations += (this.opCode -> this)
- }
-
- init()
-
- val opDesc = CompanionDesc(this)
- }
- object ValueCompanion {
- private val _allOperations: mutable.HashMap[Byte, ValueCompanion] = mutable.HashMap.empty
- lazy val allOperations = _allOperations.toMap
- }
-
- /** Should be inherited by companion objects of operations with fixed cost kind. */
- trait FixedCostValueCompanion extends ValueCompanion {
- /** Returns cost descriptor of this operation. */
- override def costKind: FixedCost
- }
-
- /** Should be inherited by companion objects of operations with per-item cost kind. */
- trait PerItemCostValueCompanion extends ValueCompanion {
- /** Returns cost descriptor of this operation. */
- override def costKind: PerItemCost
- }
-
- /** Base class for ErgoTree nodes which represents a data value which has already been
- * evaluated and no further evaluation (aka reduction) is necessary by the interpreter.
- *
- * @see Constant, ConcreteCollection, Tuple
- */
- abstract class EvaluatedValue[+S <: SType] extends Value[S] {
- /** The evaluated data value of the corresponding underlying data type. */
- val value: S#WrappedType
-
- override def opType: SFunc = {
- val resType = tpe match {
- case ct : SCollection[_] =>
- SCollection(ct.typeParams.head.ident)
- case ft @ SFunc(_, _, _) =>
- ft.getGenericType
- case _ => tpe
- }
- SFunc(ArraySeq.empty, resType)
- }
- }
-
- /** Base class for all constant literals whose data value is already known and never
- * changes.
- * @see ConstantNode
- */
- abstract class Constant[+S <: SType] extends EvaluatedValue[S]
-
- /** ErgoTree node which represents data literals, i.e. data values embedded in an
- * expression.
- *
- * @param value data value of the underlying Scala type
- * @param tpe type descriptor of the data value and also the type of the value
- * represented by this node.
- * @see Constant
- */
- case class ConstantNode[S <: SType](value: S#WrappedType, tpe: S) extends Constant[S] {
- require(sigmastate.crypto.Platform.isCorrectType(value, tpe),
- s"Invalid type of constant value $value, expected type $tpe")
- override def companion: ValueCompanion = Constant
- override def opCode: OpCode = companion.opCode
- override def opName: String = s"Const"
-
- protected final override def eval(env: DataEnv)(implicit E: ErgoTreeEvaluator): Any = {
- addCost(Constant.costKind)
- value
- }
-
- override def equals(obj: scala.Any): Boolean = (obj != null) && (this.eq(obj.asInstanceOf[AnyRef]) || (obj match {
- case c: Constant[_] => tpe == c.tpe && Objects.deepEquals(value, c.value)
- case _ => false
- }))
-
- override def hashCode(): Int = Arrays.deepHashCode(Array(value.asInstanceOf[AnyRef], tpe))
-
- override def toString: String = tpe.asInstanceOf[SType] match {
- case SGroupElement if value.isInstanceOf[GroupElement] =>
- s"ConstantNode(${showECPoint(value.asInstanceOf[GroupElement])},$tpe)"
- case SGroupElement =>
- sys.error(s"Invalid value in Constant($value, $tpe)")
- case SInt => s"IntConstant($value)"
- case SLong => s"LongConstant($value)"
- case SBoolean if value == true => "TrueLeaf"
- case SBoolean if value == false => "FalseLeaf"
- case _ => s"ConstantNode($value,$tpe)"
- }
- }
-
- object Constant extends FixedCostValueCompanion {
- override def opCode: OpCode = ConstantCode
- /** Cost of: returning value from Constant node. */
- override val costKind = FixedCost(JitCost(5))
-
- /** Immutable empty array, can be used to save allocations in many places. */
- val EmptyArray = Array.empty[Constant[SType]]
-
- /** Immutable empty IndexedSeq, can be used to save allocations in many places. */
- val EmptySeq: IndexedSeq[Constant[SType]] = Array.empty[Constant[SType]]
-
- /** Helper factory method. */
- def apply[S <: SType](value: S#WrappedType, tpe: S): Constant[S] = ConstantNode(value, tpe)
-
- /** Recognizer of Constant tree nodes used in patterns. */
- def unapply[S <: SType](v: EvaluatedValue[S]): Option[(S#WrappedType, S)] = v match {
- case ConstantNode(value, tpe) => Some((value, tpe))
- case _ => None
- }
-
- }
-
- /** Placeholder for a constant in ErgoTree. Zero based index in ErgoTree.constants array. */
- case class ConstantPlaceholder[S <: SType](id: Int, override val tpe: S) extends Value[S] {
- def opType = SFunc(SInt, tpe)
- override def companion: ValueCompanion = ConstantPlaceholder
- override protected def eval(env: DataEnv)(implicit E: ErgoTreeEvaluator): Any = {
- val c = E.constants(id)
- addCost(ConstantPlaceholder.costKind)
- val res = c.value
- Value.checkType(c, res)
- res
- }
- }
- object ConstantPlaceholder extends ValueCompanion {
- override def opCode: OpCode = ConstantPlaceholderCode
- /** Cost of: accessing Constant in array by index. */
- override val costKind = FixedCost(JitCost(1))
- }
-
- trait NotReadyValue[S <: SType] extends Value[S] {
- }
-
- /** Base class for references to context variables. */
- trait ContextVariable[S <: SType] extends NotReadyValue[S] {
- }
-
- /** Reference a context variable by id. */
- trait TaggedVariable[T <: SType] extends ContextVariable[T] {
- val varId: Byte
- }
-
- case class TaggedVariableNode[T <: SType](varId: Byte, override val tpe: T)
- extends TaggedVariable[T] {
- override def companion = TaggedVariable
- def opType: SFunc = Value.notSupportedError(this, "opType")
- }
-
- object TaggedVariable extends ValueCompanion {
- override def opCode: OpCode = TaggedVariableCode
- override def costKind: CostKind = FixedCost(JitCost(1))
- def apply[T <: SType](varId: Byte, tpe: T): TaggedVariable[T] =
- TaggedVariableNode(varId, tpe)
- }
-
- /** High-level interface to internal representation of Unit constants in ErgoTree. */
- object UnitConstant {
- /** ErgoTree node that represent a literal of Unit type. It is global immutable value
- * which should be reused wherever necessary to avoid allocations.
- */
- val instance = apply()
-
- /** Constucts a fresh new instance of Unit literal node. */
- def apply() = Constant[SUnit.type]((), SUnit)
-
- /** Recognizer to pattern match on Unit constant literal nodes (aka Unit constants). */
- def unapply(node: SValue): Boolean = node match {
- case ConstantNode(_, SUnit) => true
- case _ => false
- }
- }
-
- type BoolValue = Value[SBoolean.type]
- type ByteValue = Value[SByte.type]
- type ShortValue = Value[SShort.type]
- type IntValue = Value[SInt.type]
- type LongValue = Value[SLong.type]
- type StringValue = Value[SString.type]
- type BigIntValue = Value[SBigInt.type]
- type BoxValue = Value[SBox.type]
- type GroupElementValue = Value[SGroupElement.type]
- type SigmaPropValue = Value[SSigmaProp.type]
- type AvlTreeValue = Value[SAvlTree.type]
- type SAnyValue = Value[SAny.type]
-
- type ByteConstant = Constant[SByte.type]
- type ShortConstant = Constant[SShort.type]
- type IntConstant = Constant[SInt.type]
- type LongConstant = Constant[SLong.type]
- type StringConstant = Constant[SString.type]
- type BigIntConstant = Constant[SBigInt.type]
- type BoxConstant = Constant[SBox.type]
- type GroupElementConstant = Constant[SGroupElement.type]
- type SigmaPropConstant = Constant[SSigmaProp.type]
- type AvlTreeConstant = Constant[SAvlTree.type]
-
- object ByteConstant {
- def apply(value: Byte): Constant[SByte.type] = Constant[SByte.type](value, SByte)
- }
- object ShortConstant {
- def apply(value: Short): Constant[SShort.type] = Constant[SShort.type](value, SShort)
- }
- object IntConstant {
- def apply(value: Int): Constant[SInt.type] = Constant[SInt.type](value, SInt)
- def unapply(v: SValue): Option[Int] = v match {
- case Constant(value: Int, SInt) => Some(value)
- case _ => None
- }
-
- def Zero = IntConstant(0)
- }
- object LongConstant {
- def apply(value: Long): Constant[SLong.type] = Constant[SLong.type](value, SLong)
- def unapply(v: SValue): Option[Long] = v match {
- case Constant(value: Long, SLong) => Some(value)
- case _ => None
- }
- }
- object BigIntConstant {
- def apply(value: BigInt): Constant[SBigInt.type] = Constant[SBigInt.type](value, SBigInt)
- def apply(value: BigInteger): Constant[SBigInt.type] = Constant[SBigInt.type](SigmaDsl.BigInt(value), SBigInt)
- def apply(value: Long): Constant[SBigInt.type] = Constant[SBigInt.type](SigmaDsl.BigInt(BigInteger.valueOf(value)), SBigInt)
- }
-
- object StringConstant {
- def apply(value: String): Constant[SString.type] = Constant[SString.type](value, SString)
- def unapply(v: SValue): Option[String] = v match {
- case Constant(value: String, SString) => Some(value)
- case _ => None
- }
- }
-
- object BoxConstant {
- def apply(value: Box): Constant[SBox.type] = Constant[SBox.type](value, SBox)
- }
-
- object GroupElementConstant {
- def apply(value: EcPointType): Constant[SGroupElement.type] = apply(SigmaDsl.GroupElement(value))
- def apply(value: GroupElement): Constant[SGroupElement.type] = Constant[SGroupElement.type](value, SGroupElement)
- def unapply(v: SValue): Option[GroupElement] = v match {
- case Constant(value: GroupElement, SGroupElement) => Some(value)
- case _ => None
- }
- }
-
- val FalseSigmaProp = SigmaPropConstant(SigmaDsl.SigmaProp(TrivialProp.FalseProp))
- val TrueSigmaProp = SigmaPropConstant(SigmaDsl.SigmaProp(TrivialProp.TrueProp))
-
- implicit def boolToSigmaProp(b: BoolValue): SigmaPropValue = BoolToSigmaProp(b)
-
- object SigmaPropConstant {
- def apply(value: SigmaProp): Constant[SSigmaProp.type] = Constant[SSigmaProp.type](value, SSigmaProp)
- def apply(value: SigmaBoolean): Constant[SSigmaProp.type] = Constant[SSigmaProp.type](SigmaDsl.SigmaProp(value), SSigmaProp)
- def unapply(v: SValue): Option[SigmaProp] = v match {
- case Constant(value: SigmaProp, SSigmaProp) => Some(value)
- case _ => None
- }
- }
-
- object AvlTreeConstant {
- def apply(value: AvlTree): Constant[SAvlTree.type] = Constant[SAvlTree.type](value, SAvlTree)
- }
-
- object PreHeaderConstant {
- def apply(value: PreHeader): Constant[SPreHeader.type] = Constant[SPreHeader.type](value, SPreHeader)
- def unapply(v: SValue): Option[PreHeader] = v match {
- case Constant(value: PreHeader, SPreHeader) => Some(value)
- case _ => None
- }
- }
-
- object HeaderConstant {
- def apply(value: Header): Constant[SHeader.type] = Constant[SHeader.type](value, SHeader)
- def unapply(v: SValue): Option[Header] = v match {
- case Constant(value: Header, SHeader) => Some(value)
- case _ => None
- }
- }
-
- trait NotReadyValueInt extends NotReadyValue[SInt.type] {
- override def tpe = SInt
- }
-
- trait NotReadyValueLong extends NotReadyValue[SLong.type] {
- override def tpe = SLong
- }
-
- trait NotReadyValueBigInt extends NotReadyValue[SBigInt.type] {
- override def tpe = SBigInt
- }
-
- type TaggedBoolean = TaggedVariable[SBoolean.type]
- type TaggedByte = TaggedVariable[SByte.type]
- type TaggedShort = TaggedVariable[SShort.type]
- type TaggedInt = TaggedVariable[SInt.type]
- type TaggedLong = TaggedVariable[SLong.type]
- type TaggedBigInt = TaggedVariable[SBigInt.type]
- type TaggedBox = TaggedVariable[SBox.type]
- type TaggedGroupElement = TaggedVariable[SGroupElement.type]
- type TaggedSigmaProp = TaggedVariable[SSigmaProp.type]
- type TaggedAvlTree = TaggedVariable[SAvlTree.type]
- type TaggedByteArray = TaggedVariable[SCollection[SByte.type]]
-
- def TaggedBox(id: Byte): Value[SBox.type] = mkTaggedVariable(id, SBox)
- def TaggedAvlTree(id: Byte): Value[SAvlTree.type] = mkTaggedVariable(id, SAvlTree)
-
- /** Base type for evaluated tree nodes of Coll type. */
- trait EvaluatedCollection[T <: SType, C <: SCollection[T]] extends EvaluatedValue[C] {
- /** Type descriptor of the collection elements. */
- def elementType: T
- }
-
- type CollectionConstant[T <: SType] = Constant[SCollection[T]]
- type CollectionValue[T <: SType] = Value[SCollection[T]]
-
- object CollectionConstant {
- def apply[T <: SType](value: Coll[T#WrappedType], elementType: T): Constant[SCollection[T]] =
- Constant[SCollection[T]](value, SCollection(elementType))
- def unapply[T <: SType](node: Value[SCollection[T]]): Option[(Coll[T#WrappedType], T)] = node match {
- case c: Constant[SCollection[a]] @unchecked if c.tpe.isCollection =>
- val v = c.value.asInstanceOf[Coll[T#WrappedType]]
- val t = c.tpe.elemType
- Some((v, t))
- case _ => None
- }
- }
-
- val ByteArrayTypeCode = (SCollectionType.CollectionTypeCode + SByte.typeCode).toByte
-
- object ByteArrayConstant {
- def apply(value: Coll[Byte]): CollectionConstant[SByte.type] = CollectionConstant[SByte.type](value, SByte)
- def apply(value: Array[Byte]): CollectionConstant[SByte.type] = CollectionConstant[SByte.type](value.toColl, SByte)
- def unapply(node: SValue): Option[Coll[Byte]] = node match {
- case coll: CollectionConstant[SByte.type] @unchecked => coll match {
- case CollectionConstant(arr, SByte) => Some(arr)
- case _ => None
- }
- case _ => None
- }
- }
-
- object ShortArrayConstant {
- def apply(value: Coll[Short]): CollectionConstant[SShort.type] = CollectionConstant[SShort.type](value, SShort)
- def apply(value: Array[Short]): CollectionConstant[SShort.type] = CollectionConstant[SShort.type](value.toColl, SShort)
- def unapply(node: SValue): Option[Coll[Short]] = node match {
- case coll: CollectionConstant[SShort.type] @unchecked => coll match {
- case CollectionConstant(arr, SShort) => Some(arr)
- case _ => None
- }
- case _ => None
- }
- }
-
- object IntArrayConstant {
- def apply(value: Coll[Int]): CollectionConstant[SInt.type] = CollectionConstant[SInt.type](value, SInt)
- def apply(value: Array[Int]): CollectionConstant[SInt.type] = CollectionConstant[SInt.type](value.toColl, SInt)
- def unapply(node: SValue): Option[Coll[Int]] = node match {
- case coll: CollectionConstant[SInt.type] @unchecked => coll match {
- case CollectionConstant(arr, SInt) => Some(arr)
- case _ => None
- }
- case _ => None
- }
- }
-
- object LongArrayConstant {
- def apply(value: Coll[Long]): CollectionConstant[SLong.type] = CollectionConstant[SLong.type](value, SLong)
- def apply(value: Array[Long]): CollectionConstant[SLong.type] = CollectionConstant[SLong.type](value.toColl, SLong)
- def unapply(node: SValue): Option[Coll[Long]] = node match {
- case coll: CollectionConstant[SLong.type] @unchecked => coll match {
- case CollectionConstant(arr, SLong) => Some(arr)
- case _ => None
- }
- case _ => None
- }
- }
-
- object BigIntArrayConstant {
- def apply(value: Coll[BigInt]): CollectionConstant[SBigInt.type] = CollectionConstant[SBigInt.type](value, SBigInt)
- def apply(value: Array[BigInt]): CollectionConstant[SBigInt.type] = CollectionConstant[SBigInt.type](value.toColl, SBigInt)
- def unapply(node: SValue): Option[Coll[BigInt]] = node match {
- case coll: CollectionConstant[SBigInt.type] @unchecked => coll match {
- case CollectionConstant(arr, SBigInt) => Some(arr)
- case _ => None
- }
- case _ => None
- }
- }
-
- val BoolArrayTypeCode = (SCollectionType.CollectionTypeCode + SBoolean.typeCode).toByte
-
- object BoolArrayConstant {
- def apply(value: Coll[Boolean]): CollectionConstant[SBoolean.type] = CollectionConstant[SBoolean.type](value, SBoolean)
- def apply(value: Array[Boolean]): CollectionConstant[SBoolean.type] = apply(value.toColl)
- def unapply(node: SValue): Option[Coll[Boolean]] = node match {
- case coll: CollectionConstant[SBoolean.type] @unchecked => coll match {
- case CollectionConstant(arr, SBoolean) => Some(arr)
- case _ => None
- }
- case _ => None
- }
- }
-
- trait NotReadyValueByteArray extends NotReadyValue[SByteArray] {
- override def tpe = SByteArray
- }
-
- trait NotReadyValueAvlTree extends NotReadyValue[SAvlTree.type] {
- override def tpe = SAvlTree
- }
-
- /** ErgoTree node that represents the operation of obtaining the generator of elliptic curve group.
- * The generator g of the group is an element of the group such that, when written
- * multiplicative form, every element of the group is a power of g.
- */
- case object GroupGenerator extends EvaluatedValue[SGroupElement.type] with ValueCompanion {
- override def opCode: OpCode = OpCodes.GroupGeneratorCode
- override val costKind = FixedCost(JitCost(10))
- override def tpe = SGroupElement
- override val value = SigmaDsl.GroupElement(CryptoConstants.dlogGroup.generator)
- override def companion = this
- protected final override def eval(env: DataEnv)(implicit E: ErgoTreeEvaluator): Any = {
- addCost(costKind)
- SigmaDsl.groupGenerator
- }
- }
-
-
- trait NotReadyValueGroupElement extends NotReadyValue[SGroupElement.type] {
- override def tpe = SGroupElement
- }
-
- type BooleanConstant = Constant[SBoolean.type]
-
- object BooleanConstant {
- def fromBoolean(v: Boolean): BooleanConstant = if (v) TrueLeaf else FalseLeaf
- def apply(value: Boolean): BooleanConstant = Constant[SBoolean.type](value, SBoolean)
- def unapply(v: SValue): Option[Boolean] = v match {
- case Constant(value: Boolean, SBoolean) => Some(value)
- case _ => None
- }
- }
-
- /** ErgoTree node which represents `true` literal. */
- object TrueLeaf extends ConstantNode[SBoolean.type](true, SBoolean) with ValueCompanion {
- override def companion = this
- override def opCode: OpCode = TrueCode
- override def costKind: FixedCost = Constant.costKind
- override def toString: String = "TrueLeaf"
- }
-
- /** ErgoTree node which represents `false` literal. */
- object FalseLeaf extends ConstantNode[SBoolean.type](false, SBoolean) with ValueCompanion {
- override def companion = this
- override def opCode: OpCode = FalseCode
- override def costKind: FixedCost = Constant.costKind
- override def toString: String = "FalseLeaf"
- }
-
- trait NotReadyValueBoolean extends NotReadyValue[SBoolean.type] {
- override def tpe = SBoolean
- }
-
- /** Algebraic data type of sigma proposition expressions.
- * Values of this type are used as values of SigmaProp type of SigmaScript and SigmaDsl
- */
- trait SigmaBoolean {
- /** Unique id of the node class used in serialization of SigmaBoolean. */
- val opCode: OpCode
- /** Size of the proposition tree (number of nodes). */
- def size: Int
- }
-
- object SigmaBoolean {
- /** Compute total size of the trees in the collection of children. */
- def totalSize(children: Seq[SigmaBoolean]): Int = {
- var res = 0
- val len = children.length
- cfor(0)(_ < len, _ + 1) { i =>
- res += children(i).size
- }
- res
- }
-
- /** HOTSPOT: don't beautify this code */
- object serializer extends SigmaSerializer[SigmaBoolean, SigmaBoolean] {
- val dhtSerializer = ProveDHTupleSerializer(ProveDHTuple.apply)
- val dlogSerializer = ProveDlogSerializer(ProveDlog.apply)
-
- override def serialize(data: SigmaBoolean, w: SigmaByteWriter): Unit = {
- w.put(data.opCode)
- data match {
- case dlog: ProveDlog => dlogSerializer.serialize(dlog, w)
- case dht: ProveDHTuple => dhtSerializer.serialize(dht, w)
- case _: TrivialProp => // besides opCode no additional bytes
- case and: CAND =>
- val nChildren = and.children.length
- w.putUShort(nChildren)
- cfor(0)(_ < nChildren, _ + 1) { i =>
- val c = and.children(i)
- serializer.serialize(c, w)
- }
-
- case or: COR =>
- val nChildren = or.children.length
- w.putUShort(nChildren)
- cfor(0)(_ < nChildren, _ + 1) { i =>
- val c = or.children(i)
- serializer.serialize(c, w)
- }
-
- case th: CTHRESHOLD =>
- w.putUShort(th.k)
- val nChildren = th.children.length
- w.putUShort(nChildren)
- cfor(0)(_ < nChildren, _ + 1) { i =>
- val c = th.children(i)
- serializer.serialize(c, w)
- }
- }
- }
-
- override def parse(r: SigmaByteReader): SigmaBoolean = {
- val depth = r.level
- r.level = depth + 1
- val opCode = r.getByte()
- val res = opCode match {
- case FalseProp.opCode => FalseProp
- case TrueProp.opCode => TrueProp
- case ProveDlogCode => dlogSerializer.parse(r)
- case ProveDiffieHellmanTupleCode => dhtSerializer.parse(r)
- case AndCode =>
- val n = r.getUShort()
- val children = safeNewArray[SigmaBoolean](n)
- cfor(0)(_ < n, _ + 1) { i =>
- children(i) = serializer.parse(r)
- }
- CAND(children)
- case OrCode =>
- val n = r.getUShort()
- val children = safeNewArray[SigmaBoolean](n)
- cfor(0)(_ < n, _ + 1) { i =>
- children(i) = serializer.parse(r)
- }
- COR(children)
- case AtLeastCode =>
- val k = r.getUShort()
- val n = r.getUShort()
- val children = safeNewArray[SigmaBoolean](n)
- cfor(0)(_ < n, _ + 1) { i =>
- children(i) = serializer.parse(r)
- }
- CTHRESHOLD(k, children)
- }
- r.level = r.level - 1
- res
- }
- }
- }
-
- trait NotReadyValueBox extends NotReadyValue[SBox.type] {
- def tpe = SBox
- }
-
- /** ErgoTree node which converts a collection of expressions into a tuple of data values
- * of different types. Each data value of the resulting collection is obtained by
- * evaluating the corresponding expression in `items`. All items may have different
- * types.
- *
- * @param items source collection of expressions
- */
- case class Tuple(items: IndexedSeq[Value[SType]])
- extends EvaluatedValue[STuple] // note, this superclass is required as Tuple can be in a register
- with EvaluatedCollection[SAny.type, STuple] {
- override def companion = Tuple
- override lazy val tpe = STuple(items.map(_.tpe))
- override def opType: SFunc = ???
- override def elementType: SAny.type = SAny
-
- override lazy val value = {
- val xs = items.cast[EvaluatedValue[SAny.type]].map(_.value)
- Colls.fromArray(xs.toArray(SAny.classTag.asInstanceOf[ClassTag[SAny.WrappedType]]))(sigma.AnyType)
- }
-
- protected final override def eval(env: DataEnv)(implicit E: ErgoTreeEvaluator): Any = {
- // in v5.0 version we support only tuples of 2 elements to be equivalent with v4.x
- if (items.length != 2)
- Interpreter.error(s"Invalid tuple $this")
-
- val item0 = items(0)
- val x = item0.evalTo[Any](env)
- Value.checkType(item0, x)
-
- val item1 = items(1)
- val y = item1.evalTo[Any](env)
- Value.checkType(item1, y)
-
- val res = (x, y) // special representation for pairs (to pass directly to Coll primitives)
-
- addCost(Tuple.costKind)
- res
- }
- }
-
- object Tuple extends FixedCostValueCompanion {
- override def opCode: OpCode = TupleCode
- /** Cost of: 1) allocating a new tuple (of limited max size)*/
- override val costKind = FixedCost(JitCost(15))
- def apply(items: Value[SType]*): Tuple = Tuple(items.toIndexedSeq)
- }
-
- /** ErgoTree node which converts a collection of expressions into a collection of data
- * values. Each data value of the resulting collection is obtained by evaluating the
- * corresponding expression in `items`. All items must have the same type.
- *
- * @param items source collection of expressions
- * @param elementType type descriptor of elements in the resulting collection
- */
- case class ConcreteCollection[V <: SType](items: Seq[Value[V]], elementType: V)
- extends EvaluatedCollection[V, SCollection[V]] {
-// TODO uncomment and make sure Ergo works with it, i.e. complex data types are never used for `items`.
-// There is nothing wrong in using List, Vector and other fancy types as a concrete representation
-// of `items`, but these types have sub-optimal performance (2-3x overhead comparing to WrappedArray)
-// which is immediately visible in profile.
-// NOTE, the assert below should be commented before production release.
-// Is it there for debuging only, basically to catch call stacks where the fancy types may
-// occasionally be used.
-// assert(
-// items.isInstanceOf[mutable.WrappedArray[_]] ||
-// items.isInstanceOf[ArrayBuffer[_]] ||
-// items.isInstanceOf[mutable.ArraySeq[_]],
-// s"Invalid types of items ${items.getClass}")
-
- private val isBooleanConstants = elementType == SBoolean && items.forall(_.isInstanceOf[Constant[_]])
- override def companion =
- if (isBooleanConstants) ConcreteCollectionBooleanConstant
- else ConcreteCollection
-
- val tpe = SCollection[V](elementType)
- implicit lazy val tElement: RType[V#WrappedType] = Evaluation.stypeToRType(elementType)
-
- // TODO refactor: this method is not used and can be removed
- lazy val value = {
- val xs = items.cast[EvaluatedValue[V]].map(_.value)
- Colls.fromArray(xs.toArray(elementType.classTag.asInstanceOf[ClassTag[V#WrappedType]]))
- }
-
- protected final override def eval(env: DataEnv)(implicit E: ErgoTreeEvaluator): Any = {
- val len = items.length
- addCost(ConcreteCollection.costKind)
- val is = Array.ofDim[V#WrappedType](len)(tElement.classTag)
- cfor(0)(_ < len, _ + 1) { i =>
- val item = items(i)
- val itemV = item.evalTo[V#WrappedType](env)
- Value.checkType(item, itemV) // necessary because cast to V#WrappedType is erased
- is(i) = itemV
- }
- Colls.fromArray(is)
- }
- }
- object ConcreteCollection extends FixedCostValueCompanion {
- override def opCode: OpCode = ConcreteCollectionCode
- /** Cost of: allocating new collection
- * @see ConcreteCollection_PerItem */
- override val costKind = FixedCost(JitCost(20))
-
- def fromSeq[V <: SType](items: Seq[Value[V]])(implicit tV: V): ConcreteCollection[V] =
- ConcreteCollection(items, tV)
-
- def fromItems[V <: SType](items: Value[V]*)(implicit tV: V): ConcreteCollection[V] =
- ConcreteCollection(items, tV)
- }
- object ConcreteCollectionBooleanConstant extends ValueCompanion {
- override def opCode: OpCode = ConcreteCollectionBooleanConstantCode
- override def costKind = ConcreteCollection.costKind
- }
-
- trait LazyCollection[V <: SType] extends NotReadyValue[SCollection[V]]
-
- implicit class CollectionOps[T <: SType](val coll: Value[SCollection[T]]) extends AnyVal {
- def length: Int = matchCase(_.items.length, _.value.length, _.items.length)
- def items = matchCase(_.items, _ => sys.error(s"Cannot get 'items' property of node $coll"), _.items)
-// def isEvaluatedCollection =
-// coll.evaluated && matchCase(_.items.forall(_.evaluated), _ => true, _.items.forall(_.evaluated))
- def matchCase[R](
- whenConcrete: ConcreteCollection[T] => R,
- whenConstant: CollectionConstant[T] => R,
- whenTuple: Tuple => R
- ): R = coll match {
- case cc: ConcreteCollection[T]@unchecked => whenConcrete(cc)
- case const: CollectionConstant[T]@unchecked => whenConstant(const)
- case tuple: Tuple => whenTuple(tuple)
- case _ => sys.error(s"Unexpected node $coll")
- }
- }
-
- implicit class SigmaPropValueOps(val p: Value[SSigmaProp.type]) extends AnyVal {
- def isProven: Value[SBoolean.type] = SigmaPropIsProven(p)
- def propBytes: Value[SByteArray] = SigmaPropBytes(p)
- def treeWithSegregation: ErgoTree = ErgoTree.withSegregation(p)
- def treeWithSegregation(headerFlags: Byte): ErgoTree =
- ErgoTree.withSegregation(headerFlags, p)
- }
-
- implicit class SigmaBooleanOps(val sb: SigmaBoolean) extends AnyVal {
- def toSigmaProp: SigmaPropValue = SigmaPropConstant(sb)
- def isProven: Value[SBoolean.type] = SigmaPropIsProven(SigmaPropConstant(sb))
- def showToString: String = sb match {
- case ProveDlog(v) =>
- s"ProveDlog(${showECPoint(v)})"
- case ProveDHTuple(gv, hv, uv, vv) =>
- s"ProveDHTuple(${showECPoint(gv)}, ${showECPoint(hv)}, ${showECPoint(uv)}, ${showECPoint(vv)})"
- case _ => sb.toString
- }
- }
-
- sealed trait BlockItem extends NotReadyValue[SType] {
- def id: Int
- def rhs: SValue
- def isValDef: Boolean
- }
- object BlockItem {
- /** Immutable empty array, can be used to save allocations in many places. */
- val EmptyArray = Array.empty[BlockItem]
-
- /** Immutable empty IndexedSeq to save allocations in many places. */
- val EmptySeq: IndexedSeq[BlockItem] = EmptyArray
- }
-
- /** IR node for let-bound expressions `let x = rhs` which is ValDef, or `let f[T] = rhs` which is FunDef.
- * These nodes are used to represent ErgoTrees after common sub-expression elimination.
- * This representation is more compact in serialized form.
- * @param id unique identifier of the variable in the current scope. */
- case class ValDef(override val id: Int,
- tpeArgs: Seq[STypeVar],
- override val rhs: SValue) extends BlockItem {
- require(id >= 0, "id must be >= 0")
- override def companion = if (tpeArgs.isEmpty) ValDef else FunDef
- override def tpe: SType = rhs.tpe
- override def isValDef: Boolean = tpeArgs.isEmpty
- /** This is not used as operation, but rather to form a program structure */
- override def opType: SFunc = Value.notSupportedError(this, "opType")
- }
- object ValDef extends ValueCompanion {
- override def opCode: OpCode = ValDefCode
- override def costKind = Value.notSupportedError(this, "costKind")
- def apply(id: Int, rhs: SValue): ValDef = ValDef(id, Nil, rhs)
- }
- object FunDef extends ValueCompanion {
- override def opCode: OpCode = FunDefCode
- override def costKind = Value.notSupportedError(this, "costKind")
- def unapply(d: BlockItem): Option[(Int, Seq[STypeVar], SValue)] = d match {
- case ValDef(id, targs, rhs) if !d.isValDef => Some((id, targs, rhs))
- case _ => None
- }
- }
-
- /** Special node which represents a reference to ValDef it was introduced as result of
- * CSE. */
- case class ValUse[T <: SType](valId: Int, tpe: T) extends NotReadyValue[T] {
- override def companion = ValUse
- /** This is not used as operation, but rather to form a program structure */
- def opType: SFunc = Value.notSupportedError(this, "opType")
-
- protected final override def eval(env: DataEnv)(implicit E: ErgoTreeEvaluator): Any = {
- addCost(ValUse.costKind)
- val res = env.getOrElse(valId, error(s"cannot resolve $this"))
- Value.checkType(this, res)
- res
- }
- }
- object ValUse extends FixedCostValueCompanion {
- override def opCode: OpCode = ValUseCode
- /** Cost of: 1) Lookup in immutable HashMap by valId: Int 2) alloc of Some(v) */
- override val costKind = FixedCost(JitCost(5))
- }
-
- /** The order of ValDefs in the block is used to assign ids to ValUse(id) nodes
- * For all i: items(i).id == {number of ValDefs preceded in a graph} with respect to topological order.
- * Specific topological order doesn't really matter, what is important is to preserve semantic linkage
- * between ValUse(id) and ValDef with the corresponding id.
- * This convention allow to valid serializing ids because we always serializing and deserializing
- * in a fixed well defined order.
- */
- case class BlockValue(items: IndexedSeq[BlockItem], result: SValue) extends NotReadyValue[SType] {
- override def companion = BlockValue
- def tpe: SType = result.tpe
-
- /** This is not used as operation, but rather to form a program structure */
- def opType: SFunc = Value.notSupportedError(this, "opType")
-
- protected final override def eval(env: DataEnv)(implicit E: ErgoTreeEvaluator): Any = {
- var curEnv = env
- val len = items.length
- addSeqCostNoOp(BlockValue.costKind, len)
- cfor(0)(_ < len, _ + 1) { i =>
- val vd = items(i).asInstanceOf[ValDef]
- val v = vd.rhs.evalTo[Any](curEnv)
- Value.checkType(vd, v)
- E.addFixedCost(FuncValue.AddToEnvironmentDesc_CostKind,
- FuncValue.AddToEnvironmentDesc) {
- curEnv = curEnv + (vd.id -> v)
- }
- }
- val res = result.evalTo[Any](curEnv)
- Value.checkType(result, res)
- res
- }
- }
- object BlockValue extends ValueCompanion {
- override def opCode: OpCode = BlockValueCode
- override val costKind = PerItemCost(
- baseCost = JitCost(1), perChunkCost = JitCost(1), chunkSize = 10)
- }
- /**
- * @param args parameters list, where each parameter has an id and a type.
- * @param body expression, which refers function parameters with ValUse.
- */
- case class FuncValue(args: IndexedSeq[(Int,SType)], body: Value[SType]) extends NotReadyValue[SFunc] {
- import FuncValue._
- override def companion = FuncValue
- lazy val tpe: SFunc = {
- val nArgs = args.length
- val argTypes = new Array[SType](nArgs)
- cfor(0)(_ < nArgs, _ + 1) { i =>
- argTypes(i) = args(i)._2
- }
- SFunc(argTypes, body.tpe)
- }
- /** This is not used as operation, but rather to form a program structure */
- override def opType: SFunc = SFunc(ArraySeq.empty, tpe)
-
- protected final override def eval(env: DataEnv)(implicit E: ErgoTreeEvaluator): Any = {
- addCost(FuncValue.costKind)
- if (args.length == 1) {
- val arg0 = args(0)
- (vArg: Any) => {
- Value.checkType(arg0._2, vArg)
- var env1: DataEnv = null
- E.addFixedCost(AddToEnvironmentDesc_CostKind, AddToEnvironmentDesc) {
- env1 = env + (arg0._1 -> vArg)
- }
- val res = body.evalTo[Any](env1)
- Value.checkType(body, res)
- res
- }
- } else {
- Interpreter.error(s"Function must have 1 argument, but was: $this")
- }
- }
- }
- object FuncValue extends FixedCostValueCompanion {
- val AddToEnvironmentDesc = NamedDesc("AddToEnvironment")
- /** Cost of: adding value to evaluator environment */
- val AddToEnvironmentDesc_CostKind = FixedCost(JitCost(5))
- override def opCode: OpCode = FuncValueCode
- /** Cost of: 1) switch on the number of args 2) allocating a new Scala closure
- * Old cost: ("Lambda", "() => (D1) => R", lambdaCost),*/
- override val costKind = FixedCost(JitCost(5))
- def apply(argId: Int, tArg: SType, body: SValue): FuncValue =
- FuncValue(IndexedSeq((argId,tArg)), body)
- }
-
- implicit class OptionValueOps[T <: SType](val p: Value[SOption[T]]) extends AnyVal {
- def get: Value[T] = OptionGet(p)
- def getOrElse(default: Value[T]): Value[T] = OptionGetOrElse(p, default)
- def isDefined: Value[SBoolean.type] = OptionIsDefined(p)
- }
-
- def GetVarBoolean(varId: Byte): GetVar[SBoolean.type] = GetVar(varId, SBoolean)
- def GetVarByte(varId: Byte): GetVar[SByte.type] = GetVar(varId, SByte)
- def GetVarShort(varId: Byte): GetVar[SShort.type] = GetVar(varId, SShort)
- def GetVarInt(varId: Byte): GetVar[SInt.type] = GetVar(varId, SInt)
- def GetVarLong(varId: Byte): GetVar[SLong.type] = GetVar(varId, SLong)
- def GetVarBigInt(varId: Byte): GetVar[SBigInt.type] = GetVar(varId, SBigInt)
- def GetVarBox(varId: Byte): GetVar[SBox.type] = GetVar(varId, SBox)
- def GetVarSigmaProp(varId: Byte): GetVar[SSigmaProp.type] = GetVar(varId, SSigmaProp)
- def GetVarByteArray(varId: Byte): GetVar[SCollection[SByte.type]] = GetVar(varId, SByteArray)
- def GetVarIntArray(varId: Byte): GetVar[SCollection[SInt.type]] = GetVar(varId, SIntArray)
-
- /** This is alternative representation of ErgoTree expression when it cannot be parsed
- * due to `error`. This is used by the nodes running old versions of code to recognize
- * soft-fork conditions and skip validation of box propositions which are unparsable. */
- case class UnparsedErgoTree(bytes: mutable.WrappedArray[Byte], error: ValidationException)
-
- /** The root of ErgoScript IR. Serialized instances of this class are self sufficient and can be passed around.
- * ErgoTreeSerializer defines top-level serialization format of the scripts.
- * The interpretation of the byte array depend on the first `header` byte, which uses VLQ encoding up to 30 bits.
- * Currently we define meaning for only first byte, which may be extended in future versions.
- * 7 6 5 4 3 2 1 0
- * -------------------------
- * | | | | | | | | |
- * -------------------------
- * Bit 7 == 1 if the header contains more than 1 byte (default == 0)
- * Bit 6 - reserved for GZIP compression (should be 0)
- * Bit 5 == 1 - reserved for context dependent costing (should be = 0)
- * Bit 4 == 1 if constant segregation is used for this ErgoTree (default = 0)
- * (see https://github.com/ScorexFoundation/sigmastate-interpreter/issues/264)
- * Bit 3 == 1 if size of the whole tree is serialized after the header byte (default = 0)
- * Bits 2-0 - language version (current version == 0)
- *
- * Currently we don't specify interpretation for the second and other bytes of the header.
- * We reserve the possibility to extend header by using Bit 7 == 1 and chain additional bytes as in VLQ.
- * Once the new bytes are required, a new version of the language should be created and implemented.
- * That new language will give an interpretation for the new bytes.
- *
- * Consistency between fields is ensured by private constructor and factory methods in `ErgoTree` object.
- * For performance reasons, ErgoTreeSerializer can be configured to perform additional constant segregation.
- * In such a case after deserialization there may be more constants segregated. This is done for example to
- * support caching optimization described in #264 mentioned above.
- *
- * The default behavior of ErgoTreeSerializer is to preserve original structure of ErgoTree and check
- * consistency. In case of any inconsistency the serializer throws exception.
- *
- * @param header the first byte of serialized byte array which determines interpretation of the rest of the array
- *
- * @param constants If isConstantSegregation == true contains the constants for which there may be
- * ConstantPlaceholders in the tree.
- * If isConstantSegregation == false this array should be empty and any placeholder in
- * the tree will lead to exception.
- *
- * @param root On the right side it has valid expression of `SigmaProp` type. Or alternatively,
- * on the left side, it has unparsed bytes along with the ValidationException,
- * which caused the deserializer to fail.
- * `Right(tree)` if isConstantSegregation == true contains ConstantPlaceholder
- * instead of some Constant nodes. Otherwise, it may not contain placeholders.
- * It is possible to have both constants and placeholders in the tree, but for every placeholder
- * there should be a constant in `constants` array.
- * @param givenComplexity structural complexity of the tree or 0 if is not specified at construction time.
- * Access to this private value is provided via `complexity` property.
- * In case of 0, the complexity is computed using ErgoTree deserializer, which can do this.
- * When specified it should be computed as the sum of complexity values taken
- * from ComplexityTable for all tree nodes. It approximates the time needed to process
- * the tree by sigma compiler to obtain cost formula. Overly complex trees can thus
- * be rejected even before compiler starts working.
- * @param propositionBytes original bytes of this tree from which it has been deserialized.
- * If null then the bytes are not provided, and will be lazily generated when `bytes`
- * method is called.
- * These bytes are obtained in two ways:
- * 1) in the ErgoTreeSerializer from Reader
- * 2) in the alternative constructor using ErgoTreeSerializer.serializeErgoTree
- * @param givenDeserialize optional flag, which contains information about presence of
- * deserialization operations in the tree. If it is None, the information is not
- * available. If Some(true) then there are deserialization operations, otherwise
- * the tree doesn't contain deserialization and is eligible
- * for optimized execution.
- * ErgoTreeSerializer parsing method computes the value of
- * this flag and provides it to the constructor.
- */
- case class ErgoTree private[sigmastate](
- header: Byte,
- constants: IndexedSeq[Constant[SType]],
- root: Either[UnparsedErgoTree, SigmaPropValue],
- private val givenComplexity: Int,
- private val propositionBytes: Array[Byte],
- private val givenDeserialize: Option[Boolean]
- ) {
-
- def this(header: Byte,
- constants: IndexedSeq[Constant[SType]],
- root: Either[UnparsedErgoTree, SigmaPropValue]) =
- this(
- header, constants, root, 0,
- propositionBytes = DefaultSerializer.serializeErgoTree(
- ErgoTree(header, constants, root, 0, null, None)
- ),
- givenDeserialize = None
- )
-
- require(isConstantSegregation || constants.isEmpty)
- require(version == 0 || hasSize, s"For newer version the size bit is required: $this")
-
- /** Then it throws the error from UnparsedErgoTree.
- * It does so on every usage of `proposition` because the lazy value remains uninitialized.
- */
- @deprecated("Use toProposition instead", "v2.1")
- lazy val proposition: SigmaPropValue = toProposition(isConstantSegregation)
-
- @inline final def version: Byte = ErgoTree.getVersion(header)
- @inline final def isRightParsed: Boolean = root.isRight
- @inline final def isConstantSegregation: Boolean = ErgoTree.isConstantSegregation(header)
- @inline final def hasSize: Boolean = ErgoTree.hasSize(header)
-
- private[sigmastate] var _bytes: Array[Byte] = propositionBytes
-
- /** Serialized bytes of this tree. */
- final def bytes: Array[Byte] = {
- if (_bytes == null) {
- _bytes = DefaultSerializer.serializeErgoTree(this)
- }
- _bytes
- }
-
- /** Hexadecimal encoded string of ErgoTree.bytes. */
- final def bytesHex: String = ErgoAlgos.encode(bytes)
-
- private var _complexity: Int = givenComplexity
-
- /** Structural complexity estimation of this tree.
- * @see ComplexityTable
- */
- lazy val complexity: Int = {
- if (_complexity == 0) {
- _complexity = DefaultSerializer.deserializeErgoTree(bytes).complexity
- }
- _complexity
- }
-
- private[sigmastate] var _hasDeserialize: Option[Boolean] = givenDeserialize
-
- /** Returns true if the tree contains at least one deserialization operation,
- * false otherwise.
- */
- lazy val hasDeserialize: Boolean = {
- if (_hasDeserialize.isEmpty) {
- _hasDeserialize = Some(root match {
- case Right(p) => Value.hasDeserialize(p)
- case _ => false
- })
- }
- _hasDeserialize.get
- }
-
- /** Serialized proposition expression of SigmaProp type with
- * ConstantPlaceholder nodes not replaced by Constant nodes.
- */
- lazy val template: Array[Byte] = {
- val r = SigmaSerializer.startReader(bytes)
- DefaultSerializer.deserializeHeaderWithTreeBytes(r)._4
- }
-
- /** Base16 encoding of `template` bytes. */
- def templateHex: String = Base16.encode(template)
-
- /** Get proposition expression from this contract.
- * When root.isRight then
- * if replaceConstants == false this is the same as `root.right.get`.
- * Otherwise, it is equivalent to `root.right.get` where all placeholders are replaced by Constants.
- * When root.isLeft then
- * throws the error from UnparsedErgoTree.
- * It does so on every usage of `proposition` because the lazy value remains uninitialized.
- */
- def toProposition(replaceConstants: Boolean): SigmaPropValue = root match {
- case Right(tree) =>
- val prop = if (replaceConstants)
- substConstants(tree, constants).asSigmaProp
- else
- tree
- prop
- case Left(UnparsedErgoTree(_, error)) =>
- throw error
- }
-
- /** The default equality of case class is overridden to exclude `complexity`. */
- override def canEqual(that: Any): Boolean = that.isInstanceOf[ErgoTree]
-
- override def hashCode(): Int = header * 31 + Objects.hash(constants, root)
-
- override def equals(obj: Any): Boolean = (this eq obj.asInstanceOf[AnyRef]) ||
- ((obj.asInstanceOf[AnyRef] != null) && (obj match {
- case other: ErgoTree =>
- other.header == header && other.constants == constants && other.root == root
- case _ => false
- }))
- }
-
- object ErgoTree {
- /** Current version of ErgoTree serialization format (aka bite-code language version)*/
- val VersionFlag: Byte = 0
-
- /** Default value of ErgoTree.header byte */
- val DefaultHeader: Byte = (0 | VersionFlag).toByte
-
- /** Header flag to indicate that constant segregation should be applied. */
- val ConstantSegregationFlag: Byte = 0x10
-
- /** Header flag to indicate that whole size of ErgoTree should be saved before tree content. */
- val SizeFlag: Byte = 0x08
-
- /** Header mask to extract version bits. */
- val VersionMask: Byte = 0x07
-
- /** Default header with constant segregation enabled. */
- val ConstantSegregationHeader: Byte = (DefaultHeader | ConstantSegregationFlag).toByte
-
- /** @return true if the constant segregation flag is set to 1 in the given header byte. */
- @inline final def isConstantSegregation(header: Byte): Boolean = (header & ConstantSegregationFlag) != 0
-
- /** @return true if the size flag is set to 1 in the given header byte. */
- @inline final def hasSize(header: Byte): Boolean = (header & SizeFlag) != 0
-
- /** @return a value of the version bits from the given header byte. */
- @inline final def getVersion(header: Byte): Byte = (header & VersionMask).toByte
-
- /** Update the version bits of the given header byte with the given version value. */
- @inline final def updateVersionBits(header: Byte, version: Byte): Byte = {
- require(version < 8, s"ErgoTree.version should be < 8: $version")
- (header | version).toByte
- }
-
- /** Creates valid header byte with the given version.
- * The SizeFlag is set if version > 0 */
- @inline def headerWithVersion(version: Byte): Byte = {
- // take default header and embedd the given version in it
- var h = updateVersionBits(DefaultHeader, version)
- if (version > 0) {
- // set SizeFlag if version is greater then 0 (see require() in ErgoTree constructor)
- h = (h | ErgoTree.SizeFlag).toByte
- }
- h
- }
-
- /** Substitute [[ConstantPlaceholder]] nodes in the given expression with the constants
- * taken from the given collection.
- * @param root expression to transform
- * @param constants collection of constants to replace placeholders
- * @return new expression without placeholders
- */
- def substConstants(root: SValue, constants: IndexedSeq[Constant[SType]]): SValue = {
- val store = new ConstantStore(constants)
- val substRule = strategy[Any] {
- case ph: ConstantPlaceholder[_] =>
- Some(store.get(ph.id))
- case _ => None
- }
- everywherebu(substRule)(root).fold(root)(_.asInstanceOf[SValue])
- }
-
- /** Create an ErgoTree with the given parameters. */
- def apply(header: Byte, constants: IndexedSeq[Constant[SType]], root: SigmaPropValue): ErgoTree = {
- new ErgoTree(header, constants, Right(root))
- }
-
- val EmptyConstants: IndexedSeq[Constant[SType]] = Array[Constant[SType]]()
-
- /** Create new ErgoTree for the given proposition using the given header flags and
- * without performing constant segregation.
- */
- def withoutSegregation(root: SigmaPropValue): ErgoTree =
- ErgoTree(ErgoTree.DefaultHeader, EmptyConstants, root)
-
- /** Create new ErgoTree for the given proposition using the given header flags and
- * without performing constant segregation.
- */
- def withoutSegregation(headerFlags: Byte, root: SigmaPropValue): ErgoTree =
- ErgoTree((ErgoTree.DefaultHeader | headerFlags).toByte, EmptyConstants, root)
-
- /** Create new ErgoTree for the given proposition using default header.
- * If the property is not a simple constant, then constant segregation is performed.
- */
- implicit def fromProposition(prop: SigmaPropValue): ErgoTree = {
- fromProposition(ErgoTree.DefaultHeader, prop)
- }
-
- /** Create new ErgoTree for the given proposition using the given header flags.
- * If the property is not a simple constant, then constant segregation is performed.
- */
- def fromProposition(headerFlags: Byte, prop: SigmaPropValue): ErgoTree = {
- prop match {
- case SigmaPropConstant(_) => withoutSegregation(headerFlags, prop)
- case _ => withSegregation(headerFlags, prop)
- }
- }
-
- /** Create new ErgoTree for the given sigma proposition using default header and
- * without performing constant segregation.
- */
- implicit def fromSigmaBoolean(pk: SigmaBoolean): ErgoTree = {
- withoutSegregation(pk.toSigmaProp)
- }
-
- /** Create new ErgoTree for the given sigma proposition using the given header flags
- * and without performing constant segregation.
- */
- def fromSigmaBoolean(headerFlags: Byte, pk: SigmaBoolean): ErgoTree = {
- withoutSegregation(headerFlags, pk.toSigmaProp)
- }
-
- /** Build ErgoTree via serialization of the value with ConstantSegregationHeader, constants segregated
- * from the tree and ConstantPlaceholders referring to the segregated constants.
- *
- * This method uses single traverse of the tree to:
- * 1) find and segregate all constants;
- * 2) replace constants with ConstantPlaceholders in the `tree`;
- * 3) write the `tree` to the Writer's buffer obtaining `treeBytes`;
- * 4) deserialize `tree` with ConstantPlaceholders.
- * @param headerFlags additional header flags to combine with
- * ConstantSegregationHeader flag.
- * @param prop expression to be transformed into ErgoTree
- **/
- def withSegregation(headerFlags: Byte, prop: SigmaPropValue): ErgoTree = {
- val constantStore = new ConstantStore()
- val byteWriter = SigmaSerializer.startWriter(constantStore)
- // serialize value and segregate constants into constantStore
- ValueSerializer.serialize(prop, byteWriter)
- val extractedConstants = constantStore.getAll
- val r = SigmaSerializer.startReader(byteWriter.toBytes)
- r.constantStore = new ConstantStore(extractedConstants)
- // deserialize value with placeholders
- val valueWithPlaceholders = ValueSerializer.deserialize(r).asSigmaProp
- val header = (ErgoTree.ConstantSegregationHeader | headerFlags).toByte
- new ErgoTree(header, extractedConstants, Right(valueWithPlaceholders))
- }
-
- /** Create new ErgoTree for the given sigma proposition using default header and
- * also performing constant segregation.
- */
- def withSegregation(prop: SigmaPropValue): ErgoTree =
- withSegregation(DefaultHeader, prop)
-
- /** Deserializes an ErgoTree instance from a hexadecimal string.
- *
- * @param hex a hexadecimal string representing the serialized ErgoTree
- */
- def fromHex(hex: String): ErgoTree = {
- val bytes = Base16.decode(hex).get
- fromBytes(bytes)
- }
-
- /** Deserializes an ErgoTree instance from an array of bytes.
- *
- * @param bytes an array of bytes representing the serialized ErgoTree
- */
- def fromBytes(bytes: Array[Byte]): ErgoTree = {
- ErgoTreeSerializer.DefaultSerializer.deserializeErgoTree(bytes)
- }
-
- }
-
-}
diff --git a/interpreter/shared/src/main/scala/sigmastate/crypto/CryptoFunctions.scala b/interpreter/shared/src/main/scala/sigmastate/crypto/CryptoFunctions.scala
index ff8d395d44..5a579ffb2c 100644
--- a/interpreter/shared/src/main/scala/sigmastate/crypto/CryptoFunctions.scala
+++ b/interpreter/shared/src/main/scala/sigmastate/crypto/CryptoFunctions.scala
@@ -1,6 +1,7 @@
package sigmastate.crypto
import scorex.crypto.hash.Blake2b256
+import sigma.crypto.CryptoConstants
object CryptoFunctions {
lazy val soundnessBytes: Int = CryptoConstants.soundnessBits / 8
diff --git a/interpreter/shared/src/main/scala/sigmastate/crypto/DLogProtocol.scala b/interpreter/shared/src/main/scala/sigmastate/crypto/DLogProtocol.scala
index a078da2ceb..7fa2dae3a1 100644
--- a/interpreter/shared/src/main/scala/sigmastate/crypto/DLogProtocol.scala
+++ b/interpreter/shared/src/main/scala/sigmastate/crypto/DLogProtocol.scala
@@ -1,49 +1,25 @@
package sigmastate.crypto
-import java.math.BigInteger
-
-import sigmastate.Values._
-import Value.PropositionCode
import scorex.util.encode.Base16
-import sigmastate._
-import sigmastate.eval._
+import sigma.crypto.{BigIntegers, EcPointType}
+import sigma.data.ProveDlog
+import sigma.serialization.GroupElementSerializer
+import sigma.crypto.CryptoConstants.dlogGroup
import sigmastate.crypto.VerifierMessage.Challenge
-import CryptoConstants.{EcPointType, dlogGroup}
-import sigmastate.serialization.{OpCodes, GroupElementSerializer}
-import sigmastate.serialization.OpCodes.OpCode
-import sigma.SigmaProp
-object DLogProtocol {
-
- trait DLogSigmaProtocol extends SigmaProtocol[DLogSigmaProtocol] {
- override type A = FirstDLogProverMessage
- override type Z = SecondDLogProverMessage
- }
-
- /** Construct a new SigmaBoolean value representing public key of discrete logarithm signature protocol. */
- case class ProveDlog(value: EcPointType) extends SigmaLeaf {
- override def size: Int = 1
- override val opCode: OpCode = OpCodes.ProveDlogCode
- /** Serialized bytes of the elliptic curve point (using GroupElementSerializer). */
- lazy val pkBytes: Array[Byte] = GroupElementSerializer.toBytes(value)
- }
-
- object ProveDlog {
- val Code: PropositionCode = 102: Byte
- }
+import java.math.BigInteger
- /** Helper extractor to match SigmaProp values and extract ProveDlog out of it. */
- object ProveDlogProp {
- def unapply(p: SigmaProp): Option[ProveDlog] = SigmaDsl.toSigmaBoolean(p) match {
- case d: ProveDlog => Some(d)
- case _ => None
- }
- }
+/** Implementation of sigma protocol steps using discrete logarithm problem in EC group. */
+object DLogProtocol {
+ /** Secret key of discrete logarithm signature protocol.
+ * @param w secret number in [0, q-1]
+ * where q - an order of DLog group.
+ */
case class DLogProverInput(w: BigInteger)
extends SigmaProtocolPrivateInput[ProveDlog] {
- import CryptoConstants.dlogGroup
+ import sigma.crypto.CryptoConstants.dlogGroup
override lazy val publicImage: ProveDlog = {
val g = dlogGroup.generator
@@ -53,7 +29,7 @@ object DLogProtocol {
object DLogProverInput {
- import CryptoConstants.dlogGroup
+ import sigma.crypto.CryptoConstants.dlogGroup
/** Create random secret in a range 0..q-1, where q - an order of DLog group. */
def random(): DLogProverInput = {
@@ -63,8 +39,13 @@ object DLogProtocol {
}
}
+ /** First message of dlog-based sigma protocol.
+ * @param ecData commitment to randomness ecData = G^r, where
+ * G - generator of EC group,
+ * r - random number known only to prover from [0, q-1] range,
+ * where q - order of EC group.
+ */
case class FirstDLogProverMessage(ecData: EcPointType) extends FirstProverMessage {
- override type SP = DLogSigmaProtocol
override def bytes: Array[Byte] = {
GroupElementSerializer.toBytes(ecData)
}
@@ -72,23 +53,35 @@ object DLogProtocol {
override def toString = s"FirstDLogProverMessage(${Base16.encode(bytes)})"
}
- case class SecondDLogProverMessage(z: BigInt) extends SecondProverMessage {
- override type SP = DLogSigmaProtocol
- }
+ /** Second message of dlog-based sigma protocol.
+ * @param z response to the challenge from the verifier
+ * @see responseToChallenge()
+ */
+ case class SecondDLogProverMessage(z: BigInt) extends SecondProverMessage
- object DLogInteractiveProver extends SigmaProtocolProver {
- import CryptoConstants.secureRandom
+ /** Prover operations of dlog-based sigma protocol. */
+ object DLogProver extends SigmaProtocolProver {
+ import sigma.crypto.CryptoConstants.secureRandom
+ /** Generate a first prover message with a commitment to a secret random number. */
def firstMessage(): (BigInteger, FirstDLogProverMessage) = {
- import CryptoConstants.dlogGroup
+ import sigma.crypto.CryptoConstants.dlogGroup
- val qMinusOne = dlogGroup.order.subtract(BigInteger.ONE)
- val r = BigIntegers.createRandomInRange(BigInteger.ZERO, qMinusOne, secureRandom)
- val a = dlogGroup.exponentiate(dlogGroup.generator, r)
+ val qMinusOne = dlogGroup.order.subtract(BigInteger.ONE) // q - 1
+ val r = BigIntegers.createRandomInRange(BigInteger.ZERO, qMinusOne, secureRandom) // r <- [0, q-1]
+ val a = dlogGroup.exponentiate(dlogGroup.generator, r) // g^r
r -> FirstDLogProverMessage(a)
}
+ /** Creates a second message of sigma protocol by computing
+ * `z = rnd + challenge * privateInput.w mod q`, where q - order of EC group.
+ *
+ * @param privateInput secret known only to prover from [0, q-1] range,
+ * @param rnd random number generated by the prover (secret random number used to
+ * compute commitment)
+ * @param challenge from the verifier (also computed by the prover in non-interactive case)
+ */
def secondMessage(privateInput: DLogProverInput, rnd: BigInteger, challenge: Challenge): SecondDLogProverMessage = {
val z = responseToChallenge(privateInput, rnd, challenge)
SecondDLogProverMessage(z)
@@ -117,9 +110,9 @@ object DLogProtocol {
*
* g^z = a*h^e => a = g^z/h^e
*
- * @param proposition
- * @param challenge
- * @param secondMessage
+ * @param proposition proposition being proved
+ * @param challenge challenge from verifier
+ * @param secondMessage prover's response to the challenge
* @return
*/
def computeCommitment(proposition: ProveDlog,
@@ -128,6 +121,7 @@ object DLogProtocol {
val g = dlogGroup.generator
val h = proposition.value
+ // COMPUTE a = g^z / h^e
dlogGroup.multiplyGroupElements(
dlogGroup.exponentiate(g, secondMessage.z.underlying()),
dlogGroup.inverseOf(dlogGroup.exponentiate(h, new BigInteger(1, challenge.toArray))))
diff --git a/interpreter/shared/src/main/scala/sigmastate/crypto/DiffieHellmanTupleProtocol.scala b/interpreter/shared/src/main/scala/sigmastate/crypto/DiffieHellmanTupleProtocol.scala
index a30e187105..ba1a6c2e0a 100644
--- a/interpreter/shared/src/main/scala/sigmastate/crypto/DiffieHellmanTupleProtocol.scala
+++ b/interpreter/shared/src/main/scala/sigmastate/crypto/DiffieHellmanTupleProtocol.scala
@@ -1,21 +1,12 @@
package sigmastate.crypto
-import java.math.BigInteger
-
-import sigmastate.Values.Value.PropositionCode
-import sigmastate._
+import sigma.crypto.{BigIntegers, CryptoConstants, EcPointType}
+import sigma.data.ProveDHTuple
+import sigma.serialization.GroupElementSerializer
import sigmastate.crypto.VerifierMessage.Challenge
-import sigmastate.eval.SigmaDsl
-import CryptoConstants.EcPointType
-import sigmastate.serialization.{OpCodes, GroupElementSerializer}
-import sigmastate.serialization.OpCodes.OpCode
-import sigma.SigmaProp
+import java.math.BigInteger
-trait DiffieHellmanTupleProtocol extends SigmaProtocol[DiffieHellmanTupleProtocol] {
- override type A = FirstDHTupleProverMessage
- override type Z = SecondDHTupleProverMessage
-}
case class DiffieHellmanTupleProverInput(w: BigInteger, commonInput: ProveDHTuple)
extends SigmaProtocolPrivateInput[ProveDHTuple] {
@@ -43,13 +34,10 @@ object DiffieHellmanTupleProverInput {
/** First message of Diffie Hellman tuple sigma protocol.
* @param a commitment to secret randomness `a = g^r`, where `g` is default generator of the group
* @param b commitment to secret randomness `b = h^r`, where `h` is another random generator of the group
- * @see createRandomGenerator in [[sigmastate.crypto.CryptoConstants.dlogGroup]]
+ * @see createRandomGenerator in [[CryptoConstants.dlogGroup]]
*/
case class FirstDHTupleProverMessage(a: EcPointType, b: EcPointType)
extends FirstProverMessage {
-
- override type SP = DiffieHellmanTupleProtocol
-
override def bytes: Array[Byte] = {
GroupElementSerializer.toBytes(a) ++ GroupElementSerializer.toBytes(b)
}
@@ -62,35 +50,9 @@ case class FirstDHTupleProverMessage(a: EcPointType, b: EcPointType)
* `w` is the prover's secret.
* `q` is the group order
*/
-case class SecondDHTupleProverMessage(z: BigInteger) extends SecondProverMessage {
- override type SP = DiffieHellmanTupleProtocol
-}
-
-/** Construct a new SigmaProp value representing public key of Diffie Hellman signature protocol.
- * Common input: (g,h,u,v) */
-case class ProveDHTuple(gv: EcPointType, hv: EcPointType, uv: EcPointType, vv: EcPointType)
- extends SigmaLeaf {
- override val opCode: OpCode = OpCodes.ProveDiffieHellmanTupleCode
- override def size: Int = 4 // one node for each EcPoint
- lazy val g = gv
- lazy val h = hv
- lazy val u = uv
- lazy val v = vv
-}
-
-object ProveDHTuple {
- val Code: PropositionCode = 103: Byte
-}
-
-/** Helper extractor to match SigmaProp values and extract ProveDHTuple out of it. */
-object ProveDHTupleProp {
- def unapply(p: SigmaProp): Option[ProveDHTuple] = SigmaDsl.toSigmaBoolean(p) match {
- case d: ProveDHTuple => Some(d)
- case _ => None
- }
-}
+case class SecondDHTupleProverMessage(z: BigInteger) extends SecondProverMessage
-object DiffieHellmanTupleInteractiveProver extends SigmaProtocolProver {
+object DiffieHellmanTupleProver extends SigmaProtocolProver {
import CryptoConstants.dlogGroup
diff --git a/interpreter/shared/src/main/scala/sigmastate/crypto/SigmaProtocolFunctions.scala b/interpreter/shared/src/main/scala/sigmastate/crypto/SigmaProtocolFunctions.scala
index 176edb201c..78f45afaa9 100644
--- a/interpreter/shared/src/main/scala/sigmastate/crypto/SigmaProtocolFunctions.scala
+++ b/interpreter/shared/src/main/scala/sigmastate/crypto/SigmaProtocolFunctions.scala
@@ -1,9 +1,9 @@
package sigmastate.crypto
-import sigmastate.SigmaLeaf
-import sigmastate.crypto.CryptoConstants.dlogGroup
+import sigma.crypto.CryptoConstants.dlogGroup
import sigmastate.crypto.VerifierMessage.Challenge
import sigma.Coll
+import sigma.data.SigmaLeaf
import supertagged.TaggedType
import java.math.BigInteger
@@ -11,7 +11,6 @@ import java.math.BigInteger
/*
Abstracting Sigma protocols
Functionality to get:
- - Interactive Sigma protocols(via actors)
- Zero-knowledge proof from a Sigma protocol
- Non-interactive Sigma protocols
- Commitment from any Sigma protocol
@@ -37,26 +36,13 @@ object VerifierMessage {
/** First message from the prover (message `a` of `SigmaProtocol`)*/
trait FirstProverMessage extends ProverMessage {
- type SP <: SigmaProtocol[SP]
-
def bytes: Array[Byte]
}
/** Second message from the prover (message `z` of `SigmaProtocol`)*/
-trait SecondProverMessage extends ProverMessage {
- type SP <: SigmaProtocol[SP]
-}
-
-/** Abstract template for sigma protocols.
- * For details see the following book
- * [1] Efficient Secure Two-Party Protocols - Techniques and Constructions, p.150)*/
-trait SigmaProtocol[SP <: SigmaProtocol[SP]] {
- type A <: FirstProverMessage
- type Z <: SecondProverMessage
-}
-
+trait SecondProverMessage extends ProverMessage
-trait SigmaProtocolPrivateInput[CI <: SigmaLeaf] {
+trait SigmaProtocolPrivateInput[+CI <: SigmaLeaf] {
/** Public image generated from the secret.
* Represents proof of knowledge proposition.
*/
@@ -66,6 +52,9 @@ trait SigmaProtocolPrivateInput[CI <: SigmaLeaf] {
def w: BigInteger
}
+/** Represents any prover of a sigma protocol.
+ * @see DLogInteractiveProver, DiffieHellmanTupleProver
+ */
trait SigmaProtocolProver {
/** Computes response for the challenge in non-interactive sigma protocol.
*
@@ -79,10 +68,10 @@ trait SigmaProtocolProver {
privateInput: SigmaProtocolPrivateInput[_ <: SigmaLeaf],
rnd: BigInteger,
challenge: Challenge): BigInteger = {
- val q: BigInteger = dlogGroup.order
+ val q: BigInteger = dlogGroup.order // order of the group
val e: BigInteger = new BigInteger(1, challenge.toArray)
- val ew: BigInteger = e.multiply(privateInput.w).mod(q)
- val z: BigInteger = rnd.add(ew).mod(q)
+ val ew: BigInteger = e.multiply(privateInput.w).mod(q) // e * w mod q
+ val z: BigInteger = rnd.add(ew).mod(q) // r + ew mod q
z
}
}
diff --git a/interpreter/shared/src/main/scala/sigmastate/crypto/package.scala b/interpreter/shared/src/main/scala/sigmastate/crypto/package.scala
deleted file mode 100644
index c7ef439d87..0000000000
--- a/interpreter/shared/src/main/scala/sigmastate/crypto/package.scala
+++ /dev/null
@@ -1,15 +0,0 @@
-package sigmastate
-
-package object crypto {
- /** Instance of Elliptic Curve descriptor. */
- type Curve = Platform.Curve
-
- /** Instance of Elliptic Curve point. */
- type Ecp = Platform.Ecp
-
- /** Instance of Elliptic Curve field element. */
- type ECFieldElem = Platform.ECFieldElem
-
- /** A cryptographically strong random number generator. */
- type SecureRandom = Platform.SecureRandom
-}
diff --git a/interpreter/shared/src/main/scala/sigmastate/eval/CAvlTreeVerifier.scala b/interpreter/shared/src/main/scala/sigmastate/eval/CAvlTreeVerifier.scala
new file mode 100644
index 0000000000..5739e65ade
--- /dev/null
+++ b/interpreter/shared/src/main/scala/sigmastate/eval/CAvlTreeVerifier.scala
@@ -0,0 +1,59 @@
+package sigmastate.eval
+
+import scorex.crypto.authds.avltree.batch.{BatchAVLVerifier, Insert, Lookup, Remove, Update}
+import scorex.crypto.authds.{ADDigest, ADKey, ADValue, SerializedAdProof}
+import scorex.crypto.hash.{Blake2b256, Digest32}
+import sigma.data.CAvlTree
+import sigma.eval.AvlTreeVerifier
+import sigma.{AvlTree, Coll}
+
+import scala.util.Try
+
+/** Implements operations of AVL tree verifier based on
+ * [[scorex.crypto.authds.avltree.batch.BatchAVLVerifier]].
+ *
+ * @see BatchAVLVerifier, CAvlTreeVerifier
+ */
+class CAvlTreeVerifier private(
+ startingDigest: ADDigest,
+ proof: SerializedAdProof,
+ override val keyLength: Int,
+ override val valueLengthOpt: Option[Int])
+ extends BatchAVLVerifier[Digest32, Blake2b256.type](
+ startingDigest, proof, keyLength, valueLengthOpt) with AvlTreeVerifier {
+ def treeHeight: Int = rootNodeHeight
+
+ override def performLookup(key: Array[Byte]): Try[Option[Array[Byte]]] =
+ performOneOperation(Lookup(ADKey @@ key))
+
+ override def performInsert(key: Array[Byte], value: Array[Byte]): Try[Option[Array[Byte]]] =
+ performOneOperation(Insert(ADKey @@ key, ADValue @@ value))
+
+ override def performUpdate(key: Array[Byte], value: Array[Byte]): Try[Option[Array[Byte]]] =
+ performOneOperation(Update(ADKey @@ key, ADValue @@ value))
+
+ override def performRemove(key: Array[Byte]): Try[Option[Array[Byte]]] =
+ performOneOperation(Remove(ADKey @@ key))
+
+ override def digest: Option[ADDigest] = super.digest
+
+ /** Override default logging which outputs stack trace to the console. */
+ override protected def logError(t: Throwable): Unit = {}
+}
+
+object CAvlTreeVerifier {
+ /** Create an instance of [[CAvlTreeVerifier]] for the given tree and proof.
+ * Both tree and proof are immutable.
+ *
+ * @param tree represents a tree state to verify
+ * @param proof proof of tree operations leading to the state digest in the tree
+ * @return a new verifier instance
+ */
+ def apply(tree: AvlTree, proof: Coll[Byte]): CAvlTreeVerifier = {
+ val treeData = tree.asInstanceOf[CAvlTree].treeData
+ val adProof = SerializedAdProof @@ proof.toArray
+ val bv = new CAvlTreeVerifier(
+ ADDigest @@ treeData.digest.toArray, adProof, treeData.keyLength, treeData.valueLengthOpt)
+ bv
+ }
+}
\ No newline at end of file
diff --git a/interpreter/shared/src/main/scala/sigmastate/eval/CContext.scala b/interpreter/shared/src/main/scala/sigmastate/eval/CContext.scala
new file mode 100644
index 0000000000..2b076403ad
--- /dev/null
+++ b/interpreter/shared/src/main/scala/sigmastate/eval/CContext.scala
@@ -0,0 +1,101 @@
+package sigmastate.eval
+
+import debox.cfor
+import sigma.Extensions.ArrayOps
+import sigma._
+import sigma.data._
+import sigma.exceptions.InvalidType
+
+import scala.annotation.unused
+import scala.reflect.ClassTag
+
+/** A default implementation of [[Context]] interface.
+ * @see [[Context]] for detailed descriptions
+ */
+case class CContext(
+ _dataInputs: Coll[Box],
+ override val headers: Coll[Header],
+ override val preHeader: PreHeader,
+ inputs: Coll[Box],
+ outputs: Coll[Box],
+ height: Int,
+ selfBox: Box,
+ private val selfIndex: Int,
+ lastBlockUtxoRootHash: AvlTree,
+ _minerPubKey: Coll[Byte],
+ vars: Coll[AnyValue],
+ override val activatedScriptVersion: Byte,
+ override val currentErgoTreeVersion: Byte
+) extends Context {
+ @inline override def builder: SigmaDslBuilder = CSigmaDslBuilder
+
+ @inline override def HEIGHT: Int = height
+
+ @inline override def SELF: Box = selfBox
+
+ @inline override def dataInputs: Coll[Box] = _dataInputs
+
+ @inline override def INPUTS = inputs
+
+ @inline override def OUTPUTS = outputs
+
+ @inline override def LastBlockUtxoRootHash = lastBlockUtxoRootHash
+
+ @inline override def minerPubKey = _minerPubKey
+
+ override def selfBoxIndex: Int = {
+ if (VersionContext.current.isJitActivated) {
+ // starting from v5.0 this is fixed
+ selfIndex
+ } else {
+ // this used to be a bug in v4.x (https://github.com/ScorexFoundation/sigmastate-interpreter/issues/603)
+ -1
+ }
+ }
+
+ override def getVar[T](id: Byte)(implicit tT: RType[T]): Option[T] = {
+ @unused // avoid warning about unused ctA
+ implicit val tag: ClassTag[T] = tT.classTag
+ if (id < 0 || id >= vars.length) return None
+ val value = vars(id)
+ if (value != null) {
+ // once the value is not null it should be of the right type
+ value match {
+ case value: CAnyValue[_] if value.value != null && value.tA == tT =>
+ Some(value.value.asInstanceOf[T])
+ case _ =>
+ throw new InvalidType(s"Cannot getVar[${tT.name}]($id): invalid type of value $value at id=$id")
+ }
+ } else None
+ }
+
+ /** Return a new context instance with variables collection updated.
+ * @param bindings a new binding of the context variables with new values.
+ * @return a new instance (if `bindings` non-empty) with the specified bindings.
+ * other existing bindings are copied to the new instance
+ */
+ def withUpdatedVars(bindings: (Int, AnyValue)*): CContext = {
+ if (bindings.isEmpty) return this
+
+ val ids = bindings.map(_._1).toArray
+ val values = bindings.map(_._2).toArray
+ val maxVarId = ids.max // INV: ids is not empty
+ val requiredNewLength = maxVarId + 1
+
+ val newVars = if (vars.length < requiredNewLength) {
+ // grow vars collection
+ val currVars = vars.toArray
+ val buf = new Array[AnyValue](requiredNewLength)
+ Array.copy(currVars, 0, buf, 0, currVars.length)
+ cfor(0)(_ < ids.length, _ + 1) { i =>
+ buf(ids(i)) = values(i)
+ }
+ buf.toColl
+ } else {
+ vars.updateMany(ids.toColl, values.toColl)
+ }
+
+ this.copy(vars = newVars)
+ }
+}
+
diff --git a/interpreter/shared/src/main/scala/sigmastate/eval/CHeader.scala b/interpreter/shared/src/main/scala/sigmastate/eval/CHeader.scala
new file mode 100644
index 0000000000..7062fa0f0e
--- /dev/null
+++ b/interpreter/shared/src/main/scala/sigmastate/eval/CHeader.scala
@@ -0,0 +1,34 @@
+package sigmastate.eval
+
+import sigma.data.SigmaConstants
+import sigma.{AvlTree, BigInt, Coll, GroupElement, Header}
+
+/** A default implementation of [[Header]] interface.
+ *
+ * @see [[Header]] for detailed descriptions
+ */
+case class CHeader(
+ id: Coll[Byte],
+ version: Byte,
+ parentId: Coll[Byte],
+ ADProofsRoot: Coll[Byte],
+ stateRoot: AvlTree,
+ transactionsRoot: Coll[Byte],
+ timestamp: Long,
+ nBits: Long,
+ height: Int,
+ extensionRoot: Coll[Byte],
+ minerPk: GroupElement,
+ powOnetimePk: GroupElement,
+ powNonce: Coll[Byte],
+ powDistance: BigInt,
+ votes: Coll[Byte]
+) extends Header
+
+object CHeader {
+ /** Size of of Header.votes array. */
+ val VotesSize: Int = SigmaConstants.VotesArraySize.value
+
+ /** Size of nonce array from Autolykos POW solution in Header.powNonce array. */
+ val NonceSize: Int = SigmaConstants.AutolykosPowSolutionNonceArraySize.value
+}
\ No newline at end of file
diff --git a/interpreter/shared/src/main/scala/sigmastate/eval/CPreHeader.scala b/interpreter/shared/src/main/scala/sigmastate/eval/CPreHeader.scala
new file mode 100644
index 0000000000..8076ab5a9c
--- /dev/null
+++ b/interpreter/shared/src/main/scala/sigmastate/eval/CPreHeader.scala
@@ -0,0 +1,17 @@
+package sigmastate.eval
+
+import sigma.{Coll, GroupElement, PreHeader}
+
+/** A default implementation of [[PreHeader]] interface.
+ *
+ * @see [[PreHeader]] for detailed descriptions
+ */
+case class CPreHeader(
+ version: Byte,
+ parentId: Coll[Byte],
+ timestamp: Long,
+ nBits: Long,
+ height: Int,
+ minerPk: GroupElement,
+ votes: Coll[Byte]
+) extends PreHeader
diff --git a/interpreter/shared/src/main/scala/sigmastate/eval/Profiler.scala b/interpreter/shared/src/main/scala/sigmastate/eval/CProfiler.scala
similarity index 94%
rename from interpreter/shared/src/main/scala/sigmastate/eval/Profiler.scala
rename to interpreter/shared/src/main/scala/sigmastate/eval/CProfiler.scala
index 80266c9063..ced8a357b8 100644
--- a/interpreter/shared/src/main/scala/sigmastate/eval/Profiler.scala
+++ b/interpreter/shared/src/main/scala/sigmastate/eval/CProfiler.scala
@@ -1,16 +1,15 @@
package sigmastate.eval
-import sigmastate.{FixedCost, JitCost, SMethod}
-import sigmastate.Values.SValue
-import sigmastate.serialization.{OpCodes, ValueSerializer}
-import sigmastate.serialization.OpCodes.OpCode
-import sigmastate.serialization.ValueSerializer.getSerializer
-import sigma.util.Extensions.ByteOps
-import debox.{Buffer => DBuffer, Map => DMap}
-import debox.sp
-import sigmastate.eval.Extensions.DBufferOps
-import sigmastate.interpreter.{CostItem, FixedCostItem, SeqCostItem, TypeBasedCostItem}
-import sigmastate.lang.Terms.{MethodCall, PropertyCall}
+import debox.{sp, Buffer => DBuffer, Map => DMap}
+import sigma.ast.{CostItem, FixedCost, FixedCostItem, JitCost, SMethod, SeqCostItem, TypeBasedCostItem}
+import sigma.ast.TypeCodes.LastConstantCode
+import sigma.ast.syntax._
+import sigma.util.Extensions.{ByteOps, DBufferOps}
+import sigma.ast.{MethodCall, PropertyCall}
+import sigma.eval.Profiler
+import sigma.serialization.ValueCodes.OpCode
+import sigma.serialization.ValueSerializer
+import sigma.serialization.ValueSerializer.getSerializer
import scala.reflect.ClassTag
@@ -105,7 +104,7 @@ class StatCollection[@sp(Int) K, @sp(Long, Double) V]
}
/** A simple profiler to measure average execution times of ErgoTree operations. */
-class Profiler {
+class CProfiler extends Profiler {
// NOTE: this class is mutable so better to keep it private
private class OpStat(
@@ -199,7 +198,7 @@ class Profiler {
/** Timings of cost items */
private val costItemsStat = new StatCollection[CostItemKey, Long]()
- def addCostItem(costItem: CostItem, time: Long) = {
+ override def addCostItem(costItem: CostItem, time: Long) = {
costItemsStat.addPoint(new CostItemKey(costItem), time)
}
@@ -256,7 +255,7 @@ class Profiler {
val suggestedCost = suggestCost(time)
val warn = if (suggestedCost > cost) "!!!" else ""
val comment = s"count: $count, suggestedCost: $suggestedCost, actualCost: $cost$warn"
- (opName, (opCode.toUByte - OpCodes.LastConstantCode).toString, time, comment)
+ (opName, (opCode.toUByte - LastConstantCode).toString, time, comment)
}.filter(line => line != null && line._1.nonEmpty)
.sortBy(_._3)(Ordering[Long].reverse)
diff --git a/interpreter/shared/src/main/scala/sigmastate/eval/CostingDataContext.scala b/interpreter/shared/src/main/scala/sigmastate/eval/CostingDataContext.scala
deleted file mode 100644
index 870cbbb5bf..0000000000
--- a/interpreter/shared/src/main/scala/sigmastate/eval/CostingDataContext.scala
+++ /dev/null
@@ -1,760 +0,0 @@
-package sigmastate.eval
-
-import debox.cfor
-import org.ergoplatform.validation.{ValidationRules, SigmaValidationSettings}
-import org.ergoplatform.{SigmaConstants, ErgoBox}
-import sigma.data.OverloadHack.Overloaded1
-import sigma.data.RType
-import sigma.util.Extensions.BigIntegerOps
-import scorex.crypto.authds.avltree.batch._
-import scorex.crypto.authds.{SerializedAdProof, ADDigest, ADValue, ADKey}
-import scorex.crypto.hash.{Blake2b256, Digest32, Sha256}
-import scorex.utils.{Longs, Ints}
-import sigmastate.SCollection.SByteArray
-import sigmastate.Values.ErgoTree.EmptyConstants
-import sigmastate.Values.{EvaluatedValue, SValue, ConstantNode, ErgoTree, SigmaBoolean}
-import sigmastate._
-import sigmastate.crypto.CryptoConstants.EcPointType
-import sigmastate.crypto.DLogProtocol.ProveDlog
-import sigmastate.crypto.{ProveDHTuple, CryptoConstants, Ecp, CryptoFacade}
-import sigmastate.eval.Extensions._
-import sigmastate.interpreter.Interpreter
-import sigmastate.serialization.ErgoTreeSerializer.DefaultSerializer
-import sigmastate.serialization.{GroupElementSerializer, SigmaSerializer}
-import sigma.{VersionContext, _}
-
-import java.math.BigInteger
-import java.util.Arrays
-import scala.annotation.unused
-import scala.reflect.ClassTag
-import scala.util.{Success, Failure}
-
-/** Interface implmented by wrappers to provide access to the underlying wrapped value. */
-trait WrapperOf[T] {
- /** The data value wrapped by this wrapper. */
- def wrappedValue: T
-}
-
-/** A default implementation of [[BigInt]] interface.
- * @see [[BigInt]] for detailed descriptions
- */
-case class CBigInt(override val wrappedValue: BigInteger) extends BigInt with WrapperOf[BigInteger] {
- val dsl = CostingSigmaDslBuilder
- override def toByte : Byte = wrappedValue.toByteExact
- override def toShort: Short = wrappedValue.toShortExact
- override def toInt : Int = wrappedValue.toIntExact
- override def toLong : Long = wrappedValue.toLongExact
-
- override def toBytes: Coll[Byte] = dsl.Colls.fromArray(wrappedValue.toByteArray)
-
- override def toAbs: BigInt = dsl.BigInt(wrappedValue.abs())
-
- override def compareTo(that: BigInt): Int =
- wrappedValue.compareTo(that.asInstanceOf[CBigInt].wrappedValue)
-
- override def toBits: Coll[Boolean] = ???
-
- override def modQ: BigInt = ???
-
- override def plusModQ(other: BigInt): BigInt = ???
-
- override def minusModQ(other: BigInt): BigInt = ???
-
- override def multModQ(other: BigInt): BigInt = ???
-
- override def inverseModQ: BigInt = ???
-
- override def signum: Int = wrappedValue.signum()
-
- override def add(that: BigInt): BigInt = dsl.BigInt(wrappedValue.add(that.asInstanceOf[CBigInt].wrappedValue).to256BitValueExact)
-
- override def subtract(that: BigInt): BigInt = dsl.BigInt(wrappedValue.subtract(that.asInstanceOf[CBigInt].wrappedValue).to256BitValueExact)
-
- override def multiply(that: BigInt): BigInt = dsl.BigInt(wrappedValue.multiply(that.asInstanceOf[CBigInt].wrappedValue).to256BitValueExact)
-
- override def divide(that: BigInt): BigInt = dsl.BigInt(wrappedValue.divide(that.asInstanceOf[CBigInt].wrappedValue))
-
- override def mod(m: BigInt): BigInt = dsl.BigInt(wrappedValue.mod(m.asInstanceOf[CBigInt].wrappedValue))
-
- override def remainder(that: BigInt): BigInt = dsl.BigInt(wrappedValue.remainder(that.asInstanceOf[CBigInt].wrappedValue))
-
- override def min(that: BigInt): BigInt = dsl.BigInt(wrappedValue.min(that.asInstanceOf[CBigInt].wrappedValue))
-
- override def max(that: BigInt): BigInt = dsl.BigInt(wrappedValue.max(that.asInstanceOf[CBigInt].wrappedValue))
-
- override def negate(): BigInt = dsl.BigInt(wrappedValue.negate().to256BitValueExact)
-
- override def and(that: BigInt): BigInt = dsl.BigInt(wrappedValue.and(that.asInstanceOf[CBigInt].wrappedValue))
-
- override def or(that: BigInt): BigInt = dsl.BigInt(wrappedValue.or(that.asInstanceOf[CBigInt].wrappedValue))
-}
-
-/** A default implementation of [[GroupElement]] interface.
- * @see [[GroupElement]] for detailed descriptions
- */
-case class CGroupElement(override val wrappedValue: Ecp) extends GroupElement with WrapperOf[Ecp] {
- val dsl = CostingSigmaDslBuilder
-
- override def toString: String = s"GroupElement(${sigmastate.eval.Extensions.showECPoint(wrappedValue)})"
-
- override def getEncoded: Coll[Byte] =
- dsl.Colls.fromArray(GroupElementSerializer.toBytes(wrappedValue))
-
- override def isIdentity: Boolean = CryptoFacade.isInfinityPoint(wrappedValue)
-
- override def exp(k: BigInt): GroupElement =
- dsl.GroupElement(CryptoFacade.exponentiatePoint(wrappedValue, k.asInstanceOf[CBigInt].wrappedValue))
-
- override def multiply(that: GroupElement): GroupElement =
- dsl.GroupElement(CryptoFacade.multiplyPoints(wrappedValue, that.asInstanceOf[CGroupElement].wrappedValue))
-
- override def negate: GroupElement =
- dsl.GroupElement(CryptoFacade.negatePoint(wrappedValue))
-}
-
-/** A default implementation of [[SigmaProp]] interface.
- * @see [[SigmaProp]] for detailed descriptions
- */
-case class CSigmaProp(sigmaTree: SigmaBoolean) extends SigmaProp with WrapperOf[SigmaBoolean] {
- override def wrappedValue: SigmaBoolean = sigmaTree
-
- // TODO refactor: remove this (it shouldn't be used in interpreter)
- override def isValid: Boolean = sigmaTree match {
- case p: TrivialProp => p.condition
- case _ => sys.error(s"Method CostingSigmaProp.isValid is not defined for $sigmaTree")
- }
-
- override def propBytes: Coll[Byte] = {
- // in order to have comparisons like `box.propositionBytes == pk.propBytes` we need to make sure
- // the same serialization method is used in both cases
- // TODO v6.0: add `pk.propBytes(version)` (see https://github.com/ScorexFoundation/sigmastate-interpreter/issues/903)
- val root = sigmaTree.toSigmaProp
- val ergoTree = new ErgoTree(ErgoTree.DefaultHeader, EmptyConstants, Right(root), 0, null, None)
- val bytes = DefaultSerializer.serializeErgoTree(ergoTree)
- Colls.fromArray(bytes)
- }
-
- override def &&(other: SigmaProp): SigmaProp = other match {
- case other: CSigmaProp =>
- CSigmaProp(CAND.normalized(Array(sigmaTree, other.sigmaTree)))
- }
-
- override def ||(other: SigmaProp): SigmaProp = other match {
- case other: CSigmaProp =>
- CSigmaProp(COR.normalized(Array(sigmaTree, other.sigmaTree)))
- }
-
- override def toString: String = s"SigmaProp(${wrappedValue.showToString})"
-}
-
-/** Implements operations of AVL tree verifier based on
- * [[scorex.crypto.authds.avltree.batch.BatchAVLVerifier]].
- *
- * @see BatchAVLVerifier
- */
-class AvlTreeVerifier private (startingDigest: ADDigest,
- proof: SerializedAdProof,
- override val keyLength: Int,
- override val valueLengthOpt: Option[Int])
- extends BatchAVLVerifier[Digest32, Blake2b256.type](
- startingDigest, proof, keyLength, valueLengthOpt) {
- def treeHeight: Int = rootNodeHeight
-
- /** Override default logging which outputs stack trace to the console. */
- override protected def logError(t: Throwable): Unit = {}
-}
-object AvlTreeVerifier {
- /** Create an instance of [[AvlTreeVerifier]] for the given tree and proof.
- * Both tree and proof are immutable.
- * @param tree represents a tree state to verify
- * @param proof proof of tree operations leading to the state digest in the tree
- * @return a new verifier instance
- */
- def apply(tree: AvlTree, proof: Coll[Byte]): AvlTreeVerifier = {
- val treeData = tree.asInstanceOf[CAvlTree].treeData
- val adProof = SerializedAdProof @@ proof.toArray
- val bv = new AvlTreeVerifier(
- ADDigest @@ treeData.digest.toArray, adProof, treeData.keyLength, treeData.valueLengthOpt)
- bv
- }
-}
-
-/** A default implementation of [[AvlTree]] interface.
- * @see [[AvlTree]] for detailed descriptions
- */
-case class CAvlTree(treeData: AvlTreeData) extends AvlTree with WrapperOf[AvlTreeData] {
- override def wrappedValue: AvlTreeData = treeData
-
- override def keyLength: Int = treeData.keyLength
-
- override def enabledOperations = treeData.treeFlags.serializeToByte
-
- override def isInsertAllowed: Boolean = treeData.treeFlags.insertAllowed
-
- override def isUpdateAllowed: Boolean = treeData.treeFlags.updateAllowed
-
- override def isRemoveAllowed: Boolean = treeData.treeFlags.removeAllowed
-
- override def updateOperations(newOperations: Byte): AvlTree = {
- val td = treeData.copy(treeFlags = AvlTreeFlags(newOperations))
- this.copy(treeData = td)
- }
-
- override def valueLengthOpt: Option[Int] = treeData.valueLengthOpt
-
- override def digest: Coll[Byte] = treeData.digest
-
- override def updateDigest(newDigest: Coll[Byte]): AvlTree = {
- val td = treeData.copy(digest = newDigest)
- this.copy(treeData = td)
- }
-
- override def contains(key: Coll[Byte], proof: Coll[Byte]): Boolean = {
- val keyBytes = key.toArray
- val bv = AvlTreeVerifier(this, proof)
- bv.performOneOperation(Lookup(ADKey @@ keyBytes)) match {
- case Success(r) => r match {
- case Some(_) => true
- case _ => false
- }
- case Failure(_) => false
- }
- }
-
- override def get(key: Coll[Byte], proof: Coll[Byte]): Option[Coll[Byte]] = {
- val keyBytes = key.toArray
- val bv = AvlTreeVerifier(this, proof)
- bv.performOneOperation(Lookup(ADKey @@ keyBytes)) match {
- case Success(r) => r match {
- case Some(v) => Some(Colls.fromArray(v))
- case _ => None
- }
- case Failure(_) => Interpreter.error(s"Tree proof is incorrect $treeData")
- }
- }
-
- override def getMany(keys: Coll[Coll[Byte]], proof: Coll[Byte]): Coll[Option[Coll[Byte]]] = {
- val bv = AvlTreeVerifier(this, proof)
- keys.map { key =>
- bv.performOneOperation(Lookup(ADKey @@ key.toArray)) match {
- case Success(r) => r match {
- case Some(v) => Some(Colls.fromArray(v))
- case _ => None
- }
- case Failure(_) => Interpreter.error(s"Tree proof is incorrect $treeData")
- }
- }
- }
-
- override def insert(entries: Coll[(Coll[Byte], Coll[Byte])], proof: Coll[Byte]): Option[AvlTree] = {
- if (!isInsertAllowed) {
- None
- } else {
- val bv = AvlTreeVerifier(this, proof)
- entries.forall { case (key, value) =>
- val insertRes = bv.performOneOperation(Insert(ADKey @@ key.toArray, ADValue @@ value.toArray))
- if (insertRes.isFailure) {
- Interpreter.error(s"Incorrect insert for $treeData (key: $key, value: $value, digest: $digest): ${insertRes.failed.get}}")
- }
- insertRes.isSuccess
- }
- bv.digest match {
- case Some(d) => Some(updateDigest(Colls.fromArray(d)))
- case _ => None
- }
- }
- }
-
- override def update(operations: Coll[(Coll[Byte], Coll[Byte])], proof: Coll[Byte]): Option[AvlTree] = {
- if (!isUpdateAllowed) {
- None
- } else {
- val bv = AvlTreeVerifier(this, proof)
- operations.forall { case (key, value) =>
- bv.performOneOperation(Update(ADKey @@ key.toArray, ADValue @@ value.toArray)).isSuccess
- }
- bv.digest match {
- case Some(d) => Some(updateDigest(Colls.fromArray(d)))
- case _ => None
- }
- }
- }
-
- override def remove(operations: Coll[Coll[Byte]], proof: Coll[Byte]): Option[AvlTree] = {
- if (!isRemoveAllowed) {
- None
- } else {
- val bv = AvlTreeVerifier(this, proof)
- cfor(0)(_ < operations.length, _ + 1) { i =>
- val key = operations(i).toArray
- bv.performOneOperation(Remove(ADKey @@ key))
- }
- bv.digest match {
- case Some(v) => Some(updateDigest(Colls.fromArray(v)))
- case _ => None
- }
- }
- }
-}
-
-/** Default implementation of AnyValue interface. */
-case class CAnyValue[A](value: A, tVal: RType[Any]) extends AnyValue {
- def tA: RType[A] = tVal.asInstanceOf[RType[A]]
- override def toString = s"TestValue($value)"
-}
-
-object CAnyValue {
- def apply[A](value: A)(implicit t: RType[A], @unused o: Overloaded1): CAnyValue[A] =
- new CAnyValue(value, t.asInstanceOf[RType[Any]])
-}
-
-import sigmastate.eval.CostingBox._
-
-/** A default implementation of [[Box]] interface.
- * @see [[Box]] for detailed descriptions
- */
-case class CostingBox(ebox: ErgoBox) extends Box with WrapperOf[ErgoBox] {
- val builder = CostingSigmaDslBuilder
-
- val value = ebox.value
- lazy val id: Coll[Byte] = Colls.fromArray(ebox.id)
- lazy val bytes: Coll[Byte] = Colls.fromArray(ebox.bytes)
- lazy val bytesWithoutRef: Coll[Byte] = Colls.fromArray(ebox.bytesWithNoRef)
- lazy val propositionBytes: Coll[Byte] = Colls.fromArray(ebox.propositionBytes)
- lazy val registers: Coll[AnyValue] = regs(ebox)
-
- override def wrappedValue: ErgoBox = ebox
-
- override def getReg[T](i: Int)(implicit tT: RType[T]): Option[T] = {
- if (i < 0 || i >= registers.length) return None
- val value = registers(i)
- if (value != null ) {
- // once the value is not null it should be of the right type
- value match {
- case value: CAnyValue[_] if value.value != null && value.tA == tT =>
- Some(value.value.asInstanceOf[T])
- case _ =>
- throw new InvalidType(s"Cannot getReg[${tT.name}]($i): invalid type of value $value at id=$i")
- }
- } else None
- }
-
- override def creationInfo: (Int, Coll[Byte]) = {
- this.getReg[(Int, Coll[Byte])](3).get.asInstanceOf[Any] match {
- case info: Tuple2[Int, Coll[Byte]]@unchecked => info
- case ConstantNode(arr: Array[Any], STuple(IndexedSeq(SInt, SByteArray))) if arr.length == 2 =>
- (arr(0).asInstanceOf[Int], builder.Colls.fromArray(arr(1).asInstanceOf[Array[Byte]]))
- case v =>
- sys.error(s"Invalid value $v of creationInfo register R3")
- }
- }
-
- override def tokens: Coll[(Coll[Byte], Long)] = {
- this.getReg[Coll[(Coll[Byte], Long)]](ErgoBox.R2.asIndex).get
- }
-
- override def executeFromRegister[T](regId: Byte)(implicit cT: RType[T]): T = ??? // TODO implement
-
- override def hashCode(): Int = Ints.fromByteArray(id.toArray)
-
- override def equals(obj: Any): Boolean = (this eq obj.asInstanceOf[AnyRef]) || (obj != null && {
- obj match {
- case obj: Box => Arrays.equals(id.toArray, obj.id.toArray)
- case _ =>
- // this case was missing in v4.x, however has never been a problem
- // Thus, v5.0 interpreter will not fail (while v4.x would fail here)
- false
- }
- })
-}
-
-object CostingBox {
-
- import Evaluation._
-
- def regs(ebox: ErgoBox): Coll[AnyValue] = {
- val res = new Array[AnyValue](ErgoBox.maxRegisters)
-
- def checkNotYetDefined(id: Int, newValue: SValue) =
- require(res(id) == null, s"register $id is defined more then once: previous value ${res(id)}, new value $newValue")
-
- for ((k, v: EvaluatedValue[t]) <- ebox.additionalRegisters) {
- checkNotYetDefined(k.number, v)
- res(k.number) = toAnyValue(v.value)(stypeToRType(v.tpe))
- }
-
- for (r <- ErgoBox.mandatoryRegisters) {
- val regId = r.number
- val v = ebox.get(r).get.asInstanceOf[EvaluatedValue[SType]]
- checkNotYetDefined(regId, v)
- res(regId) = toAnyValue(v.value)(stypeToRType(v.tpe))
- }
- Colls.fromArray(res)
- }
-
-}
-
-/** This class represents context variable and register value of a functional type A => B.
- * When variable or register is accessed using `getVar[A => B](id).get` or
- * `box.getReg[A => B].get an instance of this class is returned.
- *
- * It internally transforms a given `tree` into executable function.
- * This it similar to what happens during validation of propositions in the input boxes:
- * - size check of underlying ErgoTree against limits
- * - construction of `calcF` and `costF` graphs, both are stored together with resulting function.
- * - check the types of `calcF` graph to be compatible with expected types A and B
- * If anything goes wrong, this operation fails and if it is used in the script, the script also fails.
- *
- * When f is obtained as `val f = getVar[Int => Int](id).get` then any application `f(x)` involves size estimation
- * using underlying `costF(x)`.
- * */
-//case class CFunc[A,B](context: sigmastate.interpreter.Context, tree: SValue)
-// (implicit tDom: RType[A], tRange: RType[B], IR: IRContext) extends (A => B) {
-// import CFunc._
-//
-// private val compiled = {
-// import IR._
-// val IR.Pair(calcF, costF) = IR.doCosting(emptyEnv, tree)
-//
-// val eDom = asElem[Any](IR.rtypeToElem(tDom))
-// val eRange = asElem[Any](IR.rtypeToElem(tRange))
-//
-// IR.verifyCalcFunc[Any => Any](asRep[Context => (Any => Any)](calcF), IR.funcElement(eDom, eRange))
-//// IR.verifyCostFunc(costF).getOrThrow
-//// IR.verifyIsProven(calcF).getOrThrow
-//
-// // check cost
-//// val costingCtx = context.toSigmaContext(IR, isCost = true)
-//// val costFun = IR.compile[SInt.type](IR.getDataEnv, costF)
-//// val IntConstant(estimatedCost) = costFun(costingCtx)
-//// if (estimatedCost > maxCost) {
-//// throw new Error(s"Estimated execution cost $estimatedCost exceeds the limit $maxCost in $tree")
-//// }
-// // check calc
-// val calcCtx = context.toSigmaContext(IR, isCost = false)
-// val valueFun = IR.compile[SFunc](IR.getDataEnv, asRep[Context => SFunc#WrappedType](calcF))
-// val res = valueFun(calcCtx) match {
-// case Constant(f, fTpe: SFunc) => f
-// case v => v
-// }
-// res.asInstanceOf[A => B]
-// }
-//
-// override def apply(x: A): B = compiled(x)
-//}
-object CFunc {
- /** The cost of creating resulting function but not its execution.
- * Thus it is expected to be small. It can be increased if useful cases are found
- * such that `tree` should contains heavy operations. */
- val maxCost = 1000
-}
-
-/** A default implementation of [[PreHeader]] interface.
- * @see [[PreHeader]] for detailed descriptions
- */
-case class CPreHeader(
- version: Byte,
- parentId: Coll[Byte],
- timestamp: Long,
- nBits: Long,
- height: Int,
- minerPk: GroupElement,
- votes: Coll[Byte]
- ) extends PreHeader {}
-
-/** A default implementation of [[Header]] interface.
- * @see [[Header]] for detailed descriptions
- */
-case class CHeader(
- id: Coll[Byte],
- version: Byte,
- parentId: Coll[Byte],
- ADProofsRoot: Coll[Byte],
- stateRoot: AvlTree,
- transactionsRoot: Coll[Byte],
- timestamp: Long,
- nBits: Long,
- height: Int,
- extensionRoot: Coll[Byte],
- minerPk: GroupElement,
- powOnetimePk: GroupElement,
- powNonce: Coll[Byte],
- powDistance: BigInt,
- votes: Coll[Byte]
- ) extends Header {
-}
-
-object CHeader {
- val VotesSize: Int = SigmaConstants.VotesArraySize.value
- val NonceSize: Int = SigmaConstants.AutolykosPowSolutionNonceArraySize.value
-}
-
-/** A default implementation of [[SigmaDslBuilder]] interface.
- * @see [[SigmaDslBuilder]] for detailed descriptions
- */
-class CostingSigmaDslBuilder extends SigmaDslBuilder { dsl =>
- implicit val validationSettings: SigmaValidationSettings = ValidationRules.currentSettings
-
- override val Colls: CollBuilder = sigma.Colls
-
- override def BigInt(n: BigInteger): BigInt = CBigInt(n)
-
- override def toBigInteger(n: BigInt): BigInteger = n.asInstanceOf[CBigInt].wrappedValue
-
- /** Wraps the given elliptic curve point into GroupElement type. */
- def GroupElement(p: Ecp): GroupElement = p match {
- case ept: EcPointType => CGroupElement(ept)
- case m => sys.error(s"Point of type ${m.getClass} is not supported")
- }
-
- /** Wraps the given sigma proposition into SigmaDsl value of type SigmaProp. */
- def SigmaProp(sigmaTree: SigmaBoolean): SigmaProp = new CSigmaProp(sigmaTree)
-
- /** Extract `sigmastate.Values.SigmaBoolean` from DSL's `SigmaProp` type. */
- @inline def toSigmaBoolean(p: SigmaProp): SigmaBoolean = p.asInstanceOf[CSigmaProp].sigmaTree
-
- /** Extract `sigmastate.AvlTreeData` from DSL's `AvlTree` type. */
- def toAvlTreeData(p: AvlTree): AvlTreeData = p.asInstanceOf[CAvlTree].treeData
-
- /** Extract `sigmastate.crypto.Ecp` from DSL's `GroupElement` type. */
- def toECPoint(ge: GroupElement): Ecp = ge.asInstanceOf[CGroupElement].wrappedValue
-
- /** Creates a new AvlTree instance with the given parameters.
- * @see AvlTreeData for details
- */
- override def avlTree(operationFlags: Byte, digest: Coll[Byte], keyLength: Int, valueLengthOpt: Option[Int]): CAvlTree = {
- val treeData = AvlTreeData(digest, AvlTreeFlags(operationFlags), keyLength, valueLengthOpt)
- CAvlTree(treeData)
- }
-
- /** Wraps the given tree data into SigmaDsl value of type [[AvlTree]]. */
- def avlTree(treeData: AvlTreeData): AvlTree = {
- CAvlTree(treeData)
- }
-
- /** Wraps the given [[ErgoBox]] into SigmaDsl value of type [[Box]].
- * @param ebox the value to be wrapped
- * @see [[sigmastate.SBox]], [[sigma.Box]]
- */
- def Box(ebox: ErgoBox): Box = CostingBox(ebox)
-
- /** Extracts [[ErgoBox]] from the given [[Box]] instance. This is inverse to the Box method. */
- def toErgoBox(b: Box): ErgoBox = b.asInstanceOf[CostingBox].ebox
-
- /** HOTSPOT: don't beautify this code */
- private def toSigmaTrees(props: Array[SigmaProp]): Array[SigmaBoolean] = {
- val len = props.length
- val res = new Array[SigmaBoolean](len)
- cfor(0)(_ < len, _ + 1) { i =>
- res(i) = toSigmaBoolean(props(i))
- }
- res
- }
-
- @inline private def toEcPointType(ge: GroupElement): EcPointType =
- toECPoint(ge).asInstanceOf[EcPointType]
-
- override def atLeast(bound: Int, props: Coll[SigmaProp]): SigmaProp = {
- if (props.length > AtLeast.MaxChildrenCount)
- throw new IllegalArgumentException(s"Expected input elements count should not exceed ${AtLeast.MaxChildrenCount}, actual: ${props.length}")
- val sigmaTrees = toSigmaTrees(props.toArray)
- val tree = AtLeast.reduce(bound, sigmaTrees)
- CSigmaProp(tree)
- }
-
- override def allOf(conditions: Coll[Boolean]): Boolean =
- conditions.forall(c => c)
-
- override def anyOf(conditions: Coll[Boolean]): Boolean =
- conditions.exists(c => c)
-
- override def xorOf(conditions: Coll[Boolean]): Boolean = {
- if (VersionContext.current.isJitActivated) {
- val len = conditions.length
- if (len == 0) false
- else if (len == 1) conditions(0)
- else {
- var res = conditions(0)
- cfor(1)(_ < len, _ + 1) { i =>
- res ^= conditions(i)
- }
- res
- }
- } else {
- // This is buggy version used in v4.x interpreter (for ErgoTrees v0, v1)
- conditions.toArray.distinct.length == 2
- }
- }
-
- override def allZK(props: Coll[SigmaProp]): SigmaProp = {
- val sigmaTrees = toSigmaTrees(props.toArray)
- val tree = CAND.normalized(sigmaTrees)
- CSigmaProp(tree)
- }
-
- override def anyZK(props: Coll[SigmaProp]): SigmaProp = {
- val sigmaTrees = toSigmaTrees(props.toArray)
- val tree = COR.normalized(sigmaTrees)
- CSigmaProp(tree)
- }
-
- override def xor(l: Coll[Byte], r: Coll[Byte]): Coll[Byte] =
- Colls.xor(l, r)
-
- override def sigmaProp(b: Boolean): SigmaProp = {
- CSigmaProp(TrivialProp(b))
- }
-
- override def blake2b256(bytes: Coll[Byte]): Coll[Byte] = {
- val h = Blake2b256.hash(bytes.toArray)
- Colls.fromArray(h)
- }
-
- override def sha256(bytes: Coll[Byte]): Coll[Byte] = {
- val h = Sha256.hash(bytes.toArray)
- Colls.fromArray(h)
- }
-
- override def byteArrayToBigInt(bytes: Coll[Byte]): BigInt = {
- val bi = new BigInteger(bytes.toArray).to256BitValueExact
- this.BigInt(bi)
- }
-
- override def longToByteArray(l: Long): Coll[Byte] =
- Colls.fromArray(Longs.toByteArray(l))
-
- override def byteArrayToLong(bytes: Coll[Byte]): Long =
- Longs.fromByteArray(bytes.toArray)
-
- override def proveDlog(ge: GroupElement): SigmaProp =
- CSigmaProp(ProveDlog(toECPoint(ge).asInstanceOf[EcPointType]))
-
- override def proveDHTuple(g: GroupElement, h: GroupElement, u: GroupElement, v: GroupElement): SigmaProp = {
- val dht = ProveDHTuple(toEcPointType(g), toEcPointType(h), toEcPointType(u), toEcPointType(v))
- CSigmaProp(dht)
- }
-
- private lazy val _generatorElement = this.GroupElement(CryptoConstants.dlogGroup.generator)
- override def groupGenerator: GroupElement = _generatorElement
-
- /**
- * @return the identity of the Dlog group used in ErgoTree
- */
- def groupIdentity: GroupElement = {
- this.GroupElement(CryptoConstants.dlogGroup.identity)
- }
-
- override def substConstants[T](scriptBytes: Coll[Byte],
- positions: Coll[Int],
- newValues: Coll[T]): Coll[Byte] = {
- val constants = try newValues.toArrayOfConstants
- catch {
- case e: Throwable =>
- throw new RuntimeException(s"Cannot evaluate substConstants($scriptBytes, $positions, $newValues)", e)
- }
- val (res, _) = SubstConstants.eval(scriptBytes.toArray, positions.toArray, constants)(validationSettings)
- Colls.fromArray(res)
- }
-
- override def decodePoint(encoded: Coll[Byte]): GroupElement = {
- val r = SigmaSerializer.startReader(encoded.toArray)
- val p = GroupElementSerializer.parse(r)
- this.GroupElement(p)
- }
-
-}
-
-/** Default singleton instance of Global object, which implements global ErgoTree functions. */
-object CostingSigmaDslBuilder extends CostingSigmaDslBuilder
-
-/** A default implementation of [[Context]] interface.
- * @see [[Context]] for detailed descriptions
- */
-case class CostingDataContext(
- _dataInputs: Coll[Box],
- override val headers: Coll[Header],
- override val preHeader: PreHeader,
- inputs: Coll[Box],
- outputs: Coll[Box],
- height: Int,
- selfBox: Box,
- private val selfIndex: Int,
- lastBlockUtxoRootHash: AvlTree,
- _minerPubKey: Coll[Byte],
- vars: Coll[AnyValue],
- override val activatedScriptVersion: Byte,
- override val currentErgoTreeVersion: Byte
- )
- extends Context {
- @inline override def builder: SigmaDslBuilder = CostingSigmaDslBuilder
-
- @inline override def HEIGHT: Int = height
-
- @inline override def SELF: Box = selfBox
-
- @inline override def dataInputs: Coll[Box] = _dataInputs
-
- @inline override def INPUTS = inputs
-
- @inline override def OUTPUTS = outputs
-
- @inline override def LastBlockUtxoRootHash = lastBlockUtxoRootHash
-
- @inline override def minerPubKey = _minerPubKey
-
- override def selfBoxIndex: Int = {
- if (VersionContext.current.isJitActivated) {
- // starting from v5.0 this is fixed
- selfIndex
- } else {
- // this used to be a bug in v4.x (https://github.com/ScorexFoundation/sigmastate-interpreter/issues/603)
- -1
- }
- }
-
- override def getVar[T](id: Byte)(implicit tT: RType[T]): Option[T] = {
- @unused // avoid warning about unused ctA
- implicit val tag: ClassTag[T] = tT.classTag
- if (id < 0 || id >= vars.length) return None
- val value = vars(id)
- if (value != null) {
- // once the value is not null it should be of the right type
- value match {
- case value: CAnyValue[_] if value.value != null && value.tA == tT =>
- Some(value.value.asInstanceOf[T])
- case _ =>
- throw new InvalidType(s"Cannot getVar[${tT.name}]($id): invalid type of value $value at id=$id")
- }
- } else None
- }
-
- /** Return a new context instance with variables collection updated.
- * @param bindings a new binding of the context variables with new values.
- * @return a new instance (if `bindings` non-empty) with the specified bindings.
- * other existing bindings are copied to the new instance
- */
- def withUpdatedVars(bindings: (Int, AnyValue)*): CostingDataContext = {
- if (bindings.isEmpty) return this
-
- val ids = bindings.map(_._1).toArray
- val values = bindings.map(_._2).toArray
- val maxVarId = ids.max // INV: ids is not empty
- val requiredNewLength = maxVarId + 1
-
- val newVars = if (vars.length < requiredNewLength) {
- // grow vars collection
- val currVars = vars.toArray
- val buf = new Array[AnyValue](requiredNewLength)
- Array.copy(currVars, 0, buf, 0, currVars.length)
- cfor(0)(_ < ids.length, _ + 1) { i =>
- buf(ids(i)) = values(i)
- }
- buf.toColl
- } else {
- vars.updateMany(ids.toColl, values.toColl)
- }
-
- this.copy(vars = newVars)
- }
-}
-
diff --git a/interpreter/shared/src/main/scala/sigmastate/eval/Extensions.scala b/interpreter/shared/src/main/scala/sigmastate/eval/Extensions.scala
index c7cac60d81..f9cb0e9f75 100644
--- a/interpreter/shared/src/main/scala/sigmastate/eval/Extensions.scala
+++ b/interpreter/shared/src/main/scala/sigmastate/eval/Extensions.scala
@@ -1,43 +1,21 @@
package sigmastate.eval
-import debox.{cfor, Buffer => DBuffer}
+import debox.cfor
import org.ergoplatform.ErgoBox
import org.ergoplatform.ErgoBox.TokenId
-import sigma.data.{Nullable, RType}
+import scorex.crypto.authds.avltree.batch.{Insert, Lookup, Remove, Update}
+import scorex.crypto.authds.{ADKey, ADValue}
import scorex.util.encode.Base16
-import sigmastate.SType.AnyOps
-import sigmastate.Values.{Constant, ConstantNode}
-import sigmastate.crypto.{CryptoFacade, Ecp}
-import sigmastate.lang.{CheckingSigmaBuilder, TransformingSigmaBuilder}
-import sigmastate.utils.Helpers
-import sigmastate.{Platform, SCollection, SCollectionType, SType}
-import sigma.Coll
+import sigma.ast.SType.AnyOps
+import sigma.ast._
+import sigma.data.{CBox, Digest32Coll, RType}
import sigma._
-import java.math.BigInteger
+import scala.util.{Failure, Success}
object Extensions {
- implicit class ByteExt(val b: Byte) extends AnyVal {
- @inline def toBigInt: BigInt = CostingSigmaDslBuilder.BigInt(BigInteger.valueOf(b.toLong))
- }
-
- implicit class IntExt(val x: Int) extends AnyVal {
- /** Convert this value to BigInt. */
- @inline def toBigInt: BigInt = CostingSigmaDslBuilder.BigInt(BigInteger.valueOf(x.toLong))
- }
-
- implicit class LongExt(val x: Long) extends AnyVal {
- /** Convert this value to BigInt. */
- @inline def toBigInt: BigInt = CostingSigmaDslBuilder.BigInt(BigInteger.valueOf(x))
- }
-
- implicit class ArrayOps[T: RType](arr: Array[T]) {
- /** Wraps array into Coll instance. The source array in not cloned. */
- @inline def toColl: Coll[T] = Colls.fromArray(arr)
- }
-
- /** Extension methods for `Coll[Byte]` not available for generic `Array[T]`. */
+ /** Extension methods for `Array[Byte]` not available for generic `Array[T]`. */
implicit class ArrayByteOps(val arr: Array[Byte]) extends AnyVal {
/** Wraps array into TokenId instance. The source array in not cloned. */
@inline def toTokenId: TokenId = Digest32Coll @@ Colls.fromArray(arr)
@@ -45,53 +23,12 @@ object Extensions {
@inline def toHex: String = Base16.encode(arr)
}
- implicit class EvalIterableOps[T: RType](seq: Iterable[T]) {
- @inline def toColl: Coll[T] = Colls.fromArray[T](seq.toArray(RType[T].classTag))
- }
-
- implicit class EvalCollOps[T](val coll: Coll[T]) extends AnyVal {
- /** Helper type synonym. */
- type ElemTpe = SType { type WrappedType = T}
-
- /** Wraps the collection into ConstantNode using collection's element type. */
- def toConstant: Constant[SCollection[ElemTpe]] = {
- val elemTpe = Evaluation.rtypeToSType(coll.tItem).asInstanceOf[ElemTpe]
- ConstantNode[SCollection[ElemTpe]](coll, SCollectionType(elemTpe))
- }
-
- /** Transforms this collection into array of constants.
- *
- * This method have exactly the same semantics on JS and JVM IF `coll.tItem`
- * precisely describes the type of elements in `call`. (Which is the case for all
- * collections created by ErgoTree interpreter).
- *
- * However, if it is not the case, then JVM and JS will have different semantics for Byte and Short.
- *
- * The JVM version preserves v5.0 consensus protocol semantics.
- * The JS version is a reasonable approximation of the JVM version.
- */
- def toArrayOfConstants: Array[Constant[SType]] = {
- val constants = coll.toArray.map { v =>
- // see ScalaDoc for ensureTypeCarringValue
- val valToLift = Helpers.ensureTypeCarringValue(v, coll.tItem.asInstanceOf[RType[Any]])
- // call platform-specific method to transform the value to a Constant
- Platform.liftToConstant(valToLift, TransformingSigmaBuilder) match {
- case Nullable(c) => c
- case _ => sys.error(s"Cannot liftToConstant($valToLift)")
- }
- }
- constants
- }
- }
-
implicit class DslDataOps[A](data: A)(implicit tA: RType[A]) {
def toTreeData: Constant[SType] = {
CheckingSigmaBuilder.mkConstant(data.asWrappedType, Evaluation.rtypeToSType(tA))
}
}
- def toAnyValue[A:RType](x: A) = new CAnyValue(x, RType[A].asInstanceOf[RType[Any]])
-
implicit class ErgoBoxOps(val ebox: ErgoBox) extends AnyVal {
def toTestBox: Box = {
/* NOHF PROOF:
@@ -100,39 +37,103 @@ object Extensions {
Safety: used in ErgoLikeContext where boxes cannot be null
Examined ergo code: all that leads to ErgoLikeContext creation.
*/
- CostingBox(ebox)
+ CBox(ebox)
}
}
- /** Shortened String representation of `source` GroupElement. */
- def showECPoint(p: Ecp): String = {
- if (p.isIdentity) {
- "IDENTITY"
+ implicit class AvlTreeOps(val tree: AvlTree) extends AnyVal {
+
+ def contains(key: Coll[Byte], proof: Coll[Byte]): Boolean = {
+ val keyBytes = key.toArray
+ val bv = CAvlTreeVerifier(tree, proof)
+ bv.performOneOperation(Lookup(ADKey @@ keyBytes)) match {
+ case Success(r) => r match {
+ case Some(_) => true
+ case _ => false
+ }
+ case Failure(_) => false
+ }
}
- else {
- CryptoFacade.showPoint(p)
+
+ def get(key: Coll[Byte], proof: Coll[Byte]): Option[Coll[Byte]] = {
+ val keyBytes = key.toArray
+ val bv = CAvlTreeVerifier(tree, proof)
+ bv.performOneOperation(Lookup(ADKey @@ keyBytes)) match {
+ case Success(r) => r match {
+ case Some(v) => Some(Colls.fromArray(v))
+ case _ => None
+ }
+ case Failure(_) => syntax.error(s"Tree proof is incorrect $tree")
+ }
}
- }
- implicit class EcpOps(val source: Ecp) extends AnyVal {
- /** Extracts [[GroupElement]] from the Ecp instance. */
- def toGroupElement: GroupElement = SigmaDsl.GroupElement(source)
- }
+ def getMany(
+ keys: Coll[Coll[Byte]],
+ proof: Coll[Byte]): Coll[Option[Coll[Byte]]] = {
+ val bv = CAvlTreeVerifier(tree, proof)
+ keys.map { key =>
+ bv.performOneOperation(Lookup(ADKey @@ key.toArray)) match {
+ case Success(r) => r match {
+ case Some(v) => Some(Colls.fromArray(v))
+ case _ => None
+ }
+ case Failure(_) => syntax.error(s"Tree proof is incorrect $tree")
+ }
+ }
+ }
- implicit class GroupElementOps(val source: GroupElement) extends AnyVal {
- /** Shortened String representation of `source` GroupElement. */
- def showToString: String = showECPoint(source.asInstanceOf[CGroupElement].wrappedValue)
- }
+ def insert(
+ entries: Coll[(Coll[Byte], Coll[Byte])],
+ proof: Coll[Byte]): Option[AvlTree] = {
+ if (!tree.isInsertAllowed) {
+ None
+ } else {
+ val bv = CAvlTreeVerifier(tree, proof)
+ entries.forall { case (key, value) =>
+ val insertRes = bv.performOneOperation(Insert(ADKey @@ key.toArray, ADValue @@ value.toArray))
+ if (insertRes.isFailure) {
+ syntax.error(s"Incorrect insert for $tree (key: $key, value: $value, digest: ${tree.digest}): ${insertRes.failed.get}}")
+ }
+ insertRes.isSuccess
+ }
+ bv.digest match {
+ case Some(d) => Some(tree.updateDigest(Colls.fromArray(d)))
+ case _ => None
+ }
+ }
+ }
+
+ def update(
+ operations: Coll[(Coll[Byte], Coll[Byte])],
+ proof: Coll[Byte]): Option[AvlTree] = {
+ if (!tree.isUpdateAllowed) {
+ None
+ } else {
+ val bv = CAvlTreeVerifier(tree, proof)
+ operations.forall { case (key, value) =>
+ bv.performOneOperation(Update(ADKey @@ key.toArray, ADValue @@ value.toArray)).isSuccess
+ }
+ bv.digest match {
+ case Some(d) => Some(tree.updateDigest(Colls.fromArray(d)))
+ case _ => None
+ }
+ }
+ }
- implicit class DBufferOps[A](val buf: DBuffer[A]) extends AnyVal {
- /** Sum all values in `buf` using the given Numeric. */
- def sumAll(implicit n: Numeric[A]): A = {
- val limit = buf.length
- var result: A = n.zero
- cfor(0)(_ < limit, _ + 1) { i =>
- result = n.plus(result, buf.elems(i))
+ def remove(operations: Coll[Coll[Byte]], proof: Coll[Byte]): Option[AvlTree] = {
+ if (!tree.isRemoveAllowed) {
+ None
+ } else {
+ val bv = CAvlTreeVerifier(tree, proof)
+ cfor(0)(_ < operations.length, _ + 1) { i =>
+ val key = operations(i).toArray
+ bv.performOneOperation(Remove(ADKey @@ key))
+ }
+ bv.digest match {
+ case Some(v) => Some(tree.updateDigest(Colls.fromArray(v)))
+ case _ => None
+ }
}
- result
}
}
}
diff --git a/interpreter/shared/src/main/scala/sigmastate/eval/package.scala b/interpreter/shared/src/main/scala/sigmastate/eval/package.scala
index 12b73de5f6..089e11c0b8 100644
--- a/interpreter/shared/src/main/scala/sigmastate/eval/package.scala
+++ b/interpreter/shared/src/main/scala/sigmastate/eval/package.scala
@@ -1,50 +1,18 @@
package sigmastate
-import java.math.BigInteger
-
import org.ergoplatform.ErgoBox
-import sigma.data.RType
-import scorex.crypto.hash.Digest32
-import sigmastate.Values.SigmaBoolean
-import sigmastate.crypto.CryptoConstants.EcPointType
-import sigma.{Coll, CollBuilder}
import sigma._
-import supertagged.TaggedType
+import sigma.data.{AvlTreeData, SigmaBoolean}
+import sigma.eval.SigmaDsl
+import sigma.exceptions.CostLimitException
import scala.language.implicitConversions
package object eval {
- /** The primary reference to Global instance of SigmaDsl.
- * Besides operations of SigmaDslBuilder class, this instance also contains methods,
- * which are not available in Dsl code, and which are not in SigmaDslBuilder interface.
- * For example methods like `Box`, `toErgoBox` are available here, but not available in Dsl.
- * @see SigmaDslBuilder
- */
- val SigmaDsl = CostingSigmaDslBuilder
-
- /** Constructor of tuple value with more than 2 items.
- * Such long tuples are represented as Coll[Any].
- * This representaion of tuples is different from representation of pairs (x, y),
- * where Tuple2 type is used instead of Coll. */
- def TupleColl(items: Any*): Coll[Any] = Colls.fromItems(items:_*)(sigma.AnyType)
-
- trait BaseDigestColl extends TaggedType[Coll[Byte]]
-
- object Digest32Coll extends BaseDigestColl
-
- type Digest32Coll = Digest32Coll.Type
- implicit val Digest32CollRType: RType[Digest32Coll] = RType[Coll[Byte]].asInstanceOf[RType[Digest32Coll] ]
-
/** Implicit conversions between Dsl type and the type wrapped by the corresponding type Dsl type.
* Here BigInt is Dsl type and BigInteger is wrapped type.
* @see `sigma.CBigInt`
*/
- implicit def bigIntegerToBigInt(bi: BigInteger): BigInt = SigmaDsl.BigInt(bi)
- implicit def bigIntToBigInteger(bi: BigInt): BigInteger = SigmaDsl.toBigInteger(bi)
-
- implicit def ecPointToGroupElement(p: EcPointType): GroupElement = SigmaDsl.GroupElement(p)
- implicit def groupElementToECPoint(p: GroupElement): EcPointType = SigmaDsl.toECPoint(p).asInstanceOf[EcPointType]
-
implicit def sigmaBooleanToSigmaProp(p: SigmaBoolean): SigmaProp = SigmaDsl.SigmaProp(p)
implicit def sigmaPropToSigmaBoolean(p: SigmaProp): SigmaBoolean = SigmaDsl.toSigmaBoolean(p)
@@ -53,4 +21,35 @@ package object eval {
implicit def ergoBoxToBox(p: ErgoBox): Box = SigmaDsl.Box(p)
implicit def boxToErgoBox(p: Box): ErgoBox = SigmaDsl.toErgoBox(p)
+
+ def msgCostLimitError(
+ cost: Long,
+ limit: Long) = s"Estimated execution cost $cost exceeds the limit $limit"
+
+ /** Helper method to accumulate cost while checking limit.
+ *
+ * @param current current cost value
+ * @param delta additional cost to add to the current value
+ * @param limit total cost limit
+ * @param msgSuffix use case-specific error message suffix
+ * @return new increased cost when it doesn't exceed the limit
+ * @throws CostLimitException
+ */
+ def addCostChecked(
+ current: Long,
+ delta: Long,
+ limit: Long,
+ msgSuffix: => String = ""): Long = {
+ val newCost = java7.compat.Math.addExact(current, delta)
+ if (newCost > limit) {
+ throw new CostLimitException(
+ estimatedCost = newCost,
+ message = {
+ val suffix = if (msgSuffix.isEmpty) "" else s": $msgSuffix"
+ msgCostLimitError(newCost, limit) + suffix
+ },
+ cause = None)
+ }
+ newCost
+ }
}
diff --git a/interpreter/shared/src/main/scala/sigmastate/exceptions/SigmaSerializerExceptions.scala b/interpreter/shared/src/main/scala/sigmastate/exceptions/SigmaSerializerExceptions.scala
deleted file mode 100644
index ee49cb433a..0000000000
--- a/interpreter/shared/src/main/scala/sigmastate/exceptions/SigmaSerializerExceptions.scala
+++ /dev/null
@@ -1,23 +0,0 @@
-package sigmastate.exceptions
-
-/** Thrown by TypeSerializer when type prefix <= 0. */
-final class InvalidTypePrefix(message: String, cause: Option[Throwable] = None)
- extends SerializerException(message, cause)
-
-/** Thrown when the current reader position > positionLimit which is set in the Reader.
- * @see [[org.ergoplatform.validation.ValidationRules.CheckPositionLimit]]
- */
-final class ReaderPositionLimitExceeded(
- message: String,
- val position: Int,
- val positionLimit: Int,
- cause: Option[Throwable] = None)
- extends SerializerException(message, cause)
-
-/** Thrown when the current depth level > maxDepthLevel which is set in the Reader. */
-final class DeserializeCallDepthExceeded(message: String, cause: Option[Throwable] = None)
- extends SerializerException(message, cause)
-
-/** Thrown by [[org.ergoplatform.validation.ValidationRules.CheckValidOpCode]] validation rule. */
-final class InvalidOpCode(message: String, cause: Option[Throwable] = None)
- extends SerializerException(message, cause)
diff --git a/interpreter/shared/src/main/scala/sigmastate/exceptions/SigmaTyperExceptions.scala b/interpreter/shared/src/main/scala/sigmastate/exceptions/SigmaTyperExceptions.scala
index b5802e39ca..8ff9cb370f 100644
--- a/interpreter/shared/src/main/scala/sigmastate/exceptions/SigmaTyperExceptions.scala
+++ b/interpreter/shared/src/main/scala/sigmastate/exceptions/SigmaTyperExceptions.scala
@@ -1,6 +1,7 @@
package sigmastate.exceptions
-import sigmastate.lang.SourceContext
+import sigma.ast.SourceContext
+import sigma.exceptions.TyperException
final class InvalidBinaryOperationParameters(message: String, source: Option[SourceContext] = None)
extends TyperException(message, source)
diff --git a/interpreter/shared/src/main/scala/sigmastate/interpreter/ErgoTreeEvaluator.scala b/interpreter/shared/src/main/scala/sigmastate/interpreter/CErgoTreeEvaluator.scala
similarity index 64%
rename from interpreter/shared/src/main/scala/sigmastate/interpreter/ErgoTreeEvaluator.scala
rename to interpreter/shared/src/main/scala/sigmastate/interpreter/CErgoTreeEvaluator.scala
index e1bcd3119c..de8aa6b620 100644
--- a/interpreter/shared/src/main/scala/sigmastate/interpreter/ErgoTreeEvaluator.scala
+++ b/interpreter/shared/src/main/scala/sigmastate/interpreter/CErgoTreeEvaluator.scala
@@ -1,86 +1,22 @@
package sigmastate.interpreter
import org.ergoplatform.ErgoLikeContext
-import sigmastate.{FixedCost, JitCost, PerItemCost, SType, TypeBasedCost}
-import sigmastate.Values._
-import sigmastate.eval.Profiler
-import sigmastate.interpreter.ErgoTreeEvaluator.DataEnv
+import sigma.ast._
+import sigma.ast.syntax._
+import sigmastate.eval.{CAvlTreeVerifier, CProfiler}
import sigmastate.interpreter.Interpreter.ReductionResult
-import sigma.{Context, SigmaProp}
+import sigma.{AvlTree, Coll, Colls, Context, VersionContext}
import sigma.util.Extensions._
-import sigmastate.interpreter.EvalSettings._
-import supertagged.TaggedType
-import debox.{Buffer => DBuffer}
-import sigma.VersionContext
-import scala.collection.compat.immutable.ArraySeq
-import scala.util.DynamicVariable
-
-/** Configuration parameters of the evaluation run. */
-case class EvalSettings(
- /** Used together with [[ErgoTreeEvaluator.profiler]] to measure individual operations timings. */
- isMeasureOperationTime: Boolean,
- /** Used together with [[ErgoTreeEvaluator.profiler]] to measure script timings. */
- isMeasureScriptTime: Boolean,
- /** Used by [[ErgoTreeEvaluator]] to conditionally perform debug mode operations. */
- isDebug: Boolean = false,
- /** Used by [[ErgoTreeEvaluator]] to conditionally emit log messages. */
- isLogEnabled: Boolean = false,
- /** Used by [[ErgoTreeEvaluator]] to conditionally build a trace of added costs.
- * @see Value.addCost
- */
- costTracingEnabled: Boolean = false,
- /** Profiler which, when defined, should be used in [[ErgoTreeEvaluator]] constructor. */
- profilerOpt: Option[Profiler] = None,
- /** Should be set to true, if evaluation is performed as part of test suite.
- * In such a case, additional operations may be performed (such as sanity checks). */
- isTestRun: Boolean = false,
- /** If true, then expected test vectors are pretty-printed. */
- printTestVectors: Boolean = false,
- /** When Some(mode) is specified then it defines which version of the Interpreter.verify
- * and Interpreter.prove methods should use.
- * The default value is None, which means the version is defined by ErgoTree.version
- * and Context.activatedScriptVersion.
- */
- evaluationMode: Option[EvaluationMode] = None,
- /** Maximum execution cost of a script used by profiler.
- * @see ErgoTreeEvaluator
- */
- scriptCostLimitInEvaluator: Int = 1000000
-)
-
-object EvalSettings {
- /** Enumeration type of evaluation modes of [[Interpreter]].
- * This type can be removed in v5.x releases together with AOT implementation once v5.0
- * protocol is activated.
- */
- object EvaluationMode extends TaggedType[Int] {
- implicit class EvaluationModeOps(val x: EvaluationMode) extends AnyVal {
- def name: String = x match {
- case AotEvaluationMode => "AotEvaluationMode"
- case JitEvaluationMode => "JitEvaluationMode"
- }
-
- /** Returns true if AOT interpreter should be evaluated. */
- def okEvaluateAot: Boolean = {
- x == AotEvaluationMode
- }
-
- /** Returns true if JIT interpreter should be evaluated. */
- def okEvaluateJit: Boolean = {
- x == JitEvaluationMode
- }
- }
- }
- type EvaluationMode = EvaluationMode.Type
-
- /** Evaluation mode when the interpreter is executing using AOT costing implementation
- * of v4.x protocol. */
- val AotEvaluationMode: EvaluationMode = EvaluationMode @@ 1 // first bit
+import debox.{cfor, Buffer => DBuffer}
+import scorex.crypto.authds.ADKey
+import sigma.ast.SAvlTreeMethods._
+import sigma.ast.SType
+import sigma.data.{CSigmaProp, KeyValueColl, SigmaBoolean}
+import sigma.eval.{AvlTreeVerifier, ErgoTreeEvaluator, EvalSettings, Profiler}
+import sigma.eval.ErgoTreeEvaluator.DataEnv
- /** Evaluation mode when the interpreter is executing using JIT costing implementation
- * of v5.x protocol. */
- val JitEvaluationMode: EvaluationMode = EvaluationMode @@ 2 // second bit
-}
+import scala.collection.compat.immutable.ArraySeq
+import scala.util.{DynamicVariable, Failure, Success}
/** Result of JITC evaluation with costing. */
case class JitEvalResult[A](value: A, cost: JitCost)
@@ -121,17 +57,169 @@ case class JitEvalResult[A](value: A, cost: JitCost)
* @param profiler Performs operations profiling and time measurements (if enabled in settings).
* @param settings Settings to be used during evaluation.
*/
-class ErgoTreeEvaluator(
+class CErgoTreeEvaluator(
val context: Context,
val constants: Seq[Constant[SType]],
protected val coster: CostAccumulator,
val profiler: Profiler,
- val settings: EvalSettings) {
+ val settings: EvalSettings) extends ErgoTreeEvaluator {
+
+ override def createTreeVerifier(tree: AvlTree, proof: Coll[Byte]): AvlTreeVerifier =
+ CAvlTreeVerifier(tree, proof)
+
+ /** Creates [[sigma.eval.AvlTreeVerifier]] for the given tree and proof. */
+ def createVerifier(tree: AvlTree, proof: Coll[Byte]) = {
+ // the cost of tree reconstruction from proof is O(proof.length)
+ addSeqCost(CreateAvlVerifier_Info, proof.length) { () =>
+ CAvlTreeVerifier(tree, proof)
+ }
+ }
+
+ override def contains_eval(mc: MethodCall, tree: AvlTree, key: Coll[Byte], proof: Coll[Byte]): Boolean = {
+ val bv = createVerifier(tree, proof)
+ val nItems = bv.treeHeight
+ var res = false
+ // the cost of tree lookup is O(bv.treeHeight)
+ addSeqCost(LookupAvlTree_Info, nItems) { () =>
+ res = bv.performLookup(ADKey @@ key.toArray) match {
+ case Success(r) => r match {
+ case Some(_) => true
+ case _ => false
+ }
+ case Failure(_) => false
+ }
+ }
+ res
+ }
+
+ override def get_eval(mc: MethodCall, tree: AvlTree, key: Coll[Byte], proof: Coll[Byte]): Option[Coll[Byte]] = {
+ val bv = createVerifier(tree, proof)
+ val nItems = bv.treeHeight
+
+ // the cost of tree lookup is O(bv.treeHeight)
+ addSeqCost(LookupAvlTree_Info, nItems) { () =>
+ bv.performLookup(ADKey @@ key.toArray) match {
+ case Success(r) => r match {
+ case Some(v) => Some(Colls.fromArray(v))
+ case _ => None
+ }
+ case Failure(_) => syntax.error(s"Tree proof is incorrect $tree")
+ }
+ }
+ }
+
+ override def getMany_eval(
+ mc: MethodCall,
+ tree: AvlTree,
+ keys: Coll[Coll[Byte]],
+ proof: Coll[Byte]): Coll[Option[Coll[Byte]]] = {
+ val bv = createVerifier(tree, proof)
+ val nItems = bv.treeHeight
+ keys.map { key =>
+ // the cost of tree lookup is O(bv.treeHeight)
+ addSeqCost(LookupAvlTree_Info, nItems) { () =>
+ bv.performLookup(ADKey @@ key.toArray) match {
+ case Success(r) => r match {
+ case Some(v) => Some(Colls.fromArray(v))
+ case _ => None
+ }
+ case Failure(_) => syntax.error(s"Tree proof is incorrect $tree")
+ }
+ }
+ }
+ }
+
+ override def insert_eval(mc: MethodCall, tree: AvlTree, entries: KeyValueColl, proof: Coll[Byte]): Option[AvlTree] = {
+ addCost(isInsertAllowed_Info)
+ if (!tree.isInsertAllowed) {
+ None
+ } else {
+ val bv = createVerifier(tree, proof)
+ // when the tree is empty we still need to add the insert cost
+ val nItems = Math.max(bv.treeHeight, 1)
+ entries.forall { case (key, value) =>
+ var res = true
+ // the cost of tree lookup is O(bv.treeHeight)
+ addSeqCost(InsertIntoAvlTree_Info, nItems) { () =>
+ val insertRes = bv.performInsert(key.toArray, value.toArray)
+ // TODO v6.0: throwing exception is not consistent with update semantics
+ // however it preserves v4.0 semantics (see https://github.com/ScorexFoundation/sigmastate-interpreter/issues/908)
+ if (insertRes.isFailure) {
+ syntax.error(s"Incorrect insert for $tree (key: $key, value: $value, digest: ${tree.digest}): ${insertRes.failed.get}}")
+ }
+ res = insertRes.isSuccess
+ }
+ res
+ }
+ bv.digest match {
+ case Some(d) =>
+ addCost(updateDigest_Info)
+ Some(tree.updateDigest(Colls.fromArray(d)))
+ case _ => None
+ }
+ }
+ }
+
+ override def update_eval(
+ mc: MethodCall, tree: AvlTree,
+ operations: KeyValueColl, proof: Coll[Byte]): Option[AvlTree] = {
+ addCost(isUpdateAllowed_Info)
+ if (!tree.isUpdateAllowed) {
+ None
+ } else {
+ val bv = createVerifier(tree, proof)
+ // when the tree is empty we still need to add the insert cost
+ val nItems = Math.max(bv.treeHeight, 1)
+
+ // here we use forall as looping with fast break on first failed tree oparation
+ operations.forall { case (key, value) =>
+ var res = true
+ // the cost of tree update is O(bv.treeHeight)
+ addSeqCost(UpdateAvlTree_Info, nItems) { () =>
+ val updateRes = bv.performUpdate(key.toArray, value.toArray)
+ res = updateRes.isSuccess
+ }
+ res
+ }
+ bv.digest match {
+ case Some(d) =>
+ addCost(updateDigest_Info)
+ Some(tree.updateDigest(Colls.fromArray(d)))
+ case _ => None
+ }
+ }
+ }
+
+ override def remove_eval(
+ mc: MethodCall, tree: AvlTree,
+ operations: Coll[Coll[Byte]], proof: Coll[Byte]): Option[AvlTree] = {
+ addCost(isRemoveAllowed_Info)
+ if (!tree.isRemoveAllowed) {
+ None
+ } else {
+ val bv = createVerifier(tree, proof)
+ // when the tree is empty we still need to add the insert cost
+ val nItems = Math.max(bv.treeHeight, 1)
+ cfor(0)(_ < operations.length, _ + 1) { i =>
+ addSeqCost(RemoveAvlTree_Info, nItems) { () =>
+ val key = operations(i).toArray
+ bv.performRemove(key)
+ }
+ }
+ addCost(digest_Info)
+ bv.digest match {
+ case Some(d) =>
+ addCost(updateDigest_Info)
+ Some(tree.updateDigest(Colls.fromArray(d)))
+ case _ => None
+ }
+ }
+ }
/** Evaluates the given expression in the given data environment. */
def eval(env: DataEnv, exp: SValue): Any = {
VersionContext.checkVersions(context.activatedScriptVersion, context.currentErgoTreeVersion)
- ErgoTreeEvaluator.currentEvaluator.withValue(this) {
+ CErgoTreeEvaluator.currentEvaluator.withValue(this) {
exp.evalTo[Any](env)(this)
}
}
@@ -168,33 +256,18 @@ class ErgoTreeEvaluator(
costTrace.clear()
}
- /** Adds the given cost to the `coster`. If tracing is enabled, associates the cost with
- * the given operation.
- *
- * @param costKind kind of the cost to be added to `coster`
- * @param opDesc operation descriptor to associate the cost with (when costTracingEnabled)
- */
- final def addCost(costKind: FixedCost, opDesc: OperationDesc): Unit = {
+ override def addCost(costKind: FixedCost, opDesc: OperationDesc): Unit = {
coster.add(costKind.cost)
if (settings.costTracingEnabled) {
costTrace += FixedCostItem(opDesc, costKind)
}
}
- @inline final def addCost(costInfo: OperationCostInfo[FixedCost]): Unit = {
+ override def addCost(costInfo: OperationCostInfo[FixedCost]): Unit = {
addCost(costInfo.costKind, costInfo.opDesc)
}
- /** Add the cost given by the cost descriptor and the type to the accumulator and
- * associate it with this operation descriptor.
- *
- * @param costKind descriptor of the cost
- * @param tpe specific type for which the cost should be computed by this descriptor
- * (see costFunc method)
- * @param opDesc operation which is associated with this cost
- */
- @inline
- final def addTypeBasedCost[R](costKind: TypeBasedCost,
+ override def addTypeBasedCost[R](costKind: TypeBasedCost,
tpe: SType, opDesc: OperationDesc)(block: () => R): R = {
var costItem: TypeBasedCostItem = null
if (settings.costTracingEnabled) {
@@ -219,14 +292,8 @@ class ErgoTreeEvaluator(
}
}
- /** Adds the given cost to the `coster`. If tracing is enabled, associates the cost with
- * the given operation.
- * @param costKind kind of the cost to be added to `coster`
- * @param opDesc the operation descriptor to associate the cost with (when costTracingEnabled)
- * @param block operation executed under the given cost
- * @hotspot don't beautify the code
- */
- final def addFixedCost(costKind: FixedCost, opDesc: OperationDesc)(block: => Unit): Unit = {
+ /** @hotspot don't beautify the code */
+ override def addFixedCost(costKind: FixedCost, opDesc: OperationDesc)(block: => Unit): Unit = {
var costItem: FixedCostItem = null
if (settings.costTracingEnabled) {
costItem = FixedCostItem(opDesc, costKind)
@@ -247,20 +314,12 @@ class ErgoTreeEvaluator(
}
}
- @inline
- final def addFixedCost(costInfo: OperationCostInfo[FixedCost])(block: => Unit): Unit = {
+ override def addFixedCost(costInfo: OperationCostInfo[FixedCost])(block: => Unit): Unit = {
addFixedCost(costInfo.costKind, costInfo.opDesc)(block)
}
- /** Adds the given cost to the `coster`. If tracing is enabled, creates a new cost item
- * with the given operation.
- *
- * @param costKind the cost to be added to `coster` for each item
- * @param nItems the number of items
- * @param opDesc the operation to associate the cost with (when costTracingEnabled)
- * @hotspot don't beautify the code
- */
- final def addSeqCostNoOp(costKind: PerItemCost, nItems: Int, opDesc: OperationDesc): Unit = {
+ /** @hotspot don't beautify the code */
+ override def addSeqCostNoOp(costKind: PerItemCost, nItems: Int, opDesc: OperationDesc): Unit = {
var costItem: SeqCostItem = null
if (settings.costTracingEnabled) {
costItem = SeqCostItem(opDesc, costKind, nItems)
@@ -270,17 +329,7 @@ class ErgoTreeEvaluator(
coster.add(cost)
}
- /** Adds the given cost to the `coster`. If tracing is enabled, creates a new cost item
- * with the given operation.
- *
- * @param costKind the cost to be added to `coster` for each item
- * @param nItems the number of items
- * @param opDesc the operation to associate the cost with (when costTracingEnabled)
- * @param block operation executed under the given cost
- * @tparam R result type of the operation
- * @hotspot don't beautify the code
- */
- final def addSeqCost[R](costKind: PerItemCost, nItems: Int, opDesc: OperationDesc)(block: () => R): R = {
+ override def addSeqCost[R](costKind: PerItemCost, nItems: Int, opDesc: OperationDesc)(block: () => R): R = {
var costItem: SeqCostItem = null
if (settings.costTracingEnabled) {
costItem = SeqCostItem(opDesc, costKind, nItems)
@@ -304,29 +353,12 @@ class ErgoTreeEvaluator(
}
}
- /** Adds the cost to the `coster`. See the other overload for details. */
- @inline
- final def addSeqCost[R](costInfo: OperationCostInfo[PerItemCost], nItems: Int)
+ override def addSeqCost[R](costInfo: OperationCostInfo[PerItemCost], nItems: Int)
(block: () => R): R = {
addSeqCost(costInfo.costKind, nItems, costInfo.opDesc)(block)
}
- /** Adds the cost to the `coster`. If tracing is enabled, creates a new cost item with
- * the given operation descriptor and cost kind. If time measuring is enabled also
- * performs profiling.
- *
- * WARNING: The cost is accumulated AFTER the block is executed.
- * Each usage of this method should be accompanied with a proof of why this cannot lead
- * to unbounded execution (see all usages).
- *
- * @param costKind the cost descriptor to be used to compute the cost based on the
- * actual number of items returned by the `block`
- * @param opDesc the operation to associate the cost with (when costTracingEnabled)
- * @param block operation executed under the given cost descriptors, returns the
- * actual number of items processed
- * @hotspot don't beautify the code
- */
- final def addSeqCost(costKind: PerItemCost, opDesc: OperationDesc)(block: () => Int): Unit = {
+ override def addSeqCost(costKind: PerItemCost, opDesc: OperationDesc)(block: () => Int): Unit = {
var costItem: SeqCostItem = null
var nItems = 0
if (settings.isMeasureOperationTime) {
@@ -350,18 +382,15 @@ class ErgoTreeEvaluator(
}
}
- /** Adds the cost to the `coster`. See the other overload for details. */
- final def addSeqCost(costInfo: OperationCostInfo[PerItemCost])(block: () => Int): Unit = {
+ override def addSeqCost(costInfo: OperationCostInfo[PerItemCost])(block: () => Int): Unit = {
addSeqCost(costInfo.costKind, costInfo.opDesc)(block)
}
}
-object ErgoTreeEvaluator {
- /** Immutable data environment used to assign data values to graph nodes. */
- type DataEnv = Map[Int, Any]
+object CErgoTreeEvaluator {
/** Size of data block in bytes. Used in JIT cost calculations.
- * @see [[sigmastate.NEQ]],
+ * @see [[NEQ]],
*/
val DataBlockSize: Int = 512
@@ -369,7 +398,7 @@ object ErgoTreeEvaluator {
val EmptyDataEnv: DataEnv = Map.empty
/** A profiler which is used by default if [[EvalSettings.isMeasureOperationTime]] is enabled. */
- val DefaultProfiler = new Profiler
+ val DefaultProfiler = new CProfiler
/** Default global [[EvalSettings]] instance. */
val DefaultEvalSettings = EvalSettings(
@@ -378,26 +407,27 @@ object ErgoTreeEvaluator {
/** Evaluator currently is being executed on the current thread.
* This variable is set in a single place, specifically in the `eval` method of
- * [[ErgoTreeEvaluator]].
+ * [[CErgoTreeEvaluator]].
+ *
* @see getCurrentEvaluator
*/
- private[sigmastate] val currentEvaluator = new DynamicVariable[ErgoTreeEvaluator](null)
+ private[sigmastate] val currentEvaluator = new DynamicVariable[CErgoTreeEvaluator](null)
/** Returns a current evaluator for the current thread. */
- def getCurrentEvaluator: ErgoTreeEvaluator = currentEvaluator.value
+ def getCurrentEvaluator: CErgoTreeEvaluator = currentEvaluator.value
- /** Creates a new [[ErgoTreeEvaluator]] instance with the given profiler and settings.
+ /** Creates a new [[CErgoTreeEvaluator]] instance with the given profiler and settings.
* The returned evaluator can be used to initialize the `currentEvaluator` variable.
* As a result, cost-aware operations (code blocks) can be implemented, even when those
* operations don't involve ErgoTree evaluation.
* As an example, see methods in [[sigmastate.SigSerializer]] and
* [[sigmastate.FiatShamirTree]] where cost-aware code blocks are used.
*/
- def forProfiling(profiler: Profiler, evalSettings: EvalSettings): ErgoTreeEvaluator = {
+ def forProfiling(profiler: CProfiler, evalSettings: EvalSettings): CErgoTreeEvaluator = {
val acc = new CostAccumulator(
initialCost = JitCost(0),
costLimit = Some(JitCost.fromBlockCost(evalSettings.scriptCostLimitInEvaluator)))
- new ErgoTreeEvaluator(
+ new CErgoTreeEvaluator(
context = null,
constants = ArraySeq.empty,
acc, profiler, evalSettings.copy(profilerOpt = Some(profiler)))
@@ -406,7 +436,7 @@ object ErgoTreeEvaluator {
/** Executes [[FixedCost]] code `block` and use the given evaluator `E` to perform
* profiling and cost tracing.
* This helper method allows implementation of cost-aware code blocks by using
- * thread-local instance of [[ErgoTreeEvaluator]].
+ * thread-local instance of [[CErgoTreeEvaluator]].
* If the `currentEvaluator` [[DynamicVariable]] is not initialized (equals to null),
* then the block is executed with minimal overhead.
*
@@ -434,7 +464,7 @@ object ErgoTreeEvaluator {
/** Executes [[PerItemCost]] code `block` and use the given evaluator `E` to perform
* profiling and cost tracing.
* This helper method allows implementation of cost-aware code blocks by using
- * thread-local instance of [[ErgoTreeEvaluator]].
+ * thread-local instance of [[CErgoTreeEvaluator]].
* If the `currentEvaluator` [[DynamicVariable]] is not initialized (equals to null),
* then the block is executed with minimal overhead.
*
@@ -467,8 +497,7 @@ object ErgoTreeEvaluator {
def evalToCrypto(context: ErgoLikeContext, ergoTree: ErgoTree, evalSettings: EvalSettings): ReductionResult = {
val (res, cost) = eval(context, ergoTree.constants, ergoTree.toProposition(replaceConstants = false), evalSettings)
val sb = res match {
- case sp: SigmaProp =>
- sigmastate.eval.SigmaDsl.toSigmaBoolean(sp)
+ case sp: CSigmaProp => sp.wrappedValue
case sb: SigmaBoolean => sb
case _ => error(s"Expected SigmaBoolean but was: $res")
}
@@ -504,7 +533,7 @@ object ErgoTreeEvaluator {
* @param costAccumulator [[CostAccumulator]] instance used for accumulating costs
* @param constants collection of segregated constants which can be refered by
* [[ConstantPlaceholder]]s in `exp`
- * @param exp ErgoTree expression represented as [[sigmastate.Values.Value]]
+ * @param exp ErgoTree expression represented as [[sigma.ast.Value]]
* @param evalSettings evaluation settings
* @return 1) the result of evaluating `exp` in a given context and
* 2) an accumulated JIT cost estimation.
@@ -514,9 +543,9 @@ object ErgoTreeEvaluator {
constants: Seq[Constant[SType]],
exp: SValue,
evalSettings: EvalSettings): (Any, Int) = {
- val evaluator = new ErgoTreeEvaluator(
+ val evaluator = new CErgoTreeEvaluator(
sigmaContext, constants, costAccumulator, DefaultProfiler, evalSettings)
- val res = evaluator.eval(Map(), exp)
+ val res = evaluator.eval(Map(), exp)
val cost = costAccumulator.totalCost.toBlockCost // scale to block cost
(res, cost)
}
diff --git a/interpreter/shared/src/main/scala/sigmastate/interpreter/CostAccumulator.scala b/interpreter/shared/src/main/scala/sigmastate/interpreter/CostAccumulator.scala
index fe86acf9a4..c79a9b77df 100644
--- a/interpreter/shared/src/main/scala/sigmastate/interpreter/CostAccumulator.scala
+++ b/interpreter/shared/src/main/scala/sigmastate/interpreter/CostAccumulator.scala
@@ -1,7 +1,7 @@
package sigmastate.interpreter
-import sigmastate.JitCost
-import sigmastate.exceptions.CostLimitException
+import sigma.ast.JitCost
+import sigma.exceptions.CostLimitException
/** Encapsulate simple monotonic (add only) counter with reset. */
class CostCounter(val initialCost: JitCost) {
diff --git a/interpreter/shared/src/main/scala/sigmastate/interpreter/Hint.scala b/interpreter/shared/src/main/scala/sigmastate/interpreter/Hint.scala
index 2e894502f4..d4ce5bf155 100644
--- a/interpreter/shared/src/main/scala/sigmastate/interpreter/Hint.scala
+++ b/interpreter/shared/src/main/scala/sigmastate/interpreter/Hint.scala
@@ -1,8 +1,8 @@
package sigmastate.interpreter
+import sigma.data.{SigmaBoolean, SigmaLeaf}
import java.math.BigInteger
-import sigmastate.{NodePosition, SigmaLeaf, UncheckedTree}
-import sigmastate.Values.SigmaBoolean
+import sigmastate.{NodePosition, UncheckedTree}
import sigmastate.crypto.FirstProverMessage
import sigmastate.crypto.VerifierMessage.Challenge
diff --git a/interpreter/shared/src/main/scala/sigmastate/interpreter/Interpreter.scala b/interpreter/shared/src/main/scala/sigmastate/interpreter/Interpreter.scala
index cb519e12ae..6b673038c7 100644
--- a/interpreter/shared/src/main/scala/sigmastate/interpreter/Interpreter.scala
+++ b/interpreter/shared/src/main/scala/sigmastate/interpreter/Interpreter.scala
@@ -1,30 +1,32 @@
package sigmastate.interpreter
-import java.util
-import sigma.kiama.rewriting.Rewriter.{everywherebu, rule, strategy}
+import debox.cfor
import org.ergoplatform.ErgoLikeContext
-import org.ergoplatform.validation.SigmaValidationSettings
import org.ergoplatform.validation.ValidationRules._
-import sigmastate.crypto.DLogProtocol.ProveDlog
-import sigmastate.SCollection.SByteArray
-import sigmastate.Values._
-import sigmastate.crypto.DLogProtocol.{DLogInteractiveProver, FirstDLogProverMessage, ProveDlog}
+import sigma.VersionContext
+import sigma.ast.SCollection.SByteArray
+import sigma.ast.syntax._
+import sigma.ast._
+import sigma.data.{CAND, COR, CTHRESHOLD, ProveDHTuple, ProveDlog, SigmaBoolean, TrivialProp}
+import sigma.kiama.rewriting.Rewriter.{everywherebu, rule, strategy}
+import sigma.kiama.rewriting.Strategy
+import sigma.serialization.SigSerializer._
+import sigma.serialization.{SigSerializer, SigmaSerializer, ValueSerializer}
+import sigma.validation.SigmaValidationSettings
+import sigma.validation.ValidationRules.trySoftForkable
+import sigmastate.FiatShamirTree._
+import sigmastate._
+import sigmastate.crypto.DLogProtocol.{DLogProver, FirstDLogProverMessage}
import sigmastate.crypto._
+import sigmastate.eval.{CProfiler, addCostChecked}
+import sigmastate.interpreter.CErgoTreeEvaluator.fixedCostOp
import sigmastate.interpreter.Interpreter._
-import sigmastate.serialization.{SigmaSerializer, ValueSerializer}
-import sigmastate.utxo.DeserializeContext
-import sigmastate.{SType, _}
-import sigmastate.eval.{Evaluation, Profiler, SigmaDsl}
-import sigmastate.FiatShamirTree._
-import sigmastate.SigSerializer._
-import sigmastate.eval.Evaluation.addCostChecked
-import sigmastate.interpreter.ErgoTreeEvaluator.fixedCostOp
+import sigma.ast.syntax.ValueOps
+import sigma.eval.{EvalSettings, SigmaDsl}
+import sigma.exceptions.{CostLimitException, InterpreterException}
+import sigma.interpreter.ProverResult
+import sigma.util.CollectionUtil
import sigmastate.utils.Helpers._
-import sigmastate.lang.Terms.ValueOps
-import debox.cfor
-import sigma.VersionContext
-import sigma.kiama.rewriting.Strategy
-import sigmastate.exceptions.{CostLimitException, InterpreterException}
import scala.util.{Success, Try}
@@ -52,10 +54,13 @@ trait Interpreter {
type ProofT = UncheckedTree
- /** Evaluation settings used by [[ErgoTreeEvaluator]] which is used by this
+ /** Force initialization of reflection. */
+ private val _ = InterpreterReflection
+
+ /** Evaluation settings used by [[CErgoTreeEvaluator]] which is used by this
* interpreter to perform fullReduction.
*/
- protected def evalSettings: EvalSettings = ErgoTreeEvaluator.DefaultEvalSettings
+ protected def evalSettings: EvalSettings = CErgoTreeEvaluator.DefaultEvalSettings
/** Logs the given message string. Can be overridden in the derived interpreter classes
* to redefine the default behavior. */
@@ -70,13 +75,13 @@ trait Interpreter {
/** The cost of Value[T] deserialization is O(n), where n is the length of its bytes
* array. To evaluate [[DeserializeContext]] and
- * [[sigmastate.utxo.DeserializeRegister]] we add the following cost of deserialization
+ * [[DeserializeRegister]] we add the following cost of deserialization
* for each byte.
*/
val CostPerByteDeserialized = 2
/** The cost of substituting [[DeserializeContext]] and
- * [[sigmastate.utxo.DeserializeRegister]] nodes with the deserialized expression is
+ * [[DeserializeRegister]] nodes with the deserialized expression is
* O(n), where n is the number of bytes in ErgoTree.
* The following is the cost added for each ErgoTree.bytes.
*/
@@ -96,7 +101,7 @@ trait Interpreter {
val script = ValueSerializer.deserialize(r) // Why ValueSerializer? read NOTE above
val scriptComplexity = java7.compat.Math.multiplyExact(scriptBytes.length, CostPerByteDeserialized)
- val currCost = Evaluation.addCostChecked(context.initCost, scriptComplexity, context.costLimit)
+ val currCost = addCostChecked(context.initCost, scriptComplexity, context.costLimit)
val ctx1 = context.withInitCost(currCost).asInstanceOf[CTX]
(ctx1, script)
}
@@ -170,7 +175,7 @@ trait Interpreter {
val (resProp, cost) = {
val ctx = context.asInstanceOf[ErgoLikeContext]
- ErgoTreeEvaluator.eval(ctx, ErgoTree.EmptyConstants, exp, evalSettings) match {
+ CErgoTreeEvaluator.eval(ctx, ErgoTree.EmptyConstants, exp, evalSettings) match {
case (p: sigma.SigmaProp, c) => (p, c)
case (res, _) =>
sys.error(s"Invalid result type of $res: expected SigmaProp when evaluating $exp")
@@ -199,7 +204,6 @@ trait Interpreter {
def fullReduction(ergoTree: ErgoTree,
ctx: CTX,
env: ScriptEnv): ReductionResult = {
- implicit val vs: SigmaValidationSettings = ctx.validationSettings
val context = ctx.withErgoTreeVersion(ergoTree.version).asInstanceOf[CTX]
VersionContext.withVersions(context.activatedScriptVersion, ergoTree.version) {
val prop = propositionFromErgoTree(ergoTree, context)
@@ -210,12 +214,12 @@ trait Interpreter {
// NOTE, evaluator cost unit needs to be scaled to the cost unit of context
val evalCost = Eval_SigmaPropConstant.costKind.cost.toBlockCost
- val resCost = Evaluation.addCostChecked(context.initCost, evalCost, context.costLimit)
+ val resCost = addCostChecked(context.initCost, evalCost, context.costLimit)
ReductionResult(sb, resCost)
case _ if !ergoTree.hasDeserialize =>
val ctx = context.asInstanceOf[ErgoLikeContext]
val res = VersionContext.withVersions(ctx.activatedScriptVersion, ergoTree.version) {
- ErgoTreeEvaluator.evalToCrypto(ctx, ergoTree, evalSettings)
+ CErgoTreeEvaluator.evalToCrypto(ctx, ergoTree, evalSettings)
}
res
case _ =>
@@ -241,7 +245,7 @@ trait Interpreter {
implicit val vs: SigmaValidationSettings = context.validationSettings
val res = VersionContext.withVersions(context.activatedScriptVersion, ergoTree.version) {
val deserializeSubstitutionCost = java7.compat.Math.multiplyExact(ergoTree.bytes.length, CostPerTreeByte)
- val currCost = Evaluation.addCostChecked(context.initCost, deserializeSubstitutionCost, context.costLimit)
+ val currCost = addCostChecked(context.initCost, deserializeSubstitutionCost, context.costLimit)
val context1 = context.withInitCost(currCost).asInstanceOf[CTX]
val (propTree, context2) = trySoftForkable[(SigmaPropValue, CTX)](whenSoftFork = (TrueSigmaProp, context1)) {
applyDeserializeContextJITC(context, prop)
@@ -361,7 +365,7 @@ trait Interpreter {
val fullCost = addCryptoCost(reduced.value, reduced.cost, context.costLimit)
val ok = if (evalSettings.isMeasureOperationTime) {
- val E = ErgoTreeEvaluator.forProfiling(verifySignatureProfiler, evalSettings)
+ val E = CErgoTreeEvaluator.forProfiling(verifySignatureProfiler, evalSettings)
verifySignature(reduced.value, message, proof)(E)
} else {
verifySignature(reduced.value, message, proof)(null)
@@ -374,10 +378,10 @@ trait Interpreter {
}
// Perform Verifier Steps 4-6
- private def checkCommitments(sp: UncheckedSigmaTree, message: Array[Byte])(implicit E: ErgoTreeEvaluator): Boolean = {
+ private def checkCommitments(sp: UncheckedSigmaTree, message: Array[Byte])(implicit E: CErgoTreeEvaluator): Boolean = {
// Perform Verifier Step 4
val newRoot = computeCommitments(sp).get.asInstanceOf[UncheckedSigmaTree]
- val bytes = concatArrays(FiatShamirTree.toBytes(newRoot), message)
+ val bytes = CollectionUtil.concatArrays(FiatShamirTree.toBytes(newRoot), message)
/**
* Verifier Steps 5-6: Convert the tree to a string `s` for input to the Fiat-Shamir hash function,
* using the same conversion as the prover in 7
@@ -393,20 +397,20 @@ trait Interpreter {
* per the verifier algorithm of the leaf's Sigma-protocol.
* If the verifier algorithm of the Sigma-protocol for any of the leaves rejects, then reject the entire proof.
*/
- private[sigmastate] val computeCommitments: Strategy = everywherebu(rule[Any] {
+ val computeCommitments: Strategy = everywherebu(rule[Any] {
case c: UncheckedConjecture => c // Do nothing for internal nodes
case sn: UncheckedSchnorr =>
- implicit val E = ErgoTreeEvaluator.getCurrentEvaluator
+ implicit val E = CErgoTreeEvaluator.getCurrentEvaluator
fixedCostOp(ComputeCommitments_Schnorr) {
- val a = DLogInteractiveProver.computeCommitment(sn.proposition, sn.challenge, sn.secondMessage)
+ val a = DLogProver.computeCommitment(sn.proposition, sn.challenge, sn.secondMessage)
sn.copy(commitmentOpt = Some(FirstDLogProverMessage(a)))
}
case dh: UncheckedDiffieHellmanTuple =>
- implicit val E = ErgoTreeEvaluator.getCurrentEvaluator
+ implicit val E = CErgoTreeEvaluator.getCurrentEvaluator
fixedCostOp(ComputeCommitments_DHT) {
- val (a, b) = DiffieHellmanTupleInteractiveProver.computeCommitment(dh.proposition, dh.challenge, dh.secondMessage)
+ val (a, b) = DiffieHellmanTupleProver.computeCommitment(dh.proposition, dh.challenge, dh.secondMessage)
dh.copy(commitmentOpt = Some(FirstDHTupleProverMessage(a, b)))
}
@@ -450,7 +454,7 @@ trait Interpreter {
*/
def verifySignature(sigmaTree: SigmaBoolean,
message: Array[Byte],
- signature: Array[Byte])(implicit E: ErgoTreeEvaluator): Boolean = {
+ signature: Array[Byte])(implicit E: CErgoTreeEvaluator): Boolean = {
// Perform Verifier Steps 1-3
try {
SigSerializer.parseAndComputeChallenges(sigmaTree, signature) match {
@@ -582,7 +586,7 @@ object Interpreter {
/** An instance of profiler used to measure cost parameters of verifySignature
* operations.
*/
- val verifySignatureProfiler = new Profiler
+ val verifySignatureProfiler = new CProfiler
private def toValidScriptTypeJITC(exp: SValue): SigmaPropValue = exp match {
case v: Value[SBoolean.type]@unchecked if v.tpe == SBoolean => v.toSigmaProp
@@ -590,7 +594,4 @@ object Interpreter {
case x => throw new Error(s"Context-dependent pre-processing should produce tree of type Boolean or SigmaProp but was $x")
}
- /** Helper method to throw errors from Interpreter. */
- def error(msg: String) = throw new InterpreterException(msg)
-
}
\ No newline at end of file
diff --git a/interpreter/shared/src/main/scala/sigmastate/interpreter/InterpreterContext.scala b/interpreter/shared/src/main/scala/sigmastate/interpreter/InterpreterContext.scala
index 864146ca07..38fc78fdb6 100644
--- a/interpreter/shared/src/main/scala/sigmastate/interpreter/InterpreterContext.scala
+++ b/interpreter/shared/src/main/scala/sigmastate/interpreter/InterpreterContext.scala
@@ -1,59 +1,8 @@
package sigmastate.interpreter
-import org.ergoplatform.validation.SigmaValidationSettings
-import sigmastate.SType
-import sigmastate.Values.EvaluatedValue
-import sigmastate.interpreter.ContextExtension.VarBinding
-import sigmastate.serialization.SigmaSerializer
-import sigmastate.utils.{SigmaByteWriter, SigmaByteReader}
-import sigma.AnyValue
-
-/**
- * User-defined variables to be put into context.
- * Each variable is identified by `id: Byte` and can be accessed from a script
- * using `getVar[T](id)` operation.
- * The value of the variable is represented by [[sigmastate.Values.Constant]] instance,
- * which contains both data value and [[SType]] descriptor. The descriptor is checked
- * against the type `T` expected in the script operation. If the types don't match,
- * exception is thrown and the box spending (protected by the script) fails.
- *
- * @param values internal container of the key-value pairs
- */
-case class ContextExtension(values: scala.collection.Map[Byte, EvaluatedValue[_ <: SType]]) {
- def add(bindings: VarBinding*): ContextExtension =
- ContextExtension(values ++ bindings)
-}
-
-object ContextExtension {
- /** Immutable instance of empty ContextExtension, which can be shared to avoid
- * allocations. */
- val empty = ContextExtension(Map())
-
- /** Type of context variable binding. */
- type VarBinding = (Byte, EvaluatedValue[_ <: SType])
-
- object serializer extends SigmaSerializer[ContextExtension, ContextExtension] {
- override def serialize(obj: ContextExtension, w: SigmaByteWriter): Unit = {
- val size = obj.values.size
- if (size > Byte.MaxValue)
- error(s"Number of ContextExtension values $size exceeds ${Byte.MaxValue}.")
- w.putUByte(size)
- obj.values.foreach { case (id, v) => w.put(id).putValue(v) }
- }
-
- override def parse(r: SigmaByteReader): ContextExtension = {
- val extSize = r.getByte()
- if (extSize < 0)
- error(s"Negative amount of context extension values: $extSize")
-
- val values = (0 until extSize)
- .map(_ => (r.getByte(), r.getValue().asInstanceOf[EvaluatedValue[_ <: SType]]))
-
- ContextExtension(values.toMap)
- }
- }
-}
-
+import sigma.interpreter.ContextExtension
+import sigma.interpreter.ContextExtension.VarBinding
+import sigma.validation.SigmaValidationSettings
/** Base class of the context passed to verifier and prover.
* @see [[sigmastate.interpreter.Interpreter]]
@@ -111,12 +60,8 @@ trait InterpreterContext {
* Thus, this method performs transformation from Ergo to internal Sigma representation
* of all context data.
*
- * @param extensions additional context variables which will be merged with those in the
- * `extension` of this instance, overriding existing bindings in case
- * variable ids overlap.
- *
* @see sigmastate.eval.Evaluation
*/
- def toSigmaContext(extensions: Map[Byte, AnyValue] = Map()): sigma.Context
+ def toSigmaContext(): sigma.Context
}
diff --git a/interpreter/shared/src/main/scala/sigmastate/interpreter/ProverInterpreter.scala b/interpreter/shared/src/main/scala/sigmastate/interpreter/ProverInterpreter.scala
index 2953e8ed0c..ed2349eb0f 100644
--- a/interpreter/shared/src/main/scala/sigmastate/interpreter/ProverInterpreter.scala
+++ b/interpreter/shared/src/main/scala/sigmastate/interpreter/ProverInterpreter.scala
@@ -4,18 +4,23 @@ import sigma.kiama.rewriting.Rewriter.{everywherebu, everywheretd, rule}
import sigma.util.CollectionUtil._
import sigma.VersionContext
import sigma.kiama.rewriting.Strategy
-import sigmastate.TrivialProp.{FalseProp, TrueProp}
-import sigmastate.Values._
+import sigma.data.TrivialProp.{FalseProp, TrueProp}
+import sigma.ast._
import sigma.VersionContext.MaxSupportedScriptVersion
import sigmastate._
import sigmastate.crypto.DLogProtocol._
import sigmastate.crypto.VerifierMessage.Challenge
import sigmastate.crypto._
import sigmastate.crypto.{GF2_192, GF2_192_Poly}
-import sigmastate.eval.Extensions.ArrayOps
-import sigmastate.exceptions.InterpreterException
import sigmastate.utils.Helpers
import sigma.Coll
+import sigma.Extensions.ArrayOps
+import sigma.crypto.CryptoConstants
+import sigma.data.{CAND, COR, CTHRESHOLD, ProveDHTuple, ProveDlog, SigmaBoolean}
+import sigma.exceptions.InterpreterException
+import sigma.interpreter.CostedProverResult
+import sigma.serialization.SigSerializer
+import sigma.util.CollectionUtil
import java.math.BigInteger
import scala.util.Try
@@ -26,7 +31,7 @@ import scala.util.Try
*/
trait ProverInterpreter extends Interpreter with ProverUtils {
- import CryptoConstants.secureRandomBytes
+ import sigma.crypto.CryptoConstants.secureRandomBytes
import Interpreter._
override type ProofT = UncheckedTree
@@ -94,7 +99,7 @@ trait ProverInterpreter extends Interpreter with ProverUtils {
// Prover Step 8: compute the challenge for the root of the tree as the Fiat-Shamir hash of propBytes
// and the message being signed.
- val rootChallenge = Challenge @@ CryptoFunctions.hashFn(Helpers.concatArrays(propBytes, message)).toColl
+ val rootChallenge = Challenge @@ CryptoFunctions.hashFn(CollectionUtil.concatArrays(propBytes, message)).toColl
val step8 = step6.withChallenge(rootChallenge)
// Prover Step 9: complete the proof by computing challenges at real nodes and additionally responses at real leaves
@@ -146,7 +151,7 @@ trait ProverInterpreter extends Interpreter with ProverUtils {
hintsBag: HintsBag): Array[Byte] = {
val proofTree = sb match {
case TrueProp => NoProof
- case FalseProp => error("Script reduced to false")
+ case FalseProp => syntax.error("Script reduced to false")
case sigmaTree =>
val unprovenTree = convertToUnproven(sigmaTree)
prove(unprovenTree, message, hintsBag)
@@ -188,7 +193,7 @@ trait ProverInterpreter extends Interpreter with ProverUtils {
}
ul.withSimulated(!isReal)
case t: UnprovenTree =>
- error(s"Don't know how to markReal($t)")
+ syntax.error(s"Don't know how to markReal($t)")
})
/**
@@ -385,11 +390,11 @@ trait ProverInterpreter extends Interpreter with ProverUtils {
if (su.simulated) {
// Step 5 (simulated leaf -- complete the simulation)
assert(su.challengeOpt.isDefined)
- val (fm, sm) = DLogInteractiveProver.simulate(su.proposition, su.challengeOpt.get)
+ val (fm, sm) = DLogProver.simulate(su.proposition, su.challengeOpt.get)
UncheckedSchnorr(su.proposition, Some(fm), su.challengeOpt.get, sm)
} else {
// Step 6 -- compute the commitment
- val (r, commitment) = DLogInteractiveProver.firstMessage()
+ val (r, commitment) = DLogProver.firstMessage()
su.copy(commitmentOpt = Some(commitment), randomnessOpt = Some(r))
}
}
@@ -405,23 +410,23 @@ trait ProverInterpreter extends Interpreter with ProverUtils {
if (dhu.simulated) {
// Step 5 (simulated leaf -- complete the simulation)
assert(dhu.challengeOpt.isDefined)
- val (fm, sm) = DiffieHellmanTupleInteractiveProver.simulate(dhu.proposition, dhu.challengeOpt.get)
+ val (fm, sm) = DiffieHellmanTupleProver.simulate(dhu.proposition, dhu.challengeOpt.get)
UncheckedDiffieHellmanTuple(dhu.proposition, Some(fm), dhu.challengeOpt.get, sm)
} else {
// Step 6 -- compute the commitment
- val (r, fm) = DiffieHellmanTupleInteractiveProver.firstMessage(dhu.proposition)
+ val (r, fm) = DiffieHellmanTupleProver.firstMessage(dhu.proposition)
dhu.copy(commitmentOpt = Some(fm), randomnessOpt = Some(r))
}
}
- case t: ProofTree => error(s"Don't know how to challengeSimulated($t)")
+ case t: ProofTree => syntax.error(s"Don't know how to challengeSimulated($t)")
})
private def extractChallenge(pt: ProofTree): Option[Challenge] = pt match {
case upt: UnprovenTree => upt.challengeOpt
case sn: UncheckedSchnorr => Some(sn.challenge)
case dh: UncheckedDiffieHellmanTuple => Some(dh.challenge)
- case _ => error(s"Cannot extractChallenge($pt)")
+ case _ => syntax.error(s"Cannot extractChallenge($pt)")
}
/**
@@ -493,12 +498,12 @@ trait ProverInterpreter extends Interpreter with ProverUtils {
val z = privKeyOpt match {
case Some(privKey: DLogProverInput) =>
hintsBag.ownCommitments.find(_.position == su.position).map { oc =>
- DLogInteractiveProver.secondMessage(
+ DLogProver.secondMessage(
privKey,
oc.secretRandomness,
su.challengeOpt.get)
}.getOrElse {
- DLogInteractiveProver.secondMessage(
+ DLogProver.secondMessage(
privKey,
su.randomnessOpt.get,
su.challengeOpt.get)
@@ -526,12 +531,12 @@ trait ProverInterpreter extends Interpreter with ProverUtils {
val z = privKeyOpt match {
case Some(privKey) =>
hintsBag.ownCommitments.find(_.position == dhu.position).map { oc =>
- DiffieHellmanTupleInteractiveProver.secondMessage(
+ DiffieHellmanTupleProver.secondMessage(
privKey.asInstanceOf[DiffieHellmanTupleProverInput],
oc.secretRandomness,
dhu.challengeOpt.get)
}.getOrElse {
- DiffieHellmanTupleInteractiveProver.secondMessage(
+ DiffieHellmanTupleProver.secondMessage(
privKey.asInstanceOf[DiffieHellmanTupleProverInput],
dhu.randomnessOpt.get,
dhu.challengeOpt.get)
@@ -579,7 +584,7 @@ trait ProverInterpreter extends Interpreter with ProverUtils {
case dh: ProveDHTuple =>
UnprovenDiffieHellmanTuple(dh, None, None, None, simulated = false)
case _ =>
- error(s"Cannot convertToUnproven($sigmaTree)")
+ syntax.error(s"Cannot convertToUnproven($sigmaTree)")
}
//converts ProofTree => UncheckedSigmaTree
@@ -593,7 +598,7 @@ trait ProverInterpreter extends Interpreter with ProverUtils {
case s: UncheckedSchnorr => s
case d: UncheckedDiffieHellmanTuple => d
case a: Any =>
- error(s"Cannot convertToUnproven($a)")
+ syntax.error(s"Cannot convertToUnproven($a)")
}
/**
diff --git a/interpreter/shared/src/main/scala/sigmastate/interpreter/ProverUtils.scala b/interpreter/shared/src/main/scala/sigmastate/interpreter/ProverUtils.scala
index 0e66cb55c5..15daaec382 100644
--- a/interpreter/shared/src/main/scala/sigmastate/interpreter/ProverUtils.scala
+++ b/interpreter/shared/src/main/scala/sigmastate/interpreter/ProverUtils.scala
@@ -1,9 +1,11 @@
package sigmastate.interpreter
+import sigma.ast.ErgoTree
+import sigma.data.{ProveDHTuple, ProveDlog, SigmaBoolean, SigmaConjecture, SigmaLeaf}
+import sigma.serialization.SigSerializer
import sigmastate._
-import sigmastate.Values.{ErgoTree, SigmaBoolean}
-import sigmastate.crypto.DLogProtocol.{DLogInteractiveProver, ProveDlog}
-import sigmastate.crypto.{DiffieHellmanTupleInteractiveProver, ProveDHTuple}
+import sigmastate.crypto.DLogProtocol.DLogProver
+import sigmastate.crypto.DiffieHellmanTupleProver
trait ProverUtils extends Interpreter {
@@ -44,9 +46,9 @@ trait ProverUtils extends Interpreter {
if (generateFor.contains(leaf)) {
val (r, a) = leaf match {
case _: ProveDlog =>
- DLogInteractiveProver.firstMessage()
+ DLogProver.firstMessage()
case pdh: ProveDHTuple =>
- DiffieHellmanTupleInteractiveProver.firstMessage(pdh)
+ DiffieHellmanTupleProver.firstMessage(pdh)
case _ => ???
}
val hints = Seq(OwnCommitment(leaf, r, a, position), RealCommitment(leaf, a, position))
diff --git a/interpreter/shared/src/main/scala/sigmastate/lang/Terms.scala b/interpreter/shared/src/main/scala/sigmastate/lang/Terms.scala
deleted file mode 100644
index bbb19434bf..0000000000
--- a/interpreter/shared/src/main/scala/sigmastate/lang/Terms.scala
+++ /dev/null
@@ -1,466 +0,0 @@
-package sigmastate.lang
-
-import sigma.kiama.rewriting.Rewriter._
-import sigma.data.Nullable
-import sigmastate.SCollection.{SIntArray, SByteArray}
-import sigmastate.Values._
-import sigmastate.utils.Overloading.Overload1
-import sigmastate._
-import sigmastate.interpreter.{Interpreter, ErgoTreeEvaluator}
-import sigmastate.interpreter.ErgoTreeEvaluator.DataEnv
-import sigmastate.serialization.OpCodes
-import sigmastate.serialization.OpCodes.OpCode
-import sigmastate.lang.TransformingSigmaBuilder._
-
-import scala.language.implicitConversions
-import scala.collection.compat.immutable.ArraySeq
-import debox.cfor
-
-object Terms {
-
- /** Frontend representation of a block of Val definitions.
- * { val x = ...; val y = ... }
- * This node is not part of ErgoTree and hence have Undefined opCode. */
- case class Block(bindings: Seq[Val], result: SValue) extends Value[SType] {
- override def companion = Block
- override def tpe: SType = result.tpe
-
- /** This is not used as operation, but rather to form a program structure */
- override def opType: SFunc = Value.notSupportedError(this, "opType")
- }
- object Block extends ValueCompanion {
- override def opCode: OpCode = OpCodes.Undefined
- override def costKind: CostKind = Value.notSupportedError(this, "costKind")
- def apply(let: Val, result: SValue)(implicit o1: Overload1): Block =
- Block(Seq(let), result)
- }
-
- /** IR node to represent explicit Zero Knowledge scope in ErgoTree.
- * Compiler checks Zero Knowledge properties and issue error message is case of violations.
- * ZK-scoping is optional, it can be used when the user want to ensure Zero Knowledge of
- * specific set of operations.
- * Usually it will require simple restructuring of the code to make the scope body explicit.
- * Invariants checked by the compiler:
- * - single ZKProof in ErgoTree in a root position
- * - no boolean operations in the body, because otherwise the result may be disclosed
- * - all the operations are over SigmaProp values
- *
- * For motivation and details see https://github.com/ScorexFoundation/sigmastate-interpreter/issues/236
- * */
- case class ZKProofBlock(body: SigmaPropValue) extends BoolValue {
- override def companion = ZKProofBlock
- override def tpe = SBoolean
- override def opType: SFunc = ZKProofBlock.OpType
- }
- object ZKProofBlock extends ValueCompanion {
- override def opCode: OpCode = OpCodes.Undefined
- override def costKind: CostKind = Value.notSupportedError(this, "costKind")
- val OpType = SFunc(SSigmaProp, SBoolean)
- }
-
- trait Val extends Value[SType] {
- val name: String
- val givenType: SType
- val body: SValue
- }
- object Val {
- def apply(name: String, body: SValue): Val = ValNode(name, NoType, body)
- def apply(name: String, givenType: SType, body: SValue): Val = ValNode(name, givenType, body)
- def unapply(v: SValue): Option[(String, SType, SValue)] = v match {
- case ValNode(name, givenType, body) => Some((name, givenType, body))
- case _ => None
- }
- }
-
- case class ValNode(name: String,
- givenType: SType,
- body: SValue) extends Val {
- override def companion = ValNode
- override def tpe: SType = givenType ?: body.tpe
- /** This is not used as operation, but rather to form a program structure */
- override def opType: SFunc = Value.notSupportedError(this, "opType")
- }
- object ValNode extends ValueCompanion {
- override def opCode: OpCode = OpCodes.Undefined
- override def costKind: CostKind = Value.notSupportedError(this, "costKind")
- }
-
- /** Frontend node to select a field from an object. Should be transformed to SelectField*/
- case class Select(obj: Value[SType], field: String, resType: Option[SType] = None) extends Value[SType] {
- override def companion = Select
- override val tpe: SType = resType.getOrElse(obj.tpe match {
- case p: SProduct =>
- val i = p.methodIndex(field)
- if (i == -1) NoType
- else p.methods(i).stype
- case _ => NoType
- })
- override def opType: SFunc = SFunc(obj.tpe, tpe)
- }
- object Select extends ValueCompanion {
- override def opCode: OpCode = OpCodes.Undefined
- override def costKind: CostKind = Value.notSupportedError(this, "costKind")
- }
-
- /** Frontend node to represent variable names parsed in a source code.
- * Should be resolved during compilation to lambda argument, Val definition or
- * compilation environment value. */
- case class Ident(name: String, tpe: SType = NoType) extends Value[SType] {
- override def companion = Ident
- override def opType: SFunc = SFunc(ArraySeq.empty, tpe)
- }
- object Ident extends ValueCompanion {
- override def opCode: OpCode = OpCodes.Undefined
- override def costKind: CostKind = Value.notSupportedError(this, "costKind")
- def apply(name: String): Ident = Ident(name, NoType)
- }
-
- // TODO refactor: move to sigmastate.Values
- /** ErgoTree node which represents application of function `func` to the given arguments.
- * @param func expression which evaluates to a function
- * @param args arguments of the function application
- */
- case class Apply(func: Value[SType], args: IndexedSeq[Value[SType]]) extends Value[SType] {
- override def companion = Apply
- override lazy val tpe: SType = func.tpe match {
- case SFunc(_, r, _) => r
- case tColl: SCollectionType[_] => tColl.elemType
- case _ => NoType
- }
- override lazy val opType: SFunc = {
- val nArgs = args.length
- val argTypes = new Array[SType](nArgs + 1)
- argTypes(0) = func.tpe
- cfor(0)(_ < nArgs, _ + 1) { i =>
- argTypes(i + 1) = args(i).tpe
- }
- SFunc(argTypes, tpe)
- }
-
- protected final override def eval(env: DataEnv)(implicit E: ErgoTreeEvaluator): Any = {
- addCost(Apply.costKind)
- if (args.length == 1) {
- val fV = func.evalTo[Any => Any](env)
- val argV = args(0).evalTo[Any](env)
- fV(argV)
- } else {
- // zero or more than 1 argument functions are not supported in v4.x, v5.0
- // see `case Terms.Apply(f, Seq(x))` in RuntimeCosting which means other cases are not supported.
- Interpreter.error(s"Function application must have 1 argument, but was: $this")
- }
- }
- }
- object Apply extends FixedCostValueCompanion {
- override def opCode: OpCode = OpCodes.FuncApplyCode
- /** Cost of: 1) switch on the number of args 2) Scala method call 3) add args to env
- * Old cost: lambdaInvoke == 30 */
- override val costKind = FixedCost(JitCost(30))
- }
-
- /** Apply types for type parameters of input value. */
- case class ApplyTypes(input: Value[SType], tpeArgs: Seq[SType]) extends Value[SType] { node =>
- override def companion = ApplyTypes
- override lazy val tpe: SType = input.tpe match {
- case funcType: SFunc =>
- val subst = funcType.tpeParams.map(_.ident).zip(tpeArgs).toMap
- Terms.applySubst(input.tpe, subst)
- case _ => input.tpe
- }
- /** This is not used as operation, but rather to form a program structure */
- override def opType: SFunc = Value.notSupportedError(this, "opType")
- }
- object ApplyTypes extends ValueCompanion {
- override def opCode: OpCode = OpCodes.Undefined
- override def costKind: CostKind = Value.notSupportedError(this, "costKind")
- }
-
- /** Frontend node to represent potential method call in a source code.
- * Should be resolved during compilation to MethodCall.
- * Cannot be serialized to ErgoTree. */
- case class MethodCallLike(obj: Value[SType], name: String, args: IndexedSeq[Value[SType]], tpe: SType = NoType) extends Value[SType] {
- override def companion = MethodCallLike
- override def opType: SFunc = SFunc(obj.tpe +: args.map(_.tpe), tpe)
- }
- object MethodCallLike extends ValueCompanion {
- override def opCode: OpCode = OpCodes.Undefined
- override def costKind: CostKind = Value.notSupportedError(this, "costKind")
- }
-
- /** Represents in ErgoTree an invocation of method of the object `obj` with arguments `args`.
- * The SMethod instances in STypeCompanions may have type STypeIdent in methods types,
- * but valid ErgoTree should have SMethod instances specialized for specific types of
- * obj and args using `specializeFor`.
- * This means, if we save typeId, methodId, and we save all the arguments,
- * we can restore the specialized SMethod instance.
- * This work by induction, if we assume all arguments are monomorphic,
- * then we can make MethodCall monomorphic.
- * Thus, all ErgoTree instances are monomorphic by construction.
- *
- * @param obj object on which method will be invoked
- * @param method method to be invoked
- * @param args arguments passed to the method on invocation
- * @param typeSubst a map of concrete type for each generic type parameter
- */
- case class MethodCall(obj: Value[SType],
- method: SMethod,
- args: IndexedSeq[Value[SType]],
- typeSubst: Map[STypeVar, SType]) extends Value[SType] {
- override def companion = if (args.isEmpty) PropertyCall else MethodCall
- override def opType: SFunc = SFunc(obj.tpe +: args.map(_.tpe), tpe)
- override val tpe: SType = method.stype match {
- case f: SFunc => f.tRange.withSubstTypes(typeSubst)
- case t => t.withSubstTypes(typeSubst)
- }
-
- /** @hotspot don't beautify this code */
- protected final override def eval(env: DataEnv)(implicit E: ErgoTreeEvaluator): Any = {
- val objV = obj.evalTo[Any](env)
- addCost(MethodCall.costKind) // MethodCall overhead
- method.costKind match {
- case fixed: FixedCost =>
- val extra = method.extraDescriptors
- val extraLen = extra.length
- val len = args.length
- val argsBuf = new Array[Any](len + extraLen)
- cfor(0)(_ < len, _ + 1) { i =>
- argsBuf(i) = args(i).evalTo[Any](env)
- }
- cfor(0)(_ < extraLen, _ + 1) { i =>
- argsBuf(len + i) = extra(i)
- }
- var res: Any = null
- E.addFixedCost(fixed, method.opDesc) {
- res = method.invokeFixed(objV, argsBuf)
- }
- res
- case _ =>
- val len = args.length
- val argsBuf = new Array[Any](len + 3)
- argsBuf(0) = this
- argsBuf(1) = objV
- cfor(0)(_ < len, _ + 1) { i =>
- argsBuf(i + 2) = args(i).evalTo[Any](env)
- }
- argsBuf(argsBuf.length - 1) = E
-
- val evalMethod = method.genericMethod.evalMethod
- evalMethod.invoke(method.objType, argsBuf.asInstanceOf[Array[AnyRef]]:_*)
- }
- }
- }
-
- object MethodCall extends FixedCostValueCompanion {
- override def opCode: OpCode = OpCodes.MethodCallCode
- /** Cost of: 1) packing args into Array 2) RMethod.invoke */
- override val costKind = FixedCost(JitCost(4))
-
- /** Helper constructor which allows to cast the resulting node to the specified
- * [[sigmastate.Values.Value]] type `T`.
- * @see [[sigmastate.lang.Terms.MethodCall]]
- */
- def typed[T <: SValue](obj: Value[SType],
- method: SMethod,
- args: IndexedSeq[Value[SType]],
- typeSubst: Map[STypeVar, SType]): T = {
- MethodCall(obj, method, args, typeSubst).asInstanceOf[T]
- }
- }
- object PropertyCall extends FixedCostValueCompanion {
- override def opCode: OpCode = OpCodes.PropertyCallCode
- /** Cost of: 1) packing args into Array 2) RMethod.invoke */
- override val costKind = FixedCost(JitCost(4))
- }
-
- case class STypeParam(ident: STypeVar, upperBound: Option[SType] = None, lowerBound: Option[SType] = None) {
- assert(upperBound.isEmpty && lowerBound.isEmpty, s"Type parameters with bounds are not supported, but found $this")
- override def toString = ident.toString + upperBound.fold("")(u => s" <: $u") + lowerBound.fold("")(l => s" >: $l")
- }
- object STypeParam {
- implicit def typeIdentToTypeParam(id: STypeVar): STypeParam = STypeParam(id)
- }
-
- /** Frontend implementation of lambdas. Should be transformed to FuncValue. */
- case class Lambda(
- tpeParams: Seq[STypeParam],
- args: IndexedSeq[(String,SType)],
- givenResType: SType,
- body: Option[Value[SType]]) extends Value[SFunc]
- {
- require(!(tpeParams.nonEmpty && body.nonEmpty), s"Generic function definitions are not supported, but found $this")
- override def companion = Lambda
- override lazy val tpe: SFunc = {
- val sRange = givenResType ?: body.fold(NoType: SType)(_.tpe)
- SFunc(args.map(_._2), sRange, tpeParams)
- }
- /** This is not used as operation, but rather to form a program structure */
- override def opType: SFunc = SFunc(Vector(), tpe)
- }
- object Lambda extends ValueCompanion {
- override def opCode: OpCode = OpCodes.Undefined
- override def costKind: CostKind = Value.notSupportedError(this, "costKind")
- def apply(args: IndexedSeq[(String,SType)], resTpe: SType, body: Value[SType]): Lambda =
- Lambda(Nil, args, resTpe, Some(body))
- def apply(args: IndexedSeq[(String,SType)], resTpe: SType, body: Option[Value[SType]]): Lambda =
- Lambda(Nil, args, resTpe, body)
- def apply(args: IndexedSeq[(String,SType)], body: Value[SType]): Lambda = Lambda(Nil, args, NoType, Some(body))
- }
-
- /** Operation identity descriptor used in AOT costing (see usages in RuntimeCosting and
- * CostTable) */
- case class OperationId(name: String, opType: SFunc)
-
- implicit class ValueOps(val v: Value[SType]) extends AnyVal {
- def asValue[T <: SType]: Value[T] = v.asInstanceOf[Value[T]]
- def asNumValue: Value[SNumericType] = v.asInstanceOf[Value[SNumericType]]
- def asStringValue: Value[SString.type] = v.asInstanceOf[Value[SString.type]]
- def asBoolValue: Value[SBoolean.type] = v.asInstanceOf[Value[SBoolean.type]]
- def asByteValue: Value[SByte.type] = v.asInstanceOf[Value[SByte.type]]
- def asShortValue: Value[SShort.type] = v.asInstanceOf[Value[SShort.type]]
- def asIntValue: Value[SInt.type] = v.asInstanceOf[Value[SInt.type]]
- def asLongValue: Value[SLong.type] = v.asInstanceOf[Value[SLong.type]]
- def asBigInt: Value[SBigInt.type] = v.asInstanceOf[Value[SBigInt.type]]
- def asBox: Value[SBox.type] = v.asInstanceOf[Value[SBox.type]]
- def asGroupElement: Value[SGroupElement.type] = v.asInstanceOf[Value[SGroupElement.type]]
- def asSigmaProp: Value[SSigmaProp.type] = v.asInstanceOf[Value[SSigmaProp.type]]
- def asByteArray: Value[SByteArray] = v.asInstanceOf[Value[SByteArray]]
- def asIntArray: Value[SIntArray] = v.asInstanceOf[Value[SIntArray]]
- def asCollection[T <: SType]: Value[SCollection[T]] = v.asInstanceOf[Value[SCollection[T]]]
- def asOption[T <: SType]: Value[SOption[T]] = v.asInstanceOf[Value[SOption[T]]]
- def asTuple: Value[STuple] = v.asInstanceOf[Value[STuple]]
- def asFunc: Value[SFunc] = v.asInstanceOf[Value[SFunc]]
- def asConcreteCollection[T <: SType]: ConcreteCollection[T] = v.asInstanceOf[ConcreteCollection[T]]
- def upcastTo[T <: SNumericType](targetType: T): Value[T] = {
- assert(v.tpe.isInstanceOf[SNumericType],
- s"Cannot upcast value of type ${v.tpe} to $targetType: only numeric types can be upcasted.")
- val tV = v.asValue[SNumericType]
- assert(targetType.max(tV.tpe) == targetType,
- s"Invalid upcast from $tV to $targetType: target type should be larger than source type.")
- if (targetType == tV.tpe) v.asValue[T]
- else
- mkUpcast(tV, targetType).withSrcCtx(v.sourceContext)
- }
- def withSrcCtx[T <: SType](sourceContext: Nullable[SourceContext]): Value[T] = {
- v.sourceContext = sourceContext
- v.asValue[T]
- }
- /**
- * Set source context only if it's empty
- */
- def withEnsuredSrcCtx[T <: SType](sourceContext: Nullable[SourceContext]): Value[T] = {
- if (v.sourceContext.isEmpty) v.sourceContext = sourceContext
- v.asValue[T]
- }
- /**
- * Set source context to all nodes missing source context in the given tree.
- * @param srcCtx source context to set
- * @return AST where all nodes with missing source context are set to the given srcCtx
- */
- def withPropagatedSrcCtx[T <: SType](srcCtx: Nullable[SourceContext]): Value[T] = {
- rewrite(everywherebu(rule[Any] {
- case node: SValue if node != null && node.sourceContext.isEmpty =>
- node.withSrcCtx(srcCtx)
- }))(v).asValue[T]
- }
-
- }
-
- /** Type alias for a substitution of type variables with their corresponding types. */
- type STypeSubst = Map[STypeVar, SType]
-
- /** Immutable and sharable empty substitution. */
- val EmptySubst = Map.empty[STypeVar, SType]
-
- /** Performs pairwise type unification making sure each type variable is equally
- * substituted in all items. */
- def unifyTypeLists(items1: Seq[SType], items2: Seq[SType]): Option[Terms.STypeSubst] = {
- // unify items pairwise independently
- val itemsUni = (items1, items2).zipped.map((t1, t2) => unifyTypes(t1, t2))
- if (itemsUni.forall(_.isDefined)) {
- // merge substitutions making sure the same id is equally substituted in all items
- val merged = itemsUni.foldLeft(EmptySubst)((acc, subst) => {
- var res = acc
- for ( (id, t) <- subst.get ) {
- if (res.contains(id) && res(id) != t) return None
- res = res + (id -> t)
- }
- res
- })
- Some(merged)
- } else
- None
- }
-
- private val unifiedWithoutSubst = Some(EmptySubst)
-
- /** Finds a substitution `subst` of type variables such that unifyTypes(applySubst(t1, subst), t2) shouldBe Some(emptySubst) */
- def unifyTypes(t1: SType, t2: SType): Option[Terms.STypeSubst] = (t1, t2) match {
- case (_ @ STypeVar(n1), _ @ STypeVar(n2)) =>
- if (n1 == n2) unifiedWithoutSubst else None
- case (id1 @ STypeVar(_), _) =>
- Some(Map(id1 -> t2))
- case (e1: SCollectionType[_], e2: SCollectionType[_]) =>
- unifyTypes(e1.elemType, e2.elemType)
- case (e1: SCollectionType[_], _: STuple) =>
- unifyTypes(e1.elemType, SAny)
- case (e1: SOption[_], e2: SOption[_]) =>
- unifyTypes(e1.elemType, e2.elemType)
- case (e1: STuple, e2: STuple) if e1.items.length == e2.items.length =>
- unifyTypeLists(e1.items, e2.items)
- case (e1: SFunc, e2: SFunc) if e1.tDom.length == e2.tDom.length =>
- unifyTypeLists(e1.tDom :+ e1.tRange, e2.tDom :+ e2.tRange)
- case (STypeApply(name1, args1), STypeApply(name2, args2))
- if name1 == name2 && args1.length == args2.length =>
- unifyTypeLists(args1, args2)
- case (SBoolean, SSigmaProp) => // it is necessary for implicit conversion in Coll(bool, prop, bool)
- unifiedWithoutSubst
- case (SPrimType(e1), SPrimType(e2)) if e1 == e2 =>
- unifiedWithoutSubst
- case (SAny, _) =>
- unifiedWithoutSubst
- case _ => None
- }
-
- /** Applies a type substitution to a given type.
- *
- * @param tpe the type to apply the substitution to
- * @param subst the type substitution to apply
- * @return the type after applying the substitution
- */
- def applySubst(tpe: SType, subst: Terms.STypeSubst): SType = tpe match {
- case SFunc(args, res, tparams) =>
- val remainingVars = tparams.filterNot { p => subst.contains(p.ident) }
- SFunc(args.map(applySubst(_, subst)), applySubst(res, subst), remainingVars)
- case _ =>
- val substRule = rule[Any] {
- case id: STypeVar if subst.contains(id) => subst(id)
- }
- rewrite(everywherebu(substRule))(tpe)
- }
-
- /** Computes the most general type given two types.
- *
- * @param t1 the first type
- * @param t2 the second type
- * @return the most general type if it exists, otherwise None
- */
- def msgType(t1: SType, t2: SType): Option[SType] = unifyTypes(t1, t2) match {
- case Some(_) => Some(t1)
- case None => unifyTypes(t2, t1).map(_ => t2)
- }
-
- /** Most Specific Generalized (MSG) type of ts.
- * Currently just the type of the first element as long as all the elements have the same type. */
- def msgTypeOf(ts: Seq[SType]): Option[SType] = {
- if (ts.isEmpty) None
- else {
- var res: SType = ts.head
- for ( t <- ts.iterator.drop(1) ) {
- msgType(t, res) match {
- case Some(msg) => res = msg //assign new
- case None => return None
- }
- }
- Some(res)
- }
- }
-}
diff --git a/interpreter/shared/src/main/scala/sigmastate/serialization/BoolToSigmaPropSerializer.scala b/interpreter/shared/src/main/scala/sigmastate/serialization/BoolToSigmaPropSerializer.scala
deleted file mode 100644
index bb3a282935..0000000000
--- a/interpreter/shared/src/main/scala/sigmastate/serialization/BoolToSigmaPropSerializer.scala
+++ /dev/null
@@ -1,22 +0,0 @@
-package sigmastate.serialization
-
-import sigmastate.Values.{BoolValue, SigmaPropValue, SValue}
-import sigmastate.lang.Terms._
-import sigmastate.utils.SigmaByteWriter.DataInfo
-import sigmastate.utils.{SigmaByteReader, SigmaByteWriter}
-import sigmastate.{BoolToSigmaProp, SType, Values}
-
-case class BoolToSigmaPropSerializer(cons: BoolValue => SigmaPropValue) extends ValueSerializer[BoolToSigmaProp] {
- import sigmastate.Operations.BoolToSigmaPropInfo._
- override def opDesc = BoolToSigmaProp
- val conditionInfo: DataInfo[SValue] = conditionArg
-
- def serialize(obj: BoolToSigmaProp, w: SigmaByteWriter): Unit = {
- w.putValue(obj.value, conditionInfo)
- }
-
- def parse(r: SigmaByteReader): Values.Value[SType] = {
- val p = r.getValue().asBoolValue
- cons(p)
- }
-}
diff --git a/interpreter/shared/src/main/scala/sigmastate/serialization/CaseObjectSerialization.scala b/interpreter/shared/src/main/scala/sigmastate/serialization/CaseObjectSerialization.scala
deleted file mode 100644
index a1ece38023..0000000000
--- a/interpreter/shared/src/main/scala/sigmastate/serialization/CaseObjectSerialization.scala
+++ /dev/null
@@ -1,13 +0,0 @@
-package sigmastate.serialization
-
-import sigmastate.SType
-import sigmastate.Values.{Value, ValueCompanion}
-import sigmastate.utils.{SigmaByteReader, SigmaByteWriter}
-
-case class CaseObjectSerialization[V <: Value[SType]](override val opDesc: ValueCompanion, obj: V)
- extends ValueSerializer[V] {
-
- override def serialize(obj: V, w: SigmaByteWriter): Unit = ()
-
- override def parse(r: SigmaByteReader): V = obj
-}
diff --git a/interpreter/shared/src/main/scala/sigmastate/serialization/ProveDlogSerializer.scala b/interpreter/shared/src/main/scala/sigmastate/serialization/ProveDlogSerializer.scala
deleted file mode 100644
index 89400938fe..0000000000
--- a/interpreter/shared/src/main/scala/sigmastate/serialization/ProveDlogSerializer.scala
+++ /dev/null
@@ -1,39 +0,0 @@
-package sigmastate.serialization
-
-import sigmastate.crypto.DLogProtocol.ProveDlog
-import sigmastate.{SGroupElement, CreateProveDlog}
-import sigmastate.Values.{Value, SValue, SigmaPropValue}
-import sigmastate.crypto.CryptoConstants.EcPointType
-import sigmastate.lang.Terms._
-import sigmastate.utils.SigmaByteWriter.DataInfo
-import sigmastate.utils.{SigmaByteReader, SigmaByteWriter}
-
-case class ProveDlogSerializer(cons: EcPointType => ProveDlog)
- extends SigmaSerializer[ProveDlog, ProveDlog] {
-
- override def serialize(obj: ProveDlog, w: SigmaByteWriter): Unit =
- GroupElementSerializer.serialize(obj.value, w)
-
- override def parse(r: SigmaByteReader) = {
- val res = GroupElementSerializer.parse(r)
- cons(res)
- }
-}
-
-case class CreateProveDlogSerializer(cons: Value[SGroupElement.type] => SigmaPropValue)
- extends ValueSerializer[CreateProveDlog] {
- import sigmastate.Operations.CreateProveDlogInfo._
- override def opDesc = CreateProveDlog
- val valueInfo: DataInfo[SValue] = valueArg
-
- override def serialize(obj: CreateProveDlog, w: SigmaByteWriter): Unit = {
- w.putValue(obj.value, valueInfo)
- }
-
- override def parse(r: SigmaByteReader) = {
- val v = r.getValue().asValue[SGroupElement.type]
- cons(v)
- }
-}
-
-
diff --git a/interpreter/shared/src/main/scala/sigmastate/serialization/SigmaPropBytesSerializer.scala b/interpreter/shared/src/main/scala/sigmastate/serialization/SigmaPropBytesSerializer.scala
deleted file mode 100644
index 754880cd16..0000000000
--- a/interpreter/shared/src/main/scala/sigmastate/serialization/SigmaPropBytesSerializer.scala
+++ /dev/null
@@ -1,23 +0,0 @@
-package sigmastate.serialization
-
-import sigmastate.Values.SValue
-import sigmastate.{Values, SType}
-import sigmastate.lang.Terms._
-import sigmastate.utils.SigmaByteWriter.DataInfo
-import sigmastate.utils.{SigmaByteReader, SigmaByteWriter}
-import sigmastate.utxo.SigmaPropBytes
-
-object SigmaPropBytesSerializer extends ValueSerializer[SigmaPropBytes] {
- import sigmastate.Operations.SigmaPropBytesInfo._
- override def opDesc = SigmaPropBytes
- val thisInfo: DataInfo[SValue] = thisArg
-
- def serialize(obj: SigmaPropBytes, w: SigmaByteWriter): Unit = {
- w.putValue(obj.input, thisInfo)
- }
-
- def parse(r: SigmaByteReader): Values.Value[SType] = {
- val p = r.getValue().asSigmaProp
- SigmaPropBytes(p)
- }
-}
diff --git a/interpreter/shared/src/main/scala/sigmastate/serialization/transformers/ProveDHTupleSerializer.scala b/interpreter/shared/src/main/scala/sigmastate/serialization/transformers/ProveDHTupleSerializer.scala
deleted file mode 100644
index 39406a35c0..0000000000
--- a/interpreter/shared/src/main/scala/sigmastate/serialization/transformers/ProveDHTupleSerializer.scala
+++ /dev/null
@@ -1,53 +0,0 @@
-package sigmastate.serialization.transformers
-
-import sigmastate.{SGroupElement, CreateProveDHTuple}
-import sigmastate.Values.{Value, SigmaPropValue}
-import sigmastate.crypto.ProveDHTuple
-import sigmastate.crypto.CryptoConstants.EcPointType
-import sigmastate.lang.Terms._
-import sigmastate.utils.{SigmaByteReader, SigmaByteWriter}
-import sigmastate.serialization._
-
-case class ProveDHTupleSerializer(
- cons: (EcPointType, EcPointType, EcPointType, EcPointType) => ProveDHTuple
- ) extends SigmaSerializer[ProveDHTuple, ProveDHTuple] {
-
- override def serialize(obj: ProveDHTuple, w: SigmaByteWriter): Unit = {
- GroupElementSerializer.serialize(obj.gv, w)
- GroupElementSerializer.serialize(obj.hv, w)
- GroupElementSerializer.serialize(obj.uv, w)
- GroupElementSerializer.serialize(obj.vv, w)
- }
-
- override def parse(r: SigmaByteReader) = {
- val gv = GroupElementSerializer.parse(r)
- val hv = GroupElementSerializer.parse(r)
- val uv = GroupElementSerializer.parse(r)
- val vv = GroupElementSerializer.parse(r)
- cons(gv, hv, uv, vv)
- }
-}
-
-case class CreateProveDHTupleSerializer(cons: (Value[SGroupElement.type],
- Value[SGroupElement.type],
- Value[SGroupElement.type],
- Value[SGroupElement.type]) => SigmaPropValue)
- extends ValueSerializer[CreateProveDHTuple] {
- import sigmastate.Operations.CreateProveDHTupleInfo._
- override def opDesc = CreateProveDHTuple
-
- override def serialize(obj: CreateProveDHTuple, w: SigmaByteWriter): Unit = {
- w.putValue(obj.gv, gArg)
- w.putValue(obj.hv, hArg)
- w.putValue(obj.uv, uArg)
- w.putValue(obj.vv, vArg)
- }
-
- override def parse(r: SigmaByteReader) = {
- val gv = r.getValue().asValue[SGroupElement.type]
- val hv = r.getValue().asValue[SGroupElement.type]
- val uv = r.getValue().asValue[SGroupElement.type]
- val vv = r.getValue().asValue[SGroupElement.type]
- cons(gv, hv, uv, vv)
- }
-}
diff --git a/interpreter/shared/src/main/scala/sigmastate/sigmastate.scala b/interpreter/shared/src/main/scala/sigmastate/sigmastate.scala
index 185fbebb9d..1c7b8d5ab6 100644
--- a/interpreter/shared/src/main/scala/sigmastate/sigmastate.scala
+++ b/interpreter/shared/src/main/scala/sigmastate/sigmastate.scala
@@ -1,30 +1,13 @@
-import org.ergoplatform.{ErgoBox, ErgoBoxCandidate, ErgoLikeContext}
-import sigma.data.{RType, GeneralType}
-import sigmastate.Values._
-import sigmastate.lang.CheckingSigmaBuilder
+import org.ergoplatform.ErgoLikeContext
+import sigma.ast._
+import sigma.data.RType
-import scala.annotation.nowarn
import scala.reflect.classTag
package object sigmastate {
import CheckingSigmaBuilder._
- /** Shadow the implicit from sigma package so it doesn't interfere with the resolution
- * of ClassTags below.
- */
- @nowarn private def rtypeToClassTag = ???
-
- /** RType descriptors for predefined types used in AOTC-based interpreter. */
-
- implicit val SigmaBooleanRType : RType[SigmaBoolean] = RType.fromClassTag(classTag[SigmaBoolean])
-
- implicit val ErgoBoxRType : RType[ErgoBox] = RType.fromClassTag(classTag[ErgoBox])
-
- implicit val ErgoBoxCandidateRType: RType[ErgoBoxCandidate] = RType.fromClassTag(classTag[ErgoBoxCandidate])
-
- implicit val AvlTreeDataRType : RType[AvlTreeData] = GeneralType(classTag[AvlTreeData])
-
- implicit val ErgoLikeContextRType : RType[ErgoLikeContext] = RType.fromClassTag(classTag[ErgoLikeContext])
+ implicit val ErgoLikeContextRType: RType[ErgoLikeContext] = RType.fromClassTag(classTag[ErgoLikeContext])
/** Helper method to create "+" operation node. */
def Plus[T <: SNumericType](left: Value[T], right: Value[T]): Value[T] =
@@ -53,5 +36,4 @@ package object sigmastate {
/** Helper method to create "max" operation node. */
def Max[T <: SNumericType](left: Value[T], right: Value[T]): Value[T] =
mkMax(left, right)
-
}
diff --git a/interpreter/shared/src/main/scala/sigmastate/types.scala b/interpreter/shared/src/main/scala/sigmastate/types.scala
deleted file mode 100644
index 586a06432e..0000000000
--- a/interpreter/shared/src/main/scala/sigmastate/types.scala
+++ /dev/null
@@ -1,2601 +0,0 @@
-package sigmastate
-
-import java.math.BigInteger
-import org.ergoplatform._
-import org.ergoplatform.validation._
-import sigma.data.{Nullable, RType}
-import sigma.data.GeneralType
-import sigmastate.SType.TypeCode
-import sigmastate.interpreter._
-import sigmastate.utils.Overloading.Overload1
-import scorex.crypto.authds.{ADKey, ADValue}
-import scorex.crypto.authds.avltree.batch.{Insert, Lookup, Remove, Update}
-import sigmastate.Values._
-import sigmastate.lang.Terms._
-import sigmastate.lang.{SigmaBuilder, Terms}
-import sigmastate.SCollection._
-import sigmastate.crypto.CryptoConstants.EcPointType
-import sigmastate.serialization.OpCodes
-import sigma.Coll
-import sigma._
-
-import scala.language.implicitConversions
-import scala.reflect.{ClassTag, classTag}
-import scala.collection.compat.immutable.ArraySeq
-import sigmastate.SMethod.{InvokeDescBuilder, MethodCallIrBuilder, MethodCostFunc, javaMethodOf}
-import sigmastate.utxo._
-import sigmastate.lang.Terms.STypeSubst
-import sigmastate.eval.Evaluation.stypeToRType
-import sigmastate.eval._
-import debox.cfor
-import sigma.reflection.{RClass, RMethod}
-import sigma.util.Extensions.{IntOps, LongOps, ShortOps}
-
-import scala.util.{Failure, Success}
-
-/** Base type for all AST nodes of sigma lang. */
-trait SigmaNode extends Product
-
-/** Base type for all companions of AST nodes of sigma lang. */
-trait SigmaNodeCompanion
-
-/** Every type descriptor is a tree represented by nodes in SType hierarchy.
- * In order to extend type family:
- * - Implement concrete class derived from SType
- * - Implement serializer (see SCollectionSerializer) and register it in STypeSerializer.table
- * Each SType is serialized to array of bytes by:
- * - emitting typeCode of each node (see special case for collections below)
- * - then recursively serializing subtrees from left to right on each level
- * - for each collection of primitive type there is special type code to emit single byte instead of two bytes
- * Types code intervals
- * - (1 .. MaxPrimTypeCode) // primitive types
- * - (CollectionTypeCode .. CollectionTypeCode + MaxPrimTypeCode) // collections of primitive types
- * - (MaxCollectionTypeCode ..) // Other types
- * Collection of non-primitive type is serialized as (CollectionTypeCode, serialize(elementType))
- * */
-sealed trait SType extends SigmaNode {
- /** The underlying Scala type of data values described by this type descriptor.
- * E.g. scala.Int for SInt descriptor.
- */
- type WrappedType
-
- /** Type code used in serialization of SType values.
- * @see TypeSerializer
- */
- val typeCode: SType.TypeCode
-
- /** Returns true if this type embeddable, i.e. a type that can be combined with type
- * constructor for optimized encoding. For each embeddable type `T`, and type
- * constructor `C`, the type `C[T]` can be represented by a single byte.
- * @see [[sigmastate.serialization.TypeSerializer]]
- */
- def isEmbeddable: Boolean = false
-
- /** Elvis operator for types. See https://en.wikipedia.org/wiki/Elvis_operator*/
- def ?:(whenNoType: => SType): SType = if (this == NoType) whenNoType else this
-
- /** Applies a type substitution to this type.
- *
- * @param subst the type substitution to apply
- * @return the type after applying the substitution
- */
- def withSubstTypes(subst: Map[STypeVar, SType]): SType =
- if (subst.isEmpty) this
- else
- Terms.applySubst(this, subst)
-
- /** Returns parsable type term string of the type described by this type descriptor.
- * For every type it should be inverse to SigmaTyper.parseType.
- * This is default fallback implementation, should be overriden if it
- * is not correct for a particular type. */
- def toTermString: String = {
- val t = Evaluation.stypeToRType(this)
- t.name
- }
-}
-
-object SType {
- /** Representation of type codes used in serialization. */
- type TypeCode = Byte
-
- val DummyValue = 0.asWrappedType
-
- implicit val typeByte : SByte.type = SByte
- implicit val typeShort : SShort.type = SShort
- implicit val typeInt : SInt.type = SInt
- implicit val typeLong : SLong.type = SLong
- implicit val typeBigInt : SBigInt.type = SBigInt
- implicit val typeBoolean : SBoolean.type = SBoolean
- implicit val typeAvlTree : SAvlTree.type = SAvlTree
- implicit val typeGroupElement: SGroupElement.type = SGroupElement
- implicit val typeSigmaProp : SSigmaProp.type = SSigmaProp
- implicit val typeBox : SBox.type = SBox
-
- /** Costructs a collection type with the given type of elements. */
- implicit def typeCollection[V <: SType](implicit tV: V): SCollection[V] = SCollection[V](tV)
-
- /** Named type variables and parameters used in generic types and method signatures.
- * Generic type terms like `(Coll[IV],(IV) => Boolean) => Boolean` are used to represent
- * method types of `Coll`` and `Option`` types. Each such type is an instance of [[SFunc]].
- * To represent variables (such as `IV` in the example above) [[STypeVar]] instances
- * are used.
- *
- * Generic types are not supported by ErgoTree serialization format and STypeVars are
- * used internally and never serialized (there is no serializer for STypeVar).
- * Thus the usage of type variables is limited.
- *
- * All necessary type variables can be declared in advance and reused across all code
- * base. This allows to avoid allocation of many duplicates and also improve
- * performance of SType values.
- */
- val tT = STypeVar("T")
- val tR = STypeVar("R")
- val tK = STypeVar("K")
- val tL = STypeVar("L")
- val tO = STypeVar("O")
- val tD = STypeVar("D")
- val tV = STypeVar("V")
- val tIV = STypeVar("IV")
- val tOV = STypeVar("OV")
-
- val paramT = STypeParam(tT)
- val paramR = STypeParam(tR)
- val paramIV = STypeParam(tIV)
- val paramOV = STypeParam(tOV)
- val paramIVSeq: Seq[STypeParam] = Array(paramIV)
-
- val IndexedSeqOfT1: IndexedSeq[SType] = Array(SType.tT)
- val IndexedSeqOfT2: IndexedSeq[SType] = Array(SType.tT, SType.tT)
-
- /** Immutable empty array, can be used to avoid repeated allocations. */
- val EmptyArray = Array.empty[SType]
-
- /** Immutable empty IndexedSeq, can be used to avoid repeated allocations. */
- val EmptySeq: IndexedSeq[SType] = EmptyArray
-
- /** All pre-defined types should be listed here. Note, NoType is not listed.
- * Should be in sync with sigmastate.lang.Types.predefTypes. */
- val allPredefTypes: Seq[SType] = Array(SBoolean, SByte, SShort, SInt, SLong, SBigInt, SContext,
- SGlobal, SHeader, SPreHeader, SAvlTree, SGroupElement, SSigmaProp, SString, SBox,
- SUnit, SAny)
-
- /** A mapping of object types supporting MethodCall operations. For each serialized
- * typeId this map contains a companion object which can be used to access the list of
- * corresponding methods.
- *
- * NOTE: in the current implementation only monomorphic methods are supported (without
- * type parameters)
- *
- * NOTE2: in v3.x SNumericType.typeId is silently shadowed by SGlobal.typeId as part of
- * `toMap` operation. As a result, the methods collected into SByte.methods cannot be
- * resolved (using SMethod.fromIds()) for all numeric types (SByte, SShort, SInt,
- * SLong, SBigInt). See the corresponding regression `property("MethodCall on numerics")`.
- * However, this "shadowing" is not a problem since all casting methods are implemented
- * via Downcast, Upcast opcodes and the remaining `toBytes`, `toBits` methods are not
- * implemented at all.
- * In order to allow MethodCalls on numeric types in future versions the SNumericType.typeId
- * should be changed and SGlobal.typeId should be preserved. The regression tests in
- * `property("MethodCall Codes")` should pass.
- */
- // TODO v6.0: should contain all numeric types (including also SNumericType)
- // to support method calls like 10.toByte which encoded as MethodCall with typeId = 4, methodId = 1
- // see https://github.com/ScorexFoundation/sigmastate-interpreter/issues/667
- lazy val types: Map[Byte, STypeCompanion] = Seq(
- SBoolean, SNumericType, SString, STuple, SGroupElement, SSigmaProp, SContext, SGlobal, SHeader, SPreHeader,
- SAvlTree, SBox, SOption, SCollection, SBigInt
- ).map { t => (t.typeId, t) }.toMap
-
- /** Checks that the type of the value corresponds to the descriptor `tpe`.
- * If the value has complex structure only root type constructor is checked.
- * NOTE, this method is used in ErgoTree evaluation to systematically check that each
- * tree node evaluates to a value of the expected type.
- * Shallow runtime checks are enough if:
- * 1) ErgoTree is well-typed, i.e. each sub-expression has correct types (agree with
- * the argument type).
- * 2) `isValueOfType == true` for each tree leaf
- * 3) `isValueOfType == true` for each sub-expression
- *
- * @param value value to check type
- * @param tpe type descriptor to check value against
- * @return true if the given `value` is of type tpe`
- */
- def isValueOfType[T <: SType](x: Any, tpe: T): Boolean = tpe match {
- case SBoolean => x.isInstanceOf[Boolean]
- case SByte => x.isInstanceOf[Byte]
- case SShort => x.isInstanceOf[Short]
- case SInt => x.isInstanceOf[Int]
- case SLong => x.isInstanceOf[Long]
- case SBigInt => x.isInstanceOf[BigInt]
- case SGroupElement => x.isInstanceOf[GroupElement]
- case SSigmaProp => x.isInstanceOf[SigmaProp]
- case SBox => x.isInstanceOf[Box]
- case _: SCollectionType[_] => x.isInstanceOf[Coll[_]]
- case _: SOption[_] => x.isInstanceOf[Option[_]]
- case t: STuple =>
- if (t.items.length == 2) x.isInstanceOf[Tuple2[_,_]]
- else sys.error(s"Unsupported tuple type $t")
- case tF: SFunc =>
- if (tF.tDom.length == 1) x.isInstanceOf[Function1[_,_]]
- else sys.error(s"Unsupported function type $tF")
- case SContext => x.isInstanceOf[Context]
- case SAvlTree => x.isInstanceOf[AvlTree]
- case SGlobal => x.isInstanceOf[SigmaDslBuilder]
- case SHeader => x.isInstanceOf[Header]
- case SPreHeader => x.isInstanceOf[PreHeader]
- case SUnit => x.isInstanceOf[Unit]
- case _ => sys.error(s"Unknown type $tpe")
- }
-
- implicit class STypeOps(val tpe: SType) extends AnyVal {
- def isCollectionLike: Boolean = tpe.isInstanceOf[SCollection[_]]
- def isCollection: Boolean = tpe.isInstanceOf[SCollectionType[_]]
- def isOption: Boolean = tpe.isInstanceOf[SOption[_]]
- def isBox: Boolean = tpe.isInstanceOf[SBox.type]
- def isGroupElement: Boolean = tpe.isInstanceOf[SGroupElement.type]
- def isSigmaProp: Boolean = tpe.isInstanceOf[SSigmaProp.type]
- def isAvlTree: Boolean = tpe.isInstanceOf[SAvlTree.type]
- def isFunc : Boolean = tpe.isInstanceOf[SFunc]
- def isTuple: Boolean = tpe.isInstanceOf[STuple]
-
- /** Returns true if this type is numeric (Byte, Short, etc.)
- * @see [[sigmastate.SNumericType]]
- */
- def isNumType: Boolean = tpe.isInstanceOf[SNumericType]
-
- /** Returns true if this type is either numeric (Byte, Short, etc.) or is NoType.
- * @see [[sigmastate.SNumericType]]
- */
- def isNumTypeOrNoType: Boolean = isNumType || tpe == NoType
-
- def asNumType: SNumericType = tpe.asInstanceOf[SNumericType]
- def asFunc: SFunc = tpe.asInstanceOf[SFunc]
- def asProduct: SProduct = tpe.asInstanceOf[SProduct]
- def asTuple: STuple = tpe.asInstanceOf[STuple]
- def asOption[T <: SType]: SOption[T] = tpe.asInstanceOf[SOption[T]]
- def whenFunc[T](action: SFunc => Unit) = if(tpe.isInstanceOf[SFunc]) action(tpe.asFunc)
- def asCollection[T <: SType] = tpe.asInstanceOf[SCollection[T]]
-
- /** Returns the [[ClassTag]] for the given [[SType]]. */
- def classTag[T <: SType#WrappedType]: ClassTag[T] = (tpe match {
- case SBoolean => reflect.classTag[Boolean]
- case SByte => reflect.classTag[Byte]
- case SShort => reflect.classTag[Short]
- case SInt => reflect.classTag[Int]
- case SLong => reflect.classTag[Long]
- case SBigInt => reflect.classTag[BigInt]
- case SAvlTree => reflect.classTag[AvlTree]
- case SGroupElement => reflect.classTag[EcPointType]
- case SSigmaProp => reflect.classTag[SigmaBoolean]
- case SUnit => reflect.classTag[Unit]
- case SBox => reflect.classTag[ErgoBox]
- case SAny => reflect.classTag[Any]
- case opt: SOption[a] => reflect.classTag[Option[a]]
- case _: STuple => reflect.classTag[Array[Any]]
- case tColl: SCollection[a] =>
- val elemType = tColl.elemType
- implicit val ca = elemType.classTag[elemType.WrappedType]
- reflect.classTag[Array[elemType.WrappedType]]
- case _ => sys.error(s"Cannot get ClassTag for type $tpe")
- }).asInstanceOf[ClassTag[T]]
- }
-
- implicit class AnyOps(val x: Any) extends AnyVal {
- /** Helper method to simplify type casts. */
- def asWrappedType: SType#WrappedType = x.asInstanceOf[SType#WrappedType]
- }
-}
-
-/** Basic interface for all type companions.
- * This is necessary to make distinction between concrete type descriptor of a type like Coll[Int]
- * and generic descriptor of Coll[T] type constructor.
- * Some simple types like Int, GroupElement inherit from both SType and STypeCompanion.
- * @see SInt, SGroupElement, SType
- */
-trait STypeCompanion {
- /** Force initialization of reflection. */
- val reflection = InterpreterReflection
-
- /** Type identifier to use in method serialization */
- def typeId: Byte
-
- /** If this is SType instance then returns the name of the corresponding RType.
- * Otherwise returns the name of type companion object (e.g. SCollection).
- */
- def typeName: String = {
- this match {
- case t: SType =>
- val rtype = stypeToRType(t)
- rtype.name
- case _ => this.getClass.getSimpleName.replace("$", "")
- }
- }
-
- /** List of methods defined for instances of this type. */
- def methods: Seq[SMethod]
-
- private lazy val _methodsMap: Map[Byte, Map[Byte, SMethod]] = methods
- .groupBy(_.objType.typeId)
- .map { case (typeId, ms) => (typeId -> ms.map(m => m.methodId -> m).toMap) }
-
- /** Lookup method by its id in this type. */
- @inline def getMethodById(methodId: Byte): Option[SMethod] =
- _methodsMap.get(typeId) match {
- case Some(ms) => ms.get(methodId)
- case None => None
- }
-
- /** Lookup method in this type by method's id or throw ValidationException.
- * This method can be used in trySoftForkable section to either obtain valid method
- * or catch ValidatioinException which can be checked for soft-fork condition.
- * It delegate to getMethodById to lookup method.
- * @see getMethodById
- */
- def methodById(methodId: Byte): SMethod = {
- ValidationRules.CheckAndGetMethod(this, methodId)
- }
-
- /** Looks up the method descriptor by the method name. */
- def getMethodByName(name: String): SMethod = methods.find(_.name == name).get
-
- /** Class which represents values of this type. When method call is executed, the corresponding method
- * of this class is invoked via [[RMethod]].invoke(). */
- def reprClass: RClass[_]
-
- /** Represents class of `this`. */
- lazy val thisRClass: RClass[_] = RClass(this.getClass)
-}
-
-/** Defines recognizer method which allows the derived object to be used in patterns
- * to recognize method descriptors by method name.
- * @see SCollecton
- */
-trait MethodByNameUnapply extends STypeCompanion {
- def unapply(methodName: String): Option[SMethod] = methods.find(_.name == methodName)
-}
-
-/** Base trait for all types which have methods (and properties) */
-trait SProduct extends SType {
- /** Returns -1 if `method` is not found. */
- def methodIndex(name: String): Int = methods.indexWhere(_.name == name)
-
- /** Returns true if this type has a method with the given name. */
- def hasMethod(name: String): Boolean = methodIndex(name) != -1
-
- /** This method should be overriden in derived classes to add new methods in addition to inherited.
- * Typical override: `super.getMethods() ++ Seq(m1, m2, m3)` */
- protected def getMethods(): Seq[SMethod] = Nil
-
- /** Returns all the methods of this type. */
- lazy val methods: Seq[SMethod] = {
- val ms = getMethods()
- assert(ms.map(_.name).distinct.length == ms.length, s"Duplicate method names in $this")
- ms.groupBy(_.objType).foreach { case (comp, ms) =>
- assert(ms.map(_.methodId).distinct.length == ms.length, s"Duplicate method ids in $comp: $ms")
- }
- ms
- }
-
- /** Finds a method descriptor [[SMethod]] for the given name. */
- def method(methodName: String): Option[SMethod] = methods.find(_.name == methodName)
-}
-
-/** Base trait implemented by all generic types (those which has type parameters,
- * e.g. Coll[T], Option[T], etc.)*/
-trait SGenericType {
- /** Type parameters of this generic type. */
- def typeParams: Seq[STypeParam]
-}
-
-/** Meta information which can be attached to each argument of SMethod.
- * @param name name of the argument
- * @param description argument description. */
-case class ArgInfo(name: String, description: String)
-
-/** Meta information which can be attached to SMethod.
- * @param opDesc optional operation descriptor
- * @param description human readable description of the method
- * @param args one item for each argument */
-case class OperationInfo(opDesc: Option[ValueCompanion], description: String, args: Seq[ArgInfo]) {
- def isFrontendOnly: Boolean = opDesc.isEmpty
- def opTypeName: String = opDesc.map(_.typeName).getOrElse("(FRONTEND ONLY)")
-}
-
-object OperationInfo {
- /** Convenience factory method. */
- def apply(opDesc: ValueCompanion, description: String, args: Seq[ArgInfo]): OperationInfo =
- OperationInfo(Some(opDesc), description, args)
-}
-
-/** Meta information connecting SMethod with ErgoTree.
- * The optional builder is used by front-end ErgoScript compiler to replace method calls
- * with ErgoTree nodes. In many cases [[SMethod.MethodCallIrBuilder]] builder is used.
- * However there are specific cases where more complex builders are used, see for example
- * usage of `withIRInfo` in the declaration of [[SCollection.GetOrElseMethod]].
- * @param irBuilder optional method call recognizer and ErgoTree node builder.
- * When the partial function is defined on a tuple
- * (builder, obj, m, args, subst) it transforms it to a new ErgoTree
- * node, which is then used in the resuting ErgoTree coming out of
- * the ErgoScript compiler.
- * @param javaMethod Java [[Method]] which should be used to evaluate
- * [[sigmastate.lang.Terms.MethodCall]] node of ErgoTree.
- * @param invokeDescsBuilder optional builder of additional type descriptors (see extraDescriptors)
- */
-case class MethodIRInfo(
- irBuilder: Option[PartialFunction[(SigmaBuilder, SValue, SMethod, Seq[SValue], STypeSubst), SValue]],
- javaMethod: Option[RMethod],
- invokeDescsBuilder: Option[InvokeDescBuilder]
-)
-
-/** Represents method descriptor.
- *
- * @param objType type or type constructor descriptor
- * @param name method name
- * @param stype method signature type,
- * where `stype.tDom`` - argument type and
- * `stype.tRange` - method result type.
- * @param methodId method code, it should be unique among methods of the same objType.
- * @param costKind cost descriptor for this method
- * @param irInfo meta information connecting SMethod with ErgoTree (see [[MethodIRInfo]])
- * @param docInfo optional human readable method description data
- * @param costFunc optional specification of how the cost should be computed for the
- * given method call (See ErgoTreeEvaluator.calcCost method).
- */
-case class SMethod(
- objType: STypeCompanion,
- name: String,
- stype: SFunc,
- methodId: Byte,
- costKind: CostKind,
- irInfo: MethodIRInfo,
- docInfo: Option[OperationInfo],
- costFunc: Option[MethodCostFunc]) {
-
- /** Operation descriptor of this method. */
- lazy val opDesc = MethodDesc(this)
-
- /** Finds and keeps the [[RMethod]] instance which corresponds to this method descriptor.
- * The lazy value is forced only if irInfo.javaMethod == None
- */
- lazy val javaMethod: RMethod = {
- irInfo.javaMethod.getOrElse {
- val paramTypes = stype.tDom.drop(1).map(t => t match {
- case _: STypeVar => classOf[AnyRef]
- case _: SFunc => classOf[_ => _]
- case _ => Evaluation.stypeToRType(t).classTag.runtimeClass
- }).toArray
- val m = objType.reprClass.getMethod(name, paramTypes:_*)
- m
- }
- }
-
- /** Additional type descriptors, which are necessary to perform invocation of Method
- * associated with this instance.
- * @see MethodCall.eval
- */
- lazy val extraDescriptors: Seq[RType[_]] = {
- irInfo.invokeDescsBuilder match {
- case Some(builder) =>
- builder(stype).map(Evaluation.stypeToRType)
- case None =>
- ArraySeq.empty[RType[_]]
- }
- }
-
- /** Invoke this method on the given object with the arguments.
- * This is used for methods with FixedCost costKind. */
- def invokeFixed(obj: Any, args: Array[Any])(implicit E: ErgoTreeEvaluator): Any = {
- javaMethod.invoke(obj, args.asInstanceOf[Array[AnyRef]]:_*)
- }
-
- // TODO optimize: avoid lookup when this SMethod is created via `specializeFor`
- /** Return generic template of this method. */
- @inline final def genericMethod: SMethod = {
- objType.getMethodById(methodId).get
- }
-
- /** Returns refection [[RMethod]] which must be invoked to evaluate this method.
- * The method is resolved by its name using `name + "_eval"` naming convention.
- * @see `map_eval`, `flatMap_eval` and other `*_eval` methods.
- * @hotspot don't beautify the code */
- lazy val evalMethod: RMethod = {
- val argTypes = stype.tDom
- val nArgs = argTypes.length
- val paramTypes = new Array[Class[_]](nArgs + 2)
- paramTypes(0) = classOf[MethodCall]
- cfor(0)(_ < nArgs, _ + 1) { i =>
- paramTypes(i + 1) = argTypes(i) match {
- case _: STypeVar => classOf[AnyRef]
- case _: SFunc => classOf[_ => _]
- case _: SCollectionType[_] => classOf[Coll[_]]
- case _: SOption[_] => classOf[Option[_]]
- case t =>
- Evaluation.stypeToRType(t).classTag.runtimeClass
- }
- }
- paramTypes(paramTypes.length - 1) = classOf[ErgoTreeEvaluator]
-
- val methodName = name + "_eval"
- val m = try {
- objType.thisRClass.getMethod(methodName, paramTypes:_*)
- }
- catch { case e: NoSuchMethodException =>
- throw new RuntimeException(s"Cannot find eval method def $methodName(${Seq(paramTypes:_*)})", e)
- }
- m
- }
-
- /** Create a new instance with the given stype. */
- def withSType(newSType: SFunc): SMethod = copy(stype = newSType)
-
- /** Create a new instance with the given cost function. */
- def withCost(costFunc: MethodCostFunc): SMethod = copy(costFunc = Some(costFunc))
-
- /** Create a new instance in which the `stype` field transformed using
- * the given substitution. */
- def withConcreteTypes(subst: Map[STypeVar, SType]): SMethod =
- withSType(stype.withSubstTypes(subst).asFunc)
-
- /** Name of a language operation represented by this method. */
- def opName = objType.getClass.getSimpleName + "." + name
-
- /** Returns [[OperationId]] for AOT costing. */
- def opId: OperationId = {
- OperationId(opName, stype)
- }
-
- /** Specializes this instance by creating a new [[SMethod]] instance where signature
- * is specialized with respect to the given object and args types. It is used in
- * [[sigmastate.serialization.MethodCallSerializer]] `parse` method, so it is part of
- * consensus protocol.
- *
- * @param objTpe specific type of method receiver (aka object)
- * @param args specific types of method arguments
- * @return new instance of method descriptor with specialized signature
- * @consensus
- */
- def specializeFor(objTpe: SType, args: Seq[SType]): SMethod = {
- Terms.unifyTypeLists(stype.tDom, objTpe +: args) match {
- case Some(subst) if subst.nonEmpty =>
- withConcreteTypes(subst)
- case _ => this
- }
- }
-
- /** Create a new instance with the given [[OperationInfo]] parameters. */
- def withInfo(opDesc: ValueCompanion, desc: String, args: ArgInfo*): SMethod = {
- this.copy(docInfo = Some(OperationInfo(opDesc, desc, ArgInfo("this", "this instance") +: args.toSeq)))
- }
-
- /** Create a new instance with the given [[OperationInfo]] parameters.
- * NOTE: opDesc parameter is not defined and falls back to None.
- */
- def withInfo(desc: String, args: ArgInfo*): SMethod = {
- this.copy(docInfo = Some(OperationInfo(None, desc, ArgInfo("this", "this instance") +: args.toSeq)))
- }
-
- /** Create a new instance with the given IR builder (aka MethodCall rewriter) parameter. */
- def withIRInfo(
- irBuilder: PartialFunction[(SigmaBuilder, SValue, SMethod, Seq[SValue], STypeSubst), SValue],
- javaMethod: RMethod = null,
- invokeHandler: InvokeDescBuilder = null): SMethod = {
- this.copy(irInfo = MethodIRInfo(Some(irBuilder), Option(javaMethod), Option(invokeHandler)))
- }
-
- /** Lookup [[ArgInfo]] for the given argName or throw an exception. */
- def argInfo(argName: String): ArgInfo =
- docInfo.get.args.find(_.name == argName).get
-}
-
-
-object SMethod {
- /** Type of functions used to assign cost to method call nodes.
- * For a function `f: (mc, obj, args) => cost` it is called before the evaluation of
- * the `mc` node with the given `obj` as method receiver and `args` as method
- * arguments.
- */
- abstract class MethodCostFunc extends Function4[ErgoTreeEvaluator, MethodCall, Any, Array[Any], CostDetails] {
- /**
- * The function returns an estimated cost of evaluation BEFORE actual evaluation of
- * the method. For this reason [[MethodCostFunc]] is not used for higher-order
- * operations like `Coll.map`, `Coll.filter` etc.
- */
- def apply(E: ErgoTreeEvaluator, mc: MethodCall, obj: Any, args: Array[Any]): CostDetails
- }
-
- /** Returns a cost function which always returs the given cost. */
- def givenCost(costKind: FixedCost): MethodCostFunc = new MethodCostFunc {
- override def apply(E: ErgoTreeEvaluator,
- mc: MethodCall,
- obj: Any, args: Array[Any]): CostDetails = {
- if (E.settings.costTracingEnabled)
- TracedCost(Array(FixedCostItem(MethodDesc(mc.method), costKind)))
- else
- GivenCost(costKind.cost)
- }
- }
-
- /** Returns a cost function which expects `obj` to be of `Coll[T]` type and
- * uses its length to compute SeqCostItem */
- def perItemCost(costKind: PerItemCost): MethodCostFunc = new MethodCostFunc {
- override def apply(E: ErgoTreeEvaluator,
- mc: MethodCall,
- obj: Any, args: Array[Any]): CostDetails = obj match {
- case coll: Coll[a] =>
- if (E.settings.costTracingEnabled) {
- val desc = MethodDesc(mc.method)
- TracedCost(Array(SeqCostItem(desc, costKind, coll.length)))
- }
- else
- GivenCost(costKind.cost(coll.length))
- case _ =>
- ErgoTreeEvaluator.error(
- s"Invalid object $obj of method call $mc: Coll type is expected")
- }
- }
-
- /** Some runtime methods (like Coll.map, Coll.flatMap) require additional RType descriptors.
- * The builder can extract those descriptors from the given type of the method signature.
- */
- type InvokeDescBuilder = SFunc => Seq[SType]
-
- /** Return [[Method]] descriptor for the given `methodName` on the given `cT` type.
- * @param methodName the name of the method to lookup
- * @param cT the class where to search the methodName
- * @param cA1 the class of the method argument
- */
- def javaMethodOf[T, A1](methodName: String)
- (implicit cT: ClassTag[T], cA1: ClassTag[A1]): RMethod =
- RClass(cT.runtimeClass).getMethod(methodName, cA1.runtimeClass)
-
- /** Return [[Method]] descriptor for the given `methodName` on the given `cT` type.
- * @param methodName the name of the method to lookup
- * @param cT the class where to search the methodName
- * @param cA1 the class of the method's first argument
- * @param cA2 the class of the method's second argument
- */
- def javaMethodOf[T, A1, A2]
- (methodName: String)
- (implicit cT: ClassTag[T], cA1: ClassTag[A1], cA2: ClassTag[A2]): RMethod =
- RClass(cT.runtimeClass).getMethod(methodName, cA1.runtimeClass, cA2.runtimeClass)
-
- /** Default fallback method call recognizer which builds MethodCall ErgoTree nodes. */
- val MethodCallIrBuilder: PartialFunction[(SigmaBuilder, SValue, SMethod, Seq[SValue], STypeSubst), SValue] = {
- case (builder, obj, method, args, tparamSubst) =>
- builder.mkMethodCall(obj, method, args.toIndexedSeq, tparamSubst)
- }
-
- /** Convenience factory method. */
- def apply(objType: STypeCompanion, name: String, stype: SFunc,
- methodId: Byte,
- costKind: CostKind): SMethod = {
- SMethod(
- objType, name, stype, methodId, costKind,
- MethodIRInfo(None, None, None), None, None)
- }
-
- /** Looks up [[SMethod]] instance for the given type and method ids.
- *
- * @param typeId id of a type which can contain methods
- * @param methodId id of a method of the type given by `typeId`
- * @return an instance of [[SMethod]] which may contain generic type variables in the
- * signature (see SMethod.stype). As a result `specializeFor` is called by
- * deserializer to obtain monomorphic method descriptor.
- * @consensus this is method is used in [[sigmastate.serialization.MethodCallSerializer]]
- * `parse` method and hence it is part of consensus protocol
- */
- def fromIds(typeId: Byte, methodId: Byte): SMethod = {
- ValidationRules.CheckTypeWithMethods(typeId, SType.types.contains(typeId))
- val typeCompanion = SType.types(typeId)
- val method = typeCompanion.methodById(methodId)
- method
- }
-}
-
-/** Special type to represent untyped values.
- * Interpreter raises an error when encounter a Value with this type.
- * All Value nodes with this type should be elimitanted during typing.
- * If no specific type can be assigned statically during typing,
- * then either error should be raised or type SAny should be assigned
- * which is interpreted as dynamic typing. */
-case object NoType extends SType {
- type WrappedType = Nothing
- override val typeCode = 0: Byte
-}
-
-/** Base trait for all pre-defined types which are not necessary primitive (e.g. Box, AvlTree).
- */
-trait SPredefType extends SType {
-}
-
-/** Base trait for all embeddable types.
- */
-trait SEmbeddable extends SType {
- override def isEmbeddable: Boolean = true
- /** Type code of embeddable type can be combined with code of type constructor.
- * Resulting code can be serialized. This simple convention allows to save space for most frequently used types.
- * See TypeSerializer */
- @inline final def embedIn(typeConstrId: Byte): Byte = (typeConstrId + this.typeCode).toByte
-}
-
-/** Base trait for all primitive types (aka atoms) which don't have internal type items.
- * All primitive types can occupy a reserved interval of codes from 1 to MaxPrimTypeCode. */
-trait SPrimType extends SType with SPredefType {
-}
-
-/** Primitive type recognizer to pattern match on TypeCode */
-object SPrimType {
- def unapply(t: SType): Option[SType] = SType.allPredefTypes.find(_ == t)
-
- /** Type code of the last valid prim type so that (1 to LastPrimTypeCode) is a range of valid codes. */
- final val LastPrimTypeCode: Byte = 8: Byte
-
- /** Upper limit of the interval of valid type codes for primitive types */
- final val MaxPrimTypeCode: Byte = 11: Byte
-
- /** Max possible number of primitive types. */
- final val PrimRange: Byte = (MaxPrimTypeCode + 1).toByte
-}
-
-/** Marker trait for all numeric types. */
-trait SNumericType extends SProduct {
- import SNumericType._
- protected override def getMethods(): Seq[SMethod] = {
- super.getMethods() ++ SNumericType.methods.map {
- m => m.copy(stype = Terms.applySubst(m.stype, Map(tNum -> this)).asFunc)
- }
- }
-
- /** Checks if the given name is a cast method name.
- * @return true if it is. */
- def isCastMethod (name: String): Boolean = castMethods.contains(name)
-
- /** Upcasts the given value of a smaller type to this larger type.
- * Corresponds to section 5.1.2 Widening Primitive Conversion of Java Language Spec.
- * @param n numeric value to be converted
- * @return a value of WrappedType of this type descriptor's instance.
- * @throw exception if `n` has actual type which is larger than this type.
- */
- def upcast(n: AnyVal): WrappedType
-
- /** Downcasts the given value of a larger type to this smaller type.
- * Corresponds to section 5.1.3 Narrowing Primitive Conversion of Java Language Spec.
- * @param n numeric value to be converted
- * @return a value of WrappedType of this type descriptor's instance.
- * @throw exception if the actual value of `i` cannot fit into this type.
- */
- def downcast(n: AnyVal): WrappedType
-
- /** Returns a type which is larger. */
- @inline def max(that: SNumericType): SNumericType =
- if (this.numericTypeIndex > that.numericTypeIndex) this else that
-
- /** Returns true if this numeric type is larger than that. */
- @inline final def >(that: SNumericType): Boolean = this.numericTypeIndex > that.numericTypeIndex
-
- /** Numeric types are ordered by the number of bytes to store the numeric values.
- * @return index in the array of all numeric types. */
- def numericTypeIndex: Int
-
- override def toString: String = this.getClass.getSimpleName
-}
-object SNumericType extends STypeCompanion {
- /** Array of all numeric types ordered by number of bytes in the representation. */
- final val allNumericTypes = Array(SByte, SShort, SInt, SLong, SBigInt)
-
- // TODO v6.0: this typeId is now shadowed by SGlobal.typeId
- // see https://github.com/ScorexFoundation/sigmastate-interpreter/issues/667
- override def typeId: TypeCode = 106: Byte
-
- /** Since this object is not used in SMethod instances. */
- override def reprClass: RClass[_] = sys.error(s"Shouldn't be called.")
-
- /** Type variable used in generic signatures of method descriptors. */
- val tNum = STypeVar("TNum")
-
- /** Cost function which is assigned for numeric cast MethodCall nodes in ErgoTree.
- * It is called as part of MethodCall.eval method. */
- val costOfNumericCast: MethodCostFunc = new MethodCostFunc {
- override def apply(E: ErgoTreeEvaluator,
- mc: MethodCall,
- obj: Any,
- args: Array[Any]): CostDetails = {
- val targetTpe = mc.method.stype.tRange
- val cast = getNumericCast(mc.obj.tpe, mc.method.name, targetTpe).get
- val costKind = if (cast == Downcast) Downcast.costKind else Upcast.costKind
- TracedCost(Array(TypeBasedCostItem(MethodDesc(mc.method), costKind, targetTpe)))
- }
- }
-
- /** The following SMethod instances are descriptors of methods available on all numeric
- * types.
- * @see `val methods` below
- * */
- val ToByteMethod: SMethod = SMethod(this, "toByte", SFunc(tNum, SByte), 1, null)
- .withCost(costOfNumericCast)
- .withInfo(PropertyCall, "Converts this numeric value to \\lst{Byte}, throwing exception if overflow.")
- val ToShortMethod: SMethod = SMethod(this, "toShort", SFunc(tNum, SShort), 2, null)
- .withCost(costOfNumericCast)
- .withInfo(PropertyCall, "Converts this numeric value to \\lst{Short}, throwing exception if overflow.")
- val ToIntMethod: SMethod = SMethod(this, "toInt", SFunc(tNum, SInt), 3, null)
- .withCost(costOfNumericCast)
- .withInfo(PropertyCall, "Converts this numeric value to \\lst{Int}, throwing exception if overflow.")
- val ToLongMethod: SMethod = SMethod(this, "toLong", SFunc(tNum, SLong), 4, null)
- .withCost(costOfNumericCast)
- .withInfo(PropertyCall, "Converts this numeric value to \\lst{Long}, throwing exception if overflow.")
- val ToBigIntMethod: SMethod = SMethod(this, "toBigInt", SFunc(tNum, SBigInt), 5, null)
- .withCost(costOfNumericCast)
- .withInfo(PropertyCall, "Converts this numeric value to \\lst{BigInt}")
-
- /** Cost of: 1) creating Byte collection from a numeric value */
- val ToBytes_CostKind = FixedCost(JitCost(5))
-
- val ToBytesMethod: SMethod = SMethod(
- this, "toBytes", SFunc(tNum, SByteArray), 6, ToBytes_CostKind)
- .withIRInfo(MethodCallIrBuilder)
- .withInfo(PropertyCall,
- """ Returns a big-endian representation of this numeric value in a collection of bytes.
- | For example, the \lst{Int} value \lst{0x12131415} would yield the
- | collection of bytes \lst{[0x12, 0x13, 0x14, 0x15]}.
- """.stripMargin)
-
- /** Cost of: 1) creating Boolean collection (one bool for each bit) from a numeric
- * value. */
- val ToBits_CostKind = FixedCost(JitCost(5))
-
- val ToBitsMethod: SMethod = SMethod(
- this, "toBits", SFunc(tNum, SBooleanArray), 7, ToBits_CostKind)
- .withIRInfo(MethodCallIrBuilder)
- .withInfo(PropertyCall,
- """ Returns a big-endian representation of this numeric in a collection of Booleans.
- | Each boolean corresponds to one bit.
- """.stripMargin)
-
- override val methods: Seq[SMethod] = Array(
- ToByteMethod, // see Downcast
- ToShortMethod, // see Downcast
- ToIntMethod, // see Downcast
- ToLongMethod, // see Downcast
- ToBigIntMethod, // see Downcast
- ToBytesMethod,
- ToBitsMethod
- )
-
- /** Collection of names of numeric casting methods (like `toByte`, `toInt`, etc). */
- val castMethods: Array[String] =
- Array(ToByteMethod, ToShortMethod, ToIntMethod, ToLongMethod, ToBigIntMethod)
- .map(_.name)
-
- /** Checks the given name is numeric type cast method (like toByte, toInt, etc.).*/
- def isCastMethod(name: String): Boolean = castMethods.contains(name)
-
- /** Convert the given method to a cast operation from fromTpe to resTpe. */
- def getNumericCast(fromTpe: SType, methodName: String, resTpe: SType): Option[NumericCastCompanion] = (fromTpe, resTpe) match {
- case (from: SNumericType, to: SNumericType) if isCastMethod(methodName) =>
- val op = if (to > from) Upcast else Downcast
- Some(op)
- case _ => None // the method in not numeric type cast
- }
-
-}
-
-/** Base type for SBoolean and SSigmaProp. */
-trait SLogical extends SType {
-}
-
-/** Monomorphic type descriptor i.e. a type without generic parameters.
- * @see `SGenericType`
- */
-trait SMonoType extends SType with STypeCompanion {
- /** Helper method to create method descriptors for properties (i.e. methods without args). */
- protected def propertyCall(name: String, tpeRes: SType, id: Byte, costKind: CostKind): SMethod =
- SMethod(this, name, SFunc(this, tpeRes), id, costKind)
- .withIRInfo(MethodCallIrBuilder)
- .withInfo(PropertyCall, "")
-
- /** Helper method to create method descriptors for properties (i.e. methods without args). */
- protected def property(name: String, tpeRes: SType, id: Byte, valueCompanion: ValueCompanion): SMethod =
- SMethod(this, name, SFunc(this, tpeRes), id, valueCompanion.costKind)
- .withIRInfo(MethodCallIrBuilder)
- .withInfo(valueCompanion, "")
-}
-
-/** Descriptor of ErgoTree type `Boolean` holding `true` or `false` values. */
-case object SBoolean extends SPrimType with SEmbeddable with SLogical with SProduct with SMonoType {
- override type WrappedType = Boolean
- override val typeCode: TypeCode = 1: Byte
- override def typeId = typeCode
- override val reprClass: RClass[_] = RClass(classOf[Boolean])
-
- val ToByte = "toByte"
- protected override def getMethods() = super.getMethods()
- /* TODO soft-fork: https://github.com/ScorexFoundation/sigmastate-interpreter/issues/479
- ++ Seq(
- SMethod(this, ToByte, SFunc(this, SByte), 1)
- .withInfo(PropertyCall, "Convert true to 1 and false to 0"),
- )
- */
-}
-
-/** Descriptor of ErgoTree type `Byte` - 8-bit signed integer. */
-case object SByte extends SPrimType with SEmbeddable with SNumericType with SMonoType {
- override type WrappedType = Byte
- override val typeCode: TypeCode = 2: Byte
- override val reprClass: RClass[_] = RClass(classOf[Byte])
- override def typeId = typeCode
- override def numericTypeIndex: Int = 0
- override def upcast(v: AnyVal): Byte = v match {
- case b: Byte => b
- case _ => sys.error(s"Cannot upcast value $v to the type $this")
- }
- override def downcast(v: AnyVal): Byte = v match {
- case b: Byte => b
- case s: Short => s.toByteExact
- case i: Int => i.toByteExact
- case l: Long => l.toByteExact
- case _ => sys.error(s"Cannot downcast value $v to the type $this")
- }
-}
-
-/** Descriptor of ErgoTree type `Short` - 16-bit signed integer. */
-case object SShort extends SPrimType with SEmbeddable with SNumericType with SMonoType {
- override type WrappedType = Short
- override val typeCode: TypeCode = 3: Byte
- override val reprClass: RClass[_] = RClass(classOf[Short])
- override def typeId = typeCode
- override def numericTypeIndex: Int = 1
- override def upcast(v: AnyVal): Short = v match {
- case x: Byte => x.toShort
- case x: Short => x
- case _ => sys.error(s"Cannot upcast value $v to the type $this")
- }
- override def downcast(v: AnyVal): Short = v match {
- case s: Short => s
- case i: Int => i.toShortExact
- case l: Long => l.toShortExact
- case _ => sys.error(s"Cannot downcast value $v to the type $this")
- }
-}
-
-/** Descriptor of ErgoTree type `Int` - 32-bit signed integer. */
-case object SInt extends SPrimType with SEmbeddable with SNumericType with SMonoType {
- override type WrappedType = Int
- override val typeCode: TypeCode = 4: Byte
- override val reprClass: RClass[_] = RClass(classOf[Int])
- override def typeId = typeCode
- override def numericTypeIndex: Int = 2
- override def upcast(v: AnyVal): Int = v match {
- case x: Byte => x.toInt
- case x: Short => x.toInt
- case x: Int => x
- case _ => sys.error(s"Cannot upcast value $v to the type $this")
- }
- override def downcast(v: AnyVal): Int = v match {
- case b: Byte => b.toInt
- case s: Short => s.toInt
- case i: Int => i
- case l: Long => l.toIntExact
- case _ => sys.error(s"Cannot downcast value $v to the type $this")
- }
-}
-
-/** Descriptor of ErgoTree type `Long` - 64-bit signed integer. */
-case object SLong extends SPrimType with SEmbeddable with SNumericType with SMonoType {
- override type WrappedType = Long
- override val typeCode: TypeCode = 5: Byte
- override val reprClass: RClass[_] = RClass(classOf[Long])
- override def typeId = typeCode
- override def numericTypeIndex: Int = 3
- override def upcast(v: AnyVal): Long = v match {
- case x: Byte => x.toLong
- case x: Short => x.toLong
- case x: Int => x.toLong
- case x: Long => x
- case _ => sys.error(s"Cannot upcast value $v to the type $this")
- }
- override def downcast(v: AnyVal): Long = v match {
- case b: Byte => b.toLong
- case s: Short => s.toLong
- case i: Int => i.toLong
- case l: Long => l
- case _ => sys.error(s"Cannot downcast value $v to the type $this")
- }
-}
-
-/** Type of 256 bit integet values. Implemented using [[java.math.BigInteger]]. */
-case object SBigInt extends SPrimType with SEmbeddable with SNumericType with SMonoType {
- override type WrappedType = BigInt
- override val typeCode: TypeCode = 6: Byte
- override val reprClass: RClass[_] = RClass(classOf[BigInt])
-
- override def typeId = typeCode
-
- /** Type of Relation binary op like GE, LE, etc. */
- val RelationOpType = SFunc(Array(SBigInt, SBigInt), SBoolean)
-
- /** The maximum size of BigInteger value in byte array representation. */
- val MaxSizeInBytes: Long = SigmaConstants.MaxBigIntSizeInBytes.value
-
- override def numericTypeIndex: Int = 4
-
- override def upcast(v: AnyVal): BigInt = {
- val bi = v match {
- case x: Byte => BigInteger.valueOf(x.toLong)
- case x: Short => BigInteger.valueOf(x.toLong)
- case x: Int => BigInteger.valueOf(x.toLong)
- case x: Long => BigInteger.valueOf(x)
- case _ => sys.error(s"Cannot upcast value $v to the type $this")
- }
- SigmaDsl.BigInt(bi)
- }
- override def downcast(v: AnyVal): BigInt = {
- val bi = v match {
- case x: Byte => BigInteger.valueOf(x.toLong)
- case x: Short => BigInteger.valueOf(x.toLong)
- case x: Int => BigInteger.valueOf(x.toLong)
- case x: Long => BigInteger.valueOf(x)
- case _ => sys.error(s"Cannot downcast value $v to the type $this")
- }
- SigmaDsl.BigInt(bi)
- }
-
- /** The following `modQ` methods are not fully implemented in v4.x and this descriptors.
- * This descritors are remain here in the code and are waiting for full implementation
- * is upcoming soft-forks at which point the cost parameters should be calculated and
- * changed.
- */
- val ModQMethod = SMethod(this, "modQ", SFunc(this, SBigInt), 1, FixedCost(JitCost(1)))
- .withInfo(ModQ, "Returns this \\lst{mod} Q, i.e. remainder of division by Q, where Q is an order of the cryprographic group.")
- val PlusModQMethod = SMethod(this, "plusModQ", SFunc(IndexedSeq(this, SBigInt), SBigInt), 2, FixedCost(JitCost(1)))
- .withInfo(ModQArithOp.PlusModQ, "Adds this number with \\lst{other} by module Q.", ArgInfo("other", "Number to add to this."))
- val MinusModQMethod = SMethod(this, "minusModQ", SFunc(IndexedSeq(this, SBigInt), SBigInt), 3, FixedCost(JitCost(1)))
- .withInfo(ModQArithOp.MinusModQ, "Subtracts \\lst{other} number from this by module Q.", ArgInfo("other", "Number to subtract from this."))
- val MultModQMethod = SMethod(this, "multModQ", SFunc(IndexedSeq(this, SBigInt), SBigInt), 4, FixedCost(JitCost(1)))
- .withIRInfo(MethodCallIrBuilder)
- .withInfo(MethodCall, "Multiply this number with \\lst{other} by module Q.", ArgInfo("other", "Number to multiply with this."))
-
- protected override def getMethods() = super.getMethods() ++ Seq(
-// ModQMethod,
-// PlusModQMethod,
-// MinusModQMethod,
- // TODO soft-fork: https://github.com/ScorexFoundation/sigmastate-interpreter/issues/479
- // MultModQMethod,
- )
-}
-
-/** Descriptor of type `String` which is not used in ErgoTree, but used in ErgoScript.
- * NOTE: this descriptor both type and type companion */
-case object SString extends SProduct with SMonoType {
- override type WrappedType = String
- override val typeCode: TypeCode = 102: Byte
- override def typeId = typeCode
- override def reprClass: RClass[_] = RClass(classOf[String])
-}
-
-/** Descriptor of ErgoTree type `GroupElement`.
- * NOTE: this descriptor both type and type companion */
-case object SGroupElement extends SProduct with SPrimType with SEmbeddable with SMonoType {
- override type WrappedType = GroupElement
- override val typeCode: TypeCode = 7: Byte
- override val reprClass: RClass[_] = RClass(classOf[GroupElement])
-
- override def typeId = typeCode
-
- /** Cost of: 1) serializing EcPointType to bytes 2) packing them in Coll. */
- val GetEncodedCostKind = FixedCost(JitCost(250))
-
- /** The following SMethod instances are descriptors of methods defined in `GroupElement` type. */
- lazy val GetEncodedMethod: SMethod = SMethod(
- this, "getEncoded", SFunc(Array(this), SByteArray), 2, GetEncodedCostKind)
- .withIRInfo(MethodCallIrBuilder)
- .withInfo(PropertyCall, "Get an encoding of the point value.")
-
- lazy val ExponentiateMethod: SMethod = SMethod(
- this, "exp", SFunc(Array(this, SBigInt), this), 3, Exponentiate.costKind)
- .withIRInfo({ case (builder, obj, _, Seq(arg), _) =>
- builder.mkExponentiate(obj.asGroupElement, arg.asBigInt)
- })
- .withInfo(Exponentiate,
- "Exponentiate this \\lst{GroupElement} to the given number. Returns this to the power of k",
- ArgInfo("k", "The power"))
-
- lazy val MultiplyMethod: SMethod = SMethod(
- this, "multiply", SFunc(Array(this, SGroupElement), this), 4, MultiplyGroup.costKind)
- .withIRInfo({ case (builder, obj, _, Seq(arg), _) =>
- builder.mkMultiplyGroup(obj.asGroupElement, arg.asGroupElement)
- })
- .withInfo(MultiplyGroup, "Group operation.", ArgInfo("other", "other element of the group"))
-
- /** Cost of: 1) calling EcPoint.negate 2) wrapping in GroupElement. */
- val Negate_CostKind = FixedCost(JitCost(45))
-
- lazy val NegateMethod: SMethod = SMethod(
- this, "negate", SFunc(this, this), 5, Negate_CostKind)
- .withIRInfo(MethodCallIrBuilder)
- .withInfo(PropertyCall, "Inverse element of the group.")
-
- protected override def getMethods(): Seq[SMethod] = super.getMethods() ++ Seq(
- /* TODO soft-fork: https://github.com/ScorexFoundation/sigmastate-interpreter/issues/479
- SMethod(this, "isIdentity", SFunc(this, SBoolean), 1)
- .withInfo(PropertyCall, "Checks if this value is identity element of the eliptic curve group."),
- */
- GetEncodedMethod,
- ExponentiateMethod,
- MultiplyMethod,
- NegateMethod
- )
-}
-
-/** Descriptor of ErgoTree type `SigmaProp` which represent sigma-protocol propositions. */
-case object SSigmaProp extends SProduct with SPrimType with SEmbeddable with SLogical with SMonoType {
- import SType._
- override type WrappedType = SigmaProp
- override val typeCode: TypeCode = 8: Byte
- override val reprClass: RClass[_] = RClass(classOf[SigmaProp])
- override def typeId = typeCode
-
- /** The maximum size of SigmaProp value in serialized byte array representation. */
- val MaxSizeInBytes: Long = SigmaConstants.MaxSigmaPropSizeInBytes.value
-
- val PropBytes = "propBytes"
- val IsProven = "isProven"
- lazy val PropBytesMethod = SMethod(
- this, PropBytes, SFunc(this, SByteArray), 1, SigmaPropBytes.costKind)
- .withInfo(SigmaPropBytes, "Serialized bytes of this sigma proposition taken as ErgoTree.")
-
- lazy val IsProvenMethod = SMethod(this, IsProven, SFunc(this, SBoolean), 2, null)
- .withInfo(// available only at frontend of ErgoScript
- "Verify that sigma proposition is proven.")
-
- protected override def getMethods() = super.getMethods() ++ Seq(
- PropBytesMethod, IsProvenMethod
- )
-}
-
-/** Any other type is implicitly subtype of this type. */
-case object SAny extends SPrimType {
- override type WrappedType = Any
- override val typeCode: TypeCode = 97: Byte
-}
-
-/** The type with single inhabitant value `()` */
-case object SUnit extends SPrimType {
- override type WrappedType = Unit
- override val typeCode: TypeCode = 98: Byte
-}
-
-/** Type description of optional values. Instances of `Option`
- * are either constructed by `Some` or by `None` constructors. */
-case class SOption[ElemType <: SType](elemType: ElemType) extends SProduct with SGenericType {
- import SOption._
- override type WrappedType = Option[ElemType#WrappedType]
- override val typeCode: TypeCode = SOption.OptionTypeCode
- protected override def getMethods() = super.getMethods() ++ SOption.methods
- override def toString = s"Option[$elemType]"
- override def toTermString: String = s"Option[${elemType.toTermString}]"
- override lazy val typeParams: Seq[STypeParam] = Array(SType.paramT)
-}
-
-object SOption extends STypeCompanion {
- /** Code of `Option[_]` type constructor. */
- val OptionTypeConstrId = 3
- /** Type code for `Option[T] for some T` type used in TypeSerializer. */
- val OptionTypeCode: TypeCode = ((SPrimType.MaxPrimTypeCode + 1) * OptionTypeConstrId).toByte
- /** Code of `Option[Coll[_]]` type constructor. */
- val OptionCollectionTypeConstrId = 4
- /** Type code for `Option[Coll[T]] for some T` type used in TypeSerializer. */
- val OptionCollectionTypeCode: TypeCode = ((SPrimType.MaxPrimTypeCode + 1) * OptionCollectionTypeConstrId).toByte
-
- override def typeId = OptionTypeCode
-
- override val reprClass: RClass[_] = RClass(classOf[Option[_]])
-
- type SBooleanOption = SOption[SBoolean.type]
- type SByteOption = SOption[SByte.type]
- type SShortOption = SOption[SShort.type]
- type SIntOption = SOption[SInt.type]
- type SLongOption = SOption[SLong.type]
- type SBigIntOption = SOption[SBigInt.type]
- type SGroupElementOption = SOption[SGroupElement.type]
- type SBoxOption = SOption[SBox.type]
- type SAvlTreeOption = SOption[SAvlTree.type]
-
- /** This descriptors are instantiated once here and then reused. */
- implicit val SByteOption = SOption(SByte)
- implicit val SByteArrayOption = SOption(SByteArray)
- implicit val SShortOption = SOption(SShort)
- implicit val SIntOption = SOption(SInt)
- implicit val SLongOption = SOption(SLong)
- implicit val SBigIntOption = SOption(SBigInt)
- implicit val SBooleanOption = SOption(SBoolean)
- implicit val SAvlTreeOption = SOption(SAvlTree)
- implicit val SGroupElementOption = SOption(SGroupElement)
- implicit val SSigmaPropOption = SOption(SSigmaProp)
- implicit val SBoxOption = SOption(SBox)
-
- val IsDefined = "isDefined"
- val Get = "get"
- val GetOrElse = "getOrElse"
-
- import SType.{tT, tR, paramT, paramR}
-
- /** Type descriptor of `this` argument used in the methods below. */
- val ThisType = SOption(tT)
-
- /** The following SMethod instances are descriptors of methods defined in `Option` type. */
- val IsDefinedMethod = SMethod(
- this, IsDefined, SFunc(ThisType, SBoolean), 2, OptionIsDefined.costKind)
- .withIRInfo({
- case (builder, obj, _, args, _) if args.isEmpty => builder.mkOptionIsDefined(obj.asValue[SOption[SType]])
- })
- .withInfo(OptionIsDefined,
- "Returns \\lst{true} if the option is an instance of \\lst{Some}, \\lst{false} otherwise.")
-
- val GetMethod = SMethod(this, Get, SFunc(ThisType, tT), 3, OptionGet.costKind)
- .withIRInfo({
- case (builder, obj, _, args, _) if args.isEmpty => builder.mkOptionGet(obj.asValue[SOption[SType]])
- })
- .withInfo(OptionGet,
- """Returns the option's value. The option must be nonempty. Throws exception if the option is empty.""")
-
- lazy val GetOrElseMethod = SMethod(
- this, GetOrElse, SFunc(Array(ThisType, tT), tT, Array[STypeParam](tT)), 4, OptionGetOrElse.costKind)
- .withIRInfo(irBuilder = {
- case (builder, obj, _, Seq(d), _) => builder.mkOptionGetOrElse(obj.asValue[SOption[SType]], d)
- })
- .withInfo(OptionGetOrElse,
- """Returns the option's value if the option is nonempty, otherwise
- |return the result of evaluating \lst{default}.
- """.stripMargin, ArgInfo("default", "the default value"))
-
-// TODO soft-fork: https://github.com/ScorexFoundation/sigmastate-interpreter/issues/479
-// val FoldMethod = SMethod(
-// this, Fold, SFunc(Array(ThisType, tR, SFunc(tT, tR)), tR, Array[STypeParam](tT, tR)), 5, FixedCost(JitCost(1)))
-// .withInfo(MethodCall,
-// """Returns the result of applying \lst{f} to this option's
-// | value if the option is nonempty. Otherwise, evaluates
-// | expression \lst{ifEmpty}.
-// | This is equivalent to \lst{option map f getOrElse ifEmpty}.
-// """.stripMargin,
-// ArgInfo("ifEmpty", "the expression to evaluate if empty"),
-// ArgInfo("f", "the function to apply if nonempty"))
-
- val MapMethod = SMethod(this, "map",
- SFunc(Array(ThisType, SFunc(tT, tR)), SOption(tR), Array(paramT, paramR)), 7, FixedCost(JitCost(20)))
- .withIRInfo(MethodCallIrBuilder)
- .withInfo(MethodCall,
- """Returns a \lst{Some} containing the result of applying \lst{f} to this option's
- | value if this option is nonempty.
- | Otherwise return \lst{None}.
- """.stripMargin, ArgInfo("f", "the function to apply"))
-
- val FilterMethod = SMethod(this, "filter",
- SFunc(Array(ThisType, SFunc(tT, SBoolean)), ThisType, Array(paramT)), 8, FixedCost(JitCost(20)))
- .withIRInfo(MethodCallIrBuilder)
- .withInfo(MethodCall,
- """Returns this option if it is nonempty and applying the predicate \lst{p} to
- | this option's value returns true. Otherwise, return \lst{None}.
- """.stripMargin, ArgInfo("p", "the predicate used for testing"))
-
- val methods: Seq[SMethod] = Seq(
- IsDefinedMethod,
- GetMethod,
- GetOrElseMethod,
- /* TODO soft-fork: https://github.com/ScorexFoundation/sigmastate-interpreter/issues/479
- FoldMethod,
- */
- MapMethod,
- FilterMethod
- )
- def apply[T <: SType](implicit elemType: T, ov: Overload1): SOption[T] = SOption(elemType)
-}
-
-/** Base class for descriptors of `Coll[T]` ErgoTree type for some elemType T. */
-trait SCollection[T <: SType] extends SProduct with SGenericType {
- def elemType: T
- override type WrappedType = Coll[T#WrappedType]
-}
-
-/** Descriptor of `Coll[T]` ErgoTree type for some elemType T. */
-case class SCollectionType[T <: SType](elemType: T) extends SCollection[T] {
- override val typeCode: TypeCode = SCollectionType.CollectionTypeCode
- override def typeParams: Seq[STypeParam] = SCollectionType.typeParams
- protected override def getMethods() = super.getMethods() ++ SCollection.methods
- override def toString = s"Coll[$elemType]"
- override def toTermString = s"Coll[${elemType.toTermString}]"
-}
-
-object SCollectionType {
- /** Code of `Coll[_]` type constructor. */
- val CollectionTypeConstrId = 1
-
- /** Type code for `Coll[T] for some T` type used in TypeSerializer. */
- val CollectionTypeCode: TypeCode = ((SPrimType.MaxPrimTypeCode + 1) * CollectionTypeConstrId).toByte
-
- /** Code of `Coll[Coll[_]]` type constructor. */
- val NestedCollectionTypeConstrId = 2
-
- /** Type code for `Coll[Coll[T]] for some T` type used in TypeSerializer. */
- val NestedCollectionTypeCode: TypeCode = ((SPrimType.MaxPrimTypeCode + 1) * NestedCollectionTypeConstrId).toByte
-
- /** Array of generic type parameters reused in all SCollectionType instances. */
- val typeParams: Seq[STypeParam] = Array(SType.paramIV)
-}
-
-object SCollection extends STypeCompanion with MethodByNameUnapply {
- override val reprClass: RClass[_] = RClass(classOf[Coll[_]])
- override def typeId = SCollectionType.CollectionTypeCode
-
- import SType.{tK, tV, paramIV, paramIVSeq, paramOV}
-
- /** Helper descriptors reused across different method descriptors. */
- def tIV = SType.tIV
- def tOV = SType.tOV
-
- /** This descriptors are instantiated once here and then reused. */
- val ThisType = SCollection(tIV)
- val tOVColl = SCollection(tOV)
- val tPredicate = SFunc(tIV, SBoolean)
-
- /** The following SMethod instances are descriptors of methods defined in `Coll` type. */
- val SizeMethod = SMethod(this, "size", SFunc(ThisType, SInt), 1, SizeOf.costKind)
- .withInfo(SizeOf, "The size of the collection in elements.")
-
- val GetOrElseMethod = SMethod(
- this, "getOrElse", SFunc(Array(ThisType, SInt, tIV), tIV, paramIVSeq), 2, DynamicCost)
- .withIRInfo({ case (builder, obj, _, Seq(index, defaultValue), _) =>
- val index1 = index.asValue[SInt.type]
- val defaultValue1 = defaultValue.asValue[SType]
- builder.mkByIndex(obj.asValue[SCollection[SType]], index1, Some(defaultValue1))
- })
- .withInfo(ByIndex, "Return the element of collection if \\lst{index} is in range \\lst{0 .. size-1}",
- ArgInfo("index", "index of the element of this collection"),
- ArgInfo("default", "value to return when \\lst{index} is out of range"))
-
- /** Implements evaluation of Coll.getOrElse method call ErgoTree node.
- * Called via reflection based on naming convention.
- * @see SMethod.evalMethod
- */
- def getOrElse_eval[A](mc: MethodCall, xs: Coll[A], i: Int, default: A)(implicit E: ErgoTreeEvaluator): A = {
- E.addCost(ByIndex.costKind, mc.method.opDesc)
- // the following lines should be semantically the same as in ByIndex.eval
- Value.checkType(mc.args.last.tpe, default)
- xs.getOrElse(i, default)
- }
-
- val MapMethod = SMethod(this, "map",
- SFunc(Array(ThisType, SFunc(tIV, tOV)), tOVColl, Array(paramIV, paramOV)), 3, MapCollection.costKind)
- .withIRInfo({
- case (builder, obj, _, Seq(mapper), _) => builder.mkMapCollection(obj.asValue[SCollection[SType]], mapper.asFunc)
- })
- .withInfo(MapCollection,
- """ Builds a new collection by applying a function to all elements of this collection.
- | Returns a new collection of type \lst{Coll[B]} resulting from applying the given function
- | \lst{f} to each element of this collection and collecting the results.
- """.stripMargin,
- ArgInfo("f", "the function to apply to each element"))
-
- /** Implements evaluation of Coll.map method call ErgoTree node.
- * Called via reflection based on naming convention.
- * @see SMethod.evalMethod
- */
- def map_eval[A,B](mc: MethodCall, xs: Coll[A], f: A => B)(implicit E: ErgoTreeEvaluator): Coll[B] = {
- val tpeB = mc.tpe.asInstanceOf[SCollection[SType]].elemType
- val tB = Evaluation.stypeToRType(tpeB).asInstanceOf[RType[B]]
- E.addSeqCostNoOp(MapCollection.costKind, xs.length, mc.method.opDesc)
- xs.map(f)(tB)
- }
-
- val ExistsMethod = SMethod(this, "exists",
- SFunc(Array(ThisType, tPredicate), SBoolean, paramIVSeq), 4, Exists.costKind)
- .withIRInfo({
- case (builder, obj, _, Seq(c), _) => builder.mkExists(obj.asValue[SCollection[SType]], c.asFunc)
- })
- .withInfo(Exists,
- """Tests whether a predicate holds for at least one element of this collection.
- |Returns \lst{true} if the given predicate \lst{p} is satisfied by at least one element of this collection, otherwise \lst{false}
- """.stripMargin,
- ArgInfo("p", "the predicate used to test elements"))
-
- val FoldMethod = SMethod(
- this, "fold",
- SFunc(Array(ThisType, tOV, SFunc(Array(tOV, tIV), tOV)), tOV, Array(paramIV, paramOV)),
- 5, Fold.costKind)
- .withIRInfo({
- case (builder, obj, _, Seq(z, op), _) => builder.mkFold(obj.asValue[SCollection[SType]], z, op.asFunc)
- })
- .withInfo(Fold, "Applies a binary operator to a start value and all elements of this collection, going left to right.",
- ArgInfo("zero", "a starting value"),
- ArgInfo("op", "the binary operator"))
-
- val ForallMethod = SMethod(this, "forall",
- SFunc(Array(ThisType, tPredicate), SBoolean, paramIVSeq), 6, ForAll.costKind)
- .withIRInfo({
- case (builder, obj, _, Seq(c), _) => builder.mkForAll(obj.asValue[SCollection[SType]], c.asFunc)
- })
- .withInfo(ForAll,
- """Tests whether a predicate holds for all elements of this collection.
- |Returns \lst{true} if this collection is empty or the given predicate \lst{p}
- |holds for all elements of this collection, otherwise \lst{false}.
- """.stripMargin,
- ArgInfo("p", "the predicate used to test elements"))
-
- val SliceMethod = SMethod(this, "slice",
- SFunc(Array(ThisType, SInt, SInt), ThisType, paramIVSeq), 7, Slice.costKind)
- .withIRInfo({
- case (builder, obj, _, Seq(from, until), _) =>
- builder.mkSlice(obj.asCollection[SType], from.asIntValue, until.asIntValue)
- })
- .withInfo(Slice,
- """Selects an interval of elements. The returned collection is made up
- | of all elements \lst{x} which satisfy the invariant:
- | \lst{
- | from <= indexOf(x) < until
- | }
- """.stripMargin,
- ArgInfo("from", "the lowest index to include from this collection"),
- ArgInfo("until", "the lowest index to EXCLUDE from this collection"))
-
- val FilterMethod = SMethod(this, "filter",
- SFunc(Array(ThisType, tPredicate), ThisType, paramIVSeq), 8, Filter.costKind)
- .withIRInfo({
- case (builder, obj, _, Seq(l), _) => builder.mkFilter(obj.asValue[SCollection[SType]], l.asFunc)
- })
- .withInfo(Filter,
- """Selects all elements of this collection which satisfy a predicate.
- | Returns a new collection consisting of all elements of this collection that satisfy the given
- | predicate \lst{p}. The order of the elements is preserved.
- """.stripMargin,
- ArgInfo("p", "the predicate used to test elements."))
-
- val AppendMethod = SMethod(this, "append",
- SFunc(Array(ThisType, ThisType), ThisType, paramIVSeq), 9, Append.costKind)
- .withIRInfo({
- case (builder, obj, _, Seq(xs), _) =>
- builder.mkAppend(obj.asCollection[SType], xs.asCollection[SType])
- })
- .withInfo(Append, "Puts the elements of other collection after the elements of this collection (concatenation of 2 collections)",
- ArgInfo("other", "the collection to append at the end of this"))
-
- val ApplyMethod = SMethod(this, "apply",
- SFunc(Array(ThisType, SInt), tIV, Array[STypeParam](tIV)), 10, ByIndex.costKind)
- .withInfo(ByIndex,
- """The element at given index.
- | Indices start at \lst{0}; \lst{xs.apply(0)} is the first element of collection \lst{xs}.
- | Note the indexing syntax \lst{xs(i)} is a shorthand for \lst{xs.apply(i)}.
- | Returns the element at the given index.
- | Throws an exception if \lst{i < 0} or \lst{length <= i}
- """.stripMargin, ArgInfo("i", "the index"))
-
- /** Cost of creating a collection of indices */
- val IndicesMethod_CostKind = PerItemCost(
- baseCost = JitCost(20), perChunkCost = JitCost(2), chunkSize = 16)
-
- val IndicesMethod = SMethod(
- this, "indices", SFunc(ThisType, SCollection(SInt)), 14, IndicesMethod_CostKind)
- .withIRInfo(MethodCallIrBuilder)
- .withInfo(PropertyCall,
- """Produces the range of all indices of this collection as a new collection
- | containing [0 .. length-1] values.
- """.stripMargin)
-
- /** Implements evaluation of Coll.indices method call ErgoTree node.
- * Called via reflection based on naming convention.
- * @see SMethod.evalMethod
- */
- def indices_eval[A, B](mc: MethodCall, xs: Coll[A])
- (implicit E: ErgoTreeEvaluator): Coll[Int] = {
- val m = mc.method
- E.addSeqCost(m.costKind.asInstanceOf[PerItemCost], xs.length, m.opDesc) { () =>
- xs.indices
- }
- }
- /** BaseCost:
- * 1) base cost of Coll.flatMap
- * PerChunkCost:
- * 1) cost of Coll.flatMap (per item)
- * 2) new collection is allocated for each item
- * 3) each collection is then appended to the resulting collection */
- val FlatMapMethod_CostKind = PerItemCost(
- baseCost = JitCost(60), perChunkCost = JitCost(10), chunkSize = 8)
-
- val FlatMapMethod = SMethod(this, "flatMap",
- SFunc(Array(ThisType, SFunc(tIV, tOVColl)), tOVColl, Array(paramIV, paramOV)),
- 15, FlatMapMethod_CostKind)
- .withIRInfo(
- MethodCallIrBuilder,
- javaMethodOf[Coll[_], Function1[_,_], RType[_]]("flatMap"),
- { mtype => Array(mtype.tRange.asCollection[SType].elemType) })
- .withInfo(MethodCall,
- """ Builds a new collection by applying a function to all elements of this collection
- | and using the elements of the resulting collections.
- | Function \lst{f} is constrained to be of the form \lst{x => x.someProperty}, otherwise
- | it is illegal.
- | Returns a new collection of type \lst{Coll[B]} resulting from applying the given collection-valued function
- | \lst{f} to each element of this collection and concatenating the results.
- """.stripMargin, ArgInfo("f", "the function to apply to each element."))
-
- /** We assume all flatMap body patterns have similar executon cost. */
- final val CheckFlatmapBody_Info = OperationCostInfo(
- PerItemCost(baseCost = JitCost(20), perChunkCost = JitCost(20), chunkSize = 1),
- NamedDesc("CheckFlatmapBody"))
-
-
- /** This patterns recognize all expressions, which are allowed as lambda body
- * of flatMap. Other bodies are rejected with throwing exception.
- */
- val flatMap_BodyPatterns = Array[PartialFunction[SValue, Int]](
- { case MethodCall(ValUse(id, tpe), m, args, _) if args.isEmpty => id },
- { case ExtractScriptBytes(ValUse(id, _)) => id },
- { case ExtractId(ValUse(id, _)) => id },
- { case SigmaPropBytes(ValUse(id, _)) => id },
- { case ExtractBytes(ValUse(id, _)) => id },
- { case ExtractBytesWithNoRef(ValUse(id, _)) => id }
- )
-
- /** Check the given expression is valid body of flatMap argument lambda.
- * @param varId id of lambda variable (see [[FuncValue]].args)
- * @param expr expression with is expected to use varId in ValUse node.
- * @return true if the body is allowed
- */
- def isValidPropertyAccess(varId: Int, expr: SValue)
- (implicit E: ErgoTreeEvaluator): Boolean = {
- var found = false
- // NOTE: the cost depends on the position of the pattern since
- // we are checking until the first matching pattern found.
- E.addSeqCost(CheckFlatmapBody_Info) { () =>
- // the loop is bounded because flatMap_BodyPatterns is fixed
- var i = 0
- val nPatterns = flatMap_BodyPatterns.length
- while (i < nPatterns && !found) {
- val p = flatMap_BodyPatterns(i)
- found = p.lift(expr) match {
- case Some(id) => id == varId // `id` in the pattern is equal to lambda `varId`
- case None => false
- }
- i += 1
- }
- i // how many patterns checked
- }
- found
- }
-
- /** Operation descriptor for matching `flatMap` method calls with valid lambdas. */
- final val MatchSingleArgMethodCall_Info = OperationCostInfo(
- FixedCost(JitCost(30)), NamedDesc("MatchSingleArgMethodCall"))
-
- /** Recognizer of `flatMap` method calls with valid lambdas. */
- object IsSingleArgMethodCall {
- def unapply(mc:MethodCall)
- (implicit E: ErgoTreeEvaluator): Nullable[(Int, SValue)] = {
- var res: Nullable[(Int, SValue)] = Nullable.None
- E.addFixedCost(MatchSingleArgMethodCall_Info) {
- res = mc match {
- case MethodCall(_, m, Seq(FuncValue(args, body)), _) if args.length == 1 =>
- val id = args(0)._1
- Nullable((id, body))
- case _ =>
- Nullable.None
- }
- }
- res
- }
- }
-
- /** Checks that the given [[MethodCall]] operation is valid flatMap. */
- def checkValidFlatmap(mc: MethodCall)(implicit E: ErgoTreeEvaluator) = {
- mc match {
- case IsSingleArgMethodCall(varId, lambdaBody)
- if isValidPropertyAccess(varId, lambdaBody) =>
- // ok, do nothing
- case _ =>
- throwInvalidFlatmap(mc)
- }
- }
-
- def throwInvalidFlatmap(mc: MethodCall) = {
- ErgoTreeEvaluator.error(
- s"Unsupported lambda in flatMap: allowed usage `xs.flatMap(x => x.property)`: $mc")
- }
-
- /** Implements evaluation of Coll.flatMap method call ErgoTree node.
- * Called via reflection based on naming convention.
- * @see SMethod.evalMethod
- */
- def flatMap_eval[A, B](mc: MethodCall, xs: Coll[A], f: A => Coll[B])
- (implicit E: ErgoTreeEvaluator): Coll[B] = {
- val m = mc.method
- var res: Coll[B] = null
- E.addSeqCost(m.costKind.asInstanceOf[PerItemCost], m.opDesc) { () =>
- val tpeB = mc.tpe.asInstanceOf[SCollection[SType]].elemType
- val tB = Evaluation.stypeToRType(tpeB).asInstanceOf[RType[B]]
- res = xs.flatMap(f)(tB)
- res.length
- }
- res
- }
-
- val PatchMethod = SMethod(this, "patch",
- SFunc(Array(ThisType, SInt, ThisType, SInt), ThisType, paramIVSeq),
- 19, PerItemCost(baseCost = JitCost(30), perChunkCost = JitCost(2), chunkSize = 10))
- .withIRInfo(MethodCallIrBuilder)
- .withInfo(MethodCall,
- "Produces a new Coll where a slice of elements in this Coll is replaced by another Coll.")
-
- /** Implements evaluation of Coll.patch method call ErgoTree node.
- * Called via reflection based on naming convention.
- * @see SMethod.evalMethod
- */
- def patch_eval[A](mc: MethodCall, xs: Coll[A], from: Int, patch: Coll[A], replaced: Int)
- (implicit E: ErgoTreeEvaluator): Coll[A] = {
- val m = mc.method
- val nItems = xs.length + patch.length
- E.addSeqCost(m.costKind.asInstanceOf[PerItemCost], nItems, m.opDesc) { () =>
- xs.patch(from, patch, replaced)
- }
- }
-
- val UpdatedMethod = SMethod(this, "updated",
- SFunc(Array(ThisType, SInt, tIV), ThisType, paramIVSeq),
- 20, PerItemCost(baseCost = JitCost(20), perChunkCost = JitCost(1), chunkSize = 10))
- .withIRInfo(MethodCallIrBuilder, javaMethodOf[Coll[_], Int, Any]("updated"))
- .withInfo(MethodCall,
- "A copy of this Coll with one single replaced element.")
-
- /** Implements evaluation of Coll.updated method call ErgoTree node.
- * Called via reflection based on naming convention.
- * @see SMethod.evalMethod
- */
- def updated_eval[A](mc: MethodCall, coll: Coll[A], index: Int, elem: A)
- (implicit E: ErgoTreeEvaluator): Coll[A] = {
- val m = mc.method
- val costKind = m.costKind.asInstanceOf[PerItemCost]
- E.addSeqCost(costKind, coll.length, m.opDesc) { () =>
- coll.updated(index, elem)
- }
- }
-
- val UpdateManyMethod = SMethod(this, "updateMany",
- SFunc(Array(ThisType, SCollection(SInt), ThisType), ThisType, paramIVSeq),
- 21, PerItemCost(baseCost = JitCost(20), perChunkCost = JitCost(2), chunkSize = 10))
- .withIRInfo(MethodCallIrBuilder).withInfo(MethodCall, "")
-
- /** Implements evaluation of Coll.updateMany method call ErgoTree node.
- * Called via reflection based on naming convention.
- * @see SMethod.evalMethod
- */
- def updateMany_eval[A](mc: MethodCall, coll: Coll[A], indexes: Coll[Int], values: Coll[A])
- (implicit E: ErgoTreeEvaluator): Coll[A] = {
- val costKind = mc.method.costKind.asInstanceOf[PerItemCost]
- E.addSeqCost(costKind, coll.length, mc.method.opDesc) { () =>
- coll.updateMany(indexes, values)
- }
- }
-
- val IndexOfMethod = SMethod(this, "indexOf",
- SFunc(Array(ThisType, tIV, SInt), SInt, paramIVSeq),
- 26, PerItemCost(baseCost = JitCost(20), perChunkCost = JitCost(10), chunkSize = 2))
- .withIRInfo(MethodCallIrBuilder, javaMethodOf[Coll[_], Any, Int]("indexOf"))
- .withInfo(MethodCall, "")
-
- /** Implements evaluation of Coll.indexOf method call ErgoTree node.
- * Called via reflection based on naming convention.
- * @see SMethod.evalMethod
- */
- def indexOf_eval[A](mc: MethodCall, xs: Coll[A], elem: A, from: Int)
- (implicit E: ErgoTreeEvaluator): Int = {
- val costKind = mc.method.costKind.asInstanceOf[PerItemCost]
- var res: Int = -1
- E.addSeqCost(costKind, mc.method.opDesc) { () =>
- // this loop is bounded because MaxArrayLength limit is enforced
- val len = xs.length
- val start = math.max(from, 0)
- var i = start
- var different = true
- while (i < len && different) {
- different = !DataValueComparer.equalDataValues(xs(i), elem)
- i += 1
- }
- if (!different)
- res = i - 1
- i - start // return number of performed iterations
- }
- res
- }
-
- /** Cost descriptor of Coll.zip operation. */
- val Zip_CostKind = PerItemCost(
- baseCost = JitCost(10), perChunkCost = JitCost(1), chunkSize = 10)
-
- val ZipMethod = SMethod(this, "zip",
- SFunc(Array(ThisType, tOVColl), SCollection(STuple(tIV, tOV)), Array[STypeParam](tIV, tOV)),
- 29, Zip_CostKind)
- .withIRInfo(MethodCallIrBuilder)
- .withInfo(MethodCall, "")
-
- /** Implements evaluation of Coll.zip method call ErgoTree node.
- * Called via reflection based on naming convention.
- * @see SMethod.evalMethod
- */
- def zip_eval[A, B](mc: MethodCall, xs: Coll[A], ys: Coll[B])
- (implicit E: ErgoTreeEvaluator): Coll[(A,B)] = {
- val m = mc.method
- E.addSeqCost(m.costKind.asInstanceOf[PerItemCost], xs.length, m.opDesc) { () =>
- xs.zip(ys)
- }
- }
-
- override lazy val methods: Seq[SMethod] = Seq(
- SizeMethod,
- GetOrElseMethod,
- MapMethod,
- ExistsMethod,
- FoldMethod,
- ForallMethod,
- SliceMethod,
- FilterMethod,
- AppendMethod,
- ApplyMethod,
- IndicesMethod,
- FlatMapMethod,
- PatchMethod,
- UpdatedMethod,
- UpdateManyMethod,
- IndexOfMethod,
- ZipMethod
- )
-
- /** Helper constructors. */
- def apply[T <: SType](elemType: T): SCollection[T] = SCollectionType(elemType)
- def apply[T <: SType](implicit elemType: T, ov: Overload1): SCollection[T] = SCollectionType(elemType)
-
- type SBooleanArray = SCollection[SBoolean.type]
- type SByteArray = SCollection[SByte.type]
- type SShortArray = SCollection[SShort.type]
- type SIntArray = SCollection[SInt.type]
- type SLongArray = SCollection[SLong.type]
- type SBigIntArray = SCollection[SBigInt.type]
- type SGroupElementArray = SCollection[SGroupElement.type]
- type SBoxArray = SCollection[SBox.type]
- type SAvlTreeArray = SCollection[SAvlTree.type]
-
- /** This descriptors are instantiated once here and then reused. */
- val SBooleanArray = SCollection(SBoolean)
- val SByteArray = SCollection(SByte)
- val SByteArray2 = SCollection(SCollection(SByte))
- val SShortArray = SCollection(SShort)
- val SIntArray = SCollection(SInt)
- val SLongArray = SCollection(SLong)
- val SBigIntArray = SCollection(SBigInt)
- val SGroupElementArray = SCollection(SGroupElement)
- val SSigmaPropArray = SCollection(SSigmaProp)
- val SBoxArray = SCollection(SBox)
- val SAvlTreeArray = SCollection(SAvlTree)
- val SHeaderArray = SCollection(SHeader)
-}
-
-/** Type descriptor of tuple type. */
-case class STuple(items: IndexedSeq[SType]) extends SCollection[SAny.type] {
- import STuple._
- override val typeCode = STuple.TupleTypeCode
-
- /** Lazily computed value representing true | false | none.
- * 0 - none, 1 - false, 2 - true
- */
- @volatile
- private var _isConstantSizeCode: Byte = 0.toByte
-
- override def elemType: SAny.type = SAny
-
- protected override def getMethods() = {
- val tupleMethods = Array.tabulate(items.size) { i =>
- SMethod(
- STuple, componentNameByIndex(i), SFunc(this, items(i)),
- (i + 1).toByte, SelectField.costKind)
- }
- colMethods ++ tupleMethods
- }
-
- override val typeParams = Nil
-
- override def toTermString = s"(${items.map(_.toTermString).mkString(",")})"
- override def toString = s"(${items.mkString(",")})"
-}
-
-object STuple extends STypeCompanion {
- /** Code of `(_, T) for some embeddable T` type constructor. */
- val Pair1TypeConstrId = 5
- /** Type code for `(E, T) for some embeddable T` type used in TypeSerializer. */
- val Pair1TypeCode: TypeCode = ((SPrimType.MaxPrimTypeCode + 1) * Pair1TypeConstrId).toByte
-
- /** Code of `(T, _) for some embeddable T` type constructor. */
- val Pair2TypeConstrId = 6
- /** Type code for `(T, E) for some embeddable T` type used in TypeSerializer. */
- val Pair2TypeCode: TypeCode = ((SPrimType.MaxPrimTypeCode + 1) * Pair2TypeConstrId).toByte
- val TripleTypeCode: TypeCode = Pair2TypeCode
-
- /** Type constructor code of symmetric pair `(T, T)` for some embeddable T. */
- val PairSymmetricTypeConstrId = 7
- /** Type code of symmetric pair `(T, T)` for some embeddable T. */
- val PairSymmetricTypeCode: TypeCode = ((SPrimType.MaxPrimTypeCode + 1) * PairSymmetricTypeConstrId).toByte
- val QuadrupleTypeCode: TypeCode = PairSymmetricTypeCode
-
- /** Type code of generic tuple type. */
- val TupleTypeCode = ((SPrimType.MaxPrimTypeCode + 1) * 8).toByte
-
- override def typeId = TupleTypeCode
-
- override val reprClass: RClass[_] = RClass(classOf[Product2[_,_]])
-
- /** A list of Coll methods inherited from Coll type and available as method of tuple. */
- lazy val colMethods: Seq[SMethod] = {
- val subst = Map(SType.tIV -> SAny)
- // TODO: implement other methods
- val activeMethods = Set(1.toByte /*Coll.size*/, 10.toByte /*Coll.apply*/)
- SCollection.methods.filter(m => activeMethods.contains(m.methodId)).map { m =>
- m.copy(stype = Terms.applySubst(m.stype, subst).asFunc)
- }
- }
-
- override def methods: Seq[SMethod] = sys.error(s"Shouldn't be called.")
-
- /** Helper factory method. */
- def apply(items: SType*): STuple = STuple(items.toArray)
-
- private val MaxTupleLength: Int = SigmaConstants.MaxTupleLength.value
- private val componentNames = Array.tabulate(MaxTupleLength){ i => s"_${i + 1}" }
-
- /** Returns method name for the tuple component accessor (i.e. `_1`, `_2`, etc.) */
- def componentNameByIndex(i: Int): String =
- try componentNames(i)
- catch {
- case e: IndexOutOfBoundsException =>
- throw new IllegalArgumentException(
- s"Tuple component '_${i+1}' is not defined: valid range (1 .. $MaxTupleLength)", e)
- }
-}
-
-/** Helper constuctor/extractor for tuples of two types. */
-object SPair {
- def apply(l: SType, r: SType) = STuple(Array(l, r))
- def unapply(t: STuple): Nullable[(SType, SType)] = t match {
- case STuple(IndexedSeq(l, r)) => Nullable((l, r))
- case _ => Nullable.None
- }
-}
-
-/** Type descriptor of lambda types. */
-case class SFunc(tDom: IndexedSeq[SType], tRange: SType, tpeParams: Seq[STypeParam] = Nil)
- extends SType with SGenericType
-{
- override type WrappedType = Any => tRange.WrappedType
- override val typeCode = SFunc.FuncTypeCode
- override def toString = {
- val args = if (tpeParams.isEmpty) "" else tpeParams.mkString("[", ",", "]")
- s"$args(${tDom.mkString(",")}) => $tRange"
- }
- override def toTermString = {
- val args = if (tpeParams.isEmpty) "" else tpeParams.mkString("[", ",", "]")
- s"$args(${tDom.map(_.toTermString).mkString(",")}) => ${tRange.toTermString}"
- }
- import SFunc._
- override val typeParams: Seq[STypeParam] = tpeParams
-
- /** Generalize this type and return a new descriptor. */
- def getGenericType: SFunc = {
- val typeParams: Seq[STypeParam] = tDom.zipWithIndex
- .map { case (_, i) => STypeParam(SType.tD.name + (i + 1)) } :+ STypeParam(SType.tR.name)
- val ts = typeParams.map(_.ident)
- SFunc(ts.init.toIndexedSeq, ts.last, Nil)
- }
-
- /** Transform function into method type by adding the given `objType` as the first
- * argument type (aka method receiver type).
- */
- def withReceiverType(objType: SType) = this.copy(tDom = objType +: tDom)
-}
-
-object SFunc {
- final val FuncTypeCode: TypeCode = OpCodes.FirstFuncType
- def apply(tDom: SType, tRange: SType): SFunc = SFunc(Array(tDom), tRange) // HOTSPOT:
- val identity = { x: Any => x }
-}
-
-/** Used by ErgoScript compiler IR and eliminated during compilation.
- * It is not used in ErgoTree.
- */
-case class STypeApply(name: String, args: IndexedSeq[SType] = IndexedSeq()) extends SType {
- override type WrappedType = Any
- override val typeCode = STypeApply.TypeCode
-}
-object STypeApply {
- val TypeCode = 94: Byte
-}
-
-/** Type variable which is used in generic method/func signatures.
- * Used by ErgoScript compiler IR and eliminated during compilation.
- * It is not used in ErgoTree.
- */
-case class STypeVar(name: String) extends SType {
- require(name.length <= 255, "name is too long")
- override type WrappedType = Any
- override val typeCode = STypeVar.TypeCode
- override def toString = name
- override def toTermString: String = name
-}
-object STypeVar {
- val TypeCode: TypeCode = 103: Byte
- implicit def liftString(n: String): STypeVar = STypeVar(n)
-
- /** Immutable empty array, can be used to avoid repeated allocations. */
- val EmptyArray = Array.empty[STypeVar]
-
- /** Immutable empty IndexedSeq, can be used to avoid repeated allocations. */
- val EmptySeq: IndexedSeq[STypeVar] = EmptyArray
-}
-
-/** Type descriptor of `Box` type of ErgoTree. */
-case object SBox extends SProduct with SPredefType with SMonoType {
- import ErgoBox._
- override type WrappedType = Box
- override val typeCode: TypeCode = 99: Byte
- override val reprClass: RClass[_] = RClass(classOf[Box])
- override def typeId = typeCode
-
- import SType.{tT, paramT}
-
- /** Defined once here and then reused in SMethod descriptors. */
- lazy val GetRegFuncType = SFunc(Array(SBox), SOption(tT), Array(paramT))
-
- /** Creates a descriptor for the given register method. (i.e. R1, R2, etc) */
- def registers(idOfs: Int): Seq[SMethod] = {
- allRegisters.map { i =>
- i match {
- case r: MandatoryRegisterId =>
- SMethod(this, s"R${i.asIndex}",
- GetRegFuncType, (idOfs + i.asIndex + 1).toByte, ExtractRegisterAs.costKind)
- .withInfo(ExtractRegisterAs, r.purpose)
- case _ =>
- SMethod(this, s"R${i.asIndex}",
- GetRegFuncType, (idOfs + i.asIndex + 1).toByte, ExtractRegisterAs.costKind)
- .withInfo(ExtractRegisterAs, "Non-mandatory register")
- }
- }
- }
-
- val PropositionBytes = "propositionBytes"
- val Value = "value"
- val Id = "id"
- val Bytes = "bytes"
- val BytesWithoutRef = "bytesWithoutRef"
- val CreationInfo = "creationInfo"
- val GetReg = "getReg"
-
- // should be lazy, otherwise lead to initialization error
- lazy val ValueMethod = SMethod(
- this, Value, SFunc(SBox, SLong), 1, ExtractAmount.costKind)
- .withInfo(ExtractAmount,
- "Mandatory: Monetary value, in Ergo tokens (NanoErg unit of measure)")
-
- lazy val PropositionBytesMethod = SMethod(
- this, PropositionBytes, SFunc(SBox, SByteArray), 2, ExtractScriptBytes.costKind)
- .withInfo(ExtractScriptBytes,
- "Serialized bytes of guarding script, which should be evaluated to true in order to\n" +
- " open this box. (aka spend it in a transaction)")
-
- lazy val BytesMethod = SMethod(
- this, Bytes, SFunc(SBox, SByteArray), 3, ExtractBytes.costKind)
- .withInfo(ExtractBytes, "Serialized bytes of this box's content, including proposition bytes.")
-
- lazy val BytesWithoutRefMethod = SMethod(
- this, BytesWithoutRef, SFunc(SBox, SByteArray), 4, ExtractBytesWithNoRef.costKind)
- .withInfo(ExtractBytesWithNoRef,
- "Serialized bytes of this box's content, excluding transactionId and index of output.")
-
- lazy val IdMethod = SMethod(this, Id, SFunc(SBox, SByteArray), 5, ExtractId.costKind)
- .withInfo(ExtractId,
- "Blake2b256 hash of this box's content, basically equals to \\lst{blake2b256(bytes)}")
-
- lazy val creationInfoMethod = SMethod(
- this, CreationInfo, ExtractCreationInfo.OpType, 6, ExtractCreationInfo.costKind)
- .withInfo(ExtractCreationInfo,
- """ If \lst{tx} is a transaction which generated this box, then \lst{creationInfo._1}
- | is a height of the tx's block. The \lst{creationInfo._2} is a serialized transaction
- | identifier followed by box index in the transaction outputs.
- """.stripMargin ) // see ExtractCreationInfo
-
- lazy val getRegMethod = SMethod(this, "getReg",
- SFunc(Array(SBox, SInt), SOption(tT), Array(paramT)), 7, ExtractRegisterAs.costKind)
- .withInfo(ExtractRegisterAs,
- """ Extracts register by id and type.
- | Type param \lst{T} expected type of the register.
- | Returns \lst{Some(value)} if the register is defined and has given type and \lst{None} otherwise
- """.stripMargin,
- ArgInfo("regId", "zero-based identifier of the register."))
-
- lazy val tokensMethod = SMethod(
- this, "tokens", SFunc(SBox, ErgoBox.STokensRegType), 8, FixedCost(JitCost(15)))
- .withIRInfo(MethodCallIrBuilder)
- .withInfo(PropertyCall, "Secondary tokens")
-
-
- // should be lazy to solve recursive initialization
- protected override def getMethods() = super.getMethods() ++ Array(
- ValueMethod, // see ExtractAmount
- PropositionBytesMethod, // see ExtractScriptBytes
- BytesMethod, // see ExtractBytes
- BytesWithoutRefMethod, // see ExtractBytesWithNoRef
- IdMethod, // see ExtractId
- creationInfoMethod,
- getRegMethod,
- tokensMethod
- ) ++ registers(8)
-}
-
-/** Type descriptor of `AvlTree` type of ErgoTree. */
-case object SAvlTree extends SProduct with SPredefType with SMonoType {
- override type WrappedType = AvlTree
- override val typeCode: TypeCode = 100: Byte
- override val reprClass: RClass[_] = RClass(classOf[AvlTree])
- override def typeId = typeCode
-
- import SOption._
- lazy val TCollOptionCollByte = SCollection(SByteArrayOption)
- lazy val CollKeyValue = SCollection(STuple(SByteArray, SByteArray))
-
- type KeyValueColl = Coll[(Coll[Byte], Coll[Byte])]
-
- lazy val digestMethod = SMethod(this, "digest", SFunc(this, SByteArray), 1, FixedCost(JitCost(15)))
- .withIRInfo(MethodCallIrBuilder)
- .withInfo(PropertyCall,
- """Returns digest of the state represented by this tree.
- | Authenticated tree \lst{digest} = \lst{root hash bytes} ++ \lst{tree height}
- """.stripMargin)
-
- /** Cost descriptor of `digest` method. */
- lazy val digest_Info = {
- val m = digestMethod
- OperationCostInfo(m.costKind.asInstanceOf[FixedCost], m.opDesc)
- }
-
- lazy val enabledOperationsMethod = SMethod(
- this, "enabledOperations", SFunc(this, SByte), 2, FixedCost(JitCost(15)))
- .withIRInfo(MethodCallIrBuilder)
- .withInfo(PropertyCall,
- """ Flags of enabled operations packed in single byte.
- | \lst{isInsertAllowed == (enabledOperations & 0x01) != 0}\newline
- | \lst{isUpdateAllowed == (enabledOperations & 0x02) != 0}\newline
- | \lst{isRemoveAllowed == (enabledOperations & 0x04) != 0}
- """.stripMargin)
-
- lazy val keyLengthMethod = SMethod(
- this, "keyLength", SFunc(this, SInt), 3, FixedCost(JitCost(15)))
- .withIRInfo(MethodCallIrBuilder)
- .withInfo(PropertyCall,
- """
- |
- """.stripMargin)
-
- lazy val valueLengthOptMethod = SMethod(
- this, "valueLengthOpt", SFunc(this, SIntOption), 4, FixedCost(JitCost(15)))
- .withIRInfo(MethodCallIrBuilder)
- .withInfo(PropertyCall,
- """
- |
- """.stripMargin)
-
- lazy val isInsertAllowedMethod = SMethod(
- this, "isInsertAllowed", SFunc(this, SBoolean), 5, FixedCost(JitCost(15)))
- .withIRInfo(MethodCallIrBuilder)
- .withInfo(PropertyCall,
- """
- |
- """.stripMargin)
-
- lazy val isInsertAllowed_Info = {
- val m = isInsertAllowedMethod
- OperationCostInfo(m.costKind.asInstanceOf[FixedCost], m.opDesc)
- }
-
- lazy val isUpdateAllowedMethod = SMethod(
- this, "isUpdateAllowed", SFunc(this, SBoolean), 6, FixedCost(JitCost(15)))
- .withIRInfo(MethodCallIrBuilder)
- .withInfo(PropertyCall,
- """
- |
- """.stripMargin)
-
- lazy val isUpdateAllowed_Info = {
- val m = isUpdateAllowedMethod
- OperationCostInfo(m.costKind.asInstanceOf[FixedCost], m.opDesc)
- }
-
- lazy val isRemoveAllowedMethod = SMethod(
- this, "isRemoveAllowed", SFunc(this, SBoolean), 7, FixedCost(JitCost(15)))
- .withIRInfo(MethodCallIrBuilder)
- .withInfo(PropertyCall,
- """
- |
- """.stripMargin)
-
- lazy val isRemoveAllowed_Info = {
- val m = isRemoveAllowedMethod
- OperationCostInfo(m.costKind.asInstanceOf[FixedCost], m.opDesc)
- }
-
- lazy val updateOperationsMethod = SMethod(this, "updateOperations",
- SFunc(Array(SAvlTree, SByte), SAvlTree), 8, FixedCost(JitCost(45)))
- .withIRInfo(MethodCallIrBuilder)
- .withInfo(MethodCall,
- """
- |
- """.stripMargin)
-
- lazy val containsMethod = SMethod(this, "contains",
- SFunc(Array(SAvlTree, SByteArray, SByteArray), SBoolean), 9, DynamicCost)
- .withIRInfo(MethodCallIrBuilder)
- .withInfo(MethodCall,
- """
- | /** Checks if an entry with key `key` exists in this tree using proof `proof`.
- | * Throws exception if proof is incorrect
- |
- | * @note CAUTION! Does not support multiple keys check, use [[getMany]] instead.
- | * Return `true` if a leaf with the key `key` exists
- | * Return `false` if leaf with provided key does not exist.
- | * @param key a key of an element of this authenticated dictionary.
- | * @param proof
- | */
- |
- """.stripMargin)
-
- /** The proof may contain keys, labels and values, we don't know for sure how many,
- * but we assume the cost is O(proof.length).
- * So the following is an approximation of the proof parsing cost.
- */
- final val CreateAvlVerifier_Info = OperationCostInfo(
- PerItemCost(baseCost = JitCost(110), perChunkCost = JitCost(20), chunkSize = 64),
- NamedDesc("CreateAvlVerifier"))
-
- final val LookupAvlTree_Info = OperationCostInfo(
- PerItemCost(baseCost = JitCost(40), perChunkCost = JitCost(10), chunkSize = 1),
- NamedDesc("LookupAvlTree"))
-
- final val InsertIntoAvlTree_Info = OperationCostInfo(
- PerItemCost(baseCost = JitCost(40), perChunkCost = JitCost(10), chunkSize = 1),
- NamedDesc("InsertIntoAvlTree"))
-
- final val UpdateAvlTree_Info = OperationCostInfo(
- PerItemCost(baseCost = JitCost(120), perChunkCost = JitCost(20), chunkSize = 1),
- NamedDesc("UpdateAvlTree"))
-
- final val RemoveAvlTree_Info = OperationCostInfo(
- PerItemCost(baseCost = JitCost(100), perChunkCost = JitCost(15), chunkSize = 1),
- NamedDesc("RemoveAvlTree"))
-
- /** Creates [[AvlTreeVerifier]] for the given tree and proof. */
- def createVerifier(tree: AvlTree, proof: Coll[Byte])(implicit E: ErgoTreeEvaluator) = {
- // the cost of tree reconstruction from proof is O(proof.length)
- E.addSeqCost(CreateAvlVerifier_Info, proof.length) { () =>
- AvlTreeVerifier(tree, proof)
- }
- }
-
- /** Implements evaluation of AvlTree.contains method call ErgoTree node.
- * Called via reflection based on naming convention.
- * @see SMethod.evalMethod
- */
- def contains_eval(mc: MethodCall, tree: AvlTree, key: Coll[Byte], proof: Coll[Byte])
- (implicit E: ErgoTreeEvaluator): Boolean = {
- val bv = createVerifier(tree, proof)
- val nItems = bv.treeHeight
-
- var res = false
- // the cost of tree lookup is O(bv.treeHeight)
- E.addSeqCost(LookupAvlTree_Info, nItems) { () =>
- res = bv.performOneOperation(Lookup(ADKey @@ key.toArray)) match {
- case Success(r) => r match {
- case Some(_) => true
- case _ => false
- }
- case Failure(_) => false
- }
- }
- res
- }
-
- lazy val getMethod = SMethod(this, "get",
- SFunc(Array(SAvlTree, SByteArray, SByteArray), SByteArrayOption), 10, DynamicCost)
- .withIRInfo(MethodCallIrBuilder)
- .withInfo(MethodCall,
- """
- | /** Perform a lookup of key `key` in this tree using proof `proof`.
- | * Throws exception if proof is incorrect
- | *
- | * @note CAUTION! Does not support multiple keys check, use [[getMany]] instead.
- | * Return Some(bytes) of leaf with key `key` if it exists
- | * Return None if leaf with provided key does not exist.
- | * @param key a key of an element of this authenticated dictionary.
- | * @param proof
- | */
- |
- """.stripMargin)
-
- /** Implements evaluation of AvlTree.get method call ErgoTree node.
- * Called via reflection based on naming convention.
- * @see SMethod.evalMethod
- */
- def get_eval(mc: MethodCall, tree: AvlTree, key: Coll[Byte], proof: Coll[Byte])
- (implicit E: ErgoTreeEvaluator): Option[Coll[Byte]] = {
- val bv = createVerifier(tree, proof)
- val nItems = bv.treeHeight
-
- // the cost of tree lookup is O(bv.treeHeight)
- E.addSeqCost(LookupAvlTree_Info, nItems) { () =>
- bv.performOneOperation(Lookup(ADKey @@ key.toArray)) match {
- case Success(r) => r match {
- case Some(v) => Some(Colls.fromArray(v))
- case _ => None
- }
- case Failure(_) => Interpreter.error(s"Tree proof is incorrect $tree")
- }
- }
- }
-
- lazy val getManyMethod = SMethod(this, "getMany",
- SFunc(Array(SAvlTree, SByteArray2, SByteArray), TCollOptionCollByte), 11, DynamicCost)
- .withIRInfo(MethodCallIrBuilder)
- .withInfo(MethodCall,
- """
- | /** Perform a lookup of many keys `keys` in this tree using proof `proof`.
- | *
- | * @note CAUTION! Keys must be ordered the same way they were in lookup before proof was generated.
- | * For each key return Some(bytes) of leaf if it exists and None if is doesn't.
- | * @param keys keys of elements of this authenticated dictionary.
- | * @param proof
- | */
- |
- """.stripMargin)
-
- /** Implements evaluation of AvlTree.getMany method call ErgoTree node.
- * Called via reflection based on naming convention.
- * @see SMethod.evalMethod
- */
- def getMany_eval(mc: MethodCall, tree: AvlTree, keys: Coll[Coll[Byte]], proof: Coll[Byte])
- (implicit E: ErgoTreeEvaluator): Coll[Option[Coll[Byte]]] = {
- val bv = createVerifier(tree, proof)
- val nItems = bv.treeHeight
- keys.map { key =>
- // the cost of tree lookup is O(bv.treeHeight)
- E.addSeqCost(LookupAvlTree_Info, nItems) { () =>
- bv.performOneOperation(Lookup(ADKey @@ key.toArray)) match {
- case Success(r) => r match {
- case Some(v) => Some(Colls.fromArray(v))
- case _ => None
- }
- case Failure(_) => Interpreter.error(s"Tree proof is incorrect $tree")
- }
- }
- }
- }
-
- lazy val insertMethod = SMethod(this, "insert",
- SFunc(Array(SAvlTree, CollKeyValue, SByteArray), SAvlTreeOption), 12, DynamicCost)
- .withIRInfo(MethodCallIrBuilder)
- .withInfo(MethodCall,
- """
- | /** Perform insertions of key-value entries into this tree using proof `proof`.
- | * Throws exception if proof is incorrect
- | *
- | * @note CAUTION! Pairs must be ordered the same way they were in insert ops before proof was generated.
- | * Return Some(newTree) if successful
- | * Return None if operations were not performed.
- | * @param operations collection of key-value pairs to insert in this authenticated dictionary.
- | * @param proof
- | */
- |
- """.stripMargin)
-
- /** Implements evaluation of AvlTree.insert method call ErgoTree node.
- * Called via reflection based on naming convention.
- * @see SMethod.evalMethod
- */
- def insert_eval(mc: MethodCall, tree: AvlTree, entries: KeyValueColl, proof: Coll[Byte])
- (implicit E: ErgoTreeEvaluator): Option[AvlTree] = {
- E.addCost(isInsertAllowed_Info)
- if (!tree.isInsertAllowed) {
- None
- } else {
- val bv = createVerifier(tree, proof)
- // when the tree is empty we still need to add the insert cost
- val nItems = Math.max(bv.treeHeight, 1)
-
- entries.forall { case (key, value) =>
- var res = true
- // the cost of tree lookup is O(bv.treeHeight)
- E.addSeqCost(InsertIntoAvlTree_Info, nItems) { () =>
- val insert = Insert(ADKey @@ key.toArray, ADValue @@ value.toArray)
- val insertRes = bv.performOneOperation(insert)
- // TODO v6.0: throwing exception is not consistent with update semantics
- // however it preserves v4.0 semantics (see https://github.com/ScorexFoundation/sigmastate-interpreter/issues/908)
- if (insertRes.isFailure) {
- Interpreter.error(s"Incorrect insert for $tree (key: $key, value: $value, digest: ${tree.digest}): ${insertRes.failed.get}}")
- }
- res = insertRes.isSuccess
- }
- res
- }
- bv.digest match {
- case Some(d) =>
- E.addCost(updateDigest_Info)
- Some(tree.updateDigest(Colls.fromArray(d)))
- case _ => None
- }
- }
- }
-
- lazy val updateMethod = SMethod(this, "update",
- SFunc(Array(SAvlTree, CollKeyValue, SByteArray), SAvlTreeOption), 13, DynamicCost)
- .withIRInfo(MethodCallIrBuilder)
- .withInfo(MethodCall,
- """
- | /** Perform updates of key-value entries into this tree using proof `proof`.
- | * Throws exception if proof is incorrect
- | *
- | * @note CAUTION! Pairs must be ordered the same way they were in update ops before proof was generated.
- | * Return Some(newTree) if successful
- | * Return None if operations were not performed.
- | * @param operations collection of key-value pairs to update in this authenticated dictionary.
- | * @param proof
- | */
- |
- """.stripMargin)
-
- /** Implements evaluation of AvlTree.update method call ErgoTree node.
- * Called via reflection based on naming convention.
- * @see SMethod.evalMethod
- */
- def update_eval(mc: MethodCall, tree: AvlTree,
- operations: KeyValueColl, proof: Coll[Byte])
- (implicit E: ErgoTreeEvaluator): Option[AvlTree] = {
- E.addCost(isUpdateAllowed_Info)
- if (!tree.isUpdateAllowed) {
- None
- } else {
- val bv = createVerifier(tree, proof)
- // when the tree is empty we still need to add the insert cost
- val nItems = Math.max(bv.treeHeight, 1)
-
- // here we use forall as looping with fast break on first failed tree oparation
- operations.forall { case (key, value) =>
- var res = true
- // the cost of tree update is O(bv.treeHeight)
- E.addSeqCost(UpdateAvlTree_Info, nItems) { () =>
- val op = Update(ADKey @@ key.toArray, ADValue @@ value.toArray)
- val updateRes = bv.performOneOperation(op)
- res = updateRes.isSuccess
- }
- res
- }
- bv.digest match {
- case Some(d) =>
- E.addCost(updateDigest_Info)
- Some(tree.updateDigest(Colls.fromArray(d)))
- case _ => None
- }
- }
- }
-
- lazy val removeMethod = SMethod(this, "remove",
- SFunc(Array(SAvlTree, SByteArray2, SByteArray), SAvlTreeOption), 14, DynamicCost)
- .withIRInfo(MethodCallIrBuilder)
- .withInfo(MethodCall,
- """
- | /** Perform removal of entries into this tree using proof `proof`.
- | * Throws exception if proof is incorrect
- | * Return Some(newTree) if successful
- | * Return None if operations were not performed.
- | *
- | * @note CAUTION! Keys must be ordered the same way they were in remove ops before proof was generated.
- | * @param operations collection of keys to remove from this authenticated dictionary.
- | * @param proof
- | */
- |
- """.stripMargin)
-
- /** Implements evaluation of AvlTree.remove method call ErgoTree node.
- * Called via reflection based on naming convention.
- * @see SMethod.evalMethod
- */
- def remove_eval(mc: MethodCall, tree: AvlTree,
- operations: Coll[Coll[Byte]], proof: Coll[Byte])
- (implicit E: ErgoTreeEvaluator): Option[AvlTree] = {
- E.addCost(isRemoveAllowed_Info)
- if (!tree.isRemoveAllowed) {
- None
- } else {
- val bv = createVerifier(tree, proof)
- // when the tree is empty we still need to add the insert cost
- val nItems = Math.max(bv.treeHeight, 1)
-
- cfor(0)(_ < operations.length, _ + 1) { i =>
- E.addSeqCost(RemoveAvlTree_Info, nItems) { () =>
- val key = operations(i).toArray
- bv.performOneOperation(Remove(ADKey @@ key))
- }
- }
-
- E.addCost(digest_Info)
- bv.digest match {
- case Some(d) =>
- E.addCost(updateDigest_Info)
- Some(tree.updateDigest(Colls.fromArray(d)))
- case _ => None
- }
- }
- }
-
- lazy val updateDigestMethod = SMethod(this, "updateDigest",
- SFunc(Array(SAvlTree, SByteArray), SAvlTree), 15, FixedCost(JitCost(40)))
- .withIRInfo(MethodCallIrBuilder)
- .withInfo(MethodCall,
- """
- |
- """.stripMargin)
-
- lazy val updateDigest_Info = {
- val m = updateDigestMethod
- OperationCostInfo(m.costKind.asInstanceOf[FixedCost], m.opDesc)
- }
-
- protected override def getMethods(): Seq[SMethod] = super.getMethods() ++ Seq(
- digestMethod,
- enabledOperationsMethod,
- keyLengthMethod,
- valueLengthOptMethod,
- isInsertAllowedMethod,
- isUpdateAllowedMethod,
- isRemoveAllowedMethod,
- updateOperationsMethod,
- containsMethod,
- getMethod,
- getManyMethod,
- insertMethod,
- updateMethod,
- removeMethod,
- updateDigestMethod
- )
-}
-
-/** Type descriptor of `Context` type of ErgoTree. */
-case object SContext extends SProduct with SPredefType with SMonoType {
- override type WrappedType = Context
- override val typeCode: TypeCode = 101: Byte
- override def reprClass: RClass[_] = RClass(classOf[Context])
- override def typeId = typeCode
-
- /** Arguments on context operation such as getVar, DeserializeContext etc.
- * This value can be reused where necessary to avoid allocations. */
- val ContextFuncDom: IndexedSeq[SType] = Array(SContext, SByte)
-
- import SType.{tT, paramT}
-
- lazy val dataInputsMethod = propertyCall("dataInputs", SBoxArray, 1, FixedCost(JitCost(15)))
- lazy val headersMethod = propertyCall("headers", SHeaderArray, 2, FixedCost(JitCost(15)))
- lazy val preHeaderMethod = propertyCall("preHeader", SPreHeader, 3, FixedCost(JitCost(15)))
- lazy val inputsMethod = property("INPUTS", SBoxArray, 4, Inputs)
- lazy val outputsMethod = property("OUTPUTS", SBoxArray, 5, Outputs)
- lazy val heightMethod = property("HEIGHT", SInt, 6, Height)
- lazy val selfMethod = property("SELF", SBox, 7, Self)
- lazy val selfBoxIndexMethod = propertyCall("selfBoxIndex", SInt, 8, FixedCost(JitCost(20)))
- lazy val lastBlockUtxoRootHashMethod = property("LastBlockUtxoRootHash", SAvlTree, 9, LastBlockUtxoRootHash)
- lazy val minerPubKeyMethod = property("minerPubKey", SByteArray, 10, MinerPubkey)
- lazy val getVarMethod = SMethod(
- this, "getVar", SFunc(ContextFuncDom, SOption(tT), Array(paramT)), 11, GetVar.costKind)
- .withInfo(GetVar, "Get context variable with given \\lst{varId} and type.",
- ArgInfo("varId", "\\lst{Byte} identifier of context variable"))
-
- protected override def getMethods() = super.getMethods() ++ Seq(
- dataInputsMethod, headersMethod, preHeaderMethod, inputsMethod, outputsMethod, heightMethod, selfMethod,
- selfBoxIndexMethod, lastBlockUtxoRootHashMethod, minerPubKeyMethod, getVarMethod
- )
-}
-
-/** Type descriptor of `Header` type of ErgoTree. */
-case object SHeader extends SProduct with SPredefType with SMonoType {
- override type WrappedType = Header
- override val typeCode: TypeCode = 104: Byte
- override val reprClass: RClass[_] = RClass(classOf[Header])
- override def typeId = typeCode
-
- lazy val idMethod = propertyCall("id", SByteArray, 1, FixedCost(JitCost(10)))
- lazy val versionMethod = propertyCall("version", SByte, 2, FixedCost(JitCost(10)))
- lazy val parentIdMethod = propertyCall("parentId", SByteArray, 3, FixedCost(JitCost(10)))
- lazy val ADProofsRootMethod = propertyCall("ADProofsRoot", SByteArray, 4, FixedCost(JitCost(10)))
- lazy val stateRootMethod = propertyCall("stateRoot", SAvlTree, 5, FixedCost(JitCost(10)))
- lazy val transactionsRootMethod = propertyCall("transactionsRoot", SByteArray, 6, FixedCost(JitCost(10)))
- lazy val timestampMethod = propertyCall("timestamp", SLong, 7, FixedCost(JitCost(10)))
- lazy val nBitsMethod = propertyCall("nBits", SLong, 8, FixedCost(JitCost(10)))
- lazy val heightMethod = propertyCall("height", SInt, 9, FixedCost(JitCost(10)))
- lazy val extensionRootMethod = propertyCall("extensionRoot", SByteArray, 10, FixedCost(JitCost(10)))
- lazy val minerPkMethod = propertyCall("minerPk", SGroupElement, 11, FixedCost(JitCost(10)))
- lazy val powOnetimePkMethod = propertyCall("powOnetimePk", SGroupElement, 12, FixedCost(JitCost(10)))
- lazy val powNonceMethod = propertyCall("powNonce", SByteArray, 13, FixedCost(JitCost(10)))
- lazy val powDistanceMethod = propertyCall("powDistance", SBigInt, 14, FixedCost(JitCost(10)))
- lazy val votesMethod = propertyCall("votes", SByteArray, 15, FixedCost(JitCost(10)))
-
- protected override def getMethods() = super.getMethods() ++ Seq(
- idMethod, versionMethod, parentIdMethod, ADProofsRootMethod, stateRootMethod, transactionsRootMethod,
- timestampMethod, nBitsMethod, heightMethod, extensionRootMethod, minerPkMethod, powOnetimePkMethod,
- powNonceMethod, powDistanceMethod, votesMethod
- )
-}
-
-/** Type descriptor of `PreHeader` type of ErgoTree. */
-case object SPreHeader extends SProduct with SPredefType with SMonoType {
- override type WrappedType = PreHeader
- override val typeCode: TypeCode = 105: Byte
- override val reprClass: RClass[_] = RClass(classOf[PreHeader])
- override def typeId = typeCode
-
- lazy val versionMethod = propertyCall("version", SByte, 1, FixedCost(JitCost(10)))
- lazy val parentIdMethod = propertyCall("parentId", SByteArray, 2, FixedCost(JitCost(10)))
- lazy val timestampMethod = propertyCall("timestamp", SLong, 3, FixedCost(JitCost(10)))
- lazy val nBitsMethod = propertyCall("nBits", SLong, 4, FixedCost(JitCost(10)))
- lazy val heightMethod = propertyCall("height", SInt, 5, FixedCost(JitCost(10)))
- lazy val minerPkMethod = propertyCall("minerPk", SGroupElement, 6, FixedCost(JitCost(10)))
- lazy val votesMethod = propertyCall("votes", SByteArray, 7, FixedCost(JitCost(10)))
-
- protected override def getMethods() = super.getMethods() ++ Seq(
- versionMethod, parentIdMethod, timestampMethod, nBitsMethod, heightMethod, minerPkMethod, votesMethod
- )
-}
-
-/** This type is introduced to unify handling of global and non-global (i.e. methods) operations.
- * It unifies implementation of global operation with implementation of methods and avoids code
- * duplication (following DRY principle https://en.wikipedia.org/wiki/Don%27t_repeat_yourself).
- * The WrappedType is `sigma.SigmaDslBuilder`, which is an interface implemented by
- * the singleton sigmastate.eval.CostingSigmaDslBuilder
- *
- * The Constant(...) tree node of this type are not allowed, as well as using it in register and
- * context variables (aka ContextExtension)
- *
- * When new methods are added to this type via a soft-fork, they will be serialized as part
- * of ErgoTree using MethodCallSerializer, where SGlobal.typeCode will be used.
- *
- * @see sigmastate.lang.SigmaPredef
- * */
-case object SGlobal extends SProduct with SPredefType with SMonoType {
- override type WrappedType = SigmaDslBuilder
- override val typeCode: TypeCode = 106: Byte
- override val reprClass: RClass[_] = RClass(classOf[SigmaDslBuilder])
- override def typeId = typeCode
-
- import SType.tT
-
- lazy val groupGeneratorMethod = SMethod(
- this, "groupGenerator", SFunc(this, SGroupElement), 1, GroupGenerator.costKind)
- .withIRInfo({ case (builder, obj, method, args, tparamSubst) => GroupGenerator })
- .withInfo(GroupGenerator, "")
-
- lazy val xorMethod = SMethod(
- this, "xor", SFunc(Array(this, SByteArray, SByteArray), SByteArray), 2, Xor.costKind)
- .withIRInfo({
- case (_, _, _, Seq(l, r), _) => Xor(l.asByteArray, r.asByteArray)
- })
- .withInfo(Xor, "Byte-wise XOR of two collections of bytes",
- ArgInfo("left", "left operand"), ArgInfo("right", "right operand"))
-
- /** Implements evaluation of Global.xor method call ErgoTree node.
- * Called via reflection based on naming convention.
- * @see SMethod.evalMethod, Xor.eval, Xor.xorWithCosting
- */
- def xor_eval(mc: MethodCall, G: SigmaDslBuilder, ls: Coll[Byte], rs: Coll[Byte])
- (implicit E: ErgoTreeEvaluator): Coll[Byte] = {
- Xor.xorWithCosting(ls, rs)
- }
-
- protected override def getMethods() = super.getMethods() ++ Seq(
- groupGeneratorMethod,
- xorMethod
- )
-}
-
diff --git a/interpreter/shared/src/main/scala/sigmastate/utils/Extensions.scala b/interpreter/shared/src/main/scala/sigmastate/utils/Extensions.scala
index 9490f76965..54abc40f4e 100644
--- a/interpreter/shared/src/main/scala/sigmastate/utils/Extensions.scala
+++ b/interpreter/shared/src/main/scala/sigmastate/utils/Extensions.scala
@@ -3,7 +3,8 @@ package sigmastate.utils
import org.ergoplatform.ErgoBox.TokenId
import scorex.util.{ModifierId, idToBytes}
import scorex.utils.{Ints, Longs, Shorts}
-import sigmastate.eval.{Digest32Coll, SigmaDsl}
+import sigma.data.Digest32Coll
+import sigma.eval.SigmaDsl
import sigma.{Coll, Colls}
object Extensions {
@@ -14,10 +15,6 @@ object Extensions {
*/
def toBytes: Coll[Byte] = SigmaDsl.Colls.fromItems(b)
- /** Returns a big-endian representation of this numeric in a collection of Booleans.
- * Each boolean corresponds to one bit.
- */
- def toBits: Coll[Boolean] = ???
}
implicit class ShortOpsForSigma(val x: Short) extends AnyVal {
@@ -26,11 +23,6 @@ object Extensions {
* byte array {@code {0x12, 0x13}}.
*/
def toBytes: Coll[Byte] = Colls.fromArray(Shorts.toByteArray(x))
-
- /** Returns a big-endian representation of this numeric in a collection of Booleans.
- * Each boolean corresponds to one bit.
- */
- def toBits: Coll[Boolean] = ???
}
implicit class IntOpsForSigma(val x: Int) extends AnyVal {
@@ -39,11 +31,6 @@ object Extensions {
* byte array {@code {0x12, 0x13, 0x14, 0x15}}.
*/
def toBytes: Coll[Byte] = Colls.fromArray(Ints.toByteArray(x))
-
- /** Returns a big-endian representation of this numeric in a collection of Booleans.
- * Each boolean corresponds to one bit.
- */
- def toBits: Coll[Boolean] = ???
}
implicit class LongOpsForSigma(val x: Long) extends AnyVal {
@@ -52,13 +39,6 @@ object Extensions {
* byte array {@code {0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19}}.
*/
def toBytes: Coll[Byte] = Colls.fromArray(Longs.toByteArray(x))
-
- /** Returns a big-endian representation of this numeric in a collection of Booleans.
- * Each boolean corresponds to one bit.
- *
- * @since 2.0
- */
- def toBits: Coll[Boolean] = ???
}
/** Provides extension methods for `ModifierId` instances.
diff --git a/interpreter/shared/src/main/scala/sigmastate/utils/Helpers.scala b/interpreter/shared/src/main/scala/sigmastate/utils/Helpers.scala
index e3407c57e8..53419a32b8 100644
--- a/interpreter/shared/src/main/scala/sigmastate/utils/Helpers.scala
+++ b/interpreter/shared/src/main/scala/sigmastate/utils/Helpers.scala
@@ -3,15 +3,10 @@ package sigmastate.utils
import debox.cfor
import io.circe.Decoder
import org.ergoplatform.settings.ErgoAlgos
-import sigma.data.{OverloadHack, RType}
-import scorex.utils.Ints
-import sigma.{Coll, Colls, Environment, GroupElement}
-import sigmastate.eval.{CAnyValue, SigmaDsl}
-import sigmastate.crypto.CryptoConstants.EcPointType
-
-import java.util
-import java.util.concurrent.locks.Lock
-import scala.reflect.ClassTag
+import sigma.crypto.EcPointType
+import sigma.{Coll, Colls, GroupElement}
+import sigma.eval.SigmaDsl
+
import scala.util.{Either, Failure, Right, Success, Try}
object Helpers {
@@ -58,45 +53,6 @@ object Helpers {
target
}
- /** Concatenates two arrays into a new resulting array.
- * All items of both arrays are copied to the result using System.arraycopy.
- */
- def concatArrays[T:ClassTag](arr1: Array[T], arr2: Array[T]): Array[T] = {
- val l1 = arr1.length
- val l2 = arr2.length
- val length: Int = l1 + l2
- val result: Array[T] = new Array[T](length)
- System.arraycopy(arr1, 0, result, 0, l1)
- System.arraycopy(arr2, 0, result, l1, l2)
- result
- }
-
- def castArray[A, B >: A : ClassTag](array: Array[A]): Array[B] = {
- val result: Array[B] = new Array[B](array.length)
- System.arraycopy(array, 0, result, 0, array.length)
- result
- }
-
- def deepHashCode[T](arr: Array[T]): Int = arr match {
- case arr: Array[AnyRef] => java.util.Arrays.deepHashCode(arr)
- case arr: Array[Byte] => java.util.Arrays.hashCode(arr)
- case arr: Array[Short] => java.util.Arrays.hashCode(arr)
- case arr: Array[Int] => java.util.Arrays.hashCode(arr)
- case arr: Array[Long] => java.util.Arrays.hashCode(arr)
- case arr: Array[Char] => java.util.Arrays.hashCode(arr)
- case arr: Array[Float] => java.util.Arrays.hashCode(arr)
- case arr: Array[Double] => java.util.Arrays.hashCode(arr)
- case arr: Array[Boolean] => java.util.Arrays.hashCode(arr)
- }
-
- /** Optimized hashCode for array of bytes when it represents some hash thus it have
- * enough randomness and we can use only first 4 bytes.
- * @param id result of some hash function
- */
- @inline final def safeIdHashCode(id: Array[Byte]): Int =
- if (id != null && id.length >= 4) Ints.fromBytes(id(0), id(1), id(2), id(3))
- else java.util.Arrays.hashCode(id)
-
implicit class TryOps[+A](val source: Try[A]) extends AnyVal {
def fold[B](onError: Throwable => B, onSuccess: A => B) = source match {
case Success(value) => onSuccess(value)
@@ -166,50 +122,5 @@ object Helpers {
Colls.fromArray(bytes)
}
- /**
- * Executes the given block with a reentrant mutual exclusion Lock with the same basic
- * behavior and semantics as the implicit monitor lock accessed using synchronized
- * methods and statements in Java.
- *
- * Note, using this method has an advantage of having this method in a stack trace in case of
- * an exception in the block.
- * @param l lock object which should be acquired by the current thread before block can start executing
- * @param block block of code which will be executed retaining the lock
- * @return the value produced by the block
- */
- def withReentrantLock[A](l: Lock)(block: => A): A = {
- l.lock()
- val res = try
- block
- finally {
- l.unlock()
- }
- res
- }
-
- /** Encapsulate platform-specific logic of ensuring the value carries its precise type.
- * For JVM this is identity function.
- * For JS it can transform to AnyValue, if the type is numeric
- */
- def ensureTypeCarringValue(v: Any, tT: RType[Any]): Any =
- if (Environment.current.isJVM) v
- else { // JS
- v match {
- case _: Byte | _: Short | _: Int =>
- // this is necessary for JS where Byte, Short, Int have the same runtime class
- // and hence we need to pass the type information explicitly
- CAnyValue(v)(tT, OverloadHack.overloaded1)
- case _ => v
- }
- }
}
-object Overloading {
- class Overload1
- class Overload2
- class Overload3
-
- implicit val overload1: Overload1 = new Overload1
- implicit val overload2: Overload2 = new Overload2
- implicit val overload3: Overload3 = new Overload3
-}
diff --git a/interpreter/shared/src/main/scala/sigmastate/utxo/ComplexityTable.scala b/interpreter/shared/src/main/scala/sigmastate/utxo/ComplexityTable.scala
deleted file mode 100644
index 2613426257..0000000000
--- a/interpreter/shared/src/main/scala/sigmastate/utxo/ComplexityTable.scala
+++ /dev/null
@@ -1,161 +0,0 @@
-package sigmastate.utxo
-
-import org.ergoplatform._
-import sigmastate._
-import sigmastate.Values._
-import sigmastate.lang.Terms._
-import sigmastate.serialization.OpCodes.OpCode
-
-object ComplexityTable {
-
- val MinimalComplexity = 100
-
- val OpCodeComplexity: Map[OpCode, Int] = Seq(
- Fold.opCode -> 4034, // count = 122
- MapCollection.opCode -> 2514, // count = 402
- BinAnd.opCode -> 2000, // count = 21858
- BinOr.opCode -> 2000, // count = 9894
- Exists.opCode -> 1997, // count = 4131
- Apply.opCode -> 1592, // count = 327
- Append.opCode -> 1524, // count = 63
- ForAll.opCode -> 1451, // count = 7952
- XorOf.opCode -> 1273, // count = 2
- GroupGenerator.opCode -> 1212, // count = 10
- Filter.opCode -> 849, // count = 1656
- ByteArrayToBigInt.opCode -> 727, // count = 9
- LastBlockUtxoRootHash.opCode -> 726, // count = 3
- ModQ.opCode -> 690, // count = 1
- GetVar.opCode -> 687, // count = 1150
- Xor.opCode -> 632, // count = 9
- Tuple.opCode -> 625, // count = 26
- SubstConstants.opCode -> 621, // count = 131
- CalcSha256.opCode -> 505, // count = 6
- OptionGetOrElse.opCode -> 449, // count = 108
- ConcreteCollectionBooleanConstant.opCode -> 428, // count = 3
- CalcBlake2b256.opCode -> 381, // count = 609
- FuncValue.opCode -> 352, // count = 5687
- OptionIsDefined.opCode -> 343, // count = 58
- Negation.opCode -> 328, // count = 9
- ByteArrayToLong.opCode -> 284, // count = 3
- If.opCode -> 284, // count = 3918
- AtLeast.opCode -> 281, // count = 7540
- ConcreteCollection.opCode -> 279, // count = 7956
- BinXor.opCode -> 277, // count = 19
- OR.opCode -> 274, // count = 837
- Inputs.opCode -> 274, // count = 8961
- ModQArithOp.PlusModQ.opCode -> 272, // count = 1
- ExtractCreationInfo.opCode -> 266, // count = 430
- Exponentiate.opCode -> 253, // count = 7
- OptionGet.opCode -> 238, // count = 29116
- AND.opCode -> 230, // count = 10153
- EQ.opCode -> 227, // count = 33055
- ArithOp.Min.opCode -> 227, // count = 30
- Outputs.opCode -> 215, // count = 29061
- ModQArithOp.MinusModQ.opCode -> 211, // count = 1
- LongToByteArray.opCode -> 209, // count = 15
- SelectField.opCode -> 205, // count = 1217
- ExtractRegisterAs.opCode -> 197, // count = 28059
- ArithOp.Modulo.opCode -> 186, // count = 34
- ExtractId.opCode -> 186, // count = 66
- ArithOp.Max.opCode -> 185, // count = 70
- DecodePoint.opCode -> 184, // count = 133
- SigmaOr.opCode -> 183, // count = 4666
- SigmaAnd.opCode -> 177, // count = 4467
- MultiplyGroup.opCode -> 176, // count = 3
- ByIndex.opCode -> 174, // count = 32408
- ExtractBytes.opCode -> 174, // count = 17
- Downcast.opCode -> 168, // count = 79
- CreateProveDHTuple.opCode -> 164, // count = 27
- SizeOf.opCode -> 151, // count = 4952
- Slice.opCode -> 143, // count = 580
- Self.opCode -> 117, // count = 18395
- ExtractBytesWithNoRef.opCode -> 116, // count = 1129
- MinerPubkey.opCode -> 107, // count = 131
- GT.opCode -> 101, // count = 7137
- ExtractScriptBytes.opCode -> 100, // count = 13780
- ArithOp.Plus.opCode -> 99, // count = 12850
- LE.opCode -> 96, // count = 3549
- NEQ.opCode -> 96, // count = 2079
- GE.opCode -> 95, // count = 10941
- ArithOp.Minus.opCode -> 94, // count = 18200
- ArithOp.Multiply.opCode -> 94, // count = 12955
- Upcast.opCode -> 94, // count = 15608
- SigmaPropBytes.opCode -> 94, // count = 4135
- ArithOp.Division.opCode -> 92, // count = 6809
- LT.opCode -> 87, // count = 8715
- TrueLeaf.opCode -> 86, // count = 6764
- BoolToSigmaProp.opCode -> 84, // count = 11765
- FalseLeaf.opCode -> 80, // count = 4825
- Height.opCode -> 80, // count = 30856
- Constant.opCode -> 80, // count = 251669
- SigmaPropIsProven.opCode -> 78, // count = 20566
- CreateProveDlog.opCode -> 76, // count = 147
- BlockValue.opCode -> 74, // count = 895
- ExtractAmount.opCode -> 74, // count = 14650
- LogicalNot.opCode -> 56, // count = 1420
- Global.opCode -> 7, // count = 3
- ValUse.opCode -> 3, // count = 18771
- Context.opCode -> 1 // count = 72
- ).toMap
-
- val MethodCallComplexity: Map[(Byte, Byte), Int] = Seq(
- (100.toByte, 13.toByte) -> 3911, // count = 1, AvlTree.update
- (36.toByte, 7.toByte) -> 2183, // count = 7, SOption.map
- (7.toByte, 2.toByte) -> 2107, // count = 2, GroupElement.getEncoded
- (100.toByte, 11.toByte) -> 1960, // count = 9, AvlTree.getMany
- (12.toByte, 15.toByte) -> 1853, // count = 820, SCollection.flatMap
- (36.toByte, 8.toByte) -> 1719, // count = 7, SOption.filter
- (12.toByte, 29.toByte) -> 1588, // count = 19, SCollection.zip
- (100.toByte, 12.toByte) -> 1460, // count = 8, AvlTree.insert
- (100.toByte, 4.toByte) -> 1343, // count = 5, AvlTree.valueLengthOpt
- (100.toByte, 10.toByte) -> 1331, // count = 22, AvlTree.get
- (100.toByte, 14.toByte) -> 1229, // count = 5, AvlTree.remove
- (105.toByte, 1.toByte) -> 1214, // count = 3, PreHeader.version
- (104.toByte, 1.toByte) -> 1157, // count = 3, Header.id
- (12.toByte, 21.toByte) -> 966, // count = 5, SCollection.updateMany
- (101.toByte, 1.toByte) -> 900, // count = 25, Context.dataInputs
- (100.toByte, 9.toByte) -> 809, // count = 13, AvlTree.contains
- (12.toByte, 26.toByte) -> 788, // count = 6, SCollection.indexOf
- (100.toByte, 7.toByte) -> 694, // count = 1, AvlTree.isRemoveAllowed
- (100.toByte, 5.toByte) -> 671, // count = 1, AvlTree.isInsertAllowed
- (12.toByte, 19.toByte) -> 557, // count = 5, SCollection.patch
- (101.toByte, 8.toByte) -> 510, // count = 1, Context.selfBoxIndex
- (100.toByte, 2.toByte) -> 452, // count = 3, AvlTree.enabledOperations
- (105.toByte, 7.toByte) -> 451, // count = 3, PreHeader.votes
- (105.toByte, 6.toByte) -> 447, // count = 3, PreHeader.minerPk
- (7.toByte, 5.toByte) -> 444, // count = 1, GroupElement.negate
- (104.toByte, 14.toByte) -> 412, // count = 3, Header.powDistance
- (100.toByte, 1.toByte) -> 384, // count = 6, AvlTree.digest
- (104.toByte, 13.toByte) -> 378, // count = 3, Header.powNonce
- (101.toByte, 3.toByte) -> 357, // count = 17, Context.preHeader
- (104.toByte, 7.toByte) -> 343, // count = 3, Header.timestamp
- (105.toByte, 3.toByte) -> 339, // count = 3, PreHeader.timestamp
- (104.toByte, 10.toByte) -> 335, // count = 3, Header.extensionRoot
- (12.toByte, 20.toByte) -> 329, // count = 5, SCollection.updated
- (100.toByte, 3.toByte) -> 328, // count = 5, AvlTree.keyLength
- (105.toByte, 5.toByte) -> 328, // count = 5, PreHeader.height
- (104.toByte, 9.toByte) -> 326, // count = 3, Header.height
- (105.toByte, 2.toByte) -> 323, // count = 3, PreHeader.parentId
- (105.toByte, 4.toByte) -> 319, // count = 3, PreHeader.nBits
- (104.toByte, 8.toByte) -> 317, // count = 3, Header.nBits
- (104.toByte, 2.toByte) -> 316, // count = 3, Header.version
- (101.toByte, 2.toByte) -> 315, // count = 33, Context.headers
- (104.toByte, 4.toByte) -> 313, // count = 3, Header.ADProofsRoot
- (104.toByte, 12.toByte) -> 303, // count = 3, Header.powOnetimePk
- (104.toByte, 11.toByte) -> 303, // count = 3, Header.minerPk
- (104.toByte, 15.toByte) -> 302, // count = 3, Header.votes
- (104.toByte, 3.toByte) -> 299, // count = 3, Header.parentId
- (104.toByte, 6.toByte) -> 296, // count = 3, Header.transactionsRoot
- (101.toByte, 4.toByte) -> 293, // count = 4, Context.INPUTS
- (100.toByte, 6.toByte) -> 288, // count = 6, AvlTree.isUpdateAllowed
- (104.toByte, 5.toByte) -> 284, // count = 3, Header.stateRoot
- (101.toByte, 7.toByte) -> 278, // count = 1, Context.SELF
- (101.toByte, 5.toByte) -> 276, // count = 1, Context.OUTPUTS
- (99.toByte, 8.toByte) -> 269, // count = 163, Box.tokens
- (101.toByte, 10.toByte) -> 249, // count = 2, Context.minerPubKey
- (12.toByte, 14.toByte) -> 238, // count = 1725, SCollection.indices
- (101.toByte, 9.toByte) -> 182, // count = 2, Context.LastBlockUtxoRootHash
- (106.toByte, 1.toByte) -> 169, // count = 3, SigmaDslBuilder.groupGenerator
- (101.toByte, 6.toByte) -> 146 // count = 1, Context.HEIGHT
- ).toMap
-}
diff --git a/interpreter/shared/src/main/scala/sigmastate/utxo/ComplexityTableStat.scala b/interpreter/shared/src/main/scala/sigmastate/utxo/ComplexityTableStat.scala
deleted file mode 100644
index e595fa2b6a..0000000000
--- a/interpreter/shared/src/main/scala/sigmastate/utxo/ComplexityTableStat.scala
+++ /dev/null
@@ -1,94 +0,0 @@
-package sigmastate.utxo
-
-import sigmastate.serialization.ValueSerializer.getSerializer
-import sigmastate.serialization.OpCodes.OpCode
-import sigma.util.Extensions.ByteOps
-import sigmastate.SMethod
-import sigmastate.serialization.OpCodes
-
-import scala.collection.mutable
-
-object ComplexityTableStat {
- // NOTE: this class is mutable so better to keep it private
- private class StatItem(
- /** How many times the operation has been executed */
- var count: Long,
- /** Sum of all execution times */
- var sum: Long
- )
-
- /** Timings of op codes */
- private val opStat = mutable.HashMap[OpCode, StatItem]()
-
- /** Timings of method calls */
- private val mcStat = mutable.HashMap[(Byte, Byte), StatItem]()
-
- def addOpTime(op: OpCode, time: Long) = {
- opStat.get(op) match {
- case Some(item) =>
- item.count += 1
- item.sum += time
- case None =>
- opStat(op) = new StatItem(1, time)
- }
- }
-
- def addMcTime(typeId: Byte, methodId: Byte, time: Long) = {
- mcStat.get((typeId, methodId)) match {
- case Some(item) =>
- item.count += 1
- item.sum += time
- case None =>
- mcStat((typeId, methodId)) = new StatItem(1, time)
- }
- }
-
- /** Prints the complexity table
- * */
- def complexityTableString: String = {
- val opCodeLines = opStat.map { case (opCode, item) =>
- val avgTime = item.sum / item.count
- val time = avgTime / 1000
- val ser = getSerializer(opCode)
- val opName = ser.opDesc.typeName
- (opName, (opCode.toUByte - OpCodes.LastConstantCode).toString, time, item.count.toString)
- }.toList.sortBy(_._3)(Ordering[Long].reverse)
-
- val mcLines = mcStat.map { case (id @ (typeId, methodId), item) =>
- val avgTime = item.sum / item.count
- val time = avgTime / 1000
- val m = SMethod.fromIds(typeId, methodId)
- val typeName = m.objType.typeName
- (s"$typeName.${m.name}", typeId, methodId, time, item.count.toString)
- }.toList.sortBy(r => (r._2,r._3))(Ordering[(Byte,Byte)].reverse)
-
-// val lines = (("Op", "OpCode", "Avg Time,us", "Count") :: opCodeLines ::: mcLines)
-// .map { case (opName, opCode, time, count) =>
-// s"${opName.padTo(30, ' ')}\t${opCode.padTo(7, ' ')}\t${time.padTo(9, ' ')}\t${count}"
-// }
-// .mkString("\n")
-
- val rows = (opCodeLines)
- .map { case (opName, opCode, time, count) =>
- val key = s"$opName.opCode".padTo(30, ' ')
- s"$key -> $time, // count = $count "
- }
- .mkString("\n")
-
- val mcRows = (mcLines)
- .map { case (opName, typeId, methodId, time, count) =>
- val key = s"($typeId.toByte, $methodId.toByte)".padTo(25, ' ')
- s"$key -> $time, // count = $count, $opName "
- }
- .mkString("\n")
-
-// val total = opStat.values.foldLeft(0L) { (acc, item) => acc + item.sum }
- s"""
- |-----------
- |$rows
- |-----------
- |$mcRows
- |-----------
- """.stripMargin
- }
-}
diff --git a/interpreter/shared/src/test/scala/org/ergoplatform/validation/ValidationSpecification.scala b/interpreter/shared/src/test/scala/org/ergoplatform/validation/ValidationSpecification.scala
index 1e30653d9b..b223355c5b 100644
--- a/interpreter/shared/src/test/scala/org/ergoplatform/validation/ValidationSpecification.scala
+++ b/interpreter/shared/src/test/scala/org/ergoplatform/validation/ValidationSpecification.scala
@@ -1,5 +1,7 @@
package org.ergoplatform.validation
+import sigma.validation.SigmaValidationSettings
+
trait ValidationSpecification {
implicit val vs: SigmaValidationSettings = ValidationRules.currentSettings
}
diff --git a/interpreter/shared/src/test/scala/sigmastate/lang/SigmaBuilderTest.scala b/interpreter/shared/src/test/scala/sigma/ast/SigmaBuilderTest.scala
similarity index 95%
rename from interpreter/shared/src/test/scala/sigmastate/lang/SigmaBuilderTest.scala
rename to interpreter/shared/src/test/scala/sigma/ast/SigmaBuilderTest.scala
index 657ded51ce..acf8e74bd2 100644
--- a/interpreter/shared/src/test/scala/sigmastate/lang/SigmaBuilderTest.scala
+++ b/interpreter/shared/src/test/scala/sigma/ast/SigmaBuilderTest.scala
@@ -1,17 +1,15 @@
-package sigmastate.lang
+package sigma.ast
import org.scalatest.matchers.should.Matchers
import org.scalatest.propspec.AnyPropSpec
import org.scalatestplus.scalacheck.ScalaCheckPropertyChecks
-import sigma.data.{Nullable, RType}
-import sigma.{Environment, VersionContext}
-import sigmastate.Values._
+import sigma.Extensions.ArrayOps
+import sigma.data.{CAnyValue, CAvlTree, CBox, Nullable, RType}
+import sigma.eval.SigmaDsl
+import sigma.exceptions.ConstraintFailed
+import sigma.serialization.OpCodes
+import sigma.{Environment, SigmaTestingData, VersionContext}
import sigmastate._
-import sigmastate.eval.Extensions.ArrayOps
-import sigmastate.eval.{CAnyValue, CAvlTree, CostingBox, SigmaDsl}
-import sigmastate.exceptions.ConstraintFailed
-import sigmastate.serialization.OpCodes
-import sigma.SigmaTestingData
import java.math.BigInteger
@@ -79,7 +77,7 @@ class SigmaBuilderTest extends AnyPropSpec with ScalaCheckPropertyChecks with Ma
an[ConstraintFailed] should be thrownBy mkDivide(LongConstant(1), IntConstant(1))
an[ConstraintFailed] should be thrownBy mkModulo(LongConstant(1), IntConstant(1))
}
- import Platform.liftToConstant
+ import sigma.Platform.liftToConstant
def testSuccess(v: Any, c: Constant[SType]): Unit = {
liftToConstant(v, TransformingSigmaBuilder) shouldBe Nullable(c)
@@ -207,7 +205,7 @@ class SigmaBuilderTest extends AnyPropSpec with ScalaCheckPropertyChecks with Ma
}
property("liftToConstant ErgoBox") {
- val v = TestData.b2.asInstanceOf[CostingBox].wrappedValue
+ val v = TestData.b2.asInstanceOf[CBox].wrappedValue
val c = BoxConstant(TestData.b2)
testSuccess(v, c) // TODO v6.0: ErgoBox should not be liftable directly (see https://github.com/ScorexFoundation/sigmastate-interpreter/issues/905)
testFailure(Array.fill(10)(v))
diff --git a/interpreter/shared/src/test/scala/sigmastate/serialization/AndSerializerSpecification.scala b/interpreter/shared/src/test/scala/sigma/serialization/AndSerializerSpecification.scala
similarity index 82%
rename from interpreter/shared/src/test/scala/sigmastate/serialization/AndSerializerSpecification.scala
rename to interpreter/shared/src/test/scala/sigma/serialization/AndSerializerSpecification.scala
index bfa922ab69..bc7e678062 100644
--- a/interpreter/shared/src/test/scala/sigmastate/serialization/AndSerializerSpecification.scala
+++ b/interpreter/shared/src/test/scala/sigma/serialization/AndSerializerSpecification.scala
@@ -1,10 +1,10 @@
-package sigmastate.serialization
+package sigma.serialization
-import sigmastate.Values.{BooleanConstant, Constant, IntConstant}
-import sigmastate._
-import sigmastate.eval.Extensions._
-import sigmastate.serialization.OpCodes._
+import sigma.ast.{AND, BooleanConstant, Constant, EQ, IntConstant, SBoolean, SCollection, SCollectionType, SInt}
+import sigma.serialization.OpCodes._
import scorex.util.encode.ZigZagEncoder.encodeZigZagInt
+import sigma.Extensions.ArrayOps
+import sigma.ast.syntax.BooleanConstant
class AndSerializerSpecification extends TableSerializationSpecification {
diff --git a/interpreter/shared/src/test/scala/sigmastate/serialization/AvlTreeSpecification.scala b/interpreter/shared/src/test/scala/sigma/serialization/AvlTreeSpecification.scala
similarity index 89%
rename from interpreter/shared/src/test/scala/sigmastate/serialization/AvlTreeSpecification.scala
rename to interpreter/shared/src/test/scala/sigma/serialization/AvlTreeSpecification.scala
index 8a0b4b9255..1bd3b47983 100644
--- a/interpreter/shared/src/test/scala/sigmastate/serialization/AvlTreeSpecification.scala
+++ b/interpreter/shared/src/test/scala/sigma/serialization/AvlTreeSpecification.scala
@@ -1,14 +1,14 @@
-package sigmastate.serialization
+package sigma.serialization
-import scorex.crypto.authds.{ADKey, ADValue}
import scorex.crypto.authds.avltree.batch.{BatchAVLProver, Insert}
+import scorex.crypto.authds.{ADKey, ADValue}
import scorex.crypto.hash.{Blake2b256, Digest32}
import sigma.Colls
-import sigmastate.Values.AvlTreeConstant
-import sigmastate.AvlTreeFlags
-import sigmastate._
-import sigmastate.eval.Extensions._
-import sigmastate.eval._
+import sigma.data.{AvlTreeData, AvlTreeFlags}
+import sigma.ast.AvlTreeConstant
+import sigma.Extensions.ArrayOps
+import sigma.eval.SigmaDsl
+import sigmastate.eval.Extensions.AvlTreeOps
class AvlTreeSpecification extends SerializationSpecification {
diff --git a/interpreter/shared/src/test/scala/sigmastate/serialization/BlockSerializerSpecification.scala b/interpreter/shared/src/test/scala/sigma/serialization/BlockSerializerSpecification.scala
similarity index 87%
rename from interpreter/shared/src/test/scala/sigmastate/serialization/BlockSerializerSpecification.scala
rename to interpreter/shared/src/test/scala/sigma/serialization/BlockSerializerSpecification.scala
index c07081b816..4a242b6fb8 100644
--- a/interpreter/shared/src/test/scala/sigmastate/serialization/BlockSerializerSpecification.scala
+++ b/interpreter/shared/src/test/scala/sigma/serialization/BlockSerializerSpecification.scala
@@ -1,9 +1,8 @@
-package sigmastate.serialization
+package sigma.serialization
import org.scalacheck.Gen
-import sigmastate.SType
-import sigmastate.Values.Constant
-import sigmastate.lang.{SigmaBuilder, DeserializationSigmaBuilder}
+import sigma.ast.{DeserializationSigmaBuilder, SType, SigmaBuilder}
+import sigma.ast.Constant
class BlockSerializerSpecification extends SerializationSpecification {
diff --git a/interpreter/shared/src/test/scala/sigmastate/serialization/ConcreteCollectionSerializerSpecification.scala b/interpreter/shared/src/test/scala/sigma/serialization/ConcreteCollectionSerializerSpecification.scala
similarity index 84%
rename from interpreter/shared/src/test/scala/sigmastate/serialization/ConcreteCollectionSerializerSpecification.scala
rename to interpreter/shared/src/test/scala/sigma/serialization/ConcreteCollectionSerializerSpecification.scala
index a0812597e5..0c795ea4f4 100644
--- a/interpreter/shared/src/test/scala/sigmastate/serialization/ConcreteCollectionSerializerSpecification.scala
+++ b/interpreter/shared/src/test/scala/sigma/serialization/ConcreteCollectionSerializerSpecification.scala
@@ -1,10 +1,9 @@
-package sigmastate.serialization
-
-import sigmastate.Values.{FalseLeaf, Constant, TrueLeaf, IntConstant, TaggedInt, ConcreteCollection}
-import sigmastate._
-import sigmastate.eval.Evaluation
-import sigmastate.lang.Terms._
+package sigma.serialization
+import sigma.Evaluation
+import sigma.ast.syntax.{IntConstant, OptionValueOps}
+import sigma.ast._
+import sigma.ast.syntax._
import scala.util.Random
class ConcreteCollectionSerializerSpecification extends TableSerializationSpecification {
@@ -37,8 +36,8 @@ class ConcreteCollectionSerializerSpecification extends TableSerializationSpecif
}
property("ConcreteCollection: Serializer round trip with different types seq") {
- forAll { (i: IntConstant, ti: TaggedInt) =>
- val seq = Random.shuffle(Seq(i.asIntValue, ti.asIntValue)).toArray
+ forAll(intConstGen, getVarIntGen) { (i: IntConstant, ti: GetVar[SInt.type]) =>
+ val seq = Random.shuffle(Seq(i.asIntValue, ti.get)).toArray
roundTripTest(ConcreteCollection.fromSeq(seq))
}
}
diff --git a/interpreter/shared/src/test/scala/sigmastate/serialization/ConstantSerializerSpecification.scala b/interpreter/shared/src/test/scala/sigma/serialization/ConstantSerializerSpecification.scala
similarity index 88%
rename from interpreter/shared/src/test/scala/sigmastate/serialization/ConstantSerializerSpecification.scala
rename to interpreter/shared/src/test/scala/sigma/serialization/ConstantSerializerSpecification.scala
index 04b016376a..7bc73643f2 100644
--- a/interpreter/shared/src/test/scala/sigmastate/serialization/ConstantSerializerSpecification.scala
+++ b/interpreter/shared/src/test/scala/sigma/serialization/ConstantSerializerSpecification.scala
@@ -1,23 +1,22 @@
-package sigmastate.serialization
+package sigma.serialization
import java.math.BigInteger
import org.ergoplatform._
import org.scalacheck.Arbitrary._
-import sigma.data.RType
-import sigmastate.SCollection.SByteArray
-import sigmastate.Values.{BigIntConstant, ByteArrayConstant, Constant, FalseLeaf, GroupGenerator, LongConstant, SValue, TrueLeaf}
-import sigmastate.crypto.CryptoConstants.EcPointType
-import sigmastate._
+import sigma.data.{RType, SigmaBoolean, TupleColl}
+import sigma.ast.SCollection.SByteArray
+import sigma.ast.{BigIntConstant, ByteArrayConstant, Constant, DeserializationSigmaBuilder, FalseLeaf, GroupGenerator, LongConstant, TrueLeaf}
import sigmastate.eval._
-import sigmastate.eval.Extensions._
-import sigmastate.Values._
-import sigmastate.eval.Evaluation
-import sigma.{AvlTree, Colls}
-import SType.AnyOps
+import sigma.Extensions.ArrayOps
+import sigma.ast._
+import sigma.{AvlTree, Colls, Evaluation}
+import sigma.ast.SType.AnyOps
import scorex.util.encode.Base16
-import sigmastate.exceptions.SerializerException
-import sigmastate.lang.DeserializationSigmaBuilder
-
+import sigma.ast.BoolArrayConstant.BoolArrayTypeCode
+import sigma.ast.ByteArrayConstant.ByteArrayTypeCode
+import sigma.ast.syntax.{BoolValue, SValue}
+import sigma.crypto.EcPointType
+import sigma.util.Extensions.{BigIntegerOps, EcpOps, SigmaBooleanOps}
import scala.annotation.nowarn
class ConstantSerializerSpecification extends TableSerializationSpecification {
@@ -67,9 +66,9 @@ class ConstantSerializerSpecification extends TableSerializationSpecification {
forAll { x: Boolean => roundTripTest(BooleanConstant.fromBoolean(x)) }
forAll { x: Long => roundTripTest(Constant[SLong.type](x, SLong)) }
forAll { x: String => roundTripTest(Constant[SString.type](x, SString)) }
- forAll { x: BigInteger => roundTripTest(Constant[SBigInt.type](x, SBigInt)) }
- forAll { x: EcPointType => roundTripTest(Constant[SGroupElement.type](x, SGroupElement)) }
- forAll { x: SigmaBoolean => roundTripTest(Constant[SSigmaProp.type](x, SSigmaProp)) }
+ forAll { x: BigInteger => roundTripTest(Constant[SBigInt.type](x.toBigInt, SBigInt)) }
+ forAll { x: EcPointType => roundTripTest(Constant[SGroupElement.type](x.toGroupElement, SGroupElement)) }
+ forAll { x: SigmaBoolean => roundTripTest(Constant[SSigmaProp.type](x.toSigmaProp, SSigmaProp)) }
forAll { x: ErgoBox => roundTripTest(Constant[SBox.type](x, SBox)) }
forAll { x: AvlTree => roundTripTest(Constant[SAvlTree.type](x, SAvlTree)) }
forAll { x: Array[Byte] => roundTripTest(Constant[SByteArray](x.toColl, SByteArray)) }
diff --git a/interpreter/shared/src/test/scala/sigmastate/serialization/ConstantStoreSpecification.scala b/interpreter/shared/src/test/scala/sigma/serialization/ConstantStoreSpecification.scala
similarity index 88%
rename from interpreter/shared/src/test/scala/sigmastate/serialization/ConstantStoreSpecification.scala
rename to interpreter/shared/src/test/scala/sigma/serialization/ConstantStoreSpecification.scala
index 70764b5e1f..f8ebeb34a6 100644
--- a/interpreter/shared/src/test/scala/sigmastate/serialization/ConstantStoreSpecification.scala
+++ b/interpreter/shared/src/test/scala/sigma/serialization/ConstantStoreSpecification.scala
@@ -1,8 +1,7 @@
-package sigmastate.serialization
+package sigma.serialization
-import sigmastate.Values.{Constant, IntConstant}
-import sigmastate._
-import sigmastate.lang.{SigmaBuilder, DeserializationSigmaBuilder}
+import sigma.ast.{DeserializationSigmaBuilder, SType, SigmaBuilder}
+import sigma.ast.{Constant, IntConstant}
class ConstantStoreSpecification extends SerializationSpecification {
diff --git a/interpreter/shared/src/test/scala/sigmastate/serialization/DataSerializerSpecification.scala b/interpreter/shared/src/test/scala/sigma/serialization/DataSerializerSpecification.scala
similarity index 79%
rename from interpreter/shared/src/test/scala/sigmastate/serialization/DataSerializerSpecification.scala
rename to interpreter/shared/src/test/scala/sigma/serialization/DataSerializerSpecification.scala
index c02df973dc..ecb2d2ef70 100644
--- a/interpreter/shared/src/test/scala/sigmastate/serialization/DataSerializerSpecification.scala
+++ b/interpreter/shared/src/test/scala/sigma/serialization/DataSerializerSpecification.scala
@@ -1,24 +1,26 @@
-package sigmastate.serialization
+package sigma.serialization
import java.math.BigInteger
import org.ergoplatform.ErgoBox
import org.scalacheck.Arbitrary._
-import sigma.data.RType
-import sigmastate.SCollection.SByteArray
-import sigmastate.Values.{ErgoTree, SigmaBoolean}
+import sigma.data.{DataValueComparer, RType, SigmaBoolean, TupleColl}
+import sigma.ast.SCollection.SByteArray
import sigmastate._
-import sigmastate.eval.Evaluation
import sigmastate.eval._
-import sigmastate.eval.Extensions._
-import sigmastate.crypto.CryptoConstants.EcPointType
-import sigma.{AvlTree, Colls}
-import SType.AnyOps
-import sigmastate.exceptions.SerializerException
-import sigmastate.interpreter.{CostAccumulator, ErgoTreeEvaluator}
-import sigmastate.interpreter.ErgoTreeEvaluator.DefaultProfiler
+import sigma.{AvlTree, Colls, Evaluation}
+import sigma.ast.SType.AnyOps
+import sigma.ast._
+import org.scalacheck.Gen
+import sigma.Extensions.ArrayOps
+import sigma.crypto.EcPointType
+import sigma.eval.SigmaDsl
+import sigma.util.Extensions.{BigIntegerOps, EcpOps, SigmaBooleanOps}
+import sigmastate.interpreter.{CostAccumulator, CErgoTreeEvaluator}
+import sigmastate.interpreter.CErgoTreeEvaluator.DefaultProfiler
import sigmastate.utils.Helpers
import scala.annotation.nowarn
+import scala.reflect.ClassTag
class DataSerializerSpecification extends SerializationSpecification {
@@ -30,11 +32,11 @@ class DataSerializerSpecification extends SerializationSpecification {
val res = DataSerializer.deserialize(tpe, r)
res shouldBe obj
- val es = ErgoTreeEvaluator.DefaultEvalSettings
+ val es = CErgoTreeEvaluator.DefaultEvalSettings
val accumulator = new CostAccumulator(
initialCost = JitCost(0),
costLimit = Some(JitCost.fromBlockCost(es.scriptCostLimitInEvaluator)))
- val evaluator = new ErgoTreeEvaluator(
+ val evaluator = new CErgoTreeEvaluator(
context = null,
constants = ErgoTree.EmptyConstants,
coster = accumulator, DefaultProfiler, es)
@@ -76,9 +78,10 @@ class DataSerializerSpecification extends SerializationSpecification {
}
def testTuples[T <: SType](tpe: T) = {
- implicit val wWrapped = wrappedTypeGen(tpe)
- @nowarn implicit val tag = tpe.classTag[T#WrappedType]
- implicit val tAny: RType[Any] = sigma.AnyType
+ implicit val wWrapped: Gen[T#WrappedType] = wrappedTypeGen(tpe)
+ val tT = Evaluation.stypeToRType(tpe)
+ @nowarn implicit val tag: ClassTag[T#WrappedType] = tT.classTag
+ implicit val tAny : RType[Any] = sigma.AnyType
forAll { in: (T#WrappedType, T#WrappedType) =>
val (x,y) = (in._1, in._2)
roundtrip[SType]((x, y).asWrappedType, STuple(tpe, tpe))
@@ -95,9 +98,9 @@ class DataSerializerSpecification extends SerializationSpecification {
forAll { x: Boolean => roundtrip[SBoolean.type](x, SBoolean) }
forAll { x: Long => roundtrip[SLong.type](x, SLong) }
forAll { x: String => roundtrip[SString.type](x, SString) }
- forAll { x: BigInteger => roundtrip[SBigInt.type](x, SBigInt) }
- forAll { x: EcPointType => roundtrip[SGroupElement.type](x, SGroupElement) }
- forAll { x: SigmaBoolean => roundtrip[SSigmaProp.type](x, SSigmaProp) }
+ forAll { x: BigInteger => roundtrip[SBigInt.type](x.toBigInt, SBigInt) }
+ forAll { x: EcPointType => roundtrip[SGroupElement.type](x.toGroupElement, SGroupElement) }
+ forAll { x: SigmaBoolean => roundtrip[SSigmaProp.type](x.toSigmaProp, SSigmaProp) }
forAll { x: ErgoBox => roundtrip[SBox.type](x, SBox) }
forAll { x: AvlTree => roundtrip[SAvlTree.type](x, SAvlTree) }
forAll { x: Array[Byte] => roundtrip[SByteArray](x.toColl, SByteArray) }
diff --git a/interpreter/shared/src/test/scala/sigmastate/serialization/GroupElementSerializerSpecification.scala b/interpreter/shared/src/test/scala/sigma/serialization/GroupElementSerializerSpecification.scala
similarity index 76%
rename from interpreter/shared/src/test/scala/sigmastate/serialization/GroupElementSerializerSpecification.scala
rename to interpreter/shared/src/test/scala/sigma/serialization/GroupElementSerializerSpecification.scala
index 04c4a8e128..aaaeee2725 100644
--- a/interpreter/shared/src/test/scala/sigmastate/serialization/GroupElementSerializerSpecification.scala
+++ b/interpreter/shared/src/test/scala/sigma/serialization/GroupElementSerializerSpecification.scala
@@ -1,8 +1,7 @@
-package sigmastate.serialization
+package sigma.serialization
-import sigmastate.crypto.CryptoConstants
-import sigmastate.crypto.CryptoFacade
-import sigmastate.eval._
+import sigma.crypto.{CryptoConstants, CryptoFacade}
+import sigma.util.Extensions.{EcpOps, GroupElementOps}
class GroupElementSerializerSpecification extends SerializationSpecification {
@@ -13,18 +12,18 @@ class GroupElementSerializerSpecification extends SerializationSpecification {
val bytes = GroupElementSerializer.toBytes(identity)
bytes.length shouldBe CryptoConstants.EncodedGroupElementLength
bytes.forall(_ == 0) shouldBe true
- GroupElementSerializer.parse(SigmaSerializer.startReader(bytes, 0)).isIdentity shouldBe true
+ GroupElementSerializer.parse(SigmaSerializer.startReader(bytes, 0)).toGroupElement.isIdentity shouldBe true
}
property("point roundtrip") {
forAll(groupElementConstGen){ge =>
- val bytes = GroupElementSerializer.toBytes(ge.value)
+ val bytes = GroupElementSerializer.toBytes(ge.value.toECPoint)
bytes.length shouldBe CryptoConstants.EncodedGroupElementLength
val restored = GroupElementSerializer.parse(SigmaSerializer.startReader(bytes, 0))
CryptoFacade.getAffineXCoord(CryptoFacade.normalizePoint(restored)) shouldBe
- CryptoFacade.getAffineXCoord(CryptoFacade.normalizePoint(ge.value))
+ CryptoFacade.getAffineXCoord(CryptoFacade.normalizePoint(ge.value.toECPoint))
CryptoFacade.getAffineYCoord(CryptoFacade.normalizePoint(restored)) shouldBe
- CryptoFacade.getAffineYCoord(CryptoFacade.normalizePoint(ge.value))
+ CryptoFacade.getAffineYCoord(CryptoFacade.normalizePoint(ge.value.toECPoint))
}
}
}
diff --git a/interpreter/shared/src/test/scala/sigmastate/serialization/MethodCallSerializerSpecification.scala b/interpreter/shared/src/test/scala/sigma/serialization/MethodCallSerializerSpecification.scala
similarity index 53%
rename from interpreter/shared/src/test/scala/sigmastate/serialization/MethodCallSerializerSpecification.scala
rename to interpreter/shared/src/test/scala/sigma/serialization/MethodCallSerializerSpecification.scala
index e84f2f64a4..ac9c997d98 100644
--- a/interpreter/shared/src/test/scala/sigmastate/serialization/MethodCallSerializerSpecification.scala
+++ b/interpreter/shared/src/test/scala/sigma/serialization/MethodCallSerializerSpecification.scala
@@ -1,16 +1,12 @@
-package sigmastate.serialization
+package sigma.serialization
-import org.ergoplatform.Outputs
-import sigmastate.Values.{FuncValue, ValUse}
-import sigmastate.lang.Terms.MethodCall
-import sigmastate.utxo.ExtractScriptBytes
-import sigmastate._
+import sigma.ast._
class MethodCallSerializerSpecification extends SerializationSpecification {
property("MethodCall deserialization round trip") {
val expr = MethodCall(Outputs,
- SCollection.FlatMapMethod.withConcreteTypes(Map(SCollection.tIV -> SBox, SCollection.tOV -> SByte)),
+ SCollectionMethods.FlatMapMethod.withConcreteTypes(Map(SCollection.tIV -> SBox, SCollection.tOV -> SByte)),
Vector(FuncValue(1, SBox, ExtractScriptBytes(ValUse(1, SBox)))),
Map()
)
@@ -19,7 +15,7 @@ class MethodCallSerializerSpecification extends SerializationSpecification {
property("MethodCall deserialization round trip (non-generic method)") {
val expr = MethodCall(Outputs,
- SCollection.SizeMethod.withConcreteTypes(Map(SCollection.tIV -> SBox)),
+ SCollectionMethods.SizeMethod.withConcreteTypes(Map(SCollection.tIV -> SBox)),
Vector(),
Map()
)
diff --git a/interpreter/shared/src/test/scala/sigmastate/serialization/ModQSerializerSpecification.scala b/interpreter/shared/src/test/scala/sigma/serialization/ModQSerializerSpecification.scala
similarity index 75%
rename from interpreter/shared/src/test/scala/sigmastate/serialization/ModQSerializerSpecification.scala
rename to interpreter/shared/src/test/scala/sigma/serialization/ModQSerializerSpecification.scala
index cfeb881fc6..13cb1b07a2 100644
--- a/interpreter/shared/src/test/scala/sigmastate/serialization/ModQSerializerSpecification.scala
+++ b/interpreter/shared/src/test/scala/sigma/serialization/ModQSerializerSpecification.scala
@@ -1,7 +1,7 @@
-package sigmastate.serialization
+package sigma.serialization
-import sigmastate.Values.BigIntConstant
-import sigmastate._
+import sigma.ast.ModQ
+import sigma.ast.syntax.BigIntConstant
class ModQSerializerSpecification extends SerializationSpecification {
diff --git a/interpreter/shared/src/test/scala/sigmastate/serialization/OrSerializerSpecification.scala b/interpreter/shared/src/test/scala/sigma/serialization/OrSerializerSpecification.scala
similarity index 82%
rename from interpreter/shared/src/test/scala/sigmastate/serialization/OrSerializerSpecification.scala
rename to interpreter/shared/src/test/scala/sigma/serialization/OrSerializerSpecification.scala
index b7fbf54c66..ad61df8a71 100644
--- a/interpreter/shared/src/test/scala/sigmastate/serialization/OrSerializerSpecification.scala
+++ b/interpreter/shared/src/test/scala/sigma/serialization/OrSerializerSpecification.scala
@@ -1,10 +1,10 @@
-package sigmastate.serialization
+package sigma.serialization
-import sigmastate.Values.{BooleanConstant, Constant, IntConstant}
-import sigmastate._
-import sigmastate.eval.Extensions._
-import sigmastate.serialization.OpCodes._
+import sigma.ast.{BooleanConstant, Constant, EQ, IntConstant, OR, SBoolean, SCollection, SCollectionType, SInt}
+import sigma.serialization.OpCodes._
import scorex.util.encode.ZigZagEncoder.encodeZigZagInt
+import sigma.Extensions.ArrayOps
+import sigma.ast.syntax.BooleanConstant
class OrSerializerSpecification extends TableSerializationSpecification {
diff --git a/interpreter/shared/src/test/scala/sigmastate/serialization/PDHTSerializerSpecification.scala b/interpreter/shared/src/test/scala/sigma/serialization/PDHTSerializerSpecification.scala
similarity index 83%
rename from interpreter/shared/src/test/scala/sigmastate/serialization/PDHTSerializerSpecification.scala
rename to interpreter/shared/src/test/scala/sigma/serialization/PDHTSerializerSpecification.scala
index dbca6fb190..bc57decbf8 100644
--- a/interpreter/shared/src/test/scala/sigmastate/serialization/PDHTSerializerSpecification.scala
+++ b/interpreter/shared/src/test/scala/sigma/serialization/PDHTSerializerSpecification.scala
@@ -1,12 +1,13 @@
-package sigmastate.serialization
+package sigma.serialization
-import sigmastate.crypto.ProveDHTuple
+import sigma.data.ProveDHTuple
+import sigma.eval.Extensions.SigmaBooleanOps
class PDHTSerializerSpecification extends SerializationSpecification {
property("ProveDiffieHellmanTupleSerializer: Serializer round trip") {
forAll { i: ProveDHTuple =>
- roundTripTest(i.toSigmaProp)
+ roundTripTest(i.toSigmaPropValue)
}
// In IntelliJ IDEA this test is executed last, at this point all statistics has been collected
diff --git a/interpreter/shared/src/test/scala/sigmastate/serialization/ProveDlogSerializerSpec.scala b/interpreter/shared/src/test/scala/sigma/serialization/ProveDlogSerializerSpec.scala
similarity index 53%
rename from interpreter/shared/src/test/scala/sigmastate/serialization/ProveDlogSerializerSpec.scala
rename to interpreter/shared/src/test/scala/sigma/serialization/ProveDlogSerializerSpec.scala
index df791f248a..cce194b3ce 100644
--- a/interpreter/shared/src/test/scala/sigmastate/serialization/ProveDlogSerializerSpec.scala
+++ b/interpreter/shared/src/test/scala/sigma/serialization/ProveDlogSerializerSpec.scala
@@ -1,12 +1,13 @@
-package sigmastate.serialization
+package sigma.serialization
-import sigmastate.crypto.DLogProtocol.ProveDlog
+import sigma.data.ProveDlog
+import sigma.eval.Extensions.SigmaBooleanOps
class ProveDlogSerializerSpec extends SerializationSpecification {
property("ProveDlog: Serializer round trip") {
forAll { pd: ProveDlog =>
- roundTripTest(pd.toSigmaProp)
+ roundTripTest(pd.toSigmaPropValue)
}
}
diff --git a/interpreter/shared/src/test/scala/sigmastate/serialization/RelationsSpecification.scala b/interpreter/shared/src/test/scala/sigma/serialization/RelationsSpecification.scala
similarity index 92%
rename from interpreter/shared/src/test/scala/sigmastate/serialization/RelationsSpecification.scala
rename to interpreter/shared/src/test/scala/sigma/serialization/RelationsSpecification.scala
index fc9d18330f..44bdabebf8 100644
--- a/interpreter/shared/src/test/scala/sigmastate/serialization/RelationsSpecification.scala
+++ b/interpreter/shared/src/test/scala/sigma/serialization/RelationsSpecification.scala
@@ -1,10 +1,10 @@
-package sigmastate.serialization
+package sigma.serialization
-import sigmastate.Values._
-import sigmastate._
-import sigmastate.serialization.OpCodes._
-import sigmastate.serialization.ValueSerializer._
+import sigma.ast._
+import sigma.serialization.OpCodes._
+import sigma.serialization.ValueSerializer._
import scorex.util.encode.ZigZagEncoder.encodeZigZagLong
+import sigma.ast.{SInt, SLong}
class RelationsSpecification extends TableSerializationSpecification {
diff --git a/interpreter/shared/src/test/scala/sigmastate/serialization/SelectFieldSerializerSpecification.scala b/interpreter/shared/src/test/scala/sigma/serialization/SelectFieldSerializerSpecification.scala
similarity index 79%
rename from interpreter/shared/src/test/scala/sigmastate/serialization/SelectFieldSerializerSpecification.scala
rename to interpreter/shared/src/test/scala/sigma/serialization/SelectFieldSerializerSpecification.scala
index 678ff1a241..fb3bbcd326 100644
--- a/interpreter/shared/src/test/scala/sigmastate/serialization/SelectFieldSerializerSpecification.scala
+++ b/interpreter/shared/src/test/scala/sigma/serialization/SelectFieldSerializerSpecification.scala
@@ -1,9 +1,9 @@
-package sigmastate.serialization
+package sigma.serialization
import org.scalacheck.Gen
-import sigmastate.Values.{FalseLeaf, IntConstant, Tuple}
-import sigmastate.serialization.OpCodes.{SelectFieldCode, TupleCode}
-import sigmastate.utxo.SelectField
+import sigma.ast.syntax.CollectionOps
+import sigma.ast.{FalseLeaf, IntConstant, SelectField, Tuple}
+import sigma.serialization.OpCodes.{SelectFieldCode, TupleCode}
class SelectFieldSerializerSpecification extends TableSerializationSpecification {
diff --git a/interpreter/shared/src/test/scala/sigmastate/serialization/SerializationSpecification.scala b/interpreter/shared/src/test/scala/sigma/serialization/SerializationSpecification.scala
similarity index 93%
rename from interpreter/shared/src/test/scala/sigmastate/serialization/SerializationSpecification.scala
rename to interpreter/shared/src/test/scala/sigma/serialization/SerializationSpecification.scala
index 03b8801459..30ae6af19b 100644
--- a/interpreter/shared/src/test/scala/sigmastate/serialization/SerializationSpecification.scala
+++ b/interpreter/shared/src/test/scala/sigma/serialization/SerializationSpecification.scala
@@ -1,4 +1,4 @@
-package sigmastate.serialization
+package sigma.serialization
import org.ergoplatform.validation.ValidationSpecification
import org.scalacheck.Gen
@@ -8,10 +8,10 @@ import org.scalacheck.Arbitrary._
import org.scalatest.matchers.should.Matchers
import org.scalatest.propspec.AnyPropSpec
import org.scalatestplus.scalacheck.{ScalaCheckDrivenPropertyChecks, ScalaCheckPropertyChecks}
-import sigmastate.Values._
-import sigmastate.SType
+import sigma.ast.SType
+import sigma.ast._
import sigmastate.helpers.NegativeTesting
-import sigmastate.serialization.generators._
+import sigma.serialization.generators._
trait SerializationSpecification extends AnyPropSpec
with ScalaCheckPropertyChecks
diff --git a/interpreter/shared/src/test/scala/sigmastate/serialization/SigSerializerSpecification.scala b/interpreter/shared/src/test/scala/sigma/serialization/SigSerializerSpecification.scala
similarity index 98%
rename from interpreter/shared/src/test/scala/sigmastate/serialization/SigSerializerSpecification.scala
rename to interpreter/shared/src/test/scala/sigma/serialization/SigSerializerSpecification.scala
index 52aaa89070..69d85f16f2 100644
--- a/interpreter/shared/src/test/scala/sigmastate/serialization/SigSerializerSpecification.scala
+++ b/interpreter/shared/src/test/scala/sigma/serialization/SigSerializerSpecification.scala
@@ -1,19 +1,20 @@
-package sigmastate.serialization
+package sigma.serialization
import java.math.BigInteger
import org.ergoplatform.settings.ErgoAlgos
import org.scalacheck.{Arbitrary, Gen}
import org.scalatest.Assertion
-import sigmastate.Values.SigmaBoolean
+import sigma.Extensions.ArrayOps
+import sigma.data.{AvlTreeData, CAND, COR, CTHRESHOLD, ProveDHTuple, ProveDlog, SigmaBoolean, TrivialProp}
+import sigma.eval.Extensions.SigmaBooleanOps
import sigmastate._
-import sigmastate.crypto.DLogProtocol.{ProveDlog, SecondDLogProverMessage}
+import sigmastate.crypto.DLogProtocol.SecondDLogProverMessage
import sigmastate.crypto.VerifierMessage.Challenge
-import sigmastate.crypto.{ProveDHTuple, SecondDHTupleProverMessage}
+import sigmastate.crypto.SecondDHTupleProverMessage
import sigmastate.crypto.GF2_192_Poly
-import sigmastate.eval.Extensions.ArrayOps
import sigmastate.helpers.{ContextEnrichingTestProvingInterpreter, ErgoLikeContextTesting, ErgoLikeTransactionTesting, TestingCommons}
import sigmastate.interpreter.Interpreter
-import sigmastate.serialization.generators.ObjectGenerators
+import sigma.serialization.generators.ObjectGenerators
import sigmastate.utils.Helpers
import scala.util.Random
@@ -72,7 +73,7 @@ class SigSerializerSpecification extends TestingCommons
property("SigSerializer round trip") {
forAll(configParams = MinSuccessful(100)) { sb: SigmaBoolean =>
- val expr = sb.toSigmaProp
+ val expr = sb.toSigmaPropValue
val challenge = Array.fill(32)(Random.nextInt(100).toByte)
val ctx = ErgoLikeContextTesting(
diff --git a/interpreter/shared/src/test/scala/sigmastate/serialization/SubstConstantsSerializerSpecification.scala b/interpreter/shared/src/test/scala/sigma/serialization/SubstConstantsSerializerSpecification.scala
similarity index 65%
rename from interpreter/shared/src/test/scala/sigmastate/serialization/SubstConstantsSerializerSpecification.scala
rename to interpreter/shared/src/test/scala/sigma/serialization/SubstConstantsSerializerSpecification.scala
index 0a6e73dac1..9c56fe2d48 100644
--- a/interpreter/shared/src/test/scala/sigmastate/serialization/SubstConstantsSerializerSpecification.scala
+++ b/interpreter/shared/src/test/scala/sigma/serialization/SubstConstantsSerializerSpecification.scala
@@ -1,8 +1,10 @@
-package sigmastate.serialization
+package sigma.serialization
-import sigmastate.Values.{ConcreteCollection, IntConstant, IntArrayConstant, IntValue}
-import sigmastate.serialization.ErgoTreeSerializer.DefaultSerializer
-import sigmastate.{CrossVersionProps, SInt, EQ, SubstConstants}
+import sigma.ast.{EQ, SInt, SubstConstants}
+import sigma.ast.syntax.IntValue
+import sigma.ast.{ConcreteCollection, IntArrayConstant, IntConstant}
+import sigma.serialization.ErgoTreeSerializer.DefaultSerializer
+import sigmastate.CrossVersionProps
class SubstConstantsSerializerSpecification extends SerializationSpecification
with CrossVersionProps {
diff --git a/interpreter/shared/src/test/scala/sigmastate/serialization/TableSerializationSpecification.scala b/interpreter/shared/src/test/scala/sigma/serialization/TableSerializationSpecification.scala
similarity index 85%
rename from interpreter/shared/src/test/scala/sigmastate/serialization/TableSerializationSpecification.scala
rename to interpreter/shared/src/test/scala/sigma/serialization/TableSerializationSpecification.scala
index 543be44806..6774d03f15 100644
--- a/interpreter/shared/src/test/scala/sigmastate/serialization/TableSerializationSpecification.scala
+++ b/interpreter/shared/src/test/scala/sigma/serialization/TableSerializationSpecification.scala
@@ -1,8 +1,8 @@
-package sigmastate.serialization
+package sigma.serialization
import org.scalatest.prop.TableFor2
-import sigmastate.Values._
-import sigmastate.SType
+import sigma.ast.SType
+import sigma.ast._
trait TableSerializationSpecification extends SerializationSpecification {
def objects: TableFor2[_ <: Value[_ <: SType], Array[Byte]]
diff --git a/interpreter/shared/src/test/scala/sigmastate/serialization/TransformersSerializationSpec.scala b/interpreter/shared/src/test/scala/sigma/serialization/TransformersSerializationSpec.scala
similarity index 98%
rename from interpreter/shared/src/test/scala/sigmastate/serialization/TransformersSerializationSpec.scala
rename to interpreter/shared/src/test/scala/sigma/serialization/TransformersSerializationSpec.scala
index 1239495bba..7de1f89512 100644
--- a/interpreter/shared/src/test/scala/sigmastate/serialization/TransformersSerializationSpec.scala
+++ b/interpreter/shared/src/test/scala/sigma/serialization/TransformersSerializationSpec.scala
@@ -1,7 +1,6 @@
-package sigmastate.serialization
+package sigma.serialization
-import sigmastate._
-import sigmastate.utxo._
+import sigma.ast._
class TransformersSerializationSpec extends SerializationSpecification {
diff --git a/interpreter/shared/src/test/scala/sigmastate/serialization/TupleSerializerSpecification.scala b/interpreter/shared/src/test/scala/sigma/serialization/TupleSerializerSpecification.scala
similarity index 85%
rename from interpreter/shared/src/test/scala/sigmastate/serialization/TupleSerializerSpecification.scala
rename to interpreter/shared/src/test/scala/sigma/serialization/TupleSerializerSpecification.scala
index c38a6fe94d..e72890cbb7 100644
--- a/interpreter/shared/src/test/scala/sigmastate/serialization/TupleSerializerSpecification.scala
+++ b/interpreter/shared/src/test/scala/sigma/serialization/TupleSerializerSpecification.scala
@@ -1,6 +1,6 @@
-package sigmastate.serialization
+package sigma.serialization
-import sigmastate.Values.{FalseLeaf, IntConstant, Tuple}
+import sigma.ast.{FalseLeaf, IntConstant, Tuple}
class TupleSerializerSpecification extends TableSerializationSpecification {
diff --git a/interpreter/shared/src/test/scala/sigmastate/serialization/TwoArgumentSerializerSpecification.scala b/interpreter/shared/src/test/scala/sigma/serialization/TwoArgumentSerializerSpecification.scala
similarity index 89%
rename from interpreter/shared/src/test/scala/sigmastate/serialization/TwoArgumentSerializerSpecification.scala
rename to interpreter/shared/src/test/scala/sigma/serialization/TwoArgumentSerializerSpecification.scala
index 8d7a4dfa88..e0c04e33b8 100644
--- a/interpreter/shared/src/test/scala/sigmastate/serialization/TwoArgumentSerializerSpecification.scala
+++ b/interpreter/shared/src/test/scala/sigma/serialization/TwoArgumentSerializerSpecification.scala
@@ -1,12 +1,12 @@
-package sigmastate.serialization
+package sigma.serialization
-import sigmastate.Values.{BigIntConstant, ByteArrayConstant, GroupElementConstant, LongConstant}
-import sigmastate._
-import sigmastate.Values._
-import sigmastate.serialization.OpCodes.OpCode
-import sigmastate.utxo.Append
-import OpCodes._
import scorex.util.encode.ZigZagEncoder.encodeZigZagLong
+import sigma.ast.ByteArrayConstant.ByteArrayTypeCode
+import sigma.ast.syntax.{BigIntConstant, GroupElementConstant, LongConstant}
+import sigma.ast._
+import sigmastate._
+import sigma.serialization.OpCodes._
+import sigma.serialization.ValueCodes.OpCode
class TwoArgumentSerializerSpecification extends TableSerializationSpecification {
diff --git a/interpreter/shared/src/test/scala/sigmastate/serialization/TypeSerializerSpecification.scala b/interpreter/shared/src/test/scala/sigma/serialization/TypeSerializerSpecification.scala
similarity index 98%
rename from interpreter/shared/src/test/scala/sigmastate/serialization/TypeSerializerSpecification.scala
rename to interpreter/shared/src/test/scala/sigma/serialization/TypeSerializerSpecification.scala
index 6521ec55f7..6419faf364 100644
--- a/interpreter/shared/src/test/scala/sigmastate/serialization/TypeSerializerSpecification.scala
+++ b/interpreter/shared/src/test/scala/sigma/serialization/TypeSerializerSpecification.scala
@@ -1,8 +1,8 @@
-package sigmastate.serialization
+package sigma.serialization
import org.scalacheck.Arbitrary._
import org.scalatest.Assertion
-import sigmastate._
+import sigma.ast._
class TypeSerializerSpecification extends SerializationSpecification {
diff --git a/interpreter/shared/src/test/scala/sigmastate/serialization/UpcastOnDeserializationSpecification.scala b/interpreter/shared/src/test/scala/sigma/serialization/UpcastOnDeserializationSpecification.scala
similarity index 74%
rename from interpreter/shared/src/test/scala/sigmastate/serialization/UpcastOnDeserializationSpecification.scala
rename to interpreter/shared/src/test/scala/sigma/serialization/UpcastOnDeserializationSpecification.scala
index de54b62295..5a2f4dc1eb 100644
--- a/interpreter/shared/src/test/scala/sigmastate/serialization/UpcastOnDeserializationSpecification.scala
+++ b/interpreter/shared/src/test/scala/sigma/serialization/UpcastOnDeserializationSpecification.scala
@@ -1,10 +1,6 @@
-package sigmastate.serialization
+package sigma.serialization
-import org.ergoplatform.Outputs
-import sigmastate.Values.{ByteConstant, IntConstant, LongConstant}
-import sigmastate.lang.CheckingSigmaBuilder
-import sigmastate.utxo.ByIndex
-import sigmastate.{SInt, SLong, Upcast}
+import sigma.ast._
class UpcastOnDeserializationSpecification extends SerializationSpecification {
import CheckingSigmaBuilder._
diff --git a/interpreter/shared/src/test/scala/sigmastate/serialization/generators/ConcreteCollectionGenerators.scala b/interpreter/shared/src/test/scala/sigma/serialization/generators/ConcreteCollectionGenerators.scala
similarity index 88%
rename from interpreter/shared/src/test/scala/sigmastate/serialization/generators/ConcreteCollectionGenerators.scala
rename to interpreter/shared/src/test/scala/sigma/serialization/generators/ConcreteCollectionGenerators.scala
index 08ae08bd3f..a8d8c8bbf0 100644
--- a/interpreter/shared/src/test/scala/sigmastate/serialization/generators/ConcreteCollectionGenerators.scala
+++ b/interpreter/shared/src/test/scala/sigma/serialization/generators/ConcreteCollectionGenerators.scala
@@ -1,8 +1,8 @@
-package sigmastate.serialization.generators
+package sigma.serialization.generators
import org.scalacheck.{Arbitrary, Gen}
-import sigmastate._
-import sigmastate.Values.{ConcreteCollection, Value, IntConstant}
+import sigma.ast.syntax.IntConstant
+import sigma.ast.{ConcreteCollection, SBoolean, SInt, SSigmaProp, SType, Value}
trait ConcreteCollectionGenerators { self: ObjectGenerators =>
val minCollLength = 1
diff --git a/interpreter/shared/src/test/scala/sigmastate/serialization/generators/ObjectGenerators.scala b/interpreter/shared/src/test/scala/sigma/serialization/generators/ObjectGenerators.scala
similarity index 93%
rename from interpreter/shared/src/test/scala/sigmastate/serialization/generators/ObjectGenerators.scala
rename to interpreter/shared/src/test/scala/sigma/serialization/generators/ObjectGenerators.scala
index 4c57f86246..d4971f88c2 100644
--- a/interpreter/shared/src/test/scala/sigmastate/serialization/generators/ObjectGenerators.scala
+++ b/interpreter/shared/src/test/scala/sigma/serialization/generators/ObjectGenerators.scala
@@ -1,29 +1,35 @@
-package sigmastate.serialization.generators
+package sigma.serialization.generators
import org.ergoplatform.ErgoBox._
-import org.ergoplatform.SigmaConstants.MaxPropositionBytes
+import sigma.data.SigmaConstants.MaxPropositionBytes
import org.ergoplatform.validation._
import org.ergoplatform._
import org.scalacheck.Arbitrary._
import org.scalacheck.Gen.{choose, frequency}
import org.scalacheck.util.Buildable
import org.scalacheck.{Arbitrary, Gen}
-import sigma.data.RType
+import sigma.data._
import scorex.crypto.authds.{ADDigest, ADKey}
import scorex.util.encode.{Base58, Base64}
import scorex.util.{ModifierId, bytesToId}
-import sigmastate.Values._
-import sigmastate.crypto.DLogProtocol.ProveDlog
-import sigmastate.crypto.{CryptoConstants, ProveDHTuple}
-import sigmastate.eval.Extensions._
-import sigmastate.eval.{CostingBox, SigmaDsl, _}
-import sigmastate.crypto.CryptoConstants.{EcPointType, dlogGroup}
-import sigmastate.interpreter.{ContextExtension, ProverResult}
-import sigmastate.lang.TransformingSigmaBuilder._
+import sigma.ast._
+import sigma.ast.syntax._
+import sigmastate.eval._
+import sigma.crypto.CryptoConstants.dlogGroup
+import TransformingSigmaBuilder._
import sigmastate._
-import sigmastate.utxo._
import sigma.Coll
+import sigma.Extensions.ArrayOps
import sigma._
+import sigma.ast.syntax.SigmaPropValue
+import sigma.crypto.{CryptoConstants, EcPointType}
+import sigma.util.Extensions.EcpOps
+import sigma.validation.{ChangedRule, DisabledRule, EnabledRule, ReplacedRule, RuleStatus}
+import sigma.validation.ValidationRules.FirstRuleId
+import ErgoTree.ZeroHeader
+import sigma.eval.Extensions.{EvalIterableOps, SigmaBooleanOps}
+import sigma.eval.SigmaDsl
+import sigma.interpreter.{ContextExtension, ProverResult}
import java.math.BigInteger
import scala.collection.compat.immutable.ArraySeq
@@ -70,11 +76,9 @@ trait ObjectGenerators extends TypeGenerators
implicit lazy val arbBoxConstant: Arbitrary[BoxConstant] = Arbitrary(boxConstantGen)
implicit lazy val arbAvlTreeConstant: Arbitrary[AvlTreeConstant] = Arbitrary(avlTreeConstantGen)
implicit lazy val arbBigIntConstant: Arbitrary[BigIntConstant] = Arbitrary(bigIntConstGen)
- implicit lazy val arbTaggedInt: Arbitrary[TaggedInt] = Arbitrary(taggedVar[SInt.type])
- implicit lazy val arbTaggedLong: Arbitrary[TaggedLong] = Arbitrary(taggedVar[SLong.type])
- implicit lazy val arbTaggedBox: Arbitrary[TaggedBox] = Arbitrary(taggedVar[SBox.type])
- implicit lazy val arbTaggedAvlTree: Arbitrary[TaggedAvlTree] = Arbitrary(taggedAvlTreeGen)
- implicit lazy val arbProveDlog: Arbitrary[ProveDlog] = Arbitrary(proveDlogGen)
+ implicit lazy val arbGetVarBox: Arbitrary[BoxValue] = Arbitrary(getVar[SBox.type])
+ implicit lazy val arbGetVarAvlTree : Arbitrary[AvlTreeValue] = Arbitrary(getVarAvlTreeGen)
+ implicit lazy val arbProveDlog : Arbitrary[ProveDlog] = Arbitrary(proveDlogGen)
implicit lazy val arbProveDHT: Arbitrary[ProveDHTuple] = Arbitrary(proveDHTGen)
implicit lazy val arbRegisterIdentifier: Arbitrary[RegisterId] = Arbitrary(registerIdentifierGen)
implicit lazy val arbBigInteger: Arbitrary[BigInteger] = Arbitrary(Arbitrary.arbBigInt.arbitrary.map(_.bigInteger))
@@ -155,17 +159,17 @@ trait ObjectGenerators extends TypeGenerators
lazy val groupElementConstGen: Gen[GroupElementConstant] = for {
p <- groupElementGen
- } yield mkConstant[SGroupElement.type](p, SGroupElement)
+ } yield mkConstant[SGroupElement.type](p.toGroupElement, SGroupElement)
lazy val constantGen: Gen[Constant[SType]] =
Gen.oneOf(booleanConstGen, byteConstGen,
shortConstGen, intConstGen, longConstGen, bigIntConstGen, byteArrayConstGen,
intArrayConstGen, groupElementConstGen).asInstanceOf[Gen[Constant[SType]]]
- def taggedVar[T <: SType](implicit aT: Arbitrary[T]): Gen[TaggedVariable[T]] = for {
+ def getVar[T <: SType](implicit aT: Arbitrary[T]): Gen[Value[T]] = for {
t <- aT.arbitrary
id <- arbByte.arbitrary
- } yield mkTaggedVariable(id, t)
+ } yield mkGetVar(id, t).get
lazy val proveDlogGen: Gen[ProveDlog] = for {v <- groupElementGen} yield ProveDlog(v)
@@ -204,8 +208,8 @@ trait ObjectGenerators extends TypeGenerators
lazy val registerIdentifierGen: Gen[RegisterId] = Gen.oneOf(R0, R1, R2, R3, R4, R5, R6, R7, R8, R9)
- lazy val taggedAvlTreeGen: Gen[TaggedAvlTree] =
- arbByte.arbitrary.map { v => TaggedAvlTree(v).asInstanceOf[TaggedAvlTree] }
+ lazy val getVarAvlTreeGen: Gen[AvlTreeValue] =
+ arbByte.arbitrary.map { v => mkGetVar(v, SAvlTree).get }
lazy val evaluatedValueGen: Gen[EvaluatedValue[SType]] =
Gen.oneOf(booleanConstGen.asInstanceOf[Gen[EvaluatedValue[SType]]], byteArrayConstGen, longConstGen)
@@ -321,19 +325,19 @@ trait ObjectGenerators extends TypeGenerators
booleanConstGen,
bigIntConstGen,
groupElementConstGen,
- taggedVar[SInt.type],
- taggedVar[SLong.type],
- taggedVar[SBox.type],
- taggedVar(Arbitrary(sTupleGen(2, 10)))
+ getVar[SInt.type],
+ getVar[SLong.type],
+ getVar[SBox.type],
+ getVar(Arbitrary(sTupleGen(2, 10)))
))
} yield mkTuple(values).asInstanceOf[Tuple]
lazy val modifierIdGen: Gen[ModifierId] =
- arrayOfN(CryptoConstants.hashLength, arbByte.arbitrary)
+ arrayOfN(sigma.crypto.hashLength, arbByte.arbitrary)
.map(bytesToId)
lazy val modifierIdBytesGen: Gen[Coll[Byte]] =
- collOfN(CryptoConstants.hashLength, arbByte.arbitrary)
+ collOfN(sigma.crypto.hashLength, arbByte.arbitrary)
val MaxTokens = 10
@@ -372,7 +376,7 @@ trait ObjectGenerators extends TypeGenerators
creationHeight <- heightGen
} yield new ErgoBoxCandidate(l, b, creationHeight, tokens, ar)
- lazy val boxConstantGen: Gen[BoxConstant] = ergoBoxGen.map { v => BoxConstant(CostingBox(v)) }
+ lazy val boxConstantGen: Gen[BoxConstant] = ergoBoxGen.map { v => BoxConstant(CBox(v)) }
lazy val digest32Gen: Gen[TokenId] = for {
bytes <- collOfN(TokenId.size, arbByte.arbitrary)
@@ -477,23 +481,23 @@ trait ObjectGenerators extends TypeGenerators
} yield mkSizeOf(input).asInstanceOf[SizeOf[SInt.type]]
lazy val extractAmountGen: Gen[ExtractAmount] =
- arbTaggedBox.arbitrary.map { b => mkExtractAmount(b).asInstanceOf[ExtractAmount] }
+ arbGetVarBox.arbitrary.map { b => mkExtractAmount(b).asInstanceOf[ExtractAmount] }
lazy val extractScriptBytesGen: Gen[ExtractScriptBytes] =
- arbTaggedBox.arbitrary.map { b => mkExtractScriptBytes(b).asInstanceOf[ExtractScriptBytes] }
+ arbGetVarBox.arbitrary.map { b => mkExtractScriptBytes(b).asInstanceOf[ExtractScriptBytes] }
lazy val extractBytesGen: Gen[ExtractBytes] =
- arbTaggedBox.arbitrary.map { b => mkExtractBytes(b).asInstanceOf[ExtractBytes] }
+ arbGetVarBox.arbitrary.map { b => mkExtractBytes(b).asInstanceOf[ExtractBytes] }
lazy val extractBytesWithNoRefGen: Gen[ExtractBytesWithNoRef] =
- arbTaggedBox.arbitrary.map { b =>
+ arbGetVarBox.arbitrary.map { b =>
mkExtractBytesWithNoRef(b).asInstanceOf[ExtractBytesWithNoRef]
}
lazy val extractIdGen: Gen[ExtractId] =
- arbTaggedBox.arbitrary.map { b => mkExtractId(b).asInstanceOf[ExtractId] }
+ arbGetVarBox.arbitrary.map { b => mkExtractId(b).asInstanceOf[ExtractId] }
lazy val extractRegisterAsGen: Gen[ExtractRegisterAs[SInt.type]] = for {
- input <- arbTaggedBox.arbitrary
+ input <- arbGetVarBox.arbitrary
r <- arbRegisterIdentifier.arbitrary
} yield ExtractRegisterAs(input, r)(SInt)
lazy val extractCreationInfoGen: Gen[ExtractCreationInfo] =
- arbTaggedBox.arbitrary.map { b => mkExtractCreationInfo(b).asInstanceOf[ExtractCreationInfo] }
+ arbGetVarBox.arbitrary.map { b => mkExtractCreationInfo(b).asInstanceOf[ExtractCreationInfo] }
lazy val deserializeContextGen: Gen[DeserializeContext[SBoolean.type]] =
Arbitrary.arbitrary[Byte].map(b =>
@@ -678,16 +682,16 @@ trait ObjectGenerators extends TypeGenerators
lazy val ergoTreeGen: Gen[ErgoTree] = for {
sigmaBoolean <- Gen.delay(sigmaBooleanGen)
propWithConstants <- Gen.delay(logicalExprTreeNodeGen(Seq(AND.apply, OR.apply, XorOf.apply)).map(_.toSigmaProp))
- prop <- Gen.oneOf(propWithConstants, sigmaBoolean.toSigmaProp)
- treeBuilder <- Gen.oneOf(Seq[SigmaPropValue => ErgoTree](ErgoTree.withSegregation,
- ErgoTree.withoutSegregation))
+ prop <- Gen.oneOf(propWithConstants, sigmaBoolean.toSigmaPropValue)
+ treeBuilder <- Gen.oneOf(Seq[SigmaPropValue => ErgoTree](ErgoTree.withSegregation(ZeroHeader, _),
+ ErgoTree.withoutSegregation(ZeroHeader, _)))
} yield treeBuilder(prop)
lazy val ergoTreeWithSegregationGen: Gen[ErgoTree] = for {
sigmaBoolean <- Gen.delay(sigmaBooleanGen)
propWithConstants <- Gen.delay(logicalExprTreeNodeGen(Seq(AND.apply, OR.apply, XorOf.apply)).map(_.toSigmaProp))
- prop <- Gen.oneOf(propWithConstants, sigmaBoolean.toSigmaProp)
- } yield ErgoTree.withSegregation(prop)
+ prop <- Gen.oneOf(propWithConstants, sigmaBoolean.toSigmaPropValue)
+ } yield ErgoTree.withSegregation(ZeroHeader, prop)
def headerGen(stateRoot: AvlTree, parentId: Coll[Byte]): Gen[Header] = for {
id <- modifierIdBytesGen
@@ -704,7 +708,7 @@ trait ObjectGenerators extends TypeGenerators
powDistance <- arbBigInt.arbitrary
votes <- minerVotesGen
} yield CHeader(id, version, parentId, adProofsRoot, stateRoot, transactionRoot, timestamp, nBits,
- height, extensionRoot, minerPk, powOnetimePk, powNonce, powDistance, votes)
+ height, extensionRoot, minerPk.toGroupElement, powOnetimePk.toGroupElement, powNonce, powDistance, votes)
lazy val headerGen: Gen[Header] = for {
stateRoot <- avlTreeGen
@@ -734,7 +738,7 @@ trait ObjectGenerators extends TypeGenerators
height <- heightGen
minerPk <- groupElementGen
votes <- minerVotesGen
- } yield CPreHeader(version, parentId, timestamp, nBits, height, minerPk, votes)
+ } yield CPreHeader(version, parentId, timestamp, nBits, height, minerPk.toGroupElement, votes)
lazy val preHeaderGen: Gen[PreHeader] = for {
parentId <- modifierIdBytesGen
diff --git a/interpreter/shared/src/test/scala/sigmastate/serialization/generators/OpcodesGen.scala b/interpreter/shared/src/test/scala/sigma/serialization/generators/OpcodesGen.scala
similarity index 59%
rename from interpreter/shared/src/test/scala/sigmastate/serialization/generators/OpcodesGen.scala
rename to interpreter/shared/src/test/scala/sigma/serialization/generators/OpcodesGen.scala
index f0b3ef092b..c0bf5b97a2 100644
--- a/interpreter/shared/src/test/scala/sigmastate/serialization/generators/OpcodesGen.scala
+++ b/interpreter/shared/src/test/scala/sigma/serialization/generators/OpcodesGen.scala
@@ -1,7 +1,8 @@
-package sigmastate.serialization.generators
+package sigma.serialization.generators
import org.scalacheck.Gen
-import sigmastate.serialization.OpCodes._
+import sigma.serialization.OpCodes._
+import sigma.serialization.ValueCodes.OpCode
trait OpcodesGen {
diff --git a/interpreter/shared/src/test/scala/sigmastate/serialization/generators/RelationGenerators.scala b/interpreter/shared/src/test/scala/sigma/serialization/generators/RelationGenerators.scala
similarity index 78%
rename from interpreter/shared/src/test/scala/sigmastate/serialization/generators/RelationGenerators.scala
rename to interpreter/shared/src/test/scala/sigma/serialization/generators/RelationGenerators.scala
index fc7193a4f5..0637f211d7 100644
--- a/interpreter/shared/src/test/scala/sigmastate/serialization/generators/RelationGenerators.scala
+++ b/interpreter/shared/src/test/scala/sigma/serialization/generators/RelationGenerators.scala
@@ -1,14 +1,14 @@
-package sigmastate.serialization.generators
+package sigma.serialization.generators
import org.scalacheck.{Arbitrary, Gen}
-import sigmastate.Values.{FalseLeaf, TrueLeaf}
-import sigmastate.{If, SInt, TreeLookup}
+import sigma.ast.{If, SInt, TreeLookup}
+import sigma.ast.{FalseLeaf, TrueLeaf}
trait RelationGenerators {
this: ObjectGenerators with ConcreteCollectionGenerators =>
val treeLookupGen: Gen[TreeLookup] = for {
- t <- arbTaggedAvlTree.arbitrary
+ t <- arbGetVarAvlTree.arbitrary
b1 <- arbByteArrayConstant.arbitrary
b2 <- arbByteArrayConstant.arbitrary
} yield TreeLookup(t, b1, b2)
diff --git a/interpreter/shared/src/test/scala/sigmastate/serialization/generators/TransformerGenerators.scala b/interpreter/shared/src/test/scala/sigma/serialization/generators/TransformerGenerators.scala
similarity index 81%
rename from interpreter/shared/src/test/scala/sigmastate/serialization/generators/TransformerGenerators.scala
rename to interpreter/shared/src/test/scala/sigma/serialization/generators/TransformerGenerators.scala
index 87256fea4e..22b51763fd 100644
--- a/interpreter/shared/src/test/scala/sigmastate/serialization/generators/TransformerGenerators.scala
+++ b/interpreter/shared/src/test/scala/sigma/serialization/generators/TransformerGenerators.scala
@@ -1,4 +1,4 @@
-package sigmastate.serialization.generators
+package sigma.serialization.generators
import org.ergoplatform.validation.ValidationSpecification
diff --git a/interpreter/shared/src/test/scala/sigmastate/serialization/generators/TypeGenerators.scala b/interpreter/shared/src/test/scala/sigma/serialization/generators/TypeGenerators.scala
similarity index 94%
rename from interpreter/shared/src/test/scala/sigmastate/serialization/generators/TypeGenerators.scala
rename to interpreter/shared/src/test/scala/sigma/serialization/generators/TypeGenerators.scala
index 2582d1305c..81073c4849 100644
--- a/interpreter/shared/src/test/scala/sigmastate/serialization/generators/TypeGenerators.scala
+++ b/interpreter/shared/src/test/scala/sigma/serialization/generators/TypeGenerators.scala
@@ -1,8 +1,8 @@
-package sigmastate.serialization.generators
+package sigma.serialization.generators
-import org.scalacheck.{Gen, Arbitrary}
+import org.scalacheck.{Arbitrary, Gen}
import org.scalacheck.Arbitrary.arbString
-import sigmastate._
+import sigma.ast._
trait TypeGenerators {
implicit val booleanTypeGen: Gen[SBoolean.type] = Gen.const(SBoolean)
diff --git a/interpreter/shared/src/test/scala/sigmastate/CalcSha256Specification.scala b/interpreter/shared/src/test/scala/sigmastate/CalcSha256Specification.scala
index 9fc8333784..ce070c6760 100644
--- a/interpreter/shared/src/test/scala/sigmastate/CalcSha256Specification.scala
+++ b/interpreter/shared/src/test/scala/sigmastate/CalcSha256Specification.scala
@@ -2,7 +2,9 @@ package sigmastate
import org.scalatest.prop.TableFor2
import scorex.util.encode.Base16
-import sigmastate.Values.{ByteArrayConstant, CollectionConstant}
+import sigma.ast.{ByteArrayConstant, CalcSha256, EQ, SByte}
+import sigma.ast.syntax.CollectionConstant
+import sigma.data.TrivialProp
import sigmastate.helpers.{ContextEnrichingTestProvingInterpreter, ErgoLikeContextTesting, TestingCommons}
class CalcSha256Specification extends TestingCommons
diff --git a/interpreter/shared/src/test/scala/sigmastate/CrossVersionProps.scala b/interpreter/shared/src/test/scala/sigmastate/CrossVersionProps.scala
index 0c4056dcee..87101a1f71 100644
--- a/interpreter/shared/src/test/scala/sigmastate/CrossVersionProps.scala
+++ b/interpreter/shared/src/test/scala/sigmastate/CrossVersionProps.scala
@@ -2,18 +2,20 @@ package sigmastate
import debox.cfor
import org.scalactic.source.Position
+
import scala.util.DynamicVariable
import org.scalatest.Tag
-import sigmastate.eval.Profiler
+import sigmastate.eval.CProfiler
import org.scalatest.propspec.AnyPropSpecLike
+import sigma.VersionContext
trait CrossVersionProps extends AnyPropSpecLike with TestsBase {
/** Number of times each test property is warmed up (i.e. executed before final execution). */
def perTestWarmUpIters: Int = 0
- private[sigmastate] val _warmupProfiler = new DynamicVariable[Option[Profiler]](None)
+ private[sigmastate] val _warmupProfiler = new DynamicVariable[Option[CProfiler]](None)
- def warmupProfiler: Option[Profiler] = _warmupProfiler.value
+ def warmupProfiler: Option[CProfiler] = _warmupProfiler.value
override protected def property(testName: String, testTags: Tag*)
(testFun: => Any)
@@ -21,7 +23,7 @@ trait CrossVersionProps extends AnyPropSpecLike with TestsBase {
super.property(testName, testTags: _*) {
// do warmup if necessary
if (perTestWarmUpIters > 0) {
- _warmupProfiler.withValue(Some(new Profiler)) {
+ _warmupProfiler.withValue(Some(new CProfiler)) {
cfor(0)(_ < perTestWarmUpIters, _ + 1) { _ =>
testFun_Run(testName, testFun)
}
@@ -29,7 +31,9 @@ trait CrossVersionProps extends AnyPropSpecLike with TestsBase {
System.gc()
}
forEachScriptAndErgoTreeVersion(activatedVersions, ergoTreeVersions) {
- testFun_Run(testName, testFun)
+ VersionContext.withVersions(activatedVersionInTests, ergoTreeVersionInTests) {
+ testFun_Run(testName, testFun)
+ }
}
}
}
diff --git a/interpreter/shared/src/test/scala/sigmastate/CryptoFacadeSpecification.scala b/interpreter/shared/src/test/scala/sigmastate/CryptoFacadeSpecification.scala
index 49fa4534bd..375ef3f4e5 100644
--- a/interpreter/shared/src/test/scala/sigmastate/CryptoFacadeSpecification.scala
+++ b/interpreter/shared/src/test/scala/sigmastate/CryptoFacadeSpecification.scala
@@ -5,7 +5,7 @@ import org.scalatest.matchers.should.Matchers
import org.scalatest.propspec.AnyPropSpec
import org.scalatestplus.scalacheck.ScalaCheckPropertyChecks
import scorex.util.encode.Base16
-import sigmastate.crypto.CryptoFacade
+import sigma.crypto.CryptoFacade
import java.math.BigInteger
diff --git a/interpreter/shared/src/test/scala/sigmastate/JitCostSpecification.scala b/interpreter/shared/src/test/scala/sigmastate/JitCostSpecification.scala
index 4a434624a8..82ebe9a297 100644
--- a/interpreter/shared/src/test/scala/sigmastate/JitCostSpecification.scala
+++ b/interpreter/shared/src/test/scala/sigmastate/JitCostSpecification.scala
@@ -1,5 +1,6 @@
package sigmastate
+import sigma.ast.JitCost
import sigmastate.helpers.TestingCommons
import scala.util.{Failure, Try}
diff --git a/interpreter/shared/src/test/scala/sigmastate/TestsBase.scala b/interpreter/shared/src/test/scala/sigmastate/TestsBase.scala
index 57ecd5e5e8..af9675c7f8 100644
--- a/interpreter/shared/src/test/scala/sigmastate/TestsBase.scala
+++ b/interpreter/shared/src/test/scala/sigmastate/TestsBase.scala
@@ -1,9 +1,12 @@
package sigmastate
import org.scalatest.matchers.should.Matchers
-import sigmastate.Values.{ErgoTree, SigmaBoolean, SigmaPropValue}
+import sigma.ast.syntax.SigmaPropValue
import org.ergoplatform.ErgoTreePredef
import sigma.VersionTesting
+import sigma.ast.ErgoTree
+import sigma.data.SigmaBoolean
+import sigma.ast.ErgoTree.{HeaderType, ZeroHeader}
trait TestsBase extends Matchers with VersionTesting {
/** Set this to true to enable debug console output in tests */
@@ -15,7 +18,7 @@ trait TestsBase extends Matchers with VersionTesting {
/** Current ErgoTree header flags assigned dynamically using [[CrossVersionProps]] and
* ergoTreeVersionInTests.
*/
- def ergoTreeHeaderInTests: Byte = ErgoTree.headerWithVersion(ergoTreeVersionInTests)
+ def ergoTreeHeaderInTests: HeaderType = ErgoTree.headerWithVersion(ZeroHeader, ergoTreeVersionInTests)
/** Obtains [[ErgoTree]] which corresponds to True proposition using current
* ergoTreeHeaderInTests. */
diff --git a/interpreter/shared/src/test/scala/sigmastate/crypto/GroupLawsSpecification.scala b/interpreter/shared/src/test/scala/sigmastate/crypto/GroupLawsSpecification.scala
index d177a26e4c..a5762444f6 100644
--- a/interpreter/shared/src/test/scala/sigmastate/crypto/GroupLawsSpecification.scala
+++ b/interpreter/shared/src/test/scala/sigmastate/crypto/GroupLawsSpecification.scala
@@ -2,10 +2,9 @@ package sigmastate.crypto
import java.math.BigInteger
import org.scalacheck.Gen
-import sigmastate.crypto.CryptoConstants
-import CryptoConstants.EcPointType
import org.scalatest.propspec.AnyPropSpec
import org.scalatestplus.scalacheck.ScalaCheckPropertyChecks
+import sigma.crypto.{CryptoConstants, CryptoFacade, EcPointType, Ecp}
import sigmastate.TestsBase
import sigmastate.utils.Helpers
diff --git a/interpreter/shared/src/test/scala/sigmastate/crypto/SigningSpecification.scala b/interpreter/shared/src/test/scala/sigmastate/crypto/SigningSpecification.scala
index 724a0171dc..16999e7457 100644
--- a/interpreter/shared/src/test/scala/sigmastate/crypto/SigningSpecification.scala
+++ b/interpreter/shared/src/test/scala/sigmastate/crypto/SigningSpecification.scala
@@ -2,13 +2,13 @@ package sigmastate.crypto
import org.scalacheck.Gen
import scorex.util.encode.Base16
-import sigmastate.{AtLeast, COR, CAND}
-import sigmastate.Values.SigmaBoolean
+import sigma.ast.{AtLeast, ErgoTree}
+import sigma.data.{CAND, COR, ProveDHTuple, SigmaBoolean}
+import sigma.interpreter.{ContextExtension, ProverResult}
+import sigma.serialization.ProveDHTupleSerializer
import sigmastate.crypto.DLogProtocol.DLogProverInput
import sigmastate.helpers.{ErgoLikeTestInterpreter, ErgoLikeTestProvingInterpreter, TestingCommons}
-import sigmastate.interpreter.{HintsBag, ContextExtension, ProverResult}
-import sigmastate.serialization.transformers.ProveDHTupleSerializer
-import sigmastate.crypto.ProveDHTuple
+import sigmastate.interpreter.HintsBag
class SigningSpecification extends TestingCommons {
@@ -24,7 +24,9 @@ class SigningSpecification extends TestingCommons {
// check that signature is correct
val verifier = new ErgoLikeTestInterpreter
val proverResult = ProverResult(signature, ContextExtension.empty)
- verifier.verify(sk.publicImage, fakeContext, proverResult, msg).get._1 shouldBe true
+ verifier.verify(
+ ErgoTree.fromSigmaBoolean(sk.publicImage),
+ fakeContext, proverResult, msg).get._1 shouldBe true
// print one more random vector for debug purposes
printSimpleSignature(msg: Array[Byte])
@@ -38,7 +40,7 @@ class SigningSpecification extends TestingCommons {
// check that signature is correct
val verifier = new ErgoLikeTestInterpreter
val proverResult = ProverResult(signature, ContextExtension.empty)
- verifier.verify(pdht, fakeContext, proverResult, msg).get._1 shouldBe true
+ verifier.verify(ErgoTree.fromSigmaBoolean(pdht), fakeContext, proverResult, msg).get._1 shouldBe true
}
property("handle improper signature") {
@@ -59,7 +61,7 @@ class SigningSpecification extends TestingCommons {
val verifier = new ErgoLikeTestInterpreter
val proverResult = ProverResult(signature, ContextExtension.empty)
val sigmaTree: SigmaBoolean = CAND(Seq(sk1.publicImage, sk2.publicImage))
- verifier.verify(sigmaTree, fakeContext, proverResult, msg).get._1 shouldBe true
+ verifier.verify(ErgoTree.fromSigmaBoolean(sigmaTree), fakeContext, proverResult, msg).get._1 shouldBe true
}
property("OR signature test vector") {
@@ -71,7 +73,9 @@ class SigningSpecification extends TestingCommons {
val verifier = new ErgoLikeTestInterpreter
val proverResult = ProverResult(signature, ContextExtension.empty)
val sigmaTree: SigmaBoolean = COR(Seq(sk1.publicImage, sk2.publicImage))
- verifier.verify(sigmaTree, fakeContext, proverResult, msg).get._1 shouldBe true
+ verifier.verify(
+ ErgoTree.fromSigmaBoolean(sigmaTree),
+ fakeContext, proverResult, msg).get._1 shouldBe true
}
property("OR with ProveDHT signature test vector") {
@@ -84,7 +88,9 @@ class SigningSpecification extends TestingCommons {
val verifier = new ErgoLikeTestInterpreter
val proverResult = ProverResult(signature, ContextExtension.empty)
val sigmaTree: SigmaBoolean = COR(Seq(sk1.publicImage, pdht))
- verifier.verify(sigmaTree, fakeContext, proverResult, msg).get._1 shouldBe true
+ verifier.verify(
+ ErgoTree.fromSigmaBoolean(sigmaTree),
+ fakeContext, proverResult, msg).get._1 shouldBe true
}
property("AND with OR signature test vector") {
@@ -97,7 +103,9 @@ class SigningSpecification extends TestingCommons {
val verifier = new ErgoLikeTestInterpreter
val proverResult = ProverResult(signature, ContextExtension.empty)
val sigmaTree: SigmaBoolean = CAND(Seq(sk1.publicImage, COR(Seq(sk2.publicImage, sk3.publicImage))))
- verifier.verify(sigmaTree, fakeContext, proverResult, msg).get._1 shouldBe true
+ verifier.verify(
+ ErgoTree.fromSigmaBoolean(sigmaTree),
+ fakeContext, proverResult, msg).get._1 shouldBe true
}
property("OR with AND signature test vector") {
@@ -110,7 +118,9 @@ class SigningSpecification extends TestingCommons {
val verifier = new ErgoLikeTestInterpreter
val proverResult = ProverResult(signature, ContextExtension.empty)
val sigmaTree: SigmaBoolean = COR(Seq(sk1.publicImage, CAND(Seq(sk2.publicImage, sk3.publicImage))))
- verifier.verify(sigmaTree, fakeContext, proverResult, msg).get._1 shouldBe true
+ verifier.verify(
+ ErgoTree.fromSigmaBoolean(sigmaTree),
+ fakeContext, proverResult, msg).get._1 shouldBe true
}
property("threshold signature test vector") {
diff --git a/interpreter/shared/src/test/scala/sigmastate/eval/BasicOpsTests.scala b/interpreter/shared/src/test/scala/sigmastate/eval/BasicOpsTests.scala
index 07b8fdcddb..ba996b0246 100644
--- a/interpreter/shared/src/test/scala/sigmastate/eval/BasicOpsTests.scala
+++ b/interpreter/shared/src/test/scala/sigmastate/eval/BasicOpsTests.scala
@@ -2,18 +2,19 @@ package sigmastate.eval
import org.scalatest.funsuite.AnyFunSuite
import org.scalatest.matchers.should.Matchers
+import sigma.crypto.SecP256K1Group
+import sigma.data.{CSigmaDslBuilder, TrivialProp}
+import sigma.util.Extensions.SigmaBooleanOps
import java.math.BigInteger
-import sigmastate.TrivialProp
-import sigmastate.crypto.SecP256K1Group
import sigma.{ContractsTestkit, SigmaDslBuilder, SigmaProp}
import scala.language.implicitConversions
class BasicOpsTests extends AnyFunSuite with ContractsTestkit with Matchers {
- override val SigmaDsl: SigmaDslBuilder = CostingSigmaDslBuilder
+ override val SigmaDsl: SigmaDslBuilder = CSigmaDslBuilder
- implicit def boolToSigma(b: Boolean): SigmaProp = TrivialProp(b)
+ implicit def boolToSigma(b: Boolean): SigmaProp = TrivialProp(b).toSigmaProp
test("atLeast") {
val props = Colls.fromArray(Array[SigmaProp](false, true, true, false))
diff --git a/interpreter/shared/src/test/scala/sigmastate/helpers/ContextEnrichingProverInterpreter.scala b/interpreter/shared/src/test/scala/sigmastate/helpers/ContextEnrichingProverInterpreter.scala
index f88d30ddcc..2eaac82790 100644
--- a/interpreter/shared/src/test/scala/sigmastate/helpers/ContextEnrichingProverInterpreter.scala
+++ b/interpreter/shared/src/test/scala/sigmastate/helpers/ContextEnrichingProverInterpreter.scala
@@ -1,9 +1,10 @@
package sigmastate.helpers
-import sigmastate.SType
-import sigmastate.Values.{ErgoTree, EvaluatedValue}
+import sigma.ast.{ErgoTree, SType}
+import sigma.ast.EvaluatedValue
+import sigma.interpreter.{ContextExtension, CostedProverResult}
import sigmastate.interpreter.Interpreter.ScriptEnv
-import sigmastate.interpreter.{ContextExtension, CostedProverResult, HintsBag, ProverInterpreter}
+import sigmastate.interpreter.{HintsBag, ProverInterpreter}
import scala.util.Try
diff --git a/interpreter/shared/src/test/scala/sigmastate/helpers/ContextEnrichingTestProvingInterpreter.scala b/interpreter/shared/src/test/scala/sigmastate/helpers/ContextEnrichingTestProvingInterpreter.scala
index 641142f43c..0d4c1904ec 100644
--- a/interpreter/shared/src/test/scala/sigmastate/helpers/ContextEnrichingTestProvingInterpreter.scala
+++ b/interpreter/shared/src/test/scala/sigmastate/helpers/ContextEnrichingTestProvingInterpreter.scala
@@ -1,8 +1,7 @@
package sigmastate.helpers
import scorex.utils.Random
-import sigmastate.SType
-import sigmastate.Values._
+import sigma.ast._
import sigmastate.crypto.DLogProtocol.DLogProverInput
import sigmastate.crypto.DiffieHellmanTupleProverInput
diff --git a/interpreter/shared/src/test/scala/sigmastate/helpers/ErgoLikeContextTesting.scala b/interpreter/shared/src/test/scala/sigmastate/helpers/ErgoLikeContextTesting.scala
index 70f644bd66..a353ff5e46 100644
--- a/interpreter/shared/src/test/scala/sigmastate/helpers/ErgoLikeContextTesting.scala
+++ b/interpreter/shared/src/test/scala/sigmastate/helpers/ErgoLikeContextTesting.scala
@@ -2,14 +2,17 @@ package sigmastate.helpers
import org.ergoplatform.ErgoLikeContext.Height
import org.ergoplatform._
-import org.ergoplatform.validation.{SigmaValidationSettings, ValidationRules}
-import sigmastate.AvlTreeData
-import sigmastate.crypto.CryptoConstants
-import sigmastate.eval._
-import sigmastate.interpreter.ContextExtension
-import sigmastate.interpreter.ErgoTreeEvaluator.DefaultEvalSettings
-import sigmastate.serialization.{GroupElementSerializer, SigmaSerializer}
+import org.ergoplatform.validation.ValidationRules
+import sigma.crypto.CryptoConstants
+import sigma.data.{AvlTreeData, CSigmaDslBuilder}
+import sigma.interpreter.ContextExtension
+import sigma.serialization.GroupElementSerializer
+import sigma.util.Extensions.EcpOps
+import sigma.validation.SigmaValidationSettings
import sigma.{Box, Coll, Colls, Header, PreHeader}
+import sigmastate.eval._
+import sigmastate.interpreter.CErgoTreeEvaluator.DefaultEvalSettings
+import sigma.serialization.SigmaSerializer
object ErgoLikeContextTesting {
/* NO HF PROOF:
@@ -22,14 +25,14 @@ object ErgoLikeContextTesting {
val dummyPubkey: Array[Byte] = GroupElementSerializer.toBytes(CryptoConstants.dlogGroup.generator)
val noBoxes: IndexedSeq[ErgoBox] = IndexedSeq.empty[ErgoBox]
- val noHeaders: Coll[Header] = CostingSigmaDslBuilder.Colls.emptyColl[Header]
+ val noHeaders: Coll[Header] = CSigmaDslBuilder.Colls.emptyColl[Header]
def dummyPreHeader(currentHeight: Height, minerPk: Array[Byte]): PreHeader = CPreHeader(0,
parentId = Colls.emptyColl[Byte],
timestamp = 3,
nBits = 0,
height = currentHeight,
- minerPk = GroupElementSerializer.parse(SigmaSerializer.startReader(minerPk)),
+ minerPk = GroupElementSerializer.parse(SigmaSerializer.startReader(minerPk)).toGroupElement,
votes = Colls.emptyColl[Byte]
)
diff --git a/interpreter/shared/src/test/scala/sigmastate/helpers/ErgoTransactionValidator.scala b/interpreter/shared/src/test/scala/sigmastate/helpers/ErgoTransactionValidator.scala
index 3203dfc13f..afacb3e6ee 100644
--- a/interpreter/shared/src/test/scala/sigmastate/helpers/ErgoTransactionValidator.scala
+++ b/interpreter/shared/src/test/scala/sigmastate/helpers/ErgoTransactionValidator.scala
@@ -1,8 +1,8 @@
package sigmastate.helpers
import org.ergoplatform._
-import sigmastate.interpreter.ErgoTreeEvaluator.DefaultEvalSettings
-import sigmastate.interpreter.EvalSettings
+import sigma.eval.EvalSettings
+import sigmastate.interpreter.CErgoTreeEvaluator.DefaultEvalSettings
import sigmastate.interpreter.Interpreter.{ScriptNameProp, emptyEnv}
import scala.util.{Failure, Success}
diff --git a/interpreter/shared/src/test/scala/sigmastate/helpers/TestingCommons.scala b/interpreter/shared/src/test/scala/sigmastate/helpers/TestingCommons.scala
index 19a8efe608..d92ad87ccd 100644
--- a/interpreter/shared/src/test/scala/sigmastate/helpers/TestingCommons.scala
+++ b/interpreter/shared/src/test/scala/sigmastate/helpers/TestingCommons.scala
@@ -1,15 +1,15 @@
package sigmastate.helpers
-import sigmastate.Values.GroupElementConstant
import org.scalatest.propspec.AnyPropSpec
import sigmastate.TestsBase
import sigmastate.helpers.TestingHelpers.createBox
-import org.scalatestplus.scalacheck.{ScalaCheckPropertyChecks, ScalaCheckDrivenPropertyChecks}
-import sigmastate.eval.SigmaDsl
+import org.scalatestplus.scalacheck.{ScalaCheckDrivenPropertyChecks, ScalaCheckPropertyChecks}
+import sigma.eval.SigmaDsl
import scorex.crypto.hash.Blake2b256
import org.ergoplatform.{ErgoBox, ErgoLikeContext}
import org.scalatest.matchers.should.Matchers
-import sigmastate.crypto.CryptoConstants.EcPointType
+import sigma.ast.syntax.GroupElementConstant
+import sigma.crypto.EcPointType
trait TestingCommons extends AnyPropSpec
with ScalaCheckPropertyChecks
diff --git a/interpreter/shared/src/test/scala/sigmastate/helpers/TestingHelpers.scala b/interpreter/shared/src/test/scala/sigmastate/helpers/TestingHelpers.scala
index c0255b6adc..392e319773 100644
--- a/interpreter/shared/src/test/scala/sigmastate/helpers/TestingHelpers.scala
+++ b/interpreter/shared/src/test/scala/sigmastate/helpers/TestingHelpers.scala
@@ -1,17 +1,13 @@
package sigmastate.helpers
import org.ergoplatform.ErgoBox.{AdditionalRegisters, Token, allZerosModifierId}
-import org.ergoplatform.validation.SigmaValidationSettings
import org.ergoplatform._
import scorex.util.ModifierId
-import sigma.data.{CollOverArray, PairOfCols}
-import sigmastate.AvlTreeData
-import sigmastate.Values.ErgoTree
-import sigmastate.eval._
-import sigmastate.interpreter.ContextExtension
-import sigma.Coll
-import sigma.{Header, PreHeader}
-
+import sigma.ast.ErgoTree
+import sigma.data.{AvlTreeData, CSigmaDslBuilder, CollOverArray, PairOfCols}
+import sigma.interpreter.ContextExtension
+import sigma.validation.SigmaValidationSettings
+import sigma.{Coll, Colls, Header, PreHeader}
import scala.collection.compat.immutable.ArraySeq
// TODO refactor: unification is required between two hierarchies of tests
@@ -28,7 +24,7 @@ object TestingHelpers {
transactionId: ModifierId = allZerosModifierId,
boxIndex: Short = 0): ErgoBox =
new ErgoBox(value, ergoTree,
- CostingSigmaDslBuilder.Colls.fromArray(additionalTokens.toArray[Token]),
+ CSigmaDslBuilder.Colls.fromArray(additionalTokens.toArray[Token]),
additionalRegisters,
transactionId, boxIndex, creationHeight)
@@ -49,7 +45,7 @@ object TestingHelpers {
*/
def cloneColl[A](c: Coll[A]): Coll[A] = (c match {
case c: CollOverArray[_] =>
- new CollOverArray(c.toArray.clone(), SigmaDsl.Colls)(c.tItem)
+ new CollOverArray(c.toArray.clone(), Colls)(c.tItem)
case ps: PairOfCols[_,_] =>
new PairOfCols(cloneColl(ps.ls), cloneColl(ps.rs))
}).asInstanceOf[Coll[A]]
diff --git a/interpreter/shared/src/test/scala/sigmastate/serialization/TaggedVariableSerializerSpecification.scala b/interpreter/shared/src/test/scala/sigmastate/serialization/TaggedVariableSerializerSpecification.scala
deleted file mode 100644
index af0e04cf3b..0000000000
--- a/interpreter/shared/src/test/scala/sigmastate/serialization/TaggedVariableSerializerSpecification.scala
+++ /dev/null
@@ -1,24 +0,0 @@
-package sigmastate.serialization
-
-import sigmastate.Values._
-import OpCodes._
-import sigmastate.SBox
-
-class TaggedVariableSerializerSpecification extends SerializationSpecification {
-
- property("TaggedVariable: TaggedInt serializer round trip") {
- forAll { ti: TaggedInt =>
- roundTripTest(ti)
- }
- }
-
- property("TaggedVariable: TaggedBox serializer round trip") {
- forAll { tb: TaggedBox =>
- roundTripTest(tb)
- }
- }
-
- property("TaggedVariable deserialize from predefined bytes") {
- predefinedBytesTest(TaggedBox(10), Array(TaggedVariableCode, 10, SBox.typeCode))
- }
-}
diff --git a/interpreter/shared/src/test/scala/sigmastate/utils/HelpersTests.scala b/interpreter/shared/src/test/scala/sigmastate/utils/HelpersTests.scala
index 3325035bbd..b02c489b08 100644
--- a/interpreter/shared/src/test/scala/sigmastate/utils/HelpersTests.scala
+++ b/interpreter/shared/src/test/scala/sigmastate/utils/HelpersTests.scala
@@ -1,11 +1,11 @@
package sigmastate.utils
-import sigmastate.serialization.generators.ObjectGenerators
+import sigma.serialization.generators.ObjectGenerators
import Helpers._
import org.scalatest.matchers.should.Matchers
import org.scalatest.propspec.AnyPropSpec
import org.scalatestplus.scalacheck.ScalaCheckPropertyChecks
-import sigmastate.eval.Extensions.ArrayOps
+import sigma.Extensions.ArrayOps
class HelpersTests extends AnyPropSpec with ScalaCheckPropertyChecks with Matchers with ObjectGenerators {
property("xorU") {
diff --git a/interpreter/shared/src/test/scala/sigmastate/utils/SparseArrayContainerSpecification.scala b/interpreter/shared/src/test/scala/sigmastate/utils/SparseArrayContainerSpecification.scala
index 0f6b69b78f..e45bc00e70 100644
--- a/interpreter/shared/src/test/scala/sigmastate/utils/SparseArrayContainerSpecification.scala
+++ b/interpreter/shared/src/test/scala/sigmastate/utils/SparseArrayContainerSpecification.scala
@@ -4,7 +4,8 @@ import org.scalacheck.{Arbitrary, Gen}
import org.scalatest.matchers.should.Matchers
import org.scalatest.propspec.AnyPropSpec
import org.scalatestplus.scalacheck.ScalaCheckPropertyChecks
-import sigmastate.serialization.generators.ObjectGenerators
+import sigma.serialization.generators.ObjectGenerators
+import sigma.utils.SparseArrayContainer
class SparseArrayContainerSpecification extends AnyPropSpec
with ObjectGenerators
diff --git a/interpreter/shared/src/test/scala/sigmastate/utxo/ProverSpecification.scala b/interpreter/shared/src/test/scala/sigmastate/utxo/ProverSpecification.scala
index 1334ee520f..8b560c523d 100644
--- a/interpreter/shared/src/test/scala/sigmastate/utxo/ProverSpecification.scala
+++ b/interpreter/shared/src/test/scala/sigmastate/utxo/ProverSpecification.scala
@@ -2,11 +2,12 @@ package sigmastate.utxo
import org.ergoplatform.ErgoLikeInterpreter
import scorex.crypto.hash.Blake2b256
-import sigmastate.Values.SigmaBoolean
+import sigma.crypto.SecP256K1Group
+import sigma.data.{CAND, COR, CTHRESHOLD, SigmaBoolean, TrivialProp}
+import sigma.exceptions.InterpreterException
import sigmastate._
import sigmastate.crypto.DLogProtocol.FirstDLogProverMessage
-import sigmastate.crypto.{FirstDHTupleProverMessage, SecP256K1Group}
-import sigmastate.exceptions.InterpreterException
+import sigmastate.crypto.FirstDHTupleProverMessage
import sigmastate.helpers.{ErgoLikeTestProvingInterpreter, TestingCommons}
import sigmastate.interpreter.{HintsBag, ProverInterpreter}
diff --git a/interpreter/shared/src/test/scala/special/sigma/ContractsTestkit.scala b/interpreter/shared/src/test/scala/special/sigma/ContractsTestkit.scala
index a1226b1d03..720223ee3a 100644
--- a/interpreter/shared/src/test/scala/special/sigma/ContractsTestkit.scala
+++ b/interpreter/shared/src/test/scala/special/sigma/ContractsTestkit.scala
@@ -1,10 +1,10 @@
package sigma
-import sigma.data.RType
-import sigmastate.Values.ErgoTree
-import sigmastate.{AvlTreeData, Values}
+import sigma.Extensions.ArrayOps
+import sigma.ast.ErgoTree
+import sigma.ast.syntax.TrueSigmaProp
+import sigma.data.{AvlTreeData, RType}
import sigmastate.eval._
-import sigmastate.eval.Extensions._
import sigmastate.helpers.TestingHelpers._
import sigma.data._
@@ -22,7 +22,7 @@ trait ContractsTestkit {
val R8 = 8.toByte;
val R9 = 9.toByte;
val Colls = new CollOverArrayBuilder
- val SigmaDsl: SigmaDslBuilder = CostingSigmaDslBuilder
+ val SigmaDsl: SigmaDslBuilder = CSigmaDslBuilder
val noRegisters = collection[AnyValue]()
val noBytes = collection[Byte]()
val noInputs = Array[Box]()
@@ -30,7 +30,7 @@ trait ContractsTestkit {
val dummyPubkey: Array[Byte] = Array.fill(32)(0: Byte)
val dummyADDigest: Coll[Byte] = Colls.fromArray(Array.fill(33)(0: Byte))
val emptyAvlTree = new CAvlTree(AvlTreeData.dummy)
- val noHeaders = CostingSigmaDslBuilder.Colls.emptyColl[Header]
+ val noHeaders = CSigmaDslBuilder.Colls.emptyColl[Header]
val dummyPreHeader: PreHeader = null
/** Create collection from array of items */
@@ -62,16 +62,16 @@ trait ContractsTestkit {
def newAliceBox(@nowarn id: Byte, value: Long): Box = {
val ergoBox = testBox(value,
- ErgoTree.fromProposition(Values.TrueSigmaProp),
+ ErgoTree.fromProposition(TrueSigmaProp),
creationHeight = 0, additionalTokens = Seq(), additionalRegisters = Map())
- new CostingBox(ergoBox)
+ new CBox(ergoBox)
}
def testContext(
inputs: Array[Box], outputs: Array[Box], height: Int, self: Box,
tree: AvlTree, minerPk: Array[Byte], activatedScriptVersion: Byte,
currErgoTreeVersion: Byte, vars: Array[AnyValue]) =
- new CostingDataContext(
+ new CContext(
noInputs.toColl, noHeaders, dummyPreHeader,
inputs.toColl, outputs.toColl, height, self, inputs.indexOf(self), tree,
minerPk.toColl, vars.toColl, activatedScriptVersion, currErgoTreeVersion)
@@ -81,13 +81,13 @@ trait ContractsTestkit {
self: Box,
activatedScriptVersion: Byte,
currErgoTreeVersion: Byte,
- vars: AnyValue*): CostingDataContext = {
+ vars: AnyValue*): CContext = {
testContext(
noInputs, noOutputs, height, self, emptyAvlTree, dummyPubkey,
activatedScriptVersion, currErgoTreeVersion, vars.toArray)
}
- implicit class TestContextOps(ctx: CostingDataContext) {
+ implicit class TestContextOps(ctx: CContext) {
def withInputs(inputs: Box*) = ctx.copy(inputs = inputs.toArray.toColl)
def withOutputs(outputs: Box*) = ctx.copy(outputs = outputs.toArray.toColl)
diff --git a/interpreter/shared/src/test/scala/special/sigma/SigmaTestingData.scala b/interpreter/shared/src/test/scala/special/sigma/SigmaTestingData.scala
index f5e695e32d..d33f09dd80 100644
--- a/interpreter/shared/src/test/scala/special/sigma/SigmaTestingData.scala
+++ b/interpreter/shared/src/test/scala/special/sigma/SigmaTestingData.scala
@@ -6,23 +6,21 @@ import org.scalacheck.Arbitrary.arbitrary
import org.scalacheck.Gen.containerOfN
import org.scalacheck.util.Buildable
import org.scalacheck.{Arbitrary, Gen}
-import sigma.data.RType
+import sigma.data._
import scorex.crypto.authds.{ADKey, ADValue}
import scorex.crypto.hash.{Blake2b256, Digest32}
import scorex.util.ModifierId
-import sigmastate.Values.{ByteArrayConstant, ConcreteCollection, ConstantPlaceholder, ErgoTree, FalseLeaf, IntConstant, LongConstant, SigmaPropConstant, TrueLeaf}
-import sigmastate.crypto.CryptoConstants.EcPointType
-import sigmastate.crypto.DLogProtocol.ProveDlog
-import sigmastate.crypto.ProveDHTuple
-import sigmastate.eval._
-import sigmastate.eval.Extensions._
-import sigmastate.eval.{CAvlTree, CBigInt, CHeader, CPreHeader, CSigmaProp, CostingBox, CostingSigmaDslBuilder, SigmaDsl}
+import sigma.ast._
+import sigma.Extensions.ArrayOps
+import sigmastate.eval.{CHeader, CPreHeader}
import sigmastate.helpers.TestingCommons
-import sigmastate.serialization.ErgoTreeSerializer
-import sigmastate.serialization.generators.ObjectGenerators
+import sigma.serialization.ErgoTreeSerializer
+import sigma.serialization.generators.ObjectGenerators
import sigmastate.utils.Helpers
-import sigmastate._
-import sigma.Coll
+import sigma.ast.{SBoolean, SSigmaProp}
+import sigma.crypto.EcPointType
+import ErgoTree.HeaderType
+import sigma.eval.SigmaDsl
import java.math.BigInteger
import scala.reflect.ClassTag
@@ -30,7 +28,7 @@ import scala.reflect.ClassTag
trait SigmaTestingData extends TestingCommons with ObjectGenerators {
/** Creates a [[sigma.Coll]] with the given `items`. */
def Coll[T](items: T*)(implicit cT: RType[T]): Coll[T] =
- CostingSigmaDslBuilder.Colls.fromItems(items: _*)
+ CSigmaDslBuilder.Colls.fromItems(items: _*)
/** Generator of random collection with `n` elements. */
def collOfN[T: RType : Arbitrary](n: Int)
@@ -208,11 +206,11 @@ trait SigmaTestingData extends TestingCommons with ObjectGenerators {
)
)
- val b1_instances = new CloneSet(1000, CostingBox(
+ val b1_instances = new CloneSet(1000, CBox(
new ErgoBox(
9223372036854775807L,
new ErgoTree(
- 16.toByte,
+ HeaderType @@ 16.toByte,
Array(
SigmaPropConstant(
CSigmaProp(
@@ -246,11 +244,11 @@ trait SigmaTestingData extends TestingCommons with ObjectGenerators {
val b1: Box = create_b1()
- val b2: Box = CostingBox(
+ val b2: Box = CBox(
new ErgoBox(
12345L,
new ErgoTree(
- 0.toByte,
+ HeaderType @@ 0.toByte,
Vector(),
Right(
BoolToSigmaProp(
diff --git a/parsers/shared/src/main/scala/sigmastate/lang/ContractParser.scala b/parsers/shared/src/main/scala/sigmastate/lang/ContractParser.scala
new file mode 100644
index 0000000000..87dd20ab0c
--- /dev/null
+++ b/parsers/shared/src/main/scala/sigmastate/lang/ContractParser.scala
@@ -0,0 +1,196 @@
+package sigmastate.lang
+
+import fastparse._
+import fastparse.NoWhitespace._
+import SigmaParser._
+import sigma.ast.SType
+import sigma.ast.syntax.SValue
+import sigmastate.lang.parsers.Basic
+
+/**
+ * Represents a docstring line.
+ */
+case class DocumentationToken(kind: DocumentationToken.Kind, name: Option[String], body: Option[String])
+
+/**
+ * Companion object containing the classes required for describing an docstring token.
+ */
+object DocumentationToken {
+ def apply(kind: Kind): DocumentationToken = new DocumentationToken(kind, None, None)
+
+ def apply(kind: Kind, body: String): DocumentationToken = new DocumentationToken(kind, None, Option(body))
+
+ def apply(kind: TagKind, name: String, body: String): DocumentationToken =
+ new DocumentationToken(kind, Option(name), Option(body))
+
+ /**
+ * Represents a documentation remark.
+ */
+ sealed abstract class Kind
+
+ /**
+ * Documents an untagged doc description, this is simply a line of text anywhere in the docstring.
+ */
+ case object Description extends Kind
+
+ /**
+ * Represents an empty doc line.
+ */
+ case object EmptyLine extends Kind
+
+ /**
+ * Represents a line starting with a tag (@) but is not supported.
+ */
+ case object UnsupportedTag extends Kind
+
+ /**
+ * Represents a labeled documentation remark.
+ */
+ sealed abstract class TagKind(val label: String) extends Kind
+
+ /**
+ * Documents a specific value parameter of the contract template.
+ */
+ case object Param extends TagKind("@param")
+
+ /**
+ * Documents the return value of the contract template.
+ */
+ case object Return extends TagKind("@returns")
+}
+
+/**
+ * Holds values extracted from a `@param` tag line in docstrings.
+ *
+ * @param name Name of the parameter.
+ * @param description Description of the parameter.
+ */
+case class ParameterDoc(name: String, description: String)
+
+/**
+ * Contract template documentation extracted from the preceding docstring.
+ *
+ * @param description Top level contract template description.
+ * @param params Contract template parameters as defined in the docstring.
+ */
+case class ContractDoc(description: String, params: Seq[ParameterDoc])
+
+object ContractDoc {
+ def apply(tokens: Seq[DocumentationToken]): ContractDoc = {
+ val nonEmptyTokens = tokens.dropWhile(_.kind == DocumentationToken.EmptyLine)
+
+ val (description, paramTokens) = nonEmptyTokens.span(_.kind == DocumentationToken.Description)
+ val descriptionText = description.flatMap(_.body).mkString(" ")
+
+ def extractParamDocs(tokens: Seq[DocumentationToken]): Seq[ParameterDoc] = {
+ tokens match {
+ case DocumentationToken(kind: DocumentationToken.TagKind, Some(name), Some(body)) +: tail if kind == DocumentationToken.Param =>
+ // grab the succeeding description tokens if there are any, this is multiline description of params
+ val (descTokens, remainingTokens) = tail.span(_.kind == DocumentationToken.Description)
+ val fullDescription = (body +: descTokens.flatMap(_.body)).mkString(" ")
+ ParameterDoc(name, fullDescription) +: extractParamDocs(remainingTokens)
+ case _ +: tail => extractParamDocs(tail)
+ case Seq() => Seq()
+ }
+ }
+
+ ContractDoc(descriptionText, extractParamDocs(paramTokens))
+ }
+}
+
+/**
+ * Represents a parsed parameter defined in a contracts signature.
+ *
+ * @param name The name of the parameter.
+ * @param tpe The type of the parameter.
+ * @param defaultValue The default value assigned to the parameter, if it exists.
+ */
+case class ContractParam(name: String, tpe: SType, defaultValue: Option[SType#WrappedType])
+
+/**
+ * Represents the signature of a contract.
+ *
+ * @param name The name of the contract.
+ * @param params The parameters for the contract.
+ */
+case class ContractSignature(name: String, params: Seq[ContractParam])
+
+/**
+ * The result of parsing a contract template.
+ * Includes the parsed docstring preceding the contract as well as the contract signature.
+ *
+ * @param docs Docstring parsed from the contract.
+ * @param signature Signature of the contract.
+ * @param body Parsed SValue of the contract.
+ */
+case class ParsedContractTemplate(docs: ContractDoc, signature: ContractSignature, body: SValue)
+
+/**
+ * Parsers that handle parsing contract definitions excluding the contract body which is handled
+ * by [[SigmaParser]].
+ */
+object ContractParser {
+ def parse(source: String): Parsed[ParsedContractTemplate] = fastparse.parse(source, parse(_))
+
+ /**
+ * Parse a contract up until the open brace (i.e the beginning of the contract logic).
+ */
+ def parse[_: P]: P[ParsedContractTemplate] = P(Docs.parse ~ Basic.Newline ~ Signature.parse ~ WL.? ~ "=" ~ WL.? ~ AnyChar.rep(1).!).map(s => ParsedContractTemplate(s._1, s._2, SigmaParser(s._3).get.value))
+
+ /**
+ * Parsers for contract docstrings.
+ * Contract docstrings follow similiar structure as scaladocs except only support a subset
+ * of documentation tags such as @param & @returns.
+ */
+ object Docs {
+
+ import DocumentationToken._
+
+ def parse(source: String): Parsed[ContractDoc] = {
+ fastparse.parse(source, parse(_))
+ }
+
+ def parse[_: P]: P[ContractDoc] = P(" ".rep.? ~ "/*" ~ docLine.rep ~ " ".rep.? ~ "*/").map(ContractDoc.apply)
+
+ def linePrefix[_: P] = P(WL.? ~ "*" ~ " ".rep.? ~ !"/")
+
+ def word[_: P] = CharsWhile(c => c != ' ')
+
+ def charUntilNewLine[_: P] = CharsWhile(c => c != '\n')
+
+ def unsupportedTag[_: P] = P("@" ~ charUntilNewLine.?).map(_ => DocumentationToken(UnsupportedTag))
+
+ def returnTag[_: P] = P("@returns").map(_ => DocumentationToken(Return))
+
+ def paramTag[_: P] = P("@param" ~ WL ~ word.! ~ WL ~ charUntilNewLine.!).map(s => DocumentationToken(Param, s._1, s._2))
+
+ def tag[_: P] = P(returnTag | paramTag | unsupportedTag)
+
+ def emptyLine[_: P] = P(("" | " ".rep.?) ~ &(Basic.Newline)).map(_ => DocumentationToken(EmptyLine))
+
+ def description[_: P] = P(!"@" ~ charUntilNewLine.!).map(s => DocumentationToken(Description, s))
+
+ def docLine[_: P] = P(linePrefix ~ (emptyLine | description | tag) ~ Basic.Newline)
+ }
+
+ /**
+ * Parsers for contract signatures.
+ * A contract signature has essentially the same shape as a scala function signature.
+ */
+ object Signature {
+
+ def parse(source: String): Parsed[ContractSignature] = {
+ fastparse.parse(source, parse(_))
+ }
+
+ def parse[_: P]: P[ContractSignature] = P(annotation ~ WL.? ~ `def` ~ WL.? ~ Id.! ~ params).map(s => ContractSignature(s._1, s._2.getOrElse(Seq())))
+
+ def annotation[_: P] = P("@contract")
+
+ def paramDefault[_: P] = P(WL.? ~ `=` ~ WL.? ~ ExprLiteral).map(s => s.asWrappedType)
+
+ def param[_: P] = P(WL.? ~ Id.! ~ ":" ~ Type ~ paramDefault.?).map(s => ContractParam(s._1, s._2, s._3))
+
+ def params[_: P] = P("(" ~ param.rep(1, ",").? ~ ")")
+ }
+}
diff --git a/parsers/shared/src/main/scala/sigmastate/lang/SigmaParser.scala b/parsers/shared/src/main/scala/sigmastate/lang/SigmaParser.scala
index 155e4ab879..3e7a5a313f 100644
--- a/parsers/shared/src/main/scala/sigmastate/lang/SigmaParser.scala
+++ b/parsers/shared/src/main/scala/sigmastate/lang/SigmaParser.scala
@@ -1,19 +1,18 @@
package sigmastate.lang
import fastparse.internal.Logger
-import sigmastate._
-import Values._
+import sigma.ast._
import sigma.data.Nullable
-import sigmastate.lang.Terms._
-import sigmastate.lang.syntax.Basic._
-import sigmastate.lang.syntax.{Core, Exprs}
+import sigma.ast.syntax._
+import sigmastate.lang.parsers.{Basic, Core, Exprs}
import scala.collection.mutable
import scala.util.DynamicVariable
/** Main facade to ErgoScript parser implementation. */
-object SigmaParser extends Exprs with Types with Core {
- import fastparse._; import ScalaWhitespace._
+object SigmaParser extends Exprs with Types with Core { parser =>
+ import fastparse._
+ import ScalaWhitespace._
import builder._
private val currentInput = new DynamicVariable[String]("")
@@ -30,7 +29,7 @@ object SigmaParser extends Exprs with Types with Core {
mkVal(n, t.getOrElse(NoType), body)
}
case (index, pat,_,_) =>
- error(s"Only single name patterns supported but was $pat", Some(srcCtx(index)))
+ Basic.error(s"Only single name patterns supported but was $pat", Some(srcCtx(index)))
}
override def BlockDef[_:P] = P( Dcl )
@@ -47,7 +46,7 @@ object SigmaParser extends Exprs with Types with Core {
mkConstant[SInt.type](-value, SInt)
case LongConstant(value) =>
mkConstant[SLong.type](-value, SLong)
- case _ => error(s"cannot prefix $arg with op $opName", arg.sourceContext)
+ case _ => Basic.error(s"cannot prefix $arg with op $opName", arg.sourceContext)
}
case "!" => mkLogicalNot(arg.asBoolValue)
@@ -56,16 +55,16 @@ object SigmaParser extends Exprs with Types with Core {
if (arg.tpe.isNumTypeOrNoType)
mkNegation(arg.asNumValue)
else
- error(s"Numeric argument expected for '$opName' operation: $arg", arg.sourceContext)
+ Basic.error(s"Numeric argument expected for '$opName' operation: $arg", arg.sourceContext)
case "~" =>
if (arg.tpe.isNumTypeOrNoType)
mkBitInversion(arg.asNumValue)
else
- error(s"Numeric argument expected for '$opName' operation: $arg", arg.sourceContext)
+ Basic.error(s"Numeric argument expected for '$opName' operation: $arg", arg.sourceContext)
case _ =>
- error(s"Unknown prefix operation $opName for $arg", arg.sourceContext)
+ Basic.error(s"Unknown prefix operation $opName for $arg", arg.sourceContext)
}
}
@@ -86,18 +85,18 @@ object SigmaParser extends Exprs with Types with Core {
if (l.tpe.isNumTypeOrNoType && r.tpe.isNumTypeOrNoType)
mkBitOr(l.asNumValue, r.asNumValue)
else
- error(s"Numeric arguments expected for '$opName' operation: ($l, $r)", l.sourceContext)
+ Basic.error(s"Numeric arguments expected for '$opName' operation: ($l, $r)", l.sourceContext)
case "&" =>
if (l.tpe.isNumTypeOrNoType && r.tpe.isNumTypeOrNoType)
mkBitAnd(l.asNumValue, r.asNumValue)
else
- error(s"Numeric arguments expected for '$opName' operation: ($l, $r)", l.sourceContext)
+ Basic.error(s"Numeric arguments expected for '$opName' operation: ($l, $r)", l.sourceContext)
case _ if parseAsMethods.contains(opName) => mkMethodCallLike(l, opName, IndexedSeq(r))
case "/" => mkDivide(l.asNumValue, r.asNumValue)
case "%" => mkModulo(l.asNumValue, r.asNumValue)
- case _ => error(s"Unknown binary operation $opName", l.sourceContext)
+ case _ => Basic.error(s"Unknown binary operation $opName", l.sourceContext)
}
}
diff --git a/parsers/shared/src/main/scala/sigmastate/lang/Types.scala b/parsers/shared/src/main/scala/sigmastate/lang/Types.scala
index e4869e4190..06683f6e96 100644
--- a/parsers/shared/src/main/scala/sigmastate/lang/Types.scala
+++ b/parsers/shared/src/main/scala/sigmastate/lang/Types.scala
@@ -2,11 +2,9 @@ package sigmastate.lang
import fastparse._
import ScalaWhitespace._
-import sigmastate._
-import Values._
-import sigmastate.lang.Terms.Ident
-import sigmastate.lang.syntax.Core
-import syntax.Basic.error
+import sigmastate.lang.parsers.Core
+import parsers.Basic.error
+import sigma.ast._
//noinspection ForwardReference
/** Parsers of type terms. Can produce values of SType. */
diff --git a/parsers/shared/src/main/scala/sigmastate/lang/syntax/Basic.scala b/parsers/shared/src/main/scala/sigmastate/lang/parsers/Basic.scala
similarity index 96%
rename from parsers/shared/src/main/scala/sigmastate/lang/syntax/Basic.scala
rename to parsers/shared/src/main/scala/sigmastate/lang/parsers/Basic.scala
index 55bdd4e399..152de08780 100644
--- a/parsers/shared/src/main/scala/sigmastate/lang/syntax/Basic.scala
+++ b/parsers/shared/src/main/scala/sigmastate/lang/parsers/Basic.scala
@@ -1,11 +1,11 @@
-package sigmastate.lang.syntax
+package sigmastate.lang.parsers
import fastparse._
import NoWhitespace._
import fastparse.CharPredicates._
+import sigma.ast.SourceContext
import sigma.data.Nullable
-import sigmastate.lang.SourceContext
-import sigmastate.exceptions.CompilerException
+import sigma.exceptions.CompilerException
/** Basic lexical parsers for ErgoScript. */
object Basic {
diff --git a/parsers/shared/src/main/scala/sigmastate/lang/syntax/Core.scala b/parsers/shared/src/main/scala/sigmastate/lang/parsers/Core.scala
similarity index 93%
rename from parsers/shared/src/main/scala/sigmastate/lang/syntax/Core.scala
rename to parsers/shared/src/main/scala/sigmastate/lang/parsers/Core.scala
index 05f0952b20..a2d7781b87 100644
--- a/parsers/shared/src/main/scala/sigmastate/lang/syntax/Core.scala
+++ b/parsers/shared/src/main/scala/sigmastate/lang/parsers/Core.scala
@@ -1,11 +1,11 @@
-package sigmastate.lang.syntax
+package sigmastate.lang.parsers
-import sigmastate._
-import sigmastate.Values._
-import sigmastate.lang.syntax
+import sigma.ast.syntax.SValue
+import sigma.ast._
+import sigmastate.lang.parsers
/** Keywords and identifiers used in expressions. */
-trait Core extends syntax.Literals {
+trait Core extends parsers.Literals {
import fastparse._
import ScalaWhitespace._
diff --git a/parsers/shared/src/main/scala/sigmastate/lang/syntax/Exprs.scala b/parsers/shared/src/main/scala/sigmastate/lang/parsers/Exprs.scala
similarity index 95%
rename from parsers/shared/src/main/scala/sigmastate/lang/syntax/Exprs.scala
rename to parsers/shared/src/main/scala/sigmastate/lang/parsers/Exprs.scala
index f2b8c68b12..3d02cb3b14 100644
--- a/parsers/shared/src/main/scala/sigmastate/lang/syntax/Exprs.scala
+++ b/parsers/shared/src/main/scala/sigmastate/lang/parsers/Exprs.scala
@@ -1,13 +1,12 @@
-package sigmastate.lang.syntax
+package sigmastate.lang.parsers
import fastparse._
import ScalaWhitespace._
-import sigmastate._
-import sigmastate.Values._
-import sigmastate.lang.Terms.{Val, Ident, ValueOps}
+import sigma.ast._
+import sigma.ast.syntax.{SValue, ValueOps}
import sigmastate.lang._
-import sigmastate.lang.SigmaPredef._
-import sigmastate.lang.syntax.Basic._
+import SigmaPredef._
+import sigmastate.lang.parsers.Basic._
import scala.annotation.tailrec
import scala.collection.compat.immutable.ArraySeq
@@ -25,11 +24,11 @@ trait Exprs extends Core with Types {
// varies.
// Expressions used as statements, directly within a {block}
- object StatCtx extends WsCtx(semiInference=true, arrowTypeAscriptions=false)
+ object StatCtx extends WsCtx(semiInference=true)
// Expressions nested within other expressions
- object ExprCtx extends WsCtx(semiInference=false, arrowTypeAscriptions=true)
+ object ExprCtx extends WsCtx(semiInference=false)
// Expressions directly within a `val x = ...` or `def x = ...`
- object FreeCtx extends WsCtx(semiInference=true, arrowTypeAscriptions=true)
+ object FreeCtx extends WsCtx(semiInference=true)
override def TypeExpr[_:P]: P[Value[SType]] = ExprCtx.Expr
@@ -38,7 +37,7 @@ trait Exprs extends Core with Types {
//noinspection TypeAnnotation,ForwardReference
/** Parsing context of expressions (see derived classes). */
- class WsCtx(semiInference: Boolean, arrowTypeAscriptions: Boolean) {
+ class WsCtx(semiInference: Boolean) {
private def OneSemiMax[_:P]: P[Unit] = if (semiInference) OneNLMax else Pass
private def NoSemis[_:P]: P[Unit] = if (semiInference) NotNewline else Pass
@@ -76,7 +75,7 @@ trait Exprs extends Core with Types {
}
private def SuperPostfixSuffix[_:P] = P( (`=` ~/ Expr).? )
- private def ExprPrefix[_:P] = P( WL ~ CharPred("-+!~".contains(_)).! ~~ !syntax.Basic.OpChar ~ WS)
+ private def ExprPrefix[_:P] = P( WL ~ CharPred("-+!~".contains(_)).! ~~ !parsers.Basic.OpChar ~ WS)
private def ExprSuffix[_:P] = P(
(WL ~ "." ~/ (Index ~ Id.!).map{ case (i, s) => atSrcPos(i) { mkIdent(s, NoType)} }
| WL ~ TypeArgs.map(items => STypeApply("", items.toIndexedSeq))
@@ -198,7 +197,7 @@ trait Exprs extends Core with Types {
case STypeApply("", targs) => mkApplyTypes(acc, targs)
case arg: SValue => acc match {
case Ident(name, _) if name == ZKProofFunc.name => arg match {
- case Terms.Block(_, body) =>
+ case Block(_, body) =>
mkApply(mkIdent(ZKProofFunc.name, ZKProofFunc.declaration.tpe), Array(body))
case nonBlock =>
error(s"expected block parameter for ZKProof, got $nonBlock", nonBlock.sourceContext)
diff --git a/parsers/shared/src/main/scala/sigmastate/lang/syntax/Identifiers.scala b/parsers/shared/src/main/scala/sigmastate/lang/parsers/Identifiers.scala
similarity index 96%
rename from parsers/shared/src/main/scala/sigmastate/lang/syntax/Identifiers.scala
rename to parsers/shared/src/main/scala/sigmastate/lang/parsers/Identifiers.scala
index 65acacc765..f8e3e4ccbd 100644
--- a/parsers/shared/src/main/scala/sigmastate/lang/syntax/Identifiers.scala
+++ b/parsers/shared/src/main/scala/sigmastate/lang/parsers/Identifiers.scala
@@ -1,9 +1,9 @@
-package sigmastate.lang.syntax
+package sigmastate.lang.parsers
import fastparse.CharPredicates.{isDigit, isLetter}
import fastparse._
import NoWhitespace._
-import sigmastate.lang.syntax.Basic._
+import sigmastate.lang.parsers.Basic._
//noinspection ForwardReference
/** Identifiers and keywords */
diff --git a/parsers/shared/src/main/scala/sigmastate/lang/syntax/Literals.scala b/parsers/shared/src/main/scala/sigmastate/lang/parsers/Literals.scala
similarity index 96%
rename from parsers/shared/src/main/scala/sigmastate/lang/syntax/Literals.scala
rename to parsers/shared/src/main/scala/sigmastate/lang/parsers/Literals.scala
index 007e4057b5..6beff079e4 100644
--- a/parsers/shared/src/main/scala/sigmastate/lang/syntax/Literals.scala
+++ b/parsers/shared/src/main/scala/sigmastate/lang/parsers/Literals.scala
@@ -1,13 +1,12 @@
-package sigmastate.lang.syntax
+package sigmastate.lang.parsers
-import fastparse._; import NoWhitespace._
-import Identifiers._
-import sigmastate._
-import Values._
-import java.lang.Long.parseLong
+import fastparse.NoWhitespace._
+import fastparse._
+import sigma.ast.syntax.BooleanConstant
+import sigma.ast._
+import sigmastate.lang.parsers.Identifiers._
import java.lang.Integer.parseInt
-
-import sigmastate.lang.{SigmaBuilder, SourceContext, StdSigmaBuilder}
+import java.lang.Long.parseLong
/** Parsers of literal expressions. */
trait Literals { l =>
diff --git a/parsers/shared/src/test/scala/sigmastate/lang/ContractParserSpec.scala b/parsers/shared/src/test/scala/sigmastate/lang/ContractParserSpec.scala
new file mode 100644
index 0000000000..9a412b7100
--- /dev/null
+++ b/parsers/shared/src/test/scala/sigmastate/lang/ContractParserSpec.scala
@@ -0,0 +1,50 @@
+package sigmastate.lang
+
+import org.scalatest.matchers.should.Matchers
+import org.scalatest.propspec.AnyPropSpec
+import org.scalatestplus.scalacheck.ScalaCheckPropertyChecks
+import sigma.ast._
+
+class ContractParserSpec extends AnyPropSpec with ScalaCheckPropertyChecks with Matchers {
+ property("parses docstring") {
+ val doc =
+ """/** This is my contracts description.
+ |* Here is another line describing what it does in more detail.
+ |*
+ |* @param p1 describe p1
+ |* @param p2 description of the 2nd parameter
+ |* which is pretty complex and on many
+ |* lines to describe functions
+ |* @param p3 the final parameter
+ |* @return
+ |*/""".stripMargin
+ val contractDoc = ContractParser.Docs.parse(doc).get.value
+
+ contractDoc.description shouldBe "This is my contracts description. Here is another line describing what it does in more detail."
+ contractDoc.params should contain theSameElementsInOrderAs Seq(
+ ParameterDoc("p1", "describe p1"),
+ ParameterDoc("p2", "description of the 2nd parameter which is pretty complex and on many lines to describe functions"),
+ ParameterDoc("p3", "the final parameter")
+ )
+ }
+
+ property("parses contract signature") {
+ val source = "@contract def contractName(p1: Int = 5, p2: String = \"default string\", param3: Long)"
+ val parsed = ContractParser.Signature.parse(source).get.value
+
+ parsed.name shouldBe "contractName"
+ parsed.params should contain theSameElementsInOrderAs Seq(
+ ContractParam("p1", SInt, Some(IntConstant(5).asWrappedType)),
+ ContractParam("p2", SString, Some(StringConstant("default string").asWrappedType)),
+ ContractParam("param3", SLong, None)
+ )
+ }
+
+ property("parses contract signature no params") {
+ val source = "@contract def contractName()"
+ val parsed = ContractParser.Signature.parse(source).get.value
+
+ parsed.name shouldBe "contractName"
+ parsed.params should contain theSameElementsInOrderAs Seq()
+ }
+}
diff --git a/parsers/shared/src/test/scala/sigmastate/lang/LangTests.scala b/parsers/shared/src/test/scala/sigmastate/lang/LangTests.scala
index a1da3d0766..498c3934bf 100644
--- a/parsers/shared/src/test/scala/sigmastate/lang/LangTests.scala
+++ b/parsers/shared/src/test/scala/sigmastate/lang/LangTests.scala
@@ -1,19 +1,18 @@
package sigmastate.lang
import org.scalatest.matchers.should.Matchers
-import sigmastate.lang.Terms.{Ident, MethodCallLike}
-import sigmastate.Values.{ConcreteCollection, LongConstant, SValue, SigmaBoolean, Value}
-import sigmastate._
+import sigma.{Coll, _}
+import sigma.ast.SCollection.SByteArray
+import sigma.ast.syntax.{SValue, ValueOps}
+import sigma.ast._
+import sigma.crypto.CryptoConstants
+import sigma.data.{CAnyValue, CSigmaDslBuilder, ProveDHTuple, ProveDlog, SigmaBoolean}
+import sigma.util.Extensions.BigIntegerOps
+import sigmastate.helpers.NegativeTesting
+import sigmastate.interpreter.Interpreter.ScriptEnv
+import sigma.ast.{Ident, MethodCallLike}
import java.math.BigInteger
-import sigmastate.crypto.DLogProtocol.ProveDlog
-import sigmastate.SCollection.SByteArray
-import sigmastate.crypto.{ProveDHTuple, CryptoConstants}
-import sigmastate.interpreter.Interpreter.ScriptEnv
-import sigma._
-import sigmastate.eval._
-import sigmastate.helpers.NegativeTesting
-import sigma.Coll
trait LangTests extends Matchers with NegativeTesting {
@@ -37,13 +36,13 @@ trait LangTests extends Matchers with NegativeTesting {
val ecp2 = dlog.multiplyGroupElements(ecp1, ecp1)
val ecp3 = dlog.multiplyGroupElements(ecp2, ecp2)
val ecp4 = dlog.multiplyGroupElements(ecp3, ecp3)
- val g1 = CostingSigmaDslBuilder.GroupElement(ecp1)
- val g2 = CostingSigmaDslBuilder.GroupElement(ecp2)
- val g3 = CostingSigmaDslBuilder.GroupElement(ecp3)
- val g4 = CostingSigmaDslBuilder.GroupElement(ecp4)
+ val g1 = CSigmaDslBuilder.GroupElement(ecp1)
+ val g2 = CSigmaDslBuilder.GroupElement(ecp2)
+ val g3 = CSigmaDslBuilder.GroupElement(ecp3)
+ val g4 = CSigmaDslBuilder.GroupElement(ecp4)
- protected val n1: BigInt = BigInt(10).underlying()
- protected val n2: BigInt = BigInt(20).underlying()
+ protected val n1: BigInt = BigInt(10).underlying().toBigInt
+ protected val n2: BigInt = BigInt(20).underlying().toBigInt
protected val bigIntegerArr1: Coll[BigInt] = Colls.fromItems(n1, n2)
protected val big: BigInteger = BigInt(Long.MaxValue).underlying().pow(2)
protected val p1: SigmaBoolean = ProveDlog(ecp1)
diff --git a/parsers/shared/src/test/scala/sigmastate/lang/SigmaParserTest.scala b/parsers/shared/src/test/scala/sigmastate/lang/SigmaParserTest.scala
index 42d02fefb5..7213088a05 100644
--- a/parsers/shared/src/test/scala/sigmastate/lang/SigmaParserTest.scala
+++ b/parsers/shared/src/test/scala/sigmastate/lang/SigmaParserTest.scala
@@ -6,13 +6,14 @@ import org.ergoplatform.ErgoBox
import org.scalatest.matchers.should.Matchers
import org.scalatest.propspec.AnyPropSpec
import org.scalatestplus.scalacheck.ScalaCheckPropertyChecks
-import sigmastate.SCollection._
-import sigmastate.Values._
+import sigma.ast.SCollection.{SByteArray, SLongArray}
+import sigma.ast._
+import sigma.ast.syntax.SValue
import sigmastate._
-import sigmastate.lang.SigmaPredef.PredefinedFuncRegistry
-import sigmastate.lang.Terms._
-import sigmastate.lang.syntax.ParserException
-import sigmastate.serialization.OpCodes
+import SigmaPredef.PredefinedFuncRegistry
+import sigma.ast.syntax._
+import sigmastate.lang.parsers.ParserException
+import sigma.serialization.OpCodes
class SigmaParserTest extends AnyPropSpec with ScalaCheckPropertyChecks with Matchers with LangTests {
import StdSigmaBuilder._
@@ -538,7 +539,7 @@ class SigmaParserTest extends AnyPropSpec with ScalaCheckPropertyChecks with Mat
property("Box properties") {
parse("{ (box: Box) => box.value }") shouldBe Lambda(IndexedSeq("box" -> SBox), NoType, Select(Ident("box"), "value"))
- parse("{ (box: Box) => box.propositionBytes }") shouldBe Lambda(IndexedSeq("box" -> SBox), NoType, Select(Ident("box"), SBox.PropositionBytes))
+ parse("{ (box: Box) => box.propositionBytes }") shouldBe Lambda(IndexedSeq("box" -> SBox), NoType, Select(Ident("box"), SBoxMethods.PropositionBytes))
parse("{ (box: Box) => box.bytes }") shouldBe Lambda(IndexedSeq("box" -> SBox), NoType, Select(Ident("box"), "bytes"))
parse("{ (box: Box) => box.id }") shouldBe Lambda(IndexedSeq("box" -> SBox), NoType, Select(Ident("box"), "id"))
}
diff --git a/sc/js/src/main/scala/sigmastate/lang/js/SigmaCompiler.scala b/sc/js/src/main/scala/sigmastate/lang/js/SigmaCompiler.scala
index d428a75294..8fe26a30b0 100644
--- a/sc/js/src/main/scala/sigmastate/lang/js/SigmaCompiler.scala
+++ b/sc/js/src/main/scala/sigmastate/lang/js/SigmaCompiler.scala
@@ -1,15 +1,16 @@
package sigmastate.lang.js
import org.ergoplatform.ErgoAddressEncoder
-import org.ergoplatform.sdk.js.Isos.isoValueToConstant
import org.scalablytyped.runtime.StringDictionary
+import sigma.ast
+import sigma.ast.js.{ErgoTree, isoValueToConstant}
import scala.scalajs.js
import scala.scalajs.js.annotation.JSExportTopLevel
-import org.ergoplatform.sdk.js.{ErgoTree, Value}
-import sigmastate.Values
+import sigma.js.Value
+import sigma.ast.ErgoTree.HeaderType
import sigmastate.eval.CompiletimeIRContext
-import sigmastate.lang.Terms.ValueOps
+import sigma.ast.syntax.ValueOps
/** Wrapper exported to JS. */
@@ -27,7 +28,7 @@ class SigmaCompiler(_compiler: sigmastate.lang.SigmaCompiler) extends js.Object
def compile(
namedConstants: StringDictionary[Value],
segregateConstants: Boolean,
- additionalHeaderFlags: Byte, ergoScript: String): ErgoTree = {
+ treeHeader: Byte, ergoScript: String): ErgoTree = {
val env = StringDictionary
.wrapStringDictionary(namedConstants)
.view.mapValues(v => isoValueToConstant.to(v)).toMap
@@ -36,15 +37,15 @@ class SigmaCompiler(_compiler: sigmastate.lang.SigmaCompiler) extends js.Object
require(prop.tpe.isSigmaProp, s"Expected SigmaProp expression type bue got ${prop.tpe}: $prop")
val tree = if (segregateConstants) {
- Values.ErgoTree.withSegregation(additionalHeaderFlags, prop.asSigmaProp)
+ ast.ErgoTree.withSegregation(HeaderType @@ treeHeader, prop.asSigmaProp)
} else {
- Values.ErgoTree.withoutSegregation(additionalHeaderFlags, prop.asSigmaProp)
+ ast.ErgoTree.withoutSegregation(HeaderType @@ treeHeader, prop.asSigmaProp)
}
new ErgoTree(tree)
}
}
-@JSExportTopLevel("SigmaCompilerObj")
+@JSExportTopLevel("SigmaCompiler$")
object SigmaCompiler extends js.Object {
/** Creates a new instance of SigmaCompiler for the mainnet. */
def forMainnet(): SigmaCompiler = create(ErgoAddressEncoder.MainnetNetworkPrefix)
@@ -58,7 +59,7 @@ object SigmaCompiler extends js.Object {
* @return SigmaCompiler instance
*/
private def create(networkPrefix: Byte): SigmaCompiler = {
- val compiler = new sigmastate.lang.SigmaCompiler(networkPrefix)
+ val compiler = sigmastate.lang.SigmaCompiler(networkPrefix)
new SigmaCompiler(compiler)
}
}
diff --git a/sc/jvm/src/test/scala/sigmastate/ErgoTreeBenchmarks.scala b/sc/jvm/src/test/scala/sigmastate/ErgoTreeBenchmarks.scala
index f5741dcb42..2b23d85846 100644
--- a/sc/jvm/src/test/scala/sigmastate/ErgoTreeBenchmarks.scala
+++ b/sc/jvm/src/test/scala/sigmastate/ErgoTreeBenchmarks.scala
@@ -3,15 +3,16 @@ package sigmastate
import debox.cfor
import org.scalameter.api.Bench
import sigma.BenchmarkGens
-import sigmastate.Values.{IntConstant, SValue}
-import sigmastate.serialization.OpCodes.PlusCode
+import sigma.ast.{ArithOp, EQ, IntConstant, SType}
+import sigma.ast.syntax.SValue
+import sigma.serialization.OpCodes.PlusCode
object ErgoTreeBenchmarks extends Bench.LocalTime with BenchmarkGens { suite: Bench[Double] =>
override def maxSize: Int = 10000
/** Expected approximate results:
- * ::Benchmark allocation of sigmastate.Values.ArithOp, EQ, IntConstant::
+ * ::Benchmark allocation of sigma.ast.ArithOp, EQ, IntConstant::
* name: OpenJDK 64-Bit Server VM
* osArch: x86_64
* osName: Mac OS X
@@ -22,7 +23,7 @@ object ErgoTreeBenchmarks extends Bench.LocalTime with BenchmarkGens { suite: Be
* Parameters(size -> 1000): 0.696851 ms
* Parameters(size -> 10000): 5.687967 ms
*/
- performance of "allocation of sigmastate.Values" in {
+ performance of "allocation of sigma.ast" in {
measure method "ArithOp, EQ, IntConstant" in {
using(sizes) in { size =>
val arr = new Array[SValue](size)
@@ -57,7 +58,7 @@ object ErgoTreeBenchmarks extends Bench.LocalTime with BenchmarkGens { suite: Be
measure method "isCorrectType" in {
using(sizes) in { size =>
cfor(0)(_ < size, _ + 1) { i =>
- sigmastate.crypto.Platform.isCorrectType(i, SType.allPredefTypes(i % 10))
+ sigma.crypto.Platform.isCorrectType(i, SType.allPredefTypes(i % 10))
}
}
}
diff --git a/sc/jvm/src/test/scala/sigmastate/ReflectionGenerator.scala b/sc/jvm/src/test/scala/sigmastate/ReflectionGenerator.scala
index 28b2733c31..1375b48d99 100644
--- a/sc/jvm/src/test/scala/sigmastate/ReflectionGenerator.scala
+++ b/sc/jvm/src/test/scala/sigmastate/ReflectionGenerator.scala
@@ -34,7 +34,7 @@ object ReflectionGenerator {
"sigma.",
"sigma.",
"special.wrappers.",
- "sigmastate.Values.",
+ "sigma.ast.",
"sigmastate.lang.Terms.",
"sigmastate.interpreter.",
"sigmastate.utxo.",
diff --git a/sc/jvm/src/test/scala/sigmastate/helpers/SigmaPPrintSpec.scala b/sc/jvm/src/test/scala/sigmastate/helpers/SigmaPPrintSpec.scala
index 5a2c65d565..54c0f652dc 100644
--- a/sc/jvm/src/test/scala/sigmastate/helpers/SigmaPPrintSpec.scala
+++ b/sc/jvm/src/test/scala/sigmastate/helpers/SigmaPPrintSpec.scala
@@ -1,18 +1,17 @@
package sigmastate.helpers
import org.ergoplatform.settings.ErgoAlgos
-import org.ergoplatform.{ErgoBox, Outputs}
-import sigma.data.{CollType, RType}
+import org.ergoplatform.ErgoBox
import scorex.util.ModifierId
-import sigmastate.Values._
-import sigmastate._
-import sigmastate.eval.Extensions.ArrayOps
+import sigma.Extensions.ArrayOps
+import sigma.SigmaDslTesting
+import sigma.ast._
+import sigma.data.{AvlTreeData, AvlTreeFlags, CBox, CollType, Digest32Coll}
+import ErgoTree.HeaderType
import sigmastate.eval._
-import sigmastate.lang.Terms.MethodCall
-import sigmastate.serialization.OpCodes
+import sigma.ast.MethodCall
+import sigma.serialization.OpCodes
import sigmastate.utils.Helpers
-import sigmastate.utxo.SelectField
-import sigma.SigmaDslTesting
import java.math.BigInteger
import scala.collection.mutable.ArrayBuffer
@@ -88,7 +87,7 @@ class SigmaPPrintSpec extends SigmaDslTesting {
|)""".stripMargin)
test(
new ErgoTree(
- 16.toByte,
+ HeaderType @@ 16.toByte,
Vector(IntArrayConstant(Array(10, 20))),
Right(BoolToSigmaProp(TrueLeaf))
),
@@ -98,10 +97,10 @@ class SigmaPPrintSpec extends SigmaDslTesting {
| Right(BoolToSigmaProp(TrueLeaf))
|)""".stripMargin)
test(
- CostingBox(
+ CBox(
new ErgoBox(
9223372036854775807L,
- new ErgoTree(0.toByte, Vector(), Right(BoolToSigmaProp(FalseLeaf))),
+ new ErgoTree(HeaderType @@ 0.toByte, Vector(), Right(BoolToSigmaProp(FalseLeaf))),
Coll(
(Digest32Coll @@ (ErgoAlgos.decodeUnsafe("6e789ab7b2fffff12280a6cd01557f6fb22b7f80ff7aff8e1f7f15973d7f0001").toColl), 10000000L)
),
@@ -111,7 +110,7 @@ class SigmaPPrintSpec extends SigmaDslTesting {
1000000
)
),
- """CostingBox(
+ """CBox(
| new ErgoBox(
| 9223372036854775807L,
| new ErgoTree(0.toByte, Vector(), Right(BoolToSigmaProp(FalseLeaf))),
@@ -149,13 +148,13 @@ class SigmaPPrintSpec extends SigmaDslTesting {
test(
MethodCall.typed[Value[SCollection[SBox.type]]](
ValUse(1, SContext),
- SContext.getMethodByName("dataInputs"),
+ SContextMethods.getMethodByName("dataInputs"),
Vector(),
Map()
),
"""MethodCall.typed[Value[SCollection[SBox.type]]](
| ValUse(1, SContext),
- | SContext.getMethodByName("dataInputs"),
+ | SContextMethods.getMethodByName("dataInputs"),
| Vector(),
| Map()
|)""".stripMargin)
@@ -165,13 +164,13 @@ class SigmaPPrintSpec extends SigmaDslTesting {
test(
MethodCall.typed[Value[SCollection[SInt.type]]](
ValUse(1, SCollectionType(SBox)),
- SCollection.IndicesMethod.withConcreteTypes(Map(SCollection.tIV -> SBox)),
+ SCollectionMethods.IndicesMethod.withConcreteTypes(Map(SCollection.tIV -> SBox)),
Vector(),
Map()
),
"""MethodCall.typed[Value[SCollection[SInt.type]]](
| ValUse(1, SCollectionType(SBox)),
- | SCollection.getMethodByName("indices").withConcreteTypes(Map(STypeVar("IV") -> SBox)),
+ | SCollectionMethods.getMethodByName("indices").withConcreteTypes(Map(STypeVar("IV") -> SBox)),
| Vector(),
| Map()
|)""".stripMargin)
diff --git a/sc/jvm/src/test/scala/sigmastate/utils/GenSerializers.scala b/sc/jvm/src/test/scala/sigmastate/utils/GenSerializers.scala
index 75e39111ab..1aa3d81c33 100644
--- a/sc/jvm/src/test/scala/sigmastate/utils/GenSerializers.scala
+++ b/sc/jvm/src/test/scala/sigmastate/utils/GenSerializers.scala
@@ -3,8 +3,8 @@ package sigmastate.utils
import sigma.util.Extensions.ByteOps
import sigma.util.FileUtil
import sigma.util.PrintExtensions._
-import sigmastate.lang.Terms.{MethodCall, PropertyCall}
-import sigmastate.serialization.ValueSerializer._
+import sigma.ast.{MethodCall, PropertyCall}
+import sigma.serialization.ValueSerializer._
/** Generate contents of ErgoTree serializer format specification.
* To generate serialization formats, it is necessary that all branches of serializers
diff --git a/sc/shared/src/main/scala/org/ergoplatform/ErgoScriptPredef.scala b/sc/shared/src/main/scala/org/ergoplatform/ErgoScriptPredef.scala
index b8c0db379a..faded6e28c 100644
--- a/sc/shared/src/main/scala/org/ergoplatform/ErgoScriptPredef.scala
+++ b/sc/shared/src/main/scala/org/ergoplatform/ErgoScriptPredef.scala
@@ -1,18 +1,19 @@
package org.ergoplatform
-import sigmastate.SType
import sigmastate.lang.SigmaCompiler
import sigmastate.eval.IRContext
import org.ergoplatform.ErgoAddressEncoder.NetworkPrefix
-import sigmastate.Values.{SigmaPropValue, Value}
-import sigmastate.lang.Terms.ValueOps
+import sigma.ast.SType
+import sigma.ast.syntax.SigmaPropValue
+import sigma.ast.Value
+import sigma.ast.syntax.ValueOps
object ErgoScriptPredef {
import sigmastate.interpreter.Interpreter._
/** Compiles the given ErgoScript `code` into ErgoTree expression. */
def compileWithCosting(env: ScriptEnv, code: String, networkPrefix: NetworkPrefix)(implicit IR: IRContext): Value[SType] = {
- val compiler = new SigmaCompiler(networkPrefix)
+ val compiler = SigmaCompiler(networkPrefix)
val res = compiler.compile(env, code)
res.buildTree
}
diff --git a/sc/shared/src/main/scala/org/ergoplatform/dsl/ContractSpec.scala b/sc/shared/src/main/scala/org/ergoplatform/dsl/ContractSpec.scala
index 5950b8fcdb..484b9e2728 100644
--- a/sc/shared/src/main/scala/org/ergoplatform/dsl/ContractSpec.scala
+++ b/sc/shared/src/main/scala/org/ergoplatform/dsl/ContractSpec.scala
@@ -1,20 +1,20 @@
package org.ergoplatform.dsl
import org.ergoplatform.ErgoBox.{BoxId, NonMandatoryRegisterId, TokenId}
-import sigmastate.interpreter.{CostedProverResult, ProverResult}
-import sigma.data.RType
+import sigma.interpreter.{CostedProverResult, ProverResult}
+import sigma.data.{CSigmaDslBuilder, RType}
import org.ergoplatform.{ErgoBox, ErgoLikeContext}
-import sigma.{AnyValue, Coll, SigmaDslBuilder, SigmaProp}
-import sigmastate.Values.ErgoTree
-import sigmastate.eval.{CostingSigmaDslBuilder, IRContext}
+import sigma.{Coll, SigmaDslBuilder, SigmaProp}
+import sigmastate.eval.IRContext
import scala.util.Try
import org.ergoplatform.dsl.ContractSyntax.{ErgoScript, Proposition, Token}
+import sigma.ast.{ErgoTree, EvaluatedValue, SType}
import scala.language.implicitConversions
trait ContractSpec {
- val dsl: SigmaDslBuilder = CostingSigmaDslBuilder
+ val dsl: SigmaDslBuilder = CSigmaDslBuilder
val Colls = dsl.Colls
implicit def Coll[T](items: Array[T])(implicit cT: RType[T]): Coll[T] = Colls.fromArray(items)
@@ -49,7 +49,7 @@ trait ContractSpec {
/** Generate proof for the given `inBox`. The input box has attached guarding proposition,
* which is executed in the Context, specifically created for `inBox`.*/
- def prove(inBox: InputBox, extensions: Map[Byte, AnyValue] = Map()): Try[CostedProverResult]
+ def prove(inBox: InputBox, extensions: Map[Byte, EvaluatedValue[_ <: SType]] = Map()): Try[CostedProverResult]
}
object ProvingParty {
def apply(name: String): ProvingParty = mkProvingParty(name)
@@ -68,7 +68,7 @@ trait ContractSpec {
trait InputBox {
def tx: TransactionCandidate
def utxoBox: OutBox
- def runDsl(extensions: Map[Byte, AnyValue] = Map()): SigmaProp
+ def runDsl(extensions: Map[Byte, EvaluatedValue[_ <: SType]] = Map()): SigmaProp
private [dsl] def toErgoContext: ErgoLikeContext
}
diff --git a/sc/shared/src/main/scala/org/ergoplatform/dsl/ContractSyntax.scala b/sc/shared/src/main/scala/org/ergoplatform/dsl/ContractSyntax.scala
index de3012ff8f..11cbaff739 100644
--- a/sc/shared/src/main/scala/org/ergoplatform/dsl/ContractSyntax.scala
+++ b/sc/shared/src/main/scala/org/ergoplatform/dsl/ContractSyntax.scala
@@ -1,17 +1,21 @@
package org.ergoplatform.dsl
+import org.ergoplatform.ErgoBox
import org.ergoplatform.ErgoBox.TokenId
-import sigma.data.RType
-import sigmastate.SType
-import sigmastate.SType.AnyOps
+import sigma.data.{AvlTreeData, CSigmaDslBuilder, RType, SigmaBoolean}
import org.ergoplatform.dsl.ContractSyntax.{ErgoScript, Proposition}
-import sigmastate.eval.{CostingSigmaDslBuilder, Evaluation}
+import org.ergoplatform.sdk.JavaHelpers.collRType
import sigmastate.interpreter.Interpreter.ScriptEnv
-import sigma.{SigmaProp, SigmaContract, Context, SigmaDslBuilder}
+import sigma._
+import sigma.ast.{SType, syntax}
+import sigma.ast.SType.AnyOps
+
+import scala.reflect.ClassTag
+import scala.util.Try
/** Defines methods to be used in contract implementations based on [[SigmaContract]]. */
trait ContractSyntax { contract: SigmaContract =>
- override def builder: SigmaDslBuilder = CostingSigmaDslBuilder
+ override def builder: SigmaDslBuilder = CSigmaDslBuilder
/** Instance of contract specification DSL, which can be imported in the body of
* [[SigmaContract]] implementations. */
@@ -29,6 +33,41 @@ trait ContractSyntax { contract: SigmaContract =>
/** Helper method to support Scala <-> ErgoScript equivalence. */
def Coll[T](items: T*)(implicit cT: RType[T]) = builder.Colls.fromItems(items:_*)
+ /** Tries to reconstruct RType of the given value.
+ * If not successfull returns failure. */
+ def rtypeOf(value: Any): Try[RType[_]] = Try {
+ value match {
+ case arr if arr.getClass.isArray =>
+ val itemClass = arr.getClass.getComponentType
+ if (itemClass.isPrimitive) {
+ val itemTag = ClassTag[Any](itemClass)
+ RType.fromClassTag(itemTag)
+ } else
+ sys.error(s"Cannot compute rtypeOf($value): non-primitive type of array items")
+ case coll: Coll[_] => collRType(coll.tItem)
+
+ // all primitive types
+ case _: Boolean => BooleanType
+ case _: Byte => ByteType
+ case _: Short => ShortType
+ case _: Int => IntType
+ case _: Long => LongType
+ case _: String => StringType
+ case _: Unit => UnitType
+ case _: sigma.BigInt => BigIntRType
+ case _: GroupElement => GroupElementRType
+ case _: ErgoBox => syntax.ErgoBoxRType // TODO remove this RType
+ case _: Box => BoxRType
+ case _: AvlTreeData => syntax.AvlTreeDataRType // TODO remove this RType
+ case _: AvlTree => AvlTreeRType
+ case _: SigmaBoolean => SigmaBooleanRType // TODO remove this RType
+ case _: SigmaProp => SigmaPropRType
+ case _: Context => ContextRType
+ case _ =>
+ sys.error(s"Don't know how to compute typeOf($value)")
+ }
+ }
+
/** Call this function in [[SigmaContract]] implementations to define propositions.
*
* @param name name of the proposition (aka contract name)
@@ -44,7 +83,7 @@ trait ContractSyntax { contract: SigmaContract =>
scriptCode: String,
scriptVersion: Option[Byte] = None): spec.PropositionSpec = {
val env = contractEnv.map { case (k, v) =>
- val tV = Evaluation.rtypeOf(v).get
+ val tV = rtypeOf(v).get
val elemTpe = Evaluation.rtypeToSType(tV)
k -> spec.IR.builder.mkConstant[SType](v.asWrappedType, elemTpe)
}.toMap
diff --git a/sc/shared/src/main/scala/org/ergoplatform/dsl/ErgoContractSpec.scala b/sc/shared/src/main/scala/org/ergoplatform/dsl/ErgoContractSpec.scala
index c1b0b40381..2c31304b70 100644
--- a/sc/shared/src/main/scala/org/ergoplatform/dsl/ErgoContractSpec.scala
+++ b/sc/shared/src/main/scala/org/ergoplatform/dsl/ErgoContractSpec.scala
@@ -1,10 +1,10 @@
package org.ergoplatform.dsl
import sigma.Coll
-import sigmastate.interpreter.CostedProverResult
import sigmastate.eval.IRContext
import org.ergoplatform.dsl.ContractSyntax.{ErgoScript, Proposition, Token}
import org.ergoplatform.ErgoBox.{BoxId, NonMandatoryRegisterId, TokenId}
+import sigma.interpreter.CostedProverResult
class ErgoContractSpec(implicit val IR: IRContext) extends ContractSpec {
diff --git a/sc/shared/src/main/scala/scalan/GraphIRReflection.scala b/sc/shared/src/main/scala/scalan/GraphIRReflection.scala
index f7218afc92..0eaba9d8a3 100644
--- a/sc/shared/src/main/scala/scalan/GraphIRReflection.scala
+++ b/sc/shared/src/main/scala/scalan/GraphIRReflection.scala
@@ -11,6 +11,10 @@ import special.wrappers.{OptionWrapSpec, RTypeWrapSpec}
import wrappers.scalan.WRTypes
/** Registrations of reflection metadata for graph-ir module (see README.md).
+ * Such metadata is only used on JS platform to support reflection-like interfaces of
+ * RClass, RMethod, RConstructor. These interfaces implemented on JVM using Java
+ * reflection.
+ *
* For each class of this module that needs reflection metadata,
* we register a class entry with the necessary information.
* Only information that is needed at runtime is registered.
@@ -26,10 +30,10 @@ object GraphIRReflection {
mkMethod(clazz, "filter", Array[Class[_]](classOf[Base#Ref[_]])) { (obj, args) =>
obj.asInstanceOf[ctx.WOption[Any]].filter(args(0).asInstanceOf[ctx.Ref[Any => Boolean]])
},
- mkMethod(clazz, "get", Array[Class[_]]()) { (obj, args) =>
+ mkMethod(clazz, "get", Array[Class[_]]()) { (obj, _) =>
obj.asInstanceOf[ctx.WOption[_]].get
},
- mkMethod(clazz, "isDefined", Array[Class[_]]()) { (obj, args) =>
+ mkMethod(clazz, "isDefined", Array[Class[_]]()) { (obj, _) =>
obj.asInstanceOf[ctx.WOption[_]].isDefined
},
mkMethod(clazz, "getOrElse", Array[Class[_]](classOf[Base#Ref[_]])) { (obj, args) =>
@@ -76,10 +80,10 @@ object GraphIRReflection {
mkMethod(clazz, "$bar$bar", Array[Class[_]](classOf[Base#Ref[_]])) { (obj, args) =>
obj.asInstanceOf[ctx.SigmaProp].$bar$bar(args(0).asInstanceOf[ctx.Ref[ctx.SigmaProp]])
},
- mkMethod(clazz, "isValid", Array[Class[_]]()) { (obj, args) =>
+ mkMethod(clazz, "isValid", Array[Class[_]]()) { (obj, _) =>
obj.asInstanceOf[ctx.SigmaProp].isValid
},
- mkMethod(clazz, "propBytes", Array[Class[_]]()) { (obj, args) =>
+ mkMethod(clazz, "propBytes", Array[Class[_]]()) { (obj, _) =>
obj.asInstanceOf[ctx.SigmaProp].propBytes
},
mkMethod(clazz, "$amp$amp", Array[Class[_]](classOf[Base#Ref[_]])) { (obj, args) =>
@@ -221,26 +225,26 @@ object GraphIRReflection {
obj.asInstanceOf[ctx.AvlTree].update(args(0).asInstanceOf[ctx.Ref[ctx.Coll[(ctx.Coll[Byte], ctx.Coll[Byte])]]],
args(1).asInstanceOf[ctx.Ref[ctx.Coll[Byte]]])
},
- mkMethod(clazz, "keyLength", Array[Class[_]]()) { (obj, args) =>
+ mkMethod(clazz, "keyLength", Array[Class[_]]()) { (obj, _) =>
obj.asInstanceOf[ctx.AvlTree].keyLength
},
- mkMethod(clazz, "enabledOperations", Array[Class[_]]()) { (obj, args) =>
+ mkMethod(clazz, "enabledOperations", Array[Class[_]]()) { (obj, _) =>
obj.asInstanceOf[ctx.AvlTree].enabledOperations
},
mkMethod(clazz, "updateDigest", Array[Class[_]](classOf[Base#Ref[_]])) { (obj, args) =>
obj.asInstanceOf[ctx.AvlTree].updateDigest(args(0).asInstanceOf[ctx.Ref[ctx.Coll[Byte]]])
},
- mkMethod(clazz, "digest", Array[Class[_]]()) { (obj, args) =>
+ mkMethod(clazz, "digest", Array[Class[_]]()) { (obj, _) =>
obj.asInstanceOf[ctx.AvlTree].digest
},
mkMethod(clazz, "insert", Array[Class[_]](classOf[Base#Ref[_]], classOf[Base#Ref[_]])) { (obj, args) =>
obj.asInstanceOf[ctx.AvlTree].insert(args(0).asInstanceOf[ctx.Ref[ctx.Coll[(ctx.Coll[Byte], ctx.Coll[Byte])]]],
args(1).asInstanceOf[ctx.Ref[ctx.Coll[Byte]]])
},
- mkMethod(clazz, "isRemoveAllowed", Array[Class[_]]()) { (obj, args) =>
+ mkMethod(clazz, "isRemoveAllowed", Array[Class[_]]()) { (obj, _) =>
obj.asInstanceOf[ctx.AvlTree].isRemoveAllowed
},
- mkMethod(clazz, "valueLengthOpt", Array[Class[_]]()) { (obj, args) =>
+ mkMethod(clazz, "valueLengthOpt", Array[Class[_]]()) { (obj, _) =>
obj.asInstanceOf[ctx.AvlTree].valueLengthOpt
},
mkMethod(clazz, "get", Array[Class[_]](classOf[Base#Ref[_]], classOf[Base#Ref[_]])) { (obj, args) =>
@@ -254,10 +258,10 @@ object GraphIRReflection {
obj.asInstanceOf[ctx.AvlTree].contains(args(0).asInstanceOf[ctx.Ref[ctx.Coll[Byte]]],
args(1).asInstanceOf[ctx.Ref[ctx.Coll[Byte]]])
},
- mkMethod(clazz, "isUpdateAllowed", Array[Class[_]]()) { (obj, args) =>
+ mkMethod(clazz, "isUpdateAllowed", Array[Class[_]]()) { (obj, _) =>
obj.asInstanceOf[ctx.AvlTree].isUpdateAllowed
},
- mkMethod(clazz, "isInsertAllowed", Array[Class[_]]()) { (obj, args) =>
+ mkMethod(clazz, "isInsertAllowed", Array[Class[_]]()) { (obj, _) =>
obj.asInstanceOf[ctx.AvlTree].isInsertAllowed
}
)
@@ -268,22 +272,22 @@ object GraphIRReflection {
val ctx = null.asInstanceOf[SigmaLibrary] // ok! type level only
registerClassEntry(clazz,
methods = Map(
- mkMethod(clazz, "value", Array[Class[_]]()) { (obj, args) =>
+ mkMethod(clazz, "value", Array[Class[_]]()) { (obj, _) =>
obj.asInstanceOf[ctx.Box].value
},
- mkMethod(clazz, "id", Array[Class[_]]()) { (obj, args) =>
+ mkMethod(clazz, "id", Array[Class[_]]()) { (obj, _) =>
obj.asInstanceOf[ctx.Box].id
},
- mkMethod(clazz, "creationInfo", Array[Class[_]]()) { (obj, args) =>
+ mkMethod(clazz, "creationInfo", Array[Class[_]]()) { (obj, _) =>
obj.asInstanceOf[ctx.Box].creationInfo
},
- mkMethod(clazz, "bytes", Array[Class[_]]()) { (obj, args) =>
+ mkMethod(clazz, "bytes", Array[Class[_]]()) { (obj, _) =>
obj.asInstanceOf[ctx.Box].bytes
},
mkMethod(clazz, "getReg", Array[Class[_]](classOf[Base#Ref[_]], classOf[TypeDescs#Elem[_]])) { (obj, args) =>
obj.asInstanceOf[ctx.Box].getReg(args(0).asInstanceOf[ctx.Ref[Int]])(args(1).asInstanceOf[ctx.Elem[_]])
},
- mkMethod(clazz, "tokens", Array[Class[_]]()) { (obj, args) =>
+ mkMethod(clazz, "tokens", Array[Class[_]]()) { (obj, _) =>
obj.asInstanceOf[ctx.Box].tokens
},
mkMethod(clazz, "bytesWithoutRef", Array[Class[_]]()) { (obj, args) =>
@@ -415,25 +419,25 @@ object GraphIRReflection {
val ctx = null.asInstanceOf[SigmaLibrary] // ok! type level only
registerClassEntry(clazz,
methods = Map(
- mkMethod(clazz, "minerPk", Array[Class[_]]()) { (obj, args) =>
+ mkMethod(clazz, "minerPk", Array[Class[_]]()) { (obj, _) =>
obj.asInstanceOf[ctx.PreHeader].minerPk
},
- mkMethod(clazz, "votes", Array[Class[_]]()) { (obj, args) =>
+ mkMethod(clazz, "votes", Array[Class[_]]()) { (obj, _) =>
obj.asInstanceOf[ctx.PreHeader].votes
},
- mkMethod(clazz, "nBits", Array[Class[_]]()) { (obj, args) =>
+ mkMethod(clazz, "nBits", Array[Class[_]]()) { (obj, _) =>
obj.asInstanceOf[ctx.PreHeader].nBits
},
- mkMethod(clazz, "version", Array[Class[_]]()) { (obj, args) =>
+ mkMethod(clazz, "version", Array[Class[_]]()) { (obj, _) =>
obj.asInstanceOf[ctx.PreHeader].version
},
- mkMethod(clazz, "timestamp", Array[Class[_]]()) { (obj, args) =>
+ mkMethod(clazz, "timestamp", Array[Class[_]]()) { (obj, _) =>
obj.asInstanceOf[ctx.PreHeader].timestamp
},
- mkMethod(clazz, "parentId", Array[Class[_]]()) { (obj, args) =>
+ mkMethod(clazz, "parentId", Array[Class[_]]()) { (obj, _) =>
obj.asInstanceOf[ctx.PreHeader].parentId
},
- mkMethod(clazz, "height", Array[Class[_]]()) { (obj, args) =>
+ mkMethod(clazz, "height", Array[Class[_]]()) { (obj, _) =>
obj.asInstanceOf[ctx.PreHeader].height
}
)
diff --git a/sc/shared/src/main/scala/scalan/TypeDescs.scala b/sc/shared/src/main/scala/scalan/TypeDescs.scala
index cb5f954109..fdef77a108 100644
--- a/sc/shared/src/main/scala/scalan/TypeDescs.scala
+++ b/sc/shared/src/main/scala/scalan/TypeDescs.scala
@@ -3,7 +3,6 @@ package scalan
import scala.language.implicitConversions
import scala.annotation.implicitNotFound
import scala.collection.immutable.ListMap
-import sigma.data.RType._
import scala.collection.mutable
import debox.cfor
diff --git a/sc/shared/src/main/scala/scalan/primitives/Functions.scala b/sc/shared/src/main/scala/scalan/primitives/Functions.scala
index e5cd6f345e..31a6ca8d81 100644
--- a/sc/shared/src/main/scala/scalan/primitives/Functions.scala
+++ b/sc/shared/src/main/scala/scalan/primitives/Functions.scala
@@ -332,7 +332,7 @@ trait Functions extends Base with ProgramGraphs { self: Scalan =>
val m = new java.util.HashMap[Sym, Sym](100)
m.put(lam.x, s)
val subst = new MapTransformer(m)
- val t = DefaultMirror.mirrorSymbols(subst, NoRewriting, lam, body)
+ val t = DefaultMirror.mirrorSymbols(subst, NoRewriting, body)
t(lam.y)
}
diff --git a/sc/shared/src/main/scala/scalan/primitives/Thunks.scala b/sc/shared/src/main/scala/scalan/primitives/Thunks.scala
index ce51dc5638..f9f843664d 100644
--- a/sc/shared/src/main/scala/scalan/primitives/Thunks.scala
+++ b/sc/shared/src/main/scala/scalan/primitives/Thunks.scala
@@ -323,7 +323,7 @@ trait Thunks extends Functions { self: Scalan =>
*/
def forceThunkDefByMirror[A](th: ThunkDef[A], subst: MapTransformer = MapTransformer.empty()): Ref[A] = {
val body = th.scheduleIds
- val t = DefaultMirror.mirrorSymbols(subst, NoRewriting, th, body)
+ val t = DefaultMirror.mirrorSymbols(subst, NoRewriting, body)
t(th.root)
}
diff --git a/sc/shared/src/main/scala/scalan/primitives/Tuples.scala b/sc/shared/src/main/scala/scalan/primitives/Tuples.scala
index c22b8a31f4..fd201b9574 100644
--- a/sc/shared/src/main/scala/scalan/primitives/Tuples.scala
+++ b/sc/shared/src/main/scala/scalan/primitives/Tuples.scala
@@ -58,8 +58,6 @@ trait Tuples extends Base { self: Scalan =>
case Tup(a, b) => (a, b)
case _ => p.elem match {
case pe: PairElem[_, _] =>
- implicit val eA = pe.eFst
- implicit val eB = pe.eSnd
if (cachePairs) {
if (!tuplesCache.containsKey(p)) {
tuplesCache.put(p, (First(p), Second(p)))
@@ -74,8 +72,6 @@ trait Tuples extends Base { self: Scalan =>
}
implicit def zipPair[A, B](p: (Ref[A], Ref[B])): Ref[(A, B)] = {
- implicit val ea = p._1.elem
- implicit val eb = p._2.elem
Tup(p._1, p._2)
}
diff --git a/sc/shared/src/main/scala/scalan/staged/ProgramGraphs.scala b/sc/shared/src/main/scala/scalan/staged/ProgramGraphs.scala
index 19d762c5bb..ccb351e7a2 100644
--- a/sc/shared/src/main/scala/scalan/staged/ProgramGraphs.scala
+++ b/sc/shared/src/main/scala/scalan/staged/ProgramGraphs.scala
@@ -63,28 +63,6 @@ trait ProgramGraphs extends AstGraphs { self: Scalan =>
sch
}
- /** Mirror all the nodes of this graph applying transformer and performing rewriting.
- * @param m mirror instance to be used for mirroring of nodes
- * @param rw rewriter to be tried for each new created mirrored node
- * @param t transformer of symbols, to be used for substitution of symbols in the new nodes.
- * @return new graph which is not necessary clone of this graph, but should be semantically
- * equivalent to this graph (provided all rw rules preserve equivalence).
- * If rw is identity, then the resulting graph is alpha-equivalent to this graph
- * as long as t is bijection.
- */
- def transform(m: Mirror, rw: Rewriter, t: Transformer): ProgramGraph = {
- val t0 = mapping match {
- case Nullable(mapping) => t merge mapping
- case _ => t
- }
- val t1 = m.mirrorSymbols(t0, rw, this, scheduleIds)
- val newRoots = roots map { t1(_) }
- new ProgramGraph(newRoots, Nullable(t1), filterNode)
- }
-
- /** Remove transformer component of the graph. */
- def withoutContext = ProgramGraph(roots, Nullable.None, filterNode)
-
override def toString: String = {
val mappingStr = if (mapping.isEmpty) "None" else mapping.toString
val filterNodeStr = if (filterNode.isDefined) filterNode.toString else "None"
@@ -92,11 +70,4 @@ trait ProgramGraphs extends AstGraphs { self: Scalan =>
}
}
- object ProgramGraph {
- def transform[A](s: Ref[A], rw: Rewriter = NoRewriting, t: MapTransformer = MapTransformer.empty()): Ref[A] = {
- val g = ProgramGraph(List(s), Nullable.None, Nullable.None)
- val g1 = g.transform(DefaultMirror, rw, t)
- g1.roots(0).asInstanceOf[Ref[A]]
- }
- }
}
diff --git a/sc/shared/src/main/scala/scalan/staged/Transforming.scala b/sc/shared/src/main/scala/scalan/staged/Transforming.scala
index 045340e503..cd1fac9fd0 100644
--- a/sc/shared/src/main/scala/scalan/staged/Transforming.scala
+++ b/sc/shared/src/main/scala/scalan/staged/Transforming.scala
@@ -65,10 +65,6 @@ trait Transforming { self: Scalan =>
def beginPass(pass: Pass): Unit = {
_currentPass = pass
}
- /** Called to let this IR context to finalized the given pass. */
- def endPass(pass: Pass): Unit = {
- _currentPass = Pass.defaultPass
- }
/** Concrete and default implementation of Transformer using underlying HashMap.
* HOTSPOT: don't beatify the code */
@@ -152,7 +148,7 @@ trait Transforming { self: Scalan =>
protected def mirrorElem(node: Sym): Elem[_] = node.elem
// every mirrorXXX method should return a pair (t + (v -> v1), v1)
- protected def mirrorVar[A](t: Transformer, rewriter: Rewriter, v: Ref[A]): Transformer = {
+ protected def mirrorVar[A](t: Transformer, v: Ref[A]): Transformer = {
val newVar = variable(Lazy(mirrorElem(v)))
t + (v, newVar)
}
@@ -173,7 +169,7 @@ trait Transforming { self: Scalan =>
protected def mirrorLambda[A, B](t: Transformer, rewriter: Rewriter, node: Ref[A => B], lam: Lambda[A, B]): Transformer = {
var tRes: Transformer = t
- val t1 = mirrorNode(t, rewriter, lam, lam.x)
+ val t1 = mirrorNode(t, rewriter, lam.x)
// original root
val originalRoot = lam.y
@@ -190,7 +186,7 @@ trait Transforming { self: Scalan =>
// lambdaStack = newLambdaCandidate :: lambdaStack
val newRoot = { // reifyEffects block
val schedule = lam.scheduleIds
- val t2 = mirrorSymbols(t1, rewriter, lam, schedule)
+ val t2 = mirrorSymbols(t1, rewriter, schedule)
tRes = t2
tRes(originalRoot) // this will be a new root
}
@@ -214,7 +210,7 @@ trait Transforming { self: Scalan =>
val newScope = thunkStack.beginScope(newThunkSym)
val schedule = thunk.scheduleIds
- val t1 = mirrorSymbols(t, rewriter, thunk, schedule)
+ val t1 = mirrorSymbols(t, rewriter, schedule)
thunkStack.endScope()
val newRoot = t1(thunk.root)
@@ -230,12 +226,12 @@ trait Transforming { self: Scalan =>
protected def isMirrored(t: Transformer, node: Sym): Boolean = t.isDefinedAt(node)
- def mirrorNode(t: Transformer, rewriter: Rewriter, g: AstGraph, node: Sym): Transformer = {
+ def mirrorNode(t: Transformer, rewriter: Rewriter, node: Sym): Transformer = {
if (isMirrored(t, node)) t
else {
node.node match {
- case v: Variable[_] =>
- mirrorVar(t, rewriter, node)
+ case _: Variable[_] =>
+ mirrorVar(t, node)
case lam: Lambda[a, b] =>
mirrorLambda(t, rewriter, node.asInstanceOf[Ref[a => b]], lam)
case th: ThunkDef[a] =>
@@ -247,12 +243,12 @@ trait Transforming { self: Scalan =>
}
/** HOTSPOT: */
- def mirrorSymbols(t0: Transformer, rewriter: Rewriter, g: AstGraph, nodes: DBuffer[Int]) = {
+ def mirrorSymbols(t0: Transformer, rewriter: Rewriter, nodes: DBuffer[Int]): Transformer = {
var t: Transformer = t0
cfor(0)(_ < nodes.length, _ + 1) { i =>
val n = nodes(i)
val s = getSym(n)
- t = mirrorNode(t, rewriter, g, s)
+ t = mirrorNode(t, rewriter, s)
}
t
}
diff --git a/sc/shared/src/main/scala/sigmastate/eval/GraphBuilding.scala b/sc/shared/src/main/scala/sigmastate/eval/GraphBuilding.scala
index 99467289f2..9c9fa5ffe1 100644
--- a/sc/shared/src/main/scala/sigmastate/eval/GraphBuilding.scala
+++ b/sc/shared/src/main/scala/sigmastate/eval/GraphBuilding.scala
@@ -2,20 +2,20 @@ package sigmastate.eval
import org.ergoplatform._
import scalan.MutableLazy
+import sigma.{SigmaException, ast}
+import sigma.ast.TypeCodes.LastConstantCode
+import sigma.ast.Value.Typed
+import sigma.ast._
+import sigma.ast.syntax.{SValue, ValueOps}
+import sigma.crypto.EcPointType
import sigma.data.ExactIntegral.{ByteIsExactIntegral, IntIsExactIntegral, LongIsExactIntegral, ShortIsExactIntegral}
import sigma.data.ExactOrdering.{ByteIsExactOrdering, IntIsExactOrdering, LongIsExactOrdering, ShortIsExactOrdering}
+import sigma.data.{CSigmaDslBuilder, ExactIntegral, ExactNumeric, ExactOrdering, Lazy, Nullable}
import sigma.util.Extensions.ByteOps
-import sigma.data.{ExactIntegral, ExactNumeric, ExactOrdering, Lazy, Nullable}
-import sigmastate.Values.Value.Typed
-import sigmastate.Values._
import sigmastate.interpreter.Interpreter.ScriptEnv
-import sigmastate.lang.{SourceContext, Terms}
-import sigmastate.lang.Terms.{Ident, Select, Val, ValueOps}
-import sigmastate.serialization.OpCodes
-import sigmastate.utxo._
-import sigmastate._
-import sigmastate.crypto.CryptoConstants.EcPointType
-import sigmastate.exceptions.{GraphBuildingException, SigmaException}
+import sigma.ast.{Ident, Select, Val}
+import sigma.exceptions.GraphBuildingException
+import sigma.serialization.OpCodes
import scala.collection.mutable.ArrayBuffer
@@ -43,10 +43,9 @@ trait GraphBuilding extends SigmaLibrary { IR: IRContext =>
import WOption._
/** Should be specified in the final cake */
- val builder: sigmastate.lang.SigmaBuilder
+ val builder: SigmaBuilder
import builder._
-
val okMeasureOperationTime: Boolean = false
this.isInlineThunksOnForce = true // this required for splitting of cost graph
@@ -60,16 +59,6 @@ trait GraphBuilding extends SigmaLibrary { IR: IRContext =>
/** Whether to save calcF and costF graphs in the file given by ScriptNameProp environment variable */
var saveGraphsInFile: Boolean = false
- // /** Pass configuration which is used by default in IRContext. */
- // val calcPass = new DefaultPass("calcPass", Pass.defaultPassConfig.copy(constantPropagation = true))
- //
- // /** Pass configuration which is used during splitting cost function out of cost graph.
- // * @see `RuntimeCosting.split2` */
- // val costPass = new DefaultPass("costPass", Pass.defaultPassConfig.copy(constantPropagation = true))
-
- /** To enable specific configuration uncomment one of the lines above and use it in the beginPass below. */
- // beginPass(costPass)
-
/** Check the tuple type is valid.
* In v5.x this code is taken from CheckTupleType validation rule which is no longer
* part of consensus.
@@ -173,7 +162,7 @@ trait GraphBuilding extends SigmaLibrary { IR: IRContext =>
case ThunkForce(Def(ThunkDef(root, sch))) if sch.isEmpty => root
// Rule: l.isValid op Thunk {... root} => (l op TrivialSigma(root)).isValid
- case ApplyBinOpLazy(op, SigmaM.isValid(l), Def(ThunkDef(root, sch))) if root.elem == BooleanElement =>
+ case ApplyBinOpLazy(op, SigmaM.isValid(l), Def(ThunkDef(root, _))) if root.elem == BooleanElement =>
// don't need new Thunk because sigma logical ops always strict
val r = asRep[SigmaProp](sigmaDslBuilder.sigmaProp(asRep[Boolean](root)))
val res = if (op == And)
@@ -298,7 +287,7 @@ trait GraphBuilding extends SigmaLibrary { IR: IRContext =>
case _: BigIntElem[_] => SBigInt
case _: GroupElementElem[_] => SGroupElement
case _: AvlTreeElem[_] => SAvlTree
- case oe: WOptionElem[_, _] => sigmastate.SOption(elemToSType(oe.eItem))
+ case oe: WOptionElem[_, _] => SOption(elemToSType(oe.eItem))
case _: BoxElem[_] => SBox
case _: ContextElem[_] => SContext
case _: SigmaDslBuilderElem[_] => SGlobal
@@ -311,8 +300,6 @@ trait GraphBuilding extends SigmaLibrary { IR: IRContext =>
case _ => error(s"Don't know how to convert Elem $e to SType")
}
- import Liftables._
-
/** Translates Elem to the corresponding Liftable instance.
* @param eWT type descriptor
*/
@@ -339,7 +326,7 @@ trait GraphBuilding extends SigmaLibrary { IR: IRContext =>
FuncIsLiftable(la, lb)
}).asInstanceOf[Liftable[_,WT]]
- import NumericOps._
+ import sigma.data.NumericOps._
private lazy val elemToExactNumericMap = Map[Elem[_], ExactNumeric[_]](
(ByteElement, ByteIsExactIntegral),
(ShortElement, ShortIsExactIntegral),
@@ -390,12 +377,12 @@ trait GraphBuilding extends SigmaLibrary { IR: IRContext =>
case OpCodes.LtCode => OrderingLT[A](elemToExactOrdering(eA))
case OpCodes.GeCode => OrderingGTEQ[A](elemToExactOrdering(eA))
case OpCodes.LeCode => OrderingLTEQ[A](elemToExactOrdering(eA))
- case _ => error(s"Cannot find BinOp for opcode newOpCode(${opCode.toUByte-OpCodes.LastConstantCode}) and type $eA")
+ case _ => error(s"Cannot find BinOp for opcode newOpCode(${opCode.toUByte - LastConstantCode}) and type $eA")
}
import sigmastate._
- protected implicit def groupElementToECPoint(g: sigma.GroupElement): EcPointType = CostingSigmaDslBuilder.toECPoint(g).asInstanceOf[EcPointType]
+ protected implicit def groupElementToECPoint(g: sigma.GroupElement): EcPointType = CSigmaDslBuilder.toECPoint(g).asInstanceOf[EcPointType]
def error(msg: String) = throw new GraphBuildingException(msg, None)
def error(msg: String, srcCtx: Option[SourceContext]) = throw new GraphBuildingException(msg, srcCtx)
@@ -484,7 +471,7 @@ trait GraphBuilding extends SigmaLibrary { IR: IRContext =>
val resV = toRep(v)(e)
resV
}
- case org.ergoplatform.Context => ctx
+ case sigma.ast.Context => ctx
case Global => sigmaDslBuilder
case Height => ctx.HEIGHT
case Inputs => ctx.INPUTS
@@ -496,10 +483,10 @@ trait GraphBuilding extends SigmaLibrary { IR: IRContext =>
case Ident(n, _) =>
env.getOrElse(n, !!!(s"Variable $n not found in environment $env"))
- case sigmastate.Upcast(Constant(value, _), toTpe: SNumericType) =>
+ case ast.Upcast(Constant(value, _), toTpe: SNumericType) =>
eval(mkConstant(toTpe.upcast(value.asInstanceOf[AnyVal]), toTpe))
- case sigmastate.Downcast(Constant(value, _), toTpe: SNumericType) =>
+ case ast.Downcast(Constant(value, _), toTpe: SNumericType) =>
eval(mkConstant(toTpe.downcast(value.asInstanceOf[AnyVal]), toTpe))
// Rule: col.size --> SizeOf(col)
@@ -510,11 +497,11 @@ trait GraphBuilding extends SigmaLibrary { IR: IRContext =>
error(s"The type of $obj is expected to be Collection to select 'size' property", obj.sourceContext.toOption)
// Rule: proof.isProven --> IsValid(proof)
- case Select(p, SSigmaProp.IsProven, _) if p.tpe == SSigmaProp =>
+ case Select(p, SSigmaPropMethods.IsProven, _) if p.tpe == SSigmaProp =>
eval(SigmaPropIsProven(p.asSigmaProp))
// Rule: prop.propBytes --> SigmaProofBytes(prop)
- case Select(p, SSigmaProp.PropBytes, _) if p.tpe == SSigmaProp =>
+ case Select(p, SSigmaPropMethods.PropBytes, _) if p.tpe == SSigmaProp =>
eval(SigmaPropBytes(p.asSigmaProp))
// box.R$i[valType] =>
@@ -525,12 +512,12 @@ trait GraphBuilding extends SigmaLibrary { IR: IRContext =>
case sel @ Select(obj, field, _) if obj.tpe == SBox =>
(obj.asValue[SBox.type], field) match {
- case (box, SBox.Value) => eval(mkExtractAmount(box))
- case (box, SBox.PropositionBytes) => eval(mkExtractScriptBytes(box))
- case (box, SBox.Id) => eval(mkExtractId(box))
- case (box, SBox.Bytes) => eval(mkExtractBytes(box))
- case (box, SBox.BytesWithoutRef) => eval(mkExtractBytesWithNoRef(box))
- case (box, SBox.CreationInfo) => eval(mkExtractCreationInfo(box))
+ case (box, SBoxMethods.Value) => eval(mkExtractAmount(box))
+ case (box, SBoxMethods.PropositionBytes) => eval(mkExtractScriptBytes(box))
+ case (box, SBoxMethods.Id) => eval(mkExtractId(box))
+ case (box, SBoxMethods.Bytes) => eval(mkExtractBytes(box))
+ case (box, SBoxMethods.BytesWithoutRef) => eval(mkExtractBytesWithNoRef(box))
+ case (box, SBoxMethods.CreationInfo) => eval(mkExtractCreationInfo(box))
case _ => error(s"Invalid access to Box property in $sel: field $field is not found", sel.sourceContext.toOption)
}
@@ -539,7 +526,7 @@ trait GraphBuilding extends SigmaLibrary { IR: IRContext =>
eval(mkSelectField(tuple.asTuple, index))
case Select(obj, method, Some(tRes: SNumericType))
- if obj.tpe.isNumType && obj.asNumValue.tpe.isCastMethod(method) =>
+ if obj.tpe.isNumType && SNumericTypeMethods.isCastMethod(method) =>
val numValue = obj.asNumValue
if (numValue.tpe == tRes)
eval(numValue)
@@ -548,7 +535,7 @@ trait GraphBuilding extends SigmaLibrary { IR: IRContext =>
else
eval(mkUpcast(numValue, tRes))
- case Terms.Apply(col, Seq(index)) if col.tpe.isCollection =>
+ case sigma.ast.Apply(col, Seq(index)) if col.tpe.isCollection =>
eval(mkByIndex(col.asCollection[SType], index.asValue[SInt.type], None))
case GetVar(id, optTpe) =>
@@ -558,7 +545,7 @@ trait GraphBuilding extends SigmaLibrary { IR: IRContext =>
case ValUse(valId, _) =>
env.getOrElse(valId, !!!(s"ValUse $valId not found in environment $env"))
- case Terms.Block(binds, res) =>
+ case Block(binds, res) =>
var curEnv = env
for (v @ Val(n, _, b) <- binds) {
if (curEnv.contains(n))
@@ -591,37 +578,37 @@ trait GraphBuilding extends SigmaLibrary { IR: IRContext =>
val vv = asRep[GroupElement](_vv)
sigmaDslBuilder.proveDHTuple(gv, hv, uv, vv)
- case sigmastate.Exponentiate(In(l), In(r)) =>
+ case Exponentiate(In(l), In(r)) =>
val lV = asRep[GroupElement](l)
val rV = asRep[BigInt](r)
lV.exp(rV)
- case sigmastate.MultiplyGroup(In(_l), In(_r)) =>
+ case MultiplyGroup(In(_l), In(_r)) =>
val l = asRep[GroupElement](_l)
val r = asRep[GroupElement](_r)
l.multiply(r)
- case Values.GroupGenerator =>
+ case GroupGenerator =>
sigmaDslBuilder.groupGenerator
- case sigmastate.ByteArrayToBigInt(In(arr)) =>
+ case ByteArrayToBigInt(In(arr)) =>
val arrV = asRep[Coll[Byte]](arr)
sigmaDslBuilder.byteArrayToBigInt(arrV)
- case sigmastate.LongToByteArray(In(x)) =>
+ case LongToByteArray(In(x)) =>
val xV = asRep[Long](x)
sigmaDslBuilder.longToByteArray(xV)
// opt.get
- case utxo.OptionGet(In(opt: ROption[_]@unchecked)) =>
+ case OptionGet(In(opt: ROption[_]@unchecked)) =>
opt.get
// opt.isDefined
- case utxo.OptionIsDefined(In(opt: ROption[_]@unchecked)) =>
+ case OptionIsDefined(In(opt: ROption[_]@unchecked)) =>
opt.isDefined
// opt.getOrElse(default)
- case utxo.OptionGetOrElse(In(opt: ROption[a]@unchecked), In(default)) =>
+ case OptionGetOrElse(In(opt: ROption[a]@unchecked), In(default)) =>
opt.getOrElse(asRep[a](default))
// tup._1 or tup._2
@@ -630,16 +617,14 @@ trait GraphBuilding extends SigmaLibrary { IR: IRContext =>
checkTupleType(IR)(eTuple)
eTuple match {
case pe: PairElem[a,b] =>
- assert(fieldIndex == 1 || fieldIndex == 2, s"Invalid field index $fieldIndex of the pair ${tup}: $pe")
- implicit val ea = pe.eFst
- implicit val eb = pe.eSnd
+ assert(fieldIndex == 1 || fieldIndex == 2, s"Invalid field index $fieldIndex of the pair $tup: $pe")
val pair = asRep[(a,b)](tup)
val res = if (fieldIndex == 1) pair._1 else pair._2
res
}
// (x, y)
- case Values.Tuple(InSeq(Seq(x, y))) =>
+ case Tuple(InSeq(Seq(x, y))) =>
Pair(x, y)
// xs.exists(predicate) or xs.forall(predicate)
@@ -705,7 +690,7 @@ trait GraphBuilding extends SigmaLibrary { IR: IRContext =>
val pV = asRep[Any => Boolean](eval(p))
inputV.filter(pV)
- case Terms.Apply(f, Seq(x)) if f.tpe.isFunc =>
+ case sigma.ast.Apply(f, Seq(x)) if f.tpe.isFunc =>
val fV = asRep[Any => Coll[Any]](eval(f))
val xV = asRep[Any](eval(x))
Apply(fV, xV, mayInline = false)
@@ -720,7 +705,7 @@ trait GraphBuilding extends SigmaLibrary { IR: IRContext =>
val res = sigmaDslBuilder.sha256(inputV)
res
- case utxo.SizeOf(In(xs)) =>
+ case ast.SizeOf(In(xs)) =>
xs.elem.asInstanceOf[Any] match {
case _: CollElem[a,_] =>
val xsV = asRep[Coll[a]](xs)
@@ -749,26 +734,26 @@ trait GraphBuilding extends SigmaLibrary { IR: IRContext =>
val pV = asRep[SigmaProp](eval(p))
pV.propBytes
- case utxo.ExtractId(In(box: Ref[Box]@unchecked)) =>
+ case ExtractId(In(box: Ref[Box]@unchecked)) =>
box.id
- case utxo.ExtractBytesWithNoRef(In(box: Ref[Box]@unchecked)) =>
+ case ExtractBytesWithNoRef(In(box: Ref[Box]@unchecked)) =>
box.bytesWithoutRef
- case utxo.ExtractAmount(In(box)) =>
+ case ExtractAmount(In(box)) =>
val boxV = asRep[Box](box)
boxV.value
- case utxo.ExtractScriptBytes(In(box: Ref[Box]@unchecked)) =>
+ case ExtractScriptBytes(In(box: Ref[Box]@unchecked)) =>
box.propositionBytes
- case utxo.ExtractBytes(In(box: Ref[Box]@unchecked)) =>
+ case ExtractBytes(In(box: Ref[Box]@unchecked)) =>
box.bytes
- case utxo.ExtractCreationInfo(In(box: Ref[Box]@unchecked)) =>
+ case ExtractCreationInfo(In(box: Ref[Box]@unchecked)) =>
box.creationInfo
- case utxo.ExtractRegisterAs(In(box: Ref[Box]@unchecked), regId, optTpe) =>
+ case ExtractRegisterAs(In(box: Ref[Box]@unchecked), regId, optTpe) =>
val elem = stypeToElem(optTpe.elemType).asInstanceOf[Elem[Any]]
val i: Ref[Int] = regId.number.toInt
box.getReg(i)(elem)
@@ -886,14 +871,14 @@ trait GraphBuilding extends SigmaLibrary { IR: IRContext =>
val y = eval(rel.right)
binop.apply(x, asRep[t#WrappedType](y))
- case Terms.Lambda(_, Seq((n, argTpe)), _, Some(body)) =>
+ case sigma.ast.Lambda(_, Seq((n, argTpe)), _, Some(body)) =>
val eArg = stypeToElem(argTpe).asInstanceOf[Elem[Any]]
val f = fun(removeIsProven({ x: Ref[Any] =>
buildNode(ctx, env + (n -> x), body)
}))(Lazy(eArg))
f
- case Terms.Lambda(_, Seq((accN, accTpe), (n, tpe)), _, Some(body)) =>
+ case sigma.ast.Lambda(_, Seq((accN, accTpe), (n, tpe)), _, Some(body)) =>
(stypeToElem(accTpe), stypeToElem(tpe)) match { case (eAcc: Elem[s], eA: Elem[a]) =>
val eArg = pairElement(eAcc, eA)
val f = fun { x: Ref[(s, a)] =>
@@ -914,11 +899,11 @@ trait GraphBuilding extends SigmaLibrary { IR: IRContext =>
val values = colBuilder.fromItems(vs: _*)(eAny)
values
- case sigmastate.Upcast(In(input), tpe) =>
+ case ast.Upcast(In(input), tpe) =>
val elem = stypeToElem(tpe.asNumType)
upcast(input)(elem)
- case sigmastate.Downcast(In(input), tpe) =>
+ case ast.Downcast(In(input), tpe) =>
val elem = stypeToElem(tpe.asNumType)
downcast(input)(elem)
@@ -936,221 +921,221 @@ trait GraphBuilding extends SigmaLibrary { IR: IRContext =>
sigmaDslBuilder.decodePoint(bytes)
// fallback rule for MethodCall, should be the last case in the list
- case Terms.MethodCall(obj, method, args, _) =>
+ case sigma.ast.MethodCall(obj, method, args, _) =>
val objV = eval(obj)
val argsV = args.map(eval)
(objV, method.objType) match {
- case (xs: RColl[t]@unchecked, SCollection) => method.name match {
- case SCollection.IndicesMethod.name =>
+ case (xs: RColl[t]@unchecked, SCollectionMethods) => method.name match {
+ case SCollectionMethods.IndicesMethod.name =>
xs.indices
- case SCollection.PatchMethod.name =>
+ case SCollectionMethods.PatchMethod.name =>
val from = asRep[Int](argsV(0))
val patch = asRep[Coll[t]](argsV(1))
val replaced = asRep[Int](argsV(2))
xs.patch(from, patch, replaced)
- case SCollection.UpdatedMethod.name =>
+ case SCollectionMethods.UpdatedMethod.name =>
val index = asRep[Int](argsV(0))
val value = asRep[t](argsV(1))
xs.updated(index, value)
- case SCollection.AppendMethod.name =>
+ case SCollectionMethods.AppendMethod.name =>
val ys = asRep[Coll[t]](argsV(0))
xs.append(ys)
- case SCollection.SliceMethod.name =>
+ case SCollectionMethods.SliceMethod.name =>
val from = asRep[Int](argsV(0))
val until = asRep[Int](argsV(1))
xs.slice(from, until)
- case SCollection.UpdateManyMethod.name =>
+ case SCollectionMethods.UpdateManyMethod.name =>
val indexes = asRep[Coll[Int]](argsV(0))
val values = asRep[Coll[t]](argsV(1))
xs.updateMany(indexes, values)
- case SCollection.IndexOfMethod.name =>
+ case SCollectionMethods.IndexOfMethod.name =>
val elem = asRep[t](argsV(0))
val from = asRep[Int](argsV(1))
xs.indexOf(elem, from)
- case SCollection.ZipMethod.name =>
+ case SCollectionMethods.ZipMethod.name =>
val ys = asRep[Coll[Any]](argsV(0))
xs.zip(ys)
- case SCollection.FlatMapMethod.name =>
+ case SCollectionMethods.FlatMapMethod.name =>
val f = asRep[Any => Coll[Any]](argsV(0))
xs.flatMap(f)
- case SCollection.MapMethod.name =>
+ case SCollectionMethods.MapMethod.name =>
val f = asRep[Any => Any](argsV(0))
xs.map(f)
- case SCollection.FilterMethod.name =>
+ case SCollectionMethods.FilterMethod.name =>
val p = asRep[Any => Boolean](argsV(0))
xs.filter(p)
- case SCollection.ForallMethod.name =>
+ case SCollectionMethods.ForallMethod.name =>
val p = asRep[Any => Boolean](argsV(0))
xs.forall(p)
- case SCollection.ExistsMethod.name =>
+ case SCollectionMethods.ExistsMethod.name =>
val p = asRep[Any => Boolean](argsV(0))
xs.exists(p)
- case SCollection.FoldMethod.name =>
+ case SCollectionMethods.FoldMethod.name =>
val zero = asRep[Any](argsV(0))
val op = asRep[((Any, Any)) => Any](argsV(1))
xs.foldLeft(zero, op)
- case SCollection.GetOrElseMethod.name =>
+ case SCollectionMethods.GetOrElseMethod.name =>
val i = asRep[Int](argsV(0))
val d = asRep[t](argsV(1))
xs.getOrElse(i, d)
case _ => throwError
}
- case (opt: ROption[t]@unchecked, SOption) => method.name match {
- case SOption.GetMethod.name =>
+ case (opt: ROption[t]@unchecked, SOptionMethods) => method.name match {
+ case SOptionMethods.GetMethod.name =>
opt.get
- case SOption.GetOrElseMethod.name =>
+ case SOptionMethods.GetOrElseMethod.name =>
val defaultTh = asRep[t](argsV(0))
opt.getOrElse(Thunk(defaultTh))
- case SOption.IsDefinedMethod.name =>
+ case SOptionMethods.IsDefinedMethod.name =>
opt.isDefined
- case SOption.MapMethod.name =>
+ case SOptionMethods.MapMethod.name =>
opt.map(asRep[t => Any](argsV(0)))
- case SOption.FilterMethod.name =>
+ case SOptionMethods.FilterMethod.name =>
opt.filter(asRep[t => Boolean](argsV(0)))
case _ => throwError
}
- case (ge: Ref[GroupElement]@unchecked, SGroupElement) => method.name match {
- case SGroupElement.GetEncodedMethod.name =>
+ case (ge: Ref[GroupElement]@unchecked, SGroupElementMethods) => method.name match {
+ case SGroupElementMethods.GetEncodedMethod.name =>
ge.getEncoded
- case SGroupElement.NegateMethod.name =>
+ case SGroupElementMethods.NegateMethod.name =>
ge.negate
- case SGroupElement.MultiplyMethod.name =>
+ case SGroupElementMethods.MultiplyMethod.name =>
val g2 = asRep[GroupElement](argsV(0))
ge.multiply(g2)
- case SGroupElement.ExponentiateMethod.name =>
+ case SGroupElementMethods.ExponentiateMethod.name =>
val k = asRep[BigInt](argsV(0))
ge.exp(k)
case _ => throwError
}
- case (box: Ref[Box]@unchecked, SBox) => method.name match {
- case SBox.tokensMethod.name =>
+ case (box: Ref[Box]@unchecked, SBoxMethods) => method.name match {
+ case SBoxMethods.tokensMethod.name =>
box.tokens
case _ => throwError
}
- case (ctx: Ref[Context]@unchecked, SContext) => method.name match {
- case SContext.dataInputsMethod.name =>
+ case (ctx: Ref[Context]@unchecked, SContextMethods) => method.name match {
+ case SContextMethods.dataInputsMethod.name =>
ctx.dataInputs
- case SContext.headersMethod.name =>
+ case SContextMethods.headersMethod.name =>
ctx.headers
- case SContext.preHeaderMethod.name =>
+ case SContextMethods.preHeaderMethod.name =>
ctx.preHeader
- case SContext.inputsMethod.name =>
+ case SContextMethods.inputsMethod.name =>
ctx.INPUTS
- case SContext.outputsMethod.name =>
+ case SContextMethods.outputsMethod.name =>
ctx.OUTPUTS
- case SContext.heightMethod.name =>
+ case SContextMethods.heightMethod.name =>
ctx.HEIGHT
- case SContext.selfMethod.name =>
+ case SContextMethods.selfMethod.name =>
ctx.SELF
- case SContext.selfBoxIndexMethod.name =>
+ case SContextMethods.selfBoxIndexMethod.name =>
ctx.selfBoxIndex
- case SContext.lastBlockUtxoRootHashMethod.name =>
+ case SContextMethods.lastBlockUtxoRootHashMethod.name =>
ctx.LastBlockUtxoRootHash
- case SContext.minerPubKeyMethod.name =>
+ case SContextMethods.minerPubKeyMethod.name =>
ctx.minerPubKey
case _ => throwError
}
- case (tree: Ref[AvlTree]@unchecked, SAvlTree) => method.name match {
- case SAvlTree.digestMethod.name =>
+ case (tree: Ref[AvlTree]@unchecked, SAvlTreeMethods) => method.name match {
+ case SAvlTreeMethods.digestMethod.name =>
tree.digest
- case SAvlTree.keyLengthMethod.name =>
+ case SAvlTreeMethods.keyLengthMethod.name =>
tree.keyLength
- case SAvlTree.valueLengthOptMethod.name =>
+ case SAvlTreeMethods.valueLengthOptMethod.name =>
tree.valueLengthOpt
- case SAvlTree.enabledOperationsMethod.name =>
+ case SAvlTreeMethods.enabledOperationsMethod.name =>
tree.enabledOperations
- case SAvlTree.isInsertAllowedMethod.name =>
+ case SAvlTreeMethods.isInsertAllowedMethod.name =>
tree.isInsertAllowed
- case SAvlTree.isRemoveAllowedMethod.name =>
+ case SAvlTreeMethods.isRemoveAllowedMethod.name =>
tree.isRemoveAllowed
- case SAvlTree.isUpdateAllowedMethod.name =>
+ case SAvlTreeMethods.isUpdateAllowedMethod.name =>
tree.isUpdateAllowed
- case SAvlTree.updateDigestMethod.name =>
+ case SAvlTreeMethods.updateDigestMethod.name =>
val digest = asRep[Coll[Byte]](argsV(0))
tree.updateDigest(digest)
- case SAvlTree.updateOperationsMethod.name =>
+ case SAvlTreeMethods.updateOperationsMethod.name =>
val operations = asRep[Byte](argsV(0))
tree.updateOperations(operations)
- case SAvlTree.getMethod.name =>
+ case SAvlTreeMethods.getMethod.name =>
val key = asRep[Coll[Byte]](argsV(0))
val proof = asRep[Coll[Byte]](argsV(1))
tree.get(key, proof)
- case SAvlTree.getManyMethod.name =>
+ case SAvlTreeMethods.getManyMethod.name =>
val keys = asRep[Coll[Coll[Byte]]](argsV(0))
val proof = asRep[Coll[Byte]](argsV(1))
tree.getMany(keys, proof)
- case SAvlTree.containsMethod.name =>
+ case SAvlTreeMethods.containsMethod.name =>
val key = asRep[Coll[Byte]](argsV(0))
val proof = asRep[Coll[Byte]](argsV(1))
tree.contains(key, proof)
- case SAvlTree.insertMethod.name =>
+ case SAvlTreeMethods.insertMethod.name =>
val operations = asRep[Coll[(Coll[Byte], Coll[Byte])]](argsV(0))
val proof = asRep[Coll[Byte]](argsV(1))
tree.insert(operations, proof)
- case SAvlTree.removeMethod.name =>
+ case SAvlTreeMethods.removeMethod.name =>
val operations = asRep[Coll[Coll[Byte]]](argsV(0))
val proof = asRep[Coll[Byte]](argsV(1))
tree.remove(operations, proof)
- case SAvlTree.updateMethod.name =>
+ case SAvlTreeMethods.updateMethod.name =>
val operations = asRep[Coll[(Coll[Byte], Coll[Byte])]](argsV(0))
val proof = asRep[Coll[Byte]](argsV(1))
tree.update(operations, proof)
case _ => throwError
}
- case (ph: Ref[PreHeader]@unchecked, SPreHeader) => method.name match {
- case SPreHeader.versionMethod.name =>
+ case (ph: Ref[PreHeader]@unchecked, SPreHeaderMethods) => method.name match {
+ case SPreHeaderMethods.versionMethod.name =>
ph.version
- case SPreHeader.parentIdMethod.name =>
+ case SPreHeaderMethods.parentIdMethod.name =>
ph.parentId
- case SPreHeader.timestampMethod.name =>
+ case SPreHeaderMethods.timestampMethod.name =>
ph.timestamp
- case SPreHeader.nBitsMethod.name =>
+ case SPreHeaderMethods.nBitsMethod.name =>
ph.nBits
- case SPreHeader.heightMethod.name =>
+ case SPreHeaderMethods.heightMethod.name =>
ph.height
- case SPreHeader.minerPkMethod.name =>
+ case SPreHeaderMethods.minerPkMethod.name =>
ph.minerPk
- case SPreHeader.votesMethod.name =>
+ case SPreHeaderMethods.votesMethod.name =>
ph.votes
case _ => throwError
}
- case (h: Ref[Header]@unchecked, SHeader) => method.name match {
- case SHeader.idMethod.name =>
+ case (h: Ref[Header]@unchecked, SHeaderMethods) => method.name match {
+ case SHeaderMethods.idMethod.name =>
h.id
- case SHeader.versionMethod.name =>
+ case SHeaderMethods.versionMethod.name =>
h.version
- case SHeader.parentIdMethod.name =>
+ case SHeaderMethods.parentIdMethod.name =>
h.parentId
- case SHeader.ADProofsRootMethod.name =>
+ case SHeaderMethods.ADProofsRootMethod.name =>
h.ADProofsRoot
- case SHeader.stateRootMethod.name =>
+ case SHeaderMethods.stateRootMethod.name =>
h.stateRoot
- case SHeader.transactionsRootMethod.name =>
+ case SHeaderMethods.transactionsRootMethod.name =>
h.transactionsRoot
- case SHeader.timestampMethod.name =>
+ case SHeaderMethods.timestampMethod.name =>
h.timestamp
- case SHeader.nBitsMethod.name =>
+ case SHeaderMethods.nBitsMethod.name =>
h.nBits
- case SHeader.heightMethod.name =>
+ case SHeaderMethods.heightMethod.name =>
h.height
- case SHeader.extensionRootMethod.name =>
+ case SHeaderMethods.extensionRootMethod.name =>
h.extensionRoot
- case SHeader.minerPkMethod.name =>
+ case SHeaderMethods.minerPkMethod.name =>
h.minerPk
- case SHeader.powOnetimePkMethod.name =>
+ case SHeaderMethods.powOnetimePkMethod.name =>
h.powOnetimePk
- case SHeader.powNonceMethod.name =>
+ case SHeaderMethods.powNonceMethod.name =>
h.powNonce
- case SHeader.powDistanceMethod.name =>
+ case SHeaderMethods.powDistanceMethod.name =>
h.powDistance
- case SHeader.votesMethod.name =>
+ case SHeaderMethods.votesMethod.name =>
h.votes
case _ => throwError
}
- case (g: Ref[SigmaDslBuilder]@unchecked, SGlobal) => method.name match {
- case SGlobal.groupGeneratorMethod.name =>
+ case (g: Ref[SigmaDslBuilder]@unchecked, SGlobalMethods) => method.name match {
+ case SGlobalMethods.groupGeneratorMethod.name =>
g.groupGenerator
- case SGlobal.xorMethod.name =>
+ case SGlobalMethods.xorMethod.name =>
val c1 = asRep[Coll[Byte]](argsV(0))
val c2 = asRep[Coll[Byte]](argsV(1))
g.xor(c1, c2)
diff --git a/sc/shared/src/main/scala/sigmastate/eval/IRContext.scala b/sc/shared/src/main/scala/sigmastate/eval/IRContext.scala
index a3338eaae6..b84098f2e7 100644
--- a/sc/shared/src/main/scala/sigmastate/eval/IRContext.scala
+++ b/sc/shared/src/main/scala/sigmastate/eval/IRContext.scala
@@ -1,6 +1,7 @@
package sigmastate.eval
-import sigmastate.lang.TransformingSigmaBuilder
+import sigma.ast.TransformingSigmaBuilder
+import sigma.data.CSigmaDslBuilder
import java.util.concurrent.locks.ReentrantLock
import scala.util.Try
@@ -28,7 +29,7 @@ trait IRContext extends TreeBuilding with GraphBuilding {
Pass.defaultPassConfig.copy(constantPropagation = false))
/** The value of Global ErgoTree operation */
- val sigmaDslBuilderValue = CostingSigmaDslBuilder
+ val sigmaDslBuilderValue = CSigmaDslBuilder
/** Finds SigmaProp.isProven method calls in the given Lambda `f` */
def findIsProven[T](f: Ref[Context => T]): Option[Sym] = {
diff --git a/sc/shared/src/main/scala/sigmastate/eval/TreeBuilding.scala b/sc/shared/src/main/scala/sigmastate/eval/TreeBuilding.scala
index 13fc8c7bd1..26bc33956f 100644
--- a/sc/shared/src/main/scala/sigmastate/eval/TreeBuilding.scala
+++ b/sc/shared/src/main/scala/sigmastate/eval/TreeBuilding.scala
@@ -1,18 +1,16 @@
package sigmastate.eval
-import sigmastate.Values._
+import sigma.ast._
import org.ergoplatform._
-import sigmastate._
-import sigmastate.lang.Terms.ValueOps
-import sigmastate.serialization.OpCodes._
-import sigmastate.serialization.ConstantStore
+import sigma.ast.syntax.ValueOps
+import sigma.serialization.OpCodes._
+import sigma.serialization.ConstantStore
+import sigma.ast.syntax._
+import sigma.data.{ProveDHTuple, ProveDlog}
import scala.collection.mutable.ArrayBuffer
-import SType._
-import sigmastate.crypto.DLogProtocol.ProveDlog
-import sigmastate.crypto.ProveDHTuple
-import sigmastate.lang.Terms
+import sigma.serialization.ValueCodes.OpCode
/** Implementation of IR-graph to ErgoTree expression translation.
* This, in a sense, is inverse to [[GraphBuilding]], however roundtrip identity is not
@@ -159,7 +157,7 @@ trait TreeBuilding extends SigmaLibrary { IR: IRContext =>
def recurse[T <: SType](s: Sym) = buildValue(ctx, mainG, env, s, defId, constantsProcessing).asValue[T]
object In { def unapply(s: Sym): Option[SValue] = Some(buildValue(ctx, mainG, env, s, defId, constantsProcessing)) }
s match {
- case _ if s == ctx => org.ergoplatform.Context
+ case _ if s == ctx => sigma.ast.Context
case _ if env.contains(s) =>
val (id, tpe) = env(s)
ValUse(id, tpe) // recursion base
@@ -242,7 +240,7 @@ trait TreeBuilding extends SigmaLibrary { IR: IRContext =>
val col = recurse(colSym)
mkByIndex(col, index.asIntValue, None)
case CollM.length(col) =>
- utxo.SizeOf(recurse(col).asCollection[SType])
+ sigma.ast.SizeOf(recurse(col).asCollection[SType])
case CollM.exists(colSym, pSym) =>
val Seq(col, p) = Seq(colSym, pSym).map(recurse)
mkExists(col.asCollection[SType], p.asFunc)
@@ -273,15 +271,15 @@ trait TreeBuilding extends SigmaLibrary { IR: IRContext =>
val args = argsSyms.map(_.asInstanceOf[Sym]).map(recurse)
val col = recurse(colSym).asCollection[SType]
val colTpe = col.tpe
- val method = SCollection.methods.find(_.name == m.getName).getOrElse(error(s"unknown method Coll.${m.getName}"))
+ val method = SCollectionMethods.methods.find(_.name == m.getName).getOrElse(error(s"unknown method Coll.${m.getName}"))
val typeSubst = (method, args) match {
- case (mth @ SCollection.FlatMapMethod, Seq(f)) =>
+ case (_ @ SCollectionMethods.FlatMapMethod, Seq(f)) =>
val typeSubst = Map(SCollection.tOV -> f.asFunc.tpe.tRange.asCollection.elemType)
typeSubst
- case (mth @ SCollection.ZipMethod, Seq(coll)) =>
+ case (_ @ SCollectionMethods.ZipMethod, Seq(coll)) =>
val typeSubst = Map(SCollection.tOV -> coll.asCollection[SType].tpe.elemType)
typeSubst
- case (mth, _) => Terms.EmptySubst
+ case (_, _) => EmptySubst
}
val specMethod = method.withConcreteTypes(typeSubst + (SCollection.tIV -> colTpe.elemType))
builder.mkMethodCall(col, specMethod, args.toIndexedSeq, Map())
@@ -402,10 +400,13 @@ trait TreeBuilding extends SigmaLibrary { IR: IRContext =>
case Def(MethodCall(objSym, m, argSyms, _)) =>
val obj = recurse[SType](objSym)
val args = argSyms.collect { case argSym: Sym => recurse[SType](argSym) }
- val method = obj.tpe.asProduct.method(m.getName)
- .getOrElse(error(s"Cannot find method ${m.getName} in object $obj"))
- val specMethod = method.specializeFor(obj.tpe, args.map(_.tpe))
- builder.mkMethodCall(obj, specMethod, args.toIndexedSeq, Map())
+ MethodsContainer.getMethod(obj.tpe, m.getName) match {
+ case Some(method) =>
+ val specMethod = method.specializeFor(obj.tpe, args.map(_.tpe))
+ builder.mkMethodCall(obj, specMethod, args.toIndexedSeq, Map())
+ case None =>
+ error(s"Cannot find method ${m.getName} in object $obj")
+ }
case Def(d) =>
!!!(s"Don't know how to buildValue($mainG, $s -> $d, $env, $defId)")
diff --git a/sc/shared/src/main/scala/sigmastate/lang/SigmaBinder.scala b/sc/shared/src/main/scala/sigmastate/lang/SigmaBinder.scala
index 3295429ffe..f93e31703d 100644
--- a/sc/shared/src/main/scala/sigmastate/lang/SigmaBinder.scala
+++ b/sc/shared/src/main/scala/sigmastate/lang/SigmaBinder.scala
@@ -2,14 +2,15 @@ package sigmastate.lang
import org.ergoplatform.ErgoAddressEncoder.NetworkPrefix
import org.ergoplatform._
+import sigma.ast.NoType
import sigma.data.Nullable
import sigma.kiama.rewriting.CallbackRewriter
-import sigmastate.Values._
-import sigmastate._
+import sigma.ast._
+import sigma.ast.syntax.SValue
import sigmastate.interpreter.Interpreter.ScriptEnv
-import sigmastate.lang.SigmaPredef.PredefinedFuncRegistry
-import sigmastate.lang.Terms._
-import sigmastate.exceptions.{BinderException, InvalidArguments}
+import SigmaPredef.PredefinedFuncRegistry
+import sigma.ast.syntax._
+import sigma.exceptions.{BinderException, InvalidArguments}
object SrcCtxCallbackRewriter extends CallbackRewriter {
override def rewriting[T](oldTerm: T, newTerm: T): T = (oldTerm, newTerm) match {
diff --git a/sc/shared/src/main/scala/sigmastate/lang/SigmaCompiler.scala b/sc/shared/src/main/scala/sigmastate/lang/SigmaCompiler.scala
index d37a037a58..849167e159 100644
--- a/sc/shared/src/main/scala/sigmastate/lang/SigmaCompiler.scala
+++ b/sc/shared/src/main/scala/sigmastate/lang/SigmaCompiler.scala
@@ -4,21 +4,23 @@ import fastparse.Parsed
import fastparse.Parsed.Success
import sigma.kiama.rewriting.Rewriter.{everywherebu, rewrite, rule}
import org.ergoplatform.ErgoAddressEncoder.NetworkPrefix
-import org.ergoplatform.Global
-import sigmastate.Values.{SValue, Value}
+import scalan.GraphIRReflection
+import sigma.ast.{Exponentiate, MultiplyGroup, SCollectionMethods, SGlobalMethods, SGroupElementMethods, Value, Xor}
import sigmastate.eval.IRContext
import sigmastate.interpreter.Interpreter.ScriptEnv
-import sigmastate.lang.SigmaPredef.PredefinedFuncRegistry
-import sigmastate.lang.Terms.MethodCall
-import sigmastate.lang.syntax.ParserException
-import sigmastate.utxo._
-import sigmastate.{Exponentiate, MultiplyGroup, SCollection, SGlobal, SGroupElement, SType, STypeVar, Xor}
+import sigma.ast.SigmaPredef.PredefinedFuncRegistry
+import sigma.ast.MethodCall
+import sigmastate.lang.parsers.ParserException
+import sigma.ast._
+import sigma.ast.syntax.SValue
+import SCollectionMethods.{ExistsMethod, ForallMethod, MapMethod}
+import sigmastate.InterpreterReflection
/**
* @param networkPrefix network prefix to decode an ergo address from string (PK op)
* @param builder used to create ErgoTree nodes
* @param lowerMethodCalls if true, then MethodCall nodes are lowered to ErgoTree nodes
- * when [[sigmastate.SMethod.irInfo.irBuilder]] is defined. For
+ * when [[sigma.ast.SMethod.irInfo.irBuilder]] is defined. For
* example, in the `coll.map(x => x+1)` code, the `map` method
* call can be lowered to MapCollection node.
* The lowering if preferable, because it is more compact (1 byte
@@ -33,9 +35,7 @@ case class CompilerSettings(
/** Result of ErgoScript source code compilation.
* @param env compiler environment used to compile the code
* @param code ErgoScript source code
- * @param calcF graph obtained by using old AOT costing based compiler
* @param compiledGraph graph obtained by using new [[GraphBuilding]]
- * @param calcTree ErgoTree expression obtained from calcF graph.
* @param buildTree ErgoTree expression obtained from graph created by [[GraphBuilding]]
*/
case class CompilerResult[Ctx <: IRContext](
@@ -49,7 +49,7 @@ case class CompilerResult[Ctx <: IRContext](
/** Compiler which compiles ErgoScript source code into ErgoTree.
* @param settings compilation parameters \
*/
-class SigmaCompiler(settings: CompilerSettings) {
+class SigmaCompiler private(settings: CompilerSettings) {
/** Constructs an instance for the given network type and with default settings. */
def this(networkPrefix: Byte) = this(
CompilerSettings(networkPrefix, TransformingSigmaBuilder, lowerMethodCalls = true)
@@ -96,6 +96,12 @@ class SigmaCompiler(settings: CompilerSettings) {
CompilerResult(env, "", compiledGraph, compiledTree)
}
+ /** Compiles the given parsed contract source. */
+ def compileParsed(env: ScriptEnv, parsedExpr: SValue)(implicit IR: IRContext): CompilerResult[IR.type] = {
+ val typed = typecheck(env, parsedExpr)
+ compileTyped(env, typed)
+ }
+
/** Unlowering transformation, which replaces some operations with equivalent MethodCall
* node. This replacement is only defined for some operations.
* This is inverse to `lowering` which is performed during compilation.
@@ -104,9 +110,9 @@ class SigmaCompiler(settings: CompilerSettings) {
import SCollection._
val r = rule[Any]({
case MultiplyGroup(l, r) =>
- MethodCall(l, SGroupElement.MultiplyMethod, Vector(r), Map())
+ MethodCall(l, SGroupElementMethods.MultiplyMethod, Vector(r), Map())
case Exponentiate(l, r) =>
- MethodCall(l, SGroupElement.ExponentiateMethod, Vector(r), Map())
+ MethodCall(l, SGroupElementMethods.ExponentiateMethod, Vector(r), Map())
case ForAll(xs, p) =>
MethodCall(xs, ForallMethod.withConcreteTypes(Map(tIV -> xs.tpe.elemType)), Vector(p), Map())
case Exists(xs, p) =>
@@ -117,21 +123,21 @@ class SigmaCompiler(settings: CompilerSettings) {
Vector(f), Map())
case Fold(xs, z, op) =>
MethodCall(xs,
- SCollection.FoldMethod.withConcreteTypes(Map(tIV -> xs.tpe.elemType, tOV -> z.tpe)),
+ SCollectionMethods.FoldMethod.withConcreteTypes(Map(tIV -> xs.tpe.elemType, tOV -> z.tpe)),
Vector(z, op), Map())
case Slice(xs, from, until) =>
MethodCall(xs,
- SCollection.SliceMethod.withConcreteTypes(Map(tIV -> xs.tpe.elemType)),
+ SCollectionMethods.SliceMethod.withConcreteTypes(Map(tIV -> xs.tpe.elemType)),
Vector(from, until), Map())
case Append(xs, ys) =>
MethodCall(xs,
- SCollection.AppendMethod.withConcreteTypes(Map(tIV -> xs.tpe.elemType)),
+ SCollectionMethods.AppendMethod.withConcreteTypes(Map(tIV -> xs.tpe.elemType)),
Vector(ys), Map())
case Xor(l, r) =>
- MethodCall(Global, SGlobal.xorMethod, Vector(l, r), Map())
+ MethodCall(Global, SGlobalMethods.xorMethod, Vector(l, r), Map())
case ByIndex(xs, index, Some(default)) =>
MethodCall(xs,
- SCollection.GetOrElseMethod.withConcreteTypes(Map(tIV -> xs.tpe.elemType)),
+ SCollectionMethods.GetOrElseMethod.withConcreteTypes(Map(tIV -> xs.tpe.elemType)),
Vector(index, default), Map())
})
rewrite(everywherebu(r))(expr)
@@ -139,6 +145,14 @@ class SigmaCompiler(settings: CompilerSettings) {
}
object SigmaCompiler {
+ /** Force initialization of reflection before any instance of SigmaCompiler is used. */
+ val _ = (InterpreterReflection, GraphIRReflection)
+
+ /** Constructs an instance for the given settings. */
def apply(settings: CompilerSettings): SigmaCompiler =
new SigmaCompiler(settings)
+
+ /** Constructs an instance for the given network type. */
+ def apply(networkPrefix: Byte): SigmaCompiler =
+ new SigmaCompiler(networkPrefix)
}
diff --git a/sc/shared/src/main/scala/sigmastate/lang/SigmaTemplateCompiler.scala b/sc/shared/src/main/scala/sigmastate/lang/SigmaTemplateCompiler.scala
new file mode 100644
index 0000000000..ec94bdfd3a
--- /dev/null
+++ b/sc/shared/src/main/scala/sigmastate/lang/SigmaTemplateCompiler.scala
@@ -0,0 +1,58 @@
+package sigmastate.lang
+
+import fastparse.Parsed
+import org.ergoplatform.sdk.ContractTemplate
+import sigmastate.eval.CompiletimeIRContext
+import org.ergoplatform.sdk.Parameter
+import sigma.ast.SourceContext
+import sigma.ast.syntax.SValue
+import sigmastate.interpreter.Interpreter.ScriptEnv
+import sigmastate.lang.parsers.ParserException
+
+/** Compiler which compiles Ergo contract templates into a [[ContractTemplate]]. */
+class SigmaTemplateCompiler(networkPrefix: Byte) {
+ val sigmaCompiler = new SigmaCompiler(networkPrefix)
+
+ /**
+ * Compiles the provided contract source code into a [[ContractTemplate]].
+ *
+ * @param source The ErgoScript contract source code.
+ * @return The contract template.
+ */
+ def compile(env: ScriptEnv, source: String): ContractTemplate = {
+ ContractParser.parse(source) match {
+ case Parsed.Success(template, _) => {
+ implicit val ir = new CompiletimeIRContext
+ val result = sigmaCompiler.compileParsed(env, template.body)
+ assemble(template, result.buildTree)
+ }
+ case f: Parsed.Failure =>
+ throw new ParserException(s"Contract template syntax error: $f", Some(SourceContext.fromParserFailure(f)))
+ }
+ }
+
+ private def assemble(parsed: ParsedContractTemplate, expr: SValue): ContractTemplate = {
+ val (constTypes, constValueOpts) = parsed.signature.params.map(param => (param.tpe, param.defaultValue)).unzip
+ val allConstValuesAreNone = constValueOpts.forall(_.isEmpty)
+ val constValues =
+ if (allConstValuesAreNone) None
+ else Some(constValueOpts.toIndexedSeq)
+ val contractParams = parsed.signature.params.zipWithIndex.map { case (param, idx) =>
+ val desc: String = parsed.docs.params.find(docParam => docParam.name == param.name).map(_.description).getOrElse("")
+ Parameter(param.name, desc, idx)
+ }
+
+ ContractTemplate(
+ name = parsed.signature.name,
+ description = parsed.docs.description,
+ constTypes = constTypes.toIndexedSeq,
+ constValues = constValues,
+ parameters = contractParams.toIndexedSeq,
+ expressionTree = expr.toSigmaProp
+ )
+ }
+}
+
+object SigmaTemplateCompiler {
+ def apply(networkPrefix: Byte): SigmaTemplateCompiler = new SigmaTemplateCompiler(networkPrefix)
+}
diff --git a/sc/shared/src/main/scala/sigmastate/lang/SigmaTyper.scala b/sc/shared/src/main/scala/sigmastate/lang/SigmaTyper.scala
index beb17a98b0..7fd6dadd45 100644
--- a/sc/shared/src/main/scala/sigmastate/lang/SigmaTyper.scala
+++ b/sc/shared/src/main/scala/sigmastate/lang/SigmaTyper.scala
@@ -1,17 +1,16 @@
package sigmastate.lang
import org.ergoplatform._
-import sigmastate.SCollection._
-import sigmastate.Values._
-import sigmastate._
-import SCollection.SBooleanArray
-import sigma.data.Nullable
+import sigma.ast.SCollection.{SBooleanArray, SByteArray}
+import sigma.ast._
+import sigma.ast.syntax.SValue
+import sigma.data.{Nullable, SigmaBoolean}
import sigma.util.Extensions.Ensuring
-import sigmastate.lang.Terms._
import sigmastate.exceptions._
-import sigmastate.lang.SigmaPredef._
-import sigmastate.serialization.OpCodes
-import sigmastate.utxo._
+import SigmaPredef._
+import sigma.ast.syntax._
+import sigma.exceptions.TyperException
+import sigma.serialization.OpCodes
import scala.collection.mutable.ArrayBuffer
@@ -46,9 +45,7 @@ class SigmaTyper(val builder: SigmaBuilder,
* Rewrite tree to typed tree. Checks constituent names and types. Uses
* the env map to resolve bound variables and their types.
*/
- def assignType(env: Map[String, SType],
- bound: SValue,
- expected: Option[SType] = None): SValue = ( bound match {
+ def assignType(env: Map[String, SType], bound: SValue): SValue = ( bound match {
case Block(bs, res) =>
var curEnv = env
val bs1 = ArrayBuffer[Val]()
@@ -74,7 +71,7 @@ class SigmaTyper(val builder: SigmaBuilder,
env.get(n) match {
case Some(t) => mkIdent(n, t)
case None =>
- SGlobal.method(n) match {
+ SGlobalMethods.method(n) match {
case Some(method) if method.stype.tDom.length == 1 => // this is like `groupGenerator` without parentheses
val srcCtx = i.sourceContext
processGlobalMethod(srcCtx, method, IndexedSeq())
@@ -87,11 +84,10 @@ class SigmaTyper(val builder: SigmaBuilder,
val newObj = assignType(env, obj)
newObj.tpe match {
case tNewObj: SProduct =>
- val iField = tNewObj.methodIndex(n)
- val method = if (iField != -1) {
- tNewObj.methods(iField)
- } else
- throw new MethodNotFound(s"Cannot find method '$n' in in the object $obj of Product type with methods ${tNewObj.methods}", obj.sourceContext.toOption)
+ val method = MethodsContainer.getMethod(tNewObj, n).getOrElse(
+ throw new MethodNotFound(
+ s"Cannot find method '$n' in in the object $obj of Product type with methods",
+ obj.sourceContext.toOption))
val tMeth = method.stype
val tRes = tMeth match {
case SFunc(args, _, _) =>
@@ -138,7 +134,7 @@ class SigmaTyper(val builder: SigmaBuilder,
val newArgs = args.map(assignType(env, _))
obj.tpe match {
case p: SProduct =>
- p.method(n) match {
+ MethodsContainer.getMethod(p, n) match {
case Some(method @ SMethod(_, _, genFunTpe @ SFunc(_, _, _), _, _, _, _, _)) =>
val subst = Map(genFunTpe.tpeParams.head.ident -> rangeTpe)
val concrFunTpe = applySubst(genFunTpe, subst)
@@ -159,7 +155,7 @@ class SigmaTyper(val builder: SigmaBuilder,
case Some(method) =>
error(s"Don't know how to handle method $method in obj $p", sel.sourceContext)
case None =>
- throw new MethodNotFound(s"Cannot find method '$n' in in the object $obj of Product type with methods ${p.methods}", obj.sourceContext.toOption)
+ throw new MethodNotFound(s"Cannot find method '$n' in in the object $obj of Product type $p", obj.sourceContext.toOption)
}
case _ =>
error(s"Cannot get field '$n' in in the object $obj of non-product type ${obj.tpe}", sel.sourceContext)
@@ -176,7 +172,7 @@ class SigmaTyper(val builder: SigmaBuilder,
unifyTypeLists(argTypes, newArgTypes) match {
case Some(subst) =>
val concrFunTpe = applySubst(genFunTpe, subst)
- newObj.tpe.asInstanceOf[SProduct].method(n) match {
+ MethodsContainer.getMethod(newObj.tpe.asInstanceOf[SProduct], n) match {
case Some(method) if method.irInfo.irBuilder.isDefined =>
val expectedArgs = concrFunTpe.asFunc.tDom
if (expectedArgs.length != newArgTypes.length
@@ -198,8 +194,8 @@ class SigmaTyper(val builder: SigmaBuilder,
mkApply(newSel, newArgs.toArray[SValue])
}
- case a @ Apply(ident: Ident, args) if SGlobal.hasMethod(ident.name) => // example: groupGenerator()
- val method = SGlobal.method(ident.name).get
+ case a @ Apply(ident: Ident, args) if SGlobalMethods.hasMethod(ident.name) => // example: groupGenerator()
+ val method = SGlobalMethods.method(ident.name).get
val srcCtx = a.sourceContext
val newArgs = args.map(assignType(env, _))
processGlobalMethod(srcCtx, method, newArgs)
@@ -212,7 +208,7 @@ class SigmaTyper(val builder: SigmaBuilder,
if (args.length != argTypes.length)
error(s"Invalid argument type of application $app: invalid number of arguments", app.sourceContext)
val typedArgs = args.zip(argTypes).map {
- case (arg, expectedType) => assignType(env, arg, Some(expectedType))
+ case (arg, expectedType) => assignType(env, arg)
}
val adaptedTypedArgs = (new_f, typedArgs) match {
case (AllOfFunc.sym | AnyOfFunc.sym, _) =>
@@ -280,7 +276,7 @@ class SigmaTyper(val builder: SigmaBuilder,
mkAppend(newObj.asCollection[a], r.asCollection[a])
else
error(s"Invalid argument type for $m, expected $tColl but was ${r.tpe}", r.sourceContext)
- case (SCollection(method), _) =>
+ case (SCollectionMethods(method), _) =>
val typeSubst = method.stype match {
case sfunc @ SFunc(_, _, _) =>
val newArgsTypes = newArgs.map(_.tpe)
@@ -335,7 +331,7 @@ class SigmaTyper(val builder: SigmaBuilder,
case SSigmaProp => (m, newArgs) match {
case ("||" | "&&" | "^", Seq(r)) => r.tpe match {
case SBoolean =>
- val (a, b) = (Select(newObj, SSigmaProp.IsProven, Some(SBoolean)).asBoolValue, r.asBoolValue)
+ val (a, b) = (Select(newObj, SSigmaPropMethods.IsProven, Some(SBoolean)).asBoolValue, r.asBoolValue)
val res = m match {
case "||" => mkBinOr(a, b)
case "&&" => mkBinAnd(a, b)
@@ -364,7 +360,7 @@ class SigmaTyper(val builder: SigmaBuilder,
case "^" => mkBinXor(newObj.asBoolValue, r.asBoolValue)
}
case SSigmaProp =>
- val (a, b) = (newObj.asBoolValue, Select(r, SSigmaProp.IsProven, Some(SBoolean)).asBoolValue)
+ val (a, b) = (newObj.asBoolValue, Select(r, SSigmaPropMethods.IsProven, Some(SBoolean)).asBoolValue)
val res = m match {
case "||" => mkBinOr(a, b)
case "&&" => mkBinAnd(a, b)
@@ -505,7 +501,6 @@ class SigmaTyper(val builder: SigmaBuilder,
case Inputs => Inputs
case Outputs => Outputs
case LastBlockUtxoRootHash => LastBlockUtxoRootHash
- case v: ContextVariable[_] => v
case v: GetVar[_] => v
case v: OptionGet[_] => v
case v: EvaluatedValue[_] => v
diff --git a/sc/shared/src/main/scala/special/collection/CollsUnit.scala b/sc/shared/src/main/scala/special/collection/CollsUnit.scala
index 02e62aeb4d..19ae1f5e48 100644
--- a/sc/shared/src/main/scala/special/collection/CollsUnit.scala
+++ b/sc/shared/src/main/scala/special/collection/CollsUnit.scala
@@ -9,9 +9,6 @@ package sigma {
* for details.
*/
trait Colls extends Base { self: Library =>
- import Coll._;
- import CollBuilder._;
- import WOption._;
trait Coll[A] extends Def[Coll[A]] {
implicit def eA: Elem[A];
def length: Ref[Int];
diff --git a/sc/shared/src/main/scala/special/sigma/impl/SigmaDslImpl.scala b/sc/shared/src/main/scala/special/sigma/impl/SigmaDslImpl.scala
index 8da36ce6cf..037505b531 100644
--- a/sc/shared/src/main/scala/special/sigma/impl/SigmaDslImpl.scala
+++ b/sc/shared/src/main/scala/special/sigma/impl/SigmaDslImpl.scala
@@ -22,19 +22,16 @@ import BigInt._
import Box._
import Coll._
import CollBuilder._
-import Context._
import GroupElement._
import Header._
import PreHeader._
-import SigmaDslBuilder._
import SigmaProp._
import WOption._
-import WRType._
+
object BigInt extends EntityObject("BigInt") {
// entityConst: single const for each entity
import Liftables._
- import scala.reflect.{ClassTag, classTag}
type SBigInt = sigma.BigInt
case class BigIntConst(
constValue: SBigInt
diff --git a/sc/shared/src/main/scala/wrappers/scalan/WRTypes.scala b/sc/shared/src/main/scala/wrappers/scalan/WRTypes.scala
index 0d55f5dd9e..8c6bc48f8e 100644
--- a/sc/shared/src/main/scala/wrappers/scalan/WRTypes.scala
+++ b/sc/shared/src/main/scala/wrappers/scalan/WRTypes.scala
@@ -1,18 +1,9 @@
package wrappers.scalan {
import scalan._
-
- import impl._
-
- import sigma.data.RType
-
import special.wrappers.WrappersModule
- import special.wrappers.RTypeWrapSpec
-
- import scala.collection.mutable.WrappedArray
trait WRTypes extends Base { self: WrappersModule =>
- import WRType._;
trait WRType[A] extends Def[WRType[A]] {
implicit def eA: Elem[A];
def name: Ref[String]
diff --git a/sc/shared/src/main/scala/wrappers/special/WSpecialPredefs.scala b/sc/shared/src/main/scala/wrappers/special/WSpecialPredefs.scala
index 42bbbb4373..5abbab95e2 100644
--- a/sc/shared/src/main/scala/wrappers/special/WSpecialPredefs.scala
+++ b/sc/shared/src/main/scala/wrappers/special/WSpecialPredefs.scala
@@ -4,8 +4,6 @@ package wrappers.special {
import special.wrappers.WrappersModule
trait WSpecialPredefs extends Base { self: WrappersModule =>
- import WOption._;
- import WSpecialPredef._;
trait WSpecialPredef extends Def[WSpecialPredef];
trait WSpecialPredefCompanion {
def some[A](x: Ref[A]): Ref[WOption[A]];
diff --git a/sc/shared/src/test/scala/org/ergoplatform/ErgoAddressSpecification.scala b/sc/shared/src/test/scala/org/ergoplatform/ErgoAddressSpecification.scala
index 73156ca1b8..d8ee6e3707 100644
--- a/sc/shared/src/test/scala/org/ergoplatform/ErgoAddressSpecification.scala
+++ b/sc/shared/src/test/scala/org/ergoplatform/ErgoAddressSpecification.scala
@@ -1,32 +1,36 @@
package org.ergoplatform
import org.ergoplatform.ErgoAddressEncoder.{MainnetNetworkPrefix, TestnetNetworkPrefix, hash256}
-import org.ergoplatform.validation.{ValidationException, ValidationRules}
+import org.scalatest.propspec.AnyPropSpecLike
import org.scalatest.{Assertion, TryValues}
import scorex.crypto.hash.Blake2b256
import scorex.util.encode.Base58
-import sigmastate.Values.{ByteArrayConstant, Constant, ErgoTree, IntConstant, UnparsedErgoTree}
-import sigmastate.crypto.DLogProtocol
-import sigmastate.crypto.DLogProtocol.{DLogProverInput, ProveDlog}
-import sigmastate.eval.InvalidType
+import sigma.ast.{ByteArrayConstant, Constant, ErgoTree, IntConstant, SigmaAnd, UnparsedErgoTree}
+import sigmastate.crypto.DLogProtocol.DLogProverInput
import sigmastate.helpers.TestingHelpers._
import sigmastate.helpers._
-import sigmastate.interpreter.ContextExtension.VarBinding
-import sigmastate.crypto.CryptoConstants.dlogGroup
-import sigmastate.exceptions.CostLimitException
+import sigma.interpreter.ContextExtension.VarBinding
+import sigma.crypto.CryptoConstants.dlogGroup
import sigmastate.interpreter.Interpreter.{ScriptEnv, ScriptNameProp}
-import sigmastate.interpreter.{ContextExtension, CostedProverResult}
-import sigmastate.lang.Terms.ValueOps
-import sigmastate.serialization.ErgoTreeSerializer.DefaultSerializer
-import sigmastate.serialization.{GroupElementSerializer, ValueSerializer}
+import sigma.ast.syntax.ValueOps
+import sigma.serialization.ErgoTreeSerializer.DefaultSerializer
+import sigma.serialization.ValueSerializer
import sigmastate.utils.Helpers._
-import sigmastate.{CompilerCrossVersionProps, SType, SigmaAnd}
-import sigma.SigmaDslTesting
+import sigmastate.CompilerCrossVersionProps
+import sigma.{SigmaDslTesting, VersionContext}
+import sigma.ast.ErgoTree.{ZeroHeader, setConstantSegregation}
+import sigma.ast.SType
+import sigma.data.ProveDlog
+import sigma.exceptions.{CostLimitException, InvalidType}
+import sigma.interpreter.{ContextExtension, CostedProverResult}
+import sigma.serialization.GroupElementSerializer
+import sigma.validation.ValidationException
+import sigma.validation.ValidationRules.CheckTypeCode
import java.math.BigInteger
class ErgoAddressSpecification extends SigmaDslTesting
- with TryValues with CompilerCrossVersionProps {
+ with TryValues with CompilerCrossVersionProps with AnyPropSpecLike {
private implicit val ergoAddressEncoder: ErgoAddressEncoder =
new ErgoAddressEncoder(TestnetNetworkPrefix)
@@ -76,12 +80,12 @@ class ErgoAddressSpecification extends SigmaDslTesting
def testFromProposition(scriptVersion: Byte,
expectedP2S: String, expectedP2SH: String, expectedP2PK: String) = {
- val pk: DLogProtocol.ProveDlog = DLogProverInput(BigInteger.ONE).publicImage
- val pk10: DLogProtocol.ProveDlog = DLogProverInput(BigInteger.TEN).publicImage
+ val pk: ProveDlog = DLogProverInput(BigInteger.ONE).publicImage
+ val pk10: ProveDlog = DLogProverInput(BigInteger.TEN).publicImage
val p2s: Pay2SAddress = Pay2SAddress(
ErgoTree.fromProposition(
- ErgoTree.headerWithVersion(scriptVersion),
+ ErgoTree.headerWithVersion(ZeroHeader, scriptVersion),
SigmaAnd(pk, pk10)))
val p2sh: Pay2SHAddress = Pay2SHAddress(pk)
val p2pk: P2PKAddress = P2PKAddress(pk)
@@ -125,7 +129,7 @@ class ErgoAddressSpecification extends SigmaDslTesting
val pk = dlogGroup.exponentiate(g, w)
val pkBytes = GroupElementSerializer.toBytes(pk)
val encoder = new ErgoAddressEncoder(MainnetNetworkPrefix)
- val p2pk = new P2PKAddress(ProveDlog(pk), pkBytes)(encoder)
+ val p2pk = P2PKAddress(ProveDlog(pk))(encoder)
val addrStr = p2pk.toString
val prefix = (encoder.networkPrefix + P2PKAddress.addressTypePrefix).toByte
@@ -148,6 +152,11 @@ class ErgoAddressSpecification extends SigmaDslTesting
expectedP2S = "2MzJLjzX6UNfJHSVvioB6seYZ99FpWHB4Ds1gekHPv5KtNmLJUecgRWwvcGEqbt8ZAokUxGvKMuNgMZFzkPPdTGiYzPQoSR55NT5isCidMywgp52LYV",
expectedP2SH = "qETVgcEctaXurNbFRgGUcZEGg4EKa8R4a5UNHY7",
expectedP2PK = "3WwXpssaZwcNzaGMv3AgxBdTPJQBt5gCmqBsg3DykQ39bYdhJBsN")
+
+ testFromProposition(scriptVersion = 2,
+ expectedP2S = "2N1Egpu5R9XtomV7x343LTXGrBLEkC8pvMVtjm6V3iHryxVfc6LUJhd1JsswhXMpPXUMatoBgnJ4qMGAC7dha27WkjqVBUsebWBDhig97zhmKS8T4YS",
+ expectedP2SH = "qETVgcEctaXurNbFRgGUcZEGg4EKa8R4a5UNHY7",
+ expectedP2PK = "3WwXpssaZwcNzaGMv3AgxBdTPJQBt5gCmqBsg3DykQ39bYdhJBsN")
}
property("decode with wrong address") {
@@ -175,7 +184,7 @@ class ErgoAddressSpecification extends SigmaDslTesting
}
{
- val pk: DLogProtocol.ProveDlog = DLogProverInput(BigInteger.ONE).publicImage
+ val pk: ProveDlog = DLogProverInput(BigInteger.ONE).publicImage
val p2pk = P2PKAddress(pk)(ergoAddressEncoder)
val invalidAddrType = 4.toByte
@@ -192,9 +201,9 @@ class ErgoAddressSpecification extends SigmaDslTesting
{
val unparsedTree = new ErgoTree(
- (ErgoTree.ConstantSegregationHeader | ergoTreeHeaderInTests).toByte,
+ setConstantSegregation(ergoTreeHeaderInTests),
Array[Constant[SType]](),
- Left(UnparsedErgoTree(Array[Byte](), ValidationException("", ValidationRules.CheckTypeCode, Seq())))
+ Left(UnparsedErgoTree(Array[Byte](), ValidationException("", CheckTypeCode, Seq())))
)
assertExceptionThrown(
ergoAddressEncoder.fromProposition(unparsedTree).getOrThrow,
@@ -204,7 +213,7 @@ class ErgoAddressSpecification extends SigmaDslTesting
{
val invalidTree = new ErgoTree(
- (ErgoTree.ConstantSegregationHeader | ergoTreeHeaderInTests).toByte,
+ setConstantSegregation(ergoTreeHeaderInTests),
Array[Constant[SType]](),
Right(IntConstant(10).asSigmaProp)
)
@@ -243,12 +252,16 @@ class ErgoAddressSpecification extends SigmaDslTesting
verifier.verify(env + (ScriptNameProp -> s"verify_ext"), address.script, ctx, pr.proof, fakeMessage).getOrThrow._1 shouldBe true
}
- property("spending a box protected by P2SH contract") {
+ def createPropAndScriptBytes() = {
implicit lazy val IR = new TestingIRContext
-
val script = "{ 1 < 2 }"
val prop = compile(Map.empty, script).asBoolValue.toSigmaProp
val scriptBytes = ValueSerializer.serialize(prop)
+ (prop, scriptBytes)
+ }
+
+ property("spending a box protected by P2SH contract") {
+ val (prop, scriptBytes) = createPropAndScriptBytes()
testPay2SHAddress(Pay2SHAddress(prop), scriptBytes)
@@ -256,8 +269,24 @@ class ErgoAddressSpecification extends SigmaDslTesting
testPay2SHAddress(Pay2SHAddress(tree), scriptBytes) // NOTE: same scriptBytes regardless of ErgoTree version
}
+ property("Pay2SHAddress.script should create ErgoTree v0") {
+ val (prop, _) = createPropAndScriptBytes()
+
+ val address = VersionContext.withVersions(activatedVersionInTests, ergoTreeVersionInTests) {
+ Pay2SHAddress(prop)
+ }
+ address.script.version shouldBe 0
+ }
+
+ // create non-versioned property which is executed under default version context
+ // see VersionContext._defaultContext
+ super[AnyPropSpecLike].property("using default VersionContext still creates ErgoTree v0") {
+ val (prop, _) = createPropAndScriptBytes()
+ val address = Pay2SHAddress(prop)
+ address.script.version shouldBe 0
+ }
+
property("negative cases: deserialized script + costing exceptions") {
- implicit lazy val IR = new TestingIRContext
def testPay2SHAddress(address: Pay2SHAddress, script: VarBinding, costLimit: Int = scriptCostLimitInTests): CostedProverResult = {
val boxToSpend = testBox(10, address.script, creationHeight = 5)
@@ -272,24 +301,23 @@ class ErgoAddressSpecification extends SigmaDslTesting
}
val scriptVarId = Pay2SHAddress.scriptId
- val script = "{ 1 < 2 }"
- val prop = compile(Map.empty, script).asBoolValue.toSigmaProp
- val scriptBytes = ValueSerializer.serialize(prop)
+ val (prop, scriptBytes) = createPropAndScriptBytes()
val addr = Pay2SHAddress(prop)
// when everything is ok
testPay2SHAddress(addr, script = scriptVarId -> ByteArrayConstant(scriptBytes))
+ val expectedCost = 88
+
// when limit is low
{
val deliberatelySmallLimit = 24
-
assertExceptionThrown(
testPay2SHAddress(addr,
script = scriptVarId -> ByteArrayConstant(scriptBytes),
costLimit = deliberatelySmallLimit),
rootCauseLike[CostLimitException](
- s"Estimated execution cost 88 exceeds the limit $deliberatelySmallLimit")
+ s"Estimated execution cost $expectedCost exceeds the limit $deliberatelySmallLimit")
)
}
@@ -305,7 +333,7 @@ class ErgoAddressSpecification extends SigmaDslTesting
costLimit = deliberatelySmallLimit)
},
rootCauseLike[CostLimitException](
- s"Estimated execution cost 88 exceeds the limit $deliberatelySmallLimit")
+ s"Estimated execution cost $expectedCost exceeds the limit $deliberatelySmallLimit")
)
}
diff --git a/sc/shared/src/test/scala/org/ergoplatform/ErgoLikeTransactionSpec.scala b/sc/shared/src/test/scala/org/ergoplatform/ErgoLikeTransactionSpec.scala
index 1661f43803..6a7ef5a512 100644
--- a/sc/shared/src/test/scala/org/ergoplatform/ErgoLikeTransactionSpec.scala
+++ b/sc/shared/src/test/scala/org/ergoplatform/ErgoLikeTransactionSpec.scala
@@ -5,16 +5,17 @@ import org.ergoplatform.ErgoBox.TokenId
import org.ergoplatform.sdk.JsonCodecs
import org.ergoplatform.settings.ErgoAlgos
import scorex.util.encode.Base16
-import scorex.util.{Random, ModifierId}
-import sigmastate.SCollection.SByteArray
-import sigmastate.{SSigmaProp, TrivialProp, SType, SPair, SInt}
-import sigmastate.Values._
-import sigmastate.interpreter.{ContextExtension, ProverResult}
-import sigmastate.serialization.SigmaSerializer
-import sigmastate.eval._
-import sigmastate.eval.Extensions._
-import sigmastate._
-import sigmastate.SType._
+import scorex.util.{ModifierId, Random}
+import sigma.Extensions._
+import sigma.SigmaDslTesting
+import sigma.ast.SCollection.SByteArray
+import sigma.ast.SType._
+import sigma.ast.syntax.{ErgoBoxCandidateRType, TrueSigmaProp}
+import sigma.ast._
+import sigma.data.{CSigmaProp, Digest32Coll, TrivialProp}
+import sigma.eval.Extensions.{EvalCollOps, EvalIterableOps}
+import sigma.interpreter.{ContextExtension, ProverResult}
+import sigma.serialization.SigmaSerializer
import sigmastate.helpers.TestingHelpers.copyTransaction
import sigmastate.utils.Helpers
import sigma.SigmaDslTesting
@@ -28,7 +29,7 @@ class ErgoLikeTransactionSpec extends SigmaDslTesting with JsonCodecs {
val token2 = "a3ff007f00057600808001ff8f8000019000ffdb806fff7cc0b6015eb37fa600"
val b1 = new ErgoBoxCandidate(
10L,
- ErgoTree(ErgoTree.DefaultHeader, Vector(), TrueSigmaProp),
+ ErgoTree(ErgoTree.ZeroHeader, Vector(), TrueSigmaProp),
100,
Coll(
(Digest32Coll @@@ (ErgoAlgos.decodeUnsafe(token1).toColl)) -> 10000000L,
@@ -37,7 +38,7 @@ class ErgoLikeTransactionSpec extends SigmaDslTesting with JsonCodecs {
)
val b1_clone = new ErgoBoxCandidate(
10L,
- ErgoTree(ErgoTree.DefaultHeader, Vector(), TrueSigmaProp),
+ ErgoTree(ErgoTree.ZeroHeader, Vector(), TrueSigmaProp),
100,
Coll(
Digest32Coll @@ (ErgoAlgos.decodeUnsafe(token1).toColl) -> 10000000L,
diff --git a/sc/shared/src/test/scala/org/ergoplatform/ErgoTreePredefSpec.scala b/sc/shared/src/test/scala/org/ergoplatform/ErgoTreePredefSpec.scala
index d017b6ca35..eb086e88c8 100644
--- a/sc/shared/src/test/scala/org/ergoplatform/ErgoTreePredefSpec.scala
+++ b/sc/shared/src/test/scala/org/ergoplatform/ErgoTreePredefSpec.scala
@@ -8,18 +8,18 @@ import org.scalacheck.Gen
import scorex.crypto.hash.Blake2b256
import scorex.util.Random
import sigma.Colls
+import sigma.ast._
+import sigma.ast.syntax.CollectionConstant
+import sigma.data.{AvlTreeData, Digest32Coll, ProveDlog, TrivialProp}
import sigma.util.BenchmarkUtil.measure
-import sigmastate.Values.{ByteArrayConstant, CollectionConstant, ErgoTree, IntConstant, SigmaPropConstant}
import sigmastate._
-import sigmastate.crypto.DLogProtocol.{DLogProverInput, ProveDlog}
+import sigmastate.crypto.DLogProtocol.DLogProverInput
import sigmastate.helpers.{CompilerTestingCommons, ContextEnrichingTestProvingInterpreter, ErgoLikeContextTesting, ErgoLikeTestInterpreter}
import sigmastate.helpers.TestingHelpers._
import sigmastate.interpreter.Interpreter.{ScriptNameProp, emptyEnv}
-import sigmastate.interpreter.{ContextExtension, ProverResult}
-import sigmastate.lang.Terms.ValueOps
-import sigmastate.serialization.ValueSerializer
-import sigmastate.utxo.{ByIndex, ExtractCreationInfo, SelectField}
-import sigmastate.eval.Digest32Coll
+import sigma.ast.syntax.ValueOps
+import sigma.interpreter.{ContextExtension, ProverResult}
+import sigma.serialization.ValueSerializer
import sigmastate.utils.Helpers._
import scala.util.Try
@@ -92,7 +92,9 @@ class ErgoTreePredefSpec extends CompilerTestingCommons with CompilerCrossVersio
// unable to satisfy R4 conditions
checkSpending(remaining(height), height, prop, R4Prop(false)).isFailure shouldBe true
// incorrect new script
- checkSpending(remaining(height), height, TrivialProp.TrueProp, R4Prop(true)).isFailure shouldBe true
+ checkSpending(remaining(height), height,
+ ErgoTree.fromProposition(TrivialProp.TrueProp),
+ R4Prop(true)).isFailure shouldBe true
// collect less coins then possible
checkSpending(remaining(height) + 1, height, prop, R4Prop(true)).isSuccess shouldBe true
// collect more coins then possible
@@ -188,7 +190,8 @@ class ErgoTreePredefSpec extends CompilerTestingCommons with CompilerCrossVersio
createRewardTx(currentRate, height, correctProp).isSuccess shouldBe true
createRewardTx(currentRate, height, incorrectDelay).isFailure shouldBe true
createRewardTx(currentRate, height, incorrectPk).isFailure shouldBe true
- createRewardTx(currentRate, height, minerPk).isFailure shouldBe true
+ createRewardTx(currentRate, height,
+ ErgoTree.fromSigmaBoolean(minerPk)).isFailure shouldBe true
}
def createRewardTx(emissionAmount: Long, nextHeight: Int, minerProp: ErgoTree): Try[ErgoLikeTransaction] = {
diff --git a/sc/shared/src/test/scala/org/ergoplatform/dsl/TestContractSpec.scala b/sc/shared/src/test/scala/org/ergoplatform/dsl/TestContractSpec.scala
index 46668c3b1a..26e8b08b14 100644
--- a/sc/shared/src/test/scala/org/ergoplatform/dsl/TestContractSpec.scala
+++ b/sc/shared/src/test/scala/org/ergoplatform/dsl/TestContractSpec.scala
@@ -3,33 +3,34 @@ package org.ergoplatform.dsl
import sigmastate.interpreter.Interpreter.ScriptNameProp
import scala.collection.mutable
-import sigmastate.interpreter.{CostedProverResult, ProverResult}
-
+import sigma.interpreter.{CostedProverResult, ProverResult}
import scala.collection.mutable.ArrayBuffer
import org.ergoplatform.ErgoBox.{NonMandatoryRegisterId, TokenId}
-import sigma.data.Nullable
+import sigma.data.{AvlTreeData, CAnyValue, CSigmaProp, Nullable}
import scala.util.Try
import org.ergoplatform.{ErgoBox, ErgoLikeContext}
import org.ergoplatform.dsl.ContractSyntax.{ErgoScript, Proposition, Token}
-import sigmastate.{AvlTreeData, SType}
-import sigmastate.Values.{ErgoTree, EvaluatedValue}
-import sigmastate.eval.{CSigmaProp, Evaluation, IRContext, CAnyValue}
-import sigmastate.helpers.{ContextEnrichingTestProvingInterpreter, ErgoLikeContextTesting, ErgoLikeTestInterpreter, CompilerTestingCommons}
+import sigma.ast.{ErgoTree, SType}
+import sigma.ast.EvaluatedValue
+import sigma.interpreter.ContextExtension
+import sigmastate.eval.IRContext
+import sigmastate.helpers.{CompilerTestingCommons, ContextEnrichingTestProvingInterpreter, ErgoLikeContextTesting, ErgoLikeTestInterpreter}
import sigmastate.helpers.TestingHelpers._
-import sigmastate.lang.Terms.ValueOps
-import sigma.{AnyValue, SigmaProp}
+import sigma.ast.syntax.ValueOps
+import sigma.{AnyValue, Evaluation, SigmaProp}
+import ErgoTree.ZeroHeader
case class TestContractSpec(testSuite: CompilerTestingCommons)(implicit val IR: IRContext) extends ContractSpec {
case class TestPropositionSpec(name: String, dslSpec: Proposition, scriptSpec: ErgoScript) extends PropositionSpec {
lazy val ergoTree: ErgoTree = {
val value = testSuite.compile(scriptSpec.env, scriptSpec.code)
- val headerFlags = scriptSpec.scriptVersion match {
- case Some(version) => ErgoTree.headerWithVersion(version)
+ val header = scriptSpec.scriptVersion match {
+ case Some(version) => ErgoTree.headerWithVersion(ZeroHeader, version)
case None => testSuite.ergoTreeHeaderInTests
}
- val tree: ErgoTree = ErgoTree.fromProposition(headerFlags, value.asSigmaProp)
+ val tree: ErgoTree = ErgoTree.fromProposition(header, value.asSigmaProp)
tree
}
}
@@ -44,16 +45,13 @@ case class TestContractSpec(testSuite: CompilerTestingCommons)(implicit val IR:
val pubKey: SigmaProp = CSigmaProp(prover.dlogSecrets.head.publicImage)
import SType.AnyOps
- def prove(inBox: InputBox, extensions: Map[Byte, AnyValue] = Map()): Try[CostedProverResult] = {
+ def prove(inBox: InputBox, extensions: Map[Byte, EvaluatedValue[_ <: SType]] = Map()): Try[CostedProverResult] = {
val boxToSpend = inBox.utxoBox
val propSpec: PropositionSpec = boxToSpend.propSpec
- val bindings = extensions.mapValues { case v: CAnyValue[a] =>
- IR.builder.mkConstant(v.value.asWrappedType, Evaluation.rtypeToSType(v.tA))
- }
val ctx = inBox.toErgoContext
val env = propSpec.scriptSpec.env + (ScriptNameProp -> (propSpec.name + "_prove"))
val prop = propSpec.ergoTree
- val p = bindings.foldLeft(prover) { (p, b) => p.withContextExtender(b._1, b._2) }
+ val p = extensions.foldLeft(prover) { (p, b) => p.withContextExtender(b._1, b._2) }
val proof = p.prove(env, prop, ctx, testSuite.fakeMessage)
proof
}
@@ -92,8 +90,8 @@ case class TestContractSpec(testSuite: CompilerTestingCommons)(implicit val IR:
.withErgoTreeVersion(testSuite.ergoTreeVersionInTests)
ctx
}
- def runDsl(extensions: Map[Byte, AnyValue] = Map()): SigmaProp = {
- val ctx = toErgoContext.toSigmaContext(extensions)
+ def runDsl(extensions: Map[Byte, EvaluatedValue[_ <: SType]] = Map()): SigmaProp = {
+ val ctx = toErgoContext.withExtension(ContextExtension(extensions)).toSigmaContext()
val res = utxoBox.propSpec.dslSpec(ctx)
res
}
@@ -170,7 +168,6 @@ case class TestContractSpec(testSuite: CompilerTestingCommons)(implicit val IR:
case class BBlockCandidate(height: Int) extends BlockCandidate {
def newTransaction() = MockTransaction(this)
-// def onTopOf(chain: ChainBlock*)
}
def candidateBlock(height: Int): BlockCandidate = BBlockCandidate(height)
diff --git a/sc/shared/src/test/scala/org/ergoplatform/validation/RuleStatusSerializerSpec.scala b/sc/shared/src/test/scala/org/ergoplatform/validation/RuleStatusSerializerSpec.scala
index 9909f485b5..da7d74e79b 100644
--- a/sc/shared/src/test/scala/org/ergoplatform/validation/RuleStatusSerializerSpec.scala
+++ b/sc/shared/src/test/scala/org/ergoplatform/validation/RuleStatusSerializerSpec.scala
@@ -1,7 +1,8 @@
package org.ergoplatform.validation
+import sigma.validation.{ReplacedRule, RuleStatus}
import sigmastate.helpers.CompilerTestingCommons
-import sigmastate.serialization.{SigmaSerializer, SerializationSpecification}
+import sigma.serialization.{SerializationSpecification, SigmaSerializer}
class RuleStatusSerializerSpec extends SerializationSpecification with CompilerTestingCommons {
diff --git a/sc/shared/src/test/scala/org/ergoplatform/validation/SigmaValidationSettingsSerializerSpec.scala b/sc/shared/src/test/scala/org/ergoplatform/validation/SigmaValidationSettingsSerializerSpec.scala
index c4162103c6..ee1c1a339a 100644
--- a/sc/shared/src/test/scala/org/ergoplatform/validation/SigmaValidationSettingsSerializerSpec.scala
+++ b/sc/shared/src/test/scala/org/ergoplatform/validation/SigmaValidationSettingsSerializerSpec.scala
@@ -1,9 +1,10 @@
package org.ergoplatform.validation
-import org.ergoplatform.validation.ValidationRules.{FirstRuleId, currentSettings}
-import org.scalatest.Assertion
+import org.ergoplatform.validation.ValidationRules.currentSettings
+import sigma.validation.{DisabledRule, SigmaValidationSettings}
+import sigma.validation.ValidationRules.FirstRuleId
import sigmastate.helpers.CompilerTestingCommons
-import sigmastate.serialization.SerializationSpecification
+import sigma.serialization.SerializationSpecification
class SigmaValidationSettingsSerializerSpec extends SerializationSpecification with CompilerTestingCommons {
diff --git a/sc/shared/src/test/scala/sigma/DataValueComparerSpecification.scala b/sc/shared/src/test/scala/sigma/DataValueComparerSpecification.scala
index df3c5dc7ed..b82a747069 100644
--- a/sc/shared/src/test/scala/sigma/DataValueComparerSpecification.scala
+++ b/sc/shared/src/test/scala/sigma/DataValueComparerSpecification.scala
@@ -1,14 +1,13 @@
package sigma
import org.scalatest.BeforeAndAfterAll
-import sigma.data.RType
+import sigma.data.{CSigmaProp, DataValueComparer, RType, TrivialProp}
import sigma.util.BenchmarkUtil
-import sigmastate.{DataValueComparer, JitCost, TrivialProp}
-import sigmastate.Values.ErgoTree
-import sigmastate.eval.{CSigmaProp, Profiler, SigmaDsl}
+import sigmastate.eval.CProfiler
import sigmastate.helpers.SigmaPPrint
-import sigmastate.interpreter.{CostAccumulator, ErgoTreeEvaluator, EvalSettings, TracedCost}
-import sigma.Coll
+import sigmastate.interpreter.{CostAccumulator, CErgoTreeEvaluator}
+import sigma.ast.{ErgoTree, JitCost}
+import sigma.eval.{EvalSettings, SigmaDsl, TracedCost}
import scala.util.{Success, Try}
@@ -18,7 +17,7 @@ class DataValueComparerSpecification extends SigmaDslTesting
implicit override val generatorDrivenConfig = PropertyCheckConfiguration(minSuccessful = 30)
implicit override val evalSettings: EvalSettings =
- ErgoTreeEvaluator.DefaultEvalSettings.copy(
+ CErgoTreeEvaluator.DefaultEvalSettings.copy(
isMeasureOperationTime = true,
isMeasureScriptTime = true,
isLogEnabled = false, // don't commit the `true` value (CI log is too high)
@@ -29,15 +28,15 @@ class DataValueComparerSpecification extends SigmaDslTesting
val nWarmUpIterations = 100
- implicit val suiteProfiler = new Profiler
+ implicit val suiteProfiler = new CProfiler
import TestData._
- def createEvaluator(settings: EvalSettings, profiler: Profiler): ErgoTreeEvaluator = {
+ def createEvaluator(settings: EvalSettings, profiler: CProfiler): CErgoTreeEvaluator = {
val accumulator = new CostAccumulator(
initialCost = JitCost(0),
costLimit = Some(JitCost.fromBlockCost(settings.scriptCostLimitInEvaluator)))
- val evaluator = new ErgoTreeEvaluator(
+ val evaluator = new CErgoTreeEvaluator(
context = null,
constants = ErgoTree.EmptyConstants,
coster = accumulator, profiler, settings)
@@ -51,7 +50,7 @@ class DataValueComparerSpecification extends SigmaDslTesting
* @param x computation which produced first argument
* @param y computation which produced second argument
*/
- def check(x: => Any, y: => Any, expected: Boolean)(implicit settings: EvalSettings, profiler: Profiler) = {
+ def check(x: => Any, y: => Any, expected: Boolean)(implicit settings: EvalSettings, profiler: CProfiler) = {
val _x = x // force computation and obtain value
val _y = y
withClue(s"EQ.equalDataValues(${_x}, ${_y})") {
@@ -96,7 +95,7 @@ class DataValueComparerSpecification extends SigmaDslTesting
override protected def beforeAll(): Unit = {
// this method warms up the code in DataValueComparer
- val warmUpProfiler = new Profiler
+ val warmUpProfiler = new CProfiler
warmUpBeforeAllTest(nTotalIters = nWarmUpIterations) {
runBaseCases(warmUpProfiler)(evalSettings = evalSettings.copy(isLogEnabled = false))
}
@@ -116,7 +115,7 @@ class DataValueComparerSpecification extends SigmaDslTesting
* This method is used:
* 1) to warm up DataValueComparer in the beforeAll method
* 2) to profile DataValueComparer operations */
- def runBaseCases(profiler: Profiler)(implicit evalSettings: EvalSettings) = {
+ def runBaseCases(profiler: CProfiler)(implicit evalSettings: EvalSettings) = {
implicit val suiteProfiler = profiler // hide suite's profiler and use explicitly passed
ones.foreach { x =>
ones.foreach { y =>
diff --git a/sc/shared/src/test/scala/sigma/SigmaDslSpecification.scala b/sc/shared/src/test/scala/sigma/SigmaDslSpecification.scala
index f5c47a055f..4dd576f03a 100644
--- a/sc/shared/src/test/scala/sigma/SigmaDslSpecification.scala
+++ b/sc/shared/src/test/scala/sigma/SigmaDslSpecification.scala
@@ -1,48 +1,42 @@
package special.sigma
-import java.math.BigInteger
+import org.ergoplatform.ErgoBox.AdditionalRegisters
import org.ergoplatform._
import org.ergoplatform.settings.ErgoAlgos
+import org.scalacheck.Arbitrary._
import org.scalacheck.{Arbitrary, Gen}
-import sigma.data.{ExactIntegral, ExactNumeric, ExactOrdering, RType}
+import org.scalatest.BeforeAndAfterAll
import scorex.crypto.authds.avltree.batch._
import scorex.crypto.authds.{ADKey, ADValue}
import scorex.crypto.hash.{Blake2b256, Digest32}
-import sigma.util.Extensions._
-import sigmastate.utils.Extensions._
-import sigmastate.SCollection._
-import sigmastate.Values.IntConstant
+import scorex.util.ModifierId
+import sigma.Extensions.{ArrayOps, CollOps}
+import sigma.ast.SCollection._
+import sigma.ast._
+import sigma.ast.syntax._
+import sigma.data.RType._
+import sigma.data._
+import sigma.util.Extensions.{BooleanOps, IntOps, LongOps}
+import sigma.{VersionContext, ast, data, _}
+import ErgoTree.{HeaderType, ZeroHeader}
+import sigma.eval.{CostDetails, EvalSettings, Profiler, SigmaDsl, TracedCost}
import sigmastate._
-import sigmastate.crypto.DLogProtocol._
-import sigmastate.Values._
-import sigmastate.lang.Terms.Apply
-import sigmastate.eval.Extensions._
+import sigmastate.eval.Extensions.AvlTreeOps
+import sigma.eval.Extensions.{ByteExt, IntExt, LongExt, ShortExt}
+import OrderingOps._
import sigmastate.eval._
-import sigmastate.lang.Terms.{MethodCall, PropertyCall}
-import sigmastate.utxo._
-import sigma._
-import sigma.Extensions._
-import sigmastate.serialization.OpCodes.OpCode
-import sigmastate.utils.Helpers
-import sigmastate.utils.Helpers._
import sigmastate.helpers.TestingHelpers._
-
-import scala.util.{Failure, Success, Try}
-import OrderingOps._
-import org.ergoplatform.ErgoBox.AdditionalRegisters
-import org.scalacheck.Arbitrary._
-import org.scalacheck.Gen.frequency
-import org.scalatest.{BeforeAndAfterAll, Tag}
-import sigma.data.RType._
-import scorex.util.ModifierId
-import sigmastate.crypto.ProveDHTuple
import sigmastate.interpreter._
-import org.scalactic.source.Position
-import sigma.VersionContext
-import sigmastate.helpers.SigmaPPrint
-import sigmastate.exceptions.GraphBuildingException
+import sigma.ast.{Apply, MethodCall, PropertyCall}
+import sigma.exceptions.InvalidType
+import sigma.serialization.ValueCodes.OpCode
+import sigmastate.utils.Extensions._
+import sigmastate.utils.Helpers
+import sigmastate.utils.Helpers._
+import java.math.BigInteger
import scala.collection.compat.immutable.ArraySeq
+import scala.util.{Failure, Success}
/** This suite tests every method of every SigmaDsl type to be equivalent to
* the evaluation of the corresponding ErgoScript operation.
@@ -86,7 +80,7 @@ class SigmaDslSpecification extends SigmaDslTesting
implicit override val generatorDrivenConfig = PropertyCheckConfiguration(minSuccessful = 30)
- val evalSettingsInTests = ErgoTreeEvaluator.DefaultEvalSettings.copy(
+ val evalSettingsInTests = CErgoTreeEvaluator.DefaultEvalSettings.copy(
isMeasureOperationTime = true,
isMeasureScriptTime = true,
isLogEnabled = false, // don't commit the `true` value (travis log is too high)
@@ -97,7 +91,7 @@ class SigmaDslSpecification extends SigmaDslTesting
*/
costTracingEnabled = true,
- profilerOpt = Some(ErgoTreeEvaluator.DefaultProfiler),
+ profilerOpt = Some(CErgoTreeEvaluator.DefaultProfiler),
isTestRun = true
)
@@ -180,7 +174,7 @@ class SigmaDslSpecification extends SigmaDslTesting
FixedCostItem(GetVar),
FixedCostItem(OptionGet),
FixedCostItem(FuncValue.AddToEnvironmentDesc, FuncValue.AddToEnvironmentDesc_CostKind),
- SeqCostItem(CompanionDesc(BlockValue), PerItemCost(JitCost(1), JitCost(1), 10), 2),
+ ast.SeqCostItem(CompanionDesc(BlockValue), PerItemCost(JitCost(1), JitCost(1), 10), 2),
FixedCostItem(ValUse),
FixedCostItem(SelectField),
FixedCostItem(FuncValue.AddToEnvironmentDesc, FuncValue.AddToEnvironmentDesc_CostKind),
@@ -674,7 +668,7 @@ class SigmaDslSpecification extends SigmaDslTesting
FixedCostItem(GetVar),
FixedCostItem(OptionGet),
FixedCostItem(FuncValue.AddToEnvironmentDesc, FixedCost(JitCost(5))),
- SeqCostItem(CompanionDesc(BlockValue), PerItemCost(JitCost(1), JitCost(1), 10), 1),
+ ast.SeqCostItem(CompanionDesc(BlockValue), PerItemCost(JitCost(1), JitCost(1), 10), 1),
FixedCostItem(ValUse),
FixedCostItem(LogicalNot),
FixedCostItem(FuncValue.AddToEnvironmentDesc, FixedCost(JitCost(5))),
@@ -1066,7 +1060,6 @@ class SigmaDslSpecification extends SigmaDslTesting
property("Byte methods equivalence (new features)") {
lazy val toBytes = newFeature((x: Byte) => x.toBytes, "{ (x: Byte) => x.toBytes }")
- lazy val toBits = newFeature((x: Byte) => x.toBits, "{ (x: Byte) => x.toBits }")
lazy val toAbs = newFeature((x: Byte) => x.toAbs, "{ (x: Byte) => x.toAbs }")
lazy val compareTo = newFeature(
(x: (Byte, Byte)) => x._1.compareTo(x._2),
@@ -1081,7 +1074,7 @@ class SigmaDslSpecification extends SigmaDslTesting
"{ (x: (Byte, Byte)) => (x._1 & x._2).toByteExact }")
forAll { x: Byte =>
- Seq(toBytes, toBits, toAbs).foreach(f => f.checkEquality(x))
+ Seq(toBytes, toAbs).foreach(f => f.checkEquality(x))
}
forAll { x: (Byte, Byte) =>
@@ -1371,7 +1364,6 @@ class SigmaDslSpecification extends SigmaDslTesting
property("Short methods equivalence (new features)") {
lazy val toBytes = newFeature((x: Short) => x.toBytes, "{ (x: Short) => x.toBytes }")
- lazy val toBits = newFeature((x: Short) => x.toBits, "{ (x: Short) => x.toBits }")
lazy val toAbs = newFeature((x: Short) => x.toAbs, "{ (x: Short) => x.toAbs }")
lazy val compareTo = newFeature((x: (Short, Short)) => x._1.compareTo(x._2),
@@ -1386,7 +1378,7 @@ class SigmaDslSpecification extends SigmaDslTesting
"{ (x: (Short, Short)) => x._1 & x._2 }")
forAll { x: Short =>
- Seq(toBytes, toBits, toAbs).foreach(_.checkEquality(x))
+ Seq(toBytes, toAbs).foreach(_.checkEquality(x))
}
forAll { x: (Short, Short) =>
Seq(compareTo, bitOr, bitAnd).foreach(_.checkEquality(x))
@@ -1675,7 +1667,6 @@ class SigmaDslSpecification extends SigmaDslTesting
property("Int methods equivalence (new features)") {
lazy val toBytes = newFeature((x: Int) => x.toBytes, "{ (x: Int) => x.toBytes }")
- lazy val toBits = newFeature((x: Int) => x.toBits, "{ (x: Int) => x.toBits }")
lazy val toAbs = newFeature((x: Int) => x.toAbs, "{ (x: Int) => x.toAbs }")
lazy val compareTo = newFeature((x: (Int, Int)) => x._1.compareTo(x._2),
"{ (x: (Int, Int)) => x._1.compareTo(x._2) }")
@@ -1689,7 +1680,7 @@ class SigmaDslSpecification extends SigmaDslTesting
"{ (x: (Int, Int)) => x._1 & x._2 }")
forAll { x: Int =>
- Seq(toBytes, toBits, toAbs).foreach(_.checkEquality(x))
+ Seq(toBytes, toAbs).foreach(_.checkEquality(x))
}
forAll { x: (Int, Int) =>
Seq(compareTo, bitOr, bitAnd).foreach(_.checkEquality(x))
@@ -1995,9 +1986,7 @@ class SigmaDslSpecification extends SigmaDslTesting
property("Long methods equivalence (new features)") {
lazy val toBytes = newFeature((x: Long) => x.toBytes, "{ (x: Long) => x.toBytes }")
- lazy val toBits = newFeature((x: Long) => x.toBits, "{ (x: Long) => x.toBits }")
lazy val toAbs = newFeature((x: Long) => x.toAbs, "{ (x: Long) => x.toAbs }")
-
lazy val compareTo = newFeature((x: (Long, Long)) => x._1.compareTo(x._2),
"{ (x: (Long, Long)) => x._1.compareTo(x._2) }")
@@ -2010,7 +1999,7 @@ class SigmaDslSpecification extends SigmaDslTesting
"{ (x: (Long, Long)) => x._1 & x._2 }")
forAll { x: Long =>
- Seq(toBytes, toBits, toAbs).foreach(_.checkEquality(x))
+ Seq(toBytes, toAbs).foreach(_.checkEquality(x))
}
forAll { x: (Long, Long) =>
Seq(compareTo, bitOr, bitAnd).foreach(_.checkEquality(x))
@@ -2309,7 +2298,6 @@ class SigmaDslSpecification extends SigmaDslTesting
FuncValue(Vector((1, SBigInt)), Downcast(ValUse(1, SBigInt), SLong)))
lazy val toBytes = newFeature((x: BigInt) => x.toBytes, "{ (x: BigInt) => x.toBytes }")
- lazy val toBits = newFeature((x: BigInt) => x.toBits, "{ (x: BigInt) => x.toBits }")
lazy val toAbs = newFeature((x: BigInt) => x.toAbs, "{ (x: BigInt) => x.toAbs }")
lazy val compareTo = newFeature((x: (BigInt, BigInt)) => x._1.compareTo(x._2),
@@ -2322,7 +2310,7 @@ class SigmaDslSpecification extends SigmaDslTesting
"{ (x: (BigInt, BigInt)) => x._1 & x._2 }")
forAll { x: BigInt =>
- Seq(toByte, toShort, toInt, toLong, toBytes, toBits, toAbs).foreach(_.checkEquality(x))
+ Seq(toByte, toShort, toInt, toLong, toBytes, toAbs).foreach(_.checkEquality(x))
}
forAll { x: (BigInt, BigInt) =>
Seq(compareTo, bitOr, bitAnd).foreach(_.checkEquality(x))
@@ -2354,7 +2342,7 @@ class SigmaDslSpecification extends SigmaDslTesting
property("NEQ of pre-defined types") {
verifyNeq(ge1, ge2, 1783, Array[CostItem](FixedCostItem(NamedDesc("EQ_GroupElement"), FixedCost(JitCost(172)))), 1783)(_.asInstanceOf[CGroupElement].copy())
verifyNeq(t1, t2, 1767, Array[CostItem](FixedCostItem(NamedDesc("EQ_AvlTree"), FixedCost(JitCost(6)))), 1767)(_.asInstanceOf[CAvlTree].copy())
- verifyNeq(b1, b2, 1767, Array[CostItem](), 1767)(_.asInstanceOf[CostingBox].copy())
+ verifyNeq(b1, b2, 1767, Array[CostItem](), 1767)(_.asInstanceOf[CBox].copy())
verifyNeq(preH1, preH2, 1766, Array[CostItem](FixedCostItem(NamedDesc("EQ_PreHeader"), FixedCost(JitCost(4)))), 1766)(_.asInstanceOf[CPreHeader].copy())
verifyNeq(h1, h2, 1767, Array[CostItem](FixedCostItem(NamedDesc("EQ_Header"), FixedCost(JitCost(6)))), 1767)(_.asInstanceOf[CHeader].copy())
}
@@ -2504,14 +2492,14 @@ class SigmaDslSpecification extends SigmaDslTesting
)
val collNeqCost2 = Array(
FixedCostItem(NamedDesc("MatchType"), FixedCost(JitCost(1))),
- SeqCostItem(NamedDesc("EQ_COA_Box"), PerItemCost(JitCost(15), JitCost(5), 1), 0)
+ ast.SeqCostItem(NamedDesc("EQ_COA_Box"), PerItemCost(JitCost(15), JitCost(5), 1), 0)
)
implicit val evalSettings = suite.evalSettings.copy(isMeasureOperationTime = false)
verifyNeq(Coll[Byte](), Coll(1.toByte), 1766, collNeqCost1, 1766)(cloneColl(_))
verifyNeq(Coll[Byte](0, 1), Coll(1.toByte, 1.toByte), 1768,
Array(
FixedCostItem(NamedDesc("MatchType"), FixedCost(JitCost(1))),
- SeqCostItem(NamedDesc("EQ_COA_Byte"), PerItemCost(JitCost(15), JitCost(2), 128), 1)),
+ ast.SeqCostItem(NamedDesc("EQ_COA_Byte"), PerItemCost(JitCost(15), JitCost(2), 128), 1)),
1768
)(cloneColl(_))
@@ -2519,7 +2507,7 @@ class SigmaDslSpecification extends SigmaDslTesting
verifyNeq(Coll[Short](0), Coll(1.toShort), 1768,
Array(
FixedCostItem(NamedDesc("MatchType"), FixedCost(JitCost(1))),
- SeqCostItem(NamedDesc("EQ_COA_Short"), PerItemCost(JitCost(15), JitCost(2), 96), 1)),
+ ast.SeqCostItem(NamedDesc("EQ_COA_Short"), PerItemCost(JitCost(15), JitCost(2), 96), 1)),
1768
)(cloneColl(_))
@@ -2527,7 +2515,7 @@ class SigmaDslSpecification extends SigmaDslTesting
verifyNeq(Coll[Int](0), Coll(1), 1768,
Array(
FixedCostItem(NamedDesc("MatchType"), FixedCost(JitCost(1))),
- SeqCostItem(NamedDesc("EQ_COA_Int"), PerItemCost(JitCost(15), JitCost(2), 64), 1)),
+ ast.SeqCostItem(NamedDesc("EQ_COA_Int"), PerItemCost(JitCost(15), JitCost(2), 64), 1)),
1768
)(cloneColl(_))
@@ -2535,7 +2523,7 @@ class SigmaDslSpecification extends SigmaDslTesting
verifyNeq(Coll[Long](0), Coll(1.toLong), 1768,
Array(
FixedCostItem(NamedDesc("MatchType"), FixedCost(JitCost(1))),
- SeqCostItem(NamedDesc("EQ_COA_Long"), PerItemCost(JitCost(15), JitCost(2), 48), 1)),
+ ast.SeqCostItem(NamedDesc("EQ_COA_Long"), PerItemCost(JitCost(15), JitCost(2), 48), 1)),
1768
)(cloneColl(_))
@@ -2544,7 +2532,7 @@ class SigmaDslSpecification extends SigmaDslTesting
verifyNeq(Coll[BigInt](0.toBigInt), Coll(1.toBigInt), 1768,
Array(
FixedCostItem(NamedDesc("MatchType"), FixedCost(JitCost(1))),
- SeqCostItem(NamedDesc("EQ_COA_BigInt"), PerItemCost(JitCost(15), JitCost(7), 5), 1)),
+ ast.SeqCostItem(NamedDesc("EQ_COA_BigInt"), PerItemCost(JitCost(15), JitCost(7), 5), 1)),
1768
)(cloneColl(_))
@@ -2553,7 +2541,7 @@ class SigmaDslSpecification extends SigmaDslTesting
verifyNeq(Coll[GroupElement](ge1), Coll(ge2), 1768,
Array(
FixedCostItem(NamedDesc("MatchType"), FixedCost(JitCost(1))),
- SeqCostItem(NamedDesc("EQ_COA_GroupElement"), PerItemCost(JitCost(15), JitCost(5), 1), 1)),
+ ast.SeqCostItem(NamedDesc("EQ_COA_GroupElement"), PerItemCost(JitCost(15), JitCost(5), 1), 1)),
1768
)(cloneColl(_))
@@ -2562,7 +2550,7 @@ class SigmaDslSpecification extends SigmaDslTesting
verifyNeq(Coll[AvlTree](t1), Coll(t2), 1768,
Array(
FixedCostItem(NamedDesc("MatchType"), FixedCost(JitCost(1))),
- SeqCostItem(NamedDesc("EQ_COA_AvlTree"), PerItemCost(JitCost(15), JitCost(5), 2), 1)),
+ ast.SeqCostItem(NamedDesc("EQ_COA_AvlTree"), PerItemCost(JitCost(15), JitCost(5), 2), 1)),
1768
)(cloneColl(_))
@@ -2583,7 +2571,7 @@ class SigmaDslSpecification extends SigmaDslTesting
verifyNeq(Coll[Box](b1), Coll(b2), 1768,
Array(
FixedCostItem(NamedDesc("MatchType"), FixedCost(JitCost(1))),
- SeqCostItem(NamedDesc("EQ_COA_Box"), PerItemCost(JitCost(15), JitCost(5), 1), 1)),
+ ast.SeqCostItem(NamedDesc("EQ_COA_Box"), PerItemCost(JitCost(15), JitCost(5), 1), 1)),
1768
)(cloneColl(_), generateCases = false)
}
@@ -2593,7 +2581,7 @@ class SigmaDslSpecification extends SigmaDslTesting
verifyNeq(Coll[PreHeader](preH1), Coll(preH2), 1768,
Array(
FixedCostItem(NamedDesc("MatchType"), FixedCost(JitCost(1))),
- SeqCostItem(NamedDesc("EQ_COA_PreHeader"), PerItemCost(JitCost(15), JitCost(3), 1), 1)),
+ ast.SeqCostItem(NamedDesc("EQ_COA_PreHeader"), PerItemCost(JitCost(15), JitCost(3), 1), 1)),
1768
)(cloneColl(_))
@@ -2602,7 +2590,7 @@ class SigmaDslSpecification extends SigmaDslTesting
verifyNeq(Coll[Header](h1), Coll(h2), 1768,
Array(
FixedCostItem(NamedDesc("MatchType"), FixedCost(JitCost(1))),
- SeqCostItem(NamedDesc("EQ_COA_Header"), PerItemCost(JitCost(15), JitCost(5), 1), 1)),
+ ast.SeqCostItem(NamedDesc("EQ_COA_Header"), PerItemCost(JitCost(15), JitCost(5), 1), 1)),
1768
)(cloneColl(_))
}
@@ -2619,13 +2607,13 @@ class SigmaDslSpecification extends SigmaDslTesting
val nestedNeq2 = Array(
FixedCostItem(NamedDesc("MatchType"), FixedCost(JitCost(1))),
FixedCostItem(NamedDesc("MatchType"), FixedCost(JitCost(1))),
- SeqCostItem(NamedDesc("EQ_Coll"), PerItemCost(JitCost(10), JitCost(2), 1), 1)
+ ast.SeqCostItem(NamedDesc("EQ_Coll"), PerItemCost(JitCost(10), JitCost(2), 1), 1)
)
val nestedNeq3 = Array(
FixedCostItem(NamedDesc("MatchType"), FixedCost(JitCost(1))),
FixedCostItem(NamedDesc("MatchType"), FixedCost(JitCost(1))),
- SeqCostItem(NamedDesc("EQ_COA_Int"), PerItemCost(JitCost(15), JitCost(2), 64), 1),
- SeqCostItem(NamedDesc("EQ_Coll"), PerItemCost(JitCost(10), JitCost(2), 1), 1)
+ ast.SeqCostItem(NamedDesc("EQ_COA_Int"), PerItemCost(JitCost(15), JitCost(2), 64), 1),
+ ast.SeqCostItem(NamedDesc("EQ_Coll"), PerItemCost(JitCost(10), JitCost(2), 1), 1)
)
verifyNeq(Coll[Coll[Int]](), Coll(Coll[Int]()), 1766, nestedNeq1, 1766)(cloneColl(_))
verifyNeq(Coll(Coll[Int]()), Coll(Coll[Int](1)), 1767, nestedNeq2, 1767)(cloneColl(_))
@@ -2641,8 +2629,8 @@ class SigmaDslSpecification extends SigmaDslTesting
FixedCostItem(NamedDesc("EQ_Tuple"), FixedCost(JitCost(4))),
FixedCostItem(NamedDesc("EQ_Prim"), FixedCost(JitCost(3))),
FixedCostItem(NamedDesc("EQ_BigInt"), FixedCost(JitCost(5))),
- SeqCostItem(NamedDesc("EQ_Coll"), PerItemCost(JitCost(10), JitCost(2), 1), 1),
- SeqCostItem(NamedDesc("EQ_Coll"), PerItemCost(JitCost(10), JitCost(2), 1), 1)
+ ast.SeqCostItem(NamedDesc("EQ_Coll"), PerItemCost(JitCost(10), JitCost(2), 1), 1),
+ ast.SeqCostItem(NamedDesc("EQ_Coll"), PerItemCost(JitCost(10), JitCost(2), 1), 1)
)
val nestedNeq5 = Array(
FixedCostItem(NamedDesc("MatchType"), FixedCost(JitCost(1))),
@@ -2651,9 +2639,9 @@ class SigmaDslSpecification extends SigmaDslTesting
FixedCostItem(NamedDesc("EQ_Tuple"), FixedCost(JitCost(4))),
FixedCostItem(NamedDesc("EQ_Prim"), FixedCost(JitCost(3))),
FixedCostItem(NamedDesc("EQ_BigInt"), FixedCost(JitCost(5))),
- SeqCostItem(NamedDesc("EQ_Coll"), PerItemCost(JitCost(10), JitCost(2), 1), 1),
- SeqCostItem(NamedDesc("EQ_Coll"), PerItemCost(JitCost(10), JitCost(2), 1), 1),
- SeqCostItem(NamedDesc("EQ_Coll"), PerItemCost(JitCost(10), JitCost(2), 1), 1)
+ ast.SeqCostItem(NamedDesc("EQ_Coll"), PerItemCost(JitCost(10), JitCost(2), 1), 1),
+ ast.SeqCostItem(NamedDesc("EQ_Coll"), PerItemCost(JitCost(10), JitCost(2), 1), 1),
+ ast.SeqCostItem(NamedDesc("EQ_Coll"), PerItemCost(JitCost(10), JitCost(2), 1), 1)
)
val nestedNeq6 = Array(
FixedCostItem(NamedDesc("EQ_Tuple"), FixedCost(JitCost(4))),
@@ -2669,9 +2657,9 @@ class SigmaDslSpecification extends SigmaDslTesting
FixedCostItem(NamedDesc("EQ_Tuple"), FixedCost(JitCost(4))),
FixedCostItem(NamedDesc("EQ_Prim"), FixedCost(JitCost(3))),
FixedCostItem(NamedDesc("EQ_BigInt"), FixedCost(JitCost(5))),
- SeqCostItem(NamedDesc("EQ_Coll"), PerItemCost(JitCost(10), JitCost(2), 1), 2),
- SeqCostItem(NamedDesc("EQ_Coll"), PerItemCost(JitCost(10), JitCost(2), 1), 1),
- SeqCostItem(NamedDesc("EQ_Coll"), PerItemCost(JitCost(10), JitCost(2), 1), 1)
+ ast.SeqCostItem(NamedDesc("EQ_Coll"), PerItemCost(JitCost(10), JitCost(2), 1), 2),
+ ast.SeqCostItem(NamedDesc("EQ_Coll"), PerItemCost(JitCost(10), JitCost(2), 1), 1),
+ ast.SeqCostItem(NamedDesc("EQ_Coll"), PerItemCost(JitCost(10), JitCost(2), 1), 1)
)
verifyNeq(Coll(Coll((1, 10.toBigInt))), Coll(Coll((1, 11.toBigInt))), 1770, nestedNeq4, 1770)(cloneColl(_))
verifyNeq(Coll(Coll(Coll((1, 10.toBigInt)))), Coll(Coll(Coll((1, 11.toBigInt)))), 1771, nestedNeq5, 1771)(cloneColl(_))
@@ -2695,7 +2683,7 @@ class SigmaDslSpecification extends SigmaDslTesting
property("GroupElement.getEncoded equivalence") {
verifyCases(
{
- def success[T](v: T) = Expected(Success(v), 1790, methodCostDetails(SGroupElement.GetEncodedMethod, 250), 1790)
+ def success[T](v: T) = Expected(Success(v), 1790, methodCostDetails(SGroupElementMethods.GetEncodedMethod, 250), 1790)
Seq(
(ge1, success(Helpers.decodeBytes(ge1str))),
(ge2, success(Helpers.decodeBytes(ge2str))),
@@ -2710,7 +2698,7 @@ class SigmaDslSpecification extends SigmaDslTesting
"{ (x: GroupElement) => x.getEncoded }",
FuncValue(
Vector((1, SGroupElement)),
- MethodCall(ValUse(1, SGroupElement), SGroupElement.getMethodByName("getEncoded"), Vector(), Map())
+ MethodCall(ValUse(1, SGroupElement), SGroupElementMethods.getMethodByName("getEncoded"), Vector(), Map())
)))
}
@@ -2720,7 +2708,7 @@ class SigmaDslSpecification extends SigmaDslTesting
val costDetails = TracedCost(
traceBase ++ Array(
FixedCostItem(PropertyCall),
- FixedCostItem(MethodDesc(SGroupElement.GetEncodedMethod), FixedCost(JitCost(250))),
+ FixedCostItem(MethodDesc(SGroupElementMethods.GetEncodedMethod), FixedCost(JitCost(250))),
FixedCostItem(DecodePoint),
FixedCostItem(ValUse),
FixedCostItem(NamedDesc("EQ_GroupElement"), FixedCost(JitCost(172)))
@@ -2743,7 +2731,7 @@ class SigmaDslSpecification extends SigmaDslTesting
DecodePoint(
MethodCall.typed[Value[SCollection[SByte.type]]](
ValUse(1, SGroupElement),
- SGroupElement.getMethodByName("getEncoded"),
+ SGroupElementMethods.getMethodByName("getEncoded"),
Vector(),
Map()
)
@@ -2756,7 +2744,7 @@ class SigmaDslSpecification extends SigmaDslTesting
property("GroupElement.negate equivalence") {
verifyCases(
{
- def success[T](v: T) = Expected(Success(v), 1785, methodCostDetails(SGroupElement.NegateMethod, 45), 1785)
+ def success[T](v: T) = Expected(Success(v), 1785, methodCostDetails(SGroupElementMethods.NegateMethod, 45), 1785)
Seq(
(ge1, success(Helpers.decodeGroupElement("02358d53f01276211f92d0aefbd278805121d4ff6eb534b777af1ee8abae5b2056"))),
(ge2, success(Helpers.decodeGroupElement("03dba7b94b111f3894e2f9120b577da595ec7d58d488485adf73bf4e153af63575"))),
@@ -2769,7 +2757,7 @@ class SigmaDslSpecification extends SigmaDslTesting
"{ (x: GroupElement) => x.negate }",
FuncValue(
Vector((1, SGroupElement)),
- MethodCall(ValUse(1, SGroupElement), SGroupElement.getMethodByName("negate"), Vector(), Map())
+ MethodCall(ValUse(1, SGroupElement), SGroupElementMethods.getMethodByName("negate"), Vector(), Map())
)))
}
@@ -2822,7 +2810,7 @@ class SigmaDslSpecification extends SigmaDslTesting
FixedCostItem(MethodCall),
FixedCostItem(ValUse),
FixedCostItem(SelectField),
- FixedCostItem(SGroupElement.ExponentiateMethod, FixedCost(JitCost(900)))
+ FixedCostItem(SGroupElementMethods.ExponentiateMethod, FixedCost(JitCost(900)))
)
)
verifyCases(cases(1873, costDetails),
@@ -2836,7 +2824,7 @@ class SigmaDslSpecification extends SigmaDslTesting
ValUse(1, STuple(Vector(SGroupElement, SBigInt))),
1.toByte
),
- SGroupElement.getMethodByName("exp"),
+ SGroupElementMethods.getMethodByName("exp"),
Vector(
SelectField.typed[Value[SBigInt.type]](
ValUse(1, STuple(Vector(SGroupElement, SBigInt))),
@@ -2868,7 +2856,7 @@ class SigmaDslSpecification extends SigmaDslTesting
FixedCostItem(MethodCall),
FixedCostItem(ValUse),
FixedCostItem(SelectField),
- FixedCostItem(SGroupElement.MultiplyMethod, FixedCost(JitCost(40)))
+ FixedCostItem(SGroupElementMethods.MultiplyMethod, FixedCost(JitCost(40)))
)
)
)
@@ -2908,7 +2896,7 @@ class SigmaDslSpecification extends SigmaDslTesting
ValUse(1, SPair(SGroupElement, SGroupElement)),
1.toByte
),
- SGroupElement.getMethodByName("multiply"),
+ SGroupElementMethods.getMethodByName("multiply"),
Vector(
SelectField.typed[Value[SGroupElement.type]](
ValUse(1, SPair(SGroupElement, SGroupElement)),
@@ -2927,7 +2915,7 @@ class SigmaDslSpecification extends SigmaDslTesting
Vector((1, SAvlTree)),
MethodCall(
ValUse(1, SAvlTree),
- SAvlTree.getMethodByName(propName),
+ SAvlTreeMethods.getMethodByName(propName),
Vector(),
Map()
)
@@ -2935,7 +2923,7 @@ class SigmaDslSpecification extends SigmaDslTesting
}
verifyCases(
{
- def success[T](v: T) = Expected(Success(v), 1767, methodCostDetails(SAvlTree.digestMethod, 15), 1767)
+ def success[T](v: T) = Expected(Success(v), 1767, methodCostDetails(SAvlTreeMethods.digestMethod, 15), 1767)
Seq(
(t1, success(Helpers.decodeBytes("000183807f66b301530120ff7fc6bd6601ff01ff7f7d2bedbbffff00187fe89094"))),
(t2, success(Helpers.decodeBytes("ff000d937f80ffd731ed802d24358001ff8080ff71007f00ad37e0a7ae43fff95b"))),
@@ -2948,7 +2936,7 @@ class SigmaDslSpecification extends SigmaDslTesting
verifyCases(
{
- def success[T](v: T) = Expected(Success(v), 1765, methodCostDetails(SAvlTree.enabledOperationsMethod, 15), 1765)
+ def success[T](v: T) = Expected(Success(v), 1765, methodCostDetails(SAvlTreeMethods.enabledOperationsMethod, 15), 1765)
Seq(
(t1, success(6.toByte)),
(t2, success(0.toByte)),
@@ -2961,7 +2949,7 @@ class SigmaDslSpecification extends SigmaDslTesting
verifyCases(
{
- def success[T](v: T) = Expected(Success(v), 1765, methodCostDetails(SAvlTree.keyLengthMethod, 15), 1765)
+ def success[T](v: T) = Expected(Success(v), 1765, methodCostDetails(SAvlTreeMethods.keyLengthMethod, 15), 1765)
Seq(
(t1, success(1)),
(t2, success(32)),
@@ -2974,7 +2962,7 @@ class SigmaDslSpecification extends SigmaDslTesting
verifyCases(
{
- def success[T](v: T, newCost: Int) = Expected(Success(v), newCost, methodCostDetails(SAvlTree.valueLengthOptMethod, 15), newCost)
+ def success[T](v: T, newCost: Int) = Expected(Success(v), newCost, methodCostDetails(SAvlTreeMethods.valueLengthOptMethod, 15), newCost)
Seq(
(t1, success(Some(1), 1766)),
(t2, success(Some(64), 1766)),
@@ -2987,7 +2975,7 @@ class SigmaDslSpecification extends SigmaDslTesting
verifyCases(
{
- def success[T](v: T) = Expected(Success(v), 1765, methodCostDetails(SAvlTree.isInsertAllowedMethod, 15), 1765)
+ def success[T](v: T) = Expected(Success(v), 1765, methodCostDetails(SAvlTreeMethods.isInsertAllowedMethod, 15), 1765)
Seq(
(t1, success(false)),
(t2, success(false)),
@@ -3000,7 +2988,7 @@ class SigmaDslSpecification extends SigmaDslTesting
verifyCases(
{
- def success[T](v: T) = Expected(Success(v), 1765, methodCostDetails(SAvlTree.isUpdateAllowedMethod, 15), 1765)
+ def success[T](v: T) = Expected(Success(v), 1765, methodCostDetails(SAvlTreeMethods.isUpdateAllowedMethod, 15), 1765)
Seq(
(t1, success(true)),
(t2, success(false)),
@@ -3013,7 +3001,7 @@ class SigmaDslSpecification extends SigmaDslTesting
verifyCases(
{
- def success[T](v: T) = Expected(Success(v), 1765, methodCostDetails(SAvlTree.isRemoveAllowedMethod, 15), 1765)
+ def success[T](v: T) = Expected(Success(v), 1765, methodCostDetails(SAvlTreeMethods.isRemoveAllowedMethod, 15), 1765)
Seq(
(t1, success(true)),
(t2, success(false)),
@@ -3055,7 +3043,7 @@ class SigmaDslSpecification extends SigmaDslTesting
),
1.toByte
),
- SAvlTree.getMethodByName("contains"),
+ SAvlTreeMethods.getMethodByName("contains"),
Vector(
SelectField.typed[Value[SCollection[SByte.type]]](
ValUse(3, STuple(Vector(SCollectionType(SByte), SCollectionType(SByte)))),
@@ -3099,7 +3087,7 @@ class SigmaDslSpecification extends SigmaDslTesting
),
1.toByte
),
- SAvlTree.getMethodByName("get"),
+ SAvlTreeMethods.getMethodByName("get"),
Vector(
SelectField.typed[Value[SCollection[SByte.type]]](
ValUse(3, STuple(Vector(SCollectionType(SByte), SCollectionType(SByte)))),
@@ -3162,7 +3150,7 @@ class SigmaDslSpecification extends SigmaDslTesting
),
1.toByte
),
- SAvlTree.getMethodByName("getMany"),
+ SAvlTreeMethods.getMethodByName("getMany"),
Vector(
SelectField.typed[Value[SCollection[SCollection[SByte.type]]]](
ValUse(3, STuple(Vector(SCollectionType(SCollectionType(SByte)), SCollectionType(SByte)))),
@@ -3188,7 +3176,7 @@ class SigmaDslSpecification extends SigmaDslTesting
ValUse(1, STuple(Vector(SAvlTree, SCollectionType(SByte)))),
1.toByte
),
- SAvlTree.getMethodByName("updateDigest"),
+ SAvlTreeMethods.getMethodByName("updateDigest"),
Vector(
SelectField.typed[Value[SCollection[SByte.type]]](
ValUse(1, STuple(Vector(SAvlTree, SCollectionType(SByte)))),
@@ -3205,7 +3193,7 @@ class SigmaDslSpecification extends SigmaDslTesting
Vector((1, STuple(Vector(SAvlTree, SByte)))),
MethodCall.typed[Value[SAvlTree.type]](
SelectField.typed[Value[SAvlTree.type]](ValUse(1, STuple(Vector(SAvlTree, SByte))), 1.toByte),
- SAvlTree.getMethodByName("updateOperations"),
+ SAvlTreeMethods.getMethodByName("updateOperations"),
Vector(
SelectField.typed[Value[SByte.type]](ValUse(1, STuple(Vector(SAvlTree, SByte))), 2.toByte)
),
@@ -3248,7 +3236,7 @@ class SigmaDslSpecification extends SigmaDslTesting
FixedCostItem(GetVar),
FixedCostItem(OptionGet),
FixedCostItem(FuncValue.AddToEnvironmentDesc, FixedCost(JitCost(5))),
- SeqCostItem(CompanionDesc(BlockValue), PerItemCost(JitCost(1), JitCost(1), 10), 1),
+ ast.SeqCostItem(CompanionDesc(BlockValue), PerItemCost(JitCost(1), JitCost(1), 10), 1),
FixedCostItem(ValUse),
FixedCostItem(SelectField),
FixedCostItem(FuncValue.AddToEnvironmentDesc, FixedCost(JitCost(5))),
@@ -3259,12 +3247,12 @@ class SigmaDslSpecification extends SigmaDslTesting
FixedCostItem(SelectField),
FixedCostItem(ValUse),
FixedCostItem(SelectField),
- SeqCostItem(NamedDesc("CreateAvlVerifier"), PerItemCost(JitCost(110), JitCost(20), 64), 456),
- SeqCostItem(NamedDesc("LookupAvlTree"), PerItemCost(JitCost(40), JitCost(10), 1), 3),
- SeqCostItem(NamedDesc("LookupAvlTree"), PerItemCost(JitCost(40), JitCost(10), 1), 3),
- SeqCostItem(NamedDesc("LookupAvlTree"), PerItemCost(JitCost(40), JitCost(10), 1), 3),
- SeqCostItem(NamedDesc("LookupAvlTree"), PerItemCost(JitCost(40), JitCost(10), 1), 3),
- SeqCostItem(NamedDesc("LookupAvlTree"), PerItemCost(JitCost(40), JitCost(10), 1), 3)
+ ast.SeqCostItem(NamedDesc("CreateAvlVerifier"), PerItemCost(JitCost(110), JitCost(20), 64), 456),
+ ast.SeqCostItem(NamedDesc("LookupAvlTree"), PerItemCost(JitCost(40), JitCost(10), 1), 3),
+ ast.SeqCostItem(NamedDesc("LookupAvlTree"), PerItemCost(JitCost(40), JitCost(10), 1), 3),
+ ast.SeqCostItem(NamedDesc("LookupAvlTree"), PerItemCost(JitCost(40), JitCost(10), 1), 3),
+ ast.SeqCostItem(NamedDesc("LookupAvlTree"), PerItemCost(JitCost(40), JitCost(10), 1), 3),
+ ast.SeqCostItem(NamedDesc("LookupAvlTree"), PerItemCost(JitCost(40), JitCost(10), 1), 3)
)
)
@@ -3295,7 +3283,7 @@ class SigmaDslSpecification extends SigmaDslTesting
FixedCostItem(GetVar),
FixedCostItem(OptionGet),
FixedCostItem(FuncValue.AddToEnvironmentDesc, FixedCost(JitCost(5))),
- SeqCostItem(CompanionDesc(BlockValue), PerItemCost(JitCost(1), JitCost(1), 10), 1),
+ ast.SeqCostItem(CompanionDesc(BlockValue), PerItemCost(JitCost(1), JitCost(1), 10), 1),
FixedCostItem(ValUse),
FixedCostItem(SelectField),
FixedCostItem(FuncValue.AddToEnvironmentDesc, FixedCost(JitCost(5))),
@@ -3306,8 +3294,8 @@ class SigmaDslSpecification extends SigmaDslTesting
FixedCostItem(SelectField),
FixedCostItem(ValUse),
FixedCostItem(SelectField),
- SeqCostItem(NamedDesc("CreateAvlVerifier"), PerItemCost(JitCost(110), JitCost(20), 64), i),
- SeqCostItem(NamedDesc("LookupAvlTree"), PerItemCost(JitCost(40), JitCost(10), 1), 1)
+ ast.SeqCostItem(NamedDesc("CreateAvlVerifier"), PerItemCost(JitCost(110), JitCost(20), 64), i),
+ ast.SeqCostItem(NamedDesc("LookupAvlTree"), PerItemCost(JitCost(40), JitCost(10), 1), 1)
)
)
@@ -3323,7 +3311,7 @@ class SigmaDslSpecification extends SigmaDslTesting
FixedCostItem(MethodCall),
FixedCostItem(ValUse),
FixedCostItem(SelectField),
- FixedCostItem(SAvlTree.updateDigestMethod, FixedCost(JitCost(40)))
+ FixedCostItem(SAvlTreeMethods.updateDigestMethod, FixedCost(JitCost(40)))
)
)
@@ -3339,7 +3327,7 @@ class SigmaDslSpecification extends SigmaDslTesting
FixedCostItem(MethodCall),
FixedCostItem(ValUse),
FixedCostItem(SelectField),
- FixedCostItem(SAvlTree.updateOperationsMethod, FixedCost(JitCost(45)))
+ FixedCostItem(SAvlTreeMethods.updateOperationsMethod, FixedCost(JitCost(45)))
)
)
@@ -3473,7 +3461,7 @@ class SigmaDslSpecification extends SigmaDslTesting
),
1.toByte
),
- SAvlTree.getMethodByName("insert"),
+ SAvlTreeMethods.getMethodByName("insert"),
Vector(
SelectField.typed[Value[SCollection[STuple]]](
ValUse(
@@ -3501,7 +3489,7 @@ class SigmaDslSpecification extends SigmaDslTesting
FixedCostItem(GetVar),
FixedCostItem(OptionGet),
FixedCostItem(FuncValue.AddToEnvironmentDesc, FixedCost(JitCost(5))),
- SeqCostItem(CompanionDesc(BlockValue), PerItemCost(JitCost(1), JitCost(1), 10), 1),
+ ast.SeqCostItem(CompanionDesc(BlockValue), PerItemCost(JitCost(1), JitCost(1), 10), 1),
FixedCostItem(ValUse),
FixedCostItem(SelectField),
FixedCostItem(FuncValue.AddToEnvironmentDesc, FixedCost(JitCost(5))),
@@ -3512,14 +3500,14 @@ class SigmaDslSpecification extends SigmaDslTesting
FixedCostItem(SelectField),
FixedCostItem(ValUse),
FixedCostItem(SelectField),
- FixedCostItem(SAvlTree.isInsertAllowedMethod, FixedCost(JitCost(15)))
+ FixedCostItem(SAvlTreeMethods.isInsertAllowedMethod, FixedCost(JitCost(15)))
)
val costDetails1 = TracedCost(testTraceBase)
val costDetails2 = TracedCost(
testTraceBase ++ Array(
- SeqCostItem(NamedDesc("CreateAvlVerifier"), PerItemCost(JitCost(110), JitCost(20), 64), 70),
- SeqCostItem(NamedDesc("InsertIntoAvlTree"), PerItemCost(JitCost(40), JitCost(10), 1), 1),
- FixedCostItem(SAvlTree.updateDigestMethod, FixedCost(JitCost(40)))
+ ast.SeqCostItem(NamedDesc("CreateAvlVerifier"), PerItemCost(JitCost(110), JitCost(20), 64), 70),
+ ast.SeqCostItem(NamedDesc("InsertIntoAvlTree"), PerItemCost(JitCost(40), JitCost(10), 1), 1),
+ FixedCostItem(SAvlTreeMethods.updateDigestMethod, FixedCost(JitCost(40)))
)
)
@@ -3611,7 +3599,7 @@ class SigmaDslSpecification extends SigmaDslTesting
),
1.toByte
),
- SAvlTree.getMethodByName("update"),
+ SAvlTreeMethods.getMethodByName("update"),
Vector(
SelectField.typed[Value[SCollection[STuple]]](
ValUse(
@@ -3639,7 +3627,7 @@ class SigmaDslSpecification extends SigmaDslTesting
FixedCostItem(GetVar),
FixedCostItem(OptionGet),
FixedCostItem(FuncValue.AddToEnvironmentDesc, FixedCost(JitCost(5))),
- SeqCostItem(CompanionDesc(BlockValue), PerItemCost(JitCost(1), JitCost(1), 10), 1),
+ ast.SeqCostItem(CompanionDesc(BlockValue), PerItemCost(JitCost(1), JitCost(1), 10), 1),
FixedCostItem(ValUse),
FixedCostItem(SelectField),
FixedCostItem(FuncValue.AddToEnvironmentDesc, FixedCost(JitCost(5))),
@@ -3650,20 +3638,20 @@ class SigmaDslSpecification extends SigmaDslTesting
FixedCostItem(SelectField),
FixedCostItem(ValUse),
FixedCostItem(SelectField),
- FixedCostItem(SAvlTree.isUpdateAllowedMethod, FixedCost(JitCost(15)))
+ FixedCostItem(SAvlTreeMethods.isUpdateAllowedMethod, FixedCost(JitCost(15)))
)
val costDetails1 = TracedCost(testTraceBase)
val costDetails2 = TracedCost(
testTraceBase ++ Array(
- SeqCostItem(NamedDesc("CreateAvlVerifier"), PerItemCost(JitCost(110), JitCost(20), 64), 111),
- SeqCostItem(NamedDesc("UpdateAvlTree"), PerItemCost(JitCost(120), JitCost(20), 1), 1),
- FixedCostItem(SAvlTree.updateDigestMethod, FixedCost(JitCost(40)))
+ ast.SeqCostItem(NamedDesc("CreateAvlVerifier"), PerItemCost(JitCost(110), JitCost(20), 64), 111),
+ ast.SeqCostItem(NamedDesc("UpdateAvlTree"), PerItemCost(JitCost(120), JitCost(20), 1), 1),
+ FixedCostItem(SAvlTreeMethods.updateDigestMethod, FixedCost(JitCost(40)))
)
)
val costDetails3 = TracedCost(
testTraceBase ++ Array(
- SeqCostItem(NamedDesc("CreateAvlVerifier"), PerItemCost(JitCost(110), JitCost(20), 64), 111),
- SeqCostItem(NamedDesc("UpdateAvlTree"), PerItemCost(JitCost(120), JitCost(20), 1), 1)
+ ast.SeqCostItem(NamedDesc("CreateAvlVerifier"), PerItemCost(JitCost(110), JitCost(20), 64), 111),
+ ast.SeqCostItem(NamedDesc("UpdateAvlTree"), PerItemCost(JitCost(120), JitCost(20), 1), 1)
)
)
@@ -3746,7 +3734,7 @@ class SigmaDslSpecification extends SigmaDslTesting
ValUse(1, STuple(Vector(SAvlTree, STuple(Vector(SByteArray2, SByteArray))))),
1.toByte
),
- SAvlTree.getMethodByName("remove"),
+ SAvlTreeMethods.getMethodByName("remove"),
Vector(
SelectField.typed[Value[SCollection[SCollection[SByte.type]]]](
ValUse(3, STuple(Vector(SByteArray2, SByteArray))),
@@ -3768,7 +3756,7 @@ class SigmaDslSpecification extends SigmaDslTesting
FixedCostItem(GetVar),
FixedCostItem(OptionGet),
FixedCostItem(FuncValue.AddToEnvironmentDesc, FixedCost(JitCost(5))),
- SeqCostItem(CompanionDesc(BlockValue), PerItemCost(JitCost(1), JitCost(1), 10), 1),
+ ast.SeqCostItem(CompanionDesc(BlockValue), PerItemCost(JitCost(1), JitCost(1), 10), 1),
FixedCostItem(ValUse),
FixedCostItem(SelectField),
FixedCostItem(FuncValue.AddToEnvironmentDesc, FixedCost(JitCost(5))),
@@ -3779,31 +3767,31 @@ class SigmaDslSpecification extends SigmaDslTesting
FixedCostItem(SelectField),
FixedCostItem(ValUse),
FixedCostItem(SelectField),
- FixedCostItem(SAvlTree.isRemoveAllowedMethod, FixedCost(JitCost(15)))
+ FixedCostItem(SAvlTreeMethods.isRemoveAllowedMethod, FixedCost(JitCost(15)))
)
val costDetails1 = TracedCost(
testTraceBase ++ Array(
- SeqCostItem(NamedDesc("CreateAvlVerifier"), PerItemCost(JitCost(110), JitCost(20), 64), 436),
- SeqCostItem(NamedDesc("RemoveAvlTree"), PerItemCost(JitCost(100), JitCost(15), 1), 3),
- SeqCostItem(NamedDesc("RemoveAvlTree"), PerItemCost(JitCost(100), JitCost(15), 1), 3),
- FixedCostItem(SAvlTree.digestMethod, FixedCost(JitCost(15))),
- FixedCostItem(SAvlTree.updateDigestMethod, FixedCost(JitCost(40)))
+ ast.SeqCostItem(NamedDesc("CreateAvlVerifier"), PerItemCost(JitCost(110), JitCost(20), 64), 436),
+ ast.SeqCostItem(NamedDesc("RemoveAvlTree"), PerItemCost(JitCost(100), JitCost(15), 1), 3),
+ ast.SeqCostItem(NamedDesc("RemoveAvlTree"), PerItemCost(JitCost(100), JitCost(15), 1), 3),
+ FixedCostItem(SAvlTreeMethods.digestMethod, FixedCost(JitCost(15))),
+ FixedCostItem(SAvlTreeMethods.updateDigestMethod, FixedCost(JitCost(40)))
)
)
val costDetails2 = TracedCost(
testTraceBase ++ Array(
- SeqCostItem(NamedDesc("CreateAvlVerifier"), PerItemCost(JitCost(110), JitCost(20), 64), 140),
- SeqCostItem(NamedDesc("RemoveAvlTree"), PerItemCost(JitCost(100), JitCost(15), 1), 1),
- FixedCostItem(SAvlTree.digestMethod, FixedCost(JitCost(15))),
- FixedCostItem(SAvlTree.updateDigestMethod, FixedCost(JitCost(40)))
+ ast.SeqCostItem(NamedDesc("CreateAvlVerifier"), PerItemCost(JitCost(110), JitCost(20), 64), 140),
+ ast.SeqCostItem(NamedDesc("RemoveAvlTree"), PerItemCost(JitCost(100), JitCost(15), 1), 1),
+ FixedCostItem(SAvlTreeMethods.digestMethod, FixedCost(JitCost(15))),
+ FixedCostItem(SAvlTreeMethods.updateDigestMethod, FixedCost(JitCost(40)))
)
)
val costDetails3 = TracedCost(testTraceBase)
val costDetails4 = TracedCost(
testTraceBase ++ Array(
- SeqCostItem(NamedDesc("CreateAvlVerifier"), PerItemCost(JitCost(110), JitCost(20), 64), 140),
- SeqCostItem(NamedDesc("RemoveAvlTree"), PerItemCost(JitCost(100), JitCost(15), 1), 1),
- FixedCostItem(SAvlTree.digestMethod, FixedCost(JitCost(15)))
+ ast.SeqCostItem(NamedDesc("CreateAvlVerifier"), PerItemCost(JitCost(110), JitCost(20), 64), 140),
+ ast.SeqCostItem(NamedDesc("RemoveAvlTree"), PerItemCost(JitCost(100), JitCost(15), 1), 1),
+ FixedCostItem(SAvlTreeMethods.digestMethod, FixedCost(JitCost(15)))
)
)
@@ -4047,8 +4035,8 @@ class SigmaDslSpecification extends SigmaDslTesting
b1 -> Expected(Success(Coll[(Coll[Byte], Long)](
(Helpers.decodeBytes("6e789ab7b2fffff12280a6cd01557f6fb22b7f80ff7aff8e1f7f15973d7f0001"), 10000000L),
(Helpers.decodeBytes("a3ff007f00057600808001ff8f8000019000ffdb806fff7cc0b6015eb37fa600"), 500L)
- ).map(identity)), 1772, methodCostDetails(SBox.tokensMethod, 15), 1772),
- b2 -> Expected(Success(Coll[(Coll[Byte], Long)]().map(identity)), 1766, methodCostDetails(SBox.tokensMethod, 15), 1766)
+ ).map(identity)), 1772, methodCostDetails(SBoxMethods.tokensMethod, 15), 1772),
+ b2 -> Expected(Success(Coll[(Coll[Byte], Long)]().map(identity)), 1766, methodCostDetails(SBoxMethods.tokensMethod, 15), 1766)
),
existingFeature({ (x: Box) => x.tokens },
"{ (x: Box) => x.tokens }",
@@ -4056,7 +4044,7 @@ class SigmaDslSpecification extends SigmaDslTesting
Vector((1, SBox)),
MethodCall.typed[Value[SCollection[STuple]]](
ValUse(1, SBox),
- SBox.getMethodByName("tokens"),
+ SBoxMethods.getMethodByName("tokens"),
Vector(),
Map()
)
@@ -4096,7 +4084,7 @@ class SigmaDslSpecification extends SigmaDslTesting
FixedCostItem(GetVar),
FixedCostItem(OptionGet),
FixedCostItem(FuncValue.AddToEnvironmentDesc, FixedCost(JitCost(5))),
- SeqCostItem(CompanionDesc(BlockValue), PerItemCost(JitCost(1), JitCost(1), 10), 1),
+ ast.SeqCostItem(CompanionDesc(BlockValue), PerItemCost(JitCost(1), JitCost(1), 10), 1),
FixedCostItem(ValUse),
FixedCostItem(CompanionDesc(ExtractRegisterAs), FixedCost(JitCost(50))),
FixedCostItem(FuncValue.AddToEnvironmentDesc, FixedCost(JitCost(5))),
@@ -4114,7 +4102,7 @@ class SigmaDslSpecification extends SigmaDslTesting
FixedCostItem(GetVar),
FixedCostItem(OptionGet),
FixedCostItem(FuncValue.AddToEnvironmentDesc, FixedCost(JitCost(5))),
- SeqCostItem(CompanionDesc(BlockValue), PerItemCost(JitCost(1), JitCost(1), 10), 1),
+ ast.SeqCostItem(CompanionDesc(BlockValue), PerItemCost(JitCost(1), JitCost(1), 10), 1),
FixedCostItem(ValUse),
FixedCostItem(CompanionDesc(ExtractRegisterAs), FixedCost(JitCost(50))),
FixedCostItem(FuncValue.AddToEnvironmentDesc, FixedCost(JitCost(5))),
@@ -4169,14 +4157,14 @@ class SigmaDslSpecification extends SigmaDslTesting
FixedCostItem(GetVar),
FixedCostItem(OptionGet),
FixedCostItem(FuncValue.AddToEnvironmentDesc, FixedCost(JitCost(5))),
- SeqCostItem(CompanionDesc(BlockValue), PerItemCost(JitCost(1), JitCost(1), 10), 1),
+ ast.SeqCostItem(CompanionDesc(BlockValue), PerItemCost(JitCost(1), JitCost(1), 10), 1),
FixedCostItem(ValUse),
FixedCostItem(CompanionDesc(ExtractRegisterAs), FixedCost(JitCost(50))),
FixedCostItem(FuncValue.AddToEnvironmentDesc, FixedCost(JitCost(5))),
FixedCostItem(ValUse),
FixedCostItem(CompanionDesc(OptionIsDefined), FixedCost(JitCost(10))),
FixedCostItem(CompanionDesc(If), FixedCost(JitCost(10))),
- SeqCostItem(CompanionDesc(BlockValue), PerItemCost(JitCost(1), JitCost(1), 10), 1),
+ ast.SeqCostItem(CompanionDesc(BlockValue), PerItemCost(JitCost(1), JitCost(1), 10), 1),
FixedCostItem(ValUse),
FixedCostItem(OptionGet),
FixedCostItem(FuncValue.AddToEnvironmentDesc, FixedCost(JitCost(5))),
@@ -4198,14 +4186,14 @@ class SigmaDslSpecification extends SigmaDslTesting
FixedCostItem(GetVar),
FixedCostItem(OptionGet),
FixedCostItem(FuncValue.AddToEnvironmentDesc, FixedCost(JitCost(5))),
- SeqCostItem(CompanionDesc(BlockValue), PerItemCost(JitCost(1), JitCost(1), 10), 1),
+ ast.SeqCostItem(CompanionDesc(BlockValue), PerItemCost(JitCost(1), JitCost(1), 10), 1),
FixedCostItem(ValUse),
FixedCostItem(CompanionDesc(ExtractRegisterAs), FixedCost(JitCost(50))),
FixedCostItem(FuncValue.AddToEnvironmentDesc, FixedCost(JitCost(5))),
FixedCostItem(ValUse),
FixedCostItem(CompanionDesc(OptionIsDefined), FixedCost(JitCost(10))),
FixedCostItem(CompanionDesc(If), FixedCost(JitCost(10))),
- SeqCostItem(CompanionDesc(BlockValue), PerItemCost(JitCost(1), JitCost(1), 10), 1),
+ ast.SeqCostItem(CompanionDesc(BlockValue), PerItemCost(JitCost(1), JitCost(1), 10), 1),
FixedCostItem(ValUse),
FixedCostItem(OptionGet),
FixedCostItem(FuncValue.AddToEnvironmentDesc, FixedCost(JitCost(5))),
@@ -4230,14 +4218,14 @@ class SigmaDslSpecification extends SigmaDslTesting
FixedCostItem(GetVar),
FixedCostItem(OptionGet),
FixedCostItem(FuncValue.AddToEnvironmentDesc, FixedCost(JitCost(5))),
- SeqCostItem(CompanionDesc(BlockValue), PerItemCost(JitCost(1), JitCost(1), 10), 1),
+ ast.SeqCostItem(CompanionDesc(BlockValue), PerItemCost(JitCost(1), JitCost(1), 10), 1),
FixedCostItem(ValUse),
FixedCostItem(CompanionDesc(ExtractRegisterAs), FixedCost(JitCost(50))),
FixedCostItem(FuncValue.AddToEnvironmentDesc, FixedCost(JitCost(5))),
FixedCostItem(ValUse),
FixedCostItem(CompanionDesc(OptionIsDefined), FixedCost(JitCost(10))),
FixedCostItem(CompanionDesc(If), FixedCost(JitCost(10))),
- SeqCostItem(CompanionDesc(BlockValue), PerItemCost(JitCost(1), JitCost(1), 10), 1),
+ ast.SeqCostItem(CompanionDesc(BlockValue), PerItemCost(JitCost(1), JitCost(1), 10), 1),
FixedCostItem(ValUse),
FixedCostItem(OptionGet),
FixedCostItem(FuncValue.AddToEnvironmentDesc, FixedCost(JitCost(5))),
@@ -4481,11 +4469,11 @@ class SigmaDslSpecification extends SigmaDslTesting
val tA = RType[A]
val typeName = tA.name
val stypeA = Evaluation.rtypeToSType(tA)
- val typeCompanion = stypeA.asInstanceOf[STypeCompanion]
+ val m = MethodsContainer.getMethod(stypeA, propName).get
existingFeature(scalaFunc,
s"{ (x: $typeName) => x.$propName }",
FuncValue(Vector((1, stypeA)),
- MethodCall(ValUse(1, stypeA), typeCompanion.getMethodByName(propName), Vector(), Map() )
+ MethodCall(ValUse(1, stypeA), m, Vector(), Map() )
))
}
@@ -4493,35 +4481,35 @@ class SigmaDslSpecification extends SigmaDslTesting
verifyCases(
- Seq((preH1, Expected(Success(0.toByte), cost = 1765, methodCostDetails(SPreHeader.versionMethod, 10), 1765))),
+ Seq((preH1, Expected(Success(0.toByte), cost = 1765, methodCostDetails(SPreHeaderMethods.versionMethod, 10), 1765))),
existingPropTest("version", { (x: PreHeader) => x.version }))
verifyCases(
Seq((preH1, Expected(Success(
Helpers.decodeBytes("7fff7fdd6f62018bae0001006d9ca888ff7f56ff8006573700a167f17f2c9f40")),
- cost = 1766, methodCostDetails(SPreHeader.parentIdMethod, 10), 1766))),
+ cost = 1766, methodCostDetails(SPreHeaderMethods.parentIdMethod, 10), 1766))),
existingPropTest("parentId", { (x: PreHeader) => x.parentId }))
verifyCases(
- Seq((preH1, Expected(Success(6306290372572472443L), cost = 1765, methodCostDetails(SPreHeader.timestampMethod, 10), 1765))),
+ Seq((preH1, Expected(Success(6306290372572472443L), cost = 1765, methodCostDetails(SPreHeaderMethods.timestampMethod, 10), 1765))),
existingPropTest("timestamp", { (x: PreHeader) => x.timestamp }))
verifyCases(
- Seq((preH1, Expected(Success(-3683306095029417063L), cost = 1765, methodCostDetails(SPreHeader.nBitsMethod, 10), 1765))),
+ Seq((preH1, Expected(Success(-3683306095029417063L), cost = 1765, methodCostDetails(SPreHeaderMethods.nBitsMethod, 10), 1765))),
existingPropTest("nBits", { (x: PreHeader) => x.nBits }))
verifyCases(
- Seq((preH1, Expected(Success(1), cost = 1765, methodCostDetails(SPreHeader.heightMethod, 10), 1765))),
+ Seq((preH1, Expected(Success(1), cost = 1765, methodCostDetails(SPreHeaderMethods.heightMethod, 10), 1765))),
existingPropTest("height", { (x: PreHeader) => x.height }))
verifyCases(
Seq((preH1, Expected(Success(
Helpers.decodeGroupElement("026930cb9972e01534918a6f6d6b8e35bc398f57140d13eb3623ea31fbd069939b")),
- cost = 1782, methodCostDetails(SPreHeader.minerPkMethod, 10), 1782))),
+ cost = 1782, methodCostDetails(SPreHeaderMethods.minerPkMethod, 10), 1782))),
existingPropTest("minerPk", { (x: PreHeader) => x.minerPk }))
verifyCases(
- Seq((preH1, Expected(Success(Helpers.decodeBytes("ff8087")), cost = 1766, methodCostDetails(SPreHeader.votesMethod,10), 1766))),
+ Seq((preH1, Expected(Success(Helpers.decodeBytes("ff8087")), cost = 1766, methodCostDetails(SPreHeaderMethods.votesMethod,10), 1766))),
existingPropTest("votes", { (x: PreHeader) => x.votes }))
}
@@ -4529,90 +4517,90 @@ class SigmaDslSpecification extends SigmaDslTesting
verifyCases(
Seq((h1, Expected(Success(
Helpers.decodeBytes("957f008001808080ffe4ffffc8f3802401df40006aa05e017fa8d3f6004c804a")),
- cost = 1766, methodCostDetails(SHeader.idMethod, 10), 1766))),
+ cost = 1766, methodCostDetails(SHeaderMethods.idMethod, 10), 1766))),
existingPropTest("id", { (x: Header) => x.id }))
verifyCases(
- Seq((h1, Expected(Success(0.toByte), cost = 1765, methodCostDetails(SHeader.versionMethod, 10), 1765))),
+ Seq((h1, Expected(Success(0.toByte), cost = 1765, methodCostDetails(SHeaderMethods.versionMethod, 10), 1765))),
existingPropTest("version", { (x: Header) => x.version }))
verifyCases(
Seq((h1, Expected(Success(
Helpers.decodeBytes("0180dd805b0000ff5400b997fd7f0b9b00de00fb03c47e37806a8186b94f07ff")),
- cost = 1766, methodCostDetails(SHeader.parentIdMethod, 10), 1766))),
+ cost = 1766, methodCostDetails(SHeaderMethods.parentIdMethod, 10), 1766))),
existingPropTest("parentId", { (x: Header) => x.parentId }))
verifyCases(
Seq((h1, Expected(Success(
Helpers.decodeBytes("01f07f60d100ffb970c3007f60ff7f24d4070bb8fffa7fca7f34c10001ffe39d")),
- cost = 1766, methodCostDetails(SHeader.ADProofsRootMethod, 10), 1766))),
+ cost = 1766, methodCostDetails(SHeaderMethods.ADProofsRootMethod, 10), 1766))),
existingPropTest("ADProofsRoot", { (x: Header) => x.ADProofsRoot}))
verifyCases(
- Seq((h1, Expected(Success(CAvlTree(createAvlTreeData())), cost = 1765, methodCostDetails(SHeader.stateRootMethod, 10), 1765))),
+ Seq((h1, Expected(Success(CAvlTree(createAvlTreeData())), cost = 1765, methodCostDetails(SHeaderMethods.stateRootMethod, 10), 1765))),
existingPropTest("stateRoot", { (x: Header) => x.stateRoot }))
verifyCases(
Seq((h1, Expected(Success(
Helpers.decodeBytes("804101ff01000080a3ffbd006ac080098df132a7017f00649311ec0e00000100")),
- cost = 1766, methodCostDetails(SHeader.transactionsRootMethod, 10), 1766))),
+ cost = 1766, methodCostDetails(SHeaderMethods.transactionsRootMethod, 10), 1766))),
existingPropTest("transactionsRoot", { (x: Header) => x.transactionsRoot }))
verifyCases(
- Seq((h1, Expected(Success(1L), cost = 1765, methodCostDetails(SHeader.timestampMethod, 10), 1765))),
+ Seq((h1, Expected(Success(1L), cost = 1765, methodCostDetails(SHeaderMethods.timestampMethod, 10), 1765))),
existingPropTest("timestamp", { (x: Header) => x.timestamp }))
verifyCases(
- Seq((h1, Expected(Success(-1L), cost = 1765, methodCostDetails(SHeader.nBitsMethod, 10), 1765))),
+ Seq((h1, Expected(Success(-1L), cost = 1765, methodCostDetails(SHeaderMethods.nBitsMethod, 10), 1765))),
existingPropTest("nBits", { (x: Header) => x.nBits }))
verifyCases(
- Seq((h1, Expected(Success(1), cost = 1765, methodCostDetails(SHeader.heightMethod, 10), 1765))),
+ Seq((h1, Expected(Success(1), cost = 1765, methodCostDetails(SHeaderMethods.heightMethod, 10), 1765))),
existingPropTest("height", { (x: Header) => x.height }))
verifyCases(
Seq((h1, Expected(Success(
Helpers.decodeBytes("e57f80885601b8ff348e01808000bcfc767f2dd37f0d01015030ec018080bc62")),
- cost = 1766, methodCostDetails(SHeader.extensionRootMethod, 10), 1766))),
+ cost = 1766, methodCostDetails(SHeaderMethods.extensionRootMethod, 10), 1766))),
existingPropTest("extensionRoot", { (x: Header) => x.extensionRoot }))
verifyCases(
Seq((h1, Expected(Success(
Helpers.decodeGroupElement("039bdbfa0b49cc6bef58297a85feff45f7bbeb500a9d2283004c74fcedd4bd2904")),
- cost = 1782, methodCostDetails(SHeader.minerPkMethod, 10), 1782))),
+ cost = 1782, methodCostDetails(SHeaderMethods.minerPkMethod, 10), 1782))),
existingPropTest("minerPk", { (x: Header) => x.minerPk }))
verifyCases(
Seq((h1, Expected(Success(
Helpers.decodeGroupElement("0361299207fa392231e23666f6945ae3e867b978e021d8d702872bde454e9abe9c")),
- cost = 1782, methodCostDetails(SHeader.powOnetimePkMethod, 10), 1782))),
+ cost = 1782, methodCostDetails(SHeaderMethods.powOnetimePkMethod, 10), 1782))),
existingPropTest("powOnetimePk", { (x: Header) => x.powOnetimePk }))
verifyCases(
Seq((h1, Expected(Success(
Helpers.decodeBytes("7f4f09012a807f01")),
- cost = 1766, methodCostDetails(SHeader.powNonceMethod, 10), 1766))),
+ cost = 1766, methodCostDetails(SHeaderMethods.powNonceMethod, 10), 1766))),
existingPropTest("powNonce", { (x: Header) => x.powNonce }))
verifyCases(
Seq((h1, Expected(Success(
CBigInt(new BigInteger("-e24990c47e15ed4d0178c44f1790cc72155d516c43c3e8684e75db3800a288", 16))),
- cost = 1765, methodCostDetails(SHeader.powDistanceMethod, 10), 1765))),
+ cost = 1765, methodCostDetails(SHeaderMethods.powDistanceMethod, 10), 1765))),
existingPropTest("powDistance", { (x: Header) => x.powDistance }))
verifyCases(
Seq((h1, Expected(Success(
Helpers.decodeBytes("7f0180")),
- cost = 1766, methodCostDetails(SHeader.votesMethod, 10), 1766))),
+ cost = 1766, methodCostDetails(SHeaderMethods.votesMethod, 10), 1766))),
existingPropTest("votes", { (x: Header) => x.votes }))
}
def contextData() = {
- val input = CostingBox(
+ val input = CBox(
new ErgoBox(
80946L,
new ErgoTree(
- 16.toByte,
+ HeaderType @@ 16.toByte,
Vector(
SigmaPropConstant(
CSigmaProp(
@@ -4638,11 +4626,11 @@ class SigmaDslSpecification extends SigmaDslTesting
)
)
- val dataBox = CostingBox(
+ val dataBox = CBox(
new ErgoBox(
-1L,
new ErgoTree(
- 0.toByte,
+ HeaderType @@ 0.toByte,
Vector(),
Right(SigmaPropConstant(CSigmaProp(ProveDlog(Helpers.decodeECPoint("02af645874c3b53465a5e9d820eb207d6001258c3b708f0d31d7c2e342833dce64")))))
),
@@ -4690,7 +4678,7 @@ class SigmaDslSpecification extends SigmaDslTesting
Helpers.decodeBytes("01ff13")
)
- val ctx = CostingDataContext(
+ val ctx = CContext(
_dataInputs = Coll[Box](dataBox),
headers = Coll[Header](header),
preHeader = CPreHeader(
@@ -4704,11 +4692,11 @@ class SigmaDslSpecification extends SigmaDslTesting
),
inputs = Coll[Box](input),
outputs = Coll[Box](
- CostingBox(
+ CBox(
new ErgoBox(
1000000L,
new ErgoTree(
- 16.toByte,
+ HeaderType @@ 16.toByte,
Vector(
SigmaPropConstant(
CSigmaProp(
@@ -4741,11 +4729,11 @@ class SigmaDslSpecification extends SigmaDslTesting
11
)
),
- CostingBox(
+ CBox(
new ErgoBox(
2769336982721999022L,
new ErgoTree(
- 0.toByte,
+ HeaderType @@ 0.toByte,
Vector(),
Right(SigmaPropConstant(CSigmaProp(ProveDlog(Helpers.decodeECPoint("02d13e1a8c31f32194761adc1cdcbaa746b3e049e682bba9308d8ee84576172991")))))
),
@@ -4783,19 +4771,19 @@ class SigmaDslSpecification extends SigmaDslTesting
(input, dataBox, header, ctx, ctx2, ctx3)
}
- def ctxWithRegsInOutput(ctx: CostingDataContext, regs: AdditionalRegisters) = {
+ def ctxWithRegsInOutput(ctx: CContext, regs: AdditionalRegisters) = {
ctx.copy(
outputs = Coll({
- val box = ctx.outputs(0).asInstanceOf[CostingBox]
+ val box = ctx.outputs(0).asInstanceOf[CBox]
box.copy(ebox = copyBox(box.ebox)(additionalRegisters = regs))
})
)
}
- def ctxWithRegsInDataInput(ctx: CostingDataContext, regs: AdditionalRegisters) = {
+ def ctxWithRegsInDataInput(ctx: CContext, regs: AdditionalRegisters) = {
ctx.copy(
_dataInputs = Coll({
- val box = ctx.dataInputs(0).asInstanceOf[CostingBox]
+ val box = ctx.dataInputs(0).asInstanceOf[CBox]
box.copy(ebox = copyBox(box.ebox)(additionalRegisters = regs))
})
)
@@ -4809,7 +4797,7 @@ class SigmaDslSpecification extends SigmaDslTesting
val testTraceBase = traceBase ++ Array(
FixedCostItem(PropertyCall),
- FixedCostItem(SContext.dataInputsMethod, FixedCost(JitCost(15))),
+ FixedCostItem(SContextMethods.dataInputsMethod, FixedCost(JitCost(15))),
FixedCostItem(Constant),
FixedCostItem(ByIndex)
)
@@ -4827,7 +4815,7 @@ class SigmaDslSpecification extends SigmaDslTesting
ByIndex(
MethodCall.typed[Value[SCollection[SBox.type]]](
ValUse(1, SContext),
- SContext.getMethodByName("dataInputs"),
+ SContextMethods.getMethodByName("dataInputs"),
Vector(),
Map()
),
@@ -4852,7 +4840,7 @@ class SigmaDslSpecification extends SigmaDslTesting
ByIndex(
MethodCall.typed[Value[SCollection[SBox.type]]](
ValUse(1, SContext),
- SContext.getMethodByName("dataInputs"),
+ SContextMethods.getMethodByName("dataInputs"),
Vector(),
Map()
),
@@ -4919,7 +4907,7 @@ class SigmaDslSpecification extends SigmaDslTesting
FixedCostItem(FuncValue.AddToEnvironmentDesc, FixedCost(JitCost(5))),
FixedCostItem(Inputs),
FixedCostItem(FuncValue),
- SeqCostItem(CompanionDesc(MapCollection), PerItemCost(JitCost(20), JitCost(1), 10), 1),
+ ast.SeqCostItem(CompanionDesc(MapCollection), PerItemCost(JitCost(20), JitCost(1), 10), 1),
FixedCostItem(FuncValue.AddToEnvironmentDesc, FixedCost(JitCost(5))),
FixedCostItem(ValUse),
FixedCostItem(ExtractAmount)))
@@ -4933,7 +4921,7 @@ class SigmaDslSpecification extends SigmaDslTesting
FixedCostItem(Inputs),
FixedCostItem(MethodCall),
FixedCostItem(FuncValue),
- SeqCostItem(MethodDesc(SCollection.MapMethod), PerItemCost(JitCost(20), JitCost(1), 10), 1),
+ ast.SeqCostItem(MethodDesc(SCollectionMethods.MapMethod), PerItemCost(JitCost(20), JitCost(1), 10), 1),
FixedCostItem(FuncValue.AddToEnvironmentDesc, FixedCost(JitCost(5))),
FixedCostItem(ValUse),
FixedCostItem(ExtractAmount)
@@ -4954,7 +4942,7 @@ class SigmaDslSpecification extends SigmaDslTesting
Array((1, SContext)),
MethodCall.typed[Value[SCollection[SLong.type]]](
Inputs,
- SCollection.getMethodByName("map").withConcreteTypes(
+ SCollectionMethods.getMethodByName("map").withConcreteTypes(
Map(STypeVar("IV") -> SBox, STypeVar("OV") -> SLong)
),
Vector(FuncValue(Array((3, SBox)), ExtractAmount(ValUse(3, SBox)))),
@@ -4975,9 +4963,9 @@ class SigmaDslSpecification extends SigmaDslTesting
if (lowerMethodCallsInTests)
Array(
FixedCostItem(FuncValue),
- SeqCostItem(CompanionDesc(MapCollection), PerItemCost(JitCost(20), JitCost(1), 10), 1),
+ ast.SeqCostItem(CompanionDesc(MapCollection), PerItemCost(JitCost(20), JitCost(1), 10), 1),
FixedCostItem(FuncValue.AddToEnvironmentDesc, FixedCost(JitCost(5))),
- SeqCostItem(CompanionDesc(BlockValue), PerItemCost(JitCost(1), JitCost(1), 10), 1),
+ ast.SeqCostItem(CompanionDesc(BlockValue), PerItemCost(JitCost(1), JitCost(1), 10), 1),
FixedCostItem(ValUse),
FixedCostItem(ExtractAmount),
FixedCostItem(FuncValue.AddToEnvironmentDesc, FixedCost(JitCost(5))),
@@ -4988,9 +4976,9 @@ class SigmaDslSpecification extends SigmaDslTesting
Array(
FixedCostItem(MethodCall),
FixedCostItem(FuncValue),
- SeqCostItem(MethodDesc(SCollection.MapMethod), PerItemCost(JitCost(20), JitCost(1), 10), 1),
+ ast.SeqCostItem(MethodDesc(SCollectionMethods.MapMethod), PerItemCost(JitCost(20), JitCost(1), 10), 1),
FixedCostItem(FuncValue.AddToEnvironmentDesc, FixedCost(JitCost(5))),
- SeqCostItem(CompanionDesc(BlockValue), PerItemCost(JitCost(1), JitCost(1), 10), 1),
+ ast.SeqCostItem(CompanionDesc(BlockValue), PerItemCost(JitCost(1), JitCost(1), 10), 1),
FixedCostItem(ValUse),
FixedCostItem(ExtractAmount),
FixedCostItem(FuncValue.AddToEnvironmentDesc, FixedCost(JitCost(5))),
@@ -5025,7 +5013,7 @@ class SigmaDslSpecification extends SigmaDslTesting
Array((1, SContext)),
MethodCall.typed[Value[SCollection[STuple]]](
Inputs,
- SCollection.getMethodByName("map").withConcreteTypes(
+ SCollectionMethods.getMethodByName("map").withConcreteTypes(
Map(STypeVar("IV") -> SBox, STypeVar("OV") -> SPair(SLong, SLong))
),
Vector(
@@ -5082,7 +5070,7 @@ class SigmaDslSpecification extends SigmaDslTesting
val selfCostDetails = TracedCost(
traceBase ++ Array(
FixedCostItem(PropertyCall),
- FixedCostItem(SContext.selfBoxIndexMethod, FixedCost(JitCost(20)))
+ FixedCostItem(SContextMethods.selfBoxIndexMethod, FixedCost(JitCost(20)))
)
)
verifyCases(
@@ -5103,7 +5091,7 @@ class SigmaDslSpecification extends SigmaDslTesting
Vector((1, SContext)),
MethodCall.typed[Value[SInt.type]](
ValUse(1, SContext),
- SContext.getMethodByName("selfBoxIndex"),
+ SContextMethods.getMethodByName("selfBoxIndex"),
Vector(),
Map()
)
@@ -5122,16 +5110,16 @@ class SigmaDslSpecification extends SigmaDslTesting
}
verifyCases(
- Seq(ctx -> Expected(Success(ctx.LastBlockUtxoRootHash), cost = 1766, methodCostDetails(SContext.lastBlockUtxoRootHashMethod, 15), 1766)),
+ Seq(ctx -> Expected(Success(ctx.LastBlockUtxoRootHash), cost = 1766, methodCostDetails(SContextMethods.lastBlockUtxoRootHashMethod, 15), 1766)),
existingPropTest("LastBlockUtxoRootHash", { (x: Context) => x.LastBlockUtxoRootHash }),
preGeneratedSamples = Some(samples))
val isUpdateAllowedCostDetails = TracedCost(
traceBase ++ Array(
FixedCostItem(PropertyCall),
- FixedCostItem(SContext.lastBlockUtxoRootHashMethod, FixedCost(JitCost(15))),
+ FixedCostItem(SContextMethods.lastBlockUtxoRootHashMethod, FixedCost(JitCost(15))),
FixedCostItem(PropertyCall),
- FixedCostItem(SAvlTree.isUpdateAllowedMethod, FixedCost(JitCost(15)))
+ FixedCostItem(SAvlTreeMethods.isUpdateAllowedMethod, FixedCost(JitCost(15)))
)
)
verifyCases(
@@ -5144,11 +5132,11 @@ class SigmaDslSpecification extends SigmaDslTesting
MethodCall.typed[Value[SBoolean.type]](
MethodCall.typed[Value[SAvlTree.type]](
ValUse(1, SContext),
- SContext.getMethodByName("LastBlockUtxoRootHash"),
+ SContextMethods.getMethodByName("LastBlockUtxoRootHash"),
Vector(),
Map()
),
- SAvlTree.getMethodByName("isUpdateAllowed"),
+ SAvlTreeMethods.getMethodByName("isUpdateAllowed"),
Vector(),
Map()
)
@@ -5156,7 +5144,7 @@ class SigmaDslSpecification extends SigmaDslTesting
preGeneratedSamples = Some(samples))
verifyCases(
- Seq(ctx -> Expected(Success(ctx.minerPubKey), cost = 1767, methodCostDetails(SContext.minerPubKeyMethod, 20), 1767)),
+ Seq(ctx -> Expected(Success(ctx.minerPubKey), cost = 1767, methodCostDetails(SContextMethods.minerPubKeyMethod, 20), 1767)),
existingPropTest("minerPubKey", { (x: Context) => x.minerPubKey }),
preGeneratedSamples = Some(samples))
@@ -5213,10 +5201,10 @@ class SigmaDslSpecification extends SigmaDslTesting
FixedCostItem(GetVar),
FixedCostItem(OptionGet),
FixedCostItem(FuncValue.AddToEnvironmentDesc, FixedCost(JitCost(5))),
- SeqCostItem(CompanionDesc(BlockValue), PerItemCost(JitCost(1), JitCost(1), 10), 1),
+ ast.SeqCostItem(CompanionDesc(BlockValue), PerItemCost(JitCost(1), JitCost(1), 10), 1),
FixedCostItem(ValUse),
FixedCostItem(PropertyCall),
- FixedCostItem(SContext.dataInputsMethod, FixedCost(JitCost(15))),
+ FixedCostItem(SContextMethods.dataInputsMethod, FixedCost(JitCost(15))),
FixedCostItem(Constant),
FixedCostItem(ByIndex),
FixedCostItem(ExtractRegisterAs),
@@ -5260,7 +5248,7 @@ class SigmaDslSpecification extends SigmaDslTesting
ByIndex(
MethodCall.typed[Value[SCollection[SBox.type]]](
ValUse(1, SContext),
- SContext.getMethodByName("dataInputs"),
+ SContextMethods.getMethodByName("dataInputs"),
Vector(),
Map()
),
@@ -5332,7 +5320,7 @@ class SigmaDslSpecification extends SigmaDslTesting
ByIndex(
MethodCall.typed[Value[SCollection[SBox.type]]](
ValUse(1, SContext),
- SContext.getMethodByName("dataInputs"),
+ SContextMethods.getMethodByName("dataInputs"),
Vector(),
Map()
),
@@ -5374,7 +5362,7 @@ class SigmaDslSpecification extends SigmaDslTesting
FixedCostItem(GetVar),
FixedCostItem(OptionGet),
FixedCostItem(FuncValue.AddToEnvironmentDesc, FixedCost(JitCost(5))),
- SeqCostItem(CompanionDesc(BlockValue), PerItemCost(JitCost(1), JitCost(1), 10), 2),
+ ast.SeqCostItem(CompanionDesc(BlockValue), PerItemCost(JitCost(1), JitCost(1), 10), 2),
FixedCostItem(Outputs),
FixedCostItem(Constant),
FixedCostItem(ByIndex),
@@ -5385,7 +5373,7 @@ class SigmaDslSpecification extends SigmaDslTesting
FixedCostItem(ValUse),
FixedCostItem(OptionIsDefined),
FixedCostItem(If),
- SeqCostItem(CompanionDesc(BlockValue), PerItemCost(JitCost(1), JitCost(1), 10), 1),
+ ast.SeqCostItem(CompanionDesc(BlockValue), PerItemCost(JitCost(1), JitCost(1), 10), 1),
FixedCostItem(ValUse),
FixedCostItem(OptionGet),
FixedCostItem(FuncValue.AddToEnvironmentDesc, FixedCost(JitCost(5))),
@@ -5409,7 +5397,7 @@ class SigmaDslSpecification extends SigmaDslTesting
FixedCostItem(GetVar),
FixedCostItem(OptionGet),
FixedCostItem(FuncValue.AddToEnvironmentDesc, FixedCost(JitCost(5))),
- SeqCostItem(CompanionDesc(BlockValue), PerItemCost(JitCost(1), JitCost(1), 10), 2),
+ ast.SeqCostItem(CompanionDesc(BlockValue), PerItemCost(JitCost(1), JitCost(1), 10), 2),
FixedCostItem(Outputs),
FixedCostItem(Constant),
FixedCostItem(ByIndex),
@@ -5420,7 +5408,7 @@ class SigmaDslSpecification extends SigmaDslTesting
FixedCostItem(ValUse),
FixedCostItem(OptionIsDefined),
FixedCostItem(If),
- SeqCostItem(CompanionDesc(BlockValue), PerItemCost(JitCost(1), JitCost(1), 10), 1),
+ ast.SeqCostItem(CompanionDesc(BlockValue), PerItemCost(JitCost(1), JitCost(1), 10), 1),
FixedCostItem(ValUse),
FixedCostItem(OptionGet),
FixedCostItem(FuncValue.AddToEnvironmentDesc, FixedCost(JitCost(5))),
@@ -5442,7 +5430,7 @@ class SigmaDslSpecification extends SigmaDslTesting
FixedCostItem(GetVar),
FixedCostItem(OptionGet),
FixedCostItem(FuncValue.AddToEnvironmentDesc, FixedCost(JitCost(5))),
- SeqCostItem(CompanionDesc(BlockValue), PerItemCost(JitCost(1), JitCost(1), 10), 2),
+ ast.SeqCostItem(CompanionDesc(BlockValue), PerItemCost(JitCost(1), JitCost(1), 10), 2),
FixedCostItem(Outputs),
FixedCostItem(Constant),
FixedCostItem(ByIndex),
@@ -5543,7 +5531,7 @@ class SigmaDslSpecification extends SigmaDslTesting
FixedCostItem(GetVar),
FixedCostItem(OptionGet),
FixedCostItem(FuncValue.AddToEnvironmentDesc, FixedCost(JitCost(5))),
- SeqCostItem(CompanionDesc(BlockValue), PerItemCost(JitCost(1), JitCost(1), 10), 2),
+ ast.SeqCostItem(CompanionDesc(BlockValue), PerItemCost(JitCost(1), JitCost(1), 10), 2),
FixedCostItem(Outputs),
FixedCostItem(Constant),
FixedCostItem(ByIndex),
@@ -5554,7 +5542,7 @@ class SigmaDslSpecification extends SigmaDslTesting
FixedCostItem(ValUse),
FixedCostItem(OptionIsDefined),
FixedCostItem(If),
- SeqCostItem(CompanionDesc(BlockValue), PerItemCost(JitCost(1), JitCost(1), 10), 1),
+ ast.SeqCostItem(CompanionDesc(BlockValue), PerItemCost(JitCost(1), JitCost(1), 10), 1),
FixedCostItem(ValUse),
FixedCostItem(OptionGet),
FixedCostItem(FuncValue.AddToEnvironmentDesc, FixedCost(JitCost(5))),
@@ -5581,7 +5569,7 @@ class SigmaDslSpecification extends SigmaDslTesting
FixedCostItem(GetVar),
FixedCostItem(OptionGet),
FixedCostItem(FuncValue.AddToEnvironmentDesc, FixedCost(JitCost(5))),
- SeqCostItem(CompanionDesc(BlockValue), PerItemCost(JitCost(1), JitCost(1), 10), 2),
+ ast.SeqCostItem(CompanionDesc(BlockValue), PerItemCost(JitCost(1), JitCost(1), 10), 2),
FixedCostItem(Outputs),
FixedCostItem(Constant),
FixedCostItem(ByIndex),
@@ -5592,7 +5580,7 @@ class SigmaDslSpecification extends SigmaDslTesting
FixedCostItem(ValUse),
FixedCostItem(OptionIsDefined),
FixedCostItem(If),
- SeqCostItem(CompanionDesc(BlockValue), PerItemCost(JitCost(1), JitCost(1), 10), 1),
+ ast.SeqCostItem(CompanionDesc(BlockValue), PerItemCost(JitCost(1), JitCost(1), 10), 1),
FixedCostItem(ValUse),
FixedCostItem(OptionGet),
FixedCostItem(FuncValue.AddToEnvironmentDesc, FixedCost(JitCost(5))),
@@ -5616,7 +5604,7 @@ class SigmaDslSpecification extends SigmaDslTesting
FixedCostItem(GetVar),
FixedCostItem(OptionGet),
FixedCostItem(FuncValue.AddToEnvironmentDesc, FixedCost(JitCost(5))),
- SeqCostItem(CompanionDesc(BlockValue), PerItemCost(JitCost(1), JitCost(1), 10), 2),
+ ast.SeqCostItem(CompanionDesc(BlockValue), PerItemCost(JitCost(1), JitCost(1), 10), 2),
FixedCostItem(Outputs),
FixedCostItem(Constant),
FixedCostItem(ByIndex),
@@ -5627,7 +5615,7 @@ class SigmaDslSpecification extends SigmaDslTesting
FixedCostItem(ValUse),
FixedCostItem(OptionIsDefined),
FixedCostItem(If),
- SeqCostItem(CompanionDesc(BlockValue), PerItemCost(JitCost(1), JitCost(1), 10), 1),
+ ast.SeqCostItem(CompanionDesc(BlockValue), PerItemCost(JitCost(1), JitCost(1), 10), 1),
FixedCostItem(ValUse),
FixedCostItem(OptionGet),
FixedCostItem(FuncValue.AddToEnvironmentDesc, FixedCost(JitCost(5))),
@@ -5649,7 +5637,7 @@ class SigmaDslSpecification extends SigmaDslTesting
FixedCostItem(GetVar),
FixedCostItem(OptionGet),
FixedCostItem(FuncValue.AddToEnvironmentDesc, FixedCost(JitCost(5))),
- SeqCostItem(CompanionDesc(BlockValue), PerItemCost(JitCost(1), JitCost(1), 10), 2),
+ ast.SeqCostItem(CompanionDesc(BlockValue), PerItemCost(JitCost(1), JitCost(1), 10), 2),
FixedCostItem(Outputs),
FixedCostItem(Constant),
FixedCostItem(ByIndex),
@@ -5772,10 +5760,10 @@ class SigmaDslSpecification extends SigmaDslTesting
FixedCostItem(GetVar),
FixedCostItem(OptionGet),
FixedCostItem(FuncValue.AddToEnvironmentDesc, FixedCost(JitCost(5))),
- SeqCostItem(CompanionDesc(BlockValue), PerItemCost(JitCost(1), JitCost(1), 10), 2),
+ ast.SeqCostItem(CompanionDesc(BlockValue), PerItemCost(JitCost(1), JitCost(1), 10), 2),
FixedCostItem(ValUse),
FixedCostItem(PropertyCall),
- FixedCostItem(SContext.dataInputsMethod, FixedCost(JitCost(15))),
+ FixedCostItem(SContextMethods.dataInputsMethod, FixedCost(JitCost(15))),
FixedCostItem(Constant),
FixedCostItem(ByIndex),
FixedCostItem(FuncValue.AddToEnvironmentDesc, FixedCost(JitCost(5))),
@@ -5785,7 +5773,7 @@ class SigmaDslSpecification extends SigmaDslTesting
FixedCostItem(ValUse),
FixedCostItem(OptionIsDefined),
FixedCostItem(If),
- SeqCostItem(CompanionDesc(BlockValue), PerItemCost(JitCost(1), JitCost(1), 10), 1),
+ ast.SeqCostItem(CompanionDesc(BlockValue), PerItemCost(JitCost(1), JitCost(1), 10), 1),
FixedCostItem(ValUse),
FixedCostItem(OptionGet),
FixedCostItem(FuncValue.AddToEnvironmentDesc, FixedCost(JitCost(5))),
@@ -5809,10 +5797,10 @@ class SigmaDslSpecification extends SigmaDslTesting
FixedCostItem(GetVar),
FixedCostItem(OptionGet),
FixedCostItem(FuncValue.AddToEnvironmentDesc, FixedCost(JitCost(5))),
- SeqCostItem(CompanionDesc(BlockValue), PerItemCost(JitCost(1), JitCost(1), 10), 2),
+ ast.SeqCostItem(CompanionDesc(BlockValue), PerItemCost(JitCost(1), JitCost(1), 10), 2),
FixedCostItem(ValUse),
FixedCostItem(PropertyCall),
- FixedCostItem(SContext.dataInputsMethod, FixedCost(JitCost(15))),
+ FixedCostItem(SContextMethods.dataInputsMethod, FixedCost(JitCost(15))),
FixedCostItem(Constant),
FixedCostItem(ByIndex),
FixedCostItem(FuncValue.AddToEnvironmentDesc, FixedCost(JitCost(5))),
@@ -5822,7 +5810,7 @@ class SigmaDslSpecification extends SigmaDslTesting
FixedCostItem(ValUse),
FixedCostItem(OptionIsDefined),
FixedCostItem(If),
- SeqCostItem(CompanionDesc(BlockValue), PerItemCost(JitCost(1), JitCost(1), 10), 1),
+ ast.SeqCostItem(CompanionDesc(BlockValue), PerItemCost(JitCost(1), JitCost(1), 10), 1),
FixedCostItem(ValUse),
FixedCostItem(OptionGet),
FixedCostItem(FuncValue.AddToEnvironmentDesc, FixedCost(JitCost(5))),
@@ -5843,10 +5831,10 @@ class SigmaDslSpecification extends SigmaDslTesting
FixedCostItem(GetVar),
FixedCostItem(OptionGet),
FixedCostItem(FuncValue.AddToEnvironmentDesc, FixedCost(JitCost(5))),
- SeqCostItem(CompanionDesc(BlockValue), PerItemCost(JitCost(1), JitCost(1), 10), 2),
+ ast.SeqCostItem(CompanionDesc(BlockValue), PerItemCost(JitCost(1), JitCost(1), 10), 2),
FixedCostItem(ValUse),
FixedCostItem(PropertyCall),
- FixedCostItem(SContext.dataInputsMethod, FixedCost(JitCost(15))),
+ FixedCostItem(SContextMethods.dataInputsMethod, FixedCost(JitCost(15))),
FixedCostItem(Constant),
FixedCostItem(ByIndex),
FixedCostItem(FuncValue.AddToEnvironmentDesc, FixedCost(JitCost(5))),
@@ -5856,7 +5844,7 @@ class SigmaDslSpecification extends SigmaDslTesting
FixedCostItem(ValUse),
FixedCostItem(OptionIsDefined),
FixedCostItem(If),
- SeqCostItem(CompanionDesc(BlockValue), PerItemCost(JitCost(1), JitCost(1), 10), 1),
+ ast.SeqCostItem(CompanionDesc(BlockValue), PerItemCost(JitCost(1), JitCost(1), 10), 1),
FixedCostItem(ValUse),
FixedCostItem(OptionGet),
FixedCostItem(FuncValue.AddToEnvironmentDesc, FixedCost(JitCost(5))),
@@ -5878,10 +5866,10 @@ class SigmaDslSpecification extends SigmaDslTesting
FixedCostItem(GetVar),
FixedCostItem(OptionGet),
FixedCostItem(FuncValue.AddToEnvironmentDesc, FixedCost(JitCost(5))),
- SeqCostItem(CompanionDesc(BlockValue), PerItemCost(JitCost(1), JitCost(1), 10), 2),
+ ast.SeqCostItem(CompanionDesc(BlockValue), PerItemCost(JitCost(1), JitCost(1), 10), 2),
FixedCostItem(ValUse),
FixedCostItem(PropertyCall),
- FixedCostItem(SContext.dataInputsMethod, FixedCost(JitCost(15))),
+ FixedCostItem(SContextMethods.dataInputsMethod, FixedCost(JitCost(15))),
FixedCostItem(Constant),
FixedCostItem(ByIndex),
FixedCostItem(FuncValue.AddToEnvironmentDesc, FixedCost(JitCost(5))),
@@ -5959,7 +5947,7 @@ class SigmaDslSpecification extends SigmaDslTesting
ByIndex(
MethodCall.typed[Value[SCollection[SBox.type]]](
ValUse(1, SContext),
- SContext.getMethodByName("dataInputs"),
+ SContextMethods.getMethodByName("dataInputs"),
Vector(),
Map()
),
@@ -6000,10 +5988,10 @@ class SigmaDslSpecification extends SigmaDslTesting
FixedCostItem(GetVar),
FixedCostItem(OptionGet),
FixedCostItem(FuncValue.AddToEnvironmentDesc, FixedCost(JitCost(5))),
- SeqCostItem(CompanionDesc(BlockValue), PerItemCost(JitCost(1), JitCost(1), 10), 2),
+ ast.SeqCostItem(CompanionDesc(BlockValue), PerItemCost(JitCost(1), JitCost(1), 10), 2),
FixedCostItem(ValUse),
FixedCostItem(PropertyCall),
- FixedCostItem(SContext.dataInputsMethod, FixedCost(JitCost(15))),
+ FixedCostItem(SContextMethods.dataInputsMethod, FixedCost(JitCost(15))),
FixedCostItem(Constant),
FixedCostItem(ByIndex),
FixedCostItem(FuncValue.AddToEnvironmentDesc, FixedCost(JitCost(5))),
@@ -6013,7 +6001,7 @@ class SigmaDslSpecification extends SigmaDslTesting
FixedCostItem(ValUse),
FixedCostItem(OptionIsDefined),
FixedCostItem(If),
- SeqCostItem(CompanionDesc(BlockValue), PerItemCost(JitCost(1), JitCost(1), 10), 1),
+ ast.SeqCostItem(CompanionDesc(BlockValue), PerItemCost(JitCost(1), JitCost(1), 10), 1),
FixedCostItem(ValUse),
FixedCostItem(OptionGet),
FixedCostItem(FuncValue.AddToEnvironmentDesc, FixedCost(JitCost(5))),
@@ -6040,10 +6028,10 @@ class SigmaDslSpecification extends SigmaDslTesting
FixedCostItem(GetVar),
FixedCostItem(OptionGet),
FixedCostItem(FuncValue.AddToEnvironmentDesc, FixedCost(JitCost(5))),
- SeqCostItem(CompanionDesc(BlockValue), PerItemCost(JitCost(1), JitCost(1), 10), 2),
+ ast.SeqCostItem(CompanionDesc(BlockValue), PerItemCost(JitCost(1), JitCost(1), 10), 2),
FixedCostItem(ValUse),
FixedCostItem(PropertyCall),
- FixedCostItem(SContext.dataInputsMethod, FixedCost(JitCost(15))),
+ FixedCostItem(SContextMethods.dataInputsMethod, FixedCost(JitCost(15))),
FixedCostItem(Constant),
FixedCostItem(ByIndex),
FixedCostItem(FuncValue.AddToEnvironmentDesc, FixedCost(JitCost(5))),
@@ -6053,7 +6041,7 @@ class SigmaDslSpecification extends SigmaDslTesting
FixedCostItem(ValUse),
FixedCostItem(OptionIsDefined),
FixedCostItem(If),
- SeqCostItem(CompanionDesc(BlockValue), PerItemCost(JitCost(1), JitCost(1), 10), 1),
+ ast.SeqCostItem(CompanionDesc(BlockValue), PerItemCost(JitCost(1), JitCost(1), 10), 1),
FixedCostItem(ValUse),
FixedCostItem(OptionGet),
FixedCostItem(FuncValue.AddToEnvironmentDesc, FixedCost(JitCost(5))),
@@ -6077,10 +6065,10 @@ class SigmaDslSpecification extends SigmaDslTesting
FixedCostItem(GetVar),
FixedCostItem(OptionGet),
FixedCostItem(FuncValue.AddToEnvironmentDesc, FixedCost(JitCost(5))),
- SeqCostItem(CompanionDesc(BlockValue), PerItemCost(JitCost(1), JitCost(1), 10), 2),
+ ast.SeqCostItem(CompanionDesc(BlockValue), PerItemCost(JitCost(1), JitCost(1), 10), 2),
FixedCostItem(ValUse),
FixedCostItem(PropertyCall),
- FixedCostItem(SContext.dataInputsMethod, FixedCost(JitCost(15))),
+ FixedCostItem(SContextMethods.dataInputsMethod, FixedCost(JitCost(15))),
FixedCostItem(Constant),
FixedCostItem(ByIndex),
FixedCostItem(FuncValue.AddToEnvironmentDesc, FixedCost(JitCost(5))),
@@ -6090,7 +6078,7 @@ class SigmaDslSpecification extends SigmaDslTesting
FixedCostItem(ValUse),
FixedCostItem(OptionIsDefined),
FixedCostItem(If),
- SeqCostItem(CompanionDesc(BlockValue), PerItemCost(JitCost(1), JitCost(1), 10), 1),
+ ast.SeqCostItem(CompanionDesc(BlockValue), PerItemCost(JitCost(1), JitCost(1), 10), 1),
FixedCostItem(ValUse),
FixedCostItem(OptionGet),
FixedCostItem(FuncValue.AddToEnvironmentDesc, FixedCost(JitCost(5))),
@@ -6112,10 +6100,10 @@ class SigmaDslSpecification extends SigmaDslTesting
FixedCostItem(GetVar),
FixedCostItem(OptionGet),
FixedCostItem(FuncValue.AddToEnvironmentDesc, FixedCost(JitCost(5))),
- SeqCostItem(CompanionDesc(BlockValue), PerItemCost(JitCost(1), JitCost(1), 10), 2),
+ ast.SeqCostItem(CompanionDesc(BlockValue), PerItemCost(JitCost(1), JitCost(1), 10), 2),
FixedCostItem(ValUse),
FixedCostItem(PropertyCall),
- FixedCostItem(SContext.dataInputsMethod, FixedCost(JitCost(15))),
+ FixedCostItem(SContextMethods.dataInputsMethod, FixedCost(JitCost(15))),
FixedCostItem(Constant),
FixedCostItem(ByIndex),
FixedCostItem(FuncValue.AddToEnvironmentDesc, FixedCost(JitCost(5))),
@@ -6192,7 +6180,7 @@ class SigmaDslSpecification extends SigmaDslTesting
ByIndex(
MethodCall.typed[Value[SCollection[SBox.type]]](
ValUse(1, SContext),
- SContext.getMethodByName("dataInputs"),
+ SContextMethods.getMethodByName("dataInputs"),
Vector(),
Map()
),
@@ -6237,7 +6225,7 @@ class SigmaDslSpecification extends SigmaDslTesting
}
property("xorOf equivalence") {
- def costDetails(i: Int) = TracedCost(traceBase :+ SeqCostItem(CompanionDesc(XorOf), PerItemCost(JitCost(20), JitCost(5), 32), i))
+ def costDetails(i: Int) = TracedCost(traceBase :+ ast.SeqCostItem(CompanionDesc(XorOf), PerItemCost(JitCost(20), JitCost(5), 32), i))
verifyCases(
{
def successNew[T](v: T, c: Int, newV: T, cd: CostDetails) = Expected(
@@ -6395,7 +6383,7 @@ class SigmaDslSpecification extends SigmaDslTesting
FixedCostItem(FuncValue.AddToEnvironmentDesc, FixedCost(JitCost(5))),
FixedCostItem(Global),
FixedCostItem(PropertyCall),
- FixedCostItem(SGlobal.groupGeneratorMethod, FixedCost(JitCost(10)))
+ FixedCostItem(SGlobalMethods.groupGeneratorMethod, FixedCost(JitCost(10)))
)
)
verifyCases(
@@ -6411,7 +6399,7 @@ class SigmaDslSpecification extends SigmaDslTesting
Vector((1, SInt)),
MethodCall.typed[Value[SGroupElement.type]](
Global,
- SGlobal.getMethodByName("groupGenerator"),
+ SGlobalMethods.getMethodByName("groupGenerator"),
Vector(),
Map()
)
@@ -6430,7 +6418,7 @@ class SigmaDslSpecification extends SigmaDslTesting
Vector((1, SInt)),
MethodCall.typed[Value[SGroupElement.type]](
Global,
- SGlobal.getMethodByName("groupGenerator"),
+ SGlobalMethods.getMethodByName("groupGenerator"),
Vector(),
Map()
)
@@ -6468,7 +6456,7 @@ class SigmaDslSpecification extends SigmaDslTesting
Exponentiate(
MethodCall.typed[Value[SGroupElement.type]](
Global,
- SGlobal.getMethodByName("groupGenerator"),
+ SGlobalMethods.getMethodByName("groupGenerator"),
Vector(),
Map()
),
@@ -6486,7 +6474,7 @@ class SigmaDslSpecification extends SigmaDslTesting
FixedCostItem(SelectField),
FixedCostItem(ValUse),
FixedCostItem(SelectField),
- SeqCostItem(CompanionDesc(Xor), PerItemCost(JitCost(10), JitCost(2), 128), i)
+ ast.SeqCostItem(CompanionDesc(Xor), PerItemCost(JitCost(10), JitCost(2), 128), i)
)
)
else
@@ -6503,7 +6491,7 @@ class SigmaDslSpecification extends SigmaDslTesting
FixedCostItem(SelectField),
FixedCostItem(ValUse),
FixedCostItem(SelectField),
- SeqCostItem(CompanionDesc(Xor), PerItemCost(JitCost(10), JitCost(2), 128), i)
+ ast.SeqCostItem(CompanionDesc(Xor), PerItemCost(JitCost(10), JitCost(2), 128), i)
)
)
}
@@ -6554,7 +6542,7 @@ class SigmaDslSpecification extends SigmaDslTesting
Array((1, SPair(SByteArray, SByteArray))),
MethodCall.typed[Value[SCollection[SByte.type]]](
Global,
- SGlobal.getMethodByName("xor"),
+ SGlobalMethods.getMethodByName("xor"),
Vector(
SelectField.typed[Value[SCollection[SByte.type]]](
ValUse(1, SPair(SByteArray, SByteArray)),
@@ -6573,11 +6561,11 @@ class SigmaDslSpecification extends SigmaDslTesting
def sampleCollBoxes = genSamples[Coll[Box]](collOfN[Box](5, arbitrary[Box]), MinSuccessful(20))
- def create_b1 = CostingBox(
+ def create_b1 = CBox(
new ErgoBox(
1L,
new ErgoTree(
- 0.toByte,
+ HeaderType @@ 0.toByte,
Vector(),
Right(
SigmaPropConstant(
@@ -6609,11 +6597,11 @@ class SigmaDslSpecification extends SigmaDslTesting
)
)
- def create_b2 = CostingBox(
+ def create_b2 = CBox(
new ErgoBox(
1000000000L,
new ErgoTree(
- 0.toByte,
+ HeaderType @@ 0.toByte,
Vector(),
Right(BoolToSigmaProp(OR(ConcreteCollection(Array(FalseLeaf, AND(ConcreteCollection(Array(FalseLeaf, FalseLeaf), SBoolean))), SBoolean))))
),
@@ -6633,13 +6621,13 @@ class SigmaDslSpecification extends SigmaDslTesting
val costDetails = TracedCost(
traceBase ++ Array(
FixedCostItem(FuncValue),
- SeqCostItem(CompanionDesc(Filter), PerItemCost(JitCost(20), JitCost(1), 10), 0)
+ ast.SeqCostItem(CompanionDesc(Filter), PerItemCost(JitCost(20), JitCost(1), 10), 0)
)
)
val costDetails2 = TracedCost(
traceBase ++ Array(
FixedCostItem(FuncValue),
- SeqCostItem(CompanionDesc(Filter), PerItemCost(JitCost(20), JitCost(1), 10), 1),
+ ast.SeqCostItem(CompanionDesc(Filter), PerItemCost(JitCost(20), JitCost(1), 10), 1),
FixedCostItem(FuncValue.AddToEnvironmentDesc, FixedCost(JitCost(5))),
FixedCostItem(ValUse),
FixedCostItem(ExtractAmount),
@@ -6650,7 +6638,7 @@ class SigmaDslSpecification extends SigmaDslTesting
val costDetails3 = TracedCost(
traceBase ++ Array(
FixedCostItem(FuncValue),
- SeqCostItem(CompanionDesc(Filter), PerItemCost(JitCost(20), JitCost(1), 10), 2),
+ ast.SeqCostItem(CompanionDesc(Filter), PerItemCost(JitCost(20), JitCost(1), 10), 2),
FixedCostItem(FuncValue.AddToEnvironmentDesc, FixedCost(JitCost(5))),
FixedCostItem(ValUse),
FixedCostItem(ExtractAmount),
@@ -6693,7 +6681,7 @@ class SigmaDslSpecification extends SigmaDslTesting
traceBase ++ Array(
FixedCostItem(MethodCall),
FixedCostItem(FuncValue),
- SeqCostItem(MethodDesc(SCollection.FlatMapMethod), PerItemCost(JitCost(60), JitCost(10), 8), 0)
+ ast.SeqCostItem(MethodDesc(SCollectionMethods.FlatMapMethod), PerItemCost(JitCost(60), JitCost(10), 8), 0)
)
)
val costDetails2 = TracedCost(
@@ -6703,7 +6691,7 @@ class SigmaDslSpecification extends SigmaDslTesting
FixedCostItem(FuncValue.AddToEnvironmentDesc, FixedCost(JitCost(5))),
FixedCostItem(ValUse),
FixedCostItem(ExtractScriptBytes),
- SeqCostItem(MethodDesc(SCollection.FlatMapMethod), PerItemCost(JitCost(60), JitCost(10), 8), 135)
+ ast.SeqCostItem(MethodDesc(SCollectionMethods.FlatMapMethod), PerItemCost(JitCost(60), JitCost(10), 8), 135)
)
)
val costDetails3 = TracedCost(
@@ -6716,7 +6704,7 @@ class SigmaDslSpecification extends SigmaDslTesting
FixedCostItem(FuncValue.AddToEnvironmentDesc, FixedCost(JitCost(5))),
FixedCostItem(ValUse),
FixedCostItem(ExtractScriptBytes),
- SeqCostItem(MethodDesc(SCollection.FlatMapMethod), PerItemCost(JitCost(60), JitCost(10), 8), 147)
+ ast.SeqCostItem(MethodDesc(SCollectionMethods.FlatMapMethod), PerItemCost(JitCost(60), JitCost(10), 8), 147)
)
)
verifyCases(
@@ -6737,7 +6725,7 @@ class SigmaDslSpecification extends SigmaDslTesting
Vector((1, SCollectionType(SBox))),
MethodCall.typed[Value[SCollection[SByte.type]]](
ValUse(1, SCollectionType(SBox)),
- SCollection.getMethodByName("flatMap").withConcreteTypes(
+ SCollectionMethods.getMethodByName("flatMap").withConcreteTypes(
Map(STypeVar("IV") -> SBox, STypeVar("OV") -> SByte)
),
Vector(FuncValue(Vector((3, SBox)), ExtractScriptBytes(ValUse(3, SBox)))),
@@ -6755,7 +6743,7 @@ class SigmaDslSpecification extends SigmaDslTesting
traceBase ++ Array(
FixedCostItem(MethodCall),
FixedCostItem(ValUse),
- SeqCostItem(MethodDesc(SCollection.ZipMethod), PerItemCost(JitCost(10), JitCost(1), 10), zipElements)
+ ast.SeqCostItem(MethodDesc(SCollectionMethods.ZipMethod), PerItemCost(JitCost(10), JitCost(1), 10), zipElements)
)
)
@@ -6774,7 +6762,7 @@ class SigmaDslSpecification extends SigmaDslTesting
Vector((1, SCollectionType(SBox))),
MethodCall.typed[Value[SCollection[STuple]]](
ValUse(1, SCollectionType(SBox)),
- SCollection.getMethodByName("zip").withConcreteTypes(
+ SCollectionMethods.getMethodByName("zip").withConcreteTypes(
Map(STypeVar("IV") -> SBox, STypeVar("OV") -> SBox)
),
Vector(ValUse(1, SCollectionType(SBox))),
@@ -6811,7 +6799,7 @@ class SigmaDslSpecification extends SigmaDslTesting
def costDetails(indicesCount: Int) = TracedCost(
traceBase ++ Array(
FixedCostItem(PropertyCall),
- SeqCostItem(MethodDesc(SCollection.IndicesMethod), PerItemCost(JitCost(20), JitCost(2), 16), indicesCount)
+ ast.SeqCostItem(MethodDesc(SCollectionMethods.IndicesMethod), PerItemCost(JitCost(20), JitCost(2), 16), indicesCount)
)
)
verifyCases(
@@ -6829,7 +6817,7 @@ class SigmaDslSpecification extends SigmaDslTesting
Vector((1, SCollectionType(SBox))),
MethodCall.typed[Value[SCollection[SInt.type]]](
ValUse(1, SCollectionType(SBox)),
- SCollection.getMethodByName("indices").withConcreteTypes(Map(STypeVar("IV") -> SBox)),
+ SCollectionMethods.getMethodByName("indices").withConcreteTypes(Map(STypeVar("IV") -> SBox)),
Vector(),
Map()
)
@@ -6845,13 +6833,13 @@ class SigmaDslSpecification extends SigmaDslTesting
val costDetails1 = TracedCost(
traceBase ++ Array(
FixedCostItem(FuncValue),
- SeqCostItem(CompanionDesc(ForAll), PerItemCost(JitCost(3), JitCost(1), 10), 0)
+ ast.SeqCostItem(CompanionDesc(ForAll), PerItemCost(JitCost(3), JitCost(1), 10), 0)
)
)
val costDetails2 = TracedCost(
traceBase ++ Array(
FixedCostItem(FuncValue),
- SeqCostItem(CompanionDesc(ForAll), PerItemCost(JitCost(3), JitCost(1), 10), 1),
+ ast.SeqCostItem(CompanionDesc(ForAll), PerItemCost(JitCost(3), JitCost(1), 10), 1),
FixedCostItem(FuncValue.AddToEnvironmentDesc, FixedCost(JitCost(5))),
FixedCostItem(ValUse),
FixedCostItem(ExtractAmount),
@@ -6862,7 +6850,7 @@ class SigmaDslSpecification extends SigmaDslTesting
val costDetails3 = TracedCost(
traceBase ++ Array(
FixedCostItem(FuncValue),
- SeqCostItem(CompanionDesc(ForAll), PerItemCost(JitCost(3), JitCost(1), 10), 2),
+ ast.SeqCostItem(CompanionDesc(ForAll), PerItemCost(JitCost(3), JitCost(1), 10), 2),
FixedCostItem(FuncValue.AddToEnvironmentDesc, FixedCost(JitCost(5))),
FixedCostItem(ValUse),
FixedCostItem(ExtractAmount),
@@ -6900,7 +6888,7 @@ class SigmaDslSpecification extends SigmaDslTesting
Array((1, SCollectionType(SBox))),
MethodCall.typed[Value[SBoolean.type]](
ValUse(1, SCollectionType(SBox)),
- SCollection.getMethodByName("forall").withConcreteTypes(Map(STypeVar("IV") -> SBox)),
+ SCollectionMethods.getMethodByName("forall").withConcreteTypes(Map(STypeVar("IV") -> SBox)),
Vector(FuncValue(Array((3, SBox)), GT(ExtractAmount(ValUse(3, SBox)), LongConstant(1L)))),
Map()
)
@@ -6916,13 +6904,13 @@ class SigmaDslSpecification extends SigmaDslTesting
val costDetails1 = TracedCost(
traceBase ++ Array(
FixedCostItem(FuncValue),
- SeqCostItem(CompanionDesc(Exists), PerItemCost(JitCost(3), JitCost(1), 10), 0)
+ ast.SeqCostItem(CompanionDesc(Exists), PerItemCost(JitCost(3), JitCost(1), 10), 0)
)
)
val costDetails2 = TracedCost(
traceBase ++ Array(
FixedCostItem(FuncValue),
- SeqCostItem(CompanionDesc(Exists), PerItemCost(JitCost(3), JitCost(1), 10), 1),
+ ast.SeqCostItem(CompanionDesc(Exists), PerItemCost(JitCost(3), JitCost(1), 10), 1),
FixedCostItem(FuncValue.AddToEnvironmentDesc, FixedCost(JitCost(5))),
FixedCostItem(ValUse),
FixedCostItem(ExtractAmount),
@@ -6933,7 +6921,7 @@ class SigmaDslSpecification extends SigmaDslTesting
val costDetails3 = TracedCost(
traceBase ++ Array(
FixedCostItem(FuncValue),
- SeqCostItem(CompanionDesc(Exists), PerItemCost(JitCost(3), JitCost(1), 10), 2),
+ ast.SeqCostItem(CompanionDesc(Exists), PerItemCost(JitCost(3), JitCost(1), 10), 2),
FixedCostItem(FuncValue.AddToEnvironmentDesc, FixedCost(JitCost(5))),
FixedCostItem(ValUse),
FixedCostItem(ExtractAmount),
@@ -6976,7 +6964,7 @@ class SigmaDslSpecification extends SigmaDslTesting
Array((1, SCollectionType(SBox))),
MethodCall.typed[Value[SBoolean.type]](
ValUse(1, SCollectionType(SBox)),
- SCollection.getMethodByName("exists").withConcreteTypes(Map(STypeVar("IV") -> SBox)),
+ SCollectionMethods.getMethodByName("exists").withConcreteTypes(Map(STypeVar("IV") -> SBox)),
Vector(FuncValue(Array((3, SBox)), GT(ExtractAmount(ValUse(3, SBox)), LongConstant(1L)))),
Map()
)
@@ -6990,13 +6978,13 @@ class SigmaDslSpecification extends SigmaDslTesting
val costDetails1 = TracedCost(
traceBase ++ Array(
FixedCostItem(FuncValue),
- SeqCostItem(CompanionDesc(Exists), PerItemCost(JitCost(3), JitCost(1), 10), 0)
+ ast.SeqCostItem(CompanionDesc(Exists), PerItemCost(JitCost(3), JitCost(1), 10), 0)
)
)
val costDetails2 = TracedCost(
traceBase ++ Array(
FixedCostItem(FuncValue),
- SeqCostItem(CompanionDesc(Exists), PerItemCost(JitCost(3), JitCost(1), 10), 1),
+ ast.SeqCostItem(CompanionDesc(Exists), PerItemCost(JitCost(3), JitCost(1), 10), 1),
FixedCostItem(FuncValue.AddToEnvironmentDesc, FixedCost(JitCost(5))),
FixedCostItem(ValUse),
FixedCostItem(Constant),
@@ -7008,7 +6996,7 @@ class SigmaDslSpecification extends SigmaDslTesting
val costDetails3 = TracedCost(
traceBase ++ Array(
FixedCostItem(FuncValue),
- SeqCostItem(CompanionDesc(Exists), PerItemCost(JitCost(3), JitCost(1), 10), 1),
+ ast.SeqCostItem(CompanionDesc(Exists), PerItemCost(JitCost(3), JitCost(1), 10), 1),
FixedCostItem(FuncValue.AddToEnvironmentDesc, FixedCost(JitCost(5))),
FixedCostItem(ValUse),
FixedCostItem(Constant),
@@ -7022,7 +7010,7 @@ class SigmaDslSpecification extends SigmaDslTesting
val costDetails4 = TracedCost(
traceBase ++ Array(
FixedCostItem(FuncValue),
- SeqCostItem(CompanionDesc(Exists), PerItemCost(JitCost(3), JitCost(1), 10), 2),
+ ast.SeqCostItem(CompanionDesc(Exists), PerItemCost(JitCost(3), JitCost(1), 10), 2),
FixedCostItem(FuncValue.AddToEnvironmentDesc, FixedCost(JitCost(5))),
FixedCostItem(ValUse),
FixedCostItem(Constant),
@@ -7082,7 +7070,7 @@ class SigmaDslSpecification extends SigmaDslTesting
Array((1, SCollectionType(SBigInt))),
MethodCall.typed[Value[SBoolean.type]](
ValUse(1, SCollectionType(SBigInt)),
- SCollection.getMethodByName("exists").withConcreteTypes(Map(STypeVar("IV") -> SBigInt)),
+ SCollectionMethods.getMethodByName("exists").withConcreteTypes(Map(STypeVar("IV") -> SBigInt)),
Vector(
FuncValue(
Array((3, SBigInt)),
@@ -7104,13 +7092,13 @@ class SigmaDslSpecification extends SigmaDslTesting
val costDetails1 = TracedCost(
traceBase ++ Array(
FixedCostItem(FuncValue),
- SeqCostItem(CompanionDesc(ForAll), PerItemCost(JitCost(3), JitCost(1), 10), 0)
+ ast.SeqCostItem(CompanionDesc(ForAll), PerItemCost(JitCost(3), JitCost(1), 10), 0)
)
)
val costDetails2 = TracedCost(
traceBase ++ Array(
FixedCostItem(FuncValue),
- SeqCostItem(CompanionDesc(ForAll), PerItemCost(JitCost(3), JitCost(1), 10), 1),
+ ast.SeqCostItem(CompanionDesc(ForAll), PerItemCost(JitCost(3), JitCost(1), 10), 1),
FixedCostItem(FuncValue.AddToEnvironmentDesc, FixedCost(JitCost(5))),
FixedCostItem(ValUse),
FixedCostItem(Constant),
@@ -7122,7 +7110,7 @@ class SigmaDslSpecification extends SigmaDslTesting
val costDetails3 = TracedCost(
traceBase ++ Array(
FixedCostItem(FuncValue),
- SeqCostItem(CompanionDesc(ForAll), PerItemCost(JitCost(3), JitCost(1), 10), 1),
+ ast.SeqCostItem(CompanionDesc(ForAll), PerItemCost(JitCost(3), JitCost(1), 10), 1),
FixedCostItem(FuncValue.AddToEnvironmentDesc, FixedCost(JitCost(5))),
FixedCostItem(ValUse),
FixedCostItem(Constant),
@@ -7136,7 +7124,7 @@ class SigmaDslSpecification extends SigmaDslTesting
val costDetails4 = TracedCost(
traceBase ++ Array(
FixedCostItem(FuncValue),
- SeqCostItem(CompanionDesc(ForAll), PerItemCost(JitCost(3), JitCost(1), 10), 2),
+ ast.SeqCostItem(CompanionDesc(ForAll), PerItemCost(JitCost(3), JitCost(1), 10), 2),
FixedCostItem(FuncValue.AddToEnvironmentDesc, FixedCost(JitCost(5))),
FixedCostItem(ValUse),
FixedCostItem(Constant),
@@ -7197,7 +7185,7 @@ class SigmaDslSpecification extends SigmaDslTesting
Array((1, SCollectionType(SBigInt))),
MethodCall.typed[Value[SBoolean.type]](
ValUse(1, SCollectionType(SBigInt)),
- SCollection.getMethodByName("forall").withConcreteTypes(Map(STypeVar("IV") -> SBigInt)),
+ SCollectionMethods.getMethodByName("forall").withConcreteTypes(Map(STypeVar("IV") -> SBigInt)),
Vector(
FuncValue(
Array((3, SBigInt)),
@@ -7225,7 +7213,7 @@ class SigmaDslSpecification extends SigmaDslTesting
traceBase ++ Array(
FixedCostItem(MethodCall),
FixedCostItem(FuncValue),
- SeqCostItem(MethodDesc(SCollection.FlatMapMethod), PerItemCost(JitCost(60), JitCost(10), 8), 0)
+ ast.SeqCostItem(MethodDesc(SCollectionMethods.FlatMapMethod), PerItemCost(JitCost(60), JitCost(10), 8), 0)
)
)
val costDetails1 = TracedCost(
@@ -7233,8 +7221,8 @@ class SigmaDslSpecification extends SigmaDslTesting
FixedCostItem(MethodCall),
FixedCostItem(FuncValue),
FixedCostItem(NamedDesc("MatchSingleArgMethodCall"), FixedCost(JitCost(30))),
- SeqCostItem(NamedDesc("CheckFlatmapBody"), PerItemCost(JitCost(20), JitCost(20), 1), 1),
- SeqCostItem(MethodDesc(SCollection.FlatMapMethod), PerItemCost(JitCost(60), JitCost(10), 8), 0)
+ ast.SeqCostItem(NamedDesc("CheckFlatmapBody"), PerItemCost(JitCost(20), JitCost(20), 1), 1),
+ ast.SeqCostItem(MethodDesc(SCollectionMethods.FlatMapMethod), PerItemCost(JitCost(60), JitCost(10), 8), 0)
)
)
val costDetails2 = TracedCost(
@@ -7244,12 +7232,12 @@ class SigmaDslSpecification extends SigmaDslTesting
FixedCostItem(FuncValue.AddToEnvironmentDesc, FixedCost(JitCost(5))),
FixedCostItem(ValUse),
FixedCostItem(PropertyCall),
- FixedCostItem(SGroupElement.GetEncodedMethod, FixedCost(JitCost(250))),
+ FixedCostItem(SGroupElementMethods.GetEncodedMethod, FixedCost(JitCost(250))),
FixedCostItem(FuncValue.AddToEnvironmentDesc, FixedCost(JitCost(5))),
FixedCostItem(ValUse),
FixedCostItem(PropertyCall),
- FixedCostItem(SGroupElement.GetEncodedMethod, FixedCost(JitCost(250))),
- SeqCostItem(MethodDesc(SCollection.FlatMapMethod), PerItemCost(JitCost(60), JitCost(10), 8), 66)
+ FixedCostItem(SGroupElementMethods.GetEncodedMethod, FixedCost(JitCost(250))),
+ ast.SeqCostItem(MethodDesc(SCollectionMethods.FlatMapMethod), PerItemCost(JitCost(60), JitCost(10), 8), 66)
)
)
val costDetails3 = TracedCost(
@@ -7259,16 +7247,16 @@ class SigmaDslSpecification extends SigmaDslTesting
FixedCostItem(FuncValue.AddToEnvironmentDesc, FixedCost(JitCost(5))),
FixedCostItem(ValUse),
FixedCostItem(PropertyCall),
- FixedCostItem(SGroupElement.GetEncodedMethod, FixedCost(JitCost(250))),
+ FixedCostItem(SGroupElementMethods.GetEncodedMethod, FixedCost(JitCost(250))),
FixedCostItem(FuncValue.AddToEnvironmentDesc, FixedCost(JitCost(5))),
FixedCostItem(ValUse),
FixedCostItem(PropertyCall),
- FixedCostItem(SGroupElement.GetEncodedMethod, FixedCost(JitCost(250))),
+ FixedCostItem(SGroupElementMethods.GetEncodedMethod, FixedCost(JitCost(250))),
FixedCostItem(FuncValue.AddToEnvironmentDesc, FixedCost(JitCost(5))),
FixedCostItem(ValUse),
FixedCostItem(PropertyCall),
- FixedCostItem(SGroupElement.GetEncodedMethod, FixedCost(JitCost(250))),
- SeqCostItem(MethodDesc(SCollection.FlatMapMethod), PerItemCost(JitCost(60), JitCost(10), 8), 99)
+ FixedCostItem(SGroupElementMethods.GetEncodedMethod, FixedCost(JitCost(250))),
+ ast.SeqCostItem(MethodDesc(SCollectionMethods.FlatMapMethod), PerItemCost(JitCost(60), JitCost(10), 8), 99)
)
)
val costDetails4 = TracedCost(
@@ -7278,16 +7266,16 @@ class SigmaDslSpecification extends SigmaDslTesting
FixedCostItem(FuncValue.AddToEnvironmentDesc, FixedCost(JitCost(5))),
FixedCostItem(ValUse),
FixedCostItem(PropertyCall),
- FixedCostItem(SGroupElement.GetEncodedMethod, FixedCost(JitCost(250))),
+ FixedCostItem(SGroupElementMethods.GetEncodedMethod, FixedCost(JitCost(250))),
FixedCostItem(PropertyCall),
- SeqCostItem(MethodDesc(SCollection.IndicesMethod), PerItemCost(JitCost(20), JitCost(2), 16), 33),
+ ast.SeqCostItem(MethodDesc(SCollectionMethods.IndicesMethod), PerItemCost(JitCost(20), JitCost(2), 16), 33),
FixedCostItem(FuncValue.AddToEnvironmentDesc, FixedCost(JitCost(5))),
FixedCostItem(ValUse),
FixedCostItem(PropertyCall),
- FixedCostItem(SGroupElement.GetEncodedMethod, FixedCost(JitCost(250))),
+ FixedCostItem(SGroupElementMethods.GetEncodedMethod, FixedCost(JitCost(250))),
FixedCostItem(PropertyCall),
- SeqCostItem(MethodDesc(SCollection.IndicesMethod), PerItemCost(JitCost(20), JitCost(2), 16), 33),
- SeqCostItem(MethodDesc(SCollection.FlatMapMethod), PerItemCost(JitCost(60), JitCost(10), 8), 66)
+ ast.SeqCostItem(MethodDesc(SCollectionMethods.IndicesMethod), PerItemCost(JitCost(20), JitCost(2), 16), 33),
+ ast.SeqCostItem(MethodDesc(SCollectionMethods.FlatMapMethod), PerItemCost(JitCost(60), JitCost(10), 8), 66)
)
)
@@ -7324,7 +7312,7 @@ class SigmaDslSpecification extends SigmaDslTesting
Vector((1, SCollectionType(SGroupElement))),
MethodCall.typed[Value[SCollection[SByte.type]]](
ValUse(1, SCollectionType(SGroupElement)),
- SCollection.getMethodByName("flatMap").withConcreteTypes(
+ SCollectionMethods.getMethodByName("flatMap").withConcreteTypes(
Map(STypeVar("IV") -> SGroupElement, STypeVar("OV") -> SByte)
),
Vector(
@@ -7332,7 +7320,7 @@ class SigmaDslSpecification extends SigmaDslTesting
Vector((3, SGroupElement)),
MethodCall.typed[Value[SCollection[SByte.type]]](
ValUse(3, SGroupElement),
- SGroupElement.getMethodByName("getEncoded"),
+ SGroupElementMethods.getMethodByName("getEncoded"),
Vector(),
Map()
)
@@ -7366,7 +7354,7 @@ class SigmaDslSpecification extends SigmaDslTesting
Array((1, SCollectionType(SGroupElement))),
MethodCall.typed[Value[SCollection[SInt.type]]](
ValUse(1, SCollectionType(SGroupElement)),
- SCollection.getMethodByName("flatMap").withConcreteTypes(
+ SCollectionMethods.getMethodByName("flatMap").withConcreteTypes(
Map(STypeVar("IV") -> SGroupElement, STypeVar("OV") -> SInt)
),
Vector(
@@ -7375,11 +7363,11 @@ class SigmaDslSpecification extends SigmaDslTesting
MethodCall.typed[Value[SCollection[SInt.type]]](
MethodCall.typed[Value[SCollection[SByte.type]]](
ValUse(3, SGroupElement),
- SGroupElement.getMethodByName("getEncoded"),
+ SGroupElementMethods.getMethodByName("getEncoded"),
Vector(),
Map()
),
- SCollection.getMethodByName("indices").withConcreteTypes(Map(STypeVar("IV") -> SByte)),
+ SCollectionMethods.getMethodByName("indices").withConcreteTypes(Map(STypeVar("IV") -> SByte)),
Vector(),
Map()
)
@@ -7402,7 +7390,7 @@ class SigmaDslSpecification extends SigmaDslTesting
FixedCostItem(GetVar),
FixedCostItem(OptionGet),
FixedCostItem(FuncValue.AddToEnvironmentDesc, FixedCost(JitCost(5))),
- SeqCostItem(CompanionDesc(BlockValue), PerItemCost(JitCost(1), JitCost(1), 10), 2),
+ ast.SeqCostItem(CompanionDesc(BlockValue), PerItemCost(JitCost(1), JitCost(1), 10), 2),
FixedCostItem(ValUse),
FixedCostItem(SelectField),
FixedCostItem(FuncValue.AddToEnvironmentDesc, FixedCost(JitCost(5))),
@@ -7416,7 +7404,7 @@ class SigmaDslSpecification extends SigmaDslTesting
FixedCostItem(ValUse),
FixedCostItem(ValUse),
FixedCostItem(SelectField),
- SeqCostItem(MethodDesc(SCollection.PatchMethod), PerItemCost(JitCost(30), JitCost(2), 10), i)
+ ast.SeqCostItem(MethodDesc(SCollectionMethods.PatchMethod), PerItemCost(JitCost(30), JitCost(2), 10), i)
)
)
@@ -7472,7 +7460,7 @@ class SigmaDslSpecification extends SigmaDslTesting
),
MethodCall.typed[Value[SCollection[SInt.type]]](
ValUse(3, SCollectionType(SInt)),
- SCollection.getMethodByName("patch").withConcreteTypes(Map(STypeVar("IV") -> SInt)),
+ SCollectionMethods.getMethodByName("patch").withConcreteTypes(Map(STypeVar("IV") -> SInt)),
Vector(
SelectField.typed[Value[SInt.type]](ValUse(4, SPair(SInt, SInt)), 1.toByte),
ValUse(3, SCollectionType(SInt)),
@@ -7494,7 +7482,7 @@ class SigmaDslSpecification extends SigmaDslTesting
FixedCostItem(GetVar),
FixedCostItem(OptionGet),
FixedCostItem(FuncValue.AddToEnvironmentDesc, FixedCost(JitCost(5))),
- SeqCostItem(CompanionDesc(BlockValue), PerItemCost(JitCost(1), JitCost(1), 10), 1),
+ ast.SeqCostItem(CompanionDesc(BlockValue), PerItemCost(JitCost(1), JitCost(1), 10), 1),
FixedCostItem(ValUse),
FixedCostItem(SelectField),
FixedCostItem(FuncValue.AddToEnvironmentDesc, FixedCost(JitCost(5))),
@@ -7505,7 +7493,7 @@ class SigmaDslSpecification extends SigmaDslTesting
FixedCostItem(SelectField),
FixedCostItem(ValUse),
FixedCostItem(SelectField),
- SeqCostItem(MethodDesc(SCollection.UpdatedMethod), PerItemCost(JitCost(20), JitCost(1), 10), i)
+ ast.SeqCostItem(MethodDesc(SCollectionMethods.UpdatedMethod), PerItemCost(JitCost(20), JitCost(1), 10), i)
)
)
verifyCases(
@@ -7544,7 +7532,7 @@ class SigmaDslSpecification extends SigmaDslTesting
ValUse(1, SPair(SCollectionType(SInt), SPair(SInt, SInt))),
1.toByte
),
- SCollection.getMethodByName("updated").withConcreteTypes(Map(STypeVar("IV") -> SInt)),
+ SCollectionMethods.getMethodByName("updated").withConcreteTypes(Map(STypeVar("IV") -> SInt)),
Vector(
SelectField.typed[Value[SInt.type]](ValUse(3, SPair(SInt, SInt)), 1.toByte),
SelectField.typed[Value[SInt.type]](ValUse(3, SPair(SInt, SInt)), 2.toByte)
@@ -7571,7 +7559,7 @@ class SigmaDslSpecification extends SigmaDslTesting
FixedCostItem(GetVar),
FixedCostItem(OptionGet),
FixedCostItem(FuncValue.AddToEnvironmentDesc, FixedCost(JitCost(5))),
- SeqCostItem(CompanionDesc(BlockValue), PerItemCost(JitCost(1), JitCost(1), 10), 1),
+ ast.SeqCostItem(CompanionDesc(BlockValue), PerItemCost(JitCost(1), JitCost(1), 10), 1),
FixedCostItem(ValUse),
FixedCostItem(SelectField),
FixedCostItem(FuncValue.AddToEnvironmentDesc, FixedCost(JitCost(5))),
@@ -7582,7 +7570,7 @@ class SigmaDslSpecification extends SigmaDslTesting
FixedCostItem(SelectField),
FixedCostItem(ValUse),
FixedCostItem(SelectField),
- SeqCostItem(MethodDesc(SCollection.UpdateManyMethod), PerItemCost(JitCost(20), JitCost(2), 10), i)
+ ast.SeqCostItem(MethodDesc(SCollectionMethods.UpdateManyMethod), PerItemCost(JitCost(20), JitCost(2), 10), i)
)
)
verifyCases(
@@ -7632,7 +7620,7 @@ class SigmaDslSpecification extends SigmaDslTesting
ValUse(1, SPair(SCollectionType(SInt), SPair(SCollectionType(SInt), SCollectionType(SInt)))),
1.toByte
),
- SCollection.getMethodByName("updateMany").withConcreteTypes(Map(STypeVar("IV") -> SInt)),
+ SCollectionMethods.getMethodByName("updateMany").withConcreteTypes(Map(STypeVar("IV") -> SInt)),
Vector(
SelectField.typed[Value[SCollection[SInt.type]]](
ValUse(3, SPair(SCollectionType(SInt), SCollectionType(SInt))),
@@ -7688,7 +7676,7 @@ class SigmaDslSpecification extends SigmaDslTesting
FixedCostItem(ValUse),
FixedCostItem(SelectField),
FixedCostItem(FuncValue),
- SeqCostItem(CompanionDesc(Fold), PerItemCost(JitCost(3), JitCost(1), 10), 0)
+ ast.SeqCostItem(CompanionDesc(Fold), PerItemCost(JitCost(3), JitCost(1), 10), 0)
)
)
val costDetails2 = TracedCost(
@@ -7697,7 +7685,7 @@ class SigmaDslSpecification extends SigmaDslTesting
FixedCostItem(ValUse),
FixedCostItem(SelectField),
FixedCostItem(FuncValue),
- SeqCostItem(CompanionDesc(Fold), PerItemCost(JitCost(3), JitCost(1), 10), 1),
+ ast.SeqCostItem(CompanionDesc(Fold), PerItemCost(JitCost(3), JitCost(1), 10), 1),
FixedCostItem(FuncValue.AddToEnvironmentDesc, FixedCost(JitCost(5))),
FixedCostItem(ValUse),
FixedCostItem(SelectField),
@@ -7713,7 +7701,7 @@ class SigmaDslSpecification extends SigmaDslTesting
FixedCostItem(ValUse),
FixedCostItem(SelectField),
FixedCostItem(FuncValue),
- SeqCostItem(CompanionDesc(Fold), PerItemCost(JitCost(3), JitCost(1), 10), 2),
+ ast.SeqCostItem(CompanionDesc(Fold), PerItemCost(JitCost(3), JitCost(1), 10), 2),
FixedCostItem(FuncValue.AddToEnvironmentDesc, FixedCost(JitCost(5))),
FixedCostItem(ValUse),
FixedCostItem(SelectField),
@@ -7736,7 +7724,7 @@ class SigmaDslSpecification extends SigmaDslTesting
FixedCostItem(ValUse),
FixedCostItem(SelectField),
FixedCostItem(FuncValue),
- SeqCostItem(CompanionDesc(Fold), PerItemCost(JitCost(3), JitCost(1), 10), 3),
+ ast.SeqCostItem(CompanionDesc(Fold), PerItemCost(JitCost(3), JitCost(1), 10), 3),
FixedCostItem(FuncValue.AddToEnvironmentDesc, FixedCost(JitCost(5))),
FixedCostItem(ValUse),
FixedCostItem(SelectField),
@@ -7805,7 +7793,7 @@ class SigmaDslSpecification extends SigmaDslTesting
Array((1, SPair(SByteArray, SInt))),
MethodCall.typed[Value[SInt.type]](
SelectField.typed[Value[SCollection[SByte.type]]](ValUse(1, SPair(SByteArray, SInt)), 1.toByte),
- SCollection.getMethodByName("fold").withConcreteTypes(Map(STypeVar("IV") -> SByte, STypeVar("OV") -> SInt)),
+ SCollectionMethods.getMethodByName("fold").withConcreteTypes(Map(STypeVar("IV") -> SByte, STypeVar("OV") -> SInt)),
Vector(
SelectField.typed[Value[SInt.type]](ValUse(1, SPair(SByteArray, SInt)), 2.toByte),
FuncValue(
@@ -7835,7 +7823,7 @@ class SigmaDslSpecification extends SigmaDslTesting
FixedCostItem(ValUse),
FixedCostItem(SelectField),
FixedCostItem(FuncValue),
- SeqCostItem(CompanionDesc(Fold), PerItemCost(JitCost(3), JitCost(1), 10), 0)
+ ast.SeqCostItem(CompanionDesc(Fold), PerItemCost(JitCost(3), JitCost(1), 10), 0)
)
)
val costDetails2 = TracedCost(
@@ -7844,9 +7832,9 @@ class SigmaDslSpecification extends SigmaDslTesting
FixedCostItem(ValUse),
FixedCostItem(SelectField),
FixedCostItem(FuncValue),
- SeqCostItem(CompanionDesc(Fold), PerItemCost(JitCost(3), JitCost(1), 10), 1),
+ ast.SeqCostItem(CompanionDesc(Fold), PerItemCost(JitCost(3), JitCost(1), 10), 1),
FixedCostItem(FuncValue.AddToEnvironmentDesc, FixedCost(JitCost(5))),
- SeqCostItem(CompanionDesc(BlockValue), PerItemCost(JitCost(1), JitCost(1), 10), 2),
+ ast.SeqCostItem(CompanionDesc(BlockValue), PerItemCost(JitCost(1), JitCost(1), 10), 2),
FixedCostItem(ValUse),
FixedCostItem(SelectField),
TypeBasedCostItem(Upcast, SInt),
@@ -7869,9 +7857,9 @@ class SigmaDslSpecification extends SigmaDslTesting
FixedCostItem(ValUse),
FixedCostItem(SelectField),
FixedCostItem(FuncValue),
- SeqCostItem(CompanionDesc(Fold), PerItemCost(JitCost(3), JitCost(1), 10), 1),
+ ast.SeqCostItem(CompanionDesc(Fold), PerItemCost(JitCost(3), JitCost(1), 10), 1),
FixedCostItem(FuncValue.AddToEnvironmentDesc, FixedCost(JitCost(5))),
- SeqCostItem(CompanionDesc(BlockValue), PerItemCost(JitCost(1), JitCost(1), 10), 2),
+ ast.SeqCostItem(CompanionDesc(BlockValue), PerItemCost(JitCost(1), JitCost(1), 10), 2),
FixedCostItem(ValUse),
FixedCostItem(SelectField),
TypeBasedCostItem(Upcast, SInt),
@@ -7892,9 +7880,9 @@ class SigmaDslSpecification extends SigmaDslTesting
FixedCostItem(ValUse),
FixedCostItem(SelectField),
FixedCostItem(FuncValue),
- SeqCostItem(CompanionDesc(Fold), PerItemCost(JitCost(3), JitCost(1), 10), 2),
+ ast.SeqCostItem(CompanionDesc(Fold), PerItemCost(JitCost(3), JitCost(1), 10), 2),
FixedCostItem(FuncValue.AddToEnvironmentDesc, FixedCost(JitCost(5))),
- SeqCostItem(CompanionDesc(BlockValue), PerItemCost(JitCost(1), JitCost(1), 10), 2),
+ ast.SeqCostItem(CompanionDesc(BlockValue), PerItemCost(JitCost(1), JitCost(1), 10), 2),
FixedCostItem(ValUse),
FixedCostItem(SelectField),
TypeBasedCostItem(Upcast, SInt),
@@ -7910,7 +7898,7 @@ class SigmaDslSpecification extends SigmaDslTesting
FixedCostItem(ValUse),
TypeBasedCostItem(ArithOp.Plus, SInt),
FixedCostItem(FuncValue.AddToEnvironmentDesc, FixedCost(JitCost(5))),
- SeqCostItem(CompanionDesc(BlockValue), PerItemCost(JitCost(1), JitCost(1), 10), 2),
+ ast.SeqCostItem(CompanionDesc(BlockValue), PerItemCost(JitCost(1), JitCost(1), 10), 2),
FixedCostItem(ValUse),
FixedCostItem(SelectField),
TypeBasedCostItem(Upcast, SInt),
@@ -7933,9 +7921,9 @@ class SigmaDslSpecification extends SigmaDslTesting
FixedCostItem(ValUse),
FixedCostItem(SelectField),
FixedCostItem(FuncValue),
- SeqCostItem(CompanionDesc(Fold), PerItemCost(JitCost(3), JitCost(1), 10), 2),
+ ast.SeqCostItem(CompanionDesc(Fold), PerItemCost(JitCost(3), JitCost(1), 10), 2),
FixedCostItem(FuncValue.AddToEnvironmentDesc, FixedCost(JitCost(5))),
- SeqCostItem(CompanionDesc(BlockValue), PerItemCost(JitCost(1), JitCost(1), 10), 2),
+ ast.SeqCostItem(CompanionDesc(BlockValue), PerItemCost(JitCost(1), JitCost(1), 10), 2),
FixedCostItem(ValUse),
FixedCostItem(SelectField),
TypeBasedCostItem(Upcast, SInt),
@@ -7951,7 +7939,7 @@ class SigmaDslSpecification extends SigmaDslTesting
FixedCostItem(ValUse),
TypeBasedCostItem(ArithOp.Plus, SInt),
FixedCostItem(FuncValue.AddToEnvironmentDesc, FixedCost(JitCost(5))),
- SeqCostItem(CompanionDesc(BlockValue), PerItemCost(JitCost(1), JitCost(1), 10), 2),
+ ast.SeqCostItem(CompanionDesc(BlockValue), PerItemCost(JitCost(1), JitCost(1), 10), 2),
FixedCostItem(ValUse),
FixedCostItem(SelectField),
TypeBasedCostItem(Upcast, SInt),
@@ -7972,9 +7960,9 @@ class SigmaDslSpecification extends SigmaDslTesting
FixedCostItem(ValUse),
FixedCostItem(SelectField),
FixedCostItem(FuncValue),
- SeqCostItem(CompanionDesc(Fold), PerItemCost(JitCost(3), JitCost(1), 10), 3),
+ ast.SeqCostItem(CompanionDesc(Fold), PerItemCost(JitCost(3), JitCost(1), 10), 3),
FixedCostItem(FuncValue.AddToEnvironmentDesc, FixedCost(JitCost(5))),
- SeqCostItem(CompanionDesc(BlockValue), PerItemCost(JitCost(1), JitCost(1), 10), 2),
+ ast.SeqCostItem(CompanionDesc(BlockValue), PerItemCost(JitCost(1), JitCost(1), 10), 2),
FixedCostItem(ValUse),
FixedCostItem(SelectField),
TypeBasedCostItem(Upcast, SInt),
@@ -7990,7 +7978,7 @@ class SigmaDslSpecification extends SigmaDslTesting
FixedCostItem(ValUse),
TypeBasedCostItem(ArithOp.Plus, SInt),
FixedCostItem(FuncValue.AddToEnvironmentDesc, FixedCost(JitCost(5))),
- SeqCostItem(CompanionDesc(BlockValue), PerItemCost(JitCost(1), JitCost(1), 10), 2),
+ ast.SeqCostItem(CompanionDesc(BlockValue), PerItemCost(JitCost(1), JitCost(1), 10), 2),
FixedCostItem(ValUse),
FixedCostItem(SelectField),
TypeBasedCostItem(Upcast, SInt),
@@ -8004,7 +7992,7 @@ class SigmaDslSpecification extends SigmaDslTesting
FixedCostItem(If),
FixedCostItem(ValUse),
FixedCostItem(FuncValue.AddToEnvironmentDesc, FixedCost(JitCost(5))),
- SeqCostItem(CompanionDesc(BlockValue), PerItemCost(JitCost(1), JitCost(1), 10), 2),
+ ast.SeqCostItem(CompanionDesc(BlockValue), PerItemCost(JitCost(1), JitCost(1), 10), 2),
FixedCostItem(ValUse),
FixedCostItem(SelectField),
TypeBasedCostItem(Upcast, SInt),
@@ -8083,7 +8071,7 @@ class SigmaDslSpecification extends SigmaDslTesting
Array((1, SPair(SByteArray, SInt))),
MethodCall.typed[Value[SInt.type]](
SelectField.typed[Value[SCollection[SByte.type]]](ValUse(1, SPair(SByteArray, SInt)), 1.toByte),
- SCollection.getMethodByName("fold").withConcreteTypes(Map(STypeVar("IV") -> SByte, STypeVar("OV") -> SInt)),
+ SCollectionMethods.getMethodByName("fold").withConcreteTypes(Map(STypeVar("IV") -> SByte, STypeVar("OV") -> SInt)),
Vector(
SelectField.typed[Value[SInt.type]](ValUse(1, SPair(SByteArray, SInt)), 2.toByte),
FuncValue(
@@ -8127,7 +8115,7 @@ class SigmaDslSpecification extends SigmaDslTesting
FixedCostItem(GetVar),
FixedCostItem(OptionGet),
FixedCostItem(FuncValue.AddToEnvironmentDesc, FixedCost(JitCost(5))),
- SeqCostItem(CompanionDesc(BlockValue), PerItemCost(JitCost(1), JitCost(1), 10), 1),
+ ast.SeqCostItem(CompanionDesc(BlockValue), PerItemCost(JitCost(1), JitCost(1), 10), 1),
FixedCostItem(ValUse),
FixedCostItem(SelectField),
FixedCostItem(FuncValue.AddToEnvironmentDesc, FixedCost(JitCost(5))),
@@ -8140,7 +8128,7 @@ class SigmaDslSpecification extends SigmaDslTesting
FixedCostItem(SelectField)
)
++ Array.fill(i)(FixedCostItem(NamedDesc("EQ_Prim"), FixedCost(JitCost(3))))
- :+ SeqCostItem(MethodDesc(SCollection.IndexOfMethod), PerItemCost(JitCost(20), JitCost(10), 2), i)
+ :+ ast.SeqCostItem(MethodDesc(SCollectionMethods.IndexOfMethod), PerItemCost(JitCost(20), JitCost(10), 2), i)
)
verifyCases(
// (coll, (elem: Byte, from: Int))
@@ -8189,7 +8177,7 @@ class SigmaDslSpecification extends SigmaDslTesting
ValUse(1, SPair(SByteArray, SPair(SByte, SInt))),
1.toByte
),
- SCollection.getMethodByName("indexOf").withConcreteTypes(Map(STypeVar("IV") -> SByte)),
+ SCollectionMethods.getMethodByName("indexOf").withConcreteTypes(Map(STypeVar("IV") -> SByte)),
Vector(
SelectField.typed[Value[SByte.type]](ValUse(3, SPair(SByte, SInt)), 1.toByte),
SelectField.typed[Value[SInt.type]](ValUse(3, SPair(SByte, SInt)), 2.toByte)
@@ -8247,7 +8235,7 @@ class SigmaDslSpecification extends SigmaDslTesting
FixedCostItem(GetVar),
FixedCostItem(OptionGet),
FixedCostItem(FuncValue.AddToEnvironmentDesc, FixedCost(JitCost(5))),
- SeqCostItem(CompanionDesc(BlockValue), PerItemCost(JitCost(1), JitCost(1), 10), 1),
+ ast.SeqCostItem(CompanionDesc(BlockValue), PerItemCost(JitCost(1), JitCost(1), 10), 1),
FixedCostItem(ValUse),
FixedCostItem(SelectField),
FixedCostItem(FuncValue.AddToEnvironmentDesc, FixedCost(JitCost(5))),
@@ -8268,7 +8256,7 @@ class SigmaDslSpecification extends SigmaDslTesting
FixedCostItem(SelectField),
FixedCostItem(ValUse),
FixedCostItem(SelectField),
- FixedCostItem(SCollection.GetOrElseMethod, FixedCost(JitCost(30)))
+ FixedCostItem(SCollectionMethods.GetOrElseMethod, FixedCost(JitCost(30)))
)
)
)
@@ -8333,7 +8321,7 @@ class SigmaDslSpecification extends SigmaDslTesting
ValUse(1, SPair(SCollectionType(SInt), SPair(SInt, SInt))),
1.toByte
),
- SCollection.getMethodByName("getOrElse").withConcreteTypes(Map(STypeVar("IV") -> SInt)),
+ SCollectionMethods.getMethodByName("getOrElse").withConcreteTypes(Map(STypeVar("IV") -> SInt)),
Vector(
SelectField.typed[Value[SInt.type]](ValUse(3, SPair(SInt, SInt)), 1.toByte),
SelectField.typed[Value[SInt.type]](ValUse(3, SPair(SInt, SInt)), 2.toByte)
@@ -8407,13 +8395,13 @@ class SigmaDslSpecification extends SigmaDslTesting
if (lowerMethodCallsInTests)
Array(
FixedCostItem(FuncValue),
- SeqCostItem(CompanionDesc(MapCollection), PerItemCost(JitCost(20), JitCost(1), 10), i)
+ ast.SeqCostItem(CompanionDesc(MapCollection), PerItemCost(JitCost(20), JitCost(1), 10), i)
)
else
Array(
FixedCostItem(MethodCall),
FixedCostItem(FuncValue),
- SeqCostItem(MethodDesc(SCollection.MapMethod), PerItemCost(JitCost(20), JitCost(1), 10), i)
+ ast.SeqCostItem(MethodDesc(SCollectionMethods.MapMethod), PerItemCost(JitCost(20), JitCost(1), 10), i)
)
)
++ repeatPlusChunk(i)
@@ -8445,7 +8433,7 @@ class SigmaDslSpecification extends SigmaDslTesting
Array((1, SCollectionType(SInt))),
MethodCall.typed[Value[SCollection[SInt.type]]](
ValUse(1, SCollectionType(SInt)),
- SCollection.getMethodByName("map").withConcreteTypes(
+ SCollectionMethods.getMethodByName("map").withConcreteTypes(
Map(STypeVar("IV") -> SInt, STypeVar("OV") -> SInt)
),
Vector(
@@ -8461,13 +8449,13 @@ class SigmaDslSpecification extends SigmaDslTesting
val costDetails1 = TracedCost(
traceBase ++ Array(
FixedCostItem(FuncValue),
- SeqCostItem(CompanionDesc(MapCollection), PerItemCost(JitCost(20), JitCost(1), 10), 0)
+ ast.SeqCostItem(CompanionDesc(MapCollection), PerItemCost(JitCost(20), JitCost(1), 10), 0)
)
)
val costDetails2 = TracedCost(
traceBase ++ Array(
FixedCostItem(FuncValue),
- SeqCostItem(CompanionDesc(MapCollection), PerItemCost(JitCost(20), JitCost(1), 10), 1),
+ ast.SeqCostItem(CompanionDesc(MapCollection), PerItemCost(JitCost(20), JitCost(1), 10), 1),
FixedCostItem(FuncValue.AddToEnvironmentDesc, FixedCost(JitCost(5))),
FixedCostItem(ValUse),
FixedCostItem(Constant),
@@ -8481,7 +8469,7 @@ class SigmaDslSpecification extends SigmaDslTesting
val costDetails3 = TracedCost(
traceBase ++ Array(
FixedCostItem(FuncValue),
- SeqCostItem(CompanionDesc(MapCollection), PerItemCost(JitCost(20), JitCost(1), 10), 1),
+ ast.SeqCostItem(CompanionDesc(MapCollection), PerItemCost(JitCost(20), JitCost(1), 10), 1),
FixedCostItem(FuncValue.AddToEnvironmentDesc, FixedCost(JitCost(5))),
FixedCostItem(ValUse),
FixedCostItem(Constant),
@@ -8495,7 +8483,7 @@ class SigmaDslSpecification extends SigmaDslTesting
val costDetails4 = TracedCost(
traceBase ++ Array(
FixedCostItem(FuncValue),
- SeqCostItem(CompanionDesc(MapCollection), PerItemCost(JitCost(20), JitCost(1), 10), 2),
+ ast.SeqCostItem(CompanionDesc(MapCollection), PerItemCost(JitCost(20), JitCost(1), 10), 2),
FixedCostItem(FuncValue.AddToEnvironmentDesc, FixedCost(JitCost(5))),
FixedCostItem(ValUse),
FixedCostItem(Constant),
@@ -8563,7 +8551,7 @@ class SigmaDslSpecification extends SigmaDslTesting
traceBase ++
Array(
FixedCostItem(FuncValue),
- SeqCostItem(CompanionDesc(Filter), PerItemCost(JitCost(20), JitCost(1), 10), i)
+ ast.SeqCostItem(CompanionDesc(Filter), PerItemCost(JitCost(20), JitCost(1), 10), i)
) ++
gtChunk
)
@@ -8617,7 +8605,7 @@ class SigmaDslSpecification extends SigmaDslTesting
traceBase ++
Array(
FixedCostItem(FuncValue),
- SeqCostItem(CompanionDesc(Filter), PerItemCost(JitCost(20), JitCost(1), 10), i)
+ ast.SeqCostItem(CompanionDesc(Filter), PerItemCost(JitCost(20), JitCost(1), 10), i)
) ++
repeatLeftBranch(i)
)
@@ -8626,7 +8614,7 @@ class SigmaDslSpecification extends SigmaDslTesting
traceBase ++
Array(
FixedCostItem(FuncValue),
- SeqCostItem(CompanionDesc(Filter), PerItemCost(JitCost(20), JitCost(1), 10), 3)
+ ast.SeqCostItem(CompanionDesc(Filter), PerItemCost(JitCost(20), JitCost(1), 10), 3)
) ++
repeatLeftBranch(2) ++
rightBranch
@@ -8635,7 +8623,7 @@ class SigmaDslSpecification extends SigmaDslTesting
traceBase ++
Array(
FixedCostItem(FuncValue),
- SeqCostItem(CompanionDesc(Filter), PerItemCost(JitCost(20), JitCost(1), 10), 5)
+ ast.SeqCostItem(CompanionDesc(Filter), PerItemCost(JitCost(20), JitCost(1), 10), 5)
) ++
leftBranch ++
rightBranch ++
@@ -8679,7 +8667,7 @@ class SigmaDslSpecification extends SigmaDslTesting
FixedCostItem(GetVar),
FixedCostItem(OptionGet),
FixedCostItem(FuncValue.AddToEnvironmentDesc, FixedCost(JitCost(5))),
- SeqCostItem(CompanionDesc(BlockValue), PerItemCost(JitCost(1), JitCost(1), 10), 1),
+ ast.SeqCostItem(CompanionDesc(BlockValue), PerItemCost(JitCost(1), JitCost(1), 10), 1),
FixedCostItem(ValUse),
FixedCostItem(SelectField),
FixedCostItem(FuncValue.AddToEnvironmentDesc, FixedCost(JitCost(5))),
@@ -8689,7 +8677,7 @@ class SigmaDslSpecification extends SigmaDslTesting
FixedCostItem(SelectField),
FixedCostItem(ValUse),
FixedCostItem(SelectField),
- SeqCostItem(CompanionDesc(Slice), PerItemCost(JitCost(10), JitCost(2), 100), i)
+ ast.SeqCostItem(CompanionDesc(Slice), PerItemCost(JitCost(10), JitCost(2), 100), i)
)
)
val samples = genSamples(collWithRangeGen, DefaultMinSuccessful)
@@ -8762,7 +8750,7 @@ class SigmaDslSpecification extends SigmaDslTesting
ValUse(1, SPair(SCollectionType(SInt), SPair(SInt, SInt))),
1.toByte
),
- SCollection.getMethodByName("slice").withConcreteTypes(Map(STypeVar("IV") -> SInt)),
+ SCollectionMethods.getMethodByName("slice").withConcreteTypes(Map(STypeVar("IV") -> SInt)),
Vector(
SelectField.typed[Value[SInt.type]](ValUse(3, SPair(SInt, SInt)), 1.toByte),
SelectField.typed[Value[SInt.type]](ValUse(3, SPair(SInt, SInt)), 2.toByte)
@@ -8781,7 +8769,7 @@ class SigmaDslSpecification extends SigmaDslTesting
FixedCostItem(SelectField),
FixedCostItem(ValUse),
FixedCostItem(SelectField),
- SeqCostItem(CompanionDesc(Append), PerItemCost(JitCost(20), JitCost(2), 100), i)
+ ast.SeqCostItem(CompanionDesc(Append), PerItemCost(JitCost(20), JitCost(2), 100), i)
)
)
if (lowerMethodCallsInTests) {
@@ -8831,7 +8819,7 @@ class SigmaDslSpecification extends SigmaDslTesting
ValUse(1, SPair(SCollectionType(SInt), SCollectionType(SInt))),
1.toByte
),
- SCollection.getMethodByName("append").withConcreteTypes(Map(STypeVar("IV") -> SInt)),
+ SCollectionMethods.getMethodByName("append").withConcreteTypes(Map(STypeVar("IV") -> SInt)),
Vector(
SelectField.typed[Value[SCollection[SInt.type]]](
ValUse(1, SPair(SCollectionType(SInt), SCollectionType(SInt))),
@@ -8857,14 +8845,14 @@ class SigmaDslSpecification extends SigmaDslTesting
traceBase ++ Array(
FixedCostItem(MethodCall),
FixedCostItem(FuncValue),
- FixedCostItem(SOption.FilterMethod, FixedCost(JitCost(20)))
+ FixedCostItem(SOptionMethods.FilterMethod, FixedCost(JitCost(20)))
)
)
val costDetails5 = TracedCost(
traceBase ++ Array(
FixedCostItem(MethodCall),
FixedCostItem(FuncValue),
- FixedCostItem(SOption.FilterMethod, FixedCost(JitCost(20))),
+ FixedCostItem(SOptionMethods.FilterMethod, FixedCost(JitCost(20))),
FixedCostItem(FuncValue.AddToEnvironmentDesc, FixedCost(JitCost(5))),
FixedCostItem(ValUse),
FixedCostItem(Constant),
@@ -8875,14 +8863,14 @@ class SigmaDslSpecification extends SigmaDslTesting
traceBase ++ Array(
FixedCostItem(MethodCall),
FixedCostItem(FuncValue),
- FixedCostItem(SOption.MapMethod, FixedCost(JitCost(20)))
+ FixedCostItem(SOptionMethods.MapMethod, FixedCost(JitCost(20)))
)
)
val costDetails7 = TracedCost(
traceBase ++ Array(
FixedCostItem(MethodCall),
FixedCostItem(FuncValue),
- FixedCostItem(SOption.MapMethod, FixedCost(JitCost(20))),
+ FixedCostItem(SOptionMethods.MapMethod, FixedCost(JitCost(20))),
FixedCostItem(FuncValue.AddToEnvironmentDesc, FixedCost(JitCost(5))),
FixedCostItem(ValUse),
FixedCostItem(Constant),
@@ -8925,7 +8913,7 @@ class SigmaDslSpecification extends SigmaDslTesting
Vector((1, SOption(SLong))),
MethodCall.typed[Value[SOption[SLong.type]]](
ValUse(1, SOption(SLong)),
- SOption.getMethodByName("filter").withConcreteTypes(Map(STypeVar("T") -> SLong)),
+ SOptionMethods.getMethodByName("filter").withConcreteTypes(Map(STypeVar("T") -> SLong)),
Vector(FuncValue(Vector((3, SLong)), EQ(ValUse(3, SLong), LongConstant(1L)))),
Map()
)
@@ -8943,7 +8931,7 @@ class SigmaDslSpecification extends SigmaDslTesting
Vector((1, SOption(SLong))),
MethodCall.typed[Value[SOption[SLong.type]]](
ValUse(1, SOption(SLong)),
- SOption.getMethodByName("map").withConcreteTypes(
+ SOptionMethods.getMethodByName("map").withConcreteTypes(
Map(STypeVar("T") -> SLong, STypeVar("R") -> SLong)
),
Vector(
@@ -8962,14 +8950,14 @@ class SigmaDslSpecification extends SigmaDslTesting
traceBase ++ Array(
FixedCostItem(MethodCall),
FixedCostItem(FuncValue),
- FixedCostItem(SOption.FilterMethod, FixedCost(JitCost(20)))
+ FixedCostItem(SOptionMethods.FilterMethod, FixedCost(JitCost(20)))
)
)
val costDetails2 = TracedCost(
traceBase ++ Array(
FixedCostItem(MethodCall),
FixedCostItem(FuncValue),
- FixedCostItem(SOption.FilterMethod, FixedCost(JitCost(20))),
+ FixedCostItem(SOptionMethods.FilterMethod, FixedCost(JitCost(20))),
FixedCostItem(FuncValue.AddToEnvironmentDesc, FixedCost(JitCost(5))),
FixedCostItem(ValUse),
FixedCostItem(Constant),
@@ -8982,7 +8970,7 @@ class SigmaDslSpecification extends SigmaDslTesting
traceBase ++ Array(
FixedCostItem(MethodCall),
FixedCostItem(FuncValue),
- FixedCostItem(SOption.FilterMethod, FixedCost(JitCost(20))),
+ FixedCostItem(SOptionMethods.FilterMethod, FixedCost(JitCost(20))),
FixedCostItem(FuncValue.AddToEnvironmentDesc, FixedCost(JitCost(5))),
FixedCostItem(ValUse),
FixedCostItem(Constant),
@@ -9008,7 +8996,7 @@ class SigmaDslSpecification extends SigmaDslTesting
Array((1, SOption(SLong))),
MethodCall.typed[Value[SOption[SLong.type]]](
ValUse(1, SOption(SLong)),
- SOption.getMethodByName("filter").withConcreteTypes(Map(STypeVar("T") -> SLong)),
+ SOptionMethods.getMethodByName("filter").withConcreteTypes(Map(STypeVar("T") -> SLong)),
Vector(
FuncValue(
Array((3, SLong)),
@@ -9027,14 +9015,14 @@ class SigmaDslSpecification extends SigmaDslTesting
traceBase ++ Array(
FixedCostItem(MethodCall),
FixedCostItem(FuncValue),
- FixedCostItem(SOption.MapMethod, FixedCost(JitCost(20)))
+ FixedCostItem(SOptionMethods.MapMethod, FixedCost(JitCost(20)))
)
)
val costDetails5 = TracedCost(
traceBase ++ Array(
FixedCostItem(MethodCall),
FixedCostItem(FuncValue),
- FixedCostItem(SOption.MapMethod, FixedCost(JitCost(20))),
+ FixedCostItem(SOptionMethods.MapMethod, FixedCost(JitCost(20))),
FixedCostItem(FuncValue.AddToEnvironmentDesc, FixedCost(JitCost(5))),
FixedCostItem(ValUse),
FixedCostItem(Constant),
@@ -9047,7 +9035,7 @@ class SigmaDslSpecification extends SigmaDslTesting
traceBase ++ Array(
FixedCostItem(MethodCall),
FixedCostItem(FuncValue),
- FixedCostItem(SOption.MapMethod, FixedCost(JitCost(20))),
+ FixedCostItem(SOptionMethods.MapMethod, FixedCost(JitCost(20))),
FixedCostItem(FuncValue.AddToEnvironmentDesc, FixedCost(JitCost(5))),
FixedCostItem(ValUse),
FixedCostItem(Constant),
@@ -9073,7 +9061,7 @@ class SigmaDslSpecification extends SigmaDslTesting
Array((1, SOption(SLong))),
MethodCall.typed[Value[SOption[SLong.type]]](
ValUse(1, SOption(SLong)),
- SOption.getMethodByName("map").withConcreteTypes(
+ SOptionMethods.getMethodByName("map").withConcreteTypes(
Map(STypeVar("T") -> SLong, STypeVar("R") -> SLong)
),
Vector(
@@ -9185,7 +9173,7 @@ class SigmaDslSpecification extends SigmaDslTesting
property("blake2b256 benchmark: to estimate timeout") {
val cases = (1 to 10).map { i =>
- val block = Colls.fromArray(Array.fill(ErgoTreeEvaluator.DataBlockSize * i)(0.toByte))
+ val block = Colls.fromArray(Array.fill(CErgoTreeEvaluator.DataBlockSize * i)(0.toByte))
block
}
benchmarkCases(cases,
@@ -9197,8 +9185,8 @@ class SigmaDslSpecification extends SigmaDslTesting
}
property("blake2b256, sha256 equivalence") {
- def costDetailsBlake(i: Int) = TracedCost(traceBase :+ SeqCostItem(CompanionDesc(CalcBlake2b256), PerItemCost(JitCost(20), JitCost(7), 128), i))
- def costDetailsSha(i: Int) = TracedCost(traceBase :+ SeqCostItem(CompanionDesc(CalcSha256), PerItemCost(JitCost(80), JitCost(8), 64), i))
+ def costDetailsBlake(i: Int) = TracedCost(traceBase :+ ast.SeqCostItem(CompanionDesc(CalcBlake2b256), PerItemCost(JitCost(20), JitCost(7), 128), i))
+ def costDetailsSha(i: Int) = TracedCost(traceBase :+ ast.SeqCostItem(CompanionDesc(CalcSha256), PerItemCost(JitCost(80), JitCost(8), 64), i))
verifyCases(
Seq(
@@ -9269,7 +9257,7 @@ class SigmaDslSpecification extends SigmaDslTesting
FixedCostItem(Constant),
TypeBasedCostItem(ArithOp.Minus, SInt),
FixedCostItem(ValUse),
- SeqCostItem(CompanionDesc(AtLeast), PerItemCost(JitCost(20), JitCost(3), 5), i)
+ ast.SeqCostItem(CompanionDesc(AtLeast), PerItemCost(JitCost(20), JitCost(3), 5), i)
)
)
@@ -9333,11 +9321,11 @@ class SigmaDslSpecification extends SigmaDslTesting
FixedCostItem(SelectField)
)
- val costDetails1 = TracedCost(testTraceBase :+ SeqCostItem(CompanionDesc(SigmaAnd), PerItemCost(JitCost(10), JitCost(2), 1), 2))
+ val costDetails1 = TracedCost(testTraceBase :+ ast.SeqCostItem(CompanionDesc(SigmaAnd), PerItemCost(JitCost(10), JitCost(2), 1), 2))
val costDetails2 = TracedCost(
testTraceBase ++ Array(
FixedCostItem(BoolToSigmaProp),
- SeqCostItem(CompanionDesc(SigmaAnd), PerItemCost(JitCost(10), JitCost(2), 1), 2)
+ ast.SeqCostItem(CompanionDesc(SigmaAnd), PerItemCost(JitCost(10), JitCost(2), 1), 2)
)
)
@@ -9415,7 +9403,7 @@ class SigmaDslSpecification extends SigmaDslTesting
FixedCostItem(SelectField)
)
- val costDetails1 = TracedCost(testTraceBase :+ SeqCostItem(CompanionDesc(SigmaOr), PerItemCost(JitCost(10), JitCost(2), 1), 2))
+ val costDetails1 = TracedCost(testTraceBase :+ ast.SeqCostItem(CompanionDesc(SigmaOr), PerItemCost(JitCost(10), JitCost(2), 1), 2))
verifyCases(
{
def success[T](v: T, newCost: Int) = Expected(Success(v), newCost, costDetails1, newCost)
@@ -9462,7 +9450,7 @@ class SigmaDslSpecification extends SigmaDslTesting
val costDetails2 = TracedCost(
testTraceBase ++ Array(
FixedCostItem(BoolToSigmaProp),
- SeqCostItem(CompanionDesc(SigmaOr), PerItemCost(JitCost(10), JitCost(2), 1), 2)
+ ast.SeqCostItem(CompanionDesc(SigmaOr), PerItemCost(JitCost(10), JitCost(2), 1), 2)
)
)
verifyCases(
@@ -9524,7 +9512,7 @@ class SigmaDslSpecification extends SigmaDslTesting
"0008980204cd039d0b1e46c21540d033143440d2fb7dd5d650cf89981c99ee53c6e0374d2b1b6fce03c046fccb95549910767d0543f5e8ce41d66ae6a8720a46f4049cac3b3d26dafb023479c9c3b86a0d3c8be3db0a2d186788e9af1db76d55f3dad127d15185d83d0303d7898641cb6653585a8e1dabfa7f665e61e0498963e329e6e3744bd764db2d72037ae057d89ec0b46ff8e9ff4c37e85c12acddb611c3f636421bef1542c11b04419702cd039d0b1e46c21540d033143440d2fb7dd5d650cf89981c99ee53c6e0374d2b1b6fce03c046fccb95549910767d0543f5e8ce41d66ae6a8720a46f4049cac3b3d26dafb023479c9c3b86a0d3c8be3db0a2d186788e9af1db76d55f3dad127d15185d83d0303d7898641cb6653585a8e1dabfa7f665e61e0498963e329e6e3744bd764db2d72037ae057d89ec0b46ff8e9ff4c37e85c12acddb611c3f636421bef1542c11b04419602cd039d0b1e46c21540d033143440d2fb7dd5d650cf89981c99ee53c6e0374d2b1b6fce03c046fccb95549910767d0543f5e8ce41d66ae6a8720a46f4049cac3b3d26dafb023479c9c3b86a0d3c8be3db0a2d186788e9af1db76d55f3dad127d15185d83d0303d7898641cb6653585a8e1dabfa7f665e61e0498963e329e6e3744bd764db2d72037ae057d89ec0b46ff8e9ff4c37e85c12acddb611c3f636421bef1542c11b0441"
)
), cost = 1780, newDetails(18), expectedNewCost = 1780),
- CSigmaProp(COR(Array(pk, dht, and, or, threshold))) -> Expected(Success(
+ CSigmaProp(data.COR(Array(pk, dht, and, or, threshold))) -> Expected(Success(
Helpers.decodeBytes(
"00089705cd039d0b1e46c21540d033143440d2fb7dd5d650cf89981c99ee53c6e0374d2b1b6fce03c046fccb95549910767d0543f5e8ce41d66ae6a8720a46f4049cac3b3d26dafb023479c9c3b86a0d3c8be3db0a2d186788e9af1db76d55f3dad127d15185d83d0303d7898641cb6653585a8e1dabfa7f665e61e0498963e329e6e3744bd764db2d72037ae057d89ec0b46ff8e9ff4c37e85c12acddb611c3f636421bef1542c11b04419602cd039d0b1e46c21540d033143440d2fb7dd5d650cf89981c99ee53c6e0374d2b1b6fce03c046fccb95549910767d0543f5e8ce41d66ae6a8720a46f4049cac3b3d26dafb023479c9c3b86a0d3c8be3db0a2d186788e9af1db76d55f3dad127d15185d83d0303d7898641cb6653585a8e1dabfa7f665e61e0498963e329e6e3744bd764db2d72037ae057d89ec0b46ff8e9ff4c37e85c12acddb611c3f636421bef1542c11b04419702cd039d0b1e46c21540d033143440d2fb7dd5d650cf89981c99ee53c6e0374d2b1b6fce03c046fccb95549910767d0543f5e8ce41d66ae6a8720a46f4049cac3b3d26dafb023479c9c3b86a0d3c8be3db0a2d186788e9af1db76d55f3dad127d15185d83d0303d7898641cb6653585a8e1dabfa7f665e61e0498963e329e6e3744bd764db2d72037ae057d89ec0b46ff8e9ff4c37e85c12acddb611c3f636421bef1542c11b0441980204cd039d0b1e46c21540d033143440d2fb7dd5d650cf89981c99ee53c6e0374d2b1b6fce03c046fccb95549910767d0543f5e8ce41d66ae6a8720a46f4049cac3b3d26dafb023479c9c3b86a0d3c8be3db0a2d186788e9af1db76d55f3dad127d15185d83d0303d7898641cb6653585a8e1dabfa7f665e61e0498963e329e6e3744bd764db2d72037ae057d89ec0b46ff8e9ff4c37e85c12acddb611c3f636421bef1542c11b04419702cd039d0b1e46c21540d033143440d2fb7dd5d650cf89981c99ee53c6e0374d2b1b6fce03c046fccb95549910767d0543f5e8ce41d66ae6a8720a46f4049cac3b3d26dafb023479c9c3b86a0d3c8be3db0a2d186788e9af1db76d55f3dad127d15185d83d0303d7898641cb6653585a8e1dabfa7f665e61e0498963e329e6e3744bd764db2d72037ae057d89ec0b46ff8e9ff4c37e85c12acddb611c3f636421bef1542c11b04419602cd039d0b1e46c21540d033143440d2fb7dd5d650cf89981c99ee53c6e0374d2b1b6fce03c046fccb95549910767d0543f5e8ce41d66ae6a8720a46f4049cac3b3d26dafb023479c9c3b86a0d3c8be3db0a2d186788e9af1db76d55f3dad127d15185d83d0303d7898641cb6653585a8e1dabfa7f665e61e0498963e329e6e3744bd764db2d72037ae057d89ec0b46ff8e9ff4c37e85c12acddb611c3f636421bef1542c11b0441"
)
@@ -9556,7 +9544,7 @@ class SigmaDslSpecification extends SigmaDslTesting
}
property("allOf equivalence") {
- def costDetails(i: Int) = TracedCost(traceBase :+ SeqCostItem(CompanionDesc(AND), PerItemCost(JitCost(10), JitCost(5), 32), i))
+ def costDetails(i: Int) = TracedCost(traceBase :+ ast.SeqCostItem(CompanionDesc(AND), PerItemCost(JitCost(10), JitCost(5), 32), i))
verifyCases(
Seq(
(Coll[Boolean]() -> Expected(Success(true), 1765, costDetails(0), 1765)),
@@ -9577,7 +9565,7 @@ class SigmaDslSpecification extends SigmaDslTesting
}
property("anyOf equivalence") {
- def costDetails(i: Int) = TracedCost(traceBase :+ SeqCostItem(CompanionDesc(OR), PerItemCost(JitCost(5), JitCost(5), 64), i))
+ def costDetails(i: Int) = TracedCost(traceBase :+ ast.SeqCostItem(CompanionDesc(OR), PerItemCost(JitCost(5), JitCost(5), 64), i))
verifyCases(
Seq(
(Coll[Boolean]() -> Expected(Success(false), 1764, costDetails(0), 1764)),
@@ -9654,14 +9642,14 @@ class SigmaDslSpecification extends SigmaDslTesting
property("substConstants equivalence") {
// tree without constant segregation
- val t1 = ErgoTree(ErgoTree.DefaultHeader, Vector(), TrueSigmaProp)
+ val t1 = ErgoTree(ErgoTree.ZeroHeader, Vector(), TrueSigmaProp)
// tree with constant segregation, but without constants
- val t2 = ErgoTree(ErgoTree.ConstantSegregationHeader, Vector(), TrueSigmaProp)
+ val t2 = ErgoTree(ErgoTree.setConstantSegregation(ZeroHeader), Vector(), TrueSigmaProp)
// tree with one segregated constant
- val t3 = ErgoTree(ErgoTree.ConstantSegregationHeader, Vector(TrueSigmaProp), ConstantPlaceholder(0, SSigmaProp))
+ val t3 = ErgoTree(ErgoTree.setConstantSegregation(ZeroHeader), Vector(TrueSigmaProp), ConstantPlaceholder(0, SSigmaProp))
// tree with one segregated constant of different type
val t4 = ErgoTree(
- ErgoTree.ConstantSegregationHeader,
+ ErgoTree.setConstantSegregation(ZeroHeader),
Vector(IntConstant(10)),
BoolToSigmaProp(EQ(ConstantPlaceholder(0, SInt), IntConstant(20))))
def costDetails(i: Int) = TracedCost(
@@ -9673,7 +9661,7 @@ class SigmaDslSpecification extends SigmaDslTesting
FixedCostItem(ConcreteCollection),
FixedCostItem(Constant),
FixedCostItem(BoolToSigmaProp),
- SeqCostItem(CompanionDesc(SubstConstants), PerItemCost(JitCost(100), JitCost(100), 1), i)
+ ast.SeqCostItem(CompanionDesc(SubstConstants), PerItemCost(JitCost(100), JitCost(100), 1), i)
)
)
verifyCases(
@@ -9745,22 +9733,22 @@ class SigmaDslSpecification extends SigmaDslTesting
FixedCostItem(GetVar),
FixedCostItem(OptionGet),
FixedCostItem(FuncValue.AddToEnvironmentDesc, FixedCost(JitCost(5))),
- SeqCostItem(CompanionDesc(BlockValue), PerItemCost(JitCost(1), JitCost(1), 10), 1),
+ ast.SeqCostItem(CompanionDesc(BlockValue), PerItemCost(JitCost(1), JitCost(1), 10), 1),
FixedCostItem(ValUse),
FixedCostItem(PropertyCall),
- FixedCostItem(SContext.headersMethod, FixedCost(JitCost(15))),
+ FixedCostItem(SContextMethods.headersMethod, FixedCost(JitCost(15))),
FixedCostItem(FuncValue.AddToEnvironmentDesc, FixedCost(JitCost(5))),
FixedCostItem(ValUse),
FixedCostItem(PropertyCall),
- SeqCostItem(MethodDesc(SCollection.IndicesMethod), PerItemCost(JitCost(20), JitCost(2), 16), 1),
+ ast.SeqCostItem(MethodDesc(SCollectionMethods.IndicesMethod), PerItemCost(JitCost(20), JitCost(2), 16), 1),
FixedCostItem(Constant),
FixedCostItem(ValUse),
FixedCostItem(SizeOf),
FixedCostItem(Constant),
TypeBasedCostItem(ArithOp.Minus, SInt),
- SeqCostItem(CompanionDesc(Slice), PerItemCost(JitCost(10), JitCost(2), 100), 0),
+ ast.SeqCostItem(CompanionDesc(Slice), PerItemCost(JitCost(10), JitCost(2), 100), 0),
FixedCostItem(FuncValue),
- SeqCostItem(CompanionDesc(ForAll), PerItemCost(JitCost(3), JitCost(1), 10), 0)
+ ast.SeqCostItem(CompanionDesc(ForAll), PerItemCost(JitCost(3), JitCost(1), 10), 0)
)
)
@@ -9811,7 +9799,7 @@ class SigmaDslSpecification extends SigmaDslTesting
List(),
MethodCall.typed[Value[SCollection[SHeader.type]]](
ValUse(1, SContext),
- SContext.getMethodByName("headers"),
+ SContextMethods.getMethodByName("headers"),
Vector(),
Map()
)
@@ -9821,7 +9809,7 @@ class SigmaDslSpecification extends SigmaDslTesting
Slice(
MethodCall.typed[Value[SCollection[SInt.type]]](
ValUse(3, SCollectionType(SHeader)),
- SCollection.getMethodByName("indices").withConcreteTypes(Map(STypeVar("IV") -> SHeader)),
+ SCollectionMethods.getMethodByName("indices").withConcreteTypes(Map(STypeVar("IV") -> SHeader)),
Vector(),
Map()
),
@@ -9842,7 +9830,7 @@ class SigmaDslSpecification extends SigmaDslTesting
Array((6, SHeader)),
MethodCall.typed[Value[SCollection[SByte.type]]](
ValUse(6, SHeader),
- SHeader.getMethodByName("parentId"),
+ SHeaderMethods.getMethodByName("parentId"),
Vector(),
Map()
)
@@ -9858,7 +9846,7 @@ class SigmaDslSpecification extends SigmaDslTesting
Array((6, SHeader)),
MethodCall.typed[Value[SCollection[SByte.type]]](
ValUse(6, SHeader),
- SHeader.getMethodByName("id"),
+ SHeaderMethods.getMethodByName("id"),
Vector(),
Map()
)
@@ -9921,7 +9909,7 @@ class SigmaDslSpecification extends SigmaDslTesting
ValUse(3, SPair(SByteArray, SByteArray)),
1.toByte
),
- SCollection.getMethodByName("zip").withConcreteTypes(
+ SCollectionMethods.getMethodByName("zip").withConcreteTypes(
Map(STypeVar("IV") -> SByte, STypeVar("OV") -> SByte)
),
Vector(
@@ -9961,7 +9949,7 @@ class SigmaDslSpecification extends SigmaDslTesting
ValUse(1, SPair(SByteArray2, SByteArray)),
1.toByte
),
- SCollection.getMethodByName("fold").withConcreteTypes(Map(STypeVar("IV") -> SCollection(SByte), STypeVar("OV") -> SCollection(SByte))),
+ SCollectionMethods.getMethodByName("fold").withConcreteTypes(Map(STypeVar("IV") -> SCollection(SByte), STypeVar("OV") -> SCollection(SByte))),
Vector(
SelectField.typed[Value[SCollection[SByte.type]]](
ValUse(1, SPair(SByteArray2, SByteArray)),
@@ -9975,7 +9963,7 @@ class SigmaDslSpecification extends SigmaDslTesting
ValUse(3, SPair(SByteArray, SByteArray)),
1.toByte
),
- SCollection.getMethodByName("zip").withConcreteTypes(
+ SCollectionMethods.getMethodByName("zip").withConcreteTypes(
Map(STypeVar("IV") -> SByte, STypeVar("OV") -> SByte)
),
Vector(
@@ -9986,7 +9974,7 @@ class SigmaDslSpecification extends SigmaDslTesting
),
Map()
),
- SCollection.getMethodByName("map").withConcreteTypes(
+ SCollectionMethods.getMethodByName("map").withConcreteTypes(
Map(STypeVar("IV") -> SPair(SByte, SByte), STypeVar("OV") -> SByte)
),
Vector(
@@ -10031,12 +10019,12 @@ class SigmaDslSpecification extends SigmaDslTesting
// TODO v6.0: Add support of SFunc in TypeSerializer (see https://github.com/ScorexFoundation/sigmastate-interpreter/issues/847)
assertExceptionThrown(
f.verifyCase(Coll[Int](), Expected(Success(Coll[Int]()), 0)),
- exceptionLike[MatchError]("(SInt$) => SInt$ (of class sigmastate.SFunc)")
+ exceptionLike[MatchError]("(SInt$) => SInt$ (of class sigma.ast.SFunc)")
)
}
override protected def afterAll(): Unit = {
- printDebug(ErgoTreeEvaluator.DefaultProfiler.generateReport)
+ printDebug(CErgoTreeEvaluator.DefaultProfiler.generateReport)
printDebug("==========================================================")
printDebug(Interpreter.verifySignatureProfiler.generateReport)
printDebug("==========================================================")
diff --git a/sc/shared/src/test/scala/sigma/SigmaDslStaginTests.scala b/sc/shared/src/test/scala/sigma/SigmaDslStaginTests.scala
index ea29c47745..5ac9b80889 100644
--- a/sc/shared/src/test/scala/sigma/SigmaDslStaginTests.scala
+++ b/sc/shared/src/test/scala/sigma/SigmaDslStaginTests.scala
@@ -2,9 +2,9 @@ package sigma
import org.scalatest.BeforeAndAfterAll
import scalan.{BaseCtxTests, BaseLiftableTests}
-import sigmastate.eval.Extensions._
+import sigma.data.TrivialProp
+import sigma.eval.Extensions.toAnyValue
import sigmastate.eval._
-import sigmastate.{TrivialProp, eval}
import scala.language.reflectiveCalls
@@ -23,7 +23,7 @@ class SigmaDslStaginTests extends BaseCtxTests with ErgoScriptTestkit with BaseL
import SigmaDslBuilder._
import SigmaProp._
- val dsl: SSigmaDslBuilder = eval.SigmaDsl
+ val dsl: SSigmaDslBuilder = sigma.eval.SigmaDsl
type RSigmaDslBuilder = cake.SigmaDslBuilder
type RContext = cake.Context
type RBox = cake.Box
@@ -33,8 +33,8 @@ class SigmaDslStaginTests extends BaseCtxTests with ErgoScriptTestkit with BaseL
val ctx: SContext = newContext(10, boxA1, VersionContext.MaxSupportedScriptVersion, VersionContext.MaxSupportedScriptVersion)
.withInputs(boxA2)
.withVariables(Map(1 -> toAnyValue(30), 2 -> toAnyValue(40)))
- val p1: SSigmaProp = eval.SigmaDsl.SigmaProp(TrivialProp(true))
- val p2: SSigmaProp = eval.SigmaDsl.SigmaProp(TrivialProp(false))
+ val p1: SSigmaProp = sigma.eval.SigmaDsl.SigmaProp(TrivialProp(true))
+ val p2: SSigmaProp = sigma.eval.SigmaDsl.SigmaProp(TrivialProp(false))
cake.check(dsl, { env: EnvRep[RSigmaDslBuilder] =>
for { dsl <- env; arg <- lifted(true) } yield dsl.sigmaProp(arg) }, dsl.sigmaProp(true))
diff --git a/sc/shared/src/test/scala/sigma/SigmaDslTesting.scala b/sc/shared/src/test/scala/sigma/SigmaDslTesting.scala
index 4aff49761e..46222d9fb1 100644
--- a/sc/shared/src/test/scala/sigma/SigmaDslTesting.scala
+++ b/sc/shared/src/test/scala/sigma/SigmaDslTesting.scala
@@ -3,8 +3,7 @@ package sigma
import debox.cfor
import org.ergoplatform._
import org.ergoplatform.dsl.{ContractSpec, SigmaContractSyntax, TestContractSpec}
-import org.ergoplatform.validation.ValidationRules.CheckSerializableTypeCode
-import org.ergoplatform.validation.{SigmaValidationSettings, ValidationException, ValidationRules}
+import org.ergoplatform.validation.ValidationRules
import org.scalacheck.Arbitrary._
import org.scalacheck.Gen.frequency
import org.scalacheck.{Arbitrary, Gen}
@@ -13,27 +12,32 @@ import org.scalatest.matchers.should.Matchers
import org.scalatest.propspec.AnyPropSpec
import org.scalatestplus.scalacheck.ScalaCheckPropertyChecks
import scalan.Platform.threadSleepOrNoOp
-import sigma.data.{CollType, OptionType, PairType, RType}
+import sigma.Extensions.ArrayOps
+import sigma.data.{CBox, CollType, OptionType, PairType, ProveDlog, RType, SigmaLeaf}
import sigma.util.BenchmarkUtil
import sigma.util.CollectionUtil._
import sigma.util.Extensions._
import sigma.util.StringUtil.StringUtilExtensions
-import sigmastate.SType.AnyOps
-import sigmastate.Values.{ByteArrayConstant, Constant, ConstantNode, ErgoTree, IntConstant, SValue}
-import sigmastate.crypto.DLogProtocol.{DLogProverInput, ProveDlog}
+import sigma.ast.ErgoTree.ZeroHeader
+import sigma.ast.SType.AnyOps
+import sigma.ast.syntax.{SValue, ValueOps}
+import sigma.ast._
+import sigma.eval.{CostDetails, EvalSettings, SigmaDsl}
+import sigmastate.crypto.DLogProtocol.DLogProverInput
import sigmastate.crypto.SigmaProtocolPrivateInput
-import sigmastate.eval.Extensions._
-import sigmastate.eval.{CompiletimeIRContext, CostingBox, CostingDataContext, Evaluation, IRContext, SigmaDsl}
+import sigmastate.eval.{CContext, CompiletimeIRContext, IRContext}
import sigmastate.helpers.TestingHelpers._
import sigmastate.helpers.{CompilerTestingCommons, ErgoLikeContextTesting, ErgoLikeTestInterpreter, SigmaPPrint}
import sigmastate.interpreter.Interpreter.{ScriptEnv, VerificationResult}
import sigmastate.interpreter._
-import sigmastate.lang.Terms.{Apply, ValueOps}
-import sigmastate.serialization.ValueSerializer
-import sigmastate.serialization.generators.ObjectGenerators
+import sigma.ast.Apply
+import sigma.eval.Extensions.SigmaBooleanOps
+import sigma.interpreter.{ContextExtension, ProverResult}
+import sigma.serialization.ValueSerializer
+import sigma.serialization.generators.ObjectGenerators
import sigmastate.utils.Helpers._
-import sigmastate.utxo.{DeserializeContext, DeserializeRegister, GetVar, OptionGet}
-import sigmastate.{SOption, SSigmaProp, SType, SigmaLeaf, eval}
+import sigma.validation.ValidationRules.CheckSerializableTypeCode
+import sigma.validation.{SigmaValidationSettings, ValidationException}
import scala.collection.mutable
import scala.reflect.ClassTag
@@ -254,11 +258,11 @@ class SigmaDslTesting extends AnyPropSpec
}
}
- /** Creates a new ErgoLikeContext using given [[CostingDataContext]] as template.
+ /** Creates a new ErgoLikeContext using given [[CContext]] as template.
* Copies most of the data from ctx and the missing data is taken from the args.
* This is a helper method to be used in tests only.
*/
- def createErgoLikeContext(ctx: CostingDataContext,
+ def createErgoLikeContext(ctx: CContext,
validationSettings: SigmaValidationSettings,
costLimit: Long,
initCost: Long
@@ -313,43 +317,43 @@ class SigmaDslTesting extends AnyPropSpec
""".stripMargin
val IR = new CompiletimeIRContext
- val pkAlice = prover.pubKeys.head.toSigmaProp
+ val pkAlice = prover.pubKeys.head.toSigmaPropValue
val env = Map("pkAlice" -> pkAlice)
// 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
- val multisig = sigmastate.AtLeast(
+ val multisig = AtLeast(
IntConstant(2),
Array(
pkAlice,
DeserializeRegister(ErgoBox.R5, SSigmaProp), // deserialize pkBob
DeserializeContext(2, SSigmaProp))) // deserialize pkCarol
- val header = ErgoTree.headerWithVersion(ergoTreeVersionInTests)
- ErgoTree.withSegregation(header, sigmastate.SigmaOr(prop, multisig))
+ val header = ErgoTree.headerWithVersion(ZeroHeader, ergoTreeVersionInTests)
+ ErgoTree.withSegregation(header, SigmaOr(prop, multisig))
}
def ergoCtx(prover: FeatureProvingInterpreter, compiledTree: ErgoTree, expectedValue: B) = {
- val pkBobBytes = ValueSerializer.serialize(prover.pubKeys(1).toSigmaProp)
- val pkCarolBytes = ValueSerializer.serialize(prover.pubKeys(2).toSigmaProp)
+ val pkBobBytes = ValueSerializer.serialize(prover.pubKeys(1).toSigmaPropValue)
+ val pkCarolBytes = ValueSerializer.serialize(prover.pubKeys(2).toSigmaPropValue)
val newRegisters = Map(
ErgoBox.R4 -> Constant[SType](expectedValue.asInstanceOf[SType#WrappedType], tpeB),
ErgoBox.R5 -> ByteArrayConstant(pkBobBytes)
)
val ctx = input match {
- case ctx: CostingDataContext =>
+ case ctx: CContext =>
// the context is passed as function argument (see func in the script)
// Since Context is singleton, we should use this instance as the basis
// for execution of verify instead of a new dummy context.
- val self = ctx.selfBox.asInstanceOf[CostingBox]
+ val self = ctx.selfBox.asInstanceOf[CBox]
val newSelf = self.copy(
ebox = updatedRegisters(self.ebox, newRegisters)
)
// We add ctx as it's own variable with id = 1
- val ctxVar = eval.Extensions.toAnyValue[sigma.Context](ctx)(sigma.ContextRType)
- val carolVar = eval.Extensions.toAnyValue[Coll[Byte]](pkCarolBytes.toColl)(RType[Coll[Byte]])
+ val ctxVar = sigma.eval.Extensions.toAnyValue[sigma.Context](ctx)(sigma.ContextRType)
+ val carolVar = sigma.eval.Extensions.toAnyValue[Coll[Byte]](pkCarolBytes.toColl)(RType[Coll[Byte]])
val newCtx = ctx
.withUpdatedVars(1 -> ctxVar, 2 -> carolVar)
.copy(
@@ -458,7 +462,7 @@ class SigmaDslTesting extends AnyPropSpec
}
/** A number of times the newF function in each test feature is repeated.
- * In combination with [[sigmastate.eval.Profiler]] it allows to collect more accurate
+ * In combination with [[sigmastate.eval.CProfiler]] it allows to collect more accurate
* timings for all operations.
* @see SigmaDslSpecification */
def nBenchmarkIters: Int = 0
diff --git a/sc/shared/src/test/scala/sigmastate/CompilerTestsBase.scala b/sc/shared/src/test/scala/sigmastate/CompilerTestsBase.scala
index cd7e15b841..28f907c199 100644
--- a/sc/shared/src/test/scala/sigmastate/CompilerTestsBase.scala
+++ b/sc/shared/src/test/scala/sigmastate/CompilerTestsBase.scala
@@ -1,13 +1,14 @@
package sigmastate
import scala.util.DynamicVariable
-import sigmastate.lang.{TransformingSigmaBuilder, CompilerResult, CompilerSettings, SigmaCompiler}
+import sigmastate.lang.{CompilerResult, CompilerSettings, SigmaCompiler}
import sigmastate.interpreter.Interpreter.ScriptEnv
-import sigmastate.Values.{SigmaPropValue, SValue, Value, ErgoTree}
+import sigma.ast.{ErgoTree, SType, TransformingSigmaBuilder, Value}
import org.ergoplatform.ErgoAddressEncoder.TestnetNetworkPrefix
-import sigmastate.serialization.ValueSerializer
+import sigma.ast.syntax.{SValue, SigmaPropValue}
+import sigma.serialization.ValueSerializer
import sigmastate.eval.IRContext
-import sigmastate.lang.Terms.ValueOps
+import sigma.ast.syntax.ValueOps
trait CompilerTestsBase extends TestsBase {
protected val _lowerMethodCalls = new DynamicVariable[Boolean](true)
diff --git a/sc/shared/src/test/scala/sigmastate/ErgoTreeSpecification.scala b/sc/shared/src/test/scala/sigmastate/ErgoTreeSpecification.scala
index 23406d9cb4..b0b6273fad 100644
--- a/sc/shared/src/test/scala/sigmastate/ErgoTreeSpecification.scala
+++ b/sc/shared/src/test/scala/sigmastate/ErgoTreeSpecification.scala
@@ -1,26 +1,28 @@
-package sigmastate
+package sigma
import org.ergoplatform.settings.ErgoAlgos
-import org.ergoplatform.validation.{ValidationException, ValidationRules}
-import org.ergoplatform.{ErgoAddressEncoder, ErgoBox, ErgoLikeContext, Self}
-import sigma.data.RType.asType
-import sigma.data.{Nullable, RType}
-import sigma.VersionContext
-import sigmastate.SCollection.{SByteArray, checkValidFlatmap}
-import sigmastate.Values._
+import org.ergoplatform.{ErgoAddressEncoder, ErgoBox, ErgoLikeContext}
import sigma.VersionContext._
-import sigmastate.eval.{CostingBox, Evaluation, Profiler}
-import sigmastate.exceptions.{CostLimitException, InterpreterException}
+import sigma.ast.SCollection.SByteArray
+import sigma.ast._
+import sigma.ast.syntax.{SValue, SigmaPropValue, TrueSigmaProp}
+import sigma.data.RType.asType
+import sigma.data.{CBox, Nullable, RType, TrivialProp}
+import sigma.validation.ValidationException
+import sigma.validation.ValidationRules.CheckTypeCode
+import ErgoTree.HeaderType
+import SCollectionMethods.checkValidFlatmap
+import sigmastate.eval.CProfiler
import sigmastate.helpers.{ErgoLikeContextTesting, SigmaPPrint}
-import sigmastate.interpreter.{ErgoTreeEvaluator, EvalSettings}
import sigmastate.interpreter.Interpreter.ReductionResult
-import sigmastate.lang.{CompilerSettings, SourceContext}
-import sigmastate.lang.Terms._
-import sigmastate.serialization.ErgoTreeSerializer.DefaultSerializer
+import sigmastate.interpreter.CErgoTreeEvaluator
+import sigma.ast.syntax._
+import sigma.eval.EvalSettings
+import sigma.exceptions.{CostLimitException, InterpreterException}
+import sigmastate.lang.CompilerSettings
+import sigma.serialization.ErgoTreeSerializer.DefaultSerializer
+import sigmastate.Plus
import sigmastate.utils.Helpers.TryOps
-import sigmastate.utxo._
-import sigma._
-import sigma.{ContractsTestkit, SigmaDslTesting}
/** Regression tests with ErgoTree related test vectors.
@@ -46,7 +48,6 @@ class ErgoTreeSpecification extends SigmaDslTesting with ContractsTestkit {
Block(Seq(), null),
ValNode("x", SInt, null),
ApplyTypes(null, Seq()),
- TaggedVariableNode(1, SByte),
ValDef(1, null),
ValUse(1, SInt),
BlockValue(IndexedSeq(), null)
@@ -59,15 +60,15 @@ class ErgoTreeSpecification extends SigmaDslTesting with ContractsTestkit {
property("ErgoTree.toProposition") {
val t1 = new ErgoTree(
- 16.toByte,
+ HeaderType @@ 16.toByte,
Array(IntConstant(1)),
Right(BoolToSigmaProp(EQ(ConstantPlaceholder(0, SInt), IntConstant(1))))
)
val t = new ErgoTree(
- 16.toByte,
+ HeaderType @@ 16.toByte,
Array(IntConstant(1)),
- Left(UnparsedErgoTree(t1.bytes, ValidationException("", ValidationRules.CheckTypeCode, Seq())))
+ Left(UnparsedErgoTree(t1.bytes, ValidationException("", CheckTypeCode, Seq())))
)
assertExceptionThrown(
t.toProposition(true),
@@ -78,7 +79,7 @@ class ErgoTreeSpecification extends SigmaDslTesting with ContractsTestkit {
property("ErgoTree.template") {
{
val t = new ErgoTree(
- 16.toByte,
+ HeaderType @@ 16.toByte,
Array(IntConstant(1)),
Right(BoolToSigmaProp(EQ(ConstantPlaceholder(0, SInt), IntConstant(1))))
)
@@ -93,7 +94,7 @@ class ErgoTreeSpecification extends SigmaDslTesting with ContractsTestkit {
property("ErgoTree.bytes") {
val t = new ErgoTree(
- 16.toByte,
+ HeaderType @@ 16.toByte,
Array(IntConstant(1)),
Right(BoolToSigmaProp(EQ(ConstantPlaceholder(0, SInt), IntConstant(1))))
)
@@ -111,7 +112,7 @@ class ErgoTreeSpecification extends SigmaDslTesting with ContractsTestkit {
Value.hasDeserialize(EQ(const, dc)) shouldBe true
Value.hasDeserialize(Plus(Plus(const, dc), dr)) shouldBe true
val t = new ErgoTree(
- 16.toByte,
+ HeaderType @@ 16.toByte,
Array(IntConstant(1)),
Right(BoolToSigmaProp(EQ(ConstantPlaceholder(0, SInt), IntConstant(1))))
)
@@ -121,7 +122,7 @@ class ErgoTreeSpecification extends SigmaDslTesting with ContractsTestkit {
property("ErgoTree.hasDeserialize") {
{
val t = new ErgoTree(
- 0.toByte,
+ HeaderType @@ 0.toByte,
Array[Constant[SType]](),
Right(TrueSigmaProp))
t._hasDeserialize shouldBe None
@@ -130,7 +131,7 @@ class ErgoTreeSpecification extends SigmaDslTesting with ContractsTestkit {
{
val t = new ErgoTree(
- 16.toByte,
+ HeaderType @@ 16.toByte,
Array(IntConstant(1)),
Right(BoolToSigmaProp(EQ(ConstantPlaceholder(0, SInt), DeserializeContext(1.toByte, SInt))))
)
@@ -139,15 +140,113 @@ class ErgoTreeSpecification extends SigmaDslTesting with ContractsTestkit {
}
}
+ property("ErgoTree.isUsingBlockchainContext") {
+ {
+ val t = new ErgoTree(
+ HeaderType @@ 0.toByte,
+ Array[Constant[SType]](),
+ Right(TrueSigmaProp))
+ t._isUsingBlockchainContext shouldBe None
+ t.isUsingBlockchainContext shouldBe false
+ }
+
+ {
+ val t = new ErgoTree(
+ HeaderType @@ 16.toByte,
+ Array(IntConstant(1)),
+ Right(BoolToSigmaProp(GT(Height, ConstantPlaceholder(0, SInt))))
+ )
+ t._isUsingBlockchainContext shouldBe None
+ t.isUsingBlockchainContext shouldBe true
+ }
+
+ {
+ val t = new ErgoTree(
+ HeaderType @@ 16.toByte,
+ Vector(),
+ Right(OptionIsDefined(IR.builder.mkMethodCall(
+ LastBlockUtxoRootHash, SAvlTreeMethods.getMethod,
+ IndexedSeq(ExtractId(GetVarBox(22: Byte).get), GetVarByteArray(23: Byte).get)).asOption[SByteArray]))
+ )
+ t._isUsingBlockchainContext shouldBe None
+ t.isUsingBlockchainContext shouldBe true
+ }
+
+ {
+ val t = new ErgoTree(
+ HeaderType @@ 16.toByte,
+ Vector(),
+ Right(BoolToSigmaProp(EQ(MinerPubkey, ErgoLikeContextTesting.dummyPubkey)))
+ )
+ t._isUsingBlockchainContext shouldBe None
+ t.isUsingBlockchainContext shouldBe true
+ }
+
+ {
+ val t = new ErgoTree(
+ HeaderType @@ 16.toByte,
+ Vector(),
+ Right(OptionIsDefined(IR.builder.mkMethodCall(
+ Context, SContextMethods.headersMethod, Vector()).asOption[SByteArray]))
+ )
+ t._isUsingBlockchainContext shouldBe None
+ t.isUsingBlockchainContext shouldBe true
+ }
+
+ {
+ val t = new ErgoTree(
+ HeaderType @@ 16.toByte,
+ Vector(),
+ Right(OptionIsDefined(IR.builder.mkMethodCall(
+ Context, SContextMethods.preHeaderMethod, Vector()).asOption[SByteArray]))
+ )
+ t._isUsingBlockchainContext shouldBe None
+ t.isUsingBlockchainContext shouldBe true
+ }
+
+ {
+ val t = new ErgoTree(
+ HeaderType @@ 16.toByte,
+ Vector(),
+ Right(OptionIsDefined(IR.builder.mkMethodCall(
+ Context, SContextMethods.heightMethod, Vector()).asOption[SByteArray]))
+ )
+ t._isUsingBlockchainContext shouldBe None
+ t.isUsingBlockchainContext shouldBe true
+ }
+
+ {
+ val t = new ErgoTree(
+ HeaderType @@ 16.toByte,
+ Vector(),
+ Right(OptionIsDefined(IR.builder.mkMethodCall(
+ Context, SContextMethods.lastBlockUtxoRootHashMethod, Vector()).asOption[SByteArray]))
+ )
+ t._isUsingBlockchainContext shouldBe None
+ t.isUsingBlockchainContext shouldBe true
+ }
+
+ {
+ val t = new ErgoTree(
+ HeaderType @@ 16.toByte,
+ Vector(),
+ Right(OptionIsDefined(IR.builder.mkMethodCall(
+ Context, SContextMethods.minerPubKeyMethod, Vector()).asOption[SByteArray]))
+ )
+ t._isUsingBlockchainContext shouldBe None
+ t.isUsingBlockchainContext shouldBe true
+ }
+ }
+
property("ErgoTree equality") {
val t1 = new ErgoTree(
- 16.toByte,
+ HeaderType @@ 16.toByte,
Array(IntConstant(1)),
Right(BoolToSigmaProp(EQ(ConstantPlaceholder(0, SInt), IntConstant(1))))
)
- val t2 = new ErgoTree(16.toByte, Array(IntConstant(1)), Right(TrueSigmaProp))
- val t3 = new ErgoTree(16.toByte, Array(IntConstant(1)), Right(TrueSigmaProp))
- val t4 = new ErgoTree(16.toByte, Vector(), Right(TrueSigmaProp))
+ val t2 = new ErgoTree(HeaderType @@ 16.toByte, Array(IntConstant(1)), Right(TrueSigmaProp))
+ val t3 = new ErgoTree(HeaderType @@ 16.toByte, Array(IntConstant(1)), Right(TrueSigmaProp))
+ val t4 = new ErgoTree(HeaderType @@ 16.toByte, Vector(), Right(TrueSigmaProp))
val t5 = new ErgoTree(ErgoTree.DefaultHeader, Vector(), Right(TrueSigmaProp))
assert(t1 != t2)
assert(t2 == t3)
@@ -228,14 +327,14 @@ class ErgoTreeSpecification extends SigmaDslTesting with ContractsTestkit {
{ // SNumericType.typeId is erroneously shadowed by SGlobal.typeId
// this should be preserved in v3.x and fixed in v4.0
(SNumericType.typeId, Seq(
- MInfo(methodId = 1, SGlobal.groupGeneratorMethod),
- MInfo(2, SGlobal.xorMethod)
+ MInfo(methodId = 1, SGlobalMethods.groupGeneratorMethod),
+ MInfo(2, SGlobalMethods.xorMethod)
), true)
},
{ // SBigInt inherit methods from SNumericType.methods
// however they are not resolvable via SBigInt.typeId
- import SNumericType._
+ import SNumericTypeMethods._
(SBigInt.typeId, Seq(
MInfo(methodId = 1, ToByteMethod, isResolvableFromIds = false),
MInfo(2, ToShortMethod, isResolvableFromIds = false),
@@ -246,7 +345,7 @@ class ErgoTreeSpecification extends SigmaDslTesting with ContractsTestkit {
MInfo(7, ToBitsMethod, isResolvableFromIds = false)
), true)
},
- { import SGroupElement._
+ { import SGroupElementMethods._
(SGroupElement.typeId, Seq(
MInfo(2, GetEncodedMethod),
MInfo(3, ExponentiateMethod),
@@ -254,13 +353,13 @@ class ErgoTreeSpecification extends SigmaDslTesting with ContractsTestkit {
MInfo(5, NegateMethod)
), true)
},
- { import SSigmaProp._
+ { import SSigmaPropMethods._
(SSigmaProp.typeId, Seq(
MInfo(1, PropBytesMethod),
MInfo(2, IsProvenMethod) // TODO v5.x (3h): this method must be removed (see https://github.com/ScorexFoundation/sigmastate-interpreter/pull/800)
), true)
},
- { import SBox._
+ { import SBoxMethods._
(SBox.typeId, Seq(
MInfo(1, ValueMethod),
MInfo(2, PropositionBytesMethod),
@@ -274,7 +373,7 @@ class ErgoTreeSpecification extends SigmaDslTesting with ContractsTestkit {
.zipWithIndex
.map { case (m,i) => MInfo((8 + i + 1).toByte, m) }, true)
},
- { import SAvlTree._
+ { import SAvlTreeMethods._
(SAvlTree.typeId, Seq(
MInfo(1, digestMethod),
MInfo(2, enabledOperationsMethod),
@@ -293,7 +392,7 @@ class ErgoTreeSpecification extends SigmaDslTesting with ContractsTestkit {
MInfo(15, updateDigestMethod)
), true)
},
- { import SHeader._
+ { import SHeaderMethods._
(SHeader.typeId, Seq(
MInfo(1, idMethod), MInfo(2, versionMethod), MInfo(3, parentIdMethod),
MInfo(4, ADProofsRootMethod), MInfo(5, stateRootMethod), MInfo(6, transactionsRootMethod),
@@ -302,14 +401,14 @@ class ErgoTreeSpecification extends SigmaDslTesting with ContractsTestkit {
MInfo(13, powNonceMethod), MInfo(14, powDistanceMethod), MInfo(15, votesMethod)
), true)
},
- { import SPreHeader._
+ { import SPreHeaderMethods._
(SPreHeader.typeId, Seq(
MInfo(1, versionMethod), MInfo(2, parentIdMethod), MInfo(3, timestampMethod),
MInfo(4, nBitsMethod), MInfo(5, heightMethod), MInfo(6, minerPkMethod),
MInfo(7, votesMethod)
), true)
},
- { import SContext._
+ { import SContextMethods._
(SContext.typeId, Seq(
MInfo(1, dataInputsMethod), MInfo(2, headersMethod), MInfo(3, preHeaderMethod),
MInfo(4, inputsMethod), MInfo(5, outputsMethod), MInfo(6, heightMethod),
@@ -317,12 +416,12 @@ class ErgoTreeSpecification extends SigmaDslTesting with ContractsTestkit {
MInfo(10, minerPubKeyMethod), MInfo(11, getVarMethod)
), true)
},
- { import SGlobal._
+ { import SGlobalMethods._
(SGlobal.typeId, Seq(
MInfo(1, groupGeneratorMethod), MInfo(2, xorMethod)
), true)
},
- { import SCollection._
+ { import SCollectionMethods._
(SCollection.typeId, Seq(
MInfo(1, SizeMethod),
MInfo(2, GetOrElseMethod),
@@ -364,7 +463,7 @@ class ErgoTreeSpecification extends SigmaDslTesting with ContractsTestkit {
*/
), true)
},
- { import SOption._
+ { import SOptionMethods._
(SOption.typeId, Seq(
MInfo(2, IsDefinedMethod),
MInfo(3, GetMethod),
@@ -384,7 +483,8 @@ class ErgoTreeSpecification extends SigmaDslTesting with ContractsTestkit {
case Some(tyDesc) =>
assert(canHaveMethods, s"Type $tyDesc should NOT have methods")
- tyDesc.methods.length shouldBe methods.length
+ val mc = MethodsContainer(tyDesc.typeId)
+ mc.methods.length shouldBe methods.length
for (expectedMethod <- methods) {
if (expectedMethod.isResolvableFromIds) {
@@ -608,11 +708,11 @@ class ErgoTreeSpecification extends SigmaDslTesting with ContractsTestkit {
}
property("checkValidFlatmap") {
- implicit val E = ErgoTreeEvaluator.forProfiling(new Profiler, evalSettings)
+ implicit val E = CErgoTreeEvaluator.forProfiling(new CProfiler, evalSettings)
def mkLambda(t: SType, mkBody: SValue => SValue) = {
MethodCall(
ValUse(1, SCollectionType(t)),
- SCollection.getMethodByName("flatMap").withConcreteTypes(
+ SCollectionMethods.getMethodByName("flatMap").withConcreteTypes(
Map(STypeVar("IV") -> t, STypeVar("OV") -> SByte)
),
Vector(FuncValue(Vector((3, t)), mkBody(ValUse(3, t)))),
@@ -625,7 +725,7 @@ class ErgoTreeSpecification extends SigmaDslTesting with ContractsTestkit {
(SBox, x => ExtractBytes(x.asBox)),
(SBox, x => ExtractBytesWithNoRef(x.asBox)),
(SSigmaProp, x => SigmaPropBytes(x.asSigmaProp)),
- (SBox, x => MethodCall(x, SBox.getMethodByName("id"), Vector(), Map()))
+ (SBox, x => MethodCall(x, SBoxMethods.getMethodByName("id"), Vector(), Map()))
).map { case (t, f) => mkLambda(t, f) }
validLambdas.foreach { l =>
@@ -643,7 +743,7 @@ class ErgoTreeSpecification extends SigmaDslTesting with ContractsTestkit {
// invalid MC like `boxes.flatMap(b => b.id, 10)`
MethodCall(
ValUse(1, SBox),
- SCollection.getMethodByName("flatMap").withConcreteTypes(
+ SCollectionMethods.getMethodByName("flatMap").withConcreteTypes(
Map(STypeVar("IV") -> SBox, STypeVar("OV") -> SByte)
),
Vector(
@@ -655,7 +755,7 @@ class ErgoTreeSpecification extends SigmaDslTesting with ContractsTestkit {
// invalid MC like `boxes.flatMap((b,_) => b.id)`
MethodCall(
ValUse(1, SBox),
- SCollection.getMethodByName("flatMap").withConcreteTypes(
+ SCollectionMethods.getMethodByName("flatMap").withConcreteTypes(
Map(STypeVar("IV") -> SBox, STypeVar("OV") -> SByte)
),
Vector(
@@ -680,25 +780,25 @@ class ErgoTreeSpecification extends SigmaDslTesting with ContractsTestkit {
val addr = ErgoAddressEncoder.Mainnet.fromString("Fo6oijFP2JM87ac7w").getOrThrow
val tree = addr.script
tree shouldBe new ErgoTree(
- 16.toByte,
+ HeaderType @@ 16.toByte,
Vector(TrueLeaf),
Right(BoolToSigmaProp(BoolToSigmaProp(ConstantPlaceholder(0, SBoolean)).asBoolValue))
)
def createCtx: ErgoLikeContext = ErgoLikeContextTesting
- .dummy(CostingBox(fakeSelf), VersionContext.current.activatedVersion)
+ .dummy(fakeSelf, VersionContext.current.activatedVersion)
.withErgoTreeVersion(tree.version)
VersionContext.withVersions(activatedVersion = 1, tree.version) {
// v4.x behavior
- val res = ErgoTreeEvaluator.evalToCrypto(createCtx, tree, evalSettings)
+ val res = CErgoTreeEvaluator.evalToCrypto(createCtx, tree, evalSettings)
res shouldBe ReductionResult(TrivialProp(true), 3)
}
VersionContext.withVersions(activatedVersion = 2, tree.version) {
// v5.0 behavior
assertExceptionThrown(
- ErgoTreeEvaluator.evalToCrypto(createCtx, tree, evalSettings),
+ CErgoTreeEvaluator.evalToCrypto(createCtx, tree, evalSettings),
exceptionLike[ClassCastException]()
)
}
@@ -716,7 +816,7 @@ class ErgoTreeSpecification extends SigmaDslTesting with ContractsTestkit {
val addr = ErgoAddressEncoder.Mainnet.fromString("Fo6oijFP2JM87ac7w").getOrThrow
val tree = addr.script
tree shouldBe new ErgoTree(
- 16.toByte,
+ HeaderType @@ 16.toByte,
Vector(TrueLeaf),
Right(BoolToSigmaProp(BoolToSigmaProp(ConstantPlaceholder(0, SBoolean)).asBoolValue))
)
@@ -748,7 +848,7 @@ class ErgoTreeSpecification extends SigmaDslTesting with ContractsTestkit {
// 4503b5d77cb74b4354771b835cd61e9d5257022a8efff0fddfac249e0c25b492
val addr = ErgoAddressEncoder.Mainnet.fromString("28JURWHTHwTnXJt5F38").getOrThrow
val tree = addr.script
- tree shouldBe new ErgoTree(16.toByte, Vector(),
+ tree shouldBe new ErgoTree(HeaderType @@ 16.toByte, Vector(),
Right(BoolToSigmaProp(
CreateProveDlog(OptionGet(ExtractRegisterAs(Self, ErgoBox.R4, SOption(SGroupElement)))).asBoolValue)
))
diff --git a/sc/shared/src/test/scala/sigmastate/FailingToProveSpec.scala b/sc/shared/src/test/scala/sigmastate/FailingToProveSpec.scala
index 775785b709..e047a8d158 100644
--- a/sc/shared/src/test/scala/sigmastate/FailingToProveSpec.scala
+++ b/sc/shared/src/test/scala/sigmastate/FailingToProveSpec.scala
@@ -2,8 +2,9 @@ package sigmastate
import sigmastate.helpers.{CompilerTestingCommons, ContextEnrichingTestProvingInterpreter, ErgoLikeContextTesting, ErgoLikeTestInterpreter}
import sigmastate.helpers.TestingHelpers._
-import sigmastate.lang.Terms._
+import sigma.ast.syntax._
import org.scalatest.TryValues._
+import sigma.data.AvlTreeData
import sigmastate.interpreter.Interpreter.{ScriptNameProp, emptyEnv}
import scala.util.Success
diff --git a/sc/shared/src/test/scala/sigmastate/ScriptVersionSwitchSpecification.scala b/sc/shared/src/test/scala/sigmastate/ScriptVersionSwitchSpecification.scala
index ad5af68649..b0206fa464 100644
--- a/sc/shared/src/test/scala/sigmastate/ScriptVersionSwitchSpecification.scala
+++ b/sc/shared/src/test/scala/sigmastate/ScriptVersionSwitchSpecification.scala
@@ -3,19 +3,22 @@ package sigmastate
import org.ergoplatform.ErgoBox.AdditionalRegisters
import org.ergoplatform._
import scorex.util.ModifierId
-import sigmastate.Values.ErgoTree.{DefaultHeader, updateVersionBits}
-import sigmastate.Values._
import sigma.VersionContext.MaxSupportedScriptVersion
+import sigma.ast.ErgoTree.{HeaderType, ZeroHeader, setConstantSegregation, setVersionBits}
+import sigma.ast._
+import sigma.{Box, SigmaDslTesting}
import sigmastate.eval._
-import sigmastate.exceptions.InterpreterException
-import sigmastate.helpers.{ErgoLikeContextTesting, ErgoLikeTestInterpreter}
import sigmastate.helpers.TestingHelpers.createBox
-import sigmastate.interpreter.ErgoTreeEvaluator.DefaultEvalSettings
-import sigmastate.interpreter.EvalSettings.EvaluationMode
-import sigmastate.interpreter.{CostedProverResult, ErgoTreeEvaluator, EvalSettings, Interpreter, ProverResult}
-import sigmastate.lang.Terms.ValueOps
+import sigmastate.helpers.{ErgoLikeContextTesting, ErgoLikeTestInterpreter}
+import sigmastate.interpreter.CErgoTreeEvaluator.DefaultEvalSettings
+import sigma.eval.EvalSettings.EvaluationMode
+import sigmastate.interpreter._
+import sigma.ast.syntax.ValueOps
+import sigma.data.CBox
+import sigma.eval.EvalSettings
+import sigma.exceptions.InterpreterException
+import sigma.interpreter.{CostedProverResult, ProverResult}
import sigmastate.utils.Helpers._
-import sigma.{Box, SigmaDslTesting}
/** Specification to verify that the interpreter behaves according to docs/aot-jit-switch.md.
*
@@ -25,17 +28,17 @@ import sigma.{Box, SigmaDslTesting}
class ScriptVersionSwitchSpecification extends SigmaDslTesting {
override implicit val generatorDrivenConfig: PropertyCheckConfiguration = PropertyCheckConfiguration(minSuccessful = 30)
override implicit val evalSettings: EvalSettings =
- ErgoTreeEvaluator.DefaultEvalSettings.copy(
+ CErgoTreeEvaluator.DefaultEvalSettings.copy(
costTracingEnabled = true // should always be enabled in tests (and false by default)
)
implicit def IR: IRContext = createIR()
- lazy val b1 = CostingBox(
+ lazy val b1 = CBox(
new ErgoBox(
1L,
new ErgoTree(
- 0.toByte,
+ HeaderType @@ 0.toByte,
Vector(),
Right(BoolToSigmaProp(OR(ConcreteCollection(Array(FalseLeaf, AND(ConcreteCollection(Array(FalseLeaf, FalseLeaf), SBoolean))), SBoolean))))
),
@@ -48,7 +51,7 @@ class ScriptVersionSwitchSpecification extends SigmaDslTesting {
)
/** Creates ErgoTree with segregated constants and also the given header flags. */
- def createErgoTree(headerFlags: Byte)(implicit IR: IRContext): ErgoTree = {
+ def createErgoTree(header: HeaderType)(implicit IR: IRContext): ErgoTree = {
val code =
s"""{
| val func = { (x: Coll[Box]) => x.filter({(b: Box) => b.value > 1 }) }
@@ -65,7 +68,7 @@ class ScriptVersionSwitchSpecification extends SigmaDslTesting {
checkCompilerResult(res)
res.buildTree.asSigmaProp
}
- ErgoTree.withSegregation(headerFlags, compiledTree)
+ ErgoTree.withSegregation(header, compiledTree)
}
/** Proves the given ergoTree in a dummy context with the given activatedScriptVersion.
@@ -136,7 +139,10 @@ class ScriptVersionSwitchSpecification extends SigmaDslTesting {
property("new versions of scripts will require size bit in the header") {
(1 to 7).foreach { version =>
assertExceptionThrown(
- createErgoTree(headerFlags = updateVersionBits(DefaultHeader, version.toByte)),
+ {
+ val tree = createErgoTree(header = setVersionBits(ZeroHeader, version.toByte))
+ new ErgoTree(setVersionBits(setConstantSegregation(ZeroHeader), version.toByte), tree.constants, tree.root)
+ },
exceptionLike[IllegalArgumentException]("For newer version the size bit is required")
)
}
@@ -160,7 +166,7 @@ class ScriptVersionSwitchSpecification extends SigmaDslTesting {
forEachErgoTreeVersion(treeVers) {
// SF inactive: check cost vectors of v4.x interpreter
- val headerFlags = ErgoTree.headerWithVersion(ergoTreeVersionInTests)
+ val headerFlags = ErgoTree.defaultHeaderWithVersion(ergoTreeVersionInTests)
val ergoTree = createErgoTree(headerFlags)
// both prove and verify are accepting with full evaluation
@@ -187,8 +193,8 @@ class ScriptVersionSwitchSpecification extends SigmaDslTesting {
forEachActivatedScriptVersion(Array[Byte](0, 1)) { // Block Versions 1, 2
forEachErgoTreeVersion(ergoTreeVers = Array[Byte](2)) { // only Script v2
- val headerFlags = ErgoTree.headerWithVersion(ergoTreeVersionInTests /* Script v2 */)
- val ergoTree = createErgoTree(headerFlags = headerFlags)
+ val header = ErgoTree.headerWithVersion(ZeroHeader, ergoTreeVersionInTests /* Script v2 */)
+ val ergoTree = createErgoTree(header)
// prover is rejecting ErgoTree versions higher than activated
assertExceptionThrown(
@@ -246,7 +252,7 @@ class ScriptVersionSwitchSpecification extends SigmaDslTesting {
forEachActivatedScriptVersion(activatedVers = Array[Byte](2)) // version for Block v3
{
forEachErgoTreeVersion(ergoTreeVers = Array[Byte](3, 4)) { // scripts >= v3
- val headerFlags = ErgoTree.headerWithVersion(ergoTreeVersionInTests)
+ val headerFlags = ErgoTree.defaultHeaderWithVersion(ergoTreeVersionInTests)
val ergoTree = createErgoTree(headerFlags)
// prover is rejecting ErgoTree versions higher than activated
@@ -273,7 +279,7 @@ class ScriptVersionSwitchSpecification extends SigmaDslTesting {
forEachActivatedScriptVersion(activatedVers = Array[Byte](3)) // version for Block v4
{
forEachErgoTreeVersion(ergoTreeVers = Array[Byte](3, 4)) { // scripts >= v3
- val headerFlags = ErgoTree.headerWithVersion(ergoTreeVersionInTests)
+ val headerFlags = ErgoTree.defaultHeaderWithVersion(ergoTreeVersionInTests)
val ergoTree = createErgoTree(headerFlags)
// prover is rejecting, because such context parameters doesn't make sense
@@ -305,7 +311,7 @@ class ScriptVersionSwitchSpecification extends SigmaDslTesting {
{
forEachErgoTreeVersion(Array[Byte](0, 1, 2)) { // tree versions supported by v5.x
// SF inactive: check cost vectors of v4.x interpreter
- val headerFlags = ErgoTree.headerWithVersion(ergoTreeVersionInTests)
+ val headerFlags = ErgoTree.defaultHeaderWithVersion(ergoTreeVersionInTests)
val ergoTree = createErgoTree(headerFlags)
// both prove and verify are accepting with full evaluation
diff --git a/sc/shared/src/test/scala/sigmastate/SoftForkabilitySpecification.scala b/sc/shared/src/test/scala/sigmastate/SoftForkabilitySpecification.scala
index c46b5a3119..bca2d0e638 100644
--- a/sc/shared/src/test/scala/sigmastate/SoftForkabilitySpecification.scala
+++ b/sc/shared/src/test/scala/sigmastate/SoftForkabilitySpecification.scala
@@ -2,24 +2,28 @@ package sigmastate
import org.ergoplatform._
import org.ergoplatform.validation.ValidationRules._
-import org.ergoplatform.validation._
import org.scalatest.BeforeAndAfterAll
-import sigmastate.SPrimType.MaxPrimTypeCode
-import sigmastate.Values.ErgoTree.EmptyConstants
-import sigmastate.Values.{ByteArrayConstant, ErgoTree, IntConstant, NotReadyValueInt, UnparsedErgoTree, ValueCompanion}
-import sigmastate.exceptions.{InterpreterException, SerializerException}
+import sigma.{Colls, SigmaTestingData}
+import sigma.ast._
+import sigma.ast.SPrimType.MaxPrimTypeCode
+import sigma.ast.TypeCodes.LastConstantCode
+import sigma.data.AvlTreeData
+import sigma.serialization.SerializerException
+import sigma.validation.ValidationRules.{CheckPrimitiveTypeCode, CheckSerializableTypeCode, CheckTypeCode, CheckTypeWithMethods, trySoftForkable}
+import sigma.validation.{ChangedRule, ReplacedRule, SigmaValidationSettings, ValidationException, ValidationRule}
+import ErgoTree.{EmptyConstants, HeaderType, ZeroHeader, setSizeBit}
import sigmastate.helpers.TestingHelpers._
import sigmastate.helpers.{CompilerTestingCommons, ErgoLikeContextTesting, ErgoLikeTestInterpreter, ErgoLikeTestProvingInterpreter}
-import sigmastate.interpreter.ErgoTreeEvaluator.DataEnv
import sigmastate.interpreter.Interpreter.{ScriptNameProp, emptyEnv}
-import sigmastate.interpreter.{ContextExtension, ErgoTreeEvaluator, ProverResult}
-import sigmastate.lang.Terms._
-import sigmastate.serialization.OpCodes.{LastConstantCode, OpCode}
-import sigmastate.serialization.SigmaSerializer.startReader
-import sigmastate.serialization._
+import sigma.interpreter.{ContextExtension, ProverResult}
+import sigma.ast.syntax._
+import sigma.eval.ErgoTreeEvaluator
+import sigma.eval.ErgoTreeEvaluator.DataEnv
+import sigma.exceptions.InterpreterException
+import sigma.serialization.SigmaSerializer.startReader
+import sigma.serialization._
+import sigma.serialization.ValueCodes.OpCode
import sigmastate.utils.Helpers._
-import sigmastate.utxo.DeserializeContext
-import sigma.{Colls, SigmaTestingData}
class SoftForkabilitySpecification extends SigmaTestingData
with CompilerTestingCommons
@@ -39,7 +43,7 @@ class SoftForkabilitySpecification extends SigmaTestingData
// cast Boolean typed prop to SigmaProp (which is invalid) // ErgoTree v0
lazy val invalidPropV1: ErgoTree =
ErgoTree.fromProposition(
- ErgoTree.headerWithVersion(0),
+ ErgoTree.headerWithVersion(ZeroHeader, 0),
booleanPropV1.asSigmaProp)
lazy val invalidTxV1 = createTransaction(createBox(boxAmt, invalidPropV1, 1))
@@ -48,7 +52,7 @@ class SoftForkabilitySpecification extends SigmaTestingData
lazy val propV1 = booleanPropV1.toSigmaProp
lazy val txV1 = createTransaction(
createBox(boxAmt,
- ErgoTree.fromProposition(ErgoTree.headerWithVersion(0), propV1), // ErgoTree v0
+ ErgoTree.fromProposition(ErgoTree.headerWithVersion(ZeroHeader, 0), propV1), // ErgoTree v0
1))
lazy val txV1bytes = txV1.messageToSign
@@ -131,7 +135,7 @@ class SoftForkabilitySpecification extends SigmaTestingData
lazy val booleanPropV2 = GT(Height2, IntConstant(deadline))
lazy val invalidPropV2: ErgoTree = ErgoTree.fromProposition(
- headerFlags = ErgoTree.headerWithVersion(0), // ErgoTree v0
+ header = ErgoTree.headerWithVersion(ZeroHeader, 0), // ErgoTree v0
prop = booleanPropV2.asSigmaProp)
lazy val invalidTxV2 = createTransaction(createBox(boxAmt, invalidPropV2, 1))
@@ -139,7 +143,7 @@ class SoftForkabilitySpecification extends SigmaTestingData
lazy val propV2 = booleanPropV2.toSigmaProp
// prepare bytes using special serialization WITH `size flag` in the header
- lazy val propV2tree = ErgoTree.withSegregation(ErgoTree.SizeFlag, propV2)
+ lazy val propV2tree = ErgoTree.withSegregation(setSizeBit(ZeroHeader), propV2)
lazy val propV2treeBytes = runOnV2Node {
propV2tree.bytes
}
@@ -154,7 +158,7 @@ class SoftForkabilitySpecification extends SigmaTestingData
property("node v1, soft-fork up to v2, script v2 without size bit") {
// try prepare v2 script without `size bit` in the header
assertExceptionThrown({
- ErgoTree(1.toByte, EmptyConstants, propV2)
+ new ErgoTree(HeaderType @@ 1.toByte, EmptyConstants, Right(propV2))
}, {
case _: IllegalArgumentException => true
case _ => false
@@ -163,7 +167,7 @@ class SoftForkabilitySpecification extends SigmaTestingData
// prepare bytes using default serialization and then replacing version in the header
val v2tree_withoutSize_bytes = runOnV2Node {
val tree = ErgoTree.fromProposition(
- ErgoTree.headerWithVersion(0), propV2) // ErgoTree v0
+ ErgoTree.headerWithVersion(ZeroHeader, 0), propV2) // ErgoTree v0
val bytes = tree.bytes
// set version to v2 while not setting the size bit,
// we cannot do this using ErgoTree constructor (due to require() check)
@@ -268,7 +272,7 @@ class SoftForkabilitySpecification extends SigmaTestingData
// v1 main script which deserializes v2 script from context
val mainProp = BinAnd(GT(Height, IntConstant(deadline)), DeserializeContext(1, SBoolean)).toSigmaProp
val mainTree = ErgoTree.fromProposition(
- headerFlags = ErgoTree.headerWithVersion(0), // ErgoTree v0
+ header = ErgoTree.headerWithVersion(ZeroHeader, 0), // ErgoTree v0
prop = mainProp)
val tx = createTransaction(createBox(boxAmt, mainTree, 1))
diff --git a/sc/shared/src/test/scala/sigmastate/TestingInterpreterSpecification.scala b/sc/shared/src/test/scala/sigmastate/TestingInterpreterSpecification.scala
index 2398a48535..fe5a678679 100644
--- a/sc/shared/src/test/scala/sigmastate/TestingInterpreterSpecification.scala
+++ b/sc/shared/src/test/scala/sigmastate/TestingInterpreterSpecification.scala
@@ -1,19 +1,21 @@
package sigmastate
-import sigmastate.crypto.DLogProtocol.{DLogProverInput, ProveDlog}
+import sigmastate.crypto.DLogProtocol.DLogProverInput
import scorex.crypto.hash.Blake2b256
-import sigmastate.Values._
+import sigma.ast._
+import sigma.ast.syntax._
import sigmastate.interpreter._
import Interpreter._
-import sigmastate.lang.Terms._
+import sigma.ast.syntax._
import org.ergoplatform._
import org.scalatest.BeforeAndAfterAll
import scorex.util.encode.Base58
+import sigma.crypto.CryptoConstants
+import sigma.data.{AvlTreeData, CAND, ProveDlog, SigmaBoolean, TrivialProp}
import sigma.util.Extensions.IntOps
-import sigmastate.crypto.CryptoConstants
import sigmastate.helpers.{CompilerTestingCommons, ErgoLikeContextTesting, ErgoLikeTestInterpreter, ErgoLikeTestProvingInterpreter}
import sigmastate.helpers.TestingHelpers._
-import sigmastate.serialization.ValueSerializer
+import sigma.serialization.ValueSerializer
import sigmastate.utils.Helpers._
import scala.util.Random
diff --git a/sc/shared/src/test/scala/sigmastate/TypesSpecification.scala b/sc/shared/src/test/scala/sigmastate/TypesSpecification.scala
index 3d5edf22f2..9a4c5ce1b8 100644
--- a/sc/shared/src/test/scala/sigmastate/TypesSpecification.scala
+++ b/sc/shared/src/test/scala/sigmastate/TypesSpecification.scala
@@ -1,9 +1,10 @@
package sigmastate
import sigma.Environment
-import sigmastate.SType.isValueOfType
-import sigmastate.eval.{CSigmaProp, CostingSigmaDslBuilder}
+import sigma.ast.SType.isValueOfType
import sigma.SigmaTestingData
+import sigma.ast._
+import sigma.data.{CSigmaDslBuilder, CSigmaProp}
class TypesSpecification extends SigmaTestingData {
@@ -96,8 +97,8 @@ class TypesSpecification extends SigmaTestingData {
assertValidType(t1, SAvlTree)
assertInvalidType(t1, SShort)
- assertValidType(CostingSigmaDslBuilder, SGlobal)
- assertInvalidType(CostingSigmaDslBuilder, SShort)
+ assertValidType(CSigmaDslBuilder, SGlobal)
+ assertInvalidType(CSigmaDslBuilder, SShort)
assertValidType(h1, SHeader)
assertInvalidType(h1, SShort)
diff --git a/sc/shared/src/test/scala/sigmastate/eval/ErgoScriptTestkit.scala b/sc/shared/src/test/scala/sigmastate/eval/ErgoScriptTestkit.scala
index 5d949d65fc..abbed09992 100644
--- a/sc/shared/src/test/scala/sigmastate/eval/ErgoScriptTestkit.scala
+++ b/sc/shared/src/test/scala/sigmastate/eval/ErgoScriptTestkit.scala
@@ -2,18 +2,22 @@ package sigmastate.eval
import org.ergoplatform.ErgoAddressEncoder.TestnetNetworkPrefix
import org.ergoplatform.validation.ValidationSpecification
-import org.ergoplatform.{Context => _, _}
+import org.ergoplatform._
import scalan.BaseCtxTests
import sigma.VersionContext
-import sigmastate.Values.{BigIntArrayConstant, EvaluatedValue, SValue, SigmaPropConstant, Value}
+import sigma.ast.{BigIntArrayConstant, ErgoTree, EvaluatedValue, SigmaPropConstant, Value}
+import sigma.ast.SType
+import sigma.ast.syntax.SValue
+import sigma.data.AvlTreeData
import sigmastate.helpers.TestingHelpers._
import sigmastate.helpers.{ContextEnrichingTestProvingInterpreter, ErgoLikeContextTesting}
import sigmastate.interpreter.Interpreter.ScriptEnv
-import sigmastate.interpreter.{ContextExtension, ErgoTreeEvaluator}
-import sigmastate.lang.Terms.ValueOps
+import sigmastate.interpreter.CErgoTreeEvaluator
+import sigma.ast.syntax.ValueOps
+import sigma.interpreter.ContextExtension
import sigmastate.lang.{CompilerResult, CompilerSettings, LangTests, SigmaCompiler}
-import sigmastate.serialization.ErgoTreeSerializer.DefaultSerializer
-import sigmastate.{AvlTreeData, CompilerTestsBase, SType}
+import sigma.serialization.ErgoTreeSerializer.DefaultSerializer
+import sigmastate.CompilerTestsBase
import sigma.{ContractsTestkit, Context => DContext}
import scala.annotation.unused
@@ -30,7 +34,7 @@ trait ErgoScriptTestkit extends ContractsTestkit with LangTests
import Context._
import Liftables._
- override lazy val compiler = new SigmaCompiler(CompilerSettings(
+ override lazy val compiler = SigmaCompiler(CompilerSettings(
TestnetNetworkPrefix,
IR.builder,
lowerMethodCalls = true
@@ -67,8 +71,8 @@ trait ErgoScriptTestkit extends ContractsTestkit with LangTests
lazy val boxToSpend = testBox(10, TrueTree, 0,
additionalRegisters = Map(ErgoBox.R4 -> BigIntArrayConstant(bigIntegerArr1)))
- lazy val tx1Output1 = testBox(minToRaise, projectPubKey, 0)
- lazy val tx1Output2 = testBox(1, projectPubKey, 0)
+ lazy val tx1Output1 = testBox(minToRaise, ErgoTree.fromProposition(projectPubKey), 0)
+ lazy val tx1Output2 = testBox(1, ErgoTree.fromProposition(projectPubKey), 0)
lazy val tx1 = new ErgoLikeTransaction(IndexedSeq(), IndexedSeq(), IndexedSeq(tx1Output1, tx1Output2))
lazy val ergoCtx = ErgoLikeContextTesting(
currentHeight = timeout - 1,
@@ -166,11 +170,11 @@ trait ErgoScriptTestkit extends ContractsTestkit with LangTests
}
// check calc
- val (res, _) = ErgoTreeEvaluator.eval(
+ val (res, _) = CErgoTreeEvaluator.eval(
context = ectx,
constants = ergoTree.constants,
exp = ergoTree.toProposition(replaceConstants = false),
- evalSettings = ErgoTreeEvaluator.DefaultEvalSettings
+ evalSettings = CErgoTreeEvaluator.DefaultEvalSettings
)
checkExpected(res, expectedResult.calc,
"Calc evaluation:\n value = %s,\n expectedResult.calc: %s\n")
diff --git a/sc/shared/src/test/scala/sigmastate/eval/ErgoTreeBuildingTest.scala b/sc/shared/src/test/scala/sigmastate/eval/ErgoTreeBuildingTest.scala
index ed9733b57c..526012f212 100644
--- a/sc/shared/src/test/scala/sigmastate/eval/ErgoTreeBuildingTest.scala
+++ b/sc/shared/src/test/scala/sigmastate/eval/ErgoTreeBuildingTest.scala
@@ -1,14 +1,13 @@
package sigmastate.eval
-import org.ergoplatform.{Height, Outputs, Self, Inputs}
import sigmastate._
-import sigmastate.Values.{LongConstant, FuncValue, BlockValue, SigmaPropConstant, IntConstant, ValDef, ValUse}
+import sigma.ast._
import sigmastate.helpers.ContextEnrichingTestProvingInterpreter
import sigmastate.interpreter.Interpreter._
import scalan.BaseCtxTests
+import sigma.ast.syntax.ValueOps
import sigmastate.lang.LangTests
-import sigmastate.lang.Terms.{ValueOps, Apply}
-import sigmastate.utxo._
+import sigma.ast.Apply
class ErgoTreeBuildingTest extends BaseCtxTests
with LangTests with ExampleContracts with ErgoScriptTestkit {
diff --git a/sc/shared/src/test/scala/sigmastate/eval/EvaluationTest.scala b/sc/shared/src/test/scala/sigmastate/eval/EvaluationTest.scala
index 9aefb272b6..5fcbd0f220 100644
--- a/sc/shared/src/test/scala/sigmastate/eval/EvaluationTest.scala
+++ b/sc/shared/src/test/scala/sigmastate/eval/EvaluationTest.scala
@@ -1,16 +1,17 @@
package sigmastate.eval
import org.ergoplatform.ErgoBox
-import sigmastate.Values.{ConcreteCollection, IntArrayConstant, IntConstant, SigmaPropConstant, SigmaPropValue}
+import sigma.ast.{AND, ConcreteCollection, CreateProveDlog, DecodePoint, EQ, ErgoTree, IntArrayConstant, IntConstant, SSigmaProp, SigmaPropConstant, SigmaPropIsProven, SubstConstants}
import sigmastate.helpers.ContextEnrichingTestProvingInterpreter
import sigmastate.helpers.TestingHelpers._
import sigmastate.interpreter.Interpreter._
import scalan.BaseCtxTests
+import sigma.ast.syntax.SigmaPropValue
+import sigma.data.ProveDlog
import sigmastate.lang.LangTests
import sigma.util.BenchmarkUtil._
-import sigmastate._
-import sigmastate.crypto.DLogProtocol.{DLogProverInput, ProveDlog}
-import sigmastate.serialization.ErgoTreeSerializer.DefaultSerializer
+import sigmastate.crypto.DLogProtocol.DLogProverInput
+import sigma.serialization.ErgoTreeSerializer.DefaultSerializer
class EvaluationTest extends BaseCtxTests
with LangTests with ExampleContracts with ErgoScriptTestkit {
@@ -38,7 +39,7 @@ class EvaluationTest extends BaseCtxTests
test("lazy logical ops") {
val prover = new ContextEnrichingTestProvingInterpreter
val pk = prover.dlogSecrets.head.publicImage
- val self = testBox(1, pk, 0, additionalRegisters = Map(ErgoBox.R4 -> IntConstant(10)))
+ val self = testBox(1, ErgoTree.fromSigmaBoolean(pk), 0, additionalRegisters = Map(ErgoBox.R4 -> IntConstant(10)))
val ctx = newErgoContext(height = 1, self)
// guarded register access: existing reg
reduce(emptyEnv, "lazy1", "SELF.R4[Int].isDefined && SELF.R4[Int].get == 10", ctx, true)
@@ -101,7 +102,7 @@ class EvaluationTest extends BaseCtxTests
test("SubstConst") {
def script(pk: ProveDlog): SigmaPropValue =
- AND(EQ(IntConstant(1), IntConstant(1)), SigmaPropConstant(pk).isProven).toSigmaProp
+ AND(EQ(IntConstant(1), IntConstant(1)), SigmaPropIsProven(SigmaPropConstant(pk))).toSigmaProp
val pk1 = DLogProverInput.random().publicImage
val pk2 = DLogProverInput.random().publicImage
diff --git a/sc/shared/src/test/scala/sigmastate/eval/ExampleContracts.scala b/sc/shared/src/test/scala/sigmastate/eval/ExampleContracts.scala
index 913a82167f..ac9e6aac07 100644
--- a/sc/shared/src/test/scala/sigmastate/eval/ExampleContracts.scala
+++ b/sc/shared/src/test/scala/sigmastate/eval/ExampleContracts.scala
@@ -1,6 +1,7 @@
package sigmastate.eval
import scalan.BaseCtxTests
+import sigma.data.CAnyValue
trait ExampleContracts extends ErgoScriptTestkit { self: BaseCtxTests =>
diff --git a/sc/shared/src/test/scala/sigmastate/helpers/CompilerTestingCommons.scala b/sc/shared/src/test/scala/sigmastate/helpers/CompilerTestingCommons.scala
index ed86bb86ed..332ee902a2 100644
--- a/sc/shared/src/test/scala/sigmastate/helpers/CompilerTestingCommons.scala
+++ b/sc/shared/src/test/scala/sigmastate/helpers/CompilerTestingCommons.scala
@@ -1,28 +1,28 @@
package sigmastate.helpers
import org.ergoplatform._
-import org.ergoplatform.validation.ValidationRules.CheckSerializableTypeCode
-import org.ergoplatform.validation.{ValidationException, ValidationSpecification}
+import org.ergoplatform.validation.ValidationSpecification
import org.scalacheck.Arbitrary.arbByte
import org.scalacheck.Gen
-import org.scalatest.Assertion
import sigma.util.BenchmarkUtil
import scalan.TestContexts
-import sigma.{Colls, TestUtils}
-import sigma.data.RType
-import sigmastate.Values.{Constant, ErgoTree, SValue, SigmaBoolean, SigmaPropValue}
-import sigmastate.eval._
+import sigma.ast.{Constant, CostItem, ErgoTree, JitCost, SOption, SType}
+import sigma.{Colls, Evaluation, TestUtils}
+import sigma.data.{RType, SigmaBoolean}
+import sigma.validation.ValidationException
+import sigma.validation.ValidationRules.CheckSerializableTypeCode
+import sigma.ast.syntax.{SValue, SigmaPropValue}
+import sigma.eval.{CostDetails, EvalSettings, Extensions, GivenCost, TracedCost}
import sigmastate.helpers.TestingHelpers._
-import sigmastate.interpreter.ContextExtension.VarBinding
-import sigmastate.interpreter.ErgoTreeEvaluator.DefaultProfiler
+import sigma.interpreter.ContextExtension.VarBinding
+import sigmastate.interpreter.CErgoTreeEvaluator.DefaultProfiler
import sigmastate.interpreter.Interpreter.ScriptEnv
import sigmastate.interpreter._
-import sigmastate.lang.{CompilerSettings, SigmaCompiler, Terms}
-import sigmastate.serialization.SigmaSerializer
-import sigmastate.{CompilerTestsBase, JitCost, SOption, SType}
+import sigmastate.lang.{CompilerSettings, SigmaCompiler}
+import sigma.serialization.SigmaSerializer
+import sigmastate.CompilerTestsBase
+import sigmastate.eval.{CContext, IRContext}
-import scala.language.implicitConversions
-import scala.reflect.ClassTag
import scala.util.DynamicVariable
trait CompilerTestingCommons extends TestingCommons
@@ -48,7 +48,7 @@ trait CompilerTestingCommons extends TestingCommons
def createContexts[A](in: A, bindings: Seq[VarBinding])(implicit tA: RType[A]) = {
val tpeA = Evaluation.rtypeToSType(tA)
in match {
- case ctx: CostingDataContext =>
+ case ctx: CContext =>
// the context is passed as function argument (this is for testing only)
// This is to overcome non-functional semantics of context operations
// (such as Inputs, Height, etc which don't have arguments and refer to the
@@ -83,7 +83,7 @@ trait CompilerTestingCommons extends TestingCommons
.withErgoTreeVersion(ergoTreeVersionInTests)
.withBindings(1.toByte -> Constant[SType](in.asInstanceOf[SType#WrappedType], tpeA))
.withBindings(bindings: _*)
- val calcCtx = ergoCtx.toSigmaContext().asInstanceOf[CostingDataContext]
+ val calcCtx = ergoCtx.toSigmaContext().asInstanceOf[CContext]
calcCtx
}
}
@@ -116,7 +116,7 @@ trait CompilerTestingCommons extends TestingCommons
compiledTree
}
- def evalSettings = ErgoTreeEvaluator.DefaultEvalSettings
+ def evalSettings = CErgoTreeEvaluator.DefaultEvalSettings
def printCostDetails(script: String, details: CostDetails) = {
val traceLines = SigmaPPrint(details, height = 550, width = 150)
@@ -132,20 +132,18 @@ trait CompilerTestingCommons extends TestingCommons
(implicit IR: IRContext,
evalSettings: EvalSettings,
compilerSettings: CompilerSettings): CompiledFunc[A, B] = {
- val tA = RType[A]
val f = (in: A) => {
- implicit val cA: ClassTag[A] = tA.classTag
val sigmaCtx = createContexts(in, bindings)
val accumulator = new CostAccumulator(
initialCost = JitCost(0),
costLimit = Some(JitCost.fromBlockCost(evalSettings.scriptCostLimitInEvaluator)))
- val evaluator = new ErgoTreeEvaluator(
+ val evaluator = new CErgoTreeEvaluator(
context = sigmaCtx,
constants = ErgoTree.EmptyConstants,
coster = accumulator, evalSettings.profilerOpt.getOrElse(DefaultProfiler), evalSettings)
val (res, actualTime) = BenchmarkUtil.measureTimeNano(
- evaluator.evalWithCost[B](ErgoTreeEvaluator.EmptyDataEnv, expr))
+ evaluator.evalWithCost[B](CErgoTreeEvaluator.EmptyDataEnv, expr))
val costDetails = if (evalSettings.costTracingEnabled) {
val trace: Seq[CostItem] = evaluator.getCostTrace()
val costDetails = TracedCost(trace, Some(actualTime))
@@ -163,7 +161,7 @@ trait CompilerTestingCommons extends TestingCommons
}
(res.value, costDetails)
}
- val Terms.Apply(funcVal, _) = expr.asInstanceOf[SValue]
+ val sigma.ast.Apply(funcVal, _) = expr.asInstanceOf[SValue]
CompiledFunc(funcScript, bindings, funcVal, expr, f)
}
diff --git a/sc/shared/src/test/scala/sigmastate/helpers/SigmaPPrint.scala b/sc/shared/src/test/scala/sigmastate/helpers/SigmaPPrint.scala
index 690630d327..1b0f7b112d 100644
--- a/sc/shared/src/test/scala/sigmastate/helpers/SigmaPPrint.scala
+++ b/sc/shared/src/test/scala/sigmastate/helpers/SigmaPPrint.scala
@@ -4,26 +4,23 @@ import org.ergoplatform.ErgoBox
import org.ergoplatform.ErgoBox.RegisterId
import org.ergoplatform.settings.ErgoAlgos
import pprint.{PPrinter, Tree}
-import sigma.data.{CollType, PrimitiveType}
+import sigma.ast.SCollection.{SBooleanArray, SByteArray, SByteArray2}
+import sigma.ast._
+import sigma.crypto.EcPointType
+import sigma.data.{AvlTreeData, AvlTreeFlags, CollType, PrimitiveType, TrivialProp}
+import sigma.serialization.GroupElementSerializer
import sigma.{Coll, GroupElement}
-import sigmastate.SCollection._
-import sigmastate.Values.{ConstantNode, ErgoTree, FuncValue, ValueCompanion}
+import sigma.ast.{ConstantNode, FuncValue, ValueCompanion}
import sigmastate._
-import sigmastate.crypto.CryptoConstants.EcPointType
import sigmastate.crypto.GF2_192_Poly
-import sigmastate.interpreter.{CompanionDesc, FixedCostItem, MethodDesc}
-import sigmastate.lang.Terms
-import sigmastate.lang.Terms.MethodCall
-import sigmastate.serialization.GroupElementSerializer
-import sigmastate.utxo.SelectField
-
+import sigma.ast.MethodCall
import java.math.BigInteger
import scala.collection.compat.immutable.ArraySeq
import scala.collection.mutable
import scala.collection.mutable.ArrayBuffer
import scala.reflect.ClassTag
-/** Pretty-printer customized to print [[sigmastate.Values.Value]] instances
+/** Pretty-printer customized to print [[sigma.ast.Value]] instances
* into a valid Scala code (can be cut-and-pasted).*/
object SigmaPPrint extends PPrinter {
override def showFieldNames = false
@@ -211,11 +208,11 @@ object SigmaPPrint extends PPrinter {
Tree.Literal(s"FuncValue.AddToEnvironmentDesc")
case MethodDesc(method) =>
Tree.Apply("MethodDesc", Seq(methodLiteral(method)).iterator)
- case sigmastate.SGlobal =>
+ case SGlobal =>
Tree.Literal(s"SGlobal")
- case sigmastate.SCollection =>
+ case SCollection =>
Tree.Literal(s"SCollection")
- case sigmastate.SOption =>
+ case SOption =>
Tree.Literal(s"SOption")
case t: STypeCompanion if t.isInstanceOf[SType] =>
Tree.Literal(s"S${t.typeName}")
@@ -247,7 +244,7 @@ object SigmaPPrint extends PPrinter {
case mc @ MethodCall(obj, method, args, typeSubst) =>
val objType = apply(method.objType).plainText
val methodTemplate = method.objType.getMethodByName(method.name)
- val methodT = Terms.unifyTypeLists(methodTemplate.stype.tDom, obj.tpe +: args.map(_.tpe)) match {
+ val methodT = unifyTypeLists(methodTemplate.stype.tDom, obj.tpe +: args.map(_.tpe)) match {
case Some(subst) if subst.nonEmpty =>
val getMethod = s"""$objType.getMethodByName("${method.name}").withConcreteTypes"""
Tree.Apply(getMethod, treeifySeq(Seq(subst)))
diff --git a/sc/shared/src/test/scala/sigmastate/lang/SigmaBinderTest.scala b/sc/shared/src/test/scala/sigmastate/lang/SigmaBinderTest.scala
index 397c5c5e5d..1f758370a0 100644
--- a/sc/shared/src/test/scala/sigmastate/lang/SigmaBinderTest.scala
+++ b/sc/shared/src/test/scala/sigmastate/lang/SigmaBinderTest.scala
@@ -1,17 +1,18 @@
package sigmastate.lang
-import org.ergoplatform.{Height, Inputs, Outputs, Self}
import org.ergoplatform.ErgoAddressEncoder._
import org.scalatest.matchers.should.Matchers
import org.scalatest.propspec.AnyPropSpec
import org.scalatestplus.scalacheck.ScalaCheckPropertyChecks
-import sigmastate.Values._
+import sigma.ast.{NoType, SBoolean, SBox, SCollection, SFunc, SInt, SLong, STuple}
+import sigma.ast._
+import sigma.ast.syntax.SValue
import sigmastate._
import sigmastate.interpreter.Interpreter.ScriptEnv
-import sigmastate.lang.SigmaPredef.PredefinedFuncRegistry
-import sigmastate.lang.Terms._
-import sigmastate.exceptions.BinderException
-import sigmastate.eval._
+import SigmaPredef.PredefinedFuncRegistry
+import sigma.ast.syntax._
+import sigma.eval.SigmaDsl
+import sigma.exceptions.BinderException
class SigmaBinderTest extends AnyPropSpec with ScalaCheckPropertyChecks with Matchers with LangTests {
import StdSigmaBuilder._
@@ -167,7 +168,7 @@ class SigmaBinderTest extends AnyPropSpec with ScalaCheckPropertyChecks with Mat
property("predefined primitives") {
bind(env, "{ (box: Box) => box.value }") shouldBe Lambda(IndexedSeq("box" -> SBox), NoType, Select(Ident("box"), "value"))
- bind(env, "{ (box: Box) => box.propositionBytes }") shouldBe Lambda(IndexedSeq("box" -> SBox), NoType, Select(Ident("box"), SBox.PropositionBytes))
+ bind(env, "{ (box: Box) => box.propositionBytes }") shouldBe Lambda(IndexedSeq("box" -> SBox), NoType, Select(Ident("box"), SBoxMethods.PropositionBytes))
bind(env, "{ (box: Box) => box.bytes }") shouldBe Lambda(IndexedSeq("box" -> SBox), NoType, Select(Ident("box"), "bytes"))
bind(env, "{ (box: Box) => box.id }") shouldBe Lambda(IndexedSeq("box" -> SBox), NoType, Select(Ident("box"), "id"))
}
diff --git a/sc/shared/src/test/scala/sigmastate/lang/SigmaCompilerTest.scala b/sc/shared/src/test/scala/sigmastate/lang/SigmaCompilerTest.scala
index 129f096d85..88c75a90b6 100644
--- a/sc/shared/src/test/scala/sigmastate/lang/SigmaCompilerTest.scala
+++ b/sc/shared/src/test/scala/sigmastate/lang/SigmaCompilerTest.scala
@@ -3,16 +3,15 @@ package sigmastate.lang
import org.ergoplatform.ErgoAddressEncoder.TestnetNetworkPrefix
import org.ergoplatform._
import scorex.util.encode.Base58
-import sigmastate.Values._
+import sigma.ast.{ByIndex, ExtractAmount, GetVar, _}
+import sigma.ast.syntax._
import sigmastate._
-import sigmastate.exceptions.{GraphBuildingException, InvalidArguments, TyperException}
import sigmastate.helpers.CompilerTestingCommons
import sigmastate.interpreter.Interpreter.ScriptEnv
-import sigmastate.lang.Terms.{Apply, MethodCall, ZKProofBlock}
-import sigmastate.serialization.ValueSerializer
-import sigmastate.serialization.generators.ObjectGenerators
-import sigmastate.utxo.{ByIndex, ExtractAmount, GetVar}
-
+import sigma.ast.{Apply, MethodCall, ZKProofBlock}
+import sigma.exceptions.{GraphBuildingException, InvalidArguments, TyperException}
+import sigma.serialization.ValueSerializer
+import sigma.serialization.generators.ObjectGenerators
import scala.annotation.unused
class SigmaCompilerTest extends CompilerTestingCommons with LangTests with ObjectGenerators {
@@ -80,8 +79,8 @@ class SigmaCompilerTest extends CompilerTestingCommons with LangTests with Objec
}
property("global methods") {
- comp(env, "{ groupGenerator }") shouldBe MethodCall(Global, SGlobal.groupGeneratorMethod, IndexedSeq(), Terms.EmptySubst)
- comp(env, "{ Global.groupGenerator }") shouldBe MethodCall(Global, SGlobal.groupGeneratorMethod, IndexedSeq(), Terms.EmptySubst)
+ comp(env, "{ groupGenerator }") shouldBe MethodCall(Global, SGlobalMethods.groupGeneratorMethod, IndexedSeq(), EmptySubst)
+ comp(env, "{ Global.groupGenerator }") shouldBe MethodCall(Global, SGlobalMethods.groupGeneratorMethod, IndexedSeq(), EmptySubst)
comp(env, "{ Global.xor(arr1, arr2) }") shouldBe Xor(ByteArrayConstant(arr1), ByteArrayConstant(arr2))
comp(env, "{ xor(arr1, arr2) }") shouldBe Xor(ByteArrayConstant(arr1), ByteArrayConstant(arr2))
}
@@ -221,24 +220,24 @@ class SigmaCompilerTest extends CompilerTestingCommons with LangTests with Objec
comp("Coll(true, false).indices") shouldBe
mkMethodCall(
ConcreteCollection.fromItems(TrueLeaf, FalseLeaf),
- SCollection.IndicesMethod.withConcreteTypes(Map(SCollection.tIV -> SBoolean)),
+ SCollectionMethods.IndicesMethod.withConcreteTypes(Map(SCollection.tIV -> SBoolean)),
Vector()
)
}
property("SBox.tokens") {
comp("SELF.tokens") shouldBe
- mkMethodCall(Self, SBox.tokensMethod, IndexedSeq())
+ mkMethodCall(Self, SBoxMethods.tokensMethod, IndexedSeq())
}
property("SContext.dataInputs") {
comp("CONTEXT.dataInputs") shouldBe
- mkMethodCall(Context, SContext.dataInputsMethod, IndexedSeq())
+ mkMethodCall(Context, SContextMethods.dataInputsMethod, IndexedSeq())
}
property("SAvlTree.digest") {
comp("getVar[AvlTree](1).get.digest") shouldBe
- mkMethodCall(GetVar(1.toByte, SAvlTree).get, SAvlTree.digestMethod, IndexedSeq())
+ mkMethodCall(GetVar(1.toByte, SAvlTree).get, SAvlTreeMethods.digestMethod, IndexedSeq())
}
property("SGroupElement.exp") {
@@ -250,7 +249,7 @@ class SigmaCompilerTest extends CompilerTestingCommons with LangTests with Objec
property("SOption.map") {
comp("getVar[Int](1).map({(i: Int) => i + 1})") shouldBe
mkMethodCall(GetVarInt(1),
- SOption.MapMethod.withConcreteTypes(Map(SType.tT -> SInt, SType.tR -> SInt)),
+ SOptionMethods.MapMethod.withConcreteTypes(Map(SType.tT -> SInt, SType.tR -> SInt)),
IndexedSeq(FuncValue(
Vector((1, SInt)),
Plus(ValUse(1, SInt), IntConstant(1)))), Map()
@@ -260,7 +259,7 @@ class SigmaCompilerTest extends CompilerTestingCommons with LangTests with Objec
property("SOption.filter") {
comp("getVar[Int](1).filter({(i: Int) => i > 0})") shouldBe
mkMethodCall(GetVarInt(1),
- SOption.FilterMethod.withConcreteTypes(Map(SType.tT -> SInt)),
+ SOptionMethods.FilterMethod.withConcreteTypes(Map(SType.tT -> SInt)),
IndexedSeq(FuncValue(
Vector((1, SInt)),
GT(ValUse(1, SInt), IntConstant(0)))), Map()
@@ -271,7 +270,7 @@ class SigmaCompilerTest extends CompilerTestingCommons with LangTests with Objec
comp("Coll(1, 2).patch(1, Coll(3), 1)") shouldBe
mkMethodCall(
ConcreteCollection.fromItems(IntConstant(1), IntConstant(2)),
- SCollection.PatchMethod.withConcreteTypes(Map(SCollection.tIV -> SInt)),
+ SCollectionMethods.PatchMethod.withConcreteTypes(Map(SCollection.tIV -> SInt)),
Vector(IntConstant(1), ConcreteCollection.fromItems(IntConstant(3)), IntConstant(1)),
Map())
}
@@ -280,7 +279,7 @@ class SigmaCompilerTest extends CompilerTestingCommons with LangTests with Objec
comp("Coll(1, 2).updated(1, 1)") shouldBe
mkMethodCall(
ConcreteCollection.fromItems(IntConstant(1), IntConstant(2)),
- SCollection.UpdatedMethod.withConcreteTypes(Map(SCollection.tIV -> SInt)),
+ SCollectionMethods.UpdatedMethod.withConcreteTypes(Map(SCollection.tIV -> SInt)),
Vector(IntConstant(1), IntConstant(1)),
Map())
}
@@ -289,7 +288,7 @@ class SigmaCompilerTest extends CompilerTestingCommons with LangTests with Objec
comp("Coll(1, 2).updateMany(Coll(1), Coll(3))") shouldBe
mkMethodCall(
ConcreteCollection.fromItems(IntConstant(1), IntConstant(2)),
- SCollection.UpdateManyMethod.withConcreteTypes(Map(SCollection.tIV -> SInt)),
+ SCollectionMethods.UpdateManyMethod.withConcreteTypes(Map(SCollection.tIV -> SInt)),
Vector(ConcreteCollection.fromItems(IntConstant(1)), ConcreteCollection.fromItems(IntConstant(3))),
Map())
}
@@ -298,7 +297,7 @@ class SigmaCompilerTest extends CompilerTestingCommons with LangTests with Objec
comp("Coll(1, 2).indexOf(1, 0)") shouldBe
mkMethodCall(
ConcreteCollection.fromItems(IntConstant(1), IntConstant(2)),
- SCollection.IndexOfMethod.withConcreteTypes(Map(SCollection.tIV -> SInt)),
+ SCollectionMethods.IndexOfMethod.withConcreteTypes(Map(SCollection.tIV -> SInt)),
Vector(IntConstant(1), IntConstant(0)),
Map())
}
@@ -307,7 +306,7 @@ class SigmaCompilerTest extends CompilerTestingCommons with LangTests with Objec
comp("Coll(1, 2).zip(Coll(1, 1))") shouldBe
mkMethodCall(
ConcreteCollection.fromItems(IntConstant(1), IntConstant(2)),
- SCollection.ZipMethod.withConcreteTypes(Map(SCollection.tIV -> SInt, SCollection.tOV -> SInt)),
+ SCollectionMethods.ZipMethod.withConcreteTypes(Map(SCollection.tIV -> SInt, SCollection.tOV -> SInt)),
Vector(ConcreteCollection.fromItems(IntConstant(1), IntConstant(1)))
)
}
diff --git a/sc/shared/src/test/scala/sigmastate/lang/SigmaTemplateCompilerTest.scala b/sc/shared/src/test/scala/sigmastate/lang/SigmaTemplateCompilerTest.scala
new file mode 100644
index 0000000000..df8f644172
--- /dev/null
+++ b/sc/shared/src/test/scala/sigmastate/lang/SigmaTemplateCompilerTest.scala
@@ -0,0 +1,88 @@
+package sigmastate.lang
+
+import org.ergoplatform.ErgoAddressEncoder
+import org.ergoplatform.sdk.Parameter
+import org.scalatest.matchers.should.Matchers
+import org.scalatest.propspec.AnyPropSpec
+import org.scalatestplus.scalacheck.ScalaCheckPropertyChecks
+import sigma.ast.{IntConstant, SInt, SLong, SString, StringConstant}
+import sigmastate.eval.CompiletimeIRContext
+
+class SigmaTemplateCompilerTest extends AnyPropSpec with ScalaCheckPropertyChecks with Matchers {
+ property("compiles full contract template") {
+ val source =
+ """/** This is my contracts description.
+ |* Here is another line describing what it does in more detail.
+ |*
+ |* @param p1 describe p1
+ |* @param p2 description of the 2nd parameter
+ |* which is pretty complex and on many
+ |* lines to describe functions
+ |* @param param3 the final parameter
+ |* @return
+ |*/
+ |@contract def contractName(p1: Int = 5, p2: String = "default string", param3: Long) = {
+ | sigmaProp(true)
+ |}""".stripMargin
+ val compiler = SigmaTemplateCompiler(ErgoAddressEncoder.MainnetNetworkPrefix)
+ val template = compiler.compile(Map.empty, source)
+
+ template.name shouldBe "contractName"
+ template.description shouldBe "This is my contracts description. Here is another line describing what it does in more detail."
+ template.parameters should contain theSameElementsInOrderAs IndexedSeq(
+ Parameter("p1", "describe p1", 0),
+ Parameter("p2", "description of the 2nd parameter which is pretty complex and on many lines to describe functions", 1),
+ Parameter("param3", "the final parameter", 2)
+ )
+ template.constTypes should contain theSameElementsInOrderAs Seq(SInt, SString, SLong)
+ template.constValues.get should contain theSameElementsInOrderAs IndexedSeq(
+ Some(IntConstant(5).asWrappedType),
+ Some(StringConstant("default string").asWrappedType),
+ None
+ )
+
+ val sigmaCompiler = new SigmaCompiler(ErgoAddressEncoder.MainnetNetworkPrefix)
+ implicit val ir = new CompiletimeIRContext
+ val result = sigmaCompiler.compile(Map.empty, "{ sigmaProp(true) }")
+
+ template.expressionTree shouldBe result.buildTree
+ }
+
+ property("compiles contract template without braces") {
+ val source =
+ """/** This is my contracts description.
+ |* Here is another line describing what it does in more detail.
+ |*
+ |* @param p1 describe p1
+ |* @param p2 description of the 2nd parameter
+ |* which is pretty complex and on many
+ |
+ |* lines to describe functions
+ |* @return
+ |*/
+ |@contract def contractName(p1: Int = 5, p2: String = "default string") = sigmaProp(true)
+ |""".stripMargin
+ val compiler = SigmaTemplateCompiler(ErgoAddressEncoder.MainnetNetworkPrefix)
+ val template = compiler.compile(Map.empty, source)
+
+ template.name shouldBe "contractName"
+ template.description shouldBe "This is my contracts description. Here is another line describing what it does in more detail."
+ template.parameters should contain theSameElementsInOrderAs IndexedSeq(
+ Parameter("p1", "describe p1", 0),
+ Parameter("p2", "description of the 2nd parameter which is pretty complex and on many lines to describe functions", 1)
+ )
+ template.constTypes should contain theSameElementsInOrderAs Seq(SInt, SString)
+ template.constValues.get should contain theSameElementsInOrderAs IndexedSeq(
+ Some(IntConstant(5).asWrappedType),
+ Some(StringConstant("default string").asWrappedType)
+ )
+
+ val sigmaCompiler = new SigmaCompiler(ErgoAddressEncoder.MainnetNetworkPrefix)
+ implicit val ir = new CompiletimeIRContext
+ val result = sigmaCompiler.compile(Map.empty, "sigmaProp(true)")
+
+ template.expressionTree shouldBe result.buildTree
+ }
+}
+
+
diff --git a/sc/shared/src/test/scala/sigmastate/lang/SigmaTyperTest.scala b/sc/shared/src/test/scala/sigmastate/lang/SigmaTyperTest.scala
index b12938db03..99ad2ae908 100644
--- a/sc/shared/src/test/scala/sigmastate/lang/SigmaTyperTest.scala
+++ b/sc/shared/src/test/scala/sigmastate/lang/SigmaTyperTest.scala
@@ -6,19 +6,20 @@ import org.scalatest.matchers.should.Matchers
import org.scalatest.propspec.AnyPropSpec
import org.scalatestplus.scalacheck.ScalaCheckPropertyChecks
import sigma.Colls
-import sigmastate.SCollection._
-import sigmastate.Values._
+import sigma.ast.SCollection._
+import sigma.ast._
+import sigma.ast.syntax.{SValue, SigmaPropValue, SigmaPropValueOps}
+import sigma.crypto.CryptoConstants
+import sigma.data.ProveDlog
import sigmastate._
-import sigmastate.crypto.CryptoConstants
-import sigmastate.crypto.DLogProtocol.{DLogProverInput, ProveDlog}
-import sigmastate.exceptions.TyperException
+import sigmastate.crypto.DLogProtocol.DLogProverInput
import sigmastate.interpreter.Interpreter.ScriptEnv
-import sigmastate.lang.SigmaPredef._
-import sigmastate.lang.Terms._
-import sigmastate.lang.syntax.ParserException
-import sigmastate.serialization.ErgoTreeSerializer
-import sigmastate.serialization.generators.ObjectGenerators
-import sigmastate.utxo.{Append, ExtractCreationInfo}
+import SigmaPredef._
+import sigmastate.lang.parsers.ParserException
+import sigma.serialization.ErgoTreeSerializer
+import sigma.serialization.generators.ObjectGenerators
+import sigma.ast.Select
+import sigma.exceptions.TyperException
class SigmaTyperTest extends AnyPropSpec
with ScalaCheckPropertyChecks with Matchers with LangTests with ObjectGenerators {
@@ -638,7 +639,7 @@ class SigmaTyperTest extends AnyPropSpec
property("substConst") {
def script(pk: ProveDlog): SigmaPropValue =
- AND(EQ(IntConstant(1), IntConstant(1)), SigmaPropConstant(pk).isProven).toSigmaProp
+ AND(EQ(IntConstant(1), IntConstant(1)), SigmaPropIsProven(SigmaPropConstant(pk))).toSigmaProp
val pk1 = DLogProverInput.random().publicImage
val pk2 = DLogProverInput.random().publicImage
diff --git a/sc/shared/src/test/scala/sigmastate/serialization/DeserializationResilience.scala b/sc/shared/src/test/scala/sigmastate/serialization/DeserializationResilience.scala
index 52ef46c642..f4344fbf8d 100644
--- a/sc/shared/src/test/scala/sigmastate/serialization/DeserializationResilience.scala
+++ b/sc/shared/src/test/scala/sigmastate/serialization/DeserializationResilience.scala
@@ -1,28 +1,29 @@
-package sigmastate.serialization
+package sigma.serialization
-import org.ergoplatform.validation.ValidationException
-import org.ergoplatform.validation.ValidationRules.CheckPositionLimit
-import org.ergoplatform.{ErgoBoxCandidate, Outputs}
+import org.ergoplatform.ErgoBoxCandidate
import org.scalacheck.Gen
-import sigma.util.BenchmarkUtil
import scorex.crypto.authds.avltree.batch.{BatchAVLProver, Insert}
import scorex.crypto.authds.{ADKey, ADValue}
import scorex.crypto.hash.{Blake2b256, Digest32}
import scorex.util.serialization.{Reader, VLQByteBufferReader}
+import sigma.ast.{SBoolean, SInt, SizeOf}
+import sigma.data.{AvlTreeData, AvlTreeFlags, CAND, SigmaBoolean}
+import sigma.util.{BenchmarkUtil, safeNewArray}
+import sigma.validation.ValidationException
+import sigma.validation.ValidationRules.CheckPositionLimit
import sigma.{Colls, Environment}
-import sigmastate.Values.{BlockValue, GetVarInt, IntConstant, SValue, SigmaBoolean, SigmaPropValue, Tuple, ValDef, ValUse}
+import sigma.ast._
+import sigma.ast.syntax._
import sigmastate._
-import sigmastate.crypto.CryptoConstants
-import sigmastate.eval.Extensions._
+import sigma.Extensions.ArrayOps
+import sigma.eval.Extensions.SigmaBooleanOps
+import sigma.eval.SigmaDsl
+import sigma.interpreter.{ContextExtension, CostedProverResult}
+import sigma.eval.Extensions.EvalIterableOps
import sigmastate.eval._
-import sigmastate.exceptions.{DeserializeCallDepthExceeded, InvalidTypePrefix, ReaderPositionLimitExceeded, SerializerException}
import sigmastate.helpers.{CompilerTestingCommons, ErgoLikeContextTesting, ErgoLikeTestInterpreter}
-import sigmastate.interpreter.{ContextExtension, CostedProverResult}
-import sigmastate.serialization.OpCodes._
-import sigma.util.safeNewArray
+import sigma.serialization.OpCodes._
import sigmastate.utils.Helpers._
-import sigmastate.utils.SigmaByteReader
-import sigmastate.utxo.SizeOf
import java.nio.ByteBuffer
import scala.collection.immutable.Seq
@@ -120,8 +121,8 @@ class DeserializationResilience extends DeserializationResilienceTesting {
property("exceeding ergo box propositionBytes max size check") {
val oversizedTree = mkTestErgoTree(SigmaAnd(
- Gen.listOfN(SigmaSerializer.MaxPropositionSize / CryptoConstants.groupSize,
- proveDlogGen.map(_.toSigmaProp)).sample.get))
+ Gen.listOfN(SigmaSerializer.MaxPropositionSize / sigma.crypto.groupSize,
+ proveDlogGen.map(_.toSigmaPropValue)).sample.get))
val b = new ErgoBoxCandidate(1L, oversizedTree, 1)
val w = SigmaSerializer.startWriter()
ErgoBoxCandidate.serializer.serialize(b, w)
@@ -137,7 +138,7 @@ class DeserializationResilience extends DeserializationResilienceTesting {
{
case SerializerException(_,
Some(ValidationException(_,CheckPositionLimit,_,
- Some(_: ReaderPositionLimitExceeded)))) => true
+ Some(_: ReaderPositionLimitExceeded))), _) => true
case _ => false
})
case _ =>
@@ -159,8 +160,8 @@ class DeserializationResilience extends DeserializationResilienceTesting {
property("ergo box propositionBytes max size check") {
val bigTree = mkTestErgoTree(SigmaAnd(
- Gen.listOfN((SigmaSerializer.MaxPropositionSize / 2) / CryptoConstants.groupSize,
- proveDlogGen.map(_.toSigmaProp)).sample.get))
+ Gen.listOfN((SigmaSerializer.MaxPropositionSize / 2) / sigma.crypto.groupSize,
+ proveDlogGen.map(_.toSigmaPropValue)).sample.get))
val b = new ErgoBoxCandidate(1L, bigTree, 1)
val w = SigmaSerializer.startWriter()
ErgoBoxCandidate.serializer.serialize(b, w)
@@ -232,7 +233,9 @@ class DeserializationResilience extends DeserializationResilienceTesting {
property("reader.level is updated in DataSerializer.deserialize") {
val expr = IntConstant(1)
val (callDepths, levels) = traceReaderCallDepth(expr)
- callDepths shouldEqual levels
+ if (Environment.current.isJVM) {
+ callDepths shouldEqual levels // on JS stacktrace differs from JVM
+ }
callDepths shouldEqual IndexedSeq(1, 2, 2, 1)
}
@@ -245,7 +248,9 @@ class DeserializationResilience extends DeserializationResilienceTesting {
property("reader.level is updated in SigmaBoolean.serializer.parse") {
val expr = CAND(Seq(proveDlogGen.sample.get, proveDHTGen.sample.get))
val (callDepths, levels) = traceReaderCallDepth(expr)
- callDepths shouldEqual levels
+ if (Environment.current.isJVM) {
+ callDepths shouldEqual levels // on JS stacktrace differs from JVM
+ }
callDepths shouldEqual IndexedSeq(1, 2, 3, 4, 4, 4, 4, 3, 2, 1)
}
@@ -258,7 +263,9 @@ class DeserializationResilience extends DeserializationResilienceTesting {
property("reader.level is updated in TypeSerializer") {
val expr = Tuple(Tuple(IntConstant(1), IntConstant(1)), IntConstant(1))
val (callDepths, levels) = traceReaderCallDepth(expr)
- callDepths shouldEqual levels
+ if (Environment.current.isJVM) {
+ callDepths shouldEqual levels // on JS stacktrace differs from JVM
+ }
callDepths shouldEqual IndexedSeq(1, 2, 3, 4, 4, 3, 3, 4, 4, 3, 2, 2, 3, 3, 2, 1)
}
@@ -270,8 +277,8 @@ class DeserializationResilience extends DeserializationResilienceTesting {
property("exceed ergo box max size check") {
val bigTree = mkTestErgoTree(SigmaAnd(
- Gen.listOfN((SigmaSerializer.MaxPropositionSize / 2) / CryptoConstants.groupSize,
- proveDlogGen.map(_.toSigmaProp)).sample.get))
+ Gen.listOfN((SigmaSerializer.MaxPropositionSize / 2) / sigma.crypto.groupSize,
+ proveDlogGen.map(_.toSigmaPropValue)).sample.get))
val tokens = additionalTokensGen(127).sample.get.map(_.sample.get).toColl
val b = new ErgoBoxCandidate(1L, bigTree, 1, tokens)
val w = SigmaSerializer.startWriter()
@@ -413,7 +420,7 @@ class DeserializationResilience extends DeserializationResilienceTesting {
val v = k
avlProver.performOneOperation(Insert(ADKey @@@ k, ADValue @@@ v))
val proof = avlProver.generateProof()
- val verifier = AvlTreeVerifier(tree, Colls.fromArray(proof))
+ val verifier = CAvlTreeVerifier(tree, Colls.fromArray(proof))
verifier.performOneOperation(Insert(ADKey @@@ k, ADValue @@@ v)).isFailure shouldBe true
// NOTE, even though performOneOperation fails, some AvlTree$ methods used in Interpreter
// (remove_eval, update_eval, contains_eval) won't throw, while others will.
diff --git a/sc/shared/src/test/scala/sigmastate/serialization/ErgoTreeSerializerSpecification.scala b/sc/shared/src/test/scala/sigmastate/serialization/ErgoTreeSerializerSpecification.scala
index c4d8ebf13d..e20d8a6d1e 100644
--- a/sc/shared/src/test/scala/sigmastate/serialization/ErgoTreeSerializerSpecification.scala
+++ b/sc/shared/src/test/scala/sigmastate/serialization/ErgoTreeSerializerSpecification.scala
@@ -1,16 +1,22 @@
-package sigmastate.serialization
+package sigma.serialization
-import java.math.BigInteger
import org.ergoplatform.ErgoBox
-import org.ergoplatform.validation.ValidationException
import org.ergoplatform.validation.ValidationRules.CheckDeserializedScriptIsSigmaProp
-import sigmastate.Values.{BigIntConstant, ByteConstant, ConstantPlaceholder, ErgoTree, IntConstant, ShortConstant, SigmaPropValue, UnparsedErgoTree}
+import sigma.SigmaProp
+import sigma.ast._
+import sigma.ast.syntax.SigmaPropValue
+import sigma.data.CBigInt
+import sigma.util.Extensions.SigmaPropOps
+import sigma.validation.ValidationException
+import ErgoTree.EmptyConstants
+import ErgoTree.HeaderType
+import sigma.eval.Extensions.SigmaBooleanOps
import sigmastate._
-import sigmastate.eval.{CBigInt, IRContext}
-import sigmastate.exceptions.{SerializerException, ReaderPositionLimitExceeded}
+import sigmastate.eval.IRContext
import sigmastate.helpers.CompilerTestingCommons
-import sigmastate.serialization.ErgoTreeSerializer.DefaultSerializer
-import sigmastate.utxo.{DeserializeContext, DeserializeRegister}
+import sigma.serialization.ErgoTreeSerializer.DefaultSerializer
+
+import java.math.BigInteger
class ErgoTreeSerializerSpecification extends SerializationSpecification
with CompilerTestingCommons with CompilerCrossVersionProps {
@@ -32,7 +38,7 @@ class ErgoTreeSerializerSpecification extends SerializationSpecification
Seq(ErgoTree(ergoTreeHeaderInTests, constants, outExpr))
} else {
Seq(
- ErgoTree((ConstantSegregationHeader | ergoTreeHeaderInTests).toByte, constants, outExpr),
+ ErgoTree(setConstantSegregation(ergoTreeHeaderInTests), constants, outExpr),
ErgoTree(ergoTreeHeaderInTests, EmptyConstants, prop)
)
}
@@ -171,7 +177,7 @@ class ErgoTreeSerializerSpecification extends SerializationSpecification
forAll(samples) { (exp, hasDeserialize) =>
val t = new ErgoTree(
- 16.toByte,
+ HeaderType @@ 16.toByte,
Array(IntConstant(1)),
Right(BoolToSigmaProp(EQ(ConstantPlaceholder(0, SInt), exp)))
)
@@ -207,4 +213,13 @@ class ErgoTreeSerializerSpecification extends SerializationSpecification
test(positions = Array(1, 2), expected = Array(-1, 0, 1, -1, -1))
test(positions = Array(1, 2, 4), expected = Array(-1, 0, 1, -1, 2))
}
+
+ property("SigmaProp.propBytes vs ErgoTree.serializer equivalence") {
+ forAll(MinSuccessful(100)) { sp: SigmaProp =>
+ val propBytes = sp.propBytes
+ val ergoTree = new ErgoTree(ErgoTree.DefaultHeader, EmptyConstants, Right(sp.toSigmaBoolean.toSigmaPropValue), null, None, None)
+ val treeBytes = DefaultSerializer.serializeErgoTree(ergoTree)
+ treeBytes shouldBe propBytes.toArray
+ }
+ }
}
diff --git a/sc/shared/src/test/scala/sigmastate/utils/GenInfoObjects.scala b/sc/shared/src/test/scala/sigmastate/utils/GenInfoObjects.scala
index 9ebdce9f31..78962f20e3 100644
--- a/sc/shared/src/test/scala/sigmastate/utils/GenInfoObjects.scala
+++ b/sc/shared/src/test/scala/sigmastate/utils/GenInfoObjects.scala
@@ -1,6 +1,6 @@
package sigmastate.utils
-import sigmastate.SMethod
+import sigma.ast.SMethod
import sigma.util.PrintExtensions._
import scala.util.Try
import Helpers._ // required for Scala 2.11
diff --git a/sc/shared/src/test/scala/sigmastate/utils/SpecGen.scala b/sc/shared/src/test/scala/sigmastate/utils/SpecGen.scala
index 7eccb1dd00..4c56580c9b 100644
--- a/sc/shared/src/test/scala/sigmastate/utils/SpecGen.scala
+++ b/sc/shared/src/test/scala/sigmastate/utils/SpecGen.scala
@@ -1,18 +1,16 @@
package sigmastate.utils
-import sigma.util.PrintExtensions.IterableExtensions
-import sigmastate._
-import sigmastate.eval.Evaluation._
-import sigma.util.Extensions.ByteOps
+import sigma.Evaluation._
+import sigma.ast.TypeCodes.LastConstantCode
+import sigma.ast._
+import sigma.serialization.CoreByteWriter.ArgInfo
import sigma.util.CollectionUtil
+import sigma.util.Extensions.ByteOps
import sigma.util.PrintExtensions._
-import sigmastate.Values._
-import sigmastate.lang.SigmaPredef.{PredefinedFunc, PredefinedFuncRegistry}
-import sigmastate.lang.StdSigmaBuilder
-import sigmastate.lang.Terms.{MethodCall, PropertyCall}
-import sigmastate.serialization.OpCodes.OpCode
-import sigmastate.serialization.{OpCodes, ValueSerializer}
-import sigmastate.utxo.{SelectField, SigmaPropIsProven}
+import SigmaPredef.{PredefinedFunc, PredefinedFuncRegistry}
+import sigma.ast.{MethodCall, PropertyCall}
+import sigma.serialization.ValueCodes.OpCode
+import sigma.serialization.ValueSerializer
object SpecGenUtils {
val types = SType.allPredefTypes.diff(Seq(SString))
@@ -29,8 +27,8 @@ trait SpecGen {
description: String,
args: Seq[ArgInfo], op: Either[PredefinedFunc, SMethod])
- def collectSerializers(): Seq[ValueSerializer[_ <: Values.Value[SType]]] = {
- ((OpCodes.LastConstantCode + 1) to 255).collect {
+ def collectSerializers(): Seq[ValueSerializer[_ <: Value[SType]]] = {
+ ((LastConstantCode + 1) to 255).collect {
case i if ValueSerializer.serializers(i.toByte) != null =>
val ser = ValueSerializer.serializers(i.toByte)
assert(i == ser.opDesc.opCode.toUByte)
@@ -39,7 +37,7 @@ trait SpecGen {
}
def collectFreeCodes(): Seq[Int] = {
- ((OpCodes.LastConstantCode + 1) to 255).collect {
+ ((LastConstantCode + 1) to 255).collect {
case i if ValueSerializer.serializers(i.toByte) == null => i
}
}
@@ -47,7 +45,8 @@ trait SpecGen {
def collectMethods(): Seq[SMethod] = {
for {
tc <- typesWithMethods.sortBy(_.typeId)
- m <- tc.methods.sortBy(_.methodId)
+ mc = MethodsContainer(tc.typeId)
+ m <- mc.methods.sortBy(_.methodId)
} yield m
}
@@ -215,7 +214,8 @@ trait SpecGen {
}
def printMethods(tc: STypeCompanion) = {
- val methodSubsections = for { m <- tc.methods.sortBy(_.methodId) } yield {
+ val mc = MethodsContainer(tc.typeId)
+ val methodSubsections = for { m <- mc.methods.sortBy(_.methodId) } yield {
methodSubsection(tc.typeName, m)
}
val res = methodSubsections.mkString("\n\n")
@@ -252,7 +252,7 @@ object GenPrimOpsApp extends SpecGen {
val methods = collectMethods()
val ops = collectSerializableOperations()
val noOps = Set(
- TaggedVariable, ValUse, ConstantPlaceholder, TrueLeaf, FalseLeaf,
+ ValUse, ConstantPlaceholder, TrueLeaf, FalseLeaf,
ConcreteCollection, ConcreteCollectionBooleanConstant, Tuple, SelectField, SigmaPropIsProven, ValDef, FunDef, BlockValue
)
diff --git a/sc/shared/src/test/scala/sigmastate/utxo/AVLTreeScriptsSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/AVLTreeScriptsSpecification.scala
index 5133692685..566bf5bd58 100644
--- a/sc/shared/src/test/scala/sigmastate/utxo/AVLTreeScriptsSpecification.scala
+++ b/sc/shared/src/test/scala/sigmastate/utxo/AVLTreeScriptsSpecification.scala
@@ -5,20 +5,25 @@ import org.ergoplatform._
import org.ergoplatform.dsl.{ContractSpec, SigmaContractSyntax, TestContractSpec}
import scorex.crypto.authds.avltree.batch._
import scorex.crypto.authds.{ADKey, ADValue, SerializedAdProof}
-import scorex.crypto.hash.{Digest32, Blake2b256}
-import sigmastate.SCollection.SByteArray
-import sigmastate.Values._
+import scorex.crypto.hash.{Blake2b256, Digest32}
+import sigma.ast.SCollection.SByteArray
+import sigma.ast._
import sigmastate._
-import sigmastate.eval.{CSigmaProp, IRContext}
+import sigmastate.eval.IRContext
import sigmastate.eval._
-import sigmastate.eval.Extensions._
-import sigmastate.helpers.{ContextEnrichingTestProvingInterpreter, ErgoLikeContextTesting, ErgoLikeTestInterpreter, CompilerTestingCommons}
+import sigma.Extensions.ArrayOps
+import sigmastate.helpers.{CompilerTestingCommons, ContextEnrichingTestProvingInterpreter, ErgoLikeContextTesting, ErgoLikeTestInterpreter}
import sigmastate.helpers.TestingHelpers._
import sigmastate.interpreter.Interpreter.ScriptNameProp
-import sigmastate.interpreter.ProverResult
-import sigmastate.lang.Terms._
+import sigma.ast.syntax._
import sigma.Coll
+import sigma.ast.SAvlTree
+import sigma.ast.syntax.{GetVarByteArray, OptionValueOps}
+import sigma.data.{AvlTreeData, AvlTreeFlags, CSigmaProp, TrivialProp}
+import sigma.eval.SigmaDsl
+import sigma.interpreter.ProverResult
import sigma.{AvlTree, Context}
+import sigmastate.eval.Extensions.AvlTreeOps
class AVLTreeScriptsSpecification extends CompilerTestingCommons
@@ -204,12 +209,12 @@ class AVLTreeScriptsSpecification extends CompilerTestingCommons
val propExp = IR.builder.mkMethodCall(
ExtractRegisterAs[SAvlTree.type](Self, reg1).get,
- SAvlTree.containsMethod,
+ SAvlTreeMethods.containsMethod,
IndexedSeq(ByteArrayConstant(key), ByteArrayConstant(proof))
).asBoolValue.toSigmaProp
prop shouldBe propExp
- val newBox1 = testBox(10, pubkey, 0)
+ val newBox1 = testBox(10, ErgoTree.fromSigmaBoolean(pubkey), 0)
val newBoxes = IndexedSeq(newBox1)
val spendingTransaction = createTransaction(newBoxes)
@@ -257,7 +262,7 @@ class AVLTreeScriptsSpecification extends CompilerTestingCommons
lastBlockUtxoRoot = AvlTreeData.dummy,
minerPubkey = ErgoLikeContextTesting.dummyPubkey,
boxesToSpend = IndexedSeq(selfBox),
- createTransaction(testBox(1, recipientProposition, 0)),
+ createTransaction(testBox(1, ErgoTree.fromSigmaBoolean(recipientProposition), 0)),
self = selfBox, activatedVersionInTests)
avlProver.performOneOperation(Lookup(treeElements.head._1))
@@ -320,12 +325,12 @@ class AVLTreeScriptsSpecification extends CompilerTestingCommons
val propExp = IR.builder.mkMethodCall(
ExtractRegisterAs[SAvlTree.type](Self, reg1).get,
- SAvlTree.containsMethod,
+ SAvlTreeMethods.containsMethod,
IndexedSeq(ExtractRegisterAs[SByteArray](Self, reg2).get, GetVarByteArray(proofId).get)
).asBoolValue.toSigmaProp
prop shouldBe propExp
- val newBox1 = testBox(10, pubkey, 0)
+ val newBox1 = testBox(10, ErgoTree.fromSigmaBoolean(pubkey), 0)
val newBoxes = IndexedSeq(newBox1)
val spendingTransaction = createTransaction(newBoxes)
@@ -379,7 +384,7 @@ class AVLTreeScriptsSpecification extends CompilerTestingCommons
val propTree = ErgoTree.fromProposition(ergoTreeHeaderInTests, prop)
- val newBox1 = testBox(10, pubkey, 0)
+ val newBox1 = testBox(10, ErgoTree.fromSigmaBoolean(pubkey), 0)
val newBoxes = IndexedSeq(newBox1)
val spendingTransaction = ErgoLikeTransaction(IndexedSeq(), newBoxes)
diff --git a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala
index eddd607178..346ad69e1a 100644
--- a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala
+++ b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala
@@ -1,25 +1,27 @@
package sigmastate.utxo
-import java.math.BigInteger
import org.ergoplatform.ErgoBox.{AdditionalRegisters, R6, R8}
import org.ergoplatform._
-import sigma.data.RType
-import sigmastate.SCollection.SByteArray
-import sigmastate.Values._
+import sigma.Extensions.ArrayOps
+import sigma.ast.SCollection.SByteArray
+import sigma.ast.SType.AnyOps
+import sigma.data.{AvlTreeData, CAnyValue}
+import sigma.util.StringUtil._
+import sigma.ast._
+import sigma.ast.syntax._
+import sigma.crypto.CryptoConstants
import sigmastate._
-import sigmastate.eval.Extensions._
-import sigmastate.helpers.{CompilerTestingCommons, ContextEnrichingTestProvingInterpreter, ErgoLikeContextTesting, ErgoLikeTestInterpreter}
import sigmastate.helpers.TestingHelpers._
+import sigmastate.helpers.{CompilerTestingCommons, ContextEnrichingTestProvingInterpreter, ErgoLikeContextTesting, ErgoLikeTestInterpreter}
+import sigma.interpreter.ContextExtension.VarBinding
+import sigmastate.interpreter.CErgoTreeEvaluator.DefaultEvalSettings
import sigmastate.interpreter.Interpreter._
-import sigmastate.lang.Terms._
-import SType.AnyOps
-import sigmastate.crypto.CryptoConstants
-import sigmastate.eval.{CAnyValue, InvalidType}
-import sigmastate.interpreter.ContextExtension.VarBinding
-import sigmastate.interpreter.ErgoTreeEvaluator.DefaultEvalSettings
-import sigmastate.interpreter.EvalSettings
+import sigma.ast.Apply
+import sigma.eval.EvalSettings
+import sigma.exceptions.InvalidType
import sigmastate.utils.Helpers._
-import sigma.util.StringUtil._
+
+import java.math.BigInteger
class BasicOpsSpecification extends CompilerTestingCommons
with CompilerCrossVersionProps {
diff --git a/sc/shared/src/test/scala/sigmastate/utxo/CollectionOperationsSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/CollectionOperationsSpecification.scala
index 54f0d1dc04..0de1a13f08 100644
--- a/sc/shared/src/test/scala/sigmastate/utxo/CollectionOperationsSpecification.scala
+++ b/sc/shared/src/test/scala/sigmastate/utxo/CollectionOperationsSpecification.scala
@@ -1,14 +1,19 @@
package sigmastate.utxo
-import sigmastate.Values._
+import sigma.ast._
import sigmastate._
-import sigmastate.helpers.{ContextEnrichingTestProvingInterpreter, ErgoLikeContextTesting, ErgoLikeTestInterpreter, CompilerTestingCommons}
+import sigmastate.helpers.{CompilerTestingCommons, ContextEnrichingTestProvingInterpreter, ErgoLikeContextTesting, ErgoLikeTestInterpreter}
import sigmastate.helpers.TestingHelpers._
-import sigmastate.lang.Terms._
+import sigma.ast.syntax._
import org.ergoplatform._
-import sigmastate.SCollection._
+import sigma.ast.SCollection._
+import sigma.data.AvlTreeData
+import SCollectionMethods.{FlatMapMethod, IndexOfMethod, IndicesMethod, PatchMethod, UpdateManyMethod, UpdatedMethod}
+import sigma.ast
import sigmastate.interpreter.Interpreter.{ScriptNameProp, emptyEnv}
-import sigmastate.serialization.OpCodes._
+import sigma.serialization.OpCodes._
+import sigma.ast.MethodCall
+import sigma.eval.Extensions.SigmaBooleanOps
import sigmastate.utils.Helpers._
class CollectionOperationsSpecification extends CompilerTestingCommons
@@ -87,7 +92,7 @@ class CollectionOperationsSpecification extends CompilerTestingCommons
val prover = new ContextEnrichingTestProvingInterpreter
val verifier = new ErgoLikeTestInterpreter
- val pubkey = prover.dlogSecrets.head.publicImage.toSigmaProp
+ val pubkey = prover.dlogSecrets.head.publicImage.toSigmaPropValue
val pubkeyTree = mkTestErgoTree(pubkey)
val prop = compile(Map(), "OUTPUTS.exists({ (box: Box) => box.value + 5 > 10 })").asBoolValue.toSigmaProp
@@ -202,7 +207,7 @@ class CollectionOperationsSpecification extends CompilerTestingCommons
val prover = new ContextEnrichingTestProvingInterpreter
val verifier = new ErgoLikeTestInterpreter
- val pubkey = prover.dlogSecrets.head.publicImage.toSigmaProp
+ val pubkey = prover.dlogSecrets.head.publicImage.toSigmaPropValue
val pubkeyTree = mkTestErgoTree(pubkey)
val prop = compile(Map(),
@@ -215,8 +220,8 @@ class CollectionOperationsSpecification extends CompilerTestingCommons
FuncValue(
Vector((1, SBox)),
EQ(
- utxo.ExtractRegisterAs[SLong.type](ValUse(1, SBox), reg1).get,
- Plus(utxo.ExtractRegisterAs[SLong.type](Self, reg1).get, LongConstant(1)))
+ ast.ExtractRegisterAs[SLong.type](ValUse(1, SBox), reg1).get,
+ Plus(ast.ExtractRegisterAs[SLong.type](Self, reg1).get, LongConstant(1)))
)
).toSigmaProp
prop shouldBe propExpected
@@ -258,8 +263,8 @@ class CollectionOperationsSpecification extends CompilerTestingCommons
FuncValue(
Vector((1, SBox)),
EQ(
- utxo.ExtractRegisterAs[SLong.type](ValUse(1, SBox), reg1).getOrElse(LongConstant(0)),
- Plus(utxo.ExtractRegisterAs[SLong.type](Self, reg1).get, LongConstant(1))
+ ast.ExtractRegisterAs[SLong.type](ValUse(1, SBox), reg1).getOrElse(LongConstant(0)),
+ Plus(ast.ExtractRegisterAs[SLong.type](Self, reg1).get, LongConstant(1))
)
)
).toSigmaProp
@@ -531,7 +536,7 @@ class CollectionOperationsSpecification extends CompilerTestingCommons
assertProof("OUTPUTS.zip(INPUTS).size == 2",
EQ(
SizeOf(MethodCall(Outputs,
- SCollection.ZipMethod.withConcreteTypes(Map(SCollection.tIV -> SBox, SCollection.tOV -> SBox)),
+ SCollectionMethods.ZipMethod.withConcreteTypes(Map(SCollection.tIV -> SBox, SCollection.tOV -> SBox)),
Vector(Inputs),
Map()).asCollection[STuple]),
IntConstant(2)),
diff --git a/sc/shared/src/test/scala/sigmastate/utxo/ComplexSigSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/ComplexSigSpecification.scala
index 89e734a6e8..961bc08020 100644
--- a/sc/shared/src/test/scala/sigmastate/utxo/ComplexSigSpecification.scala
+++ b/sc/shared/src/test/scala/sigmastate/utxo/ComplexSigSpecification.scala
@@ -1,11 +1,11 @@
package sigmastate.utxo
-import org.ergoplatform.Height
import org.scalacheck.Gen
-import sigmastate.Values.IntConstant
+import sigma.data.{AvlTreeData, CAND, COR, CTHRESHOLD}
+import sigma.ast.{GT, Height, IntConstant, SigmaAnd, SigmaOr}
import sigmastate._
import sigmastate.helpers._
-import sigmastate.lang.Terms._
+import sigma.ast.syntax._
import scala.util.Random
diff --git a/sc/shared/src/test/scala/sigmastate/utxo/ContextEnrichingSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/ContextEnrichingSpecification.scala
index 6c84a5f54f..fe3dac68b3 100644
--- a/sc/shared/src/test/scala/sigmastate/utxo/ContextEnrichingSpecification.scala
+++ b/sc/shared/src/test/scala/sigmastate/utxo/ContextEnrichingSpecification.scala
@@ -2,9 +2,9 @@ package sigmastate.utxo
import scorex.util.encode.Base16
import scorex.crypto.hash.Blake2b256
-import sigmastate.Values._
+import sigma.ast._
+import sigma.ast.syntax._
import sigmastate._
-import sigmastate.lang.Terms._
import sigmastate.helpers.{ContextEnrichingTestProvingInterpreter, ErgoLikeContextTesting, ErgoLikeTestInterpreter, CompilerTestingCommons}
import sigma.Coll
diff --git a/sc/shared/src/test/scala/sigmastate/utxo/DistributedSigSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/DistributedSigSpecification.scala
index 9276413e1e..74c28c2ec9 100644
--- a/sc/shared/src/test/scala/sigmastate/utxo/DistributedSigSpecification.scala
+++ b/sc/shared/src/test/scala/sigmastate/utxo/DistributedSigSpecification.scala
@@ -1,9 +1,11 @@
package sigmastate.utxo
+import sigma.ast.ErgoTree
+import sigma.data.CAND
import sigmastate._
-import sigmastate.helpers.{ContextEnrichingTestProvingInterpreter, ErgoLikeTestProvingInterpreter, CompilerTestingCommons}
+import sigmastate.helpers.{CompilerTestingCommons, ContextEnrichingTestProvingInterpreter, ErgoLikeTestProvingInterpreter}
import sigmastate.interpreter._
-import sigmastate.lang.Terms._
+import sigma.ast.syntax._
/**
* Distributed signatures examples.
@@ -518,7 +520,10 @@ class DistributedSigSpecification extends CompilerTestingCommons
val sigAlice = proverA.signMessage(sigmaTree, msg, bagA).get
- val bagB = proverB.bagForMultisig(ctx, sigmaTree, sigAlice, Seq(pubkeyAlice))
+ val bagB = proverB.bagForMultisig(ctx,
+ ErgoTree.fromSigmaBoolean(ergoTreeHeaderInTests, sigmaTree),
+ proof = sigAlice,
+ realSecretsToExtract = Seq(pubkeyAlice))
.addHint(hintsFromBob.ownCommitments.head)
val sigBob = proverB.signMessage(sigmaTree, msg, bagB).get
diff --git a/sc/shared/src/test/scala/sigmastate/utxo/ErgoLikeInterpreterSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/ErgoLikeInterpreterSpecification.scala
index 58bbb522c6..615a826649 100644
--- a/sc/shared/src/test/scala/sigmastate/utxo/ErgoLikeInterpreterSpecification.scala
+++ b/sc/shared/src/test/scala/sigmastate/utxo/ErgoLikeInterpreterSpecification.scala
@@ -3,23 +3,23 @@ package sigmastate.utxo
import scorex.utils.Bytes
import org.ergoplatform.ErgoBox.R4
import org.ergoplatform._
-import org.ergoplatform.validation.ValidationException
import org.scalatest.TryValues._
import scorex.crypto.hash.Blake2b256
-import sigmastate.SCollection.SByteArray
-import sigmastate.Values._
+import sigma.ast.SCollection.SByteArray
+import sigma.ast._
import sigmastate._
+import sigma.ast.syntax._
+import sigma.data.{AvlTreeData, ProveDHTuple, ProveDlog, TrivialProp}
+import sigma.util.Extensions.EcpOps
+import sigma.validation.ValidationException
import sigmastate.eval._
-import sigmastate.eval.Extensions._
import sigmastate.interpreter.Interpreter._
-import sigmastate.crypto.DLogProtocol.ProveDlog
-import sigmastate.crypto.ProveDHTuple
import sigmastate.helpers._
import sigmastate.helpers.TestingHelpers._
-import sigmastate.interpreter.ContextExtension.VarBinding
-import sigmastate.interpreter.{ContextExtension, CostedProverResult}
-import sigmastate.lang.Terms._
-import sigmastate.serialization.{ValueSerializer, SerializationSpecification}
+import sigma.interpreter.ContextExtension.VarBinding
+import sigma.eval.Extensions.SigmaBooleanOps
+import sigma.interpreter.{ContextExtension, CostedProverResult}
+import sigma.serialization.{SerializationSpecification, ValueSerializer}
import sigmastate.utils.Helpers._
class ErgoLikeInterpreterSpecification extends CompilerTestingCommons
@@ -29,6 +29,15 @@ class ErgoLikeInterpreterSpecification extends CompilerTestingCommons
implicit lazy val IR: TestingIRContext = new TestingIRContext
private val reg1 = ErgoBox.nonMandatoryRegisters.head
+ def sum[T <: SNumericType](input: Value[SCollection[T]], varId: Int)(implicit tT: T) =
+ Fold(input,
+ Constant(tT.upcast(0.toByte), tT),
+ FuncValue(Array((varId, STuple(tT, tT))),
+ Plus(
+ SelectField(ValUse(varId, STuple(tT, tT)), 1).asNumValue,
+ SelectField(ValUse(varId, STuple(tT, tT)), 2).asNumValue))
+ )
+
property("scripts EQ/NEQ") {
val prover1 = new ContextEnrichingTestProvingInterpreter
val prover2 = new ContextEnrichingTestProvingInterpreter
@@ -42,8 +51,8 @@ class ErgoLikeInterpreterSpecification extends CompilerTestingCommons
.withErgoTreeVersion(ergoTreeVersionInTests)
val e = compile(Map(
- "h1" -> h1.treeWithSegregation(ergoTreeHeaderInTests).bytes,
- "h2" -> h2.treeWithSegregation(ergoTreeHeaderInTests).bytes),
+ "h1" -> ErgoTree.withSegregation(ergoTreeHeaderInTests, h1).bytes,
+ "h2" -> ErgoTree.withSegregation(ergoTreeHeaderInTests, h2).bytes),
"h1 == h1")
val exp = TrueLeaf
e shouldBe exp
@@ -52,8 +61,8 @@ class ErgoLikeInterpreterSpecification extends CompilerTestingCommons
res shouldBe TrivialProp.TrueProp
val ergoTree = mkTestErgoTree(
EQ(
- ByteArrayConstant(h1.treeWithSegregation(ergoTreeHeaderInTests).bytes),
- ByteArrayConstant(h2.treeWithSegregation(ergoTreeHeaderInTests).bytes)
+ ByteArrayConstant(ErgoTree.withSegregation(ergoTreeHeaderInTests, h1).bytes),
+ ByteArrayConstant(ErgoTree.withSegregation(ergoTreeHeaderInTests, h2).bytes)
).toSigmaProp
)
val res2 = verifier.fullReduction(ergoTree, ctx).value
@@ -247,7 +256,7 @@ class ErgoLikeInterpreterSpecification extends CompilerTestingCommons
SigmaPropConstant(pubkey),
BoolToSigmaProp(
GT(
- Fold.sum[SLong.type](MapCollection(Outputs,
+ sum[SLong.type](MapCollection(Outputs,
FuncValue(Vector((1, SBox)), ExtractAmount(ValUse(1, SBox)))), 1),
LongConstant(20))
)
@@ -411,7 +420,7 @@ class ErgoLikeInterpreterSpecification extends CompilerTestingCommons
val prover0 = new ContextEnrichingTestProvingInterpreter()
- val customScript = prover0.dlogSecrets.head.publicImage.toSigmaProp
+ val customScript = prover0.dlogSecrets.head.publicImage.toSigmaPropValue
val scriptBytes = ValueSerializer.serialize(customScript)
val scriptHash = Blake2b256(scriptBytes).take(bytesCount)
@@ -742,7 +751,7 @@ class ErgoLikeInterpreterSpecification extends CompilerTestingCommons
}
property("non-const ProveDHT") {
- import sigmastate.crypto.CryptoConstants.dlogGroup
+ import sigma.crypto.CryptoConstants.dlogGroup
compile(Map("gA" -> dlogGroup.generator.toGroupElement),
"proveDHTuple(gA, OUTPUTS(0).R4[GroupElement].get, gA, gA)"
).asInstanceOf[BlockValue].result shouldBe a [CreateProveDHTuple]
diff --git a/sc/shared/src/test/scala/sigmastate/utxo/SerializationRoundTripSpec.scala b/sc/shared/src/test/scala/sigmastate/utxo/SerializationRoundTripSpec.scala
index 8899b90584..0fdf6db97b 100644
--- a/sc/shared/src/test/scala/sigmastate/utxo/SerializationRoundTripSpec.scala
+++ b/sc/shared/src/test/scala/sigmastate/utxo/SerializationRoundTripSpec.scala
@@ -3,8 +3,8 @@ package sigmastate.utxo
import org.ergoplatform._
import sigma.util.BenchmarkUtil
import sigmastate.helpers.CompilerTestingCommons
-import sigmastate.interpreter.{ContextExtension, ProverResult}
-import sigmastate.serialization.generators.ObjectGenerators
+import sigma.interpreter.{ContextExtension, ProverResult}
+import sigma.serialization.generators.ObjectGenerators
import debox.{Buffer => DBuffer}
import org.scalatest.matchers.should.Matchers
import org.scalatest.propspec.AnyPropSpec
diff --git a/sc/shared/src/test/scala/sigmastate/utxo/SigmaCompilerSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/SigmaCompilerSpecification.scala
index ffbb02dd98..e84dc6211b 100644
--- a/sc/shared/src/test/scala/sigmastate/utxo/SigmaCompilerSpecification.scala
+++ b/sc/shared/src/test/scala/sigmastate/utxo/SigmaCompilerSpecification.scala
@@ -1,11 +1,12 @@
package sigmastate.utxo
-import sigmastate.Values._
-import sigmastate.eval.CAnyValue
+import sigma.ast.{GE, ModQ, SType}
+import sigma.data.CAnyValue
+import sigma.ast._
+import sigma.ast.syntax.{GetVarInt, OptionValueOps}
import sigmastate.helpers.CompilerTestingCommons
import sigmastate.interpreter.Interpreter.ScriptEnv
-import sigmastate.lang.Terms._
-import sigmastate.{GE, ModQ, SType}
+import sigma.ast.syntax._
/**
* Specification for compile function
diff --git a/sc/shared/src/test/scala/sigmastate/utxo/ThresholdSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/ThresholdSpecification.scala
index 31536a76fd..2328b51989 100644
--- a/sc/shared/src/test/scala/sigmastate/utxo/ThresholdSpecification.scala
+++ b/sc/shared/src/test/scala/sigmastate/utxo/ThresholdSpecification.scala
@@ -1,10 +1,13 @@
package sigmastate.utxo
-import sigmastate.crypto.DLogProtocol.{DLogProverInput, ProveDlog}
-import sigmastate.Values.{ConcreteCollection, FalseLeaf, IntConstant, SigmaPropConstant, SigmaPropValue, TrueLeaf}
+import sigma.ast._
+import sigma.ast.syntax._
+import sigma.data.{AvlTreeData, CAND, COR, ProveDlog, TrivialProp}
+import sigma.eval.Extensions.SigmaBooleanOps
+import sigma.exceptions.GraphBuildingException
import sigmastate._
-import sigmastate.helpers.{ContextEnrichingTestProvingInterpreter, ErgoLikeContextTesting, ErgoLikeTestInterpreter, ErgoLikeTransactionTesting, CompilerTestingCommons}
-import sigmastate.exceptions.GraphBuildingException
+import sigmastate.crypto.DLogProtocol.DLogProverInput
+import sigmastate.helpers._
class ThresholdSpecification extends CompilerTestingCommons
with CompilerCrossVersionProps {
@@ -88,7 +91,7 @@ class ThresholdSpecification extends CompilerTestingCommons
proverD.prove(compiledTree3, ctx, fakeMessage).isFailure shouldBe true
{
- val prop3Or = COR(Seq(pubkeyA, pubkeyB, pubkeyC)).toSigmaProp
+ val prop3Or = COR(Seq(pubkeyA, pubkeyB, pubkeyC)).toSigmaPropValue
val res1 = testReduce(proverA)(ctx, compiledProp3)
val res2 = testReduce(proverA)(ctx, prop3Or)
res1 shouldBe res2
@@ -113,7 +116,6 @@ class ThresholdSpecification extends CompilerTestingCommons
}
property("threshold reduce to crypto") {
- import TrivialProp._
val prover = new ContextEnrichingTestProvingInterpreter
val ctx = ErgoLikeContextTesting(
currentHeight = 1,
diff --git a/sc/shared/src/test/scala/sigmastate/utxo/UsingContextPropertiesSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/UsingContextPropertiesSpecification.scala
index e83d9a8569..e3d43ab868 100644
--- a/sc/shared/src/test/scala/sigmastate/utxo/UsingContextPropertiesSpecification.scala
+++ b/sc/shared/src/test/scala/sigmastate/utxo/UsingContextPropertiesSpecification.scala
@@ -1,13 +1,14 @@
package sigmastate.utxo
-import sigmastate.{TrivialProp, CompilerCrossVersionProps}
-import sigmastate.eval.{IRContext, CSigmaProp}
-import sigmastate.eval.Extensions._
+import sigmastate.CompilerCrossVersionProps
+import sigmastate.eval.IRContext
+import sigma.Extensions.ArrayOps
import sigma.Context
import sigmastate.helpers.CompilerTestingCommons
-import org.ergoplatform.dsl.{SigmaContractSyntax, ContractSpec, TestContractSpec}
+import org.ergoplatform.dsl.{ContractSpec, SigmaContractSyntax, TestContractSpec}
import org.ergoplatform.ErgoBox
import scorex.crypto.hash.Blake2b256
+import sigma.data.{CSigmaProp, TrivialProp}
class UsingContextPropertiesSpecification extends CompilerTestingCommons
with CompilerCrossVersionProps { suite =>
diff --git a/sc/shared/src/test/scala/sigmastate/utxo/blockchain/BlockchainSimulationSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/blockchain/BlockchainSimulationSpecification.scala
index 13ec9f2518..f063cf5aa0 100644
--- a/sc/shared/src/test/scala/sigmastate/utxo/blockchain/BlockchainSimulationSpecification.scala
+++ b/sc/shared/src/test/scala/sigmastate/utxo/blockchain/BlockchainSimulationSpecification.scala
@@ -1,15 +1,12 @@
package sigmastate.utxo.blockchain
-import java.io.{FileWriter, File}
-
+import sigma.ast.TrueLeaf
+import sigma.ast.syntax.{GetVarBoolean, OptionValueOps}
import sigmastate.CompilerCrossVersionProps
-import sigmastate.Values.{TrueLeaf, GetVarBoolean}
-import sigmastate.helpers.{ContextEnrichingTestProvingInterpreter, ErgoLikeTestProvingInterpreter}
-import sigmastate.interpreter.ContextExtension
+import sigmastate.helpers.ErgoLikeTestProvingInterpreter
+import sigma.interpreter.ContextExtension
import sigmastate.utxo.blockchain.BlockchainSimulationTestingCommons._
-import scala.collection.concurrent.TrieMap
-
class BlockchainSimulationSpecification extends BlockchainSimulationTestingCommons
with CompilerCrossVersionProps {
diff --git a/sc/shared/src/test/scala/sigmastate/utxo/blockchain/BlockchainSimulationTestingCommons.scala b/sc/shared/src/test/scala/sigmastate/utxo/blockchain/BlockchainSimulationTestingCommons.scala
index e9cf82616b..0dca8a4471 100644
--- a/sc/shared/src/test/scala/sigmastate/utxo/blockchain/BlockchainSimulationTestingCommons.scala
+++ b/sc/shared/src/test/scala/sigmastate/utxo/blockchain/BlockchainSimulationTestingCommons.scala
@@ -5,8 +5,7 @@ import org.ergoplatform._
import scorex.crypto.authds.{ADDigest, ADKey, ADValue}
import scorex.crypto.authds.avltree.batch.{BatchAVLProver, Insert, Remove}
import scorex.crypto.hash.{Blake2b256, Digest32}
-import sigmastate.{AvlTreeData, AvlTreeFlags, Values}
-import sigmastate.Values.{ErgoTree, LongConstant}
+import sigma.ast.{ErgoTree, LongConstant, TrueLeaf}
import sigmastate.eval._
import sigmastate.helpers.{BlockchainState, CompilerTestingCommons, ErgoLikeContextTesting, ErgoLikeTestProvingInterpreter, ErgoTransactionValidator}
import sigmastate.helpers.TestingHelpers._
@@ -16,7 +15,10 @@ import scala.collection.mutable
import scala.util.{Random, Try}
import scorex.util._
import sigma.Colls
-import sigmastate.interpreter.ContextExtension
+import sigma.data.{AvlTreeData, AvlTreeFlags}
+import ErgoTree.ZeroHeader
+import sigma.eval.Extensions.SigmaBooleanOps
+import sigma.interpreter.ContextExtension
import sigmastate.interpreter.Interpreter.{ScriptNameProp, emptyEnv}
import sigmastate.utxo.blockchain.BlockchainSimulationTestingCommons.{FullBlock, ValidationState}
@@ -45,7 +47,7 @@ trait BlockchainSimulationTestingCommons extends CompilerTestingCommons {
propOpt: Option[ErgoTree] = None,
extension: ContextExtension = ContextExtension.empty): FullBlock = {
val prop: ErgoTree = propOpt.getOrElse(
- mkTestErgoTree(prover.dlogSecrets.head.publicImage.toSigmaProp))
+ mkTestErgoTree(prover.dlogSecrets.head.publicImage.toSigmaPropValue))
val minerPubkey = prover.dlogSecrets.head.publicImage.pkBytes
val boxesToSpend = state.boxesReader.randomBoxes(30 + height)
@@ -155,8 +157,8 @@ object BlockchainSimulationTestingCommons extends CompilerTestingCommons {
val boxes = (1 to 50).map(_ =>
testBox(10,
ErgoTree.fromProposition(
- ErgoTree.headerWithVersion(scriptVersion),
- Values.TrueLeaf.toSigmaProp),
+ ErgoTree.headerWithVersion(ZeroHeader, scriptVersion),
+ TrueLeaf.toSigmaProp),
i, Seq(), Map(), txId))
createTransaction(boxes)
},
diff --git a/sc/shared/src/test/scala/sigmastate/utxo/examples/AssetsAtomicExchangeErgoTests.scala b/sc/shared/src/test/scala/sigmastate/utxo/examples/AssetsAtomicExchangeErgoTests.scala
index 5eb852265d..7d9258bc5c 100644
--- a/sc/shared/src/test/scala/sigmastate/utxo/examples/AssetsAtomicExchangeErgoTests.scala
+++ b/sc/shared/src/test/scala/sigmastate/utxo/examples/AssetsAtomicExchangeErgoTests.scala
@@ -5,7 +5,7 @@ import org.ergoplatform.dsl.ContractSyntax.Token
import org.ergoplatform.dsl.ErgoContractSpec
import sigma.Coll
import scorex.crypto.hash.Blake2b256
-import sigmastate.eval.Digest32Coll
+import sigma.data.Digest32Coll
class AssetsAtomicExchangeErgoTests extends CompilerTestingCommons { suite =>
lazy val spec = new ErgoContractSpec()(new TestingIRContext)
diff --git a/sc/shared/src/test/scala/sigmastate/utxo/examples/AssetsAtomicExchangeTests.scala b/sc/shared/src/test/scala/sigmastate/utxo/examples/AssetsAtomicExchangeTests.scala
index b8fe0a8410..1bda3992c7 100644
--- a/sc/shared/src/test/scala/sigmastate/utxo/examples/AssetsAtomicExchangeTests.scala
+++ b/sc/shared/src/test/scala/sigmastate/utxo/examples/AssetsAtomicExchangeTests.scala
@@ -1,18 +1,18 @@
package sigmastate.utxo.examples
-import org.ergoplatform.{Height, Outputs, ErgoBox, Self}
+import org.ergoplatform.ErgoBox
import org.ergoplatform.ErgoBox.R4
import sigmastate.helpers.CompilerTestingCommons
import org.ergoplatform.dsl.ContractSyntax.Token
import org.ergoplatform.dsl.TestContractSpec
import scorex.crypto.hash.Blake2b256
-import sigmastate.SCollection.SByteArray
-import sigmastate._
-import sigmastate.Values.{BlockValue, ByteArrayConstant, LongConstant, ValDef, ValUse, Value}
-import sigmastate.eval.{CSigmaProp, Digest32Coll}
+import sigma.ast.SCollection.SByteArray
+import sigma.ast._
+import sigma.ast.syntax._
+import sigma.data.{CSigmaProp, Digest32Coll, TrivialProp}
+import sigma.ast.{BlockValue, ByteArrayConstant, LongConstant, ValDef, ValUse, Value}
import sigmastate.eval.Extensions._
-import sigmastate.lang.Terms.ValueOps
-import sigmastate.utxo._
+import sigma.ast.syntax.ValueOps
/** An example of an atomic ergo <=> asset exchange.
* Let's assume that Alice is willing to buy 60 assets of type "token1" for 100 ergo coins, and Bob
@@ -140,7 +140,7 @@ class AssetsAtomicExchangeTests extends CompilerTestingCommons { suite =>
// ASSERT
val input0 = spendingTx.inputs(0)
- val buyerExt = Map(Byte.MaxValue -> toAnyValue(0.toShort))
+ val buyerExt = Map(Byte.MaxValue -> ShortConstant(0.toShort))
val res = input0.runDsl(buyerExt)
res shouldBe CSigmaProp(TrivialProp.TrueProp)
@@ -148,7 +148,7 @@ class AssetsAtomicExchangeTests extends CompilerTestingCommons { suite =>
contract.verifier.verify(input0, buyerProof) shouldBe true
val input1 = spendingTx.inputs(1)
- val sellerExt = Map(Byte.MaxValue -> toAnyValue(1.toShort))
+ val sellerExt = Map(Byte.MaxValue -> ShortConstant(1.toShort))
val res1 = input1.runDsl(sellerExt)
res1 shouldBe CSigmaProp(TrivialProp.TrueProp)
val sellerProof = contract.tokenSeller.prove(input1, sellerExt).get
diff --git a/sc/shared/src/test/scala/sigmastate/utxo/examples/AtomicSwapExampleSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/examples/AtomicSwapExampleSpecification.scala
index ef004f602a..131aba22d0 100644
--- a/sc/shared/src/test/scala/sigmastate/utxo/examples/AtomicSwapExampleSpecification.scala
+++ b/sc/shared/src/test/scala/sigmastate/utxo/examples/AtomicSwapExampleSpecification.scala
@@ -1,14 +1,14 @@
package sigmastate.utxo.examples
-import org.ergoplatform.Height
import scorex.crypto.hash.Blake2b256
import scorex.utils.Random
-import sigmastate.Values._
+import sigma.data.AvlTreeData
+import sigma.ast._
+import sigma.ast.syntax.{CollectionConstant, GetVarByteArray, OptionValueOps}
import sigmastate._
import sigmastate.interpreter.Interpreter._
import sigmastate.helpers._
-import sigmastate.lang.Terms._
-import sigmastate.utxo.SizeOf
+import sigma.ast.syntax._
class AtomicSwapExampleSpecification extends CompilerTestingCommons with CompilerCrossVersionProps {
private implicit lazy val IR: TestingIRContext = new TestingIRContext
diff --git a/sc/shared/src/test/scala/sigmastate/utxo/examples/CoinEmissionSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/examples/CoinEmissionSpecification.scala
index a6c612a037..12e6a236c8 100644
--- a/sc/shared/src/test/scala/sigmastate/utxo/examples/CoinEmissionSpecification.scala
+++ b/sc/shared/src/test/scala/sigmastate/utxo/examples/CoinEmissionSpecification.scala
@@ -3,15 +3,14 @@ package sigmastate.utxo.examples
import org.ergoplatform._
import org.ergoplatform.settings.ErgoAlgos
import sigma.Colls
-import sigmastate.Values.{BlockValue, ErgoTree, IntConstant, LongConstant, ValDef, ValUse}
+import sigma.ast.syntax.OptionValueOps
+import sigma.ast._
import sigmastate._
-import sigmastate.eval._
import sigmastate.helpers.TestingHelpers._
import sigmastate.helpers.{CompilerTestingCommons, ContextEnrichingTestProvingInterpreter, ErgoLikeContextTesting}
-import sigmastate.interpreter.ContextExtension
+import sigma.interpreter.ContextExtension
import sigmastate.interpreter.Interpreter.{ScriptNameProp, emptyEnv}
-import sigmastate.lang.Terms._
-import sigmastate.utxo._
+import sigma.ast.syntax._
import sigmastate.utxo.blockchain.BlockchainSimulationTestingCommons._
/**
@@ -167,7 +166,7 @@ block 1600 in 1622 ms, 30000000000 coins remain, defs: 61661
height: Int): ErgoLikeTransaction = {
assert(state.state.currentHeight == height - 1)
val ut = if (emissionBox.value > s.oneEpochReduction) {
- val minerBox = new ErgoBoxCandidate(emissionAtHeight(height), minerProp, height, Colls.emptyColl, Map())
+ val minerBox = new ErgoBoxCandidate(emissionAtHeight(height), ErgoTree.fromSigmaBoolean(minerProp), height, Colls.emptyColl, Map())
val newEmissionBox: ErgoBoxCandidate =
new ErgoBoxCandidate(emissionBox.value - minerBox.value, tree, height, Colls.emptyColl, Map(register -> IntConstant(height)))
@@ -176,8 +175,8 @@ block 1600 in 1622 ms, 30000000000 coins remain, defs: 61661
IndexedSeq(newEmissionBox, minerBox)
)
} else {
- val minerBox1 = new ErgoBoxCandidate(emissionBox.value - 1, minerProp, height, Colls.emptyColl, Map(register -> IntConstant(height)))
- val minerBox2 = new ErgoBoxCandidate(1, minerProp, height, Colls.emptyColl, Map(register -> IntConstant(height)))
+ val minerBox1 = new ErgoBoxCandidate(emissionBox.value - 1, ErgoTree.fromSigmaBoolean(minerProp), height, Colls.emptyColl, Map(register -> IntConstant(height)))
+ val minerBox2 = new ErgoBoxCandidate(1, ErgoTree.fromSigmaBoolean(minerProp), height, Colls.emptyColl, Map(register -> IntConstant(height)))
UnsignedErgoLikeTransaction(
IndexedSeq(new UnsignedInput(emissionBox.id)),
IndexedSeq(minerBox1, minerBox2)
diff --git a/sc/shared/src/test/scala/sigmastate/utxo/examples/ColdWalletAdvContractExampleSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/examples/ColdWalletAdvContractExampleSpecification.scala
index 1230177437..9bcfd81ecf 100644
--- a/sc/shared/src/test/scala/sigmastate/utxo/examples/ColdWalletAdvContractExampleSpecification.scala
+++ b/sc/shared/src/test/scala/sigmastate/utxo/examples/ColdWalletAdvContractExampleSpecification.scala
@@ -1,13 +1,14 @@
package sigmastate.utxo.examples
-import org.ergoplatform.ErgoBox.{R6, R4, R5}
+import org.ergoplatform.ErgoBox.{R4, R5, R6}
import org.ergoplatform._
-import sigmastate.{AvlTreeData, CompilerCrossVersionProps}
-import sigmastate.Values.{LongConstant, IntConstant}
-import sigmastate.helpers.{ErgoLikeContextTesting, ErgoLikeTestInterpreter, ErgoLikeTestProvingInterpreter, CompilerTestingCommons, ContextEnrichingTestProvingInterpreter}
+import sigma.data.AvlTreeData
+import sigmastate.CompilerCrossVersionProps
+import sigma.ast.{ErgoTree, IntConstant, LongConstant}
+import sigmastate.helpers.{CompilerTestingCommons, ContextEnrichingTestProvingInterpreter, ErgoLikeContextTesting, ErgoLikeTestInterpreter, ErgoLikeTestProvingInterpreter}
import sigmastate.helpers.TestingHelpers._
import sigmastate.interpreter.Interpreter.ScriptNameProp
-import sigmastate.lang.Terms._
+import sigma.ast.syntax._
class ColdWalletAdvContractExampleSpecification extends CompilerTestingCommons
@@ -126,7 +127,7 @@ class ColdWalletAdvContractExampleSpecification extends CompilerTestingCommons
R6 -> LongConstant(avbl2Key) // new avbl2Key (= old avbl2Key)
)
)
- val firstWithdrawOutput1Key = testBox(firstWithdrawAmount1Key, carolPubKey, firstWithdrawHeight)
+ val firstWithdrawOutput1Key = testBox(firstWithdrawAmount1Key, ErgoTree.fromSigmaBoolean(carolPubKey), firstWithdrawHeight)
//normally this transaction would be invalid, but we're not checking it in this test
val firstWithdrawTx1Key = ErgoLikeTransaction(IndexedSeq(), IndexedSeq(firstChangeOutput1Key, firstWithdrawOutput1Key))
@@ -163,7 +164,7 @@ class ColdWalletAdvContractExampleSpecification extends CompilerTestingCommons
R6 -> LongConstant(avbl2Key - firstWithdrawAmount2Key) // new avbl2Key (= old avbl2Key)
)
)
- val firstWithdrawOutput2Key = testBox(firstWithdrawAmount2Key, carolPubKey, firstWithdrawHeight)
+ val firstWithdrawOutput2Key = testBox(firstWithdrawAmount2Key, ErgoTree.fromSigmaBoolean(carolPubKey), firstWithdrawHeight)
//normally this transaction would be invalid, but we're not checking it in this test
val firstWithdrawTx2Key = ErgoLikeTransaction(IndexedSeq(), IndexedSeq(firstChangeOutput2Key, firstWithdrawOutput2Key))
diff --git a/sc/shared/src/test/scala/sigmastate/utxo/examples/ColdWalletContractExampleSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/examples/ColdWalletContractExampleSpecification.scala
index ffd4b17018..1948bc16d9 100644
--- a/sc/shared/src/test/scala/sigmastate/utxo/examples/ColdWalletContractExampleSpecification.scala
+++ b/sc/shared/src/test/scala/sigmastate/utxo/examples/ColdWalletContractExampleSpecification.scala
@@ -2,12 +2,13 @@ package sigmastate.utxo.examples
import org.ergoplatform.ErgoBox.{R4, R5}
import org.ergoplatform._
-import sigmastate.helpers.{ContextEnrichingTestProvingInterpreter, ErgoLikeContextTesting, CompilerTestingCommons, ErgoLikeTestInterpreter}
+import sigma.data.AvlTreeData
+import sigmastate.helpers.{CompilerTestingCommons, ContextEnrichingTestProvingInterpreter, ErgoLikeContextTesting, ErgoLikeTestInterpreter}
import sigmastate.helpers.TestingHelpers._
-import sigmastate.{AvlTreeData, CompilerCrossVersionProps}
-import sigmastate.Values.{LongConstant, IntConstant}
+import sigmastate.CompilerCrossVersionProps
+import sigma.ast.{ErgoTree, IntConstant, LongConstant}
import sigmastate.interpreter.Interpreter.ScriptNameProp
-import sigmastate.lang.Terms._
+import sigma.ast.syntax._
class ColdWalletContractExampleSpecification extends CompilerTestingCommons
@@ -92,7 +93,7 @@ class ColdWalletContractExampleSpecification extends CompilerTestingCommons
// Both Alice ane Bob withdraw
val withdrawAmountFull = depositAmount // full amount is withdrawn
- val withdrawOutputAliceAndBob = testBox(withdrawAmountFull, carolPubKey, firstWithdrawHeight)
+ val withdrawOutputAliceAndBob = testBox(withdrawAmountFull, ErgoTree.fromSigmaBoolean(carolPubKey), firstWithdrawHeight)
val withdrawTxAliceAndBob = ErgoLikeTransaction(IndexedSeq(), IndexedSeq(withdrawOutputAliceAndBob))
@@ -122,7 +123,7 @@ class ColdWalletContractExampleSpecification extends CompilerTestingCommons
R5 -> LongConstant(min) // newMin (= old min) = 99000
)
)
- val firstWithdrawOutput = testBox(firstWithdrawAmount, carolPubKey, firstWithdrawHeight)
+ val firstWithdrawOutput = testBox(firstWithdrawAmount, ErgoTree.fromSigmaBoolean(carolPubKey), firstWithdrawHeight)
//normally this transaction would be invalid, but we're not checking it in this test
val firstWithdrawTx = ErgoLikeTransaction(IndexedSeq(), IndexedSeq(firstChangeOutput, firstWithdrawOutput))
@@ -152,7 +153,7 @@ class ColdWalletContractExampleSpecification extends CompilerTestingCommons
R5 -> LongConstant(min) // newMin (= old min)
)
)
- val withdrawOutputInvalid = testBox(withdrawAmountInvalid, carolPubKey, firstWithdrawHeight)
+ val withdrawOutputInvalid = testBox(withdrawAmountInvalid, ErgoTree.fromSigmaBoolean(carolPubKey), firstWithdrawHeight)
// normally this transaction would be invalid, but we're not checking it in this test
val withdrawTxInvalid = ErgoLikeTransaction(IndexedSeq(), IndexedSeq(changeOutputInvalid, withdrawOutputInvalid))
@@ -187,7 +188,7 @@ class ColdWalletContractExampleSpecification extends CompilerTestingCommons
R5 -> LongConstant(secondMin) // newMin
)
)
- val secondWithdrawOutput = testBox(secondWithdrawAmount, carolPubKey, secondWithdrawHeight)
+ val secondWithdrawOutput = testBox(secondWithdrawAmount, ErgoTree.fromSigmaBoolean(carolPubKey), secondWithdrawHeight)
//normally this transaction would be invalid, but we're not checking it in this test
val secondWithdrawTx = ErgoLikeTransaction(IndexedSeq(), IndexedSeq(secondChangeOutput, secondWithdrawOutput))
diff --git a/sc/shared/src/test/scala/sigmastate/utxo/examples/CoopExampleSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/examples/CoopExampleSpecification.scala
index 44b69db572..d197845e80 100644
--- a/sc/shared/src/test/scala/sigmastate/utxo/examples/CoopExampleSpecification.scala
+++ b/sc/shared/src/test/scala/sigmastate/utxo/examples/CoopExampleSpecification.scala
@@ -1,15 +1,17 @@
package sigmastate.utxo.examples
-import org.ergoplatform.{ErgoLikeContext, ErgoLikeTransaction, ErgoBox}
+import org.ergoplatform.{ErgoBox, ErgoLikeContext, ErgoLikeTransaction}
import org.scalatest.Assertion
import org.scalatest.TryValues._
-import sigmastate.crypto.DLogProtocol.{ProveDlog, DLogProverInput}
import scorex.crypto.hash.Blake2b256
-import sigmastate.Values.{ByteArrayConstant, ErgoTree, BooleanConstant}
-import sigmastate.helpers.{ContextEnrichingTestProvingInterpreter, ErgoLikeContextTesting, CompilerTestingCommons, ErgoLikeTestInterpreter}
+import sigma.data.{AvlTreeData, ProveDlog}
+import sigma.ast.ErgoTree.ZeroHeader
+import sigma.ast.{BooleanConstant, ByteArrayConstant, ErgoTree}
+import sigmastate.crypto.DLogProtocol.DLogProverInput
import sigmastate.helpers.TestingHelpers._
-import sigmastate.lang.Terms._
-import sigmastate.{AvlTreeData, CompilerCrossVersionProps}
+import sigmastate.helpers.{CompilerTestingCommons, ContextEnrichingTestProvingInterpreter, ErgoLikeContextTesting, ErgoLikeTestInterpreter}
+import sigma.ast.syntax._
+import sigmastate.CompilerCrossVersionProps
class CoopExampleSpecification extends CompilerTestingCommons
with CompilerCrossVersionProps {
@@ -65,7 +67,7 @@ class CoopExampleSpecification extends CompilerTestingCommons
def pkWithTree(in: DLogProverInput): (ProveDlog, ErgoTree) = {
val pk = in.publicImage
- val tree = ErgoTree.fromSigmaBoolean(ErgoTree.headerWithVersion(0), pk)
+ val tree = ErgoTree.fromSigmaBoolean(ErgoTree.headerWithVersion(ZeroHeader, 0), pk)
(pk, tree)
}
diff --git a/sc/shared/src/test/scala/sigmastate/utxo/examples/DHTupleExampleSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/examples/DHTupleExampleSpecification.scala
index 92f6e6c4cb..9246cc1c8e 100644
--- a/sc/shared/src/test/scala/sigmastate/utxo/examples/DHTupleExampleSpecification.scala
+++ b/sc/shared/src/test/scala/sigmastate/utxo/examples/DHTupleExampleSpecification.scala
@@ -2,17 +2,17 @@
package sigmastate.utxo.examples
import java.math.BigInteger
-
import org.ergoplatform.ErgoBox.{R4, R5}
-import sigmastate.{AvlTreeData, CompilerCrossVersionProps}
-import sigmastate.Values.GroupElementConstant
-import sigmastate.crypto.DLogProtocol.ProveDlog
-import sigmastate.crypto.{DiffieHellmanTupleProverInput, ProveDHTuple, CryptoConstants}
-import sigmastate.helpers.{ContextEnrichingTestProvingInterpreter, ErgoLikeContextTesting, CompilerTestingCommons, ErgoLikeTestInterpreter}
+import sigma.data.{AvlTreeData, ProveDHTuple, ProveDlog}
+import sigma.util.Extensions.EcpOps
+import sigmastate.CompilerCrossVersionProps
+import sigma.ast.GroupElementConstant
+import sigma.crypto.CryptoConstants
+import sigmastate.crypto.DiffieHellmanTupleProverInput
+import sigmastate.helpers.{CompilerTestingCommons, ContextEnrichingTestProvingInterpreter, ErgoLikeContextTesting, ErgoLikeTestInterpreter}
import sigmastate.helpers.TestingHelpers._
import sigmastate.interpreter.Interpreter._
-import sigmastate.lang.Terms._
-import sigmastate.eval.Extensions._
+import sigma.ast.syntax._
class DHTupleExampleSpecification extends CompilerTestingCommons
with CompilerCrossVersionProps {
@@ -31,7 +31,7 @@ class DHTupleExampleSpecification extends CompilerTestingCommons
val g = dlogGroup.generator
val alice = new ContextEnrichingTestProvingInterpreter
- val alicePubKey:ProveDlog = alice.dlogSecrets.head.publicImage
+ val alicePubKey: ProveDlog = alice.dlogSecrets.head.publicImage
val x:BigInteger = alice.dlogSecrets.head.w // x is Alice's private key
diff --git a/sc/shared/src/test/scala/sigmastate/utxo/examples/DemurrageExampleSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/examples/DemurrageExampleSpecification.scala
index 8eb5b3b04c..4ec6922c38 100644
--- a/sc/shared/src/test/scala/sigmastate/utxo/examples/DemurrageExampleSpecification.scala
+++ b/sc/shared/src/test/scala/sigmastate/utxo/examples/DemurrageExampleSpecification.scala
@@ -2,12 +2,13 @@ package sigmastate.utxo.examples
import sigmastate.interpreter.Interpreter._
import org.ergoplatform._
-import sigmastate.Values.ShortConstant
+import sigma.data.AvlTreeData
+import sigma.ast.ShortConstant
import sigmastate._
-import sigmastate.helpers.{ContextEnrichingTestProvingInterpreter, ErgoLikeContextTesting, ErgoLikeTestInterpreter, CompilerTestingCommons}
+import sigmastate.helpers.{CompilerTestingCommons, ContextEnrichingTestProvingInterpreter, ErgoLikeContextTesting, ErgoLikeTestInterpreter}
import sigmastate.helpers.TestingHelpers._
-import sigmastate.interpreter.ContextExtension
-import sigmastate.lang.Terms._
+import sigma.interpreter.ContextExtension
+import sigma.ast.syntax._
class DemurrageExampleSpecification extends CompilerTestingCommons
with CompilerCrossVersionProps {
diff --git a/sc/shared/src/test/scala/sigmastate/utxo/examples/DummyExamplesSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/examples/DummyExamplesSpecification.scala
index 754e3baa73..f10a54463a 100644
--- a/sc/shared/src/test/scala/sigmastate/utxo/examples/DummyExamplesSpecification.scala
+++ b/sc/shared/src/test/scala/sigmastate/utxo/examples/DummyExamplesSpecification.scala
@@ -3,9 +3,9 @@ package sigmastate.utxo.examples
import org.ergoplatform.ErgoBox
import org.ergoplatform.dsl.{ContractSpec, SigmaContractSyntax, StdContracts, TestContractSpec}
import scorex.crypto.hash
+import sigma.ast.{ByteArrayConstant, CollectionConstant, SByte, SCollection}
import sigmastate.helpers.CompilerTestingCommons
-import sigma.{Box, Context, Coll}
-import sigmastate.eval.Extensions
+import sigma.{Box, Coll, Context}
class DummyExamplesSpecification extends CompilerTestingCommons { suite =>
implicit lazy val IR = new TestingIRContext
@@ -92,9 +92,9 @@ class DummyExamplesSpecification extends CompilerTestingCommons { suite =>
val res = in.runDsl(
Map(
- 0.toByte -> Extensions.toAnyValue(dummyPath),
- 1.toByte -> Extensions.toAnyValue(dummyBytes),
- 2.toByte -> Extensions.toAnyValue(dummyBytes)
+ 0.toByte -> CollectionConstant[SCollection[SByte.type]](dummyPath, SCollection(SByte)),
+ 1.toByte -> ByteArrayConstant(dummyBytes),
+ 2.toByte -> ByteArrayConstant(dummyBytes)
)
)
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 5ea4ef7a05..b75b404aed 100644
--- a/sc/shared/src/test/scala/sigmastate/utxo/examples/ExecuteFromExamplesSpecification.scala
+++ b/sc/shared/src/test/scala/sigmastate/utxo/examples/ExecuteFromExamplesSpecification.scala
@@ -4,7 +4,7 @@ import org.ergoplatform._
import org.ergoplatform.dsl.{ContractSpec, SigmaContractSyntax, StdContracts, TestContractSpec}
import sigmastate.helpers.CompilerTestingCommons
import sigma.Context
-import sigmastate.eval.Extensions._
+import sigma.ast.ByteArrayConstant
class ExecuteFromExamplesSpecification extends CompilerTestingCommons { suite =>
implicit lazy val IR = new TestingIRContext
@@ -55,7 +55,7 @@ class ExecuteFromExamplesSpecification extends CompilerTestingCommons { suite =>
tx.outBox(20, contract.aliceSignature)
val in = tx.inputs(0)
- val vars = Map(1.toByte -> toAnyValue(alice.pubKey.propBytes))
+ val vars = Map(1.toByte -> ByteArrayConstant(alice.pubKey.propBytes))
val res = in.runDsl(vars)
res shouldBe alice.pubKey
diff --git a/sc/shared/src/test/scala/sigmastate/utxo/examples/FsmExampleSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/examples/FsmExampleSpecification.scala
index 77918e453a..8f4f3414a3 100644
--- a/sc/shared/src/test/scala/sigmastate/utxo/examples/FsmExampleSpecification.scala
+++ b/sc/shared/src/test/scala/sigmastate/utxo/examples/FsmExampleSpecification.scala
@@ -6,16 +6,17 @@ import scorex.crypto.authds.{ADKey, ADValue}
import scorex.crypto.hash
import scorex.crypto.hash.{Blake2b256, Digest32}
import sigma.Colls
-import sigmastate.SCollection.SByteArray
-import sigmastate.Values._
+import sigma.ast.SCollection.SByteArray
+import sigma.ast._
import sigmastate._
-import sigmastate.eval._
-import sigmastate.lang.Terms._
+import sigma.ast.syntax._
+import sigma.data.{AvlTreeData, AvlTreeFlags}
+import sigma.eval.Extensions.SigmaBooleanOps
+import sigma.eval.SigmaDsl
import sigmastate.helpers.{CompilerTestingCommons, ContextEnrichingTestProvingInterpreter, ErgoLikeContextTesting, ErgoLikeTestInterpreter}
import sigmastate.helpers.TestingHelpers._
import sigmastate.interpreter.Interpreter.{ScriptNameProp, emptyEnv}
-import sigmastate.serialization.ValueSerializer
-import sigmastate.utxo._
+import sigma.serialization.ValueSerializer
class FsmExampleSpecification extends CompilerTestingCommons
@@ -48,10 +49,10 @@ class FsmExampleSpecification extends CompilerTestingCommons
val prover = new ContextEnrichingTestProvingInterpreter
- val script1 = prover.dlogSecrets.head.publicImage.toSigmaProp
- val script2 = prover.dhSecrets.head.publicImage.toSigmaProp
+ val script1 = prover.dlogSecrets.head.publicImage.toSigmaPropValue
+ val script2 = prover.dhSecrets.head.publicImage.toSigmaPropValue
val script3 = SigmaAnd(script1, script2)
- val script4 = prover.dlogSecrets.tail.head.publicImage.toSigmaProp //a script to leave FSM
+ val script4 = prover.dlogSecrets.tail.head.publicImage.toSigmaPropValue //a script to leave FSM
val script1Hash = hash.Blake2b256(ValueSerializer.serialize(script1))
val script2Hash = hash.Blake2b256(ValueSerializer.serialize(script2))
@@ -89,7 +90,7 @@ class FsmExampleSpecification extends CompilerTestingCommons
val isMember = OptionIsDefined(
IR.builder.mkMethodCall(
OptionGet(ExtractRegisterAs[SAvlTree.type](Self, fsmDescRegister)),
- SAvlTree.getMethod,
+ SAvlTreeMethods.getMethod,
IndexedSeq(Append(
ConcreteCollection.fromItems[SByte.type](
OptionGet(ExtractRegisterAs[SByte.type](Self, currentStateRegister)),
diff --git a/sc/shared/src/test/scala/sigmastate/utxo/examples/IcoExample.scala b/sc/shared/src/test/scala/sigmastate/utxo/examples/IcoExample.scala
index 95899f0aa9..c930135bc2 100644
--- a/sc/shared/src/test/scala/sigmastate/utxo/examples/IcoExample.scala
+++ b/sc/shared/src/test/scala/sigmastate/utxo/examples/IcoExample.scala
@@ -9,19 +9,22 @@ import scorex.crypto.authds.avltree.batch._
import scorex.crypto.authds.{ADKey, ADValue}
import scorex.crypto.hash.{Blake2b256, Digest32}
import sigma.Colls
-import sigmastate.Values._
+import sigma.ast.SByte
+import sigma.data.{AvlTreeData, AvlTreeFlags, Digest32Coll}
+import sigma.ast._
import sigmastate._
-import sigmastate.crypto.CryptoConstants
-import sigmastate.eval.Extensions.ArrayOps
+import sigma.Extensions.ArrayOps
+import sigma.ast.syntax.{CollectionConstant, SigmaPropValue}
+import sigma.crypto.CryptoConstants
import sigmastate.eval._
import sigmastate.helpers.TestingHelpers._
import sigmastate.helpers.{CompilerTestingCommons, ContextEnrichingTestProvingInterpreter, ErgoLikeContextTesting, ErgoLikeTestProvingInterpreter}
import sigmastate.interpreter.Interpreter.ScriptNameProp
import sigmastate.interpreter.Interpreter
-import sigmastate.lang.Terms._
-import sigmastate.serialization.ErgoTreeSerializer
-import sigmastate.serialization.ErgoTreeSerializer.DefaultSerializer
-import sigmastate.utxo.ComplexityTableStat
+import sigma.ast.syntax._
+import sigma.eval.SigmaDsl
+import sigma.serialization.ErgoTreeSerializer
+import sigma.serialization.ErgoTreeSerializer.DefaultSerializer
import scala.util.Random
@@ -550,10 +553,6 @@ class IcoExample extends CompilerTestingCommons
printDebug("lookup proof size: " + lookupProof.length)
}
- property("ComplexityTableStat") {
- printDebug(ComplexityTableStat.complexityTableString)
- }
-
/** This is the last executed test suite, so this method is executed after all tests.
* We output statistics of how PrecompiledScriptProcessor cache was used. */
override protected def afterAll(): Unit = {
diff --git a/sc/shared/src/test/scala/sigmastate/utxo/examples/LetsSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/examples/LetsSpecification.scala
index 22f7f1c7c9..ce4ed2114e 100644
--- a/sc/shared/src/test/scala/sigmastate/utxo/examples/LetsSpecification.scala
+++ b/sc/shared/src/test/scala/sigmastate/utxo/examples/LetsSpecification.scala
@@ -6,15 +6,17 @@ import scorex.crypto.authds.{ADKey, ADValue}
import scorex.crypto.authds.avltree.batch.{BatchAVLProver, Insert, Lookup}
import scorex.crypto.hash.{Blake2b256, Digest32}
import sigma.Colls
-import sigmastate.{AvlTreeData, AvlTreeFlags, CompilerCrossVersionProps, TrivialProp}
-import sigmastate.Values.{AvlTreeConstant, ByteArrayConstant, LongConstant, SigmaPropConstant}
-import sigmastate.eval.Extensions.ArrayOps
-import sigmastate.eval.{Digest32Coll, IRContext, SigmaDsl}
+import sigma.data.{AvlTreeData, AvlTreeFlags, Digest32Coll, TrivialProp}
+import sigmastate.CompilerCrossVersionProps
+import sigma.ast.{AvlTreeConstant, ByteArrayConstant, LongConstant, SigmaPropConstant}
+import sigma.Extensions.ArrayOps
+import sigmastate.eval.IRContext
import sigmastate.helpers.{CompilerTestingCommons, ContextEnrichingTestProvingInterpreter, ErgoLikeContextTesting, ErgoLikeTestProvingInterpreter}
import sigmastate.helpers.TestingHelpers._
import sigmastate.interpreter.Interpreter.ScriptNameProp
-import sigmastate.serialization.ErgoTreeSerializer
-import sigmastate.lang.Terms._
+import sigma.serialization.ErgoTreeSerializer
+import sigma.ast.syntax._
+import sigma.eval.SigmaDsl
import scala.util.Random
diff --git a/sc/shared/src/test/scala/sigmastate/utxo/examples/MASTExampleSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/examples/MASTExampleSpecification.scala
index 54d2ec0241..368fe3d8ea 100644
--- a/sc/shared/src/test/scala/sigmastate/utxo/examples/MASTExampleSpecification.scala
+++ b/sc/shared/src/test/scala/sigmastate/utxo/examples/MASTExampleSpecification.scala
@@ -4,17 +4,19 @@ import org.ergoplatform._
import scorex.crypto.authds.avltree.batch.{BatchAVLProver, Insert, Lookup}
import scorex.crypto.authds.{ADKey, ADValue}
import scorex.crypto.hash.{Blake2b256, Digest32}
-import sigmastate.SCollection.SByteArray
-import sigmastate.Values._
+import sigma.ast.{SAvlTree, SBoolean, SLong}
+import sigma.ast.SCollection.SByteArray
+import sigma.data.{AvlTreeData, AvlTreeFlags}
+import sigma.ast._
import sigmastate._
-import sigmastate.eval.Extensions.ArrayOps
+import sigma.Extensions.ArrayOps
+import sigma.ast.syntax.{GetVarByteArray, OptionValueOps}
import sigmastate.helpers.{CompilerTestingCommons, ContextEnrichingTestProvingInterpreter, ErgoLikeContextTesting, ErgoLikeTestInterpreter}
import sigmastate.helpers.TestingHelpers._
-import sigmastate.lang.Terms._
+import sigma.ast.syntax._
+import sigma.eval.SigmaDsl
import sigmastate.interpreter.Interpreter._
-import sigmastate.serialization.ValueSerializer
-import sigmastate.utxo._
-import sigmastate.eval._
+import sigma.serialization.ValueSerializer
import scala.util.Random
@@ -96,7 +98,7 @@ class MASTExampleSpecification extends CompilerTestingCommons
val merklePathToScript = OptionIsDefined(
IR.builder.mkMethodCall(
ExtractRegisterAs[SAvlTree.type](Self, reg1).get,
- SAvlTree.getMethod,
+ SAvlTreeMethods.getMethod,
IndexedSeq(
CalcBlake2b256(GetVarByteArray(scriptId).get),
GetVarByteArray(proofId).get)).asOption[SByteArray]
@@ -113,7 +115,7 @@ class MASTExampleSpecification extends CompilerTestingCommons
lastBlockUtxoRoot = AvlTreeData.dummy,
minerPubkey = ErgoLikeContextTesting.dummyPubkey,
boxesToSpend = IndexedSeq(selfBox),
- createTransaction(testBox(1, recipientProposition, 0)),
+ createTransaction(testBox(1, ErgoTree.fromSigmaBoolean(recipientProposition), 0)),
self = selfBox, activatedVersionInTests)
avlProver.performOneOperation(Lookup(knownSecretTreeKey))
diff --git a/sc/shared/src/test/scala/sigmastate/utxo/examples/MixExampleSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/examples/MixExampleSpecification.scala
index 6bbf410dc1..fc19a485ee 100644
--- a/sc/shared/src/test/scala/sigmastate/utxo/examples/MixExampleSpecification.scala
+++ b/sc/shared/src/test/scala/sigmastate/utxo/examples/MixExampleSpecification.scala
@@ -1,19 +1,20 @@
package sigmastate.utxo.examples
import java.math.BigInteger
-
import org.ergoplatform.ErgoBox.{R4, R5}
import scorex.crypto.hash.Blake2b256
-import sigmastate.{AvlTreeData, CompilerCrossVersionProps}
-import sigmastate.Values.GroupElementConstant
-import sigmastate.crypto.DLogProtocol.ProveDlog
-import sigmastate.crypto.{DiffieHellmanTupleProverInput, ProveDHTuple, CryptoConstants}
-import sigmastate.helpers.{ContextEnrichingTestProvingInterpreter, ErgoLikeContextTesting, CompilerTestingCommons, ErgoLikeTestInterpreter}
+import sigma.data.{AvlTreeData, ProveDHTuple, ProveDlog}
+import sigma.util.Extensions.EcpOps
+import sigmastate.CompilerCrossVersionProps
+import sigma.ast.{ErgoTree, GroupElementConstant}
+import sigma.ast.syntax.GroupElementConstant
+import sigma.crypto.CryptoConstants
+import sigmastate.crypto.DiffieHellmanTupleProverInput
+import sigmastate.helpers.{CompilerTestingCommons, ContextEnrichingTestProvingInterpreter, ErgoLikeContextTesting, ErgoLikeTestInterpreter}
import sigmastate.helpers.TestingHelpers._
import sigmastate.interpreter.Interpreter._
-import sigmastate.lang.Terms._
-import sigmastate.eval._
-import sigmastate.eval.Extensions._
+import sigma.ast.syntax._
+import sigma.eval.SigmaDsl
class MixExampleSpecification extends CompilerTestingCommons
with CompilerCrossVersionProps {
@@ -185,7 +186,7 @@ class MixExampleSpecification extends CompilerTestingCommons
val carolPubKey: ProveDlog = carol.dlogSecrets.head.publicImage
val spendHeight = 90
- val carolOutput = testBox(mixAmount, carolPubKey, spendHeight)
+ val carolOutput = testBox(mixAmount, ErgoTree.fromSigmaBoolean(carolPubKey), spendHeight)
// normally this transaction would be invalid, but we're not checking it in this test
val spendingTx = createTransaction(carolOutput)
diff --git a/sc/shared/src/test/scala/sigmastate/utxo/examples/OracleDataInputsExamplesSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/examples/OracleDataInputsExamplesSpecification.scala
index 564385fd96..3207245fbb 100644
--- a/sc/shared/src/test/scala/sigmastate/utxo/examples/OracleDataInputsExamplesSpecification.scala
+++ b/sc/shared/src/test/scala/sigmastate/utxo/examples/OracleDataInputsExamplesSpecification.scala
@@ -4,7 +4,7 @@ import org.ergoplatform._
import org.ergoplatform.dsl.ContractSyntax.Token
import org.ergoplatform.dsl.{ContractSpec, SigmaContractSyntax, StdContracts, TestContractSpec}
import scorex.crypto.hash.Blake2b256
-import sigmastate.eval.Digest32Coll
+import sigma.data.Digest32Coll
import sigmastate.helpers.CompilerTestingCommons
import sigma.Coll
import sigma.Context
diff --git a/sc/shared/src/test/scala/sigmastate/utxo/examples/OracleExamplesSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/examples/OracleExamplesSpecification.scala
index 8566ce437e..9d0ffc880b 100644
--- a/sc/shared/src/test/scala/sigmastate/utxo/examples/OracleExamplesSpecification.scala
+++ b/sc/shared/src/test/scala/sigmastate/utxo/examples/OracleExamplesSpecification.scala
@@ -5,21 +5,21 @@ import org.ergoplatform.ErgoBox.RegisterId
import scorex.crypto.authds.avltree.batch.{BatchAVLProver, Insert, Lookup}
import scorex.crypto.authds.{ADKey, ADValue}
import scorex.crypto.hash.{Blake2b256, Digest32}
-import sigmastate.SCollection.SByteArray
-import sigmastate.Values._
+import sigma.ast.SCollection.SByteArray
+import sigma.ast._
import sigmastate._
import sigmastate.eval._
-import sigmastate.lang.Terms._
+import sigma.ast.syntax._
import sigmastate.helpers.{CompilerTestingCommons, ContextEnrichingTestProvingInterpreter, ErgoLikeContextTesting, ErgoLikeTestInterpreter}
import sigmastate.helpers.TestingHelpers._
import org.ergoplatform._
import org.ergoplatform.dsl.{ContractSpec, SigmaContractSyntax, StdContracts, TestContractSpec}
-import sigmastate.crypto.CryptoConstants
-import sigmastate.crypto.{BigIntegers, CryptoFacade}
-import sigmastate.eval.Extensions.ArrayOps
+import sigma.Extensions.ArrayOps
import sigmastate.interpreter.Interpreter.{ScriptNameProp, emptyEnv}
-import sigmastate.utxo._
import sigma.Context
+import sigma.ast.syntax._
+import sigma.crypto.{BigIntegers, CryptoConstants, CryptoFacade}
+import sigma.data.{AvlTreeData, AvlTreeFlags}
import sigmastate.utils.Helpers._
class OracleExamplesSpecification extends CompilerTestingCommons
@@ -103,7 +103,7 @@ class OracleExamplesSpecification extends CompilerTestingCommons
val oracleBox = testBox(
value = 1L,
- ergoTree = oraclePubKey,
+ ergoTree = ErgoTree.fromSigmaBoolean(oraclePubKey),
creationHeight = 0,
additionalRegisters = Map(
reg1 -> LongConstant(temperature),
@@ -135,7 +135,7 @@ class OracleExamplesSpecification extends CompilerTestingCommons
val oracleProp = SigmaAnd(
OptionIsDefined(IR.builder.mkMethodCall(
- LastBlockUtxoRootHash, SAvlTree.getMethod,
+ LastBlockUtxoRootHash, SAvlTreeMethods.getMethod,
IndexedSeq(ExtractId(GetVarBox(22: Byte).get), GetVarByteArray(23: Byte).get)).asOption[SByteArray]),
EQ(extract[SByteArray](ErgoBox.ScriptRegId), ByteArrayConstant(ErgoTree.fromSigmaBoolean(oraclePubKey).bytes)),
EQ(Exponentiate(GroupGenerator, extract[SBigInt.type](reg3)),
@@ -156,7 +156,7 @@ class OracleExamplesSpecification extends CompilerTestingCommons
avlProver.performOneOperation(Lookup(ADKey @@@ oracleBox.id))
val proof = avlProver.generateProof()
- val newBox1 = testBox(20, alicePubKey, 0, boxIndex = 2)
+ val newBox1 = testBox(20, ErgoTree.fromSigmaBoolean(alicePubKey), 0, boxIndex = 2)
val newBoxes = IndexedSeq(newBox1)
val spendingTransaction = createTransaction(newBoxes)
@@ -250,8 +250,8 @@ class OracleExamplesSpecification extends CompilerTestingCommons
)
val sOracle = oracleBox
- val sAlice = testBox(10, prop, 0, Seq(), Map())
- val sBob = testBox(10, prop, 0, Seq(), Map())
+ val sAlice = testBox(10, ErgoTree.fromProposition(prop), 0, Seq(), Map())
+ val sBob = testBox(10, ErgoTree.fromProposition(prop), 0, Seq(), Map())
val newBox1 = testBox(20, mkTestErgoTree(alicePubKey), 0)
val newBoxes = IndexedSeq(newBox1)
@@ -265,8 +265,10 @@ class OracleExamplesSpecification extends CompilerTestingCommons
spendingTransaction,
self = sOracle, activatedVersionInTests)
- val prA = alice.prove(emptyEnv + (ScriptNameProp -> "alice_prove"), prop, ctx, fakeMessage).get
- verifier.verify(emptyEnv + (ScriptNameProp -> "verify"), prop, ctx, prA, fakeMessage).get._1 shouldBe true
+ val prA = alice.prove(emptyEnv + (ScriptNameProp -> "alice_prove"),
+ mkTestErgoTree(prop), ctx, fakeMessage).get
+ verifier.verify(emptyEnv + (ScriptNameProp -> "verify"),
+ mkTestErgoTree(prop), ctx, prA, fakeMessage).get._1 shouldBe true
}
case class OracleContract[Spec <: ContractSpec]
diff --git a/sc/shared/src/test/scala/sigmastate/utxo/examples/OracleTokenExamplesSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/examples/OracleTokenExamplesSpecification.scala
index 5a30cd6689..e14f47f1c7 100644
--- a/sc/shared/src/test/scala/sigmastate/utxo/examples/OracleTokenExamplesSpecification.scala
+++ b/sc/shared/src/test/scala/sigmastate/utxo/examples/OracleTokenExamplesSpecification.scala
@@ -4,7 +4,7 @@ import org.ergoplatform._
import org.ergoplatform.dsl.ContractSyntax.Token
import org.ergoplatform.dsl.{ContractSpec, SigmaContractSyntax, StdContracts, TestContractSpec}
import scorex.crypto.hash.Blake2b256
-import sigmastate.eval.Digest32Coll
+import sigma.data.Digest32Coll
import sigmastate.helpers.CompilerTestingCommons
import sigma.Coll
import sigma.Context
diff --git a/sc/shared/src/test/scala/sigmastate/utxo/examples/RPSGameExampleSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/examples/RPSGameExampleSpecification.scala
index 1f00dbfc3c..c695b8e07d 100644
--- a/sc/shared/src/test/scala/sigmastate/utxo/examples/RPSGameExampleSpecification.scala
+++ b/sc/shared/src/test/scala/sigmastate/utxo/examples/RPSGameExampleSpecification.scala
@@ -4,13 +4,13 @@ package sigmastate.utxo.examples
import org.ergoplatform.ErgoBox.{R4, R5, R6, R7}
import scorex.crypto.hash.Blake2b256
import scorex.utils.Random
-import sigmastate.Values.{ByteArrayConstant, ByteConstant, IntConstant, SigmaPropConstant}
+import sigma.data.{AvlTreeData, ProveDlog}
+import sigma.ast.{ByteArrayConstant, ByteConstant, ErgoTree, IntConstant, SigmaPropConstant}
import sigmastate._
-import sigmastate.crypto.DLogProtocol.ProveDlog
-import sigmastate.helpers.{ContextEnrichingTestProvingInterpreter, ErgoLikeContextTesting, ErgoLikeTestInterpreter, CompilerTestingCommons}
import sigmastate.helpers.TestingHelpers._
+import sigmastate.helpers.{CompilerTestingCommons, ContextEnrichingTestProvingInterpreter, ErgoLikeContextTesting, ErgoLikeTestInterpreter}
import sigmastate.interpreter.Interpreter._
-import sigmastate.lang.Terms._
+import sigma.ast.syntax._
class RPSGameExampleSpecification extends CompilerTestingCommons
with CompilerCrossVersionProps {
@@ -184,7 +184,7 @@ class RPSGameExampleSpecification extends CompilerTestingCommons
val carolPubKey:ProveDlog = carol.dlogSecrets.head.publicImage
// note that playAmount below is not checked. It could be anything.
- val gameOverOutput = testBox(playAmount, carolPubKey, gameOverHeight)
+ val gameOverOutput = testBox(playAmount, ErgoTree.fromSigmaBoolean(carolPubKey), gameOverHeight)
// normally this transaction would be invalid, but we're not checking it in this test
val gameOverTx = createTransaction(gameOverOutput)
@@ -273,7 +273,7 @@ class RPSGameExampleSpecification extends CompilerTestingCommons
// assume Bob is paying to Carol
// note that playAmount*2 below is not checked. It could be anything.
- val defaultWinOutput = testBox(playAmount*2, carolPubKey, defaultWinHeight)
+ val defaultWinOutput = testBox(playAmount*2, ErgoTree.fromSigmaBoolean(carolPubKey), defaultWinHeight)
//normally this transaction would invalid (why?), but we're not checking it in this test
val defaultWinTx = createTransaction(defaultWinOutput)
diff --git a/sc/shared/src/test/scala/sigmastate/utxo/examples/RevenueSharingExamplesSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/examples/RevenueSharingExamplesSpecification.scala
index 41d3b59039..39326bb01c 100644
--- a/sc/shared/src/test/scala/sigmastate/utxo/examples/RevenueSharingExamplesSpecification.scala
+++ b/sc/shared/src/test/scala/sigmastate/utxo/examples/RevenueSharingExamplesSpecification.scala
@@ -1,9 +1,9 @@
package sigmastate.utxo.examples
-import org.ergoplatform.dsl.{SigmaContractSyntax, ContractSpec, TestContractSpec, StdContracts}
-import sigmastate.eval.Extensions
+import org.ergoplatform.dsl.{ContractSpec, SigmaContractSyntax, StdContracts, TestContractSpec}
import sigmastate.helpers.CompilerTestingCommons
import sigma.Context
+import sigma.ast.IntConstant
class RevenueSharingExamplesSpecification extends CompilerTestingCommons { suite =>
implicit lazy val IR = new TestingIRContext
@@ -121,7 +121,7 @@ class RevenueSharingExamplesSpecification extends CompilerTestingCommons { suite
val in = tx.inputs(0)
- val res = in.runDsl(Map(1.toByte -> Extensions.toAnyValue(1)))
+ val res = in.runDsl(Map(1.toByte -> IntConstant(1)))
val pr = alice.prove(in).get
contract.verifier.verify(in, pr) shouldBe true
diff --git a/sc/shared/src/test/scala/sigmastate/utxo/examples/ReversibleTxExampleSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/examples/ReversibleTxExampleSpecification.scala
index f68c97079b..4294dc5b4b 100644
--- a/sc/shared/src/test/scala/sigmastate/utxo/examples/ReversibleTxExampleSpecification.scala
+++ b/sc/shared/src/test/scala/sigmastate/utxo/examples/ReversibleTxExampleSpecification.scala
@@ -3,12 +3,13 @@ package sigmastate.utxo.examples
import org.ergoplatform.ErgoBox.{R4, R5}
import org.ergoplatform._
import scorex.crypto.hash.Blake2b256
-import sigmastate.Values.{IntConstant, SigmaPropConstant}
+import sigma.data.AvlTreeData
+import sigma.ast.{ErgoTree, IntConstant, SigmaPropConstant}
import sigmastate._
-import sigmastate.helpers.{ContextEnrichingTestProvingInterpreter, ErgoLikeContextTesting, ErgoLikeTestInterpreter, CompilerTestingCommons}
+import sigmastate.helpers.{CompilerTestingCommons, ContextEnrichingTestProvingInterpreter, ErgoLikeContextTesting, ErgoLikeTestInterpreter}
import sigmastate.helpers.TestingHelpers._
import sigmastate.interpreter.Interpreter.ScriptNameProp
-import sigmastate.lang.Terms._
+import sigma.ast.syntax._
class ReversibleTxExampleSpecification extends CompilerTestingCommons
@@ -174,7 +175,7 @@ class ReversibleTxExampleSpecification extends CompilerTestingCommons
val bobSpendAmount = 10
val bobSpendHeight = bobDeadline+1
- val bobSpendOutput = testBox(bobSpendAmount, davePubKey, bobSpendHeight)
+ val bobSpendOutput = testBox(bobSpendAmount, ErgoTree.fromSigmaBoolean(davePubKey), bobSpendHeight)
//normally this transaction would be invalid (why?), but we're not checking it in this test
val bobSpendTx = createTransaction(bobSpendOutput)
@@ -201,7 +202,7 @@ class ReversibleTxExampleSpecification extends CompilerTestingCommons
val carolSpendHeight = bobDeadline - 1
// Carol sends to Dave
- val carolSpendOutput = testBox(carolSpendAmount, davePubKey, carolSpendHeight)
+ val carolSpendOutput = testBox(carolSpendAmount, ErgoTree.fromSigmaBoolean(davePubKey), carolSpendHeight)
//normally this transaction would be invalid (why?), but we're not checking it in this test
val carolSpendTx = createTransaction(carolSpendOutput)
diff --git a/sc/shared/src/test/scala/sigmastate/utxo/examples/Rule110Specification.scala b/sc/shared/src/test/scala/sigmastate/utxo/examples/Rule110Specification.scala
index 00b25ba8e1..a8c58bcc40 100644
--- a/sc/shared/src/test/scala/sigmastate/utxo/examples/Rule110Specification.scala
+++ b/sc/shared/src/test/scala/sigmastate/utxo/examples/Rule110Specification.scala
@@ -4,15 +4,15 @@ import org.ergoplatform._
import scorex.crypto.hash.Blake2b256
import scorex.util._
import sigma.Colls
-import sigmastate.Values._
+import sigma.ast.syntax.{BooleanConstant, GetVarByteArray, OptionValueOps}
+import sigma.ast._
+import sigma.data.AvlTreeData
import sigmastate._
-import sigmastate.eval._
-import sigmastate.helpers.{CompilerTestingCommons, ContextEnrichingTestProvingInterpreter, ErgoLikeContextTesting, ErgoLikeTestInterpreter}
import sigmastate.helpers.TestingHelpers._
-import sigmastate.interpreter.ContextExtension
-import sigmastate.lang.Terms._
-import sigmastate.serialization.ValueSerializer
-import sigmastate.utxo._
+import sigmastate.helpers.{CompilerTestingCommons, ContextEnrichingTestProvingInterpreter, ErgoLikeContextTesting, ErgoLikeTestInterpreter}
+import sigma.ast.syntax._
+import sigma.interpreter.ContextExtension
+import sigma.serialization.ValueSerializer
import sigmastate.utxo.blockchain.BlockchainSimulationTestingCommons._
/**
diff --git a/sc/shared/src/test/scala/sigmastate/utxo/examples/TimedPaymentExampleSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/examples/TimedPaymentExampleSpecification.scala
index 04390272e8..2657a49eb0 100644
--- a/sc/shared/src/test/scala/sigmastate/utxo/examples/TimedPaymentExampleSpecification.scala
+++ b/sc/shared/src/test/scala/sigmastate/utxo/examples/TimedPaymentExampleSpecification.scala
@@ -1,13 +1,14 @@
package sigmastate.utxo.examples
import org.ergoplatform._
-import sigmastate.Values.IntConstant
+import sigma.ast.{ErgoTree, IntConstant}
+import sigma.data.AvlTreeData
import sigmastate._
-import sigmastate.exceptions.InterpreterException
-import sigmastate.helpers.{ContextEnrichingTestProvingInterpreter, ErgoLikeContextTesting, CompilerTestingCommons, ErgoLikeTestInterpreter}
+import sigmastate.helpers.{CompilerTestingCommons, ContextEnrichingTestProvingInterpreter, ErgoLikeContextTesting, ErgoLikeTestInterpreter}
import sigmastate.helpers.TestingHelpers._
import sigmastate.interpreter.Interpreter.ScriptNameProp
-import sigmastate.lang.Terms._
+import sigma.ast.syntax._
+import sigma.exceptions.InterpreterException
class TimedPaymentExampleSpecification extends CompilerTestingCommons
with CompilerCrossVersionProps {
@@ -53,7 +54,7 @@ class TimedPaymentExampleSpecification extends CompilerTestingCommons
val withdrawHeight = 100
val confDeadline = 110
- val timedWithdrawOutput = testBox(withdrawAmount, bobPubKey, withdrawHeight)
+ val timedWithdrawOutput = testBox(withdrawAmount, ErgoTree.fromSigmaBoolean(bobPubKey), withdrawHeight)
//normally this transaction would be invalid, but we're not checking it in this test
val withdrawTx = createTransaction(IndexedSeq(timedWithdrawOutput))
diff --git a/sc/shared/src/test/scala/sigmastate/utxo/examples/TrustlessLETS.scala b/sc/shared/src/test/scala/sigmastate/utxo/examples/TrustlessLETS.scala
index ecaa4c0a14..50348ce7ab 100644
--- a/sc/shared/src/test/scala/sigmastate/utxo/examples/TrustlessLETS.scala
+++ b/sc/shared/src/test/scala/sigmastate/utxo/examples/TrustlessLETS.scala
@@ -5,7 +5,7 @@ import scorex.crypto.hash.Blake2b256
import sigmastate.helpers.{ContextEnrichingTestProvingInterpreter, CompilerTestingCommons}
import sigmastate.helpers.TestingHelpers._
import sigmastate.interpreter.Interpreter._
-import sigmastate.lang.Terms._
+import sigma.ast.syntax._
class TrustlessLETS1 extends CompilerTestingCommons {
private implicit lazy val IR: TestingIRContext = new TestingIRContext
diff --git a/sc/shared/src/test/scala/sigmastate/utxo/examples/XorGameExampleSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/examples/XorGameExampleSpecification.scala
index 436115e9c2..b3d6d4eff8 100644
--- a/sc/shared/src/test/scala/sigmastate/utxo/examples/XorGameExampleSpecification.scala
+++ b/sc/shared/src/test/scala/sigmastate/utxo/examples/XorGameExampleSpecification.scala
@@ -4,13 +4,13 @@ package sigmastate.utxo.examples
import org.ergoplatform.ErgoBox.{R4, R5, R6}
import scorex.crypto.hash.Blake2b256
import scorex.utils.Random
-import sigmastate.Values.{ByteArrayConstant, ByteConstant, IntConstant, SigmaPropConstant}
+import sigma.data.{AvlTreeData, ProveDlog}
+import sigma.ast.{ByteArrayConstant, ByteConstant, IntConstant, SigmaPropConstant}
import sigmastate._
-import sigmastate.crypto.DLogProtocol.ProveDlog
-import sigmastate.helpers.{ContextEnrichingTestProvingInterpreter, ErgoLikeContextTesting, ErgoLikeTestInterpreter, CompilerTestingCommons}
+import sigmastate.helpers.{CompilerTestingCommons, ContextEnrichingTestProvingInterpreter, ErgoLikeContextTesting, ErgoLikeTestInterpreter}
import sigmastate.helpers.TestingHelpers._
import sigmastate.interpreter.Interpreter._
-import sigmastate.lang.Terms._
+import sigma.ast.syntax._
class XorGameExampleSpecification extends CompilerTestingCommons
with CompilerCrossVersionProps {
diff --git a/sdk/js/src/main/scala/org/ergoplatform/sdk/js/AvlTree.scala b/sdk/js/src/main/scala/org/ergoplatform/sdk/js/AvlTree.scala
deleted file mode 100644
index f1cf64377c..0000000000
--- a/sdk/js/src/main/scala/org/ergoplatform/sdk/js/AvlTree.scala
+++ /dev/null
@@ -1,16 +0,0 @@
-package org.ergoplatform.sdk.js
-
-import scala.scalajs.js
-import scala.scalajs.js.UndefOr
-import scala.scalajs.js.annotation.JSExportTopLevel
-
-/** Equivalent of [[sigma.AvlTree]] available from JS. */
-@JSExportTopLevel("AvlTree")
-class AvlTree(
- val digest: String,
- val insertAllowed: Boolean,
- val updateAllowed: Boolean,
- val removeAllowed: Boolean,
- val keyLength: Int,
- val valueLengthOpt: UndefOr[Int]
-) extends js.Object
diff --git a/sdk/js/src/main/scala/org/ergoplatform/sdk/js/ContractTemplate.scala b/sdk/js/src/main/scala/org/ergoplatform/sdk/js/ContractTemplate.scala
new file mode 100644
index 0000000000..7b3d1dd19a
--- /dev/null
+++ b/sdk/js/src/main/scala/org/ergoplatform/sdk/js/ContractTemplate.scala
@@ -0,0 +1,155 @@
+package org.ergoplatform.sdk.js
+
+import org.ergoplatform.sdk
+import org.ergoplatform.sdk.js.ContractTemplate.isoToSdk
+import org.scalablytyped.runtime.StringDictionary
+import sigma.ast.Constant
+import sigma.ast.js.{ErgoTree, Expr}
+import sigma.ast.syntax.SigmaPropValue
+import sigma.data.Iso
+import sigma.js.Type
+import sigma.js.Isos._
+
+import scala.scalajs.js
+import scala.scalajs.js.UndefOr
+import scala.scalajs.js.annotation.JSExportTopLevel
+
+/**
+ * Represents a ContractTemplate parameter.
+ */
+@JSExportTopLevel("Parameter")
+class Parameter(
+ /** User readable parameter name (string bytes in UTF-8 encoding) */
+ val name: String,
+ /** User readable parameter description (string bytes in UTF-8 encoding) */
+ val description: String,
+ /** Index in the ErgoTree.constants array */
+ val constantIndex: Int
+) extends js.Object
+
+@JSExportTopLevel("Parameter$")
+object Parameter extends js.Object {
+ implicit val isoToSdk: sigma.data.Iso[Parameter, sdk.Parameter] =
+ new sigma.data.Iso[Parameter, sdk.Parameter] {
+ override def to(p: Parameter): sdk.Parameter =
+ sdk.Parameter(p.name, p.description, p.constantIndex)
+
+ override def from(p: sdk.Parameter): Parameter =
+ new Parameter(p.name, p.description, p.constantIndex)
+ }
+}
+
+
+/** Represents a reusable ContractTemplate with support to generate ErgoTree based on provided parameters.
+ *
+ * @param treeVersion the optional version of ErgoTree which should be used. If this value is not provided here then
+ * it must be provided while generating the `ErgoTree` by calling `applyTemplate`.
+ * @param name user readable name (non-empty string bytes in UTF-8 encoding)
+ * @param description user readable contract description (string bytes in UTF-8 encoding)
+ * @param constTypes list denoting the type of ConstantPlaceholders in the expressionTree
+ * @param constValues optional list of optional default values for the ConstantPlaceholders in the expressionTree.
+ * If an entry in the sequence is None, it must have a corresponding entry in parameters and its
+ * value must be provided while generating the `ErgoTree` by calling `applyTemplate`. If all the
+ * entries are None, the whole `constValues` field can be set to None.
+ * @param parameters typed template parameters of the contract template. It must have an entry for each
+ * `ConstantPlaceholder` which has a `None` in the `constValues` field. Other fields which do have
+ * a value defined in `constValues` can also be allowed to be optionally overridden by accepting
+ * it in `parameters`.
+ * @param expressionTree root of the contract which is a valid expression of `SigmaProp` type. Must have constants
+ * segregated into `constTypes` and optionally `constValues`
+ */
+@JSExportTopLevel("ContractTemplate")
+class ContractTemplate(
+ val treeVersion: UndefOr[Byte],
+ val name: String,
+ val description: String,
+ val constTypes: js.Array[sigma.js.Type],
+ val constValues: UndefOr[js.Array[UndefOr[sigma.js.Value]]],
+ val parameters: js.Array[Parameter],
+ val expressionTree: Expr
+) extends js.Object {
+ /**
+ * Generate the ErgoTree from the template by providing the values for parameters.
+ *
+ * @param version the version of the `ErgoTree` to use. Must be provided if the `treeVersion` was not provided in the
+ * template.
+ * @param paramValues the name-value map for the parameters accepted by the `ContractTemplate`. Must contain an entry
+ * for each parameter for which no default value was provided in the template. Optionally, can also
+ * provide values to override for parameters which do have a default value defined in the template.
+ * The type of the provided value must match with the corresponding entry in the `constTypes`
+ * provided in the template.
+ * @return `ErgoTree` generated by replacing the template parameters with the value provided in `paramValues`.
+ */
+ def applyTemplate(
+ version: UndefOr[Byte],
+ paramValues: StringDictionary[sigma.js.Value]): sigma.ast.js.ErgoTree = {
+ val params = StringDictionary
+ .wrapStringDictionary(paramValues)
+ .view.mapValues(v => sigma.ast.js.isoValueToConstant.to(v))
+ .toMap
+ val tree = isoToSdk.to(this).applyTemplate(
+ version = isoUndefOr(Iso.identityIso[Byte]).to(version),
+ paramValues = params
+ )
+ new ErgoTree(tree)
+ }
+
+ /** @return JSON representation of this contract template pretty-printed to a string
+ * indentation of two spaces.
+ */
+ def toJsonString(): String = {
+ val template = ContractTemplate.isoToSdk.to(this)
+ template.toJsonString
+ }
+}
+
+@JSExportTopLevel("ContractTemplate$")
+object ContractTemplate extends js.Object {
+
+ /** Create a new contract template from a JSON string.
+ *
+ * @param json JSON string representing a contract template.
+ * @return a new contract template.
+ */
+ def fromJsonString(json: String): ContractTemplate = {
+ io.circe.parser.parse(json) match {
+ case Left(err) => throw err
+ case Right(json) =>
+ val ct = sdk.ContractTemplate.jsonEncoder.decoder(json.hcursor).toOption.get
+ ContractTemplate.isoToSdk.from(ct)
+ }
+ }
+
+ private val constsIso = isoUndefOr(isoArrayToIndexed(isoUndefOr(sigma.ast.js.isoValueToConstant)))
+
+ implicit val isoToSdk: sigma.data.Iso[ContractTemplate, sdk.ContractTemplate] =
+ new sigma.data.Iso[ContractTemplate, sdk.ContractTemplate] {
+ override def to(ct: ContractTemplate): sdk.ContractTemplate = {
+ new sdk.ContractTemplate(
+ isoUndefOr(Iso.identityIso[Byte]).to(ct.treeVersion),
+ ct.name,
+ ct.description,
+ isoArrayToIndexed(Type.isoToSType).to(ct.constTypes),
+ constsIso.to(ct.constValues).map(_.map(costOpt => costOpt.map(_.value))),
+ isoArrayToIndexed(Parameter.isoToSdk).to(ct.parameters),
+ ct.expressionTree.wrappedValue.asInstanceOf[SigmaPropValue]
+ )
+ }
+
+ override def from(ct: sdk.ContractTemplate): ContractTemplate = {
+ // optionally, match each value with its type
+ val constants = ct.constValues.map(values => values.zip(ct.constTypes).map {
+ case (value, tpe) => value.map(v => Constant(v, tpe))
+ })
+ new ContractTemplate(
+ isoUndefOr(Iso.identityIso[Byte]).from(ct.treeVersion),
+ ct.name,
+ ct.description,
+ isoArrayToIndexed(Type.isoToSType).from(ct.constTypes),
+ constsIso.from(constants),
+ isoArrayToIndexed(Parameter.isoToSdk).from(ct.parameters),
+ new Expr(ct.expressionTree)
+ )
+ }
+ }
+}
\ No newline at end of file
diff --git a/sdk/js/src/main/scala/org/ergoplatform/sdk/js/Header.scala b/sdk/js/src/main/scala/org/ergoplatform/sdk/js/Header.scala
index 4d10c9f3dd..ef53e13dbd 100644
--- a/sdk/js/src/main/scala/org/ergoplatform/sdk/js/Header.scala
+++ b/sdk/js/src/main/scala/org/ergoplatform/sdk/js/Header.scala
@@ -1,5 +1,7 @@
package org.ergoplatform.sdk.js
+import sigma.js.{AvlTree, GroupElement}
+
import scala.scalajs.js
import scala.scalajs.js.annotation.JSExportTopLevel
diff --git a/sdk/js/src/main/scala/org/ergoplatform/sdk/js/Isos.scala b/sdk/js/src/main/scala/org/ergoplatform/sdk/js/Isos.scala
index b2ffd664e8..f6393f62bb 100644
--- a/sdk/js/src/main/scala/org/ergoplatform/sdk/js/Isos.scala
+++ b/sdk/js/src/main/scala/org/ergoplatform/sdk/js/Isos.scala
@@ -1,60 +1,37 @@
package org.ergoplatform.sdk.js
import org.ergoplatform.ErgoBox._
+import org.ergoplatform._
+import org.ergoplatform.sdk.ExtendedInputBox
import org.ergoplatform.sdk.JavaHelpers.UniversalConverter
-import org.ergoplatform.sdk.{Iso, ExtendedInputBox}
import org.ergoplatform.sdk.wallet.protocol.context
-import org.ergoplatform._
-import sigma.data.RType
import scorex.crypto.authds.ADKey
import scorex.util.ModifierId
import scorex.util.encode.Base16
-import sigmastate.Values.{Constant, GroupElementConstant}
-import sigmastate.eval.Extensions.ArrayOps
-import sigmastate.eval.{CBigInt, Digest32Coll, Evaluation, CAvlTree, CGroupElement, CPreHeader, CHeader}
+import sigma.Extensions.CollBytesOps
+import sigma.ast.syntax.GroupElementConstant
+import sigma.ast.{Constant, GroupElementConstant, SType}
+import sigma.data.Iso.{isoStringToArray, isoStringToColl}
+import sigma.data.{CBigInt, CGroupElement, Digest32Coll, Digest32CollRType, Iso}
+import sigma.interpreter.{ContextExtension, ProverResult}
+import sigma.js.{AvlTree, GroupElement}
+import sigma.serialization.{ErgoTreeSerializer, ValueSerializer}
+import sigma.{Coll, Colls}
+import sigmastate.eval.{CHeader, CPreHeader}
import sigmastate.fleetSdkCommon.distEsmTypesBoxesMod.Box
import sigmastate.fleetSdkCommon.distEsmTypesCommonMod.HexString
import sigmastate.fleetSdkCommon.distEsmTypesRegistersMod.NonMandatoryRegisters
import sigmastate.fleetSdkCommon.distEsmTypesTokenMod.TokenAmount
-import sigmastate.fleetSdkCommon.distEsmTypesTransactionsMod.{UnsignedTransaction, SignedTransaction}
-import sigmastate.fleetSdkCommon.{distEsmTypesProverResultMod => proverResultMod, distEsmTypesContextExtensionMod => contextExtensionMod, distEsmTypesInputsMod => inputsMod, distEsmTypesBoxesMod => boxesMod, distEsmTypesCommonMod => commonMod, distEsmTypesRegistersMod => registersMod, distEsmTypesTokenMod => tokenMod}
-import sigmastate.interpreter.{ContextExtension, ProverResult}
-import sigmastate.serialization.{ErgoTreeSerializer, ValueSerializer}
-import sigmastate.{AvlTreeData, AvlTreeFlags, SType}
-import sigma.{Coll, Colls}
-import sigma.Extensions.CollBytesOps
+import sigmastate.fleetSdkCommon.distEsmTypesTransactionsMod.{SignedTransaction, UnsignedTransaction}
+import sigmastate.fleetSdkCommon.{distEsmTypesBoxesMod => boxesMod, distEsmTypesCommonMod => commonMod, distEsmTypesContextExtensionMod => contextExtensionMod, distEsmTypesInputsMod => inputsMod, distEsmTypesProverResultMod => proverResultMod, distEsmTypesRegistersMod => registersMod, distEsmTypesTokenMod => tokenMod}
import java.math.BigInteger
import scala.collection.immutable.ListMap
-import scala.reflect.ClassTag
import scala.scalajs.js
-import scala.scalajs.js.JSConverters.JSRichOption
import scala.scalajs.js.Object
/** Definitions of isomorphisms. */
object Isos {
- /** Conversion between `Value` and `Constant[SType]`. */
- implicit val isoValueToConstant: Iso[Value, Constant[SType]] = new Iso[Value, Constant[SType]] {
- override def to(x: Value): Constant[SType] =
- Constant(x.runtimeData.asInstanceOf[SType#WrappedType], Evaluation.rtypeToSType(x.tpe.rtype))
-
- override def from(x: Constant[SType]): Value = {
- val rtype = Evaluation.stypeToRType(x.tpe)
- val jsvalue = Value.fromRuntimeData(x.value, rtype)
- new Value(jsvalue, new Type(rtype))
- }
- }
-
- val isoStringToArray: Iso[String, Array[Byte]] = new Iso[String, Array[Byte]] {
- override def to(x: String): Array[Byte] = Base16.decode(x).get
- override def from(x: Array[Byte]): String = Base16.encode(x)
- }
-
- val isoStringToColl: Iso[String, Coll[Byte]] = new Iso[String, Coll[Byte]] {
- override def to(x: String): Coll[Byte] = Colls.fromArray(Base16.decode(x).get)
- override def from(x: Coll[Byte]): String = x.toHex
- }
-
val isoStringToGroupElement: Iso[String, sigma.GroupElement] = new Iso[String, sigma.GroupElement] {
override def to(x: String): sigma.GroupElement = {
val bytes = Base16.decode(x).get
@@ -93,31 +70,6 @@ object Isos {
}
}
- implicit val isoAvlTree: Iso[AvlTree, sigma.AvlTree] = new Iso[AvlTree, sigma.AvlTree] {
- override def to(x: AvlTree): sigma.AvlTree = {
- CAvlTree(
- AvlTreeData(
- digest = isoStringToArray.to(x.digest).toColl,
- treeFlags = AvlTreeFlags(x.insertAllowed, x.updateAllowed, x.removeAllowed),
- x.keyLength,
- valueLengthOpt = isoUndefOr(Iso.identityIso[Int]).to(x.valueLengthOpt),
- ),
- )
- }
- override def from(x: sigma.AvlTree): AvlTree = {
- val tree = x.asInstanceOf[CAvlTree]
- val data = tree.treeData
- new AvlTree(
- digest = isoStringToColl.from(tree.digest),
- insertAllowed = data.treeFlags.insertAllowed,
- updateAllowed = data.treeFlags.updateAllowed,
- removeAllowed = data.treeFlags.removeAllowed,
- keyLength = data.keyLength,
- valueLengthOpt = isoUndefOr(Iso.identityIso[Int]).from(data.valueLengthOpt),
- )
- }
- }
-
implicit val isoHeader: Iso[Header, sigma.Header] = new Iso[Header, sigma.Header] {
override def to(a: Header): sigma.Header = {
CHeader(
@@ -125,16 +77,16 @@ object Isos {
version = a.version,
parentId = isoStringToColl.to(a.parentId),
ADProofsRoot = isoStringToColl.to(a.ADProofsRoot),
- stateRoot = isoAvlTree.to(a.stateRoot),
+ stateRoot = AvlTree.isoAvlTree.to(a.stateRoot),
transactionsRoot = isoStringToColl.to(a.transactionsRoot),
- timestamp = isoBigIntToLong.to(a.timestamp),
- nBits = isoBigIntToLong.to(a.nBits),
+ timestamp = sigma.js.Isos.isoBigIntToLong.to(a.timestamp),
+ nBits = sigma.js.Isos.isoBigIntToLong.to(a.nBits),
height = a.height,
extensionRoot = isoStringToColl.to(a.extensionRoot),
minerPk = isoGroupElement.to(a.minerPk),
powOnetimePk = isoGroupElement.to(a.powOnetimePk),
powNonce = isoStringToColl.to(a.powNonce),
- powDistance = isoBigInt.to(a.powDistance),
+ powDistance = sigma.js.Isos.isoBigInt.to(a.powDistance),
votes = isoStringToColl.to(a.votes)
)
}
@@ -145,16 +97,16 @@ object Isos {
version = header.version,
parentId = isoStringToColl.from(header.parentId),
ADProofsRoot = isoStringToColl.from(header.ADProofsRoot),
- stateRoot = isoAvlTree.from(header.stateRoot),
+ stateRoot = AvlTree.isoAvlTree.from(header.stateRoot),
transactionsRoot = isoStringToColl.from(header.transactionsRoot),
- timestamp = isoBigIntToLong.from(header.timestamp),
- nBits = isoBigIntToLong.from(header.nBits),
+ timestamp = sigma.js.Isos.isoBigIntToLong.from(header.timestamp),
+ nBits = sigma.js.Isos.isoBigIntToLong.from(header.nBits),
height = header.height,
extensionRoot = isoStringToColl.from(header.extensionRoot),
minerPk = isoGroupElement.from(header.minerPk),
powOnetimePk = isoGroupElement.from(header.powOnetimePk),
powNonce = isoStringToColl.from(header.powNonce),
- powDistance = isoBigInt.from(header.powDistance),
+ powDistance = sigma.js.Isos.isoBigInt.from(header.powDistance),
votes = isoStringToColl.from(header.votes)
)
}
@@ -165,8 +117,8 @@ object Isos {
CPreHeader(
version = a.version,
parentId = isoStringToColl.to(a.parentId),
- timestamp = isoBigIntToLong.to(a.timestamp),
- nBits = isoBigIntToLong.to(a.nBits),
+ timestamp = sigma.js.Isos.isoBigIntToLong.to(a.timestamp),
+ nBits = sigma.js.Isos.isoBigIntToLong.to(a.nBits),
height = a.height,
minerPk = isoGroupElement.to(a.minerPk),
votes = isoStringToColl.to(a.votes)
@@ -177,8 +129,8 @@ object Isos {
new PreHeader(
version = header.version,
parentId = isoStringToColl.from(header.parentId),
- timestamp = isoBigIntToLong.from(header.timestamp),
- nBits = isoBigIntToLong.from(header.nBits),
+ timestamp = sigma.js.Isos.isoBigIntToLong.from(header.timestamp),
+ nBits = sigma.js.Isos.isoBigIntToLong.from(header.nBits),
height = header.height,
minerPk = isoGroupElement.from(header.minerPk),
votes = isoStringToColl.from(header.votes)
@@ -197,8 +149,8 @@ object Isos {
dataInputCost = a.dataInputCost,
outputCost = a.outputCost,
maxBlockCost = a.maxBlockCost,
- softForkStartingHeight = Isos.isoUndefOr[Int, Int](Iso.identityIso).to(a.softForkStartingHeight),
- softForkVotesCollected = Isos.isoUndefOr[Int, Int](Iso.identityIso).to(a.softForkVotesCollected),
+ softForkStartingHeight = sigma.js.Isos.isoUndefOr[Int, Int](Iso.identityIso).to(a.softForkStartingHeight),
+ softForkVotesCollected = sigma.js.Isos.isoUndefOr[Int, Int](Iso.identityIso).to(a.softForkVotesCollected),
blockVersion = a.blockVersion
)
}
@@ -212,8 +164,8 @@ object Isos {
dataInputCost = b.dataInputCost,
outputCost = b.outputCost,
maxBlockCost = b.maxBlockCost,
- softForkStartingHeight = Isos.isoUndefOr[Int, Int](Iso.identityIso).from(b.softForkStartingHeight),
- softForkVotesCollected = Isos.isoUndefOr[Int, Int](Iso.identityIso).from(b.softForkVotesCollected),
+ softForkStartingHeight = sigma.js.Isos.isoUndefOr[Int, Int](Iso.identityIso).from(b.softForkStartingHeight),
+ softForkVotesCollected = sigma.js.Isos.isoUndefOr[Int, Int](Iso.identityIso).from(b.softForkVotesCollected),
blockVersion = b.blockVersion
)
}
@@ -222,7 +174,7 @@ object Isos {
implicit val isoBlockchainStateContext: Iso[BlockchainStateContext, context.BlockchainStateContext] = new Iso[BlockchainStateContext, context.BlockchainStateContext] {
override def to(a: BlockchainStateContext): context.BlockchainStateContext = {
context.CBlockchainStateContext(
- sigmaLastHeaders = isoArrayToColl(isoHeader).to(a.sigmaLastHeaders),
+ sigmaLastHeaders = sigma.js.Isos.isoArrayToColl(isoHeader).to(a.sigmaLastHeaders),
previousStateDigest = isoStringToColl.to(a.previousStateDigest),
sigmaPreHeader = isoPreHeader.to(a.sigmaPreHeader)
)
@@ -230,7 +182,7 @@ object Isos {
override def from(b: context.BlockchainStateContext): BlockchainStateContext = {
new BlockchainStateContext(
- sigmaLastHeaders = isoArrayToColl(isoHeader).from(b.sigmaLastHeaders),
+ sigmaLastHeaders = sigma.js.Isos.isoArrayToColl(isoHeader).from(b.sigmaLastHeaders),
previousStateDigest = isoStringToColl.from(b.previousStateDigest),
sigmaPreHeader = isoPreHeader.from(b.sigmaPreHeader)
)
@@ -295,22 +247,6 @@ object Isos {
override def from(x: DataInput): inputsMod.DataInput = inputsMod.DataInput(x.boxId.convertTo[boxesMod.BoxId])
}
- implicit val isoBigInt: Iso[js.BigInt, sigma.BigInt] = new Iso[js.BigInt, sigma.BigInt] {
- override def to(x: js.BigInt): sigma.BigInt = {
- CBigInt(new BigInteger(x.toString(10)))
- }
- override def from(x: sigma.BigInt): js.BigInt = {
- val bi = x.asInstanceOf[CBigInt].wrappedValue
- val s = bi.toString(10)
- js.BigInt(s)
- }
- }
-
- implicit val isoBigIntToLong: Iso[js.BigInt, Long] = new Iso[js.BigInt, Long] {
- override def to(x: js.BigInt): Long = java.lang.Long.parseLong(x.toString(10))
- override def from(x: Long): js.BigInt = js.BigInt(x.toString)
- }
-
implicit val isoAmount: Iso[commonMod.Amount, Long] = new Iso[commonMod.Amount, Long] {
override def to(x: commonMod.Amount): Long = x.asInstanceOf[Any] match {
case s: String => BigInt(s).toLong
@@ -328,28 +264,13 @@ object Isos {
tokenMod.TokenAmount[commonMod.Amount](isoAmount.from(x._2), x._1.toHex)
}
- implicit def isoUndefOr[A, B](implicit iso: Iso[A, B]): Iso[js.UndefOr[A], Option[B]] = new Iso[js.UndefOr[A], Option[B]] {
- override def to(x: js.UndefOr[A]): Option[B] = x.toOption.map(iso.to)
- override def from(x: Option[B]): js.UndefOr[A] = x.map(iso.from).orUndefined
- }
-
- implicit def isoArrayToColl[A, B](iso: Iso[A, B])(implicit ctA: ClassTag[A], tB: RType[B]): Iso[js.Array[A], Coll[B]] = new Iso[js.Array[A], Coll[B]] {
- override def to(x: js.Array[A]): Coll[B] = Colls.fromArray(x.map(iso.to).toArray(tB.classTag))
- override def from(x: Coll[B]): js.Array[A] = js.Array(x.toArray.map(iso.from):_*)
- }
-
- implicit def isoArrayToIndexed[A, B](iso: Iso[A, B])(implicit cB: ClassTag[B]): Iso[js.Array[A], IndexedSeq[B]] = new Iso[js.Array[A], IndexedSeq[B]] {
- override def to(x: js.Array[A]): IndexedSeq[B] = x.map(iso.to).toArray(cB).toIndexedSeq
- override def from(x: IndexedSeq[B]): js.Array[A] = js.Array(x.map(iso.from):_*)
- }
-
val isoTokenArray: Iso[js.Array[tokenMod.TokenAmount[commonMod.Amount]], Coll[Token]] =
new Iso[js.Array[tokenMod.TokenAmount[commonMod.Amount]], Coll[Token]] {
override def to(x: js.Array[tokenMod.TokenAmount[commonMod.Amount]]): Coll[Token] = {
- isoArrayToColl(isoToken).to(x)
+ sigma.js.Isos.isoArrayToColl(isoToken).to(x)
}
override def from(x: Coll[Token]): js.Array[tokenMod.TokenAmount[commonMod.Amount]] = {
- isoArrayToColl(isoToken).from(x)
+ sigma.js.Isos.isoArrayToColl(isoToken).from(x)
}
}
@@ -484,17 +405,17 @@ object Isos {
new Iso[UnsignedTransaction, UnsignedErgoLikeTransaction] {
override def to(a: UnsignedTransaction): UnsignedErgoLikeTransaction = {
new UnsignedErgoLikeTransaction(
- inputs = isoArrayToIndexed(isoUnsignedInput).to(a.inputs),
- dataInputs = isoArrayToIndexed(isoDataInput).to(a.dataInputs),
- outputCandidates = isoArrayToIndexed(isoBoxCandidate).to(a.outputs),
+ inputs = sigma.js.Isos.isoArrayToIndexed(isoUnsignedInput).to(a.inputs),
+ dataInputs = sigma.js.Isos.isoArrayToIndexed(isoDataInput).to(a.dataInputs),
+ outputCandidates = sigma.js.Isos.isoArrayToIndexed(isoBoxCandidate).to(a.outputs),
)
}
override def from(b: UnsignedErgoLikeTransaction): UnsignedTransaction = {
UnsignedTransaction(
- inputs = isoArrayToIndexed(isoUnsignedInput).from(b.inputs),
- dataInputs = isoArrayToIndexed(isoDataInput).from(b.dataInputs),
- outputs = isoArrayToIndexed(isoBoxCandidate).from(b.outputCandidates)
+ inputs = sigma.js.Isos.isoArrayToIndexed(isoUnsignedInput).from(b.inputs),
+ dataInputs = sigma.js.Isos.isoArrayToIndexed(isoDataInput).from(b.dataInputs),
+ outputs = sigma.js.Isos.isoArrayToIndexed(isoBoxCandidate).from(b.outputCandidates)
)
}
}
@@ -503,16 +424,16 @@ object Isos {
new Iso[SignedTransaction, ErgoLikeTransaction] {
override def to(a: SignedTransaction): ErgoLikeTransaction = {
new ErgoLikeTransaction(
- inputs = isoArrayToIndexed(isoSignedInput).to(a.inputs),
- dataInputs = isoArrayToIndexed(isoDataInput).to(a.dataInputs),
- outputCandidates = isoArrayToIndexed(isoBox).to(a.outputs),
+ inputs = sigma.js.Isos.isoArrayToIndexed(isoSignedInput).to(a.inputs),
+ dataInputs = sigma.js.Isos.isoArrayToIndexed(isoDataInput).to(a.dataInputs),
+ outputCandidates = sigma.js.Isos.isoArrayToIndexed(isoBox).to(a.outputs),
)
}
override def from(tx: ErgoLikeTransaction): SignedTransaction = {
- val inputs = isoArrayToIndexed(isoSignedInput).from(tx.inputs)
- val dataInputs = isoArrayToIndexed(isoDataInput).from(tx.dataInputs)
- val outputs = isoArrayToIndexed(isoBox).from(tx.outputs)
+ val inputs = sigma.js.Isos.isoArrayToIndexed(isoSignedInput).from(tx.inputs)
+ val dataInputs = sigma.js.Isos.isoArrayToIndexed(isoDataInput).from(tx.dataInputs)
+ val outputs = sigma.js.Isos.isoArrayToIndexed(isoBox).from(tx.outputs)
SignedTransaction(dataInputs, tx.id, inputs, outputs)
}
}
diff --git a/sdk/js/src/main/scala/org/ergoplatform/sdk/js/PreHeader.scala b/sdk/js/src/main/scala/org/ergoplatform/sdk/js/PreHeader.scala
index 08a8ace0d9..c2c0c993bf 100644
--- a/sdk/js/src/main/scala/org/ergoplatform/sdk/js/PreHeader.scala
+++ b/sdk/js/src/main/scala/org/ergoplatform/sdk/js/PreHeader.scala
@@ -1,5 +1,7 @@
package org.ergoplatform.sdk.js
+import sigma.js.GroupElement
+
import scala.scalajs.js
import scala.scalajs.js.annotation.JSExportTopLevel
diff --git a/sdk/js/src/main/scala/org/ergoplatform/sdk/js/ProverBuilder.scala b/sdk/js/src/main/scala/org/ergoplatform/sdk/js/ProverBuilder.scala
index 2c27a177d4..12ecf1d03f 100644
--- a/sdk/js/src/main/scala/org/ergoplatform/sdk/js/ProverBuilder.scala
+++ b/sdk/js/src/main/scala/org/ergoplatform/sdk/js/ProverBuilder.scala
@@ -6,7 +6,7 @@ import org.ergoplatform.sdk.SecretString
import scala.scalajs.js
import scala.scalajs.js.annotation.JSExportTopLevel
import Isos._
-import sigmastate.eval.SigmaDsl
+import sigma.eval.SigmaDsl
/** Equivalent of [[sdk.ProverBuilder]] available from JS.
*
@@ -70,7 +70,7 @@ class ProverBuilder(parameters: BlockchainParameters, network: Byte) extends js.
isoStringToGroupElement.to(h),
isoStringToGroupElement.to(u),
isoStringToGroupElement.to(v),
- SigmaDsl.toBigInteger(isoBigInt.to(x))
+ SigmaDsl.toBigInteger(sigma.js.Isos.isoBigInt.to(x))
)
this
}
@@ -84,7 +84,7 @@ class ProverBuilder(parameters: BlockchainParameters, network: Byte) extends js.
* as proveDlog(a) && proveDlog(b), where a and b are two group elements.
*/
def withDLogSecret(x: js.BigInt): ProverBuilder = {
- _builder.withDLogSecret(SigmaDsl.toBigInteger(isoBigInt.to(x)))
+ _builder.withDLogSecret(SigmaDsl.toBigInteger(sigma.js.Isos.isoBigInt.to(x)))
this
}
@@ -95,7 +95,7 @@ class ProverBuilder(parameters: BlockchainParameters, network: Byte) extends js.
}
}
-@JSExportTopLevel("ProverBuilderObj")
+@JSExportTopLevel("ProverBuilder$")
object ProverBuilder extends js.Object {
/** Creates a new [[ProverBuilder]] instance with the given blockchain parameters
* and network prefix.
diff --git a/sdk/js/src/main/scala/org/ergoplatform/sdk/js/ReducedTransaction.scala b/sdk/js/src/main/scala/org/ergoplatform/sdk/js/ReducedTransaction.scala
index a27c61d261..c01a61adb8 100644
--- a/sdk/js/src/main/scala/org/ergoplatform/sdk/js/ReducedTransaction.scala
+++ b/sdk/js/src/main/scala/org/ergoplatform/sdk/js/ReducedTransaction.scala
@@ -12,7 +12,7 @@ class ReducedTransaction(val _tx: sdk.ReducedTransaction) extends js.Object {
def toHex(): String = _tx.toHex
}
-@JSExportTopLevel("ReducedTransactionObj")
+@JSExportTopLevel("ReducedTransaction$")
object ReducedTransaction extends js.Object {
/** Creates a [[ReducedTransaction]] from serialized bytes in hex format. */
def fromHex(hex: String): ReducedTransaction = {
diff --git a/sdk/js/src/main/scala/org/ergoplatform/sdk/js/SigmaProp.scala b/sdk/js/src/main/scala/org/ergoplatform/sdk/js/SigmaProp.scala
deleted file mode 100644
index 2dc665d918..0000000000
--- a/sdk/js/src/main/scala/org/ergoplatform/sdk/js/SigmaProp.scala
+++ /dev/null
@@ -1,24 +0,0 @@
-package org.ergoplatform.sdk.js
-
-import sigmastate.Values.SigmaBoolean
-import sigmastate.crypto.DLogProtocol.ProveDlog
-
-import scala.scalajs.js
-import scala.scalajs.js.annotation.JSExportTopLevel
-
-/** Equivalent of [[sigma.SigmaProp]] available from JS. */
-@JSExportTopLevel("SigmaProp")
-class SigmaProp(val sigmaBoolean: SigmaBoolean) extends js.Object {
-}
-
-@JSExportTopLevel("SigmaPropObj")
-object SigmaProp extends js.Object {
- /** Creates a new [[SigmaProp]] from the given hex string of public key.
- * @param pointHex hex representation of elliptic curve point (ASN.1 encoded)
- * @see CryptoFacade.getASN1Encoding, GroupElement.fromPointHex, Point
- */
- def fromPointHex(pointHex: String): SigmaProp = {
- val point = GroupElement.fromPointHex(pointHex).point
- new SigmaProp(ProveDlog(point))
- }
-}
diff --git a/sdk/js/src/main/scala/org/ergoplatform/sdk/js/SigmaProver.scala b/sdk/js/src/main/scala/org/ergoplatform/sdk/js/SigmaProver.scala
index 6aedecf2e9..0a6aca4830 100644
--- a/sdk/js/src/main/scala/org/ergoplatform/sdk/js/SigmaProver.scala
+++ b/sdk/js/src/main/scala/org/ergoplatform/sdk/js/SigmaProver.scala
@@ -24,7 +24,7 @@ class SigmaProver(_prover: sdk.SigmaProver) extends js.Object {
/** Returns the prover's secret key. */
def getSecretKey(): js.BigInt =
- isoBigInt.from(_prover.getSecretKey)
+ sigma.js.Isos.isoBigInt.from(_prover.getSecretKey)
/** Returns an array of EIP-3 addresses associated with the prover's secret keys. */
def getEip3Addresses(): js.Array[String] = {
@@ -50,9 +50,9 @@ class SigmaProver(_prover: sdk.SigmaProver) extends js.Object {
baseCost: Int): ReducedTransaction = {
val unreducedTx = sdk.UnreducedTransaction(
unsignedTx = isoUnsignedTransaction.to(unsignedTx),
- boxesToSpend = isoArrayToIndexed(isoEIP12UnsignedInput).to(boxesToSpend),
- dataInputs = isoArrayToIndexed(isoBox).to(dataInputs),
- tokensToBurn = isoArrayToIndexed(isoToken.andThen(sdk.Iso.isoErgoTokenToPair.inverse)).to(tokensToBurn)
+ boxesToSpend = sigma.js.Isos.isoArrayToIndexed(isoEIP12UnsignedInput).to(boxesToSpend),
+ dataInputs = sigma.js.Isos.isoArrayToIndexed(isoBox).to(dataInputs),
+ tokensToBurn = sigma.js.Isos.isoArrayToIndexed(isoToken.andThen(sdk.SdkIsos.isoErgoTokenToPair.inverse)).to(tokensToBurn)
)
val ctx = isoBlockchainStateContext.to(stateCtx)
val reducedTx = _prover.reduce(ctx, unreducedTx, baseCost)
diff --git a/sdk/js/src/test/scala/org/ergoplatform/sdk/js/IsosSpec.scala b/sdk/js/src/test/scala/org/ergoplatform/sdk/js/IsosSpec.scala
index 2164b9b339..a366e33d3c 100644
--- a/sdk/js/src/test/scala/org/ergoplatform/sdk/js/IsosSpec.scala
+++ b/sdk/js/src/test/scala/org/ergoplatform/sdk/js/IsosSpec.scala
@@ -2,52 +2,30 @@ package org.ergoplatform.sdk.js
import org.ergoplatform.ErgoBox.{AdditionalRegisters, BoxId, TokenId}
import org.ergoplatform._
-import org.ergoplatform.sdk.wallet.protocol.context.{BlockchainStateContext, CBlockchainStateContext}
-import org.ergoplatform.sdk.{ExtendedInputBox, Iso}
-import org.scalacheck.{Arbitrary, Gen}
-import org.scalatest.matchers.should.Matchers
-import org.scalatest.propspec.AnyPropSpec
-import org.scalatestplus.scalacheck.ScalaCheckPropertyChecks
-import sigmastate.SType
-import sigmastate.Values.Constant
-import sigmastate.interpreter.{ContextExtension, ProverResult}
-import sigmastate.serialization.generators.ObjectGenerators
-import sigma.{Coll, Colls, GroupElement}
+import org.ergoplatform.sdk.ExtendedInputBox
+import org.ergoplatform.sdk.wallet.protocol.context.BlockchainStateContext
+import org.scalacheck.Arbitrary
+import sigma.ast.{Constant, SType}
+import sigma.data.Iso
+import sigma.interpreter.{ContextExtension, ProverResult}
+import sigma.js.AvlTree
+import sigma.{Coll, GroupElement}
import scala.scalajs.js
-class IsosSpec extends AnyPropSpec with Matchers with ObjectGenerators with ScalaCheckPropertyChecks{
-
- lazy val extendedInputBoxGen: Gen[ExtendedInputBox] = for {
- box <- ergoBoxGen
- extension <- contextExtensionGen
- } yield ExtendedInputBox(box, extension)
-
- lazy val blockchainStateContextGen: Gen[BlockchainStateContext] = for {
- stateRoot <- avlTreeGen
- headers <- headersGen(stateRoot)
- preHeader <- preHeaderGen(headers.headOption.map(_.id).getOrElse(modifierIdBytesGen.sample.get))
- } yield CBlockchainStateContext(
- sigmaLastHeaders = Colls.fromItems(headers:_*),
- previousStateDigest = stateRoot.digest,
- sigmaPreHeader = preHeader
- )
-
- def roundtrip[A,B](iso: Iso[A,B])(b: B): Unit = {
- iso.to(iso.from(b)) shouldBe b
- }
+class IsosSpec extends IsosSpecBase with sdk.generators.ObjectGenerators {
override implicit val generatorDrivenConfig: PropertyCheckConfiguration = PropertyCheckConfiguration(minSuccessful = 30)
property("Iso.isoStringToArray") {
forAll() { (bytes: Array[Byte]) =>
- roundtrip(Isos.isoStringToArray)(bytes)
+ roundtrip(Iso.isoStringToArray)(bytes)
}
}
property("Iso.isoStringToColl") {
forAll() { (bytes: Coll[Byte]) =>
- roundtrip(Isos.isoStringToColl)(bytes)
+ roundtrip(Iso.isoStringToColl)(bytes)
}
}
@@ -71,7 +49,7 @@ class IsosSpec extends AnyPropSpec with Matchers with ObjectGenerators with Sca
property("Iso.avlTree") {
forAll { (c: sigma.AvlTree) =>
- roundtrip(Isos.isoAvlTree)(c)
+ roundtrip(AvlTree.isoAvlTree)(c)
}
}
@@ -125,13 +103,13 @@ class IsosSpec extends AnyPropSpec with Matchers with ObjectGenerators with Sca
property("Iso.isoBigInt") {
forAll { (c: sigma.BigInt) =>
- roundtrip(Isos.isoBigInt)(c)
+ roundtrip(sigma.js.Isos.isoBigInt)(c)
}
}
property("Iso.isoBigIntToLong") {
forAll { (c: Long) =>
- roundtrip(Isos.isoBigIntToLong)(c)
+ roundtrip(sigma.js.Isos.isoBigIntToLong)(c)
}
}
@@ -156,7 +134,7 @@ class IsosSpec extends AnyPropSpec with Matchers with ObjectGenerators with Sca
property("Iso.isoUndefOr") {
forAll { opt: Option[Long] =>
- roundtrip(Isos.isoUndefOr(Iso.identityIso[Long]))(opt)
+ roundtrip(sigma.js.Isos.isoUndefOr(Iso.identityIso[Long]))(opt)
}
}
@@ -195,4 +173,11 @@ class IsosSpec extends AnyPropSpec with Matchers with ObjectGenerators with Sca
roundtrip(Isos.isoSignedTransaction)(tx)
}
}
+
+ property("Iso.isoContractTemplate") {
+ forAll(contractTemplateGen) { (tx: sdk.ContractTemplate) =>
+ roundtrip(ContractTemplate.isoToSdk)(tx)
+ }
+ }
+
}
diff --git a/sdk/js/src/test/scala/org/ergoplatform/sdk/js/IsosSpecBase.scala b/sdk/js/src/test/scala/org/ergoplatform/sdk/js/IsosSpecBase.scala
new file mode 100644
index 0000000000..ca15ed6853
--- /dev/null
+++ b/sdk/js/src/test/scala/org/ergoplatform/sdk/js/IsosSpecBase.scala
@@ -0,0 +1,32 @@
+package org.ergoplatform.sdk.js
+
+import org.ergoplatform.sdk.ExtendedInputBox
+import org.ergoplatform.sdk.wallet.protocol.context.{BlockchainStateContext, CBlockchainStateContext}
+import org.scalacheck.Gen
+import org.scalatest.matchers.should.Matchers
+import org.scalatest.propspec.AnyPropSpec
+import org.scalatestplus.scalacheck.ScalaCheckPropertyChecks
+import sigma.Colls
+import sigma.data.Iso
+import sigma.serialization.generators.ObjectGenerators
+
+class IsosSpecBase extends AnyPropSpec with Matchers with ObjectGenerators with ScalaCheckPropertyChecks {
+ lazy val extendedInputBoxGen: Gen[ExtendedInputBox] = for {
+ box <- ergoBoxGen
+ extension <- contextExtensionGen
+ } yield ExtendedInputBox(box, extension)
+
+ lazy val blockchainStateContextGen: Gen[BlockchainStateContext] = for {
+ stateRoot <- avlTreeGen
+ headers <- headersGen(stateRoot)
+ preHeader <- preHeaderGen(headers.headOption.map(_.id).getOrElse(modifierIdBytesGen.sample.get))
+ } yield CBlockchainStateContext(
+ sigmaLastHeaders = Colls.fromItems(headers: _*),
+ previousStateDigest = stateRoot.digest,
+ sigmaPreHeader = preHeader
+ )
+
+ def roundtrip[A, B](iso: Iso[A, B])(b: B): Unit = {
+ iso.to(iso.from(b)) shouldBe b
+ }
+}
diff --git a/sdk/js/src/test/scala/org/ergoplatform/sdk/js/ValueSpec.scala b/sdk/js/src/test/scala/org/ergoplatform/sdk/js/ValueSpec.scala
index be0997fcc6..4599980006 100644
--- a/sdk/js/src/test/scala/org/ergoplatform/sdk/js/ValueSpec.scala
+++ b/sdk/js/src/test/scala/org/ergoplatform/sdk/js/ValueSpec.scala
@@ -4,27 +4,27 @@ import org.scalatest.matchers.should.Matchers
import org.scalatest.propspec.AnyPropSpec
import org.scalatestplus.scalacheck.ScalaCheckPropertyChecks
import scorex.util.encode.Base16
-import sigmastate.SType
-import sigmastate.Values.{AvlTreeConstant, BigIntConstant, BooleanConstant, BoxConstant, ByteConstant, Constant, GroupElementConstant, IntConstant, LongConstant, ShortConstant, SigmaPropConstant, UnitConstant}
-import sigmastate.crypto.CryptoConstants.dlogGroup
-import sigmastate.crypto.DLogProtocol.ProveDlog
-import sigmastate.crypto.CryptoFacade
-import sigmastate.eval.CSigmaProp
-import sigmastate.lang.DeserializationSigmaBuilder
-import sigmastate.serialization.ConstantSerializer
+import sigma.ast.{DeserializationSigmaBuilder, SType}
+import sigma.ast._
+import sigma.crypto.CryptoConstants.dlogGroup
+import sigma.crypto.CryptoFacade
+import sigma.serialization.ConstantSerializer
import sigmastate.utils.Helpers
import sigma.SigmaTestingData
+import sigma.data.{CSigmaProp, ProveDlog}
+import sigma.ast.js.isoValueToConstant
+import sigma.js.Value
import java.math.BigInteger
class ValueSpec extends AnyPropSpec with Matchers with SigmaTestingData with ScalaCheckPropertyChecks {
def test[T <: SType](c: Constant[T], expectedHex: String) = {
- val v = Isos.isoValueToConstant.from(c)
+ val v = isoValueToConstant.from(c)
val S = ConstantSerializer(DeserializationSigmaBuilder)
Base16.encode(S.toBytes(c)) shouldBe expectedHex
v.toHex() shouldBe expectedHex
- Isos.isoValueToConstant.to(Value.fromHex(expectedHex)) shouldBe c
+ isoValueToConstant.to(Value.fromHex(expectedHex)) shouldBe c
}
property("Boolean toHex()/fromHex()") {
@@ -61,7 +61,8 @@ class ValueSpec extends AnyPropSpec with Matchers with SigmaTestingData with Sca
test(AvlTreeConstant(TestData.t3), "643100d2e101ff01fc047c7f6f00ff80129df69a5090012f01ffca99f5bfff0c803601800100")
}
- property("Box toHex()/fromHex()") {
+ // TODO turn on when Value.fromHex is implemented for Box
+ ignore("Box toHex()/fromHex()") {
test(BoxConstant(TestData.b2), "63b96000d1968302010100ff83020193040204020100c0843d000401010e32297000800b80f1d56c809a8c6affbed864b87f007f6f007f00ac00018c01c4fdff011088807f0100657f00f9ab0101ff6d6505a4a7b5a2e7a4a4dd3a05feffffffffffffffff01003bd5c630803cfff6c1ff7f7fb980ff136afc011f8080b8b04ad4dbda2d7f4e01")
}
diff --git a/sdk/shared/src/main/scala/org/ergoplatform/sdk/AppkitProvingInterpreter.scala b/sdk/shared/src/main/scala/org/ergoplatform/sdk/AppkitProvingInterpreter.scala
index b3b470c604..c0dc075a9b 100644
--- a/sdk/shared/src/main/scala/org/ergoplatform/sdk/AppkitProvingInterpreter.scala
+++ b/sdk/shared/src/main/scala/org/ergoplatform/sdk/AppkitProvingInterpreter.scala
@@ -8,16 +8,15 @@ import org.ergoplatform.sdk.utils.ArithUtils
import org.ergoplatform.sdk.wallet.protocol.context.{BlockchainStateContext, TransactionContext}
import org.ergoplatform.sdk.wallet.secrets.ExtendedSecretKey
import org.ergoplatform.validation.ValidationRules
-import sigma.util.Extensions.LongOps
import sigma.VersionContext
-import sigmastate.Values.SigmaBoolean
-import sigmastate.crypto.DLogProtocol.{DLogProverInput, ProveDlog}
+import sigma.data.{AvlTreeData, ProveDlog, SigmaBoolean}
+import sigma.interpreter.{ContextExtension, ProverResult}
+import sigma.util.Extensions.LongOps
+import sigmastate.crypto.DLogProtocol.DLogProverInput
import sigmastate.crypto.{DiffieHellmanTupleProverInput, SigmaProtocolPrivateInput}
import sigmastate.interpreter.Interpreter.{ReductionResult, estimateCryptoVerifyCost}
import sigmastate.interpreter._
-import sigmastate.serialization.SigmaSerializer
-import sigmastate.utils.{SigmaByteReader, SigmaByteWriter}
-import sigmastate.AvlTreeData
+import sigma.serialization.{SigmaByteReader, SigmaByteWriter, SigmaSerializer}
import java.util
import java.util.{Objects, List => JList}
@@ -40,7 +39,7 @@ class AppkitProvingInterpreter(
extends ReducingInterpreter(params) with ProverInterpreter {
override type CTX = ErgoLikeContext
- import org.ergoplatform.sdk.Iso._
+ import org.ergoplatform.sdk.SdkIsos._
/** All secrets available to this interpreter including [[ExtendedSecretKey]], dlog and
* dht secrets.
diff --git a/sdk/shared/src/main/scala/org/ergoplatform/sdk/ContractTemplate.scala b/sdk/shared/src/main/scala/org/ergoplatform/sdk/ContractTemplate.scala
index 47d2a06d3e..5e491630bd 100644
--- a/sdk/shared/src/main/scala/org/ergoplatform/sdk/ContractTemplate.scala
+++ b/sdk/shared/src/main/scala/org/ergoplatform/sdk/ContractTemplate.scala
@@ -1,24 +1,21 @@
package org.ergoplatform.sdk
-import cats.syntax.either._ // required for Scala 2.11
+import cats.syntax.either._ // required for Scala 2.11
import debox.cfor
import io.circe._
import io.circe.syntax.EncoderOps
import org.ergoplatform.sdk.utils.SerializationUtils.{parseString, serializeString}
import org.ergoplatform.sdk.utils.Zero
+import sigma.Evaluation
+import sigma.ast.{DeserializationSigmaBuilder, SType, StdSigmaBuilder}
+import sigma.serialization.{SerializerException, SigmaByteReader, SigmaByteWriter}
import sigma.util.safeNewArray
-import sigmastate.Values.ErgoTree.headerWithVersion
-import sigmastate.Values.{ErgoTree, _}
-import sigmastate._
-import sigmastate.eval._
-import sigmastate.exceptions.SerializerException
-import sigmastate.lang.{DeserializationSigmaBuilder, StdSigmaBuilder}
-import sigmastate.serialization._
-import sigmastate.utils.{SigmaByteReader, SigmaByteWriter}
-
+import sigma.ast.ErgoTree.{ZeroHeader, headerWithVersion, setConstantSegregation}
+import sigma.ast._
+import sigma.ast.syntax.SigmaPropValue
+import sigma.serialization._
import java.util.Objects
import scala.collection.mutable
-import scala.language.implicitConversions
/**
* Represents a ContractTemplate parameter.
@@ -145,7 +142,7 @@ case class ContractTemplate(
* provided in the template.
* @return `ErgoTree` generated by replacing the template parameters with the value provided in `paramValues`.
*/
- def applyTemplate(version: Option[Byte], paramValues: Map[String, Values.Constant[SType]]): Values.ErgoTree = {
+ def applyTemplate(version: Option[Byte], paramValues: Map[String, Constant[SType]]): ErgoTree = {
require(treeVersion.isDefined || version.isDefined, "ErgoTreeVersion must be provided to generate the ErgoTree.")
val nConsts = constTypes.size
val requiredParameterNames =
@@ -173,14 +170,22 @@ case class ContractTemplate(
}
}
- val usedErgoTreeVersion = headerWithVersion(if (version.isDefined) version.get else treeVersion.get)
+ val usedErgoTreeHeader = headerWithVersion(ZeroHeader, if (version.isDefined) version.get else treeVersion.get)
ErgoTree(
- (ErgoTree.ConstantSegregationHeader | usedErgoTreeVersion).toByte,
+ setConstantSegregation(usedErgoTreeHeader),
constants,
this.expressionTree
)
}
+ /** @return Json representation of this contract template */
+ def toJson: Json = ContractTemplate.jsonEncoder.encoder(this)
+
+ /** @return JSON representation of this contract template pretty-printed to a string
+ * indentation of two spaces.
+ */
+ def toJsonString: String = toJson.spaces2
+
override def hashCode(): Int = Objects.hash(treeVersion, name, description, constTypes, constValues, parameters, expressionTree)
override def equals(obj: Any): Boolean = (this eq obj.asInstanceOf[AnyRef]) ||
diff --git a/sdk/shared/src/main/scala/org/ergoplatform/sdk/DataJsonEncoder.scala b/sdk/shared/src/main/scala/org/ergoplatform/sdk/DataJsonEncoder.scala
index a92eef9947..fc95b77e61 100644
--- a/sdk/shared/src/main/scala/org/ergoplatform/sdk/DataJsonEncoder.scala
+++ b/sdk/shared/src/main/scala/org/ergoplatform/sdk/DataJsonEncoder.scala
@@ -5,22 +5,21 @@ import io.circe._
import io.circe.syntax._
import org.ergoplatform.ErgoBox
import org.ergoplatform.ErgoBox.{NonMandatoryRegisterId, Token}
-import org.ergoplatform.settings.ErgoAlgos
-import sigma.data.RType
+import sigma.data.{CAnyValue, RType}
import scorex.util._
-import sigmastate.Values.{Constant, EvaluatedValue}
-import sigmastate._
import sigmastate.lang.SigmaParser
import sigmastate.eval._
import sigma._
import debox.cfor
-import sigmastate.exceptions.SerializerException
+import scorex.util.encode.Base16
+
import scala.collection.compat.immutable.ArraySeq
import scala.collection.mutable
-import fastparse.{Parsed, parse}
-import sigmastate.serialization.SigmaSerializer
-import sigmastate.serialization.DataSerializer
-import sigmastate.serialization.ErgoTreeSerializer
+import sigma.ast._
+import sigma.eval.SigmaDsl
+import sigma.serialization.SerializerException
+import sigma.serialization.{DataSerializer, SigmaSerializer}
+import sigma.serialization.ErgoTreeSerializer
object DataJsonEncoder {
def encode[T <: SType](v: T#WrappedType, tpe: T): Json = {
@@ -33,7 +32,7 @@ object DataJsonEncoder {
}
private def encodeBytes: Encoder[Array[Byte]] = Encoder.instance((bytes: Array[Byte]) => {
- ErgoAlgos.encode(bytes).asJson
+ Base16.encode(bytes).asJson
})
def encodeAnyValue(v: AnyValue): Json = {
@@ -153,7 +152,7 @@ object DataJsonEncoder {
private def decodeBytes(json: Json): Array[Byte] = {
val jsonStr = json.as[String]
jsonStr match {
- case Right(jsonStr) => ErgoAlgos.decode(jsonStr).get
+ case Right(jsonStr) => Base16.decode(jsonStr).get
case Left(error) => throw new SerializerException(error.getMessage)
}
}
diff --git a/sdk/shared/src/main/scala/org/ergoplatform/sdk/ErgoId.scala b/sdk/shared/src/main/scala/org/ergoplatform/sdk/ErgoId.scala
index 7d56b05295..330400a824 100644
--- a/sdk/shared/src/main/scala/org/ergoplatform/sdk/ErgoId.scala
+++ b/sdk/shared/src/main/scala/org/ergoplatform/sdk/ErgoId.scala
@@ -2,8 +2,6 @@ package org.ergoplatform.sdk
import scorex.utils.Ints
-import java.util
-
object ErgoId {
/** Creates a new ErgoId decoding it from the given hex string. */
def create(base16Str: String) = new ErgoId(JavaHelpers.decodeStringToBytes(base16Str))
@@ -17,7 +15,7 @@ class ErgoId(val _idBytes: Array[Byte]) {
/** Extracts underlying byte array with id bytes. */
def getBytes = _idBytes
- override def hashCode =
+ override def hashCode: Int =
if (_idBytes != null && _idBytes.length >= 4) Ints.fromByteArray(_idBytes)
else java.util.Arrays.hashCode(_idBytes)
diff --git a/sdk/shared/src/main/scala/org/ergoplatform/sdk/ExtendedInputBox.scala b/sdk/shared/src/main/scala/org/ergoplatform/sdk/ExtendedInputBox.scala
index 05cd83daea..81b1ba0085 100644
--- a/sdk/shared/src/main/scala/org/ergoplatform/sdk/ExtendedInputBox.scala
+++ b/sdk/shared/src/main/scala/org/ergoplatform/sdk/ExtendedInputBox.scala
@@ -2,7 +2,7 @@ package org.ergoplatform.sdk
import org.ergoplatform.{ErgoBox, ErgoBoxCandidate, UnsignedInput}
import scorex.util.ModifierId
-import sigmastate.interpreter.ContextExtension
+import sigma.interpreter.ContextExtension
/** Input ErgoBox paired with context variables (aka ContextExtensions).
*
diff --git a/sdk/shared/src/main/scala/org/ergoplatform/sdk/Extensions.scala b/sdk/shared/src/main/scala/org/ergoplatform/sdk/Extensions.scala
index c8fb2e57f8..320aae5919 100644
--- a/sdk/shared/src/main/scala/org/ergoplatform/sdk/Extensions.scala
+++ b/sdk/shared/src/main/scala/org/ergoplatform/sdk/Extensions.scala
@@ -13,29 +13,6 @@ import scala.reflect.ClassTag
object Extensions {
- implicit class GenIterableOps[A, Source[X] <: GenIterable[X]](val xs: Source[A]) extends AnyVal {
-
- /** Apply m for each element of this collection, group by key and reduce each group
- * using r.
- * Note, the ordering of the resulting keys is deterministic and the keys appear in
- * the order they first produced by `map`.
- *
- * @returns one item for each group in a new collection of (K,V) pairs. */
- def mapReduce[K, V](map: A => (K, V))(reduce: (V, V) => V)
- (implicit cbf: BuildFrom[Source[A], (K, V), Source[(K, V)]]): Source[(K, V)] = {
- val result = scala.collection.mutable.LinkedHashMap.empty[K, V]
- xs.foreach { x =>
- val (key, value) = map(x)
- val reduced = if (result.contains(key)) reduce(result(key), value) else value
- result.update(key, reduced)
- }
-
- val b = cbf.newBuilder(xs)
- for ( kv <- result ) b += kv
- b.result()
- }
- }
-
implicit class CollOps[A](val coll: Coll[A]) extends AnyVal {
/** Partitions this $coll in two $colls according to a predicate.
@@ -205,7 +182,4 @@ object Extensions {
}
}
- implicit class DoubleOps(val i: Double) extends AnyVal {
- def erg: Long = (i * 1000000000L).toLong
- }
}
diff --git a/sdk/shared/src/main/scala/org/ergoplatform/sdk/InputBoxesValidator.scala b/sdk/shared/src/main/scala/org/ergoplatform/sdk/InputBoxesValidator.scala
index 7e3e24a8b7..98e4f45ac7 100644
--- a/sdk/shared/src/main/scala/org/ergoplatform/sdk/InputBoxesValidator.scala
+++ b/sdk/shared/src/main/scala/org/ergoplatform/sdk/InputBoxesValidator.scala
@@ -1,6 +1,6 @@
package org.ergoplatform.sdk
-import org.ergoplatform.SigmaConstants.MaxBoxSize
+import sigma.data.SigmaConstants.MaxBoxSize
import org.ergoplatform.sdk.wallet.Constants.MaxAssetsPerBox
import org.ergoplatform.sdk.wallet.{AssetUtils, TokensMap}
import org.ergoplatform.{ErgoBoxAssets, ErgoBoxAssetsHolder}
diff --git a/sdk/shared/src/main/scala/org/ergoplatform/sdk/JavaHelpers.scala b/sdk/shared/src/main/scala/org/ergoplatform/sdk/JavaHelpers.scala
index 75825defa3..14cdf7f6bb 100644
--- a/sdk/shared/src/main/scala/org/ergoplatform/sdk/JavaHelpers.scala
+++ b/sdk/shared/src/main/scala/org/ergoplatform/sdk/JavaHelpers.scala
@@ -9,20 +9,20 @@ import org.ergoplatform.sdk.wallet.secrets.{DerivationPath, ExtendedSecretKey}
import org.ergoplatform.sdk.wallet.{Constants, TokensMap}
import org.ergoplatform.settings.ErgoAlgos
import scorex.crypto.authds.ADKey
-import sigmastate.utils.Helpers._ // don't remove, required for Scala 2.11
import scorex.util.encode.Base16
import scorex.util.{ModifierId, bytesToId, idToBytes}
+import sigma.ast.{ErgoTree, SType}
+import sigma.ast.syntax.SValue
+import sigma.crypto.{CryptoFacade, EcPointType}
import sigma.data.ExactIntegral.LongIsExactIntegral
-import sigma.data.RType
+import sigma.data.{CSigmaDslBuilder, Digest32Coll, Iso, ProveDHTuple, ProveDlog, RType, SigmaBoolean, SigmaConstants}
+import sigma.serialization.GroupElementSerializer
import sigma.util.StringUtil.StringUtilExtensions
-import sigma.{AnyValue, AvlTree, Coll, Colls, GroupElement, Header}
-import sigmastate.SType
-import sigmastate.Values.{Constant, ErgoTree, EvaluatedValue, SValue, SigmaBoolean, SigmaPropConstant}
-import sigmastate.crypto.CryptoConstants.EcPointType
-import sigmastate.crypto.DLogProtocol.ProveDlog
-import sigmastate.crypto.{CryptoFacade, DiffieHellmanTupleProverInput, ProveDHTuple}
-import sigmastate.eval.{CostingSigmaDslBuilder, Digest32Coll, Evaluation}
-import sigmastate.serialization.{ErgoTreeSerializer, GroupElementSerializer, SigmaSerializer, ValueSerializer}
+import sigma.{AnyValue, AvlTree, Coll, Colls, Evaluation, GroupElement, Header}
+import sigma.ast.{Constant, EvaluatedValue, SigmaPropConstant}
+import sigmastate.crypto.DiffieHellmanTupleProverInput
+import sigma.serialization.{ErgoTreeSerializer, SigmaSerializer, ValueSerializer}
+import sigmastate.utils.Helpers._ // required for Scala 2.11
import java.lang.{Boolean => JBoolean, Byte => JByte, Integer => JInt, Long => JLong, Short => JShort, String => JString}
import java.math.BigInteger
@@ -30,45 +30,10 @@ import java.util
import java.util.{List => JList, Map => JMap}
import scala.collection.{JavaConverters, mutable}
-/** Type-class of isomorphisms between types.
- * Isomorphism between two types `A` and `B` essentially say that both types
- * represents the same information (entity) but in a different way.
- *
- * The information is not lost so that both are true:
- * 1) a == from(to(a))
- * 2) b == to(from(b))
- *
- * It is used to define type-full conversions:
- * - different conversions between Java and Scala data types.
- * - conversion between Ergo representations and generated API representations
- */
-abstract class Iso[A, B] {
- def to(a: A): B
- def from(b: B): A
- def andThen[C](iso: Iso[B,C]): Iso[A,C] = ComposeIso(iso, this)
- def inverse: Iso[B, A] = InverseIso(this)
-}
-final case class InverseIso[A,B](iso: Iso[A,B]) extends Iso[B,A] {
- override def to(a: B): A = iso.from(a)
- override def from(b: A): B = iso.to(b)
-}
-final case class ComposeIso[A, B, C](iso2: Iso[B, C], iso1: Iso[A, B]) extends Iso[A, C] {
- def from(c: C): A = iso1.from(iso2.from(c))
- def to(a: A): C = iso2.to(iso1.to(a))
-}
-
trait LowPriorityIsos {
}
-object Iso extends LowPriorityIsos {
- implicit def identityIso[A]: Iso[A, A] = new Iso[A, A] {
- override def to(a: A): A = a
-
- override def from(b: A): A = b
- }
-
- implicit def inverseIso[A,B](implicit iso: Iso[A,B]): Iso[B,A] = InverseIso[A,B](iso)
-
+object SdkIsos extends LowPriorityIsos {
implicit val jbyteToByte: Iso[JByte, Byte] = new Iso[JByte, Byte] {
override def to(b: JByte): Byte = b
override def from(a: Byte): JByte = a
@@ -295,14 +260,6 @@ object JavaHelpers {
ErgoAlgos.encode(ErgoAlgos.hash(s))
}
-
- def toSigmaBoolean(ergoTree: ErgoTree): SigmaBoolean = {
- val prop = ergoTree.toProposition(ergoTree.isConstantSegregation)
- prop match {
- case SigmaPropConstant(p) => SigmaDsl.toSigmaBoolean(p)
- }
- }
-
def toErgoTree(sigmaBoolean: SigmaBoolean): ErgoTree = ErgoTree.fromSigmaBoolean(sigmaBoolean)
def getStateDigest(tree: AvlTree): Array[Byte] = {
@@ -368,7 +325,7 @@ object JavaHelpers {
def BoxRType: RType[sigma.Box] = sigma.BoxRType
- def SigmaDsl: CostingSigmaDslBuilder = sigmastate.eval.SigmaDsl
+ def SigmaDsl: CSigmaDslBuilder = sigma.eval.SigmaDsl
def collFrom(arr: Array[Byte]): Coll[Byte] = {
Colls.fromArray(arr)
diff --git a/sdk/shared/src/main/scala/org/ergoplatform/sdk/JsonCodecs.scala b/sdk/shared/src/main/scala/org/ergoplatform/sdk/JsonCodecs.scala
index 878c936c80..ae14fd831a 100644
--- a/sdk/shared/src/main/scala/org/ergoplatform/sdk/JsonCodecs.scala
+++ b/sdk/shared/src/main/scala/org/ergoplatform/sdk/JsonCodecs.scala
@@ -1,38 +1,30 @@
package org.ergoplatform.sdk
-import java.math.BigInteger
import cats.syntax.either._
import io.circe._
import io.circe.syntax._
-import org.ergoplatform.ErgoBox.{BoxId, NonMandatoryRegisterId, Token, TokenId}
+import org.ergoplatform.ErgoBox.{NonMandatoryRegisterId, Token, TokenId}
+import org.ergoplatform._
import org.ergoplatform.settings.ErgoAlgos
-import org.ergoplatform.validation.{SigmaValidationSettings, SigmaValidationSettingsSerializer}
+import org.ergoplatform.validation.SigmaValidationSettingsSerializer
import scorex.crypto.authds.{ADDigest, ADKey}
import scorex.crypto.hash.Digest32
import scorex.util.ModifierId
-import sigmastate.Values.{EvaluatedValue, ErgoTree}
-import sigmastate.eval.Extensions._
-import sigmastate.eval.{WrapperOf, CPreHeader, _}
-import sigmastate.exceptions.SigmaException
-import sigmastate.interpreter.{ContextExtension, ProverResult}
-import sigmastate.{AvlTreeData, SType, AvlTreeFlags}
-import sigma.{Header, AnyValue, Colls, Coll, PreHeader}
-
-import scala.util.Try
-import sigmastate.utils.Helpers._ // required for Scala 2.11
-import org.ergoplatform.ErgoBox
-import sigmastate.serialization.ValueSerializer
-import org.ergoplatform.DataInput
-import org.ergoplatform.Input
-import org.ergoplatform.UnsignedInput
-import sigmastate.serialization.ErgoTreeSerializer
-import org.ergoplatform.ErgoLikeTransaction
-import org.ergoplatform.UnsignedErgoLikeTransaction
-import org.ergoplatform.ErgoLikeTransactionTemplate
-import org.ergoplatform.ErgoBoxCandidate
-import org.ergoplatform.ErgoLikeContext
+import sigma.Extensions.ArrayOps
+import sigma.ast.{ErgoTree, EvaluatedValue, SType}
+import sigma.data.{AvlTreeData, AvlTreeFlags, CBigInt, Digest32Coll, WrapperOf}
+import sigma.eval.Extensions.EvalIterableOps
+import sigma.eval.SigmaDsl
+import sigma.interpreter.{ContextExtension, ProverResult}
+import sigma.serialization.{ErgoTreeSerializer, ValueSerializer}
+import sigma.validation.SigmaValidationSettings
+import sigma.{AnyValue, Coll, Colls, Header, PreHeader, SigmaException}
+import sigmastate.eval.{CPreHeader, _}
+import sigmastate.utils.Helpers._ // required for Scala 2.11
+import java.math.BigInteger
import scala.collection.mutable
+import scala.util.Try
trait JsonCodecs {
diff --git a/sdk/shared/src/main/scala/org/ergoplatform/sdk/OutBoxBuilder.scala b/sdk/shared/src/main/scala/org/ergoplatform/sdk/OutBoxBuilder.scala
index 61a71fcfa2..1046767fbf 100644
--- a/sdk/shared/src/main/scala/org/ergoplatform/sdk/OutBoxBuilder.scala
+++ b/sdk/shared/src/main/scala/org/ergoplatform/sdk/OutBoxBuilder.scala
@@ -2,11 +2,11 @@ package org.ergoplatform.sdk
import org.ergoplatform.ErgoBox.TokenId
import org.ergoplatform.sdk.JavaHelpers.collRType
-import org.ergoplatform.{ErgoBox, ErgoBoxCandidate, SigmaConstants}
+import org.ergoplatform.{ErgoBox, ErgoBoxCandidate}
import sigma.Colls
-import sigma.data.RType
-import sigmastate.SType
-import sigmastate.Values.{Constant, ErgoTree, EvaluatedValue}
+import sigma.ast.{ErgoTree, SType}
+import sigma.data.{RType, SigmaConstants}
+import sigma.ast.{Constant, EvaluatedValue}
import scala.collection.mutable.ArrayBuffer
@@ -69,7 +69,7 @@ object OutBoxBuilder {
require(nRegs <= nonMandatoryRegisters.length,
s"Too many additional registers $nRegs. Max allowed ${nonMandatoryRegisters.length}")
implicit val TokenIdRType: RType[TokenId] = collRType(sigma.ByteType).asInstanceOf[RType[TokenId]]
- val ts = Colls.fromItems(tokens.map(Iso.isoErgoTokenToPair.to(_)): _*)
+ val ts = Colls.fromItems(tokens.map(SdkIsos.isoErgoTokenToPair.to(_)): _*)
val rs = registers.zipWithIndex.map { case (c, i) =>
val id = ErgoBox.nonMandatoryRegisters(i)
id -> c.asInstanceOf[EvaluatedValue[_ <: SType]]
diff --git a/sdk/shared/src/main/scala/org/ergoplatform/sdk/ReducingInterpreter.scala b/sdk/shared/src/main/scala/org/ergoplatform/sdk/ReducingInterpreter.scala
index 1e73c49640..229853a172 100644
--- a/sdk/shared/src/main/scala/org/ergoplatform/sdk/ReducingInterpreter.scala
+++ b/sdk/shared/src/main/scala/org/ergoplatform/sdk/ReducingInterpreter.scala
@@ -6,11 +6,11 @@ import org.ergoplatform.sdk.utils.ArithUtils
import org.ergoplatform.sdk.wallet.protocol.context.{BlockchainStateContext, TransactionContext}
import org.ergoplatform.validation.ValidationRules
import org.ergoplatform.{ErgoLikeContext, ErgoLikeInterpreter}
+import sigma.ast.ErgoTree
+import sigma.data.AvlTreeData
+import sigma.exceptions.CostLimitException
import sigma.util.Extensions.LongOps
-import sigmastate.AvlTreeData
-import sigmastate.Values.ErgoTree
-import sigmastate.eval.Evaluation.addCostChecked
-import sigmastate.exceptions.CostLimitException
+import sigmastate.eval.addCostChecked
import sigmastate.interpreter.Interpreter
import sigmastate.interpreter.Interpreter.ScriptEnv
@@ -21,7 +21,7 @@ import scala.collection.mutable
/** Interpreter that can reduce transactions with given chain parameters. */
class ReducingInterpreter(params: BlockchainParameters) extends ErgoLikeInterpreter {
override type CTX = ErgoLikeContext
- import org.ergoplatform.sdk.Iso._
+ import org.ergoplatform.sdk.SdkIsos._
/** Reduces the given ErgoTree in the given context to the sigma proposition.
*
@@ -31,7 +31,7 @@ class ReducingInterpreter(params: BlockchainParameters) extends ErgoLikeInterpre
* @return data object containing enough data to sign a transaction without Context.
*/
def reduce(env: ScriptEnv, ergoTree: ErgoTree, context: CTX): ReducedInputData = {
- val initCost = ergoTree.complexity + context.initCost
+ val initCost = context.initCost
val remainingLimit = context.costLimit - initCost
if (remainingLimit <= 0)
throw new CostLimitException(initCost,
diff --git a/sdk/shared/src/main/scala/org/ergoplatform/sdk/SecretString.scala b/sdk/shared/src/main/scala/org/ergoplatform/sdk/SecretString.scala
index 83ff2e0a10..99b576d870 100644
--- a/sdk/shared/src/main/scala/org/ergoplatform/sdk/SecretString.scala
+++ b/sdk/shared/src/main/scala/org/ergoplatform/sdk/SecretString.scala
@@ -2,7 +2,6 @@ package org.ergoplatform.sdk
import debox.cfor
-import java.util
/**
* Encapsulates secret array of characters (char[]) with proper equality.
diff --git a/sdk/shared/src/main/scala/org/ergoplatform/sdk/SigmaProver.scala b/sdk/shared/src/main/scala/org/ergoplatform/sdk/SigmaProver.scala
index aa281f5b10..6dc08fbfee 100644
--- a/sdk/shared/src/main/scala/org/ergoplatform/sdk/SigmaProver.scala
+++ b/sdk/shared/src/main/scala/org/ergoplatform/sdk/SigmaProver.scala
@@ -3,7 +3,8 @@ package org.ergoplatform.sdk
import org.ergoplatform.ErgoAddressEncoder.NetworkPrefix
import org.ergoplatform._
import org.ergoplatform.sdk.wallet.protocol.context.BlockchainStateContext
-import sigmastate.eval.{CostingSigmaDslBuilder, SigmaDsl}
+import sigma.data.CSigmaDslBuilder
+import sigma.eval.SigmaDsl
import sigmastate.interpreter.HintsBag
import sigmastate.utils.Helpers.TryOps
import sigma.{BigInt, SigmaProp}
@@ -27,7 +28,7 @@ class SigmaProver(_prover: AppkitProvingInterpreter, networkPrefix: NetworkPrefi
/** Returns the prover's secret key. */
def getSecretKey: BigInt =
- CostingSigmaDslBuilder.BigInt(_prover.secretKeys(0).privateInput.w)
+ CSigmaDslBuilder.BigInt(_prover.secretKeys(0).privateInput.w)
/** Returns a sequence of EIP-3 addresses associated with the prover's secret keys. */
def getEip3Addresses: Seq[P2PKAddress] = {
diff --git a/sdk/shared/src/main/scala/org/ergoplatform/sdk/Transactions.scala b/sdk/shared/src/main/scala/org/ergoplatform/sdk/Transactions.scala
index 8848e73c42..a3a4510653 100644
--- a/sdk/shared/src/main/scala/org/ergoplatform/sdk/Transactions.scala
+++ b/sdk/shared/src/main/scala/org/ergoplatform/sdk/Transactions.scala
@@ -3,9 +3,7 @@ package org.ergoplatform.sdk
import org.ergoplatform.sdk.JavaHelpers.StringExtensions
import org.ergoplatform.{ErgoBox, ErgoLikeTransaction, UnsignedErgoLikeTransaction}
import sigmastate.eval.Extensions.ArrayByteOps
-import sigmastate.serialization.SigmaSerializer
-
-import java.util
+import sigma.serialization.SigmaSerializer
/** Represents a transaction data chat can be reduced to [[ReducedTransaction]].
*
diff --git a/sdk/shared/src/main/scala/org/ergoplatform/sdk/UnsignedTransactionBuilder.scala b/sdk/shared/src/main/scala/org/ergoplatform/sdk/UnsignedTransactionBuilder.scala
index dab4a73efd..0f18b5e74b 100644
--- a/sdk/shared/src/main/scala/org/ergoplatform/sdk/UnsignedTransactionBuilder.scala
+++ b/sdk/shared/src/main/scala/org/ergoplatform/sdk/UnsignedTransactionBuilder.scala
@@ -7,11 +7,12 @@ import org.ergoplatform.sdk.BoxSelection.InputBoxesValidator
import org.ergoplatform.sdk.Extensions.HeaderOps
import org.ergoplatform.sdk.wallet.{AssetUtils, TokensMap}
import scorex.util.{ModifierId, bytesToId}
-import sigmastate.eval.Extensions.ArrayOps
+import sigma.Extensions.ArrayOps
import sigmastate.utils.Extensions.ModifierIdOps
import sigma.Coll
import sigma.Extensions.CollBytesOps
import sigma.PreHeader
+import sigma.data.Digest32CollRType
import scala.collection.mutable.ArrayBuffer
import scala.util.Try
@@ -87,7 +88,7 @@ class UnsignedTransactionBuilder(val ctx: BlockchainContext) {
val changeAddress = getDefined(_changeAddress, "Change address is not defined")
val inputBoxesSeq = boxesToSpend.map(eb => eb.box)
val requestedToBurn = _tokensToBurn.fold(IndexedSeq.empty[ErgoToken])(_.toIndexedSeq)
- val burnTokens = Iso.isoErgoTokenSeqToLinkedMap.to(requestedToBurn).toMap
+ val burnTokens = SdkIsos.isoErgoTokenSeqToLinkedMap.to(requestedToBurn).toMap
val rewardDelay = ctx.networkType match {
case NetworkType.Mainnet => BlockchainParameters.MinerRewardDelay_Mainnet
case NetworkType.Testnet => BlockchainParameters.MinerRewardDelay_Testnet
diff --git a/sdk/shared/src/main/scala/org/ergoplatform/sdk/utils/SerializationUtils.scala b/sdk/shared/src/main/scala/org/ergoplatform/sdk/utils/SerializationUtils.scala
index 1530e1876a..4291a750f4 100644
--- a/sdk/shared/src/main/scala/org/ergoplatform/sdk/utils/SerializationUtils.scala
+++ b/sdk/shared/src/main/scala/org/ergoplatform/sdk/utils/SerializationUtils.scala
@@ -1,7 +1,6 @@
package org.ergoplatform.sdk.utils
-import sigmastate.utils.{SigmaByteReader, SigmaByteWriter}
-
+import sigma.serialization.{SigmaByteReader, SigmaByteWriter}
import java.nio.charset.StandardCharsets
object SerializationUtils {
diff --git a/sdk/shared/src/main/scala/org/ergoplatform/sdk/utils/Zero.scala b/sdk/shared/src/main/scala/org/ergoplatform/sdk/utils/Zero.scala
index 6cc7e6718c..78dfe2dc94 100644
--- a/sdk/shared/src/main/scala/org/ergoplatform/sdk/utils/Zero.scala
+++ b/sdk/shared/src/main/scala/org/ergoplatform/sdk/utils/Zero.scala
@@ -1,17 +1,16 @@
package org.ergoplatform.sdk.utils
import org.ergoplatform.ErgoBox
-import sigma.data.{CollType, FuncType, OptionType, PairType, RType, TupleType}
+import sigma.data.{AvlTreeData, AvlTreeFlags, CAvlTree, CBigInt, CGroupElement, CSigmaProp, CollType, FuncType, OptionType, PairType, RType, TrivialProp, TupleType}
import sigma.data.RType._
import scorex.crypto.authds.avltree.batch.BatchAVLProver
import scorex.crypto.hash.{Blake2b256, Digest32}
import scorex.util.ModifierId
-import sigmastate.Values.ErgoTree
-import sigmastate.crypto.CryptoConstants
import sigmastate.eval._
-import sigmastate.{AvlTreeData, AvlTreeFlags, TrivialProp}
import sigma._
-
+import sigma.ast.ErgoTree
+import ErgoTree.HeaderType
+import sigma.crypto.CryptoConstants
import java.math.BigInteger
import scala.language.implicitConversions
@@ -62,7 +61,7 @@ object Zero extends ZeroLowPriority {
new ErgoBox(
LongIsZero.zero,
new ErgoTree(
- ByteIsZero.zero,
+ HeaderType @@ ByteIsZero.zero,
IndexedSeq.empty,
Right(sigmaPropIsZero.zero)
),
diff --git a/sdk/shared/src/main/scala/org/ergoplatform/sdk/wallet/secrets/DerivationPath.scala b/sdk/shared/src/main/scala/org/ergoplatform/sdk/wallet/secrets/DerivationPath.scala
index 601a45e537..ac2143694e 100644
--- a/sdk/shared/src/main/scala/org/ergoplatform/sdk/wallet/secrets/DerivationPath.scala
+++ b/sdk/shared/src/main/scala/org/ergoplatform/sdk/wallet/secrets/DerivationPath.scala
@@ -1,10 +1,7 @@
package org.ergoplatform.sdk.wallet.secrets
import org.ergoplatform.sdk.wallet.Constants
-import scorex.util.serialization.{Reader, Writer}
-import sigmastate.serialization.SigmaSerializer
-import sigmastate.utils.{SigmaByteReader, SigmaByteWriter}
-
+import sigma.serialization.{SigmaByteReader, SigmaByteWriter, SigmaSerializer}
import scala.util.{Failure, Success, Try}
/**
diff --git a/sdk/shared/src/main/scala/org/ergoplatform/sdk/wallet/secrets/ExtendedPublicKey.scala b/sdk/shared/src/main/scala/org/ergoplatform/sdk/wallet/secrets/ExtendedPublicKey.scala
index 2ad287972e..43488974b9 100644
--- a/sdk/shared/src/main/scala/org/ergoplatform/sdk/wallet/secrets/ExtendedPublicKey.scala
+++ b/sdk/shared/src/main/scala/org/ergoplatform/sdk/wallet/secrets/ExtendedPublicKey.scala
@@ -1,12 +1,9 @@
package org.ergoplatform.sdk.wallet.secrets
-import sigmastate.crypto.DLogProtocol.{DLogProverInput, ProveDlog}
-import sigmastate.crypto.CryptoConstants
-import sigmastate.crypto.CryptoFacade
-import sigmastate.crypto.BigIntegers
-import sigmastate.serialization.SigmaSerializer
-import sigmastate.utils.{SigmaByteReader, SigmaByteWriter}
-
+import sigma.crypto.{BigIntegers, CryptoConstants, CryptoFacade}
+import sigma.data.ProveDlog
+import sigmastate.crypto.DLogProtocol.DLogProverInput
+import sigma.serialization.{SigmaByteReader, SigmaByteWriter, SigmaSerializer}
import scala.annotation.tailrec
/**
diff --git a/sdk/shared/src/main/scala/org/ergoplatform/sdk/wallet/secrets/ExtendedSecretKey.scala b/sdk/shared/src/main/scala/org/ergoplatform/sdk/wallet/secrets/ExtendedSecretKey.scala
index 4b87e31e13..5493929ac5 100644
--- a/sdk/shared/src/main/scala/org/ergoplatform/sdk/wallet/secrets/ExtendedSecretKey.scala
+++ b/sdk/shared/src/main/scala/org/ergoplatform/sdk/wallet/secrets/ExtendedSecretKey.scala
@@ -1,13 +1,10 @@
package org.ergoplatform.sdk.wallet.secrets
+import sigma.crypto.{BigIntegers, CryptoConstants, CryptoFacade}
+import sigma.data.ProveDlog
import java.math.BigInteger
-import sigmastate.crypto.BigIntegers
-import sigmastate.crypto.DLogProtocol
import sigmastate.crypto.DLogProtocol.DLogProverInput
-import sigmastate.crypto.CryptoConstants
-import sigmastate.crypto.CryptoFacade
-import sigmastate.serialization.SigmaSerializer
-import sigmastate.utils.{SigmaByteReader, SigmaByteWriter}
+import sigma.serialization.{SigmaByteReader, SigmaByteWriter, SigmaSerializer}
/**
* Secret, its chain code and path in key tree.
@@ -23,7 +20,7 @@ final class ExtendedSecretKey(/*private[secrets]*/ val keyBytes: Array[Byte],
override def privateInput: DLogProverInput = DLogProverInput(BigIntegers.fromUnsignedByteArray(keyBytes))
- def publicImage: DLogProtocol.ProveDlog = privateInput.publicImage
+ def publicImage: ProveDlog = privateInput.publicImage
def child(idx: Int): ExtendedSecretKey = ExtendedSecretKey.deriveChildSecretKey(this, idx)
diff --git a/sdk/shared/src/test/scala/org/ergoplatform/sdk/ContractTemplateSpecification.scala b/sdk/shared/src/test/scala/org/ergoplatform/sdk/ContractTemplateSpecification.scala
index 268012ac3c..dace012c9a 100644
--- a/sdk/shared/src/test/scala/org/ergoplatform/sdk/ContractTemplateSpecification.scala
+++ b/sdk/shared/src/test/scala/org/ergoplatform/sdk/ContractTemplateSpecification.scala
@@ -3,12 +3,15 @@ package org.ergoplatform.sdk
import org.ergoplatform.sdk.generators.ObjectGenerators
import org.scalatest.compatible.Assertion
import org.scalatestplus.scalacheck.ScalaCheckPropertyChecks
-import sigmastate.Values._
+import sigma.ast._
import sigmastate._
-import sigmastate.eval.CBigInt
import sigmastate.helpers.NegativeTesting
-import sigmastate.serialization.{SerializationSpecification, SigmaSerializer}
-import sigma.ContractsTestkit
+import sigma.serialization.{SerializationSpecification, SigmaSerializer}
+import sigma.{ContractsTestkit, VersionContext}
+import sigma.ast.syntax.SigmaPropValue
+import sigma.ast.{SByte, SInt, SType}
+import sigma.data.CBigInt
+import ErgoTree.setConstantSegregation
import java.math.BigInteger
@@ -66,15 +69,15 @@ class ContractTemplateSpecification extends SerializationSpecification
property("unequal length of constTypes and constValues") {
assertExceptionThrown(
createContractTemplate(
- IndexedSeq(SType.typeByte, SType.typeByte, SType.typeByte).asInstanceOf[IndexedSeq[SType]],
+ IndexedSeq(SByte, SByte, SByte).asInstanceOf[IndexedSeq[SType]],
Some(IndexedSeq(Some(10.toByte), Some(20.toByte)).asInstanceOf[IndexedSeq[Option[SType#WrappedType]]]),
IndexedSeq(
createParameter("p1", 0),
createParameter("p2", 1),
createParameter("p3", 2)),
- EQ(Plus(ConstantPlaceholder(0, SType.typeByte),
- ConstantPlaceholder(1, SType.typeByte)),
- ConstantPlaceholder(2, SType.typeByte)).toSigmaProp
+ EQ(Plus(ConstantPlaceholder(0, SByte),
+ ConstantPlaceholder(1, SByte)),
+ ConstantPlaceholder(2, SByte)).toSigmaProp
),
exceptionLike[IllegalArgumentException]("constValues must be empty or of same length as constTypes. Got 2, expected 3")
)
@@ -83,16 +86,16 @@ class ContractTemplateSpecification extends SerializationSpecification
property("more parameters than constants") {
assertExceptionThrown(
createContractTemplate(
- IndexedSeq(SType.typeByte, SType.typeByte, SType.typeByte).asInstanceOf[IndexedSeq[SType]],
+ IndexedSeq(SByte, SByte, SByte).asInstanceOf[IndexedSeq[SType]],
Some(IndexedSeq(Some(10.toByte), Some(20.toByte), Some(30.toByte)).asInstanceOf[IndexedSeq[Option[SType#WrappedType]]]),
IndexedSeq(
createParameter("p1", 0),
createParameter("p2", 1),
createParameter("p3", 2),
createParameter("p4", 3)),
- EQ(Plus(ConstantPlaceholder(0, SType.typeByte),
- ConstantPlaceholder(1, SType.typeByte)),
- ConstantPlaceholder(2, SType.typeByte)).toSigmaProp
+ EQ(Plus(ConstantPlaceholder(0, SByte),
+ ConstantPlaceholder(1, SByte)),
+ ConstantPlaceholder(2, SByte)).toSigmaProp
),
exceptionLike[IllegalArgumentException]("number of parameters must be <= number of constants")
)
@@ -101,15 +104,15 @@ class ContractTemplateSpecification extends SerializationSpecification
property("invalid parameter constantIndex") {
assertExceptionThrown(
createContractTemplate(
- IndexedSeq(SType.typeByte, SType.typeByte, SType.typeByte).asInstanceOf[IndexedSeq[SType]],
+ IndexedSeq(SByte, SByte, SByte).asInstanceOf[IndexedSeq[SType]],
Some(IndexedSeq(Some(10.toByte), Some(20.toByte), Some(30.toByte)).asInstanceOf[IndexedSeq[Option[SType#WrappedType]]]),
IndexedSeq(
createParameter("p1", 0),
createParameter("p2", 1),
createParameter("p3", 100)),
- EQ(Plus(ConstantPlaceholder(0, SType.typeByte),
- ConstantPlaceholder(1, SType.typeByte)),
- ConstantPlaceholder(2, SType.typeByte)).toSigmaProp
+ EQ(Plus(ConstantPlaceholder(0, SByte),
+ ConstantPlaceholder(1, SByte)),
+ ConstantPlaceholder(2, SByte)).toSigmaProp
),
exceptionLike[IllegalArgumentException]("parameter constantIndex must be in range [0, 3)")
)
@@ -118,15 +121,15 @@ class ContractTemplateSpecification extends SerializationSpecification
property("duplicate parameter constantIndex") {
assertExceptionThrown(
createContractTemplate(
- IndexedSeq(SType.typeByte, SType.typeByte, SType.typeByte).asInstanceOf[IndexedSeq[SType]],
+ IndexedSeq(SByte, SByte, SByte).asInstanceOf[IndexedSeq[SType]],
Some(IndexedSeq(Some(10.toByte), Some(20.toByte), Some(30.toByte)).asInstanceOf[IndexedSeq[Option[SType#WrappedType]]]),
IndexedSeq(
createParameter("p1", 0),
createParameter("p2", 1),
createParameter("p3", 1)),
- EQ(Plus(ConstantPlaceholder(0, SType.typeByte),
- ConstantPlaceholder(1, SType.typeByte)),
- ConstantPlaceholder(2, SType.typeByte)).toSigmaProp
+ EQ(Plus(ConstantPlaceholder(0, SByte),
+ ConstantPlaceholder(1, SByte)),
+ ConstantPlaceholder(2, SByte)).toSigmaProp
),
exceptionLike[IllegalArgumentException]("multiple parameters point to the same constantIndex")
)
@@ -135,15 +138,15 @@ class ContractTemplateSpecification extends SerializationSpecification
property("duplicate parameter names") {
assertExceptionThrown(
createContractTemplate(
- IndexedSeq(SType.typeByte, SType.typeByte, SType.typeByte).asInstanceOf[IndexedSeq[SType]],
+ IndexedSeq(SByte, SByte, SByte).asInstanceOf[IndexedSeq[SType]],
Some(IndexedSeq(Some(10.toByte), Some(20.toByte), Some(30.toByte)).asInstanceOf[IndexedSeq[Option[SType#WrappedType]]]),
IndexedSeq(
createParameter("duplicate_name", 0),
createParameter("p2", 1),
createParameter("duplicate_name", 2)),
- EQ(Plus(ConstantPlaceholder(0, SType.typeByte),
- ConstantPlaceholder(1, SType.typeByte)),
- ConstantPlaceholder(2, SType.typeByte)).toSigmaProp
+ EQ(Plus(ConstantPlaceholder(0, SByte),
+ ConstantPlaceholder(1, SByte)),
+ ConstantPlaceholder(2, SByte)).toSigmaProp
),
exceptionLike[IllegalArgumentException]("parameter names must be unique. Found duplicate parameters with name duplicate_name")
)
@@ -152,14 +155,14 @@ class ContractTemplateSpecification extends SerializationSpecification
property("constantIndex without default value and parameter") {
assertExceptionThrown(
createContractTemplate(
- IndexedSeq(SType.typeByte, SType.typeByte, SType.typeByte).asInstanceOf[IndexedSeq[SType]],
+ IndexedSeq(SByte, SByte, SByte).asInstanceOf[IndexedSeq[SType]],
Some(IndexedSeq(None, Some(20.toByte), Some(30.toByte)).asInstanceOf[IndexedSeq[Option[SType#WrappedType]]]),
IndexedSeq(
createParameter("p2", 1),
createParameter("p3", 2)),
- EQ(Plus(ConstantPlaceholder(0, SType.typeByte),
- ConstantPlaceholder(1, SType.typeByte)),
- ConstantPlaceholder(2, SType.typeByte)).toSigmaProp
+ EQ(Plus(ConstantPlaceholder(0, SByte),
+ ConstantPlaceholder(1, SByte)),
+ ConstantPlaceholder(2, SByte)).toSigmaProp
),
exceptionLike[IllegalArgumentException]("constantIndex 0 does not have a default value and absent from parameter as well")
)
@@ -171,23 +174,23 @@ class ContractTemplateSpecification extends SerializationSpecification
createParameter("p2", 1),
createParameter("p3", 2))
val expressionTrees = IndexedSeq(
- EQ(Plus(ConstantPlaceholder(0, SType.typeByte),
- ConstantPlaceholder(1, SType.typeByte)),
- ConstantPlaceholder(2, SType.typeByte)).toSigmaProp,
- EQ(Plus(ConstantPlaceholder(0, SType.typeInt),
- ConstantPlaceholder(1, SType.typeInt)),
- ConstantPlaceholder(2, SType.typeInt)).toSigmaProp,
+ EQ(Plus(ConstantPlaceholder(0, SByte),
+ ConstantPlaceholder(1, SByte)),
+ ConstantPlaceholder(2, SByte)).toSigmaProp,
+ EQ(Plus(ConstantPlaceholder(0, SInt),
+ ConstantPlaceholder(1, SInt)),
+ ConstantPlaceholder(2, SInt)).toSigmaProp,
EQ(Plus(CBigInt(BigInteger.valueOf(10L)), BigIntConstant(20L)), BigIntConstant(30L)).toSigmaProp
)
val templates = Seq(
createContractTemplate(
- IndexedSeq(SType.typeByte, SType.typeByte, SType.typeByte).asInstanceOf[IndexedSeq[SType]],
+ IndexedSeq(SByte, SByte, SByte).asInstanceOf[IndexedSeq[SType]],
Some(IndexedSeq(Some(10.toByte), Some(20.toByte), Some(30.toByte)).asInstanceOf[IndexedSeq[Option[SType#WrappedType]]]),
parameters,
expressionTrees(0)
),
createContractTemplate(
- IndexedSeq(SType.typeInt, SType.typeInt, SType.typeInt).asInstanceOf[IndexedSeq[SType]],
+ IndexedSeq(SInt, SInt, SInt).asInstanceOf[IndexedSeq[SType]],
Some(IndexedSeq(Some(10), None, Some(30)).asInstanceOf[IndexedSeq[Option[SType#WrappedType]]]),
parameters,
expressionTrees(1)
@@ -204,13 +207,10 @@ class ContractTemplateSpecification extends SerializationSpecification
Map("p1" -> IntConstant(10), "p2" -> IntConstant(20)),
Map.empty[String, Constant[SType]]
)
- var expectedErgoTreeVersion = (ErgoTree.ConstantSegregationHeader | ergoTreeVersionInTests).toByte
- if (ergoTreeVersionInTests > 0) {
- expectedErgoTreeVersion = (expectedErgoTreeVersion | ErgoTree.SizeFlag).toByte
- }
+ val expectedErgoTreeHeader = setConstantSegregation(ergoTreeHeaderInTests)
val expectedErgoTree = Seq(
ErgoTree(
- expectedErgoTreeVersion,
+ expectedErgoTreeHeader,
IndexedSeq(
ByteConstant(10.toByte),
ByteConstant(40.toByte),
@@ -219,7 +219,7 @@ class ContractTemplateSpecification extends SerializationSpecification
expressionTrees(0)
),
ErgoTree(
- expectedErgoTreeVersion,
+ expectedErgoTreeHeader,
IndexedSeq(
IntConstant(10),
IntConstant(20),
@@ -228,15 +228,17 @@ class ContractTemplateSpecification extends SerializationSpecification
expressionTrees(1)
),
ErgoTree(
- expectedErgoTreeVersion,
+ expectedErgoTreeHeader,
Constant.EmptySeq,
expressionTrees(2)
)
)
- templates.indices.foreach(i =>
- templates(i).applyTemplate(Some(ergoTreeVersionInTests), templateValues(i)) shouldEqual expectedErgoTree(i)
- )
+ templates.indices.foreach { i =>
+ val template = templates(i)
+ val applied = template.applyTemplate(Some(ergoTreeVersionInTests), templateValues(i))
+ applied shouldEqual expectedErgoTree(i)
+ }
}
property("applyTemplate num(parameters) < num(constants)") {
@@ -244,23 +246,20 @@ class ContractTemplateSpecification extends SerializationSpecification
createParameter("p1", 0),
createParameter("p2", 2))
val expressionTree =
- EQ(Plus(ConstantPlaceholder(0, SType.typeInt),
- ConstantPlaceholder(1, SType.typeInt)),
- ConstantPlaceholder(2, SType.typeInt)).toSigmaProp
+ EQ(Plus(ConstantPlaceholder(0, SInt),
+ ConstantPlaceholder(1, SInt)),
+ ConstantPlaceholder(2, SInt)).toSigmaProp
val template = createContractTemplate(
- IndexedSeq(SType.typeInt, SType.typeInt, SType.typeInt).asInstanceOf[IndexedSeq[SType]],
+ IndexedSeq(SInt, SInt, SInt).asInstanceOf[IndexedSeq[SType]],
Some(IndexedSeq(None, Some(20), None).asInstanceOf[IndexedSeq[Option[SType#WrappedType]]]),
parameters,
expressionTree
)
val templateValues = Map("p1" -> IntConstant(10), "p2" -> IntConstant(30))
- var expectedErgoTreeVersion = (ErgoTree.ConstantSegregationHeader | ergoTreeVersionInTests).toByte
- if (ergoTreeVersionInTests > 0) {
- expectedErgoTreeVersion = (expectedErgoTreeVersion | ErgoTree.SizeFlag).toByte
- }
+ val expectedErgoTreeHeader = setConstantSegregation(ergoTreeHeaderInTests)
val expectedErgoTree = ErgoTree(
- expectedErgoTreeVersion,
+ expectedErgoTreeHeader,
IndexedSeq(
IntConstant(10),
IntConstant(20),
diff --git a/sdk/shared/src/test/scala/org/ergoplatform/sdk/DataJsonEncoderSpecification.scala b/sdk/shared/src/test/scala/org/ergoplatform/sdk/DataJsonEncoderSpecification.scala
index 89330bc759..c3f7b43af4 100644
--- a/sdk/shared/src/test/scala/org/ergoplatform/sdk/DataJsonEncoderSpecification.scala
+++ b/sdk/shared/src/test/scala/org/ergoplatform/sdk/DataJsonEncoderSpecification.scala
@@ -4,17 +4,17 @@ package org.ergoplatform.sdk
import java.math.BigInteger
import org.scalacheck.Arbitrary._
import org.scalacheck.Gen
-import sigma.data.RType
-import sigmastate.SCollection.SByteArray
-import sigmastate.SType.AnyOps
-import sigmastate.Values.SigmaBoolean
-import sigmastate._
-import sigmastate.eval.Extensions._
-import sigmastate.eval.{Evaluation, _}
-import sigmastate.crypto.CryptoConstants.EcPointType
-import sigmastate.exceptions.SerializerException
-import sigma.{AvlTree, Box, Colls}
-import sigmastate.serialization.SerializationSpecification
+import sigma.data.{CAnyValue, RType, SigmaBoolean, TupleColl}
+import sigma.ast._
+import sigma.ast.SCollection.SByteArray
+import sigma.ast.SType.AnyOps
+import sigma.crypto.EcPointType
+import sigma.serialization.SerializerException
+import sigma.util.Extensions.{BigIntegerOps, EcpOps, SigmaBooleanOps}
+import sigma.Extensions.ArrayOps
+import sigma.eval.SigmaDsl
+import sigma.{AvlTree, Box, Colls, Evaluation}
+import sigma.serialization.SerializationSpecification
import scala.annotation.nowarn
import scala.reflect.ClassTag
@@ -51,8 +51,9 @@ class DataJsonEncoderSpecification extends SerializationSpecification {
def testTuples[T <: SType](tpe: T) = {
implicit val wWrapped: Gen[T#WrappedType] = wrappedTypeGen(tpe)
- implicit val tag : ClassTag[T#WrappedType] = tpe.classTag[T#WrappedType]
- implicit val tAny : RType[Any] = sigma.AnyType
+ val tT = Evaluation.stypeToRType(tpe)
+ @nowarn implicit val tag : ClassTag[T#WrappedType] = tT.classTag
+ @nowarn implicit val tAny : RType[Any] = sigma.AnyType
forAll { in: (T#WrappedType, T#WrappedType) =>
val (x,y) = (in._1, in._2)
roundtrip[SType]((x, y).asWrappedType, STuple(tpe, tpe))
@@ -63,8 +64,8 @@ class DataJsonEncoderSpecification extends SerializationSpecification {
@nowarn def testAnyValue[T <: SType](tpe: T) = {
implicit val wWrapped = wrappedTypeGen(tpe)
- implicit val tag = tpe.classTag[T#WrappedType]
implicit val tT = Evaluation.stypeToRType(tpe)
+ implicit val tag = tT.classTag
implicit val tAny = sigma.AnyType
forAll { in: T#WrappedType =>
val x = CAnyValue(in)
@@ -91,9 +92,9 @@ class DataJsonEncoderSpecification extends SerializationSpecification {
forAll { x: Boolean => roundtrip[SBoolean.type](x, SBoolean) }
forAll { x: Long => roundtrip[SLong.type](x, SLong) }
forAll { x: String => roundtrip[SString.type](x, SString) }
- forAll { x: BigInteger => roundtrip[SBigInt.type](x, SBigInt) }
- forAll { x: EcPointType => roundtrip[SGroupElement.type](x, SGroupElement) }
- forAll { x: SigmaBoolean => roundtrip[SSigmaProp.type](x, SSigmaProp) }
+ forAll { x: BigInteger => roundtrip[SBigInt.type](x.toBigInt, SBigInt) }
+ forAll { x: EcPointType => roundtrip[SGroupElement.type](x.toGroupElement, SGroupElement) }
+ forAll { x: SigmaBoolean => roundtrip[SSigmaProp.type](x.toSigmaProp, SSigmaProp) }
forAll { x: AvlTree => roundtrip[SAvlTree.type](x, SAvlTree) }
forAll { x: Array[Byte] => roundtrip[SByteArray](x.toColl, SByteArray) }
forAll { x: Box => roundtrip[SBox.type](x, SBox) }
@@ -183,8 +184,9 @@ class DataJsonEncoderSpecification extends SerializationSpecification {
def testEncodeError[T <: SType](tpe: T) = {
implicit val wWrapped = wrappedTypeGen(tpe)
- implicit val tag = tpe.classTag[T#WrappedType]
- implicit val tAny = sigma.AnyType
+ val tT = Evaluation.stypeToRType(tpe)
+ @nowarn implicit val tag = tT.classTag
+ @nowarn implicit val tAny = sigma.AnyType
forAll { x: T#WrappedType =>
an[SerializerException] should be thrownBy {
DataJsonEncoder.encode(TupleColl(x, x, x).asWrappedType, STuple(tpe, tpe, tpe))
diff --git a/sdk/shared/src/test/scala/org/ergoplatform/sdk/ExtensionsSpec.scala b/sdk/shared/src/test/scala/org/ergoplatform/sdk/ExtensionsSpec.scala
index f250b9fce5..1f3c8d9064 100644
--- a/sdk/shared/src/test/scala/org/ergoplatform/sdk/ExtensionsSpec.scala
+++ b/sdk/shared/src/test/scala/org/ergoplatform/sdk/ExtensionsSpec.scala
@@ -4,20 +4,16 @@ import org.scalatest.matchers.should.Matchers
import org.scalatest.propspec.AnyPropSpec
import org.scalatestplus.scalacheck.ScalaCheckPropertyChecks
import sigma.{Coll, CollGens}
-import org.ergoplatform.sdk.Extensions.{CollBuilderOps, CollOps, GenIterableOps, PairCollOps}
-import sigma.data.RType
-import sigmastate.eval.CostingSigmaDslBuilder
+import org.ergoplatform.sdk.Extensions.{CollBuilderOps, CollOps, PairCollOps}
+import sigma.Extensions.ArrayOps
+import sigma.data.{CSigmaDslBuilder, RType}
class ExtensionsSpec extends AnyPropSpec with ScalaCheckPropertyChecks with Matchers with CollGens {
def Coll[T](items: T*)(implicit cT: RType[T]) =
- CostingSigmaDslBuilder.Colls.fromItems(items: _*)
+ CSigmaDslBuilder.Colls.fromItems(items: _*)
val items: Iterable[(Int, String)] = Array((1, "a"), (2, "b"), (1, "c"))
- property("Traversable.mapReduce") {
- val res = items.mapReduce(p => (p._1, p._2))((v1, v2) => v1 + v2)
- assertResult(List((1, "ac"), (2, "b")))(res)
- }
property("Coll.partition") {
forAll(collGen) { col: Coll[Int] =>
@@ -29,14 +25,14 @@ class ExtensionsSpec extends AnyPropSpec with ScalaCheckPropertyChecks with Matc
}
property("Coll.mapReduce") {
- def m(x: Int) = (math.abs(x) % 10, x)
+ def m(x: Int): (Int, Int) = (math.abs(x) % 10, x)
forAll(collGen) { col =>
val res = col.mapReduce(m, plusF)
val (ks, vs) = builder.unzip(res)
vs.toArray.sum shouldBe col.toArray.sum
ks.length <= 10 shouldBe true
- res.toArray shouldBe col.toArray.toIterable.mapReduce(m)(plus).toArray
+ res.toArray shouldBe col.toArray.toColl.mapReduce[Int, Int](m, plusF).toArray
}
}
diff --git a/sdk/shared/src/test/scala/org/ergoplatform/sdk/JsonSerializationSpec.scala b/sdk/shared/src/test/scala/org/ergoplatform/sdk/JsonSerializationSpec.scala
index 34c966df0a..0753b1ffc7 100644
--- a/sdk/shared/src/test/scala/org/ergoplatform/sdk/JsonSerializationSpec.scala
+++ b/sdk/shared/src/test/scala/org/ergoplatform/sdk/JsonSerializationSpec.scala
@@ -5,23 +5,18 @@ import io.circe._
import io.circe.syntax._
import org.ergoplatform.ErgoBox._
import org.ergoplatform.validation.ValidationRules
+import org.ergoplatform._
import org.scalacheck.Arbitrary.arbitrary
import scorex.crypto.authds.{ADDigest, ADKey}
import scorex.util.ModifierId
import scorex.util.encode.Base16
-import sigmastate.{AvlTreeData, SType}
-import sigmastate.Values.{ByteArrayConstant, ByteConstant, ErgoTree, EvaluatedValue, IntConstant, LongArrayConstant, SigmaPropConstant}
-import sigmastate.crypto.CryptoConstants
-import sigmastate.crypto.DLogProtocol.ProveDlog
-import sigmastate.eval.Digest32Coll
-import sigmastate.interpreter.{ContextExtension, ProverResult}
-import sigmastate.serialization.SerializationSpecification
-import sigmastate.utils.Helpers.DecoderResultOps // required for Scala 2.11 (extension method toTry)
-import sigma.Coll
-import sigma.{Header, PreHeader}
-import org.ergoplatform.{DataInput, ErgoBox, ErgoBoxCandidate, ErgoLikeContext, ErgoLikeTransaction, ErgoLikeTransactionTemplate, Input, UnsignedErgoLikeTransaction, UnsignedInput}
-
-import scala.collection.mutable
+import sigma.data.{AvlTreeData, Digest32Coll, ProveDlog}
+import sigma.{Coll, Header, PreHeader}
+import sigma.ast._
+import sigma.crypto.CryptoConstants
+import sigma.interpreter.{ContextExtension, ProverResult}
+import sigma.serialization.SerializationSpecification
+import sigmastate.utils.Helpers.DecoderResultOps // required for Scala 2.11
class JsonSerializationSpec extends SerializationSpecification with JsonCodecs {
@@ -138,7 +133,7 @@ class JsonSerializationSpec extends SerializationSpecification with JsonCodecs {
val minerPkHex = "0326df75ea615c18acc6bb4b517ac82795872f388d5d180aac90eaa84de750b942"
val minerPk = Base16.decode(minerPkHex).map { point =>
ProveDlog(
- CryptoConstants.dlogGroup.ctx.decodePoint(point).asInstanceOf[CryptoConstants.EcPointType]
+ CryptoConstants.dlogGroup.ctx.decodePoint(point)
)
}.get
val regs = scala.collection.Map(
diff --git a/sdk/shared/src/test/scala/org/ergoplatform/sdk/generators/ObjectGenerators.scala b/sdk/shared/src/test/scala/org/ergoplatform/sdk/generators/ObjectGenerators.scala
index 3908760e59..1c6d2efc5d 100644
--- a/sdk/shared/src/test/scala/org/ergoplatform/sdk/generators/ObjectGenerators.scala
+++ b/sdk/shared/src/test/scala/org/ergoplatform/sdk/generators/ObjectGenerators.scala
@@ -3,9 +3,9 @@ package org.ergoplatform.sdk.generators
import org.ergoplatform.sdk.{ContractTemplate, Parameter}
import org.ergoplatform.validation.ValidationSpecification
import org.scalacheck.Gen
-import sigmastate.Values.{ErgoTree, SigmaPropValue}
-import sigmastate.serialization.generators.{ConcreteCollectionGenerators, TypeGenerators, ObjectGenerators => InterpreterObjectGenerators}
-import sigmastate.{SType, TestsBase}
+import sigma.ast.{ErgoTree, SType}
+import sigmastate.TestsBase
+import sigma.serialization.generators.{ConcreteCollectionGenerators, TypeGenerators, ObjectGenerators => InterpreterObjectGenerators}
import scala.util.Random
diff --git a/sdk/shared/src/test/scala/org/ergoplatform/sdk/wallet/utils/Generators.scala b/sdk/shared/src/test/scala/org/ergoplatform/sdk/wallet/utils/Generators.scala
index 80164f5f23..56b2ea02d1 100644
--- a/sdk/shared/src/test/scala/org/ergoplatform/sdk/wallet/utils/Generators.scala
+++ b/sdk/shared/src/test/scala/org/ergoplatform/sdk/wallet/utils/Generators.scala
@@ -2,22 +2,20 @@ package org.ergoplatform.sdk.wallet.utils
import org.ergoplatform.ErgoBox.{BoxId, NonMandatoryRegisterId, Token}
import org.ergoplatform.sdk.wallet.Constants
-import org.ergoplatform.sdk.wallet.secrets.ExtendedPublicKey
-import org.ergoplatform.sdk.wallet.secrets.{DerivationPath, ExtendedSecretKey, Index, SecretKey}
+import org.ergoplatform.sdk.wallet.secrets._
import org.ergoplatform.sdk.wallet.settings.EncryptionSettings
+import org.ergoplatform._
import org.scalacheck.Arbitrary.arbByte
import org.scalacheck.{Arbitrary, Gen}
import scorex.crypto.authds.ADKey
-import sigmastate.Values.{ByteArrayConstant, CollectionConstant, ErgoTree, EvaluatedValue, FalseLeaf, TrueLeaf}
-import sigmastate.crypto.DLogProtocol.ProveDlog
-import sigmastate.{SByte, SType}
import scorex.util._
-import org.ergoplatform.{ErgoBox, ErgoBoxCandidate, ErgoTreePredef, UnsignedErgoLikeTransaction, UnsignedInput}
-import sigmastate.eval.Extensions._
-import scorex.util.{ModifierId, bytesToId}
-import sigmastate.eval._
+import sigma.Extensions.ArrayOps
+import sigma.ast._
+import sigma.ast.syntax.CollectionConstant
+import sigma.crypto.CryptoFacade
+import sigma.data.{Digest32Coll, ProveDlog}
+import sigma.eval.Extensions.EvalIterableOps
import sigmastate.helpers.TestingHelpers._
-import sigmastate.crypto.CryptoFacade
trait Generators {
@@ -100,7 +98,7 @@ trait Generators {
Gen.choose(minValue, CoinsTotalTest / 1000)
}
- def ergoBoxGen(propGen: Gen[ErgoTree] = Gen.const(TrueLeaf.toSigmaProp),
+ def ergoBoxGen(propGen: Gen[ErgoTree] = Gen.const(ErgoTree.fromProposition(TrueLeaf.toSigmaProp)),
tokensGen: Gen[Seq[Token]] = additionalTokensGen,
valueGenOpt: Option[Gen[Long]] = None,
heightGen: Gen[Int] = heightGen): Gen[ErgoBox] = for {
@@ -144,10 +142,8 @@ trait Generators {
}
}
-
-
def unsignedTxGen(secret: SecretKey): Gen[(IndexedSeq[ErgoBox], UnsignedErgoLikeTransaction)] = {
- val dlog: Gen[ErgoTree] = Gen.const(secret.privateInput.publicImage.asInstanceOf[ProveDlog].toSigmaProp)
+ val dlog: Gen[ErgoTree] = Gen.const(ErgoTree.fromSigmaBoolean(secret.privateInput.publicImage.asInstanceOf[ProveDlog]))
for {
ins <- Gen.listOfN(2, ergoBoxGen(dlog))
diff --git a/sigma-js/README.md b/sigma-js/README.md
index 1531088cbd..ff867e1cb6 100644
--- a/sigma-js/README.md
+++ b/sigma-js/README.md
@@ -1,5 +1,4 @@
[![CI](https://github.com/ScorexFoundation/sigmastate-interpreter/actions/workflows/ci.yml/badge.svg)](https://github.com/ScorexFoundation/sigmastate-interpreter/actions/workflows/ci.yml)
-[![codecov](https://codecov.io/gh/ScorexFoundation/sigmastate-interpreter/branch/develop/graph/badge.svg?token=HNu2ZEOoV6)](https://codecov.io/gh/ScorexFoundation/sigmastate-interpreter)
# ErgoScript compiler and ErgoTree interpreter
@@ -21,29 +20,91 @@ Run following command to add Sigma.JS as a project dependency:
npm install sigmastate-js
```
-# Examples
+## Package organization
+
+All classes of this package are separated into several modules (which can also be thought
+as layers). Each module contains a subset of all the class exported to JavaScript. You can
+decide which modules to import in your application depending on which classes from this
+package you want to use.
+Each subsequent module contains all the classes from the previous modules and some new
+classes thus forming a layering of modules.
+
+See TypeScript [definitions](sigmastate-js.d.ts) for the list of all exported classes,
+methods and documentation.
+
+NOTE, you only need to import only one of the modules, the one which contains all the
+classes you need. This will allow optimizing the size of the final bundle.
+
+The modules are compiled from Scala classes, which are exported to JavaScript (here is an
+[example](../core/js/src/main/scala/sigma/js/Type.scala)).
+The Scala declarations correspond to the TypeScript definitions.
+Each exported type have two parts: the first part is a Scala class, the second part is a
+companion object. In Scala the companion object is used to declare static methods and has
+the same name as the corresponding class. In TypeScript the companion object is exported
+with `$` suffix, thus if X is the JS class, then X$ is the JS object, which corresponds to X.
+
+## The list of modules and their exported classes
+- [sigma-core module](../core/js) - contains core classes of Sigma.js library
+ - [Type](../core/js/src/main/scala/sigma/js/Type.scala)
+ - [Value](../core/js/src/main/scala/sigma/js/Value.scala)
+ - [GroupElement](../core/js/src/main/scala/sigma/js/GroupElement.scala)
+ - [SigmaProp](../core/js/src/main/scala/sigma/js/SigmaProp.scala)
+ - [AvlTree](../core/js/src/main/scala/sigma/js/AvlTree.scala)
+
+- [sigma-data module](../data/js) - contains classes for working with ErgoTree, addresses and all related serializers
+ - all classes from sigma-core module
+ - [ErgoTree](../data/js/src/main/scala/sigma/ast/js/ErgoTree.scala)
+ - [Address](../data/js/src/main/scala/org/ergoplatform/js/Address.scala)
+ - [Expr](../data/js/src/main/scala/sigma/ast/js/Expr.scala)
+
+- [sigma-interpreter module](../interpreter/js) - contains classes for proving sigma proposition and their verification
+ - all classes from sigma-data module
+ - [ProverHints](../interpreter/js/src/main/scala/sigma/interpreter/js/ProverHints.scala)
+ - [ProverSecret](../interpreter/js/src/main/scala/sigma/interpreter/js/ProverSecret.scala)
+ - [SigmaPropProver](../interpreter/js/src/main/scala/sigma/interpreter/js/SigmaPropProver.scala)
+ - [SigmaPropVerifier](../interpreter/js/src/main/scala/sigma/interpreter/js/SigmaPropVerifier.scala)
+
+- [sigma-sdk module](../sdk/js) - contains classes for reducing and signing transactions
+ - all classes from sigma-interpreter module
+ - [BlockchainParameters](../sdk/js/src/main/scala/org/ergoplatform/sdk/js/BlockchainParameters.scala)
+ - [BlockchainStateContext](../sdk/js/src/main/scala/org/ergoplatform/sdk/js/BlockchainStateContext.scala)
+ - [ContractTemplate](../sdk/js/src/main/scala/org/ergoplatform/sdk/js/ContractTemplate.scala)
+ - [Header](../sdk/js/src/main/scala/org/ergoplatform/sdk/js/Header.scala)
+ - [PreHeader](../sdk/js/src/main/scala/org/ergoplatform/sdk/js/PreHeader.scala)
+ - [ProverBuilder](../sdk/js/src/main/scala/org/ergoplatform/sdk/js/ProverBuilder.scala)
+ - [ReducedTransaction](../sdk/js/src/main/scala/org/ergoplatform/sdk/js/ReducedTransaction.scala)
+ - [SigmaProver](../sdk/js/src/main/scala/org/ergoplatform/sdk/js/SigmaProver.scala)
+
+- [sigma-compiler module](../sc/js) - contains classes for working with ErgoScript compiler
+ - [SigmaCompiler](../sc/js/src/main/scala/sigmastate/lang/js/SigmaCompiler.scala)
+
+## Examples
### How to create Sigma type descriptors
-Import `TypeObj` module, then use:
+Import `Type$` module, then use its fields to access pre-defined descriptors of simple
+types (e.g. `Type$.Int`).
-- fields to create simple types (e.g. `TypeObj.Int`)
-- method `TypeObj.pairType` (e.g. `TypeObj.pairType(TypeObj.Int, TypeObj.Long)`)
-- method `TypeObj.collType` (e.g. `TypeObj.collType(TypeObj.Int)`)
+Use factory methods like `Type$.pairType` to create more complex type descriptors. For
+example,`Type$.pairType(Type$.Int, Type$.Long)` will create a descriptor of a pair of Int
+and Long types `(Int, Long)`.
-See examples in tests [Type.spec.js](https://github.com/ScorexFoundation/sigmastate-interpreter/blob/933acd7a3753725c8b41994c2126a20279b6809b/sigma-js/tests/js/Type.spec.js)
+See also examples in tests [Type.spec.js](tests/js/Type.spec.js)
### How to create Sigma values
-Import `ValueObj` module, then use its methods.
-See examples in tests [Value.spec.js](https://github.com/ScorexFoundation/sigmastate-interpreter/blob/933acd7a3753725c8b41994c2126a20279b6809b/sigma-js/tests/js/Value.spec.js)
+Import `Value$` module, then use its factory methods.
+See examples in tests [Value.spec.js](tests/js/Value.spec.js)
### How to work with ErgoTree
-Import `ErgoTreeObj` module, and `ErgoTree` class then use its methods.
-See examples in tests [ErgoTree.spec.js](https://github.com/ScorexFoundation/sigmastate-interpreter/blob/79df4ca171a77233947d835042ce5c82ee520469/sigma-js/tests/js/ErgoTree.spec.js)
+Import `ErgoTree$` module, and `ErgoTree` class then use its methods.
+See examples in tests [ErgoTree.spec.js](tests/js/ErgoTree.spec.js)
### Compile ErgoScript to ErgoTree
-Import `SigmaCompilerObj` module and `SigmaCompiler` class, then use its methods.
-See compiler tests in [SigmaCompiler.spec.js](https://github.com/ScorexFoundation/sigmastate-interpreter/blob/933acd7a3753725c8b41994c2126a20279b6809b/sigma-js/tests/js/SigmaCompiler.spec.js)
+Import `SigmaCompiler$` module and `SigmaCompiler` class, then use its methods.
+See compiler tests in [SigmaCompiler.spec.js](tests/js/SigmaCompiler.spec.js)
+
+### Other examples
+See tests in [tests/js](tests/js) folder.
diff --git a/sigma-js/package.json b/sigma-js/package.json
index 79f15e803d..77ff920585 100644
--- a/sigma-js/package.json
+++ b/sigma-js/package.json
@@ -1,6 +1,6 @@
{
"name": "sigmastate-js",
- "version": "0.3.0",
+ "version": "0.4.0",
"description": "Sigma.js library",
"files": [
"dist/",
diff --git a/sigma-js/sigmastate-js.d.ts b/sigma-js/sigmastate-js.d.ts
index 775f585570..b70ca39258 100644
--- a/sigma-js/sigmastate-js.d.ts
+++ b/sigma-js/sigmastate-js.d.ts
@@ -1,304 +1,664 @@
declare module "sigmastate-js/main" {
- import {
- Amount,
- Box,
- EIP12UnsignedInput,
- NonMandatoryRegisters, SignedTransaction, TokenAmount,
- UnsignedTransaction
- } from "@fleet-sdk/common";
-
- type SigmaCompilerNamedConstantsMap = { [key: string]: Value };
- type HexString = string;
- type ByteArray = { u: Int8Array };
-
- export declare class ErgoTree {
- toHex(): HexString;
- bytes(): ByteArray;
- header(): number;
- version(): number;
- isConstantSegregation(): boolean;
- hasSize(): boolean;
- constants(): Value[];
- template(): ByteArray;
- templateHex(): HexString;
- toString(): string;
- }
-
- export declare class ErgoTreeObj {
- static fromHex(value: HexString): ErgoTree;
- }
-
- export declare class GroupElement {
- toPointHex(): HexString;
- }
-
- export declare class GroupElementObj {
- static fromPointHex(value: HexString): GroupElement;
- }
-
- export declare class SigmaProp {
- }
-
- export declare class SigmaPropObj {
- static fromPointHex(value: HexString): SigmaProp;
- }
-
- export declare class AvlTree {
- digest: HexString;
- insertAllowed: Boolean;
- updateAllowed: Boolean;
- removeAllowed: Boolean;
- keyLength: number;
- valueLengthOpt: number | undefined;
- }
-
- export declare class PreHeader {
- /** Block version, to be increased on every soft and hardfork. */
- version: number;
- /** Hex of id of parent block */
- parentId: HexString;
- /** Block timestamp (in milliseconds since beginning of Unix Epoch) */
- timestamp: bigint;
- /** Current difficulty in a compressed view.
- * NOTE: actually it is unsigned integer */
- nBits: bigint;
- /** Block height */
- height: number;
- /** Miner public key (hex of EC Point). Should be used to collect block rewards. */
- minerPk: GroupElement;
- /** Hex of miner votes bytes for changing system parameters. */
- votes: HexString;
- }
-
- export declare class Header {
- /** Hex representation of ModifierId of this Header */
- id: HexString;
- /** Block version, to be increased on every soft and hardfork. */
- version: number;
- /** Hex representation of ModifierId of the parent block */
- parentId: HexString;
- /** Hex hash of ADProofs for transactions in a block */
- ADProofsRoot: HexString;
- /** AvlTree of a state after block application */
- stateRoot: AvlTree;
- /** Hex of root hash (for a Merkle tree) of transactions in a block. */
- transactionsRoot: HexString;
- /** Block timestamp (in milliseconds since beginning of Unix Epoch) */
- timestamp: bigint;
- /** Current difficulty in a compressed view.
- * NOTE: actually it is unsigned Int */
- nBits: bigint;
- /** Block height */
- height: number;
- /** Hex of root hash of extension section */
- extensionRoot: HexString;
-
- /** Miner public key (hex of EC Point). Should be used to collect block rewards.
- * Part of Autolykos solution.
- */
- minerPk: GroupElement;
-
- /** One-time public key (hex of EC Point). Prevents revealing of miners secret. */
- powOnetimePk: GroupElement;
-
- /** Hex of nonce bytes */
- powNonce: HexString;
-
- /** Distance between pseudo-random number, corresponding to nonce `powNonce` and a secret,
- * corresponding to `minerPk`. The lower `powDistance` is, the harder it was to find this solution. */
- powDistance: bigint;
-
- /** Miner votes for changing system parameters. */
- votes: HexString;
- }
-
- export declare class BlockchainParameters {
- storageFeeFactor: number;
- minValuePerByte: number;
- maxBlockSize: number;
- tokenAccessCost: number;
- inputCost: number;
- dataInputCost: number;
- outputCost: number;
- maxBlockCost: number;
- softForkStartingHeight: number | undefined;
- softForkVotesCollected: number | undefined;
- blockVersion: number;
- }
-
- export declare class BlockchainStateContext {
- sigmaLastHeaders: Header[];
- previousStateDigest: HexString;
- sigmaPreHeader: PreHeader;
- }
-
- export declare class Type {
- name: string;
- toString(): string;
- }
-
- export declare class TypeObj {
- static Byte: Type;
- static Short: Type;
- static Int: Type;
- static Long: Type;
- static BigInt: Type;
- static GroupElement: Type;
- static SigmaProp: Type;
- static Box: Type;
- static AvlTree: Type;
- static Context: Type;
- static Header: Type;
- static PreHeader: Type;
- static SigmaDslBuilder: Type;
- static pairType(left: Type, right: Type): Type;
- static collType(elemType: Type): Type;
- }
-
- export declare class Value {
- data: T;
- tpe: Type;
- toHex(): HexString;
- }
-
- export declare class ValueObj {
- static ofByte(value: number): Value;
- static ofShort(value: number): Value;
- static ofInt(value: number): Value;
- static ofLong(value: bigint): Value;
- static ofBigInt(value: bigint): Value;
- static ofGroupElement(pointHex: string): Value;
- static ofSigmaProp(pointHex: string): Value;
- static pairOf(left: Value, right: Value): Value<[R, L]>;
- static collOf(items: T[], elemType: Type): Value;
- static fromHex(hex: HexString): Value;
- }
-
- export declare class SigmaCompiler {
- compile(
- namedConstants: SigmaCompilerNamedConstantsMap,
- segregateConstants: boolean,
- additionalHeaderFlags: number,
- ergoScript: string
- ): ErgoTree;
- }
-
- export declare class SigmaCompilerObj {
- static forMainnet(): SigmaCompiler;
- static forTestnet(): SigmaCompiler;
- }
-
- /** Represents results for transaction reduction by {@link SigmaProver}. */
- export declare class ReducedTransaction {
- /** Serialized bytes of this transaction in hex format. */
- toHex(): HexString;
- }
-
- export declare class ReducedTransactionObj {
- /** Creates a {@link ReducedTransaction} from serialized bytes in hex format. */
- fromHex(hex: HexString): ReducedTransaction;
- }
-
- /** Represents a prover for signing Ergo transactions and messages.
- *
- * Equivalent of [[org.ergoplatform.sdk.SigmaProver]] available from JS.
- */
- export declare class SigmaProver {
- /** Returns the Pay-to-Public-Key (P2PK) address associated with the prover's public key.
- * The returned address corresponds to the master secret derived from the mnemonic
- * phrase configured in the [[ProverBuilder]].
+ import {
+ Amount,
+ Box,
+ EIP12UnsignedInput,
+ NonMandatoryRegisters, SignedTransaction, TokenAmount,
+ UnsignedTransaction
+ } from "@fleet-sdk/common";
+
+ type SigmaCompilerNamedConstantsMap = { [key: string]: Value };
+ type HexString = string;
+ type ByteArray = { u: Int8Array };
+
+ export declare class Address {
+ /** Serialize this address to bytes. */
+ addressBytes(): ByteArray;
+
+ /** Address type code used to differentiate between pay-to-public-key, pay-to-script,
+ * pay-to-script-hash addresses.
+ *
+ * @see [[P2PKAddress]], [[P2SAddress]], [[P2SHAddress]]
+ */
+ addressTypePrefix(): number;
+
+ /** @return true if this address from Ergo mainnet. */
+ isMainnet(): boolean;
+
+ /** @return true if this address has Pay-To-Public-Key type. */
+ isP2PK(): boolean;
+
+ /** @return underlying {@link P2PKAddress}.
+ * @throws IllegalArgumentException if this instance is not P2PK address
+ */
+ asP2PK(): P2PKAddress;
+
+ /** @return true if this address has Pay-To-Script type. */
+ isP2S(): boolean;
+
+ /** @return underlying {@link P2PKAddress}.
+ * @throws IllegalArgumentException if this instance is not P2PK address
+ */
+ asP2S(): P2SAddress;
+
+ /** @return true if this address has Pay-To-Script-Hash type. */
+ isP2SH(): boolean;
+
+ /** @return underlying {@link P2SHAddress}.
+ * @throws IllegalArgumentException if this instance is not P2SH address
+ */
+ asP2SH(): P2SHAddress;
+
+ /** Extracts a {@link SigmaProp} from this address of the underlying ErgoTree if of
+ * specific form.
+ * @see ErgoTree.toSigmaBooleanOpt()
+ */
+ toSigmaPropOpt(): SigmaProp | undefined;
+
+ /** ErgoTree which corresponds to the address (depending on the address type).
+ *
+ * @see P2PKAddress, P2SAddress, P2SHAddress
+ */
+ toErgoTree(): ErgoTree;
+
+ /** @return this addresses ErgoTree's proposition bytes. Use this to store this address
+ * on Box registers.
+ */
+ toPropositionBytes(): ByteArray;
+
+ /** Converts the given {@link Address} to Base58 string. */
+ toString(): string;
+ }
+
+ export declare class Address$ {
+ /** Creates JS wrapper over given [[ErgoAddress]]. */
+ static fromErgoAddress(ergoAddress: any /*org.ergoplatform.ErgoAddress*/): Address;
+
+ /** Deserializes an ErgoTree instance from an address string.
+ *
+ * @param base58String a Base58 string representing the serialized ErgoTree
+ */
+ static fromString(base58String: string): Address;
+
+ /** Creates an `Address` instance from an `ErgoTree` and a network prefix.
+ *
+ * @param ergoTree The `ErgoTree` instance to be converted into an `Address`.
+ * @param networkPrefix The network prefix indicating the network for which the address is valid.
+ * @return An `Address` instance corresponding to the given `ErgoTree` and network prefix.
+ */
+ static fromErgoTree(ergoTree: ErgoTree, networkPrefix: number): Address;
+
+ /**
+ * Creates an `Address` from a `SigmaProp` and a network prefix.
+ *
+ * @param sigmaProp The `SigmaProp` to be converted into an `Address`.
+ * @param networkPrefix The network prefix indicating the network for which the address is valid.
+ * @return An `Address` instance corresponding to the given `SigmaProp` and network prefix.
+ */
+ static fromSigmaProp(sigmaProp: SigmaProp, networkPrefix: number): Address;
+
+ /** Creates address from given ergovalue containing an ErgoTree proposition bytes.
+ * Use this to convert a box register containing an ErgoTree into its address.
+ *
+ * @param networkPrefix mainnet or testnet network
+ * @param propositionBytes ErgoTree proposition bytes
+ */
+ static fromPropositionBytes(networkPrefix: number, propositionBytes: ByteArray): Address
+ }
+
+ /** Implementation of pay-to-public-key {@link Address}. */
+ export declare class P2PKAddress extends Address {
+ /** Converts this address to the underlying ProveDlog sigma proposition wrapped in {@link SigmaProp}. */
+ toSigmaProp(): SigmaProp;
+
+ /** Extract the underlying {@link GroupElement} of this address. */
+ getPublicKeyGE(): GroupElement;
+ }
+
+ /** Implementation of pay-to-script {@link Address}. */
+ export declare class P2SAddress extends Address {
+ }
+
+ /** Implementation of pay-to-script-hash {@link Address}. */
+ export declare class P2SHAddress extends Address {
+ }
+
+ export declare class ErgoTree {
+ toHex(): HexString;
+
+ bytes(): ByteArray;
+
+ header(): number;
+
+ version(): number;
+
+ isConstantSegregation(): boolean;
+
+ hasSize(): boolean;
+
+ constants(): Value[];
+
+ template(): ByteArray;
+
+ templateHex(): HexString;
+
+ toString(): string;
+ }
+
+ export declare class ErgoTree$ {
+ static fromHex(value: HexString): ErgoTree;
+ }
+
+ export declare class GroupElement {
+ toPointHex(): HexString;
+ }
+
+ export declare class GroupElement$ {
+ static fromPointHex(value: HexString): GroupElement;
+ }
+
+ export declare class SigmaProp {
+ }
+
+ export declare class SigmaProp$ {
+ static fromPointHex(value: HexString): SigmaProp;
+ }
+
+ export declare class AvlTree {
+ digest: HexString;
+ insertAllowed: Boolean;
+ updateAllowed: Boolean;
+ removeAllowed: Boolean;
+ keyLength: number;
+ valueLengthOpt: number | undefined;
+ }
+
+ export declare class PreHeader {
+ /** Block version, to be increased on every soft and hardfork. */
+ version: number;
+ /** Hex of id of parent block */
+ parentId: HexString;
+ /** Block timestamp (in milliseconds since beginning of Unix Epoch) */
+ timestamp: bigint;
+ /** Current difficulty in a compressed view.
+ * NOTE: actually it is unsigned integer */
+ nBits: bigint;
+ /** Block height */
+ height: number;
+ /** Miner public key (hex of EC Point). Should be used to collect block rewards. */
+ minerPk: GroupElement;
+ /** Hex of miner votes bytes for changing system parameters. */
+ votes: HexString;
+ }
+
+ export declare class Header {
+ /** Hex representation of ModifierId of this Header */
+ id: HexString;
+ /** Block version, to be increased on every soft and hardfork. */
+ version: number;
+ /** Hex representation of ModifierId of the parent block */
+ parentId: HexString;
+ /** Hex hash of ADProofs for transactions in a block */
+ ADProofsRoot: HexString;
+ /** AvlTree of a state after block application */
+ stateRoot: AvlTree;
+ /** Hex of root hash (for a Merkle tree) of transactions in a block. */
+ transactionsRoot: HexString;
+ /** Block timestamp (in milliseconds since beginning of Unix Epoch) */
+ timestamp: bigint;
+ /** Current difficulty in a compressed view.
+ * NOTE: actually it is unsigned Int */
+ nBits: bigint;
+ /** Block height */
+ height: number;
+ /** Hex of root hash of extension section */
+ extensionRoot: HexString;
+
+ /** Miner public key (hex of EC Point). Should be used to collect block rewards.
+ * Part of Autolykos solution.
+ */
+ minerPk: GroupElement;
+
+ /** One-time public key (hex of EC Point). Prevents revealing of miners secret. */
+ powOnetimePk: GroupElement;
+
+ /** Hex of nonce bytes */
+ powNonce: HexString;
+
+ /** Distance between pseudo-random number, corresponding to nonce `powNonce` and a secret,
+ * corresponding to `minerPk`. The lower `powDistance` is, the harder it was to find this solution. */
+ powDistance: bigint;
+
+ /** Miner votes for changing system parameters. */
+ votes: HexString;
+ }
+
+ export declare class BlockchainParameters {
+ storageFeeFactor: number;
+ minValuePerByte: number;
+ maxBlockSize: number;
+ tokenAccessCost: number;
+ inputCost: number;
+ dataInputCost: number;
+ outputCost: number;
+ maxBlockCost: number;
+ softForkStartingHeight: number | undefined;
+ softForkVotesCollected: number | undefined;
+ blockVersion: number;
+ }
+
+ export declare class BlockchainStateContext {
+ sigmaLastHeaders: Header[];
+ previousStateDigest: HexString;
+ sigmaPreHeader: PreHeader;
+ }
+
+ export declare class Type {
+ name: string;
+
+ toString(): string;
+ }
+
+ export declare class Type$ {
+ static Byte: Type;
+ static Short: Type;
+ static Int: Type;
+ static Long: Type;
+ static BigInt: Type;
+ static GroupElement: Type;
+ static SigmaProp: Type;
+ static Box: Type;
+ static AvlTree: Type;
+ static Context: Type;
+ static Header: Type;
+ static PreHeader: Type;
+ static SigmaDslBuilder: Type;
+
+ static pairType(left: Type, right: Type): Type;
+
+ static collType(elemType: Type): Type;
+ }
+
+ export declare class Value {
+ data: T;
+ tpe: Type;
+
+ toHex(): HexString;
+ }
+
+ export declare class Value$ {
+ static ofByte(value: number): Value;
+
+ static ofShort(value: number): Value;
+
+ static ofInt(value: number): Value;
+
+ static ofLong(value: bigint): Value;
+
+ static ofBigInt(value: bigint): Value;
+
+ static ofGroupElement(pointHex: string): Value;
+
+ static ofSigmaProp(pointHex: string): Value;
+
+ static pairOf(left: Value, right: Value): Value<[R, L]>;
+
+ static collOf(items: T[], elemType: Type): Value;
+
+ static fromHex(hex: HexString): Value;
+ }
+
+ export declare class SigmaCompiler {
+ compile(
+ namedConstants: SigmaCompilerNamedConstantsMap,
+ segregateConstants: boolean,
+ additionalHeaderFlags: number,
+ ergoScript: string
+ ): ErgoTree;
+ }
+
+ export declare class SigmaCompiler$ {
+ static forMainnet(): SigmaCompiler;
+
+ static forTestnet(): SigmaCompiler;
+ }
+
+ /** Represents results for transaction reduction by {@link SigmaProver}. */
+ export declare class ReducedTransaction {
+ /** Serialized bytes of this transaction in hex format. */
+ toHex(): HexString;
+ }
+
+ export declare class ReducedTransaction$ {
+ /** Creates a {@link ReducedTransaction} from serialized bytes in hex format. */
+ fromHex(hex: HexString): ReducedTransaction;
+ }
+
+ /** Represents hints used by [[SigmaPropProver]] to perform operations as part of
+ * multi-signature scheme. See [EIP-11](https://github.com/ergoplatform/eips/pull/8).
*/
- getP2PKAddress(): HexString;
-
- /** Returns the prover's secret key. */
- getSecretKey(): bigint;
-
- /** Returns an array of EIP-3 addresses associated with the prover's secret keys. */
- getEip3Addresses(): HexString[];
-
- /** Reduces the transaction to the reduced form, which is ready to be signed.
- * @param stateCtx blockchain state context
- * @param unsignedTx unsigned transaction to be reduced (created by Fleet builders)
- * @param boxesToSpend boxes to be spent by the transaction
- * @param dataInputs data inputs to be used by the transaction
- * @param tokensToBurn tokens to be burned by the transaction
- * @param baseCost base cost of the transaction
- * @return reduced transaction
- */
- reduce(
- stateCtx: BlockchainStateContext,
- unsignedTx: UnsignedTransaction,
- boxesToSpend: EIP12UnsignedInput[],
- dataInputs: Box[],
- tokensToBurn: TokenAmount[],
- baseCost: number): ReducedTransaction;
-
- /** Signs the reduced transaction.
- * @param reducedTx reduced transaction to be signed
- * @return signed transaction containting all the required proofs (signatures)
- */
- signReduced(reducedTx: ReducedTransaction): SignedTransaction;
- }
-
- /** Equivalent of [[sdk.ProverBuilder]] available from JS.
- *
- * @param parameters Blockchain parameters re-adjustable via miners voting and
- * voting-related data. All of them are included into extension
- * section of a first block of a voting epoch.
- * @param network Network prefix to use for addresses.
- */
- export declare class ProverBuilder {
- /** Configure this builder to use the given seed when building a new prover.
+ export declare class ProverHints {
+
+ }
+
+ export declare class ProverHints$ {
+ /** Empty bag of hints. Immutable value can be reused where necessary. */
+ empty(): ProverHints
+ }
+
+ /** Represents one secret (aka SigmaProtocolPrivateInput) used by [[SigmaPropProver]]. */
+ export declare class ProverSecret {
+ /** Public key generated from the secret.
+ * Represents proof of knowledge sigma proposition.
+ */
+ publicKey(): SigmaProp
+
+ /** Secret random number stored in this instance. */
+ secret(): bigint
+ }
+
+ export declare class ProverSecret$ {
+ /** Creates a new [[ProverSecret]] instance for the given secret of descrete logarithm
+ * sigma protocol.
+ * @param w secret exponent value
+ */
+ dlog(w: bigint): ProverSecret
+
+ /** Creates a new [[ProverSecret]] instance for the given secret of Diffie Hellman tuple
+ * sigma protocol.
+ * @param w secret exponent value used to compute `u = g^w` and `v = h^w`, where `g` and `h` are generators
+ * @param dhtProp a [[SigmaProp]] representing public key of Diffie Hellman tuple sigma protocol, should be created using `w`
+ */
+ dht(w: bigint, dhtProp: SigmaProp): ProverSecret
+ }
+
+ /** Prover which can sign messages (generate proofs) for arbitrary sigma propositions
+ * represented by [[SigmaProp]] values.
*
- * @param mnemonicPhrase secret seed phrase to be used in prover for generating proofs.
- * @param mnemonicPass password to protect secret seed phrase.
- */
- withMnemonic(mnemonicPhrase: HexString, mnemonicPass: HexString): ProverBuilder;
- /** Configure this builder to derive the new EIP-3 secret key with the given index.
- * The derivation uses master key derived from the mnemonic configured using
- * [[ErgoProverBuilder.withMnemonic]].
+ * See [EIP-11](https://github.com/ergoplatform/eips/pull/8) for details of multi-signature scheme.
*
- * @param index last index in the EIP-3 derivation path.
+ * @see SigmaPropVerifier
*/
- withEip3Secret(index: number): ProverBuilder;
-
- /** Configures this builder to use group elements (g, h, u, v) and secret x for a
- * ProveDHTuple statement when building a new prover.
- *
- * ProveDHTuple is a statement consisting of 4 group elements (g, h, u, v) and
- * requires the prover to prove knowledge of secret integer x such that.
+ export declare class SigmaPropProver {
+ /**
+ * A method which is generating commitments for all the public keys provided.
+ * This is used as part of multi-signature scheme.
+ *
+ * Currently only keys in form of ProveDlog and ProveDiffieHellman are supported, not more complex subtrees.
+ *
+ * @param sigmaTree - crypto-tree which is being signed
+ * @param generateFor - public keys for which commitments should be generated
+ * @return generated commitments in a form of prover hints
+ * - private, containing secret randomness
+ * - public, containing only commitments
+ */
+ generateCommitmentsFor(
+ sigmaTree: SigmaProp,
+ generateFor: SigmaProp[]): ProverHints
+
+ /**
+ * A method which is extracting partial proofs of secret knowledge for particular secrets with their
+ * respective public images given. Useful for distributed signature applications.
+ *
+ * See DistributedSigSpecification for examples of usage.
+ *
+ * @param sigmaTree - public key (in form of a sigma-tree)
+ * @param proof - signature for the key
+ * @param realSecretsToExtract - public keys of secrets with real proofs
+ * @param simulatedSecretsToExtract - public keys of secrets with simulated proofs
+ * @return - bag of OtherSecretProven and OtherCommitment hints
+ */
+ hintsForMultisig(
+ sigmaTree: SigmaProp,
+ proof: Int8Array,
+ realSecretsToExtract: SigmaProp[],
+ simulatedSecretsToExtract: SigmaProp[]): ProverHints
+
+ /**
+ * Generate commitments for given crypto-tree (sigma-tree) for prover's secrets.
+ */
+ generateCommitments(sigmaTree: SigmaProp): ProverHints
+
+ /** Sign arbitrary message under a key representing a statement provable via a sigma-protocol.
+ *
+ * @param sigmaProp - public key
+ * @param message - message to sign
+ * @param hintsBag - additional hints for a signer (useful for distributed signing)
+ * @return - signature or error
+ */
+ signMessage(
+ sigmaProp: SigmaProp,
+ message: Int8Array,
+ hintsBag: ProverHints): Int8Array
+ }
+
+ export declare class SigmaPropProver$ {
+ /** Creates a new [[SigmaPropProver]] with the given secrets. */
+ withSecrets(secrets: ProverSecret[]): SigmaPropProver
+ }
+
+ /** Verifier which can verify signature (proof) for arbitrary sigma propositions
+ * represented by [[SigmaProp]] values.
*
- * u = g^x
- * and
- * y = h^x
+ * See [EIP-11](https://github.com/ergoplatform/eips/pull/8) for details of multi-signature scheme.
*
- * @param g [[GroupElement]] instance defining g
- * @param h [[GroupElement]] instance defining h
- * @param u [[GroupElement]] instance defining u
- * @param v [[GroupElement]] instance defining v
- * @param x [[BigInteger]] instance defining x
- * @see
- * example
- * @see
- * implementation
+ * @see SigmaPropProver
*/
- withDHTSecret(g: HexString, h: HexString, u: HexString, v: HexString, x: bigint): ProverBuilder;
-
- /** This allows adding additional secret for use in proveDlog, when the secret is not
- * part of the wallet.
+ export declare class SigmaPropVerifier {
+ /**
+ * Verify a signature on given (arbitrary) message for a given sigma proposition (public key).
+ *
+ * @param sigmaProp public key (represented as a sigma proposition)
+ * @param message message
+ * @param signature signature for the message
+ * @return whether signature is valid or not (valid signature contains proofs for the sigma proposition)
+ */
+ verifySignature(
+ sigmaProp: SigmaProp,
+ message: Int8Array,
+ signature: Int8Array): boolean
+ }
+ export declare class SigmaPropVerifier$ {
+ /** Create a new instance of [[SigmaPropVerifier]]. */
+ create(): SigmaPropVerifier
+ }
+
+ export declare class Utils {
+ /** Convert an Int8Array to a hex string. */
+ int8ArrayToHex(arr: Int8Array): string
+ }
+
+ /** Represents a prover for signing Ergo transactions and messages.
*
- * Multiple secrets can be added by calling this method multiple times.
+ * Equivalent of [[org.ergoplatform.sdk.SigmaProver]] available from JS.
+ */
+ export declare class SigmaProver {
+ /** Returns the Pay-to-Public-Key (P2PK) address associated with the prover's public key.
+ * The returned address corresponds to the master secret derived from the mnemonic
+ * phrase configured in the [[ProverBuilder]].
+ */
+ getP2PKAddress(): HexString;
+
+ /** Returns the prover's secret key. */
+ getSecretKey(): bigint;
+
+ /** Returns an array of EIP-3 addresses associated with the prover's secret keys. */
+ getEip3Addresses(): HexString[];
+
+ /** Reduces the transaction to the reduced form, which is ready to be signed.
+ * @param stateCtx blockchain state context
+ * @param unsignedTx unsigned transaction to be reduced (created by Fleet builders)
+ * @param boxesToSpend boxes to be spent by the transaction
+ * @param dataInputs data inputs to be used by the transaction
+ * @param tokensToBurn tokens to be burned by the transaction
+ * @param baseCost base cost of the transaction
+ * @return reduced transaction
+ */
+ reduce(
+ stateCtx: BlockchainStateContext,
+ unsignedTx: UnsignedTransaction,
+ boxesToSpend: EIP12UnsignedInput[],
+ dataInputs: Box[],
+ tokensToBurn: TokenAmount[],
+ baseCost: number): ReducedTransaction;
+
+ /** Signs the reduced transaction.
+ * @param reducedTx reduced transaction to be signed
+ * @return signed transaction containting all the required proofs (signatures)
+ */
+ signReduced(reducedTx: ReducedTransaction): SignedTransaction;
+ }
+
+ /** Equivalent of [[sdk.ProverBuilder]] available from JS.
*
- * Multiple secrets are necessary for statements that need multiple proveDlogs, such
- * as proveDlog(a) && proveDlog(b), where a and b are two group elements.
+ * @param parameters Blockchain parameters re-adjustable via miners voting and
+ * voting-related data. All of them are included into extension
+ * section of a first block of a voting epoch.
+ * @param network Network prefix to use for addresses.
*/
- withDLogSecret(x: bigint): ProverBuilder;
-
- /** Builds a new prover using provided configuration. */
- build(): SigmaProver;
- }
-
- export declare class ProverBuilderObj {
- static create(parameters: BlockchainParameters, network: number): ProverBuilder;
- }
+ export declare class ProverBuilder {
+ /** Configure this builder to use the given seed when building a new prover.
+ *
+ * @param mnemonicPhrase secret seed phrase to be used in prover for generating proofs.
+ * @param mnemonicPass password to protect secret seed phrase.
+ */
+ withMnemonic(mnemonicPhrase: HexString, mnemonicPass: HexString): ProverBuilder;
+
+ /** Configure this builder to derive the new EIP-3 secret key with the given index.
+ * The derivation uses master key derived from the mnemonic configured using
+ * [[ErgoProverBuilder.withMnemonic]].
+ *
+ * @param index last index in the EIP-3 derivation path.
+ */
+ withEip3Secret(index: number): ProverBuilder;
+
+ /** Configures this builder to use group elements (g, h, u, v) and secret x for a
+ * ProveDHTuple statement when building a new prover.
+ *
+ * ProveDHTuple is a statement consisting of 4 group elements (g, h, u, v) and
+ * requires the prover to prove knowledge of secret integer x such that.
+ *
+ * u = g^x
+ * and
+ * y = h^x
+ *
+ * @param g [[GroupElement]] instance defining g
+ * @param h [[GroupElement]] instance defining h
+ * @param u [[GroupElement]] instance defining u
+ * @param v [[GroupElement]] instance defining v
+ * @param x [[BigInteger]] instance defining x
+ * @see
+ * example
+ * @see
+ * implementation
+ */
+ withDHTSecret(g: HexString, h: HexString, u: HexString, v: HexString, x: bigint): ProverBuilder;
+
+ /** This allows adding additional secret for use in proveDlog, when the secret is not
+ * part of the wallet.
+ *
+ * Multiple secrets can be added by calling this method multiple times.
+ *
+ * Multiple secrets are necessary for statements that need multiple proveDlogs, such
+ * as proveDlog(a) && proveDlog(b), where a and b are two group elements.
+ */
+ withDLogSecret(x: bigint): ProverBuilder;
+
+ /** Builds a new prover using provided configuration. */
+ build(): SigmaProver;
+ }
+
+ export declare class ProverBuilder$ {
+ static create(parameters: BlockchainParameters, network: number): ProverBuilder;
+ }
+
+ /**
+ * Represents a ContractTemplate parameter.
+ */
+ export declare class Parameter {
+ /** User readable parameter name (string bytes in UTF-8 encoding) */
+ name: String
+ /** User readable parameter description (string bytes in UTF-8 encoding) */
+ description: String
+ /** Index in the ErgoTree.constants array */
+ constantIndex: number
+ }
+
+ /** JavaScript class wrapping the Scala [[sigma.ast.Value]]. */
+ export declare class Expr {
+ }
+
+ /**
+ * Represents a reusable ContractTemplate with support to generate ErgoTree based on
+ * provided parameters.
+ */
+ export declare class ContractTemplate {
+ /**
+ * The optional version of ErgoTree which should be used. If this value is not
+ * provided here then it must be provided while generating the `ErgoTree` by
+ * calling `applyTemplate`.
+ */
+ treeVersion: number | undefined;
+
+ /** User readable name (non-empty string bytes in UTF-8 encoding). */
+ name: string;
+
+ /** User readable contract description (string bytes in UTF-8 encoding). */
+ description: string;
+
+ /** List denoting the type of ConstantPlaceholders in the expressionTree. */
+ constTypes: Type[];
+
+ /**
+ * Optional list of optional default values for the ConstantPlaceholders in the
+ * expressionTree. If an entry in the sequence is None, it must have a
+ * corresponding entry in parameters and its value must be provided while
+ * generating the `ErgoTree` by calling `applyTemplate`. If all the entries are
+ * None, the whole `constValues` field can be set to None.
+ */
+ constValues: (Value | undefined)[] | undefined;
+
+ /**
+ * Typed template parameters of the contract template. It must have an entry for
+ * each `ConstantPlaceholder` which has a `None` in the `constValues` field. Other
+ * fields which do have a value defined in `constValues` can also be allowed to be
+ * optionally overridden by accepting it in `parameters`.
+ */
+ parameters: Parameter[];
+
+ /** Root of the contract which is a valid expression of `SigmaProp` type. Must
+ * have constants segregated into `constTypes` and optionally `constValues`
+ */
+ expressionTree: Expr
+
+ /** @return JSON representation of this contract template pretty-printed to a string
+ * indentation of two spaces.
+ */
+ toJsonString(): String
+
+ /**
+ * Generate the ErgoTree from the template by providing the values for parameters.
+ *
+ * @param version the version of the `ErgoTree` to use. Must be provided if the `treeVersion` was not provided in the
+ * template.
+ * @param paramValues the name-value map for the parameters accepted by the `ContractTemplate`. Must contain an entry
+ * for each parameter for which no default value was provided in the template. Optionally, can also
+ * provide values to override for parameters which do have a default value defined in the template.
+ * The type of the provided value must match with the corresponding entry in the `constTypes`
+ * provided in the template.
+ * @return `ErgoTree` generated by replacing the template parameters with the value provided in `paramValues`.
+ */
+ applyTemplate(
+ version: number | undefined,
+ paramValues: SigmaCompilerNamedConstantsMap): ErgoTree
+ }
+
+ export declare class ContractTemplate$ {
+ /** Create a new contract template from a JSON string.
+ *
+ * @param json JSON string representing a contract template.
+ * @return a new contract template.
+ */
+ fromJsonString(json: String): ContractTemplate
+ }
}
diff --git a/sigma-js/tests/js/Address.spec.js b/sigma-js/tests/js/Address.spec.js
new file mode 100644
index 0000000000..0e78434cf0
--- /dev/null
+++ b/sigma-js/tests/js/Address.spec.js
@@ -0,0 +1,53 @@
+const { Address, Address$ } = require("sigmastate-js/main");
+
+describe("Smoke tests for API exporting", () => {
+ it("Should export Address object", () => {
+ expect(Address).not.toBeUndefined();
+ });
+});
+
+describe("Address", () => {
+ let addrStr = "9iJd9drp1KR3R7HLi7YmQbB5sJ5HFKZoPb5MxGepamggJs5vDHm";
+ let p2sStr = "JryiCXrZf5VDetH1PM7rKDX3q4sLF34AdErWJFqG87Hf5ikTDf636b35Nr7goWMdRUKA3ZPxdeqFNbQzBjhnDR9SUMYwDX1tdV8ZuGgXwQPaRVcB9"
+
+ it("roundtrip for P2PK", () => {
+ let addr = Address$.fromString(addrStr);
+ expect(addr.isP2PK()).toEqual(true)
+ expect(addr.isP2S()).toEqual(false)
+
+ expect(addr.toString()).not.toBeUndefined();
+ expect(addr.toString()).toEqual(addrStr)
+ expect(addr.asP2PK()).not.toBeUndefined();
+ });
+
+ it("roundtrip for P2S", () => {
+ let addr = Address$.fromString(p2sStr);
+ expect(addr.isP2S()).toEqual(true)
+ expect(addr.isP2PK()).toEqual(false)
+
+ expect(addr.toString()).not.toBeUndefined();
+ expect(addr.toString()).toEqual(p2sStr)
+ expect(addr.asP2S()).not.toBeUndefined();
+ });
+
+ it("toSigmaPropOpt", () => {
+ let addr = Address$.fromString(addrStr);
+
+ expect(addr.isMainnet()).toEqual(true)
+ expect(addr.toSigmaPropOpt()).not.toBeUndefined()
+ });
+
+ it("other properties", () => {
+ let addr = Address$.fromString(addrStr);
+ expect(addr.toErgoTree()).not.toBeUndefined()
+ expect(addr.asP2PK()).not.toBeUndefined()
+ expect(addr.asP2PK().isP2PK()).toEqual(true)
+ expect(addr.asP2PK().toErgoTree()).not.toBeUndefined()
+ expect(addr.asP2PK().toSigmaProp()).not.toBeUndefined()
+ expect(addr.asP2PK().toPropositionBytes()).not.toBeUndefined()
+ expect(addr.asP2PK().addressTypePrefix()).not.toBeUndefined()
+ expect(addr.asP2PK().getPublicKeyGE()).not.toBeUndefined()
+ });
+
+});
+
diff --git a/sigma-js/tests/js/ContractTemplate.spec.js b/sigma-js/tests/js/ContractTemplate.spec.js
new file mode 100644
index 0000000000..fc45198549
--- /dev/null
+++ b/sigma-js/tests/js/ContractTemplate.spec.js
@@ -0,0 +1,64 @@
+const {ContractTemplate, ContractTemplate$, Value$} = require("sigmastate-js/main");
+
+describe("Smoke tests for API exporting", () => {
+ it("Should export ContractTempate object", () => {
+ expect(ContractTemplate).not.toBeUndefined();
+ });
+});
+
+describe("ContractTemplate", () => {
+ let templateJsonStr = "{\n" +
+ " \"treeVersion\" : null,\n" +
+ " \"name\" : \"TestContractTemplate\",\n" +
+ " \"description\" : \"TestContractTemplateDescription\",\n" +
+ " \"constTypes\" : [\n" +
+ " \"02\",\n" +
+ " \"02\",\n" +
+ " \"02\"\n" +
+ " ],\n" +
+ " \"constValues\" : [\n" +
+ " 10,\n" +
+ " 20,\n" +
+ " 30\n" +
+ " ],\n" +
+ " \"parameters\" : [\n" +
+ " {\n" +
+ " \"name\" : \"p1\",\n" +
+ " \"description\" : \"p1_description\",\n" +
+ " \"constantIndex\" : 0\n" +
+ " },\n" +
+ " {\n" +
+ " \"name\" : \"p2\",\n" +
+ " \"description\" : \"p2_description\",\n" +
+ " \"constantIndex\" : 1\n" +
+ " },\n" +
+ " {\n" +
+ " \"name\" : \"p3\",\n" +
+ " \"description\" : \"p3_description\",\n" +
+ " \"constantIndex\" : 2\n" +
+ " }\n" +
+ " ],\n" +
+ " \"expressionTree\" : \"d1939a730073017302\"\n" +
+ "}";
+
+ let template = ContractTemplate$.fromJsonString(templateJsonStr);
+
+ it("Json encoding roundtrip", () => {
+ expect(template).not.toBeUndefined();
+ expect(template.toJsonString()).toEqual(templateJsonStr);
+ }
+ );
+
+ it("applyTemplate", () => {
+ let templateValues = {
+ "p1": Value$.ofByte(10),
+ "p2": Value$.ofByte(40),
+ "p3": Value$.ofByte(50)
+ };
+ let tree = template.applyTemplate(2, templateValues);
+ expect(tree.toHex()).toEqual("1a1003020a02280232d1939a730073017302");
+ }
+ );
+
+});
+
diff --git a/sigma-js/tests/js/ErgoTree.spec.js b/sigma-js/tests/js/ErgoTree.spec.js
index 688ea9bfa3..48058bc788 100644
--- a/sigma-js/tests/js/ErgoTree.spec.js
+++ b/sigma-js/tests/js/ErgoTree.spec.js
@@ -1,4 +1,4 @@
-const { ErgoTree, ErgoTreeObj } = require("sigmastate-js/main");
+const { ErgoTree, ErgoTree$ } = require("sigmastate-js/main");
describe("Smoke tests for API exporting", () => {
it("Should export ErgoTree object", () => {
@@ -10,13 +10,13 @@ describe("Smoke tests for ErgoTree", () => {
let hex = "100604000e000400040005000500d803d601e30004d602e4c6a70408d603e4c6a7050595e67201d804d604b2a5e4720100d605b2db63087204730000d606db6308a7d60799c1a7c17204d1968302019683050193c27204c2a7938c720501730193e4c672040408720293e4c672040505720393e4c67204060ec5a796830201929c998c7205029591b1720673028cb272067303000273047203720792720773057202";
it("Should create fromHex", () => {
- let tree = ErgoTreeObj.fromHex(hex);
+ let tree = ErgoTree$.fromHex(hex);
expect(tree.toString()).not.toBeUndefined();
expect(tree.toHex()).toEqual(hex)
});
it("Has properties", () => {
- let tree = ErgoTreeObj.fromHex(hex);
+ let tree = ErgoTree$.fromHex(hex);
expect(tree.header()).toEqual(0x10)
expect(tree.version()).toEqual(0)
@@ -25,13 +25,13 @@ describe("Smoke tests for ErgoTree", () => {
});
it("Has constants", () => {
- let tree = ErgoTreeObj.fromHex(hex);
+ let tree = ErgoTree$.fromHex(hex);
let constants = tree.constants().map(c => c.toHex())
expect(constants).toEqual(["0400", "0e00", "0400", "0400", "0500", "0500"])
});
it("Has template", () => {
- let tree = ErgoTreeObj.fromHex(hex);
+ let tree = ErgoTree$.fromHex(hex);
let templateHex = tree.templateHex();
expect(templateHex).toEqual("d803d601e30004d602e4c6a70408d603e4c6a7050595e67201d804d604b2a5e4720100d605b2db63087204730000d606db6308a7d60799c1a7c17204d1968302019683050193c27204c2a7938c720501730193e4c672040408720293e4c672040505720393e4c67204060ec5a796830201929c998c7205029591b1720673028cb272067303000273047203720792720773057202")
});
diff --git a/sigma-js/tests/js/GroupElement.spec.js b/sigma-js/tests/js/GroupElement.spec.js
index 6d860691be..f408728602 100644
--- a/sigma-js/tests/js/GroupElement.spec.js
+++ b/sigma-js/tests/js/GroupElement.spec.js
@@ -1,13 +1,13 @@
-const { GroupElementObj, ValueObj } = require("sigmastate-js/main");
+const { GroupElement$, Value$ } = require("sigmastate-js/main");
let pointAsn1Hex = "02c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5";
describe("GroupElement", () => {
it("should implement toPointHex/fromPointHex", () => {
- let ge = GroupElementObj.fromPointHex(pointAsn1Hex)
+ let ge = GroupElement$.fromPointHex(pointAsn1Hex)
expect(ge.toPointHex()).toEqual(pointAsn1Hex)
- let v = ValueObj.ofGroupElement(pointAsn1Hex)
+ let v = Value$.ofGroupElement(pointAsn1Hex)
expect(v.toHex()).toEqual("07"/* GroupElement type id */ + pointAsn1Hex)
});
});
\ No newline at end of file
diff --git a/sigma-js/tests/js/SigmaCompiler.spec.js b/sigma-js/tests/js/SigmaCompiler.spec.js
index 6e531d63aa..312747d504 100644
--- a/sigma-js/tests/js/SigmaCompiler.spec.js
+++ b/sigma-js/tests/js/SigmaCompiler.spec.js
@@ -1,7 +1,7 @@
-const { ValueObj, SigmaCompilerObj } = require("sigmastate-js/main");
+const { Value$, SigmaCompiler$ } = require("sigmastate-js/main");
describe("Smoke tests for API exporting", () => {
- let compiler = SigmaCompilerObj.forMainnet();
+ let compiler = SigmaCompiler$.forMainnet();
it("Should create SigmaCompiler", () => {
expect(compiler).not.toBeUndefined();
@@ -21,7 +21,7 @@ describe("Smoke tests for API exporting", () => {
it("SigmaCompiler should compile with named constants", () => {
let treeWithSegregation = compiler.compile(
- {"deadline": ValueObj.ofInt(100)},
+ {"deadline": Value$.ofInt(100)},
true, 0, "sigmaProp(HEIGHT > deadline)");
expect(treeWithSegregation).not.toBeUndefined();
expect(treeWithSegregation.toHex()).toEqual(segregatedTreeHex)
diff --git a/sigma-js/tests/js/SigmaProp.spec.js b/sigma-js/tests/js/SigmaProp.spec.js
index 89568120c7..8191b24ccd 100644
--- a/sigma-js/tests/js/SigmaProp.spec.js
+++ b/sigma-js/tests/js/SigmaProp.spec.js
@@ -1,13 +1,13 @@
-const { SigmaPropObj, ValueObj } = require("sigmastate-js/main");
+const { SigmaProp$, Value$ } = require("sigmastate-js/main");
let pointAsn1Hex = "02c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5";
describe("SigmaProp", () => {
it("should implement fromPointHex", () => {
- let ge = SigmaPropObj.fromPointHex(pointAsn1Hex)
+ let ge = SigmaProp$.fromPointHex(pointAsn1Hex)
expect(ge).not.toBeUndefined()
- let v = ValueObj.ofSigmaProp(pointAsn1Hex)
+ let v = Value$.ofSigmaProp(pointAsn1Hex)
expect(v.toHex())
.toEqual("08"/* SigmaProp type id */ + "cd"/* ProveDlog.opCode */ + pointAsn1Hex)
});
diff --git a/sigma-js/tests/js/SigmaPropProver.spec.js b/sigma-js/tests/js/SigmaPropProver.spec.js
new file mode 100644
index 0000000000..4703f75b57
--- /dev/null
+++ b/sigma-js/tests/js/SigmaPropProver.spec.js
@@ -0,0 +1,30 @@
+const {
+ ProverSecret$, SigmaPropProver$,
+ ProverHints$, SigmaPropVerifier$
+} = require("sigmastate-js/main");
+
+describe("SigmaPropProver", () => {
+ let w = 0xadf47e32000fc75e2923dba482c843c7f6b684cbf2ceec5bfdf5fe6d13cabe5dn
+ let secret = ProverSecret$.dlog(w)
+ expect(secret.secret()).toEqual(w)
+
+ let p = SigmaPropProver$.withSecrets([secret])
+ expect(p).not.toBeUndefined()
+
+ it("generateCommitments", () => {
+ let hints = p.generateCommitments(secret.publicKey())
+ expect(hints).not.toBeUndefined()
+ });
+
+ it("signMessage", () => {
+ let message = Int8Array.of(1, 2, 3)
+ let signature = p.signMessage(secret.publicKey(), message, ProverHints$.empty())
+ expect(signature).not.toBeUndefined()
+ expect(signature.length).toBeGreaterThan(0)
+
+ let V = SigmaPropVerifier$.create()
+ let ok = V.verifySignature(secret.publicKey(), message, signature)
+ expect(ok).toEqual(true)
+ });
+
+});
\ No newline at end of file
diff --git a/sigma-js/tests/js/Type.spec.js b/sigma-js/tests/js/Type.spec.js
index fe1b0c0383..83d60481b7 100644
--- a/sigma-js/tests/js/Type.spec.js
+++ b/sigma-js/tests/js/Type.spec.js
@@ -1,27 +1,27 @@
-const { TypeObj } = require("sigmastate-js/main");
+const { Type$ } = require("sigmastate-js/main");
describe("Smoke tests for Types", () => {
it("Should create primitive types", () => {
- expect(TypeObj.Byte.name).toEqual("Byte");
- expect(TypeObj.Short.name).toEqual("Short");
- expect(TypeObj.Int.name).toEqual("Int");
- expect(TypeObj.Long.name).toEqual("Long");
- expect(TypeObj.BigInt.name).toEqual("BigInt");
- expect(TypeObj.GroupElement.name).toEqual("GroupElement");
- expect(TypeObj.SigmaProp.name).toEqual("SigmaProp");
- expect(TypeObj.Box.name).toEqual("Box");
- expect(TypeObj.AvlTree.name).toEqual("AvlTree");
- expect(TypeObj.Context.name).toEqual("Context");
- expect(TypeObj.Header.name).toEqual("Header");
- expect(TypeObj.PreHeader.name).toEqual("PreHeader");
- expect(TypeObj.SigmaDslBuilder.name).toEqual("SigmaDslBuilder");
+ expect(Type$.Byte.name).toEqual("Byte");
+ expect(Type$.Short.name).toEqual("Short");
+ expect(Type$.Int.name).toEqual("Int");
+ expect(Type$.Long.name).toEqual("Long");
+ expect(Type$.BigInt.name).toEqual("BigInt");
+ expect(Type$.GroupElement.name).toEqual("GroupElement");
+ expect(Type$.SigmaProp.name).toEqual("SigmaProp");
+ expect(Type$.Box.name).toEqual("Box");
+ expect(Type$.AvlTree.name).toEqual("AvlTree");
+ expect(Type$.Context.name).toEqual("Context");
+ expect(Type$.Header.name).toEqual("Header");
+ expect(Type$.PreHeader.name).toEqual("PreHeader");
+ expect(Type$.SigmaDslBuilder.name).toEqual("SigmaDslBuilder");
});
it("Should create complex types", () => {
- expect(TypeObj.pairType(TypeObj.Int, TypeObj.Long).name).toEqual("(Int, Long)");
- expect(TypeObj.collType(TypeObj.Int).name).toEqual("Coll[Int]");
- expect(TypeObj.collType(TypeObj.pairType(TypeObj.Int, TypeObj.Long)).name)
+ expect(Type$.pairType(Type$.Int, Type$.Long).name).toEqual("(Int, Long)");
+ expect(Type$.collType(Type$.Int).name).toEqual("Coll[Int]");
+ expect(Type$.collType(Type$.pairType(Type$.Int, Type$.Long)).name)
.toEqual("Coll[(Int, Long)]");
});
});
diff --git a/sigma-js/tests/js/Value.spec.js b/sigma-js/tests/js/Value.spec.js
index e687f8aecb..694ba2064b 100644
--- a/sigma-js/tests/js/Value.spec.js
+++ b/sigma-js/tests/js/Value.spec.js
@@ -1,4 +1,4 @@
-const { TypeObj, ValueObj, SigmaPropObj, SigmaProp} = require("sigmastate-js/main");
+const { Type$, Value$, SigmaProp$, SigmaProp} = require("sigmastate-js/main");
function testRange(factory, min, max) {
expect(factory(max).data).toEqual(max);
@@ -10,20 +10,20 @@ function testRange(factory, min, max) {
describe("Smoke tests for Values", () => {
it("Should create values of primitive types", () => {
- expect(ValueObj.ofByte(0).data).toEqual(0);
- expect(ValueObj.ofByte(0).tpe).toEqual(TypeObj.Byte);
- testRange(function(v) { return ValueObj.ofByte(v); }, -128, 127);
- testRange(function(v) { return ValueObj.ofShort(v); }, -32768, 32767);
- testRange(function(v) { return ValueObj.ofInt(v); }, -0x7FFFFFFF - 1, 0x7FFFFFFF);
- testRange(function(v) { return ValueObj.ofLong(v); }, -0x8000000000000000n, 0x7fffffffffffffffn);
+ expect(Value$.ofByte(0).data).toEqual(0);
+ expect(Value$.ofByte(0).tpe).toEqual(Type$.Byte);
+ testRange(function(v) { return Value$.ofByte(v); }, -128, 127);
+ testRange(function(v) { return Value$.ofShort(v); }, -32768, 32767);
+ testRange(function(v) { return Value$.ofInt(v); }, -0x7FFFFFFF - 1, 0x7FFFFFFF);
+ testRange(function(v) { return Value$.ofLong(v); }, -0x8000000000000000n, 0x7fffffffffffffffn);
});
it("Should create values of complex types", () => {
- let pair = ValueObj.pairOf(ValueObj.ofByte(10), ValueObj.ofLong(20n));
+ let pair = Value$.pairOf(Value$.ofByte(10), Value$.ofLong(20n));
expect(pair.data).toEqual([10, 20n]);
expect(pair.tpe.name).toEqual("(Byte, Long)");
- let coll = ValueObj.collOf([-10, 0, 10], TypeObj.Byte)
+ let coll = Value$.collOf([-10, 0, 10], Type$.Byte)
expect(coll.tpe.name).toEqual("Coll[Byte]");
});
@@ -42,99 +42,100 @@ describe("Smoke tests for Values", () => {
let pairHex = "3e050a28"
it("Unit Value.toHex", () => {
- let v = ValueObj.fromHex(unitHex)
+ let v = Value$.fromHex(unitHex)
expect(v.toHex()).toEqual(unitHex)
});
it("Boolean Value.toHex", () => {
- let v = ValueObj.fromHex(booleanHex)
+ let v = Value$.fromHex(booleanHex)
expect(v.toHex()).toEqual(booleanHex)
});
it("Byte Value.toHex", () => {
- let v = ValueObj.fromHex(byteHex)
+ let v = Value$.fromHex(byteHex)
expect(v.toHex()).toEqual(byteHex)
});
it("Short Value.toHex", () => {
- let v = ValueObj.fromHex(shortHex)
+ let v = Value$.fromHex(shortHex)
expect(v.toHex()).toEqual(shortHex)
});
it("Int Value.toHex", () => {
- let v = ValueObj.fromHex(intHex)
+ let v = Value$.fromHex(intHex)
expect(v.toHex()).toEqual(intHex)
});
it("Long Value.toHex", () => {
- let v = ValueObj.ofLong(1200n)
+ let v = Value$.ofLong(1200n)
expect(v.toHex()).toEqual(longHex)
});
it("BigInt Value.toHex", () => {
- let v = ValueObj.ofBigInt(0xfffffffffffffffen)
+ let v = Value$.ofBigInt(0xfffffffffffffffen)
expect(v.toHex()).toEqual(bigIntHex)
});
it("GroupElement Value.toHex", () => {
- let v = ValueObj.fromHex(groupElementHex)
+ let v = Value$.fromHex(groupElementHex)
expect(v.toHex()).toEqual(groupElementHex)
});
it("SigmaProp Value.toHex", () => {
- let v = ValueObj.fromHex(sigmaPropHex)
+ let v = Value$.fromHex(sigmaPropHex)
expect(v.toHex()).toEqual(sigmaPropHex)
});
it("AvlTree Value.toHex", () => {
- let v = ValueObj.fromHex(avlTreeHex)
+ let v = Value$.fromHex(avlTreeHex)
expect(v.toHex()).toEqual(avlTreeHex)
});
- it("Box Value.toHex", () => {
- let v = ValueObj.fromHex(boxHex)
- expect(v.toHex()).toEqual(boxHex)
- });
+ // TODO uncomment when Box is implemented
+ // ignore("Box Value.toHex", () => {
+ // let v = Value$.fromHex(boxHex)
+ // expect(v.toHex()).toEqual(boxHex)
+ // });
it("Coll Value.toHex", () => {
let arr = [ [1, 2, 3], [10, 20] ]
- let t = TypeObj.collType(TypeObj.Byte)
- let collV = ValueObj.collOf(arr, t)
+ let t = Type$.collType(Type$.Byte)
+ let collV = Value$.collOf(arr, t)
expect(collV.tpe.name).toEqual("Coll[Coll[Byte]]");
expect(collV.toHex()).toEqual(collHex)
});
it("Value of type Coll[SigmaProp]", () => {
- let sp1 = SigmaPropObj.fromPointHex(groupElementHex.substring(2))
- let sp2 = SigmaPropObj.fromPointHex(sigmaPropHex.substring(4))
- let collV = ValueObj.collOf([sp1, sp2], TypeObj.SigmaProp)
+ let sp1 = SigmaProp$.fromPointHex(groupElementHex.substring(2))
+ let sp2 = SigmaProp$.fromPointHex(sigmaPropHex.substring(4))
+ let collV = Value$.collOf([sp1, sp2], Type$.SigmaProp)
expect(collV.tpe.name).toEqual("Coll[SigmaProp]");
});
it("Pair Value.toHex", () => {
- let fst = ValueObj.ofByte(10)
- let snd = ValueObj.ofLong(20)
- let pair = ValueObj.pairOf(fst, snd)
+ let fst = Value$.ofByte(10)
+ let snd = Value$.ofLong(20)
+ let pair = Value$.pairOf(fst, snd)
expect(pair.tpe.name).toEqual("(Byte, Long)");
expect(pair.toHex()).toEqual(pairHex)
});
it("Long Value.fromHex", () => {
- let v = ValueObj.fromHex(longHex)
+ let v = Value$.fromHex(longHex)
expect(v.data).toEqual(1200n)
expect(v.tpe.name).toEqual("Long")
});
it("Coll Value.fromHex", () => {
- let coll = ValueObj.fromHex(collHex)
+ let coll = Value$.fromHex(collHex)
expect(coll.tpe.name).toEqual("Coll[Coll[Byte]]");
expect(coll.toHex()).toEqual(collHex)
});
it("Pair Value.fromHex", () => {
- let p = ValueObj.fromHex(pairHex)
+ let p = Value$.fromHex(pairHex)
expect(p.tpe.name).toEqual("(Byte, Long)");
expect(p.toHex()).toEqual(pairHex)
});