diff --git a/core/js/src/main/scala/sigma/js/GroupElement.scala b/core/js/src/main/scala/sigma/js/GroupElement.scala index 21b53b265d..82d8d462d6 100644 --- a/core/js/src/main/scala/sigma/js/GroupElement.scala +++ b/core/js/src/main/scala/sigma/js/GroupElement.scala @@ -1,6 +1,6 @@ package sigma.js -import sigma.Extensions.CoreArrayByteOps +import scorex.util.encode.Base16 import sigma.crypto.{CryptoFacade, CryptoFacadeJs, Ecp, Platform} import scala.scalajs.js @@ -13,7 +13,7 @@ class GroupElement(val point: Ecp) extends js.Object { * @see CryptoFacade.getASN1Encoding */ def toPointHex(): String = { - CryptoFacade.getASN1Encoding(point, true).toHex + Base16.encode(CryptoFacade.getASN1Encoding(point, true)) } } diff --git a/core/js/src/main/scala/sigma/js/Isos.scala b/core/js/src/main/scala/sigma/js/Isos.scala index b28a3337b8..767a358d62 100644 --- a/core/js/src/main/scala/sigma/js/Isos.scala +++ b/core/js/src/main/scala/sigma/js/Isos.scala @@ -8,6 +8,9 @@ import scala.reflect.ClassTag import scala.scalajs.js import scala.scalajs.js.JSConverters.JSRichOption +/** Definitions of isomorphisms for sigma-core module. + * @see sigma.data.Iso + */ 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]] { diff --git a/core/shared/src/main/scala/sigma/Environment.scala b/core/shared/src/main/scala/sigma/Environment.scala index 959e02c1fb..432c40110c 100644 --- a/core/shared/src/main/scala/sigma/Environment.scala +++ b/core/shared/src/main/scala/sigma/Environment.scala @@ -14,7 +14,7 @@ sealed abstract class Environment { object Environment { /** Current runtime environment. */ - implicit val current: Environment = new Environment { + val current: Environment = new Environment { override def isJVM: Boolean = runtimePlatform == RuntimePlatform.JVM override def isJS: Boolean = runtimePlatform == RuntimePlatform.JS override def runtimePlatform: RuntimePlatform = sigma.reflection.Platform.runtimePlatform diff --git a/core/shared/src/main/scala/sigma/Evaluation.scala b/core/shared/src/main/scala/sigma/Evaluation.scala index 893bdfb9f8..d86b7c1650 100644 --- a/core/shared/src/main/scala/sigma/Evaluation.scala +++ b/core/shared/src/main/scala/sigma/Evaluation.scala @@ -76,8 +76,7 @@ object Evaluation { case HeaderRType => SHeader case PreHeaderRType => SPreHeader case SigmaPropRType => SSigmaProp - // TODO remove commented code below after full sync test - // case SigmaBooleanRType => SSigmaProp // this is not used in consensus code + 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)) diff --git a/core/shared/src/main/scala/sigma/Extensions.scala b/core/shared/src/main/scala/sigma/Extensions.scala index 865d488803..0c79df94ea 100644 --- a/core/shared/src/main/scala/sigma/Extensions.scala +++ b/core/shared/src/main/scala/sigma/Extensions.scala @@ -5,13 +5,14 @@ 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) diff --git a/core/shared/src/main/scala/sigma/VersionContext.scala b/core/shared/src/main/scala/sigma/VersionContext.scala index 5663bfed60..19a4857086 100644 --- a/core/shared/src/main/scala/sigma/VersionContext.scala +++ b/core/shared/src/main/scala/sigma/VersionContext.scala @@ -1,6 +1,6 @@ package sigma -import VersionContext.{EvolutionVersion, JitActivationVersion} +import VersionContext.{JitActivationVersion, V6SoftForkVersion} import scala.util.DynamicVariable @@ -24,7 +24,7 @@ case class VersionContext(activatedVersion: Byte, ergoTreeVersion: Byte) { /** @return true, if the activated script version of Ergo protocol on the network is * including Evolution update. */ - def isEvolutionActivated: Boolean = activatedVersion >= EvolutionVersion + def isV6SoftForkActivated: Boolean = activatedVersion >= V6SoftForkVersion } object VersionContext { @@ -48,7 +48,7 @@ object VersionContext { /** * The version of ErgoTree corresponding to "evolution" (6.0) soft-fork */ - val EvolutionVersion: Byte = 3 + val V6SoftForkVersion: Byte = 3 private val _defaultContext = VersionContext( activatedVersion = 1 /* v4.x */, diff --git a/core/shared/src/main/scala/sigma/ast/SType.scala b/core/shared/src/main/scala/sigma/ast/SType.scala index e9ea0d43f0..f75cbc9e8b 100644 --- a/core/shared/src/main/scala/sigma/ast/SType.scala +++ b/core/shared/src/main/scala/sigma/ast/SType.scala @@ -94,7 +94,6 @@ object SType { 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. */ @@ -146,7 +145,7 @@ object SType { * 2) `isValueOfType == true` for each tree leaf * 3) `isValueOfType == true` for each sub-expression * - * @param value value to check type + * @param x value to check type * @param tpe type descriptor to check value against * @return true if the given `value` is of type tpe` */ diff --git a/core/shared/src/main/scala/sigma/data/Iso.scala b/core/shared/src/main/scala/sigma/data/Iso.scala index 9b90d63bb0..0e463bdd04 100644 --- a/core/shared/src/main/scala/sigma/data/Iso.scala +++ b/core/shared/src/main/scala/sigma/data/Iso.scala @@ -7,14 +7,20 @@ 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. + * + * Each isomorphism defined by two functions: + * - `to: A => B` - conversion from `A` to `B` + * - `from: B => A` - conversion from `B` to `A` + * *

- * The information is not lost so that both are true: + * such that the information is not lost during conversion, 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 + * - conversion between internal Ergo representations and API representations + * - conversions between exported JS classes and internal Ergo representations */ abstract class Iso[A, B] { def to(a: A): B diff --git a/core/shared/src/main/scala/sigma/data/SigmaPropCodes.scala b/core/shared/src/main/scala/sigma/data/SigmaPropCodes.scala index 17257c9ce5..fafd24ffdd 100644 --- a/core/shared/src/main/scala/sigma/data/SigmaPropCodes.scala +++ b/core/shared/src/main/scala/sigma/data/SigmaPropCodes.scala @@ -3,7 +3,7 @@ package sigma.data import sigma.ast.TypeCodes.LastConstantCode import supertagged.TaggedType -/** Encoding of sigma proposition nodes. +/** Opcodes of sigma proposition nodes. * * @see SigmaBoolean.opCode */ diff --git a/core/shared/src/main/scala/sigma/data/package.scala b/core/shared/src/main/scala/sigma/data/package.scala index a0fb219af8..c5a35f7b5f 100644 --- a/core/shared/src/main/scala/sigma/data/package.scala +++ b/core/shared/src/main/scala/sigma/data/package.scala @@ -16,6 +16,7 @@ package object data { 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] diff --git a/core/shared/src/main/scala/sigma/package.scala b/core/shared/src/main/scala/sigma/package.scala index 67560b462c..89b883f52d 100644 --- a/core/shared/src/main/scala/sigma/package.scala +++ b/core/shared/src/main/scala/sigma/package.scala @@ -25,9 +25,12 @@ package object sigma { 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 2aac1a5670..028e68bf72 100644 --- a/core/shared/src/main/scala/sigma/reflection/ReflectionData.scala +++ b/core/shared/src/main/scala/sigma/reflection/ReflectionData.scala @@ -9,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. */ diff --git a/core/shared/src/main/scala/sigma/serialization/CoreByteReader.scala b/core/shared/src/main/scala/sigma/serialization/CoreByteReader.scala index 34ed74ac6a..e238829b6c 100644 --- a/core/shared/src/main/scala/sigma/serialization/CoreByteReader.scala +++ b/core/shared/src/main/scala/sigma/serialization/CoreByteReader.scala @@ -10,10 +10,6 @@ import sigma.validation.ValidationRules.CheckPositionLimit * 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 */ diff --git a/core/shared/src/main/scala/sigma/serialization/CoreByteWriter.scala b/core/shared/src/main/scala/sigma/serialization/CoreByteWriter.scala index d6cc9a8d8e..aa4255449c 100644 --- a/core/shared/src/main/scala/sigma/serialization/CoreByteWriter.scala +++ b/core/shared/src/main/scala/sigma/serialization/CoreByteWriter.scala @@ -5,6 +5,9 @@ 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 diff --git a/core/shared/src/main/scala/sigma/serialization/CoreSerializer.scala b/core/shared/src/main/scala/sigma/serialization/CoreSerializer.scala index aec82eb9df..938d3f22c1 100644 --- a/core/shared/src/main/scala/sigma/serialization/CoreSerializer.scala +++ b/core/shared/src/main/scala/sigma/serialization/CoreSerializer.scala @@ -6,25 +6,31 @@ 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 new SerializerException(msg, None) + 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 { - type Position = Int - + /** 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. diff --git a/core/shared/src/test/scala/sigma/VersionTesting.scala b/core/shared/src/test/scala/sigma/VersionTesting.scala index 69e15ff491..08053a6c48 100644 --- a/core/shared/src/test/scala/sigma/VersionTesting.scala +++ b/core/shared/src/test/scala/sigma/VersionTesting.scala @@ -39,9 +39,7 @@ trait VersionTesting { _ + 1) { j => val treeVersion = ergoTreeVers(j) // for each tree version up to currently activated, set it up and execute block - _currErgoTreeVersion.withValue(treeVersion) { - VersionContext.withVersions(activatedVersion, treeVersion)(block) - } + _currErgoTreeVersion.withValue(treeVersion)(block) } } } diff --git a/data/js/src/main/scala/sigma/data/js/Isos.scala b/data/js/src/main/scala/sigma/data/js/Isos.scala new file mode 100644 index 0000000000..22300b1fd8 --- /dev/null +++ b/data/js/src/main/scala/sigma/data/js/Isos.scala @@ -0,0 +1,152 @@ +package sigma.data.js + +import org.ergoplatform.ErgoBox._ +import org.ergoplatform.{ErgoBox, ErgoBoxCandidate} +import scorex.crypto.authds.ADKey +import scorex.util.encode.Base16 +import sigma.Extensions._ +import sigma.ast.syntax.GroupElementConstant +import sigma.ast.{Constant, GroupElementConstant, SType} +import sigma.data.Iso.isoStringToArray +import sigma.data.{CGroupElement, Digest32Coll, Iso} +import sigma.js.GroupElement +import sigma.serialization.{ErgoTreeSerializer, ValueSerializer} +import sigma.{Coll, Colls} +import sigmastate.fleetSdkCommon.distEsmTypesCommonMod.HexString +import sigmastate.fleetSdkCommon.distEsmTypesRegistersMod.NonMandatoryRegisters +import sigmastate.fleetSdkCommon.{distEsmTypesBoxesMod => boxesMod, distEsmTypesCommonMod => commonMod, distEsmTypesRegistersMod => registersMod, distEsmTypesTokenMod => tokenMod} + +import scala.scalajs.js + +/** Definitions of isomorphisms for sigma-data module. + * @see sigma.data.Iso + */ +object Isos { + + val isoStringToGroupElement: Iso[String, sigma.GroupElement] = new Iso[String, sigma.GroupElement] { + override def to(x: String): sigma.GroupElement = { + val bytes = Base16.decode(x).get + ValueSerializer.deserialize(bytes).asInstanceOf[GroupElementConstant].value + } + override def from(x: sigma.GroupElement): String = { + val bytes = ValueSerializer.serialize(GroupElementConstant(x)) + Base16.encode(bytes) + } + } + + val isoGroupElement: Iso[GroupElement, sigma.GroupElement] = new Iso[GroupElement, sigma.GroupElement] { + override def to(x: GroupElement): sigma.GroupElement = { + CGroupElement(x.point) + } + override def from(x: sigma.GroupElement): GroupElement = { + new GroupElement(x.asInstanceOf[CGroupElement].wrappedValue) + } + } + + implicit val isoBoxId: Iso[boxesMod.BoxId, ErgoBox.BoxId] = new Iso[boxesMod.BoxId, ErgoBox.BoxId] { + override def to(x: boxesMod.BoxId): ErgoBox.BoxId = ADKey @@@ isoStringToArray.to(x) + + override def from(x: ErgoBox.BoxId): boxesMod.BoxId = isoStringToArray.from(x) + } + + implicit val isoHexStringToConstant: Iso[HexString, Constant[SType]] = new Iso[HexString, Constant[SType]] { + override def to(x: HexString): Constant[SType] = { + val bytes = isoStringToArray.to(x) + val value = ValueSerializer.deserialize(bytes) + value.asInstanceOf[Constant[SType]] + } + override def from(x: Constant[SType]): HexString = { + val bytes = ValueSerializer.serialize(x) + isoStringToArray.from(bytes) + } + } + + + 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 + case _ => java.lang.Long.parseLong(x.asInstanceOf[js.BigInt].toString(10)) + } + override def from(x: Long): commonMod.Amount = x.toString + } + + implicit val isoToken: Iso[tokenMod.TokenAmount[commonMod.Amount], Token] = + new Iso[tokenMod.TokenAmount[commonMod.Amount], Token] { + override def to(x: tokenMod.TokenAmount[commonMod.Amount]): Token = + (Digest32Coll @@@ Colls.fromArray(Base16.decode(x.tokenId).get), isoAmount.to(x.amount)) + + override def from(x: Token): tokenMod.TokenAmount[commonMod.Amount] = + tokenMod.TokenAmount[commonMod.Amount](isoAmount.from(x._2), x._1.toHex) + } + + 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] = { + sigma.js.Isos.isoArrayToColl(isoToken).to(x) + } + override def from(x: Coll[Token]): js.Array[tokenMod.TokenAmount[commonMod.Amount]] = { + sigma.js.Isos.isoArrayToColl(isoToken).from(x) + } + } + + val isoNonMandatoryRegisters: Iso[registersMod.NonMandatoryRegisters, AdditionalRegisters] = + new Iso[registersMod.NonMandatoryRegisters, AdditionalRegisters] { + override def to(x: registersMod.NonMandatoryRegisters): AdditionalRegisters = { + val regs = Seq( + x.R4 -> R4, + x.R5 -> R5, + x.R6 -> R6, + x.R7 -> R7, + x.R8 -> R8, + x.R9 -> R9 + ).collect { + case (regOpt, id) if regOpt.isDefined => id -> isoHexStringToConstant.to(regOpt.get) + } + Map(regs:_*) + } + override def from(regs: AdditionalRegisters): registersMod.NonMandatoryRegisters = { + def regHexOpt(t: NonMandatoryRegisterId): Option[HexString] = + regs.get(t).map(v => isoHexStringToConstant.from(v.asInstanceOf[Constant[SType]])) + + val resRegs = NonMandatoryRegisters() + regHexOpt(R4).foreach(resRegs.setR4(_)) + regHexOpt(R5).foreach(resRegs.setR5(_)) + regHexOpt(R6).foreach(resRegs.setR6(_)) + regHexOpt(R7).foreach(resRegs.setR7(_)) + regHexOpt(R8).foreach(resRegs.setR8(_)) + regHexOpt(R9).foreach(resRegs.setR9(_)) + resRegs + } + } + + implicit val isoBoxCandidate: Iso[boxesMod.BoxCandidate[commonMod.Amount, NonMandatoryRegisters], ErgoBoxCandidate] = new Iso[boxesMod.BoxCandidate[commonMod.Amount, NonMandatoryRegisters], ErgoBoxCandidate] { + override def to(x: boxesMod.BoxCandidate[commonMod.Amount, NonMandatoryRegisters]): ErgoBoxCandidate = { + val ergoBoxCandidate = new ErgoBoxCandidate( + value = isoAmount.to(x.value), + ergoTree = { + val bytes = Base16.decode(x.ergoTree).get + ErgoTreeSerializer.DefaultSerializer.deserializeErgoTree(bytes) + }, + x.creationHeight.toInt, + additionalTokens = isoTokenArray.to(x.assets), + additionalRegisters = isoNonMandatoryRegisters.to(x.additionalRegisters) + ) + ergoBoxCandidate + } + + override def from(x: ErgoBoxCandidate): boxesMod.BoxCandidate[commonMod.Amount, NonMandatoryRegisters] = { + val ergoTree = ErgoTreeSerializer.DefaultSerializer.serializeErgoTree(x.ergoTree) + val ergoTreeStr = Base16.encode(ergoTree) + val assets = isoTokenArray.from(x.additionalTokens) + boxesMod.BoxCandidate[commonMod.Amount, NonMandatoryRegisters]( + ergoTree = ergoTreeStr, + value = isoAmount.from(x.value), + assets = assets, + creationHeight = x.creationHeight, + additionalRegisters = isoNonMandatoryRegisters.from(x.additionalRegisters) + ) + } + } + + +} diff --git a/data/js/src/main/scala/sigma/js/Box.scala b/data/js/src/main/scala/sigma/js/Box.scala new file mode 100644 index 0000000000..70155633d5 --- /dev/null +++ b/data/js/src/main/scala/sigma/js/Box.scala @@ -0,0 +1,61 @@ +package sigma.js + +import org.ergoplatform.ErgoBox +import scorex.util.ModifierId +import scorex.util.encode.Base16 +import sigma.data.Iso +import sigma.data.js.Isos.{isoAmount, isoNonMandatoryRegisters, isoTokenArray} +import sigma.serialization.ErgoTreeSerializer +import sigmastate.fleetSdkCommon.distEsmTypesBoxesMod.{Box => FBox} +import sigmastate.fleetSdkCommon.distEsmTypesCommonMod.Amount +import sigmastate.fleetSdkCommon.distEsmTypesRegistersMod.NonMandatoryRegisters +import sigmastate.fleetSdkCommon.{distEsmTypesCommonMod => commonMod} + +import scala.scalajs.js +import scala.scalajs.js.annotation.JSExportTopLevel + +/** Equivalent of [[sigma.Box]] available from JS. */ +@JSExportTopLevel("Box") +class Box(val box: FBox[Amount, NonMandatoryRegisters]) extends js.Object + +object Box extends js.Object { + /** Represents a box in Fleet SDK. */ + type FleetBox = FBox[commonMod.Amount, NonMandatoryRegisters] + + /** Converts Fleet box to ErgoBox and back. */ + val isoBox: Iso[FleetBox, ErgoBox] = new Iso[FleetBox, ErgoBox] { + override def to(x: FleetBox): ErgoBox = { + val ergoBox = new ErgoBox( + value = isoAmount.to(x.value), + ergoTree = { + val bytes = Base16.decode(x.ergoTree).get + ErgoTreeSerializer.DefaultSerializer.deserializeErgoTree(bytes) + }, + creationHeight = x.creationHeight.toInt, + additionalTokens = isoTokenArray.to(x.assets), + additionalRegisters = isoNonMandatoryRegisters.to(x.additionalRegisters), + transactionId = ModifierId @@ x.transactionId, + index = x.index.toShort + ) + ergoBox + } + + override def from(x: ErgoBox): FleetBox = { + val ergoTree = ErgoTreeSerializer.DefaultSerializer.serializeErgoTree(x.ergoTree) + val ergoTreeStr = Base16.encode(ergoTree) + val assets = isoTokenArray.from(x.additionalTokens) + FBox[commonMod.Amount, NonMandatoryRegisters]( + boxId = Base16.encode(x.id), + ergoTree = ergoTreeStr, + value = isoAmount.from(x.value), + assets = assets, + creationHeight = x.creationHeight, + additionalRegisters = isoNonMandatoryRegisters.from(x.additionalRegisters), + transactionId = x.transactionId, + index = x.index + ) + } + } + + +} \ No newline at end of file diff --git a/core/js/src/main/scala/sigma/js/Value.scala b/data/js/src/main/scala/sigma/js/Value.scala similarity index 92% rename from core/js/src/main/scala/sigma/js/Value.scala rename to data/js/src/main/scala/sigma/js/Value.scala index 13b63c2abc..a65156bd43 100644 --- a/core/js/src/main/scala/sigma/js/Value.scala +++ b/data/js/src/main/scala/sigma/js/Value.scala @@ -7,9 +7,10 @@ import sigma.ast.SType import sigma.crypto.Platform import sigma.data._ import sigma.js.Value.toRuntimeData -import sigma.serialization.{CoreDataSerializer, CoreSerializer} +import sigma.serialization.{DataSerializer, SigmaSerializer} import sigma.util.Extensions.BigIntOps import sigma.{Coll, Colls, Evaluation} +import sigmastate.fleetSdkCommon.distEsmTypesBoxesMod.{Box => FBox} import java.math.BigInteger import scala.scalajs.js @@ -55,9 +56,9 @@ class Value(val data: Any, val tpe: Type) extends js.Object { def toHex(): String = { val stype = Evaluation.rtypeToSType(tpe.rtype) val value = runtimeData.asInstanceOf[SType#WrappedType] - val w = CoreSerializer.startWriter() + val w = SigmaSerializer.startWriter() w.putType(stype) - CoreDataSerializer.serialize(value, stype, w) + DataSerializer.serialize(value, stype, w) Base16.encode(w.toBytes) } } @@ -89,6 +90,9 @@ object Value extends js.Object { case sigma.AvlTreeRType => val t = data.asInstanceOf[AvlTree] AvlTree.isoAvlTree.to(t) + case sigma.BoxRType => + val t = data.asInstanceOf[Box] + CBox(Box.isoBox.to(t.box)) case ct: CollType[a] => val xs = data.asInstanceOf[js.Array[Any]] implicit val cT = ct.tItem.classTag @@ -124,6 +128,9 @@ object Value extends js.Object { new SigmaProp(value.asInstanceOf[CSigmaProp].wrappedValue) case sigma.AvlTreeRType => AvlTree.isoAvlTree.from(value.asInstanceOf[CAvlTree]) + case sigma.BoxRType => + val fleetBox = Box.isoBox.from(value.asInstanceOf[CBox].wrappedValue) + new Box(fleetBox) case ct: CollType[a] => val arr = value.asInstanceOf[Coll[a]].toArray js.Array(arr.map(x => fromRuntimeData(x, ct.tItem)):_*) @@ -220,6 +227,13 @@ object Value extends js.Object { new Value(sp, Type.SigmaProp) } + /** Creates a Value of Box type from a [[FBox]] instance. + * @param fleetBox a Fleet box to be wrapped in a [[Value]] + */ + def ofBox(fleetBox: Box.FleetBox): Value = { + new Value(new Box(fleetBox), Type.Box) + } + /** Create Pair value from two values. */ def pairOf(l: Value, r: Value): Value = { val data = js.Array(l.data, r.data) // the l and r data have been validated @@ -251,9 +265,9 @@ object Value extends js.Object { */ def fromHex(hex: String): Value = { val bytes = Base16.decode(hex).fold(t => throw t, identity) - val r = CoreSerializer.startReader(bytes) + val r = SigmaSerializer.startReader(bytes) val stype = r.getType() - val value = CoreDataSerializer.deserialize(stype, r) + val value = DataSerializer.deserialize(stype, r) val rtype = Evaluation.stypeToRType(stype) val jsvalue = Value.fromRuntimeData(value, rtype) new Value(jsvalue, new Type(rtype)) diff --git a/data/shared/src/main/scala/sigma/SigmaDataReflection.scala b/data/shared/src/main/scala/sigma/SigmaDataReflection.scala index 31703b0856..48939b1460 100644 --- a/data/shared/src/main/scala/sigma/SigmaDataReflection.scala +++ b/data/shared/src/main/scala/sigma/SigmaDataReflection.scala @@ -11,6 +11,10 @@ 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. diff --git a/data/shared/src/main/scala/sigma/ast/CostItem.scala b/data/shared/src/main/scala/sigma/ast/CostItem.scala index 8fa973b575..c69c81daa3 100644 --- a/data/shared/src/main/scala/sigma/ast/CostItem.scala +++ b/data/shared/src/main/scala/sigma/ast/CostItem.scala @@ -1,8 +1,5 @@ package sigma.ast -import sigma.ast -import sigma.eval.CostDetails - /** An item in the cost accumulation trace of a [[sigma.ast.ErgoTree]] evaluation. */ abstract class CostItem { def opName: String diff --git a/data/shared/src/main/scala/sigma/ast/SMethod.scala b/data/shared/src/main/scala/sigma/ast/SMethod.scala index 2d306d8948..669625ef1e 100644 --- a/data/shared/src/main/scala/sigma/ast/SMethod.scala +++ b/data/shared/src/main/scala/sigma/ast/SMethod.scala @@ -105,7 +105,7 @@ case class SMethod( /** 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 = { + def invokeFixed(obj: Any, args: Array[Any]): Any = { javaMethod.invoke(obj, args.asInstanceOf[Array[AnyRef]]:_*) } diff --git a/data/shared/src/main/scala/sigma/ast/SigmaPredef.scala b/data/shared/src/main/scala/sigma/ast/SigmaPredef.scala index 5cdbdedaa8..631f7f2d75 100644 --- a/data/shared/src/main/scala/sigma/ast/SigmaPredef.scala +++ b/data/shared/src/main/scala/sigma/ast/SigmaPredef.scala @@ -12,6 +12,8 @@ import sigma.exceptions.InvalidArguments import sigma.serialization.CoreByteWriter.ArgInfo import sigma.serialization.ValueSerializer +import java.math.BigInteger + object SigmaPredef { type IrBuilderFunc = PartialFunction[(SValue, Seq[SValue]), SValue] @@ -179,6 +181,17 @@ object SigmaPredef { Seq(ArgInfo("", ""))) ) + val BigIntFromStringFunc = PredefinedFunc("bigInt", + Lambda(Array("input" -> SString), SBigInt, None), + PredefFuncInfo( + { case (_, Seq(arg: EvaluatedValue[SString.type]@unchecked)) => + BigIntConstant(new BigInteger(arg.value)) + }), + OperationInfo(Constant, + """Parsing string literal argument as a 256-bit signed big integer.""".stripMargin, + Seq(ArgInfo("", ""))) + ) + val FromBase16Func = PredefinedFunc("fromBase16", Lambda(Array("input" -> SString), SByteArray, None), PredefFuncInfo( @@ -402,6 +415,7 @@ object SigmaPredef { SigmaPropFunc, GetVarFunc, DeserializeFunc, + BigIntFromStringFunc, FromBase16Func, FromBase64Func, FromBase58Func, @@ -591,7 +605,7 @@ object SigmaPredef { ).map(f => f.name -> f).toMap private val funcNameToIrBuilderMap: Map[String, PredefinedFunc] = - funcs.filter { case (n, f) => f.irInfo.irBuilder != undefined } + funcs.filter { case (_, f) => f.irInfo.irBuilder != undefined } def irBuilderForFunc(name: String): Option[IrBuilderFunc] = funcNameToIrBuilderMap.get(name).map(_.irInfo.irBuilder) } diff --git a/data/shared/src/main/scala/sigma/ast/methods.scala b/data/shared/src/main/scala/sigma/ast/methods.scala index 5371be233c..3642a82ddb 100644 --- a/data/shared/src/main/scala/sigma/ast/methods.scala +++ b/data/shared/src/main/scala/sigma/ast/methods.scala @@ -15,7 +15,6 @@ 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 @@ -61,7 +60,7 @@ sealed trait MethodsContainer { } ms } - private lazy val _methodsMap: Map[Byte, Map[Byte, SMethod]] = methods + private def _methodsMap: Map[Byte, Map[Byte, SMethod]] = methods //todo: consider versioned caching .groupBy(_.objType.typeId) .map { case (typeId, ms) => (typeId -> ms.map(m => m.methodId -> m).toMap) } @@ -235,7 +234,7 @@ object SNumericTypeMethods extends MethodsContainer { | Each boolean corresponds to one bit. """.stripMargin) - protected override def getMethods: Seq[SMethod] = Array( + protected override def getMethods(): Seq[SMethod] = Array( ToByteMethod, // see Downcast ToShortMethod, // see Downcast ToIntMethod, // see Downcast @@ -322,6 +321,13 @@ case object SBigIntMethods extends SNumericTypeMethods { /** Type for which this container defines methods. */ override def ownerType: SMonoType = SBigInt + final val ToNBitsCostInfo = OperationCostInfo( + FixedCost(JitCost(5)), NamedDesc("NBitsMethodCall")) + + //id = 8 to make it after toBits + val ToNBits = SMethod(this, "nbits", SFunc(this.ownerType, SLong), 8, ToNBitsCostInfo.costKind) + .withInfo(ModQ, "Encode this big integer value as NBits") + /** 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 @@ -337,13 +343,26 @@ case object SBigIntMethods extends SNumericTypeMethods { .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, - ) + protected override def getMethods(): Seq[SMethod] = { + if (VersionContext.current.isV6SoftForkActivated) { + super.getMethods() ++ Seq(ToNBits) + // ModQMethod, + // PlusModQMethod, + // MinusModQMethod, + // TODO soft-fork: https://github.com/ScorexFoundation/sigmastate-interpreter/issues/479 + // MultModQMethod, + } else { + super.getMethods() + } + } + + /** + * + */ + def nbits_eval(mc: MethodCall, bi: sigma.BigInt)(implicit E: ErgoTreeEvaluator): Long = { + ??? + } + } /** Methods of type `String`. */ @@ -732,7 +751,7 @@ object SCollectionMethods extends MethodsContainer with MethodByNameUnapply { * 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 MethodCall(ValUse(id, _), _, args, _) if args.isEmpty => id }, { case ExtractScriptBytes(ValUse(id, _)) => id }, { case ExtractId(ValUse(id, _)) => id }, { case SigmaPropBytes(ValUse(id, _)) => id }, @@ -778,7 +797,7 @@ object SCollectionMethods extends MethodsContainer with MethodByNameUnapply { 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 => + case MethodCall(_, _, Seq(FuncValue(args, body)), _) if args.length == 1 => val id = args(0)._1 Nullable((id, body)) case _ => @@ -1492,7 +1511,7 @@ case object SGlobalMethods extends MonoTypeMethods { lazy val groupGeneratorMethod = SMethod( this, "groupGenerator", SFunc(SGlobal, SGroupElement), 1, GroupGenerator.costKind) - .withIRInfo({ case (builder, obj, method, args, tparamSubst) => GroupGenerator }) + .withIRInfo({ case (_, _, _, _, _) => GroupGenerator }) .withInfo(GroupGenerator, "") lazy val xorMethod = SMethod( diff --git a/data/shared/src/main/scala/sigma/ast/syntax.scala b/data/shared/src/main/scala/sigma/ast/syntax.scala index d75c71a779..5a257481cb 100644 --- a/data/shared/src/main/scala/sigma/ast/syntax.scala +++ b/data/shared/src/main/scala/sigma/ast/syntax.scala @@ -118,8 +118,6 @@ object syntax { @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]) diff --git a/data/shared/src/main/scala/sigma/ast/trees.scala b/data/shared/src/main/scala/sigma/ast/trees.scala index 38d4565f30..39e666a389 100644 --- a/data/shared/src/main/scala/sigma/ast/trees.scala +++ b/data/shared/src/main/scala/sigma/ast/trees.scala @@ -295,7 +295,6 @@ object AND extends LogicalTransformerCompanion { def apply(children: Seq[Value[SBoolean.type]]): AND = AND(ConcreteCollection.fromSeq(children)) -// def apply(head: Value[SBoolean.type], tail: Value[SBoolean.type]*): AND = apply(head +: tail) def apply(items: Value[SBoolean.type]*)(implicit o1: Overloaded1): AND = apply(items) } diff --git a/data/shared/src/main/scala/sigma/serialization/ErgoTreeSerializer.scala b/data/shared/src/main/scala/sigma/serialization/ErgoTreeSerializer.scala index 3d1061d774..43e41f91ff 100644 --- a/data/shared/src/main/scala/sigma/serialization/ErgoTreeSerializer.scala +++ b/data/shared/src/main/scala/sigma/serialization/ErgoTreeSerializer.scala @@ -1,13 +1,13 @@ package sigma.serialization import org.ergoplatform.validation.ValidationRules.{CheckDeserializedScriptIsSigmaProp, CheckHeaderSizeBit} -import sigma.ast.{Constant, DeserializationSigmaBuilder, ErgoTree, SType, SubstConstants, UnparsedErgoTree} +import sigma.ast.{Constant, DeserializationSigmaBuilder, ErgoTree, SType, UnparsedErgoTree} import sigma.ast.syntax.ValueOps import sigma.ast.ErgoTree.{EmptyConstants, HeaderType} import sigma.util.safeNewArray import debox.cfor import sigma.VersionContext -import sigma.validation.{SigmaValidationSettings, ValidationException} +import sigma.validation.ValidationException import sigma.validation.ValidationRules.CheckPositionLimit /** @@ -299,7 +299,7 @@ class ErgoTreeSerializer { */ def substituteConstants(scriptBytes: Array[Byte], positions: Array[Int], - newVals: Array[Constant[SType]])(implicit vs: SigmaValidationSettings): (Array[Byte], Int) = { + newVals: Array[Constant[SType]]): (Array[Byte], Int) = { require(positions.length == newVals.length, s"expected positions and newVals to have the same length, got: positions: ${positions.toSeq},\n newVals: ${newVals.toSeq}") val r = SigmaSerializer.startReader(scriptBytes) diff --git a/data/shared/src/main/scala/sigma/serialization/SigmaSerializer.scala b/data/shared/src/main/scala/sigma/serialization/SigmaSerializer.scala index cdb28d724b..3765adb029 100644 --- a/data/shared/src/main/scala/sigma/serialization/SigmaSerializer.scala +++ b/data/shared/src/main/scala/sigma/serialization/SigmaSerializer.scala @@ -4,7 +4,6 @@ import java.nio.ByteBuffer import scorex.util.ByteArrayBuilder import scorex.util.serialization._ import sigma.data.SigmaConstants -import sigma.validation.SigmaValidationSettings import sigma.serialization.ValueCodes.OpCode object SigmaSerializer { @@ -35,8 +34,7 @@ object SigmaSerializer { /** Helper function to be use in serializers. */ def startReader(bytes: Array[Byte], constantStore: ConstantStore, - resolvePlaceholdersToConstants: Boolean) - (implicit vs: SigmaValidationSettings): SigmaByteReader = { + resolvePlaceholdersToConstants: Boolean): SigmaByteReader = { val buf = ByteBuffer.wrap(bytes) val r = new SigmaByteReader(new VLQByteBufferReader(buf), constantStore, diff --git a/docs/LangSpec.md b/docs/LangSpec.md index ddbb7bd680..ba66748f08 100644 --- a/docs/LangSpec.md +++ b/docs/LangSpec.md @@ -985,6 +985,12 @@ def proveDHTuple(g: GroupElement, h: GroupElement, */ def proveDlog(value: GroupElement): SigmaProp +/** Transforms Base16 encoded string literal into constant of type BigInt. + * It is a compile-time operation and only string literal (constant) can be its + * argument. + */ +def bigInt(input: String): BigInt + /** Transforms Base16 encoded string literal into constant of type Coll[Byte]. * It is a compile-time operation and only string literal (constant) can be its * argument. diff --git a/interpreter/js/src/main/scala/sigma/interpreter/js/SigmaPropProver.scala b/interpreter/js/src/main/scala/sigma/interpreter/js/SigmaPropProver.scala index a04d32fa54..414a9d1220 100644 --- a/interpreter/js/src/main/scala/sigma/interpreter/js/SigmaPropProver.scala +++ b/interpreter/js/src/main/scala/sigma/interpreter/js/SigmaPropProver.scala @@ -65,7 +65,6 @@ class SigmaPropProver(override val wrappedValue: org.ergoplatform.SigmaPropProve val realsToExtract = toSigmaBooleanSeq(realSecretsToExtract) val simsToExtract = toSigmaBooleanSeq(simulatedSecretsToExtract) val hints = wrappedValue.bagForMultisig( - context = null, sigmaTree = sigmaTree.sigmaBoolean, proof.toArray, realSecretsToExtract = realsToExtract, simulatedSecretsToExtract = simsToExtract) diff --git a/interpreter/shared/src/main/scala/org/ergoplatform/ErgoLikeContext.scala b/interpreter/shared/src/main/scala/org/ergoplatform/ErgoLikeContext.scala index 8468175631..e421e8fdfe 100644 --- a/interpreter/shared/src/main/scala/org/ergoplatform/ErgoLikeContext.scala +++ b/interpreter/shared/src/main/scala/org/ergoplatform/ErgoLikeContext.scala @@ -6,7 +6,6 @@ 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} diff --git a/interpreter/shared/src/main/scala/sigmastate/InterpreterReflection.scala b/interpreter/shared/src/main/scala/sigmastate/InterpreterReflection.scala index 8b18e20459..9a06322166 100644 --- a/interpreter/shared/src/main/scala/sigmastate/InterpreterReflection.scala +++ b/interpreter/shared/src/main/scala/sigmastate/InterpreterReflection.scala @@ -8,6 +8,10 @@ import sigmastate.crypto.GF2_192_Poly 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. diff --git a/interpreter/shared/src/main/scala/sigmastate/crypto/GF2_192.scala b/interpreter/shared/src/main/scala/sigmastate/crypto/GF2_192.scala index bb0ad60a84..e63526e854 100644 --- a/interpreter/shared/src/main/scala/sigmastate/crypto/GF2_192.scala +++ b/interpreter/shared/src/main/scala/sigmastate/crypto/GF2_192.scala @@ -30,8 +30,6 @@ package sigmastate.crypto import debox.cfor -import java.util - class GF2_192 extends AnyRef { private[crypto] val word: Array[Long] = new Array[Long](3) diff --git a/interpreter/shared/src/main/scala/sigmastate/crypto/GF2_192_Poly.scala b/interpreter/shared/src/main/scala/sigmastate/crypto/GF2_192_Poly.scala index a9212fe565..d2ddc4db48 100644 --- a/interpreter/shared/src/main/scala/sigmastate/crypto/GF2_192_Poly.scala +++ b/interpreter/shared/src/main/scala/sigmastate/crypto/GF2_192_Poly.scala @@ -31,8 +31,6 @@ package sigmastate.crypto import debox.cfor -import java.util - class GF2_192_Poly { final private var c: Array[GF2_192] = null // must be not null and of length at least 1 diff --git a/interpreter/shared/src/main/scala/sigmastate/eval/CContext.scala b/interpreter/shared/src/main/scala/sigmastate/eval/CContext.scala index 418f9e8959..2b076403ad 100644 --- a/interpreter/shared/src/main/scala/sigmastate/eval/CContext.scala +++ b/interpreter/shared/src/main/scala/sigmastate/eval/CContext.scala @@ -9,62 +9,6 @@ import sigma.exceptions.InvalidType import scala.annotation.unused import scala.reflect.ClassTag - -/** 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 [[Context]] interface. * @see [[Context]] for detailed descriptions */ diff --git a/interpreter/shared/src/main/scala/sigmastate/eval/CProfiler.scala b/interpreter/shared/src/main/scala/sigmastate/eval/CProfiler.scala index ced8a357b8..d07153bd51 100644 --- a/interpreter/shared/src/main/scala/sigmastate/eval/CProfiler.scala +++ b/interpreter/shared/src/main/scala/sigmastate/eval/CProfiler.scala @@ -280,7 +280,7 @@ class CProfiler extends Profiler { case ci: TypeBasedCostItem => val comment = s"count: $count, suggested: $suggestedCost, actCost: ${ci.cost}$warn" (ci.opName, time, time, comment) - case ci @ SeqCostItem(_, costKind, nItems) => + case ci @ SeqCostItem(_, costKind, _) => val nChunks = ci.chunks val timePerChunk = if (nChunks > 0) time / nChunks else time val name = s"${ci.opName}(nChunks: $nChunks)" @@ -289,7 +289,7 @@ class CProfiler extends Profiler { } } (name, timePerItem, time, comment) - }.sortBy({ case (name, tpi, t, c) => (name, tpi)})(Ordering[(String, Long)]) + }.sortBy({ case (name, tpi, _, _) => (name, tpi)})(Ordering[(String, Long)]) val estLines = estimationCostStat.mapToArray { case (script, stat) => val (cost, count) = stat.mean @@ -302,7 +302,7 @@ class CProfiler extends Profiler { val rows = opCodeLines - .map { case (opName, opCode, time, comment) => + .map { case (opName, _, time, comment) => val key = s"$opName".padTo(26, ' ') s"$key -> time: $time ns, $comment " } diff --git a/interpreter/shared/src/main/scala/sigmastate/interpreter/Interpreter.scala b/interpreter/shared/src/main/scala/sigmastate/interpreter/Interpreter.scala index 6b673038c7..9a1ab11f0e 100644 --- a/interpreter/shared/src/main/scala/sigmastate/interpreter/Interpreter.scala +++ b/interpreter/shared/src/main/scala/sigmastate/interpreter/Interpreter.scala @@ -23,7 +23,7 @@ import sigmastate.interpreter.CErgoTreeEvaluator.fixedCostOp import sigmastate.interpreter.Interpreter._ import sigma.ast.syntax.ValueOps import sigma.eval.{EvalSettings, SigmaDsl} -import sigma.exceptions.{CostLimitException, InterpreterException} +import sigma.exceptions.InterpreterException import sigma.interpreter.ProverResult import sigma.util.CollectionUtil import sigmastate.utils.Helpers._ @@ -164,12 +164,11 @@ trait Interpreter { * else `exp` is computed in the given context and the resulting SigmaBoolean returned. * * @param context the context in which `exp` should be executed - * @param env environment of system variables used by the interpreter internally * @param exp expression to be executed in the given `context` * @return result of script reduction * @see `ReductionResult` */ - protected def reduceToCryptoJITC(context: CTX, env: ScriptEnv, exp: SigmaPropValue): Try[ReductionResult] = Try { + protected def reduceToCryptoJITC(context: CTX, exp: SigmaPropValue): Try[ReductionResult] = Try { implicit val vs = context.validationSettings trySoftForkable[ReductionResult](whenSoftFork = WhenSoftForkReductionResult(context.initCost)) { @@ -253,7 +252,7 @@ trait Interpreter { // here we assume that when `propTree` is TrueProp then `reduceToCrypto` always succeeds // and the rest of the verification is also trivial - reduceToCryptoJITC(context2, env, propTree).getOrThrow + reduceToCryptoJITC(context2, propTree).getOrThrow } res diff --git a/interpreter/shared/src/main/scala/sigmastate/interpreter/ProverUtils.scala b/interpreter/shared/src/main/scala/sigmastate/interpreter/ProverUtils.scala index 15daaec382..dc2259b0b7 100644 --- a/interpreter/shared/src/main/scala/sigmastate/interpreter/ProverUtils.scala +++ b/interpreter/shared/src/main/scala/sigmastate/interpreter/ProverUtils.scala @@ -81,7 +81,7 @@ trait ProverUtils extends Interpreter { realSecretsToExtract: Seq[SigmaBoolean], simulatedSecretsToExtract: Seq[SigmaBoolean] = Seq.empty): HintsBag = { val reduced = fullReduction(ergoTree, context, Interpreter.emptyEnv) - bagForMultisig(context, reduced.value, proof, realSecretsToExtract, simulatedSecretsToExtract) + bagForMultisig(reduced.value, proof, realSecretsToExtract, simulatedSecretsToExtract) } /** @@ -90,15 +90,13 @@ trait ProverUtils extends Interpreter { * * See DistributedSigSpecification for examples of usage. * - * @param context - context used to reduce the proposition * @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 bagForMultisig(context: CTX, - sigmaTree: SigmaBoolean, + def bagForMultisig(sigmaTree: SigmaBoolean, proof: Array[Byte], realSecretsToExtract: Seq[SigmaBoolean], simulatedSecretsToExtract: Seq[SigmaBoolean]): HintsBag = { diff --git a/interpreter/shared/src/test/scala/sigma/serialization/ConstantSerializerSpecification.scala b/interpreter/shared/src/test/scala/sigma/serialization/ConstantSerializerSpecification.scala index 7bc73643f2..43e9cf9e5d 100644 --- a/interpreter/shared/src/test/scala/sigma/serialization/ConstantSerializerSpecification.scala +++ b/interpreter/shared/src/test/scala/sigma/serialization/ConstantSerializerSpecification.scala @@ -61,7 +61,7 @@ class ConstantSerializerSpecification extends TableSerializationSpecification { } property("Constant serialization round trip") { - forAll { x: Unit => roundTripTest(UnitConstant()) } + forAll { _: Unit => roundTripTest(UnitConstant()) } forAll { x: Byte => roundTripTest(Constant[SByte.type](x, SByte)) } forAll { x: Boolean => roundTripTest(BooleanConstant.fromBoolean(x)) } forAll { x: Long => roundTripTest(Constant[SLong.type](x, SLong)) } diff --git a/interpreter/shared/src/test/scala/sigma/serialization/DataSerializerSpecification.scala b/interpreter/shared/src/test/scala/sigma/serialization/DataSerializerSpecification.scala index ecb2d2ef70..7cd9967e54 100644 --- a/interpreter/shared/src/test/scala/sigma/serialization/DataSerializerSpecification.scala +++ b/interpreter/shared/src/test/scala/sigma/serialization/DataSerializerSpecification.scala @@ -5,7 +5,6 @@ import org.ergoplatform.ErgoBox import org.scalacheck.Arbitrary._ import sigma.data.{DataValueComparer, RType, SigmaBoolean, TupleColl} import sigma.ast.SCollection.SByteArray -import sigmastate._ import sigmastate.eval._ import sigma.{AvlTree, Colls, Evaluation} import sigma.ast.SType.AnyOps diff --git a/interpreter/shared/src/test/scala/sigma/serialization/MethodCallSerializerSpecification.scala b/interpreter/shared/src/test/scala/sigma/serialization/MethodCallSerializerSpecification.scala index ac9c997d98..1db166c685 100644 --- a/interpreter/shared/src/test/scala/sigma/serialization/MethodCallSerializerSpecification.scala +++ b/interpreter/shared/src/test/scala/sigma/serialization/MethodCallSerializerSpecification.scala @@ -1,6 +1,8 @@ package sigma.serialization +import sigma.VersionContext import sigma.ast._ +import sigma.validation.ValidationException class MethodCallSerializerSpecification extends SerializationSpecification { @@ -21,4 +23,26 @@ class MethodCallSerializerSpecification extends SerializationSpecification { ) roundTripTest(expr) } + + property("MethodCall deserialization round trip for BigInt.nbits") { + def code = { + val bi = BigIntConstant(5) + val expr = MethodCall(bi, + SBigIntMethods.ToNBits, + Vector(), + Map() + ) + roundTripTest(expr) + } + + VersionContext.withVersions(VersionContext.V6SoftForkVersion, 1) { + code + } + + an[ValidationException] should be thrownBy ( + VersionContext.withVersions((VersionContext.V6SoftForkVersion - 1).toByte, 1) { + code + } + ) + } } diff --git a/interpreter/shared/src/test/scala/sigmastate/eval/BasicOpsTests.scala b/interpreter/shared/src/test/scala/sigmastate/eval/BasicOpsTests.scala index ba996b0246..e9ba273e17 100644 --- a/interpreter/shared/src/test/scala/sigmastate/eval/BasicOpsTests.scala +++ b/interpreter/shared/src/test/scala/sigmastate/eval/BasicOpsTests.scala @@ -3,16 +3,15 @@ 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.data.{CSigmaDslBuilder => SigmaDsl, TrivialProp} import sigma.util.Extensions.SigmaBooleanOps import java.math.BigInteger -import sigma.{ContractsTestkit, SigmaDslBuilder, SigmaProp} +import sigma.{ContractsTestkit, SigmaProp} import scala.language.implicitConversions class BasicOpsTests extends AnyFunSuite with ContractsTestkit with Matchers { - override val SigmaDsl: SigmaDslBuilder = CSigmaDslBuilder implicit def boolToSigma(b: Boolean): SigmaProp = TrivialProp(b).toSigmaProp @@ -60,7 +59,7 @@ class BasicOpsTests extends AnyFunSuite with ContractsTestkit with Matchers { } test("box.creationInfo._1 is Int") { - val box = newAliceBox(1, 100) + val box = newAliceBox(100) box.creationInfo._1 shouldBe a [Integer] } diff --git a/interpreter/shared/src/test/scala/special/sigma/ContractsTestkit.scala b/interpreter/shared/src/test/scala/special/sigma/ContractsTestkit.scala index 720223ee3a..b04e9c150f 100644 --- a/interpreter/shared/src/test/scala/special/sigma/ContractsTestkit.scala +++ b/interpreter/shared/src/test/scala/special/sigma/ContractsTestkit.scala @@ -8,43 +8,18 @@ import sigmastate.eval._ import sigmastate.helpers.TestingHelpers._ import sigma.data._ -import scala.annotation.nowarn // imports implicit ClassTag - trait ContractsTestkit { - val R0 = 0.toByte; - val R1 = 1.toByte; - val R2 = 2.toByte; - val R3 = 3.toByte; - val R4 = 4.toByte; - val R5 = 5.toByte; - val R6 = 6.toByte; - val R7 = 7.toByte; - val R8 = 8.toByte; - val R9 = 9.toByte; + val Colls = new CollOverArrayBuilder - val SigmaDsl: SigmaDslBuilder = CSigmaDslBuilder - val noRegisters = collection[AnyValue]() - val noBytes = collection[Byte]() val noInputs = Array[Box]() val noOutputs = Array[Box]() 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 = CSigmaDslBuilder.Colls.emptyColl[Header] val dummyPreHeader: PreHeader = null /** Create collection from array of items */ - def collection[T: RType](items: T*) = Colls.fromArray(items.toArray) - - /** Converts a map of registers to collection of registers. */ - def regs(m: Map[Byte, AnyValue]): Coll[AnyValue] = { - val res = new Array[AnyValue](10) - for ( (id, v) <- m ) { - assert(res(id) == null, s"register $id is defined more then once") - res(id) = v - } - Colls.fromArray(res) - } + def collection[T: RType](items: T*): Coll[T] = Colls.fromArray(items.toArray) /** Converts a map of context vars to collection of context vars. */ def contextVars(m: Map[Byte, AnyValue]): Coll[AnyValue] = { @@ -58,9 +33,7 @@ trait ContractsTestkit { Colls.fromArray(res) } - val AliceId = Array[Byte](1) // 0x0001 - - def newAliceBox(@nowarn id: Byte, value: Long): Box = { + def newAliceBox(value: Long): Box = { val ergoBox = testBox(value, ErgoTree.fromProposition(TrueSigmaProp), creationHeight = 0, additionalTokens = Seq(), additionalRegisters = Map()) @@ -90,8 +63,6 @@ trait ContractsTestkit { 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) - def withVariables(vars: Map[Int, AnyValue]) = ctx.copy(vars = contextVars(vars.map { case (k, v) => (k.toByte, v) })) } diff --git a/interpreter/shared/src/test/scala/special/sigma/SigmaTestingData.scala b/interpreter/shared/src/test/scala/special/sigma/SigmaTestingData.scala index d33f09dd80..f113a484ef 100644 --- a/interpreter/shared/src/test/scala/special/sigma/SigmaTestingData.scala +++ b/interpreter/shared/src/test/scala/special/sigma/SigmaTestingData.scala @@ -30,13 +30,6 @@ trait SigmaTestingData extends TestingCommons with ObjectGenerators { def Coll[T](items: T*)(implicit cT: RType[T]): Coll[T] = CSigmaDslBuilder.Colls.fromItems(items: _*) - /** Generator of random collection with `n` elements. */ - def collOfN[T: RType : Arbitrary](n: Int) - (implicit b: Buildable[T, Array[T]]): Gen[Coll[T]] = { - implicit val g: Gen[T] = Arbitrary.arbitrary[T] - containerOfN[Array, T](n, g).map(Colls.fromArray(_)) - } - val bytesGen: Gen[Array[Byte]] = for { len <- Gen.choose(0, 100) arr <- containerOfN[Array, Byte](len, Arbitrary.arbByte.arbitrary) @@ -54,63 +47,9 @@ trait SigmaTestingData extends TestingCommons with ObjectGenerators { res } - protected def sampleAvlProver = { - val keys = arrayOfN(100, keyCollGen).sample.get - val values = arrayOfN(100, bytesCollGen).sample.get - val (tree, prover) = createAvlTreeAndProver(keys.zip(values): _*) - (keys, values, tree, prover) - } - - protected def sampleAvlTree: AvlTree = { - val (_, _, _, avlProver) = sampleAvlProver - val digest = avlProver.digest.toColl - val tree = SigmaDsl.avlTree(AvlTreeFlags.ReadOnly.serializeToByte, digest, 32, None) - tree - } - val tokenId1: Digest32 = Blake2b256("id1") val tokenId2: Digest32 = Blake2b256("id2") - val header1: Header = CHeader(Blake2b256("Header.id").toColl, - 0, - Blake2b256("Header.parentId").toColl, - Blake2b256("ADProofsRoot").toColl, - sampleAvlTree, - Blake2b256("transactionsRoot").toColl, - timestamp = 0, - nBits = 0, - height = 0, - extensionRoot = Blake2b256("transactionsRoot").toColl, - minerPk = SigmaDsl.groupGenerator, - powOnetimePk = SigmaDsl.groupGenerator, - powNonce = Colls.fromArray(Array[Byte](0, 1, 2, 3, 4, 5, 6, 7)), - powDistance = SigmaDsl.BigInt(BigInt("1405498250268750867257727119510201256371618473728619086008183115260323").bigInteger), - votes = Colls.fromArray(Array[Byte](0, 1, 2)) - ) - val header2: Header = CHeader(Blake2b256("Header2.id").toColl, - 0, - header1.id, - Blake2b256("ADProofsRoot2").toColl, - sampleAvlTree, - Blake2b256("transactionsRoot2").toColl, - timestamp = 2, - nBits = 0, - height = 1, - extensionRoot = Blake2b256("transactionsRoot2").toColl, - minerPk = SigmaDsl.groupGenerator, - powOnetimePk = SigmaDsl.groupGenerator, - powNonce = Colls.fromArray(Array.fill(0.toByte)(8)), - powDistance = SigmaDsl.BigInt(BigInt("19306206489815517413186395405558417825367537880571815686937307203793939").bigInteger), - votes = Colls.fromArray(Array[Byte](0, 1, 0)) - ) - val headers = Colls.fromItems(header2, header1) - val preHeader: PreHeader = CPreHeader(0, - header2.id, - timestamp = 3, - nBits = 0, - height = 2, - minerPk = SigmaDsl.groupGenerator, - votes = Colls.emptyColl[Byte] - ) + object TestData { val BigIntZero: BigInt = CBigInt(new BigInteger("0", 16)) diff --git a/parsers/shared/src/test/scala/sigmastate/lang/LangTests.scala b/parsers/shared/src/test/scala/sigmastate/lang/LangTests.scala index c04f35ef71..498c3934bf 100644 --- a/parsers/shared/src/test/scala/sigmastate/lang/LangTests.scala +++ b/parsers/shared/src/test/scala/sigmastate/lang/LangTests.scala @@ -8,7 +8,6 @@ import sigma.ast._ import sigma.crypto.CryptoConstants import sigma.data.{CAnyValue, CSigmaDslBuilder, ProveDHTuple, ProveDlog, SigmaBoolean} import sigma.util.Extensions.BigIntegerOps -import sigmastate.eval._ import sigmastate.helpers.NegativeTesting import sigmastate.interpreter.Interpreter.ScriptEnv import sigma.ast.{Ident, MethodCallLike} diff --git a/parsers/shared/src/test/scala/sigmastate/lang/SigmaParserTest.scala b/parsers/shared/src/test/scala/sigmastate/lang/SigmaParserTest.scala index 7213088a05..02b28f86ca 100644 --- a/parsers/shared/src/test/scala/sigmastate/lang/SigmaParserTest.scala +++ b/parsers/shared/src/test/scala/sigmastate/lang/SigmaParserTest.scala @@ -615,6 +615,11 @@ class SigmaParserTest extends AnyPropSpec with ScalaCheckPropertyChecks with Mat MethodCallLike(StringConstant("hello"), "+", IndexedSeq(StringConstant("hello"))) } + property("bigInt string decoding") { + parse("""bigInt("32667486267383620946248345338628674027033885928301927616853987602485119134400")""") shouldBe + Apply(BigIntFromStringFunc.symNoType, IndexedSeq(StringConstant("32667486267383620946248345338628674027033885928301927616853987602485119134400"))) + } + property("fromBaseX string decoding") { parse("""fromBase16("1111")""") shouldBe Apply(FromBase16Func.symNoType, IndexedSeq(StringConstant("1111"))) parse("""fromBase58("111")""") shouldBe Apply(FromBase58Func.symNoType, IndexedSeq(StringConstant("111"))) 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 d4accabf3e..11cbaff739 100644 --- a/sc/shared/src/main/scala/org/ergoplatform/dsl/ContractSyntax.scala +++ b/sc/shared/src/main/scala/org/ergoplatform/dsl/ContractSyntax.scala @@ -60,7 +60,7 @@ trait ContractSyntax { contract: SigmaContract => case _: Box => BoxRType case _: AvlTreeData => syntax.AvlTreeDataRType // TODO remove this RType case _: AvlTree => AvlTreeRType - case _: SigmaBoolean => syntax.SigmaBooleanRType // TODO remove this RType + case _: SigmaBoolean => SigmaBooleanRType // TODO remove this RType case _: SigmaProp => SigmaPropRType case _: Context => ContextRType case _ => diff --git a/sc/shared/src/main/scala/scalan/GraphIRReflection.scala b/sc/shared/src/main/scala/scalan/GraphIRReflection.scala index ee29924fb7..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. diff --git a/sc/shared/src/main/scala/scalan/Library.scala b/sc/shared/src/main/scala/scalan/Library.scala index ee1ff80ad3..43f20813f0 100644 --- a/sc/shared/src/main/scala/scalan/Library.scala +++ b/sc/shared/src/main/scala/scalan/Library.scala @@ -107,7 +107,7 @@ trait Library extends Scalan override def invokeUnlifted(e: Elem[_], mc: MethodCall, dataEnv: DataEnv): Any = e match { case _: CollElem[_,_] => mc match { - case CollMethods.map(xs, f) => + case CollMethods.map(_, f) => val newMC = mc.copy(args = mc.args :+ f.elem.eRange)(mc.resultType, mc.isAdapterCall) super.invokeUnlifted(e, newMC, dataEnv) case _ => diff --git a/sc/shared/src/main/scala/scalan/MethodCalls.scala b/sc/shared/src/main/scala/scalan/MethodCalls.scala index af3c3201ef..14212df632 100644 --- a/sc/shared/src/main/scala/scalan/MethodCalls.scala +++ b/sc/shared/src/main/scala/scalan/MethodCalls.scala @@ -101,11 +101,6 @@ trait MethodCalls extends Base { self: Scalan => reifyObject(MethodCall(receiver, method, args, neverInvoke)(asElem[Any](resultElem), isAdapterCall)) } - /** Creates new NewObject node and returns its node ref. */ - def newObjEx[A](args: Any*)(implicit eA: Elem[A]): Ref[A] = { - reifyObject(NewObject[A](eA, args)) - } - @tailrec private def baseCause(e: Throwable): Throwable = e match { case e: ExceptionInInitializerError => baseCause(e.getCause) @@ -120,21 +115,6 @@ trait MethodCalls extends Base { self: Scalan => * point we know that the first RW set didn't triggered any rewrite. */ def rewriteNonInvokableMethodCall(@unused mc: MethodCall): Ref[_] = null - /** Create delegate instance suitable for method invocation. - * It is used when T is a class or a trait and the node referred by x doesn't conform to T. - * This method returns dynamically constructed instance, which conforms to T. - * Whenever a method of T is called on that instance, the call is intercepted and - * `DelegatedInterceptionHandler.invoke` method is called, then a new MethodCall can - * be constructed (which is befavior by default). - */ - protected def unrefDelegate[T <: AnyRef](x: Ref[T])(implicit ct: ClassTag[T]): T = { - val d = x.node - if (d.isInstanceOf[Const[_]]) - d.asInstanceOf[Const[T]@unchecked].x - else - !!!(s"Cannot do undefDelegate($x -> ${x.node})") - } - /** Generic helper to call the given method on the given receiver node. */ private[scalan] def invokeMethod[A](receiver: Sym, m: RMethod, args: Array[AnyRef], onInvokeSuccess: Any => A, @@ -148,9 +128,9 @@ trait MethodCalls extends Base { self: Scalan => } catch { case e: Exception => onInvokeException(baseCause(e)) } - } - else + } else { onInvokeImpossible + } } /** Method invocation enabler. diff --git a/sc/shared/src/main/scala/scalan/meta/SSymName.scala b/sc/shared/src/main/scala/scalan/meta/SSymName.scala index ea9b1546ba..b0f8dae6d2 100644 --- a/sc/shared/src/main/scala/scalan/meta/SSymName.scala +++ b/sc/shared/src/main/scala/scalan/meta/SSymName.scala @@ -6,16 +6,11 @@ case class ImportItem(packageName: String, importedNames: List[String]) case class SSymName(packageName: String, name: String) { import SSymName._ - def this(name: String) = this("", name) def mkFullName = fullNameString(packageName, name) - def isImportedBy(item: ImportItem): Boolean = { - if (packageName != item.packageName) return false - item.importedNames.contains(SSymName.ImportAllWildcard) || item.importedNames.contains(name) - } } object SSymName { - /** Wildcard character used to signify imporing all names from namespace */ + /** Wildcard character used to signify importing all names from namespace */ val ImportAllWildcard = "*" def fullNameString(packageName: String, name: String): String = if (packageName.isNullOrEmpty) name else s"$packageName.$name" diff --git a/sc/shared/src/main/scala/scalan/primitives/Functions.scala b/sc/shared/src/main/scala/scalan/primitives/Functions.scala index e5cd6f345e..9026461777 100644 --- a/sc/shared/src/main/scala/scalan/primitives/Functions.scala +++ b/sc/shared/src/main/scala/scalan/primitives/Functions.scala @@ -16,12 +16,6 @@ trait Functions extends Base with ProgramGraphs { self: Scalan => /** Apply given function symbol to the given argument symbol. * @return symbol representing result of function application */ final def apply(x: Ref[A]): Ref[B] = mkApply(f, x) - - /** Build new function which applies `f` and then `g`*/ - final def >>[C](g: Ref[B => C]): Ref[A => C] = compose(g, f) - - /** Build new function which applies `g` and then `f`*/ - final def <<[C](g: Ref[C => A]): Ref[C => B] = compose(f, g) } /** Global lambda equality mode used by default. It is used in `fun` and `fun2` lambda builders. @@ -332,7 +326,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/staged/Transforming.scala b/sc/shared/src/main/scala/scalan/staged/Transforming.scala index 045340e503..a64b998ff6 100644 --- a/sc/shared/src/main/scala/scalan/staged/Transforming.scala +++ b/sc/shared/src/main/scala/scalan/staged/Transforming.scala @@ -47,9 +47,6 @@ trait Transforming { self: Scalan => constantPropagation: Boolean = true, /** Used in SlicingPass */ shouldSlice: Boolean = false) - { - def withConstantPropagation(value: Boolean) = this.copy(constantPropagation = value) - } /** Default pass to be used when IR is used without special compiler configuration. */ class DefaultPass(val name: String, override val config: PassConfig = PassConfig()) extends Pass @@ -65,10 +62,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 +145,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 +166,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 +183,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 +207,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 +223,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 +240,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 9c9fa5ffe1..5ddcdfa946 100644 --- a/sc/shared/src/main/scala/sigmastate/eval/GraphBuilding.scala +++ b/sc/shared/src/main/scala/sigmastate/eval/GraphBuilding.scala @@ -52,10 +52,6 @@ trait GraphBuilding extends SigmaLibrary { IR: IRContext => this.keepOriginalFunc = false // original lambda of Lambda node contains invocations of evalNode and we don't want that this.useAlphaEquality = false - /** Whether to create CostOf nodes or substutute costs from CostTable as constants in the graph. - * true - substitute; false - create CostOf nodes */ - var substFromCostTable: Boolean = true - /** Whether to save calcF and costF graphs in the file given by ScriptNameProp environment variable */ var saveGraphsInFile: Boolean = false @@ -380,8 +376,6 @@ trait GraphBuilding extends SigmaLibrary { IR: IRContext => 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 = CSigmaDslBuilder.toECPoint(g).asInstanceOf[EcPointType] def error(msg: String) = throw new GraphBuildingException(msg, None) @@ -436,7 +430,7 @@ trait GraphBuilding extends SigmaLibrary { IR: IRContext => error(s"Don't know how to buildNode($node)", node.sourceContext.toOption) val res: Ref[Any] = node match { - case c @ Constant(v, tpe) => v match { + case Constant(v, tpe) => v match { case p: SSigmaProp => assert(tpe == SSigmaProp) val resV = liftConst(p) @@ -887,7 +881,7 @@ trait GraphBuilding extends SigmaLibrary { IR: IRContext => f } - case l @ FuncValue(Seq((n, argTpe)), body) => + case FuncValue(Seq((n, argTpe)), body) => val eArg = stypeToElem(argTpe).asInstanceOf[Elem[Any]] val f = fun { x: Ref[Any] => buildNode(ctx, env + (n -> x), body) diff --git a/sc/shared/src/main/scala/sigmastate/eval/IRContext.scala b/sc/shared/src/main/scala/sigmastate/eval/IRContext.scala index b84098f2e7..597711d458 100644 --- a/sc/shared/src/main/scala/sigmastate/eval/IRContext.scala +++ b/sc/shared/src/main/scala/sigmastate/eval/IRContext.scala @@ -1,65 +1,25 @@ package sigmastate.eval import sigma.ast.TransformingSigmaBuilder -import sigma.data.CSigmaDslBuilder - -import java.util.concurrent.locks.ReentrantLock -import scala.util.Try /** Main interface of graph IR context which contain both GraphBuilding and TreeBuilding * methods. * It is not used in v5.0 interpreter and thus not part of consensus. * - * @see RuntimeIRContext, CompiletimeIRContext + * Used in ErgoScript compiler only. + * + * @see CompiletimeIRContext */ trait IRContext extends TreeBuilding with GraphBuilding { - import SigmaProp._ - - private val SigmaM = SigmaPropMethods - override val builder = TransformingSigmaBuilder - /** Can be used to synchronize access to this IR object from multiple threads. */ - val lock = new ReentrantLock() - /** Pass configuration which is used to turn-off constant propagation. + * USED IN TESTS ONLY. * @see `beginPass(noCostPropagationPass)` */ lazy val noConstPropagationPass = new DefaultPass( "noCostPropagationPass", Pass.defaultPassConfig.copy(constantPropagation = false)) - - /** The value of Global ErgoTree operation */ - val sigmaDslBuilderValue = CSigmaDslBuilder - - /** Finds SigmaProp.isProven method calls in the given Lambda `f` */ - def findIsProven[T](f: Ref[Context => T]): Option[Sym] = { - val Def(Lambda(lam,_,_,_)) = f - val s = lam.flatSchedule.find(sym => sym.node match { - case SigmaM.isValid(_) => true - case _ => false - }) - s - } - - /** Checks that if SigmaProp.isProven method calls exists in the given Lambda's schedule, - * then it is the last operation. */ - def verifyIsProven[T](f: Ref[Context => T]): Try[Unit] = { - val isProvenOpt = findIsProven(f) - Try { - isProvenOpt match { - case Some(s) => - if (f.getLambda.y != s) !!!(s"Sigma.isProven found in none-root position", s) - case None => - } - } - } -} - -/** IR context to be used by blockchain nodes to validate transactions. */ -class RuntimeIRContext extends IRContext { } /** IR context to be used by script development tools to compile ErgoScript into ErgoTree bytecode. */ -class CompiletimeIRContext extends IRContext { -} - +class CompiletimeIRContext extends IRContext diff --git a/sc/shared/src/main/scala/sigmastate/eval/SigmaLibrary.scala b/sc/shared/src/main/scala/sigmastate/eval/SigmaLibrary.scala index be17179cbf..7745873620 100644 --- a/sc/shared/src/main/scala/sigmastate/eval/SigmaLibrary.scala +++ b/sc/shared/src/main/scala/sigmastate/eval/SigmaLibrary.scala @@ -10,7 +10,7 @@ trait SigmaLibrary extends Library { import WRType._ - implicit lazy val wRTypeAnyElement = wRTypeElement(AnyElement) + implicit lazy val wRTypeAnyElement: Elem[WRType[Any]] = wRTypeElement(AnyElement) /** During compilation represent a global value Global, see also SGlobal type. */ def sigmaDslBuilder: Ref[SigmaDslBuilder] diff --git a/sc/shared/src/main/scala/sigmastate/eval/TreeBuilding.scala b/sc/shared/src/main/scala/sigmastate/eval/TreeBuilding.scala index 26bc33956f..27f659c1ed 100644 --- a/sc/shared/src/main/scala/sigmastate/eval/TreeBuilding.scala +++ b/sc/shared/src/main/scala/sigmastate/eval/TreeBuilding.scala @@ -161,7 +161,7 @@ trait TreeBuilding extends SigmaLibrary { IR: IRContext => case _ if env.contains(s) => val (id, tpe) = env(s) ValUse(id, tpe) // recursion base - case Def(Lambda(lam, _, x, y)) => + case Def(Lambda(lam, _, x, _)) => val varId = defId + 1 // arguments are treated as ValDefs and occupy id space val env1 = env + (x -> (varId, elemToSType(x.elem))) val block = processAstGraph(ctx, mainG, env1, lam, varId + 1, constantsProcessing) @@ -170,7 +170,7 @@ trait TreeBuilding extends SigmaLibrary { IR: IRContext => case Def(Apply(fSym, xSym, _)) => val Seq(f, x) = Seq(fSym, xSym).map(recurse) builder.mkApply(f, Array(x)) - case Def(th @ ThunkDef(root, _)) => + case Def(th @ ThunkDef(_, _)) => val block = processAstGraph(ctx, mainG, env, th, defId, constantsProcessing) block case Def(Const(x)) => @@ -449,7 +449,7 @@ trait TreeBuilding extends SigmaLibrary { IR: IRContext => (valdefs.toArray[BlockItem], rhs) match { // simple optimization to avoid producing block sub-expressions like: // `{ val idNew = id; idNew }` which this rules rewrites to just `id` - case (Array(ValDef(idNew, _, source @ ValUse(id, tpe))), ValUse(idUse, tpeUse)) + case (Array(ValDef(idNew, _, source @ ValUse(_, tpe))), ValUse(idUse, tpeUse)) if idUse == idNew && tpeUse == tpe => source case (items, _) => BlockValue(items, rhs) diff --git a/sc/shared/src/main/scala/sigmastate/lang/SigmaBinder.scala b/sc/shared/src/main/scala/sigmastate/lang/SigmaBinder.scala index f93e31703d..82aaea7e30 100644 --- a/sc/shared/src/main/scala/sigmastate/lang/SigmaBinder.scala +++ b/sc/shared/src/main/scala/sigmastate/lang/SigmaBinder.scala @@ -1,7 +1,6 @@ package sigmastate.lang import org.ergoplatform.ErgoAddressEncoder.NetworkPrefix -import org.ergoplatform._ import sigma.ast.NoType import sigma.data.Nullable import sigma.kiama.rewriting.CallbackRewriter diff --git a/sc/shared/src/main/scala/special/collection/CollsUnit.scala b/sc/shared/src/main/scala/special/collection/CollsUnit.scala index 02e62aeb4d..90f0dca99e 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]; @@ -37,7 +34,5 @@ package sigma { def xor(left: Ref[Coll[Byte]], right: Ref[Coll[Byte]]): Ref[Coll[Byte]]; def replicate[T](n: Ref[Int], v: Ref[T]): Ref[Coll[T]]; }; - trait CollCompanion; - trait CollBuilderCompanion } } \ No newline at end of file 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..70fb35c329 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 @@ -1918,7 +1915,6 @@ object SigmaDslBuilder extends EntityObject("SigmaDslBuilder") { } override def substConstants[T](scriptBytes: Ref[Coll[Byte]], positions: Ref[Coll[Int]], newValues: Ref[Coll[T]]): Ref[Coll[Byte]] = { - implicit val eT = newValues.eA asRep[Coll[Byte]](mkMethodCall(self, SigmaDslBuilderClass.getMethod("substConstants", classOf[Sym], classOf[Sym], classOf[Sym]), Array[AnyRef](scriptBytes, positions, newValues), @@ -2078,7 +2074,6 @@ object SigmaDslBuilder extends EntityObject("SigmaDslBuilder") { } def substConstants[T](scriptBytes: Ref[Coll[Byte]], positions: Ref[Coll[Int]], newValues: Ref[Coll[T]]): Ref[Coll[Byte]] = { - implicit val eT = newValues.eA asRep[Coll[Byte]](mkMethodCall(source, SigmaDslBuilderClass.getMethod("substConstants", classOf[Sym], classOf[Sym], classOf[Sym]), Array[AnyRef](scriptBytes, positions, newValues), @@ -2281,16 +2276,6 @@ object SigmaDslBuilder extends EntityObject("SigmaDslBuilder") { def unapply(exp: Sym): Nullable[(Ref[SigmaDslBuilder], Ref[GroupElement], Ref[GroupElement], Ref[GroupElement], Ref[GroupElement])] = unapply(exp.node) } - object groupGenerator { - def unapply(d: Def[_]): Nullable[Ref[SigmaDslBuilder]] = d match { - case MethodCall(receiver, method, _, _) if method.getName == "groupGenerator" && receiver.elem.isInstanceOf[SigmaDslBuilderElem[_]] => - val res = receiver - Nullable(res).asInstanceOf[Nullable[Ref[SigmaDslBuilder]]] - case _ => Nullable.None - } - def unapply(exp: Sym): Nullable[Ref[SigmaDslBuilder]] = unapply(exp.node) - } - object substConstants { def unapply(d: Def[_]): Nullable[(Ref[SigmaDslBuilder], Ref[Coll[Byte]], Ref[Coll[Int]], Ref[Coll[T]]) forSome {type T}] = d match { case MethodCall(receiver, method, args, _) if method.getName == "substConstants" && receiver.elem.isInstanceOf[SigmaDslBuilderElem[_]] => diff --git a/sc/shared/src/test/scala/scalan/LibraryTests.scala b/sc/shared/src/test/scala/scalan/LibraryTests.scala index e082e9154d..d095a2f20a 100644 --- a/sc/shared/src/test/scala/scalan/LibraryTests.scala +++ b/sc/shared/src/test/scala/scalan/LibraryTests.scala @@ -8,7 +8,7 @@ class Benchmark[T <: Scalan](createContext: => T) { def run() = { val (ctx, total) = measureTime { var ctx = createContext - measure(10000, okShowIterTime = printDebugInfo, okShowTotalTime = printDebugInfo) { i => + measure(10000, okShowIterTime = printDebugInfo, okShowTotalTime = printDebugInfo) { _ => ctx = createContext } ctx diff --git a/sc/shared/src/test/scala/sigma/SigmaDslSpecification.scala b/sc/shared/src/test/scala/sigma/SigmaDslSpecification.scala index 4dd576f03a..c820e65e73 100644 --- a/sc/shared/src/test/scala/sigma/SigmaDslSpecification.scala +++ b/sc/shared/src/test/scala/sigma/SigmaDslSpecification.scala @@ -5081,7 +5081,7 @@ class SigmaDslSpecification extends SigmaDslTesting newCost = 1766, newVersionedResults = { val res = (ExpectedResult(Success(0), Some(1766)) -> Some(selfCostDetails)) - Seq(0, 1, 2).map(version => version -> res) + Seq(0, 1, 2, 3).map(version => version -> res) })) ), changedFeature({ (x: Context) => x.selfBoxIndex }, @@ -5280,7 +5280,7 @@ class SigmaDslSpecification extends SigmaDslTesting Seq( ctx -> Expected(Failure(expectedError), 0, CostDetails.ZeroCost, 1793, newVersionedResults = { - Seq.tabulate(3)(v => v -> (ExpectedResult(Success(true), Some(1793)) -> None)) + Seq.tabulate(4)(v => v -> (ExpectedResult(Success(true), Some(1793)) -> None)) } ) ), @@ -6233,7 +6233,7 @@ class SigmaDslSpecification extends SigmaDslTesting cost = c, expectedDetails = CostDetails.ZeroCost, newCost = 1766, - newVersionedResults = Seq(0, 1, 2).map(i => i -> (ExpectedResult(Success(newV), Some(1766)) -> Some(cd))) + newVersionedResults = Seq(0, 1, 2, 3).map(i => i -> (ExpectedResult(Success(newV), Some(1766)) -> Some(cd))) ) Seq( (Coll[Boolean](), successNew(false, 1766, newV = false, costDetails(0))), @@ -6511,7 +6511,7 @@ class SigmaDslSpecification extends SigmaDslTesting newCost = 1769, newVersionedResults = { val res = (ExpectedResult(Success(Helpers.decodeBytes("00")), Some(1769)), Some(costDetails(1))) - Seq(0, 1, 2).map(version => version -> res) + Seq(0, 1, 2, 3).map(version => version -> res) } )), ((Helpers.decodeBytes("800136fe89afff802acea67128a0ff007fffe3498c8001806080012b"), @@ -9120,7 +9120,7 @@ class SigmaDslSpecification extends SigmaDslTesting cost = 0, expectedDetails = CostDetails.ZeroCost, newCost = 1766, - newVersionedResults = Seq.tabulate(3)(v => v -> (ExpectedResult(Success(5L), Some(1766)) -> Some(costDetails1))) + newVersionedResults = Seq.tabulate(4)(v => v -> (ExpectedResult(Success(5L), Some(1766)) -> Some(costDetails1))) )), (Some(0L) -> Expected( Success(1L), @@ -9679,7 +9679,7 @@ class SigmaDslSpecification extends SigmaDslTesting newCost = 1783, newVersionedResults = { val res = (ExpectedResult(Success(Helpers.decodeBytes("0008d3")), Some(1783)) -> Some(costDetails(0))) - Seq(0, 1, 2).map(version => version -> res) + Seq(0, 1, 2, 3).map(version => version -> res) }), (Helpers.decodeBytes("000008d3"), 0) -> Expected( @@ -9690,7 +9690,7 @@ class SigmaDslSpecification extends SigmaDslTesting newVersionedResults = { // since the tree without constant segregation, substitution has no effect val res = (ExpectedResult(Success(Helpers.decodeBytes("000008d3")), Some(1783)) -> Some(costDetails(0))) - Seq(0, 1, 2).map(version => version -> res) + Seq(0, 1, 2, 3).map(version => version -> res) }), // tree with segregation flag, empty constants array (Coll(t2.bytes:_*), 0) -> success(Helpers.decodeBytes("100008d3"), costDetails(0), 1783), @@ -9761,7 +9761,7 @@ class SigmaDslSpecification extends SigmaDslTesting cost = 1776, expectedDetails = CostDetails.ZeroCost, newCost = 1776, - newVersionedResults = (0 to 2).map(i => i -> (ExpectedResult(Success(true), Some(1776)) -> Some(costDetails))) + newVersionedResults = Seq(0, 1, 2, 3).map(i => i -> (ExpectedResult(Success(true), Some(1776)) -> Some(costDetails))) ) ), changedFeature( diff --git a/sc/shared/src/test/scala/sigma/SigmaDslStaginTests.scala b/sc/shared/src/test/scala/sigma/SigmaDslStaginTests.scala index 5ac9b80889..91178b2b67 100644 --- a/sc/shared/src/test/scala/sigma/SigmaDslStaginTests.scala +++ b/sc/shared/src/test/scala/sigma/SigmaDslStaginTests.scala @@ -28,8 +28,8 @@ class SigmaDslStaginTests extends BaseCtxTests with ErgoScriptTestkit with BaseL type RContext = cake.Context type RBox = cake.Box type RSigmaProp = cake.SigmaProp - val boxA1 = newAliceBox(1, 100) - val boxA2 = newAliceBox(2, 200) + val boxA1 = newAliceBox(100) + val boxA2 = newAliceBox(200) val ctx: SContext = newContext(10, boxA1, VersionContext.MaxSupportedScriptVersion, VersionContext.MaxSupportedScriptVersion) .withInputs(boxA2) .withVariables(Map(1 -> toAnyValue(30), 2 -> toAnyValue(40))) diff --git a/sc/shared/src/test/scala/sigmastate/ErgoTreeSpecification.scala b/sc/shared/src/test/scala/sigmastate/ErgoTreeSpecification.scala index 0b3e275985..b0b6273fad 100644 --- a/sc/shared/src/test/scala/sigmastate/ErgoTreeSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/ErgoTreeSpecification.scala @@ -332,7 +332,6 @@ class ErgoTreeSpecification extends SigmaDslTesting with ContractsTestkit { ), true) }, - { // SBigInt inherit methods from SNumericType.methods // however they are not resolvable via SBigInt.typeId import SNumericTypeMethods._ diff --git a/sc/shared/src/test/scala/sigmastate/ScriptVersionSwitchSpecification.scala b/sc/shared/src/test/scala/sigmastate/ScriptVersionSwitchSpecification.scala index b0206fa464..aedf35e914 100644 --- a/sc/shared/src/test/scala/sigmastate/ScriptVersionSwitchSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/ScriptVersionSwitchSpecification.scala @@ -276,13 +276,14 @@ class ScriptVersionSwitchSpecification extends SigmaDslTesting { * 20 | 4 | mined | Script v3 | v5.0 | skip-accept (rely on majority) */ property("Rules 19,20 | Block v4 | candidate or mined block | Script v3") { - forEachActivatedScriptVersion(activatedVers = Array[Byte](3)) // version for Block v4 + forEachActivatedScriptVersion(activatedVers = Array[Byte](4)) // activated version is greater then MaxSupported { - forEachErgoTreeVersion(ergoTreeVers = Array[Byte](3, 4)) { // scripts >= v3 + forEachErgoTreeVersion(ergoTreeVers = Array[Byte](4, 5)) { // tree version >= activated val headerFlags = ErgoTree.defaultHeaderWithVersion(ergoTreeVersionInTests) val ergoTree = createErgoTree(headerFlags) - // prover is rejecting, because such context parameters doesn't make sense + // prover is rejecting, because it cannot generate proofs for ErgoTrees with version + // higher than max supported by the interpreter assertExceptionThrown( testProve(ergoTree, activatedScriptVersion = activatedVersionInTests), exceptionLike[InterpreterException](s"Both ErgoTree version ${ergoTree.version} and activated version $activatedVersionInTests is greater than MaxSupportedScriptVersion $MaxSupportedScriptVersion") diff --git a/sc/shared/src/test/scala/sigmastate/SoftForkabilitySpecification.scala b/sc/shared/src/test/scala/sigmastate/SoftForkabilitySpecification.scala index bca2d0e638..c8b9f06399 100644 --- a/sc/shared/src/test/scala/sigmastate/SoftForkabilitySpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/SoftForkabilitySpecification.scala @@ -29,7 +29,7 @@ class SoftForkabilitySpecification extends SigmaTestingData with CompilerTestingCommons with BeforeAndAfterAll { - implicit lazy val IR: TestingIRContext = new TestingIRContext + val IR: TestingIRContext = new TestingIRContext lazy val prover = new ErgoLikeTestProvingInterpreter() lazy val verifier = new ErgoLikeTestInterpreter val deadline = 100 @@ -38,7 +38,7 @@ class SoftForkabilitySpecification extends SigmaTestingData lazy val booleanPropV1 = compile(emptyEnv + ("deadline" -> deadline), """{ | HEIGHT > deadline && OUTPUTS.size == 1 - |}""".stripMargin).asBoolValue + |}""".stripMargin)(IR).asBoolValue // cast Boolean typed prop to SigmaProp (which is invalid) // ErgoTree v0 lazy val invalidPropV1: ErgoTree = diff --git a/sc/shared/src/test/scala/sigmastate/TestingInterpreterSpecification.scala b/sc/shared/src/test/scala/sigmastate/TestingInterpreterSpecification.scala index fe5a678679..446f1972a7 100644 --- a/sc/shared/src/test/scala/sigmastate/TestingInterpreterSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/TestingInterpreterSpecification.scala @@ -22,15 +22,12 @@ import scala.util.Random class TestingInterpreterSpecification extends CompilerTestingCommons with CompilerCrossVersionProps with BeforeAndAfterAll { - implicit lazy val IR: TestingIRContext = new TestingIRContext - lazy val prover = new ErgoLikeTestProvingInterpreter() { - } + val IR: TestingIRContext = new TestingIRContext - lazy val verifier = new ErgoLikeTestInterpreter { - } + lazy val prover = new ErgoLikeTestProvingInterpreter() - implicit val soundness: Int = CryptoConstants.soundnessBits + lazy val verifier = new ErgoLikeTestInterpreter def testingContext(h: Int) = ErgoLikeContextTesting(h, @@ -128,7 +125,7 @@ class TestingInterpreterSpecification extends CompilerTestingCommons "box1" -> testBox(10, TrueTree, 0, Seq(), Map( reg1 -> IntArrayConstant(Array[Int](1, 2, 3)), reg2 -> BoolArrayConstant(Array[Boolean](true, false, true))))) - val prop = mkTestErgoTree(compile(env, code).asBoolValue.toSigmaProp) + val prop = mkTestErgoTree(compile(env, code)(IR).asBoolValue.toSigmaProp) val challenge = Array.fill(32)(Random.nextInt(100).toByte) val proof1 = prover.prove(prop, ctx, challenge).get.proof verifier.verify(Interpreter.emptyEnv, prop, ctx, proof1, challenge) diff --git a/sc/shared/src/test/scala/sigmastate/eval/ErgoScriptTestkit.scala b/sc/shared/src/test/scala/sigmastate/eval/ErgoScriptTestkit.scala index abbed09992..a10a717d2f 100644 --- a/sc/shared/src/test/scala/sigmastate/eval/ErgoScriptTestkit.scala +++ b/sc/shared/src/test/scala/sigmastate/eval/ErgoScriptTestkit.scala @@ -21,7 +21,7 @@ import sigmastate.CompilerTestsBase import sigma.{ContractsTestkit, Context => DContext} import scala.annotation.unused -import scala.util.Success +import scala.util.{Success, Try} trait ErgoScriptTestkit extends ContractsTestkit with LangTests with ValidationSpecification with CompilerTestsBase { self: BaseCtxTests => @@ -54,9 +54,8 @@ trait ErgoScriptTestkit extends ContractsTestkit with LangTests ergoCtx } - - lazy val boxA1 = newAliceBox(1, 100) - lazy val boxA2 = newAliceBox(2, 200) + lazy val boxA1 = newAliceBox(100) + lazy val boxA2 = newAliceBox(200) lazy val n1Sym = liftConst(n1) @@ -147,6 +146,31 @@ trait ErgoScriptTestkit extends ContractsTestkit with LangTests res } + private val SigmaM = SigmaProp.SigmaPropMethods + + /** Finds SigmaProp.isProven method calls in the given Lambda `f` */ + private def findIsProven[T](f: Ref[Context => T]): Option[Sym] = { + val Def(Lambda(lam,_,_,_)) = f + val s = lam.flatSchedule.find(sym => sym.node match { + case SigmaM.isValid(_) => true + case _ => false + }) + s + } + + /** Checks that if SigmaProp.isProven method calls exists in the given Lambda's schedule, + * then it is the last operation. */ + private def verifyIsProven[T](f: Ref[Context => T]): Try[Unit] = { + val isProvenOpt = findIsProven(f) + Try { + isProvenOpt match { + case Some(s) => + if (f.getLambda.y != s) !!!(s"Sigma.isProven found in none-root position", s) + case None => + } + } + } + def doReduce(): Unit = { val res = doCosting verifyIsProven(res.compiledGraph) shouldBe Success(()) @@ -183,13 +207,6 @@ trait ErgoScriptTestkit extends ContractsTestkit with LangTests } } - def Case(env: ScriptEnv, name: String, script: String, ctx: ErgoLikeContext, - calc: Ref[Context] => Ref[Any], - tree: SValue, - result: Result) = - EsTestCase(name, env, Code(script), Option(ctx), None, - Option(calc), Option(tree), result) - def reduce(env: ScriptEnv, name: String, script: String, ergoCtx: ErgoLikeContext, expectedResult: Any): Unit = { val tcase = EsTestCase(name, env, Code(script), Some(ergoCtx), expectedResult = Result(expectedResult)) tcase.doReduce() diff --git a/sc/shared/src/test/scala/sigmastate/eval/EvaluationTest.scala b/sc/shared/src/test/scala/sigmastate/eval/EvaluationTest.scala index 5fcbd0f220..f9a7edf0cb 100644 --- a/sc/shared/src/test/scala/sigmastate/eval/EvaluationTest.scala +++ b/sc/shared/src/test/scala/sigmastate/eval/EvaluationTest.scala @@ -81,24 +81,6 @@ class EvaluationTest extends BaseCtxTests | f(SELF) || g(SELF.R5[Coll[Int]].get) | }""".stripMargin, ctx, true) } - - test("Measure IRContext creation speed") { - var ctx: RuntimeIRContext = new RuntimeIRContext - measure(100, okShowIterTime = printDebugInfo, okShowTotalTime = printDebugInfo) { i => - ctx = new RuntimeIRContext - } - printDebug(s"Def count: ${ctx.defCount}") - /* - Iter 0: 4 ms - ... - Iter 96: 2 ms - Iter 97: 1 ms - Iter 98: 2 ms - Iter 99: 2 ms - Total time: 244 ms - Def count: 20 - */ - } test("SubstConst") { def script(pk: ProveDlog): SigmaPropValue = diff --git a/sc/shared/src/test/scala/sigmastate/eval/MeasureIRContext.scala b/sc/shared/src/test/scala/sigmastate/eval/MeasureIRContext.scala deleted file mode 100644 index 9f88588cc9..0000000000 --- a/sc/shared/src/test/scala/sigmastate/eval/MeasureIRContext.scala +++ /dev/null @@ -1,36 +0,0 @@ -package sigmastate.eval - -import scalan.{BaseCtxTests, Benchmark} -import sigma.util.BenchmarkUtil.measure - -object MeasureIRContext extends App { - var ctx: RuntimeIRContext = null - measure(1, false) { i => - ctx = new RuntimeIRContext - } - measure(10000, false) { i => - ctx = new RuntimeIRContext - } - print(s"Def count: ${ctx.defCount}") - /* - Total time: 2485 ms - Total time: 2714 ms - Def count: 20 - */ -} - -class SigmaLibraryTests extends BaseCtxTests { - - test("Benchmark SigmaLibrary creation time") { - new Benchmark(new RuntimeIRContext).run() - } -} - -object MeasureSigmaLibraryCreate extends App { - new Benchmark(new RuntimeIRContext).run() - /* - Total time: 12932 ms - Def count: 20, total: 15774 msec - */ -} - diff --git a/sc/shared/src/test/scala/sigmastate/helpers/CompilerTestingCommons.scala b/sc/shared/src/test/scala/sigmastate/helpers/CompilerTestingCommons.scala index 332ee902a2..6c3708b782 100644 --- a/sc/shared/src/test/scala/sigmastate/helpers/CompilerTestingCommons.scala +++ b/sc/shared/src/test/scala/sigmastate/helpers/CompilerTestingCommons.scala @@ -29,8 +29,7 @@ trait CompilerTestingCommons extends TestingCommons with TestUtils with TestContexts with ValidationSpecification with CompilerTestsBase { - class TestingIRContext extends TestContext with IRContext { - } + class TestingIRContext extends TestContext with IRContext case class CompiledFunc[A,B] (script: String, bindings: Seq[VarBinding], expr: SValue, compiledTree: SValue, func: A => (B, CostDetails)) diff --git a/sc/shared/src/test/scala/sigmastate/lang/SigmaCompilerTest.scala b/sc/shared/src/test/scala/sigmastate/lang/SigmaCompilerTest.scala index 88c75a90b6..90e5d21b1e 100644 --- a/sc/shared/src/test/scala/sigmastate/lang/SigmaCompilerTest.scala +++ b/sc/shared/src/test/scala/sigmastate/lang/SigmaCompilerTest.scala @@ -12,6 +12,8 @@ import sigma.ast.{Apply, MethodCall, ZKProofBlock} import sigma.exceptions.{GraphBuildingException, InvalidArguments, TyperException} import sigma.serialization.ValueSerializer import sigma.serialization.generators.ObjectGenerators + +import java.math.BigInteger import scala.annotation.unused class SigmaCompilerTest extends CompilerTestingCommons with LangTests with ObjectGenerators { @@ -127,6 +129,13 @@ class SigmaCompilerTest extends CompilerTestingCommons with LangTests with Objec res shouldEqual SigmaPropConstant(dk1) } + property("bigInt") { + comp(""" bigInt("326674862673836209462483453386286740270338859283019276168539876024851191344") """) shouldBe + BigIntConstant(new BigInteger("326674862673836209462483453386286740270338859283019276168539876024851191344")) + comp(""" bigInt("-10") """) shouldBe + BigIntConstant(-10L) + } + property("fromBaseX") { comp(""" fromBase16("31") """) shouldBe ByteArrayConstant(Array[Byte](49)) comp(""" fromBase58("r") """) shouldBe ByteArrayConstant(Array[Byte](49)) diff --git a/sc/shared/src/test/scala/sigmastate/lang/SigmaTyperTest.scala b/sc/shared/src/test/scala/sigmastate/lang/SigmaTyperTest.scala index 99ad2ae908..a474727943 100644 --- a/sc/shared/src/test/scala/sigmastate/lang/SigmaTyperTest.scala +++ b/sc/shared/src/test/scala/sigmastate/lang/SigmaTyperTest.scala @@ -113,6 +113,7 @@ class SigmaTyperTest extends AnyPropSpec typecheck(env, "min(HEIGHT, INPUTS.size)") shouldBe SInt typecheck(env, "max(1, 2)") shouldBe SInt typecheck(env, "max(1L, 2)") shouldBe SLong + typecheck(env, """bigInt("1111")""") shouldBe SBigInt typecheck(env, """fromBase16("1111")""") shouldBe SByteArray typecheck(env, """fromBase58("111")""") shouldBe SByteArray typecheck(env, """fromBase64("111")""") shouldBe SByteArray diff --git a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala index 346ad69e1a..79701d6e07 100644 --- a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala @@ -5,7 +5,7 @@ import org.ergoplatform._ import sigma.Extensions.ArrayOps import sigma.ast.SCollection.SByteArray import sigma.ast.SType.AnyOps -import sigma.data.{AvlTreeData, CAnyValue} +import sigma.data.{AvlTreeData, CAnyValue, CSigmaDslBuilder} import sigma.util.StringUtil._ import sigma.ast._ import sigma.ast.syntax._ @@ -339,7 +339,7 @@ class BasicOpsSpecification extends CompilerTestingCommons }) val dataVar = (lastExtVar + 1).toByte - val Colls = IR.sigmaDslBuilderValue.Colls + val Colls = CSigmaDslBuilder.Colls implicit val eAny = sigma.AnyType val data = Colls.fromItems((Array[Byte](1,2,3).toColl, 10L)) val env1 = env + ("dataVar" -> CAnyValue(dataVar)) 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 f6393f62bb..0f50a52686 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,75 +1,29 @@ 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.wallet.protocol.context -import scorex.crypto.authds.ADKey -import scorex.util.ModifierId -import scorex.util.encode.Base16 -import sigma.Extensions.CollBytesOps -import sigma.ast.syntax.GroupElementConstant -import sigma.ast.{Constant, GroupElementConstant, SType} +import sigma.ast.{Constant, SType} +import sigma.data.Iso import sigma.data.Iso.{isoStringToArray, isoStringToColl} -import sigma.data.{CBigInt, CGroupElement, Digest32Coll, Digest32CollRType, Iso} +import sigma.data.js.{Isos => DataIsos} import sigma.interpreter.{ContextExtension, ProverResult} -import sigma.js.{AvlTree, GroupElement} -import sigma.serialization.{ErgoTreeSerializer, ValueSerializer} -import sigma.{Coll, Colls} +import sigma.js.AvlTree 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.{SignedTransaction, UnsignedTransaction} -import sigmastate.fleetSdkCommon.{distEsmTypesBoxesMod => boxesMod, distEsmTypesCommonMod => commonMod, distEsmTypesContextExtensionMod => contextExtensionMod, distEsmTypesInputsMod => inputsMod, distEsmTypesProverResultMod => proverResultMod, distEsmTypesRegistersMod => registersMod, distEsmTypesTokenMod => tokenMod} +import sigmastate.fleetSdkCommon.{distEsmTypesCommonMod => commonMod, distEsmTypesContextExtensionMod => contextExtensionMod, distEsmTypesInputsMod => inputsMod, distEsmTypesProverResultMod => proverResultMod} -import java.math.BigInteger import scala.collection.immutable.ListMap import scala.scalajs.js import scala.scalajs.js.Object -/** Definitions of isomorphisms. */ +/** Definitions of isomorphisms for sigma-sdk module. + * @see sigma.data.Iso + */ object Isos { - val isoStringToGroupElement: Iso[String, sigma.GroupElement] = new Iso[String, sigma.GroupElement] { - override def to(x: String): sigma.GroupElement = { - val bytes = Base16.decode(x).get - ValueSerializer.deserialize(bytes).asInstanceOf[GroupElementConstant].value - } - override def from(x: sigma.GroupElement): String = { - val bytes = ValueSerializer.serialize(GroupElementConstant(x)) - Base16.encode(bytes) - } - } - - val isoGroupElement: Iso[GroupElement, sigma.GroupElement] = new Iso[GroupElement, sigma.GroupElement] { - override def to(x: GroupElement): sigma.GroupElement = { - CGroupElement(x.point) - } - override def from(x: sigma.GroupElement): GroupElement = { - new GroupElement(x.asInstanceOf[CGroupElement].wrappedValue) - } - } - - implicit val isoBoxId: Iso[boxesMod.BoxId, ErgoBox.BoxId] = new Iso[boxesMod.BoxId, ErgoBox.BoxId] { - override def to(x: boxesMod.BoxId): ErgoBox.BoxId = ADKey @@@ isoStringToArray.to(x) - - override def from(x: ErgoBox.BoxId): boxesMod.BoxId = isoStringToArray.from(x) - } - - implicit val isoHexStringToConstant: Iso[HexString, Constant[SType]] = new Iso[HexString, Constant[SType]] { - override def to(x: HexString): Constant[SType] = { - val bytes = isoStringToArray.to(x) - val value = ValueSerializer.deserialize(bytes) - value.asInstanceOf[Constant[SType]] - } - override def from(x: Constant[SType]): HexString = { - val bytes = ValueSerializer.serialize(x) - isoStringToArray.from(bytes) - } - } - implicit val isoHeader: Iso[Header, sigma.Header] = new Iso[Header, sigma.Header] { override def to(a: Header): sigma.Header = { CHeader( @@ -83,8 +37,8 @@ object Isos { 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), + minerPk = DataIsos.isoGroupElement.to(a.minerPk), + powOnetimePk = DataIsos.isoGroupElement.to(a.powOnetimePk), powNonce = isoStringToColl.to(a.powNonce), powDistance = sigma.js.Isos.isoBigInt.to(a.powDistance), votes = isoStringToColl.to(a.votes) @@ -103,8 +57,8 @@ object Isos { 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), + minerPk = DataIsos.isoGroupElement.from(header.minerPk), + powOnetimePk = DataIsos.isoGroupElement.from(header.powOnetimePk), powNonce = isoStringToColl.from(header.powNonce), powDistance = sigma.js.Isos.isoBigInt.from(header.powDistance), votes = isoStringToColl.from(header.votes) @@ -120,7 +74,7 @@ object Isos { timestamp = sigma.js.Isos.isoBigIntToLong.to(a.timestamp), nBits = sigma.js.Isos.isoBigIntToLong.to(a.nBits), height = a.height, - minerPk = isoGroupElement.to(a.minerPk), + minerPk = DataIsos.isoGroupElement.to(a.minerPk), votes = isoStringToColl.to(a.votes) ) } @@ -132,7 +86,7 @@ object Isos { timestamp = sigma.js.Isos.isoBigIntToLong.from(header.timestamp), nBits = sigma.js.Isos.isoBigIntToLong.from(header.nBits), height = header.height, - minerPk = isoGroupElement.from(header.minerPk), + minerPk = DataIsos.isoGroupElement.from(header.minerPk), votes = isoStringToColl.from(header.votes) ) } @@ -195,7 +149,7 @@ object Isos { val keys = js.Object.keys(x).sorted for ( k <- keys ) { val id = k.toInt.toByte - val c = isoHexStringToConstant.to(x.apply(id).get.get) + val c = DataIsos.isoHexStringToConstant.to(x.apply(id).get.get) map = map + (id -> c) } ContextExtension(map) @@ -204,7 +158,7 @@ object Isos { override def from(x: ContextExtension): contextExtensionMod.ContextExtension = { val res = new Object().asInstanceOf[contextExtensionMod.ContextExtension] x.values.foreach { case (k, v: Constant[_]) => - val hex = isoHexStringToConstant.from(v) + val hex = DataIsos.isoHexStringToConstant.from(v) res.update(k, hex) } res @@ -213,10 +167,10 @@ object Isos { implicit val isoUnsignedInput: Iso[inputsMod.UnsignedInput, UnsignedInput] = new Iso[inputsMod.UnsignedInput, UnsignedInput] { override def to(x: inputsMod.UnsignedInput): UnsignedInput = - new UnsignedInput(x.boxId.convertTo[ErgoBox.BoxId], isoContextExtension.to(x.extension)) + new UnsignedInput(DataIsos.isoBoxId.to(x.boxId), isoContextExtension.to(x.extension)) override def from(x: UnsignedInput): inputsMod.UnsignedInput = - inputsMod.UnsignedInput(x.boxId.convertTo[boxesMod.BoxId], isoContextExtension.from(x.extension)) + inputsMod.UnsignedInput(DataIsos.isoBoxId.from(x.boxId), isoContextExtension.from(x.extension)) } implicit val isoProverResult: Iso[proverResultMod.ProverResult, ProverResult] = new Iso[proverResultMod.ProverResult, ProverResult] { @@ -236,135 +190,17 @@ object Isos { implicit val isoSignedInput: Iso[inputsMod.SignedInput, Input] = new Iso[inputsMod.SignedInput, Input] { override def to(x: inputsMod.SignedInput): Input = - Input(x.boxId.convertTo[ErgoBox.BoxId], isoProverResult.to(x.spendingProof)) + Input(DataIsos.isoBoxId.to(x.boxId), isoProverResult.to(x.spendingProof)) override def from(x: Input): inputsMod.SignedInput = - inputsMod.SignedInput(x.boxId.convertTo[boxesMod.BoxId], isoProverResult.from(x.spendingProof)) + inputsMod.SignedInput(DataIsos.isoBoxId.from(x.boxId), isoProverResult.from(x.spendingProof)) } implicit val isoDataInput: Iso[inputsMod.DataInput, DataInput] = new Iso[inputsMod.DataInput, DataInput] { - override def to(x: inputsMod.DataInput): DataInput = DataInput(x.boxId.convertTo[ErgoBox.BoxId]) - - override def from(x: DataInput): inputsMod.DataInput = inputsMod.DataInput(x.boxId.convertTo[boxesMod.BoxId]) - } - - 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 - case _ => java.lang.Long.parseLong(x.asInstanceOf[js.BigInt].toString(10)) - } - override def from(x: Long): commonMod.Amount = x.toString - } - - implicit val isoToken: Iso[tokenMod.TokenAmount[commonMod.Amount], Token] = - new Iso[tokenMod.TokenAmount[commonMod.Amount], Token] { - override def to(x: tokenMod.TokenAmount[commonMod.Amount]): Token = - (Digest32Coll @@@ Colls.fromArray(Base16.decode(x.tokenId).get), isoAmount.to(x.amount)) - - override def from(x: Token): tokenMod.TokenAmount[commonMod.Amount] = - tokenMod.TokenAmount[commonMod.Amount](isoAmount.from(x._2), x._1.toHex) - } - - 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] = { - sigma.js.Isos.isoArrayToColl(isoToken).to(x) - } - override def from(x: Coll[Token]): js.Array[tokenMod.TokenAmount[commonMod.Amount]] = { - sigma.js.Isos.isoArrayToColl(isoToken).from(x) - } - } - - val isoNonMandatoryRegisters: Iso[registersMod.NonMandatoryRegisters, AdditionalRegisters] = - new Iso[registersMod.NonMandatoryRegisters, AdditionalRegisters] { - override def to(x: registersMod.NonMandatoryRegisters): AdditionalRegisters = { - val regs = Seq( - x.R4 -> R4, - x.R5 -> R5, - x.R6 -> R6, - x.R7 -> R7, - x.R8 -> R8, - x.R9 -> R9 - ).collect { - case (regOpt, id) if regOpt.isDefined => id -> isoHexStringToConstant.to(regOpt.get) - } - Map(regs:_*) - } - override def from(regs: AdditionalRegisters): registersMod.NonMandatoryRegisters = { - def regHexOpt(t: NonMandatoryRegisterId): Option[HexString] = - regs.get(t).map(v => isoHexStringToConstant.from(v.asInstanceOf[Constant[SType]])) - - val resRegs = NonMandatoryRegisters() - regHexOpt(R4).foreach(resRegs.setR4(_)) - regHexOpt(R5).foreach(resRegs.setR5(_)) - regHexOpt(R6).foreach(resRegs.setR6(_)) - regHexOpt(R7).foreach(resRegs.setR7(_)) - regHexOpt(R8).foreach(resRegs.setR8(_)) - regHexOpt(R9).foreach(resRegs.setR9(_)) - resRegs - } - } - - implicit val isoBoxCandidate: Iso[boxesMod.BoxCandidate[commonMod.Amount, NonMandatoryRegisters], ErgoBoxCandidate] = new Iso[boxesMod.BoxCandidate[commonMod.Amount, NonMandatoryRegisters], ErgoBoxCandidate] { - override def to(x: boxesMod.BoxCandidate[commonMod.Amount, NonMandatoryRegisters]): ErgoBoxCandidate = { - val ergoBoxCandidate = new ErgoBoxCandidate( - value = isoAmount.to(x.value), - ergoTree = { - val bytes = Base16.decode(x.ergoTree).get - ErgoTreeSerializer.DefaultSerializer.deserializeErgoTree(bytes) - }, - x.creationHeight.toInt, - additionalTokens = isoTokenArray.to(x.assets), - additionalRegisters = isoNonMandatoryRegisters.to(x.additionalRegisters) - ) - ergoBoxCandidate - } - - override def from(x: ErgoBoxCandidate): boxesMod.BoxCandidate[commonMod.Amount, NonMandatoryRegisters] = { - val ergoTree = ErgoTreeSerializer.DefaultSerializer.serializeErgoTree(x.ergoTree) - val ergoTreeStr = Base16.encode(ergoTree) - val assets = isoTokenArray.from(x.additionalTokens) - boxesMod.BoxCandidate[commonMod.Amount, NonMandatoryRegisters]( - ergoTree = ergoTreeStr, - value = isoAmount.from(x.value), - assets = assets, - creationHeight = x.creationHeight, - additionalRegisters = isoNonMandatoryRegisters.from(x.additionalRegisters) - ) - } - } + override def to(x: inputsMod.DataInput): DataInput = + DataInput(DataIsos.isoBoxId.to(x.boxId)) - val isoBox: Iso[Box[commonMod.Amount, NonMandatoryRegisters], ErgoBox] = new Iso[Box[commonMod.Amount, NonMandatoryRegisters], ErgoBox] { - override def to(x: Box[commonMod.Amount, NonMandatoryRegisters]): ErgoBox = { - val ergoBox = new ErgoBox( - value = isoAmount.to(x.value), - ergoTree = { - val bytes = Base16.decode(x.ergoTree).get - ErgoTreeSerializer.DefaultSerializer.deserializeErgoTree(bytes) - }, - creationHeight = x.creationHeight.toInt, - additionalTokens = isoTokenArray.to(x.assets), - additionalRegisters = isoNonMandatoryRegisters.to(x.additionalRegisters), - transactionId = ModifierId @@ x.transactionId, - index = x.index.toShort - ) - ergoBox - } - - override def from(x: ErgoBox): Box[commonMod.Amount, NonMandatoryRegisters] = { - val ergoTree = ErgoTreeSerializer.DefaultSerializer.serializeErgoTree(x.ergoTree) - val ergoTreeStr = Base16.encode(ergoTree) - val assets = isoTokenArray.from(x.additionalTokens) - Box[commonMod.Amount, NonMandatoryRegisters]( - boxId = Base16.encode(x.id), - ergoTree = ergoTreeStr, - value = isoAmount.from(x.value), - assets = assets, - creationHeight = x.creationHeight, - additionalRegisters = isoNonMandatoryRegisters.from(x.additionalRegisters), - transactionId = x.transactionId, - index = x.index - ) - } + override def from(x: DataInput): inputsMod.DataInput = + inputsMod.DataInput(DataIsos.isoBoxId.from(x.boxId)) } val isoEIP12UnsignedInput: Iso[inputsMod.EIP12UnsignedInput, ExtendedInputBox] = @@ -380,12 +216,12 @@ object Isos { transactionId = x.transactionId, index = x.index ) - val ergoBox = isoBox.to(box) + val ergoBox = sigma.js.Box.isoBox.to(box) val extendedInputBox = ExtendedInputBox(ergoBox, isoContextExtension.to(x.extension)) extendedInputBox } override def from(x: ExtendedInputBox): inputsMod.EIP12UnsignedInput = { - val box = isoBox.from(x.box) + val box = sigma.js.Box.isoBox.from(x.box) val ext = isoContextExtension.from(x.extension) inputsMod.EIP12UnsignedInput( boxId = box.boxId, @@ -407,7 +243,7 @@ object Isos { new UnsignedErgoLikeTransaction( 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), + outputCandidates = sigma.js.Isos.isoArrayToIndexed(DataIsos.isoBoxCandidate).to(a.outputs), ) } @@ -415,7 +251,7 @@ object Isos { UnsignedTransaction( 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) + outputs = sigma.js.Isos.isoArrayToIndexed(DataIsos.isoBoxCandidate).from(b.outputCandidates) ) } } @@ -426,14 +262,14 @@ object Isos { new ErgoLikeTransaction( 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), + outputCandidates = sigma.js.Isos.isoArrayToIndexed(sigma.js.Box.isoBox).to(a.outputs), ) } override def from(tx: ErgoLikeTransaction): SignedTransaction = { 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) + val outputs = sigma.js.Isos.isoArrayToIndexed(sigma.js.Box.isoBox).from(tx.outputs) SignedTransaction(dataInputs, tx.id, inputs, outputs) } } 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 12ecf1d03f..7ab95c187e 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,6 +6,7 @@ import org.ergoplatform.sdk.SecretString import scala.scalajs.js import scala.scalajs.js.annotation.JSExportTopLevel import Isos._ +import sigma.data.js.{Isos => DataIsos} import sigma.eval.SigmaDsl /** Equivalent of [[sdk.ProverBuilder]] available from JS. @@ -66,10 +67,10 @@ class ProverBuilder(parameters: BlockchainParameters, network: Byte) extends js. */ def withDHTSecret(g: String, h: String, u: String, v: String, x: js.BigInt): ProverBuilder = { _builder.withDHTData( - isoStringToGroupElement.to(g), - isoStringToGroupElement.to(h), - isoStringToGroupElement.to(u), - isoStringToGroupElement.to(v), + DataIsos.isoStringToGroupElement.to(g), + DataIsos.isoStringToGroupElement.to(h), + DataIsos.isoStringToGroupElement.to(u), + DataIsos.isoStringToGroupElement.to(v), SigmaDsl.toBigInteger(sigma.js.Isos.isoBigInt.to(x)) ) this 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 0a6aca4830..693c0717bb 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 @@ -51,8 +51,8 @@ class SigmaProver(_prover: sdk.SigmaProver) extends js.Object { val unreducedTx = sdk.UnreducedTransaction( unsignedTx = isoUnsignedTransaction.to(unsignedTx), 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) + dataInputs = sigma.js.Isos.isoArrayToIndexed(sigma.js.Box.isoBox).to(dataInputs), + tokensToBurn = sigma.js.Isos.isoArrayToIndexed(sigma.data.js.Isos.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 a366e33d3c..a040731b20 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 @@ -10,7 +10,7 @@ import sigma.data.Iso import sigma.interpreter.{ContextExtension, ProverResult} import sigma.js.AvlTree import sigma.{Coll, GroupElement} - +import sigma.data.js.{Isos => DataIsos} import scala.scalajs.js class IsosSpec extends IsosSpecBase with sdk.generators.ObjectGenerators { @@ -31,19 +31,19 @@ class IsosSpec extends IsosSpecBase with sdk.generators.ObjectGenerators { property("Iso.isoStringToGroupElement") { forAll() { (bytes: GroupElement) => - roundtrip(Isos.isoStringToGroupElement)(bytes) + roundtrip(DataIsos.isoStringToGroupElement)(bytes) } } property("Iso.isoBoxId") { forAll(boxIdGen) { (id: BoxId) => - roundtrip(Isos.isoBoxId)(id) + roundtrip(DataIsos.isoBoxId)(id) } } property("Iso.isoHexStringToConstant") { forAll(constantGen, MinSuccessful(100)) { (c: Constant[SType]) => - roundtrip(Isos.isoHexStringToConstant)(c) + roundtrip(DataIsos.isoHexStringToConstant)(c) } } @@ -115,20 +115,20 @@ class IsosSpec extends IsosSpecBase with sdk.generators.ObjectGenerators { property("Iso.isoAmount") { forAll { (c: Long) => - roundtrip(Isos.isoAmount)(c) - Isos.isoAmount.to(js.BigInt(c.toString)) shouldBe c + roundtrip(DataIsos.isoAmount)(c) + DataIsos.isoAmount.to(js.BigInt(c.toString)) shouldBe c } } property("Iso.isoToken") { forAll(tokenIdGen, Arbitrary.arbLong.arbitrary) { (id: TokenId, amount: Long) => - roundtrip(Isos.isoToken)((id, amount)) + roundtrip(DataIsos.isoToken)((id, amount)) } } property("Iso.isoTokenArray") { forAll(ergoBoxTokens(tokensGen.sample.get)) { tokens => - roundtrip(Isos.isoTokenArray)(tokens) + roundtrip(DataIsos.isoTokenArray)(tokens) } } @@ -140,19 +140,19 @@ class IsosSpec extends IsosSpecBase with sdk.generators.ObjectGenerators { property("Iso.isoNonMandatoryRegisters") { forAll(additionalRegistersGen) { (x: AdditionalRegisters) => - roundtrip(Isos.isoNonMandatoryRegisters)(x) + roundtrip(DataIsos.isoNonMandatoryRegisters)(x) } } property("Iso.isoBoxCandidate") { forAll { (box: ErgoBoxCandidate) => - roundtrip(Isos.isoBoxCandidate)(box) + roundtrip(DataIsos.isoBoxCandidate)(box) } } property("Iso.isoBox") { forAll { (b: ErgoBox) => - roundtrip(Isos.isoBox)(b) + roundtrip(sigma.js.Box.isoBox)(b) } } 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/test/scala/org/ergoplatform/sdk/ExtensionsSpec.scala b/sdk/shared/src/test/scala/org/ergoplatform/sdk/ExtensionsSpec.scala index 98f61331bb..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,7 +4,8 @@ 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 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 { @@ -13,10 +14,6 @@ class ExtensionsSpec extends AnyPropSpec with ScalaCheckPropertyChecks with Matc 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] => @@ -28,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/sigma-js/README.md b/sigma-js/README.md index ff867e1cb6..c1f30f3497 100644 --- a/sigma-js/README.md +++ b/sigma-js/README.md @@ -46,14 +46,15 @@ with `$` suffix, thus if X is the JS class, then X$ is the JS object, which corr ## 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 + - [Value](../data/js/src/main/scala/sigma/js/Value.scala) - [ErgoTree](../data/js/src/main/scala/sigma/ast/js/ErgoTree.scala) + - [Box](../data/js/src/main/scala/sigma/js/Box.scala) - [Address](../data/js/src/main/scala/org/ergoplatform/js/Address.scala) - [Expr](../data/js/src/main/scala/sigma/ast/js/Expr.scala) diff --git a/sigma-js/package-lock.json b/sigma-js/package-lock.json index 893a0ee141..c34f802f6e 100644 --- a/sigma-js/package-lock.json +++ b/sigma-js/package-lock.json @@ -1,12 +1,12 @@ { "name": "sigmastate-js", - "version": "0.3.0", + "version": "0.4.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "sigmastate-js", - "version": "0.3.0", + "version": "0.4.0", "license": "MIT", "dependencies": { "@fleet-sdk/common": "0.1.3", diff --git a/sigma-js/package.json b/sigma-js/package.json index 77ff920585..f6900571bd 100644 --- a/sigma-js/package.json +++ b/sigma-js/package.json @@ -1,6 +1,6 @@ { "name": "sigmastate-js", - "version": "0.4.0", + "version": "0.4.2", "description": "Sigma.js library", "files": [ "dist/", diff --git a/sigma-js/sigmastate-js.d.ts b/sigma-js/sigmastate-js.d.ts index b70ca39258..53baa3b026 100644 --- a/sigma-js/sigmastate-js.d.ts +++ b/sigma-js/sigmastate-js.d.ts @@ -1,7 +1,7 @@ declare module "sigmastate-js/main" { import { Amount, - Box, + Box as FBox, EIP12UnsignedInput, NonMandatoryRegisters, SignedTransaction, TokenAmount, UnsignedTransaction @@ -173,6 +173,10 @@ declare module "sigmastate-js/main" { valueLengthOpt: number | undefined; } + export declare class Box { + box: FBox; + } + export declare class PreHeader { /** Block version, to be increased on every soft and hardfork. */ version: number; @@ -301,6 +305,8 @@ declare module "sigmastate-js/main" { static ofSigmaProp(pointHex: string): Value; + static ofBox(box: FBox): Value; + static pairOf(left: Value, right: Value): Value<[R, L]>; static collOf(items: T[], elemType: Type): Value; @@ -498,7 +504,7 @@ declare module "sigmastate-js/main" { stateCtx: BlockchainStateContext, unsignedTx: UnsignedTransaction, boxesToSpend: EIP12UnsignedInput[], - dataInputs: Box[], + dataInputs: FBox[], tokensToBurn: TokenAmount[], baseCost: number): ReducedTransaction; diff --git a/sigma-js/tests/js/Box.spec.js b/sigma-js/tests/js/Box.spec.js new file mode 100644 index 0000000000..24238013ba --- /dev/null +++ b/sigma-js/tests/js/Box.spec.js @@ -0,0 +1,28 @@ +const {Box$, Value$} = require("sigmastate-js/main"); + +describe("Box", () => { + it("should serialize from/to hex", () => { + let boxHex = "63b96000d1968302010100ff83020193040204020100c0843d000401010e32297000800b80f1d56c809a8c6affbed864b87f007f6f007f00ac00018c01c4fdff011088807f0100657f00f9ab0101ff6d6505a4a7b5a2e7a4a4dd3a05feffffffffffffffff01003bd5c630803cfff6c1ff7f7fb980ff136afc011f8080b8b04ad4dbda2d7f4e01" + let deserialized = Value$.fromHex(boxHex); + let expected = { + additionalRegisters: { + R4: '0101', + R5: '0e32297000800b80f1d56c809a8c6affbed864b87f007f6f007f00ac00018c01c4fdff011088807f0100657f00f9ab0101ff6d65', + R6: '05a4a7b5a2e7a4a4dd3a', + R7: '05feffffffffffffffff01' + }, + assets: [], + boxId: '3a0089be265460e29ca47d26e5b55a6f3e3ffaf5b4aed941410a2437913848ad', + creationHeight: 1000000, + ergoTree: '00d1968302010100ff83020193040204020100', + index: 1, + transactionId: '003bd5c630803cfff6c1ff7f7fb980ff136afc011f8080b8b04ad4dbda2d7f4e', + value: '12345' + } + let fleetBox = deserialized.data.box + expect(fleetBox).toEqual(expected) + + let newBoxValue = Value$.ofBox(fleetBox) + expect(newBoxValue.toHex()).toEqual(boxHex) + }); +}); \ No newline at end of file