Skip to content

Commit

Permalink
impl and tests done without costing etc
Browse files Browse the repository at this point in the history
  • Loading branch information
kushti committed Jun 18, 2024
1 parent 62fd2a3 commit 8bcc1ef
Show file tree
Hide file tree
Showing 7 changed files with 136 additions and 13 deletions.
2 changes: 1 addition & 1 deletion data/shared/src/main/scala/sigma/ast/methods.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1521,7 +1521,7 @@ case object SGlobalMethods extends MonoTypeMethods {
}

lazy val fromBigEndianBytesMethod = SMethod(
this, "fromBigEndianBytes", SFunc(Array(SGlobal, SByteArray), tT, Array(paramT)), 3, Xor.costKind) // todo: id, cossting
this, "fromBigEndianBytes", SFunc(Array(SGlobal, SByteArray), tT, Array(paramT)), 30, Xor.costKind, Seq(tT)) // todo: id, cossting
.withIRInfo(MethodCallIrBuilder)
.withInfo(MethodCall, "Multiply this number with \\lst{other} by module Q.", ArgInfo("other", "Number to multiply with this.")) // todo: desc

Expand Down
32 changes: 27 additions & 5 deletions data/shared/src/main/scala/sigma/data/CSigmaDslBuilder.scala
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ import debox.cfor
import org.ergoplatform.ErgoBox
import org.ergoplatform.validation.ValidationRules
import scorex.crypto.hash.{Blake2b256, Sha256}
import scorex.utils.Longs
import sigma.ast.{AtLeast, SByte, SLong, SType, SubstConstants}
import scorex.utils.{Ints, Longs, Shorts}
import sigma.ast.{AtLeast, SBigInt, SByte, SInt, SLong, SShort, SType, SubstConstants}
import sigma.crypto.{CryptoConstants, EcPointType, Ecp}
import sigma.eval.Extensions.EvalCollOps
import sigma.serialization.{GroupElementSerializer, SigmaSerializer}
import sigma.serialization.{CoreDataSerializer, DataSerializer, GroupElementSerializer, SerializerException, SigmaSerializer}
import sigma.util.Extensions.BigIntegerOps
import sigma.validation.SigmaValidationSettings
import sigma.{AvlTree, BigInt, Box, Coll, CollBuilder, GroupElement, SigmaDslBuilder, SigmaProp, VersionContext}
Expand Down Expand Up @@ -208,9 +208,31 @@ class CSigmaDslBuilder extends SigmaDslBuilder { dsl =>
} else {
bytes.apply(0).asInstanceOf[T]
}
case SLong => Longs.fromByteArray(bytes.toArray).asInstanceOf[T]
case SShort => if (bytes.length != 2) {
throw new IllegalArgumentException("To deserialize SShort with fromBigEndianBytes, exactly two bytes should be provided")
} else {
val b0 = bytes(0)
val b1 = bytes(1)
((b0 & 0xFF) << 8 | (b1 & 0xFF)).toShort.asInstanceOf[T]
}
case SInt => if (bytes.length != 4) {
throw new IllegalArgumentException("To deserialize SInt with fromBigEndianBytes, exactly four bytes should be provided")
} else {
Ints.fromByteArray(bytes.toArray).asInstanceOf[T]
}
case SLong => if (bytes.length != 8) {
throw new IllegalArgumentException("To deserialize SLong with fromBigEndianBytes, exactly eight bytes should be provided")
} else {
Longs.fromByteArray(bytes.toArray).asInstanceOf[T]
}
case SBigInt =>
if (bytes.length > SBigInt.MaxSizeInBytes) {
throw SerializerException(s"BigInt value doesn't not fit into ${SBigInt.MaxSizeInBytes} bytes in fromBigEndianBytes")
}
CBigInt(new BigInteger(bytes.toArray)).asInstanceOf[T]
// todo: UnsignedBitInt
case _ => throw new IllegalArgumentException("Unsupported type provided in fromBigEndianBytes")
// todo: more types

}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -928,7 +928,7 @@ trait GraphBuilding extends Base with DefRewriting { IR: IRContext =>
sigmaDslBuilder.decodePoint(bytes)

// fallback rule for MethodCall, should be the last case in the list
case sigma.ast.MethodCall(obj, method, args, _) =>
case sigma.ast.MethodCall(obj, method, args, typeSubst) =>
val objV = eval(obj)
val argsV = args.map(eval)
(objV, method.objType) match {
Expand Down Expand Up @@ -1146,6 +1146,10 @@ trait GraphBuilding extends Base with DefRewriting { IR: IRContext =>
val c1 = asRep[Coll[Byte]](argsV(0))
val c2 = asRep[Coll[Byte]](argsV(1))
g.xor(c1, c2)
case SGlobalMethods.fromBigEndianBytesMethod.name =>
val bytes = asRep[Coll[Byte]](argsV(0))
val cT = stypeToElem(method.stype.tRange.withSubstTypes(typeSubst))
g.fromBigEndianBytes(bytes)(cT)
case _ => throwError
}
case _ => throwError
Expand Down
19 changes: 16 additions & 3 deletions sc/shared/src/main/scala/sigma/compiler/ir/TreeBuilding.scala
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package sigma.compiler.ir

import org.ergoplatform._
import sigma.Evaluation.{rtypeToSType, stypeToRType}
import sigma.ast.SType.tT
import sigma.ast._
import sigma.ast.syntax.{ValueOps, _}
import sigma.data.{ProveDHTuple, ProveDlog}
Expand Down Expand Up @@ -399,13 +401,24 @@ trait TreeBuilding extends Base { IR: IRContext =>
mkMultiplyGroup(obj.asGroupElement, arg.asGroupElement)

// Fallback MethodCall rule: should be the last in this list of cases
case Def(MethodCall(objSym, m, argSyms, _)) =>
case Def(mc @ MethodCall(objSym, m, argSyms, _)) =>
val obj = recurse[SType](objSym)
val args = argSyms.collect { case argSym: Sym => recurse[SType](argSym) }
MethodsContainer.getMethod(obj.tpe, m.getName) match {
case Some(method) =>
val specMethod = method.specializeFor(obj.tpe, args.map(_.tpe))
builder.mkMethodCall(obj, specMethod, args.toIndexedSeq, Map())

val typeSubst: STypeSubst = {
if (method.hasExplicitTypeArgs) {
val cT = rtypeToSType(mc.resultType.sourceType)
Map(tT -> cT)
} else {
Map.empty
}
}

val specMethod = method.specializeFor(obj.tpe, args.map(_.tpe)).withConcreteTypes(typeSubst)

builder.mkMethodCall(obj, specMethod, args.toIndexedSeq, typeSubst)
case None =>
error(s"Cannot find method ${m.getName} in object $obj")
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ import scalan._
/** This method will be used in v6.0 to handle CreateAvlTree operation in GraphBuilding */
def avlTree(operationFlags: Ref[Byte], digest: Ref[Coll[Byte]], keyLength: Ref[Int], valueLengthOpt: Ref[WOption[Int]]): Ref[AvlTree];
def xor(l: Ref[Coll[Byte]], r: Ref[Coll[Byte]]): Ref[Coll[Byte]]
def fromBigEndianBytes[T](bytes: Ref[Coll[Byte]])(implicit cT: Elem[T]): Ref[T]
};
trait CostModelCompanion;
trait BigIntCompanion;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1945,6 +1945,13 @@ object SigmaDslBuilder extends EntityObject("SigmaDslBuilder") {
Array[AnyRef](l, r),
true, false, element[Coll[Byte]]))
}

override def fromBigEndianBytes[T](bytes: Ref[Coll[Byte]])(implicit cT: Elem[T]): Ref[T] = {
asRep[T](mkMethodCall(self,
SigmaDslBuilderClass.getMethod("fromBigEndianBytes", classOf[Sym], classOf[Elem[T]]),
Array[AnyRef](bytes, cT),
true, false, cT))
}
}

