diff --git a/core/shared/src/main/scala/sigma/SigmaDsl.scala b/core/shared/src/main/scala/sigma/SigmaDsl.scala index 9bbef3d9b..67e1b1138 100644 --- a/core/shared/src/main/scala/sigma/SigmaDsl.scala +++ b/core/shared/src/main/scala/sigma/SigmaDsl.scala @@ -1,7 +1,8 @@ package sigma -import java.math.BigInteger +import sigma.ast.SType +import java.math.BigInteger import sigma.data._ /** @@ -777,5 +778,8 @@ trait SigmaDslBuilder { /** Returns a byte-wise XOR of the two collections of bytes. */ def xor(l: Coll[Byte], r: Coll[Byte]): Coll[Byte] + + /** Returns a number decoded from provided big-endian bytes array. */ + def fromBigEndianBytes[T](bytes: Coll[Byte])(implicit cT: RType[T]): T } diff --git a/core/shared/src/main/scala/sigma/reflection/ReflectionData.scala b/core/shared/src/main/scala/sigma/reflection/ReflectionData.scala index e01403d09..272594da3 100644 --- a/core/shared/src/main/scala/sigma/reflection/ReflectionData.scala +++ b/core/shared/src/main/scala/sigma/reflection/ReflectionData.scala @@ -451,6 +451,9 @@ object ReflectionData { mkMethod(clazz, "decodePoint", Array[Class[_]](cColl)) { (obj, args) => obj.asInstanceOf[SigmaDslBuilder].decodePoint(args(0).asInstanceOf[Coll[Byte]]) }, + mkMethod(clazz, "fromBigEndianBytes", Array[Class[_]](cColl, classOf[RType[_]])) { (obj, args) => + obj.asInstanceOf[SigmaDslBuilder].fromBigEndianBytes(args(0).asInstanceOf[Coll[Byte]])(args(1).asInstanceOf[RType[_]]) + }, mkMethod(clazz, "encodeNbits", Array[Class[_]](classOf[BigInt])) { (obj, args) => obj.asInstanceOf[SigmaDslBuilder].encodeNbits(args(0).asInstanceOf[BigInt]) }, diff --git a/data/shared/src/main/scala/sigma/ast/SigmaPredef.scala b/data/shared/src/main/scala/sigma/ast/SigmaPredef.scala index 8b8985193..96573d095 100644 --- a/data/shared/src/main/scala/sigma/ast/SigmaPredef.scala +++ b/data/shared/src/main/scala/sigma/ast/SigmaPredef.scala @@ -420,6 +420,25 @@ object SigmaPredef { ) ) + val FromBigEndianBytesFunc = PredefinedFunc("fromBigEndianBytes", + Lambda(Seq(paramT), Array("bytes" -> SByteArray), tT, None), + irInfo = PredefFuncInfo( + irBuilder = { case (u, args) => + val resType = u.opType.tRange.asInstanceOf[SFunc].tRange + MethodCall( + Global, + SGlobalMethods.fromBigEndianBytesMethod.withConcreteTypes(Map(tT -> resType)), + args.toIndexedSeq, + Map(tT -> resType) + ) + }), + docInfo = OperationInfo(MethodCall, + """Deserializes provided big endian bytes into a numeric value of given type. + """.stripMargin, + Seq(ArgInfo("bytes", "bytes to deserialize")) + ) + ) + val globalFuncs: Map[String, PredefinedFunc] = Seq( AllOfFunc, AnyOfFunc, @@ -448,7 +467,8 @@ object SigmaPredef { SubstConstantsFunc, ExecuteFromVarFunc, ExecuteFromSelfRegFunc, - SerializeFunc + SerializeFunc, + FromBigEndianBytesFunc ).map(f => f.name -> f).toMap def comparisonOp(symbolName: String, opDesc: ValueCompanion, desc: String, args: Seq[ArgInfo]) = { diff --git a/data/shared/src/main/scala/sigma/ast/methods.scala b/data/shared/src/main/scala/sigma/ast/methods.scala index d0a92d1cc..2f0bc6a69 100644 --- a/data/shared/src/main/scala/sigma/ast/methods.scala +++ b/data/shared/src/main/scala/sigma/ast/methods.scala @@ -2,6 +2,8 @@ package sigma.ast import org.ergoplatform._ import org.ergoplatform.validation._ +import sigma.Evaluation.stypeToRType +import sigma._ import sigma.{VersionContext, _} import sigma.ast.SCollection.{SBooleanArray, SBoxArray, SByteArray, SByteArray2, SHeaderArray} import sigma.ast.SGlobalMethods.{decodeNBitsMethod, encodeNBitsMethod} @@ -482,7 +484,6 @@ case object SBigIntMethods extends SNumericTypeMethods { } } - } /** Methods of type `String`. */ @@ -1693,6 +1694,18 @@ case object SGlobalMethods extends MonoTypeMethods { Xor.xorWithCosting(ls, rs) } + private val BigEndianBytesCostKind = FixedCost(JitCost(10)) + + // id = 4 is reserved for deserializeTo () + lazy val fromBigEndianBytesMethod = SMethod( + this, "fromBigEndianBytes", SFunc(Array(SGlobal, SByteArray), tT, Array(paramT)), 5, BigEndianBytesCostKind, Seq(tT)) + .withIRInfo(MethodCallIrBuilder, + javaMethodOf[SigmaDslBuilder, Coll[Byte], RType[_]]("fromBigEndianBytes"), + { mtype => Array(mtype.tRange) }) + .withInfo(MethodCall, + "Decode a number from big endian bytes.", + ArgInfo("first", "Bytes which are big-endian encoded number.")) + private lazy val EnDecodeNBitsCost = FixedCost(JitCost(5)) // the same cost for nbits encoding and decoding lazy val encodeNBitsMethod: SMethod = SMethod( @@ -1759,7 +1772,8 @@ case object SGlobalMethods extends MonoTypeMethods { xorMethod, serializeMethod, encodeNBitsMethod, - decodeNBitsMethod + decodeNBitsMethod, + fromBigEndianBytesMethod ) } else { Seq( diff --git a/data/shared/src/main/scala/sigma/data/CSigmaDslBuilder.scala b/data/shared/src/main/scala/sigma/data/CSigmaDslBuilder.scala index 7cfb06f0b..d0b585b0c 100644 --- a/data/shared/src/main/scala/sigma/data/CSigmaDslBuilder.scala +++ b/data/shared/src/main/scala/sigma/data/CSigmaDslBuilder.scala @@ -4,11 +4,14 @@ import debox.cfor import org.ergoplatform.ErgoBox import org.ergoplatform.validation.ValidationRules import scorex.crypto.hash.{Blake2b256, Sha256} +import scorex.utils.{Ints, Longs} +import sigma.ast.{AtLeast, SBigInt, SubstConstants} import scorex.utils.Longs import sigma.ast.{AtLeast, SType, SubstConstants} import sigma.crypto.{CryptoConstants, EcPointType, Ecp} import sigma.eval.Extensions.EvalCollOps import sigma.serialization.{DataSerializer, GroupElementSerializer, SigmaSerializer} +import sigma.serialization.{GroupElementSerializer, SerializerException, SigmaSerializer} import sigma.util.Extensions.BigIntegerOps import sigma.util.NBitsUtils import sigma.validation.SigmaValidationSettings @@ -210,6 +213,40 @@ class CSigmaDslBuilder extends SigmaDslBuilder { dsl => this.GroupElement(p) } + override def fromBigEndianBytes[T](bytes: Coll[Byte])(implicit cT: RType[T]): T = { + cT match { + case sigma.ByteType => if (bytes.length != 1) { + throw new IllegalArgumentException("To deserialize SByte with fromBigEndianBytes, exactly one byte should be provided") + } else { + bytes.apply(0).asInstanceOf[T] + } + case sigma.ShortType => 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 sigma.IntType => 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 sigma.LongType => 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 sigma.BigIntRType => + 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).to256BitValueExact).asInstanceOf[T] + // todo: UnsignedBitInt + case _ => throw new IllegalArgumentException("Unsupported type provided in fromBigEndianBytes") + } + } + /** Serializes the given `value` into bytes using the default serialization format. */ override def serialize[T](value: T)(implicit cT: RType[T]): Coll[Byte] = { val tpe = Evaluation.rtypeToSType(cT) diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/GraphBuilding.scala b/sc/shared/src/main/scala/sigma/compiler/ir/GraphBuilding.scala index 160fe132f..23d1c16df 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/GraphBuilding.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/GraphBuilding.scala @@ -1164,6 +1164,10 @@ trait GraphBuilding extends Base with DefRewriting { IR: IRContext => case SGlobalMethods.serializeMethod.name => val value = asRep[Any](argsV(0)) g.serialize(value) + 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 (x: Ref[tNum], _: SNumericTypeMethods) => method.name match { diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/GraphIRReflection.scala b/sc/shared/src/main/scala/sigma/compiler/ir/GraphIRReflection.scala index dcdce623a..79fba9bb9 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/GraphIRReflection.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/GraphIRReflection.scala @@ -1,5 +1,6 @@ package sigma.compiler.ir +import sigma.ast.SType import sigma.compiler.ir.primitives.Thunks import sigma.data.RType import sigma.reflection.ReflectionData.registerClassEntry @@ -510,6 +511,9 @@ object GraphIRReflection { }, mkMethod(clazz, "serialize", Array[Class[_]](classOf[Base#Ref[_]])) { (obj, args) => obj.asInstanceOf[ctx.SigmaDslBuilder].serialize(args(0).asInstanceOf[ctx.Ref[Any]]) + }, + mkMethod(clazz, "fromBigEndianBytes", Array[Class[_]](classOf[Base#Ref[_]], classOf[TypeDescs#Elem[_]])) { (obj, args) => + obj.asInstanceOf[ctx.SigmaDslBuilder].fromBigEndianBytes(args(0).asInstanceOf[ctx.Ref[ctx.Coll[Byte]]])(args(1).asInstanceOf[ctx.Elem[SType]]) } ) ) diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/TreeBuilding.scala b/sc/shared/src/main/scala/sigma/compiler/ir/TreeBuilding.scala index aed197843..906ace0fa 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/TreeBuilding.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/TreeBuilding.scala @@ -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} diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/SigmaDslUnit.scala b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/SigmaDslUnit.scala index c366efcfd..d4ca5f5b4 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/SigmaDslUnit.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/SigmaDslUnit.scala @@ -118,6 +118,7 @@ import scalan._ def encodeNbits(bi: Ref[BigInt]): Ref[Long] def decodeNbits(l: Ref[Long]): Ref[BigInt] def serialize[T](value: Ref[T]): Ref[Coll[Byte]] + def fromBigEndianBytes[T](bytes: Ref[Coll[Byte]])(implicit cT: Elem[T]): Ref[T] }; trait CostModelCompanion; trait BigIntCompanion; diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/SigmaDslImpl.scala b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/SigmaDslImpl.scala index c80e8f2d8..eb081d607 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/SigmaDslImpl.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/SigmaDslImpl.scala @@ -1971,6 +1971,13 @@ object SigmaDslBuilder extends EntityObject("SigmaDslBuilder") { 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, Map(tT -> Evaluation.rtypeToSType(cT.sourceType))), + true, false, cT)) + } + override def encodeNbits(bi: Ref[BigInt]): Ref[Long] = { asRep[Long](mkMethodCall(self, SigmaDslBuilderClass.getMethod("encodeNbits", classOf[Sym]), @@ -2151,6 +2158,13 @@ object SigmaDslBuilder extends EntityObject("SigmaDslBuilder") { 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, Map(tT -> Evaluation.rtypeToSType(cT.sourceType)))) + } + override def encodeNbits(bi: Ref[BigInt]): Ref[Long] = { asRep[Long](mkMethodCall(source, SigmaDslBuilderClass.getMethod("encodeNbits", classOf[Sym]), @@ -2183,7 +2197,7 @@ object SigmaDslBuilder extends EntityObject("SigmaDslBuilder") { Elem.declaredMethods(RClass(classOf[SigmaDslBuilder]), RClass(classOf[SSigmaDslBuilder]), Set( "Colls", "verifyZK", "atLeast", "allOf", "allZK", "anyOf", "anyZK", "xorOf", "sigmaProp", "blake2b256", "sha256", "byteArrayToBigInt", "longToByteArray", "byteArrayToLong", "proveDlog", "proveDHTuple", "groupGenerator", - "substConstants", "decodePoint", "avlTree", "xor", "encodeNBits", "decodeNBits" + "substConstants", "decodePoint", "avlTree", "xor", "encodeNBits", "decodeNBits", "serialize", "fromBigEndianBytes" )) } } diff --git a/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala b/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala index 7605043ce..bbfd260f2 100644 --- a/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala +++ b/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala @@ -11,11 +11,10 @@ import sigma.ast.ErgoTree.ZeroHeader import sigma.ast.SCollection.SByteArray import sigma.ast.syntax.TrueSigmaProp import sigma.ast.{SInt, _} -import sigma.data.{CBigInt, CBox, CHeader, ExactNumeric} +import sigma.data.{CBigInt, CBox, CHeader, CSigmaDslBuilder, ExactNumeric, RType} import sigma.eval.{CostDetails, SigmaDsl, TracedCost} import sigma.serialization.ValueCodes.OpCode -import sigma.data.{RType} -import sigma.util.Extensions.{BooleanOps, ByteOps, IntOps, LongOps} +import sigma.util.Extensions.{BooleanOps, IntOps} import sigmastate.exceptions.MethodNotFound import sigmastate.utils.Extensions.ByteOpsForSigma import sigmastate.utils.Helpers @@ -1523,4 +1522,93 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite => ) } + + property("Global - fromBigEndianBytes") { + import sigma.data.OrderingOps.BigIntOrdering + + def byteFromBigEndianBytes: Feature[Byte, Boolean] = { + newFeature( + { (x: Byte) => CSigmaDslBuilder.fromBigEndianBytes[Byte](Colls.fromArray(Array(x))) == x}, + "{ (x: Byte) => fromBigEndianBytes[Byte](x.toBytes) == x }", + sinceVersion = VersionContext.V6SoftForkVersion + ) + } + + verifyCases( + Seq( + 5.toByte -> new Expected(ExpectedResult(Success(true), None)), + Byte.MaxValue -> new Expected(ExpectedResult(Success(true), None)), + Byte.MinValue -> new Expected(ExpectedResult(Success(true), None)) + ), + byteFromBigEndianBytes + ) + + def shortFromBigEndianBytes: Feature[Short, Boolean] = { + newFeature( + { (x: Short) => CSigmaDslBuilder.fromBigEndianBytes[Short](Colls.fromArray(Shorts.toByteArray(x))) == x}, + "{ (x: Short) => fromBigEndianBytes[Short](x.toBytes) == x }", + sinceVersion = VersionContext.V6SoftForkVersion + ) + } + + verifyCases( + Seq( + 5.toShort -> new Expected(ExpectedResult(Success(true), None)), + Short.MaxValue -> new Expected(ExpectedResult(Success(true), None)), + Short.MinValue -> new Expected(ExpectedResult(Success(true), None)) + ), + shortFromBigEndianBytes + ) + + def intFromBigEndianBytes: Feature[Int, Boolean] = { + newFeature( + { (x: Int) => CSigmaDslBuilder.fromBigEndianBytes[Int](Colls.fromArray(Ints.toByteArray(x))) == x}, + "{ (x: Int) => fromBigEndianBytes[Int](x.toBytes) == x }", + sinceVersion = VersionContext.V6SoftForkVersion + ) + } + + verifyCases( + Seq( + 5 -> new Expected(ExpectedResult(Success(true), None)), + Int.MaxValue -> new Expected(ExpectedResult(Success(true), None)) + ), + intFromBigEndianBytes + ) + + def longFromBigEndianBytes: Feature[Long, Boolean] = { + newFeature( + { (x: Long) => CSigmaDslBuilder.fromBigEndianBytes[Long](Colls.fromArray(Longs.toByteArray(x))) == x}, + "{ (x: Long) => fromBigEndianBytes[Long](x.toBytes) == x }", + sinceVersion = VersionContext.V6SoftForkVersion + ) + } + + verifyCases( + Seq( + 5L -> new Expected(ExpectedResult(Success(true), None)), + Long.MinValue -> new Expected(ExpectedResult(Success(true), None)) + ), + longFromBigEndianBytes + ) + + def bigIntFromBigEndianBytes: Feature[BigInt, Boolean] = { + newFeature( + { (x: BigInt) => CSigmaDslBuilder.fromBigEndianBytes[BigInt](x.toBytes) == x}, + "{ (x: BigInt) => Global.fromBigEndianBytes[BigInt](x.toBytes) == x }", + sinceVersion = VersionContext.V6SoftForkVersion + ) + } + + verifyCases( + Seq( + CBigInt(BigInteger.valueOf(50)) -> new Expected(ExpectedResult(Success(true), None)), + CBigInt(BigInteger.valueOf(-500000000000L)) -> new Expected(ExpectedResult(Success(true), None)), + CBigInt(sigma.crypto.CryptoConstants.groupOrder.divide(BigInteger.valueOf(2))) -> new Expected(ExpectedResult(Success(true), None)) + ), + bigIntFromBigEndianBytes + ) + + } + } diff --git a/sc/shared/src/test/scala/sigmastate/ErgoTreeSpecification.scala b/sc/shared/src/test/scala/sigmastate/ErgoTreeSpecification.scala index 8ae4c5073..0f12476e4 100644 --- a/sc/shared/src/test/scala/sigmastate/ErgoTreeSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/ErgoTreeSpecification.scala @@ -516,7 +516,8 @@ class ErgoTreeSpecification extends SigmaDslTesting with ContractsTestkit with C (SGlobal.typeId, Seq( MInfo(1, groupGeneratorMethod), MInfo(2, xorMethod) ) ++ (if (isV6Activated) { - Seq(MInfo(3, serializeMethod), MInfo(6, encodeNBitsMethod), MInfo(7, decodeNBitsMethod)) // methods added in v6.0 + // id = 4 reserved for deserializeTo method + Seq(MInfo(3, serializeMethod), MInfo(5, fromBigEndianBytesMethod), MInfo(6, encodeNBitsMethod), MInfo(7, decodeNBitsMethod)) // methods added in v6.0 } else { Seq.empty[MInfo] }), true) diff --git a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala index 2e1adb464..f6c450604 100644 --- a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala @@ -6,9 +6,11 @@ import org.scalatest.Assertion import scorex.util.encode.Base16 import org.scalatest.Assertion import scorex.util.encode.Base16 +import scorex.utils.Ints import sigma.Extensions.ArrayOps import sigma.{SigmaTestingData, VersionContext} import sigma.VersionContext.V6SoftForkVersion +import sigma.VersionContext import sigma.ast.SCollection.SByteArray import sigma.ast.SType.AnyOps import sigma.data.{AvlTreeData, CAnyValue, CSigmaDslBuilder} @@ -556,6 +558,105 @@ class BasicOpsSpecification extends CompilerTestingCommons ) } + property("Global.fromBigEndianBytes - byte") { + def fromTest() = test("fromBigEndianBytes - byte", env, ext, + s"""{ + | 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 + |} + |""".stripMargin, + null + ) + if(VersionContext.current.isV6SoftForkActivated) { + fromTest() + } else { + an[Exception] should be thrownBy(fromTest()) + } + } + + property("Global.fromBigEndianBytes - Long.toBytes") { + def fromTest() = test("fromBigEndianBytes - long", env, ext, + s"""{ + | val l = 1088800L + | val ba = l.toBytes + | Global.fromBigEndianBytes[Long](ba) == l + |} + |""".stripMargin, + null + ) + if(VersionContext.current.isV6SoftForkActivated) { + fromTest() + } else { + an[Exception] should be thrownBy(fromTest()) + } + } + + 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()) + } + } + property("Int.toBytes") { def toBytesTest() = test("Int.toBytes", env, ext, """{