Skip to content

Commit

Permalink
merging w. 6.0.0
Browse files Browse the repository at this point in the history
  • Loading branch information
kushti committed Jun 5, 2024
2 parents 0902147 + 2baf8ca commit d6e1bec
Show file tree
Hide file tree
Showing 115 changed files with 1,145 additions and 904 deletions.
3 changes: 3 additions & 0 deletions core/js/src/main/scala/sigma/js/Isos.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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]] {
Expand Down
3 changes: 2 additions & 1 deletion core/shared/src/main/scala/sigma/ast/SType.scala
Original file line number Diff line number Diff line change
Expand Up @@ -602,7 +602,8 @@ object STypeApply {
/** Type description of optional values. Instances of `Option`
* are either constructed by `Some` or by `None` constructors. */
case class SOption[ElemType <: SType](elemType: ElemType) extends SProduct with SGenericType {
override type WrappedType = Option[ElemType#WrappedType]
type ElemWrappedType = ElemType#WrappedType
override type WrappedType = Option[ElemWrappedType]
override val typeCode: TypeCode = SOption.OptionTypeCode
override def toString = s"Option[$elemType]"
override def toTermString: String = s"Option[${elemType.toTermString}]"
Expand Down
10 changes: 8 additions & 2 deletions core/shared/src/main/scala/sigma/data/Iso.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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`
*
* <p>
* 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))
* <p>
* 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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,12 @@ class CoreDataSerializer {
i += 1
}

// TODO v6.0 : support Option[T] (see https://github.com/ScorexFoundation/sigmastate-interpreter/issues/659)
// TODO v6.0 : support Header
case SOption(elemType) if VersionContext.current.isV6SoftForkActivated =>
val o = v.asInstanceOf[Option[elemType.WrappedType]]
w.putOption(o){case (w, v) =>
serialize(v, elemType, w)
}

case _ =>
CheckSerializableTypeCode(tpe.typeCode)
throw new SerializerException(s"Don't know how to serialize ($v, $tpe)")
Expand Down Expand Up @@ -119,6 +123,10 @@ class CoreDataSerializer {
}.toArray[Any]
val coll = Colls.fromArray(arr)(sigma.AnyType)
Evaluation.toDslTuple(coll, tuple)
case tOption: SOption[_] if VersionContext.current.isV6SoftForkActivated =>
r.getOption[tOption.ElemWrappedType] {
deserialize(tOption.elemType, r).asInstanceOf[tOption.ElemWrappedType]
}
case t =>
CheckSerializableTypeCode(t.typeCode)
throw new SerializerException(s"Not defined DataSerializer for type $t")
Expand Down
4 changes: 1 addition & 3 deletions core/shared/src/test/scala/sigma/VersionTesting.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
}
}
Expand Down
152 changes: 152 additions & 0 deletions data/js/src/main/scala/sigma/data/js/Isos.scala
Original file line number Diff line number Diff line change
@@ -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)
)
}
}


}
61 changes: 61 additions & 0 deletions data/js/src/main/scala/sigma/js/Box.scala
Original file line number Diff line number Diff line change
@@ -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
)
}
}


}
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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)
}
}
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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)):_*)
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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))
Expand Down
4 changes: 2 additions & 2 deletions data/shared/src/main/scala/sigma/ast/ErgoTree.scala
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,13 @@ case class UnparsedErgoTree(bytes: mutable.WrappedArray[Byte], error: Validation
* ErgoTreeSerializer defines top-level serialization format of the scripts.
* The interpretation of the byte array depend on the first `header` byte, which uses VLQ encoding up to 30 bits.
* Currently we define meaning for only first byte, which may be extended in future versions.
* 7 6 5 4 3 2 1 0
* 7 6 5 4 3 2 1 0
* -------------------------
* | | | | | | | | |
* -------------------------
* Bit 7 == 1 if the header contains more than 1 byte (default == 0)
* Bit 6 - reserved for GZIP compression (should be 0)
* Bit 5 == 1 - reserved for context dependent costing (should be = 0)
* Bit 5 == 1 - reserved (should be = 0)
* Bit 4 == 1 if constant segregation is used for this ErgoTree (default = 0)
* (see https://github.com/ScorexFoundation/sigmastate-interpreter/issues/264)
* Bit 3 == 1 if size of the whole tree is serialized after the header byte (default = 0)
Expand Down
Loading

0 comments on commit d6e1bec

Please sign in to comment.