Skip to content

Commit

Permalink
Merge pull request #990 from ScorexFoundation/i659
Browse files Browse the repository at this point in the history
[6.0] SOption[T] (de)serialization support
  • Loading branch information
kushti authored Jun 3, 2024
2 parents 3fe08a0 + ea91fae commit 2baf8ca
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 5 deletions.
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
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,12 @@ class CoreDataSerializer {
i += 1
}

// TODO v6.0 (3h): support Option[T] (see https://github.com/ScorexFoundation/sigmastate-interpreter/issues/659)
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 @@ -118,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
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,18 @@ package sigma.serialization
import java.math.BigInteger
import org.ergoplatform.ErgoBox
import org.scalacheck.Arbitrary._
import sigma.data.{DataValueComparer, RType, SigmaBoolean, TupleColl}
import sigma.data.{DataValueComparer, OptionType, RType, SigmaBoolean, TupleColl}
import sigma.ast.SCollection.SByteArray
import sigmastate.eval._
import sigma.{AvlTree, Colls, Evaluation}
import sigma.{AvlTree, Colls, Evaluation, VersionContext}
import sigma.ast.SType.AnyOps
import sigma.ast._
import org.scalacheck.Gen
import sigma.Extensions.ArrayOps
import sigma.crypto.EcPointType
import sigma.eval.SigmaDsl
import sigma.util.Extensions.{BigIntegerOps, EcpOps, SigmaBooleanOps}
import sigmastate.interpreter.{CostAccumulator, CErgoTreeEvaluator}
import sigmastate.interpreter.{CErgoTreeEvaluator, CostAccumulator}
import sigmastate.interpreter.CErgoTreeEvaluator.DefaultProfiler
import sigmastate.utils.Helpers

Expand Down Expand Up @@ -92,6 +92,32 @@ class DataSerializerSpecification extends SerializationSpecification {
}
}

def testOption[T <: SType](tpe: T) = {
implicit val wWrapped: Gen[T#WrappedType] = wrappedTypeGen(tpe)
val tT = Evaluation.stypeToRType(tpe)

an[Exception] should be thrownBy (
VersionContext.withVersions((VersionContext.V6SoftForkVersion - 1).toByte, 1) {
forAll { in: T#WrappedType =>
roundtrip[SType](Some(in).asWrappedType, SOption(tpe))
roundtrip[SOption[SCollection[T]]](Some(Colls.fromItems(in)(tT)), SOption(SCollectionType(tpe)))
}
})

VersionContext.withVersions(VersionContext.V6SoftForkVersion, 1) {
forAll { in: T#WrappedType =>
roundtrip[SType](Some(in).asWrappedType, SOption(tpe))
roundtrip[SOption[T]](None, SOption(tpe))
roundtrip[SOption[T]](Some(in), SOption(tpe))
roundtrip[SOption[SCollection[T]]](Some(Colls.fromItems(in)(tT)), SOption(SCollectionType(tpe)))
roundtrip[SCollection[SOption[T]]](Colls.fromItems(Option(in), None.asInstanceOf[Option[T#WrappedType]])(OptionType(tT)), SCollectionType(SOption(tpe)))
roundtrip[SOption[SOption[T]]](None, SOption(SOption(tpe)))
roundtrip[SOption[SOption[T]]](Some(Some(in)), SOption(SOption(tpe)))
roundtrip[SOption[SOption[T]]](Some(None), SOption(SOption(tpe)))
}
}
}

property("Data serialization round trip") {
forAll { x: Byte => roundtrip[SByte.type](x, SByte) }
forAll { x: Boolean => roundtrip[SBoolean.type](x, SBoolean) }
Expand All @@ -105,6 +131,7 @@ class DataSerializerSpecification extends SerializationSpecification {
forAll { x: Array[Byte] => roundtrip[SByteArray](x.toColl, SByteArray) }
forAll { t: SPredefType => testCollection(t) }
forAll { t: SPredefType => testTuples(t) }
forAll { t: SPredefType => testOption(t) }
}

property("Should check limits and fail") {
Expand Down

0 comments on commit 2baf8ca

Please sign in to comment.