diff --git a/core/shared/src/main/scala/sigma/VersionContext.scala b/core/shared/src/main/scala/sigma/VersionContext.scala index 6ede0a1556..9efb5911e7 100644 --- a/core/shared/src/main/scala/sigma/VersionContext.scala +++ b/core/shared/src/main/scala/sigma/VersionContext.scala @@ -24,7 +24,10 @@ case class VersionContext(activatedVersion: Byte, ergoTreeVersion: Byte) { /** @return true, if the activated script version of Ergo protocol on the network is * including v6.0 update. */ - def isV6SoftForkActivated: Boolean = activatedVersion >= V6SoftForkVersion + def isV3OrLaterErgoTreeVersion: Boolean = ergoTreeVersion >= V6SoftForkVersion + + def isV6Activated: Boolean = activatedVersion >= V6SoftForkVersion + } object VersionContext { @@ -104,4 +107,8 @@ object VersionContext { } } + def fromBlockVersion(blockVersion: Byte): VersionContext = { + VersionContext((blockVersion - 1).toByte, (blockVersion - 1).toByte) + } + } diff --git a/core/shared/src/main/scala/sigma/ast/SType.scala b/core/shared/src/main/scala/sigma/ast/SType.scala index 3e915cf304..a87b9a8076 100644 --- a/core/shared/src/main/scala/sigma/ast/SType.scala +++ b/core/shared/src/main/scala/sigma/ast/SType.scala @@ -114,7 +114,7 @@ object SType { /** All pre-defined types should be listed here. Note, NoType is not listed. * Should be in sync with sigmastate.lang.Types.predefTypes. */ def allPredefTypes: Seq[SType] = { - if(VersionContext.current.isV6SoftForkActivated) { + if(VersionContext.current.isV3OrLaterErgoTreeVersion) { v6PredefTypes } else { v5PredefTypes @@ -164,7 +164,7 @@ object SType { private val v6TypesMap = v6Types.map { t => (t.typeId, t) }.toMap - def types: Map[Byte, STypeCompanion] = if (VersionContext.current.isV6SoftForkActivated) { + def types: Map[Byte, STypeCompanion] = if (VersionContext.current.isV3OrLaterErgoTreeVersion) { v6TypesMap } else { v5TypesMap @@ -191,7 +191,7 @@ object SType { case SInt => x.isInstanceOf[Int] case SLong => x.isInstanceOf[Long] case SBigInt => x.isInstanceOf[BigInt] - case SUnsignedBigInt if VersionContext.current.isV6SoftForkActivated => x.isInstanceOf[UnsignedBigInt] + case SUnsignedBigInt if VersionContext.current.isV3OrLaterErgoTreeVersion => x.isInstanceOf[UnsignedBigInt] case SGroupElement => x.isInstanceOf[GroupElement] case SSigmaProp => x.isInstanceOf[SigmaProp] case SBox => x.isInstanceOf[Box] @@ -409,8 +409,8 @@ case object SByte extends SPrimType with SEmbeddable with SNumericType with SMon case s: Short => s.toByteExact case i: Int => i.toByteExact case l: Long => l.toByteExact - case bi: BigInt if VersionContext.current.isV6SoftForkActivated => bi.toByte // toByteExact from int is called under the hood - case ubi: UnsignedBigInt if VersionContext.current.isV6SoftForkActivated => ubi.toByte // toByteExact from int is called under the hood + case bi: BigInt if VersionContext.current.isV3OrLaterErgoTreeVersion => bi.toByte // toByteExact from int is called under the hood + case ubi: UnsignedBigInt if VersionContext.current.isV3OrLaterErgoTreeVersion => ubi.toByte // toByteExact from int is called under the hood case _ => sys.error(s"Cannot downcast value $v to the type $this") } } @@ -432,8 +432,8 @@ case object SShort extends SPrimType with SEmbeddable with SNumericType with SMo case s: Short => s case i: Int => i.toShortExact case l: Long => l.toShortExact - case bi: BigInt if VersionContext.current.isV6SoftForkActivated => bi.toShort // toShortExact from int is called under the hood - case ubi: UnsignedBigInt if VersionContext.current.isV6SoftForkActivated => ubi.toShort // toShortExact from int is called under the hood + case bi: BigInt if VersionContext.current.isV3OrLaterErgoTreeVersion => bi.toShort // toShortExact from int is called under the hood + case ubi: UnsignedBigInt if VersionContext.current.isV3OrLaterErgoTreeVersion => ubi.toShort // toShortExact from int is called under the hood case _ => sys.error(s"Cannot downcast value $v to the type $this") } } @@ -457,8 +457,8 @@ case object SInt extends SPrimType with SEmbeddable with SNumericType with SMono case s: Short => s.toInt case i: Int => i case l: Long => l.toIntExact - case bi: BigInt if VersionContext.current.isV6SoftForkActivated => bi.toInt - case ubi: UnsignedBigInt if VersionContext.current.isV6SoftForkActivated => ubi.toInt + case bi: BigInt if VersionContext.current.isV3OrLaterErgoTreeVersion => bi.toInt + case ubi: UnsignedBigInt if VersionContext.current.isV3OrLaterErgoTreeVersion => ubi.toInt case _ => sys.error(s"Cannot downcast value $v to the type $this") } } @@ -484,8 +484,8 @@ case object SLong extends SPrimType with SEmbeddable with SNumericType with SMon case s: Short => s.toLong case i: Int => i.toLong case l: Long => l - case bi: BigInt if VersionContext.current.isV6SoftForkActivated => bi.toLong - case ubi: UnsignedBigInt if VersionContext.current.isV6SoftForkActivated => ubi.toLong + case bi: BigInt if VersionContext.current.isV3OrLaterErgoTreeVersion => bi.toLong + case ubi: UnsignedBigInt if VersionContext.current.isV3OrLaterErgoTreeVersion => ubi.toLong case _ => sys.error(s"Cannot downcast value $v to the type $this") } } @@ -512,7 +512,7 @@ case object SBigInt extends SPrimType with SEmbeddable with SNumericType with SM case x: Short => CBigInt(BigInteger.valueOf(x.toLong)) case x: Int => CBigInt(BigInteger.valueOf(x.toLong)) case x: Long => CBigInt(BigInteger.valueOf(x)) - case x: BigInt if VersionContext.current.isV6SoftForkActivated => x + case x: BigInt if VersionContext.current.isV3OrLaterErgoTreeVersion => x case _ => sys.error(s"Cannot upcast value $v to the type $this") } } @@ -524,7 +524,7 @@ case object SBigInt extends SPrimType with SEmbeddable with SNumericType with SM case x: Short => CBigInt(BigInteger.valueOf(x.toLong)) case x: Int => CBigInt(BigInteger.valueOf(x.toLong)) case x: Long => CBigInt(BigInteger.valueOf(x)) - case x: BigInt if VersionContext.current.isV6SoftForkActivated => x + case x: BigInt if VersionContext.current.isV3OrLaterErgoTreeVersion => x case _ => sys.error(s"Cannot downcast value $v to the type $this") } } diff --git a/core/shared/src/main/scala/sigma/data/CollsOverArrays.scala b/core/shared/src/main/scala/sigma/data/CollsOverArrays.scala index 2d6a4a5cdf..dbaa430b69 100644 --- a/core/shared/src/main/scala/sigma/data/CollsOverArrays.scala +++ b/core/shared/src/main/scala/sigma/data/CollsOverArrays.scala @@ -150,7 +150,7 @@ class CollOverArray[@specialized A](val toArray: Array[A], val builder: CollBuil case obj: CollOverArray[_] if obj.tItem == this.tItem => java.util.Objects.deepEquals(obj.toArray, this.toArray) case obj: PairColl[Any, Any] if obj.tItem == this.tItem => - if (VersionContext.current.isV6SoftForkActivated) { + if (VersionContext.current.isV3OrLaterErgoTreeVersion) { equalsPairCollWithCollOverArray(obj, this.asInstanceOf[CollOverArray[Any]]) } else { false @@ -282,7 +282,7 @@ class PairOfCols[@specialized L, @specialized R](val ls: Coll[L], val rs: Coll[R case that: PairColl[_, _] if that.tItem == this.tItem => ls == that.ls && rs == that.rs case that: CollOverArray[Any] if that.tItem == this.tItem => - if (VersionContext.current.isV6SoftForkActivated) { + if (VersionContext.current.isV3OrLaterErgoTreeVersion) { equalsPairCollWithCollOverArray(this.asInstanceOf[PairColl[Any, Any]], that) } else { false diff --git a/core/shared/src/main/scala/sigma/serialization/CoreDataSerializer.scala b/core/shared/src/main/scala/sigma/serialization/CoreDataSerializer.scala index 175e91fbcb..1f6f95b471 100644 --- a/core/shared/src/main/scala/sigma/serialization/CoreDataSerializer.scala +++ b/core/shared/src/main/scala/sigma/serialization/CoreDataSerializer.scala @@ -34,7 +34,7 @@ class CoreDataSerializer { val data = v.asInstanceOf[BigInt].toBigInteger.toByteArray w.putUShort(data.length) w.putBytes(data) - case SUnsignedBigInt if VersionContext.current.isV6SoftForkActivated => + case SUnsignedBigInt if VersionContext.current.isV3OrLaterErgoTreeVersion => val data = BigIntegers.asUnsignedByteArray(v.asInstanceOf[CUnsignedBigInt].wrappedValue) w.putUShort(data.length) w.putBytes(data) @@ -73,7 +73,7 @@ class CoreDataSerializer { i += 1 } - case SOption(elemType) if VersionContext.current.isV6SoftForkActivated => + case SOption(elemType) if VersionContext.current.isV3OrLaterErgoTreeVersion => val o = v.asInstanceOf[Option[elemType.WrappedType]] w.putOption(o){case (w, v) => serialize(v, elemType, w) @@ -113,7 +113,7 @@ class CoreDataSerializer { } val valueBytes = r.getBytes(size) CBigInt(new BigInteger(valueBytes)) - case SUnsignedBigInt if VersionContext.current.isV6SoftForkActivated => + case SUnsignedBigInt if VersionContext.current.isV3OrLaterErgoTreeVersion => val size: Short = r.getUShort().toShort if (size > SBigInt.MaxSizeInBytes) { throw SerializerException(s"BigInt value doesn't not fit into ${SBigInt.MaxSizeInBytes} bytes: $size") @@ -135,7 +135,7 @@ class CoreDataSerializer { }.toArray[Any] val coll = Colls.fromArray(arr)(sigma.AnyType) Evaluation.toDslTuple(coll, tuple) - case tOption: SOption[_] if VersionContext.current.isV6SoftForkActivated => + case tOption: SOption[_] if VersionContext.current.isV3OrLaterErgoTreeVersion => r.getOption[tOption.ElemWrappedType] { deserialize(tOption.elemType, r).asInstanceOf[tOption.ElemWrappedType] } diff --git a/core/shared/src/main/scala/sigma/serialization/TypeSerializer.scala b/core/shared/src/main/scala/sigma/serialization/TypeSerializer.scala index aa5d43e229..51f4c834af 100644 --- a/core/shared/src/main/scala/sigma/serialization/TypeSerializer.scala +++ b/core/shared/src/main/scala/sigma/serialization/TypeSerializer.scala @@ -5,7 +5,7 @@ import sigma.VersionContext import sigma.ast.SCollectionType.{CollectionTypeCode, NestedCollectionTypeCode} import sigma.ast._ import sigma.util.safeNewArray -import sigma.validation.ValidationRules.{CheckPrimitiveTypeCode, CheckTypeCode} +import sigma.validation.ValidationRules.{CheckPrimitiveTypeCode, CheckPrimitiveTypeCodeV6, CheckTypeCode, CheckTypeCodeV6} import java.nio.charset.StandardCharsets @@ -14,7 +14,12 @@ class TypeSerializer { import TypeSerializer._ def getEmbeddableType(code: Int): SType = { - CheckPrimitiveTypeCode(code.toByte) + // todo : add unsigned bit int to embeddable id to type + if (VersionContext.current.isV6Activated) { + CheckPrimitiveTypeCodeV6(code.toByte) + } else { + CheckPrimitiveTypeCode(code.toByte) + } embeddableIdToType(code) } @@ -200,7 +205,7 @@ class TypeSerializer { case SHeader.typeCode => SHeader case SPreHeader.typeCode => SPreHeader case SGlobal.typeCode => SGlobal - case SFunc.FuncTypeCode if VersionContext.current.isV6SoftForkActivated => + case SFunc.FuncTypeCode if VersionContext.current.isV3OrLaterErgoTreeVersion => val tdLength = r.getUByte() val tDom = (1 to tdLength).map { _ => @@ -215,9 +220,13 @@ class TypeSerializer { } SFunc(tDom, tRange, tpeParams) case _ => - // todo: 6.0: replace 1008 check with identical behavior but other opcode, to activate - // ReplacedRule(1008 -> new opcode) during 6.0 activation - CheckTypeCode(c.toByte) + // the #1008 check replaced with one with identical behavior but different opcode (1018), to activate + // ReplacedRule(1008 -> 1018) during 6.0 activation + if (VersionContext.current.isV6Activated) { + CheckTypeCodeV6(c.toByte) + } else { + CheckTypeCode(c.toByte) + } NoType } } @@ -243,7 +252,7 @@ object TypeSerializer extends TypeSerializer { /** The list of embeddable types, i.e. types that can be combined with type constructor for optimized encoding. * For each embeddable type `T`, and type constructor `C`, the type `C[T]` can be represented by single byte. */ def embeddableIdToType = { - if (VersionContext.current.isV6SoftForkActivated) { + if (VersionContext.current.isV3OrLaterErgoTreeVersion) { embeddableV6 } else { embeddableV5 diff --git a/core/shared/src/main/scala/sigma/validation/RuleStatus.scala b/core/shared/src/main/scala/sigma/validation/RuleStatus.scala index 3d0451b240..ae1a380898 100644 --- a/core/shared/src/main/scala/sigma/validation/RuleStatus.scala +++ b/core/shared/src/main/scala/sigma/validation/RuleStatus.scala @@ -32,7 +32,7 @@ case object DisabledRule extends RuleStatus { * @see `ValidationSettings.isSoftFork` * @param newRuleId id of a new rule which replaces the rule marked with this status */ -case class ReplacedRule(newRuleId: Short) extends RuleStatus { +case class ReplacedRule(newRuleId: Short) extends RuleStatus { val statusCode: Byte = RuleStatus.ReplacedRuleCode } diff --git a/core/shared/src/main/scala/sigma/validation/SigmaValidationSettings.scala b/core/shared/src/main/scala/sigma/validation/SigmaValidationSettings.scala index 51fb97c8ad..9063f88bfb 100644 --- a/core/shared/src/main/scala/sigma/validation/SigmaValidationSettings.scala +++ b/core/shared/src/main/scala/sigma/validation/SigmaValidationSettings.scala @@ -1,5 +1,7 @@ package sigma.validation +import sigma.VersionContext + /** * Configuration of validation. Each `ValidationRule` instance should be * implemented as an `object` to facilitate type-safe usage. It then should be @@ -48,7 +50,11 @@ abstract class SigmaValidationSettings extends Iterable[(Short, (ValidationRule, def isSoftFork(ruleId: Short, ve: ValidationException): Boolean = { val infoOpt = get(ruleId) infoOpt match { - case Some((_, ReplacedRule(_))) => true + case Some((vr, ReplacedRule(_))) => if ((vr.id == 1011 || vr.id == 1007 || vr.id == 1008) && VersionContext.current.isV6Activated) { + false + } else { + true + } case Some((rule, status)) => rule.isSoftFork(this, rule.id, status, ve.args) case None => false } diff --git a/core/shared/src/main/scala/sigma/validation/ValidationRules.scala b/core/shared/src/main/scala/sigma/validation/ValidationRules.scala index 249e2fce0a..3cae0a3f27 100644 --- a/core/shared/src/main/scala/sigma/validation/ValidationRules.scala +++ b/core/shared/src/main/scala/sigma/validation/ValidationRules.scala @@ -1,6 +1,6 @@ package sigma.validation -import sigma.SigmaException +import sigma.{SigmaException, VersionContext} import sigma.ast.{SGlobal, SOption, TypeCodes} import sigma.serialization.{ReaderPositionLimitExceeded, SerializerException} import sigma.util.Extensions.toUByte @@ -77,7 +77,7 @@ object ValidationRules { /** The id of the first validation rule. Can be used as the beginning of the rules id range. */ val FirstRuleId = 1000.toShort - object CheckPrimitiveTypeCode extends ValidationRule(1007, + class CheckPrimitiveTypeCodeTemplate(ruleId: Short) extends ValidationRule(ruleId, "Check the primitive type code is supported or is added via soft-fork") with SoftForkWhenCodeAdded { override protected lazy val settings: SigmaValidationSettings = coreSettings @@ -93,10 +93,14 @@ object ValidationRules { } } - object CheckTypeCode extends ValidationRule(1008, + object CheckPrimitiveTypeCode extends CheckPrimitiveTypeCodeTemplate(1007) + + object CheckPrimitiveTypeCodeV6 extends CheckPrimitiveTypeCodeTemplate(1017) + + class CheckTypeCodeTemplate(ruleId: Short) extends ValidationRule(ruleId, "Check the non-primitive type code is supported or is added via soft-fork") with SoftForkWhenCodeAdded { - override protected lazy val settings: SigmaValidationSettings = coreSettings + override protected def settings: SigmaValidationSettings = coreSettings final def apply[T](typeCode: Byte): Unit = { checkRule() @@ -109,10 +113,14 @@ object ValidationRules { } } + object CheckTypeCode extends CheckTypeCodeTemplate(1008) + + object CheckTypeCodeV6 extends CheckTypeCodeTemplate(1018) + object CheckSerializableTypeCode extends ValidationRule(1009, "Check the data values of the type (given by type code) can be serialized") with SoftForkWhenReplaced { - override protected lazy val settings: SigmaValidationSettings = coreSettings + override protected def settings: SigmaValidationSettings = coreSettings /** Creates an exception which is used as a cause when throwing a ValidationException. */ def throwValidationException(typeCode: Byte): Nothing = { @@ -141,7 +149,7 @@ object ValidationRules { object CheckTypeWithMethods extends ValidationRule(1010, "Check the type (given by type code) supports methods") with SoftForkWhenCodeAdded { - override protected lazy val settings: SigmaValidationSettings = coreSettings + override protected def settings: SigmaValidationSettings = coreSettings final def apply[T](typeCode: Byte, cond: Boolean): Unit = { checkRule() @@ -160,7 +168,7 @@ object ValidationRules { */ object CheckPositionLimit extends ValidationRule(1014, "Check that the Reader has not exceeded the position limit.") with SoftForkWhenReplaced { - override protected lazy val settings: SigmaValidationSettings = coreSettings + override protected def settings: SigmaValidationSettings = coreSettings /** Wraps the given cause into [[ValidationException]] and throws it. */ def throwValidationException(cause: ReaderPositionLimitExceeded): Nothing = { @@ -183,7 +191,7 @@ object ValidationRules { } } - private val ruleSpecs: Seq[ValidationRule] = Seq( + private val ruleSpecsV5: Seq[ValidationRule] = Seq( CheckPrimitiveTypeCode, CheckTypeCode, CheckSerializableTypeCode, @@ -191,13 +199,30 @@ object ValidationRules { CheckPositionLimit ) + private val ruleSpecsV6: Seq[ValidationRule] = Seq( + CheckPrimitiveTypeCodeV6, + CheckTypeCodeV6, + CheckSerializableTypeCode, + CheckTypeWithMethods, + CheckPositionLimit + ) + + private def ruleSpecs: Seq[ValidationRule] = { + if(VersionContext.current.isV6Activated) { + ruleSpecsV6 + } else { + ruleSpecsV5 + } + } + /** Validation settings that correspond to the current version of the ErgoScript implementation. * Different version of the code will have a different set of rules here. * This variable is globally available and can be use wherever checking of the rules is necessary. * This is immutable data structure, it can be augmented with RuleStates from block extension * sections of the blockchain, but that augmentation is only available in stateful context. */ - val coreSettings: SigmaValidationSettings = new MapSigmaValidationSettings({ + // todo: versioned cache here for efficiency + def coreSettings: SigmaValidationSettings = new MapSigmaValidationSettings({ val map = ruleSpecs.map(r => r.id -> (r, EnabledRule)).toMap assert(map.size == ruleSpecs.size, s"Duplicate ruleIds ${ruleSpecs.groupBy(_.id).filter(g => g._2.length > 1)}") map diff --git a/data/js/src/main/scala/sigma/Platform.scala b/data/js/src/main/scala/sigma/Platform.scala index 63c2ab5555..9db049b368 100644 --- a/data/js/src/main/scala/sigma/Platform.scala +++ b/data/js/src/main/scala/sigma/Platform.scala @@ -14,33 +14,33 @@ object Platform { private[sigma] def liftToConstant(obj: Any, builder: SigmaBuilder): Nullable[Constant[SType]] = { import builder._ obj match { - case arr: Array[Boolean] if !VersionContext.current.isV6SoftForkActivated => Nullable(mkCollectionConstant[SBoolean.type](arr, SBoolean)) - case arr: Array[Byte] if !VersionContext.current.isV6SoftForkActivated => Nullable(mkCollectionConstant[SByte.type](arr, SByte)) - case arr: Array[Short] if !VersionContext.current.isV6SoftForkActivated => Nullable(mkCollectionConstant[SShort.type](arr, SShort)) - case arr: Array[Int] if !VersionContext.current.isV6SoftForkActivated => Nullable(mkCollectionConstant[SInt.type](arr, SInt)) - case arr: Array[Long] if !VersionContext.current.isV6SoftForkActivated => Nullable(mkCollectionConstant[SLong.type](arr, SLong)) - case arr: Array[BigInteger] if !VersionContext.current.isV6SoftForkActivated => Nullable(mkCollectionConstant[SBigInt.type](arr.map[BigInt](n => CBigInt(n)), SBigInt)) - case arr: Array[String] if !VersionContext.current.isV6SoftForkActivated => Nullable(mkCollectionConstant[SString.type](arr, SString)) + case arr: Array[Boolean] if !VersionContext.current.isV3OrLaterErgoTreeVersion => Nullable(mkCollectionConstant[SBoolean.type](arr, SBoolean)) + case arr: Array[Byte] if !VersionContext.current.isV3OrLaterErgoTreeVersion => Nullable(mkCollectionConstant[SByte.type](arr, SByte)) + case arr: Array[Short] if !VersionContext.current.isV3OrLaterErgoTreeVersion => Nullable(mkCollectionConstant[SShort.type](arr, SShort)) + case arr: Array[Int] if !VersionContext.current.isV3OrLaterErgoTreeVersion => Nullable(mkCollectionConstant[SInt.type](arr, SInt)) + case arr: Array[Long] if !VersionContext.current.isV3OrLaterErgoTreeVersion => Nullable(mkCollectionConstant[SLong.type](arr, SLong)) + case arr: Array[BigInteger] if !VersionContext.current.isV3OrLaterErgoTreeVersion => Nullable(mkCollectionConstant[SBigInt.type](arr.map[BigInt](n => CBigInt(n)), SBigInt)) + case arr: Array[String] if !VersionContext.current.isV3OrLaterErgoTreeVersion => Nullable(mkCollectionConstant[SString.type](arr, SString)) case v: AnyValue => val tpe = Evaluation.rtypeToSType(v.tVal) Nullable(mkConstant[tpe.type](v.value.asInstanceOf[tpe.WrappedType], tpe)) case v: Int => Nullable(mkConstant[SInt.type](v, SInt)) case v: Long => Nullable(mkConstant[SLong.type](v, SLong)) - case v: BigInteger if !VersionContext.current.isV6SoftForkActivated => Nullable(mkConstant[SBigInt.type](CBigInt(v), SBigInt)) + case v: BigInteger if !VersionContext.current.isV3OrLaterErgoTreeVersion => Nullable(mkConstant[SBigInt.type](CBigInt(v), SBigInt)) case n: sigma.BigInt => Nullable(mkConstant[SBigInt.type](n, SBigInt)) case n: sigma.UnsignedBigInt => Nullable(mkConstant[SUnsignedBigInt.type](n, SUnsignedBigInt)) case ge: GroupElement => Nullable(mkConstant[SGroupElement.type](ge, SGroupElement)) case b: Boolean => Nullable(if (b) TrueLeaf else FalseLeaf) - case v: String if !VersionContext.current.isV6SoftForkActivated => Nullable(mkConstant[SString.type](v, SString)) - case h: Header if VersionContext.current.isV6SoftForkActivated => Nullable(mkConstant[SHeader.type](h, SHeader)) - case h: PreHeader if VersionContext.current.isV6SoftForkActivated => Nullable(mkConstant[SPreHeader.type](h, SPreHeader)) + case v: String if !VersionContext.current.isV3OrLaterErgoTreeVersion => Nullable(mkConstant[SString.type](v, SString)) + case h: Header if VersionContext.current.isV3OrLaterErgoTreeVersion => Nullable(mkConstant[SHeader.type](h, SHeader)) + case h: PreHeader if VersionContext.current.isV3OrLaterErgoTreeVersion => Nullable(mkConstant[SPreHeader.type](h, SPreHeader)) // The Box lifting was broken in v4.x. `SigmaDsl.Box(b)` was missing which means the // isCorrectType requirement would fail in ConstantNode constructor. // This method is used as part of consensus in SubstConstants operation, however // ErgoBox cannot be passed as argument as it is never valid value during evaluation. // Thus we can use activation-based versioning and fix this code when v5.0 is activated. - case b: ErgoBox if !VersionContext.current.isV6SoftForkActivated => + case b: ErgoBox if !VersionContext.current.isV3OrLaterErgoTreeVersion => Nullable(mkConstant[SBox.type](CBox(b), SBox)) // fixed in v5.0 // this case is added in v5.0 and it can be useful when the box value comes from a @@ -50,7 +50,7 @@ object Platform { Nullable(mkConstant[SBox.type](b, SBox)) else Nullable.None // return the same result as in v4.x when there was no this case - case avl: AvlTreeData if !VersionContext.current.isV6SoftForkActivated => Nullable(mkConstant[SAvlTree.type](CAvlTree(avl), SAvlTree)) + case avl: AvlTreeData if !VersionContext.current.isV3OrLaterErgoTreeVersion => Nullable(mkConstant[SAvlTree.type](CAvlTree(avl), SAvlTree)) case avl: AvlTree => Nullable(mkConstant[SAvlTree.type](avl, SAvlTree)) case sb: SigmaBoolean => Nullable(mkConstant[SSigmaProp.type](CSigmaProp(sb), SSigmaProp)) case p: SigmaProp => Nullable(mkConstant[SSigmaProp.type](p, SSigmaProp)) diff --git a/data/jvm/src/main/scala/sigma/Platform.scala b/data/jvm/src/main/scala/sigma/Platform.scala index 8fc5019bf9..178ae242c7 100644 --- a/data/jvm/src/main/scala/sigma/Platform.scala +++ b/data/jvm/src/main/scala/sigma/Platform.scala @@ -16,33 +16,33 @@ object Platform { private[sigma] def liftToConstant(obj: Any, builder: SigmaBuilder): Nullable[Constant[SType]] = { import builder._ obj match { - case arr: Array[Boolean] if !VersionContext.current.isV6SoftForkActivated => Nullable(mkCollectionConstant[SBoolean.type](arr, SBoolean)) - case arr: Array[Byte] if !VersionContext.current.isV6SoftForkActivated => Nullable(mkCollectionConstant[SByte.type](arr, SByte)) - case arr: Array[Short] if !VersionContext.current.isV6SoftForkActivated => Nullable(mkCollectionConstant[SShort.type](arr, SShort)) - case arr: Array[Int] if !VersionContext.current.isV6SoftForkActivated => Nullable(mkCollectionConstant[SInt.type](arr, SInt)) - case arr: Array[Long] if !VersionContext.current.isV6SoftForkActivated => Nullable(mkCollectionConstant[SLong.type](arr, SLong)) - case arr: Array[BigInteger] if !VersionContext.current.isV6SoftForkActivated => Nullable(mkCollectionConstant[SBigInt.type](arr.map(SigmaDsl.BigInt(_)), SBigInt)) - case arr: Array[String] if !VersionContext.current.isV6SoftForkActivated => Nullable(mkCollectionConstant[SString.type](arr, SString)) + case arr: Array[Boolean] if !VersionContext.current.isV3OrLaterErgoTreeVersion => Nullable(mkCollectionConstant[SBoolean.type](arr, SBoolean)) + case arr: Array[Byte] if !VersionContext.current.isV3OrLaterErgoTreeVersion => Nullable(mkCollectionConstant[SByte.type](arr, SByte)) + case arr: Array[Short] if !VersionContext.current.isV3OrLaterErgoTreeVersion => Nullable(mkCollectionConstant[SShort.type](arr, SShort)) + case arr: Array[Int] if !VersionContext.current.isV3OrLaterErgoTreeVersion => Nullable(mkCollectionConstant[SInt.type](arr, SInt)) + case arr: Array[Long] if !VersionContext.current.isV3OrLaterErgoTreeVersion => Nullable(mkCollectionConstant[SLong.type](arr, SLong)) + case arr: Array[BigInteger] if !VersionContext.current.isV3OrLaterErgoTreeVersion => Nullable(mkCollectionConstant[SBigInt.type](arr.map(SigmaDsl.BigInt(_)), SBigInt)) + case arr: Array[String] if !VersionContext.current.isV3OrLaterErgoTreeVersion => Nullable(mkCollectionConstant[SString.type](arr, SString)) case v: Byte => Nullable(mkConstant[SByte.type](v, SByte)) case v: Short => Nullable(mkConstant[SShort.type](v, SShort)) case v: Int => Nullable(mkConstant[SInt.type](v, SInt)) case v: Long => Nullable(mkConstant[SLong.type](v, SLong)) - case v: BigInteger if !VersionContext.current.isV6SoftForkActivated => Nullable(mkConstant[SBigInt.type](SigmaDsl.BigInt(v), SBigInt)) + case v: BigInteger if !VersionContext.current.isV3OrLaterErgoTreeVersion => Nullable(mkConstant[SBigInt.type](SigmaDsl.BigInt(v), SBigInt)) case n: sigma.BigInt => Nullable(mkConstant[SBigInt.type](n, SBigInt)) case ge: GroupElement => Nullable(mkConstant[SGroupElement.type](ge, SGroupElement)) case b: Boolean => Nullable(if (b) TrueLeaf else FalseLeaf) - case h: Header if VersionContext.current.isV6SoftForkActivated => Nullable(mkConstant[SHeader.type](h, SHeader)) - case h: PreHeader if VersionContext.current.isV6SoftForkActivated => Nullable(mkConstant[SPreHeader.type](h, SPreHeader)) - case n: sigma.UnsignedBigInt if VersionContext.current.isV6SoftForkActivated => Nullable(mkConstant[SUnsignedBigInt.type](n, SUnsignedBigInt)) + case h: Header if VersionContext.current.isV3OrLaterErgoTreeVersion => Nullable(mkConstant[SHeader.type](h, SHeader)) + case h: PreHeader if VersionContext.current.isV3OrLaterErgoTreeVersion => Nullable(mkConstant[SPreHeader.type](h, SPreHeader)) + case n: sigma.UnsignedBigInt if VersionContext.current.isV3OrLaterErgoTreeVersion => Nullable(mkConstant[SUnsignedBigInt.type](n, SUnsignedBigInt)) - case v: String if !VersionContext.current.isV6SoftForkActivated => Nullable(mkConstant[SString.type](v, SString)) + case v: String if !VersionContext.current.isV3OrLaterErgoTreeVersion => Nullable(mkConstant[SString.type](v, SString)) // The Box lifting was broken in v4.x. `SigmaDsl.Box(b)` was missing which means the // isCorrectType requirement would fail in ConstantNode constructor. // This method is used as part of consensus in SubstConstants operation, however // ErgoBox cannot be passed as argument as it is never valid value during evaluation. // Thus we can use activation-based versioning and fix this code when v5.0 is activated. - case b: ErgoBox if !VersionContext.current.isV6SoftForkActivated => + case b: ErgoBox if !VersionContext.current.isV3OrLaterErgoTreeVersion => Nullable(mkConstant[SBox.type](SigmaDsl.Box(b), SBox)) // fixed in v5.0 // this case is added in v5.0 and it can be useful when the box value comes from a @@ -52,7 +52,7 @@ object Platform { Nullable(mkConstant[SBox.type](b, SBox)) else Nullable.None // return the same result as in v4.x when there was no this case - case avl: AvlTreeData if !VersionContext.current.isV6SoftForkActivated => Nullable(mkConstant[SAvlTree.type](SigmaDsl.avlTree(avl), SAvlTree)) + case avl: AvlTreeData if !VersionContext.current.isV3OrLaterErgoTreeVersion => Nullable(mkConstant[SAvlTree.type](SigmaDsl.avlTree(avl), SAvlTree)) case avl: AvlTree => Nullable(mkConstant[SAvlTree.type](avl, SAvlTree)) case sb: SigmaBoolean => Nullable(mkConstant[SSigmaProp.type](SigmaDsl.SigmaProp(sb), SSigmaProp)) case p: SigmaProp => Nullable(mkConstant[SSigmaProp.type](p, SSigmaProp)) 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..ed461aa2f2 100644 --- a/data/shared/src/main/scala/org/ergoplatform/validation/ValidationRules.scala +++ b/data/shared/src/main/scala/org/ergoplatform/validation/ValidationRules.scala @@ -1,6 +1,6 @@ package org.ergoplatform.validation -import sigma.SigmaException +import sigma.{SigmaException, VersionContext} import sigma.ast.{DeserializeContext, ErgoTree, MethodsContainer, SMethod} import sigma.ast.TypeCodes.LastConstantCode import sigma.serialization.{InvalidOpCode, SerializerException} @@ -23,7 +23,7 @@ object ValidationRules { object CheckDeserializedScriptType extends ValidationRule(FirstRuleId, "Deserialized script should have expected type") { - override protected lazy val settings: SigmaValidationSettings = currentSettings + override protected def settings: SigmaValidationSettings = currentSettings final def apply[T](d: DeserializeContext[_], script: SValue): Unit = { checkRule() @@ -38,7 +38,7 @@ object ValidationRules { object CheckDeserializedScriptIsSigmaProp extends ValidationRule(1001, "Deserialized script should have SigmaProp type") { - override protected lazy val settings: SigmaValidationSettings = currentSettings + override protected def settings: SigmaValidationSettings = currentSettings /** @param root candidate node before it is added as a root of ErgoTree */ final def apply[T](root: SValue): Unit = { @@ -54,7 +54,7 @@ object ValidationRules { object CheckValidOpCode extends ValidationRule(1002, "Check the opcode is supported by registered serializer or is added via soft-fork") with SoftForkWhenCodeAdded { - override protected lazy val settings: SigmaValidationSettings = currentSettings + override protected def settings: SigmaValidationSettings = currentSettings final def apply[T](ser: ValueSerializer[_], opCode: OpCode): Unit = { checkRule() @@ -69,18 +69,18 @@ object ValidationRules { /** Not used since v5.0.1. */ object CheckIsSupportedIndexExpression extends ValidationRule(1003, "Check the index expression for accessing collection element is supported.") { - override protected lazy val settings: SigmaValidationSettings = currentSettings + override protected def settings: SigmaValidationSettings = currentSettings } /** Not used since v5.0.3 */ object CheckCostFunc extends ValidationRule(1004, "Cost function should contain only operations from specified list.") { - override protected lazy val settings: SigmaValidationSettings = currentSettings + override protected def settings: SigmaValidationSettings = currentSettings } object CheckCalcFunc extends ValidationRule(1005, "If SigmaProp.isProven method calls exists in the given function,\n then it is the last operation") { - override protected lazy val settings: SigmaValidationSettings = currentSettings + override protected def settings: SigmaValidationSettings = currentSettings } /** This rule is not use in v5.x, keep the commented code below as a precise @@ -88,7 +88,7 @@ object ValidationRules { */ object CheckTupleType extends ValidationRule(1006, "Supported tuple type.") with SoftForkWhenReplaced { - override protected lazy val settings: SigmaValidationSettings = currentSettings + override protected def settings: SigmaValidationSettings = currentSettings // final def apply[Ctx <: IRContext, T](ctx: Ctx)(e: ctx.Elem[_]): Unit = { // checkRule() @@ -102,15 +102,16 @@ object ValidationRules { // } } - object CheckAndGetMethod extends ValidationRule(1011, + class CheckAndGetMethodTemplate(ruleId: Short) extends ValidationRule(ruleId, "Check the type has the declared method.") { - override protected lazy val settings: SigmaValidationSettings = currentSettings + override protected def settings: SigmaValidationSettings = currentSettings final def apply[T](objType: MethodsContainer, methodId: Byte): SMethod = { checkRule() val methodOpt = objType.getMethodById(methodId) - if (methodOpt.isDefined) methodOpt.get - else { + if (methodOpt.isDefined) { + methodOpt.get + } else { throwValidationException( new SerializerException(s"The method with code $methodId doesn't declared in the type $objType."), Array[Any](objType, methodId)) @@ -120,17 +121,30 @@ object ValidationRules { override def isSoftFork(vs: SigmaValidationSettings, ruleId: Short, status: RuleStatus, - args: Seq[Any]): Boolean = (status, args) match { - case (ChangedRule(newValue), Seq(objType: MethodsContainer, methodId: Byte)) => - val key = Array(objType.ownerType.typeId, methodId) - newValue.grouped(2).exists(java.util.Arrays.equals(_, key)) - case _ => false + args: Seq[Any]): Boolean = { + (status, args) match { + case (ChangedRule(newValue), Seq(objType: MethodsContainer, methodId: Byte)) => + val key = Array(objType.ownerType.typeId, methodId) + newValue.grouped(2).exists(java.util.Arrays.equals(_, key)) + case _ => false + } + } + } + + object CheckAndGetMethod extends CheckAndGetMethodTemplate(1011) { + override def isSoftFork(vs: SigmaValidationSettings, + ruleId: Short, + status: RuleStatus, + args: Seq[Any]): Boolean = { + false } } + object CheckAndGetMethodV6 extends CheckAndGetMethodTemplate(1016) + object CheckHeaderSizeBit extends ValidationRule(1012, "For version greater then 0, size bit should be set.") with SoftForkWhenReplaced { - override protected lazy val settings: SigmaValidationSettings = currentSettings + override protected def settings: SigmaValidationSettings = currentSettings final def apply(header: HeaderType): Unit = { checkRule() @@ -146,16 +160,16 @@ object ValidationRules { /** Not used since v5.0.3 */ object CheckCostFuncOperation extends ValidationRule(1013, "Check the opcode is allowed in cost function") { - override protected lazy val settings: SigmaValidationSettings = currentSettings + override protected def settings: SigmaValidationSettings = currentSettings } /** Not used since v5.0.1 */ object CheckLoopLevelInCostFunction extends ValidationRule(1015, "Check that loop level is not exceeded.") { - override protected lazy val settings: SigmaValidationSettings = currentSettings + override protected def settings: SigmaValidationSettings = currentSettings } - val ruleSpecs: Seq[ValidationRule] = Seq( + private val ruleSpecsV5: Seq[ValidationRule] = Seq( CheckDeserializedScriptType, CheckDeserializedScriptIsSigmaProp, CheckValidOpCode, @@ -174,13 +188,26 @@ object ValidationRules { CheckLoopLevelInCostFunction ) + // v6 validation rules below + private val ruleSpecsV6: Seq[ValidationRule] = { + ruleSpecsV5.filter(_.id != CheckAndGetMethod.id) ++ Seq(CheckAndGetMethodV6) + } + + def ruleSpecs: Seq[ValidationRule] = { + if (VersionContext.current.isV6Activated) { + ruleSpecsV6 + } else { + ruleSpecsV5 + } + } + /** Validation settings that correspond to the current version of the ErgoScript implementation. * Different version of the code will have a different set of rules here. * This variable is globally available and can be use wherever checking of the rules is necessary. * This is immutable data structure, it can be augmented with RuleStates from block extension * sections of the blockchain, but that augmentation is only available in stateful context. */ - val currentSettings: SigmaValidationSettings = new MapSigmaValidationSettings({ + def currentSettings: SigmaValidationSettings = new MapSigmaValidationSettings({ val map = ruleSpecs.map(r => r.id -> (r, EnabledRule)).toMap assert(map.size == ruleSpecs.size, s"Duplicate ruleIds ${ruleSpecs.groupBy(_.id).filter(g => g._2.length > 1)}") map diff --git a/data/shared/src/main/scala/sigma/ast/ErgoTree.scala b/data/shared/src/main/scala/sigma/ast/ErgoTree.scala index 8d731e1c67..ec902a20eb 100644 --- a/data/shared/src/main/scala/sigma/ast/ErgoTree.scala +++ b/data/shared/src/main/scala/sigma/ast/ErgoTree.scala @@ -375,7 +375,7 @@ object ErgoTree { * 3) write the `tree` to the Writer's buffer obtaining `treeBytes`; * 4) deserialize `tree` with ConstantPlaceholders. * - * @param headerFlags additional header flags to combine with + * @param header additional header flags to combine with * ConstantSegregationHeader flag. * @param prop expression to be transformed into ErgoTree * */ @@ -411,4 +411,5 @@ object ErgoTree { def fromBytes(bytes: Array[Byte]): ErgoTree = { ErgoTreeSerializer.DefaultSerializer.deserializeErgoTree(bytes) } + } diff --git a/data/shared/src/main/scala/sigma/ast/methods.scala b/data/shared/src/main/scala/sigma/ast/methods.scala index 25ad4f94cb..74c6d42776 100644 --- a/data/shared/src/main/scala/sigma/ast/methods.scala +++ b/data/shared/src/main/scala/sigma/ast/methods.scala @@ -85,13 +85,17 @@ sealed trait MethodsContainer { /** Lookup method in this type by method's id or throw ValidationException. * This method can be used in trySoftForkable section to either obtain valid method - * or catch ValidatioinException which can be checked for soft-fork condition. + * or catch ValidationException which can be checked for soft-fork condition. * It delegate to getMethodById to lookup method. * * @see getMethodById */ def methodById(methodId: Byte): SMethod = { - ValidationRules.CheckAndGetMethod(this, methodId) + if (VersionContext.current.isV6Activated) { + ValidationRules.CheckAndGetMethodV6(this, methodId) + } else { + ValidationRules.CheckAndGetMethod(this, methodId) + } } /** Finds a method descriptor [[SMethod]] for the given name. */ @@ -132,7 +136,7 @@ object MethodsContainer { private val containersV6 = new SparseArrayContainer[MethodsContainer](methodsV6.map(m => (m.typeId, m))) def contains(typeId: TypeCode): Boolean = { - if (VersionContext.current.isV6SoftForkActivated) { + if (VersionContext.current.isV3OrLaterErgoTreeVersion) { containersV6.contains(typeId) } else { containersV5.contains(typeId) @@ -140,7 +144,7 @@ object MethodsContainer { } def apply(typeId: TypeCode): MethodsContainer = { - if (VersionContext.current.isV6SoftForkActivated) { + if (VersionContext.current.isV3OrLaterErgoTreeVersion) { containersV6(typeId) } else { containersV5(typeId) @@ -157,7 +161,7 @@ object MethodsContainer { case tup: STuple => STupleMethods.getTupleMethod(tup, methodName) case _ => - if (VersionContext.current.isV6SoftForkActivated) { + if (VersionContext.current.isV3OrLaterErgoTreeVersion) { containersV6.get(tpe.typeCode).flatMap(_.method(methodName)) } else { containersV5.get(tpe.typeCode).flatMap(_.method(methodName)) @@ -208,7 +212,7 @@ trait SNumericTypeMethods extends MonoTypeMethods { } protected override def getMethods(): Seq[SMethod] = { - if (VersionContext.current.isV6SoftForkActivated) { + if (VersionContext.current.isV3OrLaterErgoTreeVersion) { super.getMethods() ++ v6Methods } else { super.getMethods() ++ v5Methods @@ -523,7 +527,7 @@ case object SBigIntMethods extends SNumericTypeMethods { ArgInfo("m", "modulo value")) protected override def getMethods(): Seq[SMethod] = { - if (VersionContext.current.isV6SoftForkActivated) { + if (VersionContext.current.isV3OrLaterErgoTreeVersion) { super.getMethods() ++ Seq(ToUnsigned, ToUnsignedMod) } else { super.getMethods() @@ -651,7 +655,7 @@ case object SGroupElementMethods extends MonoTypeMethods { MultiplyMethod, NegateMethod) - super.getMethods() ++ (if (VersionContext.current.isV6SoftForkActivated) { + super.getMethods() ++ (if (VersionContext.current.isV3OrLaterErgoTreeVersion) { v5Methods ++ Seq(ExponentiateUnsignedMethod) } else { v5Methods @@ -1309,7 +1313,7 @@ object SCollectionMethods extends MethodsContainer with MethodByNameUnapply { * Typical override: `super.getMethods() ++ Seq(m1, m2, m3)` */ override protected def getMethods(): Seq[SMethod] = { - if (VersionContext.current.isV6SoftForkActivated) { + if (VersionContext.current.isV3OrLaterErgoTreeVersion) { v6Methods } else { v5Methods @@ -1462,7 +1466,7 @@ case object SBoxMethods extends MonoTypeMethods { // should be lazy to solve recursive initialization protected override def getMethods() = { - if (VersionContext.current.isV6SoftForkActivated) { + if (VersionContext.current.isV3OrLaterErgoTreeVersion) { v6Methods } else { v5Methods @@ -1809,7 +1813,7 @@ case object SAvlTreeMethods extends MonoTypeMethods { lazy val v6Methods = v5Methods ++ Seq(insertOrUpdateMethod) protected override def getMethods(): Seq[SMethod] = { - if (VersionContext.current.isV6SoftForkActivated) { + if (VersionContext.current.isV3OrLaterErgoTreeVersion) { v6Methods } else { v5Methods @@ -1877,7 +1881,7 @@ case object SContextMethods extends MonoTypeMethods { ) protected override def getMethods(): Seq[SMethod] = { - if (VersionContext.current.isV6SoftForkActivated) { + if (VersionContext.current.isV3OrLaterErgoTreeVersion) { v6Methods } else { v5Methods @@ -1928,7 +1932,7 @@ case object SHeaderMethods extends MonoTypeMethods { private lazy val v6Methods = v5Methods ++ Seq(checkPowMethod) protected override def getMethods() = { - if (VersionContext.current.isV6SoftForkActivated) { + if (VersionContext.current.isV3OrLaterErgoTreeVersion) { v6Methods } else { v5Methods @@ -2101,7 +2105,7 @@ case object SGlobalMethods extends MonoTypeMethods { .withInfo(MethodCall, "Returns empty Option[T] of given type T.") protected override def getMethods() = super.getMethods() ++ { - if (VersionContext.current.isV6SoftForkActivated) { + if (VersionContext.current.isV3OrLaterErgoTreeVersion) { Seq( groupGeneratorMethod, xorMethod, diff --git a/data/shared/src/main/scala/sigma/ast/transformers.scala b/data/shared/src/main/scala/sigma/ast/transformers.scala index 8d7e689a18..9c622ca2da 100644 --- a/data/shared/src/main/scala/sigma/ast/transformers.scala +++ b/data/shared/src/main/scala/sigma/ast/transformers.scala @@ -258,7 +258,7 @@ case class ByIndex[V <: SType](input: Value[SCollection[V]], val indexV = index.evalTo[Int](env) default match { case Some(d) => - if (VersionContext.current.isV6SoftForkActivated) { + if (VersionContext.current.isV3OrLaterErgoTreeVersion) { // lazy evaluation of default in 6.0 addCost(ByIndex.costKind) if (inputV.isDefinedAt(indexV)) { @@ -625,7 +625,7 @@ case class OptionGetOrElse[V <: SType](input: Value[SOption[V]], default: Value[ override val opType = SFunc(IndexedSeq(input.tpe, tpe), tpe) override def tpe: V = input.tpe.elemType protected final override def eval(env: DataEnv)(implicit E: ErgoTreeEvaluator): Any = { - if(VersionContext.current.isV6SoftForkActivated) { + if (VersionContext.current.isV3OrLaterErgoTreeVersion) { // lazy evaluation of default in 6.0 val inputV = input.evalTo[Option[V#WrappedType]](env) addCost(OptionGetOrElse.costKind) diff --git a/data/shared/src/main/scala/sigma/serialization/DataSerializer.scala b/data/shared/src/main/scala/sigma/serialization/DataSerializer.scala index 92a54f9aa4..4955db5bdc 100644 --- a/data/shared/src/main/scala/sigma/serialization/DataSerializer.scala +++ b/data/shared/src/main/scala/sigma/serialization/DataSerializer.scala @@ -16,7 +16,7 @@ object DataSerializer extends CoreDataSerializer { case SBox => val b = v.asInstanceOf[CBox] ErgoBox.sigmaSerializer.serialize(b.ebox, w.asInstanceOf[SigmaByteWriter]) - case SHeader if VersionContext.current.isV6SoftForkActivated => + case SHeader if VersionContext.current.isV3OrLaterErgoTreeVersion => val h = v.asInstanceOf[CHeader] ErgoHeader.sigmaSerializer.serialize(h.ergoHeader, w.asInstanceOf[SigmaByteWriter]) case _ => @@ -36,7 +36,7 @@ object DataSerializer extends CoreDataSerializer { val res = CBox(ErgoBox.sigmaSerializer.parse(r.asInstanceOf[SigmaByteReader])) r.level = r.level - 1 res - case SHeader if VersionContext.current.isV6SoftForkActivated => + case SHeader if VersionContext.current.isV3OrLaterErgoTreeVersion => val depth = r.level r.level = depth + 1 val res = new CHeader(ErgoHeader.sigmaSerializer.parse(r.asInstanceOf[SigmaByteReader])) diff --git a/data/shared/src/main/scala/sigma/serialization/ErgoTreeSerializer.scala b/data/shared/src/main/scala/sigma/serialization/ErgoTreeSerializer.scala index 5122ee940c..5812132e0e 100644 --- a/data/shared/src/main/scala/sigma/serialization/ErgoTreeSerializer.scala +++ b/data/shared/src/main/scala/sigma/serialization/ErgoTreeSerializer.scala @@ -3,7 +3,7 @@ package sigma.serialization import org.ergoplatform.validation.ValidationRules.{CheckDeserializedScriptIsSigmaProp, CheckHeaderSizeBit} import sigma.ast.{Constant, DeserializationSigmaBuilder, ErgoTree, SType, UnparsedErgoTree} import sigma.ast.syntax.ValueOps -import sigma.ast.ErgoTree.{EmptyConstants, HeaderType} +import sigma.ast.ErgoTree.{EmptyConstants, HeaderType, getVersion} import sigma.util.safeNewArray import debox.cfor import sigma.VersionContext @@ -103,20 +103,24 @@ class ErgoTreeSerializer { * Doesn't apply any transformations and guarantee to preserve original * structure after deserialization. */ def serializeErgoTree(ergoTree: ErgoTree): Array[Byte] = { - val res = ergoTree.root match { - case Left(UnparsedErgoTree(bytes, _)) => bytes.array.asInstanceOf[Array[Byte]] - case _ => - val bytes = serializeWithoutSize(ergoTree) - if (ergoTree.hasSize) { - val w = SigmaSerializer.startWriter() - val header = bytes(0) - val contentLength = bytes.length - 1 - w.put(header) - w.putUInt(contentLength) - w.putBytes(bytes, 1, contentLength) - w.toBytes - } - else bytes + val treeVersion = ergoTree.version + val scriptVersion = Math.max(VersionContext.current.activatedVersion, treeVersion).toByte + val res = VersionContext.withVersions(scriptVersion, treeVersion) { + ergoTree.root match { + case Left(UnparsedErgoTree(bytes, _)) => bytes.array.asInstanceOf[Array[Byte]] + case _ => + val bytes = serializeWithoutSize(ergoTree) + if (ergoTree.hasSize) { + val w = SigmaSerializer.startWriter() + val header = bytes(0) + val contentLength = bytes.length - 1 + w.put(header) + w.putUInt(contentLength) + w.putBytes(bytes, 1, contentLength) + w.toBytes + } + else bytes + } } res } @@ -140,37 +144,42 @@ class ErgoTreeSerializer { val bodyPos = r.position val tree = try { try { // nested try-catch to intercept size limit exceptions and rethrow them as ValidationExceptions - val cs = deserializeConstants(h, r) - val previousConstantStore = r.constantStore - // reader with constant store attached is required (to get tpe for a constant placeholder) - r.constantStore = new ConstantStore(cs) - val wasDeserialize_saved = r.wasDeserialize - r.wasDeserialize = false + val treeVersion = getVersion(h) + val scriptVersion = Math.max(VersionContext.current.activatedVersion, treeVersion).toByte + VersionContext.withVersions(scriptVersion, treeVersion) { + val cs = deserializeConstants(h, r) + val previousConstantStore = r.constantStore + // reader with constant store attached is required (to get tpe for a constant placeholder) + r.constantStore = new ConstantStore(cs) - val wasUsingBlockchainContext_saved = r.wasUsingBlockchainContext - r.wasUsingBlockchainContext = false + val wasDeserialize_saved = r.wasDeserialize + r.wasDeserialize = false - val root = ValueSerializer.deserialize(r) - val hasDeserialize = r.wasDeserialize // == true if there was deserialization node - r.wasDeserialize = wasDeserialize_saved + val wasUsingBlockchainContext_saved = r.wasUsingBlockchainContext + r.wasUsingBlockchainContext = false - val isUsingBlockchainContext = r.wasUsingBlockchainContext // == true if there was a node using the blockchain context - r.wasUsingBlockchainContext = wasUsingBlockchainContext_saved + val root = ValueSerializer.deserialize(r) + val hasDeserialize = r.wasDeserialize // == true if there was deserialization node + r.wasDeserialize = wasDeserialize_saved - if (checkType) { - CheckDeserializedScriptIsSigmaProp(root) - } + val isUsingBlockchainContext = r.wasUsingBlockchainContext // == true if there was a node using the blockchain context + r.wasUsingBlockchainContext = wasUsingBlockchainContext_saved - r.constantStore = previousConstantStore - // now we know the end position of propositionBytes, read them all at once into array - val treeSize = r.position - startPos - r.position = startPos - val propositionBytes = r.getBytes(treeSize) + if (checkType) { + CheckDeserializedScriptIsSigmaProp(root) + } - new ErgoTree( - h, cs, Right(root.asSigmaProp), - propositionBytes, Some(hasDeserialize), Some(isUsingBlockchainContext)) + r.constantStore = previousConstantStore + // now we know the end position of propositionBytes, read them all at once into array + val treeSize = r.position - startPos + r.position = startPos + val propositionBytes = r.getBytes(treeSize) + + new ErgoTree( + h, cs, Right(root.asSigmaProp), + propositionBytes, Some(hasDeserialize), Some(isUsingBlockchainContext)) + } } catch { case e: ReaderPositionLimitExceeded => @@ -309,83 +318,85 @@ class ErgoTreeSerializer { val (header, _, constants, treeBytes) = deserializeHeaderWithTreeBytes(r) 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() - - // 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)) { - constW.putUInt(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() + + // 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)) { + constW.putUInt(constants.length) + } - // The following is optimized O(nConstants + position.length) implementation - if (nConstants > 0) { - val backrefs = getPositionsBackref(positions, nConstants) - cfor(0)(_ < nConstants, _ + 1) { i => - val c = constants(i) - val iPos = backrefs(i) // index to `positions` - if (iPos == -1) { - // no position => no substitution, serialize original constant - constantSerializer.serialize(c, constW) - } else { - 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, constW) + // The following is optimized O(nConstants + position.length) implementation + if (nConstants > 0) { + val backrefs = getPositionsBackref(positions, nConstants) + cfor(0)(_ < nConstants, _ + 1) { i => + val c = constants(i) + val iPos = backrefs(i) // index to `positions` + if (iPos == -1) { + // no position => no substitution, serialize original constant + constantSerializer.serialize(c, constW) + } else { + 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, constW) + } } } - } - val constBytes = constW.toBytes // nConstants + serialized new constants + val constBytes = constW.toBytes // nConstants + serialized new constants + + // start composing the resulting tree bytes + val w = SigmaSerializer.startWriter() + w.put(header) // header byte - // start composing the resulting tree bytes - val w = SigmaSerializer.startWriter() - w.put(header) // header byte + if (VersionContext.current.isV3OrLaterErgoTreeVersion) { + // 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 + } + } - 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) + + // the following is v4.x O(nConstants * positions.length) inefficient implementation + constants.zipWithIndex.foreach { + case (c, i) if positions.contains(i) => + val newVal = newVals(positions.indexOf(i)) + // we need to get newVal's serialized constant value (see ProveDlogSerializer for example) + val constantStore = new ConstantStore() + val valW = SigmaSerializer.startWriter(Some(constantStore)) + valW.putValue(newVal) + val newConsts = constantStore.getAll + require(newConsts.length == 1) + val newConst = newConsts.head + require(c.tpe == newConst.tpe, s"expected new constant to have the same ${c.tpe} tpe, got ${newConst.tpe}") + constantSerializer.serialize(newConst, w) + case (c, _) => + constantSerializer.serialize(c, w) } - } - 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) - - // the following is v4.x O(nConstants * positions.length) inefficient implementation - constants.zipWithIndex.foreach { - case (c, i) if positions.contains(i) => - val newVal = newVals(positions.indexOf(i)) - // we need to get newVal's serialized constant value (see ProveDlogSerializer for example) - val constantStore = new ConstantStore() - val valW = SigmaSerializer.startWriter(Some(constantStore)) - valW.putValue(newVal) - val newConsts = constantStore.getAll - require(newConsts.length == 1) - val newConst = newConsts.head - require(c.tpe == newConst.tpe, s"expected new constant to have the same ${c.tpe} tpe, got ${newConst.tpe}") - constantSerializer.serialize(newConst, w) - case (c, _) => - constantSerializer.serialize(c, w) + w.putBytes(treeBytes) + w.toBytes } - - w.putBytes(treeBytes) - w.toBytes } (resBytes, nConstants) diff --git a/interpreter/shared/src/main/scala/sigmastate/eval/Extensions.scala b/interpreter/shared/src/main/scala/sigmastate/eval/Extensions.scala index 98f044af9b..2df6fd040a 100644 --- a/interpreter/shared/src/main/scala/sigmastate/eval/Extensions.scala +++ b/interpreter/shared/src/main/scala/sigmastate/eval/Extensions.scala @@ -91,7 +91,7 @@ object Extensions { val bv = CAvlTreeVerifier(tree, proof) entries.forall { case (key, value) => val insertRes = bv.performOneOperation(Insert(ADKey @@ key.toArray, ADValue @@ value.toArray)) - if (insertRes.isFailure && !VersionContext.current.isV6SoftForkActivated) { + if (insertRes.isFailure && !VersionContext.current.isV6Activated) { syntax.error(s"Incorrect insert for $tree (key: $key, value: $value, digest: ${tree.digest}): ${insertRes.failed.get}}") } insertRes.isSuccess diff --git a/interpreter/shared/src/main/scala/sigmastate/interpreter/CErgoTreeEvaluator.scala b/interpreter/shared/src/main/scala/sigmastate/interpreter/CErgoTreeEvaluator.scala index 809b16270b..e1df1a92a3 100644 --- a/interpreter/shared/src/main/scala/sigmastate/interpreter/CErgoTreeEvaluator.scala +++ b/interpreter/shared/src/main/scala/sigmastate/interpreter/CErgoTreeEvaluator.scala @@ -145,7 +145,7 @@ class CErgoTreeEvaluator( addSeqCost(InsertIntoAvlTree_Info, nItems) { () => val insertRes = bv.performInsert(key.toArray, value.toArray) // For versioned change details, see see https://github.com/ScorexFoundation/sigmastate-interpreter/issues/908 - if (insertRes.isFailure && !VersionContext.current.isV6SoftForkActivated) { + if (insertRes.isFailure && !VersionContext.current.isV6Activated) { syntax.error(s"Incorrect insert for $tree (key: $key, value: $value, digest: ${tree.digest}): ${insertRes.failed.get}}") } res = insertRes.isSuccess diff --git a/interpreter/shared/src/main/scala/sigmastate/interpreter/Interpreter.scala b/interpreter/shared/src/main/scala/sigmastate/interpreter/Interpreter.scala index 88d7be4324..369af2a960 100644 --- a/interpreter/shared/src/main/scala/sigmastate/interpreter/Interpreter.scala +++ b/interpreter/shared/src/main/scala/sigmastate/interpreter/Interpreter.scala @@ -248,7 +248,7 @@ trait Interpreter { val context1 = context.withInitCost(currCost).asInstanceOf[CTX] val (propTree, context2) = trySoftForkable[(SigmaPropValue, CTX)](whenSoftFork = (TrueSigmaProp, context1)) { // Before ErgoTree V3 the deserialization cost was not added to the total cost - applyDeserializeContextJITC(if (VersionContext.current.activatedVersion >= VersionContext.V6SoftForkVersion) { + applyDeserializeContextJITC(if (VersionContext.current.isV6Activated) { context1 } else { context @@ -360,7 +360,6 @@ trait Interpreter { case None => // proceed normally } VersionContext.withVersions(context.activatedScriptVersion, ergoTree.version) { - // NOTE, ergoTree.complexity is not acrued to the cost in v5.0 val reduced = fullReduction(ergoTree, context, env) reduced.value match { case TrivialProp.TrueProp => (true, reduced.cost) diff --git a/interpreter/shared/src/test/scala/org/ergoplatform/validation/ValidationSpecification.scala b/interpreter/shared/src/test/scala/org/ergoplatform/validation/ValidationSpecification.scala index b223355c5b..47068a9102 100644 --- a/interpreter/shared/src/test/scala/org/ergoplatform/validation/ValidationSpecification.scala +++ b/interpreter/shared/src/test/scala/org/ergoplatform/validation/ValidationSpecification.scala @@ -3,5 +3,5 @@ package org.ergoplatform.validation import sigma.validation.SigmaValidationSettings trait ValidationSpecification { - implicit val vs: SigmaValidationSettings = ValidationRules.currentSettings + def vs: SigmaValidationSettings = ValidationRules.currentSettings } diff --git a/interpreter/shared/src/test/scala/sigma/ast/SigmaBuilderTest.scala b/interpreter/shared/src/test/scala/sigma/ast/SigmaBuilderTest.scala index ea3fa5d5ec..ce007d0e7f 100644 --- a/interpreter/shared/src/test/scala/sigma/ast/SigmaBuilderTest.scala +++ b/interpreter/shared/src/test/scala/sigma/ast/SigmaBuilderTest.scala @@ -138,7 +138,7 @@ class SigmaBuilderTest extends AnyPropSpec with ScalaCheckPropertyChecks with Ma val v = true val c = BooleanConstant(v) test[SBoolean.type](v, c) - if (!VersionContext.current.isV6SoftForkActivated) { + if (!VersionContext.current.isV3OrLaterErgoTreeVersion) { testArray[SBoolean.type](v, c) } else { testArrayFailure[SBoolean.type](v, c) @@ -151,7 +151,7 @@ class SigmaBuilderTest extends AnyPropSpec with ScalaCheckPropertyChecks with Ma val c = ByteConstant(v) testNumeric[SByte.type](v, c) testLiftingOfCAnyValue[SByte.type](v, c) - if (!VersionContext.current.isV6SoftForkActivated) { + if (!VersionContext.current.isV3OrLaterErgoTreeVersion) { testArray[SByte.type](v, c) } else { testArrayFailure[SByte.type](v, c) @@ -164,7 +164,7 @@ class SigmaBuilderTest extends AnyPropSpec with ScalaCheckPropertyChecks with Ma val c = ShortConstant(v) testNumeric[SShort.type](v, c) testLiftingOfCAnyValue[SShort.type](v, c) - if (!VersionContext.current.isV6SoftForkActivated) { + if (!VersionContext.current.isV3OrLaterErgoTreeVersion) { testArray[SShort.type](v, c) } else { testArrayFailure[SShort.type](v, c) @@ -176,7 +176,7 @@ class SigmaBuilderTest extends AnyPropSpec with ScalaCheckPropertyChecks with Ma val v = 1 val c = IntConstant(v) test[SInt.type](v, c) - if (!VersionContext.current.isV6SoftForkActivated) { + if (!VersionContext.current.isV3OrLaterErgoTreeVersion) { testArray[SInt.type](v, c) } else { testArrayFailure[SInt.type](v, c) @@ -188,7 +188,7 @@ class SigmaBuilderTest extends AnyPropSpec with ScalaCheckPropertyChecks with Ma val v = 1L val c = LongConstant(v) test[SLong.type](v, c) - if (!VersionContext.current.isV6SoftForkActivated) { + if (!VersionContext.current.isV3OrLaterErgoTreeVersion) { testArray[SLong.type](v, c) } else { testArrayFailure[SLong.type](v, c) @@ -199,7 +199,7 @@ class SigmaBuilderTest extends AnyPropSpec with ScalaCheckPropertyChecks with Ma property("liftToConstant String") { val v = "abc" val c = StringConstant(v) - if (!VersionContext.current.isV6SoftForkActivated) { + if (!VersionContext.current.isV3OrLaterErgoTreeVersion) { // v6.0: String should not be liftable at all (not supported in ErgoTree) (see https://github.com/ScorexFoundation/sigmastate-interpreter/issues/905) test[SString.type](v, c) testArray[SString.type](v, c) @@ -212,13 +212,13 @@ class SigmaBuilderTest extends AnyPropSpec with ScalaCheckPropertyChecks with Ma property("liftToConstant BigInteger") { val v = BigInteger.valueOf(1L) val c = BigIntConstant(v) - if (!VersionContext.current.isV6SoftForkActivated) { + if (!VersionContext.current.isV3OrLaterErgoTreeVersion) { testSuccess(v, c) } else { testFailure(v) } val arr = Array.fill(10)(v) - if (!VersionContext.current.isV6SoftForkActivated) { + if (!VersionContext.current.isV3OrLaterErgoTreeVersion) { testSuccess(arr, TransformingSigmaBuilder.mkCollectionConstant[SBigInt.type](arr.map(SigmaDsl.BigInt), c.tpe)) } else { testFailure(arr) @@ -244,7 +244,7 @@ class SigmaBuilderTest extends AnyPropSpec with ScalaCheckPropertyChecks with Ma property("liftToConstant Header") { val h = TestData.h1 val c = HeaderConstant(h) - if (VersionContext.current.isV6SoftForkActivated) { + if (VersionContext.current.isV3OrLaterErgoTreeVersion) { testSuccess(h, c) } else { testFailure(h) @@ -256,7 +256,7 @@ class SigmaBuilderTest extends AnyPropSpec with ScalaCheckPropertyChecks with Ma property("liftToConstant ErgoBox") { val v = TestData.b2.asInstanceOf[CBox].wrappedValue val c = BoxConstant(TestData.b2) - if (!VersionContext.current.isV6SoftForkActivated) { + if (!VersionContext.current.isV3OrLaterErgoTreeVersion) { testSuccess(v, c) } else { testFailure(v) @@ -287,7 +287,7 @@ class SigmaBuilderTest extends AnyPropSpec with ScalaCheckPropertyChecks with Ma property("liftToConstant AvlTreeData") { val v = TestData.t1.asInstanceOf[CAvlTree].wrappedValue val c = AvlTreeConstant(SigmaDsl.avlTree(v)) - if (!VersionContext.current.isV6SoftForkActivated) { + if (!VersionContext.current.isV3OrLaterErgoTreeVersion) { testSuccess(v, c) } else { testFailure(v) diff --git a/interpreter/shared/src/test/scala/sigma/serialization/DataSerializerSpecification.scala b/interpreter/shared/src/test/scala/sigma/serialization/DataSerializerSpecification.scala index 9201214e4f..d0b5a55569 100644 --- a/interpreter/shared/src/test/scala/sigma/serialization/DataSerializerSpecification.scala +++ b/interpreter/shared/src/test/scala/sigma/serialization/DataSerializerSpecification.scala @@ -52,7 +52,7 @@ class DataSerializerSpecification extends SerializationSpecification { withVersion match { case Some(ver) => - VersionContext.withVersions(ver, 1) { + VersionContext.withVersions(ver, ver) { test() } case None => @@ -129,7 +129,7 @@ class DataSerializerSpecification extends SerializationSpecification { } }) - VersionContext.withVersions(VersionContext.V6SoftForkVersion, 1) { + VersionContext.withVersions(VersionContext.V6SoftForkVersion, VersionContext.V6SoftForkVersion) { forAll { in: T#WrappedType => roundtrip[SType](Some(in).asWrappedType, SOption(tpe)) roundtrip[SOption[T]](None, SOption(tpe)) @@ -189,7 +189,7 @@ class DataSerializerSpecification extends SerializationSpecification { } property("nuanced versioned test for header roundtrip") { - VersionContext.withVersions(VersionContext.V6SoftForkVersion, 1) { + VersionContext.withVersions(VersionContext.V6SoftForkVersion, VersionContext.V6SoftForkVersion) { forAll { x: Header => roundtrip[SHeader.type](x, SHeader) } } @@ -219,7 +219,7 @@ class DataSerializerSpecification extends SerializationSpecification { Colls.emptyColl ) - VersionContext.withVersions(VersionContext.V6SoftForkVersion, 1) { + VersionContext.withVersions(VersionContext.V6SoftForkVersion, VersionContext.V6SoftForkVersion) { roundtrip[SHeader.type](header, SHeader) } } diff --git a/interpreter/shared/src/test/scala/sigma/serialization/MethodCallSerializerSpecification.scala b/interpreter/shared/src/test/scala/sigma/serialization/MethodCallSerializerSpecification.scala index 4bfe3c6a25..1a29d2cc9f 100644 --- a/interpreter/shared/src/test/scala/sigma/serialization/MethodCallSerializerSpecification.scala +++ b/interpreter/shared/src/test/scala/sigma/serialization/MethodCallSerializerSpecification.scala @@ -38,7 +38,7 @@ class MethodCallSerializerSpecification extends SerializationSpecification { roundTripTest(expr) } - VersionContext.withVersions(VersionContext.V6SoftForkVersion, 1) { + VersionContext.withVersions(VersionContext.V6SoftForkVersion, VersionContext.V6SoftForkVersion) { code } @@ -47,6 +47,12 @@ class MethodCallSerializerSpecification extends SerializationSpecification { code } ) + + a[sigma.serialization.SerializerException] should be thrownBy ( + VersionContext.withVersions(VersionContext.V6SoftForkVersion, (VersionContext.V6SoftForkVersion - 1).toByte) { + code + } + ) } property("MethodCall deserialization round trip for Global.powHit") { @@ -65,15 +71,21 @@ class MethodCallSerializerSpecification extends SerializationSpecification { roundTripTest(expr) } - VersionContext.withVersions(VersionContext.V6SoftForkVersion, 1) { + VersionContext.withVersions(VersionContext.V6SoftForkVersion, VersionContext.V6SoftForkVersion) { code } - an[ValidationException] should be thrownBy ( + a[ValidationException] should be thrownBy ( VersionContext.withVersions((VersionContext.V6SoftForkVersion - 1).toByte, 1) { code } ) + + a[ValidationException] should be thrownBy ( + VersionContext.withVersions(VersionContext.V6SoftForkVersion, (VersionContext.V6SoftForkVersion - 1).toByte) { + code + } + ) } property("MethodCall deserialization round trip for Global.serialize") { @@ -87,15 +99,21 @@ class MethodCallSerializerSpecification extends SerializationSpecification { roundTripTest(expr) } - VersionContext.withVersions(VersionContext.V6SoftForkVersion, 1) { + VersionContext.withVersions(VersionContext.V6SoftForkVersion, VersionContext.V6SoftForkVersion) { code } - an[ValidationException] should be thrownBy ( + a[ValidationException] should be thrownBy ( VersionContext.withVersions((VersionContext.V6SoftForkVersion - 1).toByte, 1) { code } - ) + ) + + a[ValidationException] should be thrownBy ( + VersionContext.withVersions(VersionContext.V6SoftForkVersion, (VersionContext.V6SoftForkVersion - 1).toByte) { + code + } + ) } property("MethodCall deserialization round trip for Global.deserializeTo[]") { @@ -109,16 +127,21 @@ class MethodCallSerializerSpecification extends SerializationSpecification { roundTripTest(expr) } - println(SGlobalMethods.deserializeToMethod.hasExplicitTypeArgs) - - VersionContext.withVersions(VersionContext.V6SoftForkVersion, 1) { + VersionContext.withVersions(VersionContext.V6SoftForkVersion, VersionContext.V6SoftForkVersion) { code } - an[Exception] should be thrownBy ( + a[SerializerException] should be thrownBy ( VersionContext.withVersions((VersionContext.V6SoftForkVersion - 1).toByte, 1) { code - }) + } + ) + + a[sigma.serialization.SerializerException] should be thrownBy ( + VersionContext.withVersions(VersionContext.V6SoftForkVersion, (VersionContext.V6SoftForkVersion - 1).toByte) { + code + } + ) } property("MethodCall deserialization round trip for Global.encodeNBits") { @@ -133,14 +156,21 @@ class MethodCallSerializerSpecification extends SerializationSpecification { } // should be ok - VersionContext.withVersions(VersionContext.V6SoftForkVersion, 1) { + VersionContext.withVersions(VersionContext.V6SoftForkVersion, VersionContext.V6SoftForkVersion) { code } - an[ValidationException] should be thrownBy ( + a[ValidationException] should be thrownBy ( VersionContext.withVersions((VersionContext.V6SoftForkVersion - 1).toByte, 1) { code - }) + } + ) + + a[ValidationException] should be thrownBy ( + VersionContext.withVersions(VersionContext.V6SoftForkVersion, (VersionContext.V6SoftForkVersion - 1).toByte) { + code + } + ) } property("MethodCall deserialization round trip for Global.decodeNBits") { @@ -154,14 +184,20 @@ class MethodCallSerializerSpecification extends SerializationSpecification { roundTripTest(expr) } - VersionContext.withVersions(VersionContext.V6SoftForkVersion, 1) { + VersionContext.withVersions(VersionContext.V6SoftForkVersion, VersionContext.V6SoftForkVersion) { code } - an[ValidationException] should be thrownBy ( + a[ValidationException] should be thrownBy ( VersionContext.withVersions((VersionContext.V6SoftForkVersion - 1).toByte, 1) { code } ) + + a[ValidationException] should be thrownBy ( + VersionContext.withVersions(VersionContext.V6SoftForkVersion, (VersionContext.V6SoftForkVersion - 1).toByte) { + code + } + ) } } diff --git a/interpreter/shared/src/test/scala/sigma/serialization/SerializationSpecification.scala b/interpreter/shared/src/test/scala/sigma/serialization/SerializationSpecification.scala index aa7a8722ba..ce0f941308 100644 --- a/interpreter/shared/src/test/scala/sigma/serialization/SerializationSpecification.scala +++ b/interpreter/shared/src/test/scala/sigma/serialization/SerializationSpecification.scala @@ -35,7 +35,7 @@ trait SerializationSpecification extends AnyPropSpec } withVersion match { case Some(ver) => - VersionContext.withVersions(ver, 0) { + VersionContext.withVersions(ver, ver) { test() } case None => diff --git a/interpreter/shared/src/test/scala/sigma/serialization/generators/ObjectGenerators.scala b/interpreter/shared/src/test/scala/sigma/serialization/generators/ObjectGenerators.scala index 1af51d4eee..52bd629e70 100644 --- a/interpreter/shared/src/test/scala/sigma/serialization/generators/ObjectGenerators.scala +++ b/interpreter/shared/src/test/scala/sigma/serialization/generators/ObjectGenerators.scala @@ -329,7 +329,7 @@ trait ObjectGenerators extends TypeGenerators longConstGen, booleanConstGen, bigIntConstGen, - if(VersionContext.current.isV6SoftForkActivated) { + if(VersionContext.current.isV3OrLaterErgoTreeVersion) { unsignedBigIntConstGen } else { bigIntConstGen diff --git a/interpreter/shared/src/test/scala/sigma/serialization/generators/TypeGenerators.scala b/interpreter/shared/src/test/scala/sigma/serialization/generators/TypeGenerators.scala index c27053ebf2..53bb8de156 100644 --- a/interpreter/shared/src/test/scala/sigma/serialization/generators/TypeGenerators.scala +++ b/interpreter/shared/src/test/scala/sigma/serialization/generators/TypeGenerators.scala @@ -24,7 +24,7 @@ trait TypeGenerators { Gen.oneOf[SPrimType](SBoolean, SByte, SShort, SInt, SLong, SBigInt, SUnsignedBigInt, SGroupElement, SSigmaProp, SUnit) implicit val arbPrimType: Arbitrary[SPrimType] = Arbitrary(primTypeGen) implicit val predefTypeGen: Gen[SPredefType] = { - if(VersionContext.current.isV6SoftForkActivated){ + if(VersionContext.current.isV3OrLaterErgoTreeVersion){ Gen.oneOf[SPredefType](SBoolean, SByte, SShort, SInt, SLong, SBigInt, SUnsignedBigInt, SGroupElement, SSigmaProp, SUnit, SBox, SAvlTree, SHeader) } else { Gen.oneOf[SPredefType](SBoolean, SByte, SShort, SInt, SLong, SBigInt, SGroupElement, SSigmaProp, SUnit, SBox, SAvlTree) @@ -42,7 +42,7 @@ trait TypeGenerators { intTypeGen, longTypeGen, bigIntTypeGen, - if(VersionContext.current.isV6SoftForkActivated) { + if(VersionContext.current.isV3OrLaterErgoTreeVersion) { unsignedBigIntTypeGen } else { bigIntTypeGen 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 7ab7845695..691b4faab2 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/GraphBuilding.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/GraphBuilding.scala @@ -1055,7 +1055,7 @@ trait GraphBuilding extends Base with DefRewriting { IR: IRContext => case (box: Ref[Box]@unchecked, SBoxMethods) => method.name match { case SBoxMethods.tokensMethod.name => box.tokens - case SBoxMethods.getRegMethodV6.name if VersionContext.current.isV6SoftForkActivated => + case SBoxMethods.getRegMethodV6.name if VersionContext.current.isV3OrLaterErgoTreeVersion => val c1 = asRep[Int](argsV(0)) val c2 = stypeToElem(typeSubst.apply(tT)) box.getReg(c1)(c2) @@ -1192,7 +1192,7 @@ trait GraphBuilding extends Base with DefRewriting { IR: IRContext => h.powDistance case SHeaderMethods.votesMethod.name => h.votes - case SHeaderMethods.checkPowMethod.name if VersionContext.current.isV6SoftForkActivated => + case SHeaderMethods.checkPowMethod.name if VersionContext.current.isV3OrLaterErgoTreeVersion => h.checkPow case _ => throwError() } @@ -1203,26 +1203,26 @@ 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.encodeNBitsMethod.name if VersionContext.current.isV6SoftForkActivated => + case SGlobalMethods.encodeNBitsMethod.name if VersionContext.current.isV3OrLaterErgoTreeVersion => val c1 = asRep[BigInt](argsV(0)) g.encodeNbits(c1) - case SGlobalMethods.decodeNBitsMethod.name if VersionContext.current.isV6SoftForkActivated => + case SGlobalMethods.decodeNBitsMethod.name if VersionContext.current.isV3OrLaterErgoTreeVersion => val c1 = asRep[Long](argsV(0)) g.decodeNbits(c1) - case SGlobalMethods.powHitMethod.name if VersionContext.current.isV6SoftForkActivated => + case SGlobalMethods.powHitMethod.name if VersionContext.current.isV3OrLaterErgoTreeVersion => val k = asRep[Int](argsV(0)) val msg = asRep[Coll[Byte]](argsV(1)) val nonce = asRep[Coll[Byte]](argsV(2)) val h = asRep[Coll[Byte]](argsV(3)) val N = asRep[Int](argsV(4)) g.powHit(k, msg, nonce, h, N) - case SGlobalMethods.encodeNBitsMethod.name if VersionContext.current.isV6SoftForkActivated => + case SGlobalMethods.encodeNBitsMethod.name if VersionContext.current.isV3OrLaterErgoTreeVersion => val c1 = asRep[BigInt](argsV(0)) g.encodeNbits(c1) - case SGlobalMethods.decodeNBitsMethod.name if VersionContext.current.isV6SoftForkActivated => + case SGlobalMethods.decodeNBitsMethod.name if VersionContext.current.isV3OrLaterErgoTreeVersion => val c1 = asRep[Long](argsV(0)) g.decodeNbits(c1) - case SGlobalMethods.deserializeToMethod.name if VersionContext.current.isV6SoftForkActivated => + case SGlobalMethods.deserializeToMethod.name if VersionContext.current.isV3OrLaterErgoTreeVersion => val c1 = asRep[Coll[Byte]](argsV(0)) val c2 = stypeToElem(method.stype.tRange.withSubstTypes(typeSubst)) g.deserializeTo(c1)(c2) diff --git a/sc/shared/src/test/scala/org/ergoplatform/ErgoLikeTransactionSpec.scala b/sc/shared/src/test/scala/org/ergoplatform/ErgoLikeTransactionSpec.scala index 4b3aa2eab5..4b9b6e44fd 100644 --- a/sc/shared/src/test/scala/org/ergoplatform/ErgoLikeTransactionSpec.scala +++ b/sc/shared/src/test/scala/org/ergoplatform/ErgoLikeTransactionSpec.scala @@ -104,7 +104,7 @@ import sigmastate.utils.Helpers.EitherOps // required for Scala 2.11 // We have versioned check here due to fixed collections equality in 6.0.0 // (PairOfColl equal CollOverArray now) // see (https://github.com/ScorexFoundation/sigmastate-interpreter/issues/909) - if(VersionContext.current.isV6SoftForkActivated) { + if(VersionContext.current.isV3OrLaterErgoTreeVersion) { val exp = Coll( (Digest32Coll @@ ErgoAlgos.decodeUnsafe(token1).toColl) -> 10000000L, (Digest32Coll @@ ErgoAlgos.decodeUnsafe(token2).toColl) -> 500L diff --git a/sc/shared/src/test/scala/sigma/LanguageSpecificationV5.scala b/sc/shared/src/test/scala/sigma/LanguageSpecificationV5.scala index c670d60c66..8bbd300d1b 100644 --- a/sc/shared/src/test/scala/sigma/LanguageSpecificationV5.scala +++ b/sc/shared/src/test/scala/sigma/LanguageSpecificationV5.scala @@ -4733,7 +4733,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => Vector(), Map() ) - )), + ), activationType = ActivationByScriptVersion), preGeneratedSamples = Some(samples)) // test vectors to reproduce v4.x bug (see https://github.com/ScorexFoundation/sigmastate-interpreter/issues/603) @@ -4993,6 +4993,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => ) ) ), + activationType = ActivationByScriptVersion, allowNewToSucceed = true ), preGeneratedSamples = Some(ArraySeq.empty)) @@ -5916,7 +5917,9 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => (x: Coll[Boolean]) => SigmaDsl.xorOf(x), (x: Coll[Boolean]) => SigmaDsl.xorOf(x), "{ (x: Coll[Boolean]) => xorOf(x) }", - FuncValue(Vector((1, SBooleanArray)), XorOf(ValUse(1, SBooleanArray))))) + FuncValue(Vector((1, SBooleanArray)), XorOf(ValUse(1, SBooleanArray))), + activationType = ActivationByScriptVersion + )) } property("LogicalNot equivalence") { @@ -6191,7 +6194,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => (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) }", - if (lowerMethodCallsInTests) + {if (lowerMethodCallsInTests) FuncValue( Vector((1, STuple(Vector(SByteArray, SByteArray)))), Xor( @@ -6223,7 +6226,8 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => ), Map() ) - ) + )}, + activationType = ActivationByScriptVersion )) } @@ -7917,7 +7921,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => ) ) ) - if(!VersionContext.current.isV6SoftForkActivated) { + if(!VersionContext.current.isV3OrLaterErgoTreeVersion) { verifyCases( // (coll, (index, default)) { @@ -8555,7 +8559,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => "{ (x: Option[Long]) => x.isDefined }", FuncValue(Vector((1, SOption(SLong))), OptionIsDefined(ValUse(1, SOption(SLong)))))) - if (!VersionContext.current.isV6SoftForkActivated) { + if (!VersionContext.current.isV3OrLaterErgoTreeVersion) { verifyCases( Seq( (None -> Expected(Success(1L), 1766, costDetails3, 1766, Seq.fill(4)(2006))), @@ -8822,6 +8826,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => LongConstant(5L) ) ), + activationType = ActivationByScriptVersion, allowNewToSucceed = true), preGeneratedSamples = Some(Nil)) } @@ -9395,7 +9400,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => ), ConcreteCollection(Array(BoolToSigmaProp(FalseLeaf)), SSigmaProp) ) - ))) + ), activationType = ActivationByScriptVersion)) } // Original issue: https://github.com/ScorexFoundation/sigmastate-interpreter/issues/604 @@ -9544,6 +9549,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => ) ) ), + activationType = ActivationByScriptVersion, allowDifferentErrors = true, allowNewToSucceed = true ), diff --git a/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala b/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala index e6844e7363..dda2c34bbe 100644 --- a/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala +++ b/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala @@ -17,27 +17,17 @@ import sigma.ast.syntax.TrueSigmaProp import sigma.ast.{SInt, _} import sigma.data.{AvlTreeData, AvlTreeFlags, CAnyValue, CAvlTree, CBigInt, CBox, CHeader, CSigmaProp, ExactNumeric, ProveDHTuple, RType} import sigma.data.CSigmaDslBuilder -import sigma.data.{AvlTreeData, AvlTreeFlags, CAnyValue, CAvlTree, CBigInt, CBox, CGroupElement, CHeader, CSigmaDslBuilder, CSigmaProp, CUnsignedBigInt, ExactNumeric, PairOfCols, ProveDHTuple, RType} +import sigma.data.{CGroupElement, CUnsignedBigInt} import sigma.crypto.SecP256K1Group -import sigma.data.{CBigInt, CBox, CGroupElement, CHeader, CSigmaDslBuilder, ExactNumeric, RType} -import sigma.data.{CBigInt, CBox, CHeader, CSigmaDslBuilder, ExactNumeric, PairOfCols, RType} import sigma.eval.{CostDetails, SigmaDsl, TracedCost} import sigma.serialization.ValueCodes.OpCode import sigma.util.Extensions.{BooleanOps, IntOps} import sigmastate.eval.{CContext, CPreHeader} -import sigma.util.Extensions.{BooleanOps, IntOps} -import sigma.serialization.ValueCodes.OpCode -import sigma.util.Extensions.{BooleanOps, ByteOps, IntOps, LongOps} -import sigma.util.Extensions.{BooleanOps, IntOps} -import sigma.data.RType -import sigma.serialization.ValueCodes.OpCode -import sigma.util.Extensions.{BooleanOps, ByteOps, IntOps, LongOps} import sigma.pow.Autolykos2PowValidation import sigmastate.exceptions.MethodNotFound import sigmastate.utils.Extensions.ByteOpsForSigma import sigmastate.utils.Helpers import sigma.Extensions.ArrayOps -import sigma.Extensions.{ArrayOps, CollOps} import sigma.crypto.CryptoConstants import sigma.data.CSigmaDslBuilder.Colls import sigma.exceptions.InterpreterException @@ -943,7 +933,7 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite => property("BigInt - 6.0 features") { import sigma.data.OrderingOps.BigIntOrdering - if (activatedVersionInTests < VersionContext.V6SoftForkVersion) { + if (ergoTreeVersionInTests < VersionContext.V6SoftForkVersion) { // The `Upcast(bigInt, SBigInt)` node is never produced by ErgoScript compiler, but is still valid ErgoTree. // Fixed in 6.0 assertExceptionThrown( @@ -1395,18 +1385,24 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite => // for tree v0, the result is the same for all versions (Coll(t1.bytes: _*), 0) -> Expected( Success(Helpers.decodeBytes("100108d27300")), - cost = 1793, + costOpt = None, expectedDetails = CostDetails.ZeroCost, - newCost = 2065, + newCostOpt = None, 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, + costOpt = None, expectedDetails = CostDetails.ZeroCost, - newCost = 2065, - newVersionedResults = expectedSuccessForAllTreeVersions(expectedTreeBytes_V6, 2065, costDetails(1))) + newCostOpt = None, + newVersionedResults = Seq( + 0 -> (ExpectedResult(Success(expectedTreeBytes_beforeV6), Some(2015)) -> Some(costDetails(1))), + 1 -> (ExpectedResult(Success(expectedTreeBytes_beforeV6), Some(2015)) -> Some(costDetails(1))), + 2 -> (ExpectedResult(Success(expectedTreeBytes_beforeV6), Some(2015)) -> Some(costDetails(1))), + 3 -> (ExpectedResult(Success(expectedTreeBytes_V6), Some(2065)) -> Some(costDetails(1))) + ) + ) ), changedFeature( changedInVersion = VersionContext.V6SoftForkVersion, @@ -1427,7 +1423,8 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite => ), ConcreteCollection(Array(BoolToSigmaProp(FalseLeaf)), SSigmaProp) ) - ) + ), + activationType = ActivationByTreeVersion ) ) @@ -1874,14 +1871,19 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite => Seq( Some(2L) -> Expected(Failure(new java.lang.ArithmeticException("/ by zero")), 6, trace, 1793, newVersionedResults = { - expectedSuccessForAllTreeVersions(2L, 2015, trace) + Seq( + 0 -> (ExpectedResult(Failure(new java.lang.ArithmeticException("/ by zero")), Some(2029)) -> Some(trace)), + 1 -> (ExpectedResult(Failure(new java.lang.ArithmeticException("/ by zero")), Some(2029)) -> Some(trace)), + 2 -> (ExpectedResult(Failure(new java.lang.ArithmeticException("/ by zero")), Some(2029)) -> Some(trace)), + 3 -> (ExpectedResult(Success(2L), Some(2015)) -> Some(trace)) + ) } ), None -> Expected(Failure(new java.lang.ArithmeticException("/ by zero")), 6, trace, 1793) ), changedFeature( changedInVersion = VersionContext.V6SoftForkVersion, { (x: Option[Long]) => val default = 1 / 0L; x.getOrElse(default) }, - { (x: Option[Long]) => if (VersionContext.current.isV6SoftForkActivated) {x.getOrElse(1 / 0L)} else {val default = 1 / 0L; x.getOrElse(default)} }, + { (x: Option[Long]) => if (VersionContext.current.isV3OrLaterErgoTreeVersion) {x.getOrElse(1 / 0L)} else {val default = 1 / 0L; x.getOrElse(default)} }, "{ (x: Option[Long]) => x.getOrElse(1 / 0L) }", FuncValue( Array((1, SOption(SLong))), @@ -1911,7 +1913,7 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite => ) def scalaFuncNew(x: Coll[Int]) = { - if (VersionContext.current.isV6SoftForkActivated) { + if (VersionContext.current.isV3OrLaterErgoTreeVersion) { x.toArray.toIndexedSeq.headOption.getOrElse(1 / 0) } else scalaFuncOld(x) } @@ -1924,7 +1926,12 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite => Seq( Coll(1) -> Expected(Failure(new java.lang.ArithmeticException("/ by zero")), 6, trace, 1793, newVersionedResults = { - expectedSuccessForAllTreeVersions(1, 2029, trace) + Seq( + 0 -> (ExpectedResult(Failure(new java.lang.ArithmeticException("/ by zero")), Some(2029)) -> Some(trace)), + 1 -> (ExpectedResult(Failure(new java.lang.ArithmeticException("/ by zero")), Some(2029)) -> Some(trace)), + 2 -> (ExpectedResult(Failure(new java.lang.ArithmeticException("/ by zero")), Some(2029)) -> Some(trace)), + 3 -> (ExpectedResult(Success(1), Some(2029)) -> Some(trace)) + ) } ), Coll[Int]() -> Expected(Failure(new java.lang.ArithmeticException("/ by zero")), 6, trace, 1793) ), @@ -2454,7 +2461,7 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite => lazy val bitOr = newFeature[(UnsignedBigInt, UnsignedBigInt), UnsignedBigInt]( { (x: (UnsignedBigInt, UnsignedBigInt)) => (x._1 | x._2) }, "{ (x: (UnsignedBigInt, UnsignedBigInt)) => x._1.bitwiseOr(x._2) }", - if (VersionContext.current.isV6SoftForkActivated) { + if (VersionContext.current.isV3OrLaterErgoTreeVersion) { FuncValue( Array((1, SPair(SUnsignedBigInt, SUnsignedBigInt))), MethodCall.typed[Value[SUnsignedBigInt.type]]( @@ -2489,7 +2496,7 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite => lazy val bitNot = newFeature[UnsignedBigInt, UnsignedBigInt]( { (x: UnsignedBigInt) => x.bitwiseInverse() }, "{ (x: UnsignedBigInt) => x.bitwiseInverse }", - if (VersionContext.current.isV6SoftForkActivated) { + if (VersionContext.current.isV3OrLaterErgoTreeVersion) { FuncValue( Array((1, SUnsignedBigInt)), MethodCall.typed[Value[SUnsignedBigInt.type]]( @@ -2855,7 +2862,16 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite => lazy val some = newFeature( { (x: Byte) => CSigmaDslBuilder.none[Byte]() }, "{ (x: Byte) => Global.none[Byte]() }", - sinceVersion = V6SoftForkVersion) + FuncValue( + Array((1, SByte)), + MethodCall.typed[Value[SOption[SByte.type]]]( + Global, + SGlobalMethods.noneMethod.withConcreteTypes(Map(STypeVar("T") -> SByte)), + IndexedSeq(), + Map(STypeVar("T") -> SByte) + ) + ), + sinceVersion = V6SoftForkVersion) val cases = Seq( (0.toByte, Success(None)), (1.toByte, Success(None)) @@ -3024,7 +3040,7 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite => val tree = createTree(preInsertDigest, insertAllowed = true) val invalidKvs = Colls.fromItems((key -> value), (key -> value)) val input = (tree, (invalidKvs, insertProof)) - if (VersionContext.current.isV6SoftForkActivated) { + if (VersionContext.current.isV6Activated) { insert.verifyCase(input, new Expected(ExpectedResult(Success(None), Some(2103)))) } else { val res = insert.checkEquality(input) @@ -3037,7 +3053,7 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite => val tree = createTree(preInsertDigest, insertAllowed = true) val invalidProof = insertProof.map(x => (-x).toByte) // any other different from proof val input = (tree, (kvs, invalidProof)) - if (VersionContext.current.isV6SoftForkActivated) { + if (VersionContext.current.isV6Activated) { insert.verifyCase(input, new Expected(ExpectedResult(Success(None), Some(2103)))) } else { val res = insert.checkEquality(input) diff --git a/sc/shared/src/test/scala/sigma/SigmaDslTesting.scala b/sc/shared/src/test/scala/sigma/SigmaDslTesting.scala index 7f3f28b791..90e104defe 100644 --- a/sc/shared/src/test/scala/sigma/SigmaDslTesting.scala +++ b/sc/shared/src/test/scala/sigma/SigmaDslTesting.scala @@ -50,8 +50,12 @@ class SigmaDslTesting extends AnyPropSpec with Matchers with SigmaTestingData with SigmaContractSyntax with CompilerTestingCommons with ObjectGenerators { suite => + override def Coll[T](items: T*)(implicit cT: RType[T]): Coll[T] = super.Coll(items:_*) + protected val ActivationByScriptVersion: Byte = 0.toByte + protected val ActivationByTreeVersion: Byte = 1.toByte + lazy val spec: ContractSpec = TestContractSpec(suite)(new TestingIRContext) override def contractEnv: ScriptEnv = Map() @@ -130,6 +134,9 @@ class SigmaDslTesting extends AnyPropSpec /** Version in which the feature is first implemented of changed. */ def sinceVersion: Byte + /** 0 = script version based activation, 1 = tree version based activation */ + def activationType: Byte + /** Script containing this feature. */ def script: String @@ -329,7 +336,9 @@ class SigmaDslTesting extends AnyPropSpec val pkAlice = prover.pubKeys.head.toSigmaPropValue val env = Map("pkAlice" -> pkAlice) // Compile script the same way it is performed by applications (i.e. via Ergo Appkit) - val prop = compile(env, code)(IR).asSigmaProp + val prop = VersionContext.withVersions(3, 3) { + compile(env, code)(IR).asSigmaProp + } // Add additional operations which are not yet implemented in ErgoScript compiler val multisig = AtLeast( @@ -404,10 +413,13 @@ class SigmaDslTesting extends AnyPropSpec ctx } - val (expectedResult, expectedCost) = if (activatedVersionInTests < sinceVersion) + val (expectedResult, expectedCost) = if ( + (activationType == ActivationByScriptVersion && activatedVersionInTests < sinceVersion) || + (activationType == ActivationByTreeVersion && ergoTreeVersionInTests < sinceVersion) + ) { (expected.oldResult, expected.verificationCostOpt) - else { - val res = expected.newResults(ergoTreeVersionInTests) + } else { + val res = expected.newResults(sinceVersion) (res._1, res._1.verificationCost) } @@ -463,7 +475,8 @@ class SigmaDslTesting extends AnyPropSpec val verificationCost = cost.toIntExact if (expectedCost.isDefined) { assertResult(expectedCost.get, - s"Actual verify() cost $cost != expected ${expectedCost.get} (version: ${VersionContext.current.activatedVersion})")(verificationCost) + s"Actual verify() cost $cost != expected ${expectedCost.get} " + + s"(script version: ${VersionContext.current.activatedVersion}, tree version: ${VersionContext.current.ergoTreeVersion})")(verificationCost) } case Failure(t) => throw t @@ -513,6 +526,8 @@ class SigmaDslTesting extends AnyPropSpec override def sinceVersion: Byte = 0 + override val activationType = ActivationByScriptVersion + override def isSupportedIn(vc: VersionContext): Boolean = true /** in v5.x the old and the new interpreters are the same */ @@ -681,6 +696,7 @@ class SigmaDslTesting extends AnyPropSpec printExpectedExpr: Boolean = true, logScript: Boolean = LogScriptDefault, allowNewToSucceed: Boolean = false, + override val activationType: Byte = ActivationByTreeVersion, override val allowDifferentErrors: Boolean = false )(implicit IR: IRContext, override val evalSettings: EvalSettings, val tA: RType[A], val tB: RType[B]) extends Feature[A, B] { feature => @@ -771,10 +787,16 @@ class SigmaDslTesting extends AnyPropSpec override def checkExpected(input: A, expected: Expected[B]): Unit = { // check the new implementation with Scala semantic function val newRes = VersionContext.withVersions(activatedVersionInTests, ergoTreeVersionInTests) { - checkEq(scalaFuncNew)(newF)(input) + checkEq(scalaFuncNew)(newF)(input) + } + + val checkOld = if(changedInVersion < V6SoftForkVersion) { + VersionContext.current.activatedVersion < changedInVersion + } else { + VersionContext.current.ergoTreeVersion < changedInVersion } - if (VersionContext.current.activatedVersion < changedInVersion) { + if (checkOld) { // check the old implementation with Scala semantic val expectedOldRes = expected.value @@ -874,12 +896,13 @@ class SigmaDslTesting extends AnyPropSpec override val scalaFuncNew: A => B, expectedExpr: Option[SValue], printExpectedExpr: Boolean = true, + override val activationType: Byte = ActivationByTreeVersion, 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 + vc.activatedVersion >= sinceVersion && vc.ergoTreeVersion >= sinceVersion override def scalaFunc: A => B = { x => if (isSupportedIn(VersionContext.current)) { @@ -1096,6 +1119,21 @@ class SigmaDslTesting extends AnyPropSpec commonNewResults.updateMany(newVersionedResults).toSeq } } + + def apply[A](value: Try[A], + costOpt: Option[Int], + expectedDetails: CostDetails, + newCostOpt: Option[Int], + newVersionedResults: Seq[(Int, (ExpectedResult[A], Option[CostDetails]))]): Expected[A] = + new Expected[A](ExpectedResult(value, costOpt)) { + override val newResults = { + val commonNewResults = defaultNewResults.map { + case (res, _) => + (ExpectedResult(res.value, newCostOpt), Option(expectedDetails)) + } + commonNewResults.updateMany(newVersionedResults).toSeq + } + } } /** Describes existing language feature which should be equally supported in both @@ -1134,12 +1172,15 @@ class SigmaDslTesting extends AnyPropSpec script: String, expectedExpr: SValue = null, allowNewToSucceed: Boolean = false, - allowDifferentErrors: Boolean = false + allowDifferentErrors: Boolean = false, + activationType: Byte = ActivationByTreeVersion ) (implicit IR: IRContext, evalSettings: EvalSettings): Feature[A, B] = { ChangedFeature(changedInVersion, script, scalaFunc, scalaFuncNew, Option(expectedExpr), allowNewToSucceed = allowNewToSucceed, - allowDifferentErrors = allowDifferentErrors) + allowDifferentErrors = allowDifferentErrors, + activationType = activationType + ) } /** Describes a NEW language feature which must NOT be supported in v4 and diff --git a/sc/shared/src/test/scala/sigmastate/ErgoTreeSpecification.scala b/sc/shared/src/test/scala/sigmastate/ErgoTreeSpecification.scala index 0655aaf8e6..ded954f170 100644 --- a/sc/shared/src/test/scala/sigmastate/ErgoTreeSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/ErgoTreeSpecification.scala @@ -316,7 +316,7 @@ class ErgoTreeSpecification extends SigmaDslTesting with ContractsTestkit with C */ case class MInfo(methodId: Byte, method: SMethod, isResolvableFromIds: Boolean = true) - def isV6Activated = VersionContext.current.isV6SoftForkActivated + def isV6Activated = VersionContext.current.isV3OrLaterErgoTreeVersion // NOTE, the type code constants are checked above // The methodId codes as checked here, they MUST be PRESERVED. @@ -476,7 +476,7 @@ class ErgoTreeSpecification extends SigmaDslTesting with ContractsTestkit with C MInfo(4, MultiplyMethod), MInfo(5, NegateMethod) ) ++ { - if(VersionContext.current.isV6SoftForkActivated) { + if(VersionContext.current.isV3OrLaterErgoTreeVersion) { Seq(MInfo(6, ExponentiateUnsignedMethod)) } else { Seq.empty @@ -554,7 +554,7 @@ class ErgoTreeSpecification extends SigmaDslTesting with ContractsTestkit with C MInfo(1, dataInputsMethod), MInfo(2, headersMethod), MInfo(3, preHeaderMethod), MInfo(4, inputsMethod), MInfo(5, outputsMethod), MInfo(6, heightMethod), MInfo(7, selfMethod), MInfo(8, selfBoxIndexMethod), MInfo(9, lastBlockUtxoRootHashMethod), - MInfo(10, minerPubKeyMethod)) ++ (if(VersionContext.current.isV6SoftForkActivated){ + MInfo(10, minerPubKeyMethod)) ++ (if(VersionContext.current.isV3OrLaterErgoTreeVersion){ Seq(MInfo(11, getVarV6Method), MInfo(12, getVarFromInputMethod)) } else { Seq(MInfo(11, getVarV5Method)) diff --git a/sc/shared/src/test/scala/sigmastate/SoftForkabilitySpecification.scala b/sc/shared/src/test/scala/sigmastate/SoftForkabilitySpecification.scala index c8b9f06399..1dfd3a3091 100644 --- a/sc/shared/src/test/scala/sigmastate/SoftForkabilitySpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/SoftForkabilitySpecification.scala @@ -3,7 +3,7 @@ package sigmastate import org.ergoplatform._ import org.ergoplatform.validation.ValidationRules._ import org.scalatest.BeforeAndAfterAll -import sigma.{Colls, SigmaTestingData} +import sigma.{Colls, SigmaTestingData, VersionContext} import sigma.ast._ import sigma.ast.SPrimType.MaxPrimTypeCode import sigma.ast.TypeCodes.LastConstantCode @@ -289,7 +289,7 @@ class SoftForkabilitySpecification extends SigmaTestingData trySoftForkable(false) { action true - } + }(vs) }, { case ve: ValidationException if ve.rule == rule => true case _ => false @@ -340,12 +340,14 @@ class SoftForkabilitySpecification extends SigmaTestingData } property("CheckMethod rule") { - val freeMethodId = 16.toByte - val mcBytes = Array[Byte](OpCodes.PropertyCallCode, SCollection.typeId, freeMethodId, Outputs.opCode) - val v2vs = vs.updated(CheckAndGetMethod.id, ChangedRule(Array(SCollection.typeId, freeMethodId))) - checkRule(CheckAndGetMethod, v2vs, { - ValueSerializer.deserialize(mcBytes) - }) + VersionContext.withVersions(3,0) { + val freeMethodId = 16.toByte + val mcBytes = Array[Byte](OpCodes.PropertyCallCode, SCollection.typeId, freeMethodId, Outputs.opCode) + val v2vs = vs.updated(CheckAndGetMethodV6.id, ChangedRule(Array(SCollection.typeId, freeMethodId))) + checkRule(CheckAndGetMethodV6, v2vs, { + ValueSerializer.deserialize(mcBytes) + }) + } } override protected def afterAll(): Unit = { diff --git a/sc/shared/src/test/scala/sigmastate/TestingInterpreterSpecification.scala b/sc/shared/src/test/scala/sigmastate/TestingInterpreterSpecification.scala index 4075ec5d77..64516b55e6 100644 --- a/sc/shared/src/test/scala/sigmastate/TestingInterpreterSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/TestingInterpreterSpecification.scala @@ -10,13 +10,9 @@ import org.ergoplatform._ import org.scalatest.BeforeAndAfterAll import scorex.util.encode.{Base16, Base58} import sigma.Colls -import sigma.VersionContext.V6SoftForkVersion -import sigma.VersionContext.V6SoftForkVersion -import sigma.VersionContext +import sigma.VersionContext.{V6SoftForkVersion, withVersions} import sigma.data.{CAND, CAvlTree, CBox, CHeader, ProveDlog, SigmaBoolean, TrivialProp} import sigma.interpreter.ContextExtension -import sigma.data.{AvlTreeData, CAND, ProveDlog, SigmaBoolean, TrivialProp} -import sigma.VersionContext.V6SoftForkVersion import sigma.VersionContext import sigma.util.Extensions.IntOps import sigmastate.helpers.{CompilerTestingCommons, ErgoLikeContextTesting, ErgoLikeTestInterpreter, ErgoLikeTestProvingInterpreter} @@ -244,10 +240,10 @@ class TestingInterpreterSpecification extends CompilerTestingCommons | Global.encodeNbits(b) == 36626176 |} |""".stripMargin - if (activatedVersionInTests < V6SoftForkVersion) { - an [sigmastate.exceptions.MethodNotFound] should be thrownBy testEval(source) - } else { + if (ergoTreeVersionInTests >= V6SoftForkVersion) { testEval(source) + } else { + an [sigmastate.exceptions.MethodNotFound] should be thrownBy testEval(source) } } @@ -267,7 +263,7 @@ class TestingInterpreterSpecification extends CompilerTestingCommons property("BigInt downcasting to byte") { def test() = testEval("{ sigmaProp(0L.toBigInt.toByte <= CONTEXT.preHeader.version) }") - if(VersionContext.current.isV6SoftForkActivated) { + if(VersionContext.current.isV3OrLaterErgoTreeVersion) { test() } else { an[Exception] shouldBe thrownBy(test()) @@ -276,7 +272,7 @@ class TestingInterpreterSpecification extends CompilerTestingCommons property("BigInt downcasting to short") { def test() = testEval("{ sigmaProp(0L.toBigInt.toShort <= CONTEXT.preHeader.version.toShort) }") - if(VersionContext.current.isV6SoftForkActivated) { + if(VersionContext.current.isV3OrLaterErgoTreeVersion) { test() } else { an[Exception] shouldBe thrownBy(test()) @@ -285,7 +281,7 @@ class TestingInterpreterSpecification extends CompilerTestingCommons property("BigInt downcasting to int") { def test() = testEval("{ sigmaProp(1L.toBigInt.toInt < CONTEXT.preHeader.timestamp.toInt) }") - if(VersionContext.current.isV6SoftForkActivated) { + if(VersionContext.current.isV3OrLaterErgoTreeVersion) { test() } else { an[Exception] shouldBe thrownBy(test()) @@ -294,7 +290,7 @@ class TestingInterpreterSpecification extends CompilerTestingCommons property("BigInt downcasting to long") { def test() = testEval("{ sigmaProp(1L.toBigInt.toLong < CONTEXT.preHeader.timestamp) }") - if(VersionContext.current.isV6SoftForkActivated) { + if(VersionContext.current.isV3OrLaterErgoTreeVersion) { test() } else { an[Exception] shouldBe thrownBy(test()) @@ -355,10 +351,10 @@ class TestingInterpreterSpecification extends CompilerTestingCommons | Global.powHit(k, msg, nonce, h, N) <= b // hit == b in this example |} |""".stripMargin - if (activatedVersionInTests < V6SoftForkVersion) { - an [sigmastate.exceptions.MethodNotFound] should be thrownBy testEval(source) - } else { + if (ergoTreeVersionInTests >= V6SoftForkVersion) { testEval(source) + } else { + an [sigmastate.exceptions.MethodNotFound] should be thrownBy testEval(source) } } @@ -516,10 +512,10 @@ class TestingInterpreterSpecification extends CompilerTestingCommons | } | """.stripMargin - if (activatedVersionInTests < V6SoftForkVersion) { - an [Exception] should be thrownBy testEval(source) - } else { + if (ergoTreeVersionInTests >= V6SoftForkVersion) { testEval(source) + } else { + an [Exception] should be thrownBy testEval(source) } } diff --git a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala index b34bd87fcf..3ccf17aef0 100644 --- a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala @@ -128,7 +128,7 @@ class BasicOpsSpecification extends CompilerTestingCommons propExp.asSigmaProp } else { // compile with the latest compiler version, to get validation exception during execution, not compilation error - withVersions(VersionContext.MaxSupportedScriptVersion, ergoTreeVersionInTests) { + withVersions(VersionContext.MaxSupportedScriptVersion, VersionContext.MaxSupportedScriptVersion) { compile(env, script).asBoolValue.toSigmaProp } } @@ -153,7 +153,7 @@ class BasicOpsSpecification extends CompilerTestingCommons val ctx = ErgoLikeContextTesting(currentHeight = 0, lastBlockUtxoRoot = AvlTreeData.dummy, ErgoLikeContextTesting.dummyPubkey, boxesToSpend = IndexedSeq(boxToSpend), - spendingTransaction = tx, self = boxToSpend, activatedVersionInTests) + spendingTransaction = tx, self = boxToSpend, ergoTreeVersionInTests) val pr = prover.prove(env + (ScriptNameProp -> s"${name}_prove"), tree, ctx, fakeMessage).getOrThrow @@ -194,7 +194,7 @@ class BasicOpsSpecification extends CompilerTestingCommons ) } - if (VersionContext.current.isV6SoftForkActivated) { + if (VersionContext.current.isV3OrLaterErgoTreeVersion) { getVarTest() } else { an[sigma.validation.ValidationException] should be thrownBy getVarTest() @@ -215,7 +215,7 @@ class BasicOpsSpecification extends CompilerTestingCommons ) } - if (VersionContext.current.isV6SoftForkActivated) { + if (VersionContext.current.isV3OrLaterErgoTreeVersion) { getVarTest() } else { an[sigma.validation.ValidationException] should be thrownBy getVarTest() @@ -233,7 +233,7 @@ class BasicOpsSpecification extends CompilerTestingCommons ) } - if (VersionContext.current.isV6SoftForkActivated) { + if (VersionContext.current.isV3OrLaterErgoTreeVersion) { getVarTest() } else { an[sigma.validation.ValidationException] should be thrownBy getVarTest() @@ -259,8 +259,8 @@ class BasicOpsSpecification extends CompilerTestingCommons true )} - if (activatedVersionInTests < V6SoftForkVersion) { - an[Exception] should be thrownBy deserTest() + if (ergoTreeVersionInTests < V6SoftForkVersion) { + an[sigma.validation.ValidationException] should be thrownBy deserTest() } else { deserTest() } @@ -280,8 +280,8 @@ class BasicOpsSpecification extends CompilerTestingCommons true )} - if (activatedVersionInTests < V6SoftForkVersion) { - an[Exception] should be thrownBy conversionTest() + if (ergoTreeVersionInTests < V6SoftForkVersion) { + an[sigma.validation.ValidationException] should be thrownBy conversionTest() } else { conversionTest() } @@ -298,8 +298,8 @@ class BasicOpsSpecification extends CompilerTestingCommons true )} - if (activatedVersionInTests < V6SoftForkVersion) { - an[Exception] should be thrownBy conversionTest() + if (ergoTreeVersionInTests < V6SoftForkVersion) { + an[sigma.validation.ValidationException] should be thrownBy conversionTest() } else { an[Exception] should be thrownBy conversionTest() } @@ -315,7 +315,7 @@ class BasicOpsSpecification extends CompilerTestingCommons true )} - if (activatedVersionInTests < V6SoftForkVersion) { + if (ergoTreeVersionInTests < V6SoftForkVersion) { an[Exception] should be thrownBy conversionTest() } else { an[sigma.exceptions.InvalidArguments] should be thrownBy conversionTest() @@ -335,8 +335,8 @@ class BasicOpsSpecification extends CompilerTestingCommons true )} - if (activatedVersionInTests < V6SoftForkVersion) { - an[Exception] should be thrownBy conversionTest() + if (ergoTreeVersionInTests < V6SoftForkVersion) { + an[sigma.validation.ValidationException] should be thrownBy conversionTest() } else { conversionTest() } @@ -355,8 +355,8 @@ class BasicOpsSpecification extends CompilerTestingCommons true )} - if (activatedVersionInTests < V6SoftForkVersion) { - an[Exception] should be thrownBy conversionTest() + if (ergoTreeVersionInTests < V6SoftForkVersion) { + an[sigma.validation.ValidationException] should be thrownBy conversionTest() } else { conversionTest() } @@ -374,8 +374,8 @@ class BasicOpsSpecification extends CompilerTestingCommons true )} - if (activatedVersionInTests < V6SoftForkVersion) { - an[Exception] should be thrownBy conversionTest() + if (ergoTreeVersionInTests < V6SoftForkVersion) { + an[sigma.serialization.SerializerException] should be thrownBy conversionTest() } else { conversionTest() } @@ -393,8 +393,8 @@ class BasicOpsSpecification extends CompilerTestingCommons true )} - if (activatedVersionInTests < V6SoftForkVersion) { - an[Exception] should be thrownBy conversionTest() + if (ergoTreeVersionInTests < V6SoftForkVersion) { + an[sigma.serialization.SerializerException] should be thrownBy conversionTest() } else { an[Exception] should be thrownBy conversionTest() } @@ -411,8 +411,8 @@ class BasicOpsSpecification extends CompilerTestingCommons true )} - if (activatedVersionInTests < V6SoftForkVersion) { - an[Exception] should be thrownBy conversionTest() + if (ergoTreeVersionInTests < V6SoftForkVersion) { + an[sigma.validation.ValidationException] should be thrownBy conversionTest() } else { conversionTest() } @@ -428,7 +428,7 @@ class BasicOpsSpecification extends CompilerTestingCommons true )} - if (activatedVersionInTests < V6SoftForkVersion) { + if (ergoTreeVersionInTests < V6SoftForkVersion) { an[Exception] should be thrownBy conversionTest() } else { val t = Try(conversionTest()) @@ -505,8 +505,8 @@ class BasicOpsSpecification extends CompilerTestingCommons ) } - if (activatedVersionInTests < V6SoftForkVersion) { - an[Exception] should be thrownBy schnorrTest() + if (ergoTreeVersionInTests < V6SoftForkVersion) { + an[sigma.validation.ValidationException] should be thrownBy schnorrTest() } else { schnorrTest() } @@ -526,7 +526,7 @@ class BasicOpsSpecification extends CompilerTestingCommons ) } - if (activatedVersionInTests < V6SoftForkVersion) { + if (ergoTreeVersionInTests < V6SoftForkVersion) { an[Exception] should be thrownBy miTest() } else { miTest() @@ -546,8 +546,8 @@ class BasicOpsSpecification extends CompilerTestingCommons ) } - if (activatedVersionInTests < V6SoftForkVersion) { - an[Exception] should be thrownBy miTest() + if (ergoTreeVersionInTests < V6SoftForkVersion) { + an[sigma.validation.ValidationException] should be thrownBy miTest() } else { miTest() } @@ -566,8 +566,8 @@ class BasicOpsSpecification extends CompilerTestingCommons ) } - if (activatedVersionInTests < V6SoftForkVersion) { - an[Exception] should be thrownBy miTest() + if (ergoTreeVersionInTests < V6SoftForkVersion) { + an[sigma.validation.ValidationException] should be thrownBy miTest() } else { miTest() } @@ -587,8 +587,8 @@ class BasicOpsSpecification extends CompilerTestingCommons ) } - if (activatedVersionInTests < V6SoftForkVersion) { - an[Exception] should be thrownBy miTest() + if (ergoTreeVersionInTests < V6SoftForkVersion) { + an[sigma.validation.ValidationException] should be thrownBy miTest() } else { miTest() } @@ -608,8 +608,8 @@ class BasicOpsSpecification extends CompilerTestingCommons ) } - if (activatedVersionInTests < V6SoftForkVersion) { - an[Exception] should be thrownBy miTest() + if (ergoTreeVersionInTests < V6SoftForkVersion) { + an[sigma.validation.ValidationException] should be thrownBy miTest() } else { miTest() } @@ -629,8 +629,8 @@ class BasicOpsSpecification extends CompilerTestingCommons ) } - if (activatedVersionInTests < V6SoftForkVersion) { - an[Exception] should be thrownBy miTest() + if (ergoTreeVersionInTests < V6SoftForkVersion) { + an[sigma.validation.ValidationException] should be thrownBy miTest() } else { miTest() } @@ -741,8 +741,8 @@ class BasicOpsSpecification extends CompilerTestingCommons ) } - if (activatedVersionInTests < V6SoftForkVersion) { - an[Exception] should be thrownBy rangeTest() + if (ergoTreeVersionInTests < V6SoftForkVersion) { + an[sigma.validation.ValidationException] should be thrownBy rangeTest() } else { rangeTest() } @@ -800,8 +800,8 @@ class BasicOpsSpecification extends CompilerTestingCommons ) } - if (activatedVersionInTests < V6SoftForkVersion) { - an[Exception] should be thrownBy circuitTest() + if (ergoTreeVersionInTests < V6SoftForkVersion) { + an[sigma.validation.ValidationException] should be thrownBy circuitTest() } else { circuitTest() } @@ -819,7 +819,7 @@ class BasicOpsSpecification extends CompilerTestingCommons null ) - if (VersionContext.current.isV6SoftForkActivated) { + if (VersionContext.current.isV3OrLaterErgoTreeVersion) { toBitsTest() } else { an[sigma.validation.ValidationException] shouldBe thrownBy(toBitsTest()) @@ -841,7 +841,7 @@ class BasicOpsSpecification extends CompilerTestingCommons null ) - if (VersionContext.current.isV6SoftForkActivated) { + if (VersionContext.current.isV3OrLaterErgoTreeVersion) { toBitsTest() } else { an[sigma.validation.ValidationException] shouldBe thrownBy(toBitsTest()) @@ -858,7 +858,7 @@ class BasicOpsSpecification extends CompilerTestingCommons null ) - if (VersionContext.current.isV6SoftForkActivated) { + if (VersionContext.current.isV3OrLaterErgoTreeVersion) { toBitsTest() } else { an[sigma.validation.ValidationException] shouldBe thrownBy(toBitsTest()) @@ -876,7 +876,7 @@ class BasicOpsSpecification extends CompilerTestingCommons null ) - if (VersionContext.current.isV6SoftForkActivated) { + if (VersionContext.current.isV3OrLaterErgoTreeVersion) { toBitsTest() } else { an[ValidationException] shouldBe thrownBy(toBitsTest()) @@ -893,7 +893,7 @@ class BasicOpsSpecification extends CompilerTestingCommons null ) - if (VersionContext.current.isV6SoftForkActivated) { + if (VersionContext.current.isV3OrLaterErgoTreeVersion) { toBitsTest() } else { an[ValidationException] shouldBe thrownBy(toBitsTest()) @@ -911,7 +911,7 @@ class BasicOpsSpecification extends CompilerTestingCommons null ) - if (VersionContext.current.isV6SoftForkActivated) { + if (VersionContext.current.isV3OrLaterErgoTreeVersion) { bitwiseInverseTest() } else { an[sigma.validation.ValidationException] shouldBe thrownBy(bitwiseInverseTest()) @@ -928,7 +928,7 @@ class BasicOpsSpecification extends CompilerTestingCommons null ) - if (VersionContext.current.isV6SoftForkActivated) { + if (VersionContext.current.isV3OrLaterErgoTreeVersion) { bitwiseInverseTest() } else { an[sigma.validation.ValidationException] shouldBe thrownBy(bitwiseInverseTest()) @@ -945,7 +945,7 @@ class BasicOpsSpecification extends CompilerTestingCommons null ) - if (VersionContext.current.isV6SoftForkActivated) { + if (VersionContext.current.isV3OrLaterErgoTreeVersion) { bitwiseInverseTest() } else { an[sigma.validation.ValidationException] shouldBe thrownBy(bitwiseInverseTest()) @@ -965,7 +965,7 @@ class BasicOpsSpecification extends CompilerTestingCommons null ) - if (VersionContext.current.isV6SoftForkActivated) { + if (VersionContext.current.isV3OrLaterErgoTreeVersion) { bitwiseInverseTest() } else { an[sigma.validation.ValidationException] shouldBe thrownBy(bitwiseInverseTest()) @@ -986,7 +986,7 @@ class BasicOpsSpecification extends CompilerTestingCommons null ) - if (VersionContext.current.isV6SoftForkActivated) { + if (VersionContext.current.isV3OrLaterErgoTreeVersion) { bitwiseOrTest() } else { an[sigma.validation.ValidationException] shouldBe thrownBy(bitwiseOrTest()) @@ -1002,7 +1002,7 @@ class BasicOpsSpecification extends CompilerTestingCommons null ) - if (VersionContext.current.isV6SoftForkActivated) { + if (VersionContext.current.isV3OrLaterErgoTreeVersion) { bitwiseOrTest() } else { an[sigma.validation.ValidationException] shouldBe thrownBy(bitwiseOrTest()) @@ -1018,7 +1018,7 @@ class BasicOpsSpecification extends CompilerTestingCommons null ) - if (VersionContext.current.isV6SoftForkActivated) { + if (VersionContext.current.isV3OrLaterErgoTreeVersion) { bitwiseOrTest() } else { an[sigma.validation.ValidationException] shouldBe thrownBy(bitwiseOrTest()) @@ -1036,7 +1036,7 @@ class BasicOpsSpecification extends CompilerTestingCommons null ) - if (VersionContext.current.isV6SoftForkActivated) { + if (VersionContext.current.isV3OrLaterErgoTreeVersion) { bitwiseOrTest() } else { an[sigma.validation.ValidationException] shouldBe thrownBy(bitwiseOrTest()) @@ -1053,7 +1053,7 @@ class BasicOpsSpecification extends CompilerTestingCommons null ) - if (VersionContext.current.isV6SoftForkActivated) { + if (VersionContext.current.isV3OrLaterErgoTreeVersion) { bitwiseAndTest() } else { an[sigma.validation.ValidationException] shouldBe thrownBy(bitwiseAndTest()) @@ -1070,7 +1070,7 @@ class BasicOpsSpecification extends CompilerTestingCommons null ) - if (VersionContext.current.isV6SoftForkActivated) { + if (VersionContext.current.isV3OrLaterErgoTreeVersion) { bitwiseAndTest() } else { an[sigma.validation.ValidationException] shouldBe thrownBy(bitwiseAndTest()) @@ -1090,7 +1090,7 @@ class BasicOpsSpecification extends CompilerTestingCommons null ) - if (VersionContext.current.isV6SoftForkActivated) { + if (VersionContext.current.isV3OrLaterErgoTreeVersion) { bitwiseAndTest() } else { an[sigma.validation.ValidationException] shouldBe thrownBy(bitwiseAndTest()) @@ -1110,7 +1110,7 @@ class BasicOpsSpecification extends CompilerTestingCommons null ) - if (VersionContext.current.isV6SoftForkActivated) { + if (VersionContext.current.isV3OrLaterErgoTreeVersion) { bitwiseAndTest() } else { an[sigma.validation.ValidationException] shouldBe thrownBy(bitwiseAndTest()) @@ -1130,7 +1130,7 @@ class BasicOpsSpecification extends CompilerTestingCommons null ) - if (VersionContext.current.isV6SoftForkActivated) { + if (VersionContext.current.isV3OrLaterErgoTreeVersion) { bitwiseXorTest() } else { an[sigma.validation.ValidationException] shouldBe thrownBy(bitwiseXorTest()) @@ -1150,7 +1150,7 @@ class BasicOpsSpecification extends CompilerTestingCommons null ) - if (VersionContext.current.isV6SoftForkActivated) { + if (VersionContext.current.isV3OrLaterErgoTreeVersion) { bitwiseAndTest() } else { an[sigma.validation.ValidationException] shouldBe thrownBy(bitwiseAndTest()) @@ -1167,7 +1167,7 @@ class BasicOpsSpecification extends CompilerTestingCommons null ) - if (VersionContext.current.isV6SoftForkActivated) { + if (VersionContext.current.isV3OrLaterErgoTreeVersion) { shiftLeftTest() } else { an[sigma.validation.ValidationException] shouldBe thrownBy(shiftLeftTest()) @@ -1184,7 +1184,7 @@ class BasicOpsSpecification extends CompilerTestingCommons null ) - if (VersionContext.current.isV6SoftForkActivated) { + if (VersionContext.current.isV3OrLaterErgoTreeVersion) { an[IllegalArgumentException] shouldBe thrownBy(shiftLeftTest()) } else { an[sigma.validation.ValidationException] shouldBe thrownBy(shiftLeftTest()) @@ -1201,7 +1201,7 @@ class BasicOpsSpecification extends CompilerTestingCommons null ) - if (VersionContext.current.isV6SoftForkActivated) { + if (VersionContext.current.isV3OrLaterErgoTreeVersion) { shiftLeftTest() } else { an[sigma.validation.ValidationException] shouldBe thrownBy(shiftLeftTest()) @@ -1218,7 +1218,7 @@ class BasicOpsSpecification extends CompilerTestingCommons null ) - if (VersionContext.current.isV6SoftForkActivated) { + if (VersionContext.current.isV3OrLaterErgoTreeVersion) { shiftLeftTest() } else { an[sigma.validation.ValidationException] shouldBe thrownBy(shiftLeftTest()) @@ -1235,7 +1235,7 @@ class BasicOpsSpecification extends CompilerTestingCommons null ) - if (VersionContext.current.isV6SoftForkActivated) { + if (VersionContext.current.isV3OrLaterErgoTreeVersion) { shiftLeftTest() } else { an[sigma.validation.ValidationException] shouldBe thrownBy(shiftLeftTest()) @@ -1251,7 +1251,7 @@ class BasicOpsSpecification extends CompilerTestingCommons null ) - if (VersionContext.current.isV6SoftForkActivated) { + if (VersionContext.current.isV3OrLaterErgoTreeVersion) { an[ArithmeticException] shouldBe thrownBy(shiftLeftTest()) } else { an[sigma.validation.ValidationException] shouldBe thrownBy(shiftLeftTest()) @@ -1268,7 +1268,7 @@ class BasicOpsSpecification extends CompilerTestingCommons null ) - if (VersionContext.current.isV6SoftForkActivated) { + if (VersionContext.current.isV3OrLaterErgoTreeVersion) { an[java.lang.IllegalArgumentException] shouldBe thrownBy(shiftLeftTest()) } else { an[sigma.validation.ValidationException] shouldBe thrownBy(shiftLeftTest()) @@ -1284,7 +1284,7 @@ class BasicOpsSpecification extends CompilerTestingCommons null ) - if (VersionContext.current.isV6SoftForkActivated) { + if (VersionContext.current.isV3OrLaterErgoTreeVersion) { an[ArithmeticException] shouldBe thrownBy(shiftLeftTest()) } else { an[sigma.validation.ValidationException] shouldBe thrownBy(shiftLeftTest()) @@ -1301,7 +1301,7 @@ class BasicOpsSpecification extends CompilerTestingCommons null ) - if (VersionContext.current.isV6SoftForkActivated) { + if (VersionContext.current.isV3OrLaterErgoTreeVersion) { shiftRightTest() } else { an[sigma.validation.ValidationException] shouldBe thrownBy(shiftRightTest()) @@ -1318,7 +1318,7 @@ class BasicOpsSpecification extends CompilerTestingCommons null ) - if (VersionContext.current.isV6SoftForkActivated) { + if (VersionContext.current.isV3OrLaterErgoTreeVersion) { shiftRightTest() } else { an[sigma.validation.ValidationException] shouldBe thrownBy(shiftRightTest()) @@ -1335,7 +1335,7 @@ class BasicOpsSpecification extends CompilerTestingCommons null ) - if (VersionContext.current.isV6SoftForkActivated) { + if (VersionContext.current.isV3OrLaterErgoTreeVersion) { an[IllegalArgumentException] shouldBe thrownBy(shiftRightTest()) } else { an[sigma.validation.ValidationException] shouldBe thrownBy(shiftRightTest()) @@ -1353,7 +1353,7 @@ class BasicOpsSpecification extends CompilerTestingCommons null ) - if (VersionContext.current.isV6SoftForkActivated) { + if (VersionContext.current.isV3OrLaterErgoTreeVersion) { shiftRightTest() } else { an[sigma.validation.ValidationException] shouldBe thrownBy(shiftRightTest()) @@ -1370,7 +1370,7 @@ class BasicOpsSpecification extends CompilerTestingCommons null ) - if (VersionContext.current.isV6SoftForkActivated) { + if (VersionContext.current.isV3OrLaterErgoTreeVersion) { an[IllegalArgumentException] shouldBe thrownBy(shiftRightTest()) } else { an[sigma.validation.ValidationException] shouldBe thrownBy(shiftRightTest()) @@ -1388,7 +1388,7 @@ class BasicOpsSpecification extends CompilerTestingCommons null ) - if (VersionContext.current.isV6SoftForkActivated) { + if (VersionContext.current.isV3OrLaterErgoTreeVersion) { shiftRightTest() } else { an[sigma.validation.ValidationException] shouldBe thrownBy(shiftRightTest()) @@ -1406,7 +1406,7 @@ class BasicOpsSpecification extends CompilerTestingCommons null ) - if (VersionContext.current.isV6SoftForkActivated) { + if (VersionContext.current.isV3OrLaterErgoTreeVersion) { an[IllegalArgumentException] shouldBe thrownBy(shiftRightTest()) } else { an[sigma.validation.ValidationException] shouldBe thrownBy(shiftRightTest()) @@ -1424,7 +1424,7 @@ class BasicOpsSpecification extends CompilerTestingCommons null ) - if (VersionContext.current.isV6SoftForkActivated) { + if (VersionContext.current.isV3OrLaterErgoTreeVersion) { shiftRightTest() } else { an[sigma.validation.ValidationException] shouldBe thrownBy(shiftRightTest()) @@ -1442,7 +1442,7 @@ class BasicOpsSpecification extends CompilerTestingCommons null ) - if (VersionContext.current.isV6SoftForkActivated) { + if (VersionContext.current.isV3OrLaterErgoTreeVersion) { an[java.lang.IllegalArgumentException] shouldBe thrownBy(shiftRightTest()) } else { an[sigma.validation.ValidationException] shouldBe thrownBy(shiftRightTest()) @@ -1460,7 +1460,7 @@ class BasicOpsSpecification extends CompilerTestingCommons ) } - if (VersionContext.current.isV6SoftForkActivated) { + if (VersionContext.current.isV3OrLaterErgoTreeVersion) { getVarTest() } else { an[sigma.validation.ValidationException] should be thrownBy getVarTest() @@ -1481,7 +1481,7 @@ class BasicOpsSpecification extends CompilerTestingCommons null ) - if(VersionContext.current.isV6SoftForkActivated) { + if(VersionContext.current.isV3OrLaterErgoTreeVersion) { reverseTest() } else { an[sigma.validation.ValidationException] shouldBe thrownBy(reverseTest()) @@ -1502,7 +1502,7 @@ class BasicOpsSpecification extends CompilerTestingCommons null ) - if(VersionContext.current.isV6SoftForkActivated) { + if(VersionContext.current.isV3OrLaterErgoTreeVersion) { reverseTest() } else { an[sigma.validation.ValidationException] shouldBe thrownBy(reverseTest()) @@ -1526,7 +1526,7 @@ class BasicOpsSpecification extends CompilerTestingCommons null ) - if(VersionContext.current.isV6SoftForkActivated) { + if(VersionContext.current.isV3OrLaterErgoTreeVersion) { reverseTest() } else { an[sigma.validation.ValidationException] shouldBe thrownBy(reverseTest()) @@ -1550,7 +1550,7 @@ class BasicOpsSpecification extends CompilerTestingCommons null ) - if(VersionContext.current.isV6SoftForkActivated) { + if(VersionContext.current.isV3OrLaterErgoTreeVersion) { reverseTest() } else { an[sigma.validation.ValidationException] shouldBe thrownBy(reverseTest()) @@ -1574,7 +1574,7 @@ class BasicOpsSpecification extends CompilerTestingCommons null ) - if(VersionContext.current.isV6SoftForkActivated) { + if(VersionContext.current.isV3OrLaterErgoTreeVersion) { reverseTest() } else { an[sigma.validation.ValidationException] shouldBe thrownBy(reverseTest()) @@ -1598,7 +1598,7 @@ class BasicOpsSpecification extends CompilerTestingCommons null ) - if(VersionContext.current.isV6SoftForkActivated) { + if(VersionContext.current.isV3OrLaterErgoTreeVersion) { reverseTest() } else { an[sigma.validation.ValidationException] shouldBe thrownBy(reverseTest()) @@ -1616,7 +1616,7 @@ class BasicOpsSpecification extends CompilerTestingCommons null ) - if(VersionContext.current.isV6SoftForkActivated) { + if(VersionContext.current.isV3OrLaterErgoTreeVersion) { getTest() } else { an[sigma.validation.ValidationException] shouldBe thrownBy(getTest()) @@ -1632,7 +1632,7 @@ class BasicOpsSpecification extends CompilerTestingCommons |""".stripMargin, null ) - if(VersionContext.current.isV6SoftForkActivated) { + if(VersionContext.current.isV3OrLaterErgoTreeVersion) { fromTest() } else { an[sigma.validation.ValidationException] should be thrownBy(fromTest()) @@ -1648,7 +1648,7 @@ class BasicOpsSpecification extends CompilerTestingCommons |""".stripMargin, null ) - if(VersionContext.current.isV6SoftForkActivated) { + if(VersionContext.current.isV3OrLaterErgoTreeVersion) { fromTest() } else { an[sigma.validation.ValidationException] should be thrownBy(fromTest()) @@ -1664,7 +1664,7 @@ class BasicOpsSpecification extends CompilerTestingCommons |""".stripMargin, null ) - if(VersionContext.current.isV6SoftForkActivated) { + if(VersionContext.current.isV3OrLaterErgoTreeVersion) { fromTest() } else { an[sigma.validation.ValidationException] should be thrownBy(fromTest()) @@ -1681,7 +1681,7 @@ class BasicOpsSpecification extends CompilerTestingCommons |""".stripMargin, null ) - if(VersionContext.current.isV6SoftForkActivated) { + if(VersionContext.current.isV3OrLaterErgoTreeVersion) { fromTest() } else { an[sigma.validation.ValidationException] should be thrownBy(fromTest()) @@ -1701,7 +1701,7 @@ class BasicOpsSpecification extends CompilerTestingCommons |""".stripMargin, null ) - if(VersionContext.current.isV6SoftForkActivated) { + if(VersionContext.current.isV3OrLaterErgoTreeVersion) { fromTest() } else { an[sigma.validation.ValidationException] should be thrownBy(fromTest()) @@ -1718,7 +1718,7 @@ class BasicOpsSpecification extends CompilerTestingCommons |""".stripMargin, null ) - if(VersionContext.current.isV6SoftForkActivated) { + if(VersionContext.current.isV3OrLaterErgoTreeVersion) { fromTest() } else { an[sigma.validation.ValidationException] should be thrownBy(fromTest()) @@ -1737,7 +1737,7 @@ class BasicOpsSpecification extends CompilerTestingCommons null ) - if (VersionContext.current.isV6SoftForkActivated) { + if (VersionContext.current.isV3OrLaterErgoTreeVersion) { toBytesTest() } else { an[sigma.validation.ValidationException] shouldBe thrownBy(toBytesTest()) @@ -1756,7 +1756,7 @@ class BasicOpsSpecification extends CompilerTestingCommons null ) - if (VersionContext.current.isV6SoftForkActivated) { + if (VersionContext.current.isV3OrLaterErgoTreeVersion) { toBytesTest() } else { an[sigma.validation.ValidationException] shouldBe thrownBy(toBytesTest()) @@ -1775,7 +1775,7 @@ class BasicOpsSpecification extends CompilerTestingCommons null ) - if (VersionContext.current.isV6SoftForkActivated) { + if (VersionContext.current.isV3OrLaterErgoTreeVersion) { toBytesTest() } else { an[sigma.validation.ValidationException] shouldBe thrownBy(toBytesTest()) @@ -1792,7 +1792,7 @@ class BasicOpsSpecification extends CompilerTestingCommons null ) - if (VersionContext.current.isV6SoftForkActivated) { + if (VersionContext.current.isV3OrLaterErgoTreeVersion) { toBytesTest() } else { an[sigma.validation.ValidationException] shouldBe thrownBy(toBytesTest()) @@ -1807,7 +1807,7 @@ class BasicOpsSpecification extends CompilerTestingCommons def toBytesTest() = test("UnsignedBigInt.toBytes", env, ext, script, null) - if (VersionContext.current.isV6SoftForkActivated) { + if (VersionContext.current.isV3OrLaterErgoTreeVersion) { toBytesTest() } else { an[ValidationException] shouldBe thrownBy(toBytesTest()) @@ -1823,7 +1823,7 @@ class BasicOpsSpecification extends CompilerTestingCommons def toBytesTest() = test("UnsignedBigInt.toBytes", env, ext, script, null) - if (VersionContext.current.isV6SoftForkActivated) { + if (VersionContext.current.isV3OrLaterErgoTreeVersion) { toBytesTest() } else { an[ValidationException] shouldBe thrownBy(toBytesTest()) @@ -1840,7 +1840,7 @@ class BasicOpsSpecification extends CompilerTestingCommons true ) - if (activatedVersionInTests < V6SoftForkVersion) { + if (ergoTreeVersionInTests < V6SoftForkVersion) { an [sigma.validation.ValidationException] should be thrownBy deserTest() } else { deserTest() @@ -1857,7 +1857,7 @@ class BasicOpsSpecification extends CompilerTestingCommons true ) - if (activatedVersionInTests < V6SoftForkVersion) { + if (ergoTreeVersionInTests < V6SoftForkVersion) { an [sigma.validation.ValidationException] should be thrownBy deserTest() } else { deserTest() @@ -1874,7 +1874,7 @@ class BasicOpsSpecification extends CompilerTestingCommons true ) - if (activatedVersionInTests < V6SoftForkVersion) { + if (ergoTreeVersionInTests < V6SoftForkVersion) { an [sigma.validation.ValidationException] should be thrownBy deserTest() } else { deserTest() @@ -1893,7 +1893,7 @@ class BasicOpsSpecification extends CompilerTestingCommons true ) - if (activatedVersionInTests < V6SoftForkVersion) { + if (ergoTreeVersionInTests < V6SoftForkVersion) { an [sigma.validation.ValidationException] should be thrownBy deserTest() } else { deserTest() @@ -1914,7 +1914,7 @@ class BasicOpsSpecification extends CompilerTestingCommons true ) - if (activatedVersionInTests < V6SoftForkVersion) { + if (ergoTreeVersionInTests < V6SoftForkVersion) { an [sigma.validation.ValidationException] should be thrownBy deserTest() } else { deserTest() @@ -1935,7 +1935,7 @@ class BasicOpsSpecification extends CompilerTestingCommons true ) - if (activatedVersionInTests < V6SoftForkVersion) { + if (ergoTreeVersionInTests < V6SoftForkVersion) { an [sigma.validation.ValidationException] should be thrownBy deserTest() } else { deserTest() @@ -1958,7 +1958,7 @@ class BasicOpsSpecification extends CompilerTestingCommons true ) - if (activatedVersionInTests < V6SoftForkVersion) { + if (ergoTreeVersionInTests < V6SoftForkVersion) { an [sigma.validation.ValidationException] should be thrownBy deserTest() } else { deserTest() @@ -1982,7 +1982,7 @@ class BasicOpsSpecification extends CompilerTestingCommons true ) - if (activatedVersionInTests < V6SoftForkVersion) { + if (ergoTreeVersionInTests < V6SoftForkVersion) { an[sigma.validation.ValidationException] should be thrownBy deserTest() } else { deserTest() @@ -2004,7 +2004,7 @@ class BasicOpsSpecification extends CompilerTestingCommons true ) - if (activatedVersionInTests < V6SoftForkVersion) { + if (ergoTreeVersionInTests < V6SoftForkVersion) { an[sigma.validation.ValidationException] should be thrownBy deserTest() } else { // we have wrapped CostLimitException here @@ -2024,7 +2024,7 @@ class BasicOpsSpecification extends CompilerTestingCommons null ) - if (VersionContext.current.isV6SoftForkActivated) { + if (VersionContext.current.isV3OrLaterErgoTreeVersion) { optTest() } else { assertExceptionThrown(optTest(), _.isInstanceOf[NoSuchElementException]) @@ -2042,7 +2042,7 @@ class BasicOpsSpecification extends CompilerTestingCommons null ) - if(VersionContext.current.isV6SoftForkActivated) { + if(VersionContext.current.isV3OrLaterErgoTreeVersion) { optTest() } else { assertExceptionThrown(optTest(), _.isInstanceOf[NoSuchElementException]) @@ -2089,7 +2089,7 @@ class BasicOpsSpecification extends CompilerTestingCommons testExceededCost = false ) } - if (activatedVersionInTests < V6SoftForkVersion) { + if (ergoTreeVersionInTests < V6SoftForkVersion) { an[sigma.validation.ValidationException] should be thrownBy powTest() } else { powTest() @@ -2121,7 +2121,7 @@ class BasicOpsSpecification extends CompilerTestingCommons ) } - if (activatedVersionInTests < V6SoftForkVersion) { + if (ergoTreeVersionInTests < V6SoftForkVersion) { an[sigma.validation.ValidationException] should be thrownBy powTest() } else { powTest() @@ -2141,7 +2141,7 @@ class BasicOpsSpecification extends CompilerTestingCommons true ) - if (activatedVersionInTests < V6SoftForkVersion) { + if (ergoTreeVersionInTests < V6SoftForkVersion) { an[Exception] should be thrownBy deserTest() } else { deserTest() @@ -2158,7 +2158,7 @@ class BasicOpsSpecification extends CompilerTestingCommons true )} - if (activatedVersionInTests < V6SoftForkVersion) { + if (ergoTreeVersionInTests < V6SoftForkVersion) { an [sigma.validation.ValidationException] should be thrownBy deserTest() } else { deserTest() @@ -2178,7 +2178,7 @@ class BasicOpsSpecification extends CompilerTestingCommons ) } - if (activatedVersionInTests < V6SoftForkVersion) { + if (ergoTreeVersionInTests < V6SoftForkVersion) { an [sigma.validation.ValidationException] should be thrownBy deserTest() } else { deserTest() @@ -2200,7 +2200,7 @@ class BasicOpsSpecification extends CompilerTestingCommons true ) - if (activatedVersionInTests < V6SoftForkVersion) { + if (ergoTreeVersionInTests < V6SoftForkVersion) { an [sigma.validation.ValidationException] should be thrownBy deserTest() } else { deserTest() @@ -2218,7 +2218,7 @@ class BasicOpsSpecification extends CompilerTestingCommons true ) - if (activatedVersionInTests < V6SoftForkVersion) { + if (ergoTreeVersionInTests < V6SoftForkVersion) { an [sigma.validation.ValidationException] should be thrownBy deserTest() } else { deserTest() @@ -2245,7 +2245,7 @@ class BasicOpsSpecification extends CompilerTestingCommons true ) - if (activatedVersionInTests < V6SoftForkVersion) { + if (ergoTreeVersionInTests < V6SoftForkVersion) { an [sigma.validation.ValidationException] should be thrownBy deserTest() } else { deserTest() @@ -2265,7 +2265,7 @@ class BasicOpsSpecification extends CompilerTestingCommons true ) - if (activatedVersionInTests < V6SoftForkVersion) { + if (ergoTreeVersionInTests < V6SoftForkVersion) { an [sigma.validation.ValidationException] should be thrownBy deserTest() } else { deserTest() @@ -2286,7 +2286,7 @@ class BasicOpsSpecification extends CompilerTestingCommons true ) - if (activatedVersionInTests < V6SoftForkVersion) { + if (ergoTreeVersionInTests < V6SoftForkVersion) { an [sigma.validation.ValidationException] should be thrownBy deserTest() } else { deserTest() @@ -2306,7 +2306,7 @@ class BasicOpsSpecification extends CompilerTestingCommons true ) - if (activatedVersionInTests < V6SoftForkVersion) { + if (ergoTreeVersionInTests < V6SoftForkVersion) { an [sigma.validation.ValidationException] should be thrownBy deserTest() } else { deserTest() @@ -2326,7 +2326,7 @@ class BasicOpsSpecification extends CompilerTestingCommons true ) - if (activatedVersionInTests < V6SoftForkVersion) { + if (ergoTreeVersionInTests < V6SoftForkVersion) { an [sigma.validation.ValidationException] should be thrownBy deserTest() } else { deserTest() @@ -2349,7 +2349,7 @@ class BasicOpsSpecification extends CompilerTestingCommons true ) - if (activatedVersionInTests < V6SoftForkVersion) { + if (ergoTreeVersionInTests < V6SoftForkVersion) { an [sigma.validation.ValidationException] should be thrownBy deserTest() } else { an [Exception] should be thrownBy deserTest() @@ -2404,7 +2404,7 @@ class BasicOpsSpecification extends CompilerTestingCommons true ) - if (activatedVersionInTests < V6SoftForkVersion) { + if (ergoTreeVersionInTests < V6SoftForkVersion) { an[sigma.validation.ValidationException] should be thrownBy deserTest() } else { deserTest() @@ -2430,7 +2430,7 @@ class BasicOpsSpecification extends CompilerTestingCommons true ) - if (activatedVersionInTests < V6SoftForkVersion) { + if (ergoTreeVersionInTests < V6SoftForkVersion) { an[sigma.validation.ValidationException] should be thrownBy deserTest() } else { deserTest() @@ -2753,7 +2753,7 @@ class BasicOpsSpecification extends CompilerTestingCommons true ) - if(VersionContext.current.isV6SoftForkActivated) { + if(VersionContext.current.isV3OrLaterErgoTreeVersion) { holTest() } else { an[sigma.validation.ValidationException] shouldBe thrownBy(holTest()) @@ -3086,7 +3086,7 @@ class BasicOpsSpecification extends CompilerTestingCommons ) } - if (VersionContext.current.isV6SoftForkActivated) { + if (VersionContext.current.isV3OrLaterErgoTreeVersion) { getRegTest() } else { an[sigma.exceptions.ConstraintFailed] should be thrownBy getRegTest() @@ -3107,7 +3107,7 @@ class BasicOpsSpecification extends CompilerTestingCommons ) } - if (VersionContext.current.isV6SoftForkActivated) { + if (VersionContext.current.isV3OrLaterErgoTreeVersion) { getRegTest() } else { an[java.nio.BufferUnderflowException] should be thrownBy getRegTest() @@ -3150,7 +3150,7 @@ class BasicOpsSpecification extends CompilerTestingCommons ) } - if (VersionContext.current.isV6SoftForkActivated) { + if (VersionContext.current.isV3OrLaterErgoTreeVersion) { someTest() } else { an[sigma.validation.ValidationException] should be thrownBy someTest() @@ -3172,7 +3172,7 @@ class BasicOpsSpecification extends CompilerTestingCommons ) } - if (VersionContext.current.isV6SoftForkActivated) { + if (VersionContext.current.isV3OrLaterErgoTreeVersion) { someTest() } else { an[sigma.validation.ValidationException] should be thrownBy someTest() @@ -3194,7 +3194,7 @@ class BasicOpsSpecification extends CompilerTestingCommons ) } - if (VersionContext.current.isV6SoftForkActivated) { + if (VersionContext.current.isV3OrLaterErgoTreeVersion) { someTest() } else { an[sigma.validation.ValidationException] should be thrownBy someTest() @@ -3241,10 +3241,10 @@ class BasicOpsSpecification extends CompilerTestingCommons true ) - if (VersionContext.current.isV6SoftForkActivated) { + if (VersionContext.current.isV3OrLaterErgoTreeVersion) { deserTest() } else { - an[ValidationException] should be thrownBy deserTest() + an[Exception] should be thrownBy deserTest() } } @@ -3262,7 +3262,7 @@ class BasicOpsSpecification extends CompilerTestingCommons ) } - if (VersionContext.current.isV6SoftForkActivated) { + if (VersionContext.current.isV3OrLaterErgoTreeVersion) { someTest(okValue) // on JVM, InvocationTargetException wrapping (ArithmeticException: BigInteger out of 256 bit range) is thrown an[Exception] should be thrownBy someTest(invalidValue) diff --git a/sdk/shared/src/test/scala/org/ergoplatform/sdk/DataJsonEncoderSpecification.scala b/sdk/shared/src/test/scala/org/ergoplatform/sdk/DataJsonEncoderSpecification.scala index 7e73b6c93d..27427245a4 100644 --- a/sdk/shared/src/test/scala/org/ergoplatform/sdk/DataJsonEncoderSpecification.scala +++ b/sdk/shared/src/test/scala/org/ergoplatform/sdk/DataJsonEncoderSpecification.scala @@ -31,7 +31,7 @@ class DataJsonEncoderSpecification extends SerializationSpecification { withVersion match { case Some(ver) => - VersionContext.withVersions(ver, 0) { + VersionContext.withVersions(ver, ver) { test() } case None =>