From c1d3ce1440b28e7468179e4e4353b0598ea75139 Mon Sep 17 00:00:00 2001 From: Alexander Slesarenko Date: Thu, 16 May 2024 22:38:46 +0100 Subject: [PATCH 01/19] v6.0-serialize: SigmaDslBuilder.serialize added SMethod declaration --- .../src/main/scala/sigma/SigmaDsl.scala | 3 ++ .../sigma/reflection/ReflectionData.scala | 4 ++ .../src/main/scala/sigma/ast/methods.scala | 37 ++++++++++++++++--- .../scala/sigma/data/CSigmaDslBuilder.scala | 14 +++++-- 4 files changed, 50 insertions(+), 8 deletions(-) diff --git a/core/shared/src/main/scala/sigma/SigmaDsl.scala b/core/shared/src/main/scala/sigma/SigmaDsl.scala index df2b419273..6e306f7a0b 100644 --- a/core/shared/src/main/scala/sigma/SigmaDsl.scala +++ b/core/shared/src/main/scala/sigma/SigmaDsl.scala @@ -727,6 +727,9 @@ trait SigmaDslBuilder { /** Construct a new authenticated dictionary with given parameters and tree root digest. */ def avlTree(operationFlags: Byte, digest: Coll[Byte], keyLength: Int, valueLengthOpt: Option[Int]): AvlTree + /** Serializes the given `value` into bytes using the default serialization format. */ + def serialize[T](value: T)(implicit cT: RType[T]): Coll[Byte] + /** Returns a byte-wise XOR of the two collections of bytes. */ def xor(l: Coll[Byte], r: Coll[Byte]): Coll[Byte] } diff --git a/core/shared/src/main/scala/sigma/reflection/ReflectionData.scala b/core/shared/src/main/scala/sigma/reflection/ReflectionData.scala index 028e68bf72..5cd678b712 100644 --- a/core/shared/src/main/scala/sigma/reflection/ReflectionData.scala +++ b/core/shared/src/main/scala/sigma/reflection/ReflectionData.scala @@ -441,6 +441,10 @@ object ReflectionData { mkMethod(clazz, "sha256", Array[Class[_]](cColl)) { (obj, args) => obj.asInstanceOf[SigmaDslBuilder].sha256(args(0).asInstanceOf[Coll[Byte]]) }, + mkMethod(clazz, "serialize", Array[Class[_]](classOf[Object], classOf[RType[_]])) { (obj, args) => + obj.asInstanceOf[SigmaDslBuilder].serialize[Any]( + args(0).asInstanceOf[Any])(args(1).asInstanceOf[RType[Any]]) + }, mkMethod(clazz, "decodePoint", Array[Class[_]](cColl)) { (obj, args) => obj.asInstanceOf[SigmaDslBuilder].decodePoint(args(0).asInstanceOf[Coll[Byte]]) } diff --git a/data/shared/src/main/scala/sigma/ast/methods.scala b/data/shared/src/main/scala/sigma/ast/methods.scala index e4cf0007e0..dd33802b1d 100644 --- a/data/shared/src/main/scala/sigma/ast/methods.scala +++ b/data/shared/src/main/scala/sigma/ast/methods.scala @@ -5,7 +5,7 @@ import org.ergoplatform.validation._ import sigma._ import sigma.ast.SCollection.{SBooleanArray, SBoxArray, SByteArray, SByteArray2, SHeaderArray} import sigma.ast.SMethod.{MethodCallIrBuilder, MethodCostFunc, javaMethodOf} -import sigma.ast.SType.TypeCode +import sigma.ast.SType.{TypeCode, paramT, tT} import sigma.ast.syntax.{SValue, ValueOps} import sigma.data.OverloadHack.Overloaded1 import sigma.data.{DataValueComparer, KeyValueColl, Nullable, RType, SigmaConstants} @@ -1519,9 +1519,36 @@ case object SGlobalMethods extends MonoTypeMethods { Xor.xorWithCosting(ls, rs) } - protected override def getMethods() = super.getMethods() ++ Seq( - groupGeneratorMethod, - xorMethod - ) + lazy val serializeMethod = SMethod(this, "serialize", + SFunc(Array(SGlobal, tT), SByteArray, Array(paramT)), 3, DynamicCost) + .withIRInfo(MethodCallIrBuilder) + .withInfo(MethodCall, "", + ArgInfo("value", "value to be serialized")) + + + /** Implements evaluation of Global.serialize method call ErgoTree node. + * Called via reflection based on naming convention. + * @see SMethod.evalMethod + */ + def serialize_eval(mc: MethodCall, G: SigmaDslBuilder, value: Any, tpe: RType[Any]) + (implicit E: ErgoTreeEvaluator): Coll[Byte] = { + // TODO v6.0: accumulate cost + G.serialize(value)(tpe) + } + + protected override def getMethods() = super.getMethods() ++ { + if (VersionContext.current.isV6SoftForkActivated) { + Seq( + groupGeneratorMethod, + xorMethod, + serializeMethod + ) + } else { + Seq( + groupGeneratorMethod, + xorMethod + ) + } + } } diff --git a/data/shared/src/main/scala/sigma/data/CSigmaDslBuilder.scala b/data/shared/src/main/scala/sigma/data/CSigmaDslBuilder.scala index 3938feacd3..21b9900028 100644 --- a/data/shared/src/main/scala/sigma/data/CSigmaDslBuilder.scala +++ b/data/shared/src/main/scala/sigma/data/CSigmaDslBuilder.scala @@ -5,13 +5,13 @@ import org.ergoplatform.ErgoBox import org.ergoplatform.validation.ValidationRules import scorex.crypto.hash.{Blake2b256, Sha256} import scorex.utils.Longs -import sigma.ast.{AtLeast, SubstConstants} +import sigma.ast.{AtLeast, SType, SubstConstants} import sigma.crypto.{CryptoConstants, EcPointType, Ecp} import sigma.eval.Extensions.EvalCollOps -import sigma.serialization.{GroupElementSerializer, SigmaSerializer} +import sigma.serialization.{DataSerializer, GroupElementSerializer, SigmaSerializer} import sigma.util.Extensions.BigIntegerOps import sigma.validation.SigmaValidationSettings -import sigma.{AvlTree, BigInt, Box, Coll, CollBuilder, GroupElement, SigmaDslBuilder, SigmaProp, VersionContext} +import sigma.{AvlTree, BigInt, Box, Coll, CollBuilder, Evaluation, GroupElement, SigmaDslBuilder, SigmaProp, VersionContext} import java.math.BigInteger @@ -200,6 +200,14 @@ class CSigmaDslBuilder extends SigmaDslBuilder { dsl => val p = GroupElementSerializer.parse(r) this.GroupElement(p) } + + /** 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) + val w = SigmaSerializer.startWriter() + DataSerializer.serialize(value.asInstanceOf[SType#WrappedType], tpe, w) + Colls.fromArray(w.toBytes) + } } /** Default singleton instance of Global object, which implements global ErgoTree functions. */ From eeb0d4ac0ceda87c6d426728f13ecd6011bb581b Mon Sep 17 00:00:00 2001 From: Alexander Slesarenko Date: Fri, 17 May 2024 11:35:59 +0100 Subject: [PATCH 02/19] v6.0-serialize: added SMethod.runtimeTypeArgs --- .../src/main/scala/sigma/ast/SMethod.scala | 34 ++++++++++++------- .../src/main/scala/sigma/ast/values.scala | 2 ++ .../serialization/MethodCallSerializer.scala | 18 ++++++++-- .../sigma/compiler/phases/SigmaTyper.scala | 2 +- 4 files changed, 39 insertions(+), 17 deletions(-) diff --git a/data/shared/src/main/scala/sigma/ast/SMethod.scala b/data/shared/src/main/scala/sigma/ast/SMethod.scala index 669625ef1e..fea76ecf52 100644 --- a/data/shared/src/main/scala/sigma/ast/SMethod.scala +++ b/data/shared/src/main/scala/sigma/ast/SMethod.scala @@ -50,17 +50,19 @@ case class MethodIRInfo( /** Represents method descriptor. * - * @param objType type or type constructor descriptor - * @param name method name - * @param stype method signature type, - * where `stype.tDom`` - argument type and - * `stype.tRange` - method result type. - * @param methodId method code, it should be unique among methods of the same objType. - * @param costKind cost descriptor for this method - * @param irInfo meta information connecting SMethod with ErgoTree (see [[MethodIRInfo]]) - * @param docInfo optional human readable method description data - * @param costFunc optional specification of how the cost should be computed for the - * given method call (See ErgoTreeEvaluator.calcCost method). + * @param objType type or type constructor descriptor + * @param name method name + * @param stype method signature type, + * where `stype.tDom`` - argument type and + * `stype.tRange` - method result type. + * @param methodId method code, it should be unique among methods of the same objType. + * @param costKind cost descriptor for this method + * @param runtimeTypeArgs list of runtime type parameters which require explicit + * serialization in [[MethodCall]]s + * @param irInfo meta information connecting SMethod with ErgoTree (see [[MethodIRInfo]]) + * @param docInfo optional human readable method description data + * @param costFunc optional specification of how the cost should be computed for the + * given method call (See ErgoTreeEvaluator.calcCost method). */ case class SMethod( objType: MethodsContainer, @@ -68,6 +70,7 @@ case class SMethod( stype: SFunc, methodId: Byte, costKind: CostKind, + runtimeTypeArgs: Seq[STypeVar], irInfo: MethodIRInfo, docInfo: Option[OperationInfo], costFunc: Option[MethodCostFunc]) { @@ -75,6 +78,9 @@ case class SMethod( /** Operation descriptor of this method. */ lazy val opDesc = MethodDesc(this) + /** Return true if this method has runtime type parameters */ + def isRuntimeGeneric: Boolean = runtimeTypeArgs.nonEmpty + /** Finds and keeps the [[RMethod]] instance which corresponds to this method descriptor. * The lazy value is forced only if irInfo.javaMethod == None */ @@ -284,9 +290,11 @@ object SMethod { /** Convenience factory method. */ def apply(objType: MethodsContainer, name: String, stype: SFunc, methodId: Byte, - costKind: CostKind): SMethod = { + costKind: CostKind, + runtimeTypeArgs: Seq[STypeVar] = Nil + ): SMethod = { SMethod( - objType, name, stype, methodId, costKind, + objType, name, stype, methodId, costKind, runtimeTypeArgs, MethodIRInfo(None, None, None), None, None) } diff --git a/data/shared/src/main/scala/sigma/ast/values.scala b/data/shared/src/main/scala/sigma/ast/values.scala index 87c661a00a..ee1bb8b783 100644 --- a/data/shared/src/main/scala/sigma/ast/values.scala +++ b/data/shared/src/main/scala/sigma/ast/values.scala @@ -1298,6 +1298,8 @@ case class MethodCall( method: SMethod, args: IndexedSeq[Value[SType]], typeSubst: Map[STypeVar, SType]) extends Value[SType] { + require(method.runtimeTypeArgs.forall(tyArg => typeSubst.contains(tyArg)), + s"Runtime Generic method call should have concrete type for each runtime type parameter, but was: $this") override def companion = if (args.isEmpty) PropertyCall else MethodCall override def opType: SFunc = SFunc(obj.tpe +: args.map(_.tpe), tpe) diff --git a/data/shared/src/main/scala/sigma/serialization/MethodCallSerializer.scala b/data/shared/src/main/scala/sigma/serialization/MethodCallSerializer.scala index 319a4284e2..f9c7658dda 100644 --- a/data/shared/src/main/scala/sigma/serialization/MethodCallSerializer.scala +++ b/data/shared/src/main/scala/sigma/serialization/MethodCallSerializer.scala @@ -1,7 +1,7 @@ package sigma.serialization import sigma.ast.syntax._ -import sigma.ast.{MethodCall, SContextMethods, SMethod, SType, STypeSubst, Value, ValueCompanion} +import sigma.ast.{MethodCall, SContextMethods, SMethod, SType, STypeSubst, STypeVar, Value, ValueCompanion} import sigma.util.safeNewArray import SigmaByteWriter._ import debox.cfor @@ -23,6 +23,10 @@ case class MethodCallSerializer(cons: (Value[SType], SMethod, IndexedSeq[Value[S w.putValue(mc.obj, objInfo) assert(mc.args.nonEmpty) w.putValues(mc.args, argsInfo, argsItemInfo) + mc.method.runtimeTypeArgs.foreach { a => + val tpe = mc.typeSubst(a) // existence is checked in MethodCall constructor + w.putType(tpe) + } } /** The SMethod instances in STypeCompanions may have type STypeIdent in methods types, @@ -42,7 +46,15 @@ case class MethodCallSerializer(cons: (Value[SType], SMethod, IndexedSeq[Value[S val methodId = r.getByte() val obj = r.getValue() val args = r.getValues() - val method = SMethod.fromIds(typeId, methodId) + val (method, runtimeTypeArgs) = SMethod.fromIds(typeId, methodId) match { + case m if m.isRuntimeGeneric => + val subst = m.runtimeTypeArgs.map { a => + a -> r.getType() // READ + }.toMap + (m.withConcreteTypes(subst), subst) + case m => (m, Map.empty[STypeVar, SType]) + } + val nArgs = args.length val types: Seq[SType] = @@ -61,6 +73,6 @@ case class MethodCallSerializer(cons: (Value[SType], SMethod, IndexedSeq[Value[S BlockchainContextMethodNames.contains(method.name) r.wasUsingBlockchainContext ||= isUsingBlockchainContext - cons(obj, specMethod, args, Map.empty) + cons(obj, specMethod, args, runtimeTypeArgs) } } diff --git a/sc/shared/src/main/scala/sigma/compiler/phases/SigmaTyper.scala b/sc/shared/src/main/scala/sigma/compiler/phases/SigmaTyper.scala index 679d98a18f..764d2b1eb7 100644 --- a/sc/shared/src/main/scala/sigma/compiler/phases/SigmaTyper.scala +++ b/sc/shared/src/main/scala/sigma/compiler/phases/SigmaTyper.scala @@ -139,7 +139,7 @@ class SigmaTyper(val builder: SigmaBuilder, obj.tpe match { case p: SProduct => MethodsContainer.getMethod(p, n) match { - case Some(method @ SMethod(_, _, genFunTpe @ SFunc(_, _, _), _, _, _, _, _)) => + case Some(method @ SMethod(_, _, genFunTpe @ SFunc(_, _, _), _, _, _, _, _, _)) => val subst = Map(genFunTpe.tpeParams.head.ident -> rangeTpe) val concrFunTpe = applySubst(genFunTpe, subst) val expectedArgs = concrFunTpe.asFunc.tDom.tail From 5cbd065a8350faf0c98b98e7c5d5139454532b2c Mon Sep 17 00:00:00 2001 From: Alexander Slesarenko Date: Fri, 17 May 2024 13:22:25 +0100 Subject: [PATCH 03/19] v6.0-serialize: support of explicitTypeArgs in MethodCallSerializer --- .../src/main/scala/sigma/ast/SMethod.scala | 12 ++--- .../src/main/scala/sigma/ast/values.scala | 2 +- .../serialization/MethodCallSerializer.scala | 51 ++++++++++++------- docs/LangSpec.md | 7 ++- 4 files changed, 46 insertions(+), 26 deletions(-) diff --git a/data/shared/src/main/scala/sigma/ast/SMethod.scala b/data/shared/src/main/scala/sigma/ast/SMethod.scala index fea76ecf52..332c74be6b 100644 --- a/data/shared/src/main/scala/sigma/ast/SMethod.scala +++ b/data/shared/src/main/scala/sigma/ast/SMethod.scala @@ -57,8 +57,8 @@ case class MethodIRInfo( * `stype.tRange` - method result type. * @param methodId method code, it should be unique among methods of the same objType. * @param costKind cost descriptor for this method - * @param runtimeTypeArgs list of runtime type parameters which require explicit - * serialization in [[MethodCall]]s + * @param explicitTypeArgs list of type parameters which require explicit + * serialization in [[MethodCall]]s (i.e for deserialize[T], getVar[T], getReg[T]) * @param irInfo meta information connecting SMethod with ErgoTree (see [[MethodIRInfo]]) * @param docInfo optional human readable method description data * @param costFunc optional specification of how the cost should be computed for the @@ -70,7 +70,7 @@ case class SMethod( stype: SFunc, methodId: Byte, costKind: CostKind, - runtimeTypeArgs: Seq[STypeVar], + explicitTypeArgs: Seq[STypeVar], irInfo: MethodIRInfo, docInfo: Option[OperationInfo], costFunc: Option[MethodCostFunc]) { @@ -79,7 +79,7 @@ case class SMethod( lazy val opDesc = MethodDesc(this) /** Return true if this method has runtime type parameters */ - def isRuntimeGeneric: Boolean = runtimeTypeArgs.nonEmpty + def hasExplicitTypeArgs: Boolean = explicitTypeArgs.nonEmpty /** Finds and keeps the [[RMethod]] instance which corresponds to this method descriptor. * The lazy value is forced only if irInfo.javaMethod == None @@ -291,10 +291,10 @@ object SMethod { def apply(objType: MethodsContainer, name: String, stype: SFunc, methodId: Byte, costKind: CostKind, - runtimeTypeArgs: Seq[STypeVar] = Nil + explicitTypeArgs: Seq[STypeVar] = Nil ): SMethod = { SMethod( - objType, name, stype, methodId, costKind, runtimeTypeArgs, + objType, name, stype, methodId, costKind, explicitTypeArgs, MethodIRInfo(None, None, None), None, None) } diff --git a/data/shared/src/main/scala/sigma/ast/values.scala b/data/shared/src/main/scala/sigma/ast/values.scala index ee1bb8b783..7980fd96ce 100644 --- a/data/shared/src/main/scala/sigma/ast/values.scala +++ b/data/shared/src/main/scala/sigma/ast/values.scala @@ -1298,7 +1298,7 @@ case class MethodCall( method: SMethod, args: IndexedSeq[Value[SType]], typeSubst: Map[STypeVar, SType]) extends Value[SType] { - require(method.runtimeTypeArgs.forall(tyArg => typeSubst.contains(tyArg)), + require(method.explicitTypeArgs.forall(tyArg => typeSubst.contains(tyArg)), s"Runtime Generic method call should have concrete type for each runtime type parameter, but was: $this") override def companion = if (args.isEmpty) PropertyCall else MethodCall diff --git a/data/shared/src/main/scala/sigma/serialization/MethodCallSerializer.scala b/data/shared/src/main/scala/sigma/serialization/MethodCallSerializer.scala index f9c7658dda..abc12c9c9e 100644 --- a/data/shared/src/main/scala/sigma/serialization/MethodCallSerializer.scala +++ b/data/shared/src/main/scala/sigma/serialization/MethodCallSerializer.scala @@ -8,6 +8,8 @@ import debox.cfor import sigma.ast.SContextMethods.BlockchainContextMethodNames import sigma.serialization.CoreByteWriter.{ArgInfo, DataInfo} +import scala.collection.compat.immutable.ArraySeq + case class MethodCallSerializer(cons: (Value[SType], SMethod, IndexedSeq[Value[SType]], STypeSubst) => Value[SType]) extends ValueSerializer[MethodCall] { override def opDesc: ValueCompanion = MethodCall @@ -23,7 +25,7 @@ case class MethodCallSerializer(cons: (Value[SType], SMethod, IndexedSeq[Value[S w.putValue(mc.obj, objInfo) assert(mc.args.nonEmpty) w.putValues(mc.args, argsInfo, argsItemInfo) - mc.method.runtimeTypeArgs.foreach { a => + mc.method.explicitTypeArgs.foreach { a => val tpe = mc.typeSubst(a) // existence is checked in MethodCall constructor w.putType(tpe) } @@ -46,18 +48,37 @@ case class MethodCallSerializer(cons: (Value[SType], SMethod, IndexedSeq[Value[S val methodId = r.getByte() val obj = r.getValue() val args = r.getValues() - val (method, runtimeTypeArgs) = SMethod.fromIds(typeId, methodId) match { - case m if m.isRuntimeGeneric => - val subst = m.runtimeTypeArgs.map { a => - a -> r.getType() // READ - }.toMap - (m.withConcreteTypes(subst), subst) - case m => (m, Map.empty[STypeVar, SType]) - } + val method = SMethod.fromIds(typeId, methodId) - val nArgs = args.length + val explicitTypes = if (method.hasExplicitTypeArgs) { + val nTypes = method.explicitTypeArgs.length + val res = safeNewArray[SType](nTypes) + cfor(0)(_ < nTypes, _ + 1) { i => + res(i) = r.getType() + } + ArraySeq.unsafeWrapArray(res) + } else SType.EmptySeq + + val explicitTypeSubst = method.explicitTypeArgs.zip(explicitTypes).toMap + val specMethod = getSpecializedMethodFor(method, explicitTypeSubst, obj, args) + + var isUsingBlockchainContext = specMethod.objType == SContextMethods && + BlockchainContextMethodNames.contains(method.name) + r.wasUsingBlockchainContext ||= isUsingBlockchainContext - val types: Seq[SType] = + cons(obj, specMethod, args, explicitTypeSubst) + } + + def getSpecializedMethodFor( + methodTemplate: SMethod, + explicitTypeSubst: STypeSubst, + obj: SValue, + args: Seq[SValue] + ): SMethod = { + // TODO optimize: avoid repeated transformation of method type + val method = methodTemplate.withConcreteTypes(explicitTypeSubst) + val nArgs = args.length + val argTypes: Seq[SType] = if (nArgs == 0) SType.EmptySeq else { val types = safeNewArray[SType](nArgs) @@ -67,12 +88,6 @@ case class MethodCallSerializer(cons: (Value[SType], SMethod, IndexedSeq[Value[S types } - val specMethod = method.specializeFor(obj.tpe, types) - - var isUsingBlockchainContext = specMethod.objType == SContextMethods && - BlockchainContextMethodNames.contains(method.name) - r.wasUsingBlockchainContext ||= isUsingBlockchainContext - - cons(obj, specMethod, args, runtimeTypeArgs) + method.specializeFor(obj.tpe, argTypes) } } diff --git a/docs/LangSpec.md b/docs/LangSpec.md index ba66748f08..04b345d6d9 100644 --- a/docs/LangSpec.md +++ b/docs/LangSpec.md @@ -68,7 +68,7 @@ The following sections describe ErgoScript and its operations. #### Operations and constructs overview - Binary operations: `>, <, >=, <=, +, -, &&, ||, ==, !=, |, &, *, /, %, ^, ++` -- predefined primitives: `blake2b256`, `byteArrayToBigInt`, `proveDlog` etc. +- predefined primitives: `serialize`, `blake2b256`, `byteArrayToBigInt`, `proveDlog` etc. - val declarations: `val h = blake2b256(pubkey)` - if-then-else clause: `if (x > 0) 1 else 0` - collection literals: `Coll(1, 2, 3, 4)` @@ -1041,6 +1041,11 @@ def deserialize[T](string: String): T * replaced and all other bytes remain exactly the same */ def substConstants[T](scriptBytes: Coll[Byte], positions: Coll[Int], newValues: Coll[T]): Coll[Byte] + +/** Serializes an instance of type T using default serialization format. + * See https://github.com/ScorexFoundation/sigmastate-interpreter/issues/988 for more details + */ +def serialize[T](value: T): Coll[Byte] ``` ## Examples From 3f4508abdf9f259c321dbb4105360baf96f77ef7 Mon Sep 17 00:00:00 2001 From: Alexander Slesarenko Date: Fri, 17 May 2024 15:26:15 +0100 Subject: [PATCH 04/19] v6.0-serialize: SigmaParserTest for serialize() --- .../sigmastate/helpers/SigmaPPrint.scala | 6 ++---- .../sigmastate/lang/SigmaParserTest.scala | 20 +++++++++++++++++++ .../sigmastate/helpers/SigmaPPrintSpec.scala | 1 - 3 files changed, 22 insertions(+), 5 deletions(-) rename {sc => parsers}/shared/src/test/scala/sigmastate/helpers/SigmaPPrint.scala (98%) diff --git a/sc/shared/src/test/scala/sigmastate/helpers/SigmaPPrint.scala b/parsers/shared/src/test/scala/sigmastate/helpers/SigmaPPrint.scala similarity index 98% rename from sc/shared/src/test/scala/sigmastate/helpers/SigmaPPrint.scala rename to parsers/shared/src/test/scala/sigmastate/helpers/SigmaPPrint.scala index 1b0f7b112d..24aaeddefd 100644 --- a/sc/shared/src/test/scala/sigmastate/helpers/SigmaPPrint.scala +++ b/parsers/shared/src/test/scala/sigmastate/helpers/SigmaPPrint.scala @@ -5,15 +5,13 @@ import org.ergoplatform.ErgoBox.RegisterId import org.ergoplatform.settings.ErgoAlgos import pprint.{PPrinter, Tree} import sigma.ast.SCollection.{SBooleanArray, SByteArray, SByteArray2} -import sigma.ast._ +import sigma.ast.{ConstantNode, FuncValue, MethodCall, ValueCompanion, _} import sigma.crypto.EcPointType import sigma.data.{AvlTreeData, AvlTreeFlags, CollType, PrimitiveType, TrivialProp} import sigma.serialization.GroupElementSerializer import sigma.{Coll, GroupElement} -import sigma.ast.{ConstantNode, FuncValue, ValueCompanion} -import sigmastate._ import sigmastate.crypto.GF2_192_Poly -import sigma.ast.MethodCall + import java.math.BigInteger import scala.collection.compat.immutable.ArraySeq import scala.collection.mutable diff --git a/parsers/shared/src/test/scala/sigmastate/lang/SigmaParserTest.scala b/parsers/shared/src/test/scala/sigmastate/lang/SigmaParserTest.scala index 02b28f86ca..70aa540a4f 100644 --- a/parsers/shared/src/test/scala/sigmastate/lang/SigmaParserTest.scala +++ b/parsers/shared/src/test/scala/sigmastate/lang/SigmaParserTest.scala @@ -14,6 +14,7 @@ import SigmaPredef.PredefinedFuncRegistry import sigma.ast.syntax._ import sigmastate.lang.parsers.ParserException import sigma.serialization.OpCodes +import sigmastate.helpers.SigmaPPrint class SigmaParserTest extends AnyPropSpec with ScalaCheckPropertyChecks with Matchers with LangTests { import StdSigmaBuilder._ @@ -34,6 +35,14 @@ class SigmaParserTest extends AnyPropSpec with ScalaCheckPropertyChecks with Mat } } + def checkParsed(x: String, expected: SValue) = { + val parsed = parse(x) + if (expected != parsed) { + SigmaPPrint.pprintln(parsed, width = 100) + } + parsed shouldBe expected + } + def parseWithException(x: String): SValue = { SigmaParser(x) match { case Parsed.Success(v, _) => v @@ -894,6 +903,17 @@ class SigmaParserTest extends AnyPropSpec with ScalaCheckPropertyChecks with Mat ) } + property("serialize") { + checkParsed("serialize(1)", Apply(Ident("serialize", NoType), Array(IntConstant(1)))) + checkParsed("serialize((1, 2L))", + Apply(Ident("serialize", NoType), Array(Tuple(Vector(IntConstant(1), LongConstant(2L)))))) + checkParsed("serialize(Coll(1, 2, 3))", + Apply( + Ident("serialize", NoType), + Array(Apply(Ident("Coll", NoType), Array(IntConstant(1), IntConstant(2), IntConstant(3)))) + )) + } + property("single name pattern fail") { fail("{val (a,b) = (1,2)}", 1, 6) } diff --git a/sc/jvm/src/test/scala/sigmastate/helpers/SigmaPPrintSpec.scala b/sc/jvm/src/test/scala/sigmastate/helpers/SigmaPPrintSpec.scala index 54c0f652dc..ffd591b0df 100644 --- a/sc/jvm/src/test/scala/sigmastate/helpers/SigmaPPrintSpec.scala +++ b/sc/jvm/src/test/scala/sigmastate/helpers/SigmaPPrintSpec.scala @@ -8,7 +8,6 @@ import sigma.SigmaDslTesting import sigma.ast._ import sigma.data.{AvlTreeData, AvlTreeFlags, CBox, CollType, Digest32Coll} import ErgoTree.HeaderType -import sigmastate.eval._ import sigma.ast.MethodCall import sigma.serialization.OpCodes import sigmastate.utils.Helpers From 06386d46aaeaf3339a7e20e8e44dac5394d605b8 Mon Sep 17 00:00:00 2001 From: Alexander Slesarenko Date: Fri, 17 May 2024 16:53:23 +0100 Subject: [PATCH 05/19] v6.0-serialize: SigmaBinderTest and SigmaTyperTest --- .../main/scala/sigma/ast/SigmaPredef.scala | 23 +++++++++- .../scala/sigmastate/lang/LangTests.scala | 6 +++ .../sigma/compiler/phases/SigmaBinder.scala | 3 ++ .../sigma/compiler/phases/SigmaTyper.scala | 1 + .../sigmastate/lang/SigmaBinderTest.scala | 21 +++++++++ .../sigmastate/lang/SigmaTyperTest.scala | 43 ++++++++++++++++++- 6 files changed, 93 insertions(+), 4 deletions(-) diff --git a/data/shared/src/main/scala/sigma/ast/SigmaPredef.scala b/data/shared/src/main/scala/sigma/ast/SigmaPredef.scala index 631f7f2d75..f2da24d2df 100644 --- a/data/shared/src/main/scala/sigma/ast/SigmaPredef.scala +++ b/data/shared/src/main/scala/sigma/ast/SigmaPredef.scala @@ -403,6 +403,24 @@ object SigmaPredef { ArgInfo("default", "optional default value, if register is not available"))) ) + val SerializeFunc = PredefinedFunc("serialize", + Lambda(Seq(paramT), Array("value" -> tT), SByteArray, None), + PredefFuncInfo( + { case (_, args @ Seq(value)) => + MethodCall.typed[Value[SCollection[SByte.type]]]( + Global, + SGlobalMethods.serializeMethod.withConcreteTypes(Map(tT -> value.tpe)), + args.toIndexedSeq, + Map() + ) + }), + OperationInfo(MethodCall, + """ + """.stripMargin, + Seq(ArgInfo("value", "")) + ) + ) + val globalFuncs: Map[String, PredefinedFunc] = Seq( AllOfFunc, AnyOfFunc, @@ -430,7 +448,8 @@ object SigmaPredef { AvlTreeFunc, SubstConstantsFunc, ExecuteFromVarFunc, - ExecuteFromSelfRegFunc + ExecuteFromSelfRegFunc, + SerializeFunc ).map(f => f.name -> f).toMap def comparisonOp(symbolName: String, opDesc: ValueCompanion, desc: String, args: Seq[ArgInfo]) = { @@ -544,7 +563,7 @@ object SigmaPredef { val funcs: Map[String, PredefinedFunc] = globalFuncs ++ infixFuncs ++ unaryFuncs - /** WARNING: This operations are not used in frontend, and should be be used. + /** WARNING: This operations are not used in frontend, and should not be used. * They are used in SpecGen only the source of metadata for the corresponding ErgoTree nodes. */ val specialFuncs: Map[String, PredefinedFunc] = Seq( diff --git a/parsers/shared/src/test/scala/sigmastate/lang/LangTests.scala b/parsers/shared/src/test/scala/sigmastate/lang/LangTests.scala index 32943bca44..de83070ac3 100644 --- a/parsers/shared/src/test/scala/sigmastate/lang/LangTests.scala +++ b/parsers/shared/src/test/scala/sigmastate/lang/LangTests.scala @@ -79,4 +79,10 @@ trait LangTests extends Matchers with NegativeTesting { node }))(tree) } + + /** Execute the given `block` having `version` as both activated and ErgoTree version. */ + def runWithVersion[T](version: Byte)(block: => T): T = { + VersionContext.withVersions(version, version)(block) + } + } diff --git a/sc/shared/src/main/scala/sigma/compiler/phases/SigmaBinder.scala b/sc/shared/src/main/scala/sigma/compiler/phases/SigmaBinder.scala index af5be938be..d4943ef892 100644 --- a/sc/shared/src/main/scala/sigma/compiler/phases/SigmaBinder.scala +++ b/sc/shared/src/main/scala/sigma/compiler/phases/SigmaBinder.scala @@ -105,6 +105,9 @@ class SigmaBinder(env: ScriptEnv, builder: SigmaBuilder, case a @ Apply(PKFunc.symNoType, args) => Some(PKFunc.irInfo.irBuilder(PKFunc.sym, args).withPropagatedSrcCtx(a.sourceContext)) + case a @ Apply(predefFuncRegistry.SerializeFunc.symNoType, args) => + Some(predefFuncRegistry.SerializeFunc.irInfo.irBuilder(PKFunc.sym, args).withPropagatedSrcCtx(a.sourceContext)) + case sel @ Select(obj, "isEmpty", _) => Some(mkLogicalNot(mkSelect(obj, "isDefined").asBoolValue).withPropagatedSrcCtx(sel.sourceContext)) diff --git a/sc/shared/src/main/scala/sigma/compiler/phases/SigmaTyper.scala b/sc/shared/src/main/scala/sigma/compiler/phases/SigmaTyper.scala index 764d2b1eb7..f9b52fe061 100644 --- a/sc/shared/src/main/scala/sigma/compiler/phases/SigmaTyper.scala +++ b/sc/shared/src/main/scala/sigma/compiler/phases/SigmaTyper.scala @@ -511,6 +511,7 @@ class SigmaTyper(val builder: SigmaBuilder, case v: SigmaBoolean => v case v: Upcast[_, _] => v case v @ Select(_, _, Some(_)) => v + case v @ MethodCall(_, _, _, _) => v case v => error(s"Don't know how to assignType($v)", v.sourceContext) }).ensuring(v => v.tpe != NoType, diff --git a/sc/shared/src/test/scala/sigmastate/lang/SigmaBinderTest.scala b/sc/shared/src/test/scala/sigmastate/lang/SigmaBinderTest.scala index b4b4ad20cd..54bd89c9c2 100644 --- a/sc/shared/src/test/scala/sigmastate/lang/SigmaBinderTest.scala +++ b/sc/shared/src/test/scala/sigmastate/lang/SigmaBinderTest.scala @@ -10,10 +10,12 @@ import sigma.ast.syntax.SValue import sigmastate._ import sigmastate.interpreter.Interpreter.ScriptEnv import SigmaPredef.PredefinedFuncRegistry +import sigma.VersionContext import sigma.ast.syntax._ import sigma.compiler.phases.SigmaBinder import sigma.eval.SigmaDsl import sigma.exceptions.BinderException +import sigmastate.helpers.SigmaPPrint class SigmaBinderTest extends AnyPropSpec with ScalaCheckPropertyChecks with Matchers with LangTests { import StdSigmaBuilder._ @@ -29,6 +31,14 @@ class SigmaBinderTest extends AnyPropSpec with ScalaCheckPropertyChecks with Mat res } + def checkBound(env: ScriptEnv, x: String, expected: SValue) = { + val bound = bind(env, x) + if (expected != bound) { + SigmaPPrint.pprintln(bound, width = 100) + } + bound shouldBe expected + } + private def fail(env: ScriptEnv, x: String, expectedLine: Int, expectedCol: Int): Unit = { val builder = TransformingSigmaBuilder val ast = SigmaParser(x).get.value @@ -203,4 +213,15 @@ class SigmaBinderTest extends AnyPropSpec with ScalaCheckPropertyChecks with Mat e.source shouldBe Some(SourceContext(2, 5, "val x = 10")) } + property("predefined `serialize` should be transformed to MethodCall") { + runWithVersion(VersionContext.V6SoftForkVersion) { + checkBound(env, "serialize(1)", + MethodCall.typed[Value[SCollection[SByte.type]]]( + Global, + SGlobalMethods.getMethodByName("serialize").withConcreteTypes(Map(STypeVar("T") -> SInt)), + Array(IntConstant(1)), + Map() + )) + } + } } diff --git a/sc/shared/src/test/scala/sigmastate/lang/SigmaTyperTest.scala b/sc/shared/src/test/scala/sigmastate/lang/SigmaTyperTest.scala index 6b93b098ea..2c3bd44d39 100644 --- a/sc/shared/src/test/scala/sigmastate/lang/SigmaTyperTest.scala +++ b/sc/shared/src/test/scala/sigmastate/lang/SigmaTyperTest.scala @@ -5,7 +5,7 @@ import org.ergoplatform._ import org.scalatest.matchers.should.Matchers import org.scalatest.propspec.AnyPropSpec import org.scalatestplus.scalacheck.ScalaCheckPropertyChecks -import sigma.Colls +import sigma.{Colls, VersionContext} import sigma.ast.SCollection._ import sigma.ast._ import sigma.ast.syntax.{SValue, SigmaPropValue, SigmaPropValueOps} @@ -21,6 +21,8 @@ import sigma.serialization.generators.ObjectGenerators import sigma.ast.Select import sigma.compiler.phases.{SigmaBinder, SigmaTyper} import sigma.exceptions.TyperException +import sigmastate.exceptions.MethodNotFound +import sigmastate.helpers.SigmaPPrint class SigmaTyperTest extends AnyPropSpec with ScalaCheckPropertyChecks with Matchers with LangTests with ObjectGenerators { @@ -39,7 +41,12 @@ class SigmaTyperTest extends AnyPropSpec val typer = new SigmaTyper(builder, predefinedFuncRegistry, typeEnv, lowerMethodCalls = true) val typed = typer.typecheck(bound) assertSrcCtxForAllNodes(typed) - if (expected != null) typed shouldBe expected + if (expected != null) { + if (expected != typed) { + SigmaPPrint.pprintln(typed, width = 100) + } + typed shouldBe expected + } typed.tpe } catch { case e: Exception => throw e @@ -663,4 +670,36 @@ class SigmaTyperTest extends AnyPropSpec ) typecheck(customEnv, "substConstants(scriptBytes, positions, newVals)") shouldBe SByteArray } + + property("Global.serialize") { + runWithVersion(VersionContext.V6SoftForkVersion) { + typecheck(env, "Global.serialize(1)", + MethodCall.typed[Value[SCollection[SByte.type]]]( + Global, + SGlobalMethods.getMethodByName("serialize").withConcreteTypes(Map(STypeVar("T") -> SInt)), + Array(IntConstant(1)), + Map() + )) shouldBe SByteArray + } + + runWithVersion((VersionContext.V6SoftForkVersion - 1).toByte) { + assertExceptionThrown( + typecheck(env, "Global.serialize(1)"), + exceptionLike[MethodNotFound]("Cannot find method 'serialize' in in the object Global") + ) + } + } + + property("predefined serialize") { + runWithVersion(VersionContext.V6SoftForkVersion) { + typecheck(env, "serialize((1, 2L))", + expected = MethodCall.typed[Value[SCollection[SByte.type]]]( + Global, + SGlobalMethods.getMethodByName("serialize").withConcreteTypes(Map(STypeVar("T") -> SPair(SInt, SLong))), + Array(Tuple(Vector(IntConstant(1), LongConstant(2L)))), + Map() + )) shouldBe SByteArray + } + } + } From f7beab4a1d7f8d46b26e4e5e41bb0775dc8fd525 Mon Sep 17 00:00:00 2001 From: Alexander Slesarenko Date: Fri, 17 May 2024 17:43:48 +0100 Subject: [PATCH 06/19] v6.0-serialize: refactor SigmaDslSpecification towards LanguageSpecifications --- .../sigma/LanguageSpecificationBase.scala | 126 +++++++++++++++++ ...on.scala => LanguageSpecificationV5.scala} | 133 ++---------------- .../scala/sigma/LanguageSpecificationV6.scala | 24 ++++ 3 files changed, 163 insertions(+), 120 deletions(-) create mode 100644 sc/shared/src/test/scala/sigma/LanguageSpecificationBase.scala rename sc/shared/src/test/scala/sigma/{SigmaDslSpecification.scala => LanguageSpecificationV5.scala} (98%) create mode 100644 sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala diff --git a/sc/shared/src/test/scala/sigma/LanguageSpecificationBase.scala b/sc/shared/src/test/scala/sigma/LanguageSpecificationBase.scala new file mode 100644 index 0000000000..2bb44fc910 --- /dev/null +++ b/sc/shared/src/test/scala/sigma/LanguageSpecificationBase.scala @@ -0,0 +1,126 @@ +package sigma + +import org.scalatest.BeforeAndAfterAll +import sigma.ast.JitCost +import sigma.eval.{EvalSettings, Profiler} +import sigmastate.CompilerCrossVersionProps +import sigmastate.interpreter.CErgoTreeEvaluator +import scala.util.Success + +/** Base class for language test suites (one suite for each language version: 5.0, 6.0, etc.) + * Each suite tests every method of every SigmaDsl type to be equivalent to + * the evaluation of the corresponding ErgoScript operation. + * + * The properties of this suite exercise two interpreters: the current (aka `old` + * interpreter) and the new interpreter for a next soft-fork. After the soft-fork is + * released, the new interpreter becomes current at which point the `old` and `new` + * interpreters in this suite should be equivalent. This change is reflected in this + * suite by commiting changes in expected values. + * The `old` and `new` interpreters are compared like the following: + * 1) for existingFeature the interpreters should be equivalent + * 2) for changedFeature the test cases contain different expected values + * 3) for newFeature the old interpreter should throw and the new interpreter is checked + * against expected values. + * + * This suite can be used for Cost profiling, i.e. measurements of operations times and + * comparing them with cost parameters of the operations. + * + * The following settings should be specified for profiling: + * isMeasureOperationTime = true + * isMeasureScriptTime = true + * isLogEnabled = false + * printTestVectors = false + * costTracingEnabled = false + * isTestRun = true + * perTestWarmUpIters = 1 + * nBenchmarkIters = 1 + */ +abstract class LanguageSpecificationBase extends SigmaDslTesting + with CompilerCrossVersionProps + with BeforeAndAfterAll { suite => + + /** Version of the language (ErgoScript/ErgoTree) which is specified by this suite. */ + def languageVersion: Byte + + /** Use VersionContext so that each property in this suite runs under correct + * parameters. + */ + protected override def testFun_Run(testName: String, testFun: => Any): Unit = { + VersionContext.withVersions(activatedVersionInTests, ergoTreeVersionInTests) { + super.testFun_Run(testName, testFun) + } + } + + implicit override val generatorDrivenConfig: PropertyCheckConfiguration = PropertyCheckConfiguration(minSuccessful = 30) + + val evalSettingsInTests = CErgoTreeEvaluator.DefaultEvalSettings.copy( + isMeasureOperationTime = true, + isMeasureScriptTime = true, + isLogEnabled = false, // don't commit the `true` value (travis log is too high) + printTestVectors = false, // don't commit the `true` value (travis log is too high) + + /** Should always be enabled in tests (and false by default) + * Should be disabled for cost profiling, which case the new costs are not checked. + */ + costTracingEnabled = true, + profilerOpt = Some(CErgoTreeEvaluator.DefaultProfiler), + isTestRun = true + ) + + def warmupSettings(p: Profiler) = evalSettingsInTests.copy( + isLogEnabled = false, + printTestVectors = false, + profilerOpt = Some(p) + ) + + implicit override def evalSettings: EvalSettings = { + warmupProfiler match { + case Some(p) => warmupSettings(p) + case _ => evalSettingsInTests + } + } + + override val perTestWarmUpIters = 0 + + override val nBenchmarkIters = 0 + + override val okRunTestsWithoutMCLowering: Boolean = true + + implicit def IR = createIR() + + def testCases[A, B](cases: Seq[(A, Expected[B])], f: Feature[A, B]) = { + val table = Table(("x", "y"), cases: _*) + forAll(table) { (x, expectedRes) => + val res = f.checkEquality(x) + val resValue = res.map(_._1) + val (expected, expDetailsOpt) = expectedRes.newResults(ergoTreeVersionInTests) + checkResult(resValue, expected.value, failOnTestVectors = true, + "SigmaDslSpecifiction#testCases: compare expected new result with res = f.checkEquality(x)") + res match { + case Success((value, details)) => + details.cost shouldBe JitCost(expected.verificationCost.get) + expDetailsOpt.foreach(expDetails => + if (details.trace != expDetails.trace) { + printCostDetails(f.script, details) + details.trace shouldBe expDetails.trace + } + ) + } + } + } + + override protected def beforeAll(): Unit = { + prepareSamples[BigInt] + prepareSamples[GroupElement] + prepareSamples[AvlTree] + prepareSamples[Box] + prepareSamples[PreHeader] + prepareSamples[Header] + prepareSamples[(BigInt, BigInt)] + prepareSamples[(GroupElement, GroupElement)] + prepareSamples[(AvlTree, AvlTree)] + prepareSamples[(Box, Box)] + prepareSamples[(PreHeader, PreHeader)] + prepareSamples[(Header, Header)] + } +} diff --git a/sc/shared/src/test/scala/sigma/SigmaDslSpecification.scala b/sc/shared/src/test/scala/sigma/LanguageSpecificationV5.scala similarity index 98% rename from sc/shared/src/test/scala/sigma/SigmaDslSpecification.scala rename to sc/shared/src/test/scala/sigma/LanguageSpecificationV5.scala index c820e65e73..eabbf776aa 100644 --- a/sc/shared/src/test/scala/sigma/SigmaDslSpecification.scala +++ b/sc/shared/src/test/scala/sigma/LanguageSpecificationV5.scala @@ -5,31 +5,28 @@ import org.ergoplatform._ import org.ergoplatform.settings.ErgoAlgos import org.scalacheck.Arbitrary._ import org.scalacheck.{Arbitrary, Gen} -import org.scalatest.BeforeAndAfterAll import scorex.crypto.authds.avltree.batch._ import scorex.crypto.authds.{ADKey, ADValue} import scorex.crypto.hash.{Blake2b256, Digest32} import scorex.util.ModifierId import sigma.Extensions.{ArrayOps, CollOps} +import sigma.ast.ErgoTree.{HeaderType, ZeroHeader} import sigma.ast.SCollection._ -import sigma.ast._ import sigma.ast.syntax._ +import sigma.ast.{Apply, MethodCall, PropertyCall, _} +import sigma.data.OrderingOps._ import sigma.data.RType._ import sigma.data._ +import sigma.eval.Extensions.{ByteExt, IntExt, LongExt, ShortExt} +import sigma.eval.{CostDetails, EvalSettings, SigmaDsl, TracedCost} +import sigma.exceptions.InvalidType +import sigma.serialization.ValueCodes.OpCode import sigma.util.Extensions.{BooleanOps, IntOps, LongOps} import sigma.{VersionContext, ast, data, _} -import ErgoTree.{HeaderType, ZeroHeader} -import sigma.eval.{CostDetails, EvalSettings, Profiler, SigmaDsl, TracedCost} -import sigmastate._ import sigmastate.eval.Extensions.AvlTreeOps -import sigma.eval.Extensions.{ByteExt, IntExt, LongExt, ShortExt} -import OrderingOps._ import sigmastate.eval._ import sigmastate.helpers.TestingHelpers._ import sigmastate.interpreter._ -import sigma.ast.{Apply, MethodCall, PropertyCall} -import sigma.exceptions.InvalidType -import sigma.serialization.ValueCodes.OpCode import sigmastate.utils.Extensions._ import sigmastate.utils.Helpers import sigmastate.utils.Helpers._ @@ -38,122 +35,18 @@ import java.math.BigInteger import scala.collection.compat.immutable.ArraySeq import scala.util.{Failure, Success} -/** This suite tests every method of every SigmaDsl type to be equivalent to - * the evaluation of the corresponding ErgoScript operation. - * - * The properties of this suite excercise two interpreters: the current (aka `old` - * interpreter) and the new interpreter for a next soft-fork. After the soft-fork is - * released, the new interpreter becomes current at which point the `old` and `new` - * interpreters in this suite should be equivalent. This change is reflected in this - * suite by commiting changes in expected values. - * The `old` and `new` interpreters are compared like the following: - * 1) for existingFeature the interpreters should be equivalent - * 2) for changedFeature the test cases contain different expected values - * 3) for newFeature the old interpreter should throw and the new interpreter is checked - * against expected values. - * - * This suite can be used for Cost profiling, i.e. measurements of operations times and - * comparing them with cost parameteres of the operations. + +/** This suite tests all operations for v5.0 version of the language. + * The base classes establish the infrastructure for the tests. * - * The following settings should be specified for profiling: - * isMeasureOperationTime = true - * isMeasureScriptTime = true - * isLogEnabled = false - * printTestVectors = false - * costTracingEnabled = false - * isTestRun = true - * perTestWarmUpIters = 1 - * nBenchmarkIters = 1 + * @see SigmaDslSpecificationBase */ -class SigmaDslSpecification extends SigmaDslTesting - with CompilerCrossVersionProps - with BeforeAndAfterAll { suite => - - /** Use VersionContext so that each property in this suite runs under correct - * parameters. - */ - protected override def testFun_Run(testName: String, testFun: => Any): Unit = { - VersionContext.withVersions(activatedVersionInTests, ergoTreeVersionInTests) { - super.testFun_Run(testName, testFun) - } - } - - implicit override val generatorDrivenConfig = PropertyCheckConfiguration(minSuccessful = 30) - - val evalSettingsInTests = CErgoTreeEvaluator.DefaultEvalSettings.copy( - isMeasureOperationTime = true, - isMeasureScriptTime = true, - isLogEnabled = false, // don't commit the `true` value (travis log is too high) - printTestVectors = false, // don't commit the `true` value (travis log is too high) - - /** Should always be enabled in tests (and false by default) - * Should be disabled for cost profiling, which case the new costs are not checked. - */ - costTracingEnabled = true, - - profilerOpt = Some(CErgoTreeEvaluator.DefaultProfiler), - isTestRun = true - ) - - def warmupSettings(p: Profiler) = evalSettingsInTests.copy( - isLogEnabled = false, - printTestVectors = false, - profilerOpt = Some(p) - ) - - implicit override def evalSettings: EvalSettings = { - warmupProfiler match { - case Some(p) => warmupSettings(p) - case _ => evalSettingsInTests - } - } - - override val perTestWarmUpIters = 0 - - override val nBenchmarkIters = 0 - - override val okRunTestsWithoutMCLowering: Boolean = true +class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => - implicit def IR = createIR() - - def testCases[A, B](cases: Seq[(A, Expected[B])], f: Feature[A, B]) = { - val table = Table(("x", "y"), cases:_*) - forAll(table) { (x, expectedRes) => - val res = f.checkEquality(x) - val resValue = res.map(_._1) - val (expected, expDetailsOpt) = expectedRes.newResults(ergoTreeVersionInTests) - checkResult(resValue, expected.value, failOnTestVectors = true, - "SigmaDslSpecifiction#testCases: compare expected new result with res = f.checkEquality(x)") - res match { - case Success((value, details)) => - details.cost shouldBe JitCost(expected.verificationCost.get) - expDetailsOpt.foreach(expDetails => - if (details.trace != expDetails.trace) { - printCostDetails(f.script, details) - details.trace shouldBe expDetails.trace - } - ) - } - } - } + override def languageVersion: Byte = VersionContext.JitActivationVersion import TestData._ - override protected def beforeAll(): Unit = { - prepareSamples[BigInt] - prepareSamples[GroupElement] - prepareSamples[AvlTree] - prepareSamples[Box] - prepareSamples[PreHeader] - prepareSamples[Header] - prepareSamples[(BigInt, BigInt)] - prepareSamples[(GroupElement, GroupElement)] - prepareSamples[(AvlTree, AvlTree)] - prepareSamples[(Box, Box)] - prepareSamples[(PreHeader, PreHeader)] - prepareSamples[(Header, Header)] - } - ///===================================================== /// CostDetails shared among test cases ///----------------------------------------------------- diff --git a/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala b/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala new file mode 100644 index 0000000000..b1db0e0eda --- /dev/null +++ b/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala @@ -0,0 +1,24 @@ +package sigma + +/** This suite tests all operations for v6.0 version of the language. + * The base classes establish the infrastructure for the tests. + * + * @see SigmaDslSpecificationBase + */ +class LanguageSpecificationV6 extends LanguageSpecificationBase { suite => + override def languageVersion: Byte = VersionContext.V6SoftForkVersion + + import TestData._ + +// property("Global.serialize") { +// lazy val toBytes = newFeature( +// (x: Byte) => x.toBytes, +// (x: Byte) => x.toBytes, +// "{ (x: Byte) => x.toBytes }") +// val cases = Seq( +// (0.toByte, Success(Coll(0.toByte))), +// (1.toByte, Success(Coll(1.toByte))) +// ) +// testCases(cases, toBytes) +// } +} From cfd6e7befcee975a6f278d1c460a827d74165ba4 Mon Sep 17 00:00:00 2001 From: Alexander Slesarenko Date: Sun, 19 May 2024 13:16:37 +0100 Subject: [PATCH 07/19] v6.0-serialize: feature tests for Byte an Short --- .../validation/ValidationRules.scala | 17 +++++- .../src/main/scala/sigma/ast/methods.scala | 7 ++- .../sigma/compiler/ir/GraphBuilding.scala | 3 + .../ir/wrappers/sigma/SigmaDslUnit.scala | 1 + .../ir/wrappers/sigma/impl/SigmaDslImpl.scala | 15 +++++ .../scala/sigma/LanguageSpecificationV6.scala | 58 +++++++++++++++---- .../test/scala/sigma/SigmaDslTesting.scala | 52 +++++++++++------ 7 files changed, 122 insertions(+), 31 deletions(-) diff --git a/data/shared/src/main/scala/org/ergoplatform/validation/ValidationRules.scala b/data/shared/src/main/scala/org/ergoplatform/validation/ValidationRules.scala index 9d4de47a99..07fe8db0ee 100644 --- a/data/shared/src/main/scala/org/ergoplatform/validation/ValidationRules.scala +++ b/data/shared/src/main/scala/org/ergoplatform/validation/ValidationRules.scala @@ -155,6 +155,20 @@ object ValidationRules { override protected lazy val settings: SigmaValidationSettings = currentSettings } + object CheckMinimalErgoTreeVersion extends ValidationRule(1016, + "ErgoTree should have at least required version") with SoftForkWhenReplaced { + override protected lazy val settings: SigmaValidationSettings = currentSettings + + final def apply(currentVersion: Byte, minVersion: Byte): Unit = { + checkRule() + if (currentVersion < minVersion) { + throwValidationException( + new SigmaException(s"ErgoTree should have at least $minVersion version, but was $currentVersion"), + Array(currentVersion, minVersion)) + } + } + } + val ruleSpecs: Seq[ValidationRule] = Seq( CheckDeserializedScriptType, CheckDeserializedScriptIsSigmaProp, @@ -171,7 +185,8 @@ object ValidationRules { CheckHeaderSizeBit, CheckCostFuncOperation, CheckPositionLimit, - CheckLoopLevelInCostFunction + CheckLoopLevelInCostFunction, + CheckMinimalErgoTreeVersion ) /** Validation settings that correspond to the current version of the ErgoScript implementation. diff --git a/data/shared/src/main/scala/sigma/ast/methods.scala b/data/shared/src/main/scala/sigma/ast/methods.scala index dd33802b1d..3f27f85e2d 100644 --- a/data/shared/src/main/scala/sigma/ast/methods.scala +++ b/data/shared/src/main/scala/sigma/ast/methods.scala @@ -1,6 +1,7 @@ package sigma.ast import org.ergoplatform._ +import org.ergoplatform.validation.ValidationRules.CheckMinimalErgoTreeVersion import org.ergoplatform.validation._ import sigma._ import sigma.ast.SCollection.{SBooleanArray, SBoxArray, SByteArray, SByteArray2, SHeaderArray} @@ -1530,10 +1531,12 @@ case object SGlobalMethods extends MonoTypeMethods { * Called via reflection based on naming convention. * @see SMethod.evalMethod */ - def serialize_eval(mc: MethodCall, G: SigmaDslBuilder, value: Any, tpe: RType[Any]) + def serialize_eval(mc: MethodCall, G: SigmaDslBuilder, value: SType#WrappedType) (implicit E: ErgoTreeEvaluator): Coll[Byte] = { // TODO v6.0: accumulate cost - G.serialize(value)(tpe) + CheckMinimalErgoTreeVersion(E.context.currentErgoTreeVersion, VersionContext.V6SoftForkVersion) + val t = Evaluation.stypeToRType(mc.args(0).tpe) + G.serialize(value)(t) } protected override def getMethods() = super.getMethods() ++ { 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 7c7b80d39a..a6a244778e 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/GraphBuilding.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/GraphBuilding.scala @@ -1146,6 +1146,9 @@ 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.serializeMethod.name => + val value = asRep[Any](argsV(0)) + g.serialize(value) case _ => throwError } case _ => throwError 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 2a6a341686..d7e574c68c 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 @@ -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 serialize[T](value: Ref[T]): Ref[Coll[Byte]] }; 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 c113cb7de3..9cd524149d 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 @@ -1945,6 +1945,14 @@ object SigmaDslBuilder extends EntityObject("SigmaDslBuilder") { Array[AnyRef](l, r), true, false, element[Coll[Byte]])) } + + def serialize[T](value: Ref[T]): Ref[Coll[Byte]] = { + asRep[Coll[Byte]](mkMethodCall(self, + SigmaDslBuilderClass.getMethod("serialize", classOf[Sym]), + Array[AnyRef](value), + true, true, element[Coll[Byte]])) + } + } implicit object LiftableSigmaDslBuilder @@ -2104,6 +2112,13 @@ object SigmaDslBuilder extends EntityObject("SigmaDslBuilder") { Array[AnyRef](l, r), true, true, element[Coll[Byte]])) } + + def serialize[T](value: Ref[T]): Ref[Coll[Byte]] = { + asRep[Coll[Byte]](mkMethodCall(source, + SigmaDslBuilderClass.getMethod("serialize", classOf[Sym]), + Array[AnyRef](value), + true, true, element[Coll[Byte]])) + } } // entityUnref: single unref method for each type family diff --git a/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala b/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala index b1db0e0eda..16b8fffbf1 100644 --- a/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala +++ b/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala @@ -1,5 +1,11 @@ package sigma +import sigma.ast.{FuncValue, Global, MethodCall, SByte, SCollection, SGlobalMethods, STypeVar, ValUse, Value} +import sigma.data.RType +import sigma.eval.SigmaDsl + +import scala.util.Success + /** This suite tests all operations for v6.0 version of the language. * The base classes establish the infrastructure for the tests. * @@ -10,15 +16,45 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite => import TestData._ -// property("Global.serialize") { -// lazy val toBytes = newFeature( -// (x: Byte) => x.toBytes, -// (x: Byte) => x.toBytes, -// "{ (x: Byte) => x.toBytes }") -// val cases = Seq( -// (0.toByte, Success(Coll(0.toByte))), -// (1.toByte, Success(Coll(1.toByte))) -// ) -// testCases(cases, toBytes) -// } + def mkSerializeFeature[A: RType]: Feature[A, Coll[Byte]] = { + val tA = RType[A] + val tpe = Evaluation.rtypeToSType(tA) + newFeature( + (x: A) => SigmaDsl.serialize(x), + s"{ (x: ${tA.name}) => serialize(x) }", + expectedExpr = FuncValue( + Array((1, tpe)), + MethodCall( + Global, + SGlobalMethods.serializeMethod.withConcreteTypes(Map(STypeVar("T") -> tpe)), + Array(ValUse(1, tpe)), + Map() + ) + ), + sinceVersion = VersionContext.V6SoftForkVersion) + } + + property("Global.serialize[Byte]") { + lazy val serializeByte = mkSerializeFeature[Byte] + val cases = Seq( + (-128.toByte, Success(Coll(-128.toByte))), + (-1.toByte, Success(Coll(-1.toByte))), + (0.toByte, Success(Coll(0.toByte))), + (1.toByte, Success(Coll(1.toByte))), + (127.toByte, Success(Coll(127.toByte))) + ) + testCases(cases, serializeByte) + } + + property("Global.serialize[Short]") { + lazy val serializeShort = mkSerializeFeature[Short] + val cases = Seq( + (Short.MinValue, Success(Coll[Byte](0xFF.toByte, 0xFF.toByte, 0x03.toByte))), + (-1.toShort, Success(Coll(1.toByte))), + (0.toShort, Success(Coll(0.toByte))), + (1.toShort, Success(Coll(2.toByte))), + (Short.MaxValue, Success(Coll(-2.toByte, -1.toByte, 3.toByte))) + ) + testCases(cases, serializeShort) + } } diff --git a/sc/shared/src/test/scala/sigma/SigmaDslTesting.scala b/sc/shared/src/test/scala/sigma/SigmaDslTesting.scala index 31e873699b..d776238011 100644 --- a/sc/shared/src/test/scala/sigma/SigmaDslTesting.scala +++ b/sc/shared/src/test/scala/sigma/SigmaDslTesting.scala @@ -177,13 +177,13 @@ class SigmaDslTesting extends AnyPropSpec } /** v3 and v4 implementation*/ - private var _oldF: CompiledFunc[A, B] = _ + private var _oldF: Try[CompiledFunc[A, B]] = _ def oldF: CompiledFunc[A, B] = { if (_oldF == null) { - _oldF = oldImpl() - checkExpectedExprIn(_oldF) + _oldF = Try(oldImpl()) + _oldF.foreach(cf => checkExpectedExprIn(cf)) } - _oldF + _oldF.getOrThrow } /** v5 implementation*/ @@ -833,8 +833,17 @@ class SigmaDslTesting extends AnyPropSpec * This in not yet implemented and will be finished in v6.0. * In v5.0 is only checks that some features are NOT implemented, i.e. work for * negative tests. + * + * @param sinceVersion language version (protocol) when the feature is introduced, see + * [[VersionContext]] + * @param script the script to be tested against semantic function + * @param scalaFuncNew semantic function which defines expected behavior of the given script + * @param expectedExpr expected ErgoTree expression which corresponds to the given script + * @param printExpectedExpr if true, print the test vector for expectedExpr when it is None + * @param logScript if true, log scripts to console */ case class NewFeature[A, B]( + sinceVersion: Byte, script: String, override val scalaFuncNew: A => B, expectedExpr: Option[SValue], @@ -842,25 +851,30 @@ class SigmaDslTesting extends AnyPropSpec logScript: Boolean = LogScriptDefault )(implicit IR: IRContext, override val evalSettings: EvalSettings, val tA: RType[A], val tB: RType[B]) extends Feature[A, B] { + + def isFeatureShouldWork: Boolean = + activatedVersionInTests >= sinceVersion && ergoTreeVersionInTests >= sinceVersion + override def scalaFunc: A => B = { x => sys.error(s"Semantic Scala function is not defined for old implementation: $this") } implicit val cs = compilerSettingsInTests - /** in v5.x the old and the new interpreters are the same */ + /** Starting from v5.x the old and the new interpreters are the same */ val oldImpl = () => funcJit[A, B](script) - val newImpl = oldImpl // funcJit[A, B](script) // TODO v6.0: use actual new implementation here (https://github.com/ScorexFoundation/sigmastate-interpreter/issues/910) + val newImpl = oldImpl - /** In v5.x this method just checks the old implementations fails on the new feature. */ + /** Check the new implementation works equal to the semantic function. + * This method also checks the old implementations fails on the new feature. + */ override def checkEquality(input: A, logInputOutput: Boolean = false): Try[(B, CostDetails)] = { - val oldRes = Try(oldF(input)) - oldRes.isFailure shouldBe true - if (!(newImpl eq oldImpl)) { - val newRes = VersionContext.withVersions(activatedVersionInTests, ergoTreeVersionInTests) { - checkEq(scalaFuncNew)(newF)(input) - } + if (this.isFeatureShouldWork) { + checkEq(scalaFuncNew)(newF)(input) + } else { + val oldRes = Try(oldF(input)) + oldRes.isFailure shouldBe true + oldRes } - oldRes } override def checkExpected(input: A, expected: Expected[B]): Unit = { @@ -880,7 +894,10 @@ class SigmaDslTesting extends AnyPropSpec printTestCases: Boolean, failOnTestVectors: Boolean): Unit = { val res = checkEquality(input, printTestCases).map(_._1) - res.isFailure shouldBe true + if (this.isFeatureShouldWork) { + res shouldBe expectedResult + } else + res.isFailure shouldBe true Try(scalaFuncNew(input)) shouldBe expectedResult } @@ -1045,6 +1062,7 @@ class SigmaDslTesting extends AnyPropSpec /** Describes a NEW language feature which must NOT be supported in v4 and * must BE supported in v5 of the language. * + * @param sinceVersion language version (protocol) when the feature is introduced, see [[VersionContext]] * @param scalaFunc semantic function which defines expected behavior of the given script * @param script the script to be tested against semantic function * @param expectedExpr expected ErgoTree expression which corresponds to the given script @@ -1052,9 +1070,9 @@ class SigmaDslTesting extends AnyPropSpec * various ways */ def newFeature[A: RType, B: RType] - (scalaFunc: A => B, script: String, expectedExpr: SValue = null) + (scalaFunc: A => B, script: String, expectedExpr: SValue = null, sinceVersion: Byte = VersionContext.JitActivationVersion) (implicit IR: IRContext, es: EvalSettings): Feature[A, B] = { - NewFeature(script, scalaFunc, Option(expectedExpr)) + NewFeature(sinceVersion, script, scalaFunc, Option(expectedExpr)) } val contextGen: Gen[Context] = ergoLikeContextGen.map(c => c.toSigmaContext()) From 4fb3daa5e5ad4f83e5f143c85499780f9b83e169 Mon Sep 17 00:00:00 2001 From: Alexander Slesarenko Date: Sun, 19 May 2024 16:21:50 +0100 Subject: [PATCH 08/19] v6.0-serialize: all new features move to LanguageSpecificationV6 --- .../scala/sigmastate/CrossVersionProps.scala | 2 - .../scala/sigma/LanguageSpecificationV5.scala | 225 ------------ .../scala/sigma/LanguageSpecificationV6.scala | 330 +++++++++++++++++- .../test/scala/sigma/SigmaDslTesting.scala | 17 +- .../CompilerCrossVersionProps.scala | 11 +- 5 files changed, 343 insertions(+), 242 deletions(-) diff --git a/interpreter/shared/src/test/scala/sigmastate/CrossVersionProps.scala b/interpreter/shared/src/test/scala/sigmastate/CrossVersionProps.scala index 87101a1f71..e55b874dc3 100644 --- a/interpreter/shared/src/test/scala/sigmastate/CrossVersionProps.scala +++ b/interpreter/shared/src/test/scala/sigmastate/CrossVersionProps.scala @@ -31,9 +31,7 @@ trait CrossVersionProps extends AnyPropSpecLike with TestsBase { System.gc() } forEachScriptAndErgoTreeVersion(activatedVersions, ergoTreeVersions) { - VersionContext.withVersions(activatedVersionInTests, ergoTreeVersionInTests) { testFun_Run(testName, testFun) - } } } } diff --git a/sc/shared/src/test/scala/sigma/LanguageSpecificationV5.scala b/sc/shared/src/test/scala/sigma/LanguageSpecificationV5.scala index eabbf776aa..700b48fd13 100644 --- a/sc/shared/src/test/scala/sigma/LanguageSpecificationV5.scala +++ b/sc/shared/src/test/scala/sigma/LanguageSpecificationV5.scala @@ -125,17 +125,6 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => /// Boolean type operations ///----------------------------------------------------- - property("Boolean methods equivalence") { - val toByte = newFeature((x: Boolean) => x.toByte, "{ (x: Boolean) => x.toByte }") - - val cases = Seq( - (true, Success(1.toByte)), - (false, Success(0.toByte)) - ) - - testCases(cases, toByte) - } - property("BinXor(logical XOR) equivalence") { val binXor = existingFeature((x: (Boolean, Boolean)) => x._1 ^ x._2, "{ (x: (Boolean, Boolean)) => x._1 ^ x._2 }", @@ -950,31 +939,6 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => swapArgs(LE_cases, cost = 1768, newCostDetails = binaryRelationCostDetails(GE, SByte)), ">=", GE.apply)(_ >= _) } - - property("Byte methods equivalence (new features)") { - lazy val toBytes = newFeature((x: Byte) => x.toBytes, "{ (x: Byte) => x.toBytes }") - lazy val toAbs = newFeature((x: Byte) => x.toAbs, "{ (x: Byte) => x.toAbs }") - lazy val compareTo = newFeature( - (x: (Byte, Byte)) => x._1.compareTo(x._2), - "{ (x: (Byte, Byte)) => x._1.compareTo(x._2) }") - - lazy val bitOr = newFeature( - { (x: (Byte, Byte)) => (x._1 | x._2).toByteExact }, - "{ (x: (Byte, Byte)) => (x._1 | x._2).toByteExact }") - - lazy val bitAnd = newFeature( - { (x: (Byte, Byte)) => (x._1 & x._2).toByteExact }, - "{ (x: (Byte, Byte)) => (x._1 & x._2).toByteExact }") - - forAll { x: Byte => - Seq(toBytes, toAbs).foreach(f => f.checkEquality(x)) - } - - forAll { x: (Byte, Byte) => - Seq(compareTo, bitOr, bitAnd).foreach(_.checkEquality(x)) - } - } - property("Short methods equivalence") { SShort.upcast(0.toShort) shouldBe 0.toShort // boundary test case SShort.downcast(0.toShort) shouldBe 0.toShort // boundary test case @@ -1255,29 +1219,6 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => ">=", GE.apply)(_ >= _) } - property("Short methods equivalence (new features)") { - lazy val toBytes = newFeature((x: Short) => x.toBytes, "{ (x: Short) => x.toBytes }") - lazy val toAbs = newFeature((x: Short) => x.toAbs, "{ (x: Short) => x.toAbs }") - - lazy val compareTo = newFeature((x: (Short, Short)) => x._1.compareTo(x._2), - "{ (x: (Short, Short)) => x._1.compareTo(x._2) }") - - lazy val bitOr = newFeature( - { (x: (Short, Short)) => (x._1 | x._2).toShortExact }, - "{ (x: (Short, Short)) => x._1 | x._2 }") - - lazy val bitAnd = newFeature( - { (x: (Short, Short)) => (x._1 & x._2).toShortExact }, - "{ (x: (Short, Short)) => x._1 & x._2 }") - - forAll { x: Short => - Seq(toBytes, toAbs).foreach(_.checkEquality(x)) - } - forAll { x: (Short, Short) => - Seq(compareTo, bitOr, bitAnd).foreach(_.checkEquality(x)) - } - } - property("Int methods equivalence") { SInt.upcast(0) shouldBe 0 // boundary test case SInt.downcast(0) shouldBe 0 // boundary test case @@ -1558,28 +1499,6 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => ">=", GE.apply)(_ >= _) } - property("Int methods equivalence (new features)") { - lazy val toBytes = newFeature((x: Int) => x.toBytes, "{ (x: Int) => x.toBytes }") - lazy val toAbs = newFeature((x: Int) => x.toAbs, "{ (x: Int) => x.toAbs }") - lazy val compareTo = newFeature((x: (Int, Int)) => x._1.compareTo(x._2), - "{ (x: (Int, Int)) => x._1.compareTo(x._2) }") - - lazy val bitOr = newFeature( - { (x: (Int, Int)) => x._1 | x._2 }, - "{ (x: (Int, Int)) => x._1 | x._2 }") - - lazy val bitAnd = newFeature( - { (x: (Int, Int)) => x._1 & x._2 }, - "{ (x: (Int, Int)) => x._1 & x._2 }") - - forAll { x: Int => - Seq(toBytes, toAbs).foreach(_.checkEquality(x)) - } - forAll { x: (Int, Int) => - Seq(compareTo, bitOr, bitAnd).foreach(_.checkEquality(x)) - } - } - property("Long downcast and upcast identity") { forAll { x: Long => SLong.upcast(x) shouldBe x // boundary test case @@ -1877,28 +1796,6 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => ">=", GE.apply)(_ >= _) } - property("Long methods equivalence (new features)") { - lazy val toBytes = newFeature((x: Long) => x.toBytes, "{ (x: Long) => x.toBytes }") - lazy val toAbs = newFeature((x: Long) => x.toAbs, "{ (x: Long) => x.toAbs }") - lazy val compareTo = newFeature((x: (Long, Long)) => x._1.compareTo(x._2), - "{ (x: (Long, Long)) => x._1.compareTo(x._2) }") - - lazy val bitOr = newFeature( - { (x: (Long, Long)) => x._1 | x._2 }, - "{ (x: (Long, Long)) => x._1 | x._2 }") - - lazy val bitAnd = newFeature( - { (x: (Long, Long)) => x._1 & x._2 }, - "{ (x: (Long, Long)) => x._1 & x._2 }") - - forAll { x: Long => - Seq(toBytes, toAbs).foreach(_.checkEquality(x)) - } - forAll { x: (Long, Long) => - Seq(compareTo, bitOr, bitAnd).foreach(_.checkEquality(x)) - } - } - property("BigInt methods equivalence") { verifyCases( { @@ -2157,59 +2054,6 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => ">=", GE.apply)(o.gteq(_, _)) } - property("BigInt methods equivalence (new features)") { - // TODO v6.0: the behavior of `upcast` for BigInt is different from all other Numeric types (see https://github.com/ScorexFoundation/sigmastate-interpreter/issues/877) - // The `Upcast(bigInt, SBigInt)` node is never produced by ErgoScript compiler, but is still valid ErgoTree. - // It makes sense to fix this inconsistency as part of upcoming forks - assertExceptionThrown( - SBigInt.upcast(CBigInt(new BigInteger("0", 16)).asInstanceOf[AnyVal]), - _.getMessage.contains("Cannot upcast value") - ) - - // TODO v6.0: the behavior of `downcast` for BigInt is different from all other Numeric types (see https://github.com/ScorexFoundation/sigmastate-interpreter/issues/877) - // The `Downcast(bigInt, SBigInt)` node is never produced by ErgoScript compiler, but is still valid ErgoTree. - // It makes sense to fix this inconsistency as part of HF - assertExceptionThrown( - SBigInt.downcast(CBigInt(new BigInteger("0", 16)).asInstanceOf[AnyVal]), - _.getMessage.contains("Cannot downcast value") - ) - - val toByte = newFeature((x: BigInt) => x.toByte, - "{ (x: BigInt) => x.toByte }", - FuncValue(Vector((1, SBigInt)), Downcast(ValUse(1, SBigInt), SByte))) - - val toShort = newFeature((x: BigInt) => x.toShort, - "{ (x: BigInt) => x.toShort }", - FuncValue(Vector((1, SBigInt)), Downcast(ValUse(1, SBigInt), SShort))) - - val toInt = newFeature((x: BigInt) => x.toInt, - "{ (x: BigInt) => x.toInt }", - FuncValue(Vector((1, SBigInt)), Downcast(ValUse(1, SBigInt), SInt))) - - val toLong = newFeature((x: BigInt) => x.toLong, - "{ (x: BigInt) => x.toLong }", - FuncValue(Vector((1, SBigInt)), Downcast(ValUse(1, SBigInt), SLong))) - - lazy val toBytes = newFeature((x: BigInt) => x.toBytes, "{ (x: BigInt) => x.toBytes }") - lazy val toAbs = newFeature((x: BigInt) => x.toAbs, "{ (x: BigInt) => x.toAbs }") - - lazy val compareTo = newFeature((x: (BigInt, BigInt)) => x._1.compareTo(x._2), - "{ (x: (BigInt, BigInt)) => x._1.compareTo(x._2) }") - - lazy val bitOr = newFeature({ (x: (BigInt, BigInt)) => x._1 | x._2 }, - "{ (x: (BigInt, BigInt)) => x._1 | x._2 }") - - lazy val bitAnd = newFeature({ (x: (BigInt, BigInt)) => x._1 & x._2 }, - "{ (x: (BigInt, BigInt)) => x._1 & x._2 }") - - forAll { x: BigInt => - Seq(toByte, toShort, toInt, toLong, toBytes, toAbs).foreach(_.checkEquality(x)) - } - forAll { x: (BigInt, BigInt) => - Seq(compareTo, bitOr, bitAnd).foreach(_.checkEquality(x)) - } - } - /** Executed a series of test cases of NEQ operation verify using two _different_ * data instances `x` and `y`. * @param cost the expected cost of `verify` (the same for all cases) @@ -3944,16 +3788,6 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => ))) } - property("Box properties equivalence (new features)") { - // TODO v6.0: related to https://github.com/ScorexFoundation/sigmastate-interpreter/issues/416 - val getReg = newFeature((x: Box) => x.getReg[Int](1).get, - "{ (x: Box) => x.getReg[Int](1).get }") - - forAll { box: Box => - Seq(getReg).foreach(_.checkEquality(box)) - } - } - property("Conditional access to registers") { def boxWithRegisters(regs: AdditionalRegisters): Box = { SigmaDsl.Box(testBox(20, TrueTree, 0, Seq(), regs)) @@ -7531,36 +7365,6 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => preGeneratedSamples = Some(samples)) } - // TODO v6.0 (3h): https://github.com/ScorexFoundation/sigmastate-interpreter/issues/479 - property("Coll find method equivalence") { - val find = newFeature((x: Coll[Int]) => x.find({ (v: Int) => v > 0 }), - "{ (x: Coll[Int]) => x.find({ (v: Int) => v > 0} ) }") - forAll { x: Coll[Int] => - find.checkEquality(x) - } - } - - // TODO v6.0 (3h): https://github.com/ScorexFoundation/sigmastate-interpreter/issues/418 - property("Coll bitwise methods equivalence") { - val shiftRight = newFeature( - { (x: Coll[Boolean]) => - if (x.size > 2) x.slice(0, x.size - 2) else Colls.emptyColl[Boolean] - }, - "{ (x: Coll[Boolean]) => x >> 2 }") - forAll { x: Array[Boolean] => - shiftRight.checkEquality(Colls.fromArray(x)) - } - } - - // TODO v6.0 (3h): https://github.com/ScorexFoundation/sigmastate-interpreter/issues/479 - property("Coll diff methods equivalence") { - val diff = newFeature((x: (Coll[Int], Coll[Int])) => x._1.diff(x._2), - "{ (x: (Coll[Int], Coll[Int])) => x._1.diff(x._2) }") - forAll { (x: Coll[Int], y: Coll[Int]) => - diff.checkEquality((x, y)) - } - } - property("Coll fold method equivalence") { val n = ExactNumeric.IntIsExactNumeric val costDetails1 = TracedCost( @@ -8972,17 +8776,6 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => ) )) } - // TODO v6.0: implement Option.fold (see https://github.com/ScorexFoundation/sigmastate-interpreter/issues/479) - property("Option new methods") { - val n = ExactNumeric.LongIsExactNumeric - val fold = newFeature({ (x: Option[Long]) => x.fold(5.toLong)( (v: Long) => n.plus(v, 1) ) }, - "{ (x: Option[Long]) => x.fold(5, { (v: Long) => v + 1 }) }") - - forAll { x: Option[Long] => - Seq(fold).map(_.checkEquality(x)) - } - } - property("Option fold workaround method") { val costDetails1 = TracedCost( traceBase ++ Array( @@ -9418,24 +9211,6 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => preGeneratedSamples = Some(Seq())) } - // TODO v6.0 (3h): implement allZK func https://github.com/ScorexFoundation/sigmastate-interpreter/issues/543 - property("allZK equivalence") { - lazy val allZK = newFeature((x: Coll[SigmaProp]) => SigmaDsl.allZK(x), - "{ (x: Coll[SigmaProp]) => allZK(x) }") - forAll { x: Coll[SigmaProp] => - allZK.checkEquality(x) - } - } - - // TODO v6.0 (3h): implement anyZK func https://github.com/ScorexFoundation/sigmastate-interpreter/issues/543 - property("anyZK equivalence") { - lazy val anyZK = newFeature((x: Coll[SigmaProp]) => SigmaDsl.anyZK(x), - "{ (x: Coll[SigmaProp]) => anyZK(x) }") - forAll { x: Coll[SigmaProp] => - anyZK.checkEquality(x) - } - } - property("allOf equivalence") { def costDetails(i: Int) = TracedCost(traceBase :+ ast.SeqCostItem(CompanionDesc(AND), PerItemCost(JitCost(10), JitCost(5), 32), i)) verifyCases( diff --git a/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala b/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala index 16b8fffbf1..20faabe128 100644 --- a/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala +++ b/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala @@ -1,9 +1,12 @@ package sigma -import sigma.ast.{FuncValue, Global, MethodCall, SByte, SCollection, SGlobalMethods, STypeVar, ValUse, Value} -import sigma.data.RType +import sigma.ast.{Downcast, FuncValue, Global, MethodCall, SBigInt, SByte, SGlobalMethods, SInt, SLong, SShort, STypeVar, ValUse} +import sigma.data.{CBigInt, ExactNumeric, RType} import sigma.eval.SigmaDsl +import sigma.util.Extensions.{BooleanOps, ByteOps, IntOps, LongOps} +import sigmastate.exceptions.MethodNotFound +import java.math.BigInteger import scala.util.Success /** This suite tests all operations for v6.0 version of the language. @@ -14,8 +17,6 @@ import scala.util.Success class LanguageSpecificationV6 extends LanguageSpecificationBase { suite => override def languageVersion: Byte = VersionContext.V6SoftForkVersion - import TestData._ - def mkSerializeFeature[A: RType]: Feature[A, Coll[Byte]] = { val tA = RType[A] val tpe = Evaluation.rtypeToSType(tA) @@ -57,4 +58,325 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite => ) testCases(cases, serializeShort) } + + // TODO v6.0: implement serialization roundtrip tests after merge with deserializeTo + + + property("Boolean.toByte") { + val toByte = newFeature((x: Boolean) => x.toByte, "{ (x: Boolean) => x.toByte }", + sinceVersion = VersionContext.V6SoftForkVersion + ) + + val cases = Seq( + (true, Success(1.toByte)), + (false, Success(0.toByte)) + ) + + if (toByte.isSupportedIn(VersionContext.current)) { + // TODO v6.0: implement as part of https://github.com/ScorexFoundation/sigmastate-interpreter/pull/932 + assertExceptionThrown( + testCases(cases, toByte), + rootCauseLike[MethodNotFound]("Cannot find method") + ) + } + else + testCases(cases, toByte) + } + + property("Byte methods equivalence (new features)") { + // TODO v6.0: implement as part of https://github.com/ScorexFoundation/sigmastate-interpreter/issues/474 + if (activatedVersionInTests < VersionContext.V6SoftForkVersion) { + // NOTE, for such versions the new features are not supported + // which is checked below + + lazy val toAbs = newFeature((x: Byte) => x.toAbs, "{ (x: Byte) => x.toAbs }", + sinceVersion = VersionContext.V6SoftForkVersion) + + lazy val compareTo = newFeature( + (x: (Byte, Byte)) => x._1.compareTo(x._2), + "{ (x: (Byte, Byte)) => x._1.compareTo(x._2) }", + sinceVersion = VersionContext.V6SoftForkVersion) + + lazy val bitOr = newFeature( + { (x: (Byte, Byte)) => (x._1 | x._2).toByteExact }, + "{ (x: (Byte, Byte)) => (x._1 | x._2) }", + sinceVersion = VersionContext.V6SoftForkVersion) + + lazy val bitAnd = newFeature( + { (x: (Byte, Byte)) => (x._1 & x._2).toByteExact }, + "{ (x: (Byte, Byte)) => (x._1 & x._2) }", + sinceVersion = VersionContext.V6SoftForkVersion) + + forAll { x: Byte => + Seq(toAbs).foreach(f => f.checkEquality(x)) + } + + forAll { x: (Byte, Byte) => + Seq(compareTo, bitOr, bitAnd).foreach(_.checkEquality(x)) + } + } + } + + // TODO v6.0: enable as part of https://github.com/ScorexFoundation/sigmastate-interpreter/issues/474 + property("Short methods equivalence (new features)") { + if (activatedVersionInTests < VersionContext.V6SoftForkVersion) { + // NOTE, for such versions the new features are not supported + // which is checked below + + lazy val toAbs = newFeature((x: Short) => x.toAbs, "{ (x: Short) => x.toAbs }", + sinceVersion = VersionContext.V6SoftForkVersion) + + lazy val compareTo = newFeature((x: (Short, Short)) => x._1.compareTo(x._2), + "{ (x: (Short, Short)) => x._1.compareTo(x._2) }", + sinceVersion = VersionContext.V6SoftForkVersion) + + lazy val bitOr = newFeature( + { (x: (Short, Short)) => (x._1 | x._2).toShortExact }, + "{ (x: (Short, Short)) => x._1 | x._2 }", + sinceVersion = VersionContext.V6SoftForkVersion) + + lazy val bitAnd = newFeature( + { (x: (Short, Short)) => (x._1 & x._2).toShortExact }, + "{ (x: (Short, Short)) => x._1 & x._2 }", + sinceVersion = VersionContext.V6SoftForkVersion) + + forAll { x: Short => + Seq(toAbs).foreach(_.checkEquality(x)) + } + forAll { x: (Short, Short) => + Seq(compareTo, bitOr, bitAnd).foreach(_.checkEquality(x)) + } + } + } + + property("Int methods equivalence (new features)") { + if (activatedVersionInTests < VersionContext.V6SoftForkVersion) { + // NOTE, for such versions the new features are not supported + // which is checked below + lazy val toAbs = newFeature((x: Int) => x.toAbs, "{ (x: Int) => x.toAbs }", + sinceVersion = VersionContext.V6SoftForkVersion) + lazy val compareTo = newFeature((x: (Int, Int)) => x._1.compareTo(x._2), + "{ (x: (Int, Int)) => x._1.compareTo(x._2) }", + sinceVersion = VersionContext.V6SoftForkVersion) + lazy val bitOr = newFeature( + { (x: (Int, Int)) => x._1 | x._2 }, + "{ (x: (Int, Int)) => x._1 | x._2 }", + sinceVersion = VersionContext.V6SoftForkVersion) + lazy val bitAnd = newFeature( + { (x: (Int, Int)) => x._1 & x._2 }, + "{ (x: (Int, Int)) => x._1 & x._2 }", + sinceVersion = VersionContext.V6SoftForkVersion) + forAll { x: Int => + Seq(toAbs).foreach(_.checkEquality(x)) + } + forAll { x: (Int, Int) => + Seq(compareTo, bitOr, bitAnd).foreach(_.checkEquality(x)) + } + } + } + + property("Long methods equivalence (new features)") { + if (activatedVersionInTests < VersionContext.V6SoftForkVersion) { + // NOTE, for such versions the new features are not supported + // which is checked below + lazy val toAbs = newFeature((x: Long) => x.toAbs, "{ (x: Long) => x.toAbs }", + sinceVersion = VersionContext.V6SoftForkVersion) + lazy val compareTo = newFeature((x: (Long, Long)) => x._1.compareTo(x._2), + "{ (x: (Long, Long)) => x._1.compareTo(x._2) }", + sinceVersion = VersionContext.V6SoftForkVersion) + + lazy val bitOr = newFeature( + { (x: (Long, Long)) => x._1 | x._2 }, + "{ (x: (Long, Long)) => x._1 | x._2 }", + sinceVersion = VersionContext.V6SoftForkVersion) + + lazy val bitAnd = newFeature( + { (x: (Long, Long)) => x._1 & x._2 }, + "{ (x: (Long, Long)) => x._1 & x._2 }", + sinceVersion = VersionContext.V6SoftForkVersion) + + forAll { x: Long => + Seq(toAbs).foreach(_.checkEquality(x)) + } + forAll { x: (Long, Long) => + Seq(compareTo, bitOr, bitAnd).foreach(_.checkEquality(x)) + } + } + + } + + property("BigInt methods equivalence (new features)") { + // TODO v6.0: the behavior of `upcast` for BigInt is different from all other Numeric types (see https://github.com/ScorexFoundation/sigmastate-interpreter/issues/877) + // The `Upcast(bigInt, SBigInt)` node is never produced by ErgoScript compiler, but is still valid ErgoTree. + // It makes sense to fix this inconsistency as part of upcoming forks + assertExceptionThrown( + SBigInt.upcast(CBigInt(new BigInteger("0", 16)).asInstanceOf[AnyVal]), + _.getMessage.contains("Cannot upcast value") + ) + + // TODO v6.0: the behavior of `downcast` for BigInt is different from all other Numeric types (see https://github.com/ScorexFoundation/sigmastate-interpreter/issues/877) + // The `Downcast(bigInt, SBigInt)` node is never produced by ErgoScript compiler, but is still valid ErgoTree. + // It makes sense to fix this inconsistency as part of HF + assertExceptionThrown( + SBigInt.downcast(CBigInt(new BigInteger("0", 16)).asInstanceOf[AnyVal]), + _.getMessage.contains("Cannot downcast value") + ) + + if (activatedVersionInTests < VersionContext.V6SoftForkVersion) { + // NOTE, for such versions the new features are not supported + // which is checked below + val toByte = newFeature((x: BigInt) => x.toByte, + "{ (x: BigInt) => x.toByte }", + FuncValue(Vector((1, SBigInt)), Downcast(ValUse(1, SBigInt), SByte)), + sinceVersion = VersionContext.V6SoftForkVersion) + val toShort = newFeature((x: BigInt) => x.toShort, + "{ (x: BigInt) => x.toShort }", + FuncValue(Vector((1, SBigInt)), Downcast(ValUse(1, SBigInt), SShort)), + sinceVersion = VersionContext.V6SoftForkVersion) + val toInt = newFeature((x: BigInt) => x.toInt, + "{ (x: BigInt) => x.toInt }", + FuncValue(Vector((1, SBigInt)), Downcast(ValUse(1, SBigInt), SInt)), + sinceVersion = VersionContext.V6SoftForkVersion) + val toLong = newFeature((x: BigInt) => x.toLong, + "{ (x: BigInt) => x.toLong }", + FuncValue(Vector((1, SBigInt)), Downcast(ValUse(1, SBigInt), SLong)), + sinceVersion = VersionContext.V6SoftForkVersion) + lazy val toAbs = newFeature((x: BigInt) => x.toAbs, "{ (x: BigInt) => x.toAbs }", + sinceVersion = VersionContext.V6SoftForkVersion) + lazy val compareTo = newFeature((x: (BigInt, BigInt)) => x._1.compareTo(x._2), + "{ (x: (BigInt, BigInt)) => x._1.compareTo(x._2) }", + sinceVersion = VersionContext.V6SoftForkVersion) + lazy val bitOr = newFeature({ (x: (BigInt, BigInt)) => x._1 | x._2 }, + "{ (x: (BigInt, BigInt)) => x._1 | x._2 }", + sinceVersion = VersionContext.V6SoftForkVersion) + lazy val bitAnd = newFeature({ (x: (BigInt, BigInt)) => x._1 & x._2 }, + "{ (x: (BigInt, BigInt)) => x._1 & x._2 }", + sinceVersion = VersionContext.V6SoftForkVersion) + + forAll { x: BigInt => + Seq(toByte, toShort, toInt, toLong, toAbs).foreach(_.checkEquality(x)) + } + forAll { x: (BigInt, BigInt) => + Seq(compareTo, bitOr, bitAnd).foreach(_.checkEquality(x)) + } + } + } + + property("Box properties equivalence (new features)") { + // TODO v6.0: related to https://github.com/ScorexFoundation/sigmastate-interpreter/issues/416 + val getReg = newFeature((x: Box) => x.getReg[Int](1).get, + "{ (x: Box) => x.getReg[Int](1).get }", + sinceVersion = VersionContext.V6SoftForkVersion) + + if (activatedVersionInTests < VersionContext.V6SoftForkVersion) { + // NOTE, for such versions getReg is not supported + // which is checked below + + forAll { box: Box => + Seq(getReg).foreach(_.checkEquality(box)) + } + } + } + + // TODO v6.0 (3h): https://github.com/ScorexFoundation/sigmastate-interpreter/issues/479 + property("Coll find method equivalence") { + val find = newFeature((x: Coll[Int]) => x.find({ (v: Int) => v > 0 }), + "{ (x: Coll[Int]) => x.find({ (v: Int) => v > 0} ) }", + sinceVersion = VersionContext.V6SoftForkVersion) + + if (activatedVersionInTests < VersionContext.V6SoftForkVersion) { + // NOTE, for such versions getReg is not supported + // which is checked below + + forAll { x: Coll[Int] => + find.checkEquality(x) + } + } + } + + // TODO v6.0 (3h): https://github.com/ScorexFoundation/sigmastate-interpreter/issues/418 + property("Coll bitwise methods equivalence") { + val shiftRight = newFeature( + { (x: Coll[Boolean]) => + if (x.size > 2) x.slice(0, x.size - 2) else Colls.emptyColl[Boolean] + }, + "{ (x: Coll[Boolean]) => x >> 2 }", + sinceVersion = VersionContext.V6SoftForkVersion) + + if (activatedVersionInTests < VersionContext.V6SoftForkVersion) { + // NOTE, for such versions getReg is not supported + // which is checked below + + forAll { x: Array[Boolean] => + shiftRight.checkEquality(Colls.fromArray(x)) + } + } + } + + // TODO v6.0 (3h): https://github.com/ScorexFoundation/sigmastate-interpreter/issues/479 + property("Coll diff methods equivalence") { + val diff = newFeature((x: (Coll[Int], Coll[Int])) => x._1.diff(x._2), + "{ (x: (Coll[Int], Coll[Int])) => x._1.diff(x._2) }", + sinceVersion = VersionContext.V6SoftForkVersion) + + if (activatedVersionInTests < VersionContext.V6SoftForkVersion) { + // NOTE, for such versions getReg is not supported + // which is checked below + + forAll { (x: Coll[Int], y: Coll[Int]) => + diff.checkEquality((x, y)) + } + } + } + + // TODO v6.0: implement Option.fold (see https://github.com/ScorexFoundation/sigmastate-interpreter/issues/479) + property("Option new methods") { + val n = ExactNumeric.LongIsExactNumeric + val fold = newFeature({ (x: Option[Long]) => x.fold(5.toLong)( (v: Long) => n.plus(v, 1) ) }, + "{ (x: Option[Long]) => x.fold(5, { (v: Long) => v + 1 }) }", + sinceVersion = VersionContext.V6SoftForkVersion) + + if (activatedVersionInTests < VersionContext.V6SoftForkVersion) { + // NOTE, for such versions getReg is not supported + // which is checked below + + forAll { x: Option[Long] => + Seq(fold).map(_.checkEquality(x)) + } + } + } + + // TODO v6.0 (3h): implement allZK func https://github.com/ScorexFoundation/sigmastate-interpreter/issues/543 + property("allZK equivalence") { + lazy val allZK = newFeature((x: Coll[SigmaProp]) => SigmaDsl.allZK(x), + "{ (x: Coll[SigmaProp]) => allZK(x) }", + sinceVersion = VersionContext.V6SoftForkVersion) + + if (activatedVersionInTests < VersionContext.V6SoftForkVersion) { + // NOTE, for such versions getReg is not supported + // which is checked below + + forAll { x: Coll[SigmaProp] => + allZK.checkEquality(x) + } + } + } + + // TODO v6.0 (3h): implement anyZK func https://github.com/ScorexFoundation/sigmastate-interpreter/issues/543 + property("anyZK equivalence") { + lazy val anyZK = newFeature((x: Coll[SigmaProp]) => SigmaDsl.anyZK(x), + "{ (x: Coll[SigmaProp]) => anyZK(x) }", + sinceVersion = VersionContext.V6SoftForkVersion) + + if (activatedVersionInTests < VersionContext.V6SoftForkVersion) { + // NOTE, for such versions getReg is not supported + // which is checked below + + forAll { x: Coll[SigmaProp] => + anyZK.checkEquality(x) + } + } + } + + } diff --git a/sc/shared/src/test/scala/sigma/SigmaDslTesting.scala b/sc/shared/src/test/scala/sigma/SigmaDslTesting.scala index d776238011..28c9c05fec 100644 --- a/sc/shared/src/test/scala/sigma/SigmaDslTesting.scala +++ b/sc/shared/src/test/scala/sigma/SigmaDslTesting.scala @@ -123,6 +123,9 @@ class SigmaDslTesting extends AnyPropSpec /** Type descriptor for type B. */ def tB: RType[B] + /** Checks if this feature is supported in the given version context. */ + def isSupportedIn(vc: VersionContext): Boolean + /** Script containing this feature. */ def script: String @@ -501,6 +504,8 @@ class SigmaDslTesting extends AnyPropSpec implicit val cs = compilerSettingsInTests + override def isSupportedIn(vc: VersionContext): Boolean = true + /** in v5.x the old and the new interpreters are the same */ override val oldImpl = () => funcJit[A, B](script) override val newImpl = () => funcJit[A, B](script) @@ -671,6 +676,8 @@ class SigmaDslTesting extends AnyPropSpec implicit val cs = compilerSettingsInTests + override def isSupportedIn(vc: VersionContext): Boolean = true + /** Apply given function to the context variable 1 */ private def getApplyExpr(funcValue: SValue) = { val sType = Evaluation.rtypeToSType(RType[A]) @@ -852,8 +859,8 @@ class SigmaDslTesting extends AnyPropSpec )(implicit IR: IRContext, override val evalSettings: EvalSettings, val tA: RType[A], val tB: RType[B]) extends Feature[A, B] { - def isFeatureShouldWork: Boolean = - activatedVersionInTests >= sinceVersion && ergoTreeVersionInTests >= sinceVersion + override def isSupportedIn(vc: VersionContext): Boolean = + vc.activatedVersion >= sinceVersion && vc.ergoTreeVersion >= sinceVersion override def scalaFunc: A => B = { x => sys.error(s"Semantic Scala function is not defined for old implementation: $this") @@ -868,7 +875,7 @@ class SigmaDslTesting extends AnyPropSpec * This method also checks the old implementations fails on the new feature. */ override def checkEquality(input: A, logInputOutput: Boolean = false): Try[(B, CostDetails)] = { - if (this.isFeatureShouldWork) { + if (this.isSupportedIn(VersionContext.current)) { checkEq(scalaFuncNew)(newF)(input) } else { val oldRes = Try(oldF(input)) @@ -894,8 +901,8 @@ class SigmaDslTesting extends AnyPropSpec printTestCases: Boolean, failOnTestVectors: Boolean): Unit = { val res = checkEquality(input, printTestCases).map(_._1) - if (this.isFeatureShouldWork) { - res shouldBe expectedResult + if (this.isSupportedIn(VersionContext.current)) { + res shouldBe expectedResult } else res.isFailure shouldBe true Try(scalaFuncNew(input)) shouldBe expectedResult diff --git a/sc/shared/src/test/scala/sigmastate/CompilerCrossVersionProps.scala b/sc/shared/src/test/scala/sigmastate/CompilerCrossVersionProps.scala index 89d15dd4df..4062f13686 100644 --- a/sc/shared/src/test/scala/sigmastate/CompilerCrossVersionProps.scala +++ b/sc/shared/src/test/scala/sigmastate/CompilerCrossVersionProps.scala @@ -12,12 +12,11 @@ trait CompilerCrossVersionProps extends CrossVersionProps with CompilerTestsBase (implicit pos: Position): Unit = { super.property(testName, testTags:_*)(testFun) - val testName2 = s"${testName}_MCLowering" - super.property2(testName2, testTags:_*) { - if (okRunTestsWithoutMCLowering) { - _lowerMethodCalls.withValue(false) { - testFun_Run(testName2, testFun) - } + if (okRunTestsWithoutMCLowering) { + val testName2 = s"${testName}_MCLowering" + _lowerMethodCalls.withValue(false) { + // run testFun for all versions again, but now with this flag + super.property(testName2, testTags:_*)(testFun) } } } From d09d735b05169e609b8e75c191c493d588373a7c Mon Sep 17 00:00:00 2001 From: Alexander Slesarenko Date: Wed, 22 May 2024 21:50:07 +0200 Subject: [PATCH 09/19] i994-fix-subst-constants: implementation + tests --- .../src/main/scala/sigma/ast/ErgoTree.scala | 5 + .../serialization/ErgoTreeSerializer.scala | 48 ++++- .../sigma/LanguageSpecificationBase.scala | 16 +- .../scala/sigma/LanguageSpecificationV5.scala | 197 +++++++++--------- .../scala/sigma/LanguageSpecificationV6.scala | 88 +++++++- .../test/scala/sigma/SigmaDslTesting.scala | 23 +- 6 files changed, 258 insertions(+), 119 deletions(-) diff --git a/data/shared/src/main/scala/sigma/ast/ErgoTree.scala b/data/shared/src/main/scala/sigma/ast/ErgoTree.scala index 68d69abd91..eae420612e 100644 --- a/data/shared/src/main/scala/sigma/ast/ErgoTree.scala +++ b/data/shared/src/main/scala/sigma/ast/ErgoTree.scala @@ -228,6 +228,11 @@ object ErgoTree { type HeaderType = HeaderType.Type + implicit class HeaderTypeOps(val header: HeaderType) extends AnyVal { + def withVersion(version: Byte): HeaderType = ErgoTree.headerWithVersion(header, version) + def withConstantSegregation: HeaderType = ErgoTree.setConstantSegregation(header) + } + /** Current version of ErgoTree serialization format (aka bite-code language version) */ val VersionFlag: Byte = VersionContext.MaxSupportedScriptVersion diff --git a/data/shared/src/main/scala/sigma/serialization/ErgoTreeSerializer.scala b/data/shared/src/main/scala/sigma/serialization/ErgoTreeSerializer.scala index 43e41f91ff..e7bb46429a 100644 --- a/data/shared/src/main/scala/sigma/serialization/ErgoTreeSerializer.scala +++ b/data/shared/src/main/scala/sigma/serialization/ErgoTreeSerializer.scala @@ -287,6 +287,9 @@ class ErgoTreeSerializer { * allow to use serialized scripts as pre-defined templates. * See [[SubstConstants]] for details. * + * Note, this operation doesn't require (de)serialization of ErgoTree expression, + * thus it is more efficient than serialization roundtrip. + * * @param scriptBytes serialized ErgoTree with ConstantSegregationFlag set to 1. * @param positions zero based indexes in ErgoTree.constants array which * should be replaced with new values @@ -304,21 +307,23 @@ class ErgoTreeSerializer { s"expected positions and newVals to have the same length, got: positions: ${positions.toSeq},\n newVals: ${newVals.toSeq}") val r = SigmaSerializer.startReader(scriptBytes) val (header, _, constants, treeBytes) = deserializeHeaderWithTreeBytes(r) - val w = SigmaSerializer.startWriter() - w.put(header) + val nConstants = constants.length + + val resBytes = if (VersionContext.current.isJitActivated) { + // need to measure the serialized size of the new constants + // by serializing them into a separate writer + val constW = SigmaSerializer.startWriter() - if (VersionContext.current.isJitActivated) { // The following `constants.length` should not be serialized when segregation is off // in the `header`, because in this case there is no `constants` section in the // ErgoTree serialization format. Thus, applying this `substituteConstants` for // non-segregated trees will return non-parsable ErgoTree bytes (when // `constants.length` is put in `w`). if (ErgoTree.isConstantSegregation(header)) { - w.putUInt(constants.length) + constW.putUInt(constants.length) } // The following is optimized O(nConstants + position.length) implementation - val nConstants = constants.length if (nConstants > 0) { val backrefs = getPositionsBackref(positions, nConstants) cfor(0)(_ < nConstants, _ + 1) { i => @@ -326,17 +331,38 @@ class ErgoTreeSerializer { val iPos = backrefs(i) // index to `positions` if (iPos == -1) { // no position => no substitution, serialize original constant - constantSerializer.serialize(c, w) + constantSerializer.serialize(c, constW) } else { - assert(positions(iPos) == i) // INV: backrefs and positions are mutually inverse + require(positions(iPos) == i) // INV: backrefs and positions are mutually inverse val newConst = newVals(iPos) require(c.tpe == newConst.tpe, s"expected new constant to have the same ${c.tpe} tpe, got ${newConst.tpe}") - constantSerializer.serialize(newConst, w) + constantSerializer.serialize(newConst, constW) } } } + + val constBytes = constW.toBytes // nConstants + serialized new constants + + // start composing the resulting tree bytes + val w = SigmaSerializer.startWriter() + w.put(header) // header byte + + if (VersionContext.current.isV6SoftForkActivated) { + // fix in v6.0 to save tree size to respect size bit of the original tree + if (ErgoTree.hasSize(header)) { + val size = constBytes.length + treeBytes.length + w.putUInt(size) // tree size + } + } + + w.putBytes(constBytes) // constants section + w.putBytes(treeBytes) // tree section + w.toBytes } else { + val w = SigmaSerializer.startWriter() + w.put(header) + // for v4.x compatibility we save constants.length here (see the above comment to // understand the consequences) w.putUInt(constants.length) @@ -357,10 +383,12 @@ class ErgoTreeSerializer { case (c, _) => constantSerializer.serialize(c, w) } + + w.putBytes(treeBytes) + w.toBytes } - w.putBytes(treeBytes) - (w.toBytes, constants.length) + (resBytes, nConstants) } } diff --git a/sc/shared/src/test/scala/sigma/LanguageSpecificationBase.scala b/sc/shared/src/test/scala/sigma/LanguageSpecificationBase.scala index 2bb44fc910..26c7d7c8c2 100644 --- a/sc/shared/src/test/scala/sigma/LanguageSpecificationBase.scala +++ b/sc/shared/src/test/scala/sigma/LanguageSpecificationBase.scala @@ -1,10 +1,11 @@ package sigma import org.scalatest.BeforeAndAfterAll -import sigma.ast.JitCost +import sigma.ast.{Apply, FixedCostItem, FuncValue, GetVar, JitCost, OptionGet, ValUse} import sigma.eval.{EvalSettings, Profiler} import sigmastate.CompilerCrossVersionProps import sigmastate.interpreter.CErgoTreeEvaluator + import scala.util.Success /** Base class for language test suites (one suite for each language version: 5.0, 6.0, etc.) @@ -123,4 +124,17 @@ abstract class LanguageSpecificationBase extends SigmaDslTesting prepareSamples[(PreHeader, PreHeader)] prepareSamples[(Header, Header)] } + + ///===================================================== + /// CostDetails shared among test cases + ///----------------------------------------------------- + val traceBase = Array( + FixedCostItem(Apply), + FixedCostItem(FuncValue), + FixedCostItem(GetVar), + FixedCostItem(OptionGet), + FixedCostItem(FuncValue.AddToEnvironmentDesc, FuncValue.AddToEnvironmentDesc_CostKind), + FixedCostItem(ValUse) + ) + } diff --git a/sc/shared/src/test/scala/sigma/LanguageSpecificationV5.scala b/sc/shared/src/test/scala/sigma/LanguageSpecificationV5.scala index 700b48fd13..47e05b9528 100644 --- a/sc/shared/src/test/scala/sigma/LanguageSpecificationV5.scala +++ b/sc/shared/src/test/scala/sigma/LanguageSpecificationV5.scala @@ -47,17 +47,6 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => import TestData._ - ///===================================================== - /// CostDetails shared among test cases - ///----------------------------------------------------- - val traceBase = Array( - FixedCostItem(Apply), - FixedCostItem(FuncValue), - FixedCostItem(GetVar), - FixedCostItem(OptionGet), - FixedCostItem(FuncValue.AddToEnvironmentDesc, FuncValue.AddToEnvironmentDesc_CostKind), - FixedCostItem(ValUse) - ) def upcastCostDetails(tpe: SType) = TracedCost(traceBase :+ TypeBasedCostItem(Upcast, tpe)) def downcastCostDetails(tpe: SType) = TracedCost(traceBase :+ TypeBasedCostItem(Downcast, tpe)) def arithOpsCostDetails(tpe: SType) = CostDetails( @@ -4811,7 +4800,9 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => Seq(0, 1, 2, 3).map(version => version -> res) })) ), - changedFeature({ (x: Context) => x.selfBoxIndex }, + changedFeature( + changedInVersion = VersionContext.JitActivationVersion, + { (x: Context) => x.selfBoxIndex }, { (x: Context) => x.selfBoxIndex }, // see versioning in selfBoxIndex implementation "{ (x: Context) => x.selfBoxIndex }", FuncValue( @@ -5012,6 +5003,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => ) ), changedFeature( + changedInVersion = VersionContext.JitActivationVersion, scalaFunc = { (x: Context) => // this error is expected in v3.x, v4.x throw expectedError @@ -5985,6 +5977,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => ) }, changedFeature( + changedInVersion = VersionContext.JitActivationVersion, (x: Coll[Boolean]) => SigmaDsl.xorOf(x), (x: Coll[Boolean]) => SigmaDsl.xorOf(x), "{ (x: Coll[Boolean]) => xorOf(x) }", @@ -6247,6 +6240,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => ) }, changedFeature( + changedInVersion = VersionContext.JitActivationVersion, (x: (Coll[Byte], Coll[Byte])) => SigmaDsl.xor(x._1, x._2), (x: (Coll[Byte], Coll[Byte])) => SigmaDsl.xor(x._1, x._2), "{ (x: (Coll[Byte], Coll[Byte])) => xor(x._1, x._2) }", @@ -8816,6 +8810,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => (Some(Long.MaxValue) -> Expected(new ArithmeticException("long overflow"))) ), changedFeature( + changedInVersion = VersionContext.JitActivationVersion, scalaFunc = { (x: Option[Long]) => def f(opt: Long): Long = n.plus(opt, 1) if (x.isDefined) f(x.get) @@ -9371,6 +9366,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => ) }, changedFeature( + changedInVersion = VersionContext.JitActivationVersion, { (x: (Coll[Byte], Int)) => SigmaDsl.substConstants(x._1, Coll[Int](x._2), Coll[Any](SigmaDsl.sigmaProp(false))(sigma.AnyType)) }, @@ -9433,103 +9429,104 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => ) ), changedFeature( - { (x: Context) => - throw error - true - }, - { (x: Context) => - val headers = x.headers - val ids = headers.map({ (h: Header) => h.id }) - val parentIds = headers.map({ (h: Header) => h.parentId }) - headers.indices.slice(0, headers.size - 1).forall({ (i: Int) => - val parentId = parentIds(i) - val id = ids(i + 1) - parentId == id - }) - }, - """{ - |(x: Context) => - | val headers = x.headers - | val ids = headers.map({(h: Header) => h.id }) - | val parentIds = headers.map({(h: Header) => h.parentId }) - | headers.indices.slice(0, headers.size - 1).forall({ (i: Int) => - | val parentId = parentIds(i) - | val id = ids(i + 1) - | parentId == id - | }) - |}""".stripMargin, - FuncValue( - Array((1, SContext)), - BlockValue( - Array( - ValDef( - 3, - List(), - MethodCall.typed[Value[SCollection[SHeader.type]]]( - ValUse(1, SContext), - SContextMethods.getMethodByName("headers"), - Vector(), - Map() - ) - ) - ), - ForAll( - Slice( - MethodCall.typed[Value[SCollection[SInt.type]]]( - ValUse(3, SCollectionType(SHeader)), - SCollectionMethods.getMethodByName("indices").withConcreteTypes(Map(STypeVar("IV") -> SHeader)), - Vector(), - Map() - ), - IntConstant(0), - ArithOp( - SizeOf(ValUse(3, SCollectionType(SHeader))), - IntConstant(1), - OpCode @@ (-103.toByte) + changedInVersion = VersionContext.JitActivationVersion, + { (x: Context) => + throw error + true + }, + { (x: Context) => + val headers = x.headers + val ids = headers.map({ (h: Header) => h.id }) + val parentIds = headers.map({ (h: Header) => h.parentId }) + headers.indices.slice(0, headers.size - 1).forall({ (i: Int) => + val parentId = parentIds(i) + val id = ids(i + 1) + parentId == id + }) + }, + """{ + |(x: Context) => + | val headers = x.headers + | val ids = headers.map({(h: Header) => h.id }) + | val parentIds = headers.map({(h: Header) => h.parentId }) + | headers.indices.slice(0, headers.size - 1).forall({ (i: Int) => + | val parentId = parentIds(i) + | val id = ids(i + 1) + | parentId == id + | }) + |}""".stripMargin, + FuncValue( + Array((1, SContext)), + BlockValue( + Array( + ValDef( + 3, + List(), + MethodCall.typed[Value[SCollection[SHeader.type]]]( + ValUse(1, SContext), + SContextMethods.getMethodByName("headers"), + Vector(), + Map() + ) ) ), - FuncValue( - Array((4, SInt)), - EQ( - ByIndex( - MapCollection( - ValUse(3, SCollectionType(SHeader)), - FuncValue( - Array((6, SHeader)), - MethodCall.typed[Value[SCollection[SByte.type]]]( - ValUse(6, SHeader), - SHeaderMethods.getMethodByName("parentId"), - Vector(), - Map() - ) - ) - ), - ValUse(4, SInt), - None + ForAll( + Slice( + MethodCall.typed[Value[SCollection[SInt.type]]]( + ValUse(3, SCollectionType(SHeader)), + SCollectionMethods.getMethodByName("indices").withConcreteTypes(Map(STypeVar("IV") -> SHeader)), + Vector(), + Map() ), - ByIndex( - MapCollection( - ValUse(3, SCollectionType(SHeader)), - FuncValue( - Array((6, SHeader)), - MethodCall.typed[Value[SCollection[SByte.type]]]( - ValUse(6, SHeader), - SHeaderMethods.getMethodByName("id"), - Vector(), - Map() + IntConstant(0), + ArithOp( + SizeOf(ValUse(3, SCollectionType(SHeader))), + IntConstant(1), + OpCode @@ (-103.toByte) + ) + ), + FuncValue( + Array((4, SInt)), + EQ( + ByIndex( + MapCollection( + ValUse(3, SCollectionType(SHeader)), + FuncValue( + Array((6, SHeader)), + MethodCall.typed[Value[SCollection[SByte.type]]]( + ValUse(6, SHeader), + SHeaderMethods.getMethodByName("parentId"), + Vector(), + Map() + ) ) - ) + ), + ValUse(4, SInt), + None ), - ArithOp(ValUse(4, SInt), IntConstant(1), OpCode @@ (-102.toByte)), - None + ByIndex( + MapCollection( + ValUse(3, SCollectionType(SHeader)), + FuncValue( + Array((6, SHeader)), + MethodCall.typed[Value[SCollection[SByte.type]]]( + ValUse(6, SHeader), + SHeaderMethods.getMethodByName("id"), + Vector(), + Map() + ) + ) + ), + ArithOp(ValUse(4, SInt), IntConstant(1), OpCode @@ (-102.toByte)), + None + ) ) ) ) ) - ) - ), - allowDifferentErrors = true, - allowNewToSucceed = true + ), + allowDifferentErrors = true, + allowNewToSucceed = true ), preGeneratedSamples = Some(ArraySeq.empty) ) diff --git a/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala b/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala index 20faabe128..78dd36ed97 100644 --- a/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala +++ b/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala @@ -1,10 +1,14 @@ package sigma -import sigma.ast.{Downcast, FuncValue, Global, MethodCall, SBigInt, SByte, SGlobalMethods, SInt, SLong, SShort, STypeVar, ValUse} +import sigma.ast.ErgoTree.ZeroHeader +import sigma.ast.SCollection.SByteArray +import sigma.ast.syntax.TrueSigmaProp +import sigma.ast.{BoolToSigmaProp, CompanionDesc, ConcreteCollection, Constant, ConstantPlaceholder, Downcast, ErgoTree, FalseLeaf, FixedCostItem, FuncValue, Global, JitCost, MethodCall, PerItemCost, SBigInt, SByte, SCollection, SGlobalMethods, SInt, SLong, SPair, SShort, SSigmaProp, STypeVar, SelectField, SubstConstants, ValUse, Value} import sigma.data.{CBigInt, ExactNumeric, RType} -import sigma.eval.SigmaDsl +import sigma.eval.{CostDetails, SigmaDsl, TracedCost} import sigma.util.Extensions.{BooleanOps, ByteOps, IntOps, LongOps} import sigmastate.exceptions.MethodNotFound +import sigmastate.utils.Helpers import java.math.BigInteger import scala.util.Success @@ -378,5 +382,85 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite => } } + property("Fix substConstants in v6.0 for ErgoTree version > 0") { + // tree with one segregated constant and v0 + val t1 = ErgoTree( + header = ZeroHeader.withConstantSegregation, + constants = Vector(TrueSigmaProp), + ConstantPlaceholder(0, SSigmaProp)) + + // tree with one segregated constant and max supported version + val t2 = ErgoTree( + header = ZeroHeader + .withVersion(VersionContext.MaxSupportedScriptVersion) + .withConstantSegregation, + Vector(TrueSigmaProp), + ConstantPlaceholder(0, SSigmaProp)) + + def costDetails(nItems: Int) = TracedCost( + traceBase ++ Array( + FixedCostItem(SelectField), + FixedCostItem(ConcreteCollection), + FixedCostItem(ValUse), + FixedCostItem(SelectField), + FixedCostItem(ConcreteCollection), + FixedCostItem(Constant), + FixedCostItem(BoolToSigmaProp), + ast.SeqCostItem(CompanionDesc(SubstConstants), PerItemCost(JitCost(100), JitCost(100), 1), nItems) + ) + ) + val expectedTreeBytes_beforeV6 = Helpers.decodeBytes("1b0108d27300") + val expectedTreeBytes_V6 = Helpers.decodeBytes("1b050108d27300") + + verifyCases( + { + def success[T](v: T, cd: CostDetails, cost: Int ) = Expected(Success(v), cost, cd, cost) + + Seq( + // for tree v0, the result is the same for all versions + (Coll(t1.bytes: _*), 0) -> Expected( + Success(Helpers.decodeBytes("100108d27300")), + cost = 1793, + expectedDetails = CostDetails.ZeroCost, + newCost = 1793, + newVersionedResults = { + val res = (ExpectedResult(Success(Helpers.decodeBytes("100108d27300")), Some(1793)) -> Some(costDetails(1))) + Seq(0, 1, 2, 3).map(version => version -> res) + }), + // for tree version > 0, the result depend on activated version + (Coll(t2.bytes: _*), 0) -> Expected( + Success(expectedTreeBytes_beforeV6), + cost = 1793, + expectedDetails = CostDetails.ZeroCost, + newCost = 1793, + newVersionedResults = { + val res = (ExpectedResult(Success(expectedTreeBytes_V6), Some(1793)) -> Some(costDetails(1))) + Seq(0, 1, 2, 3).map(version => version -> res) + }) + ) + }, + changedFeature( + changedInVersion = VersionContext.V6SoftForkVersion, + { (x: (Coll[Byte], Int)) => + SigmaDsl.substConstants(x._1, Coll[Int](x._2), Coll[Any](SigmaDsl.sigmaProp(false))(sigma.AnyType)) + }, + { (x: (Coll[Byte], Int)) => + SigmaDsl.substConstants(x._1, Coll[Int](x._2), Coll[Any](SigmaDsl.sigmaProp(false))(sigma.AnyType)) + }, + "{ (x: (Coll[Byte], Int)) => substConstants[Any](x._1, Coll[Int](x._2), Coll[Any](sigmaProp(false))) }", + FuncValue( + Vector((1, SPair(SByteArray, SInt))), + SubstConstants( + SelectField.typed[Value[SCollection[SByte.type]]](ValUse(1, SPair(SByteArray, SInt)), 1.toByte), + ConcreteCollection( + Array(SelectField.typed[Value[SInt.type]](ValUse(1, SPair(SByteArray, SInt)), 2.toByte)), + SInt + ), + ConcreteCollection(Array(BoolToSigmaProp(FalseLeaf)), SSigmaProp) + ) + ) + ) + ) + } } diff --git a/sc/shared/src/test/scala/sigma/SigmaDslTesting.scala b/sc/shared/src/test/scala/sigma/SigmaDslTesting.scala index 28c9c05fec..3246f968a0 100644 --- a/sc/shared/src/test/scala/sigma/SigmaDslTesting.scala +++ b/sc/shared/src/test/scala/sigma/SigmaDslTesting.scala @@ -126,6 +126,9 @@ class SigmaDslTesting extends AnyPropSpec /** Checks if this feature is supported in the given version context. */ def isSupportedIn(vc: VersionContext): Boolean + /** Version in which the feature is first implemented of changed. */ + def sinceVersion: Byte + /** Script containing this feature. */ def script: String @@ -397,7 +400,7 @@ class SigmaDslTesting extends AnyPropSpec ctx } - val (expectedResult, expectedCost) = if (activatedVersionInTests < VersionContext.JitActivationVersion) + val (expectedResult, expectedCost) = if (activatedVersionInTests < sinceVersion) (expected.oldResult, expected.verificationCostOpt) else { val res = expected.newResults(ergoTreeVersionInTests) @@ -504,6 +507,8 @@ class SigmaDslTesting extends AnyPropSpec implicit val cs = compilerSettingsInTests + override def sinceVersion: Byte = 0 + override def isSupportedIn(vc: VersionContext): Boolean = true /** in v5.x the old and the new interpreters are the same */ @@ -640,10 +645,11 @@ class SigmaDslTesting extends AnyPropSpec } } - /** Descriptor of a language feature which is changed in v5.0. + /** Descriptor of a language feature which is changed in the specified version. * * @tparam A type of an input test data * @tparam B type of an output of the feature function + * @param changedInVersion version in which the feature behaviour is changed * @param script script of the feature function (see Feature trait) * @param scalaFunc feature function written in Scala and used to simulate the behavior * of the script @@ -663,6 +669,7 @@ class SigmaDslTesting extends AnyPropSpec * @param allowDifferentErrors if true, allow v4.x and v5.0 to fail with different error */ case class ChangedFeature[A, B]( + changedInVersion: Byte, script: String, scalaFunc: A => B, override val scalaFuncNew: A => B, @@ -676,6 +683,8 @@ class SigmaDslTesting extends AnyPropSpec implicit val cs = compilerSettingsInTests + override def sinceVersion: Byte = changedInVersion + override def isSupportedIn(vc: VersionContext): Boolean = true /** Apply given function to the context variable 1 */ @@ -755,7 +764,7 @@ class SigmaDslTesting extends AnyPropSpec checkEq(scalaFuncNew)(newF)(input) } - if (!VersionContext.current.isJitActivated) { + if (VersionContext.current.activatedVersion < changedInVersion) { // check the old implementation with Scala semantic val expectedOldRes = expected.value @@ -1054,14 +1063,16 @@ class SigmaDslTesting extends AnyPropSpec * various ways */ def changedFeature[A: RType, B: RType] - (scalaFunc: A => B, + (changedInVersion: Byte, + scalaFunc: A => B, scalaFuncNew: A => B, script: String, expectedExpr: SValue = null, allowNewToSucceed: Boolean = false, - allowDifferentErrors: Boolean = false) + allowDifferentErrors: Boolean = false + ) (implicit IR: IRContext, evalSettings: EvalSettings): Feature[A, B] = { - ChangedFeature(script, scalaFunc, scalaFuncNew, Option(expectedExpr), + ChangedFeature(changedInVersion, script, scalaFunc, scalaFuncNew, Option(expectedExpr), allowNewToSucceed = allowNewToSucceed, allowDifferentErrors = allowDifferentErrors) } From d4bbccc7364000a80dcfc18847d126de05ed0e27 Mon Sep 17 00:00:00 2001 From: Alexander Slesarenko Date: Thu, 23 May 2024 13:28:53 +0200 Subject: [PATCH 10/19] v6.0-serialize: fix JS tests (added reflection data) --- data/shared/src/main/scala/sigma/SigmaDataReflection.scala | 5 +++++ .../src/main/scala/sigma/compiler/ir/GraphIRReflection.scala | 3 +++ 2 files changed, 8 insertions(+) diff --git a/data/shared/src/main/scala/sigma/SigmaDataReflection.scala b/data/shared/src/main/scala/sigma/SigmaDataReflection.scala index 48939b1460..a6e5de2a26 100644 --- a/data/shared/src/main/scala/sigma/SigmaDataReflection.scala +++ b/data/shared/src/main/scala/sigma/SigmaDataReflection.scala @@ -322,6 +322,11 @@ object SigmaDataReflection { args(1).asInstanceOf[SigmaDslBuilder], args(2).asInstanceOf[Coll[Byte]], args(3).asInstanceOf[Coll[Byte]])(args(4).asInstanceOf[ErgoTreeEvaluator]) + }, + mkMethod(clazz, "serialize_eval", Array[Class[_]](classOf[MethodCall], classOf[SigmaDslBuilder], classOf[Object], classOf[ErgoTreeEvaluator])) { (obj, args) => + obj.asInstanceOf[SGlobalMethods.type].serialize_eval(args(0).asInstanceOf[MethodCall], + args(1).asInstanceOf[SigmaDslBuilder], + args(2).asInstanceOf[SType#WrappedType])(args(3).asInstanceOf[ErgoTreeEvaluator]) } ) ) 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 69736a0224..6c0403f643 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/GraphIRReflection.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/GraphIRReflection.scala @@ -504,6 +504,9 @@ object GraphIRReflection { }, mkMethod(clazz, "decodePoint", Array[Class[_]](classOf[Base#Ref[_]])) { (obj, args) => obj.asInstanceOf[ctx.SigmaDslBuilder].decodePoint(args(0).asInstanceOf[ctx.Ref[ctx.Coll[Byte]]]) + }, + mkMethod(clazz, "serialize", Array[Class[_]](classOf[Base#Ref[_]])) { (obj, args) => + obj.asInstanceOf[ctx.SigmaDslBuilder].serialize(args(0).asInstanceOf[ctx.Ref[Any]]) } ) ) From de18eeb662a0701ec2def489f89e537d113dfc6e Mon Sep 17 00:00:00 2001 From: Alexander Slesarenko Date: Thu, 23 May 2024 16:08:20 +0200 Subject: [PATCH 11/19] i994-fix-subst-constants: more tests --- .../scala/sigma/LanguageSpecificationV6.scala | 52 +++++++++++-------- 1 file changed, 31 insertions(+), 21 deletions(-) diff --git a/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala b/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala index 78dd36ed97..fd2e18ebfb 100644 --- a/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala +++ b/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala @@ -1,11 +1,13 @@ package sigma +import org.ergoplatform.sdk.utils.ErgoTreeUtils import sigma.ast.ErgoTree.ZeroHeader import sigma.ast.SCollection.SByteArray import sigma.ast.syntax.TrueSigmaProp import sigma.ast.{BoolToSigmaProp, CompanionDesc, ConcreteCollection, Constant, ConstantPlaceholder, Downcast, ErgoTree, FalseLeaf, FixedCostItem, FuncValue, Global, JitCost, MethodCall, PerItemCost, SBigInt, SByte, SCollection, SGlobalMethods, SInt, SLong, SPair, SShort, SSigmaProp, STypeVar, SelectField, SubstConstants, ValUse, Value} import sigma.data.{CBigInt, ExactNumeric, RType} import sigma.eval.{CostDetails, SigmaDsl, TracedCost} +import sigma.serialization.ErgoTreeSerializer import sigma.util.Extensions.{BooleanOps, ByteOps, IntOps, LongOps} import sigmastate.exceptions.MethodNotFound import sigmastate.utils.Helpers @@ -21,6 +23,11 @@ import scala.util.Success class LanguageSpecificationV6 extends LanguageSpecificationBase { suite => override def languageVersion: Byte = VersionContext.V6SoftForkVersion + def expectedSuccessForAllTreeVersions[A](value: A, cost: Int, costDetails: CostDetails) = { + val res = ExpectedResult(Success(value), Some(cost)) -> Some(costDetails) + Seq(0, 1, 2, 3).map(version => version -> res) + } + def mkSerializeFeature[A: RType]: Feature[A, Coll[Byte]] = { val tA = RType[A] val tpe = Evaluation.rtypeToSType(tA) @@ -414,32 +421,25 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite => val expectedTreeBytes_V6 = Helpers.decodeBytes("1b050108d27300") verifyCases( - { - def success[T](v: T, cd: CostDetails, cost: Int ) = Expected(Success(v), cost, cd, cost) - - Seq( - // for tree v0, the result is the same for all versions - (Coll(t1.bytes: _*), 0) -> Expected( - Success(Helpers.decodeBytes("100108d27300")), - cost = 1793, - expectedDetails = CostDetails.ZeroCost, - newCost = 1793, - newVersionedResults = { - val res = (ExpectedResult(Success(Helpers.decodeBytes("100108d27300")), Some(1793)) -> Some(costDetails(1))) - Seq(0, 1, 2, 3).map(version => version -> res) - }), - // for tree version > 0, the result depend on activated version + Seq( + // for tree v0, the result is the same for all versions + (Coll(t1.bytes: _*), 0) -> Expected( + Success(Helpers.decodeBytes("100108d27300")), + cost = 1793, + expectedDetails = CostDetails.ZeroCost, + newCost = 1793, + newVersionedResults = expectedSuccessForAllTreeVersions(Helpers.decodeBytes("100108d27300"), 1793, costDetails(1)) + ), + // for tree version > 0, the result depend on activated version + { (Coll(t2.bytes: _*), 0) -> Expected( Success(expectedTreeBytes_beforeV6), cost = 1793, expectedDetails = CostDetails.ZeroCost, newCost = 1793, - newVersionedResults = { - val res = (ExpectedResult(Success(expectedTreeBytes_V6), Some(1793)) -> Some(costDetails(1))) - Seq(0, 1, 2, 3).map(version => version -> res) - }) - ) - }, + newVersionedResults = expectedSuccessForAllTreeVersions(expectedTreeBytes_V6, 1793, costDetails(1))) + } + ), changedFeature( changedInVersion = VersionContext.V6SoftForkVersion, { (x: (Coll[Byte], Int)) => @@ -462,5 +462,15 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite => ) ) ) + + // before v6.0 the expected tree is not parsable + ErgoTree.fromBytes(expectedTreeBytes_beforeV6.toArray).isRightParsed shouldBe false + + // in v6.0 the expected tree should be parsable and similar to the original tree + val tree = ErgoTree.fromBytes(expectedTreeBytes_V6.toArray) + tree.isRightParsed shouldBe true + tree.header shouldBe t2.header + tree.constants.length shouldBe t2.constants.length + tree.root shouldBe t2.root } } From fd8e5d7a17694a22f5062c180659696af4e4f890 Mon Sep 17 00:00:00 2001 From: Alexander Slesarenko Date: Mon, 3 Jun 2024 21:27:23 +0200 Subject: [PATCH 12/19] i994-fix-subst-constants: cleanup + ScalaDocs --- data/shared/src/main/scala/sigma/ast/ErgoTree.scala | 6 ++++++ .../src/test/scala/sigma/LanguageSpecificationBase.scala | 8 +++++++- .../src/test/scala/sigma/LanguageSpecificationV6.scala | 6 ------ 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/data/shared/src/main/scala/sigma/ast/ErgoTree.scala b/data/shared/src/main/scala/sigma/ast/ErgoTree.scala index eae420612e..3bb69b96dc 100644 --- a/data/shared/src/main/scala/sigma/ast/ErgoTree.scala +++ b/data/shared/src/main/scala/sigma/ast/ErgoTree.scala @@ -228,8 +228,14 @@ object ErgoTree { type HeaderType = HeaderType.Type + /** Convenience methods for working with ErgoTree headers. */ implicit class HeaderTypeOps(val header: HeaderType) extends AnyVal { + /** Update the version bits of the given header byte with the given version value, + * leaving all other bits unchanged. + */ def withVersion(version: Byte): HeaderType = ErgoTree.headerWithVersion(header, version) + + /** Sets the constant segregation bit in the given header. */ def withConstantSegregation: HeaderType = ErgoTree.setConstantSegregation(header) } diff --git a/sc/shared/src/test/scala/sigma/LanguageSpecificationBase.scala b/sc/shared/src/test/scala/sigma/LanguageSpecificationBase.scala index 26c7d7c8c2..7be79546e7 100644 --- a/sc/shared/src/test/scala/sigma/LanguageSpecificationBase.scala +++ b/sc/shared/src/test/scala/sigma/LanguageSpecificationBase.scala @@ -2,7 +2,7 @@ package sigma import org.scalatest.BeforeAndAfterAll import sigma.ast.{Apply, FixedCostItem, FuncValue, GetVar, JitCost, OptionGet, ValUse} -import sigma.eval.{EvalSettings, Profiler} +import sigma.eval.{CostDetails, EvalSettings, Profiler} import sigmastate.CompilerCrossVersionProps import sigmastate.interpreter.CErgoTreeEvaluator @@ -137,4 +137,10 @@ abstract class LanguageSpecificationBase extends SigmaDslTesting FixedCostItem(ValUse) ) + /** Helper method to create the given expected results for all tree versions. */ + def expectedSuccessForAllTreeVersions[A](value: A, cost: Int, costDetails: CostDetails) = { + val res = ExpectedResult(Success(value), Some(cost)) -> Some(costDetails) + Seq(0, 1, 2, 3).map(version => version -> res) + } + } diff --git a/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala b/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala index fd2e18ebfb..e8837a02d7 100644 --- a/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala +++ b/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala @@ -7,7 +7,6 @@ import sigma.ast.syntax.TrueSigmaProp import sigma.ast.{BoolToSigmaProp, CompanionDesc, ConcreteCollection, Constant, ConstantPlaceholder, Downcast, ErgoTree, FalseLeaf, FixedCostItem, FuncValue, Global, JitCost, MethodCall, PerItemCost, SBigInt, SByte, SCollection, SGlobalMethods, SInt, SLong, SPair, SShort, SSigmaProp, STypeVar, SelectField, SubstConstants, ValUse, Value} import sigma.data.{CBigInt, ExactNumeric, RType} import sigma.eval.{CostDetails, SigmaDsl, TracedCost} -import sigma.serialization.ErgoTreeSerializer import sigma.util.Extensions.{BooleanOps, ByteOps, IntOps, LongOps} import sigmastate.exceptions.MethodNotFound import sigmastate.utils.Helpers @@ -23,11 +22,6 @@ import scala.util.Success class LanguageSpecificationV6 extends LanguageSpecificationBase { suite => override def languageVersion: Byte = VersionContext.V6SoftForkVersion - def expectedSuccessForAllTreeVersions[A](value: A, cost: Int, costDetails: CostDetails) = { - val res = ExpectedResult(Success(value), Some(cost)) -> Some(costDetails) - Seq(0, 1, 2, 3).map(version => version -> res) - } - def mkSerializeFeature[A: RType]: Feature[A, Coll[Byte]] = { val tA = RType[A] val tpe = Evaluation.rtypeToSType(tA) From 07b86446ec812e6073912de1de3f0b6d6404aeba Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Thu, 6 Jun 2024 12:34:46 +0300 Subject: [PATCH 13/19] moving newFeature related code from serializePR --- .../sigmastate/helpers/SigmaPPrint.scala | 6 +- .../scala/sigmastate/lang/LangTests.scala | 6 + .../sigmastate/lang/SigmaParserTest.scala | 12 + .../sigmastate/helpers/SigmaPPrintSpec.scala | 1 - .../sigma/LanguageSpecificationBase.scala | 126 ++++++ ...on.scala => LanguageSpecificationV5.scala} | 358 +----------------- .../scala/sigma/LanguageSpecificationV6.scala | 348 +++++++++++++++++ .../test/scala/sigma/SigmaDslTesting.scala | 142 +++++-- .../CompilerCrossVersionProps.scala | 11 +- .../sigmastate/lang/SigmaBinderTest.scala | 13 + .../sigmastate/lang/SigmaTyperTest.scala | 9 +- 11 files changed, 634 insertions(+), 398 deletions(-) rename {sc => parsers}/shared/src/test/scala/sigmastate/helpers/SigmaPPrint.scala (98%) create mode 100644 sc/shared/src/test/scala/sigma/LanguageSpecificationBase.scala rename sc/shared/src/test/scala/sigma/{SigmaDslSpecification.scala => LanguageSpecificationV5.scala} (96%) create mode 100644 sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala diff --git a/sc/shared/src/test/scala/sigmastate/helpers/SigmaPPrint.scala b/parsers/shared/src/test/scala/sigmastate/helpers/SigmaPPrint.scala similarity index 98% rename from sc/shared/src/test/scala/sigmastate/helpers/SigmaPPrint.scala rename to parsers/shared/src/test/scala/sigmastate/helpers/SigmaPPrint.scala index 1b0f7b112d..24aaeddefd 100644 --- a/sc/shared/src/test/scala/sigmastate/helpers/SigmaPPrint.scala +++ b/parsers/shared/src/test/scala/sigmastate/helpers/SigmaPPrint.scala @@ -5,15 +5,13 @@ import org.ergoplatform.ErgoBox.RegisterId import org.ergoplatform.settings.ErgoAlgos import pprint.{PPrinter, Tree} import sigma.ast.SCollection.{SBooleanArray, SByteArray, SByteArray2} -import sigma.ast._ +import sigma.ast.{ConstantNode, FuncValue, MethodCall, ValueCompanion, _} import sigma.crypto.EcPointType import sigma.data.{AvlTreeData, AvlTreeFlags, CollType, PrimitiveType, TrivialProp} import sigma.serialization.GroupElementSerializer import sigma.{Coll, GroupElement} -import sigma.ast.{ConstantNode, FuncValue, ValueCompanion} -import sigmastate._ import sigmastate.crypto.GF2_192_Poly -import sigma.ast.MethodCall + import java.math.BigInteger import scala.collection.compat.immutable.ArraySeq import scala.collection.mutable diff --git a/parsers/shared/src/test/scala/sigmastate/lang/LangTests.scala b/parsers/shared/src/test/scala/sigmastate/lang/LangTests.scala index 32943bca44..de83070ac3 100644 --- a/parsers/shared/src/test/scala/sigmastate/lang/LangTests.scala +++ b/parsers/shared/src/test/scala/sigmastate/lang/LangTests.scala @@ -79,4 +79,10 @@ trait LangTests extends Matchers with NegativeTesting { node }))(tree) } + + /** Execute the given `block` having `version` as both activated and ErgoTree version. */ + def runWithVersion[T](version: Byte)(block: => T): T = { + VersionContext.withVersions(version, version)(block) + } + } diff --git a/parsers/shared/src/test/scala/sigmastate/lang/SigmaParserTest.scala b/parsers/shared/src/test/scala/sigmastate/lang/SigmaParserTest.scala index 02b28f86ca..dc63330f95 100644 --- a/parsers/shared/src/test/scala/sigmastate/lang/SigmaParserTest.scala +++ b/parsers/shared/src/test/scala/sigmastate/lang/SigmaParserTest.scala @@ -14,6 +14,7 @@ import SigmaPredef.PredefinedFuncRegistry import sigma.ast.syntax._ import sigmastate.lang.parsers.ParserException import sigma.serialization.OpCodes +import sigmastate.helpers.SigmaPPrint class SigmaParserTest extends AnyPropSpec with ScalaCheckPropertyChecks with Matchers with LangTests { import StdSigmaBuilder._ @@ -34,6 +35,17 @@ class SigmaParserTest extends AnyPropSpec with ScalaCheckPropertyChecks with Mat } } + /** Checks parsing result, printing the actual value as a test vector if expected value + * is not equal to actual. + */ + def checkParsed(x: String, expected: SValue) = { + val parsed = parse(x) + if (expected != parsed) { + SigmaPPrint.pprintln(parsed, width = 100) + } + parsed shouldBe expected + } + def parseWithException(x: String): SValue = { SigmaParser(x) match { case Parsed.Success(v, _) => v diff --git a/sc/jvm/src/test/scala/sigmastate/helpers/SigmaPPrintSpec.scala b/sc/jvm/src/test/scala/sigmastate/helpers/SigmaPPrintSpec.scala index 54c0f652dc..ffd591b0df 100644 --- a/sc/jvm/src/test/scala/sigmastate/helpers/SigmaPPrintSpec.scala +++ b/sc/jvm/src/test/scala/sigmastate/helpers/SigmaPPrintSpec.scala @@ -8,7 +8,6 @@ import sigma.SigmaDslTesting import sigma.ast._ import sigma.data.{AvlTreeData, AvlTreeFlags, CBox, CollType, Digest32Coll} import ErgoTree.HeaderType -import sigmastate.eval._ import sigma.ast.MethodCall import sigma.serialization.OpCodes import sigmastate.utils.Helpers diff --git a/sc/shared/src/test/scala/sigma/LanguageSpecificationBase.scala b/sc/shared/src/test/scala/sigma/LanguageSpecificationBase.scala new file mode 100644 index 0000000000..2bb44fc910 --- /dev/null +++ b/sc/shared/src/test/scala/sigma/LanguageSpecificationBase.scala @@ -0,0 +1,126 @@ +package sigma + +import org.scalatest.BeforeAndAfterAll +import sigma.ast.JitCost +import sigma.eval.{EvalSettings, Profiler} +import sigmastate.CompilerCrossVersionProps +import sigmastate.interpreter.CErgoTreeEvaluator +import scala.util.Success + +/** Base class for language test suites (one suite for each language version: 5.0, 6.0, etc.) + * Each suite tests every method of every SigmaDsl type to be equivalent to + * the evaluation of the corresponding ErgoScript operation. + * + * The properties of this suite exercise two interpreters: the current (aka `old` + * interpreter) and the new interpreter for a next soft-fork. After the soft-fork is + * released, the new interpreter becomes current at which point the `old` and `new` + * interpreters in this suite should be equivalent. This change is reflected in this + * suite by commiting changes in expected values. + * The `old` and `new` interpreters are compared like the following: + * 1) for existingFeature the interpreters should be equivalent + * 2) for changedFeature the test cases contain different expected values + * 3) for newFeature the old interpreter should throw and the new interpreter is checked + * against expected values. + * + * This suite can be used for Cost profiling, i.e. measurements of operations times and + * comparing them with cost parameters of the operations. + * + * The following settings should be specified for profiling: + * isMeasureOperationTime = true + * isMeasureScriptTime = true + * isLogEnabled = false + * printTestVectors = false + * costTracingEnabled = false + * isTestRun = true + * perTestWarmUpIters = 1 + * nBenchmarkIters = 1 + */ +abstract class LanguageSpecificationBase extends SigmaDslTesting + with CompilerCrossVersionProps + with BeforeAndAfterAll { suite => + + /** Version of the language (ErgoScript/ErgoTree) which is specified by this suite. */ + def languageVersion: Byte + + /** Use VersionContext so that each property in this suite runs under correct + * parameters. + */ + protected override def testFun_Run(testName: String, testFun: => Any): Unit = { + VersionContext.withVersions(activatedVersionInTests, ergoTreeVersionInTests) { + super.testFun_Run(testName, testFun) + } + } + + implicit override val generatorDrivenConfig: PropertyCheckConfiguration = PropertyCheckConfiguration(minSuccessful = 30) + + val evalSettingsInTests = CErgoTreeEvaluator.DefaultEvalSettings.copy( + isMeasureOperationTime = true, + isMeasureScriptTime = true, + isLogEnabled = false, // don't commit the `true` value (travis log is too high) + printTestVectors = false, // don't commit the `true` value (travis log is too high) + + /** Should always be enabled in tests (and false by default) + * Should be disabled for cost profiling, which case the new costs are not checked. + */ + costTracingEnabled = true, + profilerOpt = Some(CErgoTreeEvaluator.DefaultProfiler), + isTestRun = true + ) + + def warmupSettings(p: Profiler) = evalSettingsInTests.copy( + isLogEnabled = false, + printTestVectors = false, + profilerOpt = Some(p) + ) + + implicit override def evalSettings: EvalSettings = { + warmupProfiler match { + case Some(p) => warmupSettings(p) + case _ => evalSettingsInTests + } + } + + override val perTestWarmUpIters = 0 + + override val nBenchmarkIters = 0 + + override val okRunTestsWithoutMCLowering: Boolean = true + + implicit def IR = createIR() + + def testCases[A, B](cases: Seq[(A, Expected[B])], f: Feature[A, B]) = { + val table = Table(("x", "y"), cases: _*) + forAll(table) { (x, expectedRes) => + val res = f.checkEquality(x) + val resValue = res.map(_._1) + val (expected, expDetailsOpt) = expectedRes.newResults(ergoTreeVersionInTests) + checkResult(resValue, expected.value, failOnTestVectors = true, + "SigmaDslSpecifiction#testCases: compare expected new result with res = f.checkEquality(x)") + res match { + case Success((value, details)) => + details.cost shouldBe JitCost(expected.verificationCost.get) + expDetailsOpt.foreach(expDetails => + if (details.trace != expDetails.trace) { + printCostDetails(f.script, details) + details.trace shouldBe expDetails.trace + } + ) + } + } + } + + override protected def beforeAll(): Unit = { + prepareSamples[BigInt] + prepareSamples[GroupElement] + prepareSamples[AvlTree] + prepareSamples[Box] + prepareSamples[PreHeader] + prepareSamples[Header] + prepareSamples[(BigInt, BigInt)] + prepareSamples[(GroupElement, GroupElement)] + prepareSamples[(AvlTree, AvlTree)] + prepareSamples[(Box, Box)] + prepareSamples[(PreHeader, PreHeader)] + prepareSamples[(Header, Header)] + } +} diff --git a/sc/shared/src/test/scala/sigma/SigmaDslSpecification.scala b/sc/shared/src/test/scala/sigma/LanguageSpecificationV5.scala similarity index 96% rename from sc/shared/src/test/scala/sigma/SigmaDslSpecification.scala rename to sc/shared/src/test/scala/sigma/LanguageSpecificationV5.scala index c820e65e73..700b48fd13 100644 --- a/sc/shared/src/test/scala/sigma/SigmaDslSpecification.scala +++ b/sc/shared/src/test/scala/sigma/LanguageSpecificationV5.scala @@ -5,31 +5,28 @@ import org.ergoplatform._ import org.ergoplatform.settings.ErgoAlgos import org.scalacheck.Arbitrary._ import org.scalacheck.{Arbitrary, Gen} -import org.scalatest.BeforeAndAfterAll import scorex.crypto.authds.avltree.batch._ import scorex.crypto.authds.{ADKey, ADValue} import scorex.crypto.hash.{Blake2b256, Digest32} import scorex.util.ModifierId import sigma.Extensions.{ArrayOps, CollOps} +import sigma.ast.ErgoTree.{HeaderType, ZeroHeader} import sigma.ast.SCollection._ -import sigma.ast._ import sigma.ast.syntax._ +import sigma.ast.{Apply, MethodCall, PropertyCall, _} +import sigma.data.OrderingOps._ import sigma.data.RType._ import sigma.data._ +import sigma.eval.Extensions.{ByteExt, IntExt, LongExt, ShortExt} +import sigma.eval.{CostDetails, EvalSettings, SigmaDsl, TracedCost} +import sigma.exceptions.InvalidType +import sigma.serialization.ValueCodes.OpCode import sigma.util.Extensions.{BooleanOps, IntOps, LongOps} import sigma.{VersionContext, ast, data, _} -import ErgoTree.{HeaderType, ZeroHeader} -import sigma.eval.{CostDetails, EvalSettings, Profiler, SigmaDsl, TracedCost} -import sigmastate._ import sigmastate.eval.Extensions.AvlTreeOps -import sigma.eval.Extensions.{ByteExt, IntExt, LongExt, ShortExt} -import OrderingOps._ import sigmastate.eval._ import sigmastate.helpers.TestingHelpers._ import sigmastate.interpreter._ -import sigma.ast.{Apply, MethodCall, PropertyCall} -import sigma.exceptions.InvalidType -import sigma.serialization.ValueCodes.OpCode import sigmastate.utils.Extensions._ import sigmastate.utils.Helpers import sigmastate.utils.Helpers._ @@ -38,122 +35,18 @@ import java.math.BigInteger import scala.collection.compat.immutable.ArraySeq import scala.util.{Failure, Success} -/** This suite tests every method of every SigmaDsl type to be equivalent to - * the evaluation of the corresponding ErgoScript operation. - * - * The properties of this suite excercise two interpreters: the current (aka `old` - * interpreter) and the new interpreter for a next soft-fork. After the soft-fork is - * released, the new interpreter becomes current at which point the `old` and `new` - * interpreters in this suite should be equivalent. This change is reflected in this - * suite by commiting changes in expected values. - * The `old` and `new` interpreters are compared like the following: - * 1) for existingFeature the interpreters should be equivalent - * 2) for changedFeature the test cases contain different expected values - * 3) for newFeature the old interpreter should throw and the new interpreter is checked - * against expected values. - * - * This suite can be used for Cost profiling, i.e. measurements of operations times and - * comparing them with cost parameteres of the operations. + +/** This suite tests all operations for v5.0 version of the language. + * The base classes establish the infrastructure for the tests. * - * The following settings should be specified for profiling: - * isMeasureOperationTime = true - * isMeasureScriptTime = true - * isLogEnabled = false - * printTestVectors = false - * costTracingEnabled = false - * isTestRun = true - * perTestWarmUpIters = 1 - * nBenchmarkIters = 1 + * @see SigmaDslSpecificationBase */ -class SigmaDslSpecification extends SigmaDslTesting - with CompilerCrossVersionProps - with BeforeAndAfterAll { suite => - - /** Use VersionContext so that each property in this suite runs under correct - * parameters. - */ - protected override def testFun_Run(testName: String, testFun: => Any): Unit = { - VersionContext.withVersions(activatedVersionInTests, ergoTreeVersionInTests) { - super.testFun_Run(testName, testFun) - } - } - - implicit override val generatorDrivenConfig = PropertyCheckConfiguration(minSuccessful = 30) +class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => - val evalSettingsInTests = CErgoTreeEvaluator.DefaultEvalSettings.copy( - isMeasureOperationTime = true, - isMeasureScriptTime = true, - isLogEnabled = false, // don't commit the `true` value (travis log is too high) - printTestVectors = false, // don't commit the `true` value (travis log is too high) - - /** Should always be enabled in tests (and false by default) - * Should be disabled for cost profiling, which case the new costs are not checked. - */ - costTracingEnabled = true, - - profilerOpt = Some(CErgoTreeEvaluator.DefaultProfiler), - isTestRun = true - ) - - def warmupSettings(p: Profiler) = evalSettingsInTests.copy( - isLogEnabled = false, - printTestVectors = false, - profilerOpt = Some(p) - ) - - implicit override def evalSettings: EvalSettings = { - warmupProfiler match { - case Some(p) => warmupSettings(p) - case _ => evalSettingsInTests - } - } - - override val perTestWarmUpIters = 0 - - override val nBenchmarkIters = 0 - - override val okRunTestsWithoutMCLowering: Boolean = true - - implicit def IR = createIR() - - def testCases[A, B](cases: Seq[(A, Expected[B])], f: Feature[A, B]) = { - val table = Table(("x", "y"), cases:_*) - forAll(table) { (x, expectedRes) => - val res = f.checkEquality(x) - val resValue = res.map(_._1) - val (expected, expDetailsOpt) = expectedRes.newResults(ergoTreeVersionInTests) - checkResult(resValue, expected.value, failOnTestVectors = true, - "SigmaDslSpecifiction#testCases: compare expected new result with res = f.checkEquality(x)") - res match { - case Success((value, details)) => - details.cost shouldBe JitCost(expected.verificationCost.get) - expDetailsOpt.foreach(expDetails => - if (details.trace != expDetails.trace) { - printCostDetails(f.script, details) - details.trace shouldBe expDetails.trace - } - ) - } - } - } + override def languageVersion: Byte = VersionContext.JitActivationVersion import TestData._ - override protected def beforeAll(): Unit = { - prepareSamples[BigInt] - prepareSamples[GroupElement] - prepareSamples[AvlTree] - prepareSamples[Box] - prepareSamples[PreHeader] - prepareSamples[Header] - prepareSamples[(BigInt, BigInt)] - prepareSamples[(GroupElement, GroupElement)] - prepareSamples[(AvlTree, AvlTree)] - prepareSamples[(Box, Box)] - prepareSamples[(PreHeader, PreHeader)] - prepareSamples[(Header, Header)] - } - ///===================================================== /// CostDetails shared among test cases ///----------------------------------------------------- @@ -232,17 +125,6 @@ class SigmaDslSpecification extends SigmaDslTesting /// Boolean type operations ///----------------------------------------------------- - property("Boolean methods equivalence") { - val toByte = newFeature((x: Boolean) => x.toByte, "{ (x: Boolean) => x.toByte }") - - val cases = Seq( - (true, Success(1.toByte)), - (false, Success(0.toByte)) - ) - - testCases(cases, toByte) - } - property("BinXor(logical XOR) equivalence") { val binXor = existingFeature((x: (Boolean, Boolean)) => x._1 ^ x._2, "{ (x: (Boolean, Boolean)) => x._1 ^ x._2 }", @@ -1057,31 +939,6 @@ class SigmaDslSpecification extends SigmaDslTesting swapArgs(LE_cases, cost = 1768, newCostDetails = binaryRelationCostDetails(GE, SByte)), ">=", GE.apply)(_ >= _) } - - property("Byte methods equivalence (new features)") { - lazy val toBytes = newFeature((x: Byte) => x.toBytes, "{ (x: Byte) => x.toBytes }") - lazy val toAbs = newFeature((x: Byte) => x.toAbs, "{ (x: Byte) => x.toAbs }") - lazy val compareTo = newFeature( - (x: (Byte, Byte)) => x._1.compareTo(x._2), - "{ (x: (Byte, Byte)) => x._1.compareTo(x._2) }") - - lazy val bitOr = newFeature( - { (x: (Byte, Byte)) => (x._1 | x._2).toByteExact }, - "{ (x: (Byte, Byte)) => (x._1 | x._2).toByteExact }") - - lazy val bitAnd = newFeature( - { (x: (Byte, Byte)) => (x._1 & x._2).toByteExact }, - "{ (x: (Byte, Byte)) => (x._1 & x._2).toByteExact }") - - forAll { x: Byte => - Seq(toBytes, toAbs).foreach(f => f.checkEquality(x)) - } - - forAll { x: (Byte, Byte) => - Seq(compareTo, bitOr, bitAnd).foreach(_.checkEquality(x)) - } - } - property("Short methods equivalence") { SShort.upcast(0.toShort) shouldBe 0.toShort // boundary test case SShort.downcast(0.toShort) shouldBe 0.toShort // boundary test case @@ -1362,29 +1219,6 @@ class SigmaDslSpecification extends SigmaDslTesting ">=", GE.apply)(_ >= _) } - property("Short methods equivalence (new features)") { - lazy val toBytes = newFeature((x: Short) => x.toBytes, "{ (x: Short) => x.toBytes }") - lazy val toAbs = newFeature((x: Short) => x.toAbs, "{ (x: Short) => x.toAbs }") - - lazy val compareTo = newFeature((x: (Short, Short)) => x._1.compareTo(x._2), - "{ (x: (Short, Short)) => x._1.compareTo(x._2) }") - - lazy val bitOr = newFeature( - { (x: (Short, Short)) => (x._1 | x._2).toShortExact }, - "{ (x: (Short, Short)) => x._1 | x._2 }") - - lazy val bitAnd = newFeature( - { (x: (Short, Short)) => (x._1 & x._2).toShortExact }, - "{ (x: (Short, Short)) => x._1 & x._2 }") - - forAll { x: Short => - Seq(toBytes, toAbs).foreach(_.checkEquality(x)) - } - forAll { x: (Short, Short) => - Seq(compareTo, bitOr, bitAnd).foreach(_.checkEquality(x)) - } - } - property("Int methods equivalence") { SInt.upcast(0) shouldBe 0 // boundary test case SInt.downcast(0) shouldBe 0 // boundary test case @@ -1665,28 +1499,6 @@ class SigmaDslSpecification extends SigmaDslTesting ">=", GE.apply)(_ >= _) } - property("Int methods equivalence (new features)") { - lazy val toBytes = newFeature((x: Int) => x.toBytes, "{ (x: Int) => x.toBytes }") - lazy val toAbs = newFeature((x: Int) => x.toAbs, "{ (x: Int) => x.toAbs }") - lazy val compareTo = newFeature((x: (Int, Int)) => x._1.compareTo(x._2), - "{ (x: (Int, Int)) => x._1.compareTo(x._2) }") - - lazy val bitOr = newFeature( - { (x: (Int, Int)) => x._1 | x._2 }, - "{ (x: (Int, Int)) => x._1 | x._2 }") - - lazy val bitAnd = newFeature( - { (x: (Int, Int)) => x._1 & x._2 }, - "{ (x: (Int, Int)) => x._1 & x._2 }") - - forAll { x: Int => - Seq(toBytes, toAbs).foreach(_.checkEquality(x)) - } - forAll { x: (Int, Int) => - Seq(compareTo, bitOr, bitAnd).foreach(_.checkEquality(x)) - } - } - property("Long downcast and upcast identity") { forAll { x: Long => SLong.upcast(x) shouldBe x // boundary test case @@ -1984,28 +1796,6 @@ class SigmaDslSpecification extends SigmaDslTesting ">=", GE.apply)(_ >= _) } - property("Long methods equivalence (new features)") { - lazy val toBytes = newFeature((x: Long) => x.toBytes, "{ (x: Long) => x.toBytes }") - lazy val toAbs = newFeature((x: Long) => x.toAbs, "{ (x: Long) => x.toAbs }") - lazy val compareTo = newFeature((x: (Long, Long)) => x._1.compareTo(x._2), - "{ (x: (Long, Long)) => x._1.compareTo(x._2) }") - - lazy val bitOr = newFeature( - { (x: (Long, Long)) => x._1 | x._2 }, - "{ (x: (Long, Long)) => x._1 | x._2 }") - - lazy val bitAnd = newFeature( - { (x: (Long, Long)) => x._1 & x._2 }, - "{ (x: (Long, Long)) => x._1 & x._2 }") - - forAll { x: Long => - Seq(toBytes, toAbs).foreach(_.checkEquality(x)) - } - forAll { x: (Long, Long) => - Seq(compareTo, bitOr, bitAnd).foreach(_.checkEquality(x)) - } - } - property("BigInt methods equivalence") { verifyCases( { @@ -2264,59 +2054,6 @@ class SigmaDslSpecification extends SigmaDslTesting ">=", GE.apply)(o.gteq(_, _)) } - property("BigInt methods equivalence (new features)") { - // TODO v6.0: the behavior of `upcast` for BigInt is different from all other Numeric types (see https://github.com/ScorexFoundation/sigmastate-interpreter/issues/877) - // The `Upcast(bigInt, SBigInt)` node is never produced by ErgoScript compiler, but is still valid ErgoTree. - // It makes sense to fix this inconsistency as part of upcoming forks - assertExceptionThrown( - SBigInt.upcast(CBigInt(new BigInteger("0", 16)).asInstanceOf[AnyVal]), - _.getMessage.contains("Cannot upcast value") - ) - - // TODO v6.0: the behavior of `downcast` for BigInt is different from all other Numeric types (see https://github.com/ScorexFoundation/sigmastate-interpreter/issues/877) - // The `Downcast(bigInt, SBigInt)` node is never produced by ErgoScript compiler, but is still valid ErgoTree. - // It makes sense to fix this inconsistency as part of HF - assertExceptionThrown( - SBigInt.downcast(CBigInt(new BigInteger("0", 16)).asInstanceOf[AnyVal]), - _.getMessage.contains("Cannot downcast value") - ) - - val toByte = newFeature((x: BigInt) => x.toByte, - "{ (x: BigInt) => x.toByte }", - FuncValue(Vector((1, SBigInt)), Downcast(ValUse(1, SBigInt), SByte))) - - val toShort = newFeature((x: BigInt) => x.toShort, - "{ (x: BigInt) => x.toShort }", - FuncValue(Vector((1, SBigInt)), Downcast(ValUse(1, SBigInt), SShort))) - - val toInt = newFeature((x: BigInt) => x.toInt, - "{ (x: BigInt) => x.toInt }", - FuncValue(Vector((1, SBigInt)), Downcast(ValUse(1, SBigInt), SInt))) - - val toLong = newFeature((x: BigInt) => x.toLong, - "{ (x: BigInt) => x.toLong }", - FuncValue(Vector((1, SBigInt)), Downcast(ValUse(1, SBigInt), SLong))) - - lazy val toBytes = newFeature((x: BigInt) => x.toBytes, "{ (x: BigInt) => x.toBytes }") - lazy val toAbs = newFeature((x: BigInt) => x.toAbs, "{ (x: BigInt) => x.toAbs }") - - lazy val compareTo = newFeature((x: (BigInt, BigInt)) => x._1.compareTo(x._2), - "{ (x: (BigInt, BigInt)) => x._1.compareTo(x._2) }") - - lazy val bitOr = newFeature({ (x: (BigInt, BigInt)) => x._1 | x._2 }, - "{ (x: (BigInt, BigInt)) => x._1 | x._2 }") - - lazy val bitAnd = newFeature({ (x: (BigInt, BigInt)) => x._1 & x._2 }, - "{ (x: (BigInt, BigInt)) => x._1 & x._2 }") - - forAll { x: BigInt => - Seq(toByte, toShort, toInt, toLong, toBytes, toAbs).foreach(_.checkEquality(x)) - } - forAll { x: (BigInt, BigInt) => - Seq(compareTo, bitOr, bitAnd).foreach(_.checkEquality(x)) - } - } - /** Executed a series of test cases of NEQ operation verify using two _different_ * data instances `x` and `y`. * @param cost the expected cost of `verify` (the same for all cases) @@ -4051,16 +3788,6 @@ class SigmaDslSpecification extends SigmaDslTesting ))) } - property("Box properties equivalence (new features)") { - // TODO v6.0: related to https://github.com/ScorexFoundation/sigmastate-interpreter/issues/416 - val getReg = newFeature((x: Box) => x.getReg[Int](1).get, - "{ (x: Box) => x.getReg[Int](1).get }") - - forAll { box: Box => - Seq(getReg).foreach(_.checkEquality(box)) - } - } - property("Conditional access to registers") { def boxWithRegisters(regs: AdditionalRegisters): Box = { SigmaDsl.Box(testBox(20, TrueTree, 0, Seq(), regs)) @@ -7638,36 +7365,6 @@ class SigmaDslSpecification extends SigmaDslTesting preGeneratedSamples = Some(samples)) } - // TODO v6.0 (3h): https://github.com/ScorexFoundation/sigmastate-interpreter/issues/479 - property("Coll find method equivalence") { - val find = newFeature((x: Coll[Int]) => x.find({ (v: Int) => v > 0 }), - "{ (x: Coll[Int]) => x.find({ (v: Int) => v > 0} ) }") - forAll { x: Coll[Int] => - find.checkEquality(x) - } - } - - // TODO v6.0 (3h): https://github.com/ScorexFoundation/sigmastate-interpreter/issues/418 - property("Coll bitwise methods equivalence") { - val shiftRight = newFeature( - { (x: Coll[Boolean]) => - if (x.size > 2) x.slice(0, x.size - 2) else Colls.emptyColl[Boolean] - }, - "{ (x: Coll[Boolean]) => x >> 2 }") - forAll { x: Array[Boolean] => - shiftRight.checkEquality(Colls.fromArray(x)) - } - } - - // TODO v6.0 (3h): https://github.com/ScorexFoundation/sigmastate-interpreter/issues/479 - property("Coll diff methods equivalence") { - val diff = newFeature((x: (Coll[Int], Coll[Int])) => x._1.diff(x._2), - "{ (x: (Coll[Int], Coll[Int])) => x._1.diff(x._2) }") - forAll { (x: Coll[Int], y: Coll[Int]) => - diff.checkEquality((x, y)) - } - } - property("Coll fold method equivalence") { val n = ExactNumeric.IntIsExactNumeric val costDetails1 = TracedCost( @@ -9079,17 +8776,6 @@ class SigmaDslSpecification extends SigmaDslTesting ) )) } - // TODO v6.0: implement Option.fold (see https://github.com/ScorexFoundation/sigmastate-interpreter/issues/479) - property("Option new methods") { - val n = ExactNumeric.LongIsExactNumeric - val fold = newFeature({ (x: Option[Long]) => x.fold(5.toLong)( (v: Long) => n.plus(v, 1) ) }, - "{ (x: Option[Long]) => x.fold(5, { (v: Long) => v + 1 }) }") - - forAll { x: Option[Long] => - Seq(fold).map(_.checkEquality(x)) - } - } - property("Option fold workaround method") { val costDetails1 = TracedCost( traceBase ++ Array( @@ -9525,24 +9211,6 @@ class SigmaDslSpecification extends SigmaDslTesting preGeneratedSamples = Some(Seq())) } - // TODO v6.0 (3h): implement allZK func https://github.com/ScorexFoundation/sigmastate-interpreter/issues/543 - property("allZK equivalence") { - lazy val allZK = newFeature((x: Coll[SigmaProp]) => SigmaDsl.allZK(x), - "{ (x: Coll[SigmaProp]) => allZK(x) }") - forAll { x: Coll[SigmaProp] => - allZK.checkEquality(x) - } - } - - // TODO v6.0 (3h): implement anyZK func https://github.com/ScorexFoundation/sigmastate-interpreter/issues/543 - property("anyZK equivalence") { - lazy val anyZK = newFeature((x: Coll[SigmaProp]) => SigmaDsl.anyZK(x), - "{ (x: Coll[SigmaProp]) => anyZK(x) }") - forAll { x: Coll[SigmaProp] => - anyZK.checkEquality(x) - } - } - property("allOf equivalence") { def costDetails(i: Int) = TracedCost(traceBase :+ ast.SeqCostItem(CompanionDesc(AND), PerItemCost(JitCost(10), JitCost(5), 32), i)) verifyCases( diff --git a/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala b/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala new file mode 100644 index 0000000000..e82bcd886b --- /dev/null +++ b/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala @@ -0,0 +1,348 @@ +package sigma + +import sigma.ast.{Apply, Downcast, FixedCost, FixedCostItem, FuncValue, GetVar, Global, JitCost, MethodCall, NamedDesc, OptionGet, SBigInt, SByte, SGlobalMethods, SInt, SLong, SShort, STypeVar, ValUse} +import sigma.data.{CBigInt, ExactNumeric, RType} +import sigma.eval.{SigmaDsl, TracedCost} +import sigma.util.Extensions.{BooleanOps, ByteOps, IntOps, LongOps} +import sigmastate.exceptions.MethodNotFound + +import java.math.BigInteger +import scala.util.Success + +/** This suite tests all operations for v6.0 version of the language. + * The base classes establish the infrastructure for the tests. + * + * @see SigmaDslSpecificationBase + */ +class LanguageSpecificationV6 extends LanguageSpecificationBase { suite => + override def languageVersion: Byte = VersionContext.V6SoftForkVersion + + implicit override def evalSettings = super.evalSettings.copy(printTestVectors = true) + + + val baseTrace = Array( + FixedCostItem(Apply), + FixedCostItem(FuncValue), + FixedCostItem(GetVar), + FixedCostItem(OptionGet), + FixedCostItem(FuncValue.AddToEnvironmentDesc, FixedCost(JitCost(5))) + ) + + property("Boolean.toByte") { + val toByte = newFeature((x: Boolean) => x.toByte, "{ (x: Boolean) => x.toByte }", + sinceVersion = VersionContext.V6SoftForkVersion + ) + + val cases = Seq( + (true, Success(1.toByte)), + (false, Success(0.toByte)) + ) + + if (toByte.isSupportedIn(VersionContext.current)) { + // TODO v6.0: implement as part of https://github.com/ScorexFoundation/sigmastate-interpreter/pull/932 + assertExceptionThrown( + testCases(cases, toByte), + rootCauseLike[MethodNotFound]("Cannot find method") + ) + } + else + testCases(cases, toByte) + } + + property("Byte methods equivalence (new features)") { + // TODO v6.0: implement as part of https://github.com/ScorexFoundation/sigmastate-interpreter/issues/474 + if (activatedVersionInTests < VersionContext.V6SoftForkVersion) { + // NOTE, for such versions the new features are not supported + // which is checked below + + lazy val toAbs = newFeature((x: Byte) => x.toAbs, "{ (x: Byte) => x.toAbs }", + sinceVersion = VersionContext.V6SoftForkVersion) + + lazy val compareTo = newFeature( + (x: (Byte, Byte)) => x._1.compareTo(x._2), + "{ (x: (Byte, Byte)) => x._1.compareTo(x._2) }", + sinceVersion = VersionContext.V6SoftForkVersion) + + lazy val bitOr = newFeature( + { (x: (Byte, Byte)) => (x._1 | x._2).toByteExact }, + "{ (x: (Byte, Byte)) => (x._1 | x._2) }", + sinceVersion = VersionContext.V6SoftForkVersion) + + lazy val bitAnd = newFeature( + { (x: (Byte, Byte)) => (x._1 & x._2).toByteExact }, + "{ (x: (Byte, Byte)) => (x._1 & x._2) }", + sinceVersion = VersionContext.V6SoftForkVersion) + + forAll { x: Byte => + Seq(toAbs).foreach(f => f.checkEquality(x)) + } + + forAll { x: (Byte, Byte) => + Seq(compareTo, bitOr, bitAnd).foreach(_.checkEquality(x)) + } + } + } + + // TODO v6.0: enable as part of https://github.com/ScorexFoundation/sigmastate-interpreter/issues/474 + property("Short methods equivalence (new features)") { + if (activatedVersionInTests < VersionContext.V6SoftForkVersion) { + // NOTE, for such versions the new features are not supported + // which is checked below + + lazy val toAbs = newFeature((x: Short) => x.toAbs, "{ (x: Short) => x.toAbs }", + sinceVersion = VersionContext.V6SoftForkVersion) + + lazy val compareTo = newFeature((x: (Short, Short)) => x._1.compareTo(x._2), + "{ (x: (Short, Short)) => x._1.compareTo(x._2) }", + sinceVersion = VersionContext.V6SoftForkVersion) + + lazy val bitOr = newFeature( + { (x: (Short, Short)) => (x._1 | x._2).toShortExact }, + "{ (x: (Short, Short)) => x._1 | x._2 }", + sinceVersion = VersionContext.V6SoftForkVersion) + + lazy val bitAnd = newFeature( + { (x: (Short, Short)) => (x._1 & x._2).toShortExact }, + "{ (x: (Short, Short)) => x._1 & x._2 }", + sinceVersion = VersionContext.V6SoftForkVersion) + + forAll { x: Short => + Seq(toAbs).foreach(_.checkEquality(x)) + } + forAll { x: (Short, Short) => + Seq(compareTo, bitOr, bitAnd).foreach(_.checkEquality(x)) + } + } + } + + property("Int methods equivalence (new features)") { + if (activatedVersionInTests < VersionContext.V6SoftForkVersion) { + // NOTE, for such versions the new features are not supported + // which is checked below + lazy val toAbs = newFeature((x: Int) => x.toAbs, "{ (x: Int) => x.toAbs }", + sinceVersion = VersionContext.V6SoftForkVersion) + lazy val compareTo = newFeature((x: (Int, Int)) => x._1.compareTo(x._2), + "{ (x: (Int, Int)) => x._1.compareTo(x._2) }", + sinceVersion = VersionContext.V6SoftForkVersion) + lazy val bitOr = newFeature( + { (x: (Int, Int)) => x._1 | x._2 }, + "{ (x: (Int, Int)) => x._1 | x._2 }", + sinceVersion = VersionContext.V6SoftForkVersion) + lazy val bitAnd = newFeature( + { (x: (Int, Int)) => x._1 & x._2 }, + "{ (x: (Int, Int)) => x._1 & x._2 }", + sinceVersion = VersionContext.V6SoftForkVersion) + forAll { x: Int => + Seq(toAbs).foreach(_.checkEquality(x)) + } + forAll { x: (Int, Int) => + Seq(compareTo, bitOr, bitAnd).foreach(_.checkEquality(x)) + } + } + } + + property("Long methods equivalence (new features)") { + if (activatedVersionInTests < VersionContext.V6SoftForkVersion) { + // NOTE, for such versions the new features are not supported + // which is checked below + lazy val toAbs = newFeature((x: Long) => x.toAbs, "{ (x: Long) => x.toAbs }", + sinceVersion = VersionContext.V6SoftForkVersion) + lazy val compareTo = newFeature((x: (Long, Long)) => x._1.compareTo(x._2), + "{ (x: (Long, Long)) => x._1.compareTo(x._2) }", + sinceVersion = VersionContext.V6SoftForkVersion) + + lazy val bitOr = newFeature( + { (x: (Long, Long)) => x._1 | x._2 }, + "{ (x: (Long, Long)) => x._1 | x._2 }", + sinceVersion = VersionContext.V6SoftForkVersion) + + lazy val bitAnd = newFeature( + { (x: (Long, Long)) => x._1 & x._2 }, + "{ (x: (Long, Long)) => x._1 & x._2 }", + sinceVersion = VersionContext.V6SoftForkVersion) + + forAll { x: Long => + Seq(toAbs).foreach(_.checkEquality(x)) + } + forAll { x: (Long, Long) => + Seq(compareTo, bitOr, bitAnd).foreach(_.checkEquality(x)) + } + } + + } + + property("BigInt methods equivalence (new features)") { + // TODO v6.0: the behavior of `upcast` for BigInt is different from all other Numeric types (see https://github.com/ScorexFoundation/sigmastate-interpreter/issues/877) + // The `Upcast(bigInt, SBigInt)` node is never produced by ErgoScript compiler, but is still valid ErgoTree. + // It makes sense to fix this inconsistency as part of upcoming forks + assertExceptionThrown( + SBigInt.upcast(CBigInt(new BigInteger("0", 16)).asInstanceOf[AnyVal]), + _.getMessage.contains("Cannot upcast value") + ) + + // TODO v6.0: the behavior of `downcast` for BigInt is different from all other Numeric types (see https://github.com/ScorexFoundation/sigmastate-interpreter/issues/877) + // The `Downcast(bigInt, SBigInt)` node is never produced by ErgoScript compiler, but is still valid ErgoTree. + // It makes sense to fix this inconsistency as part of HF + assertExceptionThrown( + SBigInt.downcast(CBigInt(new BigInteger("0", 16)).asInstanceOf[AnyVal]), + _.getMessage.contains("Cannot downcast value") + ) + + if (activatedVersionInTests < VersionContext.V6SoftForkVersion) { + // NOTE, for such versions the new features are not supported + // which is checked below + val toByte = newFeature((x: BigInt) => x.toByte, + "{ (x: BigInt) => x.toByte }", + FuncValue(Vector((1, SBigInt)), Downcast(ValUse(1, SBigInt), SByte)), + sinceVersion = VersionContext.V6SoftForkVersion) + val toShort = newFeature((x: BigInt) => x.toShort, + "{ (x: BigInt) => x.toShort }", + FuncValue(Vector((1, SBigInt)), Downcast(ValUse(1, SBigInt), SShort)), + sinceVersion = VersionContext.V6SoftForkVersion) + val toInt = newFeature((x: BigInt) => x.toInt, + "{ (x: BigInt) => x.toInt }", + FuncValue(Vector((1, SBigInt)), Downcast(ValUse(1, SBigInt), SInt)), + sinceVersion = VersionContext.V6SoftForkVersion) + val toLong = newFeature((x: BigInt) => x.toLong, + "{ (x: BigInt) => x.toLong }", + FuncValue(Vector((1, SBigInt)), Downcast(ValUse(1, SBigInt), SLong)), + sinceVersion = VersionContext.V6SoftForkVersion) + lazy val toAbs = newFeature((x: BigInt) => x.toAbs, "{ (x: BigInt) => x.toAbs }", + sinceVersion = VersionContext.V6SoftForkVersion) + lazy val compareTo = newFeature((x: (BigInt, BigInt)) => x._1.compareTo(x._2), + "{ (x: (BigInt, BigInt)) => x._1.compareTo(x._2) }", + sinceVersion = VersionContext.V6SoftForkVersion) + lazy val bitOr = newFeature({ (x: (BigInt, BigInt)) => x._1 | x._2 }, + "{ (x: (BigInt, BigInt)) => x._1 | x._2 }", + sinceVersion = VersionContext.V6SoftForkVersion) + lazy val bitAnd = newFeature({ (x: (BigInt, BigInt)) => x._1 & x._2 }, + "{ (x: (BigInt, BigInt)) => x._1 & x._2 }", + sinceVersion = VersionContext.V6SoftForkVersion) + + forAll { x: BigInt => + Seq(toByte, toShort, toInt, toLong, toAbs).foreach(_.checkEquality(x)) + } + forAll { x: (BigInt, BigInt) => + Seq(compareTo, bitOr, bitAnd).foreach(_.checkEquality(x)) + } + } + } + + property("Box properties equivalence (new features)") { + // TODO v6.0: related to https://github.com/ScorexFoundation/sigmastate-interpreter/issues/416 + val getReg = newFeature((x: Box) => x.getReg[Int](1).get, + "{ (x: Box) => x.getReg[Int](1).get }", + sinceVersion = VersionContext.V6SoftForkVersion) + + if (activatedVersionInTests < VersionContext.V6SoftForkVersion) { + // NOTE, for such versions getReg is not supported + // which is checked below + + forAll { box: Box => + Seq(getReg).foreach(_.checkEquality(box)) + } + } + } + + // TODO v6.0 (3h): https://github.com/ScorexFoundation/sigmastate-interpreter/issues/479 + property("Coll find method equivalence") { + val find = newFeature((x: Coll[Int]) => x.find({ (v: Int) => v > 0 }), + "{ (x: Coll[Int]) => x.find({ (v: Int) => v > 0} ) }", + sinceVersion = VersionContext.V6SoftForkVersion) + + if (activatedVersionInTests < VersionContext.V6SoftForkVersion) { + // NOTE, for such versions getReg is not supported + // which is checked below + + forAll { x: Coll[Int] => + find.checkEquality(x) + } + } + } + + // TODO v6.0 (3h): https://github.com/ScorexFoundation/sigmastate-interpreter/issues/418 + property("Coll bitwise methods equivalence") { + val shiftRight = newFeature( + { (x: Coll[Boolean]) => + if (x.size > 2) x.slice(0, x.size - 2) else Colls.emptyColl[Boolean] + }, + "{ (x: Coll[Boolean]) => x >> 2 }", + sinceVersion = VersionContext.V6SoftForkVersion) + + if (activatedVersionInTests < VersionContext.V6SoftForkVersion) { + // NOTE, for such versions getReg is not supported + // which is checked below + + forAll { x: Array[Boolean] => + shiftRight.checkEquality(Colls.fromArray(x)) + } + } + } + + // TODO v6.0 (3h): https://github.com/ScorexFoundation/sigmastate-interpreter/issues/479 + property("Coll diff methods equivalence") { + val diff = newFeature((x: (Coll[Int], Coll[Int])) => x._1.diff(x._2), + "{ (x: (Coll[Int], Coll[Int])) => x._1.diff(x._2) }", + sinceVersion = VersionContext.V6SoftForkVersion) + + if (activatedVersionInTests < VersionContext.V6SoftForkVersion) { + // NOTE, for such versions getReg is not supported + // which is checked below + + forAll { (x: Coll[Int], y: Coll[Int]) => + diff.checkEquality((x, y)) + } + } + } + + // TODO v6.0: implement Option.fold (see https://github.com/ScorexFoundation/sigmastate-interpreter/issues/479) + property("Option new methods") { + val n = ExactNumeric.LongIsExactNumeric + val fold = newFeature({ (x: Option[Long]) => x.fold(5.toLong)( (v: Long) => n.plus(v, 1) ) }, + "{ (x: Option[Long]) => x.fold(5, { (v: Long) => v + 1 }) }", + sinceVersion = VersionContext.V6SoftForkVersion) + + if (activatedVersionInTests < VersionContext.V6SoftForkVersion) { + // NOTE, for such versions getReg is not supported + // which is checked below + + forAll { x: Option[Long] => + Seq(fold).map(_.checkEquality(x)) + } + } + } + + // TODO v6.0 (3h): implement allZK func https://github.com/ScorexFoundation/sigmastate-interpreter/issues/543 + property("allZK equivalence") { + lazy val allZK = newFeature((x: Coll[SigmaProp]) => SigmaDsl.allZK(x), + "{ (x: Coll[SigmaProp]) => allZK(x) }", + sinceVersion = VersionContext.V6SoftForkVersion) + + if (activatedVersionInTests < VersionContext.V6SoftForkVersion) { + // NOTE, for such versions getReg is not supported + // which is checked below + + forAll { x: Coll[SigmaProp] => + allZK.checkEquality(x) + } + } + } + + // TODO v6.0 (3h): implement anyZK func https://github.com/ScorexFoundation/sigmastate-interpreter/issues/543 + property("anyZK equivalence") { + lazy val anyZK = newFeature((x: Coll[SigmaProp]) => SigmaDsl.anyZK(x), + "{ (x: Coll[SigmaProp]) => anyZK(x) }", + sinceVersion = VersionContext.V6SoftForkVersion) + + if (activatedVersionInTests < VersionContext.V6SoftForkVersion) { + // NOTE, for such versions getReg is not supported + // which is checked below + + forAll { x: Coll[SigmaProp] => + anyZK.checkEquality(x) + } + } + } + + +} diff --git a/sc/shared/src/test/scala/sigma/SigmaDslTesting.scala b/sc/shared/src/test/scala/sigma/SigmaDslTesting.scala index 31e873699b..37fb0e6503 100644 --- a/sc/shared/src/test/scala/sigma/SigmaDslTesting.scala +++ b/sc/shared/src/test/scala/sigma/SigmaDslTesting.scala @@ -123,6 +123,9 @@ class SigmaDslTesting extends AnyPropSpec /** Type descriptor for type B. */ def tB: RType[B] + /** Checks if this feature is supported in the given version context. */ + def isSupportedIn(vc: VersionContext): Boolean + /** Script containing this feature. */ def script: String @@ -176,14 +179,42 @@ class SigmaDslTesting extends AnyPropSpec true } + /** Checks the result of feature execution against expected result. + * If settings.failOnTestVectors == true, then print out actual cost results + * + * @param res the result of feature execution + * @param expected the expected result + */ + protected def checkResultAgainstExpected(res: Try[(B, CostDetails)], expected: Expected[B]): Unit = { + val newRes = expected.newResults(ergoTreeVersionInTests) + val expectedTrace = newRes._2.fold(Seq.empty[CostItem])(_.trace) + if (expectedTrace.isEmpty) { + // new cost expectation is missing, print out actual cost results + if (evalSettings.printTestVectors) { + res.foreach { case (_, newDetails) => + printCostDetails(script, newDetails) + } + } + } + else { + // new cost expectation is specified, compare it with the actual result + res.foreach { case (_, newDetails) => + if (newDetails.trace != expectedTrace) { + printCostDetails(script, newDetails) + newDetails.trace shouldBe expectedTrace + } + } + } + } + /** v3 and v4 implementation*/ - private var _oldF: CompiledFunc[A, B] = _ + private var _oldF: Try[CompiledFunc[A, B]] = _ def oldF: CompiledFunc[A, B] = { if (_oldF == null) { - _oldF = oldImpl() - checkExpectedExprIn(_oldF) + _oldF = Try(oldImpl()) + _oldF.foreach(cf => checkExpectedExprIn(cf)) } - _oldF + _oldF.getOrThrow } /** v5 implementation*/ @@ -252,13 +283,21 @@ class SigmaDslTesting extends AnyPropSpec fail( s"""Should succeed with the same value or fail with the same exception, but was: - |First result: $b1 - |Second result: $b2 + |First result: ${errorWithStack(b1)} + |Second result: ${errorWithStack(b2)} |Root cause: $cause |""".stripMargin) } } + private def errorWithStack[A](e: Try[A]): String = e match { + case Failure(t) => + val sw = new java.io.StringWriter + t.printStackTrace(new java.io.PrintWriter(sw)) + sw.toString + case _ => e.toString + } + /** Creates a new ErgoLikeContext using given [[CContext]] as template. * Copies most of the data from ctx and the missing data is taken from the args. * This is a helper method to be used in tests only. @@ -501,6 +540,8 @@ class SigmaDslTesting extends AnyPropSpec implicit val cs = compilerSettingsInTests + override def isSupportedIn(vc: VersionContext): Boolean = true + /** in v5.x the old and the new interpreters are the same */ override val oldImpl = () => funcJit[A, B](script) override val newImpl = () => funcJit[A, B](script) @@ -611,28 +652,10 @@ class SigmaDslTesting extends AnyPropSpec checkResult(funcRes.map(_._1), expected.value, failOnTestVectors, "ExistingFeature#verifyCase: ") - val newRes = expected.newResults(ergoTreeVersionInTests) - val expectedTrace = newRes._2.fold(Seq.empty[CostItem])(_.trace) - if (expectedTrace.isEmpty) { - // new cost expectation is missing, print out actual cost results - if (evalSettings.printTestVectors) { - funcRes.foreach { case (_, newDetails) => - printCostDetails(script, newDetails) - } - } - } - else { - // new cost expectation is specified, compare it with the actual result - funcRes.foreach { case (_, newDetails) => - if (newDetails.trace != expectedTrace) { - printCostDetails(script, newDetails) - newDetails.trace shouldBe expectedTrace - } - } - } - + checkResultAgainstExpected(funcRes, expected) checkVerify(input, expected) } + } /** Descriptor of a language feature which is changed in v5.0. @@ -671,6 +694,8 @@ class SigmaDslTesting extends AnyPropSpec implicit val cs = compilerSettingsInTests + override def isSupportedIn(vc: VersionContext): Boolean = true + /** Apply given function to the context variable 1 */ private def getApplyExpr(funcValue: SValue) = { val sType = Evaluation.rtypeToSType(RType[A]) @@ -833,8 +858,17 @@ class SigmaDslTesting extends AnyPropSpec * This in not yet implemented and will be finished in v6.0. * In v5.0 is only checks that some features are NOT implemented, i.e. work for * negative tests. + * + * @param sinceVersion language version (protocol) when the feature is introduced, see + * [[VersionContext]] + * @param script the script to be tested against semantic function + * @param scalaFuncNew semantic function which defines expected behavior of the given script + * @param expectedExpr expected ErgoTree expression which corresponds to the given script + * @param printExpectedExpr if true, print the test vector for expectedExpr when it is None + * @param logScript if true, log scripts to console */ case class NewFeature[A, B]( + sinceVersion: Byte, script: String, override val scalaFuncNew: A => B, expectedExpr: Option[SValue], @@ -842,25 +876,30 @@ class SigmaDslTesting extends AnyPropSpec logScript: Boolean = LogScriptDefault )(implicit IR: IRContext, override val evalSettings: EvalSettings, val tA: RType[A], val tB: RType[B]) extends Feature[A, B] { + + override def isSupportedIn(vc: VersionContext): Boolean = + vc.activatedVersion >= sinceVersion + override def scalaFunc: A => B = { x => sys.error(s"Semantic Scala function is not defined for old implementation: $this") } implicit val cs = compilerSettingsInTests - /** in v5.x the old and the new interpreters are the same */ + /** Starting from v5.x the old and the new interpreters are the same */ val oldImpl = () => funcJit[A, B](script) - val newImpl = oldImpl // funcJit[A, B](script) // TODO v6.0: use actual new implementation here (https://github.com/ScorexFoundation/sigmastate-interpreter/issues/910) + val newImpl = oldImpl - /** In v5.x this method just checks the old implementations fails on the new feature. */ + /** Check the new implementation works equal to the semantic function. + * This method also checks the old implementations fails on the new feature. + */ override def checkEquality(input: A, logInputOutput: Boolean = false): Try[(B, CostDetails)] = { - val oldRes = Try(oldF(input)) - oldRes.isFailure shouldBe true - if (!(newImpl eq oldImpl)) { - val newRes = VersionContext.withVersions(activatedVersionInTests, ergoTreeVersionInTests) { - checkEq(scalaFuncNew)(newF)(input) - } + if (this.isSupportedIn(VersionContext.current)) { + checkEq(scalaFuncNew)(newF)(input) + } else { + val oldRes = Try(oldF(input)) + oldRes.isFailure shouldBe true + oldRes } - oldRes } override def checkExpected(input: A, expected: Expected[B]): Unit = { @@ -880,7 +919,10 @@ class SigmaDslTesting extends AnyPropSpec printTestCases: Boolean, failOnTestVectors: Boolean): Unit = { val res = checkEquality(input, printTestCases).map(_._1) - res.isFailure shouldBe true + if (this.isSupportedIn(VersionContext.current)) { + res shouldBe expectedResult + } else + res.isFailure shouldBe true Try(scalaFuncNew(input)) shouldBe expectedResult } @@ -889,8 +931,11 @@ class SigmaDslTesting extends AnyPropSpec printTestCases: Boolean, failOnTestVectors: Boolean): Unit = { val funcRes = checkEquality(input, printTestCases) - funcRes.isFailure shouldBe true - Try(scalaFunc(input)) shouldBe expected.value + if (this.isSupportedIn(VersionContext.current)) { + checkResultAgainstExpected(funcRes, expected) + } else + funcRes.isFailure shouldBe true + Try(scalaFuncNew(input)) shouldBe expected.value } } @@ -958,6 +1003,20 @@ class SigmaDslTesting extends AnyPropSpec } } + /** Used when the old and new value are the same for all versions + * and the expected costs are not specified. + * + * @param value expected result of tested function + * @param expectedDetails expected cost details for all versions + */ + def apply[A](value: Try[A], expectedDetails: CostDetails): Expected[A] = + new Expected(ExpectedResult(value, None)) { + override val newResults = defaultNewResults.map { + case (ExpectedResult(v, _), _) => + (ExpectedResult(v, None), Some(expectedDetails)) + } + } + /** Used when the old and new value and costs are the same for all versions. * * @param value expected result of tested function @@ -1045,6 +1104,7 @@ class SigmaDslTesting extends AnyPropSpec /** Describes a NEW language feature which must NOT be supported in v4 and * must BE supported in v5 of the language. * + * @param sinceVersion language version (protocol) when the feature is introduced, see [[VersionContext]] * @param scalaFunc semantic function which defines expected behavior of the given script * @param script the script to be tested against semantic function * @param expectedExpr expected ErgoTree expression which corresponds to the given script @@ -1052,9 +1112,9 @@ class SigmaDslTesting extends AnyPropSpec * various ways */ def newFeature[A: RType, B: RType] - (scalaFunc: A => B, script: String, expectedExpr: SValue = null) + (scalaFunc: A => B, script: String, expectedExpr: SValue = null, sinceVersion: Byte = VersionContext.JitActivationVersion) (implicit IR: IRContext, es: EvalSettings): Feature[A, B] = { - NewFeature(script, scalaFunc, Option(expectedExpr)) + NewFeature(sinceVersion, script, scalaFunc, Option(expectedExpr)) } val contextGen: Gen[Context] = ergoLikeContextGen.map(c => c.toSigmaContext()) diff --git a/sc/shared/src/test/scala/sigmastate/CompilerCrossVersionProps.scala b/sc/shared/src/test/scala/sigmastate/CompilerCrossVersionProps.scala index 89d15dd4df..4062f13686 100644 --- a/sc/shared/src/test/scala/sigmastate/CompilerCrossVersionProps.scala +++ b/sc/shared/src/test/scala/sigmastate/CompilerCrossVersionProps.scala @@ -12,12 +12,11 @@ trait CompilerCrossVersionProps extends CrossVersionProps with CompilerTestsBase (implicit pos: Position): Unit = { super.property(testName, testTags:_*)(testFun) - val testName2 = s"${testName}_MCLowering" - super.property2(testName2, testTags:_*) { - if (okRunTestsWithoutMCLowering) { - _lowerMethodCalls.withValue(false) { - testFun_Run(testName2, testFun) - } + if (okRunTestsWithoutMCLowering) { + val testName2 = s"${testName}_MCLowering" + _lowerMethodCalls.withValue(false) { + // run testFun for all versions again, but now with this flag + super.property(testName2, testTags:_*)(testFun) } } } diff --git a/sc/shared/src/test/scala/sigmastate/lang/SigmaBinderTest.scala b/sc/shared/src/test/scala/sigmastate/lang/SigmaBinderTest.scala index b4b4ad20cd..aa552e9b69 100644 --- a/sc/shared/src/test/scala/sigmastate/lang/SigmaBinderTest.scala +++ b/sc/shared/src/test/scala/sigmastate/lang/SigmaBinderTest.scala @@ -10,10 +10,12 @@ import sigma.ast.syntax.SValue import sigmastate._ import sigmastate.interpreter.Interpreter.ScriptEnv import SigmaPredef.PredefinedFuncRegistry +import sigma.VersionContext import sigma.ast.syntax._ import sigma.compiler.phases.SigmaBinder import sigma.eval.SigmaDsl import sigma.exceptions.BinderException +import sigmastate.helpers.SigmaPPrint class SigmaBinderTest extends AnyPropSpec with ScalaCheckPropertyChecks with Matchers with LangTests { import StdSigmaBuilder._ @@ -29,6 +31,17 @@ class SigmaBinderTest extends AnyPropSpec with ScalaCheckPropertyChecks with Mat res } + /** Checks that parsing and binding results in the expected value. + * @return the inferred type of the expression + */ + def checkBound(env: ScriptEnv, x: String, expected: SValue) = { + val bound = bind(env, x) + if (expected != bound) { + SigmaPPrint.pprintln(bound, width = 100) + } + bound shouldBe expected + } + private def fail(env: ScriptEnv, x: String, expectedLine: Int, expectedCol: Int): Unit = { val builder = TransformingSigmaBuilder val ast = SigmaParser(x).get.value diff --git a/sc/shared/src/test/scala/sigmastate/lang/SigmaTyperTest.scala b/sc/shared/src/test/scala/sigmastate/lang/SigmaTyperTest.scala index 6b93b098ea..3b2e130100 100644 --- a/sc/shared/src/test/scala/sigmastate/lang/SigmaTyperTest.scala +++ b/sc/shared/src/test/scala/sigmastate/lang/SigmaTyperTest.scala @@ -21,6 +21,7 @@ import sigma.serialization.generators.ObjectGenerators import sigma.ast.Select import sigma.compiler.phases.{SigmaBinder, SigmaTyper} import sigma.exceptions.TyperException +import sigmastate.helpers.SigmaPPrint class SigmaTyperTest extends AnyPropSpec with ScalaCheckPropertyChecks with Matchers with LangTests with ObjectGenerators { @@ -28,6 +29,7 @@ class SigmaTyperTest extends AnyPropSpec private val predefFuncRegistry = new PredefinedFuncRegistry(StdSigmaBuilder) import predefFuncRegistry._ + /** Checks that parsing, binding and typing of `x` results in the given expected value. */ def typecheck(env: ScriptEnv, x: String, expected: SValue = null): SType = { try { val builder = TransformingSigmaBuilder @@ -39,7 +41,12 @@ class SigmaTyperTest extends AnyPropSpec val typer = new SigmaTyper(builder, predefinedFuncRegistry, typeEnv, lowerMethodCalls = true) val typed = typer.typecheck(bound) assertSrcCtxForAllNodes(typed) - if (expected != null) typed shouldBe expected + if (expected != null) { + if (expected != typed) { + SigmaPPrint.pprintln(typed, width = 100) + } + typed shouldBe expected + } typed.tpe } catch { case e: Exception => throw e From 91a9729b36b40a68d07ac58948829aea87bb6493 Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Fri, 7 Jun 2024 13:10:16 +0300 Subject: [PATCH 14/19] removing serialize from tests --- .../src/main/scala/sigma/SigmaDsl.scala | 3 -- .../sigma/reflection/ReflectionData.scala | 4 --- .../sigmastate/lang/SigmaBinderTest.scala | 11 ------- .../sigmastate/lang/SigmaTyperTest.scala | 31 ------------------- 4 files changed, 49 deletions(-) diff --git a/core/shared/src/main/scala/sigma/SigmaDsl.scala b/core/shared/src/main/scala/sigma/SigmaDsl.scala index 6e306f7a0b..df2b419273 100644 --- a/core/shared/src/main/scala/sigma/SigmaDsl.scala +++ b/core/shared/src/main/scala/sigma/SigmaDsl.scala @@ -727,9 +727,6 @@ trait SigmaDslBuilder { /** Construct a new authenticated dictionary with given parameters and tree root digest. */ def avlTree(operationFlags: Byte, digest: Coll[Byte], keyLength: Int, valueLengthOpt: Option[Int]): AvlTree - /** Serializes the given `value` into bytes using the default serialization format. */ - def serialize[T](value: T)(implicit cT: RType[T]): Coll[Byte] - /** Returns a byte-wise XOR of the two collections of bytes. */ def xor(l: Coll[Byte], r: Coll[Byte]): Coll[Byte] } diff --git a/core/shared/src/main/scala/sigma/reflection/ReflectionData.scala b/core/shared/src/main/scala/sigma/reflection/ReflectionData.scala index 5cd678b712..028e68bf72 100644 --- a/core/shared/src/main/scala/sigma/reflection/ReflectionData.scala +++ b/core/shared/src/main/scala/sigma/reflection/ReflectionData.scala @@ -441,10 +441,6 @@ object ReflectionData { mkMethod(clazz, "sha256", Array[Class[_]](cColl)) { (obj, args) => obj.asInstanceOf[SigmaDslBuilder].sha256(args(0).asInstanceOf[Coll[Byte]]) }, - mkMethod(clazz, "serialize", Array[Class[_]](classOf[Object], classOf[RType[_]])) { (obj, args) => - obj.asInstanceOf[SigmaDslBuilder].serialize[Any]( - args(0).asInstanceOf[Any])(args(1).asInstanceOf[RType[Any]]) - }, mkMethod(clazz, "decodePoint", Array[Class[_]](cColl)) { (obj, args) => obj.asInstanceOf[SigmaDslBuilder].decodePoint(args(0).asInstanceOf[Coll[Byte]]) } diff --git a/sc/shared/src/test/scala/sigmastate/lang/SigmaBinderTest.scala b/sc/shared/src/test/scala/sigmastate/lang/SigmaBinderTest.scala index 54bd89c9c2..1f15f5d747 100644 --- a/sc/shared/src/test/scala/sigmastate/lang/SigmaBinderTest.scala +++ b/sc/shared/src/test/scala/sigmastate/lang/SigmaBinderTest.scala @@ -213,15 +213,4 @@ class SigmaBinderTest extends AnyPropSpec with ScalaCheckPropertyChecks with Mat e.source shouldBe Some(SourceContext(2, 5, "val x = 10")) } - property("predefined `serialize` should be transformed to MethodCall") { - runWithVersion(VersionContext.V6SoftForkVersion) { - checkBound(env, "serialize(1)", - MethodCall.typed[Value[SCollection[SByte.type]]]( - Global, - SGlobalMethods.getMethodByName("serialize").withConcreteTypes(Map(STypeVar("T") -> SInt)), - Array(IntConstant(1)), - Map() - )) - } - } } diff --git a/sc/shared/src/test/scala/sigmastate/lang/SigmaTyperTest.scala b/sc/shared/src/test/scala/sigmastate/lang/SigmaTyperTest.scala index 2c3bd44d39..52dab65991 100644 --- a/sc/shared/src/test/scala/sigmastate/lang/SigmaTyperTest.scala +++ b/sc/shared/src/test/scala/sigmastate/lang/SigmaTyperTest.scala @@ -671,35 +671,4 @@ class SigmaTyperTest extends AnyPropSpec typecheck(customEnv, "substConstants(scriptBytes, positions, newVals)") shouldBe SByteArray } - property("Global.serialize") { - runWithVersion(VersionContext.V6SoftForkVersion) { - typecheck(env, "Global.serialize(1)", - MethodCall.typed[Value[SCollection[SByte.type]]]( - Global, - SGlobalMethods.getMethodByName("serialize").withConcreteTypes(Map(STypeVar("T") -> SInt)), - Array(IntConstant(1)), - Map() - )) shouldBe SByteArray - } - - runWithVersion((VersionContext.V6SoftForkVersion - 1).toByte) { - assertExceptionThrown( - typecheck(env, "Global.serialize(1)"), - exceptionLike[MethodNotFound]("Cannot find method 'serialize' in in the object Global") - ) - } - } - - property("predefined serialize") { - runWithVersion(VersionContext.V6SoftForkVersion) { - typecheck(env, "serialize((1, 2L))", - expected = MethodCall.typed[Value[SCollection[SByte.type]]]( - Global, - SGlobalMethods.getMethodByName("serialize").withConcreteTypes(Map(STypeVar("T") -> SPair(SInt, SLong))), - Array(Tuple(Vector(IntConstant(1), LongConstant(2L)))), - Map() - )) shouldBe SByteArray - } - } - } From e7a1aaf13a60a640c47713a4fc39efce1b5c670a Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Tue, 11 Jun 2024 13:06:33 +0300 Subject: [PATCH 15/19] removing more serialize artefacts and HeaderTypeOps --- data/shared/src/main/scala/sigma/ast/ErgoTree.scala | 11 ----------- .../shared/src/main/scala/sigma/ast/SigmaPredef.scala | 1 - .../src/main/scala/sigma/data/CSigmaDslBuilder.scala | 6 +++--- .../sigma/serialization/MethodCallSerializer.scala | 4 +--- .../test/scala/sigmastate/lang/SigmaParserTest.scala | 3 +++ .../ir/wrappers/sigma/impl/SigmaDslImpl.scala | 7 ------- .../main/scala/sigma/compiler/phases/SigmaTyper.scala | 1 - .../test/scala/sigma/LanguageSpecificationV6.scala | 11 +++++------ .../test/scala/sigmastate/lang/SigmaTyperTest.scala | 3 +-- 9 files changed, 13 insertions(+), 34 deletions(-) diff --git a/data/shared/src/main/scala/sigma/ast/ErgoTree.scala b/data/shared/src/main/scala/sigma/ast/ErgoTree.scala index 3bb69b96dc..68d69abd91 100644 --- a/data/shared/src/main/scala/sigma/ast/ErgoTree.scala +++ b/data/shared/src/main/scala/sigma/ast/ErgoTree.scala @@ -228,17 +228,6 @@ object ErgoTree { type HeaderType = HeaderType.Type - /** Convenience methods for working with ErgoTree headers. */ - implicit class HeaderTypeOps(val header: HeaderType) extends AnyVal { - /** Update the version bits of the given header byte with the given version value, - * leaving all other bits unchanged. - */ - def withVersion(version: Byte): HeaderType = ErgoTree.headerWithVersion(header, version) - - /** Sets the constant segregation bit in the given header. */ - def withConstantSegregation: HeaderType = ErgoTree.setConstantSegregation(header) - } - /** Current version of ErgoTree serialization format (aka bite-code language version) */ val VersionFlag: Byte = VersionContext.MaxSupportedScriptVersion diff --git a/data/shared/src/main/scala/sigma/ast/SigmaPredef.scala b/data/shared/src/main/scala/sigma/ast/SigmaPredef.scala index ebe8aa0213..068d955541 100644 --- a/data/shared/src/main/scala/sigma/ast/SigmaPredef.scala +++ b/data/shared/src/main/scala/sigma/ast/SigmaPredef.scala @@ -5,7 +5,6 @@ import org.ergoplatform.{ErgoAddressEncoder, P2PKAddress} import scorex.util.encode.{Base16, Base58, Base64} import sigma.ast.SCollection.{SByteArray, SIntArray} import sigma.ast.SOption.SIntOption -import sigma.ast.SigmaPropConstant import sigma.ast.syntax._ import sigma.data.Nullable import sigma.exceptions.InvalidArguments diff --git a/data/shared/src/main/scala/sigma/data/CSigmaDslBuilder.scala b/data/shared/src/main/scala/sigma/data/CSigmaDslBuilder.scala index d7b092fc0e..3938feacd3 100644 --- a/data/shared/src/main/scala/sigma/data/CSigmaDslBuilder.scala +++ b/data/shared/src/main/scala/sigma/data/CSigmaDslBuilder.scala @@ -5,13 +5,13 @@ import org.ergoplatform.ErgoBox import org.ergoplatform.validation.ValidationRules import scorex.crypto.hash.{Blake2b256, Sha256} import scorex.utils.Longs -import sigma.ast.{AtLeast, SType, SubstConstants} +import sigma.ast.{AtLeast, SubstConstants} import sigma.crypto.{CryptoConstants, EcPointType, Ecp} import sigma.eval.Extensions.EvalCollOps -import sigma.serialization.{DataSerializer, GroupElementSerializer, SigmaSerializer} +import sigma.serialization.{GroupElementSerializer, SigmaSerializer} import sigma.util.Extensions.BigIntegerOps import sigma.validation.SigmaValidationSettings -import sigma.{AvlTree, BigInt, Box, Coll, CollBuilder, Evaluation, GroupElement, SigmaDslBuilder, SigmaProp, VersionContext} +import sigma.{AvlTree, BigInt, Box, Coll, CollBuilder, GroupElement, SigmaDslBuilder, SigmaProp, VersionContext} import java.math.BigInteger diff --git a/data/shared/src/main/scala/sigma/serialization/MethodCallSerializer.scala b/data/shared/src/main/scala/sigma/serialization/MethodCallSerializer.scala index 8a3a226fd8..319a4284e2 100644 --- a/data/shared/src/main/scala/sigma/serialization/MethodCallSerializer.scala +++ b/data/shared/src/main/scala/sigma/serialization/MethodCallSerializer.scala @@ -1,15 +1,13 @@ package sigma.serialization import sigma.ast.syntax._ -import sigma.ast.{MethodCall, SContextMethods, SMethod, SType, STypeSubst, STypeVar, Value, ValueCompanion} +import sigma.ast.{MethodCall, SContextMethods, SMethod, SType, STypeSubst, Value, ValueCompanion} import sigma.util.safeNewArray import SigmaByteWriter._ import debox.cfor import sigma.ast.SContextMethods.BlockchainContextMethodNames import sigma.serialization.CoreByteWriter.{ArgInfo, DataInfo} -import scala.collection.compat.immutable.ArraySeq - case class MethodCallSerializer(cons: (Value[SType], SMethod, IndexedSeq[Value[SType]], STypeSubst) => Value[SType]) extends ValueSerializer[MethodCall] { override def opDesc: ValueCompanion = MethodCall diff --git a/parsers/shared/src/test/scala/sigmastate/lang/SigmaParserTest.scala b/parsers/shared/src/test/scala/sigmastate/lang/SigmaParserTest.scala index 9c79fbd31b..dc63330f95 100644 --- a/parsers/shared/src/test/scala/sigmastate/lang/SigmaParserTest.scala +++ b/parsers/shared/src/test/scala/sigmastate/lang/SigmaParserTest.scala @@ -35,6 +35,9 @@ class SigmaParserTest extends AnyPropSpec with ScalaCheckPropertyChecks with Mat } } + /** Checks parsing result, printing the actual value as a test vector if expected value + * is not equal to actual. + */ def checkParsed(x: String, expected: SValue) = { val parsed = parse(x) if (expected != parsed) { 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 f5500ae979..c113cb7de3 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 @@ -2104,13 +2104,6 @@ object SigmaDslBuilder extends EntityObject("SigmaDslBuilder") { Array[AnyRef](l, r), true, true, element[Coll[Byte]])) } - - def serialize[T](value: Ref[T]): Ref[Coll[Byte]] = { - asRep[Coll[Byte]](mkMethodCall(source, - SigmaDslBuilderClass.getMethod("serialize", classOf[Sym]), - Array[AnyRef](value), - true, true, element[Coll[Byte]])) - } } // entityUnref: single unref method for each type family diff --git a/sc/shared/src/main/scala/sigma/compiler/phases/SigmaTyper.scala b/sc/shared/src/main/scala/sigma/compiler/phases/SigmaTyper.scala index 0d1763b6e2..679d98a18f 100644 --- a/sc/shared/src/main/scala/sigma/compiler/phases/SigmaTyper.scala +++ b/sc/shared/src/main/scala/sigma/compiler/phases/SigmaTyper.scala @@ -511,7 +511,6 @@ class SigmaTyper(val builder: SigmaBuilder, case v: SigmaBoolean => v case v: Upcast[_, _] => v case v @ Select(_, _, Some(_)) => v - case v @ MethodCall(_, _, _, _) => v case v => error(s"Don't know how to assignType($v)", v.sourceContext) }).ensuring(v => v.tpe != NoType, diff --git a/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala b/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala index 2b658073d8..e23a795b25 100644 --- a/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala +++ b/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala @@ -1,7 +1,6 @@ package sigma -import org.ergoplatform.sdk.utils.ErgoTreeUtils -import sigma.ast.ErgoTree.ZeroHeader +import sigma.ast.ErgoTree.{HeaderType, ZeroHeader} import sigma.ast.SCollection.SByteArray import sigma.ast.syntax.TrueSigmaProp import sigma.ast.{BoolToSigmaProp, CompanionDesc, ConcreteCollection, Constant, ConstantPlaceholder, Downcast, ErgoTree, FalseLeaf, FixedCostItem, FuncValue, Global, JitCost, MethodCall, PerItemCost, SBigInt, SByte, SCollection, SGlobalMethods, SInt, SLong, SPair, SShort, SSigmaProp, STypeVar, SelectField, SubstConstants, ValUse, Value} @@ -341,15 +340,15 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite => property("Fix substConstants in v6.0 for ErgoTree version > 0") { // tree with one segregated constant and v0 val t1 = ErgoTree( - header = ZeroHeader.withConstantSegregation, + header = ErgoTree.setConstantSegregation(ZeroHeader), constants = Vector(TrueSigmaProp), ConstantPlaceholder(0, SSigmaProp)) // tree with one segregated constant and max supported version val t2 = ErgoTree( - header = ZeroHeader - .withVersion(VersionContext.MaxSupportedScriptVersion) - .withConstantSegregation, + header = ErgoTree.setConstantSegregation( + ErgoTree.headerWithVersion(ZeroHeader, VersionContext.MaxSupportedScriptVersion) + ), Vector(TrueSigmaProp), ConstantPlaceholder(0, SSigmaProp)) diff --git a/sc/shared/src/test/scala/sigmastate/lang/SigmaTyperTest.scala b/sc/shared/src/test/scala/sigmastate/lang/SigmaTyperTest.scala index 52dab65991..c68c37a4dc 100644 --- a/sc/shared/src/test/scala/sigmastate/lang/SigmaTyperTest.scala +++ b/sc/shared/src/test/scala/sigmastate/lang/SigmaTyperTest.scala @@ -21,7 +21,6 @@ import sigma.serialization.generators.ObjectGenerators import sigma.ast.Select import sigma.compiler.phases.{SigmaBinder, SigmaTyper} import sigma.exceptions.TyperException -import sigmastate.exceptions.MethodNotFound import sigmastate.helpers.SigmaPPrint class SigmaTyperTest extends AnyPropSpec @@ -30,6 +29,7 @@ class SigmaTyperTest extends AnyPropSpec private val predefFuncRegistry = new PredefinedFuncRegistry(StdSigmaBuilder) import predefFuncRegistry._ + /** Checks that parsing, binding and typing of `x` results in the given expected value. */ def typecheck(env: ScriptEnv, x: String, expected: SValue = null): SType = { try { val builder = TransformingSigmaBuilder @@ -670,5 +670,4 @@ class SigmaTyperTest extends AnyPropSpec ) typecheck(customEnv, "substConstants(scriptBytes, positions, newVals)") shouldBe SByteArray } - } From 04f6feea44c6c40b9d067828fd0823e01468eb5a Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Mon, 5 Aug 2024 00:01:45 +0300 Subject: [PATCH 16/19] test for substConstants with 5 elems --- .../utxo/BasicOpsSpecification.scala | 45 +++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala index 79701d6e07..b2414d36da 100644 --- a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala @@ -2,6 +2,7 @@ package sigmastate.utxo import org.ergoplatform.ErgoBox.{AdditionalRegisters, R6, R8} import org.ergoplatform._ +import scorex.util.encode.Base16 import sigma.Extensions.ArrayOps import sigma.ast.SCollection.SByteArray import sigma.ast.SType.AnyOps @@ -19,9 +20,11 @@ import sigmastate.interpreter.Interpreter._ import sigma.ast.Apply import sigma.eval.EvalSettings import sigma.exceptions.InvalidType +import sigma.serialization.ErgoTreeSerializer import sigmastate.utils.Helpers._ import java.math.BigInteger +import scala.reflect.internal.pickling.PickleFormat class BasicOpsSpecification extends CompilerTestingCommons with CompilerCrossVersionProps { @@ -721,4 +724,46 @@ class BasicOpsSpecification extends CompilerTestingCommons true ) } + + property("substConstants") { + val initTreeScript = + """ + | { + | val v1 = 1 // 0 + | val v2 = 2 // 2 + | val v3 = 3 // 4 + | val v4 = 4 // 3 + | val v5 = 5 // 1 + | sigmaProp(v1 == -v5 && v2 == -v4 && v3 == v2 + v4) + | } + |""".stripMargin + + val iet = ErgoTree.fromProposition(compile(Map.empty, initTreeScript).asInstanceOf[SigmaPropValue]) + + iet.constants.toArray shouldBe Array(IntConstant(1), IntConstant(5), IntConstant(2), IntConstant(4), IntConstant(3), IntConstant(6)) + + val originalBytes = Base16.encode(ErgoTreeSerializer.DefaultSerializer.serializeErgoTree(iet)) + + val set = ErgoTree( + iet.header, + IndexedSeq(IntConstant(-2), IntConstant(2), IntConstant(-1), IntConstant(1), IntConstant(0), IntConstant(0)), + iet.toProposition(false) + ) + + val hostScript = + s""" + |{ + | val bytes = fromBase16("${originalBytes}") + | + | val substBytes = substConstants[Int](bytes, Coll[Int](0, 2, 4, 3, 1, 5), Coll[Int](-2, -1, 0, 1, 2, 0)) + | + | val checkSubst = substBytes == fromBase16("${Base16.encode(ErgoTreeSerializer.DefaultSerializer.serializeErgoTree(set))}") + | + | sigmaProp(checkSubst) + |} + |""".stripMargin + + test("subst", env, ext, hostScript, null) + } + } From f851b62bda75794d2e049bcc2312372184044f80 Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Mon, 5 Aug 2024 16:04:36 +0300 Subject: [PATCH 17/19] LSV5 fix --- .../scala/sigma/LanguageSpecificationV5.scala | 786 +++++++++--------- 1 file changed, 393 insertions(+), 393 deletions(-) diff --git a/sc/shared/src/test/scala/sigma/LanguageSpecificationV5.scala b/sc/shared/src/test/scala/sigma/LanguageSpecificationV5.scala index 64b2890082..af4f93d861 100644 --- a/sc/shared/src/test/scala/sigma/LanguageSpecificationV5.scala +++ b/sc/shared/src/test/scala/sigma/LanguageSpecificationV5.scala @@ -135,7 +135,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => ) val newCost = 1768 - def success(b: Boolean) = Expected(Success(b), 1768, newDetails, newCost, 2010 +: Seq.fill(3)(2012)) + def success(b: Boolean) = Expected(Success(b), 1768, newDetails, newCost, Seq.fill(4)(2012)) val cases = Seq( (true, true) -> success(false), @@ -165,14 +165,14 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => val expectedCost = 1768 val newCost = 1768 val cases = Seq( - (true, true) -> Expected(Success(false), expectedCost, newDetails, newCost, 2010 +: Seq.fill(3)(2012)) + (true, true) -> Expected(Success(false), expectedCost, newDetails, newCost, Seq.fill(4)(2012)) ) verifyCases(cases, feature) val initCost = 100 initialCostInTests.withValue(initCost) { val cases = Seq( - (true, true) -> Expected(Success(false), expectedCost + initCost, newDetails, newCost + initCost, (2010 + initCost) +: Seq.fill(3)(2012 + initCost)) + (true, true) -> Expected(Success(false), expectedCost + initCost, newDetails, newCost + initCost, Seq.fill(4)(2012 + initCost)) ) verifyCases(cases, feature) } @@ -202,7 +202,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => ) ) - def success(b: Boolean) = Expected(Success(b), 1769, newDetails, 1769, 2025 +: Seq.fill(3)(2027)) + def success(b: Boolean) = Expected(Success(b), 1769, newDetails, 1769, Seq.fill(4)(2027)) val cases = Seq( (1095564593, true) -> success(true), @@ -240,10 +240,10 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => ) ) val cases = Seq( - (false, true) -> Expected(Success(false), 1766, newDetails1, 1766, 2008 +: Seq.fill(3)(2010)), - (false, false) -> Expected(Success(false), 1766, newDetails1, 1766, 2008 +: Seq.fill(3)(2010)), - (true, true) -> Expected(Success(true), 1768, newDetails2, 1768, 2010 +: Seq.fill(3)(2012)), - (true, false) -> Expected(Success(false), 1768, newDetails2, 1768, 2010 +: Seq.fill(3)(2012)) + (false, true) -> Expected(Success(false), 1766, newDetails1, 1766, Seq.fill(4)(2010)), + (false, false) -> Expected(Success(false), 1766, newDetails1, 1766, Seq.fill(4)(2010)), + (true, true) -> Expected(Success(true), 1768, newDetails2, 1768, Seq.fill(4)(2012)), + (true, false) -> Expected(Success(false), 1768, newDetails2, 1768, Seq.fill(4)(2012)) ) verifyCases(cases, eq) } @@ -273,10 +273,10 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => ) ) val cases = Seq( - (true, false) -> Expected(Success(true), 1766, newDetails1, 1766, 2008 +: Seq.fill(3)(2010)), - (true, true) -> Expected(Success(true), 1766, newDetails1, 1766, 2008 +: Seq.fill(3)(2010)), - (false, false) -> Expected(Success(false), 1768, newDetails2, 1768, 2010 +: Seq.fill(3)(2012)), - (false, true) -> Expected(Success(true), 1768, newDetails2, 1768, 2010 +: Seq.fill(3)(2012)) + (true, false) -> Expected(Success(true), 1766, newDetails1, 1766, Seq.fill(4)(2010)), + (true, true) -> Expected(Success(true), 1766, newDetails1, 1766, Seq.fill(4)(2010)), + (false, false) -> Expected(Success(false), 1768, newDetails2, 1768, Seq.fill(4)(2012)), + (false, true) -> Expected(Success(true), 1768, newDetails2, 1768, Seq.fill(4)(2012)) ) verifyCases(cases, eq) } @@ -321,7 +321,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => ) verifyCases( Seq( - (true, Expected(Success(true), 1765, newDetails1, 1765, 2023 +: Seq.fill(3)(2027))), + (true, Expected(Success(true), 1765, newDetails1, 1765, Seq.fill(4)(2027))), (false, Expected(new ArithmeticException("/ by zero"))) ), existingFeature((x: Boolean) => x || (1 / 0 == 1), @@ -337,7 +337,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( Seq( (true, Expected(new ArithmeticException("/ by zero"))), - (false, Expected(Success(false), 1765, newDetails2, 1765, 2023 +: Seq.fill(3)(2027))) + (false, Expected(Success(false), 1765, newDetails2, 1765, Seq.fill(4)(2027))) ), existingFeature((x: Boolean) => x && (1 / 0 == 1), "{ (x: Boolean) => x && (1 / 0 == 1) }", @@ -351,8 +351,8 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( Seq( - (false, Expected(Success(false), 1765, newDetails2, 1765, 2029 +: Seq.fill(3)(2033))), - (true, Expected(Success(true), 1768, newDetails3, 1768, 2032 +: Seq.fill(3)(2036))) + (false, Expected(Success(false), 1765, newDetails2, 1765, Seq.fill(4)(2033))), + (true, Expected(Success(true), 1768, newDetails3, 1768, Seq.fill(4)(2036))) ), existingFeature((x: Boolean) => x && (x || (1 / 0 == 1)), "{ (x: Boolean) => x && (x || (1 / 0 == 1)) }", @@ -369,8 +369,8 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( Seq( - (false, Expected(Success(false), 1765, newDetails2, 1765, 2035 +: Seq.fill(3)(2039))), - (true, Expected(Success(true), 1770, newDetails4, 1770, 2040 +: Seq.fill(3)(2044))) + (false, Expected(Success(false), 1765, newDetails2, 1765, Seq.fill(4)(2039))), + (true, Expected(Success(true), 1770, newDetails4, 1770, Seq.fill(4)(2044))) ), existingFeature((x: Boolean) => x && (x && (x || (1 / 0 == 1))), "{ (x: Boolean) => x && (x && (x || (1 / 0 == 1))) }", @@ -390,8 +390,8 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( Seq( - (false, Expected(Success(false), 1765, newDetails2, 1765, 2041 +: Seq.fill(3)(2045))), - (true, Expected(Success(true), 1773, newDetails5, 1773, 2049 +: Seq.fill(3)(2053))) + (false, Expected(Success(false), 1765, newDetails2, 1765, Seq.fill(4)(2045))), + (true, Expected(Success(true), 1773, newDetails5, 1773, Seq.fill(4)(2053))) ), existingFeature((x: Boolean) => x && (x && (x && (x || (1 / 0 == 1)))), "{ (x: Boolean) => x && (x && (x && (x || (1 / 0 == 1)))) }", @@ -425,7 +425,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( Seq( (false, Expected(new ArithmeticException("/ by zero"))), - (true, Expected(Success(true), 1773, newDetails6, 1773, 2071 +: Seq.fill(3)(2075))) + (true, Expected(Success(true), 1773, newDetails6, 1773, Seq.fill(4)(2075))) ), existingFeature((x: Boolean) => !(!x && (1 / 0 == 1)) && (x || (1 / 0 == 1)), "{ (x: Boolean) => !(!x && (1 / 0 == 1)) && (x || (1 / 0 == 1)) }", @@ -454,7 +454,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => ) verifyCases( Seq( - (true, Expected(Success(true), 1768, newDetails7, 1768, 2032 +: Seq.fill(3)(2036))), + (true, Expected(Success(true), 1768, newDetails7, 1768, Seq.fill(4)(2036))), (false, Expected(new ArithmeticException("/ by zero"))) ), existingFeature((x: Boolean) => (x || (1 / 0 == 1)) && x, @@ -480,7 +480,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => ) verifyCases( Seq( - (true, Expected(Success(true), 1770, newDetails8, 1770, 2064 +: Seq.fill(3)(2068))), + (true, Expected(Success(true), 1770, newDetails8, 1770, Seq.fill(4)(2068))), (false, Expected(new ArithmeticException("/ by zero"))) ), existingFeature((x: Boolean) => (x || (1 / 0 == 1)) && (x || (1 / 0 == 1)), @@ -512,7 +512,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => ) verifyCases( Seq( - (true, Expected(Success(true), 1775, newDetails9, 1775, 2103 +: Seq.fill(3)(2107))), + (true, Expected(Success(true), 1775, newDetails9, 1775, Seq.fill(4)(2107))), (false, Expected(new ArithmeticException("/ by zero"))) ), existingFeature( @@ -562,7 +562,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( Seq( (false, Expected(new ArithmeticException("/ by zero"))), - (true, Expected(Success(true), 1780, newDetails10, 1780, 2152 +: Seq.fill(3)(2156))) + (true, Expected(Success(true), 1780, newDetails10, 1780, Seq.fill(4)(2156))) ), existingFeature( (x: Boolean) => (!(!x && (1 / 0 == 1)) || (1 / 0 == 0)) && (!(!x && (1 / 0 == 1)) || (1 / 0 == 1)), @@ -605,7 +605,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( { - def expect(v: Byte) = Expected(Success(v), 1763, TracedCost(traceBase), 1763, 1991 +: Seq.fill(3)(1993)) + def expect(v: Byte) = Expected(Success(v), 1763, TracedCost(traceBase), 1763, Seq.fill(4)(1993)) Seq( (0.toByte, expect(0.toByte)), @@ -623,7 +623,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( { - def expected(v: Short) = Expected(Success(v), 1764, upcastCostDetails(SShort), 1764, 1996 +: Seq.fill(3)(1998)) + def expected(v: Short) = Expected(Success(v), 1764, upcastCostDetails(SShort), 1764, Seq.fill(4)(1998)) Seq( (0.toByte, expected(0.toShort)), @@ -641,7 +641,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( { - def expected(v: Int) = Expected(Success(v), 1764, upcastCostDetails(SInt), 1764, 1996 +: Seq.fill(3)(1998)) + def expected(v: Int) = Expected(Success(v), 1764, upcastCostDetails(SInt), 1764, Seq.fill(4)(1998)) Seq( (0.toByte, expected(0)), @@ -659,7 +659,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( { - def expected(v: Long) = Expected(Success(v), 1764, upcastCostDetails(SLong), 1764, 1996 +: Seq.fill(3)(1998)) + def expected(v: Long) = Expected(Success(v), 1764, upcastCostDetails(SLong), 1764, Seq.fill(4)(1998)) Seq( (0.toByte, expected(0L)), @@ -677,7 +677,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( { - def expected(v: BigInt) = Expected(Success(v), 1767, upcastCostDetails(SBigInt), 1767, 1999 +: Seq.fill(3)(2001)) + def expected(v: BigInt) = Expected(Success(v), 1767, upcastCostDetails(SBigInt), 1767, Seq.fill(4)(2001)) Seq( (0.toByte, expected(CBigInt(new BigInteger("0", 16)))), @@ -696,7 +696,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => val n = ExactIntegral.ByteIsExactIntegral verifyCases( { - def success[T](v: (T, (T, (T, (T, T))))) = Expected(Success(v), 1788, arithOpsCostDetails(SByte), 1788, 2112 +: Seq.fill(3)(2116)) + def success[T](v: (T, (T, (T, (T, T))))) = Expected(Success(v), 1788, arithOpsCostDetails(SByte), 1788, Seq.fill(4)(2116)) Seq( ((-128.toByte, -128.toByte), Expected(new ArithmeticException("Byte overflow"))), @@ -858,7 +858,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => property("Byte LT, GT, NEQ") { val o = ExactOrdering.ByteIsExactOrdering - def expect(v: Boolean) = Expected(Success(v), 1768, binaryRelationCostDetails(LT, SByte), 1768, 2010 +: Seq.fill(3)(2012)) + def expect(v: Boolean) = Expected(Success(v), 1768, binaryRelationCostDetails(LT, SByte), 1768, Seq.fill(4)(2012)) val LT_cases: Seq[((Byte, Byte), Expected[Boolean])] = Seq( (-128.toByte, -128.toByte) -> expect(false), @@ -900,17 +900,17 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyOp(LT_cases, "<", LT.apply)(_ < _) verifyOp( - swapArgs(LT_cases, cost = 1768, newCostDetails = binaryRelationCostDetails(GT, SByte), expectedV3Costs = 2010 +: Seq.fill(3)(2012)), + swapArgs(LT_cases, cost = 1768, newCostDetails = binaryRelationCostDetails(GT, SByte), expectedV3Costs = Seq.fill(4)(2012)), ">", GT.apply)(_ > _) - val neqCases = newCasesFrom3(LT_cases.map(_._1))(_ != _, cost = 1766, newCostDetails = costNEQ(constNeqCost), expectedV3Costs = 2008 +: Seq.fill(3)(2010)) + val neqCases = newCasesFrom3(LT_cases.map(_._1))(_ != _, cost = 1766, newCostDetails = costNEQ(constNeqCost), expectedV3Costs = Seq.fill(4)(2010)) verifyOp(neqCases, "!=", NEQ.apply)(_ != _) } property("Byte LE, GE") { val o = ExactOrdering.ByteIsExactOrdering - def expect(v: Boolean) = Expected(Success(v), 1768, binaryRelationCostDetails(LE, SByte), 1768, 2010 +: Seq.fill(3)(2012)) + def expect(v: Boolean) = Expected(Success(v), 1768, binaryRelationCostDetails(LE, SByte), 1768, Seq.fill(4)(2012)) val LE_cases: Seq[((Byte, Byte), Expected[Boolean])] = Seq( (-128.toByte, -128.toByte) -> expect(true), @@ -953,7 +953,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyOp(LE_cases, "<=", LE.apply)(_ <= _) verifyOp( - swapArgs(LE_cases, cost = 1768, newCostDetails = binaryRelationCostDetails(GE, SByte), expectedV3Costs = 2010 +: Seq.fill(3)(2012)), + swapArgs(LE_cases, cost = 1768, newCostDetails = binaryRelationCostDetails(GE, SByte), expectedV3Costs = Seq.fill(4)(2012)), ">=", GE.apply)(_ >= _) } property("Short methods equivalence") { @@ -962,7 +962,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( { - def success[T](v: T) = Expected(Success(v), 1764, downcastCostDetails(SByte), 1764, 1996 +: Seq.fill(3)(1998)) + def success[T](v: T) = Expected(Success(v), 1764, downcastCostDetails(SByte), 1764, Seq.fill(4)(1998)) Seq( (Short.MinValue, Expected(new ArithmeticException("Byte overflow"))), @@ -982,7 +982,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( { - def success[T](v: T) = Expected(Success(v), 1763, TracedCost(traceBase), 1763, 1991 +: Seq.fill(3)(1993)) + def success[T](v: T) = Expected(Success(v), 1763, TracedCost(traceBase), 1763, Seq.fill(4)(1993)) Seq( (-32768.toShort, success(-32768.toShort)), @@ -1000,7 +1000,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( { - def success[T](v: T) = Expected(Success(v), 1764, upcastCostDetails(SInt), 1764, 1996 +: Seq.fill(3)(1998)) + def success[T](v: T) = Expected(Success(v), 1764, upcastCostDetails(SInt), 1764, Seq.fill(4)(1998)) Seq( (-32768.toShort, success(-32768)), @@ -1018,7 +1018,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( { - def success[T](v: T) = Expected(Success(v), 1764, upcastCostDetails(SLong), 1764, 1996 +: Seq.fill(3)(1998)) + def success[T](v: T) = Expected(Success(v), 1764, upcastCostDetails(SLong), 1764, Seq.fill(4)(1998)) Seq( (-32768.toShort, success(-32768L)), @@ -1036,7 +1036,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( { - def success(v: BigInt) = Expected(Success(v), 1767, upcastCostDetails(SBigInt), 1767, 1999 +: Seq.fill(3)(2001)) + def success(v: BigInt) = Expected(Success(v), 1767, upcastCostDetails(SBigInt), 1767, Seq.fill(4)(2001)) Seq( (-32768.toShort, success(CBigInt(new BigInteger("-8000", 16)))), @@ -1055,7 +1055,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => val n = ExactIntegral.ShortIsExactIntegral verifyCases( { - def success[T](v: T) = Expected(Success(v), 1788, arithOpsCostDetails(SShort), 1788, 2112 +: Seq.fill(3)(2116)) + def success[T](v: T) = Expected(Success(v), 1788, arithOpsCostDetails(SShort), 1788, Seq.fill(4)(2116)) Seq( ((-32768.toShort, 1.toShort), Expected(new ArithmeticException("Short overflow"))), @@ -1149,7 +1149,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => property("Short LT, GT, NEQ") { val o = ExactOrdering.ShortIsExactOrdering - def expect(v: Boolean) = Expected(Success(v), 1768, binaryRelationCostDetails(LT, SShort), 1768, 2010 +: Seq.fill(3)(2012)) + def expect(v: Boolean) = Expected(Success(v), 1768, binaryRelationCostDetails(LT, SShort), 1768, Seq.fill(4)(2012)) val LT_cases: Seq[((Short, Short), Expected[Boolean])] = Seq( (Short.MinValue, Short.MinValue) -> expect(false), @@ -1190,16 +1190,16 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyOp(LT_cases, "<", LT.apply)(_ < _) - verifyOp(swapArgs(LT_cases, cost = 1768, newCostDetails = binaryRelationCostDetails(GT, SShort), expectedV3Costs = 2010 +: Seq.fill(3)(2012)), ">", GT.apply)(_ > _) + verifyOp(swapArgs(LT_cases, cost = 1768, newCostDetails = binaryRelationCostDetails(GT, SShort), expectedV3Costs = Seq.fill(4)(2012)), ">", GT.apply)(_ > _) - val neqCases = newCasesFrom3(LT_cases.map(_._1))(_ != _, cost = 1766, newCostDetails = costNEQ(constNeqCost), expectedV3Costs = 2008 +: Seq.fill(3)(2010)) + val neqCases = newCasesFrom3(LT_cases.map(_._1))(_ != _, cost = 1766, newCostDetails = costNEQ(constNeqCost), expectedV3Costs = Seq.fill(4)(2010)) verifyOp(neqCases, "!=", NEQ.apply)(_ != _) } property("Short LE, GE") { val o = ExactOrdering.ShortIsExactOrdering - def expect(v: Boolean) = Expected(Success(v), 1768, binaryRelationCostDetails(LE, SShort), 1768, 2010 +: Seq.fill(3)(2012)) + def expect(v: Boolean) = Expected(Success(v), 1768, binaryRelationCostDetails(LE, SShort), 1768, Seq.fill(4)(2012)) val LE_cases: Seq[((Short, Short), Expected[Boolean])] = Seq( (Short.MinValue, Short.MinValue) -> expect(true), @@ -1242,7 +1242,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyOp(LE_cases, "<=", LE.apply)(_ <= _) verifyOp( - swapArgs(LE_cases, cost = 1768, newCostDetails = binaryRelationCostDetails(GE, SShort), expectedV3Costs = 2010 +: Seq.fill(3)(2012)), + swapArgs(LE_cases, cost = 1768, newCostDetails = binaryRelationCostDetails(GE, SShort), expectedV3Costs = Seq.fill(4)(2012)), ">=", GE.apply)(_ >= _) } @@ -1252,7 +1252,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( { - def success[T](v: T) = Expected(Success(v), 1764, downcastCostDetails(SByte), 1764, 1996 +: Seq.fill(3)(1998)) + def success[T](v: T) = Expected(Success(v), 1764, downcastCostDetails(SByte), 1764, Seq.fill(4)(1998)) Seq( (Int.MinValue, Expected(new ArithmeticException("Byte overflow"))), @@ -1272,7 +1272,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( { - def success[T](v: T) = Expected(Success(v), 1764, downcastCostDetails(SShort), 1764, 1996 +: Seq.fill(3)(1998)) + def success[T](v: T) = Expected(Success(v), 1764, downcastCostDetails(SShort), 1764, Seq.fill(4)(1998)) Seq( (Int.MinValue, Expected(new ArithmeticException("Short overflow"))), @@ -1292,7 +1292,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( { - def success[T](v: T) = Expected(Success(v), 1763, TracedCost(traceBase), 1763, 1991 +: Seq.fill(3)(1993)) + def success[T](v: T) = Expected(Success(v), 1763, TracedCost(traceBase), 1763, Seq.fill(4)(1993)) Seq( (Int.MinValue, success(Int.MinValue)), @@ -1308,7 +1308,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( { - def success[T](v: T) = Expected(Success(v), 1764, upcastCostDetails(SLong), 1764, 1996 +: Seq.fill(3)(1998)) + def success[T](v: T) = Expected(Success(v), 1764, upcastCostDetails(SLong), 1764, Seq.fill(4)(1998)) Seq( (Int.MinValue, success(Int.MinValue.toLong)), @@ -1324,7 +1324,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( { - def success(v: BigInt) = Expected(Success(v), 1767, upcastCostDetails(SBigInt), 1767, 1999 +: Seq.fill(3)(2001)) + def success(v: BigInt) = Expected(Success(v), 1767, upcastCostDetails(SBigInt), 1767, Seq.fill(4)(2001)) Seq( (Int.MinValue, success(CBigInt(new BigInteger("-80000000", 16)))), @@ -1343,7 +1343,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => val n = ExactNumeric.IntIsExactNumeric verifyCases( { - def success[T](v: T) = Expected(Success(v), 1788, arithOpsCostDetails(SInt), 1788, 2112 +: Seq.fill(3)(2116)) + def success[T](v: T) = Expected(Success(v), 1788, arithOpsCostDetails(SInt), 1788, Seq.fill(4)(2116)) Seq( ((Int.MinValue, 449583993), Expected(new ArithmeticException("integer overflow"))), @@ -1438,7 +1438,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => property("Int LT, GT, NEQ") { val o = ExactOrdering.IntIsExactOrdering - def expect(v: Boolean) = Expected(Success(v), 1768, binaryRelationCostDetails(LT, SInt), 1768, 2010 +: Seq.fill(3)(2012)) + def expect(v: Boolean) = Expected(Success(v), 1768, binaryRelationCostDetails(LT, SInt), 1768, Seq.fill(4)(2012)) val LT_cases: Seq[((Int, Int), Expected[Boolean])] = Seq( (Int.MinValue, Int.MinValue) -> expect(false), @@ -1480,16 +1480,16 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyOp(LT_cases, "<", LT.apply)(_ < _) verifyOp( - swapArgs(LT_cases, cost = 1768, newCostDetails = binaryRelationCostDetails(GT, SInt), expectedV3Costs = 2010 +: Seq.fill(3)(2012)), + swapArgs(LT_cases, cost = 1768, newCostDetails = binaryRelationCostDetails(GT, SInt), expectedV3Costs = Seq.fill(4)(2012)), ">", GT.apply)(_ > _) - val neqCases = newCasesFrom3(LT_cases.map(_._1))(_ != _, cost = 1766, newCostDetails = costNEQ(constNeqCost), expectedV3Costs = 2008 +: Seq.fill(3)(2010)) + val neqCases = newCasesFrom3(LT_cases.map(_._1))(_ != _, cost = 1766, newCostDetails = costNEQ(constNeqCost), expectedV3Costs = Seq.fill(4)(2010)) verifyOp(neqCases, "!=", NEQ.apply)(_ != _) } property("Int LE, GE") { val o = ExactOrdering.IntIsExactOrdering - def expect(v: Boolean) = Expected(Success(v), 1768, binaryRelationCostDetails(LE, SInt), 1768, 2010 +: Seq.fill(3)(2012)) + def expect(v: Boolean) = Expected(Success(v), 1768, binaryRelationCostDetails(LE, SInt), 1768, Seq.fill(4)(2012)) val LE_cases: Seq[((Int, Int), Expected[Boolean])] = Seq( (Int.MinValue, Int.MinValue) -> expect(true), (Int.MinValue, (Int.MinValue + 1).toInt) -> expect(true), @@ -1531,7 +1531,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyOp(LE_cases, "<=", LE.apply)(_ <= _) verifyOp( - swapArgs(LE_cases, cost = 1768, newCostDetails = binaryRelationCostDetails(GE, SInt), expectedV3Costs = 2010 +: Seq.fill(3)(2012)), + swapArgs(LE_cases, cost = 1768, newCostDetails = binaryRelationCostDetails(GE, SInt), expectedV3Costs = Seq.fill(4)(2012)), ">=", GE.apply)(_ >= _) } @@ -1545,7 +1545,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => property("Long.toByte method") { verifyCases( { - def success[T](v: T) = Expected(Success(v), 1764, downcastCostDetails(SByte), 1764, 1996 +: Seq.fill(3)(1998)) + def success[T](v: T) = Expected(Success(v), 1764, downcastCostDetails(SByte), 1764, Seq.fill(4)(1998)) Seq( (Long.MinValue, Expected(new ArithmeticException("Byte overflow"))), (Byte.MinValue.toLong - 1, Expected(new ArithmeticException("Byte overflow"))), @@ -1566,7 +1566,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => property("Long.toShort method") { verifyCases( { - def success[T](v: T) = Expected(Success(v), 1764, downcastCostDetails(SShort), 1764, 1996 +: Seq.fill(3)(1998)) + def success[T](v: T) = Expected(Success(v), 1764, downcastCostDetails(SShort), 1764, Seq.fill(4)(1998)) Seq( (Long.MinValue, Expected(new ArithmeticException("Short overflow"))), (Short.MinValue.toLong - 1, Expected(new ArithmeticException("Short overflow"))), @@ -1587,7 +1587,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => property("Long.toInt method") { verifyCases( { - def success[T](v: T) = Expected(Success(v), 1764, downcastCostDetails(SInt), 1764, 1996 +: Seq.fill(3)(1998)) + def success[T](v: T) = Expected(Success(v), 1764, downcastCostDetails(SInt), 1764, Seq.fill(4)(1998)) Seq( (Long.MinValue, Expected(new ArithmeticException("Int overflow"))), @@ -1609,7 +1609,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => property("Long.toLong method") { verifyCases( { - def success[T](v: T) = Expected(Success(v), 1763, TracedCost(traceBase), 1763, 1991 +: Seq.fill(3)(1993)) + def success[T](v: T) = Expected(Success(v), 1763, TracedCost(traceBase), 1763, Seq.fill(4)(1993)) Seq( (Long.MinValue, success(Long.MinValue)), (-1L, success(-1L)), @@ -1626,7 +1626,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => property("Long.toBigInt method") { verifyCases( { - def success(v: BigInt) = Expected(Success(v), 1767, upcastCostDetails(SBigInt), 1767, 1999 +: Seq.fill(3)(2001)) + def success(v: BigInt) = Expected(Success(v), 1767, upcastCostDetails(SBigInt), 1767, Seq.fill(4)(2001)) Seq( (Long.MinValue, success(CBigInt(new BigInteger("-8000000000000000", 16)))), (-1074651039980347209L, success(CBigInt(new BigInteger("-ee9ed6d57885f49", 16)))), @@ -1647,7 +1647,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => val n = ExactNumeric.LongIsExactNumeric verifyCases( { - def success[T](v: T) = Expected(Success(v), 1788, arithOpsCostDetails(SLong), 1788, 2112 +: Seq.fill(3)(2116)) + def success[T](v: T) = Expected(Success(v), 1788, arithOpsCostDetails(SLong), 1788, Seq.fill(4)(2116)) Seq( ((Long.MinValue, -4677100190307931395L), Expected(new ArithmeticException("long overflow"))), ((Long.MinValue, -1L), Expected(new ArithmeticException("long overflow"))), @@ -1738,7 +1738,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => property("Long LT, GT, NEQ") { val o = ExactOrdering.LongIsExactOrdering - def expect(v: Boolean) = Expected(Success(v), 1768, binaryRelationCostDetails(LT, SLong), 1768, 2010 +: Seq.fill(3)(2012)) + def expect(v: Boolean) = Expected(Success(v), 1768, binaryRelationCostDetails(LT, SLong), 1768, Seq.fill(4)(2012)) val LT_cases: Seq[((Long, Long), Expected[Boolean])] = Seq( (Long.MinValue, Long.MinValue) -> expect(false), (Long.MinValue, (Long.MinValue + 1).toLong) -> expect(true), @@ -1779,16 +1779,16 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyOp(LT_cases, "<", LT.apply)(_ < _) verifyOp( - swapArgs(LT_cases, cost = 1768, newCostDetails = binaryRelationCostDetails(GT, SLong), expectedV3Costs = 2010 +: Seq.fill(3)(2012)), + swapArgs(LT_cases, cost = 1768, newCostDetails = binaryRelationCostDetails(GT, SLong), expectedV3Costs = Seq.fill(4)(2012)), ">", GT.apply)(_ > _) - val neqCases = newCasesFrom3(LT_cases.map(_._1))(_ != _, cost = 1766, newCostDetails = costNEQ(constNeqCost), 2008 +: Seq.fill(3)(2010)) + val neqCases = newCasesFrom3(LT_cases.map(_._1))(_ != _, cost = 1766, newCostDetails = costNEQ(constNeqCost), Seq.fill(4)(2010)) verifyOp(neqCases, "!=", NEQ.apply)(_ != _) } property("Long LE, GE") { val o = ExactOrdering.LongIsExactOrdering - def expect(v: Boolean) = Expected(Success(v), 1768, binaryRelationCostDetails(LE, SLong), 1768, 2010 +: Seq.fill(3)(2012)) + def expect(v: Boolean) = Expected(Success(v), 1768, binaryRelationCostDetails(LE, SLong), 1768, Seq.fill(4)(2012)) val LE_cases: Seq[((Long, Long), Expected[Boolean])] = Seq( (Long.MinValue, Long.MinValue) -> expect(true), (Long.MinValue, (Long.MinValue + 1).toLong) -> expect(true), @@ -1830,14 +1830,14 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyOp(LE_cases, "<=", LE.apply)(_ <= _) verifyOp( - swapArgs(LE_cases, cost = 1768, newCostDetails = binaryRelationCostDetails(GE, SLong), expectedV3Costs = 2010 +: Seq.fill(3)(2012)), + swapArgs(LE_cases, cost = 1768, newCostDetails = binaryRelationCostDetails(GE, SLong), expectedV3Costs = Seq.fill(4)(2012)), ">=", GE.apply)(_ >= _) } property("BigInt methods equivalence") { verifyCases( { - def success(v: BigInt) = Expected(Success(v), 1764, TracedCost(traceBase), 1764, 1992 +: Seq.fill(3)(1994)) + def success(v: BigInt) = Expected(Success(v), 1764, TracedCost(traceBase), 1764, Seq.fill(4)(1994)) Seq( (CBigInt(new BigInteger("-85102d7f884ca0e8f56193b46133acaf7e4681e1757d03f191ae4f445c8e0", 16)), success( CBigInt(new BigInteger("-85102d7f884ca0e8f56193b46133acaf7e4681e1757d03f191ae4f445c8e0", 16)) @@ -1860,7 +1860,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( { def success(v: (BigInt, (BigInt, (BigInt, (BigInt, BigInt))))) = - Expected(Success(v), 1793, arithOpsCostDetails(SBigInt), 1793, 2117 +: Seq.fill(3)(2121)) + Expected(Success(v), 1793, arithOpsCostDetails(SBigInt), 1793, Seq.fill(4)(2121)) Seq( ((CBigInt(new BigInteger("-8683d1cd99d5fcf0e6eff6295c285c36526190e13dbde008c49e5ae6fddc1c", 16)), CBigInt(new BigInteger("-2ef55db3f245feddacf0182e299dd", 16))), @@ -1984,7 +1984,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => property("BigInt LT, GT, NEQ") { val o = NumericOps.BigIntIsExactOrdering - def expect(v: Boolean) = Expected(Success(v), 1768, binaryRelationCostDetails(LT, SBigInt), 1768, 2010 +: Seq.fill(3)(2012)) + def expect(v: Boolean) = Expected(Success(v), 1768, binaryRelationCostDetails(LT, SBigInt), 1768, Seq.fill(4)(2012)) val LT_cases: Seq[((BigInt, BigInt), Expected[Boolean])] = Seq( (BigIntMinValue, BigIntMinValue) -> expect(false), (BigIntMinValue, BigIntMinValue.add(1.toBigInt)) -> expect(true), @@ -2027,11 +2027,11 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyOp(LT_cases, "<", LT.apply)(o.lt(_, _)) verifyOp( - swapArgs(LT_cases, cost = 1768, newCostDetails = binaryRelationCostDetails(GT, SBigInt), expectedV3Costs = 2010 +: Seq.fill(3)(2012)), + swapArgs(LT_cases, cost = 1768, newCostDetails = binaryRelationCostDetails(GT, SBigInt), expectedV3Costs = Seq.fill(4)(2012)), ">", GT.apply)(o.gt(_, _)) val constBigIntCost = Array[CostItem](FixedCostItem(NamedDesc("EQ_BigInt"), FixedCost(JitCost(5)))) - val neqCases = newCasesFrom3(LT_cases.map(_._1))(_ != _, cost = 1766, newCostDetails = costNEQ(constBigIntCost), expectedV3Costs = 2008 +: Seq.fill(3)(2010)) + val neqCases = newCasesFrom3(LT_cases.map(_._1))(_ != _, cost = 1766, newCostDetails = costNEQ(constBigIntCost), expectedV3Costs = Seq.fill(4)(2010)) verifyOp(neqCases, "!=", NEQ.apply)(_ != _) } @@ -2042,7 +2042,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => val BigIntMaxValue = CBigInt(new BigInteger("7F" + "ff" * 31, 16)) val BigIntOverlimit = CBigInt(new BigInteger("7F" + "ff" * 33, 16)) - def expect(v: Boolean) = Expected(Success(v), 1768, binaryRelationCostDetails(LE, SBigInt), 1768, 2010 +: Seq.fill(3)(2012)) + def expect(v: Boolean) = Expected(Success(v), 1768, binaryRelationCostDetails(LE, SBigInt), 1768, Seq.fill(4)(2012)) val LE_cases: Seq[((BigInt, BigInt), Expected[Boolean])] = Seq( (BigIntMinValue, BigIntMinValue) -> expect(true), (BigIntMinValue, BigIntMinValue.add(1.toBigInt)) -> expect(true), @@ -2086,7 +2086,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyOp(LE_cases, "<=", LE.apply)(o.lteq(_, _)) verifyOp( - swapArgs(LE_cases, cost = 1768, newCostDetails = binaryRelationCostDetails(GE, SBigInt), expectedV3Costs = 2010 +: Seq.fill(3)(2012)), + swapArgs(LE_cases, cost = 1768, newCostDetails = binaryRelationCostDetails(GE, SBigInt), expectedV3Costs = Seq.fill(4)(2012)), ">=", GE.apply)(o.gteq(_, _)) } @@ -2113,11 +2113,11 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => } property("NEQ of pre-defined types") { - verifyNeq(ge1, ge2, 1783, Array[CostItem](FixedCostItem(NamedDesc("EQ_GroupElement"), FixedCost(JitCost(172)))), 1783, 2025 +: Seq.fill(3)(2027))(_.asInstanceOf[CGroupElement].copy()) - verifyNeq(t1, t2, 1767, Array[CostItem](FixedCostItem(NamedDesc("EQ_AvlTree"), FixedCost(JitCost(6)))), 1767, 2017 +: Seq.fill(3)(2019))(_.asInstanceOf[CAvlTree].copy()) - verifyNeq(b1, b2, 1767, Array[CostItem](), 1767, 2017 +: Seq.fill(3)(2019))(_.asInstanceOf[CBox].copy()) - verifyNeq(preH1, preH2, 1766, Array[CostItem](FixedCostItem(NamedDesc("EQ_PreHeader"), FixedCost(JitCost(4)))), 1766, 2016 +: Seq.fill(3)(2018))(_.asInstanceOf[CPreHeader].copy()) - verifyNeq(h1, h2, 1767, Array[CostItem](FixedCostItem(NamedDesc("EQ_Header"), FixedCost(JitCost(6)))), 1767, 2017 +: Seq.fill(3)(2019))(_.asInstanceOf[CHeader].copy()) + verifyNeq(ge1, ge2, 1783, Array[CostItem](FixedCostItem(NamedDesc("EQ_GroupElement"), FixedCost(JitCost(172)))), 1783, Seq.fill(4)(2027))(_.asInstanceOf[CGroupElement].copy()) + verifyNeq(t1, t2, 1767, Array[CostItem](FixedCostItem(NamedDesc("EQ_AvlTree"), FixedCost(JitCost(6)))), 1767, Seq.fill(4)(2019))(_.asInstanceOf[CAvlTree].copy()) + verifyNeq(b1, b2, 1767, Array[CostItem](), 1767, Seq.fill(4)(2019))(_.asInstanceOf[CBox].copy()) + verifyNeq(preH1, preH2, 1766, Array[CostItem](FixedCostItem(NamedDesc("EQ_PreHeader"), FixedCost(JitCost(4)))), 1766, Seq.fill(4)(2018))(_.asInstanceOf[CPreHeader].copy()) + verifyNeq(h1, h2, 1767, Array[CostItem](FixedCostItem(NamedDesc("EQ_Header"), FixedCost(JitCost(6)))), 1767, Seq.fill(4)(2019))(_.asInstanceOf[CHeader].copy()) } property("NEQ of tuples of numerics") { @@ -2125,14 +2125,14 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => FixedCostItem(NamedDesc("EQ_Tuple"), FixedCost(JitCost(4))), FixedCostItem(NamedDesc("EQ_Prim"), FixedCost(JitCost(3))) ) - verifyNeq((0.toByte, 1.toByte), (1.toByte, 1.toByte), 1767, tuplesNeqCost, 1767, 2017 +: Seq.fill(3)(2019))(_.copy()) - verifyNeq((0.toShort, 1.toByte), (1.toShort, 1.toByte), 1767, tuplesNeqCost, 1767, 2025 +: Seq.fill(3)(2029))(_.copy()) - verifyNeq((0, 1.toByte), (1, 1.toByte), 1767, tuplesNeqCost, 1767, 2025 +: Seq.fill(3)(2029))(_.copy()) - verifyNeq((0.toLong, 1.toByte), (1.toLong, 1.toByte), 1767, tuplesNeqCost, 1767, 2025 +: Seq.fill(3)(2029))(_.copy()) + verifyNeq((0.toByte, 1.toByte), (1.toByte, 1.toByte), 1767, tuplesNeqCost, 1767, Seq.fill(4)(2019))(_.copy()) + verifyNeq((0.toShort, 1.toByte), (1.toShort, 1.toByte), 1767, tuplesNeqCost, 1767, Seq.fill(4)(2029))(_.copy()) + verifyNeq((0, 1.toByte), (1, 1.toByte), 1767, tuplesNeqCost, 1767, Seq.fill(4)(2029))(_.copy()) + verifyNeq((0.toLong, 1.toByte), (1.toLong, 1.toByte), 1767, tuplesNeqCost, 1767, Seq.fill(4)(2029))(_.copy()) verifyNeq((0.toBigInt, 1.toByte), (1.toBigInt, 1.toByte), 1767, Array( FixedCostItem(NamedDesc("EQ_Tuple"), FixedCost(JitCost(4))), FixedCostItem(NamedDesc("EQ_BigInt"), FixedCost(JitCost(5))) - ), 1767, 2025 +: Seq.fill(3)(2029))(_.copy()) + ), 1767, Seq.fill(4)(2029))(_.copy()) } property("NEQ of tuples of pre-defined types") { @@ -2141,29 +2141,29 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => FixedCostItem(NamedDesc("EQ_GroupElement"), FixedCost(JitCost(172))), FixedCostItem(NamedDesc("EQ_GroupElement"), FixedCost(JitCost(172))) ) - verifyNeq((ge1, ge1), (ge1, ge2), 1801, groupNeqCost, 1801, 2051 +: Seq.fill(3)(2053))(_.copy()) + verifyNeq((ge1, ge1), (ge1, ge2), 1801, groupNeqCost, 1801, Seq.fill(4)(2053))(_.copy()) val treeNeqCost = Array( FixedCostItem(NamedDesc("EQ_Tuple"), FixedCost(JitCost(4))), FixedCostItem(NamedDesc("EQ_AvlTree"), FixedCost(JitCost(6))), FixedCostItem(NamedDesc("EQ_AvlTree"), FixedCost(JitCost(6))) ) - verifyNeq((t1, t1), (t1, t2), 1768, treeNeqCost, 1768, 2034 +: Seq.fill(3)(2038))(_.copy()) - verifyNeq((b1, b1), (b1, b2), 1768, Array[CostItem](), 1768, 2034 +: Seq.fill(3)(2038))(_.copy()) + verifyNeq((t1, t1), (t1, t2), 1768, treeNeqCost, 1768, Seq.fill(4)(2038))(_.copy()) + verifyNeq((b1, b1), (b1, b2), 1768, Array[CostItem](), 1768, Seq.fill(4)(2038))(_.copy()) val preHeaderNeqCost = Array( FixedCostItem(NamedDesc("EQ_Tuple"), FixedCost(JitCost(4))), FixedCostItem(NamedDesc("EQ_PreHeader"), FixedCost(JitCost(4))), FixedCostItem(NamedDesc("EQ_PreHeader"), FixedCost(JitCost(4))) ) - verifyNeq((preH1, preH1), (preH1, preH2), 1767, preHeaderNeqCost, 1767, 2033 +: Seq.fill(3)(2037))(_.copy()) + verifyNeq((preH1, preH1), (preH1, preH2), 1767, preHeaderNeqCost, 1767, Seq.fill(4)(2037))(_.copy()) val headerNeqCost = Array( FixedCostItem(NamedDesc("EQ_Tuple"), FixedCost(JitCost(4))), FixedCostItem(NamedDesc("EQ_Header"), FixedCost(JitCost(6))), FixedCostItem(NamedDesc("EQ_Header"), FixedCost(JitCost(6))) ) - verifyNeq((h1, h1), (h1, h2), 1768, headerNeqCost, 1768, 2034 +: Seq.fill(3)(2038))(_.copy()) + verifyNeq((h1, h1), (h1, h2), 1768, headerNeqCost, 1768, Seq.fill(4)(2038))(_.copy()) } property("NEQ of nested tuples") { @@ -2247,15 +2247,15 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => FixedCostItem(NamedDesc("EQ_Header"), FixedCost(JitCost(6))), FixedCostItem(NamedDesc("EQ_Header"), FixedCost(JitCost(6))) ) - verifyNeq((ge1, (t1, t1)), (ge1, (t1, t2)), 1785, nestedTuplesNeqCost1, 1785, 2059 +: Seq.fill(3)(2063))(_.copy()) - verifyNeq((ge1, (t1, (b1, b1))), (ge1, (t1, (b1, b2))), 1786, nestedTuplesNeqCost2, 1786, 2076 +: Seq.fill(3)(2080))(_.copy()) - verifyNeq((ge1, (t1, (b1, (preH1, preH1)))), (ge1, (t1, (b1, (preH1, preH2)))), 1787, nestedTuplesNeqCost3, 1787, 2093 +: Seq.fill(3)(2097))(_.copy()) - verifyNeq((ge1, (t1, (b1, (preH1, (h1, h1))))), (ge1, (t1, (b1, (preH1, (h1, h2))))), 1788, nestedTuplesNeqCost4, 1788, 2110 +: Seq.fill(3)(2114))(_.copy()) + verifyNeq((ge1, (t1, t1)), (ge1, (t1, t2)), 1785, nestedTuplesNeqCost1, 1785, Seq.fill(4)(2063))(_.copy()) + verifyNeq((ge1, (t1, (b1, b1))), (ge1, (t1, (b1, b2))), 1786, nestedTuplesNeqCost2, 1786, Seq.fill(4)(2080))(_.copy()) + verifyNeq((ge1, (t1, (b1, (preH1, preH1)))), (ge1, (t1, (b1, (preH1, preH2)))), 1787, nestedTuplesNeqCost3, 1787, Seq.fill(4)(2097))(_.copy()) + verifyNeq((ge1, (t1, (b1, (preH1, (h1, h1))))), (ge1, (t1, (b1, (preH1, (h1, h2))))), 1788, nestedTuplesNeqCost4, 1788, Seq.fill(4)(2114))(_.copy()) - verifyNeq(((ge1, t1), t1), ((ge1, t1), t2), 1785, nestedTuplesNeqCost5, 1785, 2059 +: Seq.fill(3)(2063))(_.copy()) - verifyNeq((((ge1, t1), b1), b1), (((ge1, t1), b1), b2), 1786, nestedTuplesNeqCost6, 1786, 2076 +: Seq.fill(3)(2080))(_.copy()) - verifyNeq((((ge1, t1), b1), (preH1, preH1)), (((ge1, t1), b1), (preH1, preH2)), 1787, nestedTuplesNeqCost7, 1787, 2093 +: Seq.fill(3)(2097))(_.copy()) - verifyNeq((((ge1, t1), b1), (preH1, (h1, h1))), (((ge1, t1), b1), (preH1, (h1, h2))), 1788, nestedTuplesNeqCost8, 1788, 2110 +: Seq.fill(3)(2114))(_.copy()) + verifyNeq(((ge1, t1), t1), ((ge1, t1), t2), 1785, nestedTuplesNeqCost5, 1785, Seq.fill(4)(2063))(_.copy()) + verifyNeq((((ge1, t1), b1), b1), (((ge1, t1), b1), b2), 1786, nestedTuplesNeqCost6, 1786, Seq.fill(4)(2080))(_.copy()) + verifyNeq((((ge1, t1), b1), (preH1, preH1)), (((ge1, t1), b1), (preH1, preH2)), 1787, nestedTuplesNeqCost7, 1787, Seq.fill(4)(2097))(_.copy()) + verifyNeq((((ge1, t1), b1), (preH1, (h1, h1))), (((ge1, t1), b1), (preH1, (h1, h2))), 1788, nestedTuplesNeqCost8, 1788, Seq.fill(4)(2114))(_.copy()) } property("NEQ of collections of pre-defined types") { @@ -2267,71 +2267,71 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => ast.SeqCostItem(NamedDesc("EQ_COA_Box"), PerItemCost(JitCost(15), JitCost(5), 1), 0) ) implicit val evalSettings = suite.evalSettings.copy(isMeasureOperationTime = false) - verifyNeq(Coll[Byte](), Coll(1.toByte), 1766, collNeqCost1, 1766, 2016 +: Seq.fill(3)(2018))(cloneColl(_)) + verifyNeq(Coll[Byte](), Coll(1.toByte), 1766, collNeqCost1, 1766, Seq.fill(4)(2018))(cloneColl(_)) verifyNeq(Coll[Byte](0, 1), Coll(1.toByte, 1.toByte), 1768, Array( FixedCostItem(NamedDesc("MatchType"), FixedCost(JitCost(1))), ast.SeqCostItem(NamedDesc("EQ_COA_Byte"), PerItemCost(JitCost(15), JitCost(2), 128), 1)), 1768, - 2018 +: Seq.fill(3)(2020) + Seq.fill(4)(2020) )(cloneColl(_)) - verifyNeq(Coll[Short](), Coll(1.toShort), 1766, collNeqCost1, 1766, 2016 +: Seq.fill(3)(2018))(cloneColl(_)) + verifyNeq(Coll[Short](), Coll(1.toShort), 1766, collNeqCost1, 1766, Seq.fill(4)(2018))(cloneColl(_)) verifyNeq(Coll[Short](0), Coll(1.toShort), 1768, Array( FixedCostItem(NamedDesc("MatchType"), FixedCost(JitCost(1))), ast.SeqCostItem(NamedDesc("EQ_COA_Short"), PerItemCost(JitCost(15), JitCost(2), 96), 1)), 1768, - 2018 +: Seq.fill(3)(2020) + Seq.fill(4)(2020) )(cloneColl(_)) - verifyNeq(Coll[Int](), Coll(1), 1766, collNeqCost1, 1766, 2016 +: Seq.fill(3)(2018))(cloneColl(_)) + verifyNeq(Coll[Int](), Coll(1), 1766, collNeqCost1, 1766, Seq.fill(4)(2018))(cloneColl(_)) verifyNeq(Coll[Int](0), Coll(1), 1768, Array( FixedCostItem(NamedDesc("MatchType"), FixedCost(JitCost(1))), ast.SeqCostItem(NamedDesc("EQ_COA_Int"), PerItemCost(JitCost(15), JitCost(2), 64), 1)), 1768, - 2018 +: Seq.fill(3)(2020) + Seq.fill(4)(2020) )(cloneColl(_)) - verifyNeq(Coll[Long](), Coll(1.toLong), 1766, collNeqCost1, 1766, 2016 +: Seq.fill(3)(2018))(cloneColl(_)) + verifyNeq(Coll[Long](), Coll(1.toLong), 1766, collNeqCost1, 1766, Seq.fill(4)(2018))(cloneColl(_)) verifyNeq(Coll[Long](0), Coll(1.toLong), 1768, Array( FixedCostItem(NamedDesc("MatchType"), FixedCost(JitCost(1))), ast.SeqCostItem(NamedDesc("EQ_COA_Long"), PerItemCost(JitCost(15), JitCost(2), 48), 1)), 1768, - 2018 +: Seq.fill(3)(2020) + Seq.fill(4)(2020) )(cloneColl(_)) prepareSamples[Coll[BigInt]] - verifyNeq(Coll[BigInt](), Coll(1.toBigInt), 1766, collNeqCost1, 1766, 2016 +: Seq.fill(3)(2018))(cloneColl(_)) + verifyNeq(Coll[BigInt](), Coll(1.toBigInt), 1766, collNeqCost1, 1766, Seq.fill(4)(2018))(cloneColl(_)) verifyNeq(Coll[BigInt](0.toBigInt), Coll(1.toBigInt), 1768, Array( FixedCostItem(NamedDesc("MatchType"), FixedCost(JitCost(1))), ast.SeqCostItem(NamedDesc("EQ_COA_BigInt"), PerItemCost(JitCost(15), JitCost(7), 5), 1)), 1768, - 2018 +: Seq.fill(3)(2020) + Seq.fill(4)(2020) )(cloneColl(_)) prepareSamples[Coll[GroupElement]] - verifyNeq(Coll[GroupElement](), Coll(ge1), 1766, collNeqCost1, 1766, 2016 +: Seq.fill(3)(2018))(cloneColl(_)) + verifyNeq(Coll[GroupElement](), Coll(ge1), 1766, collNeqCost1, 1766, Seq.fill(4)(2018))(cloneColl(_)) verifyNeq(Coll[GroupElement](ge1), Coll(ge2), 1768, Array( FixedCostItem(NamedDesc("MatchType"), FixedCost(JitCost(1))), ast.SeqCostItem(NamedDesc("EQ_COA_GroupElement"), PerItemCost(JitCost(15), JitCost(5), 1), 1)), 1768, - 2018 +: Seq.fill(3)(2020) + Seq.fill(4)(2020) )(cloneColl(_)) prepareSamples[Coll[AvlTree]] - verifyNeq(Coll[AvlTree](), Coll(t1), 1766, collNeqCost1, 1766, 2024 +: Seq.fill(3)(2028))(cloneColl(_)) + verifyNeq(Coll[AvlTree](), Coll(t1), 1766, collNeqCost1, 1766, Seq.fill(4)(2028))(cloneColl(_)) verifyNeq(Coll[AvlTree](t1), Coll(t2), 1768, Array( FixedCostItem(NamedDesc("MatchType"), FixedCost(JitCost(1))), ast.SeqCostItem(NamedDesc("EQ_COA_AvlTree"), PerItemCost(JitCost(15), JitCost(5), 2), 1)), 1768, - 2026 +: Seq.fill(3)(2030) + Seq.fill(4)(2030) )(cloneColl(_)) { // since SBox.isConstantSize = false, the cost is different among cases @@ -2340,11 +2340,11 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => val y = Coll(b1) val copied_x = cloneColl(x) verifyOp(Seq( - (x, x) -> Expected(Success(false), 1768, costNEQ(collNeqCost2), 1768, 2026 +: Seq.fill(3)(2030)), - (x, copied_x) -> Expected(Success(false), 1768, costNEQ(collNeqCost2), 1768, 2026 +: Seq.fill(3)(2030)), - (copied_x, x) -> Expected(Success(false), 1768, costNEQ(collNeqCost2), 1768, 2026 +: Seq.fill(3)(2030)), - (x, y) -> Expected(Success(true), 1766, costNEQ(collNeqCost1), 1766, 2024 +: Seq.fill(3)(2028)), - (y, x) -> Expected(Success(true), 1766, costNEQ(collNeqCost1), 1766, 2024 +: Seq.fill(3)(2028)) + (x, x) -> Expected(Success(false), 1768, costNEQ(collNeqCost2), 1768, Seq.fill(4)(2030)), + (x, copied_x) -> Expected(Success(false), 1768, costNEQ(collNeqCost2), 1768, Seq.fill(4)(2030)), + (copied_x, x) -> Expected(Success(false), 1768, costNEQ(collNeqCost2), 1768, Seq.fill(4)(2030)), + (x, y) -> Expected(Success(true), 1766, costNEQ(collNeqCost1), 1766, Seq.fill(4)(2028)), + (y, x) -> Expected(Success(true), 1766, costNEQ(collNeqCost1), 1766, Seq.fill(4)(2028)) ), "!=", NEQ.apply)(_ != _, generateCases = false) @@ -2353,27 +2353,27 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => FixedCostItem(NamedDesc("MatchType"), FixedCost(JitCost(1))), ast.SeqCostItem(NamedDesc("EQ_COA_Box"), PerItemCost(JitCost(15), JitCost(5), 1), 1)), 1768, - 2026 +: Seq.fill(3)(2030) + Seq.fill(4)(2030) )(cloneColl(_), generateCases = false) } prepareSamples[Coll[PreHeader]] - verifyNeq(Coll[PreHeader](), Coll(preH1), 1766, collNeqCost1, 1766, 2024 +: Seq.fill(3)(2028))(cloneColl(_)) + verifyNeq(Coll[PreHeader](), Coll(preH1), 1766, collNeqCost1, 1766, Seq.fill(4)(2028))(cloneColl(_)) verifyNeq(Coll[PreHeader](preH1), Coll(preH2), 1768, Array( FixedCostItem(NamedDesc("MatchType"), FixedCost(JitCost(1))), ast.SeqCostItem(NamedDesc("EQ_COA_PreHeader"), PerItemCost(JitCost(15), JitCost(3), 1), 1)), 1768, - 2026 +: Seq.fill(3)(2030) + Seq.fill(4)(2030) )(cloneColl(_)) prepareSamples[Coll[Header]] - verifyNeq(Coll[Header](), Coll(h1), 1766, collNeqCost1, 1766, 2024 +: Seq.fill(3)(2028))(cloneColl(_)) + verifyNeq(Coll[Header](), Coll(h1), 1766, collNeqCost1, 1766, Seq.fill(4)(2028))(cloneColl(_)) verifyNeq(Coll[Header](h1), Coll(h2), 1768, Array( FixedCostItem(NamedDesc("MatchType"), FixedCost(JitCost(1))), ast.SeqCostItem(NamedDesc("EQ_COA_Header"), PerItemCost(JitCost(15), JitCost(5), 1), 1)), - 1768, 2026 +: Seq.fill(3)(2030) + 1768, Seq.fill(4)(2030) )(cloneColl(_)) } @@ -2397,10 +2397,10 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => ast.SeqCostItem(NamedDesc("EQ_COA_Int"), PerItemCost(JitCost(15), JitCost(2), 64), 1), ast.SeqCostItem(NamedDesc("EQ_Coll"), PerItemCost(JitCost(10), JitCost(2), 1), 1) ) - verifyNeq(Coll[Coll[Int]](), Coll(Coll[Int]()), 1766, nestedNeq1, 1766, 2016 +: Seq.fill(3)(2018))(cloneColl(_)) - verifyNeq(Coll(Coll[Int]()), Coll(Coll[Int](1)), 1767, nestedNeq2, 1767, 2017 +: Seq.fill(3)(2019))(cloneColl(_)) - verifyNeq(Coll(Coll[Int](1)), Coll(Coll[Int](2)), 1769, nestedNeq3, 1769, 2019 +: Seq.fill(3)(2021))(cloneColl(_)) - verifyNeq(Coll(Coll[Int](1)), Coll(Coll[Int](1, 2)), 1767, nestedNeq2, 1767, 2017 +: Seq.fill(3)(2019))(cloneColl(_)) + verifyNeq(Coll[Coll[Int]](), Coll(Coll[Int]()), 1766, nestedNeq1, 1766, Seq.fill(4)(2018))(cloneColl(_)) + verifyNeq(Coll(Coll[Int]()), Coll(Coll[Int](1)), 1767, nestedNeq2, 1767, Seq.fill(4)(2019))(cloneColl(_)) + verifyNeq(Coll(Coll[Int](1)), Coll(Coll[Int](2)), 1769, nestedNeq3, 1769, Seq.fill(4)(2021))(cloneColl(_)) + verifyNeq(Coll(Coll[Int](1)), Coll(Coll[Int](1, 2)), 1767, nestedNeq2, 1767, Seq.fill(4)(2019))(cloneColl(_)) prepareSamples[Coll[(Int, BigInt)]] prepareSamples[Coll[Coll[(Int, BigInt)]]] @@ -2443,8 +2443,8 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => ast.SeqCostItem(NamedDesc("EQ_Coll"), PerItemCost(JitCost(10), JitCost(2), 1), 1), ast.SeqCostItem(NamedDesc("EQ_Coll"), PerItemCost(JitCost(10), JitCost(2), 1), 1) ) - verifyNeq(Coll(Coll((1, 10.toBigInt))), Coll(Coll((1, 11.toBigInt))), 1770, nestedNeq4, 1770, 2044 +: Seq.fill(3)(2048))(cloneColl(_)) - verifyNeq(Coll(Coll(Coll((1, 10.toBigInt)))), Coll(Coll(Coll((1, 11.toBigInt)))), 1771, nestedNeq5, 1771, 2053 +: Seq.fill(3)(2057))(cloneColl(_)) + verifyNeq(Coll(Coll((1, 10.toBigInt))), Coll(Coll((1, 11.toBigInt))), 1770, nestedNeq4, 1770, Seq.fill(4)(2048))(cloneColl(_)) + verifyNeq(Coll(Coll(Coll((1, 10.toBigInt)))), Coll(Coll(Coll((1, 11.toBigInt)))), 1771, nestedNeq5, 1771, Seq.fill(4)(2057))(cloneColl(_)) verifyNeq( (Coll( (Coll( @@ -2459,14 +2459,14 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => 1774, nestedNeq6, 1774, - 2096 +: Seq.fill(3)(2100) + Seq.fill(4)(2100) )(x => (cloneColl(x._1), x._2)) } property("GroupElement.getEncoded equivalence") { verifyCases( { - def success[T](v: T) = Expected(Success(v), 1790, methodCostDetails(SGroupElementMethods.GetEncodedMethod, 250), 1790, 2024 +: Seq.fill(3)(2026)) + def success[T](v: T) = Expected(Success(v), 1790, methodCostDetails(SGroupElementMethods.GetEncodedMethod, 250), 1790, Seq.fill(4)(2026)) Seq( (ge1, success(Helpers.decodeBytes(ge1str))), (ge2, success(Helpers.decodeBytes(ge2str))), @@ -2497,7 +2497,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => FixedCostItem(NamedDesc("EQ_GroupElement"), FixedCost(JitCost(172))) ) ) - def success[T](v: T) = Expected(Success(v), 1837, costDetails, 1837, 2079 +: Seq.fill(3)(2081)) + def success[T](v: T) = Expected(Success(v), 1837, costDetails, 1837, Seq.fill(4)(2081)) Seq( (ge1, success(true)), (ge2, success(true)), @@ -2527,7 +2527,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => property("GroupElement.negate equivalence") { verifyCases( { - def success[T](v: T) = Expected(Success(v), 1785, methodCostDetails(SGroupElementMethods.NegateMethod, 45), 1785, 2019 +: Seq.fill(3)(2021)) + def success[T](v: T) = Expected(Success(v), 1785, methodCostDetails(SGroupElementMethods.NegateMethod, 45), 1785, Seq.fill(4)(2021)) Seq( (ge1, success(Helpers.decodeGroupElement("02358d53f01276211f92d0aefbd278805121d4ff6eb534b777af1ee8abae5b2056"))), (ge2, success(Helpers.decodeGroupElement("03dba7b94b111f3894e2f9120b577da595ec7d58d488485adf73bf4e153af63575"))), @@ -2570,7 +2570,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => FixedCostItem(Exponentiate) ) ) - verifyCases(cases(1873, costDetails, 2119 +: Seq.fill(3)(2121)), + verifyCases(cases(1873, costDetails, Seq.fill(4)(2121)), existingFeature( scalaFunc, script, @@ -2597,7 +2597,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => FixedCostItem(SGroupElementMethods.ExponentiateMethod, FixedCost(JitCost(900))) ) ) - verifyCases(cases(1873, costDetails, 2119 +: Seq.fill(3)(2121)), + verifyCases(cases(1873, costDetails, Seq.fill(4)(2121)), existingFeature( scalaFunc, script, @@ -2644,7 +2644,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => ) ) ) - def success[T](v: T) = Expected(Success(v), 1787, costDetails, 1787, 2029 +: Seq.fill(3)(2031)) + def success[T](v: T) = Expected(Success(v), 1787, costDetails, 1787, Seq.fill(4)(2031)) Seq( ((ge1, Helpers.decodeGroupElement("03e132ca090614bd6c9f811e91f6daae61f16968a1e6c694ed65aacd1b1092320e")), success(Helpers.decodeGroupElement("02bc48937b4a66f249a32dfb4d2efd0743dc88d46d770b8c5d39fd03325ba211df"))), @@ -2707,7 +2707,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => } verifyCases( { - def success[T](v: T) = Expected(Success(v), 1767, methodCostDetails(SAvlTreeMethods.digestMethod, 15), 1767, 2001 +: Seq.fill(3)(2003)) + def success[T](v: T) = Expected(Success(v), 1767, methodCostDetails(SAvlTreeMethods.digestMethod, 15), 1767, Seq.fill(4)(2003)) Seq( (t1, success(Helpers.decodeBytes("000183807f66b301530120ff7fc6bd6601ff01ff7f7d2bedbbffff00187fe89094"))), (t2, success(Helpers.decodeBytes("ff000d937f80ffd731ed802d24358001ff8080ff71007f00ad37e0a7ae43fff95b"))), @@ -2720,7 +2720,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( { - def success[T](v: T) = Expected(Success(v), 1765, methodCostDetails(SAvlTreeMethods.enabledOperationsMethod, 15), 1765, 1999 +: Seq.fill(3)(2001)) + def success[T](v: T) = Expected(Success(v), 1765, methodCostDetails(SAvlTreeMethods.enabledOperationsMethod, 15), 1765, Seq.fill(4)(2001)) Seq( (t1, success(6.toByte)), (t2, success(0.toByte)), @@ -2733,7 +2733,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( { - def success[T](v: T) = Expected(Success(v), 1765, methodCostDetails(SAvlTreeMethods.keyLengthMethod, 15), 1765, 1999 +: Seq.fill(3)(2001)) + def success[T](v: T) = Expected(Success(v), 1765, methodCostDetails(SAvlTreeMethods.keyLengthMethod, 15), 1765, Seq.fill(4)(2001)) Seq( (t1, success(1)), (t2, success(32)), @@ -2748,9 +2748,9 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => { def success[T](v: T, newCost: Int, expectedV3Costs: Seq[Int]) = Expected(Success(v), newCost, methodCostDetails(SAvlTreeMethods.valueLengthOptMethod, 15), newCost, expectedV3Costs) Seq( - (t1, success(Some(1), 1766, 2000 +: Seq.fill(3)(2002))), - (t2, success(Some(64), 1766, 2000 +: Seq.fill(3)(2002))), - (t3, success(None, 1765, 1999 +: Seq.fill(3)(2001))) + (t1, success(Some(1), 1766, Seq.fill(4)(2002))), + (t2, success(Some(64), 1766, Seq.fill(4)(2002))), + (t3, success(None, 1765, Seq.fill(4)(2001))) ) }, existingFeature((t: AvlTree) => t.valueLengthOpt, @@ -2759,7 +2759,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( { - def success[T](v: T) = Expected(Success(v), 1765, methodCostDetails(SAvlTreeMethods.isInsertAllowedMethod, 15), 1765, 1999 +: Seq.fill(3)(2001)) + def success[T](v: T) = Expected(Success(v), 1765, methodCostDetails(SAvlTreeMethods.isInsertAllowedMethod, 15), 1765, Seq.fill(4)(2001)) Seq( (t1, success(false)), (t2, success(false)), @@ -2772,7 +2772,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( { - def success[T](v: T) = Expected(Success(v), 1765, methodCostDetails(SAvlTreeMethods.isUpdateAllowedMethod, 15), 1765, 1999 +: Seq.fill(3)(2001)) + def success[T](v: T) = Expected(Success(v), 1765, methodCostDetails(SAvlTreeMethods.isUpdateAllowedMethod, 15), 1765, Seq.fill(4)(2001)) Seq( (t1, success(true)), (t2, success(false)), @@ -2785,7 +2785,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( { - def success[T](v: T) = Expected(Success(v), 1765, methodCostDetails(SAvlTreeMethods.isRemoveAllowedMethod, 15), 1765, 1999 +: Seq.fill(3)(2001)) + def success[T](v: T) = Expected(Success(v), 1765, methodCostDetails(SAvlTreeMethods.isRemoveAllowedMethod, 15), 1765, Seq.fill(4)(2001)) Seq( (t1, success(true)), (t2, success(false)), @@ -3040,7 +3040,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => ) ) - getMany.checkExpected(input, Expected(Success(expRes), 1845, costDetails, 1845, 2135 +: Seq.fill(3)(2139))) + getMany.checkExpected(input, Expected(Success(expRes), 1845, costDetails, 1845, Seq.fill(4)(2139))) } val key = Colls.fromArray(Array[Byte](-16,-128,99,86,1,-128,-36,-83,109,72,-124,-114,1,-32,15,127,-30,125,127,1,-102,-53,-53,-128,-107,0,64,8,1,127,22,1)) @@ -3118,7 +3118,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => // positive test { val input = (tree, (key, proof)) - val expectedV3Costs: Seq[Int] = 2078 +: Seq.fill(3)(2082) + val expectedV3Costs: Seq[Int] = Seq.fill(4)(2082) contains.checkExpected(input, Expected(Success(okContains), 1790, costDetails(105 + additionalDetails), 1790, expectedV3Costs)) get.checkExpected(input, Expected(Success(valueOpt), 1790 + additionalCost, costDetails(105 + additionalDetails), 1790 + additionalCost, expectedV3Costs.map(additionalCost + _))) } @@ -3128,7 +3128,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => { val input = (tree, (keys, proof)) - val expectedV3Costs: Seq[Int] = (2081 + additionalCost) +: Seq.fill(3)(2085 + additionalCost) + val expectedV3Costs: Seq[Int] = Seq.fill(4)(2085 + additionalCost) getMany.checkExpected(input, Expected(Success(expRes), 1791 + additionalCost, costDetails(105 + additionalDetails), 1791 + additionalCost, expectedV3Costs)) } @@ -3136,7 +3136,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => val input = (tree, digest) val (res, _) = updateDigest.checkEquality(input).getOrThrow res.digest shouldBe digest - updateDigest.checkExpected(input, Expected(Success(res), 1771, updateDigestCostDetails, 1771, 2027 +: Seq.fill(3)(2029))) + updateDigest.checkExpected(input, Expected(Success(res), 1771, updateDigestCostDetails, 1771, Seq.fill(4)(2029))) } val newOps = 1.toByte @@ -3145,7 +3145,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => val input = (tree, newOps) val (res,_) = updateOperations.checkEquality(input).getOrThrow res.enabledOperations shouldBe newOps - updateOperations.checkExpected(input, Expected(Success(res), 1771, updateOperationsCostDetails, 1771, 2023 +: Seq.fill(3)(2025))) + updateOperations.checkExpected(input, Expected(Success(res), 1771, updateOperationsCostDetails, 1771, Seq.fill(4)(2025))) } // negative tests: invalid proof @@ -3155,7 +3155,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => val input = (tree, (key, invalidProof)) val (res, _) = contains.checkEquality(input).getOrThrow res shouldBe false - contains.checkExpected(input, Expected(Success(res), 1790, costDetails(105 + additionalDetails), 1790, 2078 +: Seq.fill(3)(2082))) + contains.checkExpected(input, Expected(Success(res), 1790, costDetails(105 + additionalDetails), 1790, Seq.fill(4)(2082))) } { @@ -3308,7 +3308,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => val input = (preInsertTree, (kvs, insertProof)) val (res, _) = insert.checkEquality(input).getOrThrow res.isDefined shouldBe true - insert.checkExpected(input, Expected(Success(res), 1796, costDetails2, 1796, 2098 +: Seq.fill(3)(2102))) + insert.checkExpected(input, Expected(Success(res), 1796, costDetails2, 1796, Seq.fill(4)(2102))) } { // negative: readonly tree @@ -3316,7 +3316,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => val input = (readonlyTree, (kvs, insertProof)) val (res, _) = insert.checkEquality(input).getOrThrow res.isDefined shouldBe false - insert.checkExpected(input, Expected(Success(res), 1772, costDetails1, 1772, 2074 +: Seq.fill(3)(2078))) + insert.checkExpected(input, Expected(Success(res), 1772, costDetails1, 1772, Seq.fill(4)(2078))) } { // negative: invalid key @@ -3326,7 +3326,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => val input = (tree, (invalidKvs, insertProof)) val (res, _) = insert.checkEquality(input).getOrThrow res.isDefined shouldBe true // TODO v6.0: should it really be true? (looks like a bug) (see https://github.com/ScorexFoundation/sigmastate-interpreter/issues/908) - insert.checkExpected(input, Expected(Success(res), 1796, costDetails2, 1796, 2098 +: Seq.fill(3)(2102))) + insert.checkExpected(input, Expected(Success(res), 1796, costDetails2, 1796, Seq.fill(4)(2102))) } { // negative: invalid proof @@ -3456,7 +3456,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => val endTree = preUpdateTree.updateDigest(endDigest) val input = (preUpdateTree, (kvs, updateProof)) val res = Some(endTree) - update.checkExpected(input, Expected(Success(res), 1805, costDetails2, 1805, 2107 +: Seq.fill(3)(2111))) + update.checkExpected(input, Expected(Success(res), 1805, costDetails2, 1805, Seq.fill(4)(2111))) } { // positive: update to the same value (identity operation) @@ -3464,13 +3464,13 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => val keys = Colls.fromItems((key -> value)) val input = (tree, (keys, updateProof)) val res = Some(tree) - update.checkExpected(input, Expected(Success(res), 1805, costDetails2, 1805, 2107 +: Seq.fill(3)(2111))) + update.checkExpected(input, Expected(Success(res), 1805, costDetails2, 1805, Seq.fill(4)(2111))) } { // negative: readonly tree val readonlyTree = createTree(preUpdateDigest) val input = (readonlyTree, (kvs, updateProof)) - update.checkExpected(input, Expected(Success(None), 1772, costDetails1, 1772, 2074 +: Seq.fill(3)(2078))) + update.checkExpected(input, Expected(Success(None), 1772, costDetails1, 1772, Seq.fill(4)(2078))) } { // negative: invalid key @@ -3478,7 +3478,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => val invalidKey = key.map(x => (-x).toByte) // any other different from key val invalidKvs = Colls.fromItems((invalidKey -> newValue)) val input = (tree, (invalidKvs, updateProof)) - update.checkExpected(input, Expected(Success(None), 1801, costDetails3, 1801, 2103 +: Seq.fill(3)(2107))) + update.checkExpected(input, Expected(Success(None), 1801, costDetails3, 1801, Seq.fill(4)(2107))) } { // negative: invalid value (different from the value in the proof) @@ -3488,14 +3488,14 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => val input = (tree, (invalidKvs, updateProof)) val (res, _) = update.checkEquality(input).getOrThrow res.isDefined shouldBe true // TODO v6.0: should it really be true? (looks like a bug) (see https://github.com/ScorexFoundation/sigmastate-interpreter/issues/908) - update.checkExpected(input, Expected(Success(res), 1805, costDetails2, 1805, 2107 +: Seq.fill(3)(2111))) + update.checkExpected(input, Expected(Success(res), 1805, costDetails2, 1805, Seq.fill(4)(2111))) } { // negative: invalid proof val tree = createTree(preUpdateDigest, updateAllowed = true) val invalidProof = updateProof.map(x => (-x).toByte) // any other different from proof val input = (tree, (kvs, invalidProof)) - update.checkExpected(input, Expected(Success(None), 1801, costDetails3, 1801, 2103 +: Seq.fill(3)(2107))) + update.checkExpected(input, Expected(Success(None), 1801, costDetails3, 1801, Seq.fill(4)(2107))) } } @@ -3606,7 +3606,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => val endTree = preRemoveTree.updateDigest(endDigest) val input = (preRemoveTree, (Colls.fromArray(keysToRemove), removeProof)) val res = Some(endTree) - remove.checkExpected(input, Expected(Success(res), 1832, costDetails1, 1832, 2122 +: Seq.fill(3)(2126))) + remove.checkExpected(input, Expected(Success(res), 1832, costDetails1, 1832, Seq.fill(4)(2126))) } { @@ -3623,13 +3623,13 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => val endTree = preRemoveTree.updateDigest(endDigest) val input = (preRemoveTree, (keys, removeProof)) val res = Some(endTree) - remove.checkExpected(input, Expected(Success(res), 1806, costDetails2, 1806, 2096 +: Seq.fill(3)(2100))) + remove.checkExpected(input, Expected(Success(res), 1806, costDetails2, 1806, Seq.fill(4)(2100))) } { // negative: readonly tree val readonlyTree = createTree(preRemoveDigest) val input = (readonlyTree, (keys, removeProof)) - remove.checkExpected(input, Expected(Success(None), 1772, costDetails3, 1772, 2062 +: Seq.fill(3)(2066))) + remove.checkExpected(input, Expected(Success(None), 1772, costDetails3, 1772, Seq.fill(4)(2066))) } { // negative: invalid key @@ -3637,14 +3637,14 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => val invalidKey = key.map(x => (-x).toByte) // any other different from `key` val invalidKeys = Colls.fromItems(invalidKey) val input = (tree, (invalidKeys, removeProof)) - remove.checkExpected(input, Expected(Success(None), 1802, costDetails4, 1802, 2092 +: Seq.fill(3)(2096))) + remove.checkExpected(input, Expected(Success(None), 1802, costDetails4, 1802, Seq.fill(4)(2096))) } { // negative: invalid proof val tree = createTree(preRemoveDigest, removeAllowed = true) val invalidProof = removeProof.map(x => (-x).toByte) // any other different from `removeProof` val input = (tree, (keys, invalidProof)) - remove.checkExpected(input, Expected(Success(None), 1802, costDetails4, 1802, 2092 +: Seq.fill(3)(2096))) + remove.checkExpected(input, Expected(Success(None), 1802, costDetails4, 1802, Seq.fill(4)(2096))) } } } @@ -3653,7 +3653,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => val costDetails = CostDetails(traceBase :+ FixedCostItem(CompanionDesc(LongToByteArray), FixedCost(JitCost(17)))) verifyCases( { - def success[T](v: T) = Expected(Success(v), 1767, costDetails, 1767, 1997 +: Seq.fill(3)(1999)) + def success[T](v: T) = Expected(Success(v), 1767, costDetails, 1767, Seq.fill(4)(1999)) Seq( (-9223372036854775808L, success(Helpers.decodeBytes("8000000000000000"))), (-1148502660425090565L, success(Helpers.decodeBytes("f00fb2ea55c579fb"))), @@ -3673,7 +3673,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => val costDetails = CostDetails(traceBase :+ FixedCostItem(CompanionDesc(ByteArrayToBigInt), FixedCost(JitCost(30)))) verifyCases( { - def success[T](v: T) = Expected(Success(v), 1767, costDetails, 1767, 1997 +: Seq.fill(3)(1999)) + def success[T](v: T) = Expected(Success(v), 1767, costDetails, 1767, Seq.fill(4)(1999)) Seq( (Helpers.decodeBytes(""), Expected(new NumberFormatException("Zero length BigInteger"))), @@ -3684,9 +3684,9 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => (Helpers.decodeBytes("ff"), success(CBigInt(new BigInteger("-1", 16)))), (Helpers.decodeBytes("80d6c201"), - Expected(Success(CBigInt(new BigInteger("-7f293dff", 16))), 1767, costDetails, 1767, 1997 +: Seq.fill(3)(1999))), + Expected(Success(CBigInt(new BigInteger("-7f293dff", 16))), 1767, costDetails, 1767, Seq.fill(4)(1999))), (Helpers.decodeBytes("70d6c20170d6c201"), - Expected(Success(CBigInt(new BigInteger("70d6c20170d6c201", 16))), 1767, costDetails, 1767, 1997 +: Seq.fill(3)(1999))), + Expected(Success(CBigInt(new BigInteger("70d6c20170d6c201", 16))), 1767, costDetails, 1767, Seq.fill(4)(1999))), (Helpers.decodeBytes( "80e0ff7f02807fff72807f0a00ff7fb7c57f75c11ba2802970fd250052807fc37f6480ffff007fff18eeba44" ), Expected(new ArithmeticException("BigInteger out of 256 bit range"))) @@ -3701,7 +3701,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => val costDetails = CostDetails(traceBase :+ FixedCostItem(CompanionDesc(ByteArrayToLong), FixedCost(JitCost(16)))) verifyCases( { - def success[T](v: T) = Expected(Success(v), 1765, costDetails, 1765, 1995 +: Seq.fill(3)(1997)) + def success[T](v: T) = Expected(Success(v), 1765, costDetails, 1765, Seq.fill(4)(1997)) Seq( (Helpers.decodeBytes(""), Expected(new IllegalArgumentException("array too small: 0 < 8"))), (Helpers.decodeBytes("81"), Expected(new IllegalArgumentException("array too small: 1 < 8"))), @@ -3723,7 +3723,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( { val costDetails = CostDetails(traceBase :+ FixedCostItem(CompanionDesc(ExtractId), FixedCost(JitCost(12)))) - def success[T](v: T) = Expected(Success(v), 1766, costDetails, 1766, 1996 +: Seq.fill(3)(1998)) + def success[T](v: T) = Expected(Success(v), 1766, costDetails, 1766, Seq.fill(4)(1998)) Seq( (b1, success(Helpers.decodeBytes("5ee78f30ae4e770e44900a46854e9fecb6b12e8112556ef1cd19aef633b4421e"))), (b2, success(Helpers.decodeBytes("3a0089be265460e29ca47d26e5b55a6f3e3ffaf5b4aed941410a2437913848ad"))) @@ -3736,7 +3736,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( { val costDetails = CostDetails(traceBase :+ FixedCostItem(CompanionDesc(ExtractAmount), FixedCost(JitCost(8)))) - def success[T](v: T) = Expected(Success(v), 1764, costDetails, 1764, 1994 +: Seq.fill(3)(1996)) + def success[T](v: T) = Expected(Success(v), 1764, costDetails, 1764, Seq.fill(4)(1996)) Seq( (b1, success(9223372036854775807L)), (b2, success(12345L)) @@ -3749,7 +3749,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( { val costDetails = CostDetails(traceBase :+ FixedCostItem(CompanionDesc(ExtractScriptBytes), FixedCost(JitCost(10)))) - def success[T](v: T) = Expected(Success(v), 1766, costDetails, 1766, 1996 +: Seq.fill(3)(1998)) + def success[T](v: T) = Expected(Success(v), 1766, costDetails, 1766, Seq.fill(4)(1998)) Seq( (b1, success(Helpers.decodeBytes( "100108cd0297c44a12f4eb99a85d298fa3ba829b5b42b9f63798c980ece801cc663cc5fc9e7300" @@ -3764,7 +3764,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( { val costDetails = CostDetails(traceBase :+ FixedCostItem(CompanionDesc(ExtractBytes), FixedCost(JitCost(12)))) - def success[T](v: T) = Expected(Success(v), 1766, costDetails, 1766, 1996 +: Seq.fill(3)(1998)) + def success[T](v: T) = Expected(Success(v), 1766, costDetails, 1766, Seq.fill(4)(1998)) Seq( (b1, success(Helpers.decodeBytes( "ffffffffffffffff7f100108cd0297c44a12f4eb99a85d298fa3ba829b5b42b9f63798c980ece801cc663cc5fc9e73009fac29026e789ab7b2fffff12280a6cd01557f6fb22b7f80ff7aff8e1f7f15973d7f000180ade204a3ff007f00057600808001ff8f8000019000ffdb806fff7cc0b6015eb37fa600f4030201000e067fc87f7f01ff218301ae8000018008637f0021fb9e00018055486f0b514121016a00ff718080bcb001" @@ -3781,7 +3781,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( { val costDetails = CostDetails(traceBase :+ FixedCostItem(CompanionDesc(ExtractBytesWithNoRef), FixedCost(JitCost(12)))) - def success[T](v: T) = Expected(Success(v), 1766, costDetails, 1766, 1996 +: Seq.fill(3)(1998)) + def success[T](v: T) = Expected(Success(v), 1766, costDetails, 1766, Seq.fill(4)(1998)) Seq( (b1, success(Helpers.decodeBytes( "ffffffffffffffff7f100108cd0297c44a12f4eb99a85d298fa3ba829b5b42b9f63798c980ece801cc663cc5fc9e73009fac29026e789ab7b2fffff12280a6cd01557f6fb22b7f80ff7aff8e1f7f15973d7f000180ade204a3ff007f00057600808001ff8f8000019000ffdb806fff7cc0b6015eb37fa600f4030201000e067fc87f7f01ff" @@ -3798,7 +3798,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( { val costDetails = CostDetails(traceBase :+ FixedCostItem(CompanionDesc(ExtractCreationInfo), FixedCost(JitCost(16)))) - def success[T](v: T) = Expected(Success(v), 1767, costDetails, 1767, 1999 +: Seq.fill(3)(2001)) + def success[T](v: T) = Expected(Success(v), 1767, costDetails, 1767, Seq.fill(4)(2001)) Seq( (b1, success(( 677407, @@ -3821,8 +3821,8 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => b1 -> Expected(Success(Coll[(Coll[Byte], Long)]( (Helpers.decodeBytes("6e789ab7b2fffff12280a6cd01557f6fb22b7f80ff7aff8e1f7f15973d7f0001"), 10000000L), (Helpers.decodeBytes("a3ff007f00057600808001ff8f8000019000ffdb806fff7cc0b6015eb37fa600"), 500L) - ).map(identity)), 1772, methodCostDetails(SBoxMethods.tokensMethod, 15), 1772, 2010 +: Seq.fill(3)(2012)), - b2 -> Expected(Success(Coll[(Coll[Byte], Long)]().map(identity)), 1766, methodCostDetails(SBoxMethods.tokensMethod, 15), 1766, 2004 +: Seq.fill(3)(2006)) + ).map(identity)), 1772, methodCostDetails(SBoxMethods.tokensMethod, 15), 1772, Seq.fill(4)(2012)), + b2 -> Expected(Success(Coll[(Coll[Byte], Long)]().map(identity)), 1766, methodCostDetails(SBoxMethods.tokensMethod, 15), 1766, Seq.fill(4)(2006)) ), existingFeature({ (x: Box) => x.tokens }, "{ (x: Box) => x.tokens }", @@ -3891,11 +3891,11 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( Seq( - (box1, Expected(Success(1024.toShort), 1774, expCostDetails1, 1774, 2038 +: Seq.fill(3)(2042))), + (box1, Expected(Success(1024.toShort), 1774, expCostDetails1, 1774, Seq.fill(4)(2042))), (box2, Expected( new InvalidType("Cannot getReg[Short](5): invalid type of value TestValue(1048576) at id=5") )), - (box3, Expected(Success(0.toShort), 1772, expCostDetails2, 1772, 2036 +: Seq.fill(3)(2040))) + (box3, Expected(Success(0.toShort), 1772, expCostDetails2, 1772, Seq.fill(4)(2040))) ), existingFeature( { (x: Box) => @@ -4020,10 +4020,10 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( Seq( - (box1, Expected(Success(1024), cost = 1785, expCostDetails3, 1785, 2125 +: Seq.fill(3)(2129))), - (box2, Expected(Success(1024 * 1024), cost = 1786, expCostDetails4, 1786, 2126 +: Seq.fill(3)(2130))), - (box3, Expected(Success(0), cost = 1779, expCostDetails5, 1779, 2119 +: Seq.fill(3)(2123))), - (box4, Expected(Success(-1), cost = 1772, expCostDetails2, 1772, 2112 +: Seq.fill(3)(2116))) + (box1, Expected(Success(1024), cost = 1785, expCostDetails3, 1785, Seq.fill(4)(2129))), + (box2, Expected(Success(1024 * 1024), cost = 1786, expCostDetails4, 1786, Seq.fill(4)(2130))), + (box3, Expected(Success(0), cost = 1779, expCostDetails5, 1779, Seq.fill(4)(2123))), + (box4, Expected(Success(-1), cost = 1772, expCostDetails2, 1772, Seq.fill(4)(2116))) ), existingFeature( { (x: Box) => @@ -4117,7 +4117,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => ) verifyCases( Seq( - (box1, Expected(Success(1.toByte), cost = 1770, expCostDetails, 1770, 2006 +: Seq.fill(3)(2008))), + (box1, Expected(Success(1.toByte), cost = 1770, expCostDetails, 1770, Seq.fill(4)(2008))), (box2, Expected(new InvalidType("Cannot getReg[Byte](4): invalid type of value Value(Coll(1)) at id=4"))) ), existingFeature((x: Box) => x.R4[Byte].get, @@ -4129,7 +4129,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( Seq( - (box1, Expected(Success(1024.toShort), cost = 1770, expCostDetails, 1770, 2006 +: Seq.fill(3)(2008))), + (box1, Expected(Success(1024.toShort), cost = 1770, expCostDetails, 1770, Seq.fill(4)(2008))), (box2, Expected(new NoSuchElementException("None.get"))) ), existingFeature((x: Box) => x.R5[Short].get, @@ -4141,7 +4141,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( Seq( - (box1, Expected(Success(1024 * 1024), cost = 1770, expCostDetails, 1770, 2006 +: Seq.fill(3)(2008))) + (box1, Expected(Success(1024 * 1024), cost = 1770, expCostDetails, 1770, Seq.fill(4)(2008))) ), existingFeature((x: Box) => x.R6[Int].get, "{ (x: Box) => x.R6[Int].get }", @@ -4152,7 +4152,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( Seq( - (box1, Expected(Success(1024.toLong), cost = 1770, expCostDetails, 1770, 2006 +: Seq.fill(3)(2008))) + (box1, Expected(Success(1024.toLong), cost = 1770, expCostDetails, 1770, Seq.fill(4)(2008))) ), existingFeature((x: Box) => x.R7[Long].get, "{ (x: Box) => x.R7[Long].get }", @@ -4163,7 +4163,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( Seq( - (box1, Expected(Success(CBigInt(BigInteger.valueOf(222L))), cost = 1770, expCostDetails, 1770, 2006 +: Seq.fill(3)(2008))) + (box1, Expected(Success(CBigInt(BigInteger.valueOf(222L))), cost = 1770, expCostDetails, 1770, Seq.fill(4)(2008))) ), existingFeature((x: Box) => x.R8[BigInt].get, "{ (x: Box) => x.R8[BigInt].get }", @@ -4184,7 +4184,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => )), cost = 1770, expCostDetails, - 1770, 2006 +: Seq.fill(3)(2008)) + 1770, Seq.fill(4)(2008)) )), existingFeature((x: Box) => x.R9[AvlTree].get, "{ (x: Box) => x.R9[AvlTree].get }", @@ -4257,35 +4257,35 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( - Seq((preH1, Expected(Success(0.toByte), cost = 1765, methodCostDetails(SPreHeaderMethods.versionMethod, 10), 1765, 1999 +: Seq.fill(3)(2001)))), + Seq((preH1, Expected(Success(0.toByte), cost = 1765, methodCostDetails(SPreHeaderMethods.versionMethod, 10), 1765, Seq.fill(4)(2001)))), existingPropTest("version", { (x: PreHeader) => x.version })) verifyCases( Seq((preH1, Expected(Success( Helpers.decodeBytes("7fff7fdd6f62018bae0001006d9ca888ff7f56ff8006573700a167f17f2c9f40")), - cost = 1766, methodCostDetails(SPreHeaderMethods.parentIdMethod, 10), 1766, 2000 +: Seq.fill(3)(2002)))), + cost = 1766, methodCostDetails(SPreHeaderMethods.parentIdMethod, 10), 1766, Seq.fill(4)(2002)))), existingPropTest("parentId", { (x: PreHeader) => x.parentId })) verifyCases( - Seq((preH1, Expected(Success(6306290372572472443L), cost = 1765, methodCostDetails(SPreHeaderMethods.timestampMethod, 10), 1765, 1999 +: Seq.fill(3)(2001)))), + Seq((preH1, Expected(Success(6306290372572472443L), cost = 1765, methodCostDetails(SPreHeaderMethods.timestampMethod, 10), 1765, Seq.fill(4)(2001)))), existingPropTest("timestamp", { (x: PreHeader) => x.timestamp })) verifyCases( - Seq((preH1, Expected(Success(-3683306095029417063L), cost = 1765, methodCostDetails(SPreHeaderMethods.nBitsMethod, 10), 1765, 1999 +: Seq.fill(3)(2001)))), + Seq((preH1, Expected(Success(-3683306095029417063L), cost = 1765, methodCostDetails(SPreHeaderMethods.nBitsMethod, 10), 1765, Seq.fill(4)(2001)))), existingPropTest("nBits", { (x: PreHeader) => x.nBits })) verifyCases( - Seq((preH1, Expected(Success(1), cost = 1765, methodCostDetails(SPreHeaderMethods.heightMethod, 10), 1765, 1999 +: Seq.fill(3)(2001)))), + Seq((preH1, Expected(Success(1), cost = 1765, methodCostDetails(SPreHeaderMethods.heightMethod, 10), 1765, Seq.fill(4)(2001)))), existingPropTest("height", { (x: PreHeader) => x.height })) verifyCases( Seq((preH1, Expected(Success( Helpers.decodeGroupElement("026930cb9972e01534918a6f6d6b8e35bc398f57140d13eb3623ea31fbd069939b")), - cost = 1782, methodCostDetails(SPreHeaderMethods.minerPkMethod, 10), 1782, 2016 +: Seq.fill(3)(2018)))), + cost = 1782, methodCostDetails(SPreHeaderMethods.minerPkMethod, 10), 1782, Seq.fill(4)(2018)))), existingPropTest("minerPk", { (x: PreHeader) => x.minerPk })) verifyCases( - Seq((preH1, Expected(Success(Helpers.decodeBytes("ff8087")), cost = 1766, methodCostDetails(SPreHeaderMethods.votesMethod, 10), 1766, 2000 +: Seq.fill(3)(2002)))), + Seq((preH1, Expected(Success(Helpers.decodeBytes("ff8087")), cost = 1766, methodCostDetails(SPreHeaderMethods.votesMethod, 10), 1766, Seq.fill(4)(2002)))), existingPropTest("votes", { (x: PreHeader) => x.votes })) } @@ -4293,81 +4293,81 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( Seq((h1, Expected(Success( Helpers.decodeBytes("957f008001808080ffe4ffffc8f3802401df40006aa05e017fa8d3f6004c804a")), - cost = 1766, methodCostDetails(SHeaderMethods.idMethod, 10), 1766, 2000 +: Seq.fill(3)(2002)))), + cost = 1766, methodCostDetails(SHeaderMethods.idMethod, 10), 1766, Seq.fill(4)(2002)))), existingPropTest("id", { (x: Header) => x.id })) verifyCases( - Seq((h1, Expected(Success(0.toByte), cost = 1765, methodCostDetails(SHeaderMethods.versionMethod, 10), 1765, 1999 +: Seq.fill(3)(2001)))), + Seq((h1, Expected(Success(0.toByte), cost = 1765, methodCostDetails(SHeaderMethods.versionMethod, 10), 1765, Seq.fill(4)(2001)))), existingPropTest("version", { (x: Header) => x.version })) verifyCases( Seq((h1, Expected(Success( Helpers.decodeBytes("0180dd805b0000ff5400b997fd7f0b9b00de00fb03c47e37806a8186b94f07ff")), - cost = 1766, methodCostDetails(SHeaderMethods.parentIdMethod, 10), 1766, 2000 +: Seq.fill(3)(2002)))), + cost = 1766, methodCostDetails(SHeaderMethods.parentIdMethod, 10), 1766, Seq.fill(4)(2002)))), existingPropTest("parentId", { (x: Header) => x.parentId })) verifyCases( Seq((h1, Expected(Success( Helpers.decodeBytes("01f07f60d100ffb970c3007f60ff7f24d4070bb8fffa7fca7f34c10001ffe39d")), - cost = 1766, methodCostDetails(SHeaderMethods.ADProofsRootMethod, 10), 1766, 2000 +: Seq.fill(3)(2002)))), + cost = 1766, methodCostDetails(SHeaderMethods.ADProofsRootMethod, 10), 1766, Seq.fill(4)(2002)))), existingPropTest("ADProofsRoot", { (x: Header) => x.ADProofsRoot })) verifyCases( - Seq((h1, Expected(Success(CAvlTree(createAvlTreeData())), cost = 1765, methodCostDetails(SHeaderMethods.stateRootMethod, 10), 1765, 1999 +: Seq.fill(3)(2001)))), + Seq((h1, Expected(Success(CAvlTree(createAvlTreeData())), cost = 1765, methodCostDetails(SHeaderMethods.stateRootMethod, 10), 1765, Seq.fill(4)(2001)))), existingPropTest("stateRoot", { (x: Header) => x.stateRoot })) verifyCases( Seq((h1, Expected(Success( Helpers.decodeBytes("804101ff01000080a3ffbd006ac080098df132a7017f00649311ec0e00000100")), - cost = 1766, methodCostDetails(SHeaderMethods.transactionsRootMethod, 10), 1766, 2000 +: Seq.fill(3)(2002)))), + cost = 1766, methodCostDetails(SHeaderMethods.transactionsRootMethod, 10), 1766, Seq.fill(4)(2002)))), existingPropTest("transactionsRoot", { (x: Header) => x.transactionsRoot })) verifyCases( - Seq((h1, Expected(Success(1L), cost = 1765, methodCostDetails(SHeaderMethods.timestampMethod, 10), 1765, 1999 +: Seq.fill(3)(2001)))), + Seq((h1, Expected(Success(1L), cost = 1765, methodCostDetails(SHeaderMethods.timestampMethod, 10), 1765, Seq.fill(4)(2001)))), existingPropTest("timestamp", { (x: Header) => x.timestamp })) verifyCases( - Seq((h1, Expected(Success(-1L), cost = 1765, methodCostDetails(SHeaderMethods.nBitsMethod, 10), 1765, 1999 +: Seq.fill(3)(2001)))), + Seq((h1, Expected(Success(-1L), cost = 1765, methodCostDetails(SHeaderMethods.nBitsMethod, 10), 1765, Seq.fill(4)(2001)))), existingPropTest("nBits", { (x: Header) => x.nBits })) verifyCases( - Seq((h1, Expected(Success(1), cost = 1765, methodCostDetails(SHeaderMethods.heightMethod, 10), 1765, 1999 +: Seq.fill(3)(2001)))), + Seq((h1, Expected(Success(1), cost = 1765, methodCostDetails(SHeaderMethods.heightMethod, 10), 1765, Seq.fill(4)(2001)))), existingPropTest("height", { (x: Header) => x.height })) verifyCases( Seq((h1, Expected(Success( Helpers.decodeBytes("e57f80885601b8ff348e01808000bcfc767f2dd37f0d01015030ec018080bc62")), - cost = 1766, methodCostDetails(SHeaderMethods.extensionRootMethod, 10), 1766, 2000 +: Seq.fill(3)(2002)))), + cost = 1766, methodCostDetails(SHeaderMethods.extensionRootMethod, 10), 1766, Seq.fill(4)(2002)))), existingPropTest("extensionRoot", { (x: Header) => x.extensionRoot })) verifyCases( Seq((h1, Expected(Success( Helpers.decodeGroupElement("039bdbfa0b49cc6bef58297a85feff45f7bbeb500a9d2283004c74fcedd4bd2904")), - cost = 1782, methodCostDetails(SHeaderMethods.minerPkMethod, 10), 1782, 2016 +: Seq.fill(3)(2018)))), + cost = 1782, methodCostDetails(SHeaderMethods.minerPkMethod, 10), 1782, Seq.fill(4)(2018)))), existingPropTest("minerPk", { (x: Header) => x.minerPk })) verifyCases( Seq((h1, Expected(Success( Helpers.decodeGroupElement("0361299207fa392231e23666f6945ae3e867b978e021d8d702872bde454e9abe9c")), - cost = 1782, methodCostDetails(SHeaderMethods.powOnetimePkMethod, 10), 1782, 2016 +: Seq.fill(3)(2018)))), + cost = 1782, methodCostDetails(SHeaderMethods.powOnetimePkMethod, 10), 1782, Seq.fill(4)(2018)))), existingPropTest("powOnetimePk", { (x: Header) => x.powOnetimePk })) verifyCases( Seq((h1, Expected(Success( Helpers.decodeBytes("7f4f09012a807f01")), - cost = 1766, methodCostDetails(SHeaderMethods.powNonceMethod, 10), 1766, 2000 +: Seq.fill(3)(2002)))), + cost = 1766, methodCostDetails(SHeaderMethods.powNonceMethod, 10), 1766, Seq.fill(4)(2002)))), existingPropTest("powNonce", { (x: Header) => x.powNonce })) verifyCases( Seq((h1, Expected(Success( CBigInt(new BigInteger("-e24990c47e15ed4d0178c44f1790cc72155d516c43c3e8684e75db3800a288", 16))), - cost = 1765, methodCostDetails(SHeaderMethods.powDistanceMethod, 10), 1765, 1999 +: Seq.fill(3)(2001)))), + cost = 1765, methodCostDetails(SHeaderMethods.powDistanceMethod, 10), 1765, Seq.fill(4)(2001)))), existingPropTest("powDistance", { (x: Header) => x.powDistance })) verifyCases( Seq((h1, Expected(Success( Helpers.decodeBytes("7f0180")), - cost = 1766, methodCostDetails(SHeaderMethods.votesMethod, 10), 1766, 2000 +: Seq.fill(3)(2002)))), + cost = 1766, methodCostDetails(SHeaderMethods.votesMethod, 10), 1766, Seq.fill(4)(2002)))), existingPropTest("votes", { (x: Header) => x.votes })) } @@ -4581,7 +4581,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => val costDetails = TracedCost(testTraceBase) verifyCases( Seq( - (ctx, Expected(Success(dataBox), cost = 1769, costDetails, 1769, 2015 +: Seq.fill(3)(2017))), + (ctx, Expected(Success(dataBox), cost = 1769, costDetails, 1769, Seq.fill(4)(2017))), (ctx.copy(_dataInputs = Coll()), Expected(new ArrayIndexOutOfBoundsException("0"))) ), existingFeature({ (x: Context) => x.dataInputs(0) }, @@ -4606,7 +4606,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => Seq( (ctx, Expected(Success( Helpers.decodeBytes("7da4b55971f19a78d007638464580f91a020ab468c0dbe608deb1f619e245bc3")), - cost = 1772, idCostDetails, 1772, 2020 +: Seq.fill(3)(2022))) + cost = 1772, idCostDetails, 1772, Seq.fill(4)(2022))) ), existingFeature({ (x: Context) => x.dataInputs(0).id }, "{ (x: Context) => x.dataInputs(0).id }", @@ -4667,7 +4667,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => ) ) verifyCases( - Seq(ctx -> Expected(Success(ctx.HEIGHT), cost = 1766, heightCostDetails, 1766, 1992 +: Seq.fill(3)(1994))), + Seq(ctx -> Expected(Success(ctx.HEIGHT), cost = 1766, heightCostDetails, 1766, Seq.fill(4)(1994))), existingFeature( { (x: Context) => x.HEIGHT }, "{ (x: Context) => x.HEIGHT }", @@ -4704,7 +4704,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => )) verifyCases( - Seq((ctx, Expected(Success(Coll[Long](80946L)), cost = 1770, inputsCostDetails1, 1770, 2012 +: Seq.fill(3)(2014)))), + Seq((ctx, Expected(Success(Coll[Long](80946L)), cost = 1770, inputsCostDetails1, 1770, Seq.fill(4)(2014)))), existingFeature( { (x: Context) => x.INPUTS.map { (b: Box) => b.value } }, "{ (x: Context) => x.INPUTS.map { (b: Box) => b.value } }", @@ -4764,7 +4764,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => ) ) verifyCases( - Seq((ctx, Expected(Success(Coll((80946L, 80946L))), cost = 1774, inputsCostDetails2, 1774, 2038 +: Seq.fill(3)(2042)))), + Seq((ctx, Expected(Success(Coll((80946L, 80946L))), cost = 1774, inputsCostDetails2, 1774, Seq.fill(4)(2042)))), existingFeature( { (x: Context) => x.INPUTS.map { (b: Box) => (b.value, b.value) } }, """{ (x: Context) => @@ -4856,7 +4856,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => expectedDetails = CostDetails.ZeroCost, newCost = 1766, newVersionedResults = { - val expectedV3Costs = 2000 +: Seq.fill(3)(2002) + val expectedV3Costs = Seq.fill(4)(2002) // V3 activation will have different costs due to deserialization cost val costs = if (activatedVersionInTests >= V6SoftForkVersion) { expectedV3Costs @@ -4895,7 +4895,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => } verifyCases( - Seq(ctx -> Expected(Success(ctx.LastBlockUtxoRootHash), cost = 1766, methodCostDetails(SContextMethods.lastBlockUtxoRootHashMethod, 15), 1766, 2000 +: Seq.fill(3)(2002))), + Seq(ctx -> Expected(Success(ctx.LastBlockUtxoRootHash), cost = 1766, methodCostDetails(SContextMethods.lastBlockUtxoRootHashMethod, 15), 1766, Seq.fill(4)(2002))), existingPropTest("LastBlockUtxoRootHash", { (x: Context) => x.LastBlockUtxoRootHash }), preGeneratedSamples = Some(samples)) @@ -4908,7 +4908,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => ) ) verifyCases( - Seq(ctx -> Expected(Success(ctx.LastBlockUtxoRootHash.isUpdateAllowed), cost = 1767, isUpdateAllowedCostDetails, 1767, 2007 +: Seq.fill(3)(2009))), + Seq(ctx -> Expected(Success(ctx.LastBlockUtxoRootHash.isUpdateAllowed), cost = 1767, isUpdateAllowedCostDetails, 1767, Seq.fill(4)(2009))), existingFeature( { (x: Context) => x.LastBlockUtxoRootHash.isUpdateAllowed }, "{ (x: Context) => x.LastBlockUtxoRootHash.isUpdateAllowed }", @@ -4929,7 +4929,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => preGeneratedSamples = Some(samples)) verifyCases( - Seq(ctx -> Expected(Success(ctx.minerPubKey), cost = 1767, methodCostDetails(SContextMethods.minerPubKeyMethod, 20), 1767, 2001 +: Seq.fill(3)(2003))), + Seq(ctx -> Expected(Success(ctx.minerPubKey), cost = 1767, methodCostDetails(SContextMethods.minerPubKeyMethod, 20), 1767, Seq.fill(4)(2003))), existingPropTest("minerPubKey", { (x: Context) => x.minerPubKey }), preGeneratedSamples = Some(samples)) @@ -4969,7 +4969,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => FixedCostItem(GetVar), FixedCostItem(OptionGet))) verifyCases( - Seq((ctx, Expected(Success(true), cost = 1765, getVarCostDetails, 1765, 1997 +: Seq.fill(3)(1999)))), + Seq((ctx, Expected(Success(true), cost = 1765, getVarCostDetails, 1765, Seq.fill(4)(1999)))), existingFeature((x: Context) => x.getVar[Boolean](11).get, "{ (x: Context) => getVar[Boolean](11).get }", FuncValue(Vector((1, SContext)), OptionGet(GetVar(11.toByte, SOption(SBoolean))))), @@ -5003,7 +5003,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => ) verifyCases( Seq( - ctx -> Expected(Success(-135729055492651903L), 1779, registerIsDefinedCostDetails, 1779, 2061 +: Seq.fill(3)(2065)) + ctx -> Expected(Success(-135729055492651903L), 1779, registerIsDefinedCostDetails, 1779, Seq.fill(4)(2065)) ), existingFeature( { (x: Context) => @@ -5065,7 +5065,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => Seq( ctx -> Expected(Failure(expectedError), 0, CostDetails.ZeroCost, 1793, newVersionedResults = { - val expectedV3Costs = 2117 +: Seq.fill(3)(2121) + val expectedV3Costs = Seq.fill(4)(2121) // V3 activation will have different costs due to deserialization cost val costs = if (activatedVersionInTests >= V6SoftForkVersion) { expectedV3Costs @@ -5239,12 +5239,12 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => ) verifyCases( Seq( - ctx -> Expected(Success(5008366408131208436L), 1791, registerTagCostDetails1, 1791, 2149 +: Seq.fill(3)(2153)), + ctx -> Expected(Success(5008366408131208436L), 1791, registerTagCostDetails1, 1791, Seq.fill(4)(2153)), ctxWithRegsInOutput(ctx, Map( ErgoBox.R5 -> LongConstant(0L), - ErgoBox.R4 -> ShortConstant(10))) -> Expected(Success(10L), 1790, registerTagCostDetails2, 1790, 2148 +: Seq.fill(3)(2152)), + ErgoBox.R4 -> ShortConstant(10))) -> Expected(Success(10L), 1790, registerTagCostDetails2, 1790, Seq.fill(4)(2152)), ctxWithRegsInOutput(ctx, Map( - ErgoBox.R4 -> ShortConstant(10))) -> Expected(Success(-1L), 1777, registerTagCostDetails3, 1777, 2135 +: Seq.fill(3)(2139)) + ErgoBox.R4 -> ShortConstant(10))) -> Expected(Success(-1L), 1777, registerTagCostDetails3, 1777, Seq.fill(4)(2139)) ), existingFeature( { (x: Context) => @@ -5447,22 +5447,22 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( Seq( // case 1L - ctx -> Expected(Success(5008366408131289382L), 1794, tagRegisterCostDetails1, 1794, 2164 +: Seq.fill(3)(2168)), + ctx -> Expected(Success(5008366408131289382L), 1794, tagRegisterCostDetails1, 1794, Seq.fill(4)(2168)), // case 0L ctxWithRegsInOutput(ctx, Map( ErgoBox.R5 -> LongConstant(0L), - ErgoBox.R4 -> ShortConstant(10))) -> Expected(Success(80956L), 1793, tagRegisterCostDetails2, 1793, 2163 +: Seq.fill(3)(2167)), + ErgoBox.R4 -> ShortConstant(10))) -> Expected(Success(80956L), 1793, tagRegisterCostDetails2, 1793, Seq.fill(4)(2167)), // case returning 0L ctxWithRegsInOutput(ctx, Map( ErgoBox.R5 -> LongConstant(2L), // note R4 is required to avoid // "RuntimeException: Set of non-mandatory indexes is not densely packed" - ErgoBox.R4 -> ShortConstant(10))) -> Expected(Success(0L), 1784, tagRegisterCostDetails3, 1784, 2154 +: Seq.fill(3)(2158)), + ErgoBox.R4 -> ShortConstant(10))) -> Expected(Success(0L), 1784, tagRegisterCostDetails3, 1784, Seq.fill(4)(2158)), // case returning -1L ctxWithRegsInOutput(ctx, Map( - ErgoBox.R4 -> ShortConstant(10))) -> Expected(Success(-1L), 1777, tagRegisterCostDetails4, 1777, 2147 +: Seq.fill(3)(2151)) + ErgoBox.R4 -> ShortConstant(10))) -> Expected(Success(-1L), 1777, tagRegisterCostDetails4, 1777, Seq.fill(4)(2151)) ), existingFeature( { (x: Context) => @@ -5680,15 +5680,15 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => Seq( ctxWithRegsInDataInput(ctx, Map( ErgoBox.R5 -> LongConstant(1L), - ErgoBox.R4 -> LongConstant(10))) -> Expected(Success(10L), 1792, tagRegisterCostDetails1, 1792, 2158 +: Seq.fill(3)(2162)), + ErgoBox.R4 -> LongConstant(10))) -> Expected(Success(10L), 1792, tagRegisterCostDetails1, 1792, Seq.fill(4)(2162)), ctxWithRegsInDataInput(ctx, Map( ErgoBox.R5 -> LongConstant(0L), - ErgoBox.R4 -> ShortConstant(10))) -> Expected(Success(10L), 1791, tagRegisterCostDetails2, 1791, 2157 +: Seq.fill(3)(2161)), + ErgoBox.R4 -> ShortConstant(10))) -> Expected(Success(10L), 1791, tagRegisterCostDetails2, 1791, Seq.fill(4)(2161)), ctxWithRegsInDataInput(ctx, Map( ErgoBox.R5 -> LongConstant(2L), - ErgoBox.R4 -> ShortConstant(10))) -> Expected(Success(0L), 1786, tagRegisterCostDetails3, 1786, 2152 +: Seq.fill(3)(2156)), + ErgoBox.R4 -> ShortConstant(10))) -> Expected(Success(0L), 1786, tagRegisterCostDetails3, 1786, Seq.fill(4)(2156)), ctxWithRegsInDataInput(ctx, Map( - ErgoBox.R4 -> ShortConstant(10))) -> Expected(Success(-1L), 1779, tagRegisterCostDetails4, 1779, 2145 +: Seq.fill(3)(2149)) + ErgoBox.R4 -> ShortConstant(10))) -> Expected(Success(-1L), 1779, tagRegisterCostDetails4, 1779, Seq.fill(4)(2149)) ), existingFeature( { (x: Context) => @@ -5913,15 +5913,15 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => Seq( ctxWithRegsInDataInput(ctx, Map( ErgoBox.R5 -> LongConstant(1L), - ErgoBox.R4 -> LongConstant(10))) -> Expected(Success(80956L), 1796, costDetails1, 1796, 2174 +: Seq.fill(3)(2178)), + ErgoBox.R4 -> LongConstant(10))) -> Expected(Success(80956L), 1796, costDetails1, 1796, Seq.fill(4)(2178)), ctxWithRegsInDataInput(ctx, Map( ErgoBox.R5 -> LongConstant(0L), - ErgoBox.R4 -> ShortConstant(10))) -> Expected(Success(80956L), 1794, costDetails2, 1794, 2172 +: Seq.fill(3)(2176)), + ErgoBox.R4 -> ShortConstant(10))) -> Expected(Success(80956L), 1794, costDetails2, 1794, Seq.fill(4)(2176)), ctxWithRegsInDataInput(ctx, Map( ErgoBox.R5 -> LongConstant(2L), - ErgoBox.R4 -> ShortConstant(10))) -> Expected(Success(0L), 1786, costDetails3, 1786, 2164 +: Seq.fill(3)(2168)), + ErgoBox.R4 -> ShortConstant(10))) -> Expected(Success(0L), 1786, costDetails3, 1786, Seq.fill(4)(2168)), ctxWithRegsInDataInput(ctx, Map( - ErgoBox.R4 -> ShortConstant(10))) -> Expected(Success(-1L), 1779, costDetails4, 1779, 2157 +: Seq.fill(3)(2161)) + ErgoBox.R4 -> ShortConstant(10))) -> Expected(Success(-1L), 1779, costDetails4, 1779, Seq.fill(4)(2161)) ), existingFeature( { (x: Context) => @@ -6028,7 +6028,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => newCost = 1766, newVersionedResults = { val costs = if (activatedVersionInTests >= V6SoftForkVersion) { - 1996 +: Seq.fill(3)(1998) + Seq.fill(4)(1998) } else { Seq.fill(4)(1766) @@ -6070,8 +6070,8 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => val costDetails = TracedCost(traceBase :+ FixedCostItem(LogicalNot)) verifyCases( Seq( - (true, Expected(Success(false), 1765, costDetails, 1765, 1995 +: Seq.fill(3)(1997))), - (false, Expected(Success(true), 1765, costDetails, 1765, 1995 +: Seq.fill(3)(1997)))), + (true, Expected(Success(false), 1765, costDetails, 1765, Seq.fill(4)(1997))), + (false, Expected(Success(true), 1765, costDetails, 1765, Seq.fill(4)(1997)))), existingFeature((x: Boolean) => !x, "{ (x: Boolean) => !x }", FuncValue(Vector((1, SBoolean)), LogicalNot(ValUse(1, SBoolean))))) @@ -6081,7 +6081,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => val costDetails = TracedCost(traceBase :+ FixedCostItem(Negation)) verifyCases( { - def success[T](v: T) = Expected(Success(v), 1766, costDetails, 1766, 1996 +: Seq.fill(3)(1998)) + def success[T](v: T) = Expected(Success(v), 1766, costDetails, 1766, Seq.fill(4)(1998)) Seq( (Byte.MinValue, success(Byte.MinValue)), // !!! @@ -6101,7 +6101,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( { - def success[T](v: T) = Expected(Success(v), 1766, costDetails, 1766, 1996 +: Seq.fill(3)(1998)) + def success[T](v: T) = Expected(Success(v), 1766, costDetails, 1766, Seq.fill(4)(1998)) Seq( (Short.MinValue, success(Short.MinValue)), // special case! ((Short.MinValue + 1).toShort, success(Short.MaxValue)), @@ -6119,7 +6119,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( { - def success[T](v: T) = Expected(Success(v), 1766, costDetails, 1766, 1996 +: Seq.fill(3)(1998)) + def success[T](v: T) = Expected(Success(v), 1766, costDetails, 1766, Seq.fill(4)(1998)) Seq( (Int.MinValue, success(Int.MinValue)), // special case! @@ -6137,7 +6137,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( { - def success[T](v: T) = Expected(Success(v), 1766, costDetails, 1766, 1996 +: Seq.fill(3)(1998)) + def success[T](v: T) = Expected(Success(v), 1766, costDetails, 1766, Seq.fill(4)(1998)) Seq( (Long.MinValue, success(Long.MinValue)), // special case! @@ -6155,7 +6155,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( { - def success[T](v: T) = Expected(Success(v), 1767, costDetails, 1767, 1997 +: Seq.fill(3)(1999)) + def success[T](v: T) = Expected(Success(v), 1767, costDetails, 1767, Seq.fill(4)(1999)) Seq( (CBigInt(new BigInteger("-1655a05845a6ad363ac88ea21e88b97e436a1f02c548537e12e2d9667bf0680", 16)), success(CBigInt(new BigInteger("1655a05845a6ad363ac88ea21e88b97e436a1f02c548537e12e2d9667bf0680", 16)))), @@ -6194,7 +6194,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => ) verifyCases( { - def success[T](v: T) = Expected(Success(v), 1782, costDetails, 1782, 2014 +: Seq.fill(3)(2016)) + def success[T](v: T) = Expected(Success(v), 1782, costDetails, 1782, Seq.fill(4)(2016)) Seq( (-1, success(Helpers.decodeGroupElement("0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798"))), (1, success(Helpers.decodeGroupElement("0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798")))) @@ -6213,7 +6213,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( { - def success[T](v: T) = Expected(Success(v), 1782, costDetails, 1782, 2014 +: Seq.fill(3)(2016)) + def success[T](v: T) = Expected(Success(v), 1782, costDetails, 1782, Seq.fill(4)(2016)) Seq( (-1, success(Helpers.decodeGroupElement("0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798"))), (1, success(Helpers.decodeGroupElement("0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798")))) @@ -6239,7 +6239,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => ) verifyCases( { - def success[T](v: T) = Expected(Success(v), 1872, expCostDetails, 1872, 2110 +: Seq.fill(3)(2112)) + def success[T](v: T) = Expected(Success(v), 1872, expCostDetails, 1872, Seq.fill(4)(2112)) Seq( (CBigInt(new BigInteger("-e5c1a54694c85d644fa30a6fc5f3aa209ed304d57f72683a0ebf21038b6a9d", 16)), success(Helpers.decodeGroupElement("023395bcba3d7cf21d73c50f8af79d09a8c404c15ce9d04f067d672823bae91a54"))), @@ -6305,7 +6305,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( { - def success[T](v: T, cd: CostDetails) = Expected(Success(v), 1769, cd, 1769, 2019 +: Seq.fill(3)(2021)) + def success[T](v: T, cd: CostDetails) = Expected(Success(v), 1769, cd, 1769, Seq.fill(4)(2021)) Seq( ((Helpers.decodeBytes(""), Helpers.decodeBytes("")), success(Helpers.decodeBytes(""), costDetails(0))), ((Helpers.decodeBytes("01"), Helpers.decodeBytes("01")), success(Helpers.decodeBytes("00"), costDetails(1))), @@ -6318,7 +6318,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => newCost = 1769, newVersionedResults = { val costs = if (activatedVersionInTests >= V6SoftForkVersion) { - 2019 +: Seq.fill(3)(2021) + Seq.fill(4)(2021) } else { Seq.fill(4)(1769) } @@ -6470,9 +6470,9 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => { def success[T](v: T, c: Int, costDetails: CostDetails, newCost: Int, expectedV3Costs: Seq[Int]) = Expected(Success(v), c, costDetails, newCost, expectedV3Costs) Seq( - (Coll[Box](), success(Coll[Box](), 1767, costDetails, 1767, 2027 +: Seq.fill(3)(2031))), - (Coll[Box](b1), success(Coll[Box](), 1772, costDetails2, 1772, 2032 +: Seq.fill(3)(2036))), - (Coll[Box](b1, b2), success(Coll[Box](b2), 1776, costDetails3, 1776, 2036 +: Seq.fill(3)(2040))) + (Coll[Box](), success(Coll[Box](), 1767, costDetails, 1767, Seq.fill(4)(2031))), + (Coll[Box](b1), success(Coll[Box](), 1772, costDetails2, 1772, Seq.fill(4)(2036))), + (Coll[Box](b1, b2), success(Coll[Box](b2), 1776, costDetails3, 1776, Seq.fill(4)(2040))) ) }, existingFeature({ (x: Coll[Box]) => x.filter({ (b: Box) => b.value > 1 }) }, @@ -6525,13 +6525,13 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( { Seq( - (Coll[Box](), Expected(Success(Coll[Byte]()), 1773, costDetails1, 1773, 2027 +: Seq.fill(3)(2029))), + (Coll[Box](), Expected(Success(Coll[Byte]()), 1773, costDetails1, 1773, Seq.fill(4)(2029))), (Coll[Box](b1), Expected(Success(Helpers.decodeBytes( "0008ce02c1a9311ecf1e76c787ba4b1c0e10157b4f6d1e4db3ef0d84f411c99f2d4d2c5b027d1bd9a437e73726ceddecc162e5c85f79aee4798505bc826b8ad1813148e4190257cff6d06fe15d1004596eeb97a7f67755188501e36adc49bd807fe65e9d8281033c6021cff6ba5fdfc4f1742486030d2ebbffd9c9c09e488792f3102b2dcdabd5" - )), 1791, costDetails2, 1791, 2045 +: Seq.fill(3)(2047))), + )), 1791, costDetails2, 1791, Seq.fill(4)(2047))), (Coll[Box](b1, b2), Expected(Success(Helpers.decodeBytes( "0008ce02c1a9311ecf1e76c787ba4b1c0e10157b4f6d1e4db3ef0d84f411c99f2d4d2c5b027d1bd9a437e73726ceddecc162e5c85f79aee4798505bc826b8ad1813148e4190257cff6d06fe15d1004596eeb97a7f67755188501e36adc49bd807fe65e9d8281033c6021cff6ba5fdfc4f1742486030d2ebbffd9c9c09e488792f3102b2dcdabd500d197830201010096850200" - )), 1795, costDetails3, 1795, 2049 +: Seq.fill(3)(2051))) + )), 1795, costDetails3, 1795, Seq.fill(4)(2051))) ) }, existingFeature({ (x: Coll[Box]) => x.flatMap({ (b: Box) => b.propositionBytes }) }, @@ -6567,9 +6567,9 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => def success[T](v: T, c: Int, cd: CostDetails, nc: Int, v3Costs: Seq[Int]) = Expected(Success(v), c, cd, nc, v3Costs) Seq( - (Coll[Box](), success(Coll[(Box, Box)](), 1766, costDetails(0), 1766, 2016 +: Seq.fill(3)(2018))), - (Coll[Box](b1), success(Coll[(Box, Box)]((b1, b1)), 1768, costDetails(1), 1768, 2018 +: Seq.fill(3)(2020))), - (Coll[Box](b1, b2), success(Coll[(Box, Box)]((b1, b1), (b2, b2)), 1770, costDetails(2), 1770, 2020 +: Seq.fill(3)(2022))) + (Coll[Box](), success(Coll[(Box, Box)](), 1766, costDetails(0), 1766, Seq.fill(4)(2018))), + (Coll[Box](b1), success(Coll[(Box, Box)]((b1, b1)), 1768, costDetails(1), 1768, Seq.fill(4)(2020))), + (Coll[Box](b1, b2), success(Coll[(Box, Box)]((b1, b1), (b2, b2)), 1770, costDetails(2), 1770, Seq.fill(4)(2022))) ) }, existingFeature({ (x: Coll[Box]) => x.zip(x) }, @@ -6595,7 +6595,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => val costDetails = TracedCost(traceBase :+ FixedCostItem(SizeOf)) verifyCases( { - def success[T](v: T) = Expected(Success(v), 1765, costDetails, 1765, 1999 +: Seq.fill(3)(2001)) + def success[T](v: T) = Expected(Success(v), 1765, costDetails, 1765, Seq.fill(4)(2001)) Seq( (Coll[Box](), success(0)), (Coll[Box](b1), success(1)), @@ -6620,7 +6620,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => ) verifyCases( { - def success[T](v: T, i: Int) = Expected(Success(v), 1768, costDetails(i), 1768, 2006 +: Seq.fill(3)(2008)) + def success[T](v: T, i: Int) = Expected(Success(v), 1768, costDetails(i), 1768, Seq.fill(4)(2008)) Seq( (Coll[Box](), success(Coll[Int](), 0)), (Coll[Box](b1), success(Coll[Int](0), 1)), @@ -6676,9 +6676,9 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => ) def cases = { Seq( - (Coll[Box](), Expected(Success(true), 1764, costDetails1, 1764, 2022 +: Seq.fill(3)(2026))), - (Coll[Box](b1), Expected(Success(false), 1769, costDetails2, 1769, 2027 +: Seq.fill(3)(2031))), - (Coll[Box](b1, b2), Expected(Success(false), 1769, costDetails3, 1769, 2027 +: Seq.fill(3)(2031))) + (Coll[Box](), Expected(Success(true), 1764, costDetails1, 1764, Seq.fill(4)(2026))), + (Coll[Box](b1), Expected(Success(false), 1769, costDetails2, 1769, Seq.fill(4)(2031))), + (Coll[Box](b1, b2), Expected(Success(false), 1769, costDetails3, 1769, Seq.fill(4)(2031))) ) } if (lowerMethodCallsInTests) { @@ -6755,9 +6755,9 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( { Seq( - (Coll[Box](), Expected(Success(false), 1764, costDetails1, 1764, 2022 +: Seq.fill(3)(2026))), - (Coll[Box](b1), Expected(Success(false), 1769, costDetails2, 1769, 2027 +: Seq.fill(3)(2031))), - (Coll[Box](b1, b2), Expected(Success(true), 1773, costDetails3, 1773, 2031 +: Seq.fill(3)(2035))) + (Coll[Box](), Expected(Success(false), 1764, costDetails1, 1764, Seq.fill(4)(2026))), + (Coll[Box](b1), Expected(Success(false), 1769, costDetails2, 1769, Seq.fill(4)(2031))), + (Coll[Box](b1, b2), Expected(Success(true), 1773, costDetails3, 1773, Seq.fill(4)(2035))) ) }, existingFeature({ (x: Coll[Box]) => x.exists({ (b: Box) => b.value > 1 }) }, @@ -6848,11 +6848,11 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( { Seq( - (Coll[BigInt](), Expected(Success(false), 1764, costDetails1, 1764, 2044 +: Seq.fill(3)(2048))), - (Coll[BigInt](BigIntZero), Expected(Success(false), 1769, costDetails2, 1769, 2049 +: Seq.fill(3)(2053))), - (Coll[BigInt](BigIntOne), Expected(Success(true), 1772, costDetails3, 1772, 2052 +: Seq.fill(3)(2056))), - (Coll[BigInt](BigIntZero, BigIntOne), Expected(Success(true), 1777, costDetails4, 1777, 2057 +: Seq.fill(3)(2061))), - (Coll[BigInt](BigIntZero, BigInt10), Expected(Success(false), 1777, costDetails4, 1777, 2057 +: Seq.fill(3)(2061))) + (Coll[BigInt](), Expected(Success(false), 1764, costDetails1, 1764, Seq.fill(4)(2048))), + (Coll[BigInt](BigIntZero), Expected(Success(false), 1769, costDetails2, 1769, Seq.fill(4)(2053))), + (Coll[BigInt](BigIntOne), Expected(Success(true), 1772, costDetails3, 1772, Seq.fill(4)(2056))), + (Coll[BigInt](BigIntZero, BigIntOne), Expected(Success(true), 1777, costDetails4, 1777, Seq.fill(4)(2061))), + (Coll[BigInt](BigIntZero, BigInt10), Expected(Success(false), 1777, costDetails4, 1777, Seq.fill(4)(2061))) ) }, existingFeature( @@ -6963,11 +6963,11 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( { Seq( - (Coll[BigInt](), Expected(Success(true), 1764, costDetails1, 1764, 2044 +: Seq.fill(3)(2048))), - (Coll[BigInt](BigIntMinusOne), Expected(Success(false), 1769, costDetails2, 1769, 2049 +: Seq.fill(3)(2053))), - (Coll[BigInt](BigIntOne), Expected(Success(true), 1772, costDetails3, 1772, 2052 +: Seq.fill(3)(2056))), - (Coll[BigInt](BigIntZero, BigIntOne), Expected(Success(true), 1779, costDetails4, 1779, 2059 +: Seq.fill(3)(2063))), - (Coll[BigInt](BigIntZero, BigInt11), Expected(Success(false), 1779, costDetails4, 1779, 2059 +: Seq.fill(3)(2063))) + (Coll[BigInt](), Expected(Success(true), 1764, costDetails1, 1764, Seq.fill(4)(2048))), + (Coll[BigInt](BigIntMinusOne), Expected(Success(false), 1769, costDetails2, 1769, Seq.fill(4)(2053))), + (Coll[BigInt](BigIntOne), Expected(Success(true), 1772, costDetails3, 1772, Seq.fill(4)(2056))), + (Coll[BigInt](BigIntZero, BigIntOne), Expected(Success(true), 1779, costDetails4, 1779, Seq.fill(4)(2063))), + (Coll[BigInt](BigIntZero, BigInt11), Expected(Success(false), 1779, costDetails4, 1779, Seq.fill(4)(2063))) ) }, existingFeature( @@ -7103,7 +7103,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => Coll[GroupElement]() -> Expected(Success(Coll[Byte]()), 1773, CostDetails.ZeroCost, 1773, newVersionedResults = { val costs = if (activatedVersionInTests >= V6SoftForkVersion) { - 2027 +: Seq.fill(3)(2029) + Seq.fill(4)(2029) } else { Seq.fill(4)(1773) @@ -7117,14 +7117,14 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => Helpers.decodeGroupElement("0390e9daa9916f30d0bc61a8e381c6005edfb7938aee5bb4fc9e8a759c7748ffaa")) -> success(Helpers.decodeBytes( "02d65904820f8330218cf7318b3810d0c9ab9df86f1ee6100882683f23c0aee5870390e9daa9916f30d0bc61a8e381c6005edfb7938aee5bb4fc9e8a759c7748ffaa" - ), 1834, costDetails2, 1834, 2088 +: Seq.fill(3)(2090)), + ), 1834, costDetails2, 1834, Seq.fill(4)(2090)), Coll[GroupElement]( Helpers.decodeGroupElement("02d65904820f8330218cf7318b3810d0c9ab9df86f1ee6100882683f23c0aee587"), Helpers.decodeGroupElement("0390e9daa9916f30d0bc61a8e381c6005edfb7938aee5bb4fc9e8a759c7748ffaa"), Helpers.decodeGroupElement("03bd839b969b02d218fd1192f2c80cbda9c6ce9c7ddb765f31b748f4666203df85")) -> success(Helpers.decodeBytes( "02d65904820f8330218cf7318b3810d0c9ab9df86f1ee6100882683f23c0aee5870390e9daa9916f30d0bc61a8e381c6005edfb7938aee5bb4fc9e8a759c7748ffaa03bd839b969b02d218fd1192f2c80cbda9c6ce9c7ddb765f31b748f4666203df85" - ), 1864, costDetails3, 1864, 2118 +: Seq.fill(3)(2120)) + ), 1864, costDetails3, 1864, Seq.fill(4)(2120)) ) }, existingFeature( @@ -7164,7 +7164,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => newCost = 1840, newVersionedResults = (0 to 3).map({ version => val costs = if (activatedVersionInTests >= V6SoftForkVersion) { - 2100 +: Seq.fill(3)(2104) + Seq.fill(4)(2104) } else { Seq.fill(4)(1840) @@ -7238,7 +7238,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( { - def success[T](v: T, cd: CostDetails) = Expected(Success(v), 1776, cd, 1776, 2068 +: Seq.fill(3)(2072)) + def success[T](v: T, cd: CostDetails) = Expected(Success(v), 1776, cd, 1776, Seq.fill(4)(2072)) Seq( ((Coll[Int](), (0, 0)), success(Coll[Int](), costDetails(0))), ((Coll[Int](1), (0, 0)), success(Coll[Int](1, 1), costDetails(2))), @@ -7327,7 +7327,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( // (coll, (index, elem)) { - def success[T](v: T, cd: CostDetails) = Expected(Success(v), 1774, cd, 1774, 2054 +: Seq.fill(3)(2058)) + def success[T](v: T, cd: CostDetails) = Expected(Success(v), 1774, cd, 1774, Seq.fill(4)(2058)) Seq( ((Coll[Int](), (0, 0)), Expected(new IndexOutOfBoundsException("0"))), ((Coll[Int](1), (0, 0)), success(Coll[Int](0), costDetails(1))), @@ -7404,7 +7404,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( // (coll, (indexes, values)) { - def success[T](v: T, i: Int) = Expected(Success(v), 1774, costDetails(i), 1774, 2062 +: Seq.fill(3)(2066)) + def success[T](v: T, i: Int) = Expected(Success(v), 1774, costDetails(i), 1774, Seq.fill(4)(2066)) Seq( ((Coll[Int](), (Coll(0), Coll(0))), Expected(new IndexOutOfBoundsException("0"))), ((Coll[Int](), (Coll(0, 1), Coll(0, 0))), Expected(new IndexOutOfBoundsException("0"))), @@ -7551,15 +7551,15 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => // (coll, initState) { Seq( - ((Coll[Byte](), 0), Expected(Success(0), 1767, costDetails1, 1767, 2045 +: Seq.fill(3)(2049))), - ((Coll[Byte](), Int.MaxValue), Expected(Success(Int.MaxValue), 1767, costDetails1, 1767, 2045 +: Seq.fill(3)(2049))), - ((Coll[Byte](1), Int.MaxValue - 1), Expected(Success(Int.MaxValue), 1773, costDetails2, 1773, 2051 +: Seq.fill(3)(2055))), + ((Coll[Byte](), 0), Expected(Success(0), 1767, costDetails1, 1767, Seq.fill(4)(2049))), + ((Coll[Byte](), Int.MaxValue), Expected(Success(Int.MaxValue), 1767, costDetails1, 1767, Seq.fill(4)(2049))), + ((Coll[Byte](1), Int.MaxValue - 1), Expected(Success(Int.MaxValue), 1773, costDetails2, 1773, Seq.fill(4)(2055))), ((Coll[Byte](1), Int.MaxValue), Expected(new ArithmeticException("integer overflow"))), - ((Coll[Byte](-1), Int.MinValue + 1), Expected(Success(Int.MinValue), 1773, costDetails2, 1773, 2051 +: Seq.fill(3)(2055))), + ((Coll[Byte](-1), Int.MinValue + 1), Expected(Success(Int.MinValue), 1773, costDetails2, 1773, Seq.fill(4)(2055))), ((Coll[Byte](-1), Int.MinValue), Expected(new ArithmeticException("integer overflow"))), - ((Coll[Byte](1, 2), 0), Expected(Success(3), 1779, costDetails3, 1779, 2057 +: Seq.fill(3)(2061))), - ((Coll[Byte](1, -1), 0), Expected(Success(0), 1779, costDetails3, 1779, 2057 +: Seq.fill(3)(2061))), - ((Coll[Byte](1, -1, 1), 0), Expected(Success(1), 1785, costDetails4, 1785, 2063 +: Seq.fill(3)(2067))) + ((Coll[Byte](1, 2), 0), Expected(Success(3), 1779, costDetails3, 1779, Seq.fill(4)(2061))), + ((Coll[Byte](1, -1), 0), Expected(Success(0), 1779, costDetails3, 1779, Seq.fill(4)(2061))), + ((Coll[Byte](1, -1, 1), 0), Expected(Success(1), 1785, costDetails4, 1785, Seq.fill(4)(2067))) ) }, existingFeature( @@ -7812,15 +7812,15 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => // (coll, initState) { Seq( - ((Coll[Byte](), 0), Expected(Success(0), 1767, costDetails1, 1767, 2085 +: Seq.fill(3)(2089))), - ((Coll[Byte](), Int.MaxValue), Expected(Success(Int.MaxValue), 1767, costDetails1, 1767, 2085 +: Seq.fill(3)(2089))), - ((Coll[Byte](1), Int.MaxValue - 1), Expected(Success(Int.MaxValue), 1779, costDetails2, 1779, 2097 +: Seq.fill(3)(2101))), + ((Coll[Byte](), 0), Expected(Success(0), 1767, costDetails1, 1767, Seq.fill(4)(2089))), + ((Coll[Byte](), Int.MaxValue), Expected(Success(Int.MaxValue), 1767, costDetails1, 1767, Seq.fill(4)(2089))), + ((Coll[Byte](1), Int.MaxValue - 1), Expected(Success(Int.MaxValue), 1779, costDetails2, 1779, Seq.fill(4)(2101))), ((Coll[Byte](1), Int.MaxValue), Expected(new ArithmeticException("integer overflow"))), - ((Coll[Byte](-1), Int.MinValue + 1), Expected(Success(Int.MinValue + 1), 1777, costDetails3, 1777, 2095 +: Seq.fill(3)(2099))), - ((Coll[Byte](-1), Int.MinValue), Expected(Success(Int.MinValue), 1777, costDetails3, 1777, 2095 +: Seq.fill(3)(2099))), - ((Coll[Byte](1, 2), 0), Expected(Success(3), 1791, costDetails4, 1791, 2109 +: Seq.fill(3)(2113))), - ((Coll[Byte](1, -1), 0), Expected(Success(1), 1789, costDetails5, 1789, 2107 +: Seq.fill(3)(2111))), - ((Coll[Byte](1, -1, 1), 0), Expected(Success(2), 1801, costDetails6, 1801, 2119 +: Seq.fill(3)(2123))) + ((Coll[Byte](-1), Int.MinValue + 1), Expected(Success(Int.MinValue + 1), 1777, costDetails3, 1777, Seq.fill(4)(2099))), + ((Coll[Byte](-1), Int.MinValue), Expected(Success(Int.MinValue), 1777, costDetails3, 1777, Seq.fill(4)(2099))), + ((Coll[Byte](1, 2), 0), Expected(Success(3), 1791, costDetails4, 1791, Seq.fill(4)(2113))), + ((Coll[Byte](1, -1), 0), Expected(Success(1), 1789, costDetails5, 1789, Seq.fill(4)(2111))), + ((Coll[Byte](1, -1, 1), 0), Expected(Success(2), 1801, costDetails6, 1801, Seq.fill(4)(2123))) ) }, existingFeature( @@ -7931,15 +7931,15 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( // (coll, (elem: Byte, from: Int)) { - def success0[T](v: T) = Expected(Success(v), 1773, costDetails(0), 1773, 2057 +: Seq.fill(3)(2061)) + def success0[T](v: T) = Expected(Success(v), 1773, costDetails(0), 1773, Seq.fill(4)(2061)) - def success1[T](v: T) = Expected(Success(v), 1773, costDetails(1), 1773, 2057 +: Seq.fill(3)(2061)) + def success1[T](v: T) = Expected(Success(v), 1773, costDetails(1), 1773, Seq.fill(4)(2061)) - def success2[T](v: T) = Expected(Success(v), 1774, costDetails(2), 1774, 2058 +: Seq.fill(3)(2062)) + def success2[T](v: T) = Expected(Success(v), 1774, costDetails(2), 1774, Seq.fill(4)(2062)) - def success3[T](v: T) = Expected(Success(v), 1775, costDetails(3), 1775, 2059 +: Seq.fill(3)(2063)) + def success3[T](v: T) = Expected(Success(v), 1775, costDetails(3), 1775, Seq.fill(4)(2063)) - def success12[T](v: T) = Expected(Success(v), 1782, costDetails(12), 1782, 2066 +: Seq.fill(3)(2070)) + def success12[T](v: T) = Expected(Success(v), 1782, costDetails(12), 1782, Seq.fill(4)(2070)) Seq( ((Coll[Byte](), (0.toByte, 0)), success0(-1)), @@ -8002,7 +8002,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => ) verifyCases( { - def success[T](v: T) = Expected(Success(v), 1769, costDetails, 1769, 2017 +: Seq.fill(3)(2019)) + def success[T](v: T) = Expected(Success(v), 1769, costDetails, 1769, Seq.fill(4)(2019)) Seq( ((Coll[Int](), 0), Expected(new ArrayIndexOutOfBoundsException("0"))), @@ -8067,7 +8067,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( // (coll, (index, default)) { - def success[T](v: T) = Expected(Success(v), 1773, costDetails, 1773, 2049 +: Seq.fill(3)(2053)) + def success[T](v: T) = Expected(Success(v), 1773, costDetails, 1773, Seq.fill(4)(2053)) Seq( ((Coll[Int](), (0, default)), success(default)), ((Coll[Int](), (-1, default)), success(default)), @@ -8150,7 +8150,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => ) verifyCases( { - def success[T](v: T) = Expected(Success(v), 1763, costDetails, 1763, 1995 +: Seq.fill(3)(1997)) + def success[T](v: T) = Expected(Success(v), 1763, costDetails, 1763, Seq.fill(4)(1997)) Seq( ((0, 0), success(2)), ((1, 2), success(2)) @@ -8165,7 +8165,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => val samples = genSamples[(Int, Int)](DefaultMinSuccessful) val costDetails = TracedCost(traceBase :+ FixedCostItem(SelectField)) verifyCases( - Seq(((1, 2), Expected(Success(1), cost = 1764, costDetails, 1764, 1996 +: Seq.fill(3)(1998)))), + Seq(((1, 2), Expected(Success(1), cost = 1764, costDetails, 1764, Seq.fill(4)(1998)))), existingFeature((x: (Int, Int)) => x._1, "{ (x: (Int, Int)) => x(0) }", FuncValue( @@ -8174,7 +8174,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => )), preGeneratedSamples = Some(samples)) verifyCases( - Seq(((1, 2), Expected(Success(2), cost = 1764, costDetails, 1764, 1996 +: Seq.fill(3)(1998)))), + Seq(((1, 2), Expected(Success(2), cost = 1764, costDetails, 1764, Seq.fill(4)(1998)))), existingFeature((x: (Int, Int)) => x._2, "{ (x: (Int, Int)) => x(1) }", FuncValue( @@ -8216,9 +8216,9 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => { def success[T](v: T, c: Int) = Expected(Success(v), c) Seq( - (Coll[Int](), Expected(Success(Coll[Int]()), 1768, costDetails(0), 1768, 2020 +: Seq.fill(3)(2022))), - (Coll[Int](1), Expected(Success(Coll[Int](2)), 1771, costDetails(1), 1771, 2023 +: Seq.fill(3)(2025))), - (Coll[Int](1, 2), Expected(Success(Coll[Int](2, 3)), 1774, costDetails(2), 1774, 2026 +: Seq.fill(3)(2028))), + (Coll[Int](), Expected(Success(Coll[Int]()), 1768, costDetails(0), 1768, Seq.fill(4)(2022))), + (Coll[Int](1), Expected(Success(Coll[Int](2)), 1771, costDetails(1), 1771, Seq.fill(4)(2025))), + (Coll[Int](1, 2), Expected(Success(Coll[Int](2, 3)), 1774, costDetails(2), 1774, Seq.fill(4)(2028))), (Coll[Int](1, 2, Int.MaxValue), Expected(new ArithmeticException("integer overflow"))) ) }, @@ -8312,10 +8312,10 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => { def success[T](v: T, c: Int) = Expected(Success(v), c) Seq( - (Coll[Int](), Expected(Success(Coll[Int]()), 1768, costDetails1, 1768, 2050 +: Seq.fill(3)(2054))), - (Coll[Int](1), Expected(Success(Coll[Int](2)), 1775, costDetails2, 1775, 2057 +: Seq.fill(3)(2061))), - (Coll[Int](-1), Expected(Success(Coll[Int](1)), 1775, costDetails3, 1775, 2057 +: Seq.fill(3)(2061))), - (Coll[Int](1, -2), Expected(Success(Coll[Int](2, 2)), 1782, costDetails4, 1782, 2064 +: Seq.fill(3)(2068))), + (Coll[Int](), Expected(Success(Coll[Int]()), 1768, costDetails1, 1768, Seq.fill(4)(2054))), + (Coll[Int](1), Expected(Success(Coll[Int](2)), 1775, costDetails2, 1775, Seq.fill(4)(2061))), + (Coll[Int](-1), Expected(Success(Coll[Int](1)), 1775, costDetails3, 1775, Seq.fill(4)(2061))), + (Coll[Int](1, -2), Expected(Success(Coll[Int](2, 2)), 1782, costDetails4, 1782, Seq.fill(4)(2068))), (Coll[Int](1, 2, Int.MaxValue), Expected(new ArithmeticException("integer overflow"))), (Coll[Int](1, 2, Int.MinValue), Expected(new ArithmeticException("integer overflow"))) ) @@ -8365,11 +8365,11 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( { Seq( - (Coll[Int](), Expected(Success(Coll[Int]()), 1768, costDetails(0), 1768, 2020 +: Seq.fill(3)(2022))), - (Coll[Int](1), Expected(Success(Coll[Int](1)), 1771, costDetails(1), 1771, 2023 +: Seq.fill(3)(2025))), - (Coll[Int](1, 2), Expected(Success(Coll[Int](1, 2)), 1775, costDetails(2), 1775, 2027 +: Seq.fill(3)(2029))), - (Coll[Int](1, 2, -1), Expected(Success(Coll[Int](1, 2)), 1778, costDetails(3), 1778, 2030 +: Seq.fill(3)(2032))), - (Coll[Int](1, -1, 2, -2), Expected(Success(Coll[Int](1, 2)), 1782, costDetails(4), 1782, 2034 +: Seq.fill(3)(2036))) + (Coll[Int](), Expected(Success(Coll[Int]()), 1768, costDetails(0), 1768, Seq.fill(4)(2022))), + (Coll[Int](1), Expected(Success(Coll[Int](1)), 1771, costDetails(1), 1771, Seq.fill(4)(2025))), + (Coll[Int](1, 2), Expected(Success(Coll[Int](1, 2)), 1775, costDetails(2), 1775, Seq.fill(4)(2029))), + (Coll[Int](1, 2, -1), Expected(Success(Coll[Int](1, 2)), 1778, costDetails(3), 1778, Seq.fill(4)(2032))), + (Coll[Int](1, -1, 2, -2), Expected(Success(Coll[Int](1, 2)), 1782, costDetails(4), 1782, Seq.fill(4)(2036))) ) }, existingFeature((x: Coll[Int]) => x.filter({ (v: Int) => o.gt(v, 0) }), @@ -8442,12 +8442,12 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => def success[T](v: T, c: Int) = Expected(Success(v), c) Seq( - (Coll[Int](), Expected(Success(Coll[Int]()), 1768, costDetails(0), 1768, 2044 +: Seq.fill(3)(2048))), - (Coll[Int](1), Expected(Success(Coll[Int](1)), 1775, costDetails(1), 1775, 2051 +: Seq.fill(3)(2055))), - (Coll[Int](10), Expected(Success(Coll[Int]()), 1775, costDetails(1), 1775, 2051 +: Seq.fill(3)(2055))), - (Coll[Int](1, 2), Expected(Success(Coll[Int](1, 2)), 1783, costDetails(2), 1783, 2059 +: Seq.fill(3)(2063))), - (Coll[Int](1, 2, 0), Expected(Success(Coll[Int](1, 2)), 1788, costDetails3, 1788, 2064 +: Seq.fill(3)(2068))), - (Coll[Int](1, -1, 2, -2, 11), Expected(Success(Coll[Int](1, 2)), 1800, costDetails5, 1800, 2076 +: Seq.fill(3)(2080))) + (Coll[Int](), Expected(Success(Coll[Int]()), 1768, costDetails(0), 1768, Seq.fill(4)(2048))), + (Coll[Int](1), Expected(Success(Coll[Int](1)), 1775, costDetails(1), 1775, Seq.fill(4)(2055))), + (Coll[Int](10), Expected(Success(Coll[Int]()), 1775, costDetails(1), 1775, Seq.fill(4)(2055))), + (Coll[Int](1, 2), Expected(Success(Coll[Int](1, 2)), 1783, costDetails(2), 1783, Seq.fill(4)(2063))), + (Coll[Int](1, 2, 0), Expected(Success(Coll[Int](1, 2)), 1788, costDetails3, 1788, Seq.fill(4)(2068))), + (Coll[Int](1, -1, 2, -2, 11), Expected(Success(Coll[Int](1, 2)), 1800, costDetails5, 1800, Seq.fill(4)(2080))) ) }, existingFeature((x: Coll[Int]) => x.filter({ (v: Int) => if (o.gt(v, 0)) v < 10 else false }), @@ -8491,7 +8491,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => { val cost = 1772 val newCost = 1772 - val v3Costs = 2046 +: Seq.fill(3)(2050) + val v3Costs = Seq.fill(4)(2050) Seq( // (coll, (from, until)) ((Coll[Int](), (-1, 0)), Expected(Success(Coll[Int]()), cost, costDetails(1), newCost, v3Costs)), @@ -8581,7 +8581,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => if (lowerMethodCallsInTests) { verifyCases( { - def success[T](v: T, size: Int) = Expected(Success(v), 1770, costDetails(size), 1770, 2020 +: Seq.fill(3)(2022)) + def success[T](v: T, size: Int) = Expected(Success(v), 1770, costDetails(size), 1770, Seq.fill(4)(2022)) val arr1 = Gen.listOfN(100, arbitrary[Int]).map(_.toArray).sample.get val arr2 = Gen.listOfN(200, arbitrary[Int]).map(_.toArray).sample.get @@ -8593,7 +8593,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => (Coll[Int](1), Coll[Int](2, 3)) -> success(Coll[Int](1, 2, 3), 3), (Coll[Int](1, 2), Coll[Int](3)) -> success(Coll[Int](1, 2, 3), 3), (Coll[Int](1, 2), Coll[Int](3, 4)) -> success(Coll[Int](1, 2, 3, 4), 4), - (Coll[Int](arr1: _*), Coll[Int](arr2: _*)) -> Expected(Success(Coll[Int](arr1 ++ arr2: _*)), 1771, costDetails(300), 1771, 2021 +: Seq.fill(3)(2023)) + (Coll[Int](arr1: _*), Coll[Int](arr2: _*)) -> Expected(Success(Coll[Int](arr1 ++ arr2: _*)), 1771, costDetails(300), 1771, Seq.fill(4)(2023)) ) }, existingFeature( @@ -8688,32 +8688,32 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( Seq( (None -> Expected(new NoSuchElementException("None.get"))), - (Some(10L) -> Expected(Success(10L), 1765, costDetails1, 1765, 1995 +: Seq.fill(3)(1997)))), + (Some(10L) -> Expected(Success(10L), 1765, costDetails1, 1765, Seq.fill(4)(1997)))), existingFeature({ (x: Option[Long]) => x.get }, "{ (x: Option[Long]) => x.get }", FuncValue(Vector((1, SOption(SLong))), OptionGet(ValUse(1, SOption(SLong)))))) verifyCases( Seq( - (None -> Expected(Success(false), 1764, costDetails2, 1764, 1994 +: Seq.fill(3)(1996))), - (Some(10L) -> Expected(Success(true), 1764, costDetails2, 1764, 1994 +: Seq.fill(3)(1996)))), + (None -> Expected(Success(false), 1764, costDetails2, 1764, Seq.fill(4)(1996))), + (Some(10L) -> Expected(Success(true), 1764, costDetails2, 1764, Seq.fill(4)(1996)))), existingFeature({ (x: Option[Long]) => x.isDefined }, "{ (x: Option[Long]) => x.isDefined }", FuncValue(Vector((1, SOption(SLong))), OptionIsDefined(ValUse(1, SOption(SLong)))))) verifyCases( Seq( - (None -> Expected(Success(1L), 1766, costDetails3, 1766, 2004 +: Seq.fill(3)(2006))), - (Some(10L) -> Expected(Success(10L), 1766, costDetails3, 1766, 2004 +: Seq.fill(3)(2006)))), + (None -> Expected(Success(1L), 1766, costDetails3, 1766, Seq.fill(4)(2006))), + (Some(10L) -> Expected(Success(10L), 1766, costDetails3, 1766, Seq.fill(4)(2006)))), existingFeature({ (x: Option[Long]) => x.getOrElse(1L) }, "{ (x: Option[Long]) => x.getOrElse(1L) }", FuncValue(Vector((1, SOption(SLong))), OptionGetOrElse(ValUse(1, SOption(SLong)), LongConstant(1L))))) verifyCases( Seq( - (None -> Expected(Success(None), 1766, costDetails4, 1766, 2024 +: Seq.fill(3)(2028))), - (Some(10L) -> Expected(Success(None), 1768, costDetails5, 1768, 2026 +: Seq.fill(3)(2030))), - (Some(1L) -> Expected(Success(Some(1L)), 1769, costDetails5, 1769, 2027 +: Seq.fill(3)(2031)))), + (None -> Expected(Success(None), 1766, costDetails4, 1766, Seq.fill(4)(2028))), + (Some(10L) -> Expected(Success(None), 1768, costDetails5, 1768, Seq.fill(4)(2030))), + (Some(1L) -> Expected(Success(Some(1L)), 1769, costDetails5, 1769, Seq.fill(4)(2031)))), existingFeature({ (x: Option[Long]) => x.filter({ (v: Long) => v == 1 }) }, "{ (x: Option[Long]) => x.filter({ (v: Long) => v == 1 }) }", FuncValue( @@ -8729,8 +8729,8 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => val n = ExactNumeric.LongIsExactNumeric verifyCases( Seq( - (None -> Expected(Success(None), 1766, costDetails6, 1766, 2024 +: Seq.fill(3)(2028))), - (Some(10L) -> Expected(Success(Some(11L)), 1770, costDetails7, 1770, 2028 +: Seq.fill(3)(2032))), + (None -> Expected(Success(None), 1766, costDetails6, 1766, Seq.fill(4)(2028))), + (Some(10L) -> Expected(Success(Some(11L)), 1770, costDetails7, 1770, Seq.fill(4)(2032))), (Some(Long.MaxValue) -> Expected(new ArithmeticException("long overflow")))), existingFeature({ (x: Option[Long]) => x.map( (v: Long) => n.plus(v, 1) ) }, "{ (x: Option[Long]) => x.map({ (v: Long) => v + 1 }) }", @@ -8792,10 +8792,10 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => val o = ExactOrdering.LongIsExactOrdering verifyCases( Seq( - (None -> Expected(Success(None), 1766, costDetails1, 1766, 2048 +: Seq.fill(3)(2052))), - (Some(0L) -> Expected(Success(None), 1771, costDetails2, 1771, 2053 +: Seq.fill(3)(2057))), - (Some(10L) -> Expected(Success(Some(10L)), 1774, costDetails3, 1774, 2056 +: Seq.fill(3)(2060))), - (Some(11L) -> Expected(Success(None), 1774, costDetails3, 1774, 2056 +: Seq.fill(3)(2060)))), + (None -> Expected(Success(None), 1766, costDetails1, 1766, Seq.fill(4)(2052))), + (Some(0L) -> Expected(Success(None), 1771, costDetails2, 1771, Seq.fill(4)(2057))), + (Some(10L) -> Expected(Success(Some(10L)), 1774, costDetails3, 1774, Seq.fill(4)(2060))), + (Some(11L) -> Expected(Success(None), 1774, costDetails3, 1774, Seq.fill(4)(2060)))), existingFeature( { (x: Option[Long]) => x.filter({ (v: Long) => if (o.gt(v, 0L)) v <= 10 else false } ) }, "{ (x: Option[Long]) => x.filter({ (v: Long) => if (v > 0) v <= 10 else false }) }", @@ -8856,10 +8856,10 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => val n = ExactNumeric.LongIsExactNumeric verifyCases( Seq( - (None -> Expected(Success(None), 1766, costDetails4, 1766, 2044 +: Seq.fill(3)(2048))), - (Some(0L) -> Expected(Success(Some(0L)), 1772, costDetails5, 1772, 2050 +: Seq.fill(3)(2054))), - (Some(10L) -> Expected(Success(Some(10L)), 1772, costDetails5, 1772, 2050 +: Seq.fill(3)(2054))), - (Some(-1L) -> Expected(Success(Some(-2L)), 1774, costDetails6, 1774, 2052 +: Seq.fill(3)(2056))), + (None -> Expected(Success(None), 1766, costDetails4, 1766, Seq.fill(4)(2048))), + (Some(0L) -> Expected(Success(Some(0L)), 1772, costDetails5, 1772, Seq.fill(4)(2054))), + (Some(10L) -> Expected(Success(Some(10L)), 1772, costDetails5, 1772, Seq.fill(4)(2054))), + (Some(-1L) -> Expected(Success(Some(-2L)), 1774, costDetails6, 1774, Seq.fill(4)(2056))), (Some(Long.MinValue) -> Expected(new ArithmeticException("long overflow")))), existingFeature( { (x: Option[Long]) => x.map( (v: Long) => if (o.lt(v, 0)) n.minus(v, 1) else v ) }, @@ -8918,7 +8918,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => newCost = 1766, newVersionedResults = Seq.tabulate(4)({ v => val costs = if (activatedVersionInTests >= V6SoftForkVersion) { - 2038 +: Seq.fill(3)(2042) + Seq.fill(4)(2042) } else { Seq.fill(4)(1766) @@ -8931,7 +8931,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => cost = 1774, expectedDetails = costDetails2, expectedNewCost = 1774, - expectedV3Costs = 2046 +: Seq.fill(3)(2050))), + expectedV3Costs = Seq.fill(4)(2050))), (Some(Long.MaxValue) -> Expected(new ArithmeticException("long overflow"))) ), changedFeature( @@ -9001,21 +9001,21 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => 1768, costDetailsBlake(0), 1768, - 1998 +: Seq.fill(3)(2000) + Seq.fill(4)(2000) ), Helpers.decodeBytes("e0ff0105ffffac31010017ff33") -> Expected( Success(Helpers.decodeBytes("33707eed9aab64874ff2daa6d6a378f61e7da36398fb36c194c7562c9ff846b5")), 1768, costDetailsBlake(13), 1768, - 1998 +: Seq.fill(3)(2000) + Seq.fill(4)(2000) ), Colls.replicate(1024, 1.toByte) -> Expected( Success(Helpers.decodeBytes("45d8456fc5d41d1ec1124cb92e41192c1c3ec88f0bf7ae2dc6e9cf75bec22045")), 1773, costDetailsBlake(1024), 1773, - 2003 +: Seq.fill(3)(2005) + Seq.fill(4)(2005) ) ), existingFeature((x: Coll[Byte]) => SigmaDsl.blake2b256(x), @@ -9029,21 +9029,21 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => 1774, costDetailsSha(0), 1774, - 2004 +: Seq.fill(3)(2006) + Seq.fill(4)(2006) ), Helpers.decodeBytes("e0ff0105ffffac31010017ff33") -> Expected( Success(Helpers.decodeBytes("367d0ec2cdc14aac29d5beb60c2bfc86d5a44a246308659af61c1b85fa2ca2cc")), 1774, costDetailsSha(13), 1774, - 2004 +: Seq.fill(3)(2006) + Seq.fill(4)(2006) ), Colls.replicate(1024, 1.toByte) -> Expected( Success(Helpers.decodeBytes("5a648d8015900d89664e00e125df179636301a2d8fa191c1aa2bd9358ea53a69")), 1786, costDetailsSha(1024), 1786, - 2016 +: Seq.fill(3)(2018) + Seq.fill(4)(2018) ) ), existingFeature((x: Coll[Byte]) => SigmaDsl.sha256(x), @@ -9053,7 +9053,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => property("sigmaProp equivalence") { val costDetails = TracedCost(traceBase :+ FixedCostItem(BoolToSigmaProp)) - val v3Costs = 1995 +: Seq.fill(3)(1997) + val v3Costs = Seq.fill(4)(1997) verifyCases( Seq( (false, Expected(Success(CSigmaProp(TrivialProp.FalseProp)), 1765, costDetails, 1765, v3Costs)), @@ -9084,7 +9084,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => Helpers.decodeECPoint("02614b14a8c6c6b4b7ce017d72fbca7f9218b72c16bdd88f170ffb300b106b9014"), Helpers.decodeECPoint("034cc5572276adfa3e283a3f1b0f0028afaadeaa362618c5ec43262d8cefe7f004") ) - )) -> Expected(Success(CSigmaProp(TrivialProp.TrueProp)), 1770, costDetails(1), 1770, 2016 +: Seq.fill(3)(2018)), + )) -> Expected(Success(CSigmaProp(TrivialProp.TrueProp)), 1770, costDetails(1), 1770, Seq.fill(4)(2018)), Coll[SigmaProp]( CSigmaProp( ProveDHTuple( @@ -9112,7 +9112,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => ) ) ) - ), 1873, costDetails(3), 1873, 2119 +: Seq.fill(3)(2121)), + ), 1873, costDetails(3), 1873, Seq.fill(4)(2121)), Colls.replicate[SigmaProp](AtLeast.MaxChildrenCount + 1, CSigmaProp(TrivialProp.TrueProp)) -> Expected(new IllegalArgumentException("Expected input elements count should not exceed 255, actual: 256")) ), @@ -9157,19 +9157,19 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => ProveDlog(Helpers.decodeECPoint("03a426a66fc1af2792b35d9583904c3fb877b49ae5cea45b7a2aa105ffa4c68606")) ) ) - ), 1802, 2046 +: Seq.fill(3)(2048)), + ), 1802, Seq.fill(4)(2048)), (CSigmaProp(TrivialProp.TrueProp), CSigmaProp(ProveDlog(Helpers.decodeECPoint("03a426a66fc1af2792b35d9583904c3fb877b49ae5cea45b7a2aa105ffa4c68606")))) -> - success(CSigmaProp(ProveDlog(Helpers.decodeECPoint("03a426a66fc1af2792b35d9583904c3fb877b49ae5cea45b7a2aa105ffa4c68606"))), 1784, 2028 +: Seq.fill(3)(2030)), + success(CSigmaProp(ProveDlog(Helpers.decodeECPoint("03a426a66fc1af2792b35d9583904c3fb877b49ae5cea45b7a2aa105ffa4c68606"))), 1784, Seq.fill(4)(2030)), (CSigmaProp(TrivialProp.FalseProp), CSigmaProp(ProveDlog(Helpers.decodeECPoint("03a426a66fc1af2792b35d9583904c3fb877b49ae5cea45b7a2aa105ffa4c68606")))) -> - success(CSigmaProp(TrivialProp.FalseProp), 1767, 2011 +: Seq.fill(3)(2013)), + success(CSigmaProp(TrivialProp.FalseProp), 1767, Seq.fill(4)(2013)), (CSigmaProp(ProveDlog(Helpers.decodeECPoint("03a426a66fc1af2792b35d9583904c3fb877b49ae5cea45b7a2aa105ffa4c68606"))), CSigmaProp(TrivialProp.TrueProp)) -> - success(CSigmaProp(ProveDlog(Helpers.decodeECPoint("03a426a66fc1af2792b35d9583904c3fb877b49ae5cea45b7a2aa105ffa4c68606"))), 1784, 2028 +: Seq.fill(3)(2030)), + success(CSigmaProp(ProveDlog(Helpers.decodeECPoint("03a426a66fc1af2792b35d9583904c3fb877b49ae5cea45b7a2aa105ffa4c68606"))), 1784, Seq.fill(4)(2030)), (CSigmaProp(ProveDlog(Helpers.decodeECPoint("03a426a66fc1af2792b35d9583904c3fb877b49ae5cea45b7a2aa105ffa4c68606"))), CSigmaProp(TrivialProp.FalseProp)) -> - success(CSigmaProp(TrivialProp.FalseProp), 1767, 2011 +: Seq.fill(3)(2013)) + success(CSigmaProp(TrivialProp.FalseProp), 1767, Seq.fill(4)(2013)) ) }, existingFeature( @@ -9189,9 +9189,9 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => { Seq( (CSigmaProp(ProveDlog(Helpers.decodeECPoint("03a426a66fc1af2792b35d9583904c3fb877b49ae5cea45b7a2aa105ffa4c68606"))), true) -> - Expected(Success(CSigmaProp(ProveDlog(Helpers.decodeECPoint("03a426a66fc1af2792b35d9583904c3fb877b49ae5cea45b7a2aa105ffa4c68606")))), 1786, costDetails2, 1786, 2036 +: Seq.fill(3)(2038)), + Expected(Success(CSigmaProp(ProveDlog(Helpers.decodeECPoint("03a426a66fc1af2792b35d9583904c3fb877b49ae5cea45b7a2aa105ffa4c68606")))), 1786, costDetails2, 1786, Seq.fill(4)(2038)), (CSigmaProp(ProveDlog(Helpers.decodeECPoint("03a426a66fc1af2792b35d9583904c3fb877b49ae5cea45b7a2aa105ffa4c68606"))), false) -> - Expected(Success(CSigmaProp(TrivialProp.FalseProp)), 1769, costDetails2, 1769, 2019 +: Seq.fill(3)(2021)) + Expected(Success(CSigmaProp(TrivialProp.FalseProp)), 1769, costDetails2, 1769, Seq.fill(4)(2021)) ) }, existingFeature( @@ -9234,19 +9234,19 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => ) ) ), - 1802, 2046 +: Seq.fill(3)(2048)), + 1802, Seq.fill(4)(2048)), (CSigmaProp(TrivialProp.FalseProp), CSigmaProp(ProveDlog(Helpers.decodeECPoint("03a426a66fc1af2792b35d9583904c3fb877b49ae5cea45b7a2aa105ffa4c68606")))) -> - success(CSigmaProp(ProveDlog(Helpers.decodeECPoint("03a426a66fc1af2792b35d9583904c3fb877b49ae5cea45b7a2aa105ffa4c68606"))), 1784, 2028 +: Seq.fill(3)(2030)), + success(CSigmaProp(ProveDlog(Helpers.decodeECPoint("03a426a66fc1af2792b35d9583904c3fb877b49ae5cea45b7a2aa105ffa4c68606"))), 1784, Seq.fill(4)(2030)), (CSigmaProp(TrivialProp.TrueProp), CSigmaProp(ProveDlog(Helpers.decodeECPoint("03a426a66fc1af2792b35d9583904c3fb877b49ae5cea45b7a2aa105ffa4c68606")))) -> - success(CSigmaProp(TrivialProp.TrueProp), 1767, 2011 +: Seq.fill(3)(2013)), + success(CSigmaProp(TrivialProp.TrueProp), 1767, Seq.fill(4)(2013)), (CSigmaProp(ProveDlog(Helpers.decodeECPoint("03a426a66fc1af2792b35d9583904c3fb877b49ae5cea45b7a2aa105ffa4c68606"))), CSigmaProp(TrivialProp.FalseProp)) -> - success(CSigmaProp(ProveDlog(Helpers.decodeECPoint("03a426a66fc1af2792b35d9583904c3fb877b49ae5cea45b7a2aa105ffa4c68606"))), 1784, 2028 +: Seq.fill(3)(2030)), + success(CSigmaProp(ProveDlog(Helpers.decodeECPoint("03a426a66fc1af2792b35d9583904c3fb877b49ae5cea45b7a2aa105ffa4c68606"))), 1784, Seq.fill(4)(2030)), (CSigmaProp(ProveDlog(Helpers.decodeECPoint("03a426a66fc1af2792b35d9583904c3fb877b49ae5cea45b7a2aa105ffa4c68606"))), CSigmaProp(TrivialProp.TrueProp)) -> - success(CSigmaProp(TrivialProp.TrueProp), 1767, 2011 +: Seq.fill(3)(2013)) + success(CSigmaProp(TrivialProp.TrueProp), 1767, Seq.fill(4)(2013)) ) }, existingFeature( @@ -9274,9 +9274,9 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => Seq( (CSigmaProp(ProveDlog(Helpers.decodeECPoint("03a426a66fc1af2792b35d9583904c3fb877b49ae5cea45b7a2aa105ffa4c68606"))), false) -> - success(CSigmaProp(ProveDlog(Helpers.decodeECPoint("03a426a66fc1af2792b35d9583904c3fb877b49ae5cea45b7a2aa105ffa4c68606"))), 1786, 2036 +: Seq.fill(3)(2038)), + success(CSigmaProp(ProveDlog(Helpers.decodeECPoint("03a426a66fc1af2792b35d9583904c3fb877b49ae5cea45b7a2aa105ffa4c68606"))), 1786, Seq.fill(4)(2038)), (CSigmaProp(ProveDlog(Helpers.decodeECPoint("03a426a66fc1af2792b35d9583904c3fb877b49ae5cea45b7a2aa105ffa4c68606"))), true) -> - success(CSigmaProp(TrivialProp.TrueProp), 1769, 2019 +: Seq.fill(3)(2021)) + success(CSigmaProp(TrivialProp.TrueProp), 1769, Seq.fill(4)(2021)) ) }, existingFeature( @@ -9314,25 +9314,25 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => Helpers.decodeBytes( "0008ce03c046fccb95549910767d0543f5e8ce41d66ae6a8720a46f4049cac3b3d26dafb023479c9c3b86a0d3c8be3db0a2d186788e9af1db76d55f3dad127d15185d83d0303d7898641cb6653585a8e1dabfa7f665e61e0498963e329e6e3744bd764db2d72037ae057d89ec0b46ff8e9ff4c37e85c12acddb611c3f636421bef1542c11b0441" ) - ), cost = 1771, newDetails(4), expectedNewCost = 1771, 2001 +: Seq.fill(3)(2003)), + ), cost = 1771, newDetails(4), expectedNewCost = 1771, Seq.fill(4)(2003)), CSigmaProp(pk) -> Expected(Success( Helpers.decodeBytes("0008cd039d0b1e46c21540d033143440d2fb7dd5d650cf89981c99ee53c6e0374d2b1b6f")), - cost = 1769, newDetails(1), expectedNewCost = 1769, 1999 +: Seq.fill(3)(2001)), + cost = 1769, newDetails(1), expectedNewCost = 1769, Seq.fill(4)(2001)), CSigmaProp(and) -> Expected(Success( Helpers.decodeBytes( "00089602cd039d0b1e46c21540d033143440d2fb7dd5d650cf89981c99ee53c6e0374d2b1b6fce03c046fccb95549910767d0543f5e8ce41d66ae6a8720a46f4049cac3b3d26dafb023479c9c3b86a0d3c8be3db0a2d186788e9af1db76d55f3dad127d15185d83d0303d7898641cb6653585a8e1dabfa7f665e61e0498963e329e6e3744bd764db2d72037ae057d89ec0b46ff8e9ff4c37e85c12acddb611c3f636421bef1542c11b0441" ) - ), cost = 1772, newDetails(6), expectedNewCost = 1772, 2002 +: Seq.fill(3)(2004)), + ), cost = 1772, newDetails(6), expectedNewCost = 1772, Seq.fill(4)(2004)), CSigmaProp(threshold) -> Expected(Success( Helpers.decodeBytes( "0008980204cd039d0b1e46c21540d033143440d2fb7dd5d650cf89981c99ee53c6e0374d2b1b6fce03c046fccb95549910767d0543f5e8ce41d66ae6a8720a46f4049cac3b3d26dafb023479c9c3b86a0d3c8be3db0a2d186788e9af1db76d55f3dad127d15185d83d0303d7898641cb6653585a8e1dabfa7f665e61e0498963e329e6e3744bd764db2d72037ae057d89ec0b46ff8e9ff4c37e85c12acddb611c3f636421bef1542c11b04419702cd039d0b1e46c21540d033143440d2fb7dd5d650cf89981c99ee53c6e0374d2b1b6fce03c046fccb95549910767d0543f5e8ce41d66ae6a8720a46f4049cac3b3d26dafb023479c9c3b86a0d3c8be3db0a2d186788e9af1db76d55f3dad127d15185d83d0303d7898641cb6653585a8e1dabfa7f665e61e0498963e329e6e3744bd764db2d72037ae057d89ec0b46ff8e9ff4c37e85c12acddb611c3f636421bef1542c11b04419602cd039d0b1e46c21540d033143440d2fb7dd5d650cf89981c99ee53c6e0374d2b1b6fce03c046fccb95549910767d0543f5e8ce41d66ae6a8720a46f4049cac3b3d26dafb023479c9c3b86a0d3c8be3db0a2d186788e9af1db76d55f3dad127d15185d83d0303d7898641cb6653585a8e1dabfa7f665e61e0498963e329e6e3744bd764db2d72037ae057d89ec0b46ff8e9ff4c37e85c12acddb611c3f636421bef1542c11b0441" ) - ), cost = 1780, newDetails(18), expectedNewCost = 1780, 2010 +: Seq.fill(3)(2012)), + ), cost = 1780, newDetails(18), expectedNewCost = 1780, Seq.fill(4)(2012)), CSigmaProp(data.COR(Array(pk, dht, and, or, threshold))) -> Expected(Success( Helpers.decodeBytes( "00089705cd039d0b1e46c21540d033143440d2fb7dd5d650cf89981c99ee53c6e0374d2b1b6fce03c046fccb95549910767d0543f5e8ce41d66ae6a8720a46f4049cac3b3d26dafb023479c9c3b86a0d3c8be3db0a2d186788e9af1db76d55f3dad127d15185d83d0303d7898641cb6653585a8e1dabfa7f665e61e0498963e329e6e3744bd764db2d72037ae057d89ec0b46ff8e9ff4c37e85c12acddb611c3f636421bef1542c11b04419602cd039d0b1e46c21540d033143440d2fb7dd5d650cf89981c99ee53c6e0374d2b1b6fce03c046fccb95549910767d0543f5e8ce41d66ae6a8720a46f4049cac3b3d26dafb023479c9c3b86a0d3c8be3db0a2d186788e9af1db76d55f3dad127d15185d83d0303d7898641cb6653585a8e1dabfa7f665e61e0498963e329e6e3744bd764db2d72037ae057d89ec0b46ff8e9ff4c37e85c12acddb611c3f636421bef1542c11b04419702cd039d0b1e46c21540d033143440d2fb7dd5d650cf89981c99ee53c6e0374d2b1b6fce03c046fccb95549910767d0543f5e8ce41d66ae6a8720a46f4049cac3b3d26dafb023479c9c3b86a0d3c8be3db0a2d186788e9af1db76d55f3dad127d15185d83d0303d7898641cb6653585a8e1dabfa7f665e61e0498963e329e6e3744bd764db2d72037ae057d89ec0b46ff8e9ff4c37e85c12acddb611c3f636421bef1542c11b0441980204cd039d0b1e46c21540d033143440d2fb7dd5d650cf89981c99ee53c6e0374d2b1b6fce03c046fccb95549910767d0543f5e8ce41d66ae6a8720a46f4049cac3b3d26dafb023479c9c3b86a0d3c8be3db0a2d186788e9af1db76d55f3dad127d15185d83d0303d7898641cb6653585a8e1dabfa7f665e61e0498963e329e6e3744bd764db2d72037ae057d89ec0b46ff8e9ff4c37e85c12acddb611c3f636421bef1542c11b04419702cd039d0b1e46c21540d033143440d2fb7dd5d650cf89981c99ee53c6e0374d2b1b6fce03c046fccb95549910767d0543f5e8ce41d66ae6a8720a46f4049cac3b3d26dafb023479c9c3b86a0d3c8be3db0a2d186788e9af1db76d55f3dad127d15185d83d0303d7898641cb6653585a8e1dabfa7f665e61e0498963e329e6e3744bd764db2d72037ae057d89ec0b46ff8e9ff4c37e85c12acddb611c3f636421bef1542c11b04419602cd039d0b1e46c21540d033143440d2fb7dd5d650cf89981c99ee53c6e0374d2b1b6fce03c046fccb95549910767d0543f5e8ce41d66ae6a8720a46f4049cac3b3d26dafb023479c9c3b86a0d3c8be3db0a2d186788e9af1db76d55f3dad127d15185d83d0303d7898641cb6653585a8e1dabfa7f665e61e0498963e329e6e3744bd764db2d72037ae057d89ec0b46ff8e9ff4c37e85c12acddb611c3f636421bef1542c11b0441" ) - ), cost = 1791, newDetails(36), expectedNewCost = 1791, 2021 +: Seq.fill(3)(2023)) + ), cost = 1791, newDetails(36), expectedNewCost = 1791, Seq.fill(4)(2023)) ) }, existingFeature((x: SigmaProp) => x.propBytes, @@ -9343,7 +9343,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => property("allOf equivalence") { def costDetails(i: Int) = TracedCost(traceBase :+ ast.SeqCostItem(CompanionDesc(AND), PerItemCost(JitCost(10), JitCost(5), 32), i)) - val v3Costs = 1995 +: Seq.fill(3)(1997) + val v3Costs = Seq.fill(4)(1997) verifyCases( Seq( (Coll[Boolean]() -> Expected(Success(true), 1765, costDetails(0), 1765, v3Costs)), @@ -9365,7 +9365,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => property("anyOf equivalence") { def costDetails(i: Int) = TracedCost(traceBase :+ ast.SeqCostItem(CompanionDesc(OR), PerItemCost(JitCost(5), JitCost(5), 64), i)) - val v3Costs = 1994 +: Seq.fill(3)(1996) + val v3Costs = Seq.fill(4)(1996) verifyCases( Seq( (Coll[Boolean]() -> Expected(Success(false), 1764, costDetails(0), 1764, v3Costs)), @@ -9395,7 +9395,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => cost = 1782, costDetails, 1782, - 2012 +: Seq.fill(3)(2014))) + Seq.fill(4)(2014))) ), existingFeature({ (x: GroupElement) => SigmaDsl.proveDlog(x) }, "{ (x: GroupElement) => proveDlog(x) }", @@ -9426,7 +9426,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => cost = 1836, costDetails, 1836, - 2078 +: Seq.fill(3)(2080) + Seq.fill(4)(2080) )) ), existingFeature({ (x: GroupElement) => SigmaDsl.proveDHTuple(x, x, x, x) }, @@ -9481,7 +9481,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => newCost = 1783, newVersionedResults = { val costs = if (activatedVersionInTests >= V6SoftForkVersion) { - 2051 +: Seq.fill(3)(2055) + Seq.fill(4)(2055) } else { Seq.fill(4)(1783) @@ -9499,7 +9499,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => newCost = 1783, newVersionedResults = { val costs = if (activatedVersionInTests >= V6SoftForkVersion) { - 2051 +: Seq.fill(3)(2055) + Seq.fill(4)(2055) } else { Seq.fill(4)(1783) @@ -9511,12 +9511,12 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => }) }), // tree with segregation flag, empty constants array - (Coll(t2.bytes: _*), 0) -> success(Helpers.decodeBytes("100008d3"), costDetails(0), 1783, 2051 +: Seq.fill(3)(2055)), - (Helpers.decodeBytes("100008d3"), 0) -> success(Helpers.decodeBytes("100008d3"), costDetails(0), 1783, 2051 +: Seq.fill(3)(2055)), + (Coll(t2.bytes: _*), 0) -> success(Helpers.decodeBytes("100008d3"), costDetails(0), 1783, Seq.fill(4)(2055)), + (Helpers.decodeBytes("100008d3"), 0) -> success(Helpers.decodeBytes("100008d3"), costDetails(0), 1783, Seq.fill(4)(2055)), // tree with one segregated constant - (Coll(t3.bytes: _*), 0) -> success(Helpers.decodeBytes("100108d27300"), costDetails(1), 1793, 2061 +: Seq.fill(3)(2065)), - (Helpers.decodeBytes("100108d37300"), 0) -> success(Helpers.decodeBytes("100108d27300"), costDetails(1), 1793, 2061 +: Seq.fill(3)(2065)), - (Coll(t3.bytes: _*), 1) -> success(Helpers.decodeBytes("100108d37300"), costDetails(1), 1793, 2061 +: Seq.fill(3)(2065)), + (Coll(t3.bytes: _*), 0) -> success(Helpers.decodeBytes("100108d27300"), costDetails(1), 1793, Seq.fill(4)(2065)), + (Helpers.decodeBytes("100108d37300"), 0) -> success(Helpers.decodeBytes("100108d27300"), costDetails(1), 1793, Seq.fill(4)(2065)), + (Coll(t3.bytes: _*), 1) -> success(Helpers.decodeBytes("100108d37300"), costDetails(1), 1793, Seq.fill(4)(2065)), (Coll(t4.bytes: _*), 0) -> Expected(new IllegalArgumentException("requirement failed: expected new constant to have the same SInt$ tpe, got SSigmaProp")) ) }, @@ -9574,7 +9574,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => if (lowerMethodCallsInTests) { val error = new RuntimeException("any exception") val costs = if (activatedVersionInTests >= V6SoftForkVersion) { - 2140 +: Seq.fill(3)(2144) + Seq.fill(4)(2144) } else { Seq.fill(4)(1776) @@ -9701,7 +9701,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => val keys = Colls.fromArray(Array(Coll[Byte](1, 2, 3, 4, 5))) val initial = Coll[Byte](0, 0, 0, 0, 0) val cases = Seq( - (keys, initial) -> Expected(Success(Coll[Byte](1, 2, 3, 4, 5)), cost = 1801, expectedDetails = CostDetails.ZeroCost, 1801, 2115 +: Seq.fill(3)(2119)) + (keys, initial) -> Expected(Success(Coll[Byte](1, 2, 3, 4, 5)), cost = 1801, expectedDetails = CostDetails.ZeroCost, 1801, Seq.fill(4)(2119)) ) val scalaFunc = { (x: (Coll[Coll[Byte]], Coll[Byte])) => x._1.foldLeft(x._2, { (a: (Coll[Byte], Coll[Byte])) => From 3f7e78469107edb59af1c9d1ec5cb7f20a1641f2 Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Mon, 5 Aug 2024 16:26:47 +0300 Subject: [PATCH 18/19] Scala 2.11 compilation fix, ScalaDoc returned --- .../sigmastate/interpreter/Interpreter.scala | 1 - .../scala/sigma/LanguageSpecificationV6.scala | 17 ++++++++--------- .../scala/sigmastate/lang/SigmaBinderTest.scala | 3 +++ .../sigmastate/utxo/BasicOpsSpecification.scala | 1 - 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/interpreter/shared/src/main/scala/sigmastate/interpreter/Interpreter.scala b/interpreter/shared/src/main/scala/sigmastate/interpreter/Interpreter.scala index e7847ef450..6bdf1656dc 100644 --- a/interpreter/shared/src/main/scala/sigmastate/interpreter/Interpreter.scala +++ b/interpreter/shared/src/main/scala/sigmastate/interpreter/Interpreter.scala @@ -3,7 +3,6 @@ package sigmastate.interpreter import debox.cfor import org.ergoplatform.ErgoLikeContext import org.ergoplatform.validation.ValidationRules._ -import scorex.crypto.encode.Base16 import sigma.VersionContext import sigma.ast.SCollection.SByteArray import sigma.ast.syntax._ diff --git a/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala b/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala index b11c1a7903..382c47403c 100644 --- a/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala +++ b/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala @@ -419,17 +419,15 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite => cost = 1793, expectedDetails = CostDetails.ZeroCost, newCost = 2065, - newVersionedResults = expectedSuccessForAllTreeVersions(Helpers.decodeBytes("100108d27300"), 2065, costDetails(1)), + newVersionedResults = expectedSuccessForAllTreeVersions(Helpers.decodeBytes("100108d27300"), 2065, costDetails(1)) ), // for tree version > 0, the result depend on activated version - { - (Coll(t2.bytes: _*), 0) -> Expected( - Success(expectedTreeBytes_beforeV6), - cost = 1793, - expectedDetails = CostDetails.ZeroCost, - newCost = 2065, - newVersionedResults = expectedSuccessForAllTreeVersions(expectedTreeBytes_V6, 2065, costDetails(1))) - } + (Coll(t2.bytes: _*), 0) -> Expected( + Success(expectedTreeBytes_beforeV6), + cost = 1793, + expectedDetails = CostDetails.ZeroCost, + newCost = 2065, + newVersionedResults = expectedSuccessForAllTreeVersions(expectedTreeBytes_V6, 2065, costDetails(1))) ), changedFeature( changedInVersion = VersionContext.V6SoftForkVersion, @@ -464,4 +462,5 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite => tree.constants.length shouldBe t2.constants.length tree.root shouldBe t2.root } + } diff --git a/sc/shared/src/test/scala/sigmastate/lang/SigmaBinderTest.scala b/sc/shared/src/test/scala/sigmastate/lang/SigmaBinderTest.scala index 1f15f5d747..aa552e9b69 100644 --- a/sc/shared/src/test/scala/sigmastate/lang/SigmaBinderTest.scala +++ b/sc/shared/src/test/scala/sigmastate/lang/SigmaBinderTest.scala @@ -31,6 +31,9 @@ class SigmaBinderTest extends AnyPropSpec with ScalaCheckPropertyChecks with Mat res } + /** Checks that parsing and binding results in the expected value. + * @return the inferred type of the expression + */ def checkBound(env: ScriptEnv, x: String, expected: SValue) = { val bound = bind(env, x) if (expected != bound) { diff --git a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala index b2414d36da..40b6caca4d 100644 --- a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala @@ -24,7 +24,6 @@ import sigma.serialization.ErgoTreeSerializer import sigmastate.utils.Helpers._ import java.math.BigInteger -import scala.reflect.internal.pickling.PickleFormat class BasicOpsSpecification extends CompilerTestingCommons with CompilerCrossVersionProps { From 8b17643d0c94335b67794eac7c97852e729c5610 Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Mon, 5 Aug 2024 17:57:14 +0300 Subject: [PATCH 19/19] fixed regression in CrossVersionProps --- .../shared/src/test/scala/sigmastate/CrossVersionProps.scala | 2 ++ 1 file changed, 2 insertions(+) diff --git a/interpreter/shared/src/test/scala/sigmastate/CrossVersionProps.scala b/interpreter/shared/src/test/scala/sigmastate/CrossVersionProps.scala index e55b874dc3..87101a1f71 100644 --- a/interpreter/shared/src/test/scala/sigmastate/CrossVersionProps.scala +++ b/interpreter/shared/src/test/scala/sigmastate/CrossVersionProps.scala @@ -31,7 +31,9 @@ trait CrossVersionProps extends AnyPropSpecLike with TestsBase { System.gc() } forEachScriptAndErgoTreeVersion(activatedVersions, ergoTreeVersions) { + VersionContext.withVersions(activatedVersionInTests, ergoTreeVersionInTests) { testFun_Run(testName, testFun) + } } } }