implicit object LiftableSigmaDslBuilder
Expand Down Expand Up @@ -2104,6 +2111,13 @@ object SigmaDslBuilder extends EntityObject("SigmaDslBuilder") {
Array[AnyRef](l, r),
true, true, element[Coll[Byte]]))
}

def fromBigEndianBytes[T](bytes: Ref[Coll[Byte]])(implicit cT: Elem[T]): Ref[T] = {
asRep[T](mkMethodCall(source,
SigmaDslBuilderClass.getMethod("fromBigEndianBytes", classOf[Sym], classOf[Elem[T]]),
Array[AnyRef](bytes, cT),
true, true, cT))
}
}

// entityUnref: single unref method for each type family
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package sigmastate.utxo

import org.ergoplatform.ErgoBox.{AdditionalRegisters, R6, R8}
import org.ergoplatform._
import scorex.util.encode.Base16
import scorex.utils.Ints
import sigma.Extensions.ArrayOps
import sigma.VersionContext
import sigma.ast.SCollection.SByteArray
Expand Down Expand Up @@ -158,10 +160,58 @@ class BasicOpsSpecification extends CompilerTestingCommons
)
}

property("Global.fromBigEndianBytes") {
def fromTest() = test("R1", env, ext,
property("Global.fromBigEndianBytes - byte") {
def fromTest() = test("fromBigEndianBytes - byte", env, ext,
s"""{
| val l = -1000L
| val ba = Coll(5.toByte)
| Global.fromBigEndianBytes[Byte](ba) == 5
|}
|""".stripMargin,
null
)
if(VersionContext.current.isV6SoftForkActivated) {
fromTest()
} else {
an[Exception] should be thrownBy(fromTest())
}
}

property("Global.fromBigEndianBytes - short") {
def fromTest() = test("fromBigEndianBytes - short", env, ext,
s"""{
| val ba = Coll(5.toByte, 5.toByte)
| Global.fromBigEndianBytes[Short](ba) != 0
|}
|""".stripMargin,
null
)
if(VersionContext.current.isV6SoftForkActivated) {
fromTest()
} else {
an[Exception] should be thrownBy(fromTest())
}
}

property("Global.fromBigEndianBytes - int") {
def fromTest() = test("fromBigEndianBytes - int", env, ext,
s"""{
| val ba = fromBase16("${Base16.encode(Ints.toByteArray(Int.MaxValue))}")
| Global.fromBigEndianBytes[Int](ba) == ${Int.MaxValue}
|}
|""".stripMargin,
null
)
if(VersionContext.current.isV6SoftForkActivated) {
fromTest()
} else {
an[Exception] should be thrownBy(fromTest())
}
}

property("Global.fromBigEndianBytes - long") {
def fromTest() = test("fromBigEndianBytes - long", env, ext,
s"""{
| val l = 1088800L
| val ba = longToByteArray(l)
| Global.fromBigEndianBytes[Long](ba) == l
|}
Expand All @@ -175,6 +225,25 @@ class BasicOpsSpecification extends CompilerTestingCommons
}
}

property("Global.fromBigEndianBytes - bigInt") {
val bi = new BigInteger("9785856985394593489356430476450674590674598659865986594859056865984690568904")
def fromTest() = test("fromBigEndianBytes - bigInt", env, ext,
s"""{
| val ba = fromBase16("${Base16.encode(bi.toByteArray)}")
| Global.fromBigEndianBytes[BigInt](ba) == bigInt("$bi")
|}
|""".stripMargin,
null
)
if(VersionContext.current.isV6SoftForkActivated) {
fromTest()
} else {
an[Exception] should be thrownBy(fromTest())
}
}

// todo: roundtrip with .toBytes

property("Relation operations") {
test("R1", env, ext,
"{ allOf(Coll(getVar[Boolean](trueVar).get, true, true)) }",
Expand Down

0 comments on commit 8bcc1ef

Please sign in to comment.