From 6241e86923a252d918d68495128d542f80e2b682 Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Mon, 6 Nov 2023 14:39:38 +0300 Subject: [PATCH 001/314] 6.0.0 version set in readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 64f08f0277..6b8429a82f 100644 --- a/README.md +++ b/README.md @@ -93,7 +93,7 @@ This library is on Maven repository and can be added to the SBT configuration of Scala project. ```scala -libraryDependencies += "org.scorexfoundation" %% "sigma-state" % "5.0.6" +libraryDependencies += "org.scorexfoundation" %% "sigma-state" % "6.0.0" ``` ## Repository Organization From 727ed8d655d8c3af5b7ec11cc6208691446cf037 Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Wed, 22 Nov 2023 14:07:46 +0300 Subject: [PATCH 002/314] evolution version --- core/shared/src/main/scala/sigma/VersionContext.scala | 2 ++ 1 file changed, 2 insertions(+) diff --git a/core/shared/src/main/scala/sigma/VersionContext.scala b/core/shared/src/main/scala/sigma/VersionContext.scala index 14e6dc8b21..18a1d8bccb 100644 --- a/core/shared/src/main/scala/sigma/VersionContext.scala +++ b/core/shared/src/main/scala/sigma/VersionContext.scala @@ -40,6 +40,8 @@ object VersionContext { */ val JitActivationVersion: Byte = 2 + val ExtensionVersion: Byte = 3 + private val _defaultContext = VersionContext( activatedVersion = 1/* v4.x */, ergoTreeVersion = 1 From 048add38745767a49978b55015dd6daf62e7fdff Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Wed, 22 Nov 2023 14:11:34 +0300 Subject: [PATCH 003/314] comments fixed --- core/shared/src/main/scala/sigma/VersionContext.scala | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/core/shared/src/main/scala/sigma/VersionContext.scala b/core/shared/src/main/scala/sigma/VersionContext.scala index 18a1d8bccb..4f1903a86c 100644 --- a/core/shared/src/main/scala/sigma/VersionContext.scala +++ b/core/shared/src/main/scala/sigma/VersionContext.scala @@ -31,6 +31,7 @@ object VersionContext { * - version 3.x this value must be 0 * - in v4.0 must be 1 * - in v5.x must be 2 + * - in 6.x must be 3 * etc. */ val MaxSupportedScriptVersion: Byte = 2 // supported versions 0, 1, 2 @@ -40,7 +41,10 @@ object VersionContext { */ val JitActivationVersion: Byte = 2 - val ExtensionVersion: Byte = 3 + /** + * The version of ErgoTree corresponding to "evolution" (6.0) soft-fork + */ + val EvolutionVersion: Byte = 3 private val _defaultContext = VersionContext( activatedVersion = 1/* v4.x */, From 9675b2a9fd2c3be7a2938be9066ba0ea333d5e05 Mon Sep 17 00:00:00 2001 From: Kamal Ahmad Date: Wed, 22 Nov 2023 09:43:42 +0500 Subject: [PATCH 004/314] [v6.0] Accumulate ErgoTree deserialization cost --- .../src/main/scala/sigma/VersionContext.scala | 2 +- .../sigmastate/interpreter/Interpreter.scala | 9 +- .../scala/sigma/SigmaDslSpecification.scala | 1847 +++++++++-------- .../test/scala/sigma/SigmaDslTesting.scala | 25 + 4 files changed, 1037 insertions(+), 846 deletions(-) diff --git a/core/shared/src/main/scala/sigma/VersionContext.scala b/core/shared/src/main/scala/sigma/VersionContext.scala index 4f1903a86c..1d9c29c225 100644 --- a/core/shared/src/main/scala/sigma/VersionContext.scala +++ b/core/shared/src/main/scala/sigma/VersionContext.scala @@ -34,7 +34,7 @@ object VersionContext { * - in 6.x must be 3 * etc. */ - val MaxSupportedScriptVersion: Byte = 2 // supported versions 0, 1, 2 + val MaxSupportedScriptVersion: Byte = 3 // supported versions 0, 1, 2, 3 /** The first version of ErgoTree starting from which the JIT costing interpreter must be used. * It must also be used for all subsequent versions (3, 4, etc). diff --git a/interpreter/shared/src/main/scala/sigmastate/interpreter/Interpreter.scala b/interpreter/shared/src/main/scala/sigmastate/interpreter/Interpreter.scala index cb519e12ae..061afde11b 100644 --- a/interpreter/shared/src/main/scala/sigmastate/interpreter/Interpreter.scala +++ b/interpreter/shared/src/main/scala/sigmastate/interpreter/Interpreter.scala @@ -244,7 +244,12 @@ trait Interpreter { val currCost = Evaluation.addCostChecked(context.initCost, deserializeSubstitutionCost, context.costLimit) val context1 = context.withInitCost(currCost).asInstanceOf[CTX] val (propTree, context2) = trySoftForkable[(SigmaPropValue, CTX)](whenSoftFork = (TrueSigmaProp, context1)) { - applyDeserializeContextJITC(context, prop) + // Before ErgoTree V3 the deserialization cost was not added to the total cost + applyDeserializeContextJITC(if (VersionContext.current.activatedVersion >= 3) { + context1 + } else { + context + }, prop) } // here we assume that when `propTree` is TrueProp then `reduceToCrypto` always succeeds @@ -593,4 +598,4 @@ object Interpreter { /** Helper method to throw errors from Interpreter. */ def error(msg: String) = throw new InterpreterException(msg) -} \ No newline at end of file +} diff --git a/sc/shared/src/test/scala/sigma/SigmaDslSpecification.scala b/sc/shared/src/test/scala/sigma/SigmaDslSpecification.scala index f5c47a055f..4124d6226f 100644 --- a/sc/shared/src/test/scala/sigma/SigmaDslSpecification.scala +++ b/sc/shared/src/test/scala/sigma/SigmaDslSpecification.scala @@ -268,7 +268,9 @@ class SigmaDslSpecification extends SigmaDslTesting ) ) val newCost = 1768 - def success(b: Boolean) = Expected(Success(b), 1768, newDetails, newCost) + + def success(b: Boolean) = Expected(Success(b), 1768, newDetails, newCost, 2010 +: Seq.fill(3)(2012)) + val cases = Seq( (true, true) -> success(false), (true, false) -> success(true), @@ -297,14 +299,14 @@ class SigmaDslSpecification extends SigmaDslTesting val expectedCost = 1768 val newCost = 1768 val cases = Seq( - (true, true) -> Expected(Success(false), expectedCost, newDetails, newCost) + (true, true) -> Expected(Success(false), expectedCost, newDetails, newCost, 2010 +: Seq.fill(3)(2012)) ) verifyCases(cases, feature) val initCost = 100 initialCostInTests.withValue(initCost) { val cases = Seq( - (true, true) -> Expected(Success(false), expectedCost + initCost, newDetails, newCost + initCost) + (true, true) -> Expected(Success(false), expectedCost + initCost, newDetails, newCost + initCost, (2010 + initCost) +: Seq.fill(3)(2012 + initCost)) ) verifyCases(cases, feature) } @@ -333,7 +335,9 @@ class SigmaDslSpecification extends SigmaDslTesting FixedCostItem(BinXor) ) ) - def success(b: Boolean) = Expected(Success(b), 1769, newDetails, 1769) + + def success(b: Boolean) = Expected(Success(b), 1769, newDetails, 1769, 2025 +: Seq.fill(3)(2027)) + val cases = Seq( (1095564593, true) -> success(true), (-901834021, true) -> success(true), @@ -370,10 +374,10 @@ class SigmaDslSpecification extends SigmaDslTesting ) ) val cases = Seq( - (false, true) -> Expected(Success(false), 1766, newDetails1, 1766), - (false, false) -> Expected(Success(false), 1766, newDetails1, 1766), - (true, true) -> Expected(Success(true), 1768, newDetails2, 1768), - (true, false) -> Expected(Success(false), 1768, newDetails2, 1768) + (false, true) -> Expected(Success(false), 1766, newDetails1, 1766, 2008 +: Seq.fill(3)(2010)), + (false, false) -> Expected(Success(false), 1766, newDetails1, 1766, 2008 +: Seq.fill(3)(2010)), + (true, true) -> Expected(Success(true), 1768, newDetails2, 1768, 2010 +: Seq.fill(3)(2012)), + (true, false) -> Expected(Success(false), 1768, newDetails2, 1768, 2010 +: Seq.fill(3)(2012)) ) verifyCases(cases, eq) } @@ -403,10 +407,10 @@ class SigmaDslSpecification extends SigmaDslTesting ) ) val cases = Seq( - (true, false) -> Expected(Success(true), 1766, newDetails1, 1766), - (true, true) -> Expected(Success(true), 1766, newDetails1, 1766), - (false, false) -> Expected(Success(false), 1768, newDetails2, 1768), - (false, true) -> Expected(Success(true), 1768, newDetails2, 1768) + (true, false) -> Expected(Success(true), 1766, newDetails1, 1766, 2008 +: Seq.fill(3)(2010)), + (true, true) -> Expected(Success(true), 1766, newDetails1, 1766, 2008 +: Seq.fill(3)(2010)), + (false, false) -> Expected(Success(false), 1768, newDetails2, 1768, 2010 +: Seq.fill(3)(2012)), + (false, true) -> Expected(Success(true), 1768, newDetails2, 1768, 2010 +: Seq.fill(3)(2012)) ) verifyCases(cases, eq) } @@ -451,7 +455,7 @@ class SigmaDslSpecification extends SigmaDslTesting ) verifyCases( Seq( - (true, Expected(Success(true), 1765, newDetails1, 1765)), + (true, Expected(Success(true), 1765, newDetails1, 1765, 2023 +: Seq.fill(3)(2027))), (false, Expected(new ArithmeticException("/ by zero"))) ), existingFeature((x: Boolean) => x || (1 / 0 == 1), @@ -467,7 +471,7 @@ class SigmaDslSpecification extends SigmaDslTesting verifyCases( Seq( (true, Expected(new ArithmeticException("/ by zero"))), - (false, Expected(Success(false), 1765, newDetails2, 1765)) + (false, Expected(Success(false), 1765, newDetails2, 1765, 2023 +: Seq.fill(3)(2027))) ), existingFeature((x: Boolean) => x && (1 / 0 == 1), "{ (x: Boolean) => x && (1 / 0 == 1) }", @@ -481,8 +485,8 @@ class SigmaDslSpecification extends SigmaDslTesting verifyCases( Seq( - (false, Expected(Success(false), 1765, newDetails2, 1765)), - (true, Expected(Success(true), 1768, newDetails3, 1768)) + (false, Expected(Success(false), 1765, newDetails2, 1765, 2029 +: Seq.fill(3)(2033))), + (true, Expected(Success(true), 1768, newDetails3, 1768, 2032 +: Seq.fill(3)(2036))) ), existingFeature((x: Boolean) => x && (x || (1 / 0 == 1)), "{ (x: Boolean) => x && (x || (1 / 0 == 1)) }", @@ -499,8 +503,8 @@ class SigmaDslSpecification extends SigmaDslTesting verifyCases( Seq( - (false, Expected(Success(false), 1765, newDetails2, 1765)), - (true, Expected(Success(true), 1770, newDetails4, 1770)) + (false, Expected(Success(false), 1765, newDetails2, 1765, 2035 +: Seq.fill(3)(2039))), + (true, Expected(Success(true), 1770, newDetails4, 1770, 2040 +: Seq.fill(3)(2044))) ), existingFeature((x: Boolean) => x && (x && (x || (1 / 0 == 1))), "{ (x: Boolean) => x && (x && (x || (1 / 0 == 1))) }", @@ -520,8 +524,8 @@ class SigmaDslSpecification extends SigmaDslTesting verifyCases( Seq( - (false, Expected(Success(false), 1765, newDetails2, 1765)), - (true, Expected(Success(true), 1773, newDetails5, 1773)) + (false, Expected(Success(false), 1765, newDetails2, 1765, 2041 +: Seq.fill(3)(2045))), + (true, Expected(Success(true), 1773, newDetails5, 1773, 2049 +: Seq.fill(3)(2053))) ), existingFeature((x: Boolean) => x && (x && (x && (x || (1 / 0 == 1)))), "{ (x: Boolean) => x && (x && (x && (x || (1 / 0 == 1)))) }", @@ -555,7 +559,7 @@ class SigmaDslSpecification extends SigmaDslTesting verifyCases( Seq( (false, Expected(new ArithmeticException("/ by zero"))), - (true, Expected(Success(true), 1773, newDetails6, 1773)) + (true, Expected(Success(true), 1773, newDetails6, 1773, 2071 +: Seq.fill(3)(2075))) ), existingFeature((x: Boolean) => !(!x && (1 / 0 == 1)) && (x || (1 / 0 == 1)), "{ (x: Boolean) => !(!x && (1 / 0 == 1)) && (x || (1 / 0 == 1)) }", @@ -584,7 +588,7 @@ class SigmaDslSpecification extends SigmaDslTesting ) verifyCases( Seq( - (true, Expected(Success(true), 1768, newDetails7, 1768)), + (true, Expected(Success(true), 1768, newDetails7, 1768, 2032 +: Seq.fill(3)(2036))), (false, Expected(new ArithmeticException("/ by zero"))) ), existingFeature((x: Boolean) => (x || (1 / 0 == 1)) && x, @@ -610,7 +614,7 @@ class SigmaDslSpecification extends SigmaDslTesting ) verifyCases( Seq( - (true, Expected(Success(true), 1770, newDetails8, 1770)), + (true, Expected(Success(true), 1770, newDetails8, 1770, 2064 +: Seq.fill(3)(2068))), (false, Expected(new ArithmeticException("/ by zero"))) ), existingFeature((x: Boolean) => (x || (1 / 0 == 1)) && (x || (1 / 0 == 1)), @@ -642,7 +646,7 @@ class SigmaDslSpecification extends SigmaDslTesting ) verifyCases( Seq( - (true, Expected(Success(true), 1775, newDetails9, 1775)), + (true, Expected(Success(true), 1775, newDetails9, 1775, 2103 +: Seq.fill(3)(2107))), (false, Expected(new ArithmeticException("/ by zero"))) ), existingFeature( @@ -692,7 +696,7 @@ class SigmaDslSpecification extends SigmaDslTesting verifyCases( Seq( (false, Expected(new ArithmeticException("/ by zero"))), - (true, Expected(Success(true), 1780, newDetails10, 1780)) + (true, Expected(Success(true), 1780, newDetails10, 1780, 2152 +: Seq.fill(3)(2156))) ), existingFeature( (x: Boolean) => (!(!x && (1 / 0 == 1)) || (1 / 0 == 0)) && (!(!x && (1 / 0 == 1)) || (1 / 0 == 1)), @@ -735,7 +739,8 @@ class SigmaDslSpecification extends SigmaDslTesting verifyCases( { - def expect(v: Byte) = Expected(Success(v), 1763, TracedCost(traceBase), 1763) + def expect(v: Byte) = Expected(Success(v), 1763, TracedCost(traceBase), 1763, 1991 +: Seq.fill(3)(1993)) + Seq( (0.toByte, expect(0.toByte)), (1.toByte, expect(1.toByte)), @@ -752,7 +757,8 @@ class SigmaDslSpecification extends SigmaDslTesting verifyCases( { - def expected(v: Short) = Expected(Success(v), 1764, upcastCostDetails(SShort), 1764) + def expected(v: Short) = Expected(Success(v), 1764, upcastCostDetails(SShort), 1764, 1996 +: Seq.fill(3)(1998)) + Seq( (0.toByte, expected(0.toShort)), (1.toByte, expected(1.toShort)), @@ -769,7 +775,8 @@ class SigmaDslSpecification extends SigmaDslTesting verifyCases( { - def expected(v: Int) = Expected(Success(v), 1764, upcastCostDetails(SInt), 1764) + def expected(v: Int) = Expected(Success(v), 1764, upcastCostDetails(SInt), 1764, 1996 +: Seq.fill(3)(1998)) + Seq( (0.toByte, expected(0)), (1.toByte, expected(1)), @@ -786,7 +793,8 @@ class SigmaDslSpecification extends SigmaDslTesting verifyCases( { - def expected(v: Long) = Expected(Success(v), 1764, upcastCostDetails(SLong), 1764) + def expected(v: Long) = Expected(Success(v), 1764, upcastCostDetails(SLong), 1764, 1996 +: Seq.fill(3)(1998)) + Seq( (0.toByte, expected(0L)), (1.toByte, expected(1L)), @@ -803,7 +811,8 @@ class SigmaDslSpecification extends SigmaDslTesting verifyCases( { - def expected(v: BigInt) = Expected(Success(v), 1767, upcastCostDetails(SBigInt), 1767) + def expected(v: BigInt) = Expected(Success(v), 1767, upcastCostDetails(SBigInt), 1767, 1999 +: Seq.fill(3)(2001)) + Seq( (0.toByte, expected(CBigInt(new BigInteger("0", 16)))), (1.toByte, expected(CBigInt(new BigInteger("1", 16)))), @@ -821,7 +830,8 @@ class SigmaDslSpecification extends SigmaDslTesting val n = ExactIntegral.ByteIsExactIntegral verifyCases( { - def success[T](v: (T, (T, (T, (T, T))))) = Expected(Success(v), 1788, arithOpsCostDetails(SByte), 1788) + def success[T](v: (T, (T, (T, (T, T))))) = Expected(Success(v), 1788, arithOpsCostDetails(SByte), 1788, 2112 +: Seq.fill(3)(2116)) + Seq( ((-128.toByte, -128.toByte), Expected(new ArithmeticException("Byte overflow"))), ((-128.toByte, 0.toByte), Expected(new ArithmeticException("/ by zero"))), @@ -920,6 +930,12 @@ class SigmaDslSpecification extends SigmaDslTesting ((y, x), Expected(res.value, cost, newCostDetails, cost)) } + def swapArgs[A](cases: Seq[((A, A), Expected[Boolean])], cost: Int, newCostDetails: CostDetails, + expectedV3Costs: Seq[Int]) = + cases.map { case ((x, y), res) => + ((y, x), Expected(res.value, cost, newCostDetails, cost, expectedV3Costs)) + } + def newCasesFrom[A, R]( cases: Seq[(A, A)] )( @@ -938,12 +954,19 @@ class SigmaDslSpecification extends SigmaDslTesting ((x, y), Expected(Success(getExpectedRes(x, y)), cost = cost, expectedDetails = newCostDetails, expectedNewCost = cost)) } - def verifyOp[A: Ordering: Arbitrary] - (cases: Seq[((A, A), Expected[Boolean])], - opName: String, - op: (SValue, SValue) => SValue) - (expectedFunc: (A, A) => Boolean, generateCases: Boolean = true) - (implicit tA: RType[A], sampled: Sampled[(A, A)], evalSettings: EvalSettings) = { + def newCasesFrom3[A, R](cases: Seq[(A, A)]) + (getExpectedRes: (A, A) => R, cost: Int, newCostDetails: CostDetails, + expectedV3Costs: Seq[Int]) = + cases.map { case (x, y) => + ((x, y), Expected(Success(getExpectedRes(x, y)), cost = cost, expectedDetails = newCostDetails, expectedNewCost = cost, expectedV3Costs)) + } + + def verifyOp[A: Ordering : Arbitrary] + (cases: Seq[((A, A), Expected[Boolean])], + opName: String, + op: (SValue, SValue) => SValue) + (expectedFunc: (A, A) => Boolean, generateCases: Boolean = true) + (implicit tA: RType[A], sampled: Sampled[(A, A)], evalSettings: EvalSettings) = { val nameA = RType[A].name val tpeA = Evaluation.rtypeToSType(tA) verifyCases(cases, @@ -968,7 +991,9 @@ class SigmaDslSpecification extends SigmaDslTesting property("Byte LT, GT, NEQ") { val o = ExactOrdering.ByteIsExactOrdering - def expect(v: Boolean) = Expected(Success(v), 1768, binaryRelationCostDetails(LT, SByte), 1768) + + def expect(v: Boolean) = Expected(Success(v), 1768, binaryRelationCostDetails(LT, SByte), 1768, 2010 +: Seq.fill(3)(2012)) + val LT_cases: Seq[((Byte, Byte), Expected[Boolean])] = Seq( (-128.toByte, -128.toByte) -> expect(false), (-128.toByte, -127.toByte) -> expect(true), @@ -1009,16 +1034,18 @@ class SigmaDslSpecification extends SigmaDslTesting verifyOp(LT_cases, "<", LT.apply)(_ < _) verifyOp( - swapArgs(LT_cases, cost = 1768, newCostDetails = binaryRelationCostDetails(GT, SByte)), + swapArgs(LT_cases, cost = 1768, newCostDetails = binaryRelationCostDetails(GT, SByte), expectedV3Costs = 2010 +: Seq.fill(3)(2012)), ">", GT.apply)(_ > _) - val neqCases = newCasesFrom2(LT_cases.map(_._1))(_ != _, cost = 1766, newCostDetails = costNEQ(constNeqCost)) + val neqCases = newCasesFrom3(LT_cases.map(_._1))(_ != _, cost = 1766, newCostDetails = costNEQ(constNeqCost), expectedV3Costs = 2008 +: Seq.fill(3)(2010)) verifyOp(neqCases, "!=", NEQ.apply)(_ != _) } property("Byte LE, GE") { val o = ExactOrdering.ByteIsExactOrdering - def expect(v: Boolean) = Expected(Success(v), 1768, binaryRelationCostDetails(LE, SByte), 1768) + + def expect(v: Boolean) = Expected(Success(v), 1768, binaryRelationCostDetails(LE, SByte), 1768, 2010 +: Seq.fill(3)(2012)) + val LE_cases: Seq[((Byte, Byte), Expected[Boolean])] = Seq( (-128.toByte, -128.toByte) -> expect(true), (-128.toByte, -127.toByte) -> expect(true), @@ -1060,7 +1087,7 @@ class SigmaDslSpecification extends SigmaDslTesting verifyOp(LE_cases, "<=", LE.apply)(_ <= _) verifyOp( - swapArgs(LE_cases, cost = 1768, newCostDetails = binaryRelationCostDetails(GE, SByte)), + swapArgs(LE_cases, cost = 1768, newCostDetails = binaryRelationCostDetails(GE, SByte), expectedV3Costs = 2010 +: Seq.fill(3)(2012)), ">=", GE.apply)(_ >= _) } @@ -1095,7 +1122,8 @@ class SigmaDslSpecification extends SigmaDslTesting verifyCases( { - def success[T](v: T) = Expected(Success(v), 1764, downcastCostDetails(SByte), 1764) + def success[T](v: T) = Expected(Success(v), 1764, downcastCostDetails(SByte), 1764, 1996 +: Seq.fill(3)(1998)) + Seq( (Short.MinValue, Expected(new ArithmeticException("Byte overflow"))), (-21626.toShort, Expected(new ArithmeticException("Byte overflow"))), @@ -1114,7 +1142,8 @@ class SigmaDslSpecification extends SigmaDslTesting verifyCases( { - def success[T](v: T) = Expected(Success(v), 1763, TracedCost(traceBase), 1763) + def success[T](v: T) = Expected(Success(v), 1763, TracedCost(traceBase), 1763, 1991 +: Seq.fill(3)(1993)) + Seq( (-32768.toShort, success(-32768.toShort)), (-27798.toShort, success(-27798.toShort)), @@ -1131,7 +1160,8 @@ class SigmaDslSpecification extends SigmaDslTesting verifyCases( { - def success[T](v: T) = Expected(Success(v), 1764, upcastCostDetails(SInt), 1764) + def success[T](v: T) = Expected(Success(v), 1764, upcastCostDetails(SInt), 1764, 1996 +: Seq.fill(3)(1998)) + Seq( (-32768.toShort, success(-32768)), (-21064.toShort, success(-21064)), @@ -1148,7 +1178,8 @@ class SigmaDslSpecification extends SigmaDslTesting verifyCases( { - def success[T](v: T) = Expected(Success(v), 1764, upcastCostDetails(SLong), 1764) + def success[T](v: T) = Expected(Success(v), 1764, upcastCostDetails(SLong), 1764, 1996 +: Seq.fill(3)(1998)) + Seq( (-32768.toShort, success(-32768L)), (-23408.toShort, success(-23408L)), @@ -1165,7 +1196,8 @@ class SigmaDslSpecification extends SigmaDslTesting verifyCases( { - def success(v: BigInt) = Expected(Success(v), 1767, upcastCostDetails(SBigInt), 1767) + def success(v: BigInt) = Expected(Success(v), 1767, upcastCostDetails(SBigInt), 1767, 1999 +: Seq.fill(3)(2001)) + Seq( (-32768.toShort, success(CBigInt(new BigInteger("-8000", 16)))), (-26248.toShort, success(CBigInt(new BigInteger("-6688", 16)))), @@ -1183,7 +1215,8 @@ class SigmaDslSpecification extends SigmaDslTesting val n = ExactIntegral.ShortIsExactIntegral verifyCases( { - def success[T](v: T) = Expected(Success(v), 1788, arithOpsCostDetails(SShort), 1788) + def success[T](v: T) = Expected(Success(v), 1788, arithOpsCostDetails(SShort), 1788, 2112 +: Seq.fill(3)(2116)) + Seq( ((-32768.toShort, 1.toShort), Expected(new ArithmeticException("Short overflow"))), ((-32768.toShort, 4006.toShort), Expected(new ArithmeticException("Short overflow"))), @@ -1275,7 +1308,9 @@ class SigmaDslSpecification extends SigmaDslTesting property("Short LT, GT, NEQ") { val o = ExactOrdering.ShortIsExactOrdering - def expect(v: Boolean) = Expected(Success(v), 1768, binaryRelationCostDetails(LT, SShort), 1768) + + def expect(v: Boolean) = Expected(Success(v), 1768, binaryRelationCostDetails(LT, SShort), 1768, 2010 +: Seq.fill(3)(2012)) + val LT_cases: Seq[((Short, Short), Expected[Boolean])] = Seq( (Short.MinValue, Short.MinValue) -> expect(false), (Short.MinValue, (Short.MinValue + 1).toShort) -> expect(true), @@ -1315,15 +1350,17 @@ class SigmaDslSpecification extends SigmaDslTesting verifyOp(LT_cases, "<", LT.apply)(_ < _) - verifyOp(swapArgs(LT_cases, cost = 1768, newCostDetails = binaryRelationCostDetails(GT, SShort)), ">", GT.apply)(_ > _) + verifyOp(swapArgs(LT_cases, cost = 1768, newCostDetails = binaryRelationCostDetails(GT, SShort), expectedV3Costs = 2010 +: Seq.fill(3)(2012)), ">", GT.apply)(_ > _) - val neqCases = newCasesFrom2(LT_cases.map(_._1))(_ != _, cost = 1766, newCostDetails = costNEQ(constNeqCost)) + val neqCases = newCasesFrom3(LT_cases.map(_._1))(_ != _, cost = 1766, newCostDetails = costNEQ(constNeqCost), expectedV3Costs = 2008 +: Seq.fill(3)(2010)) verifyOp(neqCases, "!=", NEQ.apply)(_ != _) } property("Short LE, GE") { val o = ExactOrdering.ShortIsExactOrdering - def expect(v: Boolean) = Expected(Success(v), 1768, binaryRelationCostDetails(LE, SShort), 1768) + + def expect(v: Boolean) = Expected(Success(v), 1768, binaryRelationCostDetails(LE, SShort), 1768, 2010 +: Seq.fill(3)(2012)) + val LE_cases: Seq[((Short, Short), Expected[Boolean])] = Seq( (Short.MinValue, Short.MinValue) -> expect(true), (Short.MinValue, (Short.MinValue + 1).toShort) -> expect(true), @@ -1365,7 +1402,7 @@ class SigmaDslSpecification extends SigmaDslTesting verifyOp(LE_cases, "<=", LE.apply)(_ <= _) verifyOp( - swapArgs(LE_cases, cost = 1768, newCostDetails = binaryRelationCostDetails(GE, SShort)), + swapArgs(LE_cases, cost = 1768, newCostDetails = binaryRelationCostDetails(GE, SShort), expectedV3Costs = 2010 +: Seq.fill(3)(2012)), ">=", GE.apply)(_ >= _) } @@ -1399,7 +1436,8 @@ class SigmaDslSpecification extends SigmaDslTesting verifyCases( { - def success[T](v: T) = Expected(Success(v), 1764, downcastCostDetails(SByte), 1764) + def success[T](v: T) = Expected(Success(v), 1764, downcastCostDetails(SByte), 1764, 1996 +: Seq.fill(3)(1998)) + Seq( (Int.MinValue, Expected(new ArithmeticException("Byte overflow"))), (-2014394379, Expected(new ArithmeticException("Byte overflow"))), @@ -1418,7 +1456,8 @@ class SigmaDslSpecification extends SigmaDslTesting verifyCases( { - def success[T](v: T) = Expected(Success(v), 1764, downcastCostDetails(SShort), 1764) + def success[T](v: T) = Expected(Success(v), 1764, downcastCostDetails(SShort), 1764, 1996 +: Seq.fill(3)(1998)) + Seq( (Int.MinValue, Expected(new ArithmeticException("Short overflow"))), (Short.MinValue - 1, Expected(new ArithmeticException("Short overflow"))), @@ -1437,7 +1476,8 @@ class SigmaDslSpecification extends SigmaDslTesting verifyCases( { - def success[T](v: T) = Expected(Success(v), 1763, TracedCost(traceBase), 1763) + def success[T](v: T) = Expected(Success(v), 1763, TracedCost(traceBase), 1763, 1991 +: Seq.fill(3)(1993)) + Seq( (Int.MinValue, success(Int.MinValue)), (-1, success(-1)), @@ -1452,7 +1492,8 @@ class SigmaDslSpecification extends SigmaDslTesting verifyCases( { - def success[T](v: T) = Expected(Success(v), 1764, upcastCostDetails(SLong), 1764) + def success[T](v: T) = Expected(Success(v), 1764, upcastCostDetails(SLong), 1764, 1996 +: Seq.fill(3)(1998)) + Seq( (Int.MinValue, success(Int.MinValue.toLong)), (-1, success(-1L)), @@ -1467,7 +1508,8 @@ class SigmaDslSpecification extends SigmaDslTesting verifyCases( { - def success(v: BigInt) = Expected(Success(v), 1767, upcastCostDetails(SBigInt), 1767) + def success(v: BigInt) = Expected(Success(v), 1767, upcastCostDetails(SBigInt), 1767, 1999 +: Seq.fill(3)(2001)) + Seq( (Int.MinValue, success(CBigInt(new BigInteger("-80000000", 16)))), (-1937187314, success(CBigInt(new BigInteger("-737721f2", 16)))), @@ -1484,57 +1526,59 @@ class SigmaDslSpecification extends SigmaDslTesting val n = ExactNumeric.IntIsExactNumeric verifyCases( - { - def success[T](v: T) = Expected(Success(v), 1788, arithOpsCostDetails(SInt), 1788) - Seq( - ((Int.MinValue, 449583993), Expected(new ArithmeticException("integer overflow"))), - ((-1589633733, 2147483647), Expected(new ArithmeticException("integer overflow"))), - ((-1585471506, -1), success((-1585471507, (-1585471505, (1585471506, (1585471506, 0)))))), - ((-1569005179, 1230236634), Expected(new ArithmeticException("integer overflow"))), - ((-1493733356, -1319619597), Expected(new ArithmeticException("integer overflow"))), - ((-1100263120, -880052091), Expected(new ArithmeticException("integer overflow"))), - ((-1055955857, 309147303), Expected(new ArithmeticException("integer overflow"))), - ((-569807371, 0), Expected(new ArithmeticException("/ by zero"))), - ((-522264843, 2147483647), Expected(new ArithmeticException("integer overflow"))), - ((-109552389, 0), Expected(new ArithmeticException("/ by zero"))), - ((-1, -2147483648), Expected(new ArithmeticException("integer overflow"))), - ((-1, -1), success((-2, (0, (1, (1, 0)))))), - ((-1, 0), Expected(new ArithmeticException("/ by zero"))), - ((0, -2147483648), Expected(new ArithmeticException("integer overflow"))), - ((1, -1525049432), success((-1525049431, (1525049433, (-1525049432, (0, 1)))))), - ((1, 0), Expected(new ArithmeticException("/ by zero"))), - ((1, 805353746), success((805353747, (-805353745, (805353746, (0, 1)))))), - ((1, 2147483647), Expected(new ArithmeticException("integer overflow"))), - ((475797978, 0), Expected(new ArithmeticException("/ by zero"))), - ((782343922, -1448560539), Expected(new ArithmeticException("integer overflow"))), - ((928769361, 542647292), Expected(new ArithmeticException("integer overflow"))), - ((1568062151, 0), Expected(new ArithmeticException("/ by zero"))), - ((1698252401, -1), success((1698252400, (1698252402, (-1698252401, (-1698252401, 0)))))), - ((1949795740, -1575667037), Expected(new ArithmeticException("integer overflow"))), - ((Int.MaxValue, -1), Expected(new ArithmeticException("integer overflow"))), - ((Int.MaxValue, 1), Expected(new ArithmeticException("integer overflow"))), - ((Int.MaxValue, 1738276576), Expected(new ArithmeticException("integer overflow"))) - ) - }, - existingFeature( - { (x: (Int, Int)) => - val a = x._1; val b = x._2 - val plus = n.plus(a, b) - val minus = n.minus(a, b) - val mul = n.times(a, b) - val div = a / b - val mod = a % b - (plus, (minus, (mul, (div, mod)))) + { + def success[T](v: T) = Expected(Success(v), 1788, arithOpsCostDetails(SInt), 1788, 2112 +: Seq.fill(3)(2116)) + + Seq( + ((Int.MinValue, 449583993), Expected(new ArithmeticException("integer overflow"))), + ((-1589633733, 2147483647), Expected(new ArithmeticException("integer overflow"))), + ((-1585471506, -1), success((-1585471507, (-1585471505, (1585471506, (1585471506, 0)))))), + ((-1569005179, 1230236634), Expected(new ArithmeticException("integer overflow"))), + ((-1493733356, -1319619597), Expected(new ArithmeticException("integer overflow"))), + ((-1100263120, -880052091), Expected(new ArithmeticException("integer overflow"))), + ((-1055955857, 309147303), Expected(new ArithmeticException("integer overflow"))), + ((-569807371, 0), Expected(new ArithmeticException("/ by zero"))), + ((-522264843, 2147483647), Expected(new ArithmeticException("integer overflow"))), + ((-109552389, 0), Expected(new ArithmeticException("/ by zero"))), + ((-1, -2147483648), Expected(new ArithmeticException("integer overflow"))), + ((-1, -1), success((-2, (0, (1, (1, 0)))))), + ((-1, 0), Expected(new ArithmeticException("/ by zero"))), + ((0, -2147483648), Expected(new ArithmeticException("integer overflow"))), + ((1, -1525049432), success((-1525049431, (1525049433, (-1525049432, (0, 1)))))), + ((1, 0), Expected(new ArithmeticException("/ by zero"))), + ((1, 805353746), success((805353747, (-805353745, (805353746, (0, 1)))))), + ((1, 2147483647), Expected(new ArithmeticException("integer overflow"))), + ((475797978, 0), Expected(new ArithmeticException("/ by zero"))), + ((782343922, -1448560539), Expected(new ArithmeticException("integer overflow"))), + ((928769361, 542647292), Expected(new ArithmeticException("integer overflow"))), + ((1568062151, 0), Expected(new ArithmeticException("/ by zero"))), + ((1698252401, -1), success((1698252400, (1698252402, (-1698252401, (-1698252401, 0)))))), + ((1949795740, -1575667037), Expected(new ArithmeticException("integer overflow"))), + ((Int.MaxValue, -1), Expected(new ArithmeticException("integer overflow"))), + ((Int.MaxValue, 1), Expected(new ArithmeticException("integer overflow"))), + ((Int.MaxValue, 1738276576), Expected(new ArithmeticException("integer overflow"))) + ) }, - """{ (x: (Int, Int)) => - | val a = x._1; val b = x._2 - | val plus = a + b - | val minus = a - b - | val mul = a * b - | val div = a / b - | val mod = a % b - | (plus, (minus, (mul, (div, mod)))) - |}""".stripMargin, + existingFeature( + { (x: (Int, Int)) => + val a = x._1; + val b = x._2 + val plus = n.plus(a, b) + val minus = n.minus(a, b) + val mul = n.times(a, b) + val div = a / b + val mod = a % b + (plus, (minus, (mul, (div, mod)))) + }, + """{ (x: (Int, Int)) => + | val a = x._1; val b = x._2 + | val plus = a + b + | val minus = a - b + | val mul = a * b + | val div = a / b + | val mod = a % b + | (plus, (minus, (mul, (div, mod)))) + |}""".stripMargin, FuncValue( Vector((1, STuple(Vector(SInt, SInt)))), BlockValue( @@ -1577,7 +1621,7 @@ class SigmaDslSpecification extends SigmaDslTesting property("Int LT, GT, NEQ") { val o = ExactOrdering.IntIsExactOrdering - def expect(v: Boolean) = Expected(Success(v), 1768, binaryRelationCostDetails(LT, SInt), 1768) + def expect(v: Boolean) = Expected(Success(v), 1768, binaryRelationCostDetails(LT, SInt), 1768, 2010 +: Seq.fill(3)(2012)) val LT_cases: Seq[((Int, Int), Expected[Boolean])] = Seq( (Int.MinValue, Int.MinValue) -> expect(false), (Int.MinValue, (Int.MinValue + 1).toInt) -> expect(true), @@ -1618,16 +1662,16 @@ class SigmaDslSpecification extends SigmaDslTesting verifyOp(LT_cases, "<", LT.apply)(_ < _) verifyOp( - swapArgs(LT_cases, cost = 1768, newCostDetails = binaryRelationCostDetails(GT, SInt)), + swapArgs(LT_cases, cost = 1768, newCostDetails = binaryRelationCostDetails(GT, SInt), expectedV3Costs = 2010 +: Seq.fill(3)(2012)), ">", GT.apply)(_ > _) - val neqCases = newCasesFrom2(LT_cases.map(_._1))(_ != _, cost = 1766, newCostDetails = costNEQ(constNeqCost)) + val neqCases = newCasesFrom3(LT_cases.map(_._1))(_ != _, cost = 1766, newCostDetails = costNEQ(constNeqCost), expectedV3Costs = 2008 +: Seq.fill(3)(2010)) verifyOp(neqCases, "!=", NEQ.apply)(_ != _) } property("Int LE, GE") { val o = ExactOrdering.IntIsExactOrdering - def expect(v: Boolean) = Expected(Success(v), 1768, binaryRelationCostDetails(LE, SInt), 1768) + def expect(v: Boolean) = Expected(Success(v), 1768, binaryRelationCostDetails(LE, SInt), 1768, 2010 +: Seq.fill(3)(2012)) val LE_cases: Seq[((Int, Int), Expected[Boolean])] = Seq( (Int.MinValue, Int.MinValue) -> expect(true), (Int.MinValue, (Int.MinValue + 1).toInt) -> expect(true), @@ -1669,7 +1713,7 @@ class SigmaDslSpecification extends SigmaDslTesting verifyOp(LE_cases, "<=", LE.apply)(_ <= _) verifyOp( - swapArgs(LE_cases, cost = 1768, newCostDetails = binaryRelationCostDetails(GE, SInt)), + swapArgs(LE_cases, cost = 1768, newCostDetails = binaryRelationCostDetails(GE, SInt), expectedV3Costs = 2010 +: Seq.fill(3)(2012)), ">=", GE.apply)(_ >= _) } @@ -1706,7 +1750,7 @@ class SigmaDslSpecification extends SigmaDslTesting property("Long.toByte method") { verifyCases( { - def success[T](v: T) = Expected(Success(v), 1764, downcastCostDetails(SByte), 1764) + def success[T](v: T) = Expected(Success(v), 1764, downcastCostDetails(SByte), 1764, 1996 +: Seq.fill(3)(1998)) Seq( (Long.MinValue, Expected(new ArithmeticException("Byte overflow"))), (Byte.MinValue.toLong - 1, Expected(new ArithmeticException("Byte overflow"))), @@ -1727,7 +1771,7 @@ class SigmaDslSpecification extends SigmaDslTesting property("Long.toShort method") { verifyCases( { - def success[T](v: T) = Expected(Success(v), 1764, downcastCostDetails(SShort), 1764) + def success[T](v: T) = Expected(Success(v), 1764, downcastCostDetails(SShort), 1764, 1996 +: Seq.fill(3)(1998)) Seq( (Long.MinValue, Expected(new ArithmeticException("Short overflow"))), (Short.MinValue.toLong - 1, Expected(new ArithmeticException("Short overflow"))), @@ -1748,7 +1792,8 @@ class SigmaDslSpecification extends SigmaDslTesting property("Long.toInt method") { verifyCases( { - def success[T](v: T) = Expected(Success(v), 1764, downcastCostDetails(SInt), 1764) + def success[T](v: T) = Expected(Success(v), 1764, downcastCostDetails(SInt), 1764, 1996 +: Seq.fill(3)(1998)) + Seq( (Long.MinValue, Expected(new ArithmeticException("Int overflow"))), (Int.MinValue.toLong - 1, Expected(new ArithmeticException("Int overflow"))), @@ -1769,7 +1814,7 @@ class SigmaDslSpecification extends SigmaDslTesting property("Long.toLong method") { verifyCases( { - def success[T](v: T) = Expected(Success(v), 1763, TracedCost(traceBase), 1763) + def success[T](v: T) = Expected(Success(v), 1763, TracedCost(traceBase), 1763, 1991 +: Seq.fill(3)(1993)) Seq( (Long.MinValue, success(Long.MinValue)), (-1L, success(-1L)), @@ -1786,7 +1831,7 @@ class SigmaDslSpecification extends SigmaDslTesting property("Long.toBigInt method") { verifyCases( { - def success(v: BigInt) = Expected(Success(v), 1767, upcastCostDetails(SBigInt), 1767) + def success(v: BigInt) = Expected(Success(v), 1767, upcastCostDetails(SBigInt), 1767, 1999 +: Seq.fill(3)(2001)) Seq( (Long.MinValue, success(CBigInt(new BigInteger("-8000000000000000", 16)))), (-1074651039980347209L, success(CBigInt(new BigInteger("-ee9ed6d57885f49", 16)))), @@ -1806,83 +1851,85 @@ class SigmaDslSpecification extends SigmaDslTesting val n = ExactNumeric.LongIsExactNumeric verifyCases( - { - def success[T](v: T) = Expected(Success(v), 1788, arithOpsCostDetails(SLong), 1788) - Seq( - ((Long.MinValue, -4677100190307931395L), Expected(new ArithmeticException("long overflow"))), - ((Long.MinValue, -1L), Expected(new ArithmeticException("long overflow"))), - ((Long.MinValue, 1L), Expected(new ArithmeticException("long overflow"))), - ((-9223372036854775808L, 0L), Expected(new ArithmeticException("/ by zero"))), - ((-5828066432064138816L, 9105034716270510411L), Expected(new ArithmeticException("long overflow"))), - ((-4564956247298949325L, -1L), success( - (-4564956247298949326L, (-4564956247298949324L, (4564956247298949325L, (4564956247298949325L, 0L)))) - )), - ((-1499553565058783253L, -3237683216870282569L), Expected(new ArithmeticException("long overflow"))), - ((-1368457031689886112L, 9223372036854775807L), Expected(new ArithmeticException("long overflow"))), - ((-1L, -4354407074688367443L), success((-4354407074688367444L, (4354407074688367442L, (4354407074688367443L, (0L, -1L)))))), - ((-1L, -1L), success((-2L, (0L, (1L, (1L, 0L)))))), - ((-1L, 5665019549505434695L), success((5665019549505434694L, (-5665019549505434696L, (-5665019549505434695L, (0L, -1L)))))), - ((0L, -1L), success((-1L, (1L, (0L, (0L, 0L)))))), - ((0L, 0L), Expected(new ArithmeticException("/ by zero"))), - ((0L, 2112386634269044172L), success((2112386634269044172L, (-2112386634269044172L, (0L, (0L, 0L)))))), - ((2254604056782701370L, -5878231674026236574L), Expected(new ArithmeticException("long overflow"))), - ((2903872550238813643L, 1L), success( - (2903872550238813644L, (2903872550238813642L, (2903872550238813643L, (2903872550238813643L, 0L)))) - )), - ((5091129735284641762L, -427673944382373638L), Expected(new ArithmeticException("long overflow"))), - ((6029085020194630780L, 2261786144956037939L), Expected(new ArithmeticException("long overflow"))), - ((8126382074515995418L, -4746652047588907829L), Expected(new ArithmeticException("long overflow"))), - ((Long.MaxValue, 1L), Expected(new ArithmeticException("long overflow"))), - ((Long.MaxValue, -1L), Expected(new ArithmeticException("long overflow"))) - ) - }, - existingFeature( - { (x: (Long, Long)) => - val a = x._1; val b = x._2 - val plus = n.plus(a, b) - val minus = n.minus(a, b) - val mul = n.times(a, b) - val div = a / b - val mod = a % b - (plus, (minus, (mul, (div, mod)))) + { + def success[T](v: T) = Expected(Success(v), 1788, arithOpsCostDetails(SLong), 1788, 2112 +: Seq.fill(3)(2116)) + Seq( + ((Long.MinValue, -4677100190307931395L), Expected(new ArithmeticException("long overflow"))), + ((Long.MinValue, -1L), Expected(new ArithmeticException("long overflow"))), + ((Long.MinValue, 1L), Expected(new ArithmeticException("long overflow"))), + ((-9223372036854775808L, 0L), Expected(new ArithmeticException("/ by zero"))), + ((-5828066432064138816L, 9105034716270510411L), Expected(new ArithmeticException("long overflow"))), + ((-4564956247298949325L, -1L), success( + (-4564956247298949326L, (-4564956247298949324L, (4564956247298949325L, (4564956247298949325L, 0L)))) + )), + ((-1499553565058783253L, -3237683216870282569L), Expected(new ArithmeticException("long overflow"))), + ((-1368457031689886112L, 9223372036854775807L), Expected(new ArithmeticException("long overflow"))), + ((-1L, -4354407074688367443L), success((-4354407074688367444L, (4354407074688367442L, (4354407074688367443L, (0L, -1L)))))), + ((-1L, -1L), success((-2L, (0L, (1L, (1L, 0L)))))), + ((-1L, 5665019549505434695L), success((5665019549505434694L, (-5665019549505434696L, (-5665019549505434695L, (0L, -1L)))))), + ((0L, -1L), success((-1L, (1L, (0L, (0L, 0L)))))), + ((0L, 0L), Expected(new ArithmeticException("/ by zero"))), + ((0L, 2112386634269044172L), success((2112386634269044172L, (-2112386634269044172L, (0L, (0L, 0L)))))), + ((2254604056782701370L, -5878231674026236574L), Expected(new ArithmeticException("long overflow"))), + ((2903872550238813643L, 1L), success( + (2903872550238813644L, (2903872550238813642L, (2903872550238813643L, (2903872550238813643L, 0L)))) + )), + ((5091129735284641762L, -427673944382373638L), Expected(new ArithmeticException("long overflow"))), + ((6029085020194630780L, 2261786144956037939L), Expected(new ArithmeticException("long overflow"))), + ((8126382074515995418L, -4746652047588907829L), Expected(new ArithmeticException("long overflow"))), + ((Long.MaxValue, 1L), Expected(new ArithmeticException("long overflow"))), + ((Long.MaxValue, -1L), Expected(new ArithmeticException("long overflow"))) + ) }, - """{ (x: (Long, Long)) => - | val a = x._1; val b = x._2 - | val plus = a + b - | val minus = a - b - | val mul = a * b - | val div = a / b - | val mod = a % b - | (plus, (minus, (mul, (div, mod)))) - |}""".stripMargin, - FuncValue( - Vector((1, STuple(Vector(SLong, SLong)))), - BlockValue( - Vector( - ValDef( - 3, - List(), - SelectField.typed[LongValue](ValUse(1, STuple(Vector(SLong, SLong))), 1.toByte) - ), - ValDef( - 4, - List(), - SelectField.typed[LongValue](ValUse(1, STuple(Vector(SLong, SLong))), 2.toByte) - ) - ), - Tuple( + existingFeature( + { (x: (Long, Long)) => + val a = x._1; + val b = x._2 + val plus = n.plus(a, b) + val minus = n.minus(a, b) + val mul = n.times(a, b) + val div = a / b + val mod = a % b + (plus, (minus, (mul, (div, mod)))) + }, + """{ (x: (Long, Long)) => + | val a = x._1; val b = x._2 + | val plus = a + b + | val minus = a - b + | val mul = a * b + | val div = a / b + | val mod = a % b + | (plus, (minus, (mul, (div, mod)))) + |}""".stripMargin, + FuncValue( + Vector((1, STuple(Vector(SLong, SLong)))), + BlockValue( Vector( - ArithOp(ValUse(3, SLong), ValUse(4, SLong), OpCode @@ (-102.toByte)), - Tuple( - Vector( - ArithOp(ValUse(3, SLong), ValUse(4, SLong), OpCode @@ (-103.toByte)), - Tuple( - Vector( - ArithOp(ValUse(3, SLong), ValUse(4, SLong), OpCode @@ (-100.toByte)), - Tuple( - Vector( - ArithOp(ValUse(3, SLong), ValUse(4, SLong), OpCode @@ (-99.toByte)), - ArithOp(ValUse(3, SLong), ValUse(4, SLong), OpCode @@ (-98.toByte)) + ValDef( + 3, + List(), + SelectField.typed[LongValue](ValUse(1, STuple(Vector(SLong, SLong))), 1.toByte) + ), + ValDef( + 4, + List(), + SelectField.typed[LongValue](ValUse(1, STuple(Vector(SLong, SLong))), 2.toByte) + ) + ), + Tuple( + Vector( + ArithOp(ValUse(3, SLong), ValUse(4, SLong), OpCode @@ (-102.toByte)), + Tuple( + Vector( + ArithOp(ValUse(3, SLong), ValUse(4, SLong), OpCode @@ (-103.toByte)), + Tuple( + Vector( + ArithOp(ValUse(3, SLong), ValUse(4, SLong), OpCode @@ (-100.toByte)), + Tuple( + Vector( + ArithOp(ValUse(3, SLong), ValUse(4, SLong), OpCode @@ (-99.toByte)), + ArithOp(ValUse(3, SLong), ValUse(4, SLong), OpCode @@ (-98.toByte)) + ) ) ) ) @@ -1891,13 +1938,12 @@ class SigmaDslSpecification extends SigmaDslTesting ) ) ) - ) - ))) + ))) } property("Long LT, GT, NEQ") { val o = ExactOrdering.LongIsExactOrdering - def expect(v: Boolean) = Expected(Success(v), 1768, binaryRelationCostDetails(LT, SLong), 1768) + def expect(v: Boolean) = Expected(Success(v), 1768, binaryRelationCostDetails(LT, SLong), 1768, 2010 +: Seq.fill(3)(2012)) val LT_cases: Seq[((Long, Long), Expected[Boolean])] = Seq( (Long.MinValue, Long.MinValue) -> expect(false), (Long.MinValue, (Long.MinValue + 1).toLong) -> expect(true), @@ -1938,16 +1984,16 @@ class SigmaDslSpecification extends SigmaDslTesting verifyOp(LT_cases, "<", LT.apply)(_ < _) verifyOp( - swapArgs(LT_cases, cost = 1768, newCostDetails = binaryRelationCostDetails(GT, SLong)), + swapArgs(LT_cases, cost = 1768, newCostDetails = binaryRelationCostDetails(GT, SLong), expectedV3Costs = 2010 +: Seq.fill(3)(2012)), ">", GT.apply)(_ > _) - val neqCases = newCasesFrom2(LT_cases.map(_._1))(_ != _, cost = 1766, newCostDetails = costNEQ(constNeqCost)) + val neqCases = newCasesFrom3(LT_cases.map(_._1))(_ != _, cost = 1766, newCostDetails = costNEQ(constNeqCost), 2008 +: Seq.fill(3)(2010)) verifyOp(neqCases, "!=", NEQ.apply)(_ != _) } property("Long LE, GE") { val o = ExactOrdering.LongIsExactOrdering - def expect(v: Boolean) = Expected(Success(v), 1768, binaryRelationCostDetails(LE, SLong), 1768) + def expect(v: Boolean) = Expected(Success(v), 1768, binaryRelationCostDetails(LE, SLong), 1768, 2010 +: Seq.fill(3)(2012)) val LE_cases: Seq[((Long, Long), Expected[Boolean])] = Seq( (Long.MinValue, Long.MinValue) -> expect(true), (Long.MinValue, (Long.MinValue + 1).toLong) -> expect(true), @@ -1989,7 +2035,7 @@ class SigmaDslSpecification extends SigmaDslTesting verifyOp(LE_cases, "<=", LE.apply)(_ <= _) verifyOp( - swapArgs(LE_cases, cost = 1768, newCostDetails = binaryRelationCostDetails(GE, SLong)), + swapArgs(LE_cases, cost = 1768, newCostDetails = binaryRelationCostDetails(GE, SLong), expectedV3Costs = 2010 +: Seq.fill(3)(2012)), ">=", GE.apply)(_ >= _) } @@ -2020,7 +2066,7 @@ class SigmaDslSpecification extends SigmaDslTesting property("BigInt methods equivalence") { verifyCases( { - def success(v: BigInt) = Expected(Success(v), 1764, TracedCost(traceBase), 1764) + def success(v: BigInt) = Expected(Success(v), 1764, TracedCost(traceBase), 1764, 1992 +: Seq.fill(3)(1994)) Seq( (CBigInt(new BigInteger("-85102d7f884ca0e8f56193b46133acaf7e4681e1757d03f191ae4f445c8e0", 16)), success( CBigInt(new BigInteger("-85102d7f884ca0e8f56193b46133acaf7e4681e1757d03f191ae4f445c8e0", 16)) @@ -2041,11 +2087,11 @@ class SigmaDslSpecification extends SigmaDslTesting val n = NumericOps.BigIntIsExactIntegral verifyCases( - { - def success(v: (BigInt, (BigInt, (BigInt, (BigInt, BigInt))))) = - Expected(Success(v), 1793, arithOpsCostDetails(SBigInt), 1793) - Seq( - ((CBigInt(new BigInteger("-8683d1cd99d5fcf0e6eff6295c285c36526190e13dbde008c49e5ae6fddc1c", 16)), + { + def success(v: (BigInt, (BigInt, (BigInt, (BigInt, BigInt))))) = + Expected(Success(v), 1793, arithOpsCostDetails(SBigInt), 1793, 2117 +: Seq.fill(3)(2121)) + Seq( + ((CBigInt(new BigInteger("-8683d1cd99d5fcf0e6eff6295c285c36526190e13dbde008c49e5ae6fddc1c", 16)), CBigInt(new BigInteger("-2ef55db3f245feddacf0182e299dd", 16))), Expected(new ArithmeticException("BigInteger out of 256 bit range"))), @@ -2167,8 +2213,7 @@ class SigmaDslSpecification extends SigmaDslTesting property("BigInt LT, GT, NEQ") { val o = NumericOps.BigIntIsExactOrdering - def expect(v: Boolean) = Expected(Success(v), 1768, binaryRelationCostDetails(LT, SBigInt), 1768) - + def expect(v: Boolean) = Expected(Success(v), 1768, binaryRelationCostDetails(LT, SBigInt), 1768, 2010 +: Seq.fill(3)(2012)) val LT_cases: Seq[((BigInt, BigInt), Expected[Boolean])] = Seq( (BigIntMinValue, BigIntMinValue) -> expect(false), (BigIntMinValue, BigIntMinValue.add(1.toBigInt)) -> expect(true), @@ -2211,11 +2256,11 @@ class SigmaDslSpecification extends SigmaDslTesting verifyOp(LT_cases, "<", LT.apply)(o.lt(_, _)) verifyOp( - swapArgs(LT_cases, cost = 1768, newCostDetails = binaryRelationCostDetails(GT, SBigInt)), + swapArgs(LT_cases, cost = 1768, newCostDetails = binaryRelationCostDetails(GT, SBigInt), expectedV3Costs = 2010 +: Seq.fill(3)(2012)), ">", GT.apply)(o.gt(_, _)) val constBigIntCost = Array[CostItem](FixedCostItem(NamedDesc("EQ_BigInt"), FixedCost(JitCost(5)))) - val neqCases = newCasesFrom2(LT_cases.map(_._1))(_ != _, cost = 1766, newCostDetails = costNEQ(constBigIntCost)) + val neqCases = newCasesFrom3(LT_cases.map(_._1))(_ != _, cost = 1766, newCostDetails = costNEQ(constBigIntCost), expectedV3Costs = 2008 +: Seq.fill(3)(2010)) verifyOp(neqCases, "!=", NEQ.apply)(_ != _) } @@ -2226,8 +2271,7 @@ class SigmaDslSpecification extends SigmaDslTesting val BigIntMaxValue = CBigInt(new BigInteger("7F" + "ff" * 31, 16)) val BigIntOverlimit = CBigInt(new BigInteger("7F" + "ff" * 33, 16)) - def expect(v: Boolean) = Expected(Success(v), 1768, binaryRelationCostDetails(LE, SBigInt), 1768) - + def expect(v: Boolean) = Expected(Success(v), 1768, binaryRelationCostDetails(LE, SBigInt), 1768, 2010 +: Seq.fill(3)(2012)) val LE_cases: Seq[((BigInt, BigInt), Expected[Boolean])] = Seq( (BigIntMinValue, BigIntMinValue) -> expect(true), (BigIntMinValue, BigIntMinValue.add(1.toBigInt)) -> expect(true), @@ -2271,7 +2315,7 @@ class SigmaDslSpecification extends SigmaDslTesting verifyOp(LE_cases, "<=", LE.apply)(o.lteq(_, _)) verifyOp( - swapArgs(LE_cases, cost = 1768, newCostDetails = binaryRelationCostDetails(GE, SBigInt)), + swapArgs(LE_cases, cost = 1768, newCostDetails = binaryRelationCostDetails(GE, SBigInt), expectedV3Costs = 2010 +: Seq.fill(3)(2012)), ">=", GE.apply)(o.gteq(_, _)) } @@ -2330,16 +2374,17 @@ class SigmaDslSpecification extends SigmaDslTesting } /** Executed a series of test cases of NEQ operation verify using two _different_ - * data instances `x` and `y`. - * @param cost the expected cost of `verify` (the same for all cases) - */ - def verifyNeq[A: Ordering: Arbitrary: RType] - (x: A, y: A, cost: Int, neqCost: Seq[CostItem] = ArraySeq.empty, newCost: Int) - (copy: A => A, generateCases: Boolean = true) - (implicit sampled: Sampled[(A, A)], evalSettings: EvalSettings) = { + * data instances `x` and `y`. + * + * @param cost the expected cost of `verify` (the same for all cases) + */ + def verifyNeq[A: Ordering : Arbitrary : RType] + (x: A, y: A, cost: Int, neqCost: Seq[CostItem] = ArraySeq.empty, newCost: Int, expectedV3Costs: Seq[Int]) + (copy: A => A, generateCases: Boolean = true) + (implicit sampled: Sampled[(A, A)], evalSettings: EvalSettings) = { val copied_x = copy(x) val newCostDetails = if (neqCost.isEmpty) CostDetails.ZeroCost else costNEQ(neqCost) - def expected(v: Boolean) = Expected(Success(v), cost, newCostDetails, newCost) + def expected(v: Boolean) = Expected(Success(v), cost, newCostDetails, newCost, expectedV3Costs) def expectedNoCost(v: Boolean) = new Expected(ExpectedResult(Success(v), None)) verifyOp(Seq( (x, y) -> expected(true), // check cost only for this test case, because the trace depends in x and y @@ -2352,11 +2397,11 @@ class SigmaDslSpecification extends SigmaDslTesting } property("NEQ of pre-defined types") { - verifyNeq(ge1, ge2, 1783, Array[CostItem](FixedCostItem(NamedDesc("EQ_GroupElement"), FixedCost(JitCost(172)))), 1783)(_.asInstanceOf[CGroupElement].copy()) - verifyNeq(t1, t2, 1767, Array[CostItem](FixedCostItem(NamedDesc("EQ_AvlTree"), FixedCost(JitCost(6)))), 1767)(_.asInstanceOf[CAvlTree].copy()) - verifyNeq(b1, b2, 1767, Array[CostItem](), 1767)(_.asInstanceOf[CostingBox].copy()) - verifyNeq(preH1, preH2, 1766, Array[CostItem](FixedCostItem(NamedDesc("EQ_PreHeader"), FixedCost(JitCost(4)))), 1766)(_.asInstanceOf[CPreHeader].copy()) - verifyNeq(h1, h2, 1767, Array[CostItem](FixedCostItem(NamedDesc("EQ_Header"), FixedCost(JitCost(6)))), 1767)(_.asInstanceOf[CHeader].copy()) + verifyNeq(ge1, ge2, 1783, Array[CostItem](FixedCostItem(NamedDesc("EQ_GroupElement"), FixedCost(JitCost(172)))), 1783, 2025 +: Seq.fill(3)(2027))(_.asInstanceOf[CGroupElement].copy()) + verifyNeq(t1, t2, 1767, Array[CostItem](FixedCostItem(NamedDesc("EQ_AvlTree"), FixedCost(JitCost(6)))), 1767, 2017 +: Seq.fill(3)(2019))(_.asInstanceOf[CAvlTree].copy()) + verifyNeq(b1, b2, 1767, Array[CostItem](), 1767, 2017 +: Seq.fill(3)(2019))(_.asInstanceOf[CostingBox].copy()) + verifyNeq(preH1, preH2, 1766, Array[CostItem](FixedCostItem(NamedDesc("EQ_PreHeader"), FixedCost(JitCost(4)))), 1766, 2016 +: Seq.fill(3)(2018))(_.asInstanceOf[CPreHeader].copy()) + verifyNeq(h1, h2, 1767, Array[CostItem](FixedCostItem(NamedDesc("EQ_Header"), FixedCost(JitCost(6)))), 1767, 2017 +: Seq.fill(3)(2019))(_.asInstanceOf[CHeader].copy()) } property("NEQ of tuples of numerics") { @@ -2364,14 +2409,14 @@ class SigmaDslSpecification extends SigmaDslTesting FixedCostItem(NamedDesc("EQ_Tuple"), FixedCost(JitCost(4))), FixedCostItem(NamedDesc("EQ_Prim"), FixedCost(JitCost(3))) ) - verifyNeq((0.toByte, 1.toByte), (1.toByte, 1.toByte), 1767, tuplesNeqCost, 1767)(_.copy()) - verifyNeq((0.toShort, 1.toByte), (1.toShort, 1.toByte), 1767, tuplesNeqCost, 1767)(_.copy()) - verifyNeq((0, 1.toByte), (1, 1.toByte), 1767, tuplesNeqCost, 1767)(_.copy()) - verifyNeq((0.toLong, 1.toByte), (1.toLong, 1.toByte), 1767, tuplesNeqCost, 1767)(_.copy()) + verifyNeq((0.toByte, 1.toByte), (1.toByte, 1.toByte), 1767, tuplesNeqCost, 1767, 2017 +: Seq.fill(3)(2019))(_.copy()) + verifyNeq((0.toShort, 1.toByte), (1.toShort, 1.toByte), 1767, tuplesNeqCost, 1767, 2025 +: Seq.fill(3)(2029))(_.copy()) + verifyNeq((0, 1.toByte), (1, 1.toByte), 1767, tuplesNeqCost, 1767, 2025 +: Seq.fill(3)(2029))(_.copy()) + verifyNeq((0.toLong, 1.toByte), (1.toLong, 1.toByte), 1767, tuplesNeqCost, 1767, 2025 +: Seq.fill(3)(2029))(_.copy()) verifyNeq((0.toBigInt, 1.toByte), (1.toBigInt, 1.toByte), 1767, Array( FixedCostItem(NamedDesc("EQ_Tuple"), FixedCost(JitCost(4))), FixedCostItem(NamedDesc("EQ_BigInt"), FixedCost(JitCost(5))) - ), 1767)(_.copy()) + ), 1767, 2025 +: Seq.fill(3)(2029))(_.copy()) } property("NEQ of tuples of pre-defined types") { @@ -2380,30 +2425,29 @@ class SigmaDslSpecification extends SigmaDslTesting FixedCostItem(NamedDesc("EQ_GroupElement"), FixedCost(JitCost(172))), FixedCostItem(NamedDesc("EQ_GroupElement"), FixedCost(JitCost(172))) ) - verifyNeq((ge1, ge1), (ge1, ge2), 1801, groupNeqCost, 1801)(_.copy()) + verifyNeq((ge1, ge1), (ge1, ge2), 1801, groupNeqCost, 1801, 2051 +: Seq.fill(3)(2053))(_.copy()) val treeNeqCost = Array( FixedCostItem(NamedDesc("EQ_Tuple"), FixedCost(JitCost(4))), FixedCostItem(NamedDesc("EQ_AvlTree"), FixedCost(JitCost(6))), FixedCostItem(NamedDesc("EQ_AvlTree"), FixedCost(JitCost(6))) ) - verifyNeq((t1, t1), (t1, t2), 1768, treeNeqCost, 1768)(_.copy()) - - verifyNeq((b1, b1), (b1, b2), 1768, Array[CostItem](), 1768)(_.copy()) + verifyNeq((t1, t1), (t1, t2), 1768, treeNeqCost, 1768, 2034 +: Seq.fill(3)(2038))(_.copy()) + verifyNeq((b1, b1), (b1, b2), 1768, Array[CostItem](), 1768, 2034 +: Seq.fill(3)(2038))(_.copy()) val preHeaderNeqCost = Array( FixedCostItem(NamedDesc("EQ_Tuple"), FixedCost(JitCost(4))), FixedCostItem(NamedDesc("EQ_PreHeader"), FixedCost(JitCost(4))), FixedCostItem(NamedDesc("EQ_PreHeader"), FixedCost(JitCost(4))) ) - verifyNeq((preH1, preH1), (preH1, preH2), 1767, preHeaderNeqCost, 1767)(_.copy()) + verifyNeq((preH1, preH1), (preH1, preH2), 1767, preHeaderNeqCost, 1767, 2033 +: Seq.fill(3)(2037))(_.copy()) val headerNeqCost = Array( FixedCostItem(NamedDesc("EQ_Tuple"), FixedCost(JitCost(4))), FixedCostItem(NamedDesc("EQ_Header"), FixedCost(JitCost(6))), FixedCostItem(NamedDesc("EQ_Header"), FixedCost(JitCost(6))) ) - verifyNeq((h1, h1), (h1, h2), 1768, headerNeqCost, 1768)(_.copy()) + verifyNeq((h1, h1), (h1, h2), 1768, headerNeqCost, 1768, 2034 +: Seq.fill(3)(2038))(_.copy()) } property("NEQ of nested tuples") { @@ -2487,15 +2531,15 @@ class SigmaDslSpecification extends SigmaDslTesting FixedCostItem(NamedDesc("EQ_Header"), FixedCost(JitCost(6))), FixedCostItem(NamedDesc("EQ_Header"), FixedCost(JitCost(6))) ) - verifyNeq((ge1, (t1, t1)), (ge1, (t1, t2)), 1785, nestedTuplesNeqCost1, 1785)(_.copy()) - verifyNeq((ge1, (t1, (b1, b1))), (ge1, (t1, (b1, b2))), 1786, nestedTuplesNeqCost2, 1786)(_.copy()) - verifyNeq((ge1, (t1, (b1, (preH1, preH1)))), (ge1, (t1, (b1, (preH1, preH2)))), 1787, nestedTuplesNeqCost3, 1787)(_.copy()) - verifyNeq((ge1, (t1, (b1, (preH1, (h1, h1))))), (ge1, (t1, (b1, (preH1, (h1, h2))))), 1788, nestedTuplesNeqCost4, 1788)(_.copy()) + verifyNeq((ge1, (t1, t1)), (ge1, (t1, t2)), 1785, nestedTuplesNeqCost1, 1785, 2059 +: Seq.fill(3)(2063))(_.copy()) + verifyNeq((ge1, (t1, (b1, b1))), (ge1, (t1, (b1, b2))), 1786, nestedTuplesNeqCost2, 1786, 2076 +: Seq.fill(3)(2080))(_.copy()) + verifyNeq((ge1, (t1, (b1, (preH1, preH1)))), (ge1, (t1, (b1, (preH1, preH2)))), 1787, nestedTuplesNeqCost3, 1787, 2093 +: Seq.fill(3)(2097))(_.copy()) + verifyNeq((ge1, (t1, (b1, (preH1, (h1, h1))))), (ge1, (t1, (b1, (preH1, (h1, h2))))), 1788, nestedTuplesNeqCost4, 1788, 2110 +: Seq.fill(3)(2114))(_.copy()) - verifyNeq(((ge1, t1), t1), ((ge1, t1), t2), 1785, nestedTuplesNeqCost5, 1785)(_.copy()) - verifyNeq((((ge1, t1), b1), b1), (((ge1, t1), b1), b2), 1786, nestedTuplesNeqCost6, 1786)(_.copy()) - verifyNeq((((ge1, t1), b1), (preH1, preH1)), (((ge1, t1), b1), (preH1, preH2)), 1787, nestedTuplesNeqCost7, 1787)(_.copy()) - verifyNeq((((ge1, t1), b1), (preH1, (h1, h1))), (((ge1, t1), b1), (preH1, (h1, h2))), 1788, nestedTuplesNeqCost8, 1788)(_.copy()) + verifyNeq(((ge1, t1), t1), ((ge1, t1), t2), 1785, nestedTuplesNeqCost5, 1785, 2059 +: Seq.fill(3)(2063))(_.copy()) + verifyNeq((((ge1, t1), b1), b1), (((ge1, t1), b1), b2), 1786, nestedTuplesNeqCost6, 1786, 2076 +: Seq.fill(3)(2080))(_.copy()) + verifyNeq((((ge1, t1), b1), (preH1, preH1)), (((ge1, t1), b1), (preH1, preH2)), 1787, nestedTuplesNeqCost7, 1787, 2093 +: Seq.fill(3)(2097))(_.copy()) + verifyNeq((((ge1, t1), b1), (preH1, (h1, h1))), (((ge1, t1), b1), (preH1, (h1, h2))), 1788, nestedTuplesNeqCost8, 1788, 2110 +: Seq.fill(3)(2114))(_.copy()) } property("NEQ of collections of pre-defined types") { @@ -2507,63 +2551,71 @@ class SigmaDslSpecification extends SigmaDslTesting SeqCostItem(NamedDesc("EQ_COA_Box"), PerItemCost(JitCost(15), JitCost(5), 1), 0) ) implicit val evalSettings = suite.evalSettings.copy(isMeasureOperationTime = false) - verifyNeq(Coll[Byte](), Coll(1.toByte), 1766, collNeqCost1, 1766)(cloneColl(_)) + verifyNeq(Coll[Byte](), Coll(1.toByte), 1766, collNeqCost1, 1766, 2016 +: Seq.fill(3)(2018))(cloneColl(_)) verifyNeq(Coll[Byte](0, 1), Coll(1.toByte, 1.toByte), 1768, Array( FixedCostItem(NamedDesc("MatchType"), FixedCost(JitCost(1))), SeqCostItem(NamedDesc("EQ_COA_Byte"), PerItemCost(JitCost(15), JitCost(2), 128), 1)), - 1768 + 1768, + 2018 +: Seq.fill(3)(2020) )(cloneColl(_)) - verifyNeq(Coll[Short](), Coll(1.toShort), 1766, collNeqCost1, 1766)(cloneColl(_)) + verifyNeq(Coll[Short](), Coll(1.toShort), 1766, collNeqCost1, 1766, 2016 +: Seq.fill(3)(2018))(cloneColl(_)) verifyNeq(Coll[Short](0), Coll(1.toShort), 1768, Array( FixedCostItem(NamedDesc("MatchType"), FixedCost(JitCost(1))), SeqCostItem(NamedDesc("EQ_COA_Short"), PerItemCost(JitCost(15), JitCost(2), 96), 1)), - 1768 + 1768, + 2018 +: Seq.fill(3)(2020) )(cloneColl(_)) - verifyNeq(Coll[Int](), Coll(1), 1766, collNeqCost1, 1766)(cloneColl(_)) + verifyNeq(Coll[Int](), Coll(1), 1766, collNeqCost1, 1766, 2016 +: Seq.fill(3)(2018))(cloneColl(_)) verifyNeq(Coll[Int](0), Coll(1), 1768, Array( FixedCostItem(NamedDesc("MatchType"), FixedCost(JitCost(1))), SeqCostItem(NamedDesc("EQ_COA_Int"), PerItemCost(JitCost(15), JitCost(2), 64), 1)), - 1768 + 1768, + 2018 +: Seq.fill(3)(2020) )(cloneColl(_)) - verifyNeq(Coll[Long](), Coll(1.toLong), 1766, collNeqCost1, 1766)(cloneColl(_)) + verifyNeq(Coll[Long](), Coll(1.toLong), 1766, collNeqCost1, 1766, 2016 +: Seq.fill(3)(2018))(cloneColl(_)) verifyNeq(Coll[Long](0), Coll(1.toLong), 1768, Array( FixedCostItem(NamedDesc("MatchType"), FixedCost(JitCost(1))), SeqCostItem(NamedDesc("EQ_COA_Long"), PerItemCost(JitCost(15), JitCost(2), 48), 1)), - 1768 + 1768, + 2018 +: Seq.fill(3)(2020) )(cloneColl(_)) prepareSamples[Coll[BigInt]] - verifyNeq(Coll[BigInt](), Coll(1.toBigInt), 1766, collNeqCost1, 1766)(cloneColl(_)) + verifyNeq(Coll[BigInt](), Coll(1.toBigInt), 1766, collNeqCost1, 1766, 2016 +: Seq.fill(3)(2018))(cloneColl(_)) verifyNeq(Coll[BigInt](0.toBigInt), Coll(1.toBigInt), 1768, Array( FixedCostItem(NamedDesc("MatchType"), FixedCost(JitCost(1))), SeqCostItem(NamedDesc("EQ_COA_BigInt"), PerItemCost(JitCost(15), JitCost(7), 5), 1)), - 1768 + 1768, + 2018 +: Seq.fill(3)(2020) )(cloneColl(_)) prepareSamples[Coll[GroupElement]] - verifyNeq(Coll[GroupElement](), Coll(ge1), 1766, collNeqCost1, 1766)(cloneColl(_)) + verifyNeq(Coll[GroupElement](), Coll(ge1), 1766, collNeqCost1, 1766, 2016 +: Seq.fill(3)(2018))(cloneColl(_)) verifyNeq(Coll[GroupElement](ge1), Coll(ge2), 1768, Array( FixedCostItem(NamedDesc("MatchType"), FixedCost(JitCost(1))), SeqCostItem(NamedDesc("EQ_COA_GroupElement"), PerItemCost(JitCost(15), JitCost(5), 1), 1)), - 1768 + 1768, + 2018 +: Seq.fill(3)(2020) )(cloneColl(_)) prepareSamples[Coll[AvlTree]] - verifyNeq(Coll[AvlTree](), Coll(t1), 1766, collNeqCost1, 1766)(cloneColl(_)) + verifyNeq(Coll[AvlTree](), Coll(t1), 1766, collNeqCost1, 1766, 2024 +: Seq.fill(3)(2028))(cloneColl(_)) + verifyNeq(Coll[AvlTree](t1), Coll(t2), 1768, Array( FixedCostItem(NamedDesc("MatchType"), FixedCost(JitCost(1))), SeqCostItem(NamedDesc("EQ_COA_AvlTree"), PerItemCost(JitCost(15), JitCost(5), 2), 1)), - 1768 + 1768, + 2026 +: Seq.fill(3)(2030) )(cloneColl(_)) { // since SBox.isConstantSize = false, the cost is different among cases @@ -2572,38 +2624,40 @@ class SigmaDslSpecification extends SigmaDslTesting val y = Coll(b1) val copied_x = cloneColl(x) verifyOp(Seq( - (x, x) -> Expected(Success(false), 1768, costNEQ(collNeqCost2), 1768), - (x, copied_x) -> Expected(Success(false), 1768, costNEQ(collNeqCost2), 1768), - (copied_x, x) -> Expected(Success(false), 1768, costNEQ(collNeqCost2), 1768), - (x, y) -> Expected(Success(true), 1766, costNEQ(collNeqCost1), 1766), - (y, x) -> Expected(Success(true), 1766, costNEQ(collNeqCost1), 1766) - ), + (x, x) -> Expected(Success(false), 1768, costNEQ(collNeqCost2), 1768, 2026 +: Seq.fill(3)(2030)), + (x, copied_x) -> Expected(Success(false), 1768, costNEQ(collNeqCost2), 1768, 2026 +: Seq.fill(3)(2030)), + (copied_x, x) -> Expected(Success(false), 1768, costNEQ(collNeqCost2), 1768, 2026 +: Seq.fill(3)(2030)), + (x, y) -> Expected(Success(true), 1766, costNEQ(collNeqCost1), 1766, 2024 +: Seq.fill(3)(2028)), + (y, x) -> Expected(Success(true), 1766, costNEQ(collNeqCost1), 1766, 2024 +: Seq.fill(3)(2028)) + ), "!=", NEQ.apply)(_ != _, generateCases = false) verifyNeq(Coll[Box](b1), Coll(b2), 1768, Array( FixedCostItem(NamedDesc("MatchType"), FixedCost(JitCost(1))), SeqCostItem(NamedDesc("EQ_COA_Box"), PerItemCost(JitCost(15), JitCost(5), 1), 1)), - 1768 + 1768, + 2026 +: Seq.fill(3)(2030) )(cloneColl(_), generateCases = false) } prepareSamples[Coll[PreHeader]] - verifyNeq(Coll[PreHeader](), Coll(preH1), 1766, collNeqCost1, 1766)(cloneColl(_)) + verifyNeq(Coll[PreHeader](), Coll(preH1), 1766, collNeqCost1, 1766, 2024 +: Seq.fill(3)(2028))(cloneColl(_)) verifyNeq(Coll[PreHeader](preH1), Coll(preH2), 1768, Array( FixedCostItem(NamedDesc("MatchType"), FixedCost(JitCost(1))), SeqCostItem(NamedDesc("EQ_COA_PreHeader"), PerItemCost(JitCost(15), JitCost(3), 1), 1)), - 1768 + 1768, + 2026 +: Seq.fill(3)(2030) )(cloneColl(_)) prepareSamples[Coll[Header]] - verifyNeq(Coll[Header](), Coll(h1), 1766, collNeqCost1, 1766)(cloneColl(_)) + verifyNeq(Coll[Header](), Coll(h1), 1766, collNeqCost1, 1766, 2024 +: Seq.fill(3)(2028))(cloneColl(_)) verifyNeq(Coll[Header](h1), Coll(h2), 1768, Array( FixedCostItem(NamedDesc("MatchType"), FixedCost(JitCost(1))), SeqCostItem(NamedDesc("EQ_COA_Header"), PerItemCost(JitCost(15), JitCost(5), 1), 1)), - 1768 + 1768, 2026 +: Seq.fill(3)(2030) )(cloneColl(_)) } @@ -2627,10 +2681,10 @@ class SigmaDslSpecification extends SigmaDslTesting SeqCostItem(NamedDesc("EQ_COA_Int"), PerItemCost(JitCost(15), JitCost(2), 64), 1), SeqCostItem(NamedDesc("EQ_Coll"), PerItemCost(JitCost(10), JitCost(2), 1), 1) ) - verifyNeq(Coll[Coll[Int]](), Coll(Coll[Int]()), 1766, nestedNeq1, 1766)(cloneColl(_)) - verifyNeq(Coll(Coll[Int]()), Coll(Coll[Int](1)), 1767, nestedNeq2, 1767)(cloneColl(_)) - verifyNeq(Coll(Coll[Int](1)), Coll(Coll[Int](2)), 1769, nestedNeq3, 1769)(cloneColl(_)) - verifyNeq(Coll(Coll[Int](1)), Coll(Coll[Int](1, 2)), 1767, nestedNeq2, 1767)(cloneColl(_)) + verifyNeq(Coll[Coll[Int]](), Coll(Coll[Int]()), 1766, nestedNeq1, 1766, 2016 +: Seq.fill(3)(2018))(cloneColl(_)) + verifyNeq(Coll(Coll[Int]()), Coll(Coll[Int](1)), 1767, nestedNeq2, 1767, 2017 +: Seq.fill(3)(2019))(cloneColl(_)) + verifyNeq(Coll(Coll[Int](1)), Coll(Coll[Int](2)), 1769, nestedNeq3, 1769, 2019 +: Seq.fill(3)(2021))(cloneColl(_)) + verifyNeq(Coll(Coll[Int](1)), Coll(Coll[Int](1, 2)), 1767, nestedNeq2, 1767, 2017 +: Seq.fill(3)(2019))(cloneColl(_)) prepareSamples[Coll[(Int, BigInt)]] prepareSamples[Coll[Coll[(Int, BigInt)]]] @@ -2673,8 +2727,8 @@ class SigmaDslSpecification extends SigmaDslTesting SeqCostItem(NamedDesc("EQ_Coll"), PerItemCost(JitCost(10), JitCost(2), 1), 1), SeqCostItem(NamedDesc("EQ_Coll"), PerItemCost(JitCost(10), JitCost(2), 1), 1) ) - verifyNeq(Coll(Coll((1, 10.toBigInt))), Coll(Coll((1, 11.toBigInt))), 1770, nestedNeq4, 1770)(cloneColl(_)) - verifyNeq(Coll(Coll(Coll((1, 10.toBigInt)))), Coll(Coll(Coll((1, 11.toBigInt)))), 1771, nestedNeq5, 1771)(cloneColl(_)) + verifyNeq(Coll(Coll((1, 10.toBigInt))), Coll(Coll((1, 11.toBigInt))), 1770, nestedNeq4, 1770, 2044 +: Seq.fill(3)(2048))(cloneColl(_)) + verifyNeq(Coll(Coll(Coll((1, 10.toBigInt)))), Coll(Coll(Coll((1, 11.toBigInt)))), 1771, nestedNeq5, 1771, 2053 +: Seq.fill(3)(2057))(cloneColl(_)) verifyNeq( (Coll( (Coll( @@ -2688,94 +2742,96 @@ class SigmaDslSpecification extends SigmaDslTesting ), preH1), 1774, nestedNeq6, - 1774 + 1774, + 2096 +: Seq.fill(3)(2100) )(x => (cloneColl(x._1), x._2)) } property("GroupElement.getEncoded equivalence") { verifyCases( - { - def success[T](v: T) = Expected(Success(v), 1790, methodCostDetails(SGroupElement.GetEncodedMethod, 250), 1790) - Seq( - (ge1, success(Helpers.decodeBytes(ge1str))), - (ge2, success(Helpers.decodeBytes(ge2str))), - (ge3, success(Helpers.decodeBytes(ge3str))), - (SigmaDsl.groupGenerator, - success(Helpers.decodeBytes("0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798"))), - (SigmaDsl.groupIdentity, - success(Helpers.decodeBytes("000000000000000000000000000000000000000000000000000000000000000000"))) - ) - }, - existingFeature((x: GroupElement) => x.getEncoded, - "{ (x: GroupElement) => x.getEncoded }", - FuncValue( - Vector((1, SGroupElement)), - MethodCall(ValUse(1, SGroupElement), SGroupElement.getMethodByName("getEncoded"), Vector(), Map()) - ))) + { + def success[T](v: T) = Expected(Success(v), 1790, methodCostDetails(SGroupElement.GetEncodedMethod, 250), 1790, 2024 +: Seq.fill(3)(2026)) + Seq( + (ge1, success(Helpers.decodeBytes(ge1str))), + (ge2, success(Helpers.decodeBytes(ge2str))), + (ge3, success(Helpers.decodeBytes(ge3str))), + (SigmaDsl.groupGenerator, + success(Helpers.decodeBytes("0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798"))), + (SigmaDsl.groupIdentity, + success(Helpers.decodeBytes("000000000000000000000000000000000000000000000000000000000000000000"))) + ) + }, + existingFeature((x: GroupElement) => x.getEncoded, + "{ (x: GroupElement) => x.getEncoded }", + FuncValue( + Vector((1, SGroupElement)), + MethodCall(ValUse(1, SGroupElement), SGroupElement.getMethodByName("getEncoded"), Vector(), Map()) + ))) } property("decodePoint(GroupElement.getEncoded) equivalence") { verifyCases( - { - val costDetails = TracedCost( - traceBase ++ Array( - FixedCostItem(PropertyCall), - FixedCostItem(MethodDesc(SGroupElement.GetEncodedMethod), FixedCost(JitCost(250))), - FixedCostItem(DecodePoint), - FixedCostItem(ValUse), - FixedCostItem(NamedDesc("EQ_GroupElement"), FixedCost(JitCost(172))) + { + val costDetails = TracedCost( + traceBase ++ Array( + FixedCostItem(PropertyCall), + FixedCostItem(MethodDesc(SGroupElement.GetEncodedMethod), FixedCost(JitCost(250))), + FixedCostItem(DecodePoint), + FixedCostItem(ValUse), + FixedCostItem(NamedDesc("EQ_GroupElement"), FixedCost(JitCost(172))) + ) ) - ) - def success[T](v: T) = Expected(Success(v), 1837, costDetails, 1837) - Seq( - (ge1, success(true)), - (ge2, success(true)), - (ge3, success(true)), - (SigmaDsl.groupGenerator, success(true)), - (SigmaDsl.groupIdentity, success(true)) - ) - }, - existingFeature({ (x: GroupElement) => decodePoint(x.getEncoded) == x }, - "{ (x: GroupElement) => decodePoint(x.getEncoded) == x }", - FuncValue( - Vector((1, SGroupElement)), - EQ( - DecodePoint( - MethodCall.typed[Value[SCollection[SByte.type]]]( - ValUse(1, SGroupElement), - SGroupElement.getMethodByName("getEncoded"), - Vector(), - Map() + def success[T](v: T) = Expected(Success(v), 1837, costDetails, 1837, 2079 +: Seq.fill(3)(2081)) + Seq( + (ge1, success(true)), + (ge2, success(true)), + (ge3, success(true)), + (SigmaDsl.groupGenerator, success(true)), + (SigmaDsl.groupIdentity, success(true)) + ) + }, + existingFeature({ (x: GroupElement) => decodePoint(x.getEncoded) == x }, + "{ (x: GroupElement) => decodePoint(x.getEncoded) == x }", + FuncValue( + Vector((1, SGroupElement)), + EQ( + DecodePoint( + MethodCall.typed[Value[SCollection[SByte.type]]]( + ValUse(1, SGroupElement), + SGroupElement.getMethodByName("getEncoded"), + Vector(), + Map() + ) + ), + ValUse(1, SGroupElement) ) - ), - ValUse(1, SGroupElement) - ) - ))) + ))) } property("GroupElement.negate equivalence") { verifyCases( - { - def success[T](v: T) = Expected(Success(v), 1785, methodCostDetails(SGroupElement.NegateMethod, 45), 1785) - Seq( - (ge1, success(Helpers.decodeGroupElement("02358d53f01276211f92d0aefbd278805121d4ff6eb534b777af1ee8abae5b2056"))), - (ge2, success(Helpers.decodeGroupElement("03dba7b94b111f3894e2f9120b577da595ec7d58d488485adf73bf4e153af63575"))), - (ge3, success(Helpers.decodeGroupElement("0390449814f5671172dd696a61b8aa49aaa4c87013f56165e27d49944e98bc414d"))), - (SigmaDsl.groupGenerator, success(Helpers.decodeGroupElement("0379be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798"))), - (SigmaDsl.groupIdentity, success(Helpers.decodeGroupElement("000000000000000000000000000000000000000000000000000000000000000000"))) - ) - }, - existingFeature({ (x: GroupElement) => x.negate }, - "{ (x: GroupElement) => x.negate }", - FuncValue( - Vector((1, SGroupElement)), - MethodCall(ValUse(1, SGroupElement), SGroupElement.getMethodByName("negate"), Vector(), Map()) - ))) + { + def success[T](v: T) = Expected(Success(v), 1785, methodCostDetails(SGroupElement.NegateMethod, 45), 1785, 2019 +: Seq.fill(3)(2021)) + Seq( + (ge1, success(Helpers.decodeGroupElement("02358d53f01276211f92d0aefbd278805121d4ff6eb534b777af1ee8abae5b2056"))), + (ge2, success(Helpers.decodeGroupElement("03dba7b94b111f3894e2f9120b577da595ec7d58d488485adf73bf4e153af63575"))), + (ge3, success(Helpers.decodeGroupElement("0390449814f5671172dd696a61b8aa49aaa4c87013f56165e27d49944e98bc414d"))), + (SigmaDsl.groupGenerator, success(Helpers.decodeGroupElement("0379be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798"))), + (SigmaDsl.groupIdentity, success(Helpers.decodeGroupElement("000000000000000000000000000000000000000000000000000000000000000000"))) + ) + }, + existingFeature({ (x: GroupElement) => x.negate }, + "{ (x: GroupElement) => x.negate }", + FuncValue( + Vector((1, SGroupElement)), + MethodCall(ValUse(1, SGroupElement), SGroupElement.getMethodByName("negate"), Vector(), Map()) + ))) } property("GroupElement.exp equivalence") { - def cases(cost: Int, details: CostDetails) = { - def success[T](v: T) = Expected(Success(v), cost, details, cost) + def cases(cost: Int, details: CostDetails, expectedV3Costs: Seq[Int]) = { + def success[T](v: T) = Expected(Success(v), cost, details, cost, expectedV3Costs) + Seq( ((ge1, CBigInt(new BigInteger("-25c80b560dd7844e2efd10f80f7ee57d", 16))), success(Helpers.decodeGroupElement("023a850181b7b73f92a5bbfa0bfc78f5bbb6ff00645ddde501037017e1a2251e2e"))), @@ -2798,7 +2854,7 @@ class SigmaDslSpecification extends SigmaDslTesting FixedCostItem(Exponentiate) ) ) - verifyCases(cases(1873, costDetails), + verifyCases(cases(1873, costDetails, 2119 +: Seq.fill(3)(2121)), existingFeature( scalaFunc, script, @@ -2825,7 +2881,7 @@ class SigmaDslSpecification extends SigmaDslTesting FixedCostItem(SGroupElement.ExponentiateMethod, FixedCost(JitCost(900))) ) ) - verifyCases(cases(1873, costDetails), + verifyCases(cases(1873, costDetails, 2119 +: Seq.fill(3)(2121)), existingFeature( scalaFunc, script, @@ -2872,7 +2928,7 @@ class SigmaDslSpecification extends SigmaDslTesting ) ) ) - def success[T](v: T) = Expected(Success(v), 1787, costDetails, 1787) + def success[T](v: T) = Expected(Success(v), 1787, costDetails, 1787, 2029 +: Seq.fill(3)(2031)) Seq( ((ge1, Helpers.decodeGroupElement("03e132ca090614bd6c9f811e91f6daae61f16968a1e6c694ed65aacd1b1092320e")), success(Helpers.decodeGroupElement("02bc48937b4a66f249a32dfb4d2efd0743dc88d46d770b8c5d39fd03325ba211df"))), @@ -2935,7 +2991,7 @@ class SigmaDslSpecification extends SigmaDslTesting } verifyCases( { - def success[T](v: T) = Expected(Success(v), 1767, methodCostDetails(SAvlTree.digestMethod, 15), 1767) + def success[T](v: T) = Expected(Success(v), 1767, methodCostDetails(SAvlTree.digestMethod, 15), 1767, 2001 +: Seq.fill(3)(2003)) Seq( (t1, success(Helpers.decodeBytes("000183807f66b301530120ff7fc6bd6601ff01ff7f7d2bedbbffff00187fe89094"))), (t2, success(Helpers.decodeBytes("ff000d937f80ffd731ed802d24358001ff8080ff71007f00ad37e0a7ae43fff95b"))), @@ -2948,7 +3004,7 @@ class SigmaDslSpecification extends SigmaDslTesting verifyCases( { - def success[T](v: T) = Expected(Success(v), 1765, methodCostDetails(SAvlTree.enabledOperationsMethod, 15), 1765) + def success[T](v: T) = Expected(Success(v), 1765, methodCostDetails(SAvlTree.enabledOperationsMethod, 15), 1765, 1999 +: Seq.fill(3)(2001)) Seq( (t1, success(6.toByte)), (t2, success(0.toByte)), @@ -2961,7 +3017,7 @@ class SigmaDslSpecification extends SigmaDslTesting verifyCases( { - def success[T](v: T) = Expected(Success(v), 1765, methodCostDetails(SAvlTree.keyLengthMethod, 15), 1765) + def success[T](v: T) = Expected(Success(v), 1765, methodCostDetails(SAvlTree.keyLengthMethod, 15), 1765, 1999 +: Seq.fill(3)(2001)) Seq( (t1, success(1)), (t2, success(32)), @@ -2974,11 +3030,11 @@ class SigmaDslSpecification extends SigmaDslTesting verifyCases( { - def success[T](v: T, newCost: Int) = Expected(Success(v), newCost, methodCostDetails(SAvlTree.valueLengthOptMethod, 15), newCost) + def success[T](v: T, newCost: Int, expectedV3Costs: Seq[Int]) = Expected(Success(v), newCost, methodCostDetails(SAvlTree.valueLengthOptMethod, 15), newCost, expectedV3Costs) Seq( - (t1, success(Some(1), 1766)), - (t2, success(Some(64), 1766)), - (t3, success(None, 1765)) + (t1, success(Some(1), 1766, 2000 +: Seq.fill(3)(2002))), + (t2, success(Some(64), 1766, 2000 +: Seq.fill(3)(2002))), + (t3, success(None, 1765, 1999 +: Seq.fill(3)(2001))) ) }, existingFeature((t: AvlTree) => t.valueLengthOpt, @@ -2987,7 +3043,7 @@ class SigmaDslSpecification extends SigmaDslTesting verifyCases( { - def success[T](v: T) = Expected(Success(v), 1765, methodCostDetails(SAvlTree.isInsertAllowedMethod, 15), 1765) + def success[T](v: T) = Expected(Success(v), 1765, methodCostDetails(SAvlTree.isInsertAllowedMethod, 15), 1765, 1999 +: Seq.fill(3)(2001)) Seq( (t1, success(false)), (t2, success(false)), @@ -3000,7 +3056,7 @@ class SigmaDslSpecification extends SigmaDslTesting verifyCases( { - def success[T](v: T) = Expected(Success(v), 1765, methodCostDetails(SAvlTree.isUpdateAllowedMethod, 15), 1765) + def success[T](v: T) = Expected(Success(v), 1765, methodCostDetails(SAvlTree.isUpdateAllowedMethod, 15), 1765, 1999 +: Seq.fill(3)(2001)) Seq( (t1, success(true)), (t2, success(false)), @@ -3013,7 +3069,7 @@ class SigmaDslSpecification extends SigmaDslTesting verifyCases( { - def success[T](v: T) = Expected(Success(v), 1765, methodCostDetails(SAvlTree.isRemoveAllowedMethod, 15), 1765) + def success[T](v: T) = Expected(Success(v), 1765, methodCostDetails(SAvlTree.isRemoveAllowedMethod, 15), 1765, 1999 +: Seq.fill(3)(2001)) Seq( (t1, success(true)), (t2, success(false)), @@ -3268,7 +3324,7 @@ class SigmaDslSpecification extends SigmaDslTesting ) ) - getMany.checkExpected(input, Expected(Success(expRes), 1845, costDetails, 1845)) + getMany.checkExpected(input, Expected(Success(expRes), 1845, costDetails, 1845, 2135 +: Seq.fill(3)(2139))) } val key = Colls.fromArray(Array[Byte](-16,-128,99,86,1,-128,-36,-83,109,72,-124,-114,1,-32,15,127,-30,125,127,1,-102,-53,-53,-128,-107,0,64,8,1,127,22,1)) @@ -3346,8 +3402,9 @@ class SigmaDslSpecification extends SigmaDslTesting // positive test { val input = (tree, (key, proof)) - contains.checkExpected(input, Expected(Success(okContains), 1790, costDetails(105 + additionalDetails), 1790)) - get.checkExpected(input, Expected(Success(valueOpt), 1790 + additionalCost, costDetails(105 + additionalDetails), 1790 + additionalCost)) + val expectedV3Costs: Seq[Int] = 2078 +: Seq.fill(3)(2082) + contains.checkExpected(input, Expected(Success(okContains), 1790, costDetails(105 + additionalDetails), 1790, expectedV3Costs)) + get.checkExpected(input, Expected(Success(valueOpt), 1790 + additionalCost, costDetails(105 + additionalDetails), 1790 + additionalCost, expectedV3Costs.map(additionalCost + _))) } val keys = Colls.fromItems(key) @@ -3355,14 +3412,15 @@ class SigmaDslSpecification extends SigmaDslTesting { val input = (tree, (keys, proof)) - getMany.checkExpected(input, Expected(Success(expRes), 1791 + additionalCost, costDetails(105 + additionalDetails), 1791 + additionalCost)) + val expectedV3Costs: Seq[Int] = (2081 + additionalCost) +: Seq.fill(3)(2085 + additionalCost) + getMany.checkExpected(input, Expected(Success(expRes), 1791 + additionalCost, costDetails(105 + additionalDetails), 1791 + additionalCost, expectedV3Costs)) } { val input = (tree, digest) val (res, _) = updateDigest.checkEquality(input).getOrThrow res.digest shouldBe digest - updateDigest.checkExpected(input, Expected(Success(res), 1771, updateDigestCostDetails, 1771)) + updateDigest.checkExpected(input, Expected(Success(res), 1771, updateDigestCostDetails, 1771, 2027 +: Seq.fill(3)(2029))) } val newOps = 1.toByte @@ -3371,7 +3429,7 @@ class SigmaDslSpecification extends SigmaDslTesting val input = (tree, newOps) val (res,_) = updateOperations.checkEquality(input).getOrThrow res.enabledOperations shouldBe newOps - updateOperations.checkExpected(input, Expected(Success(res), 1771, updateOperationsCostDetails, 1771)) + updateOperations.checkExpected(input, Expected(Success(res), 1771, updateOperationsCostDetails, 1771, 2023 +: Seq.fill(3)(2025))) } // negative tests: invalid proof @@ -3381,7 +3439,7 @@ class SigmaDslSpecification extends SigmaDslTesting val input = (tree, (key, invalidProof)) val (res, _) = contains.checkEquality(input).getOrThrow res shouldBe false - contains.checkExpected(input, Expected(Success(res), 1790, costDetails(105 + additionalDetails), 1790)) + contains.checkExpected(input, Expected(Success(res), 1790, costDetails(105 + additionalDetails), 1790, 2078 +: Seq.fill(3)(2082))) } { @@ -3534,7 +3592,7 @@ class SigmaDslSpecification extends SigmaDslTesting val input = (preInsertTree, (kvs, insertProof)) val (res, _) = insert.checkEquality(input).getOrThrow res.isDefined shouldBe true - insert.checkExpected(input, Expected(Success(res), 1796, costDetails2, 1796)) + insert.checkExpected(input, Expected(Success(res), 1796, costDetails2, 1796, 2098 +: Seq.fill(3)(2102))) } { // negative: readonly tree @@ -3542,7 +3600,7 @@ class SigmaDslSpecification extends SigmaDslTesting val input = (readonlyTree, (kvs, insertProof)) val (res, _) = insert.checkEquality(input).getOrThrow res.isDefined shouldBe false - insert.checkExpected(input, Expected(Success(res), 1772, costDetails1, 1772)) + insert.checkExpected(input, Expected(Success(res), 1772, costDetails1, 1772, 2074 +: Seq.fill(3)(2078))) } { // negative: invalid key @@ -3552,7 +3610,7 @@ class SigmaDslSpecification extends SigmaDslTesting val input = (tree, (invalidKvs, insertProof)) val (res, _) = insert.checkEquality(input).getOrThrow res.isDefined shouldBe true // TODO v6.0: should it really be true? (looks like a bug) (see https://github.com/ScorexFoundation/sigmastate-interpreter/issues/908) - insert.checkExpected(input, Expected(Success(res), 1796, costDetails2, 1796)) + insert.checkExpected(input, Expected(Success(res), 1796, costDetails2, 1796, 2098 +: Seq.fill(3)(2102))) } { // negative: invalid proof @@ -3682,7 +3740,7 @@ class SigmaDslSpecification extends SigmaDslTesting val endTree = preUpdateTree.updateDigest(endDigest) val input = (preUpdateTree, (kvs, updateProof)) val res = Some(endTree) - update.checkExpected(input, Expected(Success(res), 1805, costDetails2, 1805)) + update.checkExpected(input, Expected(Success(res), 1805, costDetails2, 1805, 2107 +: Seq.fill(3)(2111))) } { // positive: update to the same value (identity operation) @@ -3690,13 +3748,13 @@ class SigmaDslSpecification extends SigmaDslTesting val keys = Colls.fromItems((key -> value)) val input = (tree, (keys, updateProof)) val res = Some(tree) - update.checkExpected(input, Expected(Success(res), 1805, costDetails2, 1805)) + update.checkExpected(input, Expected(Success(res), 1805, costDetails2, 1805, 2107 +: Seq.fill(3)(2111))) } { // negative: readonly tree val readonlyTree = createTree(preUpdateDigest) val input = (readonlyTree, (kvs, updateProof)) - update.checkExpected(input, Expected(Success(None), 1772, costDetails1, 1772)) + update.checkExpected(input, Expected(Success(None), 1772, costDetails1, 1772, 2074 +: Seq.fill(3)(2078))) } { // negative: invalid key @@ -3704,7 +3762,7 @@ class SigmaDslSpecification extends SigmaDslTesting val invalidKey = key.map(x => (-x).toByte) // any other different from key val invalidKvs = Colls.fromItems((invalidKey -> newValue)) val input = (tree, (invalidKvs, updateProof)) - update.checkExpected(input, Expected(Success(None), 1801, costDetails3, 1801)) + update.checkExpected(input, Expected(Success(None), 1801, costDetails3, 1801, 2103 +: Seq.fill(3)(2107))) } { // negative: invalid value (different from the value in the proof) @@ -3713,15 +3771,15 @@ class SigmaDslSpecification extends SigmaDslTesting val invalidKvs = Colls.fromItems((key -> invalidValue)) val input = (tree, (invalidKvs, updateProof)) val (res, _) = update.checkEquality(input).getOrThrow - res.isDefined shouldBe true // TODO v6.0: should it really be true? (looks like a bug) (see https://github.com/ScorexFoundation/sigmastate-interpreter/issues/908) - update.checkExpected(input, Expected(Success(res), 1805, costDetails2, 1805)) + res.isDefined shouldBe true // TODO v6.0: should it really be true? (looks like a bug) (see https://github.com/ScorexFoundation/sigmastate-interpreter/issues/908) + update.checkExpected(input, Expected(Success(res), 1805, costDetails2, 1805, 2107 +: Seq.fill(3)(2111))) } { // negative: invalid proof val tree = createTree(preUpdateDigest, updateAllowed = true) val invalidProof = updateProof.map(x => (-x).toByte) // any other different from proof val input = (tree, (kvs, invalidProof)) - update.checkExpected(input, Expected(Success(None), 1801, costDetails3, 1801)) + update.checkExpected(input, Expected(Success(None), 1801, costDetails3, 1801, 2103 +: Seq.fill(3)(2107))) } } @@ -3832,7 +3890,7 @@ class SigmaDslSpecification extends SigmaDslTesting val endTree = preRemoveTree.updateDigest(endDigest) val input = (preRemoveTree, (Colls.fromArray(keysToRemove), removeProof)) val res = Some(endTree) - remove.checkExpected(input, Expected(Success(res), 1832, costDetails1, 1832)) + remove.checkExpected(input, Expected(Success(res), 1832, costDetails1, 1832, 2122 +: Seq.fill(3)(2126))) } { @@ -3849,13 +3907,13 @@ class SigmaDslSpecification extends SigmaDslTesting val endTree = preRemoveTree.updateDigest(endDigest) val input = (preRemoveTree, (keys, removeProof)) val res = Some(endTree) - remove.checkExpected(input, Expected(Success(res), 1806, costDetails2, 1806)) + remove.checkExpected(input, Expected(Success(res), 1806, costDetails2, 1806, 2096 +: Seq.fill(3)(2100))) } { // negative: readonly tree val readonlyTree = createTree(preRemoveDigest) val input = (readonlyTree, (keys, removeProof)) - remove.checkExpected(input, Expected(Success(None), 1772, costDetails3, 1772)) + remove.checkExpected(input, Expected(Success(None), 1772, costDetails3, 1772, 2062 +: Seq.fill(3)(2066))) } { // negative: invalid key @@ -3863,14 +3921,14 @@ class SigmaDslSpecification extends SigmaDslTesting val invalidKey = key.map(x => (-x).toByte) // any other different from `key` val invalidKeys = Colls.fromItems(invalidKey) val input = (tree, (invalidKeys, removeProof)) - remove.checkExpected(input, Expected(Success(None), 1802, costDetails4, 1802)) + remove.checkExpected(input, Expected(Success(None), 1802, costDetails4, 1802, 2092 +: Seq.fill(3)(2096))) } { // negative: invalid proof val tree = createTree(preRemoveDigest, removeAllowed = true) val invalidProof = removeProof.map(x => (-x).toByte) // any other different from `removeProof` val input = (tree, (keys, invalidProof)) - remove.checkExpected(input, Expected(Success(None), 1802, costDetails4, 1802)) + remove.checkExpected(input, Expected(Success(None), 1802, costDetails4, 1802, 2092 +: Seq.fill(3)(2096))) } } } @@ -3879,7 +3937,7 @@ class SigmaDslSpecification extends SigmaDslTesting val costDetails = CostDetails(traceBase :+ FixedCostItem(CompanionDesc(LongToByteArray), FixedCost(JitCost(17)))) verifyCases( { - def success[T](v: T) = Expected(Success(v), 1767, costDetails, 1767) + def success[T](v: T) = Expected(Success(v), 1767, costDetails, 1767, 1997 +: Seq.fill(3)(1999)) Seq( (-9223372036854775808L, success(Helpers.decodeBytes("8000000000000000"))), (-1148502660425090565L, success(Helpers.decodeBytes("f00fb2ea55c579fb"))), @@ -3899,20 +3957,20 @@ class SigmaDslSpecification extends SigmaDslTesting val costDetails = CostDetails(traceBase :+ FixedCostItem(CompanionDesc(ByteArrayToBigInt), FixedCost(JitCost(30)))) verifyCases( { - def success[T](v: T) = Expected(Success(v), 1767, costDetails, 1767) + def success[T](v: T) = Expected(Success(v), 1767, costDetails, 1767, 1997 +: Seq.fill(3)(1999)) Seq( (Helpers.decodeBytes(""), Expected(new NumberFormatException("Zero length BigInteger"))), (Helpers.decodeBytes("00"), - success(CBigInt(new BigInteger("0", 16)))), + success(CBigInt(new BigInteger("0", 16)))), (Helpers.decodeBytes("01"), - success(CBigInt(new BigInteger("1", 16)))), + success(CBigInt(new BigInteger("1", 16)))), (Helpers.decodeBytes("ff"), - success(CBigInt(new BigInteger("-1", 16)))), + success(CBigInt(new BigInteger("-1", 16)))), (Helpers.decodeBytes("80d6c201"), - Expected(Success(CBigInt(new BigInteger("-7f293dff", 16))), 1767, costDetails, 1767)), + Expected(Success(CBigInt(new BigInteger("-7f293dff", 16))), 1767, costDetails, 1767, 1997 +: Seq.fill(3)(1999))), (Helpers.decodeBytes("70d6c20170d6c201"), - Expected(Success(CBigInt(new BigInteger("70d6c20170d6c201", 16))), 1767, costDetails, 1767)), + Expected(Success(CBigInt(new BigInteger("70d6c20170d6c201", 16))), 1767, costDetails, 1767, 1997 +: Seq.fill(3)(1999))), (Helpers.decodeBytes( "80e0ff7f02807fff72807f0a00ff7fb7c57f75c11ba2802970fd250052807fc37f6480ffff007fff18eeba44" ), Expected(new ArithmeticException("BigInteger out of 256 bit range"))) @@ -3927,7 +3985,7 @@ class SigmaDslSpecification extends SigmaDslTesting val costDetails = CostDetails(traceBase :+ FixedCostItem(CompanionDesc(ByteArrayToLong), FixedCost(JitCost(16)))) verifyCases( { - def success[T](v: T) = Expected(Success(v), 1765, costDetails, 1765) + def success[T](v: T) = Expected(Success(v), 1765, costDetails, 1765, 1995 +: Seq.fill(3)(1997)) Seq( (Helpers.decodeBytes(""), Expected(new IllegalArgumentException("array too small: 0 < 8"))), (Helpers.decodeBytes("81"), Expected(new IllegalArgumentException("array too small: 1 < 8"))), @@ -3949,7 +4007,7 @@ class SigmaDslSpecification extends SigmaDslTesting verifyCases( { val costDetails = CostDetails(traceBase :+ FixedCostItem(CompanionDesc(ExtractId), FixedCost(JitCost(12)))) - def success[T](v: T) = Expected(Success(v), 1766, costDetails, 1766) + def success[T](v: T) = Expected(Success(v), 1766, costDetails, 1766, 1996 +: Seq.fill(3)(1998)) Seq( (b1, success(Helpers.decodeBytes("5ee78f30ae4e770e44900a46854e9fecb6b12e8112556ef1cd19aef633b4421e"))), (b2, success(Helpers.decodeBytes("3a0089be265460e29ca47d26e5b55a6f3e3ffaf5b4aed941410a2437913848ad"))) @@ -3962,7 +4020,7 @@ class SigmaDslSpecification extends SigmaDslTesting verifyCases( { val costDetails = CostDetails(traceBase :+ FixedCostItem(CompanionDesc(ExtractAmount), FixedCost(JitCost(8)))) - def success[T](v: T) = Expected(Success(v), 1764, costDetails, 1764) + def success[T](v: T) = Expected(Success(v), 1764, costDetails, 1764, 1994 +: Seq.fill(3)(1996)) Seq( (b1, success(9223372036854775807L)), (b2, success(12345L)) @@ -3975,7 +4033,7 @@ class SigmaDslSpecification extends SigmaDslTesting verifyCases( { val costDetails = CostDetails(traceBase :+ FixedCostItem(CompanionDesc(ExtractScriptBytes), FixedCost(JitCost(10)))) - def success[T](v: T) = Expected(Success(v), 1766, costDetails, 1766) + def success[T](v: T) = Expected(Success(v), 1766, costDetails, 1766, 1996 +: Seq.fill(3)(1998)) Seq( (b1, success(Helpers.decodeBytes( "100108cd0297c44a12f4eb99a85d298fa3ba829b5b42b9f63798c980ece801cc663cc5fc9e7300" @@ -3990,7 +4048,7 @@ class SigmaDslSpecification extends SigmaDslTesting verifyCases( { val costDetails = CostDetails(traceBase :+ FixedCostItem(CompanionDesc(ExtractBytes), FixedCost(JitCost(12)))) - def success[T](v: T) = Expected(Success(v), 1766, costDetails, 1766) + def success[T](v: T) = Expected(Success(v), 1766, costDetails, 1766, 1996 +: Seq.fill(3)(1998)) Seq( (b1, success(Helpers.decodeBytes( "ffffffffffffffff7f100108cd0297c44a12f4eb99a85d298fa3ba829b5b42b9f63798c980ece801cc663cc5fc9e73009fac29026e789ab7b2fffff12280a6cd01557f6fb22b7f80ff7aff8e1f7f15973d7f000180ade204a3ff007f00057600808001ff8f8000019000ffdb806fff7cc0b6015eb37fa600f4030201000e067fc87f7f01ff218301ae8000018008637f0021fb9e00018055486f0b514121016a00ff718080bcb001" @@ -4007,7 +4065,7 @@ class SigmaDslSpecification extends SigmaDslTesting verifyCases( { val costDetails = CostDetails(traceBase :+ FixedCostItem(CompanionDesc(ExtractBytesWithNoRef), FixedCost(JitCost(12)))) - def success[T](v: T) = Expected(Success(v), 1766, costDetails, 1766) + def success[T](v: T) = Expected(Success(v), 1766, costDetails, 1766, 1996 +: Seq.fill(3)(1998)) Seq( (b1, success(Helpers.decodeBytes( "ffffffffffffffff7f100108cd0297c44a12f4eb99a85d298fa3ba829b5b42b9f63798c980ece801cc663cc5fc9e73009fac29026e789ab7b2fffff12280a6cd01557f6fb22b7f80ff7aff8e1f7f15973d7f000180ade204a3ff007f00057600808001ff8f8000019000ffdb806fff7cc0b6015eb37fa600f4030201000e067fc87f7f01ff" @@ -4024,7 +4082,7 @@ class SigmaDslSpecification extends SigmaDslTesting verifyCases( { val costDetails = CostDetails(traceBase :+ FixedCostItem(CompanionDesc(ExtractCreationInfo), FixedCost(JitCost(16)))) - def success[T](v: T) = Expected(Success(v), 1767, costDetails, 1767) + def success[T](v: T) = Expected(Success(v), 1767, costDetails, 1767, 1999 +: Seq.fill(3)(2001)) Seq( (b1, success(( 677407, @@ -4047,8 +4105,8 @@ class SigmaDslSpecification extends SigmaDslTesting b1 -> Expected(Success(Coll[(Coll[Byte], Long)]( (Helpers.decodeBytes("6e789ab7b2fffff12280a6cd01557f6fb22b7f80ff7aff8e1f7f15973d7f0001"), 10000000L), (Helpers.decodeBytes("a3ff007f00057600808001ff8f8000019000ffdb806fff7cc0b6015eb37fa600"), 500L) - ).map(identity)), 1772, methodCostDetails(SBox.tokensMethod, 15), 1772), - b2 -> Expected(Success(Coll[(Coll[Byte], Long)]().map(identity)), 1766, methodCostDetails(SBox.tokensMethod, 15), 1766) + ).map(identity)), 1772, methodCostDetails(SBox.tokensMethod, 15), 1772, 2010 +: Seq.fill(3)(2012)), + b2 -> Expected(Success(Coll[(Coll[Byte], Long)]().map(identity)), 1766, methodCostDetails(SBox.tokensMethod, 15), 1766, 2004 +: Seq.fill(3)(2006)) ), existingFeature({ (x: Box) => x.tokens }, "{ (x: Box) => x.tokens }", @@ -4127,11 +4185,11 @@ class SigmaDslSpecification extends SigmaDslTesting verifyCases( Seq( - (box1, Expected(Success(1024.toShort), 1774, expCostDetails1, 1774)), + (box1, Expected(Success(1024.toShort), 1774, expCostDetails1, 1774, 2038 +: Seq.fill(3)(2042))), (box2, Expected( new InvalidType("Cannot getReg[Short](5): invalid type of value TestValue(1048576) at id=5") )), - (box3, Expected(Success(0.toShort), 1772, expCostDetails2, 1772)) + (box3, Expected(Success(0.toShort), 1772, expCostDetails2, 1772, 2036 +: Seq.fill(3)(2040))) ), existingFeature( { (x: Box) => @@ -4256,10 +4314,10 @@ class SigmaDslSpecification extends SigmaDslTesting verifyCases( Seq( - (box1, Expected(Success(1024), cost = 1785, expCostDetails3, 1785)), - (box2, Expected(Success(1024 * 1024), cost = 1786, expCostDetails4, 1786)), - (box3, Expected(Success(0), cost = 1779, expCostDetails5, 1779)), - (box4, Expected(Success(-1), cost = 1772, expCostDetails2, 1772)) + (box1, Expected(Success(1024), cost = 1785, expCostDetails3, 1785, 2125 +: Seq.fill(3)(2129))), + (box2, Expected(Success(1024 * 1024), cost = 1786, expCostDetails4, 1786, 2126 +: Seq.fill(3)(2130))), + (box3, Expected(Success(0), cost = 1779, expCostDetails5, 1779, 2119 +: Seq.fill(3)(2123))), + (box4, Expected(Success(-1), cost = 1772, expCostDetails2, 1772, 2112 +: Seq.fill(3)(2116))) ), existingFeature( { (x: Box) => @@ -4353,7 +4411,7 @@ class SigmaDslSpecification extends SigmaDslTesting ) verifyCases( Seq( - (box1, Expected(Success(1.toByte), cost = 1770, expCostDetails, 1770)), + (box1, Expected(Success(1.toByte), cost = 1770, expCostDetails, 1770, 2006 +: Seq.fill(3)(2008))), (box2, Expected(new InvalidType("Cannot getReg[Byte](4): invalid type of value Value(Coll(1)) at id=4"))) ), existingFeature((x: Box) => x.R4[Byte].get, @@ -4365,7 +4423,7 @@ class SigmaDslSpecification extends SigmaDslTesting verifyCases( Seq( - (box1, Expected(Success(1024.toShort), cost = 1770, expCostDetails, 1770)), + (box1, Expected(Success(1024.toShort), cost = 1770, expCostDetails, 1770, 2006 +: Seq.fill(3)(2008))), (box2, Expected(new NoSuchElementException("None.get"))) ), existingFeature((x: Box) => x.R5[Short].get, @@ -4377,7 +4435,7 @@ class SigmaDslSpecification extends SigmaDslTesting verifyCases( Seq( - (box1, Expected(Success(1024 * 1024), cost = 1770, expCostDetails, 1770)) + (box1, Expected(Success(1024 * 1024), cost = 1770, expCostDetails, 1770, 2006 +: Seq.fill(3)(2008))) ), existingFeature((x: Box) => x.R6[Int].get, "{ (x: Box) => x.R6[Int].get }", @@ -4388,7 +4446,7 @@ class SigmaDslSpecification extends SigmaDslTesting verifyCases( Seq( - (box1, Expected(Success(1024.toLong), cost = 1770, expCostDetails, 1770)) + (box1, Expected(Success(1024.toLong), cost = 1770, expCostDetails, 1770, 2006 +: Seq.fill(3)(2008))) ), existingFeature((x: Box) => x.R7[Long].get, "{ (x: Box) => x.R7[Long].get }", @@ -4399,7 +4457,7 @@ class SigmaDslSpecification extends SigmaDslTesting verifyCases( Seq( - (box1, Expected(Success(CBigInt(BigInteger.valueOf(222L))), cost = 1770, expCostDetails, 1770)) + (box1, Expected(Success(CBigInt(BigInteger.valueOf(222L))), cost = 1770, expCostDetails, 1770, 2006 +: Seq.fill(3)(2008))) ), existingFeature((x: Box) => x.R8[BigInt].get, "{ (x: Box) => x.R8[BigInt].get }", @@ -4418,10 +4476,10 @@ class SigmaDslSpecification extends SigmaDslTesting None ) )), - cost = 1770, - expCostDetails, - 1770) - )), + cost = 1770, + expCostDetails, + 1770, 2006 +: Seq.fill(3)(2008)) + )), existingFeature((x: Box) => x.R9[AvlTree].get, "{ (x: Box) => x.R9[AvlTree].get }", FuncValue( @@ -4493,35 +4551,35 @@ class SigmaDslSpecification extends SigmaDslTesting verifyCases( - Seq((preH1, Expected(Success(0.toByte), cost = 1765, methodCostDetails(SPreHeader.versionMethod, 10), 1765))), + Seq((preH1, Expected(Success(0.toByte), cost = 1765, methodCostDetails(SPreHeader.versionMethod, 10), 1765, 1999 +: Seq.fill(3)(2001)))), existingPropTest("version", { (x: PreHeader) => x.version })) verifyCases( Seq((preH1, Expected(Success( Helpers.decodeBytes("7fff7fdd6f62018bae0001006d9ca888ff7f56ff8006573700a167f17f2c9f40")), - cost = 1766, methodCostDetails(SPreHeader.parentIdMethod, 10), 1766))), + cost = 1766, methodCostDetails(SPreHeader.parentIdMethod, 10), 1766, 2000 +: Seq.fill(3)(2002)))), existingPropTest("parentId", { (x: PreHeader) => x.parentId })) verifyCases( - Seq((preH1, Expected(Success(6306290372572472443L), cost = 1765, methodCostDetails(SPreHeader.timestampMethod, 10), 1765))), + Seq((preH1, Expected(Success(6306290372572472443L), cost = 1765, methodCostDetails(SPreHeader.timestampMethod, 10), 1765, 1999 +: Seq.fill(3)(2001)))), existingPropTest("timestamp", { (x: PreHeader) => x.timestamp })) verifyCases( - Seq((preH1, Expected(Success(-3683306095029417063L), cost = 1765, methodCostDetails(SPreHeader.nBitsMethod, 10), 1765))), + Seq((preH1, Expected(Success(-3683306095029417063L), cost = 1765, methodCostDetails(SPreHeader.nBitsMethod, 10), 1765, 1999 +: Seq.fill(3)(2001)))), existingPropTest("nBits", { (x: PreHeader) => x.nBits })) verifyCases( - Seq((preH1, Expected(Success(1), cost = 1765, methodCostDetails(SPreHeader.heightMethod, 10), 1765))), + Seq((preH1, Expected(Success(1), cost = 1765, methodCostDetails(SPreHeader.heightMethod, 10), 1765, 1999 +: Seq.fill(3)(2001)))), existingPropTest("height", { (x: PreHeader) => x.height })) verifyCases( Seq((preH1, Expected(Success( Helpers.decodeGroupElement("026930cb9972e01534918a6f6d6b8e35bc398f57140d13eb3623ea31fbd069939b")), - cost = 1782, methodCostDetails(SPreHeader.minerPkMethod, 10), 1782))), + cost = 1782, methodCostDetails(SPreHeader.minerPkMethod, 10), 1782, 2016 +: Seq.fill(3)(2018)))), existingPropTest("minerPk", { (x: PreHeader) => x.minerPk })) verifyCases( - Seq((preH1, Expected(Success(Helpers.decodeBytes("ff8087")), cost = 1766, methodCostDetails(SPreHeader.votesMethod,10), 1766))), + Seq((preH1, Expected(Success(Helpers.decodeBytes("ff8087")), cost = 1766, methodCostDetails(SPreHeader.votesMethod, 10), 1766, 2000 +: Seq.fill(3)(2002)))), existingPropTest("votes", { (x: PreHeader) => x.votes })) } @@ -4529,81 +4587,81 @@ class SigmaDslSpecification extends SigmaDslTesting verifyCases( Seq((h1, Expected(Success( Helpers.decodeBytes("957f008001808080ffe4ffffc8f3802401df40006aa05e017fa8d3f6004c804a")), - cost = 1766, methodCostDetails(SHeader.idMethod, 10), 1766))), + cost = 1766, methodCostDetails(SHeader.idMethod, 10), 1766, 2000 +: Seq.fill(3)(2002)))), existingPropTest("id", { (x: Header) => x.id })) verifyCases( - Seq((h1, Expected(Success(0.toByte), cost = 1765, methodCostDetails(SHeader.versionMethod, 10), 1765))), + Seq((h1, Expected(Success(0.toByte), cost = 1765, methodCostDetails(SHeader.versionMethod, 10), 1765, 1999 +: Seq.fill(3)(2001)))), existingPropTest("version", { (x: Header) => x.version })) verifyCases( Seq((h1, Expected(Success( Helpers.decodeBytes("0180dd805b0000ff5400b997fd7f0b9b00de00fb03c47e37806a8186b94f07ff")), - cost = 1766, methodCostDetails(SHeader.parentIdMethod, 10), 1766))), + cost = 1766, methodCostDetails(SHeader.parentIdMethod, 10), 1766, 2000 +: Seq.fill(3)(2002)))), existingPropTest("parentId", { (x: Header) => x.parentId })) verifyCases( Seq((h1, Expected(Success( Helpers.decodeBytes("01f07f60d100ffb970c3007f60ff7f24d4070bb8fffa7fca7f34c10001ffe39d")), - cost = 1766, methodCostDetails(SHeader.ADProofsRootMethod, 10), 1766))), - existingPropTest("ADProofsRoot", { (x: Header) => x.ADProofsRoot})) + cost = 1766, methodCostDetails(SHeader.ADProofsRootMethod, 10), 1766, 2000 +: Seq.fill(3)(2002)))), + existingPropTest("ADProofsRoot", { (x: Header) => x.ADProofsRoot })) verifyCases( - Seq((h1, Expected(Success(CAvlTree(createAvlTreeData())), cost = 1765, methodCostDetails(SHeader.stateRootMethod, 10), 1765))), + Seq((h1, Expected(Success(CAvlTree(createAvlTreeData())), cost = 1765, methodCostDetails(SHeader.stateRootMethod, 10), 1765, 1999 +: Seq.fill(3)(2001)))), existingPropTest("stateRoot", { (x: Header) => x.stateRoot })) verifyCases( Seq((h1, Expected(Success( Helpers.decodeBytes("804101ff01000080a3ffbd006ac080098df132a7017f00649311ec0e00000100")), - cost = 1766, methodCostDetails(SHeader.transactionsRootMethod, 10), 1766))), + cost = 1766, methodCostDetails(SHeader.transactionsRootMethod, 10), 1766, 2000 +: Seq.fill(3)(2002)))), existingPropTest("transactionsRoot", { (x: Header) => x.transactionsRoot })) verifyCases( - Seq((h1, Expected(Success(1L), cost = 1765, methodCostDetails(SHeader.timestampMethod, 10), 1765))), + Seq((h1, Expected(Success(1L), cost = 1765, methodCostDetails(SHeader.timestampMethod, 10), 1765, 1999 +: Seq.fill(3)(2001)))), existingPropTest("timestamp", { (x: Header) => x.timestamp })) verifyCases( - Seq((h1, Expected(Success(-1L), cost = 1765, methodCostDetails(SHeader.nBitsMethod, 10), 1765))), + Seq((h1, Expected(Success(-1L), cost = 1765, methodCostDetails(SHeader.nBitsMethod, 10), 1765, 1999 +: Seq.fill(3)(2001)))), existingPropTest("nBits", { (x: Header) => x.nBits })) verifyCases( - Seq((h1, Expected(Success(1), cost = 1765, methodCostDetails(SHeader.heightMethod, 10), 1765))), + Seq((h1, Expected(Success(1), cost = 1765, methodCostDetails(SHeader.heightMethod, 10), 1765, 1999 +: Seq.fill(3)(2001)))), existingPropTest("height", { (x: Header) => x.height })) verifyCases( Seq((h1, Expected(Success( Helpers.decodeBytes("e57f80885601b8ff348e01808000bcfc767f2dd37f0d01015030ec018080bc62")), - cost = 1766, methodCostDetails(SHeader.extensionRootMethod, 10), 1766))), + cost = 1766, methodCostDetails(SHeader.extensionRootMethod, 10), 1766, 2000 +: Seq.fill(3)(2002)))), existingPropTest("extensionRoot", { (x: Header) => x.extensionRoot })) verifyCases( Seq((h1, Expected(Success( Helpers.decodeGroupElement("039bdbfa0b49cc6bef58297a85feff45f7bbeb500a9d2283004c74fcedd4bd2904")), - cost = 1782, methodCostDetails(SHeader.minerPkMethod, 10), 1782))), + cost = 1782, methodCostDetails(SHeader.minerPkMethod, 10), 1782, 2016 +: Seq.fill(3)(2018)))), existingPropTest("minerPk", { (x: Header) => x.minerPk })) verifyCases( Seq((h1, Expected(Success( Helpers.decodeGroupElement("0361299207fa392231e23666f6945ae3e867b978e021d8d702872bde454e9abe9c")), - cost = 1782, methodCostDetails(SHeader.powOnetimePkMethod, 10), 1782))), + cost = 1782, methodCostDetails(SHeader.powOnetimePkMethod, 10), 1782, 2016 +: Seq.fill(3)(2018)))), existingPropTest("powOnetimePk", { (x: Header) => x.powOnetimePk })) verifyCases( Seq((h1, Expected(Success( Helpers.decodeBytes("7f4f09012a807f01")), - cost = 1766, methodCostDetails(SHeader.powNonceMethod, 10), 1766))), + cost = 1766, methodCostDetails(SHeader.powNonceMethod, 10), 1766, 2000 +: Seq.fill(3)(2002)))), existingPropTest("powNonce", { (x: Header) => x.powNonce })) verifyCases( Seq((h1, Expected(Success( CBigInt(new BigInteger("-e24990c47e15ed4d0178c44f1790cc72155d516c43c3e8684e75db3800a288", 16))), - cost = 1765, methodCostDetails(SHeader.powDistanceMethod, 10), 1765))), + cost = 1765, methodCostDetails(SHeader.powDistanceMethod, 10), 1765, 1999 +: Seq.fill(3)(2001)))), existingPropTest("powDistance", { (x: Header) => x.powDistance })) verifyCases( Seq((h1, Expected(Success( Helpers.decodeBytes("7f0180")), - cost = 1766, methodCostDetails(SHeader.votesMethod, 10), 1766))), + cost = 1766, methodCostDetails(SHeader.votesMethod, 10), 1766, 2000 +: Seq.fill(3)(2002)))), existingPropTest("votes", { (x: Header) => x.votes })) } @@ -4817,7 +4875,7 @@ class SigmaDslSpecification extends SigmaDslTesting val costDetails = TracedCost(testTraceBase) verifyCases( Seq( - (ctx, Expected(Success(dataBox), cost = 1769, costDetails, 1769)), + (ctx, Expected(Success(dataBox), cost = 1769, costDetails, 1769, 2015 +: Seq.fill(3)(2017))), (ctx.copy(_dataInputs = Coll()), Expected(new ArrayIndexOutOfBoundsException("0"))) ), existingFeature({ (x: Context) => x.dataInputs(0) }, @@ -4842,7 +4900,7 @@ class SigmaDslSpecification extends SigmaDslTesting Seq( (ctx, Expected(Success( Helpers.decodeBytes("7da4b55971f19a78d007638464580f91a020ab468c0dbe608deb1f619e245bc3")), - cost = 1772, idCostDetails, 1772)) + cost = 1772, idCostDetails, 1772, 2020 +: Seq.fill(3)(2022))) ), existingFeature({ (x: Context) => x.dataInputs(0).id }, "{ (x: Context) => x.dataInputs(0).id }", @@ -4903,7 +4961,7 @@ class SigmaDslSpecification extends SigmaDslTesting ) ) verifyCases( - Seq(ctx -> Expected(Success(ctx.HEIGHT), cost = 1766, heightCostDetails, 1766)), + Seq(ctx -> Expected(Success(ctx.HEIGHT), cost = 1766, heightCostDetails, 1766, 1992 +: Seq.fill(3)(1994))), existingFeature( { (x: Context) => x.HEIGHT }, "{ (x: Context) => x.HEIGHT }", @@ -4940,7 +4998,7 @@ class SigmaDslSpecification extends SigmaDslTesting )) verifyCases( - Seq((ctx, Expected(Success(Coll[Long](80946L)), cost = 1770, inputsCostDetails1, 1770))), + Seq((ctx, Expected(Success(Coll[Long](80946L)), cost = 1770, inputsCostDetails1, 1770, 2012 +: Seq.fill(3)(2014)))), existingFeature( { (x: Context) => x.INPUTS.map { (b: Box) => b.value } }, "{ (x: Context) => x.INPUTS.map { (b: Box) => b.value } }", @@ -5000,7 +5058,7 @@ class SigmaDslSpecification extends SigmaDslTesting ) ) verifyCases( - Seq((ctx, Expected(Success(Coll((80946L, 80946L))), cost = 1774, inputsCostDetails2, 1774))), + Seq((ctx, Expected(Success(Coll((80946L, 80946L))), cost = 1774, inputsCostDetails2, 1774, 2038 +: Seq.fill(3)(2042)))), existingFeature( { (x: Context) => x.INPUTS.map { (b: Box) => (b.value, b.value) } }, """{ (x: Context) => @@ -5092,8 +5150,15 @@ class SigmaDslSpecification extends SigmaDslTesting expectedDetails = CostDetails.ZeroCost, newCost = 1766, newVersionedResults = { + val expectedV3Costs = 2000 +: Seq.fill(3)(2002) + // V3 activation will have different costs due to deserialization cost + val costs = if (activatedVersionInTests >= 3) { + expectedV3Costs + } else { + Seq.fill(4)(1766) + } val res = (ExpectedResult(Success(0), Some(1766)) -> Some(selfCostDetails)) - Seq(0, 1, 2).map(version => version -> res) + Seq(0, 1, 2, 3).map(version => version -> (ExpectedResult(Success(0), Some(costs(version))) -> Some(selfCostDetails))) })) ), changedFeature({ (x: Context) => x.selfBoxIndex }, @@ -5122,7 +5187,7 @@ class SigmaDslSpecification extends SigmaDslTesting } verifyCases( - Seq(ctx -> Expected(Success(ctx.LastBlockUtxoRootHash), cost = 1766, methodCostDetails(SContext.lastBlockUtxoRootHashMethod, 15), 1766)), + Seq(ctx -> Expected(Success(ctx.LastBlockUtxoRootHash), cost = 1766, methodCostDetails(SContext.lastBlockUtxoRootHashMethod, 15), 1766, 2000 +: Seq.fill(3)(2002))), existingPropTest("LastBlockUtxoRootHash", { (x: Context) => x.LastBlockUtxoRootHash }), preGeneratedSamples = Some(samples)) @@ -5135,7 +5200,7 @@ class SigmaDslSpecification extends SigmaDslTesting ) ) verifyCases( - Seq(ctx -> Expected(Success(ctx.LastBlockUtxoRootHash.isUpdateAllowed), cost = 1767, isUpdateAllowedCostDetails, 1767)), + Seq(ctx -> Expected(Success(ctx.LastBlockUtxoRootHash.isUpdateAllowed), cost = 1767, isUpdateAllowedCostDetails, 1767, 2007 +: Seq.fill(3)(2009))), existingFeature( { (x: Context) => x.LastBlockUtxoRootHash.isUpdateAllowed }, "{ (x: Context) => x.LastBlockUtxoRootHash.isUpdateAllowed }", @@ -5156,7 +5221,7 @@ class SigmaDslSpecification extends SigmaDslTesting preGeneratedSamples = Some(samples)) verifyCases( - Seq(ctx -> Expected(Success(ctx.minerPubKey), cost = 1767, methodCostDetails(SContext.minerPubKeyMethod, 20), 1767)), + Seq(ctx -> Expected(Success(ctx.minerPubKey), cost = 1767, methodCostDetails(SContext.minerPubKeyMethod, 20), 1767, 2001 +: Seq.fill(3)(2003))), existingPropTest("minerPubKey", { (x: Context) => x.minerPubKey }), preGeneratedSamples = Some(samples)) @@ -5196,7 +5261,7 @@ class SigmaDslSpecification extends SigmaDslTesting FixedCostItem(GetVar), FixedCostItem(OptionGet))) verifyCases( - Seq((ctx, Expected(Success(true), cost = 1765, getVarCostDetails, 1765))), + Seq((ctx, Expected(Success(true), cost = 1765, getVarCostDetails, 1765, 1997 +: Seq.fill(3)(1999)))), existingFeature((x: Context) => x.getVar[Boolean](11).get, "{ (x: Context) => getVar[Boolean](11).get }", FuncValue(Vector((1, SContext)), OptionGet(GetVar(11.toByte, SOption(SBoolean))))), @@ -5230,7 +5295,7 @@ class SigmaDslSpecification extends SigmaDslTesting ) verifyCases( Seq( - ctx -> Expected(Success(-135729055492651903L), 1779, registerIsDefinedCostDetails, 1779) + ctx -> Expected(Success(-135729055492651903L), 1779, registerIsDefinedCostDetails, 1779, 2061 +: Seq.fill(3)(2065)) ), existingFeature( { (x: Context) => @@ -5292,7 +5357,14 @@ class SigmaDslSpecification extends SigmaDslTesting Seq( ctx -> Expected(Failure(expectedError), 0, CostDetails.ZeroCost, 1793, newVersionedResults = { - Seq.tabulate(3)(v => v -> (ExpectedResult(Success(true), Some(1793)) -> None)) + val expectedV3Costs = 2117 +: Seq.fill(3)(2121) + // V3 activation will have different costs due to deserialization cost + val costs = if (activatedVersionInTests >= 3) { + expectedV3Costs + } else { + Seq.fill(4)(1793) + } + Seq.tabulate(4)(v => v -> (ExpectedResult(Success(true), Some(costs(v))) -> None)) } ) ), @@ -5458,12 +5530,12 @@ class SigmaDslSpecification extends SigmaDslTesting ) verifyCases( Seq( - ctx -> Expected(Success(5008366408131208436L), 1791, registerTagCostDetails1, 1791), + ctx -> Expected(Success(5008366408131208436L), 1791, registerTagCostDetails1, 1791, 2149 +: Seq.fill(3)(2153)), ctxWithRegsInOutput(ctx, Map( ErgoBox.R5 -> LongConstant(0L), - ErgoBox.R4 -> ShortConstant(10))) -> Expected(Success(10L), 1790, registerTagCostDetails2, 1790), + ErgoBox.R4 -> ShortConstant(10))) -> Expected(Success(10L), 1790, registerTagCostDetails2, 1790, 2148 +: Seq.fill(3)(2152)), ctxWithRegsInOutput(ctx, Map( - ErgoBox.R4 -> ShortConstant(10))) -> Expected(Success(-1L), 1777, registerTagCostDetails3, 1777) + ErgoBox.R4 -> ShortConstant(10))) -> Expected(Success(-1L), 1777, registerTagCostDetails3, 1777, 2135 +: Seq.fill(3)(2139)) ), existingFeature( { (x: Context) => @@ -5666,22 +5738,22 @@ class SigmaDslSpecification extends SigmaDslTesting verifyCases( Seq( // case 1L - ctx -> Expected(Success(5008366408131289382L), 1794, tagRegisterCostDetails1, 1794), + ctx -> Expected(Success(5008366408131289382L), 1794, tagRegisterCostDetails1, 1794, 2164 +: Seq.fill(3)(2168)), // case 0L ctxWithRegsInOutput(ctx, Map( ErgoBox.R5 -> LongConstant(0L), - ErgoBox.R4 -> ShortConstant(10))) -> Expected(Success(80956L), 1793, tagRegisterCostDetails2, 1793), + ErgoBox.R4 -> ShortConstant(10))) -> Expected(Success(80956L), 1793, tagRegisterCostDetails2, 1793, 2163 +: Seq.fill(3)(2167)), // case returning 0L ctxWithRegsInOutput(ctx, Map( ErgoBox.R5 -> LongConstant(2L), // note R4 is required to avoid // "RuntimeException: Set of non-mandatory indexes is not densely packed" - ErgoBox.R4 -> ShortConstant(10))) -> Expected(Success(0L), 1784, tagRegisterCostDetails3, 1784), + ErgoBox.R4 -> ShortConstant(10))) -> Expected(Success(0L), 1784, tagRegisterCostDetails3, 1784, 2154 +: Seq.fill(3)(2158)), // case returning -1L ctxWithRegsInOutput(ctx, Map( - ErgoBox.R4 -> ShortConstant(10))) -> Expected(Success(-1L), 1777, tagRegisterCostDetails4, 1777) + ErgoBox.R4 -> ShortConstant(10))) -> Expected(Success(-1L), 1777, tagRegisterCostDetails4, 1777, 2147 +: Seq.fill(3)(2151)) ), existingFeature( { (x: Context) => @@ -5899,15 +5971,15 @@ class SigmaDslSpecification extends SigmaDslTesting Seq( ctxWithRegsInDataInput(ctx, Map( ErgoBox.R5 -> LongConstant(1L), - ErgoBox.R4 -> LongConstant(10))) -> Expected(Success(10L), 1792, tagRegisterCostDetails1, 1792), + ErgoBox.R4 -> LongConstant(10))) -> Expected(Success(10L), 1792, tagRegisterCostDetails1, 1792, 2158 +: Seq.fill(3)(2162)), ctxWithRegsInDataInput(ctx, Map( ErgoBox.R5 -> LongConstant(0L), - ErgoBox.R4 -> ShortConstant(10))) -> Expected(Success(10L), 1791, tagRegisterCostDetails2, 1791), + ErgoBox.R4 -> ShortConstant(10))) -> Expected(Success(10L), 1791, tagRegisterCostDetails2, 1791, 2157 +: Seq.fill(3)(2161)), ctxWithRegsInDataInput(ctx, Map( ErgoBox.R5 -> LongConstant(2L), - ErgoBox.R4 -> ShortConstant(10))) -> Expected(Success(0L), 1786, tagRegisterCostDetails3, 1786), + ErgoBox.R4 -> ShortConstant(10))) -> Expected(Success(0L), 1786, tagRegisterCostDetails3, 1786, 2152 +: Seq.fill(3)(2156)), ctxWithRegsInDataInput(ctx, Map( - ErgoBox.R4 -> ShortConstant(10))) -> Expected(Success(-1L), 1779, tagRegisterCostDetails4, 1779) + ErgoBox.R4 -> ShortConstant(10))) -> Expected(Success(-1L), 1779, tagRegisterCostDetails4, 1779, 2145 +: Seq.fill(3)(2149)) ), existingFeature( { (x: Context) => @@ -6132,15 +6204,15 @@ class SigmaDslSpecification extends SigmaDslTesting Seq( ctxWithRegsInDataInput(ctx, Map( ErgoBox.R5 -> LongConstant(1L), - ErgoBox.R4 -> LongConstant(10))) -> Expected(Success(80956L), 1796, costDetails1, 1796), + ErgoBox.R4 -> LongConstant(10))) -> Expected(Success(80956L), 1796, costDetails1, 1796, 2174 +: Seq.fill(3)(2178)), ctxWithRegsInDataInput(ctx, Map( ErgoBox.R5 -> LongConstant(0L), - ErgoBox.R4 -> ShortConstant(10))) -> Expected(Success(80956L), 1794, costDetails2, 1794), + ErgoBox.R4 -> ShortConstant(10))) -> Expected(Success(80956L), 1794, costDetails2, 1794, 2172 +: Seq.fill(3)(2176)), ctxWithRegsInDataInput(ctx, Map( ErgoBox.R5 -> LongConstant(2L), - ErgoBox.R4 -> ShortConstant(10))) -> Expected(Success(0L), 1786, costDetails3, 1786), + ErgoBox.R4 -> ShortConstant(10))) -> Expected(Success(0L), 1786, costDetails3, 1786, 2164 +: Seq.fill(3)(2168)), ctxWithRegsInDataInput(ctx, Map( - ErgoBox.R4 -> ShortConstant(10))) -> Expected(Success(-1L), 1779, costDetails4, 1779) + ErgoBox.R4 -> ShortConstant(10))) -> Expected(Success(-1L), 1779, costDetails4, 1779, 2157 +: Seq.fill(3)(2161)) ), existingFeature( { (x: Context) => @@ -6245,7 +6317,15 @@ class SigmaDslSpecification extends SigmaDslTesting cost = c, expectedDetails = CostDetails.ZeroCost, newCost = 1766, - newVersionedResults = Seq(0, 1, 2).map(i => i -> (ExpectedResult(Success(newV), Some(1766)) -> Some(cd))) + newVersionedResults = { + val costs = if (activatedVersionInTests >= 3) { + 1996 +: Seq.fill(3)(1998) + } + else { + Seq.fill(4)(1766) + } + Seq.tabulate(4)(i => i -> (ExpectedResult(Success(newV), Some(costs(i))) -> Some(cd))) + } ) Seq( (Coll[Boolean](), successNew(false, 1766, newV = false, costDetails(0))), @@ -6280,8 +6360,8 @@ class SigmaDslSpecification extends SigmaDslTesting val costDetails = TracedCost(traceBase :+ FixedCostItem(LogicalNot)) verifyCases( Seq( - (true, Expected(Success(false), 1765, costDetails, 1765)), - (false, Expected(Success(true), 1765, costDetails, 1765))), + (true, Expected(Success(false), 1765, costDetails, 1765, 1995 +: Seq.fill(3)(1997))), + (false, Expected(Success(true), 1765, costDetails, 1765, 1995 +: Seq.fill(3)(1997)))), existingFeature((x: Boolean) => !x, "{ (x: Boolean) => !x }", FuncValue(Vector((1, SBoolean)), LogicalNot(ValUse(1, SBoolean))))) @@ -6291,7 +6371,8 @@ class SigmaDslSpecification extends SigmaDslTesting val costDetails = TracedCost(traceBase :+ FixedCostItem(Negation)) verifyCases( { - def success[T](v: T) = Expected(Success(v), 1766, costDetails, 1766) + def success[T](v: T) = Expected(Success(v), 1766, costDetails, 1766, 1996 +: Seq.fill(3)(1998)) + Seq( (Byte.MinValue, success(Byte.MinValue)), // !!! ((Byte.MinValue + 1).toByte, success(Byte.MaxValue)), @@ -6310,7 +6391,7 @@ class SigmaDslSpecification extends SigmaDslTesting verifyCases( { - def success[T](v: T) = Expected(Success(v), 1766, costDetails, 1766) + def success[T](v: T) = Expected(Success(v), 1766, costDetails, 1766, 1996 +: Seq.fill(3)(1998)) Seq( (Short.MinValue, success(Short.MinValue)), // special case! ((Short.MinValue + 1).toShort, success(Short.MaxValue)), @@ -6328,7 +6409,8 @@ class SigmaDslSpecification extends SigmaDslTesting verifyCases( { - def success[T](v: T) = Expected(Success(v), 1766, costDetails, 1766) + def success[T](v: T) = Expected(Success(v), 1766, costDetails, 1766, 1996 +: Seq.fill(3)(1998)) + Seq( (Int.MinValue, success(Int.MinValue)), // special case! (Int.MinValue + 1, success(Int.MaxValue)), @@ -6345,7 +6427,8 @@ class SigmaDslSpecification extends SigmaDslTesting verifyCases( { - def success[T](v: T) = Expected(Success(v), 1766, costDetails, 1766) + def success[T](v: T) = Expected(Success(v), 1766, costDetails, 1766, 1996 +: Seq.fill(3)(1998)) + Seq( (Long.MinValue, success(Long.MinValue)), // special case! (Long.MinValue + 1, success(Long.MaxValue)), @@ -6362,7 +6445,8 @@ class SigmaDslSpecification extends SigmaDslTesting verifyCases( { - def success[T](v: T) = Expected(Success(v), 1767, costDetails, 1767) + def success[T](v: T) = Expected(Success(v), 1767, costDetails, 1767, 1997 +: Seq.fill(3)(1999)) + Seq( (CBigInt(new BigInteger("-1655a05845a6ad363ac88ea21e88b97e436a1f02c548537e12e2d9667bf0680", 16)), success(CBigInt(new BigInteger("1655a05845a6ad363ac88ea21e88b97e436a1f02c548537e12e2d9667bf0680", 16)))), (CBigInt(new BigInteger("-1b24ba8badba8abf347cce054d9b9f14f229321507245b8", 16)), success(CBigInt(new BigInteger("1b24ba8badba8abf347cce054d9b9f14f229321507245b8", 16)))), @@ -6400,7 +6484,7 @@ class SigmaDslSpecification extends SigmaDslTesting ) verifyCases( { - def success[T](v: T) = Expected(Success(v), 1782, costDetails, 1782) + def success[T](v: T) = Expected(Success(v), 1782, costDetails, 1782, 2014 +: Seq.fill(3)(2016)) Seq( (-1, success(Helpers.decodeGroupElement("0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798"))), (1, success(Helpers.decodeGroupElement("0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798")))) @@ -6419,7 +6503,7 @@ class SigmaDslSpecification extends SigmaDslTesting verifyCases( { - def success[T](v: T) = Expected(Success(v), 1782, costDetails, 1782) + def success[T](v: T) = Expected(Success(v), 1782, costDetails, 1782, 2014 +: Seq.fill(3)(2016)) Seq( (-1, success(Helpers.decodeGroupElement("0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798"))), (1, success(Helpers.decodeGroupElement("0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798")))) @@ -6444,37 +6528,38 @@ class SigmaDslSpecification extends SigmaDslTesting ) ) verifyCases( - { - def success[T](v: T) = Expected(Success(v), 1872, expCostDetails, 1872) - Seq( - (CBigInt(new BigInteger("-e5c1a54694c85d644fa30a6fc5f3aa209ed304d57f72683a0ebf21038b6a9d", 16)), success(Helpers.decodeGroupElement("023395bcba3d7cf21d73c50f8af79d09a8c404c15ce9d04f067d672823bae91a54"))), - (CBigInt(new BigInteger("-bc2d08f935259e0eebf272c66c6e1dbd484c6706390215", 16)), success(Helpers.decodeGroupElement("02ddcf4c48105faf3c16f7399b5dbedd82ab0bb50ae292d8f88f49a3f86e78974e"))), - (CBigInt(new BigInteger("-35cbe9a7a652e5fe85f735ee9909fdd8", 16)), success(Helpers.decodeGroupElement("03b110ec9c7a8c20ed873818e976a0e96e5a17be979d3422d59b362de2a3ae043e"))), - (CBigInt(new BigInteger("-3f05ffca6bd4b15c", 16)), success(Helpers.decodeGroupElement("02acf2657d0714cef8d65ae15c362faa09c0934c0bce872a23398e564c090b85c8"))), - (CBigInt(new BigInteger("-80000001", 16)), success(Helpers.decodeGroupElement("0391b418fd1778356ce947a5cbb46539fd29842aea168486fae91fc5317177a575"))), - (CBigInt(new BigInteger("-80000000", 16)), success(Helpers.decodeGroupElement("025318f9b1a2697010c5ac235e9af475a8c7e5419f33d47b18d33feeb329eb99a4"))), - (CBigInt(new BigInteger("-1", 16)), success(Helpers.decodeGroupElement("0379be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798"))), - (CBigInt(new BigInteger("0", 16)), success(Helpers.decodeGroupElement("000000000000000000000000000000000000000000000000000000000000000000"))), - (CBigInt(new BigInteger("1", 16)), success(Helpers.decodeGroupElement("0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798"))), - (CBigInt(new BigInteger("80000000", 16)), success(Helpers.decodeGroupElement("035318f9b1a2697010c5ac235e9af475a8c7e5419f33d47b18d33feeb329eb99a4"))), - (CBigInt(new BigInteger("1251b7fcd8a01e95", 16)), success(Helpers.decodeGroupElement("030fde7238b8dddfafab8f5481dc17b880505d6bacbe3cdf2ce975afdcadf66354"))), - (CBigInt(new BigInteger("12f6bd76d8fe1d035bdb14bf2f696e52", 16)), success(Helpers.decodeGroupElement("028f2ccf13669461cb3cfbea281e2db08fbb67b38493a1628855203d3f69b82763"))), - (CBigInt(new BigInteger("102bb404f5e36bdba004fdefa34df8cfa02e7912f3caf79", 16)), success(Helpers.decodeGroupElement("03ce82f431d115d45ad555084f8b2861ce5c4561d154e931e9f778594896e46a25")))) - }, - existingFeature({ (n: BigInt) => SigmaDsl.groupGenerator.exp(n) }, - "{ (n: BigInt) => groupGenerator.exp(n) }", - FuncValue( - Vector((1, SBigInt)), - Exponentiate( - MethodCall.typed[Value[SGroupElement.type]]( - Global, - SGlobal.getMethodByName("groupGenerator"), - Vector(), - Map() - ), - ValUse(1, SBigInt) - ) - ))) + { + def success[T](v: T) = Expected(Success(v), 1872, expCostDetails, 1872, 2110 +: Seq.fill(3)(2112)) + + Seq( + (CBigInt(new BigInteger("-e5c1a54694c85d644fa30a6fc5f3aa209ed304d57f72683a0ebf21038b6a9d", 16)), success(Helpers.decodeGroupElement("023395bcba3d7cf21d73c50f8af79d09a8c404c15ce9d04f067d672823bae91a54"))), + (CBigInt(new BigInteger("-bc2d08f935259e0eebf272c66c6e1dbd484c6706390215", 16)), success(Helpers.decodeGroupElement("02ddcf4c48105faf3c16f7399b5dbedd82ab0bb50ae292d8f88f49a3f86e78974e"))), + (CBigInt(new BigInteger("-35cbe9a7a652e5fe85f735ee9909fdd8", 16)), success(Helpers.decodeGroupElement("03b110ec9c7a8c20ed873818e976a0e96e5a17be979d3422d59b362de2a3ae043e"))), + (CBigInt(new BigInteger("-3f05ffca6bd4b15c", 16)), success(Helpers.decodeGroupElement("02acf2657d0714cef8d65ae15c362faa09c0934c0bce872a23398e564c090b85c8"))), + (CBigInt(new BigInteger("-80000001", 16)), success(Helpers.decodeGroupElement("0391b418fd1778356ce947a5cbb46539fd29842aea168486fae91fc5317177a575"))), + (CBigInt(new BigInteger("-80000000", 16)), success(Helpers.decodeGroupElement("025318f9b1a2697010c5ac235e9af475a8c7e5419f33d47b18d33feeb329eb99a4"))), + (CBigInt(new BigInteger("-1", 16)), success(Helpers.decodeGroupElement("0379be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798"))), + (CBigInt(new BigInteger("0", 16)), success(Helpers.decodeGroupElement("000000000000000000000000000000000000000000000000000000000000000000"))), + (CBigInt(new BigInteger("1", 16)), success(Helpers.decodeGroupElement("0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798"))), + (CBigInt(new BigInteger("80000000", 16)), success(Helpers.decodeGroupElement("035318f9b1a2697010c5ac235e9af475a8c7e5419f33d47b18d33feeb329eb99a4"))), + (CBigInt(new BigInteger("1251b7fcd8a01e95", 16)), success(Helpers.decodeGroupElement("030fde7238b8dddfafab8f5481dc17b880505d6bacbe3cdf2ce975afdcadf66354"))), + (CBigInt(new BigInteger("12f6bd76d8fe1d035bdb14bf2f696e52", 16)), success(Helpers.decodeGroupElement("028f2ccf13669461cb3cfbea281e2db08fbb67b38493a1628855203d3f69b82763"))), + (CBigInt(new BigInteger("102bb404f5e36bdba004fdefa34df8cfa02e7912f3caf79", 16)), success(Helpers.decodeGroupElement("03ce82f431d115d45ad555084f8b2861ce5c4561d154e931e9f778594896e46a25")))) + }, + existingFeature({ (n: BigInt) => SigmaDsl.groupGenerator.exp(n) }, + "{ (n: BigInt) => groupGenerator.exp(n) }", + FuncValue( + Vector((1, SBigInt)), + Exponentiate( + MethodCall.typed[Value[SGroupElement.type]]( + Global, + SGlobal.getMethodByName("groupGenerator"), + Vector(), + Map() + ), + ValUse(1, SBigInt) + ) + ))) } } @@ -6510,7 +6595,7 @@ class SigmaDslSpecification extends SigmaDslTesting verifyCases( { - def success[T](v: T, cd: CostDetails) = Expected(Success(v), 1769, cd, 1769) + def success[T](v: T, cd: CostDetails) = Expected(Success(v), 1769, cd, 1769, 2019 +: Seq.fill(3)(2021)) Seq( ((Helpers.decodeBytes(""), Helpers.decodeBytes("")), success(Helpers.decodeBytes(""), costDetails(0))), ((Helpers.decodeBytes("01"), Helpers.decodeBytes("01")), success(Helpers.decodeBytes("00"), costDetails(1))), @@ -6521,9 +6606,16 @@ class SigmaDslSpecification extends SigmaDslTesting cost = 0, expectedDetails = CostDetails.ZeroCost, newCost = 1769, - newVersionedResults = { - val res = (ExpectedResult(Success(Helpers.decodeBytes("00")), Some(1769)), Some(costDetails(1))) - Seq(0, 1, 2).map(version => version -> res) + newVersionedResults = { + val costs = if (activatedVersionInTests >= 3) { + 2019 +: Seq.fill(3)(2021) + } else { + Seq.fill(4)(1769) + } + Seq.tabulate(4) { version => + val res = (ExpectedResult(Success(Helpers.decodeBytes("00")), Some(costs(version))), Some(costDetails(1))) + version -> res + } } )), ((Helpers.decodeBytes("800136fe89afff802acea67128a0ff007fffe3498c8001806080012b"), @@ -6665,11 +6757,11 @@ class SigmaDslSpecification extends SigmaDslTesting ) verifyCases( { - def success[T](v: T, c: Int, costDetails: CostDetails, newCost: Int) = Expected(Success(v), c, costDetails, newCost) + def success[T](v: T, c: Int, costDetails: CostDetails, newCost: Int, expectedV3Costs: Seq[Int]) = Expected(Success(v), c, costDetails, newCost, expectedV3Costs) Seq( - (Coll[Box](), success(Coll[Box](), 1767, costDetails, 1767)), - (Coll[Box](b1), success(Coll[Box](), 1772, costDetails2, 1772)), - (Coll[Box](b1, b2), success(Coll[Box](b2), 1776, costDetails3, 1776)) + (Coll[Box](), success(Coll[Box](), 1767, costDetails, 1767, 2027 +: Seq.fill(3)(2031))), + (Coll[Box](b1), success(Coll[Box](), 1772, costDetails2, 1772, 2032 +: Seq.fill(3)(2036))), + (Coll[Box](b1, b2), success(Coll[Box](b2), 1776, costDetails3, 1776, 2036 +: Seq.fill(3)(2040))) ) }, existingFeature({ (x: Coll[Box]) => x.filter({ (b: Box) => b.value > 1 }) }, @@ -6722,13 +6814,13 @@ class SigmaDslSpecification extends SigmaDslTesting verifyCases( { Seq( - (Coll[Box](), Expected(Success(Coll[Byte]()), 1773, costDetails1, 1773)), + (Coll[Box](), Expected(Success(Coll[Byte]()), 1773, costDetails1, 1773, 2027 +: Seq.fill(3)(2029))), (Coll[Box](b1), Expected(Success(Helpers.decodeBytes( "0008ce02c1a9311ecf1e76c787ba4b1c0e10157b4f6d1e4db3ef0d84f411c99f2d4d2c5b027d1bd9a437e73726ceddecc162e5c85f79aee4798505bc826b8ad1813148e4190257cff6d06fe15d1004596eeb97a7f67755188501e36adc49bd807fe65e9d8281033c6021cff6ba5fdfc4f1742486030d2ebbffd9c9c09e488792f3102b2dcdabd5" - )), 1791, costDetails2, 1791)), + )), 1791, costDetails2, 1791, 2045 +: Seq.fill(3)(2047))), (Coll[Box](b1, b2), Expected(Success(Helpers.decodeBytes( "0008ce02c1a9311ecf1e76c787ba4b1c0e10157b4f6d1e4db3ef0d84f411c99f2d4d2c5b027d1bd9a437e73726ceddecc162e5c85f79aee4798505bc826b8ad1813148e4190257cff6d06fe15d1004596eeb97a7f67755188501e36adc49bd807fe65e9d8281033c6021cff6ba5fdfc4f1742486030d2ebbffd9c9c09e488792f3102b2dcdabd500d197830201010096850200" - )), 1795, costDetails3, 1795)) + )), 1795, costDetails3, 1795, 2049 +: Seq.fill(3)(2051))) ) }, existingFeature({ (x: Coll[Box]) => x.flatMap({ (b: Box) => b.propositionBytes }) }, @@ -6761,11 +6853,12 @@ class SigmaDslSpecification extends SigmaDslTesting verifyCases( { - def success[T](v: T, c: Int, cd: CostDetails, nc: Int) = Expected(Success(v), c, cd, nc) + def success[T](v: T, c: Int, cd: CostDetails, nc: Int, v3Costs: Seq[Int]) = Expected(Success(v), c, cd, nc, v3Costs) + Seq( - (Coll[Box](), success(Coll[(Box, Box)](), 1766, costDetails(0), 1766)), - (Coll[Box](b1), success(Coll[(Box, Box)]((b1, b1)), 1768, costDetails(1), 1768)), - (Coll[Box](b1, b2), success(Coll[(Box, Box)]((b1, b1), (b2, b2)), 1770, costDetails(2), 1770)) + (Coll[Box](), success(Coll[(Box, Box)](), 1766, costDetails(0), 1766, 2016 +: Seq.fill(3)(2018))), + (Coll[Box](b1), success(Coll[(Box, Box)]((b1, b1)), 1768, costDetails(1), 1768, 2018 +: Seq.fill(3)(2020))), + (Coll[Box](b1, b2), success(Coll[(Box, Box)]((b1, b1), (b2, b2)), 1770, costDetails(2), 1770, 2020 +: Seq.fill(3)(2022))) ) }, existingFeature({ (x: Coll[Box]) => x.zip(x) }, @@ -6791,7 +6884,7 @@ class SigmaDslSpecification extends SigmaDslTesting val costDetails = TracedCost(traceBase :+ FixedCostItem(SizeOf)) verifyCases( { - def success[T](v: T) = Expected(Success(v), 1765, costDetails, 1765) + def success[T](v: T) = Expected(Success(v), 1765, costDetails, 1765, 1999 +: Seq.fill(3)(2001)) Seq( (Coll[Box](), success(0)), (Coll[Box](b1), success(1)), @@ -6816,7 +6909,7 @@ class SigmaDslSpecification extends SigmaDslTesting ) verifyCases( { - def success[T](v: T, i: Int) = Expected(Success(v), 1768, costDetails(i), 1768) + def success[T](v: T, i: Int) = Expected(Success(v), 1768, costDetails(i), 1768, 2006 +: Seq.fill(3)(2008)) Seq( (Coll[Box](), success(Coll[Int](), 0)), (Coll[Box](b1), success(Coll[Int](0), 1)), @@ -6872,9 +6965,9 @@ class SigmaDslSpecification extends SigmaDslTesting ) def cases = { Seq( - (Coll[Box](), Expected(Success(true), 1764, costDetails1, 1764)), - (Coll[Box](b1), Expected(Success(false), 1769, costDetails2, 1769)), - (Coll[Box](b1, b2), Expected(Success(false), 1769, costDetails3, 1769)) + (Coll[Box](), Expected(Success(true), 1764, costDetails1, 1764, 2022 +: Seq.fill(3)(2026))), + (Coll[Box](b1), Expected(Success(false), 1769, costDetails2, 1769, 2027 +: Seq.fill(3)(2031))), + (Coll[Box](b1, b2), Expected(Success(false), 1769, costDetails3, 1769, 2027 +: Seq.fill(3)(2031))) ) } if (lowerMethodCallsInTests) { @@ -6951,20 +7044,20 @@ class SigmaDslSpecification extends SigmaDslTesting verifyCases( { Seq( - (Coll[Box](), Expected(Success(false), 1764, costDetails1, 1764)), - (Coll[Box](b1), Expected(Success(false), 1769, costDetails2, 1769)), - (Coll[Box](b1, b2), Expected(Success(true), 1773, costDetails3, 1773)) + (Coll[Box](), Expected(Success(false), 1764, costDetails1, 1764, 2022 +: Seq.fill(3)(2026))), + (Coll[Box](b1), Expected(Success(false), 1769, costDetails2, 1769, 2027 +: Seq.fill(3)(2031))), + (Coll[Box](b1, b2), Expected(Success(true), 1773, costDetails3, 1773, 2031 +: Seq.fill(3)(2035))) ) }, existingFeature({ (x: Coll[Box]) => x.exists({ (b: Box) => b.value > 1 }) }, - "{ (x: Coll[Box]) => x.exists({(b: Box) => b.value > 1 }) }", - FuncValue( - Vector((1, SCollectionType(SBox))), - Exists( - ValUse(1, SCollectionType(SBox)), - FuncValue(Vector((3, SBox)), GT(ExtractAmount(ValUse(3, SBox)), LongConstant(1L))) - ) - )), + "{ (x: Coll[Box]) => x.exists({(b: Box) => b.value > 1 }) }", + FuncValue( + Vector((1, SCollectionType(SBox))), + Exists( + ValUse(1, SCollectionType(SBox)), + FuncValue(Vector((3, SBox)), GT(ExtractAmount(ValUse(3, SBox)), LongConstant(1L))) + ) + )), preGeneratedSamples = Some(samples)) } else { def error = new java.lang.NoSuchMethodException("sigmastate.SCollection$.exist_eval(sigmastate.lang.Terms$MethodCall,sigma.Coll,scala.Function1,sigmastate.interpreter.ErgoTreeEvaluator))") @@ -7044,11 +7137,11 @@ class SigmaDslSpecification extends SigmaDslTesting verifyCases( { Seq( - (Coll[BigInt](), Expected(Success(false), 1764, costDetails1, 1764)), - (Coll[BigInt](BigIntZero), Expected(Success(false), 1769, costDetails2, 1769)), - (Coll[BigInt](BigIntOne), Expected(Success(true), 1772, costDetails3, 1772)), - (Coll[BigInt](BigIntZero, BigIntOne), Expected(Success(true), 1777, costDetails4, 1777)), - (Coll[BigInt](BigIntZero, BigInt10), Expected(Success(false), 1777, costDetails4, 1777)) + (Coll[BigInt](), Expected(Success(false), 1764, costDetails1, 1764, 2044 +: Seq.fill(3)(2048))), + (Coll[BigInt](BigIntZero), Expected(Success(false), 1769, costDetails2, 1769, 2049 +: Seq.fill(3)(2053))), + (Coll[BigInt](BigIntOne), Expected(Success(true), 1772, costDetails3, 1772, 2052 +: Seq.fill(3)(2056))), + (Coll[BigInt](BigIntZero, BigIntOne), Expected(Success(true), 1777, costDetails4, 1777, 2057 +: Seq.fill(3)(2061))), + (Coll[BigInt](BigIntZero, BigInt10), Expected(Success(false), 1777, costDetails4, 1777, 2057 +: Seq.fill(3)(2061))) ) }, existingFeature( @@ -7159,11 +7252,11 @@ class SigmaDslSpecification extends SigmaDslTesting verifyCases( { Seq( - (Coll[BigInt](), Expected(Success(true), 1764, costDetails1, 1764)), - (Coll[BigInt](BigIntMinusOne), Expected(Success(false), 1769, costDetails2, 1769)), - (Coll[BigInt](BigIntOne), Expected(Success(true), 1772, costDetails3, 1772)), - (Coll[BigInt](BigIntZero, BigIntOne), Expected(Success(true), 1779, costDetails4, 1779)), - (Coll[BigInt](BigIntZero, BigInt11), Expected(Success(false), 1779, costDetails4, 1779)) + (Coll[BigInt](), Expected(Success(true), 1764, costDetails1, 1764, 2044 +: Seq.fill(3)(2048))), + (Coll[BigInt](BigIntMinusOne), Expected(Success(false), 1769, costDetails2, 1769, 2049 +: Seq.fill(3)(2053))), + (Coll[BigInt](BigIntOne), Expected(Success(true), 1772, costDetails3, 1772, 2052 +: Seq.fill(3)(2056))), + (Coll[BigInt](BigIntZero, BigIntOne), Expected(Success(true), 1779, costDetails4, 1779, 2059 +: Seq.fill(3)(2063))), + (Coll[BigInt](BigIntZero, BigInt11), Expected(Success(false), 1779, costDetails4, 1779, 2059 +: Seq.fill(3)(2063))) ) }, existingFeature( @@ -7293,28 +7386,34 @@ class SigmaDslSpecification extends SigmaDslTesting verifyCases( { - def success[T](v: T, c: Int, cd: CostDetails, newCost: Int) = Expected(Success(v), c, cd, newCost) + def success[T](v: T, c: Int, cd: CostDetails, newCost: Int, expectedV3Costs: Seq[Int]) = Expected(Success(v), c, cd, newCost, expectedV3Costs) + Seq( - Coll[GroupElement]() -> Expected(Success(Coll[Byte]()), 1773, CostDetails.ZeroCost, 1773, - newVersionedResults = { - val res = ExpectedResult(Success(Coll[Byte]()), Some(1773)) - Seq.tabulate(3)(v => - v -> (res -> Some(costDetails0)) - ) - }), + Coll[GroupElement]() -> Expected(Success(Coll[Byte]()), 1773, CostDetails.ZeroCost, 1773, + newVersionedResults = { + val costs = if (activatedVersionInTests >= 3) { + 2027 +: Seq.fill(3)(2029) + } + else { + Seq.fill(4)(1773) + } + Seq.tabulate(4)(v => + v -> (ExpectedResult(Success(Coll[Byte]()), Some(costs(v))) -> Some(costDetails0)) + ) + }), Coll[GroupElement]( Helpers.decodeGroupElement("02d65904820f8330218cf7318b3810d0c9ab9df86f1ee6100882683f23c0aee587"), Helpers.decodeGroupElement("0390e9daa9916f30d0bc61a8e381c6005edfb7938aee5bb4fc9e8a759c7748ffaa")) -> - success(Helpers.decodeBytes( - "02d65904820f8330218cf7318b3810d0c9ab9df86f1ee6100882683f23c0aee5870390e9daa9916f30d0bc61a8e381c6005edfb7938aee5bb4fc9e8a759c7748ffaa" - ), 1834, costDetails2, 1834), + success(Helpers.decodeBytes( + "02d65904820f8330218cf7318b3810d0c9ab9df86f1ee6100882683f23c0aee5870390e9daa9916f30d0bc61a8e381c6005edfb7938aee5bb4fc9e8a759c7748ffaa" + ), 1834, costDetails2, 1834, 2088 +: Seq.fill(3)(2090)), Coll[GroupElement]( Helpers.decodeGroupElement("02d65904820f8330218cf7318b3810d0c9ab9df86f1ee6100882683f23c0aee587"), Helpers.decodeGroupElement("0390e9daa9916f30d0bc61a8e381c6005edfb7938aee5bb4fc9e8a759c7748ffaa"), Helpers.decodeGroupElement("03bd839b969b02d218fd1192f2c80cbda9c6ce9c7ddb765f31b748f4666203df85")) -> - success(Helpers.decodeBytes( - "02d65904820f8330218cf7318b3810d0c9ab9df86f1ee6100882683f23c0aee5870390e9daa9916f30d0bc61a8e381c6005edfb7938aee5bb4fc9e8a759c7748ffaa03bd839b969b02d218fd1192f2c80cbda9c6ce9c7ddb765f31b748f4666203df85" - ), 1864, costDetails3, 1864) + success(Helpers.decodeBytes( + "02d65904820f8330218cf7318b3810d0c9ab9df86f1ee6100882683f23c0aee5870390e9daa9916f30d0bc61a8e381c6005edfb7938aee5bb4fc9e8a759c7748ffaa03bd839b969b02d218fd1192f2c80cbda9c6ce9c7ddb765f31b748f4666203df85" + ), 1864, costDetails3, 1864, 2118 +: Seq.fill(3)(2120)) ) }, existingFeature( @@ -7352,11 +7451,17 @@ class SigmaDslSpecification extends SigmaDslTesting ) -> Expected(res, 1840, expectedDetails = CostDetails.ZeroCost, newCost = 1840, - newVersionedResults = (0 to 2).map(version => + newVersionedResults = (0 to 3).map({ version => + val costs = if (activatedVersionInTests >= 3) { + 2100 +: Seq.fill(3)(2104) + } + else { + Seq.fill(4)(1840) + } // successful result for each version version -> (ExpectedResult(res, - verificationCost = Some(1840)) -> Some(costDetails4)) - )) + verificationCost = Some(costs(version))) -> Some(costDetails4)) + })) ) } val f = existingFeature( @@ -7422,7 +7527,7 @@ class SigmaDslSpecification extends SigmaDslTesting verifyCases( { - def success[T](v: T, cd: CostDetails) = Expected(Success(v), 1776, cd, 1776) + def success[T](v: T, cd: CostDetails) = Expected(Success(v), 1776, cd, 1776, 2068 +: Seq.fill(3)(2072)) Seq( ((Coll[Int](), (0, 0)), success(Coll[Int](), costDetails(0))), ((Coll[Int](1), (0, 0)), success(Coll[Int](1, 1), costDetails(2))), @@ -7511,7 +7616,7 @@ class SigmaDslSpecification extends SigmaDslTesting verifyCases( // (coll, (index, elem)) { - def success[T](v: T, cd: CostDetails) = Expected(Success(v), 1774, cd, 1774) + def success[T](v: T, cd: CostDetails) = Expected(Success(v), 1774, cd, 1774, 2054 +: Seq.fill(3)(2058)) Seq( ((Coll[Int](), (0, 0)), Expected(new IndexOutOfBoundsException("0"))), ((Coll[Int](1), (0, 0)), success(Coll[Int](0), costDetails(1))), @@ -7588,7 +7693,7 @@ class SigmaDslSpecification extends SigmaDslTesting verifyCases( // (coll, (indexes, values)) { - def success[T](v: T, i: Int) = Expected(Success(v), 1774, costDetails(i), 1774) + def success[T](v: T, i: Int) = Expected(Success(v), 1774, costDetails(i), 1774, 2062 +: Seq.fill(3)(2066)) Seq( ((Coll[Int](), (Coll(0), Coll(0))), Expected(new IndexOutOfBoundsException("0"))), ((Coll[Int](), (Coll(0, 1), Coll(0, 0))), Expected(new IndexOutOfBoundsException("0"))), @@ -7765,15 +7870,15 @@ class SigmaDslSpecification extends SigmaDslTesting // (coll, initState) { Seq( - ((Coll[Byte](), 0), Expected(Success(0), 1767, costDetails1, 1767)), - ((Coll[Byte](), Int.MaxValue), Expected(Success(Int.MaxValue), 1767, costDetails1, 1767)), - ((Coll[Byte](1), Int.MaxValue - 1), Expected(Success(Int.MaxValue), 1773, costDetails2, 1773)), - ((Coll[Byte](1), Int.MaxValue), Expected(new ArithmeticException("integer overflow"))), - ((Coll[Byte](-1), Int.MinValue + 1), Expected(Success(Int.MinValue), 1773, costDetails2, 1773)), - ((Coll[Byte](-1), Int.MinValue), Expected(new ArithmeticException("integer overflow"))), - ((Coll[Byte](1, 2), 0), Expected(Success(3), 1779, costDetails3, 1779)), - ((Coll[Byte](1, -1), 0), Expected(Success(0), 1779, costDetails3, 1779)), - ((Coll[Byte](1, -1, 1), 0), Expected(Success(1), 1785, costDetails4, 1785)) + ((Coll[Byte](), 0), Expected(Success(0), 1767, costDetails1, 1767, 2045 +: Seq.fill(3)(2049))), + ((Coll[Byte](), Int.MaxValue), Expected(Success(Int.MaxValue), 1767, costDetails1, 1767, 2045 +: Seq.fill(3)(2049))), + ((Coll[Byte](1), Int.MaxValue - 1), Expected(Success(Int.MaxValue), 1773, costDetails2, 1773, 2051 +: Seq.fill(3)(2055))), + ((Coll[Byte](1), Int.MaxValue), Expected(new ArithmeticException("integer overflow"))), + ((Coll[Byte](-1), Int.MinValue + 1), Expected(Success(Int.MinValue), 1773, costDetails2, 1773, 2051 +: Seq.fill(3)(2055))), + ((Coll[Byte](-1), Int.MinValue), Expected(new ArithmeticException("integer overflow"))), + ((Coll[Byte](1, 2), 0), Expected(Success(3), 1779, costDetails3, 1779, 2057 +: Seq.fill(3)(2061))), + ((Coll[Byte](1, -1), 0), Expected(Success(0), 1779, costDetails3, 1779, 2057 +: Seq.fill(3)(2061))), + ((Coll[Byte](1, -1, 1), 0), Expected(Success(1), 1785, costDetails4, 1785, 2063 +: Seq.fill(3)(2067))) ) }, existingFeature( @@ -8026,15 +8131,15 @@ class SigmaDslSpecification extends SigmaDslTesting // (coll, initState) { Seq( - ((Coll[Byte](), 0), Expected(Success(0), 1767, costDetails1, 1767)), - ((Coll[Byte](), Int.MaxValue), Expected(Success(Int.MaxValue), 1767, costDetails1, 1767)), - ((Coll[Byte](1), Int.MaxValue - 1), Expected(Success(Int.MaxValue), 1779, costDetails2, 1779)), - ((Coll[Byte](1), Int.MaxValue), Expected(new ArithmeticException("integer overflow"))), - ((Coll[Byte](-1), Int.MinValue + 1), Expected(Success(Int.MinValue + 1), 1777, costDetails3, 1777)), - ((Coll[Byte](-1), Int.MinValue), Expected(Success(Int.MinValue), 1777, costDetails3, 1777)), - ((Coll[Byte](1, 2), 0), Expected(Success(3), 1791, costDetails4, 1791)), - ((Coll[Byte](1, -1), 0), Expected(Success(1), 1789, costDetails5, 1789)), - ((Coll[Byte](1, -1, 1), 0), Expected(Success(2), 1801, costDetails6, 1801)) + ((Coll[Byte](), 0), Expected(Success(0), 1767, costDetails1, 1767, 2085 +: Seq.fill(3)(2089))), + ((Coll[Byte](), Int.MaxValue), Expected(Success(Int.MaxValue), 1767, costDetails1, 1767, 2085 +: Seq.fill(3)(2089))), + ((Coll[Byte](1), Int.MaxValue - 1), Expected(Success(Int.MaxValue), 1779, costDetails2, 1779, 2097 +: Seq.fill(3)(2101))), + ((Coll[Byte](1), Int.MaxValue), Expected(new ArithmeticException("integer overflow"))), + ((Coll[Byte](-1), Int.MinValue + 1), Expected(Success(Int.MinValue + 1), 1777, costDetails3, 1777, 2095 +: Seq.fill(3)(2099))), + ((Coll[Byte](-1), Int.MinValue), Expected(Success(Int.MinValue), 1777, costDetails3, 1777, 2095 +: Seq.fill(3)(2099))), + ((Coll[Byte](1, 2), 0), Expected(Success(3), 1791, costDetails4, 1791, 2109 +: Seq.fill(3)(2113))), + ((Coll[Byte](1, -1), 0), Expected(Success(1), 1789, costDetails5, 1789, 2107 +: Seq.fill(3)(2111))), + ((Coll[Byte](1, -1, 1), 0), Expected(Success(2), 1801, costDetails6, 1801, 2119 +: Seq.fill(3)(2123))) ) }, existingFeature( @@ -8145,11 +8250,16 @@ class SigmaDslSpecification extends SigmaDslTesting verifyCases( // (coll, (elem: Byte, from: Int)) { - def success0[T](v: T) = Expected(Success(v), 1773, costDetails(0), 1773) - def success1[T](v: T) = Expected(Success(v), 1773, costDetails(1), 1773) - def success2[T](v: T) = Expected(Success(v), 1774, costDetails(2), 1774) - def success3[T](v: T) = Expected(Success(v), 1775, costDetails(3), 1775) - def success12[T](v: T) = Expected(Success(v), 1782, costDetails(12), 1782) + def success0[T](v: T) = Expected(Success(v), 1773, costDetails(0), 1773, 2057 +: Seq.fill(3)(2061)) + + def success1[T](v: T) = Expected(Success(v), 1773, costDetails(1), 1773, 2057 +: Seq.fill(3)(2061)) + + def success2[T](v: T) = Expected(Success(v), 1774, costDetails(2), 1774, 2058 +: Seq.fill(3)(2062)) + + def success3[T](v: T) = Expected(Success(v), 1775, costDetails(3), 1775, 2059 +: Seq.fill(3)(2063)) + + def success12[T](v: T) = Expected(Success(v), 1782, costDetails(12), 1782, 2066 +: Seq.fill(3)(2070)) + Seq( ((Coll[Byte](), (0.toByte, 0)), success0(-1)), ((Coll[Byte](), (0.toByte, -1)), success0(-1)), @@ -8211,7 +8321,8 @@ class SigmaDslSpecification extends SigmaDslTesting ) verifyCases( { - def success[T](v: T) = Expected(Success(v), 1769, costDetails, 1769) + def success[T](v: T) = Expected(Success(v), 1769, costDetails, 1769, 2017 +: Seq.fill(3)(2019)) + Seq( ((Coll[Int](), 0), Expected(new ArrayIndexOutOfBoundsException("0"))), ((Coll[Int](), -1), Expected(new ArrayIndexOutOfBoundsException("-1"))), @@ -8275,7 +8386,7 @@ class SigmaDslSpecification extends SigmaDslTesting verifyCases( // (coll, (index, default)) { - def success[T](v: T) = Expected(Success(v), 1773, costDetails, 1773) + def success[T](v: T) = Expected(Success(v), 1773, costDetails, 1773, 2049 +: Seq.fill(3)(2053)) Seq( ((Coll[Int](), (0, default)), success(default)), ((Coll[Int](), (-1, default)), success(default)), @@ -8358,7 +8469,7 @@ class SigmaDslSpecification extends SigmaDslTesting ) verifyCases( { - def success[T](v: T) = Expected(Success(v), 1763, costDetails, 1763) + def success[T](v: T) = Expected(Success(v), 1763, costDetails, 1763, 1995 +: Seq.fill(3)(1997)) Seq( ((0, 0), success(2)), ((1, 2), success(2)) @@ -8373,7 +8484,7 @@ class SigmaDslSpecification extends SigmaDslTesting val samples = genSamples[(Int, Int)](DefaultMinSuccessful) val costDetails = TracedCost(traceBase :+ FixedCostItem(SelectField)) verifyCases( - Seq(((1, 2), Expected(Success(1), cost = 1764, costDetails, 1764))), + Seq(((1, 2), Expected(Success(1), cost = 1764, costDetails, 1764, 1996 +: Seq.fill(3)(1998)))), existingFeature((x: (Int, Int)) => x._1, "{ (x: (Int, Int)) => x(0) }", FuncValue( @@ -8382,7 +8493,7 @@ class SigmaDslSpecification extends SigmaDslTesting )), preGeneratedSamples = Some(samples)) verifyCases( - Seq(((1, 2), Expected(Success(2), cost = 1764, costDetails, 1764))), + Seq(((1, 2), Expected(Success(2), cost = 1764, costDetails, 1764, 1996 +: Seq.fill(3)(1998)))), existingFeature((x: (Int, Int)) => x._2, "{ (x: (Int, Int)) => x(1) }", FuncValue( @@ -8424,9 +8535,9 @@ class SigmaDslSpecification extends SigmaDslTesting { def success[T](v: T, c: Int) = Expected(Success(v), c) Seq( - (Coll[Int](), Expected(Success(Coll[Int]()), 1768, costDetails(0), 1768)), - (Coll[Int](1), Expected(Success(Coll[Int](2)), 1771, costDetails(1), 1771)), - (Coll[Int](1, 2), Expected(Success(Coll[Int](2, 3)), 1774, costDetails(2), 1774)), + (Coll[Int](), Expected(Success(Coll[Int]()), 1768, costDetails(0), 1768, 2020 +: Seq.fill(3)(2022))), + (Coll[Int](1), Expected(Success(Coll[Int](2)), 1771, costDetails(1), 1771, 2023 +: Seq.fill(3)(2025))), + (Coll[Int](1, 2), Expected(Success(Coll[Int](2, 3)), 1774, costDetails(2), 1774, 2026 +: Seq.fill(3)(2028))), (Coll[Int](1, 2, Int.MaxValue), Expected(new ArithmeticException("integer overflow"))) ) }, @@ -8520,10 +8631,10 @@ class SigmaDslSpecification extends SigmaDslTesting { def success[T](v: T, c: Int) = Expected(Success(v), c) Seq( - (Coll[Int](), Expected(Success(Coll[Int]()), 1768, costDetails1, 1768)), - (Coll[Int](1), Expected(Success(Coll[Int](2)), 1775, costDetails2, 1775)), - (Coll[Int](-1), Expected(Success(Coll[Int](1)), 1775, costDetails3, 1775)), - (Coll[Int](1, -2), Expected(Success(Coll[Int](2, 2)), 1782, costDetails4, 1782)), + (Coll[Int](), Expected(Success(Coll[Int]()), 1768, costDetails1, 1768, 2050 +: Seq.fill(3)(2054))), + (Coll[Int](1), Expected(Success(Coll[Int](2)), 1775, costDetails2, 1775, 2057 +: Seq.fill(3)(2061))), + (Coll[Int](-1), Expected(Success(Coll[Int](1)), 1775, costDetails3, 1775, 2057 +: Seq.fill(3)(2061))), + (Coll[Int](1, -2), Expected(Success(Coll[Int](2, 2)), 1782, costDetails4, 1782, 2064 +: Seq.fill(3)(2068))), (Coll[Int](1, 2, Int.MaxValue), Expected(new ArithmeticException("integer overflow"))), (Coll[Int](1, 2, Int.MinValue), Expected(new ArithmeticException("integer overflow"))) ) @@ -8571,24 +8682,24 @@ class SigmaDslSpecification extends SigmaDslTesting val o = ExactOrdering.IntIsExactOrdering verifyCases( - { - Seq( - (Coll[Int](), Expected(Success(Coll[Int]()), 1768, costDetails(0), 1768)), - (Coll[Int](1), Expected(Success(Coll[Int](1)), 1771, costDetails(1), 1771)), - (Coll[Int](1, 2), Expected(Success(Coll[Int](1, 2)), 1775, costDetails(2), 1775)), - (Coll[Int](1, 2, -1), Expected(Success(Coll[Int](1, 2)), 1778, costDetails(3), 1778)), - (Coll[Int](1, -1, 2, -2), Expected(Success(Coll[Int](1, 2)), 1782, costDetails(4), 1782)) - ) - }, - existingFeature((x: Coll[Int]) => x.filter({ (v: Int) => o.gt(v, 0) }), - "{ (x: Coll[Int]) => x.filter({ (v: Int) => v > 0 }) }", - FuncValue( - Array((1, SCollectionType(SInt))), - Filter( - ValUse(1, SCollectionType(SInt)), - FuncValue(Array((3, SInt)), GT(ValUse(3, SInt), IntConstant(0))) + { + Seq( + (Coll[Int](), Expected(Success(Coll[Int]()), 1768, costDetails(0), 1768, 2020 +: Seq.fill(3)(2022))), + (Coll[Int](1), Expected(Success(Coll[Int](1)), 1771, costDetails(1), 1771, 2023 +: Seq.fill(3)(2025))), + (Coll[Int](1, 2), Expected(Success(Coll[Int](1, 2)), 1775, costDetails(2), 1775, 2027 +: Seq.fill(3)(2029))), + (Coll[Int](1, 2, -1), Expected(Success(Coll[Int](1, 2)), 1778, costDetails(3), 1778, 2030 +: Seq.fill(3)(2032))), + (Coll[Int](1, -1, 2, -2), Expected(Success(Coll[Int](1, 2)), 1782, costDetails(4), 1782, 2034 +: Seq.fill(3)(2036))) ) - ))) + }, + existingFeature((x: Coll[Int]) => x.filter({ (v: Int) => o.gt(v, 0) }), + "{ (x: Coll[Int]) => x.filter({ (v: Int) => v > 0 }) }", + FuncValue( + Array((1, SCollectionType(SInt))), + Filter( + ValUse(1, SCollectionType(SInt)), + FuncValue(Array((3, SInt)), GT(ValUse(3, SInt), IntConstant(0))) + ) + ))) } property("Coll filter with nested If") { @@ -8646,29 +8757,30 @@ class SigmaDslSpecification extends SigmaDslTesting val o = ExactOrdering.IntIsExactOrdering verifyCases( - { - def success[T](v: T, c: Int) = Expected(Success(v), c) - Seq( - (Coll[Int](), Expected(Success(Coll[Int]()), 1768, costDetails(0), 1768)), - (Coll[Int](1), Expected(Success(Coll[Int](1)), 1775, costDetails(1), 1775)), - (Coll[Int](10), Expected(Success(Coll[Int]()), 1775, costDetails(1), 1775)), - (Coll[Int](1, 2), Expected(Success(Coll[Int](1, 2)), 1783, costDetails(2), 1783)), - (Coll[Int](1, 2, 0), Expected(Success(Coll[Int](1, 2)), 1788, costDetails3, 1788)), - (Coll[Int](1, -1, 2, -2, 11), Expected(Success(Coll[Int](1, 2)), 1800, costDetails5, 1800)) - ) - }, - existingFeature((x: Coll[Int]) => x.filter({ (v: Int) => if (o.gt(v, 0)) v < 10 else false }), - "{ (x: Coll[Int]) => x.filter({ (v: Int) => if (v > 0) v < 10 else false }) }", - FuncValue( - Array((1, SCollectionType(SInt))), - Filter( - ValUse(1, SCollectionType(SInt)), - FuncValue( - Array((3, SInt)), - If(GT(ValUse(3, SInt), IntConstant(0)), LT(ValUse(3, SInt), IntConstant(10)), FalseLeaf) - ) + { + def success[T](v: T, c: Int) = Expected(Success(v), c) + + Seq( + (Coll[Int](), Expected(Success(Coll[Int]()), 1768, costDetails(0), 1768, 2044 +: Seq.fill(3)(2048))), + (Coll[Int](1), Expected(Success(Coll[Int](1)), 1775, costDetails(1), 1775, 2051 +: Seq.fill(3)(2055))), + (Coll[Int](10), Expected(Success(Coll[Int]()), 1775, costDetails(1), 1775, 2051 +: Seq.fill(3)(2055))), + (Coll[Int](1, 2), Expected(Success(Coll[Int](1, 2)), 1783, costDetails(2), 1783, 2059 +: Seq.fill(3)(2063))), + (Coll[Int](1, 2, 0), Expected(Success(Coll[Int](1, 2)), 1788, costDetails3, 1788, 2064 +: Seq.fill(3)(2068))), + (Coll[Int](1, -1, 2, -2, 11), Expected(Success(Coll[Int](1, 2)), 1800, costDetails5, 1800, 2076 +: Seq.fill(3)(2080))) ) - ))) + }, + existingFeature((x: Coll[Int]) => x.filter({ (v: Int) => if (o.gt(v, 0)) v < 10 else false }), + "{ (x: Coll[Int]) => x.filter({ (v: Int) => if (v > 0) v < 10 else false }) }", + FuncValue( + Array((1, SCollectionType(SInt))), + Filter( + ValUse(1, SCollectionType(SInt)), + FuncValue( + Array((3, SInt)), + If(GT(ValUse(3, SInt), IntConstant(0)), LT(ValUse(3, SInt), IntConstant(10)), FalseLeaf) + ) + ) + ))) } property("Coll slice method equivalence") { @@ -8695,48 +8807,49 @@ class SigmaDslSpecification extends SigmaDslTesting val samples = genSamples(collWithRangeGen, DefaultMinSuccessful) if (lowerMethodCallsInTests) { verifyCases( - { - val cost = 1772 - val newCost = 1772 - Seq( - // (coll, (from, until)) - ((Coll[Int](), (-1, 0)), Expected(Success(Coll[Int]()), cost, costDetails(1), newCost)), - ((Coll[Int](), (0, 0)), Expected(Success(Coll[Int]()), cost, costDetails(0), newCost)), - ((Coll[Int](1), (0, 0)), Expected(Success(Coll[Int]()), cost, costDetails(0), newCost)), - ((Coll[Int](1), (0, -1)), Expected(Success(Coll[Int]()), cost, costDetails(0), newCost)), - ((Coll[Int](1), (1, 1)), Expected(Success(Coll[Int]()), cost, costDetails(0), newCost)), - ((Coll[Int](1), (-1, 1)), Expected(Success(Coll[Int](1)), cost, costDetails(2), newCost)), - ((Coll[Int](1, 2), (1, 1)), Expected(Success(Coll[Int]()), cost, costDetails(0), newCost)), - ((Coll[Int](1, 2), (1, 0)), Expected(Success(Coll[Int]()), cost, costDetails(0), newCost)), - ((Coll[Int](1, 2), (1, 2)), Expected(Success(Coll[Int](2)), cost, costDetails(1), newCost)), - ((Coll[Int](1, 2, 3, 4), (1, 3)), Expected(Success(Coll[Int](2, 3)), cost, costDetails(2), newCost)) - ) - }, - existingFeature((x: (Coll[Int], (Int, Int))) => x._1.slice(x._2._1, x._2._2), - "{ (x: (Coll[Int], (Int, Int))) => x._1.slice(x._2._1, x._2._2) }", - FuncValue( - Vector((1, SPair(SCollectionType(SInt), SPair(SInt, SInt)))), - BlockValue( - Vector( - ValDef( - 3, - List(), - SelectField.typed[Value[STuple]]( - ValUse(1, SPair(SCollectionType(SInt), SPair(SInt, SInt))), - 2.toByte + { + val cost = 1772 + val newCost = 1772 + val v3Costs = 2046 +: Seq.fill(3)(2050) + Seq( + // (coll, (from, until)) + ((Coll[Int](), (-1, 0)), Expected(Success(Coll[Int]()), cost, costDetails(1), newCost, v3Costs)), + ((Coll[Int](), (0, 0)), Expected(Success(Coll[Int]()), cost, costDetails(0), newCost, v3Costs)), + ((Coll[Int](1), (0, 0)), Expected(Success(Coll[Int]()), cost, costDetails(0), newCost, v3Costs)), + ((Coll[Int](1), (0, -1)), Expected(Success(Coll[Int]()), cost, costDetails(0), newCost, v3Costs)), + ((Coll[Int](1), (1, 1)), Expected(Success(Coll[Int]()), cost, costDetails(0), newCost, v3Costs)), + ((Coll[Int](1), (-1, 1)), Expected(Success(Coll[Int](1)), cost, costDetails(2), newCost, v3Costs)), + ((Coll[Int](1, 2), (1, 1)), Expected(Success(Coll[Int]()), cost, costDetails(0), newCost, v3Costs)), + ((Coll[Int](1, 2), (1, 0)), Expected(Success(Coll[Int]()), cost, costDetails(0), newCost, v3Costs)), + ((Coll[Int](1, 2), (1, 2)), Expected(Success(Coll[Int](2)), cost, costDetails(1), newCost, v3Costs)), + ((Coll[Int](1, 2, 3, 4), (1, 3)), Expected(Success(Coll[Int](2, 3)), cost, costDetails(2), newCost, v3Costs)) + ) + }, + existingFeature((x: (Coll[Int], (Int, Int))) => x._1.slice(x._2._1, x._2._2), + "{ (x: (Coll[Int], (Int, Int))) => x._1.slice(x._2._1, x._2._2) }", + FuncValue( + Vector((1, SPair(SCollectionType(SInt), SPair(SInt, SInt)))), + BlockValue( + Vector( + ValDef( + 3, + List(), + SelectField.typed[Value[STuple]]( + ValUse(1, SPair(SCollectionType(SInt), SPair(SInt, SInt))), + 2.toByte + ) ) - ) - ), - Slice( - SelectField.typed[Value[SCollection[SInt.type]]]( - ValUse(1, SPair(SCollectionType(SInt), SPair(SInt, SInt))), - 1.toByte ), - SelectField.typed[Value[SInt.type]](ValUse(3, SPair(SInt, SInt)), 1.toByte), - SelectField.typed[Value[SInt.type]](ValUse(3, SPair(SInt, SInt)), 2.toByte) + Slice( + SelectField.typed[Value[SCollection[SInt.type]]]( + ValUse(1, SPair(SCollectionType(SInt), SPair(SInt, SInt))), + 1.toByte + ), + SelectField.typed[Value[SInt.type]](ValUse(3, SPair(SInt, SInt)), 1.toByte), + SelectField.typed[Value[SInt.type]](ValUse(3, SPair(SInt, SInt)), 2.toByte) + ) ) - ) - )), + )), preGeneratedSamples = Some(samples)) } else { def error = new java.lang.NoSuchMethodException("sigmastate.SCollection$.slice_eval(sigmastate.lang.Terms$MethodCall,sigma.Coll,int,int,sigmastate.interpreter.ErgoTreeEvaluator))") @@ -8786,37 +8899,38 @@ class SigmaDslSpecification extends SigmaDslTesting ) if (lowerMethodCallsInTests) { verifyCases( - { - def success[T](v: T, size: Int) = Expected(Success(v), 1770, costDetails(size), 1770) - val arr1 = Gen.listOfN(100, arbitrary[Int]).map(_.toArray).sample.get - val arr2 = Gen.listOfN(200, arbitrary[Int]).map(_.toArray).sample.get - Seq( - (Coll[Int](), Coll[Int]()) -> success(Coll[Int](), 0), - (Coll[Int](), Coll[Int](1)) -> success(Coll[Int](1), 1), - (Coll[Int](1), Coll[Int]()) -> success(Coll[Int](1), 1), - (Coll[Int](1), Coll[Int](2)) -> success(Coll[Int](1, 2), 2), - (Coll[Int](1), Coll[Int](2, 3)) -> success(Coll[Int](1, 2, 3), 3), - (Coll[Int](1, 2), Coll[Int](3)) -> success(Coll[Int](1, 2, 3), 3), - (Coll[Int](1, 2), Coll[Int](3, 4)) -> success(Coll[Int](1, 2, 3, 4), 4), - (Coll[Int](arr1:_*), Coll[Int](arr2:_*)) -> Expected(Success(Coll[Int](arr1 ++ arr2:_*)), 1771, costDetails(300), 1771) - ) - }, - existingFeature( - { (x: (Coll[Int], Coll[Int])) => x._1.append(x._2) }, - "{ (x: (Coll[Int], Coll[Int])) => x._1.append(x._2) }", - FuncValue( - Vector((1, SPair(SCollectionType(SInt), SCollectionType(SInt)))), - Append( - SelectField.typed[Value[SCollection[SInt.type]]]( - ValUse(1, SPair(SCollectionType(SInt), SCollectionType(SInt))), - 1.toByte - ), - SelectField.typed[Value[SCollection[SInt.type]]]( - ValUse(1, SPair(SCollectionType(SInt), SCollectionType(SInt))), - 2.toByte - ) + { + def success[T](v: T, size: Int) = Expected(Success(v), 1770, costDetails(size), 1770, 2020 +: Seq.fill(3)(2022)) + + val arr1 = Gen.listOfN(100, arbitrary[Int]).map(_.toArray).sample.get + val arr2 = Gen.listOfN(200, arbitrary[Int]).map(_.toArray).sample.get + Seq( + (Coll[Int](), Coll[Int]()) -> success(Coll[Int](), 0), + (Coll[Int](), Coll[Int](1)) -> success(Coll[Int](1), 1), + (Coll[Int](1), Coll[Int]()) -> success(Coll[Int](1), 1), + (Coll[Int](1), Coll[Int](2)) -> success(Coll[Int](1, 2), 2), + (Coll[Int](1), Coll[Int](2, 3)) -> success(Coll[Int](1, 2, 3), 3), + (Coll[Int](1, 2), Coll[Int](3)) -> success(Coll[Int](1, 2, 3), 3), + (Coll[Int](1, 2), Coll[Int](3, 4)) -> success(Coll[Int](1, 2, 3, 4), 4), + (Coll[Int](arr1: _*), Coll[Int](arr2: _*)) -> Expected(Success(Coll[Int](arr1 ++ arr2: _*)), 1771, costDetails(300), 1771, 2021 +: Seq.fill(3)(2023)) ) - ))) + }, + existingFeature( + { (x: (Coll[Int], Coll[Int])) => x._1.append(x._2) }, + "{ (x: (Coll[Int], Coll[Int])) => x._1.append(x._2) }", + FuncValue( + Vector((1, SPair(SCollectionType(SInt), SCollectionType(SInt)))), + Append( + SelectField.typed[Value[SCollection[SInt.type]]]( + ValUse(1, SPair(SCollectionType(SInt), SCollectionType(SInt))), + 1.toByte + ), + SelectField.typed[Value[SCollection[SInt.type]]]( + ValUse(1, SPair(SCollectionType(SInt), SCollectionType(SInt))), + 2.toByte + ) + ) + ))) } else { def error = new java.lang.NoSuchMethodException("sigmastate.SCollection$.append_eval(sigmastate.lang.Terms$MethodCall,sigma.Coll,sigma.Coll,sigmastate.interpreter.ErgoTreeEvaluator))") verifyCases( @@ -8893,33 +9007,33 @@ class SigmaDslSpecification extends SigmaDslTesting verifyCases( Seq( (None -> Expected(new NoSuchElementException("None.get"))), - (Some(10L) -> Expected(Success(10L), 1765, costDetails1, 1765))), + (Some(10L) -> Expected(Success(10L), 1765, costDetails1, 1765, 1995 +: Seq.fill(3)(1997)))), existingFeature({ (x: Option[Long]) => x.get }, "{ (x: Option[Long]) => x.get }", FuncValue(Vector((1, SOption(SLong))), OptionGet(ValUse(1, SOption(SLong)))))) verifyCases( Seq( - (None -> Expected(Success(false), 1764, costDetails2, 1764)), - (Some(10L) -> Expected(Success(true), 1764, costDetails2, 1764))), + (None -> Expected(Success(false), 1764, costDetails2, 1764, 1994 +: Seq.fill(3)(1996))), + (Some(10L) -> Expected(Success(true), 1764, costDetails2, 1764, 1994 +: Seq.fill(3)(1996)))), existingFeature({ (x: Option[Long]) => x.isDefined }, "{ (x: Option[Long]) => x.isDefined }", FuncValue(Vector((1, SOption(SLong))), OptionIsDefined(ValUse(1, SOption(SLong)))))) verifyCases( Seq( - (None -> Expected(Success(1L), 1766, costDetails3, 1766)), - (Some(10L) -> Expected(Success(10L), 1766, costDetails3, 1766))), + (None -> Expected(Success(1L), 1766, costDetails3, 1766, 2004 +: Seq.fill(3)(2006))), + (Some(10L) -> Expected(Success(10L), 1766, costDetails3, 1766, 2004 +: Seq.fill(3)(2006)))), existingFeature({ (x: Option[Long]) => x.getOrElse(1L) }, "{ (x: Option[Long]) => x.getOrElse(1L) }", FuncValue(Vector((1, SOption(SLong))), OptionGetOrElse(ValUse(1, SOption(SLong)), LongConstant(1L))))) verifyCases( Seq( - (None -> Expected(Success(None), 1766, costDetails4, 1766)), - (Some(10L) -> Expected(Success(None), 1768, costDetails5, 1768)), - (Some(1L) -> Expected(Success(Some(1L)), 1769, costDetails5, 1769))), - existingFeature({ (x: Option[Long]) => x.filter({ (v: Long) => v == 1} ) }, + (None -> Expected(Success(None), 1766, costDetails4, 1766, 2024 +: Seq.fill(3)(2028))), + (Some(10L) -> Expected(Success(None), 1768, costDetails5, 1768, 2026 +: Seq.fill(3)(2030))), + (Some(1L) -> Expected(Success(Some(1L)), 1769, costDetails5, 1769, 2027 +: Seq.fill(3)(2031)))), + existingFeature({ (x: Option[Long]) => x.filter({ (v: Long) => v == 1 }) }, "{ (x: Option[Long]) => x.filter({ (v: Long) => v == 1 }) }", FuncValue( Vector((1, SOption(SLong))), @@ -8934,8 +9048,8 @@ class SigmaDslSpecification extends SigmaDslTesting val n = ExactNumeric.LongIsExactNumeric verifyCases( Seq( - (None -> Expected(Success(None), 1766, costDetails6, 1766)), - (Some(10L) -> Expected(Success(Some(11L)), 1770, costDetails7, 1770)), + (None -> Expected(Success(None), 1766, costDetails6, 1766, 2024 +: Seq.fill(3)(2028))), + (Some(10L) -> Expected(Success(Some(11L)), 1770, costDetails7, 1770, 2028 +: Seq.fill(3)(2032))), (Some(Long.MaxValue) -> Expected(new ArithmeticException("long overflow")))), existingFeature({ (x: Option[Long]) => x.map( (v: Long) => n.plus(v, 1) ) }, "{ (x: Option[Long]) => x.map({ (v: Long) => v + 1 }) }", @@ -8997,10 +9111,10 @@ class SigmaDslSpecification extends SigmaDslTesting val o = ExactOrdering.LongIsExactOrdering verifyCases( Seq( - (None -> Expected(Success(None), 1766, costDetails1, 1766)), - (Some(0L) -> Expected(Success(None), 1771, costDetails2, 1771)), - (Some(10L) -> Expected(Success(Some(10L)), 1774, costDetails3, 1774)), - (Some(11L) -> Expected(Success(None), 1774, costDetails3, 1774))), + (None -> Expected(Success(None), 1766, costDetails1, 1766, 2048 +: Seq.fill(3)(2052))), + (Some(0L) -> Expected(Success(None), 1771, costDetails2, 1771, 2053 +: Seq.fill(3)(2057))), + (Some(10L) -> Expected(Success(Some(10L)), 1774, costDetails3, 1774, 2056 +: Seq.fill(3)(2060))), + (Some(11L) -> Expected(Success(None), 1774, costDetails3, 1774, 2056 +: Seq.fill(3)(2060)))), existingFeature( { (x: Option[Long]) => x.filter({ (v: Long) => if (o.gt(v, 0L)) v <= 10 else false } ) }, "{ (x: Option[Long]) => x.filter({ (v: Long) => if (v > 0) v <= 10 else false }) }", @@ -9061,10 +9175,10 @@ class SigmaDslSpecification extends SigmaDslTesting val n = ExactNumeric.LongIsExactNumeric verifyCases( Seq( - (None -> Expected(Success(None), 1766, costDetails4, 1766)), - (Some(0L) -> Expected(Success(Some(0L)), 1772, costDetails5, 1772)), - (Some(10L) -> Expected(Success(Some(10L)), 1772, costDetails5, 1772)), - (Some(-1L) -> Expected(Success(Some(-2L)), 1774, costDetails6, 1774)), + (None -> Expected(Success(None), 1766, costDetails4, 1766, 2044 +: Seq.fill(3)(2048))), + (Some(0L) -> Expected(Success(Some(0L)), 1772, costDetails5, 1772, 2050 +: Seq.fill(3)(2054))), + (Some(10L) -> Expected(Success(Some(10L)), 1772, costDetails5, 1772, 2050 +: Seq.fill(3)(2054))), + (Some(-1L) -> Expected(Success(Some(-2L)), 1774, costDetails6, 1774, 2052 +: Seq.fill(3)(2056))), (Some(Long.MinValue) -> Expected(new ArithmeticException("long overflow")))), existingFeature( { (x: Option[Long]) => x.map( (v: Long) => if (o.lt(v, 0)) n.minus(v, 1) else v ) }, @@ -9128,17 +9242,26 @@ class SigmaDslSpecification extends SigmaDslTesting verifyCases( Seq( (None -> Expected( - value = Failure(new NoSuchElementException("None.get")), - cost = 0, - expectedDetails = CostDetails.ZeroCost, - newCost = 1766, - newVersionedResults = Seq.tabulate(3)(v => v -> (ExpectedResult(Success(5L), Some(1766)) -> Some(costDetails1))) - )), + value = Failure(new NoSuchElementException("None.get")), + cost = 0, + expectedDetails = CostDetails.ZeroCost, + newCost = 1766, + newVersionedResults = Seq.tabulate(4)({ v => + val costs = if (activatedVersionInTests >= 3) { + 2038 +: Seq.fill(3)(2042) + } + else { + Seq.fill(4)(1766) + } + v -> (ExpectedResult(Success(5L), Some(costs(v))) -> Some(costDetails1)) + }) + )), (Some(0L) -> Expected( Success(1L), cost = 1774, expectedDetails = costDetails2, - expectedNewCost = 1774)), + expectedNewCost = 1774, + expectedV3Costs = 2046 +: Seq.fill(3)(2050))), (Some(Long.MaxValue) -> Expected(new ArithmeticException("long overflow"))) ), changedFeature( @@ -9206,19 +9329,22 @@ class SigmaDslSpecification extends SigmaDslTesting Success(Helpers.decodeBytes("0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a8")), 1768, costDetailsBlake(0), - 1768 + 1768, + 1998 +: Seq.fill(3)(2000) ), Helpers.decodeBytes("e0ff0105ffffac31010017ff33") -> Expected( Success(Helpers.decodeBytes("33707eed9aab64874ff2daa6d6a378f61e7da36398fb36c194c7562c9ff846b5")), 1768, costDetailsBlake(13), - 1768 + 1768, + 1998 +: Seq.fill(3)(2000) ), Colls.replicate(1024, 1.toByte) -> Expected( Success(Helpers.decodeBytes("45d8456fc5d41d1ec1124cb92e41192c1c3ec88f0bf7ae2dc6e9cf75bec22045")), 1773, costDetailsBlake(1024), - 1773 + 1773, + 2003 +: Seq.fill(3)(2005) ) ), existingFeature((x: Coll[Byte]) => SigmaDsl.blake2b256(x), @@ -9231,19 +9357,22 @@ class SigmaDslSpecification extends SigmaDslTesting Success(Helpers.decodeBytes("e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855")), 1774, costDetailsSha(0), - 1774 + 1774, + 2004 +: Seq.fill(3)(2006) ), Helpers.decodeBytes("e0ff0105ffffac31010017ff33") -> Expected( Success(Helpers.decodeBytes("367d0ec2cdc14aac29d5beb60c2bfc86d5a44a246308659af61c1b85fa2ca2cc")), 1774, costDetailsSha(13), - 1774 + 1774, + 2004 +: Seq.fill(3)(2006) ), Colls.replicate(1024, 1.toByte) -> Expected( Success(Helpers.decodeBytes("5a648d8015900d89664e00e125df179636301a2d8fa191c1aa2bd9358ea53a69")), 1786, costDetailsSha(1024), - 1786 + 1786, + 2016 +: Seq.fill(3)(2018) ) ), existingFeature((x: Coll[Byte]) => SigmaDsl.sha256(x), @@ -9253,10 +9382,11 @@ class SigmaDslSpecification extends SigmaDslTesting property("sigmaProp equivalence") { val costDetails = TracedCost(traceBase :+ FixedCostItem(BoolToSigmaProp)) + val v3Costs = 1995 +: Seq.fill(3)(1997) verifyCases( Seq( - (false, Expected(Success(CSigmaProp(TrivialProp.FalseProp)), 1765, costDetails, 1765)), - (true, Expected(Success(CSigmaProp(TrivialProp.TrueProp)), 1765, costDetails, 1765))), + (false, Expected(Success(CSigmaProp(TrivialProp.FalseProp)), 1765, costDetails, 1765, v3Costs)), + (true, Expected(Success(CSigmaProp(TrivialProp.TrueProp)), 1765, costDetails, 1765, v3Costs))), existingFeature((x: Boolean) => sigmaProp(x), "{ (x: Boolean) => sigmaProp(x) }", FuncValue(Vector((1, SBoolean)), BoolToSigmaProp(ValUse(1, SBoolean))))) @@ -9283,7 +9413,7 @@ class SigmaDslSpecification extends SigmaDslTesting Helpers.decodeECPoint("02614b14a8c6c6b4b7ce017d72fbca7f9218b72c16bdd88f170ffb300b106b9014"), Helpers.decodeECPoint("034cc5572276adfa3e283a3f1b0f0028afaadeaa362618c5ec43262d8cefe7f004") ) - )) -> Expected(Success(CSigmaProp(TrivialProp.TrueProp)), 1770, costDetails(1), 1770), + )) -> Expected(Success(CSigmaProp(TrivialProp.TrueProp)), 1770, costDetails(1), 1770, 2016 +: Seq.fill(3)(2018)), Coll[SigmaProp]( CSigmaProp( ProveDHTuple( @@ -9311,7 +9441,7 @@ class SigmaDslSpecification extends SigmaDslTesting ) ) ) - ), 1873, costDetails(3), 1873), + ), 1873, costDetails(3), 1873, 2119 +: Seq.fill(3)(2121)), Colls.replicate[SigmaProp](AtLeast.MaxChildrenCount + 1, CSigmaProp(TrivialProp.TrueProp)) -> Expected(new IllegalArgumentException("Expected input elements count should not exceed 255, actual: 256")) ), @@ -9343,31 +9473,32 @@ class SigmaDslSpecification extends SigmaDslTesting verifyCases( { - def success[T](v: T, newCost: Int) = Expected(Success(v), newCost, costDetails1, newCost) + def success[T](v: T, newCost: Int, expectedV3Costs: Seq[Int]) = Expected(Success(v), newCost, costDetails1, newCost, expectedV3Costs) + Seq( (CSigmaProp(ProveDlog(Helpers.decodeECPoint("02ea9bf6da7f512386c6ca509d40f8c5e7e0ffb3eea5dc3c398443ea17f4510798"))), - CSigmaProp(ProveDlog(Helpers.decodeECPoint("03a426a66fc1af2792b35d9583904c3fb877b49ae5cea45b7a2aa105ffa4c68606")))) -> - success( - CSigmaProp( - CAND( - Seq( - ProveDlog(Helpers.decodeECPoint("02ea9bf6da7f512386c6ca509d40f8c5e7e0ffb3eea5dc3c398443ea17f4510798")), - ProveDlog(Helpers.decodeECPoint("03a426a66fc1af2792b35d9583904c3fb877b49ae5cea45b7a2aa105ffa4c68606")) - ) + CSigmaProp(ProveDlog(Helpers.decodeECPoint("03a426a66fc1af2792b35d9583904c3fb877b49ae5cea45b7a2aa105ffa4c68606")))) -> + success( + CSigmaProp( + CAND( + Seq( + ProveDlog(Helpers.decodeECPoint("02ea9bf6da7f512386c6ca509d40f8c5e7e0ffb3eea5dc3c398443ea17f4510798")), + ProveDlog(Helpers.decodeECPoint("03a426a66fc1af2792b35d9583904c3fb877b49ae5cea45b7a2aa105ffa4c68606")) ) - ), 1802), + ) + ), 1802, 2046 +: Seq.fill(3)(2048)), (CSigmaProp(TrivialProp.TrueProp), - CSigmaProp(ProveDlog(Helpers.decodeECPoint("03a426a66fc1af2792b35d9583904c3fb877b49ae5cea45b7a2aa105ffa4c68606")))) -> - success(CSigmaProp(ProveDlog(Helpers.decodeECPoint("03a426a66fc1af2792b35d9583904c3fb877b49ae5cea45b7a2aa105ffa4c68606"))), 1784), + CSigmaProp(ProveDlog(Helpers.decodeECPoint("03a426a66fc1af2792b35d9583904c3fb877b49ae5cea45b7a2aa105ffa4c68606")))) -> + success(CSigmaProp(ProveDlog(Helpers.decodeECPoint("03a426a66fc1af2792b35d9583904c3fb877b49ae5cea45b7a2aa105ffa4c68606"))), 1784, 2028 +: Seq.fill(3)(2030)), (CSigmaProp(TrivialProp.FalseProp), - CSigmaProp(ProveDlog(Helpers.decodeECPoint("03a426a66fc1af2792b35d9583904c3fb877b49ae5cea45b7a2aa105ffa4c68606")))) -> - success(CSigmaProp(TrivialProp.FalseProp), 1767), + CSigmaProp(ProveDlog(Helpers.decodeECPoint("03a426a66fc1af2792b35d9583904c3fb877b49ae5cea45b7a2aa105ffa4c68606")))) -> + success(CSigmaProp(TrivialProp.FalseProp), 1767, 2011 +: Seq.fill(3)(2013)), (CSigmaProp(ProveDlog(Helpers.decodeECPoint("03a426a66fc1af2792b35d9583904c3fb877b49ae5cea45b7a2aa105ffa4c68606"))), - CSigmaProp(TrivialProp.TrueProp)) -> - success(CSigmaProp(ProveDlog(Helpers.decodeECPoint("03a426a66fc1af2792b35d9583904c3fb877b49ae5cea45b7a2aa105ffa4c68606"))), 1784), + CSigmaProp(TrivialProp.TrueProp)) -> + success(CSigmaProp(ProveDlog(Helpers.decodeECPoint("03a426a66fc1af2792b35d9583904c3fb877b49ae5cea45b7a2aa105ffa4c68606"))), 1784, 2028 +: Seq.fill(3)(2030)), (CSigmaProp(ProveDlog(Helpers.decodeECPoint("03a426a66fc1af2792b35d9583904c3fb877b49ae5cea45b7a2aa105ffa4c68606"))), - CSigmaProp(TrivialProp.FalseProp)) -> - success(CSigmaProp(TrivialProp.FalseProp), 1767) + CSigmaProp(TrivialProp.FalseProp)) -> + success(CSigmaProp(TrivialProp.FalseProp), 1767, 2011 +: Seq.fill(3)(2013)) ) }, existingFeature( @@ -9387,9 +9518,9 @@ class SigmaDslSpecification extends SigmaDslTesting { Seq( (CSigmaProp(ProveDlog(Helpers.decodeECPoint("03a426a66fc1af2792b35d9583904c3fb877b49ae5cea45b7a2aa105ffa4c68606"))), true) -> - Expected(Success(CSigmaProp(ProveDlog(Helpers.decodeECPoint("03a426a66fc1af2792b35d9583904c3fb877b49ae5cea45b7a2aa105ffa4c68606")))), 1786, costDetails2, 1786), + Expected(Success(CSigmaProp(ProveDlog(Helpers.decodeECPoint("03a426a66fc1af2792b35d9583904c3fb877b49ae5cea45b7a2aa105ffa4c68606")))), 1786, costDetails2, 1786, 2036 +: Seq.fill(3)(2038)), (CSigmaProp(ProveDlog(Helpers.decodeECPoint("03a426a66fc1af2792b35d9583904c3fb877b49ae5cea45b7a2aa105ffa4c68606"))), false) -> - Expected(Success(CSigmaProp(TrivialProp.FalseProp)), 1769, costDetails2, 1769) + Expected(Success(CSigmaProp(TrivialProp.FalseProp)), 1769, costDetails2, 1769, 2019 +: Seq.fill(3)(2021)) ) }, existingFeature( @@ -9418,32 +9549,33 @@ class SigmaDslSpecification extends SigmaDslTesting val costDetails1 = TracedCost(testTraceBase :+ SeqCostItem(CompanionDesc(SigmaOr), PerItemCost(JitCost(10), JitCost(2), 1), 2)) verifyCases( { - def success[T](v: T, newCost: Int) = Expected(Success(v), newCost, costDetails1, newCost) + def success[T](v: T, newCost: Int, v3Costs: Seq[Int]) = Expected(Success(v), newCost, costDetails1, newCost, v3Costs) + Seq( (CSigmaProp(ProveDlog(Helpers.decodeECPoint("02ea9bf6da7f512386c6ca509d40f8c5e7e0ffb3eea5dc3c398443ea17f4510798"))), - CSigmaProp(ProveDlog(Helpers.decodeECPoint("03a426a66fc1af2792b35d9583904c3fb877b49ae5cea45b7a2aa105ffa4c68606")))) -> - success( - CSigmaProp( - COR( - Seq( - ProveDlog(Helpers.decodeECPoint("02ea9bf6da7f512386c6ca509d40f8c5e7e0ffb3eea5dc3c398443ea17f4510798")), - ProveDlog(Helpers.decodeECPoint("03a426a66fc1af2792b35d9583904c3fb877b49ae5cea45b7a2aa105ffa4c68606")) - ) + CSigmaProp(ProveDlog(Helpers.decodeECPoint("03a426a66fc1af2792b35d9583904c3fb877b49ae5cea45b7a2aa105ffa4c68606")))) -> + success( + CSigmaProp( + COR( + Seq( + ProveDlog(Helpers.decodeECPoint("02ea9bf6da7f512386c6ca509d40f8c5e7e0ffb3eea5dc3c398443ea17f4510798")), + ProveDlog(Helpers.decodeECPoint("03a426a66fc1af2792b35d9583904c3fb877b49ae5cea45b7a2aa105ffa4c68606")) ) - ), - 1802), + ) + ), + 1802, 2046 +: Seq.fill(3)(2048)), (CSigmaProp(TrivialProp.FalseProp), - CSigmaProp(ProveDlog(Helpers.decodeECPoint("03a426a66fc1af2792b35d9583904c3fb877b49ae5cea45b7a2aa105ffa4c68606")))) -> - success(CSigmaProp(ProveDlog(Helpers.decodeECPoint("03a426a66fc1af2792b35d9583904c3fb877b49ae5cea45b7a2aa105ffa4c68606"))), 1784), + CSigmaProp(ProveDlog(Helpers.decodeECPoint("03a426a66fc1af2792b35d9583904c3fb877b49ae5cea45b7a2aa105ffa4c68606")))) -> + success(CSigmaProp(ProveDlog(Helpers.decodeECPoint("03a426a66fc1af2792b35d9583904c3fb877b49ae5cea45b7a2aa105ffa4c68606"))), 1784, 2028 +: Seq.fill(3)(2030)), (CSigmaProp(TrivialProp.TrueProp), - CSigmaProp(ProveDlog(Helpers.decodeECPoint("03a426a66fc1af2792b35d9583904c3fb877b49ae5cea45b7a2aa105ffa4c68606")))) -> - success(CSigmaProp(TrivialProp.TrueProp), 1767), + CSigmaProp(ProveDlog(Helpers.decodeECPoint("03a426a66fc1af2792b35d9583904c3fb877b49ae5cea45b7a2aa105ffa4c68606")))) -> + success(CSigmaProp(TrivialProp.TrueProp), 1767, 2011 +: Seq.fill(3)(2013)), (CSigmaProp(ProveDlog(Helpers.decodeECPoint("03a426a66fc1af2792b35d9583904c3fb877b49ae5cea45b7a2aa105ffa4c68606"))), - CSigmaProp(TrivialProp.FalseProp)) -> - success(CSigmaProp(ProveDlog(Helpers.decodeECPoint("03a426a66fc1af2792b35d9583904c3fb877b49ae5cea45b7a2aa105ffa4c68606"))), 1784), + CSigmaProp(TrivialProp.FalseProp)) -> + success(CSigmaProp(ProveDlog(Helpers.decodeECPoint("03a426a66fc1af2792b35d9583904c3fb877b49ae5cea45b7a2aa105ffa4c68606"))), 1784, 2028 +: Seq.fill(3)(2030)), (CSigmaProp(ProveDlog(Helpers.decodeECPoint("03a426a66fc1af2792b35d9583904c3fb877b49ae5cea45b7a2aa105ffa4c68606"))), - CSigmaProp(TrivialProp.TrueProp)) -> - success(CSigmaProp(TrivialProp.TrueProp), 1767) + CSigmaProp(TrivialProp.TrueProp)) -> + success(CSigmaProp(TrivialProp.TrueProp), 1767, 2011 +: Seq.fill(3)(2013)) ) }, existingFeature( @@ -9467,12 +9599,13 @@ class SigmaDslSpecification extends SigmaDslTesting ) verifyCases( { - def success[T](v: T, newCost: Int) = Expected(Success(v), newCost, costDetails2, newCost) + def success[T](v: T, newCost: Int, v3Costs: Seq[Int]) = Expected(Success(v), newCost, costDetails2, newCost, v3Costs) + Seq( (CSigmaProp(ProveDlog(Helpers.decodeECPoint("03a426a66fc1af2792b35d9583904c3fb877b49ae5cea45b7a2aa105ffa4c68606"))), false) -> - success(CSigmaProp(ProveDlog(Helpers.decodeECPoint("03a426a66fc1af2792b35d9583904c3fb877b49ae5cea45b7a2aa105ffa4c68606"))), 1786), + success(CSigmaProp(ProveDlog(Helpers.decodeECPoint("03a426a66fc1af2792b35d9583904c3fb877b49ae5cea45b7a2aa105ffa4c68606"))), 1786, 2036 +: Seq.fill(3)(2038)), (CSigmaProp(ProveDlog(Helpers.decodeECPoint("03a426a66fc1af2792b35d9583904c3fb877b49ae5cea45b7a2aa105ffa4c68606"))), true) -> - success(CSigmaProp(TrivialProp.TrueProp), 1769) + success(CSigmaProp(TrivialProp.TrueProp), 1769, 2019 +: Seq.fill(3)(2021)) ) }, existingFeature( @@ -9510,25 +9643,25 @@ class SigmaDslSpecification extends SigmaDslTesting Helpers.decodeBytes( "0008ce03c046fccb95549910767d0543f5e8ce41d66ae6a8720a46f4049cac3b3d26dafb023479c9c3b86a0d3c8be3db0a2d186788e9af1db76d55f3dad127d15185d83d0303d7898641cb6653585a8e1dabfa7f665e61e0498963e329e6e3744bd764db2d72037ae057d89ec0b46ff8e9ff4c37e85c12acddb611c3f636421bef1542c11b0441" ) - ), cost = 1771, newDetails(4), expectedNewCost = 1771), + ), cost = 1771, newDetails(4), expectedNewCost = 1771, 2001 +: Seq.fill(3)(2003)), CSigmaProp(pk) -> Expected(Success( Helpers.decodeBytes("0008cd039d0b1e46c21540d033143440d2fb7dd5d650cf89981c99ee53c6e0374d2b1b6f")), - cost = 1769, newDetails(1), expectedNewCost = 1769), + cost = 1769, newDetails(1), expectedNewCost = 1769, 1999 +: Seq.fill(3)(2001)), CSigmaProp(and) -> Expected(Success( Helpers.decodeBytes( "00089602cd039d0b1e46c21540d033143440d2fb7dd5d650cf89981c99ee53c6e0374d2b1b6fce03c046fccb95549910767d0543f5e8ce41d66ae6a8720a46f4049cac3b3d26dafb023479c9c3b86a0d3c8be3db0a2d186788e9af1db76d55f3dad127d15185d83d0303d7898641cb6653585a8e1dabfa7f665e61e0498963e329e6e3744bd764db2d72037ae057d89ec0b46ff8e9ff4c37e85c12acddb611c3f636421bef1542c11b0441" ) - ), cost = 1772, newDetails(6), expectedNewCost = 1772), + ), cost = 1772, newDetails(6), expectedNewCost = 1772, 2002 +: Seq.fill(3)(2004)), CSigmaProp(threshold) -> Expected(Success( Helpers.decodeBytes( "0008980204cd039d0b1e46c21540d033143440d2fb7dd5d650cf89981c99ee53c6e0374d2b1b6fce03c046fccb95549910767d0543f5e8ce41d66ae6a8720a46f4049cac3b3d26dafb023479c9c3b86a0d3c8be3db0a2d186788e9af1db76d55f3dad127d15185d83d0303d7898641cb6653585a8e1dabfa7f665e61e0498963e329e6e3744bd764db2d72037ae057d89ec0b46ff8e9ff4c37e85c12acddb611c3f636421bef1542c11b04419702cd039d0b1e46c21540d033143440d2fb7dd5d650cf89981c99ee53c6e0374d2b1b6fce03c046fccb95549910767d0543f5e8ce41d66ae6a8720a46f4049cac3b3d26dafb023479c9c3b86a0d3c8be3db0a2d186788e9af1db76d55f3dad127d15185d83d0303d7898641cb6653585a8e1dabfa7f665e61e0498963e329e6e3744bd764db2d72037ae057d89ec0b46ff8e9ff4c37e85c12acddb611c3f636421bef1542c11b04419602cd039d0b1e46c21540d033143440d2fb7dd5d650cf89981c99ee53c6e0374d2b1b6fce03c046fccb95549910767d0543f5e8ce41d66ae6a8720a46f4049cac3b3d26dafb023479c9c3b86a0d3c8be3db0a2d186788e9af1db76d55f3dad127d15185d83d0303d7898641cb6653585a8e1dabfa7f665e61e0498963e329e6e3744bd764db2d72037ae057d89ec0b46ff8e9ff4c37e85c12acddb611c3f636421bef1542c11b0441" ) - ), cost = 1780, newDetails(18), expectedNewCost = 1780), + ), cost = 1780, newDetails(18), expectedNewCost = 1780, 2010 +: Seq.fill(3)(2012)), CSigmaProp(COR(Array(pk, dht, and, or, threshold))) -> Expected(Success( Helpers.decodeBytes( "00089705cd039d0b1e46c21540d033143440d2fb7dd5d650cf89981c99ee53c6e0374d2b1b6fce03c046fccb95549910767d0543f5e8ce41d66ae6a8720a46f4049cac3b3d26dafb023479c9c3b86a0d3c8be3db0a2d186788e9af1db76d55f3dad127d15185d83d0303d7898641cb6653585a8e1dabfa7f665e61e0498963e329e6e3744bd764db2d72037ae057d89ec0b46ff8e9ff4c37e85c12acddb611c3f636421bef1542c11b04419602cd039d0b1e46c21540d033143440d2fb7dd5d650cf89981c99ee53c6e0374d2b1b6fce03c046fccb95549910767d0543f5e8ce41d66ae6a8720a46f4049cac3b3d26dafb023479c9c3b86a0d3c8be3db0a2d186788e9af1db76d55f3dad127d15185d83d0303d7898641cb6653585a8e1dabfa7f665e61e0498963e329e6e3744bd764db2d72037ae057d89ec0b46ff8e9ff4c37e85c12acddb611c3f636421bef1542c11b04419702cd039d0b1e46c21540d033143440d2fb7dd5d650cf89981c99ee53c6e0374d2b1b6fce03c046fccb95549910767d0543f5e8ce41d66ae6a8720a46f4049cac3b3d26dafb023479c9c3b86a0d3c8be3db0a2d186788e9af1db76d55f3dad127d15185d83d0303d7898641cb6653585a8e1dabfa7f665e61e0498963e329e6e3744bd764db2d72037ae057d89ec0b46ff8e9ff4c37e85c12acddb611c3f636421bef1542c11b0441980204cd039d0b1e46c21540d033143440d2fb7dd5d650cf89981c99ee53c6e0374d2b1b6fce03c046fccb95549910767d0543f5e8ce41d66ae6a8720a46f4049cac3b3d26dafb023479c9c3b86a0d3c8be3db0a2d186788e9af1db76d55f3dad127d15185d83d0303d7898641cb6653585a8e1dabfa7f665e61e0498963e329e6e3744bd764db2d72037ae057d89ec0b46ff8e9ff4c37e85c12acddb611c3f636421bef1542c11b04419702cd039d0b1e46c21540d033143440d2fb7dd5d650cf89981c99ee53c6e0374d2b1b6fce03c046fccb95549910767d0543f5e8ce41d66ae6a8720a46f4049cac3b3d26dafb023479c9c3b86a0d3c8be3db0a2d186788e9af1db76d55f3dad127d15185d83d0303d7898641cb6653585a8e1dabfa7f665e61e0498963e329e6e3744bd764db2d72037ae057d89ec0b46ff8e9ff4c37e85c12acddb611c3f636421bef1542c11b04419602cd039d0b1e46c21540d033143440d2fb7dd5d650cf89981c99ee53c6e0374d2b1b6fce03c046fccb95549910767d0543f5e8ce41d66ae6a8720a46f4049cac3b3d26dafb023479c9c3b86a0d3c8be3db0a2d186788e9af1db76d55f3dad127d15185d83d0303d7898641cb6653585a8e1dabfa7f665e61e0498963e329e6e3744bd764db2d72037ae057d89ec0b46ff8e9ff4c37e85c12acddb611c3f636421bef1542c11b0441" ) - ), cost = 1791, newDetails(36), expectedNewCost = 1791) + ), cost = 1791, newDetails(36), expectedNewCost = 1791, 2021 +: Seq.fill(3)(2023)) ) }, existingFeature((x: SigmaProp) => x.propBytes, @@ -9557,19 +9690,20 @@ class SigmaDslSpecification extends SigmaDslTesting property("allOf equivalence") { def costDetails(i: Int) = TracedCost(traceBase :+ SeqCostItem(CompanionDesc(AND), PerItemCost(JitCost(10), JitCost(5), 32), i)) + val v3Costs = 1995 +: Seq.fill(3)(1997) verifyCases( Seq( - (Coll[Boolean]() -> Expected(Success(true), 1765, costDetails(0), 1765)), - (Coll[Boolean](true) -> Expected(Success(true), 1765, costDetails(1), 1765)), - (Coll[Boolean](false) -> Expected(Success(false), 1765, costDetails(1), 1765)), - (Coll[Boolean](false, false) -> Expected(Success(false), 1765, costDetails(1), 1765)), - (Coll[Boolean](false, true) -> Expected(Success(false), 1765, costDetails(1), 1765)), - (Coll[Boolean](true, false) -> Expected(Success(false), 1765, costDetails(2), 1765)), - (Coll[Boolean](true, true) -> Expected(Success(true), 1765, costDetails(2), 1765)), - (Coll[Boolean](true, false, false) -> Expected(Success(false), 1765, costDetails(2), 1765)), - (Coll[Boolean](true, false, true) -> Expected(Success(false), 1765, costDetails(2), 1765)), - (Coll[Boolean](true, true, false) -> Expected(Success(false), 1765, costDetails(3), 1765)), - (Coll[Boolean](true, true, true) -> Expected(Success(true), 1765, costDetails(3), 1765)) + (Coll[Boolean]() -> Expected(Success(true), 1765, costDetails(0), 1765, v3Costs)), + (Coll[Boolean](true) -> Expected(Success(true), 1765, costDetails(1), 1765, v3Costs)), + (Coll[Boolean](false) -> Expected(Success(false), 1765, costDetails(1), 1765, v3Costs)), + (Coll[Boolean](false, false) -> Expected(Success(false), 1765, costDetails(1), 1765, v3Costs)), + (Coll[Boolean](false, true) -> Expected(Success(false), 1765, costDetails(1), 1765, v3Costs)), + (Coll[Boolean](true, false) -> Expected(Success(false), 1765, costDetails(2), 1765, v3Costs)), + (Coll[Boolean](true, true) -> Expected(Success(true), 1765, costDetails(2), 1765, v3Costs)), + (Coll[Boolean](true, false, false) -> Expected(Success(false), 1765, costDetails(2), 1765, v3Costs)), + (Coll[Boolean](true, false, true) -> Expected(Success(false), 1765, costDetails(2), 1765, v3Costs)), + (Coll[Boolean](true, true, false) -> Expected(Success(false), 1765, costDetails(3), 1765, v3Costs)), + (Coll[Boolean](true, true, true) -> Expected(Success(true), 1765, costDetails(3), 1765, v3Costs)) ), existingFeature((x: Coll[Boolean]) => SigmaDsl.allOf(x), "{ (x: Coll[Boolean]) => allOf(x) }", @@ -9578,19 +9712,20 @@ class SigmaDslSpecification extends SigmaDslTesting property("anyOf equivalence") { def costDetails(i: Int) = TracedCost(traceBase :+ SeqCostItem(CompanionDesc(OR), PerItemCost(JitCost(5), JitCost(5), 64), i)) + val v3Costs = 1994 +: Seq.fill(3)(1996) verifyCases( Seq( - (Coll[Boolean]() -> Expected(Success(false), 1764, costDetails(0), 1764)), - (Coll[Boolean](true) -> Expected(Success(true), 1764, costDetails(1), 1764)), - (Coll[Boolean](false) -> Expected(Success(false), 1764, costDetails(1), 1764)), - (Coll[Boolean](false, false) -> Expected(Success(false), 1764, costDetails(2), 1764)), - (Coll[Boolean](false, true) -> Expected(Success(true), 1764, costDetails(2), 1764)), - (Coll[Boolean](true, false) -> Expected(Success(true), 1764, costDetails(1), 1764)), - (Coll[Boolean](true, true) -> Expected(Success(true), 1764, costDetails(1), 1764)), - (Coll[Boolean](true, false, false) -> Expected(Success(true), 1764, costDetails(1), 1764)), - (Coll[Boolean](true, false, true) -> Expected(Success(true), 1764, costDetails(1), 1764)), - (Coll[Boolean](true, true, false) -> Expected(Success(true), 1764, costDetails(1), 1764)), - (Coll[Boolean](true, true, true) -> Expected(Success(true), 1764, costDetails(1), 1764)) + (Coll[Boolean]() -> Expected(Success(false), 1764, costDetails(0), 1764, v3Costs)), + (Coll[Boolean](true) -> Expected(Success(true), 1764, costDetails(1), 1764, v3Costs)), + (Coll[Boolean](false) -> Expected(Success(false), 1764, costDetails(1), 1764, v3Costs)), + (Coll[Boolean](false, false) -> Expected(Success(false), 1764, costDetails(2), 1764, v3Costs)), + (Coll[Boolean](false, true) -> Expected(Success(true), 1764, costDetails(2), 1764, v3Costs)), + (Coll[Boolean](true, false) -> Expected(Success(true), 1764, costDetails(1), 1764, v3Costs)), + (Coll[Boolean](true, true) -> Expected(Success(true), 1764, costDetails(1), 1764, v3Costs)), + (Coll[Boolean](true, false, false) -> Expected(Success(true), 1764, costDetails(1), 1764, v3Costs)), + (Coll[Boolean](true, false, true) -> Expected(Success(true), 1764, costDetails(1), 1764, v3Costs)), + (Coll[Boolean](true, true, false) -> Expected(Success(true), 1764, costDetails(1), 1764, v3Costs)), + (Coll[Boolean](true, true, true) -> Expected(Success(true), 1764, costDetails(1), 1764, v3Costs)) ), existingFeature((x: Coll[Boolean]) => SigmaDsl.anyOf(x), "{ (x: Coll[Boolean]) => anyOf(x) }", @@ -9603,10 +9738,11 @@ class SigmaDslSpecification extends SigmaDslTesting Seq( (Helpers.decodeGroupElement("02288f0e55610c3355c89ed6c5de43cf20da145b8c54f03a29f481e540d94e9a69") -> Expected(Success( - CSigmaProp(ProveDlog(Helpers.decodeECPoint("02288f0e55610c3355c89ed6c5de43cf20da145b8c54f03a29f481e540d94e9a69")))), - cost = 1782, - costDetails, - 1782)) + CSigmaProp(ProveDlog(Helpers.decodeECPoint("02288f0e55610c3355c89ed6c5de43cf20da145b8c54f03a29f481e540d94e9a69")))), + cost = 1782, + costDetails, + 1782, + 2012 +: Seq.fill(3)(2014))) ), existingFeature({ (x: GroupElement) => SigmaDsl.proveDlog(x) }, "{ (x: GroupElement) => proveDlog(x) }", @@ -9626,18 +9762,19 @@ class SigmaDslSpecification extends SigmaDslTesting Seq( (Helpers.decodeGroupElement("039c15221a318d27c186eba84fa8d986c1f63bbd9f8060380c9bfc2ef455d8346a") -> Expected(Success( - CSigmaProp( - ProveDHTuple( - Helpers.decodeECPoint("039c15221a318d27c186eba84fa8d986c1f63bbd9f8060380c9bfc2ef455d8346a"), - Helpers.decodeECPoint("039c15221a318d27c186eba84fa8d986c1f63bbd9f8060380c9bfc2ef455d8346a"), - Helpers.decodeECPoint("039c15221a318d27c186eba84fa8d986c1f63bbd9f8060380c9bfc2ef455d8346a"), - Helpers.decodeECPoint("039c15221a318d27c186eba84fa8d986c1f63bbd9f8060380c9bfc2ef455d8346a") - ) - )), - cost = 1836, - costDetails, - 1836 - )) + CSigmaProp( + ProveDHTuple( + Helpers.decodeECPoint("039c15221a318d27c186eba84fa8d986c1f63bbd9f8060380c9bfc2ef455d8346a"), + Helpers.decodeECPoint("039c15221a318d27c186eba84fa8d986c1f63bbd9f8060380c9bfc2ef455d8346a"), + Helpers.decodeECPoint("039c15221a318d27c186eba84fa8d986c1f63bbd9f8060380c9bfc2ef455d8346a"), + Helpers.decodeECPoint("039c15221a318d27c186eba84fa8d986c1f63bbd9f8060380c9bfc2ef455d8346a") + ) + )), + cost = 1836, + costDetails, + 1836, + 2078 +: Seq.fill(3)(2080) + )) ), existingFeature({ (x: GroupElement) => SigmaDsl.proveDHTuple(x, x, x, x) }, "{ (x: GroupElement) => proveDHTuple(x, x, x, x) }", @@ -9678,7 +9815,7 @@ class SigmaDslSpecification extends SigmaDslTesting ) verifyCases( { - def success[T](v: T, cd: CostDetails, cost: Int) = Expected(Success(v), cost, cd, cost) + def success[T](v: T, cd: CostDetails, cost: Int, expectedV3Costs: Seq[Int]) = Expected(Success(v), cost, cd, cost, expectedV3Costs) Seq( (Helpers.decodeBytes(""), 0) -> Expected(new java.nio.BufferUnderflowException()), @@ -9690,8 +9827,16 @@ class SigmaDslSpecification extends SigmaDslTesting expectedDetails = CostDetails.ZeroCost, newCost = 1783, newVersionedResults = { - val res = (ExpectedResult(Success(Helpers.decodeBytes("0008d3")), Some(1783)) -> Some(costDetails(0))) - Seq(0, 1, 2).map(version => version -> res) + val costs = if (activatedVersionInTests >= 3) { + 2051 +: Seq.fill(3)(2055) + } + else { + Seq.fill(4)(1783) + } + Seq(0, 1, 2, 3).map({ version => + val res = (ExpectedResult(Success(Helpers.decodeBytes("0008d3")), Some(costs(version))) -> Some(costDetails(0))) + version -> res + }) }), (Helpers.decodeBytes("000008d3"), 0) -> Expected( @@ -9700,18 +9845,26 @@ class SigmaDslSpecification extends SigmaDslTesting expectedDetails = CostDetails.ZeroCost, newCost = 1783, newVersionedResults = { - // since the tree without constant segregation, substitution has no effect - val res = (ExpectedResult(Success(Helpers.decodeBytes("000008d3")), Some(1783)) -> Some(costDetails(0))) - Seq(0, 1, 2).map(version => version -> res) + val costs = if (activatedVersionInTests >= 3) { + 2051 +: Seq.fill(3)(2055) + } + else { + Seq.fill(4)(1783) + } + Seq(0, 1, 2, 3).map({ version => + // since the tree without constant segregation, substitution has no effect + val res = (ExpectedResult(Success(Helpers.decodeBytes("000008d3")), Some(costs(version))) -> Some(costDetails(0))) + version -> res + }) }), // tree with segregation flag, empty constants array - (Coll(t2.bytes:_*), 0) -> success(Helpers.decodeBytes("100008d3"), costDetails(0), 1783), - (Helpers.decodeBytes("100008d3"), 0) -> success(Helpers.decodeBytes("100008d3"), costDetails(0), 1783), + (Coll(t2.bytes: _*), 0) -> success(Helpers.decodeBytes("100008d3"), costDetails(0), 1783, 2051 +: Seq.fill(3)(2055)), + (Helpers.decodeBytes("100008d3"), 0) -> success(Helpers.decodeBytes("100008d3"), costDetails(0), 1783, 2051 +: Seq.fill(3)(2055)), // tree with one segregated constant - (Coll(t3.bytes:_*), 0) -> success(Helpers.decodeBytes("100108d27300"), costDetails(1), 1793), - (Helpers.decodeBytes("100108d37300"), 0) -> success(Helpers.decodeBytes("100108d27300"), costDetails(1), 1793), - (Coll(t3.bytes:_*), 1) -> success(Helpers.decodeBytes("100108d37300"), costDetails(1), 1793), - (Coll(t4.bytes:_*), 0) -> Expected(new IllegalArgumentException("requirement failed: expected new constant to have the same SInt$ tpe, got SSigmaProp")) + (Coll(t3.bytes: _*), 0) -> success(Helpers.decodeBytes("100108d27300"), costDetails(1), 1793, 2061 +: Seq.fill(3)(2065)), + (Helpers.decodeBytes("100108d37300"), 0) -> success(Helpers.decodeBytes("100108d27300"), costDetails(1), 1793, 2061 +: Seq.fill(3)(2065)), + (Coll(t3.bytes: _*), 1) -> success(Helpers.decodeBytes("100108d37300"), costDetails(1), 1793, 2061 +: Seq.fill(3)(2065)), + (Coll(t4.bytes: _*), 0) -> Expected(new IllegalArgumentException("requirement failed: expected new constant to have the same SInt$ tpe, got SSigmaProp")) ) }, changedFeature( @@ -9766,6 +9919,12 @@ class SigmaDslSpecification extends SigmaDslTesting if (lowerMethodCallsInTests) { val error = new RuntimeException("any exception") + val costs = if (activatedVersionInTests >= 3) { + 2140 +: Seq.fill(3)(2144) + } + else { + Seq.fill(4)(1776) + } verifyCases( Seq( ctx -> Expected( @@ -9773,7 +9932,9 @@ class SigmaDslSpecification extends SigmaDslTesting cost = 1776, expectedDetails = CostDetails.ZeroCost, newCost = 1776, - newVersionedResults = (0 to 2).map(i => i -> (ExpectedResult(Success(true), Some(1776)) -> Some(costDetails))) + newVersionedResults = (0 to 3).map({ i => + i -> (ExpectedResult(Success(true), Some(costs(i))) -> Some(costDetails)) + }) ) ), changedFeature( @@ -9884,8 +10045,8 @@ class SigmaDslSpecification extends SigmaDslTesting property("nested loops: map inside fold") { val keys = Colls.fromArray(Array(Coll[Byte](1, 2, 3, 4, 5))) val initial = Coll[Byte](0, 0, 0, 0, 0) - val cases = Seq( - (keys, initial) -> Expected(Success(Coll[Byte](1, 2, 3, 4, 5)), cost = 1801, expectedDetails = CostDetails.ZeroCost, 1801) + val cases = Seq( + (keys, initial) -> Expected(Success(Coll[Byte](1, 2, 3, 4, 5)), cost = 1801, expectedDetails = CostDetails.ZeroCost, 1801, 2115 +: Seq.fill(3)(2119)) ) val scalaFunc = { (x: (Coll[Coll[Byte]], Coll[Byte])) => x._1.foldLeft(x._2, { (a: (Coll[Byte], Coll[Byte])) => diff --git a/sc/shared/src/test/scala/sigma/SigmaDslTesting.scala b/sc/shared/src/test/scala/sigma/SigmaDslTesting.scala index 4aff49761e..62ad4aa4d8 100644 --- a/sc/shared/src/test/scala/sigma/SigmaDslTesting.scala +++ b/sc/shared/src/test/scala/sigma/SigmaDslTesting.scala @@ -447,6 +447,7 @@ class SigmaDslTesting extends AnyPropSpec ok shouldBe true val verificationCost = cost.toIntExact if (expectedCost.isDefined) { + if (verificationCost != expectedCost.get) assertResult(expectedCost.get, s"Actual verify() cost $cost != expected ${expectedCost.get}")(verificationCost) } @@ -971,6 +972,30 @@ class SigmaDslTesting extends AnyPropSpec } } + /** Used when the old and new value and costs are the same for all versions, but Version 3 (Ergo 6.0) will have a different cost due to deserialization cost being added. + * Different versions of ErgoTree can have different deserialization costs as well + * + * @param value expected result of tested function + * @param cost expected verification cost + * @param expectedDetails expected cost details for all versions <= V3 + * @param expectedNewCost expected new verification cost for all versions <= V3 + * @param expectedV3Cost expected cost for >=V3 + */ + def apply[A](value: Try[A], + cost: Int, + expectedDetails: CostDetails, + expectedNewCost: Int, + expectedV3Costs: Seq[Int] + )(implicit dummy: DummyImplicit): Expected[A] = + new Expected(ExpectedResult(value, Some(cost))) { + override val newResults = defaultNewResults.zipWithIndex.map { + case ((ExpectedResult(v, _), _), version) => { + var cost = if (activatedVersionInTests >= 3) expectedV3Costs(version) else expectedNewCost + (ExpectedResult(v, Some(cost)), Some(expectedDetails)) + } + } + } + /** Used when operation semantics changes in new versions. For those versions expected * test vectors can be specified. * From 47f2272001c005854cbc70d7e872829576d3f698 Mon Sep 17 00:00:00 2001 From: Kamal Ahmad Date: Wed, 22 Nov 2023 19:33:19 +0500 Subject: [PATCH 005/314] Rebase to v6.0.0 --- .../scala/sigma/SigmaDslSpecification.scala | 35 ++++++++++--------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/sc/shared/src/test/scala/sigma/SigmaDslSpecification.scala b/sc/shared/src/test/scala/sigma/SigmaDslSpecification.scala index 4124d6226f..dc2bb98608 100644 --- a/sc/shared/src/test/scala/sigma/SigmaDslSpecification.scala +++ b/sc/shared/src/test/scala/sigma/SigmaDslSpecification.scala @@ -180,7 +180,7 @@ class SigmaDslSpecification extends SigmaDslTesting FixedCostItem(GetVar), FixedCostItem(OptionGet), FixedCostItem(FuncValue.AddToEnvironmentDesc, FuncValue.AddToEnvironmentDesc_CostKind), - SeqCostItem(CompanionDesc(BlockValue), PerItemCost(JitCost(1), JitCost(1), 10), 2), + SeqCostItem(CompanionDesc(BlockValue), PerItemCost(JitCost(1), JitCost(1), 10), 2), FixedCostItem(ValUse), FixedCostItem(SelectField), FixedCostItem(FuncValue.AddToEnvironmentDesc, FuncValue.AddToEnvironmentDesc_CostKind), @@ -1621,7 +1621,9 @@ class SigmaDslSpecification extends SigmaDslTesting property("Int LT, GT, NEQ") { val o = ExactOrdering.IntIsExactOrdering + def expect(v: Boolean) = Expected(Success(v), 1768, binaryRelationCostDetails(LT, SInt), 1768, 2010 +: Seq.fill(3)(2012)) + val LT_cases: Seq[((Int, Int), Expected[Boolean])] = Seq( (Int.MinValue, Int.MinValue) -> expect(false), (Int.MinValue, (Int.MinValue + 1).toInt) -> expect(true), @@ -2374,14 +2376,13 @@ class SigmaDslSpecification extends SigmaDslTesting } /** Executed a series of test cases of NEQ operation verify using two _different_ - * data instances `x` and `y`. - * - * @param cost the expected cost of `verify` (the same for all cases) - */ - def verifyNeq[A: Ordering : Arbitrary : RType] - (x: A, y: A, cost: Int, neqCost: Seq[CostItem] = ArraySeq.empty, newCost: Int, expectedV3Costs: Seq[Int]) - (copy: A => A, generateCases: Boolean = true) - (implicit sampled: Sampled[(A, A)], evalSettings: EvalSettings) = { + * data instances `x` and `y`. + * @param cost the expected cost of `verify` (the same for all cases) + */ + def verifyNeq[A: Ordering: Arbitrary: RType] + (x: A, y: A, cost: Int, neqCost: Seq[CostItem] = ArraySeq.empty, newCost: Int, expectedV3Costs: Seq[Int]) + (copy: A => A, generateCases: Boolean = true) + (implicit sampled: Sampled[(A, A)], evalSettings: EvalSettings) = { val copied_x = copy(x) val newCostDetails = if (neqCost.isEmpty) CostDetails.ZeroCost else costNEQ(neqCost) def expected(v: Boolean) = Expected(Success(v), cost, newCostDetails, newCost, expectedV3Costs) @@ -7050,14 +7051,14 @@ class SigmaDslSpecification extends SigmaDslTesting ) }, existingFeature({ (x: Coll[Box]) => x.exists({ (b: Box) => b.value > 1 }) }, - "{ (x: Coll[Box]) => x.exists({(b: Box) => b.value > 1 }) }", - FuncValue( - Vector((1, SCollectionType(SBox))), - Exists( - ValUse(1, SCollectionType(SBox)), - FuncValue(Vector((3, SBox)), GT(ExtractAmount(ValUse(3, SBox)), LongConstant(1L))) - ) - )), + "{ (x: Coll[Box]) => x.exists({(b: Box) => b.value > 1 }) }", + FuncValue( + Vector((1, SCollectionType(SBox))), + Exists( + ValUse(1, SCollectionType(SBox)), + FuncValue(Vector((3, SBox)), GT(ExtractAmount(ValUse(3, SBox)), LongConstant(1L))) + ) + )), preGeneratedSamples = Some(samples)) } else { def error = new java.lang.NoSuchMethodException("sigmastate.SCollection$.exist_eval(sigmastate.lang.Terms$MethodCall,sigma.Coll,scala.Function1,sigmastate.interpreter.ErgoTreeEvaluator))") From 7a1a8c826665d0ad784b55f86ab5029be0d6e80c Mon Sep 17 00:00:00 2001 From: Kamal Ahmad Date: Wed, 29 Nov 2023 04:16:52 +0500 Subject: [PATCH 006/314] Use VersionContext.EvolutionVersion for V3 tests --- .../scala/sigma/SigmaDslSpecification.scala | 21 ++++++++++--------- .../test/scala/sigma/SigmaDslTesting.scala | 4 ++-- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/sc/shared/src/test/scala/sigma/SigmaDslSpecification.scala b/sc/shared/src/test/scala/sigma/SigmaDslSpecification.scala index dc2bb98608..8d7d8ef4e3 100644 --- a/sc/shared/src/test/scala/sigma/SigmaDslSpecification.scala +++ b/sc/shared/src/test/scala/sigma/SigmaDslSpecification.scala @@ -39,6 +39,7 @@ import sigmastate.crypto.ProveDHTuple import sigmastate.interpreter._ import org.scalactic.source.Position import sigma.VersionContext +import sigma.VersionContext.EvolutionVersion import sigmastate.helpers.SigmaPPrint import sigmastate.exceptions.GraphBuildingException @@ -5153,7 +5154,7 @@ class SigmaDslSpecification extends SigmaDslTesting newVersionedResults = { val expectedV3Costs = 2000 +: Seq.fill(3)(2002) // V3 activation will have different costs due to deserialization cost - val costs = if (activatedVersionInTests >= 3) { + val costs = if (activatedVersionInTests >= EvolutionVersion) { expectedV3Costs } else { Seq.fill(4)(1766) @@ -5360,7 +5361,7 @@ class SigmaDslSpecification extends SigmaDslTesting newVersionedResults = { val expectedV3Costs = 2117 +: Seq.fill(3)(2121) // V3 activation will have different costs due to deserialization cost - val costs = if (activatedVersionInTests >= 3) { + val costs = if (activatedVersionInTests >= EvolutionVersion) { expectedV3Costs } else { Seq.fill(4)(1793) @@ -6319,7 +6320,7 @@ class SigmaDslSpecification extends SigmaDslTesting expectedDetails = CostDetails.ZeroCost, newCost = 1766, newVersionedResults = { - val costs = if (activatedVersionInTests >= 3) { + val costs = if (activatedVersionInTests >= EvolutionVersion) { 1996 +: Seq.fill(3)(1998) } else { @@ -6608,7 +6609,7 @@ class SigmaDslSpecification extends SigmaDslTesting expectedDetails = CostDetails.ZeroCost, newCost = 1769, newVersionedResults = { - val costs = if (activatedVersionInTests >= 3) { + val costs = if (activatedVersionInTests >= EvolutionVersion) { 2019 +: Seq.fill(3)(2021) } else { Seq.fill(4)(1769) @@ -7392,7 +7393,7 @@ class SigmaDslSpecification extends SigmaDslTesting Seq( Coll[GroupElement]() -> Expected(Success(Coll[Byte]()), 1773, CostDetails.ZeroCost, 1773, newVersionedResults = { - val costs = if (activatedVersionInTests >= 3) { + val costs = if (activatedVersionInTests >= EvolutionVersion) { 2027 +: Seq.fill(3)(2029) } else { @@ -7453,7 +7454,7 @@ class SigmaDslSpecification extends SigmaDslTesting expectedDetails = CostDetails.ZeroCost, newCost = 1840, newVersionedResults = (0 to 3).map({ version => - val costs = if (activatedVersionInTests >= 3) { + val costs = if (activatedVersionInTests >= EvolutionVersion) { 2100 +: Seq.fill(3)(2104) } else { @@ -9248,7 +9249,7 @@ class SigmaDslSpecification extends SigmaDslTesting expectedDetails = CostDetails.ZeroCost, newCost = 1766, newVersionedResults = Seq.tabulate(4)({ v => - val costs = if (activatedVersionInTests >= 3) { + val costs = if (activatedVersionInTests >= EvolutionVersion) { 2038 +: Seq.fill(3)(2042) } else { @@ -9828,7 +9829,7 @@ class SigmaDslSpecification extends SigmaDslTesting expectedDetails = CostDetails.ZeroCost, newCost = 1783, newVersionedResults = { - val costs = if (activatedVersionInTests >= 3) { + val costs = if (activatedVersionInTests >= EvolutionVersion) { 2051 +: Seq.fill(3)(2055) } else { @@ -9846,7 +9847,7 @@ class SigmaDslSpecification extends SigmaDslTesting expectedDetails = CostDetails.ZeroCost, newCost = 1783, newVersionedResults = { - val costs = if (activatedVersionInTests >= 3) { + val costs = if (activatedVersionInTests >= EvolutionVersion) { 2051 +: Seq.fill(3)(2055) } else { @@ -9920,7 +9921,7 @@ class SigmaDslSpecification extends SigmaDslTesting if (lowerMethodCallsInTests) { val error = new RuntimeException("any exception") - val costs = if (activatedVersionInTests >= 3) { + val costs = if (activatedVersionInTests >= EvolutionVersion) { 2140 +: Seq.fill(3)(2144) } else { diff --git a/sc/shared/src/test/scala/sigma/SigmaDslTesting.scala b/sc/shared/src/test/scala/sigma/SigmaDslTesting.scala index 62ad4aa4d8..6a76930bfd 100644 --- a/sc/shared/src/test/scala/sigma/SigmaDslTesting.scala +++ b/sc/shared/src/test/scala/sigma/SigmaDslTesting.scala @@ -13,6 +13,7 @@ import org.scalatest.matchers.should.Matchers import org.scalatest.propspec.AnyPropSpec import org.scalatestplus.scalacheck.ScalaCheckPropertyChecks import scalan.Platform.threadSleepOrNoOp +import sigma.VersionContext.EvolutionVersion import sigma.data.{CollType, OptionType, PairType, RType} import sigma.util.BenchmarkUtil import sigma.util.CollectionUtil._ @@ -447,7 +448,6 @@ class SigmaDslTesting extends AnyPropSpec ok shouldBe true val verificationCost = cost.toIntExact if (expectedCost.isDefined) { - if (verificationCost != expectedCost.get) assertResult(expectedCost.get, s"Actual verify() cost $cost != expected ${expectedCost.get}")(verificationCost) } @@ -990,7 +990,7 @@ class SigmaDslTesting extends AnyPropSpec new Expected(ExpectedResult(value, Some(cost))) { override val newResults = defaultNewResults.zipWithIndex.map { case ((ExpectedResult(v, _), _), version) => { - var cost = if (activatedVersionInTests >= 3) expectedV3Costs(version) else expectedNewCost + var cost = if (activatedVersionInTests >= EvolutionVersion) expectedV3Costs(version) else expectedNewCost (ExpectedResult(v, Some(cost)), Some(expectedDetails)) } } From bd6112535698f405403d226db9bccfd06123e9ff Mon Sep 17 00:00:00 2001 From: Kamal Ahmad Date: Thu, 21 Dec 2023 22:41:55 +0500 Subject: [PATCH 007/314] ScriptVersionSwitchSpecification change rules 19,20 from skip-accept to full V6 Validation + Add new rule tests for BlockVer V4/Script v3 --- .../ScriptVersionSwitchSpecification.scala | 33 ++++++++++--------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/sc/shared/src/test/scala/sigmastate/ScriptVersionSwitchSpecification.scala b/sc/shared/src/test/scala/sigmastate/ScriptVersionSwitchSpecification.scala index ad5af68649..2eaf82f49d 100644 --- a/sc/shared/src/test/scala/sigmastate/ScriptVersionSwitchSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/ScriptVersionSwitchSpecification.scala @@ -266,44 +266,45 @@ class ScriptVersionSwitchSpecification extends SigmaDslTesting { /** Rule#| BlockVer | Block Type| Script Version | Release | Validation Action * -----|----------|-----------|----------------|---------|-------- - * 19 | 4 | candidate | Script v3 | v5.0 | skip-accept (rely on majority) - * 20 | 4 | mined | Script v3 | v5.0 | skip-accept (rely on majority) + * 19 | 4 | candidate | Script v3 | v6.0 | R6.0-JIT-verify + * 20 | 4 | mined | Script v3 | v6.0 | R6.0-JIT-verify */ property("Rules 19,20 | Block v4 | candidate or mined block | Script v3") { forEachActivatedScriptVersion(activatedVers = Array[Byte](3)) // version for Block v4 { - forEachErgoTreeVersion(ergoTreeVers = Array[Byte](3, 4)) { // scripts >= v3 + forEachErgoTreeVersion(ergoTreeVers = Array[Byte](3)) { // scripts >= v3 val headerFlags = ErgoTree.headerWithVersion(ergoTreeVersionInTests) val ergoTree = createErgoTree(headerFlags) - // prover is rejecting, because such context parameters doesn't make sense - assertExceptionThrown( - testProve(ergoTree, activatedScriptVersion = activatedVersionInTests), - exceptionLike[InterpreterException](s"Both ErgoTree version ${ergoTree.version} and activated version $activatedVersionInTests is greater than MaxSupportedScriptVersion $MaxSupportedScriptVersion") - ) + // both prove and verify are accepting with full evaluation + val pr = testProve(ergoTree, activatedScriptVersion = activatedVersionInTests) + pr.proof shouldBe Array.emptyByteArray + pr.cost shouldBe 24L // and verify is accepting without evaluation val (ok, cost) = testVerify(ergoTree, activatedScriptVersion = activatedVersionInTests) ok shouldBe true - cost shouldBe 0L + cost shouldBe 24L } } } /** Rule#| BlockVer | Block Type| Script Version | Release | Validation Action * -----|----------|-----------|----------------|---------|-------- - * 21 | 4 | candidate | Script v0/v1 | v5.0 | R5.0-JIT-verify - * 22 | 4 | candidate | Script v2 | v5.0 | R5.0-JIT-verify - * 23 | 4 | mined | Script v0/v1 | v5.0 | R5.0-JIT-verify - * 24 | 4 | mined | Script v2 | v5.0 | R5.0-JIT-verify + * 21 | 4 | candidate | Script v0/v1 | v5.0 | R6.0-JIT-verify + * 22 | 4 | candidate | Script v2 | v5.0 | R6.0-JIT-verify + * 23 | 4 | candidate | Script v3 | v5.0 | R6.0-JIT-verify + * 24 | 4 | mined | Script v0/v1 | v5.0 | R6.0-JIT-verify + * 25 | 4 | mined | Script v2 | v5.0 | R6.0-JIT-verify + * 26 | 4 | mined | Script v3 | v5.0 | R6.0-JIT-verify */ - property("Rules 21,22,23,24 | Block v4 | candidate or mined block | Script v0/v1/v2") { + property("Rules 21,22,23,24,25,26 | Block v4 | candidate or mined block | Script v0/v1/v2/v3") { // this test verifies the normal validation action R5.0-JIT-verify of v5.x releases - // when Block v4 already activated, but the script is v0, v1 or v2. + // when Block v4 already activated, and the script is v0, v1, v2, or v3. forEachActivatedScriptVersion(Array[Byte](3)) // version for Block v4 { - forEachErgoTreeVersion(Array[Byte](0, 1, 2)) { // tree versions supported by v5.x + forEachErgoTreeVersion(Array[Byte](0, 1, 2, 3)) { // tree versions supported by v6.x // SF inactive: check cost vectors of v4.x interpreter val headerFlags = ErgoTree.headerWithVersion(ergoTreeVersionInTests) val ergoTree = createErgoTree(headerFlags) From 01a424ebaeb258e8b027509e3d28e406d4499bf2 Mon Sep 17 00:00:00 2001 From: Kamal Ahmad Date: Fri, 2 Feb 2024 10:35:50 +0500 Subject: [PATCH 008/314] Revise ScriptVersionSwitchSpecification tests for v6.0 --- .../sigmastate/interpreter/Interpreter.scala | 2 +- .../ScriptVersionSwitchSpecification.scala | 43 +++++++++---------- 2 files changed, 22 insertions(+), 23 deletions(-) diff --git a/interpreter/shared/src/main/scala/sigmastate/interpreter/Interpreter.scala b/interpreter/shared/src/main/scala/sigmastate/interpreter/Interpreter.scala index 061afde11b..37a907144d 100644 --- a/interpreter/shared/src/main/scala/sigmastate/interpreter/Interpreter.scala +++ b/interpreter/shared/src/main/scala/sigmastate/interpreter/Interpreter.scala @@ -245,7 +245,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 >= 3) { + applyDeserializeContextJITC(if (VersionContext.current.activatedVersion >= VersionContext.EvolutionVersion) { context1 } else { context diff --git a/sc/shared/src/test/scala/sigmastate/ScriptVersionSwitchSpecification.scala b/sc/shared/src/test/scala/sigmastate/ScriptVersionSwitchSpecification.scala index 2eaf82f49d..7666a013b5 100644 --- a/sc/shared/src/test/scala/sigmastate/ScriptVersionSwitchSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/ScriptVersionSwitchSpecification.scala @@ -266,43 +266,42 @@ class ScriptVersionSwitchSpecification extends SigmaDslTesting { /** Rule#| BlockVer | Block Type| Script Version | Release | Validation Action * -----|----------|-----------|----------------|---------|-------- - * 19 | 4 | candidate | Script v3 | v6.0 | R6.0-JIT-verify - * 20 | 4 | mined | Script v3 | v6.0 | R6.0-JIT-verify + * 19 | 5 | candidate | Script v4 | v6.0 | skip-accept (rely on majority) + * 20 | 5 | mined | Script v4 | v6.0 | skip-accept (rely on majority) */ - property("Rules 19,20 | Block v4 | candidate or mined block | Script v3") { - forEachActivatedScriptVersion(activatedVers = Array[Byte](3)) // version for Block v4 + property("Rules 19,20 | Block v5 | candidate or mined block | Script v4") { + forEachActivatedScriptVersion(activatedVers = Array[Byte](4)) // version for Block v5 { - forEachErgoTreeVersion(ergoTreeVers = Array[Byte](3)) { // scripts >= v3 + forEachErgoTreeVersion(ergoTreeVers = Array[Byte](4, 5)) { // scripts >= v4 val headerFlags = ErgoTree.headerWithVersion(ergoTreeVersionInTests) val ergoTree = createErgoTree(headerFlags) - // both prove and verify are accepting with full evaluation - val pr = testProve(ergoTree, activatedScriptVersion = activatedVersionInTests) - pr.proof shouldBe Array.emptyByteArray - pr.cost shouldBe 24L + // prover is rejecting, because such context parameters doesn't make sense + assertExceptionThrown( + testProve(ergoTree, activatedScriptVersion = activatedVersionInTests), + exceptionLike[InterpreterException](s"Both ErgoTree version ${ergoTree.version} and activated version $activatedVersionInTests is greater than MaxSupportedScriptVersion $MaxSupportedScriptVersion") + ) // and verify is accepting without evaluation val (ok, cost) = testVerify(ergoTree, activatedScriptVersion = activatedVersionInTests) ok shouldBe true - cost shouldBe 24L + cost shouldBe 0L } } } - /** Rule#| BlockVer | Block Type| Script Version | Release | Validation Action - * -----|----------|-----------|----------------|---------|-------- - * 21 | 4 | candidate | Script v0/v1 | v5.0 | R6.0-JIT-verify - * 22 | 4 | candidate | Script v2 | v5.0 | R6.0-JIT-verify - * 23 | 4 | candidate | Script v3 | v5.0 | R6.0-JIT-verify - * 24 | 4 | mined | Script v0/v1 | v5.0 | R6.0-JIT-verify - * 25 | 4 | mined | Script v2 | v5.0 | R6.0-JIT-verify - * 26 | 4 | mined | Script v3 | v5.0 | R6.0-JIT-verify + /** Rule#| BlockVer | Block Type| Script Version | Release | Validation Action + * -----|----------|-----------|-----------------|---------|-------- + * 21 | 5 | candidate | Script v0/v1/v2 | v6.0 | R6.0-JIT-verify + * 22 | 5 | candidate | Script v3 | v6.0 | R6.0-JIT-verify + * 23 | 5 | mined | Script v0/v1/v2 | v6.0 | R6.0-JIT-verify + * 24 | 5 | mined | Script v3 | v6.0 | R6.0-JIT-verify */ - property("Rules 21,22,23,24,25,26 | Block v4 | candidate or mined block | Script v0/v1/v2/v3") { - // this test verifies the normal validation action R5.0-JIT-verify of v5.x releases - // when Block v4 already activated, and the script is v0, v1, v2, or v3. + property("Rules 21,22,23,24 | Block v5 | candidate or mined block | Script v0/v1/v2/v3") { + // this test verifies the normal validation action R6.0-JIT-verify of v6.x releases + // when Block v5 already activated, but the script is v0, v1, v2, or v3. - forEachActivatedScriptVersion(Array[Byte](3)) // version for Block v4 + forEachActivatedScriptVersion(Array[Byte](4)) // version for Block v5 { forEachErgoTreeVersion(Array[Byte](0, 1, 2, 3)) { // tree versions supported by v6.x // SF inactive: check cost vectors of v4.x interpreter From 3865cd11eb3a6fb5fa502d8d47ea0f72caf2890a Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Thu, 21 Mar 2024 12:26:56 +0300 Subject: [PATCH 009/314] removing more unused arguments --- data/shared/src/main/scala/sigma/ast/SigmaPredef.scala | 2 +- data/shared/src/main/scala/sigma/ast/methods.scala | 7 +++---- data/shared/src/main/scala/sigma/ast/trees.scala | 1 - .../scala/sigma/serialization/ErgoTreeSerializer.scala | 2 +- .../main/scala/sigma/serialization/SigmaSerializer.scala | 4 +--- .../main/scala/sigma/interpreter/js/SigmaPropProver.scala | 1 - .../src/main/scala/org/ergoplatform/ErgoLikeContext.scala | 1 - .../shared/src/main/scala/sigmastate/crypto/GF2_192.scala | 2 -- .../src/main/scala/sigmastate/crypto/GF2_192_Poly.scala | 2 -- .../shared/src/main/scala/sigmastate/eval/CProfiler.scala | 6 +++--- .../main/scala/sigmastate/interpreter/Interpreter.scala | 5 ++--- .../main/scala/sigmastate/interpreter/ProverUtils.scala | 6 ++---- 12 files changed, 13 insertions(+), 26 deletions(-) diff --git a/data/shared/src/main/scala/sigma/ast/SigmaPredef.scala b/data/shared/src/main/scala/sigma/ast/SigmaPredef.scala index 5cdbdedaa8..c4bc32e4a5 100644 --- a/data/shared/src/main/scala/sigma/ast/SigmaPredef.scala +++ b/data/shared/src/main/scala/sigma/ast/SigmaPredef.scala @@ -591,7 +591,7 @@ object SigmaPredef { ).map(f => f.name -> f).toMap private val funcNameToIrBuilderMap: Map[String, PredefinedFunc] = - funcs.filter { case (n, f) => f.irInfo.irBuilder != undefined } + funcs.filter { case (_, f) => f.irInfo.irBuilder != undefined } def irBuilderForFunc(name: String): Option[IrBuilderFunc] = funcNameToIrBuilderMap.get(name).map(_.irInfo.irBuilder) } diff --git a/data/shared/src/main/scala/sigma/ast/methods.scala b/data/shared/src/main/scala/sigma/ast/methods.scala index b637acf792..23a73c9fae 100644 --- a/data/shared/src/main/scala/sigma/ast/methods.scala +++ b/data/shared/src/main/scala/sigma/ast/methods.scala @@ -15,7 +15,6 @@ import sigma.serialization.CoreByteWriter.ArgInfo import sigma.utils.SparseArrayContainer import scala.annotation.unused -import scala.language.implicitConversions /** Base type for all companions of AST nodes of sigma lang. */ trait SigmaNodeCompanion @@ -720,7 +719,7 @@ object SCollectionMethods extends MethodsContainer with MethodByNameUnapply { * of flatMap. Other bodies are rejected with throwing exception. */ val flatMap_BodyPatterns = Array[PartialFunction[SValue, Int]]( - { case MethodCall(ValUse(id, tpe), m, args, _) if args.isEmpty => id }, + { case MethodCall(ValUse(id, _), _, args, _) if args.isEmpty => id }, { case ExtractScriptBytes(ValUse(id, _)) => id }, { case ExtractId(ValUse(id, _)) => id }, { case SigmaPropBytes(ValUse(id, _)) => id }, @@ -766,7 +765,7 @@ object SCollectionMethods extends MethodsContainer with MethodByNameUnapply { var res: Nullable[(Int, SValue)] = Nullable.None E.addFixedCost(MatchSingleArgMethodCall_Info) { res = mc match { - case MethodCall(_, m, Seq(FuncValue(args, body)), _) if args.length == 1 => + case MethodCall(_, _, Seq(FuncValue(args, body)), _) if args.length == 1 => val id = args(0)._1 Nullable((id, body)) case _ => @@ -1480,7 +1479,7 @@ case object SGlobalMethods extends MonoTypeMethods { lazy val groupGeneratorMethod = SMethod( this, "groupGenerator", SFunc(SGlobal, SGroupElement), 1, GroupGenerator.costKind) - .withIRInfo({ case (builder, obj, method, args, tparamSubst) => GroupGenerator }) + .withIRInfo({ case (_, _, _, _, _) => GroupGenerator }) .withInfo(GroupGenerator, "") lazy val xorMethod = SMethod( diff --git a/data/shared/src/main/scala/sigma/ast/trees.scala b/data/shared/src/main/scala/sigma/ast/trees.scala index 38d4565f30..39e666a389 100644 --- a/data/shared/src/main/scala/sigma/ast/trees.scala +++ b/data/shared/src/main/scala/sigma/ast/trees.scala @@ -295,7 +295,6 @@ object AND extends LogicalTransformerCompanion { def apply(children: Seq[Value[SBoolean.type]]): AND = AND(ConcreteCollection.fromSeq(children)) -// def apply(head: Value[SBoolean.type], tail: Value[SBoolean.type]*): AND = apply(head +: tail) def apply(items: Value[SBoolean.type]*)(implicit o1: Overloaded1): AND = apply(items) } diff --git a/data/shared/src/main/scala/sigma/serialization/ErgoTreeSerializer.scala b/data/shared/src/main/scala/sigma/serialization/ErgoTreeSerializer.scala index 3d1061d774..91765f764b 100644 --- a/data/shared/src/main/scala/sigma/serialization/ErgoTreeSerializer.scala +++ b/data/shared/src/main/scala/sigma/serialization/ErgoTreeSerializer.scala @@ -299,7 +299,7 @@ class ErgoTreeSerializer { */ def substituteConstants(scriptBytes: Array[Byte], positions: Array[Int], - newVals: Array[Constant[SType]])(implicit vs: SigmaValidationSettings): (Array[Byte], Int) = { + newVals: Array[Constant[SType]]): (Array[Byte], Int) = { require(positions.length == newVals.length, s"expected positions and newVals to have the same length, got: positions: ${positions.toSeq},\n newVals: ${newVals.toSeq}") val r = SigmaSerializer.startReader(scriptBytes) diff --git a/data/shared/src/main/scala/sigma/serialization/SigmaSerializer.scala b/data/shared/src/main/scala/sigma/serialization/SigmaSerializer.scala index cdb28d724b..3765adb029 100644 --- a/data/shared/src/main/scala/sigma/serialization/SigmaSerializer.scala +++ b/data/shared/src/main/scala/sigma/serialization/SigmaSerializer.scala @@ -4,7 +4,6 @@ import java.nio.ByteBuffer import scorex.util.ByteArrayBuilder import scorex.util.serialization._ import sigma.data.SigmaConstants -import sigma.validation.SigmaValidationSettings import sigma.serialization.ValueCodes.OpCode object SigmaSerializer { @@ -35,8 +34,7 @@ object SigmaSerializer { /** Helper function to be use in serializers. */ def startReader(bytes: Array[Byte], constantStore: ConstantStore, - resolvePlaceholdersToConstants: Boolean) - (implicit vs: SigmaValidationSettings): SigmaByteReader = { + resolvePlaceholdersToConstants: Boolean): SigmaByteReader = { val buf = ByteBuffer.wrap(bytes) val r = new SigmaByteReader(new VLQByteBufferReader(buf), constantStore, diff --git a/interpreter/js/src/main/scala/sigma/interpreter/js/SigmaPropProver.scala b/interpreter/js/src/main/scala/sigma/interpreter/js/SigmaPropProver.scala index a04d32fa54..414a9d1220 100644 --- a/interpreter/js/src/main/scala/sigma/interpreter/js/SigmaPropProver.scala +++ b/interpreter/js/src/main/scala/sigma/interpreter/js/SigmaPropProver.scala @@ -65,7 +65,6 @@ class SigmaPropProver(override val wrappedValue: org.ergoplatform.SigmaPropProve val realsToExtract = toSigmaBooleanSeq(realSecretsToExtract) val simsToExtract = toSigmaBooleanSeq(simulatedSecretsToExtract) val hints = wrappedValue.bagForMultisig( - context = null, sigmaTree = sigmaTree.sigmaBoolean, proof.toArray, realSecretsToExtract = realsToExtract, simulatedSecretsToExtract = simsToExtract) diff --git a/interpreter/shared/src/main/scala/org/ergoplatform/ErgoLikeContext.scala b/interpreter/shared/src/main/scala/org/ergoplatform/ErgoLikeContext.scala index 8468175631..e421e8fdfe 100644 --- a/interpreter/shared/src/main/scala/org/ergoplatform/ErgoLikeContext.scala +++ b/interpreter/shared/src/main/scala/org/ergoplatform/ErgoLikeContext.scala @@ -6,7 +6,6 @@ import sigma.ast.SType.{AnyOps, TypeCode} import sigma.ast._ import sigma.data.{AvlTreeData, CAvlTree, CSigmaDslBuilder, SigmaConstants} import sigma.eval.Extensions.toAnyValue -import sigma.exceptions.InterpreterException import sigma.interpreter.ContextExtension import sigma.validation.SigmaValidationSettings import sigma.{AnyValue, Coll, Header, PreHeader} diff --git a/interpreter/shared/src/main/scala/sigmastate/crypto/GF2_192.scala b/interpreter/shared/src/main/scala/sigmastate/crypto/GF2_192.scala index bb0ad60a84..e63526e854 100644 --- a/interpreter/shared/src/main/scala/sigmastate/crypto/GF2_192.scala +++ b/interpreter/shared/src/main/scala/sigmastate/crypto/GF2_192.scala @@ -30,8 +30,6 @@ package sigmastate.crypto import debox.cfor -import java.util - class GF2_192 extends AnyRef { private[crypto] val word: Array[Long] = new Array[Long](3) diff --git a/interpreter/shared/src/main/scala/sigmastate/crypto/GF2_192_Poly.scala b/interpreter/shared/src/main/scala/sigmastate/crypto/GF2_192_Poly.scala index a9212fe565..d2ddc4db48 100644 --- a/interpreter/shared/src/main/scala/sigmastate/crypto/GF2_192_Poly.scala +++ b/interpreter/shared/src/main/scala/sigmastate/crypto/GF2_192_Poly.scala @@ -31,8 +31,6 @@ package sigmastate.crypto import debox.cfor -import java.util - class GF2_192_Poly { final private var c: Array[GF2_192] = null // must be not null and of length at least 1 diff --git a/interpreter/shared/src/main/scala/sigmastate/eval/CProfiler.scala b/interpreter/shared/src/main/scala/sigmastate/eval/CProfiler.scala index ced8a357b8..d07153bd51 100644 --- a/interpreter/shared/src/main/scala/sigmastate/eval/CProfiler.scala +++ b/interpreter/shared/src/main/scala/sigmastate/eval/CProfiler.scala @@ -280,7 +280,7 @@ class CProfiler extends Profiler { case ci: TypeBasedCostItem => val comment = s"count: $count, suggested: $suggestedCost, actCost: ${ci.cost}$warn" (ci.opName, time, time, comment) - case ci @ SeqCostItem(_, costKind, nItems) => + case ci @ SeqCostItem(_, costKind, _) => val nChunks = ci.chunks val timePerChunk = if (nChunks > 0) time / nChunks else time val name = s"${ci.opName}(nChunks: $nChunks)" @@ -289,7 +289,7 @@ class CProfiler extends Profiler { } } (name, timePerItem, time, comment) - }.sortBy({ case (name, tpi, t, c) => (name, tpi)})(Ordering[(String, Long)]) + }.sortBy({ case (name, tpi, _, _) => (name, tpi)})(Ordering[(String, Long)]) val estLines = estimationCostStat.mapToArray { case (script, stat) => val (cost, count) = stat.mean @@ -302,7 +302,7 @@ class CProfiler extends Profiler { val rows = opCodeLines - .map { case (opName, opCode, time, comment) => + .map { case (opName, _, time, comment) => val key = s"$opName".padTo(26, ' ') s"$key -> time: $time ns, $comment " } diff --git a/interpreter/shared/src/main/scala/sigmastate/interpreter/Interpreter.scala b/interpreter/shared/src/main/scala/sigmastate/interpreter/Interpreter.scala index 6b673038c7..523b2a7f35 100644 --- a/interpreter/shared/src/main/scala/sigmastate/interpreter/Interpreter.scala +++ b/interpreter/shared/src/main/scala/sigmastate/interpreter/Interpreter.scala @@ -164,12 +164,11 @@ trait Interpreter { * else `exp` is computed in the given context and the resulting SigmaBoolean returned. * * @param context the context in which `exp` should be executed - * @param env environment of system variables used by the interpreter internally * @param exp expression to be executed in the given `context` * @return result of script reduction * @see `ReductionResult` */ - protected def reduceToCryptoJITC(context: CTX, env: ScriptEnv, exp: SigmaPropValue): Try[ReductionResult] = Try { + protected def reduceToCryptoJITC(context: CTX, exp: SigmaPropValue): Try[ReductionResult] = Try { implicit val vs = context.validationSettings trySoftForkable[ReductionResult](whenSoftFork = WhenSoftForkReductionResult(context.initCost)) { @@ -253,7 +252,7 @@ trait Interpreter { // here we assume that when `propTree` is TrueProp then `reduceToCrypto` always succeeds // and the rest of the verification is also trivial - reduceToCryptoJITC(context2, env, propTree).getOrThrow + reduceToCryptoJITC(context2, propTree).getOrThrow } res diff --git a/interpreter/shared/src/main/scala/sigmastate/interpreter/ProverUtils.scala b/interpreter/shared/src/main/scala/sigmastate/interpreter/ProverUtils.scala index 15daaec382..dc2259b0b7 100644 --- a/interpreter/shared/src/main/scala/sigmastate/interpreter/ProverUtils.scala +++ b/interpreter/shared/src/main/scala/sigmastate/interpreter/ProverUtils.scala @@ -81,7 +81,7 @@ trait ProverUtils extends Interpreter { realSecretsToExtract: Seq[SigmaBoolean], simulatedSecretsToExtract: Seq[SigmaBoolean] = Seq.empty): HintsBag = { val reduced = fullReduction(ergoTree, context, Interpreter.emptyEnv) - bagForMultisig(context, reduced.value, proof, realSecretsToExtract, simulatedSecretsToExtract) + bagForMultisig(reduced.value, proof, realSecretsToExtract, simulatedSecretsToExtract) } /** @@ -90,15 +90,13 @@ trait ProverUtils extends Interpreter { * * See DistributedSigSpecification for examples of usage. * - * @param context - context used to reduce the proposition * @param sigmaTree - public key (in form of a sigma-tree) * @param proof - signature for the key * @param realSecretsToExtract - public keys of secrets with real proofs * @param simulatedSecretsToExtract - public keys of secrets with simulated proofs * @return - bag of OtherSecretProven and OtherCommitment hints */ - def bagForMultisig(context: CTX, - sigmaTree: SigmaBoolean, + def bagForMultisig(sigmaTree: SigmaBoolean, proof: Array[Byte], realSecretsToExtract: Seq[SigmaBoolean], simulatedSecretsToExtract: Seq[SigmaBoolean]): HintsBag = { From 059cac1925bf2619a5ed83b875e3254d99125cc7 Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Fri, 29 Mar 2024 20:21:46 +0300 Subject: [PATCH 010/314] more unused code removed --- data/shared/src/main/scala/sigma/SigmaDataReflection.scala | 3 +-- data/shared/src/main/scala/sigma/ast/SMethod.scala | 2 +- data/shared/src/main/scala/sigma/ast/methods.scala | 2 +- .../src/main/scala/sigmastate/eval/GraphBuilding.scala | 6 ++---- sc/shared/src/main/scala/sigmastate/eval/SigmaLibrary.scala | 2 +- sc/shared/src/main/scala/sigmastate/eval/TreeBuilding.scala | 6 +++--- sc/shared/src/main/scala/sigmastate/lang/SigmaBinder.scala | 1 - sc/shared/src/test/scala/scalan/LibraryTests.scala | 2 +- 8 files changed, 10 insertions(+), 14 deletions(-) diff --git a/data/shared/src/main/scala/sigma/SigmaDataReflection.scala b/data/shared/src/main/scala/sigma/SigmaDataReflection.scala index 31703b0856..276deaeeee 100644 --- a/data/shared/src/main/scala/sigma/SigmaDataReflection.scala +++ b/data/shared/src/main/scala/sigma/SigmaDataReflection.scala @@ -314,8 +314,7 @@ object SigmaDataReflection { registerClassEntry(clazz, methods = Map( mkMethod(clazz, "xor_eval", Array[Class[_]](classOf[MethodCall], classOf[SigmaDslBuilder], classOf[Coll[_]], classOf[Coll[_]], classOf[ErgoTreeEvaluator])) { (obj, args) => - obj.asInstanceOf[SGlobalMethods.type].xor_eval(args(0).asInstanceOf[MethodCall], - args(1).asInstanceOf[SigmaDslBuilder], + obj.asInstanceOf[SGlobalMethods.type].xor_eval( args(2).asInstanceOf[Coll[Byte]], args(3).asInstanceOf[Coll[Byte]])(args(4).asInstanceOf[ErgoTreeEvaluator]) } diff --git a/data/shared/src/main/scala/sigma/ast/SMethod.scala b/data/shared/src/main/scala/sigma/ast/SMethod.scala index 2d306d8948..669625ef1e 100644 --- a/data/shared/src/main/scala/sigma/ast/SMethod.scala +++ b/data/shared/src/main/scala/sigma/ast/SMethod.scala @@ -105,7 +105,7 @@ case class SMethod( /** Invoke this method on the given object with the arguments. * This is used for methods with FixedCost costKind. */ - def invokeFixed(obj: Any, args: Array[Any])(implicit E: ErgoTreeEvaluator): Any = { + def invokeFixed(obj: Any, args: Array[Any]): Any = { javaMethod.invoke(obj, args.asInstanceOf[Array[AnyRef]]:_*) } diff --git a/data/shared/src/main/scala/sigma/ast/methods.scala b/data/shared/src/main/scala/sigma/ast/methods.scala index 23a73c9fae..2cbc2fda8c 100644 --- a/data/shared/src/main/scala/sigma/ast/methods.scala +++ b/data/shared/src/main/scala/sigma/ast/methods.scala @@ -1494,7 +1494,7 @@ case object SGlobalMethods extends MonoTypeMethods { * Called via reflection based on naming convention. * @see SMethod.evalMethod, Xor.eval, Xor.xorWithCosting */ - def xor_eval(mc: MethodCall, G: SigmaDslBuilder, ls: Coll[Byte], rs: Coll[Byte]) + def xor_eval(ls: Coll[Byte], rs: Coll[Byte]) (implicit E: ErgoTreeEvaluator): Coll[Byte] = { Xor.xorWithCosting(ls, rs) } diff --git a/sc/shared/src/main/scala/sigmastate/eval/GraphBuilding.scala b/sc/shared/src/main/scala/sigmastate/eval/GraphBuilding.scala index 9c9fa5ffe1..ed25b6afa4 100644 --- a/sc/shared/src/main/scala/sigmastate/eval/GraphBuilding.scala +++ b/sc/shared/src/main/scala/sigmastate/eval/GraphBuilding.scala @@ -380,8 +380,6 @@ trait GraphBuilding extends SigmaLibrary { IR: IRContext => case _ => error(s"Cannot find BinOp for opcode newOpCode(${opCode.toUByte - LastConstantCode}) and type $eA") } - import sigmastate._ - protected implicit def groupElementToECPoint(g: sigma.GroupElement): EcPointType = CSigmaDslBuilder.toECPoint(g).asInstanceOf[EcPointType] def error(msg: String) = throw new GraphBuildingException(msg, None) @@ -436,7 +434,7 @@ trait GraphBuilding extends SigmaLibrary { IR: IRContext => error(s"Don't know how to buildNode($node)", node.sourceContext.toOption) val res: Ref[Any] = node match { - case c @ Constant(v, tpe) => v match { + case Constant(v, tpe) => v match { case p: SSigmaProp => assert(tpe == SSigmaProp) val resV = liftConst(p) @@ -887,7 +885,7 @@ trait GraphBuilding extends SigmaLibrary { IR: IRContext => f } - case l @ FuncValue(Seq((n, argTpe)), body) => + case FuncValue(Seq((n, argTpe)), body) => val eArg = stypeToElem(argTpe).asInstanceOf[Elem[Any]] val f = fun { x: Ref[Any] => buildNode(ctx, env + (n -> x), body) diff --git a/sc/shared/src/main/scala/sigmastate/eval/SigmaLibrary.scala b/sc/shared/src/main/scala/sigmastate/eval/SigmaLibrary.scala index be17179cbf..7745873620 100644 --- a/sc/shared/src/main/scala/sigmastate/eval/SigmaLibrary.scala +++ b/sc/shared/src/main/scala/sigmastate/eval/SigmaLibrary.scala @@ -10,7 +10,7 @@ trait SigmaLibrary extends Library { import WRType._ - implicit lazy val wRTypeAnyElement = wRTypeElement(AnyElement) + implicit lazy val wRTypeAnyElement: Elem[WRType[Any]] = wRTypeElement(AnyElement) /** During compilation represent a global value Global, see also SGlobal type. */ def sigmaDslBuilder: Ref[SigmaDslBuilder] diff --git a/sc/shared/src/main/scala/sigmastate/eval/TreeBuilding.scala b/sc/shared/src/main/scala/sigmastate/eval/TreeBuilding.scala index 26bc33956f..27f659c1ed 100644 --- a/sc/shared/src/main/scala/sigmastate/eval/TreeBuilding.scala +++ b/sc/shared/src/main/scala/sigmastate/eval/TreeBuilding.scala @@ -161,7 +161,7 @@ trait TreeBuilding extends SigmaLibrary { IR: IRContext => case _ if env.contains(s) => val (id, tpe) = env(s) ValUse(id, tpe) // recursion base - case Def(Lambda(lam, _, x, y)) => + case Def(Lambda(lam, _, x, _)) => val varId = defId + 1 // arguments are treated as ValDefs and occupy id space val env1 = env + (x -> (varId, elemToSType(x.elem))) val block = processAstGraph(ctx, mainG, env1, lam, varId + 1, constantsProcessing) @@ -170,7 +170,7 @@ trait TreeBuilding extends SigmaLibrary { IR: IRContext => case Def(Apply(fSym, xSym, _)) => val Seq(f, x) = Seq(fSym, xSym).map(recurse) builder.mkApply(f, Array(x)) - case Def(th @ ThunkDef(root, _)) => + case Def(th @ ThunkDef(_, _)) => val block = processAstGraph(ctx, mainG, env, th, defId, constantsProcessing) block case Def(Const(x)) => @@ -449,7 +449,7 @@ trait TreeBuilding extends SigmaLibrary { IR: IRContext => (valdefs.toArray[BlockItem], rhs) match { // simple optimization to avoid producing block sub-expressions like: // `{ val idNew = id; idNew }` which this rules rewrites to just `id` - case (Array(ValDef(idNew, _, source @ ValUse(id, tpe))), ValUse(idUse, tpeUse)) + case (Array(ValDef(idNew, _, source @ ValUse(_, tpe))), ValUse(idUse, tpeUse)) if idUse == idNew && tpeUse == tpe => source case (items, _) => BlockValue(items, rhs) diff --git a/sc/shared/src/main/scala/sigmastate/lang/SigmaBinder.scala b/sc/shared/src/main/scala/sigmastate/lang/SigmaBinder.scala index f93e31703d..82aaea7e30 100644 --- a/sc/shared/src/main/scala/sigmastate/lang/SigmaBinder.scala +++ b/sc/shared/src/main/scala/sigmastate/lang/SigmaBinder.scala @@ -1,7 +1,6 @@ package sigmastate.lang import org.ergoplatform.ErgoAddressEncoder.NetworkPrefix -import org.ergoplatform._ import sigma.ast.NoType import sigma.data.Nullable import sigma.kiama.rewriting.CallbackRewriter diff --git a/sc/shared/src/test/scala/scalan/LibraryTests.scala b/sc/shared/src/test/scala/scalan/LibraryTests.scala index e082e9154d..d095a2f20a 100644 --- a/sc/shared/src/test/scala/scalan/LibraryTests.scala +++ b/sc/shared/src/test/scala/scalan/LibraryTests.scala @@ -8,7 +8,7 @@ class Benchmark[T <: Scalan](createContext: => T) { def run() = { val (ctx, total) = measureTime { var ctx = createContext - measure(10000, okShowIterTime = printDebugInfo, okShowTotalTime = printDebugInfo) { i => + measure(10000, okShowIterTime = printDebugInfo, okShowTotalTime = printDebugInfo) { _ => ctx = createContext } ctx From f9856794239258a0137755c3e3ff9e1e35ccbb09 Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Tue, 2 Apr 2024 21:15:59 +0300 Subject: [PATCH 011/314] versioned tests --- .../shared/src/main/scala/sigma/VersionContext.scala | 12 +++++++++--- .../shared/src/test/scala/sigma/VersionTesting.scala | 11 +++++------ .../scala/sigmastate/ErgoTreeSpecification.scala | 1 + 3 files changed, 15 insertions(+), 9 deletions(-) diff --git a/core/shared/src/main/scala/sigma/VersionContext.scala b/core/shared/src/main/scala/sigma/VersionContext.scala index 8d3caf4284..b3b53e9f34 100644 --- a/core/shared/src/main/scala/sigma/VersionContext.scala +++ b/core/shared/src/main/scala/sigma/VersionContext.scala @@ -1,6 +1,6 @@ package sigma -import VersionContext.JitActivationVersion +import VersionContext.{EvolutionVersion, JitActivationVersion} import scala.util.DynamicVariable @@ -21,6 +21,10 @@ case class VersionContext(activatedVersion: Byte, ergoTreeVersion: Byte) { /** @return true, if the activated script version of Ergo protocol on the network is * greater than v1. */ def isJitActivated: Boolean = activatedVersion >= JitActivationVersion + + /** @return true, if the activated script version of Ergo protocol on the network is + * including Evolution update. */ + def isEvolutionActivated: Boolean = activatedVersion >= EvolutionVersion } object VersionContext { @@ -34,9 +38,11 @@ object VersionContext { * - in 6.x must be 3 * etc. */ - val MaxSupportedScriptVersion: Byte = 2 // supported versions 0, 1, 2 + val MaxSupportedScriptVersion: Byte = 3 // supported versions 0, 1, 2, 3 - /** The first version of ErgoTree starting from which the JIT costing interpreter is used. */ + /** The first version of ErgoTree starting from which the JIT costing interpreter must be used. + * It must also be used for all subsequent versions (3, 4, etc). + */ val JitActivationVersion: Byte = 2 /** diff --git a/core/shared/src/test/scala/sigma/VersionTesting.scala b/core/shared/src/test/scala/sigma/VersionTesting.scala index a17fc7a7f9..69e15ff491 100644 --- a/core/shared/src/test/scala/sigma/VersionTesting.scala +++ b/core/shared/src/test/scala/sigma/VersionTesting.scala @@ -6,13 +6,11 @@ import scala.util.DynamicVariable trait VersionTesting { - /** In v5.x we run test for only one activated version on the network (== 2). - * In the branch for v6.0 the new version 3 should be added so that the tests run for both. - */ + /** Tests run for both version 2 & version 3 */ protected val activatedVersions: Seq[Byte] = (0 to VersionContext.MaxSupportedScriptVersion).map(_.toByte).toArray[Byte] - private[sigma] val _currActivatedVersion = new DynamicVariable[Byte](2) // v5.x by default + private[sigma] val _currActivatedVersion = new DynamicVariable[Byte](3) // v6.x by default /** Current activated version used in tests. */ def activatedVersionInTests: Byte = _currActivatedVersion.value @@ -41,9 +39,10 @@ trait VersionTesting { _ + 1) { j => val treeVersion = ergoTreeVers(j) // for each tree version up to currently activated, set it up and execute block - _currErgoTreeVersion.withValue(treeVersion)(block) + _currErgoTreeVersion.withValue(treeVersion) { + VersionContext.withVersions(activatedVersion, treeVersion)(block) + } } - } } } diff --git a/sc/shared/src/test/scala/sigmastate/ErgoTreeSpecification.scala b/sc/shared/src/test/scala/sigmastate/ErgoTreeSpecification.scala index 23406d9cb4..b05ee23e0d 100644 --- a/sc/shared/src/test/scala/sigmastate/ErgoTreeSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/ErgoTreeSpecification.scala @@ -233,6 +233,7 @@ class ErgoTreeSpecification extends SigmaDslTesting with ContractsTestkit { ), true) }, + { // SBigInt inherit methods from SNumericType.methods // however they are not resolvable via SBigInt.typeId import SNumericType._ From 08439025534cfcdb35e5b10792bf615bf14f6ed9 Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Tue, 2 Apr 2024 22:23:12 +0300 Subject: [PATCH 012/314] DecodeNBitsMethod definition --- .../src/main/scala/sigmastate/types.scala | 28 ++++++++++++++----- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/interpreter/shared/src/main/scala/sigmastate/types.scala b/interpreter/shared/src/main/scala/sigmastate/types.scala index 586a06432e..7ba062046a 100644 --- a/interpreter/shared/src/main/scala/sigmastate/types.scala +++ b/interpreter/shared/src/main/scala/sigmastate/types.scala @@ -739,6 +739,7 @@ object SPrimType { /** Marker trait for all numeric types. */ trait SNumericType extends SProduct { import SNumericType._ + protected override def getMethods(): Seq[SMethod] = { super.getMethods() ++ SNumericType.methods.map { m => m.copy(stype = Terms.applySubst(m.stype, Map(tNum -> this)).asFunc) @@ -778,6 +779,7 @@ trait SNumericType extends SProduct { override def toString: String = this.getClass.getSimpleName } + object SNumericType extends STypeCompanion { /** Array of all numeric types ordered by number of bytes in the representation. */ final val allNumericTypes = Array(SByte, SShort, SInt, SLong, SBigInt) @@ -983,7 +985,7 @@ case object SLong extends SPrimType with SEmbeddable with SNumericType with SMon override type WrappedType = Long override val typeCode: TypeCode = 5: Byte override val reprClass: RClass[_] = RClass(classOf[Long]) - override def typeId = typeCode + override def typeId: TypeCode = typeCode override def numericTypeIndex: Int = 3 override def upcast(v: AnyVal): Long = v match { case x: Byte => x.toLong @@ -999,15 +1001,27 @@ case object SLong extends SPrimType with SEmbeddable with SNumericType with SMon case l: Long => l case _ => sys.error(s"Cannot downcast value $v to the type $this") } + + lazy val DecodeNBitsMethod: SMethod = SMethod( + this, "DecodeNBits", SFunc(this, SBigInt), 8, FixedCost(JitCost(5))) + .withInfo(PropertyCall, "Consider this Long value as nbits-encoded BigInt value and decode it to BigInt") + + protected override def getMethods(): Seq[SMethod] = { + if (VersionContext.current.isEvolutionActivated) { + super.getMethods() ++ Seq(DecodeNBitsMethod) + } else { + super.getMethods() + } + } } -/** Type of 256 bit integet values. Implemented using [[java.math.BigInteger]]. */ +/** Type of 256 bit signed integer values. Implemented using [[java.math.BigInteger]]. */ case object SBigInt extends SPrimType with SEmbeddable with SNumericType with SMonoType { override type WrappedType = BigInt override val typeCode: TypeCode = 6: Byte override val reprClass: RClass[_] = RClass(classOf[BigInt]) - override def typeId = typeCode + override def typeId: TypeCode = typeCode /** Type of Relation binary op like GE, LE, etc. */ val RelationOpType = SFunc(Array(SBigInt, SBigInt), SBoolean) @@ -1038,8 +1052,8 @@ case object SBigInt extends SPrimType with SEmbeddable with SNumericType with SM SigmaDsl.BigInt(bi) } - /** The following `modQ` methods are not fully implemented in v4.x and this descriptors. - * This descritors are remain here in the code and are waiting for full implementation + /** The following `modQ` methods are not fully implemented in v4.x. + * The following descriptors remain here in the code and are waiting for full implementation * is upcoming soft-forks at which point the cost parameters should be calculated and * changed. */ @@ -1053,7 +1067,7 @@ case object SBigInt extends SPrimType with SEmbeddable with SNumericType with SM .withIRInfo(MethodCallIrBuilder) .withInfo(MethodCall, "Multiply this number with \\lst{other} by module Q.", ArgInfo("other", "Number to multiply with this.")) - protected override def getMethods() = super.getMethods() ++ Seq( + protected override def getMethods(): Seq[SMethod] = super.getMethods() ++ Seq( // ModQMethod, // PlusModQMethod, // MinusModQMethod, @@ -1067,7 +1081,7 @@ case object SBigInt extends SPrimType with SEmbeddable with SNumericType with SM case object SString extends SProduct with SMonoType { override type WrappedType = String override val typeCode: TypeCode = 102: Byte - override def typeId = typeCode + override def typeId: TypeCode = typeCode override def reprClass: RClass[_] = RClass(classOf[String]) } From 08d6b12a73e66d7a1a4903e247154abdb7dfe255 Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Tue, 2 Apr 2024 22:29:08 +0300 Subject: [PATCH 013/314] unused SSymName.isImportedBy removed --- sc/shared/src/main/scala/scalan/meta/SSymName.scala | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/sc/shared/src/main/scala/scalan/meta/SSymName.scala b/sc/shared/src/main/scala/scalan/meta/SSymName.scala index ea9b1546ba..b0f8dae6d2 100644 --- a/sc/shared/src/main/scala/scalan/meta/SSymName.scala +++ b/sc/shared/src/main/scala/scalan/meta/SSymName.scala @@ -6,16 +6,11 @@ case class ImportItem(packageName: String, importedNames: List[String]) case class SSymName(packageName: String, name: String) { import SSymName._ - def this(name: String) = this("", name) def mkFullName = fullNameString(packageName, name) - def isImportedBy(item: ImportItem): Boolean = { - if (packageName != item.packageName) return false - item.importedNames.contains(SSymName.ImportAllWildcard) || item.importedNames.contains(name) - } } object SSymName { - /** Wildcard character used to signify imporing all names from namespace */ + /** Wildcard character used to signify importing all names from namespace */ val ImportAllWildcard = "*" def fullNameString(packageName: String, name: String): String = if (packageName.isNullOrEmpty) name else s"$packageName.$name" From de8d3cc849997f5fe60af0d4348a6c4c1742067b Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Tue, 2 Apr 2024 22:42:45 +0300 Subject: [PATCH 014/314] unused PassConfig.withConstantPropagation removed --- data/shared/src/main/scala/sigma/ast/methods.scala | 2 +- .../main/scala/sigma/serialization/ErgoTreeSerializer.scala | 4 ++-- .../src/main/scala/sigmastate/interpreter/Interpreter.scala | 2 +- .../sigma/serialization/ConstantSerializerSpecification.scala | 2 +- .../sigma/serialization/DataSerializerSpecification.scala | 1 - sc/shared/src/main/scala/scalan/Library.scala | 2 +- sc/shared/src/main/scala/scalan/staged/Transforming.scala | 3 --- sc/shared/src/main/scala/special/collection/CollsUnit.scala | 2 -- 8 files changed, 6 insertions(+), 12 deletions(-) diff --git a/data/shared/src/main/scala/sigma/ast/methods.scala b/data/shared/src/main/scala/sigma/ast/methods.scala index 2cbc2fda8c..73d9c4b7b8 100644 --- a/data/shared/src/main/scala/sigma/ast/methods.scala +++ b/data/shared/src/main/scala/sigma/ast/methods.scala @@ -234,7 +234,7 @@ object SNumericTypeMethods extends MethodsContainer { | Each boolean corresponds to one bit. """.stripMargin) - protected override def getMethods: Seq[SMethod] = Array( + protected override def getMethods(): Seq[SMethod] = Array( ToByteMethod, // see Downcast ToShortMethod, // see Downcast ToIntMethod, // see Downcast diff --git a/data/shared/src/main/scala/sigma/serialization/ErgoTreeSerializer.scala b/data/shared/src/main/scala/sigma/serialization/ErgoTreeSerializer.scala index 91765f764b..43e41f91ff 100644 --- a/data/shared/src/main/scala/sigma/serialization/ErgoTreeSerializer.scala +++ b/data/shared/src/main/scala/sigma/serialization/ErgoTreeSerializer.scala @@ -1,13 +1,13 @@ package sigma.serialization import org.ergoplatform.validation.ValidationRules.{CheckDeserializedScriptIsSigmaProp, CheckHeaderSizeBit} -import sigma.ast.{Constant, DeserializationSigmaBuilder, ErgoTree, SType, SubstConstants, UnparsedErgoTree} +import sigma.ast.{Constant, DeserializationSigmaBuilder, ErgoTree, SType, UnparsedErgoTree} import sigma.ast.syntax.ValueOps import sigma.ast.ErgoTree.{EmptyConstants, HeaderType} import sigma.util.safeNewArray import debox.cfor import sigma.VersionContext -import sigma.validation.{SigmaValidationSettings, ValidationException} +import sigma.validation.ValidationException import sigma.validation.ValidationRules.CheckPositionLimit /** diff --git a/interpreter/shared/src/main/scala/sigmastate/interpreter/Interpreter.scala b/interpreter/shared/src/main/scala/sigmastate/interpreter/Interpreter.scala index 523b2a7f35..9a1ab11f0e 100644 --- a/interpreter/shared/src/main/scala/sigmastate/interpreter/Interpreter.scala +++ b/interpreter/shared/src/main/scala/sigmastate/interpreter/Interpreter.scala @@ -23,7 +23,7 @@ import sigmastate.interpreter.CErgoTreeEvaluator.fixedCostOp import sigmastate.interpreter.Interpreter._ import sigma.ast.syntax.ValueOps import sigma.eval.{EvalSettings, SigmaDsl} -import sigma.exceptions.{CostLimitException, InterpreterException} +import sigma.exceptions.InterpreterException import sigma.interpreter.ProverResult import sigma.util.CollectionUtil import sigmastate.utils.Helpers._ diff --git a/interpreter/shared/src/test/scala/sigma/serialization/ConstantSerializerSpecification.scala b/interpreter/shared/src/test/scala/sigma/serialization/ConstantSerializerSpecification.scala index 7bc73643f2..43e9cf9e5d 100644 --- a/interpreter/shared/src/test/scala/sigma/serialization/ConstantSerializerSpecification.scala +++ b/interpreter/shared/src/test/scala/sigma/serialization/ConstantSerializerSpecification.scala @@ -61,7 +61,7 @@ class ConstantSerializerSpecification extends TableSerializationSpecification { } property("Constant serialization round trip") { - forAll { x: Unit => roundTripTest(UnitConstant()) } + forAll { _: Unit => roundTripTest(UnitConstant()) } forAll { x: Byte => roundTripTest(Constant[SByte.type](x, SByte)) } forAll { x: Boolean => roundTripTest(BooleanConstant.fromBoolean(x)) } forAll { x: Long => roundTripTest(Constant[SLong.type](x, SLong)) } diff --git a/interpreter/shared/src/test/scala/sigma/serialization/DataSerializerSpecification.scala b/interpreter/shared/src/test/scala/sigma/serialization/DataSerializerSpecification.scala index ecb2d2ef70..7cd9967e54 100644 --- a/interpreter/shared/src/test/scala/sigma/serialization/DataSerializerSpecification.scala +++ b/interpreter/shared/src/test/scala/sigma/serialization/DataSerializerSpecification.scala @@ -5,7 +5,6 @@ import org.ergoplatform.ErgoBox import org.scalacheck.Arbitrary._ import sigma.data.{DataValueComparer, RType, SigmaBoolean, TupleColl} import sigma.ast.SCollection.SByteArray -import sigmastate._ import sigmastate.eval._ import sigma.{AvlTree, Colls, Evaluation} import sigma.ast.SType.AnyOps diff --git a/sc/shared/src/main/scala/scalan/Library.scala b/sc/shared/src/main/scala/scalan/Library.scala index ee1ff80ad3..43f20813f0 100644 --- a/sc/shared/src/main/scala/scalan/Library.scala +++ b/sc/shared/src/main/scala/scalan/Library.scala @@ -107,7 +107,7 @@ trait Library extends Scalan override def invokeUnlifted(e: Elem[_], mc: MethodCall, dataEnv: DataEnv): Any = e match { case _: CollElem[_,_] => mc match { - case CollMethods.map(xs, f) => + case CollMethods.map(_, f) => val newMC = mc.copy(args = mc.args :+ f.elem.eRange)(mc.resultType, mc.isAdapterCall) super.invokeUnlifted(e, newMC, dataEnv) case _ => diff --git a/sc/shared/src/main/scala/scalan/staged/Transforming.scala b/sc/shared/src/main/scala/scalan/staged/Transforming.scala index cd1fac9fd0..a64b998ff6 100644 --- a/sc/shared/src/main/scala/scalan/staged/Transforming.scala +++ b/sc/shared/src/main/scala/scalan/staged/Transforming.scala @@ -47,9 +47,6 @@ trait Transforming { self: Scalan => constantPropagation: Boolean = true, /** Used in SlicingPass */ shouldSlice: Boolean = false) - { - def withConstantPropagation(value: Boolean) = this.copy(constantPropagation = value) - } /** Default pass to be used when IR is used without special compiler configuration. */ class DefaultPass(val name: String, override val config: PassConfig = PassConfig()) extends Pass diff --git a/sc/shared/src/main/scala/special/collection/CollsUnit.scala b/sc/shared/src/main/scala/special/collection/CollsUnit.scala index 19ae1f5e48..90f0dca99e 100644 --- a/sc/shared/src/main/scala/special/collection/CollsUnit.scala +++ b/sc/shared/src/main/scala/special/collection/CollsUnit.scala @@ -34,7 +34,5 @@ package sigma { def xor(left: Ref[Coll[Byte]], right: Ref[Coll[Byte]]): Ref[Coll[Byte]]; def replicate[T](n: Ref[Int], v: Ref[T]): Ref[Coll[T]]; }; - trait CollCompanion; - trait CollBuilderCompanion } } \ No newline at end of file From 11c6fe94e3e3938449fcee3a4a111e822fe3ae09 Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Tue, 2 Apr 2024 22:44:44 +0300 Subject: [PATCH 015/314] CoreByteReader scaladoc cleared --- .../src/main/scala/sigma/serialization/CoreByteReader.scala | 4 ---- 1 file changed, 4 deletions(-) diff --git a/core/shared/src/main/scala/sigma/serialization/CoreByteReader.scala b/core/shared/src/main/scala/sigma/serialization/CoreByteReader.scala index 34ed74ac6a..e238829b6c 100644 --- a/core/shared/src/main/scala/sigma/serialization/CoreByteReader.scala +++ b/core/shared/src/main/scala/sigma/serialization/CoreByteReader.scala @@ -10,10 +10,6 @@ import sigma.validation.ValidationRules.CheckPositionLimit * methods. * * @param r the underlying reader this reader reads from - * @param constantStore the store of constants which is used to resolve - * [[sigma.ast.ConstantPlaceholder]] - * @param resolvePlaceholdersToConstants if true then resolved constants will be - * substituted in the tree instead of the placeholder. * @param maxTreeDepth limit on the tree depth (recursive invocations) * of the deserializer */ From e8978e3c63f5c69d6e719354552cfaa640471a9b Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Wed, 3 Apr 2024 00:04:22 +0300 Subject: [PATCH 016/314] unused LambdaOps.{>>,<<} --- sc/shared/src/main/scala/scalan/primitives/Functions.scala | 6 ------ 1 file changed, 6 deletions(-) diff --git a/sc/shared/src/main/scala/scalan/primitives/Functions.scala b/sc/shared/src/main/scala/scalan/primitives/Functions.scala index 31a6ca8d81..9026461777 100644 --- a/sc/shared/src/main/scala/scalan/primitives/Functions.scala +++ b/sc/shared/src/main/scala/scalan/primitives/Functions.scala @@ -16,12 +16,6 @@ trait Functions extends Base with ProgramGraphs { self: Scalan => /** Apply given function symbol to the given argument symbol. * @return symbol representing result of function application */ final def apply(x: Ref[A]): Ref[B] = mkApply(f, x) - - /** Build new function which applies `f` and then `g`*/ - final def >>[C](g: Ref[B => C]): Ref[A => C] = compose(g, f) - - /** Build new function which applies `g` and then `f`*/ - final def <<[C](g: Ref[C => A]): Ref[C => B] = compose(f, g) } /** Global lambda equality mode used by default. It is used in `fun` and `fun2` lambda builders. From 49dce782be238e5bce6704d200b2790a1375f5c5 Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Wed, 3 Apr 2024 00:24:01 +0300 Subject: [PATCH 017/314] ToNBits def --- interpreter/shared/src/main/scala/sigmastate/types.scala | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/interpreter/shared/src/main/scala/sigmastate/types.scala b/interpreter/shared/src/main/scala/sigmastate/types.scala index 7ba062046a..095dfccd0b 100644 --- a/interpreter/shared/src/main/scala/sigmastate/types.scala +++ b/interpreter/shared/src/main/scala/sigmastate/types.scala @@ -1052,6 +1052,9 @@ case object SBigInt extends SPrimType with SEmbeddable with SNumericType with SM SigmaDsl.BigInt(bi) } + val ToNBits = SMethod(this, "toNbits", SFunc(this, SLong), 1, FixedCost(JitCost(5))) + .withInfo(ModQ, "Encode this big integer value as NBits") + /** The following `modQ` methods are not fully implemented in v4.x. * The following descriptors remain here in the code and are waiting for full implementation * is upcoming soft-forks at which point the cost parameters should be calculated and @@ -1068,6 +1071,7 @@ case object SBigInt extends SPrimType with SEmbeddable with SNumericType with SM .withInfo(MethodCall, "Multiply this number with \\lst{other} by module Q.", ArgInfo("other", "Number to multiply with this.")) protected override def getMethods(): Seq[SMethod] = super.getMethods() ++ Seq( + ToNBits // ModQMethod, // PlusModQMethod, // MinusModQMethod, From 37bb86c3cf7c07648e36d6114ef857ec3ddf6d65 Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Thu, 4 Apr 2024 10:12:11 +0300 Subject: [PATCH 018/314] toNBits added to SigmaDsl --- core/shared/src/main/scala/sigma/SigmaDsl.scala | 2 ++ core/shared/src/main/scala/sigma/data/CBigInt.scala | 2 ++ 2 files changed, 4 insertions(+) diff --git a/core/shared/src/main/scala/sigma/SigmaDsl.scala b/core/shared/src/main/scala/sigma/SigmaDsl.scala index df2b419273..19bca4ab1a 100644 --- a/core/shared/src/main/scala/sigma/SigmaDsl.scala +++ b/core/shared/src/main/scala/sigma/SigmaDsl.scala @@ -154,6 +154,8 @@ trait BigInt { */ def or(that: BigInt): BigInt def |(that: BigInt): BigInt = or(that) + + def toNbits(): Long } /** Base class for points on elliptic curves. */ diff --git a/core/shared/src/main/scala/sigma/data/CBigInt.scala b/core/shared/src/main/scala/sigma/data/CBigInt.scala index bbf1a85e46..b41d7d2347 100644 --- a/core/shared/src/main/scala/sigma/data/CBigInt.scala +++ b/core/shared/src/main/scala/sigma/data/CBigInt.scala @@ -49,4 +49,6 @@ case class CBigInt(override val wrappedValue: BigInteger) extends BigInt with Wr override def and(that: BigInt): BigInt = CBigInt(wrappedValue.and(that.asInstanceOf[CBigInt].wrappedValue)) override def or(that: BigInt): BigInt = CBigInt(wrappedValue.or(that.asInstanceOf[CBigInt].wrappedValue)) + + override def toNbits(): Long = ??? // todo: implement } From 6f8981f84f6c6d3e94732c63fe1c83a8e634a952 Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Thu, 4 Apr 2024 13:57:48 +0300 Subject: [PATCH 019/314] NBitsUtils --- .../src/main/scala/sigma/ast/SType.scala | 2 +- .../src/main/scala/sigma/data/CBigInt.scala | 3 +- .../main/scala/sigma/util/NBitsUtils.scala | 84 +++++++++++++++++++ 3 files changed, 87 insertions(+), 2 deletions(-) create mode 100644 core/shared/src/main/scala/sigma/util/NBitsUtils.scala diff --git a/core/shared/src/main/scala/sigma/ast/SType.scala b/core/shared/src/main/scala/sigma/ast/SType.scala index 0a0b12c59b..f1bf9d1508 100644 --- a/core/shared/src/main/scala/sigma/ast/SType.scala +++ b/core/shared/src/main/scala/sigma/ast/SType.scala @@ -449,7 +449,7 @@ case object SLong extends SPrimType with SEmbeddable with SNumericType with SMon } } -/** Type of 256 bit integet values. Implemented using [[java.math.BigInteger]]. */ +/** Type of 256 bit integer values. Implemented using [[java.math.BigInteger]]. */ case object SBigInt extends SPrimType with SEmbeddable with SNumericType with SMonoType { override type WrappedType = BigInt override val typeCode: TypeCode = 6: Byte diff --git a/core/shared/src/main/scala/sigma/data/CBigInt.scala b/core/shared/src/main/scala/sigma/data/CBigInt.scala index b41d7d2347..8b9deaf9bd 100644 --- a/core/shared/src/main/scala/sigma/data/CBigInt.scala +++ b/core/shared/src/main/scala/sigma/data/CBigInt.scala @@ -1,6 +1,7 @@ package sigma.data import sigma.util.Extensions.BigIntegerOps +import sigma.util.NBitsUtils import sigma.{BigInt, Coll, Colls} import java.math.BigInteger @@ -50,5 +51,5 @@ case class CBigInt(override val wrappedValue: BigInteger) extends BigInt with Wr override def or(that: BigInt): BigInt = CBigInt(wrappedValue.or(that.asInstanceOf[CBigInt].wrappedValue)) - override def toNbits(): Long = ??? // todo: implement + override def toNbits(): Long = NBitsUtils.encodeCompactBits(wrappedValue) } diff --git a/core/shared/src/main/scala/sigma/util/NBitsUtils.scala b/core/shared/src/main/scala/sigma/util/NBitsUtils.scala new file mode 100644 index 0000000000..36d526d1d5 --- /dev/null +++ b/core/shared/src/main/scala/sigma/util/NBitsUtils.scala @@ -0,0 +1,84 @@ +package sigma.util + +import java.math.BigInteger + +object NBitsUtils { + + /** + *

The "compact" format is a representation of a whole number N using an unsigned 32 bit number similar to a + * floating point format. The most significant 8 bits are the unsigned exponent of base 256. This exponent can + * be thought of as "number of bytes of N". The lower 23 bits are the mantissa. Bit number 24 (0x800000) represents + * the sign of N. Therefore, N = (-1^sign) * mantissa * 256^(exponent-3).

+ * + *

Satoshi's original implementation used BN_bn2mpi() and BN_mpi2bn(). MPI uses the most significant bit of the + * first byte as sign. Thus 0x1234560000 is compact 0x05123456 and 0xc0de000000 is compact 0x0600c0de. Compact + * 0x05c0de00 would be -0x40de000000.

+ * + *

Bitcoin only uses this "compact" format for encoding difficulty targets, which are unsigned 256bit quantities. + * Thus, all the complexities of the sign bit and using base 256 are probably an implementation accident.

+ */ + def decodeCompactBits(compact: Long): BigInt = { + val size: Int = (compact >> 24).toInt & 0xFF + val bytes: Array[Byte] = new Array[Byte](4 + size) + bytes(3) = size.toByte + if (size >= 1) bytes(4) = ((compact >> 16) & 0xFF).toByte + if (size >= 2) bytes(5) = ((compact >> 8) & 0xFF).toByte + if (size >= 3) bytes(6) = (compact & 0xFF).toByte + decodeMPI(bytes) + } + + /** + * @see Utils#decodeCompactBits(long) + */ + def encodeCompactBits(requiredDifficulty: BigInt): Long = { + val value = requiredDifficulty.bigInteger + var result: Long = 0L + var size: Int = value.toByteArray.length + if (size <= 3) { + result = value.longValue << 8 * (3 - size) + } else { + result = value.shiftRight(8 * (size - 3)).longValue + } + // The 0x00800000 bit denotes the sign. + // Thus, if it is already set, divide the mantissa by 256 and increase the exponent. + if ((result & 0x00800000L) != 0) { + result >>= 8 + size += 1 + } + result |= size << 24 + val a: Int = if (value.signum == -1) 0x00800000 else 0 + result |= a + result + } + + + /** Parse 4 bytes from the byte array (starting at the offset) as unsigned 32-bit integer in big endian format. */ + def readUint32BE(bytes: Array[Byte]): Long = ((bytes(0) & 0xffL) << 24) | ((bytes(1) & 0xffL) << 16) | ((bytes(2) & 0xffL) << 8) | (bytes(3) & 0xffL) + + /** + * MPI encoded numbers are produced by the OpenSSL BN_bn2mpi function. They consist of + * a 4 byte big endian length field, followed by the stated number of bytes representing + * the number in big endian format (with a sign bit). + * + */ + private def decodeMPI(mpi: Array[Byte]): BigInteger = { + + val length: Int = readUint32BE(mpi).toInt + val buf = new Array[Byte](length) + System.arraycopy(mpi, 4, buf, 0, length) + + if (buf.length == 0) { + BigInteger.ZERO + } else { + val isNegative: Boolean = (buf(0) & 0x80) == 0x80 + if (isNegative) buf(0) = (buf(0) & 0x7f).toByte + val result: BigInteger = new BigInteger(buf) + if (isNegative) { + result.negate + } else { + result + } + } + } + +} From 2b1e49a6fda8327fdcd7ddbd0a933ea89c20573c Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Thu, 4 Apr 2024 19:26:44 +0300 Subject: [PATCH 020/314] RuntimeIRContext removed --- .../scala/sigmastate/eval/IRContext.scala | 8 ++--- .../sigmastate/eval/EvaluationTest.scala | 18 ---------- .../sigmastate/eval/MeasureIRContext.scala | 36 ------------------- 3 files changed, 3 insertions(+), 59 deletions(-) delete mode 100644 sc/shared/src/test/scala/sigmastate/eval/MeasureIRContext.scala diff --git a/sc/shared/src/main/scala/sigmastate/eval/IRContext.scala b/sc/shared/src/main/scala/sigmastate/eval/IRContext.scala index b84098f2e7..a7b6df3f58 100644 --- a/sc/shared/src/main/scala/sigmastate/eval/IRContext.scala +++ b/sc/shared/src/main/scala/sigmastate/eval/IRContext.scala @@ -10,7 +10,9 @@ import scala.util.Try * methods. * It is not used in v5.0 interpreter and thus not part of consensus. * - * @see RuntimeIRContext, CompiletimeIRContext + * Used in ErgoScript compiler only. + * + * @see CompiletimeIRContext */ trait IRContext extends TreeBuilding with GraphBuilding { import SigmaProp._ @@ -55,10 +57,6 @@ trait IRContext extends TreeBuilding with GraphBuilding { } } -/** IR context to be used by blockchain nodes to validate transactions. */ -class RuntimeIRContext extends IRContext { -} - /** IR context to be used by script development tools to compile ErgoScript into ErgoTree bytecode. */ class CompiletimeIRContext extends IRContext { } diff --git a/sc/shared/src/test/scala/sigmastate/eval/EvaluationTest.scala b/sc/shared/src/test/scala/sigmastate/eval/EvaluationTest.scala index 5fcbd0f220..f9a7edf0cb 100644 --- a/sc/shared/src/test/scala/sigmastate/eval/EvaluationTest.scala +++ b/sc/shared/src/test/scala/sigmastate/eval/EvaluationTest.scala @@ -81,24 +81,6 @@ class EvaluationTest extends BaseCtxTests | f(SELF) || g(SELF.R5[Coll[Int]].get) | }""".stripMargin, ctx, true) } - - test("Measure IRContext creation speed") { - var ctx: RuntimeIRContext = new RuntimeIRContext - measure(100, okShowIterTime = printDebugInfo, okShowTotalTime = printDebugInfo) { i => - ctx = new RuntimeIRContext - } - printDebug(s"Def count: ${ctx.defCount}") - /* - Iter 0: 4 ms - ... - Iter 96: 2 ms - Iter 97: 1 ms - Iter 98: 2 ms - Iter 99: 2 ms - Total time: 244 ms - Def count: 20 - */ - } test("SubstConst") { def script(pk: ProveDlog): SigmaPropValue = diff --git a/sc/shared/src/test/scala/sigmastate/eval/MeasureIRContext.scala b/sc/shared/src/test/scala/sigmastate/eval/MeasureIRContext.scala deleted file mode 100644 index 9f88588cc9..0000000000 --- a/sc/shared/src/test/scala/sigmastate/eval/MeasureIRContext.scala +++ /dev/null @@ -1,36 +0,0 @@ -package sigmastate.eval - -import scalan.{BaseCtxTests, Benchmark} -import sigma.util.BenchmarkUtil.measure - -object MeasureIRContext extends App { - var ctx: RuntimeIRContext = null - measure(1, false) { i => - ctx = new RuntimeIRContext - } - measure(10000, false) { i => - ctx = new RuntimeIRContext - } - print(s"Def count: ${ctx.defCount}") - /* - Total time: 2485 ms - Total time: 2714 ms - Def count: 20 - */ -} - -class SigmaLibraryTests extends BaseCtxTests { - - test("Benchmark SigmaLibrary creation time") { - new Benchmark(new RuntimeIRContext).run() - } -} - -object MeasureSigmaLibraryCreate extends App { - new Benchmark(new RuntimeIRContext).run() - /* - Total time: 12932 ms - Def count: 20, total: 15774 msec - */ -} - From dcec230aea345c8bd10cf23c61d3b5654b4b97e4 Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Thu, 4 Apr 2024 19:39:02 +0300 Subject: [PATCH 021/314] xor_eval rollback --- data/shared/src/main/scala/sigma/SigmaDataReflection.scala | 3 ++- data/shared/src/main/scala/sigma/ast/methods.scala | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/data/shared/src/main/scala/sigma/SigmaDataReflection.scala b/data/shared/src/main/scala/sigma/SigmaDataReflection.scala index 9efb3fbf8b..48939b1460 100644 --- a/data/shared/src/main/scala/sigma/SigmaDataReflection.scala +++ b/data/shared/src/main/scala/sigma/SigmaDataReflection.scala @@ -318,7 +318,8 @@ object SigmaDataReflection { registerClassEntry(clazz, methods = Map( mkMethod(clazz, "xor_eval", Array[Class[_]](classOf[MethodCall], classOf[SigmaDslBuilder], classOf[Coll[_]], classOf[Coll[_]], classOf[ErgoTreeEvaluator])) { (obj, args) => - obj.asInstanceOf[SGlobalMethods.type].xor_eval( + obj.asInstanceOf[SGlobalMethods.type].xor_eval(args(0).asInstanceOf[MethodCall], + args(1).asInstanceOf[SigmaDslBuilder], args(2).asInstanceOf[Coll[Byte]], args(3).asInstanceOf[Coll[Byte]])(args(4).asInstanceOf[ErgoTreeEvaluator]) } diff --git a/data/shared/src/main/scala/sigma/ast/methods.scala b/data/shared/src/main/scala/sigma/ast/methods.scala index 73d9c4b7b8..3b7368c542 100644 --- a/data/shared/src/main/scala/sigma/ast/methods.scala +++ b/data/shared/src/main/scala/sigma/ast/methods.scala @@ -1494,7 +1494,7 @@ case object SGlobalMethods extends MonoTypeMethods { * Called via reflection based on naming convention. * @see SMethod.evalMethod, Xor.eval, Xor.xorWithCosting */ - def xor_eval(ls: Coll[Byte], rs: Coll[Byte]) + def xor_eval(mc: MethodCall, G: SigmaDslBuilder, ls: Coll[Byte], rs: Coll[Byte]) (implicit E: ErgoTreeEvaluator): Coll[Byte] = { Xor.xorWithCosting(ls, rs) } From 810ca16eb50b7a33d53e3e20baff9d44ce24f664 Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Fri, 5 Apr 2024 12:45:00 +0300 Subject: [PATCH 022/314] IRContext cleared --- .../src/main/scala/sigma/ast/SType.scala | 3 +- .../scala/sigmastate/eval/IRContext.scala | 42 +------------------ .../sigmastate/eval/ErgoScriptTestkit.scala | 27 +++++++++++- .../helpers/CompilerTestingCommons.scala | 3 +- .../utxo/BasicOpsSpecification.scala | 4 +- 5 files changed, 32 insertions(+), 47 deletions(-) diff --git a/core/shared/src/main/scala/sigma/ast/SType.scala b/core/shared/src/main/scala/sigma/ast/SType.scala index e9ea0d43f0..f75cbc9e8b 100644 --- a/core/shared/src/main/scala/sigma/ast/SType.scala +++ b/core/shared/src/main/scala/sigma/ast/SType.scala @@ -94,7 +94,6 @@ object SType { val paramOV = STypeParam(tOV) val paramIVSeq: Seq[STypeParam] = Array(paramIV) - val IndexedSeqOfT1: IndexedSeq[SType] = Array(SType.tT) val IndexedSeqOfT2: IndexedSeq[SType] = Array(SType.tT, SType.tT) /** Immutable empty array, can be used to avoid repeated allocations. */ @@ -146,7 +145,7 @@ object SType { * 2) `isValueOfType == true` for each tree leaf * 3) `isValueOfType == true` for each sub-expression * - * @param value value to check type + * @param x value to check type * @param tpe type descriptor to check value against * @return true if the given `value` is of type tpe` */ diff --git a/sc/shared/src/main/scala/sigmastate/eval/IRContext.scala b/sc/shared/src/main/scala/sigmastate/eval/IRContext.scala index a7b6df3f58..597711d458 100644 --- a/sc/shared/src/main/scala/sigmastate/eval/IRContext.scala +++ b/sc/shared/src/main/scala/sigmastate/eval/IRContext.scala @@ -1,10 +1,6 @@ package sigmastate.eval import sigma.ast.TransformingSigmaBuilder -import sigma.data.CSigmaDslBuilder - -import java.util.concurrent.locks.ReentrantLock -import scala.util.Try /** Main interface of graph IR context which contain both GraphBuilding and TreeBuilding * methods. @@ -15,49 +11,15 @@ import scala.util.Try * @see CompiletimeIRContext */ trait IRContext extends TreeBuilding with GraphBuilding { - import SigmaProp._ - - private val SigmaM = SigmaPropMethods - override val builder = TransformingSigmaBuilder - /** Can be used to synchronize access to this IR object from multiple threads. */ - val lock = new ReentrantLock() - /** Pass configuration which is used to turn-off constant propagation. + * USED IN TESTS ONLY. * @see `beginPass(noCostPropagationPass)` */ lazy val noConstPropagationPass = new DefaultPass( "noCostPropagationPass", Pass.defaultPassConfig.copy(constantPropagation = false)) - - /** The value of Global ErgoTree operation */ - val sigmaDslBuilderValue = CSigmaDslBuilder - - /** Finds SigmaProp.isProven method calls in the given Lambda `f` */ - def findIsProven[T](f: Ref[Context => T]): Option[Sym] = { - val Def(Lambda(lam,_,_,_)) = f - val s = lam.flatSchedule.find(sym => sym.node match { - case SigmaM.isValid(_) => true - case _ => false - }) - s - } - - /** Checks that if SigmaProp.isProven method calls exists in the given Lambda's schedule, - * then it is the last operation. */ - def verifyIsProven[T](f: Ref[Context => T]): Try[Unit] = { - val isProvenOpt = findIsProven(f) - Try { - isProvenOpt match { - case Some(s) => - if (f.getLambda.y != s) !!!(s"Sigma.isProven found in none-root position", s) - case None => - } - } - } } /** IR context to be used by script development tools to compile ErgoScript into ErgoTree bytecode. */ -class CompiletimeIRContext extends IRContext { -} - +class CompiletimeIRContext extends IRContext diff --git a/sc/shared/src/test/scala/sigmastate/eval/ErgoScriptTestkit.scala b/sc/shared/src/test/scala/sigmastate/eval/ErgoScriptTestkit.scala index abbed09992..2832ad27e7 100644 --- a/sc/shared/src/test/scala/sigmastate/eval/ErgoScriptTestkit.scala +++ b/sc/shared/src/test/scala/sigmastate/eval/ErgoScriptTestkit.scala @@ -21,7 +21,7 @@ import sigmastate.CompilerTestsBase import sigma.{ContractsTestkit, Context => DContext} import scala.annotation.unused -import scala.util.Success +import scala.util.{Success, Try} trait ErgoScriptTestkit extends ContractsTestkit with LangTests with ValidationSpecification with CompilerTestsBase { self: BaseCtxTests => @@ -147,6 +147,31 @@ trait ErgoScriptTestkit extends ContractsTestkit with LangTests res } + private val SigmaM = SigmaProp.SigmaPropMethods + + /** Finds SigmaProp.isProven method calls in the given Lambda `f` */ + private def findIsProven[T](f: Ref[Context => T]): Option[Sym] = { + val Def(Lambda(lam,_,_,_)) = f + val s = lam.flatSchedule.find(sym => sym.node match { + case SigmaM.isValid(_) => true + case _ => false + }) + s + } + + /** Checks that if SigmaProp.isProven method calls exists in the given Lambda's schedule, + * then it is the last operation. */ + private def verifyIsProven[T](f: Ref[Context => T]): Try[Unit] = { + val isProvenOpt = findIsProven(f) + Try { + isProvenOpt match { + case Some(s) => + if (f.getLambda.y != s) !!!(s"Sigma.isProven found in none-root position", s) + case None => + } + } + } + def doReduce(): Unit = { val res = doCosting verifyIsProven(res.compiledGraph) shouldBe Success(()) diff --git a/sc/shared/src/test/scala/sigmastate/helpers/CompilerTestingCommons.scala b/sc/shared/src/test/scala/sigmastate/helpers/CompilerTestingCommons.scala index 332ee902a2..6c3708b782 100644 --- a/sc/shared/src/test/scala/sigmastate/helpers/CompilerTestingCommons.scala +++ b/sc/shared/src/test/scala/sigmastate/helpers/CompilerTestingCommons.scala @@ -29,8 +29,7 @@ trait CompilerTestingCommons extends TestingCommons with TestUtils with TestContexts with ValidationSpecification with CompilerTestsBase { - class TestingIRContext extends TestContext with IRContext { - } + class TestingIRContext extends TestContext with IRContext case class CompiledFunc[A,B] (script: String, bindings: Seq[VarBinding], expr: SValue, compiledTree: SValue, func: A => (B, CostDetails)) diff --git a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala index 346ad69e1a..79701d6e07 100644 --- a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala @@ -5,7 +5,7 @@ import org.ergoplatform._ import sigma.Extensions.ArrayOps import sigma.ast.SCollection.SByteArray import sigma.ast.SType.AnyOps -import sigma.data.{AvlTreeData, CAnyValue} +import sigma.data.{AvlTreeData, CAnyValue, CSigmaDslBuilder} import sigma.util.StringUtil._ import sigma.ast._ import sigma.ast.syntax._ @@ -339,7 +339,7 @@ class BasicOpsSpecification extends CompilerTestingCommons }) val dataVar = (lastExtVar + 1).toByte - val Colls = IR.sigmaDslBuilderValue.Colls + val Colls = CSigmaDslBuilder.Colls implicit val eAny = sigma.AnyType val data = Colls.fromItems((Array[Byte](1,2,3).toColl, 10L)) val env1 = env + ("dataVar" -> CAnyValue(dataVar)) From d0f1b7d6c3fd05d7e5477ec670d7d2a0974a4e6c Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Fri, 5 Apr 2024 17:19:20 +0300 Subject: [PATCH 023/314] unused import removed --- core/shared/src/main/scala/sigma/ast/SType.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/shared/src/main/scala/sigma/ast/SType.scala b/core/shared/src/main/scala/sigma/ast/SType.scala index f1bf9d1508..e01edf938f 100644 --- a/core/shared/src/main/scala/sigma/ast/SType.scala +++ b/core/shared/src/main/scala/sigma/ast/SType.scala @@ -7,7 +7,7 @@ import sigma.data.OverloadHack.Overloaded1 import sigma.data.{CBigInt, Nullable, SigmaConstants} import sigma.reflection.{RClass, RMethod, ReflectionData} import sigma.util.Extensions.{IntOps, LongOps, ShortOps} -import sigma.{AvlTree, BigInt, Box, Coll, Context, Evaluation, GroupElement, Header, PreHeader, SigmaDslBuilder, SigmaProp, VersionContext} +import sigma.{AvlTree, BigInt, Box, Coll, Context, Evaluation, GroupElement, Header, PreHeader, SigmaDslBuilder, SigmaProp} import java.math.BigInteger From fcc7f0f69f5ed34c8c6fdfa44c4116e43e4d9d3d Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Sat, 6 Apr 2024 21:57:01 +0300 Subject: [PATCH 024/314] merging latest 5.0.14 commits --- core/shared/src/main/scala/sigma/VersionContext.scala | 4 ++-- .../src/main/scala/org/ergoplatform/ErgoAddress.scala | 6 +----- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/core/shared/src/main/scala/sigma/VersionContext.scala b/core/shared/src/main/scala/sigma/VersionContext.scala index ea564f335b..5663bfed60 100644 --- a/core/shared/src/main/scala/sigma/VersionContext.scala +++ b/core/shared/src/main/scala/sigma/VersionContext.scala @@ -51,8 +51,8 @@ object VersionContext { val EvolutionVersion: Byte = 3 private val _defaultContext = VersionContext( - activatedVersion = 2/* v5.x */, - ergoTreeVersion = 2 + activatedVersion = 1 /* v4.x */, + ergoTreeVersion = 1 ) /** Universally accessible version context which is used to version the code diff --git a/data/shared/src/main/scala/org/ergoplatform/ErgoAddress.scala b/data/shared/src/main/scala/org/ergoplatform/ErgoAddress.scala index 270f32d35d..59eb8df5c5 100644 --- a/data/shared/src/main/scala/org/ergoplatform/ErgoAddress.scala +++ b/data/shared/src/main/scala/org/ergoplatform/ErgoAddress.scala @@ -165,11 +165,7 @@ class Pay2SHAddress(val scriptHash: Array[Byte])(implicit val encoder: ErgoAddre ByteArrayConstant(scriptHash) ) val scriptIsCorrect = DeserializeContext(scriptId, SSigmaProp) - // Get script version either from the default context or from a context provided by an application - // This is never part of the consensus and can be controlled by applications - val treeVersion = VersionContext.current.ergoTreeVersion - val header = setVersionBits(ZeroHeader, treeVersion) - ErgoTree.withoutSegregation(header, SigmaAnd(hashEquals.toSigmaProp, scriptIsCorrect)) + ErgoTree.withoutSegregation(ZeroHeader, SigmaAnd(hashEquals.toSigmaProp, scriptIsCorrect)) } override def equals(obj: Any): Boolean = obj match { From 6e47167f76c99b5defa41f79edd3038df8e28e8d Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Tue, 9 Apr 2024 13:58:23 +0300 Subject: [PATCH 025/314] nbits impl --- .../src/main/scala/sigma/SigmaDsl.scala | 2 +- .../src/main/scala/sigma/VersionContext.scala | 6 +-- .../src/main/scala/sigma/data/CBigInt.scala | 2 +- .../sigma/reflection/ReflectionData.scala | 3 ++ .../src/main/scala/sigma/ast/methods.scala | 22 ++++++++--- .../scala/sigma/eval/ErgoTreeEvaluator.scala | 7 +++- .../interpreter/CErgoTreeEvaluator.scala | 13 +++++-- .../scala/sigmastate/eval/GraphBuilding.scala | 10 ++++- .../scala/special/sigma/SigmaDslUnit.scala | 1 + .../special/sigma/impl/SigmaDslImpl.scala | 14 +++++++ .../ErgoAddressSpecification.scala | 37 ++++++++++++++----- .../TestingInterpreterSpecification.scala | 19 +++++++++- 12 files changed, 109 insertions(+), 27 deletions(-) diff --git a/core/shared/src/main/scala/sigma/SigmaDsl.scala b/core/shared/src/main/scala/sigma/SigmaDsl.scala index 19bca4ab1a..56e4a1da37 100644 --- a/core/shared/src/main/scala/sigma/SigmaDsl.scala +++ b/core/shared/src/main/scala/sigma/SigmaDsl.scala @@ -155,7 +155,7 @@ trait BigInt { def or(that: BigInt): BigInt def |(that: BigInt): BigInt = or(that) - def toNbits(): Long + def nbits: Long } /** Base class for points on elliptic curves. */ diff --git a/core/shared/src/main/scala/sigma/VersionContext.scala b/core/shared/src/main/scala/sigma/VersionContext.scala index 5663bfed60..19a4857086 100644 --- a/core/shared/src/main/scala/sigma/VersionContext.scala +++ b/core/shared/src/main/scala/sigma/VersionContext.scala @@ -1,6 +1,6 @@ package sigma -import VersionContext.{EvolutionVersion, JitActivationVersion} +import VersionContext.{JitActivationVersion, V6SoftForkVersion} import scala.util.DynamicVariable @@ -24,7 +24,7 @@ case class VersionContext(activatedVersion: Byte, ergoTreeVersion: Byte) { /** @return true, if the activated script version of Ergo protocol on the network is * including Evolution update. */ - def isEvolutionActivated: Boolean = activatedVersion >= EvolutionVersion + def isV6SoftForkActivated: Boolean = activatedVersion >= V6SoftForkVersion } object VersionContext { @@ -48,7 +48,7 @@ object VersionContext { /** * The version of ErgoTree corresponding to "evolution" (6.0) soft-fork */ - val EvolutionVersion: Byte = 3 + val V6SoftForkVersion: Byte = 3 private val _defaultContext = VersionContext( activatedVersion = 1 /* v4.x */, diff --git a/core/shared/src/main/scala/sigma/data/CBigInt.scala b/core/shared/src/main/scala/sigma/data/CBigInt.scala index 8b9deaf9bd..43198fbf8a 100644 --- a/core/shared/src/main/scala/sigma/data/CBigInt.scala +++ b/core/shared/src/main/scala/sigma/data/CBigInt.scala @@ -51,5 +51,5 @@ case class CBigInt(override val wrappedValue: BigInteger) extends BigInt with Wr override def or(that: BigInt): BigInt = CBigInt(wrappedValue.or(that.asInstanceOf[CBigInt].wrappedValue)) - override def toNbits(): Long = NBitsUtils.encodeCompactBits(wrappedValue) + override def nbits: Long = NBitsUtils.encodeCompactBits(wrappedValue) } diff --git a/core/shared/src/main/scala/sigma/reflection/ReflectionData.scala b/core/shared/src/main/scala/sigma/reflection/ReflectionData.scala index 2aac1a5670..e25462651f 100644 --- a/core/shared/src/main/scala/sigma/reflection/ReflectionData.scala +++ b/core/shared/src/main/scala/sigma/reflection/ReflectionData.scala @@ -118,6 +118,9 @@ object ReflectionData { }, mkMethod(clazz, "divide", paramTypes) { (obj, args) => obj.asInstanceOf[BigInt].divide(args(0).asInstanceOf[BigInt]) + }, + mkMethod(clazz, "nbits", paramTypes) { (obj, _) => + obj.asInstanceOf[BigInt].nbits } ) ) diff --git a/data/shared/src/main/scala/sigma/ast/methods.scala b/data/shared/src/main/scala/sigma/ast/methods.scala index 275ad9e4b5..a21459fcb9 100644 --- a/data/shared/src/main/scala/sigma/ast/methods.scala +++ b/data/shared/src/main/scala/sigma/ast/methods.scala @@ -53,7 +53,7 @@ sealed trait MethodsContainer { protected def getMethods(): Seq[SMethod] = Nil /** Returns all the methods of this type. */ - lazy val methods: Seq[SMethod] = { + def methods: Seq[SMethod] = { //todo: consider versioned caching val ms = getMethods().toArray assert(ms.map(_.name).distinct.length == ms.length, s"Duplicate method names in $this") ms.groupBy(_.objType).foreach { case (comp, ms) => @@ -309,7 +309,7 @@ case object SLongMethods extends SNumericTypeMethods { .withInfo(PropertyCall, "Consider this Long value as nbits-encoded BigInt value and decode it to BigInt") protected override def getMethods(): Seq[SMethod] = { - if (VersionContext.current.isEvolutionActivated) { + if (VersionContext.current.isV6SoftForkActivated) { super.getMethods() ++ Seq(DecodeNBitsMethod) } else { super.getMethods() @@ -322,8 +322,12 @@ case object SBigIntMethods extends SNumericTypeMethods { /** Type for which this container defines methods. */ override def ownerType: SMonoType = SBigInt - val ToNBits = SMethod(this, "toNbits", SFunc(this.ownerType, SLong), 1, FixedCost(JitCost(5))) - .withInfo(ModQ, "Encode this big integer value as NBits") + final val ToNBitsCostInfo = OperationCostInfo( + FixedCost(JitCost(5)), NamedDesc("NBitsMethodCall")) + + //id = 8 to make it after toBits + val ToNBits = SMethod(this, "nbits", SFunc(this.ownerType, SLong), 8, ToNBitsCostInfo.costKind) + .withInfo(ModQ, "Encode this big integer value as NBits") /** The following `modQ` methods are not fully implemented in v4.x and this descriptors. * This descritors are remain here in the code and are waiting for full implementation @@ -341,7 +345,7 @@ case object SBigIntMethods extends SNumericTypeMethods { .withInfo(MethodCall, "Multiply this number with \\lst{other} by module Q.", ArgInfo("other", "Number to multiply with this.")) protected override def getMethods(): Seq[SMethod] = { - if (VersionContext.current.isEvolutionActivated) { + if (VersionContext.current.isV6SoftForkActivated) { super.getMethods() ++ Seq(ToNBits) // ModQMethod, // PlusModQMethod, @@ -352,6 +356,14 @@ case object SBigIntMethods extends SNumericTypeMethods { super.getMethods() } } + + /** + * + */ + def nbits_eval(mc: MethodCall, bi: sigma.BigInt)(implicit E: ErgoTreeEvaluator): Long = { + E.nbits(mc, bi) + } + } /** Methods of type `String`. */ diff --git a/data/shared/src/main/scala/sigma/eval/ErgoTreeEvaluator.scala b/data/shared/src/main/scala/sigma/eval/ErgoTreeEvaluator.scala index 52f839354c..ec12a52849 100644 --- a/data/shared/src/main/scala/sigma/eval/ErgoTreeEvaluator.scala +++ b/data/shared/src/main/scala/sigma/eval/ErgoTreeEvaluator.scala @@ -59,9 +59,9 @@ abstract class ErgoTreeEvaluator { * @param opDesc the operation descriptor to associate the cost with (when costTracingEnabled) * @param block operation executed under the given cost */ - def addFixedCost(costKind: FixedCost, opDesc: OperationDesc)(block: => Unit): Unit + def addFixedCost[R](costKind: FixedCost, opDesc: OperationDesc)(block: => R): R - def addFixedCost(costInfo: OperationCostInfo[FixedCost])(block: => Unit): Unit + def addFixedCost[R](costInfo: OperationCostInfo[FixedCost])(block: => R): R /** Adds the given cost to the `coster`. If tracing is enabled, creates a new cost item * with the given operation. @@ -98,6 +98,9 @@ abstract class ErgoTreeEvaluator { /** Represents blockchain data context for ErgoTree evaluation. */ def context: Context + /** Implements evaluation of BigInt.nbits method call ErgoTree node. */ + def nbits(mc: MethodCall, bi: sigma.BigInt): Long + /** Create an instance of [[AvlTreeVerifier]] for the given tree and proof. */ def createTreeVerifier(tree: AvlTree, proof: Coll[Byte]): AvlTreeVerifier diff --git a/interpreter/shared/src/main/scala/sigmastate/interpreter/CErgoTreeEvaluator.scala b/interpreter/shared/src/main/scala/sigmastate/interpreter/CErgoTreeEvaluator.scala index de8aa6b620..53aa3dc08b 100644 --- a/interpreter/shared/src/main/scala/sigmastate/interpreter/CErgoTreeEvaluator.scala +++ b/interpreter/shared/src/main/scala/sigmastate/interpreter/CErgoTreeEvaluator.scala @@ -67,6 +67,12 @@ class CErgoTreeEvaluator( override def createTreeVerifier(tree: AvlTree, proof: Coll[Byte]): AvlTreeVerifier = CAvlTreeVerifier(tree, proof) + def nbits(mc: MethodCall, bi: sigma.BigInt): Long = { + addFixedCost(SBigIntMethods.ToNBitsCostInfo) { + bi.nbits + } + } + /** Creates [[sigma.eval.AvlTreeVerifier]] for the given tree and proof. */ def createVerifier(tree: AvlTree, proof: Coll[Byte]) = { // the cost of tree reconstruction from proof is O(proof.length) @@ -293,7 +299,7 @@ class CErgoTreeEvaluator( } /** @hotspot don't beautify the code */ - override def addFixedCost(costKind: FixedCost, opDesc: OperationDesc)(block: => Unit): Unit = { + override def addFixedCost[R](costKind: FixedCost, opDesc: OperationDesc)(block: => R): R = { var costItem: FixedCostItem = null if (settings.costTracingEnabled) { costItem = FixedCostItem(opDesc, costKind) @@ -305,16 +311,17 @@ class CErgoTreeEvaluator( } val start = System.nanoTime() coster.add(costKind.cost) - val _ = block + val res = block val end = System.nanoTime() profiler.addCostItem(costItem, end - start) + res } else { coster.add(costKind.cost) block } } - override def addFixedCost(costInfo: OperationCostInfo[FixedCost])(block: => Unit): Unit = { + override def addFixedCost[R](costInfo: OperationCostInfo[FixedCost])(block: => R): R = { addFixedCost(costInfo.costKind, costInfo.opDesc)(block) } diff --git a/sc/shared/src/main/scala/sigmastate/eval/GraphBuilding.scala b/sc/shared/src/main/scala/sigmastate/eval/GraphBuilding.scala index 9c9fa5ffe1..0ea648691e 100644 --- a/sc/shared/src/main/scala/sigmastate/eval/GraphBuilding.scala +++ b/sc/shared/src/main/scala/sigmastate/eval/GraphBuilding.scala @@ -8,6 +8,7 @@ import sigma.ast.Value.Typed import sigma.ast._ import sigma.ast.syntax.{SValue, ValueOps} import sigma.crypto.EcPointType +import sigma.VersionContext import sigma.data.ExactIntegral.{ByteIsExactIntegral, IntIsExactIntegral, LongIsExactIntegral, ShortIsExactIntegral} import sigma.data.ExactOrdering.{ByteIsExactOrdering, IntIsExactOrdering, LongIsExactOrdering, ShortIsExactOrdering} import sigma.data.{CSigmaDslBuilder, ExactIntegral, ExactNumeric, ExactOrdering, Lazy, Nullable} @@ -52,7 +53,7 @@ trait GraphBuilding extends SigmaLibrary { IR: IRContext => this.keepOriginalFunc = false // original lambda of Lambda node contains invocations of evalNode and we don't want that this.useAlphaEquality = false - /** Whether to create CostOf nodes or substutute costs from CostTable as constants in the graph. + /** Whether to create CostOf nodes or substitute costs from CostTable as constants in the graph. * true - substitute; false - create CostOf nodes */ var substFromCostTable: Boolean = true @@ -496,6 +497,9 @@ trait GraphBuilding extends SigmaLibrary { IR: IRContext => else error(s"The type of $obj is expected to be Collection to select 'size' property", obj.sourceContext.toOption) + case Select(obj, SBigIntMethods.ToNBits.name, _) if obj.tpe == SBigInt && VersionContext.current.isV6SoftForkActivated => + eval(sigma.ast.MethodCall(obj, SBigIntMethods.ToNBits, IndexedSeq.empty, Map.empty)) + // Rule: proof.isProven --> IsValid(proof) case Select(p, SSigmaPropMethods.IsProven, _) if p.tpe == SSigmaProp => eval(SigmaPropIsProven(p.asSigmaProp)) @@ -925,6 +929,10 @@ trait GraphBuilding extends SigmaLibrary { IR: IRContext => val objV = eval(obj) val argsV = args.map(eval) (objV, method.objType) match { + case (bi: Ref[BigInt]@unchecked, SBigIntMethods) => method.name match { + case SBigIntMethods.ToNBits.name => + bi.nbits + } case (xs: RColl[t]@unchecked, SCollectionMethods) => method.name match { case SCollectionMethods.IndicesMethod.name => xs.indices diff --git a/sc/shared/src/main/scala/special/sigma/SigmaDslUnit.scala b/sc/shared/src/main/scala/special/sigma/SigmaDslUnit.scala index 48548226a5..9e3a06a62f 100644 --- a/sc/shared/src/main/scala/special/sigma/SigmaDslUnit.scala +++ b/sc/shared/src/main/scala/special/sigma/SigmaDslUnit.scala @@ -11,6 +11,7 @@ package sigma { def mod(m: Ref[BigInt]): Ref[BigInt]; def min(that: Ref[BigInt]): Ref[BigInt]; def max(that: Ref[BigInt]): Ref[BigInt]; + def nbits: Ref[Long] }; trait GroupElement extends Def[GroupElement] { def exp(k: Ref[BigInt]): Ref[GroupElement]; diff --git a/sc/shared/src/main/scala/special/sigma/impl/SigmaDslImpl.scala b/sc/shared/src/main/scala/special/sigma/impl/SigmaDslImpl.scala index 8da36ce6cf..c9f7ec9656 100644 --- a/sc/shared/src/main/scala/special/sigma/impl/SigmaDslImpl.scala +++ b/sc/shared/src/main/scala/special/sigma/impl/SigmaDslImpl.scala @@ -96,6 +96,13 @@ object BigInt extends EntityObject("BigInt") { Array[AnyRef](that), true, false, element[BigInt])) } + + override def nbits: Ref[Long] = { + asRep[Long](mkMethodCall(self, + BigIntClass.getMethod("nbits"), + Array[AnyRef](), + neverInvoke = true, isAdapterCall = false, element[Long])) + } } implicit object LiftableBigInt @@ -164,6 +171,13 @@ object BigInt extends EntityObject("BigInt") { Array[AnyRef](that), true, true, element[BigInt])) } + + def nbits: Ref[Long] = { + asRep[Long](mkMethodCall(source, + BigIntClass.getMethod("nbits", classOf[Sym]), + Array[AnyRef](), + neverInvoke = true, isAdapterCall = true, element[Long])) + } } // entityUnref: single unref method for each type family diff --git a/sc/shared/src/test/scala/org/ergoplatform/ErgoAddressSpecification.scala b/sc/shared/src/test/scala/org/ergoplatform/ErgoAddressSpecification.scala index ad0d316519..83d2892a0c 100644 --- a/sc/shared/src/test/scala/org/ergoplatform/ErgoAddressSpecification.scala +++ b/sc/shared/src/test/scala/org/ergoplatform/ErgoAddressSpecification.scala @@ -16,9 +16,8 @@ import sigma.serialization.ErgoTreeSerializer.DefaultSerializer import sigma.serialization.ValueSerializer import sigmastate.utils.Helpers._ import sigmastate.CompilerCrossVersionProps -import sigma.SigmaDslTesting +import sigma.{SigmaDslTesting, VersionContext} import sigma.ast.ErgoTree.{ZeroHeader, setConstantSegregation} - import sigma.ast.SType import sigma.data.ProveDlog import sigma.exceptions.{CostLimitException, InvalidType} @@ -30,7 +29,7 @@ import sigma.validation.ValidationRules.CheckTypeCode import java.math.BigInteger class ErgoAddressSpecification extends SigmaDslTesting - with TryValues with CompilerCrossVersionProps { + with TryValues with CompilerCrossVersionProps with AnyPropSpecLike { private implicit val ergoAddressEncoder: ErgoAddressEncoder = new ErgoAddressEncoder(TestnetNetworkPrefix) @@ -252,12 +251,16 @@ class ErgoAddressSpecification extends SigmaDslTesting verifier.verify(env + (ScriptNameProp -> s"verify_ext"), address.script, ctx, pr.proof, fakeMessage).getOrThrow._1 shouldBe true } - property("spending a box protected by P2SH contract") { + def createPropAndScriptBytes() = { implicit lazy val IR = new TestingIRContext - val script = "{ 1 < 2 }" val prop = compile(Map.empty, script).asBoolValue.toSigmaProp val scriptBytes = ValueSerializer.serialize(prop) + (prop, scriptBytes) + } + + property("spending a box protected by P2SH contract") { + val (prop, scriptBytes) = createPropAndScriptBytes() testPay2SHAddress(Pay2SHAddress(prop), scriptBytes) @@ -265,8 +268,24 @@ class ErgoAddressSpecification extends SigmaDslTesting testPay2SHAddress(Pay2SHAddress(tree), scriptBytes) // NOTE: same scriptBytes regardless of ErgoTree version } + property("Pay2SHAddress.script should create ErgoTree v0") { + val (prop, _) = createPropAndScriptBytes() + + val address = VersionContext.withVersions(activatedVersionInTests, ergoTreeVersionInTests) { + Pay2SHAddress(prop) + } + address.script.version shouldBe 0 + } + + // create non-versioned property which is executed under default version context + // see VersionContext._defaultContext + super[AnyPropSpecLike].property("using default VersionContext still creates ErgoTree v0") { + val (prop, _) = createPropAndScriptBytes() + val address = Pay2SHAddress(prop) + address.script.version shouldBe 0 + } + property("negative cases: deserialized script + costing exceptions") { - implicit lazy val IR = new TestingIRContext def testPay2SHAddress(address: Pay2SHAddress, script: VarBinding, costLimit: Int = scriptCostLimitInTests): CostedProverResult = { val boxToSpend = testBox(10, address.script, creationHeight = 5) @@ -281,15 +300,13 @@ class ErgoAddressSpecification extends SigmaDslTesting } val scriptVarId = Pay2SHAddress.scriptId - val script = "{ 1 < 2 }" - val prop = compile(Map.empty, script).asBoolValue.toSigmaProp - val scriptBytes = ValueSerializer.serialize(prop) + val (prop, scriptBytes) = createPropAndScriptBytes() val addr = Pay2SHAddress(prop) // when everything is ok testPay2SHAddress(addr, script = scriptVarId -> ByteArrayConstant(scriptBytes)) - val expectedCost = if (ergoTreeVersionInTests == 0) 88 else 90 // account for size serialized for version > 0 + val expectedCost = 88 // when limit is low { diff --git a/sc/shared/src/test/scala/sigmastate/TestingInterpreterSpecification.scala b/sc/shared/src/test/scala/sigmastate/TestingInterpreterSpecification.scala index fe5a678679..736ea15abb 100644 --- a/sc/shared/src/test/scala/sigmastate/TestingInterpreterSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/TestingInterpreterSpecification.scala @@ -6,12 +6,12 @@ import sigma.ast._ import sigma.ast.syntax._ import sigmastate.interpreter._ import Interpreter._ -import sigma.ast.syntax._ import org.ergoplatform._ import org.scalatest.BeforeAndAfterAll import scorex.util.encode.Base58 import sigma.crypto.CryptoConstants import sigma.data.{AvlTreeData, CAND, ProveDlog, SigmaBoolean, TrivialProp} +import sigma.VersionContext.V6SoftForkVersion import sigma.util.Extensions.IntOps import sigmastate.helpers.{CompilerTestingCommons, ErgoLikeContextTesting, ErgoLikeTestInterpreter, ErgoLikeTestProvingInterpreter} import sigmastate.helpers.TestingHelpers._ @@ -204,6 +204,23 @@ class TestingInterpreterSpecification extends CompilerTestingCommons |}""".stripMargin) } + property("Evaluate BigInt to nbits conversion") { + val source = + """ + |{ + | val b: BigInt = 11999.toBigInt + | b.nbits == 36626176 + |} + |""".stripMargin + if (activatedVersionInTests < V6SoftForkVersion) { + println("h") + an [sigmastate.exceptions.MethodNotFound] should be thrownBy testEval(source, true) + } else { + println("here!") + testEval(source, true) + } + } + property("Evaluate numeric casting ops") { def testWithCasting(castSuffix: String): Unit = { testEval(s"OUTPUTS.size.toByte.$castSuffix == 0.$castSuffix") From bb6224ca8408baf61130d6144e49adfcb10a4da7 Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Tue, 9 Apr 2024 14:25:48 +0300 Subject: [PATCH 026/314] removing unused code from ContractsTestkit, ErgoScriptTestkit, and MethodCalls --- .../scala/sigmastate/eval/BasicOpsTests.scala | 7 ++-- .../special/sigma/ContractsTestkit.scala | 35 ++----------------- .../src/main/scala/scalan/MethodCalls.scala | 24 ++----------- .../scala/sigma/SigmaDslStaginTests.scala | 4 +-- .../sigmastate/eval/ErgoScriptTestkit.scala | 12 ++----- 5 files changed, 12 insertions(+), 70 deletions(-) diff --git a/interpreter/shared/src/test/scala/sigmastate/eval/BasicOpsTests.scala b/interpreter/shared/src/test/scala/sigmastate/eval/BasicOpsTests.scala index ba996b0246..e9ba273e17 100644 --- a/interpreter/shared/src/test/scala/sigmastate/eval/BasicOpsTests.scala +++ b/interpreter/shared/src/test/scala/sigmastate/eval/BasicOpsTests.scala @@ -3,16 +3,15 @@ package sigmastate.eval import org.scalatest.funsuite.AnyFunSuite import org.scalatest.matchers.should.Matchers import sigma.crypto.SecP256K1Group -import sigma.data.{CSigmaDslBuilder, TrivialProp} +import sigma.data.{CSigmaDslBuilder => SigmaDsl, TrivialProp} import sigma.util.Extensions.SigmaBooleanOps import java.math.BigInteger -import sigma.{ContractsTestkit, SigmaDslBuilder, SigmaProp} +import sigma.{ContractsTestkit, SigmaProp} import scala.language.implicitConversions class BasicOpsTests extends AnyFunSuite with ContractsTestkit with Matchers { - override val SigmaDsl: SigmaDslBuilder = CSigmaDslBuilder implicit def boolToSigma(b: Boolean): SigmaProp = TrivialProp(b).toSigmaProp @@ -60,7 +59,7 @@ class BasicOpsTests extends AnyFunSuite with ContractsTestkit with Matchers { } test("box.creationInfo._1 is Int") { - val box = newAliceBox(1, 100) + val box = newAliceBox(100) box.creationInfo._1 shouldBe a [Integer] } diff --git a/interpreter/shared/src/test/scala/special/sigma/ContractsTestkit.scala b/interpreter/shared/src/test/scala/special/sigma/ContractsTestkit.scala index 720223ee3a..b04e9c150f 100644 --- a/interpreter/shared/src/test/scala/special/sigma/ContractsTestkit.scala +++ b/interpreter/shared/src/test/scala/special/sigma/ContractsTestkit.scala @@ -8,43 +8,18 @@ import sigmastate.eval._ import sigmastate.helpers.TestingHelpers._ import sigma.data._ -import scala.annotation.nowarn // imports implicit ClassTag - trait ContractsTestkit { - val R0 = 0.toByte; - val R1 = 1.toByte; - val R2 = 2.toByte; - val R3 = 3.toByte; - val R4 = 4.toByte; - val R5 = 5.toByte; - val R6 = 6.toByte; - val R7 = 7.toByte; - val R8 = 8.toByte; - val R9 = 9.toByte; + val Colls = new CollOverArrayBuilder - val SigmaDsl: SigmaDslBuilder = CSigmaDslBuilder - val noRegisters = collection[AnyValue]() - val noBytes = collection[Byte]() val noInputs = Array[Box]() val noOutputs = Array[Box]() val dummyPubkey: Array[Byte] = Array.fill(32)(0: Byte) - val dummyADDigest: Coll[Byte] = Colls.fromArray(Array.fill(33)(0: Byte)) val emptyAvlTree = new CAvlTree(AvlTreeData.dummy) val noHeaders = CSigmaDslBuilder.Colls.emptyColl[Header] val dummyPreHeader: PreHeader = null /** Create collection from array of items */ - def collection[T: RType](items: T*) = Colls.fromArray(items.toArray) - - /** Converts a map of registers to collection of registers. */ - def regs(m: Map[Byte, AnyValue]): Coll[AnyValue] = { - val res = new Array[AnyValue](10) - for ( (id, v) <- m ) { - assert(res(id) == null, s"register $id is defined more then once") - res(id) = v - } - Colls.fromArray(res) - } + def collection[T: RType](items: T*): Coll[T] = Colls.fromArray(items.toArray) /** Converts a map of context vars to collection of context vars. */ def contextVars(m: Map[Byte, AnyValue]): Coll[AnyValue] = { @@ -58,9 +33,7 @@ trait ContractsTestkit { Colls.fromArray(res) } - val AliceId = Array[Byte](1) // 0x0001 - - def newAliceBox(@nowarn id: Byte, value: Long): Box = { + def newAliceBox(value: Long): Box = { val ergoBox = testBox(value, ErgoTree.fromProposition(TrueSigmaProp), creationHeight = 0, additionalTokens = Seq(), additionalRegisters = Map()) @@ -90,8 +63,6 @@ trait ContractsTestkit { implicit class TestContextOps(ctx: CContext) { def withInputs(inputs: Box*) = ctx.copy(inputs = inputs.toArray.toColl) - def withOutputs(outputs: Box*) = ctx.copy(outputs = outputs.toArray.toColl) - def withVariables(vars: Map[Int, AnyValue]) = ctx.copy(vars = contextVars(vars.map { case (k, v) => (k.toByte, v) })) } diff --git a/sc/shared/src/main/scala/scalan/MethodCalls.scala b/sc/shared/src/main/scala/scalan/MethodCalls.scala index af3c3201ef..14212df632 100644 --- a/sc/shared/src/main/scala/scalan/MethodCalls.scala +++ b/sc/shared/src/main/scala/scalan/MethodCalls.scala @@ -101,11 +101,6 @@ trait MethodCalls extends Base { self: Scalan => reifyObject(MethodCall(receiver, method, args, neverInvoke)(asElem[Any](resultElem), isAdapterCall)) } - /** Creates new NewObject node and returns its node ref. */ - def newObjEx[A](args: Any*)(implicit eA: Elem[A]): Ref[A] = { - reifyObject(NewObject[A](eA, args)) - } - @tailrec private def baseCause(e: Throwable): Throwable = e match { case e: ExceptionInInitializerError => baseCause(e.getCause) @@ -120,21 +115,6 @@ trait MethodCalls extends Base { self: Scalan => * point we know that the first RW set didn't triggered any rewrite. */ def rewriteNonInvokableMethodCall(@unused mc: MethodCall): Ref[_] = null - /** Create delegate instance suitable for method invocation. - * It is used when T is a class or a trait and the node referred by x doesn't conform to T. - * This method returns dynamically constructed instance, which conforms to T. - * Whenever a method of T is called on that instance, the call is intercepted and - * `DelegatedInterceptionHandler.invoke` method is called, then a new MethodCall can - * be constructed (which is befavior by default). - */ - protected def unrefDelegate[T <: AnyRef](x: Ref[T])(implicit ct: ClassTag[T]): T = { - val d = x.node - if (d.isInstanceOf[Const[_]]) - d.asInstanceOf[Const[T]@unchecked].x - else - !!!(s"Cannot do undefDelegate($x -> ${x.node})") - } - /** Generic helper to call the given method on the given receiver node. */ private[scalan] def invokeMethod[A](receiver: Sym, m: RMethod, args: Array[AnyRef], onInvokeSuccess: Any => A, @@ -148,9 +128,9 @@ trait MethodCalls extends Base { self: Scalan => } catch { case e: Exception => onInvokeException(baseCause(e)) } - } - else + } else { onInvokeImpossible + } } /** Method invocation enabler. diff --git a/sc/shared/src/test/scala/sigma/SigmaDslStaginTests.scala b/sc/shared/src/test/scala/sigma/SigmaDslStaginTests.scala index 5ac9b80889..91178b2b67 100644 --- a/sc/shared/src/test/scala/sigma/SigmaDslStaginTests.scala +++ b/sc/shared/src/test/scala/sigma/SigmaDslStaginTests.scala @@ -28,8 +28,8 @@ class SigmaDslStaginTests extends BaseCtxTests with ErgoScriptTestkit with BaseL type RContext = cake.Context type RBox = cake.Box type RSigmaProp = cake.SigmaProp - val boxA1 = newAliceBox(1, 100) - val boxA2 = newAliceBox(2, 200) + val boxA1 = newAliceBox(100) + val boxA2 = newAliceBox(200) val ctx: SContext = newContext(10, boxA1, VersionContext.MaxSupportedScriptVersion, VersionContext.MaxSupportedScriptVersion) .withInputs(boxA2) .withVariables(Map(1 -> toAnyValue(30), 2 -> toAnyValue(40))) diff --git a/sc/shared/src/test/scala/sigmastate/eval/ErgoScriptTestkit.scala b/sc/shared/src/test/scala/sigmastate/eval/ErgoScriptTestkit.scala index 2832ad27e7..a10a717d2f 100644 --- a/sc/shared/src/test/scala/sigmastate/eval/ErgoScriptTestkit.scala +++ b/sc/shared/src/test/scala/sigmastate/eval/ErgoScriptTestkit.scala @@ -54,9 +54,8 @@ trait ErgoScriptTestkit extends ContractsTestkit with LangTests ergoCtx } - - lazy val boxA1 = newAliceBox(1, 100) - lazy val boxA2 = newAliceBox(2, 200) + lazy val boxA1 = newAliceBox(100) + lazy val boxA2 = newAliceBox(200) lazy val n1Sym = liftConst(n1) @@ -208,13 +207,6 @@ trait ErgoScriptTestkit extends ContractsTestkit with LangTests } } - def Case(env: ScriptEnv, name: String, script: String, ctx: ErgoLikeContext, - calc: Ref[Context] => Ref[Any], - tree: SValue, - result: Result) = - EsTestCase(name, env, Code(script), Option(ctx), None, - Option(calc), Option(tree), result) - def reduce(env: ScriptEnv, name: String, script: String, ergoCtx: ErgoLikeContext, expectedResult: Any): Unit = { val tcase = EsTestCase(name, env, Code(script), Some(ergoCtx), expectedResult = Result(expectedResult)) tcase.doReduce() From 9e4e098873227744bb809ef6ea5c3b567e5995bb Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Wed, 10 Apr 2024 13:34:41 +0300 Subject: [PATCH 027/314] failing roundtrip test for deserialization roundtrip --- .../MethodCallSerializerSpecification.scala | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/interpreter/shared/src/test/scala/sigma/serialization/MethodCallSerializerSpecification.scala b/interpreter/shared/src/test/scala/sigma/serialization/MethodCallSerializerSpecification.scala index ac9c997d98..e04f5e3746 100644 --- a/interpreter/shared/src/test/scala/sigma/serialization/MethodCallSerializerSpecification.scala +++ b/interpreter/shared/src/test/scala/sigma/serialization/MethodCallSerializerSpecification.scala @@ -21,4 +21,14 @@ class MethodCallSerializerSpecification extends SerializationSpecification { ) roundTripTest(expr) } + + property("MethodCall deserialization round trip for BigInt.nbits") { + val bi = BigIntConstant(5) + val expr = MethodCall(bi, + SBigIntMethods.ToNBits, + Vector(), + Map() + ) + roundTripTest(expr) + } } From 1016323a7acec0489c3bf54afa5fca6860e16d46 Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Wed, 10 Apr 2024 14:15:50 +0300 Subject: [PATCH 028/314] importing method def from i675 --- .../src/main/scala/sigma/ast/methods.scala | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/data/shared/src/main/scala/sigma/ast/methods.scala b/data/shared/src/main/scala/sigma/ast/methods.scala index b637acf792..5371be233c 100644 --- a/data/shared/src/main/scala/sigma/ast/methods.scala +++ b/data/shared/src/main/scala/sigma/ast/methods.scala @@ -2,7 +2,7 @@ package sigma.ast import org.ergoplatform._ import org.ergoplatform.validation._ -import sigma._ +import sigma.{VersionContext, _} import sigma.ast.SCollection.{SBooleanArray, SBoxArray, SByteArray, SByteArray2, SHeaderArray} import sigma.ast.SMethod.{MethodCallIrBuilder, MethodCostFunc, javaMethodOf} import sigma.ast.SType.TypeCode @@ -53,7 +53,7 @@ sealed trait MethodsContainer { protected def getMethods(): Seq[SMethod] = Nil /** Returns all the methods of this type. */ - lazy val methods: Seq[SMethod] = { + def methods: Seq[SMethod] = { //todo: consider versioned caching val ms = getMethods().toArray assert(ms.map(_.name).distinct.length == ms.length, s"Duplicate method names in $this") ms.groupBy(_.objType).foreach { case (comp, ms) => @@ -303,6 +303,18 @@ case object SIntMethods extends SNumericTypeMethods { case object SLongMethods extends SNumericTypeMethods { /** Type for which this container defines methods. */ override def ownerType: SMonoType = SLong + + lazy val DecodeNBitsMethod: SMethod = SMethod( + this, "DecodeNBits", SFunc(this.ownerType, SBigInt), 8, FixedCost(JitCost(5))) + .withInfo(PropertyCall, "Consider this Long value as nbits-encoded BigInt value and decode it to BigInt") + + protected override def getMethods(): Seq[SMethod] = { + if (VersionContext.current.isV6SoftForkActivated) { + super.getMethods() ++ Seq(DecodeNBitsMethod) + } else { + super.getMethods() + } + } } /** Methods of BigInt type. Implemented using [[java.math.BigInteger]]. */ From 93748f1ee7c8027ce98c80186e5ebcfed8a199ed Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Wed, 10 Apr 2024 14:32:45 +0300 Subject: [PATCH 029/314] removing decode nbits --- data/shared/src/main/scala/sigma/ast/methods.scala | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/data/shared/src/main/scala/sigma/ast/methods.scala b/data/shared/src/main/scala/sigma/ast/methods.scala index a21459fcb9..adc2a119bf 100644 --- a/data/shared/src/main/scala/sigma/ast/methods.scala +++ b/data/shared/src/main/scala/sigma/ast/methods.scala @@ -303,18 +303,6 @@ case object SIntMethods extends SNumericTypeMethods { case object SLongMethods extends SNumericTypeMethods { /** Type for which this container defines methods. */ override def ownerType: SMonoType = SLong - - lazy val DecodeNBitsMethod: SMethod = SMethod( - this, "DecodeNBits", SFunc(this.ownerType, SBigInt), 8, FixedCost(JitCost(5))) - .withInfo(PropertyCall, "Consider this Long value as nbits-encoded BigInt value and decode it to BigInt") - - protected override def getMethods(): Seq[SMethod] = { - if (VersionContext.current.isV6SoftForkActivated) { - super.getMethods() ++ Seq(DecodeNBitsMethod) - } else { - super.getMethods() - } - } } /** Methods of BigInt type. Implemented using [[java.math.BigInteger]]. */ From 815b224e5d506cc267b8672973bd19005e62f9d6 Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Wed, 10 Apr 2024 19:36:19 +0300 Subject: [PATCH 030/314] importing tonbits method for playing with --- .../src/main/scala/sigma/VersionContext.scala | 6 +-- .../src/main/scala/sigma/ast/methods.scala | 38 ++++++++++++++----- .../MethodCallSerializerSpecification.scala | 10 +++++ 3 files changed, 42 insertions(+), 12 deletions(-) diff --git a/core/shared/src/main/scala/sigma/VersionContext.scala b/core/shared/src/main/scala/sigma/VersionContext.scala index 5663bfed60..19a4857086 100644 --- a/core/shared/src/main/scala/sigma/VersionContext.scala +++ b/core/shared/src/main/scala/sigma/VersionContext.scala @@ -1,6 +1,6 @@ package sigma -import VersionContext.{EvolutionVersion, JitActivationVersion} +import VersionContext.{JitActivationVersion, V6SoftForkVersion} import scala.util.DynamicVariable @@ -24,7 +24,7 @@ case class VersionContext(activatedVersion: Byte, ergoTreeVersion: Byte) { /** @return true, if the activated script version of Ergo protocol on the network is * including Evolution update. */ - def isEvolutionActivated: Boolean = activatedVersion >= EvolutionVersion + def isV6SoftForkActivated: Boolean = activatedVersion >= V6SoftForkVersion } object VersionContext { @@ -48,7 +48,7 @@ object VersionContext { /** * The version of ErgoTree corresponding to "evolution" (6.0) soft-fork */ - val EvolutionVersion: Byte = 3 + val V6SoftForkVersion: Byte = 3 private val _defaultContext = VersionContext( activatedVersion = 1 /* v4.x */, diff --git a/data/shared/src/main/scala/sigma/ast/methods.scala b/data/shared/src/main/scala/sigma/ast/methods.scala index b637acf792..321bbb0f05 100644 --- a/data/shared/src/main/scala/sigma/ast/methods.scala +++ b/data/shared/src/main/scala/sigma/ast/methods.scala @@ -2,7 +2,7 @@ package sigma.ast import org.ergoplatform._ import org.ergoplatform.validation._ -import sigma._ +import sigma.{VersionContext, _} import sigma.ast.SCollection.{SBooleanArray, SBoxArray, SByteArray, SByteArray2, SHeaderArray} import sigma.ast.SMethod.{MethodCallIrBuilder, MethodCostFunc, javaMethodOf} import sigma.ast.SType.TypeCode @@ -53,7 +53,7 @@ sealed trait MethodsContainer { protected def getMethods(): Seq[SMethod] = Nil /** Returns all the methods of this type. */ - lazy val methods: Seq[SMethod] = { + def methods: Seq[SMethod] = { //todo: consider versioned caching val ms = getMethods().toArray assert(ms.map(_.name).distinct.length == ms.length, s"Duplicate method names in $this") ms.groupBy(_.objType).foreach { case (comp, ms) => @@ -310,6 +310,13 @@ case object SBigIntMethods extends SNumericTypeMethods { /** Type for which this container defines methods. */ override def ownerType: SMonoType = SBigInt + final val ToNBitsCostInfo = OperationCostInfo( + FixedCost(JitCost(5)), NamedDesc("NBitsMethodCall")) + + //id = 8 to make it after toBits + val ToNBits = SMethod(this, "nbits", SFunc(this.ownerType, SLong), 8, ToNBitsCostInfo.costKind) + .withInfo(ModQ, "Encode this big integer value as NBits") + /** The following `modQ` methods are not fully implemented in v4.x and this descriptors. * This descritors are remain here in the code and are waiting for full implementation * is upcoming soft-forks at which point the cost parameters should be calculated and @@ -325,13 +332,26 @@ case object SBigIntMethods extends SNumericTypeMethods { .withIRInfo(MethodCallIrBuilder) .withInfo(MethodCall, "Multiply this number with \\lst{other} by module Q.", ArgInfo("other", "Number to multiply with this.")) - protected override def getMethods() = super.getMethods() ++ Seq( -// ModQMethod, -// PlusModQMethod, -// MinusModQMethod, - // TODO soft-fork: https://github.com/ScorexFoundation/sigmastate-interpreter/issues/479 - // MultModQMethod, - ) + protected override def getMethods(): Seq[SMethod] = { + if (VersionContext.current.isV6SoftForkActivated) { + super.getMethods() ++ Seq(ToNBits) + // ModQMethod, + // PlusModQMethod, + // MinusModQMethod, + // TODO soft-fork: https://github.com/ScorexFoundation/sigmastate-interpreter/issues/479 + // MultModQMethod, + } else { + super.getMethods() + } + } + + /** + * + */ + def nbits_eval(mc: MethodCall, bi: sigma.BigInt)(implicit E: ErgoTreeEvaluator): Long = { + ??? + } + } /** Methods of type `String`. */ diff --git a/interpreter/shared/src/test/scala/sigma/serialization/MethodCallSerializerSpecification.scala b/interpreter/shared/src/test/scala/sigma/serialization/MethodCallSerializerSpecification.scala index ac9c997d98..e04f5e3746 100644 --- a/interpreter/shared/src/test/scala/sigma/serialization/MethodCallSerializerSpecification.scala +++ b/interpreter/shared/src/test/scala/sigma/serialization/MethodCallSerializerSpecification.scala @@ -21,4 +21,14 @@ class MethodCallSerializerSpecification extends SerializationSpecification { ) roundTripTest(expr) } + + property("MethodCall deserialization round trip for BigInt.nbits") { + val bi = BigIntConstant(5) + val expr = MethodCall(bi, + SBigIntMethods.ToNBits, + Vector(), + Map() + ) + roundTripTest(expr) + } } From 4fc62c67f7d7351d8ba075891b2c406ecd5598fb Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Thu, 11 Apr 2024 19:12:50 +0300 Subject: [PATCH 031/314] version test for nbits --- .../src/main/scala/sigma/ast/methods.scala | 2 +- .../MethodCallSerializerSpecification.scala | 28 ++++++++++++++----- 2 files changed, 22 insertions(+), 8 deletions(-) diff --git a/data/shared/src/main/scala/sigma/ast/methods.scala b/data/shared/src/main/scala/sigma/ast/methods.scala index 321bbb0f05..c6b71cd120 100644 --- a/data/shared/src/main/scala/sigma/ast/methods.scala +++ b/data/shared/src/main/scala/sigma/ast/methods.scala @@ -61,7 +61,7 @@ sealed trait MethodsContainer { } ms } - private lazy val _methodsMap: Map[Byte, Map[Byte, SMethod]] = methods + private def _methodsMap: Map[Byte, Map[Byte, SMethod]] = methods //todo: consider versioned caching .groupBy(_.objType.typeId) .map { case (typeId, ms) => (typeId -> ms.map(m => m.methodId -> m).toMap) } diff --git a/interpreter/shared/src/test/scala/sigma/serialization/MethodCallSerializerSpecification.scala b/interpreter/shared/src/test/scala/sigma/serialization/MethodCallSerializerSpecification.scala index e04f5e3746..1db166c685 100644 --- a/interpreter/shared/src/test/scala/sigma/serialization/MethodCallSerializerSpecification.scala +++ b/interpreter/shared/src/test/scala/sigma/serialization/MethodCallSerializerSpecification.scala @@ -1,6 +1,8 @@ package sigma.serialization +import sigma.VersionContext import sigma.ast._ +import sigma.validation.ValidationException class MethodCallSerializerSpecification extends SerializationSpecification { @@ -23,12 +25,24 @@ class MethodCallSerializerSpecification extends SerializationSpecification { } property("MethodCall deserialization round trip for BigInt.nbits") { - val bi = BigIntConstant(5) - val expr = MethodCall(bi, - SBigIntMethods.ToNBits, - Vector(), - Map() - ) - roundTripTest(expr) + def code = { + val bi = BigIntConstant(5) + val expr = MethodCall(bi, + SBigIntMethods.ToNBits, + Vector(), + Map() + ) + roundTripTest(expr) + } + + VersionContext.withVersions(VersionContext.V6SoftForkVersion, 1) { + code + } + + an[ValidationException] should be thrownBy ( + VersionContext.withVersions((VersionContext.V6SoftForkVersion - 1).toByte, 1) { + code + } + ) } } From a3cb64d3ba78d31121a2b681d08d67ee886355cd Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Fri, 12 Apr 2024 12:09:31 +0300 Subject: [PATCH 032/314] versioned nbits serialization roundtrip test --- .../MethodCallSerializerSpecification.scala | 28 ++++++++++++++----- .../ErgoAddressSpecification.scala | 1 + .../TestingInterpreterSpecification.scala | 6 ++-- 3 files changed, 24 insertions(+), 11 deletions(-) diff --git a/interpreter/shared/src/test/scala/sigma/serialization/MethodCallSerializerSpecification.scala b/interpreter/shared/src/test/scala/sigma/serialization/MethodCallSerializerSpecification.scala index e04f5e3746..769874d148 100644 --- a/interpreter/shared/src/test/scala/sigma/serialization/MethodCallSerializerSpecification.scala +++ b/interpreter/shared/src/test/scala/sigma/serialization/MethodCallSerializerSpecification.scala @@ -1,6 +1,8 @@ package sigma.serialization +import sigma.VersionContext import sigma.ast._ +import sigma.validation.ValidationException class MethodCallSerializerSpecification extends SerializationSpecification { @@ -23,12 +25,24 @@ class MethodCallSerializerSpecification extends SerializationSpecification { } property("MethodCall deserialization round trip for BigInt.nbits") { - val bi = BigIntConstant(5) - val expr = MethodCall(bi, - SBigIntMethods.ToNBits, - Vector(), - Map() - ) - roundTripTest(expr) + def code = { + val bi = BigIntConstant(5) + val expr = MethodCall(bi, + SBigIntMethods.ToNBits, + Vector(), + Map() + ) + roundTripTest(expr) + } + + // should be ok + VersionContext.withVersions(VersionContext.V6SoftForkVersion, 1) { + code + } + + an[ValidationException] should be thrownBy ( + VersionContext.withVersions((VersionContext.V6SoftForkVersion - 1).toByte, 1) { + code + }) } } diff --git a/sc/shared/src/test/scala/org/ergoplatform/ErgoAddressSpecification.scala b/sc/shared/src/test/scala/org/ergoplatform/ErgoAddressSpecification.scala index 83d2892a0c..d8ee6e3707 100644 --- a/sc/shared/src/test/scala/org/ergoplatform/ErgoAddressSpecification.scala +++ b/sc/shared/src/test/scala/org/ergoplatform/ErgoAddressSpecification.scala @@ -1,6 +1,7 @@ package org.ergoplatform import org.ergoplatform.ErgoAddressEncoder.{MainnetNetworkPrefix, TestnetNetworkPrefix, hash256} +import org.scalatest.propspec.AnyPropSpecLike import org.scalatest.{Assertion, TryValues} import scorex.crypto.hash.Blake2b256 import scorex.util.encode.Base58 diff --git a/sc/shared/src/test/scala/sigmastate/TestingInterpreterSpecification.scala b/sc/shared/src/test/scala/sigmastate/TestingInterpreterSpecification.scala index 736ea15abb..15b94b3ab3 100644 --- a/sc/shared/src/test/scala/sigmastate/TestingInterpreterSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/TestingInterpreterSpecification.scala @@ -213,11 +213,9 @@ class TestingInterpreterSpecification extends CompilerTestingCommons |} |""".stripMargin if (activatedVersionInTests < V6SoftForkVersion) { - println("h") - an [sigmastate.exceptions.MethodNotFound] should be thrownBy testEval(source, true) + an [sigmastate.exceptions.MethodNotFound] should be thrownBy testEval(source) } else { - println("here!") - testEval(source, true) + testEval(source) } } From 8941a8ed7cf06c08879c533f071a604ba3ebe3c9 Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Mon, 15 Apr 2024 20:52:59 +0300 Subject: [PATCH 033/314] nbits evaluation test --- .../scala/sigmastate/eval/BasicOpsTests.scala | 29 ++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/interpreter/shared/src/test/scala/sigmastate/eval/BasicOpsTests.scala b/interpreter/shared/src/test/scala/sigmastate/eval/BasicOpsTests.scala index ba996b0246..d3474d9355 100644 --- a/interpreter/shared/src/test/scala/sigmastate/eval/BasicOpsTests.scala +++ b/interpreter/shared/src/test/scala/sigmastate/eval/BasicOpsTests.scala @@ -2,12 +2,16 @@ package sigmastate.eval import org.scalatest.funsuite.AnyFunSuite import org.scalatest.matchers.should.Matchers +import sigma.ast.{BigIntConstant, ErgoTree, JitCost, MethodCall, SBigIntMethods} import sigma.crypto.SecP256K1Group -import sigma.data.{CSigmaDslBuilder, TrivialProp} +import sigma.data.{CBigInt, CSigmaDslBuilder, TrivialProp} import sigma.util.Extensions.SigmaBooleanOps +import sigma.util.NBitsUtils import java.math.BigInteger import sigma.{ContractsTestkit, SigmaDslBuilder, SigmaProp} +import sigmastate.interpreter.{CErgoTreeEvaluator, CostAccumulator} +import sigmastate.interpreter.CErgoTreeEvaluator.DefaultProfiler import scala.language.implicitConversions @@ -64,4 +68,27 @@ class BasicOpsTests extends AnyFunSuite with ContractsTestkit with Matchers { box.creationInfo._1 shouldBe a [Integer] } + /** + * Checks BigInt.nbits evaluation for SigmaDSL as well as AST interpreter (MethodCall) layers + */ + test("nbits evaluation") { + SigmaDsl.BigInt(BigInteger.valueOf(0)).nbits should be + (NBitsUtils.encodeCompactBits(0)) + + val es = CErgoTreeEvaluator.DefaultEvalSettings + val accumulator = new CostAccumulator( + initialCost = JitCost(0), + costLimit = Some(JitCost.fromBlockCost(es.scriptCostLimitInEvaluator))) + val evaluator = new CErgoTreeEvaluator( + context = null, + constants = ErgoTree.EmptyConstants, + coster = accumulator, DefaultProfiler, es) + + val res = MethodCall(BigIntConstant(BigInteger.valueOf(0)), SBigIntMethods.ToNBits, IndexedSeq.empty, Map.empty) + .evalTo[Long](Map.empty)(evaluator) + + res should be (NBitsUtils.encodeCompactBits(0)) + + } + } From 9c93753ccc54359b9b1d870bed42b7eb92103fda Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Mon, 15 Apr 2024 22:39:29 +0300 Subject: [PATCH 034/314] removing unused code from SigmaTestingData --- .../special/sigma/SigmaTestingData.scala | 63 +------------------ 1 file changed, 1 insertion(+), 62 deletions(-) diff --git a/interpreter/shared/src/test/scala/special/sigma/SigmaTestingData.scala b/interpreter/shared/src/test/scala/special/sigma/SigmaTestingData.scala index d33f09dd80..f113a484ef 100644 --- a/interpreter/shared/src/test/scala/special/sigma/SigmaTestingData.scala +++ b/interpreter/shared/src/test/scala/special/sigma/SigmaTestingData.scala @@ -30,13 +30,6 @@ trait SigmaTestingData extends TestingCommons with ObjectGenerators { def Coll[T](items: T*)(implicit cT: RType[T]): Coll[T] = CSigmaDslBuilder.Colls.fromItems(items: _*) - /** Generator of random collection with `n` elements. */ - def collOfN[T: RType : Arbitrary](n: Int) - (implicit b: Buildable[T, Array[T]]): Gen[Coll[T]] = { - implicit val g: Gen[T] = Arbitrary.arbitrary[T] - containerOfN[Array, T](n, g).map(Colls.fromArray(_)) - } - val bytesGen: Gen[Array[Byte]] = for { len <- Gen.choose(0, 100) arr <- containerOfN[Array, Byte](len, Arbitrary.arbByte.arbitrary) @@ -54,63 +47,9 @@ trait SigmaTestingData extends TestingCommons with ObjectGenerators { res } - protected def sampleAvlProver = { - val keys = arrayOfN(100, keyCollGen).sample.get - val values = arrayOfN(100, bytesCollGen).sample.get - val (tree, prover) = createAvlTreeAndProver(keys.zip(values): _*) - (keys, values, tree, prover) - } - - protected def sampleAvlTree: AvlTree = { - val (_, _, _, avlProver) = sampleAvlProver - val digest = avlProver.digest.toColl - val tree = SigmaDsl.avlTree(AvlTreeFlags.ReadOnly.serializeToByte, digest, 32, None) - tree - } - val tokenId1: Digest32 = Blake2b256("id1") val tokenId2: Digest32 = Blake2b256("id2") - val header1: Header = CHeader(Blake2b256("Header.id").toColl, - 0, - Blake2b256("Header.parentId").toColl, - Blake2b256("ADProofsRoot").toColl, - sampleAvlTree, - Blake2b256("transactionsRoot").toColl, - timestamp = 0, - nBits = 0, - height = 0, - extensionRoot = Blake2b256("transactionsRoot").toColl, - minerPk = SigmaDsl.groupGenerator, - powOnetimePk = SigmaDsl.groupGenerator, - powNonce = Colls.fromArray(Array[Byte](0, 1, 2, 3, 4, 5, 6, 7)), - powDistance = SigmaDsl.BigInt(BigInt("1405498250268750867257727119510201256371618473728619086008183115260323").bigInteger), - votes = Colls.fromArray(Array[Byte](0, 1, 2)) - ) - val header2: Header = CHeader(Blake2b256("Header2.id").toColl, - 0, - header1.id, - Blake2b256("ADProofsRoot2").toColl, - sampleAvlTree, - Blake2b256("transactionsRoot2").toColl, - timestamp = 2, - nBits = 0, - height = 1, - extensionRoot = Blake2b256("transactionsRoot2").toColl, - minerPk = SigmaDsl.groupGenerator, - powOnetimePk = SigmaDsl.groupGenerator, - powNonce = Colls.fromArray(Array.fill(0.toByte)(8)), - powDistance = SigmaDsl.BigInt(BigInt("19306206489815517413186395405558417825367537880571815686937307203793939").bigInteger), - votes = Colls.fromArray(Array[Byte](0, 1, 0)) - ) - val headers = Colls.fromItems(header2, header1) - val preHeader: PreHeader = CPreHeader(0, - header2.id, - timestamp = 3, - nBits = 0, - height = 2, - minerPk = SigmaDsl.groupGenerator, - votes = Colls.emptyColl[Byte] - ) + object TestData { val BigIntZero: BigInt = CBigInt(new BigInteger("0", 16)) From a9cf9037c6c5bced20c4d4506a5e5e80dd056a9c Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Wed, 17 Apr 2024 18:41:50 +0300 Subject: [PATCH 035/314] SigmaDsl.toBigInteger/BigInt removed --- core/shared/src/main/scala/sigma/SigmaDsl.scala | 6 ------ .../shared/src/main/scala/sigma/data/CSigmaDslBuilder.scala | 4 ---- 2 files changed, 10 deletions(-) diff --git a/core/shared/src/main/scala/sigma/SigmaDsl.scala b/core/shared/src/main/scala/sigma/SigmaDsl.scala index df2b419273..e8ffef3fcf 100644 --- a/core/shared/src/main/scala/sigma/SigmaDsl.scala +++ b/core/shared/src/main/scala/sigma/SigmaDsl.scala @@ -718,12 +718,6 @@ trait SigmaDslBuilder { */ def decodePoint(encoded: Coll[Byte]): GroupElement - /** Create DSL big integer from existing `java.math.BigInteger`*/ - def BigInt(n: BigInteger): BigInt - - /** Extract `java.math.BigInteger` from DSL's `BigInt` type*/ - def toBigInteger(n: BigInt): BigInteger - /** Construct a new authenticated dictionary with given parameters and tree root digest. */ def avlTree(operationFlags: Byte, digest: Coll[Byte], keyLength: Int, valueLengthOpt: Option[Int]): AvlTree diff --git a/data/shared/src/main/scala/sigma/data/CSigmaDslBuilder.scala b/data/shared/src/main/scala/sigma/data/CSigmaDslBuilder.scala index 3938feacd3..c806d4a8c5 100644 --- a/data/shared/src/main/scala/sigma/data/CSigmaDslBuilder.scala +++ b/data/shared/src/main/scala/sigma/data/CSigmaDslBuilder.scala @@ -24,10 +24,6 @@ class CSigmaDslBuilder extends SigmaDslBuilder { dsl => override val Colls: CollBuilder = sigma.Colls - override def BigInt(n: BigInteger): BigInt = CBigInt(n) - - override def toBigInteger(n: BigInt): BigInteger = n.asInstanceOf[CBigInt].wrappedValue - /** Wraps the given elliptic curve point into GroupElement type. */ def GroupElement(p: Ecp): GroupElement = p match { case ept: EcPointType => CGroupElement(ept) From 7562e33bce5dfc20c3fc8ba13ebabb3099b82cf3 Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Tue, 23 Apr 2024 12:30:55 +0300 Subject: [PATCH 036/314] unused SigmaDslBuilderAdapter.groupGenerator removed --- .../main/scala/special/sigma/impl/SigmaDslImpl.scala | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/sc/shared/src/main/scala/special/sigma/impl/SigmaDslImpl.scala b/sc/shared/src/main/scala/special/sigma/impl/SigmaDslImpl.scala index 037505b531..929d81460d 100644 --- a/sc/shared/src/main/scala/special/sigma/impl/SigmaDslImpl.scala +++ b/sc/shared/src/main/scala/special/sigma/impl/SigmaDslImpl.scala @@ -2278,16 +2278,6 @@ object SigmaDslBuilder extends EntityObject("SigmaDslBuilder") { def unapply(exp: Sym): Nullable[(Ref[SigmaDslBuilder], Ref[GroupElement], Ref[GroupElement], Ref[GroupElement], Ref[GroupElement])] = unapply(exp.node) } - object groupGenerator { - def unapply(d: Def[_]): Nullable[Ref[SigmaDslBuilder]] = d match { - case MethodCall(receiver, method, _, _) if method.getName == "groupGenerator" && receiver.elem.isInstanceOf[SigmaDslBuilderElem[_]] => - val res = receiver - Nullable(res).asInstanceOf[Nullable[Ref[SigmaDslBuilder]]] - case _ => Nullable.None - } - def unapply(exp: Sym): Nullable[Ref[SigmaDslBuilder]] = unapply(exp.node) - } - object substConstants { def unapply(d: Def[_]): Nullable[(Ref[SigmaDslBuilder], Ref[Coll[Byte]], Ref[Coll[Int]], Ref[Coll[T]]) forSome {type T}] = d match { case MethodCall(receiver, method, args, _) if method.getName == "substConstants" && receiver.elem.isInstanceOf[SigmaDslBuilderElem[_]] => From 2590bfa0e92f9442abb940a69f8d57bd8d3cde1c Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Wed, 24 Apr 2024 15:04:49 +0300 Subject: [PATCH 037/314] bigInt predefined function --- .../src/main/scala/sigma/ast/SigmaPredef.scala | 14 ++++++++++++++ docs/LangSpec.md | 6 ++++++ .../scala/sigmastate/lang/SigmaParserTest.scala | 5 +++++ .../scala/sigmastate/lang/SigmaCompilerTest.scala | 9 +++++++++ .../scala/sigmastate/lang/SigmaTyperTest.scala | 1 + 5 files changed, 35 insertions(+) diff --git a/data/shared/src/main/scala/sigma/ast/SigmaPredef.scala b/data/shared/src/main/scala/sigma/ast/SigmaPredef.scala index c4bc32e4a5..8edf9683f5 100644 --- a/data/shared/src/main/scala/sigma/ast/SigmaPredef.scala +++ b/data/shared/src/main/scala/sigma/ast/SigmaPredef.scala @@ -12,6 +12,8 @@ import sigma.exceptions.InvalidArguments import sigma.serialization.CoreByteWriter.ArgInfo import sigma.serialization.ValueSerializer +import java.math.BigInteger + object SigmaPredef { type IrBuilderFunc = PartialFunction[(SValue, Seq[SValue]), SValue] @@ -179,6 +181,17 @@ object SigmaPredef { Seq(ArgInfo("", ""))) ) + val BigIntFromStringFunc = PredefinedFunc("bigInt", + Lambda(Array("input" -> SString), SBigInt, None), + PredefFuncInfo( + { case (_, Seq(arg: EvaluatedValue[SString.type]@unchecked)) => + BigIntConstant(new BigInteger(arg.value)) + }), + OperationInfo(Constant, + """Parsing string argument as a 256-bit signed big integer.""".stripMargin, + Seq(ArgInfo("", ""))) + ) + val FromBase16Func = PredefinedFunc("fromBase16", Lambda(Array("input" -> SString), SByteArray, None), PredefFuncInfo( @@ -402,6 +415,7 @@ object SigmaPredef { SigmaPropFunc, GetVarFunc, DeserializeFunc, + BigIntFromStringFunc, FromBase16Func, FromBase64Func, FromBase58Func, diff --git a/docs/LangSpec.md b/docs/LangSpec.md index ddbb7bd680..59eacc3d80 100644 --- a/docs/LangSpec.md +++ b/docs/LangSpec.md @@ -985,6 +985,12 @@ def proveDHTuple(g: GroupElement, h: GroupElement, */ def proveDlog(value: GroupElement): SigmaProp +/** Transforms Base16 encoded string literal into constant of type Coll[Byte]. + * It is a compile-time operation and only string literal (constant) can be its + * argument. + */ +def bigInt(input: String): BigInt + /** Transforms Base16 encoded string literal into constant of type Coll[Byte]. * It is a compile-time operation and only string literal (constant) can be its * argument. diff --git a/parsers/shared/src/test/scala/sigmastate/lang/SigmaParserTest.scala b/parsers/shared/src/test/scala/sigmastate/lang/SigmaParserTest.scala index 7213088a05..02b28f86ca 100644 --- a/parsers/shared/src/test/scala/sigmastate/lang/SigmaParserTest.scala +++ b/parsers/shared/src/test/scala/sigmastate/lang/SigmaParserTest.scala @@ -615,6 +615,11 @@ class SigmaParserTest extends AnyPropSpec with ScalaCheckPropertyChecks with Mat MethodCallLike(StringConstant("hello"), "+", IndexedSeq(StringConstant("hello"))) } + property("bigInt string decoding") { + parse("""bigInt("32667486267383620946248345338628674027033885928301927616853987602485119134400")""") shouldBe + Apply(BigIntFromStringFunc.symNoType, IndexedSeq(StringConstant("32667486267383620946248345338628674027033885928301927616853987602485119134400"))) + } + property("fromBaseX string decoding") { parse("""fromBase16("1111")""") shouldBe Apply(FromBase16Func.symNoType, IndexedSeq(StringConstant("1111"))) parse("""fromBase58("111")""") shouldBe Apply(FromBase58Func.symNoType, IndexedSeq(StringConstant("111"))) diff --git a/sc/shared/src/test/scala/sigmastate/lang/SigmaCompilerTest.scala b/sc/shared/src/test/scala/sigmastate/lang/SigmaCompilerTest.scala index 88c75a90b6..90e5d21b1e 100644 --- a/sc/shared/src/test/scala/sigmastate/lang/SigmaCompilerTest.scala +++ b/sc/shared/src/test/scala/sigmastate/lang/SigmaCompilerTest.scala @@ -12,6 +12,8 @@ import sigma.ast.{Apply, MethodCall, ZKProofBlock} import sigma.exceptions.{GraphBuildingException, InvalidArguments, TyperException} import sigma.serialization.ValueSerializer import sigma.serialization.generators.ObjectGenerators + +import java.math.BigInteger import scala.annotation.unused class SigmaCompilerTest extends CompilerTestingCommons with LangTests with ObjectGenerators { @@ -127,6 +129,13 @@ class SigmaCompilerTest extends CompilerTestingCommons with LangTests with Objec res shouldEqual SigmaPropConstant(dk1) } + property("bigInt") { + comp(""" bigInt("326674862673836209462483453386286740270338859283019276168539876024851191344") """) shouldBe + BigIntConstant(new BigInteger("326674862673836209462483453386286740270338859283019276168539876024851191344")) + comp(""" bigInt("-10") """) shouldBe + BigIntConstant(-10L) + } + property("fromBaseX") { comp(""" fromBase16("31") """) shouldBe ByteArrayConstant(Array[Byte](49)) comp(""" fromBase58("r") """) shouldBe ByteArrayConstant(Array[Byte](49)) diff --git a/sc/shared/src/test/scala/sigmastate/lang/SigmaTyperTest.scala b/sc/shared/src/test/scala/sigmastate/lang/SigmaTyperTest.scala index 99ad2ae908..a474727943 100644 --- a/sc/shared/src/test/scala/sigmastate/lang/SigmaTyperTest.scala +++ b/sc/shared/src/test/scala/sigmastate/lang/SigmaTyperTest.scala @@ -113,6 +113,7 @@ class SigmaTyperTest extends AnyPropSpec typecheck(env, "min(HEIGHT, INPUTS.size)") shouldBe SInt typecheck(env, "max(1, 2)") shouldBe SInt typecheck(env, "max(1L, 2)") shouldBe SLong + typecheck(env, """bigInt("1111")""") shouldBe SBigInt typecheck(env, """fromBase16("1111")""") shouldBe SByteArray typecheck(env, """fromBase58("111")""") shouldBe SByteArray typecheck(env, """fromBase64("111")""") shouldBe SByteArray From 647ae31fc80bdf7e7746a04b8454beab3bc50fe0 Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Sat, 27 Apr 2024 21:17:36 +0300 Subject: [PATCH 038/314] checkPow impl before tests --- .../src/main/scala/sigma/SigmaDsl.scala | 7 + .../sigma/reflection/ReflectionData.scala | 3 + .../main/scala/sigma/util/NBitsUtils.scala | 84 +++++++++ .../org/ergoplatform/HeaderWithoutPow.scala | 137 ++++++++++++++ .../src/main/scala/sigma/ast/methods.scala | 30 +++- .../scala/sigma/eval/ErgoTreeEvaluator.scala | 5 +- .../sigma/pow/Autolykos2PowValidation.scala | 167 ++++++++++++++++++ .../main/scala/sigmastate/eval/CHeader.scala | 25 ++- .../interpreter/CErgoTreeEvaluator.scala | 15 +- .../generators/ObjectGenerators.scala | 3 +- .../special/sigma/SigmaTestingData.scala | 9 +- .../scala/sigmastate/eval/GraphBuilding.scala | 4 +- .../scala/special/sigma/SigmaDslUnit.scala | 1 + .../special/sigma/impl/SigmaDslImpl.scala | 14 ++ .../scala/sigma/SigmaDslSpecification.scala | 3 +- .../org/ergoplatform/sdk/js/Header.scala | 4 +- .../scala/org/ergoplatform/sdk/js/Isos.scala | 7 +- .../org/ergoplatform/sdk/JsonCodecs.scala | 7 +- 18 files changed, 502 insertions(+), 23 deletions(-) create mode 100644 core/shared/src/main/scala/sigma/util/NBitsUtils.scala create mode 100644 data/shared/src/main/scala/org/ergoplatform/HeaderWithoutPow.scala create mode 100644 data/shared/src/main/scala/sigma/pow/Autolykos2PowValidation.scala diff --git a/core/shared/src/main/scala/sigma/SigmaDsl.scala b/core/shared/src/main/scala/sigma/SigmaDsl.scala index df2b419273..a2894515a2 100644 --- a/core/shared/src/main/scala/sigma/SigmaDsl.scala +++ b/core/shared/src/main/scala/sigma/SigmaDsl.scala @@ -459,6 +459,13 @@ trait Header { /** Miner votes for changing system parameters. */ def votes: Coll[Byte] //3 bytes + + def unparsedBytes: Coll[Byte] + + def serializeWithoutPoW: Coll[Byte] + + def checkPow: Boolean + } /** Runtime representation of Context ErgoTree type. diff --git a/core/shared/src/main/scala/sigma/reflection/ReflectionData.scala b/core/shared/src/main/scala/sigma/reflection/ReflectionData.scala index 2aac1a5670..c5259e142f 100644 --- a/core/shared/src/main/scala/sigma/reflection/ReflectionData.scala +++ b/core/shared/src/main/scala/sigma/reflection/ReflectionData.scala @@ -340,6 +340,9 @@ object ReflectionData { }, mkMethod(clazz, "powDistance", Array[Class[_]]()) { (obj, _) => obj.asInstanceOf[Header].powDistance + }, + mkMethod(clazz, "checkPow", Array[Class[_]]()) { (obj, _) => + obj.asInstanceOf[Header].checkPow } ) ) diff --git a/core/shared/src/main/scala/sigma/util/NBitsUtils.scala b/core/shared/src/main/scala/sigma/util/NBitsUtils.scala new file mode 100644 index 0000000000..36d526d1d5 --- /dev/null +++ b/core/shared/src/main/scala/sigma/util/NBitsUtils.scala @@ -0,0 +1,84 @@ +package sigma.util + +import java.math.BigInteger + +object NBitsUtils { + + /** + *

The "compact" format is a representation of a whole number N using an unsigned 32 bit number similar to a + * floating point format. The most significant 8 bits are the unsigned exponent of base 256. This exponent can + * be thought of as "number of bytes of N". The lower 23 bits are the mantissa. Bit number 24 (0x800000) represents + * the sign of N. Therefore, N = (-1^sign) * mantissa * 256^(exponent-3).

+ * + *

Satoshi's original implementation used BN_bn2mpi() and BN_mpi2bn(). MPI uses the most significant bit of the + * first byte as sign. Thus 0x1234560000 is compact 0x05123456 and 0xc0de000000 is compact 0x0600c0de. Compact + * 0x05c0de00 would be -0x40de000000.

+ * + *

Bitcoin only uses this "compact" format for encoding difficulty targets, which are unsigned 256bit quantities. + * Thus, all the complexities of the sign bit and using base 256 are probably an implementation accident.

+ */ + def decodeCompactBits(compact: Long): BigInt = { + val size: Int = (compact >> 24).toInt & 0xFF + val bytes: Array[Byte] = new Array[Byte](4 + size) + bytes(3) = size.toByte + if (size >= 1) bytes(4) = ((compact >> 16) & 0xFF).toByte + if (size >= 2) bytes(5) = ((compact >> 8) & 0xFF).toByte + if (size >= 3) bytes(6) = (compact & 0xFF).toByte + decodeMPI(bytes) + } + + /** + * @see Utils#decodeCompactBits(long) + */ + def encodeCompactBits(requiredDifficulty: BigInt): Long = { + val value = requiredDifficulty.bigInteger + var result: Long = 0L + var size: Int = value.toByteArray.length + if (size <= 3) { + result = value.longValue << 8 * (3 - size) + } else { + result = value.shiftRight(8 * (size - 3)).longValue + } + // The 0x00800000 bit denotes the sign. + // Thus, if it is already set, divide the mantissa by 256 and increase the exponent. + if ((result & 0x00800000L) != 0) { + result >>= 8 + size += 1 + } + result |= size << 24 + val a: Int = if (value.signum == -1) 0x00800000 else 0 + result |= a + result + } + + + /** Parse 4 bytes from the byte array (starting at the offset) as unsigned 32-bit integer in big endian format. */ + def readUint32BE(bytes: Array[Byte]): Long = ((bytes(0) & 0xffL) << 24) | ((bytes(1) & 0xffL) << 16) | ((bytes(2) & 0xffL) << 8) | (bytes(3) & 0xffL) + + /** + * MPI encoded numbers are produced by the OpenSSL BN_bn2mpi function. They consist of + * a 4 byte big endian length field, followed by the stated number of bytes representing + * the number in big endian format (with a sign bit). + * + */ + private def decodeMPI(mpi: Array[Byte]): BigInteger = { + + val length: Int = readUint32BE(mpi).toInt + val buf = new Array[Byte](length) + System.arraycopy(mpi, 4, buf, 0, length) + + if (buf.length == 0) { + BigInteger.ZERO + } else { + val isNegative: Boolean = (buf(0) & 0x80) == 0x80 + if (isNegative) buf(0) = (buf(0) & 0x7f).toByte + val result: BigInteger = new BigInteger(buf) + if (isNegative) { + result.negate + } else { + result + } + } + } + +} diff --git a/data/shared/src/main/scala/org/ergoplatform/HeaderWithoutPow.scala b/data/shared/src/main/scala/org/ergoplatform/HeaderWithoutPow.scala new file mode 100644 index 0000000000..d29cc6cbd8 --- /dev/null +++ b/data/shared/src/main/scala/org/ergoplatform/HeaderWithoutPow.scala @@ -0,0 +1,137 @@ +package org.ergoplatform + +import scorex.crypto.authds.ADDigest +import scorex.crypto.hash.Digest32 +import scorex.util.{ModifierId, bytesToId, idToBytes} +import sigma.serialization.{SigmaByteReader, SigmaByteWriter, SigmaSerializer} +import scorex.util.Extensions._ + +//todo: unify with Ergo node codebase + +/** + * Header without proof-of-work puzzle solution, see Header class description for details. + */ +class HeaderWithoutPow(val version: Byte, // 1 byte + val parentId: ModifierId, // 32 bytes + val ADProofsRoot: Digest32, // 32 bytes + val stateRoot: ADDigest, //33 bytes! extra byte with tree height here! + val transactionsRoot: Digest32, // 32 bytes + val timestamp: Long, + val nBits: Long, //actually it is unsigned int + val height: Int, + val extensionRoot: Digest32, + val votes: Array[Byte], //3 bytes + val unparsedBytes: Array[Byte]) + +object HeaderWithoutPow { + + def apply(version: Byte, parentId: ModifierId, ADProofsRoot: Digest32, stateRoot: ADDigest, + transactionsRoot: Digest32, timestamp: Long, nBits: Long, height: Int, + extensionRoot: Digest32, votes: Array[Byte], unparsedBytes: Array[Byte]): HeaderWithoutPow = { + new HeaderWithoutPow(version, parentId, ADProofsRoot, stateRoot, transactionsRoot, timestamp, + nBits, height, extensionRoot, votes, unparsedBytes) + } + +} + +object HeaderWithoutPowSerializer extends SigmaSerializer[HeaderWithoutPow, HeaderWithoutPow] { + + override def serialize(h: HeaderWithoutPow, w: SigmaByteWriter): Unit = { + w.put(h.version) + w.putBytes(idToBytes(h.parentId)) + w.putBytes(h.ADProofsRoot) + w.putBytes(h.transactionsRoot) + w.putBytes(h.stateRoot) + w.putULong(h.timestamp) + w.putBytes(h.extensionRoot) + DifficultySerializer.serialize(h.nBits, w) + w.putUInt(h.height.toLong) + w.putBytes(h.votes) + + // For block version >= 2, this new byte encodes length of possible new fields. + // Set to 0 for now, so no new fields. + if (h.version > HeaderVersion.InitialVersion) { + w.putUByte(h.unparsedBytes.length) + w.putBytes(h.unparsedBytes) + } + } + + override def parse(r: SigmaByteReader): HeaderWithoutPow = { + val version = r.getByte() + val parentId = bytesToId(r.getBytes(32)) + val ADProofsRoot = Digest32 @@ r.getBytes(32) + val transactionsRoot = Digest32 @@ r.getBytes(32) + val stateRoot = ADDigest @@ r.getBytes(33) + val timestamp = r.getULong() + val extensionHash = Digest32 @@ r.getBytes(32) + val nBits = DifficultySerializer.parse(r) + val height = r.getUInt().toIntExact + val votes = r.getBytes(3) + + // For block version >= 2, a new byte encodes length of possible new fields. + // If this byte > 0, we read new fields but do nothing, as semantics of the fields is not known. + val unparsedBytes = if (version > HeaderVersion.InitialVersion) { + val newFieldsSize = r.getUByte() + if (newFieldsSize > 0 && version > HeaderVersion.Interpreter60Version) { + // new bytes could be added only for block version >= 5 + r.getBytes(newFieldsSize) + } else { + Array.emptyByteArray + } + } else { + Array.emptyByteArray + } + + HeaderWithoutPow(version, parentId, ADProofsRoot, stateRoot, transactionsRoot, timestamp, + nBits, height, extensionHash, votes, unparsedBytes) + } + +} + + +object DifficultySerializer extends SigmaSerializer[Long, Long] { + + /** Parse 4 bytes from the byte array (starting at the offset) as unsigned 32-bit integer in big endian format. */ + def readUint32BE(bytes: Array[Byte]): Long = ((bytes(0) & 0xffL) << 24) | ((bytes(1) & 0xffL) << 16) | ((bytes(2) & 0xffL) << 8) | (bytes(3) & 0xffL) + + def uint32ToByteArrayBE(value: Long): Array[Byte] = { + Array(0xFF & (value >> 24), 0xFF & (value >> 16), 0xFF & (value >> 8), 0xFF & value).map(_.toByte) + } + + override def serialize(obj: Long, w: SigmaByteWriter): Unit = { + w.putBytes(uint32ToByteArrayBE(obj)) + } + + override def parse(r: SigmaByteReader): Long = { + readUint32BE(r.getBytes(4)) + } + +} + +object HeaderVersion { + type Value = Byte + + /** + * Block version during mainnet launch + */ + val InitialVersion: Value = 1.toByte + + /** + * Block version after the Hardening hard-fork + * Autolykos v2 PoW, witnesses in transactions Merkle tree + */ + val HardeningVersion: Value = 2.toByte + + /** + * Block version after the 5.0 soft-fork + * 5.0 interpreter with JITC, monotonic height rule (EIP-39) + */ + val Interpreter50Version: Value = 3.toByte + + /** + * Block version after the 6.0 soft-fork + * 6.0 interpreter (EIP-50) + */ + val Interpreter60Version: Value = 4.toByte + +} diff --git a/data/shared/src/main/scala/sigma/ast/methods.scala b/data/shared/src/main/scala/sigma/ast/methods.scala index c6b71cd120..a8c6545a53 100644 --- a/data/shared/src/main/scala/sigma/ast/methods.scala +++ b/data/shared/src/main/scala/sigma/ast/methods.scala @@ -10,6 +10,7 @@ import sigma.ast.syntax.{SValue, ValueOps} import sigma.data.OverloadHack.Overloaded1 import sigma.data.{DataValueComparer, KeyValueColl, Nullable, RType, SigmaConstants} import sigma.eval.{CostDetails, ErgoTreeEvaluator, TracedCost} +import sigma.pow.Autolykos2PowValidation import sigma.reflection.RClass import sigma.serialization.CoreByteWriter.ArgInfo import sigma.utils.SparseArrayContainer @@ -1457,11 +1458,30 @@ case object SHeaderMethods extends MonoTypeMethods { lazy val powDistanceMethod = propertyCall("powDistance", SBigInt, 14, FixedCost(JitCost(10))) lazy val votesMethod = propertyCall("votes", SByteArray, 15, FixedCost(JitCost(10))) - protected override def getMethods() = super.getMethods() ++ Seq( - idMethod, versionMethod, parentIdMethod, ADProofsRootMethod, stateRootMethod, transactionsRootMethod, - timestampMethod, nBitsMethod, heightMethod, extensionRootMethod, minerPkMethod, powOnetimePkMethod, - powNonceMethod, powDistanceMethod, votesMethod - ) + lazy val checkPowMethod = SMethod( + this, "checkPow", SFunc(Array(SHeader), SBoolean), 3, GroupGenerator.costKind) // todo: cost + .withIRInfo(MethodCallIrBuilder) + .withInfo(Xor, "Byte-wise XOR of two collections of bytes") // todo: desc + + def checkPow_eval(mc: MethodCall, G: SigmaDslBuilder, header: Header) + (implicit E: ErgoTreeEvaluator): Boolean = { + E.checkPow_eval(mc, header) + } + + protected override def getMethods() = { + if (VersionContext.current.isV6SoftForkActivated) { + // 6.0 : checkPow method added + super.getMethods() ++ Seq( + idMethod, versionMethod, parentIdMethod, ADProofsRootMethod, stateRootMethod, transactionsRootMethod, + timestampMethod, nBitsMethod, heightMethod, extensionRootMethod, minerPkMethod, powOnetimePkMethod, + powNonceMethod, powDistanceMethod, votesMethod, checkPowMethod) + } else { + super.getMethods() ++ Seq( + idMethod, versionMethod, parentIdMethod, ADProofsRootMethod, stateRootMethod, transactionsRootMethod, + timestampMethod, nBitsMethod, heightMethod, extensionRootMethod, minerPkMethod, powOnetimePkMethod, + powNonceMethod, powDistanceMethod, votesMethod) + } + } } /** Type descriptor of `PreHeader` type of ErgoTree. */ diff --git a/data/shared/src/main/scala/sigma/eval/ErgoTreeEvaluator.scala b/data/shared/src/main/scala/sigma/eval/ErgoTreeEvaluator.scala index 52f839354c..610be08c9c 100644 --- a/data/shared/src/main/scala/sigma/eval/ErgoTreeEvaluator.scala +++ b/data/shared/src/main/scala/sigma/eval/ErgoTreeEvaluator.scala @@ -1,6 +1,6 @@ package sigma.eval -import sigma.{AvlTree, Coll, Context} +import sigma.{AvlTree, Coll, Context, Header} import sigma.ast.{Constant, FixedCost, MethodCall, OperationCostInfo, OperationDesc, PerItemCost, SType, TypeBasedCost} import sigma.data.KeyValueColl @@ -138,6 +138,9 @@ abstract class ErgoTreeEvaluator { def remove_eval( mc: MethodCall, tree: AvlTree, operations: Coll[Coll[Byte]], proof: Coll[Byte]): Option[AvlTree] + + def checkPow_eval(mc: MethodCall, header: Header): Boolean + } object ErgoTreeEvaluator { diff --git a/data/shared/src/main/scala/sigma/pow/Autolykos2PowValidation.scala b/data/shared/src/main/scala/sigma/pow/Autolykos2PowValidation.scala new file mode 100644 index 0000000000..a27dc864d1 --- /dev/null +++ b/data/shared/src/main/scala/sigma/pow/Autolykos2PowValidation.scala @@ -0,0 +1,167 @@ +package sigma.pow + + +import org.bouncycastle.util.BigIntegers +import scorex.crypto.hash.Blake2b256 +import scorex.utils.{Bytes, Ints, Longs} +import sigma.Header +import sigma.crypto.{BcDlogGroup, CryptoConstants} +import sigma.util.NBitsUtils + +object Autolykos2PowValidation { + + type Height = Int + + val k = 32 + + val NStart = 26 + + val group: BcDlogGroup = CryptoConstants.dlogGroup + + // Group order, used in Autolykos V.1 for non-outsourceability, + // and also to obtain target in both Autolykos v1 and v2 + val q: BigInt = group.order + + /** + * Number of elements in a table to find k-sum problem solution on top of + */ + val NBase: Int = Math.pow(2, NStart.toDouble).toInt + + /** + * Initial height since which table (`N` value) starting to increase by 5% per `IncreasePeriodForN` blocks + */ + val IncreaseStart: Height = 600 * 1024 + + /** + * Table size (`N`) increased every 50 * 1024 blocks + */ + val IncreasePeriodForN: Height = 50 * 1024 + + /** + * On this height, the table (`N` value) will stop to grow. + * Max N on and after this height would be 2,143,944,600 which is still less than 2^^31. + */ + val NIncreasementHeightMax: Height = 4198400 + + /** + * Blake2b256 hash function invocation + * @param in - input bit-string + * @return - 256 bits (32 bytes) array + */ + def hash(in: Array[Byte]): Array[Byte] = Blake2b256.hash(in) + + /** + * Convert byte array to unsigned integer + * @param in - byte array + * @return - unsigned integer + */ + def toBigInt(in: Array[Byte]): BigInt = BigInt(BigIntegers.fromUnsignedByteArray(in)) + + /** + * Constant data to be added to hash function to increase its calculation time + */ + val M: Array[Byte] = (0 until 1024).toArray.flatMap(i => Longs.toByteArray(i.toLong)) + + /** + * Calculates table size (N value) for a given height (moment of time) + * + * @see papers/yellow/pow/ErgoPow.tex for full description and test vectors + * @param headerHeight - height of a header to mine + * @return - N value + */ + def calcN(headerHeight: Height): Int = { + val height = Math.min(NIncreasementHeightMax, headerHeight) + if (height < IncreaseStart) { + NBase + } else { + val itersNumber = (height - IncreaseStart) / IncreasePeriodForN + 1 + (1 to itersNumber).foldLeft(NBase) { case (step, _) => + step / 100 * 105 + } + } + } + + def calcN(header: Header): Int = calcN(header.height) + + /** + * Hash function that takes `m` and `nonceBytes` and returns a list of size `k` with numbers in + * [0,`N`) + */ + private def genIndexes(k: Int, seed: Array[Byte], N: Int): Seq[Int] = { + val hash = Blake2b256(seed) + val extendedHash = Bytes.concat(hash, hash.take(3)) + (0 until k).map { i => + BigInt(1, extendedHash.slice(i, i + 4)).mod(N).toInt + } + }.ensuring(_.length == k) + + /** + * Generate element of Autolykos equation. + */ + private def genElementV2(indexBytes: Array[Byte], heightBytes: => Array[Byte]): BigInt = { + // Autolykos v. 2: H(j|h|M) (line 5 from the Algo 2 of the spec) + toBigInt(hash(Bytes.concat(indexBytes, heightBytes, M)).drop(1)) + } + + def hitForVersion2ForMessage(k: Int, msg: Array[Byte], nonce: Array[Byte], h: Array[Byte], N: Int): BigInt = { + + val prei8 = BigIntegers.fromUnsignedByteArray(hash(Bytes.concat(msg, nonce)).takeRight(8)) + val i = BigIntegers.asUnsignedByteArray(4, prei8.mod(BigInt(N).underlying())) + val f = Blake2b256(Bytes.concat(i, h, M)).drop(1) // .drop(1) is the same as takeRight(31) + val seed = Bytes.concat(f, msg, nonce) // Autolykos v1, Alg. 2, line4: + + val indexes = genIndexes(k, seed, N) + //pk and w not used in v2 + val elems = indexes.map(idx => genElementV2(Ints.toByteArray(idx), h)) + val f2 = elems.sum + + // sum as byte array is always about 32 bytes + val array: Array[Byte] = BigIntegers.asUnsignedByteArray(32, f2.underlying()) + val ha = hash(array) + toBigInt(ha) + } + + /** + * Header digest ("message" for default GPU miners) a miner is working on + */ + def msgByHeader(h: Header): Array[Byte] = Blake2b256(h.serializeWithoutPoW.toArray) + + /** + * Get hit for Autolykos v2 header (to test it then against PoW target) + * + * @param header - header to check PoW for + * @return PoW hit + */ + def hitForVersion2(header: Header): BigInt = { + + val msg = msgByHeader(header) + val nonce = header.powNonce + + val h = Ints.toByteArray(header.height) // used in AL v.2 only + + val N = calcN(header) + + hitForVersion2ForMessage(k, msg, nonce.toArray, h, N) + } + + /** + * Get target `b` from encoded difficulty `nBits` + */ + def getB(nBits: Long): BigInt = { + q / NBitsUtils.decodeCompactBits(nBits) + } + + /** + * Check PoW for Autolykos v2 header + * + * @param header - header to check PoW for + * @return whether PoW is valid or not + */ + def checkPoWForVersion2(header: Header): Boolean = { + val b = getB(header.nBits) + // for version 2, we're calculating hit and compare it with target + val hit = hitForVersion2(header) + hit < b + } + +} diff --git a/interpreter/shared/src/main/scala/sigmastate/eval/CHeader.scala b/interpreter/shared/src/main/scala/sigmastate/eval/CHeader.scala index 7062fa0f0e..3bd0dd62f9 100644 --- a/interpreter/shared/src/main/scala/sigmastate/eval/CHeader.scala +++ b/interpreter/shared/src/main/scala/sigmastate/eval/CHeader.scala @@ -1,7 +1,12 @@ package sigmastate.eval +import org.ergoplatform.{HeaderWithoutPow, HeaderWithoutPowSerializer} +import scorex.crypto.authds.ADDigest +import scorex.crypto.hash.Digest32 +import scorex.util.bytesToId import sigma.data.SigmaConstants -import sigma.{AvlTree, BigInt, Coll, GroupElement, Header} +import sigma.pow.Autolykos2PowValidation +import sigma.{AvlTree, BigInt, Coll, Colls, GroupElement, Header} /** A default implementation of [[Header]] interface. * @@ -22,8 +27,22 @@ case class CHeader( powOnetimePk: GroupElement, powNonce: Coll[Byte], powDistance: BigInt, - votes: Coll[Byte] -) extends Header + votes: Coll[Byte], + unparsedBytes: Coll[Byte] +) extends Header { + + override def serializeWithoutPoW: Coll[Byte] = { + val headerWithoutPow = HeaderWithoutPow(version, bytesToId(parentId.toArray), Digest32 @@ ADProofsRoot.toArray, + ADDigest @@ stateRoot.digest.toArray, Digest32 @@ transactionsRoot.toArray, timestamp, + nBits, height, Digest32 @@ extensionRoot.toArray, votes.toArray, unparsedBytes.toArray) + Colls.fromArray(HeaderWithoutPowSerializer.toBytes(headerWithoutPow)) + } + + override def checkPow: Boolean = { + Autolykos2PowValidation.checkPoWForVersion2(this) + } + +} object CHeader { /** Size of of Header.votes array. */ diff --git a/interpreter/shared/src/main/scala/sigmastate/interpreter/CErgoTreeEvaluator.scala b/interpreter/shared/src/main/scala/sigmastate/interpreter/CErgoTreeEvaluator.scala index de8aa6b620..59c9af09ef 100644 --- a/interpreter/shared/src/main/scala/sigmastate/interpreter/CErgoTreeEvaluator.scala +++ b/interpreter/shared/src/main/scala/sigmastate/interpreter/CErgoTreeEvaluator.scala @@ -5,7 +5,7 @@ import sigma.ast._ import sigma.ast.syntax._ import sigmastate.eval.{CAvlTreeVerifier, CProfiler} import sigmastate.interpreter.Interpreter.ReductionResult -import sigma.{AvlTree, Coll, Colls, Context, VersionContext} +import sigma.{AvlTree, Coll, Colls, Context, Header, VersionContext} import sigma.util.Extensions._ import debox.{cfor, Buffer => DBuffer} import scorex.crypto.authds.ADKey @@ -14,6 +14,8 @@ import sigma.ast.SType import sigma.data.{CSigmaProp, KeyValueColl, SigmaBoolean} import sigma.eval.{AvlTreeVerifier, ErgoTreeEvaluator, EvalSettings, Profiler} import sigma.eval.ErgoTreeEvaluator.DataEnv +import sigma.pow.Autolykos2PowValidation +import sigmastate.interpreter.CErgoTreeEvaluator.fixedCostOp import scala.collection.compat.immutable.ArraySeq import scala.util.{DynamicVariable, Failure, Success} @@ -216,6 +218,15 @@ class CErgoTreeEvaluator( } } + override def checkPow_eval(mc: MethodCall, header: Header): Boolean = { + VersionContext.checkVersions(context.activatedScriptVersion, context.currentErgoTreeVersion) + // todo: consider cost + val checkPowCostInfo = OperationCostInfo(FixedCost(JitCost(10)), NamedDesc("Header.checkPow")) + fixedCostOp(checkPowCostInfo){ + header.checkPow + }(this) + } + /** Evaluates the given expression in the given data environment. */ def eval(env: DataEnv, exp: SValue): Any = { VersionContext.checkVersions(context.activatedScriptVersion, context.currentErgoTreeVersion) @@ -449,7 +460,7 @@ object CErgoTreeEvaluator { * HOTSPOT: don't beautify the code * Note, `null` is used instead of Option to avoid allocations. */ - def fixedCostOp[R <: AnyRef](costInfo: OperationCostInfo[FixedCost]) + def fixedCostOp[R](costInfo: OperationCostInfo[FixedCost]) (block: => R)(implicit E: ErgoTreeEvaluator): R = { if (E != null) { var res: R = null.asInstanceOf[R] 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 d4971f88c2..e625923413 100644 --- a/interpreter/shared/src/test/scala/sigma/serialization/generators/ObjectGenerators.scala +++ b/interpreter/shared/src/test/scala/sigma/serialization/generators/ObjectGenerators.scala @@ -707,8 +707,9 @@ trait ObjectGenerators extends TypeGenerators powNonce <- nonceBytesGen powDistance <- arbBigInt.arbitrary votes <- minerVotesGen + unparsedBytes <- collOfRange(0, 32, arbByte.arbitrary) } yield CHeader(id, version, parentId, adProofsRoot, stateRoot, transactionRoot, timestamp, nBits, - height, extensionRoot, minerPk.toGroupElement, powOnetimePk.toGroupElement, powNonce, powDistance, votes) + height, extensionRoot, minerPk.toGroupElement, powOnetimePk.toGroupElement, powNonce, powDistance, votes, unparsedBytes) lazy val headerGen: Gen[Header] = for { stateRoot <- avlTreeGen diff --git a/interpreter/shared/src/test/scala/special/sigma/SigmaTestingData.scala b/interpreter/shared/src/test/scala/special/sigma/SigmaTestingData.scala index d33f09dd80..08fa3439d6 100644 --- a/interpreter/shared/src/test/scala/special/sigma/SigmaTestingData.scala +++ b/interpreter/shared/src/test/scala/special/sigma/SigmaTestingData.scala @@ -84,7 +84,8 @@ trait SigmaTestingData extends TestingCommons with ObjectGenerators { powOnetimePk = SigmaDsl.groupGenerator, powNonce = Colls.fromArray(Array[Byte](0, 1, 2, 3, 4, 5, 6, 7)), powDistance = SigmaDsl.BigInt(BigInt("1405498250268750867257727119510201256371618473728619086008183115260323").bigInteger), - votes = Colls.fromArray(Array[Byte](0, 1, 2)) + votes = Colls.fromArray(Array[Byte](0, 1, 2)), + unparsedBytes = Colls.emptyColl[Byte] ) val header2: Header = CHeader(Blake2b256("Header2.id").toColl, 0, @@ -100,7 +101,8 @@ trait SigmaTestingData extends TestingCommons with ObjectGenerators { powOnetimePk = SigmaDsl.groupGenerator, powNonce = Colls.fromArray(Array.fill(0.toByte)(8)), powDistance = SigmaDsl.BigInt(BigInt("19306206489815517413186395405558417825367537880571815686937307203793939").bigInteger), - votes = Colls.fromArray(Array[Byte](0, 1, 0)) + votes = Colls.fromArray(Array[Byte](0, 1, 0)), + unparsedBytes = Colls.emptyColl[Byte] ) val headers = Colls.fromItems(header2, header1) val preHeader: PreHeader = CPreHeader(0, @@ -321,7 +323,8 @@ trait SigmaTestingData extends TestingCommons with ObjectGenerators { Helpers.decodeGroupElement("0361299207fa392231e23666f6945ae3e867b978e021d8d702872bde454e9abe9c"), Helpers.decodeBytes("7f4f09012a807f01"), CBigInt(new BigInteger("-e24990c47e15ed4d0178c44f1790cc72155d516c43c3e8684e75db3800a288", 16)), - Helpers.decodeBytes("7f0180") + Helpers.decodeBytes("7f0180"), + Colls.emptyColl[Byte] )) def create_h1(): Header = h1_instances.getNext diff --git a/sc/shared/src/main/scala/sigmastate/eval/GraphBuilding.scala b/sc/shared/src/main/scala/sigmastate/eval/GraphBuilding.scala index 9c9fa5ffe1..83db8d3ede 100644 --- a/sc/shared/src/main/scala/sigmastate/eval/GraphBuilding.scala +++ b/sc/shared/src/main/scala/sigmastate/eval/GraphBuilding.scala @@ -2,7 +2,7 @@ package sigmastate.eval import org.ergoplatform._ import scalan.MutableLazy -import sigma.{SigmaException, ast} +import sigma.{SigmaException, VersionContext, ast} import sigma.ast.TypeCodes.LastConstantCode import sigma.ast.Value.Typed import sigma.ast._ @@ -1130,6 +1130,8 @@ trait GraphBuilding extends SigmaLibrary { IR: IRContext => h.powDistance case SHeaderMethods.votesMethod.name => h.votes + case SHeaderMethods.checkPowMethod.name if VersionContext.current.isV6SoftForkActivated => + h.checkPow case _ => throwError } case (g: Ref[SigmaDslBuilder]@unchecked, SGlobalMethods) => method.name match { diff --git a/sc/shared/src/main/scala/special/sigma/SigmaDslUnit.scala b/sc/shared/src/main/scala/special/sigma/SigmaDslUnit.scala index 48548226a5..d84bf40c4f 100644 --- a/sc/shared/src/main/scala/special/sigma/SigmaDslUnit.scala +++ b/sc/shared/src/main/scala/special/sigma/SigmaDslUnit.scala @@ -76,6 +76,7 @@ package sigma { def powNonce: Ref[Coll[Byte]]; def powDistance: Ref[BigInt]; def votes: Ref[Coll[Byte]] + def checkPow: Ref[Boolean] }; trait Context extends Def[Context] { def OUTPUTS: Ref[Coll[Box]]; diff --git a/sc/shared/src/main/scala/special/sigma/impl/SigmaDslImpl.scala b/sc/shared/src/main/scala/special/sigma/impl/SigmaDslImpl.scala index 8da36ce6cf..1a6639c8cd 100644 --- a/sc/shared/src/main/scala/special/sigma/impl/SigmaDslImpl.scala +++ b/sc/shared/src/main/scala/special/sigma/impl/SigmaDslImpl.scala @@ -1367,6 +1367,13 @@ object Header extends EntityObject("Header") { ArraySeq.empty, true, false, element[Coll[Byte]])) } + + override def checkPow: Ref[Boolean] = { + asRep[Boolean](mkMethodCall(self, + HeaderClass.getMethod("checkPow"), + ArraySeq.empty, + true, false, element[Boolean])) + } } implicit object LiftableHeader @@ -1491,6 +1498,13 @@ object Header extends EntityObject("Header") { ArraySeq.empty, true, true, element[Coll[Byte]])) } + + def checkPow: Ref[Boolean] = { + asRep[Boolean](mkMethodCall(source, + HeaderClass.getMethod("checkPow"), + ArraySeq.empty, + true, true, element[Boolean])) + } } // entityUnref: single unref method for each type family diff --git a/sc/shared/src/test/scala/sigma/SigmaDslSpecification.scala b/sc/shared/src/test/scala/sigma/SigmaDslSpecification.scala index 4dd576f03a..7fe0d4395c 100644 --- a/sc/shared/src/test/scala/sigma/SigmaDslSpecification.scala +++ b/sc/shared/src/test/scala/sigma/SigmaDslSpecification.scala @@ -4675,7 +4675,8 @@ class SigmaDslSpecification extends SigmaDslTesting Helpers.decodeGroupElement("034e2d3b5f9e409e3ae8a2e768340760362ca33764eda5855f7a43487f14883300"), Helpers.decodeBytes("974651c9efff7f00"), CBigInt(new BigInteger("478e827dfa1e4b57", 16)), - Helpers.decodeBytes("01ff13") + Helpers.decodeBytes("01ff13"), + Colls.emptyColl ) val ctx = CContext( diff --git a/sdk/js/src/main/scala/org/ergoplatform/sdk/js/Header.scala b/sdk/js/src/main/scala/org/ergoplatform/sdk/js/Header.scala index ef53e13dbd..ec3767c1cd 100644 --- a/sdk/js/src/main/scala/org/ergoplatform/sdk/js/Header.scala +++ b/sdk/js/src/main/scala/org/ergoplatform/sdk/js/Header.scala @@ -48,5 +48,7 @@ class Header( val powDistance: js.BigInt, /** Miner votes for changing system parameters. */ - val votes: String + val votes: String, + + val unparsedBytes: String ) extends js.Object diff --git a/sdk/js/src/main/scala/org/ergoplatform/sdk/js/Isos.scala b/sdk/js/src/main/scala/org/ergoplatform/sdk/js/Isos.scala index f6393f62bb..340765d313 100644 --- a/sdk/js/src/main/scala/org/ergoplatform/sdk/js/Isos.scala +++ b/sdk/js/src/main/scala/org/ergoplatform/sdk/js/Isos.scala @@ -25,7 +25,6 @@ import sigmastate.fleetSdkCommon.distEsmTypesTokenMod.TokenAmount import sigmastate.fleetSdkCommon.distEsmTypesTransactionsMod.{SignedTransaction, UnsignedTransaction} import sigmastate.fleetSdkCommon.{distEsmTypesBoxesMod => boxesMod, distEsmTypesCommonMod => commonMod, distEsmTypesContextExtensionMod => contextExtensionMod, distEsmTypesInputsMod => inputsMod, distEsmTypesProverResultMod => proverResultMod, distEsmTypesRegistersMod => registersMod, distEsmTypesTokenMod => tokenMod} -import java.math.BigInteger import scala.collection.immutable.ListMap import scala.scalajs.js import scala.scalajs.js.Object @@ -87,7 +86,8 @@ object Isos { powOnetimePk = isoGroupElement.to(a.powOnetimePk), powNonce = isoStringToColl.to(a.powNonce), powDistance = sigma.js.Isos.isoBigInt.to(a.powDistance), - votes = isoStringToColl.to(a.votes) + votes = isoStringToColl.to(a.votes), + unparsedBytes = isoStringToColl.to(a.unparsedBytes) ) } override def from(b: sigma.Header): Header = { @@ -107,7 +107,8 @@ object Isos { powOnetimePk = isoGroupElement.from(header.powOnetimePk), powNonce = isoStringToColl.from(header.powNonce), powDistance = sigma.js.Isos.isoBigInt.from(header.powDistance), - votes = isoStringToColl.from(header.votes) + votes = isoStringToColl.from(header.votes), + unparsedBytes = isoStringToColl.from(header.unparsedBytes) ) } } diff --git a/sdk/shared/src/main/scala/org/ergoplatform/sdk/JsonCodecs.scala b/sdk/shared/src/main/scala/org/ergoplatform/sdk/JsonCodecs.scala index ae14fd831a..c2fc1c0c8c 100644 --- a/sdk/shared/src/main/scala/org/ergoplatform/sdk/JsonCodecs.scala +++ b/sdk/shared/src/main/scala/org/ergoplatform/sdk/JsonCodecs.scala @@ -125,7 +125,8 @@ trait JsonCodecs { "powOnetimePk" -> h.powOnetimePk.getEncoded.asJson, "powNonce" -> h.powNonce.asJson, "powDistance" -> h.powDistance.asJson, - "votes" -> h.votes.asJson + "votes" -> h.votes.asJson, + "unparsedBytes" -> h.unparsedBytes.asJson ).asJson }) @@ -146,8 +147,10 @@ trait JsonCodecs { powNonce <- cursor.downField("powNonce").as[Coll[Byte]] powDistance <- cursor.downField("powDistance").as[sigma.BigInt] votes <- cursor.downField("votes").as[Coll[Byte]] + unparsedBytes <- cursor.downField("unparsedBytes").as[Option[Coll[Byte]]] } yield new CHeader(id, version, parentId, adProofsRoot, stateRoot, transactionsRoot, timestamp, nBits, - height, extensionRoot, SigmaDsl.decodePoint(minerPk), SigmaDsl.decodePoint(powOnetimePk), powNonce, powDistance, votes) + height, extensionRoot, SigmaDsl.decodePoint(minerPk), SigmaDsl.decodePoint(powOnetimePk), powNonce, powDistance, + votes, unparsedBytes.getOrElse(Colls.emptyColl)) }) implicit val preHeaderEncoder: Encoder[PreHeader] = Encoder.instance({ v: PreHeader => From 7ada12a374bd5812db4d81e2e8f3f1483999205d Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Sat, 27 Apr 2024 21:32:30 +0300 Subject: [PATCH 039/314] big int related methods back, TestingInterpreterSpecification.soundness and GraphBuilding.substFromCostTable removed --- core/shared/src/main/scala/sigma/SigmaDsl.scala | 6 ++++++ .../src/main/scala/sigma/data/CSigmaDslBuilder.scala | 4 ++++ .../src/main/scala/sigmastate/eval/GraphBuilding.scala | 4 ---- .../sigmastate/TestingInterpreterSpecification.scala | 8 ++------ 4 files changed, 12 insertions(+), 10 deletions(-) diff --git a/core/shared/src/main/scala/sigma/SigmaDsl.scala b/core/shared/src/main/scala/sigma/SigmaDsl.scala index e8ffef3fcf..df2b419273 100644 --- a/core/shared/src/main/scala/sigma/SigmaDsl.scala +++ b/core/shared/src/main/scala/sigma/SigmaDsl.scala @@ -718,6 +718,12 @@ trait SigmaDslBuilder { */ def decodePoint(encoded: Coll[Byte]): GroupElement + /** Create DSL big integer from existing `java.math.BigInteger`*/ + def BigInt(n: BigInteger): BigInt + + /** Extract `java.math.BigInteger` from DSL's `BigInt` type*/ + def toBigInteger(n: BigInt): BigInteger + /** Construct a new authenticated dictionary with given parameters and tree root digest. */ def avlTree(operationFlags: Byte, digest: Coll[Byte], keyLength: Int, valueLengthOpt: Option[Int]): AvlTree diff --git a/data/shared/src/main/scala/sigma/data/CSigmaDslBuilder.scala b/data/shared/src/main/scala/sigma/data/CSigmaDslBuilder.scala index c806d4a8c5..3938feacd3 100644 --- a/data/shared/src/main/scala/sigma/data/CSigmaDslBuilder.scala +++ b/data/shared/src/main/scala/sigma/data/CSigmaDslBuilder.scala @@ -24,6 +24,10 @@ class CSigmaDslBuilder extends SigmaDslBuilder { dsl => override val Colls: CollBuilder = sigma.Colls + override def BigInt(n: BigInteger): BigInt = CBigInt(n) + + override def toBigInteger(n: BigInt): BigInteger = n.asInstanceOf[CBigInt].wrappedValue + /** Wraps the given elliptic curve point into GroupElement type. */ def GroupElement(p: Ecp): GroupElement = p match { case ept: EcPointType => CGroupElement(ept) diff --git a/sc/shared/src/main/scala/sigmastate/eval/GraphBuilding.scala b/sc/shared/src/main/scala/sigmastate/eval/GraphBuilding.scala index ed25b6afa4..5ddcdfa946 100644 --- a/sc/shared/src/main/scala/sigmastate/eval/GraphBuilding.scala +++ b/sc/shared/src/main/scala/sigmastate/eval/GraphBuilding.scala @@ -52,10 +52,6 @@ trait GraphBuilding extends SigmaLibrary { IR: IRContext => this.keepOriginalFunc = false // original lambda of Lambda node contains invocations of evalNode and we don't want that this.useAlphaEquality = false - /** Whether to create CostOf nodes or substutute costs from CostTable as constants in the graph. - * true - substitute; false - create CostOf nodes */ - var substFromCostTable: Boolean = true - /** Whether to save calcF and costF graphs in the file given by ScriptNameProp environment variable */ var saveGraphsInFile: Boolean = false diff --git a/sc/shared/src/test/scala/sigmastate/TestingInterpreterSpecification.scala b/sc/shared/src/test/scala/sigmastate/TestingInterpreterSpecification.scala index fe5a678679..66c7099436 100644 --- a/sc/shared/src/test/scala/sigmastate/TestingInterpreterSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/TestingInterpreterSpecification.scala @@ -24,13 +24,9 @@ class TestingInterpreterSpecification extends CompilerTestingCommons with CompilerCrossVersionProps with BeforeAndAfterAll { implicit lazy val IR: TestingIRContext = new TestingIRContext - lazy val prover = new ErgoLikeTestProvingInterpreter() { - } - - lazy val verifier = new ErgoLikeTestInterpreter { - } + lazy val prover = new ErgoLikeTestProvingInterpreter() - implicit val soundness: Int = CryptoConstants.soundnessBits + lazy val verifier = new ErgoLikeTestInterpreter def testingContext(h: Int) = ErgoLikeContextTesting(h, From e0795c54565be916a9bbe84c4200abb699d547df Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Sat, 27 Apr 2024 22:01:06 +0300 Subject: [PATCH 040/314] implicits removed #1 --- .../src/main/scala/special/sigma/impl/SigmaDslImpl.scala | 2 -- sc/shared/src/test/scala/sigma/SigmaDslTesting.scala | 4 ++-- .../test/scala/sigmastate/SoftForkabilitySpecification.scala | 4 ++-- .../scala/sigmastate/TestingInterpreterSpecification.scala | 5 +++-- 4 files changed, 7 insertions(+), 8 deletions(-) diff --git a/sc/shared/src/main/scala/special/sigma/impl/SigmaDslImpl.scala b/sc/shared/src/main/scala/special/sigma/impl/SigmaDslImpl.scala index 929d81460d..70fb35c329 100644 --- a/sc/shared/src/main/scala/special/sigma/impl/SigmaDslImpl.scala +++ b/sc/shared/src/main/scala/special/sigma/impl/SigmaDslImpl.scala @@ -1915,7 +1915,6 @@ object SigmaDslBuilder extends EntityObject("SigmaDslBuilder") { } override def substConstants[T](scriptBytes: Ref[Coll[Byte]], positions: Ref[Coll[Int]], newValues: Ref[Coll[T]]): Ref[Coll[Byte]] = { - implicit val eT = newValues.eA asRep[Coll[Byte]](mkMethodCall(self, SigmaDslBuilderClass.getMethod("substConstants", classOf[Sym], classOf[Sym], classOf[Sym]), Array[AnyRef](scriptBytes, positions, newValues), @@ -2075,7 +2074,6 @@ object SigmaDslBuilder extends EntityObject("SigmaDslBuilder") { } def substConstants[T](scriptBytes: Ref[Coll[Byte]], positions: Ref[Coll[Int]], newValues: Ref[Coll[T]]): Ref[Coll[Byte]] = { - implicit val eT = newValues.eA asRep[Coll[Byte]](mkMethodCall(source, SigmaDslBuilderClass.getMethod("substConstants", classOf[Sym], classOf[Sym], classOf[Sym]), Array[AnyRef](scriptBytes, positions, newValues), diff --git a/sc/shared/src/test/scala/sigma/SigmaDslTesting.scala b/sc/shared/src/test/scala/sigma/SigmaDslTesting.scala index 46222d9fb1..cd99f5498c 100644 --- a/sc/shared/src/test/scala/sigma/SigmaDslTesting.scala +++ b/sc/shared/src/test/scala/sigma/SigmaDslTesting.scala @@ -1152,8 +1152,8 @@ class SigmaDslTesting extends AnyPropSpec (cases: Seq[A], f: Feature[A, B], nIters: Int, formatter: MeasureFormatter[A]) (implicit IR: IRContext, evalSettings: EvalSettings): Seq[Long] = { val fNew = f.newF - implicit val tA = fNew.tA - implicit val tB = fNew.tB + val tA = fNew.tA + val tB = fNew.tB implicit val cs = defaultCompilerSettings val func = funcJit[A, B](f.script) val noTraceSettings = evalSettings.copy( diff --git a/sc/shared/src/test/scala/sigmastate/SoftForkabilitySpecification.scala b/sc/shared/src/test/scala/sigmastate/SoftForkabilitySpecification.scala index bca2d0e638..c8b9f06399 100644 --- a/sc/shared/src/test/scala/sigmastate/SoftForkabilitySpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/SoftForkabilitySpecification.scala @@ -29,7 +29,7 @@ class SoftForkabilitySpecification extends SigmaTestingData with CompilerTestingCommons with BeforeAndAfterAll { - implicit lazy val IR: TestingIRContext = new TestingIRContext + val IR: TestingIRContext = new TestingIRContext lazy val prover = new ErgoLikeTestProvingInterpreter() lazy val verifier = new ErgoLikeTestInterpreter val deadline = 100 @@ -38,7 +38,7 @@ class SoftForkabilitySpecification extends SigmaTestingData lazy val booleanPropV1 = compile(emptyEnv + ("deadline" -> deadline), """{ | HEIGHT > deadline && OUTPUTS.size == 1 - |}""".stripMargin).asBoolValue + |}""".stripMargin)(IR).asBoolValue // cast Boolean typed prop to SigmaProp (which is invalid) // ErgoTree v0 lazy val invalidPropV1: ErgoTree = diff --git a/sc/shared/src/test/scala/sigmastate/TestingInterpreterSpecification.scala b/sc/shared/src/test/scala/sigmastate/TestingInterpreterSpecification.scala index 66c7099436..446f1972a7 100644 --- a/sc/shared/src/test/scala/sigmastate/TestingInterpreterSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/TestingInterpreterSpecification.scala @@ -22,7 +22,8 @@ import scala.util.Random class TestingInterpreterSpecification extends CompilerTestingCommons with CompilerCrossVersionProps with BeforeAndAfterAll { - implicit lazy val IR: TestingIRContext = new TestingIRContext + + val IR: TestingIRContext = new TestingIRContext lazy val prover = new ErgoLikeTestProvingInterpreter() @@ -124,7 +125,7 @@ class TestingInterpreterSpecification extends CompilerTestingCommons "box1" -> testBox(10, TrueTree, 0, Seq(), Map( reg1 -> IntArrayConstant(Array[Int](1, 2, 3)), reg2 -> BoolArrayConstant(Array[Boolean](true, false, true))))) - val prop = mkTestErgoTree(compile(env, code).asBoolValue.toSigmaProp) + val prop = mkTestErgoTree(compile(env, code)(IR).asBoolValue.toSigmaProp) val challenge = Array.fill(32)(Random.nextInt(100).toByte) val proof1 = prover.prove(prop, ctx, challenge).get.proof verifier.verify(Interpreter.emptyEnv, prop, ctx, proof1, challenge) From 7f01f11403b9807558f80e25cfb704cf2a9a1280 Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Sun, 28 Apr 2024 02:01:10 +0300 Subject: [PATCH 041/314] rolling back implicits in benchmarkCases --- sc/shared/src/test/scala/sigma/SigmaDslTesting.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sc/shared/src/test/scala/sigma/SigmaDslTesting.scala b/sc/shared/src/test/scala/sigma/SigmaDslTesting.scala index cd99f5498c..46222d9fb1 100644 --- a/sc/shared/src/test/scala/sigma/SigmaDslTesting.scala +++ b/sc/shared/src/test/scala/sigma/SigmaDslTesting.scala @@ -1152,8 +1152,8 @@ class SigmaDslTesting extends AnyPropSpec (cases: Seq[A], f: Feature[A, B], nIters: Int, formatter: MeasureFormatter[A]) (implicit IR: IRContext, evalSettings: EvalSettings): Seq[Long] = { val fNew = f.newF - val tA = fNew.tA - val tB = fNew.tB + implicit val tA = fNew.tA + implicit val tB = fNew.tB implicit val cs = defaultCompilerSettings val func = funcJit[A, B](f.script) val noTraceSettings = evalSettings.copy( From 691c5eecccd3ae5a9a519b7e1b9fb143ef3e7ac8 Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Sun, 28 Apr 2024 02:13:13 +0300 Subject: [PATCH 042/314] CoreArrayByteOps removed --- core/js/src/main/scala/sigma/js/GroupElement.scala | 4 ++-- core/shared/src/main/scala/sigma/Environment.scala | 2 +- core/shared/src/main/scala/sigma/Extensions.scala | 5 ----- 3 files changed, 3 insertions(+), 8 deletions(-) diff --git a/core/js/src/main/scala/sigma/js/GroupElement.scala b/core/js/src/main/scala/sigma/js/GroupElement.scala index 21b53b265d..82d8d462d6 100644 --- a/core/js/src/main/scala/sigma/js/GroupElement.scala +++ b/core/js/src/main/scala/sigma/js/GroupElement.scala @@ -1,6 +1,6 @@ package sigma.js -import sigma.Extensions.CoreArrayByteOps +import scorex.util.encode.Base16 import sigma.crypto.{CryptoFacade, CryptoFacadeJs, Ecp, Platform} import scala.scalajs.js @@ -13,7 +13,7 @@ class GroupElement(val point: Ecp) extends js.Object { * @see CryptoFacade.getASN1Encoding */ def toPointHex(): String = { - CryptoFacade.getASN1Encoding(point, true).toHex + Base16.encode(CryptoFacade.getASN1Encoding(point, true)) } } diff --git a/core/shared/src/main/scala/sigma/Environment.scala b/core/shared/src/main/scala/sigma/Environment.scala index 959e02c1fb..432c40110c 100644 --- a/core/shared/src/main/scala/sigma/Environment.scala +++ b/core/shared/src/main/scala/sigma/Environment.scala @@ -14,7 +14,7 @@ sealed abstract class Environment { object Environment { /** Current runtime environment. */ - implicit val current: Environment = new Environment { + val current: Environment = new Environment { override def isJVM: Boolean = runtimePlatform == RuntimePlatform.JVM override def isJS: Boolean = runtimePlatform == RuntimePlatform.JS override def runtimePlatform: RuntimePlatform = sigma.reflection.Platform.runtimePlatform diff --git a/core/shared/src/main/scala/sigma/Extensions.scala b/core/shared/src/main/scala/sigma/Extensions.scala index 81976a3c12..0c79df94ea 100644 --- a/core/shared/src/main/scala/sigma/Extensions.scala +++ b/core/shared/src/main/scala/sigma/Extensions.scala @@ -9,11 +9,6 @@ import sigma.data.RType * See `implicit class ...` wrappers below. */ object Extensions { - /** Extension methods for `Array[Byte]` not available for generic `Array[T]`. */ - implicit class CoreArrayByteOps(val arr: Array[Byte]) extends AnyVal { - /** Encodes array into hex string */ - @inline def toHex: String = Base16.encode(arr) - } /** Extension methods for `Array[T]` where implicit descriptor `RType[T]` is also * required. From a8e1acff73cb9ad6cd6b2b065c85af333c2adc21 Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Mon, 29 Apr 2024 23:21:24 +0300 Subject: [PATCH 043/314] checkPow test in TestingInterpreterSpecification --- .../serialization/CoreDataSerializer.scala | 3 +- .../src/main/scala/sigma/ast/methods.scala | 2 +- .../TestingInterpreterSpecification.scala | 102 ++++++++++++++++-- 3 files changed, 95 insertions(+), 12 deletions(-) diff --git a/core/shared/src/main/scala/sigma/serialization/CoreDataSerializer.scala b/core/shared/src/main/scala/sigma/serialization/CoreDataSerializer.scala index 479b199da5..56872cd68e 100644 --- a/core/shared/src/main/scala/sigma/serialization/CoreDataSerializer.scala +++ b/core/shared/src/main/scala/sigma/serialization/CoreDataSerializer.scala @@ -68,7 +68,8 @@ class CoreDataSerializer { i += 1 } - // TODO v6.0 (3h): support Option[T] (see https://github.com/ScorexFoundation/sigmastate-interpreter/issues/659) + // TODO v6.0 : support Option[T] (see https://github.com/ScorexFoundation/sigmastate-interpreter/issues/659) + // TODO v6.0 : support Header case _ => CheckSerializableTypeCode(tpe.typeCode) throw new SerializerException(s"Don't know how to serialize ($v, $tpe)") diff --git a/data/shared/src/main/scala/sigma/ast/methods.scala b/data/shared/src/main/scala/sigma/ast/methods.scala index a8c6545a53..ca4501967f 100644 --- a/data/shared/src/main/scala/sigma/ast/methods.scala +++ b/data/shared/src/main/scala/sigma/ast/methods.scala @@ -1459,7 +1459,7 @@ case object SHeaderMethods extends MonoTypeMethods { lazy val votesMethod = propertyCall("votes", SByteArray, 15, FixedCost(JitCost(10))) lazy val checkPowMethod = SMethod( - this, "checkPow", SFunc(Array(SHeader), SBoolean), 3, GroupGenerator.costKind) // todo: cost + this, "checkPow", SFunc(Array(SHeader), SBoolean), 16, GroupGenerator.costKind) // todo: cost .withIRInfo(MethodCallIrBuilder) .withInfo(Xor, "Byte-wise XOR of two collections of bytes") // todo: desc diff --git a/sc/shared/src/test/scala/sigmastate/TestingInterpreterSpecification.scala b/sc/shared/src/test/scala/sigmastate/TestingInterpreterSpecification.scala index fe5a678679..387efe7b1c 100644 --- a/sc/shared/src/test/scala/sigmastate/TestingInterpreterSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/TestingInterpreterSpecification.scala @@ -6,17 +6,26 @@ import sigma.ast._ import sigma.ast.syntax._ import sigmastate.interpreter._ import Interpreter._ +import io.circe.parser.parse import sigma.ast.syntax._ import org.ergoplatform._ +import org.ergoplatform.sdk.JsonCodecs import org.scalatest.BeforeAndAfterAll import scorex.util.encode.Base58 +import sigma.Colls +import sigma.VersionContext.V6SoftForkVersion import sigma.crypto.CryptoConstants -import sigma.data.{AvlTreeData, CAND, ProveDlog, SigmaBoolean, TrivialProp} +import sigma.data.{AvlTreeData, CAND, CAvlTree, ProveDlog, SigmaBoolean, TrivialProp} +import sigma.interpreter.ContextExtension import sigma.util.Extensions.IntOps import sigmastate.helpers.{CompilerTestingCommons, ErgoLikeContextTesting, ErgoLikeTestInterpreter, ErgoLikeTestProvingInterpreter} import sigmastate.helpers.TestingHelpers._ -import sigma.serialization.ValueSerializer +import sigma.serialization.{GroupElementSerializer, SigmaSerializer, ValueSerializer} +import sigmastate.eval.CPreHeader +import sigmastate.helpers.ErgoLikeContextTesting.{dummyPreHeader, noBoxes, noHeaders} +import sigmastate.interpreter.CErgoTreeEvaluator.DefaultEvalSettings import sigmastate.utils.Helpers._ +import sigma.util.Extensions._ import scala.util.Random @@ -32,12 +41,60 @@ class TestingInterpreterSpecification extends CompilerTestingCommons implicit val soundness: Int = CryptoConstants.soundnessBits - def testingContext(h: Int) = - ErgoLikeContextTesting(h, - AvlTreeData.dummy, ErgoLikeContextTesting.dummyPubkey, IndexedSeq(fakeSelf), - ErgoLikeTransaction(IndexedSeq.empty, IndexedSeq.empty), - fakeSelf, activatedVersionInTests) - .withErgoTreeVersion(ergoTreeVersionInTests) + def testingContext(h: Int = 614401) = { + + // valid header from Ergo blockchain + val headerJson = + """ + |{ + | "extensionId" : "00cce45975d87414e8bdd8146bc88815be59cd9fe37a125b5021101e05675a18", + | "votes" : "000000", + | "timestamp" : 4928911477310178288, + | "size" : 223, + | "unparsedBytes" : "", + | "stateRoot" : { + | "digest" : "5c8c00b8403d3701557181c8df800001b6d5009e2201c6ff807d71808c00019780", + | "treeFlags" : "0", + | "keyLength" : "32" + | }, + | "height" : 614400, + | "nBits" : 37748736, + | "version" : 2, + | "id" : "5603a937ec1988220fc44fb5022fb82d5565b961f005ebb55d85bd5a9e6f801f", + | "adProofsRoot" : "5d3f80dcff7f5e7f59007294c180808d0158d1ff6ba10000f901c7f0ef87dcff", + | "transactionsRoot" : "f17fffacb6ff7f7f1180d2ff7f1e24ffffe1ff937f807f0797b9ff6ebdae007e", + | "extensionRoot" : "1480887f80007f4b01cf7f013ff1ffff564a0000b9a54f00770e807f41ff88c0", + | "minerPk" : "03bedaee069ff4829500b3c07c4d5fe6b3ea3d3bf76c5c28c1d4dcdb1bed0ade0c", + | "powOnetimePk" : "0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798", + | "powNonce" : "0000000000003105", + | "powDistance" : 0, + | "adProofsId" : "dec129290a763f4de41f04e87e2b661dd59758af6bdd00dd51f5d97c3a8cb9b5", + | "transactionsId" : "eba1dd82cf51147232e09c1f72b37c554c30f63274d5093bff36849a83472a42", + | "parentId" : "ac2101807f0000ca01ff0119db227f202201007f62000177a080005d440896d0" + |} + |""".stripMargin + + object JsonCodecs extends JsonCodecs + val header1 = JsonCodecs.headerDecoder.decodeJson(parse(headerJson).toOption.get).toOption.get + + val boxesToSpend = IndexedSeq(fakeSelf) + + val preHeader = CPreHeader(activatedVersionInTests, + parentId = header1.id, + timestamp = 3, + nBits = 0, + height = h, + minerPk = GroupElementSerializer.parse(SigmaSerializer.startReader(ErgoLikeContextTesting.dummyPubkey)).toGroupElement, + votes = Colls.emptyColl[Byte] + ) + + new ErgoLikeContext( + header1.stateRoot.asInstanceOf[CAvlTree].treeData, Colls.fromArray(Array(header1)), + preHeader, noBoxes, + boxesToSpend, ErgoLikeTransaction(IndexedSeq.empty, IndexedSeq.empty), + boxesToSpend.indexOf(fakeSelf), ContextExtension.empty, vs, DefaultEvalSettings.scriptCostLimitInEvaluator, + initCost = 0L, activatedVersionInTests).withErgoTreeVersion(ergoTreeVersionInTests) + } property("Reduction to crypto #1") { forAll() { i: Int => @@ -119,7 +176,7 @@ class TestingInterpreterSpecification extends CompilerTestingCommons val dk1 = prover.dlogSecrets(0).publicImage val dk2 = prover.dlogSecrets(1).publicImage - val ctx = testingContext(99) + val ctx = testingContext() val env = Map( "dk1" -> dk1, "dk2" -> dk2, @@ -127,7 +184,9 @@ class TestingInterpreterSpecification extends CompilerTestingCommons "bytes2" -> Array[Byte](4, 5, 6), "box1" -> testBox(10, TrueTree, 0, Seq(), Map( reg1 -> IntArrayConstant(Array[Int](1, 2, 3)), - reg2 -> BoolArrayConstant(Array[Boolean](true, false, true))))) + reg2 -> BoolArrayConstant(Array[Boolean](true, false, true)) + )) + ) val prop = mkTestErgoTree(compile(env, code).asBoolValue.toSigmaProp) val challenge = Array.fill(32)(Random.nextInt(100).toByte) val proof1 = prover.prove(prop, ctx, challenge).get.proof @@ -374,6 +433,29 @@ class TestingInterpreterSpecification extends CompilerTestingCommons testEval(s"""deserialize[Coll[Byte]]("$str")(0) == 2""") } + property("header.id") { + testEval( + """ { + | val h = CONTEXT.headers(0) + | val id = h.id + | id.size == 32 + | }""".stripMargin) + } + + property("checkPow") { + val source = """ { + | val h = CONTEXT.headers(0) + | h.checkPow + | } + | """.stripMargin + + if (activatedVersionInTests < V6SoftForkVersion) { + an [sigmastate.exceptions.MethodNotFound] should be thrownBy testEval(source) + } else { + testEval(source) + } + } + override protected def afterAll(): Unit = { } From 69278ee1db2ac2af6bdf8693b271b8d3ec5360c9 Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Wed, 1 May 2024 12:45:51 +0300 Subject: [PATCH 044/314] MethodCall deserialization round trip for Header.checkPow --- .../MethodCallSerializerSpecification.scala | 23 +++++++++++++++++++ .../TestingInterpreterSpecification.scala | 8 ++++--- 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/interpreter/shared/src/test/scala/sigma/serialization/MethodCallSerializerSpecification.scala b/interpreter/shared/src/test/scala/sigma/serialization/MethodCallSerializerSpecification.scala index 1db166c685..c65b86930c 100644 --- a/interpreter/shared/src/test/scala/sigma/serialization/MethodCallSerializerSpecification.scala +++ b/interpreter/shared/src/test/scala/sigma/serialization/MethodCallSerializerSpecification.scala @@ -45,4 +45,27 @@ class MethodCallSerializerSpecification extends SerializationSpecification { } ) } + + property("MethodCall deserialization round trip for Header.checkPow") { + def code = { + val bi = HeaderConstant(headerGen.sample.get) + val expr = MethodCall(bi, + SHeaderMethods.checkPowMethod, + Vector(), + Map() + ) + roundTripTest(expr) + } + + VersionContext.withVersions(VersionContext.V6SoftForkVersion, 1) { + code + } + + an[ValidationException] should be thrownBy ( + VersionContext.withVersions((VersionContext.V6SoftForkVersion - 1).toByte, 1) { + code + } + ) + } + } diff --git a/sc/shared/src/test/scala/sigmastate/TestingInterpreterSpecification.scala b/sc/shared/src/test/scala/sigmastate/TestingInterpreterSpecification.scala index 387efe7b1c..d6bce80a4c 100644 --- a/sc/shared/src/test/scala/sigmastate/TestingInterpreterSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/TestingInterpreterSpecification.scala @@ -7,7 +7,6 @@ import sigma.ast.syntax._ import sigmastate.interpreter._ import Interpreter._ import io.circe.parser.parse -import sigma.ast.syntax._ import org.ergoplatform._ import org.ergoplatform.sdk.JsonCodecs import org.scalatest.BeforeAndAfterAll @@ -15,14 +14,14 @@ import scorex.util.encode.Base58 import sigma.Colls import sigma.VersionContext.V6SoftForkVersion import sigma.crypto.CryptoConstants -import sigma.data.{AvlTreeData, CAND, CAvlTree, ProveDlog, SigmaBoolean, TrivialProp} +import sigma.data.{CAND, CAvlTree, ProveDlog, SigmaBoolean, TrivialProp} import sigma.interpreter.ContextExtension import sigma.util.Extensions.IntOps import sigmastate.helpers.{CompilerTestingCommons, ErgoLikeContextTesting, ErgoLikeTestInterpreter, ErgoLikeTestProvingInterpreter} import sigmastate.helpers.TestingHelpers._ import sigma.serialization.{GroupElementSerializer, SigmaSerializer, ValueSerializer} import sigmastate.eval.CPreHeader -import sigmastate.helpers.ErgoLikeContextTesting.{dummyPreHeader, noBoxes, noHeaders} +import sigmastate.helpers.ErgoLikeContextTesting.noBoxes import sigmastate.interpreter.CErgoTreeEvaluator.DefaultEvalSettings import sigmastate.utils.Helpers._ import sigma.util.Extensions._ @@ -443,6 +442,9 @@ class TestingInterpreterSpecification extends CompilerTestingCommons } property("checkPow") { + + //todo: check invalid header + val source = """ { | val h = CONTEXT.headers(0) | h.checkPow From 72814c0786c5c01b3d6904956d9da5129dfca4c7 Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Wed, 1 May 2024 13:43:29 +0300 Subject: [PATCH 045/314] merging w. develop --- .../main/scala/sigma/js/GroupElement.scala | 4 +- .../src/main/scala/sigma/Environment.scala | 2 +- .../src/main/scala/sigma/Evaluation.scala | 3 +- .../src/main/scala/sigma/Extensions.scala | 11 ++-- .../src/main/scala/sigma/ast/SType.scala | 3 +- .../scala/sigma/data/SigmaPropCodes.scala | 2 +- .../src/main/scala/sigma/data/package.scala | 1 + .../shared/src/main/scala/sigma/package.scala | 7 ++- .../sigma/reflection/ReflectionData.scala | 10 ++- .../sigma/serialization/CoreByteReader.scala | 4 -- .../sigma/serialization/CoreByteWriter.scala | 3 + .../sigma/serialization/CoreSerializer.scala | 12 +++- .../scala/sigma/SigmaDataReflection.scala | 4 ++ .../src/main/scala/sigma/ast/CostItem.scala | 3 - .../src/main/scala/sigma/ast/SMethod.scala | 2 +- .../main/scala/sigma/ast/SigmaPredef.scala | 2 +- .../src/main/scala/sigma/ast/methods.scala | 11 ++-- .../src/main/scala/sigma/ast/syntax.scala | 2 - .../src/main/scala/sigma/ast/trees.scala | 1 - .../serialization/ErgoTreeSerializer.scala | 6 +- .../sigma/serialization/SigmaSerializer.scala | 4 +- .../interpreter/js/SigmaPropProver.scala | 1 - .../org/ergoplatform/ErgoLikeContext.scala | 1 - .../sigmastate/InterpreterReflection.scala | 4 ++ .../scala/sigmastate/crypto/GF2_192.scala | 2 - .../sigmastate/crypto/GF2_192_Poly.scala | 2 - .../main/scala/sigmastate/eval/CContext.scala | 56 ----------------- .../scala/sigmastate/eval/CProfiler.scala | 6 +- .../sigmastate/interpreter/Interpreter.scala | 7 +-- .../sigmastate/interpreter/ProverUtils.scala | 6 +- .../ConstantSerializerSpecification.scala | 2 +- .../DataSerializerSpecification.scala | 1 - .../scala/sigmastate/eval/BasicOpsTests.scala | 7 +-- .../special/sigma/ContractsTestkit.scala | 35 +---------- .../special/sigma/SigmaTestingData.scala | 63 +------------------ .../scala/sigmastate/lang/LangTests.scala | 1 - .../org/ergoplatform/dsl/ContractSyntax.scala | 2 +- .../main/scala/scalan/GraphIRReflection.scala | 4 ++ sc/shared/src/main/scala/scalan/Library.scala | 2 +- .../src/main/scala/scalan/MethodCalls.scala | 24 +------ .../src/main/scala/scalan/meta/SSymName.scala | 7 +-- .../scala/scalan/primitives/Functions.scala | 8 +-- .../main/scala/scalan/primitives/Thunks.scala | 2 +- .../scala/scalan/staged/Transforming.scala | 25 +++----- .../scala/sigmastate/eval/GraphBuilding.scala | 10 +-- .../scala/sigmastate/eval/IRContext.scala | 50 ++------------- .../scala/sigmastate/eval/SigmaLibrary.scala | 2 +- .../scala/sigmastate/eval/TreeBuilding.scala | 6 +- .../scala/sigmastate/lang/SigmaBinder.scala | 1 - .../scala/special/collection/CollsUnit.scala | 5 -- .../special/sigma/impl/SigmaDslImpl.scala | 17 +---- .../src/test/scala/scalan/LibraryTests.scala | 2 +- .../scala/sigma/SigmaDslStaginTests.scala | 4 +- .../sigmastate/ErgoTreeSpecification.scala | 1 - .../SoftForkabilitySpecification.scala | 4 +- .../TestingInterpreterSpecification.scala | 11 ++-- .../sigmastate/eval/ErgoScriptTestkit.scala | 39 ++++++++---- .../sigmastate/eval/EvaluationTest.scala | 18 ------ .../sigmastate/eval/MeasureIRContext.scala | 36 ----------- .../helpers/CompilerTestingCommons.scala | 3 +- .../utxo/BasicOpsSpecification.scala | 4 +- .../org/ergoplatform/sdk/Extensions.scala | 26 -------- .../org/ergoplatform/sdk/ExtensionsSpec.scala | 11 ++-- 63 files changed, 149 insertions(+), 466 deletions(-) delete mode 100644 sc/shared/src/test/scala/sigmastate/eval/MeasureIRContext.scala diff --git a/core/js/src/main/scala/sigma/js/GroupElement.scala b/core/js/src/main/scala/sigma/js/GroupElement.scala index 21b53b265d..82d8d462d6 100644 --- a/core/js/src/main/scala/sigma/js/GroupElement.scala +++ b/core/js/src/main/scala/sigma/js/GroupElement.scala @@ -1,6 +1,6 @@ package sigma.js -import sigma.Extensions.CoreArrayByteOps +import scorex.util.encode.Base16 import sigma.crypto.{CryptoFacade, CryptoFacadeJs, Ecp, Platform} import scala.scalajs.js @@ -13,7 +13,7 @@ class GroupElement(val point: Ecp) extends js.Object { * @see CryptoFacade.getASN1Encoding */ def toPointHex(): String = { - CryptoFacade.getASN1Encoding(point, true).toHex + Base16.encode(CryptoFacade.getASN1Encoding(point, true)) } } diff --git a/core/shared/src/main/scala/sigma/Environment.scala b/core/shared/src/main/scala/sigma/Environment.scala index 959e02c1fb..432c40110c 100644 --- a/core/shared/src/main/scala/sigma/Environment.scala +++ b/core/shared/src/main/scala/sigma/Environment.scala @@ -14,7 +14,7 @@ sealed abstract class Environment { object Environment { /** Current runtime environment. */ - implicit val current: Environment = new Environment { + val current: Environment = new Environment { override def isJVM: Boolean = runtimePlatform == RuntimePlatform.JVM override def isJS: Boolean = runtimePlatform == RuntimePlatform.JS override def runtimePlatform: RuntimePlatform = sigma.reflection.Platform.runtimePlatform diff --git a/core/shared/src/main/scala/sigma/Evaluation.scala b/core/shared/src/main/scala/sigma/Evaluation.scala index 893bdfb9f8..d86b7c1650 100644 --- a/core/shared/src/main/scala/sigma/Evaluation.scala +++ b/core/shared/src/main/scala/sigma/Evaluation.scala @@ -76,8 +76,7 @@ object Evaluation { case HeaderRType => SHeader case PreHeaderRType => SPreHeader case SigmaPropRType => SSigmaProp - // TODO remove commented code below after full sync test - // case SigmaBooleanRType => SSigmaProp // this is not used in consensus code + case SigmaBooleanRType => SSigmaProp // TODO remove: this is not used in consensus code case tup: TupleType => STuple(tup.items.map(t => rtypeToSType(t))) case at: ArrayType[_] => SCollection(rtypeToSType(at.tA)) case ct: CollType[_] => SCollection(rtypeToSType(ct.tItem)) diff --git a/core/shared/src/main/scala/sigma/Extensions.scala b/core/shared/src/main/scala/sigma/Extensions.scala index 865d488803..0c79df94ea 100644 --- a/core/shared/src/main/scala/sigma/Extensions.scala +++ b/core/shared/src/main/scala/sigma/Extensions.scala @@ -5,13 +5,14 @@ import scorex.util.encode.Base16 import scorex.util.{ModifierId, bytesToId} import sigma.data.RType +/** Declaration of extension methods introduced in `sigma-core` module. + * See `implicit class ...` wrappers below. + */ object Extensions { - /** Extension methods for `Array[Byte]` not available for generic `Array[T]`. */ - implicit class CoreArrayByteOps(val arr: Array[Byte]) extends AnyVal { - /** Encodes array into hex string */ - @inline def toHex: String = Base16.encode(arr) - } + /** Extension methods for `Array[T]` where implicit descriptor `RType[T]` is also + * required. + */ implicit class ArrayOps[T: RType](arr: Array[T]) { /** Wraps array into Coll instance. The source array in not cloned. */ @inline def toColl: Coll[T] = Colls.fromArray(arr) diff --git a/core/shared/src/main/scala/sigma/ast/SType.scala b/core/shared/src/main/scala/sigma/ast/SType.scala index e9ea0d43f0..f75cbc9e8b 100644 --- a/core/shared/src/main/scala/sigma/ast/SType.scala +++ b/core/shared/src/main/scala/sigma/ast/SType.scala @@ -94,7 +94,6 @@ object SType { val paramOV = STypeParam(tOV) val paramIVSeq: Seq[STypeParam] = Array(paramIV) - val IndexedSeqOfT1: IndexedSeq[SType] = Array(SType.tT) val IndexedSeqOfT2: IndexedSeq[SType] = Array(SType.tT, SType.tT) /** Immutable empty array, can be used to avoid repeated allocations. */ @@ -146,7 +145,7 @@ object SType { * 2) `isValueOfType == true` for each tree leaf * 3) `isValueOfType == true` for each sub-expression * - * @param value value to check type + * @param x value to check type * @param tpe type descriptor to check value against * @return true if the given `value` is of type tpe` */ diff --git a/core/shared/src/main/scala/sigma/data/SigmaPropCodes.scala b/core/shared/src/main/scala/sigma/data/SigmaPropCodes.scala index 17257c9ce5..fafd24ffdd 100644 --- a/core/shared/src/main/scala/sigma/data/SigmaPropCodes.scala +++ b/core/shared/src/main/scala/sigma/data/SigmaPropCodes.scala @@ -3,7 +3,7 @@ package sigma.data import sigma.ast.TypeCodes.LastConstantCode import supertagged.TaggedType -/** Encoding of sigma proposition nodes. +/** Opcodes of sigma proposition nodes. * * @see SigmaBoolean.opCode */ diff --git a/core/shared/src/main/scala/sigma/data/package.scala b/core/shared/src/main/scala/sigma/data/package.scala index a0fb219af8..c5a35f7b5f 100644 --- a/core/shared/src/main/scala/sigma/data/package.scala +++ b/core/shared/src/main/scala/sigma/data/package.scala @@ -16,6 +16,7 @@ package object data { val BigIntClassTag = classTag[BigInt] val GroupElementClassTag = classTag[GroupElement] val SigmaPropClassTag = classTag[SigmaProp] + val SigmaBooleanClassTag = classTag[SigmaBoolean] val AvlTreeClassTag = classTag[AvlTree] val BoxClassTag = classTag[Box] val ContextClassTag = classTag[Context] diff --git a/core/shared/src/main/scala/sigma/package.scala b/core/shared/src/main/scala/sigma/package.scala index 67560b462c..89b883f52d 100644 --- a/core/shared/src/main/scala/sigma/package.scala +++ b/core/shared/src/main/scala/sigma/package.scala @@ -25,9 +25,12 @@ package object sigma { implicit val StringType : RType[String] = GeneralType(StringClassTag) - implicit val BigIntRType: RType[BigInt] = GeneralType(BigIntClassTag) + implicit val BigIntRType : RType[BigInt] = GeneralType(BigIntClassTag) implicit val GroupElementRType: RType[GroupElement] = GeneralType(GroupElementClassTag) - implicit val SigmaPropRType: RType[SigmaProp] = GeneralType(SigmaPropClassTag) + implicit val SigmaPropRType : RType[SigmaProp] = GeneralType(SigmaPropClassTag) + implicit val SigmaBooleanRType: RType[SigmaBoolean] = GeneralType(SigmaBooleanClassTag) + + implicit val AvlTreeRType: RType[AvlTree] = GeneralType(AvlTreeClassTag) implicit val BoxRType: RType[Box] = GeneralType(BoxClassTag) diff --git a/core/shared/src/main/scala/sigma/reflection/ReflectionData.scala b/core/shared/src/main/scala/sigma/reflection/ReflectionData.scala index 2aac1a5670..028e68bf72 100644 --- a/core/shared/src/main/scala/sigma/reflection/ReflectionData.scala +++ b/core/shared/src/main/scala/sigma/reflection/ReflectionData.scala @@ -9,9 +9,15 @@ import scala.collection.mutable import scala.collection.immutable /** Reflection metadata and global dictionaries to access it. - * For each class of this module that needs reflection metadata, - * we register a class entry with the necessary information. + * Such metadata is only used on JS platform to support reflection-like interfaces of + * RClass, RMethod, RConstructor. These interfaces implemented on JVM using Java + * reflection. + * + * For each class that needs reflection metadata, we register a class entry using + * `registerClassEntry` method with the necessary information such as constructors and + * methods. * Only information that is needed at runtime is registered. + * @see mkConstructor, mkMethod */ object ReflectionData { /** Descriptors of classes. */ diff --git a/core/shared/src/main/scala/sigma/serialization/CoreByteReader.scala b/core/shared/src/main/scala/sigma/serialization/CoreByteReader.scala index 34ed74ac6a..e238829b6c 100644 --- a/core/shared/src/main/scala/sigma/serialization/CoreByteReader.scala +++ b/core/shared/src/main/scala/sigma/serialization/CoreByteReader.scala @@ -10,10 +10,6 @@ import sigma.validation.ValidationRules.CheckPositionLimit * methods. * * @param r the underlying reader this reader reads from - * @param constantStore the store of constants which is used to resolve - * [[sigma.ast.ConstantPlaceholder]] - * @param resolvePlaceholdersToConstants if true then resolved constants will be - * substituted in the tree instead of the placeholder. * @param maxTreeDepth limit on the tree depth (recursive invocations) * of the deserializer */ diff --git a/core/shared/src/main/scala/sigma/serialization/CoreByteWriter.scala b/core/shared/src/main/scala/sigma/serialization/CoreByteWriter.scala index d6cc9a8d8e..aa4255449c 100644 --- a/core/shared/src/main/scala/sigma/serialization/CoreByteWriter.scala +++ b/core/shared/src/main/scala/sigma/serialization/CoreByteWriter.scala @@ -5,6 +5,9 @@ import scorex.util.serialization.{VLQByteBufferWriter, Writer} import sigma.ast.SType import sigma.serialization.CoreByteWriter.{Bits, DataInfo, U, Vlq, ZigZag} +/** Implementation of [[Writer]] provided by `sigma-core` module. + * @param w destination [[Writer]] to which all the call got delegated. + */ class CoreByteWriter(val w: Writer) extends Writer { type CH = w.CH diff --git a/core/shared/src/main/scala/sigma/serialization/CoreSerializer.scala b/core/shared/src/main/scala/sigma/serialization/CoreSerializer.scala index aec82eb9df..938d3f22c1 100644 --- a/core/shared/src/main/scala/sigma/serialization/CoreSerializer.scala +++ b/core/shared/src/main/scala/sigma/serialization/CoreSerializer.scala @@ -6,25 +6,31 @@ import sigma.data.SigmaConstants import java.nio.ByteBuffer +/** Implementation of [[Serializer]] provided by `sigma-core` module. */ abstract class CoreSerializer[TFamily, T <: TFamily] extends Serializer[TFamily, T, CoreByteReader, CoreByteWriter] { - def error(msg: String) = throw new SerializerException(msg, None) + def error(msg: String) = throw SerializerException(msg, None) + /** Serializes the given 'obj' to a new array of bytes using this serializer. */ final def toBytes(obj: T): Array[Byte] = { val w = CoreSerializer.startWriter() serialize(obj, w) w.toBytes } + /** Deserializes `bytes` to an object of this [[TFamily]] using this serializer. + * The actual class of the returned object is expected to be descendant of [[TFamily]]. + */ final def fromBytes(bytes: Array[Byte]): TFamily = { parse(CoreSerializer.startReader(bytes)) } } object CoreSerializer { - type Position = Int - + /** Max length of Box.propositionBytes collection */ val MaxPropositionSize: Int = SigmaConstants.MaxPropositionBytes.value + + /** Max tree depth should not be greater then provided value */ val MaxTreeDepth: Int = SigmaConstants.MaxTreeDepth.value /** Helper function to be use in serializers. diff --git a/data/shared/src/main/scala/sigma/SigmaDataReflection.scala b/data/shared/src/main/scala/sigma/SigmaDataReflection.scala index 31703b0856..48939b1460 100644 --- a/data/shared/src/main/scala/sigma/SigmaDataReflection.scala +++ b/data/shared/src/main/scala/sigma/SigmaDataReflection.scala @@ -11,6 +11,10 @@ import sigma.reflection.{ReflectionData, mkConstructor, mkMethod} import sigma.serialization.ValueCodes.OpCode /** Reflection metadata for `interpreter` module. + * Such metadata is only used on JS platform to support reflection-like interfaces of + * RClass, RMethod, RConstructor. These interfaces implemented on JVM using Java + * reflection. + * * For each class of this module that needs reflection metadata, * we register a class entry with the necessary information. * Only information that is needed at runtime is registered. diff --git a/data/shared/src/main/scala/sigma/ast/CostItem.scala b/data/shared/src/main/scala/sigma/ast/CostItem.scala index 8fa973b575..c69c81daa3 100644 --- a/data/shared/src/main/scala/sigma/ast/CostItem.scala +++ b/data/shared/src/main/scala/sigma/ast/CostItem.scala @@ -1,8 +1,5 @@ package sigma.ast -import sigma.ast -import sigma.eval.CostDetails - /** An item in the cost accumulation trace of a [[sigma.ast.ErgoTree]] evaluation. */ abstract class CostItem { def opName: String diff --git a/data/shared/src/main/scala/sigma/ast/SMethod.scala b/data/shared/src/main/scala/sigma/ast/SMethod.scala index 2d306d8948..669625ef1e 100644 --- a/data/shared/src/main/scala/sigma/ast/SMethod.scala +++ b/data/shared/src/main/scala/sigma/ast/SMethod.scala @@ -105,7 +105,7 @@ case class SMethod( /** Invoke this method on the given object with the arguments. * This is used for methods with FixedCost costKind. */ - def invokeFixed(obj: Any, args: Array[Any])(implicit E: ErgoTreeEvaluator): Any = { + def invokeFixed(obj: Any, args: Array[Any]): Any = { javaMethod.invoke(obj, args.asInstanceOf[Array[AnyRef]]:_*) } diff --git a/data/shared/src/main/scala/sigma/ast/SigmaPredef.scala b/data/shared/src/main/scala/sigma/ast/SigmaPredef.scala index 5cdbdedaa8..c4bc32e4a5 100644 --- a/data/shared/src/main/scala/sigma/ast/SigmaPredef.scala +++ b/data/shared/src/main/scala/sigma/ast/SigmaPredef.scala @@ -591,7 +591,7 @@ object SigmaPredef { ).map(f => f.name -> f).toMap private val funcNameToIrBuilderMap: Map[String, PredefinedFunc] = - funcs.filter { case (n, f) => f.irInfo.irBuilder != undefined } + funcs.filter { case (_, f) => f.irInfo.irBuilder != undefined } def irBuilderForFunc(name: String): Option[IrBuilderFunc] = funcNameToIrBuilderMap.get(name).map(_.irInfo.irBuilder) } diff --git a/data/shared/src/main/scala/sigma/ast/methods.scala b/data/shared/src/main/scala/sigma/ast/methods.scala index c6b71cd120..e4cf0007e0 100644 --- a/data/shared/src/main/scala/sigma/ast/methods.scala +++ b/data/shared/src/main/scala/sigma/ast/methods.scala @@ -2,7 +2,7 @@ package sigma.ast import org.ergoplatform._ import org.ergoplatform.validation._ -import sigma.{VersionContext, _} +import sigma._ import sigma.ast.SCollection.{SBooleanArray, SBoxArray, SByteArray, SByteArray2, SHeaderArray} import sigma.ast.SMethod.{MethodCallIrBuilder, MethodCostFunc, javaMethodOf} import sigma.ast.SType.TypeCode @@ -15,7 +15,6 @@ import sigma.serialization.CoreByteWriter.ArgInfo import sigma.utils.SparseArrayContainer import scala.annotation.unused -import scala.language.implicitConversions /** Base type for all companions of AST nodes of sigma lang. */ trait SigmaNodeCompanion @@ -235,7 +234,7 @@ object SNumericTypeMethods extends MethodsContainer { | Each boolean corresponds to one bit. """.stripMargin) - protected override def getMethods: Seq[SMethod] = Array( + protected override def getMethods(): Seq[SMethod] = Array( ToByteMethod, // see Downcast ToShortMethod, // see Downcast ToIntMethod, // see Downcast @@ -740,7 +739,7 @@ object SCollectionMethods extends MethodsContainer with MethodByNameUnapply { * of flatMap. Other bodies are rejected with throwing exception. */ val flatMap_BodyPatterns = Array[PartialFunction[SValue, Int]]( - { case MethodCall(ValUse(id, tpe), m, args, _) if args.isEmpty => id }, + { case MethodCall(ValUse(id, _), _, args, _) if args.isEmpty => id }, { case ExtractScriptBytes(ValUse(id, _)) => id }, { case ExtractId(ValUse(id, _)) => id }, { case SigmaPropBytes(ValUse(id, _)) => id }, @@ -786,7 +785,7 @@ object SCollectionMethods extends MethodsContainer with MethodByNameUnapply { var res: Nullable[(Int, SValue)] = Nullable.None E.addFixedCost(MatchSingleArgMethodCall_Info) { res = mc match { - case MethodCall(_, m, Seq(FuncValue(args, body)), _) if args.length == 1 => + case MethodCall(_, _, Seq(FuncValue(args, body)), _) if args.length == 1 => val id = args(0)._1 Nullable((id, body)) case _ => @@ -1500,7 +1499,7 @@ case object SGlobalMethods extends MonoTypeMethods { lazy val groupGeneratorMethod = SMethod( this, "groupGenerator", SFunc(SGlobal, SGroupElement), 1, GroupGenerator.costKind) - .withIRInfo({ case (builder, obj, method, args, tparamSubst) => GroupGenerator }) + .withIRInfo({ case (_, _, _, _, _) => GroupGenerator }) .withInfo(GroupGenerator, "") lazy val xorMethod = SMethod( diff --git a/data/shared/src/main/scala/sigma/ast/syntax.scala b/data/shared/src/main/scala/sigma/ast/syntax.scala index d75c71a779..5a257481cb 100644 --- a/data/shared/src/main/scala/sigma/ast/syntax.scala +++ b/data/shared/src/main/scala/sigma/ast/syntax.scala @@ -118,8 +118,6 @@ object syntax { @nowarn private def rtypeToClassTag = ??? /** RType descriptors for predefined types used in AOTC-based interpreter. */ - implicit val SigmaBooleanRType: RType[SigmaBoolean] = RType.fromClassTag(classTag[SigmaBoolean]) - implicit val ErgoBoxRType: RType[ErgoBox] = RType.fromClassTag(classTag[ErgoBox]) implicit val ErgoBoxCandidateRType: RType[ErgoBoxCandidate] = RType.fromClassTag(classTag[ErgoBoxCandidate]) diff --git a/data/shared/src/main/scala/sigma/ast/trees.scala b/data/shared/src/main/scala/sigma/ast/trees.scala index 38d4565f30..39e666a389 100644 --- a/data/shared/src/main/scala/sigma/ast/trees.scala +++ b/data/shared/src/main/scala/sigma/ast/trees.scala @@ -295,7 +295,6 @@ object AND extends LogicalTransformerCompanion { def apply(children: Seq[Value[SBoolean.type]]): AND = AND(ConcreteCollection.fromSeq(children)) -// def apply(head: Value[SBoolean.type], tail: Value[SBoolean.type]*): AND = apply(head +: tail) def apply(items: Value[SBoolean.type]*)(implicit o1: Overloaded1): AND = apply(items) } diff --git a/data/shared/src/main/scala/sigma/serialization/ErgoTreeSerializer.scala b/data/shared/src/main/scala/sigma/serialization/ErgoTreeSerializer.scala index 3d1061d774..43e41f91ff 100644 --- a/data/shared/src/main/scala/sigma/serialization/ErgoTreeSerializer.scala +++ b/data/shared/src/main/scala/sigma/serialization/ErgoTreeSerializer.scala @@ -1,13 +1,13 @@ package sigma.serialization import org.ergoplatform.validation.ValidationRules.{CheckDeserializedScriptIsSigmaProp, CheckHeaderSizeBit} -import sigma.ast.{Constant, DeserializationSigmaBuilder, ErgoTree, SType, SubstConstants, UnparsedErgoTree} +import sigma.ast.{Constant, DeserializationSigmaBuilder, ErgoTree, SType, UnparsedErgoTree} import sigma.ast.syntax.ValueOps import sigma.ast.ErgoTree.{EmptyConstants, HeaderType} import sigma.util.safeNewArray import debox.cfor import sigma.VersionContext -import sigma.validation.{SigmaValidationSettings, ValidationException} +import sigma.validation.ValidationException import sigma.validation.ValidationRules.CheckPositionLimit /** @@ -299,7 +299,7 @@ class ErgoTreeSerializer { */ def substituteConstants(scriptBytes: Array[Byte], positions: Array[Int], - newVals: Array[Constant[SType]])(implicit vs: SigmaValidationSettings): (Array[Byte], Int) = { + newVals: Array[Constant[SType]]): (Array[Byte], Int) = { require(positions.length == newVals.length, s"expected positions and newVals to have the same length, got: positions: ${positions.toSeq},\n newVals: ${newVals.toSeq}") val r = SigmaSerializer.startReader(scriptBytes) diff --git a/data/shared/src/main/scala/sigma/serialization/SigmaSerializer.scala b/data/shared/src/main/scala/sigma/serialization/SigmaSerializer.scala index cdb28d724b..3765adb029 100644 --- a/data/shared/src/main/scala/sigma/serialization/SigmaSerializer.scala +++ b/data/shared/src/main/scala/sigma/serialization/SigmaSerializer.scala @@ -4,7 +4,6 @@ import java.nio.ByteBuffer import scorex.util.ByteArrayBuilder import scorex.util.serialization._ import sigma.data.SigmaConstants -import sigma.validation.SigmaValidationSettings import sigma.serialization.ValueCodes.OpCode object SigmaSerializer { @@ -35,8 +34,7 @@ object SigmaSerializer { /** Helper function to be use in serializers. */ def startReader(bytes: Array[Byte], constantStore: ConstantStore, - resolvePlaceholdersToConstants: Boolean) - (implicit vs: SigmaValidationSettings): SigmaByteReader = { + resolvePlaceholdersToConstants: Boolean): SigmaByteReader = { val buf = ByteBuffer.wrap(bytes) val r = new SigmaByteReader(new VLQByteBufferReader(buf), constantStore, diff --git a/interpreter/js/src/main/scala/sigma/interpreter/js/SigmaPropProver.scala b/interpreter/js/src/main/scala/sigma/interpreter/js/SigmaPropProver.scala index a04d32fa54..414a9d1220 100644 --- a/interpreter/js/src/main/scala/sigma/interpreter/js/SigmaPropProver.scala +++ b/interpreter/js/src/main/scala/sigma/interpreter/js/SigmaPropProver.scala @@ -65,7 +65,6 @@ class SigmaPropProver(override val wrappedValue: org.ergoplatform.SigmaPropProve val realsToExtract = toSigmaBooleanSeq(realSecretsToExtract) val simsToExtract = toSigmaBooleanSeq(simulatedSecretsToExtract) val hints = wrappedValue.bagForMultisig( - context = null, sigmaTree = sigmaTree.sigmaBoolean, proof.toArray, realSecretsToExtract = realsToExtract, simulatedSecretsToExtract = simsToExtract) diff --git a/interpreter/shared/src/main/scala/org/ergoplatform/ErgoLikeContext.scala b/interpreter/shared/src/main/scala/org/ergoplatform/ErgoLikeContext.scala index 8468175631..e421e8fdfe 100644 --- a/interpreter/shared/src/main/scala/org/ergoplatform/ErgoLikeContext.scala +++ b/interpreter/shared/src/main/scala/org/ergoplatform/ErgoLikeContext.scala @@ -6,7 +6,6 @@ import sigma.ast.SType.{AnyOps, TypeCode} import sigma.ast._ import sigma.data.{AvlTreeData, CAvlTree, CSigmaDslBuilder, SigmaConstants} import sigma.eval.Extensions.toAnyValue -import sigma.exceptions.InterpreterException import sigma.interpreter.ContextExtension import sigma.validation.SigmaValidationSettings import sigma.{AnyValue, Coll, Header, PreHeader} diff --git a/interpreter/shared/src/main/scala/sigmastate/InterpreterReflection.scala b/interpreter/shared/src/main/scala/sigmastate/InterpreterReflection.scala index 8b18e20459..9a06322166 100644 --- a/interpreter/shared/src/main/scala/sigmastate/InterpreterReflection.scala +++ b/interpreter/shared/src/main/scala/sigmastate/InterpreterReflection.scala @@ -8,6 +8,10 @@ import sigmastate.crypto.GF2_192_Poly import sigmastate.crypto.VerifierMessage.Challenge /** Reflection metadata for `interpreter` module. + * Such metadata is only used on JS platform to support reflection-like interfaces of + * RClass, RMethod, RConstructor. These interfaces implemented on JVM using Java + * reflection. + * * For each class of this module that needs reflection metadata, * we register a class entry with the necessary information. * Only information that is needed at runtime is registered. diff --git a/interpreter/shared/src/main/scala/sigmastate/crypto/GF2_192.scala b/interpreter/shared/src/main/scala/sigmastate/crypto/GF2_192.scala index bb0ad60a84..e63526e854 100644 --- a/interpreter/shared/src/main/scala/sigmastate/crypto/GF2_192.scala +++ b/interpreter/shared/src/main/scala/sigmastate/crypto/GF2_192.scala @@ -30,8 +30,6 @@ package sigmastate.crypto import debox.cfor -import java.util - class GF2_192 extends AnyRef { private[crypto] val word: Array[Long] = new Array[Long](3) diff --git a/interpreter/shared/src/main/scala/sigmastate/crypto/GF2_192_Poly.scala b/interpreter/shared/src/main/scala/sigmastate/crypto/GF2_192_Poly.scala index a9212fe565..d2ddc4db48 100644 --- a/interpreter/shared/src/main/scala/sigmastate/crypto/GF2_192_Poly.scala +++ b/interpreter/shared/src/main/scala/sigmastate/crypto/GF2_192_Poly.scala @@ -31,8 +31,6 @@ package sigmastate.crypto import debox.cfor -import java.util - class GF2_192_Poly { final private var c: Array[GF2_192] = null // must be not null and of length at least 1 diff --git a/interpreter/shared/src/main/scala/sigmastate/eval/CContext.scala b/interpreter/shared/src/main/scala/sigmastate/eval/CContext.scala index 418f9e8959..2b076403ad 100644 --- a/interpreter/shared/src/main/scala/sigmastate/eval/CContext.scala +++ b/interpreter/shared/src/main/scala/sigmastate/eval/CContext.scala @@ -9,62 +9,6 @@ import sigma.exceptions.InvalidType import scala.annotation.unused import scala.reflect.ClassTag - -/** This class represents context variable and register value of a functional type A => B. - * When variable or register is accessed using `getVar[A => B](id).get` or - * `box.getReg[A => B].get an instance of this class is returned. - * - * It internally transforms a given `tree` into executable function. - * This it similar to what happens during validation of propositions in the input boxes: - * - size check of underlying ErgoTree against limits - * - construction of `calcF` and `costF` graphs, both are stored together with resulting function. - * - check the types of `calcF` graph to be compatible with expected types A and B - * If anything goes wrong, this operation fails and if it is used in the script, the script also fails. - * - * When f is obtained as `val f = getVar[Int => Int](id).get` then any application `f(x)` involves size estimation - * using underlying `costF(x)`. - * */ -//case class CFunc[A,B](context: sigmastate.interpreter.Context, tree: SValue) -// (implicit tDom: RType[A], tRange: RType[B], IR: IRContext) extends (A => B) { -// import CFunc._ -// -// private val compiled = { -// import IR._ -// val IR.Pair(calcF, costF) = IR.doCosting(emptyEnv, tree) -// -// val eDom = asElem[Any](IR.rtypeToElem(tDom)) -// val eRange = asElem[Any](IR.rtypeToElem(tRange)) -// -// IR.verifyCalcFunc[Any => Any](asRep[Context => (Any => Any)](calcF), IR.funcElement(eDom, eRange)) -//// IR.verifyCostFunc(costF).getOrThrow -//// IR.verifyIsProven(calcF).getOrThrow -// -// // check cost -//// val costingCtx = context.toSigmaContext(IR, isCost = true) -//// val costFun = IR.compile[SInt.type](IR.getDataEnv, costF) -//// val IntConstant(estimatedCost) = costFun(costingCtx) -//// if (estimatedCost > maxCost) { -//// throw new Error(s"Estimated execution cost $estimatedCost exceeds the limit $maxCost in $tree") -//// } -// // check calc -// val calcCtx = context.toSigmaContext(IR, isCost = false) -// val valueFun = IR.compile[SFunc](IR.getDataEnv, asRep[Context => SFunc#WrappedType](calcF)) -// val res = valueFun(calcCtx) match { -// case Constant(f, fTpe: SFunc) => f -// case v => v -// } -// res.asInstanceOf[A => B] -// } -// -// override def apply(x: A): B = compiled(x) -//} -object CFunc { - /** The cost of creating resulting function but not its execution. - * Thus it is expected to be small. It can be increased if useful cases are found - * such that `tree` should contains heavy operations. */ - val maxCost = 1000 -} - /** A default implementation of [[Context]] interface. * @see [[Context]] for detailed descriptions */ diff --git a/interpreter/shared/src/main/scala/sigmastate/eval/CProfiler.scala b/interpreter/shared/src/main/scala/sigmastate/eval/CProfiler.scala index ced8a357b8..d07153bd51 100644 --- a/interpreter/shared/src/main/scala/sigmastate/eval/CProfiler.scala +++ b/interpreter/shared/src/main/scala/sigmastate/eval/CProfiler.scala @@ -280,7 +280,7 @@ class CProfiler extends Profiler { case ci: TypeBasedCostItem => val comment = s"count: $count, suggested: $suggestedCost, actCost: ${ci.cost}$warn" (ci.opName, time, time, comment) - case ci @ SeqCostItem(_, costKind, nItems) => + case ci @ SeqCostItem(_, costKind, _) => val nChunks = ci.chunks val timePerChunk = if (nChunks > 0) time / nChunks else time val name = s"${ci.opName}(nChunks: $nChunks)" @@ -289,7 +289,7 @@ class CProfiler extends Profiler { } } (name, timePerItem, time, comment) - }.sortBy({ case (name, tpi, t, c) => (name, tpi)})(Ordering[(String, Long)]) + }.sortBy({ case (name, tpi, _, _) => (name, tpi)})(Ordering[(String, Long)]) val estLines = estimationCostStat.mapToArray { case (script, stat) => val (cost, count) = stat.mean @@ -302,7 +302,7 @@ class CProfiler extends Profiler { val rows = opCodeLines - .map { case (opName, opCode, time, comment) => + .map { case (opName, _, time, comment) => val key = s"$opName".padTo(26, ' ') s"$key -> time: $time ns, $comment " } diff --git a/interpreter/shared/src/main/scala/sigmastate/interpreter/Interpreter.scala b/interpreter/shared/src/main/scala/sigmastate/interpreter/Interpreter.scala index 6b673038c7..9a1ab11f0e 100644 --- a/interpreter/shared/src/main/scala/sigmastate/interpreter/Interpreter.scala +++ b/interpreter/shared/src/main/scala/sigmastate/interpreter/Interpreter.scala @@ -23,7 +23,7 @@ import sigmastate.interpreter.CErgoTreeEvaluator.fixedCostOp import sigmastate.interpreter.Interpreter._ import sigma.ast.syntax.ValueOps import sigma.eval.{EvalSettings, SigmaDsl} -import sigma.exceptions.{CostLimitException, InterpreterException} +import sigma.exceptions.InterpreterException import sigma.interpreter.ProverResult import sigma.util.CollectionUtil import sigmastate.utils.Helpers._ @@ -164,12 +164,11 @@ trait Interpreter { * else `exp` is computed in the given context and the resulting SigmaBoolean returned. * * @param context the context in which `exp` should be executed - * @param env environment of system variables used by the interpreter internally * @param exp expression to be executed in the given `context` * @return result of script reduction * @see `ReductionResult` */ - protected def reduceToCryptoJITC(context: CTX, env: ScriptEnv, exp: SigmaPropValue): Try[ReductionResult] = Try { + protected def reduceToCryptoJITC(context: CTX, exp: SigmaPropValue): Try[ReductionResult] = Try { implicit val vs = context.validationSettings trySoftForkable[ReductionResult](whenSoftFork = WhenSoftForkReductionResult(context.initCost)) { @@ -253,7 +252,7 @@ trait Interpreter { // here we assume that when `propTree` is TrueProp then `reduceToCrypto` always succeeds // and the rest of the verification is also trivial - reduceToCryptoJITC(context2, env, propTree).getOrThrow + reduceToCryptoJITC(context2, propTree).getOrThrow } res diff --git a/interpreter/shared/src/main/scala/sigmastate/interpreter/ProverUtils.scala b/interpreter/shared/src/main/scala/sigmastate/interpreter/ProverUtils.scala index 15daaec382..dc2259b0b7 100644 --- a/interpreter/shared/src/main/scala/sigmastate/interpreter/ProverUtils.scala +++ b/interpreter/shared/src/main/scala/sigmastate/interpreter/ProverUtils.scala @@ -81,7 +81,7 @@ trait ProverUtils extends Interpreter { realSecretsToExtract: Seq[SigmaBoolean], simulatedSecretsToExtract: Seq[SigmaBoolean] = Seq.empty): HintsBag = { val reduced = fullReduction(ergoTree, context, Interpreter.emptyEnv) - bagForMultisig(context, reduced.value, proof, realSecretsToExtract, simulatedSecretsToExtract) + bagForMultisig(reduced.value, proof, realSecretsToExtract, simulatedSecretsToExtract) } /** @@ -90,15 +90,13 @@ trait ProverUtils extends Interpreter { * * See DistributedSigSpecification for examples of usage. * - * @param context - context used to reduce the proposition * @param sigmaTree - public key (in form of a sigma-tree) * @param proof - signature for the key * @param realSecretsToExtract - public keys of secrets with real proofs * @param simulatedSecretsToExtract - public keys of secrets with simulated proofs * @return - bag of OtherSecretProven and OtherCommitment hints */ - def bagForMultisig(context: CTX, - sigmaTree: SigmaBoolean, + def bagForMultisig(sigmaTree: SigmaBoolean, proof: Array[Byte], realSecretsToExtract: Seq[SigmaBoolean], simulatedSecretsToExtract: Seq[SigmaBoolean]): HintsBag = { diff --git a/interpreter/shared/src/test/scala/sigma/serialization/ConstantSerializerSpecification.scala b/interpreter/shared/src/test/scala/sigma/serialization/ConstantSerializerSpecification.scala index 7bc73643f2..43e9cf9e5d 100644 --- a/interpreter/shared/src/test/scala/sigma/serialization/ConstantSerializerSpecification.scala +++ b/interpreter/shared/src/test/scala/sigma/serialization/ConstantSerializerSpecification.scala @@ -61,7 +61,7 @@ class ConstantSerializerSpecification extends TableSerializationSpecification { } property("Constant serialization round trip") { - forAll { x: Unit => roundTripTest(UnitConstant()) } + forAll { _: Unit => roundTripTest(UnitConstant()) } forAll { x: Byte => roundTripTest(Constant[SByte.type](x, SByte)) } forAll { x: Boolean => roundTripTest(BooleanConstant.fromBoolean(x)) } forAll { x: Long => roundTripTest(Constant[SLong.type](x, SLong)) } diff --git a/interpreter/shared/src/test/scala/sigma/serialization/DataSerializerSpecification.scala b/interpreter/shared/src/test/scala/sigma/serialization/DataSerializerSpecification.scala index ecb2d2ef70..7cd9967e54 100644 --- a/interpreter/shared/src/test/scala/sigma/serialization/DataSerializerSpecification.scala +++ b/interpreter/shared/src/test/scala/sigma/serialization/DataSerializerSpecification.scala @@ -5,7 +5,6 @@ import org.ergoplatform.ErgoBox import org.scalacheck.Arbitrary._ import sigma.data.{DataValueComparer, RType, SigmaBoolean, TupleColl} import sigma.ast.SCollection.SByteArray -import sigmastate._ import sigmastate.eval._ import sigma.{AvlTree, Colls, Evaluation} import sigma.ast.SType.AnyOps diff --git a/interpreter/shared/src/test/scala/sigmastate/eval/BasicOpsTests.scala b/interpreter/shared/src/test/scala/sigmastate/eval/BasicOpsTests.scala index ba996b0246..e9ba273e17 100644 --- a/interpreter/shared/src/test/scala/sigmastate/eval/BasicOpsTests.scala +++ b/interpreter/shared/src/test/scala/sigmastate/eval/BasicOpsTests.scala @@ -3,16 +3,15 @@ package sigmastate.eval import org.scalatest.funsuite.AnyFunSuite import org.scalatest.matchers.should.Matchers import sigma.crypto.SecP256K1Group -import sigma.data.{CSigmaDslBuilder, TrivialProp} +import sigma.data.{CSigmaDslBuilder => SigmaDsl, TrivialProp} import sigma.util.Extensions.SigmaBooleanOps import java.math.BigInteger -import sigma.{ContractsTestkit, SigmaDslBuilder, SigmaProp} +import sigma.{ContractsTestkit, SigmaProp} import scala.language.implicitConversions class BasicOpsTests extends AnyFunSuite with ContractsTestkit with Matchers { - override val SigmaDsl: SigmaDslBuilder = CSigmaDslBuilder implicit def boolToSigma(b: Boolean): SigmaProp = TrivialProp(b).toSigmaProp @@ -60,7 +59,7 @@ class BasicOpsTests extends AnyFunSuite with ContractsTestkit with Matchers { } test("box.creationInfo._1 is Int") { - val box = newAliceBox(1, 100) + val box = newAliceBox(100) box.creationInfo._1 shouldBe a [Integer] } diff --git a/interpreter/shared/src/test/scala/special/sigma/ContractsTestkit.scala b/interpreter/shared/src/test/scala/special/sigma/ContractsTestkit.scala index 720223ee3a..b04e9c150f 100644 --- a/interpreter/shared/src/test/scala/special/sigma/ContractsTestkit.scala +++ b/interpreter/shared/src/test/scala/special/sigma/ContractsTestkit.scala @@ -8,43 +8,18 @@ import sigmastate.eval._ import sigmastate.helpers.TestingHelpers._ import sigma.data._ -import scala.annotation.nowarn // imports implicit ClassTag - trait ContractsTestkit { - val R0 = 0.toByte; - val R1 = 1.toByte; - val R2 = 2.toByte; - val R3 = 3.toByte; - val R4 = 4.toByte; - val R5 = 5.toByte; - val R6 = 6.toByte; - val R7 = 7.toByte; - val R8 = 8.toByte; - val R9 = 9.toByte; + val Colls = new CollOverArrayBuilder - val SigmaDsl: SigmaDslBuilder = CSigmaDslBuilder - val noRegisters = collection[AnyValue]() - val noBytes = collection[Byte]() val noInputs = Array[Box]() val noOutputs = Array[Box]() val dummyPubkey: Array[Byte] = Array.fill(32)(0: Byte) - val dummyADDigest: Coll[Byte] = Colls.fromArray(Array.fill(33)(0: Byte)) val emptyAvlTree = new CAvlTree(AvlTreeData.dummy) val noHeaders = CSigmaDslBuilder.Colls.emptyColl[Header] val dummyPreHeader: PreHeader = null /** Create collection from array of items */ - def collection[T: RType](items: T*) = Colls.fromArray(items.toArray) - - /** Converts a map of registers to collection of registers. */ - def regs(m: Map[Byte, AnyValue]): Coll[AnyValue] = { - val res = new Array[AnyValue](10) - for ( (id, v) <- m ) { - assert(res(id) == null, s"register $id is defined more then once") - res(id) = v - } - Colls.fromArray(res) - } + def collection[T: RType](items: T*): Coll[T] = Colls.fromArray(items.toArray) /** Converts a map of context vars to collection of context vars. */ def contextVars(m: Map[Byte, AnyValue]): Coll[AnyValue] = { @@ -58,9 +33,7 @@ trait ContractsTestkit { Colls.fromArray(res) } - val AliceId = Array[Byte](1) // 0x0001 - - def newAliceBox(@nowarn id: Byte, value: Long): Box = { + def newAliceBox(value: Long): Box = { val ergoBox = testBox(value, ErgoTree.fromProposition(TrueSigmaProp), creationHeight = 0, additionalTokens = Seq(), additionalRegisters = Map()) @@ -90,8 +63,6 @@ trait ContractsTestkit { implicit class TestContextOps(ctx: CContext) { def withInputs(inputs: Box*) = ctx.copy(inputs = inputs.toArray.toColl) - def withOutputs(outputs: Box*) = ctx.copy(outputs = outputs.toArray.toColl) - def withVariables(vars: Map[Int, AnyValue]) = ctx.copy(vars = contextVars(vars.map { case (k, v) => (k.toByte, v) })) } diff --git a/interpreter/shared/src/test/scala/special/sigma/SigmaTestingData.scala b/interpreter/shared/src/test/scala/special/sigma/SigmaTestingData.scala index d33f09dd80..f113a484ef 100644 --- a/interpreter/shared/src/test/scala/special/sigma/SigmaTestingData.scala +++ b/interpreter/shared/src/test/scala/special/sigma/SigmaTestingData.scala @@ -30,13 +30,6 @@ trait SigmaTestingData extends TestingCommons with ObjectGenerators { def Coll[T](items: T*)(implicit cT: RType[T]): Coll[T] = CSigmaDslBuilder.Colls.fromItems(items: _*) - /** Generator of random collection with `n` elements. */ - def collOfN[T: RType : Arbitrary](n: Int) - (implicit b: Buildable[T, Array[T]]): Gen[Coll[T]] = { - implicit val g: Gen[T] = Arbitrary.arbitrary[T] - containerOfN[Array, T](n, g).map(Colls.fromArray(_)) - } - val bytesGen: Gen[Array[Byte]] = for { len <- Gen.choose(0, 100) arr <- containerOfN[Array, Byte](len, Arbitrary.arbByte.arbitrary) @@ -54,63 +47,9 @@ trait SigmaTestingData extends TestingCommons with ObjectGenerators { res } - protected def sampleAvlProver = { - val keys = arrayOfN(100, keyCollGen).sample.get - val values = arrayOfN(100, bytesCollGen).sample.get - val (tree, prover) = createAvlTreeAndProver(keys.zip(values): _*) - (keys, values, tree, prover) - } - - protected def sampleAvlTree: AvlTree = { - val (_, _, _, avlProver) = sampleAvlProver - val digest = avlProver.digest.toColl - val tree = SigmaDsl.avlTree(AvlTreeFlags.ReadOnly.serializeToByte, digest, 32, None) - tree - } - val tokenId1: Digest32 = Blake2b256("id1") val tokenId2: Digest32 = Blake2b256("id2") - val header1: Header = CHeader(Blake2b256("Header.id").toColl, - 0, - Blake2b256("Header.parentId").toColl, - Blake2b256("ADProofsRoot").toColl, - sampleAvlTree, - Blake2b256("transactionsRoot").toColl, - timestamp = 0, - nBits = 0, - height = 0, - extensionRoot = Blake2b256("transactionsRoot").toColl, - minerPk = SigmaDsl.groupGenerator, - powOnetimePk = SigmaDsl.groupGenerator, - powNonce = Colls.fromArray(Array[Byte](0, 1, 2, 3, 4, 5, 6, 7)), - powDistance = SigmaDsl.BigInt(BigInt("1405498250268750867257727119510201256371618473728619086008183115260323").bigInteger), - votes = Colls.fromArray(Array[Byte](0, 1, 2)) - ) - val header2: Header = CHeader(Blake2b256("Header2.id").toColl, - 0, - header1.id, - Blake2b256("ADProofsRoot2").toColl, - sampleAvlTree, - Blake2b256("transactionsRoot2").toColl, - timestamp = 2, - nBits = 0, - height = 1, - extensionRoot = Blake2b256("transactionsRoot2").toColl, - minerPk = SigmaDsl.groupGenerator, - powOnetimePk = SigmaDsl.groupGenerator, - powNonce = Colls.fromArray(Array.fill(0.toByte)(8)), - powDistance = SigmaDsl.BigInt(BigInt("19306206489815517413186395405558417825367537880571815686937307203793939").bigInteger), - votes = Colls.fromArray(Array[Byte](0, 1, 0)) - ) - val headers = Colls.fromItems(header2, header1) - val preHeader: PreHeader = CPreHeader(0, - header2.id, - timestamp = 3, - nBits = 0, - height = 2, - minerPk = SigmaDsl.groupGenerator, - votes = Colls.emptyColl[Byte] - ) + object TestData { val BigIntZero: BigInt = CBigInt(new BigInteger("0", 16)) diff --git a/parsers/shared/src/test/scala/sigmastate/lang/LangTests.scala b/parsers/shared/src/test/scala/sigmastate/lang/LangTests.scala index c04f35ef71..498c3934bf 100644 --- a/parsers/shared/src/test/scala/sigmastate/lang/LangTests.scala +++ b/parsers/shared/src/test/scala/sigmastate/lang/LangTests.scala @@ -8,7 +8,6 @@ import sigma.ast._ import sigma.crypto.CryptoConstants import sigma.data.{CAnyValue, CSigmaDslBuilder, ProveDHTuple, ProveDlog, SigmaBoolean} import sigma.util.Extensions.BigIntegerOps -import sigmastate.eval._ import sigmastate.helpers.NegativeTesting import sigmastate.interpreter.Interpreter.ScriptEnv import sigma.ast.{Ident, MethodCallLike} diff --git a/sc/shared/src/main/scala/org/ergoplatform/dsl/ContractSyntax.scala b/sc/shared/src/main/scala/org/ergoplatform/dsl/ContractSyntax.scala index d4accabf3e..11cbaff739 100644 --- a/sc/shared/src/main/scala/org/ergoplatform/dsl/ContractSyntax.scala +++ b/sc/shared/src/main/scala/org/ergoplatform/dsl/ContractSyntax.scala @@ -60,7 +60,7 @@ trait ContractSyntax { contract: SigmaContract => case _: Box => BoxRType case _: AvlTreeData => syntax.AvlTreeDataRType // TODO remove this RType case _: AvlTree => AvlTreeRType - case _: SigmaBoolean => syntax.SigmaBooleanRType // TODO remove this RType + case _: SigmaBoolean => SigmaBooleanRType // TODO remove this RType case _: SigmaProp => SigmaPropRType case _: Context => ContextRType case _ => diff --git a/sc/shared/src/main/scala/scalan/GraphIRReflection.scala b/sc/shared/src/main/scala/scalan/GraphIRReflection.scala index ee29924fb7..0eaba9d8a3 100644 --- a/sc/shared/src/main/scala/scalan/GraphIRReflection.scala +++ b/sc/shared/src/main/scala/scalan/GraphIRReflection.scala @@ -11,6 +11,10 @@ import special.wrappers.{OptionWrapSpec, RTypeWrapSpec} import wrappers.scalan.WRTypes /** Registrations of reflection metadata for graph-ir module (see README.md). + * Such metadata is only used on JS platform to support reflection-like interfaces of + * RClass, RMethod, RConstructor. These interfaces implemented on JVM using Java + * reflection. + * * For each class of this module that needs reflection metadata, * we register a class entry with the necessary information. * Only information that is needed at runtime is registered. diff --git a/sc/shared/src/main/scala/scalan/Library.scala b/sc/shared/src/main/scala/scalan/Library.scala index ee1ff80ad3..43f20813f0 100644 --- a/sc/shared/src/main/scala/scalan/Library.scala +++ b/sc/shared/src/main/scala/scalan/Library.scala @@ -107,7 +107,7 @@ trait Library extends Scalan override def invokeUnlifted(e: Elem[_], mc: MethodCall, dataEnv: DataEnv): Any = e match { case _: CollElem[_,_] => mc match { - case CollMethods.map(xs, f) => + case CollMethods.map(_, f) => val newMC = mc.copy(args = mc.args :+ f.elem.eRange)(mc.resultType, mc.isAdapterCall) super.invokeUnlifted(e, newMC, dataEnv) case _ => diff --git a/sc/shared/src/main/scala/scalan/MethodCalls.scala b/sc/shared/src/main/scala/scalan/MethodCalls.scala index af3c3201ef..14212df632 100644 --- a/sc/shared/src/main/scala/scalan/MethodCalls.scala +++ b/sc/shared/src/main/scala/scalan/MethodCalls.scala @@ -101,11 +101,6 @@ trait MethodCalls extends Base { self: Scalan => reifyObject(MethodCall(receiver, method, args, neverInvoke)(asElem[Any](resultElem), isAdapterCall)) } - /** Creates new NewObject node and returns its node ref. */ - def newObjEx[A](args: Any*)(implicit eA: Elem[A]): Ref[A] = { - reifyObject(NewObject[A](eA, args)) - } - @tailrec private def baseCause(e: Throwable): Throwable = e match { case e: ExceptionInInitializerError => baseCause(e.getCause) @@ -120,21 +115,6 @@ trait MethodCalls extends Base { self: Scalan => * point we know that the first RW set didn't triggered any rewrite. */ def rewriteNonInvokableMethodCall(@unused mc: MethodCall): Ref[_] = null - /** Create delegate instance suitable for method invocation. - * It is used when T is a class or a trait and the node referred by x doesn't conform to T. - * This method returns dynamically constructed instance, which conforms to T. - * Whenever a method of T is called on that instance, the call is intercepted and - * `DelegatedInterceptionHandler.invoke` method is called, then a new MethodCall can - * be constructed (which is befavior by default). - */ - protected def unrefDelegate[T <: AnyRef](x: Ref[T])(implicit ct: ClassTag[T]): T = { - val d = x.node - if (d.isInstanceOf[Const[_]]) - d.asInstanceOf[Const[T]@unchecked].x - else - !!!(s"Cannot do undefDelegate($x -> ${x.node})") - } - /** Generic helper to call the given method on the given receiver node. */ private[scalan] def invokeMethod[A](receiver: Sym, m: RMethod, args: Array[AnyRef], onInvokeSuccess: Any => A, @@ -148,9 +128,9 @@ trait MethodCalls extends Base { self: Scalan => } catch { case e: Exception => onInvokeException(baseCause(e)) } - } - else + } else { onInvokeImpossible + } } /** Method invocation enabler. diff --git a/sc/shared/src/main/scala/scalan/meta/SSymName.scala b/sc/shared/src/main/scala/scalan/meta/SSymName.scala index ea9b1546ba..b0f8dae6d2 100644 --- a/sc/shared/src/main/scala/scalan/meta/SSymName.scala +++ b/sc/shared/src/main/scala/scalan/meta/SSymName.scala @@ -6,16 +6,11 @@ case class ImportItem(packageName: String, importedNames: List[String]) case class SSymName(packageName: String, name: String) { import SSymName._ - def this(name: String) = this("", name) def mkFullName = fullNameString(packageName, name) - def isImportedBy(item: ImportItem): Boolean = { - if (packageName != item.packageName) return false - item.importedNames.contains(SSymName.ImportAllWildcard) || item.importedNames.contains(name) - } } object SSymName { - /** Wildcard character used to signify imporing all names from namespace */ + /** Wildcard character used to signify importing all names from namespace */ val ImportAllWildcard = "*" def fullNameString(packageName: String, name: String): String = if (packageName.isNullOrEmpty) name else s"$packageName.$name" diff --git a/sc/shared/src/main/scala/scalan/primitives/Functions.scala b/sc/shared/src/main/scala/scalan/primitives/Functions.scala index e5cd6f345e..9026461777 100644 --- a/sc/shared/src/main/scala/scalan/primitives/Functions.scala +++ b/sc/shared/src/main/scala/scalan/primitives/Functions.scala @@ -16,12 +16,6 @@ trait Functions extends Base with ProgramGraphs { self: Scalan => /** Apply given function symbol to the given argument symbol. * @return symbol representing result of function application */ final def apply(x: Ref[A]): Ref[B] = mkApply(f, x) - - /** Build new function which applies `f` and then `g`*/ - final def >>[C](g: Ref[B => C]): Ref[A => C] = compose(g, f) - - /** Build new function which applies `g` and then `f`*/ - final def <<[C](g: Ref[C => A]): Ref[C => B] = compose(f, g) } /** Global lambda equality mode used by default. It is used in `fun` and `fun2` lambda builders. @@ -332,7 +326,7 @@ trait Functions extends Base with ProgramGraphs { self: Scalan => val m = new java.util.HashMap[Sym, Sym](100) m.put(lam.x, s) val subst = new MapTransformer(m) - val t = DefaultMirror.mirrorSymbols(subst, NoRewriting, lam, body) + val t = DefaultMirror.mirrorSymbols(subst, NoRewriting, body) t(lam.y) } diff --git a/sc/shared/src/main/scala/scalan/primitives/Thunks.scala b/sc/shared/src/main/scala/scalan/primitives/Thunks.scala index ce51dc5638..f9f843664d 100644 --- a/sc/shared/src/main/scala/scalan/primitives/Thunks.scala +++ b/sc/shared/src/main/scala/scalan/primitives/Thunks.scala @@ -323,7 +323,7 @@ trait Thunks extends Functions { self: Scalan => */ def forceThunkDefByMirror[A](th: ThunkDef[A], subst: MapTransformer = MapTransformer.empty()): Ref[A] = { val body = th.scheduleIds - val t = DefaultMirror.mirrorSymbols(subst, NoRewriting, th, body) + val t = DefaultMirror.mirrorSymbols(subst, NoRewriting, body) t(th.root) } diff --git a/sc/shared/src/main/scala/scalan/staged/Transforming.scala b/sc/shared/src/main/scala/scalan/staged/Transforming.scala index 045340e503..a64b998ff6 100644 --- a/sc/shared/src/main/scala/scalan/staged/Transforming.scala +++ b/sc/shared/src/main/scala/scalan/staged/Transforming.scala @@ -47,9 +47,6 @@ trait Transforming { self: Scalan => constantPropagation: Boolean = true, /** Used in SlicingPass */ shouldSlice: Boolean = false) - { - def withConstantPropagation(value: Boolean) = this.copy(constantPropagation = value) - } /** Default pass to be used when IR is used without special compiler configuration. */ class DefaultPass(val name: String, override val config: PassConfig = PassConfig()) extends Pass @@ -65,10 +62,6 @@ trait Transforming { self: Scalan => def beginPass(pass: Pass): Unit = { _currentPass = pass } - /** Called to let this IR context to finalized the given pass. */ - def endPass(pass: Pass): Unit = { - _currentPass = Pass.defaultPass - } /** Concrete and default implementation of Transformer using underlying HashMap. * HOTSPOT: don't beatify the code */ @@ -152,7 +145,7 @@ trait Transforming { self: Scalan => protected def mirrorElem(node: Sym): Elem[_] = node.elem // every mirrorXXX method should return a pair (t + (v -> v1), v1) - protected def mirrorVar[A](t: Transformer, rewriter: Rewriter, v: Ref[A]): Transformer = { + protected def mirrorVar[A](t: Transformer, v: Ref[A]): Transformer = { val newVar = variable(Lazy(mirrorElem(v))) t + (v, newVar) } @@ -173,7 +166,7 @@ trait Transforming { self: Scalan => protected def mirrorLambda[A, B](t: Transformer, rewriter: Rewriter, node: Ref[A => B], lam: Lambda[A, B]): Transformer = { var tRes: Transformer = t - val t1 = mirrorNode(t, rewriter, lam, lam.x) + val t1 = mirrorNode(t, rewriter, lam.x) // original root val originalRoot = lam.y @@ -190,7 +183,7 @@ trait Transforming { self: Scalan => // lambdaStack = newLambdaCandidate :: lambdaStack val newRoot = { // reifyEffects block val schedule = lam.scheduleIds - val t2 = mirrorSymbols(t1, rewriter, lam, schedule) + val t2 = mirrorSymbols(t1, rewriter, schedule) tRes = t2 tRes(originalRoot) // this will be a new root } @@ -214,7 +207,7 @@ trait Transforming { self: Scalan => val newScope = thunkStack.beginScope(newThunkSym) val schedule = thunk.scheduleIds - val t1 = mirrorSymbols(t, rewriter, thunk, schedule) + val t1 = mirrorSymbols(t, rewriter, schedule) thunkStack.endScope() val newRoot = t1(thunk.root) @@ -230,12 +223,12 @@ trait Transforming { self: Scalan => protected def isMirrored(t: Transformer, node: Sym): Boolean = t.isDefinedAt(node) - def mirrorNode(t: Transformer, rewriter: Rewriter, g: AstGraph, node: Sym): Transformer = { + def mirrorNode(t: Transformer, rewriter: Rewriter, node: Sym): Transformer = { if (isMirrored(t, node)) t else { node.node match { - case v: Variable[_] => - mirrorVar(t, rewriter, node) + case _: Variable[_] => + mirrorVar(t, node) case lam: Lambda[a, b] => mirrorLambda(t, rewriter, node.asInstanceOf[Ref[a => b]], lam) case th: ThunkDef[a] => @@ -247,12 +240,12 @@ trait Transforming { self: Scalan => } /** HOTSPOT: */ - def mirrorSymbols(t0: Transformer, rewriter: Rewriter, g: AstGraph, nodes: DBuffer[Int]) = { + def mirrorSymbols(t0: Transformer, rewriter: Rewriter, nodes: DBuffer[Int]): Transformer = { var t: Transformer = t0 cfor(0)(_ < nodes.length, _ + 1) { i => val n = nodes(i) val s = getSym(n) - t = mirrorNode(t, rewriter, g, s) + t = mirrorNode(t, rewriter, s) } t } diff --git a/sc/shared/src/main/scala/sigmastate/eval/GraphBuilding.scala b/sc/shared/src/main/scala/sigmastate/eval/GraphBuilding.scala index 9c9fa5ffe1..5ddcdfa946 100644 --- a/sc/shared/src/main/scala/sigmastate/eval/GraphBuilding.scala +++ b/sc/shared/src/main/scala/sigmastate/eval/GraphBuilding.scala @@ -52,10 +52,6 @@ trait GraphBuilding extends SigmaLibrary { IR: IRContext => this.keepOriginalFunc = false // original lambda of Lambda node contains invocations of evalNode and we don't want that this.useAlphaEquality = false - /** Whether to create CostOf nodes or substutute costs from CostTable as constants in the graph. - * true - substitute; false - create CostOf nodes */ - var substFromCostTable: Boolean = true - /** Whether to save calcF and costF graphs in the file given by ScriptNameProp environment variable */ var saveGraphsInFile: Boolean = false @@ -380,8 +376,6 @@ trait GraphBuilding extends SigmaLibrary { IR: IRContext => case _ => error(s"Cannot find BinOp for opcode newOpCode(${opCode.toUByte - LastConstantCode}) and type $eA") } - import sigmastate._ - protected implicit def groupElementToECPoint(g: sigma.GroupElement): EcPointType = CSigmaDslBuilder.toECPoint(g).asInstanceOf[EcPointType] def error(msg: String) = throw new GraphBuildingException(msg, None) @@ -436,7 +430,7 @@ trait GraphBuilding extends SigmaLibrary { IR: IRContext => error(s"Don't know how to buildNode($node)", node.sourceContext.toOption) val res: Ref[Any] = node match { - case c @ Constant(v, tpe) => v match { + case Constant(v, tpe) => v match { case p: SSigmaProp => assert(tpe == SSigmaProp) val resV = liftConst(p) @@ -887,7 +881,7 @@ trait GraphBuilding extends SigmaLibrary { IR: IRContext => f } - case l @ FuncValue(Seq((n, argTpe)), body) => + case FuncValue(Seq((n, argTpe)), body) => val eArg = stypeToElem(argTpe).asInstanceOf[Elem[Any]] val f = fun { x: Ref[Any] => buildNode(ctx, env + (n -> x), body) diff --git a/sc/shared/src/main/scala/sigmastate/eval/IRContext.scala b/sc/shared/src/main/scala/sigmastate/eval/IRContext.scala index b84098f2e7..597711d458 100644 --- a/sc/shared/src/main/scala/sigmastate/eval/IRContext.scala +++ b/sc/shared/src/main/scala/sigmastate/eval/IRContext.scala @@ -1,65 +1,25 @@ package sigmastate.eval import sigma.ast.TransformingSigmaBuilder -import sigma.data.CSigmaDslBuilder - -import java.util.concurrent.locks.ReentrantLock -import scala.util.Try /** Main interface of graph IR context which contain both GraphBuilding and TreeBuilding * methods. * It is not used in v5.0 interpreter and thus not part of consensus. * - * @see RuntimeIRContext, CompiletimeIRContext + * Used in ErgoScript compiler only. + * + * @see CompiletimeIRContext */ trait IRContext extends TreeBuilding with GraphBuilding { - import SigmaProp._ - - private val SigmaM = SigmaPropMethods - override val builder = TransformingSigmaBuilder - /** Can be used to synchronize access to this IR object from multiple threads. */ - val lock = new ReentrantLock() - /** Pass configuration which is used to turn-off constant propagation. + * USED IN TESTS ONLY. * @see `beginPass(noCostPropagationPass)` */ lazy val noConstPropagationPass = new DefaultPass( "noCostPropagationPass", Pass.defaultPassConfig.copy(constantPropagation = false)) - - /** The value of Global ErgoTree operation */ - val sigmaDslBuilderValue = CSigmaDslBuilder - - /** Finds SigmaProp.isProven method calls in the given Lambda `f` */ - def findIsProven[T](f: Ref[Context => T]): Option[Sym] = { - val Def(Lambda(lam,_,_,_)) = f - val s = lam.flatSchedule.find(sym => sym.node match { - case SigmaM.isValid(_) => true - case _ => false - }) - s - } - - /** Checks that if SigmaProp.isProven method calls exists in the given Lambda's schedule, - * then it is the last operation. */ - def verifyIsProven[T](f: Ref[Context => T]): Try[Unit] = { - val isProvenOpt = findIsProven(f) - Try { - isProvenOpt match { - case Some(s) => - if (f.getLambda.y != s) !!!(s"Sigma.isProven found in none-root position", s) - case None => - } - } - } -} - -/** IR context to be used by blockchain nodes to validate transactions. */ -class RuntimeIRContext extends IRContext { } /** IR context to be used by script development tools to compile ErgoScript into ErgoTree bytecode. */ -class CompiletimeIRContext extends IRContext { -} - +class CompiletimeIRContext extends IRContext diff --git a/sc/shared/src/main/scala/sigmastate/eval/SigmaLibrary.scala b/sc/shared/src/main/scala/sigmastate/eval/SigmaLibrary.scala index be17179cbf..7745873620 100644 --- a/sc/shared/src/main/scala/sigmastate/eval/SigmaLibrary.scala +++ b/sc/shared/src/main/scala/sigmastate/eval/SigmaLibrary.scala @@ -10,7 +10,7 @@ trait SigmaLibrary extends Library { import WRType._ - implicit lazy val wRTypeAnyElement = wRTypeElement(AnyElement) + implicit lazy val wRTypeAnyElement: Elem[WRType[Any]] = wRTypeElement(AnyElement) /** During compilation represent a global value Global, see also SGlobal type. */ def sigmaDslBuilder: Ref[SigmaDslBuilder] diff --git a/sc/shared/src/main/scala/sigmastate/eval/TreeBuilding.scala b/sc/shared/src/main/scala/sigmastate/eval/TreeBuilding.scala index 26bc33956f..27f659c1ed 100644 --- a/sc/shared/src/main/scala/sigmastate/eval/TreeBuilding.scala +++ b/sc/shared/src/main/scala/sigmastate/eval/TreeBuilding.scala @@ -161,7 +161,7 @@ trait TreeBuilding extends SigmaLibrary { IR: IRContext => case _ if env.contains(s) => val (id, tpe) = env(s) ValUse(id, tpe) // recursion base - case Def(Lambda(lam, _, x, y)) => + case Def(Lambda(lam, _, x, _)) => val varId = defId + 1 // arguments are treated as ValDefs and occupy id space val env1 = env + (x -> (varId, elemToSType(x.elem))) val block = processAstGraph(ctx, mainG, env1, lam, varId + 1, constantsProcessing) @@ -170,7 +170,7 @@ trait TreeBuilding extends SigmaLibrary { IR: IRContext => case Def(Apply(fSym, xSym, _)) => val Seq(f, x) = Seq(fSym, xSym).map(recurse) builder.mkApply(f, Array(x)) - case Def(th @ ThunkDef(root, _)) => + case Def(th @ ThunkDef(_, _)) => val block = processAstGraph(ctx, mainG, env, th, defId, constantsProcessing) block case Def(Const(x)) => @@ -449,7 +449,7 @@ trait TreeBuilding extends SigmaLibrary { IR: IRContext => (valdefs.toArray[BlockItem], rhs) match { // simple optimization to avoid producing block sub-expressions like: // `{ val idNew = id; idNew }` which this rules rewrites to just `id` - case (Array(ValDef(idNew, _, source @ ValUse(id, tpe))), ValUse(idUse, tpeUse)) + case (Array(ValDef(idNew, _, source @ ValUse(_, tpe))), ValUse(idUse, tpeUse)) if idUse == idNew && tpeUse == tpe => source case (items, _) => BlockValue(items, rhs) diff --git a/sc/shared/src/main/scala/sigmastate/lang/SigmaBinder.scala b/sc/shared/src/main/scala/sigmastate/lang/SigmaBinder.scala index f93e31703d..82aaea7e30 100644 --- a/sc/shared/src/main/scala/sigmastate/lang/SigmaBinder.scala +++ b/sc/shared/src/main/scala/sigmastate/lang/SigmaBinder.scala @@ -1,7 +1,6 @@ package sigmastate.lang import org.ergoplatform.ErgoAddressEncoder.NetworkPrefix -import org.ergoplatform._ import sigma.ast.NoType import sigma.data.Nullable import sigma.kiama.rewriting.CallbackRewriter diff --git a/sc/shared/src/main/scala/special/collection/CollsUnit.scala b/sc/shared/src/main/scala/special/collection/CollsUnit.scala index 02e62aeb4d..90f0dca99e 100644 --- a/sc/shared/src/main/scala/special/collection/CollsUnit.scala +++ b/sc/shared/src/main/scala/special/collection/CollsUnit.scala @@ -9,9 +9,6 @@ package sigma { * for details. */ trait Colls extends Base { self: Library => - import Coll._; - import CollBuilder._; - import WOption._; trait Coll[A] extends Def[Coll[A]] { implicit def eA: Elem[A]; def length: Ref[Int]; @@ -37,7 +34,5 @@ package sigma { def xor(left: Ref[Coll[Byte]], right: Ref[Coll[Byte]]): Ref[Coll[Byte]]; def replicate[T](n: Ref[Int], v: Ref[T]): Ref[Coll[T]]; }; - trait CollCompanion; - trait CollBuilderCompanion } } \ No newline at end of file diff --git a/sc/shared/src/main/scala/special/sigma/impl/SigmaDslImpl.scala b/sc/shared/src/main/scala/special/sigma/impl/SigmaDslImpl.scala index 8da36ce6cf..70fb35c329 100644 --- a/sc/shared/src/main/scala/special/sigma/impl/SigmaDslImpl.scala +++ b/sc/shared/src/main/scala/special/sigma/impl/SigmaDslImpl.scala @@ -22,19 +22,16 @@ import BigInt._ import Box._ import Coll._ import CollBuilder._ -import Context._ import GroupElement._ import Header._ import PreHeader._ -import SigmaDslBuilder._ import SigmaProp._ import WOption._ -import WRType._ + object BigInt extends EntityObject("BigInt") { // entityConst: single const for each entity import Liftables._ - import scala.reflect.{ClassTag, classTag} type SBigInt = sigma.BigInt case class BigIntConst( constValue: SBigInt @@ -1918,7 +1915,6 @@ object SigmaDslBuilder extends EntityObject("SigmaDslBuilder") { } override def substConstants[T](scriptBytes: Ref[Coll[Byte]], positions: Ref[Coll[Int]], newValues: Ref[Coll[T]]): Ref[Coll[Byte]] = { - implicit val eT = newValues.eA asRep[Coll[Byte]](mkMethodCall(self, SigmaDslBuilderClass.getMethod("substConstants", classOf[Sym], classOf[Sym], classOf[Sym]), Array[AnyRef](scriptBytes, positions, newValues), @@ -2078,7 +2074,6 @@ object SigmaDslBuilder extends EntityObject("SigmaDslBuilder") { } def substConstants[T](scriptBytes: Ref[Coll[Byte]], positions: Ref[Coll[Int]], newValues: Ref[Coll[T]]): Ref[Coll[Byte]] = { - implicit val eT = newValues.eA asRep[Coll[Byte]](mkMethodCall(source, SigmaDslBuilderClass.getMethod("substConstants", classOf[Sym], classOf[Sym], classOf[Sym]), Array[AnyRef](scriptBytes, positions, newValues), @@ -2281,16 +2276,6 @@ object SigmaDslBuilder extends EntityObject("SigmaDslBuilder") { def unapply(exp: Sym): Nullable[(Ref[SigmaDslBuilder], Ref[GroupElement], Ref[GroupElement], Ref[GroupElement], Ref[GroupElement])] = unapply(exp.node) } - object groupGenerator { - def unapply(d: Def[_]): Nullable[Ref[SigmaDslBuilder]] = d match { - case MethodCall(receiver, method, _, _) if method.getName == "groupGenerator" && receiver.elem.isInstanceOf[SigmaDslBuilderElem[_]] => - val res = receiver - Nullable(res).asInstanceOf[Nullable[Ref[SigmaDslBuilder]]] - case _ => Nullable.None - } - def unapply(exp: Sym): Nullable[Ref[SigmaDslBuilder]] = unapply(exp.node) - } - object substConstants { def unapply(d: Def[_]): Nullable[(Ref[SigmaDslBuilder], Ref[Coll[Byte]], Ref[Coll[Int]], Ref[Coll[T]]) forSome {type T}] = d match { case MethodCall(receiver, method, args, _) if method.getName == "substConstants" && receiver.elem.isInstanceOf[SigmaDslBuilderElem[_]] => diff --git a/sc/shared/src/test/scala/scalan/LibraryTests.scala b/sc/shared/src/test/scala/scalan/LibraryTests.scala index e082e9154d..d095a2f20a 100644 --- a/sc/shared/src/test/scala/scalan/LibraryTests.scala +++ b/sc/shared/src/test/scala/scalan/LibraryTests.scala @@ -8,7 +8,7 @@ class Benchmark[T <: Scalan](createContext: => T) { def run() = { val (ctx, total) = measureTime { var ctx = createContext - measure(10000, okShowIterTime = printDebugInfo, okShowTotalTime = printDebugInfo) { i => + measure(10000, okShowIterTime = printDebugInfo, okShowTotalTime = printDebugInfo) { _ => ctx = createContext } ctx diff --git a/sc/shared/src/test/scala/sigma/SigmaDslStaginTests.scala b/sc/shared/src/test/scala/sigma/SigmaDslStaginTests.scala index 5ac9b80889..91178b2b67 100644 --- a/sc/shared/src/test/scala/sigma/SigmaDslStaginTests.scala +++ b/sc/shared/src/test/scala/sigma/SigmaDslStaginTests.scala @@ -28,8 +28,8 @@ class SigmaDslStaginTests extends BaseCtxTests with ErgoScriptTestkit with BaseL type RContext = cake.Context type RBox = cake.Box type RSigmaProp = cake.SigmaProp - val boxA1 = newAliceBox(1, 100) - val boxA2 = newAliceBox(2, 200) + val boxA1 = newAliceBox(100) + val boxA2 = newAliceBox(200) val ctx: SContext = newContext(10, boxA1, VersionContext.MaxSupportedScriptVersion, VersionContext.MaxSupportedScriptVersion) .withInputs(boxA2) .withVariables(Map(1 -> toAnyValue(30), 2 -> toAnyValue(40))) diff --git a/sc/shared/src/test/scala/sigmastate/ErgoTreeSpecification.scala b/sc/shared/src/test/scala/sigmastate/ErgoTreeSpecification.scala index 0b3e275985..b0b6273fad 100644 --- a/sc/shared/src/test/scala/sigmastate/ErgoTreeSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/ErgoTreeSpecification.scala @@ -332,7 +332,6 @@ class ErgoTreeSpecification extends SigmaDslTesting with ContractsTestkit { ), true) }, - { // SBigInt inherit methods from SNumericType.methods // however they are not resolvable via SBigInt.typeId import SNumericTypeMethods._ diff --git a/sc/shared/src/test/scala/sigmastate/SoftForkabilitySpecification.scala b/sc/shared/src/test/scala/sigmastate/SoftForkabilitySpecification.scala index bca2d0e638..c8b9f06399 100644 --- a/sc/shared/src/test/scala/sigmastate/SoftForkabilitySpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/SoftForkabilitySpecification.scala @@ -29,7 +29,7 @@ class SoftForkabilitySpecification extends SigmaTestingData with CompilerTestingCommons with BeforeAndAfterAll { - implicit lazy val IR: TestingIRContext = new TestingIRContext + val IR: TestingIRContext = new TestingIRContext lazy val prover = new ErgoLikeTestProvingInterpreter() lazy val verifier = new ErgoLikeTestInterpreter val deadline = 100 @@ -38,7 +38,7 @@ class SoftForkabilitySpecification extends SigmaTestingData lazy val booleanPropV1 = compile(emptyEnv + ("deadline" -> deadline), """{ | HEIGHT > deadline && OUTPUTS.size == 1 - |}""".stripMargin).asBoolValue + |}""".stripMargin)(IR).asBoolValue // cast Boolean typed prop to SigmaProp (which is invalid) // ErgoTree v0 lazy val invalidPropV1: ErgoTree = diff --git a/sc/shared/src/test/scala/sigmastate/TestingInterpreterSpecification.scala b/sc/shared/src/test/scala/sigmastate/TestingInterpreterSpecification.scala index fe5a678679..446f1972a7 100644 --- a/sc/shared/src/test/scala/sigmastate/TestingInterpreterSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/TestingInterpreterSpecification.scala @@ -22,15 +22,12 @@ import scala.util.Random class TestingInterpreterSpecification extends CompilerTestingCommons with CompilerCrossVersionProps with BeforeAndAfterAll { - implicit lazy val IR: TestingIRContext = new TestingIRContext - lazy val prover = new ErgoLikeTestProvingInterpreter() { - } + val IR: TestingIRContext = new TestingIRContext - lazy val verifier = new ErgoLikeTestInterpreter { - } + lazy val prover = new ErgoLikeTestProvingInterpreter() - implicit val soundness: Int = CryptoConstants.soundnessBits + lazy val verifier = new ErgoLikeTestInterpreter def testingContext(h: Int) = ErgoLikeContextTesting(h, @@ -128,7 +125,7 @@ class TestingInterpreterSpecification extends CompilerTestingCommons "box1" -> testBox(10, TrueTree, 0, Seq(), Map( reg1 -> IntArrayConstant(Array[Int](1, 2, 3)), reg2 -> BoolArrayConstant(Array[Boolean](true, false, true))))) - val prop = mkTestErgoTree(compile(env, code).asBoolValue.toSigmaProp) + val prop = mkTestErgoTree(compile(env, code)(IR).asBoolValue.toSigmaProp) val challenge = Array.fill(32)(Random.nextInt(100).toByte) val proof1 = prover.prove(prop, ctx, challenge).get.proof verifier.verify(Interpreter.emptyEnv, prop, ctx, proof1, challenge) diff --git a/sc/shared/src/test/scala/sigmastate/eval/ErgoScriptTestkit.scala b/sc/shared/src/test/scala/sigmastate/eval/ErgoScriptTestkit.scala index abbed09992..a10a717d2f 100644 --- a/sc/shared/src/test/scala/sigmastate/eval/ErgoScriptTestkit.scala +++ b/sc/shared/src/test/scala/sigmastate/eval/ErgoScriptTestkit.scala @@ -21,7 +21,7 @@ import sigmastate.CompilerTestsBase import sigma.{ContractsTestkit, Context => DContext} import scala.annotation.unused -import scala.util.Success +import scala.util.{Success, Try} trait ErgoScriptTestkit extends ContractsTestkit with LangTests with ValidationSpecification with CompilerTestsBase { self: BaseCtxTests => @@ -54,9 +54,8 @@ trait ErgoScriptTestkit extends ContractsTestkit with LangTests ergoCtx } - - lazy val boxA1 = newAliceBox(1, 100) - lazy val boxA2 = newAliceBox(2, 200) + lazy val boxA1 = newAliceBox(100) + lazy val boxA2 = newAliceBox(200) lazy val n1Sym = liftConst(n1) @@ -147,6 +146,31 @@ trait ErgoScriptTestkit extends ContractsTestkit with LangTests res } + private val SigmaM = SigmaProp.SigmaPropMethods + + /** Finds SigmaProp.isProven method calls in the given Lambda `f` */ + private def findIsProven[T](f: Ref[Context => T]): Option[Sym] = { + val Def(Lambda(lam,_,_,_)) = f + val s = lam.flatSchedule.find(sym => sym.node match { + case SigmaM.isValid(_) => true + case _ => false + }) + s + } + + /** Checks that if SigmaProp.isProven method calls exists in the given Lambda's schedule, + * then it is the last operation. */ + private def verifyIsProven[T](f: Ref[Context => T]): Try[Unit] = { + val isProvenOpt = findIsProven(f) + Try { + isProvenOpt match { + case Some(s) => + if (f.getLambda.y != s) !!!(s"Sigma.isProven found in none-root position", s) + case None => + } + } + } + def doReduce(): Unit = { val res = doCosting verifyIsProven(res.compiledGraph) shouldBe Success(()) @@ -183,13 +207,6 @@ trait ErgoScriptTestkit extends ContractsTestkit with LangTests } } - def Case(env: ScriptEnv, name: String, script: String, ctx: ErgoLikeContext, - calc: Ref[Context] => Ref[Any], - tree: SValue, - result: Result) = - EsTestCase(name, env, Code(script), Option(ctx), None, - Option(calc), Option(tree), result) - def reduce(env: ScriptEnv, name: String, script: String, ergoCtx: ErgoLikeContext, expectedResult: Any): Unit = { val tcase = EsTestCase(name, env, Code(script), Some(ergoCtx), expectedResult = Result(expectedResult)) tcase.doReduce() diff --git a/sc/shared/src/test/scala/sigmastate/eval/EvaluationTest.scala b/sc/shared/src/test/scala/sigmastate/eval/EvaluationTest.scala index 5fcbd0f220..f9a7edf0cb 100644 --- a/sc/shared/src/test/scala/sigmastate/eval/EvaluationTest.scala +++ b/sc/shared/src/test/scala/sigmastate/eval/EvaluationTest.scala @@ -81,24 +81,6 @@ class EvaluationTest extends BaseCtxTests | f(SELF) || g(SELF.R5[Coll[Int]].get) | }""".stripMargin, ctx, true) } - - test("Measure IRContext creation speed") { - var ctx: RuntimeIRContext = new RuntimeIRContext - measure(100, okShowIterTime = printDebugInfo, okShowTotalTime = printDebugInfo) { i => - ctx = new RuntimeIRContext - } - printDebug(s"Def count: ${ctx.defCount}") - /* - Iter 0: 4 ms - ... - Iter 96: 2 ms - Iter 97: 1 ms - Iter 98: 2 ms - Iter 99: 2 ms - Total time: 244 ms - Def count: 20 - */ - } test("SubstConst") { def script(pk: ProveDlog): SigmaPropValue = diff --git a/sc/shared/src/test/scala/sigmastate/eval/MeasureIRContext.scala b/sc/shared/src/test/scala/sigmastate/eval/MeasureIRContext.scala deleted file mode 100644 index 9f88588cc9..0000000000 --- a/sc/shared/src/test/scala/sigmastate/eval/MeasureIRContext.scala +++ /dev/null @@ -1,36 +0,0 @@ -package sigmastate.eval - -import scalan.{BaseCtxTests, Benchmark} -import sigma.util.BenchmarkUtil.measure - -object MeasureIRContext extends App { - var ctx: RuntimeIRContext = null - measure(1, false) { i => - ctx = new RuntimeIRContext - } - measure(10000, false) { i => - ctx = new RuntimeIRContext - } - print(s"Def count: ${ctx.defCount}") - /* - Total time: 2485 ms - Total time: 2714 ms - Def count: 20 - */ -} - -class SigmaLibraryTests extends BaseCtxTests { - - test("Benchmark SigmaLibrary creation time") { - new Benchmark(new RuntimeIRContext).run() - } -} - -object MeasureSigmaLibraryCreate extends App { - new Benchmark(new RuntimeIRContext).run() - /* - Total time: 12932 ms - Def count: 20, total: 15774 msec - */ -} - diff --git a/sc/shared/src/test/scala/sigmastate/helpers/CompilerTestingCommons.scala b/sc/shared/src/test/scala/sigmastate/helpers/CompilerTestingCommons.scala index 332ee902a2..6c3708b782 100644 --- a/sc/shared/src/test/scala/sigmastate/helpers/CompilerTestingCommons.scala +++ b/sc/shared/src/test/scala/sigmastate/helpers/CompilerTestingCommons.scala @@ -29,8 +29,7 @@ trait CompilerTestingCommons extends TestingCommons with TestUtils with TestContexts with ValidationSpecification with CompilerTestsBase { - class TestingIRContext extends TestContext with IRContext { - } + class TestingIRContext extends TestContext with IRContext case class CompiledFunc[A,B] (script: String, bindings: Seq[VarBinding], expr: SValue, compiledTree: SValue, func: A => (B, CostDetails)) diff --git a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala index 346ad69e1a..79701d6e07 100644 --- a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala @@ -5,7 +5,7 @@ import org.ergoplatform._ import sigma.Extensions.ArrayOps import sigma.ast.SCollection.SByteArray import sigma.ast.SType.AnyOps -import sigma.data.{AvlTreeData, CAnyValue} +import sigma.data.{AvlTreeData, CAnyValue, CSigmaDslBuilder} import sigma.util.StringUtil._ import sigma.ast._ import sigma.ast.syntax._ @@ -339,7 +339,7 @@ class BasicOpsSpecification extends CompilerTestingCommons }) val dataVar = (lastExtVar + 1).toByte - val Colls = IR.sigmaDslBuilderValue.Colls + val Colls = CSigmaDslBuilder.Colls implicit val eAny = sigma.AnyType val data = Colls.fromItems((Array[Byte](1,2,3).toColl, 10L)) val env1 = env + ("dataVar" -> CAnyValue(dataVar)) diff --git a/sdk/shared/src/main/scala/org/ergoplatform/sdk/Extensions.scala b/sdk/shared/src/main/scala/org/ergoplatform/sdk/Extensions.scala index c8fb2e57f8..320aae5919 100644 --- a/sdk/shared/src/main/scala/org/ergoplatform/sdk/Extensions.scala +++ b/sdk/shared/src/main/scala/org/ergoplatform/sdk/Extensions.scala @@ -13,29 +13,6 @@ import scala.reflect.ClassTag object Extensions { - implicit class GenIterableOps[A, Source[X] <: GenIterable[X]](val xs: Source[A]) extends AnyVal { - - /** Apply m for each element of this collection, group by key and reduce each group - * using r. - * Note, the ordering of the resulting keys is deterministic and the keys appear in - * the order they first produced by `map`. - * - * @returns one item for each group in a new collection of (K,V) pairs. */ - def mapReduce[K, V](map: A => (K, V))(reduce: (V, V) => V) - (implicit cbf: BuildFrom[Source[A], (K, V), Source[(K, V)]]): Source[(K, V)] = { - val result = scala.collection.mutable.LinkedHashMap.empty[K, V] - xs.foreach { x => - val (key, value) = map(x) - val reduced = if (result.contains(key)) reduce(result(key), value) else value - result.update(key, reduced) - } - - val b = cbf.newBuilder(xs) - for ( kv <- result ) b += kv - b.result() - } - } - implicit class CollOps[A](val coll: Coll[A]) extends AnyVal { /** Partitions this $coll in two $colls according to a predicate. @@ -205,7 +182,4 @@ object Extensions { } } - implicit class DoubleOps(val i: Double) extends AnyVal { - def erg: Long = (i * 1000000000L).toLong - } } diff --git a/sdk/shared/src/test/scala/org/ergoplatform/sdk/ExtensionsSpec.scala b/sdk/shared/src/test/scala/org/ergoplatform/sdk/ExtensionsSpec.scala index 98f61331bb..1f3c8d9064 100644 --- a/sdk/shared/src/test/scala/org/ergoplatform/sdk/ExtensionsSpec.scala +++ b/sdk/shared/src/test/scala/org/ergoplatform/sdk/ExtensionsSpec.scala @@ -4,7 +4,8 @@ import org.scalatest.matchers.should.Matchers import org.scalatest.propspec.AnyPropSpec import org.scalatestplus.scalacheck.ScalaCheckPropertyChecks import sigma.{Coll, CollGens} -import org.ergoplatform.sdk.Extensions.{CollBuilderOps, CollOps, GenIterableOps, PairCollOps} +import org.ergoplatform.sdk.Extensions.{CollBuilderOps, CollOps, PairCollOps} +import sigma.Extensions.ArrayOps import sigma.data.{CSigmaDslBuilder, RType} class ExtensionsSpec extends AnyPropSpec with ScalaCheckPropertyChecks with Matchers with CollGens { @@ -13,10 +14,6 @@ class ExtensionsSpec extends AnyPropSpec with ScalaCheckPropertyChecks with Matc val items: Iterable[(Int, String)] = Array((1, "a"), (2, "b"), (1, "c")) - property("Traversable.mapReduce") { - val res = items.mapReduce(p => (p._1, p._2))((v1, v2) => v1 + v2) - assertResult(List((1, "ac"), (2, "b")))(res) - } property("Coll.partition") { forAll(collGen) { col: Coll[Int] => @@ -28,14 +25,14 @@ class ExtensionsSpec extends AnyPropSpec with ScalaCheckPropertyChecks with Matc } property("Coll.mapReduce") { - def m(x: Int) = (math.abs(x) % 10, x) + def m(x: Int): (Int, Int) = (math.abs(x) % 10, x) forAll(collGen) { col => val res = col.mapReduce(m, plusF) val (ks, vs) = builder.unzip(res) vs.toArray.sum shouldBe col.toArray.sum ks.length <= 10 shouldBe true - res.toArray shouldBe col.toArray.toIterable.mapReduce(m)(plus).toArray + res.toArray shouldBe col.toArray.toColl.mapReduce[Int, Int](m, plusF).toArray } } From 45325928254349f21e3ab9bae784b101ce9fd950 Mon Sep 17 00:00:00 2001 From: Alexander Slesarenko Date: Wed, 1 May 2024 12:26:42 +0100 Subject: [PATCH 046/314] es-bigint: fixes in ScalaDocs --- data/shared/src/main/scala/sigma/ast/SigmaPredef.scala | 2 +- docs/LangSpec.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/data/shared/src/main/scala/sigma/ast/SigmaPredef.scala b/data/shared/src/main/scala/sigma/ast/SigmaPredef.scala index 8edf9683f5..631f7f2d75 100644 --- a/data/shared/src/main/scala/sigma/ast/SigmaPredef.scala +++ b/data/shared/src/main/scala/sigma/ast/SigmaPredef.scala @@ -188,7 +188,7 @@ object SigmaPredef { BigIntConstant(new BigInteger(arg.value)) }), OperationInfo(Constant, - """Parsing string argument as a 256-bit signed big integer.""".stripMargin, + """Parsing string literal argument as a 256-bit signed big integer.""".stripMargin, Seq(ArgInfo("", ""))) ) diff --git a/docs/LangSpec.md b/docs/LangSpec.md index 59eacc3d80..ba66748f08 100644 --- a/docs/LangSpec.md +++ b/docs/LangSpec.md @@ -985,7 +985,7 @@ def proveDHTuple(g: GroupElement, h: GroupElement, */ def proveDlog(value: GroupElement): SigmaProp -/** Transforms Base16 encoded string literal into constant of type Coll[Byte]. +/** Transforms Base16 encoded string literal into constant of type BigInt. * It is a compile-time operation and only string literal (constant) can be its * argument. */ From 60660f20656370e0c191266604211c4866c34db7 Mon Sep 17 00:00:00 2001 From: Alexander Slesarenko Date: Thu, 2 May 2024 13:43:28 +0100 Subject: [PATCH 047/314] i956-box-in-register: moved Value to sigma-data --- .../src/main/scala/sigma/data/js/Isos.scala | 152 ++++++++++ data/js/src/main/scala/sigma/js/Box.scala | 61 ++++ data/js/src/main/scala/sigma/js/Value.scala | 266 ++++++++++++++++++ .../scala/org/ergoplatform/sdk/js/Isos.scala | 204 ++------------ .../ergoplatform/sdk/js/ProverBuilder.scala | 9 +- .../org/ergoplatform/sdk/js/SigmaProver.scala | 4 +- .../org/ergoplatform/sdk/js/IsosSpec.scala | 22 +- 7 files changed, 521 insertions(+), 197 deletions(-) create mode 100644 data/js/src/main/scala/sigma/data/js/Isos.scala create mode 100644 data/js/src/main/scala/sigma/js/Box.scala create mode 100644 data/js/src/main/scala/sigma/js/Value.scala diff --git a/data/js/src/main/scala/sigma/data/js/Isos.scala b/data/js/src/main/scala/sigma/data/js/Isos.scala new file mode 100644 index 0000000000..95bbce8bbe --- /dev/null +++ b/data/js/src/main/scala/sigma/data/js/Isos.scala @@ -0,0 +1,152 @@ +package sigma.data.js + +import org.ergoplatform.{ErgoBox, ErgoBoxCandidate} +import org.ergoplatform.ErgoBox._ +import scorex.crypto.authds.ADKey +import scorex.util.ModifierId +import scorex.util.encode.Base16 +import sigma.{Coll, Colls} +import sigmastate.fleetSdkCommon.distEsmTypesBoxesMod.{Box => FBox} +import sigmastate.fleetSdkCommon.distEsmTypesCommonMod.{Amount, HexString} +import sigmastate.fleetSdkCommon.distEsmTypesRegistersMod.NonMandatoryRegisters +import sigmastate.fleetSdkCommon.{distEsmTypesBoxesMod => boxesMod, distEsmTypesCommonMod => commonMod, distEsmTypesRegistersMod => registersMod, distEsmTypesTokenMod => tokenMod} +import sigma.Extensions._ +import sigma.ast.syntax.GroupElementConstant +import sigma.ast.{Constant, GroupElementConstant, SType} +import sigma.data.Iso.isoStringToArray +import sigma.data.{CGroupElement, Digest32Coll, Iso} +import sigma.js.GroupElement +import sigma.serialization.{ErgoTreeSerializer, ValueSerializer} + +import scala.scalajs.js + +/** Definitions of isomorphisms for sigma-data module. */ +object Isos { + + val isoStringToGroupElement: Iso[String, sigma.GroupElement] = new Iso[String, sigma.GroupElement] { + override def to(x: String): sigma.GroupElement = { + val bytes = Base16.decode(x).get + ValueSerializer.deserialize(bytes).asInstanceOf[GroupElementConstant].value + } + override def from(x: sigma.GroupElement): String = { + val bytes = ValueSerializer.serialize(GroupElementConstant(x)) + Base16.encode(bytes) + } + } + + val isoGroupElement: Iso[GroupElement, sigma.GroupElement] = new Iso[GroupElement, sigma.GroupElement] { + override def to(x: GroupElement): sigma.GroupElement = { + CGroupElement(x.point) + } + override def from(x: sigma.GroupElement): GroupElement = { + new GroupElement(x.asInstanceOf[CGroupElement].wrappedValue) + } + } + + implicit val isoBoxId: Iso[boxesMod.BoxId, ErgoBox.BoxId] = new Iso[boxesMod.BoxId, ErgoBox.BoxId] { + override def to(x: boxesMod.BoxId): ErgoBox.BoxId = ADKey @@@ isoStringToArray.to(x) + + override def from(x: ErgoBox.BoxId): boxesMod.BoxId = isoStringToArray.from(x) + } + + implicit val isoHexStringToConstant: Iso[HexString, Constant[SType]] = new Iso[HexString, Constant[SType]] { + override def to(x: HexString): Constant[SType] = { + val bytes = isoStringToArray.to(x) + val value = ValueSerializer.deserialize(bytes) + value.asInstanceOf[Constant[SType]] + } + override def from(x: Constant[SType]): HexString = { + val bytes = ValueSerializer.serialize(x) + isoStringToArray.from(bytes) + } + } + + + implicit val isoAmount: Iso[commonMod.Amount, Long] = new Iso[commonMod.Amount, Long] { + override def to(x: commonMod.Amount): Long = x.asInstanceOf[Any] match { + case s: String => BigInt(s).toLong + case _ => java.lang.Long.parseLong(x.asInstanceOf[js.BigInt].toString(10)) + } + override def from(x: Long): commonMod.Amount = x.toString + } + + implicit val isoToken: Iso[tokenMod.TokenAmount[commonMod.Amount], Token] = + new Iso[tokenMod.TokenAmount[commonMod.Amount], Token] { + override def to(x: tokenMod.TokenAmount[commonMod.Amount]): Token = + (Digest32Coll @@@ Colls.fromArray(Base16.decode(x.tokenId).get), isoAmount.to(x.amount)) + + override def from(x: Token): tokenMod.TokenAmount[commonMod.Amount] = + tokenMod.TokenAmount[commonMod.Amount](isoAmount.from(x._2), x._1.toHex) + } + + val isoTokenArray: Iso[js.Array[tokenMod.TokenAmount[commonMod.Amount]], Coll[Token]] = + new Iso[js.Array[tokenMod.TokenAmount[commonMod.Amount]], Coll[Token]] { + override def to(x: js.Array[tokenMod.TokenAmount[commonMod.Amount]]): Coll[Token] = { + sigma.js.Isos.isoArrayToColl(isoToken).to(x) + } + override def from(x: Coll[Token]): js.Array[tokenMod.TokenAmount[commonMod.Amount]] = { + sigma.js.Isos.isoArrayToColl(isoToken).from(x) + } + } + + val isoNonMandatoryRegisters: Iso[registersMod.NonMandatoryRegisters, AdditionalRegisters] = + new Iso[registersMod.NonMandatoryRegisters, AdditionalRegisters] { + override def to(x: registersMod.NonMandatoryRegisters): AdditionalRegisters = { + val regs = Seq( + x.R4 -> R4, + x.R5 -> R5, + x.R6 -> R6, + x.R7 -> R7, + x.R8 -> R8, + x.R9 -> R9 + ).collect { + case (regOpt, id) if regOpt.isDefined => id -> isoHexStringToConstant.to(regOpt.get) + } + Map(regs:_*) + } + override def from(regs: AdditionalRegisters): registersMod.NonMandatoryRegisters = { + def regHexOpt(t: NonMandatoryRegisterId): Option[HexString] = + regs.get(t).map(v => isoHexStringToConstant.from(v.asInstanceOf[Constant[SType]])) + + val resRegs = NonMandatoryRegisters() + regHexOpt(R4).foreach(resRegs.setR4(_)) + regHexOpt(R5).foreach(resRegs.setR5(_)) + regHexOpt(R6).foreach(resRegs.setR6(_)) + regHexOpt(R7).foreach(resRegs.setR7(_)) + regHexOpt(R8).foreach(resRegs.setR8(_)) + regHexOpt(R9).foreach(resRegs.setR9(_)) + resRegs + } + } + + implicit val isoBoxCandidate: Iso[boxesMod.BoxCandidate[commonMod.Amount, NonMandatoryRegisters], ErgoBoxCandidate] = new Iso[boxesMod.BoxCandidate[commonMod.Amount, NonMandatoryRegisters], ErgoBoxCandidate] { + override def to(x: boxesMod.BoxCandidate[commonMod.Amount, NonMandatoryRegisters]): ErgoBoxCandidate = { + val ergoBoxCandidate = new ErgoBoxCandidate( + value = isoAmount.to(x.value), + ergoTree = { + val bytes = Base16.decode(x.ergoTree).get + ErgoTreeSerializer.DefaultSerializer.deserializeErgoTree(bytes) + }, + x.creationHeight.toInt, + additionalTokens = isoTokenArray.to(x.assets), + additionalRegisters = isoNonMandatoryRegisters.to(x.additionalRegisters) + ) + ergoBoxCandidate + } + + override def from(x: ErgoBoxCandidate): boxesMod.BoxCandidate[commonMod.Amount, NonMandatoryRegisters] = { + val ergoTree = ErgoTreeSerializer.DefaultSerializer.serializeErgoTree(x.ergoTree) + val ergoTreeStr = Base16.encode(ergoTree) + val assets = isoTokenArray.from(x.additionalTokens) + boxesMod.BoxCandidate[commonMod.Amount, NonMandatoryRegisters]( + ergoTree = ergoTreeStr, + value = isoAmount.from(x.value), + assets = assets, + creationHeight = x.creationHeight, + additionalRegisters = isoNonMandatoryRegisters.from(x.additionalRegisters) + ) + } + } + + +} diff --git a/data/js/src/main/scala/sigma/js/Box.scala b/data/js/src/main/scala/sigma/js/Box.scala new file mode 100644 index 0000000000..209e15d489 --- /dev/null +++ b/data/js/src/main/scala/sigma/js/Box.scala @@ -0,0 +1,61 @@ +package sigma.js + +import org.ergoplatform.ErgoBox +import scorex.util.ModifierId +import scorex.util.encode.Base16 +import sigma.data.Iso +import sigma.data.js.Isos.{isoAmount, isoNonMandatoryRegisters, isoTokenArray} +import sigma.serialization.ErgoTreeSerializer +import sigmastate.fleetSdkCommon.distEsmTypesBoxesMod.{Box => FBox} +import sigmastate.fleetSdkCommon.distEsmTypesCommonMod.Amount +import sigmastate.fleetSdkCommon.distEsmTypesRegistersMod.NonMandatoryRegisters +import sigmastate.fleetSdkCommon.{distEsmTypesCommonMod => commonMod} + +import scala.scalajs.js +import scala.scalajs.js.annotation.JSExportTopLevel + +/** Equivalent of [[sigma.Box]] available from JS. */ +@JSExportTopLevel("Box") +class Box(val box: FBox[Amount, NonMandatoryRegisters]) extends js.Object { +} + +@JSExportTopLevel("Box$") +object Box extends js.Object { + + /** Converts Fleet box to ErgoBox and back. */ + val isoBox: Iso[FBox[commonMod.Amount, NonMandatoryRegisters], ErgoBox] = new Iso[FBox[commonMod.Amount, NonMandatoryRegisters], ErgoBox] { + override def to(x: FBox[commonMod.Amount, NonMandatoryRegisters]): ErgoBox = { + val ergoBox = new ErgoBox( + value = isoAmount.to(x.value), + ergoTree = { + val bytes = Base16.decode(x.ergoTree).get + ErgoTreeSerializer.DefaultSerializer.deserializeErgoTree(bytes) + }, + creationHeight = x.creationHeight.toInt, + additionalTokens = isoTokenArray.to(x.assets), + additionalRegisters = isoNonMandatoryRegisters.to(x.additionalRegisters), + transactionId = ModifierId @@ x.transactionId, + index = x.index.toShort + ) + ergoBox + } + + override def from(x: ErgoBox): FBox[commonMod.Amount, NonMandatoryRegisters] = { + val ergoTree = ErgoTreeSerializer.DefaultSerializer.serializeErgoTree(x.ergoTree) + val ergoTreeStr = Base16.encode(ergoTree) + val assets = isoTokenArray.from(x.additionalTokens) + FBox[commonMod.Amount, NonMandatoryRegisters]( + boxId = Base16.encode(x.id), + ergoTree = ergoTreeStr, + value = isoAmount.from(x.value), + assets = assets, + creationHeight = x.creationHeight, + additionalRegisters = isoNonMandatoryRegisters.from(x.additionalRegisters), + transactionId = x.transactionId, + index = x.index + ) + } + } + + +} \ No newline at end of file diff --git a/data/js/src/main/scala/sigma/js/Value.scala b/data/js/src/main/scala/sigma/js/Value.scala new file mode 100644 index 0000000000..785f9e04db --- /dev/null +++ b/data/js/src/main/scala/sigma/js/Value.scala @@ -0,0 +1,266 @@ +package sigma +package js + +import scorex.util.Extensions.{IntOps, LongOps} +import scorex.util.encode.Base16 +import sigma.ast.SType +import sigma.crypto.Platform +import sigma.data._ +import sigma.js.Value.toRuntimeData +import sigma.serialization.{CoreSerializer, DataSerializer} +import sigma.util.Extensions.BigIntOps +import sigma.{Coll, Colls, Evaluation} + +import java.math.BigInteger +import scala.scalajs.js +import scala.scalajs.js.annotation.JSExportTopLevel + +/** + * This class is used to represent any valid value of ErgoScript language. + * Any such value comes equipped with {@link Type} descriptor. + * Note, there is a distinction between JS types and ErgoScript types. + * Each Value instance represents the concrete ErgoScript type given by `tpe`. + * The implementation is based on the pre-defined mapping between JS and ES types. + * This mapping is applied recursively and is given by the following: + * + * JS type | ErgoScript Type + * -------------------------------------- + * Number | Byte + * Number | Short + * Number | Int + * BigInt | Long + * BigInt | BigInt + * array [A, B] | (A, B) - pair + * array [a1, a2 ..] | Coll[A] - collection + * + * @param data JS value wrapped in this value + * @param tpe type descriptor of the ErgoScript type + */ +@JSExportTopLevel("Value") +class Value(val data: Any, val tpe: Type) extends js.Object { + + /** Get Sigma runtime value which can be passed to interpreter, saved in register and + * [[sigma.ast.Constant]] nodes. + */ + final def runtimeData: Any = toRuntimeData(data, tpe.rtype) + + /** + * Encode this value as Base16 hex string. + * 1) it transforms this value into {@link sigma.ast.ConstantNode} of sigma. + * 2) it serializes the constant into byte array using {@link sigmastate.serialization.ConstantSerializer} + * 3) the bytes are encoded using Base16 encoder into string + * + * @return hex string of serialized bytes + */ + def toHex(): String = { + val stype = Evaluation.rtypeToSType(tpe.rtype) + val value = runtimeData.asInstanceOf[SType#WrappedType] + val w = CoreSerializer.startWriter() + w.putType(stype) + DataSerializer.serialize(value, stype, w) + Base16.encode(w.toBytes) + } +} + +@JSExportTopLevel("Value$") +object Value extends js.Object { + /** Maximal positive value of ES type Long */ + val MaxLong = js.BigInt("0x7fffffffffffffff") + + /** Minimal negative value of ES type Long */ + val MinLong = -js.BigInt("0x8000000000000000") + + /** Helper method to get Sigma runtime value which can be passed to interpreter, saved + * in register and [[sigma.ast.Constant]] nodes. + */ + final private[js] def toRuntimeData(data: Any, rtype: RType[_]): Any = rtype match { + case sigma.BooleanType => data + case sigma.ByteType | sigma.ShortType | sigma.IntType => data + case sigma.LongType => java.lang.Long.parseLong(data.asInstanceOf[js.BigInt].toString(10)) + case sigma.BigIntRType => + val v = data.asInstanceOf[js.BigInt] + CBigInt(new BigInteger(v.toString(16), 16)) + case sigma.GroupElementRType => + val ge = data.asInstanceOf[GroupElement] + CGroupElement(ge.point) + case sigma.SigmaPropRType => + val p = data.asInstanceOf[SigmaProp] + CSigmaProp(p.sigmaBoolean) + case sigma.AvlTreeRType => + val t = data.asInstanceOf[AvlTree] + AvlTree.isoAvlTree.to(t) + case sigma.BoxRType => + val t = data.asInstanceOf[Box] + CBox(Box.isoBox.to(t.box)) + case ct: CollType[a] => + val xs = data.asInstanceOf[js.Array[Any]] + implicit val cT = ct.tItem.classTag + val items = xs.map(x => toRuntimeData(x, ct.tItem).asInstanceOf[a]).toArray[a] + Colls.fromItems(items:_*)(ct.tItem) + case pt: PairType[a, b] => + val p = data.asInstanceOf[js.Array[Any]] + val x = toRuntimeData(p(0), pt.tFst).asInstanceOf[a] + val y = toRuntimeData(p(1), pt.tSnd).asInstanceOf[b] + (x, y) + case sigma.UnitType => data + case _ => + throw new IllegalArgumentException(s"Unsupported type $rtype") + } + + /** Helper method to extract JS data value from Sigma runtime value. + * This should be inverse to `toRuntimeData`. + * + * @param value runtime value of type given by `rtype` + * @param rtype type descriptor of Sigma runtime value + */ + final def fromRuntimeData(value: Any, rtype: RType[_]): Any = rtype match { + case sigma.BooleanType => value + case sigma.ByteType | sigma.ShortType | sigma.IntType => value + case sigma.LongType => js.BigInt(value.asInstanceOf[Long].toString) + case sigma.BigIntRType => + val hex = value.asInstanceOf[sigma.BigInt].toBigInteger.toString(10) + js.BigInt(hex) + case sigma.GroupElementRType => + val point = value.asInstanceOf[CGroupElement].wrappedValue.asInstanceOf[Platform.Ecp] + new GroupElement(point) + case sigma.SigmaPropRType => + new SigmaProp(value.asInstanceOf[CSigmaProp].wrappedValue) + case sigma.AvlTreeRType => + AvlTree.isoAvlTree.from(value.asInstanceOf[CAvlTree]) + case sigma.BoxRType => + AvlTree.isoAvlTree.from(value.asInstanceOf[CAvlTree]) + case ct: CollType[a] => + val arr = value.asInstanceOf[Coll[a]].toArray + js.Array(arr.map(x => fromRuntimeData(x, ct.tItem)):_*) + case pt: PairType[a, b] => + val p = value.asInstanceOf[(a, b)] + js.Array(fromRuntimeData(p._1, pt.tFst), fromRuntimeData(p._2, pt.tSnd)) + case sigma.UnitType => value + case _ => + throw new IllegalArgumentException(s"Unsupported type $rtype") + } + + /** Helper method to check validity of JS data value against the given runtime type. + * + * @param data js value + * @param rtype type descriptor of Sigma runtime value + */ + final private def checkJsData[T](data: T, rtype: RType[_]): Any = rtype match { + case sigma.ByteType => data.asInstanceOf[Int].toByteExact + case sigma.ShortType => data.asInstanceOf[Int].toShortExact + case sigma.IntType => data.asInstanceOf[Int].toLong.toIntExact + case sigma.LongType => + val n = data.asInstanceOf[js.BigInt] + if (n < MinLong || n > MaxLong) + throw new ArithmeticException(s"value $n is out of long range") + n + case sigma.BigIntRType => + data.asInstanceOf[js.BigInt] + case sigma.GroupElementRType => + data.asInstanceOf[GroupElement] + case sigma.SigmaPropRType => + data.asInstanceOf[SigmaProp] + case PairType(l, r) => data match { + case arr: js.Array[Any @unchecked] => + checkJsData(arr(0), l) + checkJsData(arr(1), r) + data + case _ => + throw new ArithmeticException(s"$data cannot represent pair value") + } + case CollType(elemType) => data match { + case arr: js.Array[Any @unchecked] => + arr.foreach(x => checkJsData(x, elemType)) + data + case _ => + throw new ArithmeticException(s"$data cannot represent Coll value") + } + case _ => + throw new IllegalArgumentException(s"Unsupported type $rtype") + } + + /** Create Byte value from JS number. */ + def ofByte(n: Int): Value = { + checkJsData(n, Type.Byte.rtype) + new Value(n, Type.Byte) + } + + /** Create Short value from JS number. */ + def ofShort(n: Int): Value = { + checkJsData(n, Type.Short.rtype) + new Value(n, Type.Short) + } + + /** Create Int value from JS number. */ + def ofInt(n: Int): Value = { + checkJsData(n, Type.Int.rtype) + new Value(n, Type.Int) + } + + /** Create Long value from JS BigInt. */ + def ofLong(n: js.BigInt): Value = { + checkJsData(n, Type.Long.rtype) + new Value(n, Type.Long) + } + + /** Create BigInt value from JS BigInt. */ + def ofBigInt(n: js.BigInt): Value = { + checkJsData(n, Type.BigInt.rtype) + new Value(n, Type.BigInt) + } + + /** Creates a Value of GroupElement type from [[sigmastate.crypto.Platform.Point]] hex. + * @param pointHex hex of ASN representation of [[sigmastate.crypto.Platform.Point]] + */ + def ofGroupElement(pointHex: String): Value = { + val ge = GroupElement.fromPointHex(pointHex) + new Value(ge, Type.GroupElement) + } + + /** Creates a Value of SigmaProp type from [[sigmastate.crypto.Platform.Point]] hex. + * @param pointHex hex of ASN representation of [[sigmastate.crypto.Platform.Point]] + */ + def ofSigmaProp(pointHex: String): Value = { + val sp = SigmaProp.fromPointHex(pointHex) + new Value(sp, Type.SigmaProp) + } + + /** Create Pair value from two values. */ + def pairOf(l: Value, r: Value): Value = { + val data = js.Array(l.data, r.data) // the l and r data have been validated + new Value(data, Type.pairType(l.tpe, r.tpe)) + } + + /** Create Coll value from array and element type descriptor. + * @param items collection elements which should be valid JS representation of `elemType` + * @param elemType descriptor of types for collection elements + */ + def collOf(items: js.Array[Any], elemType: Type): Value = { + val t = Type.collType(elemType) + checkJsData(items, t.rtype) + new Value(items, t) + } + + /** + * Creates Value from hex encoded serialized bytes of Constant values. + *

+ * In order to create Value you need to provide both value instance and + * Type descriptor. This is similar to how values are represented in sigma + * ConstantNode. Each ConstantNode also have value instance and `tpe: SType` + * descriptor. + * @param hex the string is obtained as hex encoding of serialized ConstantNode. + * (The bytes obtained by ConstantSerializer in sigma) + * @return new deserialized Value instance containing: + * - suitable JS value in its `data` field + * - and [[Type]] descriptor in its `tpe` field + */ + def fromHex(hex: String): Value = { + val bytes = Base16.decode(hex).fold(t => throw t, identity) + val r = CoreSerializer.startReader(bytes) + val stype = r.getType() + val value = DataSerializer.deserialize(stype, r) + val rtype = Evaluation.stypeToRType(stype) + val jsvalue = Value.fromRuntimeData(value, rtype) + new Value(jsvalue, new Type(rtype)) + } +} diff --git a/sdk/js/src/main/scala/org/ergoplatform/sdk/js/Isos.scala b/sdk/js/src/main/scala/org/ergoplatform/sdk/js/Isos.scala index f6393f62bb..f4085cf2a9 100644 --- a/sdk/js/src/main/scala/org/ergoplatform/sdk/js/Isos.scala +++ b/sdk/js/src/main/scala/org/ergoplatform/sdk/js/Isos.scala @@ -24,52 +24,14 @@ import sigmastate.fleetSdkCommon.distEsmTypesRegistersMod.NonMandatoryRegisters import sigmastate.fleetSdkCommon.distEsmTypesTokenMod.TokenAmount import sigmastate.fleetSdkCommon.distEsmTypesTransactionsMod.{SignedTransaction, UnsignedTransaction} import sigmastate.fleetSdkCommon.{distEsmTypesBoxesMod => boxesMod, distEsmTypesCommonMod => commonMod, distEsmTypesContextExtensionMod => contextExtensionMod, distEsmTypesInputsMod => inputsMod, distEsmTypesProverResultMod => proverResultMod, distEsmTypesRegistersMod => registersMod, distEsmTypesTokenMod => tokenMod} - +import sigma.data.js.{Isos => DataIsos} import java.math.BigInteger import scala.collection.immutable.ListMap import scala.scalajs.js import scala.scalajs.js.Object -/** Definitions of isomorphisms. */ +/** Definitions of isomorphisms for sigma-sdk module. */ object Isos { - val isoStringToGroupElement: Iso[String, sigma.GroupElement] = new Iso[String, sigma.GroupElement] { - override def to(x: String): sigma.GroupElement = { - val bytes = Base16.decode(x).get - ValueSerializer.deserialize(bytes).asInstanceOf[GroupElementConstant].value - } - override def from(x: sigma.GroupElement): String = { - val bytes = ValueSerializer.serialize(GroupElementConstant(x)) - Base16.encode(bytes) - } - } - - val isoGroupElement: Iso[GroupElement, sigma.GroupElement] = new Iso[GroupElement, sigma.GroupElement] { - override def to(x: GroupElement): sigma.GroupElement = { - CGroupElement(x.point) - } - override def from(x: sigma.GroupElement): GroupElement = { - new GroupElement(x.asInstanceOf[CGroupElement].wrappedValue) - } - } - - implicit val isoBoxId: Iso[boxesMod.BoxId, ErgoBox.BoxId] = new Iso[boxesMod.BoxId, ErgoBox.BoxId] { - override def to(x: boxesMod.BoxId): ErgoBox.BoxId = ADKey @@@ isoStringToArray.to(x) - - override def from(x: ErgoBox.BoxId): boxesMod.BoxId = isoStringToArray.from(x) - } - - implicit val isoHexStringToConstant: Iso[HexString, Constant[SType]] = new Iso[HexString, Constant[SType]] { - override def to(x: HexString): Constant[SType] = { - val bytes = isoStringToArray.to(x) - val value = ValueSerializer.deserialize(bytes) - value.asInstanceOf[Constant[SType]] - } - override def from(x: Constant[SType]): HexString = { - val bytes = ValueSerializer.serialize(x) - isoStringToArray.from(bytes) - } - } - implicit val isoHeader: Iso[Header, sigma.Header] = new Iso[Header, sigma.Header] { override def to(a: Header): sigma.Header = { CHeader( @@ -83,8 +45,8 @@ object Isos { nBits = sigma.js.Isos.isoBigIntToLong.to(a.nBits), height = a.height, extensionRoot = isoStringToColl.to(a.extensionRoot), - minerPk = isoGroupElement.to(a.minerPk), - powOnetimePk = isoGroupElement.to(a.powOnetimePk), + minerPk = DataIsos.isoGroupElement.to(a.minerPk), + powOnetimePk = DataIsos.isoGroupElement.to(a.powOnetimePk), powNonce = isoStringToColl.to(a.powNonce), powDistance = sigma.js.Isos.isoBigInt.to(a.powDistance), votes = isoStringToColl.to(a.votes) @@ -103,8 +65,8 @@ object Isos { nBits = sigma.js.Isos.isoBigIntToLong.from(header.nBits), height = header.height, extensionRoot = isoStringToColl.from(header.extensionRoot), - minerPk = isoGroupElement.from(header.minerPk), - powOnetimePk = isoGroupElement.from(header.powOnetimePk), + minerPk = DataIsos.isoGroupElement.from(header.minerPk), + powOnetimePk = DataIsos.isoGroupElement.from(header.powOnetimePk), powNonce = isoStringToColl.from(header.powNonce), powDistance = sigma.js.Isos.isoBigInt.from(header.powDistance), votes = isoStringToColl.from(header.votes) @@ -120,7 +82,7 @@ object Isos { timestamp = sigma.js.Isos.isoBigIntToLong.to(a.timestamp), nBits = sigma.js.Isos.isoBigIntToLong.to(a.nBits), height = a.height, - minerPk = isoGroupElement.to(a.minerPk), + minerPk = DataIsos.isoGroupElement.to(a.minerPk), votes = isoStringToColl.to(a.votes) ) } @@ -132,7 +94,7 @@ object Isos { timestamp = sigma.js.Isos.isoBigIntToLong.from(header.timestamp), nBits = sigma.js.Isos.isoBigIntToLong.from(header.nBits), height = header.height, - minerPk = isoGroupElement.from(header.minerPk), + minerPk = DataIsos.isoGroupElement.from(header.minerPk), votes = isoStringToColl.from(header.votes) ) } @@ -195,7 +157,7 @@ object Isos { val keys = js.Object.keys(x).sorted for ( k <- keys ) { val id = k.toInt.toByte - val c = isoHexStringToConstant.to(x.apply(id).get.get) + val c = DataIsos.isoHexStringToConstant.to(x.apply(id).get.get) map = map + (id -> c) } ContextExtension(map) @@ -204,7 +166,7 @@ object Isos { override def from(x: ContextExtension): contextExtensionMod.ContextExtension = { val res = new Object().asInstanceOf[contextExtensionMod.ContextExtension] x.values.foreach { case (k, v: Constant[_]) => - val hex = isoHexStringToConstant.from(v) + val hex = DataIsos.isoHexStringToConstant.from(v) res.update(k, hex) } res @@ -213,10 +175,10 @@ object Isos { implicit val isoUnsignedInput: Iso[inputsMod.UnsignedInput, UnsignedInput] = new Iso[inputsMod.UnsignedInput, UnsignedInput] { override def to(x: inputsMod.UnsignedInput): UnsignedInput = - new UnsignedInput(x.boxId.convertTo[ErgoBox.BoxId], isoContextExtension.to(x.extension)) + new UnsignedInput(DataIsos.isoBoxId.to(x.boxId), isoContextExtension.to(x.extension)) override def from(x: UnsignedInput): inputsMod.UnsignedInput = - inputsMod.UnsignedInput(x.boxId.convertTo[boxesMod.BoxId], isoContextExtension.from(x.extension)) + inputsMod.UnsignedInput(DataIsos.isoBoxId.from(x.boxId), isoContextExtension.from(x.extension)) } implicit val isoProverResult: Iso[proverResultMod.ProverResult, ProverResult] = new Iso[proverResultMod.ProverResult, ProverResult] { @@ -236,135 +198,17 @@ object Isos { implicit val isoSignedInput: Iso[inputsMod.SignedInput, Input] = new Iso[inputsMod.SignedInput, Input] { override def to(x: inputsMod.SignedInput): Input = - Input(x.boxId.convertTo[ErgoBox.BoxId], isoProverResult.to(x.spendingProof)) + Input(DataIsos.isoBoxId.to(x.boxId), isoProverResult.to(x.spendingProof)) override def from(x: Input): inputsMod.SignedInput = - inputsMod.SignedInput(x.boxId.convertTo[boxesMod.BoxId], isoProverResult.from(x.spendingProof)) + inputsMod.SignedInput(DataIsos.isoBoxId.from(x.boxId), isoProverResult.from(x.spendingProof)) } implicit val isoDataInput: Iso[inputsMod.DataInput, DataInput] = new Iso[inputsMod.DataInput, DataInput] { - override def to(x: inputsMod.DataInput): DataInput = DataInput(x.boxId.convertTo[ErgoBox.BoxId]) - - override def from(x: DataInput): inputsMod.DataInput = inputsMod.DataInput(x.boxId.convertTo[boxesMod.BoxId]) - } + override def to(x: inputsMod.DataInput): DataInput = + DataInput(DataIsos.isoBoxId.to(x.boxId)) - implicit val isoAmount: Iso[commonMod.Amount, Long] = new Iso[commonMod.Amount, Long] { - override def to(x: commonMod.Amount): Long = x.asInstanceOf[Any] match { - case s: String => BigInt(s).toLong - case _ => java.lang.Long.parseLong(x.asInstanceOf[js.BigInt].toString(10)) - } - override def from(x: Long): commonMod.Amount = x.toString - } - - implicit val isoToken: Iso[tokenMod.TokenAmount[commonMod.Amount], Token] = - new Iso[tokenMod.TokenAmount[commonMod.Amount], Token] { - override def to(x: tokenMod.TokenAmount[commonMod.Amount]): Token = - (Digest32Coll @@@ Colls.fromArray(Base16.decode(x.tokenId).get), isoAmount.to(x.amount)) - - override def from(x: Token): tokenMod.TokenAmount[commonMod.Amount] = - tokenMod.TokenAmount[commonMod.Amount](isoAmount.from(x._2), x._1.toHex) - } - - val isoTokenArray: Iso[js.Array[tokenMod.TokenAmount[commonMod.Amount]], Coll[Token]] = - new Iso[js.Array[tokenMod.TokenAmount[commonMod.Amount]], Coll[Token]] { - override def to(x: js.Array[tokenMod.TokenAmount[commonMod.Amount]]): Coll[Token] = { - sigma.js.Isos.isoArrayToColl(isoToken).to(x) - } - override def from(x: Coll[Token]): js.Array[tokenMod.TokenAmount[commonMod.Amount]] = { - sigma.js.Isos.isoArrayToColl(isoToken).from(x) - } - } - - val isoNonMandatoryRegisters: Iso[registersMod.NonMandatoryRegisters, AdditionalRegisters] = - new Iso[registersMod.NonMandatoryRegisters, AdditionalRegisters] { - override def to(x: registersMod.NonMandatoryRegisters): AdditionalRegisters = { - val regs = Seq( - x.R4 -> R4, - x.R5 -> R5, - x.R6 -> R6, - x.R7 -> R7, - x.R8 -> R8, - x.R9 -> R9 - ).collect { - case (regOpt, id) if regOpt.isDefined => id -> isoHexStringToConstant.to(regOpt.get) - } - Map(regs:_*) - } - override def from(regs: AdditionalRegisters): registersMod.NonMandatoryRegisters = { - def regHexOpt(t: NonMandatoryRegisterId): Option[HexString] = - regs.get(t).map(v => isoHexStringToConstant.from(v.asInstanceOf[Constant[SType]])) - - val resRegs = NonMandatoryRegisters() - regHexOpt(R4).foreach(resRegs.setR4(_)) - regHexOpt(R5).foreach(resRegs.setR5(_)) - regHexOpt(R6).foreach(resRegs.setR6(_)) - regHexOpt(R7).foreach(resRegs.setR7(_)) - regHexOpt(R8).foreach(resRegs.setR8(_)) - regHexOpt(R9).foreach(resRegs.setR9(_)) - resRegs - } - } - - implicit val isoBoxCandidate: Iso[boxesMod.BoxCandidate[commonMod.Amount, NonMandatoryRegisters], ErgoBoxCandidate] = new Iso[boxesMod.BoxCandidate[commonMod.Amount, NonMandatoryRegisters], ErgoBoxCandidate] { - override def to(x: boxesMod.BoxCandidate[commonMod.Amount, NonMandatoryRegisters]): ErgoBoxCandidate = { - val ergoBoxCandidate = new ErgoBoxCandidate( - value = isoAmount.to(x.value), - ergoTree = { - val bytes = Base16.decode(x.ergoTree).get - ErgoTreeSerializer.DefaultSerializer.deserializeErgoTree(bytes) - }, - x.creationHeight.toInt, - additionalTokens = isoTokenArray.to(x.assets), - additionalRegisters = isoNonMandatoryRegisters.to(x.additionalRegisters) - ) - ergoBoxCandidate - } - - override def from(x: ErgoBoxCandidate): boxesMod.BoxCandidate[commonMod.Amount, NonMandatoryRegisters] = { - val ergoTree = ErgoTreeSerializer.DefaultSerializer.serializeErgoTree(x.ergoTree) - val ergoTreeStr = Base16.encode(ergoTree) - val assets = isoTokenArray.from(x.additionalTokens) - boxesMod.BoxCandidate[commonMod.Amount, NonMandatoryRegisters]( - ergoTree = ergoTreeStr, - value = isoAmount.from(x.value), - assets = assets, - creationHeight = x.creationHeight, - additionalRegisters = isoNonMandatoryRegisters.from(x.additionalRegisters) - ) - } - } - - val isoBox: Iso[Box[commonMod.Amount, NonMandatoryRegisters], ErgoBox] = new Iso[Box[commonMod.Amount, NonMandatoryRegisters], ErgoBox] { - override def to(x: Box[commonMod.Amount, NonMandatoryRegisters]): ErgoBox = { - val ergoBox = new ErgoBox( - value = isoAmount.to(x.value), - ergoTree = { - val bytes = Base16.decode(x.ergoTree).get - ErgoTreeSerializer.DefaultSerializer.deserializeErgoTree(bytes) - }, - creationHeight = x.creationHeight.toInt, - additionalTokens = isoTokenArray.to(x.assets), - additionalRegisters = isoNonMandatoryRegisters.to(x.additionalRegisters), - transactionId = ModifierId @@ x.transactionId, - index = x.index.toShort - ) - ergoBox - } - - override def from(x: ErgoBox): Box[commonMod.Amount, NonMandatoryRegisters] = { - val ergoTree = ErgoTreeSerializer.DefaultSerializer.serializeErgoTree(x.ergoTree) - val ergoTreeStr = Base16.encode(ergoTree) - val assets = isoTokenArray.from(x.additionalTokens) - Box[commonMod.Amount, NonMandatoryRegisters]( - boxId = Base16.encode(x.id), - ergoTree = ergoTreeStr, - value = isoAmount.from(x.value), - assets = assets, - creationHeight = x.creationHeight, - additionalRegisters = isoNonMandatoryRegisters.from(x.additionalRegisters), - transactionId = x.transactionId, - index = x.index - ) - } + override def from(x: DataInput): inputsMod.DataInput = + inputsMod.DataInput(DataIsos.isoBoxId.from(x.boxId)) } val isoEIP12UnsignedInput: Iso[inputsMod.EIP12UnsignedInput, ExtendedInputBox] = @@ -380,12 +224,12 @@ object Isos { transactionId = x.transactionId, index = x.index ) - val ergoBox = isoBox.to(box) + val ergoBox = sigma.js.Box.isoBox.to(box) val extendedInputBox = ExtendedInputBox(ergoBox, isoContextExtension.to(x.extension)) extendedInputBox } override def from(x: ExtendedInputBox): inputsMod.EIP12UnsignedInput = { - val box = isoBox.from(x.box) + val box = sigma.js.Box.isoBox.from(x.box) val ext = isoContextExtension.from(x.extension) inputsMod.EIP12UnsignedInput( boxId = box.boxId, @@ -407,7 +251,7 @@ object Isos { new UnsignedErgoLikeTransaction( inputs = sigma.js.Isos.isoArrayToIndexed(isoUnsignedInput).to(a.inputs), dataInputs = sigma.js.Isos.isoArrayToIndexed(isoDataInput).to(a.dataInputs), - outputCandidates = sigma.js.Isos.isoArrayToIndexed(isoBoxCandidate).to(a.outputs), + outputCandidates = sigma.js.Isos.isoArrayToIndexed(DataIsos.isoBoxCandidate).to(a.outputs), ) } @@ -415,7 +259,7 @@ object Isos { UnsignedTransaction( inputs = sigma.js.Isos.isoArrayToIndexed(isoUnsignedInput).from(b.inputs), dataInputs = sigma.js.Isos.isoArrayToIndexed(isoDataInput).from(b.dataInputs), - outputs = sigma.js.Isos.isoArrayToIndexed(isoBoxCandidate).from(b.outputCandidates) + outputs = sigma.js.Isos.isoArrayToIndexed(DataIsos.isoBoxCandidate).from(b.outputCandidates) ) } } @@ -426,14 +270,14 @@ object Isos { new ErgoLikeTransaction( inputs = sigma.js.Isos.isoArrayToIndexed(isoSignedInput).to(a.inputs), dataInputs = sigma.js.Isos.isoArrayToIndexed(isoDataInput).to(a.dataInputs), - outputCandidates = sigma.js.Isos.isoArrayToIndexed(isoBox).to(a.outputs), + outputCandidates = sigma.js.Isos.isoArrayToIndexed(sigma.js.Box.isoBox).to(a.outputs), ) } override def from(tx: ErgoLikeTransaction): SignedTransaction = { val inputs = sigma.js.Isos.isoArrayToIndexed(isoSignedInput).from(tx.inputs) val dataInputs = sigma.js.Isos.isoArrayToIndexed(isoDataInput).from(tx.dataInputs) - val outputs = sigma.js.Isos.isoArrayToIndexed(isoBox).from(tx.outputs) + val outputs = sigma.js.Isos.isoArrayToIndexed(sigma.js.Box.isoBox).from(tx.outputs) SignedTransaction(dataInputs, tx.id, inputs, outputs) } } diff --git a/sdk/js/src/main/scala/org/ergoplatform/sdk/js/ProverBuilder.scala b/sdk/js/src/main/scala/org/ergoplatform/sdk/js/ProverBuilder.scala index 12ecf1d03f..7ab95c187e 100644 --- a/sdk/js/src/main/scala/org/ergoplatform/sdk/js/ProverBuilder.scala +++ b/sdk/js/src/main/scala/org/ergoplatform/sdk/js/ProverBuilder.scala @@ -6,6 +6,7 @@ import org.ergoplatform.sdk.SecretString import scala.scalajs.js import scala.scalajs.js.annotation.JSExportTopLevel import Isos._ +import sigma.data.js.{Isos => DataIsos} import sigma.eval.SigmaDsl /** Equivalent of [[sdk.ProverBuilder]] available from JS. @@ -66,10 +67,10 @@ class ProverBuilder(parameters: BlockchainParameters, network: Byte) extends js. */ def withDHTSecret(g: String, h: String, u: String, v: String, x: js.BigInt): ProverBuilder = { _builder.withDHTData( - isoStringToGroupElement.to(g), - isoStringToGroupElement.to(h), - isoStringToGroupElement.to(u), - isoStringToGroupElement.to(v), + DataIsos.isoStringToGroupElement.to(g), + DataIsos.isoStringToGroupElement.to(h), + DataIsos.isoStringToGroupElement.to(u), + DataIsos.isoStringToGroupElement.to(v), SigmaDsl.toBigInteger(sigma.js.Isos.isoBigInt.to(x)) ) this diff --git a/sdk/js/src/main/scala/org/ergoplatform/sdk/js/SigmaProver.scala b/sdk/js/src/main/scala/org/ergoplatform/sdk/js/SigmaProver.scala index 0a6aca4830..693c0717bb 100644 --- a/sdk/js/src/main/scala/org/ergoplatform/sdk/js/SigmaProver.scala +++ b/sdk/js/src/main/scala/org/ergoplatform/sdk/js/SigmaProver.scala @@ -51,8 +51,8 @@ class SigmaProver(_prover: sdk.SigmaProver) extends js.Object { val unreducedTx = sdk.UnreducedTransaction( unsignedTx = isoUnsignedTransaction.to(unsignedTx), boxesToSpend = sigma.js.Isos.isoArrayToIndexed(isoEIP12UnsignedInput).to(boxesToSpend), - dataInputs = sigma.js.Isos.isoArrayToIndexed(isoBox).to(dataInputs), - tokensToBurn = sigma.js.Isos.isoArrayToIndexed(isoToken.andThen(sdk.SdkIsos.isoErgoTokenToPair.inverse)).to(tokensToBurn) + dataInputs = sigma.js.Isos.isoArrayToIndexed(sigma.js.Box.isoBox).to(dataInputs), + tokensToBurn = sigma.js.Isos.isoArrayToIndexed(sigma.data.js.Isos.isoToken.andThen(sdk.SdkIsos.isoErgoTokenToPair.inverse)).to(tokensToBurn) ) val ctx = isoBlockchainStateContext.to(stateCtx) val reducedTx = _prover.reduce(ctx, unreducedTx, baseCost) diff --git a/sdk/js/src/test/scala/org/ergoplatform/sdk/js/IsosSpec.scala b/sdk/js/src/test/scala/org/ergoplatform/sdk/js/IsosSpec.scala index a366e33d3c..a040731b20 100644 --- a/sdk/js/src/test/scala/org/ergoplatform/sdk/js/IsosSpec.scala +++ b/sdk/js/src/test/scala/org/ergoplatform/sdk/js/IsosSpec.scala @@ -10,7 +10,7 @@ import sigma.data.Iso import sigma.interpreter.{ContextExtension, ProverResult} import sigma.js.AvlTree import sigma.{Coll, GroupElement} - +import sigma.data.js.{Isos => DataIsos} import scala.scalajs.js class IsosSpec extends IsosSpecBase with sdk.generators.ObjectGenerators { @@ -31,19 +31,19 @@ class IsosSpec extends IsosSpecBase with sdk.generators.ObjectGenerators { property("Iso.isoStringToGroupElement") { forAll() { (bytes: GroupElement) => - roundtrip(Isos.isoStringToGroupElement)(bytes) + roundtrip(DataIsos.isoStringToGroupElement)(bytes) } } property("Iso.isoBoxId") { forAll(boxIdGen) { (id: BoxId) => - roundtrip(Isos.isoBoxId)(id) + roundtrip(DataIsos.isoBoxId)(id) } } property("Iso.isoHexStringToConstant") { forAll(constantGen, MinSuccessful(100)) { (c: Constant[SType]) => - roundtrip(Isos.isoHexStringToConstant)(c) + roundtrip(DataIsos.isoHexStringToConstant)(c) } } @@ -115,20 +115,20 @@ class IsosSpec extends IsosSpecBase with sdk.generators.ObjectGenerators { property("Iso.isoAmount") { forAll { (c: Long) => - roundtrip(Isos.isoAmount)(c) - Isos.isoAmount.to(js.BigInt(c.toString)) shouldBe c + roundtrip(DataIsos.isoAmount)(c) + DataIsos.isoAmount.to(js.BigInt(c.toString)) shouldBe c } } property("Iso.isoToken") { forAll(tokenIdGen, Arbitrary.arbLong.arbitrary) { (id: TokenId, amount: Long) => - roundtrip(Isos.isoToken)((id, amount)) + roundtrip(DataIsos.isoToken)((id, amount)) } } property("Iso.isoTokenArray") { forAll(ergoBoxTokens(tokensGen.sample.get)) { tokens => - roundtrip(Isos.isoTokenArray)(tokens) + roundtrip(DataIsos.isoTokenArray)(tokens) } } @@ -140,19 +140,19 @@ class IsosSpec extends IsosSpecBase with sdk.generators.ObjectGenerators { property("Iso.isoNonMandatoryRegisters") { forAll(additionalRegistersGen) { (x: AdditionalRegisters) => - roundtrip(Isos.isoNonMandatoryRegisters)(x) + roundtrip(DataIsos.isoNonMandatoryRegisters)(x) } } property("Iso.isoBoxCandidate") { forAll { (box: ErgoBoxCandidate) => - roundtrip(Isos.isoBoxCandidate)(box) + roundtrip(DataIsos.isoBoxCandidate)(box) } } property("Iso.isoBox") { forAll { (b: ErgoBox) => - roundtrip(Isos.isoBox)(b) + roundtrip(sigma.js.Box.isoBox)(b) } } From 1177d09640f4db75708edc70cb8bff805bd6de4c Mon Sep 17 00:00:00 2001 From: Alexander Slesarenko Date: Thu, 2 May 2024 18:25:37 +0100 Subject: [PATCH 048/314] i956-box-in-register: tests for Box Value toHex/fromHex --- core/js/src/main/scala/sigma/js/Value.scala | 261 -------------------- data/js/src/main/scala/sigma/js/Box.scala | 12 +- data/js/src/main/scala/sigma/js/Value.scala | 17 +- sigma-js/package-lock.json | 4 +- sigma-js/sigmastate-js.d.ts | 10 +- sigma-js/tests/js/Box.spec.js | 29 +++ 6 files changed, 58 insertions(+), 275 deletions(-) delete mode 100644 core/js/src/main/scala/sigma/js/Value.scala create mode 100644 sigma-js/tests/js/Box.spec.js diff --git a/core/js/src/main/scala/sigma/js/Value.scala b/core/js/src/main/scala/sigma/js/Value.scala deleted file mode 100644 index 13b63c2abc..0000000000 --- a/core/js/src/main/scala/sigma/js/Value.scala +++ /dev/null @@ -1,261 +0,0 @@ -package sigma -package js - -import scorex.util.Extensions.{IntOps, LongOps} -import scorex.util.encode.Base16 -import sigma.ast.SType -import sigma.crypto.Platform -import sigma.data._ -import sigma.js.Value.toRuntimeData -import sigma.serialization.{CoreDataSerializer, CoreSerializer} -import sigma.util.Extensions.BigIntOps -import sigma.{Coll, Colls, Evaluation} - -import java.math.BigInteger -import scala.scalajs.js -import scala.scalajs.js.annotation.JSExportTopLevel - -/** - * This class is used to represent any valid value of ErgoScript language. - * Any such value comes equipped with {@link Type} descriptor. - * Note, there is a distinction between JS types and ErgoScript types. - * Each Value instance represents the concrete ErgoScript type given by `tpe`. - * The implementation is based on the pre-defined mapping between JS and ES types. - * This mapping is applied recursively and is given by the following: - * - * JS type | ErgoScript Type - * -------------------------------------- - * Number | Byte - * Number | Short - * Number | Int - * BigInt | Long - * BigInt | BigInt - * array [A, B] | (A, B) - pair - * array [a1, a2 ..] | Coll[A] - collection - * - * @param data JS value wrapped in this value - * @param tpe type descriptor of the ErgoScript type - */ -@JSExportTopLevel("Value") -class Value(val data: Any, val tpe: Type) extends js.Object { - - /** Get Sigma runtime value which can be passed to interpreter, saved in register and - * [[sigma.ast.Constant]] nodes. - */ - final def runtimeData: Any = toRuntimeData(data, tpe.rtype) - - /** - * Encode this value as Base16 hex string. - * 1) it transforms this value into {@link sigma.ast.ConstantNode} of sigma. - * 2) it serializes the constant into byte array using {@link sigmastate.serialization.ConstantSerializer} - * 3) the bytes are encoded using Base16 encoder into string - * - * @return hex string of serialized bytes - */ - def toHex(): String = { - val stype = Evaluation.rtypeToSType(tpe.rtype) - val value = runtimeData.asInstanceOf[SType#WrappedType] - val w = CoreSerializer.startWriter() - w.putType(stype) - CoreDataSerializer.serialize(value, stype, w) - Base16.encode(w.toBytes) - } -} - -@JSExportTopLevel("Value$") -object Value extends js.Object { - /** Maximal positive value of ES type Long */ - val MaxLong = js.BigInt("0x7fffffffffffffff") - - /** Minimal negative value of ES type Long */ - val MinLong = -js.BigInt("0x8000000000000000") - - /** Helper method to get Sigma runtime value which can be passed to interpreter, saved - * in register and [[sigma.ast.Constant]] nodes. - */ - final private[js] def toRuntimeData(data: Any, rtype: RType[_]): Any = rtype match { - case sigma.BooleanType => data - case sigma.ByteType | sigma.ShortType | sigma.IntType => data - case sigma.LongType => java.lang.Long.parseLong(data.asInstanceOf[js.BigInt].toString(10)) - case sigma.BigIntRType => - val v = data.asInstanceOf[js.BigInt] - CBigInt(new BigInteger(v.toString(16), 16)) - case sigma.GroupElementRType => - val ge = data.asInstanceOf[GroupElement] - CGroupElement(ge.point) - case sigma.SigmaPropRType => - val p = data.asInstanceOf[SigmaProp] - CSigmaProp(p.sigmaBoolean) - case sigma.AvlTreeRType => - val t = data.asInstanceOf[AvlTree] - AvlTree.isoAvlTree.to(t) - case ct: CollType[a] => - val xs = data.asInstanceOf[js.Array[Any]] - implicit val cT = ct.tItem.classTag - val items = xs.map(x => toRuntimeData(x, ct.tItem).asInstanceOf[a]).toArray[a] - Colls.fromItems(items:_*)(ct.tItem) - case pt: PairType[a, b] => - val p = data.asInstanceOf[js.Array[Any]] - val x = toRuntimeData(p(0), pt.tFst).asInstanceOf[a] - val y = toRuntimeData(p(1), pt.tSnd).asInstanceOf[b] - (x, y) - case sigma.UnitType => data - case _ => - throw new IllegalArgumentException(s"Unsupported type $rtype") - } - - /** Helper method to extract JS data value from Sigma runtime value. - * This should be inverse to `toRuntimeData`. - * - * @param value runtime value of type given by `rtype` - * @param rtype type descriptor of Sigma runtime value - */ - final def fromRuntimeData(value: Any, rtype: RType[_]): Any = rtype match { - case sigma.BooleanType => value - case sigma.ByteType | sigma.ShortType | sigma.IntType => value - case sigma.LongType => js.BigInt(value.asInstanceOf[Long].toString) - case sigma.BigIntRType => - val hex = value.asInstanceOf[sigma.BigInt].toBigInteger.toString(10) - js.BigInt(hex) - case sigma.GroupElementRType => - val point = value.asInstanceOf[CGroupElement].wrappedValue.asInstanceOf[Platform.Ecp] - new GroupElement(point) - case sigma.SigmaPropRType => - new SigmaProp(value.asInstanceOf[CSigmaProp].wrappedValue) - case sigma.AvlTreeRType => - AvlTree.isoAvlTree.from(value.asInstanceOf[CAvlTree]) - case ct: CollType[a] => - val arr = value.asInstanceOf[Coll[a]].toArray - js.Array(arr.map(x => fromRuntimeData(x, ct.tItem)):_*) - case pt: PairType[a, b] => - val p = value.asInstanceOf[(a, b)] - js.Array(fromRuntimeData(p._1, pt.tFst), fromRuntimeData(p._2, pt.tSnd)) - case sigma.UnitType => value - case _ => - throw new IllegalArgumentException(s"Unsupported type $rtype") - } - - /** Helper method to check validity of JS data value against the given runtime type. - * - * @param data js value - * @param rtype type descriptor of Sigma runtime value - */ - final private def checkJsData[T](data: T, rtype: RType[_]): Any = rtype match { - case sigma.ByteType => data.asInstanceOf[Int].toByteExact - case sigma.ShortType => data.asInstanceOf[Int].toShortExact - case sigma.IntType => data.asInstanceOf[Int].toLong.toIntExact - case sigma.LongType => - val n = data.asInstanceOf[js.BigInt] - if (n < MinLong || n > MaxLong) - throw new ArithmeticException(s"value $n is out of long range") - n - case sigma.BigIntRType => - data.asInstanceOf[js.BigInt] - case sigma.GroupElementRType => - data.asInstanceOf[GroupElement] - case sigma.SigmaPropRType => - data.asInstanceOf[SigmaProp] - case PairType(l, r) => data match { - case arr: js.Array[Any @unchecked] => - checkJsData(arr(0), l) - checkJsData(arr(1), r) - data - case _ => - throw new ArithmeticException(s"$data cannot represent pair value") - } - case CollType(elemType) => data match { - case arr: js.Array[Any @unchecked] => - arr.foreach(x => checkJsData(x, elemType)) - data - case _ => - throw new ArithmeticException(s"$data cannot represent Coll value") - } - case _ => - throw new IllegalArgumentException(s"Unsupported type $rtype") - } - - /** Create Byte value from JS number. */ - def ofByte(n: Int): Value = { - checkJsData(n, Type.Byte.rtype) - new Value(n, Type.Byte) - } - - /** Create Short value from JS number. */ - def ofShort(n: Int): Value = { - checkJsData(n, Type.Short.rtype) - new Value(n, Type.Short) - } - - /** Create Int value from JS number. */ - def ofInt(n: Int): Value = { - checkJsData(n, Type.Int.rtype) - new Value(n, Type.Int) - } - - /** Create Long value from JS BigInt. */ - def ofLong(n: js.BigInt): Value = { - checkJsData(n, Type.Long.rtype) - new Value(n, Type.Long) - } - - /** Create BigInt value from JS BigInt. */ - def ofBigInt(n: js.BigInt): Value = { - checkJsData(n, Type.BigInt.rtype) - new Value(n, Type.BigInt) - } - - /** Creates a Value of GroupElement type from [[sigmastate.crypto.Platform.Point]] hex. - * @param pointHex hex of ASN representation of [[sigmastate.crypto.Platform.Point]] - */ - def ofGroupElement(pointHex: String): Value = { - val ge = GroupElement.fromPointHex(pointHex) - new Value(ge, Type.GroupElement) - } - - /** Creates a Value of SigmaProp type from [[sigmastate.crypto.Platform.Point]] hex. - * @param pointHex hex of ASN representation of [[sigmastate.crypto.Platform.Point]] - */ - def ofSigmaProp(pointHex: String): Value = { - val sp = SigmaProp.fromPointHex(pointHex) - new Value(sp, Type.SigmaProp) - } - - /** Create Pair value from two values. */ - def pairOf(l: Value, r: Value): Value = { - val data = js.Array(l.data, r.data) // the l and r data have been validated - new Value(data, Type.pairType(l.tpe, r.tpe)) - } - - /** Create Coll value from array and element type descriptor. - * @param items collection elements which should be valid JS representation of `elemType` - * @param elemType descriptor of types for collection elements - */ - def collOf(items: js.Array[Any], elemType: Type): Value = { - val t = Type.collType(elemType) - checkJsData(items, t.rtype) - new Value(items, t) - } - - /** - * Creates Value from hex encoded serialized bytes of Constant values. - *

- * In order to create Value you need to provide both value instance and - * Type descriptor. This is similar to how values are represented in sigma - * ConstantNode. Each ConstantNode also have value instance and `tpe: SType` - * descriptor. - * @param hex the string is obtained as hex encoding of serialized ConstantNode. - * (The bytes obtained by ConstantSerializer in sigma) - * @return new deserialized Value instance containing: - * - suitable JS value in its `data` field - * - and [[Type]] descriptor in its `tpe` field - */ - def fromHex(hex: String): Value = { - val bytes = Base16.decode(hex).fold(t => throw t, identity) - val r = CoreSerializer.startReader(bytes) - val stype = r.getType() - val value = CoreDataSerializer.deserialize(stype, r) - val rtype = Evaluation.stypeToRType(stype) - val jsvalue = Value.fromRuntimeData(value, rtype) - new Value(jsvalue, new Type(rtype)) - } -} diff --git a/data/js/src/main/scala/sigma/js/Box.scala b/data/js/src/main/scala/sigma/js/Box.scala index 209e15d489..70155633d5 100644 --- a/data/js/src/main/scala/sigma/js/Box.scala +++ b/data/js/src/main/scala/sigma/js/Box.scala @@ -16,15 +16,15 @@ import scala.scalajs.js.annotation.JSExportTopLevel /** Equivalent of [[sigma.Box]] available from JS. */ @JSExportTopLevel("Box") -class Box(val box: FBox[Amount, NonMandatoryRegisters]) extends js.Object { -} +class Box(val box: FBox[Amount, NonMandatoryRegisters]) extends js.Object -@JSExportTopLevel("Box$") object Box extends js.Object { + /** Represents a box in Fleet SDK. */ + type FleetBox = FBox[commonMod.Amount, NonMandatoryRegisters] /** Converts Fleet box to ErgoBox and back. */ - val isoBox: Iso[FBox[commonMod.Amount, NonMandatoryRegisters], ErgoBox] = new Iso[FBox[commonMod.Amount, NonMandatoryRegisters], ErgoBox] { - override def to(x: FBox[commonMod.Amount, NonMandatoryRegisters]): ErgoBox = { + val isoBox: Iso[FleetBox, ErgoBox] = new Iso[FleetBox, ErgoBox] { + override def to(x: FleetBox): ErgoBox = { val ergoBox = new ErgoBox( value = isoAmount.to(x.value), ergoTree = { @@ -40,7 +40,7 @@ object Box extends js.Object { ergoBox } - override def from(x: ErgoBox): FBox[commonMod.Amount, NonMandatoryRegisters] = { + override def from(x: ErgoBox): FleetBox = { val ergoTree = ErgoTreeSerializer.DefaultSerializer.serializeErgoTree(x.ergoTree) val ergoTreeStr = Base16.encode(ergoTree) val assets = isoTokenArray.from(x.additionalTokens) diff --git a/data/js/src/main/scala/sigma/js/Value.scala b/data/js/src/main/scala/sigma/js/Value.scala index 785f9e04db..fea6cd9b8b 100644 --- a/data/js/src/main/scala/sigma/js/Value.scala +++ b/data/js/src/main/scala/sigma/js/Value.scala @@ -7,9 +7,10 @@ import sigma.ast.SType import sigma.crypto.Platform import sigma.data._ import sigma.js.Value.toRuntimeData -import sigma.serialization.{CoreSerializer, DataSerializer} +import sigma.serialization.{CoreDataSerializer, CoreSerializer, DataSerializer, SigmaSerializer} import sigma.util.Extensions.BigIntOps import sigma.{Coll, Colls, Evaluation} +import sigmastate.fleetSdkCommon.distEsmTypesBoxesMod.{Box => FBox} import java.math.BigInteger import scala.scalajs.js @@ -55,7 +56,7 @@ class Value(val data: Any, val tpe: Type) extends js.Object { def toHex(): String = { val stype = Evaluation.rtypeToSType(tpe.rtype) val value = runtimeData.asInstanceOf[SType#WrappedType] - val w = CoreSerializer.startWriter() + val w = SigmaSerializer.startWriter() w.putType(stype) DataSerializer.serialize(value, stype, w) Base16.encode(w.toBytes) @@ -128,7 +129,8 @@ object Value extends js.Object { case sigma.AvlTreeRType => AvlTree.isoAvlTree.from(value.asInstanceOf[CAvlTree]) case sigma.BoxRType => - AvlTree.isoAvlTree.from(value.asInstanceOf[CAvlTree]) + val fleetBox = Box.isoBox.from(value.asInstanceOf[CBox].wrappedValue) + new Box(fleetBox) case ct: CollType[a] => val arr = value.asInstanceOf[Coll[a]].toArray js.Array(arr.map(x => fromRuntimeData(x, ct.tItem)):_*) @@ -225,6 +227,13 @@ object Value extends js.Object { new Value(sp, Type.SigmaProp) } + /** Creates a Value of Box type from a [[FBox]] instance. + * @param fleetBox a Fleet box to be wrapped in a [[Value]] + */ + def ofBox(fleetBox: Box.FleetBox): Value = { + new Value(new Box(fleetBox), Type.Box) + } + /** Create Pair value from two values. */ def pairOf(l: Value, r: Value): Value = { val data = js.Array(l.data, r.data) // the l and r data have been validated @@ -256,7 +265,7 @@ object Value extends js.Object { */ def fromHex(hex: String): Value = { val bytes = Base16.decode(hex).fold(t => throw t, identity) - val r = CoreSerializer.startReader(bytes) + val r = SigmaSerializer.startReader(bytes) val stype = r.getType() val value = DataSerializer.deserialize(stype, r) val rtype = Evaluation.stypeToRType(stype) diff --git a/sigma-js/package-lock.json b/sigma-js/package-lock.json index 893a0ee141..c34f802f6e 100644 --- a/sigma-js/package-lock.json +++ b/sigma-js/package-lock.json @@ -1,12 +1,12 @@ { "name": "sigmastate-js", - "version": "0.3.0", + "version": "0.4.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "sigmastate-js", - "version": "0.3.0", + "version": "0.4.0", "license": "MIT", "dependencies": { "@fleet-sdk/common": "0.1.3", diff --git a/sigma-js/sigmastate-js.d.ts b/sigma-js/sigmastate-js.d.ts index b70ca39258..53baa3b026 100644 --- a/sigma-js/sigmastate-js.d.ts +++ b/sigma-js/sigmastate-js.d.ts @@ -1,7 +1,7 @@ declare module "sigmastate-js/main" { import { Amount, - Box, + Box as FBox, EIP12UnsignedInput, NonMandatoryRegisters, SignedTransaction, TokenAmount, UnsignedTransaction @@ -173,6 +173,10 @@ declare module "sigmastate-js/main" { valueLengthOpt: number | undefined; } + export declare class Box { + box: FBox; + } + export declare class PreHeader { /** Block version, to be increased on every soft and hardfork. */ version: number; @@ -301,6 +305,8 @@ declare module "sigmastate-js/main" { static ofSigmaProp(pointHex: string): Value; + static ofBox(box: FBox): Value; + static pairOf(left: Value, right: Value): Value<[R, L]>; static collOf(items: T[], elemType: Type): Value; @@ -498,7 +504,7 @@ declare module "sigmastate-js/main" { stateCtx: BlockchainStateContext, unsignedTx: UnsignedTransaction, boxesToSpend: EIP12UnsignedInput[], - dataInputs: Box[], + dataInputs: FBox[], tokensToBurn: TokenAmount[], baseCost: number): ReducedTransaction; diff --git a/sigma-js/tests/js/Box.spec.js b/sigma-js/tests/js/Box.spec.js new file mode 100644 index 0000000000..5782507ae4 --- /dev/null +++ b/sigma-js/tests/js/Box.spec.js @@ -0,0 +1,29 @@ +const {Box$, Value$} = require("sigmastate-js/main"); + +describe("Box", () => { + it("should deserialize from hex", () => { + let boxHex = "63b96000d1968302010100ff83020193040204020100c0843d000401010e32297000800b80f1d56c809a8c6affbed864b87f007f6f007f00ac00018c01c4fdff011088807f0100657f00f9ab0101ff6d6505a4a7b5a2e7a4a4dd3a05feffffffffffffffff01003bd5c630803cfff6c1ff7f7fb980ff136afc011f8080b8b04ad4dbda2d7f4e01" + let deserialized = Value$.fromHex(boxHex); + // console.log(b.data) + let expected = { + additionalRegisters: { + R4: '0101', + R5: '0e32297000800b80f1d56c809a8c6affbed864b87f007f6f007f00ac00018c01c4fdff011088807f0100657f00f9ab0101ff6d65', + R6: '05a4a7b5a2e7a4a4dd3a', + R7: '05feffffffffffffffff01' + }, + assets: [], + boxId: '3a0089be265460e29ca47d26e5b55a6f3e3ffaf5b4aed941410a2437913848ad', + creationHeight: 1000000, + ergoTree: '00d1968302010100ff83020193040204020100', + index: 1, + transactionId: '003bd5c630803cfff6c1ff7f7fb980ff136afc011f8080b8b04ad4dbda2d7f4e', + value: '12345' + } + let fleetBox = deserialized.data.box + expect(fleetBox).toEqual(expected) + + let newBoxValue = Value$.ofBox(fleetBox) + expect(newBoxValue.toHex()).toEqual(boxHex) + }); +}); \ No newline at end of file From 42e79d7887d71904d5c6d13ea8c943d87997628b Mon Sep 17 00:00:00 2001 From: Alexander Slesarenko Date: Thu, 2 May 2024 18:34:48 +0100 Subject: [PATCH 049/314] i956-box-in-register: cleanup --- sigma-js/tests/js/Box.spec.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sigma-js/tests/js/Box.spec.js b/sigma-js/tests/js/Box.spec.js index 5782507ae4..24238013ba 100644 --- a/sigma-js/tests/js/Box.spec.js +++ b/sigma-js/tests/js/Box.spec.js @@ -1,10 +1,9 @@ const {Box$, Value$} = require("sigmastate-js/main"); describe("Box", () => { - it("should deserialize from hex", () => { + it("should serialize from/to hex", () => { let boxHex = "63b96000d1968302010100ff83020193040204020100c0843d000401010e32297000800b80f1d56c809a8c6affbed864b87f007f6f007f00ac00018c01c4fdff011088807f0100657f00f9ab0101ff6d6505a4a7b5a2e7a4a4dd3a05feffffffffffffffff01003bd5c630803cfff6c1ff7f7fb980ff136afc011f8080b8b04ad4dbda2d7f4e01" let deserialized = Value$.fromHex(boxHex); - // console.log(b.data) let expected = { additionalRegisters: { R4: '0101', From 16af268db73971f3bf5e910ae3d6fc2289e36beb Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Fri, 3 May 2024 17:14:25 +0300 Subject: [PATCH 050/314] checking header version in checkPow() --- .../shared/src/main/scala/sigmastate/eval/CHeader.scala | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/interpreter/shared/src/main/scala/sigmastate/eval/CHeader.scala b/interpreter/shared/src/main/scala/sigmastate/eval/CHeader.scala index 3bd0dd62f9..c23118100b 100644 --- a/interpreter/shared/src/main/scala/sigmastate/eval/CHeader.scala +++ b/interpreter/shared/src/main/scala/sigmastate/eval/CHeader.scala @@ -39,7 +39,11 @@ case class CHeader( } override def checkPow: Boolean = { - Autolykos2PowValidation.checkPoWForVersion2(this) + if (version == 1) { + throw new Exception("Autolykos v1 is not supported") //todo: more specific exception? + } else { + Autolykos2PowValidation.checkPoWForVersion2(this) + } } } From 83a7e701445c53918c877c01d1a93eb5d1d84ac1 Mon Sep 17 00:00:00 2001 From: Alexander Slesarenko Date: Fri, 3 May 2024 21:09:37 +0100 Subject: [PATCH 051/314] i956-box-in-register: Iso ScalaDoc + imports cleanup --- core/js/src/main/scala/sigma/js/Isos.scala | 3 +++ .../src/main/scala/sigma/data/Iso.scala | 10 +++++-- .../src/main/scala/sigma/data/js/Isos.scala | 16 ++++++------ data/js/src/main/scala/sigma/js/Value.scala | 2 +- .../scala/org/ergoplatform/sdk/js/Isos.scala | 26 +++++++------------ 5 files changed, 29 insertions(+), 28 deletions(-) diff --git a/core/js/src/main/scala/sigma/js/Isos.scala b/core/js/src/main/scala/sigma/js/Isos.scala index b28a3337b8..767a358d62 100644 --- a/core/js/src/main/scala/sigma/js/Isos.scala +++ b/core/js/src/main/scala/sigma/js/Isos.scala @@ -8,6 +8,9 @@ import scala.reflect.ClassTag import scala.scalajs.js import scala.scalajs.js.JSConverters.JSRichOption +/** Definitions of isomorphisms for sigma-core module. + * @see sigma.data.Iso + */ object Isos { implicit def isoUndefOr[A, B](implicit iso: Iso[A, B]): Iso[js.UndefOr[A], Option[B]] = new Iso[js.UndefOr[A], Option[B]] { diff --git a/core/shared/src/main/scala/sigma/data/Iso.scala b/core/shared/src/main/scala/sigma/data/Iso.scala index 9b90d63bb0..0e463bdd04 100644 --- a/core/shared/src/main/scala/sigma/data/Iso.scala +++ b/core/shared/src/main/scala/sigma/data/Iso.scala @@ -7,14 +7,20 @@ import sigma.{Coll, Colls} /** Type-class of isomorphisms between types. * Isomorphism between two types `A` and `B` essentially say that both types * represents the same information (entity) but in a different way. + * + * Each isomorphism defined by two functions: + * - `to: A => B` - conversion from `A` to `B` + * - `from: B => A` - conversion from `B` to `A` + * *

- * The information is not lost so that both are true: + * such that the information is not lost during conversion, so that both are true: * 1) a == from(to(a)) * 2) b == to(from(b)) *

* It is used to define type-full conversions: * - different conversions between Java and Scala data types. - * - conversion between Ergo representations and generated API representations + * - conversion between internal Ergo representations and API representations + * - conversions between exported JS classes and internal Ergo representations */ abstract class Iso[A, B] { def to(a: A): B diff --git a/data/js/src/main/scala/sigma/data/js/Isos.scala b/data/js/src/main/scala/sigma/data/js/Isos.scala index 95bbce8bbe..22300b1fd8 100644 --- a/data/js/src/main/scala/sigma/data/js/Isos.scala +++ b/data/js/src/main/scala/sigma/data/js/Isos.scala @@ -1,15 +1,9 @@ package sigma.data.js -import org.ergoplatform.{ErgoBox, ErgoBoxCandidate} import org.ergoplatform.ErgoBox._ +import org.ergoplatform.{ErgoBox, ErgoBoxCandidate} import scorex.crypto.authds.ADKey -import scorex.util.ModifierId import scorex.util.encode.Base16 -import sigma.{Coll, Colls} -import sigmastate.fleetSdkCommon.distEsmTypesBoxesMod.{Box => FBox} -import sigmastate.fleetSdkCommon.distEsmTypesCommonMod.{Amount, HexString} -import sigmastate.fleetSdkCommon.distEsmTypesRegistersMod.NonMandatoryRegisters -import sigmastate.fleetSdkCommon.{distEsmTypesBoxesMod => boxesMod, distEsmTypesCommonMod => commonMod, distEsmTypesRegistersMod => registersMod, distEsmTypesTokenMod => tokenMod} import sigma.Extensions._ import sigma.ast.syntax.GroupElementConstant import sigma.ast.{Constant, GroupElementConstant, SType} @@ -17,10 +11,16 @@ import sigma.data.Iso.isoStringToArray import sigma.data.{CGroupElement, Digest32Coll, Iso} import sigma.js.GroupElement import sigma.serialization.{ErgoTreeSerializer, ValueSerializer} +import sigma.{Coll, Colls} +import sigmastate.fleetSdkCommon.distEsmTypesCommonMod.HexString +import sigmastate.fleetSdkCommon.distEsmTypesRegistersMod.NonMandatoryRegisters +import sigmastate.fleetSdkCommon.{distEsmTypesBoxesMod => boxesMod, distEsmTypesCommonMod => commonMod, distEsmTypesRegistersMod => registersMod, distEsmTypesTokenMod => tokenMod} import scala.scalajs.js -/** Definitions of isomorphisms for sigma-data module. */ +/** Definitions of isomorphisms for sigma-data module. + * @see sigma.data.Iso + */ object Isos { val isoStringToGroupElement: Iso[String, sigma.GroupElement] = new Iso[String, sigma.GroupElement] { diff --git a/data/js/src/main/scala/sigma/js/Value.scala b/data/js/src/main/scala/sigma/js/Value.scala index fea6cd9b8b..a65156bd43 100644 --- a/data/js/src/main/scala/sigma/js/Value.scala +++ b/data/js/src/main/scala/sigma/js/Value.scala @@ -7,7 +7,7 @@ import sigma.ast.SType import sigma.crypto.Platform import sigma.data._ import sigma.js.Value.toRuntimeData -import sigma.serialization.{CoreDataSerializer, CoreSerializer, DataSerializer, SigmaSerializer} +import sigma.serialization.{DataSerializer, SigmaSerializer} import sigma.util.Extensions.BigIntOps import sigma.{Coll, Colls, Evaluation} import sigmastate.fleetSdkCommon.distEsmTypesBoxesMod.{Box => FBox} diff --git a/sdk/js/src/main/scala/org/ergoplatform/sdk/js/Isos.scala b/sdk/js/src/main/scala/org/ergoplatform/sdk/js/Isos.scala index f4085cf2a9..0f50a52686 100644 --- a/sdk/js/src/main/scala/org/ergoplatform/sdk/js/Isos.scala +++ b/sdk/js/src/main/scala/org/ergoplatform/sdk/js/Isos.scala @@ -1,36 +1,28 @@ package org.ergoplatform.sdk.js -import org.ergoplatform.ErgoBox._ import org.ergoplatform._ import org.ergoplatform.sdk.ExtendedInputBox -import org.ergoplatform.sdk.JavaHelpers.UniversalConverter import org.ergoplatform.sdk.wallet.protocol.context -import scorex.crypto.authds.ADKey -import scorex.util.ModifierId -import scorex.util.encode.Base16 -import sigma.Extensions.CollBytesOps -import sigma.ast.syntax.GroupElementConstant -import sigma.ast.{Constant, GroupElementConstant, SType} +import sigma.ast.{Constant, SType} +import sigma.data.Iso import sigma.data.Iso.{isoStringToArray, isoStringToColl} -import sigma.data.{CBigInt, CGroupElement, Digest32Coll, Digest32CollRType, Iso} +import sigma.data.js.{Isos => DataIsos} import sigma.interpreter.{ContextExtension, ProverResult} -import sigma.js.{AvlTree, GroupElement} -import sigma.serialization.{ErgoTreeSerializer, ValueSerializer} -import sigma.{Coll, Colls} +import sigma.js.AvlTree import sigmastate.eval.{CHeader, CPreHeader} import sigmastate.fleetSdkCommon.distEsmTypesBoxesMod.Box -import sigmastate.fleetSdkCommon.distEsmTypesCommonMod.HexString import sigmastate.fleetSdkCommon.distEsmTypesRegistersMod.NonMandatoryRegisters import sigmastate.fleetSdkCommon.distEsmTypesTokenMod.TokenAmount import sigmastate.fleetSdkCommon.distEsmTypesTransactionsMod.{SignedTransaction, UnsignedTransaction} -import sigmastate.fleetSdkCommon.{distEsmTypesBoxesMod => boxesMod, distEsmTypesCommonMod => commonMod, distEsmTypesContextExtensionMod => contextExtensionMod, distEsmTypesInputsMod => inputsMod, distEsmTypesProverResultMod => proverResultMod, distEsmTypesRegistersMod => registersMod, distEsmTypesTokenMod => tokenMod} -import sigma.data.js.{Isos => DataIsos} -import java.math.BigInteger +import sigmastate.fleetSdkCommon.{distEsmTypesCommonMod => commonMod, distEsmTypesContextExtensionMod => contextExtensionMod, distEsmTypesInputsMod => inputsMod, distEsmTypesProverResultMod => proverResultMod} + import scala.collection.immutable.ListMap import scala.scalajs.js import scala.scalajs.js.Object -/** Definitions of isomorphisms for sigma-sdk module. */ +/** Definitions of isomorphisms for sigma-sdk module. + * @see sigma.data.Iso + */ object Isos { implicit val isoHeader: Iso[Header, sigma.Header] = new Iso[Header, sigma.Header] { override def to(a: Header): sigma.Header = { From acecce014884395b58fb532d6a095372681f0ae4 Mon Sep 17 00:00:00 2001 From: Alexander Slesarenko Date: Fri, 3 May 2024 21:52:38 +0100 Subject: [PATCH 052/314] [sigma-js]: bump version 0.4.2 + update sigma-js/README.md --- sigma-js/README.md | 3 ++- sigma-js/package.json | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/sigma-js/README.md b/sigma-js/README.md index ff867e1cb6..c1f30f3497 100644 --- a/sigma-js/README.md +++ b/sigma-js/README.md @@ -46,14 +46,15 @@ with `$` suffix, thus if X is the JS class, then X$ is the JS object, which corr ## The list of modules and their exported classes - [sigma-core module](../core/js) - contains core classes of Sigma.js library - [Type](../core/js/src/main/scala/sigma/js/Type.scala) - - [Value](../core/js/src/main/scala/sigma/js/Value.scala) - [GroupElement](../core/js/src/main/scala/sigma/js/GroupElement.scala) - [SigmaProp](../core/js/src/main/scala/sigma/js/SigmaProp.scala) - [AvlTree](../core/js/src/main/scala/sigma/js/AvlTree.scala) - [sigma-data module](../data/js) - contains classes for working with ErgoTree, addresses and all related serializers - all classes from sigma-core module + - [Value](../data/js/src/main/scala/sigma/js/Value.scala) - [ErgoTree](../data/js/src/main/scala/sigma/ast/js/ErgoTree.scala) + - [Box](../data/js/src/main/scala/sigma/js/Box.scala) - [Address](../data/js/src/main/scala/org/ergoplatform/js/Address.scala) - [Expr](../data/js/src/main/scala/sigma/ast/js/Expr.scala) diff --git a/sigma-js/package.json b/sigma-js/package.json index 77ff920585..f6900571bd 100644 --- a/sigma-js/package.json +++ b/sigma-js/package.json @@ -1,6 +1,6 @@ { "name": "sigmastate-js", - "version": "0.4.0", + "version": "0.4.2", "description": "Sigma.js library", "files": [ "dist/", From 60aa790b9f7cd71e076ab3925aa30bb6612778af Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Sun, 5 May 2024 21:37:59 +0300 Subject: [PATCH 053/314] close #969 : versioned support for Header (de)serialization --- .../scala/org/ergoplatform/ErgoHeader.scala | 153 ++++++++++++++++++ .../org/ergoplatform/HeaderWithoutPow.scala | 6 +- .../src/main/scala/sigma/ast/methods.scala | 2 +- .../src/main/scala/sigma/data/CHeader.scala | 132 +++++++++++++++ .../sigma/serialization/DataSerializer.scala | 14 +- .../main/scala/sigmastate/eval/CHeader.scala | 57 ------- .../DataSerializerSpecification.scala | 18 ++- .../MethodCallSerializerSpecification.scala | 12 +- .../SerializationSpecification.scala | 2 +- .../special/sigma/SigmaTestingData.scala | 4 +- .../scala/org/ergoplatform/sdk/js/Isos.scala | 4 +- .../org/ergoplatform/sdk/JsonCodecs.scala | 4 +- 12 files changed, 334 insertions(+), 74 deletions(-) create mode 100644 data/shared/src/main/scala/org/ergoplatform/ErgoHeader.scala create mode 100644 data/shared/src/main/scala/sigma/data/CHeader.scala delete mode 100644 interpreter/shared/src/main/scala/sigmastate/eval/CHeader.scala diff --git a/data/shared/src/main/scala/org/ergoplatform/ErgoHeader.scala b/data/shared/src/main/scala/org/ergoplatform/ErgoHeader.scala new file mode 100644 index 0000000000..cc678003d6 --- /dev/null +++ b/data/shared/src/main/scala/org/ergoplatform/ErgoHeader.scala @@ -0,0 +1,153 @@ +package org.ergoplatform + +import org.bouncycastle.util.BigIntegers +import scorex.crypto.authds.ADDigest +import scorex.crypto.hash.{Blake2b256, Digest32} +import scorex.util.ModifierId +import sigma.Colls +import sigma.crypto.{CryptoConstants, CryptoFacade, EcPointType} +import sigma.serialization.{GroupElementSerializer, SigmaByteReader, SigmaByteWriter, SigmaSerializer} + + +/** + * Solution for an Autolykos PoW puzzle. + * + * In Autolykos v.1 all the four fields are used, in Autolykos v.2 only pk and n fields are used. + * + * @param pk - miner public key. Should be used to collect block rewards + * @param w - one-time public key. Prevents revealing of miners secret + * @param n - nonce (8 bytes) + * @param d - distance between pseudo-random number, corresponding to nonce `n` and a secret, + * corresponding to `pk`. The lower `d` is, the harder it was to find this solution. + */ +case class AutolykosSolution(pk: EcPointType, + w: EcPointType, + n: Array[Byte], + d: BigInt) { + + val encodedPk: Array[Byte] = GroupElementSerializer.toBytes(pk) + +} + + +object AutolykosSolution { + // "pk", "w" and "d" values for Autolykos v2 solution, where they not passed from outside + val pkForV2: EcPointType = CryptoConstants.dlogGroup.identity + val wForV2: EcPointType = CryptoConstants.dlogGroup.generator + val dForV2: BigInt = 0 + + object sigmaSerializerV1 extends SigmaSerializer[AutolykosSolution, AutolykosSolution] { + override def serialize(s: AutolykosSolution, w: SigmaByteWriter): Unit = { + GroupElementSerializer.serialize(s.pk, w) + GroupElementSerializer.serialize(s.w, w) + require(s.n.length == 8) // non-consensus check on prover side + w.putBytes(s.n) + val dBytes = BigIntegers.asUnsignedByteArray(s.d.bigInteger) + w.putUByte(dBytes.length) + w.putBytes(dBytes) + } + + override def parse(r: SigmaByteReader): AutolykosSolution = { + val pk = GroupElementSerializer.parse(r) + val w = GroupElementSerializer.parse(r) + val nonce = r.getBytes(8) + val dBytesLength = r.getUByte() + val d = BigInt(BigIntegers.fromUnsignedByteArray(r.getBytes(dBytesLength))) + AutolykosSolution(pk, w, nonce, d) + } + } + + object sigmaSerializerV2 extends SigmaSerializer[AutolykosSolution, AutolykosSolution] { + override def serialize(s: AutolykosSolution, w: SigmaByteWriter): Unit = { + GroupElementSerializer.serialize(s.pk, w) + require(s.n.length == 8) // non-consensus check on prover side + w.putBytes(s.n) + } + + override def parse(r: SigmaByteReader): AutolykosSolution = { + val pk = GroupElementSerializer.parse(r) + val nonce = r.getBytes(8) + AutolykosSolution(pk, wForV2, nonce, dForV2) + } + } +} + +/** + * Header of a block. It authenticates link to a previous block, other block sections + * (transactions, UTXO set transformation proofs, extension), UTXO set, votes for parameters + * to be changed and proof-of-work related data. + * + * @param version - protocol version + * @param parentId - id of a parent block header + * @param ADProofsRoot - digest of UTXO set transformation proofs + * @param stateRoot - AVL+ tree digest of UTXO set (after the block) + * @param transactionsRoot - Merkle tree digest of transactions in the block (BlockTransactions section) + * @param timestamp - block generation time reported by a miner + * @param nBits - difficulty encoded + * @param height - height of the block (genesis block height == 1) + * @param extensionRoot - Merkle tree digest of the extension section of the block + * @param powSolution - solution for the proof-of-work puzzle + * @param votes - votes for changing system parameters + * @param _bytes - serialized bytes of the header when not `null` + */ +case class ErgoHeader(override val version: ErgoHeader.Version, + override val parentId: ModifierId, + override val ADProofsRoot: Digest32, + override val stateRoot: ADDigest, //33 bytes! extra byte with tree height here! + override val transactionsRoot: Digest32, + override val timestamp: ErgoHeader.Timestamp, + override val nBits: Long, //actually it is unsigned int + override val height: Int, + override val extensionRoot: Digest32, + powSolution: AutolykosSolution, + override val votes: Array[Byte], //3 bytes + override val unparsedBytes: Array[Byte], + _bytes: Array[Byte]) extends + HeaderWithoutPow(version, parentId, ADProofsRoot, stateRoot, transactionsRoot, timestamp, + nBits, height, extensionRoot, votes, unparsedBytes) { + + lazy val bytes = if(_bytes != null) { + _bytes + } else { + ErgoHeader.sigmaSerializer.toBytes(this) + } + + lazy val serializedId: Array[Byte] = Blake2b256.hash(bytes) + + lazy val id = Colls.fromArray(serializedId) + +} + + +object ErgoHeader { + + type Timestamp = Long + + type Version = Byte + + object sigmaSerializer extends SigmaSerializer[ErgoHeader, ErgoHeader] { + override def serialize(hdr: ErgoHeader, w: SigmaByteWriter): Unit = { + HeaderWithoutPowSerializer.serialize(hdr, w) + if (hdr.version == 1) { + AutolykosSolution.sigmaSerializerV1.serialize(hdr.powSolution, w) + } else { + AutolykosSolution.sigmaSerializerV2.serialize(hdr.powSolution, w) + } + } + + override def parse(r: SigmaByteReader): ErgoHeader = { + val start = r.position + val headerWithoutPow = HeaderWithoutPowSerializer.parse(r) + val powSolution = if (headerWithoutPow.version == 1) { + AutolykosSolution.sigmaSerializerV1.parse(r) + } else { + AutolykosSolution.sigmaSerializerV2.parse(r) + } + val end = r.position + val len = end - start + r.position = start + val headerBytes = r.getBytes(len) // also moves position back to end + headerWithoutPow.toHeader(powSolution, headerBytes) + } + } +} \ No newline at end of file diff --git a/data/shared/src/main/scala/org/ergoplatform/HeaderWithoutPow.scala b/data/shared/src/main/scala/org/ergoplatform/HeaderWithoutPow.scala index d29cc6cbd8..56e2eafb1b 100644 --- a/data/shared/src/main/scala/org/ergoplatform/HeaderWithoutPow.scala +++ b/data/shared/src/main/scala/org/ergoplatform/HeaderWithoutPow.scala @@ -21,7 +21,11 @@ class HeaderWithoutPow(val version: Byte, // 1 byte val height: Int, val extensionRoot: Digest32, val votes: Array[Byte], //3 bytes - val unparsedBytes: Array[Byte]) + val unparsedBytes: Array[Byte]) { + def toHeader(powSolution: AutolykosSolution, bytes: Array[Byte]): ErgoHeader = + ErgoHeader(version, parentId, ADProofsRoot, stateRoot, transactionsRoot, timestamp, + nBits, height, extensionRoot, powSolution, votes, unparsedBytes, bytes) +} object HeaderWithoutPow { diff --git a/data/shared/src/main/scala/sigma/ast/methods.scala b/data/shared/src/main/scala/sigma/ast/methods.scala index e58fa35adb..97c2302b2d 100644 --- a/data/shared/src/main/scala/sigma/ast/methods.scala +++ b/data/shared/src/main/scala/sigma/ast/methods.scala @@ -1460,7 +1460,7 @@ case object SHeaderMethods extends MonoTypeMethods { lazy val checkPowMethod = SMethod( this, "checkPow", SFunc(Array(SHeader), SBoolean), 16, GroupGenerator.costKind) // todo: cost .withIRInfo(MethodCallIrBuilder) - .withInfo(Xor, "Byte-wise XOR of two collections of bytes") // todo: desc + .withInfo(Xor, "Check PoW of this header") // todo: desc def checkPow_eval(mc: MethodCall, G: SigmaDslBuilder, header: Header) (implicit E: ErgoTreeEvaluator): Boolean = { diff --git a/data/shared/src/main/scala/sigma/data/CHeader.scala b/data/shared/src/main/scala/sigma/data/CHeader.scala new file mode 100644 index 0000000000..ed75fee4be --- /dev/null +++ b/data/shared/src/main/scala/sigma/data/CHeader.scala @@ -0,0 +1,132 @@ +package sigma.data + +import org.ergoplatform.{AutolykosSolution, ErgoHeader, HeaderWithoutPow, HeaderWithoutPowSerializer} +import scorex.crypto.authds.ADDigest +import scorex.crypto.hash.Digest32 +import scorex.util.{bytesToId, idToBytes} +import sigma.pow.Autolykos2PowValidation +import sigma.{AvlTree, BigInt, Coll, Colls, GroupElement, Header} + +/** A default implementation of [[Header]] interface. + * + * @see [[Header]] for detailed descriptions + */ +class CHeader(val ergoHeader: ErgoHeader) extends Header with WrapperOf[ErgoHeader] { + + /** Bytes representation of ModifierId of this Header */ + override lazy val id: Coll[Byte] = ergoHeader.id + + /** Block version, to be increased on every soft and hardfork. */ + override def version: Byte = ergoHeader.version + + /** Bytes representation of ModifierId of the parent block */ + override def parentId: Coll[Byte] = Colls.fromArray(idToBytes(ergoHeader.parentId)) + + /** Hash of ADProofs for transactions in a block */ + override def ADProofsRoot: Coll[Byte] = Colls.fromArray(ergoHeader.ADProofsRoot) + + /** AvlTree of a state after block application */ + override def stateRoot: AvlTree = CAvlTree(AvlTreeData.avlTreeFromDigest(Colls.fromArray(ergoHeader.stateRoot))) + + /** Root hash (for a Merkle tree) of transactions in a block. */ + override def transactionsRoot: Coll[Byte] = Colls.fromArray(ergoHeader.transactionsRoot) + + /** Block timestamp (in milliseconds since beginning of Unix Epoch) */ + override def timestamp: Long = ergoHeader.timestamp + + /** Current difficulty in a compressed view. + * NOTE: actually it is unsigned Int */ + override def nBits: Long = ergoHeader.nBits + + /** Block height */ + override def height: Int = ergoHeader.height + + /** Root hash of extension section */ + override def extensionRoot: Coll[Byte] = Colls.fromArray(ergoHeader.extensionRoot) + + /** Miner public key. Should be used to collect block rewards. + * Part of Autolykos solution. */ + override def minerPk: GroupElement = CGroupElement(ergoHeader.powSolution.pk) + + /** One-time public key. Prevents revealing of miners secret. */ + override def powOnetimePk: GroupElement = CGroupElement(ergoHeader.powSolution.w) + + /** nonce */ + override def powNonce: Coll[Byte] = Colls.fromArray(ergoHeader.powSolution.n) + + /** Distance between pseudo-random number, corresponding to nonce `powNonce` and a secret, + * corresponding to `minerPk`. The lower `powDistance` is, the harder it was to find this solution. */ + override def powDistance: BigInt = CBigInt(ergoHeader.powSolution.d.bigInteger) + + /** Miner votes for changing system parameters. */ + override def votes: Coll[Byte] = Colls.fromArray(ergoHeader.votes) + + override def unparsedBytes: Coll[Byte] = Colls.fromArray(ergoHeader.unparsedBytes) + + /** The data value wrapped by this wrapper. */ + override def wrappedValue: ErgoHeader = ergoHeader + + override def serializeWithoutPoW: Coll[Byte] = { + val headerWithoutPow = HeaderWithoutPow(version, bytesToId(parentId.toArray), Digest32 @@ ADProofsRoot.toArray, + ADDigest @@ stateRoot.digest.toArray, Digest32 @@ transactionsRoot.toArray, timestamp, + nBits, height, Digest32 @@ extensionRoot.toArray, votes.toArray, unparsedBytes.toArray) + Colls.fromArray(HeaderWithoutPowSerializer.toBytes(headerWithoutPow)) + } + + override def checkPow: Boolean = { + if (version == 1) { + throw new Exception("Autolykos v1 is not supported") //todo: more specific exception? + } else { + Autolykos2PowValidation.checkPoWForVersion2(this) + } + } + + override def hashCode(): Int = id.hashCode() + + override def equals(other: Any): Boolean = other match { + case ch: CHeader => ch.id == this.id + case _ => false + } +} + +object CHeader { + + def apply( id: Coll[Byte], // todo: ignored + version: Byte, + parentId: Coll[Byte], + ADProofsRoot: Coll[Byte], + stateRoot: AvlTree, + transactionsRoot: Coll[Byte], + timestamp: Long, + nBits: Long, + height: Int, + extensionRoot: Coll[Byte], + minerPk: GroupElement, + powOnetimePk: GroupElement, + powNonce: Coll[Byte], + powDistance: BigInt, + votes: Coll[Byte], + unparsedBytes: Coll[Byte] + ): CHeader = { + + val solution = AutolykosSolution( + minerPk.asInstanceOf[CGroupElement].wrappedValue, + powOnetimePk.asInstanceOf[CGroupElement].wrappedValue, + powNonce.toArray, + powDistance.asInstanceOf[CBigInt].wrappedValue) + + val h = ErgoHeader(version, bytesToId(parentId.toArray), Digest32 @@ ADProofsRoot.toArray, + ADDigest @@ stateRoot.digest.toArray, Digest32 @@ transactionsRoot.toArray, timestamp, nBits, height, + Digest32 @@ extensionRoot.toArray, solution, votes.toArray, unparsedBytes.toArray, null) + + new CHeader(h) + } + + /** Size of of Header.votes array. */ + val VotesSize: Int = SigmaConstants.VotesArraySize.value + + /** Size of nonce array from Autolykos POW solution in Header.powNonce array. */ + val NonceSize: Int = SigmaConstants.AutolykosPowSolutionNonceArraySize.value + + +} \ No newline at end of file diff --git a/data/shared/src/main/scala/sigma/serialization/DataSerializer.scala b/data/shared/src/main/scala/sigma/serialization/DataSerializer.scala index 5f554e96a1..92a54f9aa4 100644 --- a/data/shared/src/main/scala/sigma/serialization/DataSerializer.scala +++ b/data/shared/src/main/scala/sigma/serialization/DataSerializer.scala @@ -1,8 +1,9 @@ package sigma.serialization -import org.ergoplatform.ErgoBox +import org.ergoplatform.{ErgoBox, ErgoHeader} +import sigma.VersionContext import sigma.ast._ -import sigma.data.CBox +import sigma.data.{CBox, CHeader} /** This works in tandem with ConstantSerializer, if you change one make sure to check the other.*/ object DataSerializer extends CoreDataSerializer { @@ -15,6 +16,9 @@ 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 => + val h = v.asInstanceOf[CHeader] + ErgoHeader.sigmaSerializer.serialize(h.ergoHeader, w.asInstanceOf[SigmaByteWriter]) case _ => super.serialize(v, tpe, w) } @@ -32,6 +36,12 @@ 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 => + val depth = r.level + r.level = depth + 1 + val res = new CHeader(ErgoHeader.sigmaSerializer.parse(r.asInstanceOf[SigmaByteReader])) + r.level = r.level - 1 + res case t => super.deserialize(t, r) }).asInstanceOf[T#WrappedType] diff --git a/interpreter/shared/src/main/scala/sigmastate/eval/CHeader.scala b/interpreter/shared/src/main/scala/sigmastate/eval/CHeader.scala deleted file mode 100644 index c23118100b..0000000000 --- a/interpreter/shared/src/main/scala/sigmastate/eval/CHeader.scala +++ /dev/null @@ -1,57 +0,0 @@ -package sigmastate.eval - -import org.ergoplatform.{HeaderWithoutPow, HeaderWithoutPowSerializer} -import scorex.crypto.authds.ADDigest -import scorex.crypto.hash.Digest32 -import scorex.util.bytesToId -import sigma.data.SigmaConstants -import sigma.pow.Autolykos2PowValidation -import sigma.{AvlTree, BigInt, Coll, Colls, GroupElement, Header} - -/** A default implementation of [[Header]] interface. - * - * @see [[Header]] for detailed descriptions - */ -case class CHeader( - id: Coll[Byte], - version: Byte, - parentId: Coll[Byte], - ADProofsRoot: Coll[Byte], - stateRoot: AvlTree, - transactionsRoot: Coll[Byte], - timestamp: Long, - nBits: Long, - height: Int, - extensionRoot: Coll[Byte], - minerPk: GroupElement, - powOnetimePk: GroupElement, - powNonce: Coll[Byte], - powDistance: BigInt, - votes: Coll[Byte], - unparsedBytes: Coll[Byte] -) extends Header { - - override def serializeWithoutPoW: Coll[Byte] = { - val headerWithoutPow = HeaderWithoutPow(version, bytesToId(parentId.toArray), Digest32 @@ ADProofsRoot.toArray, - ADDigest @@ stateRoot.digest.toArray, Digest32 @@ transactionsRoot.toArray, timestamp, - nBits, height, Digest32 @@ extensionRoot.toArray, votes.toArray, unparsedBytes.toArray) - Colls.fromArray(HeaderWithoutPowSerializer.toBytes(headerWithoutPow)) - } - - override def checkPow: Boolean = { - if (version == 1) { - throw new Exception("Autolykos v1 is not supported") //todo: more specific exception? - } else { - Autolykos2PowValidation.checkPoWForVersion2(this) - } - } - -} - -object CHeader { - /** Size of of Header.votes array. */ - val VotesSize: Int = SigmaConstants.VotesArraySize.value - - /** Size of nonce array from Autolykos POW solution in Header.powNonce array. */ - val NonceSize: Int = SigmaConstants.AutolykosPowSolutionNonceArraySize.value -} \ No newline at end of file diff --git a/interpreter/shared/src/test/scala/sigma/serialization/DataSerializerSpecification.scala b/interpreter/shared/src/test/scala/sigma/serialization/DataSerializerSpecification.scala index 7cd9967e54..6009d215d8 100644 --- a/interpreter/shared/src/test/scala/sigma/serialization/DataSerializerSpecification.scala +++ b/interpreter/shared/src/test/scala/sigma/serialization/DataSerializerSpecification.scala @@ -6,7 +6,7 @@ import org.scalacheck.Arbitrary._ import sigma.data.{DataValueComparer, RType, SigmaBoolean, TupleColl} import sigma.ast.SCollection.SByteArray import sigmastate.eval._ -import sigma.{AvlTree, Colls, Evaluation} +import sigma.{AvlTree, Colls, Evaluation, Header, VersionContext} import sigma.ast.SType.AnyOps import sigma.ast._ import org.scalacheck.Gen @@ -14,7 +14,7 @@ import sigma.Extensions.ArrayOps import sigma.crypto.EcPointType import sigma.eval.SigmaDsl import sigma.util.Extensions.{BigIntegerOps, EcpOps, SigmaBooleanOps} -import sigmastate.interpreter.{CostAccumulator, CErgoTreeEvaluator} +import sigmastate.interpreter.{CErgoTreeEvaluator, CostAccumulator} import sigmastate.interpreter.CErgoTreeEvaluator.DefaultProfiler import sigmastate.utils.Helpers @@ -132,6 +132,20 @@ class DataSerializerSpecification extends SerializationSpecification { t.isInstanceOf[SerializerException] && t.getMessage.contains(s"BigInt value doesn't not fit into ${SBigInt.MaxSizeInBytes} bytes") }) + } + + property("header roundtrip") { + VersionContext.withVersions(VersionContext.V6SoftForkVersion, 1) { + forAll { x: Header => roundtrip[SHeader.type](x, SHeader) } + } + an[SerializerException] should be thrownBy ( + VersionContext.withVersions((VersionContext.V6SoftForkVersion - 1).toByte, 1) { + val h = headerGen.sample.get + val res = roundtrip[SHeader.type](h, SHeader) + println("r: " + res) + res + }) } + } diff --git a/interpreter/shared/src/test/scala/sigma/serialization/MethodCallSerializerSpecification.scala b/interpreter/shared/src/test/scala/sigma/serialization/MethodCallSerializerSpecification.scala index c65b86930c..2332aaccaa 100644 --- a/interpreter/shared/src/test/scala/sigma/serialization/MethodCallSerializerSpecification.scala +++ b/interpreter/shared/src/test/scala/sigma/serialization/MethodCallSerializerSpecification.scala @@ -4,6 +4,9 @@ import sigma.VersionContext import sigma.ast._ import sigma.validation.ValidationException +import scala.util.Try + + class MethodCallSerializerSpecification extends SerializationSpecification { property("MethodCall deserialization round trip") { @@ -48,8 +51,8 @@ class MethodCallSerializerSpecification extends SerializationSpecification { property("MethodCall deserialization round trip for Header.checkPow") { def code = { - val bi = HeaderConstant(headerGen.sample.get) - val expr = MethodCall(bi, + val h = HeaderConstant(headerGen.sample.get) + val expr = MethodCall(h, SHeaderMethods.checkPowMethod, Vector(), Map() @@ -61,11 +64,12 @@ class MethodCallSerializerSpecification extends SerializationSpecification { code } - an[ValidationException] should be thrownBy ( + // sigma.serialization.SerializerException: Don't know how to serialize (sigma.data.CHeader@51dbec76, SHeader) + an[SerializerException] should be thrownBy ( VersionContext.withVersions((VersionContext.V6SoftForkVersion - 1).toByte, 1) { code } - ) + ) } } diff --git a/interpreter/shared/src/test/scala/sigma/serialization/SerializationSpecification.scala b/interpreter/shared/src/test/scala/sigma/serialization/SerializationSpecification.scala index 30ae6af19b..36c75f3224 100644 --- a/interpreter/shared/src/test/scala/sigma/serialization/SerializationSpecification.scala +++ b/interpreter/shared/src/test/scala/sigma/serialization/SerializationSpecification.scala @@ -41,7 +41,7 @@ trait SerializationSpecification extends AnyPropSpec r.positionLimit shouldBe positionLimitBefore } - //check that pos and consumed are being implented correctly + //check that pos and consumed are being implemented correctly protected def predefinedBytesTestNotFomZeroElement[V <: Value[_ <: SType]](bytes: Array[Byte], v: V): Assertion = { val randomInt = Gen.chooseNum(1, 20).sample.get val randomBytes = Gen.listOfN(randomInt, arbByte.arbitrary).sample.get.toArray diff --git a/interpreter/shared/src/test/scala/special/sigma/SigmaTestingData.scala b/interpreter/shared/src/test/scala/special/sigma/SigmaTestingData.scala index 6b8c833931..d1253d4686 100644 --- a/interpreter/shared/src/test/scala/special/sigma/SigmaTestingData.scala +++ b/interpreter/shared/src/test/scala/special/sigma/SigmaTestingData.scala @@ -12,7 +12,7 @@ import scorex.crypto.hash.{Blake2b256, Digest32} import scorex.util.ModifierId import sigma.ast._ import sigma.Extensions.ArrayOps -import sigmastate.eval.{CHeader, CPreHeader} +import sigmastate.eval.CPreHeader import sigmastate.helpers.TestingCommons import sigma.serialization.ErgoTreeSerializer import sigma.serialization.generators.ObjectGenerators @@ -268,7 +268,7 @@ trait SigmaTestingData extends TestingCommons with ObjectGenerators { val h1: Header = create_h1() - val h2: Header = create_h1().asInstanceOf[CHeader].copy(height = 2) + val h2: Header = new CHeader(h1.asInstanceOf[CHeader].wrappedValue.copy(height = 2)) val dlog_instances = new CloneSet(1000, ProveDlog( SigmaDsl.toECPoint(create_ge1()).asInstanceOf[EcPointType] diff --git a/sdk/js/src/main/scala/org/ergoplatform/sdk/js/Isos.scala b/sdk/js/src/main/scala/org/ergoplatform/sdk/js/Isos.scala index 340765d313..5cf7889894 100644 --- a/sdk/js/src/main/scala/org/ergoplatform/sdk/js/Isos.scala +++ b/sdk/js/src/main/scala/org/ergoplatform/sdk/js/Isos.scala @@ -12,12 +12,12 @@ import sigma.Extensions.CollBytesOps import sigma.ast.syntax.GroupElementConstant import sigma.ast.{Constant, GroupElementConstant, SType} import sigma.data.Iso.{isoStringToArray, isoStringToColl} -import sigma.data.{CBigInt, CGroupElement, Digest32Coll, Digest32CollRType, Iso} +import sigma.data.{CBigInt, CGroupElement, CHeader, Digest32Coll, Digest32CollRType, Iso} import sigma.interpreter.{ContextExtension, ProverResult} import sigma.js.{AvlTree, GroupElement} import sigma.serialization.{ErgoTreeSerializer, ValueSerializer} import sigma.{Coll, Colls} -import sigmastate.eval.{CHeader, CPreHeader} +import sigmastate.eval.CPreHeader import sigmastate.fleetSdkCommon.distEsmTypesBoxesMod.Box import sigmastate.fleetSdkCommon.distEsmTypesCommonMod.HexString import sigmastate.fleetSdkCommon.distEsmTypesRegistersMod.NonMandatoryRegisters diff --git a/sdk/shared/src/main/scala/org/ergoplatform/sdk/JsonCodecs.scala b/sdk/shared/src/main/scala/org/ergoplatform/sdk/JsonCodecs.scala index c2fc1c0c8c..f3ece3a894 100644 --- a/sdk/shared/src/main/scala/org/ergoplatform/sdk/JsonCodecs.scala +++ b/sdk/shared/src/main/scala/org/ergoplatform/sdk/JsonCodecs.scala @@ -12,7 +12,7 @@ import scorex.crypto.hash.Digest32 import scorex.util.ModifierId import sigma.Extensions.ArrayOps import sigma.ast.{ErgoTree, EvaluatedValue, SType} -import sigma.data.{AvlTreeData, AvlTreeFlags, CBigInt, Digest32Coll, WrapperOf} +import sigma.data.{AvlTreeData, AvlTreeFlags, CBigInt, CHeader, Digest32Coll, WrapperOf} import sigma.eval.Extensions.EvalIterableOps import sigma.eval.SigmaDsl import sigma.interpreter.{ContextExtension, ProverResult} @@ -20,7 +20,7 @@ import sigma.serialization.{ErgoTreeSerializer, ValueSerializer} import sigma.validation.SigmaValidationSettings import sigma.{AnyValue, Coll, Colls, Header, PreHeader, SigmaException} import sigmastate.eval.{CPreHeader, _} -import sigmastate.utils.Helpers._ // required for Scala 2.11 +import sigmastate.utils.Helpers._ import java.math.BigInteger import scala.collection.mutable From 2ad11dfcbbf1dd25df1705ba565289516e222466 Mon Sep 17 00:00:00 2001 From: Alexander Slesarenko Date: Thu, 9 May 2024 20:13:58 +0100 Subject: [PATCH 054/314] i966-template-compiler: use default values of parameters in compiler env --- .../sigmastate/lang/ContractParser.scala | 6 +- .../sigmastate/lang/ContractParserSpec.scala | 4 +- .../lang/SigmaTemplateCompiler.scala | 12 ++- .../lang/SigmaTemplateCompilerTest.scala | 83 +++++++++++++++++-- 4 files changed, 89 insertions(+), 16 deletions(-) diff --git a/parsers/shared/src/main/scala/sigmastate/lang/ContractParser.scala b/parsers/shared/src/main/scala/sigmastate/lang/ContractParser.scala index 87dd20ab0c..69136c5a91 100644 --- a/parsers/shared/src/main/scala/sigmastate/lang/ContractParser.scala +++ b/parsers/shared/src/main/scala/sigmastate/lang/ContractParser.scala @@ -3,7 +3,7 @@ package sigmastate.lang import fastparse._ import fastparse.NoWhitespace._ import SigmaParser._ -import sigma.ast.SType +import sigma.ast.{Constant, SType} import sigma.ast.syntax.SValue import sigmastate.lang.parsers.Basic @@ -105,7 +105,7 @@ object ContractDoc { * @param tpe The type of the parameter. * @param defaultValue The default value assigned to the parameter, if it exists. */ -case class ContractParam(name: String, tpe: SType, defaultValue: Option[SType#WrappedType]) +case class ContractParam(name: String, tpe: SType, defaultValue: Option[Constant[SType]]) /** * Represents the signature of a contract. @@ -187,7 +187,7 @@ object ContractParser { def annotation[_: P] = P("@contract") - def paramDefault[_: P] = P(WL.? ~ `=` ~ WL.? ~ ExprLiteral).map(s => s.asWrappedType) + def paramDefault[_: P] = P(WL.? ~ `=` ~ WL.? ~ ExprLiteral) def param[_: P] = P(WL.? ~ Id.! ~ ":" ~ Type ~ paramDefault.?).map(s => ContractParam(s._1, s._2, s._3)) diff --git a/parsers/shared/src/test/scala/sigmastate/lang/ContractParserSpec.scala b/parsers/shared/src/test/scala/sigmastate/lang/ContractParserSpec.scala index 9a412b7100..a4c535ac8f 100644 --- a/parsers/shared/src/test/scala/sigmastate/lang/ContractParserSpec.scala +++ b/parsers/shared/src/test/scala/sigmastate/lang/ContractParserSpec.scala @@ -34,8 +34,8 @@ class ContractParserSpec extends AnyPropSpec with ScalaCheckPropertyChecks with parsed.name shouldBe "contractName" parsed.params should contain theSameElementsInOrderAs Seq( - ContractParam("p1", SInt, Some(IntConstant(5).asWrappedType)), - ContractParam("p2", SString, Some(StringConstant("default string").asWrappedType)), + ContractParam("p1", SInt, Some(IntConstant(5))), + ContractParam("p2", SString, Some(StringConstant("default string"))), ContractParam("param3", SLong, None) ) } diff --git a/sc/shared/src/main/scala/sigmastate/lang/SigmaTemplateCompiler.scala b/sc/shared/src/main/scala/sigmastate/lang/SigmaTemplateCompiler.scala index ec94bdfd3a..c751962826 100644 --- a/sc/shared/src/main/scala/sigmastate/lang/SigmaTemplateCompiler.scala +++ b/sc/shared/src/main/scala/sigmastate/lang/SigmaTemplateCompiler.scala @@ -2,9 +2,9 @@ package sigmastate.lang import fastparse.Parsed import org.ergoplatform.sdk.ContractTemplate -import sigmastate.eval.CompiletimeIRContext +import sigmastate.eval.{CompiletimeIRContext, msgCostLimitError} import org.ergoplatform.sdk.Parameter -import sigma.ast.SourceContext +import sigma.ast.{Constant, SType, SourceContext} import sigma.ast.syntax.SValue import sigmastate.interpreter.Interpreter.ScriptEnv import sigmastate.lang.parsers.ParserException @@ -23,7 +23,11 @@ class SigmaTemplateCompiler(networkPrefix: Byte) { ContractParser.parse(source) match { case Parsed.Success(template, _) => { implicit val ir = new CompiletimeIRContext - val result = sigmaCompiler.compileParsed(env, template.body) + val mergedEnv = template.signature.params + .collect { case ContractParam(name, tpe, Some(defaultValue)) => + name -> defaultValue + }.toMap ++ env + val result = sigmaCompiler.compileParsed(mergedEnv, template.body) assemble(template, result.buildTree) } case f: Parsed.Failure => @@ -46,7 +50,7 @@ class SigmaTemplateCompiler(networkPrefix: Byte) { name = parsed.signature.name, description = parsed.docs.description, constTypes = constTypes.toIndexedSeq, - constValues = constValues, + constValues = constValues.map(_.map(_.map(_.value))), parameters = contractParams.toIndexedSeq, expressionTree = expr.toSigmaProp ) diff --git a/sc/shared/src/test/scala/sigmastate/lang/SigmaTemplateCompilerTest.scala b/sc/shared/src/test/scala/sigmastate/lang/SigmaTemplateCompilerTest.scala index df8f644172..168815452d 100644 --- a/sc/shared/src/test/scala/sigmastate/lang/SigmaTemplateCompilerTest.scala +++ b/sc/shared/src/test/scala/sigmastate/lang/SigmaTemplateCompilerTest.scala @@ -2,13 +2,14 @@ package sigmastate.lang import org.ergoplatform.ErgoAddressEncoder import org.ergoplatform.sdk.Parameter -import org.scalatest.matchers.should.Matchers import org.scalatest.propspec.AnyPropSpec import org.scalatestplus.scalacheck.ScalaCheckPropertyChecks -import sigma.ast.{IntConstant, SInt, SLong, SString, StringConstant} +import sigma.ast.{SBoolean, SInt, SLong, SString} +import sigma.exceptions.TyperException import sigmastate.eval.CompiletimeIRContext +import sigmastate.interpreter.Interpreter.ScriptEnv -class SigmaTemplateCompilerTest extends AnyPropSpec with ScalaCheckPropertyChecks with Matchers { +class SigmaTemplateCompilerTest extends AnyPropSpec with ScalaCheckPropertyChecks with LangTests { property("compiles full contract template") { val source = """/** This is my contracts description. @@ -36,8 +37,8 @@ class SigmaTemplateCompilerTest extends AnyPropSpec with ScalaCheckPropertyCheck ) template.constTypes should contain theSameElementsInOrderAs Seq(SInt, SString, SLong) template.constValues.get should contain theSameElementsInOrderAs IndexedSeq( - Some(IntConstant(5).asWrappedType), - Some(StringConstant("default string").asWrappedType), + Some(5), + Some("default string"), None ) @@ -73,8 +74,8 @@ class SigmaTemplateCompilerTest extends AnyPropSpec with ScalaCheckPropertyCheck ) template.constTypes should contain theSameElementsInOrderAs Seq(SInt, SString) template.constValues.get should contain theSameElementsInOrderAs IndexedSeq( - Some(IntConstant(5).asWrappedType), - Some(StringConstant("default string").asWrappedType) + Some(5), + Some("default string") ) val sigmaCompiler = new SigmaCompiler(ErgoAddressEncoder.MainnetNetworkPrefix) @@ -83,6 +84,74 @@ class SigmaTemplateCompilerTest extends AnyPropSpec with ScalaCheckPropertyCheck template.expressionTree shouldBe result.buildTree } + + property("uses default value from parameter definition") { + val source = + """/**/ + |@contract def contractName(p: Boolean = true) = sigmaProp(p) + |""".stripMargin + val compiler = SigmaTemplateCompiler(ErgoAddressEncoder.MainnetNetworkPrefix) + val template = compiler.compile(Map.empty, source) + + template.parameters should contain theSameElementsInOrderAs IndexedSeq( + Parameter("p", "", 0), + ) + template.constTypes should contain theSameElementsInOrderAs Seq(SBoolean) + template.constValues.get should contain theSameElementsInOrderAs IndexedSeq( + Some(true), + ) + + val sigmaCompiler = new SigmaCompiler(ErgoAddressEncoder.MainnetNetworkPrefix) + implicit val ir = new CompiletimeIRContext + val result = sigmaCompiler.compile(Map("p" -> true), "sigmaProp(p)") + + template.expressionTree shouldBe result.buildTree + } + + property("uses given environment when provided (overriding default value)") { + val explicitEnv = Map("low" -> 10, "high" -> 100) + val source = + """/**/ + |@contract def contractName(low: Int = 0, high: Int) = sigmaProp(low < HEIGHT && HEIGHT < high) + |""".stripMargin + val compiler = SigmaTemplateCompiler(ErgoAddressEncoder.MainnetNetworkPrefix) + val template = compiler.compile(explicitEnv, source) + + template.parameters should contain theSameElementsInOrderAs IndexedSeq( + Parameter("low", "", 0), + Parameter("high", "", 1), + ) + template.constTypes should contain theSameElementsInOrderAs Seq(SInt, SInt) + // check parsed default values + template.constValues.get should contain theSameElementsInOrderAs IndexedSeq( + Some(0), + None, + ) + + val sigmaCompiler = new SigmaCompiler(ErgoAddressEncoder.MainnetNetworkPrefix) + implicit val ir = new CompiletimeIRContext + val result = sigmaCompiler.compile( + env = explicitEnv, + code = "sigmaProp(low < HEIGHT && HEIGHT < high)" + ) + + template.expressionTree shouldBe result.buildTree + } + + property("fails when constant value in not provided") { + // NOTE: parameter `high` without default value */ + val source = + """/**/ + |@contract def contractName(low: Int = 0, high: Int) = sigmaProp(low < HEIGHT && HEIGHT < high) + |""".stripMargin + val compiler = SigmaTemplateCompiler(ErgoAddressEncoder.MainnetNetworkPrefix) + val env: ScriptEnv = Map.empty // no value for "high" + assertExceptionThrown( + compiler.compile(env, source), + exceptionLike[TyperException]("Cannot assign type for variable 'high' because it is not found in env") + ) + } + } From 98fd5b7d0bf93fc87ebc4a8e98d7e31eefa8c678 Mon Sep 17 00:00:00 2001 From: Alexander Slesarenko Date: Thu, 9 May 2024 20:20:30 +0100 Subject: [PATCH 055/314] i966-template-compiler: fix type of ContractParam field --- .../src/main/scala/sigmastate/lang/ContractParser.scala | 4 ++-- .../src/test/scala/sigmastate/lang/ContractParserSpec.scala | 5 +++-- .../main/scala/sigmastate/lang/SigmaTemplateCompiler.scala | 2 +- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/parsers/shared/src/main/scala/sigmastate/lang/ContractParser.scala b/parsers/shared/src/main/scala/sigmastate/lang/ContractParser.scala index 69136c5a91..a192a789b9 100644 --- a/parsers/shared/src/main/scala/sigmastate/lang/ContractParser.scala +++ b/parsers/shared/src/main/scala/sigmastate/lang/ContractParser.scala @@ -105,7 +105,7 @@ object ContractDoc { * @param tpe The type of the parameter. * @param defaultValue The default value assigned to the parameter, if it exists. */ -case class ContractParam(name: String, tpe: SType, defaultValue: Option[Constant[SType]]) +case class ContractParam(name: String, tpe: SType, defaultValue: Option[SType#WrappedType]) /** * Represents the signature of a contract. @@ -189,7 +189,7 @@ object ContractParser { def paramDefault[_: P] = P(WL.? ~ `=` ~ WL.? ~ ExprLiteral) - def param[_: P] = P(WL.? ~ Id.! ~ ":" ~ Type ~ paramDefault.?).map(s => ContractParam(s._1, s._2, s._3)) + def param[_: P] = P(WL.? ~ Id.! ~ ":" ~ Type ~ paramDefault.?).map(s => ContractParam(s._1, s._2, s._3.map(_.value))) def params[_: P] = P("(" ~ param.rep(1, ",").? ~ ")") } diff --git a/parsers/shared/src/test/scala/sigmastate/lang/ContractParserSpec.scala b/parsers/shared/src/test/scala/sigmastate/lang/ContractParserSpec.scala index a4c535ac8f..bce252d866 100644 --- a/parsers/shared/src/test/scala/sigmastate/lang/ContractParserSpec.scala +++ b/parsers/shared/src/test/scala/sigmastate/lang/ContractParserSpec.scala @@ -3,6 +3,7 @@ package sigmastate.lang import org.scalatest.matchers.should.Matchers import org.scalatest.propspec.AnyPropSpec import org.scalatestplus.scalacheck.ScalaCheckPropertyChecks +import sigma.ast.SType.AnyOps import sigma.ast._ class ContractParserSpec extends AnyPropSpec with ScalaCheckPropertyChecks with Matchers { @@ -34,8 +35,8 @@ class ContractParserSpec extends AnyPropSpec with ScalaCheckPropertyChecks with parsed.name shouldBe "contractName" parsed.params should contain theSameElementsInOrderAs Seq( - ContractParam("p1", SInt, Some(IntConstant(5))), - ContractParam("p2", SString, Some(StringConstant("default string"))), + ContractParam("p1", SInt, Some(5.asWrappedType)), + ContractParam("p2", SString, Some("default string".asWrappedType)), ContractParam("param3", SLong, None) ) } diff --git a/sc/shared/src/main/scala/sigmastate/lang/SigmaTemplateCompiler.scala b/sc/shared/src/main/scala/sigmastate/lang/SigmaTemplateCompiler.scala index c751962826..b124684d50 100644 --- a/sc/shared/src/main/scala/sigmastate/lang/SigmaTemplateCompiler.scala +++ b/sc/shared/src/main/scala/sigmastate/lang/SigmaTemplateCompiler.scala @@ -50,7 +50,7 @@ class SigmaTemplateCompiler(networkPrefix: Byte) { name = parsed.signature.name, description = parsed.docs.description, constTypes = constTypes.toIndexedSeq, - constValues = constValues.map(_.map(_.map(_.value))), + constValues = constValues, parameters = contractParams.toIndexedSeq, expressionTree = expr.toSigmaProp ) From 232c25d56ccd2ed035bbe55a426a7a59d96445b7 Mon Sep 17 00:00:00 2001 From: Alexander Slesarenko Date: Thu, 9 May 2024 22:16:52 +0100 Subject: [PATCH 056/314] i966-template-compiler: fix for Scala 2.11 --- .../scala/sigmastate/lang/SigmaTemplateCompilerTest.scala | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sc/shared/src/test/scala/sigmastate/lang/SigmaTemplateCompilerTest.scala b/sc/shared/src/test/scala/sigmastate/lang/SigmaTemplateCompilerTest.scala index 168815452d..82a080cf1a 100644 --- a/sc/shared/src/test/scala/sigmastate/lang/SigmaTemplateCompilerTest.scala +++ b/sc/shared/src/test/scala/sigmastate/lang/SigmaTemplateCompilerTest.scala @@ -94,11 +94,11 @@ class SigmaTemplateCompilerTest extends AnyPropSpec with ScalaCheckPropertyCheck val template = compiler.compile(Map.empty, source) template.parameters should contain theSameElementsInOrderAs IndexedSeq( - Parameter("p", "", 0), + Parameter("p", "", 0) ) template.constTypes should contain theSameElementsInOrderAs Seq(SBoolean) template.constValues.get should contain theSameElementsInOrderAs IndexedSeq( - Some(true), + Some(true) ) val sigmaCompiler = new SigmaCompiler(ErgoAddressEncoder.MainnetNetworkPrefix) @@ -119,13 +119,13 @@ class SigmaTemplateCompilerTest extends AnyPropSpec with ScalaCheckPropertyCheck template.parameters should contain theSameElementsInOrderAs IndexedSeq( Parameter("low", "", 0), - Parameter("high", "", 1), + Parameter("high", "", 1) ) template.constTypes should contain theSameElementsInOrderAs Seq(SInt, SInt) // check parsed default values template.constValues.get should contain theSameElementsInOrderAs IndexedSeq( Some(0), - None, + None ) val sigmaCompiler = new SigmaCompiler(ErgoAddressEncoder.MainnetNetworkPrefix) From eb6270c88e5687a6d0b88000b05bee311b7d3fa5 Mon Sep 17 00:00:00 2001 From: Alexander Slesarenko Date: Sun, 12 May 2024 12:44:41 +0100 Subject: [PATCH 057/314] i966-template-compiler: create ConstantPlaceholder for each parameter in the compiled expression --- .../scala/sigmastate/eval/GraphBuilding.scala | 14 ++++ .../scala/sigmastate/eval/TreeBuilding.scala | 4 ++ .../scala/sigmastate/lang/SigmaCompiler.scala | 10 ++- .../lang/SigmaTemplateCompiler.scala | 23 +++---- .../scala/sigmastate/lang/SigmaTyper.scala | 8 ++- .../lang/SigmaTemplateCompilerTest.scala | 67 ++++++++----------- .../sigmastate/lang/SigmaTyperTest.scala | 6 +- 7 files changed, 73 insertions(+), 59 deletions(-) diff --git a/sc/shared/src/main/scala/sigmastate/eval/GraphBuilding.scala b/sc/shared/src/main/scala/sigmastate/eval/GraphBuilding.scala index 5ddcdfa946..4a126754a5 100644 --- a/sc/shared/src/main/scala/sigmastate/eval/GraphBuilding.scala +++ b/sc/shared/src/main/scala/sigmastate/eval/GraphBuilding.scala @@ -381,6 +381,18 @@ trait GraphBuilding extends SigmaLibrary { IR: IRContext => def error(msg: String) = throw new GraphBuildingException(msg, None) def error(msg: String, srcCtx: Option[SourceContext]) = throw new GraphBuildingException(msg, srcCtx) + /** Graph node to represent a placeholder of a constant in ErgoTree. + * @param id Zero based index in ErgoTree.constants array. + * @param resultType type descriptor of the constant value. + */ + case class ConstantPlaceholder[T](id: Int, resultType: Elem[T]) extends Def[T] + + /** Smart constructor method for [[ConstantPlaceholder]], should be used instead of the + * class constructor. + */ + @inline def constantPlaceholder[T](id: Int, eT: Elem[T]): Ref[T] = ConstantPlaceholder(id, eT) + + /** Translates the given typed expression to IR graph representing a function from * Context to some type T. * @param env contains values for each named constant used @@ -465,6 +477,8 @@ trait GraphBuilding extends SigmaLibrary { IR: IRContext => val resV = toRep(v)(e) resV } + case sigma.ast.ConstantPlaceholder(id, tpe) => + constantPlaceholder(id, stypeToElem(tpe)) case sigma.ast.Context => ctx case Global => sigmaDslBuilder case Height => ctx.HEIGHT diff --git a/sc/shared/src/main/scala/sigmastate/eval/TreeBuilding.scala b/sc/shared/src/main/scala/sigmastate/eval/TreeBuilding.scala index 27f659c1ed..11ae0b85f4 100644 --- a/sc/shared/src/main/scala/sigmastate/eval/TreeBuilding.scala +++ b/sc/shared/src/main/scala/sigmastate/eval/TreeBuilding.scala @@ -183,6 +183,10 @@ trait TreeBuilding extends SigmaLibrary { IR: IRContext => case None => mkConstant[tpe.type](x.asInstanceOf[tpe.WrappedType], tpe) } + case Def(IR.ConstantPlaceholder(id, elem)) => + val tpe = elemToSType(elem) + mkConstantPlaceholder[tpe.type](id, tpe) + case Def(wc: LiftedConst[a,_]) => val tpe = elemToSType(s.elem) mkConstant[tpe.type](wc.constValue.asInstanceOf[tpe.WrappedType], tpe) diff --git a/sc/shared/src/main/scala/sigmastate/lang/SigmaCompiler.scala b/sc/shared/src/main/scala/sigmastate/lang/SigmaCompiler.scala index 849167e159..3e83aa866c 100644 --- a/sc/shared/src/main/scala/sigmastate/lang/SigmaCompiler.scala +++ b/sc/shared/src/main/scala/sigmastate/lang/SigmaCompiler.scala @@ -72,7 +72,8 @@ class SigmaCompiler private(settings: CompilerSettings) { val predefinedFuncRegistry = new PredefinedFuncRegistry(builder) val binder = new SigmaBinder(env, builder, networkPrefix, predefinedFuncRegistry) val bound = binder.bind(parsed) - val typer = new SigmaTyper(builder, predefinedFuncRegistry, settings.lowerMethodCalls) + val typeEnv = env.collect { case (k, v: SType) => k -> v } + val typer = new SigmaTyper(builder, predefinedFuncRegistry, typeEnv, settings.lowerMethodCalls) val typed = typer.typecheck(bound) typed } @@ -91,7 +92,12 @@ class SigmaCompiler private(settings: CompilerSettings) { /** Compiles the given typed expression. */ def compileTyped(env: ScriptEnv, typedExpr: SValue)(implicit IR: IRContext): CompilerResult[IR.type] = { - val compiledGraph = IR.buildGraph(env, typedExpr) + val placeholdersEnv = env + .collect { case (name, t: SType) => name -> t } + .zipWithIndex + .map { case ((name, t), index) => name -> ConstantPlaceholder(index, t) } + .toMap + val compiledGraph = IR.buildGraph(env ++ placeholdersEnv, typedExpr) val compiledTree = IR.buildTree(compiledGraph) CompilerResult(env, "", compiledGraph, compiledTree) } diff --git a/sc/shared/src/main/scala/sigmastate/lang/SigmaTemplateCompiler.scala b/sc/shared/src/main/scala/sigmastate/lang/SigmaTemplateCompiler.scala index b124684d50..f77735118c 100644 --- a/sc/shared/src/main/scala/sigmastate/lang/SigmaTemplateCompiler.scala +++ b/sc/shared/src/main/scala/sigmastate/lang/SigmaTemplateCompiler.scala @@ -1,12 +1,10 @@ package sigmastate.lang import fastparse.Parsed -import org.ergoplatform.sdk.ContractTemplate -import sigmastate.eval.{CompiletimeIRContext, msgCostLimitError} -import org.ergoplatform.sdk.Parameter -import sigma.ast.{Constant, SType, SourceContext} +import org.ergoplatform.sdk.{ContractTemplate, Parameter} +import sigma.ast.SourceContext import sigma.ast.syntax.SValue -import sigmastate.interpreter.Interpreter.ScriptEnv +import sigmastate.eval.CompiletimeIRContext import sigmastate.lang.parsers.ParserException /** Compiler which compiles Ergo contract templates into a [[ContractTemplate]]. */ @@ -19,17 +17,14 @@ class SigmaTemplateCompiler(networkPrefix: Byte) { * @param source The ErgoScript contract source code. * @return The contract template. */ - def compile(env: ScriptEnv, source: String): ContractTemplate = { + def compile(source: String): ContractTemplate = { ContractParser.parse(source) match { - case Parsed.Success(template, _) => { + case Parsed.Success(parsedTemplate, _) => implicit val ir = new CompiletimeIRContext - val mergedEnv = template.signature.params - .collect { case ContractParam(name, tpe, Some(defaultValue)) => - name -> defaultValue - }.toMap ++ env - val result = sigmaCompiler.compileParsed(mergedEnv, template.body) - assemble(template, result.buildTree) - } + val parEnv = parsedTemplate.signature.params.map { p => p.name -> p.tpe }.toMap + val result = sigmaCompiler.compileParsed(parEnv, parsedTemplate.body) + assemble(parsedTemplate, result.buildTree) + case f: Parsed.Failure => throw new ParserException(s"Contract template syntax error: $f", Some(SourceContext.fromParserFailure(f))) } diff --git a/sc/shared/src/main/scala/sigmastate/lang/SigmaTyper.scala b/sc/shared/src/main/scala/sigmastate/lang/SigmaTyper.scala index 7fd6dadd45..857ed66338 100644 --- a/sc/shared/src/main/scala/sigmastate/lang/SigmaTyper.scala +++ b/sc/shared/src/main/scala/sigmastate/lang/SigmaTyper.scala @@ -1,6 +1,5 @@ package sigmastate.lang -import org.ergoplatform._ import sigma.ast.SCollection.{SBooleanArray, SByteArray} import sigma.ast._ import sigma.ast.syntax.SValue @@ -19,6 +18,7 @@ import scala.collection.mutable.ArrayBuffer */ class SigmaTyper(val builder: SigmaBuilder, predefFuncRegistry: PredefinedFuncRegistry, + typeEnv: Map[String, SType], lowerMethodCalls: Boolean) { import SigmaTyper._ import builder._ @@ -28,8 +28,10 @@ class SigmaTyper(val builder: SigmaBuilder, import SType.tT - private val predefinedEnv: Map[String, SType] = - predefFuncRegistry.funcs.map { case (k, f) => k -> f.declaration.tpe }.toMap + private val predefinedEnv: Map[String, SType] = { + val predefFuncs = predefFuncRegistry.funcs.map { case (k, f) => k -> f.declaration.tpe }.toMap + predefFuncs ++ typeEnv + } private def processGlobalMethod(srcCtx: Nullable[SourceContext], method: SMethod, diff --git a/sc/shared/src/test/scala/sigmastate/lang/SigmaTemplateCompilerTest.scala b/sc/shared/src/test/scala/sigmastate/lang/SigmaTemplateCompilerTest.scala index 82a080cf1a..a0f9c7d8aa 100644 --- a/sc/shared/src/test/scala/sigmastate/lang/SigmaTemplateCompilerTest.scala +++ b/sc/shared/src/test/scala/sigmastate/lang/SigmaTemplateCompilerTest.scala @@ -4,12 +4,14 @@ import org.ergoplatform.ErgoAddressEncoder import org.ergoplatform.sdk.Parameter import org.scalatest.propspec.AnyPropSpec import org.scalatestplus.scalacheck.ScalaCheckPropertyChecks -import sigma.ast.{SBoolean, SInt, SLong, SString} +import sigma.ast.{BinAnd, BoolToSigmaProp, ConstantPlaceholder, Height, LT, SBoolean, SInt, SLong, SString, TrueLeaf} import sigma.exceptions.TyperException -import sigmastate.eval.CompiletimeIRContext +import sigmastate.helpers.SigmaPPrint import sigmastate.interpreter.Interpreter.ScriptEnv class SigmaTemplateCompilerTest extends AnyPropSpec with ScalaCheckPropertyChecks with LangTests { + val templateCompiler = SigmaTemplateCompiler(ErgoAddressEncoder.MainnetNetworkPrefix) + property("compiles full contract template") { val source = """/** This is my contracts description. @@ -25,8 +27,7 @@ class SigmaTemplateCompilerTest extends AnyPropSpec with ScalaCheckPropertyCheck |@contract def contractName(p1: Int = 5, p2: String = "default string", param3: Long) = { | sigmaProp(true) |}""".stripMargin - val compiler = SigmaTemplateCompiler(ErgoAddressEncoder.MainnetNetworkPrefix) - val template = compiler.compile(Map.empty, source) + val template = templateCompiler.compile(source) template.name shouldBe "contractName" template.description shouldBe "This is my contracts description. Here is another line describing what it does in more detail." @@ -42,11 +43,8 @@ class SigmaTemplateCompilerTest extends AnyPropSpec with ScalaCheckPropertyCheck None ) - val sigmaCompiler = new SigmaCompiler(ErgoAddressEncoder.MainnetNetworkPrefix) - implicit val ir = new CompiletimeIRContext - val result = sigmaCompiler.compile(Map.empty, "{ sigmaProp(true) }") - - template.expressionTree shouldBe result.buildTree + val expectedExpr = BoolToSigmaProp(TrueLeaf) + template.expressionTree shouldBe expectedExpr } property("compiles contract template without braces") { @@ -63,8 +61,7 @@ class SigmaTemplateCompilerTest extends AnyPropSpec with ScalaCheckPropertyCheck |*/ |@contract def contractName(p1: Int = 5, p2: String = "default string") = sigmaProp(true) |""".stripMargin - val compiler = SigmaTemplateCompiler(ErgoAddressEncoder.MainnetNetworkPrefix) - val template = compiler.compile(Map.empty, source) + val template = templateCompiler.compile(source) template.name shouldBe "contractName" template.description shouldBe "This is my contracts description. Here is another line describing what it does in more detail." @@ -78,11 +75,8 @@ class SigmaTemplateCompilerTest extends AnyPropSpec with ScalaCheckPropertyCheck Some("default string") ) - val sigmaCompiler = new SigmaCompiler(ErgoAddressEncoder.MainnetNetworkPrefix) - implicit val ir = new CompiletimeIRContext - val result = sigmaCompiler.compile(Map.empty, "sigmaProp(true)") - - template.expressionTree shouldBe result.buildTree + val expectedExpr = BoolToSigmaProp(TrueLeaf) + template.expressionTree shouldBe expectedExpr } property("uses default value from parameter definition") { @@ -90,8 +84,7 @@ class SigmaTemplateCompilerTest extends AnyPropSpec with ScalaCheckPropertyCheck """/**/ |@contract def contractName(p: Boolean = true) = sigmaProp(p) |""".stripMargin - val compiler = SigmaTemplateCompiler(ErgoAddressEncoder.MainnetNetworkPrefix) - val template = compiler.compile(Map.empty, source) + val template = templateCompiler.compile(source) template.parameters should contain theSameElementsInOrderAs IndexedSeq( Parameter("p", "", 0) @@ -101,21 +94,16 @@ class SigmaTemplateCompilerTest extends AnyPropSpec with ScalaCheckPropertyCheck Some(true) ) - val sigmaCompiler = new SigmaCompiler(ErgoAddressEncoder.MainnetNetworkPrefix) - implicit val ir = new CompiletimeIRContext - val result = sigmaCompiler.compile(Map("p" -> true), "sigmaProp(p)") - - template.expressionTree shouldBe result.buildTree + val expectedExpr = BoolToSigmaProp(ConstantPlaceholder(0, SBoolean)) + template.expressionTree shouldBe expectedExpr } property("uses given environment when provided (overriding default value)") { - val explicitEnv = Map("low" -> 10, "high" -> 100) val source = """/**/ |@contract def contractName(low: Int = 0, high: Int) = sigmaProp(low < HEIGHT && HEIGHT < high) |""".stripMargin - val compiler = SigmaTemplateCompiler(ErgoAddressEncoder.MainnetNetworkPrefix) - val template = compiler.compile(explicitEnv, source) + val template = templateCompiler.compile(source) template.parameters should contain theSameElementsInOrderAs IndexedSeq( Parameter("low", "", 0), @@ -128,27 +116,30 @@ class SigmaTemplateCompilerTest extends AnyPropSpec with ScalaCheckPropertyCheck None ) - val sigmaCompiler = new SigmaCompiler(ErgoAddressEncoder.MainnetNetworkPrefix) - implicit val ir = new CompiletimeIRContext - val result = sigmaCompiler.compile( - env = explicitEnv, - code = "sigmaProp(low < HEIGHT && HEIGHT < high)" + SigmaPPrint.pprintln(template.expressionTree, 100) + + val expectedExpr = BoolToSigmaProp( + BinAnd( + LT(ConstantPlaceholder(0, SInt), Height), + LT(Height, ConstantPlaceholder(1, SInt)) + ) ) + template.expressionTree shouldBe expectedExpr + + val explicitEnv = Map("low" -> 10, "high" -> 100) - template.expressionTree shouldBe result.buildTree } - property("fails when constant value in not provided") { - // NOTE: parameter `high` without default value */ + property("fails when the parameter is not provided") { + // NOTE: parameter `condition` is not provided */ val source = """/**/ - |@contract def contractName(low: Int = 0, high: Int) = sigmaProp(low < HEIGHT && HEIGHT < high) + |@contract def contractName(low: Int = 0, high: Int) = sigmaProp(low < HEIGHT && HEIGHT < high) && condition |""".stripMargin - val compiler = SigmaTemplateCompiler(ErgoAddressEncoder.MainnetNetworkPrefix) val env: ScriptEnv = Map.empty // no value for "high" assertExceptionThrown( - compiler.compile(env, source), - exceptionLike[TyperException]("Cannot assign type for variable 'high' because it is not found in env") + templateCompiler.compile(source), + exceptionLike[TyperException]("Cannot assign type for variable 'condition' because it is not found in env") ) } diff --git a/sc/shared/src/test/scala/sigmastate/lang/SigmaTyperTest.scala b/sc/shared/src/test/scala/sigmastate/lang/SigmaTyperTest.scala index a474727943..5bb38c7998 100644 --- a/sc/shared/src/test/scala/sigmastate/lang/SigmaTyperTest.scala +++ b/sc/shared/src/test/scala/sigmastate/lang/SigmaTyperTest.scala @@ -34,7 +34,8 @@ class SigmaTyperTest extends AnyPropSpec val predefinedFuncRegistry = new PredefinedFuncRegistry(builder) val binder = new SigmaBinder(env, builder, TestnetNetworkPrefix, predefinedFuncRegistry) val bound = binder.bind(parsed) - val typer = new SigmaTyper(builder, predefinedFuncRegistry, lowerMethodCalls = true) + val typeEnv = env.collect { case (k, v: SType) => k -> v } + val typer = new SigmaTyper(builder, predefinedFuncRegistry, typeEnv, lowerMethodCalls = true) val typed = typer.typecheck(bound) assertSrcCtxForAllNodes(typed) if (expected != null) typed shouldBe expected @@ -51,7 +52,8 @@ class SigmaTyperTest extends AnyPropSpec val predefinedFuncRegistry = new PredefinedFuncRegistry(builder) val binder = new SigmaBinder(env, builder, TestnetNetworkPrefix, predefinedFuncRegistry) val bound = binder.bind(parsed) - val typer = new SigmaTyper(builder, predefinedFuncRegistry, lowerMethodCalls = true) + val typeEnv = env.collect { case (k, v: SType) => k -> v } + val typer = new SigmaTyper(builder, predefinedFuncRegistry, typeEnv, lowerMethodCalls = true) typer.typecheck(bound) }, { case te: TyperException => From 6abf2925bf441d39bbb6807d0491864f2fc15f55 Mon Sep 17 00:00:00 2001 From: Alexander Slesarenko Date: Sun, 12 May 2024 13:53:31 +0100 Subject: [PATCH 058/314] i966-template-compiler: added ErgoTreeUtils.explainTreeHeader --- .../sdk/utils/ErgoTreeUtils.scala | 26 +++++++++++++++++++ .../sdk/utils/ErgoTreeUtilsSpec.scala | 23 ++++++++++++++++ 2 files changed, 49 insertions(+) create mode 100644 sdk/shared/src/main/scala/org/ergoplatform/sdk/utils/ErgoTreeUtils.scala create mode 100644 sdk/shared/src/test/scala/org/ergoplatform/sdk/utils/ErgoTreeUtilsSpec.scala diff --git a/sdk/shared/src/main/scala/org/ergoplatform/sdk/utils/ErgoTreeUtils.scala b/sdk/shared/src/main/scala/org/ergoplatform/sdk/utils/ErgoTreeUtils.scala new file mode 100644 index 0000000000..8feccb2dfc --- /dev/null +++ b/sdk/shared/src/main/scala/org/ergoplatform/sdk/utils/ErgoTreeUtils.scala @@ -0,0 +1,26 @@ +package org.ergoplatform.sdk.utils + +import sigma.ast.ErgoTree +import sigma.ast.ErgoTree.HeaderType +import sigma.util.Extensions.BooleanOps + +/** SDK level utilities and helper methods to work with ErgoTrees. */ +object ErgoTreeUtils { + /** Prints description of the bits in the given ErgoTree header. */ + def explainTreeHeader(header: HeaderType): String = { + // convert byte to hex and decimal string + val byteToHex = (b: Byte) => f"Ox${b & 0xff}%02x" + val hasSize = ErgoTree.hasSize(header) + s""" + |Header: ${byteToHex(header)} (${header.toString}) + |Bit 0: ${header.toByte & 0x01} \\ + |Bit 1: ${(header.toByte & 0x02) >> 1}\t-- ErgoTree version ${ErgoTree.getVersion(header)} + |Bit 2: ${(header.toByte & 0x04) >> 2} / + |Bit 3: ${hasSize.toByte} \t-- size of the whole tree is serialized after the header byte + |Bit 4: ${ErgoTree.isConstantSegregation(header).toByte} \t-- constant segregation is used for this ErgoTree + |Bit 5: ${header.toByte & 0x20} \t-- reserved (should be 0) + |Bit 6: ${header.toByte & 0x40} \t-- reserved for GZIP compression (should be 0) + |Bit 7: ${header.toByte & 0x80} \t-- header contains more than 1 byte (default == 0) + |""".stripMargin + } +} diff --git a/sdk/shared/src/test/scala/org/ergoplatform/sdk/utils/ErgoTreeUtilsSpec.scala b/sdk/shared/src/test/scala/org/ergoplatform/sdk/utils/ErgoTreeUtilsSpec.scala new file mode 100644 index 0000000000..cb3321d28e --- /dev/null +++ b/sdk/shared/src/test/scala/org/ergoplatform/sdk/utils/ErgoTreeUtilsSpec.scala @@ -0,0 +1,23 @@ +package org.ergoplatform.sdk.utils + +import org.scalatest.matchers.should.Matchers +import org.scalatest.propspec.AnyPropSpec +import org.scalatestplus.scalacheck.ScalaCheckPropertyChecks +import sigma.ast.ErgoTree.HeaderType + +class ErgoTreeUtilsSpec extends AnyPropSpec with ScalaCheckPropertyChecks with Matchers { + property("explainTreeHeader") { + ErgoTreeUtils.explainTreeHeader(HeaderType @@ 26.toByte) shouldBe + """| + |Header: Ox1a (26) + |Bit 0: 0 \ + |Bit 1: 1 -- ErgoTree version 2 + |Bit 2: 0 / + |Bit 3: 1 -- size of the whole tree is serialized after the header byte + |Bit 4: 1 -- constant segregation is used for this ErgoTree + |Bit 5: 0 -- reserved (should be 0) + |Bit 6: 0 -- reserved for GZIP compression (should be 0) + |Bit 7: 0 -- header contains more than 1 byte (default == 0) + |""".stripMargin + } +} From efabf245052c77cd4c386bdbc5ce0ba147e79199 Mon Sep 17 00:00:00 2001 From: Alexander Slesarenko Date: Sun, 12 May 2024 14:33:30 +0100 Subject: [PATCH 059/314] i966-template-compiler: test ContractTemplate.applyTemplate method --- .../src/main/scala/sigma/ast/ErgoTree.scala | 4 +-- .../lang/SigmaTemplateCompilerTest.scala | 27 ++++++++++++++++--- 2 files changed, 26 insertions(+), 5 deletions(-) diff --git a/data/shared/src/main/scala/sigma/ast/ErgoTree.scala b/data/shared/src/main/scala/sigma/ast/ErgoTree.scala index d6ed6118dc..68d69abd91 100644 --- a/data/shared/src/main/scala/sigma/ast/ErgoTree.scala +++ b/data/shared/src/main/scala/sigma/ast/ErgoTree.scala @@ -25,13 +25,13 @@ case class UnparsedErgoTree(bytes: mutable.WrappedArray[Byte], error: Validation * ErgoTreeSerializer defines top-level serialization format of the scripts. * The interpretation of the byte array depend on the first `header` byte, which uses VLQ encoding up to 30 bits. * Currently we define meaning for only first byte, which may be extended in future versions. - * 7 6 5 4 3 2 1 0 + * 7 6 5 4 3 2 1 0 * ------------------------- * | | | | | | | | | * ------------------------- * Bit 7 == 1 if the header contains more than 1 byte (default == 0) * Bit 6 - reserved for GZIP compression (should be 0) - * Bit 5 == 1 - reserved for context dependent costing (should be = 0) + * Bit 5 == 1 - reserved (should be = 0) * Bit 4 == 1 if constant segregation is used for this ErgoTree (default = 0) * (see https://github.com/ScorexFoundation/sigmastate-interpreter/issues/264) * Bit 3 == 1 if size of the whole tree is serialized after the header byte (default = 0) diff --git a/sc/shared/src/test/scala/sigmastate/lang/SigmaTemplateCompilerTest.scala b/sc/shared/src/test/scala/sigmastate/lang/SigmaTemplateCompilerTest.scala index a0f9c7d8aa..d3e08a700f 100644 --- a/sc/shared/src/test/scala/sigmastate/lang/SigmaTemplateCompilerTest.scala +++ b/sc/shared/src/test/scala/sigmastate/lang/SigmaTemplateCompilerTest.scala @@ -4,7 +4,9 @@ import org.ergoplatform.ErgoAddressEncoder import org.ergoplatform.sdk.Parameter import org.scalatest.propspec.AnyPropSpec import org.scalatestplus.scalacheck.ScalaCheckPropertyChecks -import sigma.ast.{BinAnd, BoolToSigmaProp, ConstantPlaceholder, Height, LT, SBoolean, SInt, SLong, SString, TrueLeaf} +import sigma.VersionContext +import sigma.ast.ErgoTree.HeaderType +import sigma.ast.{BinAnd, BoolToSigmaProp, ConstantPlaceholder, ErgoTree, FalseLeaf, Height, LT, SBoolean, SInt, SLong, SString, TrueLeaf} import sigma.exceptions.TyperException import sigmastate.helpers.SigmaPPrint import sigmastate.interpreter.Interpreter.ScriptEnv @@ -96,6 +98,27 @@ class SigmaTemplateCompilerTest extends AnyPropSpec with ScalaCheckPropertyCheck val expectedExpr = BoolToSigmaProp(ConstantPlaceholder(0, SBoolean)) template.expressionTree shouldBe expectedExpr + + val expectedTree = new ErgoTree( + HeaderType @@ 26.toByte, // use ErgoTreeUtils to get explanation + Vector(TrueLeaf), + Right(BoolToSigmaProp(ConstantPlaceholder(0, SBoolean)))) + + expectedTree.version shouldBe VersionContext.JitActivationVersion + expectedTree.hasSize shouldBe true + expectedTree.isConstantSegregation shouldBe true + + // apply using default values declared in the parameters + template.applyTemplate( + version = Some(VersionContext.JitActivationVersion), + paramValues = Map.empty + ) shouldBe expectedTree + + // apply overriding the default values + template.applyTemplate( + version = Some(VersionContext.JitActivationVersion), + paramValues = Map("p" -> FalseLeaf) + ) shouldBe expectedTree.copy(constants = Vector(FalseLeaf)) } property("uses given environment when provided (overriding default value)") { @@ -116,8 +139,6 @@ class SigmaTemplateCompilerTest extends AnyPropSpec with ScalaCheckPropertyCheck None ) - SigmaPPrint.pprintln(template.expressionTree, 100) - val expectedExpr = BoolToSigmaProp( BinAnd( LT(ConstantPlaceholder(0, SInt), Height), From dcee25851110f0241445f83da95f3baceff40806 Mon Sep 17 00:00:00 2001 From: Alexander Slesarenko Date: Sun, 12 May 2024 17:47:43 +0100 Subject: [PATCH 060/314] i966-template-compiler: more tests for CompilerTemplate.applyTemplate --- .../scala/sigmastate/lang/LangTests.scala | 3 +- .../scala/sigmastate/CompilerTestsBase.scala | 11 ++- .../lang/SigmaTemplateCompilerTest.scala | 90 +++++++++++++------ .../ergoplatform/sdk/ContractTemplate.scala | 2 +- .../sdk/utils/ErgoTreeUtils.scala | 4 +- 5 files changed, 79 insertions(+), 31 deletions(-) diff --git a/parsers/shared/src/test/scala/sigmastate/lang/LangTests.scala b/parsers/shared/src/test/scala/sigmastate/lang/LangTests.scala index 498c3934bf..32943bca44 100644 --- a/parsers/shared/src/test/scala/sigmastate/lang/LangTests.scala +++ b/parsers/shared/src/test/scala/sigmastate/lang/LangTests.scala @@ -1,16 +1,15 @@ package sigmastate.lang import org.scalatest.matchers.should.Matchers -import sigma.{Coll, _} import sigma.ast.SCollection.SByteArray import sigma.ast.syntax.{SValue, ValueOps} import sigma.ast._ import sigma.crypto.CryptoConstants import sigma.data.{CAnyValue, CSigmaDslBuilder, ProveDHTuple, ProveDlog, SigmaBoolean} import sigma.util.Extensions.BigIntegerOps +import sigma._ import sigmastate.helpers.NegativeTesting import sigmastate.interpreter.Interpreter.ScriptEnv -import sigma.ast.{Ident, MethodCallLike} import java.math.BigInteger diff --git a/sc/shared/src/test/scala/sigmastate/CompilerTestsBase.scala b/sc/shared/src/test/scala/sigmastate/CompilerTestsBase.scala index 28f907c199..0b2951b92f 100644 --- a/sc/shared/src/test/scala/sigmastate/CompilerTestsBase.scala +++ b/sc/shared/src/test/scala/sigmastate/CompilerTestsBase.scala @@ -9,8 +9,9 @@ import sigma.ast.syntax.{SValue, SigmaPropValue} import sigma.serialization.ValueSerializer import sigmastate.eval.IRContext import sigma.ast.syntax.ValueOps +import sigmastate.helpers.{NegativeTesting, SigmaPPrint} -trait CompilerTestsBase extends TestsBase { +trait CompilerTestsBase extends TestsBase with NegativeTesting { protected val _lowerMethodCalls = new DynamicVariable[Boolean](true) /** Returns true if MethodCall nodes should be lowered by TypeChecker to the @@ -63,4 +64,12 @@ trait CompilerTestsBase extends TestsBase { val tree = mkTestErgoTree(prop) (tree, prop) } + + /** Checks expectation pretty printing the actual value if there is a difference. */ + def checkEquals[T](actual: T, expected: T): Unit = { + if (expected != actual) { + SigmaPPrint.pprintln(actual, width = 100) + } + actual shouldBe expected + } } diff --git a/sc/shared/src/test/scala/sigmastate/lang/SigmaTemplateCompilerTest.scala b/sc/shared/src/test/scala/sigmastate/lang/SigmaTemplateCompilerTest.scala index d3e08a700f..35f16618ec 100644 --- a/sc/shared/src/test/scala/sigmastate/lang/SigmaTemplateCompilerTest.scala +++ b/sc/shared/src/test/scala/sigmastate/lang/SigmaTemplateCompilerTest.scala @@ -6,12 +6,12 @@ import org.scalatest.propspec.AnyPropSpec import org.scalatestplus.scalacheck.ScalaCheckPropertyChecks import sigma.VersionContext import sigma.ast.ErgoTree.HeaderType -import sigma.ast.{BinAnd, BoolToSigmaProp, ConstantPlaceholder, ErgoTree, FalseLeaf, Height, LT, SBoolean, SInt, SLong, SString, TrueLeaf} +import sigma.ast.{BinAnd, BoolToSigmaProp, ConstantPlaceholder, ErgoTree, FalseLeaf, GT, Height, IntConstant, LT, SBoolean, SInt, SLong, SString, TrueLeaf} import sigma.exceptions.TyperException -import sigmastate.helpers.SigmaPPrint +import sigmastate.CompilerTestsBase import sigmastate.interpreter.Interpreter.ScriptEnv -class SigmaTemplateCompilerTest extends AnyPropSpec with ScalaCheckPropertyChecks with LangTests { +class SigmaTemplateCompilerTest extends AnyPropSpec with ScalaCheckPropertyChecks with CompilerTestsBase { val templateCompiler = SigmaTemplateCompiler(ErgoAddressEncoder.MainnetNetworkPrefix) property("compiles full contract template") { @@ -45,8 +45,7 @@ class SigmaTemplateCompilerTest extends AnyPropSpec with ScalaCheckPropertyCheck None ) - val expectedExpr = BoolToSigmaProp(TrueLeaf) - template.expressionTree shouldBe expectedExpr + checkEquals(template.expressionTree, BoolToSigmaProp(TrueLeaf)) } property("compiles contract template without braces") { @@ -77,14 +76,13 @@ class SigmaTemplateCompilerTest extends AnyPropSpec with ScalaCheckPropertyCheck Some("default string") ) - val expectedExpr = BoolToSigmaProp(TrueLeaf) - template.expressionTree shouldBe expectedExpr + checkEquals(template.expressionTree, BoolToSigmaProp(TrueLeaf)) } property("uses default value from parameter definition") { val source = """/**/ - |@contract def contractName(p: Boolean = true) = sigmaProp(p) + |@contract def contractName(p: Boolean = true) = sigmaProp(p && HEIGHT > 1000) |""".stripMargin val template = templateCompiler.compile(source) @@ -96,29 +94,35 @@ class SigmaTemplateCompilerTest extends AnyPropSpec with ScalaCheckPropertyCheck Some(true) ) - val expectedExpr = BoolToSigmaProp(ConstantPlaceholder(0, SBoolean)) - template.expressionTree shouldBe expectedExpr + val expectedExpr = BoolToSigmaProp(BinAnd(ConstantPlaceholder(0, SBoolean), GT(Height, IntConstant(1000)))) + checkEquals(template.expressionTree, expectedExpr) val expectedTree = new ErgoTree( HeaderType @@ 26.toByte, // use ErgoTreeUtils to get explanation Vector(TrueLeaf), - Right(BoolToSigmaProp(ConstantPlaceholder(0, SBoolean)))) + Right(BoolToSigmaProp(BinAnd(ConstantPlaceholder(0, SBoolean), GT(Height, IntConstant(1000)))))) expectedTree.version shouldBe VersionContext.JitActivationVersion expectedTree.hasSize shouldBe true expectedTree.isConstantSegregation shouldBe true // apply using default values declared in the parameters - template.applyTemplate( - version = Some(VersionContext.JitActivationVersion), - paramValues = Map.empty - ) shouldBe expectedTree + checkEquals( + template.applyTemplate( + version = Some(VersionContext.JitActivationVersion), + paramValues = Map.empty + ), + expectedTree + ) // apply overriding the default values - template.applyTemplate( - version = Some(VersionContext.JitActivationVersion), - paramValues = Map("p" -> FalseLeaf) - ) shouldBe expectedTree.copy(constants = Vector(FalseLeaf)) + checkEquals( + template.applyTemplate( + version = Some(VersionContext.JitActivationVersion), + paramValues = Map("p" -> FalseLeaf) + ), + expectedTree.copy(constants = Vector(FalseLeaf)) + ) } property("uses given environment when provided (overriding default value)") { @@ -138,17 +142,53 @@ class SigmaTemplateCompilerTest extends AnyPropSpec with ScalaCheckPropertyCheck Some(0), None ) + checkEquals( + template.expressionTree, + BoolToSigmaProp( + BinAnd( + LT(ConstantPlaceholder(0, SInt), Height), + LT(Height, ConstantPlaceholder(1, SInt)) + ) + ) + ) + + // incomplete application (missing `high` parameter) + assertExceptionThrown( + template.applyTemplate( + version = Some(VersionContext.JitActivationVersion), + paramValues = Map.empty + ), + exceptionLike[IllegalArgumentException]( + "requirement failed: value for parameter `high` was not provided while it does not have a default value.") + ) - val expectedExpr = BoolToSigmaProp( - BinAnd( - LT(ConstantPlaceholder(0, SInt), Height), - LT(Height, ConstantPlaceholder(1, SInt)) + val expectedTree = new ErgoTree( + HeaderType @@ 26.toByte, + Vector(IntConstant(0), IntConstant(100)), + Right( + BoolToSigmaProp( + BinAnd(LT(ConstantPlaceholder(0, SInt), Height), LT(Height, ConstantPlaceholder(1, SInt))) + ) ) ) - template.expressionTree shouldBe expectedExpr - val explicitEnv = Map("low" -> 10, "high" -> 100) + // apply providing the parameter without default value + checkEquals( + template.applyTemplate( + version = Some(VersionContext.JitActivationVersion), + paramValues = Map("high" -> IntConstant(100)) + ), + expectedTree + ) + // apply providing all parameters overriding the default values + checkEquals( + template.applyTemplate( + version = Some(VersionContext.JitActivationVersion), + paramValues = Map("low" -> IntConstant(10), "high" -> IntConstant(100)) + ), + expectedTree.copy(constants = Vector(IntConstant(10), IntConstant(100))) + ) } property("fails when the parameter is not provided") { diff --git a/sdk/shared/src/main/scala/org/ergoplatform/sdk/ContractTemplate.scala b/sdk/shared/src/main/scala/org/ergoplatform/sdk/ContractTemplate.scala index 5e491630bd..8da420bee6 100644 --- a/sdk/shared/src/main/scala/org/ergoplatform/sdk/ContractTemplate.scala +++ b/sdk/shared/src/main/scala/org/ergoplatform/sdk/ContractTemplate.scala @@ -153,7 +153,7 @@ case class ContractTemplate( .map(p => p.name) requiredParameterNames.foreach(name => require( paramValues.contains(name), - s"value for parameter $name was not provided while it does not have a default value.")) + s"value for parameter `$name` was not provided while it does not have a default value.")) val parameterizedConstantIndices = this.parameters.map(p => p.constantIndex).toSet val constIndexToParamIndex = this.parameters.zipWithIndex.map(pi => pi._1.constantIndex -> pi._2).toMap diff --git a/sdk/shared/src/main/scala/org/ergoplatform/sdk/utils/ErgoTreeUtils.scala b/sdk/shared/src/main/scala/org/ergoplatform/sdk/utils/ErgoTreeUtils.scala index 8feccb2dfc..ffa6505377 100644 --- a/sdk/shared/src/main/scala/org/ergoplatform/sdk/utils/ErgoTreeUtils.scala +++ b/sdk/shared/src/main/scala/org/ergoplatform/sdk/utils/ErgoTreeUtils.scala @@ -8,7 +8,7 @@ import sigma.util.Extensions.BooleanOps object ErgoTreeUtils { /** Prints description of the bits in the given ErgoTree header. */ def explainTreeHeader(header: HeaderType): String = { - // convert byte to hex and decimal string + // convert byte to hex val byteToHex = (b: Byte) => f"Ox${b & 0xff}%02x" val hasSize = ErgoTree.hasSize(header) s""" @@ -19,7 +19,7 @@ object ErgoTreeUtils { |Bit 3: ${hasSize.toByte} \t-- size of the whole tree is serialized after the header byte |Bit 4: ${ErgoTree.isConstantSegregation(header).toByte} \t-- constant segregation is used for this ErgoTree |Bit 5: ${header.toByte & 0x20} \t-- reserved (should be 0) - |Bit 6: ${header.toByte & 0x40} \t-- reserved for GZIP compression (should be 0) + |Bit 6: ${header.toByte & 0x40} \t-- reserved (should be 0) |Bit 7: ${header.toByte & 0x80} \t-- header contains more than 1 byte (default == 0) |""".stripMargin } From ba6abadfc39ea7f2f6c77d71adaa6a0a93101b52 Mon Sep 17 00:00:00 2001 From: Alexander Slesarenko Date: Sun, 12 May 2024 17:56:15 +0100 Subject: [PATCH 061/314] i966-template-compiler: fix ErgoTreeUtilsSpec --- .../scala/org/ergoplatform/sdk/utils/ErgoTreeUtilsSpec.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/shared/src/test/scala/org/ergoplatform/sdk/utils/ErgoTreeUtilsSpec.scala b/sdk/shared/src/test/scala/org/ergoplatform/sdk/utils/ErgoTreeUtilsSpec.scala index cb3321d28e..8dd20ecf81 100644 --- a/sdk/shared/src/test/scala/org/ergoplatform/sdk/utils/ErgoTreeUtilsSpec.scala +++ b/sdk/shared/src/test/scala/org/ergoplatform/sdk/utils/ErgoTreeUtilsSpec.scala @@ -16,7 +16,7 @@ class ErgoTreeUtilsSpec extends AnyPropSpec with ScalaCheckPropertyChecks with M |Bit 3: 1 -- size of the whole tree is serialized after the header byte |Bit 4: 1 -- constant segregation is used for this ErgoTree |Bit 5: 0 -- reserved (should be 0) - |Bit 6: 0 -- reserved for GZIP compression (should be 0) + |Bit 6: 0 -- reserved (should be 0) |Bit 7: 0 -- header contains more than 1 byte (default == 0) |""".stripMargin } From 28f7e1534960e6e3e56cde16a78e900366170543 Mon Sep 17 00:00:00 2001 From: Alexander Slesarenko Date: Sun, 12 May 2024 21:06:31 +0100 Subject: [PATCH 062/314] i966-template-compiler: addressed review comments --- sc/shared/src/main/scala/sigmastate/lang/SigmaTyper.scala | 7 +++++-- .../scala/sigmastate/lang/SigmaTemplateCompilerTest.scala | 1 - 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/sc/shared/src/main/scala/sigmastate/lang/SigmaTyper.scala b/sc/shared/src/main/scala/sigmastate/lang/SigmaTyper.scala index 857ed66338..416f2d7fbb 100644 --- a/sc/shared/src/main/scala/sigmastate/lang/SigmaTyper.scala +++ b/sc/shared/src/main/scala/sigmastate/lang/SigmaTyper.scala @@ -13,8 +13,11 @@ import sigma.serialization.OpCodes import scala.collection.mutable.ArrayBuffer -/** - * Type inference and analysis for Sigma expressions. +/** Type inference and analysis for Sigma expressions. + * @param builder SigmaBuilder instance to create new nodes + * @param predefFuncRegistry predefined functions registry used to resolve names + * @param typeEnv environment with types of variables/names + * @param lowerMethodCalls if true, then MethodCall nodes are lowered to the corresponding ErgoTree nodes */ class SigmaTyper(val builder: SigmaBuilder, predefFuncRegistry: PredefinedFuncRegistry, diff --git a/sc/shared/src/test/scala/sigmastate/lang/SigmaTemplateCompilerTest.scala b/sc/shared/src/test/scala/sigmastate/lang/SigmaTemplateCompilerTest.scala index 35f16618ec..966a7c4c74 100644 --- a/sc/shared/src/test/scala/sigmastate/lang/SigmaTemplateCompilerTest.scala +++ b/sc/shared/src/test/scala/sigmastate/lang/SigmaTemplateCompilerTest.scala @@ -197,7 +197,6 @@ class SigmaTemplateCompilerTest extends AnyPropSpec with ScalaCheckPropertyCheck """/**/ |@contract def contractName(low: Int = 0, high: Int) = sigmaProp(low < HEIGHT && HEIGHT < high) && condition |""".stripMargin - val env: ScriptEnv = Map.empty // no value for "high" assertExceptionThrown( templateCompiler.compile(source), exceptionLike[TyperException]("Cannot assign type for variable 'condition' because it is not found in env") From 4004cc9efcd724b115f2b43f280c1f3d9dc5c8fe Mon Sep 17 00:00:00 2001 From: Alexander Slesarenko Date: Tue, 14 May 2024 10:10:51 +0100 Subject: [PATCH 063/314] i486-toBytes: tests added to SigmaTyperTest --- .../sigmastate/lang/SigmaTyperTest.scala | 50 ++++++++++++++++++- 1 file changed, 49 insertions(+), 1 deletion(-) diff --git a/sc/shared/src/test/scala/sigmastate/lang/SigmaTyperTest.scala b/sc/shared/src/test/scala/sigmastate/lang/SigmaTyperTest.scala index a474727943..f2ac5e8cf2 100644 --- a/sc/shared/src/test/scala/sigmastate/lang/SigmaTyperTest.scala +++ b/sc/shared/src/test/scala/sigmastate/lang/SigmaTyperTest.scala @@ -20,6 +20,7 @@ import sigma.serialization.ErgoTreeSerializer import sigma.serialization.generators.ObjectGenerators import sigma.ast.Select import sigma.exceptions.TyperException +import sigmastate.helpers.SigmaPPrint class SigmaTyperTest extends AnyPropSpec with ScalaCheckPropertyChecks with Matchers with LangTests with ObjectGenerators { @@ -37,7 +38,12 @@ class SigmaTyperTest extends AnyPropSpec val typer = new SigmaTyper(builder, predefinedFuncRegistry, lowerMethodCalls = true) val typed = typer.typecheck(bound) assertSrcCtxForAllNodes(typed) - if (expected != null) typed shouldBe expected + if (expected != null) { + if (expected != typed) { + SigmaPPrint.pprintln(typed, width = 100) + } + typed shouldBe expected + } typed.tpe } catch { case e: Exception => throw e @@ -508,6 +514,48 @@ class SigmaTyperTest extends AnyPropSpec typefail(env, "1.toSuperBigInteger", 1, 1) } + property("toBytes method for numeric types") { + typecheck(env, "1.toByte.toBytes", + expected = MethodCall.typed[Value[SCollection[SByte.type]]]( + Select(IntConstant(1), "toByte", Some(SByte)), + SNumericTypeMethods.getMethodByName("toBytes").withConcreteTypes(Map(STypeVar("TNum") -> SByte)), + Vector(), + Map() + )) shouldBe SByteArray + + typecheck(env, "1.toShort.toBytes", + expected = MethodCall.typed[Value[SCollection[SByte.type]]]( + Select(IntConstant(1), "toShort", Some(SShort)), + SNumericTypeMethods.getMethodByName("toBytes").withConcreteTypes(Map(STypeVar("TNum") -> SShort)), + Vector(), + Map() + )) shouldBe SByteArray + + typecheck(env, "1.toBytes", + expected = MethodCall.typed[Value[SCollection[SByte.type]]]( + IntConstant(1), + SNumericTypeMethods.getMethodByName("toBytes").withConcreteTypes(Map(STypeVar("TNum") -> SInt)), + Vector(), + Map() + )) shouldBe SByteArray + + typecheck(env, "1.toLong.toBytes", + expected = MethodCall.typed[Value[SCollection[SByte.type]]]( + Select(IntConstant(1), "toLong", Some(SLong)), + SNumericTypeMethods.getMethodByName("toBytes").withConcreteTypes(Map(STypeVar("TNum") -> SLong)), + Vector(), + Map() + )) shouldBe SByteArray + + typecheck(env, "1.toBigInt.toBytes", + expected = MethodCall.typed[Value[SCollection[SByte.type]]]( + Select(IntConstant(1), "toBigInt", Some(SBigInt)), + SNumericTypeMethods.getMethodByName("toBytes").withConcreteTypes(Map(STypeVar("TNum") -> SBigInt)), + Vector(), + Map() + )) shouldBe SByteArray + } + property("string concat") { typecheck(env, """ "a" + "b" """) shouldBe SString } From b55d3362de79afad58f9755e89dc75984bf78c3c Mon Sep 17 00:00:00 2001 From: Alexander Slesarenko Date: Tue, 14 May 2024 12:34:02 +0100 Subject: [PATCH 064/314] i486-toBytes: ExactNumeric.toBytes implemented --- .../main/scala/sigma/data/BigIntegerOps.scala | 3 +++ .../main/scala/sigma/data/ExactIntegral.scala | 7 +++++++ .../src/main/scala/sigma/data/ExactNumeric.scala | 7 +++++++ .../test/scala/sigma/SigmaDslSpecification.scala | 16 ++++++++++++++-- 4 files changed, 31 insertions(+), 2 deletions(-) diff --git a/data/shared/src/main/scala/sigma/data/BigIntegerOps.scala b/data/shared/src/main/scala/sigma/data/BigIntegerOps.scala index 168b2f8266..b93334daf6 100644 --- a/data/shared/src/main/scala/sigma/data/BigIntegerOps.scala +++ b/data/shared/src/main/scala/sigma/data/BigIntegerOps.scala @@ -2,6 +2,7 @@ package sigma.data import sigma._ import sigma.eval.Extensions.IntExt +import sigma.util.Extensions.BigIntOps import scala.math.{Integral, Ordering} @@ -89,6 +90,8 @@ object NumericOps { * NOTE: This method should not be used in v4.x */ override def divisionRemainder(x: BigInt, y: BigInt): BigInt = x.mod(y) + + override def toBytes(x: BigInt): Coll[Byte] = Colls.fromArray(x.toBigInteger.toByteArray) } /** The instance of [[scalan.ExactOrdering]] typeclass for [[BigInt]]. */ diff --git a/data/shared/src/main/scala/sigma/data/ExactIntegral.scala b/data/shared/src/main/scala/sigma/data/ExactIntegral.scala index 34e2f47f63..b207a1794d 100644 --- a/data/shared/src/main/scala/sigma/data/ExactIntegral.scala +++ b/data/shared/src/main/scala/sigma/data/ExactIntegral.scala @@ -1,5 +1,6 @@ package sigma.data +import sigma.{Coll, Colls} import sigma.util.Extensions.{ByteOps, ShortOps} /** Type-class which defines the operations on Integral types (Byte, Short, Int, Long, BigInt) @@ -37,6 +38,7 @@ object ExactIntegral { override def plus(x: Byte, y: Byte): Byte = x.addExact(y) override def minus(x: Byte, y: Byte): Byte = x.subtractExact(y) override def times(x: Byte, y: Byte): Byte = x.multiplyExact(y) + override def toBytes(x: Byte): Coll[Byte] = Colls.fromItems(x) } implicit object ShortIsExactIntegral extends ExactIntegral[Short] { @@ -44,6 +46,7 @@ object ExactIntegral { override def plus(x: Short, y: Short): Short = x.addExact(y) override def minus(x: Short, y: Short): Short = x.subtractExact(y) override def times(x: Short, y: Short): Short = x.multiplyExact(y) + override def toBytes(x: Short): Coll[Byte] = Colls.fromItems((x >> 8).toByte, x.toByte) } implicit object IntIsExactIntegral extends ExactIntegral[Int] { @@ -51,6 +54,8 @@ object ExactIntegral { override def plus(x: Int, y: Int): Int = java7.compat.Math.addExact(x, y) override def minus(x: Int, y: Int): Int = java7.compat.Math.subtractExact(x, y) override def times(x: Int, y: Int): Int = java7.compat.Math.multiplyExact(x, y) + override def toBytes(x: Int): Coll[Byte] = + Colls.fromItems((x >> 24).toByte, (x >> 16).toByte, (x >> 8).toByte, x.toByte) } implicit object LongIsExactIntegral extends ExactIntegral[Long] { @@ -58,5 +63,7 @@ object ExactIntegral { override def plus(x: Long, y: Long): Long = java7.compat.Math.addExact(x, y) override def minus(x: Long, y: Long): Long = java7.compat.Math.subtractExact(x, y) override def times(x: Long, y: Long): Long = java7.compat.Math.multiplyExact(x, y) + override def toBytes(x: Long): Coll[Byte] = + Colls.fromItems((x >> 56).toByte, (x >> 48).toByte, (x >> 40).toByte, (x >> 32).toByte, (x >> 24).toByte, (x >> 16).toByte, (x >> 8).toByte, x.toByte) } } diff --git a/data/shared/src/main/scala/sigma/data/ExactNumeric.scala b/data/shared/src/main/scala/sigma/data/ExactNumeric.scala index 2e9b799a61..fef951b4d7 100644 --- a/data/shared/src/main/scala/sigma/data/ExactNumeric.scala +++ b/data/shared/src/main/scala/sigma/data/ExactNumeric.scala @@ -1,5 +1,6 @@ package sigma.data +import sigma.Coll import sigma.data.ExactIntegral._ /** Numeric operations with overflow checks. @@ -30,6 +31,12 @@ trait ExactNumeric[T] { def toInt(x: T): Int = n.toInt(x) def toLong(x: T): Long = n.toLong(x) + /** Returns a big-endian representation of this value in a collection of bytes. + * For example, the `Int` value `0x12131415` would yield the + * collection of bytes [0x12, 0x13, 0x14, 0x15] + */ + def toBytes(x: T): Coll[Byte] + /** A value of type T which corresponds to integer 0. */ lazy val zero: T = fromInt(0) diff --git a/sc/shared/src/test/scala/sigma/SigmaDslSpecification.scala b/sc/shared/src/test/scala/sigma/SigmaDslSpecification.scala index 4dd576f03a..e9ea2b8776 100644 --- a/sc/shared/src/test/scala/sigma/SigmaDslSpecification.scala +++ b/sc/shared/src/test/scala/sigma/SigmaDslSpecification.scala @@ -1058,8 +1058,20 @@ class SigmaDslSpecification extends SigmaDslTesting ">=", GE.apply)(_ >= _) } +// property("Numeric.toBytes methods equivalence") { +// lazy val toBytes = changedFeature( +// (x: Byte) => x.toBytes, +// (x: Byte) => x.toBytes, +// "{ (x: Byte) => x.toBytes }") +// val cases = Seq( +// (0.toByte, Success(Coll(0.toByte))), +// (1.toByte, Success(Coll(1.toByte))) +// ) +// +// testCases(cases, toBytes) +// } + property("Byte methods equivalence (new features)") { - lazy val toBytes = newFeature((x: Byte) => x.toBytes, "{ (x: Byte) => x.toBytes }") lazy val toAbs = newFeature((x: Byte) => x.toAbs, "{ (x: Byte) => x.toAbs }") lazy val compareTo = newFeature( (x: (Byte, Byte)) => x._1.compareTo(x._2), @@ -1074,7 +1086,7 @@ class SigmaDslSpecification extends SigmaDslTesting "{ (x: (Byte, Byte)) => (x._1 & x._2).toByteExact }") forAll { x: Byte => - Seq(toBytes, toAbs).foreach(f => f.checkEquality(x)) + Seq(toAbs).foreach(f => f.checkEquality(x)) } forAll { x: (Byte, Byte) => From d6efd22b61cda3e8ad6f1a14f619e813dddcb0f1 Mon Sep 17 00:00:00 2001 From: Alexander Slesarenko Date: Tue, 14 May 2024 15:40:16 +0100 Subject: [PATCH 065/314] v6.0.0-fix-tests: necessary changes due to MaxSupportedVersion upgrade --- .../src/test/scala/sigma/VersionTesting.scala | 4 +--- .../test/scala/sigma/SigmaDslSpecification.scala | 16 ++++++++-------- .../ScriptVersionSwitchSpecification.scala | 7 ++++--- 3 files changed, 13 insertions(+), 14 deletions(-) diff --git a/core/shared/src/test/scala/sigma/VersionTesting.scala b/core/shared/src/test/scala/sigma/VersionTesting.scala index 69e15ff491..08053a6c48 100644 --- a/core/shared/src/test/scala/sigma/VersionTesting.scala +++ b/core/shared/src/test/scala/sigma/VersionTesting.scala @@ -39,9 +39,7 @@ trait VersionTesting { _ + 1) { j => val treeVersion = ergoTreeVers(j) // for each tree version up to currently activated, set it up and execute block - _currErgoTreeVersion.withValue(treeVersion) { - VersionContext.withVersions(activatedVersion, treeVersion)(block) - } + _currErgoTreeVersion.withValue(treeVersion)(block) } } } diff --git a/sc/shared/src/test/scala/sigma/SigmaDslSpecification.scala b/sc/shared/src/test/scala/sigma/SigmaDslSpecification.scala index 4dd576f03a..c820e65e73 100644 --- a/sc/shared/src/test/scala/sigma/SigmaDslSpecification.scala +++ b/sc/shared/src/test/scala/sigma/SigmaDslSpecification.scala @@ -5081,7 +5081,7 @@ class SigmaDslSpecification extends SigmaDslTesting newCost = 1766, newVersionedResults = { val res = (ExpectedResult(Success(0), Some(1766)) -> Some(selfCostDetails)) - Seq(0, 1, 2).map(version => version -> res) + Seq(0, 1, 2, 3).map(version => version -> res) })) ), changedFeature({ (x: Context) => x.selfBoxIndex }, @@ -5280,7 +5280,7 @@ class SigmaDslSpecification extends SigmaDslTesting Seq( ctx -> Expected(Failure(expectedError), 0, CostDetails.ZeroCost, 1793, newVersionedResults = { - Seq.tabulate(3)(v => v -> (ExpectedResult(Success(true), Some(1793)) -> None)) + Seq.tabulate(4)(v => v -> (ExpectedResult(Success(true), Some(1793)) -> None)) } ) ), @@ -6233,7 +6233,7 @@ class SigmaDslSpecification extends SigmaDslTesting cost = c, expectedDetails = CostDetails.ZeroCost, newCost = 1766, - newVersionedResults = Seq(0, 1, 2).map(i => i -> (ExpectedResult(Success(newV), Some(1766)) -> Some(cd))) + newVersionedResults = Seq(0, 1, 2, 3).map(i => i -> (ExpectedResult(Success(newV), Some(1766)) -> Some(cd))) ) Seq( (Coll[Boolean](), successNew(false, 1766, newV = false, costDetails(0))), @@ -6511,7 +6511,7 @@ class SigmaDslSpecification extends SigmaDslTesting newCost = 1769, newVersionedResults = { val res = (ExpectedResult(Success(Helpers.decodeBytes("00")), Some(1769)), Some(costDetails(1))) - Seq(0, 1, 2).map(version => version -> res) + Seq(0, 1, 2, 3).map(version => version -> res) } )), ((Helpers.decodeBytes("800136fe89afff802acea67128a0ff007fffe3498c8001806080012b"), @@ -9120,7 +9120,7 @@ class SigmaDslSpecification extends SigmaDslTesting cost = 0, expectedDetails = CostDetails.ZeroCost, newCost = 1766, - newVersionedResults = Seq.tabulate(3)(v => v -> (ExpectedResult(Success(5L), Some(1766)) -> Some(costDetails1))) + newVersionedResults = Seq.tabulate(4)(v => v -> (ExpectedResult(Success(5L), Some(1766)) -> Some(costDetails1))) )), (Some(0L) -> Expected( Success(1L), @@ -9679,7 +9679,7 @@ class SigmaDslSpecification extends SigmaDslTesting newCost = 1783, newVersionedResults = { val res = (ExpectedResult(Success(Helpers.decodeBytes("0008d3")), Some(1783)) -> Some(costDetails(0))) - Seq(0, 1, 2).map(version => version -> res) + Seq(0, 1, 2, 3).map(version => version -> res) }), (Helpers.decodeBytes("000008d3"), 0) -> Expected( @@ -9690,7 +9690,7 @@ class SigmaDslSpecification extends SigmaDslTesting newVersionedResults = { // since the tree without constant segregation, substitution has no effect val res = (ExpectedResult(Success(Helpers.decodeBytes("000008d3")), Some(1783)) -> Some(costDetails(0))) - Seq(0, 1, 2).map(version => version -> res) + Seq(0, 1, 2, 3).map(version => version -> res) }), // tree with segregation flag, empty constants array (Coll(t2.bytes:_*), 0) -> success(Helpers.decodeBytes("100008d3"), costDetails(0), 1783), @@ -9761,7 +9761,7 @@ class SigmaDslSpecification extends SigmaDslTesting cost = 1776, expectedDetails = CostDetails.ZeroCost, newCost = 1776, - newVersionedResults = (0 to 2).map(i => i -> (ExpectedResult(Success(true), Some(1776)) -> Some(costDetails))) + newVersionedResults = Seq(0, 1, 2, 3).map(i => i -> (ExpectedResult(Success(true), Some(1776)) -> Some(costDetails))) ) ), changedFeature( diff --git a/sc/shared/src/test/scala/sigmastate/ScriptVersionSwitchSpecification.scala b/sc/shared/src/test/scala/sigmastate/ScriptVersionSwitchSpecification.scala index b0206fa464..aedf35e914 100644 --- a/sc/shared/src/test/scala/sigmastate/ScriptVersionSwitchSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/ScriptVersionSwitchSpecification.scala @@ -276,13 +276,14 @@ class ScriptVersionSwitchSpecification extends SigmaDslTesting { * 20 | 4 | mined | Script v3 | v5.0 | skip-accept (rely on majority) */ property("Rules 19,20 | Block v4 | candidate or mined block | Script v3") { - forEachActivatedScriptVersion(activatedVers = Array[Byte](3)) // version for Block v4 + forEachActivatedScriptVersion(activatedVers = Array[Byte](4)) // activated version is greater then MaxSupported { - forEachErgoTreeVersion(ergoTreeVers = Array[Byte](3, 4)) { // scripts >= v3 + forEachErgoTreeVersion(ergoTreeVers = Array[Byte](4, 5)) { // tree version >= activated val headerFlags = ErgoTree.defaultHeaderWithVersion(ergoTreeVersionInTests) val ergoTree = createErgoTree(headerFlags) - // prover is rejecting, because such context parameters doesn't make sense + // prover is rejecting, because it cannot generate proofs for ErgoTrees with version + // higher than max supported by the interpreter assertExceptionThrown( testProve(ergoTree, activatedScriptVersion = activatedVersionInTests), exceptionLike[InterpreterException](s"Both ErgoTree version ${ergoTree.version} and activated version $activatedVersionInTests is greater than MaxSupportedScriptVersion $MaxSupportedScriptVersion") From 302b09d494c3bdc449b6e83f0bbaf1112463caf8 Mon Sep 17 00:00:00 2001 From: Alexander Slesarenko Date: Tue, 14 May 2024 16:48:50 +0100 Subject: [PATCH 066/314] refactor-ir-cake: removed Library trait (merged with Scalan) --- .../InterpreterReflectionGeneratorTests.scala | 2 +- .../main/scala/scalan/GraphIRReflection.scala | 6 +- sc/shared/src/main/scala/scalan/Library.scala | 120 ------------------ sc/shared/src/main/scala/scalan/Scalan.scala | 118 ++++++++++++++++- .../scala/sigmastate/eval/SigmaLibrary.scala | 4 +- .../scala/special/collection/CollsUnit.scala | 2 +- .../special/collection/impl/CollsImpl.scala | 6 +- .../sigma/wrappers/WrappersModule.scala | 4 +- .../special/wrappers/WrappersModule.scala | 3 +- .../main/scala/wrappers/scala/WOptions.scala | 2 +- .../wrappers/scala/impl/WOptionsImpl.scala | 6 +- .../main/scala/wrappers/scalan/WRTypes.scala | 3 +- .../wrappers/scalan/impl/WRTypesImpl.scala | 14 +- .../wrappers/special/WSpecialPredefs.scala | 4 +- .../special/impl/WSpecialPredefsImpl.scala | 6 +- .../src/test/scala/scalan/TestLibrary.scala | 2 +- .../test/scala/sigma/CollsStagingTests.scala | 4 +- .../scala/special/wrappers/WOptionTests.scala | 1 - 18 files changed, 152 insertions(+), 155 deletions(-) delete mode 100644 sc/shared/src/main/scala/scalan/Library.scala diff --git a/sc/jvm/src/test/scala/sigmastate/InterpreterReflectionGeneratorTests.scala b/sc/jvm/src/test/scala/sigmastate/InterpreterReflectionGeneratorTests.scala index aaa1d6c424..5d81e0d19a 100644 --- a/sc/jvm/src/test/scala/sigmastate/InterpreterReflectionGeneratorTests.scala +++ b/sc/jvm/src/test/scala/sigmastate/InterpreterReflectionGeneratorTests.scala @@ -37,7 +37,7 @@ class InterpreterReflectionGeneratorTests extends AnyPropSpec with Matchers { } property("inner class") { - val ctx = null.asInstanceOf[scalan.Library] // ok! type level only + val ctx = null.asInstanceOf[scalan.Scalan] // ok! type level only val clazz = classOf[ctx.Coll.CollElem[_, _]] registerClassEntry(clazz, constructors = Array( diff --git a/sc/shared/src/main/scala/scalan/GraphIRReflection.scala b/sc/shared/src/main/scala/scalan/GraphIRReflection.scala index 0eaba9d8a3..787873035d 100644 --- a/sc/shared/src/main/scala/scalan/GraphIRReflection.scala +++ b/sc/shared/src/main/scala/scalan/GraphIRReflection.scala @@ -24,7 +24,7 @@ object GraphIRReflection { val reflection = ReflectionData { val clazz = classOf[wrappers.scala.WOptions#WOption[_]] - val ctx = null.asInstanceOf[scalan.Library] // ok! type level only + val ctx = null.asInstanceOf[scalan.Scalan] // ok! type level only registerClassEntry(clazz, methods = Map( mkMethod(clazz, "filter", Array[Class[_]](classOf[Base#Ref[_]])) { (obj, args) => @@ -123,7 +123,7 @@ object GraphIRReflection { } { val clazz = classOf[Colls#CollBuilder] - val ctx = null.asInstanceOf[Library] // ok! type level only + val ctx = null.asInstanceOf[Scalan] // ok! type level only registerClassEntry(clazz, methods = Map( mkMethod(clazz, "xor", Array[Class[_]](classOf[Base#Ref[_]], classOf[Base#Ref[_]])) { (obj, args) => @@ -145,7 +145,7 @@ object GraphIRReflection { { val clazz = classOf[Colls#Coll[_]] - val ctx = null.asInstanceOf[Library] // ok! type level only + val ctx = null.asInstanceOf[Scalan] // ok! type level only registerClassEntry(clazz, methods = Map( mkMethod(clazz, "append", Array[Class[_]](classOf[Base#Ref[_]])) { (obj, args) => diff --git a/sc/shared/src/main/scala/scalan/Library.scala b/sc/shared/src/main/scala/scalan/Library.scala deleted file mode 100644 index 43f20813f0..0000000000 --- a/sc/shared/src/main/scala/scalan/Library.scala +++ /dev/null @@ -1,120 +0,0 @@ -package scalan - -import scala.language.implicitConversions -import sigma._ -import sigma.data.{Nullable, RType} -import special.wrappers.WrappersModule -import sigma.util.MemoizedFunc - -trait Library extends Scalan - with WrappersModule - with CollsModule -{ - import WOption._ - import WRType._ - import Coll._; import CollBuilder._; - import WSpecialPredef._ - - type LazyRep[T] = MutableLazy[Ref[T]] - - private val _liftElemMemo = new MemoizedFunc({ - case eT: Elem[t] => - val lT = Liftables.asLiftable[Any, t](eT.liftable) - liftableRType(lT).lift(eT.sourceType.asInstanceOf[RType[Any]]) - }) - implicit def liftElem[T](eT: Elem[T]): Ref[WRType[T]] = { - _liftElemMemo(eT).asInstanceOf[Ref[WRType[T]]] // asRep cannot be used for AnyRef - } - - private val _specialPredef: LazyRep[WSpecialPredefCompanionCtor] = MutableLazy(RWSpecialPredef.value) - def specialPredef: Ref[WSpecialPredefCompanionCtor] = _specialPredef.value - - override protected def onReset(): Unit = { - _specialPredef.reset() - _liftElemMemo.reset() - super.onReset() - } - - val CM = CollMethods - private val CBM = CollBuilderMethods - private val WOptionM = WOptionMethods - private val SPCM = WSpecialPredefCompanionMethods - - def colBuilder: Ref[CollBuilder] - - object IsNumericToInt { - def unapply(d: Def[_]): Nullable[Ref[A] forSome {type A}] = d match { - case ApplyUnOp(_: NumericToInt[_], x) => Nullable(x.asInstanceOf[Ref[A] forSome {type A}]) - case _ => Nullable.None - } - } - object IsNumericToLong { - def unapply(d: Def[_]): Nullable[Ref[A] forSome {type A}] = d match { - case ApplyUnOp(_: NumericToLong[_], x) => Nullable(x.asInstanceOf[Ref[A] forSome {type A}]) - case _ => Nullable.None - } - } - - override def rewriteDef[T](d: Def[T]) = d match { - case CM.length(ys) => ys.node match { - // Rule: xs.map(f).length ==> xs.length - case CM.map(xs, _) => - xs.length - // Rule: replicate(len, v).length => len - case CBM.replicate(_, len, _) => - len - // Rule: Const[Coll[T]](coll).length => - case CollConst(coll, _) => - coll.length - // Rule: Coll(items @ Seq(x1, x2, x3)).length => items.length - case CBM.fromItems(_, items, _) => - items.length - case _ => super.rewriteDef(d) - } - - // Rule: replicate(l, x).zip(replicate(l, y)) ==> replicate(l, (x,y)) - case CM.zip(CBM.replicate(b1, l1, v1), CBM.replicate(b2, l2, v2)) if b1 == b2 && l1 == l2 => - b1.replicate(l1, Pair(v1, v2)) - - case CM.map(xs, _f) => _f.node match { - case IdentityLambda() => xs - case _ => xs.node match { - // Rule: replicate(l, v).map(f) ==> replicate(l, f(v)) - case CBM.replicate(b, l, v: Ref[a]) => - val f = asRep[a => Any](_f) - b.replicate(l, Apply(f, v, false)) - - // Rule: xs.map(f).map(g) ==> xs.map(x => g(f(x))) - case CM.map(_xs, f: RFunc[a, b]) => - implicit val ea = f.elem.eDom - val xs = asRep[Coll[a]](_xs) - val g = asRep[b => Any](_f) - xs.map[Any](fun { x: Ref[a] => g(f(x)) }) - - case _ => super.rewriteDef(d) - } - } - - case WOptionM.getOrElse(opt, _) => opt.node match { - // Rule: Some(x).getOrElse(_) ==> x - case SPCM.some(x) => x - case WOptionConst(Some(x), lA) => lA.lift(x) - case _ => super.rewriteDef(d) - } - - case _ => super.rewriteDef(d) - } - - override def invokeUnlifted(e: Elem[_], mc: MethodCall, dataEnv: DataEnv): Any = e match { - case _: CollElem[_,_] => mc match { - case CollMethods.map(_, f) => - val newMC = mc.copy(args = mc.args :+ f.elem.eRange)(mc.resultType, mc.isAdapterCall) - super.invokeUnlifted(e, newMC, dataEnv) - case _ => - super.invokeUnlifted(e, mc, dataEnv) - } - case _ => - super.invokeUnlifted(e, mc, dataEnv) - } - -} diff --git a/sc/shared/src/main/scala/scalan/Scalan.scala b/sc/shared/src/main/scala/scalan/Scalan.scala index c2e9359261..a466df29fa 100644 --- a/sc/shared/src/main/scala/scalan/Scalan.scala +++ b/sc/shared/src/main/scala/scalan/Scalan.scala @@ -2,6 +2,10 @@ package scalan import scalan.primitives._ import scalan.staged.Transforming +import sigma.CollsModule +import sigma.data.{Nullable, RType} +import sigma.util.MemoizedFunc +import special.wrappers.WrappersModule /** Aggregate cake with all inter-dependent modules assembled together. * Each instance of this class contains independent IR context, thus many @@ -16,7 +20,7 @@ import scalan.staged.Transforming * in classed derived from `Scalan`, this is significant benefit over * *everything is global* design. */ -class Scalan + trait Scalan extends TypeDescs with MethodCalls with Tuples @@ -33,4 +37,116 @@ class Scalan with Entities with Modules with DefRewriting + with WrappersModule + with CollsModule { + + import WOption._ + import WRType._ + import Coll._; import CollBuilder._; + import WSpecialPredef._ + + type LazyRep[T] = MutableLazy[Ref[T]] + + private val _liftElemMemo = new MemoizedFunc({ + case eT: Elem[t] => + val lT = Liftables.asLiftable[Any, t](eT.liftable) + liftableRType(lT).lift(eT.sourceType.asInstanceOf[RType[Any]]) + }) + implicit def liftElem[T](eT: Elem[T]): Ref[WRType[T]] = { + _liftElemMemo(eT).asInstanceOf[Ref[WRType[T]]] // asRep cannot be used for AnyRef + } + + private val _specialPredef: LazyRep[WSpecialPredefCompanionCtor] = MutableLazy(RWSpecialPredef.value) + def specialPredef: Ref[WSpecialPredefCompanionCtor] = _specialPredef.value + + override protected def onReset(): Unit = { + _specialPredef.reset() + _liftElemMemo.reset() + super.onReset() + } + + val CM = CollMethods + private val CBM = CollBuilderMethods + private val WOptionM = WOptionMethods + private val SPCM = WSpecialPredefCompanionMethods + + def colBuilder: Ref[CollBuilder] + + object IsNumericToInt { + def unapply(d: Def[_]): Nullable[Ref[A] forSome {type A}] = d match { + case ApplyUnOp(_: NumericToInt[_], x) => Nullable(x.asInstanceOf[Ref[A] forSome {type A}]) + case _ => Nullable.None + } + } + object IsNumericToLong { + def unapply(d: Def[_]): Nullable[Ref[A] forSome {type A}] = d match { + case ApplyUnOp(_: NumericToLong[_], x) => Nullable(x.asInstanceOf[Ref[A] forSome {type A}]) + case _ => Nullable.None + } + } + + override def rewriteDef[T](d: Def[T]) = d match { + case CM.length(ys) => ys.node match { + // Rule: xs.map(f).length ==> xs.length + case CM.map(xs, _) => + xs.length + // Rule: replicate(len, v).length => len + case CBM.replicate(_, len, _) => + len + // Rule: Const[Coll[T]](coll).length => + case CollConst(coll, _) => + coll.length + // Rule: Coll(items @ Seq(x1, x2, x3)).length => items.length + case CBM.fromItems(_, items, _) => + items.length + case _ => super.rewriteDef(d) + } + + // Rule: replicate(l, x).zip(replicate(l, y)) ==> replicate(l, (x,y)) + case CM.zip(CBM.replicate(b1, l1, v1), CBM.replicate(b2, l2, v2)) if b1 == b2 && l1 == l2 => + b1.replicate(l1, Pair(v1, v2)) + + case CM.map(xs, _f) => _f.node match { + case IdentityLambda() => xs + case _ => xs.node match { + // Rule: replicate(l, v).map(f) ==> replicate(l, f(v)) + case CBM.replicate(b, l, v: Ref[a]) => + val f = asRep[a => Any](_f) + b.replicate(l, Apply(f, v, false)) + + // Rule: xs.map(f).map(g) ==> xs.map(x => g(f(x))) + case CM.map(_xs, f: RFunc[a, b]) => + implicit val ea = f.elem.eDom + val xs = asRep[Coll[a]](_xs) + val g = asRep[b => Any](_f) + xs.map[Any](fun { x: Ref[a] => g(f(x)) }) + + case _ => super.rewriteDef(d) + } + } + + case WOptionM.getOrElse(opt, _) => opt.node match { + // Rule: Some(x).getOrElse(_) ==> x + case SPCM.some(x) => x + case WOptionConst(Some(x), lA) => lA.lift(x) + case _ => super.rewriteDef(d) + } + + case _ => super.rewriteDef(d) + } + + override def invokeUnlifted(e: Elem[_], mc: MethodCall, dataEnv: DataEnv): Any = e match { + case _: CollElem[_,_] => mc match { + case CollMethods.map(_, f) => + val newMC = mc.copy(args = mc.args :+ f.elem.eRange)(mc.resultType, mc.isAdapterCall) + super.invokeUnlifted(e, newMC, dataEnv) + case _ => + super.invokeUnlifted(e, mc, dataEnv) + } + case _ => + super.invokeUnlifted(e, mc, dataEnv) + } + + +} diff --git a/sc/shared/src/main/scala/sigmastate/eval/SigmaLibrary.scala b/sc/shared/src/main/scala/sigmastate/eval/SigmaLibrary.scala index 7745873620..ea0329e3db 100644 --- a/sc/shared/src/main/scala/sigmastate/eval/SigmaLibrary.scala +++ b/sc/shared/src/main/scala/sigmastate/eval/SigmaLibrary.scala @@ -1,10 +1,10 @@ package sigmastate.eval -import scalan.Library +import scalan.Scalan import sigma.SigmaDslModule /** Main trait which represents sigma operations in graph IR cake. */ -trait SigmaLibrary extends Library +trait SigmaLibrary extends Scalan with sigma.wrappers.WrappersModule with SigmaDslModule { diff --git a/sc/shared/src/main/scala/special/collection/CollsUnit.scala b/sc/shared/src/main/scala/special/collection/CollsUnit.scala index 90f0dca99e..db9922b82f 100644 --- a/sc/shared/src/main/scala/special/collection/CollsUnit.scala +++ b/sc/shared/src/main/scala/special/collection/CollsUnit.scala @@ -8,7 +8,7 @@ package sigma { * The semantics of each method is the same as in the original class, please look there * for details. */ - trait Colls extends Base { self: Library => + trait Colls extends Base { self: Scalan => trait Coll[A] extends Def[Coll[A]] { implicit def eA: Elem[A]; def length: Ref[Int]; diff --git a/sc/shared/src/main/scala/special/collection/impl/CollsImpl.scala b/sc/shared/src/main/scala/special/collection/impl/CollsImpl.scala index 239bfff4e5..382f5fe763 100644 --- a/sc/shared/src/main/scala/special/collection/impl/CollsImpl.scala +++ b/sc/shared/src/main/scala/special/collection/impl/CollsImpl.scala @@ -9,8 +9,8 @@ package impl { import sigma.reflection.{RClass, RMethod} // Abs ----------------------------------- -trait CollsDefs extends scalan.Scalan with Colls { - self: Library => +trait CollsDefs extends Base with Colls { + self: Scalan => registerModule(CollsModule) @@ -639,4 +639,4 @@ object CollsModule extends scalan.ModuleInfo("sigma", "Colls") { } } -trait CollsModule extends sigma.impl.CollsDefs {self: Library =>} +trait CollsModule extends sigma.impl.CollsDefs {self: Scalan =>} diff --git a/sc/shared/src/main/scala/special/sigma/wrappers/WrappersModule.scala b/sc/shared/src/main/scala/special/sigma/wrappers/WrappersModule.scala index 6696788621..50869cc4e1 100644 --- a/sc/shared/src/main/scala/special/sigma/wrappers/WrappersModule.scala +++ b/sc/shared/src/main/scala/special/sigma/wrappers/WrappersModule.scala @@ -1,4 +1,6 @@ package sigma.wrappers +import scalan.Scalan + trait WrappersModule - extends special.wrappers.WrappersModule + extends special.wrappers.WrappersModule { self: Scalan => } diff --git a/sc/shared/src/main/scala/special/wrappers/WrappersModule.scala b/sc/shared/src/main/scala/special/wrappers/WrappersModule.scala index b74bec314e..745413569a 100644 --- a/sc/shared/src/main/scala/special/wrappers/WrappersModule.scala +++ b/sc/shared/src/main/scala/special/wrappers/WrappersModule.scala @@ -1,5 +1,6 @@ package special.wrappers +import scalan.Scalan import wrappers.scala.WOptionsModule import wrappers.scalan.WRTypesModule import wrappers.special.WSpecialPredefsModule @@ -7,4 +8,4 @@ import wrappers.special.WSpecialPredefsModule trait WrappersModule extends WSpecialPredefsModule with WOptionsModule - with WRTypesModule \ No newline at end of file + with WRTypesModule { self: Scalan => } \ No newline at end of file diff --git a/sc/shared/src/main/scala/wrappers/scala/WOptions.scala b/sc/shared/src/main/scala/wrappers/scala/WOptions.scala index 4bd314c1de..445da52006 100644 --- a/sc/shared/src/main/scala/wrappers/scala/WOptions.scala +++ b/sc/shared/src/main/scala/wrappers/scala/WOptions.scala @@ -3,7 +3,7 @@ package wrappers.scala { import special.wrappers.WrappersModule - trait WOptions extends Base { self: WrappersModule => + trait WOptions extends Base { self: Scalan => trait WOption[A] extends Def[WOption[A]] { implicit def eA: Elem[A]; def isDefined: Ref[Boolean]; diff --git a/sc/shared/src/main/scala/wrappers/scala/impl/WOptionsImpl.scala b/sc/shared/src/main/scala/wrappers/scala/impl/WOptionsImpl.scala index 45d0a91ad6..62a0e0c10f 100644 --- a/sc/shared/src/main/scala/wrappers/scala/impl/WOptionsImpl.scala +++ b/sc/shared/src/main/scala/wrappers/scala/impl/WOptionsImpl.scala @@ -11,8 +11,8 @@ package impl { import sigma.reflection.{RClass, RMethod} // Abs ----------------------------------- -trait WOptionsDefs extends scalan.Scalan with WOptions { - self: WrappersModule => +trait WOptionsDefs extends Base with WOptions { + self: Scalan => class WOptionCls extends EntityObject("WOption") { // entityConst: single const for each entity @@ -240,4 +240,4 @@ object WOptionsModule extends scalan.ModuleInfo("wrappers.scala", "WOptions") { } } -trait WOptionsModule extends wrappers.scala.impl.WOptionsDefs {self: WrappersModule =>} +trait WOptionsModule extends wrappers.scala.impl.WOptionsDefs {self: Scalan =>} diff --git a/sc/shared/src/main/scala/wrappers/scalan/WRTypes.scala b/sc/shared/src/main/scala/wrappers/scalan/WRTypes.scala index 8c6bc48f8e..bc71b8ad26 100644 --- a/sc/shared/src/main/scala/wrappers/scalan/WRTypes.scala +++ b/sc/shared/src/main/scala/wrappers/scalan/WRTypes.scala @@ -1,9 +1,8 @@ package wrappers.scalan { import scalan._ - import special.wrappers.WrappersModule - trait WRTypes extends Base { self: WrappersModule => + trait WRTypes extends Base { self: Scalan => trait WRType[A] extends Def[WRType[A]] { implicit def eA: Elem[A]; def name: Ref[String] diff --git a/sc/shared/src/main/scala/wrappers/scalan/impl/WRTypesImpl.scala b/sc/shared/src/main/scala/wrappers/scalan/impl/WRTypesImpl.scala index 9b2676f70d..c78a2268bf 100644 --- a/sc/shared/src/main/scala/wrappers/scalan/impl/WRTypesImpl.scala +++ b/sc/shared/src/main/scala/wrappers/scalan/impl/WRTypesImpl.scala @@ -1,18 +1,20 @@ package wrappers.scalan -import scala.language.{existentials,implicitConversions} +import scalan.Scalan + +import scala.language.{existentials, implicitConversions} import sigma.data.RType -import special.wrappers.WrappersModule import special.wrappers.RTypeWrapSpec + import scala.collection.compat.immutable.ArraySeq package impl { - import scalan.GraphIRReflection + import scalan.{Base, GraphIRReflection, Scalan} import sigma.reflection.{RClass, RMethod} // Abs ----------------------------------- -trait WRTypesDefs extends scalan.Scalan with WRTypes { - self: WrappersModule => +trait WRTypesDefs extends Base with WRTypes { + self: Scalan => registerModule(WRTypesModule) @@ -116,4 +118,4 @@ object WRTypesModule extends scalan.ModuleInfo("wrappers.scalan", "WRTypes") { } } -trait WRTypesModule extends wrappers.scalan.impl.WRTypesDefs {self: WrappersModule =>} +trait WRTypesModule extends wrappers.scalan.impl.WRTypesDefs {self: Scalan =>} diff --git a/sc/shared/src/main/scala/wrappers/special/WSpecialPredefs.scala b/sc/shared/src/main/scala/wrappers/special/WSpecialPredefs.scala index 5abbab95e2..d1c1260391 100644 --- a/sc/shared/src/main/scala/wrappers/special/WSpecialPredefs.scala +++ b/sc/shared/src/main/scala/wrappers/special/WSpecialPredefs.scala @@ -1,9 +1,7 @@ package wrappers.special { import scalan._ - import special.wrappers.WrappersModule - - trait WSpecialPredefs extends Base { self: WrappersModule => + trait WSpecialPredefs extends Base { self: Scalan => trait WSpecialPredef extends Def[WSpecialPredef]; trait WSpecialPredefCompanion { def some[A](x: Ref[A]): Ref[WOption[A]]; diff --git a/sc/shared/src/main/scala/wrappers/special/impl/WSpecialPredefsImpl.scala b/sc/shared/src/main/scala/wrappers/special/impl/WSpecialPredefsImpl.scala index 1f80e71676..697de01802 100644 --- a/sc/shared/src/main/scala/wrappers/special/impl/WSpecialPredefsImpl.scala +++ b/sc/shared/src/main/scala/wrappers/special/impl/WSpecialPredefsImpl.scala @@ -9,8 +9,8 @@ package impl { import sigma.reflection.RClass // Abs ----------------------------------- -trait WSpecialPredefsDefs extends scalan.Scalan with WSpecialPredefs { - self: WrappersModule => +trait WSpecialPredefsDefs extends Base with WSpecialPredefs { + self: Scalan => registerModule(WSpecialPredefsModule) @@ -66,4 +66,4 @@ object WSpecialPredefsModule extends scalan.ModuleInfo("wrappers.special", "WSpe } } -trait WSpecialPredefsModule extends wrappers.special.impl.WSpecialPredefsDefs {self: WrappersModule =>} +trait WSpecialPredefsModule extends wrappers.special.impl.WSpecialPredefsDefs {self: Scalan =>} diff --git a/sc/shared/src/test/scala/scalan/TestLibrary.scala b/sc/shared/src/test/scala/scalan/TestLibrary.scala index efbce25e68..d78312317f 100644 --- a/sc/shared/src/test/scala/scalan/TestLibrary.scala +++ b/sc/shared/src/test/scala/scalan/TestLibrary.scala @@ -1,6 +1,6 @@ package scalan -trait TestLibrary extends Library { +trait TestLibrary extends Scalan { import CollBuilder._ val reflection = (GraphIRReflection) lazy val colBuilder: Ref[CollBuilder] = variable[CollBuilder] diff --git a/sc/shared/src/test/scala/sigma/CollsStagingTests.scala b/sc/shared/src/test/scala/sigma/CollsStagingTests.scala index 3b56920c8d..332c5e300c 100644 --- a/sc/shared/src/test/scala/sigma/CollsStagingTests.scala +++ b/sc/shared/src/test/scala/sigma/CollsStagingTests.scala @@ -41,7 +41,7 @@ class CollsStagingTests extends WrappersTests { } test("invokeUnlifted for Col") { - val ctx = new WrappersCtx with Library + val ctx = new WrappersCtx with Scalan import ctx._ import Coll._ import CollBuilder._ @@ -59,7 +59,7 @@ class CollsStagingTests extends WrappersTests { } test("invokeUnlifted for method of Ctor") { - val ctx = new WrappersCtx with Library + val ctx = new WrappersCtx with Scalan import ctx._ import Coll._ import CollBuilder._ diff --git a/sc/shared/src/test/scala/special/wrappers/WOptionTests.scala b/sc/shared/src/test/scala/special/wrappers/WOptionTests.scala index 7e046739f0..e952ba7c00 100644 --- a/sc/shared/src/test/scala/special/wrappers/WOptionTests.scala +++ b/sc/shared/src/test/scala/special/wrappers/WOptionTests.scala @@ -1,7 +1,6 @@ package special.wrappers import scala.language.reflectiveCalls -import scalan.Library class WOptionTests extends WrappersTests { From 3ffafe76a8bb42b948d8ba109aa6b03c44cdecdb Mon Sep 17 00:00:00 2001 From: Alexander Slesarenko Date: Wed, 15 May 2024 20:12:39 +0100 Subject: [PATCH 067/314] refactor-ir-cake: removed SigmaLibrary.scala --- .../main/scala/scalan/GraphIRReflection.scala | 25 +++++++++---------- sc/shared/src/main/scala/scalan/Scalan.scala | 14 ++++++++--- .../scala/sigmastate/eval/GraphBuilding.scala | 4 +-- .../scala/sigmastate/eval/SigmaLibrary.scala | 17 ------------- .../scala/sigmastate/eval/TreeBuilding.scala | 3 ++- .../scala/special/sigma/SigmaDslUnit.scala | 3 +-- .../special/sigma/impl/SigmaDslImpl.scala | 8 +++--- .../src/test/scala/scalan/TestLibrary.scala | 2 ++ 8 files changed, 32 insertions(+), 44 deletions(-) delete mode 100644 sc/shared/src/main/scala/sigmastate/eval/SigmaLibrary.scala diff --git a/sc/shared/src/main/scala/scalan/GraphIRReflection.scala b/sc/shared/src/main/scala/scalan/GraphIRReflection.scala index 787873035d..86244fb675 100644 --- a/sc/shared/src/main/scala/scalan/GraphIRReflection.scala +++ b/sc/shared/src/main/scala/scalan/GraphIRReflection.scala @@ -3,7 +3,6 @@ package scalan import scalan.primitives.Thunks import sigma.reflection.ReflectionData.registerClassEntry import sigma.reflection.{ReflectionData, mkConstructor, mkMethod} -import sigmastate.eval.SigmaLibrary import sigma.Colls import sigma.SigmaDsl import sigma.data.RType @@ -211,7 +210,7 @@ object GraphIRReflection { } { val clazz = classOf[SigmaDsl#AvlTree] - val ctx = null.asInstanceOf[SigmaLibrary] // ok! type level only + val ctx = null.asInstanceOf[Scalan] // ok! type level only registerClassEntry(clazz, methods = Map( mkMethod(clazz, "updateOperations", Array[Class[_]](classOf[Base#Ref[_]])) { (obj, args) => @@ -269,7 +268,7 @@ object GraphIRReflection { } { val clazz = classOf[SigmaDsl#Box] - val ctx = null.asInstanceOf[SigmaLibrary] // ok! type level only + val ctx = null.asInstanceOf[Scalan] // ok! type level only registerClassEntry(clazz, methods = Map( mkMethod(clazz, "value", Array[Class[_]]()) { (obj, _) => @@ -302,7 +301,7 @@ object GraphIRReflection { { val clazz = classOf[SigmaDsl#Context] - val ctx = null.asInstanceOf[SigmaLibrary] // ok! type level only + val ctx = null.asInstanceOf[Scalan] // ok! type level only registerClassEntry(clazz, methods = Map( mkMethod(clazz, "LastBlockUtxoRootHash", Array[Class[_]]()) { (obj, args) => @@ -343,7 +342,7 @@ object GraphIRReflection { } { val clazz = classOf[SigmaDsl#GroupElement] - val ctx = null.asInstanceOf[SigmaLibrary] // ok! type level only + val ctx = null.asInstanceOf[Scalan] // ok! type level only registerClassEntry(clazz, methods = Map( mkMethod(clazz, "exp", Array[Class[_]](classOf[Base#Ref[_]])) { (obj, args) => @@ -363,7 +362,7 @@ object GraphIRReflection { } { val clazz = classOf[SigmaDsl#Header] - val ctx = null.asInstanceOf[SigmaLibrary] // ok! type level only + val ctx = null.asInstanceOf[Scalan] // ok! type level only registerClassEntry(clazz, methods = Map( mkMethod(clazz, "minerPk", Array[Class[_]]()) { (obj, args) => @@ -416,7 +415,7 @@ object GraphIRReflection { } { val clazz = classOf[SigmaDsl#PreHeader] - val ctx = null.asInstanceOf[SigmaLibrary] // ok! type level only + val ctx = null.asInstanceOf[Scalan] // ok! type level only registerClassEntry(clazz, methods = Map( mkMethod(clazz, "minerPk", Array[Class[_]]()) { (obj, _) => @@ -445,7 +444,7 @@ object GraphIRReflection { } { val clazz = classOf[SigmaDsl#SigmaDslBuilder] - val ctx = null.asInstanceOf[SigmaLibrary] // ok! type level only + val ctx = null.asInstanceOf[Scalan] // ok! type level only registerClassEntry(clazz, methods = Map( mkMethod(clazz, "byteArrayToLong", Array[Class[_]](classOf[Base#Ref[_]])) { (obj, args) => @@ -512,7 +511,7 @@ object GraphIRReflection { ) } - { val ctx = null.asInstanceOf[SigmaLibrary] // ok! type level only + { val ctx = null.asInstanceOf[Scalan] // ok! type level only val clazz = classOf[ctx.WOption.WOptionElem[_, _]] registerClassEntry(clazz, constructors = Array( @@ -525,7 +524,7 @@ object GraphIRReflection { } { val clazz = classOf[WRTypes#WRType[_]] - val ctx = null.asInstanceOf[SigmaLibrary] // ok! type level only + val ctx = null.asInstanceOf[Scalan] // ok! type level only registerClassEntry(clazz, methods = Map( mkMethod(clazz, "name", Array[Class[_]]()) { (obj, _) => @@ -535,7 +534,7 @@ object GraphIRReflection { ) } - { val ctx = null.asInstanceOf[SigmaLibrary] // ok! type level only + { val ctx = null.asInstanceOf[Scalan] // ok! type level only val clazz = classOf[ctx.WRType.WRTypeElem[_, _]] registerClassEntry(clazz, constructors = Array( @@ -547,7 +546,7 @@ object GraphIRReflection { ) } - { val ctx = null.asInstanceOf[SigmaLibrary] // ok! type level only + { val ctx = null.asInstanceOf[Scalan] // ok! type level only val clazz = classOf[ctx.Coll.CollElem[_, _]] registerClassEntry(clazz, constructors = Array( @@ -560,7 +559,7 @@ object GraphIRReflection { } { val clazz = classOf[wrappers.special.WSpecialPredefs#WSpecialPredefCompanion] - val ctx = null.asInstanceOf[SigmaLibrary] // ok! type level only + val ctx = null.asInstanceOf[Scalan] // ok! type level only registerClassEntry(clazz, methods = Map( mkMethod(clazz, "some", Array[Class[_]](classOf[Base#Ref[_]])) { (obj, args) => diff --git a/sc/shared/src/main/scala/scalan/Scalan.scala b/sc/shared/src/main/scala/scalan/Scalan.scala index a466df29fa..b6e9ae2efd 100644 --- a/sc/shared/src/main/scala/scalan/Scalan.scala +++ b/sc/shared/src/main/scala/scalan/Scalan.scala @@ -2,7 +2,7 @@ package scalan import scalan.primitives._ import scalan.staged.Transforming -import sigma.CollsModule +import sigma.{CollsModule, SigmaDslModule} import sigma.data.{Nullable, RType} import sigma.util.MemoizedFunc import special.wrappers.WrappersModule @@ -20,7 +20,7 @@ import special.wrappers.WrappersModule * in classed derived from `Scalan`, this is significant benefit over * *everything is global* design. */ - trait Scalan +trait Scalan extends TypeDescs with MethodCalls with Tuples @@ -38,7 +38,9 @@ import special.wrappers.WrappersModule with Modules with DefRewriting with WrappersModule - with CollsModule { + with CollsModule + with sigma.wrappers.WrappersModule + with SigmaDslModule { import WOption._ import WRType._ @@ -72,6 +74,11 @@ import special.wrappers.WrappersModule def colBuilder: Ref[CollBuilder] + implicit lazy val wRTypeAnyElement: Elem[WRType[Any]] = wRTypeElement(AnyElement) + + /** During compilation represent a global value Global, see also SGlobal type. */ + def sigmaDslBuilder: Ref[SigmaDslBuilder] + object IsNumericToInt { def unapply(d: Def[_]): Nullable[Ref[A] forSome {type A}] = d match { case ApplyUnOp(_: NumericToInt[_], x) => Nullable(x.asInstanceOf[Ref[A] forSome {type A}]) @@ -147,6 +154,5 @@ import special.wrappers.WrappersModule super.invokeUnlifted(e, mc, dataEnv) } - } diff --git a/sc/shared/src/main/scala/sigmastate/eval/GraphBuilding.scala b/sc/shared/src/main/scala/sigmastate/eval/GraphBuilding.scala index 4a126754a5..ebfd0c8e90 100644 --- a/sc/shared/src/main/scala/sigmastate/eval/GraphBuilding.scala +++ b/sc/shared/src/main/scala/sigmastate/eval/GraphBuilding.scala @@ -1,7 +1,7 @@ package sigmastate.eval import org.ergoplatform._ -import scalan.MutableLazy +import scalan.{MutableLazy, Scalan} import sigma.{SigmaException, ast} import sigma.ast.TypeCodes.LastConstantCode import sigma.ast.Value.Typed @@ -27,7 +27,7 @@ import scala.collection.mutable.ArrayBuffer * CSE however means the original structure of source code may not be preserved in the * resulting ErgoTree. * */ -trait GraphBuilding extends SigmaLibrary { IR: IRContext => +trait GraphBuilding extends Scalan { IR: IRContext => import AvlTree._ import BigInt._ import Box._ diff --git a/sc/shared/src/main/scala/sigmastate/eval/SigmaLibrary.scala b/sc/shared/src/main/scala/sigmastate/eval/SigmaLibrary.scala deleted file mode 100644 index ea0329e3db..0000000000 --- a/sc/shared/src/main/scala/sigmastate/eval/SigmaLibrary.scala +++ /dev/null @@ -1,17 +0,0 @@ -package sigmastate.eval - -import scalan.Scalan -import sigma.SigmaDslModule - -/** Main trait which represents sigma operations in graph IR cake. */ -trait SigmaLibrary extends Scalan - with sigma.wrappers.WrappersModule - with SigmaDslModule -{ - import WRType._ - - implicit lazy val wRTypeAnyElement: Elem[WRType[Any]] = wRTypeElement(AnyElement) - - /** During compilation represent a global value Global, see also SGlobal type. */ - def sigmaDslBuilder: Ref[SigmaDslBuilder] -} diff --git a/sc/shared/src/main/scala/sigmastate/eval/TreeBuilding.scala b/sc/shared/src/main/scala/sigmastate/eval/TreeBuilding.scala index 11ae0b85f4..770e7a408f 100644 --- a/sc/shared/src/main/scala/sigmastate/eval/TreeBuilding.scala +++ b/sc/shared/src/main/scala/sigmastate/eval/TreeBuilding.scala @@ -3,6 +3,7 @@ package sigmastate.eval import sigma.ast._ import org.ergoplatform._ +import scalan.Scalan import sigma.ast.syntax.ValueOps import sigma.serialization.OpCodes._ import sigma.serialization.ConstantStore @@ -24,7 +25,7 @@ import sigma.serialization.ValueCodes.OpCode * * @see buildTree method * */ -trait TreeBuilding extends SigmaLibrary { IR: IRContext => +trait TreeBuilding extends Scalan { IR: IRContext => import Liftables._ import Context._ import SigmaProp._ diff --git a/sc/shared/src/main/scala/special/sigma/SigmaDslUnit.scala b/sc/shared/src/main/scala/special/sigma/SigmaDslUnit.scala index 48548226a5..91add24b4d 100644 --- a/sc/shared/src/main/scala/special/sigma/SigmaDslUnit.scala +++ b/sc/shared/src/main/scala/special/sigma/SigmaDslUnit.scala @@ -1,8 +1,7 @@ package sigma { import scalan._ - import sigmastate.eval.SigmaLibrary - trait SigmaDsl extends Base { self: SigmaLibrary => + trait SigmaDsl extends Base { self: Scalan => trait BigInt extends Def[BigInt] { def add(that: Ref[BigInt]): Ref[BigInt]; def subtract(that: Ref[BigInt]): Ref[BigInt]; diff --git a/sc/shared/src/main/scala/special/sigma/impl/SigmaDslImpl.scala b/sc/shared/src/main/scala/special/sigma/impl/SigmaDslImpl.scala index 70fb35c329..a79b006515 100644 --- a/sc/shared/src/main/scala/special/sigma/impl/SigmaDslImpl.scala +++ b/sc/shared/src/main/scala/special/sigma/impl/SigmaDslImpl.scala @@ -2,18 +2,16 @@ package sigma import scala.language.{existentials, implicitConversions} import scalan._ -import sigmastate.eval.SigmaLibrary import scala.collection.compat.immutable.ArraySeq package impl { import sigma.data.{Nullable, RType} import sigma.reflection.{RClass, RMethod} - import sigmastate.eval.SigmaLibrary // Abs ----------------------------------- -trait SigmaDslDefs extends scalan.Scalan with SigmaDsl { - self: SigmaLibrary => +trait SigmaDslDefs extends Base with SigmaDsl { + self: Scalan => registerModule(SigmaDslModule) @@ -2326,4 +2324,4 @@ object SigmaDslModule extends scalan.ModuleInfo("sigma", "SigmaDsl") { } } -trait SigmaDslModule extends sigma.impl.SigmaDslDefs {self: SigmaLibrary =>} +trait SigmaDslModule extends sigma.impl.SigmaDslDefs {self: Scalan =>} diff --git a/sc/shared/src/test/scala/scalan/TestLibrary.scala b/sc/shared/src/test/scala/scalan/TestLibrary.scala index d78312317f..c3d8a5beb8 100644 --- a/sc/shared/src/test/scala/scalan/TestLibrary.scala +++ b/sc/shared/src/test/scala/scalan/TestLibrary.scala @@ -2,6 +2,8 @@ package scalan trait TestLibrary extends Scalan { import CollBuilder._ + import SigmaDslBuilder._ val reflection = (GraphIRReflection) lazy val colBuilder: Ref[CollBuilder] = variable[CollBuilder] + lazy val sigmaDslBuilder: Ref[SigmaDslBuilder] = variable[SigmaDslBuilder] } From 30d3bd9ef588b0e07f7258af71c5a0dab139822e Mon Sep 17 00:00:00 2001 From: Alexander Slesarenko Date: Wed, 15 May 2024 20:34:54 +0100 Subject: [PATCH 068/314] refactor-ir-cake: Scalan moved to sigma.compiler package --- sc/js/src/test/scala/scalan/Platform.scala | 2 ++ sc/jvm/src/test/scala/scalan/Platform.scala | 1 + .../scalan/compilation/GraphVizExport.scala | 2 +- .../InterpreterReflectionGeneratorTests.scala | 4 +-- .../sigmastate/ReflectionGenerator.scala | 2 +- .../{scalan => sigma/compiler}/Base.scala | 27 ++++++++++--------- .../compiler}/DefRewriting.scala | 3 ++- .../{scalan => sigma/compiler}/Entities.scala | 2 +- .../compiler}/Exceptions.scala | 0 .../compiler}/GraphIRReflection.scala | 11 ++++---- .../compiler}/MethodCalls.scala | 12 ++++----- .../compiler}/ModuleInfo.scala | 2 +- .../{scalan => sigma/compiler}/Modules.scala | 2 +- .../compiler}/MutableLazy.scala | 0 .../{scalan => sigma/compiler}/Scalan.scala | 12 +++++---- .../compiler}/TypeDescs.scala | 16 +++++------ .../compiler}/core/Variance.scala | 0 .../compiler}/meta/SSymName.scala | 0 .../compiler}/primitives/Equal.scala | 4 +-- .../compiler}/primitives/Functions.scala | 15 +++++------ .../compiler}/primitives/IfThenElse.scala | 4 +-- .../compiler}/primitives/LogicalOps.scala | 4 +-- .../compiler}/primitives/NumericOps.scala | 4 +-- .../compiler}/primitives/OrderingOps.scala | 4 +-- .../compiler}/primitives/Thunks.scala | 9 +++---- .../compiler}/primitives/Tuples.scala | 7 ++--- .../compiler}/primitives/UnBinOps.scala | 4 +-- .../compiler}/primitives/UniversalOps.scala | 4 +-- .../compiler}/staged/AstGraphs.scala | 10 +++---- .../compiler}/staged/ProgramGraphs.scala | 10 +++---- .../compiler}/staged/Transforming.scala | 12 ++++----- .../scala/sigmastate/eval/GraphBuilding.scala | 3 ++- .../scala/sigmastate/eval/TreeBuilding.scala | 2 +- .../scala/sigmastate/lang/SigmaCompiler.scala | 2 +- .../scala/special/collection/CollsUnit.scala | 1 + .../special/collection/impl/CollsImpl.scala | 7 +++-- .../scala/special/sigma/SigmaDslUnit.scala | 1 + .../special/sigma/impl/SigmaDslImpl.scala | 4 ++- .../sigma/wrappers/WrappersModule.scala | 2 +- .../special/wrappers/WrappersModule.scala | 2 +- .../main/scala/wrappers/scala/WOptions.scala | 2 +- .../wrappers/scala/impl/WOptionsImpl.scala | 7 +++-- .../main/scala/wrappers/scalan/WRTypes.scala | 1 + .../wrappers/scalan/impl/WRTypesImpl.scala | 7 +++-- .../wrappers/special/WSpecialPredefs.scala | 1 + .../special/impl/WSpecialPredefsImpl.scala | 6 +++-- .../test/scala/scalan/BaseLiftableTests.scala | 2 ++ .../src/test/scala/scalan/LibraryTests.scala | 1 + .../src/test/scala/scalan/TestContexts.scala | 1 + .../src/test/scala/scalan/TestLibrary.scala | 2 ++ .../test/scala/sigma/CollsStagingTests.scala | 1 + 51 files changed, 135 insertions(+), 109 deletions(-) rename sc/shared/src/main/scala/{scalan => sigma/compiler}/Base.scala (98%) rename sc/shared/src/main/scala/{scalan => sigma/compiler}/DefRewriting.scala (99%) rename sc/shared/src/main/scala/{scalan => sigma/compiler}/Entities.scala (99%) rename sc/shared/src/main/scala/{scalan => sigma/compiler}/Exceptions.scala (100%) rename sc/shared/src/main/scala/{scalan => sigma/compiler}/GraphIRReflection.scala (99%) rename sc/shared/src/main/scala/{scalan => sigma/compiler}/MethodCalls.scala (97%) rename sc/shared/src/main/scala/{scalan => sigma/compiler}/ModuleInfo.scala (95%) rename sc/shared/src/main/scala/{scalan => sigma/compiler}/Modules.scala (95%) rename sc/shared/src/main/scala/{scalan => sigma/compiler}/MutableLazy.scala (100%) rename sc/shared/src/main/scala/{scalan => sigma/compiler}/Scalan.scala (95%) rename sc/shared/src/main/scala/{scalan => sigma/compiler}/TypeDescs.scala (98%) rename sc/shared/src/main/scala/{scalan => sigma/compiler}/core/Variance.scala (100%) rename sc/shared/src/main/scala/{scalan => sigma/compiler}/meta/SSymName.scala (100%) rename sc/shared/src/main/scala/{scalan => sigma/compiler}/primitives/Equal.scala (93%) rename sc/shared/src/main/scala/{scalan => sigma/compiler}/primitives/Functions.scala (98%) rename sc/shared/src/main/scala/{scalan => sigma/compiler}/primitives/IfThenElse.scala (96%) rename sc/shared/src/main/scala/{scalan => sigma/compiler}/primitives/LogicalOps.scala (97%) rename sc/shared/src/main/scala/{scalan => sigma/compiler}/primitives/NumericOps.scala (98%) rename sc/shared/src/main/scala/{scalan => sigma/compiler}/primitives/OrderingOps.scala (97%) rename sc/shared/src/main/scala/{scalan => sigma/compiler}/primitives/Thunks.scala (99%) rename sc/shared/src/main/scala/{scalan => sigma/compiler}/primitives/Tuples.scala (96%) rename sc/shared/src/main/scala/{scalan => sigma/compiler}/primitives/UnBinOps.scala (97%) rename sc/shared/src/main/scala/{scalan => sigma/compiler}/primitives/UniversalOps.scala (98%) rename sc/shared/src/main/scala/{scalan => sigma/compiler}/staged/AstGraphs.scala (98%) rename sc/shared/src/main/scala/{scalan => sigma/compiler}/staged/ProgramGraphs.scala (96%) rename sc/shared/src/main/scala/{scalan => sigma/compiler}/staged/Transforming.scala (98%) diff --git a/sc/js/src/test/scala/scalan/Platform.scala b/sc/js/src/test/scala/scalan/Platform.scala index 5f938111d2..2349a1f444 100644 --- a/sc/js/src/test/scala/scalan/Platform.scala +++ b/sc/js/src/test/scala/scalan/Platform.scala @@ -1,5 +1,7 @@ package scalan +import sigma.compiler.Scalan + import scala.annotation.unused object Platform { diff --git a/sc/jvm/src/test/scala/scalan/Platform.scala b/sc/jvm/src/test/scala/scalan/Platform.scala index 43041a92c6..b9c65374c2 100644 --- a/sc/jvm/src/test/scala/scalan/Platform.scala +++ b/sc/jvm/src/test/scala/scalan/Platform.scala @@ -3,6 +3,7 @@ package scalan import scalan.compilation.GraphVizExport import sigma.util.FileUtil import org.scalatest.Assertions +import sigma.compiler.Scalan object Platform { /** Output graph given by symbols in `sfs` to files. diff --git a/sc/jvm/src/test/scala/scalan/compilation/GraphVizExport.scala b/sc/jvm/src/test/scala/scalan/compilation/GraphVizExport.scala index 8568e6c1db..c5b7f16cca 100644 --- a/sc/jvm/src/test/scala/scalan/compilation/GraphVizExport.scala +++ b/sc/jvm/src/test/scala/scalan/compilation/GraphVizExport.scala @@ -2,8 +2,8 @@ package scalan.compilation import java.awt.Desktop import java.io.{File, PrintWriter} -import scalan.Scalan import scalan.core.ScalaNameUtil +import sigma.compiler.Scalan import sigma.util.{FileUtil, ProcessUtil, StringUtil} import scala.annotation.unused diff --git a/sc/jvm/src/test/scala/sigmastate/InterpreterReflectionGeneratorTests.scala b/sc/jvm/src/test/scala/sigmastate/InterpreterReflectionGeneratorTests.scala index 5d81e0d19a..2a65dfedf5 100644 --- a/sc/jvm/src/test/scala/sigmastate/InterpreterReflectionGeneratorTests.scala +++ b/sc/jvm/src/test/scala/sigmastate/InterpreterReflectionGeneratorTests.scala @@ -2,7 +2,7 @@ package sigmastate import org.scalatest.matchers.should.Matchers import org.scalatest.propspec.AnyPropSpec -import scalan.TypeDescs +import sigma.compiler.{Scalan, TypeDescs} import sigma.reflection.ReflectionData.registerClassEntry import sigma.reflection.SRConstructor @@ -37,7 +37,7 @@ class InterpreterReflectionGeneratorTests extends AnyPropSpec with Matchers { } property("inner class") { - val ctx = null.asInstanceOf[scalan.Scalan] // ok! type level only + val ctx = null.asInstanceOf[Scalan] // ok! type level only val clazz = classOf[ctx.Coll.CollElem[_, _]] registerClassEntry(clazz, constructors = Array( diff --git a/sc/jvm/src/test/scala/sigmastate/ReflectionGenerator.scala b/sc/jvm/src/test/scala/sigmastate/ReflectionGenerator.scala index 1375b48d99..735297d119 100644 --- a/sc/jvm/src/test/scala/sigmastate/ReflectionGenerator.scala +++ b/sc/jvm/src/test/scala/sigmastate/ReflectionGenerator.scala @@ -1,6 +1,6 @@ package sigmastate -import scalan.{Base, TypeDescs} +import sigma.compiler.{Base, TypeDescs} import sigma.reflection._ import scala.annotation.unused import scala.collection.mutable diff --git a/sc/shared/src/main/scala/scalan/Base.scala b/sc/shared/src/main/scala/sigma/compiler/Base.scala similarity index 98% rename from sc/shared/src/main/scala/scalan/Base.scala rename to sc/shared/src/main/scala/sigma/compiler/Base.scala index cc29af45b9..b6e81f2a6f 100644 --- a/sc/shared/src/main/scala/scalan/Base.scala +++ b/sc/shared/src/main/scala/sigma/compiler/Base.scala @@ -1,14 +1,15 @@ -package scalan +package sigma.compiler import debox.{cfor, Buffer => DBuffer} -import sigma.data.{AVHashMap, Nullable, RType} +import scalan.MutableLazy import sigma.data.OverloadHack.Overloaded1 -import sigma.util.StringUtil +import sigma.data.{AVHashMap, Nullable, RType} import sigma.reflection.RConstructor +import sigma.util.StringUtil import java.util.Arrays -import scala.annotation.{implicitNotFound, unused} import scala.annotation.unchecked.uncheckedVariance +import scala.annotation.{implicitNotFound, unused} import scala.collection.compat.immutable.ArraySeq import scala.collection.mutable import scala.language.implicitConversions @@ -51,7 +52,7 @@ abstract class Base { scalan: Scalan => /** Base class for all IR nodes/operations/definitions. */ abstract class Node extends Product { - private[scalan] var _nodeId: Int = freshId + private[compiler] var _nodeId: Int = freshId /** Unique id of the graph node assigned for each new instance using * `freshId` generator. @@ -365,8 +366,8 @@ abstract class Base { scalan: Scalan => /** Most of the references are initialized when created. * These methods are used in core to assign new value for the reference.*/ - private[scalan] def assignDef[B >: T](d: Def[B]): Unit - private[scalan] def assignDefFrom[B >: T](ref: Ref[B]): Unit + private[compiler] def assignDef[B >: T](d: Def[B]): Unit + private[compiler] def assignDefFrom[B >: T](ref: Ref[B]): Unit /** Whether the underlying node is Placeholder. */ @inline final def isPlaceholder: Boolean = node.isInstanceOf[Placeholder[_]] @@ -550,7 +551,7 @@ abstract class Base { scalan: Scalan => } /** Prepend owner parameter depending on its kind. */ - private[scalan] def addOwnerParameter(ownerType: OwnerKind, params: Seq[Any]): Seq[AnyRef] = { + private[compiler] def addOwnerParameter(ownerType: OwnerKind, params: Seq[Any]): Seq[AnyRef] = { val finalParams = (ownerType match { case EntityObjectOwner(obj) => obj +: params case ScalanOwner => scalan +: params @@ -601,7 +602,7 @@ abstract class Base { scalan: Scalan => override def elem: Elem[T @uncheckedVariance] = _node.resultType override def node: Def[T] = _node - private[scalan] def assignDefInternal[B >: T](d: Def[B]): Unit = { + private[compiler] def assignDefInternal[B >: T](d: Def[B]): Unit = { assert(_node.isInstanceOf[Placeholder[_]]) assert(_node.nodeId > 0) val tab = _symbolTable @@ -612,12 +613,12 @@ abstract class Base { scalan: Scalan => _node = d.asInstanceOf[Def[T]] } - private[scalan] def assignDef[B >: T](d: Def[B]): Unit = { + private[compiler] def assignDef[B >: T](d: Def[B]): Unit = { assignDefInternal(d) updateSymbolTable(this, d) } - private[scalan] def assignDefFrom[B >: T](sym: Ref[B]): Unit = { + private[compiler] def assignDefFrom[B >: T](sym: Ref[B]): Unit = { assignDefInternal(sym.node) } @@ -670,7 +671,7 @@ abstract class Base { scalan: Scalan => } /** Should be invoked to reset IR global node counter. */ - @inline final private[scalan] def resetIdCounter() = { currId = 0 } + @inline final private[compiler] def resetIdCounter() = { currId = 0 } /** Create or find symbol (node Ref) which refers to the given node in the table of all created symbols. * The d.nodeId is the index in the _symbolTable which is DBuffer (backed by Array) @@ -825,7 +826,7 @@ abstract class Base { scalan: Scalan => * @tparam T * @return The symbol of the graph which is semantically(up to rewrites) equivalent to d */ - protected[scalan] def toExp[T](d: Def[T], newSym: => Ref[T]): Ref[T] = { + protected[compiler] def toExp[T](d: Def[T], newSym: => Ref[T]): Ref[T] = { var res = findOrCreateDefinition(d, newSym) var currSym = res var currDef = d diff --git a/sc/shared/src/main/scala/scalan/DefRewriting.scala b/sc/shared/src/main/scala/sigma/compiler/DefRewriting.scala similarity index 99% rename from sc/shared/src/main/scala/scalan/DefRewriting.scala rename to sc/shared/src/main/scala/sigma/compiler/DefRewriting.scala index 114fb1b0e6..38930d0307 100644 --- a/sc/shared/src/main/scala/scalan/DefRewriting.scala +++ b/sc/shared/src/main/scala/sigma/compiler/DefRewriting.scala @@ -1,5 +1,6 @@ -package scalan +package sigma.compiler +import scalan.DelayInvokeException import sigma.data.ExactNumeric trait DefRewriting { scalan: Scalan => diff --git a/sc/shared/src/main/scala/scalan/Entities.scala b/sc/shared/src/main/scala/sigma/compiler/Entities.scala similarity index 99% rename from sc/shared/src/main/scala/scalan/Entities.scala rename to sc/shared/src/main/scala/sigma/compiler/Entities.scala index 8a32dcde10..2cce7fe7d7 100644 --- a/sc/shared/src/main/scala/scalan/Entities.scala +++ b/sc/shared/src/main/scala/sigma/compiler/Entities.scala @@ -1,4 +1,4 @@ -package scalan +package sigma.compiler /** A slice in the Scalan cake with base classes for various descriptors. */ trait Entities extends TypeDescs { self: Scalan => diff --git a/sc/shared/src/main/scala/scalan/Exceptions.scala b/sc/shared/src/main/scala/sigma/compiler/Exceptions.scala similarity index 100% rename from sc/shared/src/main/scala/scalan/Exceptions.scala rename to sc/shared/src/main/scala/sigma/compiler/Exceptions.scala diff --git a/sc/shared/src/main/scala/scalan/GraphIRReflection.scala b/sc/shared/src/main/scala/sigma/compiler/GraphIRReflection.scala similarity index 99% rename from sc/shared/src/main/scala/scalan/GraphIRReflection.scala rename to sc/shared/src/main/scala/sigma/compiler/GraphIRReflection.scala index 86244fb675..054cfed9b7 100644 --- a/sc/shared/src/main/scala/scalan/GraphIRReflection.scala +++ b/sc/shared/src/main/scala/sigma/compiler/GraphIRReflection.scala @@ -1,11 +1,10 @@ -package scalan +package sigma.compiler -import scalan.primitives.Thunks +import sigma.compiler.primitives.Thunks +import sigma.{Colls, SigmaDsl} +import sigma.data.RType import sigma.reflection.ReflectionData.registerClassEntry import sigma.reflection.{ReflectionData, mkConstructor, mkMethod} -import sigma.Colls -import sigma.SigmaDsl -import sigma.data.RType import special.wrappers.{OptionWrapSpec, RTypeWrapSpec} import wrappers.scalan.WRTypes @@ -23,7 +22,7 @@ object GraphIRReflection { val reflection = ReflectionData { val clazz = classOf[wrappers.scala.WOptions#WOption[_]] - val ctx = null.asInstanceOf[scalan.Scalan] // ok! type level only + val ctx = null.asInstanceOf[Scalan] // ok! type level only registerClassEntry(clazz, methods = Map( mkMethod(clazz, "filter", Array[Class[_]](classOf[Base#Ref[_]])) { (obj, args) => diff --git a/sc/shared/src/main/scala/scalan/MethodCalls.scala b/sc/shared/src/main/scala/sigma/compiler/MethodCalls.scala similarity index 97% rename from sc/shared/src/main/scala/scalan/MethodCalls.scala rename to sc/shared/src/main/scala/sigma/compiler/MethodCalls.scala index 14212df632..4a0a189edd 100644 --- a/sc/shared/src/main/scala/scalan/MethodCalls.scala +++ b/sc/shared/src/main/scala/sigma/compiler/MethodCalls.scala @@ -1,12 +1,12 @@ -package scalan +package sigma.compiler -import scala.annotation.{tailrec, unused} -import scala.reflect.ClassTag -import debox.{Buffer => DBuffer} -import debox.cfor +import debox.{cfor, Buffer => DBuffer} +import scalan.DelayInvokeException import sigma.reflection.RMethod import sigma.util.CollectionUtil.TraversableOps +import scala.annotation.{tailrec, unused} + trait MethodCalls extends Base { self: Scalan => def delayInvoke = throw new DelayInvokeException @@ -116,7 +116,7 @@ trait MethodCalls extends Base { self: Scalan => def rewriteNonInvokableMethodCall(@unused mc: MethodCall): Ref[_] = null /** Generic helper to call the given method on the given receiver node. */ - private[scalan] def invokeMethod[A](receiver: Sym, m: RMethod, args: Array[AnyRef], + private[compiler] def invokeMethod[A](receiver: Sym, m: RMethod, args: Array[AnyRef], onInvokeSuccess: Any => A, onInvokeException: Throwable => A, onInvokeImpossible: => A): A = { diff --git a/sc/shared/src/main/scala/scalan/ModuleInfo.scala b/sc/shared/src/main/scala/sigma/compiler/ModuleInfo.scala similarity index 95% rename from sc/shared/src/main/scala/scalan/ModuleInfo.scala rename to sc/shared/src/main/scala/sigma/compiler/ModuleInfo.scala index 86fce48ce6..8c2030b1c7 100644 --- a/sc/shared/src/main/scala/scalan/ModuleInfo.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ModuleInfo.scala @@ -1,4 +1,4 @@ -package scalan +package sigma.compiler import scalan.meta.SSymName diff --git a/sc/shared/src/main/scala/scalan/Modules.scala b/sc/shared/src/main/scala/sigma/compiler/Modules.scala similarity index 95% rename from sc/shared/src/main/scala/scalan/Modules.scala rename to sc/shared/src/main/scala/sigma/compiler/Modules.scala index 989f2c524c..94cbaf9816 100644 --- a/sc/shared/src/main/scala/scalan/Modules.scala +++ b/sc/shared/src/main/scala/sigma/compiler/Modules.scala @@ -1,4 +1,4 @@ -package scalan +package sigma.compiler trait Modules extends Base { self: Scalan => diff --git a/sc/shared/src/main/scala/scalan/MutableLazy.scala b/sc/shared/src/main/scala/sigma/compiler/MutableLazy.scala similarity index 100% rename from sc/shared/src/main/scala/scalan/MutableLazy.scala rename to sc/shared/src/main/scala/sigma/compiler/MutableLazy.scala diff --git a/sc/shared/src/main/scala/scalan/Scalan.scala b/sc/shared/src/main/scala/sigma/compiler/Scalan.scala similarity index 95% rename from sc/shared/src/main/scala/scalan/Scalan.scala rename to sc/shared/src/main/scala/sigma/compiler/Scalan.scala index b6e9ae2efd..76fee8c7f1 100644 --- a/sc/shared/src/main/scala/scalan/Scalan.scala +++ b/sc/shared/src/main/scala/sigma/compiler/Scalan.scala @@ -1,10 +1,11 @@ -package scalan +package sigma.compiler -import scalan.primitives._ -import scalan.staged.Transforming -import sigma.{CollsModule, SigmaDslModule} +import scalan._ +import sigma.compiler.primitives.{Equal, Functions, IfThenElse, LogicalOps, NumericOps, OrderingOps, Thunks, Tuples, UnBinOps, UniversalOps} +import sigma.compiler.staged.Transforming import sigma.data.{Nullable, RType} import sigma.util.MemoizedFunc +import sigma.{CollsModule, SigmaDslModule} import special.wrappers.WrappersModule /** Aggregate cake with all inter-dependent modules assembled together. @@ -42,9 +43,10 @@ trait Scalan with sigma.wrappers.WrappersModule with SigmaDslModule { + import Coll._ + import CollBuilder._ import WOption._ import WRType._ - import Coll._; import CollBuilder._; import WSpecialPredef._ type LazyRep[T] = MutableLazy[Ref[T]] diff --git a/sc/shared/src/main/scala/scalan/TypeDescs.scala b/sc/shared/src/main/scala/sigma/compiler/TypeDescs.scala similarity index 98% rename from sc/shared/src/main/scala/scalan/TypeDescs.scala rename to sc/shared/src/main/scala/sigma/compiler/TypeDescs.scala index fdef77a108..875c3f7b9a 100644 --- a/sc/shared/src/main/scala/scalan/TypeDescs.scala +++ b/sc/shared/src/main/scala/sigma/compiler/TypeDescs.scala @@ -1,10 +1,5 @@ -package scalan +package sigma.compiler -import scala.language.implicitConversions -import scala.annotation.implicitNotFound -import scala.collection.immutable.ListMap - -import scala.collection.mutable import debox.cfor import scalan.core.{Contravariant, Covariant, Variance} import sigma.data.{AVHashMap, Lazy, Nullable, RType} @@ -12,6 +7,11 @@ import sigma.reflection.{RClass, RConstructor, RMethod} import sigma.util.CollectionUtil import special.wrappers.WrapSpec +import scala.annotation.implicitNotFound +import scala.collection.immutable.ListMap +import scala.collection.mutable +import scala.language.implicitConversions + abstract class TypeDescs extends Base { self: Scalan => /** Helper type case method. */ @@ -267,7 +267,7 @@ abstract class TypeDescs extends Base { self: Scalan => e.invokeUnlifted(mc, dataEnv) /** Get first (and the only) constructor of the `clazz`. */ - private[scalan] final def getConstructor(clazz: RClass[_]): RConstructor[_] = { + private[compiler] final def getConstructor(clazz: RClass[_]): RConstructor[_] = { val constructors = clazz.getConstructors() if (constructors.length != 1) !!!(s"Element class $clazz has ${constructors.length} constructors, 1 expected") @@ -297,7 +297,7 @@ abstract class TypeDescs extends Base { self: Scalan => protected val elemCache = AVHashMap[RClass[_], ElemCacheEntry](1000) - private[scalan] final def cachedElem0(clazz: RClass[_], optConstructor: Nullable[RConstructor[_]], args: Seq[AnyRef]): Elem[_] = { + private[compiler] final def cachedElem0(clazz: RClass[_], optConstructor: Nullable[RConstructor[_]], args: Seq[AnyRef]): Elem[_] = { val entry = elemCache.get(clazz) match { case Nullable(entry) => entry case _ => diff --git a/sc/shared/src/main/scala/scalan/core/Variance.scala b/sc/shared/src/main/scala/sigma/compiler/core/Variance.scala similarity index 100% rename from sc/shared/src/main/scala/scalan/core/Variance.scala rename to sc/shared/src/main/scala/sigma/compiler/core/Variance.scala diff --git a/sc/shared/src/main/scala/scalan/meta/SSymName.scala b/sc/shared/src/main/scala/sigma/compiler/meta/SSymName.scala similarity index 100% rename from sc/shared/src/main/scala/scalan/meta/SSymName.scala rename to sc/shared/src/main/scala/sigma/compiler/meta/SSymName.scala diff --git a/sc/shared/src/main/scala/scalan/primitives/Equal.scala b/sc/shared/src/main/scala/sigma/compiler/primitives/Equal.scala similarity index 93% rename from sc/shared/src/main/scala/scalan/primitives/Equal.scala rename to sc/shared/src/main/scala/sigma/compiler/primitives/Equal.scala index 4d64e94383..f0aab234b2 100644 --- a/sc/shared/src/main/scala/scalan/primitives/Equal.scala +++ b/sc/shared/src/main/scala/sigma/compiler/primitives/Equal.scala @@ -1,6 +1,6 @@ -package scalan.primitives +package sigma.compiler.primitives -import scalan.{Base, Scalan} +import sigma.compiler.{Base, Scalan} import scala.annotation.unused diff --git a/sc/shared/src/main/scala/scalan/primitives/Functions.scala b/sc/shared/src/main/scala/sigma/compiler/primitives/Functions.scala similarity index 98% rename from sc/shared/src/main/scala/scalan/primitives/Functions.scala rename to sc/shared/src/main/scala/sigma/compiler/primitives/Functions.scala index 9026461777..f572f2b126 100644 --- a/sc/shared/src/main/scala/scalan/primitives/Functions.scala +++ b/sc/shared/src/main/scala/sigma/compiler/primitives/Functions.scala @@ -1,15 +1,14 @@ -package scalan.primitives +package sigma.compiler.primitives -import java.util -import scalan.staged.ProgramGraphs -import scalan.{Base, Scalan} -import debox.{Buffer => DBuffer} - -import scala.language.implicitConversions -import debox.cfor +import debox.{cfor, Buffer => DBuffer} +import sigma.compiler.staged.ProgramGraphs +import sigma.compiler.{Base, Scalan} import sigma.data.{Lazy, Nullable, emptyDBufferOfInt} import sigma.util.GraphUtil +import java.util +import scala.language.implicitConversions + trait Functions extends Base with ProgramGraphs { self: Scalan => implicit class LambdaOps[A,B](f: Ref[A => B]) { diff --git a/sc/shared/src/main/scala/scalan/primitives/IfThenElse.scala b/sc/shared/src/main/scala/sigma/compiler/primitives/IfThenElse.scala similarity index 96% rename from sc/shared/src/main/scala/scalan/primitives/IfThenElse.scala rename to sc/shared/src/main/scala/sigma/compiler/primitives/IfThenElse.scala index 22fd2095d7..57d742b194 100644 --- a/sc/shared/src/main/scala/scalan/primitives/IfThenElse.scala +++ b/sc/shared/src/main/scala/sigma/compiler/primitives/IfThenElse.scala @@ -1,6 +1,6 @@ -package scalan.primitives +package sigma.compiler.primitives -import scalan.{Base, Scalan} +import sigma.compiler.{Base, Scalan} trait IfThenElse extends Base { self: Scalan => diff --git a/sc/shared/src/main/scala/scalan/primitives/LogicalOps.scala b/sc/shared/src/main/scala/sigma/compiler/primitives/LogicalOps.scala similarity index 97% rename from sc/shared/src/main/scala/scalan/primitives/LogicalOps.scala rename to sc/shared/src/main/scala/sigma/compiler/primitives/LogicalOps.scala index e81b546139..16510eb1fa 100644 --- a/sc/shared/src/main/scala/scalan/primitives/LogicalOps.scala +++ b/sc/shared/src/main/scala/sigma/compiler/primitives/LogicalOps.scala @@ -1,6 +1,6 @@ -package scalan.primitives +package sigma.compiler.primitives -import scalan.{Base, Scalan} +import sigma.compiler.{Base, Scalan} /** Slice in Scala cake with definitions of logical operations. */ trait LogicalOps extends Base { self: Scalan => diff --git a/sc/shared/src/main/scala/scalan/primitives/NumericOps.scala b/sc/shared/src/main/scala/sigma/compiler/primitives/NumericOps.scala similarity index 98% rename from sc/shared/src/main/scala/scalan/primitives/NumericOps.scala rename to sc/shared/src/main/scala/sigma/compiler/primitives/NumericOps.scala index 3c3d80e94d..8783df2ce1 100644 --- a/sc/shared/src/main/scala/scalan/primitives/NumericOps.scala +++ b/sc/shared/src/main/scala/sigma/compiler/primitives/NumericOps.scala @@ -1,6 +1,6 @@ -package scalan.primitives +package sigma.compiler.primitives -import scalan.{Base, Scalan} +import sigma.compiler.{Base, Scalan} import sigma.data.{ExactIntegral, ExactNumeric} /** Slice in Scala cake with definitions of numeric operations. */ diff --git a/sc/shared/src/main/scala/scalan/primitives/OrderingOps.scala b/sc/shared/src/main/scala/sigma/compiler/primitives/OrderingOps.scala similarity index 97% rename from sc/shared/src/main/scala/scalan/primitives/OrderingOps.scala rename to sc/shared/src/main/scala/sigma/compiler/primitives/OrderingOps.scala index 8e6f5e0134..d125787d07 100644 --- a/sc/shared/src/main/scala/scalan/primitives/OrderingOps.scala +++ b/sc/shared/src/main/scala/sigma/compiler/primitives/OrderingOps.scala @@ -1,6 +1,6 @@ -package scalan.primitives +package sigma.compiler.primitives -import scalan.{Base, Scalan} +import sigma.compiler.{Base, Scalan} import sigma.data.ExactOrdering import scala.language.implicitConversions diff --git a/sc/shared/src/main/scala/scalan/primitives/Thunks.scala b/sc/shared/src/main/scala/sigma/compiler/primitives/Thunks.scala similarity index 99% rename from sc/shared/src/main/scala/scalan/primitives/Thunks.scala rename to sc/shared/src/main/scala/sigma/compiler/primitives/Thunks.scala index f9f843664d..24b9e97708 100644 --- a/sc/shared/src/main/scala/scalan/primitives/Thunks.scala +++ b/sc/shared/src/main/scala/sigma/compiler/primitives/Thunks.scala @@ -1,15 +1,14 @@ -package scalan.primitives +package sigma.compiler.primitives -import scala.language.{existentials, implicitConversions} -import scalan._ -import debox.{Buffer => DBuffer, Set => DSet} -import debox.cfor +import debox.{cfor, Buffer => DBuffer, Set => DSet} import scalan.core.Covariant +import sigma.compiler.Scalan import sigma.data.{AVHashMap, DFunc, Lazy, Nullable, RType} import sigma.reflection.RClass import sigma.util.GraphUtil import scala.collection.Seq +import scala.language.{existentials, implicitConversions} /** Slice in the [[Scalan]] cake with definitions of Thunk operations. * See https://en.wikipedia.org/wiki/Thunk. diff --git a/sc/shared/src/main/scala/scalan/primitives/Tuples.scala b/sc/shared/src/main/scala/sigma/compiler/primitives/Tuples.scala similarity index 96% rename from sc/shared/src/main/scala/scalan/primitives/Tuples.scala rename to sc/shared/src/main/scala/sigma/compiler/primitives/Tuples.scala index fd201b9574..ae30569c29 100644 --- a/sc/shared/src/main/scala/scalan/primitives/Tuples.scala +++ b/sc/shared/src/main/scala/sigma/compiler/primitives/Tuples.scala @@ -2,11 +2,12 @@ * Author: Alexander Slesarenko * Date: 7/25/12 */ -package scalan.primitives +package sigma.compiler.primitives + +import sigma.compiler.{Base, Scalan} +import sigma.data.AVHashMap -import scalan.{Base, Scalan} import scala.language.implicitConversions -import sigma.data.{AVHashMap} trait Tuples extends Base { self: Scalan => object Pair { diff --git a/sc/shared/src/main/scala/scalan/primitives/UnBinOps.scala b/sc/shared/src/main/scala/sigma/compiler/primitives/UnBinOps.scala similarity index 97% rename from sc/shared/src/main/scala/scalan/primitives/UnBinOps.scala rename to sc/shared/src/main/scala/sigma/compiler/primitives/UnBinOps.scala index 749556bf0e..701239488d 100644 --- a/sc/shared/src/main/scala/scalan/primitives/UnBinOps.scala +++ b/sc/shared/src/main/scala/sigma/compiler/primitives/UnBinOps.scala @@ -1,6 +1,6 @@ -package scalan.primitives +package sigma.compiler.primitives -import scalan.{Scalan, Base} +import sigma.compiler.{Base, Scalan} trait UnBinOps extends Base { self: Scalan => diff --git a/sc/shared/src/main/scala/scalan/primitives/UniversalOps.scala b/sc/shared/src/main/scala/sigma/compiler/primitives/UniversalOps.scala similarity index 98% rename from sc/shared/src/main/scala/scalan/primitives/UniversalOps.scala rename to sc/shared/src/main/scala/sigma/compiler/primitives/UniversalOps.scala index eaca5821ce..c6dd96f03b 100644 --- a/sc/shared/src/main/scala/scalan/primitives/UniversalOps.scala +++ b/sc/shared/src/main/scala/sigma/compiler/primitives/UniversalOps.scala @@ -1,6 +1,6 @@ -package scalan.primitives +package sigma.compiler.primitives -import scalan.{Base, Scalan} +import sigma.compiler.{Base, Scalan} trait UniversalOps extends Base { scalan: Scalan => case class HashCode[A]() extends UnOp[A, Int]("hashCode") { diff --git a/sc/shared/src/main/scala/scalan/staged/AstGraphs.scala b/sc/shared/src/main/scala/sigma/compiler/staged/AstGraphs.scala similarity index 98% rename from sc/shared/src/main/scala/scalan/staged/AstGraphs.scala rename to sc/shared/src/main/scala/sigma/compiler/staged/AstGraphs.scala index 7ad5c24f17..09000db191 100644 --- a/sc/shared/src/main/scala/scalan/staged/AstGraphs.scala +++ b/sc/shared/src/main/scala/sigma/compiler/staged/AstGraphs.scala @@ -1,11 +1,11 @@ -package scalan.staged +package sigma.compiler.staged -import scala.collection._ -import scalan.Scalan -import debox.cfor -import debox.{Buffer => DBuffer, Map => DMap, Set => DSet} +import debox.{cfor, Buffer => DBuffer, Map => DMap, Set => DSet} +import sigma.compiler.Scalan import sigma.data.emptyDBufferOfInt +import scala.collection._ + trait AstGraphs extends Transforming { self: Scalan => diff --git a/sc/shared/src/main/scala/scalan/staged/ProgramGraphs.scala b/sc/shared/src/main/scala/sigma/compiler/staged/ProgramGraphs.scala similarity index 96% rename from sc/shared/src/main/scala/scalan/staged/ProgramGraphs.scala rename to sc/shared/src/main/scala/sigma/compiler/staged/ProgramGraphs.scala index ccb351e7a2..1c8617bc74 100644 --- a/sc/shared/src/main/scala/scalan/staged/ProgramGraphs.scala +++ b/sc/shared/src/main/scala/sigma/compiler/staged/ProgramGraphs.scala @@ -1,10 +1,10 @@ -package scalan.staged +package sigma.compiler.staged -import scalan.Scalan -import debox.{Buffer => DBuffer} -import sigma.util.GraphUtil -import debox.cfor +import debox.{cfor, Buffer => DBuffer} +import sigma.compiler.Scalan import sigma.data.{DFunc, Nullable} +import sigma.util.GraphUtil + import scala.collection.compat.immutable.ArraySeq trait ProgramGraphs extends AstGraphs { self: Scalan => diff --git a/sc/shared/src/main/scala/scalan/staged/Transforming.scala b/sc/shared/src/main/scala/sigma/compiler/staged/Transforming.scala similarity index 98% rename from sc/shared/src/main/scala/scalan/staged/Transforming.scala rename to sc/shared/src/main/scala/sigma/compiler/staged/Transforming.scala index a64b998ff6..90cc2dd350 100644 --- a/sc/shared/src/main/scala/scalan/staged/Transforming.scala +++ b/sc/shared/src/main/scala/sigma/compiler/staged/Transforming.scala @@ -1,13 +1,13 @@ -package scalan.staged +package sigma.compiler.staged -import java.util -import scala.language.existentials -import scalan.Scalan -import debox.{Buffer => DBuffer} -import debox.cfor +import debox.{cfor, Buffer => DBuffer} +import sigma.compiler.Scalan import sigma.data.{Lazy, Nullable} import sigma.reflection.RMethod +import java.util +import scala.language.existentials + trait Transforming { self: Scalan => /** Descriptor of a current compiler pass. diff --git a/sc/shared/src/main/scala/sigmastate/eval/GraphBuilding.scala b/sc/shared/src/main/scala/sigmastate/eval/GraphBuilding.scala index ebfd0c8e90..445edd3594 100644 --- a/sc/shared/src/main/scala/sigmastate/eval/GraphBuilding.scala +++ b/sc/shared/src/main/scala/sigmastate/eval/GraphBuilding.scala @@ -1,7 +1,7 @@ package sigmastate.eval import org.ergoplatform._ -import scalan.{MutableLazy, Scalan} +import scalan.MutableLazy import sigma.{SigmaException, ast} import sigma.ast.TypeCodes.LastConstantCode import sigma.ast.Value.Typed @@ -14,6 +14,7 @@ import sigma.data.{CSigmaDslBuilder, ExactIntegral, ExactNumeric, ExactOrdering, import sigma.util.Extensions.ByteOps import sigmastate.interpreter.Interpreter.ScriptEnv import sigma.ast.{Ident, Select, Val} +import sigma.compiler.Scalan import sigma.exceptions.GraphBuildingException import sigma.serialization.OpCodes diff --git a/sc/shared/src/main/scala/sigmastate/eval/TreeBuilding.scala b/sc/shared/src/main/scala/sigmastate/eval/TreeBuilding.scala index 770e7a408f..4a6bca7d2e 100644 --- a/sc/shared/src/main/scala/sigmastate/eval/TreeBuilding.scala +++ b/sc/shared/src/main/scala/sigmastate/eval/TreeBuilding.scala @@ -3,11 +3,11 @@ package sigmastate.eval import sigma.ast._ import org.ergoplatform._ -import scalan.Scalan import sigma.ast.syntax.ValueOps import sigma.serialization.OpCodes._ import sigma.serialization.ConstantStore import sigma.ast.syntax._ +import sigma.compiler.Scalan import sigma.data.{ProveDHTuple, ProveDlog} import scala.collection.mutable.ArrayBuffer diff --git a/sc/shared/src/main/scala/sigmastate/lang/SigmaCompiler.scala b/sc/shared/src/main/scala/sigmastate/lang/SigmaCompiler.scala index 3e83aa866c..20e1e28471 100644 --- a/sc/shared/src/main/scala/sigmastate/lang/SigmaCompiler.scala +++ b/sc/shared/src/main/scala/sigmastate/lang/SigmaCompiler.scala @@ -4,7 +4,6 @@ import fastparse.Parsed import fastparse.Parsed.Success import sigma.kiama.rewriting.Rewriter.{everywherebu, rewrite, rule} import org.ergoplatform.ErgoAddressEncoder.NetworkPrefix -import scalan.GraphIRReflection import sigma.ast.{Exponentiate, MultiplyGroup, SCollectionMethods, SGlobalMethods, SGroupElementMethods, Value, Xor} import sigmastate.eval.IRContext import sigmastate.interpreter.Interpreter.ScriptEnv @@ -14,6 +13,7 @@ import sigmastate.lang.parsers.ParserException import sigma.ast._ import sigma.ast.syntax.SValue import SCollectionMethods.{ExistsMethod, ForallMethod, MapMethod} +import sigma.compiler.GraphIRReflection import sigmastate.InterpreterReflection /** diff --git a/sc/shared/src/main/scala/special/collection/CollsUnit.scala b/sc/shared/src/main/scala/special/collection/CollsUnit.scala index db9922b82f..a057f40f7a 100644 --- a/sc/shared/src/main/scala/special/collection/CollsUnit.scala +++ b/sc/shared/src/main/scala/special/collection/CollsUnit.scala @@ -1,5 +1,6 @@ package sigma { import scalan._ + import sigma.compiler.{Base, Scalan} /** Staged version of collection interfaces which is used in graph-based IR to represent * methods of Coll and CollBuilder. diff --git a/sc/shared/src/main/scala/special/collection/impl/CollsImpl.scala b/sc/shared/src/main/scala/special/collection/impl/CollsImpl.scala index 382f5fe763..c85621bbbe 100644 --- a/sc/shared/src/main/scala/special/collection/impl/CollsImpl.scala +++ b/sc/shared/src/main/scala/special/collection/impl/CollsImpl.scala @@ -1,10 +1,13 @@ package sigma -import scala.language.{existentials,implicitConversions} +import scala.language.{existentials, implicitConversions} import scalan._ +import sigma.compiler.Scalan + import scala.collection.compat.immutable.ArraySeq package impl { + import sigma.compiler.{Base, GraphIRReflection, ModuleInfo, Scalan} import sigma.data.{Nullable, RType} import sigma.reflection.{RClass, RMethod} @@ -634,7 +637,7 @@ object CollBuilder extends EntityObject("CollBuilder") { } -object CollsModule extends scalan.ModuleInfo("sigma", "Colls") { +object CollsModule extends ModuleInfo("sigma", "Colls") { val reflection = GraphIRReflection } } diff --git a/sc/shared/src/main/scala/special/sigma/SigmaDslUnit.scala b/sc/shared/src/main/scala/special/sigma/SigmaDslUnit.scala index 91add24b4d..6cc97daba6 100644 --- a/sc/shared/src/main/scala/special/sigma/SigmaDslUnit.scala +++ b/sc/shared/src/main/scala/special/sigma/SigmaDslUnit.scala @@ -1,5 +1,6 @@ package sigma { import scalan._ + import sigma.compiler.{Base, Scalan} trait SigmaDsl extends Base { self: Scalan => trait BigInt extends Def[BigInt] { diff --git a/sc/shared/src/main/scala/special/sigma/impl/SigmaDslImpl.scala b/sc/shared/src/main/scala/special/sigma/impl/SigmaDslImpl.scala index a79b006515..760f5094ca 100644 --- a/sc/shared/src/main/scala/special/sigma/impl/SigmaDslImpl.scala +++ b/sc/shared/src/main/scala/special/sigma/impl/SigmaDslImpl.scala @@ -2,10 +2,12 @@ package sigma import scala.language.{existentials, implicitConversions} import scalan._ +import sigma.compiler.Scalan import scala.collection.compat.immutable.ArraySeq package impl { + import sigma.compiler.{Base, GraphIRReflection, ModuleInfo, Scalan} import sigma.data.{Nullable, RType} import sigma.reflection.{RClass, RMethod} @@ -2319,7 +2321,7 @@ object SigmaDslBuilder extends EntityObject("SigmaDslBuilder") { registerEntityObject("SigmaDslBuilder", SigmaDslBuilder) } -object SigmaDslModule extends scalan.ModuleInfo("sigma", "SigmaDsl") { +object SigmaDslModule extends ModuleInfo("sigma", "SigmaDsl") { val reflection = GraphIRReflection } } diff --git a/sc/shared/src/main/scala/special/sigma/wrappers/WrappersModule.scala b/sc/shared/src/main/scala/special/sigma/wrappers/WrappersModule.scala index 50869cc4e1..1250487071 100644 --- a/sc/shared/src/main/scala/special/sigma/wrappers/WrappersModule.scala +++ b/sc/shared/src/main/scala/special/sigma/wrappers/WrappersModule.scala @@ -1,6 +1,6 @@ package sigma.wrappers -import scalan.Scalan +import sigma.compiler.Scalan trait WrappersModule extends special.wrappers.WrappersModule { self: Scalan => } diff --git a/sc/shared/src/main/scala/special/wrappers/WrappersModule.scala b/sc/shared/src/main/scala/special/wrappers/WrappersModule.scala index 745413569a..1a25f6a9d4 100644 --- a/sc/shared/src/main/scala/special/wrappers/WrappersModule.scala +++ b/sc/shared/src/main/scala/special/wrappers/WrappersModule.scala @@ -1,6 +1,6 @@ package special.wrappers -import scalan.Scalan +import sigma.compiler.Scalan import wrappers.scala.WOptionsModule import wrappers.scalan.WRTypesModule import wrappers.special.WSpecialPredefsModule diff --git a/sc/shared/src/main/scala/wrappers/scala/WOptions.scala b/sc/shared/src/main/scala/wrappers/scala/WOptions.scala index 445da52006..830d05233f 100644 --- a/sc/shared/src/main/scala/wrappers/scala/WOptions.scala +++ b/sc/shared/src/main/scala/wrappers/scala/WOptions.scala @@ -1,6 +1,6 @@ package wrappers.scala { import scalan._ - + import sigma.compiler.{Base, Scalan} import special.wrappers.WrappersModule trait WOptions extends Base { self: Scalan => diff --git a/sc/shared/src/main/scala/wrappers/scala/impl/WOptionsImpl.scala b/sc/shared/src/main/scala/wrappers/scala/impl/WOptionsImpl.scala index 62a0e0c10f..b1006c4e9f 100644 --- a/sc/shared/src/main/scala/wrappers/scala/impl/WOptionsImpl.scala +++ b/sc/shared/src/main/scala/wrappers/scala/impl/WOptionsImpl.scala @@ -1,12 +1,15 @@ package wrappers.scala -import scala.language.{existentials,implicitConversions} +import scala.language.{existentials, implicitConversions} import scalan._ +import sigma.compiler.Scalan import special.wrappers.WrappersModule import special.wrappers.OptionWrapSpec + import scala.collection.compat.immutable.ArraySeq package impl { + import sigma.compiler.{Base, GraphIRReflection, ModuleInfo, Scalan} import sigma.data.{Nullable, RType} import sigma.reflection.{RClass, RMethod} @@ -235,7 +238,7 @@ class WOptionCls extends EntityObject("WOption") { registerEntityObject("WOption", WOption) } -object WOptionsModule extends scalan.ModuleInfo("wrappers.scala", "WOptions") { +object WOptionsModule extends ModuleInfo("wrappers.scala", "WOptions") { val reflection = GraphIRReflection } } diff --git a/sc/shared/src/main/scala/wrappers/scalan/WRTypes.scala b/sc/shared/src/main/scala/wrappers/scalan/WRTypes.scala index bc71b8ad26..204fa40957 100644 --- a/sc/shared/src/main/scala/wrappers/scalan/WRTypes.scala +++ b/sc/shared/src/main/scala/wrappers/scalan/WRTypes.scala @@ -1,5 +1,6 @@ package wrappers.scalan { import scalan._ + import sigma.compiler.{Base, Scalan} trait WRTypes extends Base { self: Scalan => diff --git a/sc/shared/src/main/scala/wrappers/scalan/impl/WRTypesImpl.scala b/sc/shared/src/main/scala/wrappers/scalan/impl/WRTypesImpl.scala index c78a2268bf..7868546bb9 100644 --- a/sc/shared/src/main/scala/wrappers/scalan/impl/WRTypesImpl.scala +++ b/sc/shared/src/main/scala/wrappers/scalan/impl/WRTypesImpl.scala @@ -1,7 +1,6 @@ package wrappers.scalan -import scalan.Scalan - +import sigma.compiler.Scalan import scala.language.{existentials, implicitConversions} import sigma.data.RType import special.wrappers.RTypeWrapSpec @@ -9,7 +8,7 @@ import special.wrappers.RTypeWrapSpec import scala.collection.compat.immutable.ArraySeq package impl { - import scalan.{Base, GraphIRReflection, Scalan} + import sigma.compiler.{Base, GraphIRReflection, ModuleInfo, Scalan} import sigma.reflection.{RClass, RMethod} // Abs ----------------------------------- @@ -113,7 +112,7 @@ registerEntityObject("WRType", WRType) } -object WRTypesModule extends scalan.ModuleInfo("wrappers.scalan", "WRTypes") { +object WRTypesModule extends ModuleInfo("wrappers.scalan", "WRTypes") { val reflection = GraphIRReflection } } diff --git a/sc/shared/src/main/scala/wrappers/special/WSpecialPredefs.scala b/sc/shared/src/main/scala/wrappers/special/WSpecialPredefs.scala index d1c1260391..3c71796c47 100644 --- a/sc/shared/src/main/scala/wrappers/special/WSpecialPredefs.scala +++ b/sc/shared/src/main/scala/wrappers/special/WSpecialPredefs.scala @@ -1,5 +1,6 @@ package wrappers.special { import scalan._ + import sigma.compiler.{Base, Scalan} trait WSpecialPredefs extends Base { self: Scalan => trait WSpecialPredef extends Def[WSpecialPredef]; diff --git a/sc/shared/src/main/scala/wrappers/special/impl/WSpecialPredefsImpl.scala b/sc/shared/src/main/scala/wrappers/special/impl/WSpecialPredefsImpl.scala index 697de01802..4bb7a13128 100644 --- a/sc/shared/src/main/scala/wrappers/special/impl/WSpecialPredefsImpl.scala +++ b/sc/shared/src/main/scala/wrappers/special/impl/WSpecialPredefsImpl.scala @@ -1,10 +1,12 @@ package wrappers.special -import scala.language.{existentials,implicitConversions} +import scala.language.{existentials, implicitConversions} import scalan._ +import sigma.compiler.Scalan import special.wrappers.WrappersModule package impl { + import sigma.compiler.{Base, GraphIRReflection, ModuleInfo, Scalan} import sigma.data.Nullable import sigma.reflection.RClass @@ -61,7 +63,7 @@ object WSpecialPredef extends EntityObject("WSpecialPredef") { } -object WSpecialPredefsModule extends scalan.ModuleInfo("wrappers.special", "WSpecialPredefs") { +object WSpecialPredefsModule extends ModuleInfo("wrappers.special", "WSpecialPredefs") { val reflection = GraphIRReflection } } diff --git a/sc/shared/src/test/scala/scalan/BaseLiftableTests.scala b/sc/shared/src/test/scala/scalan/BaseLiftableTests.scala index 3d437a2f1d..120c15dfe6 100644 --- a/sc/shared/src/test/scala/scalan/BaseLiftableTests.scala +++ b/sc/shared/src/test/scala/scalan/BaseLiftableTests.scala @@ -1,5 +1,7 @@ package scalan +import sigma.compiler.Scalan + trait BaseLiftableTests { self: BaseCtxTests => trait LiftableTestKit { scalan: Scalan => diff --git a/sc/shared/src/test/scala/scalan/LibraryTests.scala b/sc/shared/src/test/scala/scalan/LibraryTests.scala index d095a2f20a..a6844070eb 100644 --- a/sc/shared/src/test/scala/scalan/LibraryTests.scala +++ b/sc/shared/src/test/scala/scalan/LibraryTests.scala @@ -1,5 +1,6 @@ package scalan +import sigma.compiler.Scalan import sigma.util.BenchmarkUtil.{measure, measureTime} class Benchmark[T <: Scalan](createContext: => T) { diff --git a/sc/shared/src/test/scala/scalan/TestContexts.scala b/sc/shared/src/test/scala/scalan/TestContexts.scala index a86bf42276..39649b541a 100644 --- a/sc/shared/src/test/scala/scalan/TestContexts.scala +++ b/sc/shared/src/test/scala/scalan/TestContexts.scala @@ -1,5 +1,6 @@ package scalan +import sigma.compiler.{GraphIRReflection, Scalan} import sigma.reflection.RMethod import sigma.{BaseNestedTests, BaseShouldTests, BaseTests, TestUtils} diff --git a/sc/shared/src/test/scala/scalan/TestLibrary.scala b/sc/shared/src/test/scala/scalan/TestLibrary.scala index c3d8a5beb8..f54d2d9073 100644 --- a/sc/shared/src/test/scala/scalan/TestLibrary.scala +++ b/sc/shared/src/test/scala/scalan/TestLibrary.scala @@ -1,5 +1,7 @@ package scalan +import sigma.compiler.{GraphIRReflection, Scalan} + trait TestLibrary extends Scalan { import CollBuilder._ import SigmaDslBuilder._ diff --git a/sc/shared/src/test/scala/sigma/CollsStagingTests.scala b/sc/shared/src/test/scala/sigma/CollsStagingTests.scala index 332c5e300c..f0d74f40e9 100644 --- a/sc/shared/src/test/scala/sigma/CollsStagingTests.scala +++ b/sc/shared/src/test/scala/sigma/CollsStagingTests.scala @@ -3,6 +3,7 @@ package sigma import scala.language.reflectiveCalls import special.wrappers.WrappersTests import scalan._ +import sigma.compiler.Scalan import sigma.data.CollOverArrayBuilder class CollsStagingTests extends WrappersTests { From bd0feb0be824fe408674d32bc63747315f423782 Mon Sep 17 00:00:00 2001 From: Alexander Slesarenko Date: Wed, 15 May 2024 21:05:36 +0100 Subject: [PATCH 069/314] refactor-ir-cake: IRContext moved to sigma.compiler --- .../compiler}/GraphBuilding.scala | 17 ++++++----- .../eval => sigma/compiler}/IRContext.scala | 2 +- .../compiler}/TreeBuilding.scala | 28 +++++++++---------- 3 files changed, 22 insertions(+), 25 deletions(-) rename sc/shared/src/main/scala/{sigmastate/eval => sigma/compiler}/GraphBuilding.scala (99%) rename sc/shared/src/main/scala/{sigmastate/eval => sigma/compiler}/IRContext.scala (94%) rename sc/shared/src/main/scala/{sigmastate/eval => sigma/compiler}/TreeBuilding.scala (99%) diff --git a/sc/shared/src/main/scala/sigmastate/eval/GraphBuilding.scala b/sc/shared/src/main/scala/sigma/compiler/GraphBuilding.scala similarity index 99% rename from sc/shared/src/main/scala/sigmastate/eval/GraphBuilding.scala rename to sc/shared/src/main/scala/sigma/compiler/GraphBuilding.scala index 445edd3594..d800ff03bd 100644 --- a/sc/shared/src/main/scala/sigmastate/eval/GraphBuilding.scala +++ b/sc/shared/src/main/scala/sigma/compiler/GraphBuilding.scala @@ -1,22 +1,21 @@ -package sigmastate.eval +package sigma.compiler import org.ergoplatform._ import scalan.MutableLazy -import sigma.{SigmaException, ast} import sigma.ast.TypeCodes.LastConstantCode import sigma.ast.Value.Typed -import sigma.ast._ import sigma.ast.syntax.{SValue, ValueOps} +import sigma.ast._ import sigma.crypto.EcPointType import sigma.data.ExactIntegral.{ByteIsExactIntegral, IntIsExactIntegral, LongIsExactIntegral, ShortIsExactIntegral} import sigma.data.ExactOrdering.{ByteIsExactOrdering, IntIsExactOrdering, LongIsExactOrdering, ShortIsExactOrdering} import sigma.data.{CSigmaDslBuilder, ExactIntegral, ExactNumeric, ExactOrdering, Lazy, Nullable} -import sigma.util.Extensions.ByteOps -import sigmastate.interpreter.Interpreter.ScriptEnv -import sigma.ast.{Ident, Select, Val} -import sigma.compiler.Scalan import sigma.exceptions.GraphBuildingException import sigma.serialization.OpCodes +import sigma.util.Extensions.ByteOps +import sigma.{SigmaException, ast} +import sigmastate.eval.IRContext +import sigmastate.interpreter.Interpreter.ScriptEnv import scala.collection.mutable.ArrayBuffer @@ -43,8 +42,8 @@ trait GraphBuilding extends Scalan { IR: IRContext => import SigmaProp._ import WOption._ - /** Should be specified in the final cake */ - val builder: SigmaBuilder + /** Builder used to create ErgoTree nodes. */ + val builder = TransformingSigmaBuilder import builder._ val okMeasureOperationTime: Boolean = false diff --git a/sc/shared/src/main/scala/sigmastate/eval/IRContext.scala b/sc/shared/src/main/scala/sigma/compiler/IRContext.scala similarity index 94% rename from sc/shared/src/main/scala/sigmastate/eval/IRContext.scala rename to sc/shared/src/main/scala/sigma/compiler/IRContext.scala index 597711d458..5365c75e5e 100644 --- a/sc/shared/src/main/scala/sigmastate/eval/IRContext.scala +++ b/sc/shared/src/main/scala/sigma/compiler/IRContext.scala @@ -1,6 +1,7 @@ package sigmastate.eval import sigma.ast.TransformingSigmaBuilder +import sigma.compiler.{GraphBuilding, TreeBuilding} /** Main interface of graph IR context which contain both GraphBuilding and TreeBuilding * methods. @@ -11,7 +12,6 @@ import sigma.ast.TransformingSigmaBuilder * @see CompiletimeIRContext */ trait IRContext extends TreeBuilding with GraphBuilding { - override val builder = TransformingSigmaBuilder /** Pass configuration which is used to turn-off constant propagation. * USED IN TESTS ONLY. diff --git a/sc/shared/src/main/scala/sigmastate/eval/TreeBuilding.scala b/sc/shared/src/main/scala/sigma/compiler/TreeBuilding.scala similarity index 99% rename from sc/shared/src/main/scala/sigmastate/eval/TreeBuilding.scala rename to sc/shared/src/main/scala/sigma/compiler/TreeBuilding.scala index 4a6bca7d2e..b5c7be20ff 100644 --- a/sc/shared/src/main/scala/sigmastate/eval/TreeBuilding.scala +++ b/sc/shared/src/main/scala/sigma/compiler/TreeBuilding.scala @@ -1,17 +1,15 @@ -package sigmastate.eval +package sigma.compiler - -import sigma.ast._ import org.ergoplatform._ -import sigma.ast.syntax.ValueOps -import sigma.serialization.OpCodes._ -import sigma.serialization.ConstantStore -import sigma.ast.syntax._ -import sigma.compiler.Scalan +import sigma.ast._ +import sigma.ast.syntax.{ValueOps, _} import sigma.data.{ProveDHTuple, ProveDlog} +import sigma.serialization.ConstantStore +import sigma.serialization.OpCodes._ +import sigma.serialization.ValueCodes.OpCode +import sigmastate.eval.IRContext import scala.collection.mutable.ArrayBuffer -import sigma.serialization.ValueCodes.OpCode /** Implementation of IR-graph to ErgoTree expression translation. * This, in a sense, is inverse to [[GraphBuilding]], however roundtrip identity is not @@ -26,16 +24,16 @@ import sigma.serialization.ValueCodes.OpCode * @see buildTree method * */ trait TreeBuilding extends Scalan { IR: IRContext => - import Liftables._ - import Context._ - import SigmaProp._ - import Coll._ + import BigInt._ import Box._ + import Coll._ import CollBuilder._ + import Context._ + import GroupElement._ + import Liftables._ import SigmaDslBuilder._ - import BigInt._ + import SigmaProp._ import WOption._ - import GroupElement._ /** Convenience synonyms for easier pattern matching. */ private val ContextM = ContextMethods From f4bd542714f1443422f77077ccefd582456d2c37 Mon Sep 17 00:00:00 2001 From: Alexander Slesarenko Date: Wed, 15 May 2024 21:39:46 +0100 Subject: [PATCH 070/314] refactor-ir-cake: everything is assembled in Scalan cake --- .../sigmastate/lang/js/SigmaCompiler.scala | 2 +- .../org/ergoplatform/ErgoScriptPredef.scala | 6 ++--- .../org/ergoplatform/dsl/ContractSpec.scala | 4 +-- .../ergoplatform/dsl/ErgoContractSpec.scala | 4 +-- .../scala/sigma/compiler/GraphBuilding.scala | 5 ++-- .../main/scala/sigma/compiler/IRContext.scala | 25 +++---------------- .../main/scala/sigma/compiler/Scalan.scala | 16 +++++++++++- .../scala/sigma/compiler/TreeBuilding.scala | 3 +-- .../scala/sigmastate/lang/SigmaCompiler.scala | 11 ++++---- .../lang/SigmaTemplateCompiler.scala | 2 +- .../ergoplatform/dsl/TestContractSpec.scala | 5 ++-- .../src/test/scala/scalan/TestLibrary.scala | 2 -- .../scala/sigma/SigmaDslStaginTests.scala | 3 ++- .../test/scala/sigma/SigmaDslTesting.scala | 19 +++++++------- .../scala/sigmastate/CompilerTestsBase.scala | 8 +++--- .../ScriptVersionSwitchSpecification.scala | 5 ++-- .../sigmastate/eval/ErgoScriptTestkit.scala | 5 ++-- .../eval/ErgoTreeBuildingTest.scala | 3 ++- .../helpers/CompilerTestingCommons.scala | 11 ++++---- .../ErgoTreeSerializerSpecification.scala | 4 +-- .../utxo/AVLTreeScriptsSpecification.scala | 4 +-- .../UsingContextPropertiesSpecification.scala | 4 +-- .../BlockchainSimulationTestingCommons.scala | 5 ++-- .../sigmastate/utxo/examples/IcoExample.scala | 3 ++- .../utxo/examples/LetsSpecification.scala | 4 +-- 25 files changed, 81 insertions(+), 82 deletions(-) diff --git a/sc/js/src/main/scala/sigmastate/lang/js/SigmaCompiler.scala b/sc/js/src/main/scala/sigmastate/lang/js/SigmaCompiler.scala index 8fe26a30b0..3dfd285e93 100644 --- a/sc/js/src/main/scala/sigmastate/lang/js/SigmaCompiler.scala +++ b/sc/js/src/main/scala/sigmastate/lang/js/SigmaCompiler.scala @@ -9,7 +9,7 @@ import scala.scalajs.js import scala.scalajs.js.annotation.JSExportTopLevel import sigma.js.Value import sigma.ast.ErgoTree.HeaderType -import sigmastate.eval.CompiletimeIRContext +import sigma.compiler.CompiletimeIRContext import sigma.ast.syntax.ValueOps diff --git a/sc/shared/src/main/scala/org/ergoplatform/ErgoScriptPredef.scala b/sc/shared/src/main/scala/org/ergoplatform/ErgoScriptPredef.scala index faded6e28c..a2bc3362d7 100644 --- a/sc/shared/src/main/scala/org/ergoplatform/ErgoScriptPredef.scala +++ b/sc/shared/src/main/scala/org/ergoplatform/ErgoScriptPredef.scala @@ -1,18 +1,18 @@ package org.ergoplatform import sigmastate.lang.SigmaCompiler -import sigmastate.eval.IRContext import org.ergoplatform.ErgoAddressEncoder.NetworkPrefix import sigma.ast.SType import sigma.ast.syntax.SigmaPropValue import sigma.ast.Value import sigma.ast.syntax.ValueOps +import sigma.compiler.Scalan object ErgoScriptPredef { import sigmastate.interpreter.Interpreter._ /** Compiles the given ErgoScript `code` into ErgoTree expression. */ - def compileWithCosting(env: ScriptEnv, code: String, networkPrefix: NetworkPrefix)(implicit IR: IRContext): Value[SType] = { + def compileWithCosting(env: ScriptEnv, code: String, networkPrefix: NetworkPrefix)(implicit IR: Scalan): Value[SType] = { val compiler = SigmaCompiler(networkPrefix) val res = compiler.compile(env, code) res.buildTree @@ -30,7 +30,7 @@ object ErgoScriptPredef { tokenId: Array[Byte], thresholdAmount: Long, networkPrefix: NetworkPrefix) - (implicit IR: IRContext): SigmaPropValue = { + (implicit IR: Scalan): SigmaPropValue = { val env = emptyEnv + ("tokenId" -> tokenId, "thresholdAmount" -> thresholdAmount) val res = compileWithCosting(env, diff --git a/sc/shared/src/main/scala/org/ergoplatform/dsl/ContractSpec.scala b/sc/shared/src/main/scala/org/ergoplatform/dsl/ContractSpec.scala index 484b9e2728..539da9d79b 100644 --- a/sc/shared/src/main/scala/org/ergoplatform/dsl/ContractSpec.scala +++ b/sc/shared/src/main/scala/org/ergoplatform/dsl/ContractSpec.scala @@ -5,11 +5,11 @@ import sigma.interpreter.{CostedProverResult, ProverResult} import sigma.data.{CSigmaDslBuilder, RType} import org.ergoplatform.{ErgoBox, ErgoLikeContext} import sigma.{Coll, SigmaDslBuilder, SigmaProp} -import sigmastate.eval.IRContext import scala.util.Try import org.ergoplatform.dsl.ContractSyntax.{ErgoScript, Proposition, Token} import sigma.ast.{ErgoTree, EvaluatedValue, SType} +import sigma.compiler.Scalan import scala.language.implicitConversions @@ -19,7 +19,7 @@ trait ContractSpec { implicit def Coll[T](items: Array[T])(implicit cT: RType[T]): Coll[T] = Colls.fromArray(items) - val IR: IRContext + val IR: Scalan trait PropositionSpec { def name: String diff --git a/sc/shared/src/main/scala/org/ergoplatform/dsl/ErgoContractSpec.scala b/sc/shared/src/main/scala/org/ergoplatform/dsl/ErgoContractSpec.scala index 2c31304b70..6a91c6f60a 100644 --- a/sc/shared/src/main/scala/org/ergoplatform/dsl/ErgoContractSpec.scala +++ b/sc/shared/src/main/scala/org/ergoplatform/dsl/ErgoContractSpec.scala @@ -1,12 +1,12 @@ package org.ergoplatform.dsl import sigma.Coll -import sigmastate.eval.IRContext import org.ergoplatform.dsl.ContractSyntax.{ErgoScript, Proposition, Token} import org.ergoplatform.ErgoBox.{BoxId, NonMandatoryRegisterId, TokenId} +import sigma.compiler.Scalan import sigma.interpreter.CostedProverResult -class ErgoContractSpec(implicit val IR: IRContext) extends ContractSpec { +class ErgoContractSpec(implicit val IR: Scalan) extends ContractSpec { case class ErgoOutBox(tx: TransactionCandidate, boxIndex: Int, value: Long, propSpec: PropositionSpec) extends OutBox { diff --git a/sc/shared/src/main/scala/sigma/compiler/GraphBuilding.scala b/sc/shared/src/main/scala/sigma/compiler/GraphBuilding.scala index d800ff03bd..784ee0e836 100644 --- a/sc/shared/src/main/scala/sigma/compiler/GraphBuilding.scala +++ b/sc/shared/src/main/scala/sigma/compiler/GraphBuilding.scala @@ -14,7 +14,6 @@ import sigma.exceptions.GraphBuildingException import sigma.serialization.OpCodes import sigma.util.Extensions.ByteOps import sigma.{SigmaException, ast} -import sigmastate.eval.IRContext import sigmastate.interpreter.Interpreter.ScriptEnv import scala.collection.mutable.ArrayBuffer @@ -27,7 +26,7 @@ import scala.collection.mutable.ArrayBuffer * CSE however means the original structure of source code may not be preserved in the * resulting ErgoTree. * */ -trait GraphBuilding extends Scalan { IR: IRContext => +trait GraphBuilding extends Base with DefRewriting { IR: Scalan => import AvlTree._ import BigInt._ import Box._ @@ -59,7 +58,7 @@ trait GraphBuilding extends Scalan { IR: IRContext => * In v5.x this code is taken from CheckTupleType validation rule which is no longer * part of consensus. */ - def checkTupleType[Ctx <: IRContext, T](ctx: Ctx)(e: ctx.Elem[_]): Unit = { + def checkTupleType[Ctx <: Scalan, T](ctx: Ctx)(e: ctx.Elem[_]): Unit = { val condition = e match { case _: ctx.PairElem[_, _] => true case _ => false diff --git a/sc/shared/src/main/scala/sigma/compiler/IRContext.scala b/sc/shared/src/main/scala/sigma/compiler/IRContext.scala index 5365c75e5e..0b958b9ab9 100644 --- a/sc/shared/src/main/scala/sigma/compiler/IRContext.scala +++ b/sc/shared/src/main/scala/sigma/compiler/IRContext.scala @@ -1,25 +1,6 @@ -package sigmastate.eval +package sigma.compiler -import sigma.ast.TransformingSigmaBuilder -import sigma.compiler.{GraphBuilding, TreeBuilding} - -/** Main interface of graph IR context which contain both GraphBuilding and TreeBuilding - * methods. - * It is not used in v5.0 interpreter and thus not part of consensus. - * - * Used in ErgoScript compiler only. - * - * @see CompiletimeIRContext - */ -trait IRContext extends TreeBuilding with GraphBuilding { - - /** Pass configuration which is used to turn-off constant propagation. - * USED IN TESTS ONLY. - * @see `beginPass(noCostPropagationPass)` */ - lazy val noConstPropagationPass = new DefaultPass( - "noCostPropagationPass", - Pass.defaultPassConfig.copy(constantPropagation = false)) -} +trait IRContext extends Scalan /** IR context to be used by script development tools to compile ErgoScript into ErgoTree bytecode. */ -class CompiletimeIRContext extends IRContext +class CompiletimeIRContext extends Scalan diff --git a/sc/shared/src/main/scala/sigma/compiler/Scalan.scala b/sc/shared/src/main/scala/sigma/compiler/Scalan.scala index 76fee8c7f1..8009cd5e36 100644 --- a/sc/shared/src/main/scala/sigma/compiler/Scalan.scala +++ b/sc/shared/src/main/scala/sigma/compiler/Scalan.scala @@ -20,6 +20,11 @@ import special.wrappers.WrappersModule * At the same time cake design pattern allow to `override` many methods and values * in classed derived from `Scalan`, this is significant benefit over * *everything is global* design. + * + * It is not used in v5.0 interpreter and thus not part of consensus. + * Used in ErgoScript compiler only. + * + * @see CompiletimeIRContext */ trait Scalan extends TypeDescs @@ -41,7 +46,9 @@ trait Scalan with WrappersModule with CollsModule with sigma.wrappers.WrappersModule - with SigmaDslModule { + with SigmaDslModule + with TreeBuilding + with GraphBuilding { import Coll._ import CollBuilder._ @@ -49,6 +56,13 @@ trait Scalan import WRType._ import WSpecialPredef._ + /** Pass configuration which is used to turn-off constant propagation. + * USED IN TESTS ONLY. + * @see `beginPass(noCostPropagationPass)` */ + lazy val noConstPropagationPass = new DefaultPass( + "noCostPropagationPass", + Pass.defaultPassConfig.copy(constantPropagation = false)) + type LazyRep[T] = MutableLazy[Ref[T]] private val _liftElemMemo = new MemoizedFunc({ diff --git a/sc/shared/src/main/scala/sigma/compiler/TreeBuilding.scala b/sc/shared/src/main/scala/sigma/compiler/TreeBuilding.scala index b5c7be20ff..f781215901 100644 --- a/sc/shared/src/main/scala/sigma/compiler/TreeBuilding.scala +++ b/sc/shared/src/main/scala/sigma/compiler/TreeBuilding.scala @@ -7,7 +7,6 @@ import sigma.data.{ProveDHTuple, ProveDlog} import sigma.serialization.ConstantStore import sigma.serialization.OpCodes._ import sigma.serialization.ValueCodes.OpCode -import sigmastate.eval.IRContext import scala.collection.mutable.ArrayBuffer @@ -23,7 +22,7 @@ import scala.collection.mutable.ArrayBuffer * * @see buildTree method * */ -trait TreeBuilding extends Scalan { IR: IRContext => +trait TreeBuilding extends Base { IR: Scalan => import BigInt._ import Box._ import Coll._ diff --git a/sc/shared/src/main/scala/sigmastate/lang/SigmaCompiler.scala b/sc/shared/src/main/scala/sigmastate/lang/SigmaCompiler.scala index 20e1e28471..4392e97216 100644 --- a/sc/shared/src/main/scala/sigmastate/lang/SigmaCompiler.scala +++ b/sc/shared/src/main/scala/sigmastate/lang/SigmaCompiler.scala @@ -5,7 +5,6 @@ import fastparse.Parsed.Success import sigma.kiama.rewriting.Rewriter.{everywherebu, rewrite, rule} import org.ergoplatform.ErgoAddressEncoder.NetworkPrefix import sigma.ast.{Exponentiate, MultiplyGroup, SCollectionMethods, SGlobalMethods, SGroupElementMethods, Value, Xor} -import sigmastate.eval.IRContext import sigmastate.interpreter.Interpreter.ScriptEnv import sigma.ast.SigmaPredef.PredefinedFuncRegistry import sigma.ast.MethodCall @@ -13,7 +12,7 @@ import sigmastate.lang.parsers.ParserException import sigma.ast._ import sigma.ast.syntax.SValue import SCollectionMethods.{ExistsMethod, ForallMethod, MapMethod} -import sigma.compiler.GraphIRReflection +import sigma.compiler.{GraphIRReflection, Scalan} import sigmastate.InterpreterReflection /** @@ -38,7 +37,7 @@ case class CompilerSettings( * @param compiledGraph graph obtained by using new [[GraphBuilding]] * @param buildTree ErgoTree expression obtained from graph created by [[GraphBuilding]] */ -case class CompilerResult[Ctx <: IRContext]( +case class CompilerResult[Ctx <: Scalan]( env: ScriptEnv, code: String, compiledGraph: Ctx#Ref[Ctx#Context => Any], @@ -84,14 +83,14 @@ class SigmaCompiler private(settings: CompilerSettings) { } /** Compiles the given ErgoScript source code. */ - def compile(env: ScriptEnv, code: String)(implicit IR: IRContext): CompilerResult[IR.type] = { + def compile(env: ScriptEnv, code: String)(implicit IR: Scalan): CompilerResult[IR.type] = { val typed = typecheck(env, code) val res = compileTyped(env, typed).copy(code = code) res } /** Compiles the given typed expression. */ - def compileTyped(env: ScriptEnv, typedExpr: SValue)(implicit IR: IRContext): CompilerResult[IR.type] = { + def compileTyped(env: ScriptEnv, typedExpr: SValue)(implicit IR: Scalan): CompilerResult[IR.type] = { val placeholdersEnv = env .collect { case (name, t: SType) => name -> t } .zipWithIndex @@ -103,7 +102,7 @@ class SigmaCompiler private(settings: CompilerSettings) { } /** Compiles the given parsed contract source. */ - def compileParsed(env: ScriptEnv, parsedExpr: SValue)(implicit IR: IRContext): CompilerResult[IR.type] = { + def compileParsed(env: ScriptEnv, parsedExpr: SValue)(implicit IR: Scalan): CompilerResult[IR.type] = { val typed = typecheck(env, parsedExpr) compileTyped(env, typed) } diff --git a/sc/shared/src/main/scala/sigmastate/lang/SigmaTemplateCompiler.scala b/sc/shared/src/main/scala/sigmastate/lang/SigmaTemplateCompiler.scala index f77735118c..8c8a84d29e 100644 --- a/sc/shared/src/main/scala/sigmastate/lang/SigmaTemplateCompiler.scala +++ b/sc/shared/src/main/scala/sigmastate/lang/SigmaTemplateCompiler.scala @@ -4,7 +4,7 @@ import fastparse.Parsed import org.ergoplatform.sdk.{ContractTemplate, Parameter} import sigma.ast.SourceContext import sigma.ast.syntax.SValue -import sigmastate.eval.CompiletimeIRContext +import sigma.compiler.CompiletimeIRContext import sigmastate.lang.parsers.ParserException /** Compiler which compiles Ergo contract templates into a [[ContractTemplate]]. */ diff --git a/sc/shared/src/test/scala/org/ergoplatform/dsl/TestContractSpec.scala b/sc/shared/src/test/scala/org/ergoplatform/dsl/TestContractSpec.scala index 26e8b08b14..0c8bb83e56 100644 --- a/sc/shared/src/test/scala/org/ergoplatform/dsl/TestContractSpec.scala +++ b/sc/shared/src/test/scala/org/ergoplatform/dsl/TestContractSpec.scala @@ -4,6 +4,7 @@ import sigmastate.interpreter.Interpreter.ScriptNameProp import scala.collection.mutable import sigma.interpreter.{CostedProverResult, ProverResult} + import scala.collection.mutable.ArrayBuffer import org.ergoplatform.ErgoBox.{NonMandatoryRegisterId, TokenId} import sigma.data.{AvlTreeData, CAnyValue, CSigmaProp, Nullable} @@ -14,14 +15,14 @@ import org.ergoplatform.dsl.ContractSyntax.{ErgoScript, Proposition, Token} import sigma.ast.{ErgoTree, SType} import sigma.ast.EvaluatedValue import sigma.interpreter.ContextExtension -import sigmastate.eval.IRContext import sigmastate.helpers.{CompilerTestingCommons, ContextEnrichingTestProvingInterpreter, ErgoLikeContextTesting, ErgoLikeTestInterpreter} import sigmastate.helpers.TestingHelpers._ import sigma.ast.syntax.ValueOps import sigma.{AnyValue, Evaluation, SigmaProp} import ErgoTree.ZeroHeader +import sigma.compiler.Scalan -case class TestContractSpec(testSuite: CompilerTestingCommons)(implicit val IR: IRContext) extends ContractSpec { +case class TestContractSpec(testSuite: CompilerTestingCommons)(implicit val IR: Scalan) extends ContractSpec { case class TestPropositionSpec(name: String, dslSpec: Proposition, scriptSpec: ErgoScript) extends PropositionSpec { lazy val ergoTree: ErgoTree = { diff --git a/sc/shared/src/test/scala/scalan/TestLibrary.scala b/sc/shared/src/test/scala/scalan/TestLibrary.scala index f54d2d9073..2c4c355cb8 100644 --- a/sc/shared/src/test/scala/scalan/TestLibrary.scala +++ b/sc/shared/src/test/scala/scalan/TestLibrary.scala @@ -6,6 +6,4 @@ trait TestLibrary extends Scalan { import CollBuilder._ import SigmaDslBuilder._ val reflection = (GraphIRReflection) - lazy val colBuilder: Ref[CollBuilder] = variable[CollBuilder] - lazy val sigmaDslBuilder: Ref[SigmaDslBuilder] = variable[SigmaDslBuilder] } diff --git a/sc/shared/src/test/scala/sigma/SigmaDslStaginTests.scala b/sc/shared/src/test/scala/sigma/SigmaDslStaginTests.scala index 91178b2b67..90eefab5e0 100644 --- a/sc/shared/src/test/scala/sigma/SigmaDslStaginTests.scala +++ b/sc/shared/src/test/scala/sigma/SigmaDslStaginTests.scala @@ -2,6 +2,7 @@ package sigma import org.scalatest.BeforeAndAfterAll import scalan.{BaseCtxTests, BaseLiftableTests} +import sigma.compiler.Scalan import sigma.data.TrivialProp import sigma.eval.Extensions.toAnyValue import sigmastate.eval._ @@ -9,7 +10,7 @@ import sigmastate.eval._ import scala.language.reflectiveCalls class SigmaDslStaginTests extends BaseCtxTests with ErgoScriptTestkit with BaseLiftableTests with BeforeAndAfterAll { - class Ctx extends TestContext with IRContext with LiftableTestKit { + class Ctx extends TestContext with Scalan with LiftableTestKit { } test("invokeUnlifted") { diff --git a/sc/shared/src/test/scala/sigma/SigmaDslTesting.scala b/sc/shared/src/test/scala/sigma/SigmaDslTesting.scala index 46222d9fb1..4acb6e0f75 100644 --- a/sc/shared/src/test/scala/sigma/SigmaDslTesting.scala +++ b/sc/shared/src/test/scala/sigma/SigmaDslTesting.scala @@ -25,12 +25,13 @@ import sigma.ast._ import sigma.eval.{CostDetails, EvalSettings, SigmaDsl} import sigmastate.crypto.DLogProtocol.DLogProverInput import sigmastate.crypto.SigmaProtocolPrivateInput -import sigmastate.eval.{CContext, CompiletimeIRContext, IRContext} +import sigmastate.eval.CContext import sigmastate.helpers.TestingHelpers._ import sigmastate.helpers.{CompilerTestingCommons, ErgoLikeContextTesting, ErgoLikeTestInterpreter, SigmaPPrint} import sigmastate.interpreter.Interpreter.{ScriptEnv, VerificationResult} import sigmastate.interpreter._ import sigma.ast.Apply +import sigma.compiler.{CompiletimeIRContext, Scalan} import sigma.eval.Extensions.SigmaBooleanOps import sigma.interpreter.{ContextExtension, ProverResult} import sigma.serialization.ValueSerializer @@ -54,7 +55,7 @@ class SigmaDslTesting extends AnyPropSpec override def contractEnv: ScriptEnv = Map() - def createIR(): IRContext = new TestingIRContext { + def createIR(): Scalan = new TestingIRContext { override val okMeasureOperationTime: Boolean = true } @@ -495,7 +496,7 @@ class SigmaDslTesting extends AnyPropSpec expectedExpr: Option[SValue], printExpectedExpr: Boolean = true, logScript: Boolean = LogScriptDefault - )(implicit IR: IRContext, val tA: RType[A], val tB: RType[B], + )(implicit IR: Scalan, val tA: RType[A], val tB: RType[B], override val evalSettings: EvalSettings) extends Feature[A, B] { implicit val cs = compilerSettingsInTests @@ -665,7 +666,7 @@ class SigmaDslTesting extends AnyPropSpec logScript: Boolean = LogScriptDefault, allowNewToSucceed: Boolean = false, override val allowDifferentErrors: Boolean = false - )(implicit IR: IRContext, override val evalSettings: EvalSettings, val tA: RType[A], val tB: RType[B]) + )(implicit IR: Scalan, override val evalSettings: EvalSettings, val tA: RType[A], val tB: RType[B]) extends Feature[A, B] { feature => implicit val cs = compilerSettingsInTests @@ -839,7 +840,7 @@ class SigmaDslTesting extends AnyPropSpec expectedExpr: Option[SValue], printExpectedExpr: Boolean = true, logScript: Boolean = LogScriptDefault - )(implicit IR: IRContext, override val evalSettings: EvalSettings, val tA: RType[A], val tB: RType[B]) + )(implicit IR: Scalan, override val evalSettings: EvalSettings, val tA: RType[A], val tB: RType[B]) extends Feature[A, B] { override def scalaFunc: A => B = { x => sys.error(s"Semantic Scala function is not defined for old implementation: $this") @@ -1012,7 +1013,7 @@ class SigmaDslTesting extends AnyPropSpec def existingFeature[A: RType, B: RType] (scalaFunc: A => B, script: String, expectedExpr: SValue = null) - (implicit IR: IRContext, evalSettings: EvalSettings): Feature[A, B] = { + (implicit IR: Scalan, evalSettings: EvalSettings): Feature[A, B] = { ExistingFeature( script, scalaFunc, Option(expectedExpr)) } @@ -1035,7 +1036,7 @@ class SigmaDslTesting extends AnyPropSpec expectedExpr: SValue = null, allowNewToSucceed: Boolean = false, allowDifferentErrors: Boolean = false) - (implicit IR: IRContext, evalSettings: EvalSettings): Feature[A, B] = { + (implicit IR: Scalan, evalSettings: EvalSettings): Feature[A, B] = { ChangedFeature(script, scalaFunc, scalaFuncNew, Option(expectedExpr), allowNewToSucceed = allowNewToSucceed, allowDifferentErrors = allowDifferentErrors) @@ -1052,7 +1053,7 @@ class SigmaDslTesting extends AnyPropSpec */ def newFeature[A: RType, B: RType] (scalaFunc: A => B, script: String, expectedExpr: SValue = null) - (implicit IR: IRContext, es: EvalSettings): Feature[A, B] = { + (implicit IR: Scalan, es: EvalSettings): Feature[A, B] = { NewFeature(script, scalaFunc, Option(expectedExpr)) } @@ -1150,7 +1151,7 @@ class SigmaDslTesting extends AnyPropSpec def benchmarkCases[A: Ordering : Arbitrary : ClassTag, B] (cases: Seq[A], f: Feature[A, B], nIters: Int, formatter: MeasureFormatter[A]) - (implicit IR: IRContext, evalSettings: EvalSettings): Seq[Long] = { + (implicit IR: Scalan, evalSettings: EvalSettings): Seq[Long] = { val fNew = f.newF implicit val tA = fNew.tA implicit val tB = fNew.tB diff --git a/sc/shared/src/test/scala/sigmastate/CompilerTestsBase.scala b/sc/shared/src/test/scala/sigmastate/CompilerTestsBase.scala index 0b2951b92f..0d00fef070 100644 --- a/sc/shared/src/test/scala/sigmastate/CompilerTestsBase.scala +++ b/sc/shared/src/test/scala/sigmastate/CompilerTestsBase.scala @@ -7,7 +7,7 @@ import sigma.ast.{ErgoTree, SType, TransformingSigmaBuilder, Value} import org.ergoplatform.ErgoAddressEncoder.TestnetNetworkPrefix import sigma.ast.syntax.{SValue, SigmaPropValue} import sigma.serialization.ValueSerializer -import sigmastate.eval.IRContext +import sigma.compiler.Scalan import sigma.ast.syntax.ValueOps import sigmastate.helpers.{NegativeTesting, SigmaPPrint} @@ -44,21 +44,21 @@ trait CompilerTestsBase extends TestsBase with NegativeTesting { } /** Compile the given code to ErgoTree expression. */ - def compile(env: ScriptEnv, code: String)(implicit IR: IRContext): Value[SType] = { + def compile(env: ScriptEnv, code: String)(implicit IR: Scalan): Value[SType] = { val res = compiler.compile(env, code) checkCompilerResult(res) res.buildTree } /** Check the given [[CompilerResult]] meets equality and sanity requirements. */ - def checkCompilerResult[Ctx <: IRContext](res: CompilerResult[Ctx]): Unit = { + def checkCompilerResult[Ctx <: Scalan](res: CompilerResult[Ctx]): Unit = { checkSerializationRoundTrip(res.buildTree) } /** Compiles the given code and checks the resulting `prop` against `expected`. */ def compileAndCheck(env: ScriptEnv, code: String, expected: SValue) - (implicit IR: IRContext): (ErgoTree, SigmaPropValue) = { + (implicit IR: Scalan): (ErgoTree, SigmaPropValue) = { val prop = compile(env, code).asSigmaProp prop shouldBe expected val tree = mkTestErgoTree(prop) diff --git a/sc/shared/src/test/scala/sigmastate/ScriptVersionSwitchSpecification.scala b/sc/shared/src/test/scala/sigmastate/ScriptVersionSwitchSpecification.scala index b0206fa464..767c1dbd7b 100644 --- a/sc/shared/src/test/scala/sigmastate/ScriptVersionSwitchSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/ScriptVersionSwitchSpecification.scala @@ -14,6 +14,7 @@ import sigmastate.interpreter.CErgoTreeEvaluator.DefaultEvalSettings import sigma.eval.EvalSettings.EvaluationMode import sigmastate.interpreter._ import sigma.ast.syntax.ValueOps +import sigma.compiler.Scalan import sigma.data.CBox import sigma.eval.EvalSettings import sigma.exceptions.InterpreterException @@ -32,7 +33,7 @@ class ScriptVersionSwitchSpecification extends SigmaDslTesting { costTracingEnabled = true // should always be enabled in tests (and false by default) ) - implicit def IR: IRContext = createIR() + implicit def IR: Scalan = createIR() lazy val b1 = CBox( new ErgoBox( @@ -51,7 +52,7 @@ class ScriptVersionSwitchSpecification extends SigmaDslTesting { ) /** Creates ErgoTree with segregated constants and also the given header flags. */ - def createErgoTree(header: HeaderType)(implicit IR: IRContext): ErgoTree = { + def createErgoTree(header: HeaderType)(implicit IR: Scalan): ErgoTree = { val code = s"""{ | val func = { (x: Coll[Box]) => x.filter({(b: Box) => b.value > 1 }) } diff --git a/sc/shared/src/test/scala/sigmastate/eval/ErgoScriptTestkit.scala b/sc/shared/src/test/scala/sigmastate/eval/ErgoScriptTestkit.scala index a10a717d2f..dc9cccae9c 100644 --- a/sc/shared/src/test/scala/sigmastate/eval/ErgoScriptTestkit.scala +++ b/sc/shared/src/test/scala/sigmastate/eval/ErgoScriptTestkit.scala @@ -14,6 +14,7 @@ import sigmastate.helpers.{ContextEnrichingTestProvingInterpreter, ErgoLikeConte import sigmastate.interpreter.Interpreter.ScriptEnv import sigmastate.interpreter.CErgoTreeEvaluator import sigma.ast.syntax.ValueOps +import sigma.compiler.Scalan import sigma.interpreter.ContextExtension import sigmastate.lang.{CompilerResult, CompilerSettings, LangTests, SigmaCompiler} import sigma.serialization.ErgoTreeSerializer.DefaultSerializer @@ -26,8 +27,8 @@ import scala.util.{Success, Try} trait ErgoScriptTestkit extends ContractsTestkit with LangTests with ValidationSpecification with CompilerTestsBase { self: BaseCtxTests => - implicit lazy val IR: TestContext with IRContext = - new TestContext with IRContext + implicit lazy val IR: TestContext with Scalan = + new TestContext with Scalan import IR._ import BigInt._ diff --git a/sc/shared/src/test/scala/sigmastate/eval/ErgoTreeBuildingTest.scala b/sc/shared/src/test/scala/sigmastate/eval/ErgoTreeBuildingTest.scala index 526012f212..deb2110443 100644 --- a/sc/shared/src/test/scala/sigmastate/eval/ErgoTreeBuildingTest.scala +++ b/sc/shared/src/test/scala/sigmastate/eval/ErgoTreeBuildingTest.scala @@ -8,11 +8,12 @@ import scalan.BaseCtxTests import sigma.ast.syntax.ValueOps import sigmastate.lang.LangTests import sigma.ast.Apply +import sigma.compiler.Scalan class ErgoTreeBuildingTest extends BaseCtxTests with LangTests with ExampleContracts with ErgoScriptTestkit { - implicit override lazy val IR: TestContext with IRContext = new TestContext with IRContext { + implicit override lazy val IR: TestContext with Scalan = new TestContext with Scalan { beginPass(noConstPropagationPass) } diff --git a/sc/shared/src/test/scala/sigmastate/helpers/CompilerTestingCommons.scala b/sc/shared/src/test/scala/sigmastate/helpers/CompilerTestingCommons.scala index 6c3708b782..b7bdf58452 100644 --- a/sc/shared/src/test/scala/sigmastate/helpers/CompilerTestingCommons.scala +++ b/sc/shared/src/test/scala/sigmastate/helpers/CompilerTestingCommons.scala @@ -12,6 +12,7 @@ import sigma.data.{RType, SigmaBoolean} import sigma.validation.ValidationException import sigma.validation.ValidationRules.CheckSerializableTypeCode import sigma.ast.syntax.{SValue, SigmaPropValue} +import sigma.compiler.Scalan import sigma.eval.{CostDetails, EvalSettings, Extensions, GivenCost, TracedCost} import sigmastate.helpers.TestingHelpers._ import sigma.interpreter.ContextExtension.VarBinding @@ -21,7 +22,7 @@ import sigmastate.interpreter._ import sigmastate.lang.{CompilerSettings, SigmaCompiler} import sigma.serialization.SigmaSerializer import sigmastate.CompilerTestsBase -import sigmastate.eval.{CContext, IRContext} +import sigmastate.eval.CContext import scala.util.DynamicVariable @@ -29,7 +30,7 @@ trait CompilerTestingCommons extends TestingCommons with TestUtils with TestContexts with ValidationSpecification with CompilerTestsBase { - class TestingIRContext extends TestContext with IRContext + class TestingIRContext extends TestContext with Scalan case class CompiledFunc[A,B] (script: String, bindings: Seq[VarBinding], expr: SValue, compiledTree: SValue, func: A => (B, CostDetails)) @@ -90,7 +91,7 @@ trait CompilerTestingCommons extends TestingCommons def compileTestScript[A] (env: ScriptEnv, funcScript: String) (implicit tA: RType[A], - IR: IRContext, + IR: Scalan, compilerSettings: CompilerSettings): SValue = { val code = s"""{ @@ -128,7 +129,7 @@ trait CompilerTestingCommons extends TestingCommons def funcJitFromExpr[A: RType, B: RType] (funcScript: String, expr: SValue, bindings: VarBinding*) - (implicit IR: IRContext, + (implicit IR: Scalan, evalSettings: EvalSettings, compilerSettings: CompilerSettings): CompiledFunc[A, B] = { val f = (in: A) => { @@ -166,7 +167,7 @@ trait CompilerTestingCommons extends TestingCommons def funcJit[A: RType, B: RType] (funcScript: String, bindings: VarBinding*) - (implicit IR: IRContext, + (implicit IR: Scalan, evalSettings: EvalSettings, compilerSettings: CompilerSettings): CompiledFunc[A, B] = { val compiledTree = compileTestScript[A](Interpreter.emptyEnv, funcScript) diff --git a/sc/shared/src/test/scala/sigmastate/serialization/ErgoTreeSerializerSpecification.scala b/sc/shared/src/test/scala/sigmastate/serialization/ErgoTreeSerializerSpecification.scala index e20d8a6d1e..ae517a2ee6 100644 --- a/sc/shared/src/test/scala/sigmastate/serialization/ErgoTreeSerializerSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/serialization/ErgoTreeSerializerSpecification.scala @@ -10,9 +10,9 @@ import sigma.util.Extensions.SigmaPropOps import sigma.validation.ValidationException import ErgoTree.EmptyConstants import ErgoTree.HeaderType +import sigma.compiler.Scalan import sigma.eval.Extensions.SigmaBooleanOps import sigmastate._ -import sigmastate.eval.IRContext import sigmastate.helpers.CompilerTestingCommons import sigma.serialization.ErgoTreeSerializer.DefaultSerializer @@ -25,7 +25,7 @@ class ErgoTreeSerializerSpecification extends SerializationSpecification beginPass(noConstPropagationPass) } - private def extractConstants(prop: SigmaPropValue)(implicit IR: IRContext): Seq[ErgoTree] = { + private def extractConstants(prop: SigmaPropValue)(implicit IR: Scalan): Seq[ErgoTree] = { import ErgoTree._ val env = Map[String, Any]() val res = compiler.compileTyped(env, prop) diff --git a/sc/shared/src/test/scala/sigmastate/utxo/AVLTreeScriptsSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/AVLTreeScriptsSpecification.scala index 566bf5bd58..7e1b9a5491 100644 --- a/sc/shared/src/test/scala/sigmastate/utxo/AVLTreeScriptsSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/utxo/AVLTreeScriptsSpecification.scala @@ -9,7 +9,6 @@ import scorex.crypto.hash.{Blake2b256, Digest32} import sigma.ast.SCollection.SByteArray import sigma.ast._ import sigmastate._ -import sigmastate.eval.IRContext import sigmastate.eval._ import sigma.Extensions.ArrayOps import sigmastate.helpers.{CompilerTestingCommons, ContextEnrichingTestProvingInterpreter, ErgoLikeContextTesting, ErgoLikeTestInterpreter} @@ -19,6 +18,7 @@ import sigma.ast.syntax._ import sigma.Coll import sigma.ast.SAvlTree import sigma.ast.syntax.{GetVarByteArray, OptionValueOps} +import sigma.compiler.Scalan import sigma.data.{AvlTreeData, AvlTreeFlags, CSigmaProp, TrivialProp} import sigma.eval.SigmaDsl import sigma.interpreter.ProverResult @@ -31,7 +31,7 @@ class AVLTreeScriptsSpecification extends CompilerTestingCommons import org.ergoplatform.dsl.AvlTreeHelpers._ lazy val spec = TestContractSpec(suite)(new TestingIRContext) lazy val prover = spec.ProvingParty("Alice") - private implicit lazy val IR: IRContext = spec.IR + private implicit lazy val IR: Scalan = spec.IR private val reg1 = ErgoBox.nonMandatoryRegisters(0) private val reg2 = ErgoBox.nonMandatoryRegisters(1) diff --git a/sc/shared/src/test/scala/sigmastate/utxo/UsingContextPropertiesSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/UsingContextPropertiesSpecification.scala index e3d43ab868..9c29c0301d 100644 --- a/sc/shared/src/test/scala/sigmastate/utxo/UsingContextPropertiesSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/utxo/UsingContextPropertiesSpecification.scala @@ -1,20 +1,20 @@ package sigmastate.utxo import sigmastate.CompilerCrossVersionProps -import sigmastate.eval.IRContext import sigma.Extensions.ArrayOps import sigma.Context import sigmastate.helpers.CompilerTestingCommons import org.ergoplatform.dsl.{ContractSpec, SigmaContractSyntax, TestContractSpec} import org.ergoplatform.ErgoBox import scorex.crypto.hash.Blake2b256 +import sigma.compiler.Scalan import sigma.data.{CSigmaProp, TrivialProp} class UsingContextPropertiesSpecification extends CompilerTestingCommons with CompilerCrossVersionProps { suite => lazy val spec = TestContractSpec(suite)(new TestingIRContext) lazy val prover = spec.ProvingParty("Alice") - private implicit lazy val IR: IRContext = spec.IR + private implicit lazy val IR: Scalan = spec.IR private val reg1 = ErgoBox.nonMandatoryRegisters(0) diff --git a/sc/shared/src/test/scala/sigmastate/utxo/blockchain/BlockchainSimulationTestingCommons.scala b/sc/shared/src/test/scala/sigmastate/utxo/blockchain/BlockchainSimulationTestingCommons.scala index 0dca8a4471..4cf39a8cb6 100644 --- a/sc/shared/src/test/scala/sigmastate/utxo/blockchain/BlockchainSimulationTestingCommons.scala +++ b/sc/shared/src/test/scala/sigmastate/utxo/blockchain/BlockchainSimulationTestingCommons.scala @@ -17,6 +17,7 @@ import scorex.util._ import sigma.Colls import sigma.data.{AvlTreeData, AvlTreeFlags} import ErgoTree.ZeroHeader +import sigma.compiler.Scalan import sigma.eval.Extensions.SigmaBooleanOps import sigma.interpreter.ContextExtension import sigmastate.interpreter.Interpreter.{ScriptNameProp, emptyEnv} @@ -125,7 +126,7 @@ object BlockchainSimulationTestingCommons extends CompilerTestingCommons { } - case class ValidationState(state: BlockchainState, boxesReader: InMemoryErgoBoxReader, activatedVersion: Byte)(implicit IR: IRContext) { + case class ValidationState(state: BlockchainState, boxesReader: InMemoryErgoBoxReader, activatedVersion: Byte)(implicit IR: Scalan) { val validator = new ErgoTransactionValidator(activatedVersion) def applyBlock(block: FullBlock, maxCost: Int = MaxBlockCost): Try[ValidationState] = Try { @@ -165,7 +166,7 @@ object BlockchainSimulationTestingCommons extends CompilerTestingCommons { ErgoLikeContextTesting.dummyPubkey ) - def initialState(activatedVersion: Byte, block: FullBlock)(implicit IR: IRContext): ValidationState = { + def initialState(activatedVersion: Byte, block: FullBlock)(implicit IR: Scalan): ValidationState = { val keySize = 32 val prover = new BatchProver(keySize, None) diff --git a/sc/shared/src/test/scala/sigmastate/utxo/examples/IcoExample.scala b/sc/shared/src/test/scala/sigmastate/utxo/examples/IcoExample.scala index c930135bc2..6a55338fbe 100644 --- a/sc/shared/src/test/scala/sigmastate/utxo/examples/IcoExample.scala +++ b/sc/shared/src/test/scala/sigmastate/utxo/examples/IcoExample.scala @@ -22,6 +22,7 @@ import sigmastate.helpers.{CompilerTestingCommons, ContextEnrichingTestProvingIn import sigmastate.interpreter.Interpreter.ScriptNameProp import sigmastate.interpreter.Interpreter import sigma.ast.syntax._ +import sigma.compiler.Scalan import sigma.eval.SigmaDsl import sigma.serialization.ErgoTreeSerializer import sigma.serialization.ErgoTreeSerializer.DefaultSerializer @@ -241,7 +242,7 @@ class IcoExample extends CompilerTestingCommons with CompilerCrossVersionProps with BeforeAndAfterAll { suite => // Not mixed with TestContext since it is not possible to call commpiler.compile outside tests if mixed - implicit lazy val IR: IRContext = new IRContext {} + implicit lazy val IR: Scalan = new Scalan {} lazy val spec = TestContractSpec(suite) lazy val project = new ErgoLikeTestProvingInterpreter() diff --git a/sc/shared/src/test/scala/sigmastate/utxo/examples/LetsSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/examples/LetsSpecification.scala index ce4ed2114e..5b40d111f3 100644 --- a/sc/shared/src/test/scala/sigmastate/utxo/examples/LetsSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/utxo/examples/LetsSpecification.scala @@ -10,12 +10,12 @@ import sigma.data.{AvlTreeData, AvlTreeFlags, Digest32Coll, TrivialProp} import sigmastate.CompilerCrossVersionProps import sigma.ast.{AvlTreeConstant, ByteArrayConstant, LongConstant, SigmaPropConstant} import sigma.Extensions.ArrayOps -import sigmastate.eval.IRContext import sigmastate.helpers.{CompilerTestingCommons, ContextEnrichingTestProvingInterpreter, ErgoLikeContextTesting, ErgoLikeTestProvingInterpreter} import sigmastate.helpers.TestingHelpers._ import sigmastate.interpreter.Interpreter.ScriptNameProp import sigma.serialization.ErgoTreeSerializer import sigma.ast.syntax._ +import sigma.compiler.Scalan import sigma.eval.SigmaDsl import scala.util.Random @@ -172,7 +172,7 @@ import scala.util.Random class LetsSpecification extends CompilerTestingCommons with CompilerCrossVersionProps { suite => // Not mixed with TestContext since it is not possible to call compiler.compile outside tests if mixed - implicit lazy val IR: IRContext = new TestingIRContext + implicit lazy val IR: Scalan = new TestingIRContext lazy val project = new ErgoLikeTestProvingInterpreter() From 26da1fad2565eb2842871f323ce0eec0c09648b1 Mon Sep 17 00:00:00 2001 From: Alexander Slesarenko Date: Wed, 15 May 2024 22:11:03 +0100 Subject: [PATCH 071/314] refactor-ir-cake: Scalan renamed to IRContext --- sc/js/src/test/scala/scalan/Platform.scala | 6 +- sc/jvm/src/test/scala/scalan/Platform.scala | 12 +- .../scalan/compilation/GraphVizExport.scala | 6 +- .../InterpreterReflectionGeneratorTests.scala | 4 +- .../sigmastate/ReflectionGenerator.scala | 4 +- .../org/ergoplatform/ErgoScriptPredef.scala | 6 +- .../org/ergoplatform/dsl/ContractSpec.scala | 4 +- .../ergoplatform/dsl/ErgoContractSpec.scala | 4 +- .../src/main/scala/sigma/compiler/Base.scala | 4 +- .../scala/sigma/compiler/DefRewriting.scala | 2 +- .../main/scala/sigma/compiler/Entities.scala | 2 +- .../scala/sigma/compiler/GraphBuilding.scala | 4 +- .../sigma/compiler/GraphIRReflection.scala | 42 ++--- .../main/scala/sigma/compiler/IRContext.scala | 174 +++++++++++++++++- .../scala/sigma/compiler/MethodCalls.scala | 2 +- .../main/scala/sigma/compiler/Modules.scala | 2 +- .../main/scala/sigma/compiler/Scalan.scala | 174 ------------------ .../scala/sigma/compiler/TreeBuilding.scala | 2 +- .../main/scala/sigma/compiler/TypeDescs.scala | 2 +- .../sigma/compiler/primitives/Equal.scala | 4 +- .../sigma/compiler/primitives/Functions.scala | 4 +- .../compiler/primitives/IfThenElse.scala | 4 +- .../compiler/primitives/LogicalOps.scala | 4 +- .../compiler/primitives/NumericOps.scala | 4 +- .../compiler/primitives/OrderingOps.scala | 4 +- .../sigma/compiler/primitives/Thunks.scala | 7 +- .../sigma/compiler/primitives/Tuples.scala | 4 +- .../sigma/compiler/primitives/UnBinOps.scala | 4 +- .../compiler/primitives/UniversalOps.scala | 4 +- .../sigma/compiler/staged/AstGraphs.scala | 4 +- .../sigma/compiler/staged/ProgramGraphs.scala | 4 +- .../sigma/compiler/staged/Transforming.scala | 4 +- .../scala/sigmastate/lang/SigmaCompiler.scala | 10 +- .../scala/special/collection/CollsUnit.scala | 5 +- .../special/collection/impl/CollsImpl.scala | 8 +- .../scala/special/sigma/SigmaDslUnit.scala | 4 +- .../special/sigma/impl/SigmaDslImpl.scala | 8 +- .../sigma/wrappers/WrappersModule.scala | 4 +- .../special/wrappers/WrappersModule.scala | 4 +- .../main/scala/wrappers/scala/WOptions.scala | 4 +- .../wrappers/scala/impl/WOptionsImpl.scala | 8 +- .../main/scala/wrappers/scalan/WRTypes.scala | 4 +- .../wrappers/scalan/impl/WRTypesImpl.scala | 8 +- .../wrappers/special/WSpecialPredefs.scala | 4 +- .../special/impl/WSpecialPredefsImpl.scala | 9 +- .../ergoplatform/dsl/TestContractSpec.scala | 4 +- .../test/scala/scalan/BaseLiftableTests.scala | 4 +- .../src/test/scala/scalan/LibraryTests.scala | 4 +- .../src/test/scala/scalan/TestContexts.scala | 6 +- .../src/test/scala/scalan/TestLibrary.scala | 4 +- .../test/scala/sigma/CollsStagingTests.scala | 6 +- .../scala/sigma/SigmaDslStaginTests.scala | 4 +- .../test/scala/sigma/SigmaDslTesting.scala | 18 +- .../scala/sigmastate/CompilerTestsBase.scala | 8 +- .../ScriptVersionSwitchSpecification.scala | 6 +- .../sigmastate/eval/ErgoScriptTestkit.scala | 6 +- .../eval/ErgoTreeBuildingTest.scala | 4 +- .../helpers/CompilerTestingCommons.scala | 10 +- .../ErgoTreeSerializerSpecification.scala | 4 +- .../utxo/AVLTreeScriptsSpecification.scala | 6 +- .../UsingContextPropertiesSpecification.scala | 6 +- .../BlockchainSimulationTestingCommons.scala | 6 +- .../sigmastate/utxo/examples/IcoExample.scala | 4 +- .../utxo/examples/LetsSpecification.scala | 4 +- 64 files changed, 350 insertions(+), 355 deletions(-) delete mode 100644 sc/shared/src/main/scala/sigma/compiler/Scalan.scala diff --git a/sc/js/src/test/scala/scalan/Platform.scala b/sc/js/src/test/scala/scalan/Platform.scala index 2349a1f444..afb5ff72c1 100644 --- a/sc/js/src/test/scala/scalan/Platform.scala +++ b/sc/js/src/test/scala/scalan/Platform.scala @@ -1,16 +1,16 @@ package scalan -import sigma.compiler.Scalan +import sigma.compiler.IRContext import scala.annotation.unused object Platform { /** In JS tests do nothing. The corresponding JVM method outputs graphs into files. */ - def stage[Ctx <: Scalan](scalan: Ctx)( + def stage[Ctx <: IRContext](ctx: Ctx)( @unused prefix: String, @unused testName: String, @unused name: String, - @unused sfs: Seq[() => scalan.Sym]): Unit = { + @unused sfs: Seq[() => ctx.Sym]): Unit = { } /** On JS it is no-operation. */ diff --git a/sc/jvm/src/test/scala/scalan/Platform.scala b/sc/jvm/src/test/scala/scalan/Platform.scala index b9c65374c2..3a194a7d50 100644 --- a/sc/jvm/src/test/scala/scalan/Platform.scala +++ b/sc/jvm/src/test/scala/scalan/Platform.scala @@ -3,23 +3,23 @@ package scalan import scalan.compilation.GraphVizExport import sigma.util.FileUtil import org.scalatest.Assertions -import sigma.compiler.Scalan +import sigma.compiler.IRContext object Platform { /** Output graph given by symbols in `sfs` to files. - * @param scalan The Scalan context + * @param ctx The Scalan context * @param prefix The prefix of the directory where the graphs will be stored. * @param testName The name of the test. * @param name The name of the graph. * @param sfs A sequence of functions that return symbols of the graph roots. */ - def stage[Ctx <: Scalan](scalan: Ctx) - (prefix: String, testName: String, name: String, sfs: Seq[() => scalan.Sym]): Unit = { + def stage[Ctx <: IRContext](ctx: Ctx) + (prefix: String, testName: String, name: String, sfs: Seq[() => ctx.Sym]): Unit = { val directory = FileUtil.file(prefix, testName) - val gv = new GraphVizExport(scalan) + val gv = new GraphVizExport(ctx) implicit val graphVizConfig = gv.defaultGraphVizConfig try { - val ss = sfs.map(_.apply()).asInstanceOf[Seq[gv.scalan.Sym]] + val ss = sfs.map(_.apply()).asInstanceOf[Seq[gv.ctx.Sym]] gv.emitDepGraph(ss, directory, name)(graphVizConfig) } catch { case e: Exception => diff --git a/sc/jvm/src/test/scala/scalan/compilation/GraphVizExport.scala b/sc/jvm/src/test/scala/scalan/compilation/GraphVizExport.scala index c5b7f16cca..1072de00e2 100644 --- a/sc/jvm/src/test/scala/scalan/compilation/GraphVizExport.scala +++ b/sc/jvm/src/test/scala/scalan/compilation/GraphVizExport.scala @@ -3,7 +3,7 @@ package scalan.compilation import java.awt.Desktop import java.io.{File, PrintWriter} import scalan.core.ScalaNameUtil -import sigma.compiler.Scalan +import sigma.compiler.IRContext import sigma.util.{FileUtil, ProcessUtil, StringUtil} import scala.annotation.unused @@ -12,8 +12,8 @@ import scala.collection.immutable.StringOps // TODO implement this outside of the cake /** Implementation of Graphviz's dot file generator. */ -class GraphVizExport[Ctx <: Scalan](val scalan: Ctx) { - import scalan._ +class GraphVizExport[Ctx <: IRContext](val ctx: Ctx) { + import ctx._ case class GraphFile(file: File, fileType: String) { def open() = { Desktop.getDesktop.open(file) diff --git a/sc/jvm/src/test/scala/sigmastate/InterpreterReflectionGeneratorTests.scala b/sc/jvm/src/test/scala/sigmastate/InterpreterReflectionGeneratorTests.scala index 2a65dfedf5..7fc0e454ed 100644 --- a/sc/jvm/src/test/scala/sigmastate/InterpreterReflectionGeneratorTests.scala +++ b/sc/jvm/src/test/scala/sigmastate/InterpreterReflectionGeneratorTests.scala @@ -2,7 +2,7 @@ package sigmastate import org.scalatest.matchers.should.Matchers import org.scalatest.propspec.AnyPropSpec -import sigma.compiler.{Scalan, TypeDescs} +import sigma.compiler.{IRContext, TypeDescs} import sigma.reflection.ReflectionData.registerClassEntry import sigma.reflection.SRConstructor @@ -37,7 +37,7 @@ class InterpreterReflectionGeneratorTests extends AnyPropSpec with Matchers { } property("inner class") { - val ctx = null.asInstanceOf[Scalan] // ok! type level only + val ctx = null.asInstanceOf[IRContext] // ok! type level only val clazz = classOf[ctx.Coll.CollElem[_, _]] registerClassEntry(clazz, constructors = Array( diff --git a/sc/jvm/src/test/scala/sigmastate/ReflectionGenerator.scala b/sc/jvm/src/test/scala/sigmastate/ReflectionGenerator.scala index 735297d119..963e1c56d1 100644 --- a/sc/jvm/src/test/scala/sigmastate/ReflectionGenerator.scala +++ b/sc/jvm/src/test/scala/sigmastate/ReflectionGenerator.scala @@ -30,7 +30,7 @@ object ReflectionGenerator { } val knownPackages = Array( - "scalan.primitives.", + "sigma.compiler.primitives.", "sigma.", "sigma.", "special.wrappers.", @@ -40,7 +40,7 @@ object ReflectionGenerator { "sigmastate.utxo.", "sigmastate.", "wrappers.scala.", - "scalan.", + "sigma.compiler.", "scala.collection.", "scala." ) diff --git a/sc/shared/src/main/scala/org/ergoplatform/ErgoScriptPredef.scala b/sc/shared/src/main/scala/org/ergoplatform/ErgoScriptPredef.scala index a2bc3362d7..1b84e7f0d6 100644 --- a/sc/shared/src/main/scala/org/ergoplatform/ErgoScriptPredef.scala +++ b/sc/shared/src/main/scala/org/ergoplatform/ErgoScriptPredef.scala @@ -6,13 +6,13 @@ import sigma.ast.SType import sigma.ast.syntax.SigmaPropValue import sigma.ast.Value import sigma.ast.syntax.ValueOps -import sigma.compiler.Scalan +import sigma.compiler.IRContext object ErgoScriptPredef { import sigmastate.interpreter.Interpreter._ /** Compiles the given ErgoScript `code` into ErgoTree expression. */ - def compileWithCosting(env: ScriptEnv, code: String, networkPrefix: NetworkPrefix)(implicit IR: Scalan): Value[SType] = { + def compileWithCosting(env: ScriptEnv, code: String, networkPrefix: NetworkPrefix)(implicit IR: IRContext): Value[SType] = { val compiler = SigmaCompiler(networkPrefix) val res = compiler.compile(env, code) res.buildTree @@ -30,7 +30,7 @@ object ErgoScriptPredef { tokenId: Array[Byte], thresholdAmount: Long, networkPrefix: NetworkPrefix) - (implicit IR: Scalan): SigmaPropValue = { + (implicit IR: IRContext): SigmaPropValue = { val env = emptyEnv + ("tokenId" -> tokenId, "thresholdAmount" -> thresholdAmount) val res = compileWithCosting(env, diff --git a/sc/shared/src/main/scala/org/ergoplatform/dsl/ContractSpec.scala b/sc/shared/src/main/scala/org/ergoplatform/dsl/ContractSpec.scala index 539da9d79b..128351efea 100644 --- a/sc/shared/src/main/scala/org/ergoplatform/dsl/ContractSpec.scala +++ b/sc/shared/src/main/scala/org/ergoplatform/dsl/ContractSpec.scala @@ -9,7 +9,7 @@ import sigma.{Coll, SigmaDslBuilder, SigmaProp} import scala.util.Try import org.ergoplatform.dsl.ContractSyntax.{ErgoScript, Proposition, Token} import sigma.ast.{ErgoTree, EvaluatedValue, SType} -import sigma.compiler.Scalan +import sigma.compiler.IRContext import scala.language.implicitConversions @@ -19,7 +19,7 @@ trait ContractSpec { implicit def Coll[T](items: Array[T])(implicit cT: RType[T]): Coll[T] = Colls.fromArray(items) - val IR: Scalan + val IR: IRContext trait PropositionSpec { def name: String diff --git a/sc/shared/src/main/scala/org/ergoplatform/dsl/ErgoContractSpec.scala b/sc/shared/src/main/scala/org/ergoplatform/dsl/ErgoContractSpec.scala index 6a91c6f60a..5929299a3b 100644 --- a/sc/shared/src/main/scala/org/ergoplatform/dsl/ErgoContractSpec.scala +++ b/sc/shared/src/main/scala/org/ergoplatform/dsl/ErgoContractSpec.scala @@ -3,10 +3,10 @@ package org.ergoplatform.dsl import sigma.Coll import org.ergoplatform.dsl.ContractSyntax.{ErgoScript, Proposition, Token} import org.ergoplatform.ErgoBox.{BoxId, NonMandatoryRegisterId, TokenId} -import sigma.compiler.Scalan +import sigma.compiler.IRContext import sigma.interpreter.CostedProverResult -class ErgoContractSpec(implicit val IR: Scalan) extends ContractSpec { +class ErgoContractSpec(implicit val IR: IRContext) extends ContractSpec { case class ErgoOutBox(tx: TransactionCandidate, boxIndex: Int, value: Long, propSpec: PropositionSpec) extends OutBox { diff --git a/sc/shared/src/main/scala/sigma/compiler/Base.scala b/sc/shared/src/main/scala/sigma/compiler/Base.scala index b6e81f2a6f..3d6b763c5a 100644 --- a/sc/shared/src/main/scala/sigma/compiler/Base.scala +++ b/sc/shared/src/main/scala/sigma/compiler/Base.scala @@ -18,7 +18,7 @@ import scala.language.implicitConversions * The Base trait houses common AST nodes. It also manages a list of encountered definitions which * allows for common sub-expression elimination (CSE). */ -abstract class Base { scalan: Scalan => +abstract class Base { thisIR: IRContext => type |[+A, +B] = Either[A, B] type RFunc[-A,+B] = Ref[Function1[A,B]] type RPair[+A, +B] = Ref[(A,B)] @@ -554,7 +554,7 @@ abstract class Base { scalan: Scalan => private[compiler] def addOwnerParameter(ownerType: OwnerKind, params: Seq[Any]): Seq[AnyRef] = { val finalParams = (ownerType match { case EntityObjectOwner(obj) => obj +: params - case ScalanOwner => scalan +: params + case ScalanOwner => thisIR +: params case NoOwner => params }) finalParams.asInstanceOf[Seq[AnyRef]] diff --git a/sc/shared/src/main/scala/sigma/compiler/DefRewriting.scala b/sc/shared/src/main/scala/sigma/compiler/DefRewriting.scala index 38930d0307..0cc86c0644 100644 --- a/sc/shared/src/main/scala/sigma/compiler/DefRewriting.scala +++ b/sc/shared/src/main/scala/sigma/compiler/DefRewriting.scala @@ -3,7 +3,7 @@ package sigma.compiler import scalan.DelayInvokeException import sigma.data.ExactNumeric -trait DefRewriting { scalan: Scalan => +trait DefRewriting { scalan: IRContext => /** Rewrites given node to another equivalent node and returns its reference. * @param d node to be matched against rewrite patterns diff --git a/sc/shared/src/main/scala/sigma/compiler/Entities.scala b/sc/shared/src/main/scala/sigma/compiler/Entities.scala index 2cce7fe7d7..bfda787fc3 100644 --- a/sc/shared/src/main/scala/sigma/compiler/Entities.scala +++ b/sc/shared/src/main/scala/sigma/compiler/Entities.scala @@ -1,7 +1,7 @@ package sigma.compiler /** A slice in the Scalan cake with base classes for various descriptors. */ -trait Entities extends TypeDescs { self: Scalan => +trait Entities extends TypeDescs { self: IRContext => /** Base class for all descriptors of staged traits. * See derived classes in `impl` packages. diff --git a/sc/shared/src/main/scala/sigma/compiler/GraphBuilding.scala b/sc/shared/src/main/scala/sigma/compiler/GraphBuilding.scala index 784ee0e836..bbc1361dfe 100644 --- a/sc/shared/src/main/scala/sigma/compiler/GraphBuilding.scala +++ b/sc/shared/src/main/scala/sigma/compiler/GraphBuilding.scala @@ -26,7 +26,7 @@ import scala.collection.mutable.ArrayBuffer * CSE however means the original structure of source code may not be preserved in the * resulting ErgoTree. * */ -trait GraphBuilding extends Base with DefRewriting { IR: Scalan => +trait GraphBuilding extends Base with DefRewriting { IR: IRContext => import AvlTree._ import BigInt._ import Box._ @@ -58,7 +58,7 @@ trait GraphBuilding extends Base with DefRewriting { IR: Scalan => * In v5.x this code is taken from CheckTupleType validation rule which is no longer * part of consensus. */ - def checkTupleType[Ctx <: Scalan, T](ctx: Ctx)(e: ctx.Elem[_]): Unit = { + def checkTupleType[Ctx <: IRContext, T](ctx: Ctx)(e: ctx.Elem[_]): Unit = { val condition = e match { case _: ctx.PairElem[_, _] => true case _ => false diff --git a/sc/shared/src/main/scala/sigma/compiler/GraphIRReflection.scala b/sc/shared/src/main/scala/sigma/compiler/GraphIRReflection.scala index 054cfed9b7..59f1116569 100644 --- a/sc/shared/src/main/scala/sigma/compiler/GraphIRReflection.scala +++ b/sc/shared/src/main/scala/sigma/compiler/GraphIRReflection.scala @@ -22,7 +22,7 @@ object GraphIRReflection { val reflection = ReflectionData { val clazz = classOf[wrappers.scala.WOptions#WOption[_]] - val ctx = null.asInstanceOf[Scalan] // ok! type level only + val ctx = null.asInstanceOf[IRContext] // ok! type level only registerClassEntry(clazz, methods = Map( mkMethod(clazz, "filter", Array[Class[_]](classOf[Base#Ref[_]])) { (obj, args) => @@ -46,8 +46,8 @@ object GraphIRReflection { registerClassEntry(classOf[TypeDescs#FuncElem[_,_]], constructors = Array( - mkConstructor(Array(classOf[Scalan], classOf[TypeDescs#Elem[_]], classOf[TypeDescs#Elem[_]])) { args => - val ctx = args(0).asInstanceOf[Scalan] + mkConstructor(Array(classOf[IRContext], classOf[TypeDescs#Elem[_]], classOf[TypeDescs#Elem[_]])) { args => + val ctx = args(0).asInstanceOf[IRContext] new ctx.FuncElem(args(1).asInstanceOf[ctx.Elem[_]], args(2).asInstanceOf[ctx.Elem[_]]) } ) @@ -55,8 +55,8 @@ object GraphIRReflection { registerClassEntry(classOf[TypeDescs#PairElem[_,_]], constructors = Array( - mkConstructor(Array(classOf[Scalan], classOf[TypeDescs#Elem[_]], classOf[TypeDescs#Elem[_]])) { args => - val ctx = args(0).asInstanceOf[Scalan] + mkConstructor(Array(classOf[IRContext], classOf[TypeDescs#Elem[_]], classOf[TypeDescs#Elem[_]])) { args => + val ctx = args(0).asInstanceOf[IRContext] new ctx.PairElem(args(1).asInstanceOf[ctx.Elem[_]], args(2).asInstanceOf[ctx.Elem[_]]) } ) @@ -64,8 +64,8 @@ object GraphIRReflection { registerClassEntry(classOf[Thunks#ThunkElem[_]], constructors = Array( - mkConstructor(Array(classOf[Scalan], classOf[TypeDescs#Elem[_]])) { args => - val ctx = args(0).asInstanceOf[Scalan] + mkConstructor(Array(classOf[IRContext], classOf[TypeDescs#Elem[_]])) { args => + val ctx = args(0).asInstanceOf[IRContext] new ctx.ThunkElem(args(1).asInstanceOf[ctx.Elem[_]]) } ) @@ -121,7 +121,7 @@ object GraphIRReflection { } { val clazz = classOf[Colls#CollBuilder] - val ctx = null.asInstanceOf[Scalan] // ok! type level only + val ctx = null.asInstanceOf[IRContext] // ok! type level only registerClassEntry(clazz, methods = Map( mkMethod(clazz, "xor", Array[Class[_]](classOf[Base#Ref[_]], classOf[Base#Ref[_]])) { (obj, args) => @@ -143,7 +143,7 @@ object GraphIRReflection { { val clazz = classOf[Colls#Coll[_]] - val ctx = null.asInstanceOf[Scalan] // ok! type level only + val ctx = null.asInstanceOf[IRContext] // ok! type level only registerClassEntry(clazz, methods = Map( mkMethod(clazz, "append", Array[Class[_]](classOf[Base#Ref[_]])) { (obj, args) => @@ -209,7 +209,7 @@ object GraphIRReflection { } { val clazz = classOf[SigmaDsl#AvlTree] - val ctx = null.asInstanceOf[Scalan] // ok! type level only + val ctx = null.asInstanceOf[IRContext] // ok! type level only registerClassEntry(clazz, methods = Map( mkMethod(clazz, "updateOperations", Array[Class[_]](classOf[Base#Ref[_]])) { (obj, args) => @@ -267,7 +267,7 @@ object GraphIRReflection { } { val clazz = classOf[SigmaDsl#Box] - val ctx = null.asInstanceOf[Scalan] // ok! type level only + val ctx = null.asInstanceOf[IRContext] // ok! type level only registerClassEntry(clazz, methods = Map( mkMethod(clazz, "value", Array[Class[_]]()) { (obj, _) => @@ -300,7 +300,7 @@ object GraphIRReflection { { val clazz = classOf[SigmaDsl#Context] - val ctx = null.asInstanceOf[Scalan] // ok! type level only + val ctx = null.asInstanceOf[IRContext] // ok! type level only registerClassEntry(clazz, methods = Map( mkMethod(clazz, "LastBlockUtxoRootHash", Array[Class[_]]()) { (obj, args) => @@ -341,7 +341,7 @@ object GraphIRReflection { } { val clazz = classOf[SigmaDsl#GroupElement] - val ctx = null.asInstanceOf[Scalan] // ok! type level only + val ctx = null.asInstanceOf[IRContext] // ok! type level only registerClassEntry(clazz, methods = Map( mkMethod(clazz, "exp", Array[Class[_]](classOf[Base#Ref[_]])) { (obj, args) => @@ -361,7 +361,7 @@ object GraphIRReflection { } { val clazz = classOf[SigmaDsl#Header] - val ctx = null.asInstanceOf[Scalan] // ok! type level only + val ctx = null.asInstanceOf[IRContext] // ok! type level only registerClassEntry(clazz, methods = Map( mkMethod(clazz, "minerPk", Array[Class[_]]()) { (obj, args) => @@ -414,7 +414,7 @@ object GraphIRReflection { } { val clazz = classOf[SigmaDsl#PreHeader] - val ctx = null.asInstanceOf[Scalan] // ok! type level only + val ctx = null.asInstanceOf[IRContext] // ok! type level only registerClassEntry(clazz, methods = Map( mkMethod(clazz, "minerPk", Array[Class[_]]()) { (obj, _) => @@ -443,7 +443,7 @@ object GraphIRReflection { } { val clazz = classOf[SigmaDsl#SigmaDslBuilder] - val ctx = null.asInstanceOf[Scalan] // ok! type level only + val ctx = null.asInstanceOf[IRContext] // ok! type level only registerClassEntry(clazz, methods = Map( mkMethod(clazz, "byteArrayToLong", Array[Class[_]](classOf[Base#Ref[_]])) { (obj, args) => @@ -510,7 +510,7 @@ object GraphIRReflection { ) } - { val ctx = null.asInstanceOf[Scalan] // ok! type level only + { val ctx = null.asInstanceOf[IRContext] // ok! type level only val clazz = classOf[ctx.WOption.WOptionElem[_, _]] registerClassEntry(clazz, constructors = Array( @@ -523,7 +523,7 @@ object GraphIRReflection { } { val clazz = classOf[WRTypes#WRType[_]] - val ctx = null.asInstanceOf[Scalan] // ok! type level only + val ctx = null.asInstanceOf[IRContext] // ok! type level only registerClassEntry(clazz, methods = Map( mkMethod(clazz, "name", Array[Class[_]]()) { (obj, _) => @@ -533,7 +533,7 @@ object GraphIRReflection { ) } - { val ctx = null.asInstanceOf[Scalan] // ok! type level only + { val ctx = null.asInstanceOf[IRContext] // ok! type level only val clazz = classOf[ctx.WRType.WRTypeElem[_, _]] registerClassEntry(clazz, constructors = Array( @@ -545,7 +545,7 @@ object GraphIRReflection { ) } - { val ctx = null.asInstanceOf[Scalan] // ok! type level only + { val ctx = null.asInstanceOf[IRContext] // ok! type level only val clazz = classOf[ctx.Coll.CollElem[_, _]] registerClassEntry(clazz, constructors = Array( @@ -558,7 +558,7 @@ object GraphIRReflection { } { val clazz = classOf[wrappers.special.WSpecialPredefs#WSpecialPredefCompanion] - val ctx = null.asInstanceOf[Scalan] // ok! type level only + val ctx = null.asInstanceOf[IRContext] // ok! type level only registerClassEntry(clazz, methods = Map( mkMethod(clazz, "some", Array[Class[_]](classOf[Base#Ref[_]])) { (obj, args) => diff --git a/sc/shared/src/main/scala/sigma/compiler/IRContext.scala b/sc/shared/src/main/scala/sigma/compiler/IRContext.scala index 0b958b9ab9..2f31d71589 100644 --- a/sc/shared/src/main/scala/sigma/compiler/IRContext.scala +++ b/sc/shared/src/main/scala/sigma/compiler/IRContext.scala @@ -1,6 +1,176 @@ package sigma.compiler -trait IRContext extends Scalan +import scalan._ +import sigma.compiler.primitives._ +import sigma.compiler.staged.Transforming +import sigma.data.{Nullable, RType} +import sigma.util.MemoizedFunc +import sigma.{CollsModule, SigmaDslModule} +import special.wrappers.WrappersModule + +/** Aggregate cake with all inter-dependent modules assembled together. + * Each instance of this class contains independent IR context, thus many + * instances can be created simultaneously. + * However, the inner types declared in the traits are path-dependant. + * This in particular means that ctx1.Ref[_] and ctx2.Ref[_] are different types. + * The typical usage is to create `val ctx = new Scalan` and then import inner + * declarations using `import ctx._`. + * This way the declaration will be directly available as if they were global + * declarations. + * At the same time cake design pattern allow to `override` many methods and values + * in classed derived from `Scalan`, this is significant benefit over + * *everything is global* design. + * + * It is not used in v5.0 interpreter and thus not part of consensus. + * Used in ErgoScript compiler only. + * + * @see CompiletimeIRContext + */ +trait IRContext + extends TypeDescs + with MethodCalls + with Tuples + with NumericOps + with UnBinOps + with LogicalOps + with OrderingOps + with Equal + with UniversalOps + with Functions + with IfThenElse + with Transforming + with Thunks + with Entities + with Modules + with DefRewriting + with WrappersModule + with CollsModule + with sigma.wrappers.WrappersModule + with SigmaDslModule + with TreeBuilding + with GraphBuilding { + + import Coll._ + import CollBuilder._ + import WOption._ + import WRType._ + import WSpecialPredef._ + + /** Pass configuration which is used to turn-off constant propagation. + * USED IN TESTS ONLY. + * @see `beginPass(noCostPropagationPass)` */ + lazy val noConstPropagationPass = new DefaultPass( + "noCostPropagationPass", + Pass.defaultPassConfig.copy(constantPropagation = false)) + + type LazyRep[T] = MutableLazy[Ref[T]] + + private val _liftElemMemo = new MemoizedFunc({ + case eT: Elem[t] => + val lT = Liftables.asLiftable[Any, t](eT.liftable) + liftableRType(lT).lift(eT.sourceType.asInstanceOf[RType[Any]]) + }) + implicit def liftElem[T](eT: Elem[T]): Ref[WRType[T]] = { + _liftElemMemo(eT).asInstanceOf[Ref[WRType[T]]] // asRep cannot be used for AnyRef + } + + private val _specialPredef: LazyRep[WSpecialPredefCompanionCtor] = MutableLazy(RWSpecialPredef.value) + def specialPredef: Ref[WSpecialPredefCompanionCtor] = _specialPredef.value + + override protected def onReset(): Unit = { + _specialPredef.reset() + _liftElemMemo.reset() + super.onReset() + } + + val CM = CollMethods + private val CBM = CollBuilderMethods + private val WOptionM = WOptionMethods + private val SPCM = WSpecialPredefCompanionMethods + + def colBuilder: Ref[CollBuilder] + + implicit lazy val wRTypeAnyElement: Elem[WRType[Any]] = wRTypeElement(AnyElement) + + /** During compilation represent a global value Global, see also SGlobal type. */ + def sigmaDslBuilder: Ref[SigmaDslBuilder] + + object IsNumericToInt { + def unapply(d: Def[_]): Nullable[Ref[A] forSome {type A}] = d match { + case ApplyUnOp(_: NumericToInt[_], x) => Nullable(x.asInstanceOf[Ref[A] forSome {type A}]) + case _ => Nullable.None + } + } + object IsNumericToLong { + def unapply(d: Def[_]): Nullable[Ref[A] forSome {type A}] = d match { + case ApplyUnOp(_: NumericToLong[_], x) => Nullable(x.asInstanceOf[Ref[A] forSome {type A}]) + case _ => Nullable.None + } + } + + override def rewriteDef[T](d: Def[T]) = d match { + case CM.length(ys) => ys.node match { + // Rule: xs.map(f).length ==> xs.length + case CM.map(xs, _) => + xs.length + // Rule: replicate(len, v).length => len + case CBM.replicate(_, len, _) => + len + // Rule: Const[Coll[T]](coll).length => + case CollConst(coll, _) => + coll.length + // Rule: Coll(items @ Seq(x1, x2, x3)).length => items.length + case CBM.fromItems(_, items, _) => + items.length + case _ => super.rewriteDef(d) + } + + // Rule: replicate(l, x).zip(replicate(l, y)) ==> replicate(l, (x,y)) + case CM.zip(CBM.replicate(b1, l1, v1), CBM.replicate(b2, l2, v2)) if b1 == b2 && l1 == l2 => + b1.replicate(l1, Pair(v1, v2)) + + case CM.map(xs, _f) => _f.node match { + case IdentityLambda() => xs + case _ => xs.node match { + // Rule: replicate(l, v).map(f) ==> replicate(l, f(v)) + case CBM.replicate(b, l, v: Ref[a]) => + val f = asRep[a => Any](_f) + b.replicate(l, Apply(f, v, false)) + + // Rule: xs.map(f).map(g) ==> xs.map(x => g(f(x))) + case CM.map(_xs, f: RFunc[a, b]) => + implicit val ea = f.elem.eDom + val xs = asRep[Coll[a]](_xs) + val g = asRep[b => Any](_f) + xs.map[Any](fun { x: Ref[a] => g(f(x)) }) + + case _ => super.rewriteDef(d) + } + } + + case WOptionM.getOrElse(opt, _) => opt.node match { + // Rule: Some(x).getOrElse(_) ==> x + case SPCM.some(x) => x + case WOptionConst(Some(x), lA) => lA.lift(x) + case _ => super.rewriteDef(d) + } + + case _ => super.rewriteDef(d) + } + + override def invokeUnlifted(e: Elem[_], mc: MethodCall, dataEnv: DataEnv): Any = e match { + case _: CollElem[_,_] => mc match { + case CollMethods.map(_, f) => + val newMC = mc.copy(args = mc.args :+ f.elem.eRange)(mc.resultType, mc.isAdapterCall) + super.invokeUnlifted(e, newMC, dataEnv) + case _ => + super.invokeUnlifted(e, mc, dataEnv) + } + case _ => + super.invokeUnlifted(e, mc, dataEnv) + } + +} /** IR context to be used by script development tools to compile ErgoScript into ErgoTree bytecode. */ -class CompiletimeIRContext extends Scalan +class CompiletimeIRContext extends IRContext diff --git a/sc/shared/src/main/scala/sigma/compiler/MethodCalls.scala b/sc/shared/src/main/scala/sigma/compiler/MethodCalls.scala index 4a0a189edd..4b534930d8 100644 --- a/sc/shared/src/main/scala/sigma/compiler/MethodCalls.scala +++ b/sc/shared/src/main/scala/sigma/compiler/MethodCalls.scala @@ -7,7 +7,7 @@ import sigma.util.CollectionUtil.TraversableOps import scala.annotation.{tailrec, unused} -trait MethodCalls extends Base { self: Scalan => +trait MethodCalls extends Base { self: IRContext => def delayInvoke = throw new DelayInvokeException diff --git a/sc/shared/src/main/scala/sigma/compiler/Modules.scala b/sc/shared/src/main/scala/sigma/compiler/Modules.scala index 94cbaf9816..527dcd6eb8 100644 --- a/sc/shared/src/main/scala/sigma/compiler/Modules.scala +++ b/sc/shared/src/main/scala/sigma/compiler/Modules.scala @@ -1,6 +1,6 @@ package sigma.compiler -trait Modules extends Base { self: Scalan => +trait Modules extends Base { self: IRContext => /** Whether staged modules should be registered when cake is constructed and initialized. */ def okRegisterModules: Boolean = false diff --git a/sc/shared/src/main/scala/sigma/compiler/Scalan.scala b/sc/shared/src/main/scala/sigma/compiler/Scalan.scala deleted file mode 100644 index 8009cd5e36..0000000000 --- a/sc/shared/src/main/scala/sigma/compiler/Scalan.scala +++ /dev/null @@ -1,174 +0,0 @@ -package sigma.compiler - -import scalan._ -import sigma.compiler.primitives.{Equal, Functions, IfThenElse, LogicalOps, NumericOps, OrderingOps, Thunks, Tuples, UnBinOps, UniversalOps} -import sigma.compiler.staged.Transforming -import sigma.data.{Nullable, RType} -import sigma.util.MemoizedFunc -import sigma.{CollsModule, SigmaDslModule} -import special.wrappers.WrappersModule - -/** Aggregate cake with all inter-dependent modules assembled together. - * Each instance of this class contains independent IR context, thus many - * instances can be created simultaneously. - * However, the inner types declared in the traits are path-dependant. - * This in particular means that ctx1.Ref[_] and ctx2.Ref[_] are different types. - * The typical usage is to create `val ctx = new Scalan` and then import inner - * declarations using `import ctx._`. - * This way the declaration will be directly available as if they were global - * declarations. - * At the same time cake design pattern allow to `override` many methods and values - * in classed derived from `Scalan`, this is significant benefit over - * *everything is global* design. - * - * It is not used in v5.0 interpreter and thus not part of consensus. - * Used in ErgoScript compiler only. - * - * @see CompiletimeIRContext - */ -trait Scalan - extends TypeDescs - with MethodCalls - with Tuples - with NumericOps - with UnBinOps - with LogicalOps - with OrderingOps - with Equal - with UniversalOps - with Functions - with IfThenElse - with Transforming - with Thunks - with Entities - with Modules - with DefRewriting - with WrappersModule - with CollsModule - with sigma.wrappers.WrappersModule - with SigmaDslModule - with TreeBuilding - with GraphBuilding { - - import Coll._ - import CollBuilder._ - import WOption._ - import WRType._ - import WSpecialPredef._ - - /** Pass configuration which is used to turn-off constant propagation. - * USED IN TESTS ONLY. - * @see `beginPass(noCostPropagationPass)` */ - lazy val noConstPropagationPass = new DefaultPass( - "noCostPropagationPass", - Pass.defaultPassConfig.copy(constantPropagation = false)) - - type LazyRep[T] = MutableLazy[Ref[T]] - - private val _liftElemMemo = new MemoizedFunc({ - case eT: Elem[t] => - val lT = Liftables.asLiftable[Any, t](eT.liftable) - liftableRType(lT).lift(eT.sourceType.asInstanceOf[RType[Any]]) - }) - implicit def liftElem[T](eT: Elem[T]): Ref[WRType[T]] = { - _liftElemMemo(eT).asInstanceOf[Ref[WRType[T]]] // asRep cannot be used for AnyRef - } - - private val _specialPredef: LazyRep[WSpecialPredefCompanionCtor] = MutableLazy(RWSpecialPredef.value) - def specialPredef: Ref[WSpecialPredefCompanionCtor] = _specialPredef.value - - override protected def onReset(): Unit = { - _specialPredef.reset() - _liftElemMemo.reset() - super.onReset() - } - - val CM = CollMethods - private val CBM = CollBuilderMethods - private val WOptionM = WOptionMethods - private val SPCM = WSpecialPredefCompanionMethods - - def colBuilder: Ref[CollBuilder] - - implicit lazy val wRTypeAnyElement: Elem[WRType[Any]] = wRTypeElement(AnyElement) - - /** During compilation represent a global value Global, see also SGlobal type. */ - def sigmaDslBuilder: Ref[SigmaDslBuilder] - - object IsNumericToInt { - def unapply(d: Def[_]): Nullable[Ref[A] forSome {type A}] = d match { - case ApplyUnOp(_: NumericToInt[_], x) => Nullable(x.asInstanceOf[Ref[A] forSome {type A}]) - case _ => Nullable.None - } - } - object IsNumericToLong { - def unapply(d: Def[_]): Nullable[Ref[A] forSome {type A}] = d match { - case ApplyUnOp(_: NumericToLong[_], x) => Nullable(x.asInstanceOf[Ref[A] forSome {type A}]) - case _ => Nullable.None - } - } - - override def rewriteDef[T](d: Def[T]) = d match { - case CM.length(ys) => ys.node match { - // Rule: xs.map(f).length ==> xs.length - case CM.map(xs, _) => - xs.length - // Rule: replicate(len, v).length => len - case CBM.replicate(_, len, _) => - len - // Rule: Const[Coll[T]](coll).length => - case CollConst(coll, _) => - coll.length - // Rule: Coll(items @ Seq(x1, x2, x3)).length => items.length - case CBM.fromItems(_, items, _) => - items.length - case _ => super.rewriteDef(d) - } - - // Rule: replicate(l, x).zip(replicate(l, y)) ==> replicate(l, (x,y)) - case CM.zip(CBM.replicate(b1, l1, v1), CBM.replicate(b2, l2, v2)) if b1 == b2 && l1 == l2 => - b1.replicate(l1, Pair(v1, v2)) - - case CM.map(xs, _f) => _f.node match { - case IdentityLambda() => xs - case _ => xs.node match { - // Rule: replicate(l, v).map(f) ==> replicate(l, f(v)) - case CBM.replicate(b, l, v: Ref[a]) => - val f = asRep[a => Any](_f) - b.replicate(l, Apply(f, v, false)) - - // Rule: xs.map(f).map(g) ==> xs.map(x => g(f(x))) - case CM.map(_xs, f: RFunc[a, b]) => - implicit val ea = f.elem.eDom - val xs = asRep[Coll[a]](_xs) - val g = asRep[b => Any](_f) - xs.map[Any](fun { x: Ref[a] => g(f(x)) }) - - case _ => super.rewriteDef(d) - } - } - - case WOptionM.getOrElse(opt, _) => opt.node match { - // Rule: Some(x).getOrElse(_) ==> x - case SPCM.some(x) => x - case WOptionConst(Some(x), lA) => lA.lift(x) - case _ => super.rewriteDef(d) - } - - case _ => super.rewriteDef(d) - } - - override def invokeUnlifted(e: Elem[_], mc: MethodCall, dataEnv: DataEnv): Any = e match { - case _: CollElem[_,_] => mc match { - case CollMethods.map(_, f) => - val newMC = mc.copy(args = mc.args :+ f.elem.eRange)(mc.resultType, mc.isAdapterCall) - super.invokeUnlifted(e, newMC, dataEnv) - case _ => - super.invokeUnlifted(e, mc, dataEnv) - } - case _ => - super.invokeUnlifted(e, mc, dataEnv) - } - -} - diff --git a/sc/shared/src/main/scala/sigma/compiler/TreeBuilding.scala b/sc/shared/src/main/scala/sigma/compiler/TreeBuilding.scala index f781215901..de6437645f 100644 --- a/sc/shared/src/main/scala/sigma/compiler/TreeBuilding.scala +++ b/sc/shared/src/main/scala/sigma/compiler/TreeBuilding.scala @@ -22,7 +22,7 @@ import scala.collection.mutable.ArrayBuffer * * @see buildTree method * */ -trait TreeBuilding extends Base { IR: Scalan => +trait TreeBuilding extends Base { IR: IRContext => import BigInt._ import Box._ import Coll._ diff --git a/sc/shared/src/main/scala/sigma/compiler/TypeDescs.scala b/sc/shared/src/main/scala/sigma/compiler/TypeDescs.scala index 875c3f7b9a..6e2de8d952 100644 --- a/sc/shared/src/main/scala/sigma/compiler/TypeDescs.scala +++ b/sc/shared/src/main/scala/sigma/compiler/TypeDescs.scala @@ -12,7 +12,7 @@ import scala.collection.immutable.ListMap import scala.collection.mutable import scala.language.implicitConversions -abstract class TypeDescs extends Base { self: Scalan => +abstract class TypeDescs extends Base { self: IRContext => /** Helper type case method. */ @inline final def asElem[T](d: TypeDesc): Elem[T] = d.asInstanceOf[Elem[T]] diff --git a/sc/shared/src/main/scala/sigma/compiler/primitives/Equal.scala b/sc/shared/src/main/scala/sigma/compiler/primitives/Equal.scala index f0aab234b2..fc6e67fbfd 100644 --- a/sc/shared/src/main/scala/sigma/compiler/primitives/Equal.scala +++ b/sc/shared/src/main/scala/sigma/compiler/primitives/Equal.scala @@ -1,10 +1,10 @@ package sigma.compiler.primitives -import sigma.compiler.{Base, Scalan} +import sigma.compiler.{Base, IRContext} import scala.annotation.unused -trait Equal extends Base { self: Scalan => +trait Equal extends Base { self: IRContext => /** Binary operation representing structural equality between arguments. */ case class Equals[A: Elem]() extends BinOp[A, Boolean]("==") { override def applySeq(x: A, y: A): Boolean = equalValues[A](x, y) diff --git a/sc/shared/src/main/scala/sigma/compiler/primitives/Functions.scala b/sc/shared/src/main/scala/sigma/compiler/primitives/Functions.scala index f572f2b126..dce2578d4f 100644 --- a/sc/shared/src/main/scala/sigma/compiler/primitives/Functions.scala +++ b/sc/shared/src/main/scala/sigma/compiler/primitives/Functions.scala @@ -2,14 +2,14 @@ package sigma.compiler.primitives import debox.{cfor, Buffer => DBuffer} import sigma.compiler.staged.ProgramGraphs -import sigma.compiler.{Base, Scalan} +import sigma.compiler.{Base, IRContext} import sigma.data.{Lazy, Nullable, emptyDBufferOfInt} import sigma.util.GraphUtil import java.util import scala.language.implicitConversions -trait Functions extends Base with ProgramGraphs { self: Scalan => +trait Functions extends Base with ProgramGraphs { self: IRContext => implicit class LambdaOps[A,B](f: Ref[A => B]) { /** Apply given function symbol to the given argument symbol. diff --git a/sc/shared/src/main/scala/sigma/compiler/primitives/IfThenElse.scala b/sc/shared/src/main/scala/sigma/compiler/primitives/IfThenElse.scala index 57d742b194..e09036fcaf 100644 --- a/sc/shared/src/main/scala/sigma/compiler/primitives/IfThenElse.scala +++ b/sc/shared/src/main/scala/sigma/compiler/primitives/IfThenElse.scala @@ -1,8 +1,8 @@ package sigma.compiler.primitives -import sigma.compiler.{Base, Scalan} +import sigma.compiler.{Base, IRContext} -trait IfThenElse extends Base { self: Scalan => +trait IfThenElse extends Base { self: IRContext => /** If c then t else e construction with standard lazy evaluation of branches. * The representation uses Thunk for each branch */ diff --git a/sc/shared/src/main/scala/sigma/compiler/primitives/LogicalOps.scala b/sc/shared/src/main/scala/sigma/compiler/primitives/LogicalOps.scala index 16510eb1fa..faf186bf04 100644 --- a/sc/shared/src/main/scala/sigma/compiler/primitives/LogicalOps.scala +++ b/sc/shared/src/main/scala/sigma/compiler/primitives/LogicalOps.scala @@ -1,9 +1,9 @@ package sigma.compiler.primitives -import sigma.compiler.{Base, Scalan} +import sigma.compiler.{Base, IRContext} /** Slice in Scala cake with definitions of logical operations. */ -trait LogicalOps extends Base { self: Scalan => +trait LogicalOps extends Base { self: IRContext => /** Logical AND binary operation. */ val And = new EndoBinOp[Boolean]("&&") { override def applySeq(x: Boolean, y: Boolean): Boolean = x && y diff --git a/sc/shared/src/main/scala/sigma/compiler/primitives/NumericOps.scala b/sc/shared/src/main/scala/sigma/compiler/primitives/NumericOps.scala index 8783df2ce1..de3f2e6fed 100644 --- a/sc/shared/src/main/scala/sigma/compiler/primitives/NumericOps.scala +++ b/sc/shared/src/main/scala/sigma/compiler/primitives/NumericOps.scala @@ -1,10 +1,10 @@ package sigma.compiler.primitives -import sigma.compiler.{Base, Scalan} +import sigma.compiler.{Base, IRContext} import sigma.data.{ExactIntegral, ExactNumeric} /** Slice in Scala cake with definitions of numeric operations. */ -trait NumericOps extends Base { self: Scalan => +trait NumericOps extends Base { self: IRContext => /** Extension methods over `Ref[T]` where T is instance of ExactNumeric type-class. */ implicit class NumericOpsCls[T](x: Ref[T])(implicit val n: ExactNumeric[T]) { diff --git a/sc/shared/src/main/scala/sigma/compiler/primitives/OrderingOps.scala b/sc/shared/src/main/scala/sigma/compiler/primitives/OrderingOps.scala index d125787d07..31d4c88365 100644 --- a/sc/shared/src/main/scala/sigma/compiler/primitives/OrderingOps.scala +++ b/sc/shared/src/main/scala/sigma/compiler/primitives/OrderingOps.scala @@ -1,12 +1,12 @@ package sigma.compiler.primitives -import sigma.compiler.{Base, Scalan} +import sigma.compiler.{Base, IRContext} import sigma.data.ExactOrdering import scala.language.implicitConversions /** Slice in Scala cake with definitions of comparison operations. */ -trait OrderingOps extends Base { self: Scalan => +trait OrderingOps extends Base { self: IRContext => implicit def repOrderingToOrderingOps[T](x: Ref[T])(implicit n: ExactOrdering[T]) = new OrderingOpsCls(x) implicit def OrderingToOrderingOps[T](x: T)(implicit n: ExactOrdering[T], et: Elem[T]) = new OrderingOpsCls(toRep(x)) diff --git a/sc/shared/src/main/scala/sigma/compiler/primitives/Thunks.scala b/sc/shared/src/main/scala/sigma/compiler/primitives/Thunks.scala index 24b9e97708..2b5c97fcba 100644 --- a/sc/shared/src/main/scala/sigma/compiler/primitives/Thunks.scala +++ b/sc/shared/src/main/scala/sigma/compiler/primitives/Thunks.scala @@ -2,7 +2,7 @@ package sigma.compiler.primitives import debox.{cfor, Buffer => DBuffer, Set => DSet} import scalan.core.Covariant -import sigma.compiler.Scalan +import sigma.compiler.IRContext import sigma.data.{AVHashMap, DFunc, Lazy, Nullable, RType} import sigma.reflection.RClass import sigma.util.GraphUtil @@ -10,12 +10,13 @@ import sigma.util.GraphUtil import scala.collection.Seq import scala.language.{existentials, implicitConversions} -/** Slice in the [[Scalan]] cake with definitions of Thunk operations. +/** Slice in the [[IRContext]] cake with definitions of Thunk operations. * See https://en.wikipedia.org/wiki/Thunk. * Thunks are used to represent lazy operations in the graph IR. + * * @see ApplyBinOpLazy, IfThenElseLazy */ -trait Thunks extends Functions { self: Scalan => +trait Thunks extends Functions { self: IRContext => type Th[+T] = Ref[Thunk[T]] diff --git a/sc/shared/src/main/scala/sigma/compiler/primitives/Tuples.scala b/sc/shared/src/main/scala/sigma/compiler/primitives/Tuples.scala index ae30569c29..d0455d0106 100644 --- a/sc/shared/src/main/scala/sigma/compiler/primitives/Tuples.scala +++ b/sc/shared/src/main/scala/sigma/compiler/primitives/Tuples.scala @@ -4,12 +4,12 @@ */ package sigma.compiler.primitives -import sigma.compiler.{Base, Scalan} +import sigma.compiler.{Base, IRContext} import sigma.data.AVHashMap import scala.language.implicitConversions -trait Tuples extends Base { self: Scalan => +trait Tuples extends Base { self: IRContext => object Pair { def apply[A, B](a: Ref[A], b: Ref[B]) = zipPair[A, B]((a, b)) def unapply[A, B](p: Ref[(A, B)]) = Some(unzipPair[A, B](p)) diff --git a/sc/shared/src/main/scala/sigma/compiler/primitives/UnBinOps.scala b/sc/shared/src/main/scala/sigma/compiler/primitives/UnBinOps.scala index 701239488d..4bb9b6b9ab 100644 --- a/sc/shared/src/main/scala/sigma/compiler/primitives/UnBinOps.scala +++ b/sc/shared/src/main/scala/sigma/compiler/primitives/UnBinOps.scala @@ -1,8 +1,8 @@ package sigma.compiler.primitives -import sigma.compiler.{Base, Scalan} +import sigma.compiler.{Base, IRContext} -trait UnBinOps extends Base { self: Scalan => +trait UnBinOps extends Base { self: IRContext => /** Base class for descriptors of unary operations. */ abstract class UnOp[A, R](val opName: String)(implicit val eResult: Elem[R]) { diff --git a/sc/shared/src/main/scala/sigma/compiler/primitives/UniversalOps.scala b/sc/shared/src/main/scala/sigma/compiler/primitives/UniversalOps.scala index c6dd96f03b..b83e152b4f 100644 --- a/sc/shared/src/main/scala/sigma/compiler/primitives/UniversalOps.scala +++ b/sc/shared/src/main/scala/sigma/compiler/primitives/UniversalOps.scala @@ -1,8 +1,8 @@ package sigma.compiler.primitives -import sigma.compiler.{Base, Scalan} +import sigma.compiler.{Base, IRContext} -trait UniversalOps extends Base { scalan: Scalan => +trait UniversalOps extends Base { self: IRContext => case class HashCode[A]() extends UnOp[A, Int]("hashCode") { override def applySeq(x: A): Int = x.hashCode } diff --git a/sc/shared/src/main/scala/sigma/compiler/staged/AstGraphs.scala b/sc/shared/src/main/scala/sigma/compiler/staged/AstGraphs.scala index 09000db191..5ee20810fa 100644 --- a/sc/shared/src/main/scala/sigma/compiler/staged/AstGraphs.scala +++ b/sc/shared/src/main/scala/sigma/compiler/staged/AstGraphs.scala @@ -1,13 +1,13 @@ package sigma.compiler.staged import debox.{cfor, Buffer => DBuffer, Map => DMap, Set => DSet} -import sigma.compiler.Scalan +import sigma.compiler.IRContext import sigma.data.emptyDBufferOfInt import scala.collection._ -trait AstGraphs extends Transforming { self: Scalan => +trait AstGraphs extends Transforming { self: IRContext => /** GraphNode is created for each symbol of the AstGraph and represents graph linking structure */ case class GraphNode( diff --git a/sc/shared/src/main/scala/sigma/compiler/staged/ProgramGraphs.scala b/sc/shared/src/main/scala/sigma/compiler/staged/ProgramGraphs.scala index 1c8617bc74..67220d1002 100644 --- a/sc/shared/src/main/scala/sigma/compiler/staged/ProgramGraphs.scala +++ b/sc/shared/src/main/scala/sigma/compiler/staged/ProgramGraphs.scala @@ -1,13 +1,13 @@ package sigma.compiler.staged import debox.{cfor, Buffer => DBuffer} -import sigma.compiler.Scalan +import sigma.compiler.IRContext import sigma.data.{DFunc, Nullable} import sigma.util.GraphUtil import scala.collection.compat.immutable.ArraySeq -trait ProgramGraphs extends AstGraphs { self: Scalan => +trait ProgramGraphs extends AstGraphs { self: IRContext => type PGraph = ProgramGraph diff --git a/sc/shared/src/main/scala/sigma/compiler/staged/Transforming.scala b/sc/shared/src/main/scala/sigma/compiler/staged/Transforming.scala index 90cc2dd350..6d729d35d0 100644 --- a/sc/shared/src/main/scala/sigma/compiler/staged/Transforming.scala +++ b/sc/shared/src/main/scala/sigma/compiler/staged/Transforming.scala @@ -1,14 +1,14 @@ package sigma.compiler.staged import debox.{cfor, Buffer => DBuffer} -import sigma.compiler.Scalan +import sigma.compiler.IRContext import sigma.data.{Lazy, Nullable} import sigma.reflection.RMethod import java.util import scala.language.existentials -trait Transforming { self: Scalan => +trait Transforming { self: IRContext => /** Descriptor of a current compiler pass. * Compiler can be configured to perform one pass after another. diff --git a/sc/shared/src/main/scala/sigmastate/lang/SigmaCompiler.scala b/sc/shared/src/main/scala/sigmastate/lang/SigmaCompiler.scala index 4392e97216..f12a385973 100644 --- a/sc/shared/src/main/scala/sigmastate/lang/SigmaCompiler.scala +++ b/sc/shared/src/main/scala/sigmastate/lang/SigmaCompiler.scala @@ -12,7 +12,7 @@ import sigmastate.lang.parsers.ParserException import sigma.ast._ import sigma.ast.syntax.SValue import SCollectionMethods.{ExistsMethod, ForallMethod, MapMethod} -import sigma.compiler.{GraphIRReflection, Scalan} +import sigma.compiler.{GraphIRReflection, IRContext} import sigmastate.InterpreterReflection /** @@ -37,7 +37,7 @@ case class CompilerSettings( * @param compiledGraph graph obtained by using new [[GraphBuilding]] * @param buildTree ErgoTree expression obtained from graph created by [[GraphBuilding]] */ -case class CompilerResult[Ctx <: Scalan]( +case class CompilerResult[Ctx <: IRContext]( env: ScriptEnv, code: String, compiledGraph: Ctx#Ref[Ctx#Context => Any], @@ -83,14 +83,14 @@ class SigmaCompiler private(settings: CompilerSettings) { } /** Compiles the given ErgoScript source code. */ - def compile(env: ScriptEnv, code: String)(implicit IR: Scalan): CompilerResult[IR.type] = { + def compile(env: ScriptEnv, code: String)(implicit IR: IRContext): CompilerResult[IR.type] = { val typed = typecheck(env, code) val res = compileTyped(env, typed).copy(code = code) res } /** Compiles the given typed expression. */ - def compileTyped(env: ScriptEnv, typedExpr: SValue)(implicit IR: Scalan): CompilerResult[IR.type] = { + def compileTyped(env: ScriptEnv, typedExpr: SValue)(implicit IR: IRContext): CompilerResult[IR.type] = { val placeholdersEnv = env .collect { case (name, t: SType) => name -> t } .zipWithIndex @@ -102,7 +102,7 @@ class SigmaCompiler private(settings: CompilerSettings) { } /** Compiles the given parsed contract source. */ - def compileParsed(env: ScriptEnv, parsedExpr: SValue)(implicit IR: Scalan): CompilerResult[IR.type] = { + def compileParsed(env: ScriptEnv, parsedExpr: SValue)(implicit IR: IRContext): CompilerResult[IR.type] = { val typed = typecheck(env, parsedExpr) compileTyped(env, typed) } diff --git a/sc/shared/src/main/scala/special/collection/CollsUnit.scala b/sc/shared/src/main/scala/special/collection/CollsUnit.scala index a057f40f7a..53bf6f0530 100644 --- a/sc/shared/src/main/scala/special/collection/CollsUnit.scala +++ b/sc/shared/src/main/scala/special/collection/CollsUnit.scala @@ -1,6 +1,5 @@ package sigma { - import scalan._ - import sigma.compiler.{Base, Scalan} + import sigma.compiler.{Base, IRContext} /** Staged version of collection interfaces which is used in graph-based IR to represent * methods of Coll and CollBuilder. @@ -9,7 +8,7 @@ package sigma { * The semantics of each method is the same as in the original class, please look there * for details. */ - trait Colls extends Base { self: Scalan => + trait Colls extends Base { self: IRContext => trait Coll[A] extends Def[Coll[A]] { implicit def eA: Elem[A]; def length: Ref[Int]; diff --git a/sc/shared/src/main/scala/special/collection/impl/CollsImpl.scala b/sc/shared/src/main/scala/special/collection/impl/CollsImpl.scala index c85621bbbe..a14b2eb3b4 100644 --- a/sc/shared/src/main/scala/special/collection/impl/CollsImpl.scala +++ b/sc/shared/src/main/scala/special/collection/impl/CollsImpl.scala @@ -2,18 +2,18 @@ package sigma import scala.language.{existentials, implicitConversions} import scalan._ -import sigma.compiler.Scalan +import sigma.compiler.IRContext import scala.collection.compat.immutable.ArraySeq package impl { - import sigma.compiler.{Base, GraphIRReflection, ModuleInfo, Scalan} + import sigma.compiler.{Base, GraphIRReflection, ModuleInfo, IRContext} import sigma.data.{Nullable, RType} import sigma.reflection.{RClass, RMethod} // Abs ----------------------------------- trait CollsDefs extends Base with Colls { - self: Scalan => + self: IRContext => registerModule(CollsModule) @@ -642,4 +642,4 @@ object CollsModule extends ModuleInfo("sigma", "Colls") { } } -trait CollsModule extends sigma.impl.CollsDefs {self: Scalan =>} +trait CollsModule extends sigma.impl.CollsDefs {self: IRContext =>} diff --git a/sc/shared/src/main/scala/special/sigma/SigmaDslUnit.scala b/sc/shared/src/main/scala/special/sigma/SigmaDslUnit.scala index 6cc97daba6..a6fb60870c 100644 --- a/sc/shared/src/main/scala/special/sigma/SigmaDslUnit.scala +++ b/sc/shared/src/main/scala/special/sigma/SigmaDslUnit.scala @@ -1,8 +1,8 @@ package sigma { import scalan._ - import sigma.compiler.{Base, Scalan} + import sigma.compiler.{Base, IRContext} - trait SigmaDsl extends Base { self: Scalan => + trait SigmaDsl extends Base { self: IRContext => trait BigInt extends Def[BigInt] { def add(that: Ref[BigInt]): Ref[BigInt]; def subtract(that: Ref[BigInt]): Ref[BigInt]; diff --git a/sc/shared/src/main/scala/special/sigma/impl/SigmaDslImpl.scala b/sc/shared/src/main/scala/special/sigma/impl/SigmaDslImpl.scala index 760f5094ca..a76ddb47d4 100644 --- a/sc/shared/src/main/scala/special/sigma/impl/SigmaDslImpl.scala +++ b/sc/shared/src/main/scala/special/sigma/impl/SigmaDslImpl.scala @@ -2,18 +2,18 @@ package sigma import scala.language.{existentials, implicitConversions} import scalan._ -import sigma.compiler.Scalan +import sigma.compiler.IRContext import scala.collection.compat.immutable.ArraySeq package impl { - import sigma.compiler.{Base, GraphIRReflection, ModuleInfo, Scalan} + import sigma.compiler.{Base, GraphIRReflection, ModuleInfo, IRContext} import sigma.data.{Nullable, RType} import sigma.reflection.{RClass, RMethod} // Abs ----------------------------------- trait SigmaDslDefs extends Base with SigmaDsl { - self: Scalan => + self: IRContext => registerModule(SigmaDslModule) @@ -2326,4 +2326,4 @@ object SigmaDslModule extends ModuleInfo("sigma", "SigmaDsl") { } } -trait SigmaDslModule extends sigma.impl.SigmaDslDefs {self: Scalan =>} +trait SigmaDslModule extends sigma.impl.SigmaDslDefs {self: IRContext =>} diff --git a/sc/shared/src/main/scala/special/sigma/wrappers/WrappersModule.scala b/sc/shared/src/main/scala/special/sigma/wrappers/WrappersModule.scala index 1250487071..6620d9db8f 100644 --- a/sc/shared/src/main/scala/special/sigma/wrappers/WrappersModule.scala +++ b/sc/shared/src/main/scala/special/sigma/wrappers/WrappersModule.scala @@ -1,6 +1,6 @@ package sigma.wrappers -import sigma.compiler.Scalan +import sigma.compiler.IRContext trait WrappersModule - extends special.wrappers.WrappersModule { self: Scalan => } + extends special.wrappers.WrappersModule { self: IRContext => } diff --git a/sc/shared/src/main/scala/special/wrappers/WrappersModule.scala b/sc/shared/src/main/scala/special/wrappers/WrappersModule.scala index 1a25f6a9d4..0d67f6147a 100644 --- a/sc/shared/src/main/scala/special/wrappers/WrappersModule.scala +++ b/sc/shared/src/main/scala/special/wrappers/WrappersModule.scala @@ -1,6 +1,6 @@ package special.wrappers -import sigma.compiler.Scalan +import sigma.compiler.IRContext import wrappers.scala.WOptionsModule import wrappers.scalan.WRTypesModule import wrappers.special.WSpecialPredefsModule @@ -8,4 +8,4 @@ import wrappers.special.WSpecialPredefsModule trait WrappersModule extends WSpecialPredefsModule with WOptionsModule - with WRTypesModule { self: Scalan => } \ No newline at end of file + with WRTypesModule { self: IRContext => } \ No newline at end of file diff --git a/sc/shared/src/main/scala/wrappers/scala/WOptions.scala b/sc/shared/src/main/scala/wrappers/scala/WOptions.scala index 830d05233f..4f41d0d025 100644 --- a/sc/shared/src/main/scala/wrappers/scala/WOptions.scala +++ b/sc/shared/src/main/scala/wrappers/scala/WOptions.scala @@ -1,9 +1,9 @@ package wrappers.scala { import scalan._ - import sigma.compiler.{Base, Scalan} + import sigma.compiler.{Base, IRContext} import special.wrappers.WrappersModule - trait WOptions extends Base { self: Scalan => + trait WOptions extends Base { self: IRContext => trait WOption[A] extends Def[WOption[A]] { implicit def eA: Elem[A]; def isDefined: Ref[Boolean]; diff --git a/sc/shared/src/main/scala/wrappers/scala/impl/WOptionsImpl.scala b/sc/shared/src/main/scala/wrappers/scala/impl/WOptionsImpl.scala index b1006c4e9f..915a271de9 100644 --- a/sc/shared/src/main/scala/wrappers/scala/impl/WOptionsImpl.scala +++ b/sc/shared/src/main/scala/wrappers/scala/impl/WOptionsImpl.scala @@ -2,20 +2,20 @@ package wrappers.scala import scala.language.{existentials, implicitConversions} import scalan._ -import sigma.compiler.Scalan +import sigma.compiler.IRContext import special.wrappers.WrappersModule import special.wrappers.OptionWrapSpec import scala.collection.compat.immutable.ArraySeq package impl { - import sigma.compiler.{Base, GraphIRReflection, ModuleInfo, Scalan} + import sigma.compiler.{Base, GraphIRReflection, ModuleInfo, IRContext} import sigma.data.{Nullable, RType} import sigma.reflection.{RClass, RMethod} // Abs ----------------------------------- trait WOptionsDefs extends Base with WOptions { - self: Scalan => + self: IRContext => class WOptionCls extends EntityObject("WOption") { // entityConst: single const for each entity @@ -243,4 +243,4 @@ object WOptionsModule extends ModuleInfo("wrappers.scala", "WOptions") { } } -trait WOptionsModule extends wrappers.scala.impl.WOptionsDefs {self: Scalan =>} +trait WOptionsModule extends wrappers.scala.impl.WOptionsDefs {self: IRContext =>} diff --git a/sc/shared/src/main/scala/wrappers/scalan/WRTypes.scala b/sc/shared/src/main/scala/wrappers/scalan/WRTypes.scala index 204fa40957..99f87242df 100644 --- a/sc/shared/src/main/scala/wrappers/scalan/WRTypes.scala +++ b/sc/shared/src/main/scala/wrappers/scalan/WRTypes.scala @@ -1,9 +1,9 @@ package wrappers.scalan { import scalan._ - import sigma.compiler.{Base, Scalan} + import sigma.compiler.{Base, IRContext} - trait WRTypes extends Base { self: Scalan => + trait WRTypes extends Base { self: IRContext => trait WRType[A] extends Def[WRType[A]] { implicit def eA: Elem[A]; def name: Ref[String] diff --git a/sc/shared/src/main/scala/wrappers/scalan/impl/WRTypesImpl.scala b/sc/shared/src/main/scala/wrappers/scalan/impl/WRTypesImpl.scala index 7868546bb9..55923c757b 100644 --- a/sc/shared/src/main/scala/wrappers/scalan/impl/WRTypesImpl.scala +++ b/sc/shared/src/main/scala/wrappers/scalan/impl/WRTypesImpl.scala @@ -1,6 +1,6 @@ package wrappers.scalan -import sigma.compiler.Scalan +import sigma.compiler.IRContext import scala.language.{existentials, implicitConversions} import sigma.data.RType import special.wrappers.RTypeWrapSpec @@ -8,12 +8,12 @@ import special.wrappers.RTypeWrapSpec import scala.collection.compat.immutable.ArraySeq package impl { - import sigma.compiler.{Base, GraphIRReflection, ModuleInfo, Scalan} + import sigma.compiler.{Base, GraphIRReflection, ModuleInfo, IRContext} import sigma.reflection.{RClass, RMethod} // Abs ----------------------------------- trait WRTypesDefs extends Base with WRTypes { - self: Scalan => + self: IRContext => registerModule(WRTypesModule) @@ -117,4 +117,4 @@ object WRTypesModule extends ModuleInfo("wrappers.scalan", "WRTypes") { } } -trait WRTypesModule extends wrappers.scalan.impl.WRTypesDefs {self: Scalan =>} +trait WRTypesModule extends wrappers.scalan.impl.WRTypesDefs {self: IRContext =>} diff --git a/sc/shared/src/main/scala/wrappers/special/WSpecialPredefs.scala b/sc/shared/src/main/scala/wrappers/special/WSpecialPredefs.scala index 3c71796c47..33f39f2458 100644 --- a/sc/shared/src/main/scala/wrappers/special/WSpecialPredefs.scala +++ b/sc/shared/src/main/scala/wrappers/special/WSpecialPredefs.scala @@ -1,8 +1,8 @@ package wrappers.special { import scalan._ - import sigma.compiler.{Base, Scalan} + import sigma.compiler.{Base, IRContext} - trait WSpecialPredefs extends Base { self: Scalan => + trait WSpecialPredefs extends Base { self: IRContext => trait WSpecialPredef extends Def[WSpecialPredef]; trait WSpecialPredefCompanion { def some[A](x: Ref[A]): Ref[WOption[A]]; diff --git a/sc/shared/src/main/scala/wrappers/special/impl/WSpecialPredefsImpl.scala b/sc/shared/src/main/scala/wrappers/special/impl/WSpecialPredefsImpl.scala index 4bb7a13128..7ec5d9bb53 100644 --- a/sc/shared/src/main/scala/wrappers/special/impl/WSpecialPredefsImpl.scala +++ b/sc/shared/src/main/scala/wrappers/special/impl/WSpecialPredefsImpl.scala @@ -2,17 +2,16 @@ package wrappers.special import scala.language.{existentials, implicitConversions} import scalan._ -import sigma.compiler.Scalan -import special.wrappers.WrappersModule +import sigma.compiler.IRContext package impl { - import sigma.compiler.{Base, GraphIRReflection, ModuleInfo, Scalan} + import sigma.compiler.{Base, GraphIRReflection, ModuleInfo, IRContext} import sigma.data.Nullable import sigma.reflection.RClass // Abs ----------------------------------- trait WSpecialPredefsDefs extends Base with WSpecialPredefs { - self: Scalan => + self: IRContext => registerModule(WSpecialPredefsModule) @@ -68,4 +67,4 @@ object WSpecialPredefsModule extends ModuleInfo("wrappers.special", "WSpecialPre } } -trait WSpecialPredefsModule extends wrappers.special.impl.WSpecialPredefsDefs {self: Scalan =>} +trait WSpecialPredefsModule extends wrappers.special.impl.WSpecialPredefsDefs {self: IRContext =>} diff --git a/sc/shared/src/test/scala/org/ergoplatform/dsl/TestContractSpec.scala b/sc/shared/src/test/scala/org/ergoplatform/dsl/TestContractSpec.scala index 0c8bb83e56..b6abfc1391 100644 --- a/sc/shared/src/test/scala/org/ergoplatform/dsl/TestContractSpec.scala +++ b/sc/shared/src/test/scala/org/ergoplatform/dsl/TestContractSpec.scala @@ -20,9 +20,9 @@ import sigmastate.helpers.TestingHelpers._ import sigma.ast.syntax.ValueOps import sigma.{AnyValue, Evaluation, SigmaProp} import ErgoTree.ZeroHeader -import sigma.compiler.Scalan +import sigma.compiler.IRContext -case class TestContractSpec(testSuite: CompilerTestingCommons)(implicit val IR: Scalan) extends ContractSpec { +case class TestContractSpec(testSuite: CompilerTestingCommons)(implicit val IR: IRContext) extends ContractSpec { case class TestPropositionSpec(name: String, dslSpec: Proposition, scriptSpec: ErgoScript) extends PropositionSpec { lazy val ergoTree: ErgoTree = { diff --git a/sc/shared/src/test/scala/scalan/BaseLiftableTests.scala b/sc/shared/src/test/scala/scalan/BaseLiftableTests.scala index 120c15dfe6..ae1cc75e73 100644 --- a/sc/shared/src/test/scala/scalan/BaseLiftableTests.scala +++ b/sc/shared/src/test/scala/scalan/BaseLiftableTests.scala @@ -1,10 +1,10 @@ package scalan -import sigma.compiler.Scalan +import sigma.compiler.IRContext trait BaseLiftableTests { self: BaseCtxTests => - trait LiftableTestKit { scalan: Scalan => + trait LiftableTestKit { scalan: IRContext => import Liftables._ /** Check the MethodCall reified in f can be mapped to unlifted method which can be invoked.*/ diff --git a/sc/shared/src/test/scala/scalan/LibraryTests.scala b/sc/shared/src/test/scala/scalan/LibraryTests.scala index a6844070eb..ef7c9f8b07 100644 --- a/sc/shared/src/test/scala/scalan/LibraryTests.scala +++ b/sc/shared/src/test/scala/scalan/LibraryTests.scala @@ -1,9 +1,9 @@ package scalan -import sigma.compiler.Scalan +import sigma.compiler.IRContext import sigma.util.BenchmarkUtil.{measure, measureTime} -class Benchmark[T <: Scalan](createContext: => T) { +class Benchmark[T <: IRContext](createContext: => T) { val printDebugInfo: Boolean = false def run() = { diff --git a/sc/shared/src/test/scala/scalan/TestContexts.scala b/sc/shared/src/test/scala/scalan/TestContexts.scala index 39649b541a..8a0caae69f 100644 --- a/sc/shared/src/test/scala/scalan/TestContexts.scala +++ b/sc/shared/src/test/scala/scalan/TestContexts.scala @@ -1,12 +1,12 @@ package scalan -import sigma.compiler.{GraphIRReflection, Scalan} +import sigma.compiler.{GraphIRReflection, IRContext} import sigma.reflection.RMethod import sigma.{BaseNestedTests, BaseShouldTests, BaseTests, TestUtils} trait TestContexts extends TestUtils { - trait TestContextApi { scalan: Scalan => + trait TestContextApi { ctx: IRContext => def invokeAll: Boolean def isInvokeEnabled(d: Def[_], m: RMethod): Boolean def shouldUnpack(e: Elem[_]): Boolean @@ -20,7 +20,7 @@ trait TestContexts extends TestUtils { emitF(testName, Seq(() => s1) ++ s2.map((s: Ref[_]) => () => s): _*) } } - abstract class TestContext(val testName: String) extends Scalan with TestContextApi { + abstract class TestContext(val testName: String) extends IRContext with TestContextApi { def this() = this(currentTestNameAsFileName) override val invokeAll = true diff --git a/sc/shared/src/test/scala/scalan/TestLibrary.scala b/sc/shared/src/test/scala/scalan/TestLibrary.scala index 2c4c355cb8..91eb2d2e0b 100644 --- a/sc/shared/src/test/scala/scalan/TestLibrary.scala +++ b/sc/shared/src/test/scala/scalan/TestLibrary.scala @@ -1,8 +1,8 @@ package scalan -import sigma.compiler.{GraphIRReflection, Scalan} +import sigma.compiler.{GraphIRReflection, IRContext} -trait TestLibrary extends Scalan { +trait TestLibrary extends IRContext { import CollBuilder._ import SigmaDslBuilder._ val reflection = (GraphIRReflection) diff --git a/sc/shared/src/test/scala/sigma/CollsStagingTests.scala b/sc/shared/src/test/scala/sigma/CollsStagingTests.scala index f0d74f40e9..82e77937fe 100644 --- a/sc/shared/src/test/scala/sigma/CollsStagingTests.scala +++ b/sc/shared/src/test/scala/sigma/CollsStagingTests.scala @@ -3,7 +3,7 @@ package sigma import scala.language.reflectiveCalls import special.wrappers.WrappersTests import scalan._ -import sigma.compiler.Scalan +import sigma.compiler.IRContext import sigma.data.CollOverArrayBuilder class CollsStagingTests extends WrappersTests { @@ -42,7 +42,7 @@ class CollsStagingTests extends WrappersTests { } test("invokeUnlifted for Col") { - val ctx = new WrappersCtx with Scalan + val ctx = new WrappersCtx with IRContext import ctx._ import Coll._ import CollBuilder._ @@ -60,7 +60,7 @@ class CollsStagingTests extends WrappersTests { } test("invokeUnlifted for method of Ctor") { - val ctx = new WrappersCtx with Scalan + val ctx = new WrappersCtx with IRContext import ctx._ import Coll._ import CollBuilder._ diff --git a/sc/shared/src/test/scala/sigma/SigmaDslStaginTests.scala b/sc/shared/src/test/scala/sigma/SigmaDslStaginTests.scala index 90eefab5e0..5b951bec38 100644 --- a/sc/shared/src/test/scala/sigma/SigmaDslStaginTests.scala +++ b/sc/shared/src/test/scala/sigma/SigmaDslStaginTests.scala @@ -2,7 +2,7 @@ package sigma import org.scalatest.BeforeAndAfterAll import scalan.{BaseCtxTests, BaseLiftableTests} -import sigma.compiler.Scalan +import sigma.compiler.IRContext import sigma.data.TrivialProp import sigma.eval.Extensions.toAnyValue import sigmastate.eval._ @@ -10,7 +10,7 @@ import sigmastate.eval._ import scala.language.reflectiveCalls class SigmaDslStaginTests extends BaseCtxTests with ErgoScriptTestkit with BaseLiftableTests with BeforeAndAfterAll { - class Ctx extends TestContext with Scalan with LiftableTestKit { + class Ctx extends TestContext with IRContext with LiftableTestKit { } test("invokeUnlifted") { diff --git a/sc/shared/src/test/scala/sigma/SigmaDslTesting.scala b/sc/shared/src/test/scala/sigma/SigmaDslTesting.scala index 4acb6e0f75..11dd9b7e68 100644 --- a/sc/shared/src/test/scala/sigma/SigmaDslTesting.scala +++ b/sc/shared/src/test/scala/sigma/SigmaDslTesting.scala @@ -31,7 +31,7 @@ import sigmastate.helpers.{CompilerTestingCommons, ErgoLikeContextTesting, ErgoL import sigmastate.interpreter.Interpreter.{ScriptEnv, VerificationResult} import sigmastate.interpreter._ import sigma.ast.Apply -import sigma.compiler.{CompiletimeIRContext, Scalan} +import sigma.compiler.{CompiletimeIRContext, IRContext} import sigma.eval.Extensions.SigmaBooleanOps import sigma.interpreter.{ContextExtension, ProverResult} import sigma.serialization.ValueSerializer @@ -55,7 +55,7 @@ class SigmaDslTesting extends AnyPropSpec override def contractEnv: ScriptEnv = Map() - def createIR(): Scalan = new TestingIRContext { + def createIR(): IRContext = new TestingIRContext { override val okMeasureOperationTime: Boolean = true } @@ -496,7 +496,7 @@ class SigmaDslTesting extends AnyPropSpec expectedExpr: Option[SValue], printExpectedExpr: Boolean = true, logScript: Boolean = LogScriptDefault - )(implicit IR: Scalan, val tA: RType[A], val tB: RType[B], + )(implicit IR: IRContext, val tA: RType[A], val tB: RType[B], override val evalSettings: EvalSettings) extends Feature[A, B] { implicit val cs = compilerSettingsInTests @@ -666,7 +666,7 @@ class SigmaDslTesting extends AnyPropSpec logScript: Boolean = LogScriptDefault, allowNewToSucceed: Boolean = false, override val allowDifferentErrors: Boolean = false - )(implicit IR: Scalan, override val evalSettings: EvalSettings, val tA: RType[A], val tB: RType[B]) + )(implicit IR: IRContext, override val evalSettings: EvalSettings, val tA: RType[A], val tB: RType[B]) extends Feature[A, B] { feature => implicit val cs = compilerSettingsInTests @@ -840,7 +840,7 @@ class SigmaDslTesting extends AnyPropSpec expectedExpr: Option[SValue], printExpectedExpr: Boolean = true, logScript: Boolean = LogScriptDefault - )(implicit IR: Scalan, override val evalSettings: EvalSettings, val tA: RType[A], val tB: RType[B]) + )(implicit IR: IRContext, override val evalSettings: EvalSettings, val tA: RType[A], val tB: RType[B]) extends Feature[A, B] { override def scalaFunc: A => B = { x => sys.error(s"Semantic Scala function is not defined for old implementation: $this") @@ -1013,7 +1013,7 @@ class SigmaDslTesting extends AnyPropSpec def existingFeature[A: RType, B: RType] (scalaFunc: A => B, script: String, expectedExpr: SValue = null) - (implicit IR: Scalan, evalSettings: EvalSettings): Feature[A, B] = { + (implicit IR: IRContext, evalSettings: EvalSettings): Feature[A, B] = { ExistingFeature( script, scalaFunc, Option(expectedExpr)) } @@ -1036,7 +1036,7 @@ class SigmaDslTesting extends AnyPropSpec expectedExpr: SValue = null, allowNewToSucceed: Boolean = false, allowDifferentErrors: Boolean = false) - (implicit IR: Scalan, evalSettings: EvalSettings): Feature[A, B] = { + (implicit IR: IRContext, evalSettings: EvalSettings): Feature[A, B] = { ChangedFeature(script, scalaFunc, scalaFuncNew, Option(expectedExpr), allowNewToSucceed = allowNewToSucceed, allowDifferentErrors = allowDifferentErrors) @@ -1053,7 +1053,7 @@ class SigmaDslTesting extends AnyPropSpec */ def newFeature[A: RType, B: RType] (scalaFunc: A => B, script: String, expectedExpr: SValue = null) - (implicit IR: Scalan, es: EvalSettings): Feature[A, B] = { + (implicit IR: IRContext, es: EvalSettings): Feature[A, B] = { NewFeature(script, scalaFunc, Option(expectedExpr)) } @@ -1151,7 +1151,7 @@ class SigmaDslTesting extends AnyPropSpec def benchmarkCases[A: Ordering : Arbitrary : ClassTag, B] (cases: Seq[A], f: Feature[A, B], nIters: Int, formatter: MeasureFormatter[A]) - (implicit IR: Scalan, evalSettings: EvalSettings): Seq[Long] = { + (implicit IR: IRContext, evalSettings: EvalSettings): Seq[Long] = { val fNew = f.newF implicit val tA = fNew.tA implicit val tB = fNew.tB diff --git a/sc/shared/src/test/scala/sigmastate/CompilerTestsBase.scala b/sc/shared/src/test/scala/sigmastate/CompilerTestsBase.scala index 0d00fef070..0a94ca85bd 100644 --- a/sc/shared/src/test/scala/sigmastate/CompilerTestsBase.scala +++ b/sc/shared/src/test/scala/sigmastate/CompilerTestsBase.scala @@ -7,7 +7,7 @@ import sigma.ast.{ErgoTree, SType, TransformingSigmaBuilder, Value} import org.ergoplatform.ErgoAddressEncoder.TestnetNetworkPrefix import sigma.ast.syntax.{SValue, SigmaPropValue} import sigma.serialization.ValueSerializer -import sigma.compiler.Scalan +import sigma.compiler.IRContext import sigma.ast.syntax.ValueOps import sigmastate.helpers.{NegativeTesting, SigmaPPrint} @@ -44,21 +44,21 @@ trait CompilerTestsBase extends TestsBase with NegativeTesting { } /** Compile the given code to ErgoTree expression. */ - def compile(env: ScriptEnv, code: String)(implicit IR: Scalan): Value[SType] = { + def compile(env: ScriptEnv, code: String)(implicit IR: IRContext): Value[SType] = { val res = compiler.compile(env, code) checkCompilerResult(res) res.buildTree } /** Check the given [[CompilerResult]] meets equality and sanity requirements. */ - def checkCompilerResult[Ctx <: Scalan](res: CompilerResult[Ctx]): Unit = { + def checkCompilerResult[Ctx <: IRContext](res: CompilerResult[Ctx]): Unit = { checkSerializationRoundTrip(res.buildTree) } /** Compiles the given code and checks the resulting `prop` against `expected`. */ def compileAndCheck(env: ScriptEnv, code: String, expected: SValue) - (implicit IR: Scalan): (ErgoTree, SigmaPropValue) = { + (implicit IR: IRContext): (ErgoTree, SigmaPropValue) = { val prop = compile(env, code).asSigmaProp prop shouldBe expected val tree = mkTestErgoTree(prop) diff --git a/sc/shared/src/test/scala/sigmastate/ScriptVersionSwitchSpecification.scala b/sc/shared/src/test/scala/sigmastate/ScriptVersionSwitchSpecification.scala index 767c1dbd7b..42c2b8706b 100644 --- a/sc/shared/src/test/scala/sigmastate/ScriptVersionSwitchSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/ScriptVersionSwitchSpecification.scala @@ -14,7 +14,7 @@ import sigmastate.interpreter.CErgoTreeEvaluator.DefaultEvalSettings import sigma.eval.EvalSettings.EvaluationMode import sigmastate.interpreter._ import sigma.ast.syntax.ValueOps -import sigma.compiler.Scalan +import sigma.compiler.IRContext import sigma.data.CBox import sigma.eval.EvalSettings import sigma.exceptions.InterpreterException @@ -33,7 +33,7 @@ class ScriptVersionSwitchSpecification extends SigmaDslTesting { costTracingEnabled = true // should always be enabled in tests (and false by default) ) - implicit def IR: Scalan = createIR() + implicit def IR: IRContext = createIR() lazy val b1 = CBox( new ErgoBox( @@ -52,7 +52,7 @@ class ScriptVersionSwitchSpecification extends SigmaDslTesting { ) /** Creates ErgoTree with segregated constants and also the given header flags. */ - def createErgoTree(header: HeaderType)(implicit IR: Scalan): ErgoTree = { + def createErgoTree(header: HeaderType)(implicit IR: IRContext): ErgoTree = { val code = s"""{ | val func = { (x: Coll[Box]) => x.filter({(b: Box) => b.value > 1 }) } diff --git a/sc/shared/src/test/scala/sigmastate/eval/ErgoScriptTestkit.scala b/sc/shared/src/test/scala/sigmastate/eval/ErgoScriptTestkit.scala index dc9cccae9c..2d8b613fa3 100644 --- a/sc/shared/src/test/scala/sigmastate/eval/ErgoScriptTestkit.scala +++ b/sc/shared/src/test/scala/sigmastate/eval/ErgoScriptTestkit.scala @@ -14,7 +14,7 @@ import sigmastate.helpers.{ContextEnrichingTestProvingInterpreter, ErgoLikeConte import sigmastate.interpreter.Interpreter.ScriptEnv import sigmastate.interpreter.CErgoTreeEvaluator import sigma.ast.syntax.ValueOps -import sigma.compiler.Scalan +import sigma.compiler.IRContext import sigma.interpreter.ContextExtension import sigmastate.lang.{CompilerResult, CompilerSettings, LangTests, SigmaCompiler} import sigma.serialization.ErgoTreeSerializer.DefaultSerializer @@ -27,8 +27,8 @@ import scala.util.{Success, Try} trait ErgoScriptTestkit extends ContractsTestkit with LangTests with ValidationSpecification with CompilerTestsBase { self: BaseCtxTests => - implicit lazy val IR: TestContext with Scalan = - new TestContext with Scalan + implicit lazy val IR: TestContext with IRContext = + new TestContext with IRContext import IR._ import BigInt._ diff --git a/sc/shared/src/test/scala/sigmastate/eval/ErgoTreeBuildingTest.scala b/sc/shared/src/test/scala/sigmastate/eval/ErgoTreeBuildingTest.scala index deb2110443..e8fc16e953 100644 --- a/sc/shared/src/test/scala/sigmastate/eval/ErgoTreeBuildingTest.scala +++ b/sc/shared/src/test/scala/sigmastate/eval/ErgoTreeBuildingTest.scala @@ -8,12 +8,12 @@ import scalan.BaseCtxTests import sigma.ast.syntax.ValueOps import sigmastate.lang.LangTests import sigma.ast.Apply -import sigma.compiler.Scalan +import sigma.compiler.IRContext class ErgoTreeBuildingTest extends BaseCtxTests with LangTests with ExampleContracts with ErgoScriptTestkit { - implicit override lazy val IR: TestContext with Scalan = new TestContext with Scalan { + implicit override lazy val IR: TestContext with IRContext = new TestContext with IRContext { beginPass(noConstPropagationPass) } diff --git a/sc/shared/src/test/scala/sigmastate/helpers/CompilerTestingCommons.scala b/sc/shared/src/test/scala/sigmastate/helpers/CompilerTestingCommons.scala index b7bdf58452..9539bfb135 100644 --- a/sc/shared/src/test/scala/sigmastate/helpers/CompilerTestingCommons.scala +++ b/sc/shared/src/test/scala/sigmastate/helpers/CompilerTestingCommons.scala @@ -12,7 +12,7 @@ import sigma.data.{RType, SigmaBoolean} import sigma.validation.ValidationException import sigma.validation.ValidationRules.CheckSerializableTypeCode import sigma.ast.syntax.{SValue, SigmaPropValue} -import sigma.compiler.Scalan +import sigma.compiler.IRContext import sigma.eval.{CostDetails, EvalSettings, Extensions, GivenCost, TracedCost} import sigmastate.helpers.TestingHelpers._ import sigma.interpreter.ContextExtension.VarBinding @@ -30,7 +30,7 @@ trait CompilerTestingCommons extends TestingCommons with TestUtils with TestContexts with ValidationSpecification with CompilerTestsBase { - class TestingIRContext extends TestContext with Scalan + class TestingIRContext extends TestContext with IRContext case class CompiledFunc[A,B] (script: String, bindings: Seq[VarBinding], expr: SValue, compiledTree: SValue, func: A => (B, CostDetails)) @@ -91,7 +91,7 @@ trait CompilerTestingCommons extends TestingCommons def compileTestScript[A] (env: ScriptEnv, funcScript: String) (implicit tA: RType[A], - IR: Scalan, + IR: IRContext, compilerSettings: CompilerSettings): SValue = { val code = s"""{ @@ -129,7 +129,7 @@ trait CompilerTestingCommons extends TestingCommons def funcJitFromExpr[A: RType, B: RType] (funcScript: String, expr: SValue, bindings: VarBinding*) - (implicit IR: Scalan, + (implicit IR: IRContext, evalSettings: EvalSettings, compilerSettings: CompilerSettings): CompiledFunc[A, B] = { val f = (in: A) => { @@ -167,7 +167,7 @@ trait CompilerTestingCommons extends TestingCommons def funcJit[A: RType, B: RType] (funcScript: String, bindings: VarBinding*) - (implicit IR: Scalan, + (implicit IR: IRContext, evalSettings: EvalSettings, compilerSettings: CompilerSettings): CompiledFunc[A, B] = { val compiledTree = compileTestScript[A](Interpreter.emptyEnv, funcScript) diff --git a/sc/shared/src/test/scala/sigmastate/serialization/ErgoTreeSerializerSpecification.scala b/sc/shared/src/test/scala/sigmastate/serialization/ErgoTreeSerializerSpecification.scala index ae517a2ee6..bbdc4cbdce 100644 --- a/sc/shared/src/test/scala/sigmastate/serialization/ErgoTreeSerializerSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/serialization/ErgoTreeSerializerSpecification.scala @@ -10,7 +10,7 @@ import sigma.util.Extensions.SigmaPropOps import sigma.validation.ValidationException import ErgoTree.EmptyConstants import ErgoTree.HeaderType -import sigma.compiler.Scalan +import sigma.compiler.IRContext import sigma.eval.Extensions.SigmaBooleanOps import sigmastate._ import sigmastate.helpers.CompilerTestingCommons @@ -25,7 +25,7 @@ class ErgoTreeSerializerSpecification extends SerializationSpecification beginPass(noConstPropagationPass) } - private def extractConstants(prop: SigmaPropValue)(implicit IR: Scalan): Seq[ErgoTree] = { + private def extractConstants(prop: SigmaPropValue)(implicit IR: IRContext): Seq[ErgoTree] = { import ErgoTree._ val env = Map[String, Any]() val res = compiler.compileTyped(env, prop) diff --git a/sc/shared/src/test/scala/sigmastate/utxo/AVLTreeScriptsSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/AVLTreeScriptsSpecification.scala index 7e1b9a5491..7cc36f798d 100644 --- a/sc/shared/src/test/scala/sigmastate/utxo/AVLTreeScriptsSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/utxo/AVLTreeScriptsSpecification.scala @@ -18,7 +18,7 @@ import sigma.ast.syntax._ import sigma.Coll import sigma.ast.SAvlTree import sigma.ast.syntax.{GetVarByteArray, OptionValueOps} -import sigma.compiler.Scalan +import sigma.compiler.IRContext import sigma.data.{AvlTreeData, AvlTreeFlags, CSigmaProp, TrivialProp} import sigma.eval.SigmaDsl import sigma.interpreter.ProverResult @@ -30,8 +30,8 @@ class AVLTreeScriptsSpecification extends CompilerTestingCommons with CompilerCrossVersionProps { suite => import org.ergoplatform.dsl.AvlTreeHelpers._ lazy val spec = TestContractSpec(suite)(new TestingIRContext) - lazy val prover = spec.ProvingParty("Alice") - private implicit lazy val IR: Scalan = spec.IR + lazy val prover = spec.ProvingParty("Alice") + private implicit lazy val IR: IRContext = spec.IR private val reg1 = ErgoBox.nonMandatoryRegisters(0) private val reg2 = ErgoBox.nonMandatoryRegisters(1) diff --git a/sc/shared/src/test/scala/sigmastate/utxo/UsingContextPropertiesSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/UsingContextPropertiesSpecification.scala index 9c29c0301d..5405c32b58 100644 --- a/sc/shared/src/test/scala/sigmastate/utxo/UsingContextPropertiesSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/utxo/UsingContextPropertiesSpecification.scala @@ -7,14 +7,14 @@ import sigmastate.helpers.CompilerTestingCommons import org.ergoplatform.dsl.{ContractSpec, SigmaContractSyntax, TestContractSpec} import org.ergoplatform.ErgoBox import scorex.crypto.hash.Blake2b256 -import sigma.compiler.Scalan +import sigma.compiler.IRContext import sigma.data.{CSigmaProp, TrivialProp} class UsingContextPropertiesSpecification extends CompilerTestingCommons with CompilerCrossVersionProps { suite => lazy val spec = TestContractSpec(suite)(new TestingIRContext) - lazy val prover = spec.ProvingParty("Alice") - private implicit lazy val IR: Scalan = spec.IR + lazy val prover = spec.ProvingParty("Alice") + private implicit lazy val IR: IRContext = spec.IR private val reg1 = ErgoBox.nonMandatoryRegisters(0) diff --git a/sc/shared/src/test/scala/sigmastate/utxo/blockchain/BlockchainSimulationTestingCommons.scala b/sc/shared/src/test/scala/sigmastate/utxo/blockchain/BlockchainSimulationTestingCommons.scala index 4cf39a8cb6..4fe0ecc136 100644 --- a/sc/shared/src/test/scala/sigmastate/utxo/blockchain/BlockchainSimulationTestingCommons.scala +++ b/sc/shared/src/test/scala/sigmastate/utxo/blockchain/BlockchainSimulationTestingCommons.scala @@ -17,7 +17,7 @@ import scorex.util._ import sigma.Colls import sigma.data.{AvlTreeData, AvlTreeFlags} import ErgoTree.ZeroHeader -import sigma.compiler.Scalan +import sigma.compiler.IRContext import sigma.eval.Extensions.SigmaBooleanOps import sigma.interpreter.ContextExtension import sigmastate.interpreter.Interpreter.{ScriptNameProp, emptyEnv} @@ -126,7 +126,7 @@ object BlockchainSimulationTestingCommons extends CompilerTestingCommons { } - case class ValidationState(state: BlockchainState, boxesReader: InMemoryErgoBoxReader, activatedVersion: Byte)(implicit IR: Scalan) { + case class ValidationState(state: BlockchainState, boxesReader: InMemoryErgoBoxReader, activatedVersion: Byte)(implicit IR: IRContext) { val validator = new ErgoTransactionValidator(activatedVersion) def applyBlock(block: FullBlock, maxCost: Int = MaxBlockCost): Try[ValidationState] = Try { @@ -166,7 +166,7 @@ object BlockchainSimulationTestingCommons extends CompilerTestingCommons { ErgoLikeContextTesting.dummyPubkey ) - def initialState(activatedVersion: Byte, block: FullBlock)(implicit IR: Scalan): ValidationState = { + def initialState(activatedVersion: Byte, block: FullBlock)(implicit IR: IRContext): ValidationState = { val keySize = 32 val prover = new BatchProver(keySize, None) diff --git a/sc/shared/src/test/scala/sigmastate/utxo/examples/IcoExample.scala b/sc/shared/src/test/scala/sigmastate/utxo/examples/IcoExample.scala index 6a55338fbe..9b5c796af8 100644 --- a/sc/shared/src/test/scala/sigmastate/utxo/examples/IcoExample.scala +++ b/sc/shared/src/test/scala/sigmastate/utxo/examples/IcoExample.scala @@ -22,7 +22,7 @@ import sigmastate.helpers.{CompilerTestingCommons, ContextEnrichingTestProvingIn import sigmastate.interpreter.Interpreter.ScriptNameProp import sigmastate.interpreter.Interpreter import sigma.ast.syntax._ -import sigma.compiler.Scalan +import sigma.compiler.IRContext import sigma.eval.SigmaDsl import sigma.serialization.ErgoTreeSerializer import sigma.serialization.ErgoTreeSerializer.DefaultSerializer @@ -242,7 +242,7 @@ class IcoExample extends CompilerTestingCommons with CompilerCrossVersionProps with BeforeAndAfterAll { suite => // Not mixed with TestContext since it is not possible to call commpiler.compile outside tests if mixed - implicit lazy val IR: Scalan = new Scalan {} + implicit lazy val IR: IRContext = new IRContext {} lazy val spec = TestContractSpec(suite) lazy val project = new ErgoLikeTestProvingInterpreter() diff --git a/sc/shared/src/test/scala/sigmastate/utxo/examples/LetsSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/examples/LetsSpecification.scala index 5b40d111f3..db3f3bc46b 100644 --- a/sc/shared/src/test/scala/sigmastate/utxo/examples/LetsSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/utxo/examples/LetsSpecification.scala @@ -15,7 +15,7 @@ import sigmastate.helpers.TestingHelpers._ import sigmastate.interpreter.Interpreter.ScriptNameProp import sigma.serialization.ErgoTreeSerializer import sigma.ast.syntax._ -import sigma.compiler.Scalan +import sigma.compiler.IRContext import sigma.eval.SigmaDsl import scala.util.Random @@ -172,7 +172,7 @@ import scala.util.Random class LetsSpecification extends CompilerTestingCommons with CompilerCrossVersionProps { suite => // Not mixed with TestContext since it is not possible to call compiler.compile outside tests if mixed - implicit lazy val IR: Scalan = new TestingIRContext + implicit lazy val IR: IRContext = new TestingIRContext lazy val project = new ErgoLikeTestProvingInterpreter() From 9c9ddc521e3090cbdeefca62434ac29c84ade044 Mon Sep 17 00:00:00 2001 From: Alexander Slesarenko Date: Thu, 16 May 2024 10:56:11 +0100 Subject: [PATCH 072/314] refactor-ir-cake: `staged` package removed --- .../src/main/scala/sigma/compiler/{staged => }/AstGraphs.scala | 3 +-- sc/shared/src/main/scala/sigma/compiler/IRContext.scala | 1 - .../main/scala/sigma/compiler/{staged => }/ProgramGraphs.scala | 3 +-- .../main/scala/sigma/compiler/{staged => }/Transforming.scala | 3 +-- .../src/main/scala/sigma/compiler/primitives/Functions.scala | 3 +-- 5 files changed, 4 insertions(+), 9 deletions(-) rename sc/shared/src/main/scala/sigma/compiler/{staged => }/AstGraphs.scala (99%) rename sc/shared/src/main/scala/sigma/compiler/{staged => }/ProgramGraphs.scala (97%) rename sc/shared/src/main/scala/sigma/compiler/{staged => }/Transforming.scala (99%) diff --git a/sc/shared/src/main/scala/sigma/compiler/staged/AstGraphs.scala b/sc/shared/src/main/scala/sigma/compiler/AstGraphs.scala similarity index 99% rename from sc/shared/src/main/scala/sigma/compiler/staged/AstGraphs.scala rename to sc/shared/src/main/scala/sigma/compiler/AstGraphs.scala index 5ee20810fa..3d6acb40ff 100644 --- a/sc/shared/src/main/scala/sigma/compiler/staged/AstGraphs.scala +++ b/sc/shared/src/main/scala/sigma/compiler/AstGraphs.scala @@ -1,7 +1,6 @@ -package sigma.compiler.staged +package sigma.compiler import debox.{cfor, Buffer => DBuffer, Map => DMap, Set => DSet} -import sigma.compiler.IRContext import sigma.data.emptyDBufferOfInt import scala.collection._ diff --git a/sc/shared/src/main/scala/sigma/compiler/IRContext.scala b/sc/shared/src/main/scala/sigma/compiler/IRContext.scala index 2f31d71589..3c204c440e 100644 --- a/sc/shared/src/main/scala/sigma/compiler/IRContext.scala +++ b/sc/shared/src/main/scala/sigma/compiler/IRContext.scala @@ -2,7 +2,6 @@ package sigma.compiler import scalan._ import sigma.compiler.primitives._ -import sigma.compiler.staged.Transforming import sigma.data.{Nullable, RType} import sigma.util.MemoizedFunc import sigma.{CollsModule, SigmaDslModule} diff --git a/sc/shared/src/main/scala/sigma/compiler/staged/ProgramGraphs.scala b/sc/shared/src/main/scala/sigma/compiler/ProgramGraphs.scala similarity index 97% rename from sc/shared/src/main/scala/sigma/compiler/staged/ProgramGraphs.scala rename to sc/shared/src/main/scala/sigma/compiler/ProgramGraphs.scala index 67220d1002..4ed6cab9b9 100644 --- a/sc/shared/src/main/scala/sigma/compiler/staged/ProgramGraphs.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ProgramGraphs.scala @@ -1,7 +1,6 @@ -package sigma.compiler.staged +package sigma.compiler import debox.{cfor, Buffer => DBuffer} -import sigma.compiler.IRContext import sigma.data.{DFunc, Nullable} import sigma.util.GraphUtil diff --git a/sc/shared/src/main/scala/sigma/compiler/staged/Transforming.scala b/sc/shared/src/main/scala/sigma/compiler/Transforming.scala similarity index 99% rename from sc/shared/src/main/scala/sigma/compiler/staged/Transforming.scala rename to sc/shared/src/main/scala/sigma/compiler/Transforming.scala index 6d729d35d0..33504ee961 100644 --- a/sc/shared/src/main/scala/sigma/compiler/staged/Transforming.scala +++ b/sc/shared/src/main/scala/sigma/compiler/Transforming.scala @@ -1,7 +1,6 @@ -package sigma.compiler.staged +package sigma.compiler import debox.{cfor, Buffer => DBuffer} -import sigma.compiler.IRContext import sigma.data.{Lazy, Nullable} import sigma.reflection.RMethod diff --git a/sc/shared/src/main/scala/sigma/compiler/primitives/Functions.scala b/sc/shared/src/main/scala/sigma/compiler/primitives/Functions.scala index dce2578d4f..3498c4ae0c 100644 --- a/sc/shared/src/main/scala/sigma/compiler/primitives/Functions.scala +++ b/sc/shared/src/main/scala/sigma/compiler/primitives/Functions.scala @@ -1,8 +1,7 @@ package sigma.compiler.primitives import debox.{cfor, Buffer => DBuffer} -import sigma.compiler.staged.ProgramGraphs -import sigma.compiler.{Base, IRContext} +import sigma.compiler.{Base, IRContext, ProgramGraphs} import sigma.data.{Lazy, Nullable, emptyDBufferOfInt} import sigma.util.GraphUtil From 291f255c87f9d07ec036d2acd6c2ebcaf9eccc5a Mon Sep 17 00:00:00 2001 From: Alexander Slesarenko Date: Thu, 16 May 2024 11:11:07 +0100 Subject: [PATCH 073/314] refactor-ir-cake: IR classes moved to sigma.compiler.ir package --- sc/js/src/main/scala/sigmastate/lang/js/SigmaCompiler.scala | 2 +- sc/js/src/test/scala/scalan/Platform.scala | 2 +- sc/jvm/src/test/scala/scalan/Platform.scala | 2 +- .../src/test/scala/scalan/compilation/GraphVizExport.scala | 2 +- .../sigmastate/InterpreterReflectionGeneratorTests.scala | 2 +- sc/jvm/src/test/scala/sigmastate/ReflectionGenerator.scala | 6 +++--- .../src/main/scala/org/ergoplatform/ErgoScriptPredef.scala | 2 +- .../src/main/scala/org/ergoplatform/dsl/ContractSpec.scala | 2 +- .../main/scala/org/ergoplatform/dsl/ErgoContractSpec.scala | 2 +- .../src/main/scala/sigma/compiler/{ => ir}/AstGraphs.scala | 2 +- sc/shared/src/main/scala/sigma/compiler/{ => ir}/Base.scala | 2 +- .../main/scala/sigma/compiler/{ => ir}/DefRewriting.scala | 2 +- .../src/main/scala/sigma/compiler/{ => ir}/Entities.scala | 2 +- .../src/main/scala/sigma/compiler/{ => ir}/Exceptions.scala | 0 .../main/scala/sigma/compiler/{ => ir}/GraphBuilding.scala | 2 +- .../scala/sigma/compiler/{ => ir}/GraphIRReflection.scala | 4 ++-- .../src/main/scala/sigma/compiler/{ => ir}/IRContext.scala | 4 ++-- .../main/scala/sigma/compiler/{ => ir}/MethodCalls.scala | 2 +- .../src/main/scala/sigma/compiler/{ => ir}/ModuleInfo.scala | 2 +- .../src/main/scala/sigma/compiler/{ => ir}/Modules.scala | 2 +- .../main/scala/sigma/compiler/{ => ir}/MutableLazy.scala | 0 .../main/scala/sigma/compiler/{ => ir}/ProgramGraphs.scala | 2 +- .../main/scala/sigma/compiler/{ => ir}/Transforming.scala | 2 +- .../main/scala/sigma/compiler/{ => ir}/TreeBuilding.scala | 2 +- .../src/main/scala/sigma/compiler/{ => ir}/TypeDescs.scala | 2 +- .../main/scala/sigma/compiler/{ => ir}/core/Variance.scala | 0 .../main/scala/sigma/compiler/{ => ir}/meta/SSymName.scala | 0 .../scala/sigma/compiler/{ => ir}/primitives/Equal.scala | 4 ++-- .../sigma/compiler/{ => ir}/primitives/Functions.scala | 4 ++-- .../sigma/compiler/{ => ir}/primitives/IfThenElse.scala | 4 ++-- .../sigma/compiler/{ => ir}/primitives/LogicalOps.scala | 4 ++-- .../sigma/compiler/{ => ir}/primitives/NumericOps.scala | 4 ++-- .../sigma/compiler/{ => ir}/primitives/OrderingOps.scala | 4 ++-- .../scala/sigma/compiler/{ => ir}/primitives/Thunks.scala | 4 ++-- .../scala/sigma/compiler/{ => ir}/primitives/Tuples.scala | 4 ++-- .../scala/sigma/compiler/{ => ir}/primitives/UnBinOps.scala | 4 ++-- .../sigma/compiler/{ => ir}/primitives/UniversalOps.scala | 4 ++-- .../src/main/scala/sigmastate/lang/SigmaCompiler.scala | 2 +- .../main/scala/sigmastate/lang/SigmaTemplateCompiler.scala | 2 +- sc/shared/src/main/scala/special/collection/CollsUnit.scala | 2 +- .../src/main/scala/special/collection/impl/CollsImpl.scala | 4 ++-- sc/shared/src/main/scala/special/sigma/SigmaDslUnit.scala | 2 +- .../src/main/scala/special/sigma/impl/SigmaDslImpl.scala | 4 ++-- .../main/scala/special/sigma/wrappers/WrappersModule.scala | 2 +- .../src/main/scala/special/wrappers/WrappersModule.scala | 2 +- sc/shared/src/main/scala/wrappers/scala/WOptions.scala | 2 +- .../src/main/scala/wrappers/scala/impl/WOptionsImpl.scala | 4 ++-- sc/shared/src/main/scala/wrappers/scalan/WRTypes.scala | 2 +- .../src/main/scala/wrappers/scalan/impl/WRTypesImpl.scala | 4 ++-- .../src/main/scala/wrappers/special/WSpecialPredefs.scala | 2 +- .../scala/wrappers/special/impl/WSpecialPredefsImpl.scala | 4 ++-- .../test/scala/org/ergoplatform/dsl/TestContractSpec.scala | 2 +- sc/shared/src/test/scala/scalan/BaseLiftableTests.scala | 2 +- sc/shared/src/test/scala/scalan/LibraryTests.scala | 2 +- sc/shared/src/test/scala/scalan/TestContexts.scala | 2 +- sc/shared/src/test/scala/scalan/TestLibrary.scala | 2 +- sc/shared/src/test/scala/sigma/CollsStagingTests.scala | 2 +- sc/shared/src/test/scala/sigma/SigmaDslStaginTests.scala | 2 +- sc/shared/src/test/scala/sigma/SigmaDslTesting.scala | 2 +- sc/shared/src/test/scala/sigmastate/CompilerTestsBase.scala | 2 +- .../scala/sigmastate/ScriptVersionSwitchSpecification.scala | 2 +- .../src/test/scala/sigmastate/eval/ErgoScriptTestkit.scala | 2 +- .../test/scala/sigmastate/eval/ErgoTreeBuildingTest.scala | 2 +- .../scala/sigmastate/helpers/CompilerTestingCommons.scala | 2 +- .../serialization/ErgoTreeSerializerSpecification.scala | 2 +- .../scala/sigmastate/utxo/AVLTreeScriptsSpecification.scala | 2 +- .../utxo/UsingContextPropertiesSpecification.scala | 2 +- .../blockchain/BlockchainSimulationTestingCommons.scala | 2 +- .../test/scala/sigmastate/utxo/examples/IcoExample.scala | 2 +- .../scala/sigmastate/utxo/examples/LetsSpecification.scala | 2 +- 70 files changed, 85 insertions(+), 85 deletions(-) rename sc/shared/src/main/scala/sigma/compiler/{ => ir}/AstGraphs.scala (99%) rename sc/shared/src/main/scala/sigma/compiler/{ => ir}/Base.scala (99%) rename sc/shared/src/main/scala/sigma/compiler/{ => ir}/DefRewriting.scala (99%) rename sc/shared/src/main/scala/sigma/compiler/{ => ir}/Entities.scala (98%) rename sc/shared/src/main/scala/sigma/compiler/{ => ir}/Exceptions.scala (100%) rename sc/shared/src/main/scala/sigma/compiler/{ => ir}/GraphBuilding.scala (99%) rename sc/shared/src/main/scala/sigma/compiler/{ => ir}/GraphIRReflection.scala (99%) rename sc/shared/src/main/scala/sigma/compiler/{ => ir}/IRContext.scala (98%) rename sc/shared/src/main/scala/sigma/compiler/{ => ir}/MethodCalls.scala (99%) rename sc/shared/src/main/scala/sigma/compiler/{ => ir}/ModuleInfo.scala (94%) rename sc/shared/src/main/scala/sigma/compiler/{ => ir}/Modules.scala (94%) rename sc/shared/src/main/scala/sigma/compiler/{ => ir}/MutableLazy.scala (100%) rename sc/shared/src/main/scala/sigma/compiler/{ => ir}/ProgramGraphs.scala (98%) rename sc/shared/src/main/scala/sigma/compiler/{ => ir}/Transforming.scala (99%) rename sc/shared/src/main/scala/sigma/compiler/{ => ir}/TreeBuilding.scala (99%) rename sc/shared/src/main/scala/sigma/compiler/{ => ir}/TypeDescs.scala (99%) rename sc/shared/src/main/scala/sigma/compiler/{ => ir}/core/Variance.scala (100%) rename sc/shared/src/main/scala/sigma/compiler/{ => ir}/meta/SSymName.scala (100%) rename sc/shared/src/main/scala/sigma/compiler/{ => ir}/primitives/Equal.scala (92%) rename sc/shared/src/main/scala/sigma/compiler/{ => ir}/primitives/Functions.scala (99%) rename sc/shared/src/main/scala/sigma/compiler/{ => ir}/primitives/IfThenElse.scala (96%) rename sc/shared/src/main/scala/sigma/compiler/{ => ir}/primitives/LogicalOps.scala (96%) rename sc/shared/src/main/scala/sigma/compiler/{ => ir}/primitives/NumericOps.scala (97%) rename sc/shared/src/main/scala/sigma/compiler/{ => ir}/primitives/OrderingOps.scala (96%) rename sc/shared/src/main/scala/sigma/compiler/{ => ir}/primitives/Thunks.scala (99%) rename sc/shared/src/main/scala/sigma/compiler/{ => ir}/primitives/Tuples.scala (97%) rename sc/shared/src/main/scala/sigma/compiler/{ => ir}/primitives/UnBinOps.scala (97%) rename sc/shared/src/main/scala/sigma/compiler/{ => ir}/primitives/UniversalOps.scala (98%) diff --git a/sc/js/src/main/scala/sigmastate/lang/js/SigmaCompiler.scala b/sc/js/src/main/scala/sigmastate/lang/js/SigmaCompiler.scala index 3dfd285e93..6264cd2f82 100644 --- a/sc/js/src/main/scala/sigmastate/lang/js/SigmaCompiler.scala +++ b/sc/js/src/main/scala/sigmastate/lang/js/SigmaCompiler.scala @@ -9,7 +9,7 @@ import scala.scalajs.js import scala.scalajs.js.annotation.JSExportTopLevel import sigma.js.Value import sigma.ast.ErgoTree.HeaderType -import sigma.compiler.CompiletimeIRContext +import sigma.compiler.ir.CompiletimeIRContext import sigma.ast.syntax.ValueOps diff --git a/sc/js/src/test/scala/scalan/Platform.scala b/sc/js/src/test/scala/scalan/Platform.scala index afb5ff72c1..697453a5d2 100644 --- a/sc/js/src/test/scala/scalan/Platform.scala +++ b/sc/js/src/test/scala/scalan/Platform.scala @@ -1,6 +1,6 @@ package scalan -import sigma.compiler.IRContext +import sigma.compiler.ir.IRContext import scala.annotation.unused diff --git a/sc/jvm/src/test/scala/scalan/Platform.scala b/sc/jvm/src/test/scala/scalan/Platform.scala index 3a194a7d50..7c9d48b135 100644 --- a/sc/jvm/src/test/scala/scalan/Platform.scala +++ b/sc/jvm/src/test/scala/scalan/Platform.scala @@ -3,7 +3,7 @@ package scalan import scalan.compilation.GraphVizExport import sigma.util.FileUtil import org.scalatest.Assertions -import sigma.compiler.IRContext +import sigma.compiler.ir.IRContext object Platform { /** Output graph given by symbols in `sfs` to files. diff --git a/sc/jvm/src/test/scala/scalan/compilation/GraphVizExport.scala b/sc/jvm/src/test/scala/scalan/compilation/GraphVizExport.scala index 1072de00e2..020e066080 100644 --- a/sc/jvm/src/test/scala/scalan/compilation/GraphVizExport.scala +++ b/sc/jvm/src/test/scala/scalan/compilation/GraphVizExport.scala @@ -3,7 +3,7 @@ package scalan.compilation import java.awt.Desktop import java.io.{File, PrintWriter} import scalan.core.ScalaNameUtil -import sigma.compiler.IRContext +import sigma.compiler.ir.IRContext import sigma.util.{FileUtil, ProcessUtil, StringUtil} import scala.annotation.unused diff --git a/sc/jvm/src/test/scala/sigmastate/InterpreterReflectionGeneratorTests.scala b/sc/jvm/src/test/scala/sigmastate/InterpreterReflectionGeneratorTests.scala index 7fc0e454ed..c10c0123b0 100644 --- a/sc/jvm/src/test/scala/sigmastate/InterpreterReflectionGeneratorTests.scala +++ b/sc/jvm/src/test/scala/sigmastate/InterpreterReflectionGeneratorTests.scala @@ -2,7 +2,7 @@ package sigmastate import org.scalatest.matchers.should.Matchers import org.scalatest.propspec.AnyPropSpec -import sigma.compiler.{IRContext, TypeDescs} +import sigma.compiler.ir.{IRContext, TypeDescs} import sigma.reflection.ReflectionData.registerClassEntry import sigma.reflection.SRConstructor diff --git a/sc/jvm/src/test/scala/sigmastate/ReflectionGenerator.scala b/sc/jvm/src/test/scala/sigmastate/ReflectionGenerator.scala index 963e1c56d1..c102f4eda8 100644 --- a/sc/jvm/src/test/scala/sigmastate/ReflectionGenerator.scala +++ b/sc/jvm/src/test/scala/sigmastate/ReflectionGenerator.scala @@ -1,6 +1,6 @@ package sigmastate -import sigma.compiler.{Base, TypeDescs} +import sigma.compiler.ir.{Base, TypeDescs} import sigma.reflection._ import scala.annotation.unused import scala.collection.mutable @@ -30,7 +30,7 @@ object ReflectionGenerator { } val knownPackages = Array( - "sigma.compiler.primitives.", + "sigma.compiler.ir.primitives.", "sigma.", "sigma.", "special.wrappers.", @@ -40,7 +40,7 @@ object ReflectionGenerator { "sigmastate.utxo.", "sigmastate.", "wrappers.scala.", - "sigma.compiler.", + "sigma.compiler.ir.", "scala.collection.", "scala." ) diff --git a/sc/shared/src/main/scala/org/ergoplatform/ErgoScriptPredef.scala b/sc/shared/src/main/scala/org/ergoplatform/ErgoScriptPredef.scala index 1b84e7f0d6..60b82a54a2 100644 --- a/sc/shared/src/main/scala/org/ergoplatform/ErgoScriptPredef.scala +++ b/sc/shared/src/main/scala/org/ergoplatform/ErgoScriptPredef.scala @@ -6,7 +6,7 @@ import sigma.ast.SType import sigma.ast.syntax.SigmaPropValue import sigma.ast.Value import sigma.ast.syntax.ValueOps -import sigma.compiler.IRContext +import sigma.compiler.ir.IRContext object ErgoScriptPredef { import sigmastate.interpreter.Interpreter._ diff --git a/sc/shared/src/main/scala/org/ergoplatform/dsl/ContractSpec.scala b/sc/shared/src/main/scala/org/ergoplatform/dsl/ContractSpec.scala index 128351efea..ffe7239c62 100644 --- a/sc/shared/src/main/scala/org/ergoplatform/dsl/ContractSpec.scala +++ b/sc/shared/src/main/scala/org/ergoplatform/dsl/ContractSpec.scala @@ -9,7 +9,7 @@ import sigma.{Coll, SigmaDslBuilder, SigmaProp} import scala.util.Try import org.ergoplatform.dsl.ContractSyntax.{ErgoScript, Proposition, Token} import sigma.ast.{ErgoTree, EvaluatedValue, SType} -import sigma.compiler.IRContext +import sigma.compiler.ir.IRContext import scala.language.implicitConversions diff --git a/sc/shared/src/main/scala/org/ergoplatform/dsl/ErgoContractSpec.scala b/sc/shared/src/main/scala/org/ergoplatform/dsl/ErgoContractSpec.scala index 5929299a3b..2511bef439 100644 --- a/sc/shared/src/main/scala/org/ergoplatform/dsl/ErgoContractSpec.scala +++ b/sc/shared/src/main/scala/org/ergoplatform/dsl/ErgoContractSpec.scala @@ -3,7 +3,7 @@ package org.ergoplatform.dsl import sigma.Coll import org.ergoplatform.dsl.ContractSyntax.{ErgoScript, Proposition, Token} import org.ergoplatform.ErgoBox.{BoxId, NonMandatoryRegisterId, TokenId} -import sigma.compiler.IRContext +import sigma.compiler.ir.IRContext import sigma.interpreter.CostedProverResult class ErgoContractSpec(implicit val IR: IRContext) extends ContractSpec { diff --git a/sc/shared/src/main/scala/sigma/compiler/AstGraphs.scala b/sc/shared/src/main/scala/sigma/compiler/ir/AstGraphs.scala similarity index 99% rename from sc/shared/src/main/scala/sigma/compiler/AstGraphs.scala rename to sc/shared/src/main/scala/sigma/compiler/ir/AstGraphs.scala index 3d6acb40ff..7f798dc8f3 100644 --- a/sc/shared/src/main/scala/sigma/compiler/AstGraphs.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/AstGraphs.scala @@ -1,4 +1,4 @@ -package sigma.compiler +package sigma.compiler.ir import debox.{cfor, Buffer => DBuffer, Map => DMap, Set => DSet} import sigma.data.emptyDBufferOfInt diff --git a/sc/shared/src/main/scala/sigma/compiler/Base.scala b/sc/shared/src/main/scala/sigma/compiler/ir/Base.scala similarity index 99% rename from sc/shared/src/main/scala/sigma/compiler/Base.scala rename to sc/shared/src/main/scala/sigma/compiler/ir/Base.scala index 3d6b763c5a..939d364953 100644 --- a/sc/shared/src/main/scala/sigma/compiler/Base.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/Base.scala @@ -1,4 +1,4 @@ -package sigma.compiler +package sigma.compiler.ir import debox.{cfor, Buffer => DBuffer} import scalan.MutableLazy diff --git a/sc/shared/src/main/scala/sigma/compiler/DefRewriting.scala b/sc/shared/src/main/scala/sigma/compiler/ir/DefRewriting.scala similarity index 99% rename from sc/shared/src/main/scala/sigma/compiler/DefRewriting.scala rename to sc/shared/src/main/scala/sigma/compiler/ir/DefRewriting.scala index 0cc86c0644..fe289cafe0 100644 --- a/sc/shared/src/main/scala/sigma/compiler/DefRewriting.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/DefRewriting.scala @@ -1,4 +1,4 @@ -package sigma.compiler +package sigma.compiler.ir import scalan.DelayInvokeException import sigma.data.ExactNumeric diff --git a/sc/shared/src/main/scala/sigma/compiler/Entities.scala b/sc/shared/src/main/scala/sigma/compiler/ir/Entities.scala similarity index 98% rename from sc/shared/src/main/scala/sigma/compiler/Entities.scala rename to sc/shared/src/main/scala/sigma/compiler/ir/Entities.scala index bfda787fc3..dfaeff207c 100644 --- a/sc/shared/src/main/scala/sigma/compiler/Entities.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/Entities.scala @@ -1,4 +1,4 @@ -package sigma.compiler +package sigma.compiler.ir /** A slice in the Scalan cake with base classes for various descriptors. */ trait Entities extends TypeDescs { self: IRContext => diff --git a/sc/shared/src/main/scala/sigma/compiler/Exceptions.scala b/sc/shared/src/main/scala/sigma/compiler/ir/Exceptions.scala similarity index 100% rename from sc/shared/src/main/scala/sigma/compiler/Exceptions.scala rename to sc/shared/src/main/scala/sigma/compiler/ir/Exceptions.scala diff --git a/sc/shared/src/main/scala/sigma/compiler/GraphBuilding.scala b/sc/shared/src/main/scala/sigma/compiler/ir/GraphBuilding.scala similarity index 99% rename from sc/shared/src/main/scala/sigma/compiler/GraphBuilding.scala rename to sc/shared/src/main/scala/sigma/compiler/ir/GraphBuilding.scala index bbc1361dfe..71029b4628 100644 --- a/sc/shared/src/main/scala/sigma/compiler/GraphBuilding.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/GraphBuilding.scala @@ -1,4 +1,4 @@ -package sigma.compiler +package sigma.compiler.ir import org.ergoplatform._ import scalan.MutableLazy diff --git a/sc/shared/src/main/scala/sigma/compiler/GraphIRReflection.scala b/sc/shared/src/main/scala/sigma/compiler/ir/GraphIRReflection.scala similarity index 99% rename from sc/shared/src/main/scala/sigma/compiler/GraphIRReflection.scala rename to sc/shared/src/main/scala/sigma/compiler/ir/GraphIRReflection.scala index 59f1116569..32d95354c3 100644 --- a/sc/shared/src/main/scala/sigma/compiler/GraphIRReflection.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/GraphIRReflection.scala @@ -1,6 +1,6 @@ -package sigma.compiler +package sigma.compiler.ir -import sigma.compiler.primitives.Thunks +import sigma.compiler.ir.primitives.Thunks import sigma.{Colls, SigmaDsl} import sigma.data.RType import sigma.reflection.ReflectionData.registerClassEntry diff --git a/sc/shared/src/main/scala/sigma/compiler/IRContext.scala b/sc/shared/src/main/scala/sigma/compiler/ir/IRContext.scala similarity index 98% rename from sc/shared/src/main/scala/sigma/compiler/IRContext.scala rename to sc/shared/src/main/scala/sigma/compiler/ir/IRContext.scala index 3c204c440e..7fae587ac4 100644 --- a/sc/shared/src/main/scala/sigma/compiler/IRContext.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/IRContext.scala @@ -1,7 +1,7 @@ -package sigma.compiler +package sigma.compiler.ir import scalan._ -import sigma.compiler.primitives._ +import sigma.compiler.ir.primitives._ import sigma.data.{Nullable, RType} import sigma.util.MemoizedFunc import sigma.{CollsModule, SigmaDslModule} diff --git a/sc/shared/src/main/scala/sigma/compiler/MethodCalls.scala b/sc/shared/src/main/scala/sigma/compiler/ir/MethodCalls.scala similarity index 99% rename from sc/shared/src/main/scala/sigma/compiler/MethodCalls.scala rename to sc/shared/src/main/scala/sigma/compiler/ir/MethodCalls.scala index 4b534930d8..de96900c62 100644 --- a/sc/shared/src/main/scala/sigma/compiler/MethodCalls.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/MethodCalls.scala @@ -1,4 +1,4 @@ -package sigma.compiler +package sigma.compiler.ir import debox.{cfor, Buffer => DBuffer} import scalan.DelayInvokeException diff --git a/sc/shared/src/main/scala/sigma/compiler/ModuleInfo.scala b/sc/shared/src/main/scala/sigma/compiler/ir/ModuleInfo.scala similarity index 94% rename from sc/shared/src/main/scala/sigma/compiler/ModuleInfo.scala rename to sc/shared/src/main/scala/sigma/compiler/ir/ModuleInfo.scala index 8c2030b1c7..ccd71ffdc0 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ModuleInfo.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/ModuleInfo.scala @@ -1,4 +1,4 @@ -package sigma.compiler +package sigma.compiler.ir import scalan.meta.SSymName diff --git a/sc/shared/src/main/scala/sigma/compiler/Modules.scala b/sc/shared/src/main/scala/sigma/compiler/ir/Modules.scala similarity index 94% rename from sc/shared/src/main/scala/sigma/compiler/Modules.scala rename to sc/shared/src/main/scala/sigma/compiler/ir/Modules.scala index 527dcd6eb8..cafee1ef84 100644 --- a/sc/shared/src/main/scala/sigma/compiler/Modules.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/Modules.scala @@ -1,4 +1,4 @@ -package sigma.compiler +package sigma.compiler.ir trait Modules extends Base { self: IRContext => diff --git a/sc/shared/src/main/scala/sigma/compiler/MutableLazy.scala b/sc/shared/src/main/scala/sigma/compiler/ir/MutableLazy.scala similarity index 100% rename from sc/shared/src/main/scala/sigma/compiler/MutableLazy.scala rename to sc/shared/src/main/scala/sigma/compiler/ir/MutableLazy.scala diff --git a/sc/shared/src/main/scala/sigma/compiler/ProgramGraphs.scala b/sc/shared/src/main/scala/sigma/compiler/ir/ProgramGraphs.scala similarity index 98% rename from sc/shared/src/main/scala/sigma/compiler/ProgramGraphs.scala rename to sc/shared/src/main/scala/sigma/compiler/ir/ProgramGraphs.scala index 4ed6cab9b9..cd0384c996 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ProgramGraphs.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/ProgramGraphs.scala @@ -1,4 +1,4 @@ -package sigma.compiler +package sigma.compiler.ir import debox.{cfor, Buffer => DBuffer} import sigma.data.{DFunc, Nullable} diff --git a/sc/shared/src/main/scala/sigma/compiler/Transforming.scala b/sc/shared/src/main/scala/sigma/compiler/ir/Transforming.scala similarity index 99% rename from sc/shared/src/main/scala/sigma/compiler/Transforming.scala rename to sc/shared/src/main/scala/sigma/compiler/ir/Transforming.scala index 33504ee961..2412c756f1 100644 --- a/sc/shared/src/main/scala/sigma/compiler/Transforming.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/Transforming.scala @@ -1,4 +1,4 @@ -package sigma.compiler +package sigma.compiler.ir import debox.{cfor, Buffer => DBuffer} import sigma.data.{Lazy, Nullable} diff --git a/sc/shared/src/main/scala/sigma/compiler/TreeBuilding.scala b/sc/shared/src/main/scala/sigma/compiler/ir/TreeBuilding.scala similarity index 99% rename from sc/shared/src/main/scala/sigma/compiler/TreeBuilding.scala rename to sc/shared/src/main/scala/sigma/compiler/ir/TreeBuilding.scala index de6437645f..4c54ef711b 100644 --- a/sc/shared/src/main/scala/sigma/compiler/TreeBuilding.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/TreeBuilding.scala @@ -1,4 +1,4 @@ -package sigma.compiler +package sigma.compiler.ir import org.ergoplatform._ import sigma.ast._ diff --git a/sc/shared/src/main/scala/sigma/compiler/TypeDescs.scala b/sc/shared/src/main/scala/sigma/compiler/ir/TypeDescs.scala similarity index 99% rename from sc/shared/src/main/scala/sigma/compiler/TypeDescs.scala rename to sc/shared/src/main/scala/sigma/compiler/ir/TypeDescs.scala index 6e2de8d952..4346d117ea 100644 --- a/sc/shared/src/main/scala/sigma/compiler/TypeDescs.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/TypeDescs.scala @@ -1,4 +1,4 @@ -package sigma.compiler +package sigma.compiler.ir import debox.cfor import scalan.core.{Contravariant, Covariant, Variance} diff --git a/sc/shared/src/main/scala/sigma/compiler/core/Variance.scala b/sc/shared/src/main/scala/sigma/compiler/ir/core/Variance.scala similarity index 100% rename from sc/shared/src/main/scala/sigma/compiler/core/Variance.scala rename to sc/shared/src/main/scala/sigma/compiler/ir/core/Variance.scala diff --git a/sc/shared/src/main/scala/sigma/compiler/meta/SSymName.scala b/sc/shared/src/main/scala/sigma/compiler/ir/meta/SSymName.scala similarity index 100% rename from sc/shared/src/main/scala/sigma/compiler/meta/SSymName.scala rename to sc/shared/src/main/scala/sigma/compiler/ir/meta/SSymName.scala diff --git a/sc/shared/src/main/scala/sigma/compiler/primitives/Equal.scala b/sc/shared/src/main/scala/sigma/compiler/ir/primitives/Equal.scala similarity index 92% rename from sc/shared/src/main/scala/sigma/compiler/primitives/Equal.scala rename to sc/shared/src/main/scala/sigma/compiler/ir/primitives/Equal.scala index fc6e67fbfd..a778465e4c 100644 --- a/sc/shared/src/main/scala/sigma/compiler/primitives/Equal.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/primitives/Equal.scala @@ -1,6 +1,6 @@ -package sigma.compiler.primitives +package sigma.compiler.ir.primitives -import sigma.compiler.{Base, IRContext} +import sigma.compiler.ir.{Base, IRContext} import scala.annotation.unused diff --git a/sc/shared/src/main/scala/sigma/compiler/primitives/Functions.scala b/sc/shared/src/main/scala/sigma/compiler/ir/primitives/Functions.scala similarity index 99% rename from sc/shared/src/main/scala/sigma/compiler/primitives/Functions.scala rename to sc/shared/src/main/scala/sigma/compiler/ir/primitives/Functions.scala index 3498c4ae0c..04d3283c01 100644 --- a/sc/shared/src/main/scala/sigma/compiler/primitives/Functions.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/primitives/Functions.scala @@ -1,7 +1,7 @@ -package sigma.compiler.primitives +package sigma.compiler.ir.primitives import debox.{cfor, Buffer => DBuffer} -import sigma.compiler.{Base, IRContext, ProgramGraphs} +import sigma.compiler.ir.{Base, IRContext, ProgramGraphs} import sigma.data.{Lazy, Nullable, emptyDBufferOfInt} import sigma.util.GraphUtil diff --git a/sc/shared/src/main/scala/sigma/compiler/primitives/IfThenElse.scala b/sc/shared/src/main/scala/sigma/compiler/ir/primitives/IfThenElse.scala similarity index 96% rename from sc/shared/src/main/scala/sigma/compiler/primitives/IfThenElse.scala rename to sc/shared/src/main/scala/sigma/compiler/ir/primitives/IfThenElse.scala index e09036fcaf..aee57ff1f9 100644 --- a/sc/shared/src/main/scala/sigma/compiler/primitives/IfThenElse.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/primitives/IfThenElse.scala @@ -1,6 +1,6 @@ -package sigma.compiler.primitives +package sigma.compiler.ir.primitives -import sigma.compiler.{Base, IRContext} +import sigma.compiler.ir.{Base, IRContext} trait IfThenElse extends Base { self: IRContext => diff --git a/sc/shared/src/main/scala/sigma/compiler/primitives/LogicalOps.scala b/sc/shared/src/main/scala/sigma/compiler/ir/primitives/LogicalOps.scala similarity index 96% rename from sc/shared/src/main/scala/sigma/compiler/primitives/LogicalOps.scala rename to sc/shared/src/main/scala/sigma/compiler/ir/primitives/LogicalOps.scala index faf186bf04..6420e46f5c 100644 --- a/sc/shared/src/main/scala/sigma/compiler/primitives/LogicalOps.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/primitives/LogicalOps.scala @@ -1,6 +1,6 @@ -package sigma.compiler.primitives +package sigma.compiler.ir.primitives -import sigma.compiler.{Base, IRContext} +import sigma.compiler.ir.{Base, IRContext} /** Slice in Scala cake with definitions of logical operations. */ trait LogicalOps extends Base { self: IRContext => diff --git a/sc/shared/src/main/scala/sigma/compiler/primitives/NumericOps.scala b/sc/shared/src/main/scala/sigma/compiler/ir/primitives/NumericOps.scala similarity index 97% rename from sc/shared/src/main/scala/sigma/compiler/primitives/NumericOps.scala rename to sc/shared/src/main/scala/sigma/compiler/ir/primitives/NumericOps.scala index de3f2e6fed..d22140870a 100644 --- a/sc/shared/src/main/scala/sigma/compiler/primitives/NumericOps.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/primitives/NumericOps.scala @@ -1,6 +1,6 @@ -package sigma.compiler.primitives +package sigma.compiler.ir.primitives -import sigma.compiler.{Base, IRContext} +import sigma.compiler.ir.{Base, IRContext} import sigma.data.{ExactIntegral, ExactNumeric} /** Slice in Scala cake with definitions of numeric operations. */ diff --git a/sc/shared/src/main/scala/sigma/compiler/primitives/OrderingOps.scala b/sc/shared/src/main/scala/sigma/compiler/ir/primitives/OrderingOps.scala similarity index 96% rename from sc/shared/src/main/scala/sigma/compiler/primitives/OrderingOps.scala rename to sc/shared/src/main/scala/sigma/compiler/ir/primitives/OrderingOps.scala index 31d4c88365..ea2b9f5a34 100644 --- a/sc/shared/src/main/scala/sigma/compiler/primitives/OrderingOps.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/primitives/OrderingOps.scala @@ -1,6 +1,6 @@ -package sigma.compiler.primitives +package sigma.compiler.ir.primitives -import sigma.compiler.{Base, IRContext} +import sigma.compiler.ir.{Base, IRContext} import sigma.data.ExactOrdering import scala.language.implicitConversions diff --git a/sc/shared/src/main/scala/sigma/compiler/primitives/Thunks.scala b/sc/shared/src/main/scala/sigma/compiler/ir/primitives/Thunks.scala similarity index 99% rename from sc/shared/src/main/scala/sigma/compiler/primitives/Thunks.scala rename to sc/shared/src/main/scala/sigma/compiler/ir/primitives/Thunks.scala index 2b5c97fcba..8674918907 100644 --- a/sc/shared/src/main/scala/sigma/compiler/primitives/Thunks.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/primitives/Thunks.scala @@ -1,8 +1,8 @@ -package sigma.compiler.primitives +package sigma.compiler.ir.primitives import debox.{cfor, Buffer => DBuffer, Set => DSet} import scalan.core.Covariant -import sigma.compiler.IRContext +import sigma.compiler.ir.IRContext import sigma.data.{AVHashMap, DFunc, Lazy, Nullable, RType} import sigma.reflection.RClass import sigma.util.GraphUtil diff --git a/sc/shared/src/main/scala/sigma/compiler/primitives/Tuples.scala b/sc/shared/src/main/scala/sigma/compiler/ir/primitives/Tuples.scala similarity index 97% rename from sc/shared/src/main/scala/sigma/compiler/primitives/Tuples.scala rename to sc/shared/src/main/scala/sigma/compiler/ir/primitives/Tuples.scala index d0455d0106..b6b9861ac7 100644 --- a/sc/shared/src/main/scala/sigma/compiler/primitives/Tuples.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/primitives/Tuples.scala @@ -2,9 +2,9 @@ * Author: Alexander Slesarenko * Date: 7/25/12 */ -package sigma.compiler.primitives +package sigma.compiler.ir.primitives -import sigma.compiler.{Base, IRContext} +import sigma.compiler.ir.{Base, IRContext} import sigma.data.AVHashMap import scala.language.implicitConversions diff --git a/sc/shared/src/main/scala/sigma/compiler/primitives/UnBinOps.scala b/sc/shared/src/main/scala/sigma/compiler/ir/primitives/UnBinOps.scala similarity index 97% rename from sc/shared/src/main/scala/sigma/compiler/primitives/UnBinOps.scala rename to sc/shared/src/main/scala/sigma/compiler/ir/primitives/UnBinOps.scala index 4bb9b6b9ab..a3a92e2f10 100644 --- a/sc/shared/src/main/scala/sigma/compiler/primitives/UnBinOps.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/primitives/UnBinOps.scala @@ -1,6 +1,6 @@ -package sigma.compiler.primitives +package sigma.compiler.ir.primitives -import sigma.compiler.{Base, IRContext} +import sigma.compiler.ir.{Base, IRContext} trait UnBinOps extends Base { self: IRContext => diff --git a/sc/shared/src/main/scala/sigma/compiler/primitives/UniversalOps.scala b/sc/shared/src/main/scala/sigma/compiler/ir/primitives/UniversalOps.scala similarity index 98% rename from sc/shared/src/main/scala/sigma/compiler/primitives/UniversalOps.scala rename to sc/shared/src/main/scala/sigma/compiler/ir/primitives/UniversalOps.scala index b83e152b4f..a5852647ac 100644 --- a/sc/shared/src/main/scala/sigma/compiler/primitives/UniversalOps.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/primitives/UniversalOps.scala @@ -1,6 +1,6 @@ -package sigma.compiler.primitives +package sigma.compiler.ir.primitives -import sigma.compiler.{Base, IRContext} +import sigma.compiler.ir.{Base, IRContext} trait UniversalOps extends Base { self: IRContext => case class HashCode[A]() extends UnOp[A, Int]("hashCode") { diff --git a/sc/shared/src/main/scala/sigmastate/lang/SigmaCompiler.scala b/sc/shared/src/main/scala/sigmastate/lang/SigmaCompiler.scala index f12a385973..0a2bb9a355 100644 --- a/sc/shared/src/main/scala/sigmastate/lang/SigmaCompiler.scala +++ b/sc/shared/src/main/scala/sigmastate/lang/SigmaCompiler.scala @@ -12,7 +12,7 @@ import sigmastate.lang.parsers.ParserException import sigma.ast._ import sigma.ast.syntax.SValue import SCollectionMethods.{ExistsMethod, ForallMethod, MapMethod} -import sigma.compiler.{GraphIRReflection, IRContext} +import sigma.compiler.ir.{GraphIRReflection, IRContext} import sigmastate.InterpreterReflection /** diff --git a/sc/shared/src/main/scala/sigmastate/lang/SigmaTemplateCompiler.scala b/sc/shared/src/main/scala/sigmastate/lang/SigmaTemplateCompiler.scala index 8c8a84d29e..09d27b2489 100644 --- a/sc/shared/src/main/scala/sigmastate/lang/SigmaTemplateCompiler.scala +++ b/sc/shared/src/main/scala/sigmastate/lang/SigmaTemplateCompiler.scala @@ -4,7 +4,7 @@ import fastparse.Parsed import org.ergoplatform.sdk.{ContractTemplate, Parameter} import sigma.ast.SourceContext import sigma.ast.syntax.SValue -import sigma.compiler.CompiletimeIRContext +import sigma.compiler.ir.CompiletimeIRContext import sigmastate.lang.parsers.ParserException /** Compiler which compiles Ergo contract templates into a [[ContractTemplate]]. */ diff --git a/sc/shared/src/main/scala/special/collection/CollsUnit.scala b/sc/shared/src/main/scala/special/collection/CollsUnit.scala index 53bf6f0530..f000b61ed6 100644 --- a/sc/shared/src/main/scala/special/collection/CollsUnit.scala +++ b/sc/shared/src/main/scala/special/collection/CollsUnit.scala @@ -1,5 +1,5 @@ package sigma { - import sigma.compiler.{Base, IRContext} + import sigma.compiler.ir.{Base, IRContext} /** Staged version of collection interfaces which is used in graph-based IR to represent * methods of Coll and CollBuilder. diff --git a/sc/shared/src/main/scala/special/collection/impl/CollsImpl.scala b/sc/shared/src/main/scala/special/collection/impl/CollsImpl.scala index a14b2eb3b4..09c888bf49 100644 --- a/sc/shared/src/main/scala/special/collection/impl/CollsImpl.scala +++ b/sc/shared/src/main/scala/special/collection/impl/CollsImpl.scala @@ -2,12 +2,12 @@ package sigma import scala.language.{existentials, implicitConversions} import scalan._ -import sigma.compiler.IRContext +import sigma.compiler.ir.IRContext import scala.collection.compat.immutable.ArraySeq package impl { - import sigma.compiler.{Base, GraphIRReflection, ModuleInfo, IRContext} + import sigma.compiler.ir.{Base, GraphIRReflection, ModuleInfo, IRContext} import sigma.data.{Nullable, RType} import sigma.reflection.{RClass, RMethod} diff --git a/sc/shared/src/main/scala/special/sigma/SigmaDslUnit.scala b/sc/shared/src/main/scala/special/sigma/SigmaDslUnit.scala index a6fb60870c..46c93558af 100644 --- a/sc/shared/src/main/scala/special/sigma/SigmaDslUnit.scala +++ b/sc/shared/src/main/scala/special/sigma/SigmaDslUnit.scala @@ -1,6 +1,6 @@ package sigma { import scalan._ - import sigma.compiler.{Base, IRContext} + import sigma.compiler.ir.{Base, IRContext} trait SigmaDsl extends Base { self: IRContext => trait BigInt extends Def[BigInt] { diff --git a/sc/shared/src/main/scala/special/sigma/impl/SigmaDslImpl.scala b/sc/shared/src/main/scala/special/sigma/impl/SigmaDslImpl.scala index a76ddb47d4..6b26a2b100 100644 --- a/sc/shared/src/main/scala/special/sigma/impl/SigmaDslImpl.scala +++ b/sc/shared/src/main/scala/special/sigma/impl/SigmaDslImpl.scala @@ -2,12 +2,12 @@ package sigma import scala.language.{existentials, implicitConversions} import scalan._ -import sigma.compiler.IRContext +import sigma.compiler.ir.IRContext import scala.collection.compat.immutable.ArraySeq package impl { - import sigma.compiler.{Base, GraphIRReflection, ModuleInfo, IRContext} + import sigma.compiler.ir.{Base, GraphIRReflection, ModuleInfo, IRContext} import sigma.data.{Nullable, RType} import sigma.reflection.{RClass, RMethod} diff --git a/sc/shared/src/main/scala/special/sigma/wrappers/WrappersModule.scala b/sc/shared/src/main/scala/special/sigma/wrappers/WrappersModule.scala index 6620d9db8f..7d0bcc6b59 100644 --- a/sc/shared/src/main/scala/special/sigma/wrappers/WrappersModule.scala +++ b/sc/shared/src/main/scala/special/sigma/wrappers/WrappersModule.scala @@ -1,6 +1,6 @@ package sigma.wrappers -import sigma.compiler.IRContext +import sigma.compiler.ir.IRContext trait WrappersModule extends special.wrappers.WrappersModule { self: IRContext => } diff --git a/sc/shared/src/main/scala/special/wrappers/WrappersModule.scala b/sc/shared/src/main/scala/special/wrappers/WrappersModule.scala index 0d67f6147a..0003fd6464 100644 --- a/sc/shared/src/main/scala/special/wrappers/WrappersModule.scala +++ b/sc/shared/src/main/scala/special/wrappers/WrappersModule.scala @@ -1,6 +1,6 @@ package special.wrappers -import sigma.compiler.IRContext +import sigma.compiler.ir.IRContext import wrappers.scala.WOptionsModule import wrappers.scalan.WRTypesModule import wrappers.special.WSpecialPredefsModule diff --git a/sc/shared/src/main/scala/wrappers/scala/WOptions.scala b/sc/shared/src/main/scala/wrappers/scala/WOptions.scala index 4f41d0d025..b59692ebd1 100644 --- a/sc/shared/src/main/scala/wrappers/scala/WOptions.scala +++ b/sc/shared/src/main/scala/wrappers/scala/WOptions.scala @@ -1,6 +1,6 @@ package wrappers.scala { import scalan._ - import sigma.compiler.{Base, IRContext} + import sigma.compiler.ir.{Base, IRContext} import special.wrappers.WrappersModule trait WOptions extends Base { self: IRContext => diff --git a/sc/shared/src/main/scala/wrappers/scala/impl/WOptionsImpl.scala b/sc/shared/src/main/scala/wrappers/scala/impl/WOptionsImpl.scala index 915a271de9..8bb0b1e5e1 100644 --- a/sc/shared/src/main/scala/wrappers/scala/impl/WOptionsImpl.scala +++ b/sc/shared/src/main/scala/wrappers/scala/impl/WOptionsImpl.scala @@ -2,14 +2,14 @@ package wrappers.scala import scala.language.{existentials, implicitConversions} import scalan._ -import sigma.compiler.IRContext +import sigma.compiler.ir.IRContext import special.wrappers.WrappersModule import special.wrappers.OptionWrapSpec import scala.collection.compat.immutable.ArraySeq package impl { - import sigma.compiler.{Base, GraphIRReflection, ModuleInfo, IRContext} + import sigma.compiler.ir.{Base, GraphIRReflection, ModuleInfo, IRContext} import sigma.data.{Nullable, RType} import sigma.reflection.{RClass, RMethod} diff --git a/sc/shared/src/main/scala/wrappers/scalan/WRTypes.scala b/sc/shared/src/main/scala/wrappers/scalan/WRTypes.scala index 99f87242df..41242c4ce3 100644 --- a/sc/shared/src/main/scala/wrappers/scalan/WRTypes.scala +++ b/sc/shared/src/main/scala/wrappers/scalan/WRTypes.scala @@ -1,6 +1,6 @@ package wrappers.scalan { import scalan._ - import sigma.compiler.{Base, IRContext} + import sigma.compiler.ir.{Base, IRContext} trait WRTypes extends Base { self: IRContext => diff --git a/sc/shared/src/main/scala/wrappers/scalan/impl/WRTypesImpl.scala b/sc/shared/src/main/scala/wrappers/scalan/impl/WRTypesImpl.scala index 55923c757b..0e8b32230a 100644 --- a/sc/shared/src/main/scala/wrappers/scalan/impl/WRTypesImpl.scala +++ b/sc/shared/src/main/scala/wrappers/scalan/impl/WRTypesImpl.scala @@ -1,6 +1,6 @@ package wrappers.scalan -import sigma.compiler.IRContext +import sigma.compiler.ir.IRContext import scala.language.{existentials, implicitConversions} import sigma.data.RType import special.wrappers.RTypeWrapSpec @@ -8,7 +8,7 @@ import special.wrappers.RTypeWrapSpec import scala.collection.compat.immutable.ArraySeq package impl { - import sigma.compiler.{Base, GraphIRReflection, ModuleInfo, IRContext} + import sigma.compiler.ir.{Base, GraphIRReflection, ModuleInfo, IRContext} import sigma.reflection.{RClass, RMethod} // Abs ----------------------------------- diff --git a/sc/shared/src/main/scala/wrappers/special/WSpecialPredefs.scala b/sc/shared/src/main/scala/wrappers/special/WSpecialPredefs.scala index 33f39f2458..45065b324b 100644 --- a/sc/shared/src/main/scala/wrappers/special/WSpecialPredefs.scala +++ b/sc/shared/src/main/scala/wrappers/special/WSpecialPredefs.scala @@ -1,6 +1,6 @@ package wrappers.special { import scalan._ - import sigma.compiler.{Base, IRContext} + import sigma.compiler.ir.{Base, IRContext} trait WSpecialPredefs extends Base { self: IRContext => trait WSpecialPredef extends Def[WSpecialPredef]; diff --git a/sc/shared/src/main/scala/wrappers/special/impl/WSpecialPredefsImpl.scala b/sc/shared/src/main/scala/wrappers/special/impl/WSpecialPredefsImpl.scala index 7ec5d9bb53..6e763850bd 100644 --- a/sc/shared/src/main/scala/wrappers/special/impl/WSpecialPredefsImpl.scala +++ b/sc/shared/src/main/scala/wrappers/special/impl/WSpecialPredefsImpl.scala @@ -2,10 +2,10 @@ package wrappers.special import scala.language.{existentials, implicitConversions} import scalan._ -import sigma.compiler.IRContext +import sigma.compiler.ir.IRContext package impl { - import sigma.compiler.{Base, GraphIRReflection, ModuleInfo, IRContext} + import sigma.compiler.ir.{Base, GraphIRReflection, ModuleInfo, IRContext} import sigma.data.Nullable import sigma.reflection.RClass diff --git a/sc/shared/src/test/scala/org/ergoplatform/dsl/TestContractSpec.scala b/sc/shared/src/test/scala/org/ergoplatform/dsl/TestContractSpec.scala index b6abfc1391..0216f71f21 100644 --- a/sc/shared/src/test/scala/org/ergoplatform/dsl/TestContractSpec.scala +++ b/sc/shared/src/test/scala/org/ergoplatform/dsl/TestContractSpec.scala @@ -20,7 +20,7 @@ import sigmastate.helpers.TestingHelpers._ import sigma.ast.syntax.ValueOps import sigma.{AnyValue, Evaluation, SigmaProp} import ErgoTree.ZeroHeader -import sigma.compiler.IRContext +import sigma.compiler.ir.IRContext case class TestContractSpec(testSuite: CompilerTestingCommons)(implicit val IR: IRContext) extends ContractSpec { diff --git a/sc/shared/src/test/scala/scalan/BaseLiftableTests.scala b/sc/shared/src/test/scala/scalan/BaseLiftableTests.scala index ae1cc75e73..a9da1792ec 100644 --- a/sc/shared/src/test/scala/scalan/BaseLiftableTests.scala +++ b/sc/shared/src/test/scala/scalan/BaseLiftableTests.scala @@ -1,6 +1,6 @@ package scalan -import sigma.compiler.IRContext +import sigma.compiler.ir.IRContext trait BaseLiftableTests { self: BaseCtxTests => diff --git a/sc/shared/src/test/scala/scalan/LibraryTests.scala b/sc/shared/src/test/scala/scalan/LibraryTests.scala index ef7c9f8b07..b21bd2daf1 100644 --- a/sc/shared/src/test/scala/scalan/LibraryTests.scala +++ b/sc/shared/src/test/scala/scalan/LibraryTests.scala @@ -1,6 +1,6 @@ package scalan -import sigma.compiler.IRContext +import sigma.compiler.ir.IRContext import sigma.util.BenchmarkUtil.{measure, measureTime} class Benchmark[T <: IRContext](createContext: => T) { diff --git a/sc/shared/src/test/scala/scalan/TestContexts.scala b/sc/shared/src/test/scala/scalan/TestContexts.scala index 8a0caae69f..82a6d6b21c 100644 --- a/sc/shared/src/test/scala/scalan/TestContexts.scala +++ b/sc/shared/src/test/scala/scalan/TestContexts.scala @@ -1,6 +1,6 @@ package scalan -import sigma.compiler.{GraphIRReflection, IRContext} +import sigma.compiler.ir.{GraphIRReflection, IRContext} import sigma.reflection.RMethod import sigma.{BaseNestedTests, BaseShouldTests, BaseTests, TestUtils} diff --git a/sc/shared/src/test/scala/scalan/TestLibrary.scala b/sc/shared/src/test/scala/scalan/TestLibrary.scala index 91eb2d2e0b..cb3608d4c3 100644 --- a/sc/shared/src/test/scala/scalan/TestLibrary.scala +++ b/sc/shared/src/test/scala/scalan/TestLibrary.scala @@ -1,6 +1,6 @@ package scalan -import sigma.compiler.{GraphIRReflection, IRContext} +import sigma.compiler.ir.{GraphIRReflection, IRContext} trait TestLibrary extends IRContext { import CollBuilder._ diff --git a/sc/shared/src/test/scala/sigma/CollsStagingTests.scala b/sc/shared/src/test/scala/sigma/CollsStagingTests.scala index 82e77937fe..b26c7d4119 100644 --- a/sc/shared/src/test/scala/sigma/CollsStagingTests.scala +++ b/sc/shared/src/test/scala/sigma/CollsStagingTests.scala @@ -3,7 +3,7 @@ package sigma import scala.language.reflectiveCalls import special.wrappers.WrappersTests import scalan._ -import sigma.compiler.IRContext +import sigma.compiler.ir.IRContext import sigma.data.CollOverArrayBuilder class CollsStagingTests extends WrappersTests { diff --git a/sc/shared/src/test/scala/sigma/SigmaDslStaginTests.scala b/sc/shared/src/test/scala/sigma/SigmaDslStaginTests.scala index 5b951bec38..bcd4b21129 100644 --- a/sc/shared/src/test/scala/sigma/SigmaDslStaginTests.scala +++ b/sc/shared/src/test/scala/sigma/SigmaDslStaginTests.scala @@ -2,7 +2,7 @@ package sigma import org.scalatest.BeforeAndAfterAll import scalan.{BaseCtxTests, BaseLiftableTests} -import sigma.compiler.IRContext +import sigma.compiler.ir.IRContext import sigma.data.TrivialProp import sigma.eval.Extensions.toAnyValue import sigmastate.eval._ diff --git a/sc/shared/src/test/scala/sigma/SigmaDslTesting.scala b/sc/shared/src/test/scala/sigma/SigmaDslTesting.scala index 11dd9b7e68..31e873699b 100644 --- a/sc/shared/src/test/scala/sigma/SigmaDslTesting.scala +++ b/sc/shared/src/test/scala/sigma/SigmaDslTesting.scala @@ -31,7 +31,7 @@ import sigmastate.helpers.{CompilerTestingCommons, ErgoLikeContextTesting, ErgoL import sigmastate.interpreter.Interpreter.{ScriptEnv, VerificationResult} import sigmastate.interpreter._ import sigma.ast.Apply -import sigma.compiler.{CompiletimeIRContext, IRContext} +import sigma.compiler.ir.{CompiletimeIRContext, IRContext} import sigma.eval.Extensions.SigmaBooleanOps import sigma.interpreter.{ContextExtension, ProverResult} import sigma.serialization.ValueSerializer diff --git a/sc/shared/src/test/scala/sigmastate/CompilerTestsBase.scala b/sc/shared/src/test/scala/sigmastate/CompilerTestsBase.scala index 0a94ca85bd..19c0a4b134 100644 --- a/sc/shared/src/test/scala/sigmastate/CompilerTestsBase.scala +++ b/sc/shared/src/test/scala/sigmastate/CompilerTestsBase.scala @@ -7,7 +7,7 @@ import sigma.ast.{ErgoTree, SType, TransformingSigmaBuilder, Value} import org.ergoplatform.ErgoAddressEncoder.TestnetNetworkPrefix import sigma.ast.syntax.{SValue, SigmaPropValue} import sigma.serialization.ValueSerializer -import sigma.compiler.IRContext +import sigma.compiler.ir.IRContext import sigma.ast.syntax.ValueOps import sigmastate.helpers.{NegativeTesting, SigmaPPrint} diff --git a/sc/shared/src/test/scala/sigmastate/ScriptVersionSwitchSpecification.scala b/sc/shared/src/test/scala/sigmastate/ScriptVersionSwitchSpecification.scala index 42c2b8706b..ecc1dace81 100644 --- a/sc/shared/src/test/scala/sigmastate/ScriptVersionSwitchSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/ScriptVersionSwitchSpecification.scala @@ -14,7 +14,7 @@ import sigmastate.interpreter.CErgoTreeEvaluator.DefaultEvalSettings import sigma.eval.EvalSettings.EvaluationMode import sigmastate.interpreter._ import sigma.ast.syntax.ValueOps -import sigma.compiler.IRContext +import sigma.compiler.ir.IRContext import sigma.data.CBox import sigma.eval.EvalSettings import sigma.exceptions.InterpreterException diff --git a/sc/shared/src/test/scala/sigmastate/eval/ErgoScriptTestkit.scala b/sc/shared/src/test/scala/sigmastate/eval/ErgoScriptTestkit.scala index 2d8b613fa3..90d9cb8b6d 100644 --- a/sc/shared/src/test/scala/sigmastate/eval/ErgoScriptTestkit.scala +++ b/sc/shared/src/test/scala/sigmastate/eval/ErgoScriptTestkit.scala @@ -14,7 +14,7 @@ import sigmastate.helpers.{ContextEnrichingTestProvingInterpreter, ErgoLikeConte import sigmastate.interpreter.Interpreter.ScriptEnv import sigmastate.interpreter.CErgoTreeEvaluator import sigma.ast.syntax.ValueOps -import sigma.compiler.IRContext +import sigma.compiler.ir.IRContext import sigma.interpreter.ContextExtension import sigmastate.lang.{CompilerResult, CompilerSettings, LangTests, SigmaCompiler} import sigma.serialization.ErgoTreeSerializer.DefaultSerializer diff --git a/sc/shared/src/test/scala/sigmastate/eval/ErgoTreeBuildingTest.scala b/sc/shared/src/test/scala/sigmastate/eval/ErgoTreeBuildingTest.scala index e8fc16e953..11ef6f4fac 100644 --- a/sc/shared/src/test/scala/sigmastate/eval/ErgoTreeBuildingTest.scala +++ b/sc/shared/src/test/scala/sigmastate/eval/ErgoTreeBuildingTest.scala @@ -8,7 +8,7 @@ import scalan.BaseCtxTests import sigma.ast.syntax.ValueOps import sigmastate.lang.LangTests import sigma.ast.Apply -import sigma.compiler.IRContext +import sigma.compiler.ir.IRContext class ErgoTreeBuildingTest extends BaseCtxTests with LangTests with ExampleContracts with ErgoScriptTestkit { diff --git a/sc/shared/src/test/scala/sigmastate/helpers/CompilerTestingCommons.scala b/sc/shared/src/test/scala/sigmastate/helpers/CompilerTestingCommons.scala index 9539bfb135..179fd6b436 100644 --- a/sc/shared/src/test/scala/sigmastate/helpers/CompilerTestingCommons.scala +++ b/sc/shared/src/test/scala/sigmastate/helpers/CompilerTestingCommons.scala @@ -12,7 +12,7 @@ import sigma.data.{RType, SigmaBoolean} import sigma.validation.ValidationException import sigma.validation.ValidationRules.CheckSerializableTypeCode import sigma.ast.syntax.{SValue, SigmaPropValue} -import sigma.compiler.IRContext +import sigma.compiler.ir.IRContext import sigma.eval.{CostDetails, EvalSettings, Extensions, GivenCost, TracedCost} import sigmastate.helpers.TestingHelpers._ import sigma.interpreter.ContextExtension.VarBinding diff --git a/sc/shared/src/test/scala/sigmastate/serialization/ErgoTreeSerializerSpecification.scala b/sc/shared/src/test/scala/sigmastate/serialization/ErgoTreeSerializerSpecification.scala index bbdc4cbdce..f7129a7723 100644 --- a/sc/shared/src/test/scala/sigmastate/serialization/ErgoTreeSerializerSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/serialization/ErgoTreeSerializerSpecification.scala @@ -10,7 +10,7 @@ import sigma.util.Extensions.SigmaPropOps import sigma.validation.ValidationException import ErgoTree.EmptyConstants import ErgoTree.HeaderType -import sigma.compiler.IRContext +import sigma.compiler.ir.IRContext import sigma.eval.Extensions.SigmaBooleanOps import sigmastate._ import sigmastate.helpers.CompilerTestingCommons diff --git a/sc/shared/src/test/scala/sigmastate/utxo/AVLTreeScriptsSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/AVLTreeScriptsSpecification.scala index 7cc36f798d..6b0c0080c9 100644 --- a/sc/shared/src/test/scala/sigmastate/utxo/AVLTreeScriptsSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/utxo/AVLTreeScriptsSpecification.scala @@ -18,7 +18,7 @@ import sigma.ast.syntax._ import sigma.Coll import sigma.ast.SAvlTree import sigma.ast.syntax.{GetVarByteArray, OptionValueOps} -import sigma.compiler.IRContext +import sigma.compiler.ir.IRContext import sigma.data.{AvlTreeData, AvlTreeFlags, CSigmaProp, TrivialProp} import sigma.eval.SigmaDsl import sigma.interpreter.ProverResult diff --git a/sc/shared/src/test/scala/sigmastate/utxo/UsingContextPropertiesSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/UsingContextPropertiesSpecification.scala index 5405c32b58..77e78aa6bf 100644 --- a/sc/shared/src/test/scala/sigmastate/utxo/UsingContextPropertiesSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/utxo/UsingContextPropertiesSpecification.scala @@ -7,7 +7,7 @@ import sigmastate.helpers.CompilerTestingCommons import org.ergoplatform.dsl.{ContractSpec, SigmaContractSyntax, TestContractSpec} import org.ergoplatform.ErgoBox import scorex.crypto.hash.Blake2b256 -import sigma.compiler.IRContext +import sigma.compiler.ir.IRContext import sigma.data.{CSigmaProp, TrivialProp} class UsingContextPropertiesSpecification extends CompilerTestingCommons diff --git a/sc/shared/src/test/scala/sigmastate/utxo/blockchain/BlockchainSimulationTestingCommons.scala b/sc/shared/src/test/scala/sigmastate/utxo/blockchain/BlockchainSimulationTestingCommons.scala index 4fe0ecc136..16b4e3e232 100644 --- a/sc/shared/src/test/scala/sigmastate/utxo/blockchain/BlockchainSimulationTestingCommons.scala +++ b/sc/shared/src/test/scala/sigmastate/utxo/blockchain/BlockchainSimulationTestingCommons.scala @@ -17,7 +17,7 @@ import scorex.util._ import sigma.Colls import sigma.data.{AvlTreeData, AvlTreeFlags} import ErgoTree.ZeroHeader -import sigma.compiler.IRContext +import sigma.compiler.ir.IRContext import sigma.eval.Extensions.SigmaBooleanOps import sigma.interpreter.ContextExtension import sigmastate.interpreter.Interpreter.{ScriptNameProp, emptyEnv} diff --git a/sc/shared/src/test/scala/sigmastate/utxo/examples/IcoExample.scala b/sc/shared/src/test/scala/sigmastate/utxo/examples/IcoExample.scala index 9b5c796af8..556c56bc03 100644 --- a/sc/shared/src/test/scala/sigmastate/utxo/examples/IcoExample.scala +++ b/sc/shared/src/test/scala/sigmastate/utxo/examples/IcoExample.scala @@ -22,7 +22,7 @@ import sigmastate.helpers.{CompilerTestingCommons, ContextEnrichingTestProvingIn import sigmastate.interpreter.Interpreter.ScriptNameProp import sigmastate.interpreter.Interpreter import sigma.ast.syntax._ -import sigma.compiler.IRContext +import sigma.compiler.ir.IRContext import sigma.eval.SigmaDsl import sigma.serialization.ErgoTreeSerializer import sigma.serialization.ErgoTreeSerializer.DefaultSerializer diff --git a/sc/shared/src/test/scala/sigmastate/utxo/examples/LetsSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/examples/LetsSpecification.scala index db3f3bc46b..556fbf9c06 100644 --- a/sc/shared/src/test/scala/sigmastate/utxo/examples/LetsSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/utxo/examples/LetsSpecification.scala @@ -15,7 +15,7 @@ import sigmastate.helpers.TestingHelpers._ import sigmastate.interpreter.Interpreter.ScriptNameProp import sigma.serialization.ErgoTreeSerializer import sigma.ast.syntax._ -import sigma.compiler.IRContext +import sigma.compiler.ir.IRContext import sigma.eval.SigmaDsl import scala.util.Random From 7247cf81c9c31a2e5336bde70adbe65315341923 Mon Sep 17 00:00:00 2001 From: Alexander Slesarenko Date: Thu, 16 May 2024 11:23:23 +0100 Subject: [PATCH 074/314] refactor-ir-cake: move classes around in sigma.compiler.ir --- .../src/main/scala/sigma/compiler/{ir => }/Exceptions.scala | 2 +- sc/shared/src/main/scala/sigma/compiler/ir/Base.scala | 2 +- .../src/main/scala/sigma/compiler/ir/DefRewriting.scala | 1 - .../src/main/scala/sigma/compiler/ir/GraphBuilding.scala | 2 +- sc/shared/src/main/scala/sigma/compiler/ir/IRContext.scala | 1 + .../src/main/scala/sigma/compiler/ir/MethodCalls.scala | 1 - sc/shared/src/main/scala/sigma/compiler/ir/Modules.scala | 2 ++ .../scala/sigma/compiler/ir/{ => core}/MutableLazy.scala | 2 +- .../scala/sigma/compiler/ir/{ => meta}/ModuleInfo.scala | 4 +--- .../src/main/scala/sigma/compiler/ir/meta/SSymName.scala | 6 +----- .../src/main/scala/special/collection/impl/CollsImpl.scala | 3 ++- .../src/main/scala/special/sigma/impl/SigmaDslImpl.scala | 3 ++- .../src/main/scala/wrappers/scala/impl/WOptionsImpl.scala | 3 ++- .../src/main/scala/wrappers/scalan/impl/WRTypesImpl.scala | 3 ++- .../scala/wrappers/special/impl/WSpecialPredefsImpl.scala | 4 +++- 15 files changed, 20 insertions(+), 19 deletions(-) rename sc/shared/src/main/scala/sigma/compiler/{ir => }/Exceptions.scala (93%) rename sc/shared/src/main/scala/sigma/compiler/ir/{ => core}/MutableLazy.scala (96%) rename sc/shared/src/main/scala/sigma/compiler/ir/{ => meta}/ModuleInfo.scala (88%) diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/Exceptions.scala b/sc/shared/src/main/scala/sigma/compiler/Exceptions.scala similarity index 93% rename from sc/shared/src/main/scala/sigma/compiler/ir/Exceptions.scala rename to sc/shared/src/main/scala/sigma/compiler/Exceptions.scala index 8ab128a06e..9147df943a 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/Exceptions.scala +++ b/sc/shared/src/main/scala/sigma/compiler/Exceptions.scala @@ -1,4 +1,4 @@ -package scalan +package sigma.compiler.ir /** * Can be thrown in staged method body to prevent body unfolding. diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/Base.scala b/sc/shared/src/main/scala/sigma/compiler/ir/Base.scala index 939d364953..48e3e5d09e 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/Base.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/Base.scala @@ -1,7 +1,7 @@ package sigma.compiler.ir import debox.{cfor, Buffer => DBuffer} -import scalan.MutableLazy +import sigma.compiler.ir.core.MutableLazy import sigma.data.OverloadHack.Overloaded1 import sigma.data.{AVHashMap, Nullable, RType} import sigma.reflection.RConstructor diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/DefRewriting.scala b/sc/shared/src/main/scala/sigma/compiler/ir/DefRewriting.scala index fe289cafe0..a37eed2558 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/DefRewriting.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/DefRewriting.scala @@ -1,6 +1,5 @@ package sigma.compiler.ir -import scalan.DelayInvokeException import sigma.data.ExactNumeric trait DefRewriting { scalan: IRContext => 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 71029b4628..7c7b80d39a 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/GraphBuilding.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/GraphBuilding.scala @@ -1,11 +1,11 @@ package sigma.compiler.ir import org.ergoplatform._ -import scalan.MutableLazy import sigma.ast.TypeCodes.LastConstantCode import sigma.ast.Value.Typed import sigma.ast.syntax.{SValue, ValueOps} import sigma.ast._ +import sigma.compiler.ir.core.MutableLazy import sigma.crypto.EcPointType import sigma.data.ExactIntegral.{ByteIsExactIntegral, IntIsExactIntegral, LongIsExactIntegral, ShortIsExactIntegral} import sigma.data.ExactOrdering.{ByteIsExactOrdering, IntIsExactOrdering, LongIsExactOrdering, ShortIsExactOrdering} diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/IRContext.scala b/sc/shared/src/main/scala/sigma/compiler/ir/IRContext.scala index 7fae587ac4..b61e76e285 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/IRContext.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/IRContext.scala @@ -1,6 +1,7 @@ package sigma.compiler.ir import scalan._ +import sigma.compiler.ir.core.MutableLazy import sigma.compiler.ir.primitives._ import sigma.data.{Nullable, RType} import sigma.util.MemoizedFunc diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/MethodCalls.scala b/sc/shared/src/main/scala/sigma/compiler/ir/MethodCalls.scala index de96900c62..fff69557b3 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/MethodCalls.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/MethodCalls.scala @@ -1,7 +1,6 @@ package sigma.compiler.ir import debox.{cfor, Buffer => DBuffer} -import scalan.DelayInvokeException import sigma.reflection.RMethod import sigma.util.CollectionUtil.TraversableOps diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/Modules.scala b/sc/shared/src/main/scala/sigma/compiler/ir/Modules.scala index cafee1ef84..b14d4471d1 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/Modules.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/Modules.scala @@ -1,5 +1,7 @@ package sigma.compiler.ir +import sigma.compiler.ir.meta.ModuleInfo + trait Modules extends Base { self: IRContext => /** Whether staged modules should be registered when cake is constructed and initialized. */ diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/MutableLazy.scala b/sc/shared/src/main/scala/sigma/compiler/ir/core/MutableLazy.scala similarity index 96% rename from sc/shared/src/main/scala/sigma/compiler/ir/MutableLazy.scala rename to sc/shared/src/main/scala/sigma/compiler/ir/core/MutableLazy.scala index 5b6a579476..efaab623a3 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/MutableLazy.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/core/MutableLazy.scala @@ -1,4 +1,4 @@ -package scalan +package sigma.compiler.ir.core import scala.language.implicitConversions diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/ModuleInfo.scala b/sc/shared/src/main/scala/sigma/compiler/ir/meta/ModuleInfo.scala similarity index 88% rename from sc/shared/src/main/scala/sigma/compiler/ir/ModuleInfo.scala rename to sc/shared/src/main/scala/sigma/compiler/ir/meta/ModuleInfo.scala index ccd71ffdc0..3ccdca18ac 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/ModuleInfo.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/meta/ModuleInfo.scala @@ -1,6 +1,4 @@ -package sigma.compiler.ir - -import scalan.meta.SSymName +package sigma.compiler.ir.meta /** Information about generated Special library module. * Instances are created in generated code. diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/meta/SSymName.scala b/sc/shared/src/main/scala/sigma/compiler/ir/meta/SSymName.scala index b0f8dae6d2..944b505250 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/meta/SSymName.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/meta/SSymName.scala @@ -1,17 +1,13 @@ -package scalan.meta +package sigma.compiler.ir.meta import sigma.util.StringUtil.StringUtilExtensions -case class ImportItem(packageName: String, importedNames: List[String]) - case class SSymName(packageName: String, name: String) { import SSymName._ def mkFullName = fullNameString(packageName, name) } object SSymName { - /** Wildcard character used to signify importing all names from namespace */ - val ImportAllWildcard = "*" def fullNameString(packageName: String, name: String): String = if (packageName.isNullOrEmpty) name else s"$packageName.$name" } \ No newline at end of file diff --git a/sc/shared/src/main/scala/special/collection/impl/CollsImpl.scala b/sc/shared/src/main/scala/special/collection/impl/CollsImpl.scala index 09c888bf49..dcfdf25217 100644 --- a/sc/shared/src/main/scala/special/collection/impl/CollsImpl.scala +++ b/sc/shared/src/main/scala/special/collection/impl/CollsImpl.scala @@ -7,7 +7,8 @@ import sigma.compiler.ir.IRContext import scala.collection.compat.immutable.ArraySeq package impl { - import sigma.compiler.ir.{Base, GraphIRReflection, ModuleInfo, IRContext} + import sigma.compiler.ir.meta.ModuleInfo + import sigma.compiler.ir.{Base, GraphIRReflection, IRContext} import sigma.data.{Nullable, RType} import sigma.reflection.{RClass, RMethod} diff --git a/sc/shared/src/main/scala/special/sigma/impl/SigmaDslImpl.scala b/sc/shared/src/main/scala/special/sigma/impl/SigmaDslImpl.scala index 6b26a2b100..17ad187b91 100644 --- a/sc/shared/src/main/scala/special/sigma/impl/SigmaDslImpl.scala +++ b/sc/shared/src/main/scala/special/sigma/impl/SigmaDslImpl.scala @@ -7,7 +7,8 @@ import sigma.compiler.ir.IRContext import scala.collection.compat.immutable.ArraySeq package impl { - import sigma.compiler.ir.{Base, GraphIRReflection, ModuleInfo, IRContext} + import sigma.compiler.ir.meta.ModuleInfo + import sigma.compiler.ir.{Base, GraphIRReflection, IRContext} import sigma.data.{Nullable, RType} import sigma.reflection.{RClass, RMethod} diff --git a/sc/shared/src/main/scala/wrappers/scala/impl/WOptionsImpl.scala b/sc/shared/src/main/scala/wrappers/scala/impl/WOptionsImpl.scala index 8bb0b1e5e1..048b27b772 100644 --- a/sc/shared/src/main/scala/wrappers/scala/impl/WOptionsImpl.scala +++ b/sc/shared/src/main/scala/wrappers/scala/impl/WOptionsImpl.scala @@ -9,7 +9,8 @@ import special.wrappers.OptionWrapSpec import scala.collection.compat.immutable.ArraySeq package impl { - import sigma.compiler.ir.{Base, GraphIRReflection, ModuleInfo, IRContext} + import sigma.compiler.ir.meta.ModuleInfo + import sigma.compiler.ir.{Base, GraphIRReflection, IRContext} import sigma.data.{Nullable, RType} import sigma.reflection.{RClass, RMethod} diff --git a/sc/shared/src/main/scala/wrappers/scalan/impl/WRTypesImpl.scala b/sc/shared/src/main/scala/wrappers/scalan/impl/WRTypesImpl.scala index 0e8b32230a..d90498e4c5 100644 --- a/sc/shared/src/main/scala/wrappers/scalan/impl/WRTypesImpl.scala +++ b/sc/shared/src/main/scala/wrappers/scalan/impl/WRTypesImpl.scala @@ -8,7 +8,8 @@ import special.wrappers.RTypeWrapSpec import scala.collection.compat.immutable.ArraySeq package impl { - import sigma.compiler.ir.{Base, GraphIRReflection, ModuleInfo, IRContext} + import sigma.compiler.ir.meta.ModuleInfo + import sigma.compiler.ir.{Base, GraphIRReflection, IRContext} import sigma.reflection.{RClass, RMethod} // Abs ----------------------------------- diff --git a/sc/shared/src/main/scala/wrappers/special/impl/WSpecialPredefsImpl.scala b/sc/shared/src/main/scala/wrappers/special/impl/WSpecialPredefsImpl.scala index 6e763850bd..66820b6792 100644 --- a/sc/shared/src/main/scala/wrappers/special/impl/WSpecialPredefsImpl.scala +++ b/sc/shared/src/main/scala/wrappers/special/impl/WSpecialPredefsImpl.scala @@ -5,7 +5,9 @@ import scalan._ import sigma.compiler.ir.IRContext package impl { - import sigma.compiler.ir.{Base, GraphIRReflection, ModuleInfo, IRContext} + import sigma.compiler.ir.core.MutableLazy + import sigma.compiler.ir.meta.ModuleInfo + import sigma.compiler.ir.{Base, GraphIRReflection, IRContext} import sigma.data.Nullable import sigma.reflection.RClass From 80114f1561e8b5d889543b992bb046553ad45c4e Mon Sep 17 00:00:00 2001 From: Alexander Slesarenko Date: Thu, 16 May 2024 11:39:09 +0100 Subject: [PATCH 075/314] refactor-ir-cake: SigmaCompiler moved to sigma.compiler package --- .../main/scala/sigmastate/lang/js/SigmaCompiler.scala | 4 ++-- .../scala/org/ergoplatform/ErgoScriptPredef.scala | 2 +- .../src/main/scala/sigma/compiler/Exceptions.scala | 2 +- .../lang => sigma/compiler}/SigmaCompiler.scala | 4 +++- .../compiler}/SigmaTemplateCompiler.scala | 3 ++- .../main/scala/sigma/compiler/ir/DefRewriting.scala | 1 + .../main/scala/sigma/compiler/ir/MethodCalls.scala | 1 + .../lang => sigma/compiler/phases}/SigmaBinder.scala | 2 +- .../lang => sigma/compiler/phases}/SigmaTyper.scala | 11 +++++------ .../src/test/scala/sigmastate/CompilerTestsBase.scala | 2 +- .../test/scala/sigmastate/ErgoTreeSpecification.scala | 2 +- .../scala/sigmastate/eval/ErgoScriptTestkit.scala | 3 ++- .../sigmastate/helpers/CompilerTestingCommons.scala | 2 +- .../test/scala/sigmastate/lang/SigmaBinderTest.scala | 1 + .../sigmastate/lang/SigmaTemplateCompilerTest.scala | 1 + .../test/scala/sigmastate/lang/SigmaTyperTest.scala | 1 + 16 files changed, 25 insertions(+), 17 deletions(-) rename sc/shared/src/main/scala/{sigmastate/lang => sigma/compiler}/SigmaCompiler.scala (98%) rename sc/shared/src/main/scala/{sigmastate/lang => sigma/compiler}/SigmaTemplateCompiler.scala (96%) rename sc/shared/src/main/scala/{sigmastate/lang => sigma/compiler/phases}/SigmaBinder.scala (99%) rename sc/shared/src/main/scala/{sigmastate/lang => sigma/compiler/phases}/SigmaTyper.scala (99%) diff --git a/sc/js/src/main/scala/sigmastate/lang/js/SigmaCompiler.scala b/sc/js/src/main/scala/sigmastate/lang/js/SigmaCompiler.scala index 6264cd2f82..2fc7556875 100644 --- a/sc/js/src/main/scala/sigmastate/lang/js/SigmaCompiler.scala +++ b/sc/js/src/main/scala/sigmastate/lang/js/SigmaCompiler.scala @@ -15,7 +15,7 @@ import sigma.ast.syntax.ValueOps /** Wrapper exported to JS. */ @JSExportTopLevel("SigmaCompiler") -class SigmaCompiler(_compiler: sigmastate.lang.SigmaCompiler) extends js.Object { +class SigmaCompiler(_compiler: sigma.compiler.SigmaCompiler) extends js.Object { /** Compiles ErgoScript code to ErgoTree. * @@ -59,7 +59,7 @@ object SigmaCompiler extends js.Object { * @return SigmaCompiler instance */ private def create(networkPrefix: Byte): SigmaCompiler = { - val compiler = sigmastate.lang.SigmaCompiler(networkPrefix) + val compiler = sigma.compiler.SigmaCompiler(networkPrefix) new SigmaCompiler(compiler) } } diff --git a/sc/shared/src/main/scala/org/ergoplatform/ErgoScriptPredef.scala b/sc/shared/src/main/scala/org/ergoplatform/ErgoScriptPredef.scala index 60b82a54a2..9eec42a4fb 100644 --- a/sc/shared/src/main/scala/org/ergoplatform/ErgoScriptPredef.scala +++ b/sc/shared/src/main/scala/org/ergoplatform/ErgoScriptPredef.scala @@ -1,11 +1,11 @@ package org.ergoplatform -import sigmastate.lang.SigmaCompiler import org.ergoplatform.ErgoAddressEncoder.NetworkPrefix import sigma.ast.SType import sigma.ast.syntax.SigmaPropValue import sigma.ast.Value import sigma.ast.syntax.ValueOps +import sigma.compiler.SigmaCompiler import sigma.compiler.ir.IRContext object ErgoScriptPredef { diff --git a/sc/shared/src/main/scala/sigma/compiler/Exceptions.scala b/sc/shared/src/main/scala/sigma/compiler/Exceptions.scala index 9147df943a..75b1ecb6a3 100644 --- a/sc/shared/src/main/scala/sigma/compiler/Exceptions.scala +++ b/sc/shared/src/main/scala/sigma/compiler/Exceptions.scala @@ -1,4 +1,4 @@ -package sigma.compiler.ir +package sigma.compiler /** * Can be thrown in staged method body to prevent body unfolding. diff --git a/sc/shared/src/main/scala/sigmastate/lang/SigmaCompiler.scala b/sc/shared/src/main/scala/sigma/compiler/SigmaCompiler.scala similarity index 98% rename from sc/shared/src/main/scala/sigmastate/lang/SigmaCompiler.scala rename to sc/shared/src/main/scala/sigma/compiler/SigmaCompiler.scala index 0a2bb9a355..942154409b 100644 --- a/sc/shared/src/main/scala/sigmastate/lang/SigmaCompiler.scala +++ b/sc/shared/src/main/scala/sigma/compiler/SigmaCompiler.scala @@ -1,4 +1,4 @@ -package sigmastate.lang +package sigma.compiler import fastparse.Parsed import fastparse.Parsed.Success @@ -13,7 +13,9 @@ import sigma.ast._ import sigma.ast.syntax.SValue import SCollectionMethods.{ExistsMethod, ForallMethod, MapMethod} import sigma.compiler.ir.{GraphIRReflection, IRContext} +import sigma.compiler.phases.{SigmaBinder, SigmaTyper} import sigmastate.InterpreterReflection +import sigmastate.lang.SigmaParser /** * @param networkPrefix network prefix to decode an ergo address from string (PK op) diff --git a/sc/shared/src/main/scala/sigmastate/lang/SigmaTemplateCompiler.scala b/sc/shared/src/main/scala/sigma/compiler/SigmaTemplateCompiler.scala similarity index 96% rename from sc/shared/src/main/scala/sigmastate/lang/SigmaTemplateCompiler.scala rename to sc/shared/src/main/scala/sigma/compiler/SigmaTemplateCompiler.scala index 09d27b2489..0b30f9830a 100644 --- a/sc/shared/src/main/scala/sigmastate/lang/SigmaTemplateCompiler.scala +++ b/sc/shared/src/main/scala/sigma/compiler/SigmaTemplateCompiler.scala @@ -1,10 +1,11 @@ -package sigmastate.lang +package sigma.compiler import fastparse.Parsed import org.ergoplatform.sdk.{ContractTemplate, Parameter} import sigma.ast.SourceContext import sigma.ast.syntax.SValue import sigma.compiler.ir.CompiletimeIRContext +import sigmastate.lang.{ContractParser, ParsedContractTemplate} import sigmastate.lang.parsers.ParserException /** Compiler which compiles Ergo contract templates into a [[ContractTemplate]]. */ diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/DefRewriting.scala b/sc/shared/src/main/scala/sigma/compiler/ir/DefRewriting.scala index a37eed2558..d7bb3a9e4d 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/DefRewriting.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/DefRewriting.scala @@ -1,5 +1,6 @@ package sigma.compiler.ir +import sigma.compiler.DelayInvokeException import sigma.data.ExactNumeric trait DefRewriting { scalan: IRContext => diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/MethodCalls.scala b/sc/shared/src/main/scala/sigma/compiler/ir/MethodCalls.scala index fff69557b3..5ecdb823a7 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/MethodCalls.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/MethodCalls.scala @@ -1,6 +1,7 @@ package sigma.compiler.ir import debox.{cfor, Buffer => DBuffer} +import sigma.compiler.DelayInvokeException import sigma.reflection.RMethod import sigma.util.CollectionUtil.TraversableOps diff --git a/sc/shared/src/main/scala/sigmastate/lang/SigmaBinder.scala b/sc/shared/src/main/scala/sigma/compiler/phases/SigmaBinder.scala similarity index 99% rename from sc/shared/src/main/scala/sigmastate/lang/SigmaBinder.scala rename to sc/shared/src/main/scala/sigma/compiler/phases/SigmaBinder.scala index 82aaea7e30..af5be938be 100644 --- a/sc/shared/src/main/scala/sigmastate/lang/SigmaBinder.scala +++ b/sc/shared/src/main/scala/sigma/compiler/phases/SigmaBinder.scala @@ -1,4 +1,4 @@ -package sigmastate.lang +package sigma.compiler.phases import org.ergoplatform.ErgoAddressEncoder.NetworkPrefix import sigma.ast.NoType diff --git a/sc/shared/src/main/scala/sigmastate/lang/SigmaTyper.scala b/sc/shared/src/main/scala/sigma/compiler/phases/SigmaTyper.scala similarity index 99% rename from sc/shared/src/main/scala/sigmastate/lang/SigmaTyper.scala rename to sc/shared/src/main/scala/sigma/compiler/phases/SigmaTyper.scala index 416f2d7fbb..679d98a18f 100644 --- a/sc/shared/src/main/scala/sigmastate/lang/SigmaTyper.scala +++ b/sc/shared/src/main/scala/sigma/compiler/phases/SigmaTyper.scala @@ -1,15 +1,14 @@ -package sigmastate.lang +package sigma.compiler.phases import sigma.ast.SCollection.{SBooleanArray, SByteArray} +import sigma.ast.SigmaPredef._ import sigma.ast._ -import sigma.ast.syntax.SValue +import sigma.ast.syntax.{SValue, _} import sigma.data.{Nullable, SigmaBoolean} -import sigma.util.Extensions.Ensuring -import sigmastate.exceptions._ -import SigmaPredef._ -import sigma.ast.syntax._ import sigma.exceptions.TyperException import sigma.serialization.OpCodes +import sigma.util.Extensions.Ensuring +import sigmastate.exceptions._ import scala.collection.mutable.ArrayBuffer diff --git a/sc/shared/src/test/scala/sigmastate/CompilerTestsBase.scala b/sc/shared/src/test/scala/sigmastate/CompilerTestsBase.scala index 19c0a4b134..f1d5c6aa89 100644 --- a/sc/shared/src/test/scala/sigmastate/CompilerTestsBase.scala +++ b/sc/shared/src/test/scala/sigmastate/CompilerTestsBase.scala @@ -1,7 +1,6 @@ package sigmastate import scala.util.DynamicVariable -import sigmastate.lang.{CompilerResult, CompilerSettings, SigmaCompiler} import sigmastate.interpreter.Interpreter.ScriptEnv import sigma.ast.{ErgoTree, SType, TransformingSigmaBuilder, Value} import org.ergoplatform.ErgoAddressEncoder.TestnetNetworkPrefix @@ -9,6 +8,7 @@ import sigma.ast.syntax.{SValue, SigmaPropValue} import sigma.serialization.ValueSerializer import sigma.compiler.ir.IRContext import sigma.ast.syntax.ValueOps +import sigma.compiler.{CompilerResult, CompilerSettings, SigmaCompiler} import sigmastate.helpers.{NegativeTesting, SigmaPPrint} trait CompilerTestsBase extends TestsBase with NegativeTesting { diff --git a/sc/shared/src/test/scala/sigmastate/ErgoTreeSpecification.scala b/sc/shared/src/test/scala/sigmastate/ErgoTreeSpecification.scala index b0b6273fad..7539bd5e48 100644 --- a/sc/shared/src/test/scala/sigmastate/ErgoTreeSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/ErgoTreeSpecification.scala @@ -17,9 +17,9 @@ import sigmastate.helpers.{ErgoLikeContextTesting, SigmaPPrint} import sigmastate.interpreter.Interpreter.ReductionResult import sigmastate.interpreter.CErgoTreeEvaluator import sigma.ast.syntax._ +import sigma.compiler.CompilerSettings import sigma.eval.EvalSettings import sigma.exceptions.{CostLimitException, InterpreterException} -import sigmastate.lang.CompilerSettings import sigma.serialization.ErgoTreeSerializer.DefaultSerializer import sigmastate.Plus import sigmastate.utils.Helpers.TryOps diff --git a/sc/shared/src/test/scala/sigmastate/eval/ErgoScriptTestkit.scala b/sc/shared/src/test/scala/sigmastate/eval/ErgoScriptTestkit.scala index 90d9cb8b6d..da9ed70efd 100644 --- a/sc/shared/src/test/scala/sigmastate/eval/ErgoScriptTestkit.scala +++ b/sc/shared/src/test/scala/sigmastate/eval/ErgoScriptTestkit.scala @@ -14,9 +14,10 @@ import sigmastate.helpers.{ContextEnrichingTestProvingInterpreter, ErgoLikeConte import sigmastate.interpreter.Interpreter.ScriptEnv import sigmastate.interpreter.CErgoTreeEvaluator import sigma.ast.syntax.ValueOps +import sigma.compiler.{CompilerResult, CompilerSettings, SigmaCompiler} import sigma.compiler.ir.IRContext import sigma.interpreter.ContextExtension -import sigmastate.lang.{CompilerResult, CompilerSettings, LangTests, SigmaCompiler} +import sigmastate.lang.LangTests import sigma.serialization.ErgoTreeSerializer.DefaultSerializer import sigmastate.CompilerTestsBase import sigma.{ContractsTestkit, Context => DContext} diff --git a/sc/shared/src/test/scala/sigmastate/helpers/CompilerTestingCommons.scala b/sc/shared/src/test/scala/sigmastate/helpers/CompilerTestingCommons.scala index 179fd6b436..3b1d6ba3dc 100644 --- a/sc/shared/src/test/scala/sigmastate/helpers/CompilerTestingCommons.scala +++ b/sc/shared/src/test/scala/sigmastate/helpers/CompilerTestingCommons.scala @@ -12,6 +12,7 @@ import sigma.data.{RType, SigmaBoolean} import sigma.validation.ValidationException import sigma.validation.ValidationRules.CheckSerializableTypeCode import sigma.ast.syntax.{SValue, SigmaPropValue} +import sigma.compiler.{CompilerSettings, SigmaCompiler} import sigma.compiler.ir.IRContext import sigma.eval.{CostDetails, EvalSettings, Extensions, GivenCost, TracedCost} import sigmastate.helpers.TestingHelpers._ @@ -19,7 +20,6 @@ import sigma.interpreter.ContextExtension.VarBinding import sigmastate.interpreter.CErgoTreeEvaluator.DefaultProfiler import sigmastate.interpreter.Interpreter.ScriptEnv import sigmastate.interpreter._ -import sigmastate.lang.{CompilerSettings, SigmaCompiler} import sigma.serialization.SigmaSerializer import sigmastate.CompilerTestsBase import sigmastate.eval.CContext diff --git a/sc/shared/src/test/scala/sigmastate/lang/SigmaBinderTest.scala b/sc/shared/src/test/scala/sigmastate/lang/SigmaBinderTest.scala index 1f758370a0..b4b4ad20cd 100644 --- a/sc/shared/src/test/scala/sigmastate/lang/SigmaBinderTest.scala +++ b/sc/shared/src/test/scala/sigmastate/lang/SigmaBinderTest.scala @@ -11,6 +11,7 @@ import sigmastate._ import sigmastate.interpreter.Interpreter.ScriptEnv import SigmaPredef.PredefinedFuncRegistry import sigma.ast.syntax._ +import sigma.compiler.phases.SigmaBinder import sigma.eval.SigmaDsl import sigma.exceptions.BinderException diff --git a/sc/shared/src/test/scala/sigmastate/lang/SigmaTemplateCompilerTest.scala b/sc/shared/src/test/scala/sigmastate/lang/SigmaTemplateCompilerTest.scala index 966a7c4c74..a03d160654 100644 --- a/sc/shared/src/test/scala/sigmastate/lang/SigmaTemplateCompilerTest.scala +++ b/sc/shared/src/test/scala/sigmastate/lang/SigmaTemplateCompilerTest.scala @@ -7,6 +7,7 @@ import org.scalatestplus.scalacheck.ScalaCheckPropertyChecks import sigma.VersionContext import sigma.ast.ErgoTree.HeaderType import sigma.ast.{BinAnd, BoolToSigmaProp, ConstantPlaceholder, ErgoTree, FalseLeaf, GT, Height, IntConstant, LT, SBoolean, SInt, SLong, SString, TrueLeaf} +import sigma.compiler.SigmaTemplateCompiler import sigma.exceptions.TyperException import sigmastate.CompilerTestsBase import sigmastate.interpreter.Interpreter.ScriptEnv diff --git a/sc/shared/src/test/scala/sigmastate/lang/SigmaTyperTest.scala b/sc/shared/src/test/scala/sigmastate/lang/SigmaTyperTest.scala index 5bb38c7998..6b93b098ea 100644 --- a/sc/shared/src/test/scala/sigmastate/lang/SigmaTyperTest.scala +++ b/sc/shared/src/test/scala/sigmastate/lang/SigmaTyperTest.scala @@ -19,6 +19,7 @@ import sigmastate.lang.parsers.ParserException import sigma.serialization.ErgoTreeSerializer import sigma.serialization.generators.ObjectGenerators import sigma.ast.Select +import sigma.compiler.phases.{SigmaBinder, SigmaTyper} import sigma.exceptions.TyperException class SigmaTyperTest extends AnyPropSpec From 66daf525f870626897521ea7ac4fda961b6b32e5 Mon Sep 17 00:00:00 2001 From: Alexander Slesarenko Date: Thu, 16 May 2024 12:14:06 +0100 Subject: [PATCH 076/314] refactor-ir-cake: wrappers moved to sigma.compiler.ir.wrappers package --- .../test/scala/sigmastate/ReflectionGenerator.scala | 4 ++-- .../scala/sigma/compiler/ir/GraphIRReflection.scala | 8 ++++---- .../src/main/scala/sigma/compiler/ir/IRContext.scala | 2 +- .../src/main/scala/sigma/compiler/ir/TypeDescs.scala | 2 +- .../compiler/ir}/wrappers/WrapSpec.scala | 2 +- .../sigma/compiler/ir/wrappers/WrappersModule.scala | 11 +++++++++++ .../compiler/ir}/wrappers/WrappersSpec.scala | 2 +- .../compiler/ir}/wrappers/scala/WOptions.scala | 4 ++-- .../ir}/wrappers/scala/impl/WOptionsImpl.scala | 10 +++++----- .../compiler/ir}/wrappers/scalan/WRTypes.scala | 2 +- .../ir}/wrappers/scalan/impl/WRTypesImpl.scala | 6 +++--- .../ir}/wrappers/special/WSpecialPredefs.scala | 2 +- .../wrappers/special/impl/WSpecialPredefsImpl.scala | 6 +++--- .../scala/special/sigma/wrappers/WrappersModule.scala | 2 +- .../main/scala/special/wrappers/WrappersModule.scala | 11 ----------- .../scala/special/wrappers/WSpecialPredefTests.scala | 1 - 16 files changed, 37 insertions(+), 38 deletions(-) rename sc/shared/src/main/scala/{special => sigma/compiler/ir}/wrappers/WrapSpec.scala (76%) create mode 100644 sc/shared/src/main/scala/sigma/compiler/ir/wrappers/WrappersModule.scala rename sc/shared/src/main/scala/{special => sigma/compiler/ir}/wrappers/WrappersSpec.scala (95%) rename sc/shared/src/main/scala/{ => sigma/compiler/ir}/wrappers/scala/WOptions.scala (82%) rename sc/shared/src/main/scala/{ => sigma/compiler/ir}/wrappers/scala/impl/WOptionsImpl.scala (96%) rename sc/shared/src/main/scala/{ => sigma/compiler/ir}/wrappers/scalan/WRTypes.scala (85%) rename sc/shared/src/main/scala/{ => sigma/compiler/ir}/wrappers/scalan/impl/WRTypesImpl.scala (95%) rename sc/shared/src/main/scala/{ => sigma/compiler/ir}/wrappers/special/WSpecialPredefs.scala (85%) rename sc/shared/src/main/scala/{ => sigma/compiler/ir}/wrappers/special/impl/WSpecialPredefsImpl.scala (89%) delete mode 100644 sc/shared/src/main/scala/special/wrappers/WrappersModule.scala diff --git a/sc/jvm/src/test/scala/sigmastate/ReflectionGenerator.scala b/sc/jvm/src/test/scala/sigmastate/ReflectionGenerator.scala index c102f4eda8..324542505e 100644 --- a/sc/jvm/src/test/scala/sigmastate/ReflectionGenerator.scala +++ b/sc/jvm/src/test/scala/sigmastate/ReflectionGenerator.scala @@ -33,13 +33,13 @@ object ReflectionGenerator { "sigma.compiler.ir.primitives.", "sigma.", "sigma.", - "special.wrappers.", + "sigma.compiler.ir.wrappers.", "sigma.ast.", "sigmastate.lang.Terms.", "sigmastate.interpreter.", "sigmastate.utxo.", "sigmastate.", - "wrappers.scala.", + "sigma.compiler.ir.wrappers.scala.", "sigma.compiler.ir.", "scala.collection.", "scala." diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/GraphIRReflection.scala b/sc/shared/src/main/scala/sigma/compiler/ir/GraphIRReflection.scala index 32d95354c3..200bbf12a7 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/GraphIRReflection.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/GraphIRReflection.scala @@ -5,8 +5,8 @@ import sigma.{Colls, SigmaDsl} import sigma.data.RType import sigma.reflection.ReflectionData.registerClassEntry import sigma.reflection.{ReflectionData, mkConstructor, mkMethod} -import special.wrappers.{OptionWrapSpec, RTypeWrapSpec} -import wrappers.scalan.WRTypes +import sigma.compiler.ir.wrappers.{OptionWrapSpec, RTypeWrapSpec} +import sigma.compiler.ir.wrappers.scalan.WRTypes /** Registrations of reflection metadata for graph-ir module (see README.md). * Such metadata is only used on JS platform to support reflection-like interfaces of @@ -21,7 +21,7 @@ object GraphIRReflection { /** Forces initialization of reflection data. */ val reflection = ReflectionData - { val clazz = classOf[wrappers.scala.WOptions#WOption[_]] + { val clazz = classOf[sigma.compiler.ir.wrappers.scala.WOptions#WOption[_]] val ctx = null.asInstanceOf[IRContext] // ok! type level only registerClassEntry(clazz, methods = Map( @@ -557,7 +557,7 @@ object GraphIRReflection { ) } - { val clazz = classOf[wrappers.special.WSpecialPredefs#WSpecialPredefCompanion] + { val clazz = classOf[sigma.compiler.ir.wrappers.special.WSpecialPredefs#WSpecialPredefCompanion] val ctx = null.asInstanceOf[IRContext] // ok! type level only registerClassEntry(clazz, methods = Map( diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/IRContext.scala b/sc/shared/src/main/scala/sigma/compiler/ir/IRContext.scala index b61e76e285..c28d42ab12 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/IRContext.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/IRContext.scala @@ -6,7 +6,7 @@ import sigma.compiler.ir.primitives._ import sigma.data.{Nullable, RType} import sigma.util.MemoizedFunc import sigma.{CollsModule, SigmaDslModule} -import special.wrappers.WrappersModule +import sigma.compiler.ir.wrappers.WrappersModule /** Aggregate cake with all inter-dependent modules assembled together. * Each instance of this class contains independent IR context, thus many diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/TypeDescs.scala b/sc/shared/src/main/scala/sigma/compiler/ir/TypeDescs.scala index 4346d117ea..8d938029e3 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/TypeDescs.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/TypeDescs.scala @@ -5,7 +5,7 @@ import scalan.core.{Contravariant, Covariant, Variance} import sigma.data.{AVHashMap, Lazy, Nullable, RType} import sigma.reflection.{RClass, RConstructor, RMethod} import sigma.util.CollectionUtil -import special.wrappers.WrapSpec +import sigma.compiler.ir.wrappers.WrapSpec import scala.annotation.implicitNotFound import scala.collection.immutable.ListMap diff --git a/sc/shared/src/main/scala/special/wrappers/WrapSpec.scala b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/WrapSpec.scala similarity index 76% rename from sc/shared/src/main/scala/special/wrappers/WrapSpec.scala rename to sc/shared/src/main/scala/sigma/compiler/ir/wrappers/WrapSpec.scala index dd07f1144c..b9c21227b2 100644 --- a/sc/shared/src/main/scala/special/wrappers/WrapSpec.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/WrapSpec.scala @@ -1,4 +1,4 @@ -package special.wrappers +package sigma.compiler.ir.wrappers /** Base type for all wrapper specification classes. * @see OptionWrapSpec as an example */ diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/WrappersModule.scala b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/WrappersModule.scala new file mode 100644 index 0000000000..d02a8c4e5b --- /dev/null +++ b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/WrappersModule.scala @@ -0,0 +1,11 @@ +package sigma.compiler.ir.wrappers + +import sigma.compiler.ir.IRContext +import sigma.compiler.ir.wrappers.scala.WOptionsModule +import sigma.compiler.ir.wrappers.scalan.WRTypesModule +import sigma.compiler.ir.wrappers.special.WSpecialPredefsModule + +trait WrappersModule + extends WSpecialPredefsModule + with WOptionsModule + with WRTypesModule { self: IRContext => } \ No newline at end of file diff --git a/sc/shared/src/main/scala/special/wrappers/WrappersSpec.scala b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/WrappersSpec.scala similarity index 95% rename from sc/shared/src/main/scala/special/wrappers/WrappersSpec.scala rename to sc/shared/src/main/scala/sigma/compiler/ir/wrappers/WrappersSpec.scala index d520ce9006..096bfc5220 100644 --- a/sc/shared/src/main/scala/special/wrappers/WrappersSpec.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/WrappersSpec.scala @@ -1,4 +1,4 @@ -package special.wrappers +package sigma.compiler.ir.wrappers import sigma.data.RType diff --git a/sc/shared/src/main/scala/wrappers/scala/WOptions.scala b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/scala/WOptions.scala similarity index 82% rename from sc/shared/src/main/scala/wrappers/scala/WOptions.scala rename to sc/shared/src/main/scala/sigma/compiler/ir/wrappers/scala/WOptions.scala index b59692ebd1..1ddb7ead40 100644 --- a/sc/shared/src/main/scala/wrappers/scala/WOptions.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/scala/WOptions.scala @@ -1,7 +1,7 @@ -package wrappers.scala { +package sigma.compiler.ir.wrappers.scala { import scalan._ import sigma.compiler.ir.{Base, IRContext} - import special.wrappers.WrappersModule + import sigma.compiler.ir.wrappers.WrappersModule trait WOptions extends Base { self: IRContext => trait WOption[A] extends Def[WOption[A]] { diff --git a/sc/shared/src/main/scala/wrappers/scala/impl/WOptionsImpl.scala b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/scala/impl/WOptionsImpl.scala similarity index 96% rename from sc/shared/src/main/scala/wrappers/scala/impl/WOptionsImpl.scala rename to sc/shared/src/main/scala/sigma/compiler/ir/wrappers/scala/impl/WOptionsImpl.scala index 048b27b772..da601f06c1 100644 --- a/sc/shared/src/main/scala/wrappers/scala/impl/WOptionsImpl.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/scala/impl/WOptionsImpl.scala @@ -1,10 +1,10 @@ -package wrappers.scala +package sigma.compiler.ir.wrappers.scala import scala.language.{existentials, implicitConversions} import scalan._ import sigma.compiler.ir.IRContext -import special.wrappers.WrappersModule -import special.wrappers.OptionWrapSpec +import sigma.compiler.ir.wrappers.WrappersModule +import sigma.compiler.ir.wrappers.OptionWrapSpec import scala.collection.compat.immutable.ArraySeq @@ -239,9 +239,9 @@ class WOptionCls extends EntityObject("WOption") { registerEntityObject("WOption", WOption) } -object WOptionsModule extends ModuleInfo("wrappers.scala", "WOptions") { +object WOptionsModule extends ModuleInfo("sigma.compiler.ir.wrappers.scala", "WOptions") { val reflection = GraphIRReflection } } -trait WOptionsModule extends wrappers.scala.impl.WOptionsDefs {self: IRContext =>} +trait WOptionsModule extends sigma.compiler.ir.wrappers.scala.impl.WOptionsDefs {self: IRContext =>} diff --git a/sc/shared/src/main/scala/wrappers/scalan/WRTypes.scala b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/scalan/WRTypes.scala similarity index 85% rename from sc/shared/src/main/scala/wrappers/scalan/WRTypes.scala rename to sc/shared/src/main/scala/sigma/compiler/ir/wrappers/scalan/WRTypes.scala index 41242c4ce3..10ce21e9ef 100644 --- a/sc/shared/src/main/scala/wrappers/scalan/WRTypes.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/scalan/WRTypes.scala @@ -1,4 +1,4 @@ -package wrappers.scalan { +package sigma.compiler.ir.wrappers.scalan { import scalan._ import sigma.compiler.ir.{Base, IRContext} diff --git a/sc/shared/src/main/scala/wrappers/scalan/impl/WRTypesImpl.scala b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/scalan/impl/WRTypesImpl.scala similarity index 95% rename from sc/shared/src/main/scala/wrappers/scalan/impl/WRTypesImpl.scala rename to sc/shared/src/main/scala/sigma/compiler/ir/wrappers/scalan/impl/WRTypesImpl.scala index d90498e4c5..1f7524bc3c 100644 --- a/sc/shared/src/main/scala/wrappers/scalan/impl/WRTypesImpl.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/scalan/impl/WRTypesImpl.scala @@ -1,9 +1,9 @@ -package wrappers.scalan +package sigma.compiler.ir.wrappers.scalan import sigma.compiler.ir.IRContext import scala.language.{existentials, implicitConversions} import sigma.data.RType -import special.wrappers.RTypeWrapSpec +import sigma.compiler.ir.wrappers.RTypeWrapSpec import scala.collection.compat.immutable.ArraySeq @@ -118,4 +118,4 @@ object WRTypesModule extends ModuleInfo("wrappers.scalan", "WRTypes") { } } -trait WRTypesModule extends wrappers.scalan.impl.WRTypesDefs {self: IRContext =>} +trait WRTypesModule extends sigma.compiler.ir.wrappers.scalan.impl.WRTypesDefs {self: IRContext =>} diff --git a/sc/shared/src/main/scala/wrappers/special/WSpecialPredefs.scala b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/special/WSpecialPredefs.scala similarity index 85% rename from sc/shared/src/main/scala/wrappers/special/WSpecialPredefs.scala rename to sc/shared/src/main/scala/sigma/compiler/ir/wrappers/special/WSpecialPredefs.scala index 45065b324b..a1b9adeaa0 100644 --- a/sc/shared/src/main/scala/wrappers/special/WSpecialPredefs.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/special/WSpecialPredefs.scala @@ -1,4 +1,4 @@ -package wrappers.special { +package sigma.compiler.ir.wrappers.special { import scalan._ import sigma.compiler.ir.{Base, IRContext} diff --git a/sc/shared/src/main/scala/wrappers/special/impl/WSpecialPredefsImpl.scala b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/special/impl/WSpecialPredefsImpl.scala similarity index 89% rename from sc/shared/src/main/scala/wrappers/special/impl/WSpecialPredefsImpl.scala rename to sc/shared/src/main/scala/sigma/compiler/ir/wrappers/special/impl/WSpecialPredefsImpl.scala index 66820b6792..a403aa0e5a 100644 --- a/sc/shared/src/main/scala/wrappers/special/impl/WSpecialPredefsImpl.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/special/impl/WSpecialPredefsImpl.scala @@ -1,4 +1,4 @@ -package wrappers.special +package sigma.compiler.ir.wrappers.special import scala.language.{existentials, implicitConversions} import scalan._ @@ -64,9 +64,9 @@ object WSpecialPredef extends EntityObject("WSpecialPredef") { } -object WSpecialPredefsModule extends ModuleInfo("wrappers.special", "WSpecialPredefs") { +object WSpecialPredefsModule extends ModuleInfo("sigma.compiler.ir.wrappers.special", "WSpecialPredefs") { val reflection = GraphIRReflection } } -trait WSpecialPredefsModule extends wrappers.special.impl.WSpecialPredefsDefs {self: IRContext =>} +trait WSpecialPredefsModule extends sigma.compiler.ir.wrappers.special.impl.WSpecialPredefsDefs {self: IRContext =>} diff --git a/sc/shared/src/main/scala/special/sigma/wrappers/WrappersModule.scala b/sc/shared/src/main/scala/special/sigma/wrappers/WrappersModule.scala index 7d0bcc6b59..d0dbb06e11 100644 --- a/sc/shared/src/main/scala/special/sigma/wrappers/WrappersModule.scala +++ b/sc/shared/src/main/scala/special/sigma/wrappers/WrappersModule.scala @@ -3,4 +3,4 @@ package sigma.wrappers import sigma.compiler.ir.IRContext trait WrappersModule - extends special.wrappers.WrappersModule { self: IRContext => } + extends sigma.compiler.ir.wrappers.WrappersModule { self: IRContext => } diff --git a/sc/shared/src/main/scala/special/wrappers/WrappersModule.scala b/sc/shared/src/main/scala/special/wrappers/WrappersModule.scala deleted file mode 100644 index 0003fd6464..0000000000 --- a/sc/shared/src/main/scala/special/wrappers/WrappersModule.scala +++ /dev/null @@ -1,11 +0,0 @@ -package special.wrappers - -import sigma.compiler.ir.IRContext -import wrappers.scala.WOptionsModule -import wrappers.scalan.WRTypesModule -import wrappers.special.WSpecialPredefsModule - -trait WrappersModule - extends WSpecialPredefsModule - with WOptionsModule - with WRTypesModule { self: IRContext => } \ No newline at end of file diff --git a/sc/shared/src/test/scala/special/wrappers/WSpecialPredefTests.scala b/sc/shared/src/test/scala/special/wrappers/WSpecialPredefTests.scala index e1097ebf6c..75123cf5bd 100644 --- a/sc/shared/src/test/scala/special/wrappers/WSpecialPredefTests.scala +++ b/sc/shared/src/test/scala/special/wrappers/WSpecialPredefTests.scala @@ -2,7 +2,6 @@ package special.wrappers import scala.language.reflectiveCalls -import sigma.data.RType class WSpecialPredefTests extends WrappersTests { From baab0a8d22dc663b543ab35f8519178b04a1e460 Mon Sep 17 00:00:00 2001 From: Alexander Slesarenko Date: Thu, 16 May 2024 12:44:29 +0100 Subject: [PATCH 077/314] refactor-ir-cake: wrappers moved to sigma.compiler.ir.wrappers package (part 2) --- .../sigma/compiler/ir/GraphIRReflection.scala | 8 ++++---- .../main/scala/sigma/compiler/ir/IRContext.scala | 14 ++++++++------ .../compiler/ir/wrappers/WrappersModule.scala | 11 ----------- .../sigma/compiler/ir/wrappers/WrappersSpec.scala | 4 +--- .../compiler/ir/wrappers/scala/WOptions.scala | 2 -- .../ir/wrappers/scala/impl/WOptionsImpl.scala | 2 -- .../compiler/ir/wrappers/scalan/WRTypes.scala | 1 - .../compiler/ir/wrappers/sigma}/CollsUnit.scala | 8 ++++---- .../compiler/ir/wrappers}/sigma/SigmaDslUnit.scala | 8 ++++---- .../ir/wrappers/sigma}/impl/CollsImpl.scala | 6 +++--- .../ir/wrappers}/sigma/impl/SigmaDslImpl.scala | 6 ++++-- .../special/impl/WSpecialPredefsImpl.scala | 1 - .../special/sigma/wrappers/WrappersModule.scala | 6 ------ 13 files changed, 28 insertions(+), 49 deletions(-) delete mode 100644 sc/shared/src/main/scala/sigma/compiler/ir/wrappers/WrappersModule.scala rename sc/shared/src/main/scala/{special/collection => sigma/compiler/ir/wrappers/sigma}/CollsUnit.scala (95%) rename sc/shared/src/main/scala/{special => sigma/compiler/ir/wrappers}/sigma/SigmaDslUnit.scala (98%) rename sc/shared/src/main/scala/{special/collection => sigma/compiler/ir/wrappers/sigma}/impl/CollsImpl.scala (99%) rename sc/shared/src/main/scala/{special => sigma/compiler/ir/wrappers}/sigma/impl/SigmaDslImpl.scala (99%) delete mode 100644 sc/shared/src/main/scala/special/sigma/wrappers/WrappersModule.scala diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/GraphIRReflection.scala b/sc/shared/src/main/scala/sigma/compiler/ir/GraphIRReflection.scala index 200bbf12a7..9482cdc048 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/GraphIRReflection.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/GraphIRReflection.scala @@ -1,12 +1,12 @@ package sigma.compiler.ir import sigma.compiler.ir.primitives.Thunks -import sigma.{Colls, SigmaDsl} import sigma.data.RType import sigma.reflection.ReflectionData.registerClassEntry import sigma.reflection.{ReflectionData, mkConstructor, mkMethod} import sigma.compiler.ir.wrappers.{OptionWrapSpec, RTypeWrapSpec} import sigma.compiler.ir.wrappers.scalan.WRTypes +import sigma.compiler.ir.wrappers.sigma.SigmaDsl /** Registrations of reflection metadata for graph-ir module (see README.md). * Such metadata is only used on JS platform to support reflection-like interfaces of @@ -71,7 +71,7 @@ object GraphIRReflection { ) ) - { val clazz = classOf[sigma.SigmaDsl#SigmaProp] + { val clazz = classOf[sigma.compiler.ir.wrappers.sigma.SigmaDsl#SigmaProp] val ctx = null.asInstanceOf[SigmaDsl] // ok! type level only registerClassEntry(clazz, methods = Map( @@ -120,7 +120,7 @@ object GraphIRReflection { ) } - { val clazz = classOf[Colls#CollBuilder] + { val clazz = classOf[sigma.compiler.ir.wrappers.sigma.Colls#CollBuilder] val ctx = null.asInstanceOf[IRContext] // ok! type level only registerClassEntry(clazz, methods = Map( @@ -142,7 +142,7 @@ object GraphIRReflection { } { - val clazz = classOf[Colls#Coll[_]] + val clazz = classOf[sigma.compiler.ir.wrappers.sigma.Colls#Coll[_]] val ctx = null.asInstanceOf[IRContext] // ok! type level only registerClassEntry(clazz, methods = Map( diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/IRContext.scala b/sc/shared/src/main/scala/sigma/compiler/ir/IRContext.scala index c28d42ab12..123bc6f209 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/IRContext.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/IRContext.scala @@ -1,12 +1,13 @@ package sigma.compiler.ir -import scalan._ import sigma.compiler.ir.core.MutableLazy import sigma.compiler.ir.primitives._ import sigma.data.{Nullable, RType} import sigma.util.MemoizedFunc -import sigma.{CollsModule, SigmaDslModule} -import sigma.compiler.ir.wrappers.WrappersModule +import sigma.compiler.ir.wrappers.scala.WOptionsModule +import sigma.compiler.ir.wrappers.scalan.WRTypesModule +import sigma.compiler.ir.wrappers.sigma.{CollsModule, SigmaDslModule} +import sigma.compiler.ir.wrappers.special.WSpecialPredefsModule /** Aggregate cake with all inter-dependent modules assembled together. * Each instance of this class contains independent IR context, thus many @@ -43,12 +44,13 @@ trait IRContext with Entities with Modules with DefRewriting - with WrappersModule with CollsModule - with sigma.wrappers.WrappersModule with SigmaDslModule with TreeBuilding - with GraphBuilding { + with GraphBuilding + with WSpecialPredefsModule + with WOptionsModule + with WRTypesModule { import Coll._ import CollBuilder._ diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/WrappersModule.scala b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/WrappersModule.scala deleted file mode 100644 index d02a8c4e5b..0000000000 --- a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/WrappersModule.scala +++ /dev/null @@ -1,11 +0,0 @@ -package sigma.compiler.ir.wrappers - -import sigma.compiler.ir.IRContext -import sigma.compiler.ir.wrappers.scala.WOptionsModule -import sigma.compiler.ir.wrappers.scalan.WRTypesModule -import sigma.compiler.ir.wrappers.special.WSpecialPredefsModule - -trait WrappersModule - extends WSpecialPredefsModule - with WOptionsModule - with WRTypesModule { self: IRContext => } \ No newline at end of file diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/WrappersSpec.scala b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/WrappersSpec.scala index 096bfc5220..4c0c5f05eb 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/WrappersSpec.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/WrappersSpec.scala @@ -1,7 +1,5 @@ package sigma.compiler.ir.wrappers - -import sigma.data.RType - +import _root_.sigma.data.RType /** Base class for wrappers of such types as WOption, WRType etc. * Used in graph IR to implement method invocation. */ diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/scala/WOptions.scala b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/scala/WOptions.scala index 1ddb7ead40..d6c0971214 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/scala/WOptions.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/scala/WOptions.scala @@ -1,7 +1,5 @@ package sigma.compiler.ir.wrappers.scala { - import scalan._ import sigma.compiler.ir.{Base, IRContext} - import sigma.compiler.ir.wrappers.WrappersModule trait WOptions extends Base { self: IRContext => trait WOption[A] extends Def[WOption[A]] { diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/scala/impl/WOptionsImpl.scala b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/scala/impl/WOptionsImpl.scala index da601f06c1..307e380a76 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/scala/impl/WOptionsImpl.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/scala/impl/WOptionsImpl.scala @@ -1,9 +1,7 @@ package sigma.compiler.ir.wrappers.scala import scala.language.{existentials, implicitConversions} -import scalan._ import sigma.compiler.ir.IRContext -import sigma.compiler.ir.wrappers.WrappersModule import sigma.compiler.ir.wrappers.OptionWrapSpec import scala.collection.compat.immutable.ArraySeq diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/scalan/WRTypes.scala b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/scalan/WRTypes.scala index 10ce21e9ef..d83c538b8c 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/scalan/WRTypes.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/scalan/WRTypes.scala @@ -1,5 +1,4 @@ package sigma.compiler.ir.wrappers.scalan { - import scalan._ import sigma.compiler.ir.{Base, IRContext} diff --git a/sc/shared/src/main/scala/special/collection/CollsUnit.scala b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/CollsUnit.scala similarity index 95% rename from sc/shared/src/main/scala/special/collection/CollsUnit.scala rename to sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/CollsUnit.scala index f000b61ed6..9b4a002a14 100644 --- a/sc/shared/src/main/scala/special/collection/CollsUnit.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/CollsUnit.scala @@ -1,5 +1,6 @@ -package sigma { - import sigma.compiler.ir.{Base, IRContext} +package sigma.compiler.ir.wrappers.sigma + +import sigma.compiler.ir.{Base, IRContext} /** Staged version of collection interfaces which is used in graph-based IR to represent * methods of Coll and CollBuilder. @@ -34,5 +35,4 @@ package sigma { def xor(left: Ref[Coll[Byte]], right: Ref[Coll[Byte]]): Ref[Coll[Byte]]; def replicate[T](n: Ref[Int], v: Ref[T]): Ref[Coll[T]]; }; - } -} \ No newline at end of file + } \ No newline at end of file diff --git a/sc/shared/src/main/scala/special/sigma/SigmaDslUnit.scala b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/SigmaDslUnit.scala similarity index 98% rename from sc/shared/src/main/scala/special/sigma/SigmaDslUnit.scala rename to sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/SigmaDslUnit.scala index 46c93558af..7b9d499c7e 100644 --- a/sc/shared/src/main/scala/special/sigma/SigmaDslUnit.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/SigmaDslUnit.scala @@ -1,5 +1,6 @@ -package sigma { - import scalan._ +package sigma.compiler.ir.wrappers.sigma + +import scalan._ import sigma.compiler.ir.{Base, IRContext} trait SigmaDsl extends Base { self: IRContext => @@ -124,5 +125,4 @@ package sigma { trait ContextCompanion; trait SigmaContractCompanion; trait SigmaDslBuilderCompanion - } -} \ No newline at end of file + } \ No newline at end of file diff --git a/sc/shared/src/main/scala/special/collection/impl/CollsImpl.scala b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/CollsImpl.scala similarity index 99% rename from sc/shared/src/main/scala/special/collection/impl/CollsImpl.scala rename to sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/CollsImpl.scala index dcfdf25217..fd3f72a642 100644 --- a/sc/shared/src/main/scala/special/collection/impl/CollsImpl.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/CollsImpl.scala @@ -1,8 +1,8 @@ -package sigma +package sigma.compiler.ir.wrappers.sigma import scala.language.{existentials, implicitConversions} -import scalan._ import sigma.compiler.ir.IRContext +import sigma.compiler.ir.wrappers.sigma.impl.CollsDefs import scala.collection.compat.immutable.ArraySeq @@ -643,4 +643,4 @@ object CollsModule extends ModuleInfo("sigma", "Colls") { } } -trait CollsModule extends sigma.impl.CollsDefs {self: IRContext =>} +trait CollsModule extends CollsDefs {self: IRContext =>} diff --git a/sc/shared/src/main/scala/special/sigma/impl/SigmaDslImpl.scala b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/SigmaDslImpl.scala similarity index 99% rename from sc/shared/src/main/scala/special/sigma/impl/SigmaDslImpl.scala rename to sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/SigmaDslImpl.scala index 17ad187b91..201c974512 100644 --- a/sc/shared/src/main/scala/special/sigma/impl/SigmaDslImpl.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/SigmaDslImpl.scala @@ -1,13 +1,15 @@ -package sigma +package sigma.compiler.ir.wrappers.sigma import scala.language.{existentials, implicitConversions} import scalan._ import sigma.compiler.ir.IRContext +import sigma.compiler.ir.wrappers.sigma.impl.SigmaDslDefs import scala.collection.compat.immutable.ArraySeq package impl { import sigma.compiler.ir.meta.ModuleInfo + import sigma.compiler.ir.wrappers.sigma.SigmaDsl import sigma.compiler.ir.{Base, GraphIRReflection, IRContext} import sigma.data.{Nullable, RType} import sigma.reflection.{RClass, RMethod} @@ -2327,4 +2329,4 @@ object SigmaDslModule extends ModuleInfo("sigma", "SigmaDsl") { } } -trait SigmaDslModule extends sigma.impl.SigmaDslDefs {self: IRContext =>} +trait SigmaDslModule extends SigmaDslDefs {self: IRContext =>} diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/special/impl/WSpecialPredefsImpl.scala b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/special/impl/WSpecialPredefsImpl.scala index a403aa0e5a..a468646ffb 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/special/impl/WSpecialPredefsImpl.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/special/impl/WSpecialPredefsImpl.scala @@ -1,7 +1,6 @@ package sigma.compiler.ir.wrappers.special import scala.language.{existentials, implicitConversions} -import scalan._ import sigma.compiler.ir.IRContext package impl { diff --git a/sc/shared/src/main/scala/special/sigma/wrappers/WrappersModule.scala b/sc/shared/src/main/scala/special/sigma/wrappers/WrappersModule.scala deleted file mode 100644 index d0dbb06e11..0000000000 --- a/sc/shared/src/main/scala/special/sigma/wrappers/WrappersModule.scala +++ /dev/null @@ -1,6 +0,0 @@ -package sigma.wrappers - -import sigma.compiler.ir.IRContext - -trait WrappersModule - extends sigma.compiler.ir.wrappers.WrappersModule { self: IRContext => } From 7c18eef30ecc58ea8a32a46e1654efcbf94b72ce Mon Sep 17 00:00:00 2001 From: Alexander Slesarenko Date: Thu, 16 May 2024 12:52:26 +0100 Subject: [PATCH 078/314] refactor-ir-cake: wrappers moved to sigma.compiler.ir.wrappers package (part 3) --- .../main/scala/sigma/compiler/ir/GraphIRReflection.scala | 5 ++--- .../src/main/scala/sigma/compiler/ir/IRContext.scala | 4 +--- .../compiler/ir/wrappers/{scalan => sigma}/WRTypes.scala | 8 ++++---- .../ir/wrappers/{special => sigma}/WSpecialPredefs.scala | 9 ++++----- .../ir/wrappers/{scalan => sigma}/impl/WRTypesImpl.scala | 5 +++-- .../{special => sigma}/impl/WSpecialPredefsImpl.scala | 5 +++-- 6 files changed, 17 insertions(+), 19 deletions(-) rename sc/shared/src/main/scala/sigma/compiler/ir/wrappers/{scalan => sigma}/WRTypes.scala (66%) rename sc/shared/src/main/scala/sigma/compiler/ir/wrappers/{special => sigma}/WSpecialPredefs.scala (64%) rename sc/shared/src/main/scala/sigma/compiler/ir/wrappers/{scalan => sigma}/impl/WRTypesImpl.scala (95%) rename sc/shared/src/main/scala/sigma/compiler/ir/wrappers/{special => sigma}/impl/WSpecialPredefsImpl.scala (94%) diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/GraphIRReflection.scala b/sc/shared/src/main/scala/sigma/compiler/ir/GraphIRReflection.scala index 9482cdc048..5ef38a97ef 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/GraphIRReflection.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/GraphIRReflection.scala @@ -5,8 +5,7 @@ import sigma.data.RType import sigma.reflection.ReflectionData.registerClassEntry import sigma.reflection.{ReflectionData, mkConstructor, mkMethod} import sigma.compiler.ir.wrappers.{OptionWrapSpec, RTypeWrapSpec} -import sigma.compiler.ir.wrappers.scalan.WRTypes -import sigma.compiler.ir.wrappers.sigma.SigmaDsl +import sigma.compiler.ir.wrappers.sigma.{SigmaDsl, WRTypes, WSpecialPredefs} /** Registrations of reflection metadata for graph-ir module (see README.md). * Such metadata is only used on JS platform to support reflection-like interfaces of @@ -557,7 +556,7 @@ object GraphIRReflection { ) } - { val clazz = classOf[sigma.compiler.ir.wrappers.special.WSpecialPredefs#WSpecialPredefCompanion] + { val clazz = classOf[WSpecialPredefs#WSpecialPredefCompanion] val ctx = null.asInstanceOf[IRContext] // ok! type level only registerClassEntry(clazz, methods = Map( diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/IRContext.scala b/sc/shared/src/main/scala/sigma/compiler/ir/IRContext.scala index 123bc6f209..b32c69a430 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/IRContext.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/IRContext.scala @@ -5,9 +5,7 @@ import sigma.compiler.ir.primitives._ import sigma.data.{Nullable, RType} import sigma.util.MemoizedFunc import sigma.compiler.ir.wrappers.scala.WOptionsModule -import sigma.compiler.ir.wrappers.scalan.WRTypesModule -import sigma.compiler.ir.wrappers.sigma.{CollsModule, SigmaDslModule} -import sigma.compiler.ir.wrappers.special.WSpecialPredefsModule +import sigma.compiler.ir.wrappers.sigma.{CollsModule, SigmaDslModule, WRTypesModule, WSpecialPredefsModule} /** Aggregate cake with all inter-dependent modules assembled together. * Each instance of this class contains independent IR context, thus many diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/scalan/WRTypes.scala b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/WRTypes.scala similarity index 66% rename from sc/shared/src/main/scala/sigma/compiler/ir/wrappers/scalan/WRTypes.scala rename to sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/WRTypes.scala index d83c538b8c..b4981dda4f 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/scalan/WRTypes.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/WRTypes.scala @@ -1,5 +1,6 @@ -package sigma.compiler.ir.wrappers.scalan { - import sigma.compiler.ir.{Base, IRContext} +package sigma.compiler.ir.wrappers.sigma + +import sigma.compiler.ir.{Base, IRContext} trait WRTypes extends Base { self: IRContext => @@ -8,5 +9,4 @@ package sigma.compiler.ir.wrappers.scalan { def name: Ref[String] }; trait WRTypeCompanion - } -} \ No newline at end of file + } \ No newline at end of file diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/special/WSpecialPredefs.scala b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/WSpecialPredefs.scala similarity index 64% rename from sc/shared/src/main/scala/sigma/compiler/ir/wrappers/special/WSpecialPredefs.scala rename to sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/WSpecialPredefs.scala index a1b9adeaa0..c7529d1ca6 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/special/WSpecialPredefs.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/WSpecialPredefs.scala @@ -1,11 +1,10 @@ -package sigma.compiler.ir.wrappers.special { - import scalan._ - import sigma.compiler.ir.{Base, IRContext} +package sigma.compiler.ir.wrappers.sigma + +import sigma.compiler.ir.{Base, IRContext} trait WSpecialPredefs extends Base { self: IRContext => trait WSpecialPredef extends Def[WSpecialPredef]; trait WSpecialPredefCompanion { def some[A](x: Ref[A]): Ref[WOption[A]]; } - } -} \ No newline at end of file + } \ No newline at end of file diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/scalan/impl/WRTypesImpl.scala b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/WRTypesImpl.scala similarity index 95% rename from sc/shared/src/main/scala/sigma/compiler/ir/wrappers/scalan/impl/WRTypesImpl.scala rename to sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/WRTypesImpl.scala index 1f7524bc3c..20d3bdf965 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/scalan/impl/WRTypesImpl.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/WRTypesImpl.scala @@ -1,4 +1,4 @@ -package sigma.compiler.ir.wrappers.scalan +package sigma.compiler.ir.wrappers.sigma import sigma.compiler.ir.IRContext import scala.language.{existentials, implicitConversions} @@ -9,6 +9,7 @@ import scala.collection.compat.immutable.ArraySeq package impl { import sigma.compiler.ir.meta.ModuleInfo + import sigma.compiler.ir.wrappers.sigma.WRTypes import sigma.compiler.ir.{Base, GraphIRReflection, IRContext} import sigma.reflection.{RClass, RMethod} @@ -118,4 +119,4 @@ object WRTypesModule extends ModuleInfo("wrappers.scalan", "WRTypes") { } } -trait WRTypesModule extends sigma.compiler.ir.wrappers.scalan.impl.WRTypesDefs {self: IRContext =>} +trait WRTypesModule extends sigma.compiler.ir.wrappers.sigma.impl.WRTypesDefs {self: IRContext =>} diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/special/impl/WSpecialPredefsImpl.scala b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/WSpecialPredefsImpl.scala similarity index 94% rename from sc/shared/src/main/scala/sigma/compiler/ir/wrappers/special/impl/WSpecialPredefsImpl.scala rename to sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/WSpecialPredefsImpl.scala index a468646ffb..4624a052ee 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/special/impl/WSpecialPredefsImpl.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/WSpecialPredefsImpl.scala @@ -1,4 +1,4 @@ -package sigma.compiler.ir.wrappers.special +package sigma.compiler.ir.wrappers.sigma import scala.language.{existentials, implicitConversions} import sigma.compiler.ir.IRContext @@ -6,6 +6,7 @@ import sigma.compiler.ir.IRContext package impl { import sigma.compiler.ir.core.MutableLazy import sigma.compiler.ir.meta.ModuleInfo + import sigma.compiler.ir.wrappers.sigma.WSpecialPredefs import sigma.compiler.ir.{Base, GraphIRReflection, IRContext} import sigma.data.Nullable import sigma.reflection.RClass @@ -68,4 +69,4 @@ object WSpecialPredefsModule extends ModuleInfo("sigma.compiler.ir.wrappers.spec } } -trait WSpecialPredefsModule extends sigma.compiler.ir.wrappers.special.impl.WSpecialPredefsDefs {self: IRContext =>} +trait WSpecialPredefsModule extends sigma.compiler.ir.wrappers.sigma.impl.WSpecialPredefsDefs {self: IRContext =>} From 3dd55aa2f743a4720e5016c12b90623a5ce1ed2c Mon Sep 17 00:00:00 2001 From: Alexander Slesarenko Date: Thu, 16 May 2024 15:18:19 +0100 Subject: [PATCH 079/314] refactor-ir-cake: SizeOf, CostOf removed from IR + more ScalaDocs --- .../scala/sigma/compiler/ir/AstGraphs.scala | 3 + .../sigma/compiler/ir/DefRewriting.scala | 5 + .../scala/sigma/compiler/ir/IRContext.scala | 3 +- .../scala/sigma/compiler/ir/MethodCalls.scala | 3 + .../scala/sigma/compiler/ir/Modules.scala | 3 + .../sigma/compiler/ir/ProgramGraphs.scala | 1 + .../sigma/compiler/ir/Transforming.scala | 5 + .../scala/sigma/compiler/ir/TypeDescs.scala | 4 + .../sigma/compiler/ir/primitives/Equal.scala | 1 + .../compiler/ir/primitives/Functions.scala | 5 +- .../compiler/ir/primitives/IfThenElse.scala | 1 + .../compiler/ir/primitives/LogicalOps.scala | 2 +- .../ir/primitives/MiscelaneousOps.scala | 41 +++++++++ .../compiler/ir/primitives/NumericOps.scala | 2 +- .../compiler/ir/primitives/OrderingOps.scala | 2 +- .../sigma/compiler/ir/primitives/Tuples.scala | 1 + .../compiler/ir/primitives/UnBinOps.scala | 1 + .../compiler/ir/primitives/UniversalOps.scala | 92 ------------------- 18 files changed, 75 insertions(+), 100 deletions(-) create mode 100644 sc/shared/src/main/scala/sigma/compiler/ir/primitives/MiscelaneousOps.scala delete mode 100644 sc/shared/src/main/scala/sigma/compiler/ir/primitives/UniversalOps.scala diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/AstGraphs.scala b/sc/shared/src/main/scala/sigma/compiler/ir/AstGraphs.scala index 7f798dc8f3..79a078ad19 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/AstGraphs.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/AstGraphs.scala @@ -6,6 +6,9 @@ import sigma.data.emptyDBufferOfInt import scala.collection._ +/** Defines reusable abstraction of AstGraph, the base class for [[ProgramGraph]], + * [[Lambda]] and [[ThunkDef]]. + */ trait AstGraphs extends Transforming { self: IRContext => /** GraphNode is created for each symbol of the AstGraph and represents graph linking structure */ diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/DefRewriting.scala b/sc/shared/src/main/scala/sigma/compiler/ir/DefRewriting.scala index d7bb3a9e4d..62deffad31 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/DefRewriting.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/DefRewriting.scala @@ -3,6 +3,11 @@ package sigma.compiler.ir import sigma.compiler.DelayInvokeException import sigma.data.ExactNumeric +/** Defines methods to implement graph rewriting optimization rules. + * The rules are defines as a series of pattern matching with stackable overriding. + * Can be mixed in into traits to add new rules (pattern cases) and call `super` + * implementation as a fallback case. + */ trait DefRewriting { scalan: IRContext => /** Rewrites given node to another equivalent node and returns its reference. diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/IRContext.scala b/sc/shared/src/main/scala/sigma/compiler/ir/IRContext.scala index b32c69a430..908e4ccb33 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/IRContext.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/IRContext.scala @@ -34,7 +34,7 @@ trait IRContext with LogicalOps with OrderingOps with Equal - with UniversalOps + with MiscelaneousOps with Functions with IfThenElse with Transforming @@ -90,6 +90,7 @@ trait IRContext def colBuilder: Ref[CollBuilder] + /** Type descriptor for [[WRType]] */ implicit lazy val wRTypeAnyElement: Elem[WRType[Any]] = wRTypeElement(AnyElement) /** During compilation represent a global value Global, see also SGlobal type. */ diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/MethodCalls.scala b/sc/shared/src/main/scala/sigma/compiler/ir/MethodCalls.scala index 5ecdb823a7..876f0e9d7e 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/MethodCalls.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/MethodCalls.scala @@ -7,6 +7,9 @@ import sigma.util.CollectionUtil.TraversableOps import scala.annotation.{tailrec, unused} +/** Defines graph-ir representation of method calls, new object creation as well as the + * related utility methods. + */ trait MethodCalls extends Base { self: IRContext => def delayInvoke = throw new DelayInvokeException diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/Modules.scala b/sc/shared/src/main/scala/sigma/compiler/ir/Modules.scala index b14d4471d1..b58bacb5fb 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/Modules.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/Modules.scala @@ -2,6 +2,9 @@ package sigma.compiler.ir import sigma.compiler.ir.meta.ModuleInfo +/** Defines registration of IR modules. + * @see ModuleInfo + */ trait Modules extends Base { self: IRContext => /** Whether staged modules should be registered when cake is constructed and initialized. */ diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/ProgramGraphs.scala b/sc/shared/src/main/scala/sigma/compiler/ir/ProgramGraphs.scala index cd0384c996..6f447d97f9 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/ProgramGraphs.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/ProgramGraphs.scala @@ -6,6 +6,7 @@ import sigma.util.GraphUtil import scala.collection.compat.immutable.ArraySeq +/** Defines implementation of [[ProgramGraph]] and related utilities. */ trait ProgramGraphs extends AstGraphs { self: IRContext => type PGraph = ProgramGraph diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/Transforming.scala b/sc/shared/src/main/scala/sigma/compiler/ir/Transforming.scala index 2412c756f1..876f2b5db1 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/Transforming.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/Transforming.scala @@ -7,6 +7,11 @@ import sigma.reflection.RMethod import java.util import scala.language.existentials +/** Implements utilites for graph transformation and rewriting. + * @see Pass + * @see MapTransformer + * @see Rewriter + */ trait Transforming { self: IRContext => /** Descriptor of a current compiler pass. diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/TypeDescs.scala b/sc/shared/src/main/scala/sigma/compiler/ir/TypeDescs.scala index 8d938029e3..366107edca 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/TypeDescs.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/TypeDescs.scala @@ -12,6 +12,10 @@ import scala.collection.immutable.ListMap import scala.collection.mutable import scala.language.implicitConversions +/** Defines [[Elem]] descriptor of types in IRContext together with related utilities. + * @see MethodDesc + * @see TypeDesc + */ abstract class TypeDescs extends Base { self: IRContext => /** Helper type case method. */ diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/primitives/Equal.scala b/sc/shared/src/main/scala/sigma/compiler/ir/primitives/Equal.scala index a778465e4c..ec27fff12b 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/primitives/Equal.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/primitives/Equal.scala @@ -4,6 +4,7 @@ import sigma.compiler.ir.{Base, IRContext} import scala.annotation.unused +/** Defines IR representation of equality operations. */ trait Equal extends Base { self: IRContext => /** Binary operation representing structural equality between arguments. */ case class Equals[A: Elem]() extends BinOp[A, Boolean]("==") { diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/primitives/Functions.scala b/sc/shared/src/main/scala/sigma/compiler/ir/primitives/Functions.scala index 04d3283c01..cd028de9b6 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/primitives/Functions.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/primitives/Functions.scala @@ -8,6 +8,7 @@ import sigma.util.GraphUtil import java.util import scala.language.implicitConversions +/** Defines IR representation of functions (Lambdas) and function application. */ trait Functions extends Base with ProgramGraphs { self: IRContext => implicit class LambdaOps[A,B](f: Ref[A => B]) { @@ -143,10 +144,6 @@ trait Functions extends Base with ProgramGraphs { self: IRContext => // emitDepGraph(roots, FileUtil.file(cwd, dir), "nested_lambda")(defaultGraphVizConfig) assert(false, s"Invalid nested lambda $l inside $this") } - case op @ OpCost(_, _, args, opCost) => - if (args.contains(opCost)) { - !!!(s"Invalid OpCost($op)") - } case _ => } } diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/primitives/IfThenElse.scala b/sc/shared/src/main/scala/sigma/compiler/ir/primitives/IfThenElse.scala index aee57ff1f9..0ce94a83c1 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/primitives/IfThenElse.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/primitives/IfThenElse.scala @@ -2,6 +2,7 @@ package sigma.compiler.ir.primitives import sigma.compiler.ir.{Base, IRContext} +/** Defines IR representation of conditional expressions `if (c) t else e`. */ trait IfThenElse extends Base { self: IRContext => /** If c then t else e construction with standard lazy evaluation of branches. diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/primitives/LogicalOps.scala b/sc/shared/src/main/scala/sigma/compiler/ir/primitives/LogicalOps.scala index 6420e46f5c..183b4a8e84 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/primitives/LogicalOps.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/primitives/LogicalOps.scala @@ -2,7 +2,7 @@ package sigma.compiler.ir.primitives import sigma.compiler.ir.{Base, IRContext} -/** Slice in Scala cake with definitions of logical operations. */ +/** Slice in IRContext cake with definitions of logical operations. */ trait LogicalOps extends Base { self: IRContext => /** Logical AND binary operation. */ val And = new EndoBinOp[Boolean]("&&") { diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/primitives/MiscelaneousOps.scala b/sc/shared/src/main/scala/sigma/compiler/ir/primitives/MiscelaneousOps.scala new file mode 100644 index 0000000000..633306da8c --- /dev/null +++ b/sc/shared/src/main/scala/sigma/compiler/ir/primitives/MiscelaneousOps.scala @@ -0,0 +1,41 @@ +package sigma.compiler.ir.primitives + +import sigma.compiler.ir.{Base, IRContext} + +trait MiscelaneousOps extends Base { self: IRContext => + case class HashCode[A]() extends UnOp[A, Int]("hashCode") { + override def applySeq(x: A): Int = x.hashCode + } + + case class ToString[A]() extends UnOp[A, String]("toString") { + override def applySeq(x: A): String = x.toString + } + + case class Downcast[From, To](input: Ref[From], eTo: Elem[To]) extends BaseDef[To]()(eTo) { + override def transform(t: Transformer) = Downcast(t(input), eTo) + } + case class Upcast[From, To](input: Ref[From], eTo: Elem[To]) extends BaseDef[To]()(eTo) { + override def transform(t: Transformer) = Upcast(t(input), eTo) + } + + def downcast[To:Elem](value: Ref[_]): Ref[To] = Downcast(value, element[To]) + def upcast[To:Elem](value: Ref[_]): Ref[To] = Upcast(value, element[To]) + + implicit class RepUniversalOps[A](x: Ref[A]) { + def hashCodeRep: Ref[Int] = HashCode[A]().apply(x) + def toStringRep = ToString[A]().apply(x) + } + + case class Convert[From,To](eFrom: Elem[From], eTo: Elem[To], x: Ref[Def[_]], conv: Ref[From => To]) + extends BaseDef[To]()(eTo) { + override def transform(t: Transformer) = Convert(eFrom, eTo, t(x), t(conv)) + } + + def tryConvert[From, To](eFrom: Elem[From], eTo: Elem[To], x: Ref[Def[_]], conv: Ref[From => To]): Ref[To] = { + if (x.elem <:< eFrom) + conv(asRep[From](x)) + else + Convert(eFrom, eTo, x, conv) + } + +} diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/primitives/NumericOps.scala b/sc/shared/src/main/scala/sigma/compiler/ir/primitives/NumericOps.scala index d22140870a..4e732bbb5f 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/primitives/NumericOps.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/primitives/NumericOps.scala @@ -3,7 +3,7 @@ package sigma.compiler.ir.primitives import sigma.compiler.ir.{Base, IRContext} import sigma.data.{ExactIntegral, ExactNumeric} -/** Slice in Scala cake with definitions of numeric operations. */ +/** Slice in IRContext cake with definitions of numeric operations. */ trait NumericOps extends Base { self: IRContext => /** Extension methods over `Ref[T]` where T is instance of ExactNumeric type-class. */ diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/primitives/OrderingOps.scala b/sc/shared/src/main/scala/sigma/compiler/ir/primitives/OrderingOps.scala index ea2b9f5a34..be8f934706 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/primitives/OrderingOps.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/primitives/OrderingOps.scala @@ -5,7 +5,7 @@ import sigma.data.ExactOrdering import scala.language.implicitConversions -/** Slice in Scala cake with definitions of comparison operations. */ +/** Slice in IRContext cake with definitions of comparison operations. */ trait OrderingOps extends Base { self: IRContext => implicit def repOrderingToOrderingOps[T](x: Ref[T])(implicit n: ExactOrdering[T]) = new OrderingOpsCls(x) implicit def OrderingToOrderingOps[T](x: T)(implicit n: ExactOrdering[T], et: Elem[T]) = new OrderingOpsCls(toRep(x)) diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/primitives/Tuples.scala b/sc/shared/src/main/scala/sigma/compiler/ir/primitives/Tuples.scala index b6b9861ac7..59a5d810b9 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/primitives/Tuples.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/primitives/Tuples.scala @@ -9,6 +9,7 @@ import sigma.data.AVHashMap import scala.language.implicitConversions +/** Slice in [[IRContext]] cake with definitions of pairs and tuples. */ trait Tuples extends Base { self: IRContext => object Pair { def apply[A, B](a: Ref[A], b: Ref[B]) = zipPair[A, B]((a, b)) diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/primitives/UnBinOps.scala b/sc/shared/src/main/scala/sigma/compiler/ir/primitives/UnBinOps.scala index a3a92e2f10..23f8bc3800 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/primitives/UnBinOps.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/primitives/UnBinOps.scala @@ -2,6 +2,7 @@ package sigma.compiler.ir.primitives import sigma.compiler.ir.{Base, IRContext} +/** Defines IR representation of unary and binary operations. */ trait UnBinOps extends Base { self: IRContext => /** Base class for descriptors of unary operations. */ diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/primitives/UniversalOps.scala b/sc/shared/src/main/scala/sigma/compiler/ir/primitives/UniversalOps.scala deleted file mode 100644 index a5852647ac..0000000000 --- a/sc/shared/src/main/scala/sigma/compiler/ir/primitives/UniversalOps.scala +++ /dev/null @@ -1,92 +0,0 @@ -package sigma.compiler.ir.primitives - -import sigma.compiler.ir.{Base, IRContext} - -trait UniversalOps extends Base { self: IRContext => - case class HashCode[A]() extends UnOp[A, Int]("hashCode") { - override def applySeq(x: A): Int = x.hashCode - } - - case class ToString[A]() extends UnOp[A, String]("toString") { - override def applySeq(x: A): String = x.toString - } - - /** Represents calculation of size in bytes of the given value. - * The descriptor value.elem can be used to decompose value into components. - */ - case class SizeOf[T](value: Ref[T]) extends BaseDef[Long] { - override def transform(t: Transformer) = SizeOf(t(value)) - } - - def sizeOf[T](value: Ref[T]): Ref[Long] = SizeOf(value) - - /** Special graph node to represent accumulation of the operation costs. - * In general, due to node sharing it is incorrect to just sum up all the `args` costs - * and add `resCost` to that value. - * Example:
- * - * val x = .. - * val y = op1(x) - * val z = op2(x) - * val res = op3(y, z) - * - * The naive summation will lead to the cost of x` is accumulated both into `cost of y` - * and into `cost of z`, so in the `cost of res` it is accumulated twice. - * To avoid this problem OpCost nodes require special handling in during evaluation. - * - * @param lambdaVar the variable of the lambda in which scope this node is created. - * This makes this node belong to the lambda body, even if it doesn't - * otherwise depend on lambda argument. - * @param costedValueId The id of the node for which this node represents cost - * @param args costs of the arguments, which are here represent dependency information. - * @param opCost operation cost, which should be added to the current scope accumulated cost - */ - case class OpCost(lambdaVar: Sym, costedValueId: Int, args: Seq[Ref[Int]], opCost: Ref[Int]) extends BaseDef[Int] { - /** When this node is mirrored (as part of mirrorLambda) we apply transformer t for all arguments - * with standard data flow semantics. - * However this is not correct to do for lambdaVar. - * Instead we use current lambda from the top of the stack, which is always points to the most nested - * lambda. - */ - override def transform(t: Transformer) = OpCost(lambdaStack.head.x, costedValueId, t(args), t(opCost)) - } - - def opCost(costedValue: Sym, args: Seq[Ref[Int]], opCost: Ref[Int]): Ref[Int] = { - val id = costedValue.node.nodeId - val lamVar = lambdaStack.head.x - OpCost(lamVar, id, args, opCost) - } - - def assertValueIdForOpCost[A,B](value: Ref[A], cost: Ref[B]): Unit = { - assert(if (cost.node.isInstanceOf[OpCost]) value.node.nodeId == cost.node.asInstanceOf[OpCost].costedValueId else true, - s"${value.node} value node id (${value.node.nodeId}) is not equal to OpCost.costedValueId (${cost.node.asInstanceOf[OpCost].costedValueId})") - } - - case class Downcast[From, To](input: Ref[From], eTo: Elem[To]) extends BaseDef[To]()(eTo) { - override def transform(t: Transformer) = Downcast(t(input), eTo) - } - case class Upcast[From, To](input: Ref[From], eTo: Elem[To]) extends BaseDef[To]()(eTo) { - override def transform(t: Transformer) = Upcast(t(input), eTo) - } - - def downcast[To:Elem](value: Ref[_]): Ref[To] = Downcast(value, element[To]) - def upcast[To:Elem](value: Ref[_]): Ref[To] = Upcast(value, element[To]) - - implicit class RepUniversalOps[A](x: Ref[A]) { - def hashCodeRep: Ref[Int] = HashCode[A]().apply(x) - def toStringRep = ToString[A]().apply(x) - } - - case class Convert[From,To](eFrom: Elem[From], eTo: Elem[To], x: Ref[Def[_]], conv: Ref[From => To]) - extends BaseDef[To]()(eTo) { - override def transform(t: Transformer) = Convert(eFrom, eTo, t(x), t(conv)) - } - - def tryConvert[From, To](eFrom: Elem[From], eTo: Elem[To], x: Ref[Def[_]], conv: Ref[From => To]): Ref[To] = { - if (x.elem <:< eFrom) - conv(asRep[From](x)) - else - Convert(eFrom, eTo, x, conv) - } - -} From f56df6a148a08fe0558141df93762742f6bc082a Mon Sep 17 00:00:00 2001 From: Alexander Slesarenko Date: Thu, 16 May 2024 16:08:20 +0100 Subject: [PATCH 080/314] refactor-ir-cake: removed WSpecialPredefs.scala --- .../sigma/compiler/ir/GraphIRReflection.scala | 12 +--- .../scala/sigma/compiler/ir/IRContext.scala | 13 +--- .../sigma/compiler/ir/TreeBuilding.scala | 2 +- .../{MiscelaneousOps.scala => MiscOps.scala} | 5 +- .../compiler/ir/wrappers/scala/WOptions.scala | 1 + .../ir/wrappers/scala/impl/WOptionsImpl.scala | 1 + .../ir/wrappers/sigma/SigmaDslUnit.scala | 1 + .../compiler/ir/wrappers/sigma/WRTypes.scala | 1 + .../ir/wrappers/sigma/WSpecialPredefs.scala | 10 --- .../ir/wrappers/sigma/impl/CollsImpl.scala | 3 +- .../ir/wrappers/sigma/impl/SigmaDslImpl.scala | 1 + .../ir/wrappers/sigma/impl/WRTypesImpl.scala | 1 + .../sigma/impl/WSpecialPredefsImpl.scala | 72 ------------------- .../wrappers/WSpecialPredefTests.scala | 23 ------ 14 files changed, 16 insertions(+), 130 deletions(-) rename sc/shared/src/main/scala/sigma/compiler/ir/primitives/{MiscelaneousOps.scala => MiscOps.scala} (89%) delete mode 100644 sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/WSpecialPredefs.scala delete mode 100644 sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/WSpecialPredefsImpl.scala delete mode 100644 sc/shared/src/test/scala/special/wrappers/WSpecialPredefTests.scala diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/GraphIRReflection.scala b/sc/shared/src/main/scala/sigma/compiler/ir/GraphIRReflection.scala index 5ef38a97ef..69736a0224 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/GraphIRReflection.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/GraphIRReflection.scala @@ -5,7 +5,7 @@ import sigma.data.RType import sigma.reflection.ReflectionData.registerClassEntry import sigma.reflection.{ReflectionData, mkConstructor, mkMethod} import sigma.compiler.ir.wrappers.{OptionWrapSpec, RTypeWrapSpec} -import sigma.compiler.ir.wrappers.sigma.{SigmaDsl, WRTypes, WSpecialPredefs} +import sigma.compiler.ir.wrappers.sigma.{SigmaDsl, WRTypes} /** Registrations of reflection metadata for graph-ir module (see README.md). * Such metadata is only used on JS platform to support reflection-like interfaces of @@ -556,16 +556,6 @@ object GraphIRReflection { ) } - { val clazz = classOf[WSpecialPredefs#WSpecialPredefCompanion] - val ctx = null.asInstanceOf[IRContext] // ok! type level only - registerClassEntry(clazz, - methods = Map( - mkMethod(clazz, "some", Array[Class[_]](classOf[Base#Ref[_]])) { (obj, args) => - obj.asInstanceOf[ctx.WSpecialPredefCompanion].some(args(0).asInstanceOf[ctx.Ref[Any]]) - } - ) - ) - } { val clazz = classOf[OptionWrapSpec] registerClassEntry(clazz, diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/IRContext.scala b/sc/shared/src/main/scala/sigma/compiler/ir/IRContext.scala index 908e4ccb33..c60bc0882f 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/IRContext.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/IRContext.scala @@ -5,7 +5,7 @@ import sigma.compiler.ir.primitives._ import sigma.data.{Nullable, RType} import sigma.util.MemoizedFunc import sigma.compiler.ir.wrappers.scala.WOptionsModule -import sigma.compiler.ir.wrappers.sigma.{CollsModule, SigmaDslModule, WRTypesModule, WSpecialPredefsModule} +import sigma.compiler.ir.wrappers.sigma.{CollsModule, SigmaDslModule, WRTypesModule} /** Aggregate cake with all inter-dependent modules assembled together. * Each instance of this class contains independent IR context, thus many @@ -34,7 +34,7 @@ trait IRContext with LogicalOps with OrderingOps with Equal - with MiscelaneousOps + with MiscOps with Functions with IfThenElse with Transforming @@ -46,7 +46,6 @@ trait IRContext with SigmaDslModule with TreeBuilding with GraphBuilding - with WSpecialPredefsModule with WOptionsModule with WRTypesModule { @@ -54,7 +53,6 @@ trait IRContext import CollBuilder._ import WOption._ import WRType._ - import WSpecialPredef._ /** Pass configuration which is used to turn-off constant propagation. * USED IN TESTS ONLY. @@ -74,11 +72,7 @@ trait IRContext _liftElemMemo(eT).asInstanceOf[Ref[WRType[T]]] // asRep cannot be used for AnyRef } - private val _specialPredef: LazyRep[WSpecialPredefCompanionCtor] = MutableLazy(RWSpecialPredef.value) - def specialPredef: Ref[WSpecialPredefCompanionCtor] = _specialPredef.value - override protected def onReset(): Unit = { - _specialPredef.reset() _liftElemMemo.reset() super.onReset() } @@ -86,7 +80,6 @@ trait IRContext val CM = CollMethods private val CBM = CollBuilderMethods private val WOptionM = WOptionMethods - private val SPCM = WSpecialPredefCompanionMethods def colBuilder: Ref[CollBuilder] @@ -150,8 +143,6 @@ trait IRContext } case WOptionM.getOrElse(opt, _) => opt.node match { - // Rule: Some(x).getOrElse(_) ==> x - case SPCM.some(x) => x case WOptionConst(Some(x), lA) => lA.lift(x) case _ => super.rewriteDef(d) } diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/TreeBuilding.scala b/sc/shared/src/main/scala/sigma/compiler/ir/TreeBuilding.scala index 4c54ef711b..725e3b1d19 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/TreeBuilding.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/TreeBuilding.scala @@ -128,7 +128,7 @@ trait TreeBuilding extends Base { IR: IRContext => */ object IsInternalDef { def unapply(d: Def[_]): Option[Def[_]] = d match { - case _: SigmaDslBuilder | _: CollBuilder | _: WSpecialPredefCompanion => Some(d) + case _: SigmaDslBuilder | _: CollBuilder => Some(d) case _ => None } } diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/primitives/MiscelaneousOps.scala b/sc/shared/src/main/scala/sigma/compiler/ir/primitives/MiscOps.scala similarity index 89% rename from sc/shared/src/main/scala/sigma/compiler/ir/primitives/MiscelaneousOps.scala rename to sc/shared/src/main/scala/sigma/compiler/ir/primitives/MiscOps.scala index 633306da8c..58382a279c 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/primitives/MiscelaneousOps.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/primitives/MiscOps.scala @@ -2,7 +2,10 @@ package sigma.compiler.ir.primitives import sigma.compiler.ir.{Base, IRContext} -trait MiscelaneousOps extends Base { self: IRContext => +/** Defines IR representation of miscellaneous operations that doesn't fit into any + * specific category. + */ +trait MiscOps extends Base { self: IRContext => case class HashCode[A]() extends UnOp[A, Int]("hashCode") { override def applySeq(x: A): Int = x.hashCode } diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/scala/WOptions.scala b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/scala/WOptions.scala index d6c0971214..2ed1237e6b 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/scala/WOptions.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/scala/WOptions.scala @@ -1,6 +1,7 @@ package sigma.compiler.ir.wrappers.scala { import sigma.compiler.ir.{Base, IRContext} + /** Defines IR representation of Option type. */ trait WOptions extends Base { self: IRContext => trait WOption[A] extends Def[WOption[A]] { implicit def eA: Elem[A]; diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/scala/impl/WOptionsImpl.scala b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/scala/impl/WOptionsImpl.scala index 307e380a76..514415d2bd 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/scala/impl/WOptionsImpl.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/scala/impl/WOptionsImpl.scala @@ -13,6 +13,7 @@ package impl { import sigma.reflection.{RClass, RMethod} // Abs ----------------------------------- +/** IR representation of Option type and methods. */ trait WOptionsDefs extends Base with WOptions { self: IRContext => diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/SigmaDslUnit.scala b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/SigmaDslUnit.scala index 7b9d499c7e..2a6a341686 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/SigmaDslUnit.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/SigmaDslUnit.scala @@ -3,6 +3,7 @@ package sigma.compiler.ir.wrappers.sigma import scalan._ import sigma.compiler.ir.{Base, IRContext} + /** IR representation of ErgoScript (Sigma) language types and methods. */ trait SigmaDsl extends Base { self: IRContext => trait BigInt extends Def[BigInt] { def add(that: Ref[BigInt]): Ref[BigInt]; diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/WRTypes.scala b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/WRTypes.scala index b4981dda4f..0bd2b47e5b 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/WRTypes.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/WRTypes.scala @@ -3,6 +3,7 @@ package sigma.compiler.ir.wrappers.sigma import sigma.compiler.ir.{Base, IRContext} + /** IR representation of RType. */ trait WRTypes extends Base { self: IRContext => trait WRType[A] extends Def[WRType[A]] { implicit def eA: Elem[A]; diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/WSpecialPredefs.scala b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/WSpecialPredefs.scala deleted file mode 100644 index c7529d1ca6..0000000000 --- a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/WSpecialPredefs.scala +++ /dev/null @@ -1,10 +0,0 @@ -package sigma.compiler.ir.wrappers.sigma - -import sigma.compiler.ir.{Base, IRContext} - - trait WSpecialPredefs extends Base { self: IRContext => - trait WSpecialPredef extends Def[WSpecialPredef]; - trait WSpecialPredefCompanion { - def some[A](x: Ref[A]): Ref[WOption[A]]; - } - } \ No newline at end of file diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/CollsImpl.scala b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/CollsImpl.scala index fd3f72a642..0a18ea586a 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/CollsImpl.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/CollsImpl.scala @@ -12,7 +12,8 @@ package impl { import sigma.data.{Nullable, RType} import sigma.reflection.{RClass, RMethod} - // Abs ----------------------------------- +// Abs ----------------------------------- +/** Implementation part of IR represenation related to Coll type and methods. */ trait CollsDefs extends Base with Colls { self: IRContext => diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/SigmaDslImpl.scala b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/SigmaDslImpl.scala index 201c974512..c113cb7de3 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/SigmaDslImpl.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/SigmaDslImpl.scala @@ -14,6 +14,7 @@ package impl { import sigma.data.{Nullable, RType} import sigma.reflection.{RClass, RMethod} +/** Implementation part of IR represenation related to Sigma types and methods. */ // Abs ----------------------------------- trait SigmaDslDefs extends Base with SigmaDsl { self: IRContext => diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/WRTypesImpl.scala b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/WRTypesImpl.scala index 20d3bdf965..beddba3085 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/WRTypesImpl.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/WRTypesImpl.scala @@ -13,6 +13,7 @@ package impl { import sigma.compiler.ir.{Base, GraphIRReflection, IRContext} import sigma.reflection.{RClass, RMethod} +/** Implementation of IR nodes related to [[RType]]. */ // Abs ----------------------------------- trait WRTypesDefs extends Base with WRTypes { self: IRContext => diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/WSpecialPredefsImpl.scala b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/WSpecialPredefsImpl.scala deleted file mode 100644 index 4624a052ee..0000000000 --- a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/WSpecialPredefsImpl.scala +++ /dev/null @@ -1,72 +0,0 @@ -package sigma.compiler.ir.wrappers.sigma - -import scala.language.{existentials, implicitConversions} -import sigma.compiler.ir.IRContext - -package impl { - import sigma.compiler.ir.core.MutableLazy - import sigma.compiler.ir.meta.ModuleInfo - import sigma.compiler.ir.wrappers.sigma.WSpecialPredefs - import sigma.compiler.ir.{Base, GraphIRReflection, IRContext} - import sigma.data.Nullable - import sigma.reflection.RClass - - // Abs ----------------------------------- -trait WSpecialPredefsDefs extends Base with WSpecialPredefs { - self: IRContext => - - registerModule(WSpecialPredefsModule) - -import WOption._ -import WSpecialPredef._ - -object WSpecialPredef extends EntityObject("WSpecialPredef") { - - implicit case object WSpecialPredefCompanionElem extends CompanionElem[WSpecialPredefCompanionCtor] - - abstract class WSpecialPredefCompanionCtor extends CompanionDef[WSpecialPredefCompanionCtor] with WSpecialPredefCompanion { - def resultType = WSpecialPredefCompanionElem - override def toString = "WSpecialPredef" - } - implicit final def unrefWSpecialPredefCompanionCtor(p: Ref[WSpecialPredefCompanionCtor]): WSpecialPredefCompanionCtor = - p.node.asInstanceOf[WSpecialPredefCompanionCtor] - - lazy val RWSpecialPredef: MutableLazy[WSpecialPredefCompanionCtor] = MutableLazy(new WSpecialPredefCompanionCtor { - private val thisClass = RClass(classOf[WSpecialPredefCompanion]) - - def some[A](x: Ref[A]): Ref[WOption[A]] = { - implicit val eA = x.elem - asRep[WOption[A]](mkMethodCall(self, - thisClass.getMethod("some", classOf[Sym]), - Array[AnyRef](x), - true, false, element[WOption[A]])) - } - }) - - object WSpecialPredefCompanionMethods { - object some { - def unapply(d: Def[_]): Nullable[Ref[A] forSome {type A}] = d match { - case MethodCall(receiver, method, args, _) if method.getName == "some" && receiver.elem == WSpecialPredefCompanionElem => - val res = args(0) - Nullable(res).asInstanceOf[Nullable[Ref[A] forSome {type A}]] - case _ => Nullable.None - } - def unapply(exp: Sym): Nullable[Ref[A] forSome {type A}] = unapply(exp.node) - } - } -} // of object WSpecialPredef - registerEntityObject("WSpecialPredef", WSpecialPredef) - - override def resetContext(): Unit = { - super.resetContext() - RWSpecialPredef.reset() - } - -} - -object WSpecialPredefsModule extends ModuleInfo("sigma.compiler.ir.wrappers.special", "WSpecialPredefs") { - val reflection = GraphIRReflection -} -} - -trait WSpecialPredefsModule extends sigma.compiler.ir.wrappers.sigma.impl.WSpecialPredefsDefs {self: IRContext =>} diff --git a/sc/shared/src/test/scala/special/wrappers/WSpecialPredefTests.scala b/sc/shared/src/test/scala/special/wrappers/WSpecialPredefTests.scala deleted file mode 100644 index 75123cf5bd..0000000000 --- a/sc/shared/src/test/scala/special/wrappers/WSpecialPredefTests.scala +++ /dev/null @@ -1,23 +0,0 @@ -package special.wrappers - - -import scala.language.reflectiveCalls - -class WSpecialPredefTests extends WrappersTests { - - lazy val ctx = new WrappersCtx - import ctx._ - import WSpecialPredef._ - - lazy val SPCM = WSpecialPredefCompanionMethods - - test("some") { - val x: Ref[Int] = 10 - val opt = RWSpecialPredef.some(x) - opt match { - case SPCM.some(_x) => _x shouldBe x - case _ => assert(false) - } - } - -} From c1d3ce1440b28e7468179e4e4353b0598ea75139 Mon Sep 17 00:00:00 2001 From: Alexander Slesarenko Date: Thu, 16 May 2024 22:38:46 +0100 Subject: [PATCH 081/314] v6.0-serialize: SigmaDslBuilder.serialize added SMethod declaration --- .../src/main/scala/sigma/SigmaDsl.scala | 3 ++ .../sigma/reflection/ReflectionData.scala | 4 ++ .../src/main/scala/sigma/ast/methods.scala | 37 ++++++++++++++++--- .../scala/sigma/data/CSigmaDslBuilder.scala | 14 +++++-- 4 files changed, 50 insertions(+), 8 deletions(-) diff --git a/core/shared/src/main/scala/sigma/SigmaDsl.scala b/core/shared/src/main/scala/sigma/SigmaDsl.scala index df2b419273..6e306f7a0b 100644 --- a/core/shared/src/main/scala/sigma/SigmaDsl.scala +++ b/core/shared/src/main/scala/sigma/SigmaDsl.scala @@ -727,6 +727,9 @@ trait SigmaDslBuilder { /** Construct a new authenticated dictionary with given parameters and tree root digest. */ def avlTree(operationFlags: Byte, digest: Coll[Byte], keyLength: Int, valueLengthOpt: Option[Int]): AvlTree + /** Serializes the given `value` into bytes using the default serialization format. */ + def serialize[T](value: T)(implicit cT: RType[T]): Coll[Byte] + /** Returns a byte-wise XOR of the two collections of bytes. */ def xor(l: Coll[Byte], r: Coll[Byte]): Coll[Byte] } diff --git a/core/shared/src/main/scala/sigma/reflection/ReflectionData.scala b/core/shared/src/main/scala/sigma/reflection/ReflectionData.scala index 028e68bf72..5cd678b712 100644 --- a/core/shared/src/main/scala/sigma/reflection/ReflectionData.scala +++ b/core/shared/src/main/scala/sigma/reflection/ReflectionData.scala @@ -441,6 +441,10 @@ object ReflectionData { mkMethod(clazz, "sha256", Array[Class[_]](cColl)) { (obj, args) => obj.asInstanceOf[SigmaDslBuilder].sha256(args(0).asInstanceOf[Coll[Byte]]) }, + mkMethod(clazz, "serialize", Array[Class[_]](classOf[Object], classOf[RType[_]])) { (obj, args) => + obj.asInstanceOf[SigmaDslBuilder].serialize[Any]( + args(0).asInstanceOf[Any])(args(1).asInstanceOf[RType[Any]]) + }, mkMethod(clazz, "decodePoint", Array[Class[_]](cColl)) { (obj, args) => obj.asInstanceOf[SigmaDslBuilder].decodePoint(args(0).asInstanceOf[Coll[Byte]]) } diff --git a/data/shared/src/main/scala/sigma/ast/methods.scala b/data/shared/src/main/scala/sigma/ast/methods.scala index e4cf0007e0..dd33802b1d 100644 --- a/data/shared/src/main/scala/sigma/ast/methods.scala +++ b/data/shared/src/main/scala/sigma/ast/methods.scala @@ -5,7 +5,7 @@ import org.ergoplatform.validation._ import sigma._ import sigma.ast.SCollection.{SBooleanArray, SBoxArray, SByteArray, SByteArray2, SHeaderArray} import sigma.ast.SMethod.{MethodCallIrBuilder, MethodCostFunc, javaMethodOf} -import sigma.ast.SType.TypeCode +import sigma.ast.SType.{TypeCode, paramT, tT} import sigma.ast.syntax.{SValue, ValueOps} import sigma.data.OverloadHack.Overloaded1 import sigma.data.{DataValueComparer, KeyValueColl, Nullable, RType, SigmaConstants} @@ -1519,9 +1519,36 @@ case object SGlobalMethods extends MonoTypeMethods { Xor.xorWithCosting(ls, rs) } - protected override def getMethods() = super.getMethods() ++ Seq( - groupGeneratorMethod, - xorMethod - ) + lazy val serializeMethod = SMethod(this, "serialize", + SFunc(Array(SGlobal, tT), SByteArray, Array(paramT)), 3, DynamicCost) + .withIRInfo(MethodCallIrBuilder) + .withInfo(MethodCall, "", + ArgInfo("value", "value to be serialized")) + + + /** Implements evaluation of Global.serialize method call ErgoTree node. + * Called via reflection based on naming convention. + * @see SMethod.evalMethod + */ + def serialize_eval(mc: MethodCall, G: SigmaDslBuilder, value: Any, tpe: RType[Any]) + (implicit E: ErgoTreeEvaluator): Coll[Byte] = { + // TODO v6.0: accumulate cost + G.serialize(value)(tpe) + } + + protected override def getMethods() = super.getMethods() ++ { + if (VersionContext.current.isV6SoftForkActivated) { + Seq( + groupGeneratorMethod, + xorMethod, + serializeMethod + ) + } else { + Seq( + groupGeneratorMethod, + xorMethod + ) + } + } } diff --git a/data/shared/src/main/scala/sigma/data/CSigmaDslBuilder.scala b/data/shared/src/main/scala/sigma/data/CSigmaDslBuilder.scala index 3938feacd3..21b9900028 100644 --- a/data/shared/src/main/scala/sigma/data/CSigmaDslBuilder.scala +++ b/data/shared/src/main/scala/sigma/data/CSigmaDslBuilder.scala @@ -5,13 +5,13 @@ import org.ergoplatform.ErgoBox import org.ergoplatform.validation.ValidationRules import scorex.crypto.hash.{Blake2b256, Sha256} import scorex.utils.Longs -import sigma.ast.{AtLeast, SubstConstants} +import sigma.ast.{AtLeast, SType, SubstConstants} import sigma.crypto.{CryptoConstants, EcPointType, Ecp} import sigma.eval.Extensions.EvalCollOps -import sigma.serialization.{GroupElementSerializer, SigmaSerializer} +import sigma.serialization.{DataSerializer, GroupElementSerializer, SigmaSerializer} import sigma.util.Extensions.BigIntegerOps import sigma.validation.SigmaValidationSettings -import sigma.{AvlTree, BigInt, Box, Coll, CollBuilder, GroupElement, SigmaDslBuilder, SigmaProp, VersionContext} +import sigma.{AvlTree, BigInt, Box, Coll, CollBuilder, Evaluation, GroupElement, SigmaDslBuilder, SigmaProp, VersionContext} import java.math.BigInteger @@ -200,6 +200,14 @@ class CSigmaDslBuilder extends SigmaDslBuilder { dsl => val p = GroupElementSerializer.parse(r) this.GroupElement(p) } + + /** Serializes the given `value` into bytes using the default serialization format. */ + override def serialize[T](value: T)(implicit cT: RType[T]): Coll[Byte] = { + val tpe = Evaluation.rtypeToSType(cT) + val w = SigmaSerializer.startWriter() + DataSerializer.serialize(value.asInstanceOf[SType#WrappedType], tpe, w) + Colls.fromArray(w.toBytes) + } } /** Default singleton instance of Global object, which implements global ErgoTree functions. */ From eeb0d4ac0ceda87c6d426728f13ecd6011bb581b Mon Sep 17 00:00:00 2001 From: Alexander Slesarenko Date: Fri, 17 May 2024 11:35:59 +0100 Subject: [PATCH 082/314] v6.0-serialize: added SMethod.runtimeTypeArgs --- .../src/main/scala/sigma/ast/SMethod.scala | 34 ++++++++++++------- .../src/main/scala/sigma/ast/values.scala | 2 ++ .../serialization/MethodCallSerializer.scala | 18 ++++++++-- .../sigma/compiler/phases/SigmaTyper.scala | 2 +- 4 files changed, 39 insertions(+), 17 deletions(-) diff --git a/data/shared/src/main/scala/sigma/ast/SMethod.scala b/data/shared/src/main/scala/sigma/ast/SMethod.scala index 669625ef1e..fea76ecf52 100644 --- a/data/shared/src/main/scala/sigma/ast/SMethod.scala +++ b/data/shared/src/main/scala/sigma/ast/SMethod.scala @@ -50,17 +50,19 @@ case class MethodIRInfo( /** Represents method descriptor. * - * @param objType type or type constructor descriptor - * @param name method name - * @param stype method signature type, - * where `stype.tDom`` - argument type and - * `stype.tRange` - method result type. - * @param methodId method code, it should be unique among methods of the same objType. - * @param costKind cost descriptor for this method - * @param irInfo meta information connecting SMethod with ErgoTree (see [[MethodIRInfo]]) - * @param docInfo optional human readable method description data - * @param costFunc optional specification of how the cost should be computed for the - * given method call (See ErgoTreeEvaluator.calcCost method). + * @param objType type or type constructor descriptor + * @param name method name + * @param stype method signature type, + * where `stype.tDom`` - argument type and + * `stype.tRange` - method result type. + * @param methodId method code, it should be unique among methods of the same objType. + * @param costKind cost descriptor for this method + * @param runtimeTypeArgs list of runtime type parameters which require explicit + * serialization in [[MethodCall]]s + * @param irInfo meta information connecting SMethod with ErgoTree (see [[MethodIRInfo]]) + * @param docInfo optional human readable method description data + * @param costFunc optional specification of how the cost should be computed for the + * given method call (See ErgoTreeEvaluator.calcCost method). */ case class SMethod( objType: MethodsContainer, @@ -68,6 +70,7 @@ case class SMethod( stype: SFunc, methodId: Byte, costKind: CostKind, + runtimeTypeArgs: Seq[STypeVar], irInfo: MethodIRInfo, docInfo: Option[OperationInfo], costFunc: Option[MethodCostFunc]) { @@ -75,6 +78,9 @@ case class SMethod( /** Operation descriptor of this method. */ lazy val opDesc = MethodDesc(this) + /** Return true if this method has runtime type parameters */ + def isRuntimeGeneric: Boolean = runtimeTypeArgs.nonEmpty + /** Finds and keeps the [[RMethod]] instance which corresponds to this method descriptor. * The lazy value is forced only if irInfo.javaMethod == None */ @@ -284,9 +290,11 @@ object SMethod { /** Convenience factory method. */ def apply(objType: MethodsContainer, name: String, stype: SFunc, methodId: Byte, - costKind: CostKind): SMethod = { + costKind: CostKind, + runtimeTypeArgs: Seq[STypeVar] = Nil + ): SMethod = { SMethod( - objType, name, stype, methodId, costKind, + objType, name, stype, methodId, costKind, runtimeTypeArgs, MethodIRInfo(None, None, None), None, None) } diff --git a/data/shared/src/main/scala/sigma/ast/values.scala b/data/shared/src/main/scala/sigma/ast/values.scala index 87c661a00a..ee1bb8b783 100644 --- a/data/shared/src/main/scala/sigma/ast/values.scala +++ b/data/shared/src/main/scala/sigma/ast/values.scala @@ -1298,6 +1298,8 @@ case class MethodCall( method: SMethod, args: IndexedSeq[Value[SType]], typeSubst: Map[STypeVar, SType]) extends Value[SType] { + require(method.runtimeTypeArgs.forall(tyArg => typeSubst.contains(tyArg)), + s"Runtime Generic method call should have concrete type for each runtime type parameter, but was: $this") override def companion = if (args.isEmpty) PropertyCall else MethodCall override def opType: SFunc = SFunc(obj.tpe +: args.map(_.tpe), tpe) diff --git a/data/shared/src/main/scala/sigma/serialization/MethodCallSerializer.scala b/data/shared/src/main/scala/sigma/serialization/MethodCallSerializer.scala index 319a4284e2..f9c7658dda 100644 --- a/data/shared/src/main/scala/sigma/serialization/MethodCallSerializer.scala +++ b/data/shared/src/main/scala/sigma/serialization/MethodCallSerializer.scala @@ -1,7 +1,7 @@ package sigma.serialization import sigma.ast.syntax._ -import sigma.ast.{MethodCall, SContextMethods, SMethod, SType, STypeSubst, Value, ValueCompanion} +import sigma.ast.{MethodCall, SContextMethods, SMethod, SType, STypeSubst, STypeVar, Value, ValueCompanion} import sigma.util.safeNewArray import SigmaByteWriter._ import debox.cfor @@ -23,6 +23,10 @@ case class MethodCallSerializer(cons: (Value[SType], SMethod, IndexedSeq[Value[S w.putValue(mc.obj, objInfo) assert(mc.args.nonEmpty) w.putValues(mc.args, argsInfo, argsItemInfo) + mc.method.runtimeTypeArgs.foreach { a => + val tpe = mc.typeSubst(a) // existence is checked in MethodCall constructor + w.putType(tpe) + } } /** The SMethod instances in STypeCompanions may have type STypeIdent in methods types, @@ -42,7 +46,15 @@ case class MethodCallSerializer(cons: (Value[SType], SMethod, IndexedSeq[Value[S val methodId = r.getByte() val obj = r.getValue() val args = r.getValues() - val method = SMethod.fromIds(typeId, methodId) + val (method, runtimeTypeArgs) = SMethod.fromIds(typeId, methodId) match { + case m if m.isRuntimeGeneric => + val subst = m.runtimeTypeArgs.map { a => + a -> r.getType() // READ + }.toMap + (m.withConcreteTypes(subst), subst) + case m => (m, Map.empty[STypeVar, SType]) + } + val nArgs = args.length val types: Seq[SType] = @@ -61,6 +73,6 @@ case class MethodCallSerializer(cons: (Value[SType], SMethod, IndexedSeq[Value[S BlockchainContextMethodNames.contains(method.name) r.wasUsingBlockchainContext ||= isUsingBlockchainContext - cons(obj, specMethod, args, Map.empty) + cons(obj, specMethod, args, runtimeTypeArgs) } } diff --git a/sc/shared/src/main/scala/sigma/compiler/phases/SigmaTyper.scala b/sc/shared/src/main/scala/sigma/compiler/phases/SigmaTyper.scala index 679d98a18f..764d2b1eb7 100644 --- a/sc/shared/src/main/scala/sigma/compiler/phases/SigmaTyper.scala +++ b/sc/shared/src/main/scala/sigma/compiler/phases/SigmaTyper.scala @@ -139,7 +139,7 @@ class SigmaTyper(val builder: SigmaBuilder, obj.tpe match { case p: SProduct => MethodsContainer.getMethod(p, n) match { - case Some(method @ SMethod(_, _, genFunTpe @ SFunc(_, _, _), _, _, _, _, _)) => + case Some(method @ SMethod(_, _, genFunTpe @ SFunc(_, _, _), _, _, _, _, _, _)) => val subst = Map(genFunTpe.tpeParams.head.ident -> rangeTpe) val concrFunTpe = applySubst(genFunTpe, subst) val expectedArgs = concrFunTpe.asFunc.tDom.tail From 5cbd065a8350faf0c98b98e7c5d5139454532b2c Mon Sep 17 00:00:00 2001 From: Alexander Slesarenko Date: Fri, 17 May 2024 13:22:25 +0100 Subject: [PATCH 083/314] v6.0-serialize: support of explicitTypeArgs in MethodCallSerializer --- .../src/main/scala/sigma/ast/SMethod.scala | 12 ++--- .../src/main/scala/sigma/ast/values.scala | 2 +- .../serialization/MethodCallSerializer.scala | 51 ++++++++++++------- docs/LangSpec.md | 7 ++- 4 files changed, 46 insertions(+), 26 deletions(-) diff --git a/data/shared/src/main/scala/sigma/ast/SMethod.scala b/data/shared/src/main/scala/sigma/ast/SMethod.scala index fea76ecf52..332c74be6b 100644 --- a/data/shared/src/main/scala/sigma/ast/SMethod.scala +++ b/data/shared/src/main/scala/sigma/ast/SMethod.scala @@ -57,8 +57,8 @@ case class MethodIRInfo( * `stype.tRange` - method result type. * @param methodId method code, it should be unique among methods of the same objType. * @param costKind cost descriptor for this method - * @param runtimeTypeArgs list of runtime type parameters which require explicit - * serialization in [[MethodCall]]s + * @param explicitTypeArgs list of type parameters which require explicit + * serialization in [[MethodCall]]s (i.e for deserialize[T], getVar[T], getReg[T]) * @param irInfo meta information connecting SMethod with ErgoTree (see [[MethodIRInfo]]) * @param docInfo optional human readable method description data * @param costFunc optional specification of how the cost should be computed for the @@ -70,7 +70,7 @@ case class SMethod( stype: SFunc, methodId: Byte, costKind: CostKind, - runtimeTypeArgs: Seq[STypeVar], + explicitTypeArgs: Seq[STypeVar], irInfo: MethodIRInfo, docInfo: Option[OperationInfo], costFunc: Option[MethodCostFunc]) { @@ -79,7 +79,7 @@ case class SMethod( lazy val opDesc = MethodDesc(this) /** Return true if this method has runtime type parameters */ - def isRuntimeGeneric: Boolean = runtimeTypeArgs.nonEmpty + def hasExplicitTypeArgs: Boolean = explicitTypeArgs.nonEmpty /** Finds and keeps the [[RMethod]] instance which corresponds to this method descriptor. * The lazy value is forced only if irInfo.javaMethod == None @@ -291,10 +291,10 @@ object SMethod { def apply(objType: MethodsContainer, name: String, stype: SFunc, methodId: Byte, costKind: CostKind, - runtimeTypeArgs: Seq[STypeVar] = Nil + explicitTypeArgs: Seq[STypeVar] = Nil ): SMethod = { SMethod( - objType, name, stype, methodId, costKind, runtimeTypeArgs, + objType, name, stype, methodId, costKind, explicitTypeArgs, MethodIRInfo(None, None, None), None, None) } diff --git a/data/shared/src/main/scala/sigma/ast/values.scala b/data/shared/src/main/scala/sigma/ast/values.scala index ee1bb8b783..7980fd96ce 100644 --- a/data/shared/src/main/scala/sigma/ast/values.scala +++ b/data/shared/src/main/scala/sigma/ast/values.scala @@ -1298,7 +1298,7 @@ case class MethodCall( method: SMethod, args: IndexedSeq[Value[SType]], typeSubst: Map[STypeVar, SType]) extends Value[SType] { - require(method.runtimeTypeArgs.forall(tyArg => typeSubst.contains(tyArg)), + require(method.explicitTypeArgs.forall(tyArg => typeSubst.contains(tyArg)), s"Runtime Generic method call should have concrete type for each runtime type parameter, but was: $this") override def companion = if (args.isEmpty) PropertyCall else MethodCall diff --git a/data/shared/src/main/scala/sigma/serialization/MethodCallSerializer.scala b/data/shared/src/main/scala/sigma/serialization/MethodCallSerializer.scala index f9c7658dda..abc12c9c9e 100644 --- a/data/shared/src/main/scala/sigma/serialization/MethodCallSerializer.scala +++ b/data/shared/src/main/scala/sigma/serialization/MethodCallSerializer.scala @@ -8,6 +8,8 @@ import debox.cfor import sigma.ast.SContextMethods.BlockchainContextMethodNames import sigma.serialization.CoreByteWriter.{ArgInfo, DataInfo} +import scala.collection.compat.immutable.ArraySeq + case class MethodCallSerializer(cons: (Value[SType], SMethod, IndexedSeq[Value[SType]], STypeSubst) => Value[SType]) extends ValueSerializer[MethodCall] { override def opDesc: ValueCompanion = MethodCall @@ -23,7 +25,7 @@ case class MethodCallSerializer(cons: (Value[SType], SMethod, IndexedSeq[Value[S w.putValue(mc.obj, objInfo) assert(mc.args.nonEmpty) w.putValues(mc.args, argsInfo, argsItemInfo) - mc.method.runtimeTypeArgs.foreach { a => + mc.method.explicitTypeArgs.foreach { a => val tpe = mc.typeSubst(a) // existence is checked in MethodCall constructor w.putType(tpe) } @@ -46,18 +48,37 @@ case class MethodCallSerializer(cons: (Value[SType], SMethod, IndexedSeq[Value[S val methodId = r.getByte() val obj = r.getValue() val args = r.getValues() - val (method, runtimeTypeArgs) = SMethod.fromIds(typeId, methodId) match { - case m if m.isRuntimeGeneric => - val subst = m.runtimeTypeArgs.map { a => - a -> r.getType() // READ - }.toMap - (m.withConcreteTypes(subst), subst) - case m => (m, Map.empty[STypeVar, SType]) - } + val method = SMethod.fromIds(typeId, methodId) - val nArgs = args.length + val explicitTypes = if (method.hasExplicitTypeArgs) { + val nTypes = method.explicitTypeArgs.length + val res = safeNewArray[SType](nTypes) + cfor(0)(_ < nTypes, _ + 1) { i => + res(i) = r.getType() + } + ArraySeq.unsafeWrapArray(res) + } else SType.EmptySeq + + val explicitTypeSubst = method.explicitTypeArgs.zip(explicitTypes).toMap + val specMethod = getSpecializedMethodFor(method, explicitTypeSubst, obj, args) + + var isUsingBlockchainContext = specMethod.objType == SContextMethods && + BlockchainContextMethodNames.contains(method.name) + r.wasUsingBlockchainContext ||= isUsingBlockchainContext - val types: Seq[SType] = + cons(obj, specMethod, args, explicitTypeSubst) + } + + def getSpecializedMethodFor( + methodTemplate: SMethod, + explicitTypeSubst: STypeSubst, + obj: SValue, + args: Seq[SValue] + ): SMethod = { + // TODO optimize: avoid repeated transformation of method type + val method = methodTemplate.withConcreteTypes(explicitTypeSubst) + val nArgs = args.length + val argTypes: Seq[SType] = if (nArgs == 0) SType.EmptySeq else { val types = safeNewArray[SType](nArgs) @@ -67,12 +88,6 @@ case class MethodCallSerializer(cons: (Value[SType], SMethod, IndexedSeq[Value[S types } - val specMethod = method.specializeFor(obj.tpe, types) - - var isUsingBlockchainContext = specMethod.objType == SContextMethods && - BlockchainContextMethodNames.contains(method.name) - r.wasUsingBlockchainContext ||= isUsingBlockchainContext - - cons(obj, specMethod, args, runtimeTypeArgs) + method.specializeFor(obj.tpe, argTypes) } } diff --git a/docs/LangSpec.md b/docs/LangSpec.md index ba66748f08..04b345d6d9 100644 --- a/docs/LangSpec.md +++ b/docs/LangSpec.md @@ -68,7 +68,7 @@ The following sections describe ErgoScript and its operations. #### Operations and constructs overview - Binary operations: `>, <, >=, <=, +, -, &&, ||, ==, !=, |, &, *, /, %, ^, ++` -- predefined primitives: `blake2b256`, `byteArrayToBigInt`, `proveDlog` etc. +- predefined primitives: `serialize`, `blake2b256`, `byteArrayToBigInt`, `proveDlog` etc. - val declarations: `val h = blake2b256(pubkey)` - if-then-else clause: `if (x > 0) 1 else 0` - collection literals: `Coll(1, 2, 3, 4)` @@ -1041,6 +1041,11 @@ def deserialize[T](string: String): T * replaced and all other bytes remain exactly the same */ def substConstants[T](scriptBytes: Coll[Byte], positions: Coll[Int], newValues: Coll[T]): Coll[Byte] + +/** Serializes an instance of type T using default serialization format. + * See https://github.com/ScorexFoundation/sigmastate-interpreter/issues/988 for more details + */ +def serialize[T](value: T): Coll[Byte] ``` ## Examples From 3f4508abdf9f259c321dbb4105360baf96f77ef7 Mon Sep 17 00:00:00 2001 From: Alexander Slesarenko Date: Fri, 17 May 2024 15:26:15 +0100 Subject: [PATCH 084/314] v6.0-serialize: SigmaParserTest for serialize() --- .../sigmastate/helpers/SigmaPPrint.scala | 6 ++---- .../sigmastate/lang/SigmaParserTest.scala | 20 +++++++++++++++++++ .../sigmastate/helpers/SigmaPPrintSpec.scala | 1 - 3 files changed, 22 insertions(+), 5 deletions(-) rename {sc => parsers}/shared/src/test/scala/sigmastate/helpers/SigmaPPrint.scala (98%) diff --git a/sc/shared/src/test/scala/sigmastate/helpers/SigmaPPrint.scala b/parsers/shared/src/test/scala/sigmastate/helpers/SigmaPPrint.scala similarity index 98% rename from sc/shared/src/test/scala/sigmastate/helpers/SigmaPPrint.scala rename to parsers/shared/src/test/scala/sigmastate/helpers/SigmaPPrint.scala index 1b0f7b112d..24aaeddefd 100644 --- a/sc/shared/src/test/scala/sigmastate/helpers/SigmaPPrint.scala +++ b/parsers/shared/src/test/scala/sigmastate/helpers/SigmaPPrint.scala @@ -5,15 +5,13 @@ import org.ergoplatform.ErgoBox.RegisterId import org.ergoplatform.settings.ErgoAlgos import pprint.{PPrinter, Tree} import sigma.ast.SCollection.{SBooleanArray, SByteArray, SByteArray2} -import sigma.ast._ +import sigma.ast.{ConstantNode, FuncValue, MethodCall, ValueCompanion, _} import sigma.crypto.EcPointType import sigma.data.{AvlTreeData, AvlTreeFlags, CollType, PrimitiveType, TrivialProp} import sigma.serialization.GroupElementSerializer import sigma.{Coll, GroupElement} -import sigma.ast.{ConstantNode, FuncValue, ValueCompanion} -import sigmastate._ import sigmastate.crypto.GF2_192_Poly -import sigma.ast.MethodCall + import java.math.BigInteger import scala.collection.compat.immutable.ArraySeq import scala.collection.mutable diff --git a/parsers/shared/src/test/scala/sigmastate/lang/SigmaParserTest.scala b/parsers/shared/src/test/scala/sigmastate/lang/SigmaParserTest.scala index 02b28f86ca..70aa540a4f 100644 --- a/parsers/shared/src/test/scala/sigmastate/lang/SigmaParserTest.scala +++ b/parsers/shared/src/test/scala/sigmastate/lang/SigmaParserTest.scala @@ -14,6 +14,7 @@ import SigmaPredef.PredefinedFuncRegistry import sigma.ast.syntax._ import sigmastate.lang.parsers.ParserException import sigma.serialization.OpCodes +import sigmastate.helpers.SigmaPPrint class SigmaParserTest extends AnyPropSpec with ScalaCheckPropertyChecks with Matchers with LangTests { import StdSigmaBuilder._ @@ -34,6 +35,14 @@ class SigmaParserTest extends AnyPropSpec with ScalaCheckPropertyChecks with Mat } } + def checkParsed(x: String, expected: SValue) = { + val parsed = parse(x) + if (expected != parsed) { + SigmaPPrint.pprintln(parsed, width = 100) + } + parsed shouldBe expected + } + def parseWithException(x: String): SValue = { SigmaParser(x) match { case Parsed.Success(v, _) => v @@ -894,6 +903,17 @@ class SigmaParserTest extends AnyPropSpec with ScalaCheckPropertyChecks with Mat ) } + property("serialize") { + checkParsed("serialize(1)", Apply(Ident("serialize", NoType), Array(IntConstant(1)))) + checkParsed("serialize((1, 2L))", + Apply(Ident("serialize", NoType), Array(Tuple(Vector(IntConstant(1), LongConstant(2L)))))) + checkParsed("serialize(Coll(1, 2, 3))", + Apply( + Ident("serialize", NoType), + Array(Apply(Ident("Coll", NoType), Array(IntConstant(1), IntConstant(2), IntConstant(3)))) + )) + } + property("single name pattern fail") { fail("{val (a,b) = (1,2)}", 1, 6) } diff --git a/sc/jvm/src/test/scala/sigmastate/helpers/SigmaPPrintSpec.scala b/sc/jvm/src/test/scala/sigmastate/helpers/SigmaPPrintSpec.scala index 54c0f652dc..ffd591b0df 100644 --- a/sc/jvm/src/test/scala/sigmastate/helpers/SigmaPPrintSpec.scala +++ b/sc/jvm/src/test/scala/sigmastate/helpers/SigmaPPrintSpec.scala @@ -8,7 +8,6 @@ import sigma.SigmaDslTesting import sigma.ast._ import sigma.data.{AvlTreeData, AvlTreeFlags, CBox, CollType, Digest32Coll} import ErgoTree.HeaderType -import sigmastate.eval._ import sigma.ast.MethodCall import sigma.serialization.OpCodes import sigmastate.utils.Helpers From 12a958ce2467635ce1ddb33feb6f42817255b0f4 Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Fri, 17 May 2024 18:34:10 +0300 Subject: [PATCH 085/314] Option[T] (de)serialization --- .../src/main/scala/sigma/ast/SType.scala | 3 ++- .../serialization/CoreDataSerializer.scala | 10 ++++++++++ .../DataSerializerSpecification.scala | 18 ++++++++++++++++-- 3 files changed, 28 insertions(+), 3 deletions(-) diff --git a/core/shared/src/main/scala/sigma/ast/SType.scala b/core/shared/src/main/scala/sigma/ast/SType.scala index f75cbc9e8b..6656ede3c9 100644 --- a/core/shared/src/main/scala/sigma/ast/SType.scala +++ b/core/shared/src/main/scala/sigma/ast/SType.scala @@ -602,7 +602,8 @@ object STypeApply { /** Type description of optional values. Instances of `Option` * are either constructed by `Some` or by `None` constructors. */ case class SOption[ElemType <: SType](elemType: ElemType) extends SProduct with SGenericType { - override type WrappedType = Option[ElemType#WrappedType] + type ElemWrappedType = ElemType#WrappedType + override type WrappedType = Option[ElemWrappedType] override val typeCode: TypeCode = SOption.OptionTypeCode override def toString = s"Option[$elemType]" override def toTermString: String = s"Option[${elemType.toTermString}]" diff --git a/core/shared/src/main/scala/sigma/serialization/CoreDataSerializer.scala b/core/shared/src/main/scala/sigma/serialization/CoreDataSerializer.scala index 479b199da5..7b4ec81c7d 100644 --- a/core/shared/src/main/scala/sigma/serialization/CoreDataSerializer.scala +++ b/core/shared/src/main/scala/sigma/serialization/CoreDataSerializer.scala @@ -68,6 +68,12 @@ class CoreDataSerializer { i += 1 } + case SOption(elemType) => + val o = v.asInstanceOf[Option[elemType.WrappedType]] + w.putOption(o){case (w, v) => + serialize(v, elemType, w) + } + // TODO v6.0 (3h): support Option[T] (see https://github.com/ScorexFoundation/sigmastate-interpreter/issues/659) case _ => CheckSerializableTypeCode(tpe.typeCode) @@ -118,6 +124,10 @@ class CoreDataSerializer { }.toArray[Any] val coll = Colls.fromArray(arr)(sigma.AnyType) Evaluation.toDslTuple(coll, tuple) + case tOption: SOption[_] => + r.getOption[tOption.ElemWrappedType] { + deserialize(tOption.elemType, r).asInstanceOf[tOption.ElemWrappedType] + } case t => CheckSerializableTypeCode(t.typeCode) throw new SerializerException(s"Not defined DataSerializer for type $t") diff --git a/interpreter/shared/src/test/scala/sigma/serialization/DataSerializerSpecification.scala b/interpreter/shared/src/test/scala/sigma/serialization/DataSerializerSpecification.scala index 7cd9967e54..3ddaffde89 100644 --- a/interpreter/shared/src/test/scala/sigma/serialization/DataSerializerSpecification.scala +++ b/interpreter/shared/src/test/scala/sigma/serialization/DataSerializerSpecification.scala @@ -3,7 +3,7 @@ package sigma.serialization import java.math.BigInteger import org.ergoplatform.ErgoBox import org.scalacheck.Arbitrary._ -import sigma.data.{DataValueComparer, RType, SigmaBoolean, TupleColl} +import sigma.data.{DataValueComparer, OptionType, RType, SigmaBoolean, TupleColl} import sigma.ast.SCollection.SByteArray import sigmastate.eval._ import sigma.{AvlTree, Colls, Evaluation} @@ -14,7 +14,7 @@ import sigma.Extensions.ArrayOps import sigma.crypto.EcPointType import sigma.eval.SigmaDsl import sigma.util.Extensions.{BigIntegerOps, EcpOps, SigmaBooleanOps} -import sigmastate.interpreter.{CostAccumulator, CErgoTreeEvaluator} +import sigmastate.interpreter.{CErgoTreeEvaluator, CostAccumulator} import sigmastate.interpreter.CErgoTreeEvaluator.DefaultProfiler import sigmastate.utils.Helpers @@ -92,6 +92,19 @@ class DataSerializerSpecification extends SerializationSpecification { } } + def testOption[T <: SType](tpe: T) = { + implicit val wWrapped: Gen[T#WrappedType] = wrappedTypeGen(tpe) + val tT = Evaluation.stypeToRType(tpe) + forAll { in: T#WrappedType => + roundtrip[SType](Some(in).asWrappedType, SOption(tpe)) + roundtrip[SOption[T]](None, SOption(tpe)) + roundtrip[SOption[T]](Some(in), SOption(tpe)) + roundtrip[SOption[SCollection[T]]](Some(Colls.fromItems(in)(tT)), SOption(SCollectionType(tpe))) + roundtrip[SCollection[SOption[T]]](Colls.fromItems(Option(in), None.asInstanceOf[Option[T#WrappedType]])(OptionType(tT)), SCollectionType(SOption(tpe))) + roundtrip[SOption[SOption[T]]](Some(Some(in)), SOption(SOption(tpe))) + } + } + property("Data serialization round trip") { forAll { x: Byte => roundtrip[SByte.type](x, SByte) } forAll { x: Boolean => roundtrip[SBoolean.type](x, SBoolean) } @@ -105,6 +118,7 @@ class DataSerializerSpecification extends SerializationSpecification { forAll { x: Array[Byte] => roundtrip[SByteArray](x.toColl, SByteArray) } forAll { t: SPredefType => testCollection(t) } forAll { t: SPredefType => testTuples(t) } + forAll { t: SPredefType => testOption(t) } } property("Should check limits and fail") { From 4f2fb23cef3165625f7fb9224e412691c91d54f0 Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Fri, 17 May 2024 18:44:03 +0300 Subject: [PATCH 086/314] versioning and tests --- .../serialization/CoreDataSerializer.scala | 4 +-- .../DataSerializerSpecification.scala | 27 +++++++++++++------ 2 files changed, 21 insertions(+), 10 deletions(-) diff --git a/core/shared/src/main/scala/sigma/serialization/CoreDataSerializer.scala b/core/shared/src/main/scala/sigma/serialization/CoreDataSerializer.scala index 7b4ec81c7d..b8174aa31e 100644 --- a/core/shared/src/main/scala/sigma/serialization/CoreDataSerializer.scala +++ b/core/shared/src/main/scala/sigma/serialization/CoreDataSerializer.scala @@ -68,7 +68,7 @@ class CoreDataSerializer { i += 1 } - case SOption(elemType) => + case SOption(elemType) if VersionContext.current.isV6SoftForkActivated => val o = v.asInstanceOf[Option[elemType.WrappedType]] w.putOption(o){case (w, v) => serialize(v, elemType, w) @@ -124,7 +124,7 @@ class CoreDataSerializer { }.toArray[Any] val coll = Colls.fromArray(arr)(sigma.AnyType) Evaluation.toDslTuple(coll, tuple) - case tOption: SOption[_] => + case tOption: SOption[_] if VersionContext.current.isV6SoftForkActivated => r.getOption[tOption.ElemWrappedType] { deserialize(tOption.elemType, r).asInstanceOf[tOption.ElemWrappedType] } diff --git a/interpreter/shared/src/test/scala/sigma/serialization/DataSerializerSpecification.scala b/interpreter/shared/src/test/scala/sigma/serialization/DataSerializerSpecification.scala index 3ddaffde89..18c1f6a092 100644 --- a/interpreter/shared/src/test/scala/sigma/serialization/DataSerializerSpecification.scala +++ b/interpreter/shared/src/test/scala/sigma/serialization/DataSerializerSpecification.scala @@ -6,7 +6,7 @@ import org.scalacheck.Arbitrary._ import sigma.data.{DataValueComparer, OptionType, RType, SigmaBoolean, TupleColl} import sigma.ast.SCollection.SByteArray import sigmastate.eval._ -import sigma.{AvlTree, Colls, Evaluation} +import sigma.{AvlTree, Colls, Evaluation, VersionContext} import sigma.ast.SType.AnyOps import sigma.ast._ import org.scalacheck.Gen @@ -95,13 +95,24 @@ class DataSerializerSpecification extends SerializationSpecification { def testOption[T <: SType](tpe: T) = { implicit val wWrapped: Gen[T#WrappedType] = wrappedTypeGen(tpe) val tT = Evaluation.stypeToRType(tpe) - forAll { in: T#WrappedType => - roundtrip[SType](Some(in).asWrappedType, SOption(tpe)) - roundtrip[SOption[T]](None, SOption(tpe)) - roundtrip[SOption[T]](Some(in), SOption(tpe)) - roundtrip[SOption[SCollection[T]]](Some(Colls.fromItems(in)(tT)), SOption(SCollectionType(tpe))) - roundtrip[SCollection[SOption[T]]](Colls.fromItems(Option(in), None.asInstanceOf[Option[T#WrappedType]])(OptionType(tT)), SCollectionType(SOption(tpe))) - roundtrip[SOption[SOption[T]]](Some(Some(in)), SOption(SOption(tpe))) + + an[Exception] should be thrownBy ( + VersionContext.withVersions((VersionContext.V6SoftForkVersion - 1).toByte, 1) { + forAll { in: T#WrappedType => + roundtrip[SType](Some(in).asWrappedType, SOption(tpe)) + roundtrip[SOption[SCollection[T]]](Some(Colls.fromItems(in)(tT)), SOption(SCollectionType(tpe))) + } + }) + + VersionContext.withVersions(VersionContext.V6SoftForkVersion, 1) { + forAll { in: T#WrappedType => + roundtrip[SType](Some(in).asWrappedType, SOption(tpe)) + roundtrip[SOption[T]](None, SOption(tpe)) + roundtrip[SOption[T]](Some(in), SOption(tpe)) + roundtrip[SOption[SCollection[T]]](Some(Colls.fromItems(in)(tT)), SOption(SCollectionType(tpe))) + roundtrip[SCollection[SOption[T]]](Colls.fromItems(Option(in), None.asInstanceOf[Option[T#WrappedType]])(OptionType(tT)), SCollectionType(SOption(tpe))) + roundtrip[SOption[SOption[T]]](Some(Some(in)), SOption(SOption(tpe))) + } } } From 06386d46aaeaf3339a7e20e8e44dac5394d605b8 Mon Sep 17 00:00:00 2001 From: Alexander Slesarenko Date: Fri, 17 May 2024 16:53:23 +0100 Subject: [PATCH 087/314] v6.0-serialize: SigmaBinderTest and SigmaTyperTest --- .../main/scala/sigma/ast/SigmaPredef.scala | 23 +++++++++- .../scala/sigmastate/lang/LangTests.scala | 6 +++ .../sigma/compiler/phases/SigmaBinder.scala | 3 ++ .../sigma/compiler/phases/SigmaTyper.scala | 1 + .../sigmastate/lang/SigmaBinderTest.scala | 21 +++++++++ .../sigmastate/lang/SigmaTyperTest.scala | 43 ++++++++++++++++++- 6 files changed, 93 insertions(+), 4 deletions(-) diff --git a/data/shared/src/main/scala/sigma/ast/SigmaPredef.scala b/data/shared/src/main/scala/sigma/ast/SigmaPredef.scala index 631f7f2d75..f2da24d2df 100644 --- a/data/shared/src/main/scala/sigma/ast/SigmaPredef.scala +++ b/data/shared/src/main/scala/sigma/ast/SigmaPredef.scala @@ -403,6 +403,24 @@ object SigmaPredef { ArgInfo("default", "optional default value, if register is not available"))) ) + val SerializeFunc = PredefinedFunc("serialize", + Lambda(Seq(paramT), Array("value" -> tT), SByteArray, None), + PredefFuncInfo( + { case (_, args @ Seq(value)) => + MethodCall.typed[Value[SCollection[SByte.type]]]( + Global, + SGlobalMethods.serializeMethod.withConcreteTypes(Map(tT -> value.tpe)), + args.toIndexedSeq, + Map() + ) + }), + OperationInfo(MethodCall, + """ + """.stripMargin, + Seq(ArgInfo("value", "")) + ) + ) + val globalFuncs: Map[String, PredefinedFunc] = Seq( AllOfFunc, AnyOfFunc, @@ -430,7 +448,8 @@ object SigmaPredef { AvlTreeFunc, SubstConstantsFunc, ExecuteFromVarFunc, - ExecuteFromSelfRegFunc + ExecuteFromSelfRegFunc, + SerializeFunc ).map(f => f.name -> f).toMap def comparisonOp(symbolName: String, opDesc: ValueCompanion, desc: String, args: Seq[ArgInfo]) = { @@ -544,7 +563,7 @@ object SigmaPredef { val funcs: Map[String, PredefinedFunc] = globalFuncs ++ infixFuncs ++ unaryFuncs - /** WARNING: This operations are not used in frontend, and should be be used. + /** WARNING: This operations are not used in frontend, and should not be used. * They are used in SpecGen only the source of metadata for the corresponding ErgoTree nodes. */ val specialFuncs: Map[String, PredefinedFunc] = Seq( diff --git a/parsers/shared/src/test/scala/sigmastate/lang/LangTests.scala b/parsers/shared/src/test/scala/sigmastate/lang/LangTests.scala index 32943bca44..de83070ac3 100644 --- a/parsers/shared/src/test/scala/sigmastate/lang/LangTests.scala +++ b/parsers/shared/src/test/scala/sigmastate/lang/LangTests.scala @@ -79,4 +79,10 @@ trait LangTests extends Matchers with NegativeTesting { node }))(tree) } + + /** Execute the given `block` having `version` as both activated and ErgoTree version. */ + def runWithVersion[T](version: Byte)(block: => T): T = { + VersionContext.withVersions(version, version)(block) + } + } diff --git a/sc/shared/src/main/scala/sigma/compiler/phases/SigmaBinder.scala b/sc/shared/src/main/scala/sigma/compiler/phases/SigmaBinder.scala index af5be938be..d4943ef892 100644 --- a/sc/shared/src/main/scala/sigma/compiler/phases/SigmaBinder.scala +++ b/sc/shared/src/main/scala/sigma/compiler/phases/SigmaBinder.scala @@ -105,6 +105,9 @@ class SigmaBinder(env: ScriptEnv, builder: SigmaBuilder, case a @ Apply(PKFunc.symNoType, args) => Some(PKFunc.irInfo.irBuilder(PKFunc.sym, args).withPropagatedSrcCtx(a.sourceContext)) + case a @ Apply(predefFuncRegistry.SerializeFunc.symNoType, args) => + Some(predefFuncRegistry.SerializeFunc.irInfo.irBuilder(PKFunc.sym, args).withPropagatedSrcCtx(a.sourceContext)) + case sel @ Select(obj, "isEmpty", _) => Some(mkLogicalNot(mkSelect(obj, "isDefined").asBoolValue).withPropagatedSrcCtx(sel.sourceContext)) diff --git a/sc/shared/src/main/scala/sigma/compiler/phases/SigmaTyper.scala b/sc/shared/src/main/scala/sigma/compiler/phases/SigmaTyper.scala index 764d2b1eb7..f9b52fe061 100644 --- a/sc/shared/src/main/scala/sigma/compiler/phases/SigmaTyper.scala +++ b/sc/shared/src/main/scala/sigma/compiler/phases/SigmaTyper.scala @@ -511,6 +511,7 @@ class SigmaTyper(val builder: SigmaBuilder, case v: SigmaBoolean => v case v: Upcast[_, _] => v case v @ Select(_, _, Some(_)) => v + case v @ MethodCall(_, _, _, _) => v case v => error(s"Don't know how to assignType($v)", v.sourceContext) }).ensuring(v => v.tpe != NoType, diff --git a/sc/shared/src/test/scala/sigmastate/lang/SigmaBinderTest.scala b/sc/shared/src/test/scala/sigmastate/lang/SigmaBinderTest.scala index b4b4ad20cd..54bd89c9c2 100644 --- a/sc/shared/src/test/scala/sigmastate/lang/SigmaBinderTest.scala +++ b/sc/shared/src/test/scala/sigmastate/lang/SigmaBinderTest.scala @@ -10,10 +10,12 @@ import sigma.ast.syntax.SValue import sigmastate._ import sigmastate.interpreter.Interpreter.ScriptEnv import SigmaPredef.PredefinedFuncRegistry +import sigma.VersionContext import sigma.ast.syntax._ import sigma.compiler.phases.SigmaBinder import sigma.eval.SigmaDsl import sigma.exceptions.BinderException +import sigmastate.helpers.SigmaPPrint class SigmaBinderTest extends AnyPropSpec with ScalaCheckPropertyChecks with Matchers with LangTests { import StdSigmaBuilder._ @@ -29,6 +31,14 @@ class SigmaBinderTest extends AnyPropSpec with ScalaCheckPropertyChecks with Mat res } + def checkBound(env: ScriptEnv, x: String, expected: SValue) = { + val bound = bind(env, x) + if (expected != bound) { + SigmaPPrint.pprintln(bound, width = 100) + } + bound shouldBe expected + } + private def fail(env: ScriptEnv, x: String, expectedLine: Int, expectedCol: Int): Unit = { val builder = TransformingSigmaBuilder val ast = SigmaParser(x).get.value @@ -203,4 +213,15 @@ class SigmaBinderTest extends AnyPropSpec with ScalaCheckPropertyChecks with Mat e.source shouldBe Some(SourceContext(2, 5, "val x = 10")) } + property("predefined `serialize` should be transformed to MethodCall") { + runWithVersion(VersionContext.V6SoftForkVersion) { + checkBound(env, "serialize(1)", + MethodCall.typed[Value[SCollection[SByte.type]]]( + Global, + SGlobalMethods.getMethodByName("serialize").withConcreteTypes(Map(STypeVar("T") -> SInt)), + Array(IntConstant(1)), + Map() + )) + } + } } diff --git a/sc/shared/src/test/scala/sigmastate/lang/SigmaTyperTest.scala b/sc/shared/src/test/scala/sigmastate/lang/SigmaTyperTest.scala index 6b93b098ea..2c3bd44d39 100644 --- a/sc/shared/src/test/scala/sigmastate/lang/SigmaTyperTest.scala +++ b/sc/shared/src/test/scala/sigmastate/lang/SigmaTyperTest.scala @@ -5,7 +5,7 @@ import org.ergoplatform._ import org.scalatest.matchers.should.Matchers import org.scalatest.propspec.AnyPropSpec import org.scalatestplus.scalacheck.ScalaCheckPropertyChecks -import sigma.Colls +import sigma.{Colls, VersionContext} import sigma.ast.SCollection._ import sigma.ast._ import sigma.ast.syntax.{SValue, SigmaPropValue, SigmaPropValueOps} @@ -21,6 +21,8 @@ import sigma.serialization.generators.ObjectGenerators import sigma.ast.Select import sigma.compiler.phases.{SigmaBinder, SigmaTyper} import sigma.exceptions.TyperException +import sigmastate.exceptions.MethodNotFound +import sigmastate.helpers.SigmaPPrint class SigmaTyperTest extends AnyPropSpec with ScalaCheckPropertyChecks with Matchers with LangTests with ObjectGenerators { @@ -39,7 +41,12 @@ class SigmaTyperTest extends AnyPropSpec val typer = new SigmaTyper(builder, predefinedFuncRegistry, typeEnv, lowerMethodCalls = true) val typed = typer.typecheck(bound) assertSrcCtxForAllNodes(typed) - if (expected != null) typed shouldBe expected + if (expected != null) { + if (expected != typed) { + SigmaPPrint.pprintln(typed, width = 100) + } + typed shouldBe expected + } typed.tpe } catch { case e: Exception => throw e @@ -663,4 +670,36 @@ class SigmaTyperTest extends AnyPropSpec ) typecheck(customEnv, "substConstants(scriptBytes, positions, newVals)") shouldBe SByteArray } + + property("Global.serialize") { + runWithVersion(VersionContext.V6SoftForkVersion) { + typecheck(env, "Global.serialize(1)", + MethodCall.typed[Value[SCollection[SByte.type]]]( + Global, + SGlobalMethods.getMethodByName("serialize").withConcreteTypes(Map(STypeVar("T") -> SInt)), + Array(IntConstant(1)), + Map() + )) shouldBe SByteArray + } + + runWithVersion((VersionContext.V6SoftForkVersion - 1).toByte) { + assertExceptionThrown( + typecheck(env, "Global.serialize(1)"), + exceptionLike[MethodNotFound]("Cannot find method 'serialize' in in the object Global") + ) + } + } + + property("predefined serialize") { + runWithVersion(VersionContext.V6SoftForkVersion) { + typecheck(env, "serialize((1, 2L))", + expected = MethodCall.typed[Value[SCollection[SByte.type]]]( + Global, + SGlobalMethods.getMethodByName("serialize").withConcreteTypes(Map(STypeVar("T") -> SPair(SInt, SLong))), + Array(Tuple(Vector(IntConstant(1), LongConstant(2L)))), + Map() + )) shouldBe SByteArray + } + } + } From f7beab4a1d7f8d46b26e4e5e41bb0775dc8fd525 Mon Sep 17 00:00:00 2001 From: Alexander Slesarenko Date: Fri, 17 May 2024 17:43:48 +0100 Subject: [PATCH 088/314] v6.0-serialize: refactor SigmaDslSpecification towards LanguageSpecifications --- .../sigma/LanguageSpecificationBase.scala | 126 +++++++++++++++++ ...on.scala => LanguageSpecificationV5.scala} | 133 ++---------------- .../scala/sigma/LanguageSpecificationV6.scala | 24 ++++ 3 files changed, 163 insertions(+), 120 deletions(-) create mode 100644 sc/shared/src/test/scala/sigma/LanguageSpecificationBase.scala rename sc/shared/src/test/scala/sigma/{SigmaDslSpecification.scala => LanguageSpecificationV5.scala} (98%) create mode 100644 sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala diff --git a/sc/shared/src/test/scala/sigma/LanguageSpecificationBase.scala b/sc/shared/src/test/scala/sigma/LanguageSpecificationBase.scala new file mode 100644 index 0000000000..2bb44fc910 --- /dev/null +++ b/sc/shared/src/test/scala/sigma/LanguageSpecificationBase.scala @@ -0,0 +1,126 @@ +package sigma + +import org.scalatest.BeforeAndAfterAll +import sigma.ast.JitCost +import sigma.eval.{EvalSettings, Profiler} +import sigmastate.CompilerCrossVersionProps +import sigmastate.interpreter.CErgoTreeEvaluator +import scala.util.Success + +/** Base class for language test suites (one suite for each language version: 5.0, 6.0, etc.) + * Each suite tests every method of every SigmaDsl type to be equivalent to + * the evaluation of the corresponding ErgoScript operation. + * + * The properties of this suite exercise two interpreters: the current (aka `old` + * interpreter) and the new interpreter for a next soft-fork. After the soft-fork is + * released, the new interpreter becomes current at which point the `old` and `new` + * interpreters in this suite should be equivalent. This change is reflected in this + * suite by commiting changes in expected values. + * The `old` and `new` interpreters are compared like the following: + * 1) for existingFeature the interpreters should be equivalent + * 2) for changedFeature the test cases contain different expected values + * 3) for newFeature the old interpreter should throw and the new interpreter is checked + * against expected values. + * + * This suite can be used for Cost profiling, i.e. measurements of operations times and + * comparing them with cost parameters of the operations. + * + * The following settings should be specified for profiling: + * isMeasureOperationTime = true + * isMeasureScriptTime = true + * isLogEnabled = false + * printTestVectors = false + * costTracingEnabled = false + * isTestRun = true + * perTestWarmUpIters = 1 + * nBenchmarkIters = 1 + */ +abstract class LanguageSpecificationBase extends SigmaDslTesting + with CompilerCrossVersionProps + with BeforeAndAfterAll { suite => + + /** Version of the language (ErgoScript/ErgoTree) which is specified by this suite. */ + def languageVersion: Byte + + /** Use VersionContext so that each property in this suite runs under correct + * parameters. + */ + protected override def testFun_Run(testName: String, testFun: => Any): Unit = { + VersionContext.withVersions(activatedVersionInTests, ergoTreeVersionInTests) { + super.testFun_Run(testName, testFun) + } + } + + implicit override val generatorDrivenConfig: PropertyCheckConfiguration = PropertyCheckConfiguration(minSuccessful = 30) + + val evalSettingsInTests = CErgoTreeEvaluator.DefaultEvalSettings.copy( + isMeasureOperationTime = true, + isMeasureScriptTime = true, + isLogEnabled = false, // don't commit the `true` value (travis log is too high) + printTestVectors = false, // don't commit the `true` value (travis log is too high) + + /** Should always be enabled in tests (and false by default) + * Should be disabled for cost profiling, which case the new costs are not checked. + */ + costTracingEnabled = true, + profilerOpt = Some(CErgoTreeEvaluator.DefaultProfiler), + isTestRun = true + ) + + def warmupSettings(p: Profiler) = evalSettingsInTests.copy( + isLogEnabled = false, + printTestVectors = false, + profilerOpt = Some(p) + ) + + implicit override def evalSettings: EvalSettings = { + warmupProfiler match { + case Some(p) => warmupSettings(p) + case _ => evalSettingsInTests + } + } + + override val perTestWarmUpIters = 0 + + override val nBenchmarkIters = 0 + + override val okRunTestsWithoutMCLowering: Boolean = true + + implicit def IR = createIR() + + def testCases[A, B](cases: Seq[(A, Expected[B])], f: Feature[A, B]) = { + val table = Table(("x", "y"), cases: _*) + forAll(table) { (x, expectedRes) => + val res = f.checkEquality(x) + val resValue = res.map(_._1) + val (expected, expDetailsOpt) = expectedRes.newResults(ergoTreeVersionInTests) + checkResult(resValue, expected.value, failOnTestVectors = true, + "SigmaDslSpecifiction#testCases: compare expected new result with res = f.checkEquality(x)") + res match { + case Success((value, details)) => + details.cost shouldBe JitCost(expected.verificationCost.get) + expDetailsOpt.foreach(expDetails => + if (details.trace != expDetails.trace) { + printCostDetails(f.script, details) + details.trace shouldBe expDetails.trace + } + ) + } + } + } + + override protected def beforeAll(): Unit = { + prepareSamples[BigInt] + prepareSamples[GroupElement] + prepareSamples[AvlTree] + prepareSamples[Box] + prepareSamples[PreHeader] + prepareSamples[Header] + prepareSamples[(BigInt, BigInt)] + prepareSamples[(GroupElement, GroupElement)] + prepareSamples[(AvlTree, AvlTree)] + prepareSamples[(Box, Box)] + prepareSamples[(PreHeader, PreHeader)] + prepareSamples[(Header, Header)] + } +} diff --git a/sc/shared/src/test/scala/sigma/SigmaDslSpecification.scala b/sc/shared/src/test/scala/sigma/LanguageSpecificationV5.scala similarity index 98% rename from sc/shared/src/test/scala/sigma/SigmaDslSpecification.scala rename to sc/shared/src/test/scala/sigma/LanguageSpecificationV5.scala index c820e65e73..eabbf776aa 100644 --- a/sc/shared/src/test/scala/sigma/SigmaDslSpecification.scala +++ b/sc/shared/src/test/scala/sigma/LanguageSpecificationV5.scala @@ -5,31 +5,28 @@ import org.ergoplatform._ import org.ergoplatform.settings.ErgoAlgos import org.scalacheck.Arbitrary._ import org.scalacheck.{Arbitrary, Gen} -import org.scalatest.BeforeAndAfterAll import scorex.crypto.authds.avltree.batch._ import scorex.crypto.authds.{ADKey, ADValue} import scorex.crypto.hash.{Blake2b256, Digest32} import scorex.util.ModifierId import sigma.Extensions.{ArrayOps, CollOps} +import sigma.ast.ErgoTree.{HeaderType, ZeroHeader} import sigma.ast.SCollection._ -import sigma.ast._ import sigma.ast.syntax._ +import sigma.ast.{Apply, MethodCall, PropertyCall, _} +import sigma.data.OrderingOps._ import sigma.data.RType._ import sigma.data._ +import sigma.eval.Extensions.{ByteExt, IntExt, LongExt, ShortExt} +import sigma.eval.{CostDetails, EvalSettings, SigmaDsl, TracedCost} +import sigma.exceptions.InvalidType +import sigma.serialization.ValueCodes.OpCode import sigma.util.Extensions.{BooleanOps, IntOps, LongOps} import sigma.{VersionContext, ast, data, _} -import ErgoTree.{HeaderType, ZeroHeader} -import sigma.eval.{CostDetails, EvalSettings, Profiler, SigmaDsl, TracedCost} -import sigmastate._ import sigmastate.eval.Extensions.AvlTreeOps -import sigma.eval.Extensions.{ByteExt, IntExt, LongExt, ShortExt} -import OrderingOps._ import sigmastate.eval._ import sigmastate.helpers.TestingHelpers._ import sigmastate.interpreter._ -import sigma.ast.{Apply, MethodCall, PropertyCall} -import sigma.exceptions.InvalidType -import sigma.serialization.ValueCodes.OpCode import sigmastate.utils.Extensions._ import sigmastate.utils.Helpers import sigmastate.utils.Helpers._ @@ -38,122 +35,18 @@ import java.math.BigInteger import scala.collection.compat.immutable.ArraySeq import scala.util.{Failure, Success} -/** This suite tests every method of every SigmaDsl type to be equivalent to - * the evaluation of the corresponding ErgoScript operation. - * - * The properties of this suite excercise two interpreters: the current (aka `old` - * interpreter) and the new interpreter for a next soft-fork. After the soft-fork is - * released, the new interpreter becomes current at which point the `old` and `new` - * interpreters in this suite should be equivalent. This change is reflected in this - * suite by commiting changes in expected values. - * The `old` and `new` interpreters are compared like the following: - * 1) for existingFeature the interpreters should be equivalent - * 2) for changedFeature the test cases contain different expected values - * 3) for newFeature the old interpreter should throw and the new interpreter is checked - * against expected values. - * - * This suite can be used for Cost profiling, i.e. measurements of operations times and - * comparing them with cost parameteres of the operations. + +/** This suite tests all operations for v5.0 version of the language. + * The base classes establish the infrastructure for the tests. * - * The following settings should be specified for profiling: - * isMeasureOperationTime = true - * isMeasureScriptTime = true - * isLogEnabled = false - * printTestVectors = false - * costTracingEnabled = false - * isTestRun = true - * perTestWarmUpIters = 1 - * nBenchmarkIters = 1 + * @see SigmaDslSpecificationBase */ -class SigmaDslSpecification extends SigmaDslTesting - with CompilerCrossVersionProps - with BeforeAndAfterAll { suite => - - /** Use VersionContext so that each property in this suite runs under correct - * parameters. - */ - protected override def testFun_Run(testName: String, testFun: => Any): Unit = { - VersionContext.withVersions(activatedVersionInTests, ergoTreeVersionInTests) { - super.testFun_Run(testName, testFun) - } - } - - implicit override val generatorDrivenConfig = PropertyCheckConfiguration(minSuccessful = 30) - - val evalSettingsInTests = CErgoTreeEvaluator.DefaultEvalSettings.copy( - isMeasureOperationTime = true, - isMeasureScriptTime = true, - isLogEnabled = false, // don't commit the `true` value (travis log is too high) - printTestVectors = false, // don't commit the `true` value (travis log is too high) - - /** Should always be enabled in tests (and false by default) - * Should be disabled for cost profiling, which case the new costs are not checked. - */ - costTracingEnabled = true, - - profilerOpt = Some(CErgoTreeEvaluator.DefaultProfiler), - isTestRun = true - ) - - def warmupSettings(p: Profiler) = evalSettingsInTests.copy( - isLogEnabled = false, - printTestVectors = false, - profilerOpt = Some(p) - ) - - implicit override def evalSettings: EvalSettings = { - warmupProfiler match { - case Some(p) => warmupSettings(p) - case _ => evalSettingsInTests - } - } - - override val perTestWarmUpIters = 0 - - override val nBenchmarkIters = 0 - - override val okRunTestsWithoutMCLowering: Boolean = true +class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => - implicit def IR = createIR() - - def testCases[A, B](cases: Seq[(A, Expected[B])], f: Feature[A, B]) = { - val table = Table(("x", "y"), cases:_*) - forAll(table) { (x, expectedRes) => - val res = f.checkEquality(x) - val resValue = res.map(_._1) - val (expected, expDetailsOpt) = expectedRes.newResults(ergoTreeVersionInTests) - checkResult(resValue, expected.value, failOnTestVectors = true, - "SigmaDslSpecifiction#testCases: compare expected new result with res = f.checkEquality(x)") - res match { - case Success((value, details)) => - details.cost shouldBe JitCost(expected.verificationCost.get) - expDetailsOpt.foreach(expDetails => - if (details.trace != expDetails.trace) { - printCostDetails(f.script, details) - details.trace shouldBe expDetails.trace - } - ) - } - } - } + override def languageVersion: Byte = VersionContext.JitActivationVersion import TestData._ - override protected def beforeAll(): Unit = { - prepareSamples[BigInt] - prepareSamples[GroupElement] - prepareSamples[AvlTree] - prepareSamples[Box] - prepareSamples[PreHeader] - prepareSamples[Header] - prepareSamples[(BigInt, BigInt)] - prepareSamples[(GroupElement, GroupElement)] - prepareSamples[(AvlTree, AvlTree)] - prepareSamples[(Box, Box)] - prepareSamples[(PreHeader, PreHeader)] - prepareSamples[(Header, Header)] - } - ///===================================================== /// CostDetails shared among test cases ///----------------------------------------------------- diff --git a/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala b/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala new file mode 100644 index 0000000000..b1db0e0eda --- /dev/null +++ b/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala @@ -0,0 +1,24 @@ +package sigma + +/** This suite tests all operations for v6.0 version of the language. + * The base classes establish the infrastructure for the tests. + * + * @see SigmaDslSpecificationBase + */ +class LanguageSpecificationV6 extends LanguageSpecificationBase { suite => + override def languageVersion: Byte = VersionContext.V6SoftForkVersion + + import TestData._ + +// property("Global.serialize") { +// lazy val toBytes = newFeature( +// (x: Byte) => x.toBytes, +// (x: Byte) => x.toBytes, +// "{ (x: Byte) => x.toBytes }") +// val cases = Seq( +// (0.toByte, Success(Coll(0.toByte))), +// (1.toByte, Success(Coll(1.toByte))) +// ) +// testCases(cases, toBytes) +// } +} From cfd6e7befcee975a6f278d1c460a827d74165ba4 Mon Sep 17 00:00:00 2001 From: Alexander Slesarenko Date: Sun, 19 May 2024 13:16:37 +0100 Subject: [PATCH 089/314] v6.0-serialize: feature tests for Byte an Short --- .../validation/ValidationRules.scala | 17 +++++- .../src/main/scala/sigma/ast/methods.scala | 7 ++- .../sigma/compiler/ir/GraphBuilding.scala | 3 + .../ir/wrappers/sigma/SigmaDslUnit.scala | 1 + .../ir/wrappers/sigma/impl/SigmaDslImpl.scala | 15 +++++ .../scala/sigma/LanguageSpecificationV6.scala | 58 +++++++++++++++---- .../test/scala/sigma/SigmaDslTesting.scala | 52 +++++++++++------ 7 files changed, 122 insertions(+), 31 deletions(-) diff --git a/data/shared/src/main/scala/org/ergoplatform/validation/ValidationRules.scala b/data/shared/src/main/scala/org/ergoplatform/validation/ValidationRules.scala index 9d4de47a99..07fe8db0ee 100644 --- a/data/shared/src/main/scala/org/ergoplatform/validation/ValidationRules.scala +++ b/data/shared/src/main/scala/org/ergoplatform/validation/ValidationRules.scala @@ -155,6 +155,20 @@ object ValidationRules { override protected lazy val settings: SigmaValidationSettings = currentSettings } + object CheckMinimalErgoTreeVersion extends ValidationRule(1016, + "ErgoTree should have at least required version") with SoftForkWhenReplaced { + override protected lazy val settings: SigmaValidationSettings = currentSettings + + final def apply(currentVersion: Byte, minVersion: Byte): Unit = { + checkRule() + if (currentVersion < minVersion) { + throwValidationException( + new SigmaException(s"ErgoTree should have at least $minVersion version, but was $currentVersion"), + Array(currentVersion, minVersion)) + } + } + } + val ruleSpecs: Seq[ValidationRule] = Seq( CheckDeserializedScriptType, CheckDeserializedScriptIsSigmaProp, @@ -171,7 +185,8 @@ object ValidationRules { CheckHeaderSizeBit, CheckCostFuncOperation, CheckPositionLimit, - CheckLoopLevelInCostFunction + CheckLoopLevelInCostFunction, + CheckMinimalErgoTreeVersion ) /** Validation settings that correspond to the current version of the ErgoScript implementation. diff --git a/data/shared/src/main/scala/sigma/ast/methods.scala b/data/shared/src/main/scala/sigma/ast/methods.scala index dd33802b1d..3f27f85e2d 100644 --- a/data/shared/src/main/scala/sigma/ast/methods.scala +++ b/data/shared/src/main/scala/sigma/ast/methods.scala @@ -1,6 +1,7 @@ package sigma.ast import org.ergoplatform._ +import org.ergoplatform.validation.ValidationRules.CheckMinimalErgoTreeVersion import org.ergoplatform.validation._ import sigma._ import sigma.ast.SCollection.{SBooleanArray, SBoxArray, SByteArray, SByteArray2, SHeaderArray} @@ -1530,10 +1531,12 @@ case object SGlobalMethods extends MonoTypeMethods { * Called via reflection based on naming convention. * @see SMethod.evalMethod */ - def serialize_eval(mc: MethodCall, G: SigmaDslBuilder, value: Any, tpe: RType[Any]) + def serialize_eval(mc: MethodCall, G: SigmaDslBuilder, value: SType#WrappedType) (implicit E: ErgoTreeEvaluator): Coll[Byte] = { // TODO v6.0: accumulate cost - G.serialize(value)(tpe) + CheckMinimalErgoTreeVersion(E.context.currentErgoTreeVersion, VersionContext.V6SoftForkVersion) + val t = Evaluation.stypeToRType(mc.args(0).tpe) + G.serialize(value)(t) } protected override def getMethods() = super.getMethods() ++ { diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/GraphBuilding.scala b/sc/shared/src/main/scala/sigma/compiler/ir/GraphBuilding.scala index 7c7b80d39a..a6a244778e 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/GraphBuilding.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/GraphBuilding.scala @@ -1146,6 +1146,9 @@ trait GraphBuilding extends Base with DefRewriting { IR: IRContext => val c1 = asRep[Coll[Byte]](argsV(0)) val c2 = asRep[Coll[Byte]](argsV(1)) g.xor(c1, c2) + case SGlobalMethods.serializeMethod.name => + val value = asRep[Any](argsV(0)) + g.serialize(value) case _ => throwError } case _ => throwError diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/SigmaDslUnit.scala b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/SigmaDslUnit.scala index 2a6a341686..d7e574c68c 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/SigmaDslUnit.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/SigmaDslUnit.scala @@ -114,6 +114,7 @@ import scalan._ /** This method will be used in v6.0 to handle CreateAvlTree operation in GraphBuilding */ def avlTree(operationFlags: Ref[Byte], digest: Ref[Coll[Byte]], keyLength: Ref[Int], valueLengthOpt: Ref[WOption[Int]]): Ref[AvlTree]; def xor(l: Ref[Coll[Byte]], r: Ref[Coll[Byte]]): Ref[Coll[Byte]] + def serialize[T](value: Ref[T]): Ref[Coll[Byte]] }; trait CostModelCompanion; trait BigIntCompanion; diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/SigmaDslImpl.scala b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/SigmaDslImpl.scala index c113cb7de3..9cd524149d 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/SigmaDslImpl.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/SigmaDslImpl.scala @@ -1945,6 +1945,14 @@ object SigmaDslBuilder extends EntityObject("SigmaDslBuilder") { Array[AnyRef](l, r), true, false, element[Coll[Byte]])) } + + def serialize[T](value: Ref[T]): Ref[Coll[Byte]] = { + asRep[Coll[Byte]](mkMethodCall(self, + SigmaDslBuilderClass.getMethod("serialize", classOf[Sym]), + Array[AnyRef](value), + true, true, element[Coll[Byte]])) + } + } implicit object LiftableSigmaDslBuilder @@ -2104,6 +2112,13 @@ object SigmaDslBuilder extends EntityObject("SigmaDslBuilder") { Array[AnyRef](l, r), true, true, element[Coll[Byte]])) } + + def serialize[T](value: Ref[T]): Ref[Coll[Byte]] = { + asRep[Coll[Byte]](mkMethodCall(source, + SigmaDslBuilderClass.getMethod("serialize", classOf[Sym]), + Array[AnyRef](value), + true, true, element[Coll[Byte]])) + } } // entityUnref: single unref method for each type family diff --git a/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala b/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala index b1db0e0eda..16b8fffbf1 100644 --- a/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala +++ b/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala @@ -1,5 +1,11 @@ package sigma +import sigma.ast.{FuncValue, Global, MethodCall, SByte, SCollection, SGlobalMethods, STypeVar, ValUse, Value} +import sigma.data.RType +import sigma.eval.SigmaDsl + +import scala.util.Success + /** This suite tests all operations for v6.0 version of the language. * The base classes establish the infrastructure for the tests. * @@ -10,15 +16,45 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite => import TestData._ -// property("Global.serialize") { -// lazy val toBytes = newFeature( -// (x: Byte) => x.toBytes, -// (x: Byte) => x.toBytes, -// "{ (x: Byte) => x.toBytes }") -// val cases = Seq( -// (0.toByte, Success(Coll(0.toByte))), -// (1.toByte, Success(Coll(1.toByte))) -// ) -// testCases(cases, toBytes) -// } + def mkSerializeFeature[A: RType]: Feature[A, Coll[Byte]] = { + val tA = RType[A] + val tpe = Evaluation.rtypeToSType(tA) + newFeature( + (x: A) => SigmaDsl.serialize(x), + s"{ (x: ${tA.name}) => serialize(x) }", + expectedExpr = FuncValue( + Array((1, tpe)), + MethodCall( + Global, + SGlobalMethods.serializeMethod.withConcreteTypes(Map(STypeVar("T") -> tpe)), + Array(ValUse(1, tpe)), + Map() + ) + ), + sinceVersion = VersionContext.V6SoftForkVersion) + } + + property("Global.serialize[Byte]") { + lazy val serializeByte = mkSerializeFeature[Byte] + val cases = Seq( + (-128.toByte, Success(Coll(-128.toByte))), + (-1.toByte, Success(Coll(-1.toByte))), + (0.toByte, Success(Coll(0.toByte))), + (1.toByte, Success(Coll(1.toByte))), + (127.toByte, Success(Coll(127.toByte))) + ) + testCases(cases, serializeByte) + } + + property("Global.serialize[Short]") { + lazy val serializeShort = mkSerializeFeature[Short] + val cases = Seq( + (Short.MinValue, Success(Coll[Byte](0xFF.toByte, 0xFF.toByte, 0x03.toByte))), + (-1.toShort, Success(Coll(1.toByte))), + (0.toShort, Success(Coll(0.toByte))), + (1.toShort, Success(Coll(2.toByte))), + (Short.MaxValue, Success(Coll(-2.toByte, -1.toByte, 3.toByte))) + ) + testCases(cases, serializeShort) + } } diff --git a/sc/shared/src/test/scala/sigma/SigmaDslTesting.scala b/sc/shared/src/test/scala/sigma/SigmaDslTesting.scala index 31e873699b..d776238011 100644 --- a/sc/shared/src/test/scala/sigma/SigmaDslTesting.scala +++ b/sc/shared/src/test/scala/sigma/SigmaDslTesting.scala @@ -177,13 +177,13 @@ class SigmaDslTesting extends AnyPropSpec } /** v3 and v4 implementation*/ - private var _oldF: CompiledFunc[A, B] = _ + private var _oldF: Try[CompiledFunc[A, B]] = _ def oldF: CompiledFunc[A, B] = { if (_oldF == null) { - _oldF = oldImpl() - checkExpectedExprIn(_oldF) + _oldF = Try(oldImpl()) + _oldF.foreach(cf => checkExpectedExprIn(cf)) } - _oldF + _oldF.getOrThrow } /** v5 implementation*/ @@ -833,8 +833,17 @@ class SigmaDslTesting extends AnyPropSpec * This in not yet implemented and will be finished in v6.0. * In v5.0 is only checks that some features are NOT implemented, i.e. work for * negative tests. + * + * @param sinceVersion language version (protocol) when the feature is introduced, see + * [[VersionContext]] + * @param script the script to be tested against semantic function + * @param scalaFuncNew semantic function which defines expected behavior of the given script + * @param expectedExpr expected ErgoTree expression which corresponds to the given script + * @param printExpectedExpr if true, print the test vector for expectedExpr when it is None + * @param logScript if true, log scripts to console */ case class NewFeature[A, B]( + sinceVersion: Byte, script: String, override val scalaFuncNew: A => B, expectedExpr: Option[SValue], @@ -842,25 +851,30 @@ class SigmaDslTesting extends AnyPropSpec logScript: Boolean = LogScriptDefault )(implicit IR: IRContext, override val evalSettings: EvalSettings, val tA: RType[A], val tB: RType[B]) extends Feature[A, B] { + + def isFeatureShouldWork: Boolean = + activatedVersionInTests >= sinceVersion && ergoTreeVersionInTests >= sinceVersion + override def scalaFunc: A => B = { x => sys.error(s"Semantic Scala function is not defined for old implementation: $this") } implicit val cs = compilerSettingsInTests - /** in v5.x the old and the new interpreters are the same */ + /** Starting from v5.x the old and the new interpreters are the same */ val oldImpl = () => funcJit[A, B](script) - val newImpl = oldImpl // funcJit[A, B](script) // TODO v6.0: use actual new implementation here (https://github.com/ScorexFoundation/sigmastate-interpreter/issues/910) + val newImpl = oldImpl - /** In v5.x this method just checks the old implementations fails on the new feature. */ + /** Check the new implementation works equal to the semantic function. + * This method also checks the old implementations fails on the new feature. + */ override def checkEquality(input: A, logInputOutput: Boolean = false): Try[(B, CostDetails)] = { - val oldRes = Try(oldF(input)) - oldRes.isFailure shouldBe true - if (!(newImpl eq oldImpl)) { - val newRes = VersionContext.withVersions(activatedVersionInTests, ergoTreeVersionInTests) { - checkEq(scalaFuncNew)(newF)(input) - } + if (this.isFeatureShouldWork) { + checkEq(scalaFuncNew)(newF)(input) + } else { + val oldRes = Try(oldF(input)) + oldRes.isFailure shouldBe true + oldRes } - oldRes } override def checkExpected(input: A, expected: Expected[B]): Unit = { @@ -880,7 +894,10 @@ class SigmaDslTesting extends AnyPropSpec printTestCases: Boolean, failOnTestVectors: Boolean): Unit = { val res = checkEquality(input, printTestCases).map(_._1) - res.isFailure shouldBe true + if (this.isFeatureShouldWork) { + res shouldBe expectedResult + } else + res.isFailure shouldBe true Try(scalaFuncNew(input)) shouldBe expectedResult } @@ -1045,6 +1062,7 @@ class SigmaDslTesting extends AnyPropSpec /** Describes a NEW language feature which must NOT be supported in v4 and * must BE supported in v5 of the language. * + * @param sinceVersion language version (protocol) when the feature is introduced, see [[VersionContext]] * @param scalaFunc semantic function which defines expected behavior of the given script * @param script the script to be tested against semantic function * @param expectedExpr expected ErgoTree expression which corresponds to the given script @@ -1052,9 +1070,9 @@ class SigmaDslTesting extends AnyPropSpec * various ways */ def newFeature[A: RType, B: RType] - (scalaFunc: A => B, script: String, expectedExpr: SValue = null) + (scalaFunc: A => B, script: String, expectedExpr: SValue = null, sinceVersion: Byte = VersionContext.JitActivationVersion) (implicit IR: IRContext, es: EvalSettings): Feature[A, B] = { - NewFeature(script, scalaFunc, Option(expectedExpr)) + NewFeature(sinceVersion, script, scalaFunc, Option(expectedExpr)) } val contextGen: Gen[Context] = ergoLikeContextGen.map(c => c.toSigmaContext()) From 4fb3daa5e5ad4f83e5f143c85499780f9b83e169 Mon Sep 17 00:00:00 2001 From: Alexander Slesarenko Date: Sun, 19 May 2024 16:21:50 +0100 Subject: [PATCH 090/314] v6.0-serialize: all new features move to LanguageSpecificationV6 --- .../scala/sigmastate/CrossVersionProps.scala | 2 - .../scala/sigma/LanguageSpecificationV5.scala | 225 ------------ .../scala/sigma/LanguageSpecificationV6.scala | 330 +++++++++++++++++- .../test/scala/sigma/SigmaDslTesting.scala | 17 +- .../CompilerCrossVersionProps.scala | 11 +- 5 files changed, 343 insertions(+), 242 deletions(-) diff --git a/interpreter/shared/src/test/scala/sigmastate/CrossVersionProps.scala b/interpreter/shared/src/test/scala/sigmastate/CrossVersionProps.scala index 87101a1f71..e55b874dc3 100644 --- a/interpreter/shared/src/test/scala/sigmastate/CrossVersionProps.scala +++ b/interpreter/shared/src/test/scala/sigmastate/CrossVersionProps.scala @@ -31,9 +31,7 @@ trait CrossVersionProps extends AnyPropSpecLike with TestsBase { System.gc() } forEachScriptAndErgoTreeVersion(activatedVersions, ergoTreeVersions) { - VersionContext.withVersions(activatedVersionInTests, ergoTreeVersionInTests) { testFun_Run(testName, testFun) - } } } } diff --git a/sc/shared/src/test/scala/sigma/LanguageSpecificationV5.scala b/sc/shared/src/test/scala/sigma/LanguageSpecificationV5.scala index eabbf776aa..700b48fd13 100644 --- a/sc/shared/src/test/scala/sigma/LanguageSpecificationV5.scala +++ b/sc/shared/src/test/scala/sigma/LanguageSpecificationV5.scala @@ -125,17 +125,6 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => /// Boolean type operations ///----------------------------------------------------- - property("Boolean methods equivalence") { - val toByte = newFeature((x: Boolean) => x.toByte, "{ (x: Boolean) => x.toByte }") - - val cases = Seq( - (true, Success(1.toByte)), - (false, Success(0.toByte)) - ) - - testCases(cases, toByte) - } - property("BinXor(logical XOR) equivalence") { val binXor = existingFeature((x: (Boolean, Boolean)) => x._1 ^ x._2, "{ (x: (Boolean, Boolean)) => x._1 ^ x._2 }", @@ -950,31 +939,6 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => swapArgs(LE_cases, cost = 1768, newCostDetails = binaryRelationCostDetails(GE, SByte)), ">=", GE.apply)(_ >= _) } - - property("Byte methods equivalence (new features)") { - lazy val toBytes = newFeature((x: Byte) => x.toBytes, "{ (x: Byte) => x.toBytes }") - lazy val toAbs = newFeature((x: Byte) => x.toAbs, "{ (x: Byte) => x.toAbs }") - lazy val compareTo = newFeature( - (x: (Byte, Byte)) => x._1.compareTo(x._2), - "{ (x: (Byte, Byte)) => x._1.compareTo(x._2) }") - - lazy val bitOr = newFeature( - { (x: (Byte, Byte)) => (x._1 | x._2).toByteExact }, - "{ (x: (Byte, Byte)) => (x._1 | x._2).toByteExact }") - - lazy val bitAnd = newFeature( - { (x: (Byte, Byte)) => (x._1 & x._2).toByteExact }, - "{ (x: (Byte, Byte)) => (x._1 & x._2).toByteExact }") - - forAll { x: Byte => - Seq(toBytes, toAbs).foreach(f => f.checkEquality(x)) - } - - forAll { x: (Byte, Byte) => - Seq(compareTo, bitOr, bitAnd).foreach(_.checkEquality(x)) - } - } - property("Short methods equivalence") { SShort.upcast(0.toShort) shouldBe 0.toShort // boundary test case SShort.downcast(0.toShort) shouldBe 0.toShort // boundary test case @@ -1255,29 +1219,6 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => ">=", GE.apply)(_ >= _) } - property("Short methods equivalence (new features)") { - lazy val toBytes = newFeature((x: Short) => x.toBytes, "{ (x: Short) => x.toBytes }") - lazy val toAbs = newFeature((x: Short) => x.toAbs, "{ (x: Short) => x.toAbs }") - - lazy val compareTo = newFeature((x: (Short, Short)) => x._1.compareTo(x._2), - "{ (x: (Short, Short)) => x._1.compareTo(x._2) }") - - lazy val bitOr = newFeature( - { (x: (Short, Short)) => (x._1 | x._2).toShortExact }, - "{ (x: (Short, Short)) => x._1 | x._2 }") - - lazy val bitAnd = newFeature( - { (x: (Short, Short)) => (x._1 & x._2).toShortExact }, - "{ (x: (Short, Short)) => x._1 & x._2 }") - - forAll { x: Short => - Seq(toBytes, toAbs).foreach(_.checkEquality(x)) - } - forAll { x: (Short, Short) => - Seq(compareTo, bitOr, bitAnd).foreach(_.checkEquality(x)) - } - } - property("Int methods equivalence") { SInt.upcast(0) shouldBe 0 // boundary test case SInt.downcast(0) shouldBe 0 // boundary test case @@ -1558,28 +1499,6 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => ">=", GE.apply)(_ >= _) } - property("Int methods equivalence (new features)") { - lazy val toBytes = newFeature((x: Int) => x.toBytes, "{ (x: Int) => x.toBytes }") - lazy val toAbs = newFeature((x: Int) => x.toAbs, "{ (x: Int) => x.toAbs }") - lazy val compareTo = newFeature((x: (Int, Int)) => x._1.compareTo(x._2), - "{ (x: (Int, Int)) => x._1.compareTo(x._2) }") - - lazy val bitOr = newFeature( - { (x: (Int, Int)) => x._1 | x._2 }, - "{ (x: (Int, Int)) => x._1 | x._2 }") - - lazy val bitAnd = newFeature( - { (x: (Int, Int)) => x._1 & x._2 }, - "{ (x: (Int, Int)) => x._1 & x._2 }") - - forAll { x: Int => - Seq(toBytes, toAbs).foreach(_.checkEquality(x)) - } - forAll { x: (Int, Int) => - Seq(compareTo, bitOr, bitAnd).foreach(_.checkEquality(x)) - } - } - property("Long downcast and upcast identity") { forAll { x: Long => SLong.upcast(x) shouldBe x // boundary test case @@ -1877,28 +1796,6 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => ">=", GE.apply)(_ >= _) } - property("Long methods equivalence (new features)") { - lazy val toBytes = newFeature((x: Long) => x.toBytes, "{ (x: Long) => x.toBytes }") - lazy val toAbs = newFeature((x: Long) => x.toAbs, "{ (x: Long) => x.toAbs }") - lazy val compareTo = newFeature((x: (Long, Long)) => x._1.compareTo(x._2), - "{ (x: (Long, Long)) => x._1.compareTo(x._2) }") - - lazy val bitOr = newFeature( - { (x: (Long, Long)) => x._1 | x._2 }, - "{ (x: (Long, Long)) => x._1 | x._2 }") - - lazy val bitAnd = newFeature( - { (x: (Long, Long)) => x._1 & x._2 }, - "{ (x: (Long, Long)) => x._1 & x._2 }") - - forAll { x: Long => - Seq(toBytes, toAbs).foreach(_.checkEquality(x)) - } - forAll { x: (Long, Long) => - Seq(compareTo, bitOr, bitAnd).foreach(_.checkEquality(x)) - } - } - property("BigInt methods equivalence") { verifyCases( { @@ -2157,59 +2054,6 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => ">=", GE.apply)(o.gteq(_, _)) } - property("BigInt methods equivalence (new features)") { - // TODO v6.0: the behavior of `upcast` for BigInt is different from all other Numeric types (see https://github.com/ScorexFoundation/sigmastate-interpreter/issues/877) - // The `Upcast(bigInt, SBigInt)` node is never produced by ErgoScript compiler, but is still valid ErgoTree. - // It makes sense to fix this inconsistency as part of upcoming forks - assertExceptionThrown( - SBigInt.upcast(CBigInt(new BigInteger("0", 16)).asInstanceOf[AnyVal]), - _.getMessage.contains("Cannot upcast value") - ) - - // TODO v6.0: the behavior of `downcast` for BigInt is different from all other Numeric types (see https://github.com/ScorexFoundation/sigmastate-interpreter/issues/877) - // The `Downcast(bigInt, SBigInt)` node is never produced by ErgoScript compiler, but is still valid ErgoTree. - // It makes sense to fix this inconsistency as part of HF - assertExceptionThrown( - SBigInt.downcast(CBigInt(new BigInteger("0", 16)).asInstanceOf[AnyVal]), - _.getMessage.contains("Cannot downcast value") - ) - - val toByte = newFeature((x: BigInt) => x.toByte, - "{ (x: BigInt) => x.toByte }", - FuncValue(Vector((1, SBigInt)), Downcast(ValUse(1, SBigInt), SByte))) - - val toShort = newFeature((x: BigInt) => x.toShort, - "{ (x: BigInt) => x.toShort }", - FuncValue(Vector((1, SBigInt)), Downcast(ValUse(1, SBigInt), SShort))) - - val toInt = newFeature((x: BigInt) => x.toInt, - "{ (x: BigInt) => x.toInt }", - FuncValue(Vector((1, SBigInt)), Downcast(ValUse(1, SBigInt), SInt))) - - val toLong = newFeature((x: BigInt) => x.toLong, - "{ (x: BigInt) => x.toLong }", - FuncValue(Vector((1, SBigInt)), Downcast(ValUse(1, SBigInt), SLong))) - - lazy val toBytes = newFeature((x: BigInt) => x.toBytes, "{ (x: BigInt) => x.toBytes }") - lazy val toAbs = newFeature((x: BigInt) => x.toAbs, "{ (x: BigInt) => x.toAbs }") - - lazy val compareTo = newFeature((x: (BigInt, BigInt)) => x._1.compareTo(x._2), - "{ (x: (BigInt, BigInt)) => x._1.compareTo(x._2) }") - - lazy val bitOr = newFeature({ (x: (BigInt, BigInt)) => x._1 | x._2 }, - "{ (x: (BigInt, BigInt)) => x._1 | x._2 }") - - lazy val bitAnd = newFeature({ (x: (BigInt, BigInt)) => x._1 & x._2 }, - "{ (x: (BigInt, BigInt)) => x._1 & x._2 }") - - forAll { x: BigInt => - Seq(toByte, toShort, toInt, toLong, toBytes, toAbs).foreach(_.checkEquality(x)) - } - forAll { x: (BigInt, BigInt) => - Seq(compareTo, bitOr, bitAnd).foreach(_.checkEquality(x)) - } - } - /** Executed a series of test cases of NEQ operation verify using two _different_ * data instances `x` and `y`. * @param cost the expected cost of `verify` (the same for all cases) @@ -3944,16 +3788,6 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => ))) } - property("Box properties equivalence (new features)") { - // TODO v6.0: related to https://github.com/ScorexFoundation/sigmastate-interpreter/issues/416 - val getReg = newFeature((x: Box) => x.getReg[Int](1).get, - "{ (x: Box) => x.getReg[Int](1).get }") - - forAll { box: Box => - Seq(getReg).foreach(_.checkEquality(box)) - } - } - property("Conditional access to registers") { def boxWithRegisters(regs: AdditionalRegisters): Box = { SigmaDsl.Box(testBox(20, TrueTree, 0, Seq(), regs)) @@ -7531,36 +7365,6 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => preGeneratedSamples = Some(samples)) } - // TODO v6.0 (3h): https://github.com/ScorexFoundation/sigmastate-interpreter/issues/479 - property("Coll find method equivalence") { - val find = newFeature((x: Coll[Int]) => x.find({ (v: Int) => v > 0 }), - "{ (x: Coll[Int]) => x.find({ (v: Int) => v > 0} ) }") - forAll { x: Coll[Int] => - find.checkEquality(x) - } - } - - // TODO v6.0 (3h): https://github.com/ScorexFoundation/sigmastate-interpreter/issues/418 - property("Coll bitwise methods equivalence") { - val shiftRight = newFeature( - { (x: Coll[Boolean]) => - if (x.size > 2) x.slice(0, x.size - 2) else Colls.emptyColl[Boolean] - }, - "{ (x: Coll[Boolean]) => x >> 2 }") - forAll { x: Array[Boolean] => - shiftRight.checkEquality(Colls.fromArray(x)) - } - } - - // TODO v6.0 (3h): https://github.com/ScorexFoundation/sigmastate-interpreter/issues/479 - property("Coll diff methods equivalence") { - val diff = newFeature((x: (Coll[Int], Coll[Int])) => x._1.diff(x._2), - "{ (x: (Coll[Int], Coll[Int])) => x._1.diff(x._2) }") - forAll { (x: Coll[Int], y: Coll[Int]) => - diff.checkEquality((x, y)) - } - } - property("Coll fold method equivalence") { val n = ExactNumeric.IntIsExactNumeric val costDetails1 = TracedCost( @@ -8972,17 +8776,6 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => ) )) } - // TODO v6.0: implement Option.fold (see https://github.com/ScorexFoundation/sigmastate-interpreter/issues/479) - property("Option new methods") { - val n = ExactNumeric.LongIsExactNumeric - val fold = newFeature({ (x: Option[Long]) => x.fold(5.toLong)( (v: Long) => n.plus(v, 1) ) }, - "{ (x: Option[Long]) => x.fold(5, { (v: Long) => v + 1 }) }") - - forAll { x: Option[Long] => - Seq(fold).map(_.checkEquality(x)) - } - } - property("Option fold workaround method") { val costDetails1 = TracedCost( traceBase ++ Array( @@ -9418,24 +9211,6 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => preGeneratedSamples = Some(Seq())) } - // TODO v6.0 (3h): implement allZK func https://github.com/ScorexFoundation/sigmastate-interpreter/issues/543 - property("allZK equivalence") { - lazy val allZK = newFeature((x: Coll[SigmaProp]) => SigmaDsl.allZK(x), - "{ (x: Coll[SigmaProp]) => allZK(x) }") - forAll { x: Coll[SigmaProp] => - allZK.checkEquality(x) - } - } - - // TODO v6.0 (3h): implement anyZK func https://github.com/ScorexFoundation/sigmastate-interpreter/issues/543 - property("anyZK equivalence") { - lazy val anyZK = newFeature((x: Coll[SigmaProp]) => SigmaDsl.anyZK(x), - "{ (x: Coll[SigmaProp]) => anyZK(x) }") - forAll { x: Coll[SigmaProp] => - anyZK.checkEquality(x) - } - } - property("allOf equivalence") { def costDetails(i: Int) = TracedCost(traceBase :+ ast.SeqCostItem(CompanionDesc(AND), PerItemCost(JitCost(10), JitCost(5), 32), i)) verifyCases( diff --git a/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala b/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala index 16b8fffbf1..20faabe128 100644 --- a/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala +++ b/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala @@ -1,9 +1,12 @@ package sigma -import sigma.ast.{FuncValue, Global, MethodCall, SByte, SCollection, SGlobalMethods, STypeVar, ValUse, Value} -import sigma.data.RType +import sigma.ast.{Downcast, FuncValue, Global, MethodCall, SBigInt, SByte, SGlobalMethods, SInt, SLong, SShort, STypeVar, ValUse} +import sigma.data.{CBigInt, ExactNumeric, RType} import sigma.eval.SigmaDsl +import sigma.util.Extensions.{BooleanOps, ByteOps, IntOps, LongOps} +import sigmastate.exceptions.MethodNotFound +import java.math.BigInteger import scala.util.Success /** This suite tests all operations for v6.0 version of the language. @@ -14,8 +17,6 @@ import scala.util.Success class LanguageSpecificationV6 extends LanguageSpecificationBase { suite => override def languageVersion: Byte = VersionContext.V6SoftForkVersion - import TestData._ - def mkSerializeFeature[A: RType]: Feature[A, Coll[Byte]] = { val tA = RType[A] val tpe = Evaluation.rtypeToSType(tA) @@ -57,4 +58,325 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite => ) testCases(cases, serializeShort) } + + // TODO v6.0: implement serialization roundtrip tests after merge with deserializeTo + + + property("Boolean.toByte") { + val toByte = newFeature((x: Boolean) => x.toByte, "{ (x: Boolean) => x.toByte }", + sinceVersion = VersionContext.V6SoftForkVersion + ) + + val cases = Seq( + (true, Success(1.toByte)), + (false, Success(0.toByte)) + ) + + if (toByte.isSupportedIn(VersionContext.current)) { + // TODO v6.0: implement as part of https://github.com/ScorexFoundation/sigmastate-interpreter/pull/932 + assertExceptionThrown( + testCases(cases, toByte), + rootCauseLike[MethodNotFound]("Cannot find method") + ) + } + else + testCases(cases, toByte) + } + + property("Byte methods equivalence (new features)") { + // TODO v6.0: implement as part of https://github.com/ScorexFoundation/sigmastate-interpreter/issues/474 + if (activatedVersionInTests < VersionContext.V6SoftForkVersion) { + // NOTE, for such versions the new features are not supported + // which is checked below + + lazy val toAbs = newFeature((x: Byte) => x.toAbs, "{ (x: Byte) => x.toAbs }", + sinceVersion = VersionContext.V6SoftForkVersion) + + lazy val compareTo = newFeature( + (x: (Byte, Byte)) => x._1.compareTo(x._2), + "{ (x: (Byte, Byte)) => x._1.compareTo(x._2) }", + sinceVersion = VersionContext.V6SoftForkVersion) + + lazy val bitOr = newFeature( + { (x: (Byte, Byte)) => (x._1 | x._2).toByteExact }, + "{ (x: (Byte, Byte)) => (x._1 | x._2) }", + sinceVersion = VersionContext.V6SoftForkVersion) + + lazy val bitAnd = newFeature( + { (x: (Byte, Byte)) => (x._1 & x._2).toByteExact }, + "{ (x: (Byte, Byte)) => (x._1 & x._2) }", + sinceVersion = VersionContext.V6SoftForkVersion) + + forAll { x: Byte => + Seq(toAbs).foreach(f => f.checkEquality(x)) + } + + forAll { x: (Byte, Byte) => + Seq(compareTo, bitOr, bitAnd).foreach(_.checkEquality(x)) + } + } + } + + // TODO v6.0: enable as part of https://github.com/ScorexFoundation/sigmastate-interpreter/issues/474 + property("Short methods equivalence (new features)") { + if (activatedVersionInTests < VersionContext.V6SoftForkVersion) { + // NOTE, for such versions the new features are not supported + // which is checked below + + lazy val toAbs = newFeature((x: Short) => x.toAbs, "{ (x: Short) => x.toAbs }", + sinceVersion = VersionContext.V6SoftForkVersion) + + lazy val compareTo = newFeature((x: (Short, Short)) => x._1.compareTo(x._2), + "{ (x: (Short, Short)) => x._1.compareTo(x._2) }", + sinceVersion = VersionContext.V6SoftForkVersion) + + lazy val bitOr = newFeature( + { (x: (Short, Short)) => (x._1 | x._2).toShortExact }, + "{ (x: (Short, Short)) => x._1 | x._2 }", + sinceVersion = VersionContext.V6SoftForkVersion) + + lazy val bitAnd = newFeature( + { (x: (Short, Short)) => (x._1 & x._2).toShortExact }, + "{ (x: (Short, Short)) => x._1 & x._2 }", + sinceVersion = VersionContext.V6SoftForkVersion) + + forAll { x: Short => + Seq(toAbs).foreach(_.checkEquality(x)) + } + forAll { x: (Short, Short) => + Seq(compareTo, bitOr, bitAnd).foreach(_.checkEquality(x)) + } + } + } + + property("Int methods equivalence (new features)") { + if (activatedVersionInTests < VersionContext.V6SoftForkVersion) { + // NOTE, for such versions the new features are not supported + // which is checked below + lazy val toAbs = newFeature((x: Int) => x.toAbs, "{ (x: Int) => x.toAbs }", + sinceVersion = VersionContext.V6SoftForkVersion) + lazy val compareTo = newFeature((x: (Int, Int)) => x._1.compareTo(x._2), + "{ (x: (Int, Int)) => x._1.compareTo(x._2) }", + sinceVersion = VersionContext.V6SoftForkVersion) + lazy val bitOr = newFeature( + { (x: (Int, Int)) => x._1 | x._2 }, + "{ (x: (Int, Int)) => x._1 | x._2 }", + sinceVersion = VersionContext.V6SoftForkVersion) + lazy val bitAnd = newFeature( + { (x: (Int, Int)) => x._1 & x._2 }, + "{ (x: (Int, Int)) => x._1 & x._2 }", + sinceVersion = VersionContext.V6SoftForkVersion) + forAll { x: Int => + Seq(toAbs).foreach(_.checkEquality(x)) + } + forAll { x: (Int, Int) => + Seq(compareTo, bitOr, bitAnd).foreach(_.checkEquality(x)) + } + } + } + + property("Long methods equivalence (new features)") { + if (activatedVersionInTests < VersionContext.V6SoftForkVersion) { + // NOTE, for such versions the new features are not supported + // which is checked below + lazy val toAbs = newFeature((x: Long) => x.toAbs, "{ (x: Long) => x.toAbs }", + sinceVersion = VersionContext.V6SoftForkVersion) + lazy val compareTo = newFeature((x: (Long, Long)) => x._1.compareTo(x._2), + "{ (x: (Long, Long)) => x._1.compareTo(x._2) }", + sinceVersion = VersionContext.V6SoftForkVersion) + + lazy val bitOr = newFeature( + { (x: (Long, Long)) => x._1 | x._2 }, + "{ (x: (Long, Long)) => x._1 | x._2 }", + sinceVersion = VersionContext.V6SoftForkVersion) + + lazy val bitAnd = newFeature( + { (x: (Long, Long)) => x._1 & x._2 }, + "{ (x: (Long, Long)) => x._1 & x._2 }", + sinceVersion = VersionContext.V6SoftForkVersion) + + forAll { x: Long => + Seq(toAbs).foreach(_.checkEquality(x)) + } + forAll { x: (Long, Long) => + Seq(compareTo, bitOr, bitAnd).foreach(_.checkEquality(x)) + } + } + + } + + property("BigInt methods equivalence (new features)") { + // TODO v6.0: the behavior of `upcast` for BigInt is different from all other Numeric types (see https://github.com/ScorexFoundation/sigmastate-interpreter/issues/877) + // The `Upcast(bigInt, SBigInt)` node is never produced by ErgoScript compiler, but is still valid ErgoTree. + // It makes sense to fix this inconsistency as part of upcoming forks + assertExceptionThrown( + SBigInt.upcast(CBigInt(new BigInteger("0", 16)).asInstanceOf[AnyVal]), + _.getMessage.contains("Cannot upcast value") + ) + + // TODO v6.0: the behavior of `downcast` for BigInt is different from all other Numeric types (see https://github.com/ScorexFoundation/sigmastate-interpreter/issues/877) + // The `Downcast(bigInt, SBigInt)` node is never produced by ErgoScript compiler, but is still valid ErgoTree. + // It makes sense to fix this inconsistency as part of HF + assertExceptionThrown( + SBigInt.downcast(CBigInt(new BigInteger("0", 16)).asInstanceOf[AnyVal]), + _.getMessage.contains("Cannot downcast value") + ) + + if (activatedVersionInTests < VersionContext.V6SoftForkVersion) { + // NOTE, for such versions the new features are not supported + // which is checked below + val toByte = newFeature((x: BigInt) => x.toByte, + "{ (x: BigInt) => x.toByte }", + FuncValue(Vector((1, SBigInt)), Downcast(ValUse(1, SBigInt), SByte)), + sinceVersion = VersionContext.V6SoftForkVersion) + val toShort = newFeature((x: BigInt) => x.toShort, + "{ (x: BigInt) => x.toShort }", + FuncValue(Vector((1, SBigInt)), Downcast(ValUse(1, SBigInt), SShort)), + sinceVersion = VersionContext.V6SoftForkVersion) + val toInt = newFeature((x: BigInt) => x.toInt, + "{ (x: BigInt) => x.toInt }", + FuncValue(Vector((1, SBigInt)), Downcast(ValUse(1, SBigInt), SInt)), + sinceVersion = VersionContext.V6SoftForkVersion) + val toLong = newFeature((x: BigInt) => x.toLong, + "{ (x: BigInt) => x.toLong }", + FuncValue(Vector((1, SBigInt)), Downcast(ValUse(1, SBigInt), SLong)), + sinceVersion = VersionContext.V6SoftForkVersion) + lazy val toAbs = newFeature((x: BigInt) => x.toAbs, "{ (x: BigInt) => x.toAbs }", + sinceVersion = VersionContext.V6SoftForkVersion) + lazy val compareTo = newFeature((x: (BigInt, BigInt)) => x._1.compareTo(x._2), + "{ (x: (BigInt, BigInt)) => x._1.compareTo(x._2) }", + sinceVersion = VersionContext.V6SoftForkVersion) + lazy val bitOr = newFeature({ (x: (BigInt, BigInt)) => x._1 | x._2 }, + "{ (x: (BigInt, BigInt)) => x._1 | x._2 }", + sinceVersion = VersionContext.V6SoftForkVersion) + lazy val bitAnd = newFeature({ (x: (BigInt, BigInt)) => x._1 & x._2 }, + "{ (x: (BigInt, BigInt)) => x._1 & x._2 }", + sinceVersion = VersionContext.V6SoftForkVersion) + + forAll { x: BigInt => + Seq(toByte, toShort, toInt, toLong, toAbs).foreach(_.checkEquality(x)) + } + forAll { x: (BigInt, BigInt) => + Seq(compareTo, bitOr, bitAnd).foreach(_.checkEquality(x)) + } + } + } + + property("Box properties equivalence (new features)") { + // TODO v6.0: related to https://github.com/ScorexFoundation/sigmastate-interpreter/issues/416 + val getReg = newFeature((x: Box) => x.getReg[Int](1).get, + "{ (x: Box) => x.getReg[Int](1).get }", + sinceVersion = VersionContext.V6SoftForkVersion) + + if (activatedVersionInTests < VersionContext.V6SoftForkVersion) { + // NOTE, for such versions getReg is not supported + // which is checked below + + forAll { box: Box => + Seq(getReg).foreach(_.checkEquality(box)) + } + } + } + + // TODO v6.0 (3h): https://github.com/ScorexFoundation/sigmastate-interpreter/issues/479 + property("Coll find method equivalence") { + val find = newFeature((x: Coll[Int]) => x.find({ (v: Int) => v > 0 }), + "{ (x: Coll[Int]) => x.find({ (v: Int) => v > 0} ) }", + sinceVersion = VersionContext.V6SoftForkVersion) + + if (activatedVersionInTests < VersionContext.V6SoftForkVersion) { + // NOTE, for such versions getReg is not supported + // which is checked below + + forAll { x: Coll[Int] => + find.checkEquality(x) + } + } + } + + // TODO v6.0 (3h): https://github.com/ScorexFoundation/sigmastate-interpreter/issues/418 + property("Coll bitwise methods equivalence") { + val shiftRight = newFeature( + { (x: Coll[Boolean]) => + if (x.size > 2) x.slice(0, x.size - 2) else Colls.emptyColl[Boolean] + }, + "{ (x: Coll[Boolean]) => x >> 2 }", + sinceVersion = VersionContext.V6SoftForkVersion) + + if (activatedVersionInTests < VersionContext.V6SoftForkVersion) { + // NOTE, for such versions getReg is not supported + // which is checked below + + forAll { x: Array[Boolean] => + shiftRight.checkEquality(Colls.fromArray(x)) + } + } + } + + // TODO v6.0 (3h): https://github.com/ScorexFoundation/sigmastate-interpreter/issues/479 + property("Coll diff methods equivalence") { + val diff = newFeature((x: (Coll[Int], Coll[Int])) => x._1.diff(x._2), + "{ (x: (Coll[Int], Coll[Int])) => x._1.diff(x._2) }", + sinceVersion = VersionContext.V6SoftForkVersion) + + if (activatedVersionInTests < VersionContext.V6SoftForkVersion) { + // NOTE, for such versions getReg is not supported + // which is checked below + + forAll { (x: Coll[Int], y: Coll[Int]) => + diff.checkEquality((x, y)) + } + } + } + + // TODO v6.0: implement Option.fold (see https://github.com/ScorexFoundation/sigmastate-interpreter/issues/479) + property("Option new methods") { + val n = ExactNumeric.LongIsExactNumeric + val fold = newFeature({ (x: Option[Long]) => x.fold(5.toLong)( (v: Long) => n.plus(v, 1) ) }, + "{ (x: Option[Long]) => x.fold(5, { (v: Long) => v + 1 }) }", + sinceVersion = VersionContext.V6SoftForkVersion) + + if (activatedVersionInTests < VersionContext.V6SoftForkVersion) { + // NOTE, for such versions getReg is not supported + // which is checked below + + forAll { x: Option[Long] => + Seq(fold).map(_.checkEquality(x)) + } + } + } + + // TODO v6.0 (3h): implement allZK func https://github.com/ScorexFoundation/sigmastate-interpreter/issues/543 + property("allZK equivalence") { + lazy val allZK = newFeature((x: Coll[SigmaProp]) => SigmaDsl.allZK(x), + "{ (x: Coll[SigmaProp]) => allZK(x) }", + sinceVersion = VersionContext.V6SoftForkVersion) + + if (activatedVersionInTests < VersionContext.V6SoftForkVersion) { + // NOTE, for such versions getReg is not supported + // which is checked below + + forAll { x: Coll[SigmaProp] => + allZK.checkEquality(x) + } + } + } + + // TODO v6.0 (3h): implement anyZK func https://github.com/ScorexFoundation/sigmastate-interpreter/issues/543 + property("anyZK equivalence") { + lazy val anyZK = newFeature((x: Coll[SigmaProp]) => SigmaDsl.anyZK(x), + "{ (x: Coll[SigmaProp]) => anyZK(x) }", + sinceVersion = VersionContext.V6SoftForkVersion) + + if (activatedVersionInTests < VersionContext.V6SoftForkVersion) { + // NOTE, for such versions getReg is not supported + // which is checked below + + forAll { x: Coll[SigmaProp] => + anyZK.checkEquality(x) + } + } + } + + } diff --git a/sc/shared/src/test/scala/sigma/SigmaDslTesting.scala b/sc/shared/src/test/scala/sigma/SigmaDslTesting.scala index d776238011..28c9c05fec 100644 --- a/sc/shared/src/test/scala/sigma/SigmaDslTesting.scala +++ b/sc/shared/src/test/scala/sigma/SigmaDslTesting.scala @@ -123,6 +123,9 @@ class SigmaDslTesting extends AnyPropSpec /** Type descriptor for type B. */ def tB: RType[B] + /** Checks if this feature is supported in the given version context. */ + def isSupportedIn(vc: VersionContext): Boolean + /** Script containing this feature. */ def script: String @@ -501,6 +504,8 @@ class SigmaDslTesting extends AnyPropSpec implicit val cs = compilerSettingsInTests + override def isSupportedIn(vc: VersionContext): Boolean = true + /** in v5.x the old and the new interpreters are the same */ override val oldImpl = () => funcJit[A, B](script) override val newImpl = () => funcJit[A, B](script) @@ -671,6 +676,8 @@ class SigmaDslTesting extends AnyPropSpec implicit val cs = compilerSettingsInTests + override def isSupportedIn(vc: VersionContext): Boolean = true + /** Apply given function to the context variable 1 */ private def getApplyExpr(funcValue: SValue) = { val sType = Evaluation.rtypeToSType(RType[A]) @@ -852,8 +859,8 @@ class SigmaDslTesting extends AnyPropSpec )(implicit IR: IRContext, override val evalSettings: EvalSettings, val tA: RType[A], val tB: RType[B]) extends Feature[A, B] { - def isFeatureShouldWork: Boolean = - activatedVersionInTests >= sinceVersion && ergoTreeVersionInTests >= sinceVersion + override def isSupportedIn(vc: VersionContext): Boolean = + vc.activatedVersion >= sinceVersion && vc.ergoTreeVersion >= sinceVersion override def scalaFunc: A => B = { x => sys.error(s"Semantic Scala function is not defined for old implementation: $this") @@ -868,7 +875,7 @@ class SigmaDslTesting extends AnyPropSpec * This method also checks the old implementations fails on the new feature. */ override def checkEquality(input: A, logInputOutput: Boolean = false): Try[(B, CostDetails)] = { - if (this.isFeatureShouldWork) { + if (this.isSupportedIn(VersionContext.current)) { checkEq(scalaFuncNew)(newF)(input) } else { val oldRes = Try(oldF(input)) @@ -894,8 +901,8 @@ class SigmaDslTesting extends AnyPropSpec printTestCases: Boolean, failOnTestVectors: Boolean): Unit = { val res = checkEquality(input, printTestCases).map(_._1) - if (this.isFeatureShouldWork) { - res shouldBe expectedResult + if (this.isSupportedIn(VersionContext.current)) { + res shouldBe expectedResult } else res.isFailure shouldBe true Try(scalaFuncNew(input)) shouldBe expectedResult diff --git a/sc/shared/src/test/scala/sigmastate/CompilerCrossVersionProps.scala b/sc/shared/src/test/scala/sigmastate/CompilerCrossVersionProps.scala index 89d15dd4df..4062f13686 100644 --- a/sc/shared/src/test/scala/sigmastate/CompilerCrossVersionProps.scala +++ b/sc/shared/src/test/scala/sigmastate/CompilerCrossVersionProps.scala @@ -12,12 +12,11 @@ trait CompilerCrossVersionProps extends CrossVersionProps with CompilerTestsBase (implicit pos: Position): Unit = { super.property(testName, testTags:_*)(testFun) - val testName2 = s"${testName}_MCLowering" - super.property2(testName2, testTags:_*) { - if (okRunTestsWithoutMCLowering) { - _lowerMethodCalls.withValue(false) { - testFun_Run(testName2, testFun) - } + if (okRunTestsWithoutMCLowering) { + val testName2 = s"${testName}_MCLowering" + _lowerMethodCalls.withValue(false) { + // run testFun for all versions again, but now with this flag + super.property(testName2, testTags:_*)(testFun) } } } From 553bee8eeace5c90d2e7fd30a73a276b01f66d7b Mon Sep 17 00:00:00 2001 From: Alexander Slesarenko Date: Tue, 21 May 2024 11:18:18 +0200 Subject: [PATCH 091/314] refactor-ir-cake: add ScalaDoc --- .../test/scala/sigmastate/ReflectionGenerator.scala | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/sc/jvm/src/test/scala/sigmastate/ReflectionGenerator.scala b/sc/jvm/src/test/scala/sigmastate/ReflectionGenerator.scala index 324542505e..dd5262e700 100644 --- a/sc/jvm/src/test/scala/sigmastate/ReflectionGenerator.scala +++ b/sc/jvm/src/test/scala/sigmastate/ReflectionGenerator.scala @@ -5,6 +5,17 @@ import sigma.reflection._ import scala.annotation.unused import scala.collection.mutable +/** Generates code for registering classes in the ReflectionData. + * It is not used in the runtime. + * + * The generated invocations of `registerClassEntry`, `mkMethod`, `mkConstructor` may + * require manual adjustments. + * + * It uses [[sigma.reflection.Platform.unknownClasses]] to collect classes which were + * accessed during runtime + * + * @see [[ReflectionData]] + */ object ReflectionGenerator { def normalizeName(name: String): String = { From d09d735b05169e609b8e75c191c493d588373a7c Mon Sep 17 00:00:00 2001 From: Alexander Slesarenko Date: Wed, 22 May 2024 21:50:07 +0200 Subject: [PATCH 092/314] i994-fix-subst-constants: implementation + tests --- .../src/main/scala/sigma/ast/ErgoTree.scala | 5 + .../serialization/ErgoTreeSerializer.scala | 48 ++++- .../sigma/LanguageSpecificationBase.scala | 16 +- .../scala/sigma/LanguageSpecificationV5.scala | 197 +++++++++--------- .../scala/sigma/LanguageSpecificationV6.scala | 88 +++++++- .../test/scala/sigma/SigmaDslTesting.scala | 23 +- 6 files changed, 258 insertions(+), 119 deletions(-) diff --git a/data/shared/src/main/scala/sigma/ast/ErgoTree.scala b/data/shared/src/main/scala/sigma/ast/ErgoTree.scala index 68d69abd91..eae420612e 100644 --- a/data/shared/src/main/scala/sigma/ast/ErgoTree.scala +++ b/data/shared/src/main/scala/sigma/ast/ErgoTree.scala @@ -228,6 +228,11 @@ object ErgoTree { type HeaderType = HeaderType.Type + implicit class HeaderTypeOps(val header: HeaderType) extends AnyVal { + def withVersion(version: Byte): HeaderType = ErgoTree.headerWithVersion(header, version) + def withConstantSegregation: HeaderType = ErgoTree.setConstantSegregation(header) + } + /** Current version of ErgoTree serialization format (aka bite-code language version) */ val VersionFlag: Byte = VersionContext.MaxSupportedScriptVersion diff --git a/data/shared/src/main/scala/sigma/serialization/ErgoTreeSerializer.scala b/data/shared/src/main/scala/sigma/serialization/ErgoTreeSerializer.scala index 43e41f91ff..e7bb46429a 100644 --- a/data/shared/src/main/scala/sigma/serialization/ErgoTreeSerializer.scala +++ b/data/shared/src/main/scala/sigma/serialization/ErgoTreeSerializer.scala @@ -287,6 +287,9 @@ class ErgoTreeSerializer { * allow to use serialized scripts as pre-defined templates. * See [[SubstConstants]] for details. * + * Note, this operation doesn't require (de)serialization of ErgoTree expression, + * thus it is more efficient than serialization roundtrip. + * * @param scriptBytes serialized ErgoTree with ConstantSegregationFlag set to 1. * @param positions zero based indexes in ErgoTree.constants array which * should be replaced with new values @@ -304,21 +307,23 @@ class ErgoTreeSerializer { s"expected positions and newVals to have the same length, got: positions: ${positions.toSeq},\n newVals: ${newVals.toSeq}") val r = SigmaSerializer.startReader(scriptBytes) val (header, _, constants, treeBytes) = deserializeHeaderWithTreeBytes(r) - val w = SigmaSerializer.startWriter() - w.put(header) + val nConstants = constants.length + + val resBytes = if (VersionContext.current.isJitActivated) { + // need to measure the serialized size of the new constants + // by serializing them into a separate writer + val constW = SigmaSerializer.startWriter() - if (VersionContext.current.isJitActivated) { // The following `constants.length` should not be serialized when segregation is off // in the `header`, because in this case there is no `constants` section in the // ErgoTree serialization format. Thus, applying this `substituteConstants` for // non-segregated trees will return non-parsable ErgoTree bytes (when // `constants.length` is put in `w`). if (ErgoTree.isConstantSegregation(header)) { - w.putUInt(constants.length) + constW.putUInt(constants.length) } // The following is optimized O(nConstants + position.length) implementation - val nConstants = constants.length if (nConstants > 0) { val backrefs = getPositionsBackref(positions, nConstants) cfor(0)(_ < nConstants, _ + 1) { i => @@ -326,17 +331,38 @@ class ErgoTreeSerializer { val iPos = backrefs(i) // index to `positions` if (iPos == -1) { // no position => no substitution, serialize original constant - constantSerializer.serialize(c, w) + constantSerializer.serialize(c, constW) } else { - assert(positions(iPos) == i) // INV: backrefs and positions are mutually inverse + require(positions(iPos) == i) // INV: backrefs and positions are mutually inverse val newConst = newVals(iPos) require(c.tpe == newConst.tpe, s"expected new constant to have the same ${c.tpe} tpe, got ${newConst.tpe}") - constantSerializer.serialize(newConst, w) + constantSerializer.serialize(newConst, constW) } } } + + val constBytes = constW.toBytes // nConstants + serialized new constants + + // start composing the resulting tree bytes + val w = SigmaSerializer.startWriter() + w.put(header) // header byte + + if (VersionContext.current.isV6SoftForkActivated) { + // fix in v6.0 to save tree size to respect size bit of the original tree + if (ErgoTree.hasSize(header)) { + val size = constBytes.length + treeBytes.length + w.putUInt(size) // tree size + } + } + + w.putBytes(constBytes) // constants section + w.putBytes(treeBytes) // tree section + w.toBytes } else { + val w = SigmaSerializer.startWriter() + w.put(header) + // for v4.x compatibility we save constants.length here (see the above comment to // understand the consequences) w.putUInt(constants.length) @@ -357,10 +383,12 @@ class ErgoTreeSerializer { case (c, _) => constantSerializer.serialize(c, w) } + + w.putBytes(treeBytes) + w.toBytes } - w.putBytes(treeBytes) - (w.toBytes, constants.length) + (resBytes, nConstants) } } diff --git a/sc/shared/src/test/scala/sigma/LanguageSpecificationBase.scala b/sc/shared/src/test/scala/sigma/LanguageSpecificationBase.scala index 2bb44fc910..26c7d7c8c2 100644 --- a/sc/shared/src/test/scala/sigma/LanguageSpecificationBase.scala +++ b/sc/shared/src/test/scala/sigma/LanguageSpecificationBase.scala @@ -1,10 +1,11 @@ package sigma import org.scalatest.BeforeAndAfterAll -import sigma.ast.JitCost +import sigma.ast.{Apply, FixedCostItem, FuncValue, GetVar, JitCost, OptionGet, ValUse} import sigma.eval.{EvalSettings, Profiler} import sigmastate.CompilerCrossVersionProps import sigmastate.interpreter.CErgoTreeEvaluator + import scala.util.Success /** Base class for language test suites (one suite for each language version: 5.0, 6.0, etc.) @@ -123,4 +124,17 @@ abstract class LanguageSpecificationBase extends SigmaDslTesting prepareSamples[(PreHeader, PreHeader)] prepareSamples[(Header, Header)] } + + ///===================================================== + /// CostDetails shared among test cases + ///----------------------------------------------------- + val traceBase = Array( + FixedCostItem(Apply), + FixedCostItem(FuncValue), + FixedCostItem(GetVar), + FixedCostItem(OptionGet), + FixedCostItem(FuncValue.AddToEnvironmentDesc, FuncValue.AddToEnvironmentDesc_CostKind), + FixedCostItem(ValUse) + ) + } diff --git a/sc/shared/src/test/scala/sigma/LanguageSpecificationV5.scala b/sc/shared/src/test/scala/sigma/LanguageSpecificationV5.scala index 700b48fd13..47e05b9528 100644 --- a/sc/shared/src/test/scala/sigma/LanguageSpecificationV5.scala +++ b/sc/shared/src/test/scala/sigma/LanguageSpecificationV5.scala @@ -47,17 +47,6 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => import TestData._ - ///===================================================== - /// CostDetails shared among test cases - ///----------------------------------------------------- - val traceBase = Array( - FixedCostItem(Apply), - FixedCostItem(FuncValue), - FixedCostItem(GetVar), - FixedCostItem(OptionGet), - FixedCostItem(FuncValue.AddToEnvironmentDesc, FuncValue.AddToEnvironmentDesc_CostKind), - FixedCostItem(ValUse) - ) def upcastCostDetails(tpe: SType) = TracedCost(traceBase :+ TypeBasedCostItem(Upcast, tpe)) def downcastCostDetails(tpe: SType) = TracedCost(traceBase :+ TypeBasedCostItem(Downcast, tpe)) def arithOpsCostDetails(tpe: SType) = CostDetails( @@ -4811,7 +4800,9 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => Seq(0, 1, 2, 3).map(version => version -> res) })) ), - changedFeature({ (x: Context) => x.selfBoxIndex }, + changedFeature( + changedInVersion = VersionContext.JitActivationVersion, + { (x: Context) => x.selfBoxIndex }, { (x: Context) => x.selfBoxIndex }, // see versioning in selfBoxIndex implementation "{ (x: Context) => x.selfBoxIndex }", FuncValue( @@ -5012,6 +5003,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => ) ), changedFeature( + changedInVersion = VersionContext.JitActivationVersion, scalaFunc = { (x: Context) => // this error is expected in v3.x, v4.x throw expectedError @@ -5985,6 +5977,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => ) }, changedFeature( + changedInVersion = VersionContext.JitActivationVersion, (x: Coll[Boolean]) => SigmaDsl.xorOf(x), (x: Coll[Boolean]) => SigmaDsl.xorOf(x), "{ (x: Coll[Boolean]) => xorOf(x) }", @@ -6247,6 +6240,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => ) }, changedFeature( + changedInVersion = VersionContext.JitActivationVersion, (x: (Coll[Byte], Coll[Byte])) => SigmaDsl.xor(x._1, x._2), (x: (Coll[Byte], Coll[Byte])) => SigmaDsl.xor(x._1, x._2), "{ (x: (Coll[Byte], Coll[Byte])) => xor(x._1, x._2) }", @@ -8816,6 +8810,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => (Some(Long.MaxValue) -> Expected(new ArithmeticException("long overflow"))) ), changedFeature( + changedInVersion = VersionContext.JitActivationVersion, scalaFunc = { (x: Option[Long]) => def f(opt: Long): Long = n.plus(opt, 1) if (x.isDefined) f(x.get) @@ -9371,6 +9366,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => ) }, changedFeature( + changedInVersion = VersionContext.JitActivationVersion, { (x: (Coll[Byte], Int)) => SigmaDsl.substConstants(x._1, Coll[Int](x._2), Coll[Any](SigmaDsl.sigmaProp(false))(sigma.AnyType)) }, @@ -9433,103 +9429,104 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => ) ), changedFeature( - { (x: Context) => - throw error - true - }, - { (x: Context) => - val headers = x.headers - val ids = headers.map({ (h: Header) => h.id }) - val parentIds = headers.map({ (h: Header) => h.parentId }) - headers.indices.slice(0, headers.size - 1).forall({ (i: Int) => - val parentId = parentIds(i) - val id = ids(i + 1) - parentId == id - }) - }, - """{ - |(x: Context) => - | val headers = x.headers - | val ids = headers.map({(h: Header) => h.id }) - | val parentIds = headers.map({(h: Header) => h.parentId }) - | headers.indices.slice(0, headers.size - 1).forall({ (i: Int) => - | val parentId = parentIds(i) - | val id = ids(i + 1) - | parentId == id - | }) - |}""".stripMargin, - FuncValue( - Array((1, SContext)), - BlockValue( - Array( - ValDef( - 3, - List(), - MethodCall.typed[Value[SCollection[SHeader.type]]]( - ValUse(1, SContext), - SContextMethods.getMethodByName("headers"), - Vector(), - Map() - ) - ) - ), - ForAll( - Slice( - MethodCall.typed[Value[SCollection[SInt.type]]]( - ValUse(3, SCollectionType(SHeader)), - SCollectionMethods.getMethodByName("indices").withConcreteTypes(Map(STypeVar("IV") -> SHeader)), - Vector(), - Map() - ), - IntConstant(0), - ArithOp( - SizeOf(ValUse(3, SCollectionType(SHeader))), - IntConstant(1), - OpCode @@ (-103.toByte) + changedInVersion = VersionContext.JitActivationVersion, + { (x: Context) => + throw error + true + }, + { (x: Context) => + val headers = x.headers + val ids = headers.map({ (h: Header) => h.id }) + val parentIds = headers.map({ (h: Header) => h.parentId }) + headers.indices.slice(0, headers.size - 1).forall({ (i: Int) => + val parentId = parentIds(i) + val id = ids(i + 1) + parentId == id + }) + }, + """{ + |(x: Context) => + | val headers = x.headers + | val ids = headers.map({(h: Header) => h.id }) + | val parentIds = headers.map({(h: Header) => h.parentId }) + | headers.indices.slice(0, headers.size - 1).forall({ (i: Int) => + | val parentId = parentIds(i) + | val id = ids(i + 1) + | parentId == id + | }) + |}""".stripMargin, + FuncValue( + Array((1, SContext)), + BlockValue( + Array( + ValDef( + 3, + List(), + MethodCall.typed[Value[SCollection[SHeader.type]]]( + ValUse(1, SContext), + SContextMethods.getMethodByName("headers"), + Vector(), + Map() + ) ) ), - FuncValue( - Array((4, SInt)), - EQ( - ByIndex( - MapCollection( - ValUse(3, SCollectionType(SHeader)), - FuncValue( - Array((6, SHeader)), - MethodCall.typed[Value[SCollection[SByte.type]]]( - ValUse(6, SHeader), - SHeaderMethods.getMethodByName("parentId"), - Vector(), - Map() - ) - ) - ), - ValUse(4, SInt), - None + ForAll( + Slice( + MethodCall.typed[Value[SCollection[SInt.type]]]( + ValUse(3, SCollectionType(SHeader)), + SCollectionMethods.getMethodByName("indices").withConcreteTypes(Map(STypeVar("IV") -> SHeader)), + Vector(), + Map() ), - ByIndex( - MapCollection( - ValUse(3, SCollectionType(SHeader)), - FuncValue( - Array((6, SHeader)), - MethodCall.typed[Value[SCollection[SByte.type]]]( - ValUse(6, SHeader), - SHeaderMethods.getMethodByName("id"), - Vector(), - Map() + IntConstant(0), + ArithOp( + SizeOf(ValUse(3, SCollectionType(SHeader))), + IntConstant(1), + OpCode @@ (-103.toByte) + ) + ), + FuncValue( + Array((4, SInt)), + EQ( + ByIndex( + MapCollection( + ValUse(3, SCollectionType(SHeader)), + FuncValue( + Array((6, SHeader)), + MethodCall.typed[Value[SCollection[SByte.type]]]( + ValUse(6, SHeader), + SHeaderMethods.getMethodByName("parentId"), + Vector(), + Map() + ) ) - ) + ), + ValUse(4, SInt), + None ), - ArithOp(ValUse(4, SInt), IntConstant(1), OpCode @@ (-102.toByte)), - None + ByIndex( + MapCollection( + ValUse(3, SCollectionType(SHeader)), + FuncValue( + Array((6, SHeader)), + MethodCall.typed[Value[SCollection[SByte.type]]]( + ValUse(6, SHeader), + SHeaderMethods.getMethodByName("id"), + Vector(), + Map() + ) + ) + ), + ArithOp(ValUse(4, SInt), IntConstant(1), OpCode @@ (-102.toByte)), + None + ) ) ) ) ) - ) - ), - allowDifferentErrors = true, - allowNewToSucceed = true + ), + allowDifferentErrors = true, + allowNewToSucceed = true ), preGeneratedSamples = Some(ArraySeq.empty) ) diff --git a/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala b/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala index 20faabe128..78dd36ed97 100644 --- a/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala +++ b/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala @@ -1,10 +1,14 @@ package sigma -import sigma.ast.{Downcast, FuncValue, Global, MethodCall, SBigInt, SByte, SGlobalMethods, SInt, SLong, SShort, STypeVar, ValUse} +import sigma.ast.ErgoTree.ZeroHeader +import sigma.ast.SCollection.SByteArray +import sigma.ast.syntax.TrueSigmaProp +import sigma.ast.{BoolToSigmaProp, CompanionDesc, ConcreteCollection, Constant, ConstantPlaceholder, Downcast, ErgoTree, FalseLeaf, FixedCostItem, FuncValue, Global, JitCost, MethodCall, PerItemCost, SBigInt, SByte, SCollection, SGlobalMethods, SInt, SLong, SPair, SShort, SSigmaProp, STypeVar, SelectField, SubstConstants, ValUse, Value} import sigma.data.{CBigInt, ExactNumeric, RType} -import sigma.eval.SigmaDsl +import sigma.eval.{CostDetails, SigmaDsl, TracedCost} import sigma.util.Extensions.{BooleanOps, ByteOps, IntOps, LongOps} import sigmastate.exceptions.MethodNotFound +import sigmastate.utils.Helpers import java.math.BigInteger import scala.util.Success @@ -378,5 +382,85 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite => } } + property("Fix substConstants in v6.0 for ErgoTree version > 0") { + // tree with one segregated constant and v0 + val t1 = ErgoTree( + header = ZeroHeader.withConstantSegregation, + constants = Vector(TrueSigmaProp), + ConstantPlaceholder(0, SSigmaProp)) + + // tree with one segregated constant and max supported version + val t2 = ErgoTree( + header = ZeroHeader + .withVersion(VersionContext.MaxSupportedScriptVersion) + .withConstantSegregation, + Vector(TrueSigmaProp), + ConstantPlaceholder(0, SSigmaProp)) + + def costDetails(nItems: Int) = TracedCost( + traceBase ++ Array( + FixedCostItem(SelectField), + FixedCostItem(ConcreteCollection), + FixedCostItem(ValUse), + FixedCostItem(SelectField), + FixedCostItem(ConcreteCollection), + FixedCostItem(Constant), + FixedCostItem(BoolToSigmaProp), + ast.SeqCostItem(CompanionDesc(SubstConstants), PerItemCost(JitCost(100), JitCost(100), 1), nItems) + ) + ) + val expectedTreeBytes_beforeV6 = Helpers.decodeBytes("1b0108d27300") + val expectedTreeBytes_V6 = Helpers.decodeBytes("1b050108d27300") + + verifyCases( + { + def success[T](v: T, cd: CostDetails, cost: Int ) = Expected(Success(v), cost, cd, cost) + + Seq( + // for tree v0, the result is the same for all versions + (Coll(t1.bytes: _*), 0) -> Expected( + Success(Helpers.decodeBytes("100108d27300")), + cost = 1793, + expectedDetails = CostDetails.ZeroCost, + newCost = 1793, + newVersionedResults = { + val res = (ExpectedResult(Success(Helpers.decodeBytes("100108d27300")), Some(1793)) -> Some(costDetails(1))) + Seq(0, 1, 2, 3).map(version => version -> res) + }), + // for tree version > 0, the result depend on activated version + (Coll(t2.bytes: _*), 0) -> Expected( + Success(expectedTreeBytes_beforeV6), + cost = 1793, + expectedDetails = CostDetails.ZeroCost, + newCost = 1793, + newVersionedResults = { + val res = (ExpectedResult(Success(expectedTreeBytes_V6), Some(1793)) -> Some(costDetails(1))) + Seq(0, 1, 2, 3).map(version => version -> res) + }) + ) + }, + changedFeature( + changedInVersion = VersionContext.V6SoftForkVersion, + { (x: (Coll[Byte], Int)) => + SigmaDsl.substConstants(x._1, Coll[Int](x._2), Coll[Any](SigmaDsl.sigmaProp(false))(sigma.AnyType)) + }, + { (x: (Coll[Byte], Int)) => + SigmaDsl.substConstants(x._1, Coll[Int](x._2), Coll[Any](SigmaDsl.sigmaProp(false))(sigma.AnyType)) + }, + "{ (x: (Coll[Byte], Int)) => substConstants[Any](x._1, Coll[Int](x._2), Coll[Any](sigmaProp(false))) }", + FuncValue( + Vector((1, SPair(SByteArray, SInt))), + SubstConstants( + SelectField.typed[Value[SCollection[SByte.type]]](ValUse(1, SPair(SByteArray, SInt)), 1.toByte), + ConcreteCollection( + Array(SelectField.typed[Value[SInt.type]](ValUse(1, SPair(SByteArray, SInt)), 2.toByte)), + SInt + ), + ConcreteCollection(Array(BoolToSigmaProp(FalseLeaf)), SSigmaProp) + ) + ) + ) + ) + } } diff --git a/sc/shared/src/test/scala/sigma/SigmaDslTesting.scala b/sc/shared/src/test/scala/sigma/SigmaDslTesting.scala index 28c9c05fec..3246f968a0 100644 --- a/sc/shared/src/test/scala/sigma/SigmaDslTesting.scala +++ b/sc/shared/src/test/scala/sigma/SigmaDslTesting.scala @@ -126,6 +126,9 @@ class SigmaDslTesting extends AnyPropSpec /** Checks if this feature is supported in the given version context. */ def isSupportedIn(vc: VersionContext): Boolean + /** Version in which the feature is first implemented of changed. */ + def sinceVersion: Byte + /** Script containing this feature. */ def script: String @@ -397,7 +400,7 @@ class SigmaDslTesting extends AnyPropSpec ctx } - val (expectedResult, expectedCost) = if (activatedVersionInTests < VersionContext.JitActivationVersion) + val (expectedResult, expectedCost) = if (activatedVersionInTests < sinceVersion) (expected.oldResult, expected.verificationCostOpt) else { val res = expected.newResults(ergoTreeVersionInTests) @@ -504,6 +507,8 @@ class SigmaDslTesting extends AnyPropSpec implicit val cs = compilerSettingsInTests + override def sinceVersion: Byte = 0 + override def isSupportedIn(vc: VersionContext): Boolean = true /** in v5.x the old and the new interpreters are the same */ @@ -640,10 +645,11 @@ class SigmaDslTesting extends AnyPropSpec } } - /** Descriptor of a language feature which is changed in v5.0. + /** Descriptor of a language feature which is changed in the specified version. * * @tparam A type of an input test data * @tparam B type of an output of the feature function + * @param changedInVersion version in which the feature behaviour is changed * @param script script of the feature function (see Feature trait) * @param scalaFunc feature function written in Scala and used to simulate the behavior * of the script @@ -663,6 +669,7 @@ class SigmaDslTesting extends AnyPropSpec * @param allowDifferentErrors if true, allow v4.x and v5.0 to fail with different error */ case class ChangedFeature[A, B]( + changedInVersion: Byte, script: String, scalaFunc: A => B, override val scalaFuncNew: A => B, @@ -676,6 +683,8 @@ class SigmaDslTesting extends AnyPropSpec implicit val cs = compilerSettingsInTests + override def sinceVersion: Byte = changedInVersion + override def isSupportedIn(vc: VersionContext): Boolean = true /** Apply given function to the context variable 1 */ @@ -755,7 +764,7 @@ class SigmaDslTesting extends AnyPropSpec checkEq(scalaFuncNew)(newF)(input) } - if (!VersionContext.current.isJitActivated) { + if (VersionContext.current.activatedVersion < changedInVersion) { // check the old implementation with Scala semantic val expectedOldRes = expected.value @@ -1054,14 +1063,16 @@ class SigmaDslTesting extends AnyPropSpec * various ways */ def changedFeature[A: RType, B: RType] - (scalaFunc: A => B, + (changedInVersion: Byte, + scalaFunc: A => B, scalaFuncNew: A => B, script: String, expectedExpr: SValue = null, allowNewToSucceed: Boolean = false, - allowDifferentErrors: Boolean = false) + allowDifferentErrors: Boolean = false + ) (implicit IR: IRContext, evalSettings: EvalSettings): Feature[A, B] = { - ChangedFeature(script, scalaFunc, scalaFuncNew, Option(expectedExpr), + ChangedFeature(changedInVersion, script, scalaFunc, scalaFuncNew, Option(expectedExpr), allowNewToSucceed = allowNewToSucceed, allowDifferentErrors = allowDifferentErrors) } From d4bbccc7364000a80dcfc18847d126de05ed0e27 Mon Sep 17 00:00:00 2001 From: Alexander Slesarenko Date: Thu, 23 May 2024 13:28:53 +0200 Subject: [PATCH 093/314] v6.0-serialize: fix JS tests (added reflection data) --- data/shared/src/main/scala/sigma/SigmaDataReflection.scala | 5 +++++ .../src/main/scala/sigma/compiler/ir/GraphIRReflection.scala | 3 +++ 2 files changed, 8 insertions(+) diff --git a/data/shared/src/main/scala/sigma/SigmaDataReflection.scala b/data/shared/src/main/scala/sigma/SigmaDataReflection.scala index 48939b1460..a6e5de2a26 100644 --- a/data/shared/src/main/scala/sigma/SigmaDataReflection.scala +++ b/data/shared/src/main/scala/sigma/SigmaDataReflection.scala @@ -322,6 +322,11 @@ object SigmaDataReflection { args(1).asInstanceOf[SigmaDslBuilder], args(2).asInstanceOf[Coll[Byte]], args(3).asInstanceOf[Coll[Byte]])(args(4).asInstanceOf[ErgoTreeEvaluator]) + }, + mkMethod(clazz, "serialize_eval", Array[Class[_]](classOf[MethodCall], classOf[SigmaDslBuilder], classOf[Object], classOf[ErgoTreeEvaluator])) { (obj, args) => + obj.asInstanceOf[SGlobalMethods.type].serialize_eval(args(0).asInstanceOf[MethodCall], + args(1).asInstanceOf[SigmaDslBuilder], + args(2).asInstanceOf[SType#WrappedType])(args(3).asInstanceOf[ErgoTreeEvaluator]) } ) ) diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/GraphIRReflection.scala b/sc/shared/src/main/scala/sigma/compiler/ir/GraphIRReflection.scala index 69736a0224..6c0403f643 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/GraphIRReflection.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/GraphIRReflection.scala @@ -504,6 +504,9 @@ object GraphIRReflection { }, mkMethod(clazz, "decodePoint", Array[Class[_]](classOf[Base#Ref[_]])) { (obj, args) => obj.asInstanceOf[ctx.SigmaDslBuilder].decodePoint(args(0).asInstanceOf[ctx.Ref[ctx.Coll[Byte]]]) + }, + mkMethod(clazz, "serialize", Array[Class[_]](classOf[Base#Ref[_]])) { (obj, args) => + obj.asInstanceOf[ctx.SigmaDslBuilder].serialize(args(0).asInstanceOf[ctx.Ref[Any]]) } ) ) From de18eeb662a0701ec2def489f89e537d113dfc6e Mon Sep 17 00:00:00 2001 From: Alexander Slesarenko Date: Thu, 23 May 2024 16:08:20 +0200 Subject: [PATCH 094/314] i994-fix-subst-constants: more tests --- .../scala/sigma/LanguageSpecificationV6.scala | 52 +++++++++++-------- 1 file changed, 31 insertions(+), 21 deletions(-) diff --git a/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala b/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala index 78dd36ed97..fd2e18ebfb 100644 --- a/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala +++ b/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala @@ -1,11 +1,13 @@ package sigma +import org.ergoplatform.sdk.utils.ErgoTreeUtils import sigma.ast.ErgoTree.ZeroHeader import sigma.ast.SCollection.SByteArray import sigma.ast.syntax.TrueSigmaProp import sigma.ast.{BoolToSigmaProp, CompanionDesc, ConcreteCollection, Constant, ConstantPlaceholder, Downcast, ErgoTree, FalseLeaf, FixedCostItem, FuncValue, Global, JitCost, MethodCall, PerItemCost, SBigInt, SByte, SCollection, SGlobalMethods, SInt, SLong, SPair, SShort, SSigmaProp, STypeVar, SelectField, SubstConstants, ValUse, Value} import sigma.data.{CBigInt, ExactNumeric, RType} import sigma.eval.{CostDetails, SigmaDsl, TracedCost} +import sigma.serialization.ErgoTreeSerializer import sigma.util.Extensions.{BooleanOps, ByteOps, IntOps, LongOps} import sigmastate.exceptions.MethodNotFound import sigmastate.utils.Helpers @@ -21,6 +23,11 @@ import scala.util.Success class LanguageSpecificationV6 extends LanguageSpecificationBase { suite => override def languageVersion: Byte = VersionContext.V6SoftForkVersion + def expectedSuccessForAllTreeVersions[A](value: A, cost: Int, costDetails: CostDetails) = { + val res = ExpectedResult(Success(value), Some(cost)) -> Some(costDetails) + Seq(0, 1, 2, 3).map(version => version -> res) + } + def mkSerializeFeature[A: RType]: Feature[A, Coll[Byte]] = { val tA = RType[A] val tpe = Evaluation.rtypeToSType(tA) @@ -414,32 +421,25 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite => val expectedTreeBytes_V6 = Helpers.decodeBytes("1b050108d27300") verifyCases( - { - def success[T](v: T, cd: CostDetails, cost: Int ) = Expected(Success(v), cost, cd, cost) - - Seq( - // for tree v0, the result is the same for all versions - (Coll(t1.bytes: _*), 0) -> Expected( - Success(Helpers.decodeBytes("100108d27300")), - cost = 1793, - expectedDetails = CostDetails.ZeroCost, - newCost = 1793, - newVersionedResults = { - val res = (ExpectedResult(Success(Helpers.decodeBytes("100108d27300")), Some(1793)) -> Some(costDetails(1))) - Seq(0, 1, 2, 3).map(version => version -> res) - }), - // for tree version > 0, the result depend on activated version + Seq( + // for tree v0, the result is the same for all versions + (Coll(t1.bytes: _*), 0) -> Expected( + Success(Helpers.decodeBytes("100108d27300")), + cost = 1793, + expectedDetails = CostDetails.ZeroCost, + newCost = 1793, + newVersionedResults = expectedSuccessForAllTreeVersions(Helpers.decodeBytes("100108d27300"), 1793, costDetails(1)) + ), + // for tree version > 0, the result depend on activated version + { (Coll(t2.bytes: _*), 0) -> Expected( Success(expectedTreeBytes_beforeV6), cost = 1793, expectedDetails = CostDetails.ZeroCost, newCost = 1793, - newVersionedResults = { - val res = (ExpectedResult(Success(expectedTreeBytes_V6), Some(1793)) -> Some(costDetails(1))) - Seq(0, 1, 2, 3).map(version => version -> res) - }) - ) - }, + newVersionedResults = expectedSuccessForAllTreeVersions(expectedTreeBytes_V6, 1793, costDetails(1))) + } + ), changedFeature( changedInVersion = VersionContext.V6SoftForkVersion, { (x: (Coll[Byte], Int)) => @@ -462,5 +462,15 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite => ) ) ) + + // before v6.0 the expected tree is not parsable + ErgoTree.fromBytes(expectedTreeBytes_beforeV6.toArray).isRightParsed shouldBe false + + // in v6.0 the expected tree should be parsable and similar to the original tree + val tree = ErgoTree.fromBytes(expectedTreeBytes_V6.toArray) + tree.isRightParsed shouldBe true + tree.header shouldBe t2.header + tree.constants.length shouldBe t2.constants.length + tree.root shouldBe t2.root } } From 3ccf11ea33c584eae38d3af7baa8e99bd80d829f Mon Sep 17 00:00:00 2001 From: Alexander Slesarenko Date: Thu, 23 May 2024 18:11:20 +0200 Subject: [PATCH 095/314] i486-toBytes: fixes after merge --- .../scala/sigmastate/utils/Extensions.scala | 8 ++--- .../scala/sigma/LanguageSpecificationV5.scala | 36 ------------------- .../scala/sigma/LanguageSpecificationV6.scala | 16 +++++++++ 3 files changed, 20 insertions(+), 40 deletions(-) diff --git a/interpreter/shared/src/main/scala/sigmastate/utils/Extensions.scala b/interpreter/shared/src/main/scala/sigmastate/utils/Extensions.scala index 54abc40f4e..2e66eb6b19 100644 --- a/interpreter/shared/src/main/scala/sigmastate/utils/Extensions.scala +++ b/interpreter/shared/src/main/scala/sigmastate/utils/Extensions.scala @@ -13,7 +13,7 @@ object Extensions { * For example, the Byte value {@code 0x12} would yield the * byte array {@code {0x12}}. */ - def toBytes: Coll[Byte] = SigmaDsl.Colls.fromItems(b) + def toBigEndianBytes: Coll[Byte] = SigmaDsl.Colls.fromItems(b) } @@ -22,7 +22,7 @@ object Extensions { * For example, the Short value {@code 0x1213} would yield the * byte array {@code {0x12, 0x13}}. */ - def toBytes: Coll[Byte] = Colls.fromArray(Shorts.toByteArray(x)) + def toBigEndianBytes: Coll[Byte] = Colls.fromArray(Shorts.toByteArray(x)) } implicit class IntOpsForSigma(val x: Int) extends AnyVal { @@ -30,7 +30,7 @@ object Extensions { * For example, the Int value {@code 0x12131415} would yield the * byte array {@code {0x12, 0x13, 0x14, 0x15}}. */ - def toBytes: Coll[Byte] = Colls.fromArray(Ints.toByteArray(x)) + def toBigEndianBytes: Coll[Byte] = Colls.fromArray(Ints.toByteArray(x)) } implicit class LongOpsForSigma(val x: Long) extends AnyVal { @@ -38,7 +38,7 @@ object Extensions { * For example, the Long value {@code 0x1213141516171819} would yield the * byte array {@code {0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19}}. */ - def toBytes: Coll[Byte] = Colls.fromArray(Longs.toByteArray(x)) + def toBigEndianBytes: Coll[Byte] = Colls.fromArray(Longs.toByteArray(x)) } /** Provides extension methods for `ModifierId` instances. diff --git a/sc/shared/src/test/scala/sigma/LanguageSpecificationV5.scala b/sc/shared/src/test/scala/sigma/LanguageSpecificationV5.scala index dc6d1f6173..f568515c89 100644 --- a/sc/shared/src/test/scala/sigma/LanguageSpecificationV5.scala +++ b/sc/shared/src/test/scala/sigma/LanguageSpecificationV5.scala @@ -929,42 +929,6 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => ">=", GE.apply)(_ >= _) } -// property("Numeric.toBytes methods equivalence") { -// lazy val toBytes = changedFeature( -// (x: Byte) => x.toBytes, -// (x: Byte) => x.toBytes, -// "{ (x: Byte) => x.toBytes }") -// val cases = Seq( -// (0.toByte, Success(Coll(0.toByte))), -// (1.toByte, Success(Coll(1.toByte))) -// ) -// -// testCases(cases, toBytes) -// } - - property("Byte methods equivalence (new features)") { - lazy val toAbs = newFeature((x: Byte) => x.toAbs, "{ (x: Byte) => x.toAbs }") - lazy val compareTo = newFeature( - (x: (Byte, Byte)) => x._1.compareTo(x._2), - "{ (x: (Byte, Byte)) => x._1.compareTo(x._2) }") - - lazy val bitOr = newFeature( - { (x: (Byte, Byte)) => (x._1 | x._2).toByteExact }, - "{ (x: (Byte, Byte)) => (x._1 | x._2).toByteExact }") - - lazy val bitAnd = newFeature( - { (x: (Byte, Byte)) => (x._1 & x._2).toByteExact }, - "{ (x: (Byte, Byte)) => (x._1 & x._2).toByteExact }") - - forAll { x: Byte => - Seq(toAbs).foreach(f => f.checkEquality(x)) - } - - forAll { x: (Byte, Byte) => - Seq(compareTo, bitOr, bitAnd).foreach(_.checkEquality(x)) - } - } - property("Short methods equivalence") { SShort.upcast(0.toShort) shouldBe 0.toShort // boundary test case SShort.downcast(0.toShort) shouldBe 0.toShort // boundary test case diff --git a/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala b/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala index fd2e18ebfb..e105e4bee9 100644 --- a/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala +++ b/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala @@ -10,6 +10,7 @@ import sigma.eval.{CostDetails, SigmaDsl, TracedCost} import sigma.serialization.ErgoTreeSerializer import sigma.util.Extensions.{BooleanOps, ByteOps, IntOps, LongOps} import sigmastate.exceptions.MethodNotFound +import sigmastate.utils.Extensions.ByteOpsForSigma import sigmastate.utils.Helpers import java.math.BigInteger @@ -473,4 +474,19 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite => tree.constants.length shouldBe t2.constants.length tree.root shouldBe t2.root } + + property("Numeric.toBytes methods equivalence") { + lazy val toBytes = newFeature( + { (x: Byte) => x.toBigEndianBytes }, + "{ (x: Byte) => x.toBytes }", + sinceVersion = VersionContext.V6SoftForkVersion) + val cases = Seq( + (0.toByte, Success(Coll(0.toByte))), + (1.toByte, Success(Coll(1.toByte))) + ) + + testCases(cases, toBytes) + } + + } From 3d47f2ac29e975de1754b46ddf210708d8eee088 Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Fri, 24 May 2024 20:50:25 +0300 Subject: [PATCH 096/314] initial raw, buggy & unversioned unsigned bit int impl --- .../main/scala/sigma/crypto/Platform.scala | 1 + .../src/main/scala/sigma/Evaluation.scala | 2 + .../src/main/scala/sigma/SigmaDsl.scala | 140 +++++++++++++++- .../src/main/scala/sigma/ast/SType.scala | 45 +++++- .../src/main/scala/sigma/data/CBigInt.scala | 43 ++++- .../src/main/scala/sigma/data/package.scala | 1 + .../shared/src/main/scala/sigma/package.scala | 1 + .../serialization/CoreDataSerializer.scala | 11 ++ .../sigma/serialization/TypeSerializer.scala | 3 +- .../main/scala/sigma/ast/SigmaPredef.scala | 12 ++ .../src/main/scala/sigma/ast/trees.scala | 4 +- .../src/main/scala/sigma/ast/values.scala | 16 +- .../scala/sigma/data/CSigmaDslBuilder.scala | 4 +- .../main/scala/sigma/data/ExactIntegral.scala | 2 +- .../sigma/data/UnsignedBigIntegerOps.scala | 98 +++++++++++ .../main/scala/sigma/eval/Extensions.scala | 3 +- .../crypto/BigIntSpecification.scala | 9 ++ .../scala/sigmastate/eval/GraphBuilding.scala | 15 +- .../scala/special/sigma/SigmaDslUnit.scala | 9 ++ .../special/sigma/impl/SigmaDslImpl.scala | 153 ++++++++++++++++++ .../utxo/BasicOpsSpecification.scala | 114 ++++++++++++- .../OracleExamplesSpecification.scala | 2 +- 22 files changed, 668 insertions(+), 20 deletions(-) create mode 100644 data/shared/src/main/scala/sigma/data/UnsignedBigIntegerOps.scala create mode 100644 interpreter/shared/src/test/scala/sigmastate/crypto/BigIntSpecification.scala diff --git a/core/jvm/src/main/scala/sigma/crypto/Platform.scala b/core/jvm/src/main/scala/sigma/crypto/Platform.scala index b71694e81b..13c8d6515e 100644 --- a/core/jvm/src/main/scala/sigma/crypto/Platform.scala +++ b/core/jvm/src/main/scala/sigma/crypto/Platform.scala @@ -185,6 +185,7 @@ object Platform { case _: Int => tpe == SInt case _: Long => tpe == SLong case _: BigInt => tpe == SBigInt + case _: UnsignedBigInt => tpe == SUnsignedBigInt case _: String => tpe == SString // TODO v6.0: remove this case (see https://github.com/ScorexFoundation/sigmastate-interpreter/issues/905) case _: GroupElement => tpe.isGroupElement case _: SigmaProp => tpe.isSigmaProp diff --git a/core/shared/src/main/scala/sigma/Evaluation.scala b/core/shared/src/main/scala/sigma/Evaluation.scala index d86b7c1650..c3ffcc8896 100644 --- a/core/shared/src/main/scala/sigma/Evaluation.scala +++ b/core/shared/src/main/scala/sigma/Evaluation.scala @@ -25,6 +25,7 @@ object Evaluation { case SAny => AnyType case SUnit => UnitType case SBigInt => BigIntRType + case SUnsignedBigInt => UnsignedBigIntRType case SBox => BoxRType case SContext => ContextRType case SGlobal => SigmaDslBuilderRType @@ -67,6 +68,7 @@ object Evaluation { case AnyType => SAny case UnitType => SUnit case BigIntRType => SBigInt + case UnsignedBigIntRType => SUnsignedBigInt case GroupElementRType => SGroupElement case AvlTreeRType => SAvlTree case ot: OptionType[_] => SOption(rtypeToSType(ot.tA)) diff --git a/core/shared/src/main/scala/sigma/SigmaDsl.scala b/core/shared/src/main/scala/sigma/SigmaDsl.scala index df2b419273..cc102b6b36 100644 --- a/core/shared/src/main/scala/sigma/SigmaDsl.scala +++ b/core/shared/src/main/scala/sigma/SigmaDsl.scala @@ -5,10 +5,8 @@ import java.math.BigInteger import sigma.data._ /** - * All `modQ` operations assume that Q is a global constant (an order of the only one cryptographically strong group - * which is used for all cryptographic operations). - * So it is globally and implicitly used in all methods. - * */ + * Base class for signed 256-bits integers + */ trait BigInt { /** Convert this BigInt value to Byte. * @throws ArithmeticException if overflow happens. @@ -156,6 +154,138 @@ trait BigInt { def |(that: BigInt): BigInt = or(that) } + +trait UnsignedBigInt { + /** Convert this BigInt value to Byte. + * @throws ArithmeticException if overflow happens. + */ + def toByte: Byte + + /** Convert this BigInt value to Short. + * @throws ArithmeticException if overflow happens. + */ + def toShort: Short + + /** Convert this BigInt value to Int. + * @throws ArithmeticException if overflow happens. + */ + def toInt: Int + + /** Convert this BigInt value to Int. + * @throws ArithmeticException if overflow happens. + */ + def toLong: Long + + /** Returns a big-endian representation of this BigInt in a collection of bytes. + * For example, the value {@code 0x1213141516171819} would yield the + * byte array {@code {0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19}}. + * @since 2.0 + */ + def toBytes: Coll[Byte] + + + /** Compares this numeric with that numeric for order. Returns a negative integer, zero, or a positive integer as the + * `this` is less than, equal to, or greater than `that`. + */ + def compareTo(that: UnsignedBigInt): Int + + /** Returns a BigInt whose value is {@code (this + that)}. + * + * @param that value to be added to this BigInt. + * @return { @code this + that} + */ + def add(that: UnsignedBigInt): UnsignedBigInt + def +(that: UnsignedBigInt): UnsignedBigInt = add(that) + + /** Returns a BigInt whose value is {@code (this - that)}. + * + * @param that value to be subtracted from this BigInt. + * @return { @code this - that} + */ + def subtract(that: UnsignedBigInt): UnsignedBigInt + + def -(that: UnsignedBigInt): UnsignedBigInt = subtract(that) + + /** Returns a BigInt whose value is {@code (this * that)}. + * + * @implNote An implementation may offer better algorithmic + * performance when { @code that == this}. + * @param that value to be multiplied by this BigInt. + * @return { @code this * that} + */ + def multiply(that: UnsignedBigInt): UnsignedBigInt + def *(that: UnsignedBigInt): UnsignedBigInt = multiply(that) + + /** Returns a BigInt whose value is {@code (this / that)}. + * + * @param that value by which this BigInt is to be divided. + * @return { @code this / that} + * @throws ArithmeticException if { @code that} is zero. + */ + def divide(that: UnsignedBigInt): UnsignedBigInt + def /(that: UnsignedBigInt): UnsignedBigInt = divide(that) + + /** + * Returns a BigInt whose value is {@code (this mod m}). This method + * differs from {@code remainder} in that it always returns a + * non-negative BigInteger. + * + * @param m the modulus. + * @return { @code this mod m} + * @throws ArithmeticException { @code m} ≤ 0 + * @see #remainder + */ + def mod(m: UnsignedBigInt): UnsignedBigInt + def %(m: UnsignedBigInt): UnsignedBigInt = mod(m) + + /** + * Returns a BigInt whose value is {@code (this % that)}. + * + * @param that value by which this BigInt is to be divided, and the + * remainder computed. + * @return { @code this % that} + * @throws ArithmeticException if { @code that} is zero. + */ + def remainder(that: UnsignedBigInt): UnsignedBigInt + + /** + * Returns the minimum of this BigInteger and {@code val}. + * + * @param that value with which the minimum is to be computed. + * @return the BigInteger whose value is the lesser of this BigInteger and + * { @code val}. If they are equal, either may be returned. + */ + def min(that: UnsignedBigInt): UnsignedBigInt + + /** + * Returns the maximum of this BigInteger and {@code val}. + * + * @param that value with which the maximum is to be computed. + * @return the BigInteger whose value is the greater of this and + * { @code val}. If they are equal, either may be returned. + */ + def max(that: UnsignedBigInt): UnsignedBigInt + + /** Returns a BigInteger whose value is `(this & that)`. + * @param that value to be AND'ed with this BigInteger. + * @return `this & that` + */ + def and(that: UnsignedBigInt): UnsignedBigInt + def &(that: UnsignedBigInt): UnsignedBigInt = and(that) + + /** Returns a BigInteger whose value is `(this | that)`. (This + * method returns a negative BigInteger if and only if either `this` or `that`` is + * negative.) + * + * @param that value to be OR'ed with this BigInteger. + * @return `this | that` + */ + def or(that: UnsignedBigInt): UnsignedBigInt + def |(that: UnsignedBigInt): UnsignedBigInt = or(that) +} + + + /** Base class for points on elliptic curves. */ trait GroupElement { /** Checks if the provided element is an identity element. */ @@ -721,6 +851,8 @@ trait SigmaDslBuilder { /** Create DSL big integer from existing `java.math.BigInteger`*/ def BigInt(n: BigInteger): BigInt + def UnsignedBigInt(n: BigInteger): UnsignedBigInt + /** Extract `java.math.BigInteger` from DSL's `BigInt` type*/ def toBigInteger(n: BigInt): BigInteger diff --git a/core/shared/src/main/scala/sigma/ast/SType.scala b/core/shared/src/main/scala/sigma/ast/SType.scala index f75cbc9e8b..50763ba56e 100644 --- a/core/shared/src/main/scala/sigma/ast/SType.scala +++ b/core/shared/src/main/scala/sigma/ast/SType.scala @@ -4,10 +4,10 @@ import sigma.Evaluation.stypeToRType import sigma.ast.SCollection.SByteArray import sigma.ast.SType.TypeCode import sigma.data.OverloadHack.Overloaded1 -import sigma.data.{CBigInt, Nullable, SigmaConstants} +import sigma.data.{CBigInt, CUnsignedBigInt, Nullable, SigmaConstants} import sigma.reflection.{RClass, RMethod, ReflectionData} import sigma.util.Extensions.{IntOps, LongOps, ShortOps} -import sigma.{AvlTree, BigInt, Box, Coll, Context, Evaluation, GroupElement, Header, PreHeader, SigmaDslBuilder, SigmaProp} +import sigma.{AvlTree, BigInt, Box, Coll, Context, Evaluation, GroupElement, Header, PreHeader, SigmaDslBuilder, SigmaProp, UnsignedBigInt} import java.math.BigInteger @@ -156,6 +156,7 @@ object SType { case SInt => x.isInstanceOf[Int] case SLong => x.isInstanceOf[Long] case SBigInt => x.isInstanceOf[BigInt] + case SUnsignedBigInt => x.isInstanceOf[UnsignedBigInt] case SGroupElement => x.isInstanceOf[GroupElement] case SSigmaProp => x.isInstanceOf[SigmaProp] case SBox => x.isInstanceOf[Box] @@ -448,13 +449,12 @@ case object SLong extends SPrimType with SEmbeddable with SNumericType with SMon } } -/** Type of 256 bit integet values. Implemented using [[java.math.BigInteger]]. */ +/** Type of 256-bit signed integer values. Implemented using [[java.math.BigInteger]]. */ case object SBigInt extends SPrimType with SEmbeddable with SNumericType with SMonoType { override type WrappedType = BigInt override val typeCode: TypeCode = 6: Byte override val reprClass: RClass[_] = RClass(classOf[BigInt]) override def typeId = typeCode - implicit def typeBigInt: SBigInt.type = this /** Type of Relation binary op like GE, LE, etc. */ val RelationOpType = SFunc(Array(SBigInt, SBigInt), SBoolean) @@ -486,6 +486,43 @@ case object SBigInt extends SPrimType with SEmbeddable with SNumericType with SM } } +/** Type of 256-bit unsigned integer values. Implemented using [[java.math.BigInteger]]. */ +case object SUnsignedBigInt extends SPrimType with SEmbeddable with SNumericType with SMonoType { + override type WrappedType = UnsignedBigInt + override val typeCode: TypeCode = 9: Byte + override val reprClass: RClass[_] = RClass(classOf[BigInt]) + override def typeId = typeCode + + /** Type of Relation binary op like GE, LE, etc. */ + val RelationOpType = SFunc(Array(SUnsignedBigInt, SUnsignedBigInt), SBoolean) + + /** The maximum size of BigInteger value in byte array representation. */ + val MaxSizeInBytes: Long = SigmaConstants.MaxBigIntSizeInBytes.value // todo: 256 bits or more? + + override def numericTypeIndex: Int = 5 + + override def upcast(v: AnyVal): UnsignedBigInt = { + val bi = v match { + case x: Byte => BigInteger.valueOf(x.toLong) + case x: Short => BigInteger.valueOf(x.toLong) + case x: Int => BigInteger.valueOf(x.toLong) + case x: Long => BigInteger.valueOf(x) + case _ => sys.error(s"Cannot upcast value $v to the type $this") + } + CUnsignedBigInt(bi) + } + override def downcast(v: AnyVal): UnsignedBigInt = { + val bi = v match { + case x: Byte => BigInteger.valueOf(x.toLong) + case x: Short => BigInteger.valueOf(x.toLong) + case x: Int => BigInteger.valueOf(x.toLong) + case x: Long => BigInteger.valueOf(x) + case _ => sys.error(s"Cannot downcast value $v to the type $this") + } + CUnsignedBigInt(bi) + } +} + /** Descriptor of type `String` which is not used in ErgoTree, but used in ErgoScript. * NOTE: this descriptor both type and type companion */ case object SString extends SProduct with SMonoType { diff --git a/core/shared/src/main/scala/sigma/data/CBigInt.scala b/core/shared/src/main/scala/sigma/data/CBigInt.scala index bbf1a85e46..5ae617feba 100644 --- a/core/shared/src/main/scala/sigma/data/CBigInt.scala +++ b/core/shared/src/main/scala/sigma/data/CBigInt.scala @@ -1,7 +1,7 @@ package sigma.data import sigma.util.Extensions.BigIntegerOps -import sigma.{BigInt, Coll, Colls} +import sigma.{BigInt, Coll, Colls, UnsignedBigInt} import java.math.BigInteger @@ -50,3 +50,44 @@ case class CBigInt(override val wrappedValue: BigInteger) extends BigInt with Wr override def or(that: BigInt): BigInt = CBigInt(wrappedValue.or(that.asInstanceOf[CBigInt].wrappedValue)) } + +/** A default implementation of [[BigInt]] interface. + * + * @see [[BigInt]] for detailed descriptions + */ +case class CUnsignedBigInt(override val wrappedValue: BigInteger) extends UnsignedBigInt with WrapperOf[BigInteger] { + + override def toByte: Byte = wrappedValue.toByteExact + + override def toShort: Short = wrappedValue.toShortExact + + override def toInt: Int = wrappedValue.toIntExact + + override def toLong: Long = wrappedValue.toLongExact + + override def toBytes: Coll[Byte] = Colls.fromArray(wrappedValue.toByteArray) + + override def compareTo(that: UnsignedBigInt): Int = + wrappedValue.compareTo(that.asInstanceOf[CUnsignedBigInt].wrappedValue) + + //todo: consider result's bits limit + override def add(that: UnsignedBigInt): UnsignedBigInt = CUnsignedBigInt(wrappedValue.add(that.asInstanceOf[CUnsignedBigInt].wrappedValue).to256BitValueExact) + + override def subtract(that: UnsignedBigInt): UnsignedBigInt = CUnsignedBigInt(wrappedValue.subtract(that.asInstanceOf[CUnsignedBigInt].wrappedValue).to256BitValueExact) + + override def multiply(that: UnsignedBigInt): UnsignedBigInt = CUnsignedBigInt(wrappedValue.multiply(that.asInstanceOf[CUnsignedBigInt].wrappedValue).to256BitValueExact) + + override def divide(that: UnsignedBigInt): UnsignedBigInt = CUnsignedBigInt(wrappedValue.divide(that.asInstanceOf[CUnsignedBigInt].wrappedValue)) + + override def mod(m: UnsignedBigInt): UnsignedBigInt = CUnsignedBigInt(wrappedValue.mod(m.asInstanceOf[CUnsignedBigInt].wrappedValue)) + + override def remainder(that: UnsignedBigInt): UnsignedBigInt = CUnsignedBigInt(wrappedValue.remainder(that.asInstanceOf[CUnsignedBigInt].wrappedValue)) + + override def min(that: UnsignedBigInt): UnsignedBigInt = CUnsignedBigInt(wrappedValue.min(that.asInstanceOf[CUnsignedBigInt].wrappedValue)) + + override def max(that: UnsignedBigInt): UnsignedBigInt = CUnsignedBigInt(wrappedValue.max(that.asInstanceOf[CUnsignedBigInt].wrappedValue)) + + override def and(that: UnsignedBigInt): UnsignedBigInt = CUnsignedBigInt(wrappedValue.and(that.asInstanceOf[CUnsignedBigInt].wrappedValue)) + + override def or(that: UnsignedBigInt): UnsignedBigInt = CUnsignedBigInt(wrappedValue.or(that.asInstanceOf[CUnsignedBigInt].wrappedValue)) +} diff --git a/core/shared/src/main/scala/sigma/data/package.scala b/core/shared/src/main/scala/sigma/data/package.scala index c5a35f7b5f..58870c0888 100644 --- a/core/shared/src/main/scala/sigma/data/package.scala +++ b/core/shared/src/main/scala/sigma/data/package.scala @@ -14,6 +14,7 @@ package object data { val StringClassTag = classTag[String] val BigIntClassTag = classTag[BigInt] + val UnsignedBigIntClassTag = classTag[UnsignedBigInt] val GroupElementClassTag = classTag[GroupElement] val SigmaPropClassTag = classTag[SigmaProp] val SigmaBooleanClassTag = classTag[SigmaBoolean] diff --git a/core/shared/src/main/scala/sigma/package.scala b/core/shared/src/main/scala/sigma/package.scala index 89b883f52d..4473bd338f 100644 --- a/core/shared/src/main/scala/sigma/package.scala +++ b/core/shared/src/main/scala/sigma/package.scala @@ -26,6 +26,7 @@ package object sigma { implicit val StringType : RType[String] = GeneralType(StringClassTag) implicit val BigIntRType : RType[BigInt] = GeneralType(BigIntClassTag) + implicit val UnsignedBigIntRType : RType[UnsignedBigInt] = GeneralType(UnsignedBigIntClassTag) implicit val GroupElementRType: RType[GroupElement] = GeneralType(GroupElementClassTag) implicit val SigmaPropRType : RType[SigmaProp] = GeneralType(SigmaPropClassTag) implicit val SigmaBooleanRType: RType[SigmaBoolean] = GeneralType(SigmaBooleanClassTag) diff --git a/core/shared/src/main/scala/sigma/serialization/CoreDataSerializer.scala b/core/shared/src/main/scala/sigma/serialization/CoreDataSerializer.scala index 479b199da5..834edfb9a4 100644 --- a/core/shared/src/main/scala/sigma/serialization/CoreDataSerializer.scala +++ b/core/shared/src/main/scala/sigma/serialization/CoreDataSerializer.scala @@ -33,6 +33,10 @@ class CoreDataSerializer { val data = v.asInstanceOf[BigInt].toBigInteger.toByteArray w.putUShort(data.length) w.putBytes(data) + case SUnsignedBigInt => // todo: versioning + val data = v.asInstanceOf[CUnsignedBigInt].wrappedValue.toByteArray + w.putUShort(data.length) + w.putBytes(data) case SGroupElement => GroupElementSerializer.serialize(v.asInstanceOf[GroupElement].toECPoint, w) case SSigmaProp => @@ -103,6 +107,13 @@ class CoreDataSerializer { } val valueBytes = r.getBytes(size) CBigInt(new BigInteger(valueBytes)) + case SUnsignedBigInt => // todo: versioning + val size: Short = r.getUShort().toShort + if (size > SBigInt.MaxSizeInBytes + 1) { //todo: use encoding with no sign bit + throw new SerializerException(s"BigInt value doesn't not fit into ${SBigInt.MaxSizeInBytes} bytes: $size") + } + val valueBytes = r.getBytes(size) + CUnsignedBigInt(new BigInteger(valueBytes)) case SGroupElement => CGroupElement(GroupElementSerializer.parse(r)) case SSigmaProp => diff --git a/core/shared/src/main/scala/sigma/serialization/TypeSerializer.scala b/core/shared/src/main/scala/sigma/serialization/TypeSerializer.scala index 9c84de0944..f00421a31c 100644 --- a/core/shared/src/main/scala/sigma/serialization/TypeSerializer.scala +++ b/core/shared/src/main/scala/sigma/serialization/TypeSerializer.scala @@ -215,6 +215,7 @@ class TypeSerializer { 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. */ - val embeddableIdToType = Array[SType](null, SBoolean, SByte, SShort, SInt, SLong, SBigInt, SGroupElement, SSigmaProp) + //todo: versioning + val embeddableIdToType = Array[SType](null, SBoolean, SByte, SShort, SInt, SLong, SBigInt, SGroupElement, SSigmaProp, SUnsignedBigInt) } \ No newline at end of file diff --git a/data/shared/src/main/scala/sigma/ast/SigmaPredef.scala b/data/shared/src/main/scala/sigma/ast/SigmaPredef.scala index 631f7f2d75..d8c65a7afe 100644 --- a/data/shared/src/main/scala/sigma/ast/SigmaPredef.scala +++ b/data/shared/src/main/scala/sigma/ast/SigmaPredef.scala @@ -192,6 +192,17 @@ object SigmaPredef { Seq(ArgInfo("", ""))) ) + val UBigIntFromStringFunc = PredefinedFunc("unsignedBigInt", + Lambda(Array("input" -> SString), SUnsignedBigInt, None), + PredefFuncInfo( + { case (_, Seq(arg: EvaluatedValue[SString.type]@unchecked)) => + UnsignedBigIntConstant(new BigInteger(arg.value)) + }), + OperationInfo(Constant, + """Parsing string literal argument as a 256-bit unsigned big integer.""".stripMargin, + Seq(ArgInfo("", ""))) + ) + val FromBase16Func = PredefinedFunc("fromBase16", Lambda(Array("input" -> SString), SByteArray, None), PredefFuncInfo( @@ -416,6 +427,7 @@ object SigmaPredef { GetVarFunc, DeserializeFunc, BigIntFromStringFunc, + UBigIntFromStringFunc, FromBase16Func, FromBase64Func, FromBase58Func, diff --git a/data/shared/src/main/scala/sigma/ast/trees.scala b/data/shared/src/main/scala/sigma/ast/trees.scala index 39e666a389..7be73ad55a 100644 --- a/data/shared/src/main/scala/sigma/ast/trees.scala +++ b/data/shared/src/main/scala/sigma/ast/trees.scala @@ -15,6 +15,7 @@ import sigma.serialization.CoreByteWriter.ArgInfo import sigma.validation.SigmaValidationSettings import sigma.{Coll, Colls, GroupElement, SigmaProp, VersionContext} import NumericOps.{BigIntIsExactIntegral, BigIntIsExactOrdering} +import sigma.data.UnsignedBigIntNumericOps.{UnsignedBigIntIsExactIntegral, UnsignedBigIntIsExactOrdering} import sigma.eval.ErgoTreeEvaluator.DataEnv import sigma.eval.Extensions.EvalCollOps import sigma.eval.{ErgoTreeEvaluator, SigmaDsl} @@ -875,7 +876,8 @@ object ArithOp { SShort -> new OperationImpl(ShortIsExactIntegral, ShortIsExactOrdering, SShort), SInt -> new OperationImpl(IntIsExactIntegral, IntIsExactOrdering, SInt), SLong -> new OperationImpl(LongIsExactIntegral, LongIsExactOrdering, SLong), - SBigInt -> new OperationImpl(BigIntIsExactIntegral, BigIntIsExactOrdering, SBigInt) + SBigInt -> new OperationImpl(BigIntIsExactIntegral, BigIntIsExactOrdering, SBigInt), + SUnsignedBigInt -> new OperationImpl(UnsignedBigIntIsExactIntegral, UnsignedBigIntIsExactOrdering, SUnsignedBigInt) ).map { case (t, n) => (t.typeCode, n) }) /** Returns operation name for the given opCode. */ diff --git a/data/shared/src/main/scala/sigma/ast/values.scala b/data/shared/src/main/scala/sigma/ast/values.scala index 87c661a00a..8c55d27a94 100644 --- a/data/shared/src/main/scala/sigma/ast/values.scala +++ b/data/shared/src/main/scala/sigma/ast/values.scala @@ -8,7 +8,7 @@ import sigma.ast.TypeCodes.ConstantCode import sigma.ast.syntax._ import sigma.crypto.{CryptoConstants, EcPointType} import sigma.data.OverloadHack.Overloaded1 -import sigma.data.{CSigmaDslBuilder, CSigmaProp, Nullable, RType, SigmaBoolean} +import sigma.data.{CSigmaDslBuilder, CSigmaProp, CUnsignedBigInt, Nullable, RType, SigmaBoolean} import sigma.eval.ErgoTreeEvaluator.DataEnv import sigma.eval.{ErgoTreeEvaluator, SigmaDsl} import sigma.exceptions.InterpreterException @@ -499,6 +499,20 @@ object BigIntConstant { def apply(value: Long): Constant[SBigInt.type] = Constant[SBigInt.type](SigmaDsl.BigInt(BigInteger.valueOf(value)), SBigInt) } +object UnsignedBigIntConstant { + def apply(value: UnsignedBigInt): Constant[SUnsignedBigInt.type] = { + Constant[SUnsignedBigInt.type](value, SUnsignedBigInt) + } + + def apply(value: BigInteger): Constant[SUnsignedBigInt.type] = { + Constant[SUnsignedBigInt.type](CUnsignedBigInt(value), SUnsignedBigInt) + } + + def apply(value: Long): Constant[SUnsignedBigInt.type] = { + Constant[SUnsignedBigInt.type](CUnsignedBigInt(BigInteger.valueOf(value)), SUnsignedBigInt) + } +} + object StringConstant { def apply(value: String): Constant[SString.type] = Constant[SString.type](value, SString) diff --git a/data/shared/src/main/scala/sigma/data/CSigmaDslBuilder.scala b/data/shared/src/main/scala/sigma/data/CSigmaDslBuilder.scala index 3938feacd3..4a3842e250 100644 --- a/data/shared/src/main/scala/sigma/data/CSigmaDslBuilder.scala +++ b/data/shared/src/main/scala/sigma/data/CSigmaDslBuilder.scala @@ -11,7 +11,7 @@ import sigma.eval.Extensions.EvalCollOps import sigma.serialization.{GroupElementSerializer, SigmaSerializer} import sigma.util.Extensions.BigIntegerOps import sigma.validation.SigmaValidationSettings -import sigma.{AvlTree, BigInt, Box, Coll, CollBuilder, GroupElement, SigmaDslBuilder, SigmaProp, VersionContext} +import sigma.{AvlTree, BigInt, Box, Coll, CollBuilder, GroupElement, SigmaDslBuilder, SigmaProp, UnsignedBigInt, VersionContext} import java.math.BigInteger @@ -26,6 +26,8 @@ class CSigmaDslBuilder extends SigmaDslBuilder { dsl => override def BigInt(n: BigInteger): BigInt = CBigInt(n) + override def UnsignedBigInt(n: BigInteger): UnsignedBigInt = CUnsignedBigInt(n) + override def toBigInteger(n: BigInt): BigInteger = n.asInstanceOf[CBigInt].wrappedValue /** Wraps the given elliptic curve point into GroupElement type. */ diff --git a/data/shared/src/main/scala/sigma/data/ExactIntegral.scala b/data/shared/src/main/scala/sigma/data/ExactIntegral.scala index 34e2f47f63..70158b828f 100644 --- a/data/shared/src/main/scala/sigma/data/ExactIntegral.scala +++ b/data/shared/src/main/scala/sigma/data/ExactIntegral.scala @@ -2,7 +2,7 @@ package sigma.data import sigma.util.Extensions.{ByteOps, ShortOps} -/** Type-class which defines the operations on Integral types (Byte, Short, Int, Long, BigInt) +/** Type-class which defines the operations on Integral types (Byte, Short, Int, Long, BigInt, UnsignedBigInt) * with overflow checks. * * An exception is raised when an overflow is detected. diff --git a/data/shared/src/main/scala/sigma/data/UnsignedBigIntegerOps.scala b/data/shared/src/main/scala/sigma/data/UnsignedBigIntegerOps.scala new file mode 100644 index 0000000000..77b4a339e4 --- /dev/null +++ b/data/shared/src/main/scala/sigma/data/UnsignedBigIntegerOps.scala @@ -0,0 +1,98 @@ +package sigma.data + +import sigma._ +import sigma.data.UnsignedBigIntOrderingOps.UnsignedBigIntOrdering +import sigma.eval.Extensions.IntExt + +import scala.math.{Integral, Ordering} + +object UnsignedBigIntOrderingOps { + def apply[T](implicit ord: Ordering[T]) = ord + + trait UnsignedBigIntOrdering extends Ordering[UnsignedBigInt] { + def compare(x: UnsignedBigInt, y: UnsignedBigInt) = x.compareTo(y) + } + implicit object UnsignedBigIntOrdering extends UnsignedBigIntOrdering +} + +object UnsignedBigIntNumericOps { + + /** Base implementation of Integral methods for UnsignedBigInt. */ + trait UnsignedBigIntIsIntegral extends Integral[UnsignedBigInt] { + /** This method should not be used in v4.x */ + def quot(x: UnsignedBigInt, y: UnsignedBigInt): UnsignedBigInt = x.divide(y) + + /** This method is used in ErgoTreeEvaluator based interpreter, to implement + * '%' operation of ErgoTree (i.e. `%: (T, T) => T` operation) for all + * numeric types T including BigInt. + * + * In the v4.x interpreter, however, the `%` operation is implemented using + * [[CBigInt]].mod method , which delegates to [[java.math.BigInteger]].mod method. + * + * Even though this method is called `rem`, the semantics of ErgoTree + * language requires it to correspond to [[java.math.BigInteger]].mod + * method. + * + * For this reason we define implementation of this `rem` method using + * [[BigInt]].mod. + * + * NOTE: This method should not be used in v4.x + */ + def rem(x: UnsignedBigInt, y: UnsignedBigInt): UnsignedBigInt = x.mod(y) + + def plus(x: UnsignedBigInt, y: UnsignedBigInt): UnsignedBigInt = x.add(y) + def minus(x: UnsignedBigInt, y: UnsignedBigInt): UnsignedBigInt = x.subtract(y) + def times(x: UnsignedBigInt, y: UnsignedBigInt): UnsignedBigInt = x.multiply(y) + def negate(x: UnsignedBigInt): UnsignedBigInt = ??? + def fromInt(x: Int): UnsignedBigInt = x.toUnsignedBigInt + def toInt(x: UnsignedBigInt): Int = x.toInt + def toLong(x: UnsignedBigInt): Long = x.toLong + def toFloat(x: UnsignedBigInt): Float = ??? + def toDouble(x: UnsignedBigInt): Double = ??? + } + + /** The instance of Integral for BigInt. + * + * Note: ExactIntegral was not defined for [[sigma.BigInt]] in v4.x. + * This is because arithmetic BigInt operations were handled in a special way + * (see `case op: ArithOp[t] if op.tpe == SBigInt =>` in RuntimeCosting.scala). + * As result [[scalan.primitives.UnBinOps.ApplyBinOp]] nodes were not created for + * BigInt operations in v4.x., and hence operation descriptors such as + * [[scalan.primitives.NumericOps.IntegralDivide]] and + * [[scalan.primitives.NumericOps.IntegralMod]] were not used for BigInt. + * NOTE: this instance is used in the new v5.0 interpreter. + */ + object UnsignedBigIntIsIntegral extends UnsignedBigIntIsIntegral with UnsignedBigIntOrdering { + def parseString(str: String): Option[UnsignedBigInt] = ??? + } + + /** The instance of [[ExactIntegral]] typeclass for [[BigInt]]. */ + implicit object UnsignedBigIntIsExactIntegral extends ExactIntegral[UnsignedBigInt] { + val n = UnsignedBigIntIsIntegral + override def plus(x: UnsignedBigInt, y: UnsignedBigInt): UnsignedBigInt = n.plus(x, y) + override def minus(x: UnsignedBigInt, y: UnsignedBigInt): UnsignedBigInt = n.minus(x, y) + override def times(x: UnsignedBigInt, y: UnsignedBigInt): UnsignedBigInt = n.times(x, y) + + override def quot(x: UnsignedBigInt, y: UnsignedBigInt): UnsignedBigInt = x.divide(y) + + /** This method is used in ErgoTreeEvaluator based interpreter, to implement + * '%' operation of ErgoTree (i.e. `%: (T, T) => T` operation) for all + * numeric types T including BigInt. + * + * In the v4.x interpreter, however, the `%` operation is implemented using + * [[CBigInt]].mod method, which delegates to [[java.math.BigInteger]].mod method. + * + * Even though this method is called `divisionRemainder`, the semantics of ErgoTree + * language requires it to correspond to [[java.math.BigInteger]].mod method. + * + * For this reason we define implementation of this method using [[BigInt]].mod. + * + * NOTE: This method should not be used in v4.x + */ + override def divisionRemainder(x: UnsignedBigInt, y: UnsignedBigInt): UnsignedBigInt = x.mod(y) + } + + /** The instance of [[scalan.ExactOrdering]] typeclass for [[BigInt]]. */ + implicit object UnsignedBigIntIsExactOrdering extends ExactOrderingImpl[UnsignedBigInt](UnsignedBigIntIsIntegral) +} + diff --git a/data/shared/src/main/scala/sigma/eval/Extensions.scala b/data/shared/src/main/scala/sigma/eval/Extensions.scala index def9086e02..520d97377d 100644 --- a/data/shared/src/main/scala/sigma/eval/Extensions.scala +++ b/data/shared/src/main/scala/sigma/eval/Extensions.scala @@ -2,7 +2,7 @@ package sigma.eval import sigma.ast.syntax.SigmaPropValue import sigma.data.{CAnyValue, CSigmaDslBuilder, Nullable, RType, SigmaBoolean} -import sigma.{BigInt, Coll, Colls, Evaluation, Platform} +import sigma.{BigInt, Coll, Colls, Evaluation, Platform, UnsignedBigInt} import sigma.ast.{Constant, ConstantNode, SBoolean, SCollection, SCollectionType, SType, SigmaPropConstant, SigmaPropIsProven, TransformingSigmaBuilder, Value} import java.math.BigInteger @@ -19,6 +19,7 @@ object Extensions { implicit class IntExt(val x: Int) extends AnyVal { /** Convert this value to BigInt. */ @inline def toBigInt: BigInt = CSigmaDslBuilder.BigInt(BigInteger.valueOf(x.toLong)) + @inline def toUnsignedBigInt: UnsignedBigInt = CSigmaDslBuilder.UnsignedBigInt(BigInteger.valueOf(x.toLong)) } implicit class LongExt(val x: Long) extends AnyVal { diff --git a/interpreter/shared/src/test/scala/sigmastate/crypto/BigIntSpecification.scala b/interpreter/shared/src/test/scala/sigmastate/crypto/BigIntSpecification.scala new file mode 100644 index 0000000000..2662ff0a7a --- /dev/null +++ b/interpreter/shared/src/test/scala/sigmastate/crypto/BigIntSpecification.scala @@ -0,0 +1,9 @@ +package sigmastate.crypto + +import org.scalatest.propspec.AnyPropSpec +import org.scalatestplus.scalacheck.ScalaCheckPropertyChecks +import sigmastate.TestsBase + +class BigIntSpecification extends AnyPropSpec with ScalaCheckPropertyChecks with TestsBase { + +} diff --git a/sc/shared/src/main/scala/sigmastate/eval/GraphBuilding.scala b/sc/shared/src/main/scala/sigmastate/eval/GraphBuilding.scala index 5ddcdfa946..e06e37272e 100644 --- a/sc/shared/src/main/scala/sigmastate/eval/GraphBuilding.scala +++ b/sc/shared/src/main/scala/sigmastate/eval/GraphBuilding.scala @@ -14,6 +14,7 @@ import sigma.data.{CSigmaDslBuilder, ExactIntegral, ExactNumeric, ExactOrdering, import sigma.util.Extensions.ByteOps import sigmastate.interpreter.Interpreter.ScriptEnv import sigma.ast.{Ident, Select, Val} +import sigma.data.UnsignedBigIntNumericOps.{UnsignedBigIntIsExactIntegral, UnsignedBigIntIsExactOrdering} import sigma.exceptions.GraphBuildingException import sigma.serialization.OpCodes @@ -30,6 +31,7 @@ import scala.collection.mutable.ArrayBuffer trait GraphBuilding extends SigmaLibrary { IR: IRContext => import AvlTree._ import BigInt._ + import UnsignedBigInt._ import Box._ import Coll._ import CollBuilder._ @@ -255,6 +257,7 @@ trait GraphBuilding extends SigmaLibrary { IR: IRContext => case SString => StringElement case SAny => AnyElement case SBigInt => bigIntElement + case SUnsignedBigInt => unsignedBigIntElement case SBox => boxElement case SContext => contextElement case SGlobal => sigmaDslBuilderElement @@ -281,6 +284,7 @@ trait GraphBuilding extends SigmaLibrary { IR: IRContext => case StringElement => SString case AnyElement => SAny case _: BigIntElem[_] => SBigInt + case _: UnsignedBigIntElem[_] => SUnsignedBigInt case _: GroupElementElem[_] => SGroupElement case _: AvlTreeElem[_] => SAvlTree case oe: WOptionElem[_, _] => SOption(elemToSType(oe.eItem)) @@ -308,6 +312,7 @@ trait GraphBuilding extends SigmaLibrary { IR: IRContext => case StringElement => StringIsLiftable case UnitElement => UnitIsLiftable case _: BigIntElem[_] => LiftableBigInt + case _: UnsignedBigIntElem[_] => LiftableUnsignedBigInt case _: GroupElementElem[_] => LiftableGroupElement case ce: CollElem[t,_] => implicit val lt = liftableFromElem[t](ce.eItem) @@ -328,7 +333,8 @@ trait GraphBuilding extends SigmaLibrary { IR: IRContext => (ShortElement, ShortIsExactIntegral), (IntElement, IntIsExactIntegral), (LongElement, LongIsExactIntegral), - (bigIntElement, BigIntIsExactIntegral) + (bigIntElement, BigIntIsExactIntegral), + (unsignedBigIntElement, UnsignedBigIntIsExactIntegral) ) private lazy val elemToExactIntegralMap = Map[Elem[_], ExactIntegral[_]]( (ByteElement, ByteIsExactIntegral), @@ -341,7 +347,8 @@ trait GraphBuilding extends SigmaLibrary { IR: IRContext => (ShortElement, ShortIsExactOrdering), (IntElement, IntIsExactOrdering), (LongElement, LongIsExactOrdering), - (bigIntElement, BigIntIsExactOrdering) + (bigIntElement, BigIntIsExactOrdering), + (unsignedBigIntElement, UnsignedBigIntIsExactOrdering) ) /** @return [[ExactNumeric]] instance for the given type */ @@ -439,6 +446,10 @@ trait GraphBuilding extends SigmaLibrary { IR: IRContext => assert(tpe == SBigInt) val resV = liftConst(bi) resV + case ubi: SUnsignedBigInt => + assert(tpe == SUnsignedBigInt) + val resV = liftConst(ubi) + resV case p: SGroupElement => assert(tpe == SGroupElement) val resV = liftConst(p) diff --git a/sc/shared/src/main/scala/special/sigma/SigmaDslUnit.scala b/sc/shared/src/main/scala/special/sigma/SigmaDslUnit.scala index 48548226a5..4984f2f35d 100644 --- a/sc/shared/src/main/scala/special/sigma/SigmaDslUnit.scala +++ b/sc/shared/src/main/scala/special/sigma/SigmaDslUnit.scala @@ -12,6 +12,15 @@ package sigma { def min(that: Ref[BigInt]): Ref[BigInt]; def max(that: Ref[BigInt]): Ref[BigInt]; }; + trait UnsignedBigInt extends Def[UnsignedBigInt] { + def add(that: Ref[UnsignedBigInt]): Ref[UnsignedBigInt]; + def subtract(that: Ref[UnsignedBigInt]): Ref[UnsignedBigInt]; + def multiply(that: Ref[UnsignedBigInt]): Ref[UnsignedBigInt]; + def divide(that: Ref[UnsignedBigInt]): Ref[UnsignedBigInt]; + def mod(m: Ref[UnsignedBigInt]): Ref[UnsignedBigInt]; + def min(that: Ref[UnsignedBigInt]): Ref[UnsignedBigInt]; + def max(that: Ref[UnsignedBigInt]): Ref[UnsignedBigInt]; + }; trait GroupElement extends Def[GroupElement] { def exp(k: Ref[BigInt]): Ref[GroupElement]; def multiply(that: Ref[GroupElement]): Ref[GroupElement]; diff --git a/sc/shared/src/main/scala/special/sigma/impl/SigmaDslImpl.scala b/sc/shared/src/main/scala/special/sigma/impl/SigmaDslImpl.scala index 70fb35c329..fb4360e05c 100644 --- a/sc/shared/src/main/scala/special/sigma/impl/SigmaDslImpl.scala +++ b/sc/shared/src/main/scala/special/sigma/impl/SigmaDslImpl.scala @@ -263,6 +263,159 @@ object BigInt extends EntityObject("BigInt") { } // of object BigInt registerEntityObject("BigInt", BigInt) +object UnsignedBigInt extends EntityObject("UnsignedBigInt") { + import Liftables._ + + type SUnsignedBigInt = sigma.UnsignedBigInt + unsignedBigIntElement + + case class UnsignedBigIntConst(constValue: SUnsignedBigInt) + extends LiftedConst[SUnsignedBigInt, UnsignedBigInt] with UnsignedBigInt + with Def[UnsignedBigInt] with UnsignedBigIntConstMethods { + val liftable: Liftable[SUnsignedBigInt, UnsignedBigInt] = LiftableUnsignedBigInt + val resultType: Elem[UnsignedBigInt] = liftable.eW + } + + trait UnsignedBigIntConstMethods extends UnsignedBigInt { thisConst: Def[_] => + + private val UnsignedBigIntClass = RClass(classOf[UnsignedBigInt]) + + override def add(that: Ref[UnsignedBigInt]): Ref[UnsignedBigInt] = { + asRep[UnsignedBigInt](mkMethodCall(self, + UnsignedBigIntClass.getMethod("add", classOf[Sym]), + Array[AnyRef](that), + true, false, element[UnsignedBigInt])) + } + + override def subtract(that: Ref[UnsignedBigInt]): Ref[UnsignedBigInt] = { + asRep[UnsignedBigInt](mkMethodCall(self, + UnsignedBigIntClass.getMethod("subtract", classOf[Sym]), + Array[AnyRef](that), + true, false, element[UnsignedBigInt])) + } + + override def multiply(that: Ref[UnsignedBigInt]): Ref[UnsignedBigInt] = { + asRep[UnsignedBigInt](mkMethodCall(self, + UnsignedBigIntClass.getMethod("multiply", classOf[Sym]), + Array[AnyRef](that), + true, false, element[UnsignedBigInt])) + } + + override def divide(that: Ref[UnsignedBigInt]): Ref[UnsignedBigInt] = { + asRep[UnsignedBigInt](mkMethodCall(self, + UnsignedBigIntClass.getMethod("divide", classOf[Sym]), + Array[AnyRef](that), + true, false, element[UnsignedBigInt])) + } + + override def mod(m: Ref[UnsignedBigInt]): Ref[UnsignedBigInt] = { + asRep[UnsignedBigInt](mkMethodCall(self, + UnsignedBigIntClass.getMethod("mod", classOf[Sym]), + Array[AnyRef](m), + true, false, element[UnsignedBigInt])) + } + + override def min(that: Ref[UnsignedBigInt]): Ref[UnsignedBigInt] = { + asRep[UnsignedBigInt](mkMethodCall(self, + UnsignedBigIntClass.getMethod("min", classOf[Sym]), + Array[AnyRef](that), + true, false, element[UnsignedBigInt])) + } + + override def max(that: Ref[UnsignedBigInt]): Ref[UnsignedBigInt] = { + asRep[UnsignedBigInt](mkMethodCall(self, + UnsignedBigIntClass.getMethod("max", classOf[Sym]), + Array[AnyRef](that), + true, false, element[UnsignedBigInt])) + } + } + + + implicit object LiftableUnsignedBigInt extends Liftable[SUnsignedBigInt, UnsignedBigInt] { + lazy val eW: Elem[UnsignedBigInt] = unsignedBigIntElement + lazy val sourceType: RType[SUnsignedBigInt] = { + RType[SUnsignedBigInt] + } + + def lift(x: SUnsignedBigInt): Ref[UnsignedBigInt] = UnsignedBigIntConst(x) + } + + private val UnsignedBigIntClass = RClass(classOf[UnsignedBigInt]) + + // entityAdapter for BigInt trait + case class UnsignedBigIntAdapter(source: Ref[UnsignedBigInt]) + extends Node with UnsignedBigInt + with Def[UnsignedBigInt] { + val resultType: Elem[UnsignedBigInt] = element[UnsignedBigInt] + + override def transform(t: Transformer) = UnsignedBigIntAdapter(t(source)) + + def add(that: Ref[UnsignedBigInt]): Ref[UnsignedBigInt] = { + asRep[UnsignedBigInt](mkMethodCall(source, + UnsignedBigIntClass.getMethod("add", classOf[Sym]), + Array[AnyRef](that), + true, true, element[UnsignedBigInt])) + } + + def subtract(that: Ref[UnsignedBigInt]): Ref[UnsignedBigInt] = { + asRep[UnsignedBigInt](mkMethodCall(source, + UnsignedBigIntClass.getMethod("subtract", classOf[Sym]), + Array[AnyRef](that), + true, true, element[UnsignedBigInt])) + } + + def multiply(that: Ref[UnsignedBigInt]): Ref[UnsignedBigInt] = { + asRep[UnsignedBigInt](mkMethodCall(source, + UnsignedBigIntClass.getMethod("multiply", classOf[Sym]), + Array[AnyRef](that), + true, true, element[UnsignedBigInt])) + } + + def divide(that: Ref[UnsignedBigInt]): Ref[UnsignedBigInt] = { + asRep[UnsignedBigInt](mkMethodCall(source, + UnsignedBigIntClass.getMethod("divide", classOf[Sym]), + Array[AnyRef](that), + true, true, element[UnsignedBigInt])) + } + + def mod(m: Ref[UnsignedBigInt]): Ref[UnsignedBigInt] = { + asRep[UnsignedBigInt](mkMethodCall(source, + UnsignedBigIntClass.getMethod("mod", classOf[Sym]), + Array[AnyRef](m), + true, true, element[UnsignedBigInt])) + } + + def min(that: Ref[UnsignedBigInt]): Ref[UnsignedBigInt] = { + asRep[UnsignedBigInt](mkMethodCall(source, + UnsignedBigIntClass.getMethod("min", classOf[Sym]), + Array[AnyRef](that), + true, true, element[UnsignedBigInt])) + } + + def max(that: Ref[UnsignedBigInt]): Ref[UnsignedBigInt] = { + asRep[UnsignedBigInt](mkMethodCall(source, + UnsignedBigIntClass.getMethod("max", classOf[Sym]), + Array[AnyRef](that), + true, true, element[UnsignedBigInt])) + } + } + + class UnsignedBigIntElem[To <: UnsignedBigInt] + extends EntityElem[To] { + override val liftable: Liftables.Liftable[_, To] = asLiftable[SUnsignedBigInt, To](LiftableUnsignedBigInt) + + override protected def collectMethods: Map[RMethod, MethodDesc] = { + super.collectMethods ++ + Elem.declaredMethods(RClass(classOf[UnsignedBigInt]), RClass(classOf[UnsignedBigInt]), Set( + "add", "subtract", "multiply", "divide", "mod", "min", "max" + )) + } + } + + implicit lazy val unsignedBigIntElement: Elem[UnsignedBigInt] = new UnsignedBigIntElem[UnsignedBigInt] +} // of object BigInt + registerEntityObject("UnsignedBigInt", UnsignedBigInt) + object GroupElement extends EntityObject("GroupElement") { // entityConst: single const for each entity import Liftables._ diff --git a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala index 79701d6e07..621e32ad3f 100644 --- a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala @@ -2,14 +2,17 @@ package sigmastate.utxo import org.ergoplatform.ErgoBox.{AdditionalRegisters, R6, R8} import org.ergoplatform._ +import scorex.util.encode.Base16 import sigma.Extensions.ArrayOps +import sigma.GroupElement +import sigma.VersionContext.V6SoftForkVersion import sigma.ast.SCollection.SByteArray import sigma.ast.SType.AnyOps -import sigma.data.{AvlTreeData, CAnyValue, CSigmaDslBuilder} +import sigma.data.{AvlTreeData, CAnyValue, CBigInt, CGroupElement, CSigmaDslBuilder} import sigma.util.StringUtil._ import sigma.ast._ import sigma.ast.syntax._ -import sigma.crypto.CryptoConstants +import sigma.crypto.{CryptoConstants, SecP256K1Group} import sigmastate._ import sigmastate.helpers.TestingHelpers._ import sigmastate.helpers.{CompilerTestingCommons, ContextEnrichingTestProvingInterpreter, ErgoLikeContextTesting, ErgoLikeTestInterpreter} @@ -22,6 +25,8 @@ import sigma.exceptions.InvalidType import sigmastate.utils.Helpers._ import java.math.BigInteger +import java.security.SecureRandom +import scala.annotation.tailrec class BasicOpsSpecification extends CompilerTestingCommons with CompilerCrossVersionProps { @@ -135,6 +140,111 @@ class BasicOpsSpecification extends CompilerTestingCommons flexVerifier.verify(verifyEnv, tree, ctxExt, pr.proof, fakeMessage).get._1 shouldBe true } + property("group order serialization") { + val value = SecP256K1Group.q.divide(new BigInteger("2")) + + def deserTest() = {test("big int - q", env, ext, + s"{ val b = bigInt(\"${value.toString}\"); b > 1 }", + null, + true + )} + + if (activatedVersionInTests < V6SoftForkVersion) { + deserTest() + } else { + deserTest() + } + } + + property("restoring unsigned 256 bits") { + val b = new BigInteger("92805629300808893548929804498612226467505866636839045998233220279839291898608") + val ub = new BigInteger(1, b.toByteArray) + + def deserTest() = {test("restoring", env, ext, + s"{ val b = unsignedBigInt(\"${ub.toString}\"); b > 1 }", + null, + true + )} + + deserTest() + } + + property("signed <-> unsigned bigint conversion") { + + } + + property("schnorr sig check") { + + val g = CGroupElement(SecP256K1Group.generator) + + def randBigInt: BigInt = { + val random = new SecureRandom() + val values = new Array[Byte](32) + random.nextBytes(values) + BigInt(values).mod(SecP256K1Group.q) + } + + @tailrec + def sign(msg: Array[Byte], secretKey: BigInt): (GroupElement, BigInt) = { + val r = randBigInt + + val a: GroupElement = g.exp(CBigInt(r.bigInteger)) + val z = (r + secretKey * BigInt(scorex.crypto.hash.Blake2b256(msg))) % CryptoConstants.groupOrder + + if(z.bitLength > 255) { + println("z: " + z) + (a, z) + } else { + sign(msg,secretKey) + } + } + + val holderSecret = randBigInt + val holderPk = g.exp(CBigInt(holderSecret.bigInteger)) + + val message = Array.fill(5)(1.toByte) + + val (a,z) = sign(message, holderSecret) + + val customExt: Seq[(Byte, EvaluatedValue[_ <: SType])] = Map( + 0.toByte -> GroupElementConstant(holderPk), + 1.toByte -> GroupElementConstant(a), + 2.toByte -> ByteArrayConstant(z.bigInteger.toByteArray) + ).toSeq + + def deserTest() = {test("schnorr", env, customExt, + s"""{ + | + | val g: GroupElement = groupGenerator + | val holder = getVar[GroupElement](0).get + | + | val message = fromBase16("${Base16.encode(message)}") + | val e: Coll[Byte] = blake2b256(message) // weak Fiat-Shamir + | val eInt = byteArrayToBigInt(e) // challenge as big integer + | + | // a of signature in (a, z) + | val a = getVar[GroupElement](1).get + | val aBytes = a.getEncoded + | + | // z of signature in (a, z) + | val zBytes = getVar[Coll[Byte]](2).get + | val z = byteArrayToBigInt(zBytes) + | + | // Signature is valid if g^z = a * x^e + | val properSignature = g.exp(z) == a.multiply(holder.exp(eInt)) + | sigmaProp(properSignature) + |}""".stripMargin, + null, + true + )} + + if (activatedVersionInTests < V6SoftForkVersion) { + deserTest() + } else { + deserTest() + } + } + property("Unit register") { // TODO frontend: implement missing Unit support in compiler // https://github.com/ScorexFoundation/sigmastate-interpreter/issues/820 diff --git a/sc/shared/src/test/scala/sigmastate/utxo/examples/OracleExamplesSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/examples/OracleExamplesSpecification.scala index 9d0ffc880b..8d3d09de74 100644 --- a/sc/shared/src/test/scala/sigmastate/utxo/examples/OracleExamplesSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/utxo/examples/OracleExamplesSpecification.scala @@ -138,7 +138,7 @@ class OracleExamplesSpecification extends CompilerTestingCommons LastBlockUtxoRootHash, SAvlTreeMethods.getMethod, IndexedSeq(ExtractId(GetVarBox(22: Byte).get), GetVarByteArray(23: Byte).get)).asOption[SByteArray]), EQ(extract[SByteArray](ErgoBox.ScriptRegId), ByteArrayConstant(ErgoTree.fromSigmaBoolean(oraclePubKey).bytes)), - EQ(Exponentiate(GroupGenerator, extract[SBigInt.type](reg3)), + EQ(Exponentiate(GroupGenerator, extract[SBigInt.type](reg3)(SBigInt)), MultiplyGroup(extract[SGroupElement.type](reg2), Exponentiate(GroupElementConstant(oraclePubImage.value), ByteArrayToBigInt( From b13cef6d0713821cb7fb31fa2f2bf82bf689fe13 Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Sat, 25 May 2024 00:23:28 +0300 Subject: [PATCH 097/314] failing schnorr sig check w. unsigned --- .../test/scala/sigmastate/utxo/BasicOpsSpecification.scala | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala index 621e32ad3f..28084be987 100644 --- a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala @@ -192,7 +192,6 @@ class BasicOpsSpecification extends CompilerTestingCommons val z = (r + secretKey * BigInt(scorex.crypto.hash.Blake2b256(msg))) % CryptoConstants.groupOrder if(z.bitLength > 255) { - println("z: " + z) (a, z) } else { sign(msg,secretKey) @@ -209,7 +208,7 @@ class BasicOpsSpecification extends CompilerTestingCommons val customExt: Seq[(Byte, EvaluatedValue[_ <: SType])] = Map( 0.toByte -> GroupElementConstant(holderPk), 1.toByte -> GroupElementConstant(a), - 2.toByte -> ByteArrayConstant(z.bigInteger.toByteArray) + 2.toByte -> UnsignedBigIntConstant(z.bigInteger) ).toSeq def deserTest() = {test("schnorr", env, customExt, @@ -227,8 +226,7 @@ class BasicOpsSpecification extends CompilerTestingCommons | val aBytes = a.getEncoded | | // z of signature in (a, z) - | val zBytes = getVar[Coll[Byte]](2).get - | val z = byteArrayToBigInt(zBytes) + | val z = getVar[UnsignedBigInt](2).get | | // Signature is valid if g^z = a * x^e | val properSignature = g.exp(z) == a.multiply(holder.exp(eInt)) From e5a32c8fe2efd772ef3d803e06d76f45d37454b9 Mon Sep 17 00:00:00 2001 From: Alexander Slesarenko Date: Sat, 25 May 2024 10:21:58 +0200 Subject: [PATCH 098/314] i486-toBytes: Versioned.scala added --- .../src/main/scala/sigma/util/Versioned.scala | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 core/shared/src/main/scala/sigma/util/Versioned.scala diff --git a/core/shared/src/main/scala/sigma/util/Versioned.scala b/core/shared/src/main/scala/sigma/util/Versioned.scala new file mode 100644 index 0000000000..a3eae2325a --- /dev/null +++ b/core/shared/src/main/scala/sigma/util/Versioned.scala @@ -0,0 +1,27 @@ +package sigma.util + +import sigma.VersionContext + +import scala.reflect.ClassTag + +/** Represents a versioned object that can be created for each supported version. + * The object is created lazily and cached for each version. + * + * @param builder a total function that creates an object for a given version in [0, + * maxVersion] range. + * @param maxVersion the maximum supported version. + */ +case class Versioned[T <: AnyRef: ClassTag](builder: Byte => T, maxVersion: Byte = VersionContext.MaxSupportedScriptVersion) { + private val cache = new Array[T](maxVersion + 1) + + def get(version: Byte): T = { + require(version <= VersionContext.MaxSupportedScriptVersion, s"Not supported version $version") + if (cache(version) == null) { + val v = builder(version) + cache(version) = v + v + } else { + cache(version) + } + } +} From bba2230da50f1fc4cb1cba8d097138aa9adadf72 Mon Sep 17 00:00:00 2001 From: Alexander Slesarenko Date: Sat, 25 May 2024 10:24:23 +0200 Subject: [PATCH 099/314] i486-toBytes: ensure VersionContext.current in tests --- .../shared/src/test/scala/sigmastate/CrossVersionProps.scala | 2 ++ 1 file changed, 2 insertions(+) diff --git a/interpreter/shared/src/test/scala/sigmastate/CrossVersionProps.scala b/interpreter/shared/src/test/scala/sigmastate/CrossVersionProps.scala index e55b874dc3..87101a1f71 100644 --- a/interpreter/shared/src/test/scala/sigmastate/CrossVersionProps.scala +++ b/interpreter/shared/src/test/scala/sigmastate/CrossVersionProps.scala @@ -31,7 +31,9 @@ trait CrossVersionProps extends AnyPropSpecLike with TestsBase { System.gc() } forEachScriptAndErgoTreeVersion(activatedVersions, ergoTreeVersions) { + VersionContext.withVersions(activatedVersionInTests, ergoTreeVersionInTests) { testFun_Run(testName, testFun) + } } } } From dc361a1469b85365e321285308eb010a155f8234 Mon Sep 17 00:00:00 2001 From: Alexander Slesarenko Date: Sat, 25 May 2024 10:49:51 +0200 Subject: [PATCH 100/314] i486-toBytes: ErgoTreeSpecification versioned and updated --- .../src/main/scala/sigma/ast/SType.scala | 36 +++-- .../src/main/scala/sigma/ast/methods.scala | 27 +++- .../main/scala/sigma/data/BigIntegerOps.scala | 2 +- .../main/scala/sigma/data/ExactIntegral.scala | 8 +- .../main/scala/sigma/data/ExactNumeric.scala | 2 +- .../sigma/compiler/ir/GraphBuilding.scala | 6 + .../sigma/compiler/ir/TreeBuilding.scala | 7 + .../compiler/ir/primitives/NumericOps.scala | 9 ++ .../scala/sigma/LanguageSpecificationV6.scala | 22 +-- .../sigmastate/ErgoTreeSpecification.scala | 145 +++++++++++++----- 10 files changed, 192 insertions(+), 72 deletions(-) diff --git a/core/shared/src/main/scala/sigma/ast/SType.scala b/core/shared/src/main/scala/sigma/ast/SType.scala index f75cbc9e8b..8b386fa729 100644 --- a/core/shared/src/main/scala/sigma/ast/SType.scala +++ b/core/shared/src/main/scala/sigma/ast/SType.scala @@ -7,7 +7,8 @@ import sigma.data.OverloadHack.Overloaded1 import sigma.data.{CBigInt, Nullable, SigmaConstants} import sigma.reflection.{RClass, RMethod, ReflectionData} import sigma.util.Extensions.{IntOps, LongOps, ShortOps} -import sigma.{AvlTree, BigInt, Box, Coll, Context, Evaluation, GroupElement, Header, PreHeader, SigmaDslBuilder, SigmaProp} +import sigma.util.Versioned +import sigma.{AvlTree, BigInt, Box, Coll, Context, Evaluation, GroupElement, Header, PreHeader, SigmaDslBuilder, SigmaProp, VersionContext} import java.math.BigInteger @@ -113,27 +114,40 @@ object SType { * typeId this map contains a companion object which can be used to access the list of * corresponding methods. * - * NOTE: in the current implementation only monomorphic methods are supported (without - * type parameters) + * @note starting from v6.0 methods with type parameters are also supported. * - * NOTE2: in v3.x SNumericType.typeId is silently shadowed by SGlobal.typeId as part of + * @note on versioning: + * In v3.x-5.x SNumericType.typeId is silently shadowed by SGlobal.typeId as part of * `toMap` operation. As a result, the methods collected into SByte.methods cannot be * resolved (using SMethod.fromIds()) for all numeric types (SByte, SShort, SInt, * SLong, SBigInt). See the corresponding regression `property("MethodCall on numerics")`. * However, this "shadowing" is not a problem since all casting methods are implemented * via Downcast, Upcast opcodes and the remaining `toBytes`, `toBits` methods are not * implemented at all. - * In order to allow MethodCalls on numeric types in future versions the SNumericType.typeId - * should be changed and SGlobal.typeId should be preserved. The regression tests in - * `property("MethodCall Codes")` should pass. + * + * Starting from v6.0 the SNumericType.typeId is not used as receiver of object of + * method call, instead, all methods from SNumericTypeMethods are copied to all the + * concrete numeric types (SByte, SShort, SInt, SLong, SBigInt) and the generic tNum + * type parameter is specialized accordingly. This difference in behaviour is tested by + * `property("MethodCall on numerics")`. + * + * The regression tests in `property("MethodCall Codes")` should pass. */ // TODO v6.0: should contain all numeric types (including also SNumericType) // to support method calls like 10.toByte which encoded as MethodCall with typeId = 4, methodId = 1 // see https://github.com/ScorexFoundation/sigmastate-interpreter/issues/667 - lazy val types: Map[Byte, STypeCompanion] = Seq( - SBoolean, SNumericType, SString, STuple, SGroupElement, SSigmaProp, SContext, SGlobal, SHeader, SPreHeader, - SAvlTree, SBox, SOption, SCollection, SBigInt - ).map { t => (t.typeId, t) }.toMap + private val _types: Versioned[Map[Byte, STypeCompanion]] = Versioned({ version => + val v5x = Seq( + SBoolean, SString, STuple, SGroupElement, SSigmaProp, SContext, SGlobal, SHeader, SPreHeader, + SAvlTree, SBox, SOption, SCollection, SBigInt + ) + val v6 = if (version >= VersionContext.V6SoftForkVersion) + Seq(SByte, SShort, SInt, SLong) + else + Seq.empty + (v5x ++ v6).map { t => (t.typeId, t) }.toMap + }) + def types: Map[Byte, STypeCompanion] = _types.get(VersionContext.current.activatedVersion) /** Checks that the type of the value corresponds to the descriptor `tpe`. * If the value has complex structure only root type constructor is checked. diff --git a/data/shared/src/main/scala/sigma/ast/methods.scala b/data/shared/src/main/scala/sigma/ast/methods.scala index 3f27f85e2d..c53a9b84c7 100644 --- a/data/shared/src/main/scala/sigma/ast/methods.scala +++ b/data/shared/src/main/scala/sigma/ast/methods.scala @@ -13,6 +13,7 @@ import sigma.data.{DataValueComparer, KeyValueColl, Nullable, RType, SigmaConsta import sigma.eval.{CostDetails, ErgoTreeEvaluator, TracedCost} import sigma.reflection.RClass import sigma.serialization.CoreByteWriter.ArgInfo +import sigma.util.Versioned import sigma.utils.SparseArrayContainer import scala.annotation.unused @@ -157,11 +158,23 @@ trait MonoTypeMethods extends MethodsContainer { trait SNumericTypeMethods extends MonoTypeMethods { import SNumericTypeMethods.tNum - protected override def getMethods(): Seq[SMethod] = { - super.getMethods() ++ SNumericTypeMethods.methods.map { - m => m.copy(stype = applySubst(m.stype, Map(tNum -> this.ownerType)).asFunc) - } - } + private val _getMethods = Versioned({ version => + val subst = Map(tNum -> this.ownerType) + val numericMethods = if (version < VersionContext.V6SoftForkVersion) + SNumericTypeMethods.methods.map { m => + m.copy(stype = applySubst(m.stype, subst).asFunc ) + } + else + SNumericTypeMethods.methods.map { m => + m.copy( + objType = this, // associate the method with the concrete numeric type + stype = applySubst(m.stype, subst).asFunc + )} + super.getMethods() ++ numericMethods + }) + + protected override def getMethods(): Seq[SMethod] = + _getMethods.get(VersionContext.current.activatedVersion) } object SNumericTypeMethods extends MethodsContainer { @@ -313,8 +326,8 @@ case object SBigIntMethods extends SNumericTypeMethods { final val ToNBitsCostInfo = OperationCostInfo( FixedCost(JitCost(5)), NamedDesc("NBitsMethodCall")) - //id = 8 to make it after toBits - val ToNBits = SMethod(this, "nbits", SFunc(this.ownerType, SLong), 8, ToNBitsCostInfo.costKind) + //id = 20 to make it after toBits and reserve space for future methods at SNumericTypeMethods + val ToNBits = SMethod(this, "nbits", SFunc(this.ownerType, SLong), 20, ToNBitsCostInfo.costKind) .withInfo(ModQ, "Encode this big integer value as NBits") /** The following `modQ` methods are not fully implemented in v4.x and this descriptors. diff --git a/data/shared/src/main/scala/sigma/data/BigIntegerOps.scala b/data/shared/src/main/scala/sigma/data/BigIntegerOps.scala index b93334daf6..0bb9e9101b 100644 --- a/data/shared/src/main/scala/sigma/data/BigIntegerOps.scala +++ b/data/shared/src/main/scala/sigma/data/BigIntegerOps.scala @@ -91,7 +91,7 @@ object NumericOps { */ override def divisionRemainder(x: BigInt, y: BigInt): BigInt = x.mod(y) - override def toBytes(x: BigInt): Coll[Byte] = Colls.fromArray(x.toBigInteger.toByteArray) + override def toBigEndianBytes(x: BigInt): Coll[Byte] = Colls.fromArray(x.toBigInteger.toByteArray) } /** The instance of [[scalan.ExactOrdering]] typeclass for [[BigInt]]. */ diff --git a/data/shared/src/main/scala/sigma/data/ExactIntegral.scala b/data/shared/src/main/scala/sigma/data/ExactIntegral.scala index b207a1794d..eaf89947c1 100644 --- a/data/shared/src/main/scala/sigma/data/ExactIntegral.scala +++ b/data/shared/src/main/scala/sigma/data/ExactIntegral.scala @@ -38,7 +38,7 @@ object ExactIntegral { override def plus(x: Byte, y: Byte): Byte = x.addExact(y) override def minus(x: Byte, y: Byte): Byte = x.subtractExact(y) override def times(x: Byte, y: Byte): Byte = x.multiplyExact(y) - override def toBytes(x: Byte): Coll[Byte] = Colls.fromItems(x) + override def toBigEndianBytes(x: Byte): Coll[Byte] = Colls.fromItems(x) } implicit object ShortIsExactIntegral extends ExactIntegral[Short] { @@ -46,7 +46,7 @@ object ExactIntegral { override def plus(x: Short, y: Short): Short = x.addExact(y) override def minus(x: Short, y: Short): Short = x.subtractExact(y) override def times(x: Short, y: Short): Short = x.multiplyExact(y) - override def toBytes(x: Short): Coll[Byte] = Colls.fromItems((x >> 8).toByte, x.toByte) + override def toBigEndianBytes(x: Short): Coll[Byte] = Colls.fromItems((x >> 8).toByte, x.toByte) } implicit object IntIsExactIntegral extends ExactIntegral[Int] { @@ -54,7 +54,7 @@ object ExactIntegral { override def plus(x: Int, y: Int): Int = java7.compat.Math.addExact(x, y) override def minus(x: Int, y: Int): Int = java7.compat.Math.subtractExact(x, y) override def times(x: Int, y: Int): Int = java7.compat.Math.multiplyExact(x, y) - override def toBytes(x: Int): Coll[Byte] = + override def toBigEndianBytes(x: Int): Coll[Byte] = Colls.fromItems((x >> 24).toByte, (x >> 16).toByte, (x >> 8).toByte, x.toByte) } @@ -63,7 +63,7 @@ object ExactIntegral { override def plus(x: Long, y: Long): Long = java7.compat.Math.addExact(x, y) override def minus(x: Long, y: Long): Long = java7.compat.Math.subtractExact(x, y) override def times(x: Long, y: Long): Long = java7.compat.Math.multiplyExact(x, y) - override def toBytes(x: Long): Coll[Byte] = + override def toBigEndianBytes(x: Long): Coll[Byte] = Colls.fromItems((x >> 56).toByte, (x >> 48).toByte, (x >> 40).toByte, (x >> 32).toByte, (x >> 24).toByte, (x >> 16).toByte, (x >> 8).toByte, x.toByte) } } diff --git a/data/shared/src/main/scala/sigma/data/ExactNumeric.scala b/data/shared/src/main/scala/sigma/data/ExactNumeric.scala index fef951b4d7..d8b3b5df0d 100644 --- a/data/shared/src/main/scala/sigma/data/ExactNumeric.scala +++ b/data/shared/src/main/scala/sigma/data/ExactNumeric.scala @@ -35,7 +35,7 @@ trait ExactNumeric[T] { * For example, the `Int` value `0x12131415` would yield the * collection of bytes [0x12, 0x13, 0x14, 0x15] */ - def toBytes(x: T): Coll[Byte] + def toBigEndianBytes(x: T): Coll[Byte] /** A value of type T which corresponds to integer 0. */ lazy val zero: T = fromInt(0) 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 a6a244778e..c34d91b41a 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/GraphBuilding.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/GraphBuilding.scala @@ -1151,6 +1151,12 @@ trait GraphBuilding extends Base with DefRewriting { IR: IRContext => g.serialize(value) case _ => throwError } + case (x: Ref[tNum], SNumericTypeMethods) => method.name match { + case SNumericTypeMethods.ToBytesMethod.name => + val op = NumericToBigEndianBytes(elemToExactNumeric(x.elem)) + ApplyUnOp(op, x) + case _ => throwError + } case _ => throwError } diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/TreeBuilding.scala b/sc/shared/src/main/scala/sigma/compiler/ir/TreeBuilding.scala index 725e3b1d19..655010dbc5 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/TreeBuilding.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/TreeBuilding.scala @@ -106,6 +106,13 @@ trait TreeBuilding extends Base { IR: IRContext => object IsNumericUnOp { def unapply(op: UnOp[_,_]): Option[SValue => SValue] = op match { case NumericNegate(_) => Some({ v: SValue => builder.mkNegation(v.asNumValue) }) + case NumericToBigEndianBytes(_) => + val mkNode = { v: SValue => + val specMethod = SNumericTypeMethods.ToBytesMethod + .withConcreteTypes(Map(SNumericTypeMethods.tNum -> v.tpe)) + builder.mkMethodCall(v.asNumValue, specMethod, IndexedSeq.empty) + } + Some(mkNode) case _ => None } } diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/primitives/NumericOps.scala b/sc/shared/src/main/scala/sigma/compiler/ir/primitives/NumericOps.scala index 4e732bbb5f..ef4124d0b5 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/primitives/NumericOps.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/primitives/NumericOps.scala @@ -14,6 +14,7 @@ trait NumericOps extends Base { self: IRContext => def unary_- : Ref[T] = NumericNegate(n)(x.elem).apply(x) def toInt: Ref[Int] = NumericToInt(n).apply(x) def toLong: Ref[Long] = NumericToLong(n).apply(x) + def toBigEndianBytes: Ref[Coll[Byte]] = NumericToBigEndianBytes(n).apply(x) } /** Extension methods over `Ref[T]` where T is instance of ExactIntegral type-class. */ @@ -66,6 +67,14 @@ trait NumericOps extends Base { self: IRContext => override def applySeq(x: T): Long = n.toLong(x) } + import Coll._ + /** Descriptor of unary `ToBigEndianBytes` conversion operation. */ + case class NumericToBigEndianBytes[T](n: ExactNumeric[T]) + extends UnOp[T, Coll[Byte]]("ToBigEndianBytes")(element[Coll[Byte]]) { + override def applySeq(x: T): Coll[Byte] = + n.toBigEndianBytes(x).asInstanceOf[Coll[Byte]] + } + /** Descriptor of binary `/` operation (integral division). */ case class IntegralDivide[T](i: ExactIntegral[T])(implicit elem: Elem[T]) extends DivOp[T]("/", i) { override def applySeq(x: T, y: T): T = i.quot(x, y) diff --git a/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala b/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala index e105e4bee9..ed6b6d5165 100644 --- a/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala +++ b/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala @@ -475,18 +475,18 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite => tree.root shouldBe t2.root } - property("Numeric.toBytes methods equivalence") { - lazy val toBytes = newFeature( - { (x: Byte) => x.toBigEndianBytes }, - "{ (x: Byte) => x.toBytes }", - sinceVersion = VersionContext.V6SoftForkVersion) - val cases = Seq( - (0.toByte, Success(Coll(0.toByte))), - (1.toByte, Success(Coll(1.toByte))) - ) + property("Numeric.toBytes methods equivalence") { + lazy val toBytes = newFeature( + { (x: Byte) => x.toBigEndianBytes }, + "{ (x: Byte) => x.toBytes }", + sinceVersion = VersionContext.V6SoftForkVersion) + val cases = Seq( + (0.toByte, Success(Coll(0.toByte))), + (1.toByte, Success(Coll(1.toByte))) + ) - testCases(cases, toBytes) - } + testCases(cases, toBytes) + } } diff --git a/sc/shared/src/test/scala/sigmastate/ErgoTreeSpecification.scala b/sc/shared/src/test/scala/sigmastate/ErgoTreeSpecification.scala index 7539bd5e48..7a48ec8b45 100644 --- a/sc/shared/src/test/scala/sigmastate/ErgoTreeSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/ErgoTreeSpecification.scala @@ -21,14 +21,14 @@ import sigma.compiler.CompilerSettings import sigma.eval.EvalSettings import sigma.exceptions.{CostLimitException, InterpreterException} import sigma.serialization.ErgoTreeSerializer.DefaultSerializer -import sigmastate.Plus +import sigmastate.{CrossVersionProps, Plus} import sigmastate.utils.Helpers.TryOps /** Regression tests with ErgoTree related test vectors. * This test vectors verify various constants which are consensus critical and should not change. */ -class ErgoTreeSpecification extends SigmaDslTesting with ContractsTestkit { +class ErgoTreeSpecification extends SigmaDslTesting with ContractsTestkit with CrossVersionProps { property("Value.sourceContext") { val srcCtx = SourceContext.fromParserIndex(0, "") @@ -313,37 +313,97 @@ class ErgoTreeSpecification extends SigmaDslTesting with ContractsTestkit { */ case class MInfo(methodId: Byte, method: SMethod, isResolvableFromIds: Boolean = true) + def isV6Activated = VersionContext.current.isV6SoftForkActivated + // NOTE, the type code constants are checked above // The methodId codes as checked here, they MUST be PRESERVED. - // The following table should be made dependent on HF activation - val methods = Table( + // Note, the following table is dependent on SF activation. + def methods = { + import SNumericTypeMethods._ + Table( ("typeId", "methods", "CanHaveMethods"), (SBoolean.typeId, Seq.empty[MInfo], true), - (SByte.typeId, Seq.empty[MInfo], false), - (SShort.typeId, Seq.empty[MInfo], false), - (SInt.typeId, Seq.empty[MInfo], false), - (SLong.typeId, Seq.empty[MInfo], false), - - { // SNumericType.typeId is erroneously shadowed by SGlobal.typeId - // this should be preserved in v3.x and fixed in v4.0 - (SNumericType.typeId, Seq( - MInfo(methodId = 1, SGlobalMethods.groupGeneratorMethod), - MInfo(2, SGlobalMethods.xorMethod) - ), true) + { + if (isV6Activated) + (SByte.typeId, Seq( + MInfo(methodId = 1, ToByteMethod), + MInfo(2, ToShortMethod), + MInfo(3, ToIntMethod), + MInfo(4, ToLongMethod), + MInfo(5, ToBigIntMethod), + MInfo(6, ToBytesMethod), + MInfo(7, ToBitsMethod) + ), true) + else + (SByte.typeId, Seq.empty[MInfo], false) + }, + { + if (isV6Activated) + (SShort.typeId, Seq( + MInfo(methodId = 1, ToByteMethod), + MInfo(2, ToShortMethod), + MInfo(3, ToIntMethod), + MInfo(4, ToLongMethod), + MInfo(5, ToBigIntMethod), + MInfo(6, ToBytesMethod), + MInfo(7, ToBitsMethod) + ), true) + else + (SShort.typeId, Seq.empty[MInfo], false) + }, + { + if (isV6Activated) + (SInt.typeId, Seq( + MInfo(methodId = 1, ToByteMethod), + MInfo(2, ToShortMethod), + MInfo(3, ToIntMethod), + MInfo(4, ToLongMethod), + MInfo(5, ToBigIntMethod), + MInfo(6, ToBytesMethod), + MInfo(7, ToBitsMethod) + ), true) + else + (SInt.typeId, Seq.empty[MInfo], false) + }, + { + if (isV6Activated) + (SLong.typeId, Seq( + MInfo(methodId = 1, ToByteMethod), + MInfo(2, ToShortMethod), + MInfo(3, ToIntMethod), + MInfo(4, ToLongMethod), + MInfo(5, ToBigIntMethod), + MInfo(6, ToBytesMethod), + MInfo(7, ToBitsMethod) + ), true) + else + (SLong.typeId, Seq.empty[MInfo], false) }, +// { // SNumericType.typeId is erroneously shadowed by SGlobal.typeId +// // this should be preserved in v3.x and fixed in v4.0 +// (SNumericType.typeId, Seq( +// MInfo(methodId = 1, SGlobalMethods.groupGeneratorMethod), +// MInfo(2, SGlobalMethods.xorMethod) +// ), true) +// }, + { // SBigInt inherit methods from SNumericType.methods - // however they are not resolvable via SBigInt.typeId + // however they are not resolvable via SBigInt.typeId before v6.0 import SNumericTypeMethods._ (SBigInt.typeId, Seq( - MInfo(methodId = 1, ToByteMethod, isResolvableFromIds = false), - MInfo(2, ToShortMethod, isResolvableFromIds = false), - MInfo(3, ToIntMethod, isResolvableFromIds = false), - MInfo(4, ToLongMethod, isResolvableFromIds = false), - MInfo(5, ToBigIntMethod, isResolvableFromIds = false), - MInfo(6, ToBytesMethod, isResolvableFromIds = false), - MInfo(7, ToBitsMethod, isResolvableFromIds = false) - ), true) + MInfo(methodId = 1, ToByteMethod, isResolvableFromIds = if (isV6Activated) true else false), + MInfo(2, ToShortMethod, isResolvableFromIds = if (isV6Activated) true else false), + MInfo(3, ToIntMethod, isResolvableFromIds = if (isV6Activated) true else false), + MInfo(4, ToLongMethod, isResolvableFromIds = if (isV6Activated) true else false), + MInfo(5, ToBigIntMethod, isResolvableFromIds = if (isV6Activated) true else false), + MInfo(6, ToBytesMethod, isResolvableFromIds = if (isV6Activated) true else false), + MInfo(7, ToBitsMethod, isResolvableFromIds = if (isV6Activated) true else false)) ++ + (if (isV6Activated) Seq( + // methods added in v6.0 + MInfo(20, SBigIntMethods.ToNBits) + ) else Seq.empty) + , true) }, { import SGroupElementMethods._ (SGroupElement.typeId, Seq( @@ -419,7 +479,10 @@ class ErgoTreeSpecification extends SigmaDslTesting with ContractsTestkit { { import SGlobalMethods._ (SGlobal.typeId, Seq( MInfo(1, groupGeneratorMethod), MInfo(2, xorMethod) - ), true) + ) ++ (if (isV6Activated) Seq( + // methods added in v6.0 + MInfo(3, serializeMethod) + ) else Seq.empty), true) }, { import SCollectionMethods._ (SCollection.typeId, Seq( @@ -475,7 +538,8 @@ class ErgoTreeSpecification extends SigmaDslTesting with ContractsTestkit { MInfo(8, FilterMethod) ), true) } - ) + ) + } property("MethodCall Codes") { forAll(methods) { (typeId, methods, canHaveMethods) => @@ -508,21 +572,28 @@ class ErgoTreeSpecification extends SigmaDslTesting with ContractsTestkit { assert(!canHaveMethods, s"Type with code $typeId can have methods") } } - } property("MethodCall on numerics") { forAll(Table[STypeCompanion]("type", SByte, SShort, SInt, SLong, SBigInt)) { t => - // this methods are expected to fail resolution in v3.x (but may change in future) - (1 to 7).foreach { methodId => - assertExceptionThrown( - SMethod.fromIds(t.typeId, methodId.toByte), - { - case _: ValidationException => true - case _ => false - }, - s"SMethod mustn't resolve for typeId = ${t.typeId} and methodId = $methodId" - ) + // this methods are expected to fail resolution in before v6.0 + if (!isV6Activated) { + (1 to 7).foreach { methodId => + assertExceptionThrown( + SMethod.fromIds(t.typeId, methodId.toByte), + { + case _: ValidationException => true + case _ => false + }, + s"SMethod mustn't resolve for typeId = ${t.typeId} and methodId = $methodId" + ) + } + } else { + // in v6.0 these codes should resolve to the methods of the concrete numeric type + (1 to 7).foreach { methodId => + val m = SMethod.fromIds(t.typeId, methodId.toByte) + m.objType.ownerType shouldBe t + } } } } From 70786a0c7dcfabc6cf65a92229d44926698785d8 Mon Sep 17 00:00:00 2001 From: Alexander Slesarenko Date: Sat, 25 May 2024 11:22:19 +0200 Subject: [PATCH 101/314] i486-toBytes: clarified description of demotion of SNumericType --- .../src/main/scala/sigma/ast/SType.scala | 29 +++++++++++-------- .../sigmastate/ErgoTreeSpecification.scala | 5 ++++ 2 files changed, 22 insertions(+), 12 deletions(-) diff --git a/core/shared/src/main/scala/sigma/ast/SType.scala b/core/shared/src/main/scala/sigma/ast/SType.scala index 8b386fa729..7143504ca8 100644 --- a/core/shared/src/main/scala/sigma/ast/SType.scala +++ b/core/shared/src/main/scala/sigma/ast/SType.scala @@ -118,24 +118,29 @@ object SType { * * @note on versioning: * In v3.x-5.x SNumericType.typeId is silently shadowed by SGlobal.typeId as part of - * `toMap` operation. As a result, the methods collected into SByte.methods cannot be + * `toMap` operation. As a result, SNumericTypeMethods container cannot be resolved by + * typeId = 106, because SNumericType was being silently removed when `_types` map is + * constructed. See `property("SNumericType.typeId resolves to SGlobal")`. + * In addition, the methods associated with the concrete numeric types cannot be * resolved (using SMethod.fromIds()) for all numeric types (SByte, SShort, SInt, - * SLong, SBigInt). See the corresponding regression `property("MethodCall on numerics")`. + * SLong) because these types are not registered in the `_types` map. + * See the corresponding property("MethodCall on numerics")`. * However, this "shadowing" is not a problem since all casting methods are implemented - * via Downcast, Upcast opcodes and the remaining `toBytes`, `toBits` methods are not - * implemented at all. + * via lowering to Downcast, Upcast opcodes and the remaining `toBytes`, `toBits` + * methods are not implemented at all. * - * Starting from v6.0 the SNumericType.typeId is not used as receiver of object of - * method call, instead, all methods from SNumericTypeMethods are copied to all the - * concrete numeric types (SByte, SShort, SInt, SLong, SBigInt) and the generic tNum - * type parameter is specialized accordingly. This difference in behaviour is tested by - * `property("MethodCall on numerics")`. + * Starting from v6.0 the SNumericType.typeId is demoted as a receiver object of + * method calls and: + * 1) numeric type SByte, SShort, SInt, SLong are promoted as receivers and added to + * the _types map. + * 2) all methods from SNumericTypeMethods are copied to all the concrete numeric types + * (SByte, SShort, SInt, SLong, SBigInt) and the generic tNum type parameter is + * specialized accordingly. + * + * This difference in behaviour is tested by `property("MethodCall on numerics")`. * * The regression tests in `property("MethodCall Codes")` should pass. */ - // TODO v6.0: should contain all numeric types (including also SNumericType) - // to support method calls like 10.toByte which encoded as MethodCall with typeId = 4, methodId = 1 - // see https://github.com/ScorexFoundation/sigmastate-interpreter/issues/667 private val _types: Versioned[Map[Byte, STypeCompanion]] = Versioned({ version => val v5x = Seq( SBoolean, SString, STuple, SGroupElement, SSigmaProp, SContext, SGlobal, SHeader, SPreHeader, diff --git a/sc/shared/src/test/scala/sigmastate/ErgoTreeSpecification.scala b/sc/shared/src/test/scala/sigmastate/ErgoTreeSpecification.scala index 7a48ec8b45..6e6fb824de 100644 --- a/sc/shared/src/test/scala/sigmastate/ErgoTreeSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/ErgoTreeSpecification.scala @@ -541,6 +541,11 @@ class ErgoTreeSpecification extends SigmaDslTesting with ContractsTestkit with C ) } + property("SNumericType.typeId resolves to SGlobal") { + SNumericType.typeId shouldBe SGlobal.typeId + SMethod.fromIds(SNumericType.typeId, 1) shouldBe SGlobalMethods.groupGeneratorMethod + } + property("MethodCall Codes") { forAll(methods) { (typeId, methods, canHaveMethods) => SType.types.get(typeId) match { From c76ac1a484e8d15a1e34469f35f1693e507a0715 Mon Sep 17 00:00:00 2001 From: Alexander Slesarenko Date: Sat, 25 May 2024 13:09:23 +0200 Subject: [PATCH 102/314] i486-toBytes: GraphBuilding to handle numeric methods --- .../sigma/compiler/ir/GraphBuilding.scala | 31 ++++++++++--------- 1 file changed, 16 insertions(+), 15 deletions(-) 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 c34d91b41a..ddbec96518 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/GraphBuilding.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/GraphBuilding.scala @@ -1,6 +1,7 @@ package sigma.compiler.ir import org.ergoplatform._ +import sigma.Evaluation.stypeToRType import sigma.ast.TypeCodes.LastConstantCode import sigma.ast.Value.Typed import sigma.ast.syntax.{SValue, ValueOps} @@ -437,8 +438,8 @@ trait GraphBuilding extends Base with DefRewriting { IR: IRContext => } Nullable(res) }} - def throwError = - error(s"Don't know how to buildNode($node)", node.sourceContext.toOption) + def throwError(clue: String = "") = + error((if (clue.nonEmpty) clue + ": " else "") + s"Don't know how to buildNode($node)", node.sourceContext.toOption) val res: Ref[Any] = node match { case Constant(v, tpe) => v match { @@ -985,7 +986,7 @@ trait GraphBuilding extends Base with DefRewriting { IR: IRContext => val i = asRep[Int](argsV(0)) val d = asRep[t](argsV(1)) xs.getOrElse(i, d) - case _ => throwError + case _ => throwError() } case (opt: ROption[t]@unchecked, SOptionMethods) => method.name match { case SOptionMethods.GetMethod.name => @@ -999,7 +1000,7 @@ trait GraphBuilding extends Base with DefRewriting { IR: IRContext => opt.map(asRep[t => Any](argsV(0))) case SOptionMethods.FilterMethod.name => opt.filter(asRep[t => Boolean](argsV(0))) - case _ => throwError + case _ => throwError() } case (ge: Ref[GroupElement]@unchecked, SGroupElementMethods) => method.name match { case SGroupElementMethods.GetEncodedMethod.name => @@ -1012,12 +1013,12 @@ trait GraphBuilding extends Base with DefRewriting { IR: IRContext => case SGroupElementMethods.ExponentiateMethod.name => val k = asRep[BigInt](argsV(0)) ge.exp(k) - case _ => throwError + case _ => throwError() } case (box: Ref[Box]@unchecked, SBoxMethods) => method.name match { case SBoxMethods.tokensMethod.name => box.tokens - case _ => throwError + case _ => throwError() } case (ctx: Ref[Context]@unchecked, SContextMethods) => method.name match { case SContextMethods.dataInputsMethod.name => @@ -1040,7 +1041,7 @@ trait GraphBuilding extends Base with DefRewriting { IR: IRContext => ctx.LastBlockUtxoRootHash case SContextMethods.minerPubKeyMethod.name => ctx.minerPubKey - case _ => throwError + case _ => throwError() } case (tree: Ref[AvlTree]@unchecked, SAvlTreeMethods) => method.name match { case SAvlTreeMethods.digestMethod.name => @@ -1087,7 +1088,7 @@ trait GraphBuilding extends Base with DefRewriting { IR: IRContext => val operations = asRep[Coll[(Coll[Byte], Coll[Byte])]](argsV(0)) val proof = asRep[Coll[Byte]](argsV(1)) tree.update(operations, proof) - case _ => throwError + case _ => throwError() } case (ph: Ref[PreHeader]@unchecked, SPreHeaderMethods) => method.name match { case SPreHeaderMethods.versionMethod.name => @@ -1104,7 +1105,7 @@ trait GraphBuilding extends Base with DefRewriting { IR: IRContext => ph.minerPk case SPreHeaderMethods.votesMethod.name => ph.votes - case _ => throwError + case _ => throwError() } case (h: Ref[Header]@unchecked, SHeaderMethods) => method.name match { case SHeaderMethods.idMethod.name => @@ -1137,7 +1138,7 @@ trait GraphBuilding extends Base with DefRewriting { IR: IRContext => h.powDistance case SHeaderMethods.votesMethod.name => h.votes - case _ => throwError + case _ => throwError() } case (g: Ref[SigmaDslBuilder]@unchecked, SGlobalMethods) => method.name match { case SGlobalMethods.groupGeneratorMethod.name => @@ -1149,19 +1150,19 @@ trait GraphBuilding extends Base with DefRewriting { IR: IRContext => case SGlobalMethods.serializeMethod.name => val value = asRep[Any](argsV(0)) g.serialize(value) - case _ => throwError + case _ => throwError() } - case (x: Ref[tNum], SNumericTypeMethods) => method.name match { + case (x: Ref[tNum], _: SNumericTypeMethods) => method.name match { case SNumericTypeMethods.ToBytesMethod.name => val op = NumericToBigEndianBytes(elemToExactNumeric(x.elem)) ApplyUnOp(op, x) - case _ => throwError + case _ => throwError() } - case _ => throwError + case _ => throwError(s"Type ${stypeToRType(obj.tpe).name} doesn't have methods") } case _ => - throwError + throwError() } val resC = asRep[T#WrappedType](res) resC From 2427db30fdaedd4f75c85677507d656ce4c86412 Mon Sep 17 00:00:00 2001 From: Alexander Slesarenko Date: Sat, 25 May 2024 13:10:24 +0200 Subject: [PATCH 103/314] i486-toBytes: added userDefinedInvoke handler to SMethod --- .../src/main/scala/sigma/ast/package.scala | 6 ++++++ .../src/main/scala/sigma/ast/SMethod.scala | 19 ++++++++++++++++--- .../sigma/compiler/ir/TreeBuilding.scala | 8 ++++---- .../sigma/compiler/phases/SigmaTyper.scala | 3 ++- 4 files changed, 28 insertions(+), 8 deletions(-) diff --git a/core/shared/src/main/scala/sigma/ast/package.scala b/core/shared/src/main/scala/sigma/ast/package.scala index 63a2cfbcba..ec51ca6e3a 100644 --- a/core/shared/src/main/scala/sigma/ast/package.scala +++ b/core/shared/src/main/scala/sigma/ast/package.scala @@ -137,6 +137,12 @@ package object ast { def asNumType: SNumericType = tpe.asInstanceOf[SNumericType] + /** Cast this type to numeric type or else throws the given error. */ + def asNumTypeOrElse(error: => Exception): SNumericType = tpe match { + case nt: SNumericType => nt + case _ => throw error + } + def asFunc: SFunc = tpe.asInstanceOf[SFunc] def asProduct: SProduct = tpe.asInstanceOf[SProduct] diff --git a/data/shared/src/main/scala/sigma/ast/SMethod.scala b/data/shared/src/main/scala/sigma/ast/SMethod.scala index 332c74be6b..19fa427b9e 100644 --- a/data/shared/src/main/scala/sigma/ast/SMethod.scala +++ b/data/shared/src/main/scala/sigma/ast/SMethod.scala @@ -73,7 +73,9 @@ case class SMethod( explicitTypeArgs: Seq[STypeVar], irInfo: MethodIRInfo, docInfo: Option[OperationInfo], - costFunc: Option[MethodCostFunc]) { + costFunc: Option[MethodCostFunc], + userDefinedInvoke: Option[SMethod.InvokeHandler] +) { /** Operation descriptor of this method. */ lazy val opDesc = MethodDesc(this) @@ -112,7 +114,12 @@ case class SMethod( /** Invoke this method on the given object with the arguments. * This is used for methods with FixedCost costKind. */ def invokeFixed(obj: Any, args: Array[Any]): Any = { - javaMethod.invoke(obj, args.asInstanceOf[Array[AnyRef]]:_*) + userDefinedInvoke match { + case Some(h) => + h(obj, args) + case None => + javaMethod.invoke(obj, args.asInstanceOf[Array[AnyRef]]:_*) + } } // TODO optimize: avoid lookup when this SMethod is created via `specializeFor` @@ -261,6 +268,12 @@ object SMethod { */ type InvokeDescBuilder = SFunc => Seq[SType] + /** Type of user-defined function which is called to handle method invocation. + * Instances of this type can be attached to [[SMethod]] instances. + * @see SNumericTypeMethods.ToBytesMethod + */ + type InvokeHandler = (Any, Array[Any]) => Any + /** Return [[Method]] descriptor for the given `methodName` on the given `cT` type. * @param methodName the name of the method to lookup * @param cT the class where to search the methodName @@ -295,7 +308,7 @@ object SMethod { ): SMethod = { SMethod( objType, name, stype, methodId, costKind, explicitTypeArgs, - MethodIRInfo(None, None, None), None, None) + MethodIRInfo(None, None, None), None, None, None) } diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/TreeBuilding.scala b/sc/shared/src/main/scala/sigma/compiler/ir/TreeBuilding.scala index 655010dbc5..f7daff90ae 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/TreeBuilding.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/TreeBuilding.scala @@ -106,11 +106,11 @@ trait TreeBuilding extends Base { IR: IRContext => object IsNumericUnOp { def unapply(op: UnOp[_,_]): Option[SValue => SValue] = op match { case NumericNegate(_) => Some({ v: SValue => builder.mkNegation(v.asNumValue) }) - case NumericToBigEndianBytes(_) => + case _: NumericToBigEndianBytes[_] => val mkNode = { v: SValue => - val specMethod = SNumericTypeMethods.ToBytesMethod - .withConcreteTypes(Map(SNumericTypeMethods.tNum -> v.tpe)) - builder.mkMethodCall(v.asNumValue, specMethod, IndexedSeq.empty) + val receiverType = v.tpe.asNumTypeOrElse(error(s"Expected numeric type, got: ${v.tpe}")) + val m = SMethod.fromIds(receiverType.typeId, SNumericTypeMethods.ToBytesMethod.methodId) + builder.mkMethodCall(v.asNumValue, m, IndexedSeq.empty) } Some(mkNode) case _ => None diff --git a/sc/shared/src/main/scala/sigma/compiler/phases/SigmaTyper.scala b/sc/shared/src/main/scala/sigma/compiler/phases/SigmaTyper.scala index f9b52fe061..ac30a6cd0a 100644 --- a/sc/shared/src/main/scala/sigma/compiler/phases/SigmaTyper.scala +++ b/sc/shared/src/main/scala/sigma/compiler/phases/SigmaTyper.scala @@ -139,7 +139,8 @@ class SigmaTyper(val builder: SigmaBuilder, obj.tpe match { case p: SProduct => MethodsContainer.getMethod(p, n) match { - case Some(method @ SMethod(_, _, genFunTpe @ SFunc(_, _, _), _, _, _, _, _, _)) => + case Some(method: SMethod) => + val genFunTpe = method.stype val subst = Map(genFunTpe.tpeParams.head.ident -> rangeTpe) val concrFunTpe = applySubst(genFunTpe, subst) val expectedArgs = concrFunTpe.asFunc.tDom.tail From 02e2d06d7b66082bed697767d6446cce138d6ef8 Mon Sep 17 00:00:00 2001 From: Alexander Slesarenko Date: Sat, 25 May 2024 15:15:40 +0200 Subject: [PATCH 104/314] i486-toBytes: toBigEndianBytes implemented --- .../src/main/scala/sigma/VersionContext.scala | 13 ++++ .../src/main/scala/sigma/ast/SMethod.scala | 9 ++- .../src/main/scala/sigma/ast/methods.scala | 11 ++- .../scala/sigma/LanguageSpecificationV5.scala | 14 ++-- .../scala/sigma/LanguageSpecificationV6.scala | 70 +++++++++---------- .../test/scala/sigma/SigmaDslTesting.scala | 23 +++--- 6 files changed, 84 insertions(+), 56 deletions(-) diff --git a/core/shared/src/main/scala/sigma/VersionContext.scala b/core/shared/src/main/scala/sigma/VersionContext.scala index 19a4857086..ecdcfb5f62 100644 --- a/core/shared/src/main/scala/sigma/VersionContext.scala +++ b/core/shared/src/main/scala/sigma/VersionContext.scala @@ -25,6 +25,12 @@ case class VersionContext(activatedVersion: Byte, ergoTreeVersion: Byte) { /** @return true, if the activated script version of Ergo protocol on the network is * including Evolution update. */ def isV6SoftForkActivated: Boolean = activatedVersion >= V6SoftForkVersion + + /** @return true if another [[VersionContext]] is greater than this. */ + def <= (that: VersionContext): Boolean = { + this.activatedVersion < that.activatedVersion || + (this.activatedVersion == that.activatedVersion && this.ergoTreeVersion <= that.ergoTreeVersion) + } } object VersionContext { @@ -104,4 +110,11 @@ object VersionContext { } } + /** Returns the VersionContext with V5 activation and the given ErgoTree version. */ + def sinceV5AndTreeVersion(treeVersion: Byte): VersionContext = + VersionContext(JitActivationVersion, ergoTreeVersion = treeVersion) + + /** Returns the VersionContext with V6 activation and the given ErgoTree version. */ + def sinceV6AndTreeVersion(treeVersion: Byte): VersionContext = + VersionContext(V6SoftForkVersion, ergoTreeVersion = treeVersion) } diff --git a/data/shared/src/main/scala/sigma/ast/SMethod.scala b/data/shared/src/main/scala/sigma/ast/SMethod.scala index 19fa427b9e..6bf8d4f9a0 100644 --- a/data/shared/src/main/scala/sigma/ast/SMethod.scala +++ b/data/shared/src/main/scala/sigma/ast/SMethod.scala @@ -116,7 +116,7 @@ case class SMethod( def invokeFixed(obj: Any, args: Array[Any]): Any = { userDefinedInvoke match { case Some(h) => - h(obj, args) + h(this, obj, args) case None => javaMethod.invoke(obj, args.asInstanceOf[Array[AnyRef]]:_*) } @@ -159,6 +159,11 @@ case class SMethod( m } + /** Create a new instance with the given user-defined invoke handler. */ + def withUserDefinedInvoke(handler: SMethod.InvokeHandler): SMethod = { + copy(userDefinedInvoke = Some(handler)) + } + /** Create a new instance with the given stype. */ def withSType(newSType: SFunc): SMethod = copy(stype = newSType) @@ -272,7 +277,7 @@ object SMethod { * Instances of this type can be attached to [[SMethod]] instances. * @see SNumericTypeMethods.ToBytesMethod */ - type InvokeHandler = (Any, Array[Any]) => Any + type InvokeHandler = (SMethod, Any, Array[Any]) => Any /** Return [[Method]] descriptor for the given `methodName` on the given `cT` type. * @param methodName the name of the method to lookup diff --git a/data/shared/src/main/scala/sigma/ast/methods.scala b/data/shared/src/main/scala/sigma/ast/methods.scala index c53a9b84c7..1a0841e97c 100644 --- a/data/shared/src/main/scala/sigma/ast/methods.scala +++ b/data/shared/src/main/scala/sigma/ast/methods.scala @@ -8,6 +8,7 @@ import sigma.ast.SCollection.{SBooleanArray, SBoxArray, SByteArray, SByteArray2, import sigma.ast.SMethod.{MethodCallIrBuilder, MethodCostFunc, javaMethodOf} import sigma.ast.SType.{TypeCode, paramT, tT} import sigma.ast.syntax.{SValue, ValueOps} +import sigma.data.ExactIntegral.{ByteIsExactIntegral, IntIsExactIntegral, LongIsExactIntegral, ShortIsExactIntegral} import sigma.data.OverloadHack.Overloaded1 import sigma.data.{DataValueComparer, KeyValueColl, Nullable, RType, SigmaConstants} import sigma.eval.{CostDetails, ErgoTreeEvaluator, TracedCost} @@ -230,6 +231,15 @@ object SNumericTypeMethods extends MethodsContainer { val ToBytesMethod: SMethod = SMethod( this, "toBytes", SFunc(tNum, SByteArray), 6, ToBytes_CostKind) .withIRInfo(MethodCallIrBuilder) + .withUserDefinedInvoke({ (m: SMethod, obj: Any, _: Array[Any]) => + m.objType match { + case SByteMethods => ByteIsExactIntegral.toBigEndianBytes(obj.asInstanceOf[Byte]) + case SShortMethods => ShortIsExactIntegral.toBigEndianBytes(obj.asInstanceOf[Short]) + case SIntMethods => IntIsExactIntegral.toBigEndianBytes(obj.asInstanceOf[Int]) + case SLongMethods => LongIsExactIntegral.toBigEndianBytes(obj.asInstanceOf[Long]) + case SBigIntMethods => obj.asInstanceOf[BigInt].toBytes + } + }) .withInfo(PropertyCall, """ Returns a big-endian representation of this numeric value in a collection of bytes. | For example, the \lst{Int} value \lst{0x12131415} would yield the @@ -1547,7 +1557,6 @@ case object SGlobalMethods extends MonoTypeMethods { def serialize_eval(mc: MethodCall, G: SigmaDslBuilder, value: SType#WrappedType) (implicit E: ErgoTreeEvaluator): Coll[Byte] = { // TODO v6.0: accumulate cost - CheckMinimalErgoTreeVersion(E.context.currentErgoTreeVersion, VersionContext.V6SoftForkVersion) val t = Evaluation.stypeToRType(mc.args(0).tpe) G.serialize(value)(t) } diff --git a/sc/shared/src/test/scala/sigma/LanguageSpecificationV5.scala b/sc/shared/src/test/scala/sigma/LanguageSpecificationV5.scala index f568515c89..48f1a3f7ca 100644 --- a/sc/shared/src/test/scala/sigma/LanguageSpecificationV5.scala +++ b/sc/shared/src/test/scala/sigma/LanguageSpecificationV5.scala @@ -4802,7 +4802,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => })) ), changedFeature( - changedInVersion = VersionContext.JitActivationVersion, + changedInVersion = VersionContext.sinceV5AndTreeVersion(0), { (x: Context) => x.selfBoxIndex }, { (x: Context) => x.selfBoxIndex }, // see versioning in selfBoxIndex implementation "{ (x: Context) => x.selfBoxIndex }", @@ -5004,7 +5004,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => ) ), changedFeature( - changedInVersion = VersionContext.JitActivationVersion, + changedInVersion = VersionContext.sinceV5AndTreeVersion(0), scalaFunc = { (x: Context) => // this error is expected in v3.x, v4.x throw expectedError @@ -5978,7 +5978,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => ) }, changedFeature( - changedInVersion = VersionContext.JitActivationVersion, + changedInVersion = VersionContext.sinceV5AndTreeVersion(0), (x: Coll[Boolean]) => SigmaDsl.xorOf(x), (x: Coll[Boolean]) => SigmaDsl.xorOf(x), "{ (x: Coll[Boolean]) => xorOf(x) }", @@ -6241,7 +6241,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => ) }, changedFeature( - changedInVersion = VersionContext.JitActivationVersion, + changedInVersion = VersionContext.sinceV5AndTreeVersion(0), (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) }", @@ -8811,7 +8811,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => (Some(Long.MaxValue) -> Expected(new ArithmeticException("long overflow"))) ), changedFeature( - changedInVersion = VersionContext.JitActivationVersion, + changedInVersion = VersionContext.sinceV5AndTreeVersion(0), scalaFunc = { (x: Option[Long]) => def f(opt: Long): Long = n.plus(opt, 1) if (x.isDefined) f(x.get) @@ -9367,7 +9367,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => ) }, changedFeature( - changedInVersion = VersionContext.JitActivationVersion, + changedInVersion = VersionContext.sinceV5AndTreeVersion(0), { (x: (Coll[Byte], Int)) => SigmaDsl.substConstants(x._1, Coll[Int](x._2), Coll[Any](SigmaDsl.sigmaProp(false))(sigma.AnyType)) }, @@ -9430,7 +9430,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => ) ), changedFeature( - changedInVersion = VersionContext.JitActivationVersion, + changedInVersion = VersionContext.sinceV5AndTreeVersion(0), { (x: Context) => throw error true diff --git a/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala b/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala index ed6b6d5165..d89fc1f623 100644 --- a/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala +++ b/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala @@ -44,7 +44,7 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite => Map() ) ), - sinceVersion = VersionContext.V6SoftForkVersion) + sinceVersion = VersionContext.sinceV6AndTreeVersion(0)) } property("Global.serialize[Byte]") { @@ -76,7 +76,7 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite => property("Boolean.toByte") { val toByte = newFeature((x: Boolean) => x.toByte, "{ (x: Boolean) => x.toByte }", - sinceVersion = VersionContext.V6SoftForkVersion + sinceVersion = VersionContext.sinceV6AndTreeVersion(0) ) val cases = Seq( @@ -102,22 +102,22 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite => // which is checked below lazy val toAbs = newFeature((x: Byte) => x.toAbs, "{ (x: Byte) => x.toAbs }", - sinceVersion = VersionContext.V6SoftForkVersion) + sinceVersion = VersionContext.sinceV6AndTreeVersion(0)) lazy val compareTo = newFeature( (x: (Byte, Byte)) => x._1.compareTo(x._2), "{ (x: (Byte, Byte)) => x._1.compareTo(x._2) }", - sinceVersion = VersionContext.V6SoftForkVersion) + sinceVersion = VersionContext.sinceV6AndTreeVersion(0)) lazy val bitOr = newFeature( { (x: (Byte, Byte)) => (x._1 | x._2).toByteExact }, "{ (x: (Byte, Byte)) => (x._1 | x._2) }", - sinceVersion = VersionContext.V6SoftForkVersion) + sinceVersion = VersionContext.sinceV6AndTreeVersion(0)) lazy val bitAnd = newFeature( { (x: (Byte, Byte)) => (x._1 & x._2).toByteExact }, "{ (x: (Byte, Byte)) => (x._1 & x._2) }", - sinceVersion = VersionContext.V6SoftForkVersion) + sinceVersion = VersionContext.sinceV6AndTreeVersion(0)) forAll { x: Byte => Seq(toAbs).foreach(f => f.checkEquality(x)) @@ -136,21 +136,21 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite => // which is checked below lazy val toAbs = newFeature((x: Short) => x.toAbs, "{ (x: Short) => x.toAbs }", - sinceVersion = VersionContext.V6SoftForkVersion) + sinceVersion = VersionContext.sinceV6AndTreeVersion(0)) lazy val compareTo = newFeature((x: (Short, Short)) => x._1.compareTo(x._2), "{ (x: (Short, Short)) => x._1.compareTo(x._2) }", - sinceVersion = VersionContext.V6SoftForkVersion) + sinceVersion = VersionContext.sinceV6AndTreeVersion(0)) lazy val bitOr = newFeature( { (x: (Short, Short)) => (x._1 | x._2).toShortExact }, "{ (x: (Short, Short)) => x._1 | x._2 }", - sinceVersion = VersionContext.V6SoftForkVersion) + sinceVersion = VersionContext.sinceV6AndTreeVersion(0)) lazy val bitAnd = newFeature( { (x: (Short, Short)) => (x._1 & x._2).toShortExact }, "{ (x: (Short, Short)) => x._1 & x._2 }", - sinceVersion = VersionContext.V6SoftForkVersion) + sinceVersion = VersionContext.sinceV6AndTreeVersion(0)) forAll { x: Short => Seq(toAbs).foreach(_.checkEquality(x)) @@ -166,18 +166,18 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite => // NOTE, for such versions the new features are not supported // which is checked below lazy val toAbs = newFeature((x: Int) => x.toAbs, "{ (x: Int) => x.toAbs }", - sinceVersion = VersionContext.V6SoftForkVersion) + sinceVersion = VersionContext.sinceV6AndTreeVersion(0)) lazy val compareTo = newFeature((x: (Int, Int)) => x._1.compareTo(x._2), "{ (x: (Int, Int)) => x._1.compareTo(x._2) }", - sinceVersion = VersionContext.V6SoftForkVersion) + sinceVersion = VersionContext.sinceV6AndTreeVersion(0)) lazy val bitOr = newFeature( { (x: (Int, Int)) => x._1 | x._2 }, "{ (x: (Int, Int)) => x._1 | x._2 }", - sinceVersion = VersionContext.V6SoftForkVersion) + sinceVersion = VersionContext.sinceV6AndTreeVersion(0)) lazy val bitAnd = newFeature( { (x: (Int, Int)) => x._1 & x._2 }, "{ (x: (Int, Int)) => x._1 & x._2 }", - sinceVersion = VersionContext.V6SoftForkVersion) + sinceVersion = VersionContext.sinceV6AndTreeVersion(0)) forAll { x: Int => Seq(toAbs).foreach(_.checkEquality(x)) } @@ -192,20 +192,20 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite => // NOTE, for such versions the new features are not supported // which is checked below lazy val toAbs = newFeature((x: Long) => x.toAbs, "{ (x: Long) => x.toAbs }", - sinceVersion = VersionContext.V6SoftForkVersion) + sinceVersion = VersionContext.sinceV6AndTreeVersion(0)) lazy val compareTo = newFeature((x: (Long, Long)) => x._1.compareTo(x._2), "{ (x: (Long, Long)) => x._1.compareTo(x._2) }", - sinceVersion = VersionContext.V6SoftForkVersion) + sinceVersion = VersionContext.sinceV6AndTreeVersion(0)) lazy val bitOr = newFeature( { (x: (Long, Long)) => x._1 | x._2 }, "{ (x: (Long, Long)) => x._1 | x._2 }", - sinceVersion = VersionContext.V6SoftForkVersion) + sinceVersion = VersionContext.sinceV6AndTreeVersion(0)) lazy val bitAnd = newFeature( { (x: (Long, Long)) => x._1 & x._2 }, "{ (x: (Long, Long)) => x._1 & x._2 }", - sinceVersion = VersionContext.V6SoftForkVersion) + sinceVersion = VersionContext.sinceV6AndTreeVersion(0)) forAll { x: Long => Seq(toAbs).foreach(_.checkEquality(x)) @@ -240,30 +240,30 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite => val toByte = newFeature((x: BigInt) => x.toByte, "{ (x: BigInt) => x.toByte }", FuncValue(Vector((1, SBigInt)), Downcast(ValUse(1, SBigInt), SByte)), - sinceVersion = VersionContext.V6SoftForkVersion) + sinceVersion = VersionContext.sinceV6AndTreeVersion(0)) val toShort = newFeature((x: BigInt) => x.toShort, "{ (x: BigInt) => x.toShort }", FuncValue(Vector((1, SBigInt)), Downcast(ValUse(1, SBigInt), SShort)), - sinceVersion = VersionContext.V6SoftForkVersion) + sinceVersion = VersionContext.sinceV6AndTreeVersion(0)) val toInt = newFeature((x: BigInt) => x.toInt, "{ (x: BigInt) => x.toInt }", FuncValue(Vector((1, SBigInt)), Downcast(ValUse(1, SBigInt), SInt)), - sinceVersion = VersionContext.V6SoftForkVersion) + sinceVersion = VersionContext.sinceV6AndTreeVersion(0)) val toLong = newFeature((x: BigInt) => x.toLong, "{ (x: BigInt) => x.toLong }", FuncValue(Vector((1, SBigInt)), Downcast(ValUse(1, SBigInt), SLong)), - sinceVersion = VersionContext.V6SoftForkVersion) + sinceVersion = VersionContext.sinceV6AndTreeVersion(0)) lazy val toAbs = newFeature((x: BigInt) => x.toAbs, "{ (x: BigInt) => x.toAbs }", - sinceVersion = VersionContext.V6SoftForkVersion) + sinceVersion = VersionContext.sinceV6AndTreeVersion(0)) lazy val compareTo = newFeature((x: (BigInt, BigInt)) => x._1.compareTo(x._2), "{ (x: (BigInt, BigInt)) => x._1.compareTo(x._2) }", - sinceVersion = VersionContext.V6SoftForkVersion) + sinceVersion = VersionContext.sinceV6AndTreeVersion(0)) lazy val bitOr = newFeature({ (x: (BigInt, BigInt)) => x._1 | x._2 }, "{ (x: (BigInt, BigInt)) => x._1 | x._2 }", - sinceVersion = VersionContext.V6SoftForkVersion) + sinceVersion = VersionContext.sinceV6AndTreeVersion(0)) lazy val bitAnd = newFeature({ (x: (BigInt, BigInt)) => x._1 & x._2 }, "{ (x: (BigInt, BigInt)) => x._1 & x._2 }", - sinceVersion = VersionContext.V6SoftForkVersion) + sinceVersion = VersionContext.sinceV6AndTreeVersion(0)) forAll { x: BigInt => Seq(toByte, toShort, toInt, toLong, toAbs).foreach(_.checkEquality(x)) @@ -278,7 +278,7 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite => // TODO v6.0: related to https://github.com/ScorexFoundation/sigmastate-interpreter/issues/416 val getReg = newFeature((x: Box) => x.getReg[Int](1).get, "{ (x: Box) => x.getReg[Int](1).get }", - sinceVersion = VersionContext.V6SoftForkVersion) + sinceVersion = VersionContext.sinceV6AndTreeVersion(0)) if (activatedVersionInTests < VersionContext.V6SoftForkVersion) { // NOTE, for such versions getReg is not supported @@ -294,7 +294,7 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite => property("Coll find method equivalence") { val find = newFeature((x: Coll[Int]) => x.find({ (v: Int) => v > 0 }), "{ (x: Coll[Int]) => x.find({ (v: Int) => v > 0} ) }", - sinceVersion = VersionContext.V6SoftForkVersion) + sinceVersion = VersionContext.sinceV6AndTreeVersion(0)) if (activatedVersionInTests < VersionContext.V6SoftForkVersion) { // NOTE, for such versions getReg is not supported @@ -313,7 +313,7 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite => if (x.size > 2) x.slice(0, x.size - 2) else Colls.emptyColl[Boolean] }, "{ (x: Coll[Boolean]) => x >> 2 }", - sinceVersion = VersionContext.V6SoftForkVersion) + sinceVersion = VersionContext.sinceV6AndTreeVersion(0)) if (activatedVersionInTests < VersionContext.V6SoftForkVersion) { // NOTE, for such versions getReg is not supported @@ -329,7 +329,7 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite => property("Coll diff methods equivalence") { val diff = newFeature((x: (Coll[Int], Coll[Int])) => x._1.diff(x._2), "{ (x: (Coll[Int], Coll[Int])) => x._1.diff(x._2) }", - sinceVersion = VersionContext.V6SoftForkVersion) + sinceVersion = VersionContext.sinceV6AndTreeVersion(0)) if (activatedVersionInTests < VersionContext.V6SoftForkVersion) { // NOTE, for such versions getReg is not supported @@ -346,7 +346,7 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite => val n = ExactNumeric.LongIsExactNumeric val fold = newFeature({ (x: Option[Long]) => x.fold(5.toLong)( (v: Long) => n.plus(v, 1) ) }, "{ (x: Option[Long]) => x.fold(5, { (v: Long) => v + 1 }) }", - sinceVersion = VersionContext.V6SoftForkVersion) + sinceVersion = VersionContext.sinceV6AndTreeVersion(0)) if (activatedVersionInTests < VersionContext.V6SoftForkVersion) { // NOTE, for such versions getReg is not supported @@ -362,7 +362,7 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite => property("allZK equivalence") { lazy val allZK = newFeature((x: Coll[SigmaProp]) => SigmaDsl.allZK(x), "{ (x: Coll[SigmaProp]) => allZK(x) }", - sinceVersion = VersionContext.V6SoftForkVersion) + sinceVersion = VersionContext.sinceV6AndTreeVersion(0)) if (activatedVersionInTests < VersionContext.V6SoftForkVersion) { // NOTE, for such versions getReg is not supported @@ -378,7 +378,7 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite => property("anyZK equivalence") { lazy val anyZK = newFeature((x: Coll[SigmaProp]) => SigmaDsl.anyZK(x), "{ (x: Coll[SigmaProp]) => anyZK(x) }", - sinceVersion = VersionContext.V6SoftForkVersion) + sinceVersion = VersionContext.sinceV6AndTreeVersion(0)) if (activatedVersionInTests < VersionContext.V6SoftForkVersion) { // NOTE, for such versions getReg is not supported @@ -442,7 +442,7 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite => } ), changedFeature( - changedInVersion = VersionContext.V6SoftForkVersion, + changedInVersion = VersionContext.sinceV6AndTreeVersion(0), { (x: (Coll[Byte], Int)) => SigmaDsl.substConstants(x._1, Coll[Int](x._2), Coll[Any](SigmaDsl.sigmaProp(false))(sigma.AnyType)) }, @@ -479,7 +479,7 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite => lazy val toBytes = newFeature( { (x: Byte) => x.toBigEndianBytes }, "{ (x: Byte) => x.toBytes }", - sinceVersion = VersionContext.V6SoftForkVersion) + sinceVersion = VersionContext.sinceV6AndTreeVersion(0)) val cases = Seq( (0.toByte, Success(Coll(0.toByte))), (1.toByte, Success(Coll(1.toByte))) diff --git a/sc/shared/src/test/scala/sigma/SigmaDslTesting.scala b/sc/shared/src/test/scala/sigma/SigmaDslTesting.scala index 3246f968a0..0b512d1380 100644 --- a/sc/shared/src/test/scala/sigma/SigmaDslTesting.scala +++ b/sc/shared/src/test/scala/sigma/SigmaDslTesting.scala @@ -126,8 +126,8 @@ class SigmaDslTesting extends AnyPropSpec /** Checks if this feature is supported in the given version context. */ def isSupportedIn(vc: VersionContext): Boolean - /** Version in which the feature is first implemented of changed. */ - def sinceVersion: Byte + /** Version in which the feature is first implemented or changed. */ + def sinceVersion: VersionContext /** Script containing this feature. */ def script: String @@ -400,7 +400,7 @@ class SigmaDslTesting extends AnyPropSpec ctx } - val (expectedResult, expectedCost) = if (activatedVersionInTests < sinceVersion) + val (expectedResult, expectedCost) = if (activatedVersionInTests < sinceVersion.activatedVersion) (expected.oldResult, expected.verificationCostOpt) else { val res = expected.newResults(ergoTreeVersionInTests) @@ -507,7 +507,7 @@ class SigmaDslTesting extends AnyPropSpec implicit val cs = compilerSettingsInTests - override def sinceVersion: Byte = 0 + override def sinceVersion: VersionContext = VersionContext(0, 0) // has always been supported override def isSupportedIn(vc: VersionContext): Boolean = true @@ -669,7 +669,7 @@ class SigmaDslTesting extends AnyPropSpec * @param allowDifferentErrors if true, allow v4.x and v5.0 to fail with different error */ case class ChangedFeature[A, B]( - changedInVersion: Byte, + changedInVersion: VersionContext, script: String, scalaFunc: A => B, override val scalaFuncNew: A => B, @@ -683,7 +683,7 @@ class SigmaDslTesting extends AnyPropSpec implicit val cs = compilerSettingsInTests - override def sinceVersion: Byte = changedInVersion + override def sinceVersion: VersionContext = changedInVersion override def isSupportedIn(vc: VersionContext): Boolean = true @@ -764,7 +764,7 @@ class SigmaDslTesting extends AnyPropSpec checkEq(scalaFuncNew)(newF)(input) } - if (VersionContext.current.activatedVersion < changedInVersion) { + if (VersionContext.current.activatedVersion < changedInVersion.activatedVersion) { // check the old implementation with Scala semantic val expectedOldRes = expected.value @@ -859,7 +859,7 @@ class SigmaDslTesting extends AnyPropSpec * @param logScript if true, log scripts to console */ case class NewFeature[A, B]( - sinceVersion: Byte, + sinceVersion: VersionContext, script: String, override val scalaFuncNew: A => B, expectedExpr: Option[SValue], @@ -869,7 +869,7 @@ class SigmaDslTesting extends AnyPropSpec extends Feature[A, B] { override def isSupportedIn(vc: VersionContext): Boolean = - vc.activatedVersion >= sinceVersion && vc.ergoTreeVersion >= sinceVersion + sinceVersion <= vc override def scalaFunc: A => B = { x => sys.error(s"Semantic Scala function is not defined for old implementation: $this") @@ -1063,7 +1063,7 @@ class SigmaDslTesting extends AnyPropSpec * various ways */ def changedFeature[A: RType, B: RType] - (changedInVersion: Byte, + (changedInVersion: VersionContext, scalaFunc: A => B, scalaFuncNew: A => B, script: String, @@ -1088,7 +1088,8 @@ class SigmaDslTesting extends AnyPropSpec * various ways */ def newFeature[A: RType, B: RType] - (scalaFunc: A => B, script: String, expectedExpr: SValue = null, sinceVersion: Byte = VersionContext.JitActivationVersion) + (scalaFunc: A => B, script: String, expectedExpr: SValue = null, + sinceVersion: VersionContext = VersionContext(VersionContext.JitActivationVersion, 0)) (implicit IR: IRContext, es: EvalSettings): Feature[A, B] = { NewFeature(sinceVersion, script, scalaFunc, Option(expectedExpr)) } From c9d0889c91b9e98c5d757711ac3984b6434c4a40 Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Sun, 26 May 2024 23:13:30 +0300 Subject: [PATCH 105/314] first pow check test --- .../src/main/scala/sigma/ast/methods.scala | 2 +- .../utxo/BasicOpsSpecification.scala | 40 +++++++++++++++++++ 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/data/shared/src/main/scala/sigma/ast/methods.scala b/data/shared/src/main/scala/sigma/ast/methods.scala index 3642a82ddb..88ee9c72ed 100644 --- a/data/shared/src/main/scala/sigma/ast/methods.scala +++ b/data/shared/src/main/scala/sigma/ast/methods.scala @@ -304,7 +304,7 @@ case object SLongMethods extends SNumericTypeMethods { override def ownerType: SMonoType = SLong lazy val DecodeNBitsMethod: SMethod = SMethod( - this, "DecodeNBits", SFunc(this.ownerType, SBigInt), 8, FixedCost(JitCost(5))) + this, "decodeNbits", SFunc(this.ownerType, SBigInt), 8, FixedCost(JitCost(5))) .withInfo(PropertyCall, "Consider this Long value as nbits-encoded BigInt value and decode it to BigInt") protected override def getMethods(): Seq[SMethod] = { diff --git a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala index 79701d6e07..e68b262c59 100644 --- a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala @@ -2,6 +2,7 @@ package sigmastate.utxo import org.ergoplatform.ErgoBox.{AdditionalRegisters, R6, R8} import org.ergoplatform._ +import scorex.util.encode.Base16 import sigma.Extensions.ArrayOps import sigma.ast.SCollection.SByteArray import sigma.ast.SType.AnyOps @@ -157,6 +158,45 @@ class BasicOpsSpecification extends CompilerTestingCommons ) } + property("checking Bitcoin PoW") { + val h = "00000020a82ff9c62e69a6cbed277b7f2a9ac9da3c7133a59a6305000000000000000000f6cd5708a6ba38d8501502b5b4e5b93627e8dcc9bd13991894c6e04ade262aa99582815c505b2e17479a751b" + val customExt = Map( + 1.toByte -> ByteArrayConstant(Base16.decode(h).get) + ).toSeq + + test("Prop1", env, customExt, + """{ + | def reverse4(bytes: Coll[Byte]): Coll[Byte] = { + | Coll(bytes(3), bytes(2), bytes(1), bytes(0)) + | } + | + | def reverse32(bytes: Coll[Byte]): Coll[Byte] = { + | Coll(bytes(31), bytes(30), bytes(29), bytes(28), bytes(27), bytes(26), bytes(25), bytes(24), + | bytes(23), bytes(22), bytes(21), bytes(20), bytes(19), bytes(18), bytes(17), bytes(16), + | bytes(15), bytes(14), bytes(13), bytes(12), bytes(11), bytes(10), bytes(9), bytes(8), + | bytes(7), bytes(6), bytes(5), bytes(4), bytes(3), bytes(2), bytes(1), bytes(0)) + | } + | + | val bitcoinHeader = getVar[Coll[Byte]](1).get + | val id = reverse32(sha256(sha256(bitcoinHeader))) + | val hit = byteArrayToBigInt(id) + | + | val nBitsBytes = reverse4(bitcoinHeader.slice(72, 76)) + | + | val pad = Coll[Byte](0.toByte, 0.toByte, 0.toByte, 0.toByte) + | + | val nbits = byteArrayToLong(pad ++ nBitsBytes) + | + | val difficulty = nbits.decodeNbits + | + | hit < 500000000000L + |} + |""".stripMargin, + propExp = null, + testExceededCost = false + ) + } + property("Relation operations") { test("R1", env, ext, "{ allOf(Coll(getVar[Boolean](trueVar).get, true, true)) }", From a90e7bea5902e1914cbe680e83ec47eff9a8341d Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Mon, 27 May 2024 00:30:55 +0300 Subject: [PATCH 106/314] pow check test passing --- .../src/main/scala/sigma/SigmaDsl.scala | 2 + .../sigma/reflection/ReflectionData.scala | 3 + .../src/main/scala/sigma/ast/methods.scala | 50 +++++++++---- .../scala/sigma/data/CSigmaDslBuilder.scala | 5 ++ .../scala/sigmastate/eval/BasicOpsTests.scala | 1 + .../scala/sigmastate/eval/GraphBuilding.scala | 3 + .../scala/special/sigma/SigmaDslUnit.scala | 1 + .../special/sigma/impl/SigmaDslImpl.scala | 14 ++++ .../utxo/BasicOpsSpecification.scala | 70 +++++++++++-------- 9 files changed, 103 insertions(+), 46 deletions(-) diff --git a/core/shared/src/main/scala/sigma/SigmaDsl.scala b/core/shared/src/main/scala/sigma/SigmaDsl.scala index 56e4a1da37..7b20ac80b9 100644 --- a/core/shared/src/main/scala/sigma/SigmaDsl.scala +++ b/core/shared/src/main/scala/sigma/SigmaDsl.scala @@ -697,6 +697,8 @@ trait SigmaDslBuilder { */ def groupGenerator: GroupElement + def decodeNbits(l: Long): BigInt + /** * Transforms serialized bytes of ErgoTree with segregated constants by replacing constants * at given positions with new values. This operation allow to use serialized scripts as diff --git a/core/shared/src/main/scala/sigma/reflection/ReflectionData.scala b/core/shared/src/main/scala/sigma/reflection/ReflectionData.scala index debb36e3c0..b4b5fd9f23 100644 --- a/core/shared/src/main/scala/sigma/reflection/ReflectionData.scala +++ b/core/shared/src/main/scala/sigma/reflection/ReflectionData.scala @@ -446,6 +446,9 @@ object ReflectionData { }, mkMethod(clazz, "decodePoint", Array[Class[_]](cColl)) { (obj, args) => obj.asInstanceOf[SigmaDslBuilder].decodePoint(args(0).asInstanceOf[Coll[Byte]]) + }, + mkMethod(clazz, "decodeNbits", Array[Class[_]](cColl)) { (obj, args) => + obj.asInstanceOf[SigmaDslBuilder].decodeNbits(args(0).asInstanceOf[Long]) } ) ) diff --git a/data/shared/src/main/scala/sigma/ast/methods.scala b/data/shared/src/main/scala/sigma/ast/methods.scala index 38919f81c5..171d2b95c7 100644 --- a/data/shared/src/main/scala/sigma/ast/methods.scala +++ b/data/shared/src/main/scala/sigma/ast/methods.scala @@ -8,10 +8,11 @@ import sigma.ast.SMethod.{MethodCallIrBuilder, MethodCostFunc, javaMethodOf} import sigma.ast.SType.TypeCode import sigma.ast.syntax.{SValue, ValueOps} import sigma.data.OverloadHack.Overloaded1 -import sigma.data.{DataValueComparer, KeyValueColl, Nullable, RType, SigmaConstants} +import sigma.data.{CBigInt, DataValueComparer, KeyValueColl, Nullable, RType, SigmaConstants} import sigma.eval.{CostDetails, ErgoTreeEvaluator, TracedCost} import sigma.reflection.RClass import sigma.serialization.CoreByteWriter.ArgInfo +import sigma.util.NBitsUtils import sigma.utils.SparseArrayContainer import scala.annotation.unused @@ -303,17 +304,8 @@ case object SLongMethods extends SNumericTypeMethods { /** Type for which this container defines methods. */ override def ownerType: SMonoType = SLong - lazy val DecodeNBitsMethod: SMethod = SMethod( - this, "decodeNbits", SFunc(this.ownerType, SBigInt), 8, FixedCost(JitCost(5))) - .withInfo(PropertyCall, "Consider this Long value as nbits-encoded BigInt value and decode it to BigInt") + protected override def getMethods(): Seq[SMethod] = super.getMethods() - protected override def getMethods(): Seq[SMethod] = { - if (VersionContext.current.isV6SoftForkActivated) { - super.getMethods() ++ Seq(DecodeNBitsMethod) - } else { - super.getMethods() - } - } } /** Methods of BigInt type. Implemented using [[java.math.BigInteger]]. */ @@ -1531,9 +1523,37 @@ case object SGlobalMethods extends MonoTypeMethods { Xor.xorWithCosting(ls, rs) } - protected override def getMethods() = super.getMethods() ++ Seq( - groupGeneratorMethod, - xorMethod - ) + lazy val decodeNBitsMethod: SMethod = SMethod( + this, "decodeNbits", SFunc(Array(SGlobal, SLong), SBigInt), 3, FixedCost(JitCost(5))) + .withIRInfo(MethodCallIrBuilder) + .withInfo(Xor, "Byte-wise XOR of two collections of bytes", ArgInfo("left", "left operand")) + + /** + * + */ + def decodeNbits_eval(mc: MethodCall, G: SigmaDslBuilder, l: Long)(implicit E: ErgoTreeEvaluator): BigInt = { + CBigInt(NBitsUtils.decodeCompactBits(l).bigInteger) // todo: costing is ignored here + } + + { + if (VersionContext.current.isV6SoftForkActivated) { + super.getMethods() ++ Seq(decodeNBitsMethod) + } else { + super.getMethods() + } + } + + protected override def getMethods() = if (VersionContext.current.isV6SoftForkActivated) { + super.getMethods() ++ Seq( + groupGeneratorMethod, + xorMethod, + decodeNBitsMethod + ) + } else { + super.getMethods() ++ Seq( + groupGeneratorMethod, + xorMethod + ) + } } diff --git a/data/shared/src/main/scala/sigma/data/CSigmaDslBuilder.scala b/data/shared/src/main/scala/sigma/data/CSigmaDslBuilder.scala index 3938feacd3..5f401ad9ff 100644 --- a/data/shared/src/main/scala/sigma/data/CSigmaDslBuilder.scala +++ b/data/shared/src/main/scala/sigma/data/CSigmaDslBuilder.scala @@ -10,6 +10,7 @@ import sigma.crypto.{CryptoConstants, EcPointType, Ecp} import sigma.eval.Extensions.EvalCollOps import sigma.serialization.{GroupElementSerializer, SigmaSerializer} import sigma.util.Extensions.BigIntegerOps +import sigma.util.NBitsUtils import sigma.validation.SigmaValidationSettings import sigma.{AvlTree, BigInt, Box, Coll, CollBuilder, GroupElement, SigmaDslBuilder, SigmaProp, VersionContext} @@ -175,6 +176,10 @@ class CSigmaDslBuilder extends SigmaDslBuilder { dsl => override def groupGenerator: GroupElement = _generatorElement + def decodeNbits(l: Long): BigInt = { + CBigInt(NBitsUtils.decodeCompactBits(l).bigInteger) + } + /** * @return the identity of the Dlog group used in ErgoTree */ diff --git a/interpreter/shared/src/test/scala/sigmastate/eval/BasicOpsTests.scala b/interpreter/shared/src/test/scala/sigmastate/eval/BasicOpsTests.scala index 95548c1969..fbd74ed873 100644 --- a/interpreter/shared/src/test/scala/sigmastate/eval/BasicOpsTests.scala +++ b/interpreter/shared/src/test/scala/sigmastate/eval/BasicOpsTests.scala @@ -5,6 +5,7 @@ import org.scalatest.matchers.should.Matchers import sigma.ast.{BigIntConstant, ErgoTree, JitCost, MethodCall, SBigIntMethods} import sigma.crypto.SecP256K1Group import sigma.data.{CBigInt, CSigmaDslBuilder, TrivialProp} +import sigma.eval.SigmaDsl import sigma.util.Extensions.SigmaBooleanOps import sigma.util.NBitsUtils diff --git a/sc/shared/src/main/scala/sigmastate/eval/GraphBuilding.scala b/sc/shared/src/main/scala/sigmastate/eval/GraphBuilding.scala index 5afdd3a28c..27bdcc0413 100644 --- a/sc/shared/src/main/scala/sigmastate/eval/GraphBuilding.scala +++ b/sc/shared/src/main/scala/sigmastate/eval/GraphBuilding.scala @@ -1141,6 +1141,9 @@ trait GraphBuilding extends SigmaLibrary { IR: IRContext => val c1 = asRep[Coll[Byte]](argsV(0)) val c2 = asRep[Coll[Byte]](argsV(1)) g.xor(c1, c2) + case SGlobalMethods.decodeNBitsMethod.name if VersionContext.current.isV6SoftForkActivated => + val c1 = asRep[Long](argsV(0)) + g.decodeNbits(c1) case _ => throwError } case _ => throwError diff --git a/sc/shared/src/main/scala/special/sigma/SigmaDslUnit.scala b/sc/shared/src/main/scala/special/sigma/SigmaDslUnit.scala index 9e3a06a62f..2ff51993c3 100644 --- a/sc/shared/src/main/scala/special/sigma/SigmaDslUnit.scala +++ b/sc/shared/src/main/scala/special/sigma/SigmaDslUnit.scala @@ -113,6 +113,7 @@ package sigma { /** This method will be used in v6.0 to handle CreateAvlTree operation in GraphBuilding */ def avlTree(operationFlags: Ref[Byte], digest: Ref[Coll[Byte]], keyLength: Ref[Int], valueLengthOpt: Ref[WOption[Int]]): Ref[AvlTree]; def xor(l: Ref[Coll[Byte]], r: Ref[Coll[Byte]]): Ref[Coll[Byte]] + def decodeNbits(l: Ref[Long]): Ref[BigInt] }; trait CostModelCompanion; trait BigIntCompanion; diff --git a/sc/shared/src/main/scala/special/sigma/impl/SigmaDslImpl.scala b/sc/shared/src/main/scala/special/sigma/impl/SigmaDslImpl.scala index 81525fa0b4..94e207ae25 100644 --- a/sc/shared/src/main/scala/special/sigma/impl/SigmaDslImpl.scala +++ b/sc/shared/src/main/scala/special/sigma/impl/SigmaDslImpl.scala @@ -1955,6 +1955,13 @@ object SigmaDslBuilder extends EntityObject("SigmaDslBuilder") { Array[AnyRef](l, r), true, false, element[Coll[Byte]])) } + + override def decodeNbits(l: Ref[Long]): Ref[BigInt] = { + asRep[BigInt](mkMethodCall(self, + SigmaDslBuilderClass.getMethod("decodeNbits", classOf[Sym]), + Array[AnyRef](), + true, false, element[BigInt])) + } } implicit object LiftableSigmaDslBuilder @@ -2114,6 +2121,13 @@ object SigmaDslBuilder extends EntityObject("SigmaDslBuilder") { Array[AnyRef](l, r), true, true, element[Coll[Byte]])) } + + override def decodeNbits(l: Ref[Long]): Ref[BigInt] = { + asRep[BigInt](mkMethodCall(source, + SigmaDslBuilderClass.getMethod("decodeNbits", classOf[Sym]), + Array[AnyRef](l), + true, true, element[BigInt])) + } } // entityUnref: single unref method for each type family diff --git a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala index e68b262c59..abfe9c0df4 100644 --- a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala @@ -4,6 +4,7 @@ import org.ergoplatform.ErgoBox.{AdditionalRegisters, R6, R8} import org.ergoplatform._ import scorex.util.encode.Base16 import sigma.Extensions.ArrayOps +import sigma.VersionContext.V6SoftForkVersion import sigma.ast.SCollection.SByteArray import sigma.ast.SType.AnyOps import sigma.data.{AvlTreeData, CAnyValue, CSigmaDslBuilder} @@ -164,37 +165,44 @@ class BasicOpsSpecification extends CompilerTestingCommons 1.toByte -> ByteArrayConstant(Base16.decode(h).get) ).toSeq - test("Prop1", env, customExt, - """{ - | def reverse4(bytes: Coll[Byte]): Coll[Byte] = { - | Coll(bytes(3), bytes(2), bytes(1), bytes(0)) - | } - | - | def reverse32(bytes: Coll[Byte]): Coll[Byte] = { - | Coll(bytes(31), bytes(30), bytes(29), bytes(28), bytes(27), bytes(26), bytes(25), bytes(24), - | bytes(23), bytes(22), bytes(21), bytes(20), bytes(19), bytes(18), bytes(17), bytes(16), - | bytes(15), bytes(14), bytes(13), bytes(12), bytes(11), bytes(10), bytes(9), bytes(8), - | bytes(7), bytes(6), bytes(5), bytes(4), bytes(3), bytes(2), bytes(1), bytes(0)) - | } - | - | val bitcoinHeader = getVar[Coll[Byte]](1).get - | val id = reverse32(sha256(sha256(bitcoinHeader))) - | val hit = byteArrayToBigInt(id) - | - | val nBitsBytes = reverse4(bitcoinHeader.slice(72, 76)) - | - | val pad = Coll[Byte](0.toByte, 0.toByte, 0.toByte, 0.toByte) - | - | val nbits = byteArrayToLong(pad ++ nBitsBytes) - | - | val difficulty = nbits.decodeNbits - | - | hit < 500000000000L - |} - |""".stripMargin, - propExp = null, - testExceededCost = false - ) + def powTest() = { + test("Prop1", env, customExt, + """{ + | def reverse4(bytes: Coll[Byte]): Coll[Byte] = { + | Coll(bytes(3), bytes(2), bytes(1), bytes(0)) + | } + | + | def reverse32(bytes: Coll[Byte]): Coll[Byte] = { + | Coll(bytes(31), bytes(30), bytes(29), bytes(28), bytes(27), bytes(26), bytes(25), bytes(24), + | bytes(23), bytes(22), bytes(21), bytes(20), bytes(19), bytes(18), bytes(17), bytes(16), + | bytes(15), bytes(14), bytes(13), bytes(12), bytes(11), bytes(10), bytes(9), bytes(8), + | bytes(7), bytes(6), bytes(5), bytes(4), bytes(3), bytes(2), bytes(1), bytes(0)) + | } + | + | val bitcoinHeader = getVar[Coll[Byte]](1).get + | val id = reverse32(sha256(sha256(bitcoinHeader))) + | val hit = byteArrayToBigInt(id) + | + | val nBitsBytes = reverse4(bitcoinHeader.slice(72, 76)) + | + | val pad = Coll[Byte](0.toByte, 0.toByte, 0.toByte, 0.toByte) + | + | val nbits = byteArrayToLong(pad ++ nBitsBytes) + | + | val difficulty = Global.decodeNbits(nbits) + | + | hit < difficulty + |} + |""".stripMargin, + propExp = null, + testExceededCost = false + ) + } + if (activatedVersionInTests < V6SoftForkVersion) { + an[sigma.exceptions.TyperException] should be thrownBy powTest() + } else { + powTest() + } } property("Relation operations") { From 2e23a2c5e01101c8655ca41160faaf61a5e63427 Mon Sep 17 00:00:00 2001 From: Alexander Slesarenko Date: Tue, 28 May 2024 15:07:01 +0200 Subject: [PATCH 107/314] v6.0-serialize: CheckMinimalErgoTreeVersion rule removed --- .../validation/ValidationRules.scala | 17 +---------------- .../src/main/scala/sigma/ast/methods.scala | 2 -- .../src/test/scala/sigma/SigmaDslTesting.scala | 2 +- 3 files changed, 2 insertions(+), 19 deletions(-) diff --git a/data/shared/src/main/scala/org/ergoplatform/validation/ValidationRules.scala b/data/shared/src/main/scala/org/ergoplatform/validation/ValidationRules.scala index 07fe8db0ee..9d4de47a99 100644 --- a/data/shared/src/main/scala/org/ergoplatform/validation/ValidationRules.scala +++ b/data/shared/src/main/scala/org/ergoplatform/validation/ValidationRules.scala @@ -155,20 +155,6 @@ object ValidationRules { override protected lazy val settings: SigmaValidationSettings = currentSettings } - object CheckMinimalErgoTreeVersion extends ValidationRule(1016, - "ErgoTree should have at least required version") with SoftForkWhenReplaced { - override protected lazy val settings: SigmaValidationSettings = currentSettings - - final def apply(currentVersion: Byte, minVersion: Byte): Unit = { - checkRule() - if (currentVersion < minVersion) { - throwValidationException( - new SigmaException(s"ErgoTree should have at least $minVersion version, but was $currentVersion"), - Array(currentVersion, minVersion)) - } - } - } - val ruleSpecs: Seq[ValidationRule] = Seq( CheckDeserializedScriptType, CheckDeserializedScriptIsSigmaProp, @@ -185,8 +171,7 @@ object ValidationRules { CheckHeaderSizeBit, CheckCostFuncOperation, CheckPositionLimit, - CheckLoopLevelInCostFunction, - CheckMinimalErgoTreeVersion + CheckLoopLevelInCostFunction ) /** Validation settings that correspond to the current version of the ErgoScript implementation. diff --git a/data/shared/src/main/scala/sigma/ast/methods.scala b/data/shared/src/main/scala/sigma/ast/methods.scala index 3f27f85e2d..706c1a7894 100644 --- a/data/shared/src/main/scala/sigma/ast/methods.scala +++ b/data/shared/src/main/scala/sigma/ast/methods.scala @@ -1,7 +1,6 @@ package sigma.ast import org.ergoplatform._ -import org.ergoplatform.validation.ValidationRules.CheckMinimalErgoTreeVersion import org.ergoplatform.validation._ import sigma._ import sigma.ast.SCollection.{SBooleanArray, SBoxArray, SByteArray, SByteArray2, SHeaderArray} @@ -1534,7 +1533,6 @@ case object SGlobalMethods extends MonoTypeMethods { def serialize_eval(mc: MethodCall, G: SigmaDslBuilder, value: SType#WrappedType) (implicit E: ErgoTreeEvaluator): Coll[Byte] = { // TODO v6.0: accumulate cost - CheckMinimalErgoTreeVersion(E.context.currentErgoTreeVersion, VersionContext.V6SoftForkVersion) val t = Evaluation.stypeToRType(mc.args(0).tpe) G.serialize(value)(t) } diff --git a/sc/shared/src/test/scala/sigma/SigmaDslTesting.scala b/sc/shared/src/test/scala/sigma/SigmaDslTesting.scala index 28c9c05fec..f14ba275ff 100644 --- a/sc/shared/src/test/scala/sigma/SigmaDslTesting.scala +++ b/sc/shared/src/test/scala/sigma/SigmaDslTesting.scala @@ -860,7 +860,7 @@ class SigmaDslTesting extends AnyPropSpec extends Feature[A, B] { override def isSupportedIn(vc: VersionContext): Boolean = - vc.activatedVersion >= sinceVersion && vc.ergoTreeVersion >= sinceVersion + vc.activatedVersion >= sinceVersion override def scalaFunc: A => B = { x => sys.error(s"Semantic Scala function is not defined for old implementation: $this") From fe68c66859104cd1580a5b16c6f324b318d7d4bc Mon Sep 17 00:00:00 2001 From: Alexander Slesarenko Date: Tue, 28 May 2024 15:53:43 +0200 Subject: [PATCH 108/314] v6.0-serialize: cleanup + ScalaDocs --- data/shared/src/main/scala/sigma/ast/SMethod.scala | 4 +++- data/shared/src/main/scala/sigma/ast/SigmaPredef.scala | 10 +++++----- data/shared/src/main/scala/sigma/ast/methods.scala | 2 +- data/shared/src/main/scala/sigma/ast/values.scala | 2 +- .../src/test/scala/sigmastate/CrossVersionProps.scala | 2 ++ .../test/scala/sigmastate/lang/SigmaParserTest.scala | 3 +++ .../compiler/ir/wrappers/sigma/impl/SigmaDslImpl.scala | 2 +- .../test/scala/sigmastate/lang/SigmaBinderTest.scala | 3 +++ .../test/scala/sigmastate/lang/SigmaTyperTest.scala | 1 + 9 files changed, 20 insertions(+), 9 deletions(-) diff --git a/data/shared/src/main/scala/sigma/ast/SMethod.scala b/data/shared/src/main/scala/sigma/ast/SMethod.scala index 332c74be6b..47f6e744b0 100644 --- a/data/shared/src/main/scala/sigma/ast/SMethod.scala +++ b/data/shared/src/main/scala/sigma/ast/SMethod.scala @@ -78,7 +78,9 @@ case class SMethod( /** Operation descriptor of this method. */ lazy val opDesc = MethodDesc(this) - /** Return true if this method has runtime type parameters */ + /** Return true if this method has explicit type parameters, which need to be serialized + * as part of [[MethodCall]]. + */ def hasExplicitTypeArgs: Boolean = explicitTypeArgs.nonEmpty /** Finds and keeps the [[RMethod]] instance which corresponds to this method descriptor. diff --git a/data/shared/src/main/scala/sigma/ast/SigmaPredef.scala b/data/shared/src/main/scala/sigma/ast/SigmaPredef.scala index f2da24d2df..7d6da0a5f9 100644 --- a/data/shared/src/main/scala/sigma/ast/SigmaPredef.scala +++ b/data/shared/src/main/scala/sigma/ast/SigmaPredef.scala @@ -405,8 +405,8 @@ object SigmaPredef { val SerializeFunc = PredefinedFunc("serialize", Lambda(Seq(paramT), Array("value" -> tT), SByteArray, None), - PredefFuncInfo( - { case (_, args @ Seq(value)) => + irInfo = PredefFuncInfo( + irBuilder = { case (_, args @ Seq(value)) => MethodCall.typed[Value[SCollection[SByte.type]]]( Global, SGlobalMethods.serializeMethod.withConcreteTypes(Map(tT -> value.tpe)), @@ -414,10 +414,10 @@ object SigmaPredef { Map() ) }), - OperationInfo(MethodCall, - """ + docInfo = OperationInfo(MethodCall, + """Serializes the given `value` into bytes using the default serialization format. """.stripMargin, - Seq(ArgInfo("value", "")) + Seq(ArgInfo("value", "value to serialize")) ) ) diff --git a/data/shared/src/main/scala/sigma/ast/methods.scala b/data/shared/src/main/scala/sigma/ast/methods.scala index 706c1a7894..262a3266dd 100644 --- a/data/shared/src/main/scala/sigma/ast/methods.scala +++ b/data/shared/src/main/scala/sigma/ast/methods.scala @@ -1522,7 +1522,7 @@ case object SGlobalMethods extends MonoTypeMethods { lazy val serializeMethod = SMethod(this, "serialize", SFunc(Array(SGlobal, tT), SByteArray, Array(paramT)), 3, DynamicCost) .withIRInfo(MethodCallIrBuilder) - .withInfo(MethodCall, "", + .withInfo(MethodCall, "Serializes the given `value` into bytes using the default serialization format.", ArgInfo("value", "value to be serialized")) diff --git a/data/shared/src/main/scala/sigma/ast/values.scala b/data/shared/src/main/scala/sigma/ast/values.scala index 7980fd96ce..dd1f10d9be 100644 --- a/data/shared/src/main/scala/sigma/ast/values.scala +++ b/data/shared/src/main/scala/sigma/ast/values.scala @@ -1299,7 +1299,7 @@ case class MethodCall( args: IndexedSeq[Value[SType]], typeSubst: Map[STypeVar, SType]) extends Value[SType] { require(method.explicitTypeArgs.forall(tyArg => typeSubst.contains(tyArg)), - s"Runtime Generic method call should have concrete type for each runtime type parameter, but was: $this") + s"Generic method call should have concrete type for each explicit type parameter, but was: $this") override def companion = if (args.isEmpty) PropertyCall else MethodCall override def opType: SFunc = SFunc(obj.tpe +: args.map(_.tpe), tpe) diff --git a/interpreter/shared/src/test/scala/sigmastate/CrossVersionProps.scala b/interpreter/shared/src/test/scala/sigmastate/CrossVersionProps.scala index e55b874dc3..87101a1f71 100644 --- a/interpreter/shared/src/test/scala/sigmastate/CrossVersionProps.scala +++ b/interpreter/shared/src/test/scala/sigmastate/CrossVersionProps.scala @@ -31,7 +31,9 @@ trait CrossVersionProps extends AnyPropSpecLike with TestsBase { System.gc() } forEachScriptAndErgoTreeVersion(activatedVersions, ergoTreeVersions) { + VersionContext.withVersions(activatedVersionInTests, ergoTreeVersionInTests) { testFun_Run(testName, testFun) + } } } } diff --git a/parsers/shared/src/test/scala/sigmastate/lang/SigmaParserTest.scala b/parsers/shared/src/test/scala/sigmastate/lang/SigmaParserTest.scala index 70aa540a4f..5a0f2b3465 100644 --- a/parsers/shared/src/test/scala/sigmastate/lang/SigmaParserTest.scala +++ b/parsers/shared/src/test/scala/sigmastate/lang/SigmaParserTest.scala @@ -35,6 +35,9 @@ class SigmaParserTest extends AnyPropSpec with ScalaCheckPropertyChecks with Mat } } + /** Checks parsing result, printing the actual value as a test vector if expected value + * is not equal to actual. + */ def checkParsed(x: String, expected: SValue) = { val parsed = parse(x) if (expected != parsed) { diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/SigmaDslImpl.scala b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/SigmaDslImpl.scala index 9cd524149d..c089c0ccb5 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/SigmaDslImpl.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/SigmaDslImpl.scala @@ -1950,7 +1950,7 @@ object SigmaDslBuilder extends EntityObject("SigmaDslBuilder") { asRep[Coll[Byte]](mkMethodCall(self, SigmaDslBuilderClass.getMethod("serialize", classOf[Sym]), Array[AnyRef](value), - true, true, element[Coll[Byte]])) + true, false, element[Coll[Byte]])) } } diff --git a/sc/shared/src/test/scala/sigmastate/lang/SigmaBinderTest.scala b/sc/shared/src/test/scala/sigmastate/lang/SigmaBinderTest.scala index 54bd89c9c2..3c3687cb37 100644 --- a/sc/shared/src/test/scala/sigmastate/lang/SigmaBinderTest.scala +++ b/sc/shared/src/test/scala/sigmastate/lang/SigmaBinderTest.scala @@ -31,6 +31,9 @@ class SigmaBinderTest extends AnyPropSpec with ScalaCheckPropertyChecks with Mat res } + /** Checks that parsing and binding results in the expected value. + * @return the inferred type of the expression + */ def checkBound(env: ScriptEnv, x: String, expected: SValue) = { val bound = bind(env, x) if (expected != bound) { diff --git a/sc/shared/src/test/scala/sigmastate/lang/SigmaTyperTest.scala b/sc/shared/src/test/scala/sigmastate/lang/SigmaTyperTest.scala index 2c3bd44d39..8aeefba8a7 100644 --- a/sc/shared/src/test/scala/sigmastate/lang/SigmaTyperTest.scala +++ b/sc/shared/src/test/scala/sigmastate/lang/SigmaTyperTest.scala @@ -30,6 +30,7 @@ class SigmaTyperTest extends AnyPropSpec private val predefFuncRegistry = new PredefinedFuncRegistry(StdSigmaBuilder) import predefFuncRegistry._ + /** Checks that parsing, binding and typing of `x` results in the given expected value. */ def typecheck(env: ScriptEnv, x: String, expected: SValue = null): SType = { try { val builder = TransformingSigmaBuilder From a5321af4e41f6f6d25fceaec079d16a8786caf38 Mon Sep 17 00:00:00 2001 From: Alexander Slesarenko Date: Tue, 28 May 2024 20:44:27 +0200 Subject: [PATCH 109/314] v6.0-serialize: added CoreByteWriter.checkCostLimit --- .../sigma/serialization/CoreByteWriter.scala | 150 ++++++++++++++---- .../sigma/serialization/CoreSerializer.scala | 2 +- .../sigma/serialization/SigmaByteWriter.scala | 65 ++++++-- .../sigma/serialization/SigmaSerializer.scala | 7 +- 4 files changed, 178 insertions(+), 46 deletions(-) diff --git a/core/shared/src/main/scala/sigma/serialization/CoreByteWriter.scala b/core/shared/src/main/scala/sigma/serialization/CoreByteWriter.scala index aa4255449c..302663ba92 100644 --- a/core/shared/src/main/scala/sigma/serialization/CoreByteWriter.scala +++ b/core/shared/src/main/scala/sigma/serialization/CoreByteWriter.scala @@ -3,25 +3,47 @@ package sigma.serialization import scorex.util.serialization.Writer.Aux import scorex.util.serialization.{VLQByteBufferWriter, Writer} import sigma.ast.SType -import sigma.serialization.CoreByteWriter.{Bits, DataInfo, U, Vlq, ZigZag} +import sigma.serialization.CoreByteWriter.{Bits, CostLimitChecker, DataInfo, U, Vlq, ZigZag} /** Implementation of [[Writer]] provided by `sigma-core` module. - * @param w destination [[Writer]] to which all the call got delegated. + * + * @param w destination [[Writer]] to which all the call got delegated. + * @param checkCostLimitOpt callback to check if the cost limit at current writing position + * is reached. The callback will throw an exception if the limit is reached. + * Note, the cost of serialization is approximated using formula + * `this.length * CostPerByte + InitialCost` */ -class CoreByteWriter(val w: Writer) extends Writer { +class CoreByteWriter(val w: Writer, val checkCostLimitOpt: Option[CostLimitChecker]) extends Writer { type CH = w.CH + /** Check the current writer length against the cost limit. */ + @inline protected def checkCostLimit(): Unit = { + if (checkCostLimitOpt.isDefined) + checkCostLimitOpt.get(this.length()) + } + @inline override def length(): Int = w.length() @inline override def newWriter(): Aux[CH] = w.newWriter() - @inline override def putChunk(chunk: CH): this.type = { w.putChunk(chunk); this } + @inline override def putChunk(chunk: CH): this.type = { + w.putChunk(chunk); + checkCostLimit() + this + } @inline override def result(): CH = w.result() - @inline def put(x: Byte): this.type = { w.put(x); this } + @inline def put(x: Byte): this.type = { + w.put(x); + checkCostLimit() + this + } + @inline def put(x: Byte, info: DataInfo[Byte]): this.type = { - w.put(x); this + w.put(x); + checkCostLimit() + this } override def putUByte(x: Int): this.type = { @@ -31,49 +53,105 @@ class CoreByteWriter(val w: Writer) extends Writer { super.putUByte(x) } - @inline def putBoolean(x: Boolean): this.type = { w.putBoolean(x); this } + @inline def putBoolean(x: Boolean): this.type = { + w.putBoolean(x); + checkCostLimit() + this + } + @inline def putBoolean(x: Boolean, info: DataInfo[Boolean]): this.type = { - w.putBoolean(x); this + w.putBoolean(x); + checkCostLimit() + this + } + + @inline def putShort(x: Short): this.type = { + w.putShort(x); + checkCostLimit() + this } - @inline def putShort(x: Short): this.type = { w.putShort(x); this } @inline def putShort(x: Short, info: DataInfo[Short]): this.type = { - w.putShort(x); this + w.putShort(x); + checkCostLimit() + this + } + + @inline def putUShort(x: Int): this.type = { + w.putUShort(x); + checkCostLimit() + this } - @inline def putUShort(x: Int): this.type = { w.putUShort(x); this } @inline def putUShort(x: Int, info: DataInfo[Vlq[U[Short]]]): this.type = { - w.putUShort(x); this + w.putUShort(x); + checkCostLimit() + this + } + + @inline def putInt(x: Int): this.type = { + w.putInt(x); + checkCostLimit() + this } - @inline def putInt(x: Int): this.type = { w.putInt(x); this } @inline def putInt(x: Int, info: DataInfo[Int]): this.type = { - w.putInt(x); this + w.putInt(x); + checkCostLimit() + this } - @inline def putUInt(x: Long): this.type = { w.putUInt(x); this } + @inline def putUInt(x: Long): this.type = { + w.putUInt(x); + checkCostLimit() + this + } @inline def putUInt(x: Long, info: DataInfo[Vlq[U[Int]]]): this.type = { - w.putUInt(x); this + w.putUInt(x); + checkCostLimit() + this } - @inline def putLong(x: Long): this.type = { w.putLong(x); this } + @inline def putLong(x: Long): this.type = { + w.putLong(x); + checkCostLimit() + this + } @inline def putLong(x: Long, info: DataInfo[Vlq[ZigZag[Long]]]): this.type = { - w.putLong(x); this + w.putLong(x); + checkCostLimit() + this + } + + @inline def putULong(x: Long): this.type = { + w.putULong(x); + checkCostLimit() + this } - @inline def putULong(x: Long): this.type = { w.putULong(x); this } @inline def putULong(x: Long, info: DataInfo[Vlq[U[Long]]]): this.type = { - w.putULong(x); this + w.putULong(x); + checkCostLimit() + this } override def putBytes(xs: Array[Byte], offset: Int, length: Int): this.type = { - w.putBytes(xs, offset, length); this + w.putBytes(xs, offset, length); + checkCostLimit() + this + } + + @inline def putBytes(xs: Array[Byte]): this.type = { + w.putBytes(xs); + checkCostLimit() + this } - @inline def putBytes(xs: Array[Byte]): this.type = { w.putBytes(xs); this } @inline def putBytes(xs: Array[Byte], info: DataInfo[Array[Byte]]): this.type = { - w.putBytes(xs); this + w.putBytes(xs); + checkCostLimit() + this } /** Put the two bytes of the big-endian representation of the Short value into the @@ -81,12 +159,18 @@ class CoreByteWriter(val w: Writer) extends Writer { @inline def putShortBytes(value: Short): this.type = { w.put((value >> 8).toByte) w.put(value.toByte) + checkCostLimit() this } - @inline def putBits(xs: Array[Boolean]): this.type = { w.putBits(xs); this } + @inline def putBits(xs: Array[Boolean]): this.type = { + w.putBits(xs); + checkCostLimit() + this + } @inline def putBits(xs: Array[Boolean], info: DataInfo[Bits]): this.type = { w.putBits(xs); + checkCostLimit() this } @@ -94,19 +178,28 @@ class CoreByteWriter(val w: Writer) extends Writer { w.putOption(x) { (_, v) => putValueC(this, v) } + checkCostLimit() this } - @inline def putShortString(s: String): this.type = { w.putShortString(s); this } + @inline def putShortString(s: String): this.type = { + w.putShortString(s); + checkCostLimit() + this + } // TODO refactor: move to Writer @inline def toBytes: Array[Byte] = w match { case wr: VLQByteBufferWriter => wr.toBytes } - @inline def putType[T <: SType](x: T): this.type = { TypeSerializer.serialize(x, this); this } + @inline def putType[T <: SType](x: T): this.type = { + TypeSerializer.serialize(x, this); // the cost is checked in TypeSerializer + this + } @inline def putType[T <: SType](x: T, info: DataInfo[SType]): this.type = { - TypeSerializer.serialize(x, this); this + TypeSerializer.serialize(x, this); // the cost is checked in TypeSerializer + this } } @@ -114,6 +207,9 @@ class CoreByteWriter(val w: Writer) extends Writer { object CoreByteWriter { import scala.language.implicitConversions + /** Callback type of cost limit checker. */ + type CostLimitChecker = Int => Unit + /** Format descriptor type family. */ trait FormatDescriptor[T] { /** Size formula associated with this format */ diff --git a/core/shared/src/main/scala/sigma/serialization/CoreSerializer.scala b/core/shared/src/main/scala/sigma/serialization/CoreSerializer.scala index 938d3f22c1..2ec3ee5c1a 100644 --- a/core/shared/src/main/scala/sigma/serialization/CoreSerializer.scala +++ b/core/shared/src/main/scala/sigma/serialization/CoreSerializer.scala @@ -66,7 +66,7 @@ object CoreSerializer { def startWriter(): CoreByteWriter = { val b = new ByteArrayBuilder() val wi = new VLQByteBufferWriter(b) - val w = new CoreByteWriter(wi) + val w = new CoreByteWriter(wi, None) w } diff --git a/data/shared/src/main/scala/sigma/serialization/SigmaByteWriter.scala b/data/shared/src/main/scala/sigma/serialization/SigmaByteWriter.scala index 35d5e0c9b9..87b115e942 100644 --- a/data/shared/src/main/scala/sigma/serialization/SigmaByteWriter.scala +++ b/data/shared/src/main/scala/sigma/serialization/SigmaByteWriter.scala @@ -4,15 +4,28 @@ import scorex.util.serialization.Writer import sigma.ast.syntax._ import sigma.ast._ import sigma.serialization.CoreByteWriter.{ArgInfo, DataInfo, FormatDescriptor, SeqFmt} - -class SigmaByteWriter(override val w: Writer, - val constantExtractionStore: Option[ConstantStore]) - extends CoreByteWriter(w) { +import CoreByteWriter.CostLimitChecker + +/** Implementation of [[Writer]] provided by `sigma-data` module. + * + * @param w destination [[Writer]] to which all the call got delegated. + * @param constantExtractionStore optional store to segregate constants to while + * replacing them with placeholders. + * @param checkCostLimitOpt callback to check if the cost limit at current writing position + * is reached. The callback will throw an exception if the limit is reached. + */ +class SigmaByteWriter( + override val w: Writer, + val constantExtractionStore: Option[ConstantStore], + override val checkCostLimitOpt: Option[CostLimitChecker] +) + extends CoreByteWriter(w, checkCostLimitOpt) { import CoreByteWriter._ import ValueSerializer._ override def put(x: Byte, info: DataInfo[Byte]): this.type = { ValueSerializer.addArgInfo(info) + checkCostLimit() w.put(x); this } @@ -23,59 +36,81 @@ class SigmaByteWriter(override val w: Writer, @inline override def putBoolean(x: Boolean, info: DataInfo[Boolean]): this.type = { ValueSerializer.addArgInfo(info) - w.putBoolean(x); this + w.putBoolean(x); + checkCostLimit() + this } @inline override def putShort(x: Short, info: DataInfo[Short]): this.type = { ValueSerializer.addArgInfo(info) - w.putShort(x); this + w.putShort(x); + checkCostLimit() + this } @inline override def putUShort(x: Int, info: DataInfo[Vlq[U[Short]]]): this.type = { ValueSerializer.addArgInfo(info) - w.putUShort(x); this + w.putUShort(x); + checkCostLimit() + this } @inline override def putInt(x: Int, info: DataInfo[Int]): this.type = { ValueSerializer.addArgInfo(info) - w.putInt(x); this + w.putInt(x); + checkCostLimit() + this } @inline override def putUInt(x: Long, info: DataInfo[Vlq[U[Int]]]): this.type = { ValueSerializer.addArgInfo(info) - w.putUInt(x); this + w.putUInt(x); + checkCostLimit() + this } @inline override def putLong(x: Long, info: DataInfo[Vlq[ZigZag[Long]]]): this.type = { ValueSerializer.addArgInfo(info) - w.putLong(x); this + w.putLong(x); + checkCostLimit() + this } @inline override def putULong(x: Long, info: DataInfo[Vlq[U[Long]]]): this.type = { ValueSerializer.addArgInfo(info) - w.putULong(x); this + w.putULong(x); + checkCostLimit() + this } @inline override def putBytes(xs: Array[Byte], info: DataInfo[Array[Byte]]): this.type = { ValueSerializer.addArgInfo(info) - w.putBytes(xs); this + w.putBytes(xs); + checkCostLimit() + this } @inline override def putBits(xs: Array[Boolean], info: DataInfo[Bits]): this.type = { ValueSerializer.addArgInfo(info) w.putBits(xs); + checkCostLimit() this } @inline override def putType[T <: SType](x: T, info: DataInfo[SType]): this.type = { ValueSerializer.addArgInfo(info) - TypeSerializer.serialize(x, this); this + TypeSerializer.serialize(x, this); // the cost is checked in TypeSerializer + this } - @inline def putValue[T <: SType](x: Value[T]): this.type = { ValueSerializer.serialize(x, this); this } + @inline def putValue[T <: SType](x: Value[T]): this.type = { + ValueSerializer.serialize(x, this) // the cost is checked in ValueSerializer + this + } @inline def putValue[T <: SType](x: Value[T], info: DataInfo[SValue]): this.type = { ValueSerializer.addArgInfo(info) - ValueSerializer.serialize(x, this); this + ValueSerializer.serialize(x, this); // the cost is checked in ValueSerializer + this } @inline def putValues[T <: SType](xs: Seq[Value[T]]): this.type = { putUInt(xs.length) diff --git a/data/shared/src/main/scala/sigma/serialization/SigmaSerializer.scala b/data/shared/src/main/scala/sigma/serialization/SigmaSerializer.scala index 3765adb029..e842258f80 100644 --- a/data/shared/src/main/scala/sigma/serialization/SigmaSerializer.scala +++ b/data/shared/src/main/scala/sigma/serialization/SigmaSerializer.scala @@ -4,6 +4,7 @@ import java.nio.ByteBuffer import scorex.util.ByteArrayBuilder import scorex.util.serialization._ import sigma.data.SigmaConstants +import sigma.serialization.CoreByteWriter.CostLimitChecker import sigma.serialization.ValueCodes.OpCode object SigmaSerializer { @@ -51,14 +52,14 @@ object SigmaSerializer { def startWriter(): SigmaByteWriter = { val b = new ByteArrayBuilder() val wi = new VLQByteBufferWriter(b) - val w = new SigmaByteWriter(wi, constantExtractionStore = None) + val w = new SigmaByteWriter(wi, constantExtractionStore = None, checkCostLimitOpt = None) w } - def startWriter(constantExtractionStore: ConstantStore): SigmaByteWriter = { + def startWriter(constantExtractionStore: ConstantStore, checkCostLimit: Option[CostLimitChecker] = None): SigmaByteWriter = { val b = new ByteArrayBuilder() val wi = new VLQByteBufferWriter(b) - val w = new SigmaByteWriter(wi, constantExtractionStore = Some(constantExtractionStore)) + val w = new SigmaByteWriter(wi, constantExtractionStore = Some(constantExtractionStore), checkCostLimit) w } } From 37b23cd9f981e4d29ed4a89c6e661040679888ee Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Wed, 29 May 2024 12:52:49 +0300 Subject: [PATCH 110/314] hit <= diff --- .../src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala index abfe9c0df4..8b7cfc07b2 100644 --- a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala @@ -191,7 +191,8 @@ class BasicOpsSpecification extends CompilerTestingCommons | | val difficulty = Global.decodeNbits(nbits) | - | hit < difficulty + | // <= according to https://bitcoin.stackexchange.com/a/105224 + | hit <= difficulty |} |""".stripMargin, propExp = null, From 432addca9dbef1dc2d1f44e797bfbe2bab376c7a Mon Sep 17 00:00:00 2001 From: Alexander Slesarenko Date: Wed, 29 May 2024 17:59:28 +0200 Subject: [PATCH 111/314] v6.0-serialize: cost accumulation in SigmaByteWriter and serialize_eval method --- .../sigma/serialization/CoreByteWriter.scala | 115 +++------ .../sigma/serialization/CoreSerializer.scala | 2 +- .../src/main/scala/sigma/ast/ErgoTree.scala | 2 +- .../src/main/scala/sigma/ast/methods.scala | 15 +- .../serialization/ErgoTreeSerializer.scala | 2 +- .../sigma/serialization/SigmaByteWriter.scala | 236 ++++++++++++++---- .../sigma/serialization/SigmaSerializer.scala | 12 +- .../test/scala/sigma/SigmaDslTesting.scala | 12 +- 8 files changed, 243 insertions(+), 153 deletions(-) diff --git a/core/shared/src/main/scala/sigma/serialization/CoreByteWriter.scala b/core/shared/src/main/scala/sigma/serialization/CoreByteWriter.scala index 302663ba92..37d1455ba3 100644 --- a/core/shared/src/main/scala/sigma/serialization/CoreByteWriter.scala +++ b/core/shared/src/main/scala/sigma/serialization/CoreByteWriter.scala @@ -3,155 +3,106 @@ package sigma.serialization import scorex.util.serialization.Writer.Aux import scorex.util.serialization.{VLQByteBufferWriter, Writer} import sigma.ast.SType -import sigma.serialization.CoreByteWriter.{Bits, CostLimitChecker, DataInfo, U, Vlq, ZigZag} +import sigma.serialization.CoreByteWriter._ /** Implementation of [[Writer]] provided by `sigma-core` module. * * @param w destination [[Writer]] to which all the call got delegated. - * @param checkCostLimitOpt callback to check if the cost limit at current writing position - * is reached. The callback will throw an exception if the limit is reached. - * Note, the cost of serialization is approximated using formula - * `this.length * CostPerByte + InitialCost` */ -class CoreByteWriter(val w: Writer, val checkCostLimitOpt: Option[CostLimitChecker]) extends Writer { +class CoreByteWriter(val w: Writer) extends Writer { type CH = w.CH - /** Check the current writer length against the cost limit. */ - @inline protected def checkCostLimit(): Unit = { - if (checkCostLimitOpt.isDefined) - checkCostLimitOpt.get(this.length()) - } - @inline override def length(): Int = w.length() @inline override def newWriter(): Aux[CH] = w.newWriter() @inline override def putChunk(chunk: CH): this.type = { - w.putChunk(chunk); - checkCostLimit() - this + w.putChunk(chunk); this } @inline override def result(): CH = w.result() - @inline def put(x: Byte): this.type = { - w.put(x); - checkCostLimit() - this + @inline override def put(x: Byte): this.type = { + w.put(x); this } @inline def put(x: Byte, info: DataInfo[Byte]): this.type = { - w.put(x); - checkCostLimit() - this + w.put(x); this } override def putUByte(x: Int): this.type = { super.putUByte(x) } + def putUByte(x: Int, info: DataInfo[U[Byte]]): this.type = { super.putUByte(x) } @inline def putBoolean(x: Boolean): this.type = { - w.putBoolean(x); - checkCostLimit() - this + w.putBoolean(x); this } @inline def putBoolean(x: Boolean, info: DataInfo[Boolean]): this.type = { - w.putBoolean(x); - checkCostLimit() - this + w.putBoolean(x); this } @inline def putShort(x: Short): this.type = { - w.putShort(x); - checkCostLimit() - this + w.putShort(x); this } @inline def putShort(x: Short, info: DataInfo[Short]): this.type = { - w.putShort(x); - checkCostLimit() - this + w.putShort(x); this } @inline def putUShort(x: Int): this.type = { - w.putUShort(x); - checkCostLimit() - this + w.putUShort(x); this } @inline def putUShort(x: Int, info: DataInfo[Vlq[U[Short]]]): this.type = { - w.putUShort(x); - checkCostLimit() - this + w.putUShort(x); this } @inline def putInt(x: Int): this.type = { - w.putInt(x); - checkCostLimit() - this + w.putInt(x); this } @inline def putInt(x: Int, info: DataInfo[Int]): this.type = { - w.putInt(x); - checkCostLimit() - this + w.putInt(x); this } @inline def putUInt(x: Long): this.type = { - w.putUInt(x); - checkCostLimit() - this + w.putUInt(x); this } @inline def putUInt(x: Long, info: DataInfo[Vlq[U[Int]]]): this.type = { - w.putUInt(x); - checkCostLimit() - this + w.putUInt(x); this } @inline def putLong(x: Long): this.type = { - w.putLong(x); - checkCostLimit() - this + w.putLong(x); this } @inline def putLong(x: Long, info: DataInfo[Vlq[ZigZag[Long]]]): this.type = { - w.putLong(x); - checkCostLimit() - this + w.putLong(x); this } @inline def putULong(x: Long): this.type = { - w.putULong(x); - checkCostLimit() - this + w.putULong(x); this } @inline def putULong(x: Long, info: DataInfo[Vlq[U[Long]]]): this.type = { - w.putULong(x); - checkCostLimit() - this + w.putULong(x); this } override def putBytes(xs: Array[Byte], offset: Int, length: Int): this.type = { - w.putBytes(xs, offset, length); - checkCostLimit() - this + w.putBytes(xs, offset, length); this } @inline def putBytes(xs: Array[Byte]): this.type = { - w.putBytes(xs); - checkCostLimit() - this + w.putBytes(xs); this } @inline def putBytes(xs: Array[Byte], info: DataInfo[Array[Byte]]): this.type = { - w.putBytes(xs); - checkCostLimit() - this + w.putBytes(xs); this } /** Put the two bytes of the big-endian representation of the Short value into the @@ -159,32 +110,25 @@ class CoreByteWriter(val w: Writer, val checkCostLimitOpt: Option[CostLimitCheck @inline def putShortBytes(value: Short): this.type = { w.put((value >> 8).toByte) w.put(value.toByte) - checkCostLimit() this } @inline def putBits(xs: Array[Boolean]): this.type = { - w.putBits(xs); - checkCostLimit() - this + w.putBits(xs); this } @inline def putBits(xs: Array[Boolean], info: DataInfo[Bits]): this.type = { - w.putBits(xs); - checkCostLimit() - this + w.putBits(xs); this } @inline def putOption[T](x: Option[T])(putValueC: (this.type, T) => Unit): this.type = { w.putOption(x) { (_, v) => putValueC(this, v) } - checkCostLimit() this } @inline def putShortString(s: String): this.type = { w.putShortString(s); - checkCostLimit() this } @@ -194,11 +138,11 @@ class CoreByteWriter(val w: Writer, val checkCostLimitOpt: Option[CostLimitCheck } @inline def putType[T <: SType](x: T): this.type = { - TypeSerializer.serialize(x, this); // the cost is checked in TypeSerializer + TypeSerializer.serialize(x, this) this } @inline def putType[T <: SType](x: T, info: DataInfo[SType]): this.type = { - TypeSerializer.serialize(x, this); // the cost is checked in TypeSerializer + TypeSerializer.serialize(x, this) this } @@ -207,9 +151,6 @@ class CoreByteWriter(val w: Writer, val checkCostLimitOpt: Option[CostLimitCheck object CoreByteWriter { import scala.language.implicitConversions - /** Callback type of cost limit checker. */ - type CostLimitChecker = Int => Unit - /** Format descriptor type family. */ trait FormatDescriptor[T] { /** Size formula associated with this format */ diff --git a/core/shared/src/main/scala/sigma/serialization/CoreSerializer.scala b/core/shared/src/main/scala/sigma/serialization/CoreSerializer.scala index 2ec3ee5c1a..938d3f22c1 100644 --- a/core/shared/src/main/scala/sigma/serialization/CoreSerializer.scala +++ b/core/shared/src/main/scala/sigma/serialization/CoreSerializer.scala @@ -66,7 +66,7 @@ object CoreSerializer { def startWriter(): CoreByteWriter = { val b = new ByteArrayBuilder() val wi = new VLQByteBufferWriter(b) - val w = new CoreByteWriter(wi, None) + val w = new CoreByteWriter(wi) w } diff --git a/data/shared/src/main/scala/sigma/ast/ErgoTree.scala b/data/shared/src/main/scala/sigma/ast/ErgoTree.scala index 68d69abd91..8d731e1c67 100644 --- a/data/shared/src/main/scala/sigma/ast/ErgoTree.scala +++ b/data/shared/src/main/scala/sigma/ast/ErgoTree.scala @@ -381,7 +381,7 @@ object ErgoTree { * */ def withSegregation(header: HeaderType, prop: SigmaPropValue): ErgoTree = { val constantStore = new ConstantStore() - val w = SigmaSerializer.startWriter(constantStore) + val w = SigmaSerializer.startWriter(Some(constantStore)) // serialize value and segregate constants into constantStore ValueSerializer.serialize(prop, w) val extractedConstants = constantStore.getAll diff --git a/data/shared/src/main/scala/sigma/ast/methods.scala b/data/shared/src/main/scala/sigma/ast/methods.scala index 262a3266dd..fd9024ee62 100644 --- a/data/shared/src/main/scala/sigma/ast/methods.scala +++ b/data/shared/src/main/scala/sigma/ast/methods.scala @@ -12,6 +12,7 @@ import sigma.data.{DataValueComparer, KeyValueColl, Nullable, RType, SigmaConsta import sigma.eval.{CostDetails, ErgoTreeEvaluator, TracedCost} import sigma.reflection.RClass import sigma.serialization.CoreByteWriter.ArgInfo +import sigma.serialization.{DataSerializer, SigmaSerializer} import sigma.utils.SparseArrayContainer import scala.annotation.unused @@ -1532,9 +1533,17 @@ case object SGlobalMethods extends MonoTypeMethods { */ def serialize_eval(mc: MethodCall, G: SigmaDslBuilder, value: SType#WrappedType) (implicit E: ErgoTreeEvaluator): Coll[Byte] = { - // TODO v6.0: accumulate cost - val t = Evaluation.stypeToRType(mc.args(0).tpe) - G.serialize(value)(t) + + val addFixedCostCallback = { (costInfo: OperationCostInfo[FixedCost]) => + E.addCost(costInfo) + } + val addPerItemCostCallback = { (info: OperationCostInfo[PerItemCost], nItems: Int) => + E.addSeqCostNoOp(info.costKind, nItems, info.opDesc) + } + val w = SigmaSerializer.startWriter(None, + Some(addFixedCostCallback), Some(addPerItemCostCallback)) + DataSerializer.serialize(value, mc.args(0).tpe, w) + Colls.fromArray(w.toBytes) } protected override def getMethods() = super.getMethods() ++ { diff --git a/data/shared/src/main/scala/sigma/serialization/ErgoTreeSerializer.scala b/data/shared/src/main/scala/sigma/serialization/ErgoTreeSerializer.scala index 43e41f91ff..ce7d1241c3 100644 --- a/data/shared/src/main/scala/sigma/serialization/ErgoTreeSerializer.scala +++ b/data/shared/src/main/scala/sigma/serialization/ErgoTreeSerializer.scala @@ -347,7 +347,7 @@ class ErgoTreeSerializer { 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(constantStore) + val valW = SigmaSerializer.startWriter(Some(constantStore)) valW.putValue(newVal) val newConsts = constantStore.getAll require(newConsts.length == 1) diff --git a/data/shared/src/main/scala/sigma/serialization/SigmaByteWriter.scala b/data/shared/src/main/scala/sigma/serialization/SigmaByteWriter.scala index 87b115e942..93e078e319 100644 --- a/data/shared/src/main/scala/sigma/serialization/SigmaByteWriter.scala +++ b/data/shared/src/main/scala/sigma/serialization/SigmaByteWriter.scala @@ -4,28 +4,52 @@ import scorex.util.serialization.Writer import sigma.ast.syntax._ import sigma.ast._ import sigma.serialization.CoreByteWriter.{ArgInfo, DataInfo, FormatDescriptor, SeqFmt} -import CoreByteWriter.CostLimitChecker +import SigmaByteWriter._ /** Implementation of [[Writer]] provided by `sigma-data` module. * - * @param w destination [[Writer]] to which all the call got delegated. - * @param constantExtractionStore optional store to segregate constants to while - * replacing them with placeholders. - * @param checkCostLimitOpt callback to check if the cost limit at current writing position - * is reached. The callback will throw an exception if the limit is reached. + * @param w destination [[Writer]] to which all the call got delegated. + * @param constantExtractionStore optional store to segregate constants to while + * replacing them with placeholders. + * @param addFixedCostCallbackOpt optional callback to accumulate fixed costs. + * @param addPerItemCostCallbackOpt optional callback to accumulate per-item costs. */ class SigmaByteWriter( override val w: Writer, val constantExtractionStore: Option[ConstantStore], - override val checkCostLimitOpt: Option[CostLimitChecker] -) - extends CoreByteWriter(w, checkCostLimitOpt) { + val addFixedCostCallbackOpt: Option[FixedCostCallback], + val addPerItemCostCallbackOpt: Option[PerItemCostCallback] +) extends CoreByteWriter(w) { import CoreByteWriter._ import ValueSerializer._ + /** Adds the given cost to the callback if it is defined. */ + @inline private def addFixedCost(cost: OperationCostInfo[FixedCost]): Unit = { + if (addFixedCostCallbackOpt.isDefined) + addFixedCostCallbackOpt.get(cost) + } + + /** Adds the given cost to the callback if it is defined. */ + @inline private def addPerItemCost(cost: OperationCostInfo[PerItemCost], nItems: Int): Unit = { + if (addPerItemCostCallbackOpt.isDefined) + addPerItemCostCallbackOpt.get(cost, nItems) + } + + override def putChunk(chunk: w.CH): SigmaByteWriter.this.type = { + val start = length() + super.putChunk(chunk) + addPerItemCost(PutChunkCost, length() - start) + this + } + + override def put(x: Byte): this.type = { + addFixedCost(PutByteCost) + super.put(x) + } + override def put(x: Byte, info: DataInfo[Byte]): this.type = { ValueSerializer.addArgInfo(info) - checkCostLimit() + addFixedCost(PutByteCost) w.put(x); this } @@ -34,90 +58,160 @@ class SigmaByteWriter( super.putUByte(x) } - @inline override def putBoolean(x: Boolean, info: DataInfo[Boolean]): this.type = { + override def putBoolean(x: Boolean): this.type = { + addFixedCost(PutByteCost) + super.putBoolean(x) + } + + override def putBoolean(x: Boolean, info: DataInfo[Boolean]): this.type = { ValueSerializer.addArgInfo(info) - w.putBoolean(x); - checkCostLimit() - this + addFixedCost(PutByteCost) + w.putBoolean(x); this + } + + override def putShort(x: Short): this.type = { + addFixedCost(PutSignedNumericCost) + super.putShort(x) } - @inline override def putShort(x: Short, info: DataInfo[Short]): this.type = { + override def putShort(x: Short, info: DataInfo[Short]): this.type = { ValueSerializer.addArgInfo(info) - w.putShort(x); - checkCostLimit() - this + addFixedCost(PutSignedNumericCost) + w.putShort(x); this + } + + override def putUShort(x: Int): this.type = { + addFixedCost(PutUnsignedNumericCost) + super.putUShort(x) } - @inline override def putUShort(x: Int, info: DataInfo[Vlq[U[Short]]]): this.type = { + override def putUShort(x: Int, info: DataInfo[Vlq[U[Short]]]): this.type = { ValueSerializer.addArgInfo(info) - w.putUShort(x); - checkCostLimit() - this + addFixedCost(PutUnsignedNumericCost) + w.putUShort(x); this } - @inline override def putInt(x: Int, info: DataInfo[Int]): this.type = { + override def putInt(x: Int): this.type = { + addFixedCost(PutSignedNumericCost) + super.putInt(x) + } + + override def putInt(x: Int, info: DataInfo[Int]): this.type = { ValueSerializer.addArgInfo(info) - w.putInt(x); - checkCostLimit() - this + addFixedCost(PutSignedNumericCost) + w.putInt(x); this } - @inline override def putUInt(x: Long, info: DataInfo[Vlq[U[Int]]]): this.type = { + override def putUInt(x: Long): SigmaByteWriter.this.type = { + super.putUInt(x) + } + + override def putUInt(x: Long, info: DataInfo[Vlq[U[Int]]]): this.type = { ValueSerializer.addArgInfo(info) - w.putUInt(x); - checkCostLimit() - this + addFixedCost(PutUnsignedNumericCost) + w.putUInt(x); this } - @inline override def putLong(x: Long, info: DataInfo[Vlq[ZigZag[Long]]]): this.type = { + override def putLong(x: Long): SigmaByteWriter.this.type = { + addFixedCost(PutSignedNumericCost) + super.putLong(x) + } + + override def putLong(x: Long, info: DataInfo[Vlq[ZigZag[Long]]]): this.type = { ValueSerializer.addArgInfo(info) - w.putLong(x); - checkCostLimit() - this + addFixedCost(PutSignedNumericCost) + w.putLong(x); this } - @inline override def putULong(x: Long, info: DataInfo[Vlq[U[Long]]]): this.type = { + override def putULong(x: Long): SigmaByteWriter.this.type = { + addFixedCost(PutUnsignedNumericCost) + super.putULong(x) + } + + override def putULong(x: Long, info: DataInfo[Vlq[U[Long]]]): this.type = { ValueSerializer.addArgInfo(info) - w.putULong(x); - checkCostLimit() - this + addFixedCost(PutUnsignedNumericCost) + w.putULong(x); this + } + + override def putBytes(xs: Array[Byte], offset: Int, length: Int): this.type = { + addPerItemCost(PutChunkCost, length) + super.putBytes(xs, offset, length) + } + + override def putBytes(xs: Array[Byte]): SigmaByteWriter.this.type = { + addPerItemCost(PutChunkCost, xs.length) + super.putBytes(xs) } - @inline override def putBytes(xs: Array[Byte], info: DataInfo[Array[Byte]]): this.type = { + override def putBytes(xs: Array[Byte], info: DataInfo[Array[Byte]]): this.type = { ValueSerializer.addArgInfo(info) - w.putBytes(xs); - checkCostLimit() - this + addPerItemCost(PutChunkCost, xs.length) + w.putBytes(xs); this + } + + /** Put the two bytes of the big-endian representation of the Short value into the + * writer. */ + override def putShortBytes(value: Short): SigmaByteWriter.this.type = { + addPerItemCost(PutChunkCost, 2) + super.putShortBytes(value) } - @inline override def putBits(xs: Array[Boolean], info: DataInfo[Bits]): this.type = { + override def putBits(xs: Array[Boolean]): SigmaByteWriter.this.type = { + addPerItemCost(PutChunkCost, xs.length) // number of bits + super.putBits(xs) + } + + override def putBits(xs: Array[Boolean], info: DataInfo[Bits]): this.type = { ValueSerializer.addArgInfo(info) - w.putBits(xs); - checkCostLimit() - this + addPerItemCost(PutChunkCost, xs.length) // number of bits + w.putBits(xs); this } - @inline override def putType[T <: SType](x: T, info: DataInfo[SType]): this.type = { + override def putOption[T](x: Option[T])(putValueC: (this.type, T) => Unit): this.type = { + addFixedCost(PutByteCost) // cost of option tag byte + super.putOption(x)(putValueC) + } + + override def putShortString(s: String): SigmaByteWriter.this.type = { + addPerItemCost(PutChunkCost, s.length) + super.putShortString(s) + } + + override def putType[T <: SType](x: T, info: DataInfo[SType]): this.type = { ValueSerializer.addArgInfo(info) - TypeSerializer.serialize(x, this); // the cost is checked in TypeSerializer + TypeSerializer.serialize(x, this); // the cost is added in TypeSerializer this } - @inline def putValue[T <: SType](x: Value[T]): this.type = { - ValueSerializer.serialize(x, this) // the cost is checked in ValueSerializer + /** Serializes the given expression using [[ValueSerializer]]. */ + def putValue[T <: SType](x: Value[T]): this.type = { + ValueSerializer.serialize(x, this) // the cost is added in ValueSerializer this } - @inline def putValue[T <: SType](x: Value[T], info: DataInfo[SValue]): this.type = { + + /** Serializes the given expression using [[ValueSerializer]]. + * @param x the ErgoTree expression to serialize + * @param info additional information about the data being serialized + */ + def putValue[T <: SType](x: Value[T], info: DataInfo[SValue]): this.type = { ValueSerializer.addArgInfo(info) - ValueSerializer.serialize(x, this); // the cost is checked in ValueSerializer + ValueSerializer.serialize(x, this); // the cost is added in ValueSerializer this } - @inline def putValues[T <: SType](xs: Seq[Value[T]]): this.type = { + + /** Serializes the given sequence of expressions using [[ValueSerializer]]. */ + def putValues[T <: SType](xs: Seq[Value[T]]): this.type = { putUInt(xs.length) xs.foreach(putValue(_)) this } - @inline def putValues[T <: SType](xs: Seq[Value[T]], info: DataInfo[Seq[SValue]], itemInfo: DataInfo[SValue]): this.type = { + + /** Serializes the given sequence of expressions using [[ValueSerializer]]. + * @param xs the sequence of ErgoTree expressions to serialize + * @param info additional information about the data being serialized + */ + def putValues[T <: SType](xs: Seq[Value[T]], info: DataInfo[Seq[SValue]], itemInfo: DataInfo[SValue]): this.type = { putUInt(xs.length, valuesLengthInfo) foreach("\\#items", xs) { x => putValue(x, itemInfo) @@ -127,6 +221,40 @@ class SigmaByteWriter( } object SigmaByteWriter { + + /** Callback to accumulate fixed costs. */ + type FixedCostCallback = OperationCostInfo[FixedCost] => Unit + + /** Callback to accumulate per-item costs (chunked cost). */ + type PerItemCostCallback = (OperationCostInfo[PerItemCost], Int) => Unit + + /** Cost of writing single byte without any encoding. + * This also include overhead of method calls. + * This is the minimal possible JitCost value + */ + val PutByteCost = OperationCostInfo(FixedCost(JitCost(1)), NamedDesc("SigmaByteWriter.put")) + + /** Cost of writing a signed numeric including: + * 1) allocation of VLQ buffer array (see putULong in [[scorex.util.serialization.VLQWriter]]) + * 2) VLQ encoding + * 3) overhead of method calls. + */ + val PutUnsignedNumericCost = OperationCostInfo(FixedCost(JitCost(3)), NamedDesc("SigmaByteWriter.putUNumeric")) + + /** Cost of writing a signed numeric including: + * 1) ZigZag encoding. + * 2) allocation of VLQ buffer array (see putULong in [[scorex.util.serialization.VLQWriter]]) + * 3) VLQ encoding + * 4) overhead of method calls. + */ + val PutSignedNumericCost = OperationCostInfo(FixedCost(JitCost(3)), NamedDesc("SigmaByteWriter.putNumeric")) + + /** Cost of writing a chunk of bytes: + * 1) method call overhead + * 2) 1 cost unit per byte + */ + val PutChunkCost = OperationCostInfo(PerItemCost(JitCost(3), JitCost(1), 1), NamedDesc("SigmaByteWriter.putChunk")) + implicit case object ValueFmt extends FormatDescriptor[SValue] { override def size: String = "[1, *]" override def toString: String = "Expr" diff --git a/data/shared/src/main/scala/sigma/serialization/SigmaSerializer.scala b/data/shared/src/main/scala/sigma/serialization/SigmaSerializer.scala index e842258f80..7da7ec1606 100644 --- a/data/shared/src/main/scala/sigma/serialization/SigmaSerializer.scala +++ b/data/shared/src/main/scala/sigma/serialization/SigmaSerializer.scala @@ -4,7 +4,7 @@ import java.nio.ByteBuffer import scorex.util.ByteArrayBuilder import scorex.util.serialization._ import sigma.data.SigmaConstants -import sigma.serialization.CoreByteWriter.CostLimitChecker +import sigma.serialization.SigmaByteWriter.{FixedCostCallback, PerItemCostCallback} import sigma.serialization.ValueCodes.OpCode object SigmaSerializer { @@ -52,14 +52,18 @@ object SigmaSerializer { def startWriter(): SigmaByteWriter = { val b = new ByteArrayBuilder() val wi = new VLQByteBufferWriter(b) - val w = new SigmaByteWriter(wi, constantExtractionStore = None, checkCostLimitOpt = None) + val w = new SigmaByteWriter(wi, constantExtractionStore = None, addFixedCostCallbackOpt = None, addPerItemCostCallbackOpt = None) w } - def startWriter(constantExtractionStore: ConstantStore, checkCostLimit: Option[CostLimitChecker] = None): SigmaByteWriter = { + def startWriter( + constantExtractionStore: Option[ConstantStore], + addFixedCostCallback: Option[FixedCostCallback] = None, + addPerItemCostCallback: Option[PerItemCostCallback] = None + ): SigmaByteWriter = { val b = new ByteArrayBuilder() val wi = new VLQByteBufferWriter(b) - val w = new SigmaByteWriter(wi, constantExtractionStore = Some(constantExtractionStore), checkCostLimit) + val w = new SigmaByteWriter(wi, constantExtractionStore = constantExtractionStore, addFixedCostCallback, addPerItemCostCallback) w } } diff --git a/sc/shared/src/test/scala/sigma/SigmaDslTesting.scala b/sc/shared/src/test/scala/sigma/SigmaDslTesting.scala index f14ba275ff..5e43eb18e1 100644 --- a/sc/shared/src/test/scala/sigma/SigmaDslTesting.scala +++ b/sc/shared/src/test/scala/sigma/SigmaDslTesting.scala @@ -255,13 +255,21 @@ class SigmaDslTesting extends AnyPropSpec fail( s"""Should succeed with the same value or fail with the same exception, but was: - |First result: $b1 - |Second result: $b2 + |First result: ${errorWithStack(b1)} + |Second result: ${errorWithStack(b2)} |Root cause: $cause |""".stripMargin) } } + private def errorWithStack[A](e: Try[A]): String = e match { + case Failure(t) => + val sw = new java.io.StringWriter + t.printStackTrace(new java.io.PrintWriter(sw)) + sw.toString + case _ => e.toString + } + /** Creates a new ErgoLikeContext using given [[CContext]] as template. * Copies most of the data from ctx and the missing data is taken from the args. * This is a helper method to be used in tests only. From 97377c2f93e2eef527af5343a784819091409f39 Mon Sep 17 00:00:00 2001 From: Alexander Slesarenko Date: Mon, 3 Jun 2024 11:29:37 +0200 Subject: [PATCH 112/314] v6.0-serialize: cleanup + ScalaDocs --- .../sigma/serialization/CoreByteWriter.scala | 101 +++++++++++++++--- .../sigma/serialization/SigmaByteWriter.scala | 2 +- 2 files changed, 90 insertions(+), 13 deletions(-) diff --git a/core/shared/src/main/scala/sigma/serialization/CoreByteWriter.scala b/core/shared/src/main/scala/sigma/serialization/CoreByteWriter.scala index 37d1455ba3..92d85ed9d8 100644 --- a/core/shared/src/main/scala/sigma/serialization/CoreByteWriter.scala +++ b/core/shared/src/main/scala/sigma/serialization/CoreByteWriter.scala @@ -7,7 +7,7 @@ import sigma.serialization.CoreByteWriter._ /** Implementation of [[Writer]] provided by `sigma-core` module. * - * @param w destination [[Writer]] to which all the call got delegated. + * @param w destination [[Writer]] to which all the call got delegated. */ class CoreByteWriter(val w: Writer) extends Writer { type CH = w.CH @@ -26,6 +26,10 @@ class CoreByteWriter(val w: Writer) extends Writer { w.put(x); this } + /** Put the given byte into the writer. + * @param x the byte to put into the writer + * @param info meta information about the data being put into the writer + */ @inline def put(x: Byte, info: DataInfo[Byte]): this.type = { w.put(x); this } @@ -34,60 +38,109 @@ class CoreByteWriter(val w: Writer) extends Writer { super.putUByte(x) } + /** Encode integer as an unsigned byte asserting the range check + * @param x integer value to encode (should be in the range of unsigned byte) + * @param info meta information about the data being put into the writer + * @return + * @throws AssertionError if x is outside of the unsigned byte range + */ def putUByte(x: Int, info: DataInfo[U[Byte]]): this.type = { super.putUByte(x) } - @inline def putBoolean(x: Boolean): this.type = { + @inline override def putBoolean(x: Boolean): this.type = { w.putBoolean(x); this } + /** Encode boolean by delegating to the underlying writer. + * @param x boolean value to encode + * @param info meta information about the data being put into the writer + * @return + */ @inline def putBoolean(x: Boolean, info: DataInfo[Boolean]): this.type = { w.putBoolean(x); this } - @inline def putShort(x: Short): this.type = { + @inline override def putShort(x: Short): this.type = { w.putShort(x); this } + /** Encode signed Short by delegating to the underlying writer. + * + * Use [[putUShort]] to encode values that are positive. + * @param x short value to encode + * @param info meta information about the data being put into the writer + */ @inline def putShort(x: Short, info: DataInfo[Short]): this.type = { w.putShort(x); this } - @inline def putUShort(x: Int): this.type = { + @inline override def putUShort(x: Int): this.type = { w.putUShort(x); this } + /** Encode Short that are positive by delegating to the underlying writer. + * + * Use [[putShort]] to encode values that might be negative. + * @param x unsigned short value (represented as Int) to encode + * @param info meta information about the data being put into the writer + */ @inline def putUShort(x: Int, info: DataInfo[Vlq[U[Short]]]): this.type = { w.putUShort(x); this } - @inline def putInt(x: Int): this.type = { + @inline override def putInt(x: Int): this.type = { w.putInt(x); this } + /** Encode signed Int by delegating to the underlying writer. + * Use [[putUInt]] to encode values that are positive. + * + * @param x integer value to encode + * @param info meta information about the data being put into the writer + */ @inline def putInt(x: Int, info: DataInfo[Int]): this.type = { w.putInt(x); this } - @inline def putUInt(x: Long): this.type = { + @inline override def putUInt(x: Long): this.type = { w.putUInt(x); this } + + /** Encode Int that are positive by delegating to the underlying writer. + * Use [[putInt]] to encode values that might be negative. + * + * @param x unsigned integer value (represented as Long) to encode + * @param info meta information about the data being put into the writer + */ @inline def putUInt(x: Long, info: DataInfo[Vlq[U[Int]]]): this.type = { w.putUInt(x); this } - @inline def putLong(x: Long): this.type = { + @inline override def putLong(x: Long): this.type = { w.putLong(x); this } + + /** Encode signed Long by delegating to the underlying writer. + * Use [[putULong]] to encode values that are positive. + * + * @param x long value to encode + * @param info meta information about the data being put into the writer + */ @inline def putLong(x: Long, info: DataInfo[Vlq[ZigZag[Long]]]): this.type = { w.putLong(x); this } - @inline def putULong(x: Long): this.type = { + @inline override def putULong(x: Long): this.type = { w.putULong(x); this } + /** Encode Long that are positive by delegating to the underlying writer. + * Use [[putLong]] to encode values that might be negative. + * + * @param x unsigned long value to encode + * @param info meta information about the data being put into the writer + */ @inline def putULong(x: Long, info: DataInfo[Vlq[U[Long]]]): this.type = { w.putULong(x); this } @@ -98,9 +151,14 @@ class CoreByteWriter(val w: Writer) extends Writer { w.putBytes(xs, offset, length); this } - @inline def putBytes(xs: Array[Byte]): this.type = { + @inline override def putBytes(xs: Array[Byte]): this.type = { w.putBytes(xs); this } + + /** Encode an array of bytes by delegating to the underlying writer. + * @param xs array of bytes to encode + * @param info meta information about the data being put into the writer + */ @inline def putBytes(xs: Array[Byte], info: DataInfo[Array[Byte]]): this.type = { w.putBytes(xs); this } @@ -113,21 +171,27 @@ class CoreByteWriter(val w: Writer) extends Writer { this } - @inline def putBits(xs: Array[Boolean]): this.type = { + @inline override def putBits(xs: Array[Boolean]): this.type = { w.putBits(xs); this } + + /** Encode an array of boolean values as a bit array (packing bits into bytes) + * + * @param xs array of boolean values + * @param info meta information about the data being put into the writer + */ @inline def putBits(xs: Array[Boolean], info: DataInfo[Bits]): this.type = { w.putBits(xs); this } - @inline def putOption[T](x: Option[T])(putValueC: (this.type, T) => Unit): this.type = { + @inline override def putOption[T](x: Option[T])(putValueC: (this.type, T) => Unit): this.type = { w.putOption(x) { (_, v) => putValueC(this, v) } this } - @inline def putShortString(s: String): this.type = { + @inline override def putShortString(s: String): this.type = { w.putShortString(s); this } @@ -137,10 +201,18 @@ class CoreByteWriter(val w: Writer) extends Writer { case wr: VLQByteBufferWriter => wr.toBytes } + /** Serialize the given type into the writer using [[TypeSerializer]]. + * @param x the type to put into the writer + */ @inline def putType[T <: SType](x: T): this.type = { TypeSerializer.serialize(x, this) this } + + /** Serialize the given type into the writer using [[TypeSerializer]]. + * @param x the type to put into the writer + * @param info meta information about the data being put into the writer + */ @inline def putType[T <: SType](x: T, info: DataInfo[SType]): this.type = { TypeSerializer.serialize(x, this) this @@ -263,6 +335,11 @@ object CoreByteWriter { * @param description argument description. */ case class ArgInfo(name: String, description: String) + /** Represents meta information about serialized data. + * Passed as additional argument of serializer methods. + * Can be used to automatically generate format specifications based on + * the actual collected method invocations. + */ case class DataInfo[T](info: ArgInfo, format: FormatDescriptor[T]) object DataInfo { diff --git a/data/shared/src/main/scala/sigma/serialization/SigmaByteWriter.scala b/data/shared/src/main/scala/sigma/serialization/SigmaByteWriter.scala index 93e078e319..7bda855005 100644 --- a/data/shared/src/main/scala/sigma/serialization/SigmaByteWriter.scala +++ b/data/shared/src/main/scala/sigma/serialization/SigmaByteWriter.scala @@ -192,7 +192,7 @@ class SigmaByteWriter( /** Serializes the given expression using [[ValueSerializer]]. * @param x the ErgoTree expression to serialize - * @param info additional information about the data being serialized + * @param info meta information about the data being serialized */ def putValue[T <: SType](x: Value[T], info: DataInfo[SValue]): this.type = { ValueSerializer.addArgInfo(info) From bc71b2f27006ce0069c9179626403496aa4a58cd Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Mon, 3 Jun 2024 15:02:08 +0300 Subject: [PATCH 113/314] todo removed, tests improved --- .../src/main/scala/sigma/serialization/CoreDataSerializer.scala | 1 - .../scala/sigma/serialization/DataSerializerSpecification.scala | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/core/shared/src/main/scala/sigma/serialization/CoreDataSerializer.scala b/core/shared/src/main/scala/sigma/serialization/CoreDataSerializer.scala index b8174aa31e..233494392a 100644 --- a/core/shared/src/main/scala/sigma/serialization/CoreDataSerializer.scala +++ b/core/shared/src/main/scala/sigma/serialization/CoreDataSerializer.scala @@ -74,7 +74,6 @@ class CoreDataSerializer { serialize(v, elemType, w) } - // TODO v6.0 (3h): support Option[T] (see https://github.com/ScorexFoundation/sigmastate-interpreter/issues/659) case _ => CheckSerializableTypeCode(tpe.typeCode) throw new SerializerException(s"Don't know how to serialize ($v, $tpe)") diff --git a/interpreter/shared/src/test/scala/sigma/serialization/DataSerializerSpecification.scala b/interpreter/shared/src/test/scala/sigma/serialization/DataSerializerSpecification.scala index 18c1f6a092..a42cf2c9e3 100644 --- a/interpreter/shared/src/test/scala/sigma/serialization/DataSerializerSpecification.scala +++ b/interpreter/shared/src/test/scala/sigma/serialization/DataSerializerSpecification.scala @@ -111,6 +111,7 @@ class DataSerializerSpecification extends SerializationSpecification { roundtrip[SOption[T]](Some(in), SOption(tpe)) roundtrip[SOption[SCollection[T]]](Some(Colls.fromItems(in)(tT)), SOption(SCollectionType(tpe))) roundtrip[SCollection[SOption[T]]](Colls.fromItems(Option(in), None.asInstanceOf[Option[T#WrappedType]])(OptionType(tT)), SCollectionType(SOption(tpe))) + roundtrip[SOption[SOption[T]]](None, SOption(SOption(tpe))) roundtrip[SOption[SOption[T]]](Some(Some(in)), SOption(SOption(tpe))) } } From 767fbb4af9e420c42a0d43e8d7c2945a46046749 Mon Sep 17 00:00:00 2001 From: Alexander Slesarenko Date: Mon, 3 Jun 2024 15:54:54 +0200 Subject: [PATCH 114/314] v6.0-serialize: tests for cost trace --- .../src/main/scala/sigma/ast/methods.scala | 5 +- .../sigma/serialization/SigmaByteWriter.scala | 6 ++ .../scala/sigma/LanguageSpecificationV6.scala | 56 +++++++++++---- .../test/scala/sigma/SigmaDslTesting.scala | 71 +++++++++++++------ 4 files changed, 101 insertions(+), 37 deletions(-) diff --git a/data/shared/src/main/scala/sigma/ast/methods.scala b/data/shared/src/main/scala/sigma/ast/methods.scala index fd9024ee62..ef548d6185 100644 --- a/data/shared/src/main/scala/sigma/ast/methods.scala +++ b/data/shared/src/main/scala/sigma/ast/methods.scala @@ -12,7 +12,7 @@ import sigma.data.{DataValueComparer, KeyValueColl, Nullable, RType, SigmaConsta import sigma.eval.{CostDetails, ErgoTreeEvaluator, TracedCost} import sigma.reflection.RClass import sigma.serialization.CoreByteWriter.ArgInfo -import sigma.serialization.{DataSerializer, SigmaSerializer} +import sigma.serialization.{DataSerializer, SigmaByteWriter, SigmaSerializer} import sigma.utils.SparseArrayContainer import scala.annotation.unused @@ -1534,6 +1534,8 @@ case object SGlobalMethods extends MonoTypeMethods { def serialize_eval(mc: MethodCall, G: SigmaDslBuilder, value: SType#WrappedType) (implicit E: ErgoTreeEvaluator): Coll[Byte] = { + E.addCost(SigmaByteWriter.StartWriterCost) + val addFixedCostCallback = { (costInfo: OperationCostInfo[FixedCost]) => E.addCost(costInfo) } @@ -1542,6 +1544,7 @@ case object SGlobalMethods extends MonoTypeMethods { } val w = SigmaSerializer.startWriter(None, Some(addFixedCostCallback), Some(addPerItemCostCallback)) + DataSerializer.serialize(value, mc.args(0).tpe, w) Colls.fromArray(w.toBytes) } diff --git a/data/shared/src/main/scala/sigma/serialization/SigmaByteWriter.scala b/data/shared/src/main/scala/sigma/serialization/SigmaByteWriter.scala index 7bda855005..db9312240f 100644 --- a/data/shared/src/main/scala/sigma/serialization/SigmaByteWriter.scala +++ b/data/shared/src/main/scala/sigma/serialization/SigmaByteWriter.scala @@ -228,6 +228,12 @@ object SigmaByteWriter { /** Callback to accumulate per-item costs (chunked cost). */ type PerItemCostCallback = (OperationCostInfo[PerItemCost], Int) => Unit + /** Cost of instantiating a new serializer. + * This also include overhead of method calls. + * This is the minimal possible JitCost value + */ + val StartWriterCost = OperationCostInfo(FixedCost(JitCost(10)), NamedDesc("SigmaByteWriter.startWriter")) + /** Cost of writing single byte without any encoding. * This also include overhead of method calls. * This is the minimal possible JitCost value diff --git a/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala b/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala index 20faabe128..e4ae10cac6 100644 --- a/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala +++ b/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala @@ -1,8 +1,8 @@ package sigma -import sigma.ast.{Downcast, FuncValue, Global, MethodCall, SBigInt, SByte, SGlobalMethods, SInt, SLong, SShort, STypeVar, ValUse} +import sigma.ast.{Apply, Downcast, FixedCost, FixedCostItem, FuncValue, GetVar, Global, JitCost, MethodCall, NamedDesc, OptionGet, SBigInt, SByte, SGlobalMethods, SInt, SLong, SShort, STypeVar, ValUse} import sigma.data.{CBigInt, ExactNumeric, RType} -import sigma.eval.SigmaDsl +import sigma.eval.{SigmaDsl, TracedCost} import sigma.util.Extensions.{BooleanOps, ByteOps, IntOps, LongOps} import sigmastate.exceptions.MethodNotFound @@ -17,6 +17,8 @@ import scala.util.Success class LanguageSpecificationV6 extends LanguageSpecificationBase { suite => override def languageVersion: Byte = VersionContext.V6SoftForkVersion + implicit override def evalSettings = super.evalSettings.copy(printTestVectors = true) + def mkSerializeFeature[A: RType]: Feature[A, Coll[Byte]] = { val tA = RType[A] val tpe = Evaluation.rtypeToSType(tA) @@ -35,28 +37,54 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite => sinceVersion = VersionContext.V6SoftForkVersion) } + val baseTrace = Array( + FixedCostItem(Apply), + FixedCostItem(FuncValue), + FixedCostItem(GetVar), + FixedCostItem(OptionGet), + FixedCostItem(FuncValue.AddToEnvironmentDesc, FixedCost(JitCost(5))) + ) + property("Global.serialize[Byte]") { lazy val serializeByte = mkSerializeFeature[Byte] + val expectedCostTrace = TracedCost( + baseTrace ++ Array( + FixedCostItem(Global), + FixedCostItem(MethodCall), + FixedCostItem(ValUse), + FixedCostItem(NamedDesc("SigmaByteWriter.startWriter"), FixedCost(JitCost(10))), + FixedCostItem(NamedDesc("SigmaByteWriter.put"), FixedCost(JitCost(1))) + ) + ) val cases = Seq( - (-128.toByte, Success(Coll(-128.toByte))), - (-1.toByte, Success(Coll(-1.toByte))), - (0.toByte, Success(Coll(0.toByte))), - (1.toByte, Success(Coll(1.toByte))), - (127.toByte, Success(Coll(127.toByte))) + (-128.toByte, Expected(Success(Coll(-128.toByte)), expectedCostTrace)), + (-1.toByte, Expected(Success(Coll(-1.toByte)), expectedCostTrace)), + (0.toByte, Expected(Success(Coll(0.toByte)), expectedCostTrace)), + (1.toByte, Expected(Success(Coll(1.toByte)), expectedCostTrace)), + (127.toByte, Expected(Success(Coll(127.toByte)), expectedCostTrace)) ) - testCases(cases, serializeByte) + verifyCases(cases, serializeByte, preGeneratedSamples = None) } property("Global.serialize[Short]") { lazy val serializeShort = mkSerializeFeature[Short] + val expectedCostTrace = TracedCost( + baseTrace ++ Array( + FixedCostItem(Global), + FixedCostItem(MethodCall), + FixedCostItem(ValUse), + FixedCostItem(NamedDesc("SigmaByteWriter.startWriter"), FixedCost(JitCost(10))), + FixedCostItem(NamedDesc("SigmaByteWriter.putNumeric"), FixedCost(JitCost(3))) + ) + ) val cases = Seq( - (Short.MinValue, Success(Coll[Byte](0xFF.toByte, 0xFF.toByte, 0x03.toByte))), - (-1.toShort, Success(Coll(1.toByte))), - (0.toShort, Success(Coll(0.toByte))), - (1.toShort, Success(Coll(2.toByte))), - (Short.MaxValue, Success(Coll(-2.toByte, -1.toByte, 3.toByte))) + (Short.MinValue, Expected(Success(Coll[Byte](0xFF.toByte, 0xFF.toByte, 0x03.toByte)), expectedCostTrace)), + (-1.toShort, Expected(Success(Coll(1.toByte)), expectedCostTrace)), + (0.toShort, Expected(Success(Coll(0.toByte)), expectedCostTrace)), + (1.toShort, Expected(Success(Coll(2.toByte)), expectedCostTrace)), + (Short.MaxValue, Expected(Success(Coll(-2.toByte, -1.toByte, 3.toByte)), expectedCostTrace)) ) - testCases(cases, serializeShort) + verifyCases(cases, serializeShort, preGeneratedSamples = None) } // TODO v6.0: implement serialization roundtrip tests after merge with deserializeTo diff --git a/sc/shared/src/test/scala/sigma/SigmaDslTesting.scala b/sc/shared/src/test/scala/sigma/SigmaDslTesting.scala index 5e43eb18e1..37fb0e6503 100644 --- a/sc/shared/src/test/scala/sigma/SigmaDslTesting.scala +++ b/sc/shared/src/test/scala/sigma/SigmaDslTesting.scala @@ -179,6 +179,34 @@ class SigmaDslTesting extends AnyPropSpec true } + /** Checks the result of feature execution against expected result. + * If settings.failOnTestVectors == true, then print out actual cost results + * + * @param res the result of feature execution + * @param expected the expected result + */ + protected def checkResultAgainstExpected(res: Try[(B, CostDetails)], expected: Expected[B]): Unit = { + val newRes = expected.newResults(ergoTreeVersionInTests) + val expectedTrace = newRes._2.fold(Seq.empty[CostItem])(_.trace) + if (expectedTrace.isEmpty) { + // new cost expectation is missing, print out actual cost results + if (evalSettings.printTestVectors) { + res.foreach { case (_, newDetails) => + printCostDetails(script, newDetails) + } + } + } + else { + // new cost expectation is specified, compare it with the actual result + res.foreach { case (_, newDetails) => + if (newDetails.trace != expectedTrace) { + printCostDetails(script, newDetails) + newDetails.trace shouldBe expectedTrace + } + } + } + } + /** v3 and v4 implementation*/ private var _oldF: Try[CompiledFunc[A, B]] = _ def oldF: CompiledFunc[A, B] = { @@ -624,28 +652,10 @@ class SigmaDslTesting extends AnyPropSpec checkResult(funcRes.map(_._1), expected.value, failOnTestVectors, "ExistingFeature#verifyCase: ") - val newRes = expected.newResults(ergoTreeVersionInTests) - val expectedTrace = newRes._2.fold(Seq.empty[CostItem])(_.trace) - if (expectedTrace.isEmpty) { - // new cost expectation is missing, print out actual cost results - if (evalSettings.printTestVectors) { - funcRes.foreach { case (_, newDetails) => - printCostDetails(script, newDetails) - } - } - } - else { - // new cost expectation is specified, compare it with the actual result - funcRes.foreach { case (_, newDetails) => - if (newDetails.trace != expectedTrace) { - printCostDetails(script, newDetails) - newDetails.trace shouldBe expectedTrace - } - } - } - + checkResultAgainstExpected(funcRes, expected) checkVerify(input, expected) } + } /** Descriptor of a language feature which is changed in v5.0. @@ -921,8 +931,11 @@ class SigmaDslTesting extends AnyPropSpec printTestCases: Boolean, failOnTestVectors: Boolean): Unit = { val funcRes = checkEquality(input, printTestCases) - funcRes.isFailure shouldBe true - Try(scalaFunc(input)) shouldBe expected.value + if (this.isSupportedIn(VersionContext.current)) { + checkResultAgainstExpected(funcRes, expected) + } else + funcRes.isFailure shouldBe true + Try(scalaFuncNew(input)) shouldBe expected.value } } @@ -990,6 +1003,20 @@ class SigmaDslTesting extends AnyPropSpec } } + /** Used when the old and new value are the same for all versions + * and the expected costs are not specified. + * + * @param value expected result of tested function + * @param expectedDetails expected cost details for all versions + */ + def apply[A](value: Try[A], expectedDetails: CostDetails): Expected[A] = + new Expected(ExpectedResult(value, None)) { + override val newResults = defaultNewResults.map { + case (ExpectedResult(v, _), _) => + (ExpectedResult(v, None), Some(expectedDetails)) + } + } + /** Used when the old and new value and costs are the same for all versions. * * @param value expected result of tested function From 744d8a58bc7c86c84f2aa1c5694db935a3172260 Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Mon, 3 Jun 2024 22:23:54 +0300 Subject: [PATCH 115/314] conversion test stub --- .../src/main/scala/sigma/ast/SigmaPredef.scala | 7 ++++++- .../sigmastate/utxo/BasicOpsSpecification.scala | 16 +++++++++++++++- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/data/shared/src/main/scala/sigma/ast/SigmaPredef.scala b/data/shared/src/main/scala/sigma/ast/SigmaPredef.scala index d8c65a7afe..752b69f636 100644 --- a/data/shared/src/main/scala/sigma/ast/SigmaPredef.scala +++ b/data/shared/src/main/scala/sigma/ast/SigmaPredef.scala @@ -196,7 +196,12 @@ object SigmaPredef { Lambda(Array("input" -> SString), SUnsignedBigInt, None), PredefFuncInfo( { case (_, Seq(arg: EvaluatedValue[SString.type]@unchecked)) => - UnsignedBigIntConstant(new BigInteger(arg.value)) + val bi = new BigInteger(arg.value) + if (bi.compareTo(BigInteger.ZERO) >= 0) { + UnsignedBigIntConstant(bi) + } else { + throw new InvalidArguments(s"Negative argument for unsignedBigInt()") + } }), OperationInfo(Constant, """Parsing string literal argument as a 256-bit unsigned big integer.""".stripMargin, diff --git a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala index 28084be987..e6f08f75fc 100644 --- a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala @@ -169,7 +169,21 @@ class BasicOpsSpecification extends CompilerTestingCommons deserTest() } - property("signed <-> unsigned bigint conversion") { + property("signed <-> unsigned bigint conversion - positive bigint") { + val b = new BigInteger("9280562930080889354892980449861222646750586663683904599823322027983929189860") + val ub = new BigInteger(1, b.toByteArray) + + // todo: how to upcast? + def deserTest() = {test("restoring", env, ext, + s"{ val b = bigInt(\"${ub.toString}\"); b > 1 }", + null, + true + )} + + deserTest() + } + + property("signed <-> unsigned bigint conversion - negative bigint") { } From ea91fae58992c1a162e0343e30ceb5eea3aaac06 Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Mon, 3 Jun 2024 22:26:59 +0300 Subject: [PATCH 116/314] Some(None) test --- .../scala/sigma/serialization/DataSerializerSpecification.scala | 1 + 1 file changed, 1 insertion(+) diff --git a/interpreter/shared/src/test/scala/sigma/serialization/DataSerializerSpecification.scala b/interpreter/shared/src/test/scala/sigma/serialization/DataSerializerSpecification.scala index a42cf2c9e3..2d9da3a87e 100644 --- a/interpreter/shared/src/test/scala/sigma/serialization/DataSerializerSpecification.scala +++ b/interpreter/shared/src/test/scala/sigma/serialization/DataSerializerSpecification.scala @@ -113,6 +113,7 @@ class DataSerializerSpecification extends SerializationSpecification { roundtrip[SCollection[SOption[T]]](Colls.fromItems(Option(in), None.asInstanceOf[Option[T#WrappedType]])(OptionType(tT)), SCollectionType(SOption(tpe))) roundtrip[SOption[SOption[T]]](None, SOption(SOption(tpe))) roundtrip[SOption[SOption[T]]](Some(Some(in)), SOption(SOption(tpe))) + roundtrip[SOption[SOption[T]]](Some(None), SOption(SOption(tpe))) } } } From fd8e5d7a17694a22f5062c180659696af4e4f890 Mon Sep 17 00:00:00 2001 From: Alexander Slesarenko Date: Mon, 3 Jun 2024 21:27:23 +0200 Subject: [PATCH 117/314] i994-fix-subst-constants: cleanup + ScalaDocs --- data/shared/src/main/scala/sigma/ast/ErgoTree.scala | 6 ++++++ .../src/test/scala/sigma/LanguageSpecificationBase.scala | 8 +++++++- .../src/test/scala/sigma/LanguageSpecificationV6.scala | 6 ------ 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/data/shared/src/main/scala/sigma/ast/ErgoTree.scala b/data/shared/src/main/scala/sigma/ast/ErgoTree.scala index eae420612e..3bb69b96dc 100644 --- a/data/shared/src/main/scala/sigma/ast/ErgoTree.scala +++ b/data/shared/src/main/scala/sigma/ast/ErgoTree.scala @@ -228,8 +228,14 @@ object ErgoTree { type HeaderType = HeaderType.Type + /** Convenience methods for working with ErgoTree headers. */ implicit class HeaderTypeOps(val header: HeaderType) extends AnyVal { + /** Update the version bits of the given header byte with the given version value, + * leaving all other bits unchanged. + */ def withVersion(version: Byte): HeaderType = ErgoTree.headerWithVersion(header, version) + + /** Sets the constant segregation bit in the given header. */ def withConstantSegregation: HeaderType = ErgoTree.setConstantSegregation(header) } diff --git a/sc/shared/src/test/scala/sigma/LanguageSpecificationBase.scala b/sc/shared/src/test/scala/sigma/LanguageSpecificationBase.scala index 26c7d7c8c2..7be79546e7 100644 --- a/sc/shared/src/test/scala/sigma/LanguageSpecificationBase.scala +++ b/sc/shared/src/test/scala/sigma/LanguageSpecificationBase.scala @@ -2,7 +2,7 @@ package sigma import org.scalatest.BeforeAndAfterAll import sigma.ast.{Apply, FixedCostItem, FuncValue, GetVar, JitCost, OptionGet, ValUse} -import sigma.eval.{EvalSettings, Profiler} +import sigma.eval.{CostDetails, EvalSettings, Profiler} import sigmastate.CompilerCrossVersionProps import sigmastate.interpreter.CErgoTreeEvaluator @@ -137,4 +137,10 @@ abstract class LanguageSpecificationBase extends SigmaDslTesting FixedCostItem(ValUse) ) + /** Helper method to create the given expected results for all tree versions. */ + def expectedSuccessForAllTreeVersions[A](value: A, cost: Int, costDetails: CostDetails) = { + val res = ExpectedResult(Success(value), Some(cost)) -> Some(costDetails) + Seq(0, 1, 2, 3).map(version => version -> res) + } + } diff --git a/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala b/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala index fd2e18ebfb..e8837a02d7 100644 --- a/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala +++ b/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala @@ -7,7 +7,6 @@ import sigma.ast.syntax.TrueSigmaProp import sigma.ast.{BoolToSigmaProp, CompanionDesc, ConcreteCollection, Constant, ConstantPlaceholder, Downcast, ErgoTree, FalseLeaf, FixedCostItem, FuncValue, Global, JitCost, MethodCall, PerItemCost, SBigInt, SByte, SCollection, SGlobalMethods, SInt, SLong, SPair, SShort, SSigmaProp, STypeVar, SelectField, SubstConstants, ValUse, Value} import sigma.data.{CBigInt, ExactNumeric, RType} import sigma.eval.{CostDetails, SigmaDsl, TracedCost} -import sigma.serialization.ErgoTreeSerializer import sigma.util.Extensions.{BooleanOps, ByteOps, IntOps, LongOps} import sigmastate.exceptions.MethodNotFound import sigmastate.utils.Helpers @@ -23,11 +22,6 @@ import scala.util.Success class LanguageSpecificationV6 extends LanguageSpecificationBase { suite => override def languageVersion: Byte = VersionContext.V6SoftForkVersion - def expectedSuccessForAllTreeVersions[A](value: A, cost: Int, costDetails: CostDetails) = { - val res = ExpectedResult(Success(value), Some(cost)) -> Some(costDetails) - Seq(0, 1, 2, 3).map(version => version -> res) - } - def mkSerializeFeature[A: RType]: Feature[A, Coll[Byte]] = { val tA = RType[A] val tpe = Evaluation.rtypeToSType(tA) From 2acc6db89d96659d1efcb6aa3ddae2ec562a132f Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Tue, 4 Jun 2024 11:08:17 +0300 Subject: [PATCH 118/314] more todos --- core/shared/src/main/scala/sigma/ast/SType.scala | 2 +- data/shared/src/main/scala/sigma/ast/methods.scala | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/core/shared/src/main/scala/sigma/ast/SType.scala b/core/shared/src/main/scala/sigma/ast/SType.scala index c72ba65e73..4be9087ca7 100644 --- a/core/shared/src/main/scala/sigma/ast/SType.scala +++ b/core/shared/src/main/scala/sigma/ast/SType.scala @@ -340,7 +340,7 @@ trait SNumericType extends SProduct with STypeCompanion { object SNumericType extends STypeCompanion { /** Array of all numeric types ordered by number of bytes in the representation. */ - final val allNumericTypes = Array(SByte, SShort, SInt, SLong, SBigInt) + final val allNumericTypes = Array(SByte, SShort, SInt, SLong, SBigInt, SUnsignedBigInt) // TODO v6.0: this typeId is now shadowed by SGlobal.typeId // see https://github.com/ScorexFoundation/sigmastate-interpreter/issues/667 diff --git a/data/shared/src/main/scala/sigma/ast/methods.scala b/data/shared/src/main/scala/sigma/ast/methods.scala index e4cf0007e0..4656d3361e 100644 --- a/data/shared/src/main/scala/sigma/ast/methods.scala +++ b/data/shared/src/main/scala/sigma/ast/methods.scala @@ -210,6 +210,8 @@ object SNumericTypeMethods extends MethodsContainer { .withCost(costOfNumericCast) .withInfo(PropertyCall, "Converts this numeric value to \\lst{BigInt}") + // todo: ToUnsignedBigInt + /** Cost of: 1) creating Byte collection from a numeric value */ val ToBytes_CostKind = FixedCost(JitCost(5)) @@ -316,7 +318,10 @@ case object SBigIntMethods extends SNumericTypeMethods { val ToNBits = SMethod(this, "nbits", SFunc(this.ownerType, SLong), 8, ToNBitsCostInfo.costKind) .withInfo(ModQ, "Encode this big integer value as NBits") - /** The following `modQ` methods are not fully implemented in v4.x and this descriptors. + /** + * todo: remove + * + * The following `modQ` methods are not fully implemented in v4.x and this descriptors. * This descritors are remain here in the code and are waiting for full implementation * is upcoming soft-forks at which point the cost parameters should be calculated and * changed. From 7795e5da4a6a355f8b1410b728b0d5462e9dad7e Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Tue, 4 Jun 2024 12:18:14 +0300 Subject: [PATCH 119/314] remove non-PR related code, improved DataSerializerSpecification --- .../src/main/scala/sigma/SigmaDsl.scala | 9 +- .../sigma/reflection/ReflectionData.scala | 3 - .../main/scala/sigma/util/NBitsUtils.scala | 84 --------- .../scala/org/ergoplatform/ErgoHeader.scala | 30 ++-- .../org/ergoplatform/HeaderWithoutPow.scala | 2 - .../src/main/scala/sigma/ast/methods.scala | 30 +--- .../src/main/scala/sigma/data/CHeader.scala | 20 +-- .../scala/sigma/eval/ErgoTreeEvaluator.scala | 5 +- .../sigma/pow/Autolykos2PowValidation.scala | 167 ------------------ .../interpreter/CErgoTreeEvaluator.scala | 13 +- .../DataSerializerSpecification.scala | 61 ++++--- .../MethodCallSerializerSpecification.scala | 27 --- .../generators/ObjectGenerators.scala | 3 +- .../special/sigma/SigmaTestingData.scala | 1 - .../sigma/compiler/ir/GraphBuilding.scala | 1 - .../ir/wrappers/sigma/SigmaDslUnit.scala | 1 - .../ir/wrappers/sigma/impl/SigmaDslImpl.scala | 14 -- .../scala/sigma/SigmaDslSpecification.scala | 1 - .../scala/org/ergoplatform/sdk/js/Isos.scala | 7 +- .../org/ergoplatform/sdk/JsonCodecs.scala | 5 +- 20 files changed, 74 insertions(+), 410 deletions(-) delete mode 100644 core/shared/src/main/scala/sigma/util/NBitsUtils.scala delete mode 100644 data/shared/src/main/scala/sigma/pow/Autolykos2PowValidation.scala diff --git a/core/shared/src/main/scala/sigma/SigmaDsl.scala b/core/shared/src/main/scala/sigma/SigmaDsl.scala index a2894515a2..7353b8f89e 100644 --- a/core/shared/src/main/scala/sigma/SigmaDsl.scala +++ b/core/shared/src/main/scala/sigma/SigmaDsl.scala @@ -460,12 +460,17 @@ trait Header { /** Miner votes for changing system parameters. */ def votes: Coll[Byte] //3 bytes + /** Bytes which are coming from future versions of the protocol, so + * their meaning is not known to current version of Sigma, but they + * are stored to get the same id as future version users. + */ def unparsedBytes: Coll[Byte] + /** + * @return bytes without proof of work, needed for working to get the proof on + */ def serializeWithoutPoW: Coll[Byte] - def checkPow: Boolean - } /** Runtime representation of Context ErgoTree type. diff --git a/core/shared/src/main/scala/sigma/reflection/ReflectionData.scala b/core/shared/src/main/scala/sigma/reflection/ReflectionData.scala index 2a5e74e659..028e68bf72 100644 --- a/core/shared/src/main/scala/sigma/reflection/ReflectionData.scala +++ b/core/shared/src/main/scala/sigma/reflection/ReflectionData.scala @@ -346,9 +346,6 @@ object ReflectionData { }, mkMethod(clazz, "powDistance", Array[Class[_]]()) { (obj, _) => obj.asInstanceOf[Header].powDistance - }, - mkMethod(clazz, "checkPow", Array[Class[_]]()) { (obj, _) => - obj.asInstanceOf[Header].checkPow } ) ) diff --git a/core/shared/src/main/scala/sigma/util/NBitsUtils.scala b/core/shared/src/main/scala/sigma/util/NBitsUtils.scala deleted file mode 100644 index 36d526d1d5..0000000000 --- a/core/shared/src/main/scala/sigma/util/NBitsUtils.scala +++ /dev/null @@ -1,84 +0,0 @@ -package sigma.util - -import java.math.BigInteger - -object NBitsUtils { - - /** - *

The "compact" format is a representation of a whole number N using an unsigned 32 bit number similar to a - * floating point format. The most significant 8 bits are the unsigned exponent of base 256. This exponent can - * be thought of as "number of bytes of N". The lower 23 bits are the mantissa. Bit number 24 (0x800000) represents - * the sign of N. Therefore, N = (-1^sign) * mantissa * 256^(exponent-3).

- * - *

Satoshi's original implementation used BN_bn2mpi() and BN_mpi2bn(). MPI uses the most significant bit of the - * first byte as sign. Thus 0x1234560000 is compact 0x05123456 and 0xc0de000000 is compact 0x0600c0de. Compact - * 0x05c0de00 would be -0x40de000000.

- * - *

Bitcoin only uses this "compact" format for encoding difficulty targets, which are unsigned 256bit quantities. - * Thus, all the complexities of the sign bit and using base 256 are probably an implementation accident.

- */ - def decodeCompactBits(compact: Long): BigInt = { - val size: Int = (compact >> 24).toInt & 0xFF - val bytes: Array[Byte] = new Array[Byte](4 + size) - bytes(3) = size.toByte - if (size >= 1) bytes(4) = ((compact >> 16) & 0xFF).toByte - if (size >= 2) bytes(5) = ((compact >> 8) & 0xFF).toByte - if (size >= 3) bytes(6) = (compact & 0xFF).toByte - decodeMPI(bytes) - } - - /** - * @see Utils#decodeCompactBits(long) - */ - def encodeCompactBits(requiredDifficulty: BigInt): Long = { - val value = requiredDifficulty.bigInteger - var result: Long = 0L - var size: Int = value.toByteArray.length - if (size <= 3) { - result = value.longValue << 8 * (3 - size) - } else { - result = value.shiftRight(8 * (size - 3)).longValue - } - // The 0x00800000 bit denotes the sign. - // Thus, if it is already set, divide the mantissa by 256 and increase the exponent. - if ((result & 0x00800000L) != 0) { - result >>= 8 - size += 1 - } - result |= size << 24 - val a: Int = if (value.signum == -1) 0x00800000 else 0 - result |= a - result - } - - - /** Parse 4 bytes from the byte array (starting at the offset) as unsigned 32-bit integer in big endian format. */ - def readUint32BE(bytes: Array[Byte]): Long = ((bytes(0) & 0xffL) << 24) | ((bytes(1) & 0xffL) << 16) | ((bytes(2) & 0xffL) << 8) | (bytes(3) & 0xffL) - - /** - * MPI encoded numbers are produced by the OpenSSL BN_bn2mpi function. They consist of - * a 4 byte big endian length field, followed by the stated number of bytes representing - * the number in big endian format (with a sign bit). - * - */ - private def decodeMPI(mpi: Array[Byte]): BigInteger = { - - val length: Int = readUint32BE(mpi).toInt - val buf = new Array[Byte](length) - System.arraycopy(mpi, 4, buf, 0, length) - - if (buf.length == 0) { - BigInteger.ZERO - } else { - val isNegative: Boolean = (buf(0) & 0x80) == 0x80 - if (isNegative) buf(0) = (buf(0) & 0x7f).toByte - val result: BigInteger = new BigInteger(buf) - if (isNegative) { - result.negate - } else { - result - } - } - } - -} diff --git a/data/shared/src/main/scala/org/ergoplatform/ErgoHeader.scala b/data/shared/src/main/scala/org/ergoplatform/ErgoHeader.scala index cc678003d6..dc076c4173 100644 --- a/data/shared/src/main/scala/org/ergoplatform/ErgoHeader.scala +++ b/data/shared/src/main/scala/org/ergoplatform/ErgoHeader.scala @@ -5,7 +5,7 @@ import scorex.crypto.authds.ADDigest import scorex.crypto.hash.{Blake2b256, Digest32} import scorex.util.ModifierId import sigma.Colls -import sigma.crypto.{CryptoConstants, CryptoFacade, EcPointType} +import sigma.crypto.{CryptoConstants, EcPointType} import sigma.serialization.{GroupElementSerializer, SigmaByteReader, SigmaByteWriter, SigmaSerializer} @@ -91,22 +91,22 @@ object AutolykosSolution { * @param _bytes - serialized bytes of the header when not `null` */ case class ErgoHeader(override val version: ErgoHeader.Version, - override val parentId: ModifierId, - override val ADProofsRoot: Digest32, - override val stateRoot: ADDigest, //33 bytes! extra byte with tree height here! - override val transactionsRoot: Digest32, - override val timestamp: ErgoHeader.Timestamp, - override val nBits: Long, //actually it is unsigned int - override val height: Int, - override val extensionRoot: Digest32, - powSolution: AutolykosSolution, - override val votes: Array[Byte], //3 bytes - override val unparsedBytes: Array[Byte], - _bytes: Array[Byte]) extends + override val parentId: ModifierId, + override val ADProofsRoot: Digest32, + override val stateRoot: ADDigest, //33 bytes! extra byte with tree height here! + override val transactionsRoot: Digest32, + override val timestamp: ErgoHeader.Timestamp, + override val nBits: Long, //actually it is unsigned int + override val height: Int, + override val extensionRoot: Digest32, + powSolution: AutolykosSolution, + override val votes: Array[Byte], //3 bytes + override val unparsedBytes: Array[Byte], + _bytes: Array[Byte]) extends HeaderWithoutPow(version, parentId, ADProofsRoot, stateRoot, transactionsRoot, timestamp, - nBits, height, extensionRoot, votes, unparsedBytes) { + nBits, height, extensionRoot, votes, unparsedBytes) { - lazy val bytes = if(_bytes != null) { + lazy val bytes = if (_bytes != null) { _bytes } else { ErgoHeader.sigmaSerializer.toBytes(this) diff --git a/data/shared/src/main/scala/org/ergoplatform/HeaderWithoutPow.scala b/data/shared/src/main/scala/org/ergoplatform/HeaderWithoutPow.scala index 56e2eafb1b..4eba9b708e 100644 --- a/data/shared/src/main/scala/org/ergoplatform/HeaderWithoutPow.scala +++ b/data/shared/src/main/scala/org/ergoplatform/HeaderWithoutPow.scala @@ -6,8 +6,6 @@ import scorex.util.{ModifierId, bytesToId, idToBytes} import sigma.serialization.{SigmaByteReader, SigmaByteWriter, SigmaSerializer} import scorex.util.Extensions._ -//todo: unify with Ergo node codebase - /** * Header without proof-of-work puzzle solution, see Header class description for details. */ diff --git a/data/shared/src/main/scala/sigma/ast/methods.scala b/data/shared/src/main/scala/sigma/ast/methods.scala index 97c2302b2d..e4cf0007e0 100644 --- a/data/shared/src/main/scala/sigma/ast/methods.scala +++ b/data/shared/src/main/scala/sigma/ast/methods.scala @@ -10,7 +10,6 @@ import sigma.ast.syntax.{SValue, ValueOps} import sigma.data.OverloadHack.Overloaded1 import sigma.data.{DataValueComparer, KeyValueColl, Nullable, RType, SigmaConstants} import sigma.eval.{CostDetails, ErgoTreeEvaluator, TracedCost} -import sigma.pow.Autolykos2PowValidation import sigma.reflection.RClass import sigma.serialization.CoreByteWriter.ArgInfo import sigma.utils.SparseArrayContainer @@ -1457,30 +1456,11 @@ case object SHeaderMethods extends MonoTypeMethods { lazy val powDistanceMethod = propertyCall("powDistance", SBigInt, 14, FixedCost(JitCost(10))) lazy val votesMethod = propertyCall("votes", SByteArray, 15, FixedCost(JitCost(10))) - lazy val checkPowMethod = SMethod( - this, "checkPow", SFunc(Array(SHeader), SBoolean), 16, GroupGenerator.costKind) // todo: cost - .withIRInfo(MethodCallIrBuilder) - .withInfo(Xor, "Check PoW of this header") // todo: desc - - def checkPow_eval(mc: MethodCall, G: SigmaDslBuilder, header: Header) - (implicit E: ErgoTreeEvaluator): Boolean = { - E.checkPow_eval(mc, header) - } - - protected override def getMethods() = { - if (VersionContext.current.isV6SoftForkActivated) { - // 6.0 : checkPow method added - super.getMethods() ++ Seq( - idMethod, versionMethod, parentIdMethod, ADProofsRootMethod, stateRootMethod, transactionsRootMethod, - timestampMethod, nBitsMethod, heightMethod, extensionRootMethod, minerPkMethod, powOnetimePkMethod, - powNonceMethod, powDistanceMethod, votesMethod, checkPowMethod) - } else { - super.getMethods() ++ Seq( - idMethod, versionMethod, parentIdMethod, ADProofsRootMethod, stateRootMethod, transactionsRootMethod, - timestampMethod, nBitsMethod, heightMethod, extensionRootMethod, minerPkMethod, powOnetimePkMethod, - powNonceMethod, powDistanceMethod, votesMethod) - } - } + protected override def getMethods() = super.getMethods() ++ Seq( + idMethod, versionMethod, parentIdMethod, ADProofsRootMethod, stateRootMethod, transactionsRootMethod, + timestampMethod, nBitsMethod, heightMethod, extensionRootMethod, minerPkMethod, powOnetimePkMethod, + powNonceMethod, powDistanceMethod, votesMethod + ) } /** Type descriptor of `PreHeader` type of ErgoTree. */ diff --git a/data/shared/src/main/scala/sigma/data/CHeader.scala b/data/shared/src/main/scala/sigma/data/CHeader.scala index 96fffb0822..d17fb5671f 100644 --- a/data/shared/src/main/scala/sigma/data/CHeader.scala +++ b/data/shared/src/main/scala/sigma/data/CHeader.scala @@ -4,7 +4,6 @@ import org.ergoplatform.{AutolykosSolution, ErgoHeader, HeaderWithoutPow, Header import scorex.crypto.authds.ADDigest import scorex.crypto.hash.Digest32 import scorex.util.{bytesToId, idToBytes} -import sigma.pow.Autolykos2PowValidation import sigma.{AvlTree, BigInt, Coll, Colls, GroupElement, Header} /** A default implementation of [[Header]] interface. @@ -73,26 +72,19 @@ class CHeader(val ergoHeader: ErgoHeader) extends Header with WrapperOf[ErgoHead Colls.fromArray(HeaderWithoutPowSerializer.toBytes(headerWithoutPow)) } - override def checkPow: Boolean = { - if (version == 1) { - throw new Exception("Autolykos v1 is not supported") //todo: more specific exception? - } else { - Autolykos2PowValidation.checkPoWForVersion2(this) - } - } - override def hashCode(): Int = id.hashCode() override def equals(other: Any): Boolean = other match { case ch: CHeader => ch.id == this.id case _ => false } + + def copy(): CHeader = new CHeader(ergoHeader.copy()) // used in tests only } object CHeader { - def apply( id: Coll[Byte], // todo: ignored, remove - version: Byte, + def apply( version: Byte, parentId: Coll[Byte], ADProofsRoot: Coll[Byte], stateRoot: AvlTree, @@ -106,8 +98,7 @@ object CHeader { powNonce: Coll[Byte], powDistance: BigInt, votes: Coll[Byte], - unparsedBytes: Coll[Byte] - ): CHeader = { + unparsedBytes: Coll[Byte]): CHeader = { val solution = AutolykosSolution( minerPk.asInstanceOf[CGroupElement].wrappedValue, @@ -128,5 +119,4 @@ object CHeader { /** Size of nonce array from Autolykos POW solution in Header.powNonce array. */ val NonceSize: Int = SigmaConstants.AutolykosPowSolutionNonceArraySize.value - -} \ No newline at end of file +} diff --git a/data/shared/src/main/scala/sigma/eval/ErgoTreeEvaluator.scala b/data/shared/src/main/scala/sigma/eval/ErgoTreeEvaluator.scala index 610be08c9c..52f839354c 100644 --- a/data/shared/src/main/scala/sigma/eval/ErgoTreeEvaluator.scala +++ b/data/shared/src/main/scala/sigma/eval/ErgoTreeEvaluator.scala @@ -1,6 +1,6 @@ package sigma.eval -import sigma.{AvlTree, Coll, Context, Header} +import sigma.{AvlTree, Coll, Context} import sigma.ast.{Constant, FixedCost, MethodCall, OperationCostInfo, OperationDesc, PerItemCost, SType, TypeBasedCost} import sigma.data.KeyValueColl @@ -138,9 +138,6 @@ abstract class ErgoTreeEvaluator { def remove_eval( mc: MethodCall, tree: AvlTree, operations: Coll[Coll[Byte]], proof: Coll[Byte]): Option[AvlTree] - - def checkPow_eval(mc: MethodCall, header: Header): Boolean - } object ErgoTreeEvaluator { diff --git a/data/shared/src/main/scala/sigma/pow/Autolykos2PowValidation.scala b/data/shared/src/main/scala/sigma/pow/Autolykos2PowValidation.scala deleted file mode 100644 index a27dc864d1..0000000000 --- a/data/shared/src/main/scala/sigma/pow/Autolykos2PowValidation.scala +++ /dev/null @@ -1,167 +0,0 @@ -package sigma.pow - - -import org.bouncycastle.util.BigIntegers -import scorex.crypto.hash.Blake2b256 -import scorex.utils.{Bytes, Ints, Longs} -import sigma.Header -import sigma.crypto.{BcDlogGroup, CryptoConstants} -import sigma.util.NBitsUtils - -object Autolykos2PowValidation { - - type Height = Int - - val k = 32 - - val NStart = 26 - - val group: BcDlogGroup = CryptoConstants.dlogGroup - - // Group order, used in Autolykos V.1 for non-outsourceability, - // and also to obtain target in both Autolykos v1 and v2 - val q: BigInt = group.order - - /** - * Number of elements in a table to find k-sum problem solution on top of - */ - val NBase: Int = Math.pow(2, NStart.toDouble).toInt - - /** - * Initial height since which table (`N` value) starting to increase by 5% per `IncreasePeriodForN` blocks - */ - val IncreaseStart: Height = 600 * 1024 - - /** - * Table size (`N`) increased every 50 * 1024 blocks - */ - val IncreasePeriodForN: Height = 50 * 1024 - - /** - * On this height, the table (`N` value) will stop to grow. - * Max N on and after this height would be 2,143,944,600 which is still less than 2^^31. - */ - val NIncreasementHeightMax: Height = 4198400 - - /** - * Blake2b256 hash function invocation - * @param in - input bit-string - * @return - 256 bits (32 bytes) array - */ - def hash(in: Array[Byte]): Array[Byte] = Blake2b256.hash(in) - - /** - * Convert byte array to unsigned integer - * @param in - byte array - * @return - unsigned integer - */ - def toBigInt(in: Array[Byte]): BigInt = BigInt(BigIntegers.fromUnsignedByteArray(in)) - - /** - * Constant data to be added to hash function to increase its calculation time - */ - val M: Array[Byte] = (0 until 1024).toArray.flatMap(i => Longs.toByteArray(i.toLong)) - - /** - * Calculates table size (N value) for a given height (moment of time) - * - * @see papers/yellow/pow/ErgoPow.tex for full description and test vectors - * @param headerHeight - height of a header to mine - * @return - N value - */ - def calcN(headerHeight: Height): Int = { - val height = Math.min(NIncreasementHeightMax, headerHeight) - if (height < IncreaseStart) { - NBase - } else { - val itersNumber = (height - IncreaseStart) / IncreasePeriodForN + 1 - (1 to itersNumber).foldLeft(NBase) { case (step, _) => - step / 100 * 105 - } - } - } - - def calcN(header: Header): Int = calcN(header.height) - - /** - * Hash function that takes `m` and `nonceBytes` and returns a list of size `k` with numbers in - * [0,`N`) - */ - private def genIndexes(k: Int, seed: Array[Byte], N: Int): Seq[Int] = { - val hash = Blake2b256(seed) - val extendedHash = Bytes.concat(hash, hash.take(3)) - (0 until k).map { i => - BigInt(1, extendedHash.slice(i, i + 4)).mod(N).toInt - } - }.ensuring(_.length == k) - - /** - * Generate element of Autolykos equation. - */ - private def genElementV2(indexBytes: Array[Byte], heightBytes: => Array[Byte]): BigInt = { - // Autolykos v. 2: H(j|h|M) (line 5 from the Algo 2 of the spec) - toBigInt(hash(Bytes.concat(indexBytes, heightBytes, M)).drop(1)) - } - - def hitForVersion2ForMessage(k: Int, msg: Array[Byte], nonce: Array[Byte], h: Array[Byte], N: Int): BigInt = { - - val prei8 = BigIntegers.fromUnsignedByteArray(hash(Bytes.concat(msg, nonce)).takeRight(8)) - val i = BigIntegers.asUnsignedByteArray(4, prei8.mod(BigInt(N).underlying())) - val f = Blake2b256(Bytes.concat(i, h, M)).drop(1) // .drop(1) is the same as takeRight(31) - val seed = Bytes.concat(f, msg, nonce) // Autolykos v1, Alg. 2, line4: - - val indexes = genIndexes(k, seed, N) - //pk and w not used in v2 - val elems = indexes.map(idx => genElementV2(Ints.toByteArray(idx), h)) - val f2 = elems.sum - - // sum as byte array is always about 32 bytes - val array: Array[Byte] = BigIntegers.asUnsignedByteArray(32, f2.underlying()) - val ha = hash(array) - toBigInt(ha) - } - - /** - * Header digest ("message" for default GPU miners) a miner is working on - */ - def msgByHeader(h: Header): Array[Byte] = Blake2b256(h.serializeWithoutPoW.toArray) - - /** - * Get hit for Autolykos v2 header (to test it then against PoW target) - * - * @param header - header to check PoW for - * @return PoW hit - */ - def hitForVersion2(header: Header): BigInt = { - - val msg = msgByHeader(header) - val nonce = header.powNonce - - val h = Ints.toByteArray(header.height) // used in AL v.2 only - - val N = calcN(header) - - hitForVersion2ForMessage(k, msg, nonce.toArray, h, N) - } - - /** - * Get target `b` from encoded difficulty `nBits` - */ - def getB(nBits: Long): BigInt = { - q / NBitsUtils.decodeCompactBits(nBits) - } - - /** - * Check PoW for Autolykos v2 header - * - * @param header - header to check PoW for - * @return whether PoW is valid or not - */ - def checkPoWForVersion2(header: Header): Boolean = { - val b = getB(header.nBits) - // for version 2, we're calculating hit and compare it with target - val hit = hitForVersion2(header) - hit < b - } - -} diff --git a/interpreter/shared/src/main/scala/sigmastate/interpreter/CErgoTreeEvaluator.scala b/interpreter/shared/src/main/scala/sigmastate/interpreter/CErgoTreeEvaluator.scala index 59c9af09ef..2f7d527e74 100644 --- a/interpreter/shared/src/main/scala/sigmastate/interpreter/CErgoTreeEvaluator.scala +++ b/interpreter/shared/src/main/scala/sigmastate/interpreter/CErgoTreeEvaluator.scala @@ -14,8 +14,6 @@ import sigma.ast.SType import sigma.data.{CSigmaProp, KeyValueColl, SigmaBoolean} import sigma.eval.{AvlTreeVerifier, ErgoTreeEvaluator, EvalSettings, Profiler} import sigma.eval.ErgoTreeEvaluator.DataEnv -import sigma.pow.Autolykos2PowValidation -import sigmastate.interpreter.CErgoTreeEvaluator.fixedCostOp import scala.collection.compat.immutable.ArraySeq import scala.util.{DynamicVariable, Failure, Success} @@ -218,15 +216,6 @@ class CErgoTreeEvaluator( } } - override def checkPow_eval(mc: MethodCall, header: Header): Boolean = { - VersionContext.checkVersions(context.activatedScriptVersion, context.currentErgoTreeVersion) - // todo: consider cost - val checkPowCostInfo = OperationCostInfo(FixedCost(JitCost(10)), NamedDesc("Header.checkPow")) - fixedCostOp(checkPowCostInfo){ - header.checkPow - }(this) - } - /** Evaluates the given expression in the given data environment. */ def eval(env: DataEnv, exp: SValue): Any = { VersionContext.checkVersions(context.activatedScriptVersion, context.currentErgoTreeVersion) @@ -460,7 +449,7 @@ object CErgoTreeEvaluator { * HOTSPOT: don't beautify the code * Note, `null` is used instead of Option to avoid allocations. */ - def fixedCostOp[R](costInfo: OperationCostInfo[FixedCost]) + def fixedCostOp[R <: AnyRef](costInfo: OperationCostInfo[FixedCost]) (block: => R)(implicit E: ErgoTreeEvaluator): R = { if (E != null) { var res: R = null.asInstanceOf[R] diff --git a/interpreter/shared/src/test/scala/sigma/serialization/DataSerializerSpecification.scala b/interpreter/shared/src/test/scala/sigma/serialization/DataSerializerSpecification.scala index 34ada33ba3..fecd077287 100644 --- a/interpreter/shared/src/test/scala/sigma/serialization/DataSerializerSpecification.scala +++ b/interpreter/shared/src/test/scala/sigma/serialization/DataSerializerSpecification.scala @@ -7,7 +7,6 @@ import sigma.data.{DataValueComparer, OptionType, RType, SigmaBoolean, TupleColl import sigma.ast.SCollection.SByteArray import sigmastate.eval._ import sigma.{AvlTree, Colls, Evaluation, Header, VersionContext} -import sigma.{AvlTree, Colls, Evaluation, VersionContext} import sigma.ast.SType.AnyOps import sigma.ast._ import org.scalacheck.Gen @@ -24,29 +23,40 @@ import scala.reflect.ClassTag class DataSerializerSpecification extends SerializationSpecification { - def roundtrip[T <: SType](obj: T#WrappedType, tpe: T) = { - val w = SigmaSerializer.startWriter() - DataSerializer.serialize(obj, tpe, w) - val bytes = w.toBytes - val r = SigmaSerializer.startReader(bytes) - val res = DataSerializer.deserialize(tpe, r) - res shouldBe obj - - val es = CErgoTreeEvaluator.DefaultEvalSettings - val accumulator = new CostAccumulator( - initialCost = JitCost(0), - costLimit = Some(JitCost.fromBlockCost(es.scriptCostLimitInEvaluator))) - val evaluator = new CErgoTreeEvaluator( - context = null, - constants = ErgoTree.EmptyConstants, - coster = accumulator, DefaultProfiler, es) - val ok = DataValueComparer.equalDataValues(res, obj)(evaluator) - ok shouldBe true - - val randomPrefix = arrayGen[Byte].sample.get - val r2 = SigmaSerializer.startReader(randomPrefix ++ bytes, randomPrefix.length) - val res2 = DataSerializer.deserialize(tpe, r2) - res2 shouldBe obj + def roundtrip[T <: SType](obj: T#WrappedType, tpe: T, withVersion: Option[Byte] = None) = { + + def test() = { + val w = SigmaSerializer.startWriter() + DataSerializer.serialize(obj, tpe, w) + val bytes = w.toBytes + val r = SigmaSerializer.startReader(bytes) + val res = DataSerializer.deserialize(tpe, r) + res shouldBe obj + + val es = CErgoTreeEvaluator.DefaultEvalSettings + val accumulator = new CostAccumulator( + initialCost = JitCost(0), + costLimit = Some(JitCost.fromBlockCost(es.scriptCostLimitInEvaluator))) + val evaluator = new CErgoTreeEvaluator( + context = null, + constants = ErgoTree.EmptyConstants, + coster = accumulator, DefaultProfiler, es) + val ok = DataValueComparer.equalDataValues(res, obj)(evaluator) + ok shouldBe true + + val randomPrefix = arrayGen[Byte].sample.get + val r2 = SigmaSerializer.startReader(randomPrefix ++ bytes, randomPrefix.length) + val res2 = DataSerializer.deserialize(tpe, r2) + res2 shouldBe obj + } + + withVersion match { + case Some(ver) => + VersionContext.withVersions(ver, 1) { + test() + } + case None => test() + } } def testCollection[T <: SType](tpe: T) = { @@ -130,6 +140,7 @@ class DataSerializerSpecification extends SerializationSpecification { forAll { x: ErgoBox => roundtrip[SBox.type](x, SBox) } forAll { x: AvlTree => roundtrip[SAvlTree.type](x, SAvlTree) } forAll { x: Array[Byte] => roundtrip[SByteArray](x.toColl, SByteArray) } + forAll { x: Header => roundtrip[SHeader.type](x, SHeader, Some(VersionContext.V6SoftForkVersion)) } forAll { t: SPredefType => testCollection(t) } forAll { t: SPredefType => testTuples(t) } forAll { t: SPredefType => testOption(t) } @@ -162,7 +173,7 @@ class DataSerializerSpecification extends SerializationSpecification { }) } - property("header roundtrip") { + property("nuanced versioned test for header roundtrip") { VersionContext.withVersions(VersionContext.V6SoftForkVersion, 1) { forAll { x: Header => roundtrip[SHeader.type](x, SHeader) } } diff --git a/interpreter/shared/src/test/scala/sigma/serialization/MethodCallSerializerSpecification.scala b/interpreter/shared/src/test/scala/sigma/serialization/MethodCallSerializerSpecification.scala index 2332aaccaa..1db166c685 100644 --- a/interpreter/shared/src/test/scala/sigma/serialization/MethodCallSerializerSpecification.scala +++ b/interpreter/shared/src/test/scala/sigma/serialization/MethodCallSerializerSpecification.scala @@ -4,9 +4,6 @@ import sigma.VersionContext import sigma.ast._ import sigma.validation.ValidationException -import scala.util.Try - - class MethodCallSerializerSpecification extends SerializationSpecification { property("MethodCall deserialization round trip") { @@ -48,28 +45,4 @@ class MethodCallSerializerSpecification extends SerializationSpecification { } ) } - - property("MethodCall deserialization round trip for Header.checkPow") { - def code = { - val h = HeaderConstant(headerGen.sample.get) - val expr = MethodCall(h, - SHeaderMethods.checkPowMethod, - Vector(), - Map() - ) - roundTripTest(expr) - } - - VersionContext.withVersions(VersionContext.V6SoftForkVersion, 1) { - code - } - - // sigma.serialization.SerializerException: Don't know how to serialize (sigma.data.CHeader@51dbec76, SHeader) - an[SerializerException] should be thrownBy ( - VersionContext.withVersions((VersionContext.V6SoftForkVersion - 1).toByte, 1) { - code - } - ) - } - } 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 e625923413..f48e1ffc96 100644 --- a/interpreter/shared/src/test/scala/sigma/serialization/generators/ObjectGenerators.scala +++ b/interpreter/shared/src/test/scala/sigma/serialization/generators/ObjectGenerators.scala @@ -694,7 +694,6 @@ trait ObjectGenerators extends TypeGenerators } yield ErgoTree.withSegregation(ZeroHeader, prop) def headerGen(stateRoot: AvlTree, parentId: Coll[Byte]): Gen[Header] = for { - id <- modifierIdBytesGen version <- arbByte.arbitrary adProofsRoot <- digest32Gen transactionRoot <- digest32Gen @@ -708,7 +707,7 @@ trait ObjectGenerators extends TypeGenerators powDistance <- arbBigInt.arbitrary votes <- minerVotesGen unparsedBytes <- collOfRange(0, 32, arbByte.arbitrary) - } yield CHeader(id, version, parentId, adProofsRoot, stateRoot, transactionRoot, timestamp, nBits, + } yield CHeader(version, parentId, adProofsRoot, stateRoot, transactionRoot, timestamp, nBits, height, extensionRoot, minerPk.toGroupElement, powOnetimePk.toGroupElement, powNonce, powDistance, votes, unparsedBytes) lazy val headerGen: Gen[Header] = for { diff --git a/interpreter/shared/src/test/scala/special/sigma/SigmaTestingData.scala b/interpreter/shared/src/test/scala/special/sigma/SigmaTestingData.scala index d1253d4686..63fc202516 100644 --- a/interpreter/shared/src/test/scala/special/sigma/SigmaTestingData.scala +++ b/interpreter/shared/src/test/scala/special/sigma/SigmaTestingData.scala @@ -246,7 +246,6 @@ trait SigmaTestingData extends TestingCommons with ObjectGenerators { ) val h1_instances = new CloneSet(1000, CHeader( - Helpers.decodeBytes("957f008001808080ffe4ffffc8f3802401df40006aa05e017fa8d3f6004c804a"), 0.toByte, Helpers.decodeBytes("0180dd805b0000ff5400b997fd7f0b9b00de00fb03c47e37806a8186b94f07ff"), Helpers.decodeBytes("01f07f60d100ffb970c3007f60ff7f24d4070bb8fffa7fca7f34c10001ffe39d"), 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 9bb501faed..7c7b80d39a 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/GraphBuilding.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/GraphBuilding.scala @@ -1,7 +1,6 @@ package sigma.compiler.ir import org.ergoplatform._ -import sigma.{SigmaException, VersionContext, ast} import sigma.ast.TypeCodes.LastConstantCode import sigma.ast.Value.Typed import sigma.ast.syntax.{SValue, ValueOps} diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/SigmaDslUnit.scala b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/SigmaDslUnit.scala index f38748bbe4..2a6a341686 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/SigmaDslUnit.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/SigmaDslUnit.scala @@ -78,7 +78,6 @@ import scalan._ def powNonce: Ref[Coll[Byte]]; def powDistance: Ref[BigInt]; def votes: Ref[Coll[Byte]] - def checkPow: Ref[Boolean] }; trait Context extends Def[Context] { def OUTPUTS: Ref[Coll[Box]]; diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/SigmaDslImpl.scala b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/SigmaDslImpl.scala index 8d1b3aa1f5..c113cb7de3 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/SigmaDslImpl.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/SigmaDslImpl.scala @@ -1368,13 +1368,6 @@ object Header extends EntityObject("Header") { ArraySeq.empty, true, false, element[Coll[Byte]])) } - - override def checkPow: Ref[Boolean] = { - asRep[Boolean](mkMethodCall(self, - HeaderClass.getMethod("checkPow"), - ArraySeq.empty, - true, false, element[Boolean])) - } } implicit object LiftableHeader @@ -1499,13 +1492,6 @@ object Header extends EntityObject("Header") { ArraySeq.empty, true, true, element[Coll[Byte]])) } - - def checkPow: Ref[Boolean] = { - asRep[Boolean](mkMethodCall(source, - HeaderClass.getMethod("checkPow"), - ArraySeq.empty, - true, true, element[Boolean])) - } } // entityUnref: single unref method for each type family diff --git a/sc/shared/src/test/scala/sigma/SigmaDslSpecification.scala b/sc/shared/src/test/scala/sigma/SigmaDslSpecification.scala index 1977537cbf..fddace6a5c 100644 --- a/sc/shared/src/test/scala/sigma/SigmaDslSpecification.scala +++ b/sc/shared/src/test/scala/sigma/SigmaDslSpecification.scala @@ -4654,7 +4654,6 @@ class SigmaDslSpecification extends SigmaDslTesting ) val header = CHeader( - Helpers.decodeBytes("1c597f88969600d2fffffdc47f00d8ffc555a9e85001000001c505ff80ff8f7f"), 0.toByte, Helpers.decodeBytes("7a7fe5347f09017818010062000001807f86808000ff7f66ffb07f7ad27f3362"), Helpers.decodeBytes("c1d70ad9b1ffc1fb9a715fff19807f2401017fcd8b73db017f1cff77727fff08"), diff --git a/sdk/js/src/main/scala/org/ergoplatform/sdk/js/Isos.scala b/sdk/js/src/main/scala/org/ergoplatform/sdk/js/Isos.scala index 89d5e3413c..66df205e85 100644 --- a/sdk/js/src/main/scala/org/ergoplatform/sdk/js/Isos.scala +++ b/sdk/js/src/main/scala/org/ergoplatform/sdk/js/Isos.scala @@ -7,13 +7,9 @@ import sigma.ast.{Constant, SType} import sigma.data.Iso import sigma.data.Iso.{isoStringToArray, isoStringToColl} import sigma.data.js.{Isos => DataIsos} -import sigma.data.{CBigInt, CGroupElement, CHeader, Digest32Coll, Digest32CollRType, Iso} +import sigma.data.CHeader import sigma.interpreter.{ContextExtension, ProverResult} import sigma.js.AvlTree -import sigmastate.eval.{CHeader, CPreHeader} -import sigma.js.{AvlTree, GroupElement} -import sigma.serialization.{ErgoTreeSerializer, ValueSerializer} -import sigma.{Coll, Colls} import sigmastate.eval.CPreHeader import sigmastate.fleetSdkCommon.distEsmTypesBoxesMod.Box import sigmastate.fleetSdkCommon.distEsmTypesRegistersMod.NonMandatoryRegisters @@ -32,7 +28,6 @@ object Isos { implicit val isoHeader: Iso[Header, sigma.Header] = new Iso[Header, sigma.Header] { override def to(a: Header): sigma.Header = { CHeader( - id = isoStringToColl.to(a.id), version = a.version, parentId = isoStringToColl.to(a.parentId), ADProofsRoot = isoStringToColl.to(a.ADProofsRoot), diff --git a/sdk/shared/src/main/scala/org/ergoplatform/sdk/JsonCodecs.scala b/sdk/shared/src/main/scala/org/ergoplatform/sdk/JsonCodecs.scala index b7f445d902..0b6aa5555f 100644 --- a/sdk/shared/src/main/scala/org/ergoplatform/sdk/JsonCodecs.scala +++ b/sdk/shared/src/main/scala/org/ergoplatform/sdk/JsonCodecs.scala @@ -20,7 +20,7 @@ import sigma.serialization.{ErgoTreeSerializer, ValueSerializer} import sigma.validation.SigmaValidationSettings import sigma.{AnyValue, Coll, Colls, Header, PreHeader, SigmaException} import sigmastate.eval.{CPreHeader, _} -import sigmastate.utils.Helpers._ +import sigmastate.utils.Helpers._ // required for Scala 2.11 import java.math.BigInteger import scala.collection.mutable @@ -132,7 +132,6 @@ trait JsonCodecs { implicit val headerDecoder: Decoder[Header] = Decoder.instance({ cursor => for { - id <- cursor.downField("id").as[Coll[Byte]] version <- cursor.downField("version").as[Byte] parentId <- cursor.downField("parentId").as[Coll[Byte]] adProofsRoot <- cursor.downField("adProofsRoot").as[Coll[Byte]] @@ -148,7 +147,7 @@ trait JsonCodecs { powDistance <- cursor.downField("powDistance").as[sigma.BigInt] votes <- cursor.downField("votes").as[Coll[Byte]] unparsedBytes <- cursor.downField("unparsedBytes").as[Option[Coll[Byte]]] - } yield CHeader(id, version, parentId, adProofsRoot, stateRoot, transactionsRoot, timestamp, nBits, + } yield CHeader(version, parentId, adProofsRoot, stateRoot, transactionsRoot, timestamp, nBits, height, extensionRoot, SigmaDsl.decodePoint(minerPk), SigmaDsl.decodePoint(powOnetimePk), powNonce, powDistance, votes, unparsedBytes.getOrElse(Colls.emptyColl)) }) From 361c7a4400b19bec95ab98549f7911c2990a4c8f Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Wed, 5 Jun 2024 14:13:23 +0300 Subject: [PATCH 120/314] merging with i969, removing BouncyCastle dep from Autolykos2PowValidation --- .../src/main/scala/sigma/SigmaDsl.scala | 10 ++ .../scala/org/ergoplatform/ErgoHeader.scala | 159 ++++++++++++++++++ .../org/ergoplatform/HeaderWithoutPow.scala | 8 +- .../sigma/pow/Autolykos2PowValidation.scala | 6 +- .../sigma/compiler/ir/GraphBuilding.scala | 2 +- .../TestingInterpreterSpecification.scala | 4 - 6 files changed, 179 insertions(+), 10 deletions(-) create mode 100644 data/shared/src/main/scala/org/ergoplatform/ErgoHeader.scala diff --git a/core/shared/src/main/scala/sigma/SigmaDsl.scala b/core/shared/src/main/scala/sigma/SigmaDsl.scala index a2894515a2..1e5b5405eb 100644 --- a/core/shared/src/main/scala/sigma/SigmaDsl.scala +++ b/core/shared/src/main/scala/sigma/SigmaDsl.scala @@ -460,10 +460,20 @@ trait Header { /** Miner votes for changing system parameters. */ def votes: Coll[Byte] //3 bytes + /** Bytes which are coming from future versions of the protocol, so + * their meaning is not known to current version of Sigma, but they + * are stored to get the same id as future version users. + */ def unparsedBytes: Coll[Byte] + /** + * @return bytes without proof of work, needed for working to get the proof on + */ def serializeWithoutPoW: Coll[Byte] + /** + * @return result of header's proof-of-work validation + */ def checkPow: Boolean } diff --git a/data/shared/src/main/scala/org/ergoplatform/ErgoHeader.scala b/data/shared/src/main/scala/org/ergoplatform/ErgoHeader.scala new file mode 100644 index 0000000000..b937bef7a3 --- /dev/null +++ b/data/shared/src/main/scala/org/ergoplatform/ErgoHeader.scala @@ -0,0 +1,159 @@ +package org.ergoplatform + +import scorex.crypto.authds.ADDigest +import scorex.crypto.hash.{Blake2b256, Digest32} +import scorex.util.ModifierId +import sigma.Colls +import sigma.crypto.{BigIntegers, CryptoConstants, EcPointType} +import sigma.serialization.{GroupElementSerializer, SigmaByteReader, SigmaByteWriter, SigmaSerializer} + + +/** + * Solution for an Autolykos PoW puzzle. + * + * In Autolykos v.1 all the four fields are used, in Autolykos v.2 only pk and n fields are used. + * + * @param pk - miner public key. Should be used to collect block rewards + * @param w - one-time public key. Prevents revealing of miners secret + * @param n - nonce (8 bytes) + * @param d - distance between pseudo-random number, corresponding to nonce `n` and a secret, + * corresponding to `pk`. The lower `d` is, the harder it was to find this solution. + */ +case class AutolykosSolution(pk: EcPointType, + w: EcPointType, + n: Array[Byte], + d: BigInt) { + + val encodedPk: Array[Byte] = GroupElementSerializer.toBytes(pk) + +} + + +object AutolykosSolution { + // "pk", "w" and "d" values for Autolykos v2 solution, where they not passed from outside + val pkForV2: EcPointType = CryptoConstants.dlogGroup.identity + val wForV2: EcPointType = CryptoConstants.dlogGroup.generator + val dForV2: BigInt = 0 + + object sigmaSerializerV1 extends SigmaSerializer[AutolykosSolution, AutolykosSolution] { + override def serialize(s: AutolykosSolution, w: SigmaByteWriter): Unit = { + GroupElementSerializer.serialize(s.pk, w) + GroupElementSerializer.serialize(s.w, w) + require(s.n.length == 8) // non-consensus check on prover side + w.putBytes(s.n) + val dBytes = BigIntegers.asUnsignedByteArray(s.d.bigInteger) + w.putUByte(dBytes.length) + w.putBytes(dBytes) + } + + override def parse(r: SigmaByteReader): AutolykosSolution = { + val pk = GroupElementSerializer.parse(r) + val w = GroupElementSerializer.parse(r) + val nonce = r.getBytes(8) + val dBytesLength = r.getUByte() + val d = BigInt(BigIntegers.fromUnsignedByteArray(r.getBytes(dBytesLength))) + AutolykosSolution(pk, w, nonce, d) + } + } + + object sigmaSerializerV2 extends SigmaSerializer[AutolykosSolution, AutolykosSolution] { + override def serialize(s: AutolykosSolution, w: SigmaByteWriter): Unit = { + GroupElementSerializer.serialize(s.pk, w) + require(s.n.length == 8) // non-consensus check on prover side + w.putBytes(s.n) + } + + override def parse(r: SigmaByteReader): AutolykosSolution = { + val pk = GroupElementSerializer.parse(r) + val nonce = r.getBytes(8) + AutolykosSolution(pk, wForV2, nonce, dForV2) + } + } +} + +/** + * Header of a block. It authenticates link to a previous block, other block sections + * (transactions, UTXO set transformation proofs, extension), UTXO set, votes for parameters + * to be changed and proof-of-work related data. + * + * @param version - protocol version + * @param parentId - id of a parent block header + * @param ADProofsRoot - digest of UTXO set transformation proofs + * @param stateRoot - AVL+ tree digest of UTXO set (after the block) + * @param transactionsRoot - Merkle tree digest of transactions in the block (BlockTransactions section) + * @param timestamp - block generation time reported by a miner + * @param nBits - difficulty encoded + * @param height - height of the block (genesis block height == 1) + * @param extensionRoot - Merkle tree digest of the extension section of the block + * @param powSolution - solution for the proof-of-work puzzle + * @param votes - votes for changing system parameters + * @param unparsedBytes - bytes from future versions of the protocol our version can't parse + * @param _bytes - serialized bytes of the header when not `null` + */ +case class ErgoHeader(override val version: ErgoHeader.Version, + override val parentId: ModifierId, + override val ADProofsRoot: Digest32, + override val stateRoot: ADDigest, //33 bytes! extra byte with tree height here! + override val transactionsRoot: Digest32, + override val timestamp: ErgoHeader.Timestamp, + override val nBits: Long, //actually it is unsigned int + override val height: Int, + override val extensionRoot: Digest32, + powSolution: AutolykosSolution, + override val votes: Array[Byte], //3 bytes + override val unparsedBytes: Array[Byte], + _bytes: Array[Byte]) extends + HeaderWithoutPow(version, parentId, ADProofsRoot, stateRoot, transactionsRoot, timestamp, + nBits, height, extensionRoot, votes, unparsedBytes) { + + lazy val bytes = if(_bytes != null) { + _bytes + } else { + ErgoHeader.sigmaSerializer.toBytes(this) + } + + lazy val serializedId: Array[Byte] = Blake2b256.hash(bytes) + + lazy val id = Colls.fromArray(serializedId) + + override def hashCode(): Int = id.hashCode() + + override def equals(other: Any): Boolean = other match { + case h: ErgoHeader => h.id == this.id + case _ => false + } +} + + +object ErgoHeader { + + type Timestamp = Long + + type Version = Byte + + object sigmaSerializer extends SigmaSerializer[ErgoHeader, ErgoHeader] { + override def serialize(hdr: ErgoHeader, w: SigmaByteWriter): Unit = { + HeaderWithoutPowSerializer.serialize(hdr, w) + if (hdr.version == 1) { + AutolykosSolution.sigmaSerializerV1.serialize(hdr.powSolution, w) + } else { + AutolykosSolution.sigmaSerializerV2.serialize(hdr.powSolution, w) + } + } + + override def parse(r: SigmaByteReader): ErgoHeader = { + val start = r.position + val headerWithoutPow = HeaderWithoutPowSerializer.parse(r) + val powSolution = if (headerWithoutPow.version == 1) { + AutolykosSolution.sigmaSerializerV1.parse(r) + } else { + AutolykosSolution.sigmaSerializerV2.parse(r) + } + val end = r.position + val len = end - start + r.position = start + val headerBytes = r.getBytes(len) // also moves position back to end + headerWithoutPow.toHeader(powSolution, headerBytes) + } + } +} \ No newline at end of file diff --git a/data/shared/src/main/scala/org/ergoplatform/HeaderWithoutPow.scala b/data/shared/src/main/scala/org/ergoplatform/HeaderWithoutPow.scala index d29cc6cbd8..4eba9b708e 100644 --- a/data/shared/src/main/scala/org/ergoplatform/HeaderWithoutPow.scala +++ b/data/shared/src/main/scala/org/ergoplatform/HeaderWithoutPow.scala @@ -6,8 +6,6 @@ import scorex.util.{ModifierId, bytesToId, idToBytes} import sigma.serialization.{SigmaByteReader, SigmaByteWriter, SigmaSerializer} import scorex.util.Extensions._ -//todo: unify with Ergo node codebase - /** * Header without proof-of-work puzzle solution, see Header class description for details. */ @@ -21,7 +19,11 @@ class HeaderWithoutPow(val version: Byte, // 1 byte val height: Int, val extensionRoot: Digest32, val votes: Array[Byte], //3 bytes - val unparsedBytes: Array[Byte]) + val unparsedBytes: Array[Byte]) { + def toHeader(powSolution: AutolykosSolution, bytes: Array[Byte]): ErgoHeader = + ErgoHeader(version, parentId, ADProofsRoot, stateRoot, transactionsRoot, timestamp, + nBits, height, extensionRoot, powSolution, votes, unparsedBytes, bytes) +} object HeaderWithoutPow { diff --git a/data/shared/src/main/scala/sigma/pow/Autolykos2PowValidation.scala b/data/shared/src/main/scala/sigma/pow/Autolykos2PowValidation.scala index a27dc864d1..c2166493e6 100644 --- a/data/shared/src/main/scala/sigma/pow/Autolykos2PowValidation.scala +++ b/data/shared/src/main/scala/sigma/pow/Autolykos2PowValidation.scala @@ -1,13 +1,15 @@ package sigma.pow -import org.bouncycastle.util.BigIntegers import scorex.crypto.hash.Blake2b256 import scorex.utils.{Bytes, Ints, Longs} import sigma.Header -import sigma.crypto.{BcDlogGroup, CryptoConstants} +import sigma.crypto.{BcDlogGroup, BigIntegers, CryptoConstants} import sigma.util.NBitsUtils +/** + * Functions used to validate Autolykos2 Proof-of-Work + */ object Autolykos2PowValidation { type Height = Int 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 fc2efd2970..f9fc2b2545 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/GraphBuilding.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/GraphBuilding.scala @@ -13,7 +13,7 @@ import sigma.data.{CSigmaDslBuilder, ExactIntegral, ExactNumeric, ExactOrdering, import sigma.exceptions.GraphBuildingException import sigma.serialization.OpCodes import sigma.util.Extensions.ByteOps -import sigma.{SigmaException, ast} +import sigma.{SigmaException, VersionContext, ast} import sigmastate.interpreter.Interpreter.ScriptEnv import scala.collection.mutable.ArrayBuffer diff --git a/sc/shared/src/test/scala/sigmastate/TestingInterpreterSpecification.scala b/sc/shared/src/test/scala/sigmastate/TestingInterpreterSpecification.scala index 4948f70c23..23d623f077 100644 --- a/sc/shared/src/test/scala/sigmastate/TestingInterpreterSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/TestingInterpreterSpecification.scala @@ -13,7 +13,6 @@ import org.scalatest.BeforeAndAfterAll import scorex.util.encode.Base58 import sigma.Colls import sigma.VersionContext.V6SoftForkVersion -import sigma.crypto.CryptoConstants import sigma.data.{CAND, CAvlTree, ProveDlog, SigmaBoolean, TrivialProp} import sigma.interpreter.ContextExtension import sigma.util.Extensions.IntOps @@ -439,9 +438,6 @@ class TestingInterpreterSpecification extends CompilerTestingCommons } property("checkPow") { - - //todo: check invalid header - val source = """ { | val h = CONTEXT.headers(0) | h.checkPow From d01469c71e46a815eaabceffe914004ef9bdeb75 Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Tue, 4 Jun 2024 12:44:33 +0300 Subject: [PATCH 121/314] fixing and improving tests --- .../scala/org/ergoplatform/ErgoHeader.scala | 14 ++-- .../src/main/scala/sigma/data/CHeader.scala | 22 ++++++- .../ConstantSerializerSpecification.scala | 41 ++++++++---- .../DataSerializerSpecification.scala | 65 +++++++++++++++---- .../SerializationSpecification.scala | 19 ++++-- .../generators/ObjectGenerators.scala | 6 +- .../generators/TypeGenerators.scala | 3 +- .../special/sigma/SigmaTestingData.scala | 8 +-- .../scala/sigma/SigmaDslSpecification.scala | 19 ++---- .../TestingInterpreterSpecification.scala | 26 -------- .../scala/org/ergoplatform/sdk/js/Isos.scala | 2 +- .../org/ergoplatform/sdk/JsonCodecs.scala | 2 +- 12 files changed, 142 insertions(+), 85 deletions(-) diff --git a/data/shared/src/main/scala/org/ergoplatform/ErgoHeader.scala b/data/shared/src/main/scala/org/ergoplatform/ErgoHeader.scala index dc076c4173..b937bef7a3 100644 --- a/data/shared/src/main/scala/org/ergoplatform/ErgoHeader.scala +++ b/data/shared/src/main/scala/org/ergoplatform/ErgoHeader.scala @@ -1,11 +1,10 @@ package org.ergoplatform -import org.bouncycastle.util.BigIntegers import scorex.crypto.authds.ADDigest import scorex.crypto.hash.{Blake2b256, Digest32} import scorex.util.ModifierId import sigma.Colls -import sigma.crypto.{CryptoConstants, EcPointType} +import sigma.crypto.{BigIntegers, CryptoConstants, EcPointType} import sigma.serialization.{GroupElementSerializer, SigmaByteReader, SigmaByteWriter, SigmaSerializer} @@ -88,6 +87,7 @@ object AutolykosSolution { * @param extensionRoot - Merkle tree digest of the extension section of the block * @param powSolution - solution for the proof-of-work puzzle * @param votes - votes for changing system parameters + * @param unparsedBytes - bytes from future versions of the protocol our version can't parse * @param _bytes - serialized bytes of the header when not `null` */ case class ErgoHeader(override val version: ErgoHeader.Version, @@ -104,9 +104,9 @@ case class ErgoHeader(override val version: ErgoHeader.Version, override val unparsedBytes: Array[Byte], _bytes: Array[Byte]) extends HeaderWithoutPow(version, parentId, ADProofsRoot, stateRoot, transactionsRoot, timestamp, - nBits, height, extensionRoot, votes, unparsedBytes) { + nBits, height, extensionRoot, votes, unparsedBytes) { - lazy val bytes = if (_bytes != null) { + lazy val bytes = if(_bytes != null) { _bytes } else { ErgoHeader.sigmaSerializer.toBytes(this) @@ -116,6 +116,12 @@ case class ErgoHeader(override val version: ErgoHeader.Version, lazy val id = Colls.fromArray(serializedId) + override def hashCode(): Int = id.hashCode() + + override def equals(other: Any): Boolean = other match { + case h: ErgoHeader => h.id == this.id + case _ => false + } } diff --git a/data/shared/src/main/scala/sigma/data/CHeader.scala b/data/shared/src/main/scala/sigma/data/CHeader.scala index d17fb5671f..5999678e5f 100644 --- a/data/shared/src/main/scala/sigma/data/CHeader.scala +++ b/data/shared/src/main/scala/sigma/data/CHeader.scala @@ -72,6 +72,24 @@ class CHeader(val ergoHeader: ErgoHeader) extends Header with WrapperOf[ErgoHead Colls.fromArray(HeaderWithoutPowSerializer.toBytes(headerWithoutPow)) } + override def toString: String = + s"""CHeader( + | id: ${id}, + | version: ${version}, + | tx proofs hash: ${ADProofsRoot}, + | state root: ${stateRoot.digest}, + | transactions root: ${transactionsRoot}, + | time: $timestamp, + | nbits: $nBits, + | extension root: $extensionRoot, + | miner pubkey: $minerPk, + | pow one time pubkey(from AL 1): $powOnetimePk, + | pow nonce: $powNonce, + | pow distance (from AL 1): $powDistance, + | votes: $votes, + | unparsed bytes: $unparsedBytes + |)""".stripMargin + override def hashCode(): Int = id.hashCode() override def equals(other: Any): Boolean = other match { @@ -87,7 +105,7 @@ object CHeader { def apply( version: Byte, parentId: Coll[Byte], ADProofsRoot: Coll[Byte], - stateRoot: AvlTree, + stateRootDigest: Coll[Byte], transactionsRoot: Coll[Byte], timestamp: Long, nBits: Long, @@ -107,7 +125,7 @@ object CHeader { powDistance.asInstanceOf[CBigInt].wrappedValue) val h = ErgoHeader(version, bytesToId(parentId.toArray), Digest32 @@ ADProofsRoot.toArray, - ADDigest @@ stateRoot.digest.toArray, Digest32 @@ transactionsRoot.toArray, timestamp, nBits, height, + ADDigest @@ stateRootDigest.toArray, Digest32 @@ transactionsRoot.toArray, timestamp, nBits, height, Digest32 @@ extensionRoot.toArray, solution, votes.toArray, unparsedBytes.toArray, null) new CHeader(h) diff --git a/interpreter/shared/src/test/scala/sigma/serialization/ConstantSerializerSpecification.scala b/interpreter/shared/src/test/scala/sigma/serialization/ConstantSerializerSpecification.scala index 43e9cf9e5d..c9478c8356 100644 --- a/interpreter/shared/src/test/scala/sigma/serialization/ConstantSerializerSpecification.scala +++ b/interpreter/shared/src/test/scala/sigma/serialization/ConstantSerializerSpecification.scala @@ -9,7 +9,7 @@ import sigma.ast.{BigIntConstant, ByteArrayConstant, Constant, DeserializationSi import sigmastate.eval._ import sigma.Extensions.ArrayOps import sigma.ast._ -import sigma.{AvlTree, Colls, Evaluation} +import sigma.{AvlTree, Colls, Evaluation, Header, VersionContext} import sigma.ast.SType.AnyOps import scorex.util.encode.Base16 import sigma.ast.BoolArrayConstant.BoolArrayTypeCode @@ -17,6 +17,7 @@ import sigma.ast.ByteArrayConstant.ByteArrayTypeCode import sigma.ast.syntax.{BoolValue, SValue} import sigma.crypto.EcPointType import sigma.util.Extensions.{BigIntegerOps, EcpOps, SigmaBooleanOps} + import scala.annotation.nowarn class ConstantSerializerSpecification extends TableSerializationSpecification { @@ -25,22 +26,29 @@ class ConstantSerializerSpecification extends TableSerializationSpecification { implicit val wWrapped = wrappedTypeGen(tpe) implicit val tT = Evaluation.stypeToRType(tpe) implicit val tag = tT.classTag + + val withVersion = if (tpe == SHeader) { + Some(VersionContext.V6SoftForkVersion) + } else { + None + } + forAll { xs: Array[T#WrappedType] => implicit val tAny = sigma.AnyType - roundTripTest(Constant[SCollection[T]](xs.toColl, SCollection(tpe))) - roundTripTest(Constant[SType](xs.toColl.map(x => (x, x)).asWrappedType, SCollection(STuple(tpe, tpe)))) // pairs are special case + roundTripTest(Constant[SCollection[T]](xs.toColl, SCollection(tpe)), withVersion) + roundTripTest(Constant[SType](xs.toColl.map(x => (x, x)).asWrappedType, SCollection(STuple(tpe, tpe))), withVersion) // pairs are special case val triples = xs.toColl.map(x => TupleColl(x, x, x)).asWrappedType - roundTripTest(Constant[SType](triples, SCollection(STuple(tpe, tpe, tpe)))) + roundTripTest(Constant[SType](triples, SCollection(STuple(tpe, tpe, tpe))), withVersion) val quartets = xs.toColl.map(x => TupleColl(x, x, x, x)).asWrappedType - roundTripTest(Constant[SType](quartets, SCollection(STuple(tpe, tpe, tpe, tpe)))) - roundTripTest(Constant[SCollection[SCollection[T]]](xs.toColl.map(x => Colls.fromItems(x, x)), SCollection(SCollection(tpe)))) + roundTripTest(Constant[SType](quartets, SCollection(STuple(tpe, tpe, tpe, tpe))), withVersion) + roundTripTest(Constant[SCollection[SCollection[T]]](xs.toColl.map(x => Colls.fromItems(x, x)), SCollection(SCollection(tpe))), withVersion) roundTripTest(Constant[SType]( xs.toColl.map { x => val arr = Colls.fromItems(x, x) (arr, arr) }.asWrappedType, SCollection(STuple(SCollection(tpe), SCollection(tpe))) - )) + ), withVersion) } } @@ -49,14 +57,19 @@ class ConstantSerializerSpecification extends TableSerializationSpecification { implicit val tT = Evaluation.stypeToRType(tpe) @nowarn implicit val tag = tT.classTag implicit val tAny: RType[Any] = sigma.AnyType + val withVersion = if (tpe == SHeader) { + Some(VersionContext.V6SoftForkVersion) + } else { + None + } forAll { in: (T#WrappedType, T#WrappedType) => val (x,y) = (in._1, in._2) - roundTripTest(Constant[SType]((x, y).asWrappedType, STuple(tpe, tpe))) - roundTripTest(Constant[SType](TupleColl(x, y, x).asWrappedType, STuple(tpe, tpe, tpe))) - roundTripTest(Constant[SType](TupleColl(x, y, x, y).asWrappedType, STuple(tpe, tpe, tpe, tpe))) - roundTripTest(Constant[STuple](Colls.fromItems[Any](x, y, (x, y)), STuple(tpe, tpe, STuple(tpe, tpe)))) - roundTripTest(Constant[STuple](Colls.fromItems[Any](x, y, TupleColl(x, y, x)), STuple(tpe, tpe, STuple(tpe, tpe, tpe)))) - roundTripTest(Constant[STuple](Colls.fromItems[Any](x, y, TupleColl(x, y, (x, y))), STuple(tpe, tpe, STuple(tpe, tpe, STuple(tpe, tpe))))) + roundTripTest(Constant[SType]((x, y).asWrappedType, STuple(tpe, tpe)), withVersion) + roundTripTest(Constant[SType](TupleColl(x, y, x).asWrappedType, STuple(tpe, tpe, tpe)), withVersion) + roundTripTest(Constant[SType](TupleColl(x, y, x, y).asWrappedType, STuple(tpe, tpe, tpe, tpe)), withVersion) + roundTripTest(Constant[STuple](Colls.fromItems[Any](x, y, (x, y)), STuple(tpe, tpe, STuple(tpe, tpe))), withVersion) + roundTripTest(Constant[STuple](Colls.fromItems[Any](x, y, TupleColl(x, y, x)), STuple(tpe, tpe, STuple(tpe, tpe, tpe))), withVersion) + roundTripTest(Constant[STuple](Colls.fromItems[Any](x, y, TupleColl(x, y, (x, y))), STuple(tpe, tpe, STuple(tpe, tpe, STuple(tpe, tpe)))), withVersion) } } @@ -71,6 +84,7 @@ class ConstantSerializerSpecification extends TableSerializationSpecification { forAll { x: SigmaBoolean => roundTripTest(Constant[SSigmaProp.type](x.toSigmaProp, SSigmaProp)) } forAll { x: ErgoBox => roundTripTest(Constant[SBox.type](x, SBox)) } forAll { x: AvlTree => roundTripTest(Constant[SAvlTree.type](x, SAvlTree)) } + forAll { x: Header => roundTripTest(Constant[SHeader.type](x, SHeader), Some(VersionContext.V6SoftForkVersion)) } forAll { x: Array[Byte] => roundTripTest(Constant[SByteArray](x.toColl, SByteArray)) } forAll { t: SPredefType => testCollection(t) } forAll { t: SPredefType => testTuples(t) } @@ -88,6 +102,7 @@ class ConstantSerializerSpecification extends TableSerializationSpecification { testCollection(SUnit) testCollection(SBox) testCollection(SAvlTree) + testCollection(SHeader) } private def caseObjectValue(v: SValue) = (v, Array[Byte](v.opCode)) diff --git a/interpreter/shared/src/test/scala/sigma/serialization/DataSerializerSpecification.scala b/interpreter/shared/src/test/scala/sigma/serialization/DataSerializerSpecification.scala index fecd077287..fe6f62dbe0 100644 --- a/interpreter/shared/src/test/scala/sigma/serialization/DataSerializerSpecification.scala +++ b/interpreter/shared/src/test/scala/sigma/serialization/DataSerializerSpecification.scala @@ -3,7 +3,7 @@ package sigma.serialization import java.math.BigInteger import org.ergoplatform.ErgoBox import org.scalacheck.Arbitrary._ -import sigma.data.{DataValueComparer, OptionType, RType, SigmaBoolean, TupleColl} +import sigma.data.{CBigInt, CHeader, DataValueComparer, OptionType, RType, SigmaBoolean, TupleColl} import sigma.ast.SCollection.SByteArray import sigmastate.eval._ import sigma.{AvlTree, Colls, Evaluation, Header, VersionContext} @@ -55,7 +55,8 @@ class DataSerializerSpecification extends SerializationSpecification { VersionContext.withVersions(ver, 1) { test() } - case None => test() + case None => + test() } } @@ -64,25 +65,32 @@ class DataSerializerSpecification extends SerializationSpecification { implicit val tT = Evaluation.stypeToRType(tpe) implicit val tagT = tT.classTag implicit val tAny = sigma.AnyType + + val withVersion = if (tpe == SHeader) { + Some(VersionContext.V6SoftForkVersion) + } else { + None + } forAll { xs: Array[T#WrappedType] => - roundtrip[SCollection[T]](xs.toColl, SCollection(tpe)) - roundtrip[SType](xs.toColl.map(x => (x, x)).asWrappedType, SCollection(STuple(tpe, tpe))) + roundtrip[SCollection[T]](xs.toColl, SCollection(tpe), withVersion) + roundtrip[SType](xs.toColl.map(x => (x, x)).asWrappedType, SCollection(STuple(tpe, tpe)), withVersion) val triples = xs.toColl.map(x => TupleColl(x, x, x)).asWrappedType - roundtrip(triples, SCollection(STuple(tpe, tpe, tpe))) + roundtrip(triples, SCollection(STuple(tpe, tpe, tpe)), withVersion) val quartets = xs.toColl.map(x => TupleColl(x, x, x, x)).asWrappedType - roundtrip(quartets, SCollection(STuple(tpe, tpe, tpe, tpe))) + roundtrip(quartets, SCollection(STuple(tpe, tpe, tpe, tpe)), withVersion) val nested = xs.toColl.map(x => Colls.fromItems[T#WrappedType](x, x)) - roundtrip[SCollection[SCollection[T]]](nested, SCollection(SCollection(tpe))) + roundtrip[SCollection[SCollection[T]]](nested, SCollection(SCollection(tpe)), withVersion) roundtrip[SType]( xs.toColl.map { x => val arr = Colls.fromItems[T#WrappedType](x, x) (arr, arr) }.asWrappedType, - SCollection(STuple(SCollection(tpe), SCollection(tpe))) + SCollection(STuple(SCollection(tpe), SCollection(tpe))), + withVersion ) } } @@ -92,14 +100,19 @@ class DataSerializerSpecification extends SerializationSpecification { val tT = Evaluation.stypeToRType(tpe) @nowarn implicit val tag: ClassTag[T#WrappedType] = tT.classTag implicit val tAny : RType[Any] = sigma.AnyType + val withVersion = if (tpe == SHeader) { + Some(VersionContext.V6SoftForkVersion) + } else { + None + } forAll { in: (T#WrappedType, T#WrappedType) => val (x,y) = (in._1, in._2) - roundtrip[SType]((x, y).asWrappedType, STuple(tpe, tpe)) - roundtrip[SType](TupleColl(x, y, x).asWrappedType, STuple(tpe, tpe, tpe)) - roundtrip[SType](TupleColl(x, y, x, y).asWrappedType, STuple(tpe, tpe, tpe, tpe)) - roundtrip[STuple](Colls.fromItems[Any](x, y, (x, y)), STuple(tpe, tpe, STuple(tpe, tpe))) - roundtrip[STuple](Colls.fromItems[Any](x, y, TupleColl(x, y, x)), STuple(tpe, tpe, STuple(tpe, tpe, tpe))) - roundtrip[STuple](Colls.fromItems[Any](x, y, TupleColl(x, y, (x, y))), STuple(tpe, tpe, STuple(tpe, tpe, STuple(tpe, tpe)))) + roundtrip[SType]((x, y).asWrappedType, STuple(tpe, tpe), withVersion) + roundtrip[SType](TupleColl(x, y, x).asWrappedType, STuple(tpe, tpe, tpe), withVersion) + roundtrip[SType](TupleColl(x, y, x, y).asWrappedType, STuple(tpe, tpe, tpe, tpe), withVersion) + roundtrip[STuple](Colls.fromItems[Any](x, y, (x, y)), STuple(tpe, tpe, STuple(tpe, tpe)), withVersion) + roundtrip[STuple](Colls.fromItems[Any](x, y, TupleColl(x, y, x)), STuple(tpe, tpe, STuple(tpe, tpe, tpe)), withVersion) + roundtrip[STuple](Colls.fromItems[Any](x, y, TupleColl(x, y, (x, y))), STuple(tpe, tpe, STuple(tpe, tpe, STuple(tpe, tpe))), withVersion) } } @@ -185,4 +198,28 @@ class DataSerializerSpecification extends SerializationSpecification { }) } + property("header vector") { + val header = CHeader( + 0.toByte, + Helpers.decodeBytes("7a7fe5347f09017818010062000001807f86808000ff7f66ffb07f7ad27f3362"), + Helpers.decodeBytes("c1d70ad9b1ffc1fb9a715fff19807f2401017fcd8b73db017f1cff77727fff08"), + Helpers.decodeBytes("54d23dd080006bdb56800100356080935a80ffb77e90b800057f00661601807f17"), + Helpers.decodeBytes("5e7f1164ccd0990080c501fc0e0181cb387fc17f00ff00c7d5ff767f91ff5e68"), + -7421721754642387858L, + -4826493284887861030L, + 10, + Helpers.decodeBytes("e580c88001ff6fc89c5501017f80e001ff0101fe48c153ff7f00666b80d780ab"), + Helpers.decodeGroupElement("03e7f2875298fddd933c2e0a38968fe85bdeeb70dd8b389559a1d36e2ff1b58fc5"), + Helpers.decodeGroupElement("034e2d3b5f9e409e3ae8a2e768340760362ca33764eda5855f7a43487f14883300"), + Helpers.decodeBytes("974651c9efff7f00"), + CBigInt(new BigInteger("478e827dfa1e4b57", 16)), + Helpers.decodeBytes("01ff13"), + Colls.emptyColl + ) + + VersionContext.withVersions(VersionContext.V6SoftForkVersion, 1) { + roundtrip[SHeader.type](header, SHeader) + } + } + } diff --git a/interpreter/shared/src/test/scala/sigma/serialization/SerializationSpecification.scala b/interpreter/shared/src/test/scala/sigma/serialization/SerializationSpecification.scala index 36c75f3224..dc8eef7319 100644 --- a/interpreter/shared/src/test/scala/sigma/serialization/SerializationSpecification.scala +++ b/interpreter/shared/src/test/scala/sigma/serialization/SerializationSpecification.scala @@ -8,6 +8,7 @@ import org.scalacheck.Arbitrary._ import org.scalatest.matchers.should.Matchers import org.scalatest.propspec.AnyPropSpec import org.scalatestplus.scalacheck.{ScalaCheckDrivenPropertyChecks, ScalaCheckPropertyChecks} +import sigma.VersionContext import sigma.ast.SType import sigma.ast._ import sigmastate.helpers.NegativeTesting @@ -26,10 +27,20 @@ trait SerializationSpecification extends AnyPropSpec with ValidationSpecification with NegativeTesting { - protected def roundTripTest[V <: Value[_ <: SType]](v: V): Assertion = { - val bytes = ValueSerializer.serialize(v) - predefinedBytesTest(v, bytes) - predefinedBytesTestNotFomZeroElement(bytes, v) + protected def roundTripTest[V <: Value[_ <: SType]](v: V, withVersion: Option[Byte] = None): Assertion = { + def test() = { + val bytes = ValueSerializer.serialize(v) + predefinedBytesTest(v, bytes) + predefinedBytesTestNotFomZeroElement(bytes, v) + } + withVersion match { + case Some(ver) => + VersionContext.withVersions(ver, 1) { + test() + } + case None => + test() + } } protected def predefinedBytesTest[V <: Value[_ <: SType]](v: V, bytes: Array[Byte]): Assertion = { 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 f48e1ffc96..bd77766830 100644 --- a/interpreter/shared/src/test/scala/sigma/serialization/generators/ObjectGenerators.scala +++ b/interpreter/shared/src/test/scala/sigma/serialization/generators/ObjectGenerators.scala @@ -311,6 +311,7 @@ trait ObjectGenerators extends TypeGenerators case SAvlTree => arbAvlTree case SAny => arbAnyVal case SUnit => arbUnit + case SHeader => arbHeader case opt: SOption[a] => Arbitrary(frequency((5, None), (5, for (x <- wrappedTypeGen(opt.elemType)) yield Some(x)))) }).asInstanceOf[Arbitrary[T#WrappedType]].arbitrary @@ -707,8 +708,9 @@ trait ObjectGenerators extends TypeGenerators powDistance <- arbBigInt.arbitrary votes <- minerVotesGen unparsedBytes <- collOfRange(0, 32, arbByte.arbitrary) - } yield CHeader(version, parentId, adProofsRoot, stateRoot, transactionRoot, timestamp, nBits, - height, extensionRoot, minerPk.toGroupElement, powOnetimePk.toGroupElement, powNonce, powDistance, votes, unparsedBytes) + } yield CHeader(version, parentId, adProofsRoot, stateRoot.digest, transactionRoot, timestamp, nBits, + height, extensionRoot, minerPk.toGroupElement, powOnetimePk.toGroupElement, powNonce, powDistance, votes, + if(version > HeaderVersion.Interpreter60Version){ unparsedBytes } else {Colls.emptyColl[Byte]}) lazy val headerGen: Gen[Header] = for { stateRoot <- avlTreeGen 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 81073c4849..70a215e831 100644 --- a/interpreter/shared/src/test/scala/sigma/serialization/generators/TypeGenerators.scala +++ b/interpreter/shared/src/test/scala/sigma/serialization/generators/TypeGenerators.scala @@ -16,12 +16,13 @@ trait TypeGenerators { implicit val boxTypeGen: Gen[SBox.type] = Gen.const(SBox) implicit val avlTreeTypeGen: Gen[SAvlTree.type] = Gen.const(SAvlTree) implicit val optionSigmaPropTypeGen: Gen[SOption[SSigmaProp.type]] = Gen.const(SOption(SSigmaProp)) + implicit val headerTypeGen: Gen[SHeader.type] = Gen.const(SHeader) implicit val primTypeGen: Gen[SPrimType] = Gen.oneOf[SPrimType](SBoolean, SByte, SShort, SInt, SLong, SBigInt, SGroupElement, SSigmaProp, SUnit) implicit val arbPrimType: Arbitrary[SPrimType] = Arbitrary(primTypeGen) implicit val predefTypeGen: Gen[SPredefType] = - Gen.oneOf[SPredefType](SBoolean, SByte, SShort, SInt, SLong, SBigInt, SGroupElement, SSigmaProp, SUnit, SBox, SAvlTree) + Gen.oneOf[SPredefType](SBoolean, SByte, SShort, SInt, SLong, SBigInt, SGroupElement, SSigmaProp, SUnit, SBox, SAvlTree, SHeader) implicit val arbPredefType: Arbitrary[SPredefType] = Arbitrary(predefTypeGen) implicit def genToArbitrary[T: Gen]: Arbitrary[T] = Arbitrary(implicitly[Gen[T]]) diff --git a/interpreter/shared/src/test/scala/special/sigma/SigmaTestingData.scala b/interpreter/shared/src/test/scala/special/sigma/SigmaTestingData.scala index 63fc202516..b8bf76cacf 100644 --- a/interpreter/shared/src/test/scala/special/sigma/SigmaTestingData.scala +++ b/interpreter/shared/src/test/scala/special/sigma/SigmaTestingData.scala @@ -240,16 +240,16 @@ trait SigmaTestingData extends TestingCommons with ObjectGenerators { def createAvlTreeData() = AvlTreeData( ErgoAlgos.decodeUnsafe("010180017f7f7b7f720c00007f7f7f0f01e857a626f37f1483d06af8077a008080").toColl, - AvlTreeFlags(false, true, false), - 728138553, - Some(2147483647) + AvlTreeFlags(true, true, true), + 32, + None ) val h1_instances = new CloneSet(1000, CHeader( 0.toByte, Helpers.decodeBytes("0180dd805b0000ff5400b997fd7f0b9b00de00fb03c47e37806a8186b94f07ff"), Helpers.decodeBytes("01f07f60d100ffb970c3007f60ff7f24d4070bb8fffa7fca7f34c10001ffe39d"), - CAvlTree(createAvlTreeData()), + CAvlTree(createAvlTreeData()).digest, Helpers.decodeBytes("804101ff01000080a3ffbd006ac080098df132a7017f00649311ec0e00000100"), 1L, -1L, diff --git a/sc/shared/src/test/scala/sigma/SigmaDslSpecification.scala b/sc/shared/src/test/scala/sigma/SigmaDslSpecification.scala index fddace6a5c..c4d1db777d 100644 --- a/sc/shared/src/test/scala/sigma/SigmaDslSpecification.scala +++ b/sc/shared/src/test/scala/sigma/SigmaDslSpecification.scala @@ -41,11 +41,11 @@ import scala.util.{Failure, Success} /** This suite tests every method of every SigmaDsl type to be equivalent to * the evaluation of the corresponding ErgoScript operation. * - * The properties of this suite excercise two interpreters: the current (aka `old` + * The properties of this suite exercise two interpreters: the current (aka `old` * interpreter) and the new interpreter for a next soft-fork. After the soft-fork is * released, the new interpreter becomes current at which point the `old` and `new` * interpreters in this suite should be equivalent. This change is reflected in this - * suite by commiting changes in expected values. + * suite by committing changes in expected values. * The `old` and `new` interpreters are compared like the following: * 1) for existingFeature the interpreters should be equivalent * 2) for changedFeature the test cases contain different expected values @@ -53,7 +53,7 @@ import scala.util.{Failure, Success} * against expected values. * * This suite can be used for Cost profiling, i.e. measurements of operations times and - * comparing them with cost parameteres of the operations. + * comparing them with cost parameters of the operations. * * The following settings should be specified for profiling: * isMeasureOperationTime = true @@ -4516,7 +4516,7 @@ class SigmaDslSpecification extends SigmaDslTesting property("Header properties equivalence") { verifyCases( Seq((h1, Expected(Success( - Helpers.decodeBytes("957f008001808080ffe4ffffc8f3802401df40006aa05e017fa8d3f6004c804a")), + Helpers.decodeBytes("cea31f0e0a794b103f65f8296a22ac8ff214e1bc75442186b90df4844c978e81")), cost = 1766, methodCostDetails(SHeaderMethods.idMethod, 10), 1766))), existingPropTest("id", { (x: Header) => x.id })) @@ -4657,14 +4657,7 @@ class SigmaDslSpecification extends SigmaDslTesting 0.toByte, Helpers.decodeBytes("7a7fe5347f09017818010062000001807f86808000ff7f66ffb07f7ad27f3362"), Helpers.decodeBytes("c1d70ad9b1ffc1fb9a715fff19807f2401017fcd8b73db017f1cff77727fff08"), - CAvlTree( - AvlTreeData( - ErgoAlgos.decodeUnsafe("54d23dd080006bdb56800100356080935a80ffb77e90b800057f00661601807f17").toColl, - AvlTreeFlags(true, true, false), - 2147483647, - None - ) - ), + Helpers.decodeBytes("54d23dd080006bdb56800100356080935a80ffb77e90b800057f00661601807f17"), Helpers.decodeBytes("5e7f1164ccd0990080c501fc0e0181cb387fc17f00ff00c7d5ff767f91ff5e68"), -7421721754642387858L, -4826493284887861030L, @@ -4683,7 +4676,7 @@ class SigmaDslSpecification extends SigmaDslTesting headers = Coll[Header](header), preHeader = CPreHeader( 0.toByte, - Helpers.decodeBytes("1c597f88969600d2fffffdc47f00d8ffc555a9e85001000001c505ff80ff8f7f"), + header.id, -755484979487531112L, 9223372036854775807L, 11, diff --git a/sc/shared/src/test/scala/sigmastate/TestingInterpreterSpecification.scala b/sc/shared/src/test/scala/sigmastate/TestingInterpreterSpecification.scala index 4948f70c23..cc98bc79c3 100644 --- a/sc/shared/src/test/scala/sigmastate/TestingInterpreterSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/TestingInterpreterSpecification.scala @@ -429,32 +429,6 @@ class TestingInterpreterSpecification extends CompilerTestingCommons testEval(s"""deserialize[Coll[Byte]]("$str")(0) == 2""") } - property("header.id") { - testEval( - """ { - | val h = CONTEXT.headers(0) - | val id = h.id - | id.size == 32 - | }""".stripMargin) - } - - property("checkPow") { - - //todo: check invalid header - - val source = """ { - | val h = CONTEXT.headers(0) - | h.checkPow - | } - | """.stripMargin - - if (activatedVersionInTests < V6SoftForkVersion) { - an [sigmastate.exceptions.MethodNotFound] should be thrownBy testEval(source) - } else { - testEval(source) - } - } - override protected def afterAll(): Unit = { } diff --git a/sdk/js/src/main/scala/org/ergoplatform/sdk/js/Isos.scala b/sdk/js/src/main/scala/org/ergoplatform/sdk/js/Isos.scala index 66df205e85..84f2b21da8 100644 --- a/sdk/js/src/main/scala/org/ergoplatform/sdk/js/Isos.scala +++ b/sdk/js/src/main/scala/org/ergoplatform/sdk/js/Isos.scala @@ -31,7 +31,7 @@ object Isos { version = a.version, parentId = isoStringToColl.to(a.parentId), ADProofsRoot = isoStringToColl.to(a.ADProofsRoot), - stateRoot = AvlTree.isoAvlTree.to(a.stateRoot), + stateRootDigest = AvlTree.isoAvlTree.to(a.stateRoot).digest, transactionsRoot = isoStringToColl.to(a.transactionsRoot), timestamp = sigma.js.Isos.isoBigIntToLong.to(a.timestamp), nBits = sigma.js.Isos.isoBigIntToLong.to(a.nBits), diff --git a/sdk/shared/src/main/scala/org/ergoplatform/sdk/JsonCodecs.scala b/sdk/shared/src/main/scala/org/ergoplatform/sdk/JsonCodecs.scala index 0b6aa5555f..1c7a4156f4 100644 --- a/sdk/shared/src/main/scala/org/ergoplatform/sdk/JsonCodecs.scala +++ b/sdk/shared/src/main/scala/org/ergoplatform/sdk/JsonCodecs.scala @@ -147,7 +147,7 @@ trait JsonCodecs { powDistance <- cursor.downField("powDistance").as[sigma.BigInt] votes <- cursor.downField("votes").as[Coll[Byte]] unparsedBytes <- cursor.downField("unparsedBytes").as[Option[Coll[Byte]]] - } yield CHeader(version, parentId, adProofsRoot, stateRoot, transactionsRoot, timestamp, nBits, + } yield CHeader(version, parentId, adProofsRoot, stateRoot.digest, transactionsRoot, timestamp, nBits, height, extensionRoot, SigmaDsl.decodePoint(minerPk), SigmaDsl.decodePoint(powOnetimePk), powNonce, powDistance, votes, unparsedBytes.getOrElse(Colls.emptyColl)) }) From 07945e9a19ec1dc6a57809730fc817f15dd4612f Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Wed, 5 Jun 2024 18:56:40 +0300 Subject: [PATCH 122/314] fixing DataJsonEncoder --- .../scala/sigmastate/TypesSpecification.scala | 2 - .../ergoplatform/sdk/DataJsonEncoder.scala | 8 ++ .../sdk/DataJsonEncoderSpecification.scala | 92 ++++++++++++++----- 3 files changed, 77 insertions(+), 25 deletions(-) diff --git a/sc/shared/src/test/scala/sigmastate/TypesSpecification.scala b/sc/shared/src/test/scala/sigmastate/TypesSpecification.scala index 9a4c5ce1b8..6d13863f26 100644 --- a/sc/shared/src/test/scala/sigmastate/TypesSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/TypesSpecification.scala @@ -13,8 +13,6 @@ class TypesSpecification extends SigmaTestingData { implicit val tWrapped = wrappedTypeGen(t) forAll { x: SPredefType#WrappedType => isValueOfType(x, t) shouldBe true - // since forall t. SHeader != t - isValueOfType(x, SHeader) shouldBe false } } } diff --git a/sdk/shared/src/main/scala/org/ergoplatform/sdk/DataJsonEncoder.scala b/sdk/shared/src/main/scala/org/ergoplatform/sdk/DataJsonEncoder.scala index fc95b77e61..6c0c866baf 100644 --- a/sdk/shared/src/main/scala/org/ergoplatform/sdk/DataJsonEncoder.scala +++ b/sdk/shared/src/main/scala/org/ergoplatform/sdk/DataJsonEncoder.scala @@ -122,6 +122,10 @@ object DataJsonEncoder { val w = SigmaSerializer.startWriter() DataSerializer.serialize(v, tpe, w) encodeBytes(w.toBytes) + case SHeader => + val w = SigmaSerializer.startWriter() + DataSerializer.serialize(v, tpe, w) + encodeBytes(w.toBytes) case SAvlTree => val w = SigmaSerializer.startWriter() DataSerializer.serialize(v, tpe, w) @@ -203,6 +207,10 @@ object DataJsonEncoder { val str = decodeBytes(json) val r = SigmaSerializer.startReader(str) DataSerializer.deserialize(SSigmaProp, r) + case SHeader => // for Sigma < 6.0 , exception will be thrown by DataSerializer + val str = decodeBytes(json) + val r = SigmaSerializer.startReader(str) + DataSerializer.deserialize(SHeader, r) case SBox => val value = decodeData(json.hcursor.downField(s"value").focus.get, SLong) val tree = ErgoTreeSerializer.DefaultSerializer.deserializeErgoTree(decodeBytes(json.hcursor.downField(s"ergoTree").focus.get)) 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 c3f7b43af4..33e9546000 100644 --- a/sdk/shared/src/test/scala/org/ergoplatform/sdk/DataJsonEncoderSpecification.scala +++ b/sdk/shared/src/test/scala/org/ergoplatform/sdk/DataJsonEncoderSpecification.scala @@ -13,7 +13,7 @@ import sigma.serialization.SerializerException import sigma.util.Extensions.{BigIntegerOps, EcpOps, SigmaBooleanOps} import sigma.Extensions.ArrayOps import sigma.eval.SigmaDsl -import sigma.{AvlTree, Box, Colls, Evaluation} +import sigma.{AvlTree, Box, Colls, Evaluation, Header, VersionContext} import sigma.serialization.SerializationSpecification import scala.annotation.nowarn @@ -22,29 +22,48 @@ import scala.reflect.ClassTag class DataJsonEncoderSpecification extends SerializationSpecification { object JsonCodecs extends JsonCodecs - def roundtrip[T <: SType](obj: T#WrappedType, tpe: T) = { - val json = DataJsonEncoder.encode(obj, tpe) - val res = DataJsonEncoder.decode(json) - res shouldBe obj + def roundtrip[T <: SType](obj: T#WrappedType, tpe: T, withVersion: Option[Byte] = None) = { + def test() = { + val json = DataJsonEncoder.encode(obj, tpe) + val res = DataJsonEncoder.decode(json) + res shouldBe obj + } + + withVersion match { + case Some(ver) => + VersionContext.withVersions(ver, 1) { + test() + } + case None => + test() + } } def testCollection[T <: SType](tpe: T) = { implicit val wWrapped = wrappedTypeGen(tpe) implicit val tT = Evaluation.stypeToRType(tpe) implicit val tagT = tT.classTag + + val withVersion = if (tpe == SHeader) { + Some(VersionContext.V6SoftForkVersion) + } else { + None + } + forAll { xs: Array[T#WrappedType] => - roundtrip[SCollection[T]](xs.toColl, SCollection(tpe)) - roundtrip[SType](xs.toColl.map(x => (x, x)).asWrappedType, SCollection(STuple(tpe, tpe))) + roundtrip[SCollection[T]](xs.toColl, SCollection(tpe), withVersion) + roundtrip[SType](xs.toColl.map(x => (x, x)).asWrappedType, SCollection(STuple(tpe, tpe)), withVersion) val nested = xs.toColl.map(x => Colls.fromItems[T#WrappedType](x, x)) - roundtrip[SCollection[SCollection[T]]](nested, SCollection(SCollection(tpe))) + roundtrip[SCollection[SCollection[T]]](nested, SCollection(SCollection(tpe)), withVersion) roundtrip[SType]( xs.toColl.map { x => val arr = Colls.fromItems[T#WrappedType](x, x) (arr, arr) }.asWrappedType, - SCollection(STuple(SCollection(tpe), SCollection(tpe))) + SCollection(STuple(SCollection(tpe), SCollection(tpe))), + withVersion ) } } @@ -54,11 +73,18 @@ class DataJsonEncoderSpecification extends SerializationSpecification { val tT = Evaluation.stypeToRType(tpe) @nowarn implicit val tag : ClassTag[T#WrappedType] = tT.classTag @nowarn implicit val tAny : RType[Any] = sigma.AnyType + + val withVersion = if (tpe == SHeader) { + Some(VersionContext.V6SoftForkVersion) + } else { + None + } + forAll { in: (T#WrappedType, T#WrappedType) => val (x,y) = (in._1, in._2) - roundtrip[SType]((x, y).asWrappedType, STuple(tpe, tpe)) - roundtrip[SType](((x, y), (x, y)).asWrappedType, STuple(STuple(tpe, tpe), STuple(tpe, tpe))) - roundtrip[SType](((x, y), ((x, y), (x, y))).asWrappedType, STuple(STuple(tpe, tpe), STuple(STuple(tpe, tpe), STuple(tpe, tpe)))) + roundtrip[SType]((x, y).asWrappedType, STuple(tpe, tpe), withVersion) + roundtrip[SType](((x, y), (x, y)).asWrappedType, STuple(STuple(tpe, tpe), STuple(tpe, tpe)), withVersion) + roundtrip[SType](((x, y), ((x, y), (x, y))).asWrappedType, STuple(STuple(tpe, tpe), STuple(STuple(tpe, tpe), STuple(tpe, tpe))), withVersion) } } @@ -98,6 +124,7 @@ class DataJsonEncoderSpecification extends SerializationSpecification { forAll { x: AvlTree => roundtrip[SAvlTree.type](x, SAvlTree) } forAll { x: Array[Byte] => roundtrip[SByteArray](x.toColl, SByteArray) } forAll { x: Box => roundtrip[SBox.type](x, SBox) } + forAll { x: Header => roundtrip[SHeader.type](x, SHeader, Some(VersionContext.V6SoftForkVersion)) } forAll { x: Option[Byte] => roundtrip[SOption[SByte.type]](x, SOption[SByte.type]) } testCollection(SOption[SLong.type]) testTuples(SOption[SLong.type]) @@ -187,25 +214,44 @@ class DataJsonEncoderSpecification extends SerializationSpecification { val tT = Evaluation.stypeToRType(tpe) @nowarn implicit val tag = tT.classTag @nowarn implicit val tAny = sigma.AnyType - forAll { x: T#WrappedType => - an[SerializerException] should be thrownBy { - DataJsonEncoder.encode(TupleColl(x, x, x).asWrappedType, STuple(tpe, tpe, tpe)) - } - // supported case - DataJsonEncoder.encode(SigmaDsl.Colls.fromItems(TupleColl(x, x)).asWrappedType, SCollection(STuple(tpe, tpe))) - // not supported case - an[SerializerException] should be thrownBy { - DataJsonEncoder.encode(SigmaDsl.Colls.fromItems(TupleColl(x, x, x)).asWrappedType, SCollection(STuple(tpe, tpe, tpe))) + def test() = { + forAll { x: T#WrappedType => + an[SerializerException] should be thrownBy { + DataJsonEncoder.encode(TupleColl(x, x, x).asWrappedType, STuple(tpe, tpe, tpe)) + } + + // supported case + DataJsonEncoder.encode(SigmaDsl.Colls.fromItems(TupleColl(x, x)).asWrappedType, SCollection(STuple(tpe, tpe))) + + // not supported case + an[SerializerException] should be thrownBy { + DataJsonEncoder.encode(SigmaDsl.Colls.fromItems(TupleColl(x, x, x)).asWrappedType, SCollection(STuple(tpe, tpe, tpe))) + } } } + + if (tpe == SHeader) { + VersionContext.withVersions(VersionContext.V6SoftForkVersion, 1) { + test() + } + } else { + test() + } } property("AnyValue") { forAll { t: SPredefType => - testAnyValue(t) - testAnyValue(SOption(t)) + if (t == SHeader) { + VersionContext.withVersions(VersionContext.V6SoftForkVersion, 1) { + testAnyValue(t) + testAnyValue(SOption(t)) + } + } else { + testAnyValue(t) + testAnyValue(SOption(t)) + } } } From 15de2e2d7004e00b2e6de4e79ee7fac9b057d9b7 Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Wed, 5 Jun 2024 19:31:56 +0300 Subject: [PATCH 123/314] merging i969 --- .../shared/src/main/scala/sigma/data}/CHeader.scala | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) rename {interpreter/shared/src/main/scala/sigmastate/eval => data/shared/src/main/scala/sigma/data}/CHeader.scala (96%) diff --git a/interpreter/shared/src/main/scala/sigmastate/eval/CHeader.scala b/data/shared/src/main/scala/sigma/data/CHeader.scala similarity index 96% rename from interpreter/shared/src/main/scala/sigmastate/eval/CHeader.scala rename to data/shared/src/main/scala/sigma/data/CHeader.scala index 3bd0dd62f9..46f6f9b7b5 100644 --- a/interpreter/shared/src/main/scala/sigmastate/eval/CHeader.scala +++ b/data/shared/src/main/scala/sigma/data/CHeader.scala @@ -1,10 +1,9 @@ -package sigmastate.eval +package sigma.data import org.ergoplatform.{HeaderWithoutPow, HeaderWithoutPowSerializer} import scorex.crypto.authds.ADDigest import scorex.crypto.hash.Digest32 import scorex.util.bytesToId -import sigma.data.SigmaConstants import sigma.pow.Autolykos2PowValidation import sigma.{AvlTree, BigInt, Coll, Colls, GroupElement, Header} From 17f5eb6fdd3aa706e51fb6c31c59b2af0994beea Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Wed, 5 Jun 2024 19:36:19 +0300 Subject: [PATCH 124/314] CHeader from i969 --- .../src/main/scala/sigma/data/CHeader.scala | 135 +++++++++++++++--- .../sigma/serialization/DataSerializer.scala | 14 +- .../ConstantSerializerSpecification.scala | 41 ++++-- .../DataSerializerSpecification.scala | 135 +++++++++++++----- .../SerializationSpecification.scala | 21 ++- .../generators/ObjectGenerators.scala | 7 +- .../generators/TypeGenerators.scala | 3 +- .../special/sigma/SigmaTestingData.scala | 13 +- .../scala/sigma/SigmaDslSpecification.scala | 20 +-- .../scala/sigmastate/TypesSpecification.scala | 2 - .../scala/org/ergoplatform/sdk/js/Isos.scala | 6 +- .../ergoplatform/sdk/DataJsonEncoder.scala | 8 ++ .../org/ergoplatform/sdk/JsonCodecs.scala | 5 +- .../sdk/DataJsonEncoderSpecification.scala | 92 +++++++++--- 14 files changed, 368 insertions(+), 134 deletions(-) diff --git a/data/shared/src/main/scala/sigma/data/CHeader.scala b/data/shared/src/main/scala/sigma/data/CHeader.scala index 46f6f9b7b5..4e1cec2413 100644 --- a/data/shared/src/main/scala/sigma/data/CHeader.scala +++ b/data/shared/src/main/scala/sigma/data/CHeader.scala @@ -1,9 +1,9 @@ package sigma.data -import org.ergoplatform.{HeaderWithoutPow, HeaderWithoutPowSerializer} +import org.ergoplatform.{AutolykosSolution, ErgoHeader, HeaderWithoutPow, HeaderWithoutPowSerializer} import scorex.crypto.authds.ADDigest import scorex.crypto.hash.Digest32 -import scorex.util.bytesToId +import scorex.util.{bytesToId, idToBytes} import sigma.pow.Autolykos2PowValidation import sigma.{AvlTree, BigInt, Coll, Colls, GroupElement, Header} @@ -11,24 +11,60 @@ import sigma.{AvlTree, BigInt, Coll, Colls, GroupElement, Header} * * @see [[Header]] for detailed descriptions */ -case class CHeader( - id: Coll[Byte], - version: Byte, - parentId: Coll[Byte], - ADProofsRoot: Coll[Byte], - stateRoot: AvlTree, - transactionsRoot: Coll[Byte], - timestamp: Long, - nBits: Long, - height: Int, - extensionRoot: Coll[Byte], - minerPk: GroupElement, - powOnetimePk: GroupElement, - powNonce: Coll[Byte], - powDistance: BigInt, - votes: Coll[Byte], - unparsedBytes: Coll[Byte] -) extends Header { +class CHeader(val ergoHeader: ErgoHeader) extends Header with WrapperOf[ErgoHeader] { + + /** Bytes representation of ModifierId of this Header */ + override lazy val id: Coll[Byte] = ergoHeader.id + + /** Block version, to be increased on every soft and hardfork. */ + override def version: Byte = ergoHeader.version + + /** Bytes representation of ModifierId of the parent block */ + override def parentId: Coll[Byte] = Colls.fromArray(idToBytes(ergoHeader.parentId)) + + /** Hash of ADProofs for transactions in a block */ + override def ADProofsRoot: Coll[Byte] = Colls.fromArray(ergoHeader.ADProofsRoot) + + /** AvlTree of a state after block application */ + override def stateRoot: AvlTree = CAvlTree(AvlTreeData.avlTreeFromDigest(Colls.fromArray(ergoHeader.stateRoot))) + + /** Root hash (for a Merkle tree) of transactions in a block. */ + override def transactionsRoot: Coll[Byte] = Colls.fromArray(ergoHeader.transactionsRoot) + + /** Block timestamp (in milliseconds since beginning of Unix Epoch) */ + override def timestamp: Long = ergoHeader.timestamp + + /** Current difficulty in a compressed view. + * NOTE: actually it is unsigned Int */ + override def nBits: Long = ergoHeader.nBits + + /** Block height */ + override def height: Int = ergoHeader.height + + /** Root hash of extension section */ + override def extensionRoot: Coll[Byte] = Colls.fromArray(ergoHeader.extensionRoot) + + /** Miner public key. Should be used to collect block rewards. + * Part of Autolykos solution. */ + override def minerPk: GroupElement = CGroupElement(ergoHeader.powSolution.pk) + + /** One-time public key. Prevents revealing of miners secret. */ + override def powOnetimePk: GroupElement = CGroupElement(ergoHeader.powSolution.w) + + /** nonce */ + override def powNonce: Coll[Byte] = Colls.fromArray(ergoHeader.powSolution.n) + + /** Distance between pseudo-random number, corresponding to nonce `powNonce` and a secret, + * corresponding to `minerPk`. The lower `powDistance` is, the harder it was to find this solution. */ + override def powDistance: BigInt = CBigInt(ergoHeader.powSolution.d.bigInteger) + + /** Miner votes for changing system parameters. */ + override def votes: Coll[Byte] = Colls.fromArray(ergoHeader.votes) + + override def unparsedBytes: Coll[Byte] = Colls.fromArray(ergoHeader.unparsedBytes) + + /** The data value wrapped by this wrapper. */ + override def wrappedValue: ErgoHeader = ergoHeader override def serializeWithoutPoW: Coll[Byte] = { val headerWithoutPow = HeaderWithoutPow(version, bytesToId(parentId.toArray), Digest32 @@ ADProofsRoot.toArray, @@ -41,12 +77,69 @@ case class CHeader( Autolykos2PowValidation.checkPoWForVersion2(this) } + override def toString: String = + s"""CHeader( + | id: ${id}, + | version: ${version}, + | tx proofs hash: ${ADProofsRoot}, + | state root: ${stateRoot.digest}, + | transactions root: ${transactionsRoot}, + | time: $timestamp, + | nbits: $nBits, + | extension root: $extensionRoot, + | miner pubkey: $minerPk, + | pow one time pubkey(from AL 1): $powOnetimePk, + | pow nonce: $powNonce, + | pow distance (from AL 1): $powDistance, + | votes: $votes, + | unparsed bytes: $unparsedBytes + |)""".stripMargin + + override def hashCode(): Int = id.hashCode() + + override def equals(other: Any): Boolean = other match { + case ch: CHeader => ch.id == this.id + case _ => false + } + + def copy(): CHeader = new CHeader(ergoHeader.copy()) // used in tests only } object CHeader { + + def apply( version: Byte, + parentId: Coll[Byte], + ADProofsRoot: Coll[Byte], + stateRootDigest: Coll[Byte], + transactionsRoot: Coll[Byte], + timestamp: Long, + nBits: Long, + height: Int, + extensionRoot: Coll[Byte], + minerPk: GroupElement, + powOnetimePk: GroupElement, + powNonce: Coll[Byte], + powDistance: BigInt, + votes: Coll[Byte], + unparsedBytes: Coll[Byte]): CHeader = { + + val solution = AutolykosSolution( + minerPk.asInstanceOf[CGroupElement].wrappedValue, + powOnetimePk.asInstanceOf[CGroupElement].wrappedValue, + powNonce.toArray, + powDistance.asInstanceOf[CBigInt].wrappedValue) + + val h = ErgoHeader(version, bytesToId(parentId.toArray), Digest32 @@ ADProofsRoot.toArray, + ADDigest @@ stateRootDigest.toArray, Digest32 @@ transactionsRoot.toArray, timestamp, nBits, height, + Digest32 @@ extensionRoot.toArray, solution, votes.toArray, unparsedBytes.toArray, null) + + new CHeader(h) + } + /** Size of of Header.votes array. */ val VotesSize: Int = SigmaConstants.VotesArraySize.value /** Size of nonce array from Autolykos POW solution in Header.powNonce array. */ val NonceSize: Int = SigmaConstants.AutolykosPowSolutionNonceArraySize.value -} \ No newline at end of file + +} diff --git a/data/shared/src/main/scala/sigma/serialization/DataSerializer.scala b/data/shared/src/main/scala/sigma/serialization/DataSerializer.scala index 5f554e96a1..92a54f9aa4 100644 --- a/data/shared/src/main/scala/sigma/serialization/DataSerializer.scala +++ b/data/shared/src/main/scala/sigma/serialization/DataSerializer.scala @@ -1,8 +1,9 @@ package sigma.serialization -import org.ergoplatform.ErgoBox +import org.ergoplatform.{ErgoBox, ErgoHeader} +import sigma.VersionContext import sigma.ast._ -import sigma.data.CBox +import sigma.data.{CBox, CHeader} /** This works in tandem with ConstantSerializer, if you change one make sure to check the other.*/ object DataSerializer extends CoreDataSerializer { @@ -15,6 +16,9 @@ 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 => + val h = v.asInstanceOf[CHeader] + ErgoHeader.sigmaSerializer.serialize(h.ergoHeader, w.asInstanceOf[SigmaByteWriter]) case _ => super.serialize(v, tpe, w) } @@ -32,6 +36,12 @@ 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 => + val depth = r.level + r.level = depth + 1 + val res = new CHeader(ErgoHeader.sigmaSerializer.parse(r.asInstanceOf[SigmaByteReader])) + r.level = r.level - 1 + res case t => super.deserialize(t, r) }).asInstanceOf[T#WrappedType] diff --git a/interpreter/shared/src/test/scala/sigma/serialization/ConstantSerializerSpecification.scala b/interpreter/shared/src/test/scala/sigma/serialization/ConstantSerializerSpecification.scala index 43e9cf9e5d..c9478c8356 100644 --- a/interpreter/shared/src/test/scala/sigma/serialization/ConstantSerializerSpecification.scala +++ b/interpreter/shared/src/test/scala/sigma/serialization/ConstantSerializerSpecification.scala @@ -9,7 +9,7 @@ import sigma.ast.{BigIntConstant, ByteArrayConstant, Constant, DeserializationSi import sigmastate.eval._ import sigma.Extensions.ArrayOps import sigma.ast._ -import sigma.{AvlTree, Colls, Evaluation} +import sigma.{AvlTree, Colls, Evaluation, Header, VersionContext} import sigma.ast.SType.AnyOps import scorex.util.encode.Base16 import sigma.ast.BoolArrayConstant.BoolArrayTypeCode @@ -17,6 +17,7 @@ import sigma.ast.ByteArrayConstant.ByteArrayTypeCode import sigma.ast.syntax.{BoolValue, SValue} import sigma.crypto.EcPointType import sigma.util.Extensions.{BigIntegerOps, EcpOps, SigmaBooleanOps} + import scala.annotation.nowarn class ConstantSerializerSpecification extends TableSerializationSpecification { @@ -25,22 +26,29 @@ class ConstantSerializerSpecification extends TableSerializationSpecification { implicit val wWrapped = wrappedTypeGen(tpe) implicit val tT = Evaluation.stypeToRType(tpe) implicit val tag = tT.classTag + + val withVersion = if (tpe == SHeader) { + Some(VersionContext.V6SoftForkVersion) + } else { + None + } + forAll { xs: Array[T#WrappedType] => implicit val tAny = sigma.AnyType - roundTripTest(Constant[SCollection[T]](xs.toColl, SCollection(tpe))) - roundTripTest(Constant[SType](xs.toColl.map(x => (x, x)).asWrappedType, SCollection(STuple(tpe, tpe)))) // pairs are special case + roundTripTest(Constant[SCollection[T]](xs.toColl, SCollection(tpe)), withVersion) + roundTripTest(Constant[SType](xs.toColl.map(x => (x, x)).asWrappedType, SCollection(STuple(tpe, tpe))), withVersion) // pairs are special case val triples = xs.toColl.map(x => TupleColl(x, x, x)).asWrappedType - roundTripTest(Constant[SType](triples, SCollection(STuple(tpe, tpe, tpe)))) + roundTripTest(Constant[SType](triples, SCollection(STuple(tpe, tpe, tpe))), withVersion) val quartets = xs.toColl.map(x => TupleColl(x, x, x, x)).asWrappedType - roundTripTest(Constant[SType](quartets, SCollection(STuple(tpe, tpe, tpe, tpe)))) - roundTripTest(Constant[SCollection[SCollection[T]]](xs.toColl.map(x => Colls.fromItems(x, x)), SCollection(SCollection(tpe)))) + roundTripTest(Constant[SType](quartets, SCollection(STuple(tpe, tpe, tpe, tpe))), withVersion) + roundTripTest(Constant[SCollection[SCollection[T]]](xs.toColl.map(x => Colls.fromItems(x, x)), SCollection(SCollection(tpe))), withVersion) roundTripTest(Constant[SType]( xs.toColl.map { x => val arr = Colls.fromItems(x, x) (arr, arr) }.asWrappedType, SCollection(STuple(SCollection(tpe), SCollection(tpe))) - )) + ), withVersion) } } @@ -49,14 +57,19 @@ class ConstantSerializerSpecification extends TableSerializationSpecification { implicit val tT = Evaluation.stypeToRType(tpe) @nowarn implicit val tag = tT.classTag implicit val tAny: RType[Any] = sigma.AnyType + val withVersion = if (tpe == SHeader) { + Some(VersionContext.V6SoftForkVersion) + } else { + None + } forAll { in: (T#WrappedType, T#WrappedType) => val (x,y) = (in._1, in._2) - roundTripTest(Constant[SType]((x, y).asWrappedType, STuple(tpe, tpe))) - roundTripTest(Constant[SType](TupleColl(x, y, x).asWrappedType, STuple(tpe, tpe, tpe))) - roundTripTest(Constant[SType](TupleColl(x, y, x, y).asWrappedType, STuple(tpe, tpe, tpe, tpe))) - roundTripTest(Constant[STuple](Colls.fromItems[Any](x, y, (x, y)), STuple(tpe, tpe, STuple(tpe, tpe)))) - roundTripTest(Constant[STuple](Colls.fromItems[Any](x, y, TupleColl(x, y, x)), STuple(tpe, tpe, STuple(tpe, tpe, tpe)))) - roundTripTest(Constant[STuple](Colls.fromItems[Any](x, y, TupleColl(x, y, (x, y))), STuple(tpe, tpe, STuple(tpe, tpe, STuple(tpe, tpe))))) + roundTripTest(Constant[SType]((x, y).asWrappedType, STuple(tpe, tpe)), withVersion) + roundTripTest(Constant[SType](TupleColl(x, y, x).asWrappedType, STuple(tpe, tpe, tpe)), withVersion) + roundTripTest(Constant[SType](TupleColl(x, y, x, y).asWrappedType, STuple(tpe, tpe, tpe, tpe)), withVersion) + roundTripTest(Constant[STuple](Colls.fromItems[Any](x, y, (x, y)), STuple(tpe, tpe, STuple(tpe, tpe))), withVersion) + roundTripTest(Constant[STuple](Colls.fromItems[Any](x, y, TupleColl(x, y, x)), STuple(tpe, tpe, STuple(tpe, tpe, tpe))), withVersion) + roundTripTest(Constant[STuple](Colls.fromItems[Any](x, y, TupleColl(x, y, (x, y))), STuple(tpe, tpe, STuple(tpe, tpe, STuple(tpe, tpe)))), withVersion) } } @@ -71,6 +84,7 @@ class ConstantSerializerSpecification extends TableSerializationSpecification { forAll { x: SigmaBoolean => roundTripTest(Constant[SSigmaProp.type](x.toSigmaProp, SSigmaProp)) } forAll { x: ErgoBox => roundTripTest(Constant[SBox.type](x, SBox)) } forAll { x: AvlTree => roundTripTest(Constant[SAvlTree.type](x, SAvlTree)) } + forAll { x: Header => roundTripTest(Constant[SHeader.type](x, SHeader), Some(VersionContext.V6SoftForkVersion)) } forAll { x: Array[Byte] => roundTripTest(Constant[SByteArray](x.toColl, SByteArray)) } forAll { t: SPredefType => testCollection(t) } forAll { t: SPredefType => testTuples(t) } @@ -88,6 +102,7 @@ class ConstantSerializerSpecification extends TableSerializationSpecification { testCollection(SUnit) testCollection(SBox) testCollection(SAvlTree) + testCollection(SHeader) } private def caseObjectValue(v: SValue) = (v, Array[Byte](v.opCode)) diff --git a/interpreter/shared/src/test/scala/sigma/serialization/DataSerializerSpecification.scala b/interpreter/shared/src/test/scala/sigma/serialization/DataSerializerSpecification.scala index 2d9da3a87e..fe6f62dbe0 100644 --- a/interpreter/shared/src/test/scala/sigma/serialization/DataSerializerSpecification.scala +++ b/interpreter/shared/src/test/scala/sigma/serialization/DataSerializerSpecification.scala @@ -3,10 +3,10 @@ package sigma.serialization import java.math.BigInteger import org.ergoplatform.ErgoBox import org.scalacheck.Arbitrary._ -import sigma.data.{DataValueComparer, OptionType, RType, SigmaBoolean, TupleColl} +import sigma.data.{CBigInt, CHeader, DataValueComparer, OptionType, RType, SigmaBoolean, TupleColl} import sigma.ast.SCollection.SByteArray import sigmastate.eval._ -import sigma.{AvlTree, Colls, Evaluation, VersionContext} +import sigma.{AvlTree, Colls, Evaluation, Header, VersionContext} import sigma.ast.SType.AnyOps import sigma.ast._ import org.scalacheck.Gen @@ -23,29 +23,41 @@ import scala.reflect.ClassTag class DataSerializerSpecification extends SerializationSpecification { - def roundtrip[T <: SType](obj: T#WrappedType, tpe: T) = { - val w = SigmaSerializer.startWriter() - DataSerializer.serialize(obj, tpe, w) - val bytes = w.toBytes - val r = SigmaSerializer.startReader(bytes) - val res = DataSerializer.deserialize(tpe, r) - res shouldBe obj - - val es = CErgoTreeEvaluator.DefaultEvalSettings - val accumulator = new CostAccumulator( - initialCost = JitCost(0), - costLimit = Some(JitCost.fromBlockCost(es.scriptCostLimitInEvaluator))) - val evaluator = new CErgoTreeEvaluator( - context = null, - constants = ErgoTree.EmptyConstants, - coster = accumulator, DefaultProfiler, es) - val ok = DataValueComparer.equalDataValues(res, obj)(evaluator) - ok shouldBe true - - val randomPrefix = arrayGen[Byte].sample.get - val r2 = SigmaSerializer.startReader(randomPrefix ++ bytes, randomPrefix.length) - val res2 = DataSerializer.deserialize(tpe, r2) - res2 shouldBe obj + def roundtrip[T <: SType](obj: T#WrappedType, tpe: T, withVersion: Option[Byte] = None) = { + + def test() = { + val w = SigmaSerializer.startWriter() + DataSerializer.serialize(obj, tpe, w) + val bytes = w.toBytes + val r = SigmaSerializer.startReader(bytes) + val res = DataSerializer.deserialize(tpe, r) + res shouldBe obj + + val es = CErgoTreeEvaluator.DefaultEvalSettings + val accumulator = new CostAccumulator( + initialCost = JitCost(0), + costLimit = Some(JitCost.fromBlockCost(es.scriptCostLimitInEvaluator))) + val evaluator = new CErgoTreeEvaluator( + context = null, + constants = ErgoTree.EmptyConstants, + coster = accumulator, DefaultProfiler, es) + val ok = DataValueComparer.equalDataValues(res, obj)(evaluator) + ok shouldBe true + + val randomPrefix = arrayGen[Byte].sample.get + val r2 = SigmaSerializer.startReader(randomPrefix ++ bytes, randomPrefix.length) + val res2 = DataSerializer.deserialize(tpe, r2) + res2 shouldBe obj + } + + withVersion match { + case Some(ver) => + VersionContext.withVersions(ver, 1) { + test() + } + case None => + test() + } } def testCollection[T <: SType](tpe: T) = { @@ -53,25 +65,32 @@ class DataSerializerSpecification extends SerializationSpecification { implicit val tT = Evaluation.stypeToRType(tpe) implicit val tagT = tT.classTag implicit val tAny = sigma.AnyType + + val withVersion = if (tpe == SHeader) { + Some(VersionContext.V6SoftForkVersion) + } else { + None + } forAll { xs: Array[T#WrappedType] => - roundtrip[SCollection[T]](xs.toColl, SCollection(tpe)) - roundtrip[SType](xs.toColl.map(x => (x, x)).asWrappedType, SCollection(STuple(tpe, tpe))) + roundtrip[SCollection[T]](xs.toColl, SCollection(tpe), withVersion) + roundtrip[SType](xs.toColl.map(x => (x, x)).asWrappedType, SCollection(STuple(tpe, tpe)), withVersion) val triples = xs.toColl.map(x => TupleColl(x, x, x)).asWrappedType - roundtrip(triples, SCollection(STuple(tpe, tpe, tpe))) + roundtrip(triples, SCollection(STuple(tpe, tpe, tpe)), withVersion) val quartets = xs.toColl.map(x => TupleColl(x, x, x, x)).asWrappedType - roundtrip(quartets, SCollection(STuple(tpe, tpe, tpe, tpe))) + roundtrip(quartets, SCollection(STuple(tpe, tpe, tpe, tpe)), withVersion) val nested = xs.toColl.map(x => Colls.fromItems[T#WrappedType](x, x)) - roundtrip[SCollection[SCollection[T]]](nested, SCollection(SCollection(tpe))) + roundtrip[SCollection[SCollection[T]]](nested, SCollection(SCollection(tpe)), withVersion) roundtrip[SType]( xs.toColl.map { x => val arr = Colls.fromItems[T#WrappedType](x, x) (arr, arr) }.asWrappedType, - SCollection(STuple(SCollection(tpe), SCollection(tpe))) + SCollection(STuple(SCollection(tpe), SCollection(tpe))), + withVersion ) } } @@ -81,14 +100,19 @@ class DataSerializerSpecification extends SerializationSpecification { val tT = Evaluation.stypeToRType(tpe) @nowarn implicit val tag: ClassTag[T#WrappedType] = tT.classTag implicit val tAny : RType[Any] = sigma.AnyType + val withVersion = if (tpe == SHeader) { + Some(VersionContext.V6SoftForkVersion) + } else { + None + } forAll { in: (T#WrappedType, T#WrappedType) => val (x,y) = (in._1, in._2) - roundtrip[SType]((x, y).asWrappedType, STuple(tpe, tpe)) - roundtrip[SType](TupleColl(x, y, x).asWrappedType, STuple(tpe, tpe, tpe)) - roundtrip[SType](TupleColl(x, y, x, y).asWrappedType, STuple(tpe, tpe, tpe, tpe)) - roundtrip[STuple](Colls.fromItems[Any](x, y, (x, y)), STuple(tpe, tpe, STuple(tpe, tpe))) - roundtrip[STuple](Colls.fromItems[Any](x, y, TupleColl(x, y, x)), STuple(tpe, tpe, STuple(tpe, tpe, tpe))) - roundtrip[STuple](Colls.fromItems[Any](x, y, TupleColl(x, y, (x, y))), STuple(tpe, tpe, STuple(tpe, tpe, STuple(tpe, tpe)))) + roundtrip[SType]((x, y).asWrappedType, STuple(tpe, tpe), withVersion) + roundtrip[SType](TupleColl(x, y, x).asWrappedType, STuple(tpe, tpe, tpe), withVersion) + roundtrip[SType](TupleColl(x, y, x, y).asWrappedType, STuple(tpe, tpe, tpe, tpe), withVersion) + roundtrip[STuple](Colls.fromItems[Any](x, y, (x, y)), STuple(tpe, tpe, STuple(tpe, tpe)), withVersion) + roundtrip[STuple](Colls.fromItems[Any](x, y, TupleColl(x, y, x)), STuple(tpe, tpe, STuple(tpe, tpe, tpe)), withVersion) + roundtrip[STuple](Colls.fromItems[Any](x, y, TupleColl(x, y, (x, y))), STuple(tpe, tpe, STuple(tpe, tpe, STuple(tpe, tpe))), withVersion) } } @@ -129,6 +153,7 @@ class DataSerializerSpecification extends SerializationSpecification { forAll { x: ErgoBox => roundtrip[SBox.type](x, SBox) } forAll { x: AvlTree => roundtrip[SAvlTree.type](x, SAvlTree) } forAll { x: Array[Byte] => roundtrip[SByteArray](x.toColl, SByteArray) } + forAll { x: Header => roundtrip[SHeader.type](x, SHeader, Some(VersionContext.V6SoftForkVersion)) } forAll { t: SPredefType => testCollection(t) } forAll { t: SPredefType => testTuples(t) } forAll { t: SPredefType => testOption(t) } @@ -159,6 +184,42 @@ class DataSerializerSpecification extends SerializationSpecification { t.isInstanceOf[SerializerException] && t.getMessage.contains(s"BigInt value doesn't not fit into ${SBigInt.MaxSizeInBytes} bytes") }) + } + property("nuanced versioned test for header roundtrip") { + VersionContext.withVersions(VersionContext.V6SoftForkVersion, 1) { + forAll { x: Header => roundtrip[SHeader.type](x, SHeader) } + } + + an[SerializerException] should be thrownBy ( + VersionContext.withVersions((VersionContext.V6SoftForkVersion - 1).toByte, 1) { + val h = headerGen.sample.get + roundtrip[SHeader.type](h, SHeader) + }) + } + + property("header vector") { + val header = CHeader( + 0.toByte, + Helpers.decodeBytes("7a7fe5347f09017818010062000001807f86808000ff7f66ffb07f7ad27f3362"), + Helpers.decodeBytes("c1d70ad9b1ffc1fb9a715fff19807f2401017fcd8b73db017f1cff77727fff08"), + Helpers.decodeBytes("54d23dd080006bdb56800100356080935a80ffb77e90b800057f00661601807f17"), + Helpers.decodeBytes("5e7f1164ccd0990080c501fc0e0181cb387fc17f00ff00c7d5ff767f91ff5e68"), + -7421721754642387858L, + -4826493284887861030L, + 10, + Helpers.decodeBytes("e580c88001ff6fc89c5501017f80e001ff0101fe48c153ff7f00666b80d780ab"), + Helpers.decodeGroupElement("03e7f2875298fddd933c2e0a38968fe85bdeeb70dd8b389559a1d36e2ff1b58fc5"), + Helpers.decodeGroupElement("034e2d3b5f9e409e3ae8a2e768340760362ca33764eda5855f7a43487f14883300"), + Helpers.decodeBytes("974651c9efff7f00"), + CBigInt(new BigInteger("478e827dfa1e4b57", 16)), + Helpers.decodeBytes("01ff13"), + Colls.emptyColl + ) + + VersionContext.withVersions(VersionContext.V6SoftForkVersion, 1) { + roundtrip[SHeader.type](header, SHeader) + } } + } diff --git a/interpreter/shared/src/test/scala/sigma/serialization/SerializationSpecification.scala b/interpreter/shared/src/test/scala/sigma/serialization/SerializationSpecification.scala index 30ae6af19b..dc8eef7319 100644 --- a/interpreter/shared/src/test/scala/sigma/serialization/SerializationSpecification.scala +++ b/interpreter/shared/src/test/scala/sigma/serialization/SerializationSpecification.scala @@ -8,6 +8,7 @@ import org.scalacheck.Arbitrary._ import org.scalatest.matchers.should.Matchers import org.scalatest.propspec.AnyPropSpec import org.scalatestplus.scalacheck.{ScalaCheckDrivenPropertyChecks, ScalaCheckPropertyChecks} +import sigma.VersionContext import sigma.ast.SType import sigma.ast._ import sigmastate.helpers.NegativeTesting @@ -26,10 +27,20 @@ trait SerializationSpecification extends AnyPropSpec with ValidationSpecification with NegativeTesting { - protected def roundTripTest[V <: Value[_ <: SType]](v: V): Assertion = { - val bytes = ValueSerializer.serialize(v) - predefinedBytesTest(v, bytes) - predefinedBytesTestNotFomZeroElement(bytes, v) + protected def roundTripTest[V <: Value[_ <: SType]](v: V, withVersion: Option[Byte] = None): Assertion = { + def test() = { + val bytes = ValueSerializer.serialize(v) + predefinedBytesTest(v, bytes) + predefinedBytesTestNotFomZeroElement(bytes, v) + } + withVersion match { + case Some(ver) => + VersionContext.withVersions(ver, 1) { + test() + } + case None => + test() + } } protected def predefinedBytesTest[V <: Value[_ <: SType]](v: V, bytes: Array[Byte]): Assertion = { @@ -41,7 +52,7 @@ trait SerializationSpecification extends AnyPropSpec r.positionLimit shouldBe positionLimitBefore } - //check that pos and consumed are being implented correctly + //check that pos and consumed are being implemented correctly protected def predefinedBytesTestNotFomZeroElement[V <: Value[_ <: SType]](bytes: Array[Byte], v: V): Assertion = { val randomInt = Gen.chooseNum(1, 20).sample.get val randomBytes = Gen.listOfN(randomInt, arbByte.arbitrary).sample.get.toArray 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 e625923413..bd77766830 100644 --- a/interpreter/shared/src/test/scala/sigma/serialization/generators/ObjectGenerators.scala +++ b/interpreter/shared/src/test/scala/sigma/serialization/generators/ObjectGenerators.scala @@ -311,6 +311,7 @@ trait ObjectGenerators extends TypeGenerators case SAvlTree => arbAvlTree case SAny => arbAnyVal case SUnit => arbUnit + case SHeader => arbHeader case opt: SOption[a] => Arbitrary(frequency((5, None), (5, for (x <- wrappedTypeGen(opt.elemType)) yield Some(x)))) }).asInstanceOf[Arbitrary[T#WrappedType]].arbitrary @@ -694,7 +695,6 @@ trait ObjectGenerators extends TypeGenerators } yield ErgoTree.withSegregation(ZeroHeader, prop) def headerGen(stateRoot: AvlTree, parentId: Coll[Byte]): Gen[Header] = for { - id <- modifierIdBytesGen version <- arbByte.arbitrary adProofsRoot <- digest32Gen transactionRoot <- digest32Gen @@ -708,8 +708,9 @@ trait ObjectGenerators extends TypeGenerators powDistance <- arbBigInt.arbitrary votes <- minerVotesGen unparsedBytes <- collOfRange(0, 32, arbByte.arbitrary) - } yield CHeader(id, version, parentId, adProofsRoot, stateRoot, transactionRoot, timestamp, nBits, - height, extensionRoot, minerPk.toGroupElement, powOnetimePk.toGroupElement, powNonce, powDistance, votes, unparsedBytes) + } yield CHeader(version, parentId, adProofsRoot, stateRoot.digest, transactionRoot, timestamp, nBits, + height, extensionRoot, minerPk.toGroupElement, powOnetimePk.toGroupElement, powNonce, powDistance, votes, + if(version > HeaderVersion.Interpreter60Version){ unparsedBytes } else {Colls.emptyColl[Byte]}) lazy val headerGen: Gen[Header] = for { stateRoot <- avlTreeGen 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 81073c4849..70a215e831 100644 --- a/interpreter/shared/src/test/scala/sigma/serialization/generators/TypeGenerators.scala +++ b/interpreter/shared/src/test/scala/sigma/serialization/generators/TypeGenerators.scala @@ -16,12 +16,13 @@ trait TypeGenerators { implicit val boxTypeGen: Gen[SBox.type] = Gen.const(SBox) implicit val avlTreeTypeGen: Gen[SAvlTree.type] = Gen.const(SAvlTree) implicit val optionSigmaPropTypeGen: Gen[SOption[SSigmaProp.type]] = Gen.const(SOption(SSigmaProp)) + implicit val headerTypeGen: Gen[SHeader.type] = Gen.const(SHeader) implicit val primTypeGen: Gen[SPrimType] = Gen.oneOf[SPrimType](SBoolean, SByte, SShort, SInt, SLong, SBigInt, SGroupElement, SSigmaProp, SUnit) implicit val arbPrimType: Arbitrary[SPrimType] = Arbitrary(primTypeGen) implicit val predefTypeGen: Gen[SPredefType] = - Gen.oneOf[SPredefType](SBoolean, SByte, SShort, SInt, SLong, SBigInt, SGroupElement, SSigmaProp, SUnit, SBox, SAvlTree) + Gen.oneOf[SPredefType](SBoolean, SByte, SShort, SInt, SLong, SBigInt, SGroupElement, SSigmaProp, SUnit, SBox, SAvlTree, SHeader) implicit val arbPredefType: Arbitrary[SPredefType] = Arbitrary(predefTypeGen) implicit def genToArbitrary[T: Gen]: Arbitrary[T] = Arbitrary(implicitly[Gen[T]]) diff --git a/interpreter/shared/src/test/scala/special/sigma/SigmaTestingData.scala b/interpreter/shared/src/test/scala/special/sigma/SigmaTestingData.scala index 6b8c833931..b8bf76cacf 100644 --- a/interpreter/shared/src/test/scala/special/sigma/SigmaTestingData.scala +++ b/interpreter/shared/src/test/scala/special/sigma/SigmaTestingData.scala @@ -12,7 +12,7 @@ import scorex.crypto.hash.{Blake2b256, Digest32} import scorex.util.ModifierId import sigma.ast._ import sigma.Extensions.ArrayOps -import sigmastate.eval.{CHeader, CPreHeader} +import sigmastate.eval.CPreHeader import sigmastate.helpers.TestingCommons import sigma.serialization.ErgoTreeSerializer import sigma.serialization.generators.ObjectGenerators @@ -240,17 +240,16 @@ trait SigmaTestingData extends TestingCommons with ObjectGenerators { def createAvlTreeData() = AvlTreeData( ErgoAlgos.decodeUnsafe("010180017f7f7b7f720c00007f7f7f0f01e857a626f37f1483d06af8077a008080").toColl, - AvlTreeFlags(false, true, false), - 728138553, - Some(2147483647) + AvlTreeFlags(true, true, true), + 32, + None ) val h1_instances = new CloneSet(1000, CHeader( - Helpers.decodeBytes("957f008001808080ffe4ffffc8f3802401df40006aa05e017fa8d3f6004c804a"), 0.toByte, Helpers.decodeBytes("0180dd805b0000ff5400b997fd7f0b9b00de00fb03c47e37806a8186b94f07ff"), Helpers.decodeBytes("01f07f60d100ffb970c3007f60ff7f24d4070bb8fffa7fca7f34c10001ffe39d"), - CAvlTree(createAvlTreeData()), + CAvlTree(createAvlTreeData()).digest, Helpers.decodeBytes("804101ff01000080a3ffbd006ac080098df132a7017f00649311ec0e00000100"), 1L, -1L, @@ -268,7 +267,7 @@ trait SigmaTestingData extends TestingCommons with ObjectGenerators { val h1: Header = create_h1() - val h2: Header = create_h1().asInstanceOf[CHeader].copy(height = 2) + val h2: Header = new CHeader(h1.asInstanceOf[CHeader].wrappedValue.copy(height = 2)) val dlog_instances = new CloneSet(1000, ProveDlog( SigmaDsl.toECPoint(create_ge1()).asInstanceOf[EcPointType] diff --git a/sc/shared/src/test/scala/sigma/SigmaDslSpecification.scala b/sc/shared/src/test/scala/sigma/SigmaDslSpecification.scala index 1977537cbf..c4d1db777d 100644 --- a/sc/shared/src/test/scala/sigma/SigmaDslSpecification.scala +++ b/sc/shared/src/test/scala/sigma/SigmaDslSpecification.scala @@ -41,11 +41,11 @@ import scala.util.{Failure, Success} /** This suite tests every method of every SigmaDsl type to be equivalent to * the evaluation of the corresponding ErgoScript operation. * - * The properties of this suite excercise two interpreters: the current (aka `old` + * The properties of this suite exercise two interpreters: the current (aka `old` * interpreter) and the new interpreter for a next soft-fork. After the soft-fork is * released, the new interpreter becomes current at which point the `old` and `new` * interpreters in this suite should be equivalent. This change is reflected in this - * suite by commiting changes in expected values. + * suite by committing changes in expected values. * The `old` and `new` interpreters are compared like the following: * 1) for existingFeature the interpreters should be equivalent * 2) for changedFeature the test cases contain different expected values @@ -53,7 +53,7 @@ import scala.util.{Failure, Success} * against expected values. * * This suite can be used for Cost profiling, i.e. measurements of operations times and - * comparing them with cost parameteres of the operations. + * comparing them with cost parameters of the operations. * * The following settings should be specified for profiling: * isMeasureOperationTime = true @@ -4516,7 +4516,7 @@ class SigmaDslSpecification extends SigmaDslTesting property("Header properties equivalence") { verifyCases( Seq((h1, Expected(Success( - Helpers.decodeBytes("957f008001808080ffe4ffffc8f3802401df40006aa05e017fa8d3f6004c804a")), + Helpers.decodeBytes("cea31f0e0a794b103f65f8296a22ac8ff214e1bc75442186b90df4844c978e81")), cost = 1766, methodCostDetails(SHeaderMethods.idMethod, 10), 1766))), existingPropTest("id", { (x: Header) => x.id })) @@ -4654,18 +4654,10 @@ class SigmaDslSpecification extends SigmaDslTesting ) val header = CHeader( - Helpers.decodeBytes("1c597f88969600d2fffffdc47f00d8ffc555a9e85001000001c505ff80ff8f7f"), 0.toByte, Helpers.decodeBytes("7a7fe5347f09017818010062000001807f86808000ff7f66ffb07f7ad27f3362"), Helpers.decodeBytes("c1d70ad9b1ffc1fb9a715fff19807f2401017fcd8b73db017f1cff77727fff08"), - CAvlTree( - AvlTreeData( - ErgoAlgos.decodeUnsafe("54d23dd080006bdb56800100356080935a80ffb77e90b800057f00661601807f17").toColl, - AvlTreeFlags(true, true, false), - 2147483647, - None - ) - ), + Helpers.decodeBytes("54d23dd080006bdb56800100356080935a80ffb77e90b800057f00661601807f17"), Helpers.decodeBytes("5e7f1164ccd0990080c501fc0e0181cb387fc17f00ff00c7d5ff767f91ff5e68"), -7421721754642387858L, -4826493284887861030L, @@ -4684,7 +4676,7 @@ class SigmaDslSpecification extends SigmaDslTesting headers = Coll[Header](header), preHeader = CPreHeader( 0.toByte, - Helpers.decodeBytes("1c597f88969600d2fffffdc47f00d8ffc555a9e85001000001c505ff80ff8f7f"), + header.id, -755484979487531112L, 9223372036854775807L, 11, diff --git a/sc/shared/src/test/scala/sigmastate/TypesSpecification.scala b/sc/shared/src/test/scala/sigmastate/TypesSpecification.scala index 9a4c5ce1b8..6d13863f26 100644 --- a/sc/shared/src/test/scala/sigmastate/TypesSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/TypesSpecification.scala @@ -13,8 +13,6 @@ class TypesSpecification extends SigmaTestingData { implicit val tWrapped = wrappedTypeGen(t) forAll { x: SPredefType#WrappedType => isValueOfType(x, t) shouldBe true - // since forall t. SHeader != t - isValueOfType(x, SHeader) shouldBe false } } } diff --git a/sdk/js/src/main/scala/org/ergoplatform/sdk/js/Isos.scala b/sdk/js/src/main/scala/org/ergoplatform/sdk/js/Isos.scala index 91be0ca61c..84f2b21da8 100644 --- a/sdk/js/src/main/scala/org/ergoplatform/sdk/js/Isos.scala +++ b/sdk/js/src/main/scala/org/ergoplatform/sdk/js/Isos.scala @@ -7,9 +7,10 @@ import sigma.ast.{Constant, SType} import sigma.data.Iso import sigma.data.Iso.{isoStringToArray, isoStringToColl} import sigma.data.js.{Isos => DataIsos} +import sigma.data.CHeader import sigma.interpreter.{ContextExtension, ProverResult} import sigma.js.AvlTree -import sigmastate.eval.{CHeader, CPreHeader} +import sigmastate.eval.CPreHeader import sigmastate.fleetSdkCommon.distEsmTypesBoxesMod.Box import sigmastate.fleetSdkCommon.distEsmTypesRegistersMod.NonMandatoryRegisters import sigmastate.fleetSdkCommon.distEsmTypesTokenMod.TokenAmount @@ -27,11 +28,10 @@ object Isos { implicit val isoHeader: Iso[Header, sigma.Header] = new Iso[Header, sigma.Header] { override def to(a: Header): sigma.Header = { CHeader( - id = isoStringToColl.to(a.id), version = a.version, parentId = isoStringToColl.to(a.parentId), ADProofsRoot = isoStringToColl.to(a.ADProofsRoot), - stateRoot = AvlTree.isoAvlTree.to(a.stateRoot), + stateRootDigest = AvlTree.isoAvlTree.to(a.stateRoot).digest, transactionsRoot = isoStringToColl.to(a.transactionsRoot), timestamp = sigma.js.Isos.isoBigIntToLong.to(a.timestamp), nBits = sigma.js.Isos.isoBigIntToLong.to(a.nBits), diff --git a/sdk/shared/src/main/scala/org/ergoplatform/sdk/DataJsonEncoder.scala b/sdk/shared/src/main/scala/org/ergoplatform/sdk/DataJsonEncoder.scala index fc95b77e61..6c0c866baf 100644 --- a/sdk/shared/src/main/scala/org/ergoplatform/sdk/DataJsonEncoder.scala +++ b/sdk/shared/src/main/scala/org/ergoplatform/sdk/DataJsonEncoder.scala @@ -122,6 +122,10 @@ object DataJsonEncoder { val w = SigmaSerializer.startWriter() DataSerializer.serialize(v, tpe, w) encodeBytes(w.toBytes) + case SHeader => + val w = SigmaSerializer.startWriter() + DataSerializer.serialize(v, tpe, w) + encodeBytes(w.toBytes) case SAvlTree => val w = SigmaSerializer.startWriter() DataSerializer.serialize(v, tpe, w) @@ -203,6 +207,10 @@ object DataJsonEncoder { val str = decodeBytes(json) val r = SigmaSerializer.startReader(str) DataSerializer.deserialize(SSigmaProp, r) + case SHeader => // for Sigma < 6.0 , exception will be thrown by DataSerializer + val str = decodeBytes(json) + val r = SigmaSerializer.startReader(str) + DataSerializer.deserialize(SHeader, r) case SBox => val value = decodeData(json.hcursor.downField(s"value").focus.get, SLong) val tree = ErgoTreeSerializer.DefaultSerializer.deserializeErgoTree(decodeBytes(json.hcursor.downField(s"ergoTree").focus.get)) diff --git a/sdk/shared/src/main/scala/org/ergoplatform/sdk/JsonCodecs.scala b/sdk/shared/src/main/scala/org/ergoplatform/sdk/JsonCodecs.scala index c2fc1c0c8c..1c7a4156f4 100644 --- a/sdk/shared/src/main/scala/org/ergoplatform/sdk/JsonCodecs.scala +++ b/sdk/shared/src/main/scala/org/ergoplatform/sdk/JsonCodecs.scala @@ -12,7 +12,7 @@ import scorex.crypto.hash.Digest32 import scorex.util.ModifierId import sigma.Extensions.ArrayOps import sigma.ast.{ErgoTree, EvaluatedValue, SType} -import sigma.data.{AvlTreeData, AvlTreeFlags, CBigInt, Digest32Coll, WrapperOf} +import sigma.data.{AvlTreeData, AvlTreeFlags, CBigInt, CHeader, Digest32Coll, WrapperOf} import sigma.eval.Extensions.EvalIterableOps import sigma.eval.SigmaDsl import sigma.interpreter.{ContextExtension, ProverResult} @@ -132,7 +132,6 @@ trait JsonCodecs { implicit val headerDecoder: Decoder[Header] = Decoder.instance({ cursor => for { - id <- cursor.downField("id").as[Coll[Byte]] version <- cursor.downField("version").as[Byte] parentId <- cursor.downField("parentId").as[Coll[Byte]] adProofsRoot <- cursor.downField("adProofsRoot").as[Coll[Byte]] @@ -148,7 +147,7 @@ trait JsonCodecs { powDistance <- cursor.downField("powDistance").as[sigma.BigInt] votes <- cursor.downField("votes").as[Coll[Byte]] unparsedBytes <- cursor.downField("unparsedBytes").as[Option[Coll[Byte]]] - } yield new CHeader(id, version, parentId, adProofsRoot, stateRoot, transactionsRoot, timestamp, nBits, + } yield CHeader(version, parentId, adProofsRoot, stateRoot.digest, transactionsRoot, timestamp, nBits, height, extensionRoot, SigmaDsl.decodePoint(minerPk), SigmaDsl.decodePoint(powOnetimePk), powNonce, powDistance, votes, unparsedBytes.getOrElse(Colls.emptyColl)) }) 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 c3f7b43af4..33e9546000 100644 --- a/sdk/shared/src/test/scala/org/ergoplatform/sdk/DataJsonEncoderSpecification.scala +++ b/sdk/shared/src/test/scala/org/ergoplatform/sdk/DataJsonEncoderSpecification.scala @@ -13,7 +13,7 @@ import sigma.serialization.SerializerException import sigma.util.Extensions.{BigIntegerOps, EcpOps, SigmaBooleanOps} import sigma.Extensions.ArrayOps import sigma.eval.SigmaDsl -import sigma.{AvlTree, Box, Colls, Evaluation} +import sigma.{AvlTree, Box, Colls, Evaluation, Header, VersionContext} import sigma.serialization.SerializationSpecification import scala.annotation.nowarn @@ -22,29 +22,48 @@ import scala.reflect.ClassTag class DataJsonEncoderSpecification extends SerializationSpecification { object JsonCodecs extends JsonCodecs - def roundtrip[T <: SType](obj: T#WrappedType, tpe: T) = { - val json = DataJsonEncoder.encode(obj, tpe) - val res = DataJsonEncoder.decode(json) - res shouldBe obj + def roundtrip[T <: SType](obj: T#WrappedType, tpe: T, withVersion: Option[Byte] = None) = { + def test() = { + val json = DataJsonEncoder.encode(obj, tpe) + val res = DataJsonEncoder.decode(json) + res shouldBe obj + } + + withVersion match { + case Some(ver) => + VersionContext.withVersions(ver, 1) { + test() + } + case None => + test() + } } def testCollection[T <: SType](tpe: T) = { implicit val wWrapped = wrappedTypeGen(tpe) implicit val tT = Evaluation.stypeToRType(tpe) implicit val tagT = tT.classTag + + val withVersion = if (tpe == SHeader) { + Some(VersionContext.V6SoftForkVersion) + } else { + None + } + forAll { xs: Array[T#WrappedType] => - roundtrip[SCollection[T]](xs.toColl, SCollection(tpe)) - roundtrip[SType](xs.toColl.map(x => (x, x)).asWrappedType, SCollection(STuple(tpe, tpe))) + roundtrip[SCollection[T]](xs.toColl, SCollection(tpe), withVersion) + roundtrip[SType](xs.toColl.map(x => (x, x)).asWrappedType, SCollection(STuple(tpe, tpe)), withVersion) val nested = xs.toColl.map(x => Colls.fromItems[T#WrappedType](x, x)) - roundtrip[SCollection[SCollection[T]]](nested, SCollection(SCollection(tpe))) + roundtrip[SCollection[SCollection[T]]](nested, SCollection(SCollection(tpe)), withVersion) roundtrip[SType]( xs.toColl.map { x => val arr = Colls.fromItems[T#WrappedType](x, x) (arr, arr) }.asWrappedType, - SCollection(STuple(SCollection(tpe), SCollection(tpe))) + SCollection(STuple(SCollection(tpe), SCollection(tpe))), + withVersion ) } } @@ -54,11 +73,18 @@ class DataJsonEncoderSpecification extends SerializationSpecification { val tT = Evaluation.stypeToRType(tpe) @nowarn implicit val tag : ClassTag[T#WrappedType] = tT.classTag @nowarn implicit val tAny : RType[Any] = sigma.AnyType + + val withVersion = if (tpe == SHeader) { + Some(VersionContext.V6SoftForkVersion) + } else { + None + } + forAll { in: (T#WrappedType, T#WrappedType) => val (x,y) = (in._1, in._2) - roundtrip[SType]((x, y).asWrappedType, STuple(tpe, tpe)) - roundtrip[SType](((x, y), (x, y)).asWrappedType, STuple(STuple(tpe, tpe), STuple(tpe, tpe))) - roundtrip[SType](((x, y), ((x, y), (x, y))).asWrappedType, STuple(STuple(tpe, tpe), STuple(STuple(tpe, tpe), STuple(tpe, tpe)))) + roundtrip[SType]((x, y).asWrappedType, STuple(tpe, tpe), withVersion) + roundtrip[SType](((x, y), (x, y)).asWrappedType, STuple(STuple(tpe, tpe), STuple(tpe, tpe)), withVersion) + roundtrip[SType](((x, y), ((x, y), (x, y))).asWrappedType, STuple(STuple(tpe, tpe), STuple(STuple(tpe, tpe), STuple(tpe, tpe))), withVersion) } } @@ -98,6 +124,7 @@ class DataJsonEncoderSpecification extends SerializationSpecification { forAll { x: AvlTree => roundtrip[SAvlTree.type](x, SAvlTree) } forAll { x: Array[Byte] => roundtrip[SByteArray](x.toColl, SByteArray) } forAll { x: Box => roundtrip[SBox.type](x, SBox) } + forAll { x: Header => roundtrip[SHeader.type](x, SHeader, Some(VersionContext.V6SoftForkVersion)) } forAll { x: Option[Byte] => roundtrip[SOption[SByte.type]](x, SOption[SByte.type]) } testCollection(SOption[SLong.type]) testTuples(SOption[SLong.type]) @@ -187,25 +214,44 @@ class DataJsonEncoderSpecification extends SerializationSpecification { val tT = Evaluation.stypeToRType(tpe) @nowarn implicit val tag = tT.classTag @nowarn implicit val tAny = sigma.AnyType - forAll { x: T#WrappedType => - an[SerializerException] should be thrownBy { - DataJsonEncoder.encode(TupleColl(x, x, x).asWrappedType, STuple(tpe, tpe, tpe)) - } - // supported case - DataJsonEncoder.encode(SigmaDsl.Colls.fromItems(TupleColl(x, x)).asWrappedType, SCollection(STuple(tpe, tpe))) - // not supported case - an[SerializerException] should be thrownBy { - DataJsonEncoder.encode(SigmaDsl.Colls.fromItems(TupleColl(x, x, x)).asWrappedType, SCollection(STuple(tpe, tpe, tpe))) + def test() = { + forAll { x: T#WrappedType => + an[SerializerException] should be thrownBy { + DataJsonEncoder.encode(TupleColl(x, x, x).asWrappedType, STuple(tpe, tpe, tpe)) + } + + // supported case + DataJsonEncoder.encode(SigmaDsl.Colls.fromItems(TupleColl(x, x)).asWrappedType, SCollection(STuple(tpe, tpe))) + + // not supported case + an[SerializerException] should be thrownBy { + DataJsonEncoder.encode(SigmaDsl.Colls.fromItems(TupleColl(x, x, x)).asWrappedType, SCollection(STuple(tpe, tpe, tpe))) + } } } + + if (tpe == SHeader) { + VersionContext.withVersions(VersionContext.V6SoftForkVersion, 1) { + test() + } + } else { + test() + } } property("AnyValue") { forAll { t: SPredefType => - testAnyValue(t) - testAnyValue(SOption(t)) + if (t == SHeader) { + VersionContext.withVersions(VersionContext.V6SoftForkVersion, 1) { + testAnyValue(t) + testAnyValue(SOption(t)) + } + } else { + testAnyValue(t) + testAnyValue(SOption(t)) + } } } From fd8d6ebe872ae2c384a71e53f4bc6f587f269f84 Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Wed, 5 Jun 2024 19:58:55 +0300 Subject: [PATCH 125/314] checkPow cost --- data/shared/src/main/scala/sigma/ast/methods.scala | 6 +++--- .../scala/sigmastate/interpreter/CErgoTreeEvaluator.scala | 6 ++---- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/data/shared/src/main/scala/sigma/ast/methods.scala b/data/shared/src/main/scala/sigma/ast/methods.scala index e58fa35adb..1208e36f7f 100644 --- a/data/shared/src/main/scala/sigma/ast/methods.scala +++ b/data/shared/src/main/scala/sigma/ast/methods.scala @@ -10,7 +10,6 @@ import sigma.ast.syntax.{SValue, ValueOps} import sigma.data.OverloadHack.Overloaded1 import sigma.data.{DataValueComparer, KeyValueColl, Nullable, RType, SigmaConstants} import sigma.eval.{CostDetails, ErgoTreeEvaluator, TracedCost} -import sigma.pow.Autolykos2PowValidation import sigma.reflection.RClass import sigma.serialization.CoreByteWriter.ArgInfo import sigma.utils.SparseArrayContainer @@ -1457,10 +1456,11 @@ case object SHeaderMethods extends MonoTypeMethods { lazy val powDistanceMethod = propertyCall("powDistance", SBigInt, 14, FixedCost(JitCost(10))) lazy val votesMethod = propertyCall("votes", SByteArray, 15, FixedCost(JitCost(10))) + // cost of checkPoW is 700 as about 2*32 hashes required, and 1 hash (id) over short data costs 10 lazy val checkPowMethod = SMethod( - this, "checkPow", SFunc(Array(SHeader), SBoolean), 16, GroupGenerator.costKind) // todo: cost + this, "checkPow", SFunc(Array(SHeader), SBoolean), 16, FixedCost(JitCost(700))) .withIRInfo(MethodCallIrBuilder) - .withInfo(Xor, "Byte-wise XOR of two collections of bytes") // todo: desc + .withInfo("Validate headers' proof-of-work") def checkPow_eval(mc: MethodCall, G: SigmaDslBuilder, header: Header) (implicit E: ErgoTreeEvaluator): Boolean = { diff --git a/interpreter/shared/src/main/scala/sigmastate/interpreter/CErgoTreeEvaluator.scala b/interpreter/shared/src/main/scala/sigmastate/interpreter/CErgoTreeEvaluator.scala index 59c9af09ef..1c58e00a97 100644 --- a/interpreter/shared/src/main/scala/sigmastate/interpreter/CErgoTreeEvaluator.scala +++ b/interpreter/shared/src/main/scala/sigmastate/interpreter/CErgoTreeEvaluator.scala @@ -10,11 +10,11 @@ import sigma.util.Extensions._ import debox.{cfor, Buffer => DBuffer} import scorex.crypto.authds.ADKey import sigma.ast.SAvlTreeMethods._ +import sigma.ast.SHeaderMethods.checkPowMethod import sigma.ast.SType import sigma.data.{CSigmaProp, KeyValueColl, SigmaBoolean} import sigma.eval.{AvlTreeVerifier, ErgoTreeEvaluator, EvalSettings, Profiler} import sigma.eval.ErgoTreeEvaluator.DataEnv -import sigma.pow.Autolykos2PowValidation import sigmastate.interpreter.CErgoTreeEvaluator.fixedCostOp import scala.collection.compat.immutable.ArraySeq @@ -219,9 +219,7 @@ class CErgoTreeEvaluator( } override def checkPow_eval(mc: MethodCall, header: Header): Boolean = { - VersionContext.checkVersions(context.activatedScriptVersion, context.currentErgoTreeVersion) - // todo: consider cost - val checkPowCostInfo = OperationCostInfo(FixedCost(JitCost(10)), NamedDesc("Header.checkPow")) + val checkPowCostInfo = OperationCostInfo(checkPowMethod.costKind.asInstanceOf[FixedCost], NamedDesc("Header.checkPow")) fixedCostOp(checkPowCostInfo){ header.checkPow }(this) From 928d8cb38b8aaf0aa36546294c56392ebac71c3f Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Wed, 5 Jun 2024 22:31:31 +0300 Subject: [PATCH 126/314] LangSpec.md update --- docs/LangSpec.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/LangSpec.md b/docs/LangSpec.md index ba66748f08..1f05a3b403 100644 --- a/docs/LangSpec.md +++ b/docs/LangSpec.md @@ -249,6 +249,10 @@ class Context { /** Represents data of the block headers available in scripts. */ class Header { + + /** Validate header's proof-of-work */ + def checkPow: Boolean + /** Bytes representation of ModifierId of this Header */ def id: Coll[Byte] From 07b86446ec812e6073912de1de3f0b6d6404aeba Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Thu, 6 Jun 2024 12:34:46 +0300 Subject: [PATCH 127/314] moving newFeature related code from serializePR --- .../sigmastate/helpers/SigmaPPrint.scala | 6 +- .../scala/sigmastate/lang/LangTests.scala | 6 + .../sigmastate/lang/SigmaParserTest.scala | 12 + .../sigmastate/helpers/SigmaPPrintSpec.scala | 1 - .../sigma/LanguageSpecificationBase.scala | 126 ++++++ ...on.scala => LanguageSpecificationV5.scala} | 358 +----------------- .../scala/sigma/LanguageSpecificationV6.scala | 348 +++++++++++++++++ .../test/scala/sigma/SigmaDslTesting.scala | 142 +++++-- .../CompilerCrossVersionProps.scala | 11 +- .../sigmastate/lang/SigmaBinderTest.scala | 13 + .../sigmastate/lang/SigmaTyperTest.scala | 9 +- 11 files changed, 634 insertions(+), 398 deletions(-) rename {sc => parsers}/shared/src/test/scala/sigmastate/helpers/SigmaPPrint.scala (98%) create mode 100644 sc/shared/src/test/scala/sigma/LanguageSpecificationBase.scala rename sc/shared/src/test/scala/sigma/{SigmaDslSpecification.scala => LanguageSpecificationV5.scala} (96%) create mode 100644 sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala diff --git a/sc/shared/src/test/scala/sigmastate/helpers/SigmaPPrint.scala b/parsers/shared/src/test/scala/sigmastate/helpers/SigmaPPrint.scala similarity index 98% rename from sc/shared/src/test/scala/sigmastate/helpers/SigmaPPrint.scala rename to parsers/shared/src/test/scala/sigmastate/helpers/SigmaPPrint.scala index 1b0f7b112d..24aaeddefd 100644 --- a/sc/shared/src/test/scala/sigmastate/helpers/SigmaPPrint.scala +++ b/parsers/shared/src/test/scala/sigmastate/helpers/SigmaPPrint.scala @@ -5,15 +5,13 @@ import org.ergoplatform.ErgoBox.RegisterId import org.ergoplatform.settings.ErgoAlgos import pprint.{PPrinter, Tree} import sigma.ast.SCollection.{SBooleanArray, SByteArray, SByteArray2} -import sigma.ast._ +import sigma.ast.{ConstantNode, FuncValue, MethodCall, ValueCompanion, _} import sigma.crypto.EcPointType import sigma.data.{AvlTreeData, AvlTreeFlags, CollType, PrimitiveType, TrivialProp} import sigma.serialization.GroupElementSerializer import sigma.{Coll, GroupElement} -import sigma.ast.{ConstantNode, FuncValue, ValueCompanion} -import sigmastate._ import sigmastate.crypto.GF2_192_Poly -import sigma.ast.MethodCall + import java.math.BigInteger import scala.collection.compat.immutable.ArraySeq import scala.collection.mutable diff --git a/parsers/shared/src/test/scala/sigmastate/lang/LangTests.scala b/parsers/shared/src/test/scala/sigmastate/lang/LangTests.scala index 32943bca44..de83070ac3 100644 --- a/parsers/shared/src/test/scala/sigmastate/lang/LangTests.scala +++ b/parsers/shared/src/test/scala/sigmastate/lang/LangTests.scala @@ -79,4 +79,10 @@ trait LangTests extends Matchers with NegativeTesting { node }))(tree) } + + /** Execute the given `block` having `version` as both activated and ErgoTree version. */ + def runWithVersion[T](version: Byte)(block: => T): T = { + VersionContext.withVersions(version, version)(block) + } + } diff --git a/parsers/shared/src/test/scala/sigmastate/lang/SigmaParserTest.scala b/parsers/shared/src/test/scala/sigmastate/lang/SigmaParserTest.scala index 02b28f86ca..dc63330f95 100644 --- a/parsers/shared/src/test/scala/sigmastate/lang/SigmaParserTest.scala +++ b/parsers/shared/src/test/scala/sigmastate/lang/SigmaParserTest.scala @@ -14,6 +14,7 @@ import SigmaPredef.PredefinedFuncRegistry import sigma.ast.syntax._ import sigmastate.lang.parsers.ParserException import sigma.serialization.OpCodes +import sigmastate.helpers.SigmaPPrint class SigmaParserTest extends AnyPropSpec with ScalaCheckPropertyChecks with Matchers with LangTests { import StdSigmaBuilder._ @@ -34,6 +35,17 @@ class SigmaParserTest extends AnyPropSpec with ScalaCheckPropertyChecks with Mat } } + /** Checks parsing result, printing the actual value as a test vector if expected value + * is not equal to actual. + */ + def checkParsed(x: String, expected: SValue) = { + val parsed = parse(x) + if (expected != parsed) { + SigmaPPrint.pprintln(parsed, width = 100) + } + parsed shouldBe expected + } + def parseWithException(x: String): SValue = { SigmaParser(x) match { case Parsed.Success(v, _) => v diff --git a/sc/jvm/src/test/scala/sigmastate/helpers/SigmaPPrintSpec.scala b/sc/jvm/src/test/scala/sigmastate/helpers/SigmaPPrintSpec.scala index 54c0f652dc..ffd591b0df 100644 --- a/sc/jvm/src/test/scala/sigmastate/helpers/SigmaPPrintSpec.scala +++ b/sc/jvm/src/test/scala/sigmastate/helpers/SigmaPPrintSpec.scala @@ -8,7 +8,6 @@ import sigma.SigmaDslTesting import sigma.ast._ import sigma.data.{AvlTreeData, AvlTreeFlags, CBox, CollType, Digest32Coll} import ErgoTree.HeaderType -import sigmastate.eval._ import sigma.ast.MethodCall import sigma.serialization.OpCodes import sigmastate.utils.Helpers diff --git a/sc/shared/src/test/scala/sigma/LanguageSpecificationBase.scala b/sc/shared/src/test/scala/sigma/LanguageSpecificationBase.scala new file mode 100644 index 0000000000..2bb44fc910 --- /dev/null +++ b/sc/shared/src/test/scala/sigma/LanguageSpecificationBase.scala @@ -0,0 +1,126 @@ +package sigma + +import org.scalatest.BeforeAndAfterAll +import sigma.ast.JitCost +import sigma.eval.{EvalSettings, Profiler} +import sigmastate.CompilerCrossVersionProps +import sigmastate.interpreter.CErgoTreeEvaluator +import scala.util.Success + +/** Base class for language test suites (one suite for each language version: 5.0, 6.0, etc.) + * Each suite tests every method of every SigmaDsl type to be equivalent to + * the evaluation of the corresponding ErgoScript operation. + * + * The properties of this suite exercise two interpreters: the current (aka `old` + * interpreter) and the new interpreter for a next soft-fork. After the soft-fork is + * released, the new interpreter becomes current at which point the `old` and `new` + * interpreters in this suite should be equivalent. This change is reflected in this + * suite by commiting changes in expected values. + * The `old` and `new` interpreters are compared like the following: + * 1) for existingFeature the interpreters should be equivalent + * 2) for changedFeature the test cases contain different expected values + * 3) for newFeature the old interpreter should throw and the new interpreter is checked + * against expected values. + * + * This suite can be used for Cost profiling, i.e. measurements of operations times and + * comparing them with cost parameters of the operations. + * + * The following settings should be specified for profiling: + * isMeasureOperationTime = true + * isMeasureScriptTime = true + * isLogEnabled = false + * printTestVectors = false + * costTracingEnabled = false + * isTestRun = true + * perTestWarmUpIters = 1 + * nBenchmarkIters = 1 + */ +abstract class LanguageSpecificationBase extends SigmaDslTesting + with CompilerCrossVersionProps + with BeforeAndAfterAll { suite => + + /** Version of the language (ErgoScript/ErgoTree) which is specified by this suite. */ + def languageVersion: Byte + + /** Use VersionContext so that each property in this suite runs under correct + * parameters. + */ + protected override def testFun_Run(testName: String, testFun: => Any): Unit = { + VersionContext.withVersions(activatedVersionInTests, ergoTreeVersionInTests) { + super.testFun_Run(testName, testFun) + } + } + + implicit override val generatorDrivenConfig: PropertyCheckConfiguration = PropertyCheckConfiguration(minSuccessful = 30) + + val evalSettingsInTests = CErgoTreeEvaluator.DefaultEvalSettings.copy( + isMeasureOperationTime = true, + isMeasureScriptTime = true, + isLogEnabled = false, // don't commit the `true` value (travis log is too high) + printTestVectors = false, // don't commit the `true` value (travis log is too high) + + /** Should always be enabled in tests (and false by default) + * Should be disabled for cost profiling, which case the new costs are not checked. + */ + costTracingEnabled = true, + profilerOpt = Some(CErgoTreeEvaluator.DefaultProfiler), + isTestRun = true + ) + + def warmupSettings(p: Profiler) = evalSettingsInTests.copy( + isLogEnabled = false, + printTestVectors = false, + profilerOpt = Some(p) + ) + + implicit override def evalSettings: EvalSettings = { + warmupProfiler match { + case Some(p) => warmupSettings(p) + case _ => evalSettingsInTests + } + } + + override val perTestWarmUpIters = 0 + + override val nBenchmarkIters = 0 + + override val okRunTestsWithoutMCLowering: Boolean = true + + implicit def IR = createIR() + + def testCases[A, B](cases: Seq[(A, Expected[B])], f: Feature[A, B]) = { + val table = Table(("x", "y"), cases: _*) + forAll(table) { (x, expectedRes) => + val res = f.checkEquality(x) + val resValue = res.map(_._1) + val (expected, expDetailsOpt) = expectedRes.newResults(ergoTreeVersionInTests) + checkResult(resValue, expected.value, failOnTestVectors = true, + "SigmaDslSpecifiction#testCases: compare expected new result with res = f.checkEquality(x)") + res match { + case Success((value, details)) => + details.cost shouldBe JitCost(expected.verificationCost.get) + expDetailsOpt.foreach(expDetails => + if (details.trace != expDetails.trace) { + printCostDetails(f.script, details) + details.trace shouldBe expDetails.trace + } + ) + } + } + } + + override protected def beforeAll(): Unit = { + prepareSamples[BigInt] + prepareSamples[GroupElement] + prepareSamples[AvlTree] + prepareSamples[Box] + prepareSamples[PreHeader] + prepareSamples[Header] + prepareSamples[(BigInt, BigInt)] + prepareSamples[(GroupElement, GroupElement)] + prepareSamples[(AvlTree, AvlTree)] + prepareSamples[(Box, Box)] + prepareSamples[(PreHeader, PreHeader)] + prepareSamples[(Header, Header)] + } +} diff --git a/sc/shared/src/test/scala/sigma/SigmaDslSpecification.scala b/sc/shared/src/test/scala/sigma/LanguageSpecificationV5.scala similarity index 96% rename from sc/shared/src/test/scala/sigma/SigmaDslSpecification.scala rename to sc/shared/src/test/scala/sigma/LanguageSpecificationV5.scala index c820e65e73..700b48fd13 100644 --- a/sc/shared/src/test/scala/sigma/SigmaDslSpecification.scala +++ b/sc/shared/src/test/scala/sigma/LanguageSpecificationV5.scala @@ -5,31 +5,28 @@ import org.ergoplatform._ import org.ergoplatform.settings.ErgoAlgos import org.scalacheck.Arbitrary._ import org.scalacheck.{Arbitrary, Gen} -import org.scalatest.BeforeAndAfterAll import scorex.crypto.authds.avltree.batch._ import scorex.crypto.authds.{ADKey, ADValue} import scorex.crypto.hash.{Blake2b256, Digest32} import scorex.util.ModifierId import sigma.Extensions.{ArrayOps, CollOps} +import sigma.ast.ErgoTree.{HeaderType, ZeroHeader} import sigma.ast.SCollection._ -import sigma.ast._ import sigma.ast.syntax._ +import sigma.ast.{Apply, MethodCall, PropertyCall, _} +import sigma.data.OrderingOps._ import sigma.data.RType._ import sigma.data._ +import sigma.eval.Extensions.{ByteExt, IntExt, LongExt, ShortExt} +import sigma.eval.{CostDetails, EvalSettings, SigmaDsl, TracedCost} +import sigma.exceptions.InvalidType +import sigma.serialization.ValueCodes.OpCode import sigma.util.Extensions.{BooleanOps, IntOps, LongOps} import sigma.{VersionContext, ast, data, _} -import ErgoTree.{HeaderType, ZeroHeader} -import sigma.eval.{CostDetails, EvalSettings, Profiler, SigmaDsl, TracedCost} -import sigmastate._ import sigmastate.eval.Extensions.AvlTreeOps -import sigma.eval.Extensions.{ByteExt, IntExt, LongExt, ShortExt} -import OrderingOps._ import sigmastate.eval._ import sigmastate.helpers.TestingHelpers._ import sigmastate.interpreter._ -import sigma.ast.{Apply, MethodCall, PropertyCall} -import sigma.exceptions.InvalidType -import sigma.serialization.ValueCodes.OpCode import sigmastate.utils.Extensions._ import sigmastate.utils.Helpers import sigmastate.utils.Helpers._ @@ -38,122 +35,18 @@ import java.math.BigInteger import scala.collection.compat.immutable.ArraySeq import scala.util.{Failure, Success} -/** This suite tests every method of every SigmaDsl type to be equivalent to - * the evaluation of the corresponding ErgoScript operation. - * - * The properties of this suite excercise two interpreters: the current (aka `old` - * interpreter) and the new interpreter for a next soft-fork. After the soft-fork is - * released, the new interpreter becomes current at which point the `old` and `new` - * interpreters in this suite should be equivalent. This change is reflected in this - * suite by commiting changes in expected values. - * The `old` and `new` interpreters are compared like the following: - * 1) for existingFeature the interpreters should be equivalent - * 2) for changedFeature the test cases contain different expected values - * 3) for newFeature the old interpreter should throw and the new interpreter is checked - * against expected values. - * - * This suite can be used for Cost profiling, i.e. measurements of operations times and - * comparing them with cost parameteres of the operations. + +/** This suite tests all operations for v5.0 version of the language. + * The base classes establish the infrastructure for the tests. * - * The following settings should be specified for profiling: - * isMeasureOperationTime = true - * isMeasureScriptTime = true - * isLogEnabled = false - * printTestVectors = false - * costTracingEnabled = false - * isTestRun = true - * perTestWarmUpIters = 1 - * nBenchmarkIters = 1 + * @see SigmaDslSpecificationBase */ -class SigmaDslSpecification extends SigmaDslTesting - with CompilerCrossVersionProps - with BeforeAndAfterAll { suite => - - /** Use VersionContext so that each property in this suite runs under correct - * parameters. - */ - protected override def testFun_Run(testName: String, testFun: => Any): Unit = { - VersionContext.withVersions(activatedVersionInTests, ergoTreeVersionInTests) { - super.testFun_Run(testName, testFun) - } - } - - implicit override val generatorDrivenConfig = PropertyCheckConfiguration(minSuccessful = 30) +class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => - val evalSettingsInTests = CErgoTreeEvaluator.DefaultEvalSettings.copy( - isMeasureOperationTime = true, - isMeasureScriptTime = true, - isLogEnabled = false, // don't commit the `true` value (travis log is too high) - printTestVectors = false, // don't commit the `true` value (travis log is too high) - - /** Should always be enabled in tests (and false by default) - * Should be disabled for cost profiling, which case the new costs are not checked. - */ - costTracingEnabled = true, - - profilerOpt = Some(CErgoTreeEvaluator.DefaultProfiler), - isTestRun = true - ) - - def warmupSettings(p: Profiler) = evalSettingsInTests.copy( - isLogEnabled = false, - printTestVectors = false, - profilerOpt = Some(p) - ) - - implicit override def evalSettings: EvalSettings = { - warmupProfiler match { - case Some(p) => warmupSettings(p) - case _ => evalSettingsInTests - } - } - - override val perTestWarmUpIters = 0 - - override val nBenchmarkIters = 0 - - override val okRunTestsWithoutMCLowering: Boolean = true - - implicit def IR = createIR() - - def testCases[A, B](cases: Seq[(A, Expected[B])], f: Feature[A, B]) = { - val table = Table(("x", "y"), cases:_*) - forAll(table) { (x, expectedRes) => - val res = f.checkEquality(x) - val resValue = res.map(_._1) - val (expected, expDetailsOpt) = expectedRes.newResults(ergoTreeVersionInTests) - checkResult(resValue, expected.value, failOnTestVectors = true, - "SigmaDslSpecifiction#testCases: compare expected new result with res = f.checkEquality(x)") - res match { - case Success((value, details)) => - details.cost shouldBe JitCost(expected.verificationCost.get) - expDetailsOpt.foreach(expDetails => - if (details.trace != expDetails.trace) { - printCostDetails(f.script, details) - details.trace shouldBe expDetails.trace - } - ) - } - } - } + override def languageVersion: Byte = VersionContext.JitActivationVersion import TestData._ - override protected def beforeAll(): Unit = { - prepareSamples[BigInt] - prepareSamples[GroupElement] - prepareSamples[AvlTree] - prepareSamples[Box] - prepareSamples[PreHeader] - prepareSamples[Header] - prepareSamples[(BigInt, BigInt)] - prepareSamples[(GroupElement, GroupElement)] - prepareSamples[(AvlTree, AvlTree)] - prepareSamples[(Box, Box)] - prepareSamples[(PreHeader, PreHeader)] - prepareSamples[(Header, Header)] - } - ///===================================================== /// CostDetails shared among test cases ///----------------------------------------------------- @@ -232,17 +125,6 @@ class SigmaDslSpecification extends SigmaDslTesting /// Boolean type operations ///----------------------------------------------------- - property("Boolean methods equivalence") { - val toByte = newFeature((x: Boolean) => x.toByte, "{ (x: Boolean) => x.toByte }") - - val cases = Seq( - (true, Success(1.toByte)), - (false, Success(0.toByte)) - ) - - testCases(cases, toByte) - } - property("BinXor(logical XOR) equivalence") { val binXor = existingFeature((x: (Boolean, Boolean)) => x._1 ^ x._2, "{ (x: (Boolean, Boolean)) => x._1 ^ x._2 }", @@ -1057,31 +939,6 @@ class SigmaDslSpecification extends SigmaDslTesting swapArgs(LE_cases, cost = 1768, newCostDetails = binaryRelationCostDetails(GE, SByte)), ">=", GE.apply)(_ >= _) } - - property("Byte methods equivalence (new features)") { - lazy val toBytes = newFeature((x: Byte) => x.toBytes, "{ (x: Byte) => x.toBytes }") - lazy val toAbs = newFeature((x: Byte) => x.toAbs, "{ (x: Byte) => x.toAbs }") - lazy val compareTo = newFeature( - (x: (Byte, Byte)) => x._1.compareTo(x._2), - "{ (x: (Byte, Byte)) => x._1.compareTo(x._2) }") - - lazy val bitOr = newFeature( - { (x: (Byte, Byte)) => (x._1 | x._2).toByteExact }, - "{ (x: (Byte, Byte)) => (x._1 | x._2).toByteExact }") - - lazy val bitAnd = newFeature( - { (x: (Byte, Byte)) => (x._1 & x._2).toByteExact }, - "{ (x: (Byte, Byte)) => (x._1 & x._2).toByteExact }") - - forAll { x: Byte => - Seq(toBytes, toAbs).foreach(f => f.checkEquality(x)) - } - - forAll { x: (Byte, Byte) => - Seq(compareTo, bitOr, bitAnd).foreach(_.checkEquality(x)) - } - } - property("Short methods equivalence") { SShort.upcast(0.toShort) shouldBe 0.toShort // boundary test case SShort.downcast(0.toShort) shouldBe 0.toShort // boundary test case @@ -1362,29 +1219,6 @@ class SigmaDslSpecification extends SigmaDslTesting ">=", GE.apply)(_ >= _) } - property("Short methods equivalence (new features)") { - lazy val toBytes = newFeature((x: Short) => x.toBytes, "{ (x: Short) => x.toBytes }") - lazy val toAbs = newFeature((x: Short) => x.toAbs, "{ (x: Short) => x.toAbs }") - - lazy val compareTo = newFeature((x: (Short, Short)) => x._1.compareTo(x._2), - "{ (x: (Short, Short)) => x._1.compareTo(x._2) }") - - lazy val bitOr = newFeature( - { (x: (Short, Short)) => (x._1 | x._2).toShortExact }, - "{ (x: (Short, Short)) => x._1 | x._2 }") - - lazy val bitAnd = newFeature( - { (x: (Short, Short)) => (x._1 & x._2).toShortExact }, - "{ (x: (Short, Short)) => x._1 & x._2 }") - - forAll { x: Short => - Seq(toBytes, toAbs).foreach(_.checkEquality(x)) - } - forAll { x: (Short, Short) => - Seq(compareTo, bitOr, bitAnd).foreach(_.checkEquality(x)) - } - } - property("Int methods equivalence") { SInt.upcast(0) shouldBe 0 // boundary test case SInt.downcast(0) shouldBe 0 // boundary test case @@ -1665,28 +1499,6 @@ class SigmaDslSpecification extends SigmaDslTesting ">=", GE.apply)(_ >= _) } - property("Int methods equivalence (new features)") { - lazy val toBytes = newFeature((x: Int) => x.toBytes, "{ (x: Int) => x.toBytes }") - lazy val toAbs = newFeature((x: Int) => x.toAbs, "{ (x: Int) => x.toAbs }") - lazy val compareTo = newFeature((x: (Int, Int)) => x._1.compareTo(x._2), - "{ (x: (Int, Int)) => x._1.compareTo(x._2) }") - - lazy val bitOr = newFeature( - { (x: (Int, Int)) => x._1 | x._2 }, - "{ (x: (Int, Int)) => x._1 | x._2 }") - - lazy val bitAnd = newFeature( - { (x: (Int, Int)) => x._1 & x._2 }, - "{ (x: (Int, Int)) => x._1 & x._2 }") - - forAll { x: Int => - Seq(toBytes, toAbs).foreach(_.checkEquality(x)) - } - forAll { x: (Int, Int) => - Seq(compareTo, bitOr, bitAnd).foreach(_.checkEquality(x)) - } - } - property("Long downcast and upcast identity") { forAll { x: Long => SLong.upcast(x) shouldBe x // boundary test case @@ -1984,28 +1796,6 @@ class SigmaDslSpecification extends SigmaDslTesting ">=", GE.apply)(_ >= _) } - property("Long methods equivalence (new features)") { - lazy val toBytes = newFeature((x: Long) => x.toBytes, "{ (x: Long) => x.toBytes }") - lazy val toAbs = newFeature((x: Long) => x.toAbs, "{ (x: Long) => x.toAbs }") - lazy val compareTo = newFeature((x: (Long, Long)) => x._1.compareTo(x._2), - "{ (x: (Long, Long)) => x._1.compareTo(x._2) }") - - lazy val bitOr = newFeature( - { (x: (Long, Long)) => x._1 | x._2 }, - "{ (x: (Long, Long)) => x._1 | x._2 }") - - lazy val bitAnd = newFeature( - { (x: (Long, Long)) => x._1 & x._2 }, - "{ (x: (Long, Long)) => x._1 & x._2 }") - - forAll { x: Long => - Seq(toBytes, toAbs).foreach(_.checkEquality(x)) - } - forAll { x: (Long, Long) => - Seq(compareTo, bitOr, bitAnd).foreach(_.checkEquality(x)) - } - } - property("BigInt methods equivalence") { verifyCases( { @@ -2264,59 +2054,6 @@ class SigmaDslSpecification extends SigmaDslTesting ">=", GE.apply)(o.gteq(_, _)) } - property("BigInt methods equivalence (new features)") { - // TODO v6.0: the behavior of `upcast` for BigInt is different from all other Numeric types (see https://github.com/ScorexFoundation/sigmastate-interpreter/issues/877) - // The `Upcast(bigInt, SBigInt)` node is never produced by ErgoScript compiler, but is still valid ErgoTree. - // It makes sense to fix this inconsistency as part of upcoming forks - assertExceptionThrown( - SBigInt.upcast(CBigInt(new BigInteger("0", 16)).asInstanceOf[AnyVal]), - _.getMessage.contains("Cannot upcast value") - ) - - // TODO v6.0: the behavior of `downcast` for BigInt is different from all other Numeric types (see https://github.com/ScorexFoundation/sigmastate-interpreter/issues/877) - // The `Downcast(bigInt, SBigInt)` node is never produced by ErgoScript compiler, but is still valid ErgoTree. - // It makes sense to fix this inconsistency as part of HF - assertExceptionThrown( - SBigInt.downcast(CBigInt(new BigInteger("0", 16)).asInstanceOf[AnyVal]), - _.getMessage.contains("Cannot downcast value") - ) - - val toByte = newFeature((x: BigInt) => x.toByte, - "{ (x: BigInt) => x.toByte }", - FuncValue(Vector((1, SBigInt)), Downcast(ValUse(1, SBigInt), SByte))) - - val toShort = newFeature((x: BigInt) => x.toShort, - "{ (x: BigInt) => x.toShort }", - FuncValue(Vector((1, SBigInt)), Downcast(ValUse(1, SBigInt), SShort))) - - val toInt = newFeature((x: BigInt) => x.toInt, - "{ (x: BigInt) => x.toInt }", - FuncValue(Vector((1, SBigInt)), Downcast(ValUse(1, SBigInt), SInt))) - - val toLong = newFeature((x: BigInt) => x.toLong, - "{ (x: BigInt) => x.toLong }", - FuncValue(Vector((1, SBigInt)), Downcast(ValUse(1, SBigInt), SLong))) - - lazy val toBytes = newFeature((x: BigInt) => x.toBytes, "{ (x: BigInt) => x.toBytes }") - lazy val toAbs = newFeature((x: BigInt) => x.toAbs, "{ (x: BigInt) => x.toAbs }") - - lazy val compareTo = newFeature((x: (BigInt, BigInt)) => x._1.compareTo(x._2), - "{ (x: (BigInt, BigInt)) => x._1.compareTo(x._2) }") - - lazy val bitOr = newFeature({ (x: (BigInt, BigInt)) => x._1 | x._2 }, - "{ (x: (BigInt, BigInt)) => x._1 | x._2 }") - - lazy val bitAnd = newFeature({ (x: (BigInt, BigInt)) => x._1 & x._2 }, - "{ (x: (BigInt, BigInt)) => x._1 & x._2 }") - - forAll { x: BigInt => - Seq(toByte, toShort, toInt, toLong, toBytes, toAbs).foreach(_.checkEquality(x)) - } - forAll { x: (BigInt, BigInt) => - Seq(compareTo, bitOr, bitAnd).foreach(_.checkEquality(x)) - } - } - /** Executed a series of test cases of NEQ operation verify using two _different_ * data instances `x` and `y`. * @param cost the expected cost of `verify` (the same for all cases) @@ -4051,16 +3788,6 @@ class SigmaDslSpecification extends SigmaDslTesting ))) } - property("Box properties equivalence (new features)") { - // TODO v6.0: related to https://github.com/ScorexFoundation/sigmastate-interpreter/issues/416 - val getReg = newFeature((x: Box) => x.getReg[Int](1).get, - "{ (x: Box) => x.getReg[Int](1).get }") - - forAll { box: Box => - Seq(getReg).foreach(_.checkEquality(box)) - } - } - property("Conditional access to registers") { def boxWithRegisters(regs: AdditionalRegisters): Box = { SigmaDsl.Box(testBox(20, TrueTree, 0, Seq(), regs)) @@ -7638,36 +7365,6 @@ class SigmaDslSpecification extends SigmaDslTesting preGeneratedSamples = Some(samples)) } - // TODO v6.0 (3h): https://github.com/ScorexFoundation/sigmastate-interpreter/issues/479 - property("Coll find method equivalence") { - val find = newFeature((x: Coll[Int]) => x.find({ (v: Int) => v > 0 }), - "{ (x: Coll[Int]) => x.find({ (v: Int) => v > 0} ) }") - forAll { x: Coll[Int] => - find.checkEquality(x) - } - } - - // TODO v6.0 (3h): https://github.com/ScorexFoundation/sigmastate-interpreter/issues/418 - property("Coll bitwise methods equivalence") { - val shiftRight = newFeature( - { (x: Coll[Boolean]) => - if (x.size > 2) x.slice(0, x.size - 2) else Colls.emptyColl[Boolean] - }, - "{ (x: Coll[Boolean]) => x >> 2 }") - forAll { x: Array[Boolean] => - shiftRight.checkEquality(Colls.fromArray(x)) - } - } - - // TODO v6.0 (3h): https://github.com/ScorexFoundation/sigmastate-interpreter/issues/479 - property("Coll diff methods equivalence") { - val diff = newFeature((x: (Coll[Int], Coll[Int])) => x._1.diff(x._2), - "{ (x: (Coll[Int], Coll[Int])) => x._1.diff(x._2) }") - forAll { (x: Coll[Int], y: Coll[Int]) => - diff.checkEquality((x, y)) - } - } - property("Coll fold method equivalence") { val n = ExactNumeric.IntIsExactNumeric val costDetails1 = TracedCost( @@ -9079,17 +8776,6 @@ class SigmaDslSpecification extends SigmaDslTesting ) )) } - // TODO v6.0: implement Option.fold (see https://github.com/ScorexFoundation/sigmastate-interpreter/issues/479) - property("Option new methods") { - val n = ExactNumeric.LongIsExactNumeric - val fold = newFeature({ (x: Option[Long]) => x.fold(5.toLong)( (v: Long) => n.plus(v, 1) ) }, - "{ (x: Option[Long]) => x.fold(5, { (v: Long) => v + 1 }) }") - - forAll { x: Option[Long] => - Seq(fold).map(_.checkEquality(x)) - } - } - property("Option fold workaround method") { val costDetails1 = TracedCost( traceBase ++ Array( @@ -9525,24 +9211,6 @@ class SigmaDslSpecification extends SigmaDslTesting preGeneratedSamples = Some(Seq())) } - // TODO v6.0 (3h): implement allZK func https://github.com/ScorexFoundation/sigmastate-interpreter/issues/543 - property("allZK equivalence") { - lazy val allZK = newFeature((x: Coll[SigmaProp]) => SigmaDsl.allZK(x), - "{ (x: Coll[SigmaProp]) => allZK(x) }") - forAll { x: Coll[SigmaProp] => - allZK.checkEquality(x) - } - } - - // TODO v6.0 (3h): implement anyZK func https://github.com/ScorexFoundation/sigmastate-interpreter/issues/543 - property("anyZK equivalence") { - lazy val anyZK = newFeature((x: Coll[SigmaProp]) => SigmaDsl.anyZK(x), - "{ (x: Coll[SigmaProp]) => anyZK(x) }") - forAll { x: Coll[SigmaProp] => - anyZK.checkEquality(x) - } - } - property("allOf equivalence") { def costDetails(i: Int) = TracedCost(traceBase :+ ast.SeqCostItem(CompanionDesc(AND), PerItemCost(JitCost(10), JitCost(5), 32), i)) verifyCases( diff --git a/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala b/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala new file mode 100644 index 0000000000..e82bcd886b --- /dev/null +++ b/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala @@ -0,0 +1,348 @@ +package sigma + +import sigma.ast.{Apply, Downcast, FixedCost, FixedCostItem, FuncValue, GetVar, Global, JitCost, MethodCall, NamedDesc, OptionGet, SBigInt, SByte, SGlobalMethods, SInt, SLong, SShort, STypeVar, ValUse} +import sigma.data.{CBigInt, ExactNumeric, RType} +import sigma.eval.{SigmaDsl, TracedCost} +import sigma.util.Extensions.{BooleanOps, ByteOps, IntOps, LongOps} +import sigmastate.exceptions.MethodNotFound + +import java.math.BigInteger +import scala.util.Success + +/** This suite tests all operations for v6.0 version of the language. + * The base classes establish the infrastructure for the tests. + * + * @see SigmaDslSpecificationBase + */ +class LanguageSpecificationV6 extends LanguageSpecificationBase { suite => + override def languageVersion: Byte = VersionContext.V6SoftForkVersion + + implicit override def evalSettings = super.evalSettings.copy(printTestVectors = true) + + + val baseTrace = Array( + FixedCostItem(Apply), + FixedCostItem(FuncValue), + FixedCostItem(GetVar), + FixedCostItem(OptionGet), + FixedCostItem(FuncValue.AddToEnvironmentDesc, FixedCost(JitCost(5))) + ) + + property("Boolean.toByte") { + val toByte = newFeature((x: Boolean) => x.toByte, "{ (x: Boolean) => x.toByte }", + sinceVersion = VersionContext.V6SoftForkVersion + ) + + val cases = Seq( + (true, Success(1.toByte)), + (false, Success(0.toByte)) + ) + + if (toByte.isSupportedIn(VersionContext.current)) { + // TODO v6.0: implement as part of https://github.com/ScorexFoundation/sigmastate-interpreter/pull/932 + assertExceptionThrown( + testCases(cases, toByte), + rootCauseLike[MethodNotFound]("Cannot find method") + ) + } + else + testCases(cases, toByte) + } + + property("Byte methods equivalence (new features)") { + // TODO v6.0: implement as part of https://github.com/ScorexFoundation/sigmastate-interpreter/issues/474 + if (activatedVersionInTests < VersionContext.V6SoftForkVersion) { + // NOTE, for such versions the new features are not supported + // which is checked below + + lazy val toAbs = newFeature((x: Byte) => x.toAbs, "{ (x: Byte) => x.toAbs }", + sinceVersion = VersionContext.V6SoftForkVersion) + + lazy val compareTo = newFeature( + (x: (Byte, Byte)) => x._1.compareTo(x._2), + "{ (x: (Byte, Byte)) => x._1.compareTo(x._2) }", + sinceVersion = VersionContext.V6SoftForkVersion) + + lazy val bitOr = newFeature( + { (x: (Byte, Byte)) => (x._1 | x._2).toByteExact }, + "{ (x: (Byte, Byte)) => (x._1 | x._2) }", + sinceVersion = VersionContext.V6SoftForkVersion) + + lazy val bitAnd = newFeature( + { (x: (Byte, Byte)) => (x._1 & x._2).toByteExact }, + "{ (x: (Byte, Byte)) => (x._1 & x._2) }", + sinceVersion = VersionContext.V6SoftForkVersion) + + forAll { x: Byte => + Seq(toAbs).foreach(f => f.checkEquality(x)) + } + + forAll { x: (Byte, Byte) => + Seq(compareTo, bitOr, bitAnd).foreach(_.checkEquality(x)) + } + } + } + + // TODO v6.0: enable as part of https://github.com/ScorexFoundation/sigmastate-interpreter/issues/474 + property("Short methods equivalence (new features)") { + if (activatedVersionInTests < VersionContext.V6SoftForkVersion) { + // NOTE, for such versions the new features are not supported + // which is checked below + + lazy val toAbs = newFeature((x: Short) => x.toAbs, "{ (x: Short) => x.toAbs }", + sinceVersion = VersionContext.V6SoftForkVersion) + + lazy val compareTo = newFeature((x: (Short, Short)) => x._1.compareTo(x._2), + "{ (x: (Short, Short)) => x._1.compareTo(x._2) }", + sinceVersion = VersionContext.V6SoftForkVersion) + + lazy val bitOr = newFeature( + { (x: (Short, Short)) => (x._1 | x._2).toShortExact }, + "{ (x: (Short, Short)) => x._1 | x._2 }", + sinceVersion = VersionContext.V6SoftForkVersion) + + lazy val bitAnd = newFeature( + { (x: (Short, Short)) => (x._1 & x._2).toShortExact }, + "{ (x: (Short, Short)) => x._1 & x._2 }", + sinceVersion = VersionContext.V6SoftForkVersion) + + forAll { x: Short => + Seq(toAbs).foreach(_.checkEquality(x)) + } + forAll { x: (Short, Short) => + Seq(compareTo, bitOr, bitAnd).foreach(_.checkEquality(x)) + } + } + } + + property("Int methods equivalence (new features)") { + if (activatedVersionInTests < VersionContext.V6SoftForkVersion) { + // NOTE, for such versions the new features are not supported + // which is checked below + lazy val toAbs = newFeature((x: Int) => x.toAbs, "{ (x: Int) => x.toAbs }", + sinceVersion = VersionContext.V6SoftForkVersion) + lazy val compareTo = newFeature((x: (Int, Int)) => x._1.compareTo(x._2), + "{ (x: (Int, Int)) => x._1.compareTo(x._2) }", + sinceVersion = VersionContext.V6SoftForkVersion) + lazy val bitOr = newFeature( + { (x: (Int, Int)) => x._1 | x._2 }, + "{ (x: (Int, Int)) => x._1 | x._2 }", + sinceVersion = VersionContext.V6SoftForkVersion) + lazy val bitAnd = newFeature( + { (x: (Int, Int)) => x._1 & x._2 }, + "{ (x: (Int, Int)) => x._1 & x._2 }", + sinceVersion = VersionContext.V6SoftForkVersion) + forAll { x: Int => + Seq(toAbs).foreach(_.checkEquality(x)) + } + forAll { x: (Int, Int) => + Seq(compareTo, bitOr, bitAnd).foreach(_.checkEquality(x)) + } + } + } + + property("Long methods equivalence (new features)") { + if (activatedVersionInTests < VersionContext.V6SoftForkVersion) { + // NOTE, for such versions the new features are not supported + // which is checked below + lazy val toAbs = newFeature((x: Long) => x.toAbs, "{ (x: Long) => x.toAbs }", + sinceVersion = VersionContext.V6SoftForkVersion) + lazy val compareTo = newFeature((x: (Long, Long)) => x._1.compareTo(x._2), + "{ (x: (Long, Long)) => x._1.compareTo(x._2) }", + sinceVersion = VersionContext.V6SoftForkVersion) + + lazy val bitOr = newFeature( + { (x: (Long, Long)) => x._1 | x._2 }, + "{ (x: (Long, Long)) => x._1 | x._2 }", + sinceVersion = VersionContext.V6SoftForkVersion) + + lazy val bitAnd = newFeature( + { (x: (Long, Long)) => x._1 & x._2 }, + "{ (x: (Long, Long)) => x._1 & x._2 }", + sinceVersion = VersionContext.V6SoftForkVersion) + + forAll { x: Long => + Seq(toAbs).foreach(_.checkEquality(x)) + } + forAll { x: (Long, Long) => + Seq(compareTo, bitOr, bitAnd).foreach(_.checkEquality(x)) + } + } + + } + + property("BigInt methods equivalence (new features)") { + // TODO v6.0: the behavior of `upcast` for BigInt is different from all other Numeric types (see https://github.com/ScorexFoundation/sigmastate-interpreter/issues/877) + // The `Upcast(bigInt, SBigInt)` node is never produced by ErgoScript compiler, but is still valid ErgoTree. + // It makes sense to fix this inconsistency as part of upcoming forks + assertExceptionThrown( + SBigInt.upcast(CBigInt(new BigInteger("0", 16)).asInstanceOf[AnyVal]), + _.getMessage.contains("Cannot upcast value") + ) + + // TODO v6.0: the behavior of `downcast` for BigInt is different from all other Numeric types (see https://github.com/ScorexFoundation/sigmastate-interpreter/issues/877) + // The `Downcast(bigInt, SBigInt)` node is never produced by ErgoScript compiler, but is still valid ErgoTree. + // It makes sense to fix this inconsistency as part of HF + assertExceptionThrown( + SBigInt.downcast(CBigInt(new BigInteger("0", 16)).asInstanceOf[AnyVal]), + _.getMessage.contains("Cannot downcast value") + ) + + if (activatedVersionInTests < VersionContext.V6SoftForkVersion) { + // NOTE, for such versions the new features are not supported + // which is checked below + val toByte = newFeature((x: BigInt) => x.toByte, + "{ (x: BigInt) => x.toByte }", + FuncValue(Vector((1, SBigInt)), Downcast(ValUse(1, SBigInt), SByte)), + sinceVersion = VersionContext.V6SoftForkVersion) + val toShort = newFeature((x: BigInt) => x.toShort, + "{ (x: BigInt) => x.toShort }", + FuncValue(Vector((1, SBigInt)), Downcast(ValUse(1, SBigInt), SShort)), + sinceVersion = VersionContext.V6SoftForkVersion) + val toInt = newFeature((x: BigInt) => x.toInt, + "{ (x: BigInt) => x.toInt }", + FuncValue(Vector((1, SBigInt)), Downcast(ValUse(1, SBigInt), SInt)), + sinceVersion = VersionContext.V6SoftForkVersion) + val toLong = newFeature((x: BigInt) => x.toLong, + "{ (x: BigInt) => x.toLong }", + FuncValue(Vector((1, SBigInt)), Downcast(ValUse(1, SBigInt), SLong)), + sinceVersion = VersionContext.V6SoftForkVersion) + lazy val toAbs = newFeature((x: BigInt) => x.toAbs, "{ (x: BigInt) => x.toAbs }", + sinceVersion = VersionContext.V6SoftForkVersion) + lazy val compareTo = newFeature((x: (BigInt, BigInt)) => x._1.compareTo(x._2), + "{ (x: (BigInt, BigInt)) => x._1.compareTo(x._2) }", + sinceVersion = VersionContext.V6SoftForkVersion) + lazy val bitOr = newFeature({ (x: (BigInt, BigInt)) => x._1 | x._2 }, + "{ (x: (BigInt, BigInt)) => x._1 | x._2 }", + sinceVersion = VersionContext.V6SoftForkVersion) + lazy val bitAnd = newFeature({ (x: (BigInt, BigInt)) => x._1 & x._2 }, + "{ (x: (BigInt, BigInt)) => x._1 & x._2 }", + sinceVersion = VersionContext.V6SoftForkVersion) + + forAll { x: BigInt => + Seq(toByte, toShort, toInt, toLong, toAbs).foreach(_.checkEquality(x)) + } + forAll { x: (BigInt, BigInt) => + Seq(compareTo, bitOr, bitAnd).foreach(_.checkEquality(x)) + } + } + } + + property("Box properties equivalence (new features)") { + // TODO v6.0: related to https://github.com/ScorexFoundation/sigmastate-interpreter/issues/416 + val getReg = newFeature((x: Box) => x.getReg[Int](1).get, + "{ (x: Box) => x.getReg[Int](1).get }", + sinceVersion = VersionContext.V6SoftForkVersion) + + if (activatedVersionInTests < VersionContext.V6SoftForkVersion) { + // NOTE, for such versions getReg is not supported + // which is checked below + + forAll { box: Box => + Seq(getReg).foreach(_.checkEquality(box)) + } + } + } + + // TODO v6.0 (3h): https://github.com/ScorexFoundation/sigmastate-interpreter/issues/479 + property("Coll find method equivalence") { + val find = newFeature((x: Coll[Int]) => x.find({ (v: Int) => v > 0 }), + "{ (x: Coll[Int]) => x.find({ (v: Int) => v > 0} ) }", + sinceVersion = VersionContext.V6SoftForkVersion) + + if (activatedVersionInTests < VersionContext.V6SoftForkVersion) { + // NOTE, for such versions getReg is not supported + // which is checked below + + forAll { x: Coll[Int] => + find.checkEquality(x) + } + } + } + + // TODO v6.0 (3h): https://github.com/ScorexFoundation/sigmastate-interpreter/issues/418 + property("Coll bitwise methods equivalence") { + val shiftRight = newFeature( + { (x: Coll[Boolean]) => + if (x.size > 2) x.slice(0, x.size - 2) else Colls.emptyColl[Boolean] + }, + "{ (x: Coll[Boolean]) => x >> 2 }", + sinceVersion = VersionContext.V6SoftForkVersion) + + if (activatedVersionInTests < VersionContext.V6SoftForkVersion) { + // NOTE, for such versions getReg is not supported + // which is checked below + + forAll { x: Array[Boolean] => + shiftRight.checkEquality(Colls.fromArray(x)) + } + } + } + + // TODO v6.0 (3h): https://github.com/ScorexFoundation/sigmastate-interpreter/issues/479 + property("Coll diff methods equivalence") { + val diff = newFeature((x: (Coll[Int], Coll[Int])) => x._1.diff(x._2), + "{ (x: (Coll[Int], Coll[Int])) => x._1.diff(x._2) }", + sinceVersion = VersionContext.V6SoftForkVersion) + + if (activatedVersionInTests < VersionContext.V6SoftForkVersion) { + // NOTE, for such versions getReg is not supported + // which is checked below + + forAll { (x: Coll[Int], y: Coll[Int]) => + diff.checkEquality((x, y)) + } + } + } + + // TODO v6.0: implement Option.fold (see https://github.com/ScorexFoundation/sigmastate-interpreter/issues/479) + property("Option new methods") { + val n = ExactNumeric.LongIsExactNumeric + val fold = newFeature({ (x: Option[Long]) => x.fold(5.toLong)( (v: Long) => n.plus(v, 1) ) }, + "{ (x: Option[Long]) => x.fold(5, { (v: Long) => v + 1 }) }", + sinceVersion = VersionContext.V6SoftForkVersion) + + if (activatedVersionInTests < VersionContext.V6SoftForkVersion) { + // NOTE, for such versions getReg is not supported + // which is checked below + + forAll { x: Option[Long] => + Seq(fold).map(_.checkEquality(x)) + } + } + } + + // TODO v6.0 (3h): implement allZK func https://github.com/ScorexFoundation/sigmastate-interpreter/issues/543 + property("allZK equivalence") { + lazy val allZK = newFeature((x: Coll[SigmaProp]) => SigmaDsl.allZK(x), + "{ (x: Coll[SigmaProp]) => allZK(x) }", + sinceVersion = VersionContext.V6SoftForkVersion) + + if (activatedVersionInTests < VersionContext.V6SoftForkVersion) { + // NOTE, for such versions getReg is not supported + // which is checked below + + forAll { x: Coll[SigmaProp] => + allZK.checkEquality(x) + } + } + } + + // TODO v6.0 (3h): implement anyZK func https://github.com/ScorexFoundation/sigmastate-interpreter/issues/543 + property("anyZK equivalence") { + lazy val anyZK = newFeature((x: Coll[SigmaProp]) => SigmaDsl.anyZK(x), + "{ (x: Coll[SigmaProp]) => anyZK(x) }", + sinceVersion = VersionContext.V6SoftForkVersion) + + if (activatedVersionInTests < VersionContext.V6SoftForkVersion) { + // NOTE, for such versions getReg is not supported + // which is checked below + + forAll { x: Coll[SigmaProp] => + anyZK.checkEquality(x) + } + } + } + + +} diff --git a/sc/shared/src/test/scala/sigma/SigmaDslTesting.scala b/sc/shared/src/test/scala/sigma/SigmaDslTesting.scala index 31e873699b..37fb0e6503 100644 --- a/sc/shared/src/test/scala/sigma/SigmaDslTesting.scala +++ b/sc/shared/src/test/scala/sigma/SigmaDslTesting.scala @@ -123,6 +123,9 @@ class SigmaDslTesting extends AnyPropSpec /** Type descriptor for type B. */ def tB: RType[B] + /** Checks if this feature is supported in the given version context. */ + def isSupportedIn(vc: VersionContext): Boolean + /** Script containing this feature. */ def script: String @@ -176,14 +179,42 @@ class SigmaDslTesting extends AnyPropSpec true } + /** Checks the result of feature execution against expected result. + * If settings.failOnTestVectors == true, then print out actual cost results + * + * @param res the result of feature execution + * @param expected the expected result + */ + protected def checkResultAgainstExpected(res: Try[(B, CostDetails)], expected: Expected[B]): Unit = { + val newRes = expected.newResults(ergoTreeVersionInTests) + val expectedTrace = newRes._2.fold(Seq.empty[CostItem])(_.trace) + if (expectedTrace.isEmpty) { + // new cost expectation is missing, print out actual cost results + if (evalSettings.printTestVectors) { + res.foreach { case (_, newDetails) => + printCostDetails(script, newDetails) + } + } + } + else { + // new cost expectation is specified, compare it with the actual result + res.foreach { case (_, newDetails) => + if (newDetails.trace != expectedTrace) { + printCostDetails(script, newDetails) + newDetails.trace shouldBe expectedTrace + } + } + } + } + /** v3 and v4 implementation*/ - private var _oldF: CompiledFunc[A, B] = _ + private var _oldF: Try[CompiledFunc[A, B]] = _ def oldF: CompiledFunc[A, B] = { if (_oldF == null) { - _oldF = oldImpl() - checkExpectedExprIn(_oldF) + _oldF = Try(oldImpl()) + _oldF.foreach(cf => checkExpectedExprIn(cf)) } - _oldF + _oldF.getOrThrow } /** v5 implementation*/ @@ -252,13 +283,21 @@ class SigmaDslTesting extends AnyPropSpec fail( s"""Should succeed with the same value or fail with the same exception, but was: - |First result: $b1 - |Second result: $b2 + |First result: ${errorWithStack(b1)} + |Second result: ${errorWithStack(b2)} |Root cause: $cause |""".stripMargin) } } + private def errorWithStack[A](e: Try[A]): String = e match { + case Failure(t) => + val sw = new java.io.StringWriter + t.printStackTrace(new java.io.PrintWriter(sw)) + sw.toString + case _ => e.toString + } + /** Creates a new ErgoLikeContext using given [[CContext]] as template. * Copies most of the data from ctx and the missing data is taken from the args. * This is a helper method to be used in tests only. @@ -501,6 +540,8 @@ class SigmaDslTesting extends AnyPropSpec implicit val cs = compilerSettingsInTests + override def isSupportedIn(vc: VersionContext): Boolean = true + /** in v5.x the old and the new interpreters are the same */ override val oldImpl = () => funcJit[A, B](script) override val newImpl = () => funcJit[A, B](script) @@ -611,28 +652,10 @@ class SigmaDslTesting extends AnyPropSpec checkResult(funcRes.map(_._1), expected.value, failOnTestVectors, "ExistingFeature#verifyCase: ") - val newRes = expected.newResults(ergoTreeVersionInTests) - val expectedTrace = newRes._2.fold(Seq.empty[CostItem])(_.trace) - if (expectedTrace.isEmpty) { - // new cost expectation is missing, print out actual cost results - if (evalSettings.printTestVectors) { - funcRes.foreach { case (_, newDetails) => - printCostDetails(script, newDetails) - } - } - } - else { - // new cost expectation is specified, compare it with the actual result - funcRes.foreach { case (_, newDetails) => - if (newDetails.trace != expectedTrace) { - printCostDetails(script, newDetails) - newDetails.trace shouldBe expectedTrace - } - } - } - + checkResultAgainstExpected(funcRes, expected) checkVerify(input, expected) } + } /** Descriptor of a language feature which is changed in v5.0. @@ -671,6 +694,8 @@ class SigmaDslTesting extends AnyPropSpec implicit val cs = compilerSettingsInTests + override def isSupportedIn(vc: VersionContext): Boolean = true + /** Apply given function to the context variable 1 */ private def getApplyExpr(funcValue: SValue) = { val sType = Evaluation.rtypeToSType(RType[A]) @@ -833,8 +858,17 @@ class SigmaDslTesting extends AnyPropSpec * This in not yet implemented and will be finished in v6.0. * In v5.0 is only checks that some features are NOT implemented, i.e. work for * negative tests. + * + * @param sinceVersion language version (protocol) when the feature is introduced, see + * [[VersionContext]] + * @param script the script to be tested against semantic function + * @param scalaFuncNew semantic function which defines expected behavior of the given script + * @param expectedExpr expected ErgoTree expression which corresponds to the given script + * @param printExpectedExpr if true, print the test vector for expectedExpr when it is None + * @param logScript if true, log scripts to console */ case class NewFeature[A, B]( + sinceVersion: Byte, script: String, override val scalaFuncNew: A => B, expectedExpr: Option[SValue], @@ -842,25 +876,30 @@ class SigmaDslTesting extends AnyPropSpec logScript: Boolean = LogScriptDefault )(implicit IR: IRContext, override val evalSettings: EvalSettings, val tA: RType[A], val tB: RType[B]) extends Feature[A, B] { + + override def isSupportedIn(vc: VersionContext): Boolean = + vc.activatedVersion >= sinceVersion + override def scalaFunc: A => B = { x => sys.error(s"Semantic Scala function is not defined for old implementation: $this") } implicit val cs = compilerSettingsInTests - /** in v5.x the old and the new interpreters are the same */ + /** Starting from v5.x the old and the new interpreters are the same */ val oldImpl = () => funcJit[A, B](script) - val newImpl = oldImpl // funcJit[A, B](script) // TODO v6.0: use actual new implementation here (https://github.com/ScorexFoundation/sigmastate-interpreter/issues/910) + val newImpl = oldImpl - /** In v5.x this method just checks the old implementations fails on the new feature. */ + /** Check the new implementation works equal to the semantic function. + * This method also checks the old implementations fails on the new feature. + */ override def checkEquality(input: A, logInputOutput: Boolean = false): Try[(B, CostDetails)] = { - val oldRes = Try(oldF(input)) - oldRes.isFailure shouldBe true - if (!(newImpl eq oldImpl)) { - val newRes = VersionContext.withVersions(activatedVersionInTests, ergoTreeVersionInTests) { - checkEq(scalaFuncNew)(newF)(input) - } + if (this.isSupportedIn(VersionContext.current)) { + checkEq(scalaFuncNew)(newF)(input) + } else { + val oldRes = Try(oldF(input)) + oldRes.isFailure shouldBe true + oldRes } - oldRes } override def checkExpected(input: A, expected: Expected[B]): Unit = { @@ -880,7 +919,10 @@ class SigmaDslTesting extends AnyPropSpec printTestCases: Boolean, failOnTestVectors: Boolean): Unit = { val res = checkEquality(input, printTestCases).map(_._1) - res.isFailure shouldBe true + if (this.isSupportedIn(VersionContext.current)) { + res shouldBe expectedResult + } else + res.isFailure shouldBe true Try(scalaFuncNew(input)) shouldBe expectedResult } @@ -889,8 +931,11 @@ class SigmaDslTesting extends AnyPropSpec printTestCases: Boolean, failOnTestVectors: Boolean): Unit = { val funcRes = checkEquality(input, printTestCases) - funcRes.isFailure shouldBe true - Try(scalaFunc(input)) shouldBe expected.value + if (this.isSupportedIn(VersionContext.current)) { + checkResultAgainstExpected(funcRes, expected) + } else + funcRes.isFailure shouldBe true + Try(scalaFuncNew(input)) shouldBe expected.value } } @@ -958,6 +1003,20 @@ class SigmaDslTesting extends AnyPropSpec } } + /** Used when the old and new value are the same for all versions + * and the expected costs are not specified. + * + * @param value expected result of tested function + * @param expectedDetails expected cost details for all versions + */ + def apply[A](value: Try[A], expectedDetails: CostDetails): Expected[A] = + new Expected(ExpectedResult(value, None)) { + override val newResults = defaultNewResults.map { + case (ExpectedResult(v, _), _) => + (ExpectedResult(v, None), Some(expectedDetails)) + } + } + /** Used when the old and new value and costs are the same for all versions. * * @param value expected result of tested function @@ -1045,6 +1104,7 @@ class SigmaDslTesting extends AnyPropSpec /** Describes a NEW language feature which must NOT be supported in v4 and * must BE supported in v5 of the language. * + * @param sinceVersion language version (protocol) when the feature is introduced, see [[VersionContext]] * @param scalaFunc semantic function which defines expected behavior of the given script * @param script the script to be tested against semantic function * @param expectedExpr expected ErgoTree expression which corresponds to the given script @@ -1052,9 +1112,9 @@ class SigmaDslTesting extends AnyPropSpec * various ways */ def newFeature[A: RType, B: RType] - (scalaFunc: A => B, script: String, expectedExpr: SValue = null) + (scalaFunc: A => B, script: String, expectedExpr: SValue = null, sinceVersion: Byte = VersionContext.JitActivationVersion) (implicit IR: IRContext, es: EvalSettings): Feature[A, B] = { - NewFeature(script, scalaFunc, Option(expectedExpr)) + NewFeature(sinceVersion, script, scalaFunc, Option(expectedExpr)) } val contextGen: Gen[Context] = ergoLikeContextGen.map(c => c.toSigmaContext()) diff --git a/sc/shared/src/test/scala/sigmastate/CompilerCrossVersionProps.scala b/sc/shared/src/test/scala/sigmastate/CompilerCrossVersionProps.scala index 89d15dd4df..4062f13686 100644 --- a/sc/shared/src/test/scala/sigmastate/CompilerCrossVersionProps.scala +++ b/sc/shared/src/test/scala/sigmastate/CompilerCrossVersionProps.scala @@ -12,12 +12,11 @@ trait CompilerCrossVersionProps extends CrossVersionProps with CompilerTestsBase (implicit pos: Position): Unit = { super.property(testName, testTags:_*)(testFun) - val testName2 = s"${testName}_MCLowering" - super.property2(testName2, testTags:_*) { - if (okRunTestsWithoutMCLowering) { - _lowerMethodCalls.withValue(false) { - testFun_Run(testName2, testFun) - } + if (okRunTestsWithoutMCLowering) { + val testName2 = s"${testName}_MCLowering" + _lowerMethodCalls.withValue(false) { + // run testFun for all versions again, but now with this flag + super.property(testName2, testTags:_*)(testFun) } } } diff --git a/sc/shared/src/test/scala/sigmastate/lang/SigmaBinderTest.scala b/sc/shared/src/test/scala/sigmastate/lang/SigmaBinderTest.scala index b4b4ad20cd..aa552e9b69 100644 --- a/sc/shared/src/test/scala/sigmastate/lang/SigmaBinderTest.scala +++ b/sc/shared/src/test/scala/sigmastate/lang/SigmaBinderTest.scala @@ -10,10 +10,12 @@ import sigma.ast.syntax.SValue import sigmastate._ import sigmastate.interpreter.Interpreter.ScriptEnv import SigmaPredef.PredefinedFuncRegistry +import sigma.VersionContext import sigma.ast.syntax._ import sigma.compiler.phases.SigmaBinder import sigma.eval.SigmaDsl import sigma.exceptions.BinderException +import sigmastate.helpers.SigmaPPrint class SigmaBinderTest extends AnyPropSpec with ScalaCheckPropertyChecks with Matchers with LangTests { import StdSigmaBuilder._ @@ -29,6 +31,17 @@ class SigmaBinderTest extends AnyPropSpec with ScalaCheckPropertyChecks with Mat res } + /** Checks that parsing and binding results in the expected value. + * @return the inferred type of the expression + */ + def checkBound(env: ScriptEnv, x: String, expected: SValue) = { + val bound = bind(env, x) + if (expected != bound) { + SigmaPPrint.pprintln(bound, width = 100) + } + bound shouldBe expected + } + private def fail(env: ScriptEnv, x: String, expectedLine: Int, expectedCol: Int): Unit = { val builder = TransformingSigmaBuilder val ast = SigmaParser(x).get.value diff --git a/sc/shared/src/test/scala/sigmastate/lang/SigmaTyperTest.scala b/sc/shared/src/test/scala/sigmastate/lang/SigmaTyperTest.scala index 6b93b098ea..3b2e130100 100644 --- a/sc/shared/src/test/scala/sigmastate/lang/SigmaTyperTest.scala +++ b/sc/shared/src/test/scala/sigmastate/lang/SigmaTyperTest.scala @@ -21,6 +21,7 @@ import sigma.serialization.generators.ObjectGenerators import sigma.ast.Select import sigma.compiler.phases.{SigmaBinder, SigmaTyper} import sigma.exceptions.TyperException +import sigmastate.helpers.SigmaPPrint class SigmaTyperTest extends AnyPropSpec with ScalaCheckPropertyChecks with Matchers with LangTests with ObjectGenerators { @@ -28,6 +29,7 @@ class SigmaTyperTest extends AnyPropSpec private val predefFuncRegistry = new PredefinedFuncRegistry(StdSigmaBuilder) import predefFuncRegistry._ + /** Checks that parsing, binding and typing of `x` results in the given expected value. */ def typecheck(env: ScriptEnv, x: String, expected: SValue = null): SType = { try { val builder = TransformingSigmaBuilder @@ -39,7 +41,12 @@ class SigmaTyperTest extends AnyPropSpec val typer = new SigmaTyper(builder, predefinedFuncRegistry, typeEnv, lowerMethodCalls = true) val typed = typer.typecheck(bound) assertSrcCtxForAllNodes(typed) - if (expected != null) typed shouldBe expected + if (expected != null) { + if (expected != typed) { + SigmaPPrint.pprintln(typed, width = 100) + } + typed shouldBe expected + } typed.tpe } catch { case e: Exception => throw e From 37ac9212daf09fe899dd9b7981668f1c0a69e979 Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Thu, 6 Jun 2024 16:34:40 +0300 Subject: [PATCH 128/314] BasicOpsSpecification tests for serialize --- .../utxo/BasicOpsSpecification.scala | 106 ++++++++++++++++++ 1 file changed, 106 insertions(+) diff --git a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala index 79701d6e07..29443406c5 100644 --- a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala @@ -2,7 +2,10 @@ package sigmastate.utxo import org.ergoplatform.ErgoBox.{AdditionalRegisters, R6, R8} import org.ergoplatform._ +import scorex.util.encode.Base16 import sigma.Extensions.ArrayOps +import sigma.SigmaTestingData +import sigma.VersionContext.V6SoftForkVersion import sigma.ast.SCollection.SByteArray import sigma.ast.SType.AnyOps import sigma.data.{AvlTreeData, CAnyValue, CSigmaDslBuilder} @@ -19,6 +22,7 @@ import sigmastate.interpreter.Interpreter._ import sigma.ast.Apply import sigma.eval.EvalSettings import sigma.exceptions.InvalidType +import sigmastate.utils.Helpers import sigmastate.utils.Helpers._ import java.math.BigInteger @@ -157,6 +161,108 @@ class BasicOpsSpecification extends CompilerTestingCommons ) } + property("serialize - collection of boxes") { + def deserTest() = test("serialize", env, ext, + s"""{ + val boxes = INPUTS; + Global.serialize(boxes).size > 0 + }""", + null, + true + ) + + if (activatedVersionInTests < V6SoftForkVersion) { + an [sigma.exceptions.TyperException] should be thrownBy deserTest() + } else { + deserTest() + } + } + + property("serialize - optional collection") { + def deserTest() = test("serialize", env, ext, + s"""{ + val opt = SELF.R1[Coll[Byte]]; + Global.serialize(opt).size > SELF.R1[Coll[Byte]].get.size + }""", + null, + true + ) + + if (activatedVersionInTests < V6SoftForkVersion) { + an [sigma.exceptions.TyperException] should be thrownBy deserTest() + } else { + deserTest() + } + } + + // the test shows that serialize(groupElement) is the same as groupElement.getEncoded + property("serialize - group element - equivalence with .getEncoded") { + val ge = Helpers.decodeGroupElement("026930cb9972e01534918a6f6d6b8e35bc398f57140d13eb3623ea31fbd069939b") + // val ba = Base16.encode(ge.getEncoded.toArray) + def deserTest() = test("serialize", env, Seq(21.toByte -> GroupElementConstant(ge)), + s"""{ + val ge = getVar[GroupElement](21).get + val ba = serialize(ge); + ba == ge.getEncoded + }""", + null, + true + ) + + if (activatedVersionInTests < V6SoftForkVersion) { + an [Exception] should be thrownBy deserTest() + } else { + deserTest() + } + } + + // the test shows that serialize(sigmaProp) is the same as sigmaProp.propBytes without first 2 bytes + property("serialize and .propBytes correspondence") { + def deserTest() = test("deserializeTo", env, ext, + s"""{ + val p1 = getVar[SigmaProp]($propVar1).get + val bytes = p1.propBytes + val ba = bytes.slice(2, bytes.size) + val ba2 = serialize(p1) + ba == ba2 + }""", + null, + true + ) + + if (activatedVersionInTests < V6SoftForkVersion) { + an [Exception] should be thrownBy deserTest() + } else { + deserTest() + } + } + + // todo: failing, needs for Header (de)serialization support from https://github.com/ScorexFoundation/sigmastate-interpreter/pull/972 + property("serialize - collection of collection of headers") { + val td = new SigmaTestingData {} + val h1 = td.TestData.h1 + + val customExt = Seq(21.toByte -> HeaderConstant(h1)) + + def deserTest() = test("serialize", env, customExt, + s"""{ + val h1 = getVar[Header](21).get; + val c = Coll(Coll(h1)) + Global.serialize(c).size > 0 + }""", + null, + true + ) + + if (activatedVersionInTests < V6SoftForkVersion) { + an [sigma.exceptions.TyperException] should be thrownBy deserTest() + } else { + deserTest() + } + } + + // todo: roundtrip tests with deserializeTo from https://github.com/ScorexFoundation/sigmastate-interpreter/pull/979 + property("Relation operations") { test("R1", env, ext, "{ allOf(Coll(getVar[Boolean](trueVar).get, true, true)) }", From 074d609ac854b9c42498efba46bcca22d0d5cdbc Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Thu, 6 Jun 2024 17:08:23 +0300 Subject: [PATCH 129/314] MethodCall deserialization round trip for Global.serialize --- .../MethodCallSerializerSpecification.scala | 23 +++++++++++++++++++ .../utxo/BasicOpsSpecification.scala | 18 ++++++++++++++- 2 files changed, 40 insertions(+), 1 deletion(-) diff --git a/interpreter/shared/src/test/scala/sigma/serialization/MethodCallSerializerSpecification.scala b/interpreter/shared/src/test/scala/sigma/serialization/MethodCallSerializerSpecification.scala index 1db166c685..e78518f8b3 100644 --- a/interpreter/shared/src/test/scala/sigma/serialization/MethodCallSerializerSpecification.scala +++ b/interpreter/shared/src/test/scala/sigma/serialization/MethodCallSerializerSpecification.scala @@ -1,6 +1,8 @@ package sigma.serialization import sigma.VersionContext +import sigma.ast.SCollection.SByteArray +import sigma.ast.SType.tT import sigma.ast._ import sigma.validation.ValidationException @@ -45,4 +47,25 @@ class MethodCallSerializerSpecification extends SerializationSpecification { } ) } + + property("MethodCall deserialization round trip for Global.serialize") { + def code = { + val b = ByteArrayConstant(Array(1.toByte, 2.toByte, 3.toByte)) + val expr = MethodCall(Global, + SGlobalMethods.serializeMethod.withConcreteTypes(Map(STypeVar("T") -> SByteArray)), + Vector(b), + Map() + ) + roundTripTest(expr) + } + + VersionContext.withVersions(VersionContext.V6SoftForkVersion, 1) { + code + } + + an[Exception] should be thrownBy ( + VersionContext.withVersions((VersionContext.V6SoftForkVersion - 1).toByte, 1) { + code + }) + } } diff --git a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala index 29443406c5..13bf74b5f6 100644 --- a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala @@ -2,7 +2,6 @@ package sigmastate.utxo import org.ergoplatform.ErgoBox.{AdditionalRegisters, R6, R8} import org.ergoplatform._ -import scorex.util.encode.Base16 import sigma.Extensions.ArrayOps import sigma.SigmaTestingData import sigma.VersionContext.V6SoftForkVersion @@ -161,6 +160,23 @@ class BasicOpsSpecification extends CompilerTestingCommons ) } + property("serialize - byte array") { + def deserTest() = test("serialize", env, ext, + s"""{ + val ba = fromBase16("c0ffee"); + Global.serialize(ba).size > ba.size + }""", + null, + true + ) + + if (activatedVersionInTests < V6SoftForkVersion) { + an [sigma.exceptions.TyperException] should be thrownBy deserTest() + } else { + deserTest() + } + } + property("serialize - collection of boxes") { def deserTest() = test("serialize", env, ext, s"""{ From bf53a6b67e22101bb13e8867c43ab6a4ad327302 Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Thu, 6 Jun 2024 18:20:33 +0300 Subject: [PATCH 130/314] spam tests, test for serialize(long) producing different result from longToByteArray() --- .../utxo/BasicOpsSpecification.scala | 67 ++++++++++++++++++- 1 file changed, 66 insertions(+), 1 deletion(-) diff --git a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala index 13bf74b5f6..52756b640f 100644 --- a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala @@ -20,7 +20,7 @@ import sigmastate.interpreter.CErgoTreeEvaluator.DefaultEvalSettings import sigmastate.interpreter.Interpreter._ import sigma.ast.Apply import sigma.eval.EvalSettings -import sigma.exceptions.InvalidType +import sigma.exceptions.{CostLimitException, InvalidType} import sigmastate.utils.Helpers import sigmastate.utils.Helpers._ @@ -211,6 +211,25 @@ class BasicOpsSpecification extends CompilerTestingCommons } } + property("serialize(long) is producing different result from longToByteArray()") { + def deserTest() = test("serialize", env, ext, + s"""{ + val l = -1000L + val ba1 = Global.serialize(l); + val ba2 = longToByteArray(l) + ba1 != ba2 + }""", + null, + true + ) + + if (activatedVersionInTests < V6SoftForkVersion) { + an [sigma.exceptions.TyperException] should be thrownBy deserTest() + } else { + deserTest() + } + } + // the test shows that serialize(groupElement) is the same as groupElement.getEncoded property("serialize - group element - equivalence with .getEncoded") { val ge = Helpers.decodeGroupElement("026930cb9972e01534918a6f6d6b8e35bc398f57140d13eb3623ea31fbd069939b") @@ -279,6 +298,52 @@ class BasicOpsSpecification extends CompilerTestingCommons // todo: roundtrip tests with deserializeTo from https://github.com/ScorexFoundation/sigmastate-interpreter/pull/979 + // todo: move spam tests to dedicated test suite? + property("serialize - not spam") { + val customExt = Seq(21.toByte -> ShortArrayConstant((1 to Short.MaxValue).map(_.toShort).toArray), + 22.toByte -> ByteArrayConstant(Array.fill(1)(1.toByte))) + def deserTest() = test("serialize", env, customExt, + s"""{ + val indices = getVar[Coll[Short]](21).get + val base = getVar[Coll[Byte]](22).get + + def check(index:Short): Boolean = { serialize(base) != base } + indices.forall(check) + }""", + null, + true + ) + + if (activatedVersionInTests < V6SoftForkVersion) { + an[Exception] should be thrownBy deserTest() + } else { + deserTest() + } + } + + property("serialize - spam attempt") { + val customExt = Seq(21.toByte -> ShortArrayConstant((1 to Short.MaxValue).map(_.toShort).toArray), + 22.toByte -> ByteArrayConstant(Array.fill(16000)(1.toByte))) + def deserTest() = test("serialize", env, customExt, + s"""{ + val indices = getVar[Coll[Short]](21).get + val base = getVar[Coll[Byte]](22).get + + def check(index:Short): Boolean = { serialize(base) != base } + indices.forall(check) + }""", + null, + true + ) + + if (activatedVersionInTests < V6SoftForkVersion) { + an[Exception] should be thrownBy deserTest() + } else { + // we have wrapped CostLimitException here + an[Exception] should be thrownBy deserTest() + } + } + property("Relation operations") { test("R1", env, ext, "{ allOf(Coll(getVar[Boolean](trueVar).get, true, true)) }", From 91a9729b36b40a68d07ac58948829aea87bb6493 Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Fri, 7 Jun 2024 13:10:16 +0300 Subject: [PATCH 131/314] removing serialize from tests --- .../src/main/scala/sigma/SigmaDsl.scala | 3 -- .../sigma/reflection/ReflectionData.scala | 4 --- .../sigmastate/lang/SigmaBinderTest.scala | 11 ------- .../sigmastate/lang/SigmaTyperTest.scala | 31 ------------------- 4 files changed, 49 deletions(-) diff --git a/core/shared/src/main/scala/sigma/SigmaDsl.scala b/core/shared/src/main/scala/sigma/SigmaDsl.scala index 6e306f7a0b..df2b419273 100644 --- a/core/shared/src/main/scala/sigma/SigmaDsl.scala +++ b/core/shared/src/main/scala/sigma/SigmaDsl.scala @@ -727,9 +727,6 @@ trait SigmaDslBuilder { /** Construct a new authenticated dictionary with given parameters and tree root digest. */ def avlTree(operationFlags: Byte, digest: Coll[Byte], keyLength: Int, valueLengthOpt: Option[Int]): AvlTree - /** Serializes the given `value` into bytes using the default serialization format. */ - def serialize[T](value: T)(implicit cT: RType[T]): Coll[Byte] - /** Returns a byte-wise XOR of the two collections of bytes. */ def xor(l: Coll[Byte], r: Coll[Byte]): Coll[Byte] } diff --git a/core/shared/src/main/scala/sigma/reflection/ReflectionData.scala b/core/shared/src/main/scala/sigma/reflection/ReflectionData.scala index 5cd678b712..028e68bf72 100644 --- a/core/shared/src/main/scala/sigma/reflection/ReflectionData.scala +++ b/core/shared/src/main/scala/sigma/reflection/ReflectionData.scala @@ -441,10 +441,6 @@ object ReflectionData { mkMethod(clazz, "sha256", Array[Class[_]](cColl)) { (obj, args) => obj.asInstanceOf[SigmaDslBuilder].sha256(args(0).asInstanceOf[Coll[Byte]]) }, - mkMethod(clazz, "serialize", Array[Class[_]](classOf[Object], classOf[RType[_]])) { (obj, args) => - obj.asInstanceOf[SigmaDslBuilder].serialize[Any]( - args(0).asInstanceOf[Any])(args(1).asInstanceOf[RType[Any]]) - }, mkMethod(clazz, "decodePoint", Array[Class[_]](cColl)) { (obj, args) => obj.asInstanceOf[SigmaDslBuilder].decodePoint(args(0).asInstanceOf[Coll[Byte]]) } diff --git a/sc/shared/src/test/scala/sigmastate/lang/SigmaBinderTest.scala b/sc/shared/src/test/scala/sigmastate/lang/SigmaBinderTest.scala index 54bd89c9c2..1f15f5d747 100644 --- a/sc/shared/src/test/scala/sigmastate/lang/SigmaBinderTest.scala +++ b/sc/shared/src/test/scala/sigmastate/lang/SigmaBinderTest.scala @@ -213,15 +213,4 @@ class SigmaBinderTest extends AnyPropSpec with ScalaCheckPropertyChecks with Mat e.source shouldBe Some(SourceContext(2, 5, "val x = 10")) } - property("predefined `serialize` should be transformed to MethodCall") { - runWithVersion(VersionContext.V6SoftForkVersion) { - checkBound(env, "serialize(1)", - MethodCall.typed[Value[SCollection[SByte.type]]]( - Global, - SGlobalMethods.getMethodByName("serialize").withConcreteTypes(Map(STypeVar("T") -> SInt)), - Array(IntConstant(1)), - Map() - )) - } - } } diff --git a/sc/shared/src/test/scala/sigmastate/lang/SigmaTyperTest.scala b/sc/shared/src/test/scala/sigmastate/lang/SigmaTyperTest.scala index 2c3bd44d39..52dab65991 100644 --- a/sc/shared/src/test/scala/sigmastate/lang/SigmaTyperTest.scala +++ b/sc/shared/src/test/scala/sigmastate/lang/SigmaTyperTest.scala @@ -671,35 +671,4 @@ class SigmaTyperTest extends AnyPropSpec typecheck(customEnv, "substConstants(scriptBytes, positions, newVals)") shouldBe SByteArray } - property("Global.serialize") { - runWithVersion(VersionContext.V6SoftForkVersion) { - typecheck(env, "Global.serialize(1)", - MethodCall.typed[Value[SCollection[SByte.type]]]( - Global, - SGlobalMethods.getMethodByName("serialize").withConcreteTypes(Map(STypeVar("T") -> SInt)), - Array(IntConstant(1)), - Map() - )) shouldBe SByteArray - } - - runWithVersion((VersionContext.V6SoftForkVersion - 1).toByte) { - assertExceptionThrown( - typecheck(env, "Global.serialize(1)"), - exceptionLike[MethodNotFound]("Cannot find method 'serialize' in in the object Global") - ) - } - } - - property("predefined serialize") { - runWithVersion(VersionContext.V6SoftForkVersion) { - typecheck(env, "serialize((1, 2L))", - expected = MethodCall.typed[Value[SCollection[SByte.type]]]( - Global, - SGlobalMethods.getMethodByName("serialize").withConcreteTypes(Map(STypeVar("T") -> SPair(SInt, SLong))), - Array(Tuple(Vector(IntConstant(1), LongConstant(2L)))), - Map() - )) shouldBe SByteArray - } - } - } From dd7bdc63024bfa4e16eb4723c7739c9e0187fb2a Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Fri, 7 Jun 2024 13:21:45 +0300 Subject: [PATCH 132/314] removing serialize --- .../src/main/scala/sigma/SigmaDsl.scala | 3 - .../sigma/reflection/ReflectionData.scala | 4 - .../validation/ValidationRules.scala | 17 +-- .../scala/sigma/SigmaDataReflection.scala | 5 - .../src/main/scala/sigma/ast/ErgoTree.scala | 5 - .../main/scala/sigma/ast/SigmaPredef.scala | 18 --- .../src/main/scala/sigma/ast/methods.scala | 37 +---- .../scala/sigma/data/CSigmaDslBuilder.scala | 8 -- .../serialization/ErgoTreeSerializer.scala | 48 ++----- docs/LangSpec.md | 7 +- .../sigmastate/lang/SigmaParserTest.scala | 14 +- .../sigmastate/ReflectionGenerator.scala | 11 ++ .../sigma/compiler/ir/GraphIRReflection.scala | 3 - .../ir/wrappers/sigma/SigmaDslUnit.scala | 1 - .../ir/wrappers/sigma/impl/SigmaDslImpl.scala | 15 -- .../sigma/compiler/phases/SigmaBinder.scala | 3 - .../scala/sigma/LanguageSpecificationV6.scala | 130 ------------------ .../sigmastate/lang/SigmaBinderTest.scala | 11 -- .../sigmastate/lang/SigmaTyperTest.scala | 31 ----- 19 files changed, 30 insertions(+), 341 deletions(-) diff --git a/core/shared/src/main/scala/sigma/SigmaDsl.scala b/core/shared/src/main/scala/sigma/SigmaDsl.scala index 6e306f7a0b..df2b419273 100644 --- a/core/shared/src/main/scala/sigma/SigmaDsl.scala +++ b/core/shared/src/main/scala/sigma/SigmaDsl.scala @@ -727,9 +727,6 @@ trait SigmaDslBuilder { /** Construct a new authenticated dictionary with given parameters and tree root digest. */ def avlTree(operationFlags: Byte, digest: Coll[Byte], keyLength: Int, valueLengthOpt: Option[Int]): AvlTree - /** Serializes the given `value` into bytes using the default serialization format. */ - def serialize[T](value: T)(implicit cT: RType[T]): Coll[Byte] - /** Returns a byte-wise XOR of the two collections of bytes. */ def xor(l: Coll[Byte], r: Coll[Byte]): Coll[Byte] } diff --git a/core/shared/src/main/scala/sigma/reflection/ReflectionData.scala b/core/shared/src/main/scala/sigma/reflection/ReflectionData.scala index 5cd678b712..028e68bf72 100644 --- a/core/shared/src/main/scala/sigma/reflection/ReflectionData.scala +++ b/core/shared/src/main/scala/sigma/reflection/ReflectionData.scala @@ -441,10 +441,6 @@ object ReflectionData { mkMethod(clazz, "sha256", Array[Class[_]](cColl)) { (obj, args) => obj.asInstanceOf[SigmaDslBuilder].sha256(args(0).asInstanceOf[Coll[Byte]]) }, - mkMethod(clazz, "serialize", Array[Class[_]](classOf[Object], classOf[RType[_]])) { (obj, args) => - obj.asInstanceOf[SigmaDslBuilder].serialize[Any]( - args(0).asInstanceOf[Any])(args(1).asInstanceOf[RType[Any]]) - }, mkMethod(clazz, "decodePoint", Array[Class[_]](cColl)) { (obj, args) => obj.asInstanceOf[SigmaDslBuilder].decodePoint(args(0).asInstanceOf[Coll[Byte]]) } diff --git a/data/shared/src/main/scala/org/ergoplatform/validation/ValidationRules.scala b/data/shared/src/main/scala/org/ergoplatform/validation/ValidationRules.scala index 07fe8db0ee..9d4de47a99 100644 --- a/data/shared/src/main/scala/org/ergoplatform/validation/ValidationRules.scala +++ b/data/shared/src/main/scala/org/ergoplatform/validation/ValidationRules.scala @@ -155,20 +155,6 @@ object ValidationRules { override protected lazy val settings: SigmaValidationSettings = currentSettings } - object CheckMinimalErgoTreeVersion extends ValidationRule(1016, - "ErgoTree should have at least required version") with SoftForkWhenReplaced { - override protected lazy val settings: SigmaValidationSettings = currentSettings - - final def apply(currentVersion: Byte, minVersion: Byte): Unit = { - checkRule() - if (currentVersion < minVersion) { - throwValidationException( - new SigmaException(s"ErgoTree should have at least $minVersion version, but was $currentVersion"), - Array(currentVersion, minVersion)) - } - } - } - val ruleSpecs: Seq[ValidationRule] = Seq( CheckDeserializedScriptType, CheckDeserializedScriptIsSigmaProp, @@ -185,8 +171,7 @@ object ValidationRules { CheckHeaderSizeBit, CheckCostFuncOperation, CheckPositionLimit, - CheckLoopLevelInCostFunction, - CheckMinimalErgoTreeVersion + CheckLoopLevelInCostFunction ) /** Validation settings that correspond to the current version of the ErgoScript implementation. diff --git a/data/shared/src/main/scala/sigma/SigmaDataReflection.scala b/data/shared/src/main/scala/sigma/SigmaDataReflection.scala index a6e5de2a26..48939b1460 100644 --- a/data/shared/src/main/scala/sigma/SigmaDataReflection.scala +++ b/data/shared/src/main/scala/sigma/SigmaDataReflection.scala @@ -322,11 +322,6 @@ object SigmaDataReflection { args(1).asInstanceOf[SigmaDslBuilder], args(2).asInstanceOf[Coll[Byte]], args(3).asInstanceOf[Coll[Byte]])(args(4).asInstanceOf[ErgoTreeEvaluator]) - }, - mkMethod(clazz, "serialize_eval", Array[Class[_]](classOf[MethodCall], classOf[SigmaDslBuilder], classOf[Object], classOf[ErgoTreeEvaluator])) { (obj, args) => - obj.asInstanceOf[SGlobalMethods.type].serialize_eval(args(0).asInstanceOf[MethodCall], - args(1).asInstanceOf[SigmaDslBuilder], - args(2).asInstanceOf[SType#WrappedType])(args(3).asInstanceOf[ErgoTreeEvaluator]) } ) ) diff --git a/data/shared/src/main/scala/sigma/ast/ErgoTree.scala b/data/shared/src/main/scala/sigma/ast/ErgoTree.scala index eae420612e..68d69abd91 100644 --- a/data/shared/src/main/scala/sigma/ast/ErgoTree.scala +++ b/data/shared/src/main/scala/sigma/ast/ErgoTree.scala @@ -228,11 +228,6 @@ object ErgoTree { type HeaderType = HeaderType.Type - implicit class HeaderTypeOps(val header: HeaderType) extends AnyVal { - def withVersion(version: Byte): HeaderType = ErgoTree.headerWithVersion(header, version) - def withConstantSegregation: HeaderType = ErgoTree.setConstantSegregation(header) - } - /** Current version of ErgoTree serialization format (aka bite-code language version) */ val VersionFlag: Byte = VersionContext.MaxSupportedScriptVersion diff --git a/data/shared/src/main/scala/sigma/ast/SigmaPredef.scala b/data/shared/src/main/scala/sigma/ast/SigmaPredef.scala index f2da24d2df..897ac6d757 100644 --- a/data/shared/src/main/scala/sigma/ast/SigmaPredef.scala +++ b/data/shared/src/main/scala/sigma/ast/SigmaPredef.scala @@ -403,24 +403,6 @@ object SigmaPredef { ArgInfo("default", "optional default value, if register is not available"))) ) - val SerializeFunc = PredefinedFunc("serialize", - Lambda(Seq(paramT), Array("value" -> tT), SByteArray, None), - PredefFuncInfo( - { case (_, args @ Seq(value)) => - MethodCall.typed[Value[SCollection[SByte.type]]]( - Global, - SGlobalMethods.serializeMethod.withConcreteTypes(Map(tT -> value.tpe)), - args.toIndexedSeq, - Map() - ) - }), - OperationInfo(MethodCall, - """ - """.stripMargin, - Seq(ArgInfo("value", "")) - ) - ) - val globalFuncs: Map[String, PredefinedFunc] = Seq( AllOfFunc, AnyOfFunc, diff --git a/data/shared/src/main/scala/sigma/ast/methods.scala b/data/shared/src/main/scala/sigma/ast/methods.scala index 1a0841e97c..136225f256 100644 --- a/data/shared/src/main/scala/sigma/ast/methods.scala +++ b/data/shared/src/main/scala/sigma/ast/methods.scala @@ -1,7 +1,6 @@ package sigma.ast import org.ergoplatform._ -import org.ergoplatform.validation.ValidationRules.CheckMinimalErgoTreeVersion import org.ergoplatform.validation._ import sigma._ import sigma.ast.SCollection.{SBooleanArray, SBoxArray, SByteArray, SByteArray2, SHeaderArray} @@ -1543,37 +1542,9 @@ case object SGlobalMethods extends MonoTypeMethods { Xor.xorWithCosting(ls, rs) } - lazy val serializeMethod = SMethod(this, "serialize", - SFunc(Array(SGlobal, tT), SByteArray, Array(paramT)), 3, DynamicCost) - .withIRInfo(MethodCallIrBuilder) - .withInfo(MethodCall, "", - ArgInfo("value", "value to be serialized")) - - - /** Implements evaluation of Global.serialize method call ErgoTree node. - * Called via reflection based on naming convention. - * @see SMethod.evalMethod - */ - def serialize_eval(mc: MethodCall, G: SigmaDslBuilder, value: SType#WrappedType) - (implicit E: ErgoTreeEvaluator): Coll[Byte] = { - // TODO v6.0: accumulate cost - val t = Evaluation.stypeToRType(mc.args(0).tpe) - G.serialize(value)(t) - } - - protected override def getMethods() = super.getMethods() ++ { - if (VersionContext.current.isV6SoftForkActivated) { - Seq( - groupGeneratorMethod, - xorMethod, - serializeMethod - ) - } else { - Seq( - groupGeneratorMethod, - xorMethod - ) - } - } + protected override def getMethods() = super.getMethods() ++ Seq( + groupGeneratorMethod, + xorMethod + ) } diff --git a/data/shared/src/main/scala/sigma/data/CSigmaDslBuilder.scala b/data/shared/src/main/scala/sigma/data/CSigmaDslBuilder.scala index 21b9900028..d7b092fc0e 100644 --- a/data/shared/src/main/scala/sigma/data/CSigmaDslBuilder.scala +++ b/data/shared/src/main/scala/sigma/data/CSigmaDslBuilder.scala @@ -200,14 +200,6 @@ class CSigmaDslBuilder extends SigmaDslBuilder { dsl => val p = GroupElementSerializer.parse(r) this.GroupElement(p) } - - /** Serializes the given `value` into bytes using the default serialization format. */ - override def serialize[T](value: T)(implicit cT: RType[T]): Coll[Byte] = { - val tpe = Evaluation.rtypeToSType(cT) - val w = SigmaSerializer.startWriter() - DataSerializer.serialize(value.asInstanceOf[SType#WrappedType], tpe, w) - Colls.fromArray(w.toBytes) - } } /** Default singleton instance of Global object, which implements global ErgoTree functions. */ diff --git a/data/shared/src/main/scala/sigma/serialization/ErgoTreeSerializer.scala b/data/shared/src/main/scala/sigma/serialization/ErgoTreeSerializer.scala index e7bb46429a..43e41f91ff 100644 --- a/data/shared/src/main/scala/sigma/serialization/ErgoTreeSerializer.scala +++ b/data/shared/src/main/scala/sigma/serialization/ErgoTreeSerializer.scala @@ -287,9 +287,6 @@ class ErgoTreeSerializer { * allow to use serialized scripts as pre-defined templates. * See [[SubstConstants]] for details. * - * Note, this operation doesn't require (de)serialization of ErgoTree expression, - * thus it is more efficient than serialization roundtrip. - * * @param scriptBytes serialized ErgoTree with ConstantSegregationFlag set to 1. * @param positions zero based indexes in ErgoTree.constants array which * should be replaced with new values @@ -307,23 +304,21 @@ class ErgoTreeSerializer { s"expected positions and newVals to have the same length, got: positions: ${positions.toSeq},\n newVals: ${newVals.toSeq}") val r = SigmaSerializer.startReader(scriptBytes) val (header, _, constants, treeBytes) = deserializeHeaderWithTreeBytes(r) - val 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() + val w = SigmaSerializer.startWriter() + w.put(header) + if (VersionContext.current.isJitActivated) { // The following `constants.length` should not be serialized when segregation is off // in the `header`, because in this case there is no `constants` section in the // ErgoTree serialization format. Thus, applying this `substituteConstants` for // non-segregated trees will return non-parsable ErgoTree bytes (when // `constants.length` is put in `w`). if (ErgoTree.isConstantSegregation(header)) { - constW.putUInt(constants.length) + w.putUInt(constants.length) } // The following is optimized O(nConstants + position.length) implementation + val nConstants = constants.length if (nConstants > 0) { val backrefs = getPositionsBackref(positions, nConstants) cfor(0)(_ < nConstants, _ + 1) { i => @@ -331,38 +326,17 @@ class ErgoTreeSerializer { val iPos = backrefs(i) // index to `positions` if (iPos == -1) { // no position => no substitution, serialize original constant - constantSerializer.serialize(c, constW) + constantSerializer.serialize(c, w) } else { - require(positions(iPos) == i) // INV: backrefs and positions are mutually inverse + assert(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) + constantSerializer.serialize(newConst, w) } } } - - val constBytes = constW.toBytes // nConstants + serialized new constants - - // start composing the resulting tree bytes - val w = SigmaSerializer.startWriter() - w.put(header) // header byte - - if (VersionContext.current.isV6SoftForkActivated) { - // fix in v6.0 to save tree size to respect size bit of the original tree - if (ErgoTree.hasSize(header)) { - val size = constBytes.length + treeBytes.length - w.putUInt(size) // tree size - } - } - - w.putBytes(constBytes) // constants section - w.putBytes(treeBytes) // tree section - w.toBytes } else { - val w = SigmaSerializer.startWriter() - w.put(header) - // for v4.x compatibility we save constants.length here (see the above comment to // understand the consequences) w.putUInt(constants.length) @@ -383,12 +357,10 @@ class ErgoTreeSerializer { case (c, _) => constantSerializer.serialize(c, w) } - - w.putBytes(treeBytes) - w.toBytes } - (resBytes, nConstants) + w.putBytes(treeBytes) + (w.toBytes, constants.length) } } diff --git a/docs/LangSpec.md b/docs/LangSpec.md index 04b345d6d9..ba66748f08 100644 --- a/docs/LangSpec.md +++ b/docs/LangSpec.md @@ -68,7 +68,7 @@ The following sections describe ErgoScript and its operations. #### Operations and constructs overview - Binary operations: `>, <, >=, <=, +, -, &&, ||, ==, !=, |, &, *, /, %, ^, ++` -- predefined primitives: `serialize`, `blake2b256`, `byteArrayToBigInt`, `proveDlog` etc. +- predefined primitives: `blake2b256`, `byteArrayToBigInt`, `proveDlog` etc. - val declarations: `val h = blake2b256(pubkey)` - if-then-else clause: `if (x > 0) 1 else 0` - collection literals: `Coll(1, 2, 3, 4)` @@ -1041,11 +1041,6 @@ def deserialize[T](string: String): T * replaced and all other bytes remain exactly the same */ def substConstants[T](scriptBytes: Coll[Byte], positions: Coll[Int], newValues: Coll[T]): Coll[Byte] - -/** Serializes an instance of type T using default serialization format. - * See https://github.com/ScorexFoundation/sigmastate-interpreter/issues/988 for more details - */ -def serialize[T](value: T): Coll[Byte] ``` ## Examples diff --git a/parsers/shared/src/test/scala/sigmastate/lang/SigmaParserTest.scala b/parsers/shared/src/test/scala/sigmastate/lang/SigmaParserTest.scala index 70aa540a4f..dc63330f95 100644 --- a/parsers/shared/src/test/scala/sigmastate/lang/SigmaParserTest.scala +++ b/parsers/shared/src/test/scala/sigmastate/lang/SigmaParserTest.scala @@ -35,6 +35,9 @@ class SigmaParserTest extends AnyPropSpec with ScalaCheckPropertyChecks with Mat } } + /** Checks parsing result, printing the actual value as a test vector if expected value + * is not equal to actual. + */ def checkParsed(x: String, expected: SValue) = { val parsed = parse(x) if (expected != parsed) { @@ -903,17 +906,6 @@ class SigmaParserTest extends AnyPropSpec with ScalaCheckPropertyChecks with Mat ) } - property("serialize") { - checkParsed("serialize(1)", Apply(Ident("serialize", NoType), Array(IntConstant(1)))) - checkParsed("serialize((1, 2L))", - Apply(Ident("serialize", NoType), Array(Tuple(Vector(IntConstant(1), LongConstant(2L)))))) - checkParsed("serialize(Coll(1, 2, 3))", - Apply( - Ident("serialize", NoType), - Array(Apply(Ident("Coll", NoType), Array(IntConstant(1), IntConstant(2), IntConstant(3)))) - )) - } - property("single name pattern fail") { fail("{val (a,b) = (1,2)}", 1, 6) } diff --git a/sc/jvm/src/test/scala/sigmastate/ReflectionGenerator.scala b/sc/jvm/src/test/scala/sigmastate/ReflectionGenerator.scala index 324542505e..dd5262e700 100644 --- a/sc/jvm/src/test/scala/sigmastate/ReflectionGenerator.scala +++ b/sc/jvm/src/test/scala/sigmastate/ReflectionGenerator.scala @@ -5,6 +5,17 @@ import sigma.reflection._ import scala.annotation.unused import scala.collection.mutable +/** Generates code for registering classes in the ReflectionData. + * It is not used in the runtime. + * + * The generated invocations of `registerClassEntry`, `mkMethod`, `mkConstructor` may + * require manual adjustments. + * + * It uses [[sigma.reflection.Platform.unknownClasses]] to collect classes which were + * accessed during runtime + * + * @see [[ReflectionData]] + */ object ReflectionGenerator { def normalizeName(name: String): String = { diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/GraphIRReflection.scala b/sc/shared/src/main/scala/sigma/compiler/ir/GraphIRReflection.scala index 6c0403f643..69736a0224 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/GraphIRReflection.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/GraphIRReflection.scala @@ -504,9 +504,6 @@ object GraphIRReflection { }, mkMethod(clazz, "decodePoint", Array[Class[_]](classOf[Base#Ref[_]])) { (obj, args) => obj.asInstanceOf[ctx.SigmaDslBuilder].decodePoint(args(0).asInstanceOf[ctx.Ref[ctx.Coll[Byte]]]) - }, - mkMethod(clazz, "serialize", Array[Class[_]](classOf[Base#Ref[_]])) { (obj, args) => - obj.asInstanceOf[ctx.SigmaDslBuilder].serialize(args(0).asInstanceOf[ctx.Ref[Any]]) } ) ) diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/SigmaDslUnit.scala b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/SigmaDslUnit.scala index d7e574c68c..2a6a341686 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/SigmaDslUnit.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/SigmaDslUnit.scala @@ -114,7 +114,6 @@ import scalan._ /** This method will be used in v6.0 to handle CreateAvlTree operation in GraphBuilding */ def avlTree(operationFlags: Ref[Byte], digest: Ref[Coll[Byte]], keyLength: Ref[Int], valueLengthOpt: Ref[WOption[Int]]): Ref[AvlTree]; def xor(l: Ref[Coll[Byte]], r: Ref[Coll[Byte]]): Ref[Coll[Byte]] - def serialize[T](value: Ref[T]): Ref[Coll[Byte]] }; trait CostModelCompanion; trait BigIntCompanion; diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/SigmaDslImpl.scala b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/SigmaDslImpl.scala index 9cd524149d..c113cb7de3 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/SigmaDslImpl.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/SigmaDslImpl.scala @@ -1945,14 +1945,6 @@ object SigmaDslBuilder extends EntityObject("SigmaDslBuilder") { Array[AnyRef](l, r), true, false, element[Coll[Byte]])) } - - def serialize[T](value: Ref[T]): Ref[Coll[Byte]] = { - asRep[Coll[Byte]](mkMethodCall(self, - SigmaDslBuilderClass.getMethod("serialize", classOf[Sym]), - Array[AnyRef](value), - true, true, element[Coll[Byte]])) - } - } implicit object LiftableSigmaDslBuilder @@ -2112,13 +2104,6 @@ object SigmaDslBuilder extends EntityObject("SigmaDslBuilder") { Array[AnyRef](l, r), true, true, element[Coll[Byte]])) } - - def serialize[T](value: Ref[T]): Ref[Coll[Byte]] = { - asRep[Coll[Byte]](mkMethodCall(source, - SigmaDslBuilderClass.getMethod("serialize", classOf[Sym]), - Array[AnyRef](value), - true, true, element[Coll[Byte]])) - } } // entityUnref: single unref method for each type family diff --git a/sc/shared/src/main/scala/sigma/compiler/phases/SigmaBinder.scala b/sc/shared/src/main/scala/sigma/compiler/phases/SigmaBinder.scala index d4943ef892..af5be938be 100644 --- a/sc/shared/src/main/scala/sigma/compiler/phases/SigmaBinder.scala +++ b/sc/shared/src/main/scala/sigma/compiler/phases/SigmaBinder.scala @@ -105,9 +105,6 @@ class SigmaBinder(env: ScriptEnv, builder: SigmaBuilder, case a @ Apply(PKFunc.symNoType, args) => Some(PKFunc.irInfo.irBuilder(PKFunc.sym, args).withPropagatedSrcCtx(a.sourceContext)) - case a @ Apply(predefFuncRegistry.SerializeFunc.symNoType, args) => - Some(predefFuncRegistry.SerializeFunc.irInfo.irBuilder(PKFunc.sym, args).withPropagatedSrcCtx(a.sourceContext)) - case sel @ Select(obj, "isEmpty", _) => Some(mkLogicalNot(mkSelect(obj, "isDefined").asBoolValue).withPropagatedSrcCtx(sel.sourceContext)) diff --git a/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala b/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala index d89fc1f623..6eb3dc4c11 100644 --- a/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala +++ b/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala @@ -29,51 +29,6 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite => Seq(0, 1, 2, 3).map(version => version -> res) } - def mkSerializeFeature[A: RType]: Feature[A, Coll[Byte]] = { - val tA = RType[A] - val tpe = Evaluation.rtypeToSType(tA) - newFeature( - (x: A) => SigmaDsl.serialize(x), - s"{ (x: ${tA.name}) => serialize(x) }", - expectedExpr = FuncValue( - Array((1, tpe)), - MethodCall( - Global, - SGlobalMethods.serializeMethod.withConcreteTypes(Map(STypeVar("T") -> tpe)), - Array(ValUse(1, tpe)), - Map() - ) - ), - sinceVersion = VersionContext.sinceV6AndTreeVersion(0)) - } - - property("Global.serialize[Byte]") { - lazy val serializeByte = mkSerializeFeature[Byte] - val cases = Seq( - (-128.toByte, Success(Coll(-128.toByte))), - (-1.toByte, Success(Coll(-1.toByte))), - (0.toByte, Success(Coll(0.toByte))), - (1.toByte, Success(Coll(1.toByte))), - (127.toByte, Success(Coll(127.toByte))) - ) - testCases(cases, serializeByte) - } - - property("Global.serialize[Short]") { - lazy val serializeShort = mkSerializeFeature[Short] - val cases = Seq( - (Short.MinValue, Success(Coll[Byte](0xFF.toByte, 0xFF.toByte, 0x03.toByte))), - (-1.toShort, Success(Coll(1.toByte))), - (0.toShort, Success(Coll(0.toByte))), - (1.toShort, Success(Coll(2.toByte))), - (Short.MaxValue, Success(Coll(-2.toByte, -1.toByte, 3.toByte))) - ) - testCases(cases, serializeShort) - } - - // TODO v6.0: implement serialization roundtrip tests after merge with deserializeTo - - property("Boolean.toByte") { val toByte = newFeature((x: Boolean) => x.toByte, "{ (x: Boolean) => x.toByte }", sinceVersion = VersionContext.sinceV6AndTreeVersion(0) @@ -390,91 +345,6 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite => } } - property("Fix substConstants in v6.0 for ErgoTree version > 0") { - // tree with one segregated constant and v0 - val t1 = ErgoTree( - header = ZeroHeader.withConstantSegregation, - constants = Vector(TrueSigmaProp), - ConstantPlaceholder(0, SSigmaProp)) - - // tree with one segregated constant and max supported version - val t2 = ErgoTree( - header = ZeroHeader - .withVersion(VersionContext.MaxSupportedScriptVersion) - .withConstantSegregation, - Vector(TrueSigmaProp), - ConstantPlaceholder(0, SSigmaProp)) - - def costDetails(nItems: Int) = TracedCost( - traceBase ++ Array( - FixedCostItem(SelectField), - FixedCostItem(ConcreteCollection), - FixedCostItem(ValUse), - FixedCostItem(SelectField), - FixedCostItem(ConcreteCollection), - FixedCostItem(Constant), - FixedCostItem(BoolToSigmaProp), - ast.SeqCostItem(CompanionDesc(SubstConstants), PerItemCost(JitCost(100), JitCost(100), 1), nItems) - ) - ) - - val expectedTreeBytes_beforeV6 = Helpers.decodeBytes("1b0108d27300") - val expectedTreeBytes_V6 = Helpers.decodeBytes("1b050108d27300") - - verifyCases( - Seq( - // for tree v0, the result is the same for all versions - (Coll(t1.bytes: _*), 0) -> Expected( - Success(Helpers.decodeBytes("100108d27300")), - cost = 1793, - expectedDetails = CostDetails.ZeroCost, - newCost = 1793, - newVersionedResults = expectedSuccessForAllTreeVersions(Helpers.decodeBytes("100108d27300"), 1793, costDetails(1)) - ), - // for tree version > 0, the result depend on activated version - { - (Coll(t2.bytes: _*), 0) -> Expected( - Success(expectedTreeBytes_beforeV6), - cost = 1793, - expectedDetails = CostDetails.ZeroCost, - newCost = 1793, - newVersionedResults = expectedSuccessForAllTreeVersions(expectedTreeBytes_V6, 1793, costDetails(1))) - } - ), - changedFeature( - changedInVersion = VersionContext.sinceV6AndTreeVersion(0), - { (x: (Coll[Byte], Int)) => - SigmaDsl.substConstants(x._1, Coll[Int](x._2), Coll[Any](SigmaDsl.sigmaProp(false))(sigma.AnyType)) - }, - { (x: (Coll[Byte], Int)) => - SigmaDsl.substConstants(x._1, Coll[Int](x._2), Coll[Any](SigmaDsl.sigmaProp(false))(sigma.AnyType)) - }, - "{ (x: (Coll[Byte], Int)) => substConstants[Any](x._1, Coll[Int](x._2), Coll[Any](sigmaProp(false))) }", - FuncValue( - Vector((1, SPair(SByteArray, SInt))), - SubstConstants( - SelectField.typed[Value[SCollection[SByte.type]]](ValUse(1, SPair(SByteArray, SInt)), 1.toByte), - ConcreteCollection( - Array(SelectField.typed[Value[SInt.type]](ValUse(1, SPair(SByteArray, SInt)), 2.toByte)), - SInt - ), - ConcreteCollection(Array(BoolToSigmaProp(FalseLeaf)), SSigmaProp) - ) - ) - ) - ) - - // before v6.0 the expected tree is not parsable - ErgoTree.fromBytes(expectedTreeBytes_beforeV6.toArray).isRightParsed shouldBe false - - // in v6.0 the expected tree should be parsable and similar to the original tree - val tree = ErgoTree.fromBytes(expectedTreeBytes_V6.toArray) - tree.isRightParsed shouldBe true - tree.header shouldBe t2.header - tree.constants.length shouldBe t2.constants.length - tree.root shouldBe t2.root - } - property("Numeric.toBytes methods equivalence") { lazy val toBytes = newFeature( { (x: Byte) => x.toBigEndianBytes }, diff --git a/sc/shared/src/test/scala/sigmastate/lang/SigmaBinderTest.scala b/sc/shared/src/test/scala/sigmastate/lang/SigmaBinderTest.scala index 54bd89c9c2..1f15f5d747 100644 --- a/sc/shared/src/test/scala/sigmastate/lang/SigmaBinderTest.scala +++ b/sc/shared/src/test/scala/sigmastate/lang/SigmaBinderTest.scala @@ -213,15 +213,4 @@ class SigmaBinderTest extends AnyPropSpec with ScalaCheckPropertyChecks with Mat e.source shouldBe Some(SourceContext(2, 5, "val x = 10")) } - property("predefined `serialize` should be transformed to MethodCall") { - runWithVersion(VersionContext.V6SoftForkVersion) { - checkBound(env, "serialize(1)", - MethodCall.typed[Value[SCollection[SByte.type]]]( - Global, - SGlobalMethods.getMethodByName("serialize").withConcreteTypes(Map(STypeVar("T") -> SInt)), - Array(IntConstant(1)), - Map() - )) - } - } } diff --git a/sc/shared/src/test/scala/sigmastate/lang/SigmaTyperTest.scala b/sc/shared/src/test/scala/sigmastate/lang/SigmaTyperTest.scala index 102033ead9..ba6eb55ee6 100644 --- a/sc/shared/src/test/scala/sigmastate/lang/SigmaTyperTest.scala +++ b/sc/shared/src/test/scala/sigmastate/lang/SigmaTyperTest.scala @@ -713,35 +713,4 @@ class SigmaTyperTest extends AnyPropSpec typecheck(customEnv, "substConstants(scriptBytes, positions, newVals)") shouldBe SByteArray } - property("Global.serialize") { - runWithVersion(VersionContext.V6SoftForkVersion) { - typecheck(env, "Global.serialize(1)", - MethodCall.typed[Value[SCollection[SByte.type]]]( - Global, - SGlobalMethods.getMethodByName("serialize").withConcreteTypes(Map(STypeVar("T") -> SInt)), - Array(IntConstant(1)), - Map() - )) shouldBe SByteArray - } - - runWithVersion((VersionContext.V6SoftForkVersion - 1).toByte) { - assertExceptionThrown( - typecheck(env, "Global.serialize(1)"), - exceptionLike[MethodNotFound]("Cannot find method 'serialize' in in the object Global") - ) - } - } - - property("predefined serialize") { - runWithVersion(VersionContext.V6SoftForkVersion) { - typecheck(env, "serialize((1, 2L))", - expected = MethodCall.typed[Value[SCollection[SByte.type]]]( - Global, - SGlobalMethods.getMethodByName("serialize").withConcreteTypes(Map(STypeVar("T") -> SPair(SInt, SLong))), - Array(Tuple(Vector(IntConstant(1), LongConstant(2L)))), - Map() - )) shouldBe SByteArray - } - } - } From e1bfb1c07999f81a9b9308695f0cd24feec43f12 Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Fri, 7 Jun 2024 15:21:08 +0300 Subject: [PATCH 133/314] remove serialize from GraphBuilding and ErgoTreeSpecification --- data/shared/src/main/scala/sigma/ast/SigmaPredef.scala | 3 +-- .../src/main/scala/sigma/compiler/ir/GraphBuilding.scala | 3 --- .../src/test/scala/sigmastate/ErgoTreeSpecification.scala | 5 +---- 3 files changed, 2 insertions(+), 9 deletions(-) diff --git a/data/shared/src/main/scala/sigma/ast/SigmaPredef.scala b/data/shared/src/main/scala/sigma/ast/SigmaPredef.scala index 897ac6d757..ebe8aa0213 100644 --- a/data/shared/src/main/scala/sigma/ast/SigmaPredef.scala +++ b/data/shared/src/main/scala/sigma/ast/SigmaPredef.scala @@ -430,8 +430,7 @@ object SigmaPredef { AvlTreeFunc, SubstConstantsFunc, ExecuteFromVarFunc, - ExecuteFromSelfRegFunc, - SerializeFunc + ExecuteFromSelfRegFunc ).map(f => f.name -> f).toMap def comparisonOp(symbolName: String, opDesc: ValueCompanion, desc: String, args: Seq[ArgInfo]) = { 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 ddbec96518..5595ded3db 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/GraphBuilding.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/GraphBuilding.scala @@ -1147,9 +1147,6 @@ trait GraphBuilding extends Base with DefRewriting { IR: IRContext => val c1 = asRep[Coll[Byte]](argsV(0)) val c2 = asRep[Coll[Byte]](argsV(1)) g.xor(c1, c2) - case SGlobalMethods.serializeMethod.name => - val value = asRep[Any](argsV(0)) - g.serialize(value) case _ => throwError() } case (x: Ref[tNum], _: SNumericTypeMethods) => method.name match { diff --git a/sc/shared/src/test/scala/sigmastate/ErgoTreeSpecification.scala b/sc/shared/src/test/scala/sigmastate/ErgoTreeSpecification.scala index 6e6fb824de..05a6017e98 100644 --- a/sc/shared/src/test/scala/sigmastate/ErgoTreeSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/ErgoTreeSpecification.scala @@ -479,10 +479,7 @@ class ErgoTreeSpecification extends SigmaDslTesting with ContractsTestkit with C { import SGlobalMethods._ (SGlobal.typeId, Seq( MInfo(1, groupGeneratorMethod), MInfo(2, xorMethod) - ) ++ (if (isV6Activated) Seq( - // methods added in v6.0 - MInfo(3, serializeMethod) - ) else Seq.empty), true) + ), true) }, { import SCollectionMethods._ (SCollection.typeId, Seq( From 15e21a4af57a45ae9a9136ad14278ac7951611ab Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Fri, 7 Jun 2024 16:00:54 +0300 Subject: [PATCH 134/314] importing new test for ErgoTreeSpecification from i486 --- .../scala/sigmastate/ErgoTreeSpecification.scala | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/sc/shared/src/test/scala/sigmastate/ErgoTreeSpecification.scala b/sc/shared/src/test/scala/sigmastate/ErgoTreeSpecification.scala index 7539bd5e48..21966aa0a9 100644 --- a/sc/shared/src/test/scala/sigmastate/ErgoTreeSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/ErgoTreeSpecification.scala @@ -21,14 +21,14 @@ import sigma.compiler.CompilerSettings import sigma.eval.EvalSettings import sigma.exceptions.{CostLimitException, InterpreterException} import sigma.serialization.ErgoTreeSerializer.DefaultSerializer -import sigmastate.Plus +import sigmastate.{CrossVersionProps, Plus} import sigmastate.utils.Helpers.TryOps /** Regression tests with ErgoTree related test vectors. * This test vectors verify various constants which are consensus critical and should not change. */ -class ErgoTreeSpecification extends SigmaDslTesting with ContractsTestkit { +class ErgoTreeSpecification extends SigmaDslTesting with ContractsTestkit with CrossVersionProps { property("Value.sourceContext") { val srcCtx = SourceContext.fromParserIndex(0, "") @@ -313,10 +313,12 @@ class ErgoTreeSpecification extends SigmaDslTesting with ContractsTestkit { */ case class MInfo(methodId: Byte, method: SMethod, isResolvableFromIds: Boolean = true) + def isV6Activated = VersionContext.current.isV6SoftForkActivated + // NOTE, the type code constants are checked above // The methodId codes as checked here, they MUST be PRESERVED. // The following table should be made dependent on HF activation - val methods = Table( + def methods = Table( ("typeId", "methods", "CanHaveMethods"), (SBoolean.typeId, Seq.empty[MInfo], true), (SByte.typeId, Seq.empty[MInfo], false), @@ -419,7 +421,10 @@ class ErgoTreeSpecification extends SigmaDslTesting with ContractsTestkit { { import SGlobalMethods._ (SGlobal.typeId, Seq( MInfo(1, groupGeneratorMethod), MInfo(2, xorMethod) - ), true) + ) ++ (if (isV6Activated) Seq( + // methods added in v6.0 + MInfo(3, serializeMethod) + ) else Seq.empty), true) }, { import SCollectionMethods._ (SCollection.typeId, Seq( From 15f4f67ba83489dff1d2ea7df232b5bea15c01a4 Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Fri, 7 Jun 2024 21:50:00 +0300 Subject: [PATCH 135/314] removing modq methods --- .../src/main/scala/sigma/ast/methods.scala | 23 ------------------- 1 file changed, 23 deletions(-) diff --git a/data/shared/src/main/scala/sigma/ast/methods.scala b/data/shared/src/main/scala/sigma/ast/methods.scala index 4656d3361e..fc2e5f11d0 100644 --- a/data/shared/src/main/scala/sigma/ast/methods.scala +++ b/data/shared/src/main/scala/sigma/ast/methods.scala @@ -318,32 +318,9 @@ case object SBigIntMethods extends SNumericTypeMethods { val ToNBits = SMethod(this, "nbits", SFunc(this.ownerType, SLong), 8, ToNBitsCostInfo.costKind) .withInfo(ModQ, "Encode this big integer value as NBits") - /** - * todo: remove - * - * The following `modQ` methods are not fully implemented in v4.x and this descriptors. - * This descritors are remain here in the code and are waiting for full implementation - * is upcoming soft-forks at which point the cost parameters should be calculated and - * changed. - */ - val ModQMethod = SMethod(this, "modQ", SFunc(this.ownerType, SBigInt), 1, FixedCost(JitCost(1))) - .withInfo(ModQ, "Returns this \\lst{mod} Q, i.e. remainder of division by Q, where Q is an order of the cryprographic group.") - val PlusModQMethod = SMethod(this, "plusModQ", SFunc(IndexedSeq(this.ownerType, SBigInt), SBigInt), 2, FixedCost(JitCost(1))) - .withInfo(ModQArithOp.PlusModQ, "Adds this number with \\lst{other} by module Q.", ArgInfo("other", "Number to add to this.")) - val MinusModQMethod = SMethod(this, "minusModQ", SFunc(IndexedSeq(this.ownerType, SBigInt), SBigInt), 3, FixedCost(JitCost(1))) - .withInfo(ModQArithOp.MinusModQ, "Subtracts \\lst{other} number from this by module Q.", ArgInfo("other", "Number to subtract from this.")) - val MultModQMethod = SMethod(this, "multModQ", SFunc(IndexedSeq(this.ownerType, SBigInt), SBigInt), 4, FixedCost(JitCost(1))) - .withIRInfo(MethodCallIrBuilder) - .withInfo(MethodCall, "Multiply this number with \\lst{other} by module Q.", ArgInfo("other", "Number to multiply with this.")) - protected override def getMethods(): Seq[SMethod] = { if (VersionContext.current.isV6SoftForkActivated) { super.getMethods() ++ Seq(ToNBits) - // ModQMethod, - // PlusModQMethod, - // MinusModQMethod, - // TODO soft-fork: https://github.com/ScorexFoundation/sigmastate-interpreter/issues/479 - // MultModQMethod, } else { super.getMethods() } From 303f96986e56ac0f0c5863e328eb9d4771fb989f Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Sat, 8 Jun 2024 21:31:27 +0300 Subject: [PATCH 136/314] expUnsigned impl (test still failing) --- .../src/main/scala/sigma/SigmaDsl.scala | 2 ++ .../main/scala/sigma/data/CGroupElement.scala | 5 +++- .../sigma/reflection/ReflectionData.scala | 3 ++ .../src/main/scala/sigma/ast/methods.scala | 28 +++++++++++++++---- .../sigma/compiler/ir/GraphBuilding.scala | 3 ++ .../ir/wrappers/sigma/SigmaDslUnit.scala | 1 + .../ir/wrappers/sigma/impl/SigmaDslImpl.scala | 14 ++++++++++ .../sigma/compiler/phases/SigmaBinder.scala | 4 +++ .../sigma/compiler/phases/SigmaTyper.scala | 5 ++++ 9 files changed, 58 insertions(+), 7 deletions(-) diff --git a/core/shared/src/main/scala/sigma/SigmaDsl.scala b/core/shared/src/main/scala/sigma/SigmaDsl.scala index cc102b6b36..723ce03bc6 100644 --- a/core/shared/src/main/scala/sigma/SigmaDsl.scala +++ b/core/shared/src/main/scala/sigma/SigmaDsl.scala @@ -298,6 +298,8 @@ trait GroupElement { */ def exp(k: BigInt): GroupElement + def expUnsigned(k: UnsignedBigInt): GroupElement + /** Group operation. */ def multiply(that: GroupElement): GroupElement diff --git a/core/shared/src/main/scala/sigma/data/CGroupElement.scala b/core/shared/src/main/scala/sigma/data/CGroupElement.scala index ed4849f0d7..c5483797cf 100644 --- a/core/shared/src/main/scala/sigma/data/CGroupElement.scala +++ b/core/shared/src/main/scala/sigma/data/CGroupElement.scala @@ -3,7 +3,7 @@ package sigma.data import sigma.crypto.{CryptoFacade, Ecp} import sigma.serialization.GroupElementSerializer import sigma.util.Extensions.EcpOps -import sigma.{BigInt, Coll, Colls, GroupElement} +import sigma.{BigInt, Coll, Colls, GroupElement, UnsignedBigInt} /** A default implementation of [[GroupElement]] interface. * @@ -21,6 +21,9 @@ case class CGroupElement(override val wrappedValue: Ecp) extends GroupElement wi override def exp(k: BigInt): GroupElement = CGroupElement(CryptoFacade.exponentiatePoint(wrappedValue, k.asInstanceOf[CBigInt].wrappedValue)) + override def expUnsigned(k: UnsignedBigInt): GroupElement = + CGroupElement(CryptoFacade.exponentiatePoint(wrappedValue, k.asInstanceOf[CUnsignedBigInt].wrappedValue)) + override def multiply(that: GroupElement): GroupElement = CGroupElement(CryptoFacade.multiplyPoints(wrappedValue, that.asInstanceOf[CGroupElement].wrappedValue)) diff --git a/core/shared/src/main/scala/sigma/reflection/ReflectionData.scala b/core/shared/src/main/scala/sigma/reflection/ReflectionData.scala index 028e68bf72..e0e890abca 100644 --- a/core/shared/src/main/scala/sigma/reflection/ReflectionData.scala +++ b/core/shared/src/main/scala/sigma/reflection/ReflectionData.scala @@ -286,6 +286,9 @@ object ReflectionData { mkMethod(clazz, "exp", Array[Class[_]](classOf[BigInt])) { (obj, args) => obj.asInstanceOf[GroupElement].exp(args(0).asInstanceOf[BigInt]) }, + mkMethod(clazz, "expUnsigned", Array[Class[_]](classOf[UnsignedBigInt])) { (obj, args) => + obj.asInstanceOf[GroupElement].expUnsigned(args(0).asInstanceOf[UnsignedBigInt]) + }, mkMethod(clazz, "multiply", Array[Class[_]](classOf[GroupElement])) { (obj, args) => obj.asInstanceOf[GroupElement].multiply(args(0).asInstanceOf[GroupElement]) }, diff --git a/data/shared/src/main/scala/sigma/ast/methods.scala b/data/shared/src/main/scala/sigma/ast/methods.scala index fc2e5f11d0..8499ecd46e 100644 --- a/data/shared/src/main/scala/sigma/ast/methods.scala +++ b/data/shared/src/main/scala/sigma/ast/methods.scala @@ -364,6 +364,11 @@ case object SGroupElementMethods extends MonoTypeMethods { "Exponentiate this \\lst{GroupElement} to the given number. Returns this to the power of k", ArgInfo("k", "The power")) + lazy val ExponentiateUnsignedMethod: SMethod = SMethod( + this, "expUnsigned", SFunc(Array(this.ownerType, SUnsignedBigInt), this.ownerType), 6, Exponentiate.costKind) // todo: recheck costing + .withInfo("Exponentiate this \\lst{GroupElement} to the given number. Returns this to the power of k", + ArgInfo("k", "The power")) + lazy val MultiplyMethod: SMethod = SMethod( this, "multiply", SFunc(Array(this.ownerType, SGroupElement), this.ownerType), 4, MultiplyGroup.costKind) .withIRInfo({ case (builder, obj, _, Seq(arg), _) => @@ -379,16 +384,27 @@ case object SGroupElementMethods extends MonoTypeMethods { .withIRInfo(MethodCallIrBuilder) .withInfo(PropertyCall, "Inverse element of the group.") - protected override def getMethods(): Seq[SMethod] = super.getMethods() ++ Seq( + protected override def getMethods(): Seq[SMethod] = { /* TODO soft-fork: https://github.com/ScorexFoundation/sigmastate-interpreter/issues/479 SMethod(this, "isIdentity", SFunc(this, SBoolean), 1) .withInfo(PropertyCall, "Checks if this value is identity element of the eliptic curve group."), */ - GetEncodedMethod, - ExponentiateMethod, - MultiplyMethod, - NegateMethod - ) + val v5Methods = Seq( + GetEncodedMethod, + ExponentiateMethod, + MultiplyMethod, + NegateMethod) + + super.getMethods() ++ (if (VersionContext.current.isV6SoftForkActivated) { + v5Methods + } else { + v5Methods ++ Seq(ExponentiateUnsignedMethod) + }) + } + + def expUnsigned_eval(mc: MethodCall, power: UnsignedBigInt)(implicit E: ErgoTreeEvaluator): GroupElement = { + ??? + } } /** Methods of type `SigmaProp` which represent sigma-protocol propositions. */ 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 3e3b576c3e..e2350b8338 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/GraphBuilding.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/GraphBuilding.scala @@ -1024,6 +1024,9 @@ trait GraphBuilding extends Base with DefRewriting { IR: IRContext => case SGroupElementMethods.ExponentiateMethod.name => val k = asRep[BigInt](argsV(0)) ge.exp(k) + case SGroupElementMethods.ExponentiateUnsignedMethod.name => + val k = asRep[UnsignedBigInt](argsV(0)) + ge.expUnsigned(k) case _ => throwError } case (box: Ref[Box]@unchecked, SBoxMethods) => method.name match { diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/SigmaDslUnit.scala b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/SigmaDslUnit.scala index 8616822dd1..b3be395a74 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/SigmaDslUnit.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/SigmaDslUnit.scala @@ -25,6 +25,7 @@ import scalan._ }; trait GroupElement extends Def[GroupElement] { def exp(k: Ref[BigInt]): Ref[GroupElement]; + def expUnsigned(k: Ref[UnsignedBigInt]): Ref[GroupElement]; def multiply(that: Ref[GroupElement]): Ref[GroupElement]; def negate: Ref[GroupElement]; def getEncoded: Ref[Coll[Byte]] diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/SigmaDslImpl.scala b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/SigmaDslImpl.scala index 060759099e..27ebaa717c 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/SigmaDslImpl.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/SigmaDslImpl.scala @@ -444,6 +444,13 @@ object GroupElement extends EntityObject("GroupElement") { true, false, element[GroupElement])) } + override def expUnsigned(k: Ref[UnsignedBigInt]): Ref[GroupElement] = { + asRep[GroupElement](mkMethodCall(self, + GroupElementClass.getMethod("expUnsigned", classOf[Sym]), + Array[AnyRef](k), + true, false, element[GroupElement])) + } + override def multiply(that: Ref[GroupElement]): Ref[GroupElement] = { asRep[GroupElement](mkMethodCall(self, GroupElementClass.getMethod("multiply", classOf[Sym]), @@ -491,6 +498,13 @@ object GroupElement extends EntityObject("GroupElement") { true, true, element[GroupElement])) } + def expUnsigned(k: Ref[UnsignedBigInt]): Ref[GroupElement] = { + asRep[GroupElement](mkMethodCall(source, + GroupElementClass.getMethod("expUnsigned", classOf[Sym]), + Array[AnyRef](k), + true, true, element[GroupElement])) + } + def multiply(that: Ref[GroupElement]): Ref[GroupElement] = { asRep[GroupElement](mkMethodCall(source, GroupElementClass.getMethod("multiply", classOf[Sym]), diff --git a/sc/shared/src/main/scala/sigma/compiler/phases/SigmaBinder.scala b/sc/shared/src/main/scala/sigma/compiler/phases/SigmaBinder.scala index af5be938be..1877131718 100644 --- a/sc/shared/src/main/scala/sigma/compiler/phases/SigmaBinder.scala +++ b/sc/shared/src/main/scala/sigma/compiler/phases/SigmaBinder.scala @@ -56,6 +56,10 @@ class SigmaBinder(env: ScriptEnv, builder: SigmaBuilder, case _ @ Apply(ApplyTypes(Ident("Coll", _), Seq(tpe)), args) => Some(mkConcreteCollection(args, tpe)) + // hack to make possible to write g.exp(ubi) for both unsigned and signed big integers + case Apply(Select(obj, n, resType), args) if n == "exp" && args(0).isInstanceOf[Value[SUnsignedBigInt.type]] => + Some(Apply(Select(obj, "expUnsigned", resType), args)) + // Rule: Coll(...) --> case Apply(Ident("Coll", _), args) => val tpe = if (args.isEmpty) NoType else args(0).tpe diff --git a/sc/shared/src/main/scala/sigma/compiler/phases/SigmaTyper.scala b/sc/shared/src/main/scala/sigma/compiler/phases/SigmaTyper.scala index 679d98a18f..3d62ff8dd8 100644 --- a/sc/shared/src/main/scala/sigma/compiler/phases/SigmaTyper.scala +++ b/sc/shared/src/main/scala/sigma/compiler/phases/SigmaTyper.scala @@ -168,6 +168,11 @@ class SigmaTyper(val builder: SigmaBuilder, case app @ Apply(sel @ Select(obj, n, _), args) => val newSel = assignType(env, sel) val newArgs = args.map(assignType(env, _)) + if(n=="expUnsigned") { + println(app) + println("newSel: " + newSel) + println("newArgs: " + newArgs) + } newSel.tpe match { case genFunTpe @ SFunc(argTypes, _, _) => // If it's a function then the application has type of that function's return type. From e7bd2a3c2adf6363a79f314e114cacdab144eee8 Mon Sep 17 00:00:00 2001 From: Alexander Slesarenko Date: Thu, 6 Jun 2024 12:34:46 +0300 Subject: [PATCH 137/314] moving newFeature related code from serializePR --- .../sigmastate/helpers/SigmaPPrint.scala | 6 +- .../scala/sigmastate/lang/LangTests.scala | 6 + .../sigmastate/lang/SigmaParserTest.scala | 12 + .../sigmastate/helpers/SigmaPPrintSpec.scala | 1 - .../sigma/LanguageSpecificationBase.scala | 126 ++++++ ...on.scala => LanguageSpecificationV5.scala} | 358 +----------------- .../scala/sigma/LanguageSpecificationV6.scala | 348 +++++++++++++++++ .../test/scala/sigma/SigmaDslTesting.scala | 142 +++++-- .../CompilerCrossVersionProps.scala | 11 +- .../sigmastate/lang/SigmaBinderTest.scala | 13 + .../sigmastate/lang/SigmaTyperTest.scala | 9 +- 11 files changed, 634 insertions(+), 398 deletions(-) rename {sc => parsers}/shared/src/test/scala/sigmastate/helpers/SigmaPPrint.scala (98%) create mode 100644 sc/shared/src/test/scala/sigma/LanguageSpecificationBase.scala rename sc/shared/src/test/scala/sigma/{SigmaDslSpecification.scala => LanguageSpecificationV5.scala} (96%) create mode 100644 sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala diff --git a/sc/shared/src/test/scala/sigmastate/helpers/SigmaPPrint.scala b/parsers/shared/src/test/scala/sigmastate/helpers/SigmaPPrint.scala similarity index 98% rename from sc/shared/src/test/scala/sigmastate/helpers/SigmaPPrint.scala rename to parsers/shared/src/test/scala/sigmastate/helpers/SigmaPPrint.scala index 1b0f7b112d..24aaeddefd 100644 --- a/sc/shared/src/test/scala/sigmastate/helpers/SigmaPPrint.scala +++ b/parsers/shared/src/test/scala/sigmastate/helpers/SigmaPPrint.scala @@ -5,15 +5,13 @@ import org.ergoplatform.ErgoBox.RegisterId import org.ergoplatform.settings.ErgoAlgos import pprint.{PPrinter, Tree} import sigma.ast.SCollection.{SBooleanArray, SByteArray, SByteArray2} -import sigma.ast._ +import sigma.ast.{ConstantNode, FuncValue, MethodCall, ValueCompanion, _} import sigma.crypto.EcPointType import sigma.data.{AvlTreeData, AvlTreeFlags, CollType, PrimitiveType, TrivialProp} import sigma.serialization.GroupElementSerializer import sigma.{Coll, GroupElement} -import sigma.ast.{ConstantNode, FuncValue, ValueCompanion} -import sigmastate._ import sigmastate.crypto.GF2_192_Poly -import sigma.ast.MethodCall + import java.math.BigInteger import scala.collection.compat.immutable.ArraySeq import scala.collection.mutable diff --git a/parsers/shared/src/test/scala/sigmastate/lang/LangTests.scala b/parsers/shared/src/test/scala/sigmastate/lang/LangTests.scala index 32943bca44..de83070ac3 100644 --- a/parsers/shared/src/test/scala/sigmastate/lang/LangTests.scala +++ b/parsers/shared/src/test/scala/sigmastate/lang/LangTests.scala @@ -79,4 +79,10 @@ trait LangTests extends Matchers with NegativeTesting { node }))(tree) } + + /** Execute the given `block` having `version` as both activated and ErgoTree version. */ + def runWithVersion[T](version: Byte)(block: => T): T = { + VersionContext.withVersions(version, version)(block) + } + } diff --git a/parsers/shared/src/test/scala/sigmastate/lang/SigmaParserTest.scala b/parsers/shared/src/test/scala/sigmastate/lang/SigmaParserTest.scala index 02b28f86ca..dc63330f95 100644 --- a/parsers/shared/src/test/scala/sigmastate/lang/SigmaParserTest.scala +++ b/parsers/shared/src/test/scala/sigmastate/lang/SigmaParserTest.scala @@ -14,6 +14,7 @@ import SigmaPredef.PredefinedFuncRegistry import sigma.ast.syntax._ import sigmastate.lang.parsers.ParserException import sigma.serialization.OpCodes +import sigmastate.helpers.SigmaPPrint class SigmaParserTest extends AnyPropSpec with ScalaCheckPropertyChecks with Matchers with LangTests { import StdSigmaBuilder._ @@ -34,6 +35,17 @@ class SigmaParserTest extends AnyPropSpec with ScalaCheckPropertyChecks with Mat } } + /** Checks parsing result, printing the actual value as a test vector if expected value + * is not equal to actual. + */ + def checkParsed(x: String, expected: SValue) = { + val parsed = parse(x) + if (expected != parsed) { + SigmaPPrint.pprintln(parsed, width = 100) + } + parsed shouldBe expected + } + def parseWithException(x: String): SValue = { SigmaParser(x) match { case Parsed.Success(v, _) => v diff --git a/sc/jvm/src/test/scala/sigmastate/helpers/SigmaPPrintSpec.scala b/sc/jvm/src/test/scala/sigmastate/helpers/SigmaPPrintSpec.scala index 54c0f652dc..ffd591b0df 100644 --- a/sc/jvm/src/test/scala/sigmastate/helpers/SigmaPPrintSpec.scala +++ b/sc/jvm/src/test/scala/sigmastate/helpers/SigmaPPrintSpec.scala @@ -8,7 +8,6 @@ import sigma.SigmaDslTesting import sigma.ast._ import sigma.data.{AvlTreeData, AvlTreeFlags, CBox, CollType, Digest32Coll} import ErgoTree.HeaderType -import sigmastate.eval._ import sigma.ast.MethodCall import sigma.serialization.OpCodes import sigmastate.utils.Helpers diff --git a/sc/shared/src/test/scala/sigma/LanguageSpecificationBase.scala b/sc/shared/src/test/scala/sigma/LanguageSpecificationBase.scala new file mode 100644 index 0000000000..2bb44fc910 --- /dev/null +++ b/sc/shared/src/test/scala/sigma/LanguageSpecificationBase.scala @@ -0,0 +1,126 @@ +package sigma + +import org.scalatest.BeforeAndAfterAll +import sigma.ast.JitCost +import sigma.eval.{EvalSettings, Profiler} +import sigmastate.CompilerCrossVersionProps +import sigmastate.interpreter.CErgoTreeEvaluator +import scala.util.Success + +/** Base class for language test suites (one suite for each language version: 5.0, 6.0, etc.) + * Each suite tests every method of every SigmaDsl type to be equivalent to + * the evaluation of the corresponding ErgoScript operation. + * + * The properties of this suite exercise two interpreters: the current (aka `old` + * interpreter) and the new interpreter for a next soft-fork. After the soft-fork is + * released, the new interpreter becomes current at which point the `old` and `new` + * interpreters in this suite should be equivalent. This change is reflected in this + * suite by commiting changes in expected values. + * The `old` and `new` interpreters are compared like the following: + * 1) for existingFeature the interpreters should be equivalent + * 2) for changedFeature the test cases contain different expected values + * 3) for newFeature the old interpreter should throw and the new interpreter is checked + * against expected values. + * + * This suite can be used for Cost profiling, i.e. measurements of operations times and + * comparing them with cost parameters of the operations. + * + * The following settings should be specified for profiling: + * isMeasureOperationTime = true + * isMeasureScriptTime = true + * isLogEnabled = false + * printTestVectors = false + * costTracingEnabled = false + * isTestRun = true + * perTestWarmUpIters = 1 + * nBenchmarkIters = 1 + */ +abstract class LanguageSpecificationBase extends SigmaDslTesting + with CompilerCrossVersionProps + with BeforeAndAfterAll { suite => + + /** Version of the language (ErgoScript/ErgoTree) which is specified by this suite. */ + def languageVersion: Byte + + /** Use VersionContext so that each property in this suite runs under correct + * parameters. + */ + protected override def testFun_Run(testName: String, testFun: => Any): Unit = { + VersionContext.withVersions(activatedVersionInTests, ergoTreeVersionInTests) { + super.testFun_Run(testName, testFun) + } + } + + implicit override val generatorDrivenConfig: PropertyCheckConfiguration = PropertyCheckConfiguration(minSuccessful = 30) + + val evalSettingsInTests = CErgoTreeEvaluator.DefaultEvalSettings.copy( + isMeasureOperationTime = true, + isMeasureScriptTime = true, + isLogEnabled = false, // don't commit the `true` value (travis log is too high) + printTestVectors = false, // don't commit the `true` value (travis log is too high) + + /** Should always be enabled in tests (and false by default) + * Should be disabled for cost profiling, which case the new costs are not checked. + */ + costTracingEnabled = true, + profilerOpt = Some(CErgoTreeEvaluator.DefaultProfiler), + isTestRun = true + ) + + def warmupSettings(p: Profiler) = evalSettingsInTests.copy( + isLogEnabled = false, + printTestVectors = false, + profilerOpt = Some(p) + ) + + implicit override def evalSettings: EvalSettings = { + warmupProfiler match { + case Some(p) => warmupSettings(p) + case _ => evalSettingsInTests + } + } + + override val perTestWarmUpIters = 0 + + override val nBenchmarkIters = 0 + + override val okRunTestsWithoutMCLowering: Boolean = true + + implicit def IR = createIR() + + def testCases[A, B](cases: Seq[(A, Expected[B])], f: Feature[A, B]) = { + val table = Table(("x", "y"), cases: _*) + forAll(table) { (x, expectedRes) => + val res = f.checkEquality(x) + val resValue = res.map(_._1) + val (expected, expDetailsOpt) = expectedRes.newResults(ergoTreeVersionInTests) + checkResult(resValue, expected.value, failOnTestVectors = true, + "SigmaDslSpecifiction#testCases: compare expected new result with res = f.checkEquality(x)") + res match { + case Success((value, details)) => + details.cost shouldBe JitCost(expected.verificationCost.get) + expDetailsOpt.foreach(expDetails => + if (details.trace != expDetails.trace) { + printCostDetails(f.script, details) + details.trace shouldBe expDetails.trace + } + ) + } + } + } + + override protected def beforeAll(): Unit = { + prepareSamples[BigInt] + prepareSamples[GroupElement] + prepareSamples[AvlTree] + prepareSamples[Box] + prepareSamples[PreHeader] + prepareSamples[Header] + prepareSamples[(BigInt, BigInt)] + prepareSamples[(GroupElement, GroupElement)] + prepareSamples[(AvlTree, AvlTree)] + prepareSamples[(Box, Box)] + prepareSamples[(PreHeader, PreHeader)] + prepareSamples[(Header, Header)] + } +} diff --git a/sc/shared/src/test/scala/sigma/SigmaDslSpecification.scala b/sc/shared/src/test/scala/sigma/LanguageSpecificationV5.scala similarity index 96% rename from sc/shared/src/test/scala/sigma/SigmaDslSpecification.scala rename to sc/shared/src/test/scala/sigma/LanguageSpecificationV5.scala index c820e65e73..700b48fd13 100644 --- a/sc/shared/src/test/scala/sigma/SigmaDslSpecification.scala +++ b/sc/shared/src/test/scala/sigma/LanguageSpecificationV5.scala @@ -5,31 +5,28 @@ import org.ergoplatform._ import org.ergoplatform.settings.ErgoAlgos import org.scalacheck.Arbitrary._ import org.scalacheck.{Arbitrary, Gen} -import org.scalatest.BeforeAndAfterAll import scorex.crypto.authds.avltree.batch._ import scorex.crypto.authds.{ADKey, ADValue} import scorex.crypto.hash.{Blake2b256, Digest32} import scorex.util.ModifierId import sigma.Extensions.{ArrayOps, CollOps} +import sigma.ast.ErgoTree.{HeaderType, ZeroHeader} import sigma.ast.SCollection._ -import sigma.ast._ import sigma.ast.syntax._ +import sigma.ast.{Apply, MethodCall, PropertyCall, _} +import sigma.data.OrderingOps._ import sigma.data.RType._ import sigma.data._ +import sigma.eval.Extensions.{ByteExt, IntExt, LongExt, ShortExt} +import sigma.eval.{CostDetails, EvalSettings, SigmaDsl, TracedCost} +import sigma.exceptions.InvalidType +import sigma.serialization.ValueCodes.OpCode import sigma.util.Extensions.{BooleanOps, IntOps, LongOps} import sigma.{VersionContext, ast, data, _} -import ErgoTree.{HeaderType, ZeroHeader} -import sigma.eval.{CostDetails, EvalSettings, Profiler, SigmaDsl, TracedCost} -import sigmastate._ import sigmastate.eval.Extensions.AvlTreeOps -import sigma.eval.Extensions.{ByteExt, IntExt, LongExt, ShortExt} -import OrderingOps._ import sigmastate.eval._ import sigmastate.helpers.TestingHelpers._ import sigmastate.interpreter._ -import sigma.ast.{Apply, MethodCall, PropertyCall} -import sigma.exceptions.InvalidType -import sigma.serialization.ValueCodes.OpCode import sigmastate.utils.Extensions._ import sigmastate.utils.Helpers import sigmastate.utils.Helpers._ @@ -38,122 +35,18 @@ import java.math.BigInteger import scala.collection.compat.immutable.ArraySeq import scala.util.{Failure, Success} -/** This suite tests every method of every SigmaDsl type to be equivalent to - * the evaluation of the corresponding ErgoScript operation. - * - * The properties of this suite excercise two interpreters: the current (aka `old` - * interpreter) and the new interpreter for a next soft-fork. After the soft-fork is - * released, the new interpreter becomes current at which point the `old` and `new` - * interpreters in this suite should be equivalent. This change is reflected in this - * suite by commiting changes in expected values. - * The `old` and `new` interpreters are compared like the following: - * 1) for existingFeature the interpreters should be equivalent - * 2) for changedFeature the test cases contain different expected values - * 3) for newFeature the old interpreter should throw and the new interpreter is checked - * against expected values. - * - * This suite can be used for Cost profiling, i.e. measurements of operations times and - * comparing them with cost parameteres of the operations. + +/** This suite tests all operations for v5.0 version of the language. + * The base classes establish the infrastructure for the tests. * - * The following settings should be specified for profiling: - * isMeasureOperationTime = true - * isMeasureScriptTime = true - * isLogEnabled = false - * printTestVectors = false - * costTracingEnabled = false - * isTestRun = true - * perTestWarmUpIters = 1 - * nBenchmarkIters = 1 + * @see SigmaDslSpecificationBase */ -class SigmaDslSpecification extends SigmaDslTesting - with CompilerCrossVersionProps - with BeforeAndAfterAll { suite => - - /** Use VersionContext so that each property in this suite runs under correct - * parameters. - */ - protected override def testFun_Run(testName: String, testFun: => Any): Unit = { - VersionContext.withVersions(activatedVersionInTests, ergoTreeVersionInTests) { - super.testFun_Run(testName, testFun) - } - } - - implicit override val generatorDrivenConfig = PropertyCheckConfiguration(minSuccessful = 30) +class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => - val evalSettingsInTests = CErgoTreeEvaluator.DefaultEvalSettings.copy( - isMeasureOperationTime = true, - isMeasureScriptTime = true, - isLogEnabled = false, // don't commit the `true` value (travis log is too high) - printTestVectors = false, // don't commit the `true` value (travis log is too high) - - /** Should always be enabled in tests (and false by default) - * Should be disabled for cost profiling, which case the new costs are not checked. - */ - costTracingEnabled = true, - - profilerOpt = Some(CErgoTreeEvaluator.DefaultProfiler), - isTestRun = true - ) - - def warmupSettings(p: Profiler) = evalSettingsInTests.copy( - isLogEnabled = false, - printTestVectors = false, - profilerOpt = Some(p) - ) - - implicit override def evalSettings: EvalSettings = { - warmupProfiler match { - case Some(p) => warmupSettings(p) - case _ => evalSettingsInTests - } - } - - override val perTestWarmUpIters = 0 - - override val nBenchmarkIters = 0 - - override val okRunTestsWithoutMCLowering: Boolean = true - - implicit def IR = createIR() - - def testCases[A, B](cases: Seq[(A, Expected[B])], f: Feature[A, B]) = { - val table = Table(("x", "y"), cases:_*) - forAll(table) { (x, expectedRes) => - val res = f.checkEquality(x) - val resValue = res.map(_._1) - val (expected, expDetailsOpt) = expectedRes.newResults(ergoTreeVersionInTests) - checkResult(resValue, expected.value, failOnTestVectors = true, - "SigmaDslSpecifiction#testCases: compare expected new result with res = f.checkEquality(x)") - res match { - case Success((value, details)) => - details.cost shouldBe JitCost(expected.verificationCost.get) - expDetailsOpt.foreach(expDetails => - if (details.trace != expDetails.trace) { - printCostDetails(f.script, details) - details.trace shouldBe expDetails.trace - } - ) - } - } - } + override def languageVersion: Byte = VersionContext.JitActivationVersion import TestData._ - override protected def beforeAll(): Unit = { - prepareSamples[BigInt] - prepareSamples[GroupElement] - prepareSamples[AvlTree] - prepareSamples[Box] - prepareSamples[PreHeader] - prepareSamples[Header] - prepareSamples[(BigInt, BigInt)] - prepareSamples[(GroupElement, GroupElement)] - prepareSamples[(AvlTree, AvlTree)] - prepareSamples[(Box, Box)] - prepareSamples[(PreHeader, PreHeader)] - prepareSamples[(Header, Header)] - } - ///===================================================== /// CostDetails shared among test cases ///----------------------------------------------------- @@ -232,17 +125,6 @@ class SigmaDslSpecification extends SigmaDslTesting /// Boolean type operations ///----------------------------------------------------- - property("Boolean methods equivalence") { - val toByte = newFeature((x: Boolean) => x.toByte, "{ (x: Boolean) => x.toByte }") - - val cases = Seq( - (true, Success(1.toByte)), - (false, Success(0.toByte)) - ) - - testCases(cases, toByte) - } - property("BinXor(logical XOR) equivalence") { val binXor = existingFeature((x: (Boolean, Boolean)) => x._1 ^ x._2, "{ (x: (Boolean, Boolean)) => x._1 ^ x._2 }", @@ -1057,31 +939,6 @@ class SigmaDslSpecification extends SigmaDslTesting swapArgs(LE_cases, cost = 1768, newCostDetails = binaryRelationCostDetails(GE, SByte)), ">=", GE.apply)(_ >= _) } - - property("Byte methods equivalence (new features)") { - lazy val toBytes = newFeature((x: Byte) => x.toBytes, "{ (x: Byte) => x.toBytes }") - lazy val toAbs = newFeature((x: Byte) => x.toAbs, "{ (x: Byte) => x.toAbs }") - lazy val compareTo = newFeature( - (x: (Byte, Byte)) => x._1.compareTo(x._2), - "{ (x: (Byte, Byte)) => x._1.compareTo(x._2) }") - - lazy val bitOr = newFeature( - { (x: (Byte, Byte)) => (x._1 | x._2).toByteExact }, - "{ (x: (Byte, Byte)) => (x._1 | x._2).toByteExact }") - - lazy val bitAnd = newFeature( - { (x: (Byte, Byte)) => (x._1 & x._2).toByteExact }, - "{ (x: (Byte, Byte)) => (x._1 & x._2).toByteExact }") - - forAll { x: Byte => - Seq(toBytes, toAbs).foreach(f => f.checkEquality(x)) - } - - forAll { x: (Byte, Byte) => - Seq(compareTo, bitOr, bitAnd).foreach(_.checkEquality(x)) - } - } - property("Short methods equivalence") { SShort.upcast(0.toShort) shouldBe 0.toShort // boundary test case SShort.downcast(0.toShort) shouldBe 0.toShort // boundary test case @@ -1362,29 +1219,6 @@ class SigmaDslSpecification extends SigmaDslTesting ">=", GE.apply)(_ >= _) } - property("Short methods equivalence (new features)") { - lazy val toBytes = newFeature((x: Short) => x.toBytes, "{ (x: Short) => x.toBytes }") - lazy val toAbs = newFeature((x: Short) => x.toAbs, "{ (x: Short) => x.toAbs }") - - lazy val compareTo = newFeature((x: (Short, Short)) => x._1.compareTo(x._2), - "{ (x: (Short, Short)) => x._1.compareTo(x._2) }") - - lazy val bitOr = newFeature( - { (x: (Short, Short)) => (x._1 | x._2).toShortExact }, - "{ (x: (Short, Short)) => x._1 | x._2 }") - - lazy val bitAnd = newFeature( - { (x: (Short, Short)) => (x._1 & x._2).toShortExact }, - "{ (x: (Short, Short)) => x._1 & x._2 }") - - forAll { x: Short => - Seq(toBytes, toAbs).foreach(_.checkEquality(x)) - } - forAll { x: (Short, Short) => - Seq(compareTo, bitOr, bitAnd).foreach(_.checkEquality(x)) - } - } - property("Int methods equivalence") { SInt.upcast(0) shouldBe 0 // boundary test case SInt.downcast(0) shouldBe 0 // boundary test case @@ -1665,28 +1499,6 @@ class SigmaDslSpecification extends SigmaDslTesting ">=", GE.apply)(_ >= _) } - property("Int methods equivalence (new features)") { - lazy val toBytes = newFeature((x: Int) => x.toBytes, "{ (x: Int) => x.toBytes }") - lazy val toAbs = newFeature((x: Int) => x.toAbs, "{ (x: Int) => x.toAbs }") - lazy val compareTo = newFeature((x: (Int, Int)) => x._1.compareTo(x._2), - "{ (x: (Int, Int)) => x._1.compareTo(x._2) }") - - lazy val bitOr = newFeature( - { (x: (Int, Int)) => x._1 | x._2 }, - "{ (x: (Int, Int)) => x._1 | x._2 }") - - lazy val bitAnd = newFeature( - { (x: (Int, Int)) => x._1 & x._2 }, - "{ (x: (Int, Int)) => x._1 & x._2 }") - - forAll { x: Int => - Seq(toBytes, toAbs).foreach(_.checkEquality(x)) - } - forAll { x: (Int, Int) => - Seq(compareTo, bitOr, bitAnd).foreach(_.checkEquality(x)) - } - } - property("Long downcast and upcast identity") { forAll { x: Long => SLong.upcast(x) shouldBe x // boundary test case @@ -1984,28 +1796,6 @@ class SigmaDslSpecification extends SigmaDslTesting ">=", GE.apply)(_ >= _) } - property("Long methods equivalence (new features)") { - lazy val toBytes = newFeature((x: Long) => x.toBytes, "{ (x: Long) => x.toBytes }") - lazy val toAbs = newFeature((x: Long) => x.toAbs, "{ (x: Long) => x.toAbs }") - lazy val compareTo = newFeature((x: (Long, Long)) => x._1.compareTo(x._2), - "{ (x: (Long, Long)) => x._1.compareTo(x._2) }") - - lazy val bitOr = newFeature( - { (x: (Long, Long)) => x._1 | x._2 }, - "{ (x: (Long, Long)) => x._1 | x._2 }") - - lazy val bitAnd = newFeature( - { (x: (Long, Long)) => x._1 & x._2 }, - "{ (x: (Long, Long)) => x._1 & x._2 }") - - forAll { x: Long => - Seq(toBytes, toAbs).foreach(_.checkEquality(x)) - } - forAll { x: (Long, Long) => - Seq(compareTo, bitOr, bitAnd).foreach(_.checkEquality(x)) - } - } - property("BigInt methods equivalence") { verifyCases( { @@ -2264,59 +2054,6 @@ class SigmaDslSpecification extends SigmaDslTesting ">=", GE.apply)(o.gteq(_, _)) } - property("BigInt methods equivalence (new features)") { - // TODO v6.0: the behavior of `upcast` for BigInt is different from all other Numeric types (see https://github.com/ScorexFoundation/sigmastate-interpreter/issues/877) - // The `Upcast(bigInt, SBigInt)` node is never produced by ErgoScript compiler, but is still valid ErgoTree. - // It makes sense to fix this inconsistency as part of upcoming forks - assertExceptionThrown( - SBigInt.upcast(CBigInt(new BigInteger("0", 16)).asInstanceOf[AnyVal]), - _.getMessage.contains("Cannot upcast value") - ) - - // TODO v6.0: the behavior of `downcast` for BigInt is different from all other Numeric types (see https://github.com/ScorexFoundation/sigmastate-interpreter/issues/877) - // The `Downcast(bigInt, SBigInt)` node is never produced by ErgoScript compiler, but is still valid ErgoTree. - // It makes sense to fix this inconsistency as part of HF - assertExceptionThrown( - SBigInt.downcast(CBigInt(new BigInteger("0", 16)).asInstanceOf[AnyVal]), - _.getMessage.contains("Cannot downcast value") - ) - - val toByte = newFeature((x: BigInt) => x.toByte, - "{ (x: BigInt) => x.toByte }", - FuncValue(Vector((1, SBigInt)), Downcast(ValUse(1, SBigInt), SByte))) - - val toShort = newFeature((x: BigInt) => x.toShort, - "{ (x: BigInt) => x.toShort }", - FuncValue(Vector((1, SBigInt)), Downcast(ValUse(1, SBigInt), SShort))) - - val toInt = newFeature((x: BigInt) => x.toInt, - "{ (x: BigInt) => x.toInt }", - FuncValue(Vector((1, SBigInt)), Downcast(ValUse(1, SBigInt), SInt))) - - val toLong = newFeature((x: BigInt) => x.toLong, - "{ (x: BigInt) => x.toLong }", - FuncValue(Vector((1, SBigInt)), Downcast(ValUse(1, SBigInt), SLong))) - - lazy val toBytes = newFeature((x: BigInt) => x.toBytes, "{ (x: BigInt) => x.toBytes }") - lazy val toAbs = newFeature((x: BigInt) => x.toAbs, "{ (x: BigInt) => x.toAbs }") - - lazy val compareTo = newFeature((x: (BigInt, BigInt)) => x._1.compareTo(x._2), - "{ (x: (BigInt, BigInt)) => x._1.compareTo(x._2) }") - - lazy val bitOr = newFeature({ (x: (BigInt, BigInt)) => x._1 | x._2 }, - "{ (x: (BigInt, BigInt)) => x._1 | x._2 }") - - lazy val bitAnd = newFeature({ (x: (BigInt, BigInt)) => x._1 & x._2 }, - "{ (x: (BigInt, BigInt)) => x._1 & x._2 }") - - forAll { x: BigInt => - Seq(toByte, toShort, toInt, toLong, toBytes, toAbs).foreach(_.checkEquality(x)) - } - forAll { x: (BigInt, BigInt) => - Seq(compareTo, bitOr, bitAnd).foreach(_.checkEquality(x)) - } - } - /** Executed a series of test cases of NEQ operation verify using two _different_ * data instances `x` and `y`. * @param cost the expected cost of `verify` (the same for all cases) @@ -4051,16 +3788,6 @@ class SigmaDslSpecification extends SigmaDslTesting ))) } - property("Box properties equivalence (new features)") { - // TODO v6.0: related to https://github.com/ScorexFoundation/sigmastate-interpreter/issues/416 - val getReg = newFeature((x: Box) => x.getReg[Int](1).get, - "{ (x: Box) => x.getReg[Int](1).get }") - - forAll { box: Box => - Seq(getReg).foreach(_.checkEquality(box)) - } - } - property("Conditional access to registers") { def boxWithRegisters(regs: AdditionalRegisters): Box = { SigmaDsl.Box(testBox(20, TrueTree, 0, Seq(), regs)) @@ -7638,36 +7365,6 @@ class SigmaDslSpecification extends SigmaDslTesting preGeneratedSamples = Some(samples)) } - // TODO v6.0 (3h): https://github.com/ScorexFoundation/sigmastate-interpreter/issues/479 - property("Coll find method equivalence") { - val find = newFeature((x: Coll[Int]) => x.find({ (v: Int) => v > 0 }), - "{ (x: Coll[Int]) => x.find({ (v: Int) => v > 0} ) }") - forAll { x: Coll[Int] => - find.checkEquality(x) - } - } - - // TODO v6.0 (3h): https://github.com/ScorexFoundation/sigmastate-interpreter/issues/418 - property("Coll bitwise methods equivalence") { - val shiftRight = newFeature( - { (x: Coll[Boolean]) => - if (x.size > 2) x.slice(0, x.size - 2) else Colls.emptyColl[Boolean] - }, - "{ (x: Coll[Boolean]) => x >> 2 }") - forAll { x: Array[Boolean] => - shiftRight.checkEquality(Colls.fromArray(x)) - } - } - - // TODO v6.0 (3h): https://github.com/ScorexFoundation/sigmastate-interpreter/issues/479 - property("Coll diff methods equivalence") { - val diff = newFeature((x: (Coll[Int], Coll[Int])) => x._1.diff(x._2), - "{ (x: (Coll[Int], Coll[Int])) => x._1.diff(x._2) }") - forAll { (x: Coll[Int], y: Coll[Int]) => - diff.checkEquality((x, y)) - } - } - property("Coll fold method equivalence") { val n = ExactNumeric.IntIsExactNumeric val costDetails1 = TracedCost( @@ -9079,17 +8776,6 @@ class SigmaDslSpecification extends SigmaDslTesting ) )) } - // TODO v6.0: implement Option.fold (see https://github.com/ScorexFoundation/sigmastate-interpreter/issues/479) - property("Option new methods") { - val n = ExactNumeric.LongIsExactNumeric - val fold = newFeature({ (x: Option[Long]) => x.fold(5.toLong)( (v: Long) => n.plus(v, 1) ) }, - "{ (x: Option[Long]) => x.fold(5, { (v: Long) => v + 1 }) }") - - forAll { x: Option[Long] => - Seq(fold).map(_.checkEquality(x)) - } - } - property("Option fold workaround method") { val costDetails1 = TracedCost( traceBase ++ Array( @@ -9525,24 +9211,6 @@ class SigmaDslSpecification extends SigmaDslTesting preGeneratedSamples = Some(Seq())) } - // TODO v6.0 (3h): implement allZK func https://github.com/ScorexFoundation/sigmastate-interpreter/issues/543 - property("allZK equivalence") { - lazy val allZK = newFeature((x: Coll[SigmaProp]) => SigmaDsl.allZK(x), - "{ (x: Coll[SigmaProp]) => allZK(x) }") - forAll { x: Coll[SigmaProp] => - allZK.checkEquality(x) - } - } - - // TODO v6.0 (3h): implement anyZK func https://github.com/ScorexFoundation/sigmastate-interpreter/issues/543 - property("anyZK equivalence") { - lazy val anyZK = newFeature((x: Coll[SigmaProp]) => SigmaDsl.anyZK(x), - "{ (x: Coll[SigmaProp]) => anyZK(x) }") - forAll { x: Coll[SigmaProp] => - anyZK.checkEquality(x) - } - } - property("allOf equivalence") { def costDetails(i: Int) = TracedCost(traceBase :+ ast.SeqCostItem(CompanionDesc(AND), PerItemCost(JitCost(10), JitCost(5), 32), i)) verifyCases( diff --git a/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala b/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala new file mode 100644 index 0000000000..e82bcd886b --- /dev/null +++ b/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala @@ -0,0 +1,348 @@ +package sigma + +import sigma.ast.{Apply, Downcast, FixedCost, FixedCostItem, FuncValue, GetVar, Global, JitCost, MethodCall, NamedDesc, OptionGet, SBigInt, SByte, SGlobalMethods, SInt, SLong, SShort, STypeVar, ValUse} +import sigma.data.{CBigInt, ExactNumeric, RType} +import sigma.eval.{SigmaDsl, TracedCost} +import sigma.util.Extensions.{BooleanOps, ByteOps, IntOps, LongOps} +import sigmastate.exceptions.MethodNotFound + +import java.math.BigInteger +import scala.util.Success + +/** This suite tests all operations for v6.0 version of the language. + * The base classes establish the infrastructure for the tests. + * + * @see SigmaDslSpecificationBase + */ +class LanguageSpecificationV6 extends LanguageSpecificationBase { suite => + override def languageVersion: Byte = VersionContext.V6SoftForkVersion + + implicit override def evalSettings = super.evalSettings.copy(printTestVectors = true) + + + val baseTrace = Array( + FixedCostItem(Apply), + FixedCostItem(FuncValue), + FixedCostItem(GetVar), + FixedCostItem(OptionGet), + FixedCostItem(FuncValue.AddToEnvironmentDesc, FixedCost(JitCost(5))) + ) + + property("Boolean.toByte") { + val toByte = newFeature((x: Boolean) => x.toByte, "{ (x: Boolean) => x.toByte }", + sinceVersion = VersionContext.V6SoftForkVersion + ) + + val cases = Seq( + (true, Success(1.toByte)), + (false, Success(0.toByte)) + ) + + if (toByte.isSupportedIn(VersionContext.current)) { + // TODO v6.0: implement as part of https://github.com/ScorexFoundation/sigmastate-interpreter/pull/932 + assertExceptionThrown( + testCases(cases, toByte), + rootCauseLike[MethodNotFound]("Cannot find method") + ) + } + else + testCases(cases, toByte) + } + + property("Byte methods equivalence (new features)") { + // TODO v6.0: implement as part of https://github.com/ScorexFoundation/sigmastate-interpreter/issues/474 + if (activatedVersionInTests < VersionContext.V6SoftForkVersion) { + // NOTE, for such versions the new features are not supported + // which is checked below + + lazy val toAbs = newFeature((x: Byte) => x.toAbs, "{ (x: Byte) => x.toAbs }", + sinceVersion = VersionContext.V6SoftForkVersion) + + lazy val compareTo = newFeature( + (x: (Byte, Byte)) => x._1.compareTo(x._2), + "{ (x: (Byte, Byte)) => x._1.compareTo(x._2) }", + sinceVersion = VersionContext.V6SoftForkVersion) + + lazy val bitOr = newFeature( + { (x: (Byte, Byte)) => (x._1 | x._2).toByteExact }, + "{ (x: (Byte, Byte)) => (x._1 | x._2) }", + sinceVersion = VersionContext.V6SoftForkVersion) + + lazy val bitAnd = newFeature( + { (x: (Byte, Byte)) => (x._1 & x._2).toByteExact }, + "{ (x: (Byte, Byte)) => (x._1 & x._2) }", + sinceVersion = VersionContext.V6SoftForkVersion) + + forAll { x: Byte => + Seq(toAbs).foreach(f => f.checkEquality(x)) + } + + forAll { x: (Byte, Byte) => + Seq(compareTo, bitOr, bitAnd).foreach(_.checkEquality(x)) + } + } + } + + // TODO v6.0: enable as part of https://github.com/ScorexFoundation/sigmastate-interpreter/issues/474 + property("Short methods equivalence (new features)") { + if (activatedVersionInTests < VersionContext.V6SoftForkVersion) { + // NOTE, for such versions the new features are not supported + // which is checked below + + lazy val toAbs = newFeature((x: Short) => x.toAbs, "{ (x: Short) => x.toAbs }", + sinceVersion = VersionContext.V6SoftForkVersion) + + lazy val compareTo = newFeature((x: (Short, Short)) => x._1.compareTo(x._2), + "{ (x: (Short, Short)) => x._1.compareTo(x._2) }", + sinceVersion = VersionContext.V6SoftForkVersion) + + lazy val bitOr = newFeature( + { (x: (Short, Short)) => (x._1 | x._2).toShortExact }, + "{ (x: (Short, Short)) => x._1 | x._2 }", + sinceVersion = VersionContext.V6SoftForkVersion) + + lazy val bitAnd = newFeature( + { (x: (Short, Short)) => (x._1 & x._2).toShortExact }, + "{ (x: (Short, Short)) => x._1 & x._2 }", + sinceVersion = VersionContext.V6SoftForkVersion) + + forAll { x: Short => + Seq(toAbs).foreach(_.checkEquality(x)) + } + forAll { x: (Short, Short) => + Seq(compareTo, bitOr, bitAnd).foreach(_.checkEquality(x)) + } + } + } + + property("Int methods equivalence (new features)") { + if (activatedVersionInTests < VersionContext.V6SoftForkVersion) { + // NOTE, for such versions the new features are not supported + // which is checked below + lazy val toAbs = newFeature((x: Int) => x.toAbs, "{ (x: Int) => x.toAbs }", + sinceVersion = VersionContext.V6SoftForkVersion) + lazy val compareTo = newFeature((x: (Int, Int)) => x._1.compareTo(x._2), + "{ (x: (Int, Int)) => x._1.compareTo(x._2) }", + sinceVersion = VersionContext.V6SoftForkVersion) + lazy val bitOr = newFeature( + { (x: (Int, Int)) => x._1 | x._2 }, + "{ (x: (Int, Int)) => x._1 | x._2 }", + sinceVersion = VersionContext.V6SoftForkVersion) + lazy val bitAnd = newFeature( + { (x: (Int, Int)) => x._1 & x._2 }, + "{ (x: (Int, Int)) => x._1 & x._2 }", + sinceVersion = VersionContext.V6SoftForkVersion) + forAll { x: Int => + Seq(toAbs).foreach(_.checkEquality(x)) + } + forAll { x: (Int, Int) => + Seq(compareTo, bitOr, bitAnd).foreach(_.checkEquality(x)) + } + } + } + + property("Long methods equivalence (new features)") { + if (activatedVersionInTests < VersionContext.V6SoftForkVersion) { + // NOTE, for such versions the new features are not supported + // which is checked below + lazy val toAbs = newFeature((x: Long) => x.toAbs, "{ (x: Long) => x.toAbs }", + sinceVersion = VersionContext.V6SoftForkVersion) + lazy val compareTo = newFeature((x: (Long, Long)) => x._1.compareTo(x._2), + "{ (x: (Long, Long)) => x._1.compareTo(x._2) }", + sinceVersion = VersionContext.V6SoftForkVersion) + + lazy val bitOr = newFeature( + { (x: (Long, Long)) => x._1 | x._2 }, + "{ (x: (Long, Long)) => x._1 | x._2 }", + sinceVersion = VersionContext.V6SoftForkVersion) + + lazy val bitAnd = newFeature( + { (x: (Long, Long)) => x._1 & x._2 }, + "{ (x: (Long, Long)) => x._1 & x._2 }", + sinceVersion = VersionContext.V6SoftForkVersion) + + forAll { x: Long => + Seq(toAbs).foreach(_.checkEquality(x)) + } + forAll { x: (Long, Long) => + Seq(compareTo, bitOr, bitAnd).foreach(_.checkEquality(x)) + } + } + + } + + property("BigInt methods equivalence (new features)") { + // TODO v6.0: the behavior of `upcast` for BigInt is different from all other Numeric types (see https://github.com/ScorexFoundation/sigmastate-interpreter/issues/877) + // The `Upcast(bigInt, SBigInt)` node is never produced by ErgoScript compiler, but is still valid ErgoTree. + // It makes sense to fix this inconsistency as part of upcoming forks + assertExceptionThrown( + SBigInt.upcast(CBigInt(new BigInteger("0", 16)).asInstanceOf[AnyVal]), + _.getMessage.contains("Cannot upcast value") + ) + + // TODO v6.0: the behavior of `downcast` for BigInt is different from all other Numeric types (see https://github.com/ScorexFoundation/sigmastate-interpreter/issues/877) + // The `Downcast(bigInt, SBigInt)` node is never produced by ErgoScript compiler, but is still valid ErgoTree. + // It makes sense to fix this inconsistency as part of HF + assertExceptionThrown( + SBigInt.downcast(CBigInt(new BigInteger("0", 16)).asInstanceOf[AnyVal]), + _.getMessage.contains("Cannot downcast value") + ) + + if (activatedVersionInTests < VersionContext.V6SoftForkVersion) { + // NOTE, for such versions the new features are not supported + // which is checked below + val toByte = newFeature((x: BigInt) => x.toByte, + "{ (x: BigInt) => x.toByte }", + FuncValue(Vector((1, SBigInt)), Downcast(ValUse(1, SBigInt), SByte)), + sinceVersion = VersionContext.V6SoftForkVersion) + val toShort = newFeature((x: BigInt) => x.toShort, + "{ (x: BigInt) => x.toShort }", + FuncValue(Vector((1, SBigInt)), Downcast(ValUse(1, SBigInt), SShort)), + sinceVersion = VersionContext.V6SoftForkVersion) + val toInt = newFeature((x: BigInt) => x.toInt, + "{ (x: BigInt) => x.toInt }", + FuncValue(Vector((1, SBigInt)), Downcast(ValUse(1, SBigInt), SInt)), + sinceVersion = VersionContext.V6SoftForkVersion) + val toLong = newFeature((x: BigInt) => x.toLong, + "{ (x: BigInt) => x.toLong }", + FuncValue(Vector((1, SBigInt)), Downcast(ValUse(1, SBigInt), SLong)), + sinceVersion = VersionContext.V6SoftForkVersion) + lazy val toAbs = newFeature((x: BigInt) => x.toAbs, "{ (x: BigInt) => x.toAbs }", + sinceVersion = VersionContext.V6SoftForkVersion) + lazy val compareTo = newFeature((x: (BigInt, BigInt)) => x._1.compareTo(x._2), + "{ (x: (BigInt, BigInt)) => x._1.compareTo(x._2) }", + sinceVersion = VersionContext.V6SoftForkVersion) + lazy val bitOr = newFeature({ (x: (BigInt, BigInt)) => x._1 | x._2 }, + "{ (x: (BigInt, BigInt)) => x._1 | x._2 }", + sinceVersion = VersionContext.V6SoftForkVersion) + lazy val bitAnd = newFeature({ (x: (BigInt, BigInt)) => x._1 & x._2 }, + "{ (x: (BigInt, BigInt)) => x._1 & x._2 }", + sinceVersion = VersionContext.V6SoftForkVersion) + + forAll { x: BigInt => + Seq(toByte, toShort, toInt, toLong, toAbs).foreach(_.checkEquality(x)) + } + forAll { x: (BigInt, BigInt) => + Seq(compareTo, bitOr, bitAnd).foreach(_.checkEquality(x)) + } + } + } + + property("Box properties equivalence (new features)") { + // TODO v6.0: related to https://github.com/ScorexFoundation/sigmastate-interpreter/issues/416 + val getReg = newFeature((x: Box) => x.getReg[Int](1).get, + "{ (x: Box) => x.getReg[Int](1).get }", + sinceVersion = VersionContext.V6SoftForkVersion) + + if (activatedVersionInTests < VersionContext.V6SoftForkVersion) { + // NOTE, for such versions getReg is not supported + // which is checked below + + forAll { box: Box => + Seq(getReg).foreach(_.checkEquality(box)) + } + } + } + + // TODO v6.0 (3h): https://github.com/ScorexFoundation/sigmastate-interpreter/issues/479 + property("Coll find method equivalence") { + val find = newFeature((x: Coll[Int]) => x.find({ (v: Int) => v > 0 }), + "{ (x: Coll[Int]) => x.find({ (v: Int) => v > 0} ) }", + sinceVersion = VersionContext.V6SoftForkVersion) + + if (activatedVersionInTests < VersionContext.V6SoftForkVersion) { + // NOTE, for such versions getReg is not supported + // which is checked below + + forAll { x: Coll[Int] => + find.checkEquality(x) + } + } + } + + // TODO v6.0 (3h): https://github.com/ScorexFoundation/sigmastate-interpreter/issues/418 + property("Coll bitwise methods equivalence") { + val shiftRight = newFeature( + { (x: Coll[Boolean]) => + if (x.size > 2) x.slice(0, x.size - 2) else Colls.emptyColl[Boolean] + }, + "{ (x: Coll[Boolean]) => x >> 2 }", + sinceVersion = VersionContext.V6SoftForkVersion) + + if (activatedVersionInTests < VersionContext.V6SoftForkVersion) { + // NOTE, for such versions getReg is not supported + // which is checked below + + forAll { x: Array[Boolean] => + shiftRight.checkEquality(Colls.fromArray(x)) + } + } + } + + // TODO v6.0 (3h): https://github.com/ScorexFoundation/sigmastate-interpreter/issues/479 + property("Coll diff methods equivalence") { + val diff = newFeature((x: (Coll[Int], Coll[Int])) => x._1.diff(x._2), + "{ (x: (Coll[Int], Coll[Int])) => x._1.diff(x._2) }", + sinceVersion = VersionContext.V6SoftForkVersion) + + if (activatedVersionInTests < VersionContext.V6SoftForkVersion) { + // NOTE, for such versions getReg is not supported + // which is checked below + + forAll { (x: Coll[Int], y: Coll[Int]) => + diff.checkEquality((x, y)) + } + } + } + + // TODO v6.0: implement Option.fold (see https://github.com/ScorexFoundation/sigmastate-interpreter/issues/479) + property("Option new methods") { + val n = ExactNumeric.LongIsExactNumeric + val fold = newFeature({ (x: Option[Long]) => x.fold(5.toLong)( (v: Long) => n.plus(v, 1) ) }, + "{ (x: Option[Long]) => x.fold(5, { (v: Long) => v + 1 }) }", + sinceVersion = VersionContext.V6SoftForkVersion) + + if (activatedVersionInTests < VersionContext.V6SoftForkVersion) { + // NOTE, for such versions getReg is not supported + // which is checked below + + forAll { x: Option[Long] => + Seq(fold).map(_.checkEquality(x)) + } + } + } + + // TODO v6.0 (3h): implement allZK func https://github.com/ScorexFoundation/sigmastate-interpreter/issues/543 + property("allZK equivalence") { + lazy val allZK = newFeature((x: Coll[SigmaProp]) => SigmaDsl.allZK(x), + "{ (x: Coll[SigmaProp]) => allZK(x) }", + sinceVersion = VersionContext.V6SoftForkVersion) + + if (activatedVersionInTests < VersionContext.V6SoftForkVersion) { + // NOTE, for such versions getReg is not supported + // which is checked below + + forAll { x: Coll[SigmaProp] => + allZK.checkEquality(x) + } + } + } + + // TODO v6.0 (3h): implement anyZK func https://github.com/ScorexFoundation/sigmastate-interpreter/issues/543 + property("anyZK equivalence") { + lazy val anyZK = newFeature((x: Coll[SigmaProp]) => SigmaDsl.anyZK(x), + "{ (x: Coll[SigmaProp]) => anyZK(x) }", + sinceVersion = VersionContext.V6SoftForkVersion) + + if (activatedVersionInTests < VersionContext.V6SoftForkVersion) { + // NOTE, for such versions getReg is not supported + // which is checked below + + forAll { x: Coll[SigmaProp] => + anyZK.checkEquality(x) + } + } + } + + +} diff --git a/sc/shared/src/test/scala/sigma/SigmaDslTesting.scala b/sc/shared/src/test/scala/sigma/SigmaDslTesting.scala index 31e873699b..37fb0e6503 100644 --- a/sc/shared/src/test/scala/sigma/SigmaDslTesting.scala +++ b/sc/shared/src/test/scala/sigma/SigmaDslTesting.scala @@ -123,6 +123,9 @@ class SigmaDslTesting extends AnyPropSpec /** Type descriptor for type B. */ def tB: RType[B] + /** Checks if this feature is supported in the given version context. */ + def isSupportedIn(vc: VersionContext): Boolean + /** Script containing this feature. */ def script: String @@ -176,14 +179,42 @@ class SigmaDslTesting extends AnyPropSpec true } + /** Checks the result of feature execution against expected result. + * If settings.failOnTestVectors == true, then print out actual cost results + * + * @param res the result of feature execution + * @param expected the expected result + */ + protected def checkResultAgainstExpected(res: Try[(B, CostDetails)], expected: Expected[B]): Unit = { + val newRes = expected.newResults(ergoTreeVersionInTests) + val expectedTrace = newRes._2.fold(Seq.empty[CostItem])(_.trace) + if (expectedTrace.isEmpty) { + // new cost expectation is missing, print out actual cost results + if (evalSettings.printTestVectors) { + res.foreach { case (_, newDetails) => + printCostDetails(script, newDetails) + } + } + } + else { + // new cost expectation is specified, compare it with the actual result + res.foreach { case (_, newDetails) => + if (newDetails.trace != expectedTrace) { + printCostDetails(script, newDetails) + newDetails.trace shouldBe expectedTrace + } + } + } + } + /** v3 and v4 implementation*/ - private var _oldF: CompiledFunc[A, B] = _ + private var _oldF: Try[CompiledFunc[A, B]] = _ def oldF: CompiledFunc[A, B] = { if (_oldF == null) { - _oldF = oldImpl() - checkExpectedExprIn(_oldF) + _oldF = Try(oldImpl()) + _oldF.foreach(cf => checkExpectedExprIn(cf)) } - _oldF + _oldF.getOrThrow } /** v5 implementation*/ @@ -252,13 +283,21 @@ class SigmaDslTesting extends AnyPropSpec fail( s"""Should succeed with the same value or fail with the same exception, but was: - |First result: $b1 - |Second result: $b2 + |First result: ${errorWithStack(b1)} + |Second result: ${errorWithStack(b2)} |Root cause: $cause |""".stripMargin) } } + private def errorWithStack[A](e: Try[A]): String = e match { + case Failure(t) => + val sw = new java.io.StringWriter + t.printStackTrace(new java.io.PrintWriter(sw)) + sw.toString + case _ => e.toString + } + /** Creates a new ErgoLikeContext using given [[CContext]] as template. * Copies most of the data from ctx and the missing data is taken from the args. * This is a helper method to be used in tests only. @@ -501,6 +540,8 @@ class SigmaDslTesting extends AnyPropSpec implicit val cs = compilerSettingsInTests + override def isSupportedIn(vc: VersionContext): Boolean = true + /** in v5.x the old and the new interpreters are the same */ override val oldImpl = () => funcJit[A, B](script) override val newImpl = () => funcJit[A, B](script) @@ -611,28 +652,10 @@ class SigmaDslTesting extends AnyPropSpec checkResult(funcRes.map(_._1), expected.value, failOnTestVectors, "ExistingFeature#verifyCase: ") - val newRes = expected.newResults(ergoTreeVersionInTests) - val expectedTrace = newRes._2.fold(Seq.empty[CostItem])(_.trace) - if (expectedTrace.isEmpty) { - // new cost expectation is missing, print out actual cost results - if (evalSettings.printTestVectors) { - funcRes.foreach { case (_, newDetails) => - printCostDetails(script, newDetails) - } - } - } - else { - // new cost expectation is specified, compare it with the actual result - funcRes.foreach { case (_, newDetails) => - if (newDetails.trace != expectedTrace) { - printCostDetails(script, newDetails) - newDetails.trace shouldBe expectedTrace - } - } - } - + checkResultAgainstExpected(funcRes, expected) checkVerify(input, expected) } + } /** Descriptor of a language feature which is changed in v5.0. @@ -671,6 +694,8 @@ class SigmaDslTesting extends AnyPropSpec implicit val cs = compilerSettingsInTests + override def isSupportedIn(vc: VersionContext): Boolean = true + /** Apply given function to the context variable 1 */ private def getApplyExpr(funcValue: SValue) = { val sType = Evaluation.rtypeToSType(RType[A]) @@ -833,8 +858,17 @@ class SigmaDslTesting extends AnyPropSpec * This in not yet implemented and will be finished in v6.0. * In v5.0 is only checks that some features are NOT implemented, i.e. work for * negative tests. + * + * @param sinceVersion language version (protocol) when the feature is introduced, see + * [[VersionContext]] + * @param script the script to be tested against semantic function + * @param scalaFuncNew semantic function which defines expected behavior of the given script + * @param expectedExpr expected ErgoTree expression which corresponds to the given script + * @param printExpectedExpr if true, print the test vector for expectedExpr when it is None + * @param logScript if true, log scripts to console */ case class NewFeature[A, B]( + sinceVersion: Byte, script: String, override val scalaFuncNew: A => B, expectedExpr: Option[SValue], @@ -842,25 +876,30 @@ class SigmaDslTesting extends AnyPropSpec logScript: Boolean = LogScriptDefault )(implicit IR: IRContext, override val evalSettings: EvalSettings, val tA: RType[A], val tB: RType[B]) extends Feature[A, B] { + + override def isSupportedIn(vc: VersionContext): Boolean = + vc.activatedVersion >= sinceVersion + override def scalaFunc: A => B = { x => sys.error(s"Semantic Scala function is not defined for old implementation: $this") } implicit val cs = compilerSettingsInTests - /** in v5.x the old and the new interpreters are the same */ + /** Starting from v5.x the old and the new interpreters are the same */ val oldImpl = () => funcJit[A, B](script) - val newImpl = oldImpl // funcJit[A, B](script) // TODO v6.0: use actual new implementation here (https://github.com/ScorexFoundation/sigmastate-interpreter/issues/910) + val newImpl = oldImpl - /** In v5.x this method just checks the old implementations fails on the new feature. */ + /** Check the new implementation works equal to the semantic function. + * This method also checks the old implementations fails on the new feature. + */ override def checkEquality(input: A, logInputOutput: Boolean = false): Try[(B, CostDetails)] = { - val oldRes = Try(oldF(input)) - oldRes.isFailure shouldBe true - if (!(newImpl eq oldImpl)) { - val newRes = VersionContext.withVersions(activatedVersionInTests, ergoTreeVersionInTests) { - checkEq(scalaFuncNew)(newF)(input) - } + if (this.isSupportedIn(VersionContext.current)) { + checkEq(scalaFuncNew)(newF)(input) + } else { + val oldRes = Try(oldF(input)) + oldRes.isFailure shouldBe true + oldRes } - oldRes } override def checkExpected(input: A, expected: Expected[B]): Unit = { @@ -880,7 +919,10 @@ class SigmaDslTesting extends AnyPropSpec printTestCases: Boolean, failOnTestVectors: Boolean): Unit = { val res = checkEquality(input, printTestCases).map(_._1) - res.isFailure shouldBe true + if (this.isSupportedIn(VersionContext.current)) { + res shouldBe expectedResult + } else + res.isFailure shouldBe true Try(scalaFuncNew(input)) shouldBe expectedResult } @@ -889,8 +931,11 @@ class SigmaDslTesting extends AnyPropSpec printTestCases: Boolean, failOnTestVectors: Boolean): Unit = { val funcRes = checkEquality(input, printTestCases) - funcRes.isFailure shouldBe true - Try(scalaFunc(input)) shouldBe expected.value + if (this.isSupportedIn(VersionContext.current)) { + checkResultAgainstExpected(funcRes, expected) + } else + funcRes.isFailure shouldBe true + Try(scalaFuncNew(input)) shouldBe expected.value } } @@ -958,6 +1003,20 @@ class SigmaDslTesting extends AnyPropSpec } } + /** Used when the old and new value are the same for all versions + * and the expected costs are not specified. + * + * @param value expected result of tested function + * @param expectedDetails expected cost details for all versions + */ + def apply[A](value: Try[A], expectedDetails: CostDetails): Expected[A] = + new Expected(ExpectedResult(value, None)) { + override val newResults = defaultNewResults.map { + case (ExpectedResult(v, _), _) => + (ExpectedResult(v, None), Some(expectedDetails)) + } + } + /** Used when the old and new value and costs are the same for all versions. * * @param value expected result of tested function @@ -1045,6 +1104,7 @@ class SigmaDslTesting extends AnyPropSpec /** Describes a NEW language feature which must NOT be supported in v4 and * must BE supported in v5 of the language. * + * @param sinceVersion language version (protocol) when the feature is introduced, see [[VersionContext]] * @param scalaFunc semantic function which defines expected behavior of the given script * @param script the script to be tested against semantic function * @param expectedExpr expected ErgoTree expression which corresponds to the given script @@ -1052,9 +1112,9 @@ class SigmaDslTesting extends AnyPropSpec * various ways */ def newFeature[A: RType, B: RType] - (scalaFunc: A => B, script: String, expectedExpr: SValue = null) + (scalaFunc: A => B, script: String, expectedExpr: SValue = null, sinceVersion: Byte = VersionContext.JitActivationVersion) (implicit IR: IRContext, es: EvalSettings): Feature[A, B] = { - NewFeature(script, scalaFunc, Option(expectedExpr)) + NewFeature(sinceVersion, script, scalaFunc, Option(expectedExpr)) } val contextGen: Gen[Context] = ergoLikeContextGen.map(c => c.toSigmaContext()) diff --git a/sc/shared/src/test/scala/sigmastate/CompilerCrossVersionProps.scala b/sc/shared/src/test/scala/sigmastate/CompilerCrossVersionProps.scala index 89d15dd4df..4062f13686 100644 --- a/sc/shared/src/test/scala/sigmastate/CompilerCrossVersionProps.scala +++ b/sc/shared/src/test/scala/sigmastate/CompilerCrossVersionProps.scala @@ -12,12 +12,11 @@ trait CompilerCrossVersionProps extends CrossVersionProps with CompilerTestsBase (implicit pos: Position): Unit = { super.property(testName, testTags:_*)(testFun) - val testName2 = s"${testName}_MCLowering" - super.property2(testName2, testTags:_*) { - if (okRunTestsWithoutMCLowering) { - _lowerMethodCalls.withValue(false) { - testFun_Run(testName2, testFun) - } + if (okRunTestsWithoutMCLowering) { + val testName2 = s"${testName}_MCLowering" + _lowerMethodCalls.withValue(false) { + // run testFun for all versions again, but now with this flag + super.property(testName2, testTags:_*)(testFun) } } } diff --git a/sc/shared/src/test/scala/sigmastate/lang/SigmaBinderTest.scala b/sc/shared/src/test/scala/sigmastate/lang/SigmaBinderTest.scala index b4b4ad20cd..aa552e9b69 100644 --- a/sc/shared/src/test/scala/sigmastate/lang/SigmaBinderTest.scala +++ b/sc/shared/src/test/scala/sigmastate/lang/SigmaBinderTest.scala @@ -10,10 +10,12 @@ import sigma.ast.syntax.SValue import sigmastate._ import sigmastate.interpreter.Interpreter.ScriptEnv import SigmaPredef.PredefinedFuncRegistry +import sigma.VersionContext import sigma.ast.syntax._ import sigma.compiler.phases.SigmaBinder import sigma.eval.SigmaDsl import sigma.exceptions.BinderException +import sigmastate.helpers.SigmaPPrint class SigmaBinderTest extends AnyPropSpec with ScalaCheckPropertyChecks with Matchers with LangTests { import StdSigmaBuilder._ @@ -29,6 +31,17 @@ class SigmaBinderTest extends AnyPropSpec with ScalaCheckPropertyChecks with Mat res } + /** Checks that parsing and binding results in the expected value. + * @return the inferred type of the expression + */ + def checkBound(env: ScriptEnv, x: String, expected: SValue) = { + val bound = bind(env, x) + if (expected != bound) { + SigmaPPrint.pprintln(bound, width = 100) + } + bound shouldBe expected + } + private def fail(env: ScriptEnv, x: String, expectedLine: Int, expectedCol: Int): Unit = { val builder = TransformingSigmaBuilder val ast = SigmaParser(x).get.value diff --git a/sc/shared/src/test/scala/sigmastate/lang/SigmaTyperTest.scala b/sc/shared/src/test/scala/sigmastate/lang/SigmaTyperTest.scala index 6b93b098ea..3b2e130100 100644 --- a/sc/shared/src/test/scala/sigmastate/lang/SigmaTyperTest.scala +++ b/sc/shared/src/test/scala/sigmastate/lang/SigmaTyperTest.scala @@ -21,6 +21,7 @@ import sigma.serialization.generators.ObjectGenerators import sigma.ast.Select import sigma.compiler.phases.{SigmaBinder, SigmaTyper} import sigma.exceptions.TyperException +import sigmastate.helpers.SigmaPPrint class SigmaTyperTest extends AnyPropSpec with ScalaCheckPropertyChecks with Matchers with LangTests with ObjectGenerators { @@ -28,6 +29,7 @@ class SigmaTyperTest extends AnyPropSpec private val predefFuncRegistry = new PredefinedFuncRegistry(StdSigmaBuilder) import predefFuncRegistry._ + /** Checks that parsing, binding and typing of `x` results in the given expected value. */ def typecheck(env: ScriptEnv, x: String, expected: SValue = null): SType = { try { val builder = TransformingSigmaBuilder @@ -39,7 +41,12 @@ class SigmaTyperTest extends AnyPropSpec val typer = new SigmaTyper(builder, predefinedFuncRegistry, typeEnv, lowerMethodCalls = true) val typed = typer.typecheck(bound) assertSrcCtxForAllNodes(typed) - if (expected != null) typed shouldBe expected + if (expected != null) { + if (expected != typed) { + SigmaPPrint.pprintln(typed, width = 100) + } + typed shouldBe expected + } typed.tpe } catch { case e: Exception => throw e From 11777ef12464235846ac81094e7f7af9a13ec1c9 Mon Sep 17 00:00:00 2001 From: Alexander Slesarenko Date: Fri, 7 Jun 2024 13:32:27 +0300 Subject: [PATCH 138/314] MethodCall new functionality extraction from i486 --- .../src/main/scala/sigma/ast/SMethod.scala | 58 ++++++++++++++----- .../serialization/MethodCallSerializer.scala | 47 +++++++++++---- .../sigma/compiler/phases/SigmaTyper.scala | 4 +- 3 files changed, 82 insertions(+), 27 deletions(-) diff --git a/data/shared/src/main/scala/sigma/ast/SMethod.scala b/data/shared/src/main/scala/sigma/ast/SMethod.scala index 669625ef1e..6bf8d4f9a0 100644 --- a/data/shared/src/main/scala/sigma/ast/SMethod.scala +++ b/data/shared/src/main/scala/sigma/ast/SMethod.scala @@ -50,17 +50,19 @@ case class MethodIRInfo( /** Represents method descriptor. * - * @param objType type or type constructor descriptor - * @param name method name - * @param stype method signature type, - * where `stype.tDom`` - argument type and - * `stype.tRange` - method result type. - * @param methodId method code, it should be unique among methods of the same objType. - * @param costKind cost descriptor for this method - * @param irInfo meta information connecting SMethod with ErgoTree (see [[MethodIRInfo]]) - * @param docInfo optional human readable method description data - * @param costFunc optional specification of how the cost should be computed for the - * given method call (See ErgoTreeEvaluator.calcCost method). + * @param objType type or type constructor descriptor + * @param name method name + * @param stype method signature type, + * where `stype.tDom`` - argument type and + * `stype.tRange` - method result type. + * @param methodId method code, it should be unique among methods of the same objType. + * @param costKind cost descriptor for this method + * @param explicitTypeArgs list of type parameters which require explicit + * serialization in [[MethodCall]]s (i.e for deserialize[T], getVar[T], getReg[T]) + * @param irInfo meta information connecting SMethod with ErgoTree (see [[MethodIRInfo]]) + * @param docInfo optional human readable method description data + * @param costFunc optional specification of how the cost should be computed for the + * given method call (See ErgoTreeEvaluator.calcCost method). */ case class SMethod( objType: MethodsContainer, @@ -68,13 +70,19 @@ case class SMethod( stype: SFunc, methodId: Byte, costKind: CostKind, + explicitTypeArgs: Seq[STypeVar], irInfo: MethodIRInfo, docInfo: Option[OperationInfo], - costFunc: Option[MethodCostFunc]) { + costFunc: Option[MethodCostFunc], + userDefinedInvoke: Option[SMethod.InvokeHandler] +) { /** Operation descriptor of this method. */ lazy val opDesc = MethodDesc(this) + /** Return true if this method has runtime type parameters */ + def hasExplicitTypeArgs: Boolean = explicitTypeArgs.nonEmpty + /** Finds and keeps the [[RMethod]] instance which corresponds to this method descriptor. * The lazy value is forced only if irInfo.javaMethod == None */ @@ -106,7 +114,12 @@ case class SMethod( /** Invoke this method on the given object with the arguments. * This is used for methods with FixedCost costKind. */ def invokeFixed(obj: Any, args: Array[Any]): Any = { - javaMethod.invoke(obj, args.asInstanceOf[Array[AnyRef]]:_*) + userDefinedInvoke match { + case Some(h) => + h(this, obj, args) + case None => + javaMethod.invoke(obj, args.asInstanceOf[Array[AnyRef]]:_*) + } } // TODO optimize: avoid lookup when this SMethod is created via `specializeFor` @@ -146,6 +159,11 @@ case class SMethod( m } + /** Create a new instance with the given user-defined invoke handler. */ + def withUserDefinedInvoke(handler: SMethod.InvokeHandler): SMethod = { + copy(userDefinedInvoke = Some(handler)) + } + /** Create a new instance with the given stype. */ def withSType(newSType: SFunc): SMethod = copy(stype = newSType) @@ -255,6 +273,12 @@ object SMethod { */ type InvokeDescBuilder = SFunc => Seq[SType] + /** Type of user-defined function which is called to handle method invocation. + * Instances of this type can be attached to [[SMethod]] instances. + * @see SNumericTypeMethods.ToBytesMethod + */ + type InvokeHandler = (SMethod, Any, Array[Any]) => Any + /** Return [[Method]] descriptor for the given `methodName` on the given `cT` type. * @param methodName the name of the method to lookup * @param cT the class where to search the methodName @@ -284,10 +308,12 @@ object SMethod { /** Convenience factory method. */ def apply(objType: MethodsContainer, name: String, stype: SFunc, methodId: Byte, - costKind: CostKind): SMethod = { + costKind: CostKind, + explicitTypeArgs: Seq[STypeVar] = Nil + ): SMethod = { SMethod( - objType, name, stype, methodId, costKind, - MethodIRInfo(None, None, None), None, None) + objType, name, stype, methodId, costKind, explicitTypeArgs, + MethodIRInfo(None, None, None), None, None, None) } diff --git a/data/shared/src/main/scala/sigma/serialization/MethodCallSerializer.scala b/data/shared/src/main/scala/sigma/serialization/MethodCallSerializer.scala index 319a4284e2..abc12c9c9e 100644 --- a/data/shared/src/main/scala/sigma/serialization/MethodCallSerializer.scala +++ b/data/shared/src/main/scala/sigma/serialization/MethodCallSerializer.scala @@ -1,13 +1,15 @@ package sigma.serialization import sigma.ast.syntax._ -import sigma.ast.{MethodCall, SContextMethods, SMethod, SType, STypeSubst, Value, ValueCompanion} +import sigma.ast.{MethodCall, SContextMethods, SMethod, SType, STypeSubst, STypeVar, Value, ValueCompanion} import sigma.util.safeNewArray import SigmaByteWriter._ import debox.cfor import sigma.ast.SContextMethods.BlockchainContextMethodNames import sigma.serialization.CoreByteWriter.{ArgInfo, DataInfo} +import scala.collection.compat.immutable.ArraySeq + case class MethodCallSerializer(cons: (Value[SType], SMethod, IndexedSeq[Value[SType]], STypeSubst) => Value[SType]) extends ValueSerializer[MethodCall] { override def opDesc: ValueCompanion = MethodCall @@ -23,6 +25,10 @@ case class MethodCallSerializer(cons: (Value[SType], SMethod, IndexedSeq[Value[S w.putValue(mc.obj, objInfo) assert(mc.args.nonEmpty) w.putValues(mc.args, argsInfo, argsItemInfo) + mc.method.explicitTypeArgs.foreach { a => + val tpe = mc.typeSubst(a) // existence is checked in MethodCall constructor + w.putType(tpe) + } } /** The SMethod instances in STypeCompanions may have type STypeIdent in methods types, @@ -43,9 +49,36 @@ case class MethodCallSerializer(cons: (Value[SType], SMethod, IndexedSeq[Value[S val obj = r.getValue() val args = r.getValues() val method = SMethod.fromIds(typeId, methodId) - val nArgs = args.length - val types: Seq[SType] = + val explicitTypes = if (method.hasExplicitTypeArgs) { + val nTypes = method.explicitTypeArgs.length + val res = safeNewArray[SType](nTypes) + cfor(0)(_ < nTypes, _ + 1) { i => + res(i) = r.getType() + } + ArraySeq.unsafeWrapArray(res) + } else SType.EmptySeq + + val explicitTypeSubst = method.explicitTypeArgs.zip(explicitTypes).toMap + val specMethod = getSpecializedMethodFor(method, explicitTypeSubst, obj, args) + + var isUsingBlockchainContext = specMethod.objType == SContextMethods && + BlockchainContextMethodNames.contains(method.name) + r.wasUsingBlockchainContext ||= isUsingBlockchainContext + + cons(obj, specMethod, args, explicitTypeSubst) + } + + def getSpecializedMethodFor( + methodTemplate: SMethod, + explicitTypeSubst: STypeSubst, + obj: SValue, + args: Seq[SValue] + ): SMethod = { + // TODO optimize: avoid repeated transformation of method type + val method = methodTemplate.withConcreteTypes(explicitTypeSubst) + val nArgs = args.length + val argTypes: Seq[SType] = if (nArgs == 0) SType.EmptySeq else { val types = safeNewArray[SType](nArgs) @@ -55,12 +88,6 @@ case class MethodCallSerializer(cons: (Value[SType], SMethod, IndexedSeq[Value[S types } - val specMethod = method.specializeFor(obj.tpe, types) - - var isUsingBlockchainContext = specMethod.objType == SContextMethods && - BlockchainContextMethodNames.contains(method.name) - r.wasUsingBlockchainContext ||= isUsingBlockchainContext - - cons(obj, specMethod, args, Map.empty) + method.specializeFor(obj.tpe, argTypes) } } diff --git a/sc/shared/src/main/scala/sigma/compiler/phases/SigmaTyper.scala b/sc/shared/src/main/scala/sigma/compiler/phases/SigmaTyper.scala index 679d98a18f..ac30a6cd0a 100644 --- a/sc/shared/src/main/scala/sigma/compiler/phases/SigmaTyper.scala +++ b/sc/shared/src/main/scala/sigma/compiler/phases/SigmaTyper.scala @@ -139,7 +139,8 @@ class SigmaTyper(val builder: SigmaBuilder, obj.tpe match { case p: SProduct => MethodsContainer.getMethod(p, n) match { - case Some(method @ SMethod(_, _, genFunTpe @ SFunc(_, _, _), _, _, _, _, _)) => + case Some(method: SMethod) => + val genFunTpe = method.stype val subst = Map(genFunTpe.tpeParams.head.ident -> rangeTpe) val concrFunTpe = applySubst(genFunTpe, subst) val expectedArgs = concrFunTpe.asFunc.tDom.tail @@ -511,6 +512,7 @@ class SigmaTyper(val builder: SigmaBuilder, case v: SigmaBoolean => v case v: Upcast[_, _] => v case v @ Select(_, _, Some(_)) => v + case v @ MethodCall(_, _, _, _) => v case v => error(s"Don't know how to assignType($v)", v.sourceContext) }).ensuring(v => v.tpe != NoType, From 982f32f4920f176c6f6d3310e1dfc843791d1503 Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Sun, 9 Jun 2024 15:48:00 +0300 Subject: [PATCH 139/314] schnorr sig example passed --- .../src/main/scala/sigma/ast/SType.scala | 4 ++-- .../src/main/scala/sigma/ast/methods.scala | 5 +++-- .../src/main/scala/sigmastate/lang/Types.scala | 1 + .../sigma/compiler/phases/SigmaBinder.scala | 4 ---- .../sigma/compiler/phases/SigmaTyper.scala | 18 ++++++++++++------ .../utxo/BasicOpsSpecification.scala | 2 +- 6 files changed, 19 insertions(+), 15 deletions(-) diff --git a/core/shared/src/main/scala/sigma/ast/SType.scala b/core/shared/src/main/scala/sigma/ast/SType.scala index 4be9087ca7..411ab1e8c7 100644 --- a/core/shared/src/main/scala/sigma/ast/SType.scala +++ b/core/shared/src/main/scala/sigma/ast/SType.scala @@ -105,7 +105,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. */ val allPredefTypes: Seq[SType] = Array[SType]( - SBoolean, SByte, SShort, SInt, SLong, SBigInt, SContext, + SBoolean, SByte, SShort, SInt, SLong, SBigInt, SUnsignedBigInt, SContext, SGlobal, SHeader, SPreHeader, SAvlTree, SGroupElement, SSigmaProp, SString, SBox, SUnit, SAny) @@ -220,7 +220,7 @@ trait STypeCompanion { /** Special type to represent untyped values. * Interpreter raises an error when encounter a Value with this type. - * All Value nodes with this type should be elimitanted during typing. + * All Value nodes with this type should be eliminated during typing. * If no specific type can be assigned statically during typing, * then either error should be raised or type SAny should be assigned * which is interpreted as dynamic typing. */ diff --git a/data/shared/src/main/scala/sigma/ast/methods.scala b/data/shared/src/main/scala/sigma/ast/methods.scala index 8499ecd46e..179e21485c 100644 --- a/data/shared/src/main/scala/sigma/ast/methods.scala +++ b/data/shared/src/main/scala/sigma/ast/methods.scala @@ -366,6 +366,7 @@ case object SGroupElementMethods extends MonoTypeMethods { lazy val ExponentiateUnsignedMethod: SMethod = SMethod( this, "expUnsigned", SFunc(Array(this.ownerType, SUnsignedBigInt), this.ownerType), 6, Exponentiate.costKind) // todo: recheck costing + .withIRInfo(MethodCallIrBuilder) .withInfo("Exponentiate this \\lst{GroupElement} to the given number. Returns this to the power of k", ArgInfo("k", "The power")) @@ -396,9 +397,9 @@ case object SGroupElementMethods extends MonoTypeMethods { NegateMethod) super.getMethods() ++ (if (VersionContext.current.isV6SoftForkActivated) { - v5Methods - } else { v5Methods ++ Seq(ExponentiateUnsignedMethod) + } else { + v5Methods }) } diff --git a/parsers/shared/src/main/scala/sigmastate/lang/Types.scala b/parsers/shared/src/main/scala/sigmastate/lang/Types.scala index 06683f6e96..d928e36f61 100644 --- a/parsers/shared/src/main/scala/sigmastate/lang/Types.scala +++ b/parsers/shared/src/main/scala/sigmastate/lang/Types.scala @@ -34,6 +34,7 @@ trait Types extends Core { "Int" -> SInt, "Long" -> SLong, "BigInt" -> SBigInt, + "UnsignedBigInt" -> SUnsignedBigInt, "AvlTree" -> SAvlTree, "Context" -> SContext, "GroupElement" -> SGroupElement, diff --git a/sc/shared/src/main/scala/sigma/compiler/phases/SigmaBinder.scala b/sc/shared/src/main/scala/sigma/compiler/phases/SigmaBinder.scala index 1877131718..af5be938be 100644 --- a/sc/shared/src/main/scala/sigma/compiler/phases/SigmaBinder.scala +++ b/sc/shared/src/main/scala/sigma/compiler/phases/SigmaBinder.scala @@ -56,10 +56,6 @@ class SigmaBinder(env: ScriptEnv, builder: SigmaBuilder, case _ @ Apply(ApplyTypes(Ident("Coll", _), Seq(tpe)), args) => Some(mkConcreteCollection(args, tpe)) - // hack to make possible to write g.exp(ubi) for both unsigned and signed big integers - case Apply(Select(obj, n, resType), args) if n == "exp" && args(0).isInstanceOf[Value[SUnsignedBigInt.type]] => - Some(Apply(Select(obj, "expUnsigned", resType), args)) - // Rule: Coll(...) --> case Apply(Ident("Coll", _), args) => val tpe = if (args.isEmpty) NoType else args(0).tpe diff --git a/sc/shared/src/main/scala/sigma/compiler/phases/SigmaTyper.scala b/sc/shared/src/main/scala/sigma/compiler/phases/SigmaTyper.scala index 3d62ff8dd8..bad5c92d61 100644 --- a/sc/shared/src/main/scala/sigma/compiler/phases/SigmaTyper.scala +++ b/sc/shared/src/main/scala/sigma/compiler/phases/SigmaTyper.scala @@ -165,14 +165,20 @@ class SigmaTyper(val builder: SigmaBuilder, error(s"Cannot get field '$n' in in the object $obj of non-product type ${obj.tpe}", sel.sourceContext) } - case app @ Apply(sel @ Select(obj, n, _), args) => - val newSel = assignType(env, sel) + case app @ Apply(selOriginal @ Select(obj, nOriginal, resType), args) => val newArgs = args.map(assignType(env, _)) - if(n=="expUnsigned") { - println(app) - println("newSel: " + newSel) - println("newArgs: " + newArgs) + + // hack to make possible to write g.exp(ubi) for both unsigned and signed big integers + // could be useful for other use cases where the same front-end code could be + // translated to different methods under the hood, based on argument types + // todo: consider better place for it + val (n, sel) = if (nOriginal == "exp" && newArgs(0).tpe.isInstanceOf[SUnsignedBigInt.type]) { + val newName = "expUnsigned" + (newName, Select(obj, newName, resType)) + } else { + (nOriginal, selOriginal) } + val newSel = assignType(env, sel) newSel.tpe match { case genFunTpe @ SFunc(argTypes, _, _) => // If it's a function then the application has type of that function's return type. diff --git a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala index e6f08f75fc..9a829f6829 100644 --- a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala @@ -251,7 +251,7 @@ class BasicOpsSpecification extends CompilerTestingCommons )} if (activatedVersionInTests < V6SoftForkVersion) { - deserTest() + an[Exception] should be thrownBy deserTest() } else { deserTest() } From eb47d172e83958225b44f8c0cdb4228e55fd0873 Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Sun, 9 Jun 2024 20:42:32 +0300 Subject: [PATCH 140/314] eq test, DataValueComparer --- .../scala/sigma/data/DataValueComparer.scala | 6 ++++ .../utxo/BasicOpsSpecification.scala | 31 +++++++------------ 2 files changed, 18 insertions(+), 19 deletions(-) diff --git a/data/shared/src/main/scala/sigma/data/DataValueComparer.scala b/data/shared/src/main/scala/sigma/data/DataValueComparer.scala index 21ca85012f..39022a2e7e 100644 --- a/data/shared/src/main/scala/sigma/data/DataValueComparer.scala +++ b/data/shared/src/main/scala/sigma/data/DataValueComparer.scala @@ -344,6 +344,12 @@ object DataValueComparer { okEqual = bi == r } + // todo: check costing + case ubi: UnsignedBigInt => /** case 5 (see [[EQ_BigInt]]) */ + E.addFixedCost(EQ_BigInt) { + okEqual = ubi == r + } + case sp1: SigmaProp => E.addCost(MatchType) // for second match below okEqual = r match { diff --git a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala index 9a829f6829..c3e732cd2b 100644 --- a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala @@ -140,28 +140,21 @@ class BasicOpsSpecification extends CompilerTestingCommons flexVerifier.verify(verifyEnv, tree, ctxExt, pr.proof, fakeMessage).get._1 shouldBe true } - property("group order serialization") { - val value = SecP256K1Group.q.divide(new BigInteger("2")) - def deserTest() = {test("big int - q", env, ext, - s"{ val b = bigInt(\"${value.toString}\"); b > 1 }", - null, - true - )} + property("group order deserialization") { + val b = SecP256K1Group.q - if (activatedVersionInTests < V6SoftForkVersion) { - deserTest() - } else { - deserTest() - } - } - - property("restoring unsigned 256 bits") { - val b = new BigInteger("92805629300808893548929804498612226467505866636839045998233220279839291898608") - val ub = new BigInteger(1, b.toByteArray) + val customExt: Seq[(Byte, EvaluatedValue[_ <: SType])] = Map( + 0.toByte -> UnsignedBigIntConstant(b) + ).toSeq - def deserTest() = {test("restoring", env, ext, - s"{ val b = unsignedBigInt(\"${ub.toString}\"); b > 1 }", + def deserTest() = {test("restoring", env, customExt, + s"""{ + | val b1 = unsignedBigInt(\"${b.toString}\") + | val b2 = getVar[UnsignedBigInt](0).get + | b1 == b2 + |} + | """.stripMargin, null, true )} From 33033fc3b9d02934dde612a3efd6bfb2fa63bf48 Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Mon, 10 Jun 2024 13:48:55 +0300 Subject: [PATCH 141/314] importing CheckMinimalErgoTreeVersion from i994 --- .../validation/ValidationRules.scala | 17 ++++++++++++++++- .../src/main/scala/sigma/ast/methods.scala | 2 ++ .../sigmastate/utxo/BasicOpsSpecification.scala | 2 +- 3 files changed, 19 insertions(+), 2 deletions(-) diff --git a/data/shared/src/main/scala/org/ergoplatform/validation/ValidationRules.scala b/data/shared/src/main/scala/org/ergoplatform/validation/ValidationRules.scala index 9d4de47a99..07fe8db0ee 100644 --- a/data/shared/src/main/scala/org/ergoplatform/validation/ValidationRules.scala +++ b/data/shared/src/main/scala/org/ergoplatform/validation/ValidationRules.scala @@ -155,6 +155,20 @@ object ValidationRules { override protected lazy val settings: SigmaValidationSettings = currentSettings } + object CheckMinimalErgoTreeVersion extends ValidationRule(1016, + "ErgoTree should have at least required version") with SoftForkWhenReplaced { + override protected lazy val settings: SigmaValidationSettings = currentSettings + + final def apply(currentVersion: Byte, minVersion: Byte): Unit = { + checkRule() + if (currentVersion < minVersion) { + throwValidationException( + new SigmaException(s"ErgoTree should have at least $minVersion version, but was $currentVersion"), + Array(currentVersion, minVersion)) + } + } + } + val ruleSpecs: Seq[ValidationRule] = Seq( CheckDeserializedScriptType, CheckDeserializedScriptIsSigmaProp, @@ -171,7 +185,8 @@ object ValidationRules { CheckHeaderSizeBit, CheckCostFuncOperation, CheckPositionLimit, - CheckLoopLevelInCostFunction + CheckLoopLevelInCostFunction, + CheckMinimalErgoTreeVersion ) /** Validation settings that correspond to the current version of the ErgoScript implementation. diff --git a/data/shared/src/main/scala/sigma/ast/methods.scala b/data/shared/src/main/scala/sigma/ast/methods.scala index ef548d6185..2cfecea15d 100644 --- a/data/shared/src/main/scala/sigma/ast/methods.scala +++ b/data/shared/src/main/scala/sigma/ast/methods.scala @@ -1,6 +1,7 @@ package sigma.ast import org.ergoplatform._ +import org.ergoplatform.validation.ValidationRules.CheckMinimalErgoTreeVersion import org.ergoplatform.validation._ import sigma._ import sigma.ast.SCollection.{SBooleanArray, SBoxArray, SByteArray, SByteArray2, SHeaderArray} @@ -1533,6 +1534,7 @@ case object SGlobalMethods extends MonoTypeMethods { */ def serialize_eval(mc: MethodCall, G: SigmaDslBuilder, value: SType#WrappedType) (implicit E: ErgoTreeEvaluator): Coll[Byte] = { + CheckMinimalErgoTreeVersion(E.context.currentErgoTreeVersion, VersionContext.V6SoftForkVersion) E.addCost(SigmaByteWriter.StartWriterCost) diff --git a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala index 52756b640f..76d3d84ced 100644 --- a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala @@ -20,7 +20,7 @@ import sigmastate.interpreter.CErgoTreeEvaluator.DefaultEvalSettings import sigmastate.interpreter.Interpreter._ import sigma.ast.Apply import sigma.eval.EvalSettings -import sigma.exceptions.{CostLimitException, InvalidType} +import sigma.exceptions.InvalidType import sigmastate.utils.Helpers import sigmastate.utils.Helpers._ From 01ede1c36047b9fa0797e39964523b7dea74e7b8 Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Mon, 10 Jun 2024 18:26:38 +0300 Subject: [PATCH 142/314] MethodCallSerializerSpecification fix --- .../sigma/serialization/MethodCallSerializerSpecification.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interpreter/shared/src/test/scala/sigma/serialization/MethodCallSerializerSpecification.scala b/interpreter/shared/src/test/scala/sigma/serialization/MethodCallSerializerSpecification.scala index c65b86930c..f93f0ccaf7 100644 --- a/interpreter/shared/src/test/scala/sigma/serialization/MethodCallSerializerSpecification.scala +++ b/interpreter/shared/src/test/scala/sigma/serialization/MethodCallSerializerSpecification.scala @@ -61,7 +61,7 @@ class MethodCallSerializerSpecification extends SerializationSpecification { code } - an[ValidationException] should be thrownBy ( + an[Exception] should be thrownBy ( VersionContext.withVersions((VersionContext.V6SoftForkVersion - 1).toByte, 1) { code } From 40d5e54447b57e187770437fedbad5acb9d3589c Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Mon, 10 Jun 2024 22:07:19 +0300 Subject: [PATCH 143/314] relaxed check in check pow test before activation --- data/shared/src/main/scala/sigma/ast/methods.scala | 2 +- .../test/scala/sigmastate/TestingInterpreterSpecification.scala | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/data/shared/src/main/scala/sigma/ast/methods.scala b/data/shared/src/main/scala/sigma/ast/methods.scala index 1208e36f7f..71ac0a1e1f 100644 --- a/data/shared/src/main/scala/sigma/ast/methods.scala +++ b/data/shared/src/main/scala/sigma/ast/methods.scala @@ -1460,7 +1460,7 @@ case object SHeaderMethods extends MonoTypeMethods { lazy val checkPowMethod = SMethod( this, "checkPow", SFunc(Array(SHeader), SBoolean), 16, FixedCost(JitCost(700))) .withIRInfo(MethodCallIrBuilder) - .withInfo("Validate headers' proof-of-work") + .withInfo("Validate header's proof-of-work") def checkPow_eval(mc: MethodCall, G: SigmaDslBuilder, header: Header) (implicit E: ErgoTreeEvaluator): Boolean = { diff --git a/sc/shared/src/test/scala/sigmastate/TestingInterpreterSpecification.scala b/sc/shared/src/test/scala/sigmastate/TestingInterpreterSpecification.scala index 23d623f077..2c048aad8b 100644 --- a/sc/shared/src/test/scala/sigmastate/TestingInterpreterSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/TestingInterpreterSpecification.scala @@ -445,7 +445,7 @@ class TestingInterpreterSpecification extends CompilerTestingCommons | """.stripMargin if (activatedVersionInTests < V6SoftForkVersion) { - an [sigmastate.exceptions.MethodNotFound] should be thrownBy testEval(source) + an [Exception] should be thrownBy testEval(source) } else { testEval(source) } From df4b0b90225524a408fd54644f5899a9ecbe772f Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Mon, 10 Jun 2024 22:15:03 +0300 Subject: [PATCH 144/314] failing test --- .../test/scala/sigmastate/utxo/BasicOpsSpecification.scala | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala index 79701d6e07..be494533ca 100644 --- a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala @@ -157,6 +157,13 @@ class BasicOpsSpecification extends CompilerTestingCommons ) } + property("BigInt downcasting") { + test("downcasting", env, ext, + "{ sigmaProp(1L.toBigInt.toLong < CONTEXT.preHeader.timestamp) }", + null + ) + } + property("Relation operations") { test("R1", env, ext, "{ allOf(Coll(getVar[Boolean](trueVar).get, true, true)) }", From e7a1aaf13a60a640c47713a4fc39efce1b5c670a Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Tue, 11 Jun 2024 13:06:33 +0300 Subject: [PATCH 145/314] removing more serialize artefacts and HeaderTypeOps --- data/shared/src/main/scala/sigma/ast/ErgoTree.scala | 11 ----------- .../shared/src/main/scala/sigma/ast/SigmaPredef.scala | 1 - .../src/main/scala/sigma/data/CSigmaDslBuilder.scala | 6 +++--- .../sigma/serialization/MethodCallSerializer.scala | 4 +--- .../test/scala/sigmastate/lang/SigmaParserTest.scala | 3 +++ .../ir/wrappers/sigma/impl/SigmaDslImpl.scala | 7 ------- .../main/scala/sigma/compiler/phases/SigmaTyper.scala | 1 - .../test/scala/sigma/LanguageSpecificationV6.scala | 11 +++++------ .../test/scala/sigmastate/lang/SigmaTyperTest.scala | 3 +-- 9 files changed, 13 insertions(+), 34 deletions(-) diff --git a/data/shared/src/main/scala/sigma/ast/ErgoTree.scala b/data/shared/src/main/scala/sigma/ast/ErgoTree.scala index 3bb69b96dc..68d69abd91 100644 --- a/data/shared/src/main/scala/sigma/ast/ErgoTree.scala +++ b/data/shared/src/main/scala/sigma/ast/ErgoTree.scala @@ -228,17 +228,6 @@ object ErgoTree { type HeaderType = HeaderType.Type - /** Convenience methods for working with ErgoTree headers. */ - implicit class HeaderTypeOps(val header: HeaderType) extends AnyVal { - /** Update the version bits of the given header byte with the given version value, - * leaving all other bits unchanged. - */ - def withVersion(version: Byte): HeaderType = ErgoTree.headerWithVersion(header, version) - - /** Sets the constant segregation bit in the given header. */ - def withConstantSegregation: HeaderType = ErgoTree.setConstantSegregation(header) - } - /** Current version of ErgoTree serialization format (aka bite-code language version) */ val VersionFlag: Byte = VersionContext.MaxSupportedScriptVersion diff --git a/data/shared/src/main/scala/sigma/ast/SigmaPredef.scala b/data/shared/src/main/scala/sigma/ast/SigmaPredef.scala index ebe8aa0213..068d955541 100644 --- a/data/shared/src/main/scala/sigma/ast/SigmaPredef.scala +++ b/data/shared/src/main/scala/sigma/ast/SigmaPredef.scala @@ -5,7 +5,6 @@ import org.ergoplatform.{ErgoAddressEncoder, P2PKAddress} import scorex.util.encode.{Base16, Base58, Base64} import sigma.ast.SCollection.{SByteArray, SIntArray} import sigma.ast.SOption.SIntOption -import sigma.ast.SigmaPropConstant import sigma.ast.syntax._ import sigma.data.Nullable import sigma.exceptions.InvalidArguments diff --git a/data/shared/src/main/scala/sigma/data/CSigmaDslBuilder.scala b/data/shared/src/main/scala/sigma/data/CSigmaDslBuilder.scala index d7b092fc0e..3938feacd3 100644 --- a/data/shared/src/main/scala/sigma/data/CSigmaDslBuilder.scala +++ b/data/shared/src/main/scala/sigma/data/CSigmaDslBuilder.scala @@ -5,13 +5,13 @@ import org.ergoplatform.ErgoBox import org.ergoplatform.validation.ValidationRules import scorex.crypto.hash.{Blake2b256, Sha256} import scorex.utils.Longs -import sigma.ast.{AtLeast, SType, SubstConstants} +import sigma.ast.{AtLeast, SubstConstants} import sigma.crypto.{CryptoConstants, EcPointType, Ecp} import sigma.eval.Extensions.EvalCollOps -import sigma.serialization.{DataSerializer, GroupElementSerializer, SigmaSerializer} +import sigma.serialization.{GroupElementSerializer, SigmaSerializer} import sigma.util.Extensions.BigIntegerOps import sigma.validation.SigmaValidationSettings -import sigma.{AvlTree, BigInt, Box, Coll, CollBuilder, Evaluation, GroupElement, SigmaDslBuilder, SigmaProp, VersionContext} +import sigma.{AvlTree, BigInt, Box, Coll, CollBuilder, GroupElement, SigmaDslBuilder, SigmaProp, VersionContext} import java.math.BigInteger diff --git a/data/shared/src/main/scala/sigma/serialization/MethodCallSerializer.scala b/data/shared/src/main/scala/sigma/serialization/MethodCallSerializer.scala index 8a3a226fd8..319a4284e2 100644 --- a/data/shared/src/main/scala/sigma/serialization/MethodCallSerializer.scala +++ b/data/shared/src/main/scala/sigma/serialization/MethodCallSerializer.scala @@ -1,15 +1,13 @@ package sigma.serialization import sigma.ast.syntax._ -import sigma.ast.{MethodCall, SContextMethods, SMethod, SType, STypeSubst, STypeVar, Value, ValueCompanion} +import sigma.ast.{MethodCall, SContextMethods, SMethod, SType, STypeSubst, Value, ValueCompanion} import sigma.util.safeNewArray import SigmaByteWriter._ import debox.cfor import sigma.ast.SContextMethods.BlockchainContextMethodNames import sigma.serialization.CoreByteWriter.{ArgInfo, DataInfo} -import scala.collection.compat.immutable.ArraySeq - case class MethodCallSerializer(cons: (Value[SType], SMethod, IndexedSeq[Value[SType]], STypeSubst) => Value[SType]) extends ValueSerializer[MethodCall] { override def opDesc: ValueCompanion = MethodCall diff --git a/parsers/shared/src/test/scala/sigmastate/lang/SigmaParserTest.scala b/parsers/shared/src/test/scala/sigmastate/lang/SigmaParserTest.scala index 9c79fbd31b..dc63330f95 100644 --- a/parsers/shared/src/test/scala/sigmastate/lang/SigmaParserTest.scala +++ b/parsers/shared/src/test/scala/sigmastate/lang/SigmaParserTest.scala @@ -35,6 +35,9 @@ class SigmaParserTest extends AnyPropSpec with ScalaCheckPropertyChecks with Mat } } + /** Checks parsing result, printing the actual value as a test vector if expected value + * is not equal to actual. + */ def checkParsed(x: String, expected: SValue) = { val parsed = parse(x) if (expected != parsed) { diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/SigmaDslImpl.scala b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/SigmaDslImpl.scala index f5500ae979..c113cb7de3 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/SigmaDslImpl.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/SigmaDslImpl.scala @@ -2104,13 +2104,6 @@ object SigmaDslBuilder extends EntityObject("SigmaDslBuilder") { Array[AnyRef](l, r), true, true, element[Coll[Byte]])) } - - def serialize[T](value: Ref[T]): Ref[Coll[Byte]] = { - asRep[Coll[Byte]](mkMethodCall(source, - SigmaDslBuilderClass.getMethod("serialize", classOf[Sym]), - Array[AnyRef](value), - true, true, element[Coll[Byte]])) - } } // entityUnref: single unref method for each type family diff --git a/sc/shared/src/main/scala/sigma/compiler/phases/SigmaTyper.scala b/sc/shared/src/main/scala/sigma/compiler/phases/SigmaTyper.scala index 0d1763b6e2..679d98a18f 100644 --- a/sc/shared/src/main/scala/sigma/compiler/phases/SigmaTyper.scala +++ b/sc/shared/src/main/scala/sigma/compiler/phases/SigmaTyper.scala @@ -511,7 +511,6 @@ class SigmaTyper(val builder: SigmaBuilder, case v: SigmaBoolean => v case v: Upcast[_, _] => v case v @ Select(_, _, Some(_)) => v - case v @ MethodCall(_, _, _, _) => v case v => error(s"Don't know how to assignType($v)", v.sourceContext) }).ensuring(v => v.tpe != NoType, diff --git a/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala b/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala index 2b658073d8..e23a795b25 100644 --- a/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala +++ b/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala @@ -1,7 +1,6 @@ package sigma -import org.ergoplatform.sdk.utils.ErgoTreeUtils -import sigma.ast.ErgoTree.ZeroHeader +import sigma.ast.ErgoTree.{HeaderType, ZeroHeader} import sigma.ast.SCollection.SByteArray import sigma.ast.syntax.TrueSigmaProp import sigma.ast.{BoolToSigmaProp, CompanionDesc, ConcreteCollection, Constant, ConstantPlaceholder, Downcast, ErgoTree, FalseLeaf, FixedCostItem, FuncValue, Global, JitCost, MethodCall, PerItemCost, SBigInt, SByte, SCollection, SGlobalMethods, SInt, SLong, SPair, SShort, SSigmaProp, STypeVar, SelectField, SubstConstants, ValUse, Value} @@ -341,15 +340,15 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite => property("Fix substConstants in v6.0 for ErgoTree version > 0") { // tree with one segregated constant and v0 val t1 = ErgoTree( - header = ZeroHeader.withConstantSegregation, + header = ErgoTree.setConstantSegregation(ZeroHeader), constants = Vector(TrueSigmaProp), ConstantPlaceholder(0, SSigmaProp)) // tree with one segregated constant and max supported version val t2 = ErgoTree( - header = ZeroHeader - .withVersion(VersionContext.MaxSupportedScriptVersion) - .withConstantSegregation, + header = ErgoTree.setConstantSegregation( + ErgoTree.headerWithVersion(ZeroHeader, VersionContext.MaxSupportedScriptVersion) + ), Vector(TrueSigmaProp), ConstantPlaceholder(0, SSigmaProp)) diff --git a/sc/shared/src/test/scala/sigmastate/lang/SigmaTyperTest.scala b/sc/shared/src/test/scala/sigmastate/lang/SigmaTyperTest.scala index 52dab65991..c68c37a4dc 100644 --- a/sc/shared/src/test/scala/sigmastate/lang/SigmaTyperTest.scala +++ b/sc/shared/src/test/scala/sigmastate/lang/SigmaTyperTest.scala @@ -21,7 +21,6 @@ import sigma.serialization.generators.ObjectGenerators import sigma.ast.Select import sigma.compiler.phases.{SigmaBinder, SigmaTyper} import sigma.exceptions.TyperException -import sigmastate.exceptions.MethodNotFound import sigmastate.helpers.SigmaPPrint class SigmaTyperTest extends AnyPropSpec @@ -30,6 +29,7 @@ class SigmaTyperTest extends AnyPropSpec private val predefFuncRegistry = new PredefinedFuncRegistry(StdSigmaBuilder) import predefFuncRegistry._ + /** Checks that parsing, binding and typing of `x` results in the given expected value. */ def typecheck(env: ScriptEnv, x: String, expected: SValue = null): SType = { try { val builder = TransformingSigmaBuilder @@ -670,5 +670,4 @@ class SigmaTyperTest extends AnyPropSpec ) typecheck(customEnv, "substConstants(scriptBytes, positions, newVals)") shouldBe SByteArray } - } From 38d8969bb48ad69c1ef52b207cd84a48315f5b77 Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Tue, 11 Jun 2024 13:48:40 +0300 Subject: [PATCH 146/314] bigint downcasting fix --- .../src/main/scala/sigma/ast/SType.scala | 6 ++- .../TestingInterpreterSpecification.scala | 37 +++++++++++++++++++ .../utxo/BasicOpsSpecification.scala | 7 ---- 3 files changed, 42 insertions(+), 8 deletions(-) diff --git a/core/shared/src/main/scala/sigma/ast/SType.scala b/core/shared/src/main/scala/sigma/ast/SType.scala index 6656ede3c9..354fa18651 100644 --- a/core/shared/src/main/scala/sigma/ast/SType.scala +++ b/core/shared/src/main/scala/sigma/ast/SType.scala @@ -7,7 +7,7 @@ import sigma.data.OverloadHack.Overloaded1 import sigma.data.{CBigInt, Nullable, SigmaConstants} import sigma.reflection.{RClass, RMethod, ReflectionData} import sigma.util.Extensions.{IntOps, LongOps, ShortOps} -import sigma.{AvlTree, BigInt, Box, Coll, Context, Evaluation, GroupElement, Header, PreHeader, SigmaDslBuilder, SigmaProp} +import sigma.{AvlTree, BigInt, Box, Coll, Context, Evaluation, GroupElement, Header, PreHeader, SigmaDslBuilder, SigmaProp, VersionContext} import java.math.BigInteger @@ -375,6 +375,7 @@ 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 _ => sys.error(s"Cannot downcast value $v to the type $this") } } @@ -396,6 +397,7 @@ 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 _ => sys.error(s"Cannot downcast value $v to the type $this") } } @@ -419,6 +421,7 @@ 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 _ => sys.error(s"Cannot downcast value $v to the type $this") } } @@ -444,6 +447,7 @@ 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 _ => sys.error(s"Cannot downcast value $v to the type $this") } } diff --git a/sc/shared/src/test/scala/sigmastate/TestingInterpreterSpecification.scala b/sc/shared/src/test/scala/sigmastate/TestingInterpreterSpecification.scala index 446f1972a7..11323dcb52 100644 --- a/sc/shared/src/test/scala/sigmastate/TestingInterpreterSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/TestingInterpreterSpecification.scala @@ -10,6 +10,7 @@ import sigma.ast.syntax._ import org.ergoplatform._ import org.scalatest.BeforeAndAfterAll import scorex.util.encode.Base58 +import sigma.VersionContext import sigma.crypto.CryptoConstants import sigma.data.{AvlTreeData, CAND, ProveDlog, SigmaBoolean, TrivialProp} import sigma.util.Extensions.IntOps @@ -215,6 +216,42 @@ class TestingInterpreterSpecification extends CompilerTestingCommons testWithCasting("toBigInt") } + property("BigInt downcasting to byte") { + def test() = testEval("{ sigmaProp(0L.toBigInt.toByte <= CONTEXT.preHeader.version) }") + if(VersionContext.current.isV6SoftForkActivated) { + test() + } else { + an[Exception] shouldBe thrownBy(test()) + } + } + + property("BigInt downcasting to short") { + def test() = testEval("{ sigmaProp(0L.toBigInt.toShort <= CONTEXT.preHeader.version.toShort) }") + if(VersionContext.current.isV6SoftForkActivated) { + test() + } else { + an[Exception] shouldBe thrownBy(test()) + } + } + + property("BigInt downcasting to int") { + def test() = testEval("{ sigmaProp(1L.toBigInt.toInt < CONTEXT.preHeader.timestamp.toInt) }") + if(VersionContext.current.isV6SoftForkActivated) { + test() + } else { + an[Exception] shouldBe thrownBy(test()) + } + } + + property("BigInt downcasting to long") { + def test() = testEval("{ sigmaProp(1L.toBigInt.toLong < CONTEXT.preHeader.timestamp) }") + if(VersionContext.current.isV6SoftForkActivated) { + test() + } else { + an[Exception] shouldBe thrownBy(test()) + } + } + property("Evaluate arithmetic ops") { def testWithCasting(castSuffix: String): Unit = { testEval(s"1.$castSuffix + 2.$castSuffix == 3.$castSuffix") diff --git a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala index be494533ca..79701d6e07 100644 --- a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala @@ -157,13 +157,6 @@ class BasicOpsSpecification extends CompilerTestingCommons ) } - property("BigInt downcasting") { - test("downcasting", env, ext, - "{ sigmaProp(1L.toBigInt.toLong < CONTEXT.preHeader.timestamp) }", - null - ) - } - property("Relation operations") { test("R1", env, ext, "{ allOf(Coll(getVar[Boolean](trueVar).get, true, true)) }", From 11b9cf3c0051045be67053404ca6894863c2b235 Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Tue, 11 Jun 2024 14:10:14 +0300 Subject: [PATCH 147/314] BigInt.down- and upcast to self fixed --- .../src/main/scala/sigma/ast/SType.scala | 24 ++++++------ .../scala/sigma/LanguageSpecificationV6.scala | 37 ++++++++++--------- .../TestingInterpreterSpecification.scala | 4 ++ 3 files changed, 36 insertions(+), 29 deletions(-) diff --git a/core/shared/src/main/scala/sigma/ast/SType.scala b/core/shared/src/main/scala/sigma/ast/SType.scala index 354fa18651..717439bcbb 100644 --- a/core/shared/src/main/scala/sigma/ast/SType.scala +++ b/core/shared/src/main/scala/sigma/ast/SType.scala @@ -469,24 +469,24 @@ case object SBigInt extends SPrimType with SEmbeddable with SNumericType with SM override def numericTypeIndex: Int = 4 override def upcast(v: AnyVal): BigInt = { - val bi = v match { - case x: Byte => BigInteger.valueOf(x.toLong) - case x: Short => BigInteger.valueOf(x.toLong) - case x: Int => BigInteger.valueOf(x.toLong) - case x: Long => BigInteger.valueOf(x) + v match { + case x: Byte => CBigInt(BigInteger.valueOf(x.toLong)) + 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 _ => sys.error(s"Cannot upcast value $v to the type $this") } - CBigInt(bi) } override def downcast(v: AnyVal): BigInt = { - val bi = v match { - case x: Byte => BigInteger.valueOf(x.toLong) - case x: Short => BigInteger.valueOf(x.toLong) - case x: Int => BigInteger.valueOf(x.toLong) - case x: Long => BigInteger.valueOf(x) + v match { + case x: Byte => CBigInt(BigInteger.valueOf(x.toLong)) + 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 _ => sys.error(s"Cannot downcast value $v to the type $this") } - CBigInt(bi) } } diff --git a/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala b/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala index e82bcd886b..fab00e21cb 100644 --- a/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala +++ b/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala @@ -1,8 +1,8 @@ package sigma -import sigma.ast.{Apply, Downcast, FixedCost, FixedCostItem, FuncValue, GetVar, Global, JitCost, MethodCall, NamedDesc, OptionGet, SBigInt, SByte, SGlobalMethods, SInt, SLong, SShort, STypeVar, ValUse} -import sigma.data.{CBigInt, ExactNumeric, RType} -import sigma.eval.{SigmaDsl, TracedCost} +import sigma.ast.{Apply, Downcast, FixedCost, FixedCostItem, FuncValue, GetVar, JitCost, OptionGet, SBigInt, SByte, SInt, SLong, SShort, ValUse} +import sigma.data.{CBigInt, ExactNumeric} +import sigma.eval.SigmaDsl import sigma.util.Extensions.{BooleanOps, ByteOps, IntOps, LongOps} import sigmastate.exceptions.MethodNotFound @@ -172,21 +172,24 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite => } property("BigInt methods equivalence (new features)") { - // TODO v6.0: the behavior of `upcast` for BigInt is different from all other Numeric types (see https://github.com/ScorexFoundation/sigmastate-interpreter/issues/877) - // The `Upcast(bigInt, SBigInt)` node is never produced by ErgoScript compiler, but is still valid ErgoTree. - // It makes sense to fix this inconsistency as part of upcoming forks - assertExceptionThrown( - SBigInt.upcast(CBigInt(new BigInteger("0", 16)).asInstanceOf[AnyVal]), - _.getMessage.contains("Cannot upcast value") - ) + if (activatedVersionInTests < VersionContext.V6SoftForkVersion) { + // The `Upcast(bigInt, SBigInt)` node is never produced by ErgoScript compiler, but is still valid ErgoTree. + // Fixed in 6.0 + assertExceptionThrown( + SBigInt.upcast(CBigInt(new BigInteger("0", 16)).asInstanceOf[AnyVal]), + _.getMessage.contains("Cannot upcast value") + ) - // TODO v6.0: the behavior of `downcast` for BigInt is different from all other Numeric types (see https://github.com/ScorexFoundation/sigmastate-interpreter/issues/877) - // The `Downcast(bigInt, SBigInt)` node is never produced by ErgoScript compiler, but is still valid ErgoTree. - // It makes sense to fix this inconsistency as part of HF - assertExceptionThrown( - SBigInt.downcast(CBigInt(new BigInteger("0", 16)).asInstanceOf[AnyVal]), - _.getMessage.contains("Cannot downcast value") - ) + // The `Downcast(bigInt, SBigInt)` node is never produced by ErgoScript compiler, but is still valid ErgoTree. + // Fixed in 6.0 + assertExceptionThrown( + SBigInt.downcast(CBigInt(new BigInteger("0", 16)).asInstanceOf[AnyVal]), + _.getMessage.contains("Cannot downcast value") + ) + } else { + SBigInt.upcast(CBigInt(new BigInteger("0", 16)).asInstanceOf[AnyVal]) shouldBe CBigInt(new BigInteger("0")) + SBigInt.downcast(CBigInt(new BigInteger("0", 16)).asInstanceOf[AnyVal]) shouldBe CBigInt(new BigInteger("0")) + } if (activatedVersionInTests < VersionContext.V6SoftForkVersion) { // NOTE, for such versions the new features are not supported diff --git a/sc/shared/src/test/scala/sigmastate/TestingInterpreterSpecification.scala b/sc/shared/src/test/scala/sigmastate/TestingInterpreterSpecification.scala index 11323dcb52..1012e9a189 100644 --- a/sc/shared/src/test/scala/sigmastate/TestingInterpreterSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/TestingInterpreterSpecification.scala @@ -252,6 +252,10 @@ class TestingInterpreterSpecification extends CompilerTestingCommons } } + property("upcasting to bigint") { + testEval("{ sigmaProp(1L.toBigInt < bigInt(\"2\")) }") + } + property("Evaluate arithmetic ops") { def testWithCasting(castSuffix: String): Unit = { testEval(s"1.$castSuffix + 2.$castSuffix == 3.$castSuffix") From dd62bd7475f3a4f4d1399bdca8e9dd2361e36255 Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Tue, 11 Jun 2024 17:15:07 +0300 Subject: [PATCH 148/314] failing tests --- .../utxo/BasicOpsSpecification.scala | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala index 79701d6e07..87a3697462 100644 --- a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala @@ -3,6 +3,7 @@ package sigmastate.utxo import org.ergoplatform.ErgoBox.{AdditionalRegisters, R6, R8} import org.ergoplatform._ import sigma.Extensions.ArrayOps +import sigma.VersionContext import sigma.ast.SCollection.SByteArray import sigma.ast.SType.AnyOps import sigma.data.{AvlTreeData, CAnyValue, CSigmaDslBuilder} @@ -157,6 +158,47 @@ class BasicOpsSpecification extends CompilerTestingCommons ) } + property("Lazy evaluation of default in Option.getOrElse") { + val customExt = Map ( + 1.toByte -> IntConstant(5) + ).toSeq + def optTest() = test("getOrElse", env, customExt, + """{ + | getVar[Int](1).getOrElse(getVar[Int](44).get) > 0 + |} + | + |""".stripMargin, + null + ) + + if(VersionContext.current.isV6SoftForkActivated) { + optTest() + } else { + an[Exception] shouldBe thrownBy(optTest()) + } + } + + property("Lazy evaluation of default in Coll.getOrElse") { + val customExt = Map ( + 1.toByte -> IntConstant(5) + ).toSeq + def optTest() = test("getOrElse", env, customExt, + """{ + | val c = Coll[Int](1) + | c.getOrElse(0, getVar[Int](44).get) > 0 + |} + | + |""".stripMargin, + null + ) + + if(VersionContext.current.isV6SoftForkActivated) { + optTest() + } else { + an[Exception] shouldBe thrownBy(optTest()) + } + } + property("Relation operations") { test("R1", env, ext, "{ allOf(Coll(getVar[Boolean](trueVar).get, true, true)) }", From aaef77e76f8b4be4c97520a56cc6b1492bb70791 Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Tue, 11 Jun 2024 17:46:20 +0300 Subject: [PATCH 149/314] close #906: lazy evaluation of default in Option.getOrElse and Coll.getOrElse --- .../main/scala/sigma/ast/transformers.scala | 43 ++++++++++++++----- .../utxo/BasicOpsSpecification.scala | 10 ++--- 2 files changed, 36 insertions(+), 17 deletions(-) diff --git a/data/shared/src/main/scala/sigma/ast/transformers.scala b/data/shared/src/main/scala/sigma/ast/transformers.scala index 939da79d98..8d7e689a18 100644 --- a/data/shared/src/main/scala/sigma/ast/transformers.scala +++ b/data/shared/src/main/scala/sigma/ast/transformers.scala @@ -10,7 +10,7 @@ import sigma.eval.ErgoTreeEvaluator.DataEnv import sigma.serialization.CoreByteWriter.ArgInfo import sigma.serialization.OpCodes import sigma.serialization.ValueCodes.OpCode -import sigma.{Box, Coll, Evaluation} +import sigma.{Box, Coll, Evaluation, VersionContext} // TODO refactor: remove this trait as it doesn't have semantic meaning @@ -258,10 +258,22 @@ case class ByIndex[V <: SType](input: Value[SCollection[V]], val indexV = index.evalTo[Int](env) default match { case Some(d) => - val dV = d.evalTo[V#WrappedType](env) - Value.checkType(d, dV) // necessary because cast to V#WrappedType is erased - addCost(ByIndex.costKind) - inputV.getOrElse(indexV, dV) + if (VersionContext.current.isV6SoftForkActivated) { + // lazy evaluation of default in 6.0 + addCost(ByIndex.costKind) + if (inputV.isDefinedAt(indexV)) { + inputV.apply(indexV) + } else { + val dV = d.evalTo[V#WrappedType](env) + Value.checkType(d, dV) // necessary because cast to V#WrappedType is erased + inputV.getOrElse(indexV, dV) + } + } else { + val dV = d.evalTo[V#WrappedType](env) + Value.checkType(d, dV) // necessary because cast to V#WrappedType is erased + addCost(ByIndex.costKind) + inputV.getOrElse(indexV, dV) + } case _ => addCost(ByIndex.costKind) inputV.apply(indexV) @@ -613,11 +625,22 @@ 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 = { - val inputV = input.evalTo[Option[V#WrappedType]](env) - val dV = default.evalTo[V#WrappedType](env) // TODO v6.0: execute lazily (see https://github.com/ScorexFoundation/sigmastate-interpreter/issues/906) - Value.checkType(default, dV) // necessary because cast to V#WrappedType is erased - addCost(OptionGetOrElse.costKind) - inputV.getOrElse(dV) + if(VersionContext.current.isV6SoftForkActivated) { + // lazy evaluation of default in 6.0 + val inputV = input.evalTo[Option[V#WrappedType]](env) + addCost(OptionGetOrElse.costKind) + inputV.getOrElse { + val dV = default.evalTo[V#WrappedType](env) + Value.checkType(default, dV) // necessary because cast to V#WrappedType is erased + dV + } + } else { + val inputV = input.evalTo[Option[V#WrappedType]](env) + val dV = default.evalTo[V#WrappedType](env) + Value.checkType(default, dV) // necessary because cast to V#WrappedType is erased + addCost(OptionGetOrElse.costKind) + inputV.getOrElse(dV) + } } } object OptionGetOrElse extends ValueCompanion with FixedCostValueCompanion { diff --git a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala index 87a3697462..c1489355e6 100644 --- a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala @@ -166,7 +166,6 @@ class BasicOpsSpecification extends CompilerTestingCommons """{ | getVar[Int](1).getOrElse(getVar[Int](44).get) > 0 |} - | |""".stripMargin, null ) @@ -179,15 +178,12 @@ class BasicOpsSpecification extends CompilerTestingCommons } property("Lazy evaluation of default in Coll.getOrElse") { - val customExt = Map ( - 1.toByte -> IntConstant(5) - ).toSeq - def optTest() = test("getOrElse", env, customExt, + def optTest() = test("getOrElse", env, ext, """{ | val c = Coll[Int](1) - | c.getOrElse(0, getVar[Int](44).get) > 0 + | c.getOrElse(0, getVar[Int](44).get) > 0 && + | c.getOrElse(1, c.getOrElse(0, getVar[Int](44).get)) > 0 |} - | |""".stripMargin, null ) From ea468c9629d84d7260730208018257b76f0ccb35 Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Tue, 11 Jun 2024 21:03:20 +0300 Subject: [PATCH 150/314] initial stubs along first todos for bulletproofs contracts --- .../utxo/BasicOpsSpecification.scala | 170 +++++++++++++++--- 1 file changed, 143 insertions(+), 27 deletions(-) diff --git a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala index c3e732cd2b..64fa69bf24 100644 --- a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala @@ -148,7 +148,7 @@ class BasicOpsSpecification extends CompilerTestingCommons 0.toByte -> UnsignedBigIntConstant(b) ).toSeq - def deserTest() = {test("restoring", env, customExt, + def deserTest() = {test("restoring q", env, customExt, s"""{ | val b1 = unsignedBigInt(\"${b.toString}\") | val b2 = getVar[UnsignedBigInt](0).get @@ -218,35 +218,151 @@ class BasicOpsSpecification extends CompilerTestingCommons 2.toByte -> UnsignedBigIntConstant(z.bigInteger) ).toSeq - def deserTest() = {test("schnorr", env, customExt, - s"""{ - | - | val g: GroupElement = groupGenerator - | val holder = getVar[GroupElement](0).get - | - | val message = fromBase16("${Base16.encode(message)}") - | val e: Coll[Byte] = blake2b256(message) // weak Fiat-Shamir - | val eInt = byteArrayToBigInt(e) // challenge as big integer - | - | // a of signature in (a, z) - | val a = getVar[GroupElement](1).get - | val aBytes = a.getEncoded - | - | // z of signature in (a, z) - | val z = getVar[UnsignedBigInt](2).get - | - | // Signature is valid if g^z = a * x^e - | val properSignature = g.exp(z) == a.multiply(holder.exp(eInt)) - | sigmaProp(properSignature) - |}""".stripMargin, - null, - true - )} + def schnorrTest() = { + test("schnorr", env, customExt, + s"""{ + | + | val g: GroupElement = groupGenerator + | val holder = getVar[GroupElement](0).get + | + | val message = fromBase16("${Base16.encode(message)}") + | val e: Coll[Byte] = blake2b256(message) // weak Fiat-Shamir + | val eInt = byteArrayToBigInt(e) // challenge as big integer + | + | // a of signature in (a, z) + | val a = getVar[GroupElement](1).get + | val aBytes = a.getEncoded + | + | // z of signature in (a, z) + | val z = getVar[UnsignedBigInt](2).get + | + | // Signature is valid if g^z = a * x^e + | val properSignature = g.exp(z) == a.multiply(holder.exp(eInt)) + | sigmaProp(properSignature) + |}""".stripMargin, + null, + true + ) + } + + if (activatedVersionInTests < V6SoftForkVersion) { + an[Exception] should be thrownBy schnorrTest() + } else { + schnorrTest() + } + } + + property("Bulletproof verification for a circuit proof") { + + val g = CGroupElement(SecP256K1Group.generator) + + def circuitTest() = { + test("schnorr", env, ext, + s"""{ + | // circuit data - should be provided via data input likely + | val lWeights: Coll[UnsignedBigInt] + | val rWeights: Coll[UnsignedBigInt] + | val oWeights: Coll[UnsignedBigInt] + | val commitmentWeights: Coll[UnsignedBigInt] + | + | val cs: Coll[UnsignedBigInt] + | val commitments: Coll[GroupElement] + | + | // proof data + | val ai: GroupElement + | val ao: GroupElement + | val s: GroupElement + | val tCommits: Coll[GroupElement] + | val tauX: UnsignedBigInt + | val mu: UnsignedBigInt + | val t: UnsignedBigInt + | + | // inner product proof + | val L: Coll[GroupElement] + | val R: Coll[GroupElement] + | val a: UnsignedBigInt + | val b: UnsignedBigInt + | + | // proof verification: + | val Q = lWeights.size + | + | val q // group order + | + | val yBytes = sha256(q.toBytes ++ aI.getEncoded ++ aO.getEncoded ++ s.getEncoded) + | + | val y = byteArrayToBigInt(yBytes) // should be to unsigned bigint + | + | val z = byteArrayToBigInt(sha256(y ++ q.toBytes)) + | + | + | + | sigmaProp(properSignature) + |}""".stripMargin, + null, + true + ) + } + + if (activatedVersionInTests < V6SoftForkVersion) { + an[Exception] should be thrownBy circuitTest() + } else { + circuitTest() + } + } + + property("Bulletproof verification for a range proof") { + + val g = CGroupElement(SecP256K1Group.generator) + + def circuitTest() = { + test("range proof", env, ext, + s"""{ + | // circuit data - should be provided via data input likely + | val input: GroupElement + | + | // proof data + | val ai: GroupElement + | val s: GroupElement + | val tCommits: Coll[GroupElement] + | val tauX: UnsignedBigInt + | val mu: UnsignedBigInt + | val t: UnsignedBigInt + | + | // inner product proof + | val L: Coll[GroupElement] + | val R: Coll[GroupElement] + | val a: UnsignedBigInt + | val b: UnsignedBigInt + | + | // proof verification: + | val Q = lWeights.size + | + | val q // group order + | + | val yBytes = sha256(q.toBytes ++ input.getEncoded ++ aI.getEncoded ++ s.getEncoded) + | + | val y = byteArrayToBigInt(yBytes) mod q // should be to unsigned bigint + | + | val z = byteArrayToBigInt(sha256(q.toBytes ++ yBytes)) mod q + | + | val zSquared = z * z mod q + | val zCubed = z * z * z mod q // todo: what to do here? + | + | def times() : // todo: implement + | + | // ops needed: modInverse, mod ops + | + | sigmaProp(properSignature) + |}""".stripMargin, + null, + true + ) + } if (activatedVersionInTests < V6SoftForkVersion) { - an[Exception] should be thrownBy deserTest() + an[Exception] should be thrownBy circuitTest() } else { - deserTest() + circuitTest() } } From e9b3253dd4c4220be2f87a1ee66240ad67fd45fd Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Wed, 12 Jun 2024 13:13:18 +0300 Subject: [PATCH 151/314] original code --- .../utxo/BasicOpsSpecification.scala | 62 ++++++++++++++++++- 1 file changed, 61 insertions(+), 1 deletion(-) diff --git a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala index 64fa69bf24..4d7d3718e9 100644 --- a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala @@ -311,6 +311,66 @@ class BasicOpsSpecification extends CompilerTestingCommons } property("Bulletproof verification for a range proof") { + /* + * Original range proof verifier code by Benedikt Bunz: + * + VectorBase vectorBase = params.getVectorBase(); + PeddersenBase base = params.getBase(); + int n = vectorBase.getGs().size(); + T a = proof.getaI(); + T s = proof.getS(); + + BigInteger q = params.getGroup().groupOrder(); + BigInteger y; + + if (salt.isPresent()) { + y = ProofUtils.computeChallenge(q, salt.get(), input, a, s); + } else { + y = ProofUtils.computeChallenge(q, input, a, s); + + } + FieldVector ys = FieldVector.from(VectorX.iterate(n, BigInteger.ONE, y::multiply), q); + + BigInteger z = ProofUtils.challengeFromints(q, y); + + BigInteger zSquared = z.pow(2).mod(q); + BigInteger zCubed = z.pow(3).mod(q); + + FieldVector twos = FieldVector.from(VectorX.iterate(n, BigInteger.ONE, bi -> bi.shiftLeft(1)), q); + FieldVector twoTimesZSquared = twos.times(zSquared); + GeneratorVector tCommits = proof.gettCommits(); + + BigInteger x = ProofUtils.computeChallenge(q,z, tCommits); + + BigInteger tauX = proof.getTauX(); + BigInteger mu = proof.getMu(); + BigInteger t = proof.getT(); + BigInteger k = ys.sum().multiply(z.subtract(zSquared)).subtract(zCubed.shiftLeft(n).subtract(zCubed)); + T lhs = base.commit(t.subtract(k), tauX); + T rhs = tCommits.commit(Arrays.asList(x, x.pow(2))).add(input.multiply(zSquared)); + System.out.println("y " + y); + System.out.println("z " + z); + + System.out.println("x " + x);pow + equal(lhs, rhs, "Polynomial identity check failed, LHS: %s, RHS %s"); + BigInteger uChallenge = ProofUtils.challengeFromints(q, x, tauX, mu, t); + System.out.println("u " + uChallenge); + T u = base.g.multiply(uChallenge); + GeneratorVector hs = vectorBase.getHs(); + GeneratorVector gs = vectorBase.getGs(); + GeneratorVector hPrimes = hs.haddamard(ys.invert()); + FieldVector hExp = ys.times(z).add(twoTimesZSquared); + T P = a.add(s.multiply(x)).add(gs.sum().multiply(z.negate())).add(hPrimes.commit(hExp)).subtract(base.h.multiply(mu)).add(u.multiply(t)); + VectorBase primeBase = new VectorBase<>(gs, hPrimes, u); + // System.out.println("PVerify "+P.normalize()); + // System.out.println("XVerify" +x); + // System.out.println("YVerify" +y); + // System.out.println("ZVerify" +z); + // System.out.println("uVerify" +u); + + EfficientInnerProductVerifier verifier = new EfficientInnerProductVerifier<>(); + verifier.verify(primeBase, P, proof.getProductProof(), uChallenge); + */ val g = CGroupElement(SecP256K1Group.generator) @@ -346,7 +406,7 @@ class BasicOpsSpecification extends CompilerTestingCommons | val z = byteArrayToBigInt(sha256(q.toBytes ++ yBytes)) mod q | | val zSquared = z * z mod q - | val zCubed = z * z * z mod q // todo: what to do here? + | val zCubed = zSquared * z mod q | | def times() : // todo: implement | From a8234b9fe2e0a46bfe1da6a165f8f1877cb35cca Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Wed, 12 Jun 2024 14:17:33 +0300 Subject: [PATCH 152/314] review comments addressed --- core/shared/src/main/scala/sigma/SigmaDsl.scala | 2 +- .../src/main/scala/org/ergoplatform/ErgoHeader.scala | 12 ++++++------ data/shared/src/main/scala/sigma/data/CHeader.scala | 2 +- .../serialization/SerializationSpecification.scala | 2 +- .../sdk/DataJsonEncoderSpecification.scala | 4 ++-- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/core/shared/src/main/scala/sigma/SigmaDsl.scala b/core/shared/src/main/scala/sigma/SigmaDsl.scala index 7353b8f89e..52c2f97bd7 100644 --- a/core/shared/src/main/scala/sigma/SigmaDsl.scala +++ b/core/shared/src/main/scala/sigma/SigmaDsl.scala @@ -467,7 +467,7 @@ trait Header { def unparsedBytes: Coll[Byte] /** - * @return bytes without proof of work, needed for working to get the proof on + * @return header bytes without proof of work, a PoW is generated over them */ def serializeWithoutPoW: Coll[Byte] diff --git a/data/shared/src/main/scala/org/ergoplatform/ErgoHeader.scala b/data/shared/src/main/scala/org/ergoplatform/ErgoHeader.scala index b937bef7a3..b8f75bd862 100644 --- a/data/shared/src/main/scala/org/ergoplatform/ErgoHeader.scala +++ b/data/shared/src/main/scala/org/ergoplatform/ErgoHeader.scala @@ -19,10 +19,10 @@ import sigma.serialization.{GroupElementSerializer, SigmaByteReader, SigmaByteWr * @param d - distance between pseudo-random number, corresponding to nonce `n` and a secret, * corresponding to `pk`. The lower `d` is, the harder it was to find this solution. */ -case class AutolykosSolution(pk: EcPointType, - w: EcPointType, - n: Array[Byte], - d: BigInt) { +class AutolykosSolution(val pk: EcPointType, + val w: EcPointType, + val n: Array[Byte], + val d: BigInt) { val encodedPk: Array[Byte] = GroupElementSerializer.toBytes(pk) @@ -52,7 +52,7 @@ object AutolykosSolution { val nonce = r.getBytes(8) val dBytesLength = r.getUByte() val d = BigInt(BigIntegers.fromUnsignedByteArray(r.getBytes(dBytesLength))) - AutolykosSolution(pk, w, nonce, d) + new AutolykosSolution(pk, w, nonce, d) } } @@ -66,7 +66,7 @@ object AutolykosSolution { override def parse(r: SigmaByteReader): AutolykosSolution = { val pk = GroupElementSerializer.parse(r) val nonce = r.getBytes(8) - AutolykosSolution(pk, wForV2, nonce, dForV2) + new AutolykosSolution(pk, wForV2, nonce, dForV2) } } } diff --git a/data/shared/src/main/scala/sigma/data/CHeader.scala b/data/shared/src/main/scala/sigma/data/CHeader.scala index 5999678e5f..d0b8db6173 100644 --- a/data/shared/src/main/scala/sigma/data/CHeader.scala +++ b/data/shared/src/main/scala/sigma/data/CHeader.scala @@ -118,7 +118,7 @@ object CHeader { votes: Coll[Byte], unparsedBytes: Coll[Byte]): CHeader = { - val solution = AutolykosSolution( + val solution = new AutolykosSolution( minerPk.asInstanceOf[CGroupElement].wrappedValue, powOnetimePk.asInstanceOf[CGroupElement].wrappedValue, powNonce.toArray, diff --git a/interpreter/shared/src/test/scala/sigma/serialization/SerializationSpecification.scala b/interpreter/shared/src/test/scala/sigma/serialization/SerializationSpecification.scala index dc8eef7319..aa7a8722ba 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, 1) { + VersionContext.withVersions(ver, 0) { test() } case None => 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 33e9546000..5835f399cb 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, 1) { + VersionContext.withVersions(ver, 0) { test() } case None => @@ -233,7 +233,7 @@ class DataJsonEncoderSpecification extends SerializationSpecification { } if (tpe == SHeader) { - VersionContext.withVersions(VersionContext.V6SoftForkVersion, 1) { + VersionContext.withVersions(VersionContext.V6SoftForkVersion, 0) { test() } } else { From 7ccce9a0f9eb702e58d5c70da18fbe53b80c7f47 Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Wed, 12 Jun 2024 15:20:17 +0300 Subject: [PATCH 153/314] distinct and reverse (w. no costing) --- .../src/main/scala/sigma/ast/methods.scala | 107 ++++++++++++++---- .../sigma/compiler/ir/GraphBuilding.scala | 4 + .../ir/wrappers/sigma/CollsUnit.scala | 2 + .../ir/wrappers/sigma/impl/CollsImpl.scala | 28 +++++ .../utxo/BasicOpsSpecification.scala | 35 ++++++ 5 files changed, 155 insertions(+), 21 deletions(-) diff --git a/data/shared/src/main/scala/sigma/ast/methods.scala b/data/shared/src/main/scala/sigma/ast/methods.scala index e4cf0007e0..34f69eb965 100644 --- a/data/shared/src/main/scala/sigma/ast/methods.scala +++ b/data/shared/src/main/scala/sigma/ast/methods.scala @@ -890,7 +890,7 @@ object SCollectionMethods extends MethodsContainer with MethodByNameUnapply { SFunc(Array(ThisType, tIV, SInt), SInt, paramIVSeq), 26, PerItemCost(baseCost = JitCost(20), perChunkCost = JitCost(10), chunkSize = 2)) .withIRInfo(MethodCallIrBuilder, javaMethodOf[Coll[_], Any, Int]("indexOf")) - .withInfo(MethodCall, "") + .withInfo(MethodCall, "Returns index of a collection element, or -1 if not found") /** Implements evaluation of Coll.indexOf method call ErgoTree node. * Called via reflection based on naming convention. @@ -939,29 +939,94 @@ object SCollectionMethods extends MethodsContainer with MethodByNameUnapply { } } + + // 6.0 methods below + val ReverseMethod = SMethod(this, "reverse", + SFunc(Array(ThisType), ThisType, paramIVSeq), + 30, Zip_CostKind) // todo: costing + .withIRInfo(MethodCallIrBuilder) + .withInfo(MethodCall, "") + + /** Implements evaluation of Coll.reverse method call ErgoTree node. + * Called via reflection based on naming convention. + * @see SMethod.evalMethod + */ + def reverse_eval[A](mc: MethodCall, xs: Coll[A]) + (implicit E: ErgoTreeEvaluator): Coll[A] = { + val m = mc.method + E.addSeqCost(m.costKind.asInstanceOf[PerItemCost], xs.length, m.opDesc) { () => + xs.reverse + } + } + + val DistinctMethod = SMethod(this, "distinct", + SFunc(Array(ThisType), ThisType, paramIVSeq), + 31, Zip_CostKind) // todo: costing + .withIRInfo(MethodCallIrBuilder) + .withInfo(MethodCall, "") + + /** Implements evaluation of Coll.reverse method call ErgoTree node. + * Called via reflection based on naming convention. + * @see SMethod.evalMethod + */ + def distinct_eval[A](mc: MethodCall, xs: Coll[A]) + (implicit E: ErgoTreeEvaluator): Coll[A] = { + val m = mc.method + E.addSeqCost(m.costKind.asInstanceOf[PerItemCost], xs.length, m.opDesc) { () => + xs.distinct + } + } + + val StartsWithMethod = SMethod(this, "startsWith", + SFunc(Array(ThisType), ThisType, paramIVSeq), + 32, Zip_CostKind) // todo: costing + .withIRInfo(MethodCallIrBuilder) + .withInfo(MethodCall, "") + + val EndsWithMethod = SMethod(this, "endsWith", + SFunc(Array(ThisType), ThisType, paramIVSeq), + 33, Zip_CostKind) // todo: costing + .withIRInfo(MethodCallIrBuilder) + .withInfo(MethodCall, "") + + private val v5Methods = Seq( + SizeMethod, + GetOrElseMethod, + MapMethod, + ExistsMethod, + FoldMethod, + ForallMethod, + SliceMethod, + FilterMethod, + AppendMethod, + ApplyMethod, + IndicesMethod, + FlatMapMethod, + PatchMethod, + UpdatedMethod, + UpdateManyMethod, + IndexOfMethod, + ZipMethod + ) + + private val v6Methods = Seq( + ReverseMethod, + DistinctMethod, + StartsWithMethod, + EndsWithMethod + ) + /** This method should be overriden in derived classes to add new methods in addition to inherited. * Typical override: `super.getMethods() ++ Seq(m1, m2, m3)` */ - override protected def getMethods(): Seq[SMethod] = super.getMethods() ++ - Seq( - SizeMethod, - GetOrElseMethod, - MapMethod, - ExistsMethod, - FoldMethod, - ForallMethod, - SliceMethod, - FilterMethod, - AppendMethod, - ApplyMethod, - IndicesMethod, - FlatMapMethod, - PatchMethod, - UpdatedMethod, - UpdateManyMethod, - IndexOfMethod, - ZipMethod - ) + override protected def getMethods(): Seq[SMethod] = { + if(VersionContext.current.isV6SoftForkActivated) { + super.getMethods() ++ v5Methods ++ v6Methods + } else { + super.getMethods() ++ v5Methods + } + } + } object STupleMethods extends MethodsContainer { diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/GraphBuilding.scala b/sc/shared/src/main/scala/sigma/compiler/ir/GraphBuilding.scala index 7c7b80d39a..29200bfaeb 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/GraphBuilding.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/GraphBuilding.scala @@ -985,6 +985,10 @@ trait GraphBuilding extends Base with DefRewriting { IR: IRContext => val i = asRep[Int](argsV(0)) val d = asRep[t](argsV(1)) xs.getOrElse(i, d) + case SCollectionMethods.ReverseMethod.name => + xs.reverse + case SCollectionMethods.DistinctMethod.name => + xs.distinct case _ => throwError } case (opt: ROption[t]@unchecked, SOptionMethods) => method.name match { diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/CollsUnit.scala b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/CollsUnit.scala index 9b4a002a14..8fe6ff847c 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/CollsUnit.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/CollsUnit.scala @@ -29,6 +29,8 @@ import sigma.compiler.ir.{Base, IRContext} def updateMany(indexes: Ref[Coll[Int]], values: Ref[Coll[A]]): Ref[Coll[A]]; def slice(from: Ref[Int], until: Ref[Int]): Ref[Coll[A]]; def append(other: Ref[Coll[A]]): Ref[Coll[A]]; + def reverse: Ref[Coll[A]] + def distinct: Ref[Coll[A]] }; trait CollBuilder extends Def[CollBuilder] { def fromItems[T](items: Ref[T]*)(implicit cT: Elem[T]): Ref[Coll[T]]; diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/CollsImpl.scala b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/CollsImpl.scala index 0a18ea586a..0ce4c0a178 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/CollsImpl.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/CollsImpl.scala @@ -164,6 +164,20 @@ class CollCls extends EntityObject("Coll") { Array[AnyRef](other), true, false, element[Coll[A]])) } + + override def reverse: Ref[Coll[A]] = { + asRep[Coll[A]](mkMethodCall(self, + CollClass.getMethod("reverse"), + Array[AnyRef](), + true, false, element[Coll[A]])) + } + + override def distinct: Ref[Coll[A]] = { + asRep[Coll[A]](mkMethodCall(self, + CollClass.getMethod("distinct"), + Array[AnyRef](), + true, false, element[Coll[A]])) + } } case class LiftableColl[SA, A](lA: Liftable[SA, A]) @@ -311,6 +325,20 @@ class CollCls extends EntityObject("Coll") { Array[AnyRef](other), true, true, element[Coll[A]])) } + + def reverse: Ref[Coll[A]] = { + asRep[Coll[A]](mkMethodCall(source, + CollClass.getMethod("reverse"), + Array[AnyRef](), + true, true, element[Coll[A]])) + } + + def distinct: Ref[Coll[A]] = { + asRep[Coll[A]](mkMethodCall(source, + CollClass.getMethod("distinct"), + Array[AnyRef](), + true, true, element[Coll[A]])) + } } // entityUnref: single unref method for each type family diff --git a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala index 79701d6e07..f1545a8867 100644 --- a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala @@ -3,6 +3,7 @@ package sigmastate.utxo import org.ergoplatform.ErgoBox.{AdditionalRegisters, R6, R8} import org.ergoplatform._ import sigma.Extensions.ArrayOps +import sigma.VersionContext import sigma.ast.SCollection.SByteArray import sigma.ast.SType.AnyOps import sigma.data.{AvlTreeData, CAnyValue, CSigmaDslBuilder} @@ -157,6 +158,40 @@ class BasicOpsSpecification extends CompilerTestingCommons ) } + property("Coll.reverse"){ + def reverseTest() = test("reverse", env, ext, + """{ + | val c1 = Coll(1, 2, 3) + | val c2 = Coll(3, 2, 1) + | c1.reverse == c2 + | }""".stripMargin, + null + ) + + if(VersionContext.current.isV6SoftForkActivated) { + reverseTest() + } else { + an[Exception] shouldBe thrownBy(reverseTest()) + } + } + + property("Coll.distinct"){ + def reverseTest() = test("distinct", env, ext, + """{ + | val c1 = Coll(1, 2, 3, 3, 2) + | val c2 = Coll(3, 2, 1) + | c1.distinct.reverse == c2 + | }""".stripMargin, + null + ) + + if(VersionContext.current.isV6SoftForkActivated) { + reverseTest() + } else { + an[Exception] shouldBe thrownBy(reverseTest()) + } + } + property("Relation operations") { test("R1", env, ext, "{ allOf(Coll(getVar[Boolean](trueVar).get, true, true)) }", From 2fa224bf13db51e77d50481d772224395f3615db Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Wed, 12 Jun 2024 19:06:54 +0300 Subject: [PATCH 154/314] startsWith and endsWith --- core/shared/src/main/scala/sigma/Colls.scala | 8 ++ .../scala/sigma/data/CollsOverArrays.scala | 8 ++ .../src/main/scala/sigma/ast/methods.scala | 28 ++++- .../sigma/compiler/ir/GraphBuilding.scala | 6 + .../ir/wrappers/sigma/CollsUnit.scala | 2 + .../ir/wrappers/sigma/impl/CollsImpl.scala | 28 +++++ .../utxo/BasicOpsSpecification.scala | 108 +++++++++++++++++- 7 files changed, 184 insertions(+), 4 deletions(-) diff --git a/core/shared/src/main/scala/sigma/Colls.scala b/core/shared/src/main/scala/sigma/Colls.scala index 625120deac..a74da8bf58 100644 --- a/core/shared/src/main/scala/sigma/Colls.scala +++ b/core/shared/src/main/scala/sigma/Colls.scala @@ -76,6 +76,14 @@ trait Coll[@specialized A] { * produces a collection ((x0, y0), ..., (xK, yK)) where K = min(N, M) */ def zip[@specialized B](ys: Coll[B]): Coll[(A, B)] + /** For this collection (x0, ..., xN) and other collection (y0, ..., yM) + * produces a collection ((x0, y0), ..., (xK, yK)) where K = min(N, M) */ + def startsWith(ys: Coll[A]): Boolean + + /** For this collection (x0, ..., xN) and other collection (y0, ..., yM) + * produces a collection ((x0, y0), ..., (xK, yK)) where K = min(N, M) */ + def endsWith(ys: Coll[A]): Boolean + /** Tests whether a predicate holds for at least one element of this collection. * @param p the predicate used to test elements. * @return `true` if the given predicate `p` is satisfied by at least one element of this collection, otherwise `false` diff --git a/core/shared/src/main/scala/sigma/data/CollsOverArrays.scala b/core/shared/src/main/scala/sigma/data/CollsOverArrays.scala index 2413f7f427..506dc001ea 100644 --- a/core/shared/src/main/scala/sigma/data/CollsOverArrays.scala +++ b/core/shared/src/main/scala/sigma/data/CollsOverArrays.scala @@ -39,6 +39,10 @@ class CollOverArray[@specialized A](val toArray: Array[A], val builder: CollBuil @inline def zip[@specialized B](ys: Coll[B]): PairColl[A, B] = builder.pairColl(this, ys) + @inline def startsWith(ys: Coll[A]): Boolean = toArray.startsWith(ys.toArray) + + @inline def endsWith(ys: Coll[A]): Boolean = toArray.endsWith(ys.toArray) + def append(other: Coll[A]): Coll[A] = { if (toArray.length <= 0) return other val result = if (VersionContext.current.isJitActivated) { @@ -350,6 +354,10 @@ class PairOfCols[@specialized L, @specialized R](val ls: Coll[L], val rs: Coll[R def zip[@specialized B](ys: Coll[B]): PairColl[(L,R), B] = builder.pairColl(this, ys) + def startsWith(ys: Coll[(L, R)]): Boolean = toArray.startsWith(ys.toArray) + + def endsWith(ys: Coll[(L, R)]): Boolean = toArray.endsWith(ys.toArray) + override def indices: Coll[Int] = if (ls.length <= rs.length) ls.indices else rs.indices override def flatMap[B: RType](f: ((L, R)) => Coll[B]): Coll[B] = diff --git a/data/shared/src/main/scala/sigma/ast/methods.scala b/data/shared/src/main/scala/sigma/ast/methods.scala index 34f69eb965..d73df90999 100644 --- a/data/shared/src/main/scala/sigma/ast/methods.scala +++ b/data/shared/src/main/scala/sigma/ast/methods.scala @@ -978,17 +978,41 @@ object SCollectionMethods extends MethodsContainer with MethodByNameUnapply { } val StartsWithMethod = SMethod(this, "startsWith", - SFunc(Array(ThisType), ThisType, paramIVSeq), + SFunc(Array(ThisType, ThisType), SBoolean, paramIVSeq), 32, Zip_CostKind) // todo: costing .withIRInfo(MethodCallIrBuilder) .withInfo(MethodCall, "") + /** Implements evaluation of Coll.zip method call ErgoTree node. + * Called via reflection based on naming convention. + * @see SMethod.evalMethod + */ + def startsWith_eval[A](mc: MethodCall, xs: Coll[A], ys: Coll[A]) + (implicit E: ErgoTreeEvaluator): Boolean = { + val m = mc.method + E.addSeqCost(m.costKind.asInstanceOf[PerItemCost], xs.length, m.opDesc) { () => + xs.startsWith(ys) + } + } + val EndsWithMethod = SMethod(this, "endsWith", - SFunc(Array(ThisType), ThisType, paramIVSeq), + SFunc(Array(ThisType, ThisType), SBoolean, paramIVSeq), 33, Zip_CostKind) // todo: costing .withIRInfo(MethodCallIrBuilder) .withInfo(MethodCall, "") + /** Implements evaluation of Coll.zip method call ErgoTree node. + * Called via reflection based on naming convention. + * @see SMethod.evalMethod + */ + def endsWith_eval[A](mc: MethodCall, xs: Coll[A], ys: Coll[A]) + (implicit E: ErgoTreeEvaluator): Boolean = { + val m = mc.method + E.addSeqCost(m.costKind.asInstanceOf[PerItemCost], xs.length, m.opDesc) { () => + xs.endsWith(ys) + } + } + private val v5Methods = Seq( SizeMethod, GetOrElseMethod, 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 29200bfaeb..4a2c8428c1 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/GraphBuilding.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/GraphBuilding.scala @@ -989,6 +989,12 @@ trait GraphBuilding extends Base with DefRewriting { IR: IRContext => xs.reverse case SCollectionMethods.DistinctMethod.name => xs.distinct + case SCollectionMethods.StartsWithMethod.name => + val ys = asRep[Coll[t]](argsV(0)) + xs.startsWith(ys) + case SCollectionMethods.EndsWithMethod.name => + val ys = asRep[Coll[t]](argsV(0)) + xs.endsWith(ys) case _ => throwError } case (opt: ROption[t]@unchecked, SOptionMethods) => method.name match { diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/CollsUnit.scala b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/CollsUnit.scala index 8fe6ff847c..a2d89ddb55 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/CollsUnit.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/CollsUnit.scala @@ -31,6 +31,8 @@ import sigma.compiler.ir.{Base, IRContext} def append(other: Ref[Coll[A]]): Ref[Coll[A]]; def reverse: Ref[Coll[A]] def distinct: Ref[Coll[A]] + def startsWith(ys: Ref[Coll[A]]): Ref[Boolean]; + def endsWith(ys: Ref[Coll[A]]): Ref[Boolean]; }; trait CollBuilder extends Def[CollBuilder] { def fromItems[T](items: Ref[T]*)(implicit cT: Elem[T]): Ref[Coll[T]]; diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/CollsImpl.scala b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/CollsImpl.scala index 0ce4c0a178..4862c90a41 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/CollsImpl.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/CollsImpl.scala @@ -178,6 +178,20 @@ class CollCls extends EntityObject("Coll") { Array[AnyRef](), true, false, element[Coll[A]])) } + + def startsWith(ys: Ref[Coll[A]]): Ref[Boolean] = { + asRep[Boolean](mkMethodCall(self, + CollClass.getMethod("startsWith", classOf[Sym]), + Array[AnyRef](ys), + true, false, element[Boolean])) + } + + def endsWith(ys: Ref[Coll[A]]): Ref[Boolean] = { + asRep[Boolean](mkMethodCall(self, + CollClass.getMethod("endsWith", classOf[Sym]), + Array[AnyRef](ys), + true, false, element[Boolean])) + } } case class LiftableColl[SA, A](lA: Liftable[SA, A]) @@ -339,6 +353,20 @@ class CollCls extends EntityObject("Coll") { Array[AnyRef](), true, true, element[Coll[A]])) } + + def startsWith(ys: Ref[Coll[A]]): Ref[Boolean] = { + asRep[Boolean](mkMethodCall(source, + CollClass.getMethod("startsWith", classOf[Sym]), + Array[AnyRef](ys), + true, true, element[Boolean])) + } + + def endsWith(ys: Ref[Coll[A]]): Ref[Boolean] = { + asRep[Boolean](mkMethodCall(source, + CollClass.getMethod("endsWith", classOf[Sym]), + Array[AnyRef](ys), + true, true, element[Boolean])) + } } // entityUnref: single unref method for each type family diff --git a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala index f1545a8867..aa502db7d0 100644 --- a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala @@ -163,7 +163,11 @@ class BasicOpsSpecification extends CompilerTestingCommons """{ | val c1 = Coll(1, 2, 3) | val c2 = Coll(3, 2, 1) - | c1.reverse == c2 + | + | val b1 = Coll(INPUTS(0), OUTPUTS(0)) + | val b2 = Coll(OUTPUTS(0), INPUTS(0)) + | + | c1.reverse == c2 && b1.reverse == b2 | }""".stripMargin, null ) @@ -180,7 +184,107 @@ class BasicOpsSpecification extends CompilerTestingCommons """{ | val c1 = Coll(1, 2, 3, 3, 2) | val c2 = Coll(3, 2, 1) - | c1.distinct.reverse == c2 + | + | val h1 = Coll(INPUTS(0), INPUTS(0)) + | val h2 = Coll(INPUTS(0)) + | + | c1.distinct.reverse == c2 && h1.distinct == h2 + | }""".stripMargin, + null + ) + + if(VersionContext.current.isV6SoftForkActivated) { + reverseTest() + } else { + an[Exception] shouldBe thrownBy(reverseTest()) + } + } + + property("Coll.startsWith"){ + def reverseTest() = test("distinct", env, ext, + """{ + | val c1 = Coll(1, 2, 3) + | val c2 = Coll(1, 2) + | val c3 = Coll(1, 3) + | val c4 = Coll[Int]() + | val c5 = Coll(1, 2, 3, 4) + | + | val b1 = c1.startsWith(c3) + | val b2 = c1.startsWith(c5) + | + | c1.startsWith(c2) && c1.startsWith(c4) && c1.startsWith(c1) && !b1 && !b2 + | }""".stripMargin, + null + ) + + if(VersionContext.current.isV6SoftForkActivated) { + reverseTest() + } else { + an[Exception] shouldBe thrownBy(reverseTest()) + } + } + + property("Coll.startsWith - tuples"){ + def reverseTest() = test("distinct", env, ext, + """{ + | val c1 = Coll((1, 2), (3, 4), (5, 6)) + | val c2 = Coll((1, 2), (3, 4)) + | val c3 = Coll((1, 3)) + | val c4 = Coll[(Int, Int)]() + | val c5 = Coll((1, 2), (3, 4), (5, 6), (7, 8)) + | + | val b1 = c1.startsWith(c3) + | val b2 = c1.startsWith(c5) + | + | c1.startsWith(c2) && c1.startsWith(c4) && c1.startsWith(c1) && !b1 && !b2 + | }""".stripMargin, + null + ) + + if(VersionContext.current.isV6SoftForkActivated) { + reverseTest() + } else { + an[Exception] shouldBe thrownBy(reverseTest()) + } + } + + property("Coll.endsWith"){ + def reverseTest() = test("distinct", env, ext, + """{ + | val c1 = Coll(1, 2, 3) + | val c2 = Coll(2, 3) + | val c3 = Coll(2, 2) + | val c4 = Coll[Int]() + | val c5 = Coll(1, 2, 3, 4) + | + | val b1 = c1.endsWith(c3) + | val b2 = c1.endsWith(c5) + | + | c1.endsWith(c2) && c1.endsWith(c4) && c1.endsWith(c1) && !b1 && !b2 + | }""".stripMargin, + null + ) + + if(VersionContext.current.isV6SoftForkActivated) { + reverseTest() + } else { + an[Exception] shouldBe thrownBy(reverseTest()) + } + } + + property("Coll.endsWith - tuples"){ + def reverseTest() = test("endsWith tuples", env, ext, + """{ + | val c1 = Coll((1, 2), (2, 3)) + | val c2 = Coll((2, 3)) + | val c3 = Coll((2, 2)) + | val c4 = Coll[(Int, Int)]() + | val c5 = Coll((0, 2), (2, 3)) + | + | val b1 = c1.endsWith(c3) + | val b2 = c1.endsWith(c5) + | + | c1.endsWith(c2) && c1.endsWith(c4) && c1.endsWith(c1) && !b1 && !b2 | }""".stripMargin, null ) From b17c8c81f1dc256276efda7e90c7a762de6999f5 Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Wed, 12 Jun 2024 22:04:03 +0300 Subject: [PATCH 155/314] get --- core/shared/src/main/scala/sigma/Colls.scala | 16 +++++++++++++++ .../src/main/scala/sigma/ast/methods.scala | 20 ++++++++++++++++++- .../sigma/compiler/ir/GraphBuilding.scala | 3 +++ .../ir/wrappers/sigma/CollsUnit.scala | 1 + .../ir/wrappers/sigma/impl/CollsImpl.scala | 15 ++++++++++++++ .../utxo/BasicOpsSpecification.scala | 18 +++++++++++++++++ 6 files changed, 72 insertions(+), 1 deletion(-) diff --git a/core/shared/src/main/scala/sigma/Colls.scala b/core/shared/src/main/scala/sigma/Colls.scala index a74da8bf58..f1633a68a4 100644 --- a/core/shared/src/main/scala/sigma/Colls.scala +++ b/core/shared/src/main/scala/sigma/Colls.scala @@ -45,6 +45,22 @@ trait Coll[@specialized A] { */ def apply(i: Int): A + /** The element at given index. + * Indices start at `0`; `xs.apply(0)` is the first element of collection `xs`. + * Note the indexing syntax `xs(i)` is a shorthand for `xs.apply(i)`. + * + * @param i the index + * @return the element at the given index + * @throws ArrayIndexOutOfBoundsException if `i < 0` or `length <= i` + */ + def get(i: Int): Option[A] = { + if (isDefinedAt(i)) { + Some(apply(i)) + } else { + None + } + } + /** Tests whether this $coll contains given index. * * The implementations of methods `apply` and `isDefinedAt` turn a `Coll[A]` into diff --git a/data/shared/src/main/scala/sigma/ast/methods.scala b/data/shared/src/main/scala/sigma/ast/methods.scala index d73df90999..5cab1118ef 100644 --- a/data/shared/src/main/scala/sigma/ast/methods.scala +++ b/data/shared/src/main/scala/sigma/ast/methods.scala @@ -1013,6 +1013,23 @@ object SCollectionMethods extends MethodsContainer with MethodByNameUnapply { } } + val GetMethod = SMethod(this, "get", + SFunc(Array(ThisType, SInt), SOption(tIV), Array[STypeParam](tIV)), 34, ByIndex.costKind) //todo: costing + .withIRInfo(MethodCallIrBuilder) + .withInfo(MethodCall, "") + + /** Implements evaluation of Coll.zip method call ErgoTree node. + * Called via reflection based on naming convention. + * @see SMethod.evalMethod + */ + def get_eval[A](mc: MethodCall, xs: Coll[A], index: Int) + (implicit E: ErgoTreeEvaluator): Option[A] = { + val m = mc.method + E.addSeqCost(m.costKind.asInstanceOf[PerItemCost], xs.length, m.opDesc) { () => // todo: costing + xs.get(index) + } + } + private val v5Methods = Seq( SizeMethod, GetOrElseMethod, @@ -1037,7 +1054,8 @@ object SCollectionMethods extends MethodsContainer with MethodByNameUnapply { ReverseMethod, DistinctMethod, StartsWithMethod, - EndsWithMethod + EndsWithMethod, + GetMethod ) /** This method should be overriden in derived classes to add new methods in addition to inherited. 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 4a2c8428c1..81092ee0c7 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/GraphBuilding.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/GraphBuilding.scala @@ -995,6 +995,9 @@ trait GraphBuilding extends Base with DefRewriting { IR: IRContext => case SCollectionMethods.EndsWithMethod.name => val ys = asRep[Coll[t]](argsV(0)) xs.endsWith(ys) + case SCollectionMethods.GetMethod.name => + val idx = asRep[Int](argsV(0)) + xs.get(idx) case _ => throwError } case (opt: ROption[t]@unchecked, SOptionMethods) => method.name match { diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/CollsUnit.scala b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/CollsUnit.scala index a2d89ddb55..fdc9fadcba 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/CollsUnit.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/CollsUnit.scala @@ -14,6 +14,7 @@ import sigma.compiler.ir.{Base, IRContext} implicit def eA: Elem[A]; def length: Ref[Int]; def apply(i: Ref[Int]): Ref[A]; + def get(index: Ref[Int]): Ref[WOption[A]]; def getOrElse(index: Ref[Int], default: Ref[A]): Ref[A]; def map[B](f: Ref[scala.Function1[A, B]]): Ref[Coll[B]]; def zip[B](ys: Ref[Coll[B]]): Ref[Coll[scala.Tuple2[A, B]]]; diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/CollsImpl.scala b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/CollsImpl.scala index 4862c90a41..04a7070acf 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/CollsImpl.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/CollsImpl.scala @@ -63,6 +63,14 @@ class CollCls extends EntityObject("Coll") { true, false, element[A])) } + override def get(index: Ref[Int]): Ref[WOption[A]] = { + asRep[WOption[A]](mkMethodCall(self, + CollClass.getMethod("get", classOf[Sym]), + Array[AnyRef](index), + true, false, element[WOption[A]])) + } + + override def map[B](f: Ref[A => B]): Ref[Coll[B]] = { implicit val eB = f.elem.eRange asRep[Coll[B]](mkMethodCall(self, @@ -238,6 +246,13 @@ class CollCls extends EntityObject("Coll") { true, true, element[A])) } + def get(index: Ref[Int]): Ref[WOption[A]] = { + asRep[WOption[A]](mkMethodCall(source, + CollClass.getMethod("get", classOf[Sym]), + Array[AnyRef](index), + true, true, element[WOption[A]])) + } + def map[B](f: Ref[A => B]): Ref[Coll[B]] = { implicit val eB = f.elem.eRange asRep[Coll[B]](mkMethodCall(source, diff --git a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala index aa502db7d0..8784f4b3c5 100644 --- a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala @@ -296,6 +296,24 @@ class BasicOpsSpecification extends CompilerTestingCommons } } + property("Coll.get"){ + def getTest() = test("get", env, ext, + """{ + | val c1 = Coll(1) + | val c2 = Coll[Int]() + | + | c2.get(0).getOrElse(c1.get(0).get) == c1.get(0).get + | }""".stripMargin, + null + ) + + if(VersionContext.current.isV6SoftForkActivated) { + getTest() + } else { + an[Exception] shouldBe thrownBy(getTest()) + } + } + property("Relation operations") { test("R1", env, ext, "{ allOf(Coll(getVar[Boolean](trueVar).get, true, true)) }", From fc3be57fa2223d12312ba8e838d8d4341a8e1c70 Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Wed, 12 Jun 2024 22:35:35 +0300 Subject: [PATCH 156/314] non-execution of get_eval todo --- data/shared/src/main/scala/sigma/ast/methods.scala | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/data/shared/src/main/scala/sigma/ast/methods.scala b/data/shared/src/main/scala/sigma/ast/methods.scala index 5cab1118ef..84fc4955a5 100644 --- a/data/shared/src/main/scala/sigma/ast/methods.scala +++ b/data/shared/src/main/scala/sigma/ast/methods.scala @@ -1024,10 +1024,9 @@ object SCollectionMethods extends MethodsContainer with MethodByNameUnapply { */ def get_eval[A](mc: MethodCall, xs: Coll[A], index: Int) (implicit E: ErgoTreeEvaluator): Option[A] = { - val m = mc.method - E.addSeqCost(m.costKind.asInstanceOf[PerItemCost], xs.length, m.opDesc) { () => // todo: costing - xs.get(index) - } + E.addCost(ByIndex.costKind, mc.method.opDesc) //todo: costing + ??? // todo: this get is not actually executed, why? + xs.get(index) } private val v5Methods = Seq( From f7f31e3614cbce8e8694d12773f2e17b2b391cf3 Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Thu, 13 Jun 2024 13:01:57 +0300 Subject: [PATCH 157/314] fix w/out tests (only manual tests are done) --- .../scala/sigma/data/CollsOverArrays.scala | 19 ++++++++++++++++--- .../utxo/BasicOpsSpecification.scala | 7 +++++++ 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/core/shared/src/main/scala/sigma/data/CollsOverArrays.scala b/core/shared/src/main/scala/sigma/data/CollsOverArrays.scala index 2413f7f427..01cad08471 100644 --- a/core/shared/src/main/scala/sigma/data/CollsOverArrays.scala +++ b/core/shared/src/main/scala/sigma/data/CollsOverArrays.scala @@ -135,7 +135,13 @@ class CollOverArray[@specialized A](val toArray: Array[A], val builder: CollBuil override def equals(obj: scala.Any): Boolean = (this eq obj.asInstanceOf[AnyRef]) || (obj match { case obj: CollOverArray[_] if obj.tItem == this.tItem => - java.util.Objects.deepEquals(obj.toArray, toArray) + java.util.Objects.deepEquals(obj.toArray, this.toArray) + case obj: PairColl[_, _] if obj.tItem == this.tItem => + if(VersionContext.current.isV6SoftForkActivated) { + java.util.Objects.deepEquals(obj.toArray, this.toArray) + } else { + false + } case _ => false }) @@ -237,8 +243,15 @@ private[sigma] class CollOverArrayBuilder extends CollBuilder { builder => class PairOfCols[@specialized L, @specialized R](val ls: Coll[L], val rs: Coll[R]) extends PairColl[L,R] { - override def equals(that: scala.Any) = (this eq that.asInstanceOf[AnyRef]) || (that match { - case that: PairColl[_,_] if that.tItem == this.tItem => ls == that.ls && rs == that.rs + override def equals(that: scala.Any): Boolean = (this eq that.asInstanceOf[AnyRef]) || (that match { + case that: PairColl[_,_] if that.tItem == this.tItem => + ls == that.ls && rs == that.rs + case that: CollOverArray[_] if that.tItem == this.tItem => + if (VersionContext.current.isV6SoftForkActivated) { + java.util.Objects.deepEquals(that.toArray, this.toArray) + } else { + false + } case _ => false }) diff --git a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala index 79701d6e07..705d83b56a 100644 --- a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala @@ -157,6 +157,13 @@ class BasicOpsSpecification extends CompilerTestingCommons ) } + property("coll equality") { + test("R1", env, ext, + "{ SELF.tokens == Coll[(Coll[Byte], Long)]() }", + null + ) + } + property("Relation operations") { test("R1", env, ext, "{ allOf(Coll(getVar[Boolean](trueVar).get, true, true)) }", From e71d7c2a2e06aec1a301c5de87419db63d7f9050 Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Thu, 13 Jun 2024 21:00:07 +0300 Subject: [PATCH 158/314] modInverse --- .../src/main/scala/sigma/SigmaDsl.scala | 6 +- .../src/main/scala/sigma/ast/SType.scala | 3 +- .../src/main/scala/sigma/data/CBigInt.scala | 4 + .../sigma/reflection/ReflectionData.scala | 1 + .../src/main/scala/sigma/ast/methods.scala | 74 +++++++++++++++++-- .../sigma/compiler/ir/GraphBuilding.scala | 5 ++ .../ir/wrappers/sigma/SigmaDslUnit.scala | 1 + .../ir/wrappers/sigma/impl/SigmaDslImpl.scala | 21 ++++++ .../utxo/BasicOpsSpecification.scala | 20 +++++ 9 files changed, 126 insertions(+), 9 deletions(-) diff --git a/core/shared/src/main/scala/sigma/SigmaDsl.scala b/core/shared/src/main/scala/sigma/SigmaDsl.scala index 723ce03bc6..3366bddfac 100644 --- a/core/shared/src/main/scala/sigma/SigmaDsl.scala +++ b/core/shared/src/main/scala/sigma/SigmaDsl.scala @@ -273,15 +273,15 @@ trait UnsignedBigInt { def and(that: UnsignedBigInt): UnsignedBigInt def &(that: UnsignedBigInt): UnsignedBigInt = and(that) - /** Returns a BigInteger whose value is `(this | that)`. (This - * method returns a negative BigInteger if and only if either `this` or `that`` is - * negative.) + /** Returns a BigInteger whose value is `(this | that)`. * * @param that value to be OR'ed with this BigInteger. * @return `this | that` */ def or(that: UnsignedBigInt): UnsignedBigInt def |(that: UnsignedBigInt): UnsignedBigInt = or(that) + + def modInverse(m: UnsignedBigInt): UnsignedBigInt } diff --git a/core/shared/src/main/scala/sigma/ast/SType.scala b/core/shared/src/main/scala/sigma/ast/SType.scala index 411ab1e8c7..1ce1663859 100644 --- a/core/shared/src/main/scala/sigma/ast/SType.scala +++ b/core/shared/src/main/scala/sigma/ast/SType.scala @@ -490,7 +490,7 @@ case object SBigInt extends SPrimType with SEmbeddable with SNumericType with SM case object SUnsignedBigInt extends SPrimType with SEmbeddable with SNumericType with SMonoType { override type WrappedType = UnsignedBigInt override val typeCode: TypeCode = 9: Byte - override val reprClass: RClass[_] = RClass(classOf[BigInt]) + override val reprClass: RClass[_] = RClass(classOf[UnsignedBigInt]) override def typeId = typeCode /** Type of Relation binary op like GE, LE, etc. */ @@ -501,6 +501,7 @@ case object SUnsignedBigInt extends SPrimType with SEmbeddable with SNumericType override def numericTypeIndex: Int = 5 + // todo: consider upcast and downcast rules override def upcast(v: AnyVal): UnsignedBigInt = { val bi = v match { case x: Byte => BigInteger.valueOf(x.toLong) diff --git a/core/shared/src/main/scala/sigma/data/CBigInt.scala b/core/shared/src/main/scala/sigma/data/CBigInt.scala index 5ae617feba..b9134ef892 100644 --- a/core/shared/src/main/scala/sigma/data/CBigInt.scala +++ b/core/shared/src/main/scala/sigma/data/CBigInt.scala @@ -90,4 +90,8 @@ case class CUnsignedBigInt(override val wrappedValue: BigInteger) extends Unsign override def and(that: UnsignedBigInt): UnsignedBigInt = CUnsignedBigInt(wrappedValue.and(that.asInstanceOf[CUnsignedBigInt].wrappedValue)) override def or(that: UnsignedBigInt): UnsignedBigInt = CUnsignedBigInt(wrappedValue.or(that.asInstanceOf[CUnsignedBigInt].wrappedValue)) + + override def modInverse(m: UnsignedBigInt): UnsignedBigInt = { + CUnsignedBigInt(wrappedValue.modInverse(m.asInstanceOf[CUnsignedBigInt].wrappedValue)) + } } diff --git a/core/shared/src/main/scala/sigma/reflection/ReflectionData.scala b/core/shared/src/main/scala/sigma/reflection/ReflectionData.scala index e0e890abca..dde155c7f3 100644 --- a/core/shared/src/main/scala/sigma/reflection/ReflectionData.scala +++ b/core/shared/src/main/scala/sigma/reflection/ReflectionData.scala @@ -128,6 +128,7 @@ object ReflectionData { ) ) } + //todo: add UnsignedBigInt { val clazz = classOf[CollBuilder] registerClassEntry(clazz, diff --git a/data/shared/src/main/scala/sigma/ast/methods.scala b/data/shared/src/main/scala/sigma/ast/methods.scala index 179e21485c..c8d8cacfbb 100644 --- a/data/shared/src/main/scala/sigma/ast/methods.scala +++ b/data/shared/src/main/scala/sigma/ast/methods.scala @@ -90,7 +90,7 @@ sealed trait MethodsContainer { } object MethodsContainer { - private val containers = new SparseArrayContainer[MethodsContainer](Array( + private val methodsV5 = Array( SByteMethods, SShortMethods, SIntMethods, @@ -111,11 +111,29 @@ object MethodsContainer { STupleMethods, SUnitMethods, SAnyMethods - ).map(m => (m.typeId, m))) + ) + + private val methodsV6 = methodsV5 ++ Seq(SUnsignedBigIntMethods) + + private val containersV5 = new SparseArrayContainer[MethodsContainer](methodsV5.map(m => (m.typeId, m))) - def contains(typeId: TypeCode): Boolean = containers.contains(typeId) + private val containersV6 = new SparseArrayContainer[MethodsContainer](methodsV6.map(m => (m.typeId, m))) - def apply(typeId: TypeCode): MethodsContainer = containers(typeId) + def contains(typeId: TypeCode): Boolean = { + if (VersionContext.current.isV6SoftForkActivated) { + containersV6.contains(typeId) + } else { + containersV5.contains(typeId) + } + } + + def apply(typeId: TypeCode): MethodsContainer = { + if (VersionContext.current.isV6SoftForkActivated) { + containersV6(typeId) + } else { + containersV5(typeId) + } + } /** Finds the method of the give type. * @@ -127,7 +145,11 @@ object MethodsContainer { case tup: STuple => STupleMethods.getTupleMethod(tup, methodName) case _ => - containers.get(tpe.typeCode).flatMap(_.method(methodName)) + if (VersionContext.current.isV6SoftForkActivated) { + containersV6.get(tpe.typeCode).flatMap(_.method(methodName)) + } else { + containersV5.get(tpe.typeCode).flatMap(_.method(methodName)) + } } } @@ -335,6 +357,48 @@ case object SBigIntMethods extends SNumericTypeMethods { } +/** Methods of UnsignedBigInt type. Implemented using [[java.math.BigInteger]]. */ +case object SUnsignedBigIntMethods extends SNumericTypeMethods { + /** Type for which this container defines methods. */ + override def ownerType: SMonoType = SUnsignedBigInt + + final val ToNBitsCostInfo = OperationCostInfo( + FixedCost(JitCost(5)), NamedDesc("NBitsMethodCall")) + + //id = 8 to make it after toBits + val ToNBits = SMethod(this, "nbits", SFunc(this.ownerType, SLong), 8, ToNBitsCostInfo.costKind) + .withInfo(ModQ, "Encode this big integer value as NBits") + + // todo: costing + final val ModInverseCostInfo = ToNBitsCostInfo + + // todo: check ids before and after merging with other PRs introducing new methods for Numeric + val ModInverseMethod = SMethod(this, "modInverse", SFunc(Array(this.ownerType, this.ownerType), this.ownerType), 9, ModInverseCostInfo.costKind) + .withIRInfo(MethodCallIrBuilder) + .withInfo(MethodCall, "") + + def modInverse_eval(mc: MethodCall, bi: UnsignedBigInt, m: UnsignedBigInt) + (implicit E: ErgoTreeEvaluator): UnsignedBigInt = { + E.addCost(ModInverseCostInfo.costKind, mc.method.opDesc) + bi.modInverse(m) + } + + // no 6.0 versioning here as it is done in method containers + protected override def getMethods(): Seq[SMethod] = { + super.getMethods() ++ Seq( + ModInverseMethod + ) + } + + /** + * + */ + def nbits_eval(mc: MethodCall, bi: sigma.BigInt)(implicit E: ErgoTreeEvaluator): Long = { + ??? + } + +} + /** Methods of type `String`. */ case object SStringMethods extends MonoTypeMethods { /** Type for which this container defines methods. */ 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 e2350b8338..f9fc30625d 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/GraphBuilding.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/GraphBuilding.scala @@ -1013,6 +1013,11 @@ trait GraphBuilding extends Base with DefRewriting { IR: IRContext => opt.filter(asRep[t => Boolean](argsV(0))) case _ => throwError } + case (ubi: Ref[UnsignedBigInt]@unchecked, SUnsignedBigIntMethods) => method.name match { + case SUnsignedBigIntMethods.ModInverseMethod.name => + val m = asRep[UnsignedBigInt](argsV(0)) + ubi.modInverse(m) + } case (ge: Ref[GroupElement]@unchecked, SGroupElementMethods) => method.name match { case SGroupElementMethods.GetEncodedMethod.name => ge.getEncoded diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/SigmaDslUnit.scala b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/SigmaDslUnit.scala index b3be395a74..e3afee48be 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/SigmaDslUnit.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/SigmaDslUnit.scala @@ -22,6 +22,7 @@ import scalan._ def mod(m: Ref[UnsignedBigInt]): Ref[UnsignedBigInt]; def min(that: Ref[UnsignedBigInt]): Ref[UnsignedBigInt]; def max(that: Ref[UnsignedBigInt]): Ref[UnsignedBigInt]; + def modInverse(m: Ref[UnsignedBigInt]): Ref[UnsignedBigInt] }; trait GroupElement extends Def[GroupElement] { def exp(k: Ref[BigInt]): Ref[GroupElement]; diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/SigmaDslImpl.scala b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/SigmaDslImpl.scala index 27ebaa717c..a81962346a 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/SigmaDslImpl.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/SigmaDslImpl.scala @@ -332,6 +332,13 @@ object UnsignedBigInt extends EntityObject("UnsignedBigInt") { Array[AnyRef](that), true, false, element[UnsignedBigInt])) } + + override def modInverse(m: Ref[UnsignedBigInt]): Ref[UnsignedBigInt] = { + asRep[UnsignedBigInt](mkMethodCall(self, + UnsignedBigIntClass.getMethod("modInverse", classOf[Sym]), + Array[AnyRef](m), + true, false, element[UnsignedBigInt])) + } } @@ -402,6 +409,20 @@ object UnsignedBigInt extends EntityObject("UnsignedBigInt") { Array[AnyRef](that), true, true, element[UnsignedBigInt])) } + + def modInverse(m: Ref[UnsignedBigInt]): Ref[UnsignedBigInt] = { + asRep[UnsignedBigInt](mkMethodCall(source, + UnsignedBigIntClass.getMethod("modInverse", classOf[Sym]), + Array[AnyRef](m), + true, true, element[UnsignedBigInt])) + } + } + + // entityUnref: single unref method for each type family + implicit final def unrefUnsignedBigInt(p: Ref[UnsignedBigInt]): UnsignedBigInt = { + if (p.node.isInstanceOf[UnsignedBigInt]) p.node.asInstanceOf[UnsignedBigInt] + else + UnsignedBigIntAdapter(p) } class UnsignedBigIntElem[To <: UnsignedBigInt] diff --git a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala index 4d7d3718e9..df339f5661 100644 --- a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala @@ -252,6 +252,26 @@ class BasicOpsSpecification extends CompilerTestingCommons } } + property("modInverse") { + def miTest() = { + test("modInverse", env, ext, + s"""{ + | val bi = unsignedBigInt("248486720836984554860790790898080606") + | val m = unsignedBigInt("575879797") + | bi.modInverse(m) > 0 + |}""".stripMargin, + null, + true + ) + } + + if (activatedVersionInTests < V6SoftForkVersion) { + an[Exception] should be thrownBy miTest() + } else { + miTest() + } + } + property("Bulletproof verification for a circuit proof") { val g = CGroupElement(SecP256K1Group.generator) From e989665dd3422d981e020d9ba37b395ac447bbde Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Thu, 13 Jun 2024 22:10:11 +0300 Subject: [PATCH 159/314] plusMod --- .../src/main/scala/sigma/SigmaDsl.scala | 1 + .../src/main/scala/sigma/data/CBigInt.scala | 6 + .../src/main/scala/sigma/ast/methods.scala | 14 ++- .../sigma/compiler/ir/GraphBuilding.scala | 4 + .../ir/wrappers/sigma/SigmaDslUnit.scala | 1 + .../ir/wrappers/sigma/impl/SigmaDslImpl.scala | 14 +++ .../utxo/BasicOpsSpecification.scala | 113 +++++++++++------- 7 files changed, 106 insertions(+), 47 deletions(-) diff --git a/core/shared/src/main/scala/sigma/SigmaDsl.scala b/core/shared/src/main/scala/sigma/SigmaDsl.scala index 3366bddfac..bd4c352b56 100644 --- a/core/shared/src/main/scala/sigma/SigmaDsl.scala +++ b/core/shared/src/main/scala/sigma/SigmaDsl.scala @@ -282,6 +282,7 @@ trait UnsignedBigInt { def |(that: UnsignedBigInt): UnsignedBigInt = or(that) def modInverse(m: UnsignedBigInt): UnsignedBigInt + def plusMod(that: UnsignedBigInt, m: UnsignedBigInt): UnsignedBigInt } diff --git a/core/shared/src/main/scala/sigma/data/CBigInt.scala b/core/shared/src/main/scala/sigma/data/CBigInt.scala index b9134ef892..448cb97e54 100644 --- a/core/shared/src/main/scala/sigma/data/CBigInt.scala +++ b/core/shared/src/main/scala/sigma/data/CBigInt.scala @@ -94,4 +94,10 @@ case class CUnsignedBigInt(override val wrappedValue: BigInteger) extends Unsign override def modInverse(m: UnsignedBigInt): UnsignedBigInt = { CUnsignedBigInt(wrappedValue.modInverse(m.asInstanceOf[CUnsignedBigInt].wrappedValue)) } + + override def plusMod(that: UnsignedBigInt, m: UnsignedBigInt): UnsignedBigInt = { + val thatBi = that.asInstanceOf[CUnsignedBigInt].wrappedValue + val mBi = m.asInstanceOf[CUnsignedBigInt].wrappedValue + CUnsignedBigInt(wrappedValue.add(thatBi).mod(mBi)) + } } diff --git a/data/shared/src/main/scala/sigma/ast/methods.scala b/data/shared/src/main/scala/sigma/ast/methods.scala index c8d8cacfbb..5a1deb184b 100644 --- a/data/shared/src/main/scala/sigma/ast/methods.scala +++ b/data/shared/src/main/scala/sigma/ast/methods.scala @@ -383,10 +383,22 @@ case object SUnsignedBigIntMethods extends SNumericTypeMethods { bi.modInverse(m) } + // todo: costing + val PlusModMethod = SMethod(this, "plusMod", SFunc(Array(this.ownerType, this.ownerType, this.ownerType), this.ownerType), 10, ModInverseCostInfo.costKind) + .withIRInfo(MethodCallIrBuilder) + .withInfo(MethodCall, "") + + def plusMod_eval(mc: MethodCall, bi: UnsignedBigInt, bi2: UnsignedBigInt, m: UnsignedBigInt) + (implicit E: ErgoTreeEvaluator): UnsignedBigInt = { + E.addCost(ModInverseCostInfo.costKind, mc.method.opDesc) // todo: costing + bi.plusMod(bi2, m) + } + // no 6.0 versioning here as it is done in method containers protected override def getMethods(): Seq[SMethod] = { super.getMethods() ++ Seq( - ModInverseMethod + ModInverseMethod, + PlusModMethod ) } 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 f9fc30625d..d24eac2895 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/GraphBuilding.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/GraphBuilding.scala @@ -1017,6 +1017,10 @@ trait GraphBuilding extends Base with DefRewriting { IR: IRContext => case SUnsignedBigIntMethods.ModInverseMethod.name => val m = asRep[UnsignedBigInt](argsV(0)) ubi.modInverse(m) + case SUnsignedBigIntMethods.PlusModMethod.name => + val that = asRep[UnsignedBigInt](argsV(0)) + val m = asRep[UnsignedBigInt](argsV(1)) + ubi.plusMod(that, m) } case (ge: Ref[GroupElement]@unchecked, SGroupElementMethods) => method.name match { case SGroupElementMethods.GetEncodedMethod.name => diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/SigmaDslUnit.scala b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/SigmaDslUnit.scala index e3afee48be..c6c24091ee 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/SigmaDslUnit.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/SigmaDslUnit.scala @@ -23,6 +23,7 @@ import scalan._ def min(that: Ref[UnsignedBigInt]): Ref[UnsignedBigInt]; def max(that: Ref[UnsignedBigInt]): Ref[UnsignedBigInt]; def modInverse(m: Ref[UnsignedBigInt]): Ref[UnsignedBigInt] + def plusMod(that: Ref[UnsignedBigInt], m: Ref[UnsignedBigInt]): Ref[UnsignedBigInt] }; trait GroupElement extends Def[GroupElement] { def exp(k: Ref[BigInt]): Ref[GroupElement]; diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/SigmaDslImpl.scala b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/SigmaDslImpl.scala index a81962346a..a34e3dbd52 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/SigmaDslImpl.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/SigmaDslImpl.scala @@ -339,6 +339,13 @@ object UnsignedBigInt extends EntityObject("UnsignedBigInt") { Array[AnyRef](m), true, false, element[UnsignedBigInt])) } + + override def plusMod(that: Ref[UnsignedBigInt], m: Ref[UnsignedBigInt]): Ref[UnsignedBigInt] = { + asRep[UnsignedBigInt](mkMethodCall(self, + UnsignedBigIntClass.getMethod("plusMod", classOf[Sym], classOf[Sym]), + Array[AnyRef](that, m), + true, false, element[UnsignedBigInt])) + } } @@ -416,6 +423,13 @@ object UnsignedBigInt extends EntityObject("UnsignedBigInt") { Array[AnyRef](m), true, true, element[UnsignedBigInt])) } + + def plusMod(that: Ref[UnsignedBigInt], m: Ref[UnsignedBigInt]): Ref[UnsignedBigInt] = { + asRep[UnsignedBigInt](mkMethodCall(source, + UnsignedBigIntClass.getMethod("plusMod", classOf[Sym], classOf[Sym]), + Array[AnyRef](that, m), + true, true, element[UnsignedBigInt])) + } } // entityUnref: single unref method for each type family diff --git a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala index df339f5661..8f942d0ea5 100644 --- a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala @@ -272,51 +272,14 @@ class BasicOpsSpecification extends CompilerTestingCommons } } - property("Bulletproof verification for a circuit proof") { - - val g = CGroupElement(SecP256K1Group.generator) - - def circuitTest() = { - test("schnorr", env, ext, + property("mod ops - plus") { + def miTest() = { + test("modInverse", env, ext, s"""{ - | // circuit data - should be provided via data input likely - | val lWeights: Coll[UnsignedBigInt] - | val rWeights: Coll[UnsignedBigInt] - | val oWeights: Coll[UnsignedBigInt] - | val commitmentWeights: Coll[UnsignedBigInt] - | - | val cs: Coll[UnsignedBigInt] - | val commitments: Coll[GroupElement] - | - | // proof data - | val ai: GroupElement - | val ao: GroupElement - | val s: GroupElement - | val tCommits: Coll[GroupElement] - | val tauX: UnsignedBigInt - | val mu: UnsignedBigInt - | val t: UnsignedBigInt - | - | // inner product proof - | val L: Coll[GroupElement] - | val R: Coll[GroupElement] - | val a: UnsignedBigInt - | val b: UnsignedBigInt - | - | // proof verification: - | val Q = lWeights.size - | - | val q // group order - | - | val yBytes = sha256(q.toBytes ++ aI.getEncoded ++ aO.getEncoded ++ s.getEncoded) - | - | val y = byteArrayToBigInt(yBytes) // should be to unsigned bigint - | - | val z = byteArrayToBigInt(sha256(y ++ q.toBytes)) - | - | - | - | sigmaProp(properSignature) + | val bi1 = unsignedBigInt("248486720836984554860790790898080606") + | val bi2 = unsignedBigInt("2484867208369845548607907908980997780606") + | val m = unsignedBigInt("575879797") + | bi1.plusMod(bi2, m) > 0 |}""".stripMargin, null, true @@ -324,9 +287,9 @@ class BasicOpsSpecification extends CompilerTestingCommons } if (activatedVersionInTests < V6SoftForkVersion) { - an[Exception] should be thrownBy circuitTest() + an[Exception] should be thrownBy miTest() } else { - circuitTest() + miTest() } } @@ -446,6 +409,64 @@ class BasicOpsSpecification extends CompilerTestingCommons } } + property("Bulletproof verification for a circuit proof") { + + val g = CGroupElement(SecP256K1Group.generator) + + def circuitTest() = { + test("schnorr", env, ext, + s"""{ + | // circuit data - should be provided via data input likely + | val lWeights = Coll[UnsignedBigInt] + | val rWeights: Coll[UnsignedBigInt] + | val oWeights: Coll[UnsignedBigInt] + | val commitmentWeights: Coll[UnsignedBigInt] + | + | val cs: Coll[UnsignedBigInt] + | val commitments: Coll[GroupElement] + | + | // proof data + | val ai: GroupElement + | val ao: GroupElement + | val s: GroupElement + | val tCommits: Coll[GroupElement] + | val tauX: UnsignedBigInt + | val mu: UnsignedBigInt + | val t: UnsignedBigInt + | + | // inner product proof + | val L: Coll[GroupElement] + | val R: Coll[GroupElement] + | val a: UnsignedBigInt + | val b: UnsignedBigInt + | + | // proof verification: + | val Q = lWeights.size + | + | val q // group order + | + | val yBytes = sha256(q.toBytes ++ aI.getEncoded ++ aO.getEncoded ++ s.getEncoded) + | + | val y = byteArrayToBigInt(yBytes) // should be to unsigned bigint + | + | val z = byteArrayToBigInt(sha256(y ++ q.toBytes)) + | + | + | + | sigmaProp(properSignature) + |}""".stripMargin, + null, + true + ) + } + + if (activatedVersionInTests < V6SoftForkVersion) { + an[Exception] should be thrownBy circuitTest() + } else { + circuitTest() + } + } + property("Unit register") { // TODO frontend: implement missing Unit support in compiler // https://github.com/ScorexFoundation/sigmastate-interpreter/issues/820 From d776db3256371c16944aa6c5824d89be4bb1cf51 Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Thu, 13 Jun 2024 22:27:28 +0300 Subject: [PATCH 160/314] multiplyMod --- .../src/main/scala/sigma/SigmaDsl.scala | 1 + .../src/main/scala/sigma/data/CBigInt.scala | 6 ++ .../src/main/scala/sigma/ast/methods.scala | 13 ++++- .../sigma/compiler/ir/GraphBuilding.scala | 4 ++ .../ir/wrappers/sigma/SigmaDslUnit.scala | 1 + .../ir/wrappers/sigma/impl/SigmaDslImpl.scala | 14 +++++ .../utxo/BasicOpsSpecification.scala | 58 +++++++++++++------ 7 files changed, 78 insertions(+), 19 deletions(-) diff --git a/core/shared/src/main/scala/sigma/SigmaDsl.scala b/core/shared/src/main/scala/sigma/SigmaDsl.scala index bd4c352b56..251b94b288 100644 --- a/core/shared/src/main/scala/sigma/SigmaDsl.scala +++ b/core/shared/src/main/scala/sigma/SigmaDsl.scala @@ -283,6 +283,7 @@ trait UnsignedBigInt { def modInverse(m: UnsignedBigInt): UnsignedBigInt def plusMod(that: UnsignedBigInt, m: UnsignedBigInt): UnsignedBigInt + def multiplyMod(that: UnsignedBigInt, m: UnsignedBigInt): UnsignedBigInt } diff --git a/core/shared/src/main/scala/sigma/data/CBigInt.scala b/core/shared/src/main/scala/sigma/data/CBigInt.scala index 448cb97e54..60f87e7cf7 100644 --- a/core/shared/src/main/scala/sigma/data/CBigInt.scala +++ b/core/shared/src/main/scala/sigma/data/CBigInt.scala @@ -100,4 +100,10 @@ case class CUnsignedBigInt(override val wrappedValue: BigInteger) extends Unsign val mBi = m.asInstanceOf[CUnsignedBigInt].wrappedValue CUnsignedBigInt(wrappedValue.add(thatBi).mod(mBi)) } + + override def multiplyMod(that: UnsignedBigInt, m: UnsignedBigInt): UnsignedBigInt = { + val thatBi = that.asInstanceOf[CUnsignedBigInt].wrappedValue + val mBi = m.asInstanceOf[CUnsignedBigInt].wrappedValue + CUnsignedBigInt(wrappedValue.multiply(thatBi).mod(mBi)) + } } diff --git a/data/shared/src/main/scala/sigma/ast/methods.scala b/data/shared/src/main/scala/sigma/ast/methods.scala index 5a1deb184b..35700f799d 100644 --- a/data/shared/src/main/scala/sigma/ast/methods.scala +++ b/data/shared/src/main/scala/sigma/ast/methods.scala @@ -394,11 +394,22 @@ case object SUnsignedBigIntMethods extends SNumericTypeMethods { bi.plusMod(bi2, m) } + val MultiplyModMethod = SMethod(this, "multiplyMod", SFunc(Array(this.ownerType, this.ownerType, this.ownerType), this.ownerType), 11, ModInverseCostInfo.costKind) + .withIRInfo(MethodCallIrBuilder) + .withInfo(MethodCall, "") + + def multiplyMod_eval(mc: MethodCall, bi: UnsignedBigInt, bi2: UnsignedBigInt, m: UnsignedBigInt) + (implicit E: ErgoTreeEvaluator): UnsignedBigInt = { + E.addCost(ModInverseCostInfo.costKind, mc.method.opDesc) // todo: costing + bi.multiplyMod(bi2, m) + } + // no 6.0 versioning here as it is done in method containers protected override def getMethods(): Seq[SMethod] = { super.getMethods() ++ Seq( ModInverseMethod, - PlusModMethod + PlusModMethod, + MultiplyModMethod ) } 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 d24eac2895..a330ae405b 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/GraphBuilding.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/GraphBuilding.scala @@ -1021,6 +1021,10 @@ trait GraphBuilding extends Base with DefRewriting { IR: IRContext => val that = asRep[UnsignedBigInt](argsV(0)) val m = asRep[UnsignedBigInt](argsV(1)) ubi.plusMod(that, m) + case SUnsignedBigIntMethods.MultiplyModMethod.name => + val that = asRep[UnsignedBigInt](argsV(0)) + val m = asRep[UnsignedBigInt](argsV(1)) + ubi.multiplyMod(that, m) } case (ge: Ref[GroupElement]@unchecked, SGroupElementMethods) => method.name match { case SGroupElementMethods.GetEncodedMethod.name => diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/SigmaDslUnit.scala b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/SigmaDslUnit.scala index c6c24091ee..5a9b6903c1 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/SigmaDslUnit.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/SigmaDslUnit.scala @@ -24,6 +24,7 @@ import scalan._ def max(that: Ref[UnsignedBigInt]): Ref[UnsignedBigInt]; def modInverse(m: Ref[UnsignedBigInt]): Ref[UnsignedBigInt] def plusMod(that: Ref[UnsignedBigInt], m: Ref[UnsignedBigInt]): Ref[UnsignedBigInt] + def multiplyMod(that: Ref[UnsignedBigInt], m: Ref[UnsignedBigInt]): Ref[UnsignedBigInt] }; trait GroupElement extends Def[GroupElement] { def exp(k: Ref[BigInt]): Ref[GroupElement]; diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/SigmaDslImpl.scala b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/SigmaDslImpl.scala index a34e3dbd52..05f799dbc5 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/SigmaDslImpl.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/SigmaDslImpl.scala @@ -346,6 +346,13 @@ object UnsignedBigInt extends EntityObject("UnsignedBigInt") { Array[AnyRef](that, m), true, false, element[UnsignedBigInt])) } + + override def multiplyMod(that: Ref[UnsignedBigInt], m: Ref[UnsignedBigInt]): Ref[UnsignedBigInt] = { + asRep[UnsignedBigInt](mkMethodCall(self, + UnsignedBigIntClass.getMethod("multiplyMod", classOf[Sym], classOf[Sym]), + Array[AnyRef](that, m), + true, false, element[UnsignedBigInt])) + } } @@ -430,6 +437,13 @@ object UnsignedBigInt extends EntityObject("UnsignedBigInt") { Array[AnyRef](that, m), true, true, element[UnsignedBigInt])) } + + def multiplyMod(that: Ref[UnsignedBigInt], m: Ref[UnsignedBigInt]): Ref[UnsignedBigInt] = { + asRep[UnsignedBigInt](mkMethodCall(source, + UnsignedBigIntClass.getMethod("multiplyMod", classOf[Sym], classOf[Sym]), + Array[AnyRef](that, m), + true, true, element[UnsignedBigInt])) + } } // entityUnref: single unref method for each type family diff --git a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala index 8f942d0ea5..8b0b8a1367 100644 --- a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala @@ -168,7 +168,7 @@ class BasicOpsSpecification extends CompilerTestingCommons // todo: how to upcast? def deserTest() = {test("restoring", env, ext, - s"{ val b = bigInt(\"${ub.toString}\"); b > 1 }", + s"{ val b = bigInt(\"${ub.toString}\").toUnsigned; b > 1 }", null, true )} @@ -293,6 +293,27 @@ class BasicOpsSpecification extends CompilerTestingCommons } } + property("mod ops - multiply") { + def miTest() = { + test("modInverse", env, ext, + s"""{ + | val bi1 = unsignedBigInt("248486720836984554860790790898080606") + | val bi2 = unsignedBigInt("2484867208369845548607907908980997780606") + | val m = unsignedBigInt("575879797") + | bi1.multiplyMod(bi2, m) > 0 + |}""".stripMargin, + null, + true + ) + } + + if (activatedVersionInTests < V6SoftForkVersion) { + an[Exception] should be thrownBy miTest() + } else { + miTest() + } + } + property("Bulletproof verification for a range proof") { /* * Original range proof verifier code by Benedikt Bunz: @@ -357,30 +378,30 @@ class BasicOpsSpecification extends CompilerTestingCommons val g = CGroupElement(SecP256K1Group.generator) - def circuitTest() = { + def rangeTest() = { test("range proof", env, ext, s"""{ - | // circuit data - should be provided via data input likely - | val input: GroupElement + | // range proof input data + | val input: GroupElement = getVar[GroupElement](0).get | | // proof data - | val ai: GroupElement - | val s: GroupElement - | val tCommits: Coll[GroupElement] - | val tauX: UnsignedBigInt - | val mu: UnsignedBigInt - | val t: UnsignedBigInt + | val ai: GroupElement = getVar[GroupElement](1).get + | val s: GroupElement = getVar[GroupElement](2).get + | val tCommits: Coll[GroupElement] = getVar[Coll[GroupElement]](3).get + | val tauX: UnsignedBigInt = getVar[UnsignedBigInt](4).get + | val mu: UnsignedBigInt = getVar[UnsignedBigInt](5).get + | val t: UnsignedBigInt = getVar[UnsignedBigInt](6).get | | // inner product proof - | val L: Coll[GroupElement] - | val R: Coll[GroupElement] - | val a: UnsignedBigInt - | val b: UnsignedBigInt + | val L: Coll[GroupElement] = getVar[Coll[GroupElement]](7).get + | val R: Coll[GroupElement] = getVar[Coll[GroupElement]](8)).get + | val a: UnsignedBigInt = getVar[UnsignedBigInt](9).get + | val b: UnsignedBigInt = getVar[UnsignedBigInt](10).get | | // proof verification: | val Q = lWeights.size | - | val q // group order + | val q // group order = getVar[UnsignedBigInt](11).get | | val yBytes = sha256(q.toBytes ++ input.getEncoded ++ aI.getEncoded ++ s.getEncoded) | @@ -403,13 +424,14 @@ class BasicOpsSpecification extends CompilerTestingCommons } if (activatedVersionInTests < V6SoftForkVersion) { - an[Exception] should be thrownBy circuitTest() + an[Exception] should be thrownBy rangeTest() } else { - circuitTest() + rangeTest() } } - property("Bulletproof verification for a circuit proof") { + // todo: complete + ignore("Bulletproof verification for a circuit proof") { val g = CGroupElement(SecP256K1Group.generator) From 72db85b0f0e1e49557368aa028801a4048b4213e Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Fri, 14 Jun 2024 23:11:04 +0300 Subject: [PATCH 161/314] toUnsigned & toUnsignedMod --- .../src/main/scala/sigma/SigmaDsl.scala | 4 ++ .../src/main/scala/sigma/data/CBigInt.scala | 12 +++++ .../src/main/scala/sigma/ast/methods.scala | 29 +++++++++- .../sigma/compiler/ir/GraphBuilding.scala | 7 +++ .../ir/wrappers/sigma/SigmaDslUnit.scala | 2 + .../ir/wrappers/sigma/impl/SigmaDslImpl.scala | 34 +++++++++++- .../utxo/BasicOpsSpecification.scala | 54 ++++++++++++++++--- 7 files changed, 133 insertions(+), 9 deletions(-) diff --git a/core/shared/src/main/scala/sigma/SigmaDsl.scala b/core/shared/src/main/scala/sigma/SigmaDsl.scala index 251b94b288..d7749f825b 100644 --- a/core/shared/src/main/scala/sigma/SigmaDsl.scala +++ b/core/shared/src/main/scala/sigma/SigmaDsl.scala @@ -152,6 +152,10 @@ trait BigInt { */ def or(that: BigInt): BigInt def |(that: BigInt): BigInt = or(that) + + def toUnsigned: UnsignedBigInt + + def toUnsignedMod(m: UnsignedBigInt): UnsignedBigInt } diff --git a/core/shared/src/main/scala/sigma/data/CBigInt.scala b/core/shared/src/main/scala/sigma/data/CBigInt.scala index 60f87e7cf7..1951f55486 100644 --- a/core/shared/src/main/scala/sigma/data/CBigInt.scala +++ b/core/shared/src/main/scala/sigma/data/CBigInt.scala @@ -49,6 +49,18 @@ case class CBigInt(override val wrappedValue: BigInteger) extends BigInt with Wr override def and(that: BigInt): BigInt = CBigInt(wrappedValue.and(that.asInstanceOf[CBigInt].wrappedValue)) override def or(that: BigInt): BigInt = CBigInt(wrappedValue.or(that.asInstanceOf[CBigInt].wrappedValue)) + + def toUnsigned: UnsignedBigInt = { + if(this.wrappedValue.compareTo(BigInteger.ZERO) < 0){ + throw new ArithmeticException("BigInteger argument for .toUnsigned is negative in"); + } else { + CUnsignedBigInt(this.wrappedValue) + } + } + + def toUnsignedMod(m: UnsignedBigInt): UnsignedBigInt = { + CUnsignedBigInt(this.wrappedValue.mod(m.asInstanceOf[CUnsignedBigInt].wrappedValue)) + } } /** A default implementation of [[BigInt]] interface. diff --git a/data/shared/src/main/scala/sigma/ast/methods.scala b/data/shared/src/main/scala/sigma/ast/methods.scala index 35700f799d..b34c256449 100644 --- a/data/shared/src/main/scala/sigma/ast/methods.scala +++ b/data/shared/src/main/scala/sigma/ast/methods.scala @@ -6,6 +6,7 @@ import sigma._ import sigma.ast.SCollection.{SBooleanArray, SBoxArray, SByteArray, SByteArray2, SHeaderArray} import sigma.ast.SMethod.{MethodCallIrBuilder, MethodCostFunc, javaMethodOf} import sigma.ast.SType.TypeCode +import sigma.ast.SUnsignedBigIntMethods.ModInverseCostInfo import sigma.ast.syntax.{SValue, ValueOps} import sigma.data.OverloadHack.Overloaded1 import sigma.data.{DataValueComparer, KeyValueColl, Nullable, RType, SigmaConstants} @@ -336,13 +337,39 @@ case object SBigIntMethods extends SNumericTypeMethods { final val ToNBitsCostInfo = OperationCostInfo( FixedCost(JitCost(5)), NamedDesc("NBitsMethodCall")) + // todo: check ids after merging w. other numeric methods + //id = 8 to make it after toBits val ToNBits = SMethod(this, "nbits", SFunc(this.ownerType, SLong), 8, ToNBitsCostInfo.costKind) .withInfo(ModQ, "Encode this big integer value as NBits") + //id = 8 to make it after toBits + val ToUnsigned = SMethod(this, "toUnsigned", SFunc(this.ownerType, SUnsignedBigInt), 9, ToNBitsCostInfo.costKind) + .withIRInfo(MethodCallIrBuilder) + .withInfo(MethodCall, "") + + def toUnsigned_eval(mc: MethodCall, bi: BigInt) + (implicit E: ErgoTreeEvaluator): UnsignedBigInt = { + E.addCost(ModInverseCostInfo.costKind, mc.method.opDesc) + bi.toUnsigned + } + + + val ToUnsignedMod = SMethod(this, "toUnsignedMod", SFunc(Array(this.ownerType, SUnsignedBigInt), SUnsignedBigInt), 10, ToNBitsCostInfo.costKind) + .withIRInfo(MethodCallIrBuilder) + .withInfo(MethodCall, "") + + def toUnsignedMod_eval(mc: MethodCall, bi: BigInt, m: UnsignedBigInt) + (implicit E: ErgoTreeEvaluator): UnsignedBigInt = { + E.addCost(ModInverseCostInfo.costKind, mc.method.opDesc) + bi.toUnsignedMod(m) + } + + + protected override def getMethods(): Seq[SMethod] = { if (VersionContext.current.isV6SoftForkActivated) { - super.getMethods() ++ Seq(ToNBits) + super.getMethods() ++ Seq(ToNBits, ToUnsigned, ToUnsignedMod) } else { super.getMethods() } diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/GraphBuilding.scala b/sc/shared/src/main/scala/sigma/compiler/ir/GraphBuilding.scala index a330ae405b..b637294d0c 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/GraphBuilding.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/GraphBuilding.scala @@ -1013,6 +1013,13 @@ trait GraphBuilding extends Base with DefRewriting { IR: IRContext => opt.filter(asRep[t => Boolean](argsV(0))) case _ => throwError } + case (bi: Ref[BigInt]@unchecked, SBigIntMethods) => method.name match { + case SBigIntMethods.ToUnsigned.name => + bi.toUnsigned() + case SBigIntMethods.ToUnsignedMod.name => + val m = asRep[UnsignedBigInt](argsV(0)) + bi.toUnsignedMod(m) + } case (ubi: Ref[UnsignedBigInt]@unchecked, SUnsignedBigIntMethods) => method.name match { case SUnsignedBigIntMethods.ModInverseMethod.name => val m = asRep[UnsignedBigInt](argsV(0)) diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/SigmaDslUnit.scala b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/SigmaDslUnit.scala index 5a9b6903c1..595880694c 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/SigmaDslUnit.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/SigmaDslUnit.scala @@ -13,6 +13,8 @@ import scalan._ def mod(m: Ref[BigInt]): Ref[BigInt]; def min(that: Ref[BigInt]): Ref[BigInt]; def max(that: Ref[BigInt]): Ref[BigInt]; + def toUnsigned(): Ref[UnsignedBigInt]; + def toUnsignedMod(m: Ref[UnsignedBigInt]): Ref[UnsignedBigInt] }; trait UnsignedBigInt extends Def[UnsignedBigInt] { def add(that: Ref[UnsignedBigInt]): Ref[UnsignedBigInt]; diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/SigmaDslImpl.scala b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/SigmaDslImpl.scala index 05f799dbc5..ef5894fc71 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/SigmaDslImpl.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/SigmaDslImpl.scala @@ -97,6 +97,22 @@ object BigInt extends EntityObject("BigInt") { Array[AnyRef](that), true, false, element[BigInt])) } + + import UnsignedBigInt.unsignedBigIntElement + + override def toUnsigned(): Ref[UnsignedBigInt] = { + asRep[UnsignedBigInt](mkMethodCall(self, + BigIntClass.getMethod("toUnsigned"), + Array[AnyRef](), + true, false, element[UnsignedBigInt](unsignedBigIntElement))) + } + + override def toUnsignedMod(m: Ref[UnsignedBigInt]): Ref[UnsignedBigInt] = { + asRep[UnsignedBigInt](mkMethodCall(self, + BigIntClass.getMethod("toUnsignedMod", classOf[Sym]), + Array[AnyRef](m), + true, false, element[UnsignedBigInt](unsignedBigIntElement))) + } } implicit object LiftableBigInt @@ -165,6 +181,22 @@ object BigInt extends EntityObject("BigInt") { Array[AnyRef](that), true, true, element[BigInt])) } + + import UnsignedBigInt.unsignedBigIntElement + + def toUnsigned(): Ref[UnsignedBigInt] = { + asRep[UnsignedBigInt](mkMethodCall(source, + BigIntClass.getMethod("toUnsigned"), + Array[AnyRef](), + true, true, element[UnsignedBigInt](unsignedBigIntElement))) + } + + def toUnsignedMod(that: Ref[UnsignedBigInt]): Ref[UnsignedBigInt] = { + asRep[UnsignedBigInt](mkMethodCall(source, + BigIntClass.getMethod("UnsignedBigInt", classOf[Sym]), + Array[AnyRef](that), + true, true, element[UnsignedBigInt](unsignedBigIntElement))) + } } // entityUnref: single unref method for each type family @@ -182,7 +214,7 @@ object BigInt extends EntityObject("BigInt") { override protected def collectMethods: Map[RMethod, MethodDesc] = { super.collectMethods ++ Elem.declaredMethods(RClass(classOf[BigInt]), RClass(classOf[SBigInt]), Set( - "add", "subtract", "multiply", "divide", "mod", "min", "max" + "add", "subtract", "multiply", "divide", "mod", "min", "max", "toUnsigned", "toUnsignedMod" )) } } diff --git a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala index 8b0b8a1367..49b565dac1 100644 --- a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala @@ -159,25 +159,65 @@ class BasicOpsSpecification extends CompilerTestingCommons true )} - deserTest() + deserTest() // todo: should fail < 6.0 } - property("signed <-> unsigned bigint conversion - positive bigint") { + property("signed -> unsigned bigint conversion - positive bigint") { val b = new BigInteger("9280562930080889354892980449861222646750586663683904599823322027983929189860") val ub = new BigInteger(1, b.toByteArray) - // todo: how to upcast? - def deserTest() = {test("restoring", env, ext, - s"{ val b = bigInt(\"${ub.toString}\").toUnsigned; b > 1 }", + def conversionTest() = {test("restoring", env, ext, + s"""{ + | val b = bigInt(\"${ub.toString}\") + | val ub = b.toUnsigned + | ub > 1 + | } """.stripMargin, null, true )} - deserTest() + if (activatedVersionInTests < V6SoftForkVersion) { + an[Exception] should be thrownBy conversionTest() + } else { + conversionTest() + } } - property("signed <-> unsigned bigint conversion - negative bigint") { + property("signed -> unsigned bigint conversion - negative bigint") { + def conversionTest() = {test("restoring", env, ext, + s"""{ + | val b = bigInt("-1") + | val ub = b.toUnsigned + | ub > 0 + | } """.stripMargin, + null, + true + )} + if (activatedVersionInTests < V6SoftForkVersion) { + an[Exception] should be thrownBy conversionTest() + } else { + an[Exception] should be thrownBy conversionTest() + } + } + + property("signed -> unsigned bigint conversion - negative bigint - mod") { + def conversionTest() = {test("restoring", env, ext, + s"""{ + | val b = bigInt("-1") + | val m = unsignedBigInt("5") + | val ub = b.toUnsignedMod(m) + | ub >= 0 + | } """.stripMargin, + null, + true + )} + + if (activatedVersionInTests < V6SoftForkVersion) { + an[Exception] should be thrownBy conversionTest() + } else { + conversionTest() + } } property("schnorr sig check") { From fc6d8562d39a7e6ca9b59a92ae4d132d0e5938d1 Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Mon, 17 Jun 2024 19:33:39 +0300 Subject: [PATCH 162/314] mod, toSigned, subtractMod --- .../src/main/scala/sigma/SigmaDsl.scala | 13 +-- .../src/main/scala/sigma/data/CBigInt.scala | 12 ++- .../src/main/scala/sigma/ast/methods.scala | 37 +++++++- .../sigma/compiler/ir/GraphBuilding.scala | 9 ++ .../ir/wrappers/sigma/SigmaDslUnit.scala | 2 + .../ir/wrappers/sigma/impl/SigmaDslImpl.scala | 28 ++++++ .../utxo/BasicOpsSpecification.scala | 88 +++++++++++++++---- 7 files changed, 158 insertions(+), 31 deletions(-) diff --git a/core/shared/src/main/scala/sigma/SigmaDsl.scala b/core/shared/src/main/scala/sigma/SigmaDsl.scala index d7749f825b..86730a705e 100644 --- a/core/shared/src/main/scala/sigma/SigmaDsl.scala +++ b/core/shared/src/main/scala/sigma/SigmaDsl.scala @@ -242,16 +242,6 @@ trait UnsignedBigInt { def mod(m: UnsignedBigInt): UnsignedBigInt def %(m: UnsignedBigInt): UnsignedBigInt = mod(m) - /** - * Returns a BigInt whose value is {@code (this % that)}. - * - * @param that value by which this BigInt is to be divided, and the - * remainder computed. - * @return { @code this % that} - * @throws ArithmeticException if { @code that} is zero. - */ - def remainder(that: UnsignedBigInt): UnsignedBigInt - /** * Returns the minimum of this BigInteger and {@code val}. * @@ -287,7 +277,10 @@ trait UnsignedBigInt { def modInverse(m: UnsignedBigInt): UnsignedBigInt def plusMod(that: UnsignedBigInt, m: UnsignedBigInt): UnsignedBigInt + def subtractMod(that: UnsignedBigInt, m: UnsignedBigInt): UnsignedBigInt def multiplyMod(that: UnsignedBigInt, m: UnsignedBigInt): UnsignedBigInt + + def toSigned(): BigInt } diff --git a/core/shared/src/main/scala/sigma/data/CBigInt.scala b/core/shared/src/main/scala/sigma/data/CBigInt.scala index 1951f55486..0ebf57ab6c 100644 --- a/core/shared/src/main/scala/sigma/data/CBigInt.scala +++ b/core/shared/src/main/scala/sigma/data/CBigInt.scala @@ -93,8 +93,6 @@ case class CUnsignedBigInt(override val wrappedValue: BigInteger) extends Unsign override def mod(m: UnsignedBigInt): UnsignedBigInt = CUnsignedBigInt(wrappedValue.mod(m.asInstanceOf[CUnsignedBigInt].wrappedValue)) - override def remainder(that: UnsignedBigInt): UnsignedBigInt = CUnsignedBigInt(wrappedValue.remainder(that.asInstanceOf[CUnsignedBigInt].wrappedValue)) - override def min(that: UnsignedBigInt): UnsignedBigInt = CUnsignedBigInt(wrappedValue.min(that.asInstanceOf[CUnsignedBigInt].wrappedValue)) override def max(that: UnsignedBigInt): UnsignedBigInt = CUnsignedBigInt(wrappedValue.max(that.asInstanceOf[CUnsignedBigInt].wrappedValue)) @@ -113,9 +111,19 @@ case class CUnsignedBigInt(override val wrappedValue: BigInteger) extends Unsign CUnsignedBigInt(wrappedValue.add(thatBi).mod(mBi)) } + override def subtractMod(that: UnsignedBigInt, m: UnsignedBigInt): UnsignedBigInt = { + val thatBi = that.asInstanceOf[CUnsignedBigInt].wrappedValue + val mBi = m.asInstanceOf[CUnsignedBigInt].wrappedValue + CUnsignedBigInt(wrappedValue.subtract(thatBi).mod(mBi)) + } + override def multiplyMod(that: UnsignedBigInt, m: UnsignedBigInt): UnsignedBigInt = { val thatBi = that.asInstanceOf[CUnsignedBigInt].wrappedValue val mBi = m.asInstanceOf[CUnsignedBigInt].wrappedValue CUnsignedBigInt(wrappedValue.multiply(thatBi).mod(mBi)) } + + override def toSigned(): BigInt = { + CBigInt(wrappedValue.to256BitValueExact) + } } diff --git a/data/shared/src/main/scala/sigma/ast/methods.scala b/data/shared/src/main/scala/sigma/ast/methods.scala index b34c256449..bcd959ebc2 100644 --- a/data/shared/src/main/scala/sigma/ast/methods.scala +++ b/data/shared/src/main/scala/sigma/ast/methods.scala @@ -421,7 +421,17 @@ case object SUnsignedBigIntMethods extends SNumericTypeMethods { bi.plusMod(bi2, m) } - val MultiplyModMethod = SMethod(this, "multiplyMod", SFunc(Array(this.ownerType, this.ownerType, this.ownerType), this.ownerType), 11, ModInverseCostInfo.costKind) + val SubtractModMethod = SMethod(this, "subtractMod", SFunc(Array(this.ownerType, this.ownerType, this.ownerType), this.ownerType), 11, ModInverseCostInfo.costKind) + .withIRInfo(MethodCallIrBuilder) + .withInfo(MethodCall, "") + + def subtractMod_eval(mc: MethodCall, bi: UnsignedBigInt, bi2: UnsignedBigInt, m: UnsignedBigInt) + (implicit E: ErgoTreeEvaluator): UnsignedBigInt = { + E.addCost(ModInverseCostInfo.costKind, mc.method.opDesc) // todo: costing + bi.subtractMod(bi2, m) + } + + val MultiplyModMethod = SMethod(this, "multiplyMod", SFunc(Array(this.ownerType, this.ownerType, this.ownerType), this.ownerType), 12, ModInverseCostInfo.costKind) .withIRInfo(MethodCallIrBuilder) .withInfo(MethodCall, "") @@ -431,12 +441,35 @@ case object SUnsignedBigIntMethods extends SNumericTypeMethods { bi.multiplyMod(bi2, m) } + val ModMethod = SMethod(this, "mod", SFunc(Array(this.ownerType, this.ownerType), this.ownerType), 13, ModInverseCostInfo.costKind) + .withIRInfo(MethodCallIrBuilder) + .withInfo(MethodCall, "") + + def mod_eval(mc: MethodCall, bi: UnsignedBigInt, m: UnsignedBigInt) + (implicit E: ErgoTreeEvaluator): UnsignedBigInt = { + E.addCost(ModInverseCostInfo.costKind, mc.method.opDesc) // todo: costing + bi.mod(m) + } + + val ToSignedMethod = SMethod(this, "toSigned", SFunc(Array(this.ownerType), SBigInt), 14, ModInverseCostInfo.costKind) + .withIRInfo(MethodCallIrBuilder) + .withInfo(MethodCall, "") + + def toSigned_eval(mc: MethodCall, bi: UnsignedBigInt) + (implicit E: ErgoTreeEvaluator): BigInt = { + E.addCost(ModInverseCostInfo.costKind, mc.method.opDesc) // todo: costing + bi.toSigned() + } + // no 6.0 versioning here as it is done in method containers protected override def getMethods(): Seq[SMethod] = { super.getMethods() ++ Seq( ModInverseMethod, PlusModMethod, - MultiplyModMethod + SubtractModMethod, + MultiplyModMethod, + ModMethod, + ToSignedMethod ) } 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 b637294d0c..80433d593d 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/GraphBuilding.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/GraphBuilding.scala @@ -1021,6 +1021,9 @@ trait GraphBuilding extends Base with DefRewriting { IR: IRContext => bi.toUnsignedMod(m) } case (ubi: Ref[UnsignedBigInt]@unchecked, SUnsignedBigIntMethods) => method.name match { + case SUnsignedBigIntMethods.ModMethod.name => + val m = asRep[UnsignedBigInt](argsV(0)) + ubi.mod(m) case SUnsignedBigIntMethods.ModInverseMethod.name => val m = asRep[UnsignedBigInt](argsV(0)) ubi.modInverse(m) @@ -1028,10 +1031,16 @@ trait GraphBuilding extends Base with DefRewriting { IR: IRContext => val that = asRep[UnsignedBigInt](argsV(0)) val m = asRep[UnsignedBigInt](argsV(1)) ubi.plusMod(that, m) + case SUnsignedBigIntMethods.SubtractModMethod.name => + val that = asRep[UnsignedBigInt](argsV(0)) + val m = asRep[UnsignedBigInt](argsV(1)) + ubi.subtractMod(that, m) case SUnsignedBigIntMethods.MultiplyModMethod.name => val that = asRep[UnsignedBigInt](argsV(0)) val m = asRep[UnsignedBigInt](argsV(1)) ubi.multiplyMod(that, m) + case SUnsignedBigIntMethods.ToSignedMethod.name => + ubi.toSigned } case (ge: Ref[GroupElement]@unchecked, SGroupElementMethods) => method.name match { case SGroupElementMethods.GetEncodedMethod.name => diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/SigmaDslUnit.scala b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/SigmaDslUnit.scala index 595880694c..a1d7c9c56b 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/SigmaDslUnit.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/SigmaDslUnit.scala @@ -26,7 +26,9 @@ import scalan._ def max(that: Ref[UnsignedBigInt]): Ref[UnsignedBigInt]; def modInverse(m: Ref[UnsignedBigInt]): Ref[UnsignedBigInt] def plusMod(that: Ref[UnsignedBigInt], m: Ref[UnsignedBigInt]): Ref[UnsignedBigInt] + def subtractMod(that: Ref[UnsignedBigInt], m: Ref[UnsignedBigInt]): Ref[UnsignedBigInt] def multiplyMod(that: Ref[UnsignedBigInt], m: Ref[UnsignedBigInt]): Ref[UnsignedBigInt] + def toSigned: Ref[BigInt] }; trait GroupElement extends Def[GroupElement] { def exp(k: Ref[BigInt]): Ref[GroupElement]; diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/SigmaDslImpl.scala b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/SigmaDslImpl.scala index ef5894fc71..6a62007523 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/SigmaDslImpl.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/SigmaDslImpl.scala @@ -379,12 +379,26 @@ object UnsignedBigInt extends EntityObject("UnsignedBigInt") { true, false, element[UnsignedBigInt])) } + override def subtractMod(that: Ref[UnsignedBigInt], m: Ref[UnsignedBigInt]): Ref[UnsignedBigInt] = { + asRep[UnsignedBigInt](mkMethodCall(self, + UnsignedBigIntClass.getMethod("subtractMod", classOf[Sym], classOf[Sym]), + Array[AnyRef](that, m), + true, false, element[UnsignedBigInt])) + } + override def multiplyMod(that: Ref[UnsignedBigInt], m: Ref[UnsignedBigInt]): Ref[UnsignedBigInt] = { asRep[UnsignedBigInt](mkMethodCall(self, UnsignedBigIntClass.getMethod("multiplyMod", classOf[Sym], classOf[Sym]), Array[AnyRef](that, m), true, false, element[UnsignedBigInt])) } + + override def toSigned: Ref[BigInt] = { + asRep[BigInt](mkMethodCall(self, + UnsignedBigIntClass.getMethod("toSigned"), + Array[AnyRef](), + true, false, element[BigInt])) + } } @@ -470,12 +484,26 @@ object UnsignedBigInt extends EntityObject("UnsignedBigInt") { true, true, element[UnsignedBigInt])) } + def subtractMod(that: Ref[UnsignedBigInt], m: Ref[UnsignedBigInt]): Ref[UnsignedBigInt] = { + asRep[UnsignedBigInt](mkMethodCall(source, + UnsignedBigIntClass.getMethod("subtractMod", classOf[Sym], classOf[Sym]), + Array[AnyRef](that, m), + true, true, element[UnsignedBigInt])) + } + def multiplyMod(that: Ref[UnsignedBigInt], m: Ref[UnsignedBigInt]): Ref[UnsignedBigInt] = { asRep[UnsignedBigInt](mkMethodCall(source, UnsignedBigIntClass.getMethod("multiplyMod", classOf[Sym], classOf[Sym]), Array[AnyRef](that, m), true, true, element[UnsignedBigInt])) } + + def toSigned: Ref[BigInt] = { + asRep[BigInt](mkMethodCall(source, + UnsignedBigIntClass.getMethod("toSigned"), + Array[AnyRef](), + true, true, element[BigInt])) + } } // entityUnref: single unref method for each type family diff --git a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala index 49b565dac1..920fa8ba2c 100644 --- a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala @@ -166,7 +166,7 @@ class BasicOpsSpecification extends CompilerTestingCommons val b = new BigInteger("9280562930080889354892980449861222646750586663683904599823322027983929189860") val ub = new BigInteger(1, b.toByteArray) - def conversionTest() = {test("restoring", env, ext, + def conversionTest() = {test("conversion", env, ext, s"""{ | val b = bigInt(\"${ub.toString}\") | val ub = b.toUnsigned @@ -184,7 +184,7 @@ class BasicOpsSpecification extends CompilerTestingCommons } property("signed -> unsigned bigint conversion - negative bigint") { - def conversionTest() = {test("restoring", env, ext, + def conversionTest() = {test("conversion", env, ext, s"""{ | val b = bigInt("-1") | val ub = b.toUnsigned @@ -202,7 +202,7 @@ class BasicOpsSpecification extends CompilerTestingCommons } property("signed -> unsigned bigint conversion - negative bigint - mod") { - def conversionTest() = {test("restoring", env, ext, + def conversionTest() = {test("conversion", env, ext, s"""{ | val b = bigInt("-1") | val m = unsignedBigInt("5") @@ -220,6 +220,24 @@ class BasicOpsSpecification extends CompilerTestingCommons } } + property("unsigned -> signed bigint conversion") { + def conversionTest() = {test("conversion", env, ext, + s"""{ + | val ub = unsignedBigInt("10") + | val b = ub.toSigned + | b - 11 == bigInt("-1") + | } """.stripMargin, + null, + true + )} + + if (activatedVersionInTests < V6SoftForkVersion) { + an[Exception] should be thrownBy conversionTest() + } else { + conversionTest() + } + } + property("schnorr sig check") { val g = CGroupElement(SecP256K1Group.generator) @@ -292,6 +310,26 @@ class BasicOpsSpecification extends CompilerTestingCommons } } + property("mod") { + def miTest() = { + test("mod", env, ext, + s"""{ + | val bi = unsignedBigInt("248486720836984554860790790898080606") + | val m = unsignedBigInt("575879797") + | bi.mod(m) < bi + |}""".stripMargin, + null, + true + ) + } + + if (activatedVersionInTests < V6SoftForkVersion) { + an[Exception] should be thrownBy miTest() + } else { + miTest() + } + } + property("modInverse") { def miTest() = { test("modInverse", env, ext, @@ -333,6 +371,27 @@ class BasicOpsSpecification extends CompilerTestingCommons } } + property("mod ops - subtract") { + def miTest() = { + test("subtractMod", env, ext, + s"""{ + | val bi1 = unsignedBigInt("2") + | val bi2 = unsignedBigInt("4") + | val m = unsignedBigInt("575879797") + | bi1.subtractMod(bi2, m) > 0 + |}""".stripMargin, + null, + true + ) + } + + if (activatedVersionInTests < V6SoftForkVersion) { + an[Exception] should be thrownBy miTest() + } else { + miTest() + } + } + property("mod ops - multiply") { def miTest() = { test("modInverse", env, ext, @@ -365,17 +424,11 @@ class BasicOpsSpecification extends CompilerTestingCommons T s = proof.getS(); BigInteger q = params.getGroup().groupOrder(); - BigInteger y; - - if (salt.isPresent()) { - y = ProofUtils.computeChallenge(q, salt.get(), input, a, s); - } else { - y = ProofUtils.computeChallenge(q, input, a, s); + BigInteger y = ProofUtils.computeChallenge(q, input, a, s); - } FieldVector ys = FieldVector.from(VectorX.iterate(n, BigInteger.ONE, y::multiply), q); - BigInteger z = ProofUtils.challengeFromints(q, y); + BigInteger z = ProofUtils.challengeFromints(q, y); BigInteger zSquared = z.pow(2).mod(q); BigInteger zCubed = z.pow(3).mod(q); @@ -445,18 +498,19 @@ class BasicOpsSpecification extends CompilerTestingCommons | | val yBytes = sha256(q.toBytes ++ input.getEncoded ++ aI.getEncoded ++ s.getEncoded) | - | val y = byteArrayToBigInt(yBytes) mod q // should be to unsigned bigint + | val y = byteArrayToBigInt(yBytes).toUnsignedMod(q) | - | val z = byteArrayToBigInt(sha256(q.toBytes ++ yBytes)) mod q + | val ys = | - | val zSquared = z * z mod q - | val zCubed = zSquared * z mod q + | val z = byteArrayToBigInt(sha256(q.toBytes ++ yBytes)).toUnsignedMod(q) + | val zSquared = z.multiplyMod(z, q) + | val zCubed = zSquared.multiplyMod(z, q) | - | def times() : // todo: implement + | // def times() : // todo: implement | | // ops needed: modInverse, mod ops | - | sigmaProp(properSignature) + | sigmaProp(zCubed > 0) |}""".stripMargin, null, true From 62fd2a363976797051bba876704b0ea86f54bd75 Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Mon, 17 Jun 2024 22:07:59 +0300 Subject: [PATCH 163/314] initial stub and roundtrip test with longToByteArray --- .../src/main/scala/sigma/SigmaDsl.scala | 5 ++- .../src/main/scala/sigma/ast/methods.scala | 31 +++++++++++++++++-- .../scala/sigma/data/CSigmaDslBuilder.scala | 15 ++++++++- .../utxo/BasicOpsSpecification.scala | 18 +++++++++++ 4 files changed, 65 insertions(+), 4 deletions(-) diff --git a/core/shared/src/main/scala/sigma/SigmaDsl.scala b/core/shared/src/main/scala/sigma/SigmaDsl.scala index df2b419273..18211c7187 100644 --- a/core/shared/src/main/scala/sigma/SigmaDsl.scala +++ b/core/shared/src/main/scala/sigma/SigmaDsl.scala @@ -1,7 +1,8 @@ package sigma -import java.math.BigInteger +import sigma.ast.SType +import java.math.BigInteger import sigma.data._ /** @@ -729,5 +730,7 @@ trait SigmaDslBuilder { /** Returns a byte-wise XOR of the two collections of bytes. */ def xor(l: Coll[Byte], r: Coll[Byte]): Coll[Byte] + + def fromBigEndianBytes[T](tpe: SType, bytes: Coll[Byte])(implicit cT: RType[T]): T } diff --git a/data/shared/src/main/scala/sigma/ast/methods.scala b/data/shared/src/main/scala/sigma/ast/methods.scala index e4cf0007e0..4d5ccb4e02 100644 --- a/data/shared/src/main/scala/sigma/ast/methods.scala +++ b/data/shared/src/main/scala/sigma/ast/methods.scala @@ -2,10 +2,11 @@ package sigma.ast import org.ergoplatform._ import org.ergoplatform.validation._ +import sigma.Evaluation.stypeToRType import sigma._ import sigma.ast.SCollection.{SBooleanArray, SBoxArray, SByteArray, SByteArray2, SHeaderArray} import sigma.ast.SMethod.{MethodCallIrBuilder, MethodCostFunc, javaMethodOf} -import sigma.ast.SType.TypeCode +import sigma.ast.SType.{TypeCode, paramT, tT} import sigma.ast.syntax.{SValue, ValueOps} import sigma.data.OverloadHack.Overloaded1 import sigma.data.{DataValueComparer, KeyValueColl, Nullable, RType, SigmaConstants} @@ -1519,9 +1520,35 @@ case object SGlobalMethods extends MonoTypeMethods { Xor.xorWithCosting(ls, rs) } - protected override def getMethods() = super.getMethods() ++ Seq( + lazy val fromBigEndianBytesMethod = SMethod( + this, "fromBigEndianBytes", SFunc(Array(SGlobal, SByteArray), tT, Array(paramT)), 3, Xor.costKind) // todo: id, cossting + .withIRInfo(MethodCallIrBuilder) + .withInfo(MethodCall, "Multiply this number with \\lst{other} by module Q.", ArgInfo("other", "Number to multiply with this.")) // todo: desc + + def fromBigEndianBytes_eval(mc: MethodCall, G: SigmaDslBuilder, bytes: Coll[Byte]) + (implicit E: ErgoTreeEvaluator): Any = { + val tpe = mc.tpe + val cT = stypeToRType(tpe) + E.addSeqCost(Xor.costKind, bytes.length, Xor.opDesc) { () => // todo: cost + G.fromBigEndianBytes(tpe, bytes)(cT) + } + } + + private val v5Methods = super.getMethods() ++ Seq( groupGeneratorMethod, xorMethod ) + + private val v6Methods = v5Methods ++ Seq( + fromBigEndianBytesMethod + ) + + protected override def getMethods() = { + if (VersionContext.current.isV6SoftForkActivated) { + v6Methods + } else { + v5Methods + } + } } diff --git a/data/shared/src/main/scala/sigma/data/CSigmaDslBuilder.scala b/data/shared/src/main/scala/sigma/data/CSigmaDslBuilder.scala index 3938feacd3..b91184ccdb 100644 --- a/data/shared/src/main/scala/sigma/data/CSigmaDslBuilder.scala +++ b/data/shared/src/main/scala/sigma/data/CSigmaDslBuilder.scala @@ -5,7 +5,7 @@ import org.ergoplatform.ErgoBox import org.ergoplatform.validation.ValidationRules import scorex.crypto.hash.{Blake2b256, Sha256} import scorex.utils.Longs -import sigma.ast.{AtLeast, SubstConstants} +import sigma.ast.{AtLeast, SByte, SLong, SType, SubstConstants} import sigma.crypto.{CryptoConstants, EcPointType, Ecp} import sigma.eval.Extensions.EvalCollOps import sigma.serialization.{GroupElementSerializer, SigmaSerializer} @@ -200,6 +200,19 @@ class CSigmaDslBuilder extends SigmaDslBuilder { dsl => val p = GroupElementSerializer.parse(r) this.GroupElement(p) } + + override def fromBigEndianBytes[T](tpe: SType, bytes: Coll[Byte])(implicit cT: RType[T]): T = { + tpe match { + case SByte => if (bytes.length != 1) { + throw new IllegalArgumentException("To deserialize SByte with fromBigEndianBytes, exactly one byte should be provided") + } else { + bytes.apply(0).asInstanceOf[T] + } + case SLong => Longs.fromByteArray(bytes.toArray).asInstanceOf[T] + case _ => throw new IllegalArgumentException("Unsupported type provided in fromBigEndianBytes") + // todo: more types + } + } } /** Default singleton instance of Global object, which implements global ErgoTree functions. */ diff --git a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala index 79701d6e07..46fa24de96 100644 --- a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala @@ -3,6 +3,7 @@ package sigmastate.utxo import org.ergoplatform.ErgoBox.{AdditionalRegisters, R6, R8} import org.ergoplatform._ import sigma.Extensions.ArrayOps +import sigma.VersionContext import sigma.ast.SCollection.SByteArray import sigma.ast.SType.AnyOps import sigma.data.{AvlTreeData, CAnyValue, CSigmaDslBuilder} @@ -157,6 +158,23 @@ class BasicOpsSpecification extends CompilerTestingCommons ) } + property("Global.fromBigEndianBytes") { + def fromTest() = test("R1", env, ext, + s"""{ + | val l = -1000L + | val ba = longToByteArray(l) + | Global.fromBigEndianBytes[Long](ba) == l + |} + |""".stripMargin, + null + ) + if(VersionContext.current.isV6SoftForkActivated) { + fromTest() + } else { + an[Exception] should be thrownBy(fromTest()) + } + } + property("Relation operations") { test("R1", env, ext, "{ allOf(Coll(getVar[Boolean](trueVar).get, true, true)) }", From 8bcc1efbbfe34cc034720395dc3699235804e9e7 Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Tue, 18 Jun 2024 22:57:07 +0300 Subject: [PATCH 164/314] impl and tests done without costing etc --- .../src/main/scala/sigma/ast/methods.scala | 2 +- .../scala/sigma/data/CSigmaDslBuilder.scala | 32 ++++++-- .../sigma/compiler/ir/GraphBuilding.scala | 6 +- .../sigma/compiler/ir/TreeBuilding.scala | 19 ++++- .../ir/wrappers/sigma/SigmaDslUnit.scala | 1 + .../ir/wrappers/sigma/impl/SigmaDslImpl.scala | 14 ++++ .../utxo/BasicOpsSpecification.scala | 75 ++++++++++++++++++- 7 files changed, 136 insertions(+), 13 deletions(-) diff --git a/data/shared/src/main/scala/sigma/ast/methods.scala b/data/shared/src/main/scala/sigma/ast/methods.scala index 4d5ccb4e02..c1a59fea2c 100644 --- a/data/shared/src/main/scala/sigma/ast/methods.scala +++ b/data/shared/src/main/scala/sigma/ast/methods.scala @@ -1521,7 +1521,7 @@ case object SGlobalMethods extends MonoTypeMethods { } lazy val fromBigEndianBytesMethod = SMethod( - this, "fromBigEndianBytes", SFunc(Array(SGlobal, SByteArray), tT, Array(paramT)), 3, Xor.costKind) // todo: id, cossting + this, "fromBigEndianBytes", SFunc(Array(SGlobal, SByteArray), tT, Array(paramT)), 30, Xor.costKind, Seq(tT)) // todo: id, cossting .withIRInfo(MethodCallIrBuilder) .withInfo(MethodCall, "Multiply this number with \\lst{other} by module Q.", ArgInfo("other", "Number to multiply with this.")) // todo: desc diff --git a/data/shared/src/main/scala/sigma/data/CSigmaDslBuilder.scala b/data/shared/src/main/scala/sigma/data/CSigmaDslBuilder.scala index b91184ccdb..2e0b3912fc 100644 --- a/data/shared/src/main/scala/sigma/data/CSigmaDslBuilder.scala +++ b/data/shared/src/main/scala/sigma/data/CSigmaDslBuilder.scala @@ -4,11 +4,11 @@ import debox.cfor import org.ergoplatform.ErgoBox import org.ergoplatform.validation.ValidationRules import scorex.crypto.hash.{Blake2b256, Sha256} -import scorex.utils.Longs -import sigma.ast.{AtLeast, SByte, SLong, SType, SubstConstants} +import scorex.utils.{Ints, Longs, Shorts} +import sigma.ast.{AtLeast, SBigInt, SByte, SInt, SLong, SShort, SType, SubstConstants} import sigma.crypto.{CryptoConstants, EcPointType, Ecp} import sigma.eval.Extensions.EvalCollOps -import sigma.serialization.{GroupElementSerializer, SigmaSerializer} +import sigma.serialization.{CoreDataSerializer, DataSerializer, GroupElementSerializer, SerializerException, SigmaSerializer} import sigma.util.Extensions.BigIntegerOps import sigma.validation.SigmaValidationSettings import sigma.{AvlTree, BigInt, Box, Coll, CollBuilder, GroupElement, SigmaDslBuilder, SigmaProp, VersionContext} @@ -208,9 +208,31 @@ class CSigmaDslBuilder extends SigmaDslBuilder { dsl => } else { bytes.apply(0).asInstanceOf[T] } - case SLong => Longs.fromByteArray(bytes.toArray).asInstanceOf[T] + case SShort => if (bytes.length != 2) { + throw new IllegalArgumentException("To deserialize SShort with fromBigEndianBytes, exactly two bytes should be provided") + } else { + val b0 = bytes(0) + val b1 = bytes(1) + ((b0 & 0xFF) << 8 | (b1 & 0xFF)).toShort.asInstanceOf[T] + } + case SInt => if (bytes.length != 4) { + throw new IllegalArgumentException("To deserialize SInt with fromBigEndianBytes, exactly four bytes should be provided") + } else { + Ints.fromByteArray(bytes.toArray).asInstanceOf[T] + } + case SLong => if (bytes.length != 8) { + throw new IllegalArgumentException("To deserialize SLong with fromBigEndianBytes, exactly eight bytes should be provided") + } else { + Longs.fromByteArray(bytes.toArray).asInstanceOf[T] + } + case SBigInt => + if (bytes.length > SBigInt.MaxSizeInBytes) { + throw SerializerException(s"BigInt value doesn't not fit into ${SBigInt.MaxSizeInBytes} bytes in fromBigEndianBytes") + } + CBigInt(new BigInteger(bytes.toArray)).asInstanceOf[T] + // todo: UnsignedBitInt case _ => throw new IllegalArgumentException("Unsupported type provided in fromBigEndianBytes") - // todo: more types + } } } diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/GraphBuilding.scala b/sc/shared/src/main/scala/sigma/compiler/ir/GraphBuilding.scala index 7c7b80d39a..23abf72d06 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/GraphBuilding.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/GraphBuilding.scala @@ -928,7 +928,7 @@ trait GraphBuilding extends Base with DefRewriting { IR: IRContext => sigmaDslBuilder.decodePoint(bytes) // fallback rule for MethodCall, should be the last case in the list - case sigma.ast.MethodCall(obj, method, args, _) => + case sigma.ast.MethodCall(obj, method, args, typeSubst) => val objV = eval(obj) val argsV = args.map(eval) (objV, method.objType) match { @@ -1146,6 +1146,10 @@ trait GraphBuilding extends Base with DefRewriting { IR: IRContext => val c1 = asRep[Coll[Byte]](argsV(0)) val c2 = asRep[Coll[Byte]](argsV(1)) g.xor(c1, c2) + case SGlobalMethods.fromBigEndianBytesMethod.name => + val bytes = asRep[Coll[Byte]](argsV(0)) + val cT = stypeToElem(method.stype.tRange.withSubstTypes(typeSubst)) + g.fromBigEndianBytes(bytes)(cT) case _ => throwError } case _ => throwError diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/TreeBuilding.scala b/sc/shared/src/main/scala/sigma/compiler/ir/TreeBuilding.scala index 725e3b1d19..ffe8ab1460 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/TreeBuilding.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/TreeBuilding.scala @@ -1,6 +1,8 @@ package sigma.compiler.ir import org.ergoplatform._ +import sigma.Evaluation.{rtypeToSType, stypeToRType} +import sigma.ast.SType.tT import sigma.ast._ import sigma.ast.syntax.{ValueOps, _} import sigma.data.{ProveDHTuple, ProveDlog} @@ -399,13 +401,24 @@ trait TreeBuilding extends Base { IR: IRContext => mkMultiplyGroup(obj.asGroupElement, arg.asGroupElement) // Fallback MethodCall rule: should be the last in this list of cases - case Def(MethodCall(objSym, m, argSyms, _)) => + case Def(mc @ MethodCall(objSym, m, argSyms, _)) => val obj = recurse[SType](objSym) val args = argSyms.collect { case argSym: Sym => recurse[SType](argSym) } MethodsContainer.getMethod(obj.tpe, m.getName) match { case Some(method) => - val specMethod = method.specializeFor(obj.tpe, args.map(_.tpe)) - builder.mkMethodCall(obj, specMethod, args.toIndexedSeq, Map()) + + val typeSubst: STypeSubst = { + if (method.hasExplicitTypeArgs) { + val cT = rtypeToSType(mc.resultType.sourceType) + Map(tT -> cT) + } else { + Map.empty + } + } + + val specMethod = method.specializeFor(obj.tpe, args.map(_.tpe)).withConcreteTypes(typeSubst) + + builder.mkMethodCall(obj, specMethod, args.toIndexedSeq, typeSubst) case None => error(s"Cannot find method ${m.getName} in object $obj") } diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/SigmaDslUnit.scala b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/SigmaDslUnit.scala index 2a6a341686..b5b4287950 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/SigmaDslUnit.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/SigmaDslUnit.scala @@ -114,6 +114,7 @@ import scalan._ /** This method will be used in v6.0 to handle CreateAvlTree operation in GraphBuilding */ def avlTree(operationFlags: Ref[Byte], digest: Ref[Coll[Byte]], keyLength: Ref[Int], valueLengthOpt: Ref[WOption[Int]]): Ref[AvlTree]; def xor(l: Ref[Coll[Byte]], r: Ref[Coll[Byte]]): Ref[Coll[Byte]] + def fromBigEndianBytes[T](bytes: Ref[Coll[Byte]])(implicit cT: Elem[T]): Ref[T] }; trait CostModelCompanion; trait BigIntCompanion; diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/SigmaDslImpl.scala b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/SigmaDslImpl.scala index c113cb7de3..ad0450a1a7 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/SigmaDslImpl.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/SigmaDslImpl.scala @@ -1945,6 +1945,13 @@ object SigmaDslBuilder extends EntityObject("SigmaDslBuilder") { Array[AnyRef](l, r), true, false, element[Coll[Byte]])) } + + override def fromBigEndianBytes[T](bytes: Ref[Coll[Byte]])(implicit cT: Elem[T]): Ref[T] = { + asRep[T](mkMethodCall(self, + SigmaDslBuilderClass.getMethod("fromBigEndianBytes", classOf[Sym], classOf[Elem[T]]), + Array[AnyRef](bytes, cT), + true, false, cT)) + } } implicit object LiftableSigmaDslBuilder @@ -2104,6 +2111,13 @@ object SigmaDslBuilder extends EntityObject("SigmaDslBuilder") { Array[AnyRef](l, r), true, true, element[Coll[Byte]])) } + + def fromBigEndianBytes[T](bytes: Ref[Coll[Byte]])(implicit cT: Elem[T]): Ref[T] = { + asRep[T](mkMethodCall(source, + SigmaDslBuilderClass.getMethod("fromBigEndianBytes", classOf[Sym], classOf[Elem[T]]), + Array[AnyRef](bytes, cT), + true, true, cT)) + } } // entityUnref: single unref method for each type family diff --git a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala index 46fa24de96..fc8221f983 100644 --- a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala @@ -2,6 +2,8 @@ package sigmastate.utxo import org.ergoplatform.ErgoBox.{AdditionalRegisters, R6, R8} import org.ergoplatform._ +import scorex.util.encode.Base16 +import scorex.utils.Ints import sigma.Extensions.ArrayOps import sigma.VersionContext import sigma.ast.SCollection.SByteArray @@ -158,10 +160,58 @@ class BasicOpsSpecification extends CompilerTestingCommons ) } - property("Global.fromBigEndianBytes") { - def fromTest() = test("R1", env, ext, + property("Global.fromBigEndianBytes - byte") { + def fromTest() = test("fromBigEndianBytes - byte", env, ext, s"""{ - | val l = -1000L + | val ba = Coll(5.toByte) + | Global.fromBigEndianBytes[Byte](ba) == 5 + |} + |""".stripMargin, + null + ) + if(VersionContext.current.isV6SoftForkActivated) { + fromTest() + } else { + an[Exception] should be thrownBy(fromTest()) + } + } + + property("Global.fromBigEndianBytes - short") { + def fromTest() = test("fromBigEndianBytes - short", env, ext, + s"""{ + | val ba = Coll(5.toByte, 5.toByte) + | Global.fromBigEndianBytes[Short](ba) != 0 + |} + |""".stripMargin, + null + ) + if(VersionContext.current.isV6SoftForkActivated) { + fromTest() + } else { + an[Exception] should be thrownBy(fromTest()) + } + } + + property("Global.fromBigEndianBytes - int") { + def fromTest() = test("fromBigEndianBytes - int", env, ext, + s"""{ + | val ba = fromBase16("${Base16.encode(Ints.toByteArray(Int.MaxValue))}") + | Global.fromBigEndianBytes[Int](ba) == ${Int.MaxValue} + |} + |""".stripMargin, + null + ) + if(VersionContext.current.isV6SoftForkActivated) { + fromTest() + } else { + an[Exception] should be thrownBy(fromTest()) + } + } + + property("Global.fromBigEndianBytes - long") { + def fromTest() = test("fromBigEndianBytes - long", env, ext, + s"""{ + | val l = 1088800L | val ba = longToByteArray(l) | Global.fromBigEndianBytes[Long](ba) == l |} @@ -175,6 +225,25 @@ class BasicOpsSpecification extends CompilerTestingCommons } } + property("Global.fromBigEndianBytes - bigInt") { + val bi = new BigInteger("9785856985394593489356430476450674590674598659865986594859056865984690568904") + def fromTest() = test("fromBigEndianBytes - bigInt", env, ext, + s"""{ + | val ba = fromBase16("${Base16.encode(bi.toByteArray)}") + | Global.fromBigEndianBytes[BigInt](ba) == bigInt("$bi") + |} + |""".stripMargin, + null + ) + if(VersionContext.current.isV6SoftForkActivated) { + fromTest() + } else { + an[Exception] should be thrownBy(fromTest()) + } + } + + // todo: roundtrip with .toBytes + property("Relation operations") { test("R1", env, ext, "{ allOf(Coll(getVar[Boolean](trueVar).get, true, true)) }", From b7e2a38132c43054fb73ada852ecba86e45cce32 Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Wed, 19 Jun 2024 12:39:33 +0300 Subject: [PATCH 165/314] first failing test --- .../src/main/scala/sigma/ast/methods.scala | 21 ++++++++++++++++++- .../sigma/compiler/phases/SigmaTyper.scala | 5 +++++ .../utxo/BasicOpsSpecification.scala | 19 +++++++++++++++++ 3 files changed, 44 insertions(+), 1 deletion(-) diff --git a/data/shared/src/main/scala/sigma/ast/methods.scala b/data/shared/src/main/scala/sigma/ast/methods.scala index e4cf0007e0..d114bb8f5f 100644 --- a/data/shared/src/main/scala/sigma/ast/methods.scala +++ b/data/shared/src/main/scala/sigma/ast/methods.scala @@ -1418,16 +1418,35 @@ case object SContextMethods extends MonoTypeMethods { lazy val selfBoxIndexMethod = propertyCall("selfBoxIndex", SInt, 8, FixedCost(JitCost(20))) lazy val lastBlockUtxoRootHashMethod = property("LastBlockUtxoRootHash", SAvlTree, 9, LastBlockUtxoRootHash) lazy val minerPubKeyMethod = property("minerPubKey", SByteArray, 10, MinerPubkey) + lazy val getVarMethod = SMethod( this, "getVar", SFunc(ContextFuncDom, SOption(tT), Array(paramT)), 11, GetVar.costKind) .withInfo(GetVar, "Get context variable with given \\lst{varId} and type.", ArgInfo("varId", "\\lst{Byte} identifier of context variable")) - protected override def getMethods() = super.getMethods() ++ Seq( + lazy val getVarFromInputMethod = SMethod( + this, "getVarFromInput", SFunc(Array(SContext, SShort, SByte), SOption(tT), Array(paramT)), 12, GetVar.costKind, Seq(tT)) + .withInfo(GetVar, "Get context variable with given \\lst{varId} and type.", + ArgInfo("varId", "\\lst{Byte} identifier of context variable")) + + private lazy val v5Methods = super.getMethods() ++ Seq( dataInputsMethod, headersMethod, preHeaderMethod, inputsMethod, outputsMethod, heightMethod, selfMethod, selfBoxIndexMethod, lastBlockUtxoRootHashMethod, minerPubKeyMethod, getVarMethod ) + private lazy val v6Methods = super.getMethods() ++ Seq( + dataInputsMethod, headersMethod, preHeaderMethod, inputsMethod, outputsMethod, heightMethod, selfMethod, + selfBoxIndexMethod, lastBlockUtxoRootHashMethod, minerPubKeyMethod, getVarMethod, getVarFromInputMethod + ) + + protected override def getMethods(): Seq[SMethod] = { + if(VersionContext.current.isV6SoftForkActivated) { + v6Methods + } else { + v5Methods + } + } + /** Names of methods which provide blockchain context. * This value can be reused where necessary to avoid allocations. */ val BlockchainContextMethodNames: IndexedSeq[String] = Array( diff --git a/sc/shared/src/main/scala/sigma/compiler/phases/SigmaTyper.scala b/sc/shared/src/main/scala/sigma/compiler/phases/SigmaTyper.scala index ac30a6cd0a..1348dff993 100644 --- a/sc/shared/src/main/scala/sigma/compiler/phases/SigmaTyper.scala +++ b/sc/shared/src/main/scala/sigma/compiler/phases/SigmaTyper.scala @@ -221,6 +221,11 @@ class SigmaTyper(val builder: SigmaBuilder, case (Ident(GetVarFunc.name | ExecuteFromVarFunc.name, _), Seq(id: Constant[SNumericType]@unchecked)) if id.tpe.isNumType => Seq(ByteConstant(SByte.downcast(id.value.asInstanceOf[AnyVal])).withSrcCtx(id.sourceContext)) + case (Ident(SContextMethods.getVarFromInputMethod.name, _), + Seq(inputId: Constant[SNumericType]@unchecked, varId: Constant[SNumericType]@unchecked)) + if inputId.tpe.isNumType && varId.tpe.isNumType => + Seq(ShortConstant(SShort.downcast(inputId.value.asInstanceOf[AnyVal])).withSrcCtx(inputId.sourceContext), + ByteConstant(SByte.downcast(varId.value.asInstanceOf[AnyVal])).withSrcCtx(varId.sourceContext)) case _ => typedArgs } val actualTypes = adaptedTypedArgs.map(_.tpe) diff --git a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala index 79701d6e07..5ec8336deb 100644 --- a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala @@ -3,6 +3,7 @@ package sigmastate.utxo import org.ergoplatform.ErgoBox.{AdditionalRegisters, R6, R8} import org.ergoplatform._ import sigma.Extensions.ArrayOps +import sigma.VersionContext import sigma.ast.SCollection.SByteArray import sigma.ast.SType.AnyOps import sigma.data.{AvlTreeData, CAnyValue, CSigmaDslBuilder} @@ -157,6 +158,24 @@ class BasicOpsSpecification extends CompilerTestingCommons ) } + property("getVarFromInput") { + def getVarTest() = { + val customExt = Map( + 1.toByte -> IntConstant(5) + ).toSeq + test("R1", env, customExt, + "{ CONTEXT.getVarFromInput[Int](0, 1) == 5 }", + null + ) + } + + if(VersionContext.current.isV6SoftForkActivated) { + getVarTest() + } else { + an[Exception] should be thrownBy getVarTest() + } + } + property("Relation operations") { test("R1", env, ext, "{ allOf(Coll(getVar[Boolean](trueVar).get, true, true)) }", From 828ba270b0f413a0c336814aba0fcd0eebd03873 Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Thu, 27 Jun 2024 18:13:27 +0300 Subject: [PATCH 166/314] passing test from getVar from another input --- .../src/main/scala/sigma/SigmaDsl.scala | 2 ++ .../sigma/reflection/ReflectionData.scala | 3 +++ .../src/main/scala/sigma/ast/methods.scala | 14 +++++++++++-- .../src/main/scala/sigma/ast/values.scala | 2 +- .../sigma/interpreter/ContextExtension.scala | 5 ++++- .../org/ergoplatform/ErgoLikeContext.scala | 2 +- .../main/scala/sigmastate/eval/CContext.scala | 12 +++++++++++ .../special/sigma/ContractsTestkit.scala | 2 +- .../sigma/compiler/ir/GraphBuilding.scala | 8 +++++++- .../scala/sigma/compiler/ir/IRContext.scala | 2 +- .../scala/sigma/compiler/ir/MethodCalls.scala | 7 ++++--- .../sigma/compiler/ir/TreeBuilding.scala | 7 ++++--- .../ir/wrappers/sigma/SigmaDslUnit.scala | 1 + .../ir/wrappers/sigma/impl/SigmaDslImpl.scala | 20 ++++++++++++++++++- .../sigma/compiler/phases/SigmaTyper.scala | 18 +++++++++++++---- .../scala/sigma/SigmaDslSpecification.scala | 1 + .../utxo/BasicOpsSpecification.scala | 13 ++++++++---- 17 files changed, 96 insertions(+), 23 deletions(-) diff --git a/core/shared/src/main/scala/sigma/SigmaDsl.scala b/core/shared/src/main/scala/sigma/SigmaDsl.scala index df2b419273..ab06306635 100644 --- a/core/shared/src/main/scala/sigma/SigmaDsl.scala +++ b/core/shared/src/main/scala/sigma/SigmaDsl.scala @@ -557,6 +557,8 @@ trait Context { */ def getVar[T](id: Byte)(implicit cT: RType[T]): Option[T] + def getVarFromInput[T](inputId: Short, id: Byte)(implicit cT: RType[T]): Option[T] + def vars: Coll[AnyValue] /** Maximum version of ErgoTree currently activated on the network. diff --git a/core/shared/src/main/scala/sigma/reflection/ReflectionData.scala b/core/shared/src/main/scala/sigma/reflection/ReflectionData.scala index 028e68bf72..76072a2fa4 100644 --- a/core/shared/src/main/scala/sigma/reflection/ReflectionData.scala +++ b/core/shared/src/main/scala/sigma/reflection/ReflectionData.scala @@ -273,6 +273,9 @@ object ReflectionData { mkMethod(clazz, "getVar", Array[Class[_]](classOf[Byte], classOf[RType[_]])) { (obj, args) => obj.asInstanceOf[Context].getVar(args(0).asInstanceOf[Byte])(args(1).asInstanceOf[RType[_]]) }, + mkMethod(clazz, "getVarFromInput", Array[Class[_]](classOf[Short], classOf[Byte], classOf[RType[_]])) { (obj, args) => + obj.asInstanceOf[Context].getVarFromInput(args(0).asInstanceOf[Byte], args(1).asInstanceOf[Byte])(args(2).asInstanceOf[RType[_]]) + }, mkMethod(clazz, "headers", Array[Class[_]]()) { (obj, _) => obj.asInstanceOf[Context].headers } diff --git a/data/shared/src/main/scala/sigma/ast/methods.scala b/data/shared/src/main/scala/sigma/ast/methods.scala index d114bb8f5f..9f6c323524 100644 --- a/data/shared/src/main/scala/sigma/ast/methods.scala +++ b/data/shared/src/main/scala/sigma/ast/methods.scala @@ -2,6 +2,7 @@ package sigma.ast import org.ergoplatform._ import org.ergoplatform.validation._ +import sigma.Evaluation.stypeToRType import sigma._ import sigma.ast.SCollection.{SBooleanArray, SBoxArray, SByteArray, SByteArray2, SHeaderArray} import sigma.ast.SMethod.{MethodCallIrBuilder, MethodCostFunc, javaMethodOf} @@ -1424,10 +1425,19 @@ case object SContextMethods extends MonoTypeMethods { .withInfo(GetVar, "Get context variable with given \\lst{varId} and type.", ArgInfo("varId", "\\lst{Byte} identifier of context variable")) + // todo: costing, desc lazy val getVarFromInputMethod = SMethod( this, "getVarFromInput", SFunc(Array(SContext, SShort, SByte), SOption(tT), Array(paramT)), 12, GetVar.costKind, Seq(tT)) - .withInfo(GetVar, "Get context variable with given \\lst{varId} and type.", - ArgInfo("varId", "\\lst{Byte} identifier of context variable")) + .withIRInfo(MethodCallIrBuilder) + .withInfo(MethodCall, "Multiply this number with \\lst{other} by module Q.", ArgInfo("other", "Number to multiply with this.")) + + def getVarFromInput_eval[T](mc: MethodCall, ctx: sigma.Context, inputId: Short, varId: Byte) + (implicit E: ErgoTreeEvaluator): Option[T] = { + // E.addCost(getVarFromInputMethod.costKind) + val rt = stypeToRType(mc.typeSubst.get(tT).get) + val res = ctx.getVarFromInput(inputId, varId)(rt).asInstanceOf[Option[T]] + res + } private lazy val v5Methods = super.getMethods() ++ Seq( dataInputsMethod, headersMethod, preHeaderMethod, inputsMethod, outputsMethod, heightMethod, selfMethod, diff --git a/data/shared/src/main/scala/sigma/ast/values.scala b/data/shared/src/main/scala/sigma/ast/values.scala index 87c661a00a..dace767d9f 100644 --- a/data/shared/src/main/scala/sigma/ast/values.scala +++ b/data/shared/src/main/scala/sigma/ast/values.scala @@ -1312,7 +1312,7 @@ case class MethodCall( val objV = obj.evalTo[Any](env) addCost(MethodCall.costKind) // MethodCall overhead method.costKind match { - case fixed: FixedCost => + case fixed: FixedCost if method.explicitTypeArgs.isEmpty => val extra = method.extraDescriptors val extraLen = extra.length val len = args.length diff --git a/data/shared/src/main/scala/sigma/interpreter/ContextExtension.scala b/data/shared/src/main/scala/sigma/interpreter/ContextExtension.scala index e8cdb7d709..fd269c177c 100644 --- a/data/shared/src/main/scala/sigma/interpreter/ContextExtension.scala +++ b/data/shared/src/main/scala/sigma/interpreter/ContextExtension.scala @@ -16,8 +16,11 @@ import sigma.serialization.{SigmaByteReader, SigmaByteWriter, SigmaSerializer} * @param values internal container of the key-value pairs */ case class ContextExtension(values: scala.collection.Map[Byte, EvaluatedValue[_ <: SType]]) { - def add(bindings: VarBinding*): ContextExtension = + def add(bindings: VarBinding*): ContextExtension = { ContextExtension(values ++ bindings) + } + + def get(varId: Byte): Option[EvaluatedValue[_ <: SType]] = values.get(varId) } object ContextExtension { diff --git a/interpreter/shared/src/main/scala/org/ergoplatform/ErgoLikeContext.scala b/interpreter/shared/src/main/scala/org/ergoplatform/ErgoLikeContext.scala index e421e8fdfe..4b1366d9fd 100644 --- a/interpreter/shared/src/main/scala/org/ergoplatform/ErgoLikeContext.scala +++ b/interpreter/shared/src/main/scala/org/ergoplatform/ErgoLikeContext.scala @@ -168,7 +168,7 @@ class ErgoLikeContext(val lastBlockUtxoRoot: AvlTreeData, syntax.error(s"Undefined context property: currentErgoTreeVersion")) CContext( dataInputs, headers, preHeader, inputs, outputs, preHeader.height, selfBox, selfIndex, avlTree, - preHeader.minerPk.getEncoded, vars, activatedScriptVersion, ergoTreeVersion) + preHeader.minerPk.getEncoded, vars, spendingTransaction, activatedScriptVersion, ergoTreeVersion) } diff --git a/interpreter/shared/src/main/scala/sigmastate/eval/CContext.scala b/interpreter/shared/src/main/scala/sigmastate/eval/CContext.scala index 2b076403ad..1c464fed37 100644 --- a/interpreter/shared/src/main/scala/sigmastate/eval/CContext.scala +++ b/interpreter/shared/src/main/scala/sigmastate/eval/CContext.scala @@ -1,8 +1,11 @@ package sigmastate.eval import debox.cfor +import org.ergoplatform.{ErgoLikeTransactionTemplate, UnsignedInput} +import sigma.Evaluation.{stypeToRType, toDslTuple} import sigma.Extensions.ArrayOps import sigma._ +import sigma.ast.SType import sigma.data._ import sigma.exceptions.InvalidType @@ -24,6 +27,7 @@ case class CContext( lastBlockUtxoRootHash: AvlTree, _minerPubKey: Coll[Byte], vars: Coll[AnyValue], + spendingTransaction: ErgoLikeTransactionTemplate[_ <: UnsignedInput], override val activatedScriptVersion: Byte, override val currentErgoTreeVersion: Byte ) extends Context { @@ -69,6 +73,14 @@ case class CContext( } else None } + override def getVarFromInput[T](inputId: Short, id: Byte)(implicit tT: RType[T]): Option[T] = { + spendingTransaction.inputs.unapply(inputId).flatMap(_.extension.get(id)) match { + case Some(v) if stypeToRType[SType](v.tpe) == tT => Some(v.value.asInstanceOf[T]) + case _ => + None + } + } + /** Return a new context instance with variables collection updated. * @param bindings a new binding of the context variables with new values. * @return a new instance (if `bindings` non-empty) with the specified bindings. diff --git a/interpreter/shared/src/test/scala/special/sigma/ContractsTestkit.scala b/interpreter/shared/src/test/scala/special/sigma/ContractsTestkit.scala index b04e9c150f..ba04df1347 100644 --- a/interpreter/shared/src/test/scala/special/sigma/ContractsTestkit.scala +++ b/interpreter/shared/src/test/scala/special/sigma/ContractsTestkit.scala @@ -47,7 +47,7 @@ trait ContractsTestkit { new CContext( noInputs.toColl, noHeaders, dummyPreHeader, inputs.toColl, outputs.toColl, height, self, inputs.indexOf(self), tree, - minerPk.toColl, vars.toColl, activatedScriptVersion, currErgoTreeVersion) + minerPk.toColl, vars.toColl, null, activatedScriptVersion, currErgoTreeVersion) def newContext( height: Int, diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/GraphBuilding.scala b/sc/shared/src/main/scala/sigma/compiler/ir/GraphBuilding.scala index 7c7b80d39a..3ed0e414b8 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/GraphBuilding.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/GraphBuilding.scala @@ -1,6 +1,7 @@ package sigma.compiler.ir import org.ergoplatform._ +import sigma.ast.SType.tT import sigma.ast.TypeCodes.LastConstantCode import sigma.ast.Value.Typed import sigma.ast.syntax.{SValue, ValueOps} @@ -928,7 +929,7 @@ trait GraphBuilding extends Base with DefRewriting { IR: IRContext => sigmaDslBuilder.decodePoint(bytes) // fallback rule for MethodCall, should be the last case in the list - case sigma.ast.MethodCall(obj, method, args, _) => + case sigma.ast.MethodCall(obj, method, args, typeSubst) => val objV = eval(obj) val argsV = args.map(eval) (objV, method.objType) match { @@ -1040,6 +1041,11 @@ trait GraphBuilding extends Base with DefRewriting { IR: IRContext => ctx.LastBlockUtxoRootHash case SContextMethods.minerPubKeyMethod.name => ctx.minerPubKey + case SContextMethods.getVarFromInputMethod.name => + val c1 = asRep[Short](argsV(0)) + val c2 = asRep[Byte](argsV(1)) + val c3 = stypeToElem(typeSubst.apply(tT)) + ctx.getVarFromInput(c1, c2)(c3) case _ => throwError } case (tree: Ref[AvlTree]@unchecked, SAvlTreeMethods) => method.name match { diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/IRContext.scala b/sc/shared/src/main/scala/sigma/compiler/ir/IRContext.scala index c60bc0882f..a22962f987 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/IRContext.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/IRContext.scala @@ -153,7 +153,7 @@ trait IRContext override def invokeUnlifted(e: Elem[_], mc: MethodCall, dataEnv: DataEnv): Any = e match { case _: CollElem[_,_] => mc match { case CollMethods.map(_, f) => - val newMC = mc.copy(args = mc.args :+ f.elem.eRange)(mc.resultType, mc.isAdapterCall) + val newMC = mc.copy(args = mc.args :+ f.elem.eRange)(mc.resultType, mc.isAdapterCall, mc.typeSubst) super.invokeUnlifted(e, newMC, dataEnv) case _ => super.invokeUnlifted(e, mc, dataEnv) diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/MethodCalls.scala b/sc/shared/src/main/scala/sigma/compiler/ir/MethodCalls.scala index 876f0e9d7e..48248f2165 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/MethodCalls.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/MethodCalls.scala @@ -1,6 +1,7 @@ package sigma.compiler.ir import debox.{cfor, Buffer => DBuffer} +import sigma.ast.{SType, STypeVar} import sigma.compiler.DelayInvokeException import sigma.reflection.RMethod import sigma.util.CollectionUtil.TraversableOps @@ -26,7 +27,7 @@ trait MethodCalls extends Base { self: IRContext => * given `method`. */ case class MethodCall private[MethodCalls](receiver: Sym, method: RMethod, args: Seq[AnyRef], neverInvoke: Boolean) - (val resultType: Elem[Any], val isAdapterCall: Boolean = false) extends Def[Any] { + (val resultType: Elem[Any], val isAdapterCall: Boolean = false, val typeSubst: Map[STypeVar, SType] = Map()) extends Def[Any] { override def mirror(t: Transformer): Ref[Any] = { val len = args.length @@ -100,8 +101,8 @@ trait MethodCalls extends Base { self: IRContext => /** Creates new MethodCall node and returns its node ref. */ def mkMethodCall(receiver: Sym, method: RMethod, args: Seq[AnyRef], - neverInvoke: Boolean, isAdapterCall: Boolean, resultElem: Elem[_]): Sym = { - reifyObject(MethodCall(receiver, method, args, neverInvoke)(asElem[Any](resultElem), isAdapterCall)) + neverInvoke: Boolean, isAdapterCall: Boolean, resultElem: Elem[_], typeSubst: Map[STypeVar, SType] = Map.empty): Sym = { + reifyObject(MethodCall(receiver, method, args, neverInvoke)(asElem[Any](resultElem), isAdapterCall, typeSubst)) } @tailrec diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/TreeBuilding.scala b/sc/shared/src/main/scala/sigma/compiler/ir/TreeBuilding.scala index 725e3b1d19..6826321ccd 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/TreeBuilding.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/TreeBuilding.scala @@ -399,13 +399,14 @@ trait TreeBuilding extends Base { IR: IRContext => mkMultiplyGroup(obj.asGroupElement, arg.asGroupElement) // Fallback MethodCall rule: should be the last in this list of cases - case Def(MethodCall(objSym, m, argSyms, _)) => + case Def(mc @ MethodCall(objSym, m, argSyms, _)) => val obj = recurse[SType](objSym) val args = argSyms.collect { case argSym: Sym => recurse[SType](argSym) } MethodsContainer.getMethod(obj.tpe, m.getName) match { case Some(method) => - val specMethod = method.specializeFor(obj.tpe, args.map(_.tpe)) - builder.mkMethodCall(obj, specMethod, args.toIndexedSeq, Map()) + val typeSubst = mc.typeSubst + val specMethod = method.specializeFor(obj.tpe, args.map(_.tpe)).withConcreteTypes(typeSubst) + builder.mkMethodCall(obj, specMethod, args.toIndexedSeq, typeSubst) case None => error(s"Cannot find method ${m.getName} in object $obj") } diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/SigmaDslUnit.scala b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/SigmaDslUnit.scala index 2a6a341686..91013f9071 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/SigmaDslUnit.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/SigmaDslUnit.scala @@ -91,6 +91,7 @@ import scalan._ def preHeader: Ref[PreHeader]; def minerPubKey: Ref[Coll[Byte]]; def getVar[T](id: Ref[Byte])(implicit cT: Elem[T]): Ref[WOption[T]]; + def getVarFromInput[T](inputId: Ref[Short], id: Ref[Byte])(implicit cT: Elem[T]): Ref[WOption[T]]; }; trait SigmaDslBuilder extends Def[SigmaDslBuilder] { def Colls: Ref[CollBuilder]; diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/SigmaDslImpl.scala b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/SigmaDslImpl.scala index c113cb7de3..d5bd87d306 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/SigmaDslImpl.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/SigmaDslImpl.scala @@ -8,6 +8,8 @@ import sigma.compiler.ir.wrappers.sigma.impl.SigmaDslDefs import scala.collection.compat.immutable.ArraySeq package impl { + import sigma.Evaluation + import sigma.ast.SType.tT import sigma.compiler.ir.meta.ModuleInfo import sigma.compiler.ir.wrappers.sigma.SigmaDsl import sigma.compiler.ir.{Base, GraphIRReflection, IRContext} @@ -1614,6 +1616,14 @@ object Context extends EntityObject("Context") { true, false, element[WOption[T]])) } + override def getVarFromInput[T](inputId: Ref[Short], varId: Ref[Byte])(implicit cT: Elem[T]): Ref[WOption[T]] = { + val st = Evaluation.rtypeToSType(cT.sourceType) + asRep[WOption[T]](mkMethodCall(self, + ContextClass.getMethod("getVarFromInput", classOf[Sym], classOf[Sym], classOf[Elem[_]]), + Array[AnyRef](inputId, varId, cT), + true, false, element[WOption[T]], Map(tT -> st))) + } + } implicit object LiftableContext @@ -1710,6 +1720,14 @@ object Context extends EntityObject("Context") { Array[AnyRef](id, cT), true, true, element[WOption[T]])) } + + def getVarFromInput[T](inputId: Ref[Short], varId: Ref[Byte])(implicit cT: Elem[T]): Ref[WOption[T]] = { + val st = Evaluation.rtypeToSType(cT.sourceType) + asRep[WOption[T]](mkMethodCall(source, + ContextClass.getMethod("getVarFromInput", classOf[Sym], classOf[Sym], classOf[Elem[_]]), + Array[AnyRef](inputId, varId, cT), + true, true, element[WOption[T]], Map(tT -> st))) + } } // entityUnref: single unref method for each type family @@ -1727,7 +1745,7 @@ object Context extends EntityObject("Context") { override protected def collectMethods: Map[RMethod, MethodDesc] = { super.collectMethods ++ Elem.declaredMethods(RClass(classOf[Context]), RClass(classOf[SContext]), Set( - "OUTPUTS", "INPUTS", "dataInputs", "HEIGHT", "SELF", "selfBoxIndex", "LastBlockUtxoRootHash", "headers", "preHeader", "minerPubKey", "getVar", "vars" + "OUTPUTS", "INPUTS", "dataInputs", "HEIGHT", "SELF", "selfBoxIndex", "LastBlockUtxoRootHash", "headers", "preHeader", "minerPubKey", "getVar", "getVarFromInput", "vars" )) } } diff --git a/sc/shared/src/main/scala/sigma/compiler/phases/SigmaTyper.scala b/sc/shared/src/main/scala/sigma/compiler/phases/SigmaTyper.scala index 1348dff993..0d53802239 100644 --- a/sc/shared/src/main/scala/sigma/compiler/phases/SigmaTyper.scala +++ b/sc/shared/src/main/scala/sigma/compiler/phases/SigmaTyper.scala @@ -134,8 +134,18 @@ class SigmaTyper(val builder: SigmaBuilder, res case Apply(ApplyTypes(sel @ Select(obj, n, _), Seq(rangeTpe)), args) => + val nArgs = if (n == SContextMethods.getVarFromInputMethod.name && + args.length == 2 && + args(0).isInstanceOf[Constant[_]] && + args(1).isInstanceOf[Constant[_]] && + args(0).tpe.isNumType && + args(1).tpe.isNumType) { + IndexedSeq(ShortConstant(SShort.downcast(args(0).asInstanceOf[Constant[SNumericType]].value.asInstanceOf[AnyVal])).withSrcCtx(args(0).sourceContext), + ByteConstant(SByte.downcast(args(1).asInstanceOf[Constant[SNumericType]].value.asInstanceOf[AnyVal])).withSrcCtx(args(1).sourceContext)) + } else args + val newObj = assignType(env, obj) - val newArgs = args.map(assignType(env, _)) + val newArgs = nArgs.map(assignType(env, _)) obj.tpe match { case p: SProduct => MethodsContainer.getMethod(p, n) match { @@ -222,10 +232,10 @@ class SigmaTyper(val builder: SigmaBuilder, if id.tpe.isNumType => Seq(ByteConstant(SByte.downcast(id.value.asInstanceOf[AnyVal])).withSrcCtx(id.sourceContext)) case (Ident(SContextMethods.getVarFromInputMethod.name, _), - Seq(inputId: Constant[SNumericType]@unchecked, varId: Constant[SNumericType]@unchecked)) - if inputId.tpe.isNumType && varId.tpe.isNumType => + Seq(inputId: Constant[SNumericType]@unchecked, varId: Constant[SNumericType]@unchecked)) + if inputId.tpe.isNumType && varId.tpe.isNumType => Seq(ShortConstant(SShort.downcast(inputId.value.asInstanceOf[AnyVal])).withSrcCtx(inputId.sourceContext), - ByteConstant(SByte.downcast(varId.value.asInstanceOf[AnyVal])).withSrcCtx(varId.sourceContext)) + ByteConstant(SByte.downcast(varId.value.asInstanceOf[AnyVal])).withSrcCtx(varId.sourceContext)) case _ => typedArgs } val actualTypes = adaptedTypedArgs.map(_.tpe) diff --git a/sc/shared/src/test/scala/sigma/SigmaDslSpecification.scala b/sc/shared/src/test/scala/sigma/SigmaDslSpecification.scala index c820e65e73..b7ce178d6c 100644 --- a/sc/shared/src/test/scala/sigma/SigmaDslSpecification.scala +++ b/sc/shared/src/test/scala/sigma/SigmaDslSpecification.scala @@ -4762,6 +4762,7 @@ class SigmaDslSpecification extends SigmaDslTesting .append(Coll[AnyValue]( CAnyValue(Helpers.decodeBytes("00")), CAnyValue(true))), + spendingTransaction = null, activatedScriptVersion = activatedVersionInTests, currentErgoTreeVersion = ergoTreeVersionInTests ) diff --git a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala index 5ec8336deb..83d405a1a1 100644 --- a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala @@ -2,6 +2,7 @@ package sigmastate.utxo import org.ergoplatform.ErgoBox.{AdditionalRegisters, R6, R8} import org.ergoplatform._ +import org.scalatest.Assertion import sigma.Extensions.ArrayOps import sigma.VersionContext import sigma.ast.SCollection.SByteArray @@ -20,9 +21,11 @@ import sigmastate.interpreter.Interpreter._ import sigma.ast.Apply import sigma.eval.EvalSettings import sigma.exceptions.InvalidType +import sigma.interpreter.{ContextExtension, ProverResult} import sigmastate.utils.Helpers._ import java.math.BigInteger +import scala.collection.compat.immutable.ArraySeq class BasicOpsSpecification extends CompilerTestingCommons with CompilerCrossVersionProps { @@ -102,7 +105,8 @@ class BasicOpsSpecification extends CompilerTestingCommons val newBox1 = testBox(10, tree, creationHeight = 0, boxIndex = 0, additionalRegisters = Map( reg1 -> IntConstant(1), reg2 -> IntConstant(10))) - val tx = createTransaction(newBox1) + val ce = ContextExtension(prover.contextExtenders) + val tx = new ErgoLikeTransaction(IndexedSeq(Input(boxToSpend.id, ProverResult(Array.empty, ce))), ArraySeq.empty, IndexedSeq(newBox1)) val ctx = ErgoLikeContextTesting(currentHeight = 0, lastBlockUtxoRoot = AvlTreeData.dummy, ErgoLikeContextTesting.dummyPubkey, boxesToSpend = IndexedSeq(boxToSpend), @@ -159,17 +163,17 @@ class BasicOpsSpecification extends CompilerTestingCommons } property("getVarFromInput") { - def getVarTest() = { + def getVarTest(): Assertion = { val customExt = Map( 1.toByte -> IntConstant(5) ).toSeq test("R1", env, customExt, - "{ CONTEXT.getVarFromInput[Int](0, 1) == 5 }", + "{ sigmaProp(CONTEXT.getVarFromInput[Int](0, 1).get == 5) }", null ) } - if(VersionContext.current.isV6SoftForkActivated) { + if (VersionContext.current.isV6SoftForkActivated) { getVarTest() } else { an[Exception] should be thrownBy getVarTest() @@ -740,4 +744,5 @@ class BasicOpsSpecification extends CompilerTestingCommons true ) } + } From b80ef294039826cd43a5ccef7e9ae946f6f448dc Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Fri, 28 Jun 2024 14:07:08 +0300 Subject: [PATCH 167/314] invalid tests --- .../utxo/BasicOpsSpecification.scala | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala index 83d405a1a1..74a51e63d0 100644 --- a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala @@ -180,6 +180,42 @@ class BasicOpsSpecification extends CompilerTestingCommons } } + property("getVarFromInput - invalid input") { + def getVarTest(): Assertion = { + val customExt = Map( + 1.toByte -> IntConstant(5) + ).toSeq + test("R1", env, customExt, + "{ sigmaProp(CONTEXT.getVarFromInput[Int](1, 1).get == 5) }", + null + ) + } + + if (VersionContext.current.isV6SoftForkActivated) { + an[Exception] should be thrownBy getVarTest() + } else { + an[Exception] should be thrownBy getVarTest() + } + } + + property("getVarFromInput - invalid var") { + def getVarTest(): Assertion = { + val customExt = Map( + 1.toByte -> IntConstant(5) + ).toSeq + test("R1", env, customExt, + "{ sigmaProp(CONTEXT.getVarFromInput[Int](0, 2).get == 5) }", + null + ) + } + + if (VersionContext.current.isV6SoftForkActivated) { + an[Exception] should be thrownBy getVarTest() + } else { + an[Exception] should be thrownBy getVarTest() + } + } + property("Relation operations") { test("R1", env, ext, "{ allOf(Coll(getVar[Boolean](trueVar).get, true, true)) }", From 6a3cbac7540baf0d15dcfbbb11f0c42fb9432eeb Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Sat, 29 Jun 2024 20:00:52 +0300 Subject: [PATCH 168/314] initial failing test & impl --- .../src/main/scala/sigma/ast/methods.scala | 20 +++++++++++++------ .../sigmastate/ErgoTreeSpecification.scala | 2 +- .../utxo/BasicOpsSpecification.scala | 16 +++++++++++++++ 3 files changed, 31 insertions(+), 7 deletions(-) diff --git a/data/shared/src/main/scala/sigma/ast/methods.scala b/data/shared/src/main/scala/sigma/ast/methods.scala index 9f6c323524..aecf63e588 100644 --- a/data/shared/src/main/scala/sigma/ast/methods.scala +++ b/data/shared/src/main/scala/sigma/ast/methods.scala @@ -1420,11 +1420,16 @@ case object SContextMethods extends MonoTypeMethods { lazy val lastBlockUtxoRootHashMethod = property("LastBlockUtxoRootHash", SAvlTree, 9, LastBlockUtxoRootHash) lazy val minerPubKeyMethod = property("minerPubKey", SByteArray, 10, MinerPubkey) - lazy val getVarMethod = SMethod( + lazy val getVarV5Method = SMethod( this, "getVar", SFunc(ContextFuncDom, SOption(tT), Array(paramT)), 11, GetVar.costKind) .withInfo(GetVar, "Get context variable with given \\lst{varId} and type.", ArgInfo("varId", "\\lst{Byte} identifier of context variable")) + lazy val getVarV6Method = SMethod( + this, "getVar", SFunc(ContextFuncDom, SOption(tT), Array(paramT)), 11, GetVar.costKind, Seq(tT)) + .withInfo(GetVar, "Get context variable with given \\lst{varId} and type.", + ArgInfo("varId", "\\lst{Byte} identifier of context variable")) + // todo: costing, desc lazy val getVarFromInputMethod = SMethod( this, "getVarFromInput", SFunc(Array(SContext, SShort, SByte), SOption(tT), Array(paramT)), 12, GetVar.costKind, Seq(tT)) @@ -1439,18 +1444,21 @@ case object SContextMethods extends MonoTypeMethods { res } - private lazy val v5Methods = super.getMethods() ++ Seq( + private lazy val commonMethods = Array( dataInputsMethod, headersMethod, preHeaderMethod, inputsMethod, outputsMethod, heightMethod, selfMethod, - selfBoxIndexMethod, lastBlockUtxoRootHashMethod, minerPubKeyMethod, getVarMethod + selfBoxIndexMethod, lastBlockUtxoRootHashMethod, minerPubKeyMethod + ) + + private lazy val v5Methods = super.getMethods() ++ Seq( + getVarV5Method ) private lazy val v6Methods = super.getMethods() ++ Seq( - dataInputsMethod, headersMethod, preHeaderMethod, inputsMethod, outputsMethod, heightMethod, selfMethod, - selfBoxIndexMethod, lastBlockUtxoRootHashMethod, minerPubKeyMethod, getVarMethod, getVarFromInputMethod + getVarV6Method, getVarFromInputMethod ) protected override def getMethods(): Seq[SMethod] = { - if(VersionContext.current.isV6SoftForkActivated) { + if (VersionContext.current.isV6SoftForkActivated) { v6Methods } else { v5Methods diff --git a/sc/shared/src/test/scala/sigmastate/ErgoTreeSpecification.scala b/sc/shared/src/test/scala/sigmastate/ErgoTreeSpecification.scala index 7539bd5e48..c39a5269bc 100644 --- a/sc/shared/src/test/scala/sigmastate/ErgoTreeSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/ErgoTreeSpecification.scala @@ -413,7 +413,7 @@ class ErgoTreeSpecification extends SigmaDslTesting with ContractsTestkit { 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), MInfo(11, getVarMethod) + MInfo(10, minerPubKeyMethod), MInfo(11, getVarV5Method) ), true) }, { import SGlobalMethods._ diff --git a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala index 74a51e63d0..5a89ebe360 100644 --- a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala @@ -454,6 +454,22 @@ class BasicOpsSpecification extends CompilerTestingCommons ) } + property("Context.getVar") { + def varTest() = { + test("GetVar1", env, ext, + "{ CONTEXT.getVar[Int](intVar2).get == 2 }", + null + ) + } + + if(VersionContext.current.isV6SoftForkActivated) { + varTest() + } else { + an[Exception] should be thrownBy(varTest()) + } + + } + property("GetVar") { test("GetVar1", env, ext, "{ getVar[Int](intVar2).get == 2 }", From af92a3fba5c4c0079f770809fdf1c565cfa03d70 Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Sat, 29 Jun 2024 22:55:31 +0300 Subject: [PATCH 169/314] test passing --- data/shared/src/main/scala/sigma/ast/methods.scala | 12 ++++++------ .../main/scala/sigma/compiler/ir/GraphBuilding.scala | 4 ++++ .../sigmastate/utxo/BasicOpsSpecification.scala | 1 - 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/data/shared/src/main/scala/sigma/ast/methods.scala b/data/shared/src/main/scala/sigma/ast/methods.scala index aecf63e588..8d8e4e9056 100644 --- a/data/shared/src/main/scala/sigma/ast/methods.scala +++ b/data/shared/src/main/scala/sigma/ast/methods.scala @@ -1427,8 +1427,8 @@ case object SContextMethods extends MonoTypeMethods { lazy val getVarV6Method = SMethod( this, "getVar", SFunc(ContextFuncDom, SOption(tT), Array(paramT)), 11, GetVar.costKind, Seq(tT)) - .withInfo(GetVar, "Get context variable with given \\lst{varId} and type.", - ArgInfo("varId", "\\lst{Byte} identifier of context variable")) + .withIRInfo(MethodCallIrBuilder) + .withInfo(MethodCall, "") // todo: desc // todo: costing, desc lazy val getVarFromInputMethod = SMethod( @@ -1449,19 +1449,19 @@ case object SContextMethods extends MonoTypeMethods { selfBoxIndexMethod, lastBlockUtxoRootHashMethod, minerPubKeyMethod ) - private lazy val v5Methods = super.getMethods() ++ Seq( + private lazy val v5Methods = commonMethods ++ Seq( getVarV5Method ) - private lazy val v6Methods = super.getMethods() ++ Seq( + private lazy val v6Methods = commonMethods ++ Seq( getVarV6Method, getVarFromInputMethod ) protected override def getMethods(): Seq[SMethod] = { if (VersionContext.current.isV6SoftForkActivated) { - v6Methods + super.getMethods() ++ v6Methods } else { - v5Methods + super.getMethods() ++ v5Methods } } 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 3ed0e414b8..82cfcb4469 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/GraphBuilding.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/GraphBuilding.scala @@ -1041,6 +1041,10 @@ trait GraphBuilding extends Base with DefRewriting { IR: IRContext => ctx.LastBlockUtxoRootHash case SContextMethods.minerPubKeyMethod.name => ctx.minerPubKey + case SContextMethods.getVarV6Method.name => + val c2 = asRep[Byte](argsV(0)) + val c3 = stypeToElem(typeSubst.apply(tT)) + ctx.getVar(c2)(c3) case SContextMethods.getVarFromInputMethod.name => val c1 = asRep[Short](argsV(0)) val c2 = asRep[Byte](argsV(1)) diff --git a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala index 5a89ebe360..5b6f71ecfc 100644 --- a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala @@ -467,7 +467,6 @@ class BasicOpsSpecification extends CompilerTestingCommons } else { an[Exception] should be thrownBy(varTest()) } - } property("GetVar") { From a731962932c40d2e240e4d282ca78c5092e96743 Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Fri, 5 Jul 2024 22:44:32 +0300 Subject: [PATCH 170/314] simplifying the code --- .../src/main/scala/sigma/VersionContext.scala | 13 ---- .../src/main/scala/sigma/ast/SType.scala | 28 ++++---- .../src/main/scala/sigma/util/Versioned.scala | 27 ------- .../src/main/scala/sigma/ast/methods.scala | 44 +++++++----- .../scala/sigma/data/CSigmaDslBuilder.scala | 6 +- .../scala/sigma/LanguageSpecificationV5.scala | 20 ++++-- .../scala/sigma/LanguageSpecificationV6.scala | 71 ++++++++++--------- .../test/scala/sigma/SigmaDslTesting.scala | 6 +- 8 files changed, 98 insertions(+), 117 deletions(-) delete mode 100644 core/shared/src/main/scala/sigma/util/Versioned.scala diff --git a/core/shared/src/main/scala/sigma/VersionContext.scala b/core/shared/src/main/scala/sigma/VersionContext.scala index ecdcfb5f62..19a4857086 100644 --- a/core/shared/src/main/scala/sigma/VersionContext.scala +++ b/core/shared/src/main/scala/sigma/VersionContext.scala @@ -25,12 +25,6 @@ case class VersionContext(activatedVersion: Byte, ergoTreeVersion: Byte) { /** @return true, if the activated script version of Ergo protocol on the network is * including Evolution update. */ def isV6SoftForkActivated: Boolean = activatedVersion >= V6SoftForkVersion - - /** @return true if another [[VersionContext]] is greater than this. */ - def <= (that: VersionContext): Boolean = { - this.activatedVersion < that.activatedVersion || - (this.activatedVersion == that.activatedVersion && this.ergoTreeVersion <= that.ergoTreeVersion) - } } object VersionContext { @@ -110,11 +104,4 @@ object VersionContext { } } - /** Returns the VersionContext with V5 activation and the given ErgoTree version. */ - def sinceV5AndTreeVersion(treeVersion: Byte): VersionContext = - VersionContext(JitActivationVersion, ergoTreeVersion = treeVersion) - - /** Returns the VersionContext with V6 activation and the given ErgoTree version. */ - def sinceV6AndTreeVersion(treeVersion: Byte): VersionContext = - VersionContext(V6SoftForkVersion, ergoTreeVersion = treeVersion) } diff --git a/core/shared/src/main/scala/sigma/ast/SType.scala b/core/shared/src/main/scala/sigma/ast/SType.scala index 4c0e797066..aa4ad0bccf 100644 --- a/core/shared/src/main/scala/sigma/ast/SType.scala +++ b/core/shared/src/main/scala/sigma/ast/SType.scala @@ -7,7 +7,6 @@ import sigma.data.OverloadHack.Overloaded1 import sigma.data.{CBigInt, Nullable, SigmaConstants} import sigma.reflection.{RClass, RMethod, ReflectionData} import sigma.util.Extensions.{IntOps, LongOps, ShortOps} -import sigma.util.Versioned import sigma.{AvlTree, BigInt, Box, Coll, Context, Evaluation, GroupElement, Header, PreHeader, SigmaDslBuilder, SigmaProp, VersionContext} import java.math.BigInteger @@ -141,18 +140,21 @@ object SType { * * The regression tests in `property("MethodCall Codes")` should pass. */ - private val _types: Versioned[Map[Byte, STypeCompanion]] = Versioned({ version => - val v5x = Seq( - SBoolean, SString, STuple, SGroupElement, SSigmaProp, SContext, SGlobal, SHeader, SPreHeader, - SAvlTree, SBox, SOption, SCollection, SBigInt - ) - val v6 = if (version >= VersionContext.V6SoftForkVersion) - Seq(SByte, SShort, SInt, SLong) - else - Seq.empty - (v5x ++ v6).map { t => (t.typeId, t) }.toMap - }) - def types: Map[Byte, STypeCompanion] = _types.get(VersionContext.current.activatedVersion) + private val v5Types = Seq( + SBoolean, SString, STuple, SGroupElement, SSigmaProp, SContext, SGlobal, SHeader, SPreHeader, + SAvlTree, SBox, SOption, SCollection, SBigInt + ) + private val v6Types = v5Types ++ Seq(SByte, SShort, SInt, SLong) + + private val v5TypesMap = v5Types.map { t => (t.typeId, t) }.toMap + + private val v6TypesMap = v6Types.map { t => (t.typeId, t) }.toMap + + def types: Map[Byte, STypeCompanion] = if (VersionContext.current.isV6SoftForkActivated) { + v6TypesMap + } else { + v5TypesMap + } /** Checks that the type of the value corresponds to the descriptor `tpe`. * If the value has complex structure only root type constructor is checked. diff --git a/core/shared/src/main/scala/sigma/util/Versioned.scala b/core/shared/src/main/scala/sigma/util/Versioned.scala deleted file mode 100644 index a3eae2325a..0000000000 --- a/core/shared/src/main/scala/sigma/util/Versioned.scala +++ /dev/null @@ -1,27 +0,0 @@ -package sigma.util - -import sigma.VersionContext - -import scala.reflect.ClassTag - -/** Represents a versioned object that can be created for each supported version. - * The object is created lazily and cached for each version. - * - * @param builder a total function that creates an object for a given version in [0, - * maxVersion] range. - * @param maxVersion the maximum supported version. - */ -case class Versioned[T <: AnyRef: ClassTag](builder: Byte => T, maxVersion: Byte = VersionContext.MaxSupportedScriptVersion) { - private val cache = new Array[T](maxVersion + 1) - - def get(version: Byte): T = { - require(version <= VersionContext.MaxSupportedScriptVersion, s"Not supported version $version") - if (cache(version) == null) { - val v = builder(version) - cache(version) = v - v - } else { - cache(version) - } - } -} diff --git a/data/shared/src/main/scala/sigma/ast/methods.scala b/data/shared/src/main/scala/sigma/ast/methods.scala index 136225f256..27112f7ac2 100644 --- a/data/shared/src/main/scala/sigma/ast/methods.scala +++ b/data/shared/src/main/scala/sigma/ast/methods.scala @@ -5,7 +5,7 @@ import org.ergoplatform.validation._ import sigma._ import sigma.ast.SCollection.{SBooleanArray, SBoxArray, SByteArray, SByteArray2, SHeaderArray} import sigma.ast.SMethod.{MethodCallIrBuilder, MethodCostFunc, javaMethodOf} -import sigma.ast.SType.{TypeCode, paramT, tT} +import sigma.ast.SType.TypeCode import sigma.ast.syntax.{SValue, ValueOps} import sigma.data.ExactIntegral.{ByteIsExactIntegral, IntIsExactIntegral, LongIsExactIntegral, ShortIsExactIntegral} import sigma.data.OverloadHack.Overloaded1 @@ -13,7 +13,6 @@ import sigma.data.{DataValueComparer, KeyValueColl, Nullable, RType, SigmaConsta import sigma.eval.{CostDetails, ErgoTreeEvaluator, TracedCost} import sigma.reflection.RClass import sigma.serialization.CoreByteWriter.ArgInfo -import sigma.util.Versioned import sigma.utils.SparseArrayContainer import scala.annotation.unused @@ -158,23 +157,30 @@ trait MonoTypeMethods extends MethodsContainer { trait SNumericTypeMethods extends MonoTypeMethods { import SNumericTypeMethods.tNum - private val _getMethods = Versioned({ version => - val subst = Map(tNum -> this.ownerType) - val numericMethods = if (version < VersionContext.V6SoftForkVersion) - SNumericTypeMethods.methods.map { m => - m.copy(stype = applySubst(m.stype, subst).asFunc ) - } - else - SNumericTypeMethods.methods.map { m => - m.copy( - objType = this, // associate the method with the concrete numeric type - stype = applySubst(m.stype, subst).asFunc - )} - super.getMethods() ++ numericMethods - }) - - protected override def getMethods(): Seq[SMethod] = - _getMethods.get(VersionContext.current.activatedVersion) + + private val subst = Map(tNum -> this.ownerType) + + private val v5Methods = { + SNumericTypeMethods.methods.map { m => + m.copy(stype = applySubst(m.stype, subst).asFunc) + } + } + + private val v6Methods = { + SNumericTypeMethods.methods.map { m => + m.copy( + objType = this, // associate the method with the concrete numeric type + stype = applySubst(m.stype, subst).asFunc + )} + } + + protected override def getMethods(): Seq[SMethod] = { + if (VersionContext.current.isV6SoftForkActivated) { + super.getMethods() ++ v6Methods + } else { + super.getMethods() ++ v5Methods + } + } } object SNumericTypeMethods extends MethodsContainer { diff --git a/data/shared/src/main/scala/sigma/data/CSigmaDslBuilder.scala b/data/shared/src/main/scala/sigma/data/CSigmaDslBuilder.scala index d7b092fc0e..3938feacd3 100644 --- a/data/shared/src/main/scala/sigma/data/CSigmaDslBuilder.scala +++ b/data/shared/src/main/scala/sigma/data/CSigmaDslBuilder.scala @@ -5,13 +5,13 @@ import org.ergoplatform.ErgoBox import org.ergoplatform.validation.ValidationRules import scorex.crypto.hash.{Blake2b256, Sha256} import scorex.utils.Longs -import sigma.ast.{AtLeast, SType, SubstConstants} +import sigma.ast.{AtLeast, SubstConstants} import sigma.crypto.{CryptoConstants, EcPointType, Ecp} import sigma.eval.Extensions.EvalCollOps -import sigma.serialization.{DataSerializer, GroupElementSerializer, SigmaSerializer} +import sigma.serialization.{GroupElementSerializer, SigmaSerializer} import sigma.util.Extensions.BigIntegerOps import sigma.validation.SigmaValidationSettings -import sigma.{AvlTree, BigInt, Box, Coll, CollBuilder, Evaluation, GroupElement, SigmaDslBuilder, SigmaProp, VersionContext} +import sigma.{AvlTree, BigInt, Box, Coll, CollBuilder, GroupElement, SigmaDslBuilder, SigmaProp, VersionContext} import java.math.BigInteger diff --git a/sc/shared/src/test/scala/sigma/LanguageSpecificationV5.scala b/sc/shared/src/test/scala/sigma/LanguageSpecificationV5.scala index 48f1a3f7ca..592971ac82 100644 --- a/sc/shared/src/test/scala/sigma/LanguageSpecificationV5.scala +++ b/sc/shared/src/test/scala/sigma/LanguageSpecificationV5.scala @@ -10,6 +10,7 @@ import scorex.crypto.authds.{ADKey, ADValue} import scorex.crypto.hash.{Blake2b256, Digest32} import scorex.util.ModifierId import sigma.Extensions.{ArrayOps, CollOps} +import sigma.VersionContext.JitActivationVersion import sigma.ast.ErgoTree.{HeaderType, ZeroHeader} import sigma.ast.SCollection._ import sigma.ast.syntax._ @@ -47,6 +48,11 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => import TestData._ + /** Returns the VersionContext with V5 activation and the given ErgoTree version. */ + def sinceV5AndTreeVersion(treeVersion: Byte): VersionContext = + VersionContext(JitActivationVersion, ergoTreeVersion = treeVersion) + + def upcastCostDetails(tpe: SType) = TracedCost(traceBase :+ TypeBasedCostItem(Upcast, tpe)) def downcastCostDetails(tpe: SType) = TracedCost(traceBase :+ TypeBasedCostItem(Downcast, tpe)) def arithOpsCostDetails(tpe: SType) = CostDetails( @@ -4802,7 +4808,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => })) ), changedFeature( - changedInVersion = VersionContext.sinceV5AndTreeVersion(0), + changedInVersion = sinceV5AndTreeVersion(0), { (x: Context) => x.selfBoxIndex }, { (x: Context) => x.selfBoxIndex }, // see versioning in selfBoxIndex implementation "{ (x: Context) => x.selfBoxIndex }", @@ -5004,7 +5010,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => ) ), changedFeature( - changedInVersion = VersionContext.sinceV5AndTreeVersion(0), + changedInVersion = sinceV5AndTreeVersion(0), scalaFunc = { (x: Context) => // this error is expected in v3.x, v4.x throw expectedError @@ -5978,7 +5984,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => ) }, changedFeature( - changedInVersion = VersionContext.sinceV5AndTreeVersion(0), + changedInVersion = sinceV5AndTreeVersion(0), (x: Coll[Boolean]) => SigmaDsl.xorOf(x), (x: Coll[Boolean]) => SigmaDsl.xorOf(x), "{ (x: Coll[Boolean]) => xorOf(x) }", @@ -6241,7 +6247,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => ) }, changedFeature( - changedInVersion = VersionContext.sinceV5AndTreeVersion(0), + changedInVersion = sinceV5AndTreeVersion(0), (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) }", @@ -8811,7 +8817,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => (Some(Long.MaxValue) -> Expected(new ArithmeticException("long overflow"))) ), changedFeature( - changedInVersion = VersionContext.sinceV5AndTreeVersion(0), + changedInVersion = sinceV5AndTreeVersion(0), scalaFunc = { (x: Option[Long]) => def f(opt: Long): Long = n.plus(opt, 1) if (x.isDefined) f(x.get) @@ -9367,7 +9373,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => ) }, changedFeature( - changedInVersion = VersionContext.sinceV5AndTreeVersion(0), + changedInVersion = sinceV5AndTreeVersion(0), { (x: (Coll[Byte], Int)) => SigmaDsl.substConstants(x._1, Coll[Int](x._2), Coll[Any](SigmaDsl.sigmaProp(false))(sigma.AnyType)) }, @@ -9430,7 +9436,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => ) ), changedFeature( - changedInVersion = VersionContext.sinceV5AndTreeVersion(0), + changedInVersion = sinceV5AndTreeVersion(0), { (x: Context) => throw error true diff --git a/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala b/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala index 6eb3dc4c11..3848e3268f 100644 --- a/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala +++ b/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala @@ -1,6 +1,7 @@ package sigma import org.ergoplatform.sdk.utils.ErgoTreeUtils +import sigma.VersionContext.V6SoftForkVersion import sigma.ast.ErgoTree.ZeroHeader import sigma.ast.SCollection.SByteArray import sigma.ast.syntax.TrueSigmaProp @@ -24,6 +25,10 @@ import scala.util.Success class LanguageSpecificationV6 extends LanguageSpecificationBase { suite => override def languageVersion: Byte = VersionContext.V6SoftForkVersion + /** Returns the VersionContext with V6 activation and the given ErgoTree version. */ + def sinceV6AndTreeVersion(treeVersion: Byte): VersionContext = + VersionContext(V6SoftForkVersion, ergoTreeVersion = treeVersion) + def expectedSuccessForAllTreeVersions[A](value: A, cost: Int, costDetails: CostDetails) = { val res = ExpectedResult(Success(value), Some(cost)) -> Some(costDetails) Seq(0, 1, 2, 3).map(version => version -> res) @@ -31,7 +36,7 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite => property("Boolean.toByte") { val toByte = newFeature((x: Boolean) => x.toByte, "{ (x: Boolean) => x.toByte }", - sinceVersion = VersionContext.sinceV6AndTreeVersion(0) + sinceVersion = sinceV6AndTreeVersion(0) ) val cases = Seq( @@ -57,22 +62,22 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite => // which is checked below lazy val toAbs = newFeature((x: Byte) => x.toAbs, "{ (x: Byte) => x.toAbs }", - sinceVersion = VersionContext.sinceV6AndTreeVersion(0)) + sinceVersion = sinceV6AndTreeVersion(0)) lazy val compareTo = newFeature( (x: (Byte, Byte)) => x._1.compareTo(x._2), "{ (x: (Byte, Byte)) => x._1.compareTo(x._2) }", - sinceVersion = VersionContext.sinceV6AndTreeVersion(0)) + sinceVersion = sinceV6AndTreeVersion(0)) lazy val bitOr = newFeature( { (x: (Byte, Byte)) => (x._1 | x._2).toByteExact }, "{ (x: (Byte, Byte)) => (x._1 | x._2) }", - sinceVersion = VersionContext.sinceV6AndTreeVersion(0)) + sinceVersion = sinceV6AndTreeVersion(0)) lazy val bitAnd = newFeature( { (x: (Byte, Byte)) => (x._1 & x._2).toByteExact }, "{ (x: (Byte, Byte)) => (x._1 & x._2) }", - sinceVersion = VersionContext.sinceV6AndTreeVersion(0)) + sinceVersion = sinceV6AndTreeVersion(0)) forAll { x: Byte => Seq(toAbs).foreach(f => f.checkEquality(x)) @@ -91,21 +96,21 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite => // which is checked below lazy val toAbs = newFeature((x: Short) => x.toAbs, "{ (x: Short) => x.toAbs }", - sinceVersion = VersionContext.sinceV6AndTreeVersion(0)) + sinceVersion = sinceV6AndTreeVersion(0)) lazy val compareTo = newFeature((x: (Short, Short)) => x._1.compareTo(x._2), "{ (x: (Short, Short)) => x._1.compareTo(x._2) }", - sinceVersion = VersionContext.sinceV6AndTreeVersion(0)) + sinceVersion = sinceV6AndTreeVersion(0)) lazy val bitOr = newFeature( { (x: (Short, Short)) => (x._1 | x._2).toShortExact }, "{ (x: (Short, Short)) => x._1 | x._2 }", - sinceVersion = VersionContext.sinceV6AndTreeVersion(0)) + sinceVersion = sinceV6AndTreeVersion(0)) lazy val bitAnd = newFeature( { (x: (Short, Short)) => (x._1 & x._2).toShortExact }, "{ (x: (Short, Short)) => x._1 & x._2 }", - sinceVersion = VersionContext.sinceV6AndTreeVersion(0)) + sinceVersion = sinceV6AndTreeVersion(0)) forAll { x: Short => Seq(toAbs).foreach(_.checkEquality(x)) @@ -121,18 +126,18 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite => // NOTE, for such versions the new features are not supported // which is checked below lazy val toAbs = newFeature((x: Int) => x.toAbs, "{ (x: Int) => x.toAbs }", - sinceVersion = VersionContext.sinceV6AndTreeVersion(0)) + sinceVersion = sinceV6AndTreeVersion(0)) lazy val compareTo = newFeature((x: (Int, Int)) => x._1.compareTo(x._2), "{ (x: (Int, Int)) => x._1.compareTo(x._2) }", - sinceVersion = VersionContext.sinceV6AndTreeVersion(0)) + sinceVersion = sinceV6AndTreeVersion(0)) lazy val bitOr = newFeature( { (x: (Int, Int)) => x._1 | x._2 }, "{ (x: (Int, Int)) => x._1 | x._2 }", - sinceVersion = VersionContext.sinceV6AndTreeVersion(0)) + sinceVersion = sinceV6AndTreeVersion(0)) lazy val bitAnd = newFeature( { (x: (Int, Int)) => x._1 & x._2 }, "{ (x: (Int, Int)) => x._1 & x._2 }", - sinceVersion = VersionContext.sinceV6AndTreeVersion(0)) + sinceVersion = sinceV6AndTreeVersion(0)) forAll { x: Int => Seq(toAbs).foreach(_.checkEquality(x)) } @@ -147,20 +152,20 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite => // NOTE, for such versions the new features are not supported // which is checked below lazy val toAbs = newFeature((x: Long) => x.toAbs, "{ (x: Long) => x.toAbs }", - sinceVersion = VersionContext.sinceV6AndTreeVersion(0)) + sinceVersion = sinceV6AndTreeVersion(0)) lazy val compareTo = newFeature((x: (Long, Long)) => x._1.compareTo(x._2), "{ (x: (Long, Long)) => x._1.compareTo(x._2) }", - sinceVersion = VersionContext.sinceV6AndTreeVersion(0)) + sinceVersion = sinceV6AndTreeVersion(0)) lazy val bitOr = newFeature( { (x: (Long, Long)) => x._1 | x._2 }, "{ (x: (Long, Long)) => x._1 | x._2 }", - sinceVersion = VersionContext.sinceV6AndTreeVersion(0)) + sinceVersion = sinceV6AndTreeVersion(0)) lazy val bitAnd = newFeature( { (x: (Long, Long)) => x._1 & x._2 }, "{ (x: (Long, Long)) => x._1 & x._2 }", - sinceVersion = VersionContext.sinceV6AndTreeVersion(0)) + sinceVersion = sinceV6AndTreeVersion(0)) forAll { x: Long => Seq(toAbs).foreach(_.checkEquality(x)) @@ -195,30 +200,30 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite => val toByte = newFeature((x: BigInt) => x.toByte, "{ (x: BigInt) => x.toByte }", FuncValue(Vector((1, SBigInt)), Downcast(ValUse(1, SBigInt), SByte)), - sinceVersion = VersionContext.sinceV6AndTreeVersion(0)) + sinceVersion = sinceV6AndTreeVersion(0)) val toShort = newFeature((x: BigInt) => x.toShort, "{ (x: BigInt) => x.toShort }", FuncValue(Vector((1, SBigInt)), Downcast(ValUse(1, SBigInt), SShort)), - sinceVersion = VersionContext.sinceV6AndTreeVersion(0)) + sinceVersion = sinceV6AndTreeVersion(0)) val toInt = newFeature((x: BigInt) => x.toInt, "{ (x: BigInt) => x.toInt }", FuncValue(Vector((1, SBigInt)), Downcast(ValUse(1, SBigInt), SInt)), - sinceVersion = VersionContext.sinceV6AndTreeVersion(0)) + sinceVersion = sinceV6AndTreeVersion(0)) val toLong = newFeature((x: BigInt) => x.toLong, "{ (x: BigInt) => x.toLong }", FuncValue(Vector((1, SBigInt)), Downcast(ValUse(1, SBigInt), SLong)), - sinceVersion = VersionContext.sinceV6AndTreeVersion(0)) + sinceVersion = sinceV6AndTreeVersion(0)) lazy val toAbs = newFeature((x: BigInt) => x.toAbs, "{ (x: BigInt) => x.toAbs }", - sinceVersion = VersionContext.sinceV6AndTreeVersion(0)) + sinceVersion = sinceV6AndTreeVersion(0)) lazy val compareTo = newFeature((x: (BigInt, BigInt)) => x._1.compareTo(x._2), "{ (x: (BigInt, BigInt)) => x._1.compareTo(x._2) }", - sinceVersion = VersionContext.sinceV6AndTreeVersion(0)) + sinceVersion = sinceV6AndTreeVersion(0)) lazy val bitOr = newFeature({ (x: (BigInt, BigInt)) => x._1 | x._2 }, "{ (x: (BigInt, BigInt)) => x._1 | x._2 }", - sinceVersion = VersionContext.sinceV6AndTreeVersion(0)) + sinceVersion = sinceV6AndTreeVersion(0)) lazy val bitAnd = newFeature({ (x: (BigInt, BigInt)) => x._1 & x._2 }, "{ (x: (BigInt, BigInt)) => x._1 & x._2 }", - sinceVersion = VersionContext.sinceV6AndTreeVersion(0)) + sinceVersion = sinceV6AndTreeVersion(0)) forAll { x: BigInt => Seq(toByte, toShort, toInt, toLong, toAbs).foreach(_.checkEquality(x)) @@ -233,7 +238,7 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite => // TODO v6.0: related to https://github.com/ScorexFoundation/sigmastate-interpreter/issues/416 val getReg = newFeature((x: Box) => x.getReg[Int](1).get, "{ (x: Box) => x.getReg[Int](1).get }", - sinceVersion = VersionContext.sinceV6AndTreeVersion(0)) + sinceVersion = sinceV6AndTreeVersion(0)) if (activatedVersionInTests < VersionContext.V6SoftForkVersion) { // NOTE, for such versions getReg is not supported @@ -249,7 +254,7 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite => property("Coll find method equivalence") { val find = newFeature((x: Coll[Int]) => x.find({ (v: Int) => v > 0 }), "{ (x: Coll[Int]) => x.find({ (v: Int) => v > 0} ) }", - sinceVersion = VersionContext.sinceV6AndTreeVersion(0)) + sinceVersion = sinceV6AndTreeVersion(0)) if (activatedVersionInTests < VersionContext.V6SoftForkVersion) { // NOTE, for such versions getReg is not supported @@ -268,7 +273,7 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite => if (x.size > 2) x.slice(0, x.size - 2) else Colls.emptyColl[Boolean] }, "{ (x: Coll[Boolean]) => x >> 2 }", - sinceVersion = VersionContext.sinceV6AndTreeVersion(0)) + sinceVersion = sinceV6AndTreeVersion(0)) if (activatedVersionInTests < VersionContext.V6SoftForkVersion) { // NOTE, for such versions getReg is not supported @@ -284,7 +289,7 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite => property("Coll diff methods equivalence") { val diff = newFeature((x: (Coll[Int], Coll[Int])) => x._1.diff(x._2), "{ (x: (Coll[Int], Coll[Int])) => x._1.diff(x._2) }", - sinceVersion = VersionContext.sinceV6AndTreeVersion(0)) + sinceVersion = sinceV6AndTreeVersion(0)) if (activatedVersionInTests < VersionContext.V6SoftForkVersion) { // NOTE, for such versions getReg is not supported @@ -301,7 +306,7 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite => val n = ExactNumeric.LongIsExactNumeric val fold = newFeature({ (x: Option[Long]) => x.fold(5.toLong)( (v: Long) => n.plus(v, 1) ) }, "{ (x: Option[Long]) => x.fold(5, { (v: Long) => v + 1 }) }", - sinceVersion = VersionContext.sinceV6AndTreeVersion(0)) + sinceVersion = sinceV6AndTreeVersion(0)) if (activatedVersionInTests < VersionContext.V6SoftForkVersion) { // NOTE, for such versions getReg is not supported @@ -317,7 +322,7 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite => property("allZK equivalence") { lazy val allZK = newFeature((x: Coll[SigmaProp]) => SigmaDsl.allZK(x), "{ (x: Coll[SigmaProp]) => allZK(x) }", - sinceVersion = VersionContext.sinceV6AndTreeVersion(0)) + sinceVersion = sinceV6AndTreeVersion(0)) if (activatedVersionInTests < VersionContext.V6SoftForkVersion) { // NOTE, for such versions getReg is not supported @@ -333,7 +338,7 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite => property("anyZK equivalence") { lazy val anyZK = newFeature((x: Coll[SigmaProp]) => SigmaDsl.anyZK(x), "{ (x: Coll[SigmaProp]) => anyZK(x) }", - sinceVersion = VersionContext.sinceV6AndTreeVersion(0)) + sinceVersion = sinceV6AndTreeVersion(0)) if (activatedVersionInTests < VersionContext.V6SoftForkVersion) { // NOTE, for such versions getReg is not supported @@ -349,7 +354,7 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite => lazy val toBytes = newFeature( { (x: Byte) => x.toBigEndianBytes }, "{ (x: Byte) => x.toBytes }", - sinceVersion = VersionContext.sinceV6AndTreeVersion(0)) + sinceVersion = sinceV6AndTreeVersion(0)) val cases = Seq( (0.toByte, Success(Coll(0.toByte))), (1.toByte, Success(Coll(1.toByte))) diff --git a/sc/shared/src/test/scala/sigma/SigmaDslTesting.scala b/sc/shared/src/test/scala/sigma/SigmaDslTesting.scala index 0b512d1380..33c4708942 100644 --- a/sc/shared/src/test/scala/sigma/SigmaDslTesting.scala +++ b/sc/shared/src/test/scala/sigma/SigmaDslTesting.scala @@ -868,8 +868,10 @@ class SigmaDslTesting extends AnyPropSpec )(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 = - sinceVersion <= vc + override def isSupportedIn(vc: VersionContext): Boolean = { + sinceVersion.activatedVersion < vc.activatedVersion || + (sinceVersion.activatedVersion == vc.activatedVersion && sinceVersion.ergoTreeVersion <= vc.ergoTreeVersion) + } override def scalaFunc: A => B = { x => sys.error(s"Semantic Scala function is not defined for old implementation: $this") From cb7e26209ee2608a7c36657e8e37279a8a48a2a6 Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Sat, 6 Jul 2024 22:15:09 +0300 Subject: [PATCH 171/314] initial toBits failing tests --- .../sigmastate/utxo/BasicOpsSpecification.scala | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala index 79701d6e07..f6f8399aeb 100644 --- a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala @@ -3,6 +3,7 @@ package sigmastate.utxo import org.ergoplatform.ErgoBox.{AdditionalRegisters, R6, R8} import org.ergoplatform._ import sigma.Extensions.ArrayOps +import sigma.VersionContext import sigma.ast.SCollection.SByteArray import sigma.ast.SType.AnyOps import sigma.data.{AvlTreeData, CAnyValue, CSigmaDslBuilder} @@ -135,6 +136,20 @@ class BasicOpsSpecification extends CompilerTestingCommons flexVerifier.verify(verifyEnv, tree, ctxExt, pr.proof, fakeMessage).get._1 shouldBe true } + property("BigInt.toBits") { + def toBitsTest() = test("R1", env, ext, + """{ + | val b = 1.toBigInt + | b.toBits == Coll(true) + |}""".stripMargin, + null + ) + + if(VersionContext.current.isV6SoftForkActivated) { + toBitsTest() + } + } + property("Unit register") { // TODO frontend: implement missing Unit support in compiler // https://github.com/ScorexFoundation/sigmastate-interpreter/issues/820 From f577fd359fe310d61c9a19b1c5bdbc996e1e96cb Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Mon, 8 Jul 2024 10:59:16 +0300 Subject: [PATCH 172/314] passing test (compilation fixed) --- .../scala/sigma/compiler/ir/TreeBuilding.scala | 6 +++++- .../compiler/ir/primitives/NumericOps.scala | 5 +++-- .../sigmastate/utxo/BasicOpsSpecification.scala | 17 +++++++++++++++++ 3 files changed, 25 insertions(+), 3 deletions(-) diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/TreeBuilding.scala b/sc/shared/src/main/scala/sigma/compiler/ir/TreeBuilding.scala index f7daff90ae..4894940ef6 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/TreeBuilding.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/TreeBuilding.scala @@ -186,7 +186,11 @@ trait TreeBuilding extends Base { IR: IRContext => .asInstanceOf[ConstantNode[SType]] s.put(constant)(builder) case None => - mkConstant[tpe.type](x.asInstanceOf[tpe.WrappedType], tpe) + if(x.isInstanceOf[CollConst[_, _]]) { // hack used to process NumericToBigEndianBytes only + mkConstant[tpe.type](x.asInstanceOf[CollConst[_, _]].constValue.asInstanceOf[tpe.WrappedType], tpe) + } else { + mkConstant[tpe.type](x.asInstanceOf[tpe.WrappedType], tpe) + } } case Def(IR.ConstantPlaceholder(id, elem)) => val tpe = elemToSType(elem) diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/primitives/NumericOps.scala b/sc/shared/src/main/scala/sigma/compiler/ir/primitives/NumericOps.scala index ef4124d0b5..80a2560d0f 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/primitives/NumericOps.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/primitives/NumericOps.scala @@ -71,8 +71,9 @@ trait NumericOps extends Base { self: IRContext => /** Descriptor of unary `ToBigEndianBytes` conversion operation. */ case class NumericToBigEndianBytes[T](n: ExactNumeric[T]) extends UnOp[T, Coll[Byte]]("ToBigEndianBytes")(element[Coll[Byte]]) { - override def applySeq(x: T): Coll[Byte] = - n.toBigEndianBytes(x).asInstanceOf[Coll[Byte]] + override def applySeq(x: T): Coll[Byte] = { + liftableColl(Liftables.ByteIsLiftable).lift(n.toBigEndianBytes(x)) + } } /** Descriptor of binary `/` operation (integral division). */ diff --git a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala index 79701d6e07..f88e821e9e 100644 --- a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala @@ -3,6 +3,7 @@ package sigmastate.utxo import org.ergoplatform.ErgoBox.{AdditionalRegisters, R6, R8} import org.ergoplatform._ import sigma.Extensions.ArrayOps +import sigma.VersionContext import sigma.ast.SCollection.SByteArray import sigma.ast.SType.AnyOps import sigma.data.{AvlTreeData, CAnyValue, CSigmaDslBuilder} @@ -157,6 +158,22 @@ class BasicOpsSpecification extends CompilerTestingCommons ) } + property("Long.toBytes") { + def toBytesTest() = test("Long.toBytes", env, ext, + """{ + | val l = 1L + | l.toBytes.size > 0 + | }""".stripMargin, + null + ) + + if (VersionContext.current.isV6SoftForkActivated) { + toBytesTest() + } else { + an[Exception] shouldBe thrownBy(toBytesTest()) + } + } + property("Relation operations") { test("R1", env, ext, "{ allOf(Coll(getVar[Boolean](trueVar).get, true, true)) }", From cadf53d8e4439cfc2427183bd56069407304a37c Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Mon, 8 Jul 2024 11:10:23 +0300 Subject: [PATCH 173/314] tests for Byte and BigInt --- .../utxo/BasicOpsSpecification.scala | 41 +++++++++++++++++-- 1 file changed, 37 insertions(+), 4 deletions(-) diff --git a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala index f88e821e9e..de30a6f509 100644 --- a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala @@ -158,11 +158,44 @@ class BasicOpsSpecification extends CompilerTestingCommons ) } - property("Long.toBytes") { - def toBytesTest() = test("Long.toBytes", env, ext, + property("Int.toBytes") { + def toBytesTest() = test("Int.toBytes", env, ext, """{ - | val l = 1L - | l.toBytes.size > 0 + | val l = 1 + | l.toBytes == Coll(0.toByte, 0.toByte, 0.toByte, 1.toByte) + | }""".stripMargin, + null + ) + + if (VersionContext.current.isV6SoftForkActivated) { + toBytesTest() + } else { + an[Exception] shouldBe thrownBy(toBytesTest()) + } + } + + property("Byte.toBytes") { + def toBytesTest() = test("Byte.toBytes", env, ext, + """{ + | val l = 10.toByte + | l.toBytes == Coll(10.toByte) + | }""".stripMargin, + null + ) + + if (VersionContext.current.isV6SoftForkActivated) { + toBytesTest() + } else { + an[Exception] shouldBe thrownBy(toBytesTest()) + } + } + + + property("BigInt.toBytes") { + def toBytesTest() = test("BigInt.toBytes", env, ext, + s"""{ + | val l = bigInt("${CryptoConstants.groupOrder.divide(new BigInteger("2"))}") + | l.toBytes.size == 32 | }""".stripMargin, null ) From ee59083d9ada7e8ea51b7ad728cc6ada74089c7c Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Mon, 8 Jul 2024 13:35:48 +0300 Subject: [PATCH 174/314] Byte.toBits test passing --- .../src/main/scala/sigma/data/BigIntegerOps.scala | 2 ++ .../src/main/scala/sigma/data/ExactIntegral.scala | 11 +++++++++++ .../src/main/scala/sigma/data/ExactNumeric.scala | 2 ++ .../main/scala/sigma/compiler/ir/GraphBuilding.scala | 3 +++ .../main/scala/sigma/compiler/ir/TreeBuilding.scala | 7 +++++++ .../sigma/compiler/ir/primitives/NumericOps.scala | 8 ++++++++ .../sigmastate/utxo/BasicOpsSpecification.scala | 12 +++++++----- 7 files changed, 40 insertions(+), 5 deletions(-) diff --git a/data/shared/src/main/scala/sigma/data/BigIntegerOps.scala b/data/shared/src/main/scala/sigma/data/BigIntegerOps.scala index 0bb9e9101b..788915a1e8 100644 --- a/data/shared/src/main/scala/sigma/data/BigIntegerOps.scala +++ b/data/shared/src/main/scala/sigma/data/BigIntegerOps.scala @@ -92,6 +92,8 @@ object NumericOps { override def divisionRemainder(x: BigInt, y: BigInt): BigInt = x.mod(y) override def toBigEndianBytes(x: BigInt): Coll[Byte] = Colls.fromArray(x.toBigInteger.toByteArray) + + override def toBits(x: BigInt): Coll[Boolean] = ??? } /** The instance of [[scalan.ExactOrdering]] typeclass for [[BigInt]]. */ diff --git a/data/shared/src/main/scala/sigma/data/ExactIntegral.scala b/data/shared/src/main/scala/sigma/data/ExactIntegral.scala index eaf89947c1..ad01e34dc3 100644 --- a/data/shared/src/main/scala/sigma/data/ExactIntegral.scala +++ b/data/shared/src/main/scala/sigma/data/ExactIntegral.scala @@ -39,6 +39,13 @@ object ExactIntegral { override def minus(x: Byte, y: Byte): Byte = x.subtractExact(y) override def times(x: Byte, y: Byte): Byte = x.multiplyExact(y) override def toBigEndianBytes(x: Byte): Coll[Byte] = Colls.fromItems(x) + override def toBits(x: Byte): Coll[Boolean] = { + def byte2Bools(b: Byte): Array[Boolean] = (0 to 7).toArray.reverse.map(isBitSet(b)) + + def isBitSet(byte: Byte)(bit: Int): Boolean = ((byte >> bit) & 1) == 1 + + Colls.fromArray(byte2Bools(x)) + } } implicit object ShortIsExactIntegral extends ExactIntegral[Short] { @@ -47,6 +54,7 @@ object ExactIntegral { override def minus(x: Short, y: Short): Short = x.subtractExact(y) override def times(x: Short, y: Short): Short = x.multiplyExact(y) override def toBigEndianBytes(x: Short): Coll[Byte] = Colls.fromItems((x >> 8).toByte, x.toByte) + override def toBits(x: Short): Coll[Boolean] = ??? } implicit object IntIsExactIntegral extends ExactIntegral[Int] { @@ -56,6 +64,7 @@ object ExactIntegral { override def times(x: Int, y: Int): Int = java7.compat.Math.multiplyExact(x, y) override def toBigEndianBytes(x: Int): Coll[Byte] = Colls.fromItems((x >> 24).toByte, (x >> 16).toByte, (x >> 8).toByte, x.toByte) + override def toBits(x: Int): Coll[Boolean] = ??? } implicit object LongIsExactIntegral extends ExactIntegral[Long] { @@ -65,5 +74,7 @@ object ExactIntegral { override def times(x: Long, y: Long): Long = java7.compat.Math.multiplyExact(x, y) override def toBigEndianBytes(x: Long): Coll[Byte] = Colls.fromItems((x >> 56).toByte, (x >> 48).toByte, (x >> 40).toByte, (x >> 32).toByte, (x >> 24).toByte, (x >> 16).toByte, (x >> 8).toByte, x.toByte) + + override def toBits(x: Long): Coll[Boolean] = ??? } } diff --git a/data/shared/src/main/scala/sigma/data/ExactNumeric.scala b/data/shared/src/main/scala/sigma/data/ExactNumeric.scala index d8b3b5df0d..166e8d4fd1 100644 --- a/data/shared/src/main/scala/sigma/data/ExactNumeric.scala +++ b/data/shared/src/main/scala/sigma/data/ExactNumeric.scala @@ -37,6 +37,8 @@ trait ExactNumeric[T] { */ def toBigEndianBytes(x: T): Coll[Byte] + def toBits(x: T): Coll[Boolean] + /** A value of type T which corresponds to integer 0. */ lazy val zero: T = fromInt(0) 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 5595ded3db..67bd0e37f3 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/GraphBuilding.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/GraphBuilding.scala @@ -1153,6 +1153,9 @@ trait GraphBuilding extends Base with DefRewriting { IR: IRContext => case SNumericTypeMethods.ToBytesMethod.name => val op = NumericToBigEndianBytes(elemToExactNumeric(x.elem)) ApplyUnOp(op, x) + case SNumericTypeMethods.ToBitsMethod.name => + val op = NumericToBits(elemToExactNumeric(x.elem)) + ApplyUnOp(op, x) case _ => throwError() } case _ => throwError(s"Type ${stypeToRType(obj.tpe).name} doesn't have methods") diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/TreeBuilding.scala b/sc/shared/src/main/scala/sigma/compiler/ir/TreeBuilding.scala index 4894940ef6..0da5f332cc 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/TreeBuilding.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/TreeBuilding.scala @@ -113,6 +113,13 @@ trait TreeBuilding extends Base { IR: IRContext => builder.mkMethodCall(v.asNumValue, m, IndexedSeq.empty) } Some(mkNode) + case _: NumericToBits[_] => + val mkNode = { v: SValue => + val receiverType = v.tpe.asNumTypeOrElse(error(s"Expected numeric type, got: ${v.tpe}")) + val m = SMethod.fromIds(receiverType.typeId, SNumericTypeMethods.ToBitsMethod.methodId) + builder.mkMethodCall(v.asNumValue, m, IndexedSeq.empty) + } + Some(mkNode) case _ => None } } diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/primitives/NumericOps.scala b/sc/shared/src/main/scala/sigma/compiler/ir/primitives/NumericOps.scala index 80a2560d0f..543bd708c9 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/primitives/NumericOps.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/primitives/NumericOps.scala @@ -76,6 +76,14 @@ trait NumericOps extends Base { self: IRContext => } } + /** Descriptor of unary `ToBigEndianBytes` conversion operation. */ + case class NumericToBits[T](n: ExactNumeric[T]) + extends UnOp[T, Coll[Boolean]]("ToBits")(element[Coll[Boolean]]) { + override def applySeq(x: T): Coll[Boolean] = { + liftableColl(Liftables.BooleanIsLiftable).lift(n.toBits(x)) + } + } + /** Descriptor of binary `/` operation (integral division). */ case class IntegralDivide[T](i: ExactIntegral[T])(implicit elem: Elem[T]) extends DivOp[T]("/", i) { override def applySeq(x: T, y: T): T = i.quot(x, y) diff --git a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala index 28886ba6c6..1380de5f72 100644 --- a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala @@ -136,17 +136,19 @@ class BasicOpsSpecification extends CompilerTestingCommons flexVerifier.verify(verifyEnv, tree, ctxExt, pr.proof, fakeMessage).get._1 shouldBe true } - property("BigInt.toBits") { - def toBitsTest() = test("R1", env, ext, + property("Byte.toBits") { + def toBitsTest() = test("Byte.toBits", env, ext, """{ - | val b = 1.toBigInt - | b.toBits == Coll(true) + | val b = 1.toByte + | b.toBits == Coll(false, false, false, false, false, false, false, true) |}""".stripMargin, null ) - if(VersionContext.current.isV6SoftForkActivated) { + if (VersionContext.current.isV6SoftForkActivated) { toBitsTest() + } else { + an[Exception] shouldBe thrownBy(toBitsTest()) } } From 3fde5faf34368843d9bcc1e2199217b378ccb1e3 Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Mon, 8 Jul 2024 19:43:08 +0300 Subject: [PATCH 175/314] toBits tests for Long and BigInt(failing) --- .../main/scala/sigma/data/BigIntegerOps.scala | 2 -- .../main/scala/sigma/data/ExactIntegral.scala | 11 ------ .../main/scala/sigma/data/ExactNumeric.scala | 19 ++++++++-- .../utxo/BasicOpsSpecification.scala | 36 +++++++++++++++++++ 4 files changed, 53 insertions(+), 15 deletions(-) diff --git a/data/shared/src/main/scala/sigma/data/BigIntegerOps.scala b/data/shared/src/main/scala/sigma/data/BigIntegerOps.scala index 788915a1e8..0bb9e9101b 100644 --- a/data/shared/src/main/scala/sigma/data/BigIntegerOps.scala +++ b/data/shared/src/main/scala/sigma/data/BigIntegerOps.scala @@ -92,8 +92,6 @@ object NumericOps { override def divisionRemainder(x: BigInt, y: BigInt): BigInt = x.mod(y) override def toBigEndianBytes(x: BigInt): Coll[Byte] = Colls.fromArray(x.toBigInteger.toByteArray) - - override def toBits(x: BigInt): Coll[Boolean] = ??? } /** The instance of [[scalan.ExactOrdering]] typeclass for [[BigInt]]. */ diff --git a/data/shared/src/main/scala/sigma/data/ExactIntegral.scala b/data/shared/src/main/scala/sigma/data/ExactIntegral.scala index ad01e34dc3..eaf89947c1 100644 --- a/data/shared/src/main/scala/sigma/data/ExactIntegral.scala +++ b/data/shared/src/main/scala/sigma/data/ExactIntegral.scala @@ -39,13 +39,6 @@ object ExactIntegral { override def minus(x: Byte, y: Byte): Byte = x.subtractExact(y) override def times(x: Byte, y: Byte): Byte = x.multiplyExact(y) override def toBigEndianBytes(x: Byte): Coll[Byte] = Colls.fromItems(x) - override def toBits(x: Byte): Coll[Boolean] = { - def byte2Bools(b: Byte): Array[Boolean] = (0 to 7).toArray.reverse.map(isBitSet(b)) - - def isBitSet(byte: Byte)(bit: Int): Boolean = ((byte >> bit) & 1) == 1 - - Colls.fromArray(byte2Bools(x)) - } } implicit object ShortIsExactIntegral extends ExactIntegral[Short] { @@ -54,7 +47,6 @@ object ExactIntegral { override def minus(x: Short, y: Short): Short = x.subtractExact(y) override def times(x: Short, y: Short): Short = x.multiplyExact(y) override def toBigEndianBytes(x: Short): Coll[Byte] = Colls.fromItems((x >> 8).toByte, x.toByte) - override def toBits(x: Short): Coll[Boolean] = ??? } implicit object IntIsExactIntegral extends ExactIntegral[Int] { @@ -64,7 +56,6 @@ object ExactIntegral { override def times(x: Int, y: Int): Int = java7.compat.Math.multiplyExact(x, y) override def toBigEndianBytes(x: Int): Coll[Byte] = Colls.fromItems((x >> 24).toByte, (x >> 16).toByte, (x >> 8).toByte, x.toByte) - override def toBits(x: Int): Coll[Boolean] = ??? } implicit object LongIsExactIntegral extends ExactIntegral[Long] { @@ -74,7 +65,5 @@ object ExactIntegral { override def times(x: Long, y: Long): Long = java7.compat.Math.multiplyExact(x, y) override def toBigEndianBytes(x: Long): Coll[Byte] = Colls.fromItems((x >> 56).toByte, (x >> 48).toByte, (x >> 40).toByte, (x >> 32).toByte, (x >> 24).toByte, (x >> 16).toByte, (x >> 8).toByte, x.toByte) - - override def toBits(x: Long): Coll[Boolean] = ??? } } diff --git a/data/shared/src/main/scala/sigma/data/ExactNumeric.scala b/data/shared/src/main/scala/sigma/data/ExactNumeric.scala index 166e8d4fd1..93bc577e14 100644 --- a/data/shared/src/main/scala/sigma/data/ExactNumeric.scala +++ b/data/shared/src/main/scala/sigma/data/ExactNumeric.scala @@ -1,8 +1,10 @@ package sigma.data -import sigma.Coll +import sigma.{Coll, Colls} import sigma.data.ExactIntegral._ +import scala.collection.mutable + /** Numeric operations with overflow checks. * Raise exception when overflow is detected. * Each instance of this typeclass overrides three methods `plus`, `minus`, `times`. @@ -37,7 +39,20 @@ trait ExactNumeric[T] { */ def toBigEndianBytes(x: T): Coll[Byte] - def toBits(x: T): Coll[Boolean] + def toBits(x: T): Coll[Boolean] = { + def byte2Bools(b: Byte): Array[Boolean] = (0 to 7).toArray.reverse.map(isBitSet(b)) + + def isBitSet(byte: Byte)(bit: Int): Boolean = ((byte >> bit) & 1) == 1 + + val bytes = toBigEndianBytes(x) + val builder = mutable.ArrayBuilder.make[Boolean] + val l = bytes.length + (0 until l).foreach{i=> + val b = bytes(i) + builder.addAll(byte2Bools(b)) + } + Colls.fromArray(builder.result()) + } /** A value of type T which corresponds to integer 0. */ lazy val zero: T = fromInt(0) diff --git a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala index 1380de5f72..85e61b31d1 100644 --- a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala @@ -152,6 +152,42 @@ class BasicOpsSpecification extends CompilerTestingCommons } } + property("Long.toBits") { + def toBitsTest() = test("Long.toBits", env, ext, + """{ + | val b = 1L + | val ba = b.toBits + | + | // only rightmost bit is set + | ba.size == 64 && ba(63) == true && ba.slice(0, 63).forall({ (b: Boolean ) => b == false }) + |}""".stripMargin, + null + ) + + if (VersionContext.current.isV6SoftForkActivated) { + toBitsTest() + } else { + an[Exception] shouldBe thrownBy(toBitsTest()) + } + } + + property("BigInt.toBits") { + def toBitsTest() = test("BigInt.toBits", env, ext, + s"""{ + | val b = bigInt("${CryptoConstants.groupOrder.divide(new BigInteger("2"))}") + | val ba = b.toBits + | ba.size == 256 + |}""".stripMargin, + null + ) + + if (VersionContext.current.isV6SoftForkActivated) { + toBitsTest() + } else { + an[Exception] shouldBe thrownBy(toBitsTest()) + } + } + property("Unit register") { // TODO frontend: implement missing Unit support in compiler // https://github.com/ScorexFoundation/sigmastate-interpreter/issues/820 From 9ea75971dac5118e0cb90ecdddf88f2efd92e562 Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Mon, 8 Jul 2024 19:50:07 +0300 Subject: [PATCH 176/314] BigInt.toBits test passing --- data/shared/src/main/scala/sigma/ast/methods.scala | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/data/shared/src/main/scala/sigma/ast/methods.scala b/data/shared/src/main/scala/sigma/ast/methods.scala index 27112f7ac2..7ac65a4613 100644 --- a/data/shared/src/main/scala/sigma/ast/methods.scala +++ b/data/shared/src/main/scala/sigma/ast/methods.scala @@ -8,6 +8,7 @@ import sigma.ast.SMethod.{MethodCallIrBuilder, MethodCostFunc, javaMethodOf} import sigma.ast.SType.TypeCode import sigma.ast.syntax.{SValue, ValueOps} import sigma.data.ExactIntegral.{ByteIsExactIntegral, IntIsExactIntegral, LongIsExactIntegral, ShortIsExactIntegral} +import sigma.data.NumericOps.BigIntIsExactIntegral import sigma.data.OverloadHack.Overloaded1 import sigma.data.{DataValueComparer, KeyValueColl, Nullable, RType, SigmaConstants} import sigma.eval.{CostDetails, ErgoTreeEvaluator, TracedCost} @@ -258,6 +259,15 @@ object SNumericTypeMethods extends MethodsContainer { val ToBitsMethod: SMethod = SMethod( this, "toBits", SFunc(tNum, SBooleanArray), 7, ToBits_CostKind) .withIRInfo(MethodCallIrBuilder) + .withUserDefinedInvoke({ (m: SMethod, obj: Any, _: Array[Any]) => + m.objType match { + case SByteMethods => ByteIsExactIntegral.toBits(obj.asInstanceOf[Byte]) + case SShortMethods => ShortIsExactIntegral.toBits(obj.asInstanceOf[Short]) + case SIntMethods => IntIsExactIntegral.toBits(obj.asInstanceOf[Int]) + case SLongMethods => LongIsExactIntegral.toBits(obj.asInstanceOf[Long]) + case SBigIntMethods => BigIntIsExactIntegral.toBits(obj.asInstanceOf[BigInt]) + } + }) .withInfo(PropertyCall, """ Returns a big-endian representation of this numeric in a collection of Booleans. | Each boolean corresponds to one bit. From be77315def76163c44006430bfba2d6f7e4e933a Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Tue, 9 Jul 2024 19:12:59 +0300 Subject: [PATCH 177/314] bitwise inversion --- .../src/main/scala/sigma/ast/methods.scala | 23 ++++++++++++++++++- .../main/scala/sigma/data/BigIntegerOps.scala | 2 ++ .../main/scala/sigma/data/ExactIntegral.scala | 4 ++++ .../main/scala/sigma/data/ExactNumeric.scala | 2 ++ .../sigma/compiler/ir/GraphBuilding.scala | 3 +++ .../sigma/compiler/ir/TreeBuilding.scala | 7 ++++++ .../compiler/ir/primitives/NumericOps.scala | 7 +++++- .../utxo/BasicOpsSpecification.scala | 18 +++++++++++++++ 8 files changed, 64 insertions(+), 2 deletions(-) diff --git a/data/shared/src/main/scala/sigma/ast/methods.scala b/data/shared/src/main/scala/sigma/ast/methods.scala index 7ac65a4613..22ba217d5f 100644 --- a/data/shared/src/main/scala/sigma/ast/methods.scala +++ b/data/shared/src/main/scala/sigma/ast/methods.scala @@ -273,6 +273,26 @@ object SNumericTypeMethods extends MethodsContainer { | Each boolean corresponds to one bit. """.stripMargin) + /** Cost of inverting bits of a number. */ + val BitwiseInverse_CostKind = FixedCost(JitCost(5)) + + val BitwiseInverseMethod: SMethod = SMethod( + this, "bitwiseInverse", SFunc(tNum, tNum), 8, BitwiseInverse_CostKind) + .withIRInfo(MethodCallIrBuilder) + .withUserDefinedInvoke({ (m: SMethod, obj: Any, _: Array[Any]) => + m.objType match { + case SByteMethods => ByteIsExactIntegral.bitwiseInverse(obj.asInstanceOf[Byte]) + case SShortMethods => ShortIsExactIntegral.bitwiseInverse(obj.asInstanceOf[Short]) + case SIntMethods => IntIsExactIntegral.bitwiseInverse(obj.asInstanceOf[Int]) + case SLongMethods => LongIsExactIntegral.bitwiseInverse(obj.asInstanceOf[Long]) + case SBigIntMethods => BigIntIsExactIntegral.bitwiseInverse(obj.asInstanceOf[BigInt]) + } + }) + .withInfo(PropertyCall, + """ Returns a big-endian representation of this numeric in a collection of Booleans. + | Each boolean corresponds to one bit. + """.stripMargin) + protected override def getMethods(): Seq[SMethod] = Array( ToByteMethod, // see Downcast ToShortMethod, // see Downcast @@ -280,7 +300,8 @@ object SNumericTypeMethods extends MethodsContainer { ToLongMethod, // see Downcast ToBigIntMethod, // see Downcast ToBytesMethod, - ToBitsMethod + ToBitsMethod, + BitwiseInverseMethod ) /** Collection of names of numeric casting methods (like `toByte`, `toInt`, etc). */ diff --git a/data/shared/src/main/scala/sigma/data/BigIntegerOps.scala b/data/shared/src/main/scala/sigma/data/BigIntegerOps.scala index 0bb9e9101b..723e6a6691 100644 --- a/data/shared/src/main/scala/sigma/data/BigIntegerOps.scala +++ b/data/shared/src/main/scala/sigma/data/BigIntegerOps.scala @@ -92,6 +92,8 @@ object NumericOps { override def divisionRemainder(x: BigInt, y: BigInt): BigInt = x.mod(y) override def toBigEndianBytes(x: BigInt): Coll[Byte] = Colls.fromArray(x.toBigInteger.toByteArray) + + override def bitwiseInverse(x: BigInt): BigInt = CBigInt(x.toBigInteger.not()) } /** The instance of [[scalan.ExactOrdering]] typeclass for [[BigInt]]. */ diff --git a/data/shared/src/main/scala/sigma/data/ExactIntegral.scala b/data/shared/src/main/scala/sigma/data/ExactIntegral.scala index eaf89947c1..7242259480 100644 --- a/data/shared/src/main/scala/sigma/data/ExactIntegral.scala +++ b/data/shared/src/main/scala/sigma/data/ExactIntegral.scala @@ -39,6 +39,7 @@ object ExactIntegral { override def minus(x: Byte, y: Byte): Byte = x.subtractExact(y) override def times(x: Byte, y: Byte): Byte = x.multiplyExact(y) override def toBigEndianBytes(x: Byte): Coll[Byte] = Colls.fromItems(x) + override def bitwiseInverse(x: Byte): Byte = (~x).toByte } implicit object ShortIsExactIntegral extends ExactIntegral[Short] { @@ -47,6 +48,7 @@ object ExactIntegral { override def minus(x: Short, y: Short): Short = x.subtractExact(y) override def times(x: Short, y: Short): Short = x.multiplyExact(y) override def toBigEndianBytes(x: Short): Coll[Byte] = Colls.fromItems((x >> 8).toByte, x.toByte) + override def bitwiseInverse(x: Short): Short = (~x).toShort } implicit object IntIsExactIntegral extends ExactIntegral[Int] { @@ -56,6 +58,7 @@ object ExactIntegral { override def times(x: Int, y: Int): Int = java7.compat.Math.multiplyExact(x, y) override def toBigEndianBytes(x: Int): Coll[Byte] = Colls.fromItems((x >> 24).toByte, (x >> 16).toByte, (x >> 8).toByte, x.toByte) + override def bitwiseInverse(x: Int): Int = ~x } implicit object LongIsExactIntegral extends ExactIntegral[Long] { @@ -65,5 +68,6 @@ object ExactIntegral { override def times(x: Long, y: Long): Long = java7.compat.Math.multiplyExact(x, y) override def toBigEndianBytes(x: Long): Coll[Byte] = Colls.fromItems((x >> 56).toByte, (x >> 48).toByte, (x >> 40).toByte, (x >> 32).toByte, (x >> 24).toByte, (x >> 16).toByte, (x >> 8).toByte, x.toByte) + override def bitwiseInverse(x: Long): Long = ~x } } diff --git a/data/shared/src/main/scala/sigma/data/ExactNumeric.scala b/data/shared/src/main/scala/sigma/data/ExactNumeric.scala index 93bc577e14..7809ec4ca6 100644 --- a/data/shared/src/main/scala/sigma/data/ExactNumeric.scala +++ b/data/shared/src/main/scala/sigma/data/ExactNumeric.scala @@ -54,6 +54,8 @@ trait ExactNumeric[T] { Colls.fromArray(builder.result()) } + def bitwiseInverse(x: T): T + /** A value of type T which corresponds to integer 0. */ lazy val zero: T = fromInt(0) 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 67bd0e37f3..fcde26e0d5 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/GraphBuilding.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/GraphBuilding.scala @@ -1156,6 +1156,9 @@ trait GraphBuilding extends Base with DefRewriting { IR: IRContext => case SNumericTypeMethods.ToBitsMethod.name => val op = NumericToBits(elemToExactNumeric(x.elem)) ApplyUnOp(op, x) + case SNumericTypeMethods.BitwiseInverseMethod.name => + val op = NumericBitwiseInverse(elemToExactNumeric(x.elem))(x.elem) + ApplyUnOp(op, x) case _ => throwError() } case _ => throwError(s"Type ${stypeToRType(obj.tpe).name} doesn't have methods") diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/TreeBuilding.scala b/sc/shared/src/main/scala/sigma/compiler/ir/TreeBuilding.scala index 0da5f332cc..c671726507 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/TreeBuilding.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/TreeBuilding.scala @@ -120,6 +120,13 @@ trait TreeBuilding extends Base { IR: IRContext => builder.mkMethodCall(v.asNumValue, m, IndexedSeq.empty) } Some(mkNode) + case _: NumericBitwiseInverse[_] => + val mkNode = { v: SValue => + val receiverType = v.tpe.asNumTypeOrElse(error(s"Expected numeric type, got: ${v.tpe}")) + val m = SMethod.fromIds(receiverType.typeId, SNumericTypeMethods.BitwiseInverseMethod.methodId) + builder.mkMethodCall(v.asNumValue, m, IndexedSeq.empty) + } + Some(mkNode) case _ => None } } diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/primitives/NumericOps.scala b/sc/shared/src/main/scala/sigma/compiler/ir/primitives/NumericOps.scala index 543bd708c9..a9f0c0a3fa 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/primitives/NumericOps.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/primitives/NumericOps.scala @@ -76,7 +76,7 @@ trait NumericOps extends Base { self: IRContext => } } - /** Descriptor of unary `ToBigEndianBytes` conversion operation. */ + /** Descriptor of unary `ToBits` conversion operation. */ case class NumericToBits[T](n: ExactNumeric[T]) extends UnOp[T, Coll[Boolean]]("ToBits")(element[Coll[Boolean]]) { override def applySeq(x: T): Coll[Boolean] = { @@ -84,6 +84,11 @@ trait NumericOps extends Base { self: IRContext => } } + /** Descriptor of unary `ToBits` conversion operation. */ + case class NumericBitwiseInverse[T: Elem](n: ExactNumeric[T]) extends UnOp[T, T]("~") { + override def applySeq(x: T): T = n.bitwiseInverse(x) + } + /** Descriptor of binary `/` operation (integral division). */ case class IntegralDivide[T](i: ExactIntegral[T])(implicit elem: Elem[T]) extends DivOp[T]("/", i) { override def applySeq(x: T, y: T): T = i.quot(x, y) diff --git a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala index 85e61b31d1..570a1b76d7 100644 --- a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala @@ -2,6 +2,7 @@ package sigmastate.utxo import org.ergoplatform.ErgoBox.{AdditionalRegisters, R6, R8} import org.ergoplatform._ +import org.scalatest.Assertion import sigma.Extensions.ArrayOps import sigma.VersionContext import sigma.ast.SCollection.SByteArray @@ -188,6 +189,23 @@ class BasicOpsSpecification extends CompilerTestingCommons } } + property("BigInt.bitwiseInverse") { + def bitwiseInverseTest(): Assertion = test("BigInt.bitwiseInverse", env, ext, + s"""{ + | val b = bigInt("${CryptoConstants.groupOrder.divide(new BigInteger("2"))}") + | val bi = b.bitwiseInverse + | bi.bitwiseInverse == b + |}""".stripMargin, + null + ) + + if (VersionContext.current.isV6SoftForkActivated) { + bitwiseInverseTest() + } else { + an[Exception] shouldBe thrownBy(bitwiseInverseTest()) + } + } + property("Unit register") { // TODO frontend: implement missing Unit support in compiler // https://github.com/ScorexFoundation/sigmastate-interpreter/issues/820 From a575d38a1b874cb9b87d3bdfb5610f918ed39868 Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Tue, 9 Jul 2024 19:41:04 +0300 Subject: [PATCH 178/314] bitwiseInverse tests for Long and Byte --- .../utxo/BasicOpsSpecification.scala | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala index 570a1b76d7..c9e05f5226 100644 --- a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala @@ -206,6 +206,39 @@ class BasicOpsSpecification extends CompilerTestingCommons } } + property("Byte.bitwiseInverse") { + def bitwiseInverseTest(): Assertion = test("Byte.bitwiseInverse", env, ext, + s"""{ + | val b = 127.toByte + | b.bitwiseInverse == (-128).toByte + |}""".stripMargin, + null + ) + + if (VersionContext.current.isV6SoftForkActivated) { + bitwiseInverseTest() + } else { + an[Exception] shouldBe thrownBy(bitwiseInverseTest()) + } + } + + property("Long.bitwiseInverse") { + def bitwiseInverseTest(): Assertion = test("Long.bitwiseInverse", env, ext, + s"""{ + | val l = 9223372036854775807L + | val lb = l.bitwiseInverse + | lb.bitwiseInverse == l + |}""".stripMargin, + null + ) + + if (VersionContext.current.isV6SoftForkActivated) { + bitwiseInverseTest() + } else { + an[Exception] shouldBe thrownBy(bitwiseInverseTest()) + } + } + property("Unit register") { // TODO frontend: implement missing Unit support in compiler // https://github.com/ScorexFoundation/sigmastate-interpreter/issues/820 From 7ff35428b87d6bdee060a390f84a212728738b38 Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Wed, 10 Jul 2024 12:34:10 +0300 Subject: [PATCH 179/314] bitwise or impl --- .../src/main/scala/sigma/ast/methods.scala | 54 ++++++++++++++++++- .../main/scala/sigma/data/BigIntegerOps.scala | 2 + .../main/scala/sigma/data/ExactIntegral.scala | 4 ++ .../main/scala/sigma/data/ExactNumeric.scala | 2 + .../sigma/compiler/ir/GraphBuilding.scala | 4 ++ .../sigma/compiler/ir/TreeBuilding.scala | 7 +++ .../compiler/ir/primitives/NumericOps.scala | 5 ++ .../utxo/BasicOpsSpecification.scala | 35 +++++++++++- 8 files changed, 111 insertions(+), 2 deletions(-) diff --git a/data/shared/src/main/scala/sigma/ast/methods.scala b/data/shared/src/main/scala/sigma/ast/methods.scala index 22ba217d5f..ade482c168 100644 --- a/data/shared/src/main/scala/sigma/ast/methods.scala +++ b/data/shared/src/main/scala/sigma/ast/methods.scala @@ -293,6 +293,57 @@ object SNumericTypeMethods extends MethodsContainer { | Each boolean corresponds to one bit. """.stripMargin) + val BitwiseOrMethod: SMethod = SMethod( + this, "bitwiseOr", SFunc(Array(tNum, tNum), tNum), 9, BitwiseInverse_CostKind) + .withIRInfo(MethodCallIrBuilder) + .withUserDefinedInvoke({ (m: SMethod, obj: Any, other: Array[Any]) => + m.objType match { + case SByteMethods => ByteIsExactIntegral.bitwiseOr(obj.asInstanceOf[Byte], other.head.asInstanceOf[Byte]) + case SShortMethods => ShortIsExactIntegral.bitwiseOr(obj.asInstanceOf[Short], other.head.asInstanceOf[Short]) + case SIntMethods => IntIsExactIntegral.bitwiseOr(obj.asInstanceOf[Int], other.head.asInstanceOf[Int]) + case SLongMethods => LongIsExactIntegral.bitwiseOr(obj.asInstanceOf[Long], other.head.asInstanceOf[Long]) + case SBigIntMethods => BigIntIsExactIntegral.bitwiseOr(obj.asInstanceOf[BigInt], other.head.asInstanceOf[BigInt]) + } + }) + .withInfo(PropertyCall, + """ Returns a big-endian representation of this numeric in a collection of Booleans. + | Each boolean corresponds to one bit. + """.stripMargin) + + val BitwiseAndMethod: SMethod = SMethod( + this, "bitwiseInverse", SFunc(tNum, tNum), 10, BitwiseInverse_CostKind) + .withIRInfo(MethodCallIrBuilder) + .withUserDefinedInvoke({ (m: SMethod, obj: Any, _: Array[Any]) => + m.objType match { + case SByteMethods => ByteIsExactIntegral.bitwiseInverse(obj.asInstanceOf[Byte]) + case SShortMethods => ShortIsExactIntegral.bitwiseInverse(obj.asInstanceOf[Short]) + case SIntMethods => IntIsExactIntegral.bitwiseInverse(obj.asInstanceOf[Int]) + case SLongMethods => LongIsExactIntegral.bitwiseInverse(obj.asInstanceOf[Long]) + case SBigIntMethods => BigIntIsExactIntegral.bitwiseInverse(obj.asInstanceOf[BigInt]) + } + }) + .withInfo(PropertyCall, + """ Returns a big-endian representation of this numeric in a collection of Booleans. + | Each boolean corresponds to one bit. + """.stripMargin) + + val BitwiseXorMethod: SMethod = SMethod( + this, "bitwiseInverse", SFunc(tNum, tNum), 11, BitwiseInverse_CostKind) + .withIRInfo(MethodCallIrBuilder) + .withUserDefinedInvoke({ (m: SMethod, obj: Any, _: Array[Any]) => + m.objType match { + case SByteMethods => ByteIsExactIntegral.bitwiseInverse(obj.asInstanceOf[Byte]) + case SShortMethods => ShortIsExactIntegral.bitwiseInverse(obj.asInstanceOf[Short]) + case SIntMethods => IntIsExactIntegral.bitwiseInverse(obj.asInstanceOf[Int]) + case SLongMethods => LongIsExactIntegral.bitwiseInverse(obj.asInstanceOf[Long]) + case SBigIntMethods => BigIntIsExactIntegral.bitwiseInverse(obj.asInstanceOf[BigInt]) + } + }) + .withInfo(PropertyCall, + """ Returns a big-endian representation of this numeric in a collection of Booleans. + | Each boolean corresponds to one bit. + """.stripMargin) + protected override def getMethods(): Seq[SMethod] = Array( ToByteMethod, // see Downcast ToShortMethod, // see Downcast @@ -301,7 +352,8 @@ object SNumericTypeMethods extends MethodsContainer { ToBigIntMethod, // see Downcast ToBytesMethod, ToBitsMethod, - BitwiseInverseMethod + BitwiseInverseMethod, + BitwiseOrMethod ) /** Collection of names of numeric casting methods (like `toByte`, `toInt`, etc). */ diff --git a/data/shared/src/main/scala/sigma/data/BigIntegerOps.scala b/data/shared/src/main/scala/sigma/data/BigIntegerOps.scala index 723e6a6691..8a7d597ed0 100644 --- a/data/shared/src/main/scala/sigma/data/BigIntegerOps.scala +++ b/data/shared/src/main/scala/sigma/data/BigIntegerOps.scala @@ -94,6 +94,8 @@ object NumericOps { override def toBigEndianBytes(x: BigInt): Coll[Byte] = Colls.fromArray(x.toBigInteger.toByteArray) override def bitwiseInverse(x: BigInt): BigInt = CBigInt(x.toBigInteger.not()) + + def bitwiseOr(x: BigInt, y: BigInt): BigInt = CBigInt(x.toBigInteger.or(y.toBigInteger)) } /** The instance of [[scalan.ExactOrdering]] typeclass for [[BigInt]]. */ diff --git a/data/shared/src/main/scala/sigma/data/ExactIntegral.scala b/data/shared/src/main/scala/sigma/data/ExactIntegral.scala index 7242259480..787800a14a 100644 --- a/data/shared/src/main/scala/sigma/data/ExactIntegral.scala +++ b/data/shared/src/main/scala/sigma/data/ExactIntegral.scala @@ -40,6 +40,7 @@ object ExactIntegral { override def times(x: Byte, y: Byte): Byte = x.multiplyExact(y) override def toBigEndianBytes(x: Byte): Coll[Byte] = Colls.fromItems(x) override def bitwiseInverse(x: Byte): Byte = (~x).toByte + override def bitwiseOr(x: Byte, y: Byte): Byte = (x | y).toByte } implicit object ShortIsExactIntegral extends ExactIntegral[Short] { @@ -49,6 +50,7 @@ object ExactIntegral { override def times(x: Short, y: Short): Short = x.multiplyExact(y) override def toBigEndianBytes(x: Short): Coll[Byte] = Colls.fromItems((x >> 8).toByte, x.toByte) override def bitwiseInverse(x: Short): Short = (~x).toShort + override def bitwiseOr(x: Short, y: Short): Short = (x | y).toShort } implicit object IntIsExactIntegral extends ExactIntegral[Int] { @@ -59,6 +61,7 @@ object ExactIntegral { override def toBigEndianBytes(x: Int): Coll[Byte] = Colls.fromItems((x >> 24).toByte, (x >> 16).toByte, (x >> 8).toByte, x.toByte) override def bitwiseInverse(x: Int): Int = ~x + override def bitwiseOr(x: Int, y: Int): Int = x | y } implicit object LongIsExactIntegral extends ExactIntegral[Long] { @@ -69,5 +72,6 @@ object ExactIntegral { override def toBigEndianBytes(x: Long): Coll[Byte] = Colls.fromItems((x >> 56).toByte, (x >> 48).toByte, (x >> 40).toByte, (x >> 32).toByte, (x >> 24).toByte, (x >> 16).toByte, (x >> 8).toByte, x.toByte) override def bitwiseInverse(x: Long): Long = ~x + override def bitwiseOr(x: Long, y: Long): Long = x | y } } diff --git a/data/shared/src/main/scala/sigma/data/ExactNumeric.scala b/data/shared/src/main/scala/sigma/data/ExactNumeric.scala index 7809ec4ca6..8328ac4143 100644 --- a/data/shared/src/main/scala/sigma/data/ExactNumeric.scala +++ b/data/shared/src/main/scala/sigma/data/ExactNumeric.scala @@ -56,6 +56,8 @@ trait ExactNumeric[T] { def bitwiseInverse(x: T): T + def bitwiseOr(x: T, y: T): T + /** A value of type T which corresponds to integer 0. */ lazy val zero: T = fromInt(0) 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 fcde26e0d5..cfa67f40a4 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/GraphBuilding.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/GraphBuilding.scala @@ -1159,6 +1159,10 @@ trait GraphBuilding extends Base with DefRewriting { IR: IRContext => case SNumericTypeMethods.BitwiseInverseMethod.name => val op = NumericBitwiseInverse(elemToExactNumeric(x.elem))(x.elem) ApplyUnOp(op, x) + case SNumericTypeMethods.BitwiseOrMethod.name => + val y = asRep[tNum](argsV(0)) + val op = NumericBitwiseOr(elemToExactNumeric(x.elem))(x.elem) + ApplyBinOp(op, x, y) case _ => throwError() } case _ => throwError(s"Type ${stypeToRType(obj.tpe).name} doesn't have methods") diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/TreeBuilding.scala b/sc/shared/src/main/scala/sigma/compiler/ir/TreeBuilding.scala index c671726507..9fa4f80208 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/TreeBuilding.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/TreeBuilding.scala @@ -217,6 +217,13 @@ trait TreeBuilding extends Base { IR: IRContext => case Def(IsContextProperty(v)) => v case s if s == sigmaDslBuilder => Global + case Def(ApplyBinOp(op, xSym, ySym)) if op.isInstanceOf[NumericBitwiseOr[_]] => + val Seq(x, y) = Seq(xSym, ySym).map(recurse) + val receiverType = x.asNumValue.tpe.asNumTypeOrElse(error(s"Expected numeric type, got: ${x.tpe}")) + val m = SMethod.fromIds(receiverType.typeId, SNumericTypeMethods.BitwiseOrMethod.methodId) + builder.mkMethodCall(x.asNumValue, m, IndexedSeq(y)) + + case Def(ApplyBinOp(IsArithOp(opCode), xSym, ySym)) => val Seq(x, y) = Seq(xSym, ySym).map(recurse) mkArith(x.asNumValue, y.asNumValue, opCode) diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/primitives/NumericOps.scala b/sc/shared/src/main/scala/sigma/compiler/ir/primitives/NumericOps.scala index a9f0c0a3fa..6c77b02fdf 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/primitives/NumericOps.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/primitives/NumericOps.scala @@ -47,6 +47,11 @@ trait NumericOps extends Base { self: IRContext => override def applySeq(x: T, y: T): T = n.times(x, y) } + /** Descriptor of unary `ToBits` conversion operation. */ + case class NumericBitwiseOr[T: Elem](n: ExactNumeric[T]) extends EndoBinOp[T]("|") { + override def applySeq(x: T, y: T): T = n.bitwiseOr(x, y) + } + /** Base class for descriptors of binary division operations. */ abstract class DivOp[T: Elem](opName: String, n: ExactIntegral[T]) extends EndoBinOp[T](opName) { override def shouldPropagate(lhs: T, rhs: T) = rhs != n.zero diff --git a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala index c9e05f5226..b87121e4e4 100644 --- a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala @@ -209,7 +209,7 @@ class BasicOpsSpecification extends CompilerTestingCommons property("Byte.bitwiseInverse") { def bitwiseInverseTest(): Assertion = test("Byte.bitwiseInverse", env, ext, s"""{ - | val b = 127.toByte + | val b = (126 + 1).toByte // max byte value | b.bitwiseInverse == (-128).toByte |}""".stripMargin, null @@ -239,6 +239,39 @@ class BasicOpsSpecification extends CompilerTestingCommons } } + property("Byte.bitwiseOr") { + def bitwiseOrTest(): Assertion = test("Byte.bitwiseOrTest", env, ext, + s"""{ + | val x = 127.toByte + | val y = (-128).toByte + | x.bitwiseOr(y) == -1 + |}""".stripMargin, + null + ) + + if (VersionContext.current.isV6SoftForkActivated) { + bitwiseOrTest() + } else { + an[Exception] shouldBe thrownBy(bitwiseOrTest()) + } + } + + property("BigInt.bitwiseOr") { + def bitwiseInverseTest(): Assertion = test("BigInt.bitwiseInverse", env, ext, + s"""{ + | val x = bigInt("${CryptoConstants.groupOrder.divide(new BigInteger("2"))}") + | x.bitwiseOr(x) == x + |}""".stripMargin, + null + ) + + if (VersionContext.current.isV6SoftForkActivated) { + bitwiseInverseTest() + } else { + an[Exception] shouldBe thrownBy(bitwiseInverseTest()) + } + } + property("Unit register") { // TODO frontend: implement missing Unit support in compiler // https://github.com/ScorexFoundation/sigmastate-interpreter/issues/820 From 868fbb10c43626faec175698bf94e8f1b9dc3908 Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Wed, 10 Jul 2024 15:24:19 +0300 Subject: [PATCH 180/314] bitwiseAnd --- .../src/main/scala/sigma/ast/methods.scala | 17 ++++---- .../main/scala/sigma/data/BigIntegerOps.scala | 2 + .../main/scala/sigma/data/ExactIntegral.scala | 4 ++ .../main/scala/sigma/data/ExactNumeric.scala | 2 + .../sigma/compiler/ir/GraphBuilding.scala | 4 ++ .../sigma/compiler/ir/TreeBuilding.scala | 6 +++ .../compiler/ir/primitives/NumericOps.scala | 4 ++ .../utxo/BasicOpsSpecification.scala | 41 +++++++++++++++++-- 8 files changed, 69 insertions(+), 11 deletions(-) diff --git a/data/shared/src/main/scala/sigma/ast/methods.scala b/data/shared/src/main/scala/sigma/ast/methods.scala index ade482c168..003b9923e0 100644 --- a/data/shared/src/main/scala/sigma/ast/methods.scala +++ b/data/shared/src/main/scala/sigma/ast/methods.scala @@ -311,15 +311,15 @@ object SNumericTypeMethods extends MethodsContainer { """.stripMargin) val BitwiseAndMethod: SMethod = SMethod( - this, "bitwiseInverse", SFunc(tNum, tNum), 10, BitwiseInverse_CostKind) + this, "bitwiseAnd", SFunc(Array(tNum, tNum), tNum), 10, BitwiseInverse_CostKind) .withIRInfo(MethodCallIrBuilder) - .withUserDefinedInvoke({ (m: SMethod, obj: Any, _: Array[Any]) => + .withUserDefinedInvoke({ (m: SMethod, obj: Any, other: Array[Any]) => m.objType match { - case SByteMethods => ByteIsExactIntegral.bitwiseInverse(obj.asInstanceOf[Byte]) - case SShortMethods => ShortIsExactIntegral.bitwiseInverse(obj.asInstanceOf[Short]) - case SIntMethods => IntIsExactIntegral.bitwiseInverse(obj.asInstanceOf[Int]) - case SLongMethods => LongIsExactIntegral.bitwiseInverse(obj.asInstanceOf[Long]) - case SBigIntMethods => BigIntIsExactIntegral.bitwiseInverse(obj.asInstanceOf[BigInt]) + case SByteMethods => ByteIsExactIntegral.bitwiseAnd(obj.asInstanceOf[Byte], other.head.asInstanceOf[Byte]) + case SShortMethods => ShortIsExactIntegral.bitwiseAnd(obj.asInstanceOf[Short], other.head.asInstanceOf[Short]) + case SIntMethods => IntIsExactIntegral.bitwiseAnd(obj.asInstanceOf[Int], other.head.asInstanceOf[Int]) + case SLongMethods => LongIsExactIntegral.bitwiseAnd(obj.asInstanceOf[Long], other.head.asInstanceOf[Long]) + case SBigIntMethods => BigIntIsExactIntegral.bitwiseAnd(obj.asInstanceOf[BigInt], other.head.asInstanceOf[BigInt]) } }) .withInfo(PropertyCall, @@ -353,7 +353,8 @@ object SNumericTypeMethods extends MethodsContainer { ToBytesMethod, ToBitsMethod, BitwiseInverseMethod, - BitwiseOrMethod + BitwiseOrMethod, + BitwiseAndMethod ) /** Collection of names of numeric casting methods (like `toByte`, `toInt`, etc). */ diff --git a/data/shared/src/main/scala/sigma/data/BigIntegerOps.scala b/data/shared/src/main/scala/sigma/data/BigIntegerOps.scala index 8a7d597ed0..2aefe1cbc8 100644 --- a/data/shared/src/main/scala/sigma/data/BigIntegerOps.scala +++ b/data/shared/src/main/scala/sigma/data/BigIntegerOps.scala @@ -96,6 +96,8 @@ object NumericOps { override def bitwiseInverse(x: BigInt): BigInt = CBigInt(x.toBigInteger.not()) def bitwiseOr(x: BigInt, y: BigInt): BigInt = CBigInt(x.toBigInteger.or(y.toBigInteger)) + + def bitwiseAnd(x: BigInt, y: BigInt): BigInt = CBigInt(x.toBigInteger.and(y.toBigInteger)) } /** The instance of [[scalan.ExactOrdering]] typeclass for [[BigInt]]. */ diff --git a/data/shared/src/main/scala/sigma/data/ExactIntegral.scala b/data/shared/src/main/scala/sigma/data/ExactIntegral.scala index 787800a14a..490890e21a 100644 --- a/data/shared/src/main/scala/sigma/data/ExactIntegral.scala +++ b/data/shared/src/main/scala/sigma/data/ExactIntegral.scala @@ -41,6 +41,7 @@ object ExactIntegral { override def toBigEndianBytes(x: Byte): Coll[Byte] = Colls.fromItems(x) override def bitwiseInverse(x: Byte): Byte = (~x).toByte override def bitwiseOr(x: Byte, y: Byte): Byte = (x | y).toByte + override def bitwiseAnd(x: Byte, y: Byte): Byte = (x & y).toByte } implicit object ShortIsExactIntegral extends ExactIntegral[Short] { @@ -51,6 +52,7 @@ object ExactIntegral { override def toBigEndianBytes(x: Short): Coll[Byte] = Colls.fromItems((x >> 8).toByte, x.toByte) override def bitwiseInverse(x: Short): Short = (~x).toShort override def bitwiseOr(x: Short, y: Short): Short = (x | y).toShort + override def bitwiseAnd(x: Short, y: Short): Short = (x & y).toShort } implicit object IntIsExactIntegral extends ExactIntegral[Int] { @@ -62,6 +64,7 @@ object ExactIntegral { Colls.fromItems((x >> 24).toByte, (x >> 16).toByte, (x >> 8).toByte, x.toByte) override def bitwiseInverse(x: Int): Int = ~x override def bitwiseOr(x: Int, y: Int): Int = x | y + override def bitwiseAnd(x: Int, y: Int): Int = x & y } implicit object LongIsExactIntegral extends ExactIntegral[Long] { @@ -73,5 +76,6 @@ object ExactIntegral { Colls.fromItems((x >> 56).toByte, (x >> 48).toByte, (x >> 40).toByte, (x >> 32).toByte, (x >> 24).toByte, (x >> 16).toByte, (x >> 8).toByte, x.toByte) override def bitwiseInverse(x: Long): Long = ~x override def bitwiseOr(x: Long, y: Long): Long = x | y + override def bitwiseAnd(x: Long, y: Long): Long = x & y } } diff --git a/data/shared/src/main/scala/sigma/data/ExactNumeric.scala b/data/shared/src/main/scala/sigma/data/ExactNumeric.scala index 8328ac4143..116599ba9b 100644 --- a/data/shared/src/main/scala/sigma/data/ExactNumeric.scala +++ b/data/shared/src/main/scala/sigma/data/ExactNumeric.scala @@ -58,6 +58,8 @@ trait ExactNumeric[T] { def bitwiseOr(x: T, y: T): T + def bitwiseAnd(x: T, y: T): T + /** A value of type T which corresponds to integer 0. */ lazy val zero: T = fromInt(0) 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 cfa67f40a4..1c467fada8 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/GraphBuilding.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/GraphBuilding.scala @@ -1163,6 +1163,10 @@ trait GraphBuilding extends Base with DefRewriting { IR: IRContext => val y = asRep[tNum](argsV(0)) val op = NumericBitwiseOr(elemToExactNumeric(x.elem))(x.elem) ApplyBinOp(op, x, y) + case SNumericTypeMethods.BitwiseAndMethod.name => + val y = asRep[tNum](argsV(0)) + val op = NumericBitwiseAnd(elemToExactNumeric(x.elem))(x.elem) + ApplyBinOp(op, x, y) case _ => throwError() } case _ => throwError(s"Type ${stypeToRType(obj.tpe).name} doesn't have methods") diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/TreeBuilding.scala b/sc/shared/src/main/scala/sigma/compiler/ir/TreeBuilding.scala index 9fa4f80208..e79fb56a2e 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/TreeBuilding.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/TreeBuilding.scala @@ -223,6 +223,12 @@ trait TreeBuilding extends Base { IR: IRContext => val m = SMethod.fromIds(receiverType.typeId, SNumericTypeMethods.BitwiseOrMethod.methodId) builder.mkMethodCall(x.asNumValue, m, IndexedSeq(y)) + case Def(ApplyBinOp(op, xSym, ySym)) if op.isInstanceOf[NumericBitwiseAnd[_]] => + val Seq(x, y) = Seq(xSym, ySym).map(recurse) + val receiverType = x.asNumValue.tpe.asNumTypeOrElse(error(s"Expected numeric type, got: ${x.tpe}")) + val m = SMethod.fromIds(receiverType.typeId, SNumericTypeMethods.BitwiseAndMethod.methodId) + builder.mkMethodCall(x.asNumValue, m, IndexedSeq(y)) + case Def(ApplyBinOp(IsArithOp(opCode), xSym, ySym)) => val Seq(x, y) = Seq(xSym, ySym).map(recurse) diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/primitives/NumericOps.scala b/sc/shared/src/main/scala/sigma/compiler/ir/primitives/NumericOps.scala index 6c77b02fdf..13766b17b7 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/primitives/NumericOps.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/primitives/NumericOps.scala @@ -52,6 +52,10 @@ trait NumericOps extends Base { self: IRContext => override def applySeq(x: T, y: T): T = n.bitwiseOr(x, y) } + case class NumericBitwiseAnd[T: Elem](n: ExactNumeric[T]) extends EndoBinOp[T]("|") { + override def applySeq(x: T, y: T): T = n.bitwiseAnd(x, y) + } + /** Base class for descriptors of binary division operations. */ abstract class DivOp[T: Elem](opName: String, n: ExactIntegral[T]) extends EndoBinOp[T](opName) { override def shouldPropagate(lhs: T, rhs: T) = rhs != n.zero diff --git a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala index b87121e4e4..0987b84835 100644 --- a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala @@ -257,7 +257,7 @@ class BasicOpsSpecification extends CompilerTestingCommons } property("BigInt.bitwiseOr") { - def bitwiseInverseTest(): Assertion = test("BigInt.bitwiseInverse", env, ext, + def bitwiseOrTest(): Assertion = test("BigInt.bitwiseOr", env, ext, s"""{ | val x = bigInt("${CryptoConstants.groupOrder.divide(new BigInteger("2"))}") | x.bitwiseOr(x) == x @@ -266,9 +266,44 @@ class BasicOpsSpecification extends CompilerTestingCommons ) if (VersionContext.current.isV6SoftForkActivated) { - bitwiseInverseTest() + bitwiseOrTest() } else { - an[Exception] shouldBe thrownBy(bitwiseInverseTest()) + an[Exception] shouldBe thrownBy(bitwiseOrTest()) + } + } + + property("BigInt.bitwiseAnd") { + def bitwiseAndTest(): Assertion = test("BigInt.bitwiseAnd", env, ext, + s"""{ + | val x = bigInt("${CryptoConstants.groupOrder.divide(new BigInteger("2"))}") + | val y = 0.toBigInt + | x.bitwiseAnd(y) == y + |}""".stripMargin, + null + ) + + if (VersionContext.current.isV6SoftForkActivated) { + bitwiseAndTest() + } else { + an[Exception] shouldBe thrownBy(bitwiseAndTest()) + } + } + + + property("Short.bitwiseAnd") { + def bitwiseAndTest(): Assertion = test("BigInt.bitwiseAnd", env, ext, + s"""{ + | val x = (32767).toShort + | val y = (-32768).toShort + | x.bitwiseAnd(y) == 0 + |}""".stripMargin, + null + ) + + if (VersionContext.current.isV6SoftForkActivated) { + bitwiseAndTest() + } else { + an[Exception] shouldBe thrownBy(bitwiseAndTest()) } } From f21436d390d197cd12666cf943c2f8ef7e38a296 Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Wed, 10 Jul 2024 15:37:29 +0300 Subject: [PATCH 181/314] bitwiseXor --- .../src/main/scala/sigma/ast/methods.scala | 18 +++++++++-------- .../main/scala/sigma/data/BigIntegerOps.scala | 2 ++ .../main/scala/sigma/data/ExactIntegral.scala | 4 ++++ .../main/scala/sigma/data/ExactNumeric.scala | 2 ++ .../sigma/compiler/ir/GraphBuilding.scala | 4 ++++ .../sigma/compiler/ir/TreeBuilding.scala | 6 ++++++ .../compiler/ir/primitives/NumericOps.scala | 6 +++++- .../utxo/BasicOpsSpecification.scala | 20 +++++++++++++++++-- 8 files changed, 51 insertions(+), 11 deletions(-) diff --git a/data/shared/src/main/scala/sigma/ast/methods.scala b/data/shared/src/main/scala/sigma/ast/methods.scala index 003b9923e0..0992788124 100644 --- a/data/shared/src/main/scala/sigma/ast/methods.scala +++ b/data/shared/src/main/scala/sigma/ast/methods.scala @@ -5,6 +5,7 @@ import org.ergoplatform.validation._ import sigma._ import sigma.ast.SCollection.{SBooleanArray, SBoxArray, SByteArray, SByteArray2, SHeaderArray} import sigma.ast.SMethod.{MethodCallIrBuilder, MethodCostFunc, javaMethodOf} +import sigma.ast.SNumericTypeMethods.BitwiseAndMethod import sigma.ast.SType.TypeCode import sigma.ast.syntax.{SValue, ValueOps} import sigma.data.ExactIntegral.{ByteIsExactIntegral, IntIsExactIntegral, LongIsExactIntegral, ShortIsExactIntegral} @@ -328,15 +329,15 @@ object SNumericTypeMethods extends MethodsContainer { """.stripMargin) val BitwiseXorMethod: SMethod = SMethod( - this, "bitwiseInverse", SFunc(tNum, tNum), 11, BitwiseInverse_CostKind) + this, "bitwiseXor", SFunc(Array(tNum, tNum), tNum), 11, BitwiseInverse_CostKind) .withIRInfo(MethodCallIrBuilder) - .withUserDefinedInvoke({ (m: SMethod, obj: Any, _: Array[Any]) => + .withUserDefinedInvoke({ (m: SMethod, obj: Any, other: Array[Any]) => m.objType match { - case SByteMethods => ByteIsExactIntegral.bitwiseInverse(obj.asInstanceOf[Byte]) - case SShortMethods => ShortIsExactIntegral.bitwiseInverse(obj.asInstanceOf[Short]) - case SIntMethods => IntIsExactIntegral.bitwiseInverse(obj.asInstanceOf[Int]) - case SLongMethods => LongIsExactIntegral.bitwiseInverse(obj.asInstanceOf[Long]) - case SBigIntMethods => BigIntIsExactIntegral.bitwiseInverse(obj.asInstanceOf[BigInt]) + case SByteMethods => ByteIsExactIntegral.bitwiseXor(obj.asInstanceOf[Byte], other.head.asInstanceOf[Byte]) + case SShortMethods => ShortIsExactIntegral.bitwiseXor(obj.asInstanceOf[Short], other.head.asInstanceOf[Short]) + case SIntMethods => IntIsExactIntegral.bitwiseXor(obj.asInstanceOf[Int], other.head.asInstanceOf[Int]) + case SLongMethods => LongIsExactIntegral.bitwiseXor(obj.asInstanceOf[Long], other.head.asInstanceOf[Long]) + case SBigIntMethods => BigIntIsExactIntegral.bitwiseXor(obj.asInstanceOf[BigInt], other.head.asInstanceOf[BigInt]) } }) .withInfo(PropertyCall, @@ -354,7 +355,8 @@ object SNumericTypeMethods extends MethodsContainer { ToBitsMethod, BitwiseInverseMethod, BitwiseOrMethod, - BitwiseAndMethod + BitwiseAndMethod, + BitwiseXorMethod ) /** Collection of names of numeric casting methods (like `toByte`, `toInt`, etc). */ diff --git a/data/shared/src/main/scala/sigma/data/BigIntegerOps.scala b/data/shared/src/main/scala/sigma/data/BigIntegerOps.scala index 2aefe1cbc8..9b50469883 100644 --- a/data/shared/src/main/scala/sigma/data/BigIntegerOps.scala +++ b/data/shared/src/main/scala/sigma/data/BigIntegerOps.scala @@ -98,6 +98,8 @@ object NumericOps { def bitwiseOr(x: BigInt, y: BigInt): BigInt = CBigInt(x.toBigInteger.or(y.toBigInteger)) def bitwiseAnd(x: BigInt, y: BigInt): BigInt = CBigInt(x.toBigInteger.and(y.toBigInteger)) + + def bitwiseXor(x: BigInt, y: BigInt): BigInt = CBigInt(x.toBigInteger.xor(y.toBigInteger)) } /** The instance of [[scalan.ExactOrdering]] typeclass for [[BigInt]]. */ diff --git a/data/shared/src/main/scala/sigma/data/ExactIntegral.scala b/data/shared/src/main/scala/sigma/data/ExactIntegral.scala index 490890e21a..58d600d987 100644 --- a/data/shared/src/main/scala/sigma/data/ExactIntegral.scala +++ b/data/shared/src/main/scala/sigma/data/ExactIntegral.scala @@ -42,6 +42,7 @@ object ExactIntegral { override def bitwiseInverse(x: Byte): Byte = (~x).toByte override def bitwiseOr(x: Byte, y: Byte): Byte = (x | y).toByte override def bitwiseAnd(x: Byte, y: Byte): Byte = (x & y).toByte + override def bitwiseXor(x: Byte, y: Byte): Byte = (x ^ y).toByte } implicit object ShortIsExactIntegral extends ExactIntegral[Short] { @@ -53,6 +54,7 @@ object ExactIntegral { override def bitwiseInverse(x: Short): Short = (~x).toShort override def bitwiseOr(x: Short, y: Short): Short = (x | y).toShort override def bitwiseAnd(x: Short, y: Short): Short = (x & y).toShort + override def bitwiseXor(x: Short, y: Short): Short = (x ^ y).toShort } implicit object IntIsExactIntegral extends ExactIntegral[Int] { @@ -65,6 +67,7 @@ object ExactIntegral { override def bitwiseInverse(x: Int): Int = ~x override def bitwiseOr(x: Int, y: Int): Int = x | y override def bitwiseAnd(x: Int, y: Int): Int = x & y + override def bitwiseXor(x: Int, y: Int): Int = x ^ y } implicit object LongIsExactIntegral extends ExactIntegral[Long] { @@ -77,5 +80,6 @@ object ExactIntegral { override def bitwiseInverse(x: Long): Long = ~x override def bitwiseOr(x: Long, y: Long): Long = x | y override def bitwiseAnd(x: Long, y: Long): Long = x & y + override def bitwiseXor(x: Long, y: Long): Long = x ^ y } } diff --git a/data/shared/src/main/scala/sigma/data/ExactNumeric.scala b/data/shared/src/main/scala/sigma/data/ExactNumeric.scala index 116599ba9b..c9903028db 100644 --- a/data/shared/src/main/scala/sigma/data/ExactNumeric.scala +++ b/data/shared/src/main/scala/sigma/data/ExactNumeric.scala @@ -60,6 +60,8 @@ trait ExactNumeric[T] { def bitwiseAnd(x: T, y: T): T + def bitwiseXor(x: T, y: T): T + /** A value of type T which corresponds to integer 0. */ lazy val zero: T = fromInt(0) 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 1c467fada8..fa1e6fb8e4 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/GraphBuilding.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/GraphBuilding.scala @@ -1167,6 +1167,10 @@ trait GraphBuilding extends Base with DefRewriting { IR: IRContext => val y = asRep[tNum](argsV(0)) val op = NumericBitwiseAnd(elemToExactNumeric(x.elem))(x.elem) ApplyBinOp(op, x, y) + case SNumericTypeMethods.BitwiseXorMethod.name => + val y = asRep[tNum](argsV(0)) + val op = NumericBitwiseXor(elemToExactNumeric(x.elem))(x.elem) + ApplyBinOp(op, x, y) case _ => throwError() } case _ => throwError(s"Type ${stypeToRType(obj.tpe).name} doesn't have methods") diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/TreeBuilding.scala b/sc/shared/src/main/scala/sigma/compiler/ir/TreeBuilding.scala index e79fb56a2e..c0f38b6801 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/TreeBuilding.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/TreeBuilding.scala @@ -229,6 +229,12 @@ trait TreeBuilding extends Base { IR: IRContext => val m = SMethod.fromIds(receiverType.typeId, SNumericTypeMethods.BitwiseAndMethod.methodId) builder.mkMethodCall(x.asNumValue, m, IndexedSeq(y)) + case Def(ApplyBinOp(op, xSym, ySym)) if op.isInstanceOf[NumericBitwiseXor[_]] => + val Seq(x, y) = Seq(xSym, ySym).map(recurse) + val receiverType = x.asNumValue.tpe.asNumTypeOrElse(error(s"Expected numeric type, got: ${x.tpe}")) + val m = SMethod.fromIds(receiverType.typeId, SNumericTypeMethods.BitwiseXorMethod.methodId) + builder.mkMethodCall(x.asNumValue, m, IndexedSeq(y)) + case Def(ApplyBinOp(IsArithOp(opCode), xSym, ySym)) => val Seq(x, y) = Seq(xSym, ySym).map(recurse) diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/primitives/NumericOps.scala b/sc/shared/src/main/scala/sigma/compiler/ir/primitives/NumericOps.scala index 13766b17b7..11f7c6a195 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/primitives/NumericOps.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/primitives/NumericOps.scala @@ -52,10 +52,14 @@ trait NumericOps extends Base { self: IRContext => override def applySeq(x: T, y: T): T = n.bitwiseOr(x, y) } - case class NumericBitwiseAnd[T: Elem](n: ExactNumeric[T]) extends EndoBinOp[T]("|") { + case class NumericBitwiseAnd[T: Elem](n: ExactNumeric[T]) extends EndoBinOp[T]("&") { override def applySeq(x: T, y: T): T = n.bitwiseAnd(x, y) } + case class NumericBitwiseXor[T: Elem](n: ExactNumeric[T]) extends EndoBinOp[T]("^") { + override def applySeq(x: T, y: T): T = n.bitwiseXor(x, y) + } + /** Base class for descriptors of binary division operations. */ abstract class DivOp[T: Elem](opName: String, n: ExactIntegral[T]) extends EndoBinOp[T](opName) { override def shouldPropagate(lhs: T, rhs: T) = rhs != n.zero diff --git a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala index 0987b84835..e4279f05bc 100644 --- a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala @@ -289,9 +289,8 @@ class BasicOpsSpecification extends CompilerTestingCommons } } - property("Short.bitwiseAnd") { - def bitwiseAndTest(): Assertion = test("BigInt.bitwiseAnd", env, ext, + def bitwiseAndTest(): Assertion = test("Short.bitwiseAnd", env, ext, s"""{ | val x = (32767).toShort | val y = (-32768).toShort @@ -307,6 +306,23 @@ class BasicOpsSpecification extends CompilerTestingCommons } } + property("Short.bitwiseXor") { + def bitwiseXorTest(): Assertion = test("Short.bitwiseXor", env, ext, + s"""{ + | val x = (32767).toShort + | val y = (-32768).toShort + | x.bitwiseXor(y) == -1 + |}""".stripMargin, + null + ) + + if (VersionContext.current.isV6SoftForkActivated) { + bitwiseXorTest() + } else { + an[Exception] shouldBe thrownBy(bitwiseXorTest()) + } + } + property("Unit register") { // TODO frontend: implement missing Unit support in compiler // https://github.com/ScorexFoundation/sigmastate-interpreter/issues/820 From ced229f60e5d1adf9a731d275fc554efd282951e Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Thu, 11 Jul 2024 15:38:49 +0300 Subject: [PATCH 182/314] shiftLeft --- .../src/main/scala/sigma/SigmaDsl.scala | 4 ++ .../src/main/scala/sigma/data/CBigInt.scala | 4 ++ .../src/main/scala/sigma/ast/methods.scala | 37 +++++++++- .../main/scala/sigma/data/BigIntegerOps.scala | 8 ++- .../main/scala/sigma/data/ExactIntegral.scala | 4 ++ .../main/scala/sigma/data/ExactNumeric.scala | 2 + .../sigma/compiler/ir/GraphBuilding.scala | 4 ++ .../sigma/compiler/ir/TreeBuilding.scala | 6 ++ .../compiler/ir/primitives/NumericOps.scala | 4 ++ .../compiler/ir/primitives/UnBinOps.scala | 35 ++++++++++ .../utxo/BasicOpsSpecification.scala | 67 +++++++++++++++++++ 11 files changed, 171 insertions(+), 4 deletions(-) diff --git a/core/shared/src/main/scala/sigma/SigmaDsl.scala b/core/shared/src/main/scala/sigma/SigmaDsl.scala index df2b419273..806d72c908 100644 --- a/core/shared/src/main/scala/sigma/SigmaDsl.scala +++ b/core/shared/src/main/scala/sigma/SigmaDsl.scala @@ -154,6 +154,10 @@ trait BigInt { */ def or(that: BigInt): BigInt def |(that: BigInt): BigInt = or(that) + + def xor(that: BigInt): BigInt + + def shiftLeft(bits: Int): BigInt } /** Base class for points on elliptic curves. */ diff --git a/core/shared/src/main/scala/sigma/data/CBigInt.scala b/core/shared/src/main/scala/sigma/data/CBigInt.scala index bbf1a85e46..a22bebbf5b 100644 --- a/core/shared/src/main/scala/sigma/data/CBigInt.scala +++ b/core/shared/src/main/scala/sigma/data/CBigInt.scala @@ -49,4 +49,8 @@ case class CBigInt(override val wrappedValue: BigInteger) extends BigInt with Wr override def and(that: BigInt): BigInt = CBigInt(wrappedValue.and(that.asInstanceOf[CBigInt].wrappedValue)) override def or(that: BigInt): BigInt = CBigInt(wrappedValue.or(that.asInstanceOf[CBigInt].wrappedValue)) + + override def xor(that: BigInt): BigInt = CBigInt(wrappedValue.xor(that.asInstanceOf[CBigInt].wrappedValue)) + + def shiftLeft(bits: Int): BigInt = CBigInt(wrappedValue.shiftLeft(bits).to256BitValueExact) } diff --git a/data/shared/src/main/scala/sigma/ast/methods.scala b/data/shared/src/main/scala/sigma/ast/methods.scala index 0992788124..5d21ff1d23 100644 --- a/data/shared/src/main/scala/sigma/ast/methods.scala +++ b/data/shared/src/main/scala/sigma/ast/methods.scala @@ -345,6 +345,40 @@ object SNumericTypeMethods extends MethodsContainer { | Each boolean corresponds to one bit. """.stripMargin) + val ShiftLeftMethod: SMethod = SMethod( + this, "shiftLeft", SFunc(Array(tNum, SInt), tNum), 12, BitwiseInverse_CostKind) + .withIRInfo(MethodCallIrBuilder) + .withUserDefinedInvoke({ (m: SMethod, obj: Any, other: Array[Any]) => + m.objType match { + case SByteMethods => ByteIsExactIntegral.shiftLeft(obj.asInstanceOf[Byte], other.head.asInstanceOf[Int]) + case SShortMethods => ShortIsExactIntegral.shiftLeft(obj.asInstanceOf[Short], other.head.asInstanceOf[Int]) + case SIntMethods => IntIsExactIntegral.shiftLeft(obj.asInstanceOf[Int], other.head.asInstanceOf[Int]) + case SLongMethods => LongIsExactIntegral.shiftLeft(obj.asInstanceOf[Long], other.head.asInstanceOf[Int]) + case SBigIntMethods => BigIntIsExactIntegral.shiftLeft(obj.asInstanceOf[BigInt], other.head.asInstanceOf[Int]) + } + }) + .withInfo(PropertyCall, + """ Returns a big-endian representation of this numeric in a collection of Booleans. + | Each boolean corresponds to one bit. + """.stripMargin) + + val ShiftRightMethod: SMethod = SMethod( + this, "shiftRight", SFunc(Array(tNum, tNum), tNum), 13, BitwiseInverse_CostKind) + .withIRInfo(MethodCallIrBuilder) + .withUserDefinedInvoke({ (m: SMethod, obj: Any, other: Array[Any]) => + m.objType match { + case SByteMethods => ByteIsExactIntegral.bitwiseXor(obj.asInstanceOf[Byte], other.head.asInstanceOf[Byte]) + case SShortMethods => ShortIsExactIntegral.bitwiseXor(obj.asInstanceOf[Short], other.head.asInstanceOf[Short]) + case SIntMethods => IntIsExactIntegral.bitwiseXor(obj.asInstanceOf[Int], other.head.asInstanceOf[Int]) + case SLongMethods => LongIsExactIntegral.bitwiseXor(obj.asInstanceOf[Long], other.head.asInstanceOf[Long]) + case SBigIntMethods => BigIntIsExactIntegral.bitwiseXor(obj.asInstanceOf[BigInt], other.head.asInstanceOf[BigInt]) + } + }) + .withInfo(PropertyCall, + """ Returns a big-endian representation of this numeric in a collection of Booleans. + | Each boolean corresponds to one bit. + """.stripMargin) + protected override def getMethods(): Seq[SMethod] = Array( ToByteMethod, // see Downcast ToShortMethod, // see Downcast @@ -356,7 +390,8 @@ object SNumericTypeMethods extends MethodsContainer { BitwiseInverseMethod, BitwiseOrMethod, BitwiseAndMethod, - BitwiseXorMethod + BitwiseXorMethod, + ShiftLeftMethod ) /** Collection of names of numeric casting methods (like `toByte`, `toInt`, etc). */ diff --git a/data/shared/src/main/scala/sigma/data/BigIntegerOps.scala b/data/shared/src/main/scala/sigma/data/BigIntegerOps.scala index 9b50469883..0db7c8fc0b 100644 --- a/data/shared/src/main/scala/sigma/data/BigIntegerOps.scala +++ b/data/shared/src/main/scala/sigma/data/BigIntegerOps.scala @@ -95,11 +95,13 @@ object NumericOps { override def bitwiseInverse(x: BigInt): BigInt = CBigInt(x.toBigInteger.not()) - def bitwiseOr(x: BigInt, y: BigInt): BigInt = CBigInt(x.toBigInteger.or(y.toBigInteger)) + override def bitwiseOr(x: BigInt, y: BigInt): BigInt = x.or(y) - def bitwiseAnd(x: BigInt, y: BigInt): BigInt = CBigInt(x.toBigInteger.and(y.toBigInteger)) + override def bitwiseAnd(x: BigInt, y: BigInt): BigInt = x.and(y) - def bitwiseXor(x: BigInt, y: BigInt): BigInt = CBigInt(x.toBigInteger.xor(y.toBigInteger)) + override def bitwiseXor(x: BigInt, y: BigInt): BigInt = x.xor(y) + + override def shiftLeft(x: BigInt, y: Int): BigInt = x.shiftLeft(y) } /** The instance of [[scalan.ExactOrdering]] typeclass for [[BigInt]]. */ diff --git a/data/shared/src/main/scala/sigma/data/ExactIntegral.scala b/data/shared/src/main/scala/sigma/data/ExactIntegral.scala index 58d600d987..a2aa6575f9 100644 --- a/data/shared/src/main/scala/sigma/data/ExactIntegral.scala +++ b/data/shared/src/main/scala/sigma/data/ExactIntegral.scala @@ -43,6 +43,7 @@ object ExactIntegral { override def bitwiseOr(x: Byte, y: Byte): Byte = (x | y).toByte override def bitwiseAnd(x: Byte, y: Byte): Byte = (x & y).toByte override def bitwiseXor(x: Byte, y: Byte): Byte = (x ^ y).toByte + override def shiftLeft(x: Byte, y: Int): Byte = (x << y).toByte } implicit object ShortIsExactIntegral extends ExactIntegral[Short] { @@ -55,6 +56,7 @@ object ExactIntegral { override def bitwiseOr(x: Short, y: Short): Short = (x | y).toShort override def bitwiseAnd(x: Short, y: Short): Short = (x & y).toShort override def bitwiseXor(x: Short, y: Short): Short = (x ^ y).toShort + override def shiftLeft(x: Short, y: Int): Short = (x << y).toShort } implicit object IntIsExactIntegral extends ExactIntegral[Int] { @@ -68,6 +70,7 @@ object ExactIntegral { override def bitwiseOr(x: Int, y: Int): Int = x | y override def bitwiseAnd(x: Int, y: Int): Int = x & y override def bitwiseXor(x: Int, y: Int): Int = x ^ y + override def shiftLeft(x: Int, y: Int): Int = x << y } implicit object LongIsExactIntegral extends ExactIntegral[Long] { @@ -81,5 +84,6 @@ object ExactIntegral { override def bitwiseOr(x: Long, y: Long): Long = x | y override def bitwiseAnd(x: Long, y: Long): Long = x & y override def bitwiseXor(x: Long, y: Long): Long = x ^ y + override def shiftLeft(x: Long, y: Int): Long = x << y } } diff --git a/data/shared/src/main/scala/sigma/data/ExactNumeric.scala b/data/shared/src/main/scala/sigma/data/ExactNumeric.scala index c9903028db..0c105c5825 100644 --- a/data/shared/src/main/scala/sigma/data/ExactNumeric.scala +++ b/data/shared/src/main/scala/sigma/data/ExactNumeric.scala @@ -62,6 +62,8 @@ trait ExactNumeric[T] { def bitwiseXor(x: T, y: T): T + def shiftLeft(x: T, y: Int): T + /** A value of type T which corresponds to integer 0. */ lazy val zero: T = fromInt(0) 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 fa1e6fb8e4..6496198075 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/GraphBuilding.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/GraphBuilding.scala @@ -1171,6 +1171,10 @@ trait GraphBuilding extends Base with DefRewriting { IR: IRContext => val y = asRep[tNum](argsV(0)) val op = NumericBitwiseXor(elemToExactNumeric(x.elem))(x.elem) ApplyBinOp(op, x, y) + case SNumericTypeMethods.ShiftLeftMethod.name => + val y = asRep[Int](argsV(0)) + val op = NumericShiftLeft(elemToExactNumeric(x.elem))(x.elem) + ApplyBinOpDiffArgs(op, x, y) case _ => throwError() } case _ => throwError(s"Type ${stypeToRType(obj.tpe).name} doesn't have methods") diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/TreeBuilding.scala b/sc/shared/src/main/scala/sigma/compiler/ir/TreeBuilding.scala index c0f38b6801..1a7621a739 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/TreeBuilding.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/TreeBuilding.scala @@ -235,6 +235,12 @@ trait TreeBuilding extends Base { IR: IRContext => val m = SMethod.fromIds(receiverType.typeId, SNumericTypeMethods.BitwiseXorMethod.methodId) builder.mkMethodCall(x.asNumValue, m, IndexedSeq(y)) + case Def(ApplyBinOpDiffArgs(op, xSym, ySym)) if op.isInstanceOf[NumericShiftLeft[_]] => + val Seq(x, y) = Seq(xSym, ySym).map(recurse) + val receiverType = x.asNumValue.tpe.asNumTypeOrElse(error(s"Expected numeric type, got: ${x.tpe}")) + val m = SMethod.fromIds(receiverType.typeId, SNumericTypeMethods.ShiftLeftMethod.methodId) + builder.mkMethodCall(x.asNumValue, m, IndexedSeq(y)) + case Def(ApplyBinOp(IsArithOp(opCode), xSym, ySym)) => val Seq(x, y) = Seq(xSym, ySym).map(recurse) diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/primitives/NumericOps.scala b/sc/shared/src/main/scala/sigma/compiler/ir/primitives/NumericOps.scala index 11f7c6a195..d8c495220a 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/primitives/NumericOps.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/primitives/NumericOps.scala @@ -60,6 +60,10 @@ trait NumericOps extends Base { self: IRContext => override def applySeq(x: T, y: T): T = n.bitwiseXor(x, y) } + case class NumericShiftLeft[T: Elem](n: ExactNumeric[T]) extends BinDiffArgsOp[T, Int]("<<") { + override def applySeq(x: T, y: Int): T = n.shiftLeft(x, y) + } + /** Base class for descriptors of binary division operations. */ abstract class DivOp[T: Elem](opName: String, n: ExactIntegral[T]) extends EndoBinOp[T](opName) { override def shouldPropagate(lhs: T, rhs: T) = rhs != n.zero diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/primitives/UnBinOps.scala b/sc/shared/src/main/scala/sigma/compiler/ir/primitives/UnBinOps.scala index 23f8bc3800..62bfc29f68 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/primitives/UnBinOps.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/primitives/UnBinOps.scala @@ -45,6 +45,29 @@ trait UnBinOps extends Base { self: IRContext => def shouldPropagate(lhs: A, rhs: A) = true } + abstract class BinDiffArgsOp[A, B](val opName: String)(implicit val eResult: Elem[A]) { + override def toString = opName + + /** Called as part of graph interpretation to execute the given binary operation. + * @param x operation argument + * @param y operation argument + * @return result of applying this operation to (x, y) + */ + def applySeq(x: A, y: B): A + + /** Builds a new graph node by applying this operation to the given arguments. */ + def apply(lhs: Ref[A], rhs: Ref[B]) = ApplyBinOpDiffArgs(this, lhs, rhs) + + /** Builds a new graph node by applying this operation to the given arguments. + * This is a short-cuting (aka lazy) version of the operation, where the lazyness is + * represented by Thunk. + */ + def applyLazy(lhs: Ref[A], rhs: Ref[Thunk[B]]) = ApplyBinOpDiffArgsLazy(this, lhs, rhs) + + /** Whether the constants should be propagated through this operations by rewriting. */ + def shouldPropagate(lhs: A, rhs: B) = true + } + type EndoUnOp[A] = UnOp[A, A] type EndoBinOp[A] = BinOp[A, A] @@ -68,6 +91,18 @@ trait UnBinOps extends Base { self: IRContext => override def transform(t: Transformer): Def[R] = ApplyBinOpLazy[A,R](op, t(lhs), t(rhs)) } + /** Graph node which represents application of the given binary operation to the given arguments. */ + case class ApplyBinOpDiffArgsLazy[A, B](op: BinDiffArgsOp[A, B], lhs: Ref[A], rhs: Ref[Thunk[B]]) extends BaseDef[A]()(op.eResult) { + override def toString = s"$lhs $op { $rhs }" + override def transform(t: Transformer): Def[A] = ApplyBinOpDiffArgsLazy[A, B](op, t(lhs), t(rhs)) + } + + /** Graph node which represents application of the given binary operation to the given arguments. */ + case class ApplyBinOpDiffArgs[A, B](op: BinDiffArgsOp[A, B], lhs: Ref[A], rhs: Ref[B]) extends BaseDef[A]()(op.eResult) { + override def toString = s"$op($lhs, $rhs)" + override def transform(t: Transformer): Def[A] = ApplyBinOpDiffArgs[A, B](op, t(lhs), t(rhs)) + } + /** Overridable constructor of an unary operation node. */ def applyUnOp[A, R](op: UnOp[A, R], arg: Ref[A]): Ref[R] = ApplyUnOp(op, arg) diff --git a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala index e4279f05bc..7bd3812443 100644 --- a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala @@ -323,6 +323,73 @@ class BasicOpsSpecification extends CompilerTestingCommons } } + property("Byte.shiftLeft") { + def shiftLeftTest(): Assertion = test("Byte.shiftLeft", env, ext, + s"""{ + | val x = 4.toByte + | val y = 2 + | x.shiftLeft(y) == 16.toByte + |}""".stripMargin, + null + ) + + if (VersionContext.current.isV6SoftForkActivated) { + shiftLeftTest() + } else { + an[Exception] shouldBe thrownBy(shiftLeftTest()) + } + } + + property("Byte.shiftLeft - over limit") { + def shiftLeftTest(): Assertion = test("Byte.shiftLeft2", env, ext, + s"""{ + | val x = 4.toByte + | val y = 2222 + | x.shiftLeft(y) == 0 + |}""".stripMargin, + null + ) + + if (VersionContext.current.isV6SoftForkActivated) { + shiftLeftTest() + } else { + an[Exception] shouldBe thrownBy(shiftLeftTest()) + } + } + + property("BigInt.shiftLeft") { + def shiftLeftTest(): Assertion = test("BigInt.shiftLeft", env, ext, + s"""{ + | val x = bigInt("${CryptoConstants.groupOrder.divide(new BigInteger("8"))}") + | val y = bigInt("${CryptoConstants.groupOrder.divide(new BigInteger("2"))}") + | x.shiftLeft(2) == y + |}""".stripMargin, + null + ) + + if (VersionContext.current.isV6SoftForkActivated) { + shiftLeftTest() + } else { + an[Exception] shouldBe thrownBy(shiftLeftTest()) + } + } + + property("BigInt.shiftLeft over limits") { + def shiftLeftTest(): Assertion = test("BigInt.shiftLeft", env, ext, + s"""{ + | val x = bigInt("${CryptoConstants.groupOrder.divide(new BigInteger("2"))}") + | x.shiftLeft(1) > x + |}""".stripMargin, + null + ) + + if (VersionContext.current.isV6SoftForkActivated) { + an[ArithmeticException] shouldBe thrownBy(shiftLeftTest()) + } else { + an[Exception] shouldBe thrownBy(shiftLeftTest()) + } + } + property("Unit register") { // TODO frontend: implement missing Unit support in compiler // https://github.com/ScorexFoundation/sigmastate-interpreter/issues/820 From 9519ef62c2d7b41163096374a2057c26602905f7 Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Tue, 16 Jul 2024 21:17:28 +0300 Subject: [PATCH 183/314] shiftRight --- .../src/main/scala/sigma/SigmaDsl.scala | 2 + .../src/main/scala/sigma/data/CBigInt.scala | 2 + .../src/main/scala/sigma/ast/methods.scala | 15 ++- .../main/scala/sigma/data/BigIntegerOps.scala | 2 + .../main/scala/sigma/data/ExactIntegral.scala | 9 +- .../main/scala/sigma/data/ExactNumeric.scala | 6 +- .../sigma/compiler/ir/GraphBuilding.scala | 4 + .../sigma/compiler/ir/TreeBuilding.scala | 6 + .../compiler/ir/primitives/NumericOps.scala | 4 + .../utxo/BasicOpsSpecification.scala | 121 ++++++++++++++++++ 10 files changed, 160 insertions(+), 11 deletions(-) diff --git a/core/shared/src/main/scala/sigma/SigmaDsl.scala b/core/shared/src/main/scala/sigma/SigmaDsl.scala index 806d72c908..6ba84374df 100644 --- a/core/shared/src/main/scala/sigma/SigmaDsl.scala +++ b/core/shared/src/main/scala/sigma/SigmaDsl.scala @@ -158,6 +158,8 @@ trait BigInt { def xor(that: BigInt): BigInt def shiftLeft(bits: Int): BigInt + + def shiftRight(bits: Int): BigInt } /** Base class for points on elliptic curves. */ diff --git a/core/shared/src/main/scala/sigma/data/CBigInt.scala b/core/shared/src/main/scala/sigma/data/CBigInt.scala index a22bebbf5b..dbfec02844 100644 --- a/core/shared/src/main/scala/sigma/data/CBigInt.scala +++ b/core/shared/src/main/scala/sigma/data/CBigInt.scala @@ -53,4 +53,6 @@ case class CBigInt(override val wrappedValue: BigInteger) extends BigInt with Wr override def xor(that: BigInt): BigInt = CBigInt(wrappedValue.xor(that.asInstanceOf[CBigInt].wrappedValue)) def shiftLeft(bits: Int): BigInt = CBigInt(wrappedValue.shiftLeft(bits).to256BitValueExact) + + def shiftRight(bits: Int): BigInt = CBigInt(wrappedValue.shiftRight(bits).to256BitValueExact) } diff --git a/data/shared/src/main/scala/sigma/ast/methods.scala b/data/shared/src/main/scala/sigma/ast/methods.scala index 5d21ff1d23..e7bf6a9bda 100644 --- a/data/shared/src/main/scala/sigma/ast/methods.scala +++ b/data/shared/src/main/scala/sigma/ast/methods.scala @@ -363,15 +363,15 @@ object SNumericTypeMethods extends MethodsContainer { """.stripMargin) val ShiftRightMethod: SMethod = SMethod( - this, "shiftRight", SFunc(Array(tNum, tNum), tNum), 13, BitwiseInverse_CostKind) + this, "shiftRight", SFunc(Array(tNum, SInt), tNum), 13, BitwiseInverse_CostKind) .withIRInfo(MethodCallIrBuilder) .withUserDefinedInvoke({ (m: SMethod, obj: Any, other: Array[Any]) => m.objType match { - case SByteMethods => ByteIsExactIntegral.bitwiseXor(obj.asInstanceOf[Byte], other.head.asInstanceOf[Byte]) - case SShortMethods => ShortIsExactIntegral.bitwiseXor(obj.asInstanceOf[Short], other.head.asInstanceOf[Short]) - case SIntMethods => IntIsExactIntegral.bitwiseXor(obj.asInstanceOf[Int], other.head.asInstanceOf[Int]) - case SLongMethods => LongIsExactIntegral.bitwiseXor(obj.asInstanceOf[Long], other.head.asInstanceOf[Long]) - case SBigIntMethods => BigIntIsExactIntegral.bitwiseXor(obj.asInstanceOf[BigInt], other.head.asInstanceOf[BigInt]) + case SByteMethods => ByteIsExactIntegral.shiftRight(obj.asInstanceOf[Byte], other.head.asInstanceOf[Int]) + case SShortMethods => ShortIsExactIntegral.shiftRight(obj.asInstanceOf[Short], other.head.asInstanceOf[Int]) + case SIntMethods => IntIsExactIntegral.shiftRight(obj.asInstanceOf[Int], other.head.asInstanceOf[Int]) + case SLongMethods => LongIsExactIntegral.shiftRight(obj.asInstanceOf[Long], other.head.asInstanceOf[Int]) + case SBigIntMethods => BigIntIsExactIntegral.shiftRight(obj.asInstanceOf[BigInt], other.head.asInstanceOf[Int]) } }) .withInfo(PropertyCall, @@ -391,7 +391,8 @@ object SNumericTypeMethods extends MethodsContainer { BitwiseOrMethod, BitwiseAndMethod, BitwiseXorMethod, - ShiftLeftMethod + ShiftLeftMethod, + ShiftRightMethod ) /** Collection of names of numeric casting methods (like `toByte`, `toInt`, etc). */ diff --git a/data/shared/src/main/scala/sigma/data/BigIntegerOps.scala b/data/shared/src/main/scala/sigma/data/BigIntegerOps.scala index 0db7c8fc0b..2e1d2f62ce 100644 --- a/data/shared/src/main/scala/sigma/data/BigIntegerOps.scala +++ b/data/shared/src/main/scala/sigma/data/BigIntegerOps.scala @@ -102,6 +102,8 @@ object NumericOps { override def bitwiseXor(x: BigInt, y: BigInt): BigInt = x.xor(y) override def shiftLeft(x: BigInt, y: Int): BigInt = x.shiftLeft(y) + + override def shiftRight(x: BigInt, y: Int): BigInt = x.shiftRight(y) } /** The instance of [[scalan.ExactOrdering]] typeclass for [[BigInt]]. */ diff --git a/data/shared/src/main/scala/sigma/data/ExactIntegral.scala b/data/shared/src/main/scala/sigma/data/ExactIntegral.scala index a2aa6575f9..418bc1837b 100644 --- a/data/shared/src/main/scala/sigma/data/ExactIntegral.scala +++ b/data/shared/src/main/scala/sigma/data/ExactIntegral.scala @@ -43,12 +43,14 @@ object ExactIntegral { override def bitwiseOr(x: Byte, y: Byte): Byte = (x | y).toByte override def bitwiseAnd(x: Byte, y: Byte): Byte = (x & y).toByte override def bitwiseXor(x: Byte, y: Byte): Byte = (x ^ y).toByte - override def shiftLeft(x: Byte, y: Int): Byte = (x << y).toByte + override def shiftLeft(x: Byte, bits: Int): Byte = (x << bits).toByte + override def shiftRight(x: Byte, bits: Int): Byte = (x >> bits).toByte } implicit object ShortIsExactIntegral extends ExactIntegral[Short] { val n = scala.math.Numeric.ShortIsIntegral - override def plus(x: Short, y: Short): Short = x.addExact(y) + override def plus(x: Short, y: Short): + Short = x.addExact(y) override def minus(x: Short, y: Short): Short = x.subtractExact(y) override def times(x: Short, y: Short): Short = x.multiplyExact(y) override def toBigEndianBytes(x: Short): Coll[Byte] = Colls.fromItems((x >> 8).toByte, x.toByte) @@ -57,6 +59,7 @@ object ExactIntegral { override def bitwiseAnd(x: Short, y: Short): Short = (x & y).toShort override def bitwiseXor(x: Short, y: Short): Short = (x ^ y).toShort override def shiftLeft(x: Short, y: Int): Short = (x << y).toShort + override def shiftRight(x: Short, bits: Int): Short = (x >> bits).toShort } implicit object IntIsExactIntegral extends ExactIntegral[Int] { @@ -71,6 +74,7 @@ object ExactIntegral { override def bitwiseAnd(x: Int, y: Int): Int = x & y override def bitwiseXor(x: Int, y: Int): Int = x ^ y override def shiftLeft(x: Int, y: Int): Int = x << y + override def shiftRight(x: Int, bits: Int): Int = x >> bits } implicit object LongIsExactIntegral extends ExactIntegral[Long] { @@ -85,5 +89,6 @@ object ExactIntegral { override def bitwiseAnd(x: Long, y: Long): Long = x & y override def bitwiseXor(x: Long, y: Long): Long = x ^ y override def shiftLeft(x: Long, y: Int): Long = x << y + override def shiftRight(x: Long, bits: Int): Long = x >> bits } } diff --git a/data/shared/src/main/scala/sigma/data/ExactNumeric.scala b/data/shared/src/main/scala/sigma/data/ExactNumeric.scala index 0c105c5825..214569e6e5 100644 --- a/data/shared/src/main/scala/sigma/data/ExactNumeric.scala +++ b/data/shared/src/main/scala/sigma/data/ExactNumeric.scala @@ -1,6 +1,6 @@ package sigma.data -import sigma.{Coll, Colls} +import sigma.{BigInt, Coll, Colls} import sigma.data.ExactIntegral._ import scala.collection.mutable @@ -62,7 +62,9 @@ trait ExactNumeric[T] { def bitwiseXor(x: T, y: T): T - def shiftLeft(x: T, y: Int): T + def shiftLeft(x: T, bits: Int): T + + def shiftRight(x: T, bits: Int): T /** A value of type T which corresponds to integer 0. */ lazy val zero: T = fromInt(0) 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 6496198075..af681fdd2e 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/GraphBuilding.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/GraphBuilding.scala @@ -1175,6 +1175,10 @@ trait GraphBuilding extends Base with DefRewriting { IR: IRContext => val y = asRep[Int](argsV(0)) val op = NumericShiftLeft(elemToExactNumeric(x.elem))(x.elem) ApplyBinOpDiffArgs(op, x, y) + case SNumericTypeMethods.ShiftRightMethod.name => + val y = asRep[Int](argsV(0)) + val op = NumericShiftRight(elemToExactNumeric(x.elem))(x.elem) + ApplyBinOpDiffArgs(op, x, y) case _ => throwError() } case _ => throwError(s"Type ${stypeToRType(obj.tpe).name} doesn't have methods") diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/TreeBuilding.scala b/sc/shared/src/main/scala/sigma/compiler/ir/TreeBuilding.scala index 1a7621a739..c218760e24 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/TreeBuilding.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/TreeBuilding.scala @@ -241,6 +241,12 @@ trait TreeBuilding extends Base { IR: IRContext => val m = SMethod.fromIds(receiverType.typeId, SNumericTypeMethods.ShiftLeftMethod.methodId) builder.mkMethodCall(x.asNumValue, m, IndexedSeq(y)) + case Def(ApplyBinOpDiffArgs(op, xSym, ySym)) if op.isInstanceOf[NumericShiftRight[_]] => + val Seq(x, y) = Seq(xSym, ySym).map(recurse) + val receiverType = x.asNumValue.tpe.asNumTypeOrElse(error(s"Expected numeric type, got: ${x.tpe}")) + val m = SMethod.fromIds(receiverType.typeId, SNumericTypeMethods.ShiftRightMethod.methodId) + builder.mkMethodCall(x.asNumValue, m, IndexedSeq(y)) + case Def(ApplyBinOp(IsArithOp(opCode), xSym, ySym)) => val Seq(x, y) = Seq(xSym, ySym).map(recurse) diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/primitives/NumericOps.scala b/sc/shared/src/main/scala/sigma/compiler/ir/primitives/NumericOps.scala index d8c495220a..9a6b372033 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/primitives/NumericOps.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/primitives/NumericOps.scala @@ -64,6 +64,10 @@ trait NumericOps extends Base { self: IRContext => override def applySeq(x: T, y: Int): T = n.shiftLeft(x, y) } + case class NumericShiftRight[T: Elem](n: ExactNumeric[T]) extends BinDiffArgsOp[T, Int](">>") { + override def applySeq(x: T, y: Int): T = n.shiftRight(x, y) + } + /** Base class for descriptors of binary division operations. */ abstract class DivOp[T: Elem](opName: String, n: ExactIntegral[T]) extends EndoBinOp[T](opName) { override def shouldPropagate(lhs: T, rhs: T) = rhs != n.zero diff --git a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala index 7bd3812443..fcd597f7cb 100644 --- a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala @@ -390,6 +390,127 @@ class BasicOpsSpecification extends CompilerTestingCommons } } + property("Byte.shiftRight") { + def shiftRightTest(): Assertion = test("Byte.shiftRight", env, ext, + s"""{ + | val x = 8.toByte + | val y = 2 + | x.shiftRight(y) == 2.toByte + |}""".stripMargin, + null + ) + + if (VersionContext.current.isV6SoftForkActivated) { + shiftRightTest() + } else { + an[Exception] shouldBe thrownBy(shiftRightTest()) + } + } + + property("Byte.shiftRight - neg") { + def shiftRightTest(): Assertion = test("Byte.shiftRight", env, ext, + s"""{ + | val x = (-8).toByte + | val y = 2 + | x.shiftRight(y) == (-2).toByte + |}""".stripMargin, + null + ) + + if (VersionContext.current.isV6SoftForkActivated) { + shiftRightTest() + } else { + an[Exception] shouldBe thrownBy(shiftRightTest()) + } + } + + property("Byte.shiftRight - neg - neg shift") { + def shiftRightTest(): Assertion = test("Byte.shiftRight", env, ext, + s"""{ + | val x = (-8).toByte + | val y = -2 + | x.shiftRight(y) == (-1).toByte + |}""".stripMargin, + null + ) + + if (VersionContext.current.isV6SoftForkActivated) { + shiftRightTest() + } else { + an[Exception] shouldBe thrownBy(shiftRightTest()) + } + } + + property("Long.shiftRight - neg") { + def shiftRightTest(): Assertion = test("Long.shiftRight", env, ext, + s"""{ + | val x = -32L + | val y = 2 + | x.shiftRight(y) == -8L + |}""".stripMargin, + null + ) + + if (VersionContext.current.isV6SoftForkActivated) { + shiftRightTest() + } else { + an[Exception] shouldBe thrownBy(shiftRightTest()) + } + } + + property("Long.shiftRight - neg - neg shift") { + def shiftRightTest(): Assertion = test("Long.shiftRight", env, ext, + s"""{ + | val x = -32L + | val y = -2 + | x.shiftRight(y) == -1L + |}""".stripMargin, + null + ) + + if (VersionContext.current.isV6SoftForkActivated) { + shiftRightTest() + } else { + an[Exception] shouldBe thrownBy(shiftRightTest()) + } + } + + property("BigInt.shiftRight") { + def shiftRightTest(): Assertion = test("BigInt.shiftRight", env, ext, + s"""{ + | val x = bigInt("${CryptoConstants.groupOrder.divide(new BigInteger("2"))}") + | val y = 2 + | val z = bigInt("${CryptoConstants.groupOrder.divide(new BigInteger("8"))}") + | x.shiftRight(y) == z + |}""".stripMargin, + null + ) + + if (VersionContext.current.isV6SoftForkActivated) { + shiftRightTest() + } else { + an[Exception] shouldBe thrownBy(shiftRightTest()) + } + } + + property("BigInt.shiftRight - neg shift") { + def shiftRightTest(): Assertion = test("BigInt.shiftRight", env, ext, + s"""{ + | val x = bigInt("${CryptoConstants.groupOrder.divide(new BigInteger("2"))}") + | val y = -2 + | val z = bigInt("${CryptoConstants.groupOrder.divide(new BigInteger("8"))}") + | z.shiftRight(y) == x + |}""".stripMargin, + null + ) + + if (VersionContext.current.isV6SoftForkActivated) { + shiftRightTest() + } else { + an[Exception] shouldBe thrownBy(shiftRightTest()) + } + } + property("Unit register") { // TODO frontend: implement missing Unit support in compiler // https://github.com/ScorexFoundation/sigmastate-interpreter/issues/820 From fb3e52ea689c234377cffb55642afcb7f3669ee5 Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Wed, 17 Jul 2024 21:05:56 +0300 Subject: [PATCH 184/314] String fix & test --- data/jvm/src/main/scala/sigma/Platform.scala | 5 ++++- .../src/test/scala/sigma/ast/SigmaBuilderTest.scala | 11 ++++++++--- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/data/jvm/src/main/scala/sigma/Platform.scala b/data/jvm/src/main/scala/sigma/Platform.scala index bd39d75ab9..4878b3fb1b 100644 --- a/data/jvm/src/main/scala/sigma/Platform.scala +++ b/data/jvm/src/main/scala/sigma/Platform.scala @@ -31,7 +31,10 @@ object Platform { 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 v: String => Nullable(mkConstant[SString.type](v, SString)) + + // todo: check Header and UnsignedBigInt + + case v: String if !VersionContext.current.isV6SoftForkActivated => 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. diff --git a/interpreter/shared/src/test/scala/sigma/ast/SigmaBuilderTest.scala b/interpreter/shared/src/test/scala/sigma/ast/SigmaBuilderTest.scala index acf8e74bd2..a964c7f662 100644 --- a/interpreter/shared/src/test/scala/sigma/ast/SigmaBuilderTest.scala +++ b/interpreter/shared/src/test/scala/sigma/ast/SigmaBuilderTest.scala @@ -175,9 +175,14 @@ class SigmaBuilderTest extends AnyPropSpec with ScalaCheckPropertyChecks with Ma property("liftToConstant String") { val v = "abc" val c = StringConstant(v) - test[SString.type](v, c) - testArray[SString.type](v, c) // TODO v6.0: String should be liftable at all (not supported in ErgoTree) (see https://github.com/ScorexFoundation/sigmastate-interpreter/issues/905) - testColl[SString.type](v, c) + if (!VersionContext.current.isV6SoftForkActivated) { + // v6.0: String should 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) + testColl[SString.type](v, c) + } else { + testFailure(v) + } } property("liftToConstant BigInteger") { From ec215dfa78093036756dde37e2c022f70c956fe7 Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Wed, 17 Jul 2024 21:25:19 +0300 Subject: [PATCH 185/314] Array fix & test --- data/jvm/src/main/scala/sigma/Platform.scala | 14 +++--- .../scala/sigma/ast/SigmaBuilderTest.scala | 43 ++++++++++++++++--- 2 files changed, 44 insertions(+), 13 deletions(-) diff --git a/data/jvm/src/main/scala/sigma/Platform.scala b/data/jvm/src/main/scala/sigma/Platform.scala index 4878b3fb1b..27e99f2be2 100644 --- a/data/jvm/src/main/scala/sigma/Platform.scala +++ b/data/jvm/src/main/scala/sigma/Platform.scala @@ -16,13 +16,13 @@ object Platform { private[sigma] def liftToConstant(obj: Any, builder: SigmaBuilder): Nullable[Constant[SType]] = { import builder._ obj match { - case arr: Array[Boolean] => Nullable(mkCollectionConstant[SBoolean.type](arr, SBoolean)) - case arr: Array[Byte] => Nullable(mkCollectionConstant[SByte.type](arr, SByte)) - case arr: Array[Short] => Nullable(mkCollectionConstant[SShort.type](arr, SShort)) - case arr: Array[Int] => Nullable(mkCollectionConstant[SInt.type](arr, SInt)) - case arr: Array[Long] => Nullable(mkCollectionConstant[SLong.type](arr, SLong)) - case arr: Array[BigInteger] => Nullable(mkCollectionConstant[SBigInt.type](arr.map(SigmaDsl.BigInt(_)), SBigInt)) - case arr: Array[String] => Nullable(mkCollectionConstant[SString.type](arr, SString)) + 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 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)) diff --git a/interpreter/shared/src/test/scala/sigma/ast/SigmaBuilderTest.scala b/interpreter/shared/src/test/scala/sigma/ast/SigmaBuilderTest.scala index a964c7f662..c8eb17e0ca 100644 --- a/interpreter/shared/src/test/scala/sigma/ast/SigmaBuilderTest.scala +++ b/interpreter/shared/src/test/scala/sigma/ast/SigmaBuilderTest.scala @@ -122,6 +122,13 @@ class SigmaBuilderTest extends AnyPropSpec with ScalaCheckPropertyChecks with Ma testSuccess(arr, TransformingSigmaBuilder.mkCollectionConstant(arr, c.tpe)) } + def testArrayFailure[T <: SType] + (v: T#WrappedType, c: Constant[T])(implicit t: RType[T#WrappedType]) = { + // for any Byte and Short value `v`, lifting of array should succeed + val arr = Array.fill[T#WrappedType](10)(v)(t.classTag) + testFailure(arr) + } + def testColl[T <: SType] (v: T#WrappedType, c: Constant[T])(implicit t: RType[T#WrappedType]) = { // for any Byte and Short value `v`, lifting of Coll should succeed @@ -134,7 +141,11 @@ class SigmaBuilderTest extends AnyPropSpec with ScalaCheckPropertyChecks with Ma val v = true val c = BooleanConstant(v) test[SBoolean.type](v, c) - testArray[SBoolean.type](v, c) // TODO v6.0: arrays should not be liftable directly (see https://github.com/ScorexFoundation/sigmastate-interpreter/issues/905) + if (!VersionContext.current.isV6SoftForkActivated) { + testArray[SBoolean.type](v, c) + } else { + testArrayFailure[SBoolean.type](v, c) + } testColl[SBoolean.type](v, c) } @@ -143,7 +154,11 @@ class SigmaBuilderTest extends AnyPropSpec with ScalaCheckPropertyChecks with Ma val c = ByteConstant(v) testNumeric[SByte.type](v, c) testLiftingOfCAnyValue[SByte.type](v, c) - testArray[SByte.type](v, c) // TODO v6.0: arrays should not be liftable directly (see https://github.com/ScorexFoundation/sigmastate-interpreter/issues/905) + if (!VersionContext.current.isV6SoftForkActivated) { + testArray[SByte.type](v, c) + } else { + testArrayFailure[SByte.type](v, c) + } testColl[SByte.type](v, c) } @@ -152,7 +167,11 @@ class SigmaBuilderTest extends AnyPropSpec with ScalaCheckPropertyChecks with Ma val c = ShortConstant(v) testNumeric[SShort.type](v, c) testLiftingOfCAnyValue[SShort.type](v, c) - testArray[SShort.type](v, c) // TODO v6.0: arrays should not be liftable directly (see https://github.com/ScorexFoundation/sigmastate-interpreter/issues/905) + if (!VersionContext.current.isV6SoftForkActivated) { + testArray[SShort.type](v, c) + } else { + testArrayFailure[SShort.type](v, c) + } testColl[SShort.type](v, c) } @@ -160,7 +179,11 @@ class SigmaBuilderTest extends AnyPropSpec with ScalaCheckPropertyChecks with Ma val v = 1 val c = IntConstant(v) test[SInt.type](v, c) - testArray[SInt.type](v, c) // TODO v6.0: arrays should not be liftable directly (see https://github.com/ScorexFoundation/sigmastate-interpreter/issues/905) + if (!VersionContext.current.isV6SoftForkActivated) { + testArray[SInt.type](v, c) + } else { + testArrayFailure[SInt.type](v, c) + } testColl[SInt.type](v, c) } @@ -168,7 +191,11 @@ class SigmaBuilderTest extends AnyPropSpec with ScalaCheckPropertyChecks with Ma val v = 1L val c = LongConstant(v) test[SLong.type](v, c) - testArray[SLong.type](v, c) // TODO v6.0: arrays should not be liftable directly (see https://github.com/ScorexFoundation/sigmastate-interpreter/issues/905) + if (!VersionContext.current.isV6SoftForkActivated) { + testArray[SLong.type](v, c) + } else { + testArrayFailure[SLong.type](v, c) + } testColl[SLong.type](v, c) } @@ -190,7 +217,11 @@ class SigmaBuilderTest extends AnyPropSpec with ScalaCheckPropertyChecks with Ma val c = BigIntConstant(v) testSuccess(v, c) // TODO v6.0: both BigInteger and arrays should not be liftable directly (see https://github.com/ScorexFoundation/sigmastate-interpreter/issues/905) val arr = Array.fill(10)(v) - testSuccess(arr, TransformingSigmaBuilder.mkCollectionConstant[SBigInt.type](arr.map(SigmaDsl.BigInt), c.tpe)) + if (!VersionContext.current.isV6SoftForkActivated) { + testSuccess(arr, TransformingSigmaBuilder.mkCollectionConstant[SBigInt.type](arr.map(SigmaDsl.BigInt), c.tpe)) + } else { + testFailure(arr) + } } property("liftToConstant BigInt") { From d257b5a0715cb9d37afbc11b3a5c6786df89772c Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Wed, 17 Jul 2024 23:58:09 +0300 Subject: [PATCH 186/314] BigInteger and ErgoBox fix and tests --- data/jvm/src/main/scala/sigma/Platform.scala | 4 ++-- .../src/test/scala/sigma/ast/SigmaBuilderTest.scala | 12 ++++++++++-- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/data/jvm/src/main/scala/sigma/Platform.scala b/data/jvm/src/main/scala/sigma/Platform.scala index 27e99f2be2..2b077a77f5 100644 --- a/data/jvm/src/main/scala/sigma/Platform.scala +++ b/data/jvm/src/main/scala/sigma/Platform.scala @@ -27,7 +27,7 @@ object Platform { 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 => Nullable(mkConstant[SBigInt.type](SigmaDsl.BigInt(v), SBigInt)) + case v: BigInteger if !VersionContext.current.isV6SoftForkActivated => 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) @@ -41,7 +41,7 @@ object Platform { // 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 => + case b: ErgoBox if !VersionContext.current.isV6SoftForkActivated => 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 diff --git a/interpreter/shared/src/test/scala/sigma/ast/SigmaBuilderTest.scala b/interpreter/shared/src/test/scala/sigma/ast/SigmaBuilderTest.scala index c8eb17e0ca..9e02a6f8f4 100644 --- a/interpreter/shared/src/test/scala/sigma/ast/SigmaBuilderTest.scala +++ b/interpreter/shared/src/test/scala/sigma/ast/SigmaBuilderTest.scala @@ -215,7 +215,11 @@ class SigmaBuilderTest extends AnyPropSpec with ScalaCheckPropertyChecks with Ma property("liftToConstant BigInteger") { val v = BigInteger.valueOf(1L) val c = BigIntConstant(v) - testSuccess(v, c) // TODO v6.0: both BigInteger and arrays should not be liftable directly (see https://github.com/ScorexFoundation/sigmastate-interpreter/issues/905) + if (!VersionContext.current.isV6SoftForkActivated) { + testSuccess(v, c) + } else { + testFailure(v) + } val arr = Array.fill(10)(v) if (!VersionContext.current.isV6SoftForkActivated) { testSuccess(arr, TransformingSigmaBuilder.mkCollectionConstant[SBigInt.type](arr.map(SigmaDsl.BigInt), c.tpe)) @@ -243,7 +247,11 @@ class SigmaBuilderTest extends AnyPropSpec with ScalaCheckPropertyChecks with Ma property("liftToConstant ErgoBox") { val v = TestData.b2.asInstanceOf[CBox].wrappedValue val c = BoxConstant(TestData.b2) - testSuccess(v, c) // TODO v6.0: ErgoBox should not be liftable directly (see https://github.com/ScorexFoundation/sigmastate-interpreter/issues/905) + if (!VersionContext.current.isV6SoftForkActivated) { + testSuccess(v, c) + } else { + testFailure(v) + } testFailure(Array.fill(10)(v)) } From 1644380074047da63e195c27ae047bac631e2688 Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Thu, 18 Jul 2024 13:43:02 +0300 Subject: [PATCH 187/314] AvlTreeData fix & test --- data/jvm/src/main/scala/sigma/Platform.scala | 2 +- .../shared/src/test/scala/sigma/ast/SigmaBuilderTest.scala | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/data/jvm/src/main/scala/sigma/Platform.scala b/data/jvm/src/main/scala/sigma/Platform.scala index 2b077a77f5..3d2d14274f 100644 --- a/data/jvm/src/main/scala/sigma/Platform.scala +++ b/data/jvm/src/main/scala/sigma/Platform.scala @@ -51,7 +51,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 => Nullable(mkConstant[SAvlTree.type](SigmaDsl.avlTree(avl), SAvlTree)) + case avl: AvlTreeData if !VersionContext.current.isV6SoftForkActivated => 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/interpreter/shared/src/test/scala/sigma/ast/SigmaBuilderTest.scala b/interpreter/shared/src/test/scala/sigma/ast/SigmaBuilderTest.scala index 9e02a6f8f4..b125893438 100644 --- a/interpreter/shared/src/test/scala/sigma/ast/SigmaBuilderTest.scala +++ b/interpreter/shared/src/test/scala/sigma/ast/SigmaBuilderTest.scala @@ -278,7 +278,11 @@ class SigmaBuilderTest extends AnyPropSpec with ScalaCheckPropertyChecks with Ma property("liftToConstant AvlTreeData") { val v = TestData.t1.asInstanceOf[CAvlTree].wrappedValue val c = AvlTreeConstant(SigmaDsl.avlTree(v)) - testSuccess(v, c) // TODO v6.0: AvlTreeData should not be liftable directly (see https://github.com/ScorexFoundation/sigmastate-interpreter/issues/905) + if (!VersionContext.current.isV6SoftForkActivated) { + testSuccess(v, c) + } else { + testFailure(v) + } testFailure(Array.fill(10)(v)) } From 7f3a33cf95e782a92a0f450c5c4361e55249c078 Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Wed, 24 Jul 2024 15:13:24 +0300 Subject: [PATCH 188/314] extending tests in LanguageSpecificationV6 --- .../scala/sigma/LanguageSpecificationV6.scala | 44 ++++++++++++++++++- 1 file changed, 42 insertions(+), 2 deletions(-) diff --git a/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala b/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala index fab00e21cb..3b3de407b5 100644 --- a/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala +++ b/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala @@ -187,8 +187,10 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite => _.getMessage.contains("Cannot downcast value") ) } else { - SBigInt.upcast(CBigInt(new BigInteger("0", 16)).asInstanceOf[AnyVal]) shouldBe CBigInt(new BigInteger("0")) - SBigInt.downcast(CBigInt(new BigInteger("0", 16)).asInstanceOf[AnyVal]) shouldBe CBigInt(new BigInteger("0")) + forAll { x: BigInteger => + SBigInt.upcast(CBigInt(x).asInstanceOf[AnyVal]) shouldBe CBigInt(x) + SBigInt.downcast(CBigInt(x).asInstanceOf[AnyVal]) shouldBe CBigInt(x) + } } if (activatedVersionInTests < VersionContext.V6SoftForkVersion) { @@ -228,6 +230,44 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite => forAll { x: (BigInt, BigInt) => Seq(compareTo, bitOr, bitAnd).foreach(_.checkEquality(x)) } + + forAll { x: Long => + assertExceptionThrown( + SLong.downcast(CBigInt(new BigInteger(x.toString)).asInstanceOf[AnyVal]), + _.getMessage.contains("Cannot downcast value") + ) + } + forAll { x: Int => + assertExceptionThrown( + SInt.downcast(CBigInt(new BigInteger(x.toString)).asInstanceOf[AnyVal]), + _.getMessage.contains("Cannot downcast value") + ) + } + forAll { x: Byte => + assertExceptionThrown( + SByte.downcast(CBigInt(new BigInteger(x.toString)).asInstanceOf[AnyVal]), + _.getMessage.contains("Cannot downcast value") + ) + } + forAll { x: Short => + assertExceptionThrown( + SShort.downcast(CBigInt(new BigInteger(x.toString)).asInstanceOf[AnyVal]), + _.getMessage.contains("Cannot downcast value") + ) + } + } else { + forAll { x: Long => + SLong.downcast(CBigInt(new BigInteger(x.toString)).asInstanceOf[AnyVal]) shouldBe x + } + forAll { x: Int => + SInt.downcast(CBigInt(new BigInteger(x.toString)).asInstanceOf[AnyVal]) shouldBe x + } + forAll { x: Byte => + SByte.downcast(CBigInt(new BigInteger(x.toString)).asInstanceOf[AnyVal]) shouldBe x + } + forAll { x: Short => + SShort.downcast(CBigInt(new BigInteger(x.toString)).asInstanceOf[AnyVal]) shouldBe x + } } } From 1271a79fe29f5685b8c3cc7c5eda0ef6abe5b54d Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Fri, 26 Jul 2024 17:44:01 +0300 Subject: [PATCH 189/314] ScalaDoc for headerDecoder --- .../src/main/scala/org/ergoplatform/sdk/JsonCodecs.scala | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/sdk/shared/src/main/scala/org/ergoplatform/sdk/JsonCodecs.scala b/sdk/shared/src/main/scala/org/ergoplatform/sdk/JsonCodecs.scala index 1c7a4156f4..98e8011bcc 100644 --- a/sdk/shared/src/main/scala/org/ergoplatform/sdk/JsonCodecs.scala +++ b/sdk/shared/src/main/scala/org/ergoplatform/sdk/JsonCodecs.scala @@ -130,6 +130,11 @@ trait JsonCodecs { ).asJson }) + /** + * JSON decoder for Header instance. Field "unparsedBytes" is optional for now, to preserve compatibility + * with clients using older JSON decoders (before node 5.0.23). Better to add an (empty) field anyway if possible. + * This field could become mandatory in future. + */ implicit val headerDecoder: Decoder[Header] = Decoder.instance({ cursor => for { version <- cursor.downField("version").as[Byte] From e501a8bbcaff2142266e279b4254e4f0aa904130 Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Fri, 26 Jul 2024 18:23:19 +0300 Subject: [PATCH 190/314] polishing, LSV6 test --- .../src/main/scala/sigma/ast/methods.scala | 19 ++++++------ .../scala/sigma/eval/ErgoTreeEvaluator.scala | 1 + .../interpreter/CErgoTreeEvaluator.scala | 1 + .../scala/sigma/LanguageSpecificationV6.scala | 30 ++++++++++++++++++- 4 files changed, 41 insertions(+), 10 deletions(-) diff --git a/data/shared/src/main/scala/sigma/ast/methods.scala b/data/shared/src/main/scala/sigma/ast/methods.scala index 71ac0a1e1f..487665aa2c 100644 --- a/data/shared/src/main/scala/sigma/ast/methods.scala +++ b/data/shared/src/main/scala/sigma/ast/methods.scala @@ -1467,18 +1467,19 @@ case object SHeaderMethods extends MonoTypeMethods { E.checkPow_eval(mc, header) } + private lazy val v5Methods = super.getMethods() ++ Seq( + idMethod, versionMethod, parentIdMethod, ADProofsRootMethod, stateRootMethod, transactionsRootMethod, + timestampMethod, nBitsMethod, heightMethod, extensionRootMethod, minerPkMethod, powOnetimePkMethod, + powNonceMethod, powDistanceMethod, votesMethod) + + // 6.0 : checkPow method added + private lazy val v6Methods = v5Methods ++ Seq(checkPowMethod) + protected override def getMethods() = { if (VersionContext.current.isV6SoftForkActivated) { - // 6.0 : checkPow method added - super.getMethods() ++ Seq( - idMethod, versionMethod, parentIdMethod, ADProofsRootMethod, stateRootMethod, transactionsRootMethod, - timestampMethod, nBitsMethod, heightMethod, extensionRootMethod, minerPkMethod, powOnetimePkMethod, - powNonceMethod, powDistanceMethod, votesMethod, checkPowMethod) + v6Methods } else { - super.getMethods() ++ Seq( - idMethod, versionMethod, parentIdMethod, ADProofsRootMethod, stateRootMethod, transactionsRootMethod, - timestampMethod, nBitsMethod, heightMethod, extensionRootMethod, minerPkMethod, powOnetimePkMethod, - powNonceMethod, powDistanceMethod, votesMethod) + v5Methods } } } diff --git a/data/shared/src/main/scala/sigma/eval/ErgoTreeEvaluator.scala b/data/shared/src/main/scala/sigma/eval/ErgoTreeEvaluator.scala index 610be08c9c..b95c034bd2 100644 --- a/data/shared/src/main/scala/sigma/eval/ErgoTreeEvaluator.scala +++ b/data/shared/src/main/scala/sigma/eval/ErgoTreeEvaluator.scala @@ -139,6 +139,7 @@ abstract class ErgoTreeEvaluator { mc: MethodCall, tree: AvlTree, operations: Coll[Coll[Byte]], proof: Coll[Byte]): Option[AvlTree] + /** Implements evaluation of Header.checkPow method call ErgoTree node. */ def checkPow_eval(mc: MethodCall, header: Header): Boolean } diff --git a/interpreter/shared/src/main/scala/sigmastate/interpreter/CErgoTreeEvaluator.scala b/interpreter/shared/src/main/scala/sigmastate/interpreter/CErgoTreeEvaluator.scala index 1c58e00a97..c0759f4a5c 100644 --- a/interpreter/shared/src/main/scala/sigmastate/interpreter/CErgoTreeEvaluator.scala +++ b/interpreter/shared/src/main/scala/sigmastate/interpreter/CErgoTreeEvaluator.scala @@ -218,6 +218,7 @@ class CErgoTreeEvaluator( } } + /** Implements evaluation of Header.checkPow method call ErgoTree node. */ override def checkPow_eval(mc: MethodCall, header: Header): Boolean = { val checkPowCostInfo = OperationCostInfo(checkPowMethod.costKind.asInstanceOf[FixedCost], NamedDesc("Header.checkPow")) fixedCostOp(checkPowCostInfo){ diff --git a/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala b/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala index 3b3de407b5..62425f747e 100644 --- a/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala +++ b/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala @@ -1,6 +1,6 @@ package sigma -import sigma.ast.{Apply, Downcast, FixedCost, FixedCostItem, FuncValue, GetVar, JitCost, OptionGet, SBigInt, SByte, SInt, SLong, SShort, ValUse} +import sigma.ast.{Apply, Downcast, FixedCost, FixedCostItem, FuncValue, GetVar, JitCost, MethodCall, OptionGet, SBigInt, SBoolean, SByte, SHeader, SHeaderMethods, SInt, SLong, SShort, ValUse, Value} import sigma.data.{CBigInt, ExactNumeric} import sigma.eval.SigmaDsl import sigma.util.Extensions.{BooleanOps, ByteOps, IntOps, LongOps} @@ -338,6 +338,34 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite => } } + property("Header new methods") { + def checkPoW = newFeature({ (x: Header) => x.checkPow}, + "{ (x: Header) => x.checkPow }", + FuncValue( + Array((1, SHeader)), + MethodCall.typed[Value[SBoolean.type]]( + ValUse(1, SHeader), + SHeaderMethods.getMethodByName("checkPow"), + IndexedSeq(), + Map() + ) + ), + sinceVersion = VersionContext.V6SoftForkVersion) + + if (VersionContext.current.isV6SoftForkActivated) { + forAll { x: Header => + Seq(checkPoW).map(_.checkEquality(x)) + } + } else { + an[Exception] shouldBe thrownBy { + forAll { x: Header => + Seq(checkPoW).map(_.checkEquality(x)) + } + } + } + + } + // TODO v6.0: implement Option.fold (see https://github.com/ScorexFoundation/sigmastate-interpreter/issues/479) property("Option new methods") { val n = ExactNumeric.LongIsExactNumeric From 4c63a60e981743fd10c29a4b87b8e996ed5b749d Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Tue, 30 Jul 2024 19:30:54 +0300 Subject: [PATCH 191/314] LSV5 & LSV6 tests --- .../scala/sigma/LanguageSpecificationV5.scala | 146 +++++++++--------- .../scala/sigma/LanguageSpecificationV6.scala | 60 ++++++- 2 files changed, 134 insertions(+), 72 deletions(-) diff --git a/sc/shared/src/test/scala/sigma/LanguageSpecificationV5.scala b/sc/shared/src/test/scala/sigma/LanguageSpecificationV5.scala index 700b48fd13..347a7b90f4 100644 --- a/sc/shared/src/test/scala/sigma/LanguageSpecificationV5.scala +++ b/sc/shared/src/test/scala/sigma/LanguageSpecificationV5.scala @@ -7957,77 +7957,81 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => ) ) ) - verifyCases( - // (coll, (index, default)) - { - def success[T](v: T) = Expected(Success(v), 1773, costDetails, 1773) - Seq( - ((Coll[Int](), (0, default)), success(default)), - ((Coll[Int](), (-1, default)), success(default)), - ((Coll[Int](1), (0, default)), success(1)), - ((Coll[Int](1), (1, default)), success(default)), - ((Coll[Int](1), (-1, default)), success(default)), - ((Coll[Int](1, 2), (0, default)), success(1)), - ((Coll[Int](1, 2), (1, default)), success(2)), - ((Coll[Int](1, 2), (2, default)), success(default)), - ((Coll[Int](1, 2), (-1, default)), success(default)) - ) - }, - existingFeature((x: (Coll[Int], (Int, Int))) => x._1.getOrElse(x._2._1, x._2._2), - "{ (x: (Coll[Int], (Int, Int))) => x._1.getOrElse(x._2._1, x._2._2) }", - if (lowerMethodCallsInTests) - FuncValue( - Vector((1, SPair(SCollectionType(SInt), SPair(SInt, SInt)))), - BlockValue( - Vector( - ValDef( - 3, - List(), - SelectField.typed[Value[STuple]]( - ValUse(1, SPair(SCollectionType(SInt), SPair(SInt, SInt))), - 2.toByte + + if(!VersionContext.current.isV6SoftForkActivated) { + verifyCases( + // (coll, (index, default)) + { + def success[T](v: T) = Expected(Success(v), 1773, costDetails, 1773) + + Seq( + ((Coll[Int](), (0, default)), success(default)), + ((Coll[Int](), (-1, default)), success(default)), + ((Coll[Int](1), (0, default)), success(1)), + ((Coll[Int](1), (1, default)), success(default)), + ((Coll[Int](1), (-1, default)), success(default)), + ((Coll[Int](1, 2), (0, default)), success(1)), + ((Coll[Int](1, 2), (1, default)), success(2)), + ((Coll[Int](1, 2), (2, default)), success(default)), + ((Coll[Int](1, 2), (-1, default)), success(default)) + ) + }, + existingFeature((x: (Coll[Int], (Int, Int))) => x._1.getOrElse(x._2._1, x._2._2), + "{ (x: (Coll[Int], (Int, Int))) => x._1.getOrElse(x._2._1, x._2._2) }", + if (lowerMethodCallsInTests) + FuncValue( + Vector((1, SPair(SCollectionType(SInt), SPair(SInt, SInt)))), + BlockValue( + Vector( + ValDef( + 3, + List(), + SelectField.typed[Value[STuple]]( + ValUse(1, SPair(SCollectionType(SInt), SPair(SInt, SInt))), + 2.toByte + ) ) - ) - ), - ByIndex( - SelectField.typed[Value[SCollection[SInt.type]]]( - ValUse(1, SPair(SCollectionType(SInt), SPair(SInt, SInt))), - 1.toByte ), - SelectField.typed[Value[SInt.type]](ValUse(3, SPair(SInt, SInt)), 1.toByte), - Some(SelectField.typed[Value[SInt.type]](ValUse(3, SPair(SInt, SInt)), 2.toByte)) + ByIndex( + SelectField.typed[Value[SCollection[SInt.type]]]( + ValUse(1, SPair(SCollectionType(SInt), SPair(SInt, SInt))), + 1.toByte + ), + SelectField.typed[Value[SInt.type]](ValUse(3, SPair(SInt, SInt)), 1.toByte), + Some(SelectField.typed[Value[SInt.type]](ValUse(3, SPair(SInt, SInt)), 2.toByte)) + ) ) ) - ) - else - FuncValue( - Array((1, SPair(SCollectionType(SInt), SPair(SInt, SInt)))), - BlockValue( - Array( - ValDef( - 3, - List(), - SelectField.typed[Value[STuple]]( - ValUse(1, SPair(SCollectionType(SInt), SPair(SInt, SInt))), - 2.toByte + else + FuncValue( + Array((1, SPair(SCollectionType(SInt), SPair(SInt, SInt)))), + BlockValue( + Array( + ValDef( + 3, + List(), + SelectField.typed[Value[STuple]]( + ValUse(1, SPair(SCollectionType(SInt), SPair(SInt, SInt))), + 2.toByte + ) ) - ) - ), - MethodCall.typed[Value[SInt.type]]( - SelectField.typed[Value[SCollection[SInt.type]]]( - ValUse(1, SPair(SCollectionType(SInt), SPair(SInt, SInt))), - 1.toByte ), - SCollectionMethods.getMethodByName("getOrElse").withConcreteTypes(Map(STypeVar("IV") -> SInt)), - Vector( - SelectField.typed[Value[SInt.type]](ValUse(3, SPair(SInt, SInt)), 1.toByte), - SelectField.typed[Value[SInt.type]](ValUse(3, SPair(SInt, SInt)), 2.toByte) - ), - Map() + MethodCall.typed[Value[SInt.type]]( + SelectField.typed[Value[SCollection[SInt.type]]]( + ValUse(1, SPair(SCollectionType(SInt), SPair(SInt, SInt))), + 1.toByte + ), + SCollectionMethods.getMethodByName("getOrElse").withConcreteTypes(Map(STypeVar("IV") -> SInt)), + Vector( + SelectField.typed[Value[SInt.type]](ValUse(3, SPair(SInt, SInt)), 1.toByte), + SelectField.typed[Value[SInt.type]](ValUse(3, SPair(SInt, SInt)), 2.toByte) + ), + Map() + ) ) ) - ) - )) + )) + } } property("Tuple size method equivalence") { @@ -8591,13 +8595,15 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => "{ (x: Option[Long]) => x.isDefined }", FuncValue(Vector((1, SOption(SLong))), OptionIsDefined(ValUse(1, SOption(SLong)))))) - verifyCases( - Seq( - (None -> Expected(Success(1L), 1766, costDetails3, 1766)), - (Some(10L) -> Expected(Success(10L), 1766, costDetails3, 1766))), - existingFeature({ (x: Option[Long]) => x.getOrElse(1L) }, - "{ (x: Option[Long]) => x.getOrElse(1L) }", - FuncValue(Vector((1, SOption(SLong))), OptionGetOrElse(ValUse(1, SOption(SLong)), LongConstant(1L))))) + if (!VersionContext.current.isV6SoftForkActivated) { + verifyCases( + Seq( + (None -> Expected(Success(1L), 1766, costDetails3, 1766)), + (Some(10L) -> Expected(Success(10L), 1766, costDetails3, 1766))), + existingFeature({ (x: Option[Long]) => x.getOrElse(1L) }, + "{ (x: Option[Long]) => x.getOrElse(1L) }", + FuncValue(Vector((1, SOption(SLong))), OptionGetOrElse(ValUse(1, SOption(SLong)), LongConstant(1L))))) + } verifyCases( Seq( diff --git a/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala b/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala index 3b3de407b5..612f0e33c3 100644 --- a/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala +++ b/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala @@ -1,8 +1,9 @@ package sigma -import sigma.ast.{Apply, Downcast, FixedCost, FixedCostItem, FuncValue, GetVar, JitCost, OptionGet, SBigInt, SByte, SInt, SLong, SShort, ValUse} +import sigma.ast.{Apply, ArithOp, BlockValue, ByIndex, CompanionDesc, Constant, Downcast, FixedCost, FixedCostItem, FuncValue, GetVar, IntConstant, JitCost, LongConstant, MethodCall, OptionGet, OptionGetOrElse, PerItemCost, SBigInt, SByte, SCollection, SCollectionMethods, SCollectionType, SInt, SLong, SOption, SPair, SShort, STuple, STypeVar, SelectField, ValDef, ValUse, Value} import sigma.data.{CBigInt, ExactNumeric} -import sigma.eval.SigmaDsl +import sigma.eval.{SigmaDsl, TracedCost} +import sigma.serialization.ValueCodes.OpCode import sigma.util.Extensions.{BooleanOps, ByteOps, IntOps, LongOps} import sigmastate.exceptions.MethodNotFound @@ -168,7 +169,62 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite => Seq(compareTo, bitOr, bitAnd).foreach(_.checkEquality(x)) } } + } + + property("Option.getOrElse with lazy default") { + def getOrElse = newFeature( + { (x: Option[Long]) => x.getOrElse(1 / 0L) }, + "{ (x: Option[Long]) => x.getOrElse(1 / 0L) }", + FuncValue( + Array((1, SOption(SLong))), + OptionGetOrElse( + ValUse(1, SOption(SLong)), + ArithOp(LongConstant(1L), LongConstant(0L), OpCode @@ (-99.toByte)) + ) + ) + ) + if (VersionContext.current.isV6SoftForkActivated) { + forAll { x: Option[Long] => + Seq(getOrElse).map(_.checkEquality(x)) + } + } else { + forAll { x: Option[Long] => + if (x.isEmpty) { + Seq(getOrElse).map(_.checkEquality(x)) + } + } + } + } + + property("Coll getOrElse with lazy default") { + def getOrElse = newFeature( + (x: (Coll[Int], Int)) => x._1.toArray.unapply(x._2).getOrElse(1 / 0), + "{ (x: (Coll[Int], Int)) => x._1.getOrElse(x._2, 1 / 0) }", + FuncValue( + Array((1, SPair(SCollectionType(SInt), SInt))), + ByIndex( + SelectField.typed[Value[SCollection[SInt.type]]]( + ValUse(1, SPair(SCollectionType(SInt), SInt)), + 1.toByte + ), + SelectField.typed[Value[SInt.type]](ValUse(1, SPair(SCollectionType(SInt), SInt)), 2.toByte), + Some(ArithOp(IntConstant(1), IntConstant(0), OpCode @@ (-99.toByte))) + ) + ) + ) + + if (VersionContext.current.isV6SoftForkActivated) { + forAll { x: (Coll[Int], Int) => + Seq(getOrElse).map(_.checkEquality(x)) + } + } else { + forAll { x: (Coll[Int], Int) => + if (x._1.isEmpty) { + Seq(getOrElse).map(_.checkEquality(x)) + } + } + } } property("BigInt methods equivalence (new features)") { From 89f2df66040ef3067f8174c08527f900bebf0dd9 Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Wed, 31 Jul 2024 13:34:25 +0300 Subject: [PATCH 192/314] checkPoW added to collectMethods --- .../sigma/compiler/ir/wrappers/sigma/impl/SigmaDslImpl.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/SigmaDslImpl.scala b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/SigmaDslImpl.scala index 8d1b3aa1f5..e73d3bbeec 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/SigmaDslImpl.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/SigmaDslImpl.scala @@ -1523,7 +1523,7 @@ object Header extends EntityObject("Header") { override protected def collectMethods: Map[RMethod, MethodDesc] = { super.collectMethods ++ Elem.declaredMethods(RClass(classOf[Header]), RClass(classOf[SHeader]), Set( - "id", "version", "parentId", "ADProofsRoot", "stateRoot", "transactionsRoot", "timestamp", "nBits", "height", "extensionRoot", "minerPk", "powOnetimePk", "powNonce", "powDistance", "votes" + "id", "version", "parentId", "ADProofsRoot", "stateRoot", "transactionsRoot", "timestamp", "nBits", "height", "extensionRoot", "minerPk", "powOnetimePk", "powNonce", "powDistance", "votes", "checkPow" )) } } From 61f90cd339b9a79ce20154f45f3db2980be9dc4c Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Wed, 31 Jul 2024 14:04:30 +0300 Subject: [PATCH 193/314] assertEXceptionThrown --- sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala | 2 +- .../test/scala/sigmastate/utxo/BasicOpsSpecification.scala | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala b/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala index 612f0e33c3..b4fb5b12fb 100644 --- a/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala +++ b/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala @@ -199,7 +199,7 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite => property("Coll getOrElse with lazy default") { def getOrElse = newFeature( - (x: (Coll[Int], Int)) => x._1.toArray.unapply(x._2).getOrElse(1 / 0), + (x: (Coll[Int], Int)) => x._1.toArray.toIndexedSeq.unapply(x._2).getOrElse(1 / 0), "{ (x: (Coll[Int], Int)) => x._1.getOrElse(x._2, 1 / 0) }", FuncValue( Array((1, SPair(SCollectionType(SInt), SInt))), diff --git a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala index c1489355e6..3d25326660 100644 --- a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala @@ -170,10 +170,10 @@ class BasicOpsSpecification extends CompilerTestingCommons null ) - if(VersionContext.current.isV6SoftForkActivated) { + if (VersionContext.current.isV6SoftForkActivated) { optTest() } else { - an[Exception] shouldBe thrownBy(optTest()) + assertExceptionThrown(optTest(), _.isInstanceOf[NoSuchElementException]) } } From a20c04fc38ea4cfb700bbfe97f18fc84e00aa516 Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Wed, 31 Jul 2024 15:29:08 +0300 Subject: [PATCH 194/314] moving to Global, finalizing costing --- .../src/main/scala/sigma/SigmaDsl.scala | 14 +++- .../src/main/scala/sigma/data/CBigInt.scala | 3 - .../sigma/reflection/ReflectionData.scala | 6 +- .../src/main/scala/sigma/ast/methods.scala | 73 +++++++++---------- .../scala/sigma/data/CSigmaDslBuilder.scala | 4 + .../scala/sigma/eval/ErgoTreeEvaluator.scala | 3 - .../interpreter/CErgoTreeEvaluator.scala | 6 -- .../MethodCallSerializerSpecification.scala | 18 ++--- .../scala/sigmastate/eval/BasicOpsTests.scala | 10 +-- .../sigma/compiler/ir/GraphBuilding.scala | 10 +-- .../ir/wrappers/sigma/SigmaDslUnit.scala | 2 +- .../ir/wrappers/sigma/impl/SigmaDslImpl.scala | 30 ++++---- .../TestingInterpreterSpecification.scala | 3 +- 13 files changed, 87 insertions(+), 95 deletions(-) diff --git a/core/shared/src/main/scala/sigma/SigmaDsl.scala b/core/shared/src/main/scala/sigma/SigmaDsl.scala index 7b20ac80b9..aa13e3f89b 100644 --- a/core/shared/src/main/scala/sigma/SigmaDsl.scala +++ b/core/shared/src/main/scala/sigma/SigmaDsl.scala @@ -154,8 +154,6 @@ trait BigInt { */ def or(that: BigInt): BigInt def |(that: BigInt): BigInt = or(that) - - def nbits: Long } /** Base class for points on elliptic curves. */ @@ -697,6 +695,18 @@ trait SigmaDslBuilder { */ def groupGenerator: GroupElement + /** + * @return big integer provided as input approximately encoded using NBits, + * see (https://bitcoin.stackexchange.com/questions/57184/what-does-the-nbits-value-represent) + * for format details + */ + def encodeNbits(bi: BigInt): Long + + /** + * @return big integer decoded from NBits value provided, + * see (https://bitcoin.stackexchange.com/questions/57184/what-does-the-nbits-value-represent) + * for format details + */ def decodeNbits(l: Long): BigInt /** diff --git a/core/shared/src/main/scala/sigma/data/CBigInt.scala b/core/shared/src/main/scala/sigma/data/CBigInt.scala index 43198fbf8a..bbf1a85e46 100644 --- a/core/shared/src/main/scala/sigma/data/CBigInt.scala +++ b/core/shared/src/main/scala/sigma/data/CBigInt.scala @@ -1,7 +1,6 @@ package sigma.data import sigma.util.Extensions.BigIntegerOps -import sigma.util.NBitsUtils import sigma.{BigInt, Coll, Colls} import java.math.BigInteger @@ -50,6 +49,4 @@ case class CBigInt(override val wrappedValue: BigInteger) extends BigInt with Wr override def and(that: BigInt): BigInt = CBigInt(wrappedValue.and(that.asInstanceOf[CBigInt].wrappedValue)) override def or(that: BigInt): BigInt = CBigInt(wrappedValue.or(that.asInstanceOf[CBigInt].wrappedValue)) - - override def nbits: Long = NBitsUtils.encodeCompactBits(wrappedValue) } diff --git a/core/shared/src/main/scala/sigma/reflection/ReflectionData.scala b/core/shared/src/main/scala/sigma/reflection/ReflectionData.scala index b4b5fd9f23..c1c7e41ef5 100644 --- a/core/shared/src/main/scala/sigma/reflection/ReflectionData.scala +++ b/core/shared/src/main/scala/sigma/reflection/ReflectionData.scala @@ -124,9 +124,6 @@ object ReflectionData { }, mkMethod(clazz, "divide", paramTypes) { (obj, args) => obj.asInstanceOf[BigInt].divide(args(0).asInstanceOf[BigInt]) - }, - mkMethod(clazz, "nbits", paramTypes) { (obj, _) => - obj.asInstanceOf[BigInt].nbits } ) ) @@ -447,6 +444,9 @@ object ReflectionData { mkMethod(clazz, "decodePoint", Array[Class[_]](cColl)) { (obj, args) => obj.asInstanceOf[SigmaDslBuilder].decodePoint(args(0).asInstanceOf[Coll[Byte]]) }, + mkMethod(clazz, "encodeNbits", Array[Class[_]](cColl)) { (obj, args) => + obj.asInstanceOf[SigmaDslBuilder].encodeNbits(args(0).asInstanceOf[BigInt]) + }, mkMethod(clazz, "decodeNbits", Array[Class[_]](cColl)) { (obj, args) => obj.asInstanceOf[SigmaDslBuilder].decodeNbits(args(0).asInstanceOf[Long]) } diff --git a/data/shared/src/main/scala/sigma/ast/methods.scala b/data/shared/src/main/scala/sigma/ast/methods.scala index 171d2b95c7..07a3aea4bf 100644 --- a/data/shared/src/main/scala/sigma/ast/methods.scala +++ b/data/shared/src/main/scala/sigma/ast/methods.scala @@ -303,9 +303,6 @@ case object SIntMethods extends SNumericTypeMethods { case object SLongMethods extends SNumericTypeMethods { /** Type for which this container defines methods. */ override def ownerType: SMonoType = SLong - - protected override def getMethods(): Seq[SMethod] = super.getMethods() - } /** Methods of BigInt type. Implemented using [[java.math.BigInteger]]. */ @@ -313,13 +310,6 @@ case object SBigIntMethods extends SNumericTypeMethods { /** Type for which this container defines methods. */ override def ownerType: SMonoType = SBigInt - final val ToNBitsCostInfo = OperationCostInfo( - FixedCost(JitCost(5)), NamedDesc("NBitsMethodCall")) - - //id = 8 to make it after toBits - val ToNBits = SMethod(this, "nbits", SFunc(this.ownerType, SLong), 8, ToNBitsCostInfo.costKind) - .withInfo(ModQ, "Encode this big integer value as NBits") - /** The following `modQ` methods are not fully implemented in v4.x and this descriptors. * This descritors are remain here in the code and are waiting for full implementation * is upcoming soft-forks at which point the cost parameters should be calculated and @@ -337,7 +327,7 @@ case object SBigIntMethods extends SNumericTypeMethods { protected override def getMethods(): Seq[SMethod] = { if (VersionContext.current.isV6SoftForkActivated) { - super.getMethods() ++ Seq(ToNBits) + super.getMethods() // ModQMethod, // PlusModQMethod, // MinusModQMethod, @@ -347,14 +337,6 @@ case object SBigIntMethods extends SNumericTypeMethods { super.getMethods() } } - - /** - * - */ - def nbits_eval(mc: MethodCall, bi: sigma.BigInt)(implicit E: ErgoTreeEvaluator): Long = { - E.nbits(mc, bi) - } - } /** Methods of type `String`. */ @@ -1523,37 +1505,50 @@ case object SGlobalMethods extends MonoTypeMethods { Xor.xorWithCosting(ls, rs) } + private lazy val EnDecodeNBitsCost = FixedCost(JitCost(5)) // the same cost for nbits encoding and decoding + + lazy val encodeNBitsMethod: SMethod = SMethod( + this, "encodeNbits", SFunc(Array(SGlobal, SBigInt), SLong), 3, EnDecodeNBitsCost) + .withIRInfo(MethodCallIrBuilder) + .withInfo(MethodCall, "Encode big integer number as nbits", ArgInfo("bigInt", "Big integer")) + lazy val decodeNBitsMethod: SMethod = SMethod( - this, "decodeNbits", SFunc(Array(SGlobal, SLong), SBigInt), 3, FixedCost(JitCost(5))) + this, "decodeNbits", SFunc(Array(SGlobal, SLong), SBigInt), 4, EnDecodeNBitsCost) .withIRInfo(MethodCallIrBuilder) - .withInfo(Xor, "Byte-wise XOR of two collections of bytes", ArgInfo("left", "left operand")) + .withInfo(MethodCall, "Decode nbits-encoded big integer number", ArgInfo("nbits", "NBits-encoded argument")) /** - * + * encodeNBits evaluation with costing + */ + def encodeNbits_eval(mc: MethodCall, G: SigmaDslBuilder, bigInt: BigInt)(implicit E: ErgoTreeEvaluator): Long = { + E.addFixedCost(EnDecodeNBitsCost, encodeNBitsMethod.opDesc) { + NBitsUtils.encodeCompactBits(bigInt.asInstanceOf[CBigInt].wrappedValue) + } + } + + /** + * decodeNBits evaluation with costing */ def decodeNbits_eval(mc: MethodCall, G: SigmaDslBuilder, l: Long)(implicit E: ErgoTreeEvaluator): BigInt = { - CBigInt(NBitsUtils.decodeCompactBits(l).bigInteger) // todo: costing is ignored here + E.addFixedCost(EnDecodeNBitsCost, decodeNBitsMethod.opDesc) { + CBigInt(NBitsUtils.decodeCompactBits(l).bigInteger) + } } - { + protected override def getMethods() = { if (VersionContext.current.isV6SoftForkActivated) { - super.getMethods() ++ Seq(decodeNBitsMethod) + super.getMethods() ++ Seq( + groupGeneratorMethod, + xorMethod, + encodeNBitsMethod, + decodeNBitsMethod + ) } else { - super.getMethods() + super.getMethods() ++ Seq( + groupGeneratorMethod, + xorMethod + ) } } - - protected override def getMethods() = if (VersionContext.current.isV6SoftForkActivated) { - super.getMethods() ++ Seq( - groupGeneratorMethod, - xorMethod, - decodeNBitsMethod - ) - } else { - super.getMethods() ++ Seq( - groupGeneratorMethod, - xorMethod - ) - } } diff --git a/data/shared/src/main/scala/sigma/data/CSigmaDslBuilder.scala b/data/shared/src/main/scala/sigma/data/CSigmaDslBuilder.scala index 5f401ad9ff..d7ebd7651a 100644 --- a/data/shared/src/main/scala/sigma/data/CSigmaDslBuilder.scala +++ b/data/shared/src/main/scala/sigma/data/CSigmaDslBuilder.scala @@ -176,6 +176,10 @@ class CSigmaDslBuilder extends SigmaDslBuilder { dsl => override def groupGenerator: GroupElement = _generatorElement + def encodeNbits(bi: BigInt): Long = { + NBitsUtils.encodeCompactBits(bi.asInstanceOf[CBigInt].wrappedValue) + } + def decodeNbits(l: Long): BigInt = { CBigInt(NBitsUtils.decodeCompactBits(l).bigInteger) } diff --git a/data/shared/src/main/scala/sigma/eval/ErgoTreeEvaluator.scala b/data/shared/src/main/scala/sigma/eval/ErgoTreeEvaluator.scala index ec12a52849..8eb6171622 100644 --- a/data/shared/src/main/scala/sigma/eval/ErgoTreeEvaluator.scala +++ b/data/shared/src/main/scala/sigma/eval/ErgoTreeEvaluator.scala @@ -98,9 +98,6 @@ abstract class ErgoTreeEvaluator { /** Represents blockchain data context for ErgoTree evaluation. */ def context: Context - /** Implements evaluation of BigInt.nbits method call ErgoTree node. */ - def nbits(mc: MethodCall, bi: sigma.BigInt): Long - /** Create an instance of [[AvlTreeVerifier]] for the given tree and proof. */ def createTreeVerifier(tree: AvlTree, proof: Coll[Byte]): AvlTreeVerifier diff --git a/interpreter/shared/src/main/scala/sigmastate/interpreter/CErgoTreeEvaluator.scala b/interpreter/shared/src/main/scala/sigmastate/interpreter/CErgoTreeEvaluator.scala index 53aa3dc08b..963a8fadc3 100644 --- a/interpreter/shared/src/main/scala/sigmastate/interpreter/CErgoTreeEvaluator.scala +++ b/interpreter/shared/src/main/scala/sigmastate/interpreter/CErgoTreeEvaluator.scala @@ -67,12 +67,6 @@ class CErgoTreeEvaluator( override def createTreeVerifier(tree: AvlTree, proof: Coll[Byte]): AvlTreeVerifier = CAvlTreeVerifier(tree, proof) - def nbits(mc: MethodCall, bi: sigma.BigInt): Long = { - addFixedCost(SBigIntMethods.ToNBitsCostInfo) { - bi.nbits - } - } - /** Creates [[sigma.eval.AvlTreeVerifier]] for the given tree and proof. */ def createVerifier(tree: AvlTree, proof: Coll[Byte]) = { // the cost of tree reconstruction from proof is O(proof.length) diff --git a/interpreter/shared/src/test/scala/sigma/serialization/MethodCallSerializerSpecification.scala b/interpreter/shared/src/test/scala/sigma/serialization/MethodCallSerializerSpecification.scala index 133361b7b7..9157c991e5 100644 --- a/interpreter/shared/src/test/scala/sigma/serialization/MethodCallSerializerSpecification.scala +++ b/interpreter/shared/src/test/scala/sigma/serialization/MethodCallSerializerSpecification.scala @@ -24,12 +24,12 @@ class MethodCallSerializerSpecification extends SerializationSpecification { roundTripTest(expr) } - property("MethodCall deserialization round trip for BigInt.nbits") { + property("MethodCall deserialization round trip for Global.encodeNBits") { def code = { val bi = BigIntConstant(5) - val expr = MethodCall(bi, - SBigIntMethods.ToNBits, - Vector(), + val expr = MethodCall(Global, + SGlobalMethods.encodeNBitsMethod, + Vector(bi), Map() ) roundTripTest(expr) @@ -46,12 +46,12 @@ class MethodCallSerializerSpecification extends SerializationSpecification { }) } - property("MethodCall deserialization round trip for BigInt.nbits") { + property("MethodCall deserialization round trip for Global.decodeNBits") { def code = { - val bi = BigIntConstant(5) - val expr = MethodCall(bi, - SBigIntMethods.ToNBits, - Vector(), + val l = LongConstant(5) + val expr = MethodCall(Global, + SGlobalMethods.decodeNBitsMethod, + Vector(l), Map() ) roundTripTest(expr) diff --git a/interpreter/shared/src/test/scala/sigmastate/eval/BasicOpsTests.scala b/interpreter/shared/src/test/scala/sigmastate/eval/BasicOpsTests.scala index fbd74ed873..c4cd58a4ef 100644 --- a/interpreter/shared/src/test/scala/sigmastate/eval/BasicOpsTests.scala +++ b/interpreter/shared/src/test/scala/sigmastate/eval/BasicOpsTests.scala @@ -2,15 +2,15 @@ package sigmastate.eval import org.scalatest.funsuite.AnyFunSuite import org.scalatest.matchers.should.Matchers -import sigma.ast.{BigIntConstant, ErgoTree, JitCost, MethodCall, SBigIntMethods} +import sigma.ast.{BigIntConstant, ErgoTree, Global, JitCost, MethodCall, SBigIntMethods, SGlobalMethods} import sigma.crypto.SecP256K1Group -import sigma.data.{CBigInt, CSigmaDslBuilder, TrivialProp} +import sigma.data.{CBigInt, TrivialProp} import sigma.eval.SigmaDsl import sigma.util.Extensions.SigmaBooleanOps import sigma.util.NBitsUtils import java.math.BigInteger -import sigma.{ContractsTestkit, SigmaDslBuilder, SigmaProp} +import sigma.{ContractsTestkit, SigmaProp} import sigmastate.interpreter.{CErgoTreeEvaluator, CostAccumulator} import sigmastate.interpreter.CErgoTreeEvaluator.DefaultProfiler @@ -72,7 +72,7 @@ class BasicOpsTests extends AnyFunSuite with ContractsTestkit with Matchers { * Checks BigInt.nbits evaluation for SigmaDSL as well as AST interpreter (MethodCall) layers */ test("nbits evaluation") { - SigmaDsl.BigInt(BigInteger.valueOf(0)).nbits should be + SigmaDsl.encodeNbits(CBigInt(BigInteger.valueOf(0))) should be (NBitsUtils.encodeCompactBits(0)) val es = CErgoTreeEvaluator.DefaultEvalSettings @@ -84,7 +84,7 @@ class BasicOpsTests extends AnyFunSuite with ContractsTestkit with Matchers { constants = ErgoTree.EmptyConstants, coster = accumulator, DefaultProfiler, es) - val res = MethodCall(BigIntConstant(BigInteger.valueOf(0)), SBigIntMethods.ToNBits, IndexedSeq.empty, Map.empty) + val res = MethodCall(Global, SGlobalMethods.encodeNBitsMethod, IndexedSeq(BigIntConstant(BigInteger.valueOf(0))), Map.empty) .evalTo[Long](Map.empty)(evaluator) res should be (NBitsUtils.encodeCompactBits(0)) 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 cda2b64ab0..be7658fa55 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/GraphBuilding.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/GraphBuilding.scala @@ -504,9 +504,6 @@ trait GraphBuilding extends Base with DefRewriting { IR: IRContext => else error(s"The type of $obj is expected to be Collection to select 'size' property", obj.sourceContext.toOption) - case Select(obj, SBigIntMethods.ToNBits.name, _) if obj.tpe == SBigInt && VersionContext.current.isV6SoftForkActivated => - eval(sigma.ast.MethodCall(obj, SBigIntMethods.ToNBits, IndexedSeq.empty, Map.empty)) - // Rule: proof.isProven --> IsValid(proof) case Select(p, SSigmaPropMethods.IsProven, _) if p.tpe == SSigmaProp => eval(SigmaPropIsProven(p.asSigmaProp)) @@ -936,10 +933,6 @@ trait GraphBuilding extends Base with DefRewriting { IR: IRContext => val objV = eval(obj) val argsV = args.map(eval) (objV, method.objType) match { - case (bi: Ref[BigInt]@unchecked, SBigIntMethods) => method.name match { - case SBigIntMethods.ToNBits.name => - bi.nbits - } case (xs: RColl[t]@unchecked, SCollectionMethods) => method.name match { case SCollectionMethods.IndicesMethod.name => xs.indices @@ -1154,6 +1147,9 @@ trait GraphBuilding extends Base with DefRewriting { IR: IRContext => val c1 = asRep[Coll[Byte]](argsV(0)) val c2 = asRep[Coll[Byte]](argsV(1)) g.xor(c1, c2) + case SGlobalMethods.encodeNBitsMethod.name if VersionContext.current.isV6SoftForkActivated => + val c1 = asRep[BigInt](argsV(0)) + g.encodeNbits(c1) case SGlobalMethods.decodeNBitsMethod.name if VersionContext.current.isV6SoftForkActivated => val c1 = asRep[Long](argsV(0)) g.decodeNbits(c1) diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/SigmaDslUnit.scala b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/SigmaDslUnit.scala index 427998588e..df229f8ce3 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/SigmaDslUnit.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/SigmaDslUnit.scala @@ -13,7 +13,6 @@ import scalan._ def mod(m: Ref[BigInt]): Ref[BigInt]; def min(that: Ref[BigInt]): Ref[BigInt]; def max(that: Ref[BigInt]): Ref[BigInt]; - def nbits: Ref[Long] }; trait GroupElement extends Def[GroupElement] { def exp(k: Ref[BigInt]): Ref[GroupElement]; @@ -115,6 +114,7 @@ import scalan._ /** This method will be used in v6.0 to handle CreateAvlTree operation in GraphBuilding */ def avlTree(operationFlags: Ref[Byte], digest: Ref[Coll[Byte]], keyLength: Ref[Int], valueLengthOpt: Ref[WOption[Int]]): Ref[AvlTree]; def xor(l: Ref[Coll[Byte]], r: Ref[Coll[Byte]]): Ref[Coll[Byte]] + def encodeNbits(bi: Ref[BigInt]): Ref[Long] def decodeNbits(l: Ref[Long]): Ref[BigInt] }; trait CostModelCompanion; diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/SigmaDslImpl.scala b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/SigmaDslImpl.scala index d92aa14a2e..c63d47cc86 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/SigmaDslImpl.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/SigmaDslImpl.scala @@ -97,13 +97,6 @@ object BigInt extends EntityObject("BigInt") { Array[AnyRef](that), true, false, element[BigInt])) } - - override def nbits: Ref[Long] = { - asRep[Long](mkMethodCall(self, - BigIntClass.getMethod("nbits"), - Array[AnyRef](), - neverInvoke = true, isAdapterCall = false, element[Long])) - } } implicit object LiftableBigInt @@ -172,13 +165,6 @@ object BigInt extends EntityObject("BigInt") { Array[AnyRef](that), true, true, element[BigInt])) } - - def nbits: Ref[Long] = { - asRep[Long](mkMethodCall(source, - BigIntClass.getMethod("nbits", classOf[Sym]), - Array[AnyRef](), - neverInvoke = true, isAdapterCall = true, element[Long])) - } } // entityUnref: single unref method for each type family @@ -1960,10 +1946,17 @@ object SigmaDslBuilder extends EntityObject("SigmaDslBuilder") { true, false, element[Coll[Byte]])) } + override def encodeNbits(bi: Ref[BigInt]): Ref[Long] = { + asRep[Long](mkMethodCall(self, + SigmaDslBuilderClass.getMethod("encodeNbits", classOf[Sym]), + Array[AnyRef](bi), + true, false, element[Long])) + } + override def decodeNbits(l: Ref[Long]): Ref[BigInt] = { asRep[BigInt](mkMethodCall(self, SigmaDslBuilderClass.getMethod("decodeNbits", classOf[Sym]), - Array[AnyRef](), + Array[AnyRef](l), true, false, element[BigInt])) } } @@ -2126,6 +2119,13 @@ object SigmaDslBuilder extends EntityObject("SigmaDslBuilder") { true, true, element[Coll[Byte]])) } + override def encodeNbits(bi: Ref[BigInt]): Ref[Long] = { + asRep[Long](mkMethodCall(source, + SigmaDslBuilderClass.getMethod("encodeNbits", classOf[Sym]), + Array[AnyRef](bi), + true, true, element[Long])) + } + override def decodeNbits(l: Ref[Long]): Ref[BigInt] = { asRep[BigInt](mkMethodCall(source, SigmaDslBuilderClass.getMethod("decodeNbits", classOf[Sym]), diff --git a/sc/shared/src/test/scala/sigmastate/TestingInterpreterSpecification.scala b/sc/shared/src/test/scala/sigmastate/TestingInterpreterSpecification.scala index 429cbd33b7..0a3bf29960 100644 --- a/sc/shared/src/test/scala/sigmastate/TestingInterpreterSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/TestingInterpreterSpecification.scala @@ -10,7 +10,6 @@ import org.ergoplatform._ import org.scalatest.BeforeAndAfterAll import scorex.util.encode.Base58 import sigma.VersionContext -import sigma.crypto.CryptoConstants import sigma.data.{AvlTreeData, CAND, ProveDlog, SigmaBoolean, TrivialProp} import sigma.VersionContext.V6SoftForkVersion import sigma.util.Extensions.IntOps @@ -207,7 +206,7 @@ class TestingInterpreterSpecification extends CompilerTestingCommons """ |{ | val b: BigInt = 11999.toBigInt - | b.nbits == 36626176 + | Global.encodeNbits(b) == 36626176 |} |""".stripMargin if (activatedVersionInTests < V6SoftForkVersion) { From 2c8df317b7cab41fbee753cb107f99ba823ac8c3 Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Wed, 31 Jul 2024 15:47:36 +0300 Subject: [PATCH 195/314] updating collectMethods --- .../sigma/compiler/ir/wrappers/sigma/impl/SigmaDslImpl.scala | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/SigmaDslImpl.scala b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/SigmaDslImpl.scala index c63d47cc86..db3a2e4933 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/SigmaDslImpl.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/SigmaDslImpl.scala @@ -2149,7 +2149,9 @@ object SigmaDslBuilder extends EntityObject("SigmaDslBuilder") { override protected def collectMethods: Map[RMethod, MethodDesc] = { super.collectMethods ++ Elem.declaredMethods(RClass(classOf[SigmaDslBuilder]), RClass(classOf[SSigmaDslBuilder]), Set( - "Colls", "verifyZK", "atLeast", "allOf", "allZK", "anyOf", "anyZK", "xorOf", "sigmaProp", "blake2b256", "sha256", "byteArrayToBigInt", "longToByteArray", "byteArrayToLong", "proveDlog", "proveDHTuple", "groupGenerator", "substConstants", "decodePoint", "avlTree", "xor" + "Colls", "verifyZK", "atLeast", "allOf", "allZK", "anyOf", "anyZK", "xorOf", "sigmaProp", "blake2b256", + "sha256", "byteArrayToBigInt", "longToByteArray", "byteArrayToLong", "proveDlog", "proveDHTuple", "groupGenerator", + "substConstants", "decodePoint", "avlTree", "xor", "encodeNBits", "decodeNBits" )) } } From 6981c34cc863cf34a19588f89e722742ba243d48 Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Wed, 31 Jul 2024 16:19:10 +0300 Subject: [PATCH 196/314] fixing JS test --- .../sigma/reflection/ReflectionData.scala | 4 +- yarn.lock | 3322 +++++++++++++++++ 2 files changed, 3324 insertions(+), 2 deletions(-) create mode 100644 yarn.lock diff --git a/core/shared/src/main/scala/sigma/reflection/ReflectionData.scala b/core/shared/src/main/scala/sigma/reflection/ReflectionData.scala index c1c7e41ef5..5eff8bd251 100644 --- a/core/shared/src/main/scala/sigma/reflection/ReflectionData.scala +++ b/core/shared/src/main/scala/sigma/reflection/ReflectionData.scala @@ -444,10 +444,10 @@ object ReflectionData { mkMethod(clazz, "decodePoint", Array[Class[_]](cColl)) { (obj, args) => obj.asInstanceOf[SigmaDslBuilder].decodePoint(args(0).asInstanceOf[Coll[Byte]]) }, - mkMethod(clazz, "encodeNbits", Array[Class[_]](cColl)) { (obj, args) => + mkMethod(clazz, "encodeNbits", Array[Class[_]](classOf[BigInt])) { (obj, args) => obj.asInstanceOf[SigmaDslBuilder].encodeNbits(args(0).asInstanceOf[BigInt]) }, - mkMethod(clazz, "decodeNbits", Array[Class[_]](cColl)) { (obj, args) => + mkMethod(clazz, "decodeNbits", Array[Class[_]](classOf[Long])) { (obj, args) => obj.asInstanceOf[SigmaDslBuilder].decodeNbits(args(0).asInstanceOf[Long]) } ) diff --git a/yarn.lock b/yarn.lock new file mode 100644 index 0000000000..161dcfd54a --- /dev/null +++ b/yarn.lock @@ -0,0 +1,3322 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@discoveryjs/json-ext@^0.5.0": + version "0.5.7" + resolved "https://registry.yarnpkg.com/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz#1d572bfbbe14b7704e0ba0f39b74815b84870d70" + integrity sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw== + +"@fleet-sdk/common@0.1.3": + version "0.1.3" + resolved "https://registry.yarnpkg.com/@fleet-sdk/common/-/common-0.1.3.tgz#f9e478b896e9192f03d2d5b30570af4e8632eb15" + integrity sha512-gYEkHhgGpgIcmCL3nCw8E9zHkT2WLmR+mPdxFlUE6fwcwISURbJrP6W9mF7D5Y0ShAP5Is2w3edh7AyIc7ctIQ== + +"@jridgewell/gen-mapping@^0.3.5": + version "0.3.5" + resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz#dcce6aff74bdf6dad1a95802b69b04a2fcb1fb36" + integrity sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg== + dependencies: + "@jridgewell/set-array" "^1.2.1" + "@jridgewell/sourcemap-codec" "^1.4.10" + "@jridgewell/trace-mapping" "^0.3.24" + +"@jridgewell/resolve-uri@^3.1.0": + version "3.1.2" + resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz#7a0ee601f60f99a20c7c7c5ff0c80388c1189bd6" + integrity sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw== + +"@jridgewell/set-array@^1.2.1": + version "1.2.1" + resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.2.1.tgz#558fb6472ed16a4c850b889530e6b36438c49280" + integrity sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A== + +"@jridgewell/source-map@^0.3.3": + version "0.3.6" + resolved "https://registry.yarnpkg.com/@jridgewell/source-map/-/source-map-0.3.6.tgz#9d71ca886e32502eb9362c9a74a46787c36df81a" + integrity sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ== + dependencies: + "@jridgewell/gen-mapping" "^0.3.5" + "@jridgewell/trace-mapping" "^0.3.25" + +"@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.14": + version "1.5.0" + resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz#3188bcb273a414b0d215fd22a58540b989b9409a" + integrity sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ== + +"@jridgewell/trace-mapping@^0.3.20", "@jridgewell/trace-mapping@^0.3.24", "@jridgewell/trace-mapping@^0.3.25": + version "0.3.25" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz#15f190e98895f3fc23276ee14bc76b675c2e50f0" + integrity sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ== + dependencies: + "@jridgewell/resolve-uri" "^3.1.0" + "@jridgewell/sourcemap-codec" "^1.4.14" + +"@noble/hashes@1.1.4": + version "1.1.4" + resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.1.4.tgz#2611ebf5764c1bf754da7c7794de4fb30512336d" + integrity sha512-+PYsVPrTSqtVjatKt2A/Proukn2Yrz61OBThOCKErc5w2/r1Fh37vbDv0Eah7pyNltrmacjwTvdw3JoR+WE4TA== + +"@noble/hashes@^1.1.4": + version "1.4.0" + resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.4.0.tgz#45814aa329f30e4fe0ba49426f49dfccdd066426" + integrity sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg== + +"@types/eslint-scope@^3.7.0": + version "3.7.7" + resolved "https://registry.yarnpkg.com/@types/eslint-scope/-/eslint-scope-3.7.7.tgz#3108bd5f18b0cdb277c867b3dd449c9ed7079ac5" + integrity sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg== + dependencies: + "@types/eslint" "*" + "@types/estree" "*" + +"@types/eslint@*": + version "9.6.0" + resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-9.6.0.tgz#51d4fe4d0316da9e9f2c80884f2c20ed5fb022ff" + integrity sha512-gi6WQJ7cHRgZxtkQEoyHMppPjq9Kxo5Tjn2prSKDSmZrCz8TZ3jSRCeTJm+WoM+oB0WG37bRqLzaaU3q7JypGg== + dependencies: + "@types/estree" "*" + "@types/json-schema" "*" + +"@types/estree@*": + version "1.0.5" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.5.tgz#a6ce3e556e00fd9895dd872dd172ad0d4bd687f4" + integrity sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw== + +"@types/estree@^0.0.46": + version "0.0.46" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.46.tgz#0fb6bfbbeabd7a30880504993369c4bf1deab1fe" + integrity sha512-laIjwTQaD+5DukBZaygQ79K1Z0jb1bPEMRrkXSLjtCcZm+abyp5YbrqpSLzD42FwWW6gK/aS4NYpJ804nG2brg== + +"@types/glob@^7.1.1": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@types/glob/-/glob-7.2.0.tgz#bc1b5bf3aa92f25bd5dd39f35c57361bdce5b2eb" + integrity sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA== + dependencies: + "@types/minimatch" "*" + "@types/node" "*" + +"@types/json-schema@*", "@types/json-schema@^7.0.8": + version "7.0.15" + resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841" + integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA== + +"@types/minimatch@*": + version "5.1.2" + resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-5.1.2.tgz#07508b45797cb81ec3f273011b054cd0755eddca" + integrity sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA== + +"@types/node@*": + version "22.0.0" + resolved "https://registry.yarnpkg.com/@types/node/-/node-22.0.0.tgz#04862a2a71e62264426083abe1e27e87cac05a30" + integrity sha512-VT7KSYudcPOzP5Q0wfbowyNLaVR8QWUdw+088uFWwfvpY6uCWaXpqV6ieLAu9WBcnTa7H4Z5RLK8I5t2FuOcqw== + dependencies: + undici-types "~6.11.1" + +"@webassemblyjs/ast@1.11.0": + version "1.11.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.11.0.tgz#a5aa679efdc9e51707a4207139da57920555961f" + integrity sha512-kX2W49LWsbthrmIRMbQZuQDhGtjyqXfEmmHyEi4XWnSZtPmxY0+3anPIzsnRb45VH/J55zlOfWvZuY47aJZTJg== + dependencies: + "@webassemblyjs/helper-numbers" "1.11.0" + "@webassemblyjs/helper-wasm-bytecode" "1.11.0" + +"@webassemblyjs/floating-point-hex-parser@1.11.0": + version "1.11.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.0.tgz#34d62052f453cd43101d72eab4966a022587947c" + integrity sha512-Q/aVYs/VnPDVYvsCBL/gSgwmfjeCb4LW8+TMrO3cSzJImgv8lxxEPM2JA5jMrivE7LSz3V+PFqtMbls3m1exDA== + +"@webassemblyjs/helper-api-error@1.11.0": + version "1.11.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.0.tgz#aaea8fb3b923f4aaa9b512ff541b013ffb68d2d4" + integrity sha512-baT/va95eXiXb2QflSx95QGT5ClzWpGaa8L7JnJbgzoYeaA27FCvuBXU758l+KXWRndEmUXjP0Q5fibhavIn8w== + +"@webassemblyjs/helper-buffer@1.11.0": + version "1.11.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.0.tgz#d026c25d175e388a7dbda9694e91e743cbe9b642" + integrity sha512-u9HPBEl4DS+vA8qLQdEQ6N/eJQ7gT7aNvMIo8AAWvAl/xMrcOSiI2M0MAnMCy3jIFke7bEee/JwdX1nUpCtdyA== + +"@webassemblyjs/helper-numbers@1.11.0": + version "1.11.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.0.tgz#7ab04172d54e312cc6ea4286d7d9fa27c88cd4f9" + integrity sha512-DhRQKelIj01s5IgdsOJMKLppI+4zpmcMQ3XboFPLwCpSNH6Hqo1ritgHgD0nqHeSYqofA6aBN/NmXuGjM1jEfQ== + dependencies: + "@webassemblyjs/floating-point-hex-parser" "1.11.0" + "@webassemblyjs/helper-api-error" "1.11.0" + "@xtuc/long" "4.2.2" + +"@webassemblyjs/helper-wasm-bytecode@1.11.0": + version "1.11.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.0.tgz#85fdcda4129902fe86f81abf7e7236953ec5a4e1" + integrity sha512-MbmhvxXExm542tWREgSFnOVo07fDpsBJg3sIl6fSp9xuu75eGz5lz31q7wTLffwL3Za7XNRCMZy210+tnsUSEA== + +"@webassemblyjs/helper-wasm-section@1.11.0": + version "1.11.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.0.tgz#9ce2cc89300262509c801b4af113d1ca25c1a75b" + integrity sha512-3Eb88hcbfY/FCukrg6i3EH8H2UsD7x8Vy47iVJrP967A9JGqgBVL9aH71SETPx1JrGsOUVLo0c7vMCN22ytJew== + dependencies: + "@webassemblyjs/ast" "1.11.0" + "@webassemblyjs/helper-buffer" "1.11.0" + "@webassemblyjs/helper-wasm-bytecode" "1.11.0" + "@webassemblyjs/wasm-gen" "1.11.0" + +"@webassemblyjs/ieee754@1.11.0": + version "1.11.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.11.0.tgz#46975d583f9828f5d094ac210e219441c4e6f5cf" + integrity sha512-KXzOqpcYQwAfeQ6WbF6HXo+0udBNmw0iXDmEK5sFlmQdmND+tr773Ti8/5T/M6Tl/413ArSJErATd8In3B+WBA== + dependencies: + "@xtuc/ieee754" "^1.2.0" + +"@webassemblyjs/leb128@1.11.0": + version "1.11.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.11.0.tgz#f7353de1df38aa201cba9fb88b43f41f75ff403b" + integrity sha512-aqbsHa1mSQAbeeNcl38un6qVY++hh8OpCOzxhixSYgbRfNWcxJNJQwe2rezK9XEcssJbbWIkblaJRwGMS9zp+g== + dependencies: + "@xtuc/long" "4.2.2" + +"@webassemblyjs/utf8@1.11.0": + version "1.11.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.11.0.tgz#86e48f959cf49e0e5091f069a709b862f5a2cadf" + integrity sha512-A/lclGxH6SpSLSyFowMzO/+aDEPU4hvEiooCMXQPcQFPPJaYcPQNKGOCLUySJsYJ4trbpr+Fs08n4jelkVTGVw== + +"@webassemblyjs/wasm-edit@1.11.0": + version "1.11.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.0.tgz#ee4a5c9f677046a210542ae63897094c2027cb78" + integrity sha512-JHQ0damXy0G6J9ucyKVXO2j08JVJ2ntkdJlq1UTiUrIgfGMmA7Ik5VdC/L8hBK46kVJgujkBIoMtT8yVr+yVOQ== + dependencies: + "@webassemblyjs/ast" "1.11.0" + "@webassemblyjs/helper-buffer" "1.11.0" + "@webassemblyjs/helper-wasm-bytecode" "1.11.0" + "@webassemblyjs/helper-wasm-section" "1.11.0" + "@webassemblyjs/wasm-gen" "1.11.0" + "@webassemblyjs/wasm-opt" "1.11.0" + "@webassemblyjs/wasm-parser" "1.11.0" + "@webassemblyjs/wast-printer" "1.11.0" + +"@webassemblyjs/wasm-gen@1.11.0": + version "1.11.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.0.tgz#3cdb35e70082d42a35166988dda64f24ceb97abe" + integrity sha512-BEUv1aj0WptCZ9kIS30th5ILASUnAPEvE3tVMTrItnZRT9tXCLW2LEXT8ezLw59rqPP9klh9LPmpU+WmRQmCPQ== + dependencies: + "@webassemblyjs/ast" "1.11.0" + "@webassemblyjs/helper-wasm-bytecode" "1.11.0" + "@webassemblyjs/ieee754" "1.11.0" + "@webassemblyjs/leb128" "1.11.0" + "@webassemblyjs/utf8" "1.11.0" + +"@webassemblyjs/wasm-opt@1.11.0": + version "1.11.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.0.tgz#1638ae188137f4bb031f568a413cd24d32f92978" + integrity sha512-tHUSP5F4ywyh3hZ0+fDQuWxKx3mJiPeFufg+9gwTpYp324mPCQgnuVKwzLTZVqj0duRDovnPaZqDwoyhIO8kYg== + dependencies: + "@webassemblyjs/ast" "1.11.0" + "@webassemblyjs/helper-buffer" "1.11.0" + "@webassemblyjs/wasm-gen" "1.11.0" + "@webassemblyjs/wasm-parser" "1.11.0" + +"@webassemblyjs/wasm-parser@1.11.0": + version "1.11.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.0.tgz#3e680b8830d5b13d1ec86cc42f38f3d4a7700754" + integrity sha512-6L285Sgu9gphrcpDXINvm0M9BskznnzJTE7gYkjDbxET28shDqp27wpruyx3C2S/dvEwiigBwLA1cz7lNUi0kw== + dependencies: + "@webassemblyjs/ast" "1.11.0" + "@webassemblyjs/helper-api-error" "1.11.0" + "@webassemblyjs/helper-wasm-bytecode" "1.11.0" + "@webassemblyjs/ieee754" "1.11.0" + "@webassemblyjs/leb128" "1.11.0" + "@webassemblyjs/utf8" "1.11.0" + +"@webassemblyjs/wast-printer@1.11.0": + version "1.11.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.11.0.tgz#680d1f6a5365d6d401974a8e949e05474e1fab7e" + integrity sha512-Fg5OX46pRdTgB7rKIUojkh9vXaVN6sGYCnEiJN1GYkb0RPwShZXp6KTDqmoMdQPKhcroOXh3fEzmkWmCYaKYhQ== + dependencies: + "@webassemblyjs/ast" "1.11.0" + "@xtuc/long" "4.2.2" + +"@webpack-cli/configtest@^1.0.1": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@webpack-cli/configtest/-/configtest-1.2.0.tgz#7b20ce1c12533912c3b217ea68262365fa29a6f5" + integrity sha512-4FB8Tj6xyVkyqjj1OaTqCjXYULB9FMkqQ8yGrZjRDrYh0nOE+7Lhs45WioWQQMV+ceFlE368Ukhe6xdvJM9Egg== + +"@webpack-cli/info@^1.2.2": + version "1.5.0" + resolved "https://registry.yarnpkg.com/@webpack-cli/info/-/info-1.5.0.tgz#6c78c13c5874852d6e2dd17f08a41f3fe4c261b1" + integrity sha512-e8tSXZpw2hPl2uMJY6fsMswaok5FdlGNRTktvFk2sD8RjH0hE2+XistawJx1vmKteh4NmGmNUrp+Tb2w+udPcQ== + dependencies: + envinfo "^7.7.3" + +"@webpack-cli/serve@^1.3.0": + version "1.7.0" + resolved "https://registry.yarnpkg.com/@webpack-cli/serve/-/serve-1.7.0.tgz#e1993689ac42d2b16e9194376cfb6753f6254db1" + integrity sha512-oxnCNGj88fL+xzV+dacXs44HcDwf1ovs3AuEzvP7mqXw7fQntqIhQ1BRmynh4qEKQSSSRSWVyXRjmTbZIX9V2Q== + +"@xtuc/ieee754@^1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@xtuc/ieee754/-/ieee754-1.2.0.tgz#eef014a3145ae477a1cbc00cd1e552336dceb790" + integrity sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA== + +"@xtuc/long@4.2.2": + version "4.2.2" + resolved "https://registry.yarnpkg.com/@xtuc/long/-/long-4.2.2.tgz#d291c6a4e97989b5c61d9acf396ae4fe133a718d" + integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ== + +abab@^2.0.5: + version "2.0.6" + resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.6.tgz#41b80f2c871d19686216b82309231cfd3cb3d291" + integrity sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA== + +accepts@~1.3.4, accepts@~1.3.5, accepts@~1.3.8: + version "1.3.8" + resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e" + integrity sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw== + dependencies: + mime-types "~2.1.34" + negotiator "0.6.3" + +acorn@^8.0.4, acorn@^8.8.2: + version "8.12.1" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.12.1.tgz#71616bdccbe25e27a54439e0046e89ca76df2248" + integrity sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg== + +ajv-errors@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/ajv-errors/-/ajv-errors-1.0.1.tgz#f35986aceb91afadec4102fbd85014950cefa64d" + integrity sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ== + +ajv-keywords@^3.1.0, ajv-keywords@^3.5.2: + version "3.5.2" + resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.5.2.tgz#31f29da5ab6e00d1c2d329acf7b5929614d5014d" + integrity sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ== + +ajv@^6.1.0, ajv@^6.12.5: + version "6.12.6" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" + integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== + dependencies: + fast-deep-equal "^3.1.1" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.4.1" + uri-js "^4.2.2" + +ansi-colors@^3.0.0: + version "3.2.4" + resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-3.2.4.tgz#e3a3da4bfbae6c86a9c285625de124a234026fbf" + integrity sha512-hHUXGagefjN2iRrID63xckIvotOXOojhQKWIPUZ4mNUZ9nLZW+7FMNoE1lOkEhNWYsx/7ysGIuJYCiMAA9FnrA== + +ansi-colors@^4.1.1: + version "4.1.3" + resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.3.tgz#37611340eb2243e70cc604cad35d63270d48781b" + integrity sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw== + +ansi-html@0.0.7: + version "0.0.7" + resolved "https://registry.yarnpkg.com/ansi-html/-/ansi-html-0.0.7.tgz#813584021962a9e9e6fd039f940d12f56ca7859e" + integrity sha512-JoAxEa1DfP9m2xfB/y2r/aKcwXNlltr4+0QSBC4TrLfcxyvepX2Pv0t/xpgGV5bGsDzCYV8SzjWgyCW0T9yYbA== + +ansi-regex@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" + integrity sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA== + +ansi-regex@^4.1.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.1.tgz#164daac87ab2d6f6db3a29875e2d1766582dabed" + integrity sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g== + +ansi-regex@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" + integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== + +ansi-styles@^3.2.0: + version "3.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" + integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== + dependencies: + color-convert "^1.9.0" + +anymatch@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-2.0.0.tgz#bcb24b4f37934d9aa7ac17b4adaf89e7c76ef2eb" + integrity sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw== + dependencies: + micromatch "^3.1.4" + normalize-path "^2.1.1" + +arr-diff@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520" + integrity sha512-YVIQ82gZPGBebQV/a8dar4AitzCQs0jjXwMPZllpXMaGjXPYVUawSxQrRsjhjupyVxEvbHgUmIhKVlND+j02kA== + +arr-flatten@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1" + integrity sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg== + +arr-union@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4" + integrity sha512-sKpyeERZ02v1FeCZT8lrfJq5u6goHCtpTAzPwJYe7c8SPFOboNjNg1vz2L4VTn9T4PQxEx13TbXLmYUcS6Ug7Q== + +array-flatten@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" + integrity sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg== + +array-flatten@^2.1.0: + version "2.1.2" + resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-2.1.2.tgz#24ef80a28c1a893617e2149b0c6d0d788293b099" + integrity sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ== + +array-union@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/array-union/-/array-union-1.0.2.tgz#9a34410e4f4e3da23dea375be5be70f24778ec39" + integrity sha512-Dxr6QJj/RdU/hCaBjOfxW+q6lyuVE6JFWIrAUpuOOhoJJoQ99cUn3igRaHVB5P9WrgFVN0FfArM3x0cueOU8ng== + dependencies: + array-uniq "^1.0.1" + +array-uniq@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6" + integrity sha512-MNha4BWQ6JbwhFhj03YK552f7cb3AzoE8SzeljgChvL1dl3IcvggXVz1DilzySZkCja+CXuZbdW7yATchWn8/Q== + +array-unique@^0.3.2: + version "0.3.2" + resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" + integrity sha512-SleRWjh9JUud2wH1hPs9rZBZ33H6T9HOiL0uwGnGx9FpE6wKGyfWugmbkEOIs6qWrZhg0LWeLziLrEwQJhs5mQ== + +assign-symbols@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367" + integrity sha512-Q+JC7Whu8HhmTdBph/Tq59IoRtoy6KAm5zzPv00WdujX82lbAL8K7WVjne7vdCsAmbF4AYaDOPyO3k0kl8qIrw== + +async-each@^1.0.1: + version "1.0.6" + resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.6.tgz#52f1d9403818c179b7561e11a5d1b77eb2160e77" + integrity sha512-c646jH1avxr+aVpndVMeAfYw7wAa6idufrlN3LPA4PmKS0QEGp6PIC9nwz0WQkkvBGAMEki3pFdtxaF39J9vvg== + +async-limiter@~1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.1.tgz#dd379e94f0db8310b08291f9d64c3209766617fd" + integrity sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ== + +async@^2.6.4: + version "2.6.4" + resolved "https://registry.yarnpkg.com/async/-/async-2.6.4.tgz#706b7ff6084664cd7eae713f6f965433b5504221" + integrity sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA== + dependencies: + lodash "^4.17.14" + +atob@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" + integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== + +balanced-match@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" + integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== + +base@^0.11.1: + version "0.11.2" + resolved "https://registry.yarnpkg.com/base/-/base-0.11.2.tgz#7bde5ced145b6d551a90db87f83c558b4eb48a8f" + integrity sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg== + dependencies: + cache-base "^1.0.1" + class-utils "^0.3.5" + component-emitter "^1.2.1" + define-property "^1.0.0" + isobject "^3.0.1" + mixin-deep "^1.2.0" + pascalcase "^0.1.1" + +batch@0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/batch/-/batch-0.6.1.tgz#dc34314f4e679318093fc760272525f94bf25c16" + integrity sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw== + +binary-extensions@^1.0.0: + version "1.13.1" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.13.1.tgz#598afe54755b2868a5330d2aff9d4ebb53209b65" + integrity sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw== + +bindings@^1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.5.0.tgz#10353c9e945334bc0511a6d90b38fbc7c9c504df" + integrity sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ== + dependencies: + file-uri-to-path "1.0.0" + +body-parser@1.20.2: + version "1.20.2" + resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.2.tgz#6feb0e21c4724d06de7ff38da36dad4f57a747fd" + integrity sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA== + dependencies: + bytes "3.1.2" + content-type "~1.0.5" + debug "2.6.9" + depd "2.0.0" + destroy "1.2.0" + http-errors "2.0.0" + iconv-lite "0.4.24" + on-finished "2.4.1" + qs "6.11.0" + raw-body "2.5.2" + type-is "~1.6.18" + unpipe "1.0.0" + +bonjour@^3.5.0: + version "3.5.0" + resolved "https://registry.yarnpkg.com/bonjour/-/bonjour-3.5.0.tgz#8e890a183d8ee9a2393b3844c691a42bcf7bc9f5" + integrity sha512-RaVTblr+OnEli0r/ud8InrU7D+G0y6aJhlxaLa6Pwty4+xoxboF1BsUI45tujvRpbj9dQVoglChqonGAsjEBYg== + dependencies: + array-flatten "^2.1.0" + deep-equal "^1.0.1" + dns-equal "^1.0.0" + dns-txt "^2.0.2" + multicast-dns "^6.0.1" + multicast-dns-service-types "^1.1.0" + +brace-expansion@^1.1.7: + version "1.1.11" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" + integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + +braces@^2.3.1, braces@^2.3.2: + version "2.3.2" + resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.2.tgz#5979fd3f14cd531565e5fa2df1abfff1dfaee729" + integrity sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w== + dependencies: + arr-flatten "^1.1.0" + array-unique "^0.3.2" + extend-shallow "^2.0.1" + fill-range "^4.0.0" + isobject "^3.0.1" + repeat-element "^1.1.2" + snapdragon "^0.8.1" + snapdragon-node "^2.0.1" + split-string "^3.0.2" + to-regex "^3.0.1" + +browserslist@^4.14.5: + version "4.23.2" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.23.2.tgz#244fe803641f1c19c28c48c4b6ec9736eb3d32ed" + integrity sha512-qkqSyistMYdxAcw+CzbZwlBy8AGmS/eEWs+sEV5TnLRGDOL+C5M2EnH6tlZyg0YoAxGJAFKh61En9BR941GnHA== + dependencies: + caniuse-lite "^1.0.30001640" + electron-to-chromium "^1.4.820" + node-releases "^2.0.14" + update-browserslist-db "^1.1.0" + +buffer-from@^1.0.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" + integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== + +buffer-indexof@^1.0.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/buffer-indexof/-/buffer-indexof-1.1.1.tgz#52fabcc6a606d1a00302802648ef68f639da268c" + integrity sha512-4/rOEg86jivtPTeOUUT61jJO1Ya1TrR/OkqCSZDyq84WJh3LuuiphBYJN+fm5xufIk4XAFcEwte/8WzC8If/1g== + +bytes@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048" + integrity sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw== + +bytes@3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5" + integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg== + +cache-base@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/cache-base/-/cache-base-1.0.1.tgz#0a7f46416831c8b662ee36fe4e7c59d76f666ab2" + integrity sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ== + dependencies: + collection-visit "^1.0.0" + component-emitter "^1.2.1" + get-value "^2.0.6" + has-value "^1.0.0" + isobject "^3.0.1" + set-value "^2.0.0" + to-object-path "^0.3.0" + union-value "^1.0.0" + unset-value "^1.0.0" + +call-bind@^1.0.2, call-bind@^1.0.6, call-bind@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.7.tgz#06016599c40c56498c18769d2730be242b6fa3b9" + integrity sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w== + dependencies: + es-define-property "^1.0.0" + es-errors "^1.3.0" + function-bind "^1.1.2" + get-intrinsic "^1.2.4" + set-function-length "^1.2.1" + +camelcase@^5.0.0: + version "5.3.1" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" + integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== + +caniuse-lite@^1.0.30001640: + version "1.0.30001645" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001645.tgz#4c4b7427683dea1170a152cd1654be8d0da7bd71" + integrity sha512-GFtY2+qt91kzyMk6j48dJcwJVq5uTkk71XxE3RtScx7XWRLsO7bU44LOFkOZYR8w9YMS0UhPSYpN/6rAMImmLw== + +chokidar@^2.1.8: + version "2.1.8" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.1.8.tgz#804b3a7b6a99358c3c5c61e71d8728f041cff917" + integrity sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg== + dependencies: + anymatch "^2.0.0" + async-each "^1.0.1" + braces "^2.3.2" + glob-parent "^3.1.0" + inherits "^2.0.3" + is-binary-path "^1.0.0" + is-glob "^4.0.0" + normalize-path "^3.0.0" + path-is-absolute "^1.0.0" + readdirp "^2.2.1" + upath "^1.1.1" + optionalDependencies: + fsevents "^1.2.7" + +chrome-trace-event@^1.0.2: + version "1.0.4" + resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.4.tgz#05bffd7ff928465093314708c93bdfa9bd1f0f5b" + integrity sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ== + +class-utils@^0.3.5: + version "0.3.6" + resolved "https://registry.yarnpkg.com/class-utils/-/class-utils-0.3.6.tgz#f93369ae8b9a7ce02fd41faad0ca83033190c463" + integrity sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg== + dependencies: + arr-union "^3.1.0" + define-property "^0.2.5" + isobject "^3.0.0" + static-extend "^0.1.1" + +cliui@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-5.0.0.tgz#deefcfdb2e800784aa34f46fa08e06851c7bbbc5" + integrity sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA== + dependencies: + string-width "^3.1.0" + strip-ansi "^5.2.0" + wrap-ansi "^5.1.0" + +clone-deep@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/clone-deep/-/clone-deep-4.0.1.tgz#c19fd9bdbbf85942b4fd979c84dcf7d5f07c2387" + integrity sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ== + dependencies: + is-plain-object "^2.0.4" + kind-of "^6.0.2" + shallow-clone "^3.0.0" + +collection-visit@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/collection-visit/-/collection-visit-1.0.0.tgz#4bc0373c164bc3291b4d368c829cf1a80a59dca0" + integrity sha512-lNkKvzEeMBBjUGHZ+q6z9pSJla0KWAQPvtzhEV9+iGyQYG+pBpl7xKDhxoNSOZH2hhv0v5k0y2yAM4o4SjoSkw== + dependencies: + map-visit "^1.0.0" + object-visit "^1.0.0" + +color-convert@^1.9.0: + version "1.9.3" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" + integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== + dependencies: + color-name "1.1.3" + +color-name@1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" + integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw== + +colorette@^1.2.1: + version "1.4.0" + resolved "https://registry.yarnpkg.com/colorette/-/colorette-1.4.0.tgz#5190fbb87276259a86ad700bff2c6d6faa3fca40" + integrity sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g== + +commander@^2.20.0: + version "2.20.3" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" + integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== + +commander@^7.0.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-7.2.0.tgz#a36cb57d0b501ce108e4d20559a150a391d97ab7" + integrity sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw== + +component-emitter@^1.2.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.1.tgz#ef1d5796f7d93f135ee6fb684340b26403c97d17" + integrity sha512-T0+barUSQRTUQASh8bx02dl+DhF54GtIDY13Y3m9oWTklKbb3Wv974meRpeZ3lp1JpLVECWWNHC4vaG2XHXouQ== + +compressible@~2.0.16: + version "2.0.18" + resolved "https://registry.yarnpkg.com/compressible/-/compressible-2.0.18.tgz#af53cca6b070d4c3c0750fbd77286a6d7cc46fba" + integrity sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg== + dependencies: + mime-db ">= 1.43.0 < 2" + +compression@^1.7.4: + version "1.7.4" + resolved "https://registry.yarnpkg.com/compression/-/compression-1.7.4.tgz#95523eff170ca57c29a0ca41e6fe131f41e5bb8f" + integrity sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ== + dependencies: + accepts "~1.3.5" + bytes "3.0.0" + compressible "~2.0.16" + debug "2.6.9" + on-headers "~1.0.2" + safe-buffer "5.1.2" + vary "~1.1.2" + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== + +concat-with-sourcemaps@1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/concat-with-sourcemaps/-/concat-with-sourcemaps-1.0.7.tgz#9420e100fb984cbde11a78dca2d818306bc8f0d2" + integrity sha512-5i4Spc9NNvVXzkR77x2kjcYCDZMNPLzP7ZBzJMNKZjXzk+E6tRVL/lPlYw60VM3hb7gf+iBQn2x1T8TpMN0SEw== + dependencies: + source-map "^0.6.1" + +connect-history-api-fallback@^1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/connect-history-api-fallback/-/connect-history-api-fallback-1.6.0.tgz#8b32089359308d111115d81cad3fceab888f97bc" + integrity sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg== + +content-disposition@0.5.4: + version "0.5.4" + resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.4.tgz#8b82b4efac82512a02bb0b1dcec9d2c5e8eb5bfe" + integrity sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ== + dependencies: + safe-buffer "5.2.1" + +content-type@~1.0.4, content-type@~1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.5.tgz#8b773162656d1d1086784c8f23a54ce6d73d7918" + integrity sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA== + +cookie-signature@1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" + integrity sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ== + +cookie@0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.6.0.tgz#2798b04b071b0ecbff0dbb62a505a8efa4e19051" + integrity sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw== + +copy-descriptor@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" + integrity sha512-XgZ0pFcakEUlbwQEVNg3+QAis1FyTL3Qel9FYy8pSkQqoG3PNoT0bOCQtOXcOkur21r2Eq2kI+IE+gsmAEVlYw== + +core-util-is@~1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85" + integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ== + +cross-spawn@^6.0.0: + version "6.0.5" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" + integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ== + dependencies: + nice-try "^1.0.4" + path-key "^2.0.1" + semver "^5.5.0" + shebang-command "^1.2.0" + which "^1.2.9" + +cross-spawn@^7.0.3: + version "7.0.3" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" + integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== + dependencies: + path-key "^3.1.0" + shebang-command "^2.0.0" + which "^2.0.1" + +debug@2.6.9, debug@^2.2.0, debug@^2.3.3: + version "2.6.9" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" + integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== + dependencies: + ms "2.0.0" + +debug@^3.2.7: + version "3.2.7" + resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" + integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ== + dependencies: + ms "^2.1.1" + +debug@^4.1.0, debug@^4.1.1: + version "4.3.6" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.6.tgz#2ab2c38fbaffebf8aa95fdfe6d88438c7a13c52b" + integrity sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg== + dependencies: + ms "2.1.2" + +decamelize@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" + integrity sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA== + +decode-uri-component@^0.2.0: + version "0.2.2" + resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.2.tgz#e69dbe25d37941171dd540e024c444cd5188e1e9" + integrity sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ== + +deep-equal@^1.0.1: + version "1.1.2" + resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.1.2.tgz#78a561b7830eef3134c7f6f3a3d6af272a678761" + integrity sha512-5tdhKF6DbU7iIzrIOa1AOUt39ZRm13cmL1cGEh//aqR8x9+tNfbywRf0n5FD/18OKMdo7DNEtrX2t22ZAkI+eg== + dependencies: + is-arguments "^1.1.1" + is-date-object "^1.0.5" + is-regex "^1.1.4" + object-is "^1.1.5" + object-keys "^1.1.1" + regexp.prototype.flags "^1.5.1" + +default-gateway@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/default-gateway/-/default-gateway-4.2.0.tgz#167104c7500c2115f6dd69b0a536bb8ed720552b" + integrity sha512-h6sMrVB1VMWVrW13mSc6ia/DwYYw5MN6+exNu1OaJeFac5aSAvwM7lZ0NVfTABuSkQelr4h5oebg3KB1XPdjgA== + dependencies: + execa "^1.0.0" + ip-regex "^2.1.0" + +define-data-property@^1.0.1, define-data-property@^1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/define-data-property/-/define-data-property-1.1.4.tgz#894dc141bb7d3060ae4366f6a0107e68fbe48c5e" + integrity sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A== + dependencies: + es-define-property "^1.0.0" + es-errors "^1.3.0" + gopd "^1.0.1" + +define-properties@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.2.1.tgz#10781cc616eb951a80a034bafcaa7377f6af2b6c" + integrity sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg== + dependencies: + define-data-property "^1.0.1" + has-property-descriptors "^1.0.0" + object-keys "^1.1.1" + +define-property@^0.2.5: + version "0.2.5" + resolved "https://registry.yarnpkg.com/define-property/-/define-property-0.2.5.tgz#c35b1ef918ec3c990f9a5bc57be04aacec5c8116" + integrity sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA== + dependencies: + is-descriptor "^0.1.0" + +define-property@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/define-property/-/define-property-1.0.0.tgz#769ebaaf3f4a63aad3af9e8d304c9bbe79bfb0e6" + integrity sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA== + dependencies: + is-descriptor "^1.0.0" + +define-property@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/define-property/-/define-property-2.0.2.tgz#d459689e8d654ba77e02a817f8710d702cb16e9d" + integrity sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ== + dependencies: + is-descriptor "^1.0.2" + isobject "^3.0.1" + +del@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/del/-/del-4.1.1.tgz#9e8f117222ea44a31ff3a156c049b99052a9f0b4" + integrity sha512-QwGuEUouP2kVwQenAsOof5Fv8K9t3D8Ca8NxcXKrIpEHjTXK5J2nXLdP+ALI1cgv8wj7KuwBhTwBkOZSJKM5XQ== + dependencies: + "@types/glob" "^7.1.1" + globby "^6.1.0" + is-path-cwd "^2.0.0" + is-path-in-cwd "^2.0.0" + p-map "^2.0.0" + pify "^4.0.1" + rimraf "^2.6.3" + +depd@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" + integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw== + +depd@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" + integrity sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ== + +destroy@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.2.0.tgz#4803735509ad8be552934c67df614f94e66fa015" + integrity sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg== + +detect-node@^2.0.4: + version "2.1.0" + resolved "https://registry.yarnpkg.com/detect-node/-/detect-node-2.1.0.tgz#c9c70775a49c3d03bc2c06d9a73be550f978f8b1" + integrity sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g== + +dns-equal@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/dns-equal/-/dns-equal-1.0.0.tgz#b39e7f1da6eb0a75ba9c17324b34753c47e0654d" + integrity sha512-z+paD6YUQsk+AbGCEM4PrOXSss5gd66QfcVBFTKR/HpFL9jCqikS94HYwKww6fQyO7IxrIIyUu+g0Ka9tUS2Cg== + +dns-packet@^1.3.1: + version "1.3.4" + resolved "https://registry.yarnpkg.com/dns-packet/-/dns-packet-1.3.4.tgz#e3455065824a2507ba886c55a89963bb107dec6f" + integrity sha512-BQ6F4vycLXBvdrJZ6S3gZewt6rcrks9KBgM9vrhW+knGRqc8uEdT7fuCwloc7nny5xNoMJ17HGH0R/6fpo8ECA== + dependencies: + ip "^1.1.0" + safe-buffer "^5.0.1" + +dns-txt@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/dns-txt/-/dns-txt-2.0.2.tgz#b91d806f5d27188e4ab3e7d107d881a1cc4642b6" + integrity sha512-Ix5PrWjphuSoUXV/Zv5gaFHjnaJtb02F2+Si3Ht9dyJ87+Z/lMmy+dpNHtTGraNK958ndXq2i+GLkWsWHcKaBQ== + dependencies: + buffer-indexof "^1.0.0" + +ee-first@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" + integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow== + +electron-to-chromium@^1.4.820: + version "1.5.4" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.4.tgz#cd477c830dd6fca41fbd5465c1ff6ce08ac22343" + integrity sha512-orzA81VqLyIGUEA77YkVA1D+N+nNfl2isJVjjmOyrlxuooZ19ynb+dOlaDTqd/idKRS9lDCSBmtzM+kyCsMnkA== + +emoji-regex@^7.0.1: + version "7.0.3" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156" + integrity sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA== + +encodeurl@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" + integrity sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w== + +end-of-stream@^1.1.0: + version "1.4.4" + resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" + integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== + dependencies: + once "^1.4.0" + +enhanced-resolve@^5.7.0: + version "5.17.1" + resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.17.1.tgz#67bfbbcc2f81d511be77d686a90267ef7f898a15" + integrity sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg== + dependencies: + graceful-fs "^4.2.4" + tapable "^2.2.0" + +enquirer@^2.3.6: + version "2.4.1" + resolved "https://registry.yarnpkg.com/enquirer/-/enquirer-2.4.1.tgz#93334b3fbd74fc7097b224ab4a8fb7e40bf4ae56" + integrity sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ== + dependencies: + ansi-colors "^4.1.1" + strip-ansi "^6.0.1" + +envinfo@^7.7.3: + version "7.13.0" + resolved "https://registry.yarnpkg.com/envinfo/-/envinfo-7.13.0.tgz#81fbb81e5da35d74e814941aeab7c325a606fb31" + integrity sha512-cvcaMr7KqXVh4nyzGTVqTum+gAiL265x5jUWQIDLq//zOGbW+gSW/C+OWLleY/rs9Qole6AZLMXPbtIFQbqu+Q== + +errno@^0.1.3: + version "0.1.8" + resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.8.tgz#8bb3e9c7d463be4976ff888f76b4809ebc2e811f" + integrity sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A== + dependencies: + prr "~1.0.1" + +es-define-property@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/es-define-property/-/es-define-property-1.0.0.tgz#c7faefbdff8b2696cf5f46921edfb77cc4ba3845" + integrity sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ== + dependencies: + get-intrinsic "^1.2.4" + +es-errors@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/es-errors/-/es-errors-1.3.0.tgz#05f75a25dab98e4fb1dcd5e1472c0546d5057c8f" + integrity sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw== + +es-module-lexer@^0.4.0: + version "0.4.1" + resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-0.4.1.tgz#dda8c6a14d8f340a24e34331e0fab0cb50438e0e" + integrity sha512-ooYciCUtfw6/d2w56UVeqHPcoCFAiJdz5XOkYpv/Txl1HMUozpXjz/2RIQgqwKdXNDPSF1W7mJCFse3G+HDyAA== + +escalade@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.2.tgz#54076e9ab29ea5bf3d8f1ed62acffbb88272df27" + integrity sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA== + +escape-html@~1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" + integrity sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow== + +eslint-scope@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" + integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw== + dependencies: + esrecurse "^4.3.0" + estraverse "^4.1.1" + +esrecurse@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" + integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== + dependencies: + estraverse "^5.2.0" + +estraverse@^4.1.1: + version "4.3.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" + integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== + +estraverse@^5.2.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" + integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== + +etag@~1.8.1: + version "1.8.1" + resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" + integrity sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg== + +eventemitter3@^4.0.0: + version "4.0.7" + resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f" + integrity sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw== + +events@^3.2.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400" + integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q== + +eventsource@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/eventsource/-/eventsource-2.0.2.tgz#76dfcc02930fb2ff339520b6d290da573a9e8508" + integrity sha512-IzUmBGPR3+oUG9dUeXynyNmf91/3zUSJg1lCktzKw47OXuhco54U3r9B7O4XX+Rb1Itm9OZ2b0RkTs10bICOxA== + +execa@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/execa/-/execa-1.0.0.tgz#c6236a5bb4df6d6f15e88e7f017798216749ddd8" + integrity sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA== + dependencies: + cross-spawn "^6.0.0" + get-stream "^4.0.0" + is-stream "^1.1.0" + npm-run-path "^2.0.0" + p-finally "^1.0.0" + signal-exit "^3.0.0" + strip-eof "^1.0.0" + +execa@^5.0.0: + version "5.1.1" + resolved "https://registry.yarnpkg.com/execa/-/execa-5.1.1.tgz#f80ad9cbf4298f7bd1d4c9555c21e93741c411dd" + integrity sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg== + dependencies: + cross-spawn "^7.0.3" + get-stream "^6.0.0" + human-signals "^2.1.0" + is-stream "^2.0.0" + merge-stream "^2.0.0" + npm-run-path "^4.0.1" + onetime "^5.1.2" + signal-exit "^3.0.3" + strip-final-newline "^2.0.0" + +expand-brackets@^2.1.4: + version "2.1.4" + resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-2.1.4.tgz#b77735e315ce30f6b6eff0f83b04151a22449622" + integrity sha512-w/ozOKR9Obk3qoWeY/WDi6MFta9AoMR+zud60mdnbniMcBxRuFJyDt2LdX/14A1UABeqk+Uk+LDfUpvoGKppZA== + dependencies: + debug "^2.3.3" + define-property "^0.2.5" + extend-shallow "^2.0.1" + posix-character-classes "^0.1.0" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.1" + +express@^4.17.1: + version "4.19.2" + resolved "https://registry.yarnpkg.com/express/-/express-4.19.2.tgz#e25437827a3aa7f2a827bc8171bbbb664a356465" + integrity sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q== + dependencies: + accepts "~1.3.8" + array-flatten "1.1.1" + body-parser "1.20.2" + content-disposition "0.5.4" + content-type "~1.0.4" + cookie "0.6.0" + cookie-signature "1.0.6" + debug "2.6.9" + depd "2.0.0" + encodeurl "~1.0.2" + escape-html "~1.0.3" + etag "~1.8.1" + finalhandler "1.2.0" + fresh "0.5.2" + http-errors "2.0.0" + merge-descriptors "1.0.1" + methods "~1.1.2" + on-finished "2.4.1" + parseurl "~1.3.3" + path-to-regexp "0.1.7" + proxy-addr "~2.0.7" + qs "6.11.0" + range-parser "~1.2.1" + safe-buffer "5.2.1" + send "0.18.0" + serve-static "1.15.0" + setprototypeof "1.2.0" + statuses "2.0.1" + type-is "~1.6.18" + utils-merge "1.0.1" + vary "~1.1.2" + +extend-shallow@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" + integrity sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug== + dependencies: + is-extendable "^0.1.0" + +extend-shallow@^3.0.0, extend-shallow@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-3.0.2.tgz#26a71aaf073b39fb2127172746131c2704028db8" + integrity sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q== + dependencies: + assign-symbols "^1.0.0" + is-extendable "^1.0.1" + +extglob@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/extglob/-/extglob-2.0.4.tgz#ad00fe4dc612a9232e8718711dc5cb5ab0285543" + integrity sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw== + dependencies: + array-unique "^0.3.2" + define-property "^1.0.0" + expand-brackets "^2.1.4" + extend-shallow "^2.0.1" + fragment-cache "^0.2.1" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.1" + +fast-deep-equal@^3.1.1: + version "3.1.3" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" + integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== + +fast-json-stable-stringify@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" + integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== + +fastest-levenshtein@^1.0.12: + version "1.0.16" + resolved "https://registry.yarnpkg.com/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz#210e61b6ff181de91ea9b3d1b84fdedd47e034e5" + integrity sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg== + +faye-websocket@^0.11.3, faye-websocket@^0.11.4: + version "0.11.4" + resolved "https://registry.yarnpkg.com/faye-websocket/-/faye-websocket-0.11.4.tgz#7f0d9275cfdd86a1c963dc8b65fcc451edcbb1da" + integrity sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g== + dependencies: + websocket-driver ">=0.5.1" + +file-uri-to-path@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd" + integrity sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw== + +fill-range@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7" + integrity sha512-VcpLTWqWDiTerugjj8e3+esbg+skS3M9e54UuR3iCeIDMXCLTsAH8hTSzDQU/X6/6t3eYkOKoZSef2PlU6U1XQ== + dependencies: + extend-shallow "^2.0.1" + is-number "^3.0.0" + repeat-string "^1.6.1" + to-regex-range "^2.1.0" + +finalhandler@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.2.0.tgz#7d23fe5731b207b4640e4fcd00aec1f9207a7b32" + integrity sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg== + dependencies: + debug "2.6.9" + encodeurl "~1.0.2" + escape-html "~1.0.3" + on-finished "2.4.1" + parseurl "~1.3.3" + statuses "2.0.1" + unpipe "~1.0.0" + +find-up@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73" + integrity sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg== + dependencies: + locate-path "^3.0.0" + +find-up@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" + integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== + dependencies: + locate-path "^5.0.0" + path-exists "^4.0.0" + +flat@^5.0.2: + version "5.0.2" + resolved "https://registry.yarnpkg.com/flat/-/flat-5.0.2.tgz#8ca6fe332069ffa9d324c327198c598259ceb241" + integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ== + +follow-redirects@^1.0.0: + version "1.15.6" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.6.tgz#7f815c0cda4249c74ff09e95ef97c23b5fd0399b" + integrity sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA== + +for-in@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" + integrity sha512-7EwmXrOjyL+ChxMhmG5lnW9MPt1aIeZEwKhQzoBUdTV0N3zuwWDZYVJatDvZ2OyzPUvdIAZDsCetk3coyMfcnQ== + +forwarded@0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811" + integrity sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow== + +fragment-cache@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/fragment-cache/-/fragment-cache-0.2.1.tgz#4290fad27f13e89be7f33799c6bc5a0abfff0d19" + integrity sha512-GMBAbW9antB8iZRHLoGw0b3HANt57diZYFO/HL1JGIC1MjKrdmhxvrJbupnVvpys0zsz7yBApXdQyfepKly2kA== + dependencies: + map-cache "^0.2.2" + +fresh@0.5.2: + version "0.5.2" + resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" + integrity sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q== + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== + +fsevents@^1.2.7: + version "1.2.13" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.2.13.tgz#f325cb0455592428bcf11b383370ef70e3bfcc38" + integrity sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw== + dependencies: + bindings "^1.5.0" + nan "^2.12.1" + +function-bind@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" + integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== + +functions-have-names@^1.2.3: + version "1.2.3" + resolved "https://registry.yarnpkg.com/functions-have-names/-/functions-have-names-1.2.3.tgz#0404fe4ee2ba2f607f0e0ec3c80bae994133b834" + integrity sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ== + +get-caller-file@^2.0.1: + version "2.0.5" + resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" + integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== + +get-intrinsic@^1.1.3, get-intrinsic@^1.2.4: + version "1.2.4" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.4.tgz#e385f5a4b5227d449c3eabbad05494ef0abbeadd" + integrity sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ== + dependencies: + es-errors "^1.3.0" + function-bind "^1.1.2" + has-proto "^1.0.1" + has-symbols "^1.0.3" + hasown "^2.0.0" + +get-stream@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5" + integrity sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w== + dependencies: + pump "^3.0.0" + +get-stream@^6.0.0: + version "6.0.1" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7" + integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg== + +get-value@^2.0.3, get-value@^2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" + integrity sha512-Ln0UQDlxH1BapMu3GPtf7CuYNwRZf2gwCuPqbyG6pB8WfmFpzqcy4xtAaAMUhnNqjMKTiCPZG2oMT3YSx8U2NA== + +glob-parent@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-3.1.0.tgz#9e6af6299d8d3bd2bd40430832bd113df906c5ae" + integrity sha512-E8Ak/2+dZY6fnzlR7+ueWvhsH1SjHr4jjss4YS/h4py44jY9MhK/VFdaZJAWDz6BbL21KeteKxFSFpq8OS5gVA== + dependencies: + is-glob "^3.1.0" + path-dirname "^1.0.0" + +glob-to-regexp@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz#c75297087c851b9a578bd217dd59a92f59fe546e" + integrity sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw== + +glob@^7.0.3, glob@^7.1.3: + version "7.2.3" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" + integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.1.1" + once "^1.3.0" + path-is-absolute "^1.0.0" + +globby@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/globby/-/globby-6.1.0.tgz#f5a6d70e8395e21c858fb0489d64df02424d506c" + integrity sha512-KVbFv2TQtbzCoxAnfD6JcHZTYCzyliEaaeM/gH8qQdkKr5s0OP9scEgvdcngyk7AVdY6YVW/TJHd+lQ/Df3Daw== + dependencies: + array-union "^1.0.1" + glob "^7.0.3" + object-assign "^4.0.1" + pify "^2.0.0" + pinkie-promise "^2.0.0" + +gopd@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.0.1.tgz#29ff76de69dac7489b7c0918a5788e56477c332c" + integrity sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA== + dependencies: + get-intrinsic "^1.1.3" + +graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.2.4: + version "4.2.11" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" + integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== + +handle-thing@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/handle-thing/-/handle-thing-2.0.1.tgz#857f79ce359580c340d43081cc648970d0bb234e" + integrity sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg== + +has-flag@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" + integrity sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw== + +has-flag@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" + integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== + +has-property-descriptors@^1.0.0, has-property-descriptors@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz#963ed7d071dc7bf5f084c5bfbe0d1b6222586854" + integrity sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg== + dependencies: + es-define-property "^1.0.0" + +has-proto@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has-proto/-/has-proto-1.0.3.tgz#b31ddfe9b0e6e9914536a6ab286426d0214f77fd" + integrity sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q== + +has-symbols@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" + integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== + +has-tostringtag@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.2.tgz#2cdc42d40bef2e5b4eeab7c01a73c54ce7ab5abc" + integrity sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw== + dependencies: + has-symbols "^1.0.3" + +has-value@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/has-value/-/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f" + integrity sha512-gpG936j8/MzaeID5Yif+577c17TxaDmhuyVgSwtnL/q8UUTySg8Mecb+8Cf1otgLoD7DDH75axp86ER7LFsf3Q== + dependencies: + get-value "^2.0.3" + has-values "^0.1.4" + isobject "^2.0.0" + +has-value@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-value/-/has-value-1.0.0.tgz#18b281da585b1c5c51def24c930ed29a0be6b177" + integrity sha512-IBXk4GTsLYdQ7Rvt+GRBrFSVEkmuOUy4re0Xjd9kJSUQpnTrWR4/y9RpfexN9vkAPMFuQoeWKwqzPozRTlasGw== + dependencies: + get-value "^2.0.6" + has-values "^1.0.0" + isobject "^3.0.0" + +has-values@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/has-values/-/has-values-0.1.4.tgz#6d61de95d91dfca9b9a02089ad384bff8f62b771" + integrity sha512-J8S0cEdWuQbqD9//tlZxiMuMNmxB8PlEwvYwuxsTmR1G5RXUePEX/SJn7aD0GMLieuZYSwNH0cQuJGwnYunXRQ== + +has-values@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-values/-/has-values-1.0.0.tgz#95b0b63fec2146619a6fe57fe75628d5a39efe4f" + integrity sha512-ODYZC64uqzmtfGMEAX/FvZiRyWLpAC3vYnNunURUnkGVTS+mI0smVsWaPydRBsE3g+ok7h960jChO8mFcWlHaQ== + dependencies: + is-number "^3.0.0" + kind-of "^4.0.0" + +hasown@^2.0.0, hasown@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.2.tgz#003eaf91be7adc372e84ec59dc37252cedb80003" + integrity sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ== + dependencies: + function-bind "^1.1.2" + +hpack.js@^2.1.6: + version "2.1.6" + resolved "https://registry.yarnpkg.com/hpack.js/-/hpack.js-2.1.6.tgz#87774c0949e513f42e84575b3c45681fade2a0b2" + integrity sha512-zJxVehUdMGIKsRaNt7apO2Gqp0BdqW5yaiGHXXmbpvxgBYVZnAql+BJb4RO5ad2MgpbZKn5G6nMnegrH1FcNYQ== + dependencies: + inherits "^2.0.1" + obuf "^1.0.0" + readable-stream "^2.0.1" + wbuf "^1.1.0" + +html-entities@^1.3.1: + version "1.4.0" + resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-1.4.0.tgz#cfbd1b01d2afaf9adca1b10ae7dffab98c71d2dc" + integrity sha512-8nxjcBcd8wovbeKx7h3wTji4e6+rhaVuPNpMqwWgnHh+N9ToqsCs6XztWRBPQ+UtzsoMAdKZtUENoVzU/EMtZA== + +http-deceiver@^1.2.7: + version "1.2.7" + resolved "https://registry.yarnpkg.com/http-deceiver/-/http-deceiver-1.2.7.tgz#fa7168944ab9a519d337cb0bec7284dc3e723d87" + integrity sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw== + +http-errors@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-2.0.0.tgz#b7774a1486ef73cf7667ac9ae0858c012c57b9d3" + integrity sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ== + dependencies: + depd "2.0.0" + inherits "2.0.4" + setprototypeof "1.2.0" + statuses "2.0.1" + toidentifier "1.0.1" + +http-errors@~1.6.2: + version "1.6.3" + resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.3.tgz#8b55680bb4be283a0b5bf4ea2e38580be1d9320d" + integrity sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A== + dependencies: + depd "~1.1.2" + inherits "2.0.3" + setprototypeof "1.1.0" + statuses ">= 1.4.0 < 2" + +http-parser-js@>=0.5.1: + version "0.5.8" + resolved "https://registry.yarnpkg.com/http-parser-js/-/http-parser-js-0.5.8.tgz#af23090d9ac4e24573de6f6aecc9d84a48bf20e3" + integrity sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q== + +http-proxy-middleware@0.19.1: + version "0.19.1" + resolved "https://registry.yarnpkg.com/http-proxy-middleware/-/http-proxy-middleware-0.19.1.tgz#183c7dc4aa1479150306498c210cdaf96080a43a" + integrity sha512-yHYTgWMQO8VvwNS22eLLloAkvungsKdKTLO8AJlftYIKNfJr3GK3zK0ZCfzDDGUBttdGc8xFy1mCitvNKQtC3Q== + dependencies: + http-proxy "^1.17.0" + is-glob "^4.0.0" + lodash "^4.17.11" + micromatch "^3.1.10" + +http-proxy@^1.17.0: + version "1.18.1" + resolved "https://registry.yarnpkg.com/http-proxy/-/http-proxy-1.18.1.tgz#401541f0534884bbf95260334e72f88ee3976549" + integrity sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ== + dependencies: + eventemitter3 "^4.0.0" + follow-redirects "^1.0.0" + requires-port "^1.0.0" + +human-signals@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" + integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw== + +iconv-lite@0.4.24: + version "0.4.24" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" + integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== + dependencies: + safer-buffer ">= 2.1.2 < 3" + +iconv-lite@^0.6.2: + version "0.6.3" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.6.3.tgz#a52f80bf38da1952eb5c681790719871a1a72501" + integrity sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw== + dependencies: + safer-buffer ">= 2.1.2 < 3.0.0" + +import-local@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/import-local/-/import-local-2.0.0.tgz#55070be38a5993cf18ef6db7e961f5bee5c5a09d" + integrity sha512-b6s04m3O+s3CGSbqDIyP4R6aAwAeYlVq9+WUWep6iHa8ETRf9yei1U48C5MmfJmV9AiLYYBKPMq/W+/WRpQmCQ== + dependencies: + pkg-dir "^3.0.0" + resolve-cwd "^2.0.0" + +import-local@^3.0.2: + version "3.2.0" + resolved "https://registry.yarnpkg.com/import-local/-/import-local-3.2.0.tgz#c3d5c745798c02a6f8b897726aba5100186ee260" + integrity sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA== + dependencies: + pkg-dir "^4.2.0" + resolve-cwd "^3.0.0" + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.3: + version "2.0.4" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== + +inherits@2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" + integrity sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw== + +internal-ip@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/internal-ip/-/internal-ip-4.3.0.tgz#845452baad9d2ca3b69c635a137acb9a0dad0907" + integrity sha512-S1zBo1D6zcsyuC6PMmY5+55YMILQ9av8lotMx447Bq6SAgo/sDK6y6uUKmuYhW7eacnIhFfsPmCNYdDzsnnDCg== + dependencies: + default-gateway "^4.2.0" + ipaddr.js "^1.9.0" + +interpret@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/interpret/-/interpret-2.2.0.tgz#1a78a0b5965c40a5416d007ad6f50ad27c417df9" + integrity sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw== + +ip-regex@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/ip-regex/-/ip-regex-2.1.0.tgz#fa78bf5d2e6913c911ce9f819ee5146bb6d844e9" + integrity sha512-58yWmlHpp7VYfcdTwMTvwMmqx/Elfxjd9RXTDyMsbL7lLWmhMylLEqiYVLKuLzOZqVgiWXD9MfR62Vv89VRxkw== + +ip@^1.1.0, ip@^1.1.5: + version "1.1.9" + resolved "https://registry.yarnpkg.com/ip/-/ip-1.1.9.tgz#8dfbcc99a754d07f425310b86a99546b1151e396" + integrity sha512-cyRxvOEpNHNtchU3Ln9KC/auJgup87llfQpQ+t5ghoC/UhL16SWzbueiCsdTnWmqAWl7LadfuwhlqmtOaqMHdQ== + +ipaddr.js@1.9.1, ipaddr.js@^1.9.0: + version "1.9.1" + resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3" + integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g== + +is-absolute-url@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/is-absolute-url/-/is-absolute-url-3.0.3.tgz#96c6a22b6a23929b11ea0afb1836c36ad4a5d698" + integrity sha512-opmNIX7uFnS96NtPmhWQgQx6/NYFgsUXYMllcfzwWKUMwfo8kku1TvE6hkNcH+Q1ts5cMVrsY7j0bxXQDciu9Q== + +is-accessor-descriptor@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-1.0.1.tgz#3223b10628354644b86260db29b3e693f5ceedd4" + integrity sha512-YBUanLI8Yoihw923YeFUS5fs0fF2f5TSFTNiYAAzhhDscDa3lEqYuz1pDOEP5KvX94I9ey3vsqjJcLVFVU+3QA== + dependencies: + hasown "^2.0.0" + +is-arguments@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.1.1.tgz#15b3f88fda01f2a97fec84ca761a560f123efa9b" + integrity sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA== + dependencies: + call-bind "^1.0.2" + has-tostringtag "^1.0.0" + +is-binary-path@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-1.0.1.tgz#75f16642b480f187a711c814161fd3a4a7655898" + integrity sha512-9fRVlXc0uCxEDj1nQzaWONSpbTfx0FmJfzHF7pwlI8DkWGoHBBea4Pg5Ky0ojwwxQmnSifgbKkI06Qv0Ljgj+Q== + dependencies: + binary-extensions "^1.0.0" + +is-buffer@^1.1.5: + version "1.1.6" + resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" + integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== + +is-core-module@^2.13.0: + version "2.15.0" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.15.0.tgz#71c72ec5442ace7e76b306e9d48db361f22699ea" + integrity sha512-Dd+Lb2/zvk9SKy1TGCt1wFJFo/MWBPMX5x7KcvLajWTGuomczdQX61PvY5yK6SVACwpoexWo81IfFyoKY2QnTA== + dependencies: + hasown "^2.0.2" + +is-data-descriptor@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-1.0.1.tgz#2109164426166d32ea38c405c1e0945d9e6a4eeb" + integrity sha512-bc4NlCDiCr28U4aEsQ3Qs2491gVq4V8G7MQyws968ImqjKuYtTJXrl7Vq7jsN7Ly/C3xj5KWFrY7sHNeDkAzXw== + dependencies: + hasown "^2.0.0" + +is-date-object@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.5.tgz#0841d5536e724c25597bf6ea62e1bd38298df31f" + integrity sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ== + dependencies: + has-tostringtag "^1.0.0" + +is-descriptor@^0.1.0: + version "0.1.7" + resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-0.1.7.tgz#2727eb61fd789dcd5bdf0ed4569f551d2fe3be33" + integrity sha512-C3grZTvObeN1xud4cRWl366OMXZTj0+HGyk4hvfpx4ZHt1Pb60ANSXqCK7pdOTeUQpRzECBSTphqvD7U+l22Eg== + dependencies: + is-accessor-descriptor "^1.0.1" + is-data-descriptor "^1.0.1" + +is-descriptor@^1.0.0, is-descriptor@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-1.0.3.tgz#92d27cb3cd311c4977a4db47df457234a13cb306" + integrity sha512-JCNNGbwWZEVaSPtS45mdtrneRWJFp07LLmykxeFV5F6oBvNF8vHSfJuJgoT472pSfk+Mf8VnlrspaFBHWM8JAw== + dependencies: + is-accessor-descriptor "^1.0.1" + is-data-descriptor "^1.0.1" + +is-extendable@^0.1.0, is-extendable@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" + integrity sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw== + +is-extendable@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-1.0.1.tgz#a7470f9e426733d81bd81e1155264e3a3507cab4" + integrity sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA== + dependencies: + is-plain-object "^2.0.4" + +is-extglob@^2.1.0, is-extglob@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== + +is-fullwidth-code-point@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" + integrity sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w== + +is-glob@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-3.1.0.tgz#7ba5ae24217804ac70707b96922567486cc3e84a" + integrity sha512-UFpDDrPgM6qpnFNI+rh/p3bUaq9hKLZN8bMUWzxmcnZVS3omf4IPK+BrewlnWjO1WmUsMYuSjKh4UJuV4+Lqmw== + dependencies: + is-extglob "^2.1.0" + +is-glob@^4.0.0: + version "4.0.3" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" + integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== + dependencies: + is-extglob "^2.1.1" + +is-number@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" + integrity sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg== + dependencies: + kind-of "^3.0.2" + +is-path-cwd@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-2.2.0.tgz#67d43b82664a7b5191fd9119127eb300048a9fdb" + integrity sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ== + +is-path-in-cwd@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-path-in-cwd/-/is-path-in-cwd-2.1.0.tgz#bfe2dca26c69f397265a4009963602935a053acb" + integrity sha512-rNocXHgipO+rvnP6dk3zI20RpOtrAM/kzbB258Uw5BWr3TpXi861yzjo16Dn4hUox07iw5AyeMLHWsujkjzvRQ== + dependencies: + is-path-inside "^2.1.0" + +is-path-inside@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-2.1.0.tgz#7c9810587d659a40d27bcdb4d5616eab059494b2" + integrity sha512-wiyhTzfDWsvwAW53OBWF5zuvaOGlZ6PwYxAbPVDhpm+gM09xKQGjBq/8uYN12aDvMxnAnq3dxTyoSoRNmg5YFg== + dependencies: + path-is-inside "^1.0.2" + +is-plain-object@^2.0.3, is-plain-object@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" + integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og== + dependencies: + isobject "^3.0.1" + +is-regex@^1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.4.tgz#eef5663cd59fa4c0ae339505323df6854bb15958" + integrity sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg== + dependencies: + call-bind "^1.0.2" + has-tostringtag "^1.0.0" + +is-stream@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" + integrity sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ== + +is-stream@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077" + integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg== + +is-windows@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" + integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA== + +is-wsl@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-1.1.0.tgz#1f16e4aa22b04d1336b66188a66af3c600c3a66d" + integrity sha512-gfygJYZ2gLTDlmbWMI0CE2MwnFzSN/2SZfkMlItC4K/JBlsWVDB0bO6XhqcY13YXE7iMcAJnzTCJjPiTeJJ0Mw== + +isarray@1.0.0, isarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" + integrity sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ== + +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== + +isobject@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89" + integrity sha512-+OUdGJlgjOBZDfxnDjYYG6zp487z0JGNQq3cYQYg5f5hKR+syHMsaztzGeml/4kGG55CSpKSpWTY+jYGgsHLgA== + dependencies: + isarray "1.0.0" + +isobject@^3.0.0, isobject@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" + integrity sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg== + +jest-worker@^27.4.5: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-27.5.1.tgz#8d146f0900e8973b106b6f73cc1e9a8cb86f8db0" + integrity sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg== + dependencies: + "@types/node" "*" + merge-stream "^2.0.0" + supports-color "^8.0.0" + +json-parse-better-errors@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" + integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw== + +json-schema-traverse@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" + integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== + +killable@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/killable/-/killable-1.0.1.tgz#4c8ce441187a061c7474fb87ca08e2a638194892" + integrity sha512-LzqtLKlUwirEUyl/nicirVmNiPvYs7l5n8wOPP7fyJVpUPkvCnW/vuiXGpylGUlnPDnB7311rARzAt3Mhswpjg== + +kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0: + version "3.2.2" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" + integrity sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ== + dependencies: + is-buffer "^1.1.5" + +kind-of@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-4.0.0.tgz#20813df3d712928b207378691a45066fae72dd57" + integrity sha512-24XsCxmEbRwEDbz/qz3stgin8TTzZ1ESR56OMCN0ujYg+vRutNSiOj9bHH9u85DKgXguraugV5sFuvbD4FW/hw== + dependencies: + is-buffer "^1.1.5" + +kind-of@^6.0.2: + version "6.0.3" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" + integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== + +loader-runner@^4.2.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-4.3.0.tgz#c1b4a163b99f614830353b16755e7149ac2314e1" + integrity sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg== + +locate-path@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e" + integrity sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A== + dependencies: + p-locate "^3.0.0" + path-exists "^3.0.0" + +locate-path@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" + integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== + dependencies: + p-locate "^4.1.0" + +lodash@^4.17.11, lodash@^4.17.14: + version "4.17.21" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" + integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== + +loglevel@^1.6.8: + version "1.9.1" + resolved "https://registry.yarnpkg.com/loglevel/-/loglevel-1.9.1.tgz#d63976ac9bcd03c7c873116d41c2a85bafff1be7" + integrity sha512-hP3I3kCrDIMuRwAwHltphhDM1r8i55H33GgqjXbrisuJhF4kRhW1dNuxsRklp4bXl8DSdLaNLuiL4A/LWRfxvg== + +map-cache@^0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf" + integrity sha512-8y/eV9QQZCiyn1SprXSrCmqJN0yNRATe+PO8ztwqrvrbdRLA3eYJF0yaR0YayLWkMbsQSKWS9N2gPcGEc4UsZg== + +map-visit@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/map-visit/-/map-visit-1.0.0.tgz#ecdca8f13144e660f1b5bd41f12f3479d98dfb8f" + integrity sha512-4y7uGv8bd2WdM9vpQsiQNo41Ln1NvhvDRuVt0k2JZQ+ezN2uaQes7lZeZ+QQUHOLQAtDaBJ+7wCbi+ab/KFs+w== + dependencies: + object-visit "^1.0.0" + +media-typer@0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" + integrity sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ== + +memory-fs@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.4.1.tgz#3a9a20b8462523e447cfbc7e8bb80ed667bfc552" + integrity sha512-cda4JKCxReDXFXRqOHPQscuIYg1PvxbE2S2GP45rnwfEK+vZaXC8C1OFvdHIbgw0DLzowXGVoxLaAmlgRy14GQ== + dependencies: + errno "^0.1.3" + readable-stream "^2.0.1" + +merge-descriptors@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" + integrity sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w== + +merge-stream@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" + integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== + +methods@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" + integrity sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w== + +micromatch@^3.1.10, micromatch@^3.1.4: + version "3.1.10" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23" + integrity sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg== + dependencies: + arr-diff "^4.0.0" + array-unique "^0.3.2" + braces "^2.3.1" + define-property "^2.0.2" + extend-shallow "^3.0.2" + extglob "^2.0.4" + fragment-cache "^0.2.1" + kind-of "^6.0.2" + nanomatch "^1.2.9" + object.pick "^1.3.0" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.2" + +mime-db@1.52.0: + version "1.52.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" + integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== + +"mime-db@>= 1.43.0 < 2": + version "1.53.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.53.0.tgz#3cb63cd820fc29896d9d4e8c32ab4fcd74ccb447" + integrity sha512-oHlN/w+3MQ3rba9rqFr6V/ypF10LSkdwUysQL7GkXoTgIWeV+tcXGA852TBxH+gsh8UWoyhR1hKcoMJTuWflpg== + +mime-types@^2.1.27, mime-types@~2.1.17, mime-types@~2.1.24, mime-types@~2.1.34: + version "2.1.35" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" + integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== + dependencies: + mime-db "1.52.0" + +mime@1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" + integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== + +mime@^2.4.4: + version "2.6.0" + resolved "https://registry.yarnpkg.com/mime/-/mime-2.6.0.tgz#a2a682a95cd4d0cb1d6257e28f83da7e35800367" + integrity sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg== + +mimic-fn@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" + integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== + +minimalistic-assert@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" + integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A== + +minimatch@^3.1.1: + version "3.1.2" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" + integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== + dependencies: + brace-expansion "^1.1.7" + +minimist@^1.2.6: + version "1.2.8" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" + integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== + +mixin-deep@^1.2.0: + version "1.3.2" + resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.2.tgz#1120b43dc359a785dce65b55b82e257ccf479566" + integrity sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA== + dependencies: + for-in "^1.0.2" + is-extendable "^1.0.1" + +mkdirp@^0.5.1, mkdirp@^0.5.6: + version "0.5.6" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.6.tgz#7def03d2432dcae4ba1d611445c48396062255f6" + integrity sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw== + dependencies: + minimist "^1.2.6" + +ms@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" + integrity sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A== + +ms@2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" + integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== + +ms@2.1.3, ms@^2.1.1: + version "2.1.3" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" + integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== + +multicast-dns-service-types@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/multicast-dns-service-types/-/multicast-dns-service-types-1.1.0.tgz#899f11d9686e5e05cb91b35d5f0e63b773cfc901" + integrity sha512-cnAsSVxIDsYt0v7HmC0hWZFwwXSh+E6PgCrREDuN/EsjgLwA5XRmlMHhSiDPrt6HxY1gTivEa/Zh7GtODoLevQ== + +multicast-dns@^6.0.1: + version "6.2.3" + resolved "https://registry.yarnpkg.com/multicast-dns/-/multicast-dns-6.2.3.tgz#a0ec7bd9055c4282f790c3c82f4e28db3b31b229" + integrity sha512-ji6J5enbMyGRHIAkAOu3WdV8nggqviKCEKtXcOqfphZZtQrmHKycfynJ2V7eVPUA4NhJ6V7Wf4TmGbTwKE9B6g== + dependencies: + dns-packet "^1.3.1" + thunky "^1.0.2" + +nan@^2.12.1: + version "2.20.0" + resolved "https://registry.yarnpkg.com/nan/-/nan-2.20.0.tgz#08c5ea813dd54ed16e5bd6505bf42af4f7838ca3" + integrity sha512-bk3gXBZDGILuuo/6sKtr0DQmSThYHLtNCdSdXk9YkxD/jK6X2vmCyyXBBxyqZ4XcnzTyYEAThfX3DCEnLf6igw== + +nanomatch@^1.2.9: + version "1.2.13" + resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119" + integrity sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA== + dependencies: + arr-diff "^4.0.0" + array-unique "^0.3.2" + define-property "^2.0.2" + extend-shallow "^3.0.2" + fragment-cache "^0.2.1" + is-windows "^1.0.2" + kind-of "^6.0.2" + object.pick "^1.3.0" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.1" + +negotiator@0.6.3: + version "0.6.3" + resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" + integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg== + +neo-async@^2.6.2: + version "2.6.2" + resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" + integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== + +nice-try@^1.0.4: + version "1.0.5" + resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" + integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== + +node-forge@^0.10.0: + version "0.10.0" + resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-0.10.0.tgz#32dea2afb3e9926f02ee5ce8794902691a676bf3" + integrity sha512-PPmu8eEeG9saEUvI97fm4OYxXVB6bFvyNTyiUOBichBpFG8A1Ljw3bY62+5oOjDEMHRnd0Y7HQ+x7uzxOzC6JA== + +node-releases@^2.0.14: + version "2.0.18" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.18.tgz#f010e8d35e2fe8d6b2944f03f70213ecedc4ca3f" + integrity sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g== + +normalize-path@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9" + integrity sha512-3pKJwH184Xo/lnH6oyP1q2pMd7HcypqqmRs91/6/i2CGtWwIKGCkOOMTm/zXbgTEWHw1uNpNi/igc3ePOYHb6w== + dependencies: + remove-trailing-separator "^1.0.1" + +normalize-path@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" + integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== + +npm-run-path@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f" + integrity sha512-lJxZYlT4DW/bRUtFh1MQIWqmLwQfAxnqWG4HhEdjMlkrJYnJn0Jrr2u3mgxqaWsdiBc76TYkTG/mhrnYTuzfHw== + dependencies: + path-key "^2.0.0" + +npm-run-path@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea" + integrity sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw== + dependencies: + path-key "^3.0.0" + +object-assign@^4.0.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" + integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== + +object-copy@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/object-copy/-/object-copy-0.1.0.tgz#7e7d858b781bd7c991a41ba975ed3812754e998c" + integrity sha512-79LYn6VAb63zgtmAteVOWo9Vdj71ZVBy3Pbse+VqxDpEP83XuujMrGqHIwAXJ5I/aM0zU7dIyIAhifVTPrNItQ== + dependencies: + copy-descriptor "^0.1.0" + define-property "^0.2.5" + kind-of "^3.0.3" + +object-inspect@^1.13.1: + version "1.13.2" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.2.tgz#dea0088467fb991e67af4058147a24824a3043ff" + integrity sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g== + +object-is@^1.1.5: + version "1.1.6" + resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.1.6.tgz#1a6a53aed2dd8f7e6775ff870bea58545956ab07" + integrity sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q== + dependencies: + call-bind "^1.0.7" + define-properties "^1.2.1" + +object-keys@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" + integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== + +object-visit@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/object-visit/-/object-visit-1.0.1.tgz#f79c4493af0c5377b59fe39d395e41042dd045bb" + integrity sha512-GBaMwwAVK9qbQN3Scdo0OyvgPW7l3lnaVMj84uTOZlswkX0KpF6fyDBJhtTthf7pymztoN36/KEr1DyhF96zEA== + dependencies: + isobject "^3.0.0" + +object.pick@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/object.pick/-/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747" + integrity sha512-tqa/UMy/CCoYmj+H5qc07qvSL9dqcs/WZENZ1JbtWBlATP+iVOe778gE6MSijnyCnORzDuX6hU+LA4SZ09YjFQ== + dependencies: + isobject "^3.0.1" + +obuf@^1.0.0, obuf@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/obuf/-/obuf-1.1.2.tgz#09bea3343d41859ebd446292d11c9d4db619084e" + integrity sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg== + +on-finished@2.4.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.4.1.tgz#58c8c44116e54845ad57f14ab10b03533184ac3f" + integrity sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg== + dependencies: + ee-first "1.1.1" + +on-headers@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/on-headers/-/on-headers-1.0.2.tgz#772b0ae6aaa525c399e489adfad90c403eb3c28f" + integrity sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA== + +once@^1.3.0, once@^1.3.1, once@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== + dependencies: + wrappy "1" + +onetime@^5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e" + integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg== + dependencies: + mimic-fn "^2.1.0" + +opn@^5.5.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/opn/-/opn-5.5.0.tgz#fc7164fab56d235904c51c3b27da6758ca3b9bfc" + integrity sha512-PqHpggC9bLV0VeWcdKhkpxY+3JTzetLSqTCWL/z/tFIbI6G8JCjondXklT1JinczLz2Xib62sSp0T/gKT4KksA== + dependencies: + is-wsl "^1.1.0" + +p-finally@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" + integrity sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow== + +p-limit@^2.0.0, p-limit@^2.2.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" + integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== + dependencies: + p-try "^2.0.0" + +p-locate@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-3.0.0.tgz#322d69a05c0264b25997d9f40cd8a891ab0064a4" + integrity sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ== + dependencies: + p-limit "^2.0.0" + +p-locate@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" + integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== + dependencies: + p-limit "^2.2.0" + +p-map@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/p-map/-/p-map-2.1.0.tgz#310928feef9c9ecc65b68b17693018a665cea175" + integrity sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw== + +p-retry@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/p-retry/-/p-retry-3.0.1.tgz#316b4c8893e2c8dc1cfa891f406c4b422bebf328" + integrity sha512-XE6G4+YTTkT2a0UWb2kjZe8xNwf8bIbnqpc/IS/idOBVhyves0mK5OJgeocjx7q5pvX/6m23xuzVPYT1uGM73w== + dependencies: + retry "^0.12.0" + +p-try@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" + integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== + +parseurl@~1.3.2, parseurl@~1.3.3: + version "1.3.3" + resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" + integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== + +pascalcase@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" + integrity sha512-XHXfu/yOQRy9vYOtUDVMN60OEJjW013GoObG1o+xwQTpB9eYJX/BjXMsdW13ZDPruFhYYn0AG22w0xgQMwl3Nw== + +path-dirname@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/path-dirname/-/path-dirname-1.0.2.tgz#cc33d24d525e099a5388c0336c6e32b9160609e0" + integrity sha512-ALzNPpyNq9AqXMBjeymIjFDAkAFH06mHJH/cSBHAgU0s4vfpBn6b2nf8tiRLvagKD8RbTpq2FKTBg7cl9l3c7Q== + +path-exists@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" + integrity sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ== + +path-exists@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" + integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== + +path-is-absolute@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== + +path-is-inside@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53" + integrity sha512-DUWJr3+ULp4zXmol/SZkFf3JGsS9/SIv+Y3Rt93/UjPpDpklB5f1er4O3POIbUuUJ3FXgqte2Q7SrU6zAqwk8w== + +path-key@^2.0.0, path-key@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" + integrity sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw== + +path-key@^3.0.0, path-key@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" + integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== + +path-parse@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" + integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== + +path-to-regexp@0.1.7: + version "0.1.7" + resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" + integrity sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ== + +picocolors@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.1.tgz#a8ad579b571952f0e5d25892de5445bcfe25aaa1" + integrity sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew== + +pify@^2.0.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" + integrity sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog== + +pify@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/pify/-/pify-4.0.1.tgz#4b2cd25c50d598735c50292224fd8c6df41e3231" + integrity sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g== + +pinkie-promise@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa" + integrity sha512-0Gni6D4UcLTbv9c57DfxDGdr41XfgUjqWZu492f0cIGr16zDU06BWP/RAEvOuo7CQ0CNjHaLlM59YJJFm3NWlw== + dependencies: + pinkie "^2.0.0" + +pinkie@^2.0.0: + version "2.0.4" + resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" + integrity sha512-MnUuEycAemtSaeFSjXKW/aroV7akBbY+Sv+RkyqFjgAe73F+MR0TBWKBRDkmfWq/HiFmdavfZ1G7h4SPZXaCSg== + +pkg-dir@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-3.0.0.tgz#2749020f239ed990881b1f71210d51eb6523bea3" + integrity sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw== + dependencies: + find-up "^3.0.0" + +pkg-dir@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" + integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ== + dependencies: + find-up "^4.0.0" + +portfinder@^1.0.26: + version "1.0.32" + resolved "https://registry.yarnpkg.com/portfinder/-/portfinder-1.0.32.tgz#2fe1b9e58389712429dc2bea5beb2146146c7f81" + integrity sha512-on2ZJVVDXRADWE6jnQaX0ioEylzgBpQk8r55NE4wjXW1ZxO+BgDlY6DXwj20i0V8eB4SenDQ00WEaxfiIQPcxg== + dependencies: + async "^2.6.4" + debug "^3.2.7" + mkdirp "^0.5.6" + +posix-character-classes@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" + integrity sha512-xTgYBc3fuo7Yt7JbiuFxSYGToMoz8fLoE6TC9Wx1P/u+LfeThMOAqmuyECnlBaaJb+u1m9hHiXUEtwW4OzfUJg== + +process-nextick-args@~2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" + integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== + +proxy-addr@~2.0.7: + version "2.0.7" + resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.7.tgz#f19fe69ceab311eeb94b42e70e8c2070f9ba1025" + integrity sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg== + dependencies: + forwarded "0.2.0" + ipaddr.js "1.9.1" + +prr@~1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476" + integrity sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw== + +pump@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64" + integrity sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww== + dependencies: + end-of-stream "^1.1.0" + once "^1.3.1" + +punycode@^1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" + integrity sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ== + +punycode@^2.1.0: + version "2.3.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5" + integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg== + +qs@6.11.0: + version "6.11.0" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.0.tgz#fd0d963446f7a65e1367e01abd85429453f0c37a" + integrity sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q== + dependencies: + side-channel "^1.0.4" + +qs@^6.12.3: + version "6.12.3" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.12.3.tgz#e43ce03c8521b9c7fd7f1f13e514e5ca37727754" + integrity sha512-AWJm14H1vVaO/iNZ4/hO+HyaTehuy9nRqVdkTqlJt0HWvBiBIEXFmb4C0DGeYo3Xes9rrEW+TxHsaigCbN5ICQ== + dependencies: + side-channel "^1.0.6" + +querystringify@^2.1.1: + version "2.2.0" + resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-2.2.0.tgz#3345941b4153cb9d082d8eee4cda2016a9aef7f6" + integrity sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ== + +randombytes@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" + integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== + dependencies: + safe-buffer "^5.1.0" + +range-parser@^1.2.1, range-parser@~1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" + integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== + +raw-body@2.5.2: + version "2.5.2" + resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.5.2.tgz#99febd83b90e08975087e8f1f9419a149366b68a" + integrity sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA== + dependencies: + bytes "3.1.2" + http-errors "2.0.0" + iconv-lite "0.4.24" + unpipe "1.0.0" + +readable-stream@^2.0.1, readable-stream@^2.0.2: + version "2.3.8" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.8.tgz#91125e8042bba1b9887f49345f6277027ce8be9b" + integrity sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA== + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.3" + isarray "~1.0.0" + process-nextick-args "~2.0.0" + safe-buffer "~5.1.1" + string_decoder "~1.1.1" + util-deprecate "~1.0.1" + +readable-stream@^3.0.6: + version "3.6.2" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967" + integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== + dependencies: + inherits "^2.0.3" + string_decoder "^1.1.1" + util-deprecate "^1.0.1" + +readdirp@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-2.2.1.tgz#0e87622a3325aa33e892285caf8b4e846529a525" + integrity sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ== + dependencies: + graceful-fs "^4.1.11" + micromatch "^3.1.10" + readable-stream "^2.0.2" + +rechoir@^0.7.0: + version "0.7.1" + resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.7.1.tgz#9478a96a1ca135b5e88fc027f03ee92d6c645686" + integrity sha512-/njmZ8s1wVeR6pjTZ+0nCnv8SpZNRMT2D1RLOJQESlYFDBvwpTA4KWJpZ+sBJ4+vhjILRcK7JIFdGCdxEAAitg== + dependencies: + resolve "^1.9.0" + +regex-not@^1.0.0, regex-not@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/regex-not/-/regex-not-1.0.2.tgz#1f4ece27e00b0b65e0247a6810e6a85d83a5752c" + integrity sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A== + dependencies: + extend-shallow "^3.0.2" + safe-regex "^1.1.0" + +regexp.prototype.flags@^1.5.1: + version "1.5.2" + resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz#138f644a3350f981a858c44f6bb1a61ff59be334" + integrity sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw== + dependencies: + call-bind "^1.0.6" + define-properties "^1.2.1" + es-errors "^1.3.0" + set-function-name "^2.0.1" + +remove-trailing-separator@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" + integrity sha512-/hS+Y0u3aOfIETiaiirUFwDBDzmXPvO+jAfKTitUngIPzdKc6Z0LoFjM/CK5PL4C+eKwHohlHAb6H0VFfmmUsw== + +repeat-element@^1.1.2: + version "1.1.4" + resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.4.tgz#be681520847ab58c7568ac75fbfad28ed42d39e9" + integrity sha512-LFiNfRcSu7KK3evMyYOuCzv3L10TW7yC1G2/+StMjK8Y6Vqd2MG7r/Qjw4ghtuCOjFvlnms/iMmLqpvW/ES/WQ== + +repeat-string@^1.6.1: + version "1.6.1" + resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" + integrity sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w== + +require-directory@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" + integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== + +require-main-filename@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b" + integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg== + +requires-port@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" + integrity sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ== + +resolve-cwd@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-2.0.0.tgz#00a9f7387556e27038eae232caa372a6a59b665a" + integrity sha512-ccu8zQTrzVr954472aUVPLEcB3YpKSYR3cg/3lo1okzobPBM+1INXBbBZlDbnI/hbEocnf8j0QVo43hQKrbchg== + dependencies: + resolve-from "^3.0.0" + +resolve-cwd@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-3.0.0.tgz#0f0075f1bb2544766cf73ba6a6e2adfebcb13f2d" + integrity sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg== + dependencies: + resolve-from "^5.0.0" + +resolve-from@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-3.0.0.tgz#b22c7af7d9d6881bc8b6e653335eebcb0a188748" + integrity sha512-GnlH6vxLymXJNMBo7XP1fJIzBFbdYt49CuTwmB/6N53t+kMPRMFKz783LlQ4tv28XoQfMWinAJX6WCGf2IlaIw== + +resolve-from@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" + integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== + +resolve-url@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" + integrity sha512-ZuF55hVUQaaczgOIwqWzkEcEidmlD/xl44x1UZnhOXcYuFN2S6+rcxpG+C1N3So0wvNI3DmJICUFfu2SxhBmvg== + +resolve@^1.9.0: + version "1.22.8" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.8.tgz#b6c87a9f2aa06dfab52e3d70ac8cde321fa5a48d" + integrity sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw== + dependencies: + is-core-module "^2.13.0" + path-parse "^1.0.7" + supports-preserve-symlinks-flag "^1.0.0" + +ret@~0.1.10: + version "0.1.15" + resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" + integrity sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg== + +retry@^0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/retry/-/retry-0.12.0.tgz#1b42a6266a21f07421d1b0b54b7dc167b01c013b" + integrity sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow== + +rimraf@^2.6.3: + version "2.7.1" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" + integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== + dependencies: + glob "^7.1.3" + +safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: + version "5.1.2" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" + integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== + +safe-buffer@5.2.1, safe-buffer@>=5.1.0, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@~5.2.0: + version "5.2.1" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" + integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== + +safe-regex@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/safe-regex/-/safe-regex-1.1.0.tgz#40a3669f3b077d1e943d44629e157dd48023bf2e" + integrity sha512-aJXcif4xnaNUzvUuC5gcb46oTS7zvg4jpMTnuqtrEPlR3vFr4pxtdTwaF1Qs3Enjn9HK+ZlwQui+a7z0SywIzg== + dependencies: + ret "~0.1.10" + +"safer-buffer@>= 2.1.2 < 3", "safer-buffer@>= 2.1.2 < 3.0.0": + version "2.1.2" + resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" + integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== + +schema-utils@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-1.0.0.tgz#0b79a93204d7b600d4b2850d1f66c2a34951c770" + integrity sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g== + dependencies: + ajv "^6.1.0" + ajv-errors "^1.0.0" + ajv-keywords "^3.1.0" + +schema-utils@^3.0.0, schema-utils@^3.1.1: + version "3.3.0" + resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-3.3.0.tgz#f50a88877c3c01652a15b622ae9e9795df7a60fe" + integrity sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg== + dependencies: + "@types/json-schema" "^7.0.8" + ajv "^6.12.5" + ajv-keywords "^3.5.2" + +select-hose@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/select-hose/-/select-hose-2.0.0.tgz#625d8658f865af43ec962bfc376a37359a4994ca" + integrity sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg== + +selfsigned@^1.10.8: + version "1.10.14" + resolved "https://registry.yarnpkg.com/selfsigned/-/selfsigned-1.10.14.tgz#ee51d84d9dcecc61e07e4aba34f229ab525c1574" + integrity sha512-lkjaiAye+wBZDCBsu5BGi0XiLRxeUlsGod5ZP924CRSEoGuZAw/f7y9RKu28rwTfiHVhdavhB0qH0INV6P1lEA== + dependencies: + node-forge "^0.10.0" + +semver@^5.5.0: + version "5.7.2" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8" + integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g== + +semver@^6.3.0: + version "6.3.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" + integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== + +send@0.18.0: + version "0.18.0" + resolved "https://registry.yarnpkg.com/send/-/send-0.18.0.tgz#670167cc654b05f5aa4a767f9113bb371bc706be" + integrity sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg== + dependencies: + debug "2.6.9" + depd "2.0.0" + destroy "1.2.0" + encodeurl "~1.0.2" + escape-html "~1.0.3" + etag "~1.8.1" + fresh "0.5.2" + http-errors "2.0.0" + mime "1.6.0" + ms "2.1.3" + on-finished "2.4.1" + range-parser "~1.2.1" + statuses "2.0.1" + +serialize-javascript@^6.0.1: + version "6.0.2" + resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.2.tgz#defa1e055c83bf6d59ea805d8da862254eb6a6c2" + integrity sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g== + dependencies: + randombytes "^2.1.0" + +serve-index@^1.9.1: + version "1.9.1" + resolved "https://registry.yarnpkg.com/serve-index/-/serve-index-1.9.1.tgz#d3768d69b1e7d82e5ce050fff5b453bea12a9239" + integrity sha512-pXHfKNP4qujrtteMrSBb0rc8HJ9Ms/GrXwcUtUtD5s4ewDJI8bT3Cz2zTVRMKtri49pLx2e0Ya8ziP5Ya2pZZw== + dependencies: + accepts "~1.3.4" + batch "0.6.1" + debug "2.6.9" + escape-html "~1.0.3" + http-errors "~1.6.2" + mime-types "~2.1.17" + parseurl "~1.3.2" + +serve-static@1.15.0: + version "1.15.0" + resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.15.0.tgz#faaef08cffe0a1a62f60cad0c4e513cff0ac9540" + integrity sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g== + dependencies: + encodeurl "~1.0.2" + escape-html "~1.0.3" + parseurl "~1.3.3" + send "0.18.0" + +set-blocking@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" + integrity sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw== + +set-function-length@^1.2.1: + version "1.2.2" + resolved "https://registry.yarnpkg.com/set-function-length/-/set-function-length-1.2.2.tgz#aac72314198eaed975cf77b2c3b6b880695e5449" + integrity sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg== + dependencies: + define-data-property "^1.1.4" + es-errors "^1.3.0" + function-bind "^1.1.2" + get-intrinsic "^1.2.4" + gopd "^1.0.1" + has-property-descriptors "^1.0.2" + +set-function-name@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/set-function-name/-/set-function-name-2.0.2.tgz#16a705c5a0dc2f5e638ca96d8a8cd4e1c2b90985" + integrity sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ== + dependencies: + define-data-property "^1.1.4" + es-errors "^1.3.0" + functions-have-names "^1.2.3" + has-property-descriptors "^1.0.2" + +set-value@^2.0.0, set-value@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/set-value/-/set-value-2.0.1.tgz#a18d40530e6f07de4228c7defe4227af8cad005b" + integrity sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw== + dependencies: + extend-shallow "^2.0.1" + is-extendable "^0.1.1" + is-plain-object "^2.0.3" + split-string "^3.0.1" + +setprototypeof@1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.0.tgz#d0bd85536887b6fe7c0d818cb962d9d91c54e656" + integrity sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ== + +setprototypeof@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424" + integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw== + +shallow-clone@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/shallow-clone/-/shallow-clone-3.0.1.tgz#8f2981ad92531f55035b01fb230769a40e02efa3" + integrity sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA== + dependencies: + kind-of "^6.0.2" + +shebang-command@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" + integrity sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg== + dependencies: + shebang-regex "^1.0.0" + +shebang-command@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" + integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== + dependencies: + shebang-regex "^3.0.0" + +shebang-regex@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" + integrity sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ== + +shebang-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" + integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== + +side-channel@^1.0.4, side-channel@^1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.6.tgz#abd25fb7cd24baf45466406b1096b7831c9215f2" + integrity sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA== + dependencies: + call-bind "^1.0.7" + es-errors "^1.3.0" + get-intrinsic "^1.2.4" + object-inspect "^1.13.1" + +sigmajs-crypto-facade@0.0.7: + version "0.0.7" + resolved "https://registry.yarnpkg.com/sigmajs-crypto-facade/-/sigmajs-crypto-facade-0.0.7.tgz#b81dd53750c38a6a7856153aad2705269bc5afb6" + integrity sha512-4XK8ZS9NKAbo8aGnU6o5GkBW6Upl8+OK8A1KreVDMAamfvZ0iq4LoVH8rHaeEPf9moVtaC4QZY5RYI+0OwiydA== + dependencies: + "@noble/hashes" "^1.1.4" + +signal-exit@^3.0.0, signal-exit@^3.0.3: + version "3.0.7" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" + integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== + +snapdragon-node@^2.0.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/snapdragon-node/-/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b" + integrity sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw== + dependencies: + define-property "^1.0.0" + isobject "^3.0.0" + snapdragon-util "^3.0.1" + +snapdragon-util@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/snapdragon-util/-/snapdragon-util-3.0.1.tgz#f956479486f2acd79700693f6f7b805e45ab56e2" + integrity sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ== + dependencies: + kind-of "^3.2.0" + +snapdragon@^0.8.1: + version "0.8.2" + resolved "https://registry.yarnpkg.com/snapdragon/-/snapdragon-0.8.2.tgz#64922e7c565b0e14204ba1aa7d6964278d25182d" + integrity sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg== + dependencies: + base "^0.11.1" + debug "^2.2.0" + define-property "^0.2.5" + extend-shallow "^2.0.1" + map-cache "^0.2.2" + source-map "^0.5.6" + source-map-resolve "^0.5.0" + use "^3.1.0" + +sockjs-client@^1.5.0: + version "1.6.1" + resolved "https://registry.yarnpkg.com/sockjs-client/-/sockjs-client-1.6.1.tgz#350b8eda42d6d52ddc030c39943364c11dcad806" + integrity sha512-2g0tjOR+fRs0amxENLi/q5TiJTqY+WXFOzb5UwXndlK6TO3U/mirZznpx6w34HVMoc3g7cY24yC/ZMIYnDlfkw== + dependencies: + debug "^3.2.7" + eventsource "^2.0.2" + faye-websocket "^0.11.4" + inherits "^2.0.4" + url-parse "^1.5.10" + +sockjs@^0.3.21: + version "0.3.24" + resolved "https://registry.yarnpkg.com/sockjs/-/sockjs-0.3.24.tgz#c9bc8995f33a111bea0395ec30aa3206bdb5ccce" + integrity sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ== + dependencies: + faye-websocket "^0.11.3" + uuid "^8.3.2" + websocket-driver "^0.7.4" + +source-list-map@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-2.0.1.tgz#3993bd873bfc48479cca9ea3a547835c7c154b34" + integrity sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw== + +source-map-loader@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/source-map-loader/-/source-map-loader-2.0.0.tgz#6651dc5a46beb2b914abacd00b8f9dd0e7757820" + integrity sha512-DJLK+gR9hlx+58yGU54EDAQZzR/TksgrtvRtyEBWnd5DR7O4n0RgdyO/KBwJ76zF+wDiFRT/1vdV3SdLUR68Lg== + dependencies: + abab "^2.0.5" + iconv-lite "^0.6.2" + source-map "^0.6.1" + +source-map-resolve@^0.5.0: + version "0.5.3" + resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.3.tgz#190866bece7553e1f8f267a2ee82c606b5509a1a" + integrity sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw== + dependencies: + atob "^2.1.2" + decode-uri-component "^0.2.0" + resolve-url "^0.2.1" + source-map-url "^0.4.0" + urix "^0.1.0" + +source-map-support@~0.5.20: + version "0.5.21" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" + integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w== + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + +source-map-url@^0.4.0: + version "0.4.1" + resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.1.tgz#0af66605a745a5a2f91cf1bbf8a7afbc283dec56" + integrity sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw== + +source-map@^0.5.6: + version "0.5.7" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" + integrity sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ== + +source-map@^0.6.0, source-map@^0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== + +spdy-transport@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/spdy-transport/-/spdy-transport-3.0.0.tgz#00d4863a6400ad75df93361a1608605e5dcdcf31" + integrity sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw== + dependencies: + debug "^4.1.0" + detect-node "^2.0.4" + hpack.js "^2.1.6" + obuf "^1.1.2" + readable-stream "^3.0.6" + wbuf "^1.7.3" + +spdy@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/spdy/-/spdy-4.0.2.tgz#b74f466203a3eda452c02492b91fb9e84a27677b" + integrity sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA== + dependencies: + debug "^4.1.0" + handle-thing "^2.0.0" + http-deceiver "^1.2.7" + select-hose "^2.0.0" + spdy-transport "^3.0.0" + +split-string@^3.0.1, split-string@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/split-string/-/split-string-3.1.0.tgz#7cb09dda3a86585705c64b39a6466038682e8fe2" + integrity sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw== + dependencies: + extend-shallow "^3.0.0" + +static-extend@^0.1.1: + version "0.1.2" + resolved "https://registry.yarnpkg.com/static-extend/-/static-extend-0.1.2.tgz#60809c39cbff55337226fd5e0b520f341f1fb5c6" + integrity sha512-72E9+uLc27Mt718pMHt9VMNiAL4LMsmDbBva8mxWUCkT07fSzEGMYUCk0XWY6lp0j6RBAG4cJ3mWuZv2OE3s0g== + dependencies: + define-property "^0.2.5" + object-copy "^0.1.0" + +statuses@2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63" + integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ== + +"statuses@>= 1.4.0 < 2": + version "1.5.0" + resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" + integrity sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA== + +string-width@^3.0.0, string-width@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961" + integrity sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w== + dependencies: + emoji-regex "^7.0.1" + is-fullwidth-code-point "^2.0.0" + strip-ansi "^5.1.0" + +string_decoder@^1.1.1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" + integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== + dependencies: + safe-buffer "~5.2.0" + +string_decoder@~1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" + integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== + dependencies: + safe-buffer "~5.1.0" + +strip-ansi@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" + integrity sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg== + dependencies: + ansi-regex "^2.0.0" + +strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae" + integrity sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA== + dependencies: + ansi-regex "^4.1.0" + +strip-ansi@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + +strip-eof@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" + integrity sha512-7FCwGGmx8mD5xQd3RPUvnSpUXHM3BWuzjtpD4TXsfcZ9EL4azvVVUscFYwD9nx8Kh+uCBC00XBtAykoMHwTh8Q== + +strip-final-newline@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad" + integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA== + +supports-color@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-6.1.0.tgz#0764abc69c63d5ac842dd4867e8d025e880df8f3" + integrity sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ== + dependencies: + has-flag "^3.0.0" + +supports-color@^8.0.0: + version "8.1.1" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" + integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== + dependencies: + has-flag "^4.0.0" + +supports-preserve-symlinks-flag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" + integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== + +tapable@^2.1.1, tapable@^2.2.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.1.tgz#1967a73ef4060a82f12ab96af86d52fdb76eeca0" + integrity sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ== + +terser-webpack-plugin@^5.1.1: + version "5.3.10" + resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-5.3.10.tgz#904f4c9193c6fd2a03f693a2150c62a92f40d199" + integrity sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w== + dependencies: + "@jridgewell/trace-mapping" "^0.3.20" + jest-worker "^27.4.5" + schema-utils "^3.1.1" + serialize-javascript "^6.0.1" + terser "^5.26.0" + +terser@^5.26.0: + version "5.31.3" + resolved "https://registry.yarnpkg.com/terser/-/terser-5.31.3.tgz#b24b7beb46062f4653f049eea4f0cd165d0f0c38" + integrity sha512-pAfYn3NIZLyZpa83ZKigvj6Rn9c/vd5KfYGX7cN1mnzqgDcxWvrU5ZtAfIKhEXz9nRecw4z3LXkjaq96/qZqAA== + dependencies: + "@jridgewell/source-map" "^0.3.3" + acorn "^8.8.2" + commander "^2.20.0" + source-map-support "~0.5.20" + +thunky@^1.0.2: + version "1.1.0" + resolved "https://registry.yarnpkg.com/thunky/-/thunky-1.1.0.tgz#5abaf714a9405db0504732bbccd2cedd9ef9537d" + integrity sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA== + +to-object-path@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/to-object-path/-/to-object-path-0.3.0.tgz#297588b7b0e7e0ac08e04e672f85c1f4999e17af" + integrity sha512-9mWHdnGRuh3onocaHzukyvCZhzvr6tiflAy/JRFXcJX0TjgfWA9pk9t8CMbzmBE4Jfw58pXbkngtBtqYxzNEyg== + dependencies: + kind-of "^3.0.2" + +to-regex-range@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-2.1.1.tgz#7c80c17b9dfebe599e27367e0d4dd5590141db38" + integrity sha512-ZZWNfCjUokXXDGXFpZehJIkZqq91BcULFq/Pi7M5i4JnxXdhMKAK682z8bCW3o8Hj1wuuzoKcW3DfVzaP6VuNg== + dependencies: + is-number "^3.0.0" + repeat-string "^1.6.1" + +to-regex@^3.0.1, to-regex@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/to-regex/-/to-regex-3.0.2.tgz#13cfdd9b336552f30b51f33a8ae1b42a7a7599ce" + integrity sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw== + dependencies: + define-property "^2.0.2" + extend-shallow "^3.0.2" + regex-not "^1.0.2" + safe-regex "^1.1.0" + +toidentifier@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" + integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA== + +type-is@~1.6.18: + version "1.6.18" + resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" + integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g== + dependencies: + media-typer "0.3.0" + mime-types "~2.1.24" + +undici-types@~6.11.1: + version "6.11.1" + resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.11.1.tgz#432ea6e8efd54a48569705a699e62d8f4981b197" + integrity sha512-mIDEX2ek50x0OlRgxryxsenE5XaQD4on5U2inY7RApK3SOJpofyw7uW2AyfMKkhAxXIceo2DeWGVGwyvng1GNQ== + +union-value@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.1.tgz#0b6fe7b835aecda61c6ea4d4f02c14221e109847" + integrity sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg== + dependencies: + arr-union "^3.1.0" + get-value "^2.0.6" + is-extendable "^0.1.1" + set-value "^2.0.1" + +unpipe@1.0.0, unpipe@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" + integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== + +unset-value@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-1.0.0.tgz#8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559" + integrity sha512-PcA2tsuGSF9cnySLHTLSh2qrQiJ70mn+r+Glzxv2TWZblxsxCC52BDlZoPCsz7STd9pN7EZetkWZBAvk4cgZdQ== + dependencies: + has-value "^0.3.1" + isobject "^3.0.0" + +upath@^1.1.1: + version "1.2.0" + resolved "https://registry.yarnpkg.com/upath/-/upath-1.2.0.tgz#8f66dbcd55a883acdae4408af8b035a5044c1894" + integrity sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg== + +update-browserslist-db@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.1.0.tgz#7ca61c0d8650766090728046e416a8cde682859e" + integrity sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ== + dependencies: + escalade "^3.1.2" + picocolors "^1.0.1" + +uri-js@^4.2.2: + version "4.4.1" + resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" + integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== + dependencies: + punycode "^2.1.0" + +urix@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72" + integrity sha512-Am1ousAhSLBeB9cG/7k7r2R0zj50uDRlZHPGbazid5s9rlF1F/QKYObEKSIunSjIOkJZqwRRLpvewjEkM7pSqg== + +url-parse@^1.5.10: + version "1.5.10" + resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.5.10.tgz#9d3c2f736c1d75dd3bd2be507dcc111f1e2ea9c1" + integrity sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ== + dependencies: + querystringify "^2.1.1" + requires-port "^1.0.0" + +url@^0.11.0: + version "0.11.4" + resolved "https://registry.yarnpkg.com/url/-/url-0.11.4.tgz#adca77b3562d56b72746e76b330b7f27b6721f3c" + integrity sha512-oCwdVC7mTuWiPyjLUz/COz5TLk6wgp0RCsN+wHZ2Ekneac9w8uuV0njcbbie2ME+Vs+d6duwmYuR3HgQXs1fOg== + dependencies: + punycode "^1.4.1" + qs "^6.12.3" + +use@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f" + integrity sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ== + +util-deprecate@^1.0.1, util-deprecate@~1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== + +utils-merge@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" + integrity sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA== + +uuid@^3.3.2: + version "3.4.0" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" + integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== + +uuid@^8.3.2: + version "8.3.2" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" + integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== + +v8-compile-cache@^2.2.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.4.0.tgz#cdada8bec61e15865f05d097c5f4fd30e94dc128" + integrity sha512-ocyWc3bAHBB/guyqJQVI5o4BZkPhznPYUG2ea80Gond/BgNWpap8TOmLSeeQG7bnh2KMISxskdADG59j7zruhw== + +vary@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" + integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg== + +watchpack@^2.0.0: + version "2.4.1" + resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.4.1.tgz#29308f2cac150fa8e4c92f90e0ec954a9fed7fff" + integrity sha512-8wrBCMtVhqcXP2Sup1ctSkga6uc2Bx0IIvKyT7yTFier5AXHooSI+QyQQAtTb7+E0IUCCKyTFmXqdqgum2XWGg== + dependencies: + glob-to-regexp "^0.4.1" + graceful-fs "^4.1.2" + +wbuf@^1.1.0, wbuf@^1.7.3: + version "1.7.3" + resolved "https://registry.yarnpkg.com/wbuf/-/wbuf-1.7.3.tgz#c1d8d149316d3ea852848895cb6a0bfe887b87df" + integrity sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA== + dependencies: + minimalistic-assert "^1.0.0" + +webpack-cli@4.5.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-4.5.0.tgz#b5213b84adf6e1f5de6391334c9fa53a48850466" + integrity sha512-wXg/ef6Ibstl2f50mnkcHblRPN/P9J4Nlod5Hg9HGFgSeF8rsqDGHJeVe4aR26q9l62TUJi6vmvC2Qz96YJw1Q== + dependencies: + "@discoveryjs/json-ext" "^0.5.0" + "@webpack-cli/configtest" "^1.0.1" + "@webpack-cli/info" "^1.2.2" + "@webpack-cli/serve" "^1.3.0" + colorette "^1.2.1" + commander "^7.0.0" + enquirer "^2.3.6" + execa "^5.0.0" + fastest-levenshtein "^1.0.12" + import-local "^3.0.2" + interpret "^2.2.0" + rechoir "^0.7.0" + v8-compile-cache "^2.2.0" + webpack-merge "^5.7.3" + +webpack-dev-middleware@^3.7.2: + version "3.7.3" + resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-3.7.3.tgz#0639372b143262e2b84ab95d3b91a7597061c2c5" + integrity sha512-djelc/zGiz9nZj/U7PTBi2ViorGJXEWo/3ltkPbDyxCXhhEXkW0ce99falaok4TPj+AsxLiXJR0EBOb0zh9fKQ== + dependencies: + memory-fs "^0.4.1" + mime "^2.4.4" + mkdirp "^0.5.1" + range-parser "^1.2.1" + webpack-log "^2.0.0" + +webpack-dev-server@3.11.2: + version "3.11.2" + resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-3.11.2.tgz#695ebced76a4929f0d5de7fd73fafe185fe33708" + integrity sha512-A80BkuHRQfCiNtGBS1EMf2ChTUs0x+B3wGDFmOeT4rmJOHhHTCH2naNxIHhmkr0/UillP4U3yeIyv1pNp+QDLQ== + dependencies: + ansi-html "0.0.7" + bonjour "^3.5.0" + chokidar "^2.1.8" + compression "^1.7.4" + connect-history-api-fallback "^1.6.0" + debug "^4.1.1" + del "^4.1.1" + express "^4.17.1" + html-entities "^1.3.1" + http-proxy-middleware "0.19.1" + import-local "^2.0.0" + internal-ip "^4.3.0" + ip "^1.1.5" + is-absolute-url "^3.0.3" + killable "^1.0.1" + loglevel "^1.6.8" + opn "^5.5.0" + p-retry "^3.0.1" + portfinder "^1.0.26" + schema-utils "^1.0.0" + selfsigned "^1.10.8" + semver "^6.3.0" + serve-index "^1.9.1" + sockjs "^0.3.21" + sockjs-client "^1.5.0" + spdy "^4.0.2" + strip-ansi "^3.0.1" + supports-color "^6.1.0" + url "^0.11.0" + webpack-dev-middleware "^3.7.2" + webpack-log "^2.0.0" + ws "^6.2.1" + yargs "^13.3.2" + +webpack-log@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/webpack-log/-/webpack-log-2.0.0.tgz#5b7928e0637593f119d32f6227c1e0ac31e1b47f" + integrity sha512-cX8G2vR/85UYG59FgkoMamwHUIkSSlV3bBMRsbxVXVUk2j6NleCKjQ/WE9eYg9WY4w25O9w8wKP4rzNZFmUcUg== + dependencies: + ansi-colors "^3.0.0" + uuid "^3.3.2" + +webpack-merge@^5.7.3: + version "5.10.0" + resolved "https://registry.yarnpkg.com/webpack-merge/-/webpack-merge-5.10.0.tgz#a3ad5d773241e9c682803abf628d4cd62b8a4177" + integrity sha512-+4zXKdx7UnO+1jaN4l2lHVD+mFvnlZQP/6ljaJVb4SZiwIKeUnrT5l0gkT8z+n4hKpC+jpOv6O9R+gLtag7pSA== + dependencies: + clone-deep "^4.0.1" + flat "^5.0.2" + wildcard "^2.0.0" + +webpack-sources@^2.1.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-2.3.1.tgz#570de0af163949fe272233c2cefe1b56f74511fd" + integrity sha512-y9EI9AO42JjEcrTJFOYmVywVZdKVUfOvDUPsJea5GIr1JOEGFVqwlY2K098fFoIjOkDzHn2AjRvM8dsBZu+gCA== + dependencies: + source-list-map "^2.0.1" + source-map "^0.6.1" + +webpack@5.24.3: + version "5.24.3" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.24.3.tgz#6ec0f5059f8d7c7961075fa553cfce7b7928acb3" + integrity sha512-x7lrWZ7wlWAdyKdML6YPvfVZkhD1ICuIZGODE5SzKJjqI9A4SpqGTjGJTc6CwaHqn19gGaoOR3ONJ46nYsn9rw== + dependencies: + "@types/eslint-scope" "^3.7.0" + "@types/estree" "^0.0.46" + "@webassemblyjs/ast" "1.11.0" + "@webassemblyjs/wasm-edit" "1.11.0" + "@webassemblyjs/wasm-parser" "1.11.0" + acorn "^8.0.4" + browserslist "^4.14.5" + chrome-trace-event "^1.0.2" + enhanced-resolve "^5.7.0" + es-module-lexer "^0.4.0" + eslint-scope "^5.1.1" + events "^3.2.0" + glob-to-regexp "^0.4.1" + graceful-fs "^4.2.4" + json-parse-better-errors "^1.0.2" + loader-runner "^4.2.0" + mime-types "^2.1.27" + neo-async "^2.6.2" + schema-utils "^3.0.0" + tapable "^2.1.1" + terser-webpack-plugin "^5.1.1" + watchpack "^2.0.0" + webpack-sources "^2.1.1" + +websocket-driver@>=0.5.1, websocket-driver@^0.7.4: + version "0.7.4" + resolved "https://registry.yarnpkg.com/websocket-driver/-/websocket-driver-0.7.4.tgz#89ad5295bbf64b480abcba31e4953aca706f5760" + integrity sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg== + dependencies: + http-parser-js ">=0.5.1" + safe-buffer ">=5.1.0" + websocket-extensions ">=0.1.1" + +websocket-extensions@>=0.1.1: + version "0.1.4" + resolved "https://registry.yarnpkg.com/websocket-extensions/-/websocket-extensions-0.1.4.tgz#7f8473bc839dfd87608adb95d7eb075211578a42" + integrity sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg== + +which-module@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.1.tgz#776b1fe35d90aebe99e8ac15eb24093389a4a409" + integrity sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ== + +which@^1.2.9: + version "1.3.1" + resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" + integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== + dependencies: + isexe "^2.0.0" + +which@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" + integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== + dependencies: + isexe "^2.0.0" + +wildcard@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/wildcard/-/wildcard-2.0.1.tgz#5ab10d02487198954836b6349f74fff961e10f67" + integrity sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ== + +wrap-ansi@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-5.1.0.tgz#1fd1f67235d5b6d0fee781056001bfb694c03b09" + integrity sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q== + dependencies: + ansi-styles "^3.2.0" + string-width "^3.0.0" + strip-ansi "^5.0.0" + +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== + +ws@^6.2.1: + version "6.2.3" + resolved "https://registry.yarnpkg.com/ws/-/ws-6.2.3.tgz#ccc96e4add5fd6fedbc491903075c85c5a11d9ee" + integrity sha512-jmTjYU0j60B+vHey6TfR3Z7RD61z/hmxBS3VMSGIrroOWXQEneK1zNuotOUrGyBHQj0yrpsLHPWtigEFd13ndA== + dependencies: + async-limiter "~1.0.0" + +y18n@^4.0.0: + version "4.0.3" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.3.tgz#b5f259c82cd6e336921efd7bfd8bf560de9eeedf" + integrity sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ== + +yargs-parser@^13.1.2: + version "13.1.2" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.1.2.tgz#130f09702ebaeef2650d54ce6e3e5706f7a4fb38" + integrity sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg== + dependencies: + camelcase "^5.0.0" + decamelize "^1.2.0" + +yargs@^13.3.2: + version "13.3.2" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.3.2.tgz#ad7ffefec1aa59565ac915f82dccb38a9c31a2dd" + integrity sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw== + dependencies: + cliui "^5.0.0" + find-up "^3.0.0" + get-caller-file "^2.0.1" + require-directory "^2.1.1" + require-main-filename "^2.0.0" + set-blocking "^2.0.0" + string-width "^3.0.0" + which-module "^2.0.0" + y18n "^4.0.0" + yargs-parser "^13.1.2" From ba878b8820e157af17921a4e600499bc8f478f1c Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Wed, 31 Jul 2024 22:51:26 +0300 Subject: [PATCH 197/314] fixing GraphIRReflection for checkPow, test for isoHeader for known vector --- .gitignore | 1 + .../src/main/scala/sigma/ast/methods.scala | 2 +- .../sigma/compiler/ir/GraphIRReflection.scala | 3 ++ .../org/ergoplatform/sdk/js/Header.scala | 2 +- .../org/ergoplatform/sdk/js/IsosSpec.scala | 45 ++++++++++++++++++- 5 files changed, 50 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index df18ce8ab1..5fe37e6b74 100644 --- a/.gitignore +++ b/.gitignore @@ -9,6 +9,7 @@ *.gz *.log +yarn.lock docs/spec/out/ test-out/ flamegraphs/ diff --git a/data/shared/src/main/scala/sigma/ast/methods.scala b/data/shared/src/main/scala/sigma/ast/methods.scala index 487665aa2c..c299d9f53a 100644 --- a/data/shared/src/main/scala/sigma/ast/methods.scala +++ b/data/shared/src/main/scala/sigma/ast/methods.scala @@ -1460,7 +1460,7 @@ case object SHeaderMethods extends MonoTypeMethods { lazy val checkPowMethod = SMethod( this, "checkPow", SFunc(Array(SHeader), SBoolean), 16, FixedCost(JitCost(700))) .withIRInfo(MethodCallIrBuilder) - .withInfo("Validate header's proof-of-work") + .withInfo(MethodCall, "Validate header's proof-of-work") def checkPow_eval(mc: MethodCall, G: SigmaDslBuilder, header: Header) (implicit E: ErgoTreeEvaluator): Boolean = { diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/GraphIRReflection.scala b/sc/shared/src/main/scala/sigma/compiler/ir/GraphIRReflection.scala index 69736a0224..d4512e1297 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/GraphIRReflection.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/GraphIRReflection.scala @@ -407,6 +407,9 @@ object GraphIRReflection { }, mkMethod(clazz, "powDistance", Array[Class[_]]()) { (obj, args) => obj.asInstanceOf[ctx.Header].powDistance + }, + mkMethod(clazz, "checkPow", Array[Class[_]]()) { (obj, args) => + obj.asInstanceOf[ctx.Header].checkPow } ) ) diff --git a/sdk/js/src/main/scala/org/ergoplatform/sdk/js/Header.scala b/sdk/js/src/main/scala/org/ergoplatform/sdk/js/Header.scala index ec3767c1cd..2220c9827a 100644 --- a/sdk/js/src/main/scala/org/ergoplatform/sdk/js/Header.scala +++ b/sdk/js/src/main/scala/org/ergoplatform/sdk/js/Header.scala @@ -12,7 +12,7 @@ import scala.scalajs.js.annotation.JSExportTopLevel class Header( /** Hex representation of ModifierId of this Header */ val id: String, - /** Block version, to be increased on every soft and hardfork. */ + /** Block version, to be increased on every soft- or hard-fork. */ val version: Byte, /** Hex representation of ModifierId of the parent block */ val parentId: String, diff --git a/sdk/js/src/test/scala/org/ergoplatform/sdk/js/IsosSpec.scala b/sdk/js/src/test/scala/org/ergoplatform/sdk/js/IsosSpec.scala index a040731b20..da44cf14ef 100644 --- a/sdk/js/src/test/scala/org/ergoplatform/sdk/js/IsosSpec.scala +++ b/sdk/js/src/test/scala/org/ergoplatform/sdk/js/IsosSpec.scala @@ -1,8 +1,9 @@ package org.ergoplatform.sdk.js +import io.circe.parser.parse import org.ergoplatform.ErgoBox.{AdditionalRegisters, BoxId, TokenId} import org.ergoplatform._ -import org.ergoplatform.sdk.ExtendedInputBox +import org.ergoplatform.sdk.{ExtendedInputBox, JsonCodecs} import org.ergoplatform.sdk.wallet.protocol.context.BlockchainStateContext import org.scalacheck.Arbitrary import sigma.ast.{Constant, SType} @@ -11,6 +12,7 @@ import sigma.interpreter.{ContextExtension, ProverResult} import sigma.js.AvlTree import sigma.{Coll, GroupElement} import sigma.data.js.{Isos => DataIsos} + import scala.scalajs.js class IsosSpec extends IsosSpecBase with sdk.generators.ObjectGenerators { @@ -59,6 +61,47 @@ class IsosSpec extends IsosSpecBase with sdk.generators.ObjectGenerators { } } + property("Iso.isoHeader - test vector") { + // valid header from Ergo blockchain + val headerJson = + """ + |{ + | "extensionId" : "00cce45975d87414e8bdd8146bc88815be59cd9fe37a125b5021101e05675a18", + | "votes" : "000000", + | "timestamp" : 4928911477310178288, + | "size" : 223, + | "unparsedBytes" : "", + | "stateRoot" : { + | "digest" : "5c8c00b8403d3701557181c8df800001b6d5009e2201c6ff807d71808c00019780", + | "treeFlags" : "0", + | "keyLength" : "32" + | }, + | "height" : 614400, + | "nBits" : 37748736, + | "version" : 2, + | "id" : "5603a937ec1988220fc44fb5022fb82d5565b961f005ebb55d85bd5a9e6f801f", + | "adProofsRoot" : "5d3f80dcff7f5e7f59007294c180808d0158d1ff6ba10000f901c7f0ef87dcff", + | "transactionsRoot" : "f17fffacb6ff7f7f1180d2ff7f1e24ffffe1ff937f807f0797b9ff6ebdae007e", + | "extensionRoot" : "1480887f80007f4b01cf7f013ff1ffff564a0000b9a54f00770e807f41ff88c0", + | "minerPk" : "03bedaee069ff4829500b3c07c4d5fe6b3ea3d3bf76c5c28c1d4dcdb1bed0ade0c", + | "powOnetimePk" : "0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798", + | "powNonce" : "0000000000003105", + | "powDistance" : 0, + | "adProofsId" : "dec129290a763f4de41f04e87e2b661dd59758af6bdd00dd51f5d97c3a8cb9b5", + | "transactionsId" : "eba1dd82cf51147232e09c1f72b37c554c30f63274d5093bff36849a83472a42", + | "parentId" : "ac2101807f0000ca01ff0119db227f202201007f62000177a080005d440896d0" + |} + |""".stripMargin + + object JsonCodecs extends JsonCodecs + val c = JsonCodecs.headerDecoder.decodeJson(parse(headerJson).toOption.get).toOption.get + + roundtrip(Isos.isoHeader)(c) + + val jh = Isos.isoHeader.from(c) + Isos.isoHeader.to(jh).serializeWithoutPoW shouldBe c.serializeWithoutPoW + } + property("Iso.isoPreHeader") { forAll { (c: sigma.PreHeader) => roundtrip(Isos.isoPreHeader)(c) From b41d16c5df0dcd9e7981985a783eb8a95b2d35f2 Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Wed, 31 Jul 2024 23:35:36 +0300 Subject: [PATCH 198/314] test vectors for Blake2b256 and Long -> BigInt --- .../org/ergoplatform/HeaderWithoutPow.scala | 6 ++++++ .../TestingInterpreterSpecification.scala | 19 ++++++++++++++++++- .../org/ergoplatform/sdk/js/IsosSpec.scala | 6 ++++++ 3 files changed, 30 insertions(+), 1 deletion(-) diff --git a/data/shared/src/main/scala/org/ergoplatform/HeaderWithoutPow.scala b/data/shared/src/main/scala/org/ergoplatform/HeaderWithoutPow.scala index 4eba9b708e..21a10a5036 100644 --- a/data/shared/src/main/scala/org/ergoplatform/HeaderWithoutPow.scala +++ b/data/shared/src/main/scala/org/ergoplatform/HeaderWithoutPow.scala @@ -23,6 +23,12 @@ class HeaderWithoutPow(val version: Byte, // 1 byte def toHeader(powSolution: AutolykosSolution, bytes: Array[Byte]): ErgoHeader = ErgoHeader(version, parentId, ADProofsRoot, stateRoot, transactionsRoot, timestamp, nBits, height, extensionRoot, powSolution, votes, unparsedBytes, bytes) + + override def toString: String = { + s"HeaderWithoutPow($version, $parentId, ${bytesToId(ADProofsRoot)}, ${bytesToId(stateRoot)}, " + + s"${bytesToId(transactionsRoot)}, $timestamp, $nBits, $height, ${bytesToId(extensionRoot)}, ${bytesToId(votes)}, " + + s"${bytesToId(unparsedBytes)} )" + } } object HeaderWithoutPow { diff --git a/sc/shared/src/test/scala/sigmastate/TestingInterpreterSpecification.scala b/sc/shared/src/test/scala/sigmastate/TestingInterpreterSpecification.scala index 13af8bd6b3..9e004aef30 100644 --- a/sc/shared/src/test/scala/sigmastate/TestingInterpreterSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/TestingInterpreterSpecification.scala @@ -14,7 +14,6 @@ import scorex.util.encode.Base58 import sigma.Colls import sigma.VersionContext.V6SoftForkVersion import sigma.VersionContext -import sigma.crypto.CryptoConstants import sigma.data.{CAND, CAvlTree, ProveDlog, SigmaBoolean, TrivialProp} import sigma.interpreter.ContextExtension import sigma.util.Extensions.IntOps @@ -436,6 +435,24 @@ class TestingInterpreterSpecification extends CompilerTestingCommons verifier.verify(prop3, env, proof, challenge).map(_._1).getOrElse(false) shouldBe false } + property("blake2b - test vector") { + testEval( + """ { + | val input = fromBase16("68656c6c6f20776f726c64") + | val output = fromBase16("256c83b297114d201b30179f3f0ef0cace9783622da5974326b436178aeef610") + | blake2b256(input) == output + | }""".stripMargin) + } + + property("blake2b - test vector #2") { + testEval( + """ { + | val input = fromBase16("02ac2101807f0000ca01ff0119db227f202201007f62000177a080005d440896d05d3f80dcff7f5e7f59007294c180808d0158d1ff6ba10000f901c7f0ef87dcfff17fffacb6ff7f7f1180d2ff7f1e24ffffe1ff937f807f0797b9ff6ebdae007e5c8c00b8403d3701557181c8df800001b6d5009e2201c6ff807d71808c00019780d085adb3fcdbc0b3441480887f80007f4b01cf7f013ff1ffff564a0000b9a54f00770e807f41ff88c00240000080c02500000000") + | val output = fromBase16("bdb84cda5b105c3eb522857b50a0882f88ed5bb3cc8cf3325a1edf7eeb6a0954") + | blake2b256(input) == output + | }""".stripMargin) + } + property("passing a lambda argument") { // single expression testEval( diff --git a/sdk/js/src/test/scala/org/ergoplatform/sdk/js/IsosSpec.scala b/sdk/js/src/test/scala/org/ergoplatform/sdk/js/IsosSpec.scala index da44cf14ef..f6a78b410e 100644 --- a/sdk/js/src/test/scala/org/ergoplatform/sdk/js/IsosSpec.scala +++ b/sdk/js/src/test/scala/org/ergoplatform/sdk/js/IsosSpec.scala @@ -156,6 +156,12 @@ class IsosSpec extends IsosSpecBase with sdk.generators.ObjectGenerators { } } + property("Iso.isoBigIntToLong - test vector") { + val l = 4928911477310178288L + val js = sigma.js.Isos.isoBigIntToLong.from(l) + l.toString shouldBe js.toString() + } + property("Iso.isoAmount") { forAll { (c: Long) => roundtrip(DataIsos.isoAmount)(c) From c2788b44b0cc6fddced779345c6c2085b4fa0001 Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Thu, 1 Aug 2024 13:58:29 +0300 Subject: [PATCH 199/314] fixing checkPow test in JS --- .../src/main/scala/sigma/data/CHeader.scala | 5 +- .../TestingInterpreterSpecification.scala | 43 ++--------------- .../org/ergoplatform/sdk/js/IsosSpec.scala | 47 ------------------- 3 files changed, 6 insertions(+), 89 deletions(-) diff --git a/data/shared/src/main/scala/sigma/data/CHeader.scala b/data/shared/src/main/scala/sigma/data/CHeader.scala index 8add26c277..aa5a5756d2 100644 --- a/data/shared/src/main/scala/sigma/data/CHeader.scala +++ b/data/shared/src/main/scala/sigma/data/CHeader.scala @@ -67,10 +67,7 @@ class CHeader(val ergoHeader: ErgoHeader) extends Header with WrapperOf[ErgoHead override def wrappedValue: ErgoHeader = ergoHeader override def serializeWithoutPoW: Coll[Byte] = { - val headerWithoutPow = HeaderWithoutPow(version, bytesToId(parentId.toArray), Digest32 @@ ADProofsRoot.toArray, - ADDigest @@ stateRoot.digest.toArray, Digest32 @@ transactionsRoot.toArray, timestamp, - nBits, height, Digest32 @@ extensionRoot.toArray, votes.toArray, unparsedBytes.toArray) - Colls.fromArray(HeaderWithoutPowSerializer.toBytes(headerWithoutPow)) + Colls.fromArray(HeaderWithoutPowSerializer.toBytes(ergoHeader)) } override def checkPow: Boolean = { diff --git a/sc/shared/src/test/scala/sigmastate/TestingInterpreterSpecification.scala b/sc/shared/src/test/scala/sigmastate/TestingInterpreterSpecification.scala index 9e004aef30..4ba6b1a9f7 100644 --- a/sc/shared/src/test/scala/sigmastate/TestingInterpreterSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/TestingInterpreterSpecification.scala @@ -6,15 +6,13 @@ import sigma.ast._ import sigma.ast.syntax._ import sigmastate.interpreter._ import Interpreter._ -import io.circe.parser.parse import org.ergoplatform._ -import org.ergoplatform.sdk.JsonCodecs import org.scalatest.BeforeAndAfterAll -import scorex.util.encode.Base58 +import scorex.util.encode.{Base16, Base58} import sigma.Colls import sigma.VersionContext.V6SoftForkVersion import sigma.VersionContext -import sigma.data.{CAND, CAvlTree, ProveDlog, SigmaBoolean, TrivialProp} +import sigma.data.{CAND, CAvlTree, CHeader, ProveDlog, SigmaBoolean, TrivialProp} import sigma.interpreter.ContextExtension import sigma.util.Extensions.IntOps import sigmastate.helpers.{CompilerTestingCommons, ErgoLikeContextTesting, ErgoLikeTestInterpreter, ErgoLikeTestProvingInterpreter} @@ -38,40 +36,9 @@ class TestingInterpreterSpecification extends CompilerTestingCommons lazy val verifier = new ErgoLikeTestInterpreter def testingContext(h: Int = 614401) = { - - // valid header from Ergo blockchain - val headerJson = - """ - |{ - | "extensionId" : "00cce45975d87414e8bdd8146bc88815be59cd9fe37a125b5021101e05675a18", - | "votes" : "000000", - | "timestamp" : 4928911477310178288, - | "size" : 223, - | "unparsedBytes" : "", - | "stateRoot" : { - | "digest" : "5c8c00b8403d3701557181c8df800001b6d5009e2201c6ff807d71808c00019780", - | "treeFlags" : "0", - | "keyLength" : "32" - | }, - | "height" : 614400, - | "nBits" : 37748736, - | "version" : 2, - | "id" : "5603a937ec1988220fc44fb5022fb82d5565b961f005ebb55d85bd5a9e6f801f", - | "adProofsRoot" : "5d3f80dcff7f5e7f59007294c180808d0158d1ff6ba10000f901c7f0ef87dcff", - | "transactionsRoot" : "f17fffacb6ff7f7f1180d2ff7f1e24ffffe1ff937f807f0797b9ff6ebdae007e", - | "extensionRoot" : "1480887f80007f4b01cf7f013ff1ffff564a0000b9a54f00770e807f41ff88c0", - | "minerPk" : "03bedaee069ff4829500b3c07c4d5fe6b3ea3d3bf76c5c28c1d4dcdb1bed0ade0c", - | "powOnetimePk" : "0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798", - | "powNonce" : "0000000000003105", - | "powDistance" : 0, - | "adProofsId" : "dec129290a763f4de41f04e87e2b661dd59758af6bdd00dd51f5d97c3a8cb9b5", - | "transactionsId" : "eba1dd82cf51147232e09c1f72b37c554c30f63274d5093bff36849a83472a42", - | "parentId" : "ac2101807f0000ca01ff0119db227f202201007f62000177a080005d440896d0" - |} - |""".stripMargin - - object JsonCodecs extends JsonCodecs - val header1 = JsonCodecs.headerDecoder.decodeJson(parse(headerJson).toOption.get).toOption.get + // bytes of real mainnet block header at height 614,440 + val headerBytes = "02ac2101807f0000ca01ff0119db227f202201007f62000177a080005d440896d05d3f80dcff7f5e7f59007294c180808d0158d1ff6ba10000f901c7f0ef87dcfff17fffacb6ff7f7f1180d2ff7f1e24ffffe1ff937f807f0797b9ff6ebdae007e5c8c00b8403d3701557181c8df800001b6d5009e2201c6ff807d71808c00019780f087adb3fcdbc0b3441480887f80007f4b01cf7f013ff1ffff564a0000b9a54f00770e807f41ff88c00240000080c0250000000003bedaee069ff4829500b3c07c4d5fe6b3ea3d3bf76c5c28c1d4dcdb1bed0ade0c0000000000003105" + val header1 = new CHeader(ErgoHeader.sigmaSerializer.fromBytes(Base16.decode(headerBytes).get)) val boxesToSpend = IndexedSeq(fakeSelf) diff --git a/sdk/js/src/test/scala/org/ergoplatform/sdk/js/IsosSpec.scala b/sdk/js/src/test/scala/org/ergoplatform/sdk/js/IsosSpec.scala index f6a78b410e..31b8a84c2b 100644 --- a/sdk/js/src/test/scala/org/ergoplatform/sdk/js/IsosSpec.scala +++ b/sdk/js/src/test/scala/org/ergoplatform/sdk/js/IsosSpec.scala @@ -61,47 +61,6 @@ class IsosSpec extends IsosSpecBase with sdk.generators.ObjectGenerators { } } - property("Iso.isoHeader - test vector") { - // valid header from Ergo blockchain - val headerJson = - """ - |{ - | "extensionId" : "00cce45975d87414e8bdd8146bc88815be59cd9fe37a125b5021101e05675a18", - | "votes" : "000000", - | "timestamp" : 4928911477310178288, - | "size" : 223, - | "unparsedBytes" : "", - | "stateRoot" : { - | "digest" : "5c8c00b8403d3701557181c8df800001b6d5009e2201c6ff807d71808c00019780", - | "treeFlags" : "0", - | "keyLength" : "32" - | }, - | "height" : 614400, - | "nBits" : 37748736, - | "version" : 2, - | "id" : "5603a937ec1988220fc44fb5022fb82d5565b961f005ebb55d85bd5a9e6f801f", - | "adProofsRoot" : "5d3f80dcff7f5e7f59007294c180808d0158d1ff6ba10000f901c7f0ef87dcff", - | "transactionsRoot" : "f17fffacb6ff7f7f1180d2ff7f1e24ffffe1ff937f807f0797b9ff6ebdae007e", - | "extensionRoot" : "1480887f80007f4b01cf7f013ff1ffff564a0000b9a54f00770e807f41ff88c0", - | "minerPk" : "03bedaee069ff4829500b3c07c4d5fe6b3ea3d3bf76c5c28c1d4dcdb1bed0ade0c", - | "powOnetimePk" : "0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798", - | "powNonce" : "0000000000003105", - | "powDistance" : 0, - | "adProofsId" : "dec129290a763f4de41f04e87e2b661dd59758af6bdd00dd51f5d97c3a8cb9b5", - | "transactionsId" : "eba1dd82cf51147232e09c1f72b37c554c30f63274d5093bff36849a83472a42", - | "parentId" : "ac2101807f0000ca01ff0119db227f202201007f62000177a080005d440896d0" - |} - |""".stripMargin - - object JsonCodecs extends JsonCodecs - val c = JsonCodecs.headerDecoder.decodeJson(parse(headerJson).toOption.get).toOption.get - - roundtrip(Isos.isoHeader)(c) - - val jh = Isos.isoHeader.from(c) - Isos.isoHeader.to(jh).serializeWithoutPoW shouldBe c.serializeWithoutPoW - } - property("Iso.isoPreHeader") { forAll { (c: sigma.PreHeader) => roundtrip(Isos.isoPreHeader)(c) @@ -156,12 +115,6 @@ class IsosSpec extends IsosSpecBase with sdk.generators.ObjectGenerators { } } - property("Iso.isoBigIntToLong - test vector") { - val l = 4928911477310178288L - val js = sigma.js.Isos.isoBigIntToLong.from(l) - l.toString shouldBe js.toString() - } - property("Iso.isoAmount") { forAll { (c: Long) => roundtrip(DataIsos.isoAmount)(c) From 26809c94f0ed8aca3d56fabb10995fb30e2889e0 Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Fri, 2 Aug 2024 13:58:07 +0300 Subject: [PATCH 200/314] passing but improper changedFeature test --- .gitignore | 1 + .../scala/sigma/LanguageSpecificationV6.scala | 48 +++++++++---------- 2 files changed, 25 insertions(+), 24 deletions(-) diff --git a/.gitignore b/.gitignore index df18ce8ab1..d328645cde 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,7 @@ *.fdb_latexmk *.gz +yarn.lock *.log docs/spec/out/ test-out/ diff --git a/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala b/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala index b4fb5b12fb..9e9827df1f 100644 --- a/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala +++ b/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala @@ -1,14 +1,14 @@ package sigma -import sigma.ast.{Apply, ArithOp, BlockValue, ByIndex, CompanionDesc, Constant, Downcast, FixedCost, FixedCostItem, FuncValue, GetVar, IntConstant, JitCost, LongConstant, MethodCall, OptionGet, OptionGetOrElse, PerItemCost, SBigInt, SByte, SCollection, SCollectionMethods, SCollectionType, SInt, SLong, SOption, SPair, SShort, STuple, STypeVar, SelectField, ValDef, ValUse, Value} +import sigma.ast.{Apply, ByIndex, Downcast, FixedCost, FixedCostItem, FuncValue, GetVar, IntConstant, JitCost, LongConstant, MethodCall, OptionGet, OptionGetOrElse, PerItemCost, SBigInt, SByte, SCollection, SCollectionMethods, SCollectionType, SInt, SLong, SOption, SPair, SShort, STuple, STypeVar, SelectField, ValDef, ValUse, Value} import sigma.data.{CBigInt, ExactNumeric} -import sigma.eval.{SigmaDsl, TracedCost} +import sigma.eval.{CostDetails, SigmaDsl, TracedCost} import sigma.serialization.ValueCodes.OpCode import sigma.util.Extensions.{BooleanOps, ByteOps, IntOps, LongOps} import sigmastate.exceptions.MethodNotFound import java.math.BigInteger -import scala.util.Success +import scala.util.{Failure, Success} /** This suite tests all operations for v6.0 version of the language. * The base classes establish the infrastructure for the tests. @@ -172,29 +172,29 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite => } property("Option.getOrElse with lazy default") { - def getOrElse = newFeature( - { (x: Option[Long]) => x.getOrElse(1 / 0L) }, - "{ (x: Option[Long]) => x.getOrElse(1 / 0L) }", - FuncValue( - Array((1, SOption(SLong))), - OptionGetOrElse( - ValUse(1, SOption(SLong)), - ArithOp(LongConstant(1L), LongConstant(0L), OpCode @@ (-99.toByte)) - ) + verifyCases( + Seq( + Some(0L) -> Expected(Failure(new java.lang.ArithmeticException("/ by zero")), 6, CostDetails.ZeroCost, 1793, + newVersionedResults = { + Seq(0 -> (ExpectedResult(Success(6L), Some(1793)) -> None)) + } ), + None -> Expected(Failure(new java.lang.ArithmeticException("/ by zero")), 6) + ), + changedFeature( + { (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]) => x.getOrElse(1 / 0L) }", + FuncValue( + Array((1, SOption(SLong))), + OptionGetOrElse( + ValUse(1, SOption(SLong)), + ArithOp(LongConstant(1L), LongConstant(0L), OpCode @@ (-99.toByte)) + ) + ), + allowNewToSucceed = true, + changedIn = VersionContext.V6SoftForkVersion ) ) - - if (VersionContext.current.isV6SoftForkActivated) { - forAll { x: Option[Long] => - Seq(getOrElse).map(_.checkEquality(x)) - } - } else { - forAll { x: Option[Long] => - if (x.isEmpty) { - Seq(getOrElse).map(_.checkEquality(x)) - } - } - } } property("Coll getOrElse with lazy default") { From bfd10497e904df0c03769d8ae24fcd0c8bca528a Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Fri, 2 Aug 2024 16:25:32 +0300 Subject: [PATCH 201/314] yarn.lock added to .gitignore --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index df18ce8ab1..4dc1640004 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,8 @@ *.fdb_latexmk *.gz + +yarn.lock *.log docs/spec/out/ test-out/ From 8133fad865e46d10efe3e7caccfb0ab760a54eab Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Fri, 2 Aug 2024 16:25:57 +0300 Subject: [PATCH 202/314] yarn.lock removed --- yarn.lock | 3322 ----------------------------------------------------- 1 file changed, 3322 deletions(-) delete mode 100644 yarn.lock diff --git a/yarn.lock b/yarn.lock deleted file mode 100644 index 161dcfd54a..0000000000 --- a/yarn.lock +++ /dev/null @@ -1,3322 +0,0 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. -# yarn lockfile v1 - - -"@discoveryjs/json-ext@^0.5.0": - version "0.5.7" - resolved "https://registry.yarnpkg.com/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz#1d572bfbbe14b7704e0ba0f39b74815b84870d70" - integrity sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw== - -"@fleet-sdk/common@0.1.3": - version "0.1.3" - resolved "https://registry.yarnpkg.com/@fleet-sdk/common/-/common-0.1.3.tgz#f9e478b896e9192f03d2d5b30570af4e8632eb15" - integrity sha512-gYEkHhgGpgIcmCL3nCw8E9zHkT2WLmR+mPdxFlUE6fwcwISURbJrP6W9mF7D5Y0ShAP5Is2w3edh7AyIc7ctIQ== - -"@jridgewell/gen-mapping@^0.3.5": - version "0.3.5" - resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz#dcce6aff74bdf6dad1a95802b69b04a2fcb1fb36" - integrity sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg== - dependencies: - "@jridgewell/set-array" "^1.2.1" - "@jridgewell/sourcemap-codec" "^1.4.10" - "@jridgewell/trace-mapping" "^0.3.24" - -"@jridgewell/resolve-uri@^3.1.0": - version "3.1.2" - resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz#7a0ee601f60f99a20c7c7c5ff0c80388c1189bd6" - integrity sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw== - -"@jridgewell/set-array@^1.2.1": - version "1.2.1" - resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.2.1.tgz#558fb6472ed16a4c850b889530e6b36438c49280" - integrity sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A== - -"@jridgewell/source-map@^0.3.3": - version "0.3.6" - resolved "https://registry.yarnpkg.com/@jridgewell/source-map/-/source-map-0.3.6.tgz#9d71ca886e32502eb9362c9a74a46787c36df81a" - integrity sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ== - dependencies: - "@jridgewell/gen-mapping" "^0.3.5" - "@jridgewell/trace-mapping" "^0.3.25" - -"@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.14": - version "1.5.0" - resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz#3188bcb273a414b0d215fd22a58540b989b9409a" - integrity sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ== - -"@jridgewell/trace-mapping@^0.3.20", "@jridgewell/trace-mapping@^0.3.24", "@jridgewell/trace-mapping@^0.3.25": - version "0.3.25" - resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz#15f190e98895f3fc23276ee14bc76b675c2e50f0" - integrity sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ== - dependencies: - "@jridgewell/resolve-uri" "^3.1.0" - "@jridgewell/sourcemap-codec" "^1.4.14" - -"@noble/hashes@1.1.4": - version "1.1.4" - resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.1.4.tgz#2611ebf5764c1bf754da7c7794de4fb30512336d" - integrity sha512-+PYsVPrTSqtVjatKt2A/Proukn2Yrz61OBThOCKErc5w2/r1Fh37vbDv0Eah7pyNltrmacjwTvdw3JoR+WE4TA== - -"@noble/hashes@^1.1.4": - version "1.4.0" - resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.4.0.tgz#45814aa329f30e4fe0ba49426f49dfccdd066426" - integrity sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg== - -"@types/eslint-scope@^3.7.0": - version "3.7.7" - resolved "https://registry.yarnpkg.com/@types/eslint-scope/-/eslint-scope-3.7.7.tgz#3108bd5f18b0cdb277c867b3dd449c9ed7079ac5" - integrity sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg== - dependencies: - "@types/eslint" "*" - "@types/estree" "*" - -"@types/eslint@*": - version "9.6.0" - resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-9.6.0.tgz#51d4fe4d0316da9e9f2c80884f2c20ed5fb022ff" - integrity sha512-gi6WQJ7cHRgZxtkQEoyHMppPjq9Kxo5Tjn2prSKDSmZrCz8TZ3jSRCeTJm+WoM+oB0WG37bRqLzaaU3q7JypGg== - dependencies: - "@types/estree" "*" - "@types/json-schema" "*" - -"@types/estree@*": - version "1.0.5" - resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.5.tgz#a6ce3e556e00fd9895dd872dd172ad0d4bd687f4" - integrity sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw== - -"@types/estree@^0.0.46": - version "0.0.46" - resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.46.tgz#0fb6bfbbeabd7a30880504993369c4bf1deab1fe" - integrity sha512-laIjwTQaD+5DukBZaygQ79K1Z0jb1bPEMRrkXSLjtCcZm+abyp5YbrqpSLzD42FwWW6gK/aS4NYpJ804nG2brg== - -"@types/glob@^7.1.1": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@types/glob/-/glob-7.2.0.tgz#bc1b5bf3aa92f25bd5dd39f35c57361bdce5b2eb" - integrity sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA== - dependencies: - "@types/minimatch" "*" - "@types/node" "*" - -"@types/json-schema@*", "@types/json-schema@^7.0.8": - version "7.0.15" - resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841" - integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA== - -"@types/minimatch@*": - version "5.1.2" - resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-5.1.2.tgz#07508b45797cb81ec3f273011b054cd0755eddca" - integrity sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA== - -"@types/node@*": - version "22.0.0" - resolved "https://registry.yarnpkg.com/@types/node/-/node-22.0.0.tgz#04862a2a71e62264426083abe1e27e87cac05a30" - integrity sha512-VT7KSYudcPOzP5Q0wfbowyNLaVR8QWUdw+088uFWwfvpY6uCWaXpqV6ieLAu9WBcnTa7H4Z5RLK8I5t2FuOcqw== - dependencies: - undici-types "~6.11.1" - -"@webassemblyjs/ast@1.11.0": - version "1.11.0" - resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.11.0.tgz#a5aa679efdc9e51707a4207139da57920555961f" - integrity sha512-kX2W49LWsbthrmIRMbQZuQDhGtjyqXfEmmHyEi4XWnSZtPmxY0+3anPIzsnRb45VH/J55zlOfWvZuY47aJZTJg== - dependencies: - "@webassemblyjs/helper-numbers" "1.11.0" - "@webassemblyjs/helper-wasm-bytecode" "1.11.0" - -"@webassemblyjs/floating-point-hex-parser@1.11.0": - version "1.11.0" - resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.0.tgz#34d62052f453cd43101d72eab4966a022587947c" - integrity sha512-Q/aVYs/VnPDVYvsCBL/gSgwmfjeCb4LW8+TMrO3cSzJImgv8lxxEPM2JA5jMrivE7LSz3V+PFqtMbls3m1exDA== - -"@webassemblyjs/helper-api-error@1.11.0": - version "1.11.0" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.0.tgz#aaea8fb3b923f4aaa9b512ff541b013ffb68d2d4" - integrity sha512-baT/va95eXiXb2QflSx95QGT5ClzWpGaa8L7JnJbgzoYeaA27FCvuBXU758l+KXWRndEmUXjP0Q5fibhavIn8w== - -"@webassemblyjs/helper-buffer@1.11.0": - version "1.11.0" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.0.tgz#d026c25d175e388a7dbda9694e91e743cbe9b642" - integrity sha512-u9HPBEl4DS+vA8qLQdEQ6N/eJQ7gT7aNvMIo8AAWvAl/xMrcOSiI2M0MAnMCy3jIFke7bEee/JwdX1nUpCtdyA== - -"@webassemblyjs/helper-numbers@1.11.0": - version "1.11.0" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.0.tgz#7ab04172d54e312cc6ea4286d7d9fa27c88cd4f9" - integrity sha512-DhRQKelIj01s5IgdsOJMKLppI+4zpmcMQ3XboFPLwCpSNH6Hqo1ritgHgD0nqHeSYqofA6aBN/NmXuGjM1jEfQ== - dependencies: - "@webassemblyjs/floating-point-hex-parser" "1.11.0" - "@webassemblyjs/helper-api-error" "1.11.0" - "@xtuc/long" "4.2.2" - -"@webassemblyjs/helper-wasm-bytecode@1.11.0": - version "1.11.0" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.0.tgz#85fdcda4129902fe86f81abf7e7236953ec5a4e1" - integrity sha512-MbmhvxXExm542tWREgSFnOVo07fDpsBJg3sIl6fSp9xuu75eGz5lz31q7wTLffwL3Za7XNRCMZy210+tnsUSEA== - -"@webassemblyjs/helper-wasm-section@1.11.0": - version "1.11.0" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.0.tgz#9ce2cc89300262509c801b4af113d1ca25c1a75b" - integrity sha512-3Eb88hcbfY/FCukrg6i3EH8H2UsD7x8Vy47iVJrP967A9JGqgBVL9aH71SETPx1JrGsOUVLo0c7vMCN22ytJew== - dependencies: - "@webassemblyjs/ast" "1.11.0" - "@webassemblyjs/helper-buffer" "1.11.0" - "@webassemblyjs/helper-wasm-bytecode" "1.11.0" - "@webassemblyjs/wasm-gen" "1.11.0" - -"@webassemblyjs/ieee754@1.11.0": - version "1.11.0" - resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.11.0.tgz#46975d583f9828f5d094ac210e219441c4e6f5cf" - integrity sha512-KXzOqpcYQwAfeQ6WbF6HXo+0udBNmw0iXDmEK5sFlmQdmND+tr773Ti8/5T/M6Tl/413ArSJErATd8In3B+WBA== - dependencies: - "@xtuc/ieee754" "^1.2.0" - -"@webassemblyjs/leb128@1.11.0": - version "1.11.0" - resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.11.0.tgz#f7353de1df38aa201cba9fb88b43f41f75ff403b" - integrity sha512-aqbsHa1mSQAbeeNcl38un6qVY++hh8OpCOzxhixSYgbRfNWcxJNJQwe2rezK9XEcssJbbWIkblaJRwGMS9zp+g== - dependencies: - "@xtuc/long" "4.2.2" - -"@webassemblyjs/utf8@1.11.0": - version "1.11.0" - resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.11.0.tgz#86e48f959cf49e0e5091f069a709b862f5a2cadf" - integrity sha512-A/lclGxH6SpSLSyFowMzO/+aDEPU4hvEiooCMXQPcQFPPJaYcPQNKGOCLUySJsYJ4trbpr+Fs08n4jelkVTGVw== - -"@webassemblyjs/wasm-edit@1.11.0": - version "1.11.0" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.0.tgz#ee4a5c9f677046a210542ae63897094c2027cb78" - integrity sha512-JHQ0damXy0G6J9ucyKVXO2j08JVJ2ntkdJlq1UTiUrIgfGMmA7Ik5VdC/L8hBK46kVJgujkBIoMtT8yVr+yVOQ== - dependencies: - "@webassemblyjs/ast" "1.11.0" - "@webassemblyjs/helper-buffer" "1.11.0" - "@webassemblyjs/helper-wasm-bytecode" "1.11.0" - "@webassemblyjs/helper-wasm-section" "1.11.0" - "@webassemblyjs/wasm-gen" "1.11.0" - "@webassemblyjs/wasm-opt" "1.11.0" - "@webassemblyjs/wasm-parser" "1.11.0" - "@webassemblyjs/wast-printer" "1.11.0" - -"@webassemblyjs/wasm-gen@1.11.0": - version "1.11.0" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.0.tgz#3cdb35e70082d42a35166988dda64f24ceb97abe" - integrity sha512-BEUv1aj0WptCZ9kIS30th5ILASUnAPEvE3tVMTrItnZRT9tXCLW2LEXT8ezLw59rqPP9klh9LPmpU+WmRQmCPQ== - dependencies: - "@webassemblyjs/ast" "1.11.0" - "@webassemblyjs/helper-wasm-bytecode" "1.11.0" - "@webassemblyjs/ieee754" "1.11.0" - "@webassemblyjs/leb128" "1.11.0" - "@webassemblyjs/utf8" "1.11.0" - -"@webassemblyjs/wasm-opt@1.11.0": - version "1.11.0" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.0.tgz#1638ae188137f4bb031f568a413cd24d32f92978" - integrity sha512-tHUSP5F4ywyh3hZ0+fDQuWxKx3mJiPeFufg+9gwTpYp324mPCQgnuVKwzLTZVqj0duRDovnPaZqDwoyhIO8kYg== - dependencies: - "@webassemblyjs/ast" "1.11.0" - "@webassemblyjs/helper-buffer" "1.11.0" - "@webassemblyjs/wasm-gen" "1.11.0" - "@webassemblyjs/wasm-parser" "1.11.0" - -"@webassemblyjs/wasm-parser@1.11.0": - version "1.11.0" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.0.tgz#3e680b8830d5b13d1ec86cc42f38f3d4a7700754" - integrity sha512-6L285Sgu9gphrcpDXINvm0M9BskznnzJTE7gYkjDbxET28shDqp27wpruyx3C2S/dvEwiigBwLA1cz7lNUi0kw== - dependencies: - "@webassemblyjs/ast" "1.11.0" - "@webassemblyjs/helper-api-error" "1.11.0" - "@webassemblyjs/helper-wasm-bytecode" "1.11.0" - "@webassemblyjs/ieee754" "1.11.0" - "@webassemblyjs/leb128" "1.11.0" - "@webassemblyjs/utf8" "1.11.0" - -"@webassemblyjs/wast-printer@1.11.0": - version "1.11.0" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.11.0.tgz#680d1f6a5365d6d401974a8e949e05474e1fab7e" - integrity sha512-Fg5OX46pRdTgB7rKIUojkh9vXaVN6sGYCnEiJN1GYkb0RPwShZXp6KTDqmoMdQPKhcroOXh3fEzmkWmCYaKYhQ== - dependencies: - "@webassemblyjs/ast" "1.11.0" - "@xtuc/long" "4.2.2" - -"@webpack-cli/configtest@^1.0.1": - version "1.2.0" - resolved "https://registry.yarnpkg.com/@webpack-cli/configtest/-/configtest-1.2.0.tgz#7b20ce1c12533912c3b217ea68262365fa29a6f5" - integrity sha512-4FB8Tj6xyVkyqjj1OaTqCjXYULB9FMkqQ8yGrZjRDrYh0nOE+7Lhs45WioWQQMV+ceFlE368Ukhe6xdvJM9Egg== - -"@webpack-cli/info@^1.2.2": - version "1.5.0" - resolved "https://registry.yarnpkg.com/@webpack-cli/info/-/info-1.5.0.tgz#6c78c13c5874852d6e2dd17f08a41f3fe4c261b1" - integrity sha512-e8tSXZpw2hPl2uMJY6fsMswaok5FdlGNRTktvFk2sD8RjH0hE2+XistawJx1vmKteh4NmGmNUrp+Tb2w+udPcQ== - dependencies: - envinfo "^7.7.3" - -"@webpack-cli/serve@^1.3.0": - version "1.7.0" - resolved "https://registry.yarnpkg.com/@webpack-cli/serve/-/serve-1.7.0.tgz#e1993689ac42d2b16e9194376cfb6753f6254db1" - integrity sha512-oxnCNGj88fL+xzV+dacXs44HcDwf1ovs3AuEzvP7mqXw7fQntqIhQ1BRmynh4qEKQSSSRSWVyXRjmTbZIX9V2Q== - -"@xtuc/ieee754@^1.2.0": - version "1.2.0" - resolved "https://registry.yarnpkg.com/@xtuc/ieee754/-/ieee754-1.2.0.tgz#eef014a3145ae477a1cbc00cd1e552336dceb790" - integrity sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA== - -"@xtuc/long@4.2.2": - version "4.2.2" - resolved "https://registry.yarnpkg.com/@xtuc/long/-/long-4.2.2.tgz#d291c6a4e97989b5c61d9acf396ae4fe133a718d" - integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ== - -abab@^2.0.5: - version "2.0.6" - resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.6.tgz#41b80f2c871d19686216b82309231cfd3cb3d291" - integrity sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA== - -accepts@~1.3.4, accepts@~1.3.5, accepts@~1.3.8: - version "1.3.8" - resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e" - integrity sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw== - dependencies: - mime-types "~2.1.34" - negotiator "0.6.3" - -acorn@^8.0.4, acorn@^8.8.2: - version "8.12.1" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.12.1.tgz#71616bdccbe25e27a54439e0046e89ca76df2248" - integrity sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg== - -ajv-errors@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/ajv-errors/-/ajv-errors-1.0.1.tgz#f35986aceb91afadec4102fbd85014950cefa64d" - integrity sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ== - -ajv-keywords@^3.1.0, ajv-keywords@^3.5.2: - version "3.5.2" - resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.5.2.tgz#31f29da5ab6e00d1c2d329acf7b5929614d5014d" - integrity sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ== - -ajv@^6.1.0, ajv@^6.12.5: - version "6.12.6" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" - integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== - dependencies: - fast-deep-equal "^3.1.1" - fast-json-stable-stringify "^2.0.0" - json-schema-traverse "^0.4.1" - uri-js "^4.2.2" - -ansi-colors@^3.0.0: - version "3.2.4" - resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-3.2.4.tgz#e3a3da4bfbae6c86a9c285625de124a234026fbf" - integrity sha512-hHUXGagefjN2iRrID63xckIvotOXOojhQKWIPUZ4mNUZ9nLZW+7FMNoE1lOkEhNWYsx/7ysGIuJYCiMAA9FnrA== - -ansi-colors@^4.1.1: - version "4.1.3" - resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.3.tgz#37611340eb2243e70cc604cad35d63270d48781b" - integrity sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw== - -ansi-html@0.0.7: - version "0.0.7" - resolved "https://registry.yarnpkg.com/ansi-html/-/ansi-html-0.0.7.tgz#813584021962a9e9e6fd039f940d12f56ca7859e" - integrity sha512-JoAxEa1DfP9m2xfB/y2r/aKcwXNlltr4+0QSBC4TrLfcxyvepX2Pv0t/xpgGV5bGsDzCYV8SzjWgyCW0T9yYbA== - -ansi-regex@^2.0.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" - integrity sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA== - -ansi-regex@^4.1.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.1.tgz#164daac87ab2d6f6db3a29875e2d1766582dabed" - integrity sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g== - -ansi-regex@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" - integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== - -ansi-styles@^3.2.0: - version "3.2.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" - integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== - dependencies: - color-convert "^1.9.0" - -anymatch@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-2.0.0.tgz#bcb24b4f37934d9aa7ac17b4adaf89e7c76ef2eb" - integrity sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw== - dependencies: - micromatch "^3.1.4" - normalize-path "^2.1.1" - -arr-diff@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520" - integrity sha512-YVIQ82gZPGBebQV/a8dar4AitzCQs0jjXwMPZllpXMaGjXPYVUawSxQrRsjhjupyVxEvbHgUmIhKVlND+j02kA== - -arr-flatten@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1" - integrity sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg== - -arr-union@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4" - integrity sha512-sKpyeERZ02v1FeCZT8lrfJq5u6goHCtpTAzPwJYe7c8SPFOboNjNg1vz2L4VTn9T4PQxEx13TbXLmYUcS6Ug7Q== - -array-flatten@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" - integrity sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg== - -array-flatten@^2.1.0: - version "2.1.2" - resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-2.1.2.tgz#24ef80a28c1a893617e2149b0c6d0d788293b099" - integrity sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ== - -array-union@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/array-union/-/array-union-1.0.2.tgz#9a34410e4f4e3da23dea375be5be70f24778ec39" - integrity sha512-Dxr6QJj/RdU/hCaBjOfxW+q6lyuVE6JFWIrAUpuOOhoJJoQ99cUn3igRaHVB5P9WrgFVN0FfArM3x0cueOU8ng== - dependencies: - array-uniq "^1.0.1" - -array-uniq@^1.0.1: - version "1.0.3" - resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6" - integrity sha512-MNha4BWQ6JbwhFhj03YK552f7cb3AzoE8SzeljgChvL1dl3IcvggXVz1DilzySZkCja+CXuZbdW7yATchWn8/Q== - -array-unique@^0.3.2: - version "0.3.2" - resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" - integrity sha512-SleRWjh9JUud2wH1hPs9rZBZ33H6T9HOiL0uwGnGx9FpE6wKGyfWugmbkEOIs6qWrZhg0LWeLziLrEwQJhs5mQ== - -assign-symbols@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367" - integrity sha512-Q+JC7Whu8HhmTdBph/Tq59IoRtoy6KAm5zzPv00WdujX82lbAL8K7WVjne7vdCsAmbF4AYaDOPyO3k0kl8qIrw== - -async-each@^1.0.1: - version "1.0.6" - resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.6.tgz#52f1d9403818c179b7561e11a5d1b77eb2160e77" - integrity sha512-c646jH1avxr+aVpndVMeAfYw7wAa6idufrlN3LPA4PmKS0QEGp6PIC9nwz0WQkkvBGAMEki3pFdtxaF39J9vvg== - -async-limiter@~1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.1.tgz#dd379e94f0db8310b08291f9d64c3209766617fd" - integrity sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ== - -async@^2.6.4: - version "2.6.4" - resolved "https://registry.yarnpkg.com/async/-/async-2.6.4.tgz#706b7ff6084664cd7eae713f6f965433b5504221" - integrity sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA== - dependencies: - lodash "^4.17.14" - -atob@^2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" - integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== - -balanced-match@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" - integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== - -base@^0.11.1: - version "0.11.2" - resolved "https://registry.yarnpkg.com/base/-/base-0.11.2.tgz#7bde5ced145b6d551a90db87f83c558b4eb48a8f" - integrity sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg== - dependencies: - cache-base "^1.0.1" - class-utils "^0.3.5" - component-emitter "^1.2.1" - define-property "^1.0.0" - isobject "^3.0.1" - mixin-deep "^1.2.0" - pascalcase "^0.1.1" - -batch@0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/batch/-/batch-0.6.1.tgz#dc34314f4e679318093fc760272525f94bf25c16" - integrity sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw== - -binary-extensions@^1.0.0: - version "1.13.1" - resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.13.1.tgz#598afe54755b2868a5330d2aff9d4ebb53209b65" - integrity sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw== - -bindings@^1.5.0: - version "1.5.0" - resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.5.0.tgz#10353c9e945334bc0511a6d90b38fbc7c9c504df" - integrity sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ== - dependencies: - file-uri-to-path "1.0.0" - -body-parser@1.20.2: - version "1.20.2" - resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.2.tgz#6feb0e21c4724d06de7ff38da36dad4f57a747fd" - integrity sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA== - dependencies: - bytes "3.1.2" - content-type "~1.0.5" - debug "2.6.9" - depd "2.0.0" - destroy "1.2.0" - http-errors "2.0.0" - iconv-lite "0.4.24" - on-finished "2.4.1" - qs "6.11.0" - raw-body "2.5.2" - type-is "~1.6.18" - unpipe "1.0.0" - -bonjour@^3.5.0: - version "3.5.0" - resolved "https://registry.yarnpkg.com/bonjour/-/bonjour-3.5.0.tgz#8e890a183d8ee9a2393b3844c691a42bcf7bc9f5" - integrity sha512-RaVTblr+OnEli0r/ud8InrU7D+G0y6aJhlxaLa6Pwty4+xoxboF1BsUI45tujvRpbj9dQVoglChqonGAsjEBYg== - dependencies: - array-flatten "^2.1.0" - deep-equal "^1.0.1" - dns-equal "^1.0.0" - dns-txt "^2.0.2" - multicast-dns "^6.0.1" - multicast-dns-service-types "^1.1.0" - -brace-expansion@^1.1.7: - version "1.1.11" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" - integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== - dependencies: - balanced-match "^1.0.0" - concat-map "0.0.1" - -braces@^2.3.1, braces@^2.3.2: - version "2.3.2" - resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.2.tgz#5979fd3f14cd531565e5fa2df1abfff1dfaee729" - integrity sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w== - dependencies: - arr-flatten "^1.1.0" - array-unique "^0.3.2" - extend-shallow "^2.0.1" - fill-range "^4.0.0" - isobject "^3.0.1" - repeat-element "^1.1.2" - snapdragon "^0.8.1" - snapdragon-node "^2.0.1" - split-string "^3.0.2" - to-regex "^3.0.1" - -browserslist@^4.14.5: - version "4.23.2" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.23.2.tgz#244fe803641f1c19c28c48c4b6ec9736eb3d32ed" - integrity sha512-qkqSyistMYdxAcw+CzbZwlBy8AGmS/eEWs+sEV5TnLRGDOL+C5M2EnH6tlZyg0YoAxGJAFKh61En9BR941GnHA== - dependencies: - caniuse-lite "^1.0.30001640" - electron-to-chromium "^1.4.820" - node-releases "^2.0.14" - update-browserslist-db "^1.1.0" - -buffer-from@^1.0.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" - integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== - -buffer-indexof@^1.0.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/buffer-indexof/-/buffer-indexof-1.1.1.tgz#52fabcc6a606d1a00302802648ef68f639da268c" - integrity sha512-4/rOEg86jivtPTeOUUT61jJO1Ya1TrR/OkqCSZDyq84WJh3LuuiphBYJN+fm5xufIk4XAFcEwte/8WzC8If/1g== - -bytes@3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048" - integrity sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw== - -bytes@3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5" - integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg== - -cache-base@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/cache-base/-/cache-base-1.0.1.tgz#0a7f46416831c8b662ee36fe4e7c59d76f666ab2" - integrity sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ== - dependencies: - collection-visit "^1.0.0" - component-emitter "^1.2.1" - get-value "^2.0.6" - has-value "^1.0.0" - isobject "^3.0.1" - set-value "^2.0.0" - to-object-path "^0.3.0" - union-value "^1.0.0" - unset-value "^1.0.0" - -call-bind@^1.0.2, call-bind@^1.0.6, call-bind@^1.0.7: - version "1.0.7" - resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.7.tgz#06016599c40c56498c18769d2730be242b6fa3b9" - integrity sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w== - dependencies: - es-define-property "^1.0.0" - es-errors "^1.3.0" - function-bind "^1.1.2" - get-intrinsic "^1.2.4" - set-function-length "^1.2.1" - -camelcase@^5.0.0: - version "5.3.1" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" - integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== - -caniuse-lite@^1.0.30001640: - version "1.0.30001645" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001645.tgz#4c4b7427683dea1170a152cd1654be8d0da7bd71" - integrity sha512-GFtY2+qt91kzyMk6j48dJcwJVq5uTkk71XxE3RtScx7XWRLsO7bU44LOFkOZYR8w9YMS0UhPSYpN/6rAMImmLw== - -chokidar@^2.1.8: - version "2.1.8" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.1.8.tgz#804b3a7b6a99358c3c5c61e71d8728f041cff917" - integrity sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg== - dependencies: - anymatch "^2.0.0" - async-each "^1.0.1" - braces "^2.3.2" - glob-parent "^3.1.0" - inherits "^2.0.3" - is-binary-path "^1.0.0" - is-glob "^4.0.0" - normalize-path "^3.0.0" - path-is-absolute "^1.0.0" - readdirp "^2.2.1" - upath "^1.1.1" - optionalDependencies: - fsevents "^1.2.7" - -chrome-trace-event@^1.0.2: - version "1.0.4" - resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.4.tgz#05bffd7ff928465093314708c93bdfa9bd1f0f5b" - integrity sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ== - -class-utils@^0.3.5: - version "0.3.6" - resolved "https://registry.yarnpkg.com/class-utils/-/class-utils-0.3.6.tgz#f93369ae8b9a7ce02fd41faad0ca83033190c463" - integrity sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg== - dependencies: - arr-union "^3.1.0" - define-property "^0.2.5" - isobject "^3.0.0" - static-extend "^0.1.1" - -cliui@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/cliui/-/cliui-5.0.0.tgz#deefcfdb2e800784aa34f46fa08e06851c7bbbc5" - integrity sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA== - dependencies: - string-width "^3.1.0" - strip-ansi "^5.2.0" - wrap-ansi "^5.1.0" - -clone-deep@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/clone-deep/-/clone-deep-4.0.1.tgz#c19fd9bdbbf85942b4fd979c84dcf7d5f07c2387" - integrity sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ== - dependencies: - is-plain-object "^2.0.4" - kind-of "^6.0.2" - shallow-clone "^3.0.0" - -collection-visit@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/collection-visit/-/collection-visit-1.0.0.tgz#4bc0373c164bc3291b4d368c829cf1a80a59dca0" - integrity sha512-lNkKvzEeMBBjUGHZ+q6z9pSJla0KWAQPvtzhEV9+iGyQYG+pBpl7xKDhxoNSOZH2hhv0v5k0y2yAM4o4SjoSkw== - dependencies: - map-visit "^1.0.0" - object-visit "^1.0.0" - -color-convert@^1.9.0: - version "1.9.3" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" - integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== - dependencies: - color-name "1.1.3" - -color-name@1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" - integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw== - -colorette@^1.2.1: - version "1.4.0" - resolved "https://registry.yarnpkg.com/colorette/-/colorette-1.4.0.tgz#5190fbb87276259a86ad700bff2c6d6faa3fca40" - integrity sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g== - -commander@^2.20.0: - version "2.20.3" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" - integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== - -commander@^7.0.0: - version "7.2.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-7.2.0.tgz#a36cb57d0b501ce108e4d20559a150a391d97ab7" - integrity sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw== - -component-emitter@^1.2.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.1.tgz#ef1d5796f7d93f135ee6fb684340b26403c97d17" - integrity sha512-T0+barUSQRTUQASh8bx02dl+DhF54GtIDY13Y3m9oWTklKbb3Wv974meRpeZ3lp1JpLVECWWNHC4vaG2XHXouQ== - -compressible@~2.0.16: - version "2.0.18" - resolved "https://registry.yarnpkg.com/compressible/-/compressible-2.0.18.tgz#af53cca6b070d4c3c0750fbd77286a6d7cc46fba" - integrity sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg== - dependencies: - mime-db ">= 1.43.0 < 2" - -compression@^1.7.4: - version "1.7.4" - resolved "https://registry.yarnpkg.com/compression/-/compression-1.7.4.tgz#95523eff170ca57c29a0ca41e6fe131f41e5bb8f" - integrity sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ== - dependencies: - accepts "~1.3.5" - bytes "3.0.0" - compressible "~2.0.16" - debug "2.6.9" - on-headers "~1.0.2" - safe-buffer "5.1.2" - vary "~1.1.2" - -concat-map@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" - integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== - -concat-with-sourcemaps@1.0.7: - version "1.0.7" - resolved "https://registry.yarnpkg.com/concat-with-sourcemaps/-/concat-with-sourcemaps-1.0.7.tgz#9420e100fb984cbde11a78dca2d818306bc8f0d2" - integrity sha512-5i4Spc9NNvVXzkR77x2kjcYCDZMNPLzP7ZBzJMNKZjXzk+E6tRVL/lPlYw60VM3hb7gf+iBQn2x1T8TpMN0SEw== - dependencies: - source-map "^0.6.1" - -connect-history-api-fallback@^1.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/connect-history-api-fallback/-/connect-history-api-fallback-1.6.0.tgz#8b32089359308d111115d81cad3fceab888f97bc" - integrity sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg== - -content-disposition@0.5.4: - version "0.5.4" - resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.4.tgz#8b82b4efac82512a02bb0b1dcec9d2c5e8eb5bfe" - integrity sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ== - dependencies: - safe-buffer "5.2.1" - -content-type@~1.0.4, content-type@~1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.5.tgz#8b773162656d1d1086784c8f23a54ce6d73d7918" - integrity sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA== - -cookie-signature@1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" - integrity sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ== - -cookie@0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.6.0.tgz#2798b04b071b0ecbff0dbb62a505a8efa4e19051" - integrity sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw== - -copy-descriptor@^0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" - integrity sha512-XgZ0pFcakEUlbwQEVNg3+QAis1FyTL3Qel9FYy8pSkQqoG3PNoT0bOCQtOXcOkur21r2Eq2kI+IE+gsmAEVlYw== - -core-util-is@~1.0.0: - version "1.0.3" - resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85" - integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ== - -cross-spawn@^6.0.0: - version "6.0.5" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" - integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ== - dependencies: - nice-try "^1.0.4" - path-key "^2.0.1" - semver "^5.5.0" - shebang-command "^1.2.0" - which "^1.2.9" - -cross-spawn@^7.0.3: - version "7.0.3" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" - integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== - dependencies: - path-key "^3.1.0" - shebang-command "^2.0.0" - which "^2.0.1" - -debug@2.6.9, debug@^2.2.0, debug@^2.3.3: - version "2.6.9" - resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" - integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== - dependencies: - ms "2.0.0" - -debug@^3.2.7: - version "3.2.7" - resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" - integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ== - dependencies: - ms "^2.1.1" - -debug@^4.1.0, debug@^4.1.1: - version "4.3.6" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.6.tgz#2ab2c38fbaffebf8aa95fdfe6d88438c7a13c52b" - integrity sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg== - dependencies: - ms "2.1.2" - -decamelize@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" - integrity sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA== - -decode-uri-component@^0.2.0: - version "0.2.2" - resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.2.tgz#e69dbe25d37941171dd540e024c444cd5188e1e9" - integrity sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ== - -deep-equal@^1.0.1: - version "1.1.2" - resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.1.2.tgz#78a561b7830eef3134c7f6f3a3d6af272a678761" - integrity sha512-5tdhKF6DbU7iIzrIOa1AOUt39ZRm13cmL1cGEh//aqR8x9+tNfbywRf0n5FD/18OKMdo7DNEtrX2t22ZAkI+eg== - dependencies: - is-arguments "^1.1.1" - is-date-object "^1.0.5" - is-regex "^1.1.4" - object-is "^1.1.5" - object-keys "^1.1.1" - regexp.prototype.flags "^1.5.1" - -default-gateway@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/default-gateway/-/default-gateway-4.2.0.tgz#167104c7500c2115f6dd69b0a536bb8ed720552b" - integrity sha512-h6sMrVB1VMWVrW13mSc6ia/DwYYw5MN6+exNu1OaJeFac5aSAvwM7lZ0NVfTABuSkQelr4h5oebg3KB1XPdjgA== - dependencies: - execa "^1.0.0" - ip-regex "^2.1.0" - -define-data-property@^1.0.1, define-data-property@^1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/define-data-property/-/define-data-property-1.1.4.tgz#894dc141bb7d3060ae4366f6a0107e68fbe48c5e" - integrity sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A== - dependencies: - es-define-property "^1.0.0" - es-errors "^1.3.0" - gopd "^1.0.1" - -define-properties@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.2.1.tgz#10781cc616eb951a80a034bafcaa7377f6af2b6c" - integrity sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg== - dependencies: - define-data-property "^1.0.1" - has-property-descriptors "^1.0.0" - object-keys "^1.1.1" - -define-property@^0.2.5: - version "0.2.5" - resolved "https://registry.yarnpkg.com/define-property/-/define-property-0.2.5.tgz#c35b1ef918ec3c990f9a5bc57be04aacec5c8116" - integrity sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA== - dependencies: - is-descriptor "^0.1.0" - -define-property@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/define-property/-/define-property-1.0.0.tgz#769ebaaf3f4a63aad3af9e8d304c9bbe79bfb0e6" - integrity sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA== - dependencies: - is-descriptor "^1.0.0" - -define-property@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/define-property/-/define-property-2.0.2.tgz#d459689e8d654ba77e02a817f8710d702cb16e9d" - integrity sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ== - dependencies: - is-descriptor "^1.0.2" - isobject "^3.0.1" - -del@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/del/-/del-4.1.1.tgz#9e8f117222ea44a31ff3a156c049b99052a9f0b4" - integrity sha512-QwGuEUouP2kVwQenAsOof5Fv8K9t3D8Ca8NxcXKrIpEHjTXK5J2nXLdP+ALI1cgv8wj7KuwBhTwBkOZSJKM5XQ== - dependencies: - "@types/glob" "^7.1.1" - globby "^6.1.0" - is-path-cwd "^2.0.0" - is-path-in-cwd "^2.0.0" - p-map "^2.0.0" - pify "^4.0.1" - rimraf "^2.6.3" - -depd@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" - integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw== - -depd@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" - integrity sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ== - -destroy@1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.2.0.tgz#4803735509ad8be552934c67df614f94e66fa015" - integrity sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg== - -detect-node@^2.0.4: - version "2.1.0" - resolved "https://registry.yarnpkg.com/detect-node/-/detect-node-2.1.0.tgz#c9c70775a49c3d03bc2c06d9a73be550f978f8b1" - integrity sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g== - -dns-equal@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/dns-equal/-/dns-equal-1.0.0.tgz#b39e7f1da6eb0a75ba9c17324b34753c47e0654d" - integrity sha512-z+paD6YUQsk+AbGCEM4PrOXSss5gd66QfcVBFTKR/HpFL9jCqikS94HYwKww6fQyO7IxrIIyUu+g0Ka9tUS2Cg== - -dns-packet@^1.3.1: - version "1.3.4" - resolved "https://registry.yarnpkg.com/dns-packet/-/dns-packet-1.3.4.tgz#e3455065824a2507ba886c55a89963bb107dec6f" - integrity sha512-BQ6F4vycLXBvdrJZ6S3gZewt6rcrks9KBgM9vrhW+knGRqc8uEdT7fuCwloc7nny5xNoMJ17HGH0R/6fpo8ECA== - dependencies: - ip "^1.1.0" - safe-buffer "^5.0.1" - -dns-txt@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/dns-txt/-/dns-txt-2.0.2.tgz#b91d806f5d27188e4ab3e7d107d881a1cc4642b6" - integrity sha512-Ix5PrWjphuSoUXV/Zv5gaFHjnaJtb02F2+Si3Ht9dyJ87+Z/lMmy+dpNHtTGraNK958ndXq2i+GLkWsWHcKaBQ== - dependencies: - buffer-indexof "^1.0.0" - -ee-first@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" - integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow== - -electron-to-chromium@^1.4.820: - version "1.5.4" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.4.tgz#cd477c830dd6fca41fbd5465c1ff6ce08ac22343" - integrity sha512-orzA81VqLyIGUEA77YkVA1D+N+nNfl2isJVjjmOyrlxuooZ19ynb+dOlaDTqd/idKRS9lDCSBmtzM+kyCsMnkA== - -emoji-regex@^7.0.1: - version "7.0.3" - resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156" - integrity sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA== - -encodeurl@~1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" - integrity sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w== - -end-of-stream@^1.1.0: - version "1.4.4" - resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" - integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== - dependencies: - once "^1.4.0" - -enhanced-resolve@^5.7.0: - version "5.17.1" - resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.17.1.tgz#67bfbbcc2f81d511be77d686a90267ef7f898a15" - integrity sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg== - dependencies: - graceful-fs "^4.2.4" - tapable "^2.2.0" - -enquirer@^2.3.6: - version "2.4.1" - resolved "https://registry.yarnpkg.com/enquirer/-/enquirer-2.4.1.tgz#93334b3fbd74fc7097b224ab4a8fb7e40bf4ae56" - integrity sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ== - dependencies: - ansi-colors "^4.1.1" - strip-ansi "^6.0.1" - -envinfo@^7.7.3: - version "7.13.0" - resolved "https://registry.yarnpkg.com/envinfo/-/envinfo-7.13.0.tgz#81fbb81e5da35d74e814941aeab7c325a606fb31" - integrity sha512-cvcaMr7KqXVh4nyzGTVqTum+gAiL265x5jUWQIDLq//zOGbW+gSW/C+OWLleY/rs9Qole6AZLMXPbtIFQbqu+Q== - -errno@^0.1.3: - version "0.1.8" - resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.8.tgz#8bb3e9c7d463be4976ff888f76b4809ebc2e811f" - integrity sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A== - dependencies: - prr "~1.0.1" - -es-define-property@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/es-define-property/-/es-define-property-1.0.0.tgz#c7faefbdff8b2696cf5f46921edfb77cc4ba3845" - integrity sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ== - dependencies: - get-intrinsic "^1.2.4" - -es-errors@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/es-errors/-/es-errors-1.3.0.tgz#05f75a25dab98e4fb1dcd5e1472c0546d5057c8f" - integrity sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw== - -es-module-lexer@^0.4.0: - version "0.4.1" - resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-0.4.1.tgz#dda8c6a14d8f340a24e34331e0fab0cb50438e0e" - integrity sha512-ooYciCUtfw6/d2w56UVeqHPcoCFAiJdz5XOkYpv/Txl1HMUozpXjz/2RIQgqwKdXNDPSF1W7mJCFse3G+HDyAA== - -escalade@^3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.2.tgz#54076e9ab29ea5bf3d8f1ed62acffbb88272df27" - integrity sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA== - -escape-html@~1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" - integrity sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow== - -eslint-scope@^5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" - integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw== - dependencies: - esrecurse "^4.3.0" - estraverse "^4.1.1" - -esrecurse@^4.3.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" - integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== - dependencies: - estraverse "^5.2.0" - -estraverse@^4.1.1: - version "4.3.0" - resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" - integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== - -estraverse@^5.2.0: - version "5.3.0" - resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" - integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== - -etag@~1.8.1: - version "1.8.1" - resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" - integrity sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg== - -eventemitter3@^4.0.0: - version "4.0.7" - resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f" - integrity sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw== - -events@^3.2.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400" - integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q== - -eventsource@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/eventsource/-/eventsource-2.0.2.tgz#76dfcc02930fb2ff339520b6d290da573a9e8508" - integrity sha512-IzUmBGPR3+oUG9dUeXynyNmf91/3zUSJg1lCktzKw47OXuhco54U3r9B7O4XX+Rb1Itm9OZ2b0RkTs10bICOxA== - -execa@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/execa/-/execa-1.0.0.tgz#c6236a5bb4df6d6f15e88e7f017798216749ddd8" - integrity sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA== - dependencies: - cross-spawn "^6.0.0" - get-stream "^4.0.0" - is-stream "^1.1.0" - npm-run-path "^2.0.0" - p-finally "^1.0.0" - signal-exit "^3.0.0" - strip-eof "^1.0.0" - -execa@^5.0.0: - version "5.1.1" - resolved "https://registry.yarnpkg.com/execa/-/execa-5.1.1.tgz#f80ad9cbf4298f7bd1d4c9555c21e93741c411dd" - integrity sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg== - dependencies: - cross-spawn "^7.0.3" - get-stream "^6.0.0" - human-signals "^2.1.0" - is-stream "^2.0.0" - merge-stream "^2.0.0" - npm-run-path "^4.0.1" - onetime "^5.1.2" - signal-exit "^3.0.3" - strip-final-newline "^2.0.0" - -expand-brackets@^2.1.4: - version "2.1.4" - resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-2.1.4.tgz#b77735e315ce30f6b6eff0f83b04151a22449622" - integrity sha512-w/ozOKR9Obk3qoWeY/WDi6MFta9AoMR+zud60mdnbniMcBxRuFJyDt2LdX/14A1UABeqk+Uk+LDfUpvoGKppZA== - dependencies: - debug "^2.3.3" - define-property "^0.2.5" - extend-shallow "^2.0.1" - posix-character-classes "^0.1.0" - regex-not "^1.0.0" - snapdragon "^0.8.1" - to-regex "^3.0.1" - -express@^4.17.1: - version "4.19.2" - resolved "https://registry.yarnpkg.com/express/-/express-4.19.2.tgz#e25437827a3aa7f2a827bc8171bbbb664a356465" - integrity sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q== - dependencies: - accepts "~1.3.8" - array-flatten "1.1.1" - body-parser "1.20.2" - content-disposition "0.5.4" - content-type "~1.0.4" - cookie "0.6.0" - cookie-signature "1.0.6" - debug "2.6.9" - depd "2.0.0" - encodeurl "~1.0.2" - escape-html "~1.0.3" - etag "~1.8.1" - finalhandler "1.2.0" - fresh "0.5.2" - http-errors "2.0.0" - merge-descriptors "1.0.1" - methods "~1.1.2" - on-finished "2.4.1" - parseurl "~1.3.3" - path-to-regexp "0.1.7" - proxy-addr "~2.0.7" - qs "6.11.0" - range-parser "~1.2.1" - safe-buffer "5.2.1" - send "0.18.0" - serve-static "1.15.0" - setprototypeof "1.2.0" - statuses "2.0.1" - type-is "~1.6.18" - utils-merge "1.0.1" - vary "~1.1.2" - -extend-shallow@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" - integrity sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug== - dependencies: - is-extendable "^0.1.0" - -extend-shallow@^3.0.0, extend-shallow@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-3.0.2.tgz#26a71aaf073b39fb2127172746131c2704028db8" - integrity sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q== - dependencies: - assign-symbols "^1.0.0" - is-extendable "^1.0.1" - -extglob@^2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/extglob/-/extglob-2.0.4.tgz#ad00fe4dc612a9232e8718711dc5cb5ab0285543" - integrity sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw== - dependencies: - array-unique "^0.3.2" - define-property "^1.0.0" - expand-brackets "^2.1.4" - extend-shallow "^2.0.1" - fragment-cache "^0.2.1" - regex-not "^1.0.0" - snapdragon "^0.8.1" - to-regex "^3.0.1" - -fast-deep-equal@^3.1.1: - version "3.1.3" - resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" - integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== - -fast-json-stable-stringify@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" - integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== - -fastest-levenshtein@^1.0.12: - version "1.0.16" - resolved "https://registry.yarnpkg.com/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz#210e61b6ff181de91ea9b3d1b84fdedd47e034e5" - integrity sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg== - -faye-websocket@^0.11.3, faye-websocket@^0.11.4: - version "0.11.4" - resolved "https://registry.yarnpkg.com/faye-websocket/-/faye-websocket-0.11.4.tgz#7f0d9275cfdd86a1c963dc8b65fcc451edcbb1da" - integrity sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g== - dependencies: - websocket-driver ">=0.5.1" - -file-uri-to-path@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd" - integrity sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw== - -fill-range@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7" - integrity sha512-VcpLTWqWDiTerugjj8e3+esbg+skS3M9e54UuR3iCeIDMXCLTsAH8hTSzDQU/X6/6t3eYkOKoZSef2PlU6U1XQ== - dependencies: - extend-shallow "^2.0.1" - is-number "^3.0.0" - repeat-string "^1.6.1" - to-regex-range "^2.1.0" - -finalhandler@1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.2.0.tgz#7d23fe5731b207b4640e4fcd00aec1f9207a7b32" - integrity sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg== - dependencies: - debug "2.6.9" - encodeurl "~1.0.2" - escape-html "~1.0.3" - on-finished "2.4.1" - parseurl "~1.3.3" - statuses "2.0.1" - unpipe "~1.0.0" - -find-up@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73" - integrity sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg== - dependencies: - locate-path "^3.0.0" - -find-up@^4.0.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" - integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== - dependencies: - locate-path "^5.0.0" - path-exists "^4.0.0" - -flat@^5.0.2: - version "5.0.2" - resolved "https://registry.yarnpkg.com/flat/-/flat-5.0.2.tgz#8ca6fe332069ffa9d324c327198c598259ceb241" - integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ== - -follow-redirects@^1.0.0: - version "1.15.6" - resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.6.tgz#7f815c0cda4249c74ff09e95ef97c23b5fd0399b" - integrity sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA== - -for-in@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" - integrity sha512-7EwmXrOjyL+ChxMhmG5lnW9MPt1aIeZEwKhQzoBUdTV0N3zuwWDZYVJatDvZ2OyzPUvdIAZDsCetk3coyMfcnQ== - -forwarded@0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811" - integrity sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow== - -fragment-cache@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/fragment-cache/-/fragment-cache-0.2.1.tgz#4290fad27f13e89be7f33799c6bc5a0abfff0d19" - integrity sha512-GMBAbW9antB8iZRHLoGw0b3HANt57diZYFO/HL1JGIC1MjKrdmhxvrJbupnVvpys0zsz7yBApXdQyfepKly2kA== - dependencies: - map-cache "^0.2.2" - -fresh@0.5.2: - version "0.5.2" - resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" - integrity sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q== - -fs.realpath@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" - integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== - -fsevents@^1.2.7: - version "1.2.13" - resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.2.13.tgz#f325cb0455592428bcf11b383370ef70e3bfcc38" - integrity sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw== - dependencies: - bindings "^1.5.0" - nan "^2.12.1" - -function-bind@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" - integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== - -functions-have-names@^1.2.3: - version "1.2.3" - resolved "https://registry.yarnpkg.com/functions-have-names/-/functions-have-names-1.2.3.tgz#0404fe4ee2ba2f607f0e0ec3c80bae994133b834" - integrity sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ== - -get-caller-file@^2.0.1: - version "2.0.5" - resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" - integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== - -get-intrinsic@^1.1.3, get-intrinsic@^1.2.4: - version "1.2.4" - resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.4.tgz#e385f5a4b5227d449c3eabbad05494ef0abbeadd" - integrity sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ== - dependencies: - es-errors "^1.3.0" - function-bind "^1.1.2" - has-proto "^1.0.1" - has-symbols "^1.0.3" - hasown "^2.0.0" - -get-stream@^4.0.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5" - integrity sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w== - dependencies: - pump "^3.0.0" - -get-stream@^6.0.0: - version "6.0.1" - resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7" - integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg== - -get-value@^2.0.3, get-value@^2.0.6: - version "2.0.6" - resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" - integrity sha512-Ln0UQDlxH1BapMu3GPtf7CuYNwRZf2gwCuPqbyG6pB8WfmFpzqcy4xtAaAMUhnNqjMKTiCPZG2oMT3YSx8U2NA== - -glob-parent@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-3.1.0.tgz#9e6af6299d8d3bd2bd40430832bd113df906c5ae" - integrity sha512-E8Ak/2+dZY6fnzlR7+ueWvhsH1SjHr4jjss4YS/h4py44jY9MhK/VFdaZJAWDz6BbL21KeteKxFSFpq8OS5gVA== - dependencies: - is-glob "^3.1.0" - path-dirname "^1.0.0" - -glob-to-regexp@^0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz#c75297087c851b9a578bd217dd59a92f59fe546e" - integrity sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw== - -glob@^7.0.3, glob@^7.1.3: - version "7.2.3" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" - integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.1.1" - once "^1.3.0" - path-is-absolute "^1.0.0" - -globby@^6.1.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/globby/-/globby-6.1.0.tgz#f5a6d70e8395e21c858fb0489d64df02424d506c" - integrity sha512-KVbFv2TQtbzCoxAnfD6JcHZTYCzyliEaaeM/gH8qQdkKr5s0OP9scEgvdcngyk7AVdY6YVW/TJHd+lQ/Df3Daw== - dependencies: - array-union "^1.0.1" - glob "^7.0.3" - object-assign "^4.0.1" - pify "^2.0.0" - pinkie-promise "^2.0.0" - -gopd@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.0.1.tgz#29ff76de69dac7489b7c0918a5788e56477c332c" - integrity sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA== - dependencies: - get-intrinsic "^1.1.3" - -graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.2.4: - version "4.2.11" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" - integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== - -handle-thing@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/handle-thing/-/handle-thing-2.0.1.tgz#857f79ce359580c340d43081cc648970d0bb234e" - integrity sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg== - -has-flag@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" - integrity sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw== - -has-flag@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" - integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== - -has-property-descriptors@^1.0.0, has-property-descriptors@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz#963ed7d071dc7bf5f084c5bfbe0d1b6222586854" - integrity sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg== - dependencies: - es-define-property "^1.0.0" - -has-proto@^1.0.1: - version "1.0.3" - resolved "https://registry.yarnpkg.com/has-proto/-/has-proto-1.0.3.tgz#b31ddfe9b0e6e9914536a6ab286426d0214f77fd" - integrity sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q== - -has-symbols@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" - integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== - -has-tostringtag@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.2.tgz#2cdc42d40bef2e5b4eeab7c01a73c54ce7ab5abc" - integrity sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw== - dependencies: - has-symbols "^1.0.3" - -has-value@^0.3.1: - version "0.3.1" - resolved "https://registry.yarnpkg.com/has-value/-/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f" - integrity sha512-gpG936j8/MzaeID5Yif+577c17TxaDmhuyVgSwtnL/q8UUTySg8Mecb+8Cf1otgLoD7DDH75axp86ER7LFsf3Q== - dependencies: - get-value "^2.0.3" - has-values "^0.1.4" - isobject "^2.0.0" - -has-value@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-value/-/has-value-1.0.0.tgz#18b281da585b1c5c51def24c930ed29a0be6b177" - integrity sha512-IBXk4GTsLYdQ7Rvt+GRBrFSVEkmuOUy4re0Xjd9kJSUQpnTrWR4/y9RpfexN9vkAPMFuQoeWKwqzPozRTlasGw== - dependencies: - get-value "^2.0.6" - has-values "^1.0.0" - isobject "^3.0.0" - -has-values@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/has-values/-/has-values-0.1.4.tgz#6d61de95d91dfca9b9a02089ad384bff8f62b771" - integrity sha512-J8S0cEdWuQbqD9//tlZxiMuMNmxB8PlEwvYwuxsTmR1G5RXUePEX/SJn7aD0GMLieuZYSwNH0cQuJGwnYunXRQ== - -has-values@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-values/-/has-values-1.0.0.tgz#95b0b63fec2146619a6fe57fe75628d5a39efe4f" - integrity sha512-ODYZC64uqzmtfGMEAX/FvZiRyWLpAC3vYnNunURUnkGVTS+mI0smVsWaPydRBsE3g+ok7h960jChO8mFcWlHaQ== - dependencies: - is-number "^3.0.0" - kind-of "^4.0.0" - -hasown@^2.0.0, hasown@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.2.tgz#003eaf91be7adc372e84ec59dc37252cedb80003" - integrity sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ== - dependencies: - function-bind "^1.1.2" - -hpack.js@^2.1.6: - version "2.1.6" - resolved "https://registry.yarnpkg.com/hpack.js/-/hpack.js-2.1.6.tgz#87774c0949e513f42e84575b3c45681fade2a0b2" - integrity sha512-zJxVehUdMGIKsRaNt7apO2Gqp0BdqW5yaiGHXXmbpvxgBYVZnAql+BJb4RO5ad2MgpbZKn5G6nMnegrH1FcNYQ== - dependencies: - inherits "^2.0.1" - obuf "^1.0.0" - readable-stream "^2.0.1" - wbuf "^1.1.0" - -html-entities@^1.3.1: - version "1.4.0" - resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-1.4.0.tgz#cfbd1b01d2afaf9adca1b10ae7dffab98c71d2dc" - integrity sha512-8nxjcBcd8wovbeKx7h3wTji4e6+rhaVuPNpMqwWgnHh+N9ToqsCs6XztWRBPQ+UtzsoMAdKZtUENoVzU/EMtZA== - -http-deceiver@^1.2.7: - version "1.2.7" - resolved "https://registry.yarnpkg.com/http-deceiver/-/http-deceiver-1.2.7.tgz#fa7168944ab9a519d337cb0bec7284dc3e723d87" - integrity sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw== - -http-errors@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-2.0.0.tgz#b7774a1486ef73cf7667ac9ae0858c012c57b9d3" - integrity sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ== - dependencies: - depd "2.0.0" - inherits "2.0.4" - setprototypeof "1.2.0" - statuses "2.0.1" - toidentifier "1.0.1" - -http-errors@~1.6.2: - version "1.6.3" - resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.3.tgz#8b55680bb4be283a0b5bf4ea2e38580be1d9320d" - integrity sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A== - dependencies: - depd "~1.1.2" - inherits "2.0.3" - setprototypeof "1.1.0" - statuses ">= 1.4.0 < 2" - -http-parser-js@>=0.5.1: - version "0.5.8" - resolved "https://registry.yarnpkg.com/http-parser-js/-/http-parser-js-0.5.8.tgz#af23090d9ac4e24573de6f6aecc9d84a48bf20e3" - integrity sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q== - -http-proxy-middleware@0.19.1: - version "0.19.1" - resolved "https://registry.yarnpkg.com/http-proxy-middleware/-/http-proxy-middleware-0.19.1.tgz#183c7dc4aa1479150306498c210cdaf96080a43a" - integrity sha512-yHYTgWMQO8VvwNS22eLLloAkvungsKdKTLO8AJlftYIKNfJr3GK3zK0ZCfzDDGUBttdGc8xFy1mCitvNKQtC3Q== - dependencies: - http-proxy "^1.17.0" - is-glob "^4.0.0" - lodash "^4.17.11" - micromatch "^3.1.10" - -http-proxy@^1.17.0: - version "1.18.1" - resolved "https://registry.yarnpkg.com/http-proxy/-/http-proxy-1.18.1.tgz#401541f0534884bbf95260334e72f88ee3976549" - integrity sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ== - dependencies: - eventemitter3 "^4.0.0" - follow-redirects "^1.0.0" - requires-port "^1.0.0" - -human-signals@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" - integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw== - -iconv-lite@0.4.24: - version "0.4.24" - resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" - integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== - dependencies: - safer-buffer ">= 2.1.2 < 3" - -iconv-lite@^0.6.2: - version "0.6.3" - resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.6.3.tgz#a52f80bf38da1952eb5c681790719871a1a72501" - integrity sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw== - dependencies: - safer-buffer ">= 2.1.2 < 3.0.0" - -import-local@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/import-local/-/import-local-2.0.0.tgz#55070be38a5993cf18ef6db7e961f5bee5c5a09d" - integrity sha512-b6s04m3O+s3CGSbqDIyP4R6aAwAeYlVq9+WUWep6iHa8ETRf9yei1U48C5MmfJmV9AiLYYBKPMq/W+/WRpQmCQ== - dependencies: - pkg-dir "^3.0.0" - resolve-cwd "^2.0.0" - -import-local@^3.0.2: - version "3.2.0" - resolved "https://registry.yarnpkg.com/import-local/-/import-local-3.2.0.tgz#c3d5c745798c02a6f8b897726aba5100186ee260" - integrity sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA== - dependencies: - pkg-dir "^4.2.0" - resolve-cwd "^3.0.0" - -inflight@^1.0.4: - version "1.0.6" - resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" - integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== - dependencies: - once "^1.3.0" - wrappy "1" - -inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.3: - version "2.0.4" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" - integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== - -inherits@2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" - integrity sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw== - -internal-ip@^4.3.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/internal-ip/-/internal-ip-4.3.0.tgz#845452baad9d2ca3b69c635a137acb9a0dad0907" - integrity sha512-S1zBo1D6zcsyuC6PMmY5+55YMILQ9av8lotMx447Bq6SAgo/sDK6y6uUKmuYhW7eacnIhFfsPmCNYdDzsnnDCg== - dependencies: - default-gateway "^4.2.0" - ipaddr.js "^1.9.0" - -interpret@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/interpret/-/interpret-2.2.0.tgz#1a78a0b5965c40a5416d007ad6f50ad27c417df9" - integrity sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw== - -ip-regex@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/ip-regex/-/ip-regex-2.1.0.tgz#fa78bf5d2e6913c911ce9f819ee5146bb6d844e9" - integrity sha512-58yWmlHpp7VYfcdTwMTvwMmqx/Elfxjd9RXTDyMsbL7lLWmhMylLEqiYVLKuLzOZqVgiWXD9MfR62Vv89VRxkw== - -ip@^1.1.0, ip@^1.1.5: - version "1.1.9" - resolved "https://registry.yarnpkg.com/ip/-/ip-1.1.9.tgz#8dfbcc99a754d07f425310b86a99546b1151e396" - integrity sha512-cyRxvOEpNHNtchU3Ln9KC/auJgup87llfQpQ+t5ghoC/UhL16SWzbueiCsdTnWmqAWl7LadfuwhlqmtOaqMHdQ== - -ipaddr.js@1.9.1, ipaddr.js@^1.9.0: - version "1.9.1" - resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3" - integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g== - -is-absolute-url@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/is-absolute-url/-/is-absolute-url-3.0.3.tgz#96c6a22b6a23929b11ea0afb1836c36ad4a5d698" - integrity sha512-opmNIX7uFnS96NtPmhWQgQx6/NYFgsUXYMllcfzwWKUMwfo8kku1TvE6hkNcH+Q1ts5cMVrsY7j0bxXQDciu9Q== - -is-accessor-descriptor@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-1.0.1.tgz#3223b10628354644b86260db29b3e693f5ceedd4" - integrity sha512-YBUanLI8Yoihw923YeFUS5fs0fF2f5TSFTNiYAAzhhDscDa3lEqYuz1pDOEP5KvX94I9ey3vsqjJcLVFVU+3QA== - dependencies: - hasown "^2.0.0" - -is-arguments@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.1.1.tgz#15b3f88fda01f2a97fec84ca761a560f123efa9b" - integrity sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA== - dependencies: - call-bind "^1.0.2" - has-tostringtag "^1.0.0" - -is-binary-path@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-1.0.1.tgz#75f16642b480f187a711c814161fd3a4a7655898" - integrity sha512-9fRVlXc0uCxEDj1nQzaWONSpbTfx0FmJfzHF7pwlI8DkWGoHBBea4Pg5Ky0ojwwxQmnSifgbKkI06Qv0Ljgj+Q== - dependencies: - binary-extensions "^1.0.0" - -is-buffer@^1.1.5: - version "1.1.6" - resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" - integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== - -is-core-module@^2.13.0: - version "2.15.0" - resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.15.0.tgz#71c72ec5442ace7e76b306e9d48db361f22699ea" - integrity sha512-Dd+Lb2/zvk9SKy1TGCt1wFJFo/MWBPMX5x7KcvLajWTGuomczdQX61PvY5yK6SVACwpoexWo81IfFyoKY2QnTA== - dependencies: - hasown "^2.0.2" - -is-data-descriptor@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-1.0.1.tgz#2109164426166d32ea38c405c1e0945d9e6a4eeb" - integrity sha512-bc4NlCDiCr28U4aEsQ3Qs2491gVq4V8G7MQyws968ImqjKuYtTJXrl7Vq7jsN7Ly/C3xj5KWFrY7sHNeDkAzXw== - dependencies: - hasown "^2.0.0" - -is-date-object@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.5.tgz#0841d5536e724c25597bf6ea62e1bd38298df31f" - integrity sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ== - dependencies: - has-tostringtag "^1.0.0" - -is-descriptor@^0.1.0: - version "0.1.7" - resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-0.1.7.tgz#2727eb61fd789dcd5bdf0ed4569f551d2fe3be33" - integrity sha512-C3grZTvObeN1xud4cRWl366OMXZTj0+HGyk4hvfpx4ZHt1Pb60ANSXqCK7pdOTeUQpRzECBSTphqvD7U+l22Eg== - dependencies: - is-accessor-descriptor "^1.0.1" - is-data-descriptor "^1.0.1" - -is-descriptor@^1.0.0, is-descriptor@^1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-1.0.3.tgz#92d27cb3cd311c4977a4db47df457234a13cb306" - integrity sha512-JCNNGbwWZEVaSPtS45mdtrneRWJFp07LLmykxeFV5F6oBvNF8vHSfJuJgoT472pSfk+Mf8VnlrspaFBHWM8JAw== - dependencies: - is-accessor-descriptor "^1.0.1" - is-data-descriptor "^1.0.1" - -is-extendable@^0.1.0, is-extendable@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" - integrity sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw== - -is-extendable@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-1.0.1.tgz#a7470f9e426733d81bd81e1155264e3a3507cab4" - integrity sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA== - dependencies: - is-plain-object "^2.0.4" - -is-extglob@^2.1.0, is-extglob@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" - integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== - -is-fullwidth-code-point@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" - integrity sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w== - -is-glob@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-3.1.0.tgz#7ba5ae24217804ac70707b96922567486cc3e84a" - integrity sha512-UFpDDrPgM6qpnFNI+rh/p3bUaq9hKLZN8bMUWzxmcnZVS3omf4IPK+BrewlnWjO1WmUsMYuSjKh4UJuV4+Lqmw== - dependencies: - is-extglob "^2.1.0" - -is-glob@^4.0.0: - version "4.0.3" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" - integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== - dependencies: - is-extglob "^2.1.1" - -is-number@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" - integrity sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg== - dependencies: - kind-of "^3.0.2" - -is-path-cwd@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-2.2.0.tgz#67d43b82664a7b5191fd9119127eb300048a9fdb" - integrity sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ== - -is-path-in-cwd@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-path-in-cwd/-/is-path-in-cwd-2.1.0.tgz#bfe2dca26c69f397265a4009963602935a053acb" - integrity sha512-rNocXHgipO+rvnP6dk3zI20RpOtrAM/kzbB258Uw5BWr3TpXi861yzjo16Dn4hUox07iw5AyeMLHWsujkjzvRQ== - dependencies: - is-path-inside "^2.1.0" - -is-path-inside@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-2.1.0.tgz#7c9810587d659a40d27bcdb4d5616eab059494b2" - integrity sha512-wiyhTzfDWsvwAW53OBWF5zuvaOGlZ6PwYxAbPVDhpm+gM09xKQGjBq/8uYN12aDvMxnAnq3dxTyoSoRNmg5YFg== - dependencies: - path-is-inside "^1.0.2" - -is-plain-object@^2.0.3, is-plain-object@^2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" - integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og== - dependencies: - isobject "^3.0.1" - -is-regex@^1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.4.tgz#eef5663cd59fa4c0ae339505323df6854bb15958" - integrity sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg== - dependencies: - call-bind "^1.0.2" - has-tostringtag "^1.0.0" - -is-stream@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" - integrity sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ== - -is-stream@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077" - integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg== - -is-windows@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" - integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA== - -is-wsl@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-1.1.0.tgz#1f16e4aa22b04d1336b66188a66af3c600c3a66d" - integrity sha512-gfygJYZ2gLTDlmbWMI0CE2MwnFzSN/2SZfkMlItC4K/JBlsWVDB0bO6XhqcY13YXE7iMcAJnzTCJjPiTeJJ0Mw== - -isarray@1.0.0, isarray@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" - integrity sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ== - -isexe@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" - integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== - -isobject@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89" - integrity sha512-+OUdGJlgjOBZDfxnDjYYG6zp487z0JGNQq3cYQYg5f5hKR+syHMsaztzGeml/4kGG55CSpKSpWTY+jYGgsHLgA== - dependencies: - isarray "1.0.0" - -isobject@^3.0.0, isobject@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" - integrity sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg== - -jest-worker@^27.4.5: - version "27.5.1" - resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-27.5.1.tgz#8d146f0900e8973b106b6f73cc1e9a8cb86f8db0" - integrity sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg== - dependencies: - "@types/node" "*" - merge-stream "^2.0.0" - supports-color "^8.0.0" - -json-parse-better-errors@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" - integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw== - -json-schema-traverse@^0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" - integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== - -killable@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/killable/-/killable-1.0.1.tgz#4c8ce441187a061c7474fb87ca08e2a638194892" - integrity sha512-LzqtLKlUwirEUyl/nicirVmNiPvYs7l5n8wOPP7fyJVpUPkvCnW/vuiXGpylGUlnPDnB7311rARzAt3Mhswpjg== - -kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0: - version "3.2.2" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" - integrity sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ== - dependencies: - is-buffer "^1.1.5" - -kind-of@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-4.0.0.tgz#20813df3d712928b207378691a45066fae72dd57" - integrity sha512-24XsCxmEbRwEDbz/qz3stgin8TTzZ1ESR56OMCN0ujYg+vRutNSiOj9bHH9u85DKgXguraugV5sFuvbD4FW/hw== - dependencies: - is-buffer "^1.1.5" - -kind-of@^6.0.2: - version "6.0.3" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" - integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== - -loader-runner@^4.2.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-4.3.0.tgz#c1b4a163b99f614830353b16755e7149ac2314e1" - integrity sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg== - -locate-path@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e" - integrity sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A== - dependencies: - p-locate "^3.0.0" - path-exists "^3.0.0" - -locate-path@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" - integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== - dependencies: - p-locate "^4.1.0" - -lodash@^4.17.11, lodash@^4.17.14: - version "4.17.21" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" - integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== - -loglevel@^1.6.8: - version "1.9.1" - resolved "https://registry.yarnpkg.com/loglevel/-/loglevel-1.9.1.tgz#d63976ac9bcd03c7c873116d41c2a85bafff1be7" - integrity sha512-hP3I3kCrDIMuRwAwHltphhDM1r8i55H33GgqjXbrisuJhF4kRhW1dNuxsRklp4bXl8DSdLaNLuiL4A/LWRfxvg== - -map-cache@^0.2.2: - version "0.2.2" - resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf" - integrity sha512-8y/eV9QQZCiyn1SprXSrCmqJN0yNRATe+PO8ztwqrvrbdRLA3eYJF0yaR0YayLWkMbsQSKWS9N2gPcGEc4UsZg== - -map-visit@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/map-visit/-/map-visit-1.0.0.tgz#ecdca8f13144e660f1b5bd41f12f3479d98dfb8f" - integrity sha512-4y7uGv8bd2WdM9vpQsiQNo41Ln1NvhvDRuVt0k2JZQ+ezN2uaQes7lZeZ+QQUHOLQAtDaBJ+7wCbi+ab/KFs+w== - dependencies: - object-visit "^1.0.0" - -media-typer@0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" - integrity sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ== - -memory-fs@^0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.4.1.tgz#3a9a20b8462523e447cfbc7e8bb80ed667bfc552" - integrity sha512-cda4JKCxReDXFXRqOHPQscuIYg1PvxbE2S2GP45rnwfEK+vZaXC8C1OFvdHIbgw0DLzowXGVoxLaAmlgRy14GQ== - dependencies: - errno "^0.1.3" - readable-stream "^2.0.1" - -merge-descriptors@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" - integrity sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w== - -merge-stream@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" - integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== - -methods@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" - integrity sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w== - -micromatch@^3.1.10, micromatch@^3.1.4: - version "3.1.10" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23" - integrity sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg== - dependencies: - arr-diff "^4.0.0" - array-unique "^0.3.2" - braces "^2.3.1" - define-property "^2.0.2" - extend-shallow "^3.0.2" - extglob "^2.0.4" - fragment-cache "^0.2.1" - kind-of "^6.0.2" - nanomatch "^1.2.9" - object.pick "^1.3.0" - regex-not "^1.0.0" - snapdragon "^0.8.1" - to-regex "^3.0.2" - -mime-db@1.52.0: - version "1.52.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" - integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== - -"mime-db@>= 1.43.0 < 2": - version "1.53.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.53.0.tgz#3cb63cd820fc29896d9d4e8c32ab4fcd74ccb447" - integrity sha512-oHlN/w+3MQ3rba9rqFr6V/ypF10LSkdwUysQL7GkXoTgIWeV+tcXGA852TBxH+gsh8UWoyhR1hKcoMJTuWflpg== - -mime-types@^2.1.27, mime-types@~2.1.17, mime-types@~2.1.24, mime-types@~2.1.34: - version "2.1.35" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" - integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== - dependencies: - mime-db "1.52.0" - -mime@1.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" - integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== - -mime@^2.4.4: - version "2.6.0" - resolved "https://registry.yarnpkg.com/mime/-/mime-2.6.0.tgz#a2a682a95cd4d0cb1d6257e28f83da7e35800367" - integrity sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg== - -mimic-fn@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" - integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== - -minimalistic-assert@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" - integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A== - -minimatch@^3.1.1: - version "3.1.2" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" - integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== - dependencies: - brace-expansion "^1.1.7" - -minimist@^1.2.6: - version "1.2.8" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" - integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== - -mixin-deep@^1.2.0: - version "1.3.2" - resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.2.tgz#1120b43dc359a785dce65b55b82e257ccf479566" - integrity sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA== - dependencies: - for-in "^1.0.2" - is-extendable "^1.0.1" - -mkdirp@^0.5.1, mkdirp@^0.5.6: - version "0.5.6" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.6.tgz#7def03d2432dcae4ba1d611445c48396062255f6" - integrity sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw== - dependencies: - minimist "^1.2.6" - -ms@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" - integrity sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A== - -ms@2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" - integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== - -ms@2.1.3, ms@^2.1.1: - version "2.1.3" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" - integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== - -multicast-dns-service-types@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/multicast-dns-service-types/-/multicast-dns-service-types-1.1.0.tgz#899f11d9686e5e05cb91b35d5f0e63b773cfc901" - integrity sha512-cnAsSVxIDsYt0v7HmC0hWZFwwXSh+E6PgCrREDuN/EsjgLwA5XRmlMHhSiDPrt6HxY1gTivEa/Zh7GtODoLevQ== - -multicast-dns@^6.0.1: - version "6.2.3" - resolved "https://registry.yarnpkg.com/multicast-dns/-/multicast-dns-6.2.3.tgz#a0ec7bd9055c4282f790c3c82f4e28db3b31b229" - integrity sha512-ji6J5enbMyGRHIAkAOu3WdV8nggqviKCEKtXcOqfphZZtQrmHKycfynJ2V7eVPUA4NhJ6V7Wf4TmGbTwKE9B6g== - dependencies: - dns-packet "^1.3.1" - thunky "^1.0.2" - -nan@^2.12.1: - version "2.20.0" - resolved "https://registry.yarnpkg.com/nan/-/nan-2.20.0.tgz#08c5ea813dd54ed16e5bd6505bf42af4f7838ca3" - integrity sha512-bk3gXBZDGILuuo/6sKtr0DQmSThYHLtNCdSdXk9YkxD/jK6X2vmCyyXBBxyqZ4XcnzTyYEAThfX3DCEnLf6igw== - -nanomatch@^1.2.9: - version "1.2.13" - resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119" - integrity sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA== - dependencies: - arr-diff "^4.0.0" - array-unique "^0.3.2" - define-property "^2.0.2" - extend-shallow "^3.0.2" - fragment-cache "^0.2.1" - is-windows "^1.0.2" - kind-of "^6.0.2" - object.pick "^1.3.0" - regex-not "^1.0.0" - snapdragon "^0.8.1" - to-regex "^3.0.1" - -negotiator@0.6.3: - version "0.6.3" - resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" - integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg== - -neo-async@^2.6.2: - version "2.6.2" - resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" - integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== - -nice-try@^1.0.4: - version "1.0.5" - resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" - integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== - -node-forge@^0.10.0: - version "0.10.0" - resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-0.10.0.tgz#32dea2afb3e9926f02ee5ce8794902691a676bf3" - integrity sha512-PPmu8eEeG9saEUvI97fm4OYxXVB6bFvyNTyiUOBichBpFG8A1Ljw3bY62+5oOjDEMHRnd0Y7HQ+x7uzxOzC6JA== - -node-releases@^2.0.14: - version "2.0.18" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.18.tgz#f010e8d35e2fe8d6b2944f03f70213ecedc4ca3f" - integrity sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g== - -normalize-path@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9" - integrity sha512-3pKJwH184Xo/lnH6oyP1q2pMd7HcypqqmRs91/6/i2CGtWwIKGCkOOMTm/zXbgTEWHw1uNpNi/igc3ePOYHb6w== - dependencies: - remove-trailing-separator "^1.0.1" - -normalize-path@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" - integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== - -npm-run-path@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f" - integrity sha512-lJxZYlT4DW/bRUtFh1MQIWqmLwQfAxnqWG4HhEdjMlkrJYnJn0Jrr2u3mgxqaWsdiBc76TYkTG/mhrnYTuzfHw== - dependencies: - path-key "^2.0.0" - -npm-run-path@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea" - integrity sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw== - dependencies: - path-key "^3.0.0" - -object-assign@^4.0.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" - integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== - -object-copy@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/object-copy/-/object-copy-0.1.0.tgz#7e7d858b781bd7c991a41ba975ed3812754e998c" - integrity sha512-79LYn6VAb63zgtmAteVOWo9Vdj71ZVBy3Pbse+VqxDpEP83XuujMrGqHIwAXJ5I/aM0zU7dIyIAhifVTPrNItQ== - dependencies: - copy-descriptor "^0.1.0" - define-property "^0.2.5" - kind-of "^3.0.3" - -object-inspect@^1.13.1: - version "1.13.2" - resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.2.tgz#dea0088467fb991e67af4058147a24824a3043ff" - integrity sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g== - -object-is@^1.1.5: - version "1.1.6" - resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.1.6.tgz#1a6a53aed2dd8f7e6775ff870bea58545956ab07" - integrity sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q== - dependencies: - call-bind "^1.0.7" - define-properties "^1.2.1" - -object-keys@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" - integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== - -object-visit@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/object-visit/-/object-visit-1.0.1.tgz#f79c4493af0c5377b59fe39d395e41042dd045bb" - integrity sha512-GBaMwwAVK9qbQN3Scdo0OyvgPW7l3lnaVMj84uTOZlswkX0KpF6fyDBJhtTthf7pymztoN36/KEr1DyhF96zEA== - dependencies: - isobject "^3.0.0" - -object.pick@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/object.pick/-/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747" - integrity sha512-tqa/UMy/CCoYmj+H5qc07qvSL9dqcs/WZENZ1JbtWBlATP+iVOe778gE6MSijnyCnORzDuX6hU+LA4SZ09YjFQ== - dependencies: - isobject "^3.0.1" - -obuf@^1.0.0, obuf@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/obuf/-/obuf-1.1.2.tgz#09bea3343d41859ebd446292d11c9d4db619084e" - integrity sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg== - -on-finished@2.4.1: - version "2.4.1" - resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.4.1.tgz#58c8c44116e54845ad57f14ab10b03533184ac3f" - integrity sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg== - dependencies: - ee-first "1.1.1" - -on-headers@~1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/on-headers/-/on-headers-1.0.2.tgz#772b0ae6aaa525c399e489adfad90c403eb3c28f" - integrity sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA== - -once@^1.3.0, once@^1.3.1, once@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" - integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== - dependencies: - wrappy "1" - -onetime@^5.1.2: - version "5.1.2" - resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e" - integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg== - dependencies: - mimic-fn "^2.1.0" - -opn@^5.5.0: - version "5.5.0" - resolved "https://registry.yarnpkg.com/opn/-/opn-5.5.0.tgz#fc7164fab56d235904c51c3b27da6758ca3b9bfc" - integrity sha512-PqHpggC9bLV0VeWcdKhkpxY+3JTzetLSqTCWL/z/tFIbI6G8JCjondXklT1JinczLz2Xib62sSp0T/gKT4KksA== - dependencies: - is-wsl "^1.1.0" - -p-finally@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" - integrity sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow== - -p-limit@^2.0.0, p-limit@^2.2.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" - integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== - dependencies: - p-try "^2.0.0" - -p-locate@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-3.0.0.tgz#322d69a05c0264b25997d9f40cd8a891ab0064a4" - integrity sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ== - dependencies: - p-limit "^2.0.0" - -p-locate@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" - integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== - dependencies: - p-limit "^2.2.0" - -p-map@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/p-map/-/p-map-2.1.0.tgz#310928feef9c9ecc65b68b17693018a665cea175" - integrity sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw== - -p-retry@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/p-retry/-/p-retry-3.0.1.tgz#316b4c8893e2c8dc1cfa891f406c4b422bebf328" - integrity sha512-XE6G4+YTTkT2a0UWb2kjZe8xNwf8bIbnqpc/IS/idOBVhyves0mK5OJgeocjx7q5pvX/6m23xuzVPYT1uGM73w== - dependencies: - retry "^0.12.0" - -p-try@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" - integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== - -parseurl@~1.3.2, parseurl@~1.3.3: - version "1.3.3" - resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" - integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== - -pascalcase@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" - integrity sha512-XHXfu/yOQRy9vYOtUDVMN60OEJjW013GoObG1o+xwQTpB9eYJX/BjXMsdW13ZDPruFhYYn0AG22w0xgQMwl3Nw== - -path-dirname@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/path-dirname/-/path-dirname-1.0.2.tgz#cc33d24d525e099a5388c0336c6e32b9160609e0" - integrity sha512-ALzNPpyNq9AqXMBjeymIjFDAkAFH06mHJH/cSBHAgU0s4vfpBn6b2nf8tiRLvagKD8RbTpq2FKTBg7cl9l3c7Q== - -path-exists@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" - integrity sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ== - -path-exists@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" - integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== - -path-is-absolute@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" - integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== - -path-is-inside@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53" - integrity sha512-DUWJr3+ULp4zXmol/SZkFf3JGsS9/SIv+Y3Rt93/UjPpDpklB5f1er4O3POIbUuUJ3FXgqte2Q7SrU6zAqwk8w== - -path-key@^2.0.0, path-key@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" - integrity sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw== - -path-key@^3.0.0, path-key@^3.1.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" - integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== - -path-parse@^1.0.7: - version "1.0.7" - resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" - integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== - -path-to-regexp@0.1.7: - version "0.1.7" - resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" - integrity sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ== - -picocolors@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.1.tgz#a8ad579b571952f0e5d25892de5445bcfe25aaa1" - integrity sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew== - -pify@^2.0.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" - integrity sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog== - -pify@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/pify/-/pify-4.0.1.tgz#4b2cd25c50d598735c50292224fd8c6df41e3231" - integrity sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g== - -pinkie-promise@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa" - integrity sha512-0Gni6D4UcLTbv9c57DfxDGdr41XfgUjqWZu492f0cIGr16zDU06BWP/RAEvOuo7CQ0CNjHaLlM59YJJFm3NWlw== - dependencies: - pinkie "^2.0.0" - -pinkie@^2.0.0: - version "2.0.4" - resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" - integrity sha512-MnUuEycAemtSaeFSjXKW/aroV7akBbY+Sv+RkyqFjgAe73F+MR0TBWKBRDkmfWq/HiFmdavfZ1G7h4SPZXaCSg== - -pkg-dir@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-3.0.0.tgz#2749020f239ed990881b1f71210d51eb6523bea3" - integrity sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw== - dependencies: - find-up "^3.0.0" - -pkg-dir@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" - integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ== - dependencies: - find-up "^4.0.0" - -portfinder@^1.0.26: - version "1.0.32" - resolved "https://registry.yarnpkg.com/portfinder/-/portfinder-1.0.32.tgz#2fe1b9e58389712429dc2bea5beb2146146c7f81" - integrity sha512-on2ZJVVDXRADWE6jnQaX0ioEylzgBpQk8r55NE4wjXW1ZxO+BgDlY6DXwj20i0V8eB4SenDQ00WEaxfiIQPcxg== - dependencies: - async "^2.6.4" - debug "^3.2.7" - mkdirp "^0.5.6" - -posix-character-classes@^0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" - integrity sha512-xTgYBc3fuo7Yt7JbiuFxSYGToMoz8fLoE6TC9Wx1P/u+LfeThMOAqmuyECnlBaaJb+u1m9hHiXUEtwW4OzfUJg== - -process-nextick-args@~2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" - integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== - -proxy-addr@~2.0.7: - version "2.0.7" - resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.7.tgz#f19fe69ceab311eeb94b42e70e8c2070f9ba1025" - integrity sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg== - dependencies: - forwarded "0.2.0" - ipaddr.js "1.9.1" - -prr@~1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476" - integrity sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw== - -pump@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64" - integrity sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww== - dependencies: - end-of-stream "^1.1.0" - once "^1.3.1" - -punycode@^1.4.1: - version "1.4.1" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" - integrity sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ== - -punycode@^2.1.0: - version "2.3.1" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5" - integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg== - -qs@6.11.0: - version "6.11.0" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.0.tgz#fd0d963446f7a65e1367e01abd85429453f0c37a" - integrity sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q== - dependencies: - side-channel "^1.0.4" - -qs@^6.12.3: - version "6.12.3" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.12.3.tgz#e43ce03c8521b9c7fd7f1f13e514e5ca37727754" - integrity sha512-AWJm14H1vVaO/iNZ4/hO+HyaTehuy9nRqVdkTqlJt0HWvBiBIEXFmb4C0DGeYo3Xes9rrEW+TxHsaigCbN5ICQ== - dependencies: - side-channel "^1.0.6" - -querystringify@^2.1.1: - version "2.2.0" - resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-2.2.0.tgz#3345941b4153cb9d082d8eee4cda2016a9aef7f6" - integrity sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ== - -randombytes@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" - integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== - dependencies: - safe-buffer "^5.1.0" - -range-parser@^1.2.1, range-parser@~1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" - integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== - -raw-body@2.5.2: - version "2.5.2" - resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.5.2.tgz#99febd83b90e08975087e8f1f9419a149366b68a" - integrity sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA== - dependencies: - bytes "3.1.2" - http-errors "2.0.0" - iconv-lite "0.4.24" - unpipe "1.0.0" - -readable-stream@^2.0.1, readable-stream@^2.0.2: - version "2.3.8" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.8.tgz#91125e8042bba1b9887f49345f6277027ce8be9b" - integrity sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA== - dependencies: - core-util-is "~1.0.0" - inherits "~2.0.3" - isarray "~1.0.0" - process-nextick-args "~2.0.0" - safe-buffer "~5.1.1" - string_decoder "~1.1.1" - util-deprecate "~1.0.1" - -readable-stream@^3.0.6: - version "3.6.2" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967" - integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== - dependencies: - inherits "^2.0.3" - string_decoder "^1.1.1" - util-deprecate "^1.0.1" - -readdirp@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-2.2.1.tgz#0e87622a3325aa33e892285caf8b4e846529a525" - integrity sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ== - dependencies: - graceful-fs "^4.1.11" - micromatch "^3.1.10" - readable-stream "^2.0.2" - -rechoir@^0.7.0: - version "0.7.1" - resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.7.1.tgz#9478a96a1ca135b5e88fc027f03ee92d6c645686" - integrity sha512-/njmZ8s1wVeR6pjTZ+0nCnv8SpZNRMT2D1RLOJQESlYFDBvwpTA4KWJpZ+sBJ4+vhjILRcK7JIFdGCdxEAAitg== - dependencies: - resolve "^1.9.0" - -regex-not@^1.0.0, regex-not@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/regex-not/-/regex-not-1.0.2.tgz#1f4ece27e00b0b65e0247a6810e6a85d83a5752c" - integrity sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A== - dependencies: - extend-shallow "^3.0.2" - safe-regex "^1.1.0" - -regexp.prototype.flags@^1.5.1: - version "1.5.2" - resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz#138f644a3350f981a858c44f6bb1a61ff59be334" - integrity sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw== - dependencies: - call-bind "^1.0.6" - define-properties "^1.2.1" - es-errors "^1.3.0" - set-function-name "^2.0.1" - -remove-trailing-separator@^1.0.1: - version "1.1.0" - resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" - integrity sha512-/hS+Y0u3aOfIETiaiirUFwDBDzmXPvO+jAfKTitUngIPzdKc6Z0LoFjM/CK5PL4C+eKwHohlHAb6H0VFfmmUsw== - -repeat-element@^1.1.2: - version "1.1.4" - resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.4.tgz#be681520847ab58c7568ac75fbfad28ed42d39e9" - integrity sha512-LFiNfRcSu7KK3evMyYOuCzv3L10TW7yC1G2/+StMjK8Y6Vqd2MG7r/Qjw4ghtuCOjFvlnms/iMmLqpvW/ES/WQ== - -repeat-string@^1.6.1: - version "1.6.1" - resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" - integrity sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w== - -require-directory@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" - integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== - -require-main-filename@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b" - integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg== - -requires-port@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" - integrity sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ== - -resolve-cwd@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-2.0.0.tgz#00a9f7387556e27038eae232caa372a6a59b665a" - integrity sha512-ccu8zQTrzVr954472aUVPLEcB3YpKSYR3cg/3lo1okzobPBM+1INXBbBZlDbnI/hbEocnf8j0QVo43hQKrbchg== - dependencies: - resolve-from "^3.0.0" - -resolve-cwd@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-3.0.0.tgz#0f0075f1bb2544766cf73ba6a6e2adfebcb13f2d" - integrity sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg== - dependencies: - resolve-from "^5.0.0" - -resolve-from@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-3.0.0.tgz#b22c7af7d9d6881bc8b6e653335eebcb0a188748" - integrity sha512-GnlH6vxLymXJNMBo7XP1fJIzBFbdYt49CuTwmB/6N53t+kMPRMFKz783LlQ4tv28XoQfMWinAJX6WCGf2IlaIw== - -resolve-from@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" - integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== - -resolve-url@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" - integrity sha512-ZuF55hVUQaaczgOIwqWzkEcEidmlD/xl44x1UZnhOXcYuFN2S6+rcxpG+C1N3So0wvNI3DmJICUFfu2SxhBmvg== - -resolve@^1.9.0: - version "1.22.8" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.8.tgz#b6c87a9f2aa06dfab52e3d70ac8cde321fa5a48d" - integrity sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw== - dependencies: - is-core-module "^2.13.0" - path-parse "^1.0.7" - supports-preserve-symlinks-flag "^1.0.0" - -ret@~0.1.10: - version "0.1.15" - resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" - integrity sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg== - -retry@^0.12.0: - version "0.12.0" - resolved "https://registry.yarnpkg.com/retry/-/retry-0.12.0.tgz#1b42a6266a21f07421d1b0b54b7dc167b01c013b" - integrity sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow== - -rimraf@^2.6.3: - version "2.7.1" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" - integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== - dependencies: - glob "^7.1.3" - -safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: - version "5.1.2" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" - integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== - -safe-buffer@5.2.1, safe-buffer@>=5.1.0, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@~5.2.0: - version "5.2.1" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" - integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== - -safe-regex@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/safe-regex/-/safe-regex-1.1.0.tgz#40a3669f3b077d1e943d44629e157dd48023bf2e" - integrity sha512-aJXcif4xnaNUzvUuC5gcb46oTS7zvg4jpMTnuqtrEPlR3vFr4pxtdTwaF1Qs3Enjn9HK+ZlwQui+a7z0SywIzg== - dependencies: - ret "~0.1.10" - -"safer-buffer@>= 2.1.2 < 3", "safer-buffer@>= 2.1.2 < 3.0.0": - version "2.1.2" - resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" - integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== - -schema-utils@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-1.0.0.tgz#0b79a93204d7b600d4b2850d1f66c2a34951c770" - integrity sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g== - dependencies: - ajv "^6.1.0" - ajv-errors "^1.0.0" - ajv-keywords "^3.1.0" - -schema-utils@^3.0.0, schema-utils@^3.1.1: - version "3.3.0" - resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-3.3.0.tgz#f50a88877c3c01652a15b622ae9e9795df7a60fe" - integrity sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg== - dependencies: - "@types/json-schema" "^7.0.8" - ajv "^6.12.5" - ajv-keywords "^3.5.2" - -select-hose@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/select-hose/-/select-hose-2.0.0.tgz#625d8658f865af43ec962bfc376a37359a4994ca" - integrity sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg== - -selfsigned@^1.10.8: - version "1.10.14" - resolved "https://registry.yarnpkg.com/selfsigned/-/selfsigned-1.10.14.tgz#ee51d84d9dcecc61e07e4aba34f229ab525c1574" - integrity sha512-lkjaiAye+wBZDCBsu5BGi0XiLRxeUlsGod5ZP924CRSEoGuZAw/f7y9RKu28rwTfiHVhdavhB0qH0INV6P1lEA== - dependencies: - node-forge "^0.10.0" - -semver@^5.5.0: - version "5.7.2" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8" - integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g== - -semver@^6.3.0: - version "6.3.1" - resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" - integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== - -send@0.18.0: - version "0.18.0" - resolved "https://registry.yarnpkg.com/send/-/send-0.18.0.tgz#670167cc654b05f5aa4a767f9113bb371bc706be" - integrity sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg== - dependencies: - debug "2.6.9" - depd "2.0.0" - destroy "1.2.0" - encodeurl "~1.0.2" - escape-html "~1.0.3" - etag "~1.8.1" - fresh "0.5.2" - http-errors "2.0.0" - mime "1.6.0" - ms "2.1.3" - on-finished "2.4.1" - range-parser "~1.2.1" - statuses "2.0.1" - -serialize-javascript@^6.0.1: - version "6.0.2" - resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.2.tgz#defa1e055c83bf6d59ea805d8da862254eb6a6c2" - integrity sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g== - dependencies: - randombytes "^2.1.0" - -serve-index@^1.9.1: - version "1.9.1" - resolved "https://registry.yarnpkg.com/serve-index/-/serve-index-1.9.1.tgz#d3768d69b1e7d82e5ce050fff5b453bea12a9239" - integrity sha512-pXHfKNP4qujrtteMrSBb0rc8HJ9Ms/GrXwcUtUtD5s4ewDJI8bT3Cz2zTVRMKtri49pLx2e0Ya8ziP5Ya2pZZw== - dependencies: - accepts "~1.3.4" - batch "0.6.1" - debug "2.6.9" - escape-html "~1.0.3" - http-errors "~1.6.2" - mime-types "~2.1.17" - parseurl "~1.3.2" - -serve-static@1.15.0: - version "1.15.0" - resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.15.0.tgz#faaef08cffe0a1a62f60cad0c4e513cff0ac9540" - integrity sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g== - dependencies: - encodeurl "~1.0.2" - escape-html "~1.0.3" - parseurl "~1.3.3" - send "0.18.0" - -set-blocking@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" - integrity sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw== - -set-function-length@^1.2.1: - version "1.2.2" - resolved "https://registry.yarnpkg.com/set-function-length/-/set-function-length-1.2.2.tgz#aac72314198eaed975cf77b2c3b6b880695e5449" - integrity sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg== - dependencies: - define-data-property "^1.1.4" - es-errors "^1.3.0" - function-bind "^1.1.2" - get-intrinsic "^1.2.4" - gopd "^1.0.1" - has-property-descriptors "^1.0.2" - -set-function-name@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/set-function-name/-/set-function-name-2.0.2.tgz#16a705c5a0dc2f5e638ca96d8a8cd4e1c2b90985" - integrity sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ== - dependencies: - define-data-property "^1.1.4" - es-errors "^1.3.0" - functions-have-names "^1.2.3" - has-property-descriptors "^1.0.2" - -set-value@^2.0.0, set-value@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/set-value/-/set-value-2.0.1.tgz#a18d40530e6f07de4228c7defe4227af8cad005b" - integrity sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw== - dependencies: - extend-shallow "^2.0.1" - is-extendable "^0.1.1" - is-plain-object "^2.0.3" - split-string "^3.0.1" - -setprototypeof@1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.0.tgz#d0bd85536887b6fe7c0d818cb962d9d91c54e656" - integrity sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ== - -setprototypeof@1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424" - integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw== - -shallow-clone@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/shallow-clone/-/shallow-clone-3.0.1.tgz#8f2981ad92531f55035b01fb230769a40e02efa3" - integrity sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA== - dependencies: - kind-of "^6.0.2" - -shebang-command@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" - integrity sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg== - dependencies: - shebang-regex "^1.0.0" - -shebang-command@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" - integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== - dependencies: - shebang-regex "^3.0.0" - -shebang-regex@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" - integrity sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ== - -shebang-regex@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" - integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== - -side-channel@^1.0.4, side-channel@^1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.6.tgz#abd25fb7cd24baf45466406b1096b7831c9215f2" - integrity sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA== - dependencies: - call-bind "^1.0.7" - es-errors "^1.3.0" - get-intrinsic "^1.2.4" - object-inspect "^1.13.1" - -sigmajs-crypto-facade@0.0.7: - version "0.0.7" - resolved "https://registry.yarnpkg.com/sigmajs-crypto-facade/-/sigmajs-crypto-facade-0.0.7.tgz#b81dd53750c38a6a7856153aad2705269bc5afb6" - integrity sha512-4XK8ZS9NKAbo8aGnU6o5GkBW6Upl8+OK8A1KreVDMAamfvZ0iq4LoVH8rHaeEPf9moVtaC4QZY5RYI+0OwiydA== - dependencies: - "@noble/hashes" "^1.1.4" - -signal-exit@^3.0.0, signal-exit@^3.0.3: - version "3.0.7" - resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" - integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== - -snapdragon-node@^2.0.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/snapdragon-node/-/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b" - integrity sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw== - dependencies: - define-property "^1.0.0" - isobject "^3.0.0" - snapdragon-util "^3.0.1" - -snapdragon-util@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/snapdragon-util/-/snapdragon-util-3.0.1.tgz#f956479486f2acd79700693f6f7b805e45ab56e2" - integrity sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ== - dependencies: - kind-of "^3.2.0" - -snapdragon@^0.8.1: - version "0.8.2" - resolved "https://registry.yarnpkg.com/snapdragon/-/snapdragon-0.8.2.tgz#64922e7c565b0e14204ba1aa7d6964278d25182d" - integrity sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg== - dependencies: - base "^0.11.1" - debug "^2.2.0" - define-property "^0.2.5" - extend-shallow "^2.0.1" - map-cache "^0.2.2" - source-map "^0.5.6" - source-map-resolve "^0.5.0" - use "^3.1.0" - -sockjs-client@^1.5.0: - version "1.6.1" - resolved "https://registry.yarnpkg.com/sockjs-client/-/sockjs-client-1.6.1.tgz#350b8eda42d6d52ddc030c39943364c11dcad806" - integrity sha512-2g0tjOR+fRs0amxENLi/q5TiJTqY+WXFOzb5UwXndlK6TO3U/mirZznpx6w34HVMoc3g7cY24yC/ZMIYnDlfkw== - dependencies: - debug "^3.2.7" - eventsource "^2.0.2" - faye-websocket "^0.11.4" - inherits "^2.0.4" - url-parse "^1.5.10" - -sockjs@^0.3.21: - version "0.3.24" - resolved "https://registry.yarnpkg.com/sockjs/-/sockjs-0.3.24.tgz#c9bc8995f33a111bea0395ec30aa3206bdb5ccce" - integrity sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ== - dependencies: - faye-websocket "^0.11.3" - uuid "^8.3.2" - websocket-driver "^0.7.4" - -source-list-map@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-2.0.1.tgz#3993bd873bfc48479cca9ea3a547835c7c154b34" - integrity sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw== - -source-map-loader@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/source-map-loader/-/source-map-loader-2.0.0.tgz#6651dc5a46beb2b914abacd00b8f9dd0e7757820" - integrity sha512-DJLK+gR9hlx+58yGU54EDAQZzR/TksgrtvRtyEBWnd5DR7O4n0RgdyO/KBwJ76zF+wDiFRT/1vdV3SdLUR68Lg== - dependencies: - abab "^2.0.5" - iconv-lite "^0.6.2" - source-map "^0.6.1" - -source-map-resolve@^0.5.0: - version "0.5.3" - resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.3.tgz#190866bece7553e1f8f267a2ee82c606b5509a1a" - integrity sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw== - dependencies: - atob "^2.1.2" - decode-uri-component "^0.2.0" - resolve-url "^0.2.1" - source-map-url "^0.4.0" - urix "^0.1.0" - -source-map-support@~0.5.20: - version "0.5.21" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" - integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w== - dependencies: - buffer-from "^1.0.0" - source-map "^0.6.0" - -source-map-url@^0.4.0: - version "0.4.1" - resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.1.tgz#0af66605a745a5a2f91cf1bbf8a7afbc283dec56" - integrity sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw== - -source-map@^0.5.6: - version "0.5.7" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" - integrity sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ== - -source-map@^0.6.0, source-map@^0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" - integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== - -spdy-transport@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/spdy-transport/-/spdy-transport-3.0.0.tgz#00d4863a6400ad75df93361a1608605e5dcdcf31" - integrity sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw== - dependencies: - debug "^4.1.0" - detect-node "^2.0.4" - hpack.js "^2.1.6" - obuf "^1.1.2" - readable-stream "^3.0.6" - wbuf "^1.7.3" - -spdy@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/spdy/-/spdy-4.0.2.tgz#b74f466203a3eda452c02492b91fb9e84a27677b" - integrity sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA== - dependencies: - debug "^4.1.0" - handle-thing "^2.0.0" - http-deceiver "^1.2.7" - select-hose "^2.0.0" - spdy-transport "^3.0.0" - -split-string@^3.0.1, split-string@^3.0.2: - version "3.1.0" - resolved "https://registry.yarnpkg.com/split-string/-/split-string-3.1.0.tgz#7cb09dda3a86585705c64b39a6466038682e8fe2" - integrity sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw== - dependencies: - extend-shallow "^3.0.0" - -static-extend@^0.1.1: - version "0.1.2" - resolved "https://registry.yarnpkg.com/static-extend/-/static-extend-0.1.2.tgz#60809c39cbff55337226fd5e0b520f341f1fb5c6" - integrity sha512-72E9+uLc27Mt718pMHt9VMNiAL4LMsmDbBva8mxWUCkT07fSzEGMYUCk0XWY6lp0j6RBAG4cJ3mWuZv2OE3s0g== - dependencies: - define-property "^0.2.5" - object-copy "^0.1.0" - -statuses@2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63" - integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ== - -"statuses@>= 1.4.0 < 2": - version "1.5.0" - resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" - integrity sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA== - -string-width@^3.0.0, string-width@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961" - integrity sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w== - dependencies: - emoji-regex "^7.0.1" - is-fullwidth-code-point "^2.0.0" - strip-ansi "^5.1.0" - -string_decoder@^1.1.1: - version "1.3.0" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" - integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== - dependencies: - safe-buffer "~5.2.0" - -string_decoder@~1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" - integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== - dependencies: - safe-buffer "~5.1.0" - -strip-ansi@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" - integrity sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg== - dependencies: - ansi-regex "^2.0.0" - -strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae" - integrity sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA== - dependencies: - ansi-regex "^4.1.0" - -strip-ansi@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" - integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== - dependencies: - ansi-regex "^5.0.1" - -strip-eof@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" - integrity sha512-7FCwGGmx8mD5xQd3RPUvnSpUXHM3BWuzjtpD4TXsfcZ9EL4azvVVUscFYwD9nx8Kh+uCBC00XBtAykoMHwTh8Q== - -strip-final-newline@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad" - integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA== - -supports-color@^6.1.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-6.1.0.tgz#0764abc69c63d5ac842dd4867e8d025e880df8f3" - integrity sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ== - dependencies: - has-flag "^3.0.0" - -supports-color@^8.0.0: - version "8.1.1" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" - integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== - dependencies: - has-flag "^4.0.0" - -supports-preserve-symlinks-flag@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" - integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== - -tapable@^2.1.1, tapable@^2.2.0: - version "2.2.1" - resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.1.tgz#1967a73ef4060a82f12ab96af86d52fdb76eeca0" - integrity sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ== - -terser-webpack-plugin@^5.1.1: - version "5.3.10" - resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-5.3.10.tgz#904f4c9193c6fd2a03f693a2150c62a92f40d199" - integrity sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w== - dependencies: - "@jridgewell/trace-mapping" "^0.3.20" - jest-worker "^27.4.5" - schema-utils "^3.1.1" - serialize-javascript "^6.0.1" - terser "^5.26.0" - -terser@^5.26.0: - version "5.31.3" - resolved "https://registry.yarnpkg.com/terser/-/terser-5.31.3.tgz#b24b7beb46062f4653f049eea4f0cd165d0f0c38" - integrity sha512-pAfYn3NIZLyZpa83ZKigvj6Rn9c/vd5KfYGX7cN1mnzqgDcxWvrU5ZtAfIKhEXz9nRecw4z3LXkjaq96/qZqAA== - dependencies: - "@jridgewell/source-map" "^0.3.3" - acorn "^8.8.2" - commander "^2.20.0" - source-map-support "~0.5.20" - -thunky@^1.0.2: - version "1.1.0" - resolved "https://registry.yarnpkg.com/thunky/-/thunky-1.1.0.tgz#5abaf714a9405db0504732bbccd2cedd9ef9537d" - integrity sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA== - -to-object-path@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/to-object-path/-/to-object-path-0.3.0.tgz#297588b7b0e7e0ac08e04e672f85c1f4999e17af" - integrity sha512-9mWHdnGRuh3onocaHzukyvCZhzvr6tiflAy/JRFXcJX0TjgfWA9pk9t8CMbzmBE4Jfw58pXbkngtBtqYxzNEyg== - dependencies: - kind-of "^3.0.2" - -to-regex-range@^2.1.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-2.1.1.tgz#7c80c17b9dfebe599e27367e0d4dd5590141db38" - integrity sha512-ZZWNfCjUokXXDGXFpZehJIkZqq91BcULFq/Pi7M5i4JnxXdhMKAK682z8bCW3o8Hj1wuuzoKcW3DfVzaP6VuNg== - dependencies: - is-number "^3.0.0" - repeat-string "^1.6.1" - -to-regex@^3.0.1, to-regex@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/to-regex/-/to-regex-3.0.2.tgz#13cfdd9b336552f30b51f33a8ae1b42a7a7599ce" - integrity sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw== - dependencies: - define-property "^2.0.2" - extend-shallow "^3.0.2" - regex-not "^1.0.2" - safe-regex "^1.1.0" - -toidentifier@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" - integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA== - -type-is@~1.6.18: - version "1.6.18" - resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" - integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g== - dependencies: - media-typer "0.3.0" - mime-types "~2.1.24" - -undici-types@~6.11.1: - version "6.11.1" - resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.11.1.tgz#432ea6e8efd54a48569705a699e62d8f4981b197" - integrity sha512-mIDEX2ek50x0OlRgxryxsenE5XaQD4on5U2inY7RApK3SOJpofyw7uW2AyfMKkhAxXIceo2DeWGVGwyvng1GNQ== - -union-value@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.1.tgz#0b6fe7b835aecda61c6ea4d4f02c14221e109847" - integrity sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg== - dependencies: - arr-union "^3.1.0" - get-value "^2.0.6" - is-extendable "^0.1.1" - set-value "^2.0.1" - -unpipe@1.0.0, unpipe@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" - integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== - -unset-value@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-1.0.0.tgz#8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559" - integrity sha512-PcA2tsuGSF9cnySLHTLSh2qrQiJ70mn+r+Glzxv2TWZblxsxCC52BDlZoPCsz7STd9pN7EZetkWZBAvk4cgZdQ== - dependencies: - has-value "^0.3.1" - isobject "^3.0.0" - -upath@^1.1.1: - version "1.2.0" - resolved "https://registry.yarnpkg.com/upath/-/upath-1.2.0.tgz#8f66dbcd55a883acdae4408af8b035a5044c1894" - integrity sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg== - -update-browserslist-db@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.1.0.tgz#7ca61c0d8650766090728046e416a8cde682859e" - integrity sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ== - dependencies: - escalade "^3.1.2" - picocolors "^1.0.1" - -uri-js@^4.2.2: - version "4.4.1" - resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" - integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== - dependencies: - punycode "^2.1.0" - -urix@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72" - integrity sha512-Am1ousAhSLBeB9cG/7k7r2R0zj50uDRlZHPGbazid5s9rlF1F/QKYObEKSIunSjIOkJZqwRRLpvewjEkM7pSqg== - -url-parse@^1.5.10: - version "1.5.10" - resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.5.10.tgz#9d3c2f736c1d75dd3bd2be507dcc111f1e2ea9c1" - integrity sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ== - dependencies: - querystringify "^2.1.1" - requires-port "^1.0.0" - -url@^0.11.0: - version "0.11.4" - resolved "https://registry.yarnpkg.com/url/-/url-0.11.4.tgz#adca77b3562d56b72746e76b330b7f27b6721f3c" - integrity sha512-oCwdVC7mTuWiPyjLUz/COz5TLk6wgp0RCsN+wHZ2Ekneac9w8uuV0njcbbie2ME+Vs+d6duwmYuR3HgQXs1fOg== - dependencies: - punycode "^1.4.1" - qs "^6.12.3" - -use@^3.1.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f" - integrity sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ== - -util-deprecate@^1.0.1, util-deprecate@~1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" - integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== - -utils-merge@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" - integrity sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA== - -uuid@^3.3.2: - version "3.4.0" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" - integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== - -uuid@^8.3.2: - version "8.3.2" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" - integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== - -v8-compile-cache@^2.2.0: - version "2.4.0" - resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.4.0.tgz#cdada8bec61e15865f05d097c5f4fd30e94dc128" - integrity sha512-ocyWc3bAHBB/guyqJQVI5o4BZkPhznPYUG2ea80Gond/BgNWpap8TOmLSeeQG7bnh2KMISxskdADG59j7zruhw== - -vary@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" - integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg== - -watchpack@^2.0.0: - version "2.4.1" - resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.4.1.tgz#29308f2cac150fa8e4c92f90e0ec954a9fed7fff" - integrity sha512-8wrBCMtVhqcXP2Sup1ctSkga6uc2Bx0IIvKyT7yTFier5AXHooSI+QyQQAtTb7+E0IUCCKyTFmXqdqgum2XWGg== - dependencies: - glob-to-regexp "^0.4.1" - graceful-fs "^4.1.2" - -wbuf@^1.1.0, wbuf@^1.7.3: - version "1.7.3" - resolved "https://registry.yarnpkg.com/wbuf/-/wbuf-1.7.3.tgz#c1d8d149316d3ea852848895cb6a0bfe887b87df" - integrity sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA== - dependencies: - minimalistic-assert "^1.0.0" - -webpack-cli@4.5.0: - version "4.5.0" - resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-4.5.0.tgz#b5213b84adf6e1f5de6391334c9fa53a48850466" - integrity sha512-wXg/ef6Ibstl2f50mnkcHblRPN/P9J4Nlod5Hg9HGFgSeF8rsqDGHJeVe4aR26q9l62TUJi6vmvC2Qz96YJw1Q== - dependencies: - "@discoveryjs/json-ext" "^0.5.0" - "@webpack-cli/configtest" "^1.0.1" - "@webpack-cli/info" "^1.2.2" - "@webpack-cli/serve" "^1.3.0" - colorette "^1.2.1" - commander "^7.0.0" - enquirer "^2.3.6" - execa "^5.0.0" - fastest-levenshtein "^1.0.12" - import-local "^3.0.2" - interpret "^2.2.0" - rechoir "^0.7.0" - v8-compile-cache "^2.2.0" - webpack-merge "^5.7.3" - -webpack-dev-middleware@^3.7.2: - version "3.7.3" - resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-3.7.3.tgz#0639372b143262e2b84ab95d3b91a7597061c2c5" - integrity sha512-djelc/zGiz9nZj/U7PTBi2ViorGJXEWo/3ltkPbDyxCXhhEXkW0ce99falaok4TPj+AsxLiXJR0EBOb0zh9fKQ== - dependencies: - memory-fs "^0.4.1" - mime "^2.4.4" - mkdirp "^0.5.1" - range-parser "^1.2.1" - webpack-log "^2.0.0" - -webpack-dev-server@3.11.2: - version "3.11.2" - resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-3.11.2.tgz#695ebced76a4929f0d5de7fd73fafe185fe33708" - integrity sha512-A80BkuHRQfCiNtGBS1EMf2ChTUs0x+B3wGDFmOeT4rmJOHhHTCH2naNxIHhmkr0/UillP4U3yeIyv1pNp+QDLQ== - dependencies: - ansi-html "0.0.7" - bonjour "^3.5.0" - chokidar "^2.1.8" - compression "^1.7.4" - connect-history-api-fallback "^1.6.0" - debug "^4.1.1" - del "^4.1.1" - express "^4.17.1" - html-entities "^1.3.1" - http-proxy-middleware "0.19.1" - import-local "^2.0.0" - internal-ip "^4.3.0" - ip "^1.1.5" - is-absolute-url "^3.0.3" - killable "^1.0.1" - loglevel "^1.6.8" - opn "^5.5.0" - p-retry "^3.0.1" - portfinder "^1.0.26" - schema-utils "^1.0.0" - selfsigned "^1.10.8" - semver "^6.3.0" - serve-index "^1.9.1" - sockjs "^0.3.21" - sockjs-client "^1.5.0" - spdy "^4.0.2" - strip-ansi "^3.0.1" - supports-color "^6.1.0" - url "^0.11.0" - webpack-dev-middleware "^3.7.2" - webpack-log "^2.0.0" - ws "^6.2.1" - yargs "^13.3.2" - -webpack-log@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/webpack-log/-/webpack-log-2.0.0.tgz#5b7928e0637593f119d32f6227c1e0ac31e1b47f" - integrity sha512-cX8G2vR/85UYG59FgkoMamwHUIkSSlV3bBMRsbxVXVUk2j6NleCKjQ/WE9eYg9WY4w25O9w8wKP4rzNZFmUcUg== - dependencies: - ansi-colors "^3.0.0" - uuid "^3.3.2" - -webpack-merge@^5.7.3: - version "5.10.0" - resolved "https://registry.yarnpkg.com/webpack-merge/-/webpack-merge-5.10.0.tgz#a3ad5d773241e9c682803abf628d4cd62b8a4177" - integrity sha512-+4zXKdx7UnO+1jaN4l2lHVD+mFvnlZQP/6ljaJVb4SZiwIKeUnrT5l0gkT8z+n4hKpC+jpOv6O9R+gLtag7pSA== - dependencies: - clone-deep "^4.0.1" - flat "^5.0.2" - wildcard "^2.0.0" - -webpack-sources@^2.1.1: - version "2.3.1" - resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-2.3.1.tgz#570de0af163949fe272233c2cefe1b56f74511fd" - integrity sha512-y9EI9AO42JjEcrTJFOYmVywVZdKVUfOvDUPsJea5GIr1JOEGFVqwlY2K098fFoIjOkDzHn2AjRvM8dsBZu+gCA== - dependencies: - source-list-map "^2.0.1" - source-map "^0.6.1" - -webpack@5.24.3: - version "5.24.3" - resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.24.3.tgz#6ec0f5059f8d7c7961075fa553cfce7b7928acb3" - integrity sha512-x7lrWZ7wlWAdyKdML6YPvfVZkhD1ICuIZGODE5SzKJjqI9A4SpqGTjGJTc6CwaHqn19gGaoOR3ONJ46nYsn9rw== - dependencies: - "@types/eslint-scope" "^3.7.0" - "@types/estree" "^0.0.46" - "@webassemblyjs/ast" "1.11.0" - "@webassemblyjs/wasm-edit" "1.11.0" - "@webassemblyjs/wasm-parser" "1.11.0" - acorn "^8.0.4" - browserslist "^4.14.5" - chrome-trace-event "^1.0.2" - enhanced-resolve "^5.7.0" - es-module-lexer "^0.4.0" - eslint-scope "^5.1.1" - events "^3.2.0" - glob-to-regexp "^0.4.1" - graceful-fs "^4.2.4" - json-parse-better-errors "^1.0.2" - loader-runner "^4.2.0" - mime-types "^2.1.27" - neo-async "^2.6.2" - schema-utils "^3.0.0" - tapable "^2.1.1" - terser-webpack-plugin "^5.1.1" - watchpack "^2.0.0" - webpack-sources "^2.1.1" - -websocket-driver@>=0.5.1, websocket-driver@^0.7.4: - version "0.7.4" - resolved "https://registry.yarnpkg.com/websocket-driver/-/websocket-driver-0.7.4.tgz#89ad5295bbf64b480abcba31e4953aca706f5760" - integrity sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg== - dependencies: - http-parser-js ">=0.5.1" - safe-buffer ">=5.1.0" - websocket-extensions ">=0.1.1" - -websocket-extensions@>=0.1.1: - version "0.1.4" - resolved "https://registry.yarnpkg.com/websocket-extensions/-/websocket-extensions-0.1.4.tgz#7f8473bc839dfd87608adb95d7eb075211578a42" - integrity sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg== - -which-module@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.1.tgz#776b1fe35d90aebe99e8ac15eb24093389a4a409" - integrity sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ== - -which@^1.2.9: - version "1.3.1" - resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" - integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== - dependencies: - isexe "^2.0.0" - -which@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" - integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== - dependencies: - isexe "^2.0.0" - -wildcard@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/wildcard/-/wildcard-2.0.1.tgz#5ab10d02487198954836b6349f74fff961e10f67" - integrity sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ== - -wrap-ansi@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-5.1.0.tgz#1fd1f67235d5b6d0fee781056001bfb694c03b09" - integrity sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q== - dependencies: - ansi-styles "^3.2.0" - string-width "^3.0.0" - strip-ansi "^5.0.0" - -wrappy@1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" - integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== - -ws@^6.2.1: - version "6.2.3" - resolved "https://registry.yarnpkg.com/ws/-/ws-6.2.3.tgz#ccc96e4add5fd6fedbc491903075c85c5a11d9ee" - integrity sha512-jmTjYU0j60B+vHey6TfR3Z7RD61z/hmxBS3VMSGIrroOWXQEneK1zNuotOUrGyBHQj0yrpsLHPWtigEFd13ndA== - dependencies: - async-limiter "~1.0.0" - -y18n@^4.0.0: - version "4.0.3" - resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.3.tgz#b5f259c82cd6e336921efd7bfd8bf560de9eeedf" - integrity sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ== - -yargs-parser@^13.1.2: - version "13.1.2" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.1.2.tgz#130f09702ebaeef2650d54ce6e3e5706f7a4fb38" - integrity sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg== - dependencies: - camelcase "^5.0.0" - decamelize "^1.2.0" - -yargs@^13.3.2: - version "13.3.2" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.3.2.tgz#ad7ffefec1aa59565ac915f82dccb38a9c31a2dd" - integrity sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw== - dependencies: - cliui "^5.0.0" - find-up "^3.0.0" - get-caller-file "^2.0.1" - require-directory "^2.1.1" - require-main-filename "^2.0.0" - set-blocking "^2.0.0" - string-width "^3.0.0" - which-module "^2.0.0" - y18n "^4.0.0" - yargs-parser "^13.1.2" From 04f6feea44c6c40b9d067828fd0823e01468eb5a Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Mon, 5 Aug 2024 00:01:45 +0300 Subject: [PATCH 203/314] test for substConstants with 5 elems --- .../utxo/BasicOpsSpecification.scala | 45 +++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala index 79701d6e07..b2414d36da 100644 --- a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala @@ -2,6 +2,7 @@ package sigmastate.utxo import org.ergoplatform.ErgoBox.{AdditionalRegisters, R6, R8} import org.ergoplatform._ +import scorex.util.encode.Base16 import sigma.Extensions.ArrayOps import sigma.ast.SCollection.SByteArray import sigma.ast.SType.AnyOps @@ -19,9 +20,11 @@ import sigmastate.interpreter.Interpreter._ import sigma.ast.Apply import sigma.eval.EvalSettings import sigma.exceptions.InvalidType +import sigma.serialization.ErgoTreeSerializer import sigmastate.utils.Helpers._ import java.math.BigInteger +import scala.reflect.internal.pickling.PickleFormat class BasicOpsSpecification extends CompilerTestingCommons with CompilerCrossVersionProps { @@ -721,4 +724,46 @@ class BasicOpsSpecification extends CompilerTestingCommons true ) } + + property("substConstants") { + val initTreeScript = + """ + | { + | val v1 = 1 // 0 + | val v2 = 2 // 2 + | val v3 = 3 // 4 + | val v4 = 4 // 3 + | val v5 = 5 // 1 + | sigmaProp(v1 == -v5 && v2 == -v4 && v3 == v2 + v4) + | } + |""".stripMargin + + val iet = ErgoTree.fromProposition(compile(Map.empty, initTreeScript).asInstanceOf[SigmaPropValue]) + + iet.constants.toArray shouldBe Array(IntConstant(1), IntConstant(5), IntConstant(2), IntConstant(4), IntConstant(3), IntConstant(6)) + + val originalBytes = Base16.encode(ErgoTreeSerializer.DefaultSerializer.serializeErgoTree(iet)) + + val set = ErgoTree( + iet.header, + IndexedSeq(IntConstant(-2), IntConstant(2), IntConstant(-1), IntConstant(1), IntConstant(0), IntConstant(0)), + iet.toProposition(false) + ) + + val hostScript = + s""" + |{ + | val bytes = fromBase16("${originalBytes}") + | + | val substBytes = substConstants[Int](bytes, Coll[Int](0, 2, 4, 3, 1, 5), Coll[Int](-2, -1, 0, 1, 2, 0)) + | + | val checkSubst = substBytes == fromBase16("${Base16.encode(ErgoTreeSerializer.DefaultSerializer.serializeErgoTree(set))}") + | + | sigmaProp(checkSubst) + |} + |""".stripMargin + + test("subst", env, ext, hostScript, null) + } + } From f851b62bda75794d2e049bcc2312372184044f80 Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Mon, 5 Aug 2024 16:04:36 +0300 Subject: [PATCH 204/314] LSV5 fix --- .../scala/sigma/LanguageSpecificationV5.scala | 786 +++++++++--------- 1 file changed, 393 insertions(+), 393 deletions(-) diff --git a/sc/shared/src/test/scala/sigma/LanguageSpecificationV5.scala b/sc/shared/src/test/scala/sigma/LanguageSpecificationV5.scala index 64b2890082..af4f93d861 100644 --- a/sc/shared/src/test/scala/sigma/LanguageSpecificationV5.scala +++ b/sc/shared/src/test/scala/sigma/LanguageSpecificationV5.scala @@ -135,7 +135,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => ) val newCost = 1768 - def success(b: Boolean) = Expected(Success(b), 1768, newDetails, newCost, 2010 +: Seq.fill(3)(2012)) + def success(b: Boolean) = Expected(Success(b), 1768, newDetails, newCost, Seq.fill(4)(2012)) val cases = Seq( (true, true) -> success(false), @@ -165,14 +165,14 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => val expectedCost = 1768 val newCost = 1768 val cases = Seq( - (true, true) -> Expected(Success(false), expectedCost, newDetails, newCost, 2010 +: Seq.fill(3)(2012)) + (true, true) -> Expected(Success(false), expectedCost, newDetails, newCost, Seq.fill(4)(2012)) ) verifyCases(cases, feature) val initCost = 100 initialCostInTests.withValue(initCost) { val cases = Seq( - (true, true) -> Expected(Success(false), expectedCost + initCost, newDetails, newCost + initCost, (2010 + initCost) +: Seq.fill(3)(2012 + initCost)) + (true, true) -> Expected(Success(false), expectedCost + initCost, newDetails, newCost + initCost, Seq.fill(4)(2012 + initCost)) ) verifyCases(cases, feature) } @@ -202,7 +202,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => ) ) - def success(b: Boolean) = Expected(Success(b), 1769, newDetails, 1769, 2025 +: Seq.fill(3)(2027)) + def success(b: Boolean) = Expected(Success(b), 1769, newDetails, 1769, Seq.fill(4)(2027)) val cases = Seq( (1095564593, true) -> success(true), @@ -240,10 +240,10 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => ) ) val cases = Seq( - (false, true) -> Expected(Success(false), 1766, newDetails1, 1766, 2008 +: Seq.fill(3)(2010)), - (false, false) -> Expected(Success(false), 1766, newDetails1, 1766, 2008 +: Seq.fill(3)(2010)), - (true, true) -> Expected(Success(true), 1768, newDetails2, 1768, 2010 +: Seq.fill(3)(2012)), - (true, false) -> Expected(Success(false), 1768, newDetails2, 1768, 2010 +: Seq.fill(3)(2012)) + (false, true) -> Expected(Success(false), 1766, newDetails1, 1766, Seq.fill(4)(2010)), + (false, false) -> Expected(Success(false), 1766, newDetails1, 1766, Seq.fill(4)(2010)), + (true, true) -> Expected(Success(true), 1768, newDetails2, 1768, Seq.fill(4)(2012)), + (true, false) -> Expected(Success(false), 1768, newDetails2, 1768, Seq.fill(4)(2012)) ) verifyCases(cases, eq) } @@ -273,10 +273,10 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => ) ) val cases = Seq( - (true, false) -> Expected(Success(true), 1766, newDetails1, 1766, 2008 +: Seq.fill(3)(2010)), - (true, true) -> Expected(Success(true), 1766, newDetails1, 1766, 2008 +: Seq.fill(3)(2010)), - (false, false) -> Expected(Success(false), 1768, newDetails2, 1768, 2010 +: Seq.fill(3)(2012)), - (false, true) -> Expected(Success(true), 1768, newDetails2, 1768, 2010 +: Seq.fill(3)(2012)) + (true, false) -> Expected(Success(true), 1766, newDetails1, 1766, Seq.fill(4)(2010)), + (true, true) -> Expected(Success(true), 1766, newDetails1, 1766, Seq.fill(4)(2010)), + (false, false) -> Expected(Success(false), 1768, newDetails2, 1768, Seq.fill(4)(2012)), + (false, true) -> Expected(Success(true), 1768, newDetails2, 1768, Seq.fill(4)(2012)) ) verifyCases(cases, eq) } @@ -321,7 +321,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => ) verifyCases( Seq( - (true, Expected(Success(true), 1765, newDetails1, 1765, 2023 +: Seq.fill(3)(2027))), + (true, Expected(Success(true), 1765, newDetails1, 1765, Seq.fill(4)(2027))), (false, Expected(new ArithmeticException("/ by zero"))) ), existingFeature((x: Boolean) => x || (1 / 0 == 1), @@ -337,7 +337,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( Seq( (true, Expected(new ArithmeticException("/ by zero"))), - (false, Expected(Success(false), 1765, newDetails2, 1765, 2023 +: Seq.fill(3)(2027))) + (false, Expected(Success(false), 1765, newDetails2, 1765, Seq.fill(4)(2027))) ), existingFeature((x: Boolean) => x && (1 / 0 == 1), "{ (x: Boolean) => x && (1 / 0 == 1) }", @@ -351,8 +351,8 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( Seq( - (false, Expected(Success(false), 1765, newDetails2, 1765, 2029 +: Seq.fill(3)(2033))), - (true, Expected(Success(true), 1768, newDetails3, 1768, 2032 +: Seq.fill(3)(2036))) + (false, Expected(Success(false), 1765, newDetails2, 1765, Seq.fill(4)(2033))), + (true, Expected(Success(true), 1768, newDetails3, 1768, Seq.fill(4)(2036))) ), existingFeature((x: Boolean) => x && (x || (1 / 0 == 1)), "{ (x: Boolean) => x && (x || (1 / 0 == 1)) }", @@ -369,8 +369,8 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( Seq( - (false, Expected(Success(false), 1765, newDetails2, 1765, 2035 +: Seq.fill(3)(2039))), - (true, Expected(Success(true), 1770, newDetails4, 1770, 2040 +: Seq.fill(3)(2044))) + (false, Expected(Success(false), 1765, newDetails2, 1765, Seq.fill(4)(2039))), + (true, Expected(Success(true), 1770, newDetails4, 1770, Seq.fill(4)(2044))) ), existingFeature((x: Boolean) => x && (x && (x || (1 / 0 == 1))), "{ (x: Boolean) => x && (x && (x || (1 / 0 == 1))) }", @@ -390,8 +390,8 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( Seq( - (false, Expected(Success(false), 1765, newDetails2, 1765, 2041 +: Seq.fill(3)(2045))), - (true, Expected(Success(true), 1773, newDetails5, 1773, 2049 +: Seq.fill(3)(2053))) + (false, Expected(Success(false), 1765, newDetails2, 1765, Seq.fill(4)(2045))), + (true, Expected(Success(true), 1773, newDetails5, 1773, Seq.fill(4)(2053))) ), existingFeature((x: Boolean) => x && (x && (x && (x || (1 / 0 == 1)))), "{ (x: Boolean) => x && (x && (x && (x || (1 / 0 == 1)))) }", @@ -425,7 +425,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( Seq( (false, Expected(new ArithmeticException("/ by zero"))), - (true, Expected(Success(true), 1773, newDetails6, 1773, 2071 +: Seq.fill(3)(2075))) + (true, Expected(Success(true), 1773, newDetails6, 1773, Seq.fill(4)(2075))) ), existingFeature((x: Boolean) => !(!x && (1 / 0 == 1)) && (x || (1 / 0 == 1)), "{ (x: Boolean) => !(!x && (1 / 0 == 1)) && (x || (1 / 0 == 1)) }", @@ -454,7 +454,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => ) verifyCases( Seq( - (true, Expected(Success(true), 1768, newDetails7, 1768, 2032 +: Seq.fill(3)(2036))), + (true, Expected(Success(true), 1768, newDetails7, 1768, Seq.fill(4)(2036))), (false, Expected(new ArithmeticException("/ by zero"))) ), existingFeature((x: Boolean) => (x || (1 / 0 == 1)) && x, @@ -480,7 +480,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => ) verifyCases( Seq( - (true, Expected(Success(true), 1770, newDetails8, 1770, 2064 +: Seq.fill(3)(2068))), + (true, Expected(Success(true), 1770, newDetails8, 1770, Seq.fill(4)(2068))), (false, Expected(new ArithmeticException("/ by zero"))) ), existingFeature((x: Boolean) => (x || (1 / 0 == 1)) && (x || (1 / 0 == 1)), @@ -512,7 +512,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => ) verifyCases( Seq( - (true, Expected(Success(true), 1775, newDetails9, 1775, 2103 +: Seq.fill(3)(2107))), + (true, Expected(Success(true), 1775, newDetails9, 1775, Seq.fill(4)(2107))), (false, Expected(new ArithmeticException("/ by zero"))) ), existingFeature( @@ -562,7 +562,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( Seq( (false, Expected(new ArithmeticException("/ by zero"))), - (true, Expected(Success(true), 1780, newDetails10, 1780, 2152 +: Seq.fill(3)(2156))) + (true, Expected(Success(true), 1780, newDetails10, 1780, Seq.fill(4)(2156))) ), existingFeature( (x: Boolean) => (!(!x && (1 / 0 == 1)) || (1 / 0 == 0)) && (!(!x && (1 / 0 == 1)) || (1 / 0 == 1)), @@ -605,7 +605,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( { - def expect(v: Byte) = Expected(Success(v), 1763, TracedCost(traceBase), 1763, 1991 +: Seq.fill(3)(1993)) + def expect(v: Byte) = Expected(Success(v), 1763, TracedCost(traceBase), 1763, Seq.fill(4)(1993)) Seq( (0.toByte, expect(0.toByte)), @@ -623,7 +623,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( { - def expected(v: Short) = Expected(Success(v), 1764, upcastCostDetails(SShort), 1764, 1996 +: Seq.fill(3)(1998)) + def expected(v: Short) = Expected(Success(v), 1764, upcastCostDetails(SShort), 1764, Seq.fill(4)(1998)) Seq( (0.toByte, expected(0.toShort)), @@ -641,7 +641,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( { - def expected(v: Int) = Expected(Success(v), 1764, upcastCostDetails(SInt), 1764, 1996 +: Seq.fill(3)(1998)) + def expected(v: Int) = Expected(Success(v), 1764, upcastCostDetails(SInt), 1764, Seq.fill(4)(1998)) Seq( (0.toByte, expected(0)), @@ -659,7 +659,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( { - def expected(v: Long) = Expected(Success(v), 1764, upcastCostDetails(SLong), 1764, 1996 +: Seq.fill(3)(1998)) + def expected(v: Long) = Expected(Success(v), 1764, upcastCostDetails(SLong), 1764, Seq.fill(4)(1998)) Seq( (0.toByte, expected(0L)), @@ -677,7 +677,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( { - def expected(v: BigInt) = Expected(Success(v), 1767, upcastCostDetails(SBigInt), 1767, 1999 +: Seq.fill(3)(2001)) + def expected(v: BigInt) = Expected(Success(v), 1767, upcastCostDetails(SBigInt), 1767, Seq.fill(4)(2001)) Seq( (0.toByte, expected(CBigInt(new BigInteger("0", 16)))), @@ -696,7 +696,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => val n = ExactIntegral.ByteIsExactIntegral verifyCases( { - def success[T](v: (T, (T, (T, (T, T))))) = Expected(Success(v), 1788, arithOpsCostDetails(SByte), 1788, 2112 +: Seq.fill(3)(2116)) + def success[T](v: (T, (T, (T, (T, T))))) = Expected(Success(v), 1788, arithOpsCostDetails(SByte), 1788, Seq.fill(4)(2116)) Seq( ((-128.toByte, -128.toByte), Expected(new ArithmeticException("Byte overflow"))), @@ -858,7 +858,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => property("Byte LT, GT, NEQ") { val o = ExactOrdering.ByteIsExactOrdering - def expect(v: Boolean) = Expected(Success(v), 1768, binaryRelationCostDetails(LT, SByte), 1768, 2010 +: Seq.fill(3)(2012)) + def expect(v: Boolean) = Expected(Success(v), 1768, binaryRelationCostDetails(LT, SByte), 1768, Seq.fill(4)(2012)) val LT_cases: Seq[((Byte, Byte), Expected[Boolean])] = Seq( (-128.toByte, -128.toByte) -> expect(false), @@ -900,17 +900,17 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyOp(LT_cases, "<", LT.apply)(_ < _) verifyOp( - swapArgs(LT_cases, cost = 1768, newCostDetails = binaryRelationCostDetails(GT, SByte), expectedV3Costs = 2010 +: Seq.fill(3)(2012)), + swapArgs(LT_cases, cost = 1768, newCostDetails = binaryRelationCostDetails(GT, SByte), expectedV3Costs = Seq.fill(4)(2012)), ">", GT.apply)(_ > _) - val neqCases = newCasesFrom3(LT_cases.map(_._1))(_ != _, cost = 1766, newCostDetails = costNEQ(constNeqCost), expectedV3Costs = 2008 +: Seq.fill(3)(2010)) + val neqCases = newCasesFrom3(LT_cases.map(_._1))(_ != _, cost = 1766, newCostDetails = costNEQ(constNeqCost), expectedV3Costs = Seq.fill(4)(2010)) verifyOp(neqCases, "!=", NEQ.apply)(_ != _) } property("Byte LE, GE") { val o = ExactOrdering.ByteIsExactOrdering - def expect(v: Boolean) = Expected(Success(v), 1768, binaryRelationCostDetails(LE, SByte), 1768, 2010 +: Seq.fill(3)(2012)) + def expect(v: Boolean) = Expected(Success(v), 1768, binaryRelationCostDetails(LE, SByte), 1768, Seq.fill(4)(2012)) val LE_cases: Seq[((Byte, Byte), Expected[Boolean])] = Seq( (-128.toByte, -128.toByte) -> expect(true), @@ -953,7 +953,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyOp(LE_cases, "<=", LE.apply)(_ <= _) verifyOp( - swapArgs(LE_cases, cost = 1768, newCostDetails = binaryRelationCostDetails(GE, SByte), expectedV3Costs = 2010 +: Seq.fill(3)(2012)), + swapArgs(LE_cases, cost = 1768, newCostDetails = binaryRelationCostDetails(GE, SByte), expectedV3Costs = Seq.fill(4)(2012)), ">=", GE.apply)(_ >= _) } property("Short methods equivalence") { @@ -962,7 +962,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( { - def success[T](v: T) = Expected(Success(v), 1764, downcastCostDetails(SByte), 1764, 1996 +: Seq.fill(3)(1998)) + def success[T](v: T) = Expected(Success(v), 1764, downcastCostDetails(SByte), 1764, Seq.fill(4)(1998)) Seq( (Short.MinValue, Expected(new ArithmeticException("Byte overflow"))), @@ -982,7 +982,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( { - def success[T](v: T) = Expected(Success(v), 1763, TracedCost(traceBase), 1763, 1991 +: Seq.fill(3)(1993)) + def success[T](v: T) = Expected(Success(v), 1763, TracedCost(traceBase), 1763, Seq.fill(4)(1993)) Seq( (-32768.toShort, success(-32768.toShort)), @@ -1000,7 +1000,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( { - def success[T](v: T) = Expected(Success(v), 1764, upcastCostDetails(SInt), 1764, 1996 +: Seq.fill(3)(1998)) + def success[T](v: T) = Expected(Success(v), 1764, upcastCostDetails(SInt), 1764, Seq.fill(4)(1998)) Seq( (-32768.toShort, success(-32768)), @@ -1018,7 +1018,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( { - def success[T](v: T) = Expected(Success(v), 1764, upcastCostDetails(SLong), 1764, 1996 +: Seq.fill(3)(1998)) + def success[T](v: T) = Expected(Success(v), 1764, upcastCostDetails(SLong), 1764, Seq.fill(4)(1998)) Seq( (-32768.toShort, success(-32768L)), @@ -1036,7 +1036,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( { - def success(v: BigInt) = Expected(Success(v), 1767, upcastCostDetails(SBigInt), 1767, 1999 +: Seq.fill(3)(2001)) + def success(v: BigInt) = Expected(Success(v), 1767, upcastCostDetails(SBigInt), 1767, Seq.fill(4)(2001)) Seq( (-32768.toShort, success(CBigInt(new BigInteger("-8000", 16)))), @@ -1055,7 +1055,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => val n = ExactIntegral.ShortIsExactIntegral verifyCases( { - def success[T](v: T) = Expected(Success(v), 1788, arithOpsCostDetails(SShort), 1788, 2112 +: Seq.fill(3)(2116)) + def success[T](v: T) = Expected(Success(v), 1788, arithOpsCostDetails(SShort), 1788, Seq.fill(4)(2116)) Seq( ((-32768.toShort, 1.toShort), Expected(new ArithmeticException("Short overflow"))), @@ -1149,7 +1149,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => property("Short LT, GT, NEQ") { val o = ExactOrdering.ShortIsExactOrdering - def expect(v: Boolean) = Expected(Success(v), 1768, binaryRelationCostDetails(LT, SShort), 1768, 2010 +: Seq.fill(3)(2012)) + def expect(v: Boolean) = Expected(Success(v), 1768, binaryRelationCostDetails(LT, SShort), 1768, Seq.fill(4)(2012)) val LT_cases: Seq[((Short, Short), Expected[Boolean])] = Seq( (Short.MinValue, Short.MinValue) -> expect(false), @@ -1190,16 +1190,16 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyOp(LT_cases, "<", LT.apply)(_ < _) - verifyOp(swapArgs(LT_cases, cost = 1768, newCostDetails = binaryRelationCostDetails(GT, SShort), expectedV3Costs = 2010 +: Seq.fill(3)(2012)), ">", GT.apply)(_ > _) + verifyOp(swapArgs(LT_cases, cost = 1768, newCostDetails = binaryRelationCostDetails(GT, SShort), expectedV3Costs = Seq.fill(4)(2012)), ">", GT.apply)(_ > _) - val neqCases = newCasesFrom3(LT_cases.map(_._1))(_ != _, cost = 1766, newCostDetails = costNEQ(constNeqCost), expectedV3Costs = 2008 +: Seq.fill(3)(2010)) + val neqCases = newCasesFrom3(LT_cases.map(_._1))(_ != _, cost = 1766, newCostDetails = costNEQ(constNeqCost), expectedV3Costs = Seq.fill(4)(2010)) verifyOp(neqCases, "!=", NEQ.apply)(_ != _) } property("Short LE, GE") { val o = ExactOrdering.ShortIsExactOrdering - def expect(v: Boolean) = Expected(Success(v), 1768, binaryRelationCostDetails(LE, SShort), 1768, 2010 +: Seq.fill(3)(2012)) + def expect(v: Boolean) = Expected(Success(v), 1768, binaryRelationCostDetails(LE, SShort), 1768, Seq.fill(4)(2012)) val LE_cases: Seq[((Short, Short), Expected[Boolean])] = Seq( (Short.MinValue, Short.MinValue) -> expect(true), @@ -1242,7 +1242,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyOp(LE_cases, "<=", LE.apply)(_ <= _) verifyOp( - swapArgs(LE_cases, cost = 1768, newCostDetails = binaryRelationCostDetails(GE, SShort), expectedV3Costs = 2010 +: Seq.fill(3)(2012)), + swapArgs(LE_cases, cost = 1768, newCostDetails = binaryRelationCostDetails(GE, SShort), expectedV3Costs = Seq.fill(4)(2012)), ">=", GE.apply)(_ >= _) } @@ -1252,7 +1252,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( { - def success[T](v: T) = Expected(Success(v), 1764, downcastCostDetails(SByte), 1764, 1996 +: Seq.fill(3)(1998)) + def success[T](v: T) = Expected(Success(v), 1764, downcastCostDetails(SByte), 1764, Seq.fill(4)(1998)) Seq( (Int.MinValue, Expected(new ArithmeticException("Byte overflow"))), @@ -1272,7 +1272,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( { - def success[T](v: T) = Expected(Success(v), 1764, downcastCostDetails(SShort), 1764, 1996 +: Seq.fill(3)(1998)) + def success[T](v: T) = Expected(Success(v), 1764, downcastCostDetails(SShort), 1764, Seq.fill(4)(1998)) Seq( (Int.MinValue, Expected(new ArithmeticException("Short overflow"))), @@ -1292,7 +1292,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( { - def success[T](v: T) = Expected(Success(v), 1763, TracedCost(traceBase), 1763, 1991 +: Seq.fill(3)(1993)) + def success[T](v: T) = Expected(Success(v), 1763, TracedCost(traceBase), 1763, Seq.fill(4)(1993)) Seq( (Int.MinValue, success(Int.MinValue)), @@ -1308,7 +1308,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( { - def success[T](v: T) = Expected(Success(v), 1764, upcastCostDetails(SLong), 1764, 1996 +: Seq.fill(3)(1998)) + def success[T](v: T) = Expected(Success(v), 1764, upcastCostDetails(SLong), 1764, Seq.fill(4)(1998)) Seq( (Int.MinValue, success(Int.MinValue.toLong)), @@ -1324,7 +1324,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( { - def success(v: BigInt) = Expected(Success(v), 1767, upcastCostDetails(SBigInt), 1767, 1999 +: Seq.fill(3)(2001)) + def success(v: BigInt) = Expected(Success(v), 1767, upcastCostDetails(SBigInt), 1767, Seq.fill(4)(2001)) Seq( (Int.MinValue, success(CBigInt(new BigInteger("-80000000", 16)))), @@ -1343,7 +1343,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => val n = ExactNumeric.IntIsExactNumeric verifyCases( { - def success[T](v: T) = Expected(Success(v), 1788, arithOpsCostDetails(SInt), 1788, 2112 +: Seq.fill(3)(2116)) + def success[T](v: T) = Expected(Success(v), 1788, arithOpsCostDetails(SInt), 1788, Seq.fill(4)(2116)) Seq( ((Int.MinValue, 449583993), Expected(new ArithmeticException("integer overflow"))), @@ -1438,7 +1438,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => property("Int LT, GT, NEQ") { val o = ExactOrdering.IntIsExactOrdering - def expect(v: Boolean) = Expected(Success(v), 1768, binaryRelationCostDetails(LT, SInt), 1768, 2010 +: Seq.fill(3)(2012)) + def expect(v: Boolean) = Expected(Success(v), 1768, binaryRelationCostDetails(LT, SInt), 1768, Seq.fill(4)(2012)) val LT_cases: Seq[((Int, Int), Expected[Boolean])] = Seq( (Int.MinValue, Int.MinValue) -> expect(false), @@ -1480,16 +1480,16 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyOp(LT_cases, "<", LT.apply)(_ < _) verifyOp( - swapArgs(LT_cases, cost = 1768, newCostDetails = binaryRelationCostDetails(GT, SInt), expectedV3Costs = 2010 +: Seq.fill(3)(2012)), + swapArgs(LT_cases, cost = 1768, newCostDetails = binaryRelationCostDetails(GT, SInt), expectedV3Costs = Seq.fill(4)(2012)), ">", GT.apply)(_ > _) - val neqCases = newCasesFrom3(LT_cases.map(_._1))(_ != _, cost = 1766, newCostDetails = costNEQ(constNeqCost), expectedV3Costs = 2008 +: Seq.fill(3)(2010)) + val neqCases = newCasesFrom3(LT_cases.map(_._1))(_ != _, cost = 1766, newCostDetails = costNEQ(constNeqCost), expectedV3Costs = Seq.fill(4)(2010)) verifyOp(neqCases, "!=", NEQ.apply)(_ != _) } property("Int LE, GE") { val o = ExactOrdering.IntIsExactOrdering - def expect(v: Boolean) = Expected(Success(v), 1768, binaryRelationCostDetails(LE, SInt), 1768, 2010 +: Seq.fill(3)(2012)) + def expect(v: Boolean) = Expected(Success(v), 1768, binaryRelationCostDetails(LE, SInt), 1768, Seq.fill(4)(2012)) val LE_cases: Seq[((Int, Int), Expected[Boolean])] = Seq( (Int.MinValue, Int.MinValue) -> expect(true), (Int.MinValue, (Int.MinValue + 1).toInt) -> expect(true), @@ -1531,7 +1531,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyOp(LE_cases, "<=", LE.apply)(_ <= _) verifyOp( - swapArgs(LE_cases, cost = 1768, newCostDetails = binaryRelationCostDetails(GE, SInt), expectedV3Costs = 2010 +: Seq.fill(3)(2012)), + swapArgs(LE_cases, cost = 1768, newCostDetails = binaryRelationCostDetails(GE, SInt), expectedV3Costs = Seq.fill(4)(2012)), ">=", GE.apply)(_ >= _) } @@ -1545,7 +1545,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => property("Long.toByte method") { verifyCases( { - def success[T](v: T) = Expected(Success(v), 1764, downcastCostDetails(SByte), 1764, 1996 +: Seq.fill(3)(1998)) + def success[T](v: T) = Expected(Success(v), 1764, downcastCostDetails(SByte), 1764, Seq.fill(4)(1998)) Seq( (Long.MinValue, Expected(new ArithmeticException("Byte overflow"))), (Byte.MinValue.toLong - 1, Expected(new ArithmeticException("Byte overflow"))), @@ -1566,7 +1566,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => property("Long.toShort method") { verifyCases( { - def success[T](v: T) = Expected(Success(v), 1764, downcastCostDetails(SShort), 1764, 1996 +: Seq.fill(3)(1998)) + def success[T](v: T) = Expected(Success(v), 1764, downcastCostDetails(SShort), 1764, Seq.fill(4)(1998)) Seq( (Long.MinValue, Expected(new ArithmeticException("Short overflow"))), (Short.MinValue.toLong - 1, Expected(new ArithmeticException("Short overflow"))), @@ -1587,7 +1587,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => property("Long.toInt method") { verifyCases( { - def success[T](v: T) = Expected(Success(v), 1764, downcastCostDetails(SInt), 1764, 1996 +: Seq.fill(3)(1998)) + def success[T](v: T) = Expected(Success(v), 1764, downcastCostDetails(SInt), 1764, Seq.fill(4)(1998)) Seq( (Long.MinValue, Expected(new ArithmeticException("Int overflow"))), @@ -1609,7 +1609,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => property("Long.toLong method") { verifyCases( { - def success[T](v: T) = Expected(Success(v), 1763, TracedCost(traceBase), 1763, 1991 +: Seq.fill(3)(1993)) + def success[T](v: T) = Expected(Success(v), 1763, TracedCost(traceBase), 1763, Seq.fill(4)(1993)) Seq( (Long.MinValue, success(Long.MinValue)), (-1L, success(-1L)), @@ -1626,7 +1626,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => property("Long.toBigInt method") { verifyCases( { - def success(v: BigInt) = Expected(Success(v), 1767, upcastCostDetails(SBigInt), 1767, 1999 +: Seq.fill(3)(2001)) + def success(v: BigInt) = Expected(Success(v), 1767, upcastCostDetails(SBigInt), 1767, Seq.fill(4)(2001)) Seq( (Long.MinValue, success(CBigInt(new BigInteger("-8000000000000000", 16)))), (-1074651039980347209L, success(CBigInt(new BigInteger("-ee9ed6d57885f49", 16)))), @@ -1647,7 +1647,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => val n = ExactNumeric.LongIsExactNumeric verifyCases( { - def success[T](v: T) = Expected(Success(v), 1788, arithOpsCostDetails(SLong), 1788, 2112 +: Seq.fill(3)(2116)) + def success[T](v: T) = Expected(Success(v), 1788, arithOpsCostDetails(SLong), 1788, Seq.fill(4)(2116)) Seq( ((Long.MinValue, -4677100190307931395L), Expected(new ArithmeticException("long overflow"))), ((Long.MinValue, -1L), Expected(new ArithmeticException("long overflow"))), @@ -1738,7 +1738,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => property("Long LT, GT, NEQ") { val o = ExactOrdering.LongIsExactOrdering - def expect(v: Boolean) = Expected(Success(v), 1768, binaryRelationCostDetails(LT, SLong), 1768, 2010 +: Seq.fill(3)(2012)) + def expect(v: Boolean) = Expected(Success(v), 1768, binaryRelationCostDetails(LT, SLong), 1768, Seq.fill(4)(2012)) val LT_cases: Seq[((Long, Long), Expected[Boolean])] = Seq( (Long.MinValue, Long.MinValue) -> expect(false), (Long.MinValue, (Long.MinValue + 1).toLong) -> expect(true), @@ -1779,16 +1779,16 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyOp(LT_cases, "<", LT.apply)(_ < _) verifyOp( - swapArgs(LT_cases, cost = 1768, newCostDetails = binaryRelationCostDetails(GT, SLong), expectedV3Costs = 2010 +: Seq.fill(3)(2012)), + swapArgs(LT_cases, cost = 1768, newCostDetails = binaryRelationCostDetails(GT, SLong), expectedV3Costs = Seq.fill(4)(2012)), ">", GT.apply)(_ > _) - val neqCases = newCasesFrom3(LT_cases.map(_._1))(_ != _, cost = 1766, newCostDetails = costNEQ(constNeqCost), 2008 +: Seq.fill(3)(2010)) + val neqCases = newCasesFrom3(LT_cases.map(_._1))(_ != _, cost = 1766, newCostDetails = costNEQ(constNeqCost), Seq.fill(4)(2010)) verifyOp(neqCases, "!=", NEQ.apply)(_ != _) } property("Long LE, GE") { val o = ExactOrdering.LongIsExactOrdering - def expect(v: Boolean) = Expected(Success(v), 1768, binaryRelationCostDetails(LE, SLong), 1768, 2010 +: Seq.fill(3)(2012)) + def expect(v: Boolean) = Expected(Success(v), 1768, binaryRelationCostDetails(LE, SLong), 1768, Seq.fill(4)(2012)) val LE_cases: Seq[((Long, Long), Expected[Boolean])] = Seq( (Long.MinValue, Long.MinValue) -> expect(true), (Long.MinValue, (Long.MinValue + 1).toLong) -> expect(true), @@ -1830,14 +1830,14 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyOp(LE_cases, "<=", LE.apply)(_ <= _) verifyOp( - swapArgs(LE_cases, cost = 1768, newCostDetails = binaryRelationCostDetails(GE, SLong), expectedV3Costs = 2010 +: Seq.fill(3)(2012)), + swapArgs(LE_cases, cost = 1768, newCostDetails = binaryRelationCostDetails(GE, SLong), expectedV3Costs = Seq.fill(4)(2012)), ">=", GE.apply)(_ >= _) } property("BigInt methods equivalence") { verifyCases( { - def success(v: BigInt) = Expected(Success(v), 1764, TracedCost(traceBase), 1764, 1992 +: Seq.fill(3)(1994)) + def success(v: BigInt) = Expected(Success(v), 1764, TracedCost(traceBase), 1764, Seq.fill(4)(1994)) Seq( (CBigInt(new BigInteger("-85102d7f884ca0e8f56193b46133acaf7e4681e1757d03f191ae4f445c8e0", 16)), success( CBigInt(new BigInteger("-85102d7f884ca0e8f56193b46133acaf7e4681e1757d03f191ae4f445c8e0", 16)) @@ -1860,7 +1860,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( { def success(v: (BigInt, (BigInt, (BigInt, (BigInt, BigInt))))) = - Expected(Success(v), 1793, arithOpsCostDetails(SBigInt), 1793, 2117 +: Seq.fill(3)(2121)) + Expected(Success(v), 1793, arithOpsCostDetails(SBigInt), 1793, Seq.fill(4)(2121)) Seq( ((CBigInt(new BigInteger("-8683d1cd99d5fcf0e6eff6295c285c36526190e13dbde008c49e5ae6fddc1c", 16)), CBigInt(new BigInteger("-2ef55db3f245feddacf0182e299dd", 16))), @@ -1984,7 +1984,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => property("BigInt LT, GT, NEQ") { val o = NumericOps.BigIntIsExactOrdering - def expect(v: Boolean) = Expected(Success(v), 1768, binaryRelationCostDetails(LT, SBigInt), 1768, 2010 +: Seq.fill(3)(2012)) + def expect(v: Boolean) = Expected(Success(v), 1768, binaryRelationCostDetails(LT, SBigInt), 1768, Seq.fill(4)(2012)) val LT_cases: Seq[((BigInt, BigInt), Expected[Boolean])] = Seq( (BigIntMinValue, BigIntMinValue) -> expect(false), (BigIntMinValue, BigIntMinValue.add(1.toBigInt)) -> expect(true), @@ -2027,11 +2027,11 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyOp(LT_cases, "<", LT.apply)(o.lt(_, _)) verifyOp( - swapArgs(LT_cases, cost = 1768, newCostDetails = binaryRelationCostDetails(GT, SBigInt), expectedV3Costs = 2010 +: Seq.fill(3)(2012)), + swapArgs(LT_cases, cost = 1768, newCostDetails = binaryRelationCostDetails(GT, SBigInt), expectedV3Costs = Seq.fill(4)(2012)), ">", GT.apply)(o.gt(_, _)) val constBigIntCost = Array[CostItem](FixedCostItem(NamedDesc("EQ_BigInt"), FixedCost(JitCost(5)))) - val neqCases = newCasesFrom3(LT_cases.map(_._1))(_ != _, cost = 1766, newCostDetails = costNEQ(constBigIntCost), expectedV3Costs = 2008 +: Seq.fill(3)(2010)) + val neqCases = newCasesFrom3(LT_cases.map(_._1))(_ != _, cost = 1766, newCostDetails = costNEQ(constBigIntCost), expectedV3Costs = Seq.fill(4)(2010)) verifyOp(neqCases, "!=", NEQ.apply)(_ != _) } @@ -2042,7 +2042,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => val BigIntMaxValue = CBigInt(new BigInteger("7F" + "ff" * 31, 16)) val BigIntOverlimit = CBigInt(new BigInteger("7F" + "ff" * 33, 16)) - def expect(v: Boolean) = Expected(Success(v), 1768, binaryRelationCostDetails(LE, SBigInt), 1768, 2010 +: Seq.fill(3)(2012)) + def expect(v: Boolean) = Expected(Success(v), 1768, binaryRelationCostDetails(LE, SBigInt), 1768, Seq.fill(4)(2012)) val LE_cases: Seq[((BigInt, BigInt), Expected[Boolean])] = Seq( (BigIntMinValue, BigIntMinValue) -> expect(true), (BigIntMinValue, BigIntMinValue.add(1.toBigInt)) -> expect(true), @@ -2086,7 +2086,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyOp(LE_cases, "<=", LE.apply)(o.lteq(_, _)) verifyOp( - swapArgs(LE_cases, cost = 1768, newCostDetails = binaryRelationCostDetails(GE, SBigInt), expectedV3Costs = 2010 +: Seq.fill(3)(2012)), + swapArgs(LE_cases, cost = 1768, newCostDetails = binaryRelationCostDetails(GE, SBigInt), expectedV3Costs = Seq.fill(4)(2012)), ">=", GE.apply)(o.gteq(_, _)) } @@ -2113,11 +2113,11 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => } property("NEQ of pre-defined types") { - verifyNeq(ge1, ge2, 1783, Array[CostItem](FixedCostItem(NamedDesc("EQ_GroupElement"), FixedCost(JitCost(172)))), 1783, 2025 +: Seq.fill(3)(2027))(_.asInstanceOf[CGroupElement].copy()) - verifyNeq(t1, t2, 1767, Array[CostItem](FixedCostItem(NamedDesc("EQ_AvlTree"), FixedCost(JitCost(6)))), 1767, 2017 +: Seq.fill(3)(2019))(_.asInstanceOf[CAvlTree].copy()) - verifyNeq(b1, b2, 1767, Array[CostItem](), 1767, 2017 +: Seq.fill(3)(2019))(_.asInstanceOf[CBox].copy()) - verifyNeq(preH1, preH2, 1766, Array[CostItem](FixedCostItem(NamedDesc("EQ_PreHeader"), FixedCost(JitCost(4)))), 1766, 2016 +: Seq.fill(3)(2018))(_.asInstanceOf[CPreHeader].copy()) - verifyNeq(h1, h2, 1767, Array[CostItem](FixedCostItem(NamedDesc("EQ_Header"), FixedCost(JitCost(6)))), 1767, 2017 +: Seq.fill(3)(2019))(_.asInstanceOf[CHeader].copy()) + verifyNeq(ge1, ge2, 1783, Array[CostItem](FixedCostItem(NamedDesc("EQ_GroupElement"), FixedCost(JitCost(172)))), 1783, Seq.fill(4)(2027))(_.asInstanceOf[CGroupElement].copy()) + verifyNeq(t1, t2, 1767, Array[CostItem](FixedCostItem(NamedDesc("EQ_AvlTree"), FixedCost(JitCost(6)))), 1767, Seq.fill(4)(2019))(_.asInstanceOf[CAvlTree].copy()) + verifyNeq(b1, b2, 1767, Array[CostItem](), 1767, Seq.fill(4)(2019))(_.asInstanceOf[CBox].copy()) + verifyNeq(preH1, preH2, 1766, Array[CostItem](FixedCostItem(NamedDesc("EQ_PreHeader"), FixedCost(JitCost(4)))), 1766, Seq.fill(4)(2018))(_.asInstanceOf[CPreHeader].copy()) + verifyNeq(h1, h2, 1767, Array[CostItem](FixedCostItem(NamedDesc("EQ_Header"), FixedCost(JitCost(6)))), 1767, Seq.fill(4)(2019))(_.asInstanceOf[CHeader].copy()) } property("NEQ of tuples of numerics") { @@ -2125,14 +2125,14 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => FixedCostItem(NamedDesc("EQ_Tuple"), FixedCost(JitCost(4))), FixedCostItem(NamedDesc("EQ_Prim"), FixedCost(JitCost(3))) ) - verifyNeq((0.toByte, 1.toByte), (1.toByte, 1.toByte), 1767, tuplesNeqCost, 1767, 2017 +: Seq.fill(3)(2019))(_.copy()) - verifyNeq((0.toShort, 1.toByte), (1.toShort, 1.toByte), 1767, tuplesNeqCost, 1767, 2025 +: Seq.fill(3)(2029))(_.copy()) - verifyNeq((0, 1.toByte), (1, 1.toByte), 1767, tuplesNeqCost, 1767, 2025 +: Seq.fill(3)(2029))(_.copy()) - verifyNeq((0.toLong, 1.toByte), (1.toLong, 1.toByte), 1767, tuplesNeqCost, 1767, 2025 +: Seq.fill(3)(2029))(_.copy()) + verifyNeq((0.toByte, 1.toByte), (1.toByte, 1.toByte), 1767, tuplesNeqCost, 1767, Seq.fill(4)(2019))(_.copy()) + verifyNeq((0.toShort, 1.toByte), (1.toShort, 1.toByte), 1767, tuplesNeqCost, 1767, Seq.fill(4)(2029))(_.copy()) + verifyNeq((0, 1.toByte), (1, 1.toByte), 1767, tuplesNeqCost, 1767, Seq.fill(4)(2029))(_.copy()) + verifyNeq((0.toLong, 1.toByte), (1.toLong, 1.toByte), 1767, tuplesNeqCost, 1767, Seq.fill(4)(2029))(_.copy()) verifyNeq((0.toBigInt, 1.toByte), (1.toBigInt, 1.toByte), 1767, Array( FixedCostItem(NamedDesc("EQ_Tuple"), FixedCost(JitCost(4))), FixedCostItem(NamedDesc("EQ_BigInt"), FixedCost(JitCost(5))) - ), 1767, 2025 +: Seq.fill(3)(2029))(_.copy()) + ), 1767, Seq.fill(4)(2029))(_.copy()) } property("NEQ of tuples of pre-defined types") { @@ -2141,29 +2141,29 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => FixedCostItem(NamedDesc("EQ_GroupElement"), FixedCost(JitCost(172))), FixedCostItem(NamedDesc("EQ_GroupElement"), FixedCost(JitCost(172))) ) - verifyNeq((ge1, ge1), (ge1, ge2), 1801, groupNeqCost, 1801, 2051 +: Seq.fill(3)(2053))(_.copy()) + verifyNeq((ge1, ge1), (ge1, ge2), 1801, groupNeqCost, 1801, Seq.fill(4)(2053))(_.copy()) val treeNeqCost = Array( FixedCostItem(NamedDesc("EQ_Tuple"), FixedCost(JitCost(4))), FixedCostItem(NamedDesc("EQ_AvlTree"), FixedCost(JitCost(6))), FixedCostItem(NamedDesc("EQ_AvlTree"), FixedCost(JitCost(6))) ) - verifyNeq((t1, t1), (t1, t2), 1768, treeNeqCost, 1768, 2034 +: Seq.fill(3)(2038))(_.copy()) - verifyNeq((b1, b1), (b1, b2), 1768, Array[CostItem](), 1768, 2034 +: Seq.fill(3)(2038))(_.copy()) + verifyNeq((t1, t1), (t1, t2), 1768, treeNeqCost, 1768, Seq.fill(4)(2038))(_.copy()) + verifyNeq((b1, b1), (b1, b2), 1768, Array[CostItem](), 1768, Seq.fill(4)(2038))(_.copy()) val preHeaderNeqCost = Array( FixedCostItem(NamedDesc("EQ_Tuple"), FixedCost(JitCost(4))), FixedCostItem(NamedDesc("EQ_PreHeader"), FixedCost(JitCost(4))), FixedCostItem(NamedDesc("EQ_PreHeader"), FixedCost(JitCost(4))) ) - verifyNeq((preH1, preH1), (preH1, preH2), 1767, preHeaderNeqCost, 1767, 2033 +: Seq.fill(3)(2037))(_.copy()) + verifyNeq((preH1, preH1), (preH1, preH2), 1767, preHeaderNeqCost, 1767, Seq.fill(4)(2037))(_.copy()) val headerNeqCost = Array( FixedCostItem(NamedDesc("EQ_Tuple"), FixedCost(JitCost(4))), FixedCostItem(NamedDesc("EQ_Header"), FixedCost(JitCost(6))), FixedCostItem(NamedDesc("EQ_Header"), FixedCost(JitCost(6))) ) - verifyNeq((h1, h1), (h1, h2), 1768, headerNeqCost, 1768, 2034 +: Seq.fill(3)(2038))(_.copy()) + verifyNeq((h1, h1), (h1, h2), 1768, headerNeqCost, 1768, Seq.fill(4)(2038))(_.copy()) } property("NEQ of nested tuples") { @@ -2247,15 +2247,15 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => FixedCostItem(NamedDesc("EQ_Header"), FixedCost(JitCost(6))), FixedCostItem(NamedDesc("EQ_Header"), FixedCost(JitCost(6))) ) - verifyNeq((ge1, (t1, t1)), (ge1, (t1, t2)), 1785, nestedTuplesNeqCost1, 1785, 2059 +: Seq.fill(3)(2063))(_.copy()) - verifyNeq((ge1, (t1, (b1, b1))), (ge1, (t1, (b1, b2))), 1786, nestedTuplesNeqCost2, 1786, 2076 +: Seq.fill(3)(2080))(_.copy()) - verifyNeq((ge1, (t1, (b1, (preH1, preH1)))), (ge1, (t1, (b1, (preH1, preH2)))), 1787, nestedTuplesNeqCost3, 1787, 2093 +: Seq.fill(3)(2097))(_.copy()) - verifyNeq((ge1, (t1, (b1, (preH1, (h1, h1))))), (ge1, (t1, (b1, (preH1, (h1, h2))))), 1788, nestedTuplesNeqCost4, 1788, 2110 +: Seq.fill(3)(2114))(_.copy()) + verifyNeq((ge1, (t1, t1)), (ge1, (t1, t2)), 1785, nestedTuplesNeqCost1, 1785, Seq.fill(4)(2063))(_.copy()) + verifyNeq((ge1, (t1, (b1, b1))), (ge1, (t1, (b1, b2))), 1786, nestedTuplesNeqCost2, 1786, Seq.fill(4)(2080))(_.copy()) + verifyNeq((ge1, (t1, (b1, (preH1, preH1)))), (ge1, (t1, (b1, (preH1, preH2)))), 1787, nestedTuplesNeqCost3, 1787, Seq.fill(4)(2097))(_.copy()) + verifyNeq((ge1, (t1, (b1, (preH1, (h1, h1))))), (ge1, (t1, (b1, (preH1, (h1, h2))))), 1788, nestedTuplesNeqCost4, 1788, Seq.fill(4)(2114))(_.copy()) - verifyNeq(((ge1, t1), t1), ((ge1, t1), t2), 1785, nestedTuplesNeqCost5, 1785, 2059 +: Seq.fill(3)(2063))(_.copy()) - verifyNeq((((ge1, t1), b1), b1), (((ge1, t1), b1), b2), 1786, nestedTuplesNeqCost6, 1786, 2076 +: Seq.fill(3)(2080))(_.copy()) - verifyNeq((((ge1, t1), b1), (preH1, preH1)), (((ge1, t1), b1), (preH1, preH2)), 1787, nestedTuplesNeqCost7, 1787, 2093 +: Seq.fill(3)(2097))(_.copy()) - verifyNeq((((ge1, t1), b1), (preH1, (h1, h1))), (((ge1, t1), b1), (preH1, (h1, h2))), 1788, nestedTuplesNeqCost8, 1788, 2110 +: Seq.fill(3)(2114))(_.copy()) + verifyNeq(((ge1, t1), t1), ((ge1, t1), t2), 1785, nestedTuplesNeqCost5, 1785, Seq.fill(4)(2063))(_.copy()) + verifyNeq((((ge1, t1), b1), b1), (((ge1, t1), b1), b2), 1786, nestedTuplesNeqCost6, 1786, Seq.fill(4)(2080))(_.copy()) + verifyNeq((((ge1, t1), b1), (preH1, preH1)), (((ge1, t1), b1), (preH1, preH2)), 1787, nestedTuplesNeqCost7, 1787, Seq.fill(4)(2097))(_.copy()) + verifyNeq((((ge1, t1), b1), (preH1, (h1, h1))), (((ge1, t1), b1), (preH1, (h1, h2))), 1788, nestedTuplesNeqCost8, 1788, Seq.fill(4)(2114))(_.copy()) } property("NEQ of collections of pre-defined types") { @@ -2267,71 +2267,71 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => ast.SeqCostItem(NamedDesc("EQ_COA_Box"), PerItemCost(JitCost(15), JitCost(5), 1), 0) ) implicit val evalSettings = suite.evalSettings.copy(isMeasureOperationTime = false) - verifyNeq(Coll[Byte](), Coll(1.toByte), 1766, collNeqCost1, 1766, 2016 +: Seq.fill(3)(2018))(cloneColl(_)) + verifyNeq(Coll[Byte](), Coll(1.toByte), 1766, collNeqCost1, 1766, Seq.fill(4)(2018))(cloneColl(_)) verifyNeq(Coll[Byte](0, 1), Coll(1.toByte, 1.toByte), 1768, Array( FixedCostItem(NamedDesc("MatchType"), FixedCost(JitCost(1))), ast.SeqCostItem(NamedDesc("EQ_COA_Byte"), PerItemCost(JitCost(15), JitCost(2), 128), 1)), 1768, - 2018 +: Seq.fill(3)(2020) + Seq.fill(4)(2020) )(cloneColl(_)) - verifyNeq(Coll[Short](), Coll(1.toShort), 1766, collNeqCost1, 1766, 2016 +: Seq.fill(3)(2018))(cloneColl(_)) + verifyNeq(Coll[Short](), Coll(1.toShort), 1766, collNeqCost1, 1766, Seq.fill(4)(2018))(cloneColl(_)) verifyNeq(Coll[Short](0), Coll(1.toShort), 1768, Array( FixedCostItem(NamedDesc("MatchType"), FixedCost(JitCost(1))), ast.SeqCostItem(NamedDesc("EQ_COA_Short"), PerItemCost(JitCost(15), JitCost(2), 96), 1)), 1768, - 2018 +: Seq.fill(3)(2020) + Seq.fill(4)(2020) )(cloneColl(_)) - verifyNeq(Coll[Int](), Coll(1), 1766, collNeqCost1, 1766, 2016 +: Seq.fill(3)(2018))(cloneColl(_)) + verifyNeq(Coll[Int](), Coll(1), 1766, collNeqCost1, 1766, Seq.fill(4)(2018))(cloneColl(_)) verifyNeq(Coll[Int](0), Coll(1), 1768, Array( FixedCostItem(NamedDesc("MatchType"), FixedCost(JitCost(1))), ast.SeqCostItem(NamedDesc("EQ_COA_Int"), PerItemCost(JitCost(15), JitCost(2), 64), 1)), 1768, - 2018 +: Seq.fill(3)(2020) + Seq.fill(4)(2020) )(cloneColl(_)) - verifyNeq(Coll[Long](), Coll(1.toLong), 1766, collNeqCost1, 1766, 2016 +: Seq.fill(3)(2018))(cloneColl(_)) + verifyNeq(Coll[Long](), Coll(1.toLong), 1766, collNeqCost1, 1766, Seq.fill(4)(2018))(cloneColl(_)) verifyNeq(Coll[Long](0), Coll(1.toLong), 1768, Array( FixedCostItem(NamedDesc("MatchType"), FixedCost(JitCost(1))), ast.SeqCostItem(NamedDesc("EQ_COA_Long"), PerItemCost(JitCost(15), JitCost(2), 48), 1)), 1768, - 2018 +: Seq.fill(3)(2020) + Seq.fill(4)(2020) )(cloneColl(_)) prepareSamples[Coll[BigInt]] - verifyNeq(Coll[BigInt](), Coll(1.toBigInt), 1766, collNeqCost1, 1766, 2016 +: Seq.fill(3)(2018))(cloneColl(_)) + verifyNeq(Coll[BigInt](), Coll(1.toBigInt), 1766, collNeqCost1, 1766, Seq.fill(4)(2018))(cloneColl(_)) verifyNeq(Coll[BigInt](0.toBigInt), Coll(1.toBigInt), 1768, Array( FixedCostItem(NamedDesc("MatchType"), FixedCost(JitCost(1))), ast.SeqCostItem(NamedDesc("EQ_COA_BigInt"), PerItemCost(JitCost(15), JitCost(7), 5), 1)), 1768, - 2018 +: Seq.fill(3)(2020) + Seq.fill(4)(2020) )(cloneColl(_)) prepareSamples[Coll[GroupElement]] - verifyNeq(Coll[GroupElement](), Coll(ge1), 1766, collNeqCost1, 1766, 2016 +: Seq.fill(3)(2018))(cloneColl(_)) + verifyNeq(Coll[GroupElement](), Coll(ge1), 1766, collNeqCost1, 1766, Seq.fill(4)(2018))(cloneColl(_)) verifyNeq(Coll[GroupElement](ge1), Coll(ge2), 1768, Array( FixedCostItem(NamedDesc("MatchType"), FixedCost(JitCost(1))), ast.SeqCostItem(NamedDesc("EQ_COA_GroupElement"), PerItemCost(JitCost(15), JitCost(5), 1), 1)), 1768, - 2018 +: Seq.fill(3)(2020) + Seq.fill(4)(2020) )(cloneColl(_)) prepareSamples[Coll[AvlTree]] - verifyNeq(Coll[AvlTree](), Coll(t1), 1766, collNeqCost1, 1766, 2024 +: Seq.fill(3)(2028))(cloneColl(_)) + verifyNeq(Coll[AvlTree](), Coll(t1), 1766, collNeqCost1, 1766, Seq.fill(4)(2028))(cloneColl(_)) verifyNeq(Coll[AvlTree](t1), Coll(t2), 1768, Array( FixedCostItem(NamedDesc("MatchType"), FixedCost(JitCost(1))), ast.SeqCostItem(NamedDesc("EQ_COA_AvlTree"), PerItemCost(JitCost(15), JitCost(5), 2), 1)), 1768, - 2026 +: Seq.fill(3)(2030) + Seq.fill(4)(2030) )(cloneColl(_)) { // since SBox.isConstantSize = false, the cost is different among cases @@ -2340,11 +2340,11 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => val y = Coll(b1) val copied_x = cloneColl(x) verifyOp(Seq( - (x, x) -> Expected(Success(false), 1768, costNEQ(collNeqCost2), 1768, 2026 +: Seq.fill(3)(2030)), - (x, copied_x) -> Expected(Success(false), 1768, costNEQ(collNeqCost2), 1768, 2026 +: Seq.fill(3)(2030)), - (copied_x, x) -> Expected(Success(false), 1768, costNEQ(collNeqCost2), 1768, 2026 +: Seq.fill(3)(2030)), - (x, y) -> Expected(Success(true), 1766, costNEQ(collNeqCost1), 1766, 2024 +: Seq.fill(3)(2028)), - (y, x) -> Expected(Success(true), 1766, costNEQ(collNeqCost1), 1766, 2024 +: Seq.fill(3)(2028)) + (x, x) -> Expected(Success(false), 1768, costNEQ(collNeqCost2), 1768, Seq.fill(4)(2030)), + (x, copied_x) -> Expected(Success(false), 1768, costNEQ(collNeqCost2), 1768, Seq.fill(4)(2030)), + (copied_x, x) -> Expected(Success(false), 1768, costNEQ(collNeqCost2), 1768, Seq.fill(4)(2030)), + (x, y) -> Expected(Success(true), 1766, costNEQ(collNeqCost1), 1766, Seq.fill(4)(2028)), + (y, x) -> Expected(Success(true), 1766, costNEQ(collNeqCost1), 1766, Seq.fill(4)(2028)) ), "!=", NEQ.apply)(_ != _, generateCases = false) @@ -2353,27 +2353,27 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => FixedCostItem(NamedDesc("MatchType"), FixedCost(JitCost(1))), ast.SeqCostItem(NamedDesc("EQ_COA_Box"), PerItemCost(JitCost(15), JitCost(5), 1), 1)), 1768, - 2026 +: Seq.fill(3)(2030) + Seq.fill(4)(2030) )(cloneColl(_), generateCases = false) } prepareSamples[Coll[PreHeader]] - verifyNeq(Coll[PreHeader](), Coll(preH1), 1766, collNeqCost1, 1766, 2024 +: Seq.fill(3)(2028))(cloneColl(_)) + verifyNeq(Coll[PreHeader](), Coll(preH1), 1766, collNeqCost1, 1766, Seq.fill(4)(2028))(cloneColl(_)) verifyNeq(Coll[PreHeader](preH1), Coll(preH2), 1768, Array( FixedCostItem(NamedDesc("MatchType"), FixedCost(JitCost(1))), ast.SeqCostItem(NamedDesc("EQ_COA_PreHeader"), PerItemCost(JitCost(15), JitCost(3), 1), 1)), 1768, - 2026 +: Seq.fill(3)(2030) + Seq.fill(4)(2030) )(cloneColl(_)) prepareSamples[Coll[Header]] - verifyNeq(Coll[Header](), Coll(h1), 1766, collNeqCost1, 1766, 2024 +: Seq.fill(3)(2028))(cloneColl(_)) + verifyNeq(Coll[Header](), Coll(h1), 1766, collNeqCost1, 1766, Seq.fill(4)(2028))(cloneColl(_)) verifyNeq(Coll[Header](h1), Coll(h2), 1768, Array( FixedCostItem(NamedDesc("MatchType"), FixedCost(JitCost(1))), ast.SeqCostItem(NamedDesc("EQ_COA_Header"), PerItemCost(JitCost(15), JitCost(5), 1), 1)), - 1768, 2026 +: Seq.fill(3)(2030) + 1768, Seq.fill(4)(2030) )(cloneColl(_)) } @@ -2397,10 +2397,10 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => ast.SeqCostItem(NamedDesc("EQ_COA_Int"), PerItemCost(JitCost(15), JitCost(2), 64), 1), ast.SeqCostItem(NamedDesc("EQ_Coll"), PerItemCost(JitCost(10), JitCost(2), 1), 1) ) - verifyNeq(Coll[Coll[Int]](), Coll(Coll[Int]()), 1766, nestedNeq1, 1766, 2016 +: Seq.fill(3)(2018))(cloneColl(_)) - verifyNeq(Coll(Coll[Int]()), Coll(Coll[Int](1)), 1767, nestedNeq2, 1767, 2017 +: Seq.fill(3)(2019))(cloneColl(_)) - verifyNeq(Coll(Coll[Int](1)), Coll(Coll[Int](2)), 1769, nestedNeq3, 1769, 2019 +: Seq.fill(3)(2021))(cloneColl(_)) - verifyNeq(Coll(Coll[Int](1)), Coll(Coll[Int](1, 2)), 1767, nestedNeq2, 1767, 2017 +: Seq.fill(3)(2019))(cloneColl(_)) + verifyNeq(Coll[Coll[Int]](), Coll(Coll[Int]()), 1766, nestedNeq1, 1766, Seq.fill(4)(2018))(cloneColl(_)) + verifyNeq(Coll(Coll[Int]()), Coll(Coll[Int](1)), 1767, nestedNeq2, 1767, Seq.fill(4)(2019))(cloneColl(_)) + verifyNeq(Coll(Coll[Int](1)), Coll(Coll[Int](2)), 1769, nestedNeq3, 1769, Seq.fill(4)(2021))(cloneColl(_)) + verifyNeq(Coll(Coll[Int](1)), Coll(Coll[Int](1, 2)), 1767, nestedNeq2, 1767, Seq.fill(4)(2019))(cloneColl(_)) prepareSamples[Coll[(Int, BigInt)]] prepareSamples[Coll[Coll[(Int, BigInt)]]] @@ -2443,8 +2443,8 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => ast.SeqCostItem(NamedDesc("EQ_Coll"), PerItemCost(JitCost(10), JitCost(2), 1), 1), ast.SeqCostItem(NamedDesc("EQ_Coll"), PerItemCost(JitCost(10), JitCost(2), 1), 1) ) - verifyNeq(Coll(Coll((1, 10.toBigInt))), Coll(Coll((1, 11.toBigInt))), 1770, nestedNeq4, 1770, 2044 +: Seq.fill(3)(2048))(cloneColl(_)) - verifyNeq(Coll(Coll(Coll((1, 10.toBigInt)))), Coll(Coll(Coll((1, 11.toBigInt)))), 1771, nestedNeq5, 1771, 2053 +: Seq.fill(3)(2057))(cloneColl(_)) + verifyNeq(Coll(Coll((1, 10.toBigInt))), Coll(Coll((1, 11.toBigInt))), 1770, nestedNeq4, 1770, Seq.fill(4)(2048))(cloneColl(_)) + verifyNeq(Coll(Coll(Coll((1, 10.toBigInt)))), Coll(Coll(Coll((1, 11.toBigInt)))), 1771, nestedNeq5, 1771, Seq.fill(4)(2057))(cloneColl(_)) verifyNeq( (Coll( (Coll( @@ -2459,14 +2459,14 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => 1774, nestedNeq6, 1774, - 2096 +: Seq.fill(3)(2100) + Seq.fill(4)(2100) )(x => (cloneColl(x._1), x._2)) } property("GroupElement.getEncoded equivalence") { verifyCases( { - def success[T](v: T) = Expected(Success(v), 1790, methodCostDetails(SGroupElementMethods.GetEncodedMethod, 250), 1790, 2024 +: Seq.fill(3)(2026)) + def success[T](v: T) = Expected(Success(v), 1790, methodCostDetails(SGroupElementMethods.GetEncodedMethod, 250), 1790, Seq.fill(4)(2026)) Seq( (ge1, success(Helpers.decodeBytes(ge1str))), (ge2, success(Helpers.decodeBytes(ge2str))), @@ -2497,7 +2497,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => FixedCostItem(NamedDesc("EQ_GroupElement"), FixedCost(JitCost(172))) ) ) - def success[T](v: T) = Expected(Success(v), 1837, costDetails, 1837, 2079 +: Seq.fill(3)(2081)) + def success[T](v: T) = Expected(Success(v), 1837, costDetails, 1837, Seq.fill(4)(2081)) Seq( (ge1, success(true)), (ge2, success(true)), @@ -2527,7 +2527,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => property("GroupElement.negate equivalence") { verifyCases( { - def success[T](v: T) = Expected(Success(v), 1785, methodCostDetails(SGroupElementMethods.NegateMethod, 45), 1785, 2019 +: Seq.fill(3)(2021)) + def success[T](v: T) = Expected(Success(v), 1785, methodCostDetails(SGroupElementMethods.NegateMethod, 45), 1785, Seq.fill(4)(2021)) Seq( (ge1, success(Helpers.decodeGroupElement("02358d53f01276211f92d0aefbd278805121d4ff6eb534b777af1ee8abae5b2056"))), (ge2, success(Helpers.decodeGroupElement("03dba7b94b111f3894e2f9120b577da595ec7d58d488485adf73bf4e153af63575"))), @@ -2570,7 +2570,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => FixedCostItem(Exponentiate) ) ) - verifyCases(cases(1873, costDetails, 2119 +: Seq.fill(3)(2121)), + verifyCases(cases(1873, costDetails, Seq.fill(4)(2121)), existingFeature( scalaFunc, script, @@ -2597,7 +2597,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => FixedCostItem(SGroupElementMethods.ExponentiateMethod, FixedCost(JitCost(900))) ) ) - verifyCases(cases(1873, costDetails, 2119 +: Seq.fill(3)(2121)), + verifyCases(cases(1873, costDetails, Seq.fill(4)(2121)), existingFeature( scalaFunc, script, @@ -2644,7 +2644,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => ) ) ) - def success[T](v: T) = Expected(Success(v), 1787, costDetails, 1787, 2029 +: Seq.fill(3)(2031)) + def success[T](v: T) = Expected(Success(v), 1787, costDetails, 1787, Seq.fill(4)(2031)) Seq( ((ge1, Helpers.decodeGroupElement("03e132ca090614bd6c9f811e91f6daae61f16968a1e6c694ed65aacd1b1092320e")), success(Helpers.decodeGroupElement("02bc48937b4a66f249a32dfb4d2efd0743dc88d46d770b8c5d39fd03325ba211df"))), @@ -2707,7 +2707,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => } verifyCases( { - def success[T](v: T) = Expected(Success(v), 1767, methodCostDetails(SAvlTreeMethods.digestMethod, 15), 1767, 2001 +: Seq.fill(3)(2003)) + def success[T](v: T) = Expected(Success(v), 1767, methodCostDetails(SAvlTreeMethods.digestMethod, 15), 1767, Seq.fill(4)(2003)) Seq( (t1, success(Helpers.decodeBytes("000183807f66b301530120ff7fc6bd6601ff01ff7f7d2bedbbffff00187fe89094"))), (t2, success(Helpers.decodeBytes("ff000d937f80ffd731ed802d24358001ff8080ff71007f00ad37e0a7ae43fff95b"))), @@ -2720,7 +2720,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( { - def success[T](v: T) = Expected(Success(v), 1765, methodCostDetails(SAvlTreeMethods.enabledOperationsMethod, 15), 1765, 1999 +: Seq.fill(3)(2001)) + def success[T](v: T) = Expected(Success(v), 1765, methodCostDetails(SAvlTreeMethods.enabledOperationsMethod, 15), 1765, Seq.fill(4)(2001)) Seq( (t1, success(6.toByte)), (t2, success(0.toByte)), @@ -2733,7 +2733,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( { - def success[T](v: T) = Expected(Success(v), 1765, methodCostDetails(SAvlTreeMethods.keyLengthMethod, 15), 1765, 1999 +: Seq.fill(3)(2001)) + def success[T](v: T) = Expected(Success(v), 1765, methodCostDetails(SAvlTreeMethods.keyLengthMethod, 15), 1765, Seq.fill(4)(2001)) Seq( (t1, success(1)), (t2, success(32)), @@ -2748,9 +2748,9 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => { def success[T](v: T, newCost: Int, expectedV3Costs: Seq[Int]) = Expected(Success(v), newCost, methodCostDetails(SAvlTreeMethods.valueLengthOptMethod, 15), newCost, expectedV3Costs) Seq( - (t1, success(Some(1), 1766, 2000 +: Seq.fill(3)(2002))), - (t2, success(Some(64), 1766, 2000 +: Seq.fill(3)(2002))), - (t3, success(None, 1765, 1999 +: Seq.fill(3)(2001))) + (t1, success(Some(1), 1766, Seq.fill(4)(2002))), + (t2, success(Some(64), 1766, Seq.fill(4)(2002))), + (t3, success(None, 1765, Seq.fill(4)(2001))) ) }, existingFeature((t: AvlTree) => t.valueLengthOpt, @@ -2759,7 +2759,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( { - def success[T](v: T) = Expected(Success(v), 1765, methodCostDetails(SAvlTreeMethods.isInsertAllowedMethod, 15), 1765, 1999 +: Seq.fill(3)(2001)) + def success[T](v: T) = Expected(Success(v), 1765, methodCostDetails(SAvlTreeMethods.isInsertAllowedMethod, 15), 1765, Seq.fill(4)(2001)) Seq( (t1, success(false)), (t2, success(false)), @@ -2772,7 +2772,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( { - def success[T](v: T) = Expected(Success(v), 1765, methodCostDetails(SAvlTreeMethods.isUpdateAllowedMethod, 15), 1765, 1999 +: Seq.fill(3)(2001)) + def success[T](v: T) = Expected(Success(v), 1765, methodCostDetails(SAvlTreeMethods.isUpdateAllowedMethod, 15), 1765, Seq.fill(4)(2001)) Seq( (t1, success(true)), (t2, success(false)), @@ -2785,7 +2785,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( { - def success[T](v: T) = Expected(Success(v), 1765, methodCostDetails(SAvlTreeMethods.isRemoveAllowedMethod, 15), 1765, 1999 +: Seq.fill(3)(2001)) + def success[T](v: T) = Expected(Success(v), 1765, methodCostDetails(SAvlTreeMethods.isRemoveAllowedMethod, 15), 1765, Seq.fill(4)(2001)) Seq( (t1, success(true)), (t2, success(false)), @@ -3040,7 +3040,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => ) ) - getMany.checkExpected(input, Expected(Success(expRes), 1845, costDetails, 1845, 2135 +: Seq.fill(3)(2139))) + getMany.checkExpected(input, Expected(Success(expRes), 1845, costDetails, 1845, Seq.fill(4)(2139))) } val key = Colls.fromArray(Array[Byte](-16,-128,99,86,1,-128,-36,-83,109,72,-124,-114,1,-32,15,127,-30,125,127,1,-102,-53,-53,-128,-107,0,64,8,1,127,22,1)) @@ -3118,7 +3118,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => // positive test { val input = (tree, (key, proof)) - val expectedV3Costs: Seq[Int] = 2078 +: Seq.fill(3)(2082) + val expectedV3Costs: Seq[Int] = Seq.fill(4)(2082) contains.checkExpected(input, Expected(Success(okContains), 1790, costDetails(105 + additionalDetails), 1790, expectedV3Costs)) get.checkExpected(input, Expected(Success(valueOpt), 1790 + additionalCost, costDetails(105 + additionalDetails), 1790 + additionalCost, expectedV3Costs.map(additionalCost + _))) } @@ -3128,7 +3128,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => { val input = (tree, (keys, proof)) - val expectedV3Costs: Seq[Int] = (2081 + additionalCost) +: Seq.fill(3)(2085 + additionalCost) + val expectedV3Costs: Seq[Int] = Seq.fill(4)(2085 + additionalCost) getMany.checkExpected(input, Expected(Success(expRes), 1791 + additionalCost, costDetails(105 + additionalDetails), 1791 + additionalCost, expectedV3Costs)) } @@ -3136,7 +3136,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => val input = (tree, digest) val (res, _) = updateDigest.checkEquality(input).getOrThrow res.digest shouldBe digest - updateDigest.checkExpected(input, Expected(Success(res), 1771, updateDigestCostDetails, 1771, 2027 +: Seq.fill(3)(2029))) + updateDigest.checkExpected(input, Expected(Success(res), 1771, updateDigestCostDetails, 1771, Seq.fill(4)(2029))) } val newOps = 1.toByte @@ -3145,7 +3145,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => val input = (tree, newOps) val (res,_) = updateOperations.checkEquality(input).getOrThrow res.enabledOperations shouldBe newOps - updateOperations.checkExpected(input, Expected(Success(res), 1771, updateOperationsCostDetails, 1771, 2023 +: Seq.fill(3)(2025))) + updateOperations.checkExpected(input, Expected(Success(res), 1771, updateOperationsCostDetails, 1771, Seq.fill(4)(2025))) } // negative tests: invalid proof @@ -3155,7 +3155,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => val input = (tree, (key, invalidProof)) val (res, _) = contains.checkEquality(input).getOrThrow res shouldBe false - contains.checkExpected(input, Expected(Success(res), 1790, costDetails(105 + additionalDetails), 1790, 2078 +: Seq.fill(3)(2082))) + contains.checkExpected(input, Expected(Success(res), 1790, costDetails(105 + additionalDetails), 1790, Seq.fill(4)(2082))) } { @@ -3308,7 +3308,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => val input = (preInsertTree, (kvs, insertProof)) val (res, _) = insert.checkEquality(input).getOrThrow res.isDefined shouldBe true - insert.checkExpected(input, Expected(Success(res), 1796, costDetails2, 1796, 2098 +: Seq.fill(3)(2102))) + insert.checkExpected(input, Expected(Success(res), 1796, costDetails2, 1796, Seq.fill(4)(2102))) } { // negative: readonly tree @@ -3316,7 +3316,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => val input = (readonlyTree, (kvs, insertProof)) val (res, _) = insert.checkEquality(input).getOrThrow res.isDefined shouldBe false - insert.checkExpected(input, Expected(Success(res), 1772, costDetails1, 1772, 2074 +: Seq.fill(3)(2078))) + insert.checkExpected(input, Expected(Success(res), 1772, costDetails1, 1772, Seq.fill(4)(2078))) } { // negative: invalid key @@ -3326,7 +3326,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => val input = (tree, (invalidKvs, insertProof)) val (res, _) = insert.checkEquality(input).getOrThrow res.isDefined shouldBe true // TODO v6.0: should it really be true? (looks like a bug) (see https://github.com/ScorexFoundation/sigmastate-interpreter/issues/908) - insert.checkExpected(input, Expected(Success(res), 1796, costDetails2, 1796, 2098 +: Seq.fill(3)(2102))) + insert.checkExpected(input, Expected(Success(res), 1796, costDetails2, 1796, Seq.fill(4)(2102))) } { // negative: invalid proof @@ -3456,7 +3456,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => val endTree = preUpdateTree.updateDigest(endDigest) val input = (preUpdateTree, (kvs, updateProof)) val res = Some(endTree) - update.checkExpected(input, Expected(Success(res), 1805, costDetails2, 1805, 2107 +: Seq.fill(3)(2111))) + update.checkExpected(input, Expected(Success(res), 1805, costDetails2, 1805, Seq.fill(4)(2111))) } { // positive: update to the same value (identity operation) @@ -3464,13 +3464,13 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => val keys = Colls.fromItems((key -> value)) val input = (tree, (keys, updateProof)) val res = Some(tree) - update.checkExpected(input, Expected(Success(res), 1805, costDetails2, 1805, 2107 +: Seq.fill(3)(2111))) + update.checkExpected(input, Expected(Success(res), 1805, costDetails2, 1805, Seq.fill(4)(2111))) } { // negative: readonly tree val readonlyTree = createTree(preUpdateDigest) val input = (readonlyTree, (kvs, updateProof)) - update.checkExpected(input, Expected(Success(None), 1772, costDetails1, 1772, 2074 +: Seq.fill(3)(2078))) + update.checkExpected(input, Expected(Success(None), 1772, costDetails1, 1772, Seq.fill(4)(2078))) } { // negative: invalid key @@ -3478,7 +3478,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => val invalidKey = key.map(x => (-x).toByte) // any other different from key val invalidKvs = Colls.fromItems((invalidKey -> newValue)) val input = (tree, (invalidKvs, updateProof)) - update.checkExpected(input, Expected(Success(None), 1801, costDetails3, 1801, 2103 +: Seq.fill(3)(2107))) + update.checkExpected(input, Expected(Success(None), 1801, costDetails3, 1801, Seq.fill(4)(2107))) } { // negative: invalid value (different from the value in the proof) @@ -3488,14 +3488,14 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => val input = (tree, (invalidKvs, updateProof)) val (res, _) = update.checkEquality(input).getOrThrow res.isDefined shouldBe true // TODO v6.0: should it really be true? (looks like a bug) (see https://github.com/ScorexFoundation/sigmastate-interpreter/issues/908) - update.checkExpected(input, Expected(Success(res), 1805, costDetails2, 1805, 2107 +: Seq.fill(3)(2111))) + update.checkExpected(input, Expected(Success(res), 1805, costDetails2, 1805, Seq.fill(4)(2111))) } { // negative: invalid proof val tree = createTree(preUpdateDigest, updateAllowed = true) val invalidProof = updateProof.map(x => (-x).toByte) // any other different from proof val input = (tree, (kvs, invalidProof)) - update.checkExpected(input, Expected(Success(None), 1801, costDetails3, 1801, 2103 +: Seq.fill(3)(2107))) + update.checkExpected(input, Expected(Success(None), 1801, costDetails3, 1801, Seq.fill(4)(2107))) } } @@ -3606,7 +3606,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => val endTree = preRemoveTree.updateDigest(endDigest) val input = (preRemoveTree, (Colls.fromArray(keysToRemove), removeProof)) val res = Some(endTree) - remove.checkExpected(input, Expected(Success(res), 1832, costDetails1, 1832, 2122 +: Seq.fill(3)(2126))) + remove.checkExpected(input, Expected(Success(res), 1832, costDetails1, 1832, Seq.fill(4)(2126))) } { @@ -3623,13 +3623,13 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => val endTree = preRemoveTree.updateDigest(endDigest) val input = (preRemoveTree, (keys, removeProof)) val res = Some(endTree) - remove.checkExpected(input, Expected(Success(res), 1806, costDetails2, 1806, 2096 +: Seq.fill(3)(2100))) + remove.checkExpected(input, Expected(Success(res), 1806, costDetails2, 1806, Seq.fill(4)(2100))) } { // negative: readonly tree val readonlyTree = createTree(preRemoveDigest) val input = (readonlyTree, (keys, removeProof)) - remove.checkExpected(input, Expected(Success(None), 1772, costDetails3, 1772, 2062 +: Seq.fill(3)(2066))) + remove.checkExpected(input, Expected(Success(None), 1772, costDetails3, 1772, Seq.fill(4)(2066))) } { // negative: invalid key @@ -3637,14 +3637,14 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => val invalidKey = key.map(x => (-x).toByte) // any other different from `key` val invalidKeys = Colls.fromItems(invalidKey) val input = (tree, (invalidKeys, removeProof)) - remove.checkExpected(input, Expected(Success(None), 1802, costDetails4, 1802, 2092 +: Seq.fill(3)(2096))) + remove.checkExpected(input, Expected(Success(None), 1802, costDetails4, 1802, Seq.fill(4)(2096))) } { // negative: invalid proof val tree = createTree(preRemoveDigest, removeAllowed = true) val invalidProof = removeProof.map(x => (-x).toByte) // any other different from `removeProof` val input = (tree, (keys, invalidProof)) - remove.checkExpected(input, Expected(Success(None), 1802, costDetails4, 1802, 2092 +: Seq.fill(3)(2096))) + remove.checkExpected(input, Expected(Success(None), 1802, costDetails4, 1802, Seq.fill(4)(2096))) } } } @@ -3653,7 +3653,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => val costDetails = CostDetails(traceBase :+ FixedCostItem(CompanionDesc(LongToByteArray), FixedCost(JitCost(17)))) verifyCases( { - def success[T](v: T) = Expected(Success(v), 1767, costDetails, 1767, 1997 +: Seq.fill(3)(1999)) + def success[T](v: T) = Expected(Success(v), 1767, costDetails, 1767, Seq.fill(4)(1999)) Seq( (-9223372036854775808L, success(Helpers.decodeBytes("8000000000000000"))), (-1148502660425090565L, success(Helpers.decodeBytes("f00fb2ea55c579fb"))), @@ -3673,7 +3673,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => val costDetails = CostDetails(traceBase :+ FixedCostItem(CompanionDesc(ByteArrayToBigInt), FixedCost(JitCost(30)))) verifyCases( { - def success[T](v: T) = Expected(Success(v), 1767, costDetails, 1767, 1997 +: Seq.fill(3)(1999)) + def success[T](v: T) = Expected(Success(v), 1767, costDetails, 1767, Seq.fill(4)(1999)) Seq( (Helpers.decodeBytes(""), Expected(new NumberFormatException("Zero length BigInteger"))), @@ -3684,9 +3684,9 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => (Helpers.decodeBytes("ff"), success(CBigInt(new BigInteger("-1", 16)))), (Helpers.decodeBytes("80d6c201"), - Expected(Success(CBigInt(new BigInteger("-7f293dff", 16))), 1767, costDetails, 1767, 1997 +: Seq.fill(3)(1999))), + Expected(Success(CBigInt(new BigInteger("-7f293dff", 16))), 1767, costDetails, 1767, Seq.fill(4)(1999))), (Helpers.decodeBytes("70d6c20170d6c201"), - Expected(Success(CBigInt(new BigInteger("70d6c20170d6c201", 16))), 1767, costDetails, 1767, 1997 +: Seq.fill(3)(1999))), + Expected(Success(CBigInt(new BigInteger("70d6c20170d6c201", 16))), 1767, costDetails, 1767, Seq.fill(4)(1999))), (Helpers.decodeBytes( "80e0ff7f02807fff72807f0a00ff7fb7c57f75c11ba2802970fd250052807fc37f6480ffff007fff18eeba44" ), Expected(new ArithmeticException("BigInteger out of 256 bit range"))) @@ -3701,7 +3701,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => val costDetails = CostDetails(traceBase :+ FixedCostItem(CompanionDesc(ByteArrayToLong), FixedCost(JitCost(16)))) verifyCases( { - def success[T](v: T) = Expected(Success(v), 1765, costDetails, 1765, 1995 +: Seq.fill(3)(1997)) + def success[T](v: T) = Expected(Success(v), 1765, costDetails, 1765, Seq.fill(4)(1997)) Seq( (Helpers.decodeBytes(""), Expected(new IllegalArgumentException("array too small: 0 < 8"))), (Helpers.decodeBytes("81"), Expected(new IllegalArgumentException("array too small: 1 < 8"))), @@ -3723,7 +3723,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( { val costDetails = CostDetails(traceBase :+ FixedCostItem(CompanionDesc(ExtractId), FixedCost(JitCost(12)))) - def success[T](v: T) = Expected(Success(v), 1766, costDetails, 1766, 1996 +: Seq.fill(3)(1998)) + def success[T](v: T) = Expected(Success(v), 1766, costDetails, 1766, Seq.fill(4)(1998)) Seq( (b1, success(Helpers.decodeBytes("5ee78f30ae4e770e44900a46854e9fecb6b12e8112556ef1cd19aef633b4421e"))), (b2, success(Helpers.decodeBytes("3a0089be265460e29ca47d26e5b55a6f3e3ffaf5b4aed941410a2437913848ad"))) @@ -3736,7 +3736,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( { val costDetails = CostDetails(traceBase :+ FixedCostItem(CompanionDesc(ExtractAmount), FixedCost(JitCost(8)))) - def success[T](v: T) = Expected(Success(v), 1764, costDetails, 1764, 1994 +: Seq.fill(3)(1996)) + def success[T](v: T) = Expected(Success(v), 1764, costDetails, 1764, Seq.fill(4)(1996)) Seq( (b1, success(9223372036854775807L)), (b2, success(12345L)) @@ -3749,7 +3749,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( { val costDetails = CostDetails(traceBase :+ FixedCostItem(CompanionDesc(ExtractScriptBytes), FixedCost(JitCost(10)))) - def success[T](v: T) = Expected(Success(v), 1766, costDetails, 1766, 1996 +: Seq.fill(3)(1998)) + def success[T](v: T) = Expected(Success(v), 1766, costDetails, 1766, Seq.fill(4)(1998)) Seq( (b1, success(Helpers.decodeBytes( "100108cd0297c44a12f4eb99a85d298fa3ba829b5b42b9f63798c980ece801cc663cc5fc9e7300" @@ -3764,7 +3764,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( { val costDetails = CostDetails(traceBase :+ FixedCostItem(CompanionDesc(ExtractBytes), FixedCost(JitCost(12)))) - def success[T](v: T) = Expected(Success(v), 1766, costDetails, 1766, 1996 +: Seq.fill(3)(1998)) + def success[T](v: T) = Expected(Success(v), 1766, costDetails, 1766, Seq.fill(4)(1998)) Seq( (b1, success(Helpers.decodeBytes( "ffffffffffffffff7f100108cd0297c44a12f4eb99a85d298fa3ba829b5b42b9f63798c980ece801cc663cc5fc9e73009fac29026e789ab7b2fffff12280a6cd01557f6fb22b7f80ff7aff8e1f7f15973d7f000180ade204a3ff007f00057600808001ff8f8000019000ffdb806fff7cc0b6015eb37fa600f4030201000e067fc87f7f01ff218301ae8000018008637f0021fb9e00018055486f0b514121016a00ff718080bcb001" @@ -3781,7 +3781,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( { val costDetails = CostDetails(traceBase :+ FixedCostItem(CompanionDesc(ExtractBytesWithNoRef), FixedCost(JitCost(12)))) - def success[T](v: T) = Expected(Success(v), 1766, costDetails, 1766, 1996 +: Seq.fill(3)(1998)) + def success[T](v: T) = Expected(Success(v), 1766, costDetails, 1766, Seq.fill(4)(1998)) Seq( (b1, success(Helpers.decodeBytes( "ffffffffffffffff7f100108cd0297c44a12f4eb99a85d298fa3ba829b5b42b9f63798c980ece801cc663cc5fc9e73009fac29026e789ab7b2fffff12280a6cd01557f6fb22b7f80ff7aff8e1f7f15973d7f000180ade204a3ff007f00057600808001ff8f8000019000ffdb806fff7cc0b6015eb37fa600f4030201000e067fc87f7f01ff" @@ -3798,7 +3798,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( { val costDetails = CostDetails(traceBase :+ FixedCostItem(CompanionDesc(ExtractCreationInfo), FixedCost(JitCost(16)))) - def success[T](v: T) = Expected(Success(v), 1767, costDetails, 1767, 1999 +: Seq.fill(3)(2001)) + def success[T](v: T) = Expected(Success(v), 1767, costDetails, 1767, Seq.fill(4)(2001)) Seq( (b1, success(( 677407, @@ -3821,8 +3821,8 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => b1 -> Expected(Success(Coll[(Coll[Byte], Long)]( (Helpers.decodeBytes("6e789ab7b2fffff12280a6cd01557f6fb22b7f80ff7aff8e1f7f15973d7f0001"), 10000000L), (Helpers.decodeBytes("a3ff007f00057600808001ff8f8000019000ffdb806fff7cc0b6015eb37fa600"), 500L) - ).map(identity)), 1772, methodCostDetails(SBoxMethods.tokensMethod, 15), 1772, 2010 +: Seq.fill(3)(2012)), - b2 -> Expected(Success(Coll[(Coll[Byte], Long)]().map(identity)), 1766, methodCostDetails(SBoxMethods.tokensMethod, 15), 1766, 2004 +: Seq.fill(3)(2006)) + ).map(identity)), 1772, methodCostDetails(SBoxMethods.tokensMethod, 15), 1772, Seq.fill(4)(2012)), + b2 -> Expected(Success(Coll[(Coll[Byte], Long)]().map(identity)), 1766, methodCostDetails(SBoxMethods.tokensMethod, 15), 1766, Seq.fill(4)(2006)) ), existingFeature({ (x: Box) => x.tokens }, "{ (x: Box) => x.tokens }", @@ -3891,11 +3891,11 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( Seq( - (box1, Expected(Success(1024.toShort), 1774, expCostDetails1, 1774, 2038 +: Seq.fill(3)(2042))), + (box1, Expected(Success(1024.toShort), 1774, expCostDetails1, 1774, Seq.fill(4)(2042))), (box2, Expected( new InvalidType("Cannot getReg[Short](5): invalid type of value TestValue(1048576) at id=5") )), - (box3, Expected(Success(0.toShort), 1772, expCostDetails2, 1772, 2036 +: Seq.fill(3)(2040))) + (box3, Expected(Success(0.toShort), 1772, expCostDetails2, 1772, Seq.fill(4)(2040))) ), existingFeature( { (x: Box) => @@ -4020,10 +4020,10 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( Seq( - (box1, Expected(Success(1024), cost = 1785, expCostDetails3, 1785, 2125 +: Seq.fill(3)(2129))), - (box2, Expected(Success(1024 * 1024), cost = 1786, expCostDetails4, 1786, 2126 +: Seq.fill(3)(2130))), - (box3, Expected(Success(0), cost = 1779, expCostDetails5, 1779, 2119 +: Seq.fill(3)(2123))), - (box4, Expected(Success(-1), cost = 1772, expCostDetails2, 1772, 2112 +: Seq.fill(3)(2116))) + (box1, Expected(Success(1024), cost = 1785, expCostDetails3, 1785, Seq.fill(4)(2129))), + (box2, Expected(Success(1024 * 1024), cost = 1786, expCostDetails4, 1786, Seq.fill(4)(2130))), + (box3, Expected(Success(0), cost = 1779, expCostDetails5, 1779, Seq.fill(4)(2123))), + (box4, Expected(Success(-1), cost = 1772, expCostDetails2, 1772, Seq.fill(4)(2116))) ), existingFeature( { (x: Box) => @@ -4117,7 +4117,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => ) verifyCases( Seq( - (box1, Expected(Success(1.toByte), cost = 1770, expCostDetails, 1770, 2006 +: Seq.fill(3)(2008))), + (box1, Expected(Success(1.toByte), cost = 1770, expCostDetails, 1770, Seq.fill(4)(2008))), (box2, Expected(new InvalidType("Cannot getReg[Byte](4): invalid type of value Value(Coll(1)) at id=4"))) ), existingFeature((x: Box) => x.R4[Byte].get, @@ -4129,7 +4129,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( Seq( - (box1, Expected(Success(1024.toShort), cost = 1770, expCostDetails, 1770, 2006 +: Seq.fill(3)(2008))), + (box1, Expected(Success(1024.toShort), cost = 1770, expCostDetails, 1770, Seq.fill(4)(2008))), (box2, Expected(new NoSuchElementException("None.get"))) ), existingFeature((x: Box) => x.R5[Short].get, @@ -4141,7 +4141,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( Seq( - (box1, Expected(Success(1024 * 1024), cost = 1770, expCostDetails, 1770, 2006 +: Seq.fill(3)(2008))) + (box1, Expected(Success(1024 * 1024), cost = 1770, expCostDetails, 1770, Seq.fill(4)(2008))) ), existingFeature((x: Box) => x.R6[Int].get, "{ (x: Box) => x.R6[Int].get }", @@ -4152,7 +4152,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( Seq( - (box1, Expected(Success(1024.toLong), cost = 1770, expCostDetails, 1770, 2006 +: Seq.fill(3)(2008))) + (box1, Expected(Success(1024.toLong), cost = 1770, expCostDetails, 1770, Seq.fill(4)(2008))) ), existingFeature((x: Box) => x.R7[Long].get, "{ (x: Box) => x.R7[Long].get }", @@ -4163,7 +4163,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( Seq( - (box1, Expected(Success(CBigInt(BigInteger.valueOf(222L))), cost = 1770, expCostDetails, 1770, 2006 +: Seq.fill(3)(2008))) + (box1, Expected(Success(CBigInt(BigInteger.valueOf(222L))), cost = 1770, expCostDetails, 1770, Seq.fill(4)(2008))) ), existingFeature((x: Box) => x.R8[BigInt].get, "{ (x: Box) => x.R8[BigInt].get }", @@ -4184,7 +4184,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => )), cost = 1770, expCostDetails, - 1770, 2006 +: Seq.fill(3)(2008)) + 1770, Seq.fill(4)(2008)) )), existingFeature((x: Box) => x.R9[AvlTree].get, "{ (x: Box) => x.R9[AvlTree].get }", @@ -4257,35 +4257,35 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( - Seq((preH1, Expected(Success(0.toByte), cost = 1765, methodCostDetails(SPreHeaderMethods.versionMethod, 10), 1765, 1999 +: Seq.fill(3)(2001)))), + Seq((preH1, Expected(Success(0.toByte), cost = 1765, methodCostDetails(SPreHeaderMethods.versionMethod, 10), 1765, Seq.fill(4)(2001)))), existingPropTest("version", { (x: PreHeader) => x.version })) verifyCases( Seq((preH1, Expected(Success( Helpers.decodeBytes("7fff7fdd6f62018bae0001006d9ca888ff7f56ff8006573700a167f17f2c9f40")), - cost = 1766, methodCostDetails(SPreHeaderMethods.parentIdMethod, 10), 1766, 2000 +: Seq.fill(3)(2002)))), + cost = 1766, methodCostDetails(SPreHeaderMethods.parentIdMethod, 10), 1766, Seq.fill(4)(2002)))), existingPropTest("parentId", { (x: PreHeader) => x.parentId })) verifyCases( - Seq((preH1, Expected(Success(6306290372572472443L), cost = 1765, methodCostDetails(SPreHeaderMethods.timestampMethod, 10), 1765, 1999 +: Seq.fill(3)(2001)))), + Seq((preH1, Expected(Success(6306290372572472443L), cost = 1765, methodCostDetails(SPreHeaderMethods.timestampMethod, 10), 1765, Seq.fill(4)(2001)))), existingPropTest("timestamp", { (x: PreHeader) => x.timestamp })) verifyCases( - Seq((preH1, Expected(Success(-3683306095029417063L), cost = 1765, methodCostDetails(SPreHeaderMethods.nBitsMethod, 10), 1765, 1999 +: Seq.fill(3)(2001)))), + Seq((preH1, Expected(Success(-3683306095029417063L), cost = 1765, methodCostDetails(SPreHeaderMethods.nBitsMethod, 10), 1765, Seq.fill(4)(2001)))), existingPropTest("nBits", { (x: PreHeader) => x.nBits })) verifyCases( - Seq((preH1, Expected(Success(1), cost = 1765, methodCostDetails(SPreHeaderMethods.heightMethod, 10), 1765, 1999 +: Seq.fill(3)(2001)))), + Seq((preH1, Expected(Success(1), cost = 1765, methodCostDetails(SPreHeaderMethods.heightMethod, 10), 1765, Seq.fill(4)(2001)))), existingPropTest("height", { (x: PreHeader) => x.height })) verifyCases( Seq((preH1, Expected(Success( Helpers.decodeGroupElement("026930cb9972e01534918a6f6d6b8e35bc398f57140d13eb3623ea31fbd069939b")), - cost = 1782, methodCostDetails(SPreHeaderMethods.minerPkMethod, 10), 1782, 2016 +: Seq.fill(3)(2018)))), + cost = 1782, methodCostDetails(SPreHeaderMethods.minerPkMethod, 10), 1782, Seq.fill(4)(2018)))), existingPropTest("minerPk", { (x: PreHeader) => x.minerPk })) verifyCases( - Seq((preH1, Expected(Success(Helpers.decodeBytes("ff8087")), cost = 1766, methodCostDetails(SPreHeaderMethods.votesMethod, 10), 1766, 2000 +: Seq.fill(3)(2002)))), + Seq((preH1, Expected(Success(Helpers.decodeBytes("ff8087")), cost = 1766, methodCostDetails(SPreHeaderMethods.votesMethod, 10), 1766, Seq.fill(4)(2002)))), existingPropTest("votes", { (x: PreHeader) => x.votes })) } @@ -4293,81 +4293,81 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( Seq((h1, Expected(Success( Helpers.decodeBytes("957f008001808080ffe4ffffc8f3802401df40006aa05e017fa8d3f6004c804a")), - cost = 1766, methodCostDetails(SHeaderMethods.idMethod, 10), 1766, 2000 +: Seq.fill(3)(2002)))), + cost = 1766, methodCostDetails(SHeaderMethods.idMethod, 10), 1766, Seq.fill(4)(2002)))), existingPropTest("id", { (x: Header) => x.id })) verifyCases( - Seq((h1, Expected(Success(0.toByte), cost = 1765, methodCostDetails(SHeaderMethods.versionMethod, 10), 1765, 1999 +: Seq.fill(3)(2001)))), + Seq((h1, Expected(Success(0.toByte), cost = 1765, methodCostDetails(SHeaderMethods.versionMethod, 10), 1765, Seq.fill(4)(2001)))), existingPropTest("version", { (x: Header) => x.version })) verifyCases( Seq((h1, Expected(Success( Helpers.decodeBytes("0180dd805b0000ff5400b997fd7f0b9b00de00fb03c47e37806a8186b94f07ff")), - cost = 1766, methodCostDetails(SHeaderMethods.parentIdMethod, 10), 1766, 2000 +: Seq.fill(3)(2002)))), + cost = 1766, methodCostDetails(SHeaderMethods.parentIdMethod, 10), 1766, Seq.fill(4)(2002)))), existingPropTest("parentId", { (x: Header) => x.parentId })) verifyCases( Seq((h1, Expected(Success( Helpers.decodeBytes("01f07f60d100ffb970c3007f60ff7f24d4070bb8fffa7fca7f34c10001ffe39d")), - cost = 1766, methodCostDetails(SHeaderMethods.ADProofsRootMethod, 10), 1766, 2000 +: Seq.fill(3)(2002)))), + cost = 1766, methodCostDetails(SHeaderMethods.ADProofsRootMethod, 10), 1766, Seq.fill(4)(2002)))), existingPropTest("ADProofsRoot", { (x: Header) => x.ADProofsRoot })) verifyCases( - Seq((h1, Expected(Success(CAvlTree(createAvlTreeData())), cost = 1765, methodCostDetails(SHeaderMethods.stateRootMethod, 10), 1765, 1999 +: Seq.fill(3)(2001)))), + Seq((h1, Expected(Success(CAvlTree(createAvlTreeData())), cost = 1765, methodCostDetails(SHeaderMethods.stateRootMethod, 10), 1765, Seq.fill(4)(2001)))), existingPropTest("stateRoot", { (x: Header) => x.stateRoot })) verifyCases( Seq((h1, Expected(Success( Helpers.decodeBytes("804101ff01000080a3ffbd006ac080098df132a7017f00649311ec0e00000100")), - cost = 1766, methodCostDetails(SHeaderMethods.transactionsRootMethod, 10), 1766, 2000 +: Seq.fill(3)(2002)))), + cost = 1766, methodCostDetails(SHeaderMethods.transactionsRootMethod, 10), 1766, Seq.fill(4)(2002)))), existingPropTest("transactionsRoot", { (x: Header) => x.transactionsRoot })) verifyCases( - Seq((h1, Expected(Success(1L), cost = 1765, methodCostDetails(SHeaderMethods.timestampMethod, 10), 1765, 1999 +: Seq.fill(3)(2001)))), + Seq((h1, Expected(Success(1L), cost = 1765, methodCostDetails(SHeaderMethods.timestampMethod, 10), 1765, Seq.fill(4)(2001)))), existingPropTest("timestamp", { (x: Header) => x.timestamp })) verifyCases( - Seq((h1, Expected(Success(-1L), cost = 1765, methodCostDetails(SHeaderMethods.nBitsMethod, 10), 1765, 1999 +: Seq.fill(3)(2001)))), + Seq((h1, Expected(Success(-1L), cost = 1765, methodCostDetails(SHeaderMethods.nBitsMethod, 10), 1765, Seq.fill(4)(2001)))), existingPropTest("nBits", { (x: Header) => x.nBits })) verifyCases( - Seq((h1, Expected(Success(1), cost = 1765, methodCostDetails(SHeaderMethods.heightMethod, 10), 1765, 1999 +: Seq.fill(3)(2001)))), + Seq((h1, Expected(Success(1), cost = 1765, methodCostDetails(SHeaderMethods.heightMethod, 10), 1765, Seq.fill(4)(2001)))), existingPropTest("height", { (x: Header) => x.height })) verifyCases( Seq((h1, Expected(Success( Helpers.decodeBytes("e57f80885601b8ff348e01808000bcfc767f2dd37f0d01015030ec018080bc62")), - cost = 1766, methodCostDetails(SHeaderMethods.extensionRootMethod, 10), 1766, 2000 +: Seq.fill(3)(2002)))), + cost = 1766, methodCostDetails(SHeaderMethods.extensionRootMethod, 10), 1766, Seq.fill(4)(2002)))), existingPropTest("extensionRoot", { (x: Header) => x.extensionRoot })) verifyCases( Seq((h1, Expected(Success( Helpers.decodeGroupElement("039bdbfa0b49cc6bef58297a85feff45f7bbeb500a9d2283004c74fcedd4bd2904")), - cost = 1782, methodCostDetails(SHeaderMethods.minerPkMethod, 10), 1782, 2016 +: Seq.fill(3)(2018)))), + cost = 1782, methodCostDetails(SHeaderMethods.minerPkMethod, 10), 1782, Seq.fill(4)(2018)))), existingPropTest("minerPk", { (x: Header) => x.minerPk })) verifyCases( Seq((h1, Expected(Success( Helpers.decodeGroupElement("0361299207fa392231e23666f6945ae3e867b978e021d8d702872bde454e9abe9c")), - cost = 1782, methodCostDetails(SHeaderMethods.powOnetimePkMethod, 10), 1782, 2016 +: Seq.fill(3)(2018)))), + cost = 1782, methodCostDetails(SHeaderMethods.powOnetimePkMethod, 10), 1782, Seq.fill(4)(2018)))), existingPropTest("powOnetimePk", { (x: Header) => x.powOnetimePk })) verifyCases( Seq((h1, Expected(Success( Helpers.decodeBytes("7f4f09012a807f01")), - cost = 1766, methodCostDetails(SHeaderMethods.powNonceMethod, 10), 1766, 2000 +: Seq.fill(3)(2002)))), + cost = 1766, methodCostDetails(SHeaderMethods.powNonceMethod, 10), 1766, Seq.fill(4)(2002)))), existingPropTest("powNonce", { (x: Header) => x.powNonce })) verifyCases( Seq((h1, Expected(Success( CBigInt(new BigInteger("-e24990c47e15ed4d0178c44f1790cc72155d516c43c3e8684e75db3800a288", 16))), - cost = 1765, methodCostDetails(SHeaderMethods.powDistanceMethod, 10), 1765, 1999 +: Seq.fill(3)(2001)))), + cost = 1765, methodCostDetails(SHeaderMethods.powDistanceMethod, 10), 1765, Seq.fill(4)(2001)))), existingPropTest("powDistance", { (x: Header) => x.powDistance })) verifyCases( Seq((h1, Expected(Success( Helpers.decodeBytes("7f0180")), - cost = 1766, methodCostDetails(SHeaderMethods.votesMethod, 10), 1766, 2000 +: Seq.fill(3)(2002)))), + cost = 1766, methodCostDetails(SHeaderMethods.votesMethod, 10), 1766, Seq.fill(4)(2002)))), existingPropTest("votes", { (x: Header) => x.votes })) } @@ -4581,7 +4581,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => val costDetails = TracedCost(testTraceBase) verifyCases( Seq( - (ctx, Expected(Success(dataBox), cost = 1769, costDetails, 1769, 2015 +: Seq.fill(3)(2017))), + (ctx, Expected(Success(dataBox), cost = 1769, costDetails, 1769, Seq.fill(4)(2017))), (ctx.copy(_dataInputs = Coll()), Expected(new ArrayIndexOutOfBoundsException("0"))) ), existingFeature({ (x: Context) => x.dataInputs(0) }, @@ -4606,7 +4606,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => Seq( (ctx, Expected(Success( Helpers.decodeBytes("7da4b55971f19a78d007638464580f91a020ab468c0dbe608deb1f619e245bc3")), - cost = 1772, idCostDetails, 1772, 2020 +: Seq.fill(3)(2022))) + cost = 1772, idCostDetails, 1772, Seq.fill(4)(2022))) ), existingFeature({ (x: Context) => x.dataInputs(0).id }, "{ (x: Context) => x.dataInputs(0).id }", @@ -4667,7 +4667,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => ) ) verifyCases( - Seq(ctx -> Expected(Success(ctx.HEIGHT), cost = 1766, heightCostDetails, 1766, 1992 +: Seq.fill(3)(1994))), + Seq(ctx -> Expected(Success(ctx.HEIGHT), cost = 1766, heightCostDetails, 1766, Seq.fill(4)(1994))), existingFeature( { (x: Context) => x.HEIGHT }, "{ (x: Context) => x.HEIGHT }", @@ -4704,7 +4704,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => )) verifyCases( - Seq((ctx, Expected(Success(Coll[Long](80946L)), cost = 1770, inputsCostDetails1, 1770, 2012 +: Seq.fill(3)(2014)))), + Seq((ctx, Expected(Success(Coll[Long](80946L)), cost = 1770, inputsCostDetails1, 1770, Seq.fill(4)(2014)))), existingFeature( { (x: Context) => x.INPUTS.map { (b: Box) => b.value } }, "{ (x: Context) => x.INPUTS.map { (b: Box) => b.value } }", @@ -4764,7 +4764,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => ) ) verifyCases( - Seq((ctx, Expected(Success(Coll((80946L, 80946L))), cost = 1774, inputsCostDetails2, 1774, 2038 +: Seq.fill(3)(2042)))), + Seq((ctx, Expected(Success(Coll((80946L, 80946L))), cost = 1774, inputsCostDetails2, 1774, Seq.fill(4)(2042)))), existingFeature( { (x: Context) => x.INPUTS.map { (b: Box) => (b.value, b.value) } }, """{ (x: Context) => @@ -4856,7 +4856,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => expectedDetails = CostDetails.ZeroCost, newCost = 1766, newVersionedResults = { - val expectedV3Costs = 2000 +: Seq.fill(3)(2002) + val expectedV3Costs = Seq.fill(4)(2002) // V3 activation will have different costs due to deserialization cost val costs = if (activatedVersionInTests >= V6SoftForkVersion) { expectedV3Costs @@ -4895,7 +4895,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => } verifyCases( - Seq(ctx -> Expected(Success(ctx.LastBlockUtxoRootHash), cost = 1766, methodCostDetails(SContextMethods.lastBlockUtxoRootHashMethod, 15), 1766, 2000 +: Seq.fill(3)(2002))), + Seq(ctx -> Expected(Success(ctx.LastBlockUtxoRootHash), cost = 1766, methodCostDetails(SContextMethods.lastBlockUtxoRootHashMethod, 15), 1766, Seq.fill(4)(2002))), existingPropTest("LastBlockUtxoRootHash", { (x: Context) => x.LastBlockUtxoRootHash }), preGeneratedSamples = Some(samples)) @@ -4908,7 +4908,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => ) ) verifyCases( - Seq(ctx -> Expected(Success(ctx.LastBlockUtxoRootHash.isUpdateAllowed), cost = 1767, isUpdateAllowedCostDetails, 1767, 2007 +: Seq.fill(3)(2009))), + Seq(ctx -> Expected(Success(ctx.LastBlockUtxoRootHash.isUpdateAllowed), cost = 1767, isUpdateAllowedCostDetails, 1767, Seq.fill(4)(2009))), existingFeature( { (x: Context) => x.LastBlockUtxoRootHash.isUpdateAllowed }, "{ (x: Context) => x.LastBlockUtxoRootHash.isUpdateAllowed }", @@ -4929,7 +4929,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => preGeneratedSamples = Some(samples)) verifyCases( - Seq(ctx -> Expected(Success(ctx.minerPubKey), cost = 1767, methodCostDetails(SContextMethods.minerPubKeyMethod, 20), 1767, 2001 +: Seq.fill(3)(2003))), + Seq(ctx -> Expected(Success(ctx.minerPubKey), cost = 1767, methodCostDetails(SContextMethods.minerPubKeyMethod, 20), 1767, Seq.fill(4)(2003))), existingPropTest("minerPubKey", { (x: Context) => x.minerPubKey }), preGeneratedSamples = Some(samples)) @@ -4969,7 +4969,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => FixedCostItem(GetVar), FixedCostItem(OptionGet))) verifyCases( - Seq((ctx, Expected(Success(true), cost = 1765, getVarCostDetails, 1765, 1997 +: Seq.fill(3)(1999)))), + Seq((ctx, Expected(Success(true), cost = 1765, getVarCostDetails, 1765, Seq.fill(4)(1999)))), existingFeature((x: Context) => x.getVar[Boolean](11).get, "{ (x: Context) => getVar[Boolean](11).get }", FuncValue(Vector((1, SContext)), OptionGet(GetVar(11.toByte, SOption(SBoolean))))), @@ -5003,7 +5003,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => ) verifyCases( Seq( - ctx -> Expected(Success(-135729055492651903L), 1779, registerIsDefinedCostDetails, 1779, 2061 +: Seq.fill(3)(2065)) + ctx -> Expected(Success(-135729055492651903L), 1779, registerIsDefinedCostDetails, 1779, Seq.fill(4)(2065)) ), existingFeature( { (x: Context) => @@ -5065,7 +5065,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => Seq( ctx -> Expected(Failure(expectedError), 0, CostDetails.ZeroCost, 1793, newVersionedResults = { - val expectedV3Costs = 2117 +: Seq.fill(3)(2121) + val expectedV3Costs = Seq.fill(4)(2121) // V3 activation will have different costs due to deserialization cost val costs = if (activatedVersionInTests >= V6SoftForkVersion) { expectedV3Costs @@ -5239,12 +5239,12 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => ) verifyCases( Seq( - ctx -> Expected(Success(5008366408131208436L), 1791, registerTagCostDetails1, 1791, 2149 +: Seq.fill(3)(2153)), + ctx -> Expected(Success(5008366408131208436L), 1791, registerTagCostDetails1, 1791, Seq.fill(4)(2153)), ctxWithRegsInOutput(ctx, Map( ErgoBox.R5 -> LongConstant(0L), - ErgoBox.R4 -> ShortConstant(10))) -> Expected(Success(10L), 1790, registerTagCostDetails2, 1790, 2148 +: Seq.fill(3)(2152)), + ErgoBox.R4 -> ShortConstant(10))) -> Expected(Success(10L), 1790, registerTagCostDetails2, 1790, Seq.fill(4)(2152)), ctxWithRegsInOutput(ctx, Map( - ErgoBox.R4 -> ShortConstant(10))) -> Expected(Success(-1L), 1777, registerTagCostDetails3, 1777, 2135 +: Seq.fill(3)(2139)) + ErgoBox.R4 -> ShortConstant(10))) -> Expected(Success(-1L), 1777, registerTagCostDetails3, 1777, Seq.fill(4)(2139)) ), existingFeature( { (x: Context) => @@ -5447,22 +5447,22 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( Seq( // case 1L - ctx -> Expected(Success(5008366408131289382L), 1794, tagRegisterCostDetails1, 1794, 2164 +: Seq.fill(3)(2168)), + ctx -> Expected(Success(5008366408131289382L), 1794, tagRegisterCostDetails1, 1794, Seq.fill(4)(2168)), // case 0L ctxWithRegsInOutput(ctx, Map( ErgoBox.R5 -> LongConstant(0L), - ErgoBox.R4 -> ShortConstant(10))) -> Expected(Success(80956L), 1793, tagRegisterCostDetails2, 1793, 2163 +: Seq.fill(3)(2167)), + ErgoBox.R4 -> ShortConstant(10))) -> Expected(Success(80956L), 1793, tagRegisterCostDetails2, 1793, Seq.fill(4)(2167)), // case returning 0L ctxWithRegsInOutput(ctx, Map( ErgoBox.R5 -> LongConstant(2L), // note R4 is required to avoid // "RuntimeException: Set of non-mandatory indexes is not densely packed" - ErgoBox.R4 -> ShortConstant(10))) -> Expected(Success(0L), 1784, tagRegisterCostDetails3, 1784, 2154 +: Seq.fill(3)(2158)), + ErgoBox.R4 -> ShortConstant(10))) -> Expected(Success(0L), 1784, tagRegisterCostDetails3, 1784, Seq.fill(4)(2158)), // case returning -1L ctxWithRegsInOutput(ctx, Map( - ErgoBox.R4 -> ShortConstant(10))) -> Expected(Success(-1L), 1777, tagRegisterCostDetails4, 1777, 2147 +: Seq.fill(3)(2151)) + ErgoBox.R4 -> ShortConstant(10))) -> Expected(Success(-1L), 1777, tagRegisterCostDetails4, 1777, Seq.fill(4)(2151)) ), existingFeature( { (x: Context) => @@ -5680,15 +5680,15 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => Seq( ctxWithRegsInDataInput(ctx, Map( ErgoBox.R5 -> LongConstant(1L), - ErgoBox.R4 -> LongConstant(10))) -> Expected(Success(10L), 1792, tagRegisterCostDetails1, 1792, 2158 +: Seq.fill(3)(2162)), + ErgoBox.R4 -> LongConstant(10))) -> Expected(Success(10L), 1792, tagRegisterCostDetails1, 1792, Seq.fill(4)(2162)), ctxWithRegsInDataInput(ctx, Map( ErgoBox.R5 -> LongConstant(0L), - ErgoBox.R4 -> ShortConstant(10))) -> Expected(Success(10L), 1791, tagRegisterCostDetails2, 1791, 2157 +: Seq.fill(3)(2161)), + ErgoBox.R4 -> ShortConstant(10))) -> Expected(Success(10L), 1791, tagRegisterCostDetails2, 1791, Seq.fill(4)(2161)), ctxWithRegsInDataInput(ctx, Map( ErgoBox.R5 -> LongConstant(2L), - ErgoBox.R4 -> ShortConstant(10))) -> Expected(Success(0L), 1786, tagRegisterCostDetails3, 1786, 2152 +: Seq.fill(3)(2156)), + ErgoBox.R4 -> ShortConstant(10))) -> Expected(Success(0L), 1786, tagRegisterCostDetails3, 1786, Seq.fill(4)(2156)), ctxWithRegsInDataInput(ctx, Map( - ErgoBox.R4 -> ShortConstant(10))) -> Expected(Success(-1L), 1779, tagRegisterCostDetails4, 1779, 2145 +: Seq.fill(3)(2149)) + ErgoBox.R4 -> ShortConstant(10))) -> Expected(Success(-1L), 1779, tagRegisterCostDetails4, 1779, Seq.fill(4)(2149)) ), existingFeature( { (x: Context) => @@ -5913,15 +5913,15 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => Seq( ctxWithRegsInDataInput(ctx, Map( ErgoBox.R5 -> LongConstant(1L), - ErgoBox.R4 -> LongConstant(10))) -> Expected(Success(80956L), 1796, costDetails1, 1796, 2174 +: Seq.fill(3)(2178)), + ErgoBox.R4 -> LongConstant(10))) -> Expected(Success(80956L), 1796, costDetails1, 1796, Seq.fill(4)(2178)), ctxWithRegsInDataInput(ctx, Map( ErgoBox.R5 -> LongConstant(0L), - ErgoBox.R4 -> ShortConstant(10))) -> Expected(Success(80956L), 1794, costDetails2, 1794, 2172 +: Seq.fill(3)(2176)), + ErgoBox.R4 -> ShortConstant(10))) -> Expected(Success(80956L), 1794, costDetails2, 1794, Seq.fill(4)(2176)), ctxWithRegsInDataInput(ctx, Map( ErgoBox.R5 -> LongConstant(2L), - ErgoBox.R4 -> ShortConstant(10))) -> Expected(Success(0L), 1786, costDetails3, 1786, 2164 +: Seq.fill(3)(2168)), + ErgoBox.R4 -> ShortConstant(10))) -> Expected(Success(0L), 1786, costDetails3, 1786, Seq.fill(4)(2168)), ctxWithRegsInDataInput(ctx, Map( - ErgoBox.R4 -> ShortConstant(10))) -> Expected(Success(-1L), 1779, costDetails4, 1779, 2157 +: Seq.fill(3)(2161)) + ErgoBox.R4 -> ShortConstant(10))) -> Expected(Success(-1L), 1779, costDetails4, 1779, Seq.fill(4)(2161)) ), existingFeature( { (x: Context) => @@ -6028,7 +6028,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => newCost = 1766, newVersionedResults = { val costs = if (activatedVersionInTests >= V6SoftForkVersion) { - 1996 +: Seq.fill(3)(1998) + Seq.fill(4)(1998) } else { Seq.fill(4)(1766) @@ -6070,8 +6070,8 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => val costDetails = TracedCost(traceBase :+ FixedCostItem(LogicalNot)) verifyCases( Seq( - (true, Expected(Success(false), 1765, costDetails, 1765, 1995 +: Seq.fill(3)(1997))), - (false, Expected(Success(true), 1765, costDetails, 1765, 1995 +: Seq.fill(3)(1997)))), + (true, Expected(Success(false), 1765, costDetails, 1765, Seq.fill(4)(1997))), + (false, Expected(Success(true), 1765, costDetails, 1765, Seq.fill(4)(1997)))), existingFeature((x: Boolean) => !x, "{ (x: Boolean) => !x }", FuncValue(Vector((1, SBoolean)), LogicalNot(ValUse(1, SBoolean))))) @@ -6081,7 +6081,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => val costDetails = TracedCost(traceBase :+ FixedCostItem(Negation)) verifyCases( { - def success[T](v: T) = Expected(Success(v), 1766, costDetails, 1766, 1996 +: Seq.fill(3)(1998)) + def success[T](v: T) = Expected(Success(v), 1766, costDetails, 1766, Seq.fill(4)(1998)) Seq( (Byte.MinValue, success(Byte.MinValue)), // !!! @@ -6101,7 +6101,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( { - def success[T](v: T) = Expected(Success(v), 1766, costDetails, 1766, 1996 +: Seq.fill(3)(1998)) + def success[T](v: T) = Expected(Success(v), 1766, costDetails, 1766, Seq.fill(4)(1998)) Seq( (Short.MinValue, success(Short.MinValue)), // special case! ((Short.MinValue + 1).toShort, success(Short.MaxValue)), @@ -6119,7 +6119,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( { - def success[T](v: T) = Expected(Success(v), 1766, costDetails, 1766, 1996 +: Seq.fill(3)(1998)) + def success[T](v: T) = Expected(Success(v), 1766, costDetails, 1766, Seq.fill(4)(1998)) Seq( (Int.MinValue, success(Int.MinValue)), // special case! @@ -6137,7 +6137,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( { - def success[T](v: T) = Expected(Success(v), 1766, costDetails, 1766, 1996 +: Seq.fill(3)(1998)) + def success[T](v: T) = Expected(Success(v), 1766, costDetails, 1766, Seq.fill(4)(1998)) Seq( (Long.MinValue, success(Long.MinValue)), // special case! @@ -6155,7 +6155,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( { - def success[T](v: T) = Expected(Success(v), 1767, costDetails, 1767, 1997 +: Seq.fill(3)(1999)) + def success[T](v: T) = Expected(Success(v), 1767, costDetails, 1767, Seq.fill(4)(1999)) Seq( (CBigInt(new BigInteger("-1655a05845a6ad363ac88ea21e88b97e436a1f02c548537e12e2d9667bf0680", 16)), success(CBigInt(new BigInteger("1655a05845a6ad363ac88ea21e88b97e436a1f02c548537e12e2d9667bf0680", 16)))), @@ -6194,7 +6194,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => ) verifyCases( { - def success[T](v: T) = Expected(Success(v), 1782, costDetails, 1782, 2014 +: Seq.fill(3)(2016)) + def success[T](v: T) = Expected(Success(v), 1782, costDetails, 1782, Seq.fill(4)(2016)) Seq( (-1, success(Helpers.decodeGroupElement("0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798"))), (1, success(Helpers.decodeGroupElement("0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798")))) @@ -6213,7 +6213,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( { - def success[T](v: T) = Expected(Success(v), 1782, costDetails, 1782, 2014 +: Seq.fill(3)(2016)) + def success[T](v: T) = Expected(Success(v), 1782, costDetails, 1782, Seq.fill(4)(2016)) Seq( (-1, success(Helpers.decodeGroupElement("0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798"))), (1, success(Helpers.decodeGroupElement("0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798")))) @@ -6239,7 +6239,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => ) verifyCases( { - def success[T](v: T) = Expected(Success(v), 1872, expCostDetails, 1872, 2110 +: Seq.fill(3)(2112)) + def success[T](v: T) = Expected(Success(v), 1872, expCostDetails, 1872, Seq.fill(4)(2112)) Seq( (CBigInt(new BigInteger("-e5c1a54694c85d644fa30a6fc5f3aa209ed304d57f72683a0ebf21038b6a9d", 16)), success(Helpers.decodeGroupElement("023395bcba3d7cf21d73c50f8af79d09a8c404c15ce9d04f067d672823bae91a54"))), @@ -6305,7 +6305,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( { - def success[T](v: T, cd: CostDetails) = Expected(Success(v), 1769, cd, 1769, 2019 +: Seq.fill(3)(2021)) + def success[T](v: T, cd: CostDetails) = Expected(Success(v), 1769, cd, 1769, Seq.fill(4)(2021)) Seq( ((Helpers.decodeBytes(""), Helpers.decodeBytes("")), success(Helpers.decodeBytes(""), costDetails(0))), ((Helpers.decodeBytes("01"), Helpers.decodeBytes("01")), success(Helpers.decodeBytes("00"), costDetails(1))), @@ -6318,7 +6318,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => newCost = 1769, newVersionedResults = { val costs = if (activatedVersionInTests >= V6SoftForkVersion) { - 2019 +: Seq.fill(3)(2021) + Seq.fill(4)(2021) } else { Seq.fill(4)(1769) } @@ -6470,9 +6470,9 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => { def success[T](v: T, c: Int, costDetails: CostDetails, newCost: Int, expectedV3Costs: Seq[Int]) = Expected(Success(v), c, costDetails, newCost, expectedV3Costs) Seq( - (Coll[Box](), success(Coll[Box](), 1767, costDetails, 1767, 2027 +: Seq.fill(3)(2031))), - (Coll[Box](b1), success(Coll[Box](), 1772, costDetails2, 1772, 2032 +: Seq.fill(3)(2036))), - (Coll[Box](b1, b2), success(Coll[Box](b2), 1776, costDetails3, 1776, 2036 +: Seq.fill(3)(2040))) + (Coll[Box](), success(Coll[Box](), 1767, costDetails, 1767, Seq.fill(4)(2031))), + (Coll[Box](b1), success(Coll[Box](), 1772, costDetails2, 1772, Seq.fill(4)(2036))), + (Coll[Box](b1, b2), success(Coll[Box](b2), 1776, costDetails3, 1776, Seq.fill(4)(2040))) ) }, existingFeature({ (x: Coll[Box]) => x.filter({ (b: Box) => b.value > 1 }) }, @@ -6525,13 +6525,13 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( { Seq( - (Coll[Box](), Expected(Success(Coll[Byte]()), 1773, costDetails1, 1773, 2027 +: Seq.fill(3)(2029))), + (Coll[Box](), Expected(Success(Coll[Byte]()), 1773, costDetails1, 1773, Seq.fill(4)(2029))), (Coll[Box](b1), Expected(Success(Helpers.decodeBytes( "0008ce02c1a9311ecf1e76c787ba4b1c0e10157b4f6d1e4db3ef0d84f411c99f2d4d2c5b027d1bd9a437e73726ceddecc162e5c85f79aee4798505bc826b8ad1813148e4190257cff6d06fe15d1004596eeb97a7f67755188501e36adc49bd807fe65e9d8281033c6021cff6ba5fdfc4f1742486030d2ebbffd9c9c09e488792f3102b2dcdabd5" - )), 1791, costDetails2, 1791, 2045 +: Seq.fill(3)(2047))), + )), 1791, costDetails2, 1791, Seq.fill(4)(2047))), (Coll[Box](b1, b2), Expected(Success(Helpers.decodeBytes( "0008ce02c1a9311ecf1e76c787ba4b1c0e10157b4f6d1e4db3ef0d84f411c99f2d4d2c5b027d1bd9a437e73726ceddecc162e5c85f79aee4798505bc826b8ad1813148e4190257cff6d06fe15d1004596eeb97a7f67755188501e36adc49bd807fe65e9d8281033c6021cff6ba5fdfc4f1742486030d2ebbffd9c9c09e488792f3102b2dcdabd500d197830201010096850200" - )), 1795, costDetails3, 1795, 2049 +: Seq.fill(3)(2051))) + )), 1795, costDetails3, 1795, Seq.fill(4)(2051))) ) }, existingFeature({ (x: Coll[Box]) => x.flatMap({ (b: Box) => b.propositionBytes }) }, @@ -6567,9 +6567,9 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => def success[T](v: T, c: Int, cd: CostDetails, nc: Int, v3Costs: Seq[Int]) = Expected(Success(v), c, cd, nc, v3Costs) Seq( - (Coll[Box](), success(Coll[(Box, Box)](), 1766, costDetails(0), 1766, 2016 +: Seq.fill(3)(2018))), - (Coll[Box](b1), success(Coll[(Box, Box)]((b1, b1)), 1768, costDetails(1), 1768, 2018 +: Seq.fill(3)(2020))), - (Coll[Box](b1, b2), success(Coll[(Box, Box)]((b1, b1), (b2, b2)), 1770, costDetails(2), 1770, 2020 +: Seq.fill(3)(2022))) + (Coll[Box](), success(Coll[(Box, Box)](), 1766, costDetails(0), 1766, Seq.fill(4)(2018))), + (Coll[Box](b1), success(Coll[(Box, Box)]((b1, b1)), 1768, costDetails(1), 1768, Seq.fill(4)(2020))), + (Coll[Box](b1, b2), success(Coll[(Box, Box)]((b1, b1), (b2, b2)), 1770, costDetails(2), 1770, Seq.fill(4)(2022))) ) }, existingFeature({ (x: Coll[Box]) => x.zip(x) }, @@ -6595,7 +6595,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => val costDetails = TracedCost(traceBase :+ FixedCostItem(SizeOf)) verifyCases( { - def success[T](v: T) = Expected(Success(v), 1765, costDetails, 1765, 1999 +: Seq.fill(3)(2001)) + def success[T](v: T) = Expected(Success(v), 1765, costDetails, 1765, Seq.fill(4)(2001)) Seq( (Coll[Box](), success(0)), (Coll[Box](b1), success(1)), @@ -6620,7 +6620,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => ) verifyCases( { - def success[T](v: T, i: Int) = Expected(Success(v), 1768, costDetails(i), 1768, 2006 +: Seq.fill(3)(2008)) + def success[T](v: T, i: Int) = Expected(Success(v), 1768, costDetails(i), 1768, Seq.fill(4)(2008)) Seq( (Coll[Box](), success(Coll[Int](), 0)), (Coll[Box](b1), success(Coll[Int](0), 1)), @@ -6676,9 +6676,9 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => ) def cases = { Seq( - (Coll[Box](), Expected(Success(true), 1764, costDetails1, 1764, 2022 +: Seq.fill(3)(2026))), - (Coll[Box](b1), Expected(Success(false), 1769, costDetails2, 1769, 2027 +: Seq.fill(3)(2031))), - (Coll[Box](b1, b2), Expected(Success(false), 1769, costDetails3, 1769, 2027 +: Seq.fill(3)(2031))) + (Coll[Box](), Expected(Success(true), 1764, costDetails1, 1764, Seq.fill(4)(2026))), + (Coll[Box](b1), Expected(Success(false), 1769, costDetails2, 1769, Seq.fill(4)(2031))), + (Coll[Box](b1, b2), Expected(Success(false), 1769, costDetails3, 1769, Seq.fill(4)(2031))) ) } if (lowerMethodCallsInTests) { @@ -6755,9 +6755,9 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( { Seq( - (Coll[Box](), Expected(Success(false), 1764, costDetails1, 1764, 2022 +: Seq.fill(3)(2026))), - (Coll[Box](b1), Expected(Success(false), 1769, costDetails2, 1769, 2027 +: Seq.fill(3)(2031))), - (Coll[Box](b1, b2), Expected(Success(true), 1773, costDetails3, 1773, 2031 +: Seq.fill(3)(2035))) + (Coll[Box](), Expected(Success(false), 1764, costDetails1, 1764, Seq.fill(4)(2026))), + (Coll[Box](b1), Expected(Success(false), 1769, costDetails2, 1769, Seq.fill(4)(2031))), + (Coll[Box](b1, b2), Expected(Success(true), 1773, costDetails3, 1773, Seq.fill(4)(2035))) ) }, existingFeature({ (x: Coll[Box]) => x.exists({ (b: Box) => b.value > 1 }) }, @@ -6848,11 +6848,11 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( { Seq( - (Coll[BigInt](), Expected(Success(false), 1764, costDetails1, 1764, 2044 +: Seq.fill(3)(2048))), - (Coll[BigInt](BigIntZero), Expected(Success(false), 1769, costDetails2, 1769, 2049 +: Seq.fill(3)(2053))), - (Coll[BigInt](BigIntOne), Expected(Success(true), 1772, costDetails3, 1772, 2052 +: Seq.fill(3)(2056))), - (Coll[BigInt](BigIntZero, BigIntOne), Expected(Success(true), 1777, costDetails4, 1777, 2057 +: Seq.fill(3)(2061))), - (Coll[BigInt](BigIntZero, BigInt10), Expected(Success(false), 1777, costDetails4, 1777, 2057 +: Seq.fill(3)(2061))) + (Coll[BigInt](), Expected(Success(false), 1764, costDetails1, 1764, Seq.fill(4)(2048))), + (Coll[BigInt](BigIntZero), Expected(Success(false), 1769, costDetails2, 1769, Seq.fill(4)(2053))), + (Coll[BigInt](BigIntOne), Expected(Success(true), 1772, costDetails3, 1772, Seq.fill(4)(2056))), + (Coll[BigInt](BigIntZero, BigIntOne), Expected(Success(true), 1777, costDetails4, 1777, Seq.fill(4)(2061))), + (Coll[BigInt](BigIntZero, BigInt10), Expected(Success(false), 1777, costDetails4, 1777, Seq.fill(4)(2061))) ) }, existingFeature( @@ -6963,11 +6963,11 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( { Seq( - (Coll[BigInt](), Expected(Success(true), 1764, costDetails1, 1764, 2044 +: Seq.fill(3)(2048))), - (Coll[BigInt](BigIntMinusOne), Expected(Success(false), 1769, costDetails2, 1769, 2049 +: Seq.fill(3)(2053))), - (Coll[BigInt](BigIntOne), Expected(Success(true), 1772, costDetails3, 1772, 2052 +: Seq.fill(3)(2056))), - (Coll[BigInt](BigIntZero, BigIntOne), Expected(Success(true), 1779, costDetails4, 1779, 2059 +: Seq.fill(3)(2063))), - (Coll[BigInt](BigIntZero, BigInt11), Expected(Success(false), 1779, costDetails4, 1779, 2059 +: Seq.fill(3)(2063))) + (Coll[BigInt](), Expected(Success(true), 1764, costDetails1, 1764, Seq.fill(4)(2048))), + (Coll[BigInt](BigIntMinusOne), Expected(Success(false), 1769, costDetails2, 1769, Seq.fill(4)(2053))), + (Coll[BigInt](BigIntOne), Expected(Success(true), 1772, costDetails3, 1772, Seq.fill(4)(2056))), + (Coll[BigInt](BigIntZero, BigIntOne), Expected(Success(true), 1779, costDetails4, 1779, Seq.fill(4)(2063))), + (Coll[BigInt](BigIntZero, BigInt11), Expected(Success(false), 1779, costDetails4, 1779, Seq.fill(4)(2063))) ) }, existingFeature( @@ -7103,7 +7103,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => Coll[GroupElement]() -> Expected(Success(Coll[Byte]()), 1773, CostDetails.ZeroCost, 1773, newVersionedResults = { val costs = if (activatedVersionInTests >= V6SoftForkVersion) { - 2027 +: Seq.fill(3)(2029) + Seq.fill(4)(2029) } else { Seq.fill(4)(1773) @@ -7117,14 +7117,14 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => Helpers.decodeGroupElement("0390e9daa9916f30d0bc61a8e381c6005edfb7938aee5bb4fc9e8a759c7748ffaa")) -> success(Helpers.decodeBytes( "02d65904820f8330218cf7318b3810d0c9ab9df86f1ee6100882683f23c0aee5870390e9daa9916f30d0bc61a8e381c6005edfb7938aee5bb4fc9e8a759c7748ffaa" - ), 1834, costDetails2, 1834, 2088 +: Seq.fill(3)(2090)), + ), 1834, costDetails2, 1834, Seq.fill(4)(2090)), Coll[GroupElement]( Helpers.decodeGroupElement("02d65904820f8330218cf7318b3810d0c9ab9df86f1ee6100882683f23c0aee587"), Helpers.decodeGroupElement("0390e9daa9916f30d0bc61a8e381c6005edfb7938aee5bb4fc9e8a759c7748ffaa"), Helpers.decodeGroupElement("03bd839b969b02d218fd1192f2c80cbda9c6ce9c7ddb765f31b748f4666203df85")) -> success(Helpers.decodeBytes( "02d65904820f8330218cf7318b3810d0c9ab9df86f1ee6100882683f23c0aee5870390e9daa9916f30d0bc61a8e381c6005edfb7938aee5bb4fc9e8a759c7748ffaa03bd839b969b02d218fd1192f2c80cbda9c6ce9c7ddb765f31b748f4666203df85" - ), 1864, costDetails3, 1864, 2118 +: Seq.fill(3)(2120)) + ), 1864, costDetails3, 1864, Seq.fill(4)(2120)) ) }, existingFeature( @@ -7164,7 +7164,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => newCost = 1840, newVersionedResults = (0 to 3).map({ version => val costs = if (activatedVersionInTests >= V6SoftForkVersion) { - 2100 +: Seq.fill(3)(2104) + Seq.fill(4)(2104) } else { Seq.fill(4)(1840) @@ -7238,7 +7238,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( { - def success[T](v: T, cd: CostDetails) = Expected(Success(v), 1776, cd, 1776, 2068 +: Seq.fill(3)(2072)) + def success[T](v: T, cd: CostDetails) = Expected(Success(v), 1776, cd, 1776, Seq.fill(4)(2072)) Seq( ((Coll[Int](), (0, 0)), success(Coll[Int](), costDetails(0))), ((Coll[Int](1), (0, 0)), success(Coll[Int](1, 1), costDetails(2))), @@ -7327,7 +7327,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( // (coll, (index, elem)) { - def success[T](v: T, cd: CostDetails) = Expected(Success(v), 1774, cd, 1774, 2054 +: Seq.fill(3)(2058)) + def success[T](v: T, cd: CostDetails) = Expected(Success(v), 1774, cd, 1774, Seq.fill(4)(2058)) Seq( ((Coll[Int](), (0, 0)), Expected(new IndexOutOfBoundsException("0"))), ((Coll[Int](1), (0, 0)), success(Coll[Int](0), costDetails(1))), @@ -7404,7 +7404,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( // (coll, (indexes, values)) { - def success[T](v: T, i: Int) = Expected(Success(v), 1774, costDetails(i), 1774, 2062 +: Seq.fill(3)(2066)) + def success[T](v: T, i: Int) = Expected(Success(v), 1774, costDetails(i), 1774, Seq.fill(4)(2066)) Seq( ((Coll[Int](), (Coll(0), Coll(0))), Expected(new IndexOutOfBoundsException("0"))), ((Coll[Int](), (Coll(0, 1), Coll(0, 0))), Expected(new IndexOutOfBoundsException("0"))), @@ -7551,15 +7551,15 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => // (coll, initState) { Seq( - ((Coll[Byte](), 0), Expected(Success(0), 1767, costDetails1, 1767, 2045 +: Seq.fill(3)(2049))), - ((Coll[Byte](), Int.MaxValue), Expected(Success(Int.MaxValue), 1767, costDetails1, 1767, 2045 +: Seq.fill(3)(2049))), - ((Coll[Byte](1), Int.MaxValue - 1), Expected(Success(Int.MaxValue), 1773, costDetails2, 1773, 2051 +: Seq.fill(3)(2055))), + ((Coll[Byte](), 0), Expected(Success(0), 1767, costDetails1, 1767, Seq.fill(4)(2049))), + ((Coll[Byte](), Int.MaxValue), Expected(Success(Int.MaxValue), 1767, costDetails1, 1767, Seq.fill(4)(2049))), + ((Coll[Byte](1), Int.MaxValue - 1), Expected(Success(Int.MaxValue), 1773, costDetails2, 1773, Seq.fill(4)(2055))), ((Coll[Byte](1), Int.MaxValue), Expected(new ArithmeticException("integer overflow"))), - ((Coll[Byte](-1), Int.MinValue + 1), Expected(Success(Int.MinValue), 1773, costDetails2, 1773, 2051 +: Seq.fill(3)(2055))), + ((Coll[Byte](-1), Int.MinValue + 1), Expected(Success(Int.MinValue), 1773, costDetails2, 1773, Seq.fill(4)(2055))), ((Coll[Byte](-1), Int.MinValue), Expected(new ArithmeticException("integer overflow"))), - ((Coll[Byte](1, 2), 0), Expected(Success(3), 1779, costDetails3, 1779, 2057 +: Seq.fill(3)(2061))), - ((Coll[Byte](1, -1), 0), Expected(Success(0), 1779, costDetails3, 1779, 2057 +: Seq.fill(3)(2061))), - ((Coll[Byte](1, -1, 1), 0), Expected(Success(1), 1785, costDetails4, 1785, 2063 +: Seq.fill(3)(2067))) + ((Coll[Byte](1, 2), 0), Expected(Success(3), 1779, costDetails3, 1779, Seq.fill(4)(2061))), + ((Coll[Byte](1, -1), 0), Expected(Success(0), 1779, costDetails3, 1779, Seq.fill(4)(2061))), + ((Coll[Byte](1, -1, 1), 0), Expected(Success(1), 1785, costDetails4, 1785, Seq.fill(4)(2067))) ) }, existingFeature( @@ -7812,15 +7812,15 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => // (coll, initState) { Seq( - ((Coll[Byte](), 0), Expected(Success(0), 1767, costDetails1, 1767, 2085 +: Seq.fill(3)(2089))), - ((Coll[Byte](), Int.MaxValue), Expected(Success(Int.MaxValue), 1767, costDetails1, 1767, 2085 +: Seq.fill(3)(2089))), - ((Coll[Byte](1), Int.MaxValue - 1), Expected(Success(Int.MaxValue), 1779, costDetails2, 1779, 2097 +: Seq.fill(3)(2101))), + ((Coll[Byte](), 0), Expected(Success(0), 1767, costDetails1, 1767, Seq.fill(4)(2089))), + ((Coll[Byte](), Int.MaxValue), Expected(Success(Int.MaxValue), 1767, costDetails1, 1767, Seq.fill(4)(2089))), + ((Coll[Byte](1), Int.MaxValue - 1), Expected(Success(Int.MaxValue), 1779, costDetails2, 1779, Seq.fill(4)(2101))), ((Coll[Byte](1), Int.MaxValue), Expected(new ArithmeticException("integer overflow"))), - ((Coll[Byte](-1), Int.MinValue + 1), Expected(Success(Int.MinValue + 1), 1777, costDetails3, 1777, 2095 +: Seq.fill(3)(2099))), - ((Coll[Byte](-1), Int.MinValue), Expected(Success(Int.MinValue), 1777, costDetails3, 1777, 2095 +: Seq.fill(3)(2099))), - ((Coll[Byte](1, 2), 0), Expected(Success(3), 1791, costDetails4, 1791, 2109 +: Seq.fill(3)(2113))), - ((Coll[Byte](1, -1), 0), Expected(Success(1), 1789, costDetails5, 1789, 2107 +: Seq.fill(3)(2111))), - ((Coll[Byte](1, -1, 1), 0), Expected(Success(2), 1801, costDetails6, 1801, 2119 +: Seq.fill(3)(2123))) + ((Coll[Byte](-1), Int.MinValue + 1), Expected(Success(Int.MinValue + 1), 1777, costDetails3, 1777, Seq.fill(4)(2099))), + ((Coll[Byte](-1), Int.MinValue), Expected(Success(Int.MinValue), 1777, costDetails3, 1777, Seq.fill(4)(2099))), + ((Coll[Byte](1, 2), 0), Expected(Success(3), 1791, costDetails4, 1791, Seq.fill(4)(2113))), + ((Coll[Byte](1, -1), 0), Expected(Success(1), 1789, costDetails5, 1789, Seq.fill(4)(2111))), + ((Coll[Byte](1, -1, 1), 0), Expected(Success(2), 1801, costDetails6, 1801, Seq.fill(4)(2123))) ) }, existingFeature( @@ -7931,15 +7931,15 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( // (coll, (elem: Byte, from: Int)) { - def success0[T](v: T) = Expected(Success(v), 1773, costDetails(0), 1773, 2057 +: Seq.fill(3)(2061)) + def success0[T](v: T) = Expected(Success(v), 1773, costDetails(0), 1773, Seq.fill(4)(2061)) - def success1[T](v: T) = Expected(Success(v), 1773, costDetails(1), 1773, 2057 +: Seq.fill(3)(2061)) + def success1[T](v: T) = Expected(Success(v), 1773, costDetails(1), 1773, Seq.fill(4)(2061)) - def success2[T](v: T) = Expected(Success(v), 1774, costDetails(2), 1774, 2058 +: Seq.fill(3)(2062)) + def success2[T](v: T) = Expected(Success(v), 1774, costDetails(2), 1774, Seq.fill(4)(2062)) - def success3[T](v: T) = Expected(Success(v), 1775, costDetails(3), 1775, 2059 +: Seq.fill(3)(2063)) + def success3[T](v: T) = Expected(Success(v), 1775, costDetails(3), 1775, Seq.fill(4)(2063)) - def success12[T](v: T) = Expected(Success(v), 1782, costDetails(12), 1782, 2066 +: Seq.fill(3)(2070)) + def success12[T](v: T) = Expected(Success(v), 1782, costDetails(12), 1782, Seq.fill(4)(2070)) Seq( ((Coll[Byte](), (0.toByte, 0)), success0(-1)), @@ -8002,7 +8002,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => ) verifyCases( { - def success[T](v: T) = Expected(Success(v), 1769, costDetails, 1769, 2017 +: Seq.fill(3)(2019)) + def success[T](v: T) = Expected(Success(v), 1769, costDetails, 1769, Seq.fill(4)(2019)) Seq( ((Coll[Int](), 0), Expected(new ArrayIndexOutOfBoundsException("0"))), @@ -8067,7 +8067,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( // (coll, (index, default)) { - def success[T](v: T) = Expected(Success(v), 1773, costDetails, 1773, 2049 +: Seq.fill(3)(2053)) + def success[T](v: T) = Expected(Success(v), 1773, costDetails, 1773, Seq.fill(4)(2053)) Seq( ((Coll[Int](), (0, default)), success(default)), ((Coll[Int](), (-1, default)), success(default)), @@ -8150,7 +8150,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => ) verifyCases( { - def success[T](v: T) = Expected(Success(v), 1763, costDetails, 1763, 1995 +: Seq.fill(3)(1997)) + def success[T](v: T) = Expected(Success(v), 1763, costDetails, 1763, Seq.fill(4)(1997)) Seq( ((0, 0), success(2)), ((1, 2), success(2)) @@ -8165,7 +8165,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => val samples = genSamples[(Int, Int)](DefaultMinSuccessful) val costDetails = TracedCost(traceBase :+ FixedCostItem(SelectField)) verifyCases( - Seq(((1, 2), Expected(Success(1), cost = 1764, costDetails, 1764, 1996 +: Seq.fill(3)(1998)))), + Seq(((1, 2), Expected(Success(1), cost = 1764, costDetails, 1764, Seq.fill(4)(1998)))), existingFeature((x: (Int, Int)) => x._1, "{ (x: (Int, Int)) => x(0) }", FuncValue( @@ -8174,7 +8174,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => )), preGeneratedSamples = Some(samples)) verifyCases( - Seq(((1, 2), Expected(Success(2), cost = 1764, costDetails, 1764, 1996 +: Seq.fill(3)(1998)))), + Seq(((1, 2), Expected(Success(2), cost = 1764, costDetails, 1764, Seq.fill(4)(1998)))), existingFeature((x: (Int, Int)) => x._2, "{ (x: (Int, Int)) => x(1) }", FuncValue( @@ -8216,9 +8216,9 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => { def success[T](v: T, c: Int) = Expected(Success(v), c) Seq( - (Coll[Int](), Expected(Success(Coll[Int]()), 1768, costDetails(0), 1768, 2020 +: Seq.fill(3)(2022))), - (Coll[Int](1), Expected(Success(Coll[Int](2)), 1771, costDetails(1), 1771, 2023 +: Seq.fill(3)(2025))), - (Coll[Int](1, 2), Expected(Success(Coll[Int](2, 3)), 1774, costDetails(2), 1774, 2026 +: Seq.fill(3)(2028))), + (Coll[Int](), Expected(Success(Coll[Int]()), 1768, costDetails(0), 1768, Seq.fill(4)(2022))), + (Coll[Int](1), Expected(Success(Coll[Int](2)), 1771, costDetails(1), 1771, Seq.fill(4)(2025))), + (Coll[Int](1, 2), Expected(Success(Coll[Int](2, 3)), 1774, costDetails(2), 1774, Seq.fill(4)(2028))), (Coll[Int](1, 2, Int.MaxValue), Expected(new ArithmeticException("integer overflow"))) ) }, @@ -8312,10 +8312,10 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => { def success[T](v: T, c: Int) = Expected(Success(v), c) Seq( - (Coll[Int](), Expected(Success(Coll[Int]()), 1768, costDetails1, 1768, 2050 +: Seq.fill(3)(2054))), - (Coll[Int](1), Expected(Success(Coll[Int](2)), 1775, costDetails2, 1775, 2057 +: Seq.fill(3)(2061))), - (Coll[Int](-1), Expected(Success(Coll[Int](1)), 1775, costDetails3, 1775, 2057 +: Seq.fill(3)(2061))), - (Coll[Int](1, -2), Expected(Success(Coll[Int](2, 2)), 1782, costDetails4, 1782, 2064 +: Seq.fill(3)(2068))), + (Coll[Int](), Expected(Success(Coll[Int]()), 1768, costDetails1, 1768, Seq.fill(4)(2054))), + (Coll[Int](1), Expected(Success(Coll[Int](2)), 1775, costDetails2, 1775, Seq.fill(4)(2061))), + (Coll[Int](-1), Expected(Success(Coll[Int](1)), 1775, costDetails3, 1775, Seq.fill(4)(2061))), + (Coll[Int](1, -2), Expected(Success(Coll[Int](2, 2)), 1782, costDetails4, 1782, Seq.fill(4)(2068))), (Coll[Int](1, 2, Int.MaxValue), Expected(new ArithmeticException("integer overflow"))), (Coll[Int](1, 2, Int.MinValue), Expected(new ArithmeticException("integer overflow"))) ) @@ -8365,11 +8365,11 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( { Seq( - (Coll[Int](), Expected(Success(Coll[Int]()), 1768, costDetails(0), 1768, 2020 +: Seq.fill(3)(2022))), - (Coll[Int](1), Expected(Success(Coll[Int](1)), 1771, costDetails(1), 1771, 2023 +: Seq.fill(3)(2025))), - (Coll[Int](1, 2), Expected(Success(Coll[Int](1, 2)), 1775, costDetails(2), 1775, 2027 +: Seq.fill(3)(2029))), - (Coll[Int](1, 2, -1), Expected(Success(Coll[Int](1, 2)), 1778, costDetails(3), 1778, 2030 +: Seq.fill(3)(2032))), - (Coll[Int](1, -1, 2, -2), Expected(Success(Coll[Int](1, 2)), 1782, costDetails(4), 1782, 2034 +: Seq.fill(3)(2036))) + (Coll[Int](), Expected(Success(Coll[Int]()), 1768, costDetails(0), 1768, Seq.fill(4)(2022))), + (Coll[Int](1), Expected(Success(Coll[Int](1)), 1771, costDetails(1), 1771, Seq.fill(4)(2025))), + (Coll[Int](1, 2), Expected(Success(Coll[Int](1, 2)), 1775, costDetails(2), 1775, Seq.fill(4)(2029))), + (Coll[Int](1, 2, -1), Expected(Success(Coll[Int](1, 2)), 1778, costDetails(3), 1778, Seq.fill(4)(2032))), + (Coll[Int](1, -1, 2, -2), Expected(Success(Coll[Int](1, 2)), 1782, costDetails(4), 1782, Seq.fill(4)(2036))) ) }, existingFeature((x: Coll[Int]) => x.filter({ (v: Int) => o.gt(v, 0) }), @@ -8442,12 +8442,12 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => def success[T](v: T, c: Int) = Expected(Success(v), c) Seq( - (Coll[Int](), Expected(Success(Coll[Int]()), 1768, costDetails(0), 1768, 2044 +: Seq.fill(3)(2048))), - (Coll[Int](1), Expected(Success(Coll[Int](1)), 1775, costDetails(1), 1775, 2051 +: Seq.fill(3)(2055))), - (Coll[Int](10), Expected(Success(Coll[Int]()), 1775, costDetails(1), 1775, 2051 +: Seq.fill(3)(2055))), - (Coll[Int](1, 2), Expected(Success(Coll[Int](1, 2)), 1783, costDetails(2), 1783, 2059 +: Seq.fill(3)(2063))), - (Coll[Int](1, 2, 0), Expected(Success(Coll[Int](1, 2)), 1788, costDetails3, 1788, 2064 +: Seq.fill(3)(2068))), - (Coll[Int](1, -1, 2, -2, 11), Expected(Success(Coll[Int](1, 2)), 1800, costDetails5, 1800, 2076 +: Seq.fill(3)(2080))) + (Coll[Int](), Expected(Success(Coll[Int]()), 1768, costDetails(0), 1768, Seq.fill(4)(2048))), + (Coll[Int](1), Expected(Success(Coll[Int](1)), 1775, costDetails(1), 1775, Seq.fill(4)(2055))), + (Coll[Int](10), Expected(Success(Coll[Int]()), 1775, costDetails(1), 1775, Seq.fill(4)(2055))), + (Coll[Int](1, 2), Expected(Success(Coll[Int](1, 2)), 1783, costDetails(2), 1783, Seq.fill(4)(2063))), + (Coll[Int](1, 2, 0), Expected(Success(Coll[Int](1, 2)), 1788, costDetails3, 1788, Seq.fill(4)(2068))), + (Coll[Int](1, -1, 2, -2, 11), Expected(Success(Coll[Int](1, 2)), 1800, costDetails5, 1800, Seq.fill(4)(2080))) ) }, existingFeature((x: Coll[Int]) => x.filter({ (v: Int) => if (o.gt(v, 0)) v < 10 else false }), @@ -8491,7 +8491,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => { val cost = 1772 val newCost = 1772 - val v3Costs = 2046 +: Seq.fill(3)(2050) + val v3Costs = Seq.fill(4)(2050) Seq( // (coll, (from, until)) ((Coll[Int](), (-1, 0)), Expected(Success(Coll[Int]()), cost, costDetails(1), newCost, v3Costs)), @@ -8581,7 +8581,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => if (lowerMethodCallsInTests) { verifyCases( { - def success[T](v: T, size: Int) = Expected(Success(v), 1770, costDetails(size), 1770, 2020 +: Seq.fill(3)(2022)) + def success[T](v: T, size: Int) = Expected(Success(v), 1770, costDetails(size), 1770, Seq.fill(4)(2022)) val arr1 = Gen.listOfN(100, arbitrary[Int]).map(_.toArray).sample.get val arr2 = Gen.listOfN(200, arbitrary[Int]).map(_.toArray).sample.get @@ -8593,7 +8593,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => (Coll[Int](1), Coll[Int](2, 3)) -> success(Coll[Int](1, 2, 3), 3), (Coll[Int](1, 2), Coll[Int](3)) -> success(Coll[Int](1, 2, 3), 3), (Coll[Int](1, 2), Coll[Int](3, 4)) -> success(Coll[Int](1, 2, 3, 4), 4), - (Coll[Int](arr1: _*), Coll[Int](arr2: _*)) -> Expected(Success(Coll[Int](arr1 ++ arr2: _*)), 1771, costDetails(300), 1771, 2021 +: Seq.fill(3)(2023)) + (Coll[Int](arr1: _*), Coll[Int](arr2: _*)) -> Expected(Success(Coll[Int](arr1 ++ arr2: _*)), 1771, costDetails(300), 1771, Seq.fill(4)(2023)) ) }, existingFeature( @@ -8688,32 +8688,32 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( Seq( (None -> Expected(new NoSuchElementException("None.get"))), - (Some(10L) -> Expected(Success(10L), 1765, costDetails1, 1765, 1995 +: Seq.fill(3)(1997)))), + (Some(10L) -> Expected(Success(10L), 1765, costDetails1, 1765, Seq.fill(4)(1997)))), existingFeature({ (x: Option[Long]) => x.get }, "{ (x: Option[Long]) => x.get }", FuncValue(Vector((1, SOption(SLong))), OptionGet(ValUse(1, SOption(SLong)))))) verifyCases( Seq( - (None -> Expected(Success(false), 1764, costDetails2, 1764, 1994 +: Seq.fill(3)(1996))), - (Some(10L) -> Expected(Success(true), 1764, costDetails2, 1764, 1994 +: Seq.fill(3)(1996)))), + (None -> Expected(Success(false), 1764, costDetails2, 1764, Seq.fill(4)(1996))), + (Some(10L) -> Expected(Success(true), 1764, costDetails2, 1764, Seq.fill(4)(1996)))), existingFeature({ (x: Option[Long]) => x.isDefined }, "{ (x: Option[Long]) => x.isDefined }", FuncValue(Vector((1, SOption(SLong))), OptionIsDefined(ValUse(1, SOption(SLong)))))) verifyCases( Seq( - (None -> Expected(Success(1L), 1766, costDetails3, 1766, 2004 +: Seq.fill(3)(2006))), - (Some(10L) -> Expected(Success(10L), 1766, costDetails3, 1766, 2004 +: Seq.fill(3)(2006)))), + (None -> Expected(Success(1L), 1766, costDetails3, 1766, Seq.fill(4)(2006))), + (Some(10L) -> Expected(Success(10L), 1766, costDetails3, 1766, Seq.fill(4)(2006)))), existingFeature({ (x: Option[Long]) => x.getOrElse(1L) }, "{ (x: Option[Long]) => x.getOrElse(1L) }", FuncValue(Vector((1, SOption(SLong))), OptionGetOrElse(ValUse(1, SOption(SLong)), LongConstant(1L))))) verifyCases( Seq( - (None -> Expected(Success(None), 1766, costDetails4, 1766, 2024 +: Seq.fill(3)(2028))), - (Some(10L) -> Expected(Success(None), 1768, costDetails5, 1768, 2026 +: Seq.fill(3)(2030))), - (Some(1L) -> Expected(Success(Some(1L)), 1769, costDetails5, 1769, 2027 +: Seq.fill(3)(2031)))), + (None -> Expected(Success(None), 1766, costDetails4, 1766, Seq.fill(4)(2028))), + (Some(10L) -> Expected(Success(None), 1768, costDetails5, 1768, Seq.fill(4)(2030))), + (Some(1L) -> Expected(Success(Some(1L)), 1769, costDetails5, 1769, Seq.fill(4)(2031)))), existingFeature({ (x: Option[Long]) => x.filter({ (v: Long) => v == 1 }) }, "{ (x: Option[Long]) => x.filter({ (v: Long) => v == 1 }) }", FuncValue( @@ -8729,8 +8729,8 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => val n = ExactNumeric.LongIsExactNumeric verifyCases( Seq( - (None -> Expected(Success(None), 1766, costDetails6, 1766, 2024 +: Seq.fill(3)(2028))), - (Some(10L) -> Expected(Success(Some(11L)), 1770, costDetails7, 1770, 2028 +: Seq.fill(3)(2032))), + (None -> Expected(Success(None), 1766, costDetails6, 1766, Seq.fill(4)(2028))), + (Some(10L) -> Expected(Success(Some(11L)), 1770, costDetails7, 1770, Seq.fill(4)(2032))), (Some(Long.MaxValue) -> Expected(new ArithmeticException("long overflow")))), existingFeature({ (x: Option[Long]) => x.map( (v: Long) => n.plus(v, 1) ) }, "{ (x: Option[Long]) => x.map({ (v: Long) => v + 1 }) }", @@ -8792,10 +8792,10 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => val o = ExactOrdering.LongIsExactOrdering verifyCases( Seq( - (None -> Expected(Success(None), 1766, costDetails1, 1766, 2048 +: Seq.fill(3)(2052))), - (Some(0L) -> Expected(Success(None), 1771, costDetails2, 1771, 2053 +: Seq.fill(3)(2057))), - (Some(10L) -> Expected(Success(Some(10L)), 1774, costDetails3, 1774, 2056 +: Seq.fill(3)(2060))), - (Some(11L) -> Expected(Success(None), 1774, costDetails3, 1774, 2056 +: Seq.fill(3)(2060)))), + (None -> Expected(Success(None), 1766, costDetails1, 1766, Seq.fill(4)(2052))), + (Some(0L) -> Expected(Success(None), 1771, costDetails2, 1771, Seq.fill(4)(2057))), + (Some(10L) -> Expected(Success(Some(10L)), 1774, costDetails3, 1774, Seq.fill(4)(2060))), + (Some(11L) -> Expected(Success(None), 1774, costDetails3, 1774, Seq.fill(4)(2060)))), existingFeature( { (x: Option[Long]) => x.filter({ (v: Long) => if (o.gt(v, 0L)) v <= 10 else false } ) }, "{ (x: Option[Long]) => x.filter({ (v: Long) => if (v > 0) v <= 10 else false }) }", @@ -8856,10 +8856,10 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => val n = ExactNumeric.LongIsExactNumeric verifyCases( Seq( - (None -> Expected(Success(None), 1766, costDetails4, 1766, 2044 +: Seq.fill(3)(2048))), - (Some(0L) -> Expected(Success(Some(0L)), 1772, costDetails5, 1772, 2050 +: Seq.fill(3)(2054))), - (Some(10L) -> Expected(Success(Some(10L)), 1772, costDetails5, 1772, 2050 +: Seq.fill(3)(2054))), - (Some(-1L) -> Expected(Success(Some(-2L)), 1774, costDetails6, 1774, 2052 +: Seq.fill(3)(2056))), + (None -> Expected(Success(None), 1766, costDetails4, 1766, Seq.fill(4)(2048))), + (Some(0L) -> Expected(Success(Some(0L)), 1772, costDetails5, 1772, Seq.fill(4)(2054))), + (Some(10L) -> Expected(Success(Some(10L)), 1772, costDetails5, 1772, Seq.fill(4)(2054))), + (Some(-1L) -> Expected(Success(Some(-2L)), 1774, costDetails6, 1774, Seq.fill(4)(2056))), (Some(Long.MinValue) -> Expected(new ArithmeticException("long overflow")))), existingFeature( { (x: Option[Long]) => x.map( (v: Long) => if (o.lt(v, 0)) n.minus(v, 1) else v ) }, @@ -8918,7 +8918,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => newCost = 1766, newVersionedResults = Seq.tabulate(4)({ v => val costs = if (activatedVersionInTests >= V6SoftForkVersion) { - 2038 +: Seq.fill(3)(2042) + Seq.fill(4)(2042) } else { Seq.fill(4)(1766) @@ -8931,7 +8931,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => cost = 1774, expectedDetails = costDetails2, expectedNewCost = 1774, - expectedV3Costs = 2046 +: Seq.fill(3)(2050))), + expectedV3Costs = Seq.fill(4)(2050))), (Some(Long.MaxValue) -> Expected(new ArithmeticException("long overflow"))) ), changedFeature( @@ -9001,21 +9001,21 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => 1768, costDetailsBlake(0), 1768, - 1998 +: Seq.fill(3)(2000) + Seq.fill(4)(2000) ), Helpers.decodeBytes("e0ff0105ffffac31010017ff33") -> Expected( Success(Helpers.decodeBytes("33707eed9aab64874ff2daa6d6a378f61e7da36398fb36c194c7562c9ff846b5")), 1768, costDetailsBlake(13), 1768, - 1998 +: Seq.fill(3)(2000) + Seq.fill(4)(2000) ), Colls.replicate(1024, 1.toByte) -> Expected( Success(Helpers.decodeBytes("45d8456fc5d41d1ec1124cb92e41192c1c3ec88f0bf7ae2dc6e9cf75bec22045")), 1773, costDetailsBlake(1024), 1773, - 2003 +: Seq.fill(3)(2005) + Seq.fill(4)(2005) ) ), existingFeature((x: Coll[Byte]) => SigmaDsl.blake2b256(x), @@ -9029,21 +9029,21 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => 1774, costDetailsSha(0), 1774, - 2004 +: Seq.fill(3)(2006) + Seq.fill(4)(2006) ), Helpers.decodeBytes("e0ff0105ffffac31010017ff33") -> Expected( Success(Helpers.decodeBytes("367d0ec2cdc14aac29d5beb60c2bfc86d5a44a246308659af61c1b85fa2ca2cc")), 1774, costDetailsSha(13), 1774, - 2004 +: Seq.fill(3)(2006) + Seq.fill(4)(2006) ), Colls.replicate(1024, 1.toByte) -> Expected( Success(Helpers.decodeBytes("5a648d8015900d89664e00e125df179636301a2d8fa191c1aa2bd9358ea53a69")), 1786, costDetailsSha(1024), 1786, - 2016 +: Seq.fill(3)(2018) + Seq.fill(4)(2018) ) ), existingFeature((x: Coll[Byte]) => SigmaDsl.sha256(x), @@ -9053,7 +9053,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => property("sigmaProp equivalence") { val costDetails = TracedCost(traceBase :+ FixedCostItem(BoolToSigmaProp)) - val v3Costs = 1995 +: Seq.fill(3)(1997) + val v3Costs = Seq.fill(4)(1997) verifyCases( Seq( (false, Expected(Success(CSigmaProp(TrivialProp.FalseProp)), 1765, costDetails, 1765, v3Costs)), @@ -9084,7 +9084,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => Helpers.decodeECPoint("02614b14a8c6c6b4b7ce017d72fbca7f9218b72c16bdd88f170ffb300b106b9014"), Helpers.decodeECPoint("034cc5572276adfa3e283a3f1b0f0028afaadeaa362618c5ec43262d8cefe7f004") ) - )) -> Expected(Success(CSigmaProp(TrivialProp.TrueProp)), 1770, costDetails(1), 1770, 2016 +: Seq.fill(3)(2018)), + )) -> Expected(Success(CSigmaProp(TrivialProp.TrueProp)), 1770, costDetails(1), 1770, Seq.fill(4)(2018)), Coll[SigmaProp]( CSigmaProp( ProveDHTuple( @@ -9112,7 +9112,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => ) ) ) - ), 1873, costDetails(3), 1873, 2119 +: Seq.fill(3)(2121)), + ), 1873, costDetails(3), 1873, Seq.fill(4)(2121)), Colls.replicate[SigmaProp](AtLeast.MaxChildrenCount + 1, CSigmaProp(TrivialProp.TrueProp)) -> Expected(new IllegalArgumentException("Expected input elements count should not exceed 255, actual: 256")) ), @@ -9157,19 +9157,19 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => ProveDlog(Helpers.decodeECPoint("03a426a66fc1af2792b35d9583904c3fb877b49ae5cea45b7a2aa105ffa4c68606")) ) ) - ), 1802, 2046 +: Seq.fill(3)(2048)), + ), 1802, Seq.fill(4)(2048)), (CSigmaProp(TrivialProp.TrueProp), CSigmaProp(ProveDlog(Helpers.decodeECPoint("03a426a66fc1af2792b35d9583904c3fb877b49ae5cea45b7a2aa105ffa4c68606")))) -> - success(CSigmaProp(ProveDlog(Helpers.decodeECPoint("03a426a66fc1af2792b35d9583904c3fb877b49ae5cea45b7a2aa105ffa4c68606"))), 1784, 2028 +: Seq.fill(3)(2030)), + success(CSigmaProp(ProveDlog(Helpers.decodeECPoint("03a426a66fc1af2792b35d9583904c3fb877b49ae5cea45b7a2aa105ffa4c68606"))), 1784, Seq.fill(4)(2030)), (CSigmaProp(TrivialProp.FalseProp), CSigmaProp(ProveDlog(Helpers.decodeECPoint("03a426a66fc1af2792b35d9583904c3fb877b49ae5cea45b7a2aa105ffa4c68606")))) -> - success(CSigmaProp(TrivialProp.FalseProp), 1767, 2011 +: Seq.fill(3)(2013)), + success(CSigmaProp(TrivialProp.FalseProp), 1767, Seq.fill(4)(2013)), (CSigmaProp(ProveDlog(Helpers.decodeECPoint("03a426a66fc1af2792b35d9583904c3fb877b49ae5cea45b7a2aa105ffa4c68606"))), CSigmaProp(TrivialProp.TrueProp)) -> - success(CSigmaProp(ProveDlog(Helpers.decodeECPoint("03a426a66fc1af2792b35d9583904c3fb877b49ae5cea45b7a2aa105ffa4c68606"))), 1784, 2028 +: Seq.fill(3)(2030)), + success(CSigmaProp(ProveDlog(Helpers.decodeECPoint("03a426a66fc1af2792b35d9583904c3fb877b49ae5cea45b7a2aa105ffa4c68606"))), 1784, Seq.fill(4)(2030)), (CSigmaProp(ProveDlog(Helpers.decodeECPoint("03a426a66fc1af2792b35d9583904c3fb877b49ae5cea45b7a2aa105ffa4c68606"))), CSigmaProp(TrivialProp.FalseProp)) -> - success(CSigmaProp(TrivialProp.FalseProp), 1767, 2011 +: Seq.fill(3)(2013)) + success(CSigmaProp(TrivialProp.FalseProp), 1767, Seq.fill(4)(2013)) ) }, existingFeature( @@ -9189,9 +9189,9 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => { Seq( (CSigmaProp(ProveDlog(Helpers.decodeECPoint("03a426a66fc1af2792b35d9583904c3fb877b49ae5cea45b7a2aa105ffa4c68606"))), true) -> - Expected(Success(CSigmaProp(ProveDlog(Helpers.decodeECPoint("03a426a66fc1af2792b35d9583904c3fb877b49ae5cea45b7a2aa105ffa4c68606")))), 1786, costDetails2, 1786, 2036 +: Seq.fill(3)(2038)), + Expected(Success(CSigmaProp(ProveDlog(Helpers.decodeECPoint("03a426a66fc1af2792b35d9583904c3fb877b49ae5cea45b7a2aa105ffa4c68606")))), 1786, costDetails2, 1786, Seq.fill(4)(2038)), (CSigmaProp(ProveDlog(Helpers.decodeECPoint("03a426a66fc1af2792b35d9583904c3fb877b49ae5cea45b7a2aa105ffa4c68606"))), false) -> - Expected(Success(CSigmaProp(TrivialProp.FalseProp)), 1769, costDetails2, 1769, 2019 +: Seq.fill(3)(2021)) + Expected(Success(CSigmaProp(TrivialProp.FalseProp)), 1769, costDetails2, 1769, Seq.fill(4)(2021)) ) }, existingFeature( @@ -9234,19 +9234,19 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => ) ) ), - 1802, 2046 +: Seq.fill(3)(2048)), + 1802, Seq.fill(4)(2048)), (CSigmaProp(TrivialProp.FalseProp), CSigmaProp(ProveDlog(Helpers.decodeECPoint("03a426a66fc1af2792b35d9583904c3fb877b49ae5cea45b7a2aa105ffa4c68606")))) -> - success(CSigmaProp(ProveDlog(Helpers.decodeECPoint("03a426a66fc1af2792b35d9583904c3fb877b49ae5cea45b7a2aa105ffa4c68606"))), 1784, 2028 +: Seq.fill(3)(2030)), + success(CSigmaProp(ProveDlog(Helpers.decodeECPoint("03a426a66fc1af2792b35d9583904c3fb877b49ae5cea45b7a2aa105ffa4c68606"))), 1784, Seq.fill(4)(2030)), (CSigmaProp(TrivialProp.TrueProp), CSigmaProp(ProveDlog(Helpers.decodeECPoint("03a426a66fc1af2792b35d9583904c3fb877b49ae5cea45b7a2aa105ffa4c68606")))) -> - success(CSigmaProp(TrivialProp.TrueProp), 1767, 2011 +: Seq.fill(3)(2013)), + success(CSigmaProp(TrivialProp.TrueProp), 1767, Seq.fill(4)(2013)), (CSigmaProp(ProveDlog(Helpers.decodeECPoint("03a426a66fc1af2792b35d9583904c3fb877b49ae5cea45b7a2aa105ffa4c68606"))), CSigmaProp(TrivialProp.FalseProp)) -> - success(CSigmaProp(ProveDlog(Helpers.decodeECPoint("03a426a66fc1af2792b35d9583904c3fb877b49ae5cea45b7a2aa105ffa4c68606"))), 1784, 2028 +: Seq.fill(3)(2030)), + success(CSigmaProp(ProveDlog(Helpers.decodeECPoint("03a426a66fc1af2792b35d9583904c3fb877b49ae5cea45b7a2aa105ffa4c68606"))), 1784, Seq.fill(4)(2030)), (CSigmaProp(ProveDlog(Helpers.decodeECPoint("03a426a66fc1af2792b35d9583904c3fb877b49ae5cea45b7a2aa105ffa4c68606"))), CSigmaProp(TrivialProp.TrueProp)) -> - success(CSigmaProp(TrivialProp.TrueProp), 1767, 2011 +: Seq.fill(3)(2013)) + success(CSigmaProp(TrivialProp.TrueProp), 1767, Seq.fill(4)(2013)) ) }, existingFeature( @@ -9274,9 +9274,9 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => Seq( (CSigmaProp(ProveDlog(Helpers.decodeECPoint("03a426a66fc1af2792b35d9583904c3fb877b49ae5cea45b7a2aa105ffa4c68606"))), false) -> - success(CSigmaProp(ProveDlog(Helpers.decodeECPoint("03a426a66fc1af2792b35d9583904c3fb877b49ae5cea45b7a2aa105ffa4c68606"))), 1786, 2036 +: Seq.fill(3)(2038)), + success(CSigmaProp(ProveDlog(Helpers.decodeECPoint("03a426a66fc1af2792b35d9583904c3fb877b49ae5cea45b7a2aa105ffa4c68606"))), 1786, Seq.fill(4)(2038)), (CSigmaProp(ProveDlog(Helpers.decodeECPoint("03a426a66fc1af2792b35d9583904c3fb877b49ae5cea45b7a2aa105ffa4c68606"))), true) -> - success(CSigmaProp(TrivialProp.TrueProp), 1769, 2019 +: Seq.fill(3)(2021)) + success(CSigmaProp(TrivialProp.TrueProp), 1769, Seq.fill(4)(2021)) ) }, existingFeature( @@ -9314,25 +9314,25 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => Helpers.decodeBytes( "0008ce03c046fccb95549910767d0543f5e8ce41d66ae6a8720a46f4049cac3b3d26dafb023479c9c3b86a0d3c8be3db0a2d186788e9af1db76d55f3dad127d15185d83d0303d7898641cb6653585a8e1dabfa7f665e61e0498963e329e6e3744bd764db2d72037ae057d89ec0b46ff8e9ff4c37e85c12acddb611c3f636421bef1542c11b0441" ) - ), cost = 1771, newDetails(4), expectedNewCost = 1771, 2001 +: Seq.fill(3)(2003)), + ), cost = 1771, newDetails(4), expectedNewCost = 1771, Seq.fill(4)(2003)), CSigmaProp(pk) -> Expected(Success( Helpers.decodeBytes("0008cd039d0b1e46c21540d033143440d2fb7dd5d650cf89981c99ee53c6e0374d2b1b6f")), - cost = 1769, newDetails(1), expectedNewCost = 1769, 1999 +: Seq.fill(3)(2001)), + cost = 1769, newDetails(1), expectedNewCost = 1769, Seq.fill(4)(2001)), CSigmaProp(and) -> Expected(Success( Helpers.decodeBytes( "00089602cd039d0b1e46c21540d033143440d2fb7dd5d650cf89981c99ee53c6e0374d2b1b6fce03c046fccb95549910767d0543f5e8ce41d66ae6a8720a46f4049cac3b3d26dafb023479c9c3b86a0d3c8be3db0a2d186788e9af1db76d55f3dad127d15185d83d0303d7898641cb6653585a8e1dabfa7f665e61e0498963e329e6e3744bd764db2d72037ae057d89ec0b46ff8e9ff4c37e85c12acddb611c3f636421bef1542c11b0441" ) - ), cost = 1772, newDetails(6), expectedNewCost = 1772, 2002 +: Seq.fill(3)(2004)), + ), cost = 1772, newDetails(6), expectedNewCost = 1772, Seq.fill(4)(2004)), CSigmaProp(threshold) -> Expected(Success( Helpers.decodeBytes( "0008980204cd039d0b1e46c21540d033143440d2fb7dd5d650cf89981c99ee53c6e0374d2b1b6fce03c046fccb95549910767d0543f5e8ce41d66ae6a8720a46f4049cac3b3d26dafb023479c9c3b86a0d3c8be3db0a2d186788e9af1db76d55f3dad127d15185d83d0303d7898641cb6653585a8e1dabfa7f665e61e0498963e329e6e3744bd764db2d72037ae057d89ec0b46ff8e9ff4c37e85c12acddb611c3f636421bef1542c11b04419702cd039d0b1e46c21540d033143440d2fb7dd5d650cf89981c99ee53c6e0374d2b1b6fce03c046fccb95549910767d0543f5e8ce41d66ae6a8720a46f4049cac3b3d26dafb023479c9c3b86a0d3c8be3db0a2d186788e9af1db76d55f3dad127d15185d83d0303d7898641cb6653585a8e1dabfa7f665e61e0498963e329e6e3744bd764db2d72037ae057d89ec0b46ff8e9ff4c37e85c12acddb611c3f636421bef1542c11b04419602cd039d0b1e46c21540d033143440d2fb7dd5d650cf89981c99ee53c6e0374d2b1b6fce03c046fccb95549910767d0543f5e8ce41d66ae6a8720a46f4049cac3b3d26dafb023479c9c3b86a0d3c8be3db0a2d186788e9af1db76d55f3dad127d15185d83d0303d7898641cb6653585a8e1dabfa7f665e61e0498963e329e6e3744bd764db2d72037ae057d89ec0b46ff8e9ff4c37e85c12acddb611c3f636421bef1542c11b0441" ) - ), cost = 1780, newDetails(18), expectedNewCost = 1780, 2010 +: Seq.fill(3)(2012)), + ), cost = 1780, newDetails(18), expectedNewCost = 1780, Seq.fill(4)(2012)), CSigmaProp(data.COR(Array(pk, dht, and, or, threshold))) -> Expected(Success( Helpers.decodeBytes( "00089705cd039d0b1e46c21540d033143440d2fb7dd5d650cf89981c99ee53c6e0374d2b1b6fce03c046fccb95549910767d0543f5e8ce41d66ae6a8720a46f4049cac3b3d26dafb023479c9c3b86a0d3c8be3db0a2d186788e9af1db76d55f3dad127d15185d83d0303d7898641cb6653585a8e1dabfa7f665e61e0498963e329e6e3744bd764db2d72037ae057d89ec0b46ff8e9ff4c37e85c12acddb611c3f636421bef1542c11b04419602cd039d0b1e46c21540d033143440d2fb7dd5d650cf89981c99ee53c6e0374d2b1b6fce03c046fccb95549910767d0543f5e8ce41d66ae6a8720a46f4049cac3b3d26dafb023479c9c3b86a0d3c8be3db0a2d186788e9af1db76d55f3dad127d15185d83d0303d7898641cb6653585a8e1dabfa7f665e61e0498963e329e6e3744bd764db2d72037ae057d89ec0b46ff8e9ff4c37e85c12acddb611c3f636421bef1542c11b04419702cd039d0b1e46c21540d033143440d2fb7dd5d650cf89981c99ee53c6e0374d2b1b6fce03c046fccb95549910767d0543f5e8ce41d66ae6a8720a46f4049cac3b3d26dafb023479c9c3b86a0d3c8be3db0a2d186788e9af1db76d55f3dad127d15185d83d0303d7898641cb6653585a8e1dabfa7f665e61e0498963e329e6e3744bd764db2d72037ae057d89ec0b46ff8e9ff4c37e85c12acddb611c3f636421bef1542c11b0441980204cd039d0b1e46c21540d033143440d2fb7dd5d650cf89981c99ee53c6e0374d2b1b6fce03c046fccb95549910767d0543f5e8ce41d66ae6a8720a46f4049cac3b3d26dafb023479c9c3b86a0d3c8be3db0a2d186788e9af1db76d55f3dad127d15185d83d0303d7898641cb6653585a8e1dabfa7f665e61e0498963e329e6e3744bd764db2d72037ae057d89ec0b46ff8e9ff4c37e85c12acddb611c3f636421bef1542c11b04419702cd039d0b1e46c21540d033143440d2fb7dd5d650cf89981c99ee53c6e0374d2b1b6fce03c046fccb95549910767d0543f5e8ce41d66ae6a8720a46f4049cac3b3d26dafb023479c9c3b86a0d3c8be3db0a2d186788e9af1db76d55f3dad127d15185d83d0303d7898641cb6653585a8e1dabfa7f665e61e0498963e329e6e3744bd764db2d72037ae057d89ec0b46ff8e9ff4c37e85c12acddb611c3f636421bef1542c11b04419602cd039d0b1e46c21540d033143440d2fb7dd5d650cf89981c99ee53c6e0374d2b1b6fce03c046fccb95549910767d0543f5e8ce41d66ae6a8720a46f4049cac3b3d26dafb023479c9c3b86a0d3c8be3db0a2d186788e9af1db76d55f3dad127d15185d83d0303d7898641cb6653585a8e1dabfa7f665e61e0498963e329e6e3744bd764db2d72037ae057d89ec0b46ff8e9ff4c37e85c12acddb611c3f636421bef1542c11b0441" ) - ), cost = 1791, newDetails(36), expectedNewCost = 1791, 2021 +: Seq.fill(3)(2023)) + ), cost = 1791, newDetails(36), expectedNewCost = 1791, Seq.fill(4)(2023)) ) }, existingFeature((x: SigmaProp) => x.propBytes, @@ -9343,7 +9343,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => property("allOf equivalence") { def costDetails(i: Int) = TracedCost(traceBase :+ ast.SeqCostItem(CompanionDesc(AND), PerItemCost(JitCost(10), JitCost(5), 32), i)) - val v3Costs = 1995 +: Seq.fill(3)(1997) + val v3Costs = Seq.fill(4)(1997) verifyCases( Seq( (Coll[Boolean]() -> Expected(Success(true), 1765, costDetails(0), 1765, v3Costs)), @@ -9365,7 +9365,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => property("anyOf equivalence") { def costDetails(i: Int) = TracedCost(traceBase :+ ast.SeqCostItem(CompanionDesc(OR), PerItemCost(JitCost(5), JitCost(5), 64), i)) - val v3Costs = 1994 +: Seq.fill(3)(1996) + val v3Costs = Seq.fill(4)(1996) verifyCases( Seq( (Coll[Boolean]() -> Expected(Success(false), 1764, costDetails(0), 1764, v3Costs)), @@ -9395,7 +9395,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => cost = 1782, costDetails, 1782, - 2012 +: Seq.fill(3)(2014))) + Seq.fill(4)(2014))) ), existingFeature({ (x: GroupElement) => SigmaDsl.proveDlog(x) }, "{ (x: GroupElement) => proveDlog(x) }", @@ -9426,7 +9426,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => cost = 1836, costDetails, 1836, - 2078 +: Seq.fill(3)(2080) + Seq.fill(4)(2080) )) ), existingFeature({ (x: GroupElement) => SigmaDsl.proveDHTuple(x, x, x, x) }, @@ -9481,7 +9481,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => newCost = 1783, newVersionedResults = { val costs = if (activatedVersionInTests >= V6SoftForkVersion) { - 2051 +: Seq.fill(3)(2055) + Seq.fill(4)(2055) } else { Seq.fill(4)(1783) @@ -9499,7 +9499,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => newCost = 1783, newVersionedResults = { val costs = if (activatedVersionInTests >= V6SoftForkVersion) { - 2051 +: Seq.fill(3)(2055) + Seq.fill(4)(2055) } else { Seq.fill(4)(1783) @@ -9511,12 +9511,12 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => }) }), // tree with segregation flag, empty constants array - (Coll(t2.bytes: _*), 0) -> success(Helpers.decodeBytes("100008d3"), costDetails(0), 1783, 2051 +: Seq.fill(3)(2055)), - (Helpers.decodeBytes("100008d3"), 0) -> success(Helpers.decodeBytes("100008d3"), costDetails(0), 1783, 2051 +: Seq.fill(3)(2055)), + (Coll(t2.bytes: _*), 0) -> success(Helpers.decodeBytes("100008d3"), costDetails(0), 1783, Seq.fill(4)(2055)), + (Helpers.decodeBytes("100008d3"), 0) -> success(Helpers.decodeBytes("100008d3"), costDetails(0), 1783, Seq.fill(4)(2055)), // tree with one segregated constant - (Coll(t3.bytes: _*), 0) -> success(Helpers.decodeBytes("100108d27300"), costDetails(1), 1793, 2061 +: Seq.fill(3)(2065)), - (Helpers.decodeBytes("100108d37300"), 0) -> success(Helpers.decodeBytes("100108d27300"), costDetails(1), 1793, 2061 +: Seq.fill(3)(2065)), - (Coll(t3.bytes: _*), 1) -> success(Helpers.decodeBytes("100108d37300"), costDetails(1), 1793, 2061 +: Seq.fill(3)(2065)), + (Coll(t3.bytes: _*), 0) -> success(Helpers.decodeBytes("100108d27300"), costDetails(1), 1793, Seq.fill(4)(2065)), + (Helpers.decodeBytes("100108d37300"), 0) -> success(Helpers.decodeBytes("100108d27300"), costDetails(1), 1793, Seq.fill(4)(2065)), + (Coll(t3.bytes: _*), 1) -> success(Helpers.decodeBytes("100108d37300"), costDetails(1), 1793, Seq.fill(4)(2065)), (Coll(t4.bytes: _*), 0) -> Expected(new IllegalArgumentException("requirement failed: expected new constant to have the same SInt$ tpe, got SSigmaProp")) ) }, @@ -9574,7 +9574,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => if (lowerMethodCallsInTests) { val error = new RuntimeException("any exception") val costs = if (activatedVersionInTests >= V6SoftForkVersion) { - 2140 +: Seq.fill(3)(2144) + Seq.fill(4)(2144) } else { Seq.fill(4)(1776) @@ -9701,7 +9701,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => val keys = Colls.fromArray(Array(Coll[Byte](1, 2, 3, 4, 5))) val initial = Coll[Byte](0, 0, 0, 0, 0) val cases = Seq( - (keys, initial) -> Expected(Success(Coll[Byte](1, 2, 3, 4, 5)), cost = 1801, expectedDetails = CostDetails.ZeroCost, 1801, 2115 +: Seq.fill(3)(2119)) + (keys, initial) -> Expected(Success(Coll[Byte](1, 2, 3, 4, 5)), cost = 1801, expectedDetails = CostDetails.ZeroCost, 1801, Seq.fill(4)(2119)) ) val scalaFunc = { (x: (Coll[Coll[Byte]], Coll[Byte])) => x._1.foldLeft(x._2, { (a: (Coll[Byte], Coll[Byte])) => From 3f7e78469107edb59af1c9d1ec5cb7f20a1641f2 Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Mon, 5 Aug 2024 16:26:47 +0300 Subject: [PATCH 205/314] Scala 2.11 compilation fix, ScalaDoc returned --- .../sigmastate/interpreter/Interpreter.scala | 1 - .../scala/sigma/LanguageSpecificationV6.scala | 17 ++++++++--------- .../scala/sigmastate/lang/SigmaBinderTest.scala | 3 +++ .../sigmastate/utxo/BasicOpsSpecification.scala | 1 - 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/interpreter/shared/src/main/scala/sigmastate/interpreter/Interpreter.scala b/interpreter/shared/src/main/scala/sigmastate/interpreter/Interpreter.scala index e7847ef450..6bdf1656dc 100644 --- a/interpreter/shared/src/main/scala/sigmastate/interpreter/Interpreter.scala +++ b/interpreter/shared/src/main/scala/sigmastate/interpreter/Interpreter.scala @@ -3,7 +3,6 @@ package sigmastate.interpreter import debox.cfor import org.ergoplatform.ErgoLikeContext import org.ergoplatform.validation.ValidationRules._ -import scorex.crypto.encode.Base16 import sigma.VersionContext import sigma.ast.SCollection.SByteArray import sigma.ast.syntax._ diff --git a/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala b/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala index b11c1a7903..382c47403c 100644 --- a/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala +++ b/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala @@ -419,17 +419,15 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite => cost = 1793, expectedDetails = CostDetails.ZeroCost, newCost = 2065, - newVersionedResults = expectedSuccessForAllTreeVersions(Helpers.decodeBytes("100108d27300"), 2065, costDetails(1)), + newVersionedResults = expectedSuccessForAllTreeVersions(Helpers.decodeBytes("100108d27300"), 2065, costDetails(1)) ), // for tree version > 0, the result depend on activated version - { - (Coll(t2.bytes: _*), 0) -> Expected( - Success(expectedTreeBytes_beforeV6), - cost = 1793, - expectedDetails = CostDetails.ZeroCost, - newCost = 2065, - newVersionedResults = expectedSuccessForAllTreeVersions(expectedTreeBytes_V6, 2065, costDetails(1))) - } + (Coll(t2.bytes: _*), 0) -> Expected( + Success(expectedTreeBytes_beforeV6), + cost = 1793, + expectedDetails = CostDetails.ZeroCost, + newCost = 2065, + newVersionedResults = expectedSuccessForAllTreeVersions(expectedTreeBytes_V6, 2065, costDetails(1))) ), changedFeature( changedInVersion = VersionContext.V6SoftForkVersion, @@ -464,4 +462,5 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite => tree.constants.length shouldBe t2.constants.length tree.root shouldBe t2.root } + } diff --git a/sc/shared/src/test/scala/sigmastate/lang/SigmaBinderTest.scala b/sc/shared/src/test/scala/sigmastate/lang/SigmaBinderTest.scala index 1f15f5d747..aa552e9b69 100644 --- a/sc/shared/src/test/scala/sigmastate/lang/SigmaBinderTest.scala +++ b/sc/shared/src/test/scala/sigmastate/lang/SigmaBinderTest.scala @@ -31,6 +31,9 @@ class SigmaBinderTest extends AnyPropSpec with ScalaCheckPropertyChecks with Mat res } + /** Checks that parsing and binding results in the expected value. + * @return the inferred type of the expression + */ def checkBound(env: ScriptEnv, x: String, expected: SValue) = { val bound = bind(env, x) if (expected != bound) { diff --git a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala index b2414d36da..40b6caca4d 100644 --- a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala @@ -24,7 +24,6 @@ import sigma.serialization.ErgoTreeSerializer import sigmastate.utils.Helpers._ import java.math.BigInteger -import scala.reflect.internal.pickling.PickleFormat class BasicOpsSpecification extends CompilerTestingCommons with CompilerCrossVersionProps { From 8b17643d0c94335b67794eac7c97852e729c5610 Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Mon, 5 Aug 2024 17:57:14 +0300 Subject: [PATCH 206/314] fixed regression in CrossVersionProps --- .../shared/src/test/scala/sigmastate/CrossVersionProps.scala | 2 ++ 1 file changed, 2 insertions(+) diff --git a/interpreter/shared/src/test/scala/sigmastate/CrossVersionProps.scala b/interpreter/shared/src/test/scala/sigmastate/CrossVersionProps.scala index e55b874dc3..87101a1f71 100644 --- a/interpreter/shared/src/test/scala/sigmastate/CrossVersionProps.scala +++ b/interpreter/shared/src/test/scala/sigmastate/CrossVersionProps.scala @@ -31,7 +31,9 @@ trait CrossVersionProps extends AnyPropSpecLike with TestsBase { System.gc() } forEachScriptAndErgoTreeVersion(activatedVersions, ergoTreeVersions) { + VersionContext.withVersions(activatedVersionInTests, ergoTreeVersionInTests) { testFun_Run(testName, testFun) + } } } } From b6aad2cb8fe0566c582ce916a7fccd4fe4f6897b Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Mon, 5 Aug 2024 20:01:13 +0300 Subject: [PATCH 207/314] userDefinedInvoke ScalaDoc --- data/shared/src/main/scala/sigma/ast/SMethod.scala | 1 + 1 file changed, 1 insertion(+) diff --git a/data/shared/src/main/scala/sigma/ast/SMethod.scala b/data/shared/src/main/scala/sigma/ast/SMethod.scala index 6bf8d4f9a0..5a17038c54 100644 --- a/data/shared/src/main/scala/sigma/ast/SMethod.scala +++ b/data/shared/src/main/scala/sigma/ast/SMethod.scala @@ -63,6 +63,7 @@ case class MethodIRInfo( * @param docInfo optional human readable method description data * @param costFunc optional specification of how the cost should be computed for the * given method call (See ErgoTreeEvaluator.calcCost method). + * @param userDefinedInvoke optional custom method evaluation function */ case class SMethod( objType: MethodsContainer, From e7fde10e26f8af36bf3de134b00aa2f5d0dce029 Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Tue, 6 Aug 2024 23:49:32 +0300 Subject: [PATCH 208/314] versioned execution depending on tree version, newFeature test --- .../src/main/scala/sigma/ast/SMethod.scala | 15 ++++- .../src/main/scala/sigma/ast/methods.scala | 8 +-- .../src/main/scala/sigma/ast/values.scala | 3 + .../scala/sigma/eval/ErgoTreeEvaluator.scala | 4 -- .../interpreter/CErgoTreeEvaluator.scala | 8 --- .../scala/sigma/LanguageSpecificationV6.scala | 63 ++++++++++--------- .../test/scala/sigma/SigmaDslTesting.scala | 16 ++++- .../TestingInterpreterSpecification.scala | 6 +- 8 files changed, 70 insertions(+), 53 deletions(-) diff --git a/data/shared/src/main/scala/sigma/ast/SMethod.scala b/data/shared/src/main/scala/sigma/ast/SMethod.scala index 5a17038c54..600701506e 100644 --- a/data/shared/src/main/scala/sigma/ast/SMethod.scala +++ b/data/shared/src/main/scala/sigma/ast/SMethod.scala @@ -75,7 +75,8 @@ case class SMethod( irInfo: MethodIRInfo, docInfo: Option[OperationInfo], costFunc: Option[MethodCostFunc], - userDefinedInvoke: Option[SMethod.InvokeHandler] + userDefinedInvoke: Option[SMethod.InvokeHandler], + sinceVersion: Byte ) { /** Operation descriptor of this method. */ @@ -314,7 +315,17 @@ object SMethod { ): SMethod = { SMethod( objType, name, stype, methodId, costKind, explicitTypeArgs, - MethodIRInfo(None, None, None), None, None, None) + MethodIRInfo(None, None, None), None, None, None, 0) + } + + /** Convenience factory method. */ + def apply(objType: MethodsContainer, name: String, stype: SFunc, + methodId: Byte, + costKind: CostKind, + sinceVersion: Byte): SMethod = { + SMethod( + objType, name, stype, methodId, costKind, Nil, + MethodIRInfo(None, None, None), None, None, None, sinceVersion) } diff --git a/data/shared/src/main/scala/sigma/ast/methods.scala b/data/shared/src/main/scala/sigma/ast/methods.scala index c299d9f53a..62164f0f24 100644 --- a/data/shared/src/main/scala/sigma/ast/methods.scala +++ b/data/shared/src/main/scala/sigma/ast/methods.scala @@ -1458,15 +1458,11 @@ case object SHeaderMethods extends MonoTypeMethods { // cost of checkPoW is 700 as about 2*32 hashes required, and 1 hash (id) over short data costs 10 lazy val checkPowMethod = SMethod( - this, "checkPow", SFunc(Array(SHeader), SBoolean), 16, FixedCost(JitCost(700))) + this, "checkPow", SFunc(Array(SHeader), SBoolean), 16, FixedCost(JitCost(700)), + sinceVersion = VersionContext.V6SoftForkVersion) .withIRInfo(MethodCallIrBuilder) .withInfo(MethodCall, "Validate header's proof-of-work") - def checkPow_eval(mc: MethodCall, G: SigmaDslBuilder, header: Header) - (implicit E: ErgoTreeEvaluator): Boolean = { - E.checkPow_eval(mc, header) - } - private lazy val v5Methods = super.getMethods() ++ Seq( idMethod, versionMethod, parentIdMethod, ADProofsRootMethod, stateRootMethod, transactionsRootMethod, timestampMethod, nBitsMethod, heightMethod, extensionRootMethod, minerPkMethod, powOnetimePkMethod, diff --git a/data/shared/src/main/scala/sigma/ast/values.scala b/data/shared/src/main/scala/sigma/ast/values.scala index 87c661a00a..5a372e6c3c 100644 --- a/data/shared/src/main/scala/sigma/ast/values.scala +++ b/data/shared/src/main/scala/sigma/ast/values.scala @@ -1313,6 +1313,9 @@ case class MethodCall( addCost(MethodCall.costKind) // MethodCall overhead method.costKind match { case fixed: FixedCost => + if (method.sinceVersion > 0 && E.context.currentErgoTreeVersion < method.sinceVersion) { + syntax.error(s"Method ${method.name} is not supported in tree version ${E.context.currentErgoTreeVersion}") + } val extra = method.extraDescriptors val extraLen = extra.length val len = args.length diff --git a/data/shared/src/main/scala/sigma/eval/ErgoTreeEvaluator.scala b/data/shared/src/main/scala/sigma/eval/ErgoTreeEvaluator.scala index b95c034bd2..6df82125df 100644 --- a/data/shared/src/main/scala/sigma/eval/ErgoTreeEvaluator.scala +++ b/data/shared/src/main/scala/sigma/eval/ErgoTreeEvaluator.scala @@ -138,10 +138,6 @@ abstract class ErgoTreeEvaluator { def remove_eval( mc: MethodCall, tree: AvlTree, operations: Coll[Coll[Byte]], proof: Coll[Byte]): Option[AvlTree] - - /** Implements evaluation of Header.checkPow method call ErgoTree node. */ - def checkPow_eval(mc: MethodCall, header: Header): Boolean - } object ErgoTreeEvaluator { diff --git a/interpreter/shared/src/main/scala/sigmastate/interpreter/CErgoTreeEvaluator.scala b/interpreter/shared/src/main/scala/sigmastate/interpreter/CErgoTreeEvaluator.scala index c0759f4a5c..a72510f641 100644 --- a/interpreter/shared/src/main/scala/sigmastate/interpreter/CErgoTreeEvaluator.scala +++ b/interpreter/shared/src/main/scala/sigmastate/interpreter/CErgoTreeEvaluator.scala @@ -218,14 +218,6 @@ class CErgoTreeEvaluator( } } - /** Implements evaluation of Header.checkPow method call ErgoTree node. */ - override def checkPow_eval(mc: MethodCall, header: Header): Boolean = { - val checkPowCostInfo = OperationCostInfo(checkPowMethod.costKind.asInstanceOf[FixedCost], NamedDesc("Header.checkPow")) - fixedCostOp(checkPowCostInfo){ - header.checkPow - }(this) - } - /** Evaluates the given expression in the given data environment. */ def eval(env: DataEnv, exp: SValue): Any = { VersionContext.checkVersions(context.activatedScriptVersion, context.currentErgoTreeVersion) diff --git a/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala b/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala index 97ebc575c7..61859a81cc 100644 --- a/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala +++ b/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala @@ -1,10 +1,12 @@ package sigma +import org.ergoplatform.ErgoHeader +import scorex.util.encode.Base16 import sigma.ast.ErgoTree.ZeroHeader import sigma.ast.SCollection.SByteArray import sigma.ast.syntax.TrueSigmaProp import sigma.ast._ -import sigma.data.{CBigInt, ExactNumeric} +import sigma.data.{CBigInt, CHeader, ExactNumeric} import sigma.eval.{CostDetails, SigmaDsl, TracedCost} import sigma.util.Extensions.{BooleanOps, ByteOps, IntOps, LongOps} import sigmastate.exceptions.MethodNotFound @@ -331,34 +333,6 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite => } } - property("Header new methods") { - def checkPoW = newFeature({ (x: Header) => x.checkPow}, - "{ (x: Header) => x.checkPow }", - FuncValue( - Array((1, SHeader)), - MethodCall.typed[Value[SBoolean.type]]( - ValUse(1, SHeader), - SHeaderMethods.getMethodByName("checkPow"), - IndexedSeq(), - Map() - ) - ), - sinceVersion = VersionContext.V6SoftForkVersion) - - if (VersionContext.current.isV6SoftForkActivated) { - forAll { x: Header => - Seq(checkPoW).map(_.checkEquality(x)) - } - } else { - an[Exception] shouldBe thrownBy { - forAll { x: Header => - Seq(checkPoW).map(_.checkEquality(x)) - } - } - } - - } - // TODO v6.0: implement Option.fold (see https://github.com/ScorexFoundation/sigmastate-interpreter/issues/479) property("Option new methods") { val n = ExactNumeric.LongIsExactNumeric @@ -491,4 +465,35 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite => tree.root shouldBe t2.root } + property("Header new methods") { + + def checkPoW = { + newFeature( + { (x: Header) => x.checkPow}, + "{ (x: Header) => x.checkPow }", + FuncValue( + Array((1, SHeader)), + MethodCall.typed[Value[SBoolean.type]]( + ValUse(1, SHeader), + SHeaderMethods.checkPowMethod, + IndexedSeq(), + Map() + ) + ), + sinceVersion = VersionContext.V6SoftForkVersion + ) + } + + // bytes of real mainnet block header at height 614,440 + val headerBytes = "02ac2101807f0000ca01ff0119db227f202201007f62000177a080005d440896d05d3f80dcff7f5e7f59007294c180808d0158d1ff6ba10000f901c7f0ef87dcfff17fffacb6ff7f7f1180d2ff7f1e24ffffe1ff937f807f0797b9ff6ebdae007e5c8c00b8403d3701557181c8df800001b6d5009e2201c6ff807d71808c00019780f087adb3fcdbc0b3441480887f80007f4b01cf7f013ff1ffff564a0000b9a54f00770e807f41ff88c00240000080c0250000000003bedaee069ff4829500b3c07c4d5fe6b3ea3d3bf76c5c28c1d4dcdb1bed0ade0c0000000000003105" + val header1 = new CHeader(ErgoHeader.sigmaSerializer.fromBytes(Base16.decode(headerBytes).get)) + + verifyCases( + Seq( + header1 -> new Expected(ExpectedResult(Success(true), None)) + ), + checkPoW + ) + } + } diff --git a/sc/shared/src/test/scala/sigma/SigmaDslTesting.scala b/sc/shared/src/test/scala/sigma/SigmaDslTesting.scala index 58873449b4..fa1402030b 100644 --- a/sc/shared/src/test/scala/sigma/SigmaDslTesting.scala +++ b/sc/shared/src/test/scala/sigma/SigmaDslTesting.scala @@ -875,7 +875,11 @@ class SigmaDslTesting extends AnyPropSpec vc.activatedVersion >= sinceVersion && vc.ergoTreeVersion >= sinceVersion override def scalaFunc: A => B = { x => - sys.error(s"Semantic Scala function is not defined for old implementation: $this") + if (isSupportedIn(VersionContext.current)) { + scalaFuncNew(x) + } else { + sys.error(s"Semantic Scala function is not defined for old implementation: $this") + } } implicit val cs = compilerSettingsInTests @@ -925,8 +929,14 @@ class SigmaDslTesting extends AnyPropSpec printTestCases: Boolean, failOnTestVectors: Boolean): Unit = { val funcRes = checkEquality(input, printTestCases) - funcRes.isFailure shouldBe true - Try(scalaFunc(input)) shouldBe expected.value + if(!isSupportedIn(VersionContext.current)) { + funcRes.isFailure shouldBe true + } + if(isSupportedIn(VersionContext.current)) { + Try(scalaFunc(input)) shouldBe expected.value + } else { + Try(scalaFunc(input)).isFailure shouldBe true + } } } diff --git a/sc/shared/src/test/scala/sigmastate/TestingInterpreterSpecification.scala b/sc/shared/src/test/scala/sigmastate/TestingInterpreterSpecification.scala index 4ba6b1a9f7..1ab6031109 100644 --- a/sc/shared/src/test/scala/sigmastate/TestingInterpreterSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/TestingInterpreterSpecification.scala @@ -473,7 +473,11 @@ class TestingInterpreterSpecification extends CompilerTestingCommons if (activatedVersionInTests < V6SoftForkVersion) { an [Exception] should be thrownBy testEval(source) } else { - testEval(source) + if(ergoTreeVersionInTests >= V6SoftForkVersion) { + testEval(source) + } else { + an [Exception] should be thrownBy testEval(source) + } } } From 8da35750e295b0fa95e440c21316d147c45b1f1d Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Fri, 9 Aug 2024 17:33:12 +0300 Subject: [PATCH 209/314] fixed tests in LSV6 --- .../scala/sigma/LanguageSpecificationV6.scala | 79 ++++++++++++------- .../test/scala/sigma/SigmaDslTesting.scala | 13 ++- 2 files changed, 60 insertions(+), 32 deletions(-) diff --git a/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala b/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala index 4e6641984b..d63d6aae65 100644 --- a/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala +++ b/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala @@ -467,7 +467,7 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite => property("Option.getOrElse with lazy default") { - val someTrace = TracedCost( + val trace = TracedCost( Array( FixedCostItem(Apply), FixedCostItem(FuncValue), @@ -481,11 +481,11 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite => verifyCases( Seq( - Some(2L) -> Expected(Failure(new java.lang.ArithmeticException("/ by zero")), 6, someTrace, 1793, + Some(2L) -> Expected(Failure(new java.lang.ArithmeticException("/ by zero")), 6, trace, 1793, newVersionedResults = { - expectedSuccessForAllTreeVersions(2L, 2015, someTrace) + expectedSuccessForAllTreeVersions(2L, 2015, trace) } ), - // None -> Expected(Failure(new java.lang.ArithmeticException("/ by zero")), 6) + None -> Expected(Failure(new java.lang.ArithmeticException("/ by zero")), 6, trace, 1793) ), changedFeature( changedInVersion = VersionContext.V6SoftForkVersion, @@ -503,35 +503,56 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite => ) ) } -/* + property("Coll getOrElse with lazy default") { - def getOrElse = newFeature( - (x: (Coll[Int], Int)) => x._1.toArray.toIndexedSeq.unapply(x._2).getOrElse(1 / 0), - "{ (x: (Coll[Int], Int)) => x._1.getOrElse(x._2, 1 / 0) }", - FuncValue( - Array((1, SPair(SCollectionType(SInt), SInt))), - ByIndex( - SelectField.typed[Value[SCollection[SInt.type]]]( - ValUse(1, SPair(SCollectionType(SInt), SInt)), - 1.toByte - ), - SelectField.typed[Value[SInt.type]](ValUse(1, SPair(SCollectionType(SInt), SInt)), 2.toByte), - Some(ArithOp(IntConstant(1), IntConstant(0), OpCode @@ (-99.toByte))) - ) + + val trace = TracedCost( + Array( + FixedCostItem(Apply), + FixedCostItem(FuncValue), + FixedCostItem(GetVar), + FixedCostItem(OptionGet), + FixedCostItem(FuncValue.AddToEnvironmentDesc, FixedCost(JitCost(5))), + FixedCostItem(ValUse), + FixedCostItem(Constant), + FixedCostItem(ByIndex) ) ) - if (VersionContext.current.isV6SoftForkActivated) { - forAll { x: (Coll[Int], Int) => - Seq(getOrElse).map(_.checkEquality(x)) - } - } else { - forAll { x: (Coll[Int], Int) => - if (x._1.isEmpty) { - Seq(getOrElse).map(_.checkEquality(x)) - } - } + def scalaFuncNew(x: Coll[Int]) = { + if (VersionContext.current.isV6SoftForkActivated) { + x.toArray.toIndexedSeq.headOption.getOrElse(1 / 0) + } else scalaFuncOld(x) + } + + def scalaFuncOld(x: Coll[Int]) = { + x.getOrElse(0, 1 / 0) } + + verifyCases( + Seq( + Coll(1) -> Expected(Failure(new java.lang.ArithmeticException("/ by zero")), 6, trace, 1793, + newVersionedResults = { + expectedSuccessForAllTreeVersions(1, 2029, trace) + } ), + Coll[Int]() -> Expected(Failure(new java.lang.ArithmeticException("/ by zero")), 6, trace, 1793) + ), + changedFeature( + changedInVersion = VersionContext.V6SoftForkVersion, + scalaFuncOld, + scalaFuncNew, + "{ (x: Coll[Int]) => x.getOrElse(0, 1 / 0) }", + FuncValue( + Array((1, SCollectionType(SInt))), + ByIndex( + ValUse(1, SCollectionType(SInt)), + IntConstant(0), + Some(ArithOp(IntConstant(1), IntConstant(0), OpCode @@ (-99.toByte))) + ) + ), + allowNewToSucceed = true + ) + ) } - */ + } diff --git a/sc/shared/src/test/scala/sigma/SigmaDslTesting.scala b/sc/shared/src/test/scala/sigma/SigmaDslTesting.scala index 58873449b4..cf2fd98ebf 100644 --- a/sc/shared/src/test/scala/sigma/SigmaDslTesting.scala +++ b/sc/shared/src/test/scala/sigma/SigmaDslTesting.scala @@ -261,6 +261,7 @@ class SigmaDslTesting extends AnyPropSpec s"""Should succeed with the same value or fail with the same exception, but was: |First result: $b1 |Second result: $b2 + |Input: $x |Root cause: $cause |""".stripMargin) } @@ -715,11 +716,17 @@ class SigmaDslTesting extends AnyPropSpec override def checkEquality(input: A, logInputOutput: Boolean = false): Try[(B, CostDetails)] = { // check the old implementation against Scala semantic function var oldRes: Try[(B, CostDetails)] = null - if (ergoTreeVersionInTests < VersionContext.JitActivationVersion) oldRes = VersionContext.withVersions(activatedVersionInTests, ergoTreeVersionInTests) { try checkEq(scalaFunc)(oldF)(input) catch { - case e: TestFailedException => throw e + case e: TestFailedException => + if(activatedVersionInTests < changedInVersion) { + throw e + } else { + // old ergoscript may succeed in new version while old scalafunc may fail, + // see e.g. "Option.getOrElse with lazy default" test + Failure(e) + } case t: Throwable => Failure(t) } @@ -764,7 +771,7 @@ 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) } if (VersionContext.current.activatedVersion < changedInVersion) { From ea0890b126a77f2e8cd0a35d999424d1e495581d Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Mon, 12 Aug 2024 14:04:14 +0300 Subject: [PATCH 210/314] tree versioning removed, scaladoc --- .../src/main/scala/sigma/ast/SMethod.scala | 15 ++---------- .../src/main/scala/sigma/ast/methods.scala | 3 +-- .../src/main/scala/sigma/ast/values.scala | 3 --- .../sigma/pow/Autolykos2PowValidation.scala | 23 ++++++++++++------- .../test/scala/sigma/SigmaDslTesting.scala | 2 +- .../TestingInterpreterSpecification.scala | 6 +---- 6 files changed, 20 insertions(+), 32 deletions(-) diff --git a/data/shared/src/main/scala/sigma/ast/SMethod.scala b/data/shared/src/main/scala/sigma/ast/SMethod.scala index 600701506e..5a17038c54 100644 --- a/data/shared/src/main/scala/sigma/ast/SMethod.scala +++ b/data/shared/src/main/scala/sigma/ast/SMethod.scala @@ -75,8 +75,7 @@ case class SMethod( irInfo: MethodIRInfo, docInfo: Option[OperationInfo], costFunc: Option[MethodCostFunc], - userDefinedInvoke: Option[SMethod.InvokeHandler], - sinceVersion: Byte + userDefinedInvoke: Option[SMethod.InvokeHandler] ) { /** Operation descriptor of this method. */ @@ -315,17 +314,7 @@ object SMethod { ): SMethod = { SMethod( objType, name, stype, methodId, costKind, explicitTypeArgs, - MethodIRInfo(None, None, None), None, None, None, 0) - } - - /** Convenience factory method. */ - def apply(objType: MethodsContainer, name: String, stype: SFunc, - methodId: Byte, - costKind: CostKind, - sinceVersion: Byte): SMethod = { - SMethod( - objType, name, stype, methodId, costKind, Nil, - MethodIRInfo(None, None, None), None, None, None, sinceVersion) + MethodIRInfo(None, None, None), None, None, None) } diff --git a/data/shared/src/main/scala/sigma/ast/methods.scala b/data/shared/src/main/scala/sigma/ast/methods.scala index 62164f0f24..969effd57d 100644 --- a/data/shared/src/main/scala/sigma/ast/methods.scala +++ b/data/shared/src/main/scala/sigma/ast/methods.scala @@ -1458,8 +1458,7 @@ case object SHeaderMethods extends MonoTypeMethods { // cost of checkPoW is 700 as about 2*32 hashes required, and 1 hash (id) over short data costs 10 lazy val checkPowMethod = SMethod( - this, "checkPow", SFunc(Array(SHeader), SBoolean), 16, FixedCost(JitCost(700)), - sinceVersion = VersionContext.V6SoftForkVersion) + this, "checkPow", SFunc(Array(SHeader), SBoolean), 16, FixedCost(JitCost(700))) .withIRInfo(MethodCallIrBuilder) .withInfo(MethodCall, "Validate header's proof-of-work") diff --git a/data/shared/src/main/scala/sigma/ast/values.scala b/data/shared/src/main/scala/sigma/ast/values.scala index 5a372e6c3c..87c661a00a 100644 --- a/data/shared/src/main/scala/sigma/ast/values.scala +++ b/data/shared/src/main/scala/sigma/ast/values.scala @@ -1313,9 +1313,6 @@ case class MethodCall( addCost(MethodCall.costKind) // MethodCall overhead method.costKind match { case fixed: FixedCost => - if (method.sinceVersion > 0 && E.context.currentErgoTreeVersion < method.sinceVersion) { - syntax.error(s"Method ${method.name} is not supported in tree version ${E.context.currentErgoTreeVersion}") - } val extra = method.extraDescriptors val extraLen = extra.length val len = args.length diff --git a/data/shared/src/main/scala/sigma/pow/Autolykos2PowValidation.scala b/data/shared/src/main/scala/sigma/pow/Autolykos2PowValidation.scala index c2166493e6..23cf722194 100644 --- a/data/shared/src/main/scala/sigma/pow/Autolykos2PowValidation.scala +++ b/data/shared/src/main/scala/sigma/pow/Autolykos2PowValidation.scala @@ -8,21 +8,28 @@ import sigma.crypto.{BcDlogGroup, BigIntegers, CryptoConstants} import sigma.util.NBitsUtils /** - * Functions used to validate Autolykos2 Proof-of-Work + * Functions used to validate Autolykos2 Proof-of-Work. */ object Autolykos2PowValidation { type Height = Int - val k = 32 - - val NStart = 26 + /** + * k value for k-sum problem Autolykos is based on (find k numbers in table on N size) + */ + private val k = 32 - val group: BcDlogGroup = CryptoConstants.dlogGroup + /** + * Initial size of N value for k-sum problem Autolykos is based on (find k numbers in table on N size). + * It grows from it since predefined block height in Autolykos 2. + */ + private val NStart = 26 - // Group order, used in Autolykos V.1 for non-outsourceability, - // and also to obtain target in both Autolykos v1 and v2 - val q: BigInt = group.order + /** + * Group order, used in Autolykos V.1 for non-outsourceability, + * and also to obtain target in both Autolykos v1 and v2 + */ + private val q: BigInt = CryptoConstants.dlogGroup.order /** * Number of elements in a table to find k-sum problem solution on top of diff --git a/sc/shared/src/test/scala/sigma/SigmaDslTesting.scala b/sc/shared/src/test/scala/sigma/SigmaDslTesting.scala index fa1402030b..4410786fd4 100644 --- a/sc/shared/src/test/scala/sigma/SigmaDslTesting.scala +++ b/sc/shared/src/test/scala/sigma/SigmaDslTesting.scala @@ -872,7 +872,7 @@ class SigmaDslTesting extends AnyPropSpec extends Feature[A, B] { override def isSupportedIn(vc: VersionContext): Boolean = - vc.activatedVersion >= sinceVersion && vc.ergoTreeVersion >= sinceVersion + vc.activatedVersion >= sinceVersion override def scalaFunc: A => B = { x => if (isSupportedIn(VersionContext.current)) { diff --git a/sc/shared/src/test/scala/sigmastate/TestingInterpreterSpecification.scala b/sc/shared/src/test/scala/sigmastate/TestingInterpreterSpecification.scala index 1ab6031109..4ba6b1a9f7 100644 --- a/sc/shared/src/test/scala/sigmastate/TestingInterpreterSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/TestingInterpreterSpecification.scala @@ -473,11 +473,7 @@ class TestingInterpreterSpecification extends CompilerTestingCommons if (activatedVersionInTests < V6SoftForkVersion) { an [Exception] should be thrownBy testEval(source) } else { - if(ergoTreeVersionInTests >= V6SoftForkVersion) { - testEval(source) - } else { - an [Exception] should be thrownBy testEval(source) - } + testEval(source) } } From 12e888d1b776d276e4013ea21c4187f1f32f4417 Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Mon, 12 Aug 2024 14:38:54 +0300 Subject: [PATCH 211/314] scala 2.11 compilation fix --- .../shared/src/main/scala/sigmastate/eval/CContext.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/interpreter/shared/src/main/scala/sigmastate/eval/CContext.scala b/interpreter/shared/src/main/scala/sigmastate/eval/CContext.scala index 1c464fed37..bed0c4b013 100644 --- a/interpreter/shared/src/main/scala/sigmastate/eval/CContext.scala +++ b/interpreter/shared/src/main/scala/sigmastate/eval/CContext.scala @@ -2,7 +2,7 @@ package sigmastate.eval import debox.cfor import org.ergoplatform.{ErgoLikeTransactionTemplate, UnsignedInput} -import sigma.Evaluation.{stypeToRType, toDslTuple} +import sigma.Evaluation.stypeToRType import sigma.Extensions.ArrayOps import sigma._ import sigma.ast.SType @@ -74,7 +74,7 @@ case class CContext( } override def getVarFromInput[T](inputId: Short, id: Byte)(implicit tT: RType[T]): Option[T] = { - spendingTransaction.inputs.unapply(inputId).flatMap(_.extension.get(id)) match { + spendingTransaction.inputs.lift(inputId).flatMap(_.extension.get(id)) match { case Some(v) if stypeToRType[SType](v.tpe) == tT => Some(v.value.asInstanceOf[T]) case _ => None From b0fbfbbd152bf3c7565135d9e31fd21874c97be7 Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Tue, 13 Aug 2024 16:54:09 +0300 Subject: [PATCH 212/314] fixing getVar typing during tree building, simpler execution for getVarFromInput --- .../src/main/scala/sigma/SigmaDsl.scala | 9 +++ .../sigma/reflection/ReflectionData.scala | 2 +- .../src/main/scala/sigma/ast/SMethod.scala | 5 ++ .../src/main/scala/sigma/ast/methods.scala | 25 +++---- .../src/main/scala/sigma/ast/values.scala | 2 +- .../sigma/compiler/ir/GraphIRReflection.scala | 3 + .../scala/sigma/compiler/ir/MethodCalls.scala | 2 +- .../sigma/compiler/ir/TreeBuilding.scala | 1 + .../ir/wrappers/sigma/impl/SigmaDslImpl.scala | 6 +- .../sigma/compiler/phases/SigmaTyper.scala | 7 +- .../scala/sigma/SigmaDslStaginTests.scala | 2 - .../sigmastate/lang/SigmaTyperTest.scala | 4 ++ .../utxo/BasicOpsSpecification.scala | 68 +++++++++---------- .../utxo/examples/AssetsPartialFilling.scala | 2 - 14 files changed, 75 insertions(+), 63 deletions(-) diff --git a/core/shared/src/main/scala/sigma/SigmaDsl.scala b/core/shared/src/main/scala/sigma/SigmaDsl.scala index ab06306635..8aa154b34e 100644 --- a/core/shared/src/main/scala/sigma/SigmaDsl.scala +++ b/core/shared/src/main/scala/sigma/SigmaDsl.scala @@ -557,6 +557,15 @@ trait Context { */ def getVar[T](id: Byte)(implicit cT: RType[T]): Option[T] + /** + * A variant of `getVar` to extract a context variable by id and type from any input + * + * @param inputId - input index + * @param id - context variable id + * @tparam T - expected type of the variable + * @return Some(value) if the variable is defined in the context AND has the given type. + * None otherwise + */ def getVarFromInput[T](inputId: Short, id: Byte)(implicit cT: RType[T]): Option[T] def vars: Coll[AnyValue] diff --git a/core/shared/src/main/scala/sigma/reflection/ReflectionData.scala b/core/shared/src/main/scala/sigma/reflection/ReflectionData.scala index 76072a2fa4..af9b9135d1 100644 --- a/core/shared/src/main/scala/sigma/reflection/ReflectionData.scala +++ b/core/shared/src/main/scala/sigma/reflection/ReflectionData.scala @@ -274,7 +274,7 @@ object ReflectionData { obj.asInstanceOf[Context].getVar(args(0).asInstanceOf[Byte])(args(1).asInstanceOf[RType[_]]) }, mkMethod(clazz, "getVarFromInput", Array[Class[_]](classOf[Short], classOf[Byte], classOf[RType[_]])) { (obj, args) => - obj.asInstanceOf[Context].getVarFromInput(args(0).asInstanceOf[Byte], args(1).asInstanceOf[Byte])(args(2).asInstanceOf[RType[_]]) + obj.asInstanceOf[Context].getVarFromInput(args(0).asInstanceOf[Short], args(1).asInstanceOf[Byte])(args(2).asInstanceOf[RType[_]]) }, mkMethod(clazz, "headers", Array[Class[_]]()) { (obj, _) => obj.asInstanceOf[Context].headers diff --git a/data/shared/src/main/scala/sigma/ast/SMethod.scala b/data/shared/src/main/scala/sigma/ast/SMethod.scala index 5a17038c54..828be052b4 100644 --- a/data/shared/src/main/scala/sigma/ast/SMethod.scala +++ b/data/shared/src/main/scala/sigma/ast/SMethod.scala @@ -300,6 +300,11 @@ object SMethod { (implicit cT: ClassTag[T], cA1: ClassTag[A1], cA2: ClassTag[A2]): RMethod = RClass(cT.runtimeClass).getMethod(methodName, cA1.runtimeClass, cA2.runtimeClass) + def javaMethodOf[T, A1, A2, A3] + (methodName: String) + (implicit cT: ClassTag[T], cA1: ClassTag[A1], cA2: ClassTag[A2], cA3: ClassTag[A3]): RMethod = + RClass(cT.runtimeClass).getMethod(methodName, cA1.runtimeClass, cA2.runtimeClass, cA3.runtimeClass) + /** Default fallback method call recognizer which builds MethodCall ErgoTree nodes. */ val MethodCallIrBuilder: PartialFunction[(SigmaBuilder, SValue, SMethod, Seq[SValue], STypeSubst), SValue] = { case (builder, obj, method, args, tparamSubst) => diff --git a/data/shared/src/main/scala/sigma/ast/methods.scala b/data/shared/src/main/scala/sigma/ast/methods.scala index 8d8e4e9056..3dbe2d707a 100644 --- a/data/shared/src/main/scala/sigma/ast/methods.scala +++ b/data/shared/src/main/scala/sigma/ast/methods.scala @@ -2,7 +2,6 @@ package sigma.ast import org.ergoplatform._ import org.ergoplatform.validation._ -import sigma.Evaluation.stypeToRType import sigma._ import sigma.ast.SCollection.{SBooleanArray, SBoxArray, SByteArray, SByteArray2, SHeaderArray} import sigma.ast.SMethod.{MethodCallIrBuilder, MethodCostFunc, javaMethodOf} @@ -1427,24 +1426,22 @@ case object SContextMethods extends MonoTypeMethods { lazy val getVarV6Method = SMethod( this, "getVar", SFunc(ContextFuncDom, SOption(tT), Array(paramT)), 11, GetVar.costKind, Seq(tT)) - .withIRInfo(MethodCallIrBuilder) + .withIRInfo( + MethodCallIrBuilder, + javaMethodOf[Context, Byte, RType[_]]("getVar"), + { mtype => Array(mtype.tRange.asOption[SType].elemType) }) .withInfo(MethodCall, "") // todo: desc // todo: costing, desc lazy val getVarFromInputMethod = SMethod( this, "getVarFromInput", SFunc(Array(SContext, SShort, SByte), SOption(tT), Array(paramT)), 12, GetVar.costKind, Seq(tT)) - .withIRInfo(MethodCallIrBuilder) + .withIRInfo( + MethodCallIrBuilder, + javaMethodOf[Context, Short, Byte, RType[_]]("getVarFromInput"), + { mtype => Array(mtype.tRange.asOption[SType].elemType) }) .withInfo(MethodCall, "Multiply this number with \\lst{other} by module Q.", ArgInfo("other", "Number to multiply with this.")) - def getVarFromInput_eval[T](mc: MethodCall, ctx: sigma.Context, inputId: Short, varId: Byte) - (implicit E: ErgoTreeEvaluator): Option[T] = { - // E.addCost(getVarFromInputMethod.costKind) - val rt = stypeToRType(mc.typeSubst.get(tT).get) - val res = ctx.getVarFromInput(inputId, varId)(rt).asInstanceOf[Option[T]] - res - } - - private lazy val commonMethods = Array( + private lazy val commonMethods = super.getMethods() ++ Array( dataInputsMethod, headersMethod, preHeaderMethod, inputsMethod, outputsMethod, heightMethod, selfMethod, selfBoxIndexMethod, lastBlockUtxoRootHashMethod, minerPubKeyMethod ) @@ -1459,9 +1456,9 @@ case object SContextMethods extends MonoTypeMethods { protected override def getMethods(): Seq[SMethod] = { if (VersionContext.current.isV6SoftForkActivated) { - super.getMethods() ++ v6Methods + v6Methods } else { - super.getMethods() ++ v5Methods + v5Methods } } diff --git a/data/shared/src/main/scala/sigma/ast/values.scala b/data/shared/src/main/scala/sigma/ast/values.scala index dace767d9f..87c661a00a 100644 --- a/data/shared/src/main/scala/sigma/ast/values.scala +++ b/data/shared/src/main/scala/sigma/ast/values.scala @@ -1312,7 +1312,7 @@ case class MethodCall( val objV = obj.evalTo[Any](env) addCost(MethodCall.costKind) // MethodCall overhead method.costKind match { - case fixed: FixedCost if method.explicitTypeArgs.isEmpty => + case fixed: FixedCost => val extra = method.extraDescriptors val extraLen = extra.length val len = args.length diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/GraphIRReflection.scala b/sc/shared/src/main/scala/sigma/compiler/ir/GraphIRReflection.scala index 69736a0224..9d1f6c045c 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/GraphIRReflection.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/GraphIRReflection.scala @@ -332,6 +332,9 @@ object GraphIRReflection { mkMethod(clazz, "getVar", Array[Class[_]](classOf[Base#Ref[_]], classOf[TypeDescs#Elem[_]])) { (obj, args) => obj.asInstanceOf[ctx.Context].getVar(args(0).asInstanceOf[ctx.Ref[Byte]])(args(1).asInstanceOf[ctx.Elem[_]]) }, + mkMethod(clazz, "getVarFromInput", Array[Class[_]](classOf[Base#Ref[_]], classOf[Base#Ref[_]], classOf[TypeDescs#Elem[_]])) { (obj, args) => + obj.asInstanceOf[ctx.Context].getVarFromInput(args(0).asInstanceOf[ctx.Ref[Short]], args(1).asInstanceOf[ctx.Ref[Byte]])(args(2).asInstanceOf[ctx.Elem[_]]) + }, mkMethod(clazz, "headers", Array[Class[_]]()) { (obj, args) => obj.asInstanceOf[ctx.Context].headers } diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/MethodCalls.scala b/sc/shared/src/main/scala/sigma/compiler/ir/MethodCalls.scala index 48248f2165..7e7840ab23 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/MethodCalls.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/MethodCalls.scala @@ -27,7 +27,7 @@ trait MethodCalls extends Base { self: IRContext => * given `method`. */ case class MethodCall private[MethodCalls](receiver: Sym, method: RMethod, args: Seq[AnyRef], neverInvoke: Boolean) - (val resultType: Elem[Any], val isAdapterCall: Boolean = false, val typeSubst: Map[STypeVar, SType] = Map()) extends Def[Any] { + (val resultType: Elem[Any], val isAdapterCall: Boolean = false, val typeSubst: Map[STypeVar, SType]) extends Def[Any] { override def mirror(t: Transformer): Ref[Any] = { val len = args.length diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/TreeBuilding.scala b/sc/shared/src/main/scala/sigma/compiler/ir/TreeBuilding.scala index 6826321ccd..41559d53ff 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/TreeBuilding.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/TreeBuilding.scala @@ -1,6 +1,7 @@ package sigma.compiler.ir import org.ergoplatform._ +import sigma.VersionContext import sigma.ast._ import sigma.ast.syntax.{ValueOps, _} import sigma.data.{ProveDHTuple, ProveDlog} diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/SigmaDslImpl.scala b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/SigmaDslImpl.scala index d5bd87d306..dad43e318a 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/SigmaDslImpl.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/SigmaDslImpl.scala @@ -1610,10 +1610,11 @@ object Context extends EntityObject("Context") { } override def getVar[T](id: Ref[Byte])(implicit cT: Elem[T]): Ref[WOption[T]] = { + val st = Evaluation.rtypeToSType(cT.sourceType) asRep[WOption[T]](mkMethodCall(self, ContextClass.getMethod("getVar", classOf[Sym], classOf[Elem[_]]), Array[AnyRef](id, cT), - true, false, element[WOption[T]])) + true, false, element[WOption[T]], Map(tT -> st))) } override def getVarFromInput[T](inputId: Ref[Short], varId: Ref[Byte])(implicit cT: Elem[T]): Ref[WOption[T]] = { @@ -1715,10 +1716,11 @@ object Context extends EntityObject("Context") { } def getVar[T](id: Ref[Byte])(implicit cT: Elem[T]): Ref[WOption[T]] = { + val st = Evaluation.rtypeToSType(cT.sourceType) asRep[WOption[T]](mkMethodCall(source, ContextClass.getMethod("getVar", classOf[Sym], classOf[Elem[_]]), Array[AnyRef](id, cT), - true, true, element[WOption[T]])) + true, true, element[WOption[T]], Map(tT -> st))) } def getVarFromInput[T](inputId: Ref[Short], varId: Ref[Byte])(implicit cT: Elem[T]): Ref[WOption[T]] = { diff --git a/sc/shared/src/main/scala/sigma/compiler/phases/SigmaTyper.scala b/sc/shared/src/main/scala/sigma/compiler/phases/SigmaTyper.scala index 0d53802239..51805b2dea 100644 --- a/sc/shared/src/main/scala/sigma/compiler/phases/SigmaTyper.scala +++ b/sc/shared/src/main/scala/sigma/compiler/phases/SigmaTyper.scala @@ -165,7 +165,7 @@ class SigmaTyper(val builder: SigmaBuilder, .getOrElse(mkMethodCall(newObj, method, newArgs, subst)) } else { val newSelect = mkSelect(newObj, n, Some(concrFunTpe)).withSrcCtx(sel.sourceContext) - mkApply(newSelect, newArgs.toArray[SValue]) + mkApply(newSelect, newArgs) } case Some(method) => error(s"Don't know how to handle method $method in obj $p", sel.sourceContext) @@ -424,11 +424,6 @@ class SigmaTyper(val builder: SigmaBuilder, error(s"Invalid application of type arguments $app: function $input doesn't have type parameters", input.sourceContext) } -// case app @ ApplyTypes(in, targs) => -// val newIn = assignType(env, in) -// ApplyTypes(newIn, targs) -// error(s"Invalid application of type arguments $app: expression doesn't have type parameters") - case If(c, t, e) => val c1 = assignType(env, c).asValue[SBoolean.type] val t1 = assignType(env, t) diff --git a/sc/shared/src/test/scala/sigma/SigmaDslStaginTests.scala b/sc/shared/src/test/scala/sigma/SigmaDslStaginTests.scala index bcd4b21129..266c5e66e5 100644 --- a/sc/shared/src/test/scala/sigma/SigmaDslStaginTests.scala +++ b/sc/shared/src/test/scala/sigma/SigmaDslStaginTests.scala @@ -34,8 +34,6 @@ class SigmaDslStaginTests extends BaseCtxTests with ErgoScriptTestkit with BaseL val ctx: SContext = newContext(10, boxA1, VersionContext.MaxSupportedScriptVersion, VersionContext.MaxSupportedScriptVersion) .withInputs(boxA2) .withVariables(Map(1 -> toAnyValue(30), 2 -> toAnyValue(40))) - val p1: SSigmaProp = sigma.eval.SigmaDsl.SigmaProp(TrivialProp(true)) - val p2: SSigmaProp = sigma.eval.SigmaDsl.SigmaProp(TrivialProp(false)) cake.check(dsl, { env: EnvRep[RSigmaDslBuilder] => for { dsl <- env; arg <- lifted(true) } yield dsl.sigmaProp(arg) }, dsl.sigmaProp(true)) diff --git a/sc/shared/src/test/scala/sigmastate/lang/SigmaTyperTest.scala b/sc/shared/src/test/scala/sigmastate/lang/SigmaTyperTest.scala index c68c37a4dc..4989a265d1 100644 --- a/sc/shared/src/test/scala/sigmastate/lang/SigmaTyperTest.scala +++ b/sc/shared/src/test/scala/sigmastate/lang/SigmaTyperTest.scala @@ -640,6 +640,10 @@ class SigmaTyperTest extends AnyPropSpec typecheck(env, "CONTEXT.dataInputs") shouldBe SCollection(SBox) } + property("SContext.getVar") { + typecheck(env, "CONTEXT.getVar[Int](1.toByte).get") shouldBe SInt + } + property("SAvlTree.digest") { typecheck(env, "getVar[AvlTree](1).get.digest") shouldBe SByteArray } diff --git a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala index f5c9e1cd32..da6c9f361d 100644 --- a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala @@ -142,26 +142,19 @@ class BasicOpsSpecification extends CompilerTestingCommons flexVerifier.verify(verifyEnv, tree, ctxExt, pr.proof, fakeMessage).get._1 shouldBe true } - property("Unit register") { - // TODO frontend: implement missing Unit support in compiler - // https://github.com/ScorexFoundation/sigmastate-interpreter/issues/820 - test("R1", env, ext, - script = "", /* means cannot be compiled - the corresponding script is { SELF.R4[Unit].isDefined } */ - ExtractRegisterAs[SUnit.type](Self, reg1)(SUnit).isDefined.toSigmaProp, - additionalRegistersOpt = Some(Map( - reg1 -> UnitConstant.instance - )) - ) + property("Context.getVar") { + def varTest() = { + test("GetVar1", env, ext, + "{ CONTEXT.getVar[Int](intVar2.toByte).get == 2 }", + null + ) + } - test("R2", env, ext, - script = "", /* means cannot be compiled - the corresponding script is "{ SELF.R4[Unit].get == () }" */ - EQ(ExtractRegisterAs[SUnit.type](Self, reg1)(SUnit).get, UnitConstant.instance).toSigmaProp, - additionalRegistersOpt = Some(Map( - reg1 -> UnitConstant.instance - )) - ) + if(VersionContext.current.isV6SoftForkActivated) { + varTest() + } else { + an[Exception] should be thrownBy(varTest()) + } } property("getVarFromInput") { @@ -456,21 +449,6 @@ class BasicOpsSpecification extends CompilerTestingCommons ) } - property("Context.getVar") { - def varTest() = { - test("GetVar1", env, ext, - "{ CONTEXT.getVar[Int](intVar2).get == 2 }", - null - ) - } - - if(VersionContext.current.isV6SoftForkActivated) { - varTest() - } else { - an[Exception] should be thrownBy(varTest()) - } - } - property("GetVar") { test("GetVar1", env, ext, "{ getVar[Int](intVar2).get == 2 }", @@ -839,4 +817,26 @@ class BasicOpsSpecification extends CompilerTestingCommons test("subst", env, ext, hostScript, null) } + property("Unit register") { + // TODO frontend: implement missing Unit support in compiler + // https://github.com/ScorexFoundation/sigmastate-interpreter/issues/820 + test("R1", env, ext, + script = "", /* means cannot be compiled + the corresponding script is { SELF.R4[Unit].isDefined } */ + ExtractRegisterAs[SUnit.type](Self, reg1)(SUnit).isDefined.toSigmaProp, + additionalRegistersOpt = Some(Map( + reg1 -> UnitConstant.instance + )) + ) + + test("R2", env, ext, + script = "", /* means cannot be compiled + the corresponding script is "{ SELF.R4[Unit].get == () }" */ + EQ(ExtractRegisterAs[SUnit.type](Self, reg1)(SUnit).get, UnitConstant.instance).toSigmaProp, + additionalRegistersOpt = Some(Map( + reg1 -> UnitConstant.instance + )) + ) + } + } diff --git a/sc/shared/src/test/scala/sigmastate/utxo/examples/AssetsPartialFilling.scala b/sc/shared/src/test/scala/sigmastate/utxo/examples/AssetsPartialFilling.scala index 969439fe59..5e89915384 100644 --- a/sc/shared/src/test/scala/sigmastate/utxo/examples/AssetsPartialFilling.scala +++ b/sc/shared/src/test/scala/sigmastate/utxo/examples/AssetsPartialFilling.scala @@ -68,11 +68,9 @@ case class AssetsPartialFilling[Spec <: ContractSpec] val out = OUTPUTS(outIdx) val tokenData = out.R2[Coll[(Coll[Byte], Long)]].get(0) - val tokenId = tokenData._1 val tokenValue = tokenData._2 val selfTokenData = SELF.R2[Coll[(Coll[Byte], Long)]].get(0) - val selfTokenId = selfTokenData._1 val selfTokenValue = selfTokenData._2 val selfValue = SELF.value From 65144a9b9e3745d68effbc494171b47c4b472e04 Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Tue, 13 Aug 2024 18:56:34 +0300 Subject: [PATCH 213/314] merging w. 6.0.0 --- .../src/main/scala/sigma/VersionContext.scala | 2 +- .../src/main/scala/sigma/ast/SType.scala | 30 +- .../validation/ValidationRules.scala | 17 +- .../src/main/scala/sigma/ast/SMethod.scala | 25 +- .../main/scala/sigma/ast/SigmaPredef.scala | 1 - .../src/main/scala/sigma/ast/methods.scala | 2 - .../src/main/scala/sigma/ast/values.scala | 2 + .../serialization/ErgoTreeSerializer.scala | 48 +- .../sigmastate/interpreter/Interpreter.scala | 7 +- .../MethodCallSerializerSpecification.scala | 1 - .../sigma/compiler/phases/SigmaTyper.scala | 3 +- .../sigma/LanguageSpecificationBase.scala | 24 +- .../scala/sigma/LanguageSpecificationV5.scala | 1890 +++++++++-------- .../scala/sigma/LanguageSpecificationV6.scala | 161 +- .../test/scala/sigma/SigmaDslTesting.scala | 84 +- 15 files changed, 1352 insertions(+), 945 deletions(-) diff --git a/core/shared/src/main/scala/sigma/VersionContext.scala b/core/shared/src/main/scala/sigma/VersionContext.scala index 19a4857086..6ede0a1556 100644 --- a/core/shared/src/main/scala/sigma/VersionContext.scala +++ b/core/shared/src/main/scala/sigma/VersionContext.scala @@ -23,7 +23,7 @@ case class VersionContext(activatedVersion: Byte, ergoTreeVersion: Byte) { def isJitActivated: Boolean = activatedVersion >= JitActivationVersion /** @return true, if the activated script version of Ergo protocol on the network is - * including Evolution update. */ + * including v6.0 update. */ def isV6SoftForkActivated: Boolean = activatedVersion >= V6SoftForkVersion } diff --git a/core/shared/src/main/scala/sigma/ast/SType.scala b/core/shared/src/main/scala/sigma/ast/SType.scala index 6656ede3c9..717439bcbb 100644 --- a/core/shared/src/main/scala/sigma/ast/SType.scala +++ b/core/shared/src/main/scala/sigma/ast/SType.scala @@ -7,7 +7,7 @@ import sigma.data.OverloadHack.Overloaded1 import sigma.data.{CBigInt, Nullable, SigmaConstants} import sigma.reflection.{RClass, RMethod, ReflectionData} import sigma.util.Extensions.{IntOps, LongOps, ShortOps} -import sigma.{AvlTree, BigInt, Box, Coll, Context, Evaluation, GroupElement, Header, PreHeader, SigmaDslBuilder, SigmaProp} +import sigma.{AvlTree, BigInt, Box, Coll, Context, Evaluation, GroupElement, Header, PreHeader, SigmaDslBuilder, SigmaProp, VersionContext} import java.math.BigInteger @@ -375,6 +375,7 @@ 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 _ => sys.error(s"Cannot downcast value $v to the type $this") } } @@ -396,6 +397,7 @@ 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 _ => sys.error(s"Cannot downcast value $v to the type $this") } } @@ -419,6 +421,7 @@ 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 _ => sys.error(s"Cannot downcast value $v to the type $this") } } @@ -444,6 +447,7 @@ 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 _ => sys.error(s"Cannot downcast value $v to the type $this") } } @@ -465,24 +469,24 @@ case object SBigInt extends SPrimType with SEmbeddable with SNumericType with SM override def numericTypeIndex: Int = 4 override def upcast(v: AnyVal): BigInt = { - val bi = v match { - case x: Byte => BigInteger.valueOf(x.toLong) - case x: Short => BigInteger.valueOf(x.toLong) - case x: Int => BigInteger.valueOf(x.toLong) - case x: Long => BigInteger.valueOf(x) + v match { + case x: Byte => CBigInt(BigInteger.valueOf(x.toLong)) + 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 _ => sys.error(s"Cannot upcast value $v to the type $this") } - CBigInt(bi) } override def downcast(v: AnyVal): BigInt = { - val bi = v match { - case x: Byte => BigInteger.valueOf(x.toLong) - case x: Short => BigInteger.valueOf(x.toLong) - case x: Int => BigInteger.valueOf(x.toLong) - case x: Long => BigInteger.valueOf(x) + v match { + case x: Byte => CBigInt(BigInteger.valueOf(x.toLong)) + 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 _ => sys.error(s"Cannot downcast value $v to the type $this") } - CBigInt(bi) } } 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 07fe8db0ee..9d4de47a99 100644 --- a/data/shared/src/main/scala/org/ergoplatform/validation/ValidationRules.scala +++ b/data/shared/src/main/scala/org/ergoplatform/validation/ValidationRules.scala @@ -155,20 +155,6 @@ object ValidationRules { override protected lazy val settings: SigmaValidationSettings = currentSettings } - object CheckMinimalErgoTreeVersion extends ValidationRule(1016, - "ErgoTree should have at least required version") with SoftForkWhenReplaced { - override protected lazy val settings: SigmaValidationSettings = currentSettings - - final def apply(currentVersion: Byte, minVersion: Byte): Unit = { - checkRule() - if (currentVersion < minVersion) { - throwValidationException( - new SigmaException(s"ErgoTree should have at least $minVersion version, but was $currentVersion"), - Array(currentVersion, minVersion)) - } - } - } - val ruleSpecs: Seq[ValidationRule] = Seq( CheckDeserializedScriptType, CheckDeserializedScriptIsSigmaProp, @@ -185,8 +171,7 @@ object ValidationRules { CheckHeaderSizeBit, CheckCostFuncOperation, CheckPositionLimit, - CheckLoopLevelInCostFunction, - CheckMinimalErgoTreeVersion + CheckLoopLevelInCostFunction ) /** Validation settings that correspond to the current version of the ErgoScript implementation. diff --git a/data/shared/src/main/scala/sigma/ast/SMethod.scala b/data/shared/src/main/scala/sigma/ast/SMethod.scala index 47f6e744b0..11e656b1be 100644 --- a/data/shared/src/main/scala/sigma/ast/SMethod.scala +++ b/data/shared/src/main/scala/sigma/ast/SMethod.scala @@ -63,6 +63,7 @@ case class MethodIRInfo( * @param docInfo optional human readable method description data * @param costFunc optional specification of how the cost should be computed for the * given method call (See ErgoTreeEvaluator.calcCost method). + * @param userDefinedInvoke optional custom method evaluation function */ case class SMethod( objType: MethodsContainer, @@ -73,7 +74,9 @@ case class SMethod( explicitTypeArgs: Seq[STypeVar], irInfo: MethodIRInfo, docInfo: Option[OperationInfo], - costFunc: Option[MethodCostFunc]) { + costFunc: Option[MethodCostFunc], + userDefinedInvoke: Option[SMethod.InvokeHandler] +) { /** Operation descriptor of this method. */ lazy val opDesc = MethodDesc(this) @@ -114,7 +117,12 @@ case class SMethod( /** Invoke this method on the given object with the arguments. * This is used for methods with FixedCost costKind. */ def invokeFixed(obj: Any, args: Array[Any]): Any = { - javaMethod.invoke(obj, args.asInstanceOf[Array[AnyRef]]:_*) + userDefinedInvoke match { + case Some(h) => + h(this, obj, args) + case None => + javaMethod.invoke(obj, args.asInstanceOf[Array[AnyRef]]:_*) + } } // TODO optimize: avoid lookup when this SMethod is created via `specializeFor` @@ -154,6 +162,11 @@ case class SMethod( m } + /** Create a new instance with the given user-defined invoke handler. */ + def withUserDefinedInvoke(handler: SMethod.InvokeHandler): SMethod = { + copy(userDefinedInvoke = Some(handler)) + } + /** Create a new instance with the given stype. */ def withSType(newSType: SFunc): SMethod = copy(stype = newSType) @@ -263,6 +276,12 @@ object SMethod { */ type InvokeDescBuilder = SFunc => Seq[SType] + /** Type of user-defined function which is called to handle method invocation. + * Instances of this type can be attached to [[SMethod]] instances. + * @see SNumericTypeMethods.ToBytesMethod + */ + type InvokeHandler = (SMethod, Any, Array[Any]) => Any + /** Return [[Method]] descriptor for the given `methodName` on the given `cT` type. * @param methodName the name of the method to lookup * @param cT the class where to search the methodName @@ -297,7 +316,7 @@ object SMethod { ): SMethod = { SMethod( objType, name, stype, methodId, costKind, explicitTypeArgs, - MethodIRInfo(None, None, None), None, None) + MethodIRInfo(None, None, None), None, None, None) } diff --git a/data/shared/src/main/scala/sigma/ast/SigmaPredef.scala b/data/shared/src/main/scala/sigma/ast/SigmaPredef.scala index 7d6da0a5f9..8b89851938 100644 --- a/data/shared/src/main/scala/sigma/ast/SigmaPredef.scala +++ b/data/shared/src/main/scala/sigma/ast/SigmaPredef.scala @@ -5,7 +5,6 @@ import org.ergoplatform.{ErgoAddressEncoder, P2PKAddress} import scorex.util.encode.{Base16, Base58, Base64} import sigma.ast.SCollection.{SByteArray, SIntArray} import sigma.ast.SOption.SIntOption -import sigma.ast.SigmaPropConstant import sigma.ast.syntax._ import sigma.data.Nullable import sigma.exceptions.InvalidArguments diff --git a/data/shared/src/main/scala/sigma/ast/methods.scala b/data/shared/src/main/scala/sigma/ast/methods.scala index 2cfecea15d..ef548d6185 100644 --- a/data/shared/src/main/scala/sigma/ast/methods.scala +++ b/data/shared/src/main/scala/sigma/ast/methods.scala @@ -1,7 +1,6 @@ package sigma.ast import org.ergoplatform._ -import org.ergoplatform.validation.ValidationRules.CheckMinimalErgoTreeVersion import org.ergoplatform.validation._ import sigma._ import sigma.ast.SCollection.{SBooleanArray, SBoxArray, SByteArray, SByteArray2, SHeaderArray} @@ -1534,7 +1533,6 @@ case object SGlobalMethods extends MonoTypeMethods { */ def serialize_eval(mc: MethodCall, G: SigmaDslBuilder, value: SType#WrappedType) (implicit E: ErgoTreeEvaluator): Coll[Byte] = { - CheckMinimalErgoTreeVersion(E.context.currentErgoTreeVersion, VersionContext.V6SoftForkVersion) E.addCost(SigmaByteWriter.StartWriterCost) diff --git a/data/shared/src/main/scala/sigma/ast/values.scala b/data/shared/src/main/scala/sigma/ast/values.scala index dd1f10d9be..ff5da32ec7 100644 --- a/data/shared/src/main/scala/sigma/ast/values.scala +++ b/data/shared/src/main/scala/sigma/ast/values.scala @@ -1298,8 +1298,10 @@ case class MethodCall( method: SMethod, args: IndexedSeq[Value[SType]], typeSubst: Map[STypeVar, SType]) extends Value[SType] { + require(method.explicitTypeArgs.forall(tyArg => typeSubst.contains(tyArg)), s"Generic method call should have concrete type for each explicit type parameter, but was: $this") + override def companion = if (args.isEmpty) PropertyCall else MethodCall override def opType: SFunc = SFunc(obj.tpe +: args.map(_.tpe), tpe) diff --git a/data/shared/src/main/scala/sigma/serialization/ErgoTreeSerializer.scala b/data/shared/src/main/scala/sigma/serialization/ErgoTreeSerializer.scala index ce7d1241c3..5122ee940c 100644 --- a/data/shared/src/main/scala/sigma/serialization/ErgoTreeSerializer.scala +++ b/data/shared/src/main/scala/sigma/serialization/ErgoTreeSerializer.scala @@ -287,6 +287,9 @@ class ErgoTreeSerializer { * allow to use serialized scripts as pre-defined templates. * See [[SubstConstants]] for details. * + * Note, this operation doesn't require (de)serialization of ErgoTree expression, + * thus it is more efficient than serialization roundtrip. + * * @param scriptBytes serialized ErgoTree with ConstantSegregationFlag set to 1. * @param positions zero based indexes in ErgoTree.constants array which * should be replaced with new values @@ -304,21 +307,23 @@ class ErgoTreeSerializer { s"expected positions and newVals to have the same length, got: positions: ${positions.toSeq},\n newVals: ${newVals.toSeq}") val r = SigmaSerializer.startReader(scriptBytes) val (header, _, constants, treeBytes) = deserializeHeaderWithTreeBytes(r) - val w = SigmaSerializer.startWriter() - w.put(header) + val nConstants = constants.length + + val resBytes = if (VersionContext.current.isJitActivated) { + // need to measure the serialized size of the new constants + // by serializing them into a separate writer + val constW = SigmaSerializer.startWriter() - if (VersionContext.current.isJitActivated) { // The following `constants.length` should not be serialized when segregation is off // in the `header`, because in this case there is no `constants` section in the // ErgoTree serialization format. Thus, applying this `substituteConstants` for // non-segregated trees will return non-parsable ErgoTree bytes (when // `constants.length` is put in `w`). if (ErgoTree.isConstantSegregation(header)) { - w.putUInt(constants.length) + constW.putUInt(constants.length) } // The following is optimized O(nConstants + position.length) implementation - val nConstants = constants.length if (nConstants > 0) { val backrefs = getPositionsBackref(positions, nConstants) cfor(0)(_ < nConstants, _ + 1) { i => @@ -326,17 +331,38 @@ class ErgoTreeSerializer { val iPos = backrefs(i) // index to `positions` if (iPos == -1) { // no position => no substitution, serialize original constant - constantSerializer.serialize(c, w) + constantSerializer.serialize(c, constW) } else { - assert(positions(iPos) == i) // INV: backrefs and positions are mutually inverse + require(positions(iPos) == i) // INV: backrefs and positions are mutually inverse val newConst = newVals(iPos) require(c.tpe == newConst.tpe, s"expected new constant to have the same ${c.tpe} tpe, got ${newConst.tpe}") - constantSerializer.serialize(newConst, w) + constantSerializer.serialize(newConst, constW) } } } + + val constBytes = constW.toBytes // nConstants + serialized new constants + + // start composing the resulting tree bytes + val w = SigmaSerializer.startWriter() + w.put(header) // header byte + + if (VersionContext.current.isV6SoftForkActivated) { + // fix in v6.0 to save tree size to respect size bit of the original tree + if (ErgoTree.hasSize(header)) { + val size = constBytes.length + treeBytes.length + w.putUInt(size) // tree size + } + } + + w.putBytes(constBytes) // constants section + w.putBytes(treeBytes) // tree section + w.toBytes } else { + val w = SigmaSerializer.startWriter() + w.put(header) + // for v4.x compatibility we save constants.length here (see the above comment to // understand the consequences) w.putUInt(constants.length) @@ -357,10 +383,12 @@ class ErgoTreeSerializer { case (c, _) => constantSerializer.serialize(c, w) } + + w.putBytes(treeBytes) + w.toBytes } - w.putBytes(treeBytes) - (w.toBytes, constants.length) + (resBytes, nConstants) } } diff --git a/interpreter/shared/src/main/scala/sigmastate/interpreter/Interpreter.scala b/interpreter/shared/src/main/scala/sigmastate/interpreter/Interpreter.scala index 9a1ab11f0e..c54e8bfc46 100644 --- a/interpreter/shared/src/main/scala/sigmastate/interpreter/Interpreter.scala +++ b/interpreter/shared/src/main/scala/sigmastate/interpreter/Interpreter.scala @@ -247,7 +247,12 @@ trait Interpreter { val currCost = addCostChecked(context.initCost, deserializeSubstitutionCost, context.costLimit) val context1 = context.withInitCost(currCost).asInstanceOf[CTX] val (propTree, context2) = trySoftForkable[(SigmaPropValue, CTX)](whenSoftFork = (TrueSigmaProp, context1)) { - applyDeserializeContextJITC(context, prop) + // Before ErgoTree V3 the deserialization cost was not added to the total cost + applyDeserializeContextJITC(if (VersionContext.current.activatedVersion >= VersionContext.V6SoftForkVersion) { + context1 + } else { + context + }, prop) } // here we assume that when `propTree` is TrueProp then `reduceToCrypto` always succeeds diff --git a/interpreter/shared/src/test/scala/sigma/serialization/MethodCallSerializerSpecification.scala b/interpreter/shared/src/test/scala/sigma/serialization/MethodCallSerializerSpecification.scala index e78518f8b3..603b75511d 100644 --- a/interpreter/shared/src/test/scala/sigma/serialization/MethodCallSerializerSpecification.scala +++ b/interpreter/shared/src/test/scala/sigma/serialization/MethodCallSerializerSpecification.scala @@ -2,7 +2,6 @@ package sigma.serialization import sigma.VersionContext import sigma.ast.SCollection.SByteArray -import sigma.ast.SType.tT import sigma.ast._ import sigma.validation.ValidationException diff --git a/sc/shared/src/main/scala/sigma/compiler/phases/SigmaTyper.scala b/sc/shared/src/main/scala/sigma/compiler/phases/SigmaTyper.scala index f9b52fe061..ac30a6cd0a 100644 --- a/sc/shared/src/main/scala/sigma/compiler/phases/SigmaTyper.scala +++ b/sc/shared/src/main/scala/sigma/compiler/phases/SigmaTyper.scala @@ -139,7 +139,8 @@ class SigmaTyper(val builder: SigmaBuilder, obj.tpe match { case p: SProduct => MethodsContainer.getMethod(p, n) match { - case Some(method @ SMethod(_, _, genFunTpe @ SFunc(_, _, _), _, _, _, _, _, _)) => + case Some(method: SMethod) => + val genFunTpe = method.stype val subst = Map(genFunTpe.tpeParams.head.ident -> rangeTpe) val concrFunTpe = applySubst(genFunTpe, subst) val expectedArgs = concrFunTpe.asFunc.tDom.tail diff --git a/sc/shared/src/test/scala/sigma/LanguageSpecificationBase.scala b/sc/shared/src/test/scala/sigma/LanguageSpecificationBase.scala index 2bb44fc910..7be79546e7 100644 --- a/sc/shared/src/test/scala/sigma/LanguageSpecificationBase.scala +++ b/sc/shared/src/test/scala/sigma/LanguageSpecificationBase.scala @@ -1,10 +1,11 @@ package sigma import org.scalatest.BeforeAndAfterAll -import sigma.ast.JitCost -import sigma.eval.{EvalSettings, Profiler} +import sigma.ast.{Apply, FixedCostItem, FuncValue, GetVar, JitCost, OptionGet, ValUse} +import sigma.eval.{CostDetails, EvalSettings, Profiler} import sigmastate.CompilerCrossVersionProps import sigmastate.interpreter.CErgoTreeEvaluator + import scala.util.Success /** Base class for language test suites (one suite for each language version: 5.0, 6.0, etc.) @@ -123,4 +124,23 @@ abstract class LanguageSpecificationBase extends SigmaDslTesting prepareSamples[(PreHeader, PreHeader)] prepareSamples[(Header, Header)] } + + ///===================================================== + /// CostDetails shared among test cases + ///----------------------------------------------------- + val traceBase = Array( + FixedCostItem(Apply), + FixedCostItem(FuncValue), + FixedCostItem(GetVar), + FixedCostItem(OptionGet), + FixedCostItem(FuncValue.AddToEnvironmentDesc, FuncValue.AddToEnvironmentDesc_CostKind), + FixedCostItem(ValUse) + ) + + /** Helper method to create the given expected results for all tree versions. */ + def expectedSuccessForAllTreeVersions[A](value: A, cost: Int, costDetails: CostDetails) = { + val res = ExpectedResult(Success(value), Some(cost)) -> Some(costDetails) + Seq(0, 1, 2, 3).map(version => version -> res) + } + } diff --git a/sc/shared/src/test/scala/sigma/LanguageSpecificationV5.scala b/sc/shared/src/test/scala/sigma/LanguageSpecificationV5.scala index 700b48fd13..af4f93d861 100644 --- a/sc/shared/src/test/scala/sigma/LanguageSpecificationV5.scala +++ b/sc/shared/src/test/scala/sigma/LanguageSpecificationV5.scala @@ -10,6 +10,7 @@ import scorex.crypto.authds.{ADKey, ADValue} import scorex.crypto.hash.{Blake2b256, Digest32} import scorex.util.ModifierId import sigma.Extensions.{ArrayOps, CollOps} +import sigma.VersionContext.V6SoftForkVersion import sigma.ast.ErgoTree.{HeaderType, ZeroHeader} import sigma.ast.SCollection._ import sigma.ast.syntax._ @@ -47,17 +48,6 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => import TestData._ - ///===================================================== - /// CostDetails shared among test cases - ///----------------------------------------------------- - val traceBase = Array( - FixedCostItem(Apply), - FixedCostItem(FuncValue), - FixedCostItem(GetVar), - FixedCostItem(OptionGet), - FixedCostItem(FuncValue.AddToEnvironmentDesc, FuncValue.AddToEnvironmentDesc_CostKind), - FixedCostItem(ValUse) - ) def upcastCostDetails(tpe: SType) = TracedCost(traceBase :+ TypeBasedCostItem(Upcast, tpe)) def downcastCostDetails(tpe: SType) = TracedCost(traceBase :+ TypeBasedCostItem(Downcast, tpe)) def arithOpsCostDetails(tpe: SType) = CostDetails( @@ -144,7 +134,9 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => ) ) val newCost = 1768 - def success(b: Boolean) = Expected(Success(b), 1768, newDetails, newCost) + + def success(b: Boolean) = Expected(Success(b), 1768, newDetails, newCost, Seq.fill(4)(2012)) + val cases = Seq( (true, true) -> success(false), (true, false) -> success(true), @@ -173,14 +165,14 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => val expectedCost = 1768 val newCost = 1768 val cases = Seq( - (true, true) -> Expected(Success(false), expectedCost, newDetails, newCost) + (true, true) -> Expected(Success(false), expectedCost, newDetails, newCost, Seq.fill(4)(2012)) ) verifyCases(cases, feature) val initCost = 100 initialCostInTests.withValue(initCost) { val cases = Seq( - (true, true) -> Expected(Success(false), expectedCost + initCost, newDetails, newCost + initCost) + (true, true) -> Expected(Success(false), expectedCost + initCost, newDetails, newCost + initCost, Seq.fill(4)(2012 + initCost)) ) verifyCases(cases, feature) } @@ -209,7 +201,9 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => FixedCostItem(BinXor) ) ) - def success(b: Boolean) = Expected(Success(b), 1769, newDetails, 1769) + + def success(b: Boolean) = Expected(Success(b), 1769, newDetails, 1769, Seq.fill(4)(2027)) + val cases = Seq( (1095564593, true) -> success(true), (-901834021, true) -> success(true), @@ -246,10 +240,10 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => ) ) val cases = Seq( - (false, true) -> Expected(Success(false), 1766, newDetails1, 1766), - (false, false) -> Expected(Success(false), 1766, newDetails1, 1766), - (true, true) -> Expected(Success(true), 1768, newDetails2, 1768), - (true, false) -> Expected(Success(false), 1768, newDetails2, 1768) + (false, true) -> Expected(Success(false), 1766, newDetails1, 1766, Seq.fill(4)(2010)), + (false, false) -> Expected(Success(false), 1766, newDetails1, 1766, Seq.fill(4)(2010)), + (true, true) -> Expected(Success(true), 1768, newDetails2, 1768, Seq.fill(4)(2012)), + (true, false) -> Expected(Success(false), 1768, newDetails2, 1768, Seq.fill(4)(2012)) ) verifyCases(cases, eq) } @@ -279,10 +273,10 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => ) ) val cases = Seq( - (true, false) -> Expected(Success(true), 1766, newDetails1, 1766), - (true, true) -> Expected(Success(true), 1766, newDetails1, 1766), - (false, false) -> Expected(Success(false), 1768, newDetails2, 1768), - (false, true) -> Expected(Success(true), 1768, newDetails2, 1768) + (true, false) -> Expected(Success(true), 1766, newDetails1, 1766, Seq.fill(4)(2010)), + (true, true) -> Expected(Success(true), 1766, newDetails1, 1766, Seq.fill(4)(2010)), + (false, false) -> Expected(Success(false), 1768, newDetails2, 1768, Seq.fill(4)(2012)), + (false, true) -> Expected(Success(true), 1768, newDetails2, 1768, Seq.fill(4)(2012)) ) verifyCases(cases, eq) } @@ -327,7 +321,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => ) verifyCases( Seq( - (true, Expected(Success(true), 1765, newDetails1, 1765)), + (true, Expected(Success(true), 1765, newDetails1, 1765, Seq.fill(4)(2027))), (false, Expected(new ArithmeticException("/ by zero"))) ), existingFeature((x: Boolean) => x || (1 / 0 == 1), @@ -343,7 +337,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( Seq( (true, Expected(new ArithmeticException("/ by zero"))), - (false, Expected(Success(false), 1765, newDetails2, 1765)) + (false, Expected(Success(false), 1765, newDetails2, 1765, Seq.fill(4)(2027))) ), existingFeature((x: Boolean) => x && (1 / 0 == 1), "{ (x: Boolean) => x && (1 / 0 == 1) }", @@ -357,8 +351,8 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( Seq( - (false, Expected(Success(false), 1765, newDetails2, 1765)), - (true, Expected(Success(true), 1768, newDetails3, 1768)) + (false, Expected(Success(false), 1765, newDetails2, 1765, Seq.fill(4)(2033))), + (true, Expected(Success(true), 1768, newDetails3, 1768, Seq.fill(4)(2036))) ), existingFeature((x: Boolean) => x && (x || (1 / 0 == 1)), "{ (x: Boolean) => x && (x || (1 / 0 == 1)) }", @@ -375,8 +369,8 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( Seq( - (false, Expected(Success(false), 1765, newDetails2, 1765)), - (true, Expected(Success(true), 1770, newDetails4, 1770)) + (false, Expected(Success(false), 1765, newDetails2, 1765, Seq.fill(4)(2039))), + (true, Expected(Success(true), 1770, newDetails4, 1770, Seq.fill(4)(2044))) ), existingFeature((x: Boolean) => x && (x && (x || (1 / 0 == 1))), "{ (x: Boolean) => x && (x && (x || (1 / 0 == 1))) }", @@ -396,8 +390,8 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( Seq( - (false, Expected(Success(false), 1765, newDetails2, 1765)), - (true, Expected(Success(true), 1773, newDetails5, 1773)) + (false, Expected(Success(false), 1765, newDetails2, 1765, Seq.fill(4)(2045))), + (true, Expected(Success(true), 1773, newDetails5, 1773, Seq.fill(4)(2053))) ), existingFeature((x: Boolean) => x && (x && (x && (x || (1 / 0 == 1)))), "{ (x: Boolean) => x && (x && (x && (x || (1 / 0 == 1)))) }", @@ -431,7 +425,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( Seq( (false, Expected(new ArithmeticException("/ by zero"))), - (true, Expected(Success(true), 1773, newDetails6, 1773)) + (true, Expected(Success(true), 1773, newDetails6, 1773, Seq.fill(4)(2075))) ), existingFeature((x: Boolean) => !(!x && (1 / 0 == 1)) && (x || (1 / 0 == 1)), "{ (x: Boolean) => !(!x && (1 / 0 == 1)) && (x || (1 / 0 == 1)) }", @@ -460,7 +454,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => ) verifyCases( Seq( - (true, Expected(Success(true), 1768, newDetails7, 1768)), + (true, Expected(Success(true), 1768, newDetails7, 1768, Seq.fill(4)(2036))), (false, Expected(new ArithmeticException("/ by zero"))) ), existingFeature((x: Boolean) => (x || (1 / 0 == 1)) && x, @@ -486,7 +480,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => ) verifyCases( Seq( - (true, Expected(Success(true), 1770, newDetails8, 1770)), + (true, Expected(Success(true), 1770, newDetails8, 1770, Seq.fill(4)(2068))), (false, Expected(new ArithmeticException("/ by zero"))) ), existingFeature((x: Boolean) => (x || (1 / 0 == 1)) && (x || (1 / 0 == 1)), @@ -518,7 +512,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => ) verifyCases( Seq( - (true, Expected(Success(true), 1775, newDetails9, 1775)), + (true, Expected(Success(true), 1775, newDetails9, 1775, Seq.fill(4)(2107))), (false, Expected(new ArithmeticException("/ by zero"))) ), existingFeature( @@ -568,7 +562,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( Seq( (false, Expected(new ArithmeticException("/ by zero"))), - (true, Expected(Success(true), 1780, newDetails10, 1780)) + (true, Expected(Success(true), 1780, newDetails10, 1780, Seq.fill(4)(2156))) ), existingFeature( (x: Boolean) => (!(!x && (1 / 0 == 1)) || (1 / 0 == 0)) && (!(!x && (1 / 0 == 1)) || (1 / 0 == 1)), @@ -611,7 +605,8 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( { - def expect(v: Byte) = Expected(Success(v), 1763, TracedCost(traceBase), 1763) + def expect(v: Byte) = Expected(Success(v), 1763, TracedCost(traceBase), 1763, Seq.fill(4)(1993)) + Seq( (0.toByte, expect(0.toByte)), (1.toByte, expect(1.toByte)), @@ -628,7 +623,8 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( { - def expected(v: Short) = Expected(Success(v), 1764, upcastCostDetails(SShort), 1764) + def expected(v: Short) = Expected(Success(v), 1764, upcastCostDetails(SShort), 1764, Seq.fill(4)(1998)) + Seq( (0.toByte, expected(0.toShort)), (1.toByte, expected(1.toShort)), @@ -645,7 +641,8 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( { - def expected(v: Int) = Expected(Success(v), 1764, upcastCostDetails(SInt), 1764) + def expected(v: Int) = Expected(Success(v), 1764, upcastCostDetails(SInt), 1764, Seq.fill(4)(1998)) + Seq( (0.toByte, expected(0)), (1.toByte, expected(1)), @@ -662,7 +659,8 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( { - def expected(v: Long) = Expected(Success(v), 1764, upcastCostDetails(SLong), 1764) + def expected(v: Long) = Expected(Success(v), 1764, upcastCostDetails(SLong), 1764, Seq.fill(4)(1998)) + Seq( (0.toByte, expected(0L)), (1.toByte, expected(1L)), @@ -679,7 +677,8 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( { - def expected(v: BigInt) = Expected(Success(v), 1767, upcastCostDetails(SBigInt), 1767) + def expected(v: BigInt) = Expected(Success(v), 1767, upcastCostDetails(SBigInt), 1767, Seq.fill(4)(2001)) + Seq( (0.toByte, expected(CBigInt(new BigInteger("0", 16)))), (1.toByte, expected(CBigInt(new BigInteger("1", 16)))), @@ -697,7 +696,8 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => val n = ExactIntegral.ByteIsExactIntegral verifyCases( { - def success[T](v: (T, (T, (T, (T, T))))) = Expected(Success(v), 1788, arithOpsCostDetails(SByte), 1788) + def success[T](v: (T, (T, (T, (T, T))))) = Expected(Success(v), 1788, arithOpsCostDetails(SByte), 1788, Seq.fill(4)(2116)) + Seq( ((-128.toByte, -128.toByte), Expected(new ArithmeticException("Byte overflow"))), ((-128.toByte, 0.toByte), Expected(new ArithmeticException("/ by zero"))), @@ -796,6 +796,12 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => ((y, x), Expected(res.value, cost, newCostDetails, cost)) } + def swapArgs[A](cases: Seq[((A, A), Expected[Boolean])], cost: Int, newCostDetails: CostDetails, + expectedV3Costs: Seq[Int]) = + cases.map { case ((x, y), res) => + ((y, x), Expected(res.value, cost, newCostDetails, cost, expectedV3Costs)) + } + def newCasesFrom[A, R]( cases: Seq[(A, A)] )( @@ -814,12 +820,19 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => ((x, y), Expected(Success(getExpectedRes(x, y)), cost = cost, expectedDetails = newCostDetails, expectedNewCost = cost)) } - def verifyOp[A: Ordering: Arbitrary] - (cases: Seq[((A, A), Expected[Boolean])], - opName: String, - op: (SValue, SValue) => SValue) - (expectedFunc: (A, A) => Boolean, generateCases: Boolean = true) - (implicit tA: RType[A], sampled: Sampled[(A, A)], evalSettings: EvalSettings) = { + def newCasesFrom3[A, R](cases: Seq[(A, A)]) + (getExpectedRes: (A, A) => R, cost: Int, newCostDetails: CostDetails, + expectedV3Costs: Seq[Int]) = + cases.map { case (x, y) => + ((x, y), Expected(Success(getExpectedRes(x, y)), cost = cost, expectedDetails = newCostDetails, expectedNewCost = cost, expectedV3Costs)) + } + + def verifyOp[A: Ordering : Arbitrary] + (cases: Seq[((A, A), Expected[Boolean])], + opName: String, + op: (SValue, SValue) => SValue) + (expectedFunc: (A, A) => Boolean, generateCases: Boolean = true) + (implicit tA: RType[A], sampled: Sampled[(A, A)], evalSettings: EvalSettings) = { val nameA = RType[A].name val tpeA = Evaluation.rtypeToSType(tA) verifyCases(cases, @@ -844,7 +857,9 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => property("Byte LT, GT, NEQ") { val o = ExactOrdering.ByteIsExactOrdering - def expect(v: Boolean) = Expected(Success(v), 1768, binaryRelationCostDetails(LT, SByte), 1768) + + def expect(v: Boolean) = Expected(Success(v), 1768, binaryRelationCostDetails(LT, SByte), 1768, Seq.fill(4)(2012)) + val LT_cases: Seq[((Byte, Byte), Expected[Boolean])] = Seq( (-128.toByte, -128.toByte) -> expect(false), (-128.toByte, -127.toByte) -> expect(true), @@ -885,16 +900,18 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyOp(LT_cases, "<", LT.apply)(_ < _) verifyOp( - swapArgs(LT_cases, cost = 1768, newCostDetails = binaryRelationCostDetails(GT, SByte)), + swapArgs(LT_cases, cost = 1768, newCostDetails = binaryRelationCostDetails(GT, SByte), expectedV3Costs = Seq.fill(4)(2012)), ">", GT.apply)(_ > _) - val neqCases = newCasesFrom2(LT_cases.map(_._1))(_ != _, cost = 1766, newCostDetails = costNEQ(constNeqCost)) + val neqCases = newCasesFrom3(LT_cases.map(_._1))(_ != _, cost = 1766, newCostDetails = costNEQ(constNeqCost), expectedV3Costs = Seq.fill(4)(2010)) verifyOp(neqCases, "!=", NEQ.apply)(_ != _) } property("Byte LE, GE") { val o = ExactOrdering.ByteIsExactOrdering - def expect(v: Boolean) = Expected(Success(v), 1768, binaryRelationCostDetails(LE, SByte), 1768) + + def expect(v: Boolean) = Expected(Success(v), 1768, binaryRelationCostDetails(LE, SByte), 1768, Seq.fill(4)(2012)) + val LE_cases: Seq[((Byte, Byte), Expected[Boolean])] = Seq( (-128.toByte, -128.toByte) -> expect(true), (-128.toByte, -127.toByte) -> expect(true), @@ -936,7 +953,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyOp(LE_cases, "<=", LE.apply)(_ <= _) verifyOp( - swapArgs(LE_cases, cost = 1768, newCostDetails = binaryRelationCostDetails(GE, SByte)), + swapArgs(LE_cases, cost = 1768, newCostDetails = binaryRelationCostDetails(GE, SByte), expectedV3Costs = Seq.fill(4)(2012)), ">=", GE.apply)(_ >= _) } property("Short methods equivalence") { @@ -945,7 +962,8 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( { - def success[T](v: T) = Expected(Success(v), 1764, downcastCostDetails(SByte), 1764) + def success[T](v: T) = Expected(Success(v), 1764, downcastCostDetails(SByte), 1764, Seq.fill(4)(1998)) + Seq( (Short.MinValue, Expected(new ArithmeticException("Byte overflow"))), (-21626.toShort, Expected(new ArithmeticException("Byte overflow"))), @@ -964,7 +982,8 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( { - def success[T](v: T) = Expected(Success(v), 1763, TracedCost(traceBase), 1763) + def success[T](v: T) = Expected(Success(v), 1763, TracedCost(traceBase), 1763, Seq.fill(4)(1993)) + Seq( (-32768.toShort, success(-32768.toShort)), (-27798.toShort, success(-27798.toShort)), @@ -981,7 +1000,8 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( { - def success[T](v: T) = Expected(Success(v), 1764, upcastCostDetails(SInt), 1764) + def success[T](v: T) = Expected(Success(v), 1764, upcastCostDetails(SInt), 1764, Seq.fill(4)(1998)) + Seq( (-32768.toShort, success(-32768)), (-21064.toShort, success(-21064)), @@ -998,7 +1018,8 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( { - def success[T](v: T) = Expected(Success(v), 1764, upcastCostDetails(SLong), 1764) + def success[T](v: T) = Expected(Success(v), 1764, upcastCostDetails(SLong), 1764, Seq.fill(4)(1998)) + Seq( (-32768.toShort, success(-32768L)), (-23408.toShort, success(-23408L)), @@ -1015,7 +1036,8 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( { - def success(v: BigInt) = Expected(Success(v), 1767, upcastCostDetails(SBigInt), 1767) + def success(v: BigInt) = Expected(Success(v), 1767, upcastCostDetails(SBigInt), 1767, Seq.fill(4)(2001)) + Seq( (-32768.toShort, success(CBigInt(new BigInteger("-8000", 16)))), (-26248.toShort, success(CBigInt(new BigInteger("-6688", 16)))), @@ -1033,7 +1055,8 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => val n = ExactIntegral.ShortIsExactIntegral verifyCases( { - def success[T](v: T) = Expected(Success(v), 1788, arithOpsCostDetails(SShort), 1788) + def success[T](v: T) = Expected(Success(v), 1788, arithOpsCostDetails(SShort), 1788, Seq.fill(4)(2116)) + Seq( ((-32768.toShort, 1.toShort), Expected(new ArithmeticException("Short overflow"))), ((-32768.toShort, 4006.toShort), Expected(new ArithmeticException("Short overflow"))), @@ -1125,7 +1148,9 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => property("Short LT, GT, NEQ") { val o = ExactOrdering.ShortIsExactOrdering - def expect(v: Boolean) = Expected(Success(v), 1768, binaryRelationCostDetails(LT, SShort), 1768) + + def expect(v: Boolean) = Expected(Success(v), 1768, binaryRelationCostDetails(LT, SShort), 1768, Seq.fill(4)(2012)) + val LT_cases: Seq[((Short, Short), Expected[Boolean])] = Seq( (Short.MinValue, Short.MinValue) -> expect(false), (Short.MinValue, (Short.MinValue + 1).toShort) -> expect(true), @@ -1165,15 +1190,17 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyOp(LT_cases, "<", LT.apply)(_ < _) - verifyOp(swapArgs(LT_cases, cost = 1768, newCostDetails = binaryRelationCostDetails(GT, SShort)), ">", GT.apply)(_ > _) + verifyOp(swapArgs(LT_cases, cost = 1768, newCostDetails = binaryRelationCostDetails(GT, SShort), expectedV3Costs = Seq.fill(4)(2012)), ">", GT.apply)(_ > _) - val neqCases = newCasesFrom2(LT_cases.map(_._1))(_ != _, cost = 1766, newCostDetails = costNEQ(constNeqCost)) + val neqCases = newCasesFrom3(LT_cases.map(_._1))(_ != _, cost = 1766, newCostDetails = costNEQ(constNeqCost), expectedV3Costs = Seq.fill(4)(2010)) verifyOp(neqCases, "!=", NEQ.apply)(_ != _) } property("Short LE, GE") { val o = ExactOrdering.ShortIsExactOrdering - def expect(v: Boolean) = Expected(Success(v), 1768, binaryRelationCostDetails(LE, SShort), 1768) + + def expect(v: Boolean) = Expected(Success(v), 1768, binaryRelationCostDetails(LE, SShort), 1768, Seq.fill(4)(2012)) + val LE_cases: Seq[((Short, Short), Expected[Boolean])] = Seq( (Short.MinValue, Short.MinValue) -> expect(true), (Short.MinValue, (Short.MinValue + 1).toShort) -> expect(true), @@ -1215,7 +1242,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyOp(LE_cases, "<=", LE.apply)(_ <= _) verifyOp( - swapArgs(LE_cases, cost = 1768, newCostDetails = binaryRelationCostDetails(GE, SShort)), + swapArgs(LE_cases, cost = 1768, newCostDetails = binaryRelationCostDetails(GE, SShort), expectedV3Costs = Seq.fill(4)(2012)), ">=", GE.apply)(_ >= _) } @@ -1225,7 +1252,8 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( { - def success[T](v: T) = Expected(Success(v), 1764, downcastCostDetails(SByte), 1764) + def success[T](v: T) = Expected(Success(v), 1764, downcastCostDetails(SByte), 1764, Seq.fill(4)(1998)) + Seq( (Int.MinValue, Expected(new ArithmeticException("Byte overflow"))), (-2014394379, Expected(new ArithmeticException("Byte overflow"))), @@ -1244,7 +1272,8 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( { - def success[T](v: T) = Expected(Success(v), 1764, downcastCostDetails(SShort), 1764) + def success[T](v: T) = Expected(Success(v), 1764, downcastCostDetails(SShort), 1764, Seq.fill(4)(1998)) + Seq( (Int.MinValue, Expected(new ArithmeticException("Short overflow"))), (Short.MinValue - 1, Expected(new ArithmeticException("Short overflow"))), @@ -1263,7 +1292,8 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( { - def success[T](v: T) = Expected(Success(v), 1763, TracedCost(traceBase), 1763) + def success[T](v: T) = Expected(Success(v), 1763, TracedCost(traceBase), 1763, Seq.fill(4)(1993)) + Seq( (Int.MinValue, success(Int.MinValue)), (-1, success(-1)), @@ -1278,7 +1308,8 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( { - def success[T](v: T) = Expected(Success(v), 1764, upcastCostDetails(SLong), 1764) + def success[T](v: T) = Expected(Success(v), 1764, upcastCostDetails(SLong), 1764, Seq.fill(4)(1998)) + Seq( (Int.MinValue, success(Int.MinValue.toLong)), (-1, success(-1L)), @@ -1293,7 +1324,8 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( { - def success(v: BigInt) = Expected(Success(v), 1767, upcastCostDetails(SBigInt), 1767) + def success(v: BigInt) = Expected(Success(v), 1767, upcastCostDetails(SBigInt), 1767, Seq.fill(4)(2001)) + Seq( (Int.MinValue, success(CBigInt(new BigInteger("-80000000", 16)))), (-1937187314, success(CBigInt(new BigInteger("-737721f2", 16)))), @@ -1310,57 +1342,59 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => val n = ExactNumeric.IntIsExactNumeric verifyCases( - { - def success[T](v: T) = Expected(Success(v), 1788, arithOpsCostDetails(SInt), 1788) - Seq( - ((Int.MinValue, 449583993), Expected(new ArithmeticException("integer overflow"))), - ((-1589633733, 2147483647), Expected(new ArithmeticException("integer overflow"))), - ((-1585471506, -1), success((-1585471507, (-1585471505, (1585471506, (1585471506, 0)))))), - ((-1569005179, 1230236634), Expected(new ArithmeticException("integer overflow"))), - ((-1493733356, -1319619597), Expected(new ArithmeticException("integer overflow"))), - ((-1100263120, -880052091), Expected(new ArithmeticException("integer overflow"))), - ((-1055955857, 309147303), Expected(new ArithmeticException("integer overflow"))), - ((-569807371, 0), Expected(new ArithmeticException("/ by zero"))), - ((-522264843, 2147483647), Expected(new ArithmeticException("integer overflow"))), - ((-109552389, 0), Expected(new ArithmeticException("/ by zero"))), - ((-1, -2147483648), Expected(new ArithmeticException("integer overflow"))), - ((-1, -1), success((-2, (0, (1, (1, 0)))))), - ((-1, 0), Expected(new ArithmeticException("/ by zero"))), - ((0, -2147483648), Expected(new ArithmeticException("integer overflow"))), - ((1, -1525049432), success((-1525049431, (1525049433, (-1525049432, (0, 1)))))), - ((1, 0), Expected(new ArithmeticException("/ by zero"))), - ((1, 805353746), success((805353747, (-805353745, (805353746, (0, 1)))))), - ((1, 2147483647), Expected(new ArithmeticException("integer overflow"))), - ((475797978, 0), Expected(new ArithmeticException("/ by zero"))), - ((782343922, -1448560539), Expected(new ArithmeticException("integer overflow"))), - ((928769361, 542647292), Expected(new ArithmeticException("integer overflow"))), - ((1568062151, 0), Expected(new ArithmeticException("/ by zero"))), - ((1698252401, -1), success((1698252400, (1698252402, (-1698252401, (-1698252401, 0)))))), - ((1949795740, -1575667037), Expected(new ArithmeticException("integer overflow"))), - ((Int.MaxValue, -1), Expected(new ArithmeticException("integer overflow"))), - ((Int.MaxValue, 1), Expected(new ArithmeticException("integer overflow"))), - ((Int.MaxValue, 1738276576), Expected(new ArithmeticException("integer overflow"))) - ) - }, - existingFeature( - { (x: (Int, Int)) => - val a = x._1; val b = x._2 - val plus = n.plus(a, b) - val minus = n.minus(a, b) - val mul = n.times(a, b) - val div = a / b - val mod = a % b - (plus, (minus, (mul, (div, mod)))) + { + def success[T](v: T) = Expected(Success(v), 1788, arithOpsCostDetails(SInt), 1788, Seq.fill(4)(2116)) + + Seq( + ((Int.MinValue, 449583993), Expected(new ArithmeticException("integer overflow"))), + ((-1589633733, 2147483647), Expected(new ArithmeticException("integer overflow"))), + ((-1585471506, -1), success((-1585471507, (-1585471505, (1585471506, (1585471506, 0)))))), + ((-1569005179, 1230236634), Expected(new ArithmeticException("integer overflow"))), + ((-1493733356, -1319619597), Expected(new ArithmeticException("integer overflow"))), + ((-1100263120, -880052091), Expected(new ArithmeticException("integer overflow"))), + ((-1055955857, 309147303), Expected(new ArithmeticException("integer overflow"))), + ((-569807371, 0), Expected(new ArithmeticException("/ by zero"))), + ((-522264843, 2147483647), Expected(new ArithmeticException("integer overflow"))), + ((-109552389, 0), Expected(new ArithmeticException("/ by zero"))), + ((-1, -2147483648), Expected(new ArithmeticException("integer overflow"))), + ((-1, -1), success((-2, (0, (1, (1, 0)))))), + ((-1, 0), Expected(new ArithmeticException("/ by zero"))), + ((0, -2147483648), Expected(new ArithmeticException("integer overflow"))), + ((1, -1525049432), success((-1525049431, (1525049433, (-1525049432, (0, 1)))))), + ((1, 0), Expected(new ArithmeticException("/ by zero"))), + ((1, 805353746), success((805353747, (-805353745, (805353746, (0, 1)))))), + ((1, 2147483647), Expected(new ArithmeticException("integer overflow"))), + ((475797978, 0), Expected(new ArithmeticException("/ by zero"))), + ((782343922, -1448560539), Expected(new ArithmeticException("integer overflow"))), + ((928769361, 542647292), Expected(new ArithmeticException("integer overflow"))), + ((1568062151, 0), Expected(new ArithmeticException("/ by zero"))), + ((1698252401, -1), success((1698252400, (1698252402, (-1698252401, (-1698252401, 0)))))), + ((1949795740, -1575667037), Expected(new ArithmeticException("integer overflow"))), + ((Int.MaxValue, -1), Expected(new ArithmeticException("integer overflow"))), + ((Int.MaxValue, 1), Expected(new ArithmeticException("integer overflow"))), + ((Int.MaxValue, 1738276576), Expected(new ArithmeticException("integer overflow"))) + ) }, - """{ (x: (Int, Int)) => - | val a = x._1; val b = x._2 - | val plus = a + b - | val minus = a - b - | val mul = a * b - | val div = a / b - | val mod = a % b - | (plus, (minus, (mul, (div, mod)))) - |}""".stripMargin, + existingFeature( + { (x: (Int, Int)) => + val a = x._1; + val b = x._2 + val plus = n.plus(a, b) + val minus = n.minus(a, b) + val mul = n.times(a, b) + val div = a / b + val mod = a % b + (plus, (minus, (mul, (div, mod)))) + }, + """{ (x: (Int, Int)) => + | val a = x._1; val b = x._2 + | val plus = a + b + | val minus = a - b + | val mul = a * b + | val div = a / b + | val mod = a % b + | (plus, (minus, (mul, (div, mod)))) + |}""".stripMargin, FuncValue( Vector((1, STuple(Vector(SInt, SInt)))), BlockValue( @@ -1403,7 +1437,9 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => property("Int LT, GT, NEQ") { val o = ExactOrdering.IntIsExactOrdering - def expect(v: Boolean) = Expected(Success(v), 1768, binaryRelationCostDetails(LT, SInt), 1768) + + def expect(v: Boolean) = Expected(Success(v), 1768, binaryRelationCostDetails(LT, SInt), 1768, Seq.fill(4)(2012)) + val LT_cases: Seq[((Int, Int), Expected[Boolean])] = Seq( (Int.MinValue, Int.MinValue) -> expect(false), (Int.MinValue, (Int.MinValue + 1).toInt) -> expect(true), @@ -1444,16 +1480,16 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyOp(LT_cases, "<", LT.apply)(_ < _) verifyOp( - swapArgs(LT_cases, cost = 1768, newCostDetails = binaryRelationCostDetails(GT, SInt)), + swapArgs(LT_cases, cost = 1768, newCostDetails = binaryRelationCostDetails(GT, SInt), expectedV3Costs = Seq.fill(4)(2012)), ">", GT.apply)(_ > _) - val neqCases = newCasesFrom2(LT_cases.map(_._1))(_ != _, cost = 1766, newCostDetails = costNEQ(constNeqCost)) + val neqCases = newCasesFrom3(LT_cases.map(_._1))(_ != _, cost = 1766, newCostDetails = costNEQ(constNeqCost), expectedV3Costs = Seq.fill(4)(2010)) verifyOp(neqCases, "!=", NEQ.apply)(_ != _) } property("Int LE, GE") { val o = ExactOrdering.IntIsExactOrdering - def expect(v: Boolean) = Expected(Success(v), 1768, binaryRelationCostDetails(LE, SInt), 1768) + def expect(v: Boolean) = Expected(Success(v), 1768, binaryRelationCostDetails(LE, SInt), 1768, Seq.fill(4)(2012)) val LE_cases: Seq[((Int, Int), Expected[Boolean])] = Seq( (Int.MinValue, Int.MinValue) -> expect(true), (Int.MinValue, (Int.MinValue + 1).toInt) -> expect(true), @@ -1495,7 +1531,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyOp(LE_cases, "<=", LE.apply)(_ <= _) verifyOp( - swapArgs(LE_cases, cost = 1768, newCostDetails = binaryRelationCostDetails(GE, SInt)), + swapArgs(LE_cases, cost = 1768, newCostDetails = binaryRelationCostDetails(GE, SInt), expectedV3Costs = Seq.fill(4)(2012)), ">=", GE.apply)(_ >= _) } @@ -1509,7 +1545,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => property("Long.toByte method") { verifyCases( { - def success[T](v: T) = Expected(Success(v), 1764, downcastCostDetails(SByte), 1764) + def success[T](v: T) = Expected(Success(v), 1764, downcastCostDetails(SByte), 1764, Seq.fill(4)(1998)) Seq( (Long.MinValue, Expected(new ArithmeticException("Byte overflow"))), (Byte.MinValue.toLong - 1, Expected(new ArithmeticException("Byte overflow"))), @@ -1530,7 +1566,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => property("Long.toShort method") { verifyCases( { - def success[T](v: T) = Expected(Success(v), 1764, downcastCostDetails(SShort), 1764) + def success[T](v: T) = Expected(Success(v), 1764, downcastCostDetails(SShort), 1764, Seq.fill(4)(1998)) Seq( (Long.MinValue, Expected(new ArithmeticException("Short overflow"))), (Short.MinValue.toLong - 1, Expected(new ArithmeticException("Short overflow"))), @@ -1551,7 +1587,8 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => property("Long.toInt method") { verifyCases( { - def success[T](v: T) = Expected(Success(v), 1764, downcastCostDetails(SInt), 1764) + def success[T](v: T) = Expected(Success(v), 1764, downcastCostDetails(SInt), 1764, Seq.fill(4)(1998)) + Seq( (Long.MinValue, Expected(new ArithmeticException("Int overflow"))), (Int.MinValue.toLong - 1, Expected(new ArithmeticException("Int overflow"))), @@ -1572,7 +1609,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => property("Long.toLong method") { verifyCases( { - def success[T](v: T) = Expected(Success(v), 1763, TracedCost(traceBase), 1763) + def success[T](v: T) = Expected(Success(v), 1763, TracedCost(traceBase), 1763, Seq.fill(4)(1993)) Seq( (Long.MinValue, success(Long.MinValue)), (-1L, success(-1L)), @@ -1589,7 +1626,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => property("Long.toBigInt method") { verifyCases( { - def success(v: BigInt) = Expected(Success(v), 1767, upcastCostDetails(SBigInt), 1767) + def success(v: BigInt) = Expected(Success(v), 1767, upcastCostDetails(SBigInt), 1767, Seq.fill(4)(2001)) Seq( (Long.MinValue, success(CBigInt(new BigInteger("-8000000000000000", 16)))), (-1074651039980347209L, success(CBigInt(new BigInteger("-ee9ed6d57885f49", 16)))), @@ -1609,83 +1646,85 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => val n = ExactNumeric.LongIsExactNumeric verifyCases( - { - def success[T](v: T) = Expected(Success(v), 1788, arithOpsCostDetails(SLong), 1788) - Seq( - ((Long.MinValue, -4677100190307931395L), Expected(new ArithmeticException("long overflow"))), - ((Long.MinValue, -1L), Expected(new ArithmeticException("long overflow"))), - ((Long.MinValue, 1L), Expected(new ArithmeticException("long overflow"))), - ((-9223372036854775808L, 0L), Expected(new ArithmeticException("/ by zero"))), - ((-5828066432064138816L, 9105034716270510411L), Expected(new ArithmeticException("long overflow"))), - ((-4564956247298949325L, -1L), success( - (-4564956247298949326L, (-4564956247298949324L, (4564956247298949325L, (4564956247298949325L, 0L)))) - )), - ((-1499553565058783253L, -3237683216870282569L), Expected(new ArithmeticException("long overflow"))), - ((-1368457031689886112L, 9223372036854775807L), Expected(new ArithmeticException("long overflow"))), - ((-1L, -4354407074688367443L), success((-4354407074688367444L, (4354407074688367442L, (4354407074688367443L, (0L, -1L)))))), - ((-1L, -1L), success((-2L, (0L, (1L, (1L, 0L)))))), - ((-1L, 5665019549505434695L), success((5665019549505434694L, (-5665019549505434696L, (-5665019549505434695L, (0L, -1L)))))), - ((0L, -1L), success((-1L, (1L, (0L, (0L, 0L)))))), - ((0L, 0L), Expected(new ArithmeticException("/ by zero"))), - ((0L, 2112386634269044172L), success((2112386634269044172L, (-2112386634269044172L, (0L, (0L, 0L)))))), - ((2254604056782701370L, -5878231674026236574L), Expected(new ArithmeticException("long overflow"))), - ((2903872550238813643L, 1L), success( - (2903872550238813644L, (2903872550238813642L, (2903872550238813643L, (2903872550238813643L, 0L)))) - )), - ((5091129735284641762L, -427673944382373638L), Expected(new ArithmeticException("long overflow"))), - ((6029085020194630780L, 2261786144956037939L), Expected(new ArithmeticException("long overflow"))), - ((8126382074515995418L, -4746652047588907829L), Expected(new ArithmeticException("long overflow"))), - ((Long.MaxValue, 1L), Expected(new ArithmeticException("long overflow"))), - ((Long.MaxValue, -1L), Expected(new ArithmeticException("long overflow"))) - ) - }, - existingFeature( - { (x: (Long, Long)) => - val a = x._1; val b = x._2 - val plus = n.plus(a, b) - val minus = n.minus(a, b) - val mul = n.times(a, b) - val div = a / b - val mod = a % b - (plus, (minus, (mul, (div, mod)))) + { + def success[T](v: T) = Expected(Success(v), 1788, arithOpsCostDetails(SLong), 1788, Seq.fill(4)(2116)) + Seq( + ((Long.MinValue, -4677100190307931395L), Expected(new ArithmeticException("long overflow"))), + ((Long.MinValue, -1L), Expected(new ArithmeticException("long overflow"))), + ((Long.MinValue, 1L), Expected(new ArithmeticException("long overflow"))), + ((-9223372036854775808L, 0L), Expected(new ArithmeticException("/ by zero"))), + ((-5828066432064138816L, 9105034716270510411L), Expected(new ArithmeticException("long overflow"))), + ((-4564956247298949325L, -1L), success( + (-4564956247298949326L, (-4564956247298949324L, (4564956247298949325L, (4564956247298949325L, 0L)))) + )), + ((-1499553565058783253L, -3237683216870282569L), Expected(new ArithmeticException("long overflow"))), + ((-1368457031689886112L, 9223372036854775807L), Expected(new ArithmeticException("long overflow"))), + ((-1L, -4354407074688367443L), success((-4354407074688367444L, (4354407074688367442L, (4354407074688367443L, (0L, -1L)))))), + ((-1L, -1L), success((-2L, (0L, (1L, (1L, 0L)))))), + ((-1L, 5665019549505434695L), success((5665019549505434694L, (-5665019549505434696L, (-5665019549505434695L, (0L, -1L)))))), + ((0L, -1L), success((-1L, (1L, (0L, (0L, 0L)))))), + ((0L, 0L), Expected(new ArithmeticException("/ by zero"))), + ((0L, 2112386634269044172L), success((2112386634269044172L, (-2112386634269044172L, (0L, (0L, 0L)))))), + ((2254604056782701370L, -5878231674026236574L), Expected(new ArithmeticException("long overflow"))), + ((2903872550238813643L, 1L), success( + (2903872550238813644L, (2903872550238813642L, (2903872550238813643L, (2903872550238813643L, 0L)))) + )), + ((5091129735284641762L, -427673944382373638L), Expected(new ArithmeticException("long overflow"))), + ((6029085020194630780L, 2261786144956037939L), Expected(new ArithmeticException("long overflow"))), + ((8126382074515995418L, -4746652047588907829L), Expected(new ArithmeticException("long overflow"))), + ((Long.MaxValue, 1L), Expected(new ArithmeticException("long overflow"))), + ((Long.MaxValue, -1L), Expected(new ArithmeticException("long overflow"))) + ) }, - """{ (x: (Long, Long)) => - | val a = x._1; val b = x._2 - | val plus = a + b - | val minus = a - b - | val mul = a * b - | val div = a / b - | val mod = a % b - | (plus, (minus, (mul, (div, mod)))) - |}""".stripMargin, - FuncValue( - Vector((1, STuple(Vector(SLong, SLong)))), - BlockValue( - Vector( - ValDef( - 3, - List(), - SelectField.typed[LongValue](ValUse(1, STuple(Vector(SLong, SLong))), 1.toByte) - ), - ValDef( - 4, - List(), - SelectField.typed[LongValue](ValUse(1, STuple(Vector(SLong, SLong))), 2.toByte) - ) - ), - Tuple( + existingFeature( + { (x: (Long, Long)) => + val a = x._1; + val b = x._2 + val plus = n.plus(a, b) + val minus = n.minus(a, b) + val mul = n.times(a, b) + val div = a / b + val mod = a % b + (plus, (minus, (mul, (div, mod)))) + }, + """{ (x: (Long, Long)) => + | val a = x._1; val b = x._2 + | val plus = a + b + | val minus = a - b + | val mul = a * b + | val div = a / b + | val mod = a % b + | (plus, (minus, (mul, (div, mod)))) + |}""".stripMargin, + FuncValue( + Vector((1, STuple(Vector(SLong, SLong)))), + BlockValue( Vector( - ArithOp(ValUse(3, SLong), ValUse(4, SLong), OpCode @@ (-102.toByte)), - Tuple( - Vector( - ArithOp(ValUse(3, SLong), ValUse(4, SLong), OpCode @@ (-103.toByte)), - Tuple( - Vector( - ArithOp(ValUse(3, SLong), ValUse(4, SLong), OpCode @@ (-100.toByte)), - Tuple( - Vector( - ArithOp(ValUse(3, SLong), ValUse(4, SLong), OpCode @@ (-99.toByte)), - ArithOp(ValUse(3, SLong), ValUse(4, SLong), OpCode @@ (-98.toByte)) + ValDef( + 3, + List(), + SelectField.typed[LongValue](ValUse(1, STuple(Vector(SLong, SLong))), 1.toByte) + ), + ValDef( + 4, + List(), + SelectField.typed[LongValue](ValUse(1, STuple(Vector(SLong, SLong))), 2.toByte) + ) + ), + Tuple( + Vector( + ArithOp(ValUse(3, SLong), ValUse(4, SLong), OpCode @@ (-102.toByte)), + Tuple( + Vector( + ArithOp(ValUse(3, SLong), ValUse(4, SLong), OpCode @@ (-103.toByte)), + Tuple( + Vector( + ArithOp(ValUse(3, SLong), ValUse(4, SLong), OpCode @@ (-100.toByte)), + Tuple( + Vector( + ArithOp(ValUse(3, SLong), ValUse(4, SLong), OpCode @@ (-99.toByte)), + ArithOp(ValUse(3, SLong), ValUse(4, SLong), OpCode @@ (-98.toByte)) + ) ) ) ) @@ -1694,13 +1733,12 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => ) ) ) - ) - ))) + ))) } property("Long LT, GT, NEQ") { val o = ExactOrdering.LongIsExactOrdering - def expect(v: Boolean) = Expected(Success(v), 1768, binaryRelationCostDetails(LT, SLong), 1768) + def expect(v: Boolean) = Expected(Success(v), 1768, binaryRelationCostDetails(LT, SLong), 1768, Seq.fill(4)(2012)) val LT_cases: Seq[((Long, Long), Expected[Boolean])] = Seq( (Long.MinValue, Long.MinValue) -> expect(false), (Long.MinValue, (Long.MinValue + 1).toLong) -> expect(true), @@ -1741,16 +1779,16 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyOp(LT_cases, "<", LT.apply)(_ < _) verifyOp( - swapArgs(LT_cases, cost = 1768, newCostDetails = binaryRelationCostDetails(GT, SLong)), + swapArgs(LT_cases, cost = 1768, newCostDetails = binaryRelationCostDetails(GT, SLong), expectedV3Costs = Seq.fill(4)(2012)), ">", GT.apply)(_ > _) - val neqCases = newCasesFrom2(LT_cases.map(_._1))(_ != _, cost = 1766, newCostDetails = costNEQ(constNeqCost)) + val neqCases = newCasesFrom3(LT_cases.map(_._1))(_ != _, cost = 1766, newCostDetails = costNEQ(constNeqCost), Seq.fill(4)(2010)) verifyOp(neqCases, "!=", NEQ.apply)(_ != _) } property("Long LE, GE") { val o = ExactOrdering.LongIsExactOrdering - def expect(v: Boolean) = Expected(Success(v), 1768, binaryRelationCostDetails(LE, SLong), 1768) + def expect(v: Boolean) = Expected(Success(v), 1768, binaryRelationCostDetails(LE, SLong), 1768, Seq.fill(4)(2012)) val LE_cases: Seq[((Long, Long), Expected[Boolean])] = Seq( (Long.MinValue, Long.MinValue) -> expect(true), (Long.MinValue, (Long.MinValue + 1).toLong) -> expect(true), @@ -1792,14 +1830,14 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyOp(LE_cases, "<=", LE.apply)(_ <= _) verifyOp( - swapArgs(LE_cases, cost = 1768, newCostDetails = binaryRelationCostDetails(GE, SLong)), + swapArgs(LE_cases, cost = 1768, newCostDetails = binaryRelationCostDetails(GE, SLong), expectedV3Costs = Seq.fill(4)(2012)), ">=", GE.apply)(_ >= _) } property("BigInt methods equivalence") { verifyCases( { - def success(v: BigInt) = Expected(Success(v), 1764, TracedCost(traceBase), 1764) + def success(v: BigInt) = Expected(Success(v), 1764, TracedCost(traceBase), 1764, Seq.fill(4)(1994)) Seq( (CBigInt(new BigInteger("-85102d7f884ca0e8f56193b46133acaf7e4681e1757d03f191ae4f445c8e0", 16)), success( CBigInt(new BigInteger("-85102d7f884ca0e8f56193b46133acaf7e4681e1757d03f191ae4f445c8e0", 16)) @@ -1820,11 +1858,11 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => val n = NumericOps.BigIntIsExactIntegral verifyCases( - { - def success(v: (BigInt, (BigInt, (BigInt, (BigInt, BigInt))))) = - Expected(Success(v), 1793, arithOpsCostDetails(SBigInt), 1793) - Seq( - ((CBigInt(new BigInteger("-8683d1cd99d5fcf0e6eff6295c285c36526190e13dbde008c49e5ae6fddc1c", 16)), + { + def success(v: (BigInt, (BigInt, (BigInt, (BigInt, BigInt))))) = + Expected(Success(v), 1793, arithOpsCostDetails(SBigInt), 1793, Seq.fill(4)(2121)) + Seq( + ((CBigInt(new BigInteger("-8683d1cd99d5fcf0e6eff6295c285c36526190e13dbde008c49e5ae6fddc1c", 16)), CBigInt(new BigInteger("-2ef55db3f245feddacf0182e299dd", 16))), Expected(new ArithmeticException("BigInteger out of 256 bit range"))), @@ -1946,8 +1984,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => property("BigInt LT, GT, NEQ") { val o = NumericOps.BigIntIsExactOrdering - def expect(v: Boolean) = Expected(Success(v), 1768, binaryRelationCostDetails(LT, SBigInt), 1768) - + def expect(v: Boolean) = Expected(Success(v), 1768, binaryRelationCostDetails(LT, SBigInt), 1768, Seq.fill(4)(2012)) val LT_cases: Seq[((BigInt, BigInt), Expected[Boolean])] = Seq( (BigIntMinValue, BigIntMinValue) -> expect(false), (BigIntMinValue, BigIntMinValue.add(1.toBigInt)) -> expect(true), @@ -1990,11 +2027,11 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyOp(LT_cases, "<", LT.apply)(o.lt(_, _)) verifyOp( - swapArgs(LT_cases, cost = 1768, newCostDetails = binaryRelationCostDetails(GT, SBigInt)), + swapArgs(LT_cases, cost = 1768, newCostDetails = binaryRelationCostDetails(GT, SBigInt), expectedV3Costs = Seq.fill(4)(2012)), ">", GT.apply)(o.gt(_, _)) val constBigIntCost = Array[CostItem](FixedCostItem(NamedDesc("EQ_BigInt"), FixedCost(JitCost(5)))) - val neqCases = newCasesFrom2(LT_cases.map(_._1))(_ != _, cost = 1766, newCostDetails = costNEQ(constBigIntCost)) + val neqCases = newCasesFrom3(LT_cases.map(_._1))(_ != _, cost = 1766, newCostDetails = costNEQ(constBigIntCost), expectedV3Costs = Seq.fill(4)(2010)) verifyOp(neqCases, "!=", NEQ.apply)(_ != _) } @@ -2005,8 +2042,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => val BigIntMaxValue = CBigInt(new BigInteger("7F" + "ff" * 31, 16)) val BigIntOverlimit = CBigInt(new BigInteger("7F" + "ff" * 33, 16)) - def expect(v: Boolean) = Expected(Success(v), 1768, binaryRelationCostDetails(LE, SBigInt), 1768) - + def expect(v: Boolean) = Expected(Success(v), 1768, binaryRelationCostDetails(LE, SBigInt), 1768, Seq.fill(4)(2012)) val LE_cases: Seq[((BigInt, BigInt), Expected[Boolean])] = Seq( (BigIntMinValue, BigIntMinValue) -> expect(true), (BigIntMinValue, BigIntMinValue.add(1.toBigInt)) -> expect(true), @@ -2050,7 +2086,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyOp(LE_cases, "<=", LE.apply)(o.lteq(_, _)) verifyOp( - swapArgs(LE_cases, cost = 1768, newCostDetails = binaryRelationCostDetails(GE, SBigInt)), + swapArgs(LE_cases, cost = 1768, newCostDetails = binaryRelationCostDetails(GE, SBigInt), expectedV3Costs = Seq.fill(4)(2012)), ">=", GE.apply)(o.gteq(_, _)) } @@ -2059,12 +2095,12 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => * @param cost the expected cost of `verify` (the same for all cases) */ def verifyNeq[A: Ordering: Arbitrary: RType] - (x: A, y: A, cost: Int, neqCost: Seq[CostItem] = ArraySeq.empty, newCost: Int) + (x: A, y: A, cost: Int, neqCost: Seq[CostItem] = ArraySeq.empty, newCost: Int, expectedV3Costs: Seq[Int]) (copy: A => A, generateCases: Boolean = true) (implicit sampled: Sampled[(A, A)], evalSettings: EvalSettings) = { val copied_x = copy(x) val newCostDetails = if (neqCost.isEmpty) CostDetails.ZeroCost else costNEQ(neqCost) - def expected(v: Boolean) = Expected(Success(v), cost, newCostDetails, newCost) + def expected(v: Boolean) = Expected(Success(v), cost, newCostDetails, newCost, expectedV3Costs) def expectedNoCost(v: Boolean) = new Expected(ExpectedResult(Success(v), None)) verifyOp(Seq( (x, y) -> expected(true), // check cost only for this test case, because the trace depends in x and y @@ -2077,11 +2113,11 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => } property("NEQ of pre-defined types") { - verifyNeq(ge1, ge2, 1783, Array[CostItem](FixedCostItem(NamedDesc("EQ_GroupElement"), FixedCost(JitCost(172)))), 1783)(_.asInstanceOf[CGroupElement].copy()) - verifyNeq(t1, t2, 1767, Array[CostItem](FixedCostItem(NamedDesc("EQ_AvlTree"), FixedCost(JitCost(6)))), 1767)(_.asInstanceOf[CAvlTree].copy()) - verifyNeq(b1, b2, 1767, Array[CostItem](), 1767)(_.asInstanceOf[CBox].copy()) - verifyNeq(preH1, preH2, 1766, Array[CostItem](FixedCostItem(NamedDesc("EQ_PreHeader"), FixedCost(JitCost(4)))), 1766)(_.asInstanceOf[CPreHeader].copy()) - verifyNeq(h1, h2, 1767, Array[CostItem](FixedCostItem(NamedDesc("EQ_Header"), FixedCost(JitCost(6)))), 1767)(_.asInstanceOf[CHeader].copy()) + verifyNeq(ge1, ge2, 1783, Array[CostItem](FixedCostItem(NamedDesc("EQ_GroupElement"), FixedCost(JitCost(172)))), 1783, Seq.fill(4)(2027))(_.asInstanceOf[CGroupElement].copy()) + verifyNeq(t1, t2, 1767, Array[CostItem](FixedCostItem(NamedDesc("EQ_AvlTree"), FixedCost(JitCost(6)))), 1767, Seq.fill(4)(2019))(_.asInstanceOf[CAvlTree].copy()) + verifyNeq(b1, b2, 1767, Array[CostItem](), 1767, Seq.fill(4)(2019))(_.asInstanceOf[CBox].copy()) + verifyNeq(preH1, preH2, 1766, Array[CostItem](FixedCostItem(NamedDesc("EQ_PreHeader"), FixedCost(JitCost(4)))), 1766, Seq.fill(4)(2018))(_.asInstanceOf[CPreHeader].copy()) + verifyNeq(h1, h2, 1767, Array[CostItem](FixedCostItem(NamedDesc("EQ_Header"), FixedCost(JitCost(6)))), 1767, Seq.fill(4)(2019))(_.asInstanceOf[CHeader].copy()) } property("NEQ of tuples of numerics") { @@ -2089,14 +2125,14 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => FixedCostItem(NamedDesc("EQ_Tuple"), FixedCost(JitCost(4))), FixedCostItem(NamedDesc("EQ_Prim"), FixedCost(JitCost(3))) ) - verifyNeq((0.toByte, 1.toByte), (1.toByte, 1.toByte), 1767, tuplesNeqCost, 1767)(_.copy()) - verifyNeq((0.toShort, 1.toByte), (1.toShort, 1.toByte), 1767, tuplesNeqCost, 1767)(_.copy()) - verifyNeq((0, 1.toByte), (1, 1.toByte), 1767, tuplesNeqCost, 1767)(_.copy()) - verifyNeq((0.toLong, 1.toByte), (1.toLong, 1.toByte), 1767, tuplesNeqCost, 1767)(_.copy()) + verifyNeq((0.toByte, 1.toByte), (1.toByte, 1.toByte), 1767, tuplesNeqCost, 1767, Seq.fill(4)(2019))(_.copy()) + verifyNeq((0.toShort, 1.toByte), (1.toShort, 1.toByte), 1767, tuplesNeqCost, 1767, Seq.fill(4)(2029))(_.copy()) + verifyNeq((0, 1.toByte), (1, 1.toByte), 1767, tuplesNeqCost, 1767, Seq.fill(4)(2029))(_.copy()) + verifyNeq((0.toLong, 1.toByte), (1.toLong, 1.toByte), 1767, tuplesNeqCost, 1767, Seq.fill(4)(2029))(_.copy()) verifyNeq((0.toBigInt, 1.toByte), (1.toBigInt, 1.toByte), 1767, Array( FixedCostItem(NamedDesc("EQ_Tuple"), FixedCost(JitCost(4))), FixedCostItem(NamedDesc("EQ_BigInt"), FixedCost(JitCost(5))) - ), 1767)(_.copy()) + ), 1767, Seq.fill(4)(2029))(_.copy()) } property("NEQ of tuples of pre-defined types") { @@ -2105,30 +2141,29 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => FixedCostItem(NamedDesc("EQ_GroupElement"), FixedCost(JitCost(172))), FixedCostItem(NamedDesc("EQ_GroupElement"), FixedCost(JitCost(172))) ) - verifyNeq((ge1, ge1), (ge1, ge2), 1801, groupNeqCost, 1801)(_.copy()) + verifyNeq((ge1, ge1), (ge1, ge2), 1801, groupNeqCost, 1801, Seq.fill(4)(2053))(_.copy()) val treeNeqCost = Array( FixedCostItem(NamedDesc("EQ_Tuple"), FixedCost(JitCost(4))), FixedCostItem(NamedDesc("EQ_AvlTree"), FixedCost(JitCost(6))), FixedCostItem(NamedDesc("EQ_AvlTree"), FixedCost(JitCost(6))) ) - verifyNeq((t1, t1), (t1, t2), 1768, treeNeqCost, 1768)(_.copy()) - - verifyNeq((b1, b1), (b1, b2), 1768, Array[CostItem](), 1768)(_.copy()) + verifyNeq((t1, t1), (t1, t2), 1768, treeNeqCost, 1768, Seq.fill(4)(2038))(_.copy()) + verifyNeq((b1, b1), (b1, b2), 1768, Array[CostItem](), 1768, Seq.fill(4)(2038))(_.copy()) val preHeaderNeqCost = Array( FixedCostItem(NamedDesc("EQ_Tuple"), FixedCost(JitCost(4))), FixedCostItem(NamedDesc("EQ_PreHeader"), FixedCost(JitCost(4))), FixedCostItem(NamedDesc("EQ_PreHeader"), FixedCost(JitCost(4))) ) - verifyNeq((preH1, preH1), (preH1, preH2), 1767, preHeaderNeqCost, 1767)(_.copy()) + verifyNeq((preH1, preH1), (preH1, preH2), 1767, preHeaderNeqCost, 1767, Seq.fill(4)(2037))(_.copy()) val headerNeqCost = Array( FixedCostItem(NamedDesc("EQ_Tuple"), FixedCost(JitCost(4))), FixedCostItem(NamedDesc("EQ_Header"), FixedCost(JitCost(6))), FixedCostItem(NamedDesc("EQ_Header"), FixedCost(JitCost(6))) ) - verifyNeq((h1, h1), (h1, h2), 1768, headerNeqCost, 1768)(_.copy()) + verifyNeq((h1, h1), (h1, h2), 1768, headerNeqCost, 1768, Seq.fill(4)(2038))(_.copy()) } property("NEQ of nested tuples") { @@ -2212,15 +2247,15 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => FixedCostItem(NamedDesc("EQ_Header"), FixedCost(JitCost(6))), FixedCostItem(NamedDesc("EQ_Header"), FixedCost(JitCost(6))) ) - verifyNeq((ge1, (t1, t1)), (ge1, (t1, t2)), 1785, nestedTuplesNeqCost1, 1785)(_.copy()) - verifyNeq((ge1, (t1, (b1, b1))), (ge1, (t1, (b1, b2))), 1786, nestedTuplesNeqCost2, 1786)(_.copy()) - verifyNeq((ge1, (t1, (b1, (preH1, preH1)))), (ge1, (t1, (b1, (preH1, preH2)))), 1787, nestedTuplesNeqCost3, 1787)(_.copy()) - verifyNeq((ge1, (t1, (b1, (preH1, (h1, h1))))), (ge1, (t1, (b1, (preH1, (h1, h2))))), 1788, nestedTuplesNeqCost4, 1788)(_.copy()) + verifyNeq((ge1, (t1, t1)), (ge1, (t1, t2)), 1785, nestedTuplesNeqCost1, 1785, Seq.fill(4)(2063))(_.copy()) + verifyNeq((ge1, (t1, (b1, b1))), (ge1, (t1, (b1, b2))), 1786, nestedTuplesNeqCost2, 1786, Seq.fill(4)(2080))(_.copy()) + verifyNeq((ge1, (t1, (b1, (preH1, preH1)))), (ge1, (t1, (b1, (preH1, preH2)))), 1787, nestedTuplesNeqCost3, 1787, Seq.fill(4)(2097))(_.copy()) + verifyNeq((ge1, (t1, (b1, (preH1, (h1, h1))))), (ge1, (t1, (b1, (preH1, (h1, h2))))), 1788, nestedTuplesNeqCost4, 1788, Seq.fill(4)(2114))(_.copy()) - verifyNeq(((ge1, t1), t1), ((ge1, t1), t2), 1785, nestedTuplesNeqCost5, 1785)(_.copy()) - verifyNeq((((ge1, t1), b1), b1), (((ge1, t1), b1), b2), 1786, nestedTuplesNeqCost6, 1786)(_.copy()) - verifyNeq((((ge1, t1), b1), (preH1, preH1)), (((ge1, t1), b1), (preH1, preH2)), 1787, nestedTuplesNeqCost7, 1787)(_.copy()) - verifyNeq((((ge1, t1), b1), (preH1, (h1, h1))), (((ge1, t1), b1), (preH1, (h1, h2))), 1788, nestedTuplesNeqCost8, 1788)(_.copy()) + verifyNeq(((ge1, t1), t1), ((ge1, t1), t2), 1785, nestedTuplesNeqCost5, 1785, Seq.fill(4)(2063))(_.copy()) + verifyNeq((((ge1, t1), b1), b1), (((ge1, t1), b1), b2), 1786, nestedTuplesNeqCost6, 1786, Seq.fill(4)(2080))(_.copy()) + verifyNeq((((ge1, t1), b1), (preH1, preH1)), (((ge1, t1), b1), (preH1, preH2)), 1787, nestedTuplesNeqCost7, 1787, Seq.fill(4)(2097))(_.copy()) + verifyNeq((((ge1, t1), b1), (preH1, (h1, h1))), (((ge1, t1), b1), (preH1, (h1, h2))), 1788, nestedTuplesNeqCost8, 1788, Seq.fill(4)(2114))(_.copy()) } property("NEQ of collections of pre-defined types") { @@ -2232,63 +2267,71 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => ast.SeqCostItem(NamedDesc("EQ_COA_Box"), PerItemCost(JitCost(15), JitCost(5), 1), 0) ) implicit val evalSettings = suite.evalSettings.copy(isMeasureOperationTime = false) - verifyNeq(Coll[Byte](), Coll(1.toByte), 1766, collNeqCost1, 1766)(cloneColl(_)) + verifyNeq(Coll[Byte](), Coll(1.toByte), 1766, collNeqCost1, 1766, Seq.fill(4)(2018))(cloneColl(_)) verifyNeq(Coll[Byte](0, 1), Coll(1.toByte, 1.toByte), 1768, Array( FixedCostItem(NamedDesc("MatchType"), FixedCost(JitCost(1))), ast.SeqCostItem(NamedDesc("EQ_COA_Byte"), PerItemCost(JitCost(15), JitCost(2), 128), 1)), - 1768 + 1768, + Seq.fill(4)(2020) )(cloneColl(_)) - verifyNeq(Coll[Short](), Coll(1.toShort), 1766, collNeqCost1, 1766)(cloneColl(_)) + verifyNeq(Coll[Short](), Coll(1.toShort), 1766, collNeqCost1, 1766, Seq.fill(4)(2018))(cloneColl(_)) verifyNeq(Coll[Short](0), Coll(1.toShort), 1768, Array( FixedCostItem(NamedDesc("MatchType"), FixedCost(JitCost(1))), ast.SeqCostItem(NamedDesc("EQ_COA_Short"), PerItemCost(JitCost(15), JitCost(2), 96), 1)), - 1768 + 1768, + Seq.fill(4)(2020) )(cloneColl(_)) - verifyNeq(Coll[Int](), Coll(1), 1766, collNeqCost1, 1766)(cloneColl(_)) + verifyNeq(Coll[Int](), Coll(1), 1766, collNeqCost1, 1766, Seq.fill(4)(2018))(cloneColl(_)) verifyNeq(Coll[Int](0), Coll(1), 1768, Array( FixedCostItem(NamedDesc("MatchType"), FixedCost(JitCost(1))), ast.SeqCostItem(NamedDesc("EQ_COA_Int"), PerItemCost(JitCost(15), JitCost(2), 64), 1)), - 1768 + 1768, + Seq.fill(4)(2020) )(cloneColl(_)) - verifyNeq(Coll[Long](), Coll(1.toLong), 1766, collNeqCost1, 1766)(cloneColl(_)) + verifyNeq(Coll[Long](), Coll(1.toLong), 1766, collNeqCost1, 1766, Seq.fill(4)(2018))(cloneColl(_)) verifyNeq(Coll[Long](0), Coll(1.toLong), 1768, Array( FixedCostItem(NamedDesc("MatchType"), FixedCost(JitCost(1))), ast.SeqCostItem(NamedDesc("EQ_COA_Long"), PerItemCost(JitCost(15), JitCost(2), 48), 1)), - 1768 + 1768, + Seq.fill(4)(2020) )(cloneColl(_)) prepareSamples[Coll[BigInt]] - verifyNeq(Coll[BigInt](), Coll(1.toBigInt), 1766, collNeqCost1, 1766)(cloneColl(_)) + verifyNeq(Coll[BigInt](), Coll(1.toBigInt), 1766, collNeqCost1, 1766, Seq.fill(4)(2018))(cloneColl(_)) verifyNeq(Coll[BigInt](0.toBigInt), Coll(1.toBigInt), 1768, Array( FixedCostItem(NamedDesc("MatchType"), FixedCost(JitCost(1))), ast.SeqCostItem(NamedDesc("EQ_COA_BigInt"), PerItemCost(JitCost(15), JitCost(7), 5), 1)), - 1768 + 1768, + Seq.fill(4)(2020) )(cloneColl(_)) prepareSamples[Coll[GroupElement]] - verifyNeq(Coll[GroupElement](), Coll(ge1), 1766, collNeqCost1, 1766)(cloneColl(_)) + verifyNeq(Coll[GroupElement](), Coll(ge1), 1766, collNeqCost1, 1766, Seq.fill(4)(2018))(cloneColl(_)) verifyNeq(Coll[GroupElement](ge1), Coll(ge2), 1768, Array( FixedCostItem(NamedDesc("MatchType"), FixedCost(JitCost(1))), ast.SeqCostItem(NamedDesc("EQ_COA_GroupElement"), PerItemCost(JitCost(15), JitCost(5), 1), 1)), - 1768 + 1768, + Seq.fill(4)(2020) )(cloneColl(_)) prepareSamples[Coll[AvlTree]] - verifyNeq(Coll[AvlTree](), Coll(t1), 1766, collNeqCost1, 1766)(cloneColl(_)) + verifyNeq(Coll[AvlTree](), Coll(t1), 1766, collNeqCost1, 1766, Seq.fill(4)(2028))(cloneColl(_)) + verifyNeq(Coll[AvlTree](t1), Coll(t2), 1768, Array( FixedCostItem(NamedDesc("MatchType"), FixedCost(JitCost(1))), ast.SeqCostItem(NamedDesc("EQ_COA_AvlTree"), PerItemCost(JitCost(15), JitCost(5), 2), 1)), - 1768 + 1768, + Seq.fill(4)(2030) )(cloneColl(_)) { // since SBox.isConstantSize = false, the cost is different among cases @@ -2297,38 +2340,40 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => val y = Coll(b1) val copied_x = cloneColl(x) verifyOp(Seq( - (x, x) -> Expected(Success(false), 1768, costNEQ(collNeqCost2), 1768), - (x, copied_x) -> Expected(Success(false), 1768, costNEQ(collNeqCost2), 1768), - (copied_x, x) -> Expected(Success(false), 1768, costNEQ(collNeqCost2), 1768), - (x, y) -> Expected(Success(true), 1766, costNEQ(collNeqCost1), 1766), - (y, x) -> Expected(Success(true), 1766, costNEQ(collNeqCost1), 1766) - ), + (x, x) -> Expected(Success(false), 1768, costNEQ(collNeqCost2), 1768, Seq.fill(4)(2030)), + (x, copied_x) -> Expected(Success(false), 1768, costNEQ(collNeqCost2), 1768, Seq.fill(4)(2030)), + (copied_x, x) -> Expected(Success(false), 1768, costNEQ(collNeqCost2), 1768, Seq.fill(4)(2030)), + (x, y) -> Expected(Success(true), 1766, costNEQ(collNeqCost1), 1766, Seq.fill(4)(2028)), + (y, x) -> Expected(Success(true), 1766, costNEQ(collNeqCost1), 1766, Seq.fill(4)(2028)) + ), "!=", NEQ.apply)(_ != _, generateCases = false) verifyNeq(Coll[Box](b1), Coll(b2), 1768, Array( FixedCostItem(NamedDesc("MatchType"), FixedCost(JitCost(1))), ast.SeqCostItem(NamedDesc("EQ_COA_Box"), PerItemCost(JitCost(15), JitCost(5), 1), 1)), - 1768 + 1768, + Seq.fill(4)(2030) )(cloneColl(_), generateCases = false) } prepareSamples[Coll[PreHeader]] - verifyNeq(Coll[PreHeader](), Coll(preH1), 1766, collNeqCost1, 1766)(cloneColl(_)) + verifyNeq(Coll[PreHeader](), Coll(preH1), 1766, collNeqCost1, 1766, Seq.fill(4)(2028))(cloneColl(_)) verifyNeq(Coll[PreHeader](preH1), Coll(preH2), 1768, Array( FixedCostItem(NamedDesc("MatchType"), FixedCost(JitCost(1))), ast.SeqCostItem(NamedDesc("EQ_COA_PreHeader"), PerItemCost(JitCost(15), JitCost(3), 1), 1)), - 1768 + 1768, + Seq.fill(4)(2030) )(cloneColl(_)) prepareSamples[Coll[Header]] - verifyNeq(Coll[Header](), Coll(h1), 1766, collNeqCost1, 1766)(cloneColl(_)) + verifyNeq(Coll[Header](), Coll(h1), 1766, collNeqCost1, 1766, Seq.fill(4)(2028))(cloneColl(_)) verifyNeq(Coll[Header](h1), Coll(h2), 1768, Array( FixedCostItem(NamedDesc("MatchType"), FixedCost(JitCost(1))), ast.SeqCostItem(NamedDesc("EQ_COA_Header"), PerItemCost(JitCost(15), JitCost(5), 1), 1)), - 1768 + 1768, Seq.fill(4)(2030) )(cloneColl(_)) } @@ -2352,10 +2397,10 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => ast.SeqCostItem(NamedDesc("EQ_COA_Int"), PerItemCost(JitCost(15), JitCost(2), 64), 1), ast.SeqCostItem(NamedDesc("EQ_Coll"), PerItemCost(JitCost(10), JitCost(2), 1), 1) ) - verifyNeq(Coll[Coll[Int]](), Coll(Coll[Int]()), 1766, nestedNeq1, 1766)(cloneColl(_)) - verifyNeq(Coll(Coll[Int]()), Coll(Coll[Int](1)), 1767, nestedNeq2, 1767)(cloneColl(_)) - verifyNeq(Coll(Coll[Int](1)), Coll(Coll[Int](2)), 1769, nestedNeq3, 1769)(cloneColl(_)) - verifyNeq(Coll(Coll[Int](1)), Coll(Coll[Int](1, 2)), 1767, nestedNeq2, 1767)(cloneColl(_)) + verifyNeq(Coll[Coll[Int]](), Coll(Coll[Int]()), 1766, nestedNeq1, 1766, Seq.fill(4)(2018))(cloneColl(_)) + verifyNeq(Coll(Coll[Int]()), Coll(Coll[Int](1)), 1767, nestedNeq2, 1767, Seq.fill(4)(2019))(cloneColl(_)) + verifyNeq(Coll(Coll[Int](1)), Coll(Coll[Int](2)), 1769, nestedNeq3, 1769, Seq.fill(4)(2021))(cloneColl(_)) + verifyNeq(Coll(Coll[Int](1)), Coll(Coll[Int](1, 2)), 1767, nestedNeq2, 1767, Seq.fill(4)(2019))(cloneColl(_)) prepareSamples[Coll[(Int, BigInt)]] prepareSamples[Coll[Coll[(Int, BigInt)]]] @@ -2398,8 +2443,8 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => ast.SeqCostItem(NamedDesc("EQ_Coll"), PerItemCost(JitCost(10), JitCost(2), 1), 1), ast.SeqCostItem(NamedDesc("EQ_Coll"), PerItemCost(JitCost(10), JitCost(2), 1), 1) ) - verifyNeq(Coll(Coll((1, 10.toBigInt))), Coll(Coll((1, 11.toBigInt))), 1770, nestedNeq4, 1770)(cloneColl(_)) - verifyNeq(Coll(Coll(Coll((1, 10.toBigInt)))), Coll(Coll(Coll((1, 11.toBigInt)))), 1771, nestedNeq5, 1771)(cloneColl(_)) + verifyNeq(Coll(Coll((1, 10.toBigInt))), Coll(Coll((1, 11.toBigInt))), 1770, nestedNeq4, 1770, Seq.fill(4)(2048))(cloneColl(_)) + verifyNeq(Coll(Coll(Coll((1, 10.toBigInt)))), Coll(Coll(Coll((1, 11.toBigInt)))), 1771, nestedNeq5, 1771, Seq.fill(4)(2057))(cloneColl(_)) verifyNeq( (Coll( (Coll( @@ -2413,14 +2458,15 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => ), preH1), 1774, nestedNeq6, - 1774 + 1774, + Seq.fill(4)(2100) )(x => (cloneColl(x._1), x._2)) } property("GroupElement.getEncoded equivalence") { verifyCases( { - def success[T](v: T) = Expected(Success(v), 1790, methodCostDetails(SGroupElementMethods.GetEncodedMethod, 250), 1790) + def success[T](v: T) = Expected(Success(v), 1790, methodCostDetails(SGroupElementMethods.GetEncodedMethod, 250), 1790, Seq.fill(4)(2026)) Seq( (ge1, success(Helpers.decodeBytes(ge1str))), (ge2, success(Helpers.decodeBytes(ge2str))), @@ -2451,7 +2497,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => FixedCostItem(NamedDesc("EQ_GroupElement"), FixedCost(JitCost(172))) ) ) - def success[T](v: T) = Expected(Success(v), 1837, costDetails, 1837) + def success[T](v: T) = Expected(Success(v), 1837, costDetails, 1837, Seq.fill(4)(2081)) Seq( (ge1, success(true)), (ge2, success(true)), @@ -2481,7 +2527,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => property("GroupElement.negate equivalence") { verifyCases( { - def success[T](v: T) = Expected(Success(v), 1785, methodCostDetails(SGroupElementMethods.NegateMethod, 45), 1785) + def success[T](v: T) = Expected(Success(v), 1785, methodCostDetails(SGroupElementMethods.NegateMethod, 45), 1785, Seq.fill(4)(2021)) Seq( (ge1, success(Helpers.decodeGroupElement("02358d53f01276211f92d0aefbd278805121d4ff6eb534b777af1ee8abae5b2056"))), (ge2, success(Helpers.decodeGroupElement("03dba7b94b111f3894e2f9120b577da595ec7d58d488485adf73bf4e153af63575"))), @@ -2499,8 +2545,9 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => } property("GroupElement.exp equivalence") { - def cases(cost: Int, details: CostDetails) = { - def success[T](v: T) = Expected(Success(v), cost, details, cost) + def cases(cost: Int, details: CostDetails, expectedV3Costs: Seq[Int]) = { + def success[T](v: T) = Expected(Success(v), cost, details, cost, expectedV3Costs) + Seq( ((ge1, CBigInt(new BigInteger("-25c80b560dd7844e2efd10f80f7ee57d", 16))), success(Helpers.decodeGroupElement("023a850181b7b73f92a5bbfa0bfc78f5bbb6ff00645ddde501037017e1a2251e2e"))), @@ -2523,7 +2570,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => FixedCostItem(Exponentiate) ) ) - verifyCases(cases(1873, costDetails), + verifyCases(cases(1873, costDetails, Seq.fill(4)(2121)), existingFeature( scalaFunc, script, @@ -2550,7 +2597,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => FixedCostItem(SGroupElementMethods.ExponentiateMethod, FixedCost(JitCost(900))) ) ) - verifyCases(cases(1873, costDetails), + verifyCases(cases(1873, costDetails, Seq.fill(4)(2121)), existingFeature( scalaFunc, script, @@ -2597,7 +2644,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => ) ) ) - def success[T](v: T) = Expected(Success(v), 1787, costDetails, 1787) + def success[T](v: T) = Expected(Success(v), 1787, costDetails, 1787, Seq.fill(4)(2031)) Seq( ((ge1, Helpers.decodeGroupElement("03e132ca090614bd6c9f811e91f6daae61f16968a1e6c694ed65aacd1b1092320e")), success(Helpers.decodeGroupElement("02bc48937b4a66f249a32dfb4d2efd0743dc88d46d770b8c5d39fd03325ba211df"))), @@ -2660,7 +2707,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => } verifyCases( { - def success[T](v: T) = Expected(Success(v), 1767, methodCostDetails(SAvlTreeMethods.digestMethod, 15), 1767) + def success[T](v: T) = Expected(Success(v), 1767, methodCostDetails(SAvlTreeMethods.digestMethod, 15), 1767, Seq.fill(4)(2003)) Seq( (t1, success(Helpers.decodeBytes("000183807f66b301530120ff7fc6bd6601ff01ff7f7d2bedbbffff00187fe89094"))), (t2, success(Helpers.decodeBytes("ff000d937f80ffd731ed802d24358001ff8080ff71007f00ad37e0a7ae43fff95b"))), @@ -2673,7 +2720,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( { - def success[T](v: T) = Expected(Success(v), 1765, methodCostDetails(SAvlTreeMethods.enabledOperationsMethod, 15), 1765) + def success[T](v: T) = Expected(Success(v), 1765, methodCostDetails(SAvlTreeMethods.enabledOperationsMethod, 15), 1765, Seq.fill(4)(2001)) Seq( (t1, success(6.toByte)), (t2, success(0.toByte)), @@ -2686,7 +2733,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( { - def success[T](v: T) = Expected(Success(v), 1765, methodCostDetails(SAvlTreeMethods.keyLengthMethod, 15), 1765) + def success[T](v: T) = Expected(Success(v), 1765, methodCostDetails(SAvlTreeMethods.keyLengthMethod, 15), 1765, Seq.fill(4)(2001)) Seq( (t1, success(1)), (t2, success(32)), @@ -2699,11 +2746,11 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( { - def success[T](v: T, newCost: Int) = Expected(Success(v), newCost, methodCostDetails(SAvlTreeMethods.valueLengthOptMethod, 15), newCost) + def success[T](v: T, newCost: Int, expectedV3Costs: Seq[Int]) = Expected(Success(v), newCost, methodCostDetails(SAvlTreeMethods.valueLengthOptMethod, 15), newCost, expectedV3Costs) Seq( - (t1, success(Some(1), 1766)), - (t2, success(Some(64), 1766)), - (t3, success(None, 1765)) + (t1, success(Some(1), 1766, Seq.fill(4)(2002))), + (t2, success(Some(64), 1766, Seq.fill(4)(2002))), + (t3, success(None, 1765, Seq.fill(4)(2001))) ) }, existingFeature((t: AvlTree) => t.valueLengthOpt, @@ -2712,7 +2759,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( { - def success[T](v: T) = Expected(Success(v), 1765, methodCostDetails(SAvlTreeMethods.isInsertAllowedMethod, 15), 1765) + def success[T](v: T) = Expected(Success(v), 1765, methodCostDetails(SAvlTreeMethods.isInsertAllowedMethod, 15), 1765, Seq.fill(4)(2001)) Seq( (t1, success(false)), (t2, success(false)), @@ -2725,7 +2772,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( { - def success[T](v: T) = Expected(Success(v), 1765, methodCostDetails(SAvlTreeMethods.isUpdateAllowedMethod, 15), 1765) + def success[T](v: T) = Expected(Success(v), 1765, methodCostDetails(SAvlTreeMethods.isUpdateAllowedMethod, 15), 1765, Seq.fill(4)(2001)) Seq( (t1, success(true)), (t2, success(false)), @@ -2738,7 +2785,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( { - def success[T](v: T) = Expected(Success(v), 1765, methodCostDetails(SAvlTreeMethods.isRemoveAllowedMethod, 15), 1765) + def success[T](v: T) = Expected(Success(v), 1765, methodCostDetails(SAvlTreeMethods.isRemoveAllowedMethod, 15), 1765, Seq.fill(4)(2001)) Seq( (t1, success(true)), (t2, success(false)), @@ -2993,7 +3040,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => ) ) - getMany.checkExpected(input, Expected(Success(expRes), 1845, costDetails, 1845)) + getMany.checkExpected(input, Expected(Success(expRes), 1845, costDetails, 1845, Seq.fill(4)(2139))) } val key = Colls.fromArray(Array[Byte](-16,-128,99,86,1,-128,-36,-83,109,72,-124,-114,1,-32,15,127,-30,125,127,1,-102,-53,-53,-128,-107,0,64,8,1,127,22,1)) @@ -3071,8 +3118,9 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => // positive test { val input = (tree, (key, proof)) - contains.checkExpected(input, Expected(Success(okContains), 1790, costDetails(105 + additionalDetails), 1790)) - get.checkExpected(input, Expected(Success(valueOpt), 1790 + additionalCost, costDetails(105 + additionalDetails), 1790 + additionalCost)) + val expectedV3Costs: Seq[Int] = Seq.fill(4)(2082) + contains.checkExpected(input, Expected(Success(okContains), 1790, costDetails(105 + additionalDetails), 1790, expectedV3Costs)) + get.checkExpected(input, Expected(Success(valueOpt), 1790 + additionalCost, costDetails(105 + additionalDetails), 1790 + additionalCost, expectedV3Costs.map(additionalCost + _))) } val keys = Colls.fromItems(key) @@ -3080,14 +3128,15 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => { val input = (tree, (keys, proof)) - getMany.checkExpected(input, Expected(Success(expRes), 1791 + additionalCost, costDetails(105 + additionalDetails), 1791 + additionalCost)) + val expectedV3Costs: Seq[Int] = Seq.fill(4)(2085 + additionalCost) + getMany.checkExpected(input, Expected(Success(expRes), 1791 + additionalCost, costDetails(105 + additionalDetails), 1791 + additionalCost, expectedV3Costs)) } { val input = (tree, digest) val (res, _) = updateDigest.checkEquality(input).getOrThrow res.digest shouldBe digest - updateDigest.checkExpected(input, Expected(Success(res), 1771, updateDigestCostDetails, 1771)) + updateDigest.checkExpected(input, Expected(Success(res), 1771, updateDigestCostDetails, 1771, Seq.fill(4)(2029))) } val newOps = 1.toByte @@ -3096,7 +3145,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => val input = (tree, newOps) val (res,_) = updateOperations.checkEquality(input).getOrThrow res.enabledOperations shouldBe newOps - updateOperations.checkExpected(input, Expected(Success(res), 1771, updateOperationsCostDetails, 1771)) + updateOperations.checkExpected(input, Expected(Success(res), 1771, updateOperationsCostDetails, 1771, Seq.fill(4)(2025))) } // negative tests: invalid proof @@ -3106,7 +3155,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => val input = (tree, (key, invalidProof)) val (res, _) = contains.checkEquality(input).getOrThrow res shouldBe false - contains.checkExpected(input, Expected(Success(res), 1790, costDetails(105 + additionalDetails), 1790)) + contains.checkExpected(input, Expected(Success(res), 1790, costDetails(105 + additionalDetails), 1790, Seq.fill(4)(2082))) } { @@ -3259,7 +3308,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => val input = (preInsertTree, (kvs, insertProof)) val (res, _) = insert.checkEquality(input).getOrThrow res.isDefined shouldBe true - insert.checkExpected(input, Expected(Success(res), 1796, costDetails2, 1796)) + insert.checkExpected(input, Expected(Success(res), 1796, costDetails2, 1796, Seq.fill(4)(2102))) } { // negative: readonly tree @@ -3267,7 +3316,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => val input = (readonlyTree, (kvs, insertProof)) val (res, _) = insert.checkEquality(input).getOrThrow res.isDefined shouldBe false - insert.checkExpected(input, Expected(Success(res), 1772, costDetails1, 1772)) + insert.checkExpected(input, Expected(Success(res), 1772, costDetails1, 1772, Seq.fill(4)(2078))) } { // negative: invalid key @@ -3277,7 +3326,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => val input = (tree, (invalidKvs, insertProof)) val (res, _) = insert.checkEquality(input).getOrThrow res.isDefined shouldBe true // TODO v6.0: should it really be true? (looks like a bug) (see https://github.com/ScorexFoundation/sigmastate-interpreter/issues/908) - insert.checkExpected(input, Expected(Success(res), 1796, costDetails2, 1796)) + insert.checkExpected(input, Expected(Success(res), 1796, costDetails2, 1796, Seq.fill(4)(2102))) } { // negative: invalid proof @@ -3407,7 +3456,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => val endTree = preUpdateTree.updateDigest(endDigest) val input = (preUpdateTree, (kvs, updateProof)) val res = Some(endTree) - update.checkExpected(input, Expected(Success(res), 1805, costDetails2, 1805)) + update.checkExpected(input, Expected(Success(res), 1805, costDetails2, 1805, Seq.fill(4)(2111))) } { // positive: update to the same value (identity operation) @@ -3415,13 +3464,13 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => val keys = Colls.fromItems((key -> value)) val input = (tree, (keys, updateProof)) val res = Some(tree) - update.checkExpected(input, Expected(Success(res), 1805, costDetails2, 1805)) + update.checkExpected(input, Expected(Success(res), 1805, costDetails2, 1805, Seq.fill(4)(2111))) } { // negative: readonly tree val readonlyTree = createTree(preUpdateDigest) val input = (readonlyTree, (kvs, updateProof)) - update.checkExpected(input, Expected(Success(None), 1772, costDetails1, 1772)) + update.checkExpected(input, Expected(Success(None), 1772, costDetails1, 1772, Seq.fill(4)(2078))) } { // negative: invalid key @@ -3429,7 +3478,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => val invalidKey = key.map(x => (-x).toByte) // any other different from key val invalidKvs = Colls.fromItems((invalidKey -> newValue)) val input = (tree, (invalidKvs, updateProof)) - update.checkExpected(input, Expected(Success(None), 1801, costDetails3, 1801)) + update.checkExpected(input, Expected(Success(None), 1801, costDetails3, 1801, Seq.fill(4)(2107))) } { // negative: invalid value (different from the value in the proof) @@ -3438,15 +3487,15 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => val invalidKvs = Colls.fromItems((key -> invalidValue)) val input = (tree, (invalidKvs, updateProof)) val (res, _) = update.checkEquality(input).getOrThrow - res.isDefined shouldBe true // TODO v6.0: should it really be true? (looks like a bug) (see https://github.com/ScorexFoundation/sigmastate-interpreter/issues/908) - update.checkExpected(input, Expected(Success(res), 1805, costDetails2, 1805)) + res.isDefined shouldBe true // TODO v6.0: should it really be true? (looks like a bug) (see https://github.com/ScorexFoundation/sigmastate-interpreter/issues/908) + update.checkExpected(input, Expected(Success(res), 1805, costDetails2, 1805, Seq.fill(4)(2111))) } { // negative: invalid proof val tree = createTree(preUpdateDigest, updateAllowed = true) val invalidProof = updateProof.map(x => (-x).toByte) // any other different from proof val input = (tree, (kvs, invalidProof)) - update.checkExpected(input, Expected(Success(None), 1801, costDetails3, 1801)) + update.checkExpected(input, Expected(Success(None), 1801, costDetails3, 1801, Seq.fill(4)(2107))) } } @@ -3557,7 +3606,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => val endTree = preRemoveTree.updateDigest(endDigest) val input = (preRemoveTree, (Colls.fromArray(keysToRemove), removeProof)) val res = Some(endTree) - remove.checkExpected(input, Expected(Success(res), 1832, costDetails1, 1832)) + remove.checkExpected(input, Expected(Success(res), 1832, costDetails1, 1832, Seq.fill(4)(2126))) } { @@ -3574,13 +3623,13 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => val endTree = preRemoveTree.updateDigest(endDigest) val input = (preRemoveTree, (keys, removeProof)) val res = Some(endTree) - remove.checkExpected(input, Expected(Success(res), 1806, costDetails2, 1806)) + remove.checkExpected(input, Expected(Success(res), 1806, costDetails2, 1806, Seq.fill(4)(2100))) } { // negative: readonly tree val readonlyTree = createTree(preRemoveDigest) val input = (readonlyTree, (keys, removeProof)) - remove.checkExpected(input, Expected(Success(None), 1772, costDetails3, 1772)) + remove.checkExpected(input, Expected(Success(None), 1772, costDetails3, 1772, Seq.fill(4)(2066))) } { // negative: invalid key @@ -3588,14 +3637,14 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => val invalidKey = key.map(x => (-x).toByte) // any other different from `key` val invalidKeys = Colls.fromItems(invalidKey) val input = (tree, (invalidKeys, removeProof)) - remove.checkExpected(input, Expected(Success(None), 1802, costDetails4, 1802)) + remove.checkExpected(input, Expected(Success(None), 1802, costDetails4, 1802, Seq.fill(4)(2096))) } { // negative: invalid proof val tree = createTree(preRemoveDigest, removeAllowed = true) val invalidProof = removeProof.map(x => (-x).toByte) // any other different from `removeProof` val input = (tree, (keys, invalidProof)) - remove.checkExpected(input, Expected(Success(None), 1802, costDetails4, 1802)) + remove.checkExpected(input, Expected(Success(None), 1802, costDetails4, 1802, Seq.fill(4)(2096))) } } } @@ -3604,7 +3653,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => val costDetails = CostDetails(traceBase :+ FixedCostItem(CompanionDesc(LongToByteArray), FixedCost(JitCost(17)))) verifyCases( { - def success[T](v: T) = Expected(Success(v), 1767, costDetails, 1767) + def success[T](v: T) = Expected(Success(v), 1767, costDetails, 1767, Seq.fill(4)(1999)) Seq( (-9223372036854775808L, success(Helpers.decodeBytes("8000000000000000"))), (-1148502660425090565L, success(Helpers.decodeBytes("f00fb2ea55c579fb"))), @@ -3624,20 +3673,20 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => val costDetails = CostDetails(traceBase :+ FixedCostItem(CompanionDesc(ByteArrayToBigInt), FixedCost(JitCost(30)))) verifyCases( { - def success[T](v: T) = Expected(Success(v), 1767, costDetails, 1767) + def success[T](v: T) = Expected(Success(v), 1767, costDetails, 1767, Seq.fill(4)(1999)) Seq( (Helpers.decodeBytes(""), Expected(new NumberFormatException("Zero length BigInteger"))), (Helpers.decodeBytes("00"), - success(CBigInt(new BigInteger("0", 16)))), + success(CBigInt(new BigInteger("0", 16)))), (Helpers.decodeBytes("01"), - success(CBigInt(new BigInteger("1", 16)))), + success(CBigInt(new BigInteger("1", 16)))), (Helpers.decodeBytes("ff"), - success(CBigInt(new BigInteger("-1", 16)))), + success(CBigInt(new BigInteger("-1", 16)))), (Helpers.decodeBytes("80d6c201"), - Expected(Success(CBigInt(new BigInteger("-7f293dff", 16))), 1767, costDetails, 1767)), + Expected(Success(CBigInt(new BigInteger("-7f293dff", 16))), 1767, costDetails, 1767, Seq.fill(4)(1999))), (Helpers.decodeBytes("70d6c20170d6c201"), - Expected(Success(CBigInt(new BigInteger("70d6c20170d6c201", 16))), 1767, costDetails, 1767)), + Expected(Success(CBigInt(new BigInteger("70d6c20170d6c201", 16))), 1767, costDetails, 1767, Seq.fill(4)(1999))), (Helpers.decodeBytes( "80e0ff7f02807fff72807f0a00ff7fb7c57f75c11ba2802970fd250052807fc37f6480ffff007fff18eeba44" ), Expected(new ArithmeticException("BigInteger out of 256 bit range"))) @@ -3652,7 +3701,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => val costDetails = CostDetails(traceBase :+ FixedCostItem(CompanionDesc(ByteArrayToLong), FixedCost(JitCost(16)))) verifyCases( { - def success[T](v: T) = Expected(Success(v), 1765, costDetails, 1765) + def success[T](v: T) = Expected(Success(v), 1765, costDetails, 1765, Seq.fill(4)(1997)) Seq( (Helpers.decodeBytes(""), Expected(new IllegalArgumentException("array too small: 0 < 8"))), (Helpers.decodeBytes("81"), Expected(new IllegalArgumentException("array too small: 1 < 8"))), @@ -3674,7 +3723,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( { val costDetails = CostDetails(traceBase :+ FixedCostItem(CompanionDesc(ExtractId), FixedCost(JitCost(12)))) - def success[T](v: T) = Expected(Success(v), 1766, costDetails, 1766) + def success[T](v: T) = Expected(Success(v), 1766, costDetails, 1766, Seq.fill(4)(1998)) Seq( (b1, success(Helpers.decodeBytes("5ee78f30ae4e770e44900a46854e9fecb6b12e8112556ef1cd19aef633b4421e"))), (b2, success(Helpers.decodeBytes("3a0089be265460e29ca47d26e5b55a6f3e3ffaf5b4aed941410a2437913848ad"))) @@ -3687,7 +3736,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( { val costDetails = CostDetails(traceBase :+ FixedCostItem(CompanionDesc(ExtractAmount), FixedCost(JitCost(8)))) - def success[T](v: T) = Expected(Success(v), 1764, costDetails, 1764) + def success[T](v: T) = Expected(Success(v), 1764, costDetails, 1764, Seq.fill(4)(1996)) Seq( (b1, success(9223372036854775807L)), (b2, success(12345L)) @@ -3700,7 +3749,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( { val costDetails = CostDetails(traceBase :+ FixedCostItem(CompanionDesc(ExtractScriptBytes), FixedCost(JitCost(10)))) - def success[T](v: T) = Expected(Success(v), 1766, costDetails, 1766) + def success[T](v: T) = Expected(Success(v), 1766, costDetails, 1766, Seq.fill(4)(1998)) Seq( (b1, success(Helpers.decodeBytes( "100108cd0297c44a12f4eb99a85d298fa3ba829b5b42b9f63798c980ece801cc663cc5fc9e7300" @@ -3715,7 +3764,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( { val costDetails = CostDetails(traceBase :+ FixedCostItem(CompanionDesc(ExtractBytes), FixedCost(JitCost(12)))) - def success[T](v: T) = Expected(Success(v), 1766, costDetails, 1766) + def success[T](v: T) = Expected(Success(v), 1766, costDetails, 1766, Seq.fill(4)(1998)) Seq( (b1, success(Helpers.decodeBytes( "ffffffffffffffff7f100108cd0297c44a12f4eb99a85d298fa3ba829b5b42b9f63798c980ece801cc663cc5fc9e73009fac29026e789ab7b2fffff12280a6cd01557f6fb22b7f80ff7aff8e1f7f15973d7f000180ade204a3ff007f00057600808001ff8f8000019000ffdb806fff7cc0b6015eb37fa600f4030201000e067fc87f7f01ff218301ae8000018008637f0021fb9e00018055486f0b514121016a00ff718080bcb001" @@ -3732,7 +3781,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( { val costDetails = CostDetails(traceBase :+ FixedCostItem(CompanionDesc(ExtractBytesWithNoRef), FixedCost(JitCost(12)))) - def success[T](v: T) = Expected(Success(v), 1766, costDetails, 1766) + def success[T](v: T) = Expected(Success(v), 1766, costDetails, 1766, Seq.fill(4)(1998)) Seq( (b1, success(Helpers.decodeBytes( "ffffffffffffffff7f100108cd0297c44a12f4eb99a85d298fa3ba829b5b42b9f63798c980ece801cc663cc5fc9e73009fac29026e789ab7b2fffff12280a6cd01557f6fb22b7f80ff7aff8e1f7f15973d7f000180ade204a3ff007f00057600808001ff8f8000019000ffdb806fff7cc0b6015eb37fa600f4030201000e067fc87f7f01ff" @@ -3749,7 +3798,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( { val costDetails = CostDetails(traceBase :+ FixedCostItem(CompanionDesc(ExtractCreationInfo), FixedCost(JitCost(16)))) - def success[T](v: T) = Expected(Success(v), 1767, costDetails, 1767) + def success[T](v: T) = Expected(Success(v), 1767, costDetails, 1767, Seq.fill(4)(2001)) Seq( (b1, success(( 677407, @@ -3772,8 +3821,8 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => b1 -> Expected(Success(Coll[(Coll[Byte], Long)]( (Helpers.decodeBytes("6e789ab7b2fffff12280a6cd01557f6fb22b7f80ff7aff8e1f7f15973d7f0001"), 10000000L), (Helpers.decodeBytes("a3ff007f00057600808001ff8f8000019000ffdb806fff7cc0b6015eb37fa600"), 500L) - ).map(identity)), 1772, methodCostDetails(SBoxMethods.tokensMethod, 15), 1772), - b2 -> Expected(Success(Coll[(Coll[Byte], Long)]().map(identity)), 1766, methodCostDetails(SBoxMethods.tokensMethod, 15), 1766) + ).map(identity)), 1772, methodCostDetails(SBoxMethods.tokensMethod, 15), 1772, Seq.fill(4)(2012)), + b2 -> Expected(Success(Coll[(Coll[Byte], Long)]().map(identity)), 1766, methodCostDetails(SBoxMethods.tokensMethod, 15), 1766, Seq.fill(4)(2006)) ), existingFeature({ (x: Box) => x.tokens }, "{ (x: Box) => x.tokens }", @@ -3842,11 +3891,11 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( Seq( - (box1, Expected(Success(1024.toShort), 1774, expCostDetails1, 1774)), + (box1, Expected(Success(1024.toShort), 1774, expCostDetails1, 1774, Seq.fill(4)(2042))), (box2, Expected( new InvalidType("Cannot getReg[Short](5): invalid type of value TestValue(1048576) at id=5") )), - (box3, Expected(Success(0.toShort), 1772, expCostDetails2, 1772)) + (box3, Expected(Success(0.toShort), 1772, expCostDetails2, 1772, Seq.fill(4)(2040))) ), existingFeature( { (x: Box) => @@ -3971,10 +4020,10 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( Seq( - (box1, Expected(Success(1024), cost = 1785, expCostDetails3, 1785)), - (box2, Expected(Success(1024 * 1024), cost = 1786, expCostDetails4, 1786)), - (box3, Expected(Success(0), cost = 1779, expCostDetails5, 1779)), - (box4, Expected(Success(-1), cost = 1772, expCostDetails2, 1772)) + (box1, Expected(Success(1024), cost = 1785, expCostDetails3, 1785, Seq.fill(4)(2129))), + (box2, Expected(Success(1024 * 1024), cost = 1786, expCostDetails4, 1786, Seq.fill(4)(2130))), + (box3, Expected(Success(0), cost = 1779, expCostDetails5, 1779, Seq.fill(4)(2123))), + (box4, Expected(Success(-1), cost = 1772, expCostDetails2, 1772, Seq.fill(4)(2116))) ), existingFeature( { (x: Box) => @@ -4068,7 +4117,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => ) verifyCases( Seq( - (box1, Expected(Success(1.toByte), cost = 1770, expCostDetails, 1770)), + (box1, Expected(Success(1.toByte), cost = 1770, expCostDetails, 1770, Seq.fill(4)(2008))), (box2, Expected(new InvalidType("Cannot getReg[Byte](4): invalid type of value Value(Coll(1)) at id=4"))) ), existingFeature((x: Box) => x.R4[Byte].get, @@ -4080,7 +4129,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( Seq( - (box1, Expected(Success(1024.toShort), cost = 1770, expCostDetails, 1770)), + (box1, Expected(Success(1024.toShort), cost = 1770, expCostDetails, 1770, Seq.fill(4)(2008))), (box2, Expected(new NoSuchElementException("None.get"))) ), existingFeature((x: Box) => x.R5[Short].get, @@ -4092,7 +4141,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( Seq( - (box1, Expected(Success(1024 * 1024), cost = 1770, expCostDetails, 1770)) + (box1, Expected(Success(1024 * 1024), cost = 1770, expCostDetails, 1770, Seq.fill(4)(2008))) ), existingFeature((x: Box) => x.R6[Int].get, "{ (x: Box) => x.R6[Int].get }", @@ -4103,7 +4152,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( Seq( - (box1, Expected(Success(1024.toLong), cost = 1770, expCostDetails, 1770)) + (box1, Expected(Success(1024.toLong), cost = 1770, expCostDetails, 1770, Seq.fill(4)(2008))) ), existingFeature((x: Box) => x.R7[Long].get, "{ (x: Box) => x.R7[Long].get }", @@ -4114,7 +4163,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( Seq( - (box1, Expected(Success(CBigInt(BigInteger.valueOf(222L))), cost = 1770, expCostDetails, 1770)) + (box1, Expected(Success(CBigInt(BigInteger.valueOf(222L))), cost = 1770, expCostDetails, 1770, Seq.fill(4)(2008))) ), existingFeature((x: Box) => x.R8[BigInt].get, "{ (x: Box) => x.R8[BigInt].get }", @@ -4133,10 +4182,10 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => None ) )), - cost = 1770, - expCostDetails, - 1770) - )), + cost = 1770, + expCostDetails, + 1770, Seq.fill(4)(2008)) + )), existingFeature((x: Box) => x.R9[AvlTree].get, "{ (x: Box) => x.R9[AvlTree].get }", FuncValue( @@ -4208,35 +4257,35 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( - Seq((preH1, Expected(Success(0.toByte), cost = 1765, methodCostDetails(SPreHeaderMethods.versionMethod, 10), 1765))), + Seq((preH1, Expected(Success(0.toByte), cost = 1765, methodCostDetails(SPreHeaderMethods.versionMethod, 10), 1765, Seq.fill(4)(2001)))), existingPropTest("version", { (x: PreHeader) => x.version })) verifyCases( Seq((preH1, Expected(Success( Helpers.decodeBytes("7fff7fdd6f62018bae0001006d9ca888ff7f56ff8006573700a167f17f2c9f40")), - cost = 1766, methodCostDetails(SPreHeaderMethods.parentIdMethod, 10), 1766))), + cost = 1766, methodCostDetails(SPreHeaderMethods.parentIdMethod, 10), 1766, Seq.fill(4)(2002)))), existingPropTest("parentId", { (x: PreHeader) => x.parentId })) verifyCases( - Seq((preH1, Expected(Success(6306290372572472443L), cost = 1765, methodCostDetails(SPreHeaderMethods.timestampMethod, 10), 1765))), + Seq((preH1, Expected(Success(6306290372572472443L), cost = 1765, methodCostDetails(SPreHeaderMethods.timestampMethod, 10), 1765, Seq.fill(4)(2001)))), existingPropTest("timestamp", { (x: PreHeader) => x.timestamp })) verifyCases( - Seq((preH1, Expected(Success(-3683306095029417063L), cost = 1765, methodCostDetails(SPreHeaderMethods.nBitsMethod, 10), 1765))), + Seq((preH1, Expected(Success(-3683306095029417063L), cost = 1765, methodCostDetails(SPreHeaderMethods.nBitsMethod, 10), 1765, Seq.fill(4)(2001)))), existingPropTest("nBits", { (x: PreHeader) => x.nBits })) verifyCases( - Seq((preH1, Expected(Success(1), cost = 1765, methodCostDetails(SPreHeaderMethods.heightMethod, 10), 1765))), + Seq((preH1, Expected(Success(1), cost = 1765, methodCostDetails(SPreHeaderMethods.heightMethod, 10), 1765, Seq.fill(4)(2001)))), existingPropTest("height", { (x: PreHeader) => x.height })) verifyCases( Seq((preH1, Expected(Success( Helpers.decodeGroupElement("026930cb9972e01534918a6f6d6b8e35bc398f57140d13eb3623ea31fbd069939b")), - cost = 1782, methodCostDetails(SPreHeaderMethods.minerPkMethod, 10), 1782))), + cost = 1782, methodCostDetails(SPreHeaderMethods.minerPkMethod, 10), 1782, Seq.fill(4)(2018)))), existingPropTest("minerPk", { (x: PreHeader) => x.minerPk })) verifyCases( - Seq((preH1, Expected(Success(Helpers.decodeBytes("ff8087")), cost = 1766, methodCostDetails(SPreHeaderMethods.votesMethod,10), 1766))), + Seq((preH1, Expected(Success(Helpers.decodeBytes("ff8087")), cost = 1766, methodCostDetails(SPreHeaderMethods.votesMethod, 10), 1766, Seq.fill(4)(2002)))), existingPropTest("votes", { (x: PreHeader) => x.votes })) } @@ -4244,81 +4293,81 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( Seq((h1, Expected(Success( Helpers.decodeBytes("957f008001808080ffe4ffffc8f3802401df40006aa05e017fa8d3f6004c804a")), - cost = 1766, methodCostDetails(SHeaderMethods.idMethod, 10), 1766))), + cost = 1766, methodCostDetails(SHeaderMethods.idMethod, 10), 1766, Seq.fill(4)(2002)))), existingPropTest("id", { (x: Header) => x.id })) verifyCases( - Seq((h1, Expected(Success(0.toByte), cost = 1765, methodCostDetails(SHeaderMethods.versionMethod, 10), 1765))), + Seq((h1, Expected(Success(0.toByte), cost = 1765, methodCostDetails(SHeaderMethods.versionMethod, 10), 1765, Seq.fill(4)(2001)))), existingPropTest("version", { (x: Header) => x.version })) verifyCases( Seq((h1, Expected(Success( Helpers.decodeBytes("0180dd805b0000ff5400b997fd7f0b9b00de00fb03c47e37806a8186b94f07ff")), - cost = 1766, methodCostDetails(SHeaderMethods.parentIdMethod, 10), 1766))), + cost = 1766, methodCostDetails(SHeaderMethods.parentIdMethod, 10), 1766, Seq.fill(4)(2002)))), existingPropTest("parentId", { (x: Header) => x.parentId })) verifyCases( Seq((h1, Expected(Success( Helpers.decodeBytes("01f07f60d100ffb970c3007f60ff7f24d4070bb8fffa7fca7f34c10001ffe39d")), - cost = 1766, methodCostDetails(SHeaderMethods.ADProofsRootMethod, 10), 1766))), - existingPropTest("ADProofsRoot", { (x: Header) => x.ADProofsRoot})) + cost = 1766, methodCostDetails(SHeaderMethods.ADProofsRootMethod, 10), 1766, Seq.fill(4)(2002)))), + existingPropTest("ADProofsRoot", { (x: Header) => x.ADProofsRoot })) verifyCases( - Seq((h1, Expected(Success(CAvlTree(createAvlTreeData())), cost = 1765, methodCostDetails(SHeaderMethods.stateRootMethod, 10), 1765))), + Seq((h1, Expected(Success(CAvlTree(createAvlTreeData())), cost = 1765, methodCostDetails(SHeaderMethods.stateRootMethod, 10), 1765, Seq.fill(4)(2001)))), existingPropTest("stateRoot", { (x: Header) => x.stateRoot })) verifyCases( Seq((h1, Expected(Success( Helpers.decodeBytes("804101ff01000080a3ffbd006ac080098df132a7017f00649311ec0e00000100")), - cost = 1766, methodCostDetails(SHeaderMethods.transactionsRootMethod, 10), 1766))), + cost = 1766, methodCostDetails(SHeaderMethods.transactionsRootMethod, 10), 1766, Seq.fill(4)(2002)))), existingPropTest("transactionsRoot", { (x: Header) => x.transactionsRoot })) verifyCases( - Seq((h1, Expected(Success(1L), cost = 1765, methodCostDetails(SHeaderMethods.timestampMethod, 10), 1765))), + Seq((h1, Expected(Success(1L), cost = 1765, methodCostDetails(SHeaderMethods.timestampMethod, 10), 1765, Seq.fill(4)(2001)))), existingPropTest("timestamp", { (x: Header) => x.timestamp })) verifyCases( - Seq((h1, Expected(Success(-1L), cost = 1765, methodCostDetails(SHeaderMethods.nBitsMethod, 10), 1765))), + Seq((h1, Expected(Success(-1L), cost = 1765, methodCostDetails(SHeaderMethods.nBitsMethod, 10), 1765, Seq.fill(4)(2001)))), existingPropTest("nBits", { (x: Header) => x.nBits })) verifyCases( - Seq((h1, Expected(Success(1), cost = 1765, methodCostDetails(SHeaderMethods.heightMethod, 10), 1765))), + Seq((h1, Expected(Success(1), cost = 1765, methodCostDetails(SHeaderMethods.heightMethod, 10), 1765, Seq.fill(4)(2001)))), existingPropTest("height", { (x: Header) => x.height })) verifyCases( Seq((h1, Expected(Success( Helpers.decodeBytes("e57f80885601b8ff348e01808000bcfc767f2dd37f0d01015030ec018080bc62")), - cost = 1766, methodCostDetails(SHeaderMethods.extensionRootMethod, 10), 1766))), + cost = 1766, methodCostDetails(SHeaderMethods.extensionRootMethod, 10), 1766, Seq.fill(4)(2002)))), existingPropTest("extensionRoot", { (x: Header) => x.extensionRoot })) verifyCases( Seq((h1, Expected(Success( Helpers.decodeGroupElement("039bdbfa0b49cc6bef58297a85feff45f7bbeb500a9d2283004c74fcedd4bd2904")), - cost = 1782, methodCostDetails(SHeaderMethods.minerPkMethod, 10), 1782))), + cost = 1782, methodCostDetails(SHeaderMethods.minerPkMethod, 10), 1782, Seq.fill(4)(2018)))), existingPropTest("minerPk", { (x: Header) => x.minerPk })) verifyCases( Seq((h1, Expected(Success( Helpers.decodeGroupElement("0361299207fa392231e23666f6945ae3e867b978e021d8d702872bde454e9abe9c")), - cost = 1782, methodCostDetails(SHeaderMethods.powOnetimePkMethod, 10), 1782))), + cost = 1782, methodCostDetails(SHeaderMethods.powOnetimePkMethod, 10), 1782, Seq.fill(4)(2018)))), existingPropTest("powOnetimePk", { (x: Header) => x.powOnetimePk })) verifyCases( Seq((h1, Expected(Success( Helpers.decodeBytes("7f4f09012a807f01")), - cost = 1766, methodCostDetails(SHeaderMethods.powNonceMethod, 10), 1766))), + cost = 1766, methodCostDetails(SHeaderMethods.powNonceMethod, 10), 1766, Seq.fill(4)(2002)))), existingPropTest("powNonce", { (x: Header) => x.powNonce })) verifyCases( Seq((h1, Expected(Success( CBigInt(new BigInteger("-e24990c47e15ed4d0178c44f1790cc72155d516c43c3e8684e75db3800a288", 16))), - cost = 1765, methodCostDetails(SHeaderMethods.powDistanceMethod, 10), 1765))), + cost = 1765, methodCostDetails(SHeaderMethods.powDistanceMethod, 10), 1765, Seq.fill(4)(2001)))), existingPropTest("powDistance", { (x: Header) => x.powDistance })) verifyCases( Seq((h1, Expected(Success( Helpers.decodeBytes("7f0180")), - cost = 1766, methodCostDetails(SHeaderMethods.votesMethod, 10), 1766))), + cost = 1766, methodCostDetails(SHeaderMethods.votesMethod, 10), 1766, Seq.fill(4)(2002)))), existingPropTest("votes", { (x: Header) => x.votes })) } @@ -4532,7 +4581,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => val costDetails = TracedCost(testTraceBase) verifyCases( Seq( - (ctx, Expected(Success(dataBox), cost = 1769, costDetails, 1769)), + (ctx, Expected(Success(dataBox), cost = 1769, costDetails, 1769, Seq.fill(4)(2017))), (ctx.copy(_dataInputs = Coll()), Expected(new ArrayIndexOutOfBoundsException("0"))) ), existingFeature({ (x: Context) => x.dataInputs(0) }, @@ -4557,7 +4606,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => Seq( (ctx, Expected(Success( Helpers.decodeBytes("7da4b55971f19a78d007638464580f91a020ab468c0dbe608deb1f619e245bc3")), - cost = 1772, idCostDetails, 1772)) + cost = 1772, idCostDetails, 1772, Seq.fill(4)(2022))) ), existingFeature({ (x: Context) => x.dataInputs(0).id }, "{ (x: Context) => x.dataInputs(0).id }", @@ -4618,7 +4667,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => ) ) verifyCases( - Seq(ctx -> Expected(Success(ctx.HEIGHT), cost = 1766, heightCostDetails, 1766)), + Seq(ctx -> Expected(Success(ctx.HEIGHT), cost = 1766, heightCostDetails, 1766, Seq.fill(4)(1994))), existingFeature( { (x: Context) => x.HEIGHT }, "{ (x: Context) => x.HEIGHT }", @@ -4655,7 +4704,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => )) verifyCases( - Seq((ctx, Expected(Success(Coll[Long](80946L)), cost = 1770, inputsCostDetails1, 1770))), + Seq((ctx, Expected(Success(Coll[Long](80946L)), cost = 1770, inputsCostDetails1, 1770, Seq.fill(4)(2014)))), existingFeature( { (x: Context) => x.INPUTS.map { (b: Box) => b.value } }, "{ (x: Context) => x.INPUTS.map { (b: Box) => b.value } }", @@ -4715,7 +4764,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => ) ) verifyCases( - Seq((ctx, Expected(Success(Coll((80946L, 80946L))), cost = 1774, inputsCostDetails2, 1774))), + Seq((ctx, Expected(Success(Coll((80946L, 80946L))), cost = 1774, inputsCostDetails2, 1774, Seq.fill(4)(2042)))), existingFeature( { (x: Context) => x.INPUTS.map { (b: Box) => (b.value, b.value) } }, """{ (x: Context) => @@ -4807,11 +4856,20 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => expectedDetails = CostDetails.ZeroCost, newCost = 1766, newVersionedResults = { + val expectedV3Costs = Seq.fill(4)(2002) + // V3 activation will have different costs due to deserialization cost + val costs = if (activatedVersionInTests >= V6SoftForkVersion) { + expectedV3Costs + } else { + Seq.fill(4)(1766) + } val res = (ExpectedResult(Success(0), Some(1766)) -> Some(selfCostDetails)) - Seq(0, 1, 2, 3).map(version => version -> res) + Seq(0, 1, 2, 3).map(version => version -> (ExpectedResult(Success(0), Some(costs(version))) -> Some(selfCostDetails))) })) ), - changedFeature({ (x: Context) => x.selfBoxIndex }, + changedFeature( + changedInVersion = VersionContext.JitActivationVersion, + { (x: Context) => x.selfBoxIndex }, { (x: Context) => x.selfBoxIndex }, // see versioning in selfBoxIndex implementation "{ (x: Context) => x.selfBoxIndex }", FuncValue( @@ -4837,7 +4895,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => } verifyCases( - Seq(ctx -> Expected(Success(ctx.LastBlockUtxoRootHash), cost = 1766, methodCostDetails(SContextMethods.lastBlockUtxoRootHashMethod, 15), 1766)), + Seq(ctx -> Expected(Success(ctx.LastBlockUtxoRootHash), cost = 1766, methodCostDetails(SContextMethods.lastBlockUtxoRootHashMethod, 15), 1766, Seq.fill(4)(2002))), existingPropTest("LastBlockUtxoRootHash", { (x: Context) => x.LastBlockUtxoRootHash }), preGeneratedSamples = Some(samples)) @@ -4850,7 +4908,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => ) ) verifyCases( - Seq(ctx -> Expected(Success(ctx.LastBlockUtxoRootHash.isUpdateAllowed), cost = 1767, isUpdateAllowedCostDetails, 1767)), + Seq(ctx -> Expected(Success(ctx.LastBlockUtxoRootHash.isUpdateAllowed), cost = 1767, isUpdateAllowedCostDetails, 1767, Seq.fill(4)(2009))), existingFeature( { (x: Context) => x.LastBlockUtxoRootHash.isUpdateAllowed }, "{ (x: Context) => x.LastBlockUtxoRootHash.isUpdateAllowed }", @@ -4871,7 +4929,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => preGeneratedSamples = Some(samples)) verifyCases( - Seq(ctx -> Expected(Success(ctx.minerPubKey), cost = 1767, methodCostDetails(SContextMethods.minerPubKeyMethod, 20), 1767)), + Seq(ctx -> Expected(Success(ctx.minerPubKey), cost = 1767, methodCostDetails(SContextMethods.minerPubKeyMethod, 20), 1767, Seq.fill(4)(2003))), existingPropTest("minerPubKey", { (x: Context) => x.minerPubKey }), preGeneratedSamples = Some(samples)) @@ -4911,7 +4969,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => FixedCostItem(GetVar), FixedCostItem(OptionGet))) verifyCases( - Seq((ctx, Expected(Success(true), cost = 1765, getVarCostDetails, 1765))), + Seq((ctx, Expected(Success(true), cost = 1765, getVarCostDetails, 1765, Seq.fill(4)(1999)))), existingFeature((x: Context) => x.getVar[Boolean](11).get, "{ (x: Context) => getVar[Boolean](11).get }", FuncValue(Vector((1, SContext)), OptionGet(GetVar(11.toByte, SOption(SBoolean))))), @@ -4945,7 +5003,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => ) verifyCases( Seq( - ctx -> Expected(Success(-135729055492651903L), 1779, registerIsDefinedCostDetails, 1779) + ctx -> Expected(Success(-135729055492651903L), 1779, registerIsDefinedCostDetails, 1779, Seq.fill(4)(2065)) ), existingFeature( { (x: Context) => @@ -5007,11 +5065,19 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => Seq( ctx -> Expected(Failure(expectedError), 0, CostDetails.ZeroCost, 1793, newVersionedResults = { - Seq.tabulate(4)(v => v -> (ExpectedResult(Success(true), Some(1793)) -> None)) + val expectedV3Costs = Seq.fill(4)(2121) + // V3 activation will have different costs due to deserialization cost + val costs = if (activatedVersionInTests >= V6SoftForkVersion) { + expectedV3Costs + } else { + Seq.fill(4)(1793) + } + Seq.tabulate(4)(v => v -> (ExpectedResult(Success(true), Some(costs(v))) -> None)) } ) ), changedFeature( + changedInVersion = VersionContext.JitActivationVersion, scalaFunc = { (x: Context) => // this error is expected in v3.x, v4.x throw expectedError @@ -5173,12 +5239,12 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => ) verifyCases( Seq( - ctx -> Expected(Success(5008366408131208436L), 1791, registerTagCostDetails1, 1791), + ctx -> Expected(Success(5008366408131208436L), 1791, registerTagCostDetails1, 1791, Seq.fill(4)(2153)), ctxWithRegsInOutput(ctx, Map( ErgoBox.R5 -> LongConstant(0L), - ErgoBox.R4 -> ShortConstant(10))) -> Expected(Success(10L), 1790, registerTagCostDetails2, 1790), + ErgoBox.R4 -> ShortConstant(10))) -> Expected(Success(10L), 1790, registerTagCostDetails2, 1790, Seq.fill(4)(2152)), ctxWithRegsInOutput(ctx, Map( - ErgoBox.R4 -> ShortConstant(10))) -> Expected(Success(-1L), 1777, registerTagCostDetails3, 1777) + ErgoBox.R4 -> ShortConstant(10))) -> Expected(Success(-1L), 1777, registerTagCostDetails3, 1777, Seq.fill(4)(2139)) ), existingFeature( { (x: Context) => @@ -5381,22 +5447,22 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( Seq( // case 1L - ctx -> Expected(Success(5008366408131289382L), 1794, tagRegisterCostDetails1, 1794), + ctx -> Expected(Success(5008366408131289382L), 1794, tagRegisterCostDetails1, 1794, Seq.fill(4)(2168)), // case 0L ctxWithRegsInOutput(ctx, Map( ErgoBox.R5 -> LongConstant(0L), - ErgoBox.R4 -> ShortConstant(10))) -> Expected(Success(80956L), 1793, tagRegisterCostDetails2, 1793), + ErgoBox.R4 -> ShortConstant(10))) -> Expected(Success(80956L), 1793, tagRegisterCostDetails2, 1793, Seq.fill(4)(2167)), // case returning 0L ctxWithRegsInOutput(ctx, Map( ErgoBox.R5 -> LongConstant(2L), // note R4 is required to avoid // "RuntimeException: Set of non-mandatory indexes is not densely packed" - ErgoBox.R4 -> ShortConstant(10))) -> Expected(Success(0L), 1784, tagRegisterCostDetails3, 1784), + ErgoBox.R4 -> ShortConstant(10))) -> Expected(Success(0L), 1784, tagRegisterCostDetails3, 1784, Seq.fill(4)(2158)), // case returning -1L ctxWithRegsInOutput(ctx, Map( - ErgoBox.R4 -> ShortConstant(10))) -> Expected(Success(-1L), 1777, tagRegisterCostDetails4, 1777) + ErgoBox.R4 -> ShortConstant(10))) -> Expected(Success(-1L), 1777, tagRegisterCostDetails4, 1777, Seq.fill(4)(2151)) ), existingFeature( { (x: Context) => @@ -5614,15 +5680,15 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => Seq( ctxWithRegsInDataInput(ctx, Map( ErgoBox.R5 -> LongConstant(1L), - ErgoBox.R4 -> LongConstant(10))) -> Expected(Success(10L), 1792, tagRegisterCostDetails1, 1792), + ErgoBox.R4 -> LongConstant(10))) -> Expected(Success(10L), 1792, tagRegisterCostDetails1, 1792, Seq.fill(4)(2162)), ctxWithRegsInDataInput(ctx, Map( ErgoBox.R5 -> LongConstant(0L), - ErgoBox.R4 -> ShortConstant(10))) -> Expected(Success(10L), 1791, tagRegisterCostDetails2, 1791), + ErgoBox.R4 -> ShortConstant(10))) -> Expected(Success(10L), 1791, tagRegisterCostDetails2, 1791, Seq.fill(4)(2161)), ctxWithRegsInDataInput(ctx, Map( ErgoBox.R5 -> LongConstant(2L), - ErgoBox.R4 -> ShortConstant(10))) -> Expected(Success(0L), 1786, tagRegisterCostDetails3, 1786), + ErgoBox.R4 -> ShortConstant(10))) -> Expected(Success(0L), 1786, tagRegisterCostDetails3, 1786, Seq.fill(4)(2156)), ctxWithRegsInDataInput(ctx, Map( - ErgoBox.R4 -> ShortConstant(10))) -> Expected(Success(-1L), 1779, tagRegisterCostDetails4, 1779) + ErgoBox.R4 -> ShortConstant(10))) -> Expected(Success(-1L), 1779, tagRegisterCostDetails4, 1779, Seq.fill(4)(2149)) ), existingFeature( { (x: Context) => @@ -5847,15 +5913,15 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => Seq( ctxWithRegsInDataInput(ctx, Map( ErgoBox.R5 -> LongConstant(1L), - ErgoBox.R4 -> LongConstant(10))) -> Expected(Success(80956L), 1796, costDetails1, 1796), + ErgoBox.R4 -> LongConstant(10))) -> Expected(Success(80956L), 1796, costDetails1, 1796, Seq.fill(4)(2178)), ctxWithRegsInDataInput(ctx, Map( ErgoBox.R5 -> LongConstant(0L), - ErgoBox.R4 -> ShortConstant(10))) -> Expected(Success(80956L), 1794, costDetails2, 1794), + ErgoBox.R4 -> ShortConstant(10))) -> Expected(Success(80956L), 1794, costDetails2, 1794, Seq.fill(4)(2176)), ctxWithRegsInDataInput(ctx, Map( ErgoBox.R5 -> LongConstant(2L), - ErgoBox.R4 -> ShortConstant(10))) -> Expected(Success(0L), 1786, costDetails3, 1786), + ErgoBox.R4 -> ShortConstant(10))) -> Expected(Success(0L), 1786, costDetails3, 1786, Seq.fill(4)(2168)), ctxWithRegsInDataInput(ctx, Map( - ErgoBox.R4 -> ShortConstant(10))) -> Expected(Success(-1L), 1779, costDetails4, 1779) + ErgoBox.R4 -> ShortConstant(10))) -> Expected(Success(-1L), 1779, costDetails4, 1779, Seq.fill(4)(2161)) ), existingFeature( { (x: Context) => @@ -5960,7 +6026,15 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => cost = c, expectedDetails = CostDetails.ZeroCost, newCost = 1766, - newVersionedResults = Seq(0, 1, 2, 3).map(i => i -> (ExpectedResult(Success(newV), Some(1766)) -> Some(cd))) + newVersionedResults = { + val costs = if (activatedVersionInTests >= V6SoftForkVersion) { + Seq.fill(4)(1998) + } + else { + Seq.fill(4)(1766) + } + Seq.tabulate(4)(i => i -> (ExpectedResult(Success(newV), Some(costs(i))) -> Some(cd))) + } ) Seq( (Coll[Boolean](), successNew(false, 1766, newV = false, costDetails(0))), @@ -5985,6 +6059,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => ) }, changedFeature( + changedInVersion = VersionContext.JitActivationVersion, (x: Coll[Boolean]) => SigmaDsl.xorOf(x), (x: Coll[Boolean]) => SigmaDsl.xorOf(x), "{ (x: Coll[Boolean]) => xorOf(x) }", @@ -5995,8 +6070,8 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => val costDetails = TracedCost(traceBase :+ FixedCostItem(LogicalNot)) verifyCases( Seq( - (true, Expected(Success(false), 1765, costDetails, 1765)), - (false, Expected(Success(true), 1765, costDetails, 1765))), + (true, Expected(Success(false), 1765, costDetails, 1765, Seq.fill(4)(1997))), + (false, Expected(Success(true), 1765, costDetails, 1765, Seq.fill(4)(1997)))), existingFeature((x: Boolean) => !x, "{ (x: Boolean) => !x }", FuncValue(Vector((1, SBoolean)), LogicalNot(ValUse(1, SBoolean))))) @@ -6006,7 +6081,8 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => val costDetails = TracedCost(traceBase :+ FixedCostItem(Negation)) verifyCases( { - def success[T](v: T) = Expected(Success(v), 1766, costDetails, 1766) + def success[T](v: T) = Expected(Success(v), 1766, costDetails, 1766, Seq.fill(4)(1998)) + Seq( (Byte.MinValue, success(Byte.MinValue)), // !!! ((Byte.MinValue + 1).toByte, success(Byte.MaxValue)), @@ -6025,7 +6101,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( { - def success[T](v: T) = Expected(Success(v), 1766, costDetails, 1766) + def success[T](v: T) = Expected(Success(v), 1766, costDetails, 1766, Seq.fill(4)(1998)) Seq( (Short.MinValue, success(Short.MinValue)), // special case! ((Short.MinValue + 1).toShort, success(Short.MaxValue)), @@ -6043,7 +6119,8 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( { - def success[T](v: T) = Expected(Success(v), 1766, costDetails, 1766) + def success[T](v: T) = Expected(Success(v), 1766, costDetails, 1766, Seq.fill(4)(1998)) + Seq( (Int.MinValue, success(Int.MinValue)), // special case! (Int.MinValue + 1, success(Int.MaxValue)), @@ -6060,7 +6137,8 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( { - def success[T](v: T) = Expected(Success(v), 1766, costDetails, 1766) + def success[T](v: T) = Expected(Success(v), 1766, costDetails, 1766, Seq.fill(4)(1998)) + Seq( (Long.MinValue, success(Long.MinValue)), // special case! (Long.MinValue + 1, success(Long.MaxValue)), @@ -6077,7 +6155,8 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( { - def success[T](v: T) = Expected(Success(v), 1767, costDetails, 1767) + def success[T](v: T) = Expected(Success(v), 1767, costDetails, 1767, Seq.fill(4)(1999)) + Seq( (CBigInt(new BigInteger("-1655a05845a6ad363ac88ea21e88b97e436a1f02c548537e12e2d9667bf0680", 16)), success(CBigInt(new BigInteger("1655a05845a6ad363ac88ea21e88b97e436a1f02c548537e12e2d9667bf0680", 16)))), (CBigInt(new BigInteger("-1b24ba8badba8abf347cce054d9b9f14f229321507245b8", 16)), success(CBigInt(new BigInteger("1b24ba8badba8abf347cce054d9b9f14f229321507245b8", 16)))), @@ -6115,7 +6194,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => ) verifyCases( { - def success[T](v: T) = Expected(Success(v), 1782, costDetails, 1782) + def success[T](v: T) = Expected(Success(v), 1782, costDetails, 1782, Seq.fill(4)(2016)) Seq( (-1, success(Helpers.decodeGroupElement("0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798"))), (1, success(Helpers.decodeGroupElement("0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798")))) @@ -6134,7 +6213,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( { - def success[T](v: T) = Expected(Success(v), 1782, costDetails, 1782) + def success[T](v: T) = Expected(Success(v), 1782, costDetails, 1782, Seq.fill(4)(2016)) Seq( (-1, success(Helpers.decodeGroupElement("0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798"))), (1, success(Helpers.decodeGroupElement("0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798")))) @@ -6159,37 +6238,38 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => ) ) verifyCases( - { - def success[T](v: T) = Expected(Success(v), 1872, expCostDetails, 1872) - Seq( - (CBigInt(new BigInteger("-e5c1a54694c85d644fa30a6fc5f3aa209ed304d57f72683a0ebf21038b6a9d", 16)), success(Helpers.decodeGroupElement("023395bcba3d7cf21d73c50f8af79d09a8c404c15ce9d04f067d672823bae91a54"))), - (CBigInt(new BigInteger("-bc2d08f935259e0eebf272c66c6e1dbd484c6706390215", 16)), success(Helpers.decodeGroupElement("02ddcf4c48105faf3c16f7399b5dbedd82ab0bb50ae292d8f88f49a3f86e78974e"))), - (CBigInt(new BigInteger("-35cbe9a7a652e5fe85f735ee9909fdd8", 16)), success(Helpers.decodeGroupElement("03b110ec9c7a8c20ed873818e976a0e96e5a17be979d3422d59b362de2a3ae043e"))), - (CBigInt(new BigInteger("-3f05ffca6bd4b15c", 16)), success(Helpers.decodeGroupElement("02acf2657d0714cef8d65ae15c362faa09c0934c0bce872a23398e564c090b85c8"))), - (CBigInt(new BigInteger("-80000001", 16)), success(Helpers.decodeGroupElement("0391b418fd1778356ce947a5cbb46539fd29842aea168486fae91fc5317177a575"))), - (CBigInt(new BigInteger("-80000000", 16)), success(Helpers.decodeGroupElement("025318f9b1a2697010c5ac235e9af475a8c7e5419f33d47b18d33feeb329eb99a4"))), - (CBigInt(new BigInteger("-1", 16)), success(Helpers.decodeGroupElement("0379be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798"))), - (CBigInt(new BigInteger("0", 16)), success(Helpers.decodeGroupElement("000000000000000000000000000000000000000000000000000000000000000000"))), - (CBigInt(new BigInteger("1", 16)), success(Helpers.decodeGroupElement("0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798"))), - (CBigInt(new BigInteger("80000000", 16)), success(Helpers.decodeGroupElement("035318f9b1a2697010c5ac235e9af475a8c7e5419f33d47b18d33feeb329eb99a4"))), - (CBigInt(new BigInteger("1251b7fcd8a01e95", 16)), success(Helpers.decodeGroupElement("030fde7238b8dddfafab8f5481dc17b880505d6bacbe3cdf2ce975afdcadf66354"))), - (CBigInt(new BigInteger("12f6bd76d8fe1d035bdb14bf2f696e52", 16)), success(Helpers.decodeGroupElement("028f2ccf13669461cb3cfbea281e2db08fbb67b38493a1628855203d3f69b82763"))), - (CBigInt(new BigInteger("102bb404f5e36bdba004fdefa34df8cfa02e7912f3caf79", 16)), success(Helpers.decodeGroupElement("03ce82f431d115d45ad555084f8b2861ce5c4561d154e931e9f778594896e46a25")))) - }, - existingFeature({ (n: BigInt) => SigmaDsl.groupGenerator.exp(n) }, - "{ (n: BigInt) => groupGenerator.exp(n) }", - FuncValue( - Vector((1, SBigInt)), - Exponentiate( - MethodCall.typed[Value[SGroupElement.type]]( - Global, - SGlobalMethods.getMethodByName("groupGenerator"), - Vector(), - Map() - ), - ValUse(1, SBigInt) - ) - ))) + { + def success[T](v: T) = Expected(Success(v), 1872, expCostDetails, 1872, Seq.fill(4)(2112)) + + Seq( + (CBigInt(new BigInteger("-e5c1a54694c85d644fa30a6fc5f3aa209ed304d57f72683a0ebf21038b6a9d", 16)), success(Helpers.decodeGroupElement("023395bcba3d7cf21d73c50f8af79d09a8c404c15ce9d04f067d672823bae91a54"))), + (CBigInt(new BigInteger("-bc2d08f935259e0eebf272c66c6e1dbd484c6706390215", 16)), success(Helpers.decodeGroupElement("02ddcf4c48105faf3c16f7399b5dbedd82ab0bb50ae292d8f88f49a3f86e78974e"))), + (CBigInt(new BigInteger("-35cbe9a7a652e5fe85f735ee9909fdd8", 16)), success(Helpers.decodeGroupElement("03b110ec9c7a8c20ed873818e976a0e96e5a17be979d3422d59b362de2a3ae043e"))), + (CBigInt(new BigInteger("-3f05ffca6bd4b15c", 16)), success(Helpers.decodeGroupElement("02acf2657d0714cef8d65ae15c362faa09c0934c0bce872a23398e564c090b85c8"))), + (CBigInt(new BigInteger("-80000001", 16)), success(Helpers.decodeGroupElement("0391b418fd1778356ce947a5cbb46539fd29842aea168486fae91fc5317177a575"))), + (CBigInt(new BigInteger("-80000000", 16)), success(Helpers.decodeGroupElement("025318f9b1a2697010c5ac235e9af475a8c7e5419f33d47b18d33feeb329eb99a4"))), + (CBigInt(new BigInteger("-1", 16)), success(Helpers.decodeGroupElement("0379be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798"))), + (CBigInt(new BigInteger("0", 16)), success(Helpers.decodeGroupElement("000000000000000000000000000000000000000000000000000000000000000000"))), + (CBigInt(new BigInteger("1", 16)), success(Helpers.decodeGroupElement("0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798"))), + (CBigInt(new BigInteger("80000000", 16)), success(Helpers.decodeGroupElement("035318f9b1a2697010c5ac235e9af475a8c7e5419f33d47b18d33feeb329eb99a4"))), + (CBigInt(new BigInteger("1251b7fcd8a01e95", 16)), success(Helpers.decodeGroupElement("030fde7238b8dddfafab8f5481dc17b880505d6bacbe3cdf2ce975afdcadf66354"))), + (CBigInt(new BigInteger("12f6bd76d8fe1d035bdb14bf2f696e52", 16)), success(Helpers.decodeGroupElement("028f2ccf13669461cb3cfbea281e2db08fbb67b38493a1628855203d3f69b82763"))), + (CBigInt(new BigInteger("102bb404f5e36bdba004fdefa34df8cfa02e7912f3caf79", 16)), success(Helpers.decodeGroupElement("03ce82f431d115d45ad555084f8b2861ce5c4561d154e931e9f778594896e46a25")))) + }, + existingFeature({ (n: BigInt) => SigmaDsl.groupGenerator.exp(n) }, + "{ (n: BigInt) => groupGenerator.exp(n) }", + FuncValue( + Vector((1, SBigInt)), + Exponentiate( + MethodCall.typed[Value[SGroupElement.type]]( + Global, + SGlobalMethods.getMethodByName("groupGenerator"), + Vector(), + Map() + ), + ValUse(1, SBigInt) + ) + ))) } } @@ -6225,7 +6305,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( { - def success[T](v: T, cd: CostDetails) = Expected(Success(v), 1769, cd, 1769) + def success[T](v: T, cd: CostDetails) = Expected(Success(v), 1769, cd, 1769, Seq.fill(4)(2021)) Seq( ((Helpers.decodeBytes(""), Helpers.decodeBytes("")), success(Helpers.decodeBytes(""), costDetails(0))), ((Helpers.decodeBytes("01"), Helpers.decodeBytes("01")), success(Helpers.decodeBytes("00"), costDetails(1))), @@ -6236,9 +6316,16 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => cost = 0, expectedDetails = CostDetails.ZeroCost, newCost = 1769, - newVersionedResults = { - val res = (ExpectedResult(Success(Helpers.decodeBytes("00")), Some(1769)), Some(costDetails(1))) - Seq(0, 1, 2, 3).map(version => version -> res) + newVersionedResults = { + val costs = if (activatedVersionInTests >= V6SoftForkVersion) { + Seq.fill(4)(2021) + } else { + Seq.fill(4)(1769) + } + Seq.tabulate(4) { version => + val res = (ExpectedResult(Success(Helpers.decodeBytes("00")), Some(costs(version))), Some(costDetails(1))) + version -> res + } } )), ((Helpers.decodeBytes("800136fe89afff802acea67128a0ff007fffe3498c8001806080012b"), @@ -6247,6 +6334,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => ) }, changedFeature( + changedInVersion = VersionContext.JitActivationVersion, (x: (Coll[Byte], Coll[Byte])) => SigmaDsl.xor(x._1, x._2), (x: (Coll[Byte], Coll[Byte])) => SigmaDsl.xor(x._1, x._2), "{ (x: (Coll[Byte], Coll[Byte])) => xor(x._1, x._2) }", @@ -6380,11 +6468,11 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => ) verifyCases( { - def success[T](v: T, c: Int, costDetails: CostDetails, newCost: Int) = Expected(Success(v), c, costDetails, newCost) + def success[T](v: T, c: Int, costDetails: CostDetails, newCost: Int, expectedV3Costs: Seq[Int]) = Expected(Success(v), c, costDetails, newCost, expectedV3Costs) Seq( - (Coll[Box](), success(Coll[Box](), 1767, costDetails, 1767)), - (Coll[Box](b1), success(Coll[Box](), 1772, costDetails2, 1772)), - (Coll[Box](b1, b2), success(Coll[Box](b2), 1776, costDetails3, 1776)) + (Coll[Box](), success(Coll[Box](), 1767, costDetails, 1767, Seq.fill(4)(2031))), + (Coll[Box](b1), success(Coll[Box](), 1772, costDetails2, 1772, Seq.fill(4)(2036))), + (Coll[Box](b1, b2), success(Coll[Box](b2), 1776, costDetails3, 1776, Seq.fill(4)(2040))) ) }, existingFeature({ (x: Coll[Box]) => x.filter({ (b: Box) => b.value > 1 }) }, @@ -6437,13 +6525,13 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( { Seq( - (Coll[Box](), Expected(Success(Coll[Byte]()), 1773, costDetails1, 1773)), + (Coll[Box](), Expected(Success(Coll[Byte]()), 1773, costDetails1, 1773, Seq.fill(4)(2029))), (Coll[Box](b1), Expected(Success(Helpers.decodeBytes( "0008ce02c1a9311ecf1e76c787ba4b1c0e10157b4f6d1e4db3ef0d84f411c99f2d4d2c5b027d1bd9a437e73726ceddecc162e5c85f79aee4798505bc826b8ad1813148e4190257cff6d06fe15d1004596eeb97a7f67755188501e36adc49bd807fe65e9d8281033c6021cff6ba5fdfc4f1742486030d2ebbffd9c9c09e488792f3102b2dcdabd5" - )), 1791, costDetails2, 1791)), + )), 1791, costDetails2, 1791, Seq.fill(4)(2047))), (Coll[Box](b1, b2), Expected(Success(Helpers.decodeBytes( "0008ce02c1a9311ecf1e76c787ba4b1c0e10157b4f6d1e4db3ef0d84f411c99f2d4d2c5b027d1bd9a437e73726ceddecc162e5c85f79aee4798505bc826b8ad1813148e4190257cff6d06fe15d1004596eeb97a7f67755188501e36adc49bd807fe65e9d8281033c6021cff6ba5fdfc4f1742486030d2ebbffd9c9c09e488792f3102b2dcdabd500d197830201010096850200" - )), 1795, costDetails3, 1795)) + )), 1795, costDetails3, 1795, Seq.fill(4)(2051))) ) }, existingFeature({ (x: Coll[Box]) => x.flatMap({ (b: Box) => b.propositionBytes }) }, @@ -6476,11 +6564,12 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( { - def success[T](v: T, c: Int, cd: CostDetails, nc: Int) = Expected(Success(v), c, cd, nc) + def success[T](v: T, c: Int, cd: CostDetails, nc: Int, v3Costs: Seq[Int]) = Expected(Success(v), c, cd, nc, v3Costs) + Seq( - (Coll[Box](), success(Coll[(Box, Box)](), 1766, costDetails(0), 1766)), - (Coll[Box](b1), success(Coll[(Box, Box)]((b1, b1)), 1768, costDetails(1), 1768)), - (Coll[Box](b1, b2), success(Coll[(Box, Box)]((b1, b1), (b2, b2)), 1770, costDetails(2), 1770)) + (Coll[Box](), success(Coll[(Box, Box)](), 1766, costDetails(0), 1766, Seq.fill(4)(2018))), + (Coll[Box](b1), success(Coll[(Box, Box)]((b1, b1)), 1768, costDetails(1), 1768, Seq.fill(4)(2020))), + (Coll[Box](b1, b2), success(Coll[(Box, Box)]((b1, b1), (b2, b2)), 1770, costDetails(2), 1770, Seq.fill(4)(2022))) ) }, existingFeature({ (x: Coll[Box]) => x.zip(x) }, @@ -6506,7 +6595,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => val costDetails = TracedCost(traceBase :+ FixedCostItem(SizeOf)) verifyCases( { - def success[T](v: T) = Expected(Success(v), 1765, costDetails, 1765) + def success[T](v: T) = Expected(Success(v), 1765, costDetails, 1765, Seq.fill(4)(2001)) Seq( (Coll[Box](), success(0)), (Coll[Box](b1), success(1)), @@ -6531,7 +6620,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => ) verifyCases( { - def success[T](v: T, i: Int) = Expected(Success(v), 1768, costDetails(i), 1768) + def success[T](v: T, i: Int) = Expected(Success(v), 1768, costDetails(i), 1768, Seq.fill(4)(2008)) Seq( (Coll[Box](), success(Coll[Int](), 0)), (Coll[Box](b1), success(Coll[Int](0), 1)), @@ -6587,9 +6676,9 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => ) def cases = { Seq( - (Coll[Box](), Expected(Success(true), 1764, costDetails1, 1764)), - (Coll[Box](b1), Expected(Success(false), 1769, costDetails2, 1769)), - (Coll[Box](b1, b2), Expected(Success(false), 1769, costDetails3, 1769)) + (Coll[Box](), Expected(Success(true), 1764, costDetails1, 1764, Seq.fill(4)(2026))), + (Coll[Box](b1), Expected(Success(false), 1769, costDetails2, 1769, Seq.fill(4)(2031))), + (Coll[Box](b1, b2), Expected(Success(false), 1769, costDetails3, 1769, Seq.fill(4)(2031))) ) } if (lowerMethodCallsInTests) { @@ -6666,9 +6755,9 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( { Seq( - (Coll[Box](), Expected(Success(false), 1764, costDetails1, 1764)), - (Coll[Box](b1), Expected(Success(false), 1769, costDetails2, 1769)), - (Coll[Box](b1, b2), Expected(Success(true), 1773, costDetails3, 1773)) + (Coll[Box](), Expected(Success(false), 1764, costDetails1, 1764, Seq.fill(4)(2026))), + (Coll[Box](b1), Expected(Success(false), 1769, costDetails2, 1769, Seq.fill(4)(2031))), + (Coll[Box](b1, b2), Expected(Success(true), 1773, costDetails3, 1773, Seq.fill(4)(2035))) ) }, existingFeature({ (x: Coll[Box]) => x.exists({ (b: Box) => b.value > 1 }) }, @@ -6759,11 +6848,11 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( { Seq( - (Coll[BigInt](), Expected(Success(false), 1764, costDetails1, 1764)), - (Coll[BigInt](BigIntZero), Expected(Success(false), 1769, costDetails2, 1769)), - (Coll[BigInt](BigIntOne), Expected(Success(true), 1772, costDetails3, 1772)), - (Coll[BigInt](BigIntZero, BigIntOne), Expected(Success(true), 1777, costDetails4, 1777)), - (Coll[BigInt](BigIntZero, BigInt10), Expected(Success(false), 1777, costDetails4, 1777)) + (Coll[BigInt](), Expected(Success(false), 1764, costDetails1, 1764, Seq.fill(4)(2048))), + (Coll[BigInt](BigIntZero), Expected(Success(false), 1769, costDetails2, 1769, Seq.fill(4)(2053))), + (Coll[BigInt](BigIntOne), Expected(Success(true), 1772, costDetails3, 1772, Seq.fill(4)(2056))), + (Coll[BigInt](BigIntZero, BigIntOne), Expected(Success(true), 1777, costDetails4, 1777, Seq.fill(4)(2061))), + (Coll[BigInt](BigIntZero, BigInt10), Expected(Success(false), 1777, costDetails4, 1777, Seq.fill(4)(2061))) ) }, existingFeature( @@ -6874,11 +6963,11 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( { Seq( - (Coll[BigInt](), Expected(Success(true), 1764, costDetails1, 1764)), - (Coll[BigInt](BigIntMinusOne), Expected(Success(false), 1769, costDetails2, 1769)), - (Coll[BigInt](BigIntOne), Expected(Success(true), 1772, costDetails3, 1772)), - (Coll[BigInt](BigIntZero, BigIntOne), Expected(Success(true), 1779, costDetails4, 1779)), - (Coll[BigInt](BigIntZero, BigInt11), Expected(Success(false), 1779, costDetails4, 1779)) + (Coll[BigInt](), Expected(Success(true), 1764, costDetails1, 1764, Seq.fill(4)(2048))), + (Coll[BigInt](BigIntMinusOne), Expected(Success(false), 1769, costDetails2, 1769, Seq.fill(4)(2053))), + (Coll[BigInt](BigIntOne), Expected(Success(true), 1772, costDetails3, 1772, Seq.fill(4)(2056))), + (Coll[BigInt](BigIntZero, BigIntOne), Expected(Success(true), 1779, costDetails4, 1779, Seq.fill(4)(2063))), + (Coll[BigInt](BigIntZero, BigInt11), Expected(Success(false), 1779, costDetails4, 1779, Seq.fill(4)(2063))) ) }, existingFeature( @@ -7008,28 +7097,34 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( { - def success[T](v: T, c: Int, cd: CostDetails, newCost: Int) = Expected(Success(v), c, cd, newCost) + def success[T](v: T, c: Int, cd: CostDetails, newCost: Int, expectedV3Costs: Seq[Int]) = Expected(Success(v), c, cd, newCost, expectedV3Costs) + Seq( - Coll[GroupElement]() -> Expected(Success(Coll[Byte]()), 1773, CostDetails.ZeroCost, 1773, - newVersionedResults = { - val res = ExpectedResult(Success(Coll[Byte]()), Some(1773)) - Seq.tabulate(3)(v => - v -> (res -> Some(costDetails0)) - ) - }), + Coll[GroupElement]() -> Expected(Success(Coll[Byte]()), 1773, CostDetails.ZeroCost, 1773, + newVersionedResults = { + val costs = if (activatedVersionInTests >= V6SoftForkVersion) { + Seq.fill(4)(2029) + } + else { + Seq.fill(4)(1773) + } + Seq.tabulate(4)(v => + v -> (ExpectedResult(Success(Coll[Byte]()), Some(costs(v))) -> Some(costDetails0)) + ) + }), Coll[GroupElement]( Helpers.decodeGroupElement("02d65904820f8330218cf7318b3810d0c9ab9df86f1ee6100882683f23c0aee587"), Helpers.decodeGroupElement("0390e9daa9916f30d0bc61a8e381c6005edfb7938aee5bb4fc9e8a759c7748ffaa")) -> - success(Helpers.decodeBytes( - "02d65904820f8330218cf7318b3810d0c9ab9df86f1ee6100882683f23c0aee5870390e9daa9916f30d0bc61a8e381c6005edfb7938aee5bb4fc9e8a759c7748ffaa" - ), 1834, costDetails2, 1834), + success(Helpers.decodeBytes( + "02d65904820f8330218cf7318b3810d0c9ab9df86f1ee6100882683f23c0aee5870390e9daa9916f30d0bc61a8e381c6005edfb7938aee5bb4fc9e8a759c7748ffaa" + ), 1834, costDetails2, 1834, Seq.fill(4)(2090)), Coll[GroupElement]( Helpers.decodeGroupElement("02d65904820f8330218cf7318b3810d0c9ab9df86f1ee6100882683f23c0aee587"), Helpers.decodeGroupElement("0390e9daa9916f30d0bc61a8e381c6005edfb7938aee5bb4fc9e8a759c7748ffaa"), Helpers.decodeGroupElement("03bd839b969b02d218fd1192f2c80cbda9c6ce9c7ddb765f31b748f4666203df85")) -> - success(Helpers.decodeBytes( - "02d65904820f8330218cf7318b3810d0c9ab9df86f1ee6100882683f23c0aee5870390e9daa9916f30d0bc61a8e381c6005edfb7938aee5bb4fc9e8a759c7748ffaa03bd839b969b02d218fd1192f2c80cbda9c6ce9c7ddb765f31b748f4666203df85" - ), 1864, costDetails3, 1864) + success(Helpers.decodeBytes( + "02d65904820f8330218cf7318b3810d0c9ab9df86f1ee6100882683f23c0aee5870390e9daa9916f30d0bc61a8e381c6005edfb7938aee5bb4fc9e8a759c7748ffaa03bd839b969b02d218fd1192f2c80cbda9c6ce9c7ddb765f31b748f4666203df85" + ), 1864, costDetails3, 1864, Seq.fill(4)(2120)) ) }, existingFeature( @@ -7067,11 +7162,17 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => ) -> Expected(res, 1840, expectedDetails = CostDetails.ZeroCost, newCost = 1840, - newVersionedResults = (0 to 2).map(version => + newVersionedResults = (0 to 3).map({ version => + val costs = if (activatedVersionInTests >= V6SoftForkVersion) { + Seq.fill(4)(2104) + } + else { + Seq.fill(4)(1840) + } // successful result for each version version -> (ExpectedResult(res, - verificationCost = Some(1840)) -> Some(costDetails4)) - )) + verificationCost = Some(costs(version))) -> Some(costDetails4)) + })) ) } val f = existingFeature( @@ -7137,7 +7238,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( { - def success[T](v: T, cd: CostDetails) = Expected(Success(v), 1776, cd, 1776) + def success[T](v: T, cd: CostDetails) = Expected(Success(v), 1776, cd, 1776, Seq.fill(4)(2072)) Seq( ((Coll[Int](), (0, 0)), success(Coll[Int](), costDetails(0))), ((Coll[Int](1), (0, 0)), success(Coll[Int](1, 1), costDetails(2))), @@ -7226,7 +7327,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( // (coll, (index, elem)) { - def success[T](v: T, cd: CostDetails) = Expected(Success(v), 1774, cd, 1774) + def success[T](v: T, cd: CostDetails) = Expected(Success(v), 1774, cd, 1774, Seq.fill(4)(2058)) Seq( ((Coll[Int](), (0, 0)), Expected(new IndexOutOfBoundsException("0"))), ((Coll[Int](1), (0, 0)), success(Coll[Int](0), costDetails(1))), @@ -7303,7 +7404,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( // (coll, (indexes, values)) { - def success[T](v: T, i: Int) = Expected(Success(v), 1774, costDetails(i), 1774) + def success[T](v: T, i: Int) = Expected(Success(v), 1774, costDetails(i), 1774, Seq.fill(4)(2066)) Seq( ((Coll[Int](), (Coll(0), Coll(0))), Expected(new IndexOutOfBoundsException("0"))), ((Coll[Int](), (Coll(0, 1), Coll(0, 0))), Expected(new IndexOutOfBoundsException("0"))), @@ -7450,15 +7551,15 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => // (coll, initState) { Seq( - ((Coll[Byte](), 0), Expected(Success(0), 1767, costDetails1, 1767)), - ((Coll[Byte](), Int.MaxValue), Expected(Success(Int.MaxValue), 1767, costDetails1, 1767)), - ((Coll[Byte](1), Int.MaxValue - 1), Expected(Success(Int.MaxValue), 1773, costDetails2, 1773)), - ((Coll[Byte](1), Int.MaxValue), Expected(new ArithmeticException("integer overflow"))), - ((Coll[Byte](-1), Int.MinValue + 1), Expected(Success(Int.MinValue), 1773, costDetails2, 1773)), - ((Coll[Byte](-1), Int.MinValue), Expected(new ArithmeticException("integer overflow"))), - ((Coll[Byte](1, 2), 0), Expected(Success(3), 1779, costDetails3, 1779)), - ((Coll[Byte](1, -1), 0), Expected(Success(0), 1779, costDetails3, 1779)), - ((Coll[Byte](1, -1, 1), 0), Expected(Success(1), 1785, costDetails4, 1785)) + ((Coll[Byte](), 0), Expected(Success(0), 1767, costDetails1, 1767, Seq.fill(4)(2049))), + ((Coll[Byte](), Int.MaxValue), Expected(Success(Int.MaxValue), 1767, costDetails1, 1767, Seq.fill(4)(2049))), + ((Coll[Byte](1), Int.MaxValue - 1), Expected(Success(Int.MaxValue), 1773, costDetails2, 1773, Seq.fill(4)(2055))), + ((Coll[Byte](1), Int.MaxValue), Expected(new ArithmeticException("integer overflow"))), + ((Coll[Byte](-1), Int.MinValue + 1), Expected(Success(Int.MinValue), 1773, costDetails2, 1773, Seq.fill(4)(2055))), + ((Coll[Byte](-1), Int.MinValue), Expected(new ArithmeticException("integer overflow"))), + ((Coll[Byte](1, 2), 0), Expected(Success(3), 1779, costDetails3, 1779, Seq.fill(4)(2061))), + ((Coll[Byte](1, -1), 0), Expected(Success(0), 1779, costDetails3, 1779, Seq.fill(4)(2061))), + ((Coll[Byte](1, -1, 1), 0), Expected(Success(1), 1785, costDetails4, 1785, Seq.fill(4)(2067))) ) }, existingFeature( @@ -7711,15 +7812,15 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => // (coll, initState) { Seq( - ((Coll[Byte](), 0), Expected(Success(0), 1767, costDetails1, 1767)), - ((Coll[Byte](), Int.MaxValue), Expected(Success(Int.MaxValue), 1767, costDetails1, 1767)), - ((Coll[Byte](1), Int.MaxValue - 1), Expected(Success(Int.MaxValue), 1779, costDetails2, 1779)), - ((Coll[Byte](1), Int.MaxValue), Expected(new ArithmeticException("integer overflow"))), - ((Coll[Byte](-1), Int.MinValue + 1), Expected(Success(Int.MinValue + 1), 1777, costDetails3, 1777)), - ((Coll[Byte](-1), Int.MinValue), Expected(Success(Int.MinValue), 1777, costDetails3, 1777)), - ((Coll[Byte](1, 2), 0), Expected(Success(3), 1791, costDetails4, 1791)), - ((Coll[Byte](1, -1), 0), Expected(Success(1), 1789, costDetails5, 1789)), - ((Coll[Byte](1, -1, 1), 0), Expected(Success(2), 1801, costDetails6, 1801)) + ((Coll[Byte](), 0), Expected(Success(0), 1767, costDetails1, 1767, Seq.fill(4)(2089))), + ((Coll[Byte](), Int.MaxValue), Expected(Success(Int.MaxValue), 1767, costDetails1, 1767, Seq.fill(4)(2089))), + ((Coll[Byte](1), Int.MaxValue - 1), Expected(Success(Int.MaxValue), 1779, costDetails2, 1779, Seq.fill(4)(2101))), + ((Coll[Byte](1), Int.MaxValue), Expected(new ArithmeticException("integer overflow"))), + ((Coll[Byte](-1), Int.MinValue + 1), Expected(Success(Int.MinValue + 1), 1777, costDetails3, 1777, Seq.fill(4)(2099))), + ((Coll[Byte](-1), Int.MinValue), Expected(Success(Int.MinValue), 1777, costDetails3, 1777, Seq.fill(4)(2099))), + ((Coll[Byte](1, 2), 0), Expected(Success(3), 1791, costDetails4, 1791, Seq.fill(4)(2113))), + ((Coll[Byte](1, -1), 0), Expected(Success(1), 1789, costDetails5, 1789, Seq.fill(4)(2111))), + ((Coll[Byte](1, -1, 1), 0), Expected(Success(2), 1801, costDetails6, 1801, Seq.fill(4)(2123))) ) }, existingFeature( @@ -7830,11 +7931,16 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( // (coll, (elem: Byte, from: Int)) { - def success0[T](v: T) = Expected(Success(v), 1773, costDetails(0), 1773) - def success1[T](v: T) = Expected(Success(v), 1773, costDetails(1), 1773) - def success2[T](v: T) = Expected(Success(v), 1774, costDetails(2), 1774) - def success3[T](v: T) = Expected(Success(v), 1775, costDetails(3), 1775) - def success12[T](v: T) = Expected(Success(v), 1782, costDetails(12), 1782) + def success0[T](v: T) = Expected(Success(v), 1773, costDetails(0), 1773, Seq.fill(4)(2061)) + + def success1[T](v: T) = Expected(Success(v), 1773, costDetails(1), 1773, Seq.fill(4)(2061)) + + def success2[T](v: T) = Expected(Success(v), 1774, costDetails(2), 1774, Seq.fill(4)(2062)) + + def success3[T](v: T) = Expected(Success(v), 1775, costDetails(3), 1775, Seq.fill(4)(2063)) + + def success12[T](v: T) = Expected(Success(v), 1782, costDetails(12), 1782, Seq.fill(4)(2070)) + Seq( ((Coll[Byte](), (0.toByte, 0)), success0(-1)), ((Coll[Byte](), (0.toByte, -1)), success0(-1)), @@ -7896,7 +8002,8 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => ) verifyCases( { - def success[T](v: T) = Expected(Success(v), 1769, costDetails, 1769) + def success[T](v: T) = Expected(Success(v), 1769, costDetails, 1769, Seq.fill(4)(2019)) + Seq( ((Coll[Int](), 0), Expected(new ArrayIndexOutOfBoundsException("0"))), ((Coll[Int](), -1), Expected(new ArrayIndexOutOfBoundsException("-1"))), @@ -7960,7 +8067,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( // (coll, (index, default)) { - def success[T](v: T) = Expected(Success(v), 1773, costDetails, 1773) + def success[T](v: T) = Expected(Success(v), 1773, costDetails, 1773, Seq.fill(4)(2053)) Seq( ((Coll[Int](), (0, default)), success(default)), ((Coll[Int](), (-1, default)), success(default)), @@ -8043,7 +8150,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => ) verifyCases( { - def success[T](v: T) = Expected(Success(v), 1763, costDetails, 1763) + def success[T](v: T) = Expected(Success(v), 1763, costDetails, 1763, Seq.fill(4)(1997)) Seq( ((0, 0), success(2)), ((1, 2), success(2)) @@ -8058,7 +8165,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => val samples = genSamples[(Int, Int)](DefaultMinSuccessful) val costDetails = TracedCost(traceBase :+ FixedCostItem(SelectField)) verifyCases( - Seq(((1, 2), Expected(Success(1), cost = 1764, costDetails, 1764))), + Seq(((1, 2), Expected(Success(1), cost = 1764, costDetails, 1764, Seq.fill(4)(1998)))), existingFeature((x: (Int, Int)) => x._1, "{ (x: (Int, Int)) => x(0) }", FuncValue( @@ -8067,7 +8174,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => )), preGeneratedSamples = Some(samples)) verifyCases( - Seq(((1, 2), Expected(Success(2), cost = 1764, costDetails, 1764))), + Seq(((1, 2), Expected(Success(2), cost = 1764, costDetails, 1764, Seq.fill(4)(1998)))), existingFeature((x: (Int, Int)) => x._2, "{ (x: (Int, Int)) => x(1) }", FuncValue( @@ -8109,9 +8216,9 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => { def success[T](v: T, c: Int) = Expected(Success(v), c) Seq( - (Coll[Int](), Expected(Success(Coll[Int]()), 1768, costDetails(0), 1768)), - (Coll[Int](1), Expected(Success(Coll[Int](2)), 1771, costDetails(1), 1771)), - (Coll[Int](1, 2), Expected(Success(Coll[Int](2, 3)), 1774, costDetails(2), 1774)), + (Coll[Int](), Expected(Success(Coll[Int]()), 1768, costDetails(0), 1768, Seq.fill(4)(2022))), + (Coll[Int](1), Expected(Success(Coll[Int](2)), 1771, costDetails(1), 1771, Seq.fill(4)(2025))), + (Coll[Int](1, 2), Expected(Success(Coll[Int](2, 3)), 1774, costDetails(2), 1774, Seq.fill(4)(2028))), (Coll[Int](1, 2, Int.MaxValue), Expected(new ArithmeticException("integer overflow"))) ) }, @@ -8205,10 +8312,10 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => { def success[T](v: T, c: Int) = Expected(Success(v), c) Seq( - (Coll[Int](), Expected(Success(Coll[Int]()), 1768, costDetails1, 1768)), - (Coll[Int](1), Expected(Success(Coll[Int](2)), 1775, costDetails2, 1775)), - (Coll[Int](-1), Expected(Success(Coll[Int](1)), 1775, costDetails3, 1775)), - (Coll[Int](1, -2), Expected(Success(Coll[Int](2, 2)), 1782, costDetails4, 1782)), + (Coll[Int](), Expected(Success(Coll[Int]()), 1768, costDetails1, 1768, Seq.fill(4)(2054))), + (Coll[Int](1), Expected(Success(Coll[Int](2)), 1775, costDetails2, 1775, Seq.fill(4)(2061))), + (Coll[Int](-1), Expected(Success(Coll[Int](1)), 1775, costDetails3, 1775, Seq.fill(4)(2061))), + (Coll[Int](1, -2), Expected(Success(Coll[Int](2, 2)), 1782, costDetails4, 1782, Seq.fill(4)(2068))), (Coll[Int](1, 2, Int.MaxValue), Expected(new ArithmeticException("integer overflow"))), (Coll[Int](1, 2, Int.MinValue), Expected(new ArithmeticException("integer overflow"))) ) @@ -8256,24 +8363,24 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => val o = ExactOrdering.IntIsExactOrdering verifyCases( - { - Seq( - (Coll[Int](), Expected(Success(Coll[Int]()), 1768, costDetails(0), 1768)), - (Coll[Int](1), Expected(Success(Coll[Int](1)), 1771, costDetails(1), 1771)), - (Coll[Int](1, 2), Expected(Success(Coll[Int](1, 2)), 1775, costDetails(2), 1775)), - (Coll[Int](1, 2, -1), Expected(Success(Coll[Int](1, 2)), 1778, costDetails(3), 1778)), - (Coll[Int](1, -1, 2, -2), Expected(Success(Coll[Int](1, 2)), 1782, costDetails(4), 1782)) - ) - }, - existingFeature((x: Coll[Int]) => x.filter({ (v: Int) => o.gt(v, 0) }), - "{ (x: Coll[Int]) => x.filter({ (v: Int) => v > 0 }) }", - FuncValue( - Array((1, SCollectionType(SInt))), - Filter( - ValUse(1, SCollectionType(SInt)), - FuncValue(Array((3, SInt)), GT(ValUse(3, SInt), IntConstant(0))) + { + Seq( + (Coll[Int](), Expected(Success(Coll[Int]()), 1768, costDetails(0), 1768, Seq.fill(4)(2022))), + (Coll[Int](1), Expected(Success(Coll[Int](1)), 1771, costDetails(1), 1771, Seq.fill(4)(2025))), + (Coll[Int](1, 2), Expected(Success(Coll[Int](1, 2)), 1775, costDetails(2), 1775, Seq.fill(4)(2029))), + (Coll[Int](1, 2, -1), Expected(Success(Coll[Int](1, 2)), 1778, costDetails(3), 1778, Seq.fill(4)(2032))), + (Coll[Int](1, -1, 2, -2), Expected(Success(Coll[Int](1, 2)), 1782, costDetails(4), 1782, Seq.fill(4)(2036))) ) - ))) + }, + existingFeature((x: Coll[Int]) => x.filter({ (v: Int) => o.gt(v, 0) }), + "{ (x: Coll[Int]) => x.filter({ (v: Int) => v > 0 }) }", + FuncValue( + Array((1, SCollectionType(SInt))), + Filter( + ValUse(1, SCollectionType(SInt)), + FuncValue(Array((3, SInt)), GT(ValUse(3, SInt), IntConstant(0))) + ) + ))) } property("Coll filter with nested If") { @@ -8331,29 +8438,30 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => val o = ExactOrdering.IntIsExactOrdering verifyCases( - { - def success[T](v: T, c: Int) = Expected(Success(v), c) - Seq( - (Coll[Int](), Expected(Success(Coll[Int]()), 1768, costDetails(0), 1768)), - (Coll[Int](1), Expected(Success(Coll[Int](1)), 1775, costDetails(1), 1775)), - (Coll[Int](10), Expected(Success(Coll[Int]()), 1775, costDetails(1), 1775)), - (Coll[Int](1, 2), Expected(Success(Coll[Int](1, 2)), 1783, costDetails(2), 1783)), - (Coll[Int](1, 2, 0), Expected(Success(Coll[Int](1, 2)), 1788, costDetails3, 1788)), - (Coll[Int](1, -1, 2, -2, 11), Expected(Success(Coll[Int](1, 2)), 1800, costDetails5, 1800)) - ) - }, - existingFeature((x: Coll[Int]) => x.filter({ (v: Int) => if (o.gt(v, 0)) v < 10 else false }), - "{ (x: Coll[Int]) => x.filter({ (v: Int) => if (v > 0) v < 10 else false }) }", - FuncValue( - Array((1, SCollectionType(SInt))), - Filter( - ValUse(1, SCollectionType(SInt)), - FuncValue( - Array((3, SInt)), - If(GT(ValUse(3, SInt), IntConstant(0)), LT(ValUse(3, SInt), IntConstant(10)), FalseLeaf) - ) + { + def success[T](v: T, c: Int) = Expected(Success(v), c) + + Seq( + (Coll[Int](), Expected(Success(Coll[Int]()), 1768, costDetails(0), 1768, Seq.fill(4)(2048))), + (Coll[Int](1), Expected(Success(Coll[Int](1)), 1775, costDetails(1), 1775, Seq.fill(4)(2055))), + (Coll[Int](10), Expected(Success(Coll[Int]()), 1775, costDetails(1), 1775, Seq.fill(4)(2055))), + (Coll[Int](1, 2), Expected(Success(Coll[Int](1, 2)), 1783, costDetails(2), 1783, Seq.fill(4)(2063))), + (Coll[Int](1, 2, 0), Expected(Success(Coll[Int](1, 2)), 1788, costDetails3, 1788, Seq.fill(4)(2068))), + (Coll[Int](1, -1, 2, -2, 11), Expected(Success(Coll[Int](1, 2)), 1800, costDetails5, 1800, Seq.fill(4)(2080))) ) - ))) + }, + existingFeature((x: Coll[Int]) => x.filter({ (v: Int) => if (o.gt(v, 0)) v < 10 else false }), + "{ (x: Coll[Int]) => x.filter({ (v: Int) => if (v > 0) v < 10 else false }) }", + FuncValue( + Array((1, SCollectionType(SInt))), + Filter( + ValUse(1, SCollectionType(SInt)), + FuncValue( + Array((3, SInt)), + If(GT(ValUse(3, SInt), IntConstant(0)), LT(ValUse(3, SInt), IntConstant(10)), FalseLeaf) + ) + ) + ))) } property("Coll slice method equivalence") { @@ -8380,48 +8488,49 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => val samples = genSamples(collWithRangeGen, DefaultMinSuccessful) if (lowerMethodCallsInTests) { verifyCases( - { - val cost = 1772 - val newCost = 1772 - Seq( - // (coll, (from, until)) - ((Coll[Int](), (-1, 0)), Expected(Success(Coll[Int]()), cost, costDetails(1), newCost)), - ((Coll[Int](), (0, 0)), Expected(Success(Coll[Int]()), cost, costDetails(0), newCost)), - ((Coll[Int](1), (0, 0)), Expected(Success(Coll[Int]()), cost, costDetails(0), newCost)), - ((Coll[Int](1), (0, -1)), Expected(Success(Coll[Int]()), cost, costDetails(0), newCost)), - ((Coll[Int](1), (1, 1)), Expected(Success(Coll[Int]()), cost, costDetails(0), newCost)), - ((Coll[Int](1), (-1, 1)), Expected(Success(Coll[Int](1)), cost, costDetails(2), newCost)), - ((Coll[Int](1, 2), (1, 1)), Expected(Success(Coll[Int]()), cost, costDetails(0), newCost)), - ((Coll[Int](1, 2), (1, 0)), Expected(Success(Coll[Int]()), cost, costDetails(0), newCost)), - ((Coll[Int](1, 2), (1, 2)), Expected(Success(Coll[Int](2)), cost, costDetails(1), newCost)), - ((Coll[Int](1, 2, 3, 4), (1, 3)), Expected(Success(Coll[Int](2, 3)), cost, costDetails(2), newCost)) - ) - }, - existingFeature((x: (Coll[Int], (Int, Int))) => x._1.slice(x._2._1, x._2._2), - "{ (x: (Coll[Int], (Int, Int))) => x._1.slice(x._2._1, x._2._2) }", - FuncValue( - Vector((1, SPair(SCollectionType(SInt), SPair(SInt, SInt)))), - BlockValue( - Vector( - ValDef( - 3, - List(), - SelectField.typed[Value[STuple]]( - ValUse(1, SPair(SCollectionType(SInt), SPair(SInt, SInt))), - 2.toByte + { + val cost = 1772 + val newCost = 1772 + val v3Costs = Seq.fill(4)(2050) + Seq( + // (coll, (from, until)) + ((Coll[Int](), (-1, 0)), Expected(Success(Coll[Int]()), cost, costDetails(1), newCost, v3Costs)), + ((Coll[Int](), (0, 0)), Expected(Success(Coll[Int]()), cost, costDetails(0), newCost, v3Costs)), + ((Coll[Int](1), (0, 0)), Expected(Success(Coll[Int]()), cost, costDetails(0), newCost, v3Costs)), + ((Coll[Int](1), (0, -1)), Expected(Success(Coll[Int]()), cost, costDetails(0), newCost, v3Costs)), + ((Coll[Int](1), (1, 1)), Expected(Success(Coll[Int]()), cost, costDetails(0), newCost, v3Costs)), + ((Coll[Int](1), (-1, 1)), Expected(Success(Coll[Int](1)), cost, costDetails(2), newCost, v3Costs)), + ((Coll[Int](1, 2), (1, 1)), Expected(Success(Coll[Int]()), cost, costDetails(0), newCost, v3Costs)), + ((Coll[Int](1, 2), (1, 0)), Expected(Success(Coll[Int]()), cost, costDetails(0), newCost, v3Costs)), + ((Coll[Int](1, 2), (1, 2)), Expected(Success(Coll[Int](2)), cost, costDetails(1), newCost, v3Costs)), + ((Coll[Int](1, 2, 3, 4), (1, 3)), Expected(Success(Coll[Int](2, 3)), cost, costDetails(2), newCost, v3Costs)) + ) + }, + existingFeature((x: (Coll[Int], (Int, Int))) => x._1.slice(x._2._1, x._2._2), + "{ (x: (Coll[Int], (Int, Int))) => x._1.slice(x._2._1, x._2._2) }", + FuncValue( + Vector((1, SPair(SCollectionType(SInt), SPair(SInt, SInt)))), + BlockValue( + Vector( + ValDef( + 3, + List(), + SelectField.typed[Value[STuple]]( + ValUse(1, SPair(SCollectionType(SInt), SPair(SInt, SInt))), + 2.toByte + ) ) - ) - ), - Slice( - SelectField.typed[Value[SCollection[SInt.type]]]( - ValUse(1, SPair(SCollectionType(SInt), SPair(SInt, SInt))), - 1.toByte ), - SelectField.typed[Value[SInt.type]](ValUse(3, SPair(SInt, SInt)), 1.toByte), - SelectField.typed[Value[SInt.type]](ValUse(3, SPair(SInt, SInt)), 2.toByte) + Slice( + SelectField.typed[Value[SCollection[SInt.type]]]( + ValUse(1, SPair(SCollectionType(SInt), SPair(SInt, SInt))), + 1.toByte + ), + SelectField.typed[Value[SInt.type]](ValUse(3, SPair(SInt, SInt)), 1.toByte), + SelectField.typed[Value[SInt.type]](ValUse(3, SPair(SInt, SInt)), 2.toByte) + ) ) - ) - )), + )), preGeneratedSamples = Some(samples)) } else { def error = new java.lang.NoSuchMethodException("sigmastate.SCollection$.slice_eval(sigmastate.lang.Terms$MethodCall,sigma.Coll,int,int,sigmastate.interpreter.ErgoTreeEvaluator))") @@ -8471,37 +8580,38 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => ) if (lowerMethodCallsInTests) { verifyCases( - { - def success[T](v: T, size: Int) = Expected(Success(v), 1770, costDetails(size), 1770) - val arr1 = Gen.listOfN(100, arbitrary[Int]).map(_.toArray).sample.get - val arr2 = Gen.listOfN(200, arbitrary[Int]).map(_.toArray).sample.get - Seq( - (Coll[Int](), Coll[Int]()) -> success(Coll[Int](), 0), - (Coll[Int](), Coll[Int](1)) -> success(Coll[Int](1), 1), - (Coll[Int](1), Coll[Int]()) -> success(Coll[Int](1), 1), - (Coll[Int](1), Coll[Int](2)) -> success(Coll[Int](1, 2), 2), - (Coll[Int](1), Coll[Int](2, 3)) -> success(Coll[Int](1, 2, 3), 3), - (Coll[Int](1, 2), Coll[Int](3)) -> success(Coll[Int](1, 2, 3), 3), - (Coll[Int](1, 2), Coll[Int](3, 4)) -> success(Coll[Int](1, 2, 3, 4), 4), - (Coll[Int](arr1:_*), Coll[Int](arr2:_*)) -> Expected(Success(Coll[Int](arr1 ++ arr2:_*)), 1771, costDetails(300), 1771) - ) - }, - existingFeature( - { (x: (Coll[Int], Coll[Int])) => x._1.append(x._2) }, - "{ (x: (Coll[Int], Coll[Int])) => x._1.append(x._2) }", - FuncValue( - Vector((1, SPair(SCollectionType(SInt), SCollectionType(SInt)))), - Append( - SelectField.typed[Value[SCollection[SInt.type]]]( - ValUse(1, SPair(SCollectionType(SInt), SCollectionType(SInt))), - 1.toByte - ), - SelectField.typed[Value[SCollection[SInt.type]]]( - ValUse(1, SPair(SCollectionType(SInt), SCollectionType(SInt))), - 2.toByte - ) + { + def success[T](v: T, size: Int) = Expected(Success(v), 1770, costDetails(size), 1770, Seq.fill(4)(2022)) + + val arr1 = Gen.listOfN(100, arbitrary[Int]).map(_.toArray).sample.get + val arr2 = Gen.listOfN(200, arbitrary[Int]).map(_.toArray).sample.get + Seq( + (Coll[Int](), Coll[Int]()) -> success(Coll[Int](), 0), + (Coll[Int](), Coll[Int](1)) -> success(Coll[Int](1), 1), + (Coll[Int](1), Coll[Int]()) -> success(Coll[Int](1), 1), + (Coll[Int](1), Coll[Int](2)) -> success(Coll[Int](1, 2), 2), + (Coll[Int](1), Coll[Int](2, 3)) -> success(Coll[Int](1, 2, 3), 3), + (Coll[Int](1, 2), Coll[Int](3)) -> success(Coll[Int](1, 2, 3), 3), + (Coll[Int](1, 2), Coll[Int](3, 4)) -> success(Coll[Int](1, 2, 3, 4), 4), + (Coll[Int](arr1: _*), Coll[Int](arr2: _*)) -> Expected(Success(Coll[Int](arr1 ++ arr2: _*)), 1771, costDetails(300), 1771, Seq.fill(4)(2023)) ) - ))) + }, + existingFeature( + { (x: (Coll[Int], Coll[Int])) => x._1.append(x._2) }, + "{ (x: (Coll[Int], Coll[Int])) => x._1.append(x._2) }", + FuncValue( + Vector((1, SPair(SCollectionType(SInt), SCollectionType(SInt)))), + Append( + SelectField.typed[Value[SCollection[SInt.type]]]( + ValUse(1, SPair(SCollectionType(SInt), SCollectionType(SInt))), + 1.toByte + ), + SelectField.typed[Value[SCollection[SInt.type]]]( + ValUse(1, SPair(SCollectionType(SInt), SCollectionType(SInt))), + 2.toByte + ) + ) + ))) } else { def error = new java.lang.NoSuchMethodException("sigmastate.SCollection$.append_eval(sigmastate.lang.Terms$MethodCall,sigma.Coll,sigma.Coll,sigmastate.interpreter.ErgoTreeEvaluator))") verifyCases( @@ -8578,33 +8688,33 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( Seq( (None -> Expected(new NoSuchElementException("None.get"))), - (Some(10L) -> Expected(Success(10L), 1765, costDetails1, 1765))), + (Some(10L) -> Expected(Success(10L), 1765, costDetails1, 1765, Seq.fill(4)(1997)))), existingFeature({ (x: Option[Long]) => x.get }, "{ (x: Option[Long]) => x.get }", FuncValue(Vector((1, SOption(SLong))), OptionGet(ValUse(1, SOption(SLong)))))) verifyCases( Seq( - (None -> Expected(Success(false), 1764, costDetails2, 1764)), - (Some(10L) -> Expected(Success(true), 1764, costDetails2, 1764))), + (None -> Expected(Success(false), 1764, costDetails2, 1764, Seq.fill(4)(1996))), + (Some(10L) -> Expected(Success(true), 1764, costDetails2, 1764, Seq.fill(4)(1996)))), existingFeature({ (x: Option[Long]) => x.isDefined }, "{ (x: Option[Long]) => x.isDefined }", FuncValue(Vector((1, SOption(SLong))), OptionIsDefined(ValUse(1, SOption(SLong)))))) verifyCases( Seq( - (None -> Expected(Success(1L), 1766, costDetails3, 1766)), - (Some(10L) -> Expected(Success(10L), 1766, costDetails3, 1766))), + (None -> Expected(Success(1L), 1766, costDetails3, 1766, Seq.fill(4)(2006))), + (Some(10L) -> Expected(Success(10L), 1766, costDetails3, 1766, Seq.fill(4)(2006)))), existingFeature({ (x: Option[Long]) => x.getOrElse(1L) }, "{ (x: Option[Long]) => x.getOrElse(1L) }", FuncValue(Vector((1, SOption(SLong))), OptionGetOrElse(ValUse(1, SOption(SLong)), LongConstant(1L))))) verifyCases( Seq( - (None -> Expected(Success(None), 1766, costDetails4, 1766)), - (Some(10L) -> Expected(Success(None), 1768, costDetails5, 1768)), - (Some(1L) -> Expected(Success(Some(1L)), 1769, costDetails5, 1769))), - existingFeature({ (x: Option[Long]) => x.filter({ (v: Long) => v == 1} ) }, + (None -> Expected(Success(None), 1766, costDetails4, 1766, Seq.fill(4)(2028))), + (Some(10L) -> Expected(Success(None), 1768, costDetails5, 1768, Seq.fill(4)(2030))), + (Some(1L) -> Expected(Success(Some(1L)), 1769, costDetails5, 1769, Seq.fill(4)(2031)))), + existingFeature({ (x: Option[Long]) => x.filter({ (v: Long) => v == 1 }) }, "{ (x: Option[Long]) => x.filter({ (v: Long) => v == 1 }) }", FuncValue( Vector((1, SOption(SLong))), @@ -8619,8 +8729,8 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => val n = ExactNumeric.LongIsExactNumeric verifyCases( Seq( - (None -> Expected(Success(None), 1766, costDetails6, 1766)), - (Some(10L) -> Expected(Success(Some(11L)), 1770, costDetails7, 1770)), + (None -> Expected(Success(None), 1766, costDetails6, 1766, Seq.fill(4)(2028))), + (Some(10L) -> Expected(Success(Some(11L)), 1770, costDetails7, 1770, Seq.fill(4)(2032))), (Some(Long.MaxValue) -> Expected(new ArithmeticException("long overflow")))), existingFeature({ (x: Option[Long]) => x.map( (v: Long) => n.plus(v, 1) ) }, "{ (x: Option[Long]) => x.map({ (v: Long) => v + 1 }) }", @@ -8682,10 +8792,10 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => val o = ExactOrdering.LongIsExactOrdering verifyCases( Seq( - (None -> Expected(Success(None), 1766, costDetails1, 1766)), - (Some(0L) -> Expected(Success(None), 1771, costDetails2, 1771)), - (Some(10L) -> Expected(Success(Some(10L)), 1774, costDetails3, 1774)), - (Some(11L) -> Expected(Success(None), 1774, costDetails3, 1774))), + (None -> Expected(Success(None), 1766, costDetails1, 1766, Seq.fill(4)(2052))), + (Some(0L) -> Expected(Success(None), 1771, costDetails2, 1771, Seq.fill(4)(2057))), + (Some(10L) -> Expected(Success(Some(10L)), 1774, costDetails3, 1774, Seq.fill(4)(2060))), + (Some(11L) -> Expected(Success(None), 1774, costDetails3, 1774, Seq.fill(4)(2060)))), existingFeature( { (x: Option[Long]) => x.filter({ (v: Long) => if (o.gt(v, 0L)) v <= 10 else false } ) }, "{ (x: Option[Long]) => x.filter({ (v: Long) => if (v > 0) v <= 10 else false }) }", @@ -8746,10 +8856,10 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => val n = ExactNumeric.LongIsExactNumeric verifyCases( Seq( - (None -> Expected(Success(None), 1766, costDetails4, 1766)), - (Some(0L) -> Expected(Success(Some(0L)), 1772, costDetails5, 1772)), - (Some(10L) -> Expected(Success(Some(10L)), 1772, costDetails5, 1772)), - (Some(-1L) -> Expected(Success(Some(-2L)), 1774, costDetails6, 1774)), + (None -> Expected(Success(None), 1766, costDetails4, 1766, Seq.fill(4)(2048))), + (Some(0L) -> Expected(Success(Some(0L)), 1772, costDetails5, 1772, Seq.fill(4)(2054))), + (Some(10L) -> Expected(Success(Some(10L)), 1772, costDetails5, 1772, Seq.fill(4)(2054))), + (Some(-1L) -> Expected(Success(Some(-2L)), 1774, costDetails6, 1774, Seq.fill(4)(2056))), (Some(Long.MinValue) -> Expected(new ArithmeticException("long overflow")))), existingFeature( { (x: Option[Long]) => x.map( (v: Long) => if (o.lt(v, 0)) n.minus(v, 1) else v ) }, @@ -8802,20 +8912,30 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( Seq( (None -> Expected( - value = Failure(new NoSuchElementException("None.get")), - cost = 0, - expectedDetails = CostDetails.ZeroCost, - newCost = 1766, - newVersionedResults = Seq.tabulate(4)(v => v -> (ExpectedResult(Success(5L), Some(1766)) -> Some(costDetails1))) - )), + value = Failure(new NoSuchElementException("None.get")), + cost = 0, + expectedDetails = CostDetails.ZeroCost, + newCost = 1766, + newVersionedResults = Seq.tabulate(4)({ v => + val costs = if (activatedVersionInTests >= V6SoftForkVersion) { + Seq.fill(4)(2042) + } + else { + Seq.fill(4)(1766) + } + v -> (ExpectedResult(Success(5L), Some(costs(v))) -> Some(costDetails1)) + }) + )), (Some(0L) -> Expected( Success(1L), cost = 1774, expectedDetails = costDetails2, - expectedNewCost = 1774)), + expectedNewCost = 1774, + expectedV3Costs = Seq.fill(4)(2050))), (Some(Long.MaxValue) -> Expected(new ArithmeticException("long overflow"))) ), changedFeature( + changedInVersion = VersionContext.JitActivationVersion, scalaFunc = { (x: Option[Long]) => def f(opt: Long): Long = n.plus(opt, 1) if (x.isDefined) f(x.get) @@ -8880,19 +9000,22 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => Success(Helpers.decodeBytes("0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a8")), 1768, costDetailsBlake(0), - 1768 + 1768, + Seq.fill(4)(2000) ), Helpers.decodeBytes("e0ff0105ffffac31010017ff33") -> Expected( Success(Helpers.decodeBytes("33707eed9aab64874ff2daa6d6a378f61e7da36398fb36c194c7562c9ff846b5")), 1768, costDetailsBlake(13), - 1768 + 1768, + Seq.fill(4)(2000) ), Colls.replicate(1024, 1.toByte) -> Expected( Success(Helpers.decodeBytes("45d8456fc5d41d1ec1124cb92e41192c1c3ec88f0bf7ae2dc6e9cf75bec22045")), 1773, costDetailsBlake(1024), - 1773 + 1773, + Seq.fill(4)(2005) ) ), existingFeature((x: Coll[Byte]) => SigmaDsl.blake2b256(x), @@ -8905,19 +9028,22 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => Success(Helpers.decodeBytes("e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855")), 1774, costDetailsSha(0), - 1774 + 1774, + Seq.fill(4)(2006) ), Helpers.decodeBytes("e0ff0105ffffac31010017ff33") -> Expected( Success(Helpers.decodeBytes("367d0ec2cdc14aac29d5beb60c2bfc86d5a44a246308659af61c1b85fa2ca2cc")), 1774, costDetailsSha(13), - 1774 + 1774, + Seq.fill(4)(2006) ), Colls.replicate(1024, 1.toByte) -> Expected( Success(Helpers.decodeBytes("5a648d8015900d89664e00e125df179636301a2d8fa191c1aa2bd9358ea53a69")), 1786, costDetailsSha(1024), - 1786 + 1786, + Seq.fill(4)(2018) ) ), existingFeature((x: Coll[Byte]) => SigmaDsl.sha256(x), @@ -8927,10 +9053,11 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => property("sigmaProp equivalence") { val costDetails = TracedCost(traceBase :+ FixedCostItem(BoolToSigmaProp)) + val v3Costs = Seq.fill(4)(1997) verifyCases( Seq( - (false, Expected(Success(CSigmaProp(TrivialProp.FalseProp)), 1765, costDetails, 1765)), - (true, Expected(Success(CSigmaProp(TrivialProp.TrueProp)), 1765, costDetails, 1765))), + (false, Expected(Success(CSigmaProp(TrivialProp.FalseProp)), 1765, costDetails, 1765, v3Costs)), + (true, Expected(Success(CSigmaProp(TrivialProp.TrueProp)), 1765, costDetails, 1765, v3Costs))), existingFeature((x: Boolean) => sigmaProp(x), "{ (x: Boolean) => sigmaProp(x) }", FuncValue(Vector((1, SBoolean)), BoolToSigmaProp(ValUse(1, SBoolean))))) @@ -8957,7 +9084,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => Helpers.decodeECPoint("02614b14a8c6c6b4b7ce017d72fbca7f9218b72c16bdd88f170ffb300b106b9014"), Helpers.decodeECPoint("034cc5572276adfa3e283a3f1b0f0028afaadeaa362618c5ec43262d8cefe7f004") ) - )) -> Expected(Success(CSigmaProp(TrivialProp.TrueProp)), 1770, costDetails(1), 1770), + )) -> Expected(Success(CSigmaProp(TrivialProp.TrueProp)), 1770, costDetails(1), 1770, Seq.fill(4)(2018)), Coll[SigmaProp]( CSigmaProp( ProveDHTuple( @@ -8985,7 +9112,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => ) ) ) - ), 1873, costDetails(3), 1873), + ), 1873, costDetails(3), 1873, Seq.fill(4)(2121)), Colls.replicate[SigmaProp](AtLeast.MaxChildrenCount + 1, CSigmaProp(TrivialProp.TrueProp)) -> Expected(new IllegalArgumentException("Expected input elements count should not exceed 255, actual: 256")) ), @@ -9017,31 +9144,32 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => verifyCases( { - def success[T](v: T, newCost: Int) = Expected(Success(v), newCost, costDetails1, newCost) + def success[T](v: T, newCost: Int, expectedV3Costs: Seq[Int]) = Expected(Success(v), newCost, costDetails1, newCost, expectedV3Costs) + Seq( (CSigmaProp(ProveDlog(Helpers.decodeECPoint("02ea9bf6da7f512386c6ca509d40f8c5e7e0ffb3eea5dc3c398443ea17f4510798"))), - CSigmaProp(ProveDlog(Helpers.decodeECPoint("03a426a66fc1af2792b35d9583904c3fb877b49ae5cea45b7a2aa105ffa4c68606")))) -> - success( - CSigmaProp( - CAND( - Seq( - ProveDlog(Helpers.decodeECPoint("02ea9bf6da7f512386c6ca509d40f8c5e7e0ffb3eea5dc3c398443ea17f4510798")), - ProveDlog(Helpers.decodeECPoint("03a426a66fc1af2792b35d9583904c3fb877b49ae5cea45b7a2aa105ffa4c68606")) - ) + CSigmaProp(ProveDlog(Helpers.decodeECPoint("03a426a66fc1af2792b35d9583904c3fb877b49ae5cea45b7a2aa105ffa4c68606")))) -> + success( + CSigmaProp( + CAND( + Seq( + ProveDlog(Helpers.decodeECPoint("02ea9bf6da7f512386c6ca509d40f8c5e7e0ffb3eea5dc3c398443ea17f4510798")), + ProveDlog(Helpers.decodeECPoint("03a426a66fc1af2792b35d9583904c3fb877b49ae5cea45b7a2aa105ffa4c68606")) ) - ), 1802), + ) + ), 1802, Seq.fill(4)(2048)), (CSigmaProp(TrivialProp.TrueProp), - CSigmaProp(ProveDlog(Helpers.decodeECPoint("03a426a66fc1af2792b35d9583904c3fb877b49ae5cea45b7a2aa105ffa4c68606")))) -> - success(CSigmaProp(ProveDlog(Helpers.decodeECPoint("03a426a66fc1af2792b35d9583904c3fb877b49ae5cea45b7a2aa105ffa4c68606"))), 1784), + CSigmaProp(ProveDlog(Helpers.decodeECPoint("03a426a66fc1af2792b35d9583904c3fb877b49ae5cea45b7a2aa105ffa4c68606")))) -> + success(CSigmaProp(ProveDlog(Helpers.decodeECPoint("03a426a66fc1af2792b35d9583904c3fb877b49ae5cea45b7a2aa105ffa4c68606"))), 1784, Seq.fill(4)(2030)), (CSigmaProp(TrivialProp.FalseProp), - CSigmaProp(ProveDlog(Helpers.decodeECPoint("03a426a66fc1af2792b35d9583904c3fb877b49ae5cea45b7a2aa105ffa4c68606")))) -> - success(CSigmaProp(TrivialProp.FalseProp), 1767), + CSigmaProp(ProveDlog(Helpers.decodeECPoint("03a426a66fc1af2792b35d9583904c3fb877b49ae5cea45b7a2aa105ffa4c68606")))) -> + success(CSigmaProp(TrivialProp.FalseProp), 1767, Seq.fill(4)(2013)), (CSigmaProp(ProveDlog(Helpers.decodeECPoint("03a426a66fc1af2792b35d9583904c3fb877b49ae5cea45b7a2aa105ffa4c68606"))), - CSigmaProp(TrivialProp.TrueProp)) -> - success(CSigmaProp(ProveDlog(Helpers.decodeECPoint("03a426a66fc1af2792b35d9583904c3fb877b49ae5cea45b7a2aa105ffa4c68606"))), 1784), + CSigmaProp(TrivialProp.TrueProp)) -> + success(CSigmaProp(ProveDlog(Helpers.decodeECPoint("03a426a66fc1af2792b35d9583904c3fb877b49ae5cea45b7a2aa105ffa4c68606"))), 1784, Seq.fill(4)(2030)), (CSigmaProp(ProveDlog(Helpers.decodeECPoint("03a426a66fc1af2792b35d9583904c3fb877b49ae5cea45b7a2aa105ffa4c68606"))), - CSigmaProp(TrivialProp.FalseProp)) -> - success(CSigmaProp(TrivialProp.FalseProp), 1767) + CSigmaProp(TrivialProp.FalseProp)) -> + success(CSigmaProp(TrivialProp.FalseProp), 1767, Seq.fill(4)(2013)) ) }, existingFeature( @@ -9061,9 +9189,9 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => { Seq( (CSigmaProp(ProveDlog(Helpers.decodeECPoint("03a426a66fc1af2792b35d9583904c3fb877b49ae5cea45b7a2aa105ffa4c68606"))), true) -> - Expected(Success(CSigmaProp(ProveDlog(Helpers.decodeECPoint("03a426a66fc1af2792b35d9583904c3fb877b49ae5cea45b7a2aa105ffa4c68606")))), 1786, costDetails2, 1786), + Expected(Success(CSigmaProp(ProveDlog(Helpers.decodeECPoint("03a426a66fc1af2792b35d9583904c3fb877b49ae5cea45b7a2aa105ffa4c68606")))), 1786, costDetails2, 1786, Seq.fill(4)(2038)), (CSigmaProp(ProveDlog(Helpers.decodeECPoint("03a426a66fc1af2792b35d9583904c3fb877b49ae5cea45b7a2aa105ffa4c68606"))), false) -> - Expected(Success(CSigmaProp(TrivialProp.FalseProp)), 1769, costDetails2, 1769) + Expected(Success(CSigmaProp(TrivialProp.FalseProp)), 1769, costDetails2, 1769, Seq.fill(4)(2021)) ) }, existingFeature( @@ -9092,32 +9220,33 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => val costDetails1 = TracedCost(testTraceBase :+ ast.SeqCostItem(CompanionDesc(SigmaOr), PerItemCost(JitCost(10), JitCost(2), 1), 2)) verifyCases( { - def success[T](v: T, newCost: Int) = Expected(Success(v), newCost, costDetails1, newCost) + def success[T](v: T, newCost: Int, v3Costs: Seq[Int]) = Expected(Success(v), newCost, costDetails1, newCost, v3Costs) + Seq( (CSigmaProp(ProveDlog(Helpers.decodeECPoint("02ea9bf6da7f512386c6ca509d40f8c5e7e0ffb3eea5dc3c398443ea17f4510798"))), - CSigmaProp(ProveDlog(Helpers.decodeECPoint("03a426a66fc1af2792b35d9583904c3fb877b49ae5cea45b7a2aa105ffa4c68606")))) -> - success( - CSigmaProp( - COR( - Seq( - ProveDlog(Helpers.decodeECPoint("02ea9bf6da7f512386c6ca509d40f8c5e7e0ffb3eea5dc3c398443ea17f4510798")), - ProveDlog(Helpers.decodeECPoint("03a426a66fc1af2792b35d9583904c3fb877b49ae5cea45b7a2aa105ffa4c68606")) - ) + CSigmaProp(ProveDlog(Helpers.decodeECPoint("03a426a66fc1af2792b35d9583904c3fb877b49ae5cea45b7a2aa105ffa4c68606")))) -> + success( + CSigmaProp( + COR( + Seq( + ProveDlog(Helpers.decodeECPoint("02ea9bf6da7f512386c6ca509d40f8c5e7e0ffb3eea5dc3c398443ea17f4510798")), + ProveDlog(Helpers.decodeECPoint("03a426a66fc1af2792b35d9583904c3fb877b49ae5cea45b7a2aa105ffa4c68606")) ) - ), - 1802), + ) + ), + 1802, Seq.fill(4)(2048)), (CSigmaProp(TrivialProp.FalseProp), - CSigmaProp(ProveDlog(Helpers.decodeECPoint("03a426a66fc1af2792b35d9583904c3fb877b49ae5cea45b7a2aa105ffa4c68606")))) -> - success(CSigmaProp(ProveDlog(Helpers.decodeECPoint("03a426a66fc1af2792b35d9583904c3fb877b49ae5cea45b7a2aa105ffa4c68606"))), 1784), + CSigmaProp(ProveDlog(Helpers.decodeECPoint("03a426a66fc1af2792b35d9583904c3fb877b49ae5cea45b7a2aa105ffa4c68606")))) -> + success(CSigmaProp(ProveDlog(Helpers.decodeECPoint("03a426a66fc1af2792b35d9583904c3fb877b49ae5cea45b7a2aa105ffa4c68606"))), 1784, Seq.fill(4)(2030)), (CSigmaProp(TrivialProp.TrueProp), - CSigmaProp(ProveDlog(Helpers.decodeECPoint("03a426a66fc1af2792b35d9583904c3fb877b49ae5cea45b7a2aa105ffa4c68606")))) -> - success(CSigmaProp(TrivialProp.TrueProp), 1767), + CSigmaProp(ProveDlog(Helpers.decodeECPoint("03a426a66fc1af2792b35d9583904c3fb877b49ae5cea45b7a2aa105ffa4c68606")))) -> + success(CSigmaProp(TrivialProp.TrueProp), 1767, Seq.fill(4)(2013)), (CSigmaProp(ProveDlog(Helpers.decodeECPoint("03a426a66fc1af2792b35d9583904c3fb877b49ae5cea45b7a2aa105ffa4c68606"))), - CSigmaProp(TrivialProp.FalseProp)) -> - success(CSigmaProp(ProveDlog(Helpers.decodeECPoint("03a426a66fc1af2792b35d9583904c3fb877b49ae5cea45b7a2aa105ffa4c68606"))), 1784), + CSigmaProp(TrivialProp.FalseProp)) -> + success(CSigmaProp(ProveDlog(Helpers.decodeECPoint("03a426a66fc1af2792b35d9583904c3fb877b49ae5cea45b7a2aa105ffa4c68606"))), 1784, Seq.fill(4)(2030)), (CSigmaProp(ProveDlog(Helpers.decodeECPoint("03a426a66fc1af2792b35d9583904c3fb877b49ae5cea45b7a2aa105ffa4c68606"))), - CSigmaProp(TrivialProp.TrueProp)) -> - success(CSigmaProp(TrivialProp.TrueProp), 1767) + CSigmaProp(TrivialProp.TrueProp)) -> + success(CSigmaProp(TrivialProp.TrueProp), 1767, Seq.fill(4)(2013)) ) }, existingFeature( @@ -9141,12 +9270,13 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => ) verifyCases( { - def success[T](v: T, newCost: Int) = Expected(Success(v), newCost, costDetails2, newCost) + def success[T](v: T, newCost: Int, v3Costs: Seq[Int]) = Expected(Success(v), newCost, costDetails2, newCost, v3Costs) + Seq( (CSigmaProp(ProveDlog(Helpers.decodeECPoint("03a426a66fc1af2792b35d9583904c3fb877b49ae5cea45b7a2aa105ffa4c68606"))), false) -> - success(CSigmaProp(ProveDlog(Helpers.decodeECPoint("03a426a66fc1af2792b35d9583904c3fb877b49ae5cea45b7a2aa105ffa4c68606"))), 1786), + success(CSigmaProp(ProveDlog(Helpers.decodeECPoint("03a426a66fc1af2792b35d9583904c3fb877b49ae5cea45b7a2aa105ffa4c68606"))), 1786, Seq.fill(4)(2038)), (CSigmaProp(ProveDlog(Helpers.decodeECPoint("03a426a66fc1af2792b35d9583904c3fb877b49ae5cea45b7a2aa105ffa4c68606"))), true) -> - success(CSigmaProp(TrivialProp.TrueProp), 1769) + success(CSigmaProp(TrivialProp.TrueProp), 1769, Seq.fill(4)(2021)) ) }, existingFeature( @@ -9184,25 +9314,25 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => Helpers.decodeBytes( "0008ce03c046fccb95549910767d0543f5e8ce41d66ae6a8720a46f4049cac3b3d26dafb023479c9c3b86a0d3c8be3db0a2d186788e9af1db76d55f3dad127d15185d83d0303d7898641cb6653585a8e1dabfa7f665e61e0498963e329e6e3744bd764db2d72037ae057d89ec0b46ff8e9ff4c37e85c12acddb611c3f636421bef1542c11b0441" ) - ), cost = 1771, newDetails(4), expectedNewCost = 1771), + ), cost = 1771, newDetails(4), expectedNewCost = 1771, Seq.fill(4)(2003)), CSigmaProp(pk) -> Expected(Success( Helpers.decodeBytes("0008cd039d0b1e46c21540d033143440d2fb7dd5d650cf89981c99ee53c6e0374d2b1b6f")), - cost = 1769, newDetails(1), expectedNewCost = 1769), + cost = 1769, newDetails(1), expectedNewCost = 1769, Seq.fill(4)(2001)), CSigmaProp(and) -> Expected(Success( Helpers.decodeBytes( "00089602cd039d0b1e46c21540d033143440d2fb7dd5d650cf89981c99ee53c6e0374d2b1b6fce03c046fccb95549910767d0543f5e8ce41d66ae6a8720a46f4049cac3b3d26dafb023479c9c3b86a0d3c8be3db0a2d186788e9af1db76d55f3dad127d15185d83d0303d7898641cb6653585a8e1dabfa7f665e61e0498963e329e6e3744bd764db2d72037ae057d89ec0b46ff8e9ff4c37e85c12acddb611c3f636421bef1542c11b0441" ) - ), cost = 1772, newDetails(6), expectedNewCost = 1772), + ), cost = 1772, newDetails(6), expectedNewCost = 1772, Seq.fill(4)(2004)), CSigmaProp(threshold) -> Expected(Success( Helpers.decodeBytes( "0008980204cd039d0b1e46c21540d033143440d2fb7dd5d650cf89981c99ee53c6e0374d2b1b6fce03c046fccb95549910767d0543f5e8ce41d66ae6a8720a46f4049cac3b3d26dafb023479c9c3b86a0d3c8be3db0a2d186788e9af1db76d55f3dad127d15185d83d0303d7898641cb6653585a8e1dabfa7f665e61e0498963e329e6e3744bd764db2d72037ae057d89ec0b46ff8e9ff4c37e85c12acddb611c3f636421bef1542c11b04419702cd039d0b1e46c21540d033143440d2fb7dd5d650cf89981c99ee53c6e0374d2b1b6fce03c046fccb95549910767d0543f5e8ce41d66ae6a8720a46f4049cac3b3d26dafb023479c9c3b86a0d3c8be3db0a2d186788e9af1db76d55f3dad127d15185d83d0303d7898641cb6653585a8e1dabfa7f665e61e0498963e329e6e3744bd764db2d72037ae057d89ec0b46ff8e9ff4c37e85c12acddb611c3f636421bef1542c11b04419602cd039d0b1e46c21540d033143440d2fb7dd5d650cf89981c99ee53c6e0374d2b1b6fce03c046fccb95549910767d0543f5e8ce41d66ae6a8720a46f4049cac3b3d26dafb023479c9c3b86a0d3c8be3db0a2d186788e9af1db76d55f3dad127d15185d83d0303d7898641cb6653585a8e1dabfa7f665e61e0498963e329e6e3744bd764db2d72037ae057d89ec0b46ff8e9ff4c37e85c12acddb611c3f636421bef1542c11b0441" ) - ), cost = 1780, newDetails(18), expectedNewCost = 1780), + ), cost = 1780, newDetails(18), expectedNewCost = 1780, Seq.fill(4)(2012)), CSigmaProp(data.COR(Array(pk, dht, and, or, threshold))) -> Expected(Success( Helpers.decodeBytes( "00089705cd039d0b1e46c21540d033143440d2fb7dd5d650cf89981c99ee53c6e0374d2b1b6fce03c046fccb95549910767d0543f5e8ce41d66ae6a8720a46f4049cac3b3d26dafb023479c9c3b86a0d3c8be3db0a2d186788e9af1db76d55f3dad127d15185d83d0303d7898641cb6653585a8e1dabfa7f665e61e0498963e329e6e3744bd764db2d72037ae057d89ec0b46ff8e9ff4c37e85c12acddb611c3f636421bef1542c11b04419602cd039d0b1e46c21540d033143440d2fb7dd5d650cf89981c99ee53c6e0374d2b1b6fce03c046fccb95549910767d0543f5e8ce41d66ae6a8720a46f4049cac3b3d26dafb023479c9c3b86a0d3c8be3db0a2d186788e9af1db76d55f3dad127d15185d83d0303d7898641cb6653585a8e1dabfa7f665e61e0498963e329e6e3744bd764db2d72037ae057d89ec0b46ff8e9ff4c37e85c12acddb611c3f636421bef1542c11b04419702cd039d0b1e46c21540d033143440d2fb7dd5d650cf89981c99ee53c6e0374d2b1b6fce03c046fccb95549910767d0543f5e8ce41d66ae6a8720a46f4049cac3b3d26dafb023479c9c3b86a0d3c8be3db0a2d186788e9af1db76d55f3dad127d15185d83d0303d7898641cb6653585a8e1dabfa7f665e61e0498963e329e6e3744bd764db2d72037ae057d89ec0b46ff8e9ff4c37e85c12acddb611c3f636421bef1542c11b0441980204cd039d0b1e46c21540d033143440d2fb7dd5d650cf89981c99ee53c6e0374d2b1b6fce03c046fccb95549910767d0543f5e8ce41d66ae6a8720a46f4049cac3b3d26dafb023479c9c3b86a0d3c8be3db0a2d186788e9af1db76d55f3dad127d15185d83d0303d7898641cb6653585a8e1dabfa7f665e61e0498963e329e6e3744bd764db2d72037ae057d89ec0b46ff8e9ff4c37e85c12acddb611c3f636421bef1542c11b04419702cd039d0b1e46c21540d033143440d2fb7dd5d650cf89981c99ee53c6e0374d2b1b6fce03c046fccb95549910767d0543f5e8ce41d66ae6a8720a46f4049cac3b3d26dafb023479c9c3b86a0d3c8be3db0a2d186788e9af1db76d55f3dad127d15185d83d0303d7898641cb6653585a8e1dabfa7f665e61e0498963e329e6e3744bd764db2d72037ae057d89ec0b46ff8e9ff4c37e85c12acddb611c3f636421bef1542c11b04419602cd039d0b1e46c21540d033143440d2fb7dd5d650cf89981c99ee53c6e0374d2b1b6fce03c046fccb95549910767d0543f5e8ce41d66ae6a8720a46f4049cac3b3d26dafb023479c9c3b86a0d3c8be3db0a2d186788e9af1db76d55f3dad127d15185d83d0303d7898641cb6653585a8e1dabfa7f665e61e0498963e329e6e3744bd764db2d72037ae057d89ec0b46ff8e9ff4c37e85c12acddb611c3f636421bef1542c11b0441" ) - ), cost = 1791, newDetails(36), expectedNewCost = 1791) + ), cost = 1791, newDetails(36), expectedNewCost = 1791, Seq.fill(4)(2023)) ) }, existingFeature((x: SigmaProp) => x.propBytes, @@ -9213,19 +9343,20 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => property("allOf equivalence") { def costDetails(i: Int) = TracedCost(traceBase :+ ast.SeqCostItem(CompanionDesc(AND), PerItemCost(JitCost(10), JitCost(5), 32), i)) + val v3Costs = Seq.fill(4)(1997) verifyCases( Seq( - (Coll[Boolean]() -> Expected(Success(true), 1765, costDetails(0), 1765)), - (Coll[Boolean](true) -> Expected(Success(true), 1765, costDetails(1), 1765)), - (Coll[Boolean](false) -> Expected(Success(false), 1765, costDetails(1), 1765)), - (Coll[Boolean](false, false) -> Expected(Success(false), 1765, costDetails(1), 1765)), - (Coll[Boolean](false, true) -> Expected(Success(false), 1765, costDetails(1), 1765)), - (Coll[Boolean](true, false) -> Expected(Success(false), 1765, costDetails(2), 1765)), - (Coll[Boolean](true, true) -> Expected(Success(true), 1765, costDetails(2), 1765)), - (Coll[Boolean](true, false, false) -> Expected(Success(false), 1765, costDetails(2), 1765)), - (Coll[Boolean](true, false, true) -> Expected(Success(false), 1765, costDetails(2), 1765)), - (Coll[Boolean](true, true, false) -> Expected(Success(false), 1765, costDetails(3), 1765)), - (Coll[Boolean](true, true, true) -> Expected(Success(true), 1765, costDetails(3), 1765)) + (Coll[Boolean]() -> Expected(Success(true), 1765, costDetails(0), 1765, v3Costs)), + (Coll[Boolean](true) -> Expected(Success(true), 1765, costDetails(1), 1765, v3Costs)), + (Coll[Boolean](false) -> Expected(Success(false), 1765, costDetails(1), 1765, v3Costs)), + (Coll[Boolean](false, false) -> Expected(Success(false), 1765, costDetails(1), 1765, v3Costs)), + (Coll[Boolean](false, true) -> Expected(Success(false), 1765, costDetails(1), 1765, v3Costs)), + (Coll[Boolean](true, false) -> Expected(Success(false), 1765, costDetails(2), 1765, v3Costs)), + (Coll[Boolean](true, true) -> Expected(Success(true), 1765, costDetails(2), 1765, v3Costs)), + (Coll[Boolean](true, false, false) -> Expected(Success(false), 1765, costDetails(2), 1765, v3Costs)), + (Coll[Boolean](true, false, true) -> Expected(Success(false), 1765, costDetails(2), 1765, v3Costs)), + (Coll[Boolean](true, true, false) -> Expected(Success(false), 1765, costDetails(3), 1765, v3Costs)), + (Coll[Boolean](true, true, true) -> Expected(Success(true), 1765, costDetails(3), 1765, v3Costs)) ), existingFeature((x: Coll[Boolean]) => SigmaDsl.allOf(x), "{ (x: Coll[Boolean]) => allOf(x) }", @@ -9234,19 +9365,20 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => property("anyOf equivalence") { def costDetails(i: Int) = TracedCost(traceBase :+ ast.SeqCostItem(CompanionDesc(OR), PerItemCost(JitCost(5), JitCost(5), 64), i)) + val v3Costs = Seq.fill(4)(1996) verifyCases( Seq( - (Coll[Boolean]() -> Expected(Success(false), 1764, costDetails(0), 1764)), - (Coll[Boolean](true) -> Expected(Success(true), 1764, costDetails(1), 1764)), - (Coll[Boolean](false) -> Expected(Success(false), 1764, costDetails(1), 1764)), - (Coll[Boolean](false, false) -> Expected(Success(false), 1764, costDetails(2), 1764)), - (Coll[Boolean](false, true) -> Expected(Success(true), 1764, costDetails(2), 1764)), - (Coll[Boolean](true, false) -> Expected(Success(true), 1764, costDetails(1), 1764)), - (Coll[Boolean](true, true) -> Expected(Success(true), 1764, costDetails(1), 1764)), - (Coll[Boolean](true, false, false) -> Expected(Success(true), 1764, costDetails(1), 1764)), - (Coll[Boolean](true, false, true) -> Expected(Success(true), 1764, costDetails(1), 1764)), - (Coll[Boolean](true, true, false) -> Expected(Success(true), 1764, costDetails(1), 1764)), - (Coll[Boolean](true, true, true) -> Expected(Success(true), 1764, costDetails(1), 1764)) + (Coll[Boolean]() -> Expected(Success(false), 1764, costDetails(0), 1764, v3Costs)), + (Coll[Boolean](true) -> Expected(Success(true), 1764, costDetails(1), 1764, v3Costs)), + (Coll[Boolean](false) -> Expected(Success(false), 1764, costDetails(1), 1764, v3Costs)), + (Coll[Boolean](false, false) -> Expected(Success(false), 1764, costDetails(2), 1764, v3Costs)), + (Coll[Boolean](false, true) -> Expected(Success(true), 1764, costDetails(2), 1764, v3Costs)), + (Coll[Boolean](true, false) -> Expected(Success(true), 1764, costDetails(1), 1764, v3Costs)), + (Coll[Boolean](true, true) -> Expected(Success(true), 1764, costDetails(1), 1764, v3Costs)), + (Coll[Boolean](true, false, false) -> Expected(Success(true), 1764, costDetails(1), 1764, v3Costs)), + (Coll[Boolean](true, false, true) -> Expected(Success(true), 1764, costDetails(1), 1764, v3Costs)), + (Coll[Boolean](true, true, false) -> Expected(Success(true), 1764, costDetails(1), 1764, v3Costs)), + (Coll[Boolean](true, true, true) -> Expected(Success(true), 1764, costDetails(1), 1764, v3Costs)) ), existingFeature((x: Coll[Boolean]) => SigmaDsl.anyOf(x), "{ (x: Coll[Boolean]) => anyOf(x) }", @@ -9259,10 +9391,11 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => Seq( (Helpers.decodeGroupElement("02288f0e55610c3355c89ed6c5de43cf20da145b8c54f03a29f481e540d94e9a69") -> Expected(Success( - CSigmaProp(ProveDlog(Helpers.decodeECPoint("02288f0e55610c3355c89ed6c5de43cf20da145b8c54f03a29f481e540d94e9a69")))), - cost = 1782, - costDetails, - 1782)) + CSigmaProp(ProveDlog(Helpers.decodeECPoint("02288f0e55610c3355c89ed6c5de43cf20da145b8c54f03a29f481e540d94e9a69")))), + cost = 1782, + costDetails, + 1782, + Seq.fill(4)(2014))) ), existingFeature({ (x: GroupElement) => SigmaDsl.proveDlog(x) }, "{ (x: GroupElement) => proveDlog(x) }", @@ -9282,18 +9415,19 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => Seq( (Helpers.decodeGroupElement("039c15221a318d27c186eba84fa8d986c1f63bbd9f8060380c9bfc2ef455d8346a") -> Expected(Success( - CSigmaProp( - ProveDHTuple( - Helpers.decodeECPoint("039c15221a318d27c186eba84fa8d986c1f63bbd9f8060380c9bfc2ef455d8346a"), - Helpers.decodeECPoint("039c15221a318d27c186eba84fa8d986c1f63bbd9f8060380c9bfc2ef455d8346a"), - Helpers.decodeECPoint("039c15221a318d27c186eba84fa8d986c1f63bbd9f8060380c9bfc2ef455d8346a"), - Helpers.decodeECPoint("039c15221a318d27c186eba84fa8d986c1f63bbd9f8060380c9bfc2ef455d8346a") - ) - )), - cost = 1836, - costDetails, - 1836 - )) + CSigmaProp( + ProveDHTuple( + Helpers.decodeECPoint("039c15221a318d27c186eba84fa8d986c1f63bbd9f8060380c9bfc2ef455d8346a"), + Helpers.decodeECPoint("039c15221a318d27c186eba84fa8d986c1f63bbd9f8060380c9bfc2ef455d8346a"), + Helpers.decodeECPoint("039c15221a318d27c186eba84fa8d986c1f63bbd9f8060380c9bfc2ef455d8346a"), + Helpers.decodeECPoint("039c15221a318d27c186eba84fa8d986c1f63bbd9f8060380c9bfc2ef455d8346a") + ) + )), + cost = 1836, + costDetails, + 1836, + Seq.fill(4)(2080) + )) ), existingFeature({ (x: GroupElement) => SigmaDsl.proveDHTuple(x, x, x, x) }, "{ (x: GroupElement) => proveDHTuple(x, x, x, x) }", @@ -9334,7 +9468,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => ) verifyCases( { - def success[T](v: T, cd: CostDetails, cost: Int) = Expected(Success(v), cost, cd, cost) + def success[T](v: T, cd: CostDetails, cost: Int, expectedV3Costs: Seq[Int]) = Expected(Success(v), cost, cd, cost, expectedV3Costs) Seq( (Helpers.decodeBytes(""), 0) -> Expected(new java.nio.BufferUnderflowException()), @@ -9346,8 +9480,16 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => expectedDetails = CostDetails.ZeroCost, newCost = 1783, newVersionedResults = { - val res = (ExpectedResult(Success(Helpers.decodeBytes("0008d3")), Some(1783)) -> Some(costDetails(0))) - Seq(0, 1, 2, 3).map(version => version -> res) + val costs = if (activatedVersionInTests >= V6SoftForkVersion) { + Seq.fill(4)(2055) + } + else { + Seq.fill(4)(1783) + } + Seq(0, 1, 2, 3).map({ version => + val res = (ExpectedResult(Success(Helpers.decodeBytes("0008d3")), Some(costs(version))) -> Some(costDetails(0))) + version -> res + }) }), (Helpers.decodeBytes("000008d3"), 0) -> Expected( @@ -9356,21 +9498,30 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => expectedDetails = CostDetails.ZeroCost, newCost = 1783, newVersionedResults = { - // since the tree without constant segregation, substitution has no effect - val res = (ExpectedResult(Success(Helpers.decodeBytes("000008d3")), Some(1783)) -> Some(costDetails(0))) - Seq(0, 1, 2, 3).map(version => version -> res) + val costs = if (activatedVersionInTests >= V6SoftForkVersion) { + Seq.fill(4)(2055) + } + else { + Seq.fill(4)(1783) + } + Seq(0, 1, 2, 3).map({ version => + // since the tree without constant segregation, substitution has no effect + val res = (ExpectedResult(Success(Helpers.decodeBytes("000008d3")), Some(costs(version))) -> Some(costDetails(0))) + version -> res + }) }), // tree with segregation flag, empty constants array - (Coll(t2.bytes:_*), 0) -> success(Helpers.decodeBytes("100008d3"), costDetails(0), 1783), - (Helpers.decodeBytes("100008d3"), 0) -> success(Helpers.decodeBytes("100008d3"), costDetails(0), 1783), + (Coll(t2.bytes: _*), 0) -> success(Helpers.decodeBytes("100008d3"), costDetails(0), 1783, Seq.fill(4)(2055)), + (Helpers.decodeBytes("100008d3"), 0) -> success(Helpers.decodeBytes("100008d3"), costDetails(0), 1783, Seq.fill(4)(2055)), // tree with one segregated constant - (Coll(t3.bytes:_*), 0) -> success(Helpers.decodeBytes("100108d27300"), costDetails(1), 1793), - (Helpers.decodeBytes("100108d37300"), 0) -> success(Helpers.decodeBytes("100108d27300"), costDetails(1), 1793), - (Coll(t3.bytes:_*), 1) -> success(Helpers.decodeBytes("100108d37300"), costDetails(1), 1793), - (Coll(t4.bytes:_*), 0) -> Expected(new IllegalArgumentException("requirement failed: expected new constant to have the same SInt$ tpe, got SSigmaProp")) + (Coll(t3.bytes: _*), 0) -> success(Helpers.decodeBytes("100108d27300"), costDetails(1), 1793, Seq.fill(4)(2065)), + (Helpers.decodeBytes("100108d37300"), 0) -> success(Helpers.decodeBytes("100108d27300"), costDetails(1), 1793, Seq.fill(4)(2065)), + (Coll(t3.bytes: _*), 1) -> success(Helpers.decodeBytes("100108d37300"), costDetails(1), 1793, Seq.fill(4)(2065)), + (Coll(t4.bytes: _*), 0) -> Expected(new IllegalArgumentException("requirement failed: expected new constant to have the same SInt$ tpe, got SSigmaProp")) ) }, changedFeature( + changedInVersion = VersionContext.JitActivationVersion, { (x: (Coll[Byte], Int)) => SigmaDsl.substConstants(x._1, Coll[Int](x._2), Coll[Any](SigmaDsl.sigmaProp(false))(sigma.AnyType)) }, @@ -9422,6 +9573,12 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => if (lowerMethodCallsInTests) { val error = new RuntimeException("any exception") + val costs = if (activatedVersionInTests >= V6SoftForkVersion) { + Seq.fill(4)(2144) + } + else { + Seq.fill(4)(1776) + } verifyCases( Seq( ctx -> Expected( @@ -9429,107 +9586,110 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => cost = 1776, expectedDetails = CostDetails.ZeroCost, newCost = 1776, - newVersionedResults = Seq(0, 1, 2, 3).map(i => i -> (ExpectedResult(Success(true), Some(1776)) -> Some(costDetails))) + newVersionedResults = (0 to 3).map({ i => + i -> (ExpectedResult(Success(true), Some(costs(i))) -> Some(costDetails)) + }) ) ), changedFeature( - { (x: Context) => - throw error - true - }, - { (x: Context) => - val headers = x.headers - val ids = headers.map({ (h: Header) => h.id }) - val parentIds = headers.map({ (h: Header) => h.parentId }) - headers.indices.slice(0, headers.size - 1).forall({ (i: Int) => - val parentId = parentIds(i) - val id = ids(i + 1) - parentId == id - }) - }, - """{ - |(x: Context) => - | val headers = x.headers - | val ids = headers.map({(h: Header) => h.id }) - | val parentIds = headers.map({(h: Header) => h.parentId }) - | headers.indices.slice(0, headers.size - 1).forall({ (i: Int) => - | val parentId = parentIds(i) - | val id = ids(i + 1) - | parentId == id - | }) - |}""".stripMargin, - FuncValue( - Array((1, SContext)), - BlockValue( - Array( - ValDef( - 3, - List(), - MethodCall.typed[Value[SCollection[SHeader.type]]]( - ValUse(1, SContext), - SContextMethods.getMethodByName("headers"), - Vector(), - Map() - ) - ) - ), - ForAll( - Slice( - MethodCall.typed[Value[SCollection[SInt.type]]]( - ValUse(3, SCollectionType(SHeader)), - SCollectionMethods.getMethodByName("indices").withConcreteTypes(Map(STypeVar("IV") -> SHeader)), - Vector(), - Map() - ), - IntConstant(0), - ArithOp( - SizeOf(ValUse(3, SCollectionType(SHeader))), - IntConstant(1), - OpCode @@ (-103.toByte) + changedInVersion = VersionContext.JitActivationVersion, + { (x: Context) => + throw error + true + }, + { (x: Context) => + val headers = x.headers + val ids = headers.map({ (h: Header) => h.id }) + val parentIds = headers.map({ (h: Header) => h.parentId }) + headers.indices.slice(0, headers.size - 1).forall({ (i: Int) => + val parentId = parentIds(i) + val id = ids(i + 1) + parentId == id + }) + }, + """{ + |(x: Context) => + | val headers = x.headers + | val ids = headers.map({(h: Header) => h.id }) + | val parentIds = headers.map({(h: Header) => h.parentId }) + | headers.indices.slice(0, headers.size - 1).forall({ (i: Int) => + | val parentId = parentIds(i) + | val id = ids(i + 1) + | parentId == id + | }) + |}""".stripMargin, + FuncValue( + Array((1, SContext)), + BlockValue( + Array( + ValDef( + 3, + List(), + MethodCall.typed[Value[SCollection[SHeader.type]]]( + ValUse(1, SContext), + SContextMethods.getMethodByName("headers"), + Vector(), + Map() + ) ) ), - FuncValue( - Array((4, SInt)), - EQ( - ByIndex( - MapCollection( - ValUse(3, SCollectionType(SHeader)), - FuncValue( - Array((6, SHeader)), - MethodCall.typed[Value[SCollection[SByte.type]]]( - ValUse(6, SHeader), - SHeaderMethods.getMethodByName("parentId"), - Vector(), - Map() - ) - ) - ), - ValUse(4, SInt), - None + ForAll( + Slice( + MethodCall.typed[Value[SCollection[SInt.type]]]( + ValUse(3, SCollectionType(SHeader)), + SCollectionMethods.getMethodByName("indices").withConcreteTypes(Map(STypeVar("IV") -> SHeader)), + Vector(), + Map() ), - ByIndex( - MapCollection( - ValUse(3, SCollectionType(SHeader)), - FuncValue( - Array((6, SHeader)), - MethodCall.typed[Value[SCollection[SByte.type]]]( - ValUse(6, SHeader), - SHeaderMethods.getMethodByName("id"), - Vector(), - Map() + IntConstant(0), + ArithOp( + SizeOf(ValUse(3, SCollectionType(SHeader))), + IntConstant(1), + OpCode @@ (-103.toByte) + ) + ), + FuncValue( + Array((4, SInt)), + EQ( + ByIndex( + MapCollection( + ValUse(3, SCollectionType(SHeader)), + FuncValue( + Array((6, SHeader)), + MethodCall.typed[Value[SCollection[SByte.type]]]( + ValUse(6, SHeader), + SHeaderMethods.getMethodByName("parentId"), + Vector(), + Map() + ) ) - ) + ), + ValUse(4, SInt), + None ), - ArithOp(ValUse(4, SInt), IntConstant(1), OpCode @@ (-102.toByte)), - None + ByIndex( + MapCollection( + ValUse(3, SCollectionType(SHeader)), + FuncValue( + Array((6, SHeader)), + MethodCall.typed[Value[SCollection[SByte.type]]]( + ValUse(6, SHeader), + SHeaderMethods.getMethodByName("id"), + Vector(), + Map() + ) + ) + ), + ArithOp(ValUse(4, SInt), IntConstant(1), OpCode @@ (-102.toByte)), + None + ) ) ) ) ) - ) - ), - allowDifferentErrors = true, - allowNewToSucceed = true + ), + allowDifferentErrors = true, + allowNewToSucceed = true ), preGeneratedSamples = Some(ArraySeq.empty) ) @@ -9540,8 +9700,8 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => property("nested loops: map inside fold") { val keys = Colls.fromArray(Array(Coll[Byte](1, 2, 3, 4, 5))) val initial = Coll[Byte](0, 0, 0, 0, 0) - val cases = Seq( - (keys, initial) -> Expected(Success(Coll[Byte](1, 2, 3, 4, 5)), cost = 1801, expectedDetails = CostDetails.ZeroCost, 1801) + val cases = Seq( + (keys, initial) -> Expected(Success(Coll[Byte](1, 2, 3, 4, 5)), cost = 1801, expectedDetails = CostDetails.ZeroCost, 1801, Seq.fill(4)(2119)) ) val scalaFunc = { (x: (Coll[Coll[Byte]], Coll[Byte])) => x._1.foldLeft(x._2, { (a: (Coll[Byte], Coll[Byte])) => diff --git a/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala b/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala index e4ae10cac6..0b9e1eb4de 100644 --- a/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala +++ b/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala @@ -1,10 +1,14 @@ package sigma -import sigma.ast.{Apply, Downcast, FixedCost, FixedCostItem, FuncValue, GetVar, Global, JitCost, MethodCall, NamedDesc, OptionGet, SBigInt, SByte, SGlobalMethods, SInt, SLong, SShort, STypeVar, ValUse} +import sigma.ast.ErgoTree.ZeroHeader +import sigma.ast.SCollection.SByteArray +import sigma.ast.syntax.TrueSigmaProp +import sigma.ast._ import sigma.data.{CBigInt, ExactNumeric, RType} -import sigma.eval.{SigmaDsl, TracedCost} +import sigma.eval.{CostDetails, SigmaDsl, TracedCost} import sigma.util.Extensions.{BooleanOps, ByteOps, IntOps, LongOps} import sigmastate.exceptions.MethodNotFound +import sigmastate.utils.Helpers import java.math.BigInteger import scala.util.Success @@ -234,21 +238,26 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite => } property("BigInt methods equivalence (new features)") { - // TODO v6.0: the behavior of `upcast` for BigInt is different from all other Numeric types (see https://github.com/ScorexFoundation/sigmastate-interpreter/issues/877) - // The `Upcast(bigInt, SBigInt)` node is never produced by ErgoScript compiler, but is still valid ErgoTree. - // It makes sense to fix this inconsistency as part of upcoming forks - assertExceptionThrown( - SBigInt.upcast(CBigInt(new BigInteger("0", 16)).asInstanceOf[AnyVal]), - _.getMessage.contains("Cannot upcast value") - ) + if (activatedVersionInTests < VersionContext.V6SoftForkVersion) { + // The `Upcast(bigInt, SBigInt)` node is never produced by ErgoScript compiler, but is still valid ErgoTree. + // Fixed in 6.0 + assertExceptionThrown( + SBigInt.upcast(CBigInt(new BigInteger("0", 16)).asInstanceOf[AnyVal]), + _.getMessage.contains("Cannot upcast value") + ) - // TODO v6.0: the behavior of `downcast` for BigInt is different from all other Numeric types (see https://github.com/ScorexFoundation/sigmastate-interpreter/issues/877) - // The `Downcast(bigInt, SBigInt)` node is never produced by ErgoScript compiler, but is still valid ErgoTree. - // It makes sense to fix this inconsistency as part of HF - assertExceptionThrown( - SBigInt.downcast(CBigInt(new BigInteger("0", 16)).asInstanceOf[AnyVal]), - _.getMessage.contains("Cannot downcast value") - ) + // The `Downcast(bigInt, SBigInt)` node is never produced by ErgoScript compiler, but is still valid ErgoTree. + // Fixed in 6.0 + assertExceptionThrown( + SBigInt.downcast(CBigInt(new BigInteger("0", 16)).asInstanceOf[AnyVal]), + _.getMessage.contains("Cannot downcast value") + ) + } else { + forAll { x: BigInteger => + SBigInt.upcast(CBigInt(x).asInstanceOf[AnyVal]) shouldBe CBigInt(x) + SBigInt.downcast(CBigInt(x).asInstanceOf[AnyVal]) shouldBe CBigInt(x) + } + } if (activatedVersionInTests < VersionContext.V6SoftForkVersion) { // NOTE, for such versions the new features are not supported @@ -287,6 +296,44 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite => forAll { x: (BigInt, BigInt) => Seq(compareTo, bitOr, bitAnd).foreach(_.checkEquality(x)) } + + forAll { x: Long => + assertExceptionThrown( + SLong.downcast(CBigInt(new BigInteger(x.toString)).asInstanceOf[AnyVal]), + _.getMessage.contains("Cannot downcast value") + ) + } + forAll { x: Int => + assertExceptionThrown( + SInt.downcast(CBigInt(new BigInteger(x.toString)).asInstanceOf[AnyVal]), + _.getMessage.contains("Cannot downcast value") + ) + } + forAll { x: Byte => + assertExceptionThrown( + SByte.downcast(CBigInt(new BigInteger(x.toString)).asInstanceOf[AnyVal]), + _.getMessage.contains("Cannot downcast value") + ) + } + forAll { x: Short => + assertExceptionThrown( + SShort.downcast(CBigInt(new BigInteger(x.toString)).asInstanceOf[AnyVal]), + _.getMessage.contains("Cannot downcast value") + ) + } + } else { + forAll { x: Long => + SLong.downcast(CBigInt(new BigInteger(x.toString)).asInstanceOf[AnyVal]) shouldBe x + } + forAll { x: Int => + SInt.downcast(CBigInt(new BigInteger(x.toString)).asInstanceOf[AnyVal]) shouldBe x + } + forAll { x: Byte => + SByte.downcast(CBigInt(new BigInteger(x.toString)).asInstanceOf[AnyVal]) shouldBe x + } + forAll { x: Short => + SShort.downcast(CBigInt(new BigInteger(x.toString)).asInstanceOf[AnyVal]) shouldBe x + } } } @@ -406,5 +453,87 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite => } } + property("Fix substConstants in v6.0 for ErgoTree version > 0") { + // tree with one segregated constant and v0 + val t1 = ErgoTree( + header = ErgoTree.setConstantSegregation(ZeroHeader), + constants = Vector(TrueSigmaProp), + ConstantPlaceholder(0, SSigmaProp)) + + // tree with one segregated constant and max supported version + val t2 = ErgoTree( + header = ErgoTree.setConstantSegregation( + ErgoTree.headerWithVersion(ZeroHeader, VersionContext.MaxSupportedScriptVersion) + ), + Vector(TrueSigmaProp), + ConstantPlaceholder(0, SSigmaProp)) + + def costDetails(nItems: Int) = TracedCost( + traceBase ++ Array( + FixedCostItem(SelectField), + FixedCostItem(ConcreteCollection), + FixedCostItem(ValUse), + FixedCostItem(SelectField), + FixedCostItem(ConcreteCollection), + FixedCostItem(Constant), + FixedCostItem(BoolToSigmaProp), + ast.SeqCostItem(CompanionDesc(SubstConstants), PerItemCost(JitCost(100), JitCost(100), 1), nItems) + ) + ) + + val expectedTreeBytes_beforeV6 = Helpers.decodeBytes("1b0108d27300") + val expectedTreeBytes_V6 = Helpers.decodeBytes("1b050108d27300") + + verifyCases( + Seq( + // for tree v0, the result is the same for all versions + (Coll(t1.bytes: _*), 0) -> Expected( + Success(Helpers.decodeBytes("100108d27300")), + cost = 1793, + expectedDetails = CostDetails.ZeroCost, + newCost = 2065, + newVersionedResults = expectedSuccessForAllTreeVersions(Helpers.decodeBytes("100108d27300"), 2065, costDetails(1)) + ), + // for tree version > 0, the result depend on activated version + (Coll(t2.bytes: _*), 0) -> Expected( + Success(expectedTreeBytes_beforeV6), + cost = 1793, + expectedDetails = CostDetails.ZeroCost, + newCost = 2065, + newVersionedResults = expectedSuccessForAllTreeVersions(expectedTreeBytes_V6, 2065, costDetails(1))) + ), + changedFeature( + changedInVersion = VersionContext.V6SoftForkVersion, + { (x: (Coll[Byte], Int)) => + SigmaDsl.substConstants(x._1, Coll[Int](x._2), Coll[Any](SigmaDsl.sigmaProp(false))(sigma.AnyType)) + }, + { (x: (Coll[Byte], Int)) => + SigmaDsl.substConstants(x._1, Coll[Int](x._2), Coll[Any](SigmaDsl.sigmaProp(false))(sigma.AnyType)) + }, + "{ (x: (Coll[Byte], Int)) => substConstants[Any](x._1, Coll[Int](x._2), Coll[Any](sigmaProp(false))) }", + FuncValue( + Vector((1, SPair(SByteArray, SInt))), + SubstConstants( + SelectField.typed[Value[SCollection[SByte.type]]](ValUse(1, SPair(SByteArray, SInt)), 1.toByte), + ConcreteCollection( + Array(SelectField.typed[Value[SInt.type]](ValUse(1, SPair(SByteArray, SInt)), 2.toByte)), + SInt + ), + ConcreteCollection(Array(BoolToSigmaProp(FalseLeaf)), SSigmaProp) + ) + ) + ) + ) + + // before v6.0 the expected tree is not parsable + ErgoTree.fromBytes(expectedTreeBytes_beforeV6.toArray).isRightParsed shouldBe false + + // in v6.0 the expected tree should be parsable and similar to the original tree + val tree = ErgoTree.fromBytes(expectedTreeBytes_V6.toArray) + tree.isRightParsed shouldBe true + tree.header shouldBe t2.header + tree.constants.length shouldBe t2.constants.length + tree.root shouldBe t2.root + } } diff --git a/sc/shared/src/test/scala/sigma/SigmaDslTesting.scala b/sc/shared/src/test/scala/sigma/SigmaDslTesting.scala index 37fb0e6503..b2446b6795 100644 --- a/sc/shared/src/test/scala/sigma/SigmaDslTesting.scala +++ b/sc/shared/src/test/scala/sigma/SigmaDslTesting.scala @@ -14,6 +14,7 @@ import org.scalatestplus.scalacheck.ScalaCheckPropertyChecks import scalan.Platform.threadSleepOrNoOp import sigma.Extensions.ArrayOps import sigma.data.{CBox, CollType, OptionType, PairType, ProveDlog, RType, SigmaLeaf} +import sigma.VersionContext.V6SoftForkVersion import sigma.util.BenchmarkUtil import sigma.util.CollectionUtil._ import sigma.util.Extensions._ @@ -126,6 +127,9 @@ class SigmaDslTesting extends AnyPropSpec /** Checks if this feature is supported in the given version context. */ def isSupportedIn(vc: VersionContext): Boolean + /** Version in which the feature is first implemented of changed. */ + def sinceVersion: Byte + /** Script containing this feature. */ def script: String @@ -362,14 +366,16 @@ class SigmaDslTesting extends AnyPropSpec // Compile script the same way it is performed by applications (i.e. via Ergo Appkit) val prop = compile(env, code)(IR).asSigmaProp - // Add additional oparations which are not yet implemented in ErgoScript compiler + // Add additional operations which are not yet implemented in ErgoScript compiler val multisig = AtLeast( IntConstant(2), Array( pkAlice, DeserializeRegister(ErgoBox.R5, SSigmaProp), // deserialize pkBob DeserializeContext(2, SSigmaProp))) // deserialize pkCarol - val header = ErgoTree.headerWithVersion(ZeroHeader, ergoTreeVersionInTests) + // We set size for trees v0 as well, to have the same size and so the same cost in V6 interpreter + // (where tree size is accounted in cost) + val header = ErgoTree.setSizeBit(ErgoTree.headerWithVersion(ZeroHeader, ergoTreeVersionInTests)) ErgoTree.withSegregation(header, SigmaOr(prop, multisig)) } @@ -433,7 +439,7 @@ class SigmaDslTesting extends AnyPropSpec ctx } - val (expectedResult, expectedCost) = if (activatedVersionInTests < VersionContext.JitActivationVersion) + val (expectedResult, expectedCost) = if (activatedVersionInTests < sinceVersion) (expected.oldResult, expected.verificationCostOpt) else { val res = expected.newResults(ergoTreeVersionInTests) @@ -492,7 +498,7 @@ class SigmaDslTesting extends AnyPropSpec val verificationCost = cost.toIntExact if (expectedCost.isDefined) { assertResult(expectedCost.get, - s"Actual verify() cost $cost != expected ${expectedCost.get}")(verificationCost) + s"Actual verify() cost $cost != expected ${expectedCost.get} (version: ${VersionContext.current.activatedVersion})")(verificationCost) } case Failure(t) => throw t @@ -540,6 +546,8 @@ class SigmaDslTesting extends AnyPropSpec implicit val cs = compilerSettingsInTests + override def sinceVersion: Byte = 0 + override def isSupportedIn(vc: VersionContext): Boolean = true /** in v5.x the old and the new interpreters are the same */ @@ -652,16 +660,35 @@ class SigmaDslTesting extends AnyPropSpec checkResult(funcRes.map(_._1), expected.value, failOnTestVectors, "ExistingFeature#verifyCase: ") - checkResultAgainstExpected(funcRes, expected) + val newRes = expected.newResults(ergoTreeVersionInTests) + val expectedTrace = newRes._2.fold(Seq.empty[CostItem])(_.trace) + if (expectedTrace.isEmpty) { + // new cost expectation is missing, print out actual cost results + if (evalSettings.printTestVectors) { + funcRes.foreach { case (_, newDetails) => + printCostDetails(script, newDetails) + } + } + } + else { + // new cost expectation is specified, compare it with the actual result + funcRes.foreach { case (_, newDetails) => + if (newDetails.trace != expectedTrace) { + printCostDetails(script, newDetails) + newDetails.trace shouldBe expectedTrace + } + } + } + checkVerify(input, expected) } - } - /** Descriptor of a language feature which is changed in v5.0. + /** Descriptor of a language feature which is changed in the specified version. * * @tparam A type of an input test data * @tparam B type of an output of the feature function + * @param changedInVersion version in which the feature behaviour is changed * @param script script of the feature function (see Feature trait) * @param scalaFunc feature function written in Scala and used to simulate the behavior * of the script @@ -681,6 +708,7 @@ class SigmaDslTesting extends AnyPropSpec * @param allowDifferentErrors if true, allow v4.x and v5.0 to fail with different error */ case class ChangedFeature[A, B]( + changedInVersion: Byte, script: String, scalaFunc: A => B, override val scalaFuncNew: A => B, @@ -694,6 +722,8 @@ class SigmaDslTesting extends AnyPropSpec implicit val cs = compilerSettingsInTests + override def sinceVersion: Byte = changedInVersion + override def isSupportedIn(vc: VersionContext): Boolean = true /** Apply given function to the context variable 1 */ @@ -773,7 +803,7 @@ class SigmaDslTesting extends AnyPropSpec checkEq(scalaFuncNew)(newF)(input) } - if (!VersionContext.current.isJitActivated) { + if (VersionContext.current.activatedVersion < changedInVersion) { // check the old implementation with Scala semantic val expectedOldRes = expected.value @@ -1035,6 +1065,30 @@ class SigmaDslTesting extends AnyPropSpec } } + /** Used when the old and new value and costs are the same for all versions, but Version 3 (Ergo 6.0) will have a different cost due to deserialization cost being added. + * Different versions of ErgoTree can have different deserialization costs as well + * + * @param value expected result of tested function + * @param cost expected verification cost + * @param expectedDetails expected cost details for all versions <= V3 + * @param expectedNewCost expected new verification cost for all versions <= V3 + * @param expectedV3Cost expected cost for >=V3 + */ + def apply[A](value: Try[A], + cost: Int, + expectedDetails: CostDetails, + expectedNewCost: Int, + expectedV3Costs: Seq[Int] + )(implicit dummy: DummyImplicit): Expected[A] = + new Expected(ExpectedResult(value, Some(cost))) { + override val newResults = defaultNewResults.zipWithIndex.map { + case ((ExpectedResult(v, _), _), version) => { + var cost = if (activatedVersionInTests >= V6SoftForkVersion) expectedV3Costs(version) else expectedNewCost + (ExpectedResult(v, Some(cost)), Some(expectedDetails)) + } + } + } + /** Used when operation semantics changes in new versions. For those versions expected * test vectors can be specified. * @@ -1045,8 +1099,10 @@ class SigmaDslTesting extends AnyPropSpec * @param newVersionedResults new results returned by each changed feature function in * v5.+ for each ErgoTree version. */ - def apply[A](value: Try[A], cost: Int, - expectedDetails: CostDetails, newCost: Int, + def apply[A](value: Try[A], + cost: Int, + expectedDetails: CostDetails, + newCost: Int, newVersionedResults: Seq[(Int, (ExpectedResult[A], Option[CostDetails]))]): Expected[A] = new Expected[A](ExpectedResult(value, Some(cost))) { override val newResults = { @@ -1089,14 +1145,16 @@ class SigmaDslTesting extends AnyPropSpec * various ways */ def changedFeature[A: RType, B: RType] - (scalaFunc: A => B, + (changedInVersion: Byte, + scalaFunc: A => B, scalaFuncNew: A => B, script: String, expectedExpr: SValue = null, allowNewToSucceed: Boolean = false, - allowDifferentErrors: Boolean = false) + allowDifferentErrors: Boolean = false + ) (implicit IR: IRContext, evalSettings: EvalSettings): Feature[A, B] = { - ChangedFeature(script, scalaFunc, scalaFuncNew, Option(expectedExpr), + ChangedFeature(changedInVersion, script, scalaFunc, scalaFuncNew, Option(expectedExpr), allowNewToSucceed = allowNewToSucceed, allowDifferentErrors = allowDifferentErrors) } From 649069b6b10241258c6535bb27dfe181db8158aa Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Mon, 19 Aug 2024 14:24:02 +0300 Subject: [PATCH 214/314] fixed cost, improved args list for SigmaDslBuilder.fromBigEndianBytes --- .../src/main/scala/sigma/SigmaDsl.scala | 3 ++- .../src/main/scala/sigma/ast/methods.scala | 21 ++++++++----------- .../scala/sigma/data/CSigmaDslBuilder.scala | 21 +++++++++---------- .../ir/wrappers/sigma/impl/SigmaDslImpl.scala | 4 +++- .../utxo/BasicOpsSpecification.scala | 1 - 5 files changed, 24 insertions(+), 26 deletions(-) diff --git a/core/shared/src/main/scala/sigma/SigmaDsl.scala b/core/shared/src/main/scala/sigma/SigmaDsl.scala index 18211c7187..eaf21b5007 100644 --- a/core/shared/src/main/scala/sigma/SigmaDsl.scala +++ b/core/shared/src/main/scala/sigma/SigmaDsl.scala @@ -731,6 +731,7 @@ trait SigmaDslBuilder { /** Returns a byte-wise XOR of the two collections of bytes. */ def xor(l: Coll[Byte], r: Coll[Byte]): Coll[Byte] - def fromBigEndianBytes[T](tpe: SType, bytes: Coll[Byte])(implicit cT: RType[T]): T + /** Returns a number decoded from provided big-endian bytes array. */ + def fromBigEndianBytes[T](bytes: Coll[Byte])(implicit cT: RType[T]): T } diff --git a/data/shared/src/main/scala/sigma/ast/methods.scala b/data/shared/src/main/scala/sigma/ast/methods.scala index c1a59fea2c..5e4a1752c9 100644 --- a/data/shared/src/main/scala/sigma/ast/methods.scala +++ b/data/shared/src/main/scala/sigma/ast/methods.scala @@ -1520,19 +1520,16 @@ case object SGlobalMethods extends MonoTypeMethods { Xor.xorWithCosting(ls, rs) } + private val BigEndianBytesCostKind = FixedCost(JitCost(10)) + lazy val fromBigEndianBytesMethod = SMethod( - this, "fromBigEndianBytes", SFunc(Array(SGlobal, SByteArray), tT, Array(paramT)), 30, Xor.costKind, Seq(tT)) // todo: id, cossting - .withIRInfo(MethodCallIrBuilder) - .withInfo(MethodCall, "Multiply this number with \\lst{other} by module Q.", ArgInfo("other", "Number to multiply with this.")) // todo: desc - - def fromBigEndianBytes_eval(mc: MethodCall, G: SigmaDslBuilder, bytes: Coll[Byte]) - (implicit E: ErgoTreeEvaluator): Any = { - val tpe = mc.tpe - val cT = stypeToRType(tpe) - E.addSeqCost(Xor.costKind, bytes.length, Xor.opDesc) { () => // todo: cost - G.fromBigEndianBytes(tpe, bytes)(cT) - } - } + this, "fromBigEndianBytes", SFunc(Array(SGlobal, SByteArray), tT, Array(paramT)), 10, BigEndianBytesCostKind, Seq(tT)) // todo: id + .withIRInfo(MethodCallIrBuilder, + javaMethodOf[SigmaDslBuilder, Coll[Byte], RType[_]]("fromBigEndianBytes"), + { mtype => Array(mtype.tRange) }) + .withInfo(MethodCall, + "Decode a number from big endian bytes.", + ArgInfo("first", "Bytes which are big-endian encoded number.")) private val v5Methods = super.getMethods() ++ Seq( groupGeneratorMethod, diff --git a/data/shared/src/main/scala/sigma/data/CSigmaDslBuilder.scala b/data/shared/src/main/scala/sigma/data/CSigmaDslBuilder.scala index 2e0b3912fc..b74b39c654 100644 --- a/data/shared/src/main/scala/sigma/data/CSigmaDslBuilder.scala +++ b/data/shared/src/main/scala/sigma/data/CSigmaDslBuilder.scala @@ -4,11 +4,11 @@ import debox.cfor import org.ergoplatform.ErgoBox import org.ergoplatform.validation.ValidationRules import scorex.crypto.hash.{Blake2b256, Sha256} -import scorex.utils.{Ints, Longs, Shorts} -import sigma.ast.{AtLeast, SBigInt, SByte, SInt, SLong, SShort, SType, SubstConstants} +import scorex.utils.{Ints, Longs} +import sigma.ast.{AtLeast, SBigInt, SubstConstants} import sigma.crypto.{CryptoConstants, EcPointType, Ecp} import sigma.eval.Extensions.EvalCollOps -import sigma.serialization.{CoreDataSerializer, DataSerializer, GroupElementSerializer, SerializerException, SigmaSerializer} +import sigma.serialization.{GroupElementSerializer, SerializerException, SigmaSerializer} import sigma.util.Extensions.BigIntegerOps import sigma.validation.SigmaValidationSettings import sigma.{AvlTree, BigInt, Box, Coll, CollBuilder, GroupElement, SigmaDslBuilder, SigmaProp, VersionContext} @@ -201,38 +201,37 @@ class CSigmaDslBuilder extends SigmaDslBuilder { dsl => this.GroupElement(p) } - override def fromBigEndianBytes[T](tpe: SType, bytes: Coll[Byte])(implicit cT: RType[T]): T = { - tpe match { - case SByte => if (bytes.length != 1) { + override def fromBigEndianBytes[T](bytes: Coll[Byte])(implicit cT: RType[T]): T = { + cT match { + case sigma.ByteType => if (bytes.length != 1) { throw new IllegalArgumentException("To deserialize SByte with fromBigEndianBytes, exactly one byte should be provided") } else { bytes.apply(0).asInstanceOf[T] } - case SShort => if (bytes.length != 2) { + case sigma.ShortType => if (bytes.length != 2) { throw new IllegalArgumentException("To deserialize SShort with fromBigEndianBytes, exactly two bytes should be provided") } else { val b0 = bytes(0) val b1 = bytes(1) ((b0 & 0xFF) << 8 | (b1 & 0xFF)).toShort.asInstanceOf[T] } - case SInt => if (bytes.length != 4) { + case sigma.IntType => if (bytes.length != 4) { throw new IllegalArgumentException("To deserialize SInt with fromBigEndianBytes, exactly four bytes should be provided") } else { Ints.fromByteArray(bytes.toArray).asInstanceOf[T] } - case SLong => if (bytes.length != 8) { + case sigma.LongType => if (bytes.length != 8) { throw new IllegalArgumentException("To deserialize SLong with fromBigEndianBytes, exactly eight bytes should be provided") } else { Longs.fromByteArray(bytes.toArray).asInstanceOf[T] } - case SBigInt => + case sigma.BigIntRType => if (bytes.length > SBigInt.MaxSizeInBytes) { throw SerializerException(s"BigInt value doesn't not fit into ${SBigInt.MaxSizeInBytes} bytes in fromBigEndianBytes") } CBigInt(new BigInteger(bytes.toArray)).asInstanceOf[T] // todo: UnsignedBitInt case _ => throw new IllegalArgumentException("Unsupported type provided in fromBigEndianBytes") - } } } diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/SigmaDslImpl.scala b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/SigmaDslImpl.scala index ad0450a1a7..c42533993c 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/SigmaDslImpl.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/SigmaDslImpl.scala @@ -2135,7 +2135,9 @@ object SigmaDslBuilder extends EntityObject("SigmaDslBuilder") { override protected def collectMethods: Map[RMethod, MethodDesc] = { super.collectMethods ++ Elem.declaredMethods(RClass(classOf[SigmaDslBuilder]), RClass(classOf[SSigmaDslBuilder]), Set( - "Colls", "verifyZK", "atLeast", "allOf", "allZK", "anyOf", "anyZK", "xorOf", "sigmaProp", "blake2b256", "sha256", "byteArrayToBigInt", "longToByteArray", "byteArrayToLong", "proveDlog", "proveDHTuple", "groupGenerator", "substConstants", "decodePoint", "avlTree", "xor" + "Colls", "verifyZK", "atLeast", "allOf", "allZK", "anyOf", "anyZK", "xorOf", "sigmaProp", "blake2b256", "sha256", + "byteArrayToBigInt", "longToByteArray", "byteArrayToLong", "proveDlog", "proveDHTuple", "groupGenerator", "substConstants", + "decodePoint", "avlTree", "xor", "fromBigEndianBytes" )) } } diff --git a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala index ed97bf3f27..37141585c4 100644 --- a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala @@ -3,7 +3,6 @@ package sigmastate.utxo import org.ergoplatform.ErgoBox.{AdditionalRegisters, R6, R8} import org.ergoplatform._ import scorex.util.encode.Base16 -import scorex.util.encode.Base16 import scorex.utils.Ints import sigma.Extensions.ArrayOps import sigma.VersionContext From bcfb24df6ed5bd95753e9164faa7e17efbddf0e8 Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Mon, 26 Aug 2024 00:36:20 +0300 Subject: [PATCH 215/314] removing unused CSigmaDslBuilder.validationSettings --- data/shared/src/main/scala/sigma/ast/trees.scala | 4 ++-- data/shared/src/main/scala/sigma/data/CSigmaDslBuilder.scala | 3 +-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/data/shared/src/main/scala/sigma/ast/trees.scala b/data/shared/src/main/scala/sigma/ast/trees.scala index 7be73ad55a..33567868fd 100644 --- a/data/shared/src/main/scala/sigma/ast/trees.scala +++ b/data/shared/src/main/scala/sigma/ast/trees.scala @@ -653,7 +653,7 @@ case class SubstConstants[T <: SType](scriptBytes: Value[SByteArray], positions: val (newBytes, nConstants) = SubstConstants.eval( scriptBytes = scriptBytesV.toArray, positions = positionsV.toArray, - newVals = typedNewVals)(SigmaDsl.validationSettings) + newVals = typedNewVals) res = Colls.fromArray(newBytes) nConstants @@ -684,7 +684,7 @@ object SubstConstants extends ValueCompanion { */ def eval(scriptBytes: Array[Byte], positions: Array[Int], - newVals: Array[Constant[SType]])(implicit vs: SigmaValidationSettings): (Array[Byte], Int) = + newVals: Array[Constant[SType]]): (Array[Byte], Int) = ErgoTreeSerializer.DefaultSerializer.substituteConstants(scriptBytes, positions, newVals) } diff --git a/data/shared/src/main/scala/sigma/data/CSigmaDslBuilder.scala b/data/shared/src/main/scala/sigma/data/CSigmaDslBuilder.scala index 4a3842e250..e5bb8920ae 100644 --- a/data/shared/src/main/scala/sigma/data/CSigmaDslBuilder.scala +++ b/data/shared/src/main/scala/sigma/data/CSigmaDslBuilder.scala @@ -20,7 +20,6 @@ import java.math.BigInteger * @see [[SigmaDslBuilder]] for detailed descriptions */ class CSigmaDslBuilder extends SigmaDslBuilder { dsl => - implicit val validationSettings: SigmaValidationSettings = ValidationRules.currentSettings override val Colls: CollBuilder = sigma.Colls @@ -193,7 +192,7 @@ class CSigmaDslBuilder extends SigmaDslBuilder { dsl => case e: Throwable => throw new RuntimeException(s"Cannot evaluate substConstants($scriptBytes, $positions, $newValues)", e) } - val (res, _) = SubstConstants.eval(scriptBytes.toArray, positions.toArray, constants)(validationSettings) + val (res, _) = SubstConstants.eval(scriptBytes.toArray, positions.toArray, constants) Colls.fromArray(res) } From 016262b6b2759529ae3f5f9567548b1191f49f7c Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Tue, 27 Aug 2024 21:26:16 +0300 Subject: [PATCH 216/314] removing unused SNumericTypeMethods.getMethods --- data/shared/src/main/scala/sigma/ast/methods.scala | 8 +++----- .../src/test/scala/sigmastate/ErgoTreeSpecification.scala | 3 --- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/data/shared/src/main/scala/sigma/ast/methods.scala b/data/shared/src/main/scala/sigma/ast/methods.scala index 99459840de..f2481fd879 100644 --- a/data/shared/src/main/scala/sigma/ast/methods.scala +++ b/data/shared/src/main/scala/sigma/ast/methods.scala @@ -186,6 +186,7 @@ trait SNumericTypeMethods extends MonoTypeMethods { } object SNumericTypeMethods extends MethodsContainer { + /** Type for which this container defines methods. */ override def ownerType: STypeCompanion = SNumericType @@ -399,11 +400,8 @@ object SNumericTypeMethods extends MethodsContainer { ) protected override def getMethods(): Seq[SMethod] = { - if (VersionContext.current.isV6SoftForkActivated) { - v6Methods - } else { - v5Methods - } + // this .getMethods shouldn't ever be called + ??? } /** Collection of names of numeric casting methods (like `toByte`, `toInt`, etc). */ diff --git a/sc/shared/src/test/scala/sigmastate/ErgoTreeSpecification.scala b/sc/shared/src/test/scala/sigmastate/ErgoTreeSpecification.scala index 7ca46c8d16..406b84e26a 100644 --- a/sc/shared/src/test/scala/sigmastate/ErgoTreeSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/ErgoTreeSpecification.scala @@ -580,9 +580,6 @@ class ErgoTreeSpecification extends SigmaDslTesting with ContractsTestkit with C val mc = MethodsContainer(tyDesc.typeId) - println("mc: " + mc.methods.map(_.name)) - println("methods: " + methods.map(_.method.name)) - mc.methods.length shouldBe methods.length for (expectedMethod <- methods) { From 877ed789ead40ae29811969e3b0f25feb0a68209 Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Fri, 30 Aug 2024 19:30:44 +0300 Subject: [PATCH 217/314] adding new methods to GraphIRReflection --- .../src/main/scala/sigma/ast/methods.scala | 38 ++++++------------- .../sigma/compiler/ir/GraphIRReflection.scala | 16 ++++++++ 2 files changed, 27 insertions(+), 27 deletions(-) diff --git a/data/shared/src/main/scala/sigma/ast/methods.scala b/data/shared/src/main/scala/sigma/ast/methods.scala index 84fc4955a5..0b69b4a2c0 100644 --- a/data/shared/src/main/scala/sigma/ast/methods.scala +++ b/data/shared/src/main/scala/sigma/ast/methods.scala @@ -922,8 +922,7 @@ object SCollectionMethods extends MethodsContainer with MethodByNameUnapply { baseCost = JitCost(10), perChunkCost = JitCost(1), chunkSize = 10) val ZipMethod = SMethod(this, "zip", - SFunc(Array(ThisType, tOVColl), SCollection(STuple(tIV, tOV)), Array[STypeParam](tIV, tOV)), - 29, Zip_CostKind) + SFunc(Array(ThisType, tOVColl), SCollection(STuple(tIV, tOV)), Array[STypeParam](tIV, tOV)), 29, Zip_CostKind) .withIRInfo(MethodCallIrBuilder) .withInfo(MethodCall, "") @@ -939,11 +938,10 @@ object SCollectionMethods extends MethodsContainer with MethodByNameUnapply { } } + // ======== 6.0 methods below =========== - // 6.0 methods below val ReverseMethod = SMethod(this, "reverse", - SFunc(Array(ThisType), ThisType, paramIVSeq), - 30, Zip_CostKind) // todo: costing + SFunc(Array(ThisType), ThisType, paramIVSeq), 30, Zip_CostKind) // todo: costing .withIRInfo(MethodCallIrBuilder) .withInfo(MethodCall, "") @@ -960,8 +958,7 @@ object SCollectionMethods extends MethodsContainer with MethodByNameUnapply { } val DistinctMethod = SMethod(this, "distinct", - SFunc(Array(ThisType), ThisType, paramIVSeq), - 31, Zip_CostKind) // todo: costing + SFunc(Array(ThisType), ThisType, paramIVSeq), 31, Zip_CostKind) // todo: costing .withIRInfo(MethodCallIrBuilder) .withInfo(MethodCall, "") @@ -978,8 +975,7 @@ object SCollectionMethods extends MethodsContainer with MethodByNameUnapply { } val StartsWithMethod = SMethod(this, "startsWith", - SFunc(Array(ThisType, ThisType), SBoolean, paramIVSeq), - 32, Zip_CostKind) // todo: costing + SFunc(Array(ThisType, ThisType), SBoolean, paramIVSeq), 32, Zip_CostKind) // todo: costing .withIRInfo(MethodCallIrBuilder) .withInfo(MethodCall, "") @@ -996,8 +992,7 @@ object SCollectionMethods extends MethodsContainer with MethodByNameUnapply { } val EndsWithMethod = SMethod(this, "endsWith", - SFunc(Array(ThisType, ThisType), SBoolean, paramIVSeq), - 33, Zip_CostKind) // todo: costing + SFunc(Array(ThisType, ThisType), SBoolean, paramIVSeq), 33, Zip_CostKind) // todo: costing .withIRInfo(MethodCallIrBuilder) .withInfo(MethodCall, "") @@ -1018,18 +1013,7 @@ object SCollectionMethods extends MethodsContainer with MethodByNameUnapply { .withIRInfo(MethodCallIrBuilder) .withInfo(MethodCall, "") - /** Implements evaluation of Coll.zip method call ErgoTree node. - * Called via reflection based on naming convention. - * @see SMethod.evalMethod - */ - def get_eval[A](mc: MethodCall, xs: Coll[A], index: Int) - (implicit E: ErgoTreeEvaluator): Option[A] = { - E.addCost(ByIndex.costKind, mc.method.opDesc) //todo: costing - ??? // todo: this get is not actually executed, why? - xs.get(index) - } - - private val v5Methods = Seq( + private val v5Methods = super.getMethods() ++ Seq( SizeMethod, GetOrElseMethod, MapMethod, @@ -1049,7 +1033,7 @@ object SCollectionMethods extends MethodsContainer with MethodByNameUnapply { ZipMethod ) - private val v6Methods = Seq( + private val v6Methods = v5Methods ++ Seq( ReverseMethod, DistinctMethod, StartsWithMethod, @@ -1061,10 +1045,10 @@ object SCollectionMethods extends MethodsContainer with MethodByNameUnapply { * Typical override: `super.getMethods() ++ Seq(m1, m2, m3)` */ override protected def getMethods(): Seq[SMethod] = { - if(VersionContext.current.isV6SoftForkActivated) { - super.getMethods() ++ v5Methods ++ v6Methods + if (VersionContext.current.isV6SoftForkActivated) { + v6Methods } else { - super.getMethods() ++ v5Methods + v5Methods } } diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/GraphIRReflection.scala b/sc/shared/src/main/scala/sigma/compiler/ir/GraphIRReflection.scala index 69736a0224..829a37f871 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/GraphIRReflection.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/GraphIRReflection.scala @@ -202,6 +202,22 @@ object GraphIRReflection { }, mkMethod(clazz, "exists", Array[Class[_]](classOf[Base#Ref[_]])) { (obj, args) => obj.asInstanceOf[ctx.Coll[Any]].exists(args(0).asInstanceOf[ctx.Ref[Any => Boolean]]) + }, + // V6 methods + mkMethod(clazz, "reverse", Array[Class[_]]()) { (obj, _) => + obj.asInstanceOf[ctx.Coll[Any]].reverse + }, + mkMethod(clazz, "distinct", Array[Class[_]]()) { (obj, _) => + obj.asInstanceOf[ctx.Coll[Any]].distinct + }, + mkMethod(clazz, "startsWith", Array[Class[_]](classOf[Base#Ref[_]])) { (obj, args) => + obj.asInstanceOf[ctx.Coll[Any]].startsWith(args(0).asInstanceOf[ctx.Ref[ctx.Coll[Any]]]) + }, + mkMethod(clazz, "endsWith", Array[Class[_]](classOf[Base#Ref[_]])) { (obj, args) => + obj.asInstanceOf[ctx.Coll[Any]].endsWith(args(0).asInstanceOf[ctx.Ref[ctx.Coll[Any]]]) + }, + mkMethod(clazz, "get", Array[Class[_]](classOf[Base#Ref[_]])) { (obj, args) => + obj.asInstanceOf[ctx.Coll[_]].apply(args(0).asInstanceOf[ctx.Ref[Int]]) } ) ) From baef87f403cf65ffdeaf264420a35c41e626eb48 Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Mon, 2 Sep 2024 20:20:50 +0300 Subject: [PATCH 218/314] more efficient toBits impl --- .../main/scala/sigma/data/ExactNumeric.scala | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/data/shared/src/main/scala/sigma/data/ExactNumeric.scala b/data/shared/src/main/scala/sigma/data/ExactNumeric.scala index 214569e6e5..90d28e5370 100644 --- a/data/shared/src/main/scala/sigma/data/ExactNumeric.scala +++ b/data/shared/src/main/scala/sigma/data/ExactNumeric.scala @@ -1,7 +1,10 @@ package sigma.data +import debox.cfor +import sigma.Evaluation.stypeToRType import sigma.{BigInt, Coll, Colls} import sigma.data.ExactIntegral._ +import sigma.data.RType.SomeType import scala.collection.mutable @@ -40,18 +43,22 @@ trait ExactNumeric[T] { def toBigEndianBytes(x: T): Coll[Byte] def toBits(x: T): Coll[Boolean] = { - def byte2Bools(b: Byte): Array[Boolean] = (0 to 7).toArray.reverse.map(isBitSet(b)) def isBitSet(byte: Byte)(bit: Int): Boolean = ((byte >> bit) & 1) == 1 + def byte2Bools(b: Byte): Array[Boolean] = (0 to 7).toArray.reverse.map(isBitSet(b)) + val bytes = toBigEndianBytes(x) - val builder = mutable.ArrayBuilder.make[Boolean] val l = bytes.length - (0 until l).foreach{i=> + val res = new Array[Boolean](l * 8) + var offset = 0 + cfor(0)(_ < l, _ + 1) { i => val b = bytes(i) - builder.addAll(byte2Bools(b)) + val bits = byte2Bools(b) + Array.copy(bits, 0, res, offset, 8) + offset += 8 } - Colls.fromArray(builder.result()) + Colls.fromArray(res) } def bitwiseInverse(x: T): T From 8208dd8c4aaa39c2fdb6823d986954e71d77cb19 Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Tue, 3 Sep 2024 12:46:56 +0300 Subject: [PATCH 219/314] Box.getReg with computable index --- .gitignore | 1 + .../src/main/scala/sigma/SigmaDsl.scala | 17 ++ .../sigma/reflection/ReflectionData.scala | 3 + .../main/scala/sigma/util/NBitsUtils.scala | 84 ++++++++ .../scala/org/ergoplatform/ErgoHeader.scala | 182 ++++++++++++++++++ .../org/ergoplatform/HeaderWithoutPow.scala | 145 ++++++++++++++ .../src/main/scala/sigma/ast/methods.scala | 67 +++++-- .../src/main/scala/sigma/data/CHeader.scala | 142 ++++++++++++++ .../scala/sigma/eval/ErgoTreeEvaluator.scala | 2 +- .../sigma/pow/Autolykos2PowValidation.scala | 176 +++++++++++++++++ .../sigma/serialization/DataSerializer.scala | 14 +- docs/LangSpec.md | 4 + .../main/scala/sigmastate/eval/CHeader.scala | 34 ---- .../interpreter/CErgoTreeEvaluator.scala | 6 +- .../ConstantSerializerSpecification.scala | 41 ++-- .../DataSerializerSpecification.scala | 135 +++++++++---- .../MethodCallSerializerSpecification.scala | 23 +++ .../SerializationSpecification.scala | 21 +- .../generators/ObjectGenerators.scala | 10 +- .../generators/TypeGenerators.scala | 3 +- .../special/sigma/SigmaTestingData.scala | 16 +- .../sigma/compiler/ir/GraphBuilding.scala | 11 +- .../sigma/compiler/ir/GraphIRReflection.scala | 3 + .../scala/sigma/compiler/ir/IRContext.scala | 2 +- .../scala/sigma/compiler/ir/MethodCalls.scala | 16 +- .../sigma/compiler/ir/TreeBuilding.scala | 16 +- .../ir/wrappers/sigma/SigmaDslUnit.scala | 1 + .../ir/wrappers/sigma/impl/SigmaDslImpl.scala | 24 ++- .../sigma/compiler/phases/SigmaTyper.scala | 6 +- .../scala/sigma/LanguageSpecificationV5.scala | 17 +- .../scala/sigma/LanguageSpecificationV6.scala | 58 +++++- .../test/scala/sigma/SigmaDslTesting.scala | 18 +- .../sigmastate/ErgoTreeSpecification.scala | 13 +- .../TestingInterpreterSpecification.scala | 91 +++++++-- .../scala/sigmastate/TypesSpecification.scala | 2 - .../utxo/BasicOpsSpecification.scala | 43 +++++ .../org/ergoplatform/sdk/js/Header.scala | 6 +- .../scala/org/ergoplatform/sdk/js/Isos.scala | 12 +- .../org/ergoplatform/sdk/js/IsosSpec.scala | 4 +- .../ergoplatform/sdk/DataJsonEncoder.scala | 8 + .../org/ergoplatform/sdk/JsonCodecs.scala | 17 +- .../sdk/DataJsonEncoderSpecification.scala | 92 ++++++--- 42 files changed, 1365 insertions(+), 221 deletions(-) create mode 100644 core/shared/src/main/scala/sigma/util/NBitsUtils.scala create mode 100644 data/shared/src/main/scala/org/ergoplatform/ErgoHeader.scala create mode 100644 data/shared/src/main/scala/org/ergoplatform/HeaderWithoutPow.scala create mode 100644 data/shared/src/main/scala/sigma/data/CHeader.scala create mode 100644 data/shared/src/main/scala/sigma/pow/Autolykos2PowValidation.scala delete mode 100644 interpreter/shared/src/main/scala/sigmastate/eval/CHeader.scala diff --git a/.gitignore b/.gitignore index 4dc1640004..3570923b1d 100644 --- a/.gitignore +++ b/.gitignore @@ -11,6 +11,7 @@ yarn.lock *.log +yarn.lock docs/spec/out/ test-out/ flamegraphs/ diff --git a/core/shared/src/main/scala/sigma/SigmaDsl.scala b/core/shared/src/main/scala/sigma/SigmaDsl.scala index df2b419273..ba22d911e2 100644 --- a/core/shared/src/main/scala/sigma/SigmaDsl.scala +++ b/core/shared/src/main/scala/sigma/SigmaDsl.scala @@ -459,6 +459,23 @@ trait Header { /** Miner votes for changing system parameters. */ def votes: Coll[Byte] //3 bytes + + /** Bytes which are coming from future versions of the protocol, so + * their meaning is not known to current version of Sigma, but they + * are stored to get the same id as future version users. + */ + def unparsedBytes: Coll[Byte] + + /** + * @return header bytes without proof of work, a PoW is generated over them + */ + def serializeWithoutPoW: Coll[Byte] + + /** + * @return result of header's proof-of-work validation + */ + def checkPow: Boolean + } /** Runtime representation of Context ErgoTree type. diff --git a/core/shared/src/main/scala/sigma/reflection/ReflectionData.scala b/core/shared/src/main/scala/sigma/reflection/ReflectionData.scala index 028e68bf72..2a5e74e659 100644 --- a/core/shared/src/main/scala/sigma/reflection/ReflectionData.scala +++ b/core/shared/src/main/scala/sigma/reflection/ReflectionData.scala @@ -346,6 +346,9 @@ object ReflectionData { }, mkMethod(clazz, "powDistance", Array[Class[_]]()) { (obj, _) => obj.asInstanceOf[Header].powDistance + }, + mkMethod(clazz, "checkPow", Array[Class[_]]()) { (obj, _) => + obj.asInstanceOf[Header].checkPow } ) ) diff --git a/core/shared/src/main/scala/sigma/util/NBitsUtils.scala b/core/shared/src/main/scala/sigma/util/NBitsUtils.scala new file mode 100644 index 0000000000..36d526d1d5 --- /dev/null +++ b/core/shared/src/main/scala/sigma/util/NBitsUtils.scala @@ -0,0 +1,84 @@ +package sigma.util + +import java.math.BigInteger + +object NBitsUtils { + + /** + *

The "compact" format is a representation of a whole number N using an unsigned 32 bit number similar to a + * floating point format. The most significant 8 bits are the unsigned exponent of base 256. This exponent can + * be thought of as "number of bytes of N". The lower 23 bits are the mantissa. Bit number 24 (0x800000) represents + * the sign of N. Therefore, N = (-1^sign) * mantissa * 256^(exponent-3).

+ * + *

Satoshi's original implementation used BN_bn2mpi() and BN_mpi2bn(). MPI uses the most significant bit of the + * first byte as sign. Thus 0x1234560000 is compact 0x05123456 and 0xc0de000000 is compact 0x0600c0de. Compact + * 0x05c0de00 would be -0x40de000000.

+ * + *

Bitcoin only uses this "compact" format for encoding difficulty targets, which are unsigned 256bit quantities. + * Thus, all the complexities of the sign bit and using base 256 are probably an implementation accident.

+ */ + def decodeCompactBits(compact: Long): BigInt = { + val size: Int = (compact >> 24).toInt & 0xFF + val bytes: Array[Byte] = new Array[Byte](4 + size) + bytes(3) = size.toByte + if (size >= 1) bytes(4) = ((compact >> 16) & 0xFF).toByte + if (size >= 2) bytes(5) = ((compact >> 8) & 0xFF).toByte + if (size >= 3) bytes(6) = (compact & 0xFF).toByte + decodeMPI(bytes) + } + + /** + * @see Utils#decodeCompactBits(long) + */ + def encodeCompactBits(requiredDifficulty: BigInt): Long = { + val value = requiredDifficulty.bigInteger + var result: Long = 0L + var size: Int = value.toByteArray.length + if (size <= 3) { + result = value.longValue << 8 * (3 - size) + } else { + result = value.shiftRight(8 * (size - 3)).longValue + } + // The 0x00800000 bit denotes the sign. + // Thus, if it is already set, divide the mantissa by 256 and increase the exponent. + if ((result & 0x00800000L) != 0) { + result >>= 8 + size += 1 + } + result |= size << 24 + val a: Int = if (value.signum == -1) 0x00800000 else 0 + result |= a + result + } + + + /** Parse 4 bytes from the byte array (starting at the offset) as unsigned 32-bit integer in big endian format. */ + def readUint32BE(bytes: Array[Byte]): Long = ((bytes(0) & 0xffL) << 24) | ((bytes(1) & 0xffL) << 16) | ((bytes(2) & 0xffL) << 8) | (bytes(3) & 0xffL) + + /** + * MPI encoded numbers are produced by the OpenSSL BN_bn2mpi function. They consist of + * a 4 byte big endian length field, followed by the stated number of bytes representing + * the number in big endian format (with a sign bit). + * + */ + private def decodeMPI(mpi: Array[Byte]): BigInteger = { + + val length: Int = readUint32BE(mpi).toInt + val buf = new Array[Byte](length) + System.arraycopy(mpi, 4, buf, 0, length) + + if (buf.length == 0) { + BigInteger.ZERO + } else { + val isNegative: Boolean = (buf(0) & 0x80) == 0x80 + if (isNegative) buf(0) = (buf(0) & 0x7f).toByte + val result: BigInteger = new BigInteger(buf) + if (isNegative) { + result.negate + } else { + result + } + } + } + +} diff --git a/data/shared/src/main/scala/org/ergoplatform/ErgoHeader.scala b/data/shared/src/main/scala/org/ergoplatform/ErgoHeader.scala new file mode 100644 index 0000000000..2c6a40d46d --- /dev/null +++ b/data/shared/src/main/scala/org/ergoplatform/ErgoHeader.scala @@ -0,0 +1,182 @@ +package org.ergoplatform + +import scorex.crypto.authds.ADDigest +import scorex.crypto.hash.{Blake2b256, Digest32} +import scorex.util.ModifierId +import sigma.Colls +import sigma.crypto.{BigIntegers, CryptoConstants, EcPointType} +import sigma.serialization.{GroupElementSerializer, SigmaByteReader, SigmaByteWriter, SigmaSerializer} + +import scala.runtime.ScalaRunTime +import scala.util.hashing.MurmurHash3 + + + +/** + * Solution for an Autolykos PoW puzzle. + * + * In Autolykos v.1 all the four fields are used, in Autolykos v.2 only pk and n fields are used. + * + * @param pk - miner public key. Should be used to collect block rewards + * @param w - one-time public key. Prevents revealing of miners secret + * @param n - nonce (8 bytes) + * @param d - distance between pseudo-random number, corresponding to nonce `n` and a secret, + * corresponding to `pk`. The lower `d` is, the harder it was to find this solution. + */ +class AutolykosSolution(val pk: EcPointType, + val w: EcPointType, + val n: Array[Byte], + val d: BigInt) { + + val encodedPk: Array[Byte] = GroupElementSerializer.toBytes(pk) + + override def hashCode(): Int = { + var h = pk.hashCode() + h = h * 31 + w.hashCode() + h = h * 31 + MurmurHash3.arrayHash(n) + h = h * 31 + d.hashCode() + h + } + + override def equals(obj: Any): Boolean = { + obj match { + case other: AutolykosSolution => + this.pk == other.pk && + this.n.sameElements(other.n) && + this.w == other.w && + this.d == other.d + + case _ => false + } + } +} + + +object AutolykosSolution { + // "pk", "w" and "d" values for Autolykos v2 solution, where they not passed from outside + val pkForV2: EcPointType = CryptoConstants.dlogGroup.identity + val wForV2: EcPointType = CryptoConstants.dlogGroup.generator + val dForV2: BigInt = 0 + + object sigmaSerializerV1 extends SigmaSerializer[AutolykosSolution, AutolykosSolution] { + override def serialize(s: AutolykosSolution, w: SigmaByteWriter): Unit = { + GroupElementSerializer.serialize(s.pk, w) + GroupElementSerializer.serialize(s.w, w) + require(s.n.length == 8) // non-consensus check on prover side + w.putBytes(s.n) + val dBytes = BigIntegers.asUnsignedByteArray(s.d.bigInteger) + w.putUByte(dBytes.length) + w.putBytes(dBytes) + } + + override def parse(r: SigmaByteReader): AutolykosSolution = { + val pk = GroupElementSerializer.parse(r) + val w = GroupElementSerializer.parse(r) + val nonce = r.getBytes(8) + val dBytesLength = r.getUByte() + val d = BigInt(BigIntegers.fromUnsignedByteArray(r.getBytes(dBytesLength))) + new AutolykosSolution(pk, w, nonce, d) + } + } + + object sigmaSerializerV2 extends SigmaSerializer[AutolykosSolution, AutolykosSolution] { + override def serialize(s: AutolykosSolution, w: SigmaByteWriter): Unit = { + GroupElementSerializer.serialize(s.pk, w) + require(s.n.length == 8) // non-consensus check on prover side + w.putBytes(s.n) + } + + override def parse(r: SigmaByteReader): AutolykosSolution = { + val pk = GroupElementSerializer.parse(r) + val nonce = r.getBytes(8) + new AutolykosSolution(pk, wForV2, nonce, dForV2) + } + } +} + +/** + * Header of a block. It authenticates link to a previous block, other block sections + * (transactions, UTXO set transformation proofs, extension), UTXO set, votes for parameters + * to be changed and proof-of-work related data. + * + * @param version - protocol version + * @param parentId - id of a parent block header + * @param ADProofsRoot - digest of UTXO set transformation proofs + * @param stateRoot - AVL+ tree digest of UTXO set (after the block) + * @param transactionsRoot - Merkle tree digest of transactions in the block (BlockTransactions section) + * @param timestamp - block generation time reported by a miner + * @param nBits - difficulty encoded + * @param height - height of the block (genesis block height == 1) + * @param extensionRoot - Merkle tree digest of the extension section of the block + * @param powSolution - solution for the proof-of-work puzzle + * @param votes - votes for changing system parameters + * @param unparsedBytes - bytes from future versions of the protocol our version can't parse + * @param _bytes - serialized bytes of the header when not `null` + */ +case class ErgoHeader(override val version: ErgoHeader.Version, + override val parentId: ModifierId, + override val ADProofsRoot: Digest32, + override val stateRoot: ADDigest, //33 bytes! extra byte with tree height here! + override val transactionsRoot: Digest32, + override val timestamp: ErgoHeader.Timestamp, + override val nBits: Long, //actually it is unsigned int + override val height: Int, + override val extensionRoot: Digest32, + powSolution: AutolykosSolution, + override val votes: Array[Byte], //3 bytes + override val unparsedBytes: Array[Byte], + _bytes: Array[Byte]) extends + HeaderWithoutPow(version, parentId, ADProofsRoot, stateRoot, transactionsRoot, timestamp, + nBits, height, extensionRoot, votes, unparsedBytes) { + + lazy val bytes = if(_bytes != null) { + _bytes + } else { + ErgoHeader.sigmaSerializer.toBytes(this) + } + + lazy val serializedId: Array[Byte] = Blake2b256.hash(bytes) + + lazy val id = Colls.fromArray(serializedId) + + override def hashCode(): Int = id.hashCode() + + override def equals(other: Any): Boolean = other match { + case h: ErgoHeader => h.id == this.id + case _ => false + } +} + + +object ErgoHeader { + + type Timestamp = Long + + type Version = Byte + + object sigmaSerializer extends SigmaSerializer[ErgoHeader, ErgoHeader] { + override def serialize(hdr: ErgoHeader, w: SigmaByteWriter): Unit = { + HeaderWithoutPowSerializer.serialize(hdr, w) + if (hdr.version == 1) { + AutolykosSolution.sigmaSerializerV1.serialize(hdr.powSolution, w) + } else { + AutolykosSolution.sigmaSerializerV2.serialize(hdr.powSolution, w) + } + } + + override def parse(r: SigmaByteReader): ErgoHeader = { + val start = r.position + val headerWithoutPow = HeaderWithoutPowSerializer.parse(r) + val powSolution = if (headerWithoutPow.version == 1) { + AutolykosSolution.sigmaSerializerV1.parse(r) + } else { + AutolykosSolution.sigmaSerializerV2.parse(r) + } + val end = r.position + val len = end - start + r.position = start + val headerBytes = r.getBytes(len) // also moves position back to end + headerWithoutPow.toHeader(powSolution, headerBytes) + } + } +} \ No newline at end of file diff --git a/data/shared/src/main/scala/org/ergoplatform/HeaderWithoutPow.scala b/data/shared/src/main/scala/org/ergoplatform/HeaderWithoutPow.scala new file mode 100644 index 0000000000..21a10a5036 --- /dev/null +++ b/data/shared/src/main/scala/org/ergoplatform/HeaderWithoutPow.scala @@ -0,0 +1,145 @@ +package org.ergoplatform + +import scorex.crypto.authds.ADDigest +import scorex.crypto.hash.Digest32 +import scorex.util.{ModifierId, bytesToId, idToBytes} +import sigma.serialization.{SigmaByteReader, SigmaByteWriter, SigmaSerializer} +import scorex.util.Extensions._ + +/** + * Header without proof-of-work puzzle solution, see Header class description for details. + */ +class HeaderWithoutPow(val version: Byte, // 1 byte + val parentId: ModifierId, // 32 bytes + val ADProofsRoot: Digest32, // 32 bytes + val stateRoot: ADDigest, //33 bytes! extra byte with tree height here! + val transactionsRoot: Digest32, // 32 bytes + val timestamp: Long, + val nBits: Long, //actually it is unsigned int + val height: Int, + val extensionRoot: Digest32, + val votes: Array[Byte], //3 bytes + val unparsedBytes: Array[Byte]) { + def toHeader(powSolution: AutolykosSolution, bytes: Array[Byte]): ErgoHeader = + ErgoHeader(version, parentId, ADProofsRoot, stateRoot, transactionsRoot, timestamp, + nBits, height, extensionRoot, powSolution, votes, unparsedBytes, bytes) + + override def toString: String = { + s"HeaderWithoutPow($version, $parentId, ${bytesToId(ADProofsRoot)}, ${bytesToId(stateRoot)}, " + + s"${bytesToId(transactionsRoot)}, $timestamp, $nBits, $height, ${bytesToId(extensionRoot)}, ${bytesToId(votes)}, " + + s"${bytesToId(unparsedBytes)} )" + } +} + +object HeaderWithoutPow { + + def apply(version: Byte, parentId: ModifierId, ADProofsRoot: Digest32, stateRoot: ADDigest, + transactionsRoot: Digest32, timestamp: Long, nBits: Long, height: Int, + extensionRoot: Digest32, votes: Array[Byte], unparsedBytes: Array[Byte]): HeaderWithoutPow = { + new HeaderWithoutPow(version, parentId, ADProofsRoot, stateRoot, transactionsRoot, timestamp, + nBits, height, extensionRoot, votes, unparsedBytes) + } + +} + +object HeaderWithoutPowSerializer extends SigmaSerializer[HeaderWithoutPow, HeaderWithoutPow] { + + override def serialize(h: HeaderWithoutPow, w: SigmaByteWriter): Unit = { + w.put(h.version) + w.putBytes(idToBytes(h.parentId)) + w.putBytes(h.ADProofsRoot) + w.putBytes(h.transactionsRoot) + w.putBytes(h.stateRoot) + w.putULong(h.timestamp) + w.putBytes(h.extensionRoot) + DifficultySerializer.serialize(h.nBits, w) + w.putUInt(h.height.toLong) + w.putBytes(h.votes) + + // For block version >= 2, this new byte encodes length of possible new fields. + // Set to 0 for now, so no new fields. + if (h.version > HeaderVersion.InitialVersion) { + w.putUByte(h.unparsedBytes.length) + w.putBytes(h.unparsedBytes) + } + } + + override def parse(r: SigmaByteReader): HeaderWithoutPow = { + val version = r.getByte() + val parentId = bytesToId(r.getBytes(32)) + val ADProofsRoot = Digest32 @@ r.getBytes(32) + val transactionsRoot = Digest32 @@ r.getBytes(32) + val stateRoot = ADDigest @@ r.getBytes(33) + val timestamp = r.getULong() + val extensionHash = Digest32 @@ r.getBytes(32) + val nBits = DifficultySerializer.parse(r) + val height = r.getUInt().toIntExact + val votes = r.getBytes(3) + + // For block version >= 2, a new byte encodes length of possible new fields. + // If this byte > 0, we read new fields but do nothing, as semantics of the fields is not known. + val unparsedBytes = if (version > HeaderVersion.InitialVersion) { + val newFieldsSize = r.getUByte() + if (newFieldsSize > 0 && version > HeaderVersion.Interpreter60Version) { + // new bytes could be added only for block version >= 5 + r.getBytes(newFieldsSize) + } else { + Array.emptyByteArray + } + } else { + Array.emptyByteArray + } + + HeaderWithoutPow(version, parentId, ADProofsRoot, stateRoot, transactionsRoot, timestamp, + nBits, height, extensionHash, votes, unparsedBytes) + } + +} + + +object DifficultySerializer extends SigmaSerializer[Long, Long] { + + /** Parse 4 bytes from the byte array (starting at the offset) as unsigned 32-bit integer in big endian format. */ + def readUint32BE(bytes: Array[Byte]): Long = ((bytes(0) & 0xffL) << 24) | ((bytes(1) & 0xffL) << 16) | ((bytes(2) & 0xffL) << 8) | (bytes(3) & 0xffL) + + def uint32ToByteArrayBE(value: Long): Array[Byte] = { + Array(0xFF & (value >> 24), 0xFF & (value >> 16), 0xFF & (value >> 8), 0xFF & value).map(_.toByte) + } + + override def serialize(obj: Long, w: SigmaByteWriter): Unit = { + w.putBytes(uint32ToByteArrayBE(obj)) + } + + override def parse(r: SigmaByteReader): Long = { + readUint32BE(r.getBytes(4)) + } + +} + +object HeaderVersion { + type Value = Byte + + /** + * Block version during mainnet launch + */ + val InitialVersion: Value = 1.toByte + + /** + * Block version after the Hardening hard-fork + * Autolykos v2 PoW, witnesses in transactions Merkle tree + */ + val HardeningVersion: Value = 2.toByte + + /** + * Block version after the 5.0 soft-fork + * 5.0 interpreter with JITC, monotonic height rule (EIP-39) + */ + val Interpreter50Version: Value = 3.toByte + + /** + * Block version after the 6.0 soft-fork + * 6.0 interpreter (EIP-50) + */ + val Interpreter60Version: Value = 4.toByte + +} diff --git a/data/shared/src/main/scala/sigma/ast/methods.scala b/data/shared/src/main/scala/sigma/ast/methods.scala index e4cf0007e0..ab3f00a675 100644 --- a/data/shared/src/main/scala/sigma/ast/methods.scala +++ b/data/shared/src/main/scala/sigma/ast/methods.scala @@ -309,13 +309,6 @@ case object SBigIntMethods extends SNumericTypeMethods { /** Type for which this container defines methods. */ override def ownerType: SMonoType = SBigInt - final val ToNBitsCostInfo = OperationCostInfo( - FixedCost(JitCost(5)), NamedDesc("NBitsMethodCall")) - - //id = 8 to make it after toBits - val ToNBits = SMethod(this, "nbits", SFunc(this.ownerType, SLong), 8, ToNBitsCostInfo.costKind) - .withInfo(ModQ, "Encode this big integer value as NBits") - /** The following `modQ` methods are not fully implemented in v4.x and this descriptors. * This descritors are remain here in the code and are waiting for full implementation * is upcoming soft-forks at which point the cost parameters should be calculated and @@ -333,7 +326,7 @@ case object SBigIntMethods extends SNumericTypeMethods { protected override def getMethods(): Seq[SMethod] = { if (VersionContext.current.isV6SoftForkActivated) { - super.getMethods() ++ Seq(ToNBits) + super.getMethods() // ModQMethod, // PlusModQMethod, // MinusModQMethod, @@ -1063,7 +1056,7 @@ case object SBoxMethods extends MonoTypeMethods { | identifier followed by box index in the transaction outputs. """.stripMargin ) // see ExtractCreationInfo - lazy val getRegMethod = SMethod(this, "getReg", + lazy val getRegMethodV5 = SMethod(this, "getReg", SFunc(Array(SBox, SInt), SOption(tT), Array(paramT)), 7, ExtractRegisterAs.costKind) .withInfo(ExtractRegisterAs, """ Extracts register by id and type. @@ -1072,23 +1065,49 @@ case object SBoxMethods extends MonoTypeMethods { """.stripMargin, ArgInfo("regId", "zero-based identifier of the register.")) + lazy val getRegMethodV6 = SMethod(this, "getReg", + SFunc(Array(SBox, SInt), SOption(tT), Array(paramT)), 7, ExtractRegisterAs.costKind, Seq(tT)) + .withIRInfo(MethodCallIrBuilder, + javaMethodOf[Box, Int, RType[_]]("getReg"), + { mtype => Array(mtype.tRange.asOption[SType].elemType) }) + .withInfo(MethodCall, """ Extracts register by id and type. + | Type param \lst{T} expected type of the register. + | Returns \lst{Some(value)} if the register is defined and has given type and \lst{None} otherwise + """.stripMargin, + ArgInfo("regId", "zero-based identifier of the register.")) + lazy val tokensMethod = SMethod( this, "tokens", SFunc(SBox, ErgoBox.STokensRegType), 8, FixedCost(JitCost(15))) .withIRInfo(MethodCallIrBuilder) .withInfo(PropertyCall, "Secondary tokens") - - // should be lazy to solve recursive initialization - protected override def getMethods() = super.getMethods() ++ Array( + lazy val commonBoxMethods = super.getMethods() ++ Array( ValueMethod, // see ExtractAmount PropositionBytesMethod, // see ExtractScriptBytes BytesMethod, // see ExtractBytes BytesWithoutRefMethod, // see ExtractBytesWithNoRef IdMethod, // see ExtractId creationInfoMethod, - getRegMethod, tokensMethod ) ++ registers(8) + + lazy val v5Methods = commonBoxMethods ++ Array( + getRegMethodV5 + ) + + lazy val v6Methods = commonBoxMethods ++ Array( + getRegMethodV6 + ) + + // should be lazy to solve recursive initialization + protected override def getMethods() = { + if (VersionContext.current.isV6SoftForkActivated) { + v6Methods + } else { + v5Methods + } + } + } /** Type descriptor of `AvlTree` type of ErgoTree. */ @@ -1456,11 +1475,27 @@ case object SHeaderMethods extends MonoTypeMethods { lazy val powDistanceMethod = propertyCall("powDistance", SBigInt, 14, FixedCost(JitCost(10))) lazy val votesMethod = propertyCall("votes", SByteArray, 15, FixedCost(JitCost(10))) - protected override def getMethods() = super.getMethods() ++ Seq( + // cost of checkPoW is 700 as about 2*32 hashes required, and 1 hash (id) over short data costs 10 + lazy val checkPowMethod = SMethod( + this, "checkPow", SFunc(Array(SHeader), SBoolean), 16, FixedCost(JitCost(700))) + .withIRInfo(MethodCallIrBuilder) + .withInfo(MethodCall, "Validate header's proof-of-work") + + private lazy val v5Methods = super.getMethods() ++ Seq( idMethod, versionMethod, parentIdMethod, ADProofsRootMethod, stateRootMethod, transactionsRootMethod, timestampMethod, nBitsMethod, heightMethod, extensionRootMethod, minerPkMethod, powOnetimePkMethod, - powNonceMethod, powDistanceMethod, votesMethod - ) + powNonceMethod, powDistanceMethod, votesMethod) + + // 6.0 : checkPow method added + private lazy val v6Methods = v5Methods ++ Seq(checkPowMethod) + + protected override def getMethods() = { + if (VersionContext.current.isV6SoftForkActivated) { + v6Methods + } else { + v5Methods + } + } } /** Type descriptor of `PreHeader` type of ErgoTree. */ diff --git a/data/shared/src/main/scala/sigma/data/CHeader.scala b/data/shared/src/main/scala/sigma/data/CHeader.scala new file mode 100644 index 0000000000..aa5a5756d2 --- /dev/null +++ b/data/shared/src/main/scala/sigma/data/CHeader.scala @@ -0,0 +1,142 @@ +package sigma.data + +import org.ergoplatform.{AutolykosSolution, ErgoHeader, HeaderWithoutPow, HeaderWithoutPowSerializer} +import scorex.crypto.authds.ADDigest +import scorex.crypto.hash.Digest32 +import scorex.util.{bytesToId, idToBytes} +import sigma.pow.Autolykos2PowValidation +import sigma.{AvlTree, BigInt, Coll, Colls, GroupElement, Header} + +/** A default implementation of [[Header]] interface. + * + * @see [[Header]] for detailed descriptions + */ +class CHeader(val ergoHeader: ErgoHeader) extends Header with WrapperOf[ErgoHeader] { + + /** Bytes representation of ModifierId of this Header */ + override lazy val id: Coll[Byte] = ergoHeader.id + + /** Block version, to be increased on every soft and hardfork. */ + override def version: Byte = ergoHeader.version + + /** Bytes representation of ModifierId of the parent block */ + override def parentId: Coll[Byte] = Colls.fromArray(idToBytes(ergoHeader.parentId)) + + /** Hash of ADProofs for transactions in a block */ + override def ADProofsRoot: Coll[Byte] = Colls.fromArray(ergoHeader.ADProofsRoot) + + /** AvlTree of a state after block application */ + override def stateRoot: AvlTree = CAvlTree(AvlTreeData.avlTreeFromDigest(Colls.fromArray(ergoHeader.stateRoot))) + + /** Root hash (for a Merkle tree) of transactions in a block. */ + override def transactionsRoot: Coll[Byte] = Colls.fromArray(ergoHeader.transactionsRoot) + + /** Block timestamp (in milliseconds since beginning of Unix Epoch) */ + override def timestamp: Long = ergoHeader.timestamp + + /** Current difficulty in a compressed view. + * NOTE: actually it is unsigned Int */ + override def nBits: Long = ergoHeader.nBits + + /** Block height */ + override def height: Int = ergoHeader.height + + /** Root hash of extension section */ + override def extensionRoot: Coll[Byte] = Colls.fromArray(ergoHeader.extensionRoot) + + /** Miner public key. Should be used to collect block rewards. + * Part of Autolykos solution. */ + override def minerPk: GroupElement = CGroupElement(ergoHeader.powSolution.pk) + + /** One-time public key. Prevents revealing of miners secret. */ + override def powOnetimePk: GroupElement = CGroupElement(ergoHeader.powSolution.w) + + /** nonce */ + override def powNonce: Coll[Byte] = Colls.fromArray(ergoHeader.powSolution.n) + + /** Distance between pseudo-random number, corresponding to nonce `powNonce` and a secret, + * corresponding to `minerPk`. The lower `powDistance` is, the harder it was to find this solution. */ + override def powDistance: BigInt = CBigInt(ergoHeader.powSolution.d.bigInteger) + + /** Miner votes for changing system parameters. */ + override def votes: Coll[Byte] = Colls.fromArray(ergoHeader.votes) + + override def unparsedBytes: Coll[Byte] = Colls.fromArray(ergoHeader.unparsedBytes) + + /** The data value wrapped by this wrapper. */ + override def wrappedValue: ErgoHeader = ergoHeader + + override def serializeWithoutPoW: Coll[Byte] = { + Colls.fromArray(HeaderWithoutPowSerializer.toBytes(ergoHeader)) + } + + override def checkPow: Boolean = { + Autolykos2PowValidation.checkPoWForVersion2(this) + } + + override def toString: String = + s"""CHeader( + | id: ${id}, + | version: ${version}, + | tx proofs hash: ${ADProofsRoot}, + | state root: ${stateRoot.digest}, + | transactions root: ${transactionsRoot}, + | time: $timestamp, + | nbits: $nBits, + | extension root: $extensionRoot, + | miner pubkey: $minerPk, + | pow one time pubkey(from AL 1): $powOnetimePk, + | pow nonce: $powNonce, + | pow distance (from AL 1): $powDistance, + | votes: $votes, + | unparsed bytes: $unparsedBytes + |)""".stripMargin + + override def hashCode(): Int = id.hashCode() + + override def equals(other: Any): Boolean = other match { + case ch: CHeader => ch.id == this.id + case _ => false + } + + def copy(): CHeader = new CHeader(ergoHeader.copy()) // used in tests only +} + +object CHeader { + + def apply( version: Byte, + parentId: Coll[Byte], + ADProofsRoot: Coll[Byte], + stateRootDigest: Coll[Byte], + transactionsRoot: Coll[Byte], + timestamp: Long, + nBits: Long, + height: Int, + extensionRoot: Coll[Byte], + minerPk: GroupElement, + powOnetimePk: GroupElement, + powNonce: Coll[Byte], + powDistance: BigInt, + votes: Coll[Byte], + unparsedBytes: Coll[Byte]): CHeader = { + + val solution = new AutolykosSolution( + minerPk.asInstanceOf[CGroupElement].wrappedValue, + powOnetimePk.asInstanceOf[CGroupElement].wrappedValue, + powNonce.toArray, + powDistance.asInstanceOf[CBigInt].wrappedValue) + + val h = ErgoHeader(version, bytesToId(parentId.toArray), Digest32 @@ ADProofsRoot.toArray, + ADDigest @@ stateRootDigest.toArray, Digest32 @@ transactionsRoot.toArray, timestamp, nBits, height, + Digest32 @@ extensionRoot.toArray, solution, votes.toArray, unparsedBytes.toArray, null) + + new CHeader(h) + } + + /** Size of of Header.votes array. */ + val VotesSize: Int = SigmaConstants.VotesArraySize.value + + /** Size of nonce array from Autolykos POW solution in Header.powNonce array. */ + val NonceSize: Int = SigmaConstants.AutolykosPowSolutionNonceArraySize.value + +} diff --git a/data/shared/src/main/scala/sigma/eval/ErgoTreeEvaluator.scala b/data/shared/src/main/scala/sigma/eval/ErgoTreeEvaluator.scala index 52f839354c..6df82125df 100644 --- a/data/shared/src/main/scala/sigma/eval/ErgoTreeEvaluator.scala +++ b/data/shared/src/main/scala/sigma/eval/ErgoTreeEvaluator.scala @@ -1,6 +1,6 @@ package sigma.eval -import sigma.{AvlTree, Coll, Context} +import sigma.{AvlTree, Coll, Context, Header} import sigma.ast.{Constant, FixedCost, MethodCall, OperationCostInfo, OperationDesc, PerItemCost, SType, TypeBasedCost} import sigma.data.KeyValueColl diff --git a/data/shared/src/main/scala/sigma/pow/Autolykos2PowValidation.scala b/data/shared/src/main/scala/sigma/pow/Autolykos2PowValidation.scala new file mode 100644 index 0000000000..23cf722194 --- /dev/null +++ b/data/shared/src/main/scala/sigma/pow/Autolykos2PowValidation.scala @@ -0,0 +1,176 @@ +package sigma.pow + + +import scorex.crypto.hash.Blake2b256 +import scorex.utils.{Bytes, Ints, Longs} +import sigma.Header +import sigma.crypto.{BcDlogGroup, BigIntegers, CryptoConstants} +import sigma.util.NBitsUtils + +/** + * Functions used to validate Autolykos2 Proof-of-Work. + */ +object Autolykos2PowValidation { + + type Height = Int + + /** + * k value for k-sum problem Autolykos is based on (find k numbers in table on N size) + */ + private val k = 32 + + /** + * Initial size of N value for k-sum problem Autolykos is based on (find k numbers in table on N size). + * It grows from it since predefined block height in Autolykos 2. + */ + private val NStart = 26 + + /** + * Group order, used in Autolykos V.1 for non-outsourceability, + * and also to obtain target in both Autolykos v1 and v2 + */ + private val q: BigInt = CryptoConstants.dlogGroup.order + + /** + * Number of elements in a table to find k-sum problem solution on top of + */ + val NBase: Int = Math.pow(2, NStart.toDouble).toInt + + /** + * Initial height since which table (`N` value) starting to increase by 5% per `IncreasePeriodForN` blocks + */ + val IncreaseStart: Height = 600 * 1024 + + /** + * Table size (`N`) increased every 50 * 1024 blocks + */ + val IncreasePeriodForN: Height = 50 * 1024 + + /** + * On this height, the table (`N` value) will stop to grow. + * Max N on and after this height would be 2,143,944,600 which is still less than 2^^31. + */ + val NIncreasementHeightMax: Height = 4198400 + + /** + * Blake2b256 hash function invocation + * @param in - input bit-string + * @return - 256 bits (32 bytes) array + */ + def hash(in: Array[Byte]): Array[Byte] = Blake2b256.hash(in) + + /** + * Convert byte array to unsigned integer + * @param in - byte array + * @return - unsigned integer + */ + def toBigInt(in: Array[Byte]): BigInt = BigInt(BigIntegers.fromUnsignedByteArray(in)) + + /** + * Constant data to be added to hash function to increase its calculation time + */ + val M: Array[Byte] = (0 until 1024).toArray.flatMap(i => Longs.toByteArray(i.toLong)) + + /** + * Calculates table size (N value) for a given height (moment of time) + * + * @see papers/yellow/pow/ErgoPow.tex for full description and test vectors + * @param headerHeight - height of a header to mine + * @return - N value + */ + def calcN(headerHeight: Height): Int = { + val height = Math.min(NIncreasementHeightMax, headerHeight) + if (height < IncreaseStart) { + NBase + } else { + val itersNumber = (height - IncreaseStart) / IncreasePeriodForN + 1 + (1 to itersNumber).foldLeft(NBase) { case (step, _) => + step / 100 * 105 + } + } + } + + def calcN(header: Header): Int = calcN(header.height) + + /** + * Hash function that takes `m` and `nonceBytes` and returns a list of size `k` with numbers in + * [0,`N`) + */ + private def genIndexes(k: Int, seed: Array[Byte], N: Int): Seq[Int] = { + val hash = Blake2b256(seed) + val extendedHash = Bytes.concat(hash, hash.take(3)) + (0 until k).map { i => + BigInt(1, extendedHash.slice(i, i + 4)).mod(N).toInt + } + }.ensuring(_.length == k) + + /** + * Generate element of Autolykos equation. + */ + private def genElementV2(indexBytes: Array[Byte], heightBytes: => Array[Byte]): BigInt = { + // Autolykos v. 2: H(j|h|M) (line 5 from the Algo 2 of the spec) + toBigInt(hash(Bytes.concat(indexBytes, heightBytes, M)).drop(1)) + } + + def hitForVersion2ForMessage(k: Int, msg: Array[Byte], nonce: Array[Byte], h: Array[Byte], N: Int): BigInt = { + + val prei8 = BigIntegers.fromUnsignedByteArray(hash(Bytes.concat(msg, nonce)).takeRight(8)) + val i = BigIntegers.asUnsignedByteArray(4, prei8.mod(BigInt(N).underlying())) + val f = Blake2b256(Bytes.concat(i, h, M)).drop(1) // .drop(1) is the same as takeRight(31) + val seed = Bytes.concat(f, msg, nonce) // Autolykos v1, Alg. 2, line4: + + val indexes = genIndexes(k, seed, N) + //pk and w not used in v2 + val elems = indexes.map(idx => genElementV2(Ints.toByteArray(idx), h)) + val f2 = elems.sum + + // sum as byte array is always about 32 bytes + val array: Array[Byte] = BigIntegers.asUnsignedByteArray(32, f2.underlying()) + val ha = hash(array) + toBigInt(ha) + } + + /** + * Header digest ("message" for default GPU miners) a miner is working on + */ + def msgByHeader(h: Header): Array[Byte] = Blake2b256(h.serializeWithoutPoW.toArray) + + /** + * Get hit for Autolykos v2 header (to test it then against PoW target) + * + * @param header - header to check PoW for + * @return PoW hit + */ + def hitForVersion2(header: Header): BigInt = { + + val msg = msgByHeader(header) + val nonce = header.powNonce + + val h = Ints.toByteArray(header.height) // used in AL v.2 only + + val N = calcN(header) + + hitForVersion2ForMessage(k, msg, nonce.toArray, h, N) + } + + /** + * Get target `b` from encoded difficulty `nBits` + */ + def getB(nBits: Long): BigInt = { + q / NBitsUtils.decodeCompactBits(nBits) + } + + /** + * Check PoW for Autolykos v2 header + * + * @param header - header to check PoW for + * @return whether PoW is valid or not + */ + def checkPoWForVersion2(header: Header): Boolean = { + val b = getB(header.nBits) + // for version 2, we're calculating hit and compare it with target + val hit = hitForVersion2(header) + hit < b + } + +} diff --git a/data/shared/src/main/scala/sigma/serialization/DataSerializer.scala b/data/shared/src/main/scala/sigma/serialization/DataSerializer.scala index 5f554e96a1..92a54f9aa4 100644 --- a/data/shared/src/main/scala/sigma/serialization/DataSerializer.scala +++ b/data/shared/src/main/scala/sigma/serialization/DataSerializer.scala @@ -1,8 +1,9 @@ package sigma.serialization -import org.ergoplatform.ErgoBox +import org.ergoplatform.{ErgoBox, ErgoHeader} +import sigma.VersionContext import sigma.ast._ -import sigma.data.CBox +import sigma.data.{CBox, CHeader} /** This works in tandem with ConstantSerializer, if you change one make sure to check the other.*/ object DataSerializer extends CoreDataSerializer { @@ -15,6 +16,9 @@ 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 => + val h = v.asInstanceOf[CHeader] + ErgoHeader.sigmaSerializer.serialize(h.ergoHeader, w.asInstanceOf[SigmaByteWriter]) case _ => super.serialize(v, tpe, w) } @@ -32,6 +36,12 @@ 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 => + val depth = r.level + r.level = depth + 1 + val res = new CHeader(ErgoHeader.sigmaSerializer.parse(r.asInstanceOf[SigmaByteReader])) + r.level = r.level - 1 + res case t => super.deserialize(t, r) }).asInstanceOf[T#WrappedType] diff --git a/docs/LangSpec.md b/docs/LangSpec.md index ba66748f08..1f05a3b403 100644 --- a/docs/LangSpec.md +++ b/docs/LangSpec.md @@ -249,6 +249,10 @@ class Context { /** Represents data of the block headers available in scripts. */ class Header { + + /** Validate header's proof-of-work */ + def checkPow: Boolean + /** Bytes representation of ModifierId of this Header */ def id: Coll[Byte] diff --git a/interpreter/shared/src/main/scala/sigmastate/eval/CHeader.scala b/interpreter/shared/src/main/scala/sigmastate/eval/CHeader.scala deleted file mode 100644 index 7062fa0f0e..0000000000 --- a/interpreter/shared/src/main/scala/sigmastate/eval/CHeader.scala +++ /dev/null @@ -1,34 +0,0 @@ -package sigmastate.eval - -import sigma.data.SigmaConstants -import sigma.{AvlTree, BigInt, Coll, GroupElement, Header} - -/** A default implementation of [[Header]] interface. - * - * @see [[Header]] for detailed descriptions - */ -case class CHeader( - id: Coll[Byte], - version: Byte, - parentId: Coll[Byte], - ADProofsRoot: Coll[Byte], - stateRoot: AvlTree, - transactionsRoot: Coll[Byte], - timestamp: Long, - nBits: Long, - height: Int, - extensionRoot: Coll[Byte], - minerPk: GroupElement, - powOnetimePk: GroupElement, - powNonce: Coll[Byte], - powDistance: BigInt, - votes: Coll[Byte] -) extends Header - -object CHeader { - /** Size of of Header.votes array. */ - val VotesSize: Int = SigmaConstants.VotesArraySize.value - - /** Size of nonce array from Autolykos POW solution in Header.powNonce array. */ - val NonceSize: Int = SigmaConstants.AutolykosPowSolutionNonceArraySize.value -} \ No newline at end of file diff --git a/interpreter/shared/src/main/scala/sigmastate/interpreter/CErgoTreeEvaluator.scala b/interpreter/shared/src/main/scala/sigmastate/interpreter/CErgoTreeEvaluator.scala index de8aa6b620..a72510f641 100644 --- a/interpreter/shared/src/main/scala/sigmastate/interpreter/CErgoTreeEvaluator.scala +++ b/interpreter/shared/src/main/scala/sigmastate/interpreter/CErgoTreeEvaluator.scala @@ -5,15 +5,17 @@ import sigma.ast._ import sigma.ast.syntax._ import sigmastate.eval.{CAvlTreeVerifier, CProfiler} import sigmastate.interpreter.Interpreter.ReductionResult -import sigma.{AvlTree, Coll, Colls, Context, VersionContext} +import sigma.{AvlTree, Coll, Colls, Context, Header, VersionContext} import sigma.util.Extensions._ import debox.{cfor, Buffer => DBuffer} import scorex.crypto.authds.ADKey import sigma.ast.SAvlTreeMethods._ +import sigma.ast.SHeaderMethods.checkPowMethod import sigma.ast.SType import sigma.data.{CSigmaProp, KeyValueColl, SigmaBoolean} import sigma.eval.{AvlTreeVerifier, ErgoTreeEvaluator, EvalSettings, Profiler} import sigma.eval.ErgoTreeEvaluator.DataEnv +import sigmastate.interpreter.CErgoTreeEvaluator.fixedCostOp import scala.collection.compat.immutable.ArraySeq import scala.util.{DynamicVariable, Failure, Success} @@ -449,7 +451,7 @@ object CErgoTreeEvaluator { * HOTSPOT: don't beautify the code * Note, `null` is used instead of Option to avoid allocations. */ - def fixedCostOp[R <: AnyRef](costInfo: OperationCostInfo[FixedCost]) + def fixedCostOp[R](costInfo: OperationCostInfo[FixedCost]) (block: => R)(implicit E: ErgoTreeEvaluator): R = { if (E != null) { var res: R = null.asInstanceOf[R] diff --git a/interpreter/shared/src/test/scala/sigma/serialization/ConstantSerializerSpecification.scala b/interpreter/shared/src/test/scala/sigma/serialization/ConstantSerializerSpecification.scala index 43e9cf9e5d..c9478c8356 100644 --- a/interpreter/shared/src/test/scala/sigma/serialization/ConstantSerializerSpecification.scala +++ b/interpreter/shared/src/test/scala/sigma/serialization/ConstantSerializerSpecification.scala @@ -9,7 +9,7 @@ import sigma.ast.{BigIntConstant, ByteArrayConstant, Constant, DeserializationSi import sigmastate.eval._ import sigma.Extensions.ArrayOps import sigma.ast._ -import sigma.{AvlTree, Colls, Evaluation} +import sigma.{AvlTree, Colls, Evaluation, Header, VersionContext} import sigma.ast.SType.AnyOps import scorex.util.encode.Base16 import sigma.ast.BoolArrayConstant.BoolArrayTypeCode @@ -17,6 +17,7 @@ import sigma.ast.ByteArrayConstant.ByteArrayTypeCode import sigma.ast.syntax.{BoolValue, SValue} import sigma.crypto.EcPointType import sigma.util.Extensions.{BigIntegerOps, EcpOps, SigmaBooleanOps} + import scala.annotation.nowarn class ConstantSerializerSpecification extends TableSerializationSpecification { @@ -25,22 +26,29 @@ class ConstantSerializerSpecification extends TableSerializationSpecification { implicit val wWrapped = wrappedTypeGen(tpe) implicit val tT = Evaluation.stypeToRType(tpe) implicit val tag = tT.classTag + + val withVersion = if (tpe == SHeader) { + Some(VersionContext.V6SoftForkVersion) + } else { + None + } + forAll { xs: Array[T#WrappedType] => implicit val tAny = sigma.AnyType - roundTripTest(Constant[SCollection[T]](xs.toColl, SCollection(tpe))) - roundTripTest(Constant[SType](xs.toColl.map(x => (x, x)).asWrappedType, SCollection(STuple(tpe, tpe)))) // pairs are special case + roundTripTest(Constant[SCollection[T]](xs.toColl, SCollection(tpe)), withVersion) + roundTripTest(Constant[SType](xs.toColl.map(x => (x, x)).asWrappedType, SCollection(STuple(tpe, tpe))), withVersion) // pairs are special case val triples = xs.toColl.map(x => TupleColl(x, x, x)).asWrappedType - roundTripTest(Constant[SType](triples, SCollection(STuple(tpe, tpe, tpe)))) + roundTripTest(Constant[SType](triples, SCollection(STuple(tpe, tpe, tpe))), withVersion) val quartets = xs.toColl.map(x => TupleColl(x, x, x, x)).asWrappedType - roundTripTest(Constant[SType](quartets, SCollection(STuple(tpe, tpe, tpe, tpe)))) - roundTripTest(Constant[SCollection[SCollection[T]]](xs.toColl.map(x => Colls.fromItems(x, x)), SCollection(SCollection(tpe)))) + roundTripTest(Constant[SType](quartets, SCollection(STuple(tpe, tpe, tpe, tpe))), withVersion) + roundTripTest(Constant[SCollection[SCollection[T]]](xs.toColl.map(x => Colls.fromItems(x, x)), SCollection(SCollection(tpe))), withVersion) roundTripTest(Constant[SType]( xs.toColl.map { x => val arr = Colls.fromItems(x, x) (arr, arr) }.asWrappedType, SCollection(STuple(SCollection(tpe), SCollection(tpe))) - )) + ), withVersion) } } @@ -49,14 +57,19 @@ class ConstantSerializerSpecification extends TableSerializationSpecification { implicit val tT = Evaluation.stypeToRType(tpe) @nowarn implicit val tag = tT.classTag implicit val tAny: RType[Any] = sigma.AnyType + val withVersion = if (tpe == SHeader) { + Some(VersionContext.V6SoftForkVersion) + } else { + None + } forAll { in: (T#WrappedType, T#WrappedType) => val (x,y) = (in._1, in._2) - roundTripTest(Constant[SType]((x, y).asWrappedType, STuple(tpe, tpe))) - roundTripTest(Constant[SType](TupleColl(x, y, x).asWrappedType, STuple(tpe, tpe, tpe))) - roundTripTest(Constant[SType](TupleColl(x, y, x, y).asWrappedType, STuple(tpe, tpe, tpe, tpe))) - roundTripTest(Constant[STuple](Colls.fromItems[Any](x, y, (x, y)), STuple(tpe, tpe, STuple(tpe, tpe)))) - roundTripTest(Constant[STuple](Colls.fromItems[Any](x, y, TupleColl(x, y, x)), STuple(tpe, tpe, STuple(tpe, tpe, tpe)))) - roundTripTest(Constant[STuple](Colls.fromItems[Any](x, y, TupleColl(x, y, (x, y))), STuple(tpe, tpe, STuple(tpe, tpe, STuple(tpe, tpe))))) + roundTripTest(Constant[SType]((x, y).asWrappedType, STuple(tpe, tpe)), withVersion) + roundTripTest(Constant[SType](TupleColl(x, y, x).asWrappedType, STuple(tpe, tpe, tpe)), withVersion) + roundTripTest(Constant[SType](TupleColl(x, y, x, y).asWrappedType, STuple(tpe, tpe, tpe, tpe)), withVersion) + roundTripTest(Constant[STuple](Colls.fromItems[Any](x, y, (x, y)), STuple(tpe, tpe, STuple(tpe, tpe))), withVersion) + roundTripTest(Constant[STuple](Colls.fromItems[Any](x, y, TupleColl(x, y, x)), STuple(tpe, tpe, STuple(tpe, tpe, tpe))), withVersion) + roundTripTest(Constant[STuple](Colls.fromItems[Any](x, y, TupleColl(x, y, (x, y))), STuple(tpe, tpe, STuple(tpe, tpe, STuple(tpe, tpe)))), withVersion) } } @@ -71,6 +84,7 @@ class ConstantSerializerSpecification extends TableSerializationSpecification { forAll { x: SigmaBoolean => roundTripTest(Constant[SSigmaProp.type](x.toSigmaProp, SSigmaProp)) } forAll { x: ErgoBox => roundTripTest(Constant[SBox.type](x, SBox)) } forAll { x: AvlTree => roundTripTest(Constant[SAvlTree.type](x, SAvlTree)) } + forAll { x: Header => roundTripTest(Constant[SHeader.type](x, SHeader), Some(VersionContext.V6SoftForkVersion)) } forAll { x: Array[Byte] => roundTripTest(Constant[SByteArray](x.toColl, SByteArray)) } forAll { t: SPredefType => testCollection(t) } forAll { t: SPredefType => testTuples(t) } @@ -88,6 +102,7 @@ class ConstantSerializerSpecification extends TableSerializationSpecification { testCollection(SUnit) testCollection(SBox) testCollection(SAvlTree) + testCollection(SHeader) } private def caseObjectValue(v: SValue) = (v, Array[Byte](v.opCode)) diff --git a/interpreter/shared/src/test/scala/sigma/serialization/DataSerializerSpecification.scala b/interpreter/shared/src/test/scala/sigma/serialization/DataSerializerSpecification.scala index 2d9da3a87e..fe6f62dbe0 100644 --- a/interpreter/shared/src/test/scala/sigma/serialization/DataSerializerSpecification.scala +++ b/interpreter/shared/src/test/scala/sigma/serialization/DataSerializerSpecification.scala @@ -3,10 +3,10 @@ package sigma.serialization import java.math.BigInteger import org.ergoplatform.ErgoBox import org.scalacheck.Arbitrary._ -import sigma.data.{DataValueComparer, OptionType, RType, SigmaBoolean, TupleColl} +import sigma.data.{CBigInt, CHeader, DataValueComparer, OptionType, RType, SigmaBoolean, TupleColl} import sigma.ast.SCollection.SByteArray import sigmastate.eval._ -import sigma.{AvlTree, Colls, Evaluation, VersionContext} +import sigma.{AvlTree, Colls, Evaluation, Header, VersionContext} import sigma.ast.SType.AnyOps import sigma.ast._ import org.scalacheck.Gen @@ -23,29 +23,41 @@ import scala.reflect.ClassTag class DataSerializerSpecification extends SerializationSpecification { - def roundtrip[T <: SType](obj: T#WrappedType, tpe: T) = { - val w = SigmaSerializer.startWriter() - DataSerializer.serialize(obj, tpe, w) - val bytes = w.toBytes - val r = SigmaSerializer.startReader(bytes) - val res = DataSerializer.deserialize(tpe, r) - res shouldBe obj - - val es = CErgoTreeEvaluator.DefaultEvalSettings - val accumulator = new CostAccumulator( - initialCost = JitCost(0), - costLimit = Some(JitCost.fromBlockCost(es.scriptCostLimitInEvaluator))) - val evaluator = new CErgoTreeEvaluator( - context = null, - constants = ErgoTree.EmptyConstants, - coster = accumulator, DefaultProfiler, es) - val ok = DataValueComparer.equalDataValues(res, obj)(evaluator) - ok shouldBe true - - val randomPrefix = arrayGen[Byte].sample.get - val r2 = SigmaSerializer.startReader(randomPrefix ++ bytes, randomPrefix.length) - val res2 = DataSerializer.deserialize(tpe, r2) - res2 shouldBe obj + def roundtrip[T <: SType](obj: T#WrappedType, tpe: T, withVersion: Option[Byte] = None) = { + + def test() = { + val w = SigmaSerializer.startWriter() + DataSerializer.serialize(obj, tpe, w) + val bytes = w.toBytes + val r = SigmaSerializer.startReader(bytes) + val res = DataSerializer.deserialize(tpe, r) + res shouldBe obj + + val es = CErgoTreeEvaluator.DefaultEvalSettings + val accumulator = new CostAccumulator( + initialCost = JitCost(0), + costLimit = Some(JitCost.fromBlockCost(es.scriptCostLimitInEvaluator))) + val evaluator = new CErgoTreeEvaluator( + context = null, + constants = ErgoTree.EmptyConstants, + coster = accumulator, DefaultProfiler, es) + val ok = DataValueComparer.equalDataValues(res, obj)(evaluator) + ok shouldBe true + + val randomPrefix = arrayGen[Byte].sample.get + val r2 = SigmaSerializer.startReader(randomPrefix ++ bytes, randomPrefix.length) + val res2 = DataSerializer.deserialize(tpe, r2) + res2 shouldBe obj + } + + withVersion match { + case Some(ver) => + VersionContext.withVersions(ver, 1) { + test() + } + case None => + test() + } } def testCollection[T <: SType](tpe: T) = { @@ -53,25 +65,32 @@ class DataSerializerSpecification extends SerializationSpecification { implicit val tT = Evaluation.stypeToRType(tpe) implicit val tagT = tT.classTag implicit val tAny = sigma.AnyType + + val withVersion = if (tpe == SHeader) { + Some(VersionContext.V6SoftForkVersion) + } else { + None + } forAll { xs: Array[T#WrappedType] => - roundtrip[SCollection[T]](xs.toColl, SCollection(tpe)) - roundtrip[SType](xs.toColl.map(x => (x, x)).asWrappedType, SCollection(STuple(tpe, tpe))) + roundtrip[SCollection[T]](xs.toColl, SCollection(tpe), withVersion) + roundtrip[SType](xs.toColl.map(x => (x, x)).asWrappedType, SCollection(STuple(tpe, tpe)), withVersion) val triples = xs.toColl.map(x => TupleColl(x, x, x)).asWrappedType - roundtrip(triples, SCollection(STuple(tpe, tpe, tpe))) + roundtrip(triples, SCollection(STuple(tpe, tpe, tpe)), withVersion) val quartets = xs.toColl.map(x => TupleColl(x, x, x, x)).asWrappedType - roundtrip(quartets, SCollection(STuple(tpe, tpe, tpe, tpe))) + roundtrip(quartets, SCollection(STuple(tpe, tpe, tpe, tpe)), withVersion) val nested = xs.toColl.map(x => Colls.fromItems[T#WrappedType](x, x)) - roundtrip[SCollection[SCollection[T]]](nested, SCollection(SCollection(tpe))) + roundtrip[SCollection[SCollection[T]]](nested, SCollection(SCollection(tpe)), withVersion) roundtrip[SType]( xs.toColl.map { x => val arr = Colls.fromItems[T#WrappedType](x, x) (arr, arr) }.asWrappedType, - SCollection(STuple(SCollection(tpe), SCollection(tpe))) + SCollection(STuple(SCollection(tpe), SCollection(tpe))), + withVersion ) } } @@ -81,14 +100,19 @@ class DataSerializerSpecification extends SerializationSpecification { val tT = Evaluation.stypeToRType(tpe) @nowarn implicit val tag: ClassTag[T#WrappedType] = tT.classTag implicit val tAny : RType[Any] = sigma.AnyType + val withVersion = if (tpe == SHeader) { + Some(VersionContext.V6SoftForkVersion) + } else { + None + } forAll { in: (T#WrappedType, T#WrappedType) => val (x,y) = (in._1, in._2) - roundtrip[SType]((x, y).asWrappedType, STuple(tpe, tpe)) - roundtrip[SType](TupleColl(x, y, x).asWrappedType, STuple(tpe, tpe, tpe)) - roundtrip[SType](TupleColl(x, y, x, y).asWrappedType, STuple(tpe, tpe, tpe, tpe)) - roundtrip[STuple](Colls.fromItems[Any](x, y, (x, y)), STuple(tpe, tpe, STuple(tpe, tpe))) - roundtrip[STuple](Colls.fromItems[Any](x, y, TupleColl(x, y, x)), STuple(tpe, tpe, STuple(tpe, tpe, tpe))) - roundtrip[STuple](Colls.fromItems[Any](x, y, TupleColl(x, y, (x, y))), STuple(tpe, tpe, STuple(tpe, tpe, STuple(tpe, tpe)))) + roundtrip[SType]((x, y).asWrappedType, STuple(tpe, tpe), withVersion) + roundtrip[SType](TupleColl(x, y, x).asWrappedType, STuple(tpe, tpe, tpe), withVersion) + roundtrip[SType](TupleColl(x, y, x, y).asWrappedType, STuple(tpe, tpe, tpe, tpe), withVersion) + roundtrip[STuple](Colls.fromItems[Any](x, y, (x, y)), STuple(tpe, tpe, STuple(tpe, tpe)), withVersion) + roundtrip[STuple](Colls.fromItems[Any](x, y, TupleColl(x, y, x)), STuple(tpe, tpe, STuple(tpe, tpe, tpe)), withVersion) + roundtrip[STuple](Colls.fromItems[Any](x, y, TupleColl(x, y, (x, y))), STuple(tpe, tpe, STuple(tpe, tpe, STuple(tpe, tpe))), withVersion) } } @@ -129,6 +153,7 @@ class DataSerializerSpecification extends SerializationSpecification { forAll { x: ErgoBox => roundtrip[SBox.type](x, SBox) } forAll { x: AvlTree => roundtrip[SAvlTree.type](x, SAvlTree) } forAll { x: Array[Byte] => roundtrip[SByteArray](x.toColl, SByteArray) } + forAll { x: Header => roundtrip[SHeader.type](x, SHeader, Some(VersionContext.V6SoftForkVersion)) } forAll { t: SPredefType => testCollection(t) } forAll { t: SPredefType => testTuples(t) } forAll { t: SPredefType => testOption(t) } @@ -159,6 +184,42 @@ class DataSerializerSpecification extends SerializationSpecification { t.isInstanceOf[SerializerException] && t.getMessage.contains(s"BigInt value doesn't not fit into ${SBigInt.MaxSizeInBytes} bytes") }) + } + property("nuanced versioned test for header roundtrip") { + VersionContext.withVersions(VersionContext.V6SoftForkVersion, 1) { + forAll { x: Header => roundtrip[SHeader.type](x, SHeader) } + } + + an[SerializerException] should be thrownBy ( + VersionContext.withVersions((VersionContext.V6SoftForkVersion - 1).toByte, 1) { + val h = headerGen.sample.get + roundtrip[SHeader.type](h, SHeader) + }) + } + + property("header vector") { + val header = CHeader( + 0.toByte, + Helpers.decodeBytes("7a7fe5347f09017818010062000001807f86808000ff7f66ffb07f7ad27f3362"), + Helpers.decodeBytes("c1d70ad9b1ffc1fb9a715fff19807f2401017fcd8b73db017f1cff77727fff08"), + Helpers.decodeBytes("54d23dd080006bdb56800100356080935a80ffb77e90b800057f00661601807f17"), + Helpers.decodeBytes("5e7f1164ccd0990080c501fc0e0181cb387fc17f00ff00c7d5ff767f91ff5e68"), + -7421721754642387858L, + -4826493284887861030L, + 10, + Helpers.decodeBytes("e580c88001ff6fc89c5501017f80e001ff0101fe48c153ff7f00666b80d780ab"), + Helpers.decodeGroupElement("03e7f2875298fddd933c2e0a38968fe85bdeeb70dd8b389559a1d36e2ff1b58fc5"), + Helpers.decodeGroupElement("034e2d3b5f9e409e3ae8a2e768340760362ca33764eda5855f7a43487f14883300"), + Helpers.decodeBytes("974651c9efff7f00"), + CBigInt(new BigInteger("478e827dfa1e4b57", 16)), + Helpers.decodeBytes("01ff13"), + Colls.emptyColl + ) + + VersionContext.withVersions(VersionContext.V6SoftForkVersion, 1) { + 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 1db166c685..f93f0ccaf7 100644 --- a/interpreter/shared/src/test/scala/sigma/serialization/MethodCallSerializerSpecification.scala +++ b/interpreter/shared/src/test/scala/sigma/serialization/MethodCallSerializerSpecification.scala @@ -45,4 +45,27 @@ class MethodCallSerializerSpecification extends SerializationSpecification { } ) } + + property("MethodCall deserialization round trip for Header.checkPow") { + def code = { + val bi = HeaderConstant(headerGen.sample.get) + val expr = MethodCall(bi, + SHeaderMethods.checkPowMethod, + Vector(), + Map() + ) + roundTripTest(expr) + } + + VersionContext.withVersions(VersionContext.V6SoftForkVersion, 1) { + code + } + + an[Exception] should be thrownBy ( + VersionContext.withVersions((VersionContext.V6SoftForkVersion - 1).toByte, 1) { + code + } + ) + } + } diff --git a/interpreter/shared/src/test/scala/sigma/serialization/SerializationSpecification.scala b/interpreter/shared/src/test/scala/sigma/serialization/SerializationSpecification.scala index 30ae6af19b..aa7a8722ba 100644 --- a/interpreter/shared/src/test/scala/sigma/serialization/SerializationSpecification.scala +++ b/interpreter/shared/src/test/scala/sigma/serialization/SerializationSpecification.scala @@ -8,6 +8,7 @@ import org.scalacheck.Arbitrary._ import org.scalatest.matchers.should.Matchers import org.scalatest.propspec.AnyPropSpec import org.scalatestplus.scalacheck.{ScalaCheckDrivenPropertyChecks, ScalaCheckPropertyChecks} +import sigma.VersionContext import sigma.ast.SType import sigma.ast._ import sigmastate.helpers.NegativeTesting @@ -26,10 +27,20 @@ trait SerializationSpecification extends AnyPropSpec with ValidationSpecification with NegativeTesting { - protected def roundTripTest[V <: Value[_ <: SType]](v: V): Assertion = { - val bytes = ValueSerializer.serialize(v) - predefinedBytesTest(v, bytes) - predefinedBytesTestNotFomZeroElement(bytes, v) + protected def roundTripTest[V <: Value[_ <: SType]](v: V, withVersion: Option[Byte] = None): Assertion = { + def test() = { + val bytes = ValueSerializer.serialize(v) + predefinedBytesTest(v, bytes) + predefinedBytesTestNotFomZeroElement(bytes, v) + } + withVersion match { + case Some(ver) => + VersionContext.withVersions(ver, 0) { + test() + } + case None => + test() + } } protected def predefinedBytesTest[V <: Value[_ <: SType]](v: V, bytes: Array[Byte]): Assertion = { @@ -41,7 +52,7 @@ trait SerializationSpecification extends AnyPropSpec r.positionLimit shouldBe positionLimitBefore } - //check that pos and consumed are being implented correctly + //check that pos and consumed are being implemented correctly protected def predefinedBytesTestNotFomZeroElement[V <: Value[_ <: SType]](bytes: Array[Byte], v: V): Assertion = { val randomInt = Gen.chooseNum(1, 20).sample.get val randomBytes = Gen.listOfN(randomInt, arbByte.arbitrary).sample.get.toArray 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 d4971f88c2..c9fc8f2c93 100644 --- a/interpreter/shared/src/test/scala/sigma/serialization/generators/ObjectGenerators.scala +++ b/interpreter/shared/src/test/scala/sigma/serialization/generators/ObjectGenerators.scala @@ -8,7 +8,6 @@ import org.scalacheck.Arbitrary._ import org.scalacheck.Gen.{choose, frequency} import org.scalacheck.util.Buildable import org.scalacheck.{Arbitrary, Gen} -import sigma.data._ import scorex.crypto.authds.{ADDigest, ADKey} import scorex.util.encode.{Base58, Base64} import scorex.util.{ModifierId, bytesToId} @@ -27,6 +26,7 @@ import sigma.util.Extensions.EcpOps import sigma.validation.{ChangedRule, DisabledRule, EnabledRule, ReplacedRule, RuleStatus} import sigma.validation.ValidationRules.FirstRuleId import ErgoTree.ZeroHeader +import sigma.data.{AvlTreeData, AvlTreeFlags, CAND, CBox, COR, CTHRESHOLD, Digest32Coll, ProveDHTuple, ProveDlog, RType, SigmaBoolean} import sigma.eval.Extensions.{EvalIterableOps, SigmaBooleanOps} import sigma.eval.SigmaDsl import sigma.interpreter.{ContextExtension, ProverResult} @@ -311,6 +311,7 @@ trait ObjectGenerators extends TypeGenerators case SAvlTree => arbAvlTree case SAny => arbAnyVal case SUnit => arbUnit + case SHeader => arbHeader case opt: SOption[a] => Arbitrary(frequency((5, None), (5, for (x <- wrappedTypeGen(opt.elemType)) yield Some(x)))) }).asInstanceOf[Arbitrary[T#WrappedType]].arbitrary @@ -694,7 +695,6 @@ trait ObjectGenerators extends TypeGenerators } yield ErgoTree.withSegregation(ZeroHeader, prop) def headerGen(stateRoot: AvlTree, parentId: Coll[Byte]): Gen[Header] = for { - id <- modifierIdBytesGen version <- arbByte.arbitrary adProofsRoot <- digest32Gen transactionRoot <- digest32Gen @@ -707,8 +707,10 @@ trait ObjectGenerators extends TypeGenerators powNonce <- nonceBytesGen powDistance <- arbBigInt.arbitrary votes <- minerVotesGen - } yield CHeader(id, version, parentId, adProofsRoot, stateRoot, transactionRoot, timestamp, nBits, - height, extensionRoot, minerPk.toGroupElement, powOnetimePk.toGroupElement, powNonce, powDistance, votes) + unparsedBytes <- collOfRange(0, 32, arbByte.arbitrary) + } yield CHeader(version, parentId, adProofsRoot, stateRoot.digest, transactionRoot, timestamp, nBits, + height, extensionRoot, minerPk.toGroupElement, powOnetimePk.toGroupElement, powNonce, powDistance, votes, + if(version > HeaderVersion.Interpreter60Version){ unparsedBytes } else {Colls.emptyColl[Byte]}) lazy val headerGen: Gen[Header] = for { stateRoot <- avlTreeGen 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 81073c4849..70a215e831 100644 --- a/interpreter/shared/src/test/scala/sigma/serialization/generators/TypeGenerators.scala +++ b/interpreter/shared/src/test/scala/sigma/serialization/generators/TypeGenerators.scala @@ -16,12 +16,13 @@ trait TypeGenerators { implicit val boxTypeGen: Gen[SBox.type] = Gen.const(SBox) implicit val avlTreeTypeGen: Gen[SAvlTree.type] = Gen.const(SAvlTree) implicit val optionSigmaPropTypeGen: Gen[SOption[SSigmaProp.type]] = Gen.const(SOption(SSigmaProp)) + implicit val headerTypeGen: Gen[SHeader.type] = Gen.const(SHeader) implicit val primTypeGen: Gen[SPrimType] = Gen.oneOf[SPrimType](SBoolean, SByte, SShort, SInt, SLong, SBigInt, SGroupElement, SSigmaProp, SUnit) implicit val arbPrimType: Arbitrary[SPrimType] = Arbitrary(primTypeGen) implicit val predefTypeGen: Gen[SPredefType] = - Gen.oneOf[SPredefType](SBoolean, SByte, SShort, SInt, SLong, SBigInt, SGroupElement, SSigmaProp, SUnit, SBox, SAvlTree) + Gen.oneOf[SPredefType](SBoolean, SByte, SShort, SInt, SLong, SBigInt, SGroupElement, SSigmaProp, SUnit, SBox, SAvlTree, SHeader) implicit val arbPredefType: Arbitrary[SPredefType] = Arbitrary(predefTypeGen) implicit def genToArbitrary[T: Gen]: Arbitrary[T] = Arbitrary(implicitly[Gen[T]]) diff --git a/interpreter/shared/src/test/scala/special/sigma/SigmaTestingData.scala b/interpreter/shared/src/test/scala/special/sigma/SigmaTestingData.scala index f113a484ef..b8bf76cacf 100644 --- a/interpreter/shared/src/test/scala/special/sigma/SigmaTestingData.scala +++ b/interpreter/shared/src/test/scala/special/sigma/SigmaTestingData.scala @@ -12,7 +12,7 @@ import scorex.crypto.hash.{Blake2b256, Digest32} import scorex.util.ModifierId import sigma.ast._ import sigma.Extensions.ArrayOps -import sigmastate.eval.{CHeader, CPreHeader} +import sigmastate.eval.CPreHeader import sigmastate.helpers.TestingCommons import sigma.serialization.ErgoTreeSerializer import sigma.serialization.generators.ObjectGenerators @@ -240,17 +240,16 @@ trait SigmaTestingData extends TestingCommons with ObjectGenerators { def createAvlTreeData() = AvlTreeData( ErgoAlgos.decodeUnsafe("010180017f7f7b7f720c00007f7f7f0f01e857a626f37f1483d06af8077a008080").toColl, - AvlTreeFlags(false, true, false), - 728138553, - Some(2147483647) + AvlTreeFlags(true, true, true), + 32, + None ) val h1_instances = new CloneSet(1000, CHeader( - Helpers.decodeBytes("957f008001808080ffe4ffffc8f3802401df40006aa05e017fa8d3f6004c804a"), 0.toByte, Helpers.decodeBytes("0180dd805b0000ff5400b997fd7f0b9b00de00fb03c47e37806a8186b94f07ff"), Helpers.decodeBytes("01f07f60d100ffb970c3007f60ff7f24d4070bb8fffa7fca7f34c10001ffe39d"), - CAvlTree(createAvlTreeData()), + CAvlTree(createAvlTreeData()).digest, Helpers.decodeBytes("804101ff01000080a3ffbd006ac080098df132a7017f00649311ec0e00000100"), 1L, -1L, @@ -260,14 +259,15 @@ trait SigmaTestingData extends TestingCommons with ObjectGenerators { Helpers.decodeGroupElement("0361299207fa392231e23666f6945ae3e867b978e021d8d702872bde454e9abe9c"), Helpers.decodeBytes("7f4f09012a807f01"), CBigInt(new BigInteger("-e24990c47e15ed4d0178c44f1790cc72155d516c43c3e8684e75db3800a288", 16)), - Helpers.decodeBytes("7f0180") + Helpers.decodeBytes("7f0180"), + Colls.emptyColl[Byte] )) def create_h1(): Header = h1_instances.getNext val h1: Header = create_h1() - val h2: Header = create_h1().asInstanceOf[CHeader].copy(height = 2) + val h2: Header = new CHeader(h1.asInstanceOf[CHeader].wrappedValue.copy(height = 2)) val dlog_instances = new CloneSet(1000, ProveDlog( SigmaDsl.toECPoint(create_ge1()).asInstanceOf[EcPointType] diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/GraphBuilding.scala b/sc/shared/src/main/scala/sigma/compiler/ir/GraphBuilding.scala index 7c7b80d39a..7485895efb 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/GraphBuilding.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/GraphBuilding.scala @@ -1,6 +1,7 @@ package sigma.compiler.ir import org.ergoplatform._ +import sigma.ast.SType.tT import sigma.ast.TypeCodes.LastConstantCode import sigma.ast.Value.Typed import sigma.ast.syntax.{SValue, ValueOps} @@ -13,7 +14,7 @@ import sigma.data.{CSigmaDslBuilder, ExactIntegral, ExactNumeric, ExactOrdering, import sigma.exceptions.GraphBuildingException import sigma.serialization.OpCodes import sigma.util.Extensions.ByteOps -import sigma.{SigmaException, ast} +import sigma.{SigmaException, VersionContext, ast} import sigmastate.interpreter.Interpreter.ScriptEnv import scala.collection.mutable.ArrayBuffer @@ -928,7 +929,7 @@ trait GraphBuilding extends Base with DefRewriting { IR: IRContext => sigmaDslBuilder.decodePoint(bytes) // fallback rule for MethodCall, should be the last case in the list - case sigma.ast.MethodCall(obj, method, args, _) => + case sigma.ast.MethodCall(obj, method, args, typeSubst) => val objV = eval(obj) val argsV = args.map(eval) (objV, method.objType) match { @@ -1017,6 +1018,10 @@ 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 => + val c1 = asRep[Int](argsV(0)) + val c2 = stypeToElem(typeSubst.apply(tT)) + box.getReg(c1)(c2) case _ => throwError } case (ctx: Ref[Context]@unchecked, SContextMethods) => method.name match { @@ -1137,6 +1142,8 @@ trait GraphBuilding extends Base with DefRewriting { IR: IRContext => h.powDistance case SHeaderMethods.votesMethod.name => h.votes + case SHeaderMethods.checkPowMethod.name if VersionContext.current.isV6SoftForkActivated => + h.checkPow case _ => throwError } case (g: Ref[SigmaDslBuilder]@unchecked, SGlobalMethods) => method.name match { diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/GraphIRReflection.scala b/sc/shared/src/main/scala/sigma/compiler/ir/GraphIRReflection.scala index 69736a0224..d4512e1297 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/GraphIRReflection.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/GraphIRReflection.scala @@ -407,6 +407,9 @@ object GraphIRReflection { }, mkMethod(clazz, "powDistance", Array[Class[_]]()) { (obj, args) => obj.asInstanceOf[ctx.Header].powDistance + }, + mkMethod(clazz, "checkPow", Array[Class[_]]()) { (obj, args) => + obj.asInstanceOf[ctx.Header].checkPow } ) ) diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/IRContext.scala b/sc/shared/src/main/scala/sigma/compiler/ir/IRContext.scala index c60bc0882f..a22962f987 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/IRContext.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/IRContext.scala @@ -153,7 +153,7 @@ trait IRContext override def invokeUnlifted(e: Elem[_], mc: MethodCall, dataEnv: DataEnv): Any = e match { case _: CollElem[_,_] => mc match { case CollMethods.map(_, f) => - val newMC = mc.copy(args = mc.args :+ f.elem.eRange)(mc.resultType, mc.isAdapterCall) + val newMC = mc.copy(args = mc.args :+ f.elem.eRange)(mc.resultType, mc.isAdapterCall, mc.typeSubst) super.invokeUnlifted(e, newMC, dataEnv) case _ => super.invokeUnlifted(e, mc, dataEnv) diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/MethodCalls.scala b/sc/shared/src/main/scala/sigma/compiler/ir/MethodCalls.scala index 876f0e9d7e..089b76cae4 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/MethodCalls.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/MethodCalls.scala @@ -1,6 +1,7 @@ package sigma.compiler.ir import debox.{cfor, Buffer => DBuffer} +import sigma.ast.{SType, STypeVar} import sigma.compiler.DelayInvokeException import sigma.reflection.RMethod import sigma.util.CollectionUtil.TraversableOps @@ -26,7 +27,9 @@ trait MethodCalls extends Base { self: IRContext => * given `method`. */ case class MethodCall private[MethodCalls](receiver: Sym, method: RMethod, args: Seq[AnyRef], neverInvoke: Boolean) - (val resultType: Elem[Any], val isAdapterCall: Boolean = false) extends Def[Any] { + (val resultType: Elem[Any], + val isAdapterCall: Boolean = false, + val typeSubst: Map[STypeVar, SType]) extends Def[Any] { override def mirror(t: Transformer): Ref[Any] = { val len = args.length @@ -99,9 +102,14 @@ trait MethodCalls extends Base { self: IRContext => } /** Creates new MethodCall node and returns its node ref. */ - def mkMethodCall(receiver: Sym, method: RMethod, args: Seq[AnyRef], - neverInvoke: Boolean, isAdapterCall: Boolean, resultElem: Elem[_]): Sym = { - reifyObject(MethodCall(receiver, method, args, neverInvoke)(asElem[Any](resultElem), isAdapterCall)) + def mkMethodCall(receiver: Sym, + method: RMethod, + args: Seq[AnyRef], + neverInvoke: Boolean, + isAdapterCall: Boolean, + resultElem: Elem[_], + typeSubst: Map[STypeVar, SType] = Map.empty): Sym = { + reifyObject(MethodCall(receiver, method, args, neverInvoke)(asElem[Any](resultElem), isAdapterCall, typeSubst)) } @tailrec diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/TreeBuilding.scala b/sc/shared/src/main/scala/sigma/compiler/ir/TreeBuilding.scala index 725e3b1d19..7b73999253 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/TreeBuilding.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/TreeBuilding.scala @@ -290,13 +290,10 @@ trait TreeBuilding extends Base { IR: IRContext => mkExtractAmount(box.asBox) case BoxM.propositionBytes(In(box)) => mkExtractScriptBytes(box.asBox) - case BoxM.getReg(In(box), regId, _) => + case BoxM.getReg(In(box), regId, _) if regId.isConst => val tpe = elemToSType(s.elem).asOption - if (regId.isConst) - mkExtractRegisterAs(box.asBox, ErgoBox.allRegisters(valueFromRep(regId)), tpe) - else - error(s"Non constant expressions (${regId.node}) are not supported in getReg") - case BoxM.creationInfo(In(box)) => + mkExtractRegisterAs(box.asBox, ErgoBox.allRegisters(valueFromRep(regId)), tpe) + case BoxM.creationInfo(In(box)) => mkExtractCreationInfo(box.asBox) case BoxM.id(In(box)) => mkExtractId(box.asBox) @@ -399,13 +396,14 @@ trait TreeBuilding extends Base { IR: IRContext => mkMultiplyGroup(obj.asGroupElement, arg.asGroupElement) // Fallback MethodCall rule: should be the last in this list of cases - case Def(MethodCall(objSym, m, argSyms, _)) => + case Def(mc @ MethodCall(objSym, m, argSyms, _)) => val obj = recurse[SType](objSym) val args = argSyms.collect { case argSym: Sym => recurse[SType](argSym) } MethodsContainer.getMethod(obj.tpe, m.getName) match { case Some(method) => - val specMethod = method.specializeFor(obj.tpe, args.map(_.tpe)) - builder.mkMethodCall(obj, specMethod, args.toIndexedSeq, Map()) + val typeSubst = mc.typeSubst + val specMethod = method.specializeFor(obj.tpe, args.map(_.tpe)).withConcreteTypes(typeSubst) + builder.mkMethodCall(obj, specMethod, args.toIndexedSeq, typeSubst) case None => error(s"Cannot find method ${m.getName} in object $obj") } diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/SigmaDslUnit.scala b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/SigmaDslUnit.scala index 2a6a341686..f38748bbe4 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/SigmaDslUnit.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/SigmaDslUnit.scala @@ -78,6 +78,7 @@ import scalan._ def powNonce: Ref[Coll[Byte]]; def powDistance: Ref[BigInt]; def votes: Ref[Coll[Byte]] + def checkPow: Ref[Boolean] }; trait Context extends Def[Context] { def OUTPUTS: Ref[Coll[Box]]; diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/SigmaDslImpl.scala b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/SigmaDslImpl.scala index c113cb7de3..5c366d5b7c 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/SigmaDslImpl.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/SigmaDslImpl.scala @@ -8,6 +8,8 @@ import sigma.compiler.ir.wrappers.sigma.impl.SigmaDslDefs import scala.collection.compat.immutable.ArraySeq package impl { + import sigma.Evaluation + import sigma.ast.SType.tT import sigma.compiler.ir.meta.ModuleInfo import sigma.compiler.ir.wrappers.sigma.SigmaDsl import sigma.compiler.ir.{Base, GraphIRReflection, IRContext} @@ -620,10 +622,11 @@ object Box extends EntityObject("Box") { } override def getReg[T](i: Ref[Int])(implicit cT: Elem[T]): Ref[WOption[T]] = { + val st = Evaluation.rtypeToSType(cT.sourceType) asRep[WOption[T]](mkMethodCall(self, BoxClass.getMethod("getReg", classOf[Sym], classOf[Elem[_]]), Array[AnyRef](i, cT), - true, false, element[WOption[T]])) + true, false, element[WOption[T]], Map(tT -> st) )) } override def tokens: Ref[Coll[(Coll[Byte], Long)]] = { @@ -695,10 +698,11 @@ object Box extends EntityObject("Box") { } def getReg[T](i: Ref[Int])(implicit cT: Elem[T]): Ref[WOption[T]] = { + val st = Evaluation.rtypeToSType(cT.sourceType) asRep[WOption[T]](mkMethodCall(source, BoxClass.getMethod("getReg", classOf[Sym], classOf[Elem[_]]), Array[AnyRef](i, cT), - true, true, element[WOption[T]])) + true, true, element[WOption[T]], Map(tT -> st))) } def tokens: Ref[Coll[(Coll[Byte], Long)]] = { @@ -1368,6 +1372,13 @@ object Header extends EntityObject("Header") { ArraySeq.empty, true, false, element[Coll[Byte]])) } + + override def checkPow: Ref[Boolean] = { + asRep[Boolean](mkMethodCall(self, + HeaderClass.getMethod("checkPow"), + ArraySeq.empty, + true, false, element[Boolean])) + } } implicit object LiftableHeader @@ -1492,6 +1503,13 @@ object Header extends EntityObject("Header") { ArraySeq.empty, true, true, element[Coll[Byte]])) } + + def checkPow: Ref[Boolean] = { + asRep[Boolean](mkMethodCall(source, + HeaderClass.getMethod("checkPow"), + ArraySeq.empty, + true, true, element[Boolean])) + } } // entityUnref: single unref method for each type family @@ -1509,7 +1527,7 @@ object Header extends EntityObject("Header") { override protected def collectMethods: Map[RMethod, MethodDesc] = { super.collectMethods ++ Elem.declaredMethods(RClass(classOf[Header]), RClass(classOf[SHeader]), Set( - "id", "version", "parentId", "ADProofsRoot", "stateRoot", "transactionsRoot", "timestamp", "nBits", "height", "extensionRoot", "minerPk", "powOnetimePk", "powNonce", "powDistance", "votes" + "id", "version", "parentId", "ADProofsRoot", "stateRoot", "transactionsRoot", "timestamp", "nBits", "height", "extensionRoot", "minerPk", "powOnetimePk", "powNonce", "powDistance", "votes", "checkPow" )) } } diff --git a/sc/shared/src/main/scala/sigma/compiler/phases/SigmaTyper.scala b/sc/shared/src/main/scala/sigma/compiler/phases/SigmaTyper.scala index ac30a6cd0a..5f5e430e47 100644 --- a/sc/shared/src/main/scala/sigma/compiler/phases/SigmaTyper.scala +++ b/sc/shared/src/main/scala/sigma/compiler/phases/SigmaTyper.scala @@ -136,7 +136,7 @@ class SigmaTyper(val builder: SigmaBuilder, case Apply(ApplyTypes(sel @ Select(obj, n, _), Seq(rangeTpe)), args) => val newObj = assignType(env, obj) val newArgs = args.map(assignType(env, _)) - obj.tpe match { + newObj.tpe match { case p: SProduct => MethodsContainer.getMethod(p, n) match { case Some(method: SMethod) => @@ -160,10 +160,10 @@ class SigmaTyper(val builder: SigmaBuilder, case Some(method) => error(s"Don't know how to handle method $method in obj $p", sel.sourceContext) case None => - throw new MethodNotFound(s"Cannot find method '$n' in in the object $obj of Product type $p", obj.sourceContext.toOption) + throw new MethodNotFound(s"Cannot find method '$n' in in the object $newObj of Product type $p", newObj.sourceContext.toOption) } case _ => - error(s"Cannot get field '$n' in in the object $obj of non-product type ${obj.tpe}", sel.sourceContext) + error(s"Cannot get field '$n' in in the object $newObj of non-product type ${newObj.tpe}", sel.sourceContext) } case app @ Apply(sel @ Select(obj, n, _), args) => diff --git a/sc/shared/src/test/scala/sigma/LanguageSpecificationV5.scala b/sc/shared/src/test/scala/sigma/LanguageSpecificationV5.scala index af4f93d861..0d9a032a16 100644 --- a/sc/shared/src/test/scala/sigma/LanguageSpecificationV5.scala +++ b/sc/shared/src/test/scala/sigma/LanguageSpecificationV5.scala @@ -4292,7 +4292,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => property("Header properties equivalence") { verifyCases( Seq((h1, Expected(Success( - Helpers.decodeBytes("957f008001808080ffe4ffffc8f3802401df40006aa05e017fa8d3f6004c804a")), + Helpers.decodeBytes("cea31f0e0a794b103f65f8296a22ac8ff214e1bc75442186b90df4844c978e81")), cost = 1766, methodCostDetails(SHeaderMethods.idMethod, 10), 1766, Seq.fill(4)(2002)))), existingPropTest("id", { (x: Header) => x.id })) @@ -4430,18 +4430,10 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => ) val header = CHeader( - Helpers.decodeBytes("1c597f88969600d2fffffdc47f00d8ffc555a9e85001000001c505ff80ff8f7f"), 0.toByte, Helpers.decodeBytes("7a7fe5347f09017818010062000001807f86808000ff7f66ffb07f7ad27f3362"), Helpers.decodeBytes("c1d70ad9b1ffc1fb9a715fff19807f2401017fcd8b73db017f1cff77727fff08"), - CAvlTree( - AvlTreeData( - ErgoAlgos.decodeUnsafe("54d23dd080006bdb56800100356080935a80ffb77e90b800057f00661601807f17").toColl, - AvlTreeFlags(true, true, false), - 2147483647, - None - ) - ), + Helpers.decodeBytes("54d23dd080006bdb56800100356080935a80ffb77e90b800057f00661601807f17"), Helpers.decodeBytes("5e7f1164ccd0990080c501fc0e0181cb387fc17f00ff00c7d5ff767f91ff5e68"), -7421721754642387858L, -4826493284887861030L, @@ -4451,7 +4443,8 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => Helpers.decodeGroupElement("034e2d3b5f9e409e3ae8a2e768340760362ca33764eda5855f7a43487f14883300"), Helpers.decodeBytes("974651c9efff7f00"), CBigInt(new BigInteger("478e827dfa1e4b57", 16)), - Helpers.decodeBytes("01ff13") + Helpers.decodeBytes("01ff13"), + Colls.emptyColl ) val ctx = CContext( @@ -4459,7 +4452,7 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => headers = Coll[Header](header), preHeader = CPreHeader( 0.toByte, - Helpers.decodeBytes("1c597f88969600d2fffffdc47f00d8ffc555a9e85001000001c505ff80ff8f7f"), + header.id, -755484979487531112L, 9223372036854775807L, 11, diff --git a/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala b/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala index 382c47403c..cd851c69b7 100644 --- a/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala +++ b/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala @@ -1,10 +1,15 @@ package sigma +import org.ergoplatform.ErgoBox +import org.ergoplatform.ErgoBox.Token +import scorex.util.ModifierId +import scorex.util.encode.Base16 +import org.ergoplatform.ErgoHeader import sigma.ast.ErgoTree.ZeroHeader import sigma.ast.SCollection.SByteArray import sigma.ast.syntax.TrueSigmaProp import sigma.ast._ -import sigma.data.{CBigInt, ExactNumeric} +import sigma.data.{CBigInt, CHeader, CBox, ExactNumeric} import sigma.eval.{CostDetails, SigmaDsl, TracedCost} import sigma.util.Extensions.{BooleanOps, ByteOps, IntOps, LongOps} import sigmastate.exceptions.MethodNotFound @@ -265,9 +270,13 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite => } property("Box properties equivalence (new features)") { - // TODO v6.0: related to https://github.com/ScorexFoundation/sigmastate-interpreter/issues/416 - val getReg = newFeature((x: Box) => x.getReg[Int](1).get, - "{ (x: Box) => x.getReg[Int](1).get }", + // related to https://github.com/ScorexFoundation/sigmastate-interpreter/issues/416 + def getReg = newFeature((x: Box) => x.getReg[Long](0).get, + "{ (x: Box) => x.getReg[Long](0).get }", + FuncValue( + Array((1, SBox)), + OptionGet(ExtractRegisterAs(ValUse(1, SBox), ErgoBox.R0, SOption(SLong))) + ), sinceVersion = VersionContext.V6SoftForkVersion) if (activatedVersionInTests < VersionContext.V6SoftForkVersion) { @@ -277,6 +286,16 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite => forAll { box: Box => Seq(getReg).foreach(_.checkEquality(box)) } + } else { + val value = 10L + val box = CBox(new ErgoBox(value, TrueTree, Colls.emptyColl[Token], Map.empty, + ModifierId @@ Base16.encode(Array.fill(32)(0)), 0, 0)) + verifyCases( + Seq( + box -> new Expected(ExpectedResult(Success(value), None)) + ), + getReg + ) } } @@ -463,4 +482,35 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite => tree.root shouldBe t2.root } + property("Header new methods") { + + def checkPoW = { + newFeature( + { (x: Header) => x.checkPow}, + "{ (x: Header) => x.checkPow }", + FuncValue( + Array((1, SHeader)), + MethodCall.typed[Value[SBoolean.type]]( + ValUse(1, SHeader), + SHeaderMethods.checkPowMethod, + IndexedSeq(), + Map() + ) + ), + sinceVersion = VersionContext.V6SoftForkVersion + ) + } + + // bytes of real mainnet block header at height 614,440 + val headerBytes = "02ac2101807f0000ca01ff0119db227f202201007f62000177a080005d440896d05d3f80dcff7f5e7f59007294c180808d0158d1ff6ba10000f901c7f0ef87dcfff17fffacb6ff7f7f1180d2ff7f1e24ffffe1ff937f807f0797b9ff6ebdae007e5c8c00b8403d3701557181c8df800001b6d5009e2201c6ff807d71808c00019780f087adb3fcdbc0b3441480887f80007f4b01cf7f013ff1ffff564a0000b9a54f00770e807f41ff88c00240000080c0250000000003bedaee069ff4829500b3c07c4d5fe6b3ea3d3bf76c5c28c1d4dcdb1bed0ade0c0000000000003105" + val header1 = new CHeader(ErgoHeader.sigmaSerializer.fromBytes(Base16.decode(headerBytes).get)) + + verifyCases( + Seq( + header1 -> new Expected(ExpectedResult(Success(true), None)) + ), + checkPoW + ) + } + } diff --git a/sc/shared/src/test/scala/sigma/SigmaDslTesting.scala b/sc/shared/src/test/scala/sigma/SigmaDslTesting.scala index 58873449b4..4410786fd4 100644 --- a/sc/shared/src/test/scala/sigma/SigmaDslTesting.scala +++ b/sc/shared/src/test/scala/sigma/SigmaDslTesting.scala @@ -872,10 +872,14 @@ class SigmaDslTesting extends AnyPropSpec extends Feature[A, B] { override def isSupportedIn(vc: VersionContext): Boolean = - vc.activatedVersion >= sinceVersion && vc.ergoTreeVersion >= sinceVersion + vc.activatedVersion >= sinceVersion override def scalaFunc: A => B = { x => - sys.error(s"Semantic Scala function is not defined for old implementation: $this") + if (isSupportedIn(VersionContext.current)) { + scalaFuncNew(x) + } else { + sys.error(s"Semantic Scala function is not defined for old implementation: $this") + } } implicit val cs = compilerSettingsInTests @@ -925,8 +929,14 @@ class SigmaDslTesting extends AnyPropSpec printTestCases: Boolean, failOnTestVectors: Boolean): Unit = { val funcRes = checkEquality(input, printTestCases) - funcRes.isFailure shouldBe true - Try(scalaFunc(input)) shouldBe expected.value + if(!isSupportedIn(VersionContext.current)) { + funcRes.isFailure shouldBe true + } + if(isSupportedIn(VersionContext.current)) { + Try(scalaFunc(input)) shouldBe expected.value + } else { + Try(scalaFunc(input)).isFailure shouldBe true + } } } diff --git a/sc/shared/src/test/scala/sigmastate/ErgoTreeSpecification.scala b/sc/shared/src/test/scala/sigmastate/ErgoTreeSpecification.scala index 7539bd5e48..c3c20422e9 100644 --- a/sc/shared/src/test/scala/sigmastate/ErgoTreeSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/ErgoTreeSpecification.scala @@ -21,14 +21,14 @@ import sigma.compiler.CompilerSettings import sigma.eval.EvalSettings import sigma.exceptions.{CostLimitException, InterpreterException} import sigma.serialization.ErgoTreeSerializer.DefaultSerializer -import sigmastate.Plus +import sigmastate.{CrossVersionProps, Plus} import sigmastate.utils.Helpers.TryOps /** Regression tests with ErgoTree related test vectors. * This test vectors verify various constants which are consensus critical and should not change. */ -class ErgoTreeSpecification extends SigmaDslTesting with ContractsTestkit { +class ErgoTreeSpecification extends SigmaDslTesting with ContractsTestkit with CrossVersionProps { property("Value.sourceContext") { val srcCtx = SourceContext.fromParserIndex(0, "") @@ -316,7 +316,7 @@ class ErgoTreeSpecification extends SigmaDslTesting with ContractsTestkit { // NOTE, the type code constants are checked above // The methodId codes as checked here, they MUST be PRESERVED. // The following table should be made dependent on HF activation - val methods = Table( + def methods = Table( ("typeId", "methods", "CanHaveMethods"), (SBoolean.typeId, Seq.empty[MInfo], true), (SByte.typeId, Seq.empty[MInfo], false), @@ -367,9 +367,12 @@ class ErgoTreeSpecification extends SigmaDslTesting with ContractsTestkit { MInfo(4, BytesWithoutRefMethod), MInfo(5, IdMethod), MInfo(6, creationInfoMethod), - MInfo(7, getRegMethod), MInfo(8, tokensMethod) - ) ++ registers(idOfs = 8) + ) ++ (if (VersionContext.current.isV6SoftForkActivated) { + Seq(MInfo(7, getRegMethodV6)) + } else { + Seq(MInfo(7, getRegMethodV5)) + }) ++ registers(idOfs = 8) .zipWithIndex .map { case (m,i) => MInfo((8 + i + 1).toByte, m) }, true) }, diff --git a/sc/shared/src/test/scala/sigmastate/TestingInterpreterSpecification.scala b/sc/shared/src/test/scala/sigmastate/TestingInterpreterSpecification.scala index 1012e9a189..4ba6b1a9f7 100644 --- a/sc/shared/src/test/scala/sigmastate/TestingInterpreterSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/TestingInterpreterSpecification.scala @@ -6,18 +6,23 @@ import sigma.ast._ import sigma.ast.syntax._ import sigmastate.interpreter._ import Interpreter._ -import sigma.ast.syntax._ import org.ergoplatform._ import org.scalatest.BeforeAndAfterAll -import scorex.util.encode.Base58 +import scorex.util.encode.{Base16, Base58} +import sigma.Colls +import sigma.VersionContext.V6SoftForkVersion import sigma.VersionContext -import sigma.crypto.CryptoConstants -import sigma.data.{AvlTreeData, CAND, ProveDlog, SigmaBoolean, TrivialProp} +import sigma.data.{CAND, CAvlTree, CHeader, ProveDlog, SigmaBoolean, TrivialProp} +import sigma.interpreter.ContextExtension import sigma.util.Extensions.IntOps import sigmastate.helpers.{CompilerTestingCommons, ErgoLikeContextTesting, ErgoLikeTestInterpreter, ErgoLikeTestProvingInterpreter} import sigmastate.helpers.TestingHelpers._ -import sigma.serialization.ValueSerializer +import sigma.serialization.{GroupElementSerializer, SigmaSerializer, ValueSerializer} +import sigmastate.eval.CPreHeader +import sigmastate.helpers.ErgoLikeContextTesting.noBoxes +import sigmastate.interpreter.CErgoTreeEvaluator.DefaultEvalSettings import sigmastate.utils.Helpers._ +import sigma.util.Extensions._ import scala.util.Random @@ -30,12 +35,29 @@ class TestingInterpreterSpecification extends CompilerTestingCommons lazy val verifier = new ErgoLikeTestInterpreter - def testingContext(h: Int) = - ErgoLikeContextTesting(h, - AvlTreeData.dummy, ErgoLikeContextTesting.dummyPubkey, IndexedSeq(fakeSelf), - ErgoLikeTransaction(IndexedSeq.empty, IndexedSeq.empty), - fakeSelf, activatedVersionInTests) - .withErgoTreeVersion(ergoTreeVersionInTests) + def testingContext(h: Int = 614401) = { + // bytes of real mainnet block header at height 614,440 + val headerBytes = "02ac2101807f0000ca01ff0119db227f202201007f62000177a080005d440896d05d3f80dcff7f5e7f59007294c180808d0158d1ff6ba10000f901c7f0ef87dcfff17fffacb6ff7f7f1180d2ff7f1e24ffffe1ff937f807f0797b9ff6ebdae007e5c8c00b8403d3701557181c8df800001b6d5009e2201c6ff807d71808c00019780f087adb3fcdbc0b3441480887f80007f4b01cf7f013ff1ffff564a0000b9a54f00770e807f41ff88c00240000080c0250000000003bedaee069ff4829500b3c07c4d5fe6b3ea3d3bf76c5c28c1d4dcdb1bed0ade0c0000000000003105" + val header1 = new CHeader(ErgoHeader.sigmaSerializer.fromBytes(Base16.decode(headerBytes).get)) + + val boxesToSpend = IndexedSeq(fakeSelf) + + val preHeader = CPreHeader(activatedVersionInTests, + parentId = header1.id, + timestamp = 3, + nBits = 0, + height = h, + minerPk = GroupElementSerializer.parse(SigmaSerializer.startReader(ErgoLikeContextTesting.dummyPubkey)).toGroupElement, + votes = Colls.emptyColl[Byte] + ) + + new ErgoLikeContext( + header1.stateRoot.asInstanceOf[CAvlTree].treeData, Colls.fromArray(Array(header1)), + preHeader, noBoxes, + boxesToSpend, ErgoLikeTransaction(IndexedSeq.empty, IndexedSeq.empty), + boxesToSpend.indexOf(fakeSelf), ContextExtension.empty, vs, DefaultEvalSettings.scriptCostLimitInEvaluator, + initCost = 0L, activatedVersionInTests).withErgoTreeVersion(ergoTreeVersionInTests) + } property("Reduction to crypto #1") { forAll() { i: Int => @@ -117,7 +139,7 @@ class TestingInterpreterSpecification extends CompilerTestingCommons val dk1 = prover.dlogSecrets(0).publicImage val dk2 = prover.dlogSecrets(1).publicImage - val ctx = testingContext(99) + val ctx = testingContext() val env = Map( "dk1" -> dk1, "dk2" -> dk2, @@ -125,7 +147,9 @@ class TestingInterpreterSpecification extends CompilerTestingCommons "bytes2" -> Array[Byte](4, 5, 6), "box1" -> testBox(10, TrueTree, 0, Seq(), Map( reg1 -> IntArrayConstant(Array[Int](1, 2, 3)), - reg2 -> BoolArrayConstant(Array[Boolean](true, false, true))))) + reg2 -> BoolArrayConstant(Array[Boolean](true, false, true)) + )) + ) val prop = mkTestErgoTree(compile(env, code)(IR).asBoolValue.toSigmaProp) val challenge = Array.fill(32)(Random.nextInt(100).toByte) val proof1 = prover.prove(prop, ctx, challenge).get.proof @@ -378,6 +402,24 @@ class TestingInterpreterSpecification extends CompilerTestingCommons verifier.verify(prop3, env, proof, challenge).map(_._1).getOrElse(false) shouldBe false } + property("blake2b - test vector") { + testEval( + """ { + | val input = fromBase16("68656c6c6f20776f726c64") + | val output = fromBase16("256c83b297114d201b30179f3f0ef0cace9783622da5974326b436178aeef610") + | blake2b256(input) == output + | }""".stripMargin) + } + + property("blake2b - test vector #2") { + testEval( + """ { + | val input = fromBase16("02ac2101807f0000ca01ff0119db227f202201007f62000177a080005d440896d05d3f80dcff7f5e7f59007294c180808d0158d1ff6ba10000f901c7f0ef87dcfff17fffacb6ff7f7f1180d2ff7f1e24ffffe1ff937f807f0797b9ff6ebdae007e5c8c00b8403d3701557181c8df800001b6d5009e2201c6ff807d71808c00019780d085adb3fcdbc0b3441480887f80007f4b01cf7f013ff1ffff564a0000b9a54f00770e807f41ff88c00240000080c02500000000") + | val output = fromBase16("bdb84cda5b105c3eb522857b50a0882f88ed5bb3cc8cf3325a1edf7eeb6a0954") + | blake2b256(input) == output + | }""".stripMargin) + } + property("passing a lambda argument") { // single expression testEval( @@ -412,6 +454,29 @@ class TestingInterpreterSpecification extends CompilerTestingCommons testEval(s"""deserialize[Coll[Byte]]("$str")(0) == 2""") } + property("header.id") { + testEval( + """ { + | val h = CONTEXT.headers(0) + | val id = h.id + | id.size == 32 + | }""".stripMargin) + } + + property("checkPow") { + val source = """ { + | val h = CONTEXT.headers(0) + | h.checkPow + | } + | """.stripMargin + + if (activatedVersionInTests < V6SoftForkVersion) { + an [Exception] should be thrownBy testEval(source) + } else { + testEval(source) + } + } + override protected def afterAll(): Unit = { } diff --git a/sc/shared/src/test/scala/sigmastate/TypesSpecification.scala b/sc/shared/src/test/scala/sigmastate/TypesSpecification.scala index 9a4c5ce1b8..6d13863f26 100644 --- a/sc/shared/src/test/scala/sigmastate/TypesSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/TypesSpecification.scala @@ -13,8 +13,6 @@ class TypesSpecification extends SigmaTestingData { implicit val tWrapped = wrappedTypeGen(t) forAll { x: SPredefType#WrappedType => isValueOfType(x, t) shouldBe true - // since forall t. SHeader != t - isValueOfType(x, SHeader) shouldBe false } } } diff --git a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala index 40b6caca4d..d80e39273f 100644 --- a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala @@ -3,7 +3,9 @@ package sigmastate.utxo import org.ergoplatform.ErgoBox.{AdditionalRegisters, R6, R8} import org.ergoplatform._ import scorex.util.encode.Base16 +import org.scalatest.Assertion import sigma.Extensions.ArrayOps +import sigma.VersionContext import sigma.ast.SCollection.SByteArray import sigma.ast.SType.AnyOps import sigma.data.{AvlTreeData, CAnyValue, CSigmaDslBuilder} @@ -765,4 +767,45 @@ class BasicOpsSpecification extends CompilerTestingCommons test("subst", env, ext, hostScript, null) } + property("Box.getReg") { + def getRegTest(): Assertion = { + test("Box.getReg", env, ext, + """{ + | val x = SELF + | x.getReg[Long](0).get == SELF.value && + | x.getReg[Coll[(Coll[Byte], Long)]](2).get == SELF.tokens && + | x.getReg[Int](9).isEmpty + |}""".stripMargin, + null + ) + } + + if (VersionContext.current.isV6SoftForkActivated) { + getRegTest() + } else { + an[Exception] should be thrownBy getRegTest() + } + } + + property("Box.getReg - computable index") { + val ext: Seq[VarBinding] = Seq( + (intVar1, IntConstant(0)) + ) + def getRegTest(): Assertion = { + test("Box.getReg", env, ext, + """{ + | val x = SELF.getReg[Long](getVar[Int](1).get).get + | x == SELF.value + |}""".stripMargin, + null + ) + } + + if (VersionContext.current.isV6SoftForkActivated) { + getRegTest() + } else { + an[Exception] should be thrownBy getRegTest() + } + } + } diff --git a/sdk/js/src/main/scala/org/ergoplatform/sdk/js/Header.scala b/sdk/js/src/main/scala/org/ergoplatform/sdk/js/Header.scala index ef53e13dbd..2220c9827a 100644 --- a/sdk/js/src/main/scala/org/ergoplatform/sdk/js/Header.scala +++ b/sdk/js/src/main/scala/org/ergoplatform/sdk/js/Header.scala @@ -12,7 +12,7 @@ import scala.scalajs.js.annotation.JSExportTopLevel class Header( /** Hex representation of ModifierId of this Header */ val id: String, - /** Block version, to be increased on every soft and hardfork. */ + /** Block version, to be increased on every soft- or hard-fork. */ val version: Byte, /** Hex representation of ModifierId of the parent block */ val parentId: String, @@ -48,5 +48,7 @@ class Header( val powDistance: js.BigInt, /** Miner votes for changing system parameters. */ - val votes: String + val votes: String, + + val unparsedBytes: String ) extends js.Object diff --git a/sdk/js/src/main/scala/org/ergoplatform/sdk/js/Isos.scala b/sdk/js/src/main/scala/org/ergoplatform/sdk/js/Isos.scala index 0f50a52686..84f2b21da8 100644 --- a/sdk/js/src/main/scala/org/ergoplatform/sdk/js/Isos.scala +++ b/sdk/js/src/main/scala/org/ergoplatform/sdk/js/Isos.scala @@ -7,9 +7,10 @@ import sigma.ast.{Constant, SType} import sigma.data.Iso import sigma.data.Iso.{isoStringToArray, isoStringToColl} import sigma.data.js.{Isos => DataIsos} +import sigma.data.CHeader import sigma.interpreter.{ContextExtension, ProverResult} import sigma.js.AvlTree -import sigmastate.eval.{CHeader, CPreHeader} +import sigmastate.eval.CPreHeader import sigmastate.fleetSdkCommon.distEsmTypesBoxesMod.Box import sigmastate.fleetSdkCommon.distEsmTypesRegistersMod.NonMandatoryRegisters import sigmastate.fleetSdkCommon.distEsmTypesTokenMod.TokenAmount @@ -27,11 +28,10 @@ object Isos { implicit val isoHeader: Iso[Header, sigma.Header] = new Iso[Header, sigma.Header] { override def to(a: Header): sigma.Header = { CHeader( - id = isoStringToColl.to(a.id), version = a.version, parentId = isoStringToColl.to(a.parentId), ADProofsRoot = isoStringToColl.to(a.ADProofsRoot), - stateRoot = AvlTree.isoAvlTree.to(a.stateRoot), + stateRootDigest = AvlTree.isoAvlTree.to(a.stateRoot).digest, transactionsRoot = isoStringToColl.to(a.transactionsRoot), timestamp = sigma.js.Isos.isoBigIntToLong.to(a.timestamp), nBits = sigma.js.Isos.isoBigIntToLong.to(a.nBits), @@ -41,7 +41,8 @@ object Isos { powOnetimePk = DataIsos.isoGroupElement.to(a.powOnetimePk), powNonce = isoStringToColl.to(a.powNonce), powDistance = sigma.js.Isos.isoBigInt.to(a.powDistance), - votes = isoStringToColl.to(a.votes) + votes = isoStringToColl.to(a.votes), + unparsedBytes = isoStringToColl.to(a.unparsedBytes) ) } override def from(b: sigma.Header): Header = { @@ -61,7 +62,8 @@ object Isos { powOnetimePk = DataIsos.isoGroupElement.from(header.powOnetimePk), powNonce = isoStringToColl.from(header.powNonce), powDistance = sigma.js.Isos.isoBigInt.from(header.powDistance), - votes = isoStringToColl.from(header.votes) + votes = isoStringToColl.from(header.votes), + unparsedBytes = isoStringToColl.from(header.unparsedBytes) ) } } diff --git a/sdk/js/src/test/scala/org/ergoplatform/sdk/js/IsosSpec.scala b/sdk/js/src/test/scala/org/ergoplatform/sdk/js/IsosSpec.scala index a040731b20..31b8a84c2b 100644 --- a/sdk/js/src/test/scala/org/ergoplatform/sdk/js/IsosSpec.scala +++ b/sdk/js/src/test/scala/org/ergoplatform/sdk/js/IsosSpec.scala @@ -1,8 +1,9 @@ package org.ergoplatform.sdk.js +import io.circe.parser.parse import org.ergoplatform.ErgoBox.{AdditionalRegisters, BoxId, TokenId} import org.ergoplatform._ -import org.ergoplatform.sdk.ExtendedInputBox +import org.ergoplatform.sdk.{ExtendedInputBox, JsonCodecs} import org.ergoplatform.sdk.wallet.protocol.context.BlockchainStateContext import org.scalacheck.Arbitrary import sigma.ast.{Constant, SType} @@ -11,6 +12,7 @@ import sigma.interpreter.{ContextExtension, ProverResult} import sigma.js.AvlTree import sigma.{Coll, GroupElement} import sigma.data.js.{Isos => DataIsos} + import scala.scalajs.js class IsosSpec extends IsosSpecBase with sdk.generators.ObjectGenerators { diff --git a/sdk/shared/src/main/scala/org/ergoplatform/sdk/DataJsonEncoder.scala b/sdk/shared/src/main/scala/org/ergoplatform/sdk/DataJsonEncoder.scala index fc95b77e61..6c0c866baf 100644 --- a/sdk/shared/src/main/scala/org/ergoplatform/sdk/DataJsonEncoder.scala +++ b/sdk/shared/src/main/scala/org/ergoplatform/sdk/DataJsonEncoder.scala @@ -122,6 +122,10 @@ object DataJsonEncoder { val w = SigmaSerializer.startWriter() DataSerializer.serialize(v, tpe, w) encodeBytes(w.toBytes) + case SHeader => + val w = SigmaSerializer.startWriter() + DataSerializer.serialize(v, tpe, w) + encodeBytes(w.toBytes) case SAvlTree => val w = SigmaSerializer.startWriter() DataSerializer.serialize(v, tpe, w) @@ -203,6 +207,10 @@ object DataJsonEncoder { val str = decodeBytes(json) val r = SigmaSerializer.startReader(str) DataSerializer.deserialize(SSigmaProp, r) + case SHeader => // for Sigma < 6.0 , exception will be thrown by DataSerializer + val str = decodeBytes(json) + val r = SigmaSerializer.startReader(str) + DataSerializer.deserialize(SHeader, r) case SBox => val value = decodeData(json.hcursor.downField(s"value").focus.get, SLong) val tree = ErgoTreeSerializer.DefaultSerializer.deserializeErgoTree(decodeBytes(json.hcursor.downField(s"ergoTree").focus.get)) diff --git a/sdk/shared/src/main/scala/org/ergoplatform/sdk/JsonCodecs.scala b/sdk/shared/src/main/scala/org/ergoplatform/sdk/JsonCodecs.scala index ae14fd831a..98e8011bcc 100644 --- a/sdk/shared/src/main/scala/org/ergoplatform/sdk/JsonCodecs.scala +++ b/sdk/shared/src/main/scala/org/ergoplatform/sdk/JsonCodecs.scala @@ -12,7 +12,7 @@ import scorex.crypto.hash.Digest32 import scorex.util.ModifierId import sigma.Extensions.ArrayOps import sigma.ast.{ErgoTree, EvaluatedValue, SType} -import sigma.data.{AvlTreeData, AvlTreeFlags, CBigInt, Digest32Coll, WrapperOf} +import sigma.data.{AvlTreeData, AvlTreeFlags, CBigInt, CHeader, Digest32Coll, WrapperOf} import sigma.eval.Extensions.EvalIterableOps import sigma.eval.SigmaDsl import sigma.interpreter.{ContextExtension, ProverResult} @@ -125,13 +125,18 @@ trait JsonCodecs { "powOnetimePk" -> h.powOnetimePk.getEncoded.asJson, "powNonce" -> h.powNonce.asJson, "powDistance" -> h.powDistance.asJson, - "votes" -> h.votes.asJson + "votes" -> h.votes.asJson, + "unparsedBytes" -> h.unparsedBytes.asJson ).asJson }) + /** + * JSON decoder for Header instance. Field "unparsedBytes" is optional for now, to preserve compatibility + * with clients using older JSON decoders (before node 5.0.23). Better to add an (empty) field anyway if possible. + * This field could become mandatory in future. + */ implicit val headerDecoder: Decoder[Header] = Decoder.instance({ cursor => for { - id <- cursor.downField("id").as[Coll[Byte]] version <- cursor.downField("version").as[Byte] parentId <- cursor.downField("parentId").as[Coll[Byte]] adProofsRoot <- cursor.downField("adProofsRoot").as[Coll[Byte]] @@ -146,8 +151,10 @@ trait JsonCodecs { powNonce <- cursor.downField("powNonce").as[Coll[Byte]] powDistance <- cursor.downField("powDistance").as[sigma.BigInt] votes <- cursor.downField("votes").as[Coll[Byte]] - } yield new CHeader(id, version, parentId, adProofsRoot, stateRoot, transactionsRoot, timestamp, nBits, - height, extensionRoot, SigmaDsl.decodePoint(minerPk), SigmaDsl.decodePoint(powOnetimePk), powNonce, powDistance, votes) + unparsedBytes <- cursor.downField("unparsedBytes").as[Option[Coll[Byte]]] + } yield CHeader(version, parentId, adProofsRoot, stateRoot.digest, transactionsRoot, timestamp, nBits, + height, extensionRoot, SigmaDsl.decodePoint(minerPk), SigmaDsl.decodePoint(powOnetimePk), powNonce, powDistance, + votes, unparsedBytes.getOrElse(Colls.emptyColl)) }) implicit val preHeaderEncoder: Encoder[PreHeader] = Encoder.instance({ v: PreHeader => 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 c3f7b43af4..5835f399cb 100644 --- a/sdk/shared/src/test/scala/org/ergoplatform/sdk/DataJsonEncoderSpecification.scala +++ b/sdk/shared/src/test/scala/org/ergoplatform/sdk/DataJsonEncoderSpecification.scala @@ -13,7 +13,7 @@ import sigma.serialization.SerializerException import sigma.util.Extensions.{BigIntegerOps, EcpOps, SigmaBooleanOps} import sigma.Extensions.ArrayOps import sigma.eval.SigmaDsl -import sigma.{AvlTree, Box, Colls, Evaluation} +import sigma.{AvlTree, Box, Colls, Evaluation, Header, VersionContext} import sigma.serialization.SerializationSpecification import scala.annotation.nowarn @@ -22,29 +22,48 @@ import scala.reflect.ClassTag class DataJsonEncoderSpecification extends SerializationSpecification { object JsonCodecs extends JsonCodecs - def roundtrip[T <: SType](obj: T#WrappedType, tpe: T) = { - val json = DataJsonEncoder.encode(obj, tpe) - val res = DataJsonEncoder.decode(json) - res shouldBe obj + def roundtrip[T <: SType](obj: T#WrappedType, tpe: T, withVersion: Option[Byte] = None) = { + def test() = { + val json = DataJsonEncoder.encode(obj, tpe) + val res = DataJsonEncoder.decode(json) + res shouldBe obj + } + + withVersion match { + case Some(ver) => + VersionContext.withVersions(ver, 0) { + test() + } + case None => + test() + } } def testCollection[T <: SType](tpe: T) = { implicit val wWrapped = wrappedTypeGen(tpe) implicit val tT = Evaluation.stypeToRType(tpe) implicit val tagT = tT.classTag + + val withVersion = if (tpe == SHeader) { + Some(VersionContext.V6SoftForkVersion) + } else { + None + } + forAll { xs: Array[T#WrappedType] => - roundtrip[SCollection[T]](xs.toColl, SCollection(tpe)) - roundtrip[SType](xs.toColl.map(x => (x, x)).asWrappedType, SCollection(STuple(tpe, tpe))) + roundtrip[SCollection[T]](xs.toColl, SCollection(tpe), withVersion) + roundtrip[SType](xs.toColl.map(x => (x, x)).asWrappedType, SCollection(STuple(tpe, tpe)), withVersion) val nested = xs.toColl.map(x => Colls.fromItems[T#WrappedType](x, x)) - roundtrip[SCollection[SCollection[T]]](nested, SCollection(SCollection(tpe))) + roundtrip[SCollection[SCollection[T]]](nested, SCollection(SCollection(tpe)), withVersion) roundtrip[SType]( xs.toColl.map { x => val arr = Colls.fromItems[T#WrappedType](x, x) (arr, arr) }.asWrappedType, - SCollection(STuple(SCollection(tpe), SCollection(tpe))) + SCollection(STuple(SCollection(tpe), SCollection(tpe))), + withVersion ) } } @@ -54,11 +73,18 @@ class DataJsonEncoderSpecification extends SerializationSpecification { val tT = Evaluation.stypeToRType(tpe) @nowarn implicit val tag : ClassTag[T#WrappedType] = tT.classTag @nowarn implicit val tAny : RType[Any] = sigma.AnyType + + val withVersion = if (tpe == SHeader) { + Some(VersionContext.V6SoftForkVersion) + } else { + None + } + forAll { in: (T#WrappedType, T#WrappedType) => val (x,y) = (in._1, in._2) - roundtrip[SType]((x, y).asWrappedType, STuple(tpe, tpe)) - roundtrip[SType](((x, y), (x, y)).asWrappedType, STuple(STuple(tpe, tpe), STuple(tpe, tpe))) - roundtrip[SType](((x, y), ((x, y), (x, y))).asWrappedType, STuple(STuple(tpe, tpe), STuple(STuple(tpe, tpe), STuple(tpe, tpe)))) + roundtrip[SType]((x, y).asWrappedType, STuple(tpe, tpe), withVersion) + roundtrip[SType](((x, y), (x, y)).asWrappedType, STuple(STuple(tpe, tpe), STuple(tpe, tpe)), withVersion) + roundtrip[SType](((x, y), ((x, y), (x, y))).asWrappedType, STuple(STuple(tpe, tpe), STuple(STuple(tpe, tpe), STuple(tpe, tpe))), withVersion) } } @@ -98,6 +124,7 @@ class DataJsonEncoderSpecification extends SerializationSpecification { forAll { x: AvlTree => roundtrip[SAvlTree.type](x, SAvlTree) } forAll { x: Array[Byte] => roundtrip[SByteArray](x.toColl, SByteArray) } forAll { x: Box => roundtrip[SBox.type](x, SBox) } + forAll { x: Header => roundtrip[SHeader.type](x, SHeader, Some(VersionContext.V6SoftForkVersion)) } forAll { x: Option[Byte] => roundtrip[SOption[SByte.type]](x, SOption[SByte.type]) } testCollection(SOption[SLong.type]) testTuples(SOption[SLong.type]) @@ -187,25 +214,44 @@ class DataJsonEncoderSpecification extends SerializationSpecification { val tT = Evaluation.stypeToRType(tpe) @nowarn implicit val tag = tT.classTag @nowarn implicit val tAny = sigma.AnyType - forAll { x: T#WrappedType => - an[SerializerException] should be thrownBy { - DataJsonEncoder.encode(TupleColl(x, x, x).asWrappedType, STuple(tpe, tpe, tpe)) - } - // supported case - DataJsonEncoder.encode(SigmaDsl.Colls.fromItems(TupleColl(x, x)).asWrappedType, SCollection(STuple(tpe, tpe))) - // not supported case - an[SerializerException] should be thrownBy { - DataJsonEncoder.encode(SigmaDsl.Colls.fromItems(TupleColl(x, x, x)).asWrappedType, SCollection(STuple(tpe, tpe, tpe))) + def test() = { + forAll { x: T#WrappedType => + an[SerializerException] should be thrownBy { + DataJsonEncoder.encode(TupleColl(x, x, x).asWrappedType, STuple(tpe, tpe, tpe)) + } + + // supported case + DataJsonEncoder.encode(SigmaDsl.Colls.fromItems(TupleColl(x, x)).asWrappedType, SCollection(STuple(tpe, tpe))) + + // not supported case + an[SerializerException] should be thrownBy { + DataJsonEncoder.encode(SigmaDsl.Colls.fromItems(TupleColl(x, x, x)).asWrappedType, SCollection(STuple(tpe, tpe, tpe))) + } } } + + if (tpe == SHeader) { + VersionContext.withVersions(VersionContext.V6SoftForkVersion, 0) { + test() + } + } else { + test() + } } property("AnyValue") { forAll { t: SPredefType => - testAnyValue(t) - testAnyValue(SOption(t)) + if (t == SHeader) { + VersionContext.withVersions(VersionContext.V6SoftForkVersion, 1) { + testAnyValue(t) + testAnyValue(SOption(t)) + } + } else { + testAnyValue(t) + testAnyValue(SOption(t)) + } } } From b068b107a038afb46743016d3492a6501343e3bf Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Tue, 3 Sep 2024 13:18:54 +0300 Subject: [PATCH 220/314] Serialize SFunc in TypeSerializer --- .../src/main/scala/sigma/ast/SType.scala | 3 +- .../src/main/scala/sigma/ast/STypeParam.scala | 14 +--- .../src/main/scala/sigma/ast/TypeCodes.scala | 6 +- .../sigma/serialization/TypeSerializer.scala | 29 ++++++++ .../MethodCallSerializerSpecification.scala | 22 ------ .../generators/ObjectGenerators.scala | 2 +- .../sigmastate/helpers/SigmaPPrint.scala | 2 + .../scala/sigma/LanguageSpecificationV5.scala | 24 ------- .../scala/sigma/LanguageSpecificationV6.scala | 72 +++++++++++++++++++ .../test/scala/sigma/SigmaDslTesting.scala | 11 ++- .../utxo/BasicOpsSpecification.scala | 26 +++++++ 11 files changed, 145 insertions(+), 66 deletions(-) diff --git a/core/shared/src/main/scala/sigma/ast/SType.scala b/core/shared/src/main/scala/sigma/ast/SType.scala index 717439bcbb..46a639e37c 100644 --- a/core/shared/src/main/scala/sigma/ast/SType.scala +++ b/core/shared/src/main/scala/sigma/ast/SType.scala @@ -587,7 +587,7 @@ case class SFunc(tDom: IndexedSeq[SType], tRange: SType, tpeParams: Seq[STypePa } object SFunc { - final val FuncTypeCode: TypeCode = TypeCodes.FirstFuncType + final val FuncTypeCode: TypeCode = TypeCodes.FuncType def apply(tDom: SType, tRange: SType): SFunc = SFunc(Array(tDom), tRange) // HOTSPOT: val identity = { x: Any => x } } @@ -654,7 +654,6 @@ object SOption extends STypeCompanion { def apply[T <: SType](implicit elemType: T, ov: Overloaded1): SOption[T] = SOption(elemType) } - /** Base class for descriptors of `Coll[T]` ErgoTree type for some elemType T. */ trait SCollection[T <: SType] extends SProduct with SGenericType { def elemType: T diff --git a/core/shared/src/main/scala/sigma/ast/STypeParam.scala b/core/shared/src/main/scala/sigma/ast/STypeParam.scala index 56d89d01f8..08349ae024 100644 --- a/core/shared/src/main/scala/sigma/ast/STypeParam.scala +++ b/core/shared/src/main/scala/sigma/ast/STypeParam.scala @@ -2,18 +2,10 @@ package sigma.ast /** Represents a type parameter in a type system. * - * @param ident The identifier for this type parameter. - * @param upperBound The upper bound of this type parameter, if exists. - * @param lowerBound The lower bound of this type parameter, if exists. - * @note Type parameters with bounds are currently not supported. + * @param ident The identifier for this type parameter */ -case class STypeParam( - ident: STypeVar, - upperBound: Option[SType] = None, - lowerBound: Option[SType] = None) { - assert(upperBound.isEmpty && lowerBound.isEmpty, s"Type parameters with bounds are not supported, but found $this") - - override def toString = ident.toString + upperBound.fold("")(u => s" <: $u") + lowerBound.fold("")(l => s" >: $l") +case class STypeParam(ident: STypeVar) { + override def toString = ident.toString } object STypeParam { diff --git a/core/shared/src/main/scala/sigma/ast/TypeCodes.scala b/core/shared/src/main/scala/sigma/ast/TypeCodes.scala index 1b7b6121d6..68670449db 100644 --- a/core/shared/src/main/scala/sigma/ast/TypeCodes.scala +++ b/core/shared/src/main/scala/sigma/ast/TypeCodes.scala @@ -14,10 +14,8 @@ object TypeCodes { val LastDataType : TypeCode = TypeCode @@ 111.toByte - /** SFunc types occupy remaining space of byte values [FirstFuncType .. 255] */ - val FirstFuncType: TypeCode = TypeCode @@ (LastDataType + 1).toByte - - val LastFuncType : TypeCode = TypeCode @@ 255.toByte + /** SFunc type */ + val FuncType: TypeCode = TypeCode @@ (LastDataType + 1).toByte /** We use optimized encoding of constant values to save space in serialization. * Since Box registers are stored as Constant nodes we save 1 byte for each register. diff --git a/core/shared/src/main/scala/sigma/serialization/TypeSerializer.scala b/core/shared/src/main/scala/sigma/serialization/TypeSerializer.scala index 9c84de0944..c21a3458c0 100644 --- a/core/shared/src/main/scala/sigma/serialization/TypeSerializer.scala +++ b/core/shared/src/main/scala/sigma/serialization/TypeSerializer.scala @@ -1,6 +1,7 @@ package sigma.serialization import debox.cfor +import sigma.VersionContext import sigma.ast.SCollectionType.{CollectionTypeCode, NestedCollectionTypeCode} import sigma.ast._ import sigma.serialization.{CoreByteReader, CoreByteWriter, InvalidTypePrefix} @@ -101,6 +102,17 @@ class TypeSerializer { // `Tuple` type with more than 4 items `(Int, Byte, Box, Boolean, Int)` serializeTuple(tup, w) } + case SFunc(tDom, tRange, tpeParams) => + w.put(SFunc.FuncTypeCode) + w.putUByte(tDom.length) + tDom.foreach { st => + serialize(st, w) + } + serialize(tRange, w) + w.putUByte(tpeParams.length) + tpeParams.foreach { tp => + serialize(tp.ident, w) + } case typeIdent: STypeVar => { w.put(typeIdent.typeCode) val bytes = typeIdent.name.getBytes(StandardCharsets.UTF_8) @@ -189,7 +201,24 @@ class TypeSerializer { case SHeader.typeCode => SHeader case SPreHeader.typeCode => SPreHeader case SGlobal.typeCode => SGlobal + case SFunc.FuncTypeCode if VersionContext.current.isV6SoftForkActivated => + val tdLength = r.getUByte() + + val tDom = (1 to tdLength).map { _ => + deserialize(r) + } + val tRange = deserialize(r) + val tpeParamsLength = r.getUByte() + val tpeParams = (1 to tpeParamsLength).map { _ => + val ident = deserialize(r) + require(ident.isInstanceOf[STypeVar]) + STypeParam(ident.asInstanceOf[STypeVar]) + } + SFunc(tDom, tRange, tpeParams) + // todo: serialize tParams 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) NoType } diff --git a/interpreter/shared/src/test/scala/sigma/serialization/MethodCallSerializerSpecification.scala b/interpreter/shared/src/test/scala/sigma/serialization/MethodCallSerializerSpecification.scala index f93f0ccaf7..da88a944d4 100644 --- a/interpreter/shared/src/test/scala/sigma/serialization/MethodCallSerializerSpecification.scala +++ b/interpreter/shared/src/test/scala/sigma/serialization/MethodCallSerializerSpecification.scala @@ -24,28 +24,6 @@ class MethodCallSerializerSpecification extends SerializationSpecification { roundTripTest(expr) } - property("MethodCall deserialization round trip for BigInt.nbits") { - def code = { - val bi = BigIntConstant(5) - val expr = MethodCall(bi, - SBigIntMethods.ToNBits, - Vector(), - Map() - ) - roundTripTest(expr) - } - - VersionContext.withVersions(VersionContext.V6SoftForkVersion, 1) { - code - } - - an[ValidationException] should be thrownBy ( - VersionContext.withVersions((VersionContext.V6SoftForkVersion - 1).toByte, 1) { - code - } - ) - } - property("MethodCall deserialization round trip for Header.checkPow") { def code = { val bi = HeaderConstant(headerGen.sample.get) 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 c9fc8f2c93..db6cd87330 100644 --- a/interpreter/shared/src/test/scala/sigma/serialization/generators/ObjectGenerators.scala +++ b/interpreter/shared/src/test/scala/sigma/serialization/generators/ObjectGenerators.scala @@ -26,7 +26,7 @@ import sigma.util.Extensions.EcpOps import sigma.validation.{ChangedRule, DisabledRule, EnabledRule, ReplacedRule, RuleStatus} import sigma.validation.ValidationRules.FirstRuleId import ErgoTree.ZeroHeader -import sigma.data.{AvlTreeData, AvlTreeFlags, CAND, CBox, COR, CTHRESHOLD, Digest32Coll, ProveDHTuple, ProveDlog, RType, SigmaBoolean} +import sigma.data.{AvlTreeData, AvlTreeFlags, CAND, CBox, CHeader, COR, CTHRESHOLD, Digest32Coll, ProveDHTuple, ProveDlog, RType, SigmaBoolean} import sigma.eval.Extensions.{EvalIterableOps, SigmaBooleanOps} import sigma.eval.SigmaDsl import sigma.interpreter.{ContextExtension, ProverResult} diff --git a/parsers/shared/src/test/scala/sigmastate/helpers/SigmaPPrint.scala b/parsers/shared/src/test/scala/sigmastate/helpers/SigmaPPrint.scala index 24aaeddefd..11381e1ac3 100644 --- a/parsers/shared/src/test/scala/sigmastate/helpers/SigmaPPrint.scala +++ b/parsers/shared/src/test/scala/sigmastate/helpers/SigmaPPrint.scala @@ -52,6 +52,8 @@ object SigmaPPrint extends PPrinter { s"SOption[${typeName(ot.elemType)}]" case _: STuple => "STuple" + case _: SFunc => + s"SFunc" case _ => sys.error(s"Cannot get typeName($tpe)") } diff --git a/sc/shared/src/test/scala/sigma/LanguageSpecificationV5.scala b/sc/shared/src/test/scala/sigma/LanguageSpecificationV5.scala index 0d9a032a16..2c532c88d9 100644 --- a/sc/shared/src/test/scala/sigma/LanguageSpecificationV5.scala +++ b/sc/shared/src/test/scala/sigma/LanguageSpecificationV5.scala @@ -9820,30 +9820,6 @@ class LanguageSpecificationV5 extends LanguageSpecificationBase { suite => } } - property("higher order lambdas") { - val f = existingFeature( - { (xs: Coll[Int]) => - val inc = { (x: Int) => x + 1 } - - def apply(in: (Int => Int, Int)) = in._1(in._2) - - xs.map { (x: Int) => apply((inc, x)) } - }, - """{(xs: Coll[Int]) => - | val inc = { (x: Int) => x + 1 } - | def apply(in: (Int => Int, Int)) = in._1(in._2) - | xs.map { (x: Int) => apply((inc, x)) } - | } - |""".stripMargin - ) - - // TODO v6.0: Add support of SFunc in TypeSerializer (see https://github.com/ScorexFoundation/sigmastate-interpreter/issues/847) - assertExceptionThrown( - f.verifyCase(Coll[Int](), Expected(Success(Coll[Int]()), 0)), - exceptionLike[MatchError]("(SInt$) => SInt$ (of class sigma.ast.SFunc)") - ) - } - override protected def afterAll(): Unit = { printDebug(CErgoTreeEvaluator.DefaultProfiler.generateReport) printDebug("==========================================================") diff --git a/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala b/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala index 007bedfd20..f9aca8d607 100644 --- a/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala +++ b/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala @@ -11,6 +11,7 @@ import sigma.ast.syntax.TrueSigmaProp import sigma.ast._ import sigma.data.{CBigInt, CHeader, CBox, ExactNumeric} import sigma.eval.{CostDetails, SigmaDsl, TracedCost} +import sigma.serialization.ValueCodes.OpCode import sigma.util.Extensions.{BooleanOps, ByteOps, IntOps, LongOps} import sigmastate.exceptions.MethodNotFound import sigmastate.utils.Helpers @@ -513,4 +514,75 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite => ) } + property("higher order lambdas") { + val f = newFeature[Coll[Int], Coll[Int]]( + { (xs: Coll[Int]) => + val inc = { (x: Int) => x + 1 } + + def apply(in: (Int => Int, Int)) = in._1(in._2) + + xs.map { (x: Int) => apply((inc, x)) } + }, + """{(xs: Coll[Int]) => + | val inc = { (x: Int) => x + 1 } + | def apply(in: (Int => Int, Int)) = in._1(in._2) + | xs.map { (x: Int) => apply((inc, x)) } + | } + |""".stripMargin, + FuncValue( + Array((1, SCollectionType(SInt))), + MapCollection( + ValUse(1, SCollectionType(SInt)), + FuncValue( + Array((3, SInt)), + Apply( + FuncValue( + Array((5, SPair(SFunc(Array(SInt), SInt, List()), SInt))), + Apply( + SelectField.typed[Value[SFunc]]( + ValUse(5, SPair(SFunc(Array(SInt), SInt, List()), SInt)), + 1.toByte + ), + Array( + SelectField.typed[Value[SInt.type]]( + ValUse(5, SPair(SFunc(Array(SInt), SInt, List()), SInt)), + 2.toByte + ) + ) + ) + ), + Array( + Tuple( + Vector( + FuncValue( + Array((5, SInt)), + ArithOp(ValUse(5, SInt), IntConstant(1), OpCode @@ (-102.toByte)) + ), + ValUse(3, SInt) + ) + ) + ) + ) + ) + ) + ), + sinceVersion = VersionContext.V6SoftForkVersion + ) + + verifyCases( + Seq( + Coll(1, 2) -> Expected( + Success(Coll(2, 3)), + cost = 1793, + expectedDetails = CostDetails.ZeroCost + ) + ), + f, + preGeneratedSamples = Some(Seq( + Coll(Int.MinValue, Int.MaxValue - 1), + Coll(0, 1, 2, 3, 100, 1000) + )) + ) + } + } diff --git a/sc/shared/src/test/scala/sigma/SigmaDslTesting.scala b/sc/shared/src/test/scala/sigma/SigmaDslTesting.scala index 4410786fd4..d334ac4653 100644 --- a/sc/shared/src/test/scala/sigma/SigmaDslTesting.scala +++ b/sc/shared/src/test/scala/sigma/SigmaDslTesting.scala @@ -261,6 +261,7 @@ class SigmaDslTesting extends AnyPropSpec s"""Should succeed with the same value or fail with the same exception, but was: |First result: $b1 |Second result: $b2 + |Input: $x |Root cause: $cause |""".stripMargin) } @@ -715,11 +716,17 @@ class SigmaDslTesting extends AnyPropSpec override def checkEquality(input: A, logInputOutput: Boolean = false): Try[(B, CostDetails)] = { // check the old implementation against Scala semantic function var oldRes: Try[(B, CostDetails)] = null - if (ergoTreeVersionInTests < VersionContext.JitActivationVersion) oldRes = VersionContext.withVersions(activatedVersionInTests, ergoTreeVersionInTests) { try checkEq(scalaFunc)(oldF)(input) catch { - case e: TestFailedException => throw e + case e: TestFailedException => + if(activatedVersionInTests < changedInVersion) { + throw e + } else { + // old ergoscript may succeed in new version while old scalafunc may fail, + // see e.g. "Option.getOrElse with lazy default" test + Failure(e) + } case t: Throwable => Failure(t) } diff --git a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala index d80e39273f..f9d4d21235 100644 --- a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala @@ -458,6 +458,32 @@ class BasicOpsSpecification extends CompilerTestingCommons rootCause(_).isInstanceOf[NoSuchElementException]) } + property("higher order lambdas") { + def holTest() = test("HOL", env, ext, + """ + | { + | val c = Coll(Coll(1)) + | def fn(xs: Coll[Int]) = { + | val inc = { (x: Int) => x + 1 } + | def apply(in: (Int => Int, Int)) = in._1(in._2) + | val ys = xs.map { (x: Int) => apply((inc, x)) } + | ys.size == xs.size && ys != xs + | } + | + | c.exists(fn) + | } + |""".stripMargin, + null, + true + ) + + if(VersionContext.current.isV6SoftForkActivated) { + holTest() + } else { + an[Exception] shouldBe thrownBy(holTest()) + } + } + property("OptionGetOrElse") { test("OptGet1", env, ext, "{ SELF.R5[Int].getOrElse(3) == 1 }", From 2e8d8f41a86acbca8b4e8d25ad2d7c86511cc7c3 Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Tue, 3 Sep 2024 14:06:50 +0300 Subject: [PATCH 221/314] optimizing imports, polishing --- core/shared/src/main/scala/sigma/SigmaDsl.scala | 3 +++ .../src/main/scala/sigma/serialization/TypeSerializer.scala | 2 -- data/shared/src/main/scala/sigma/ast/methods.scala | 1 - data/shared/src/main/scala/sigma/data/ExactNumeric.scala | 6 +----- 4 files changed, 4 insertions(+), 8 deletions(-) diff --git a/core/shared/src/main/scala/sigma/SigmaDsl.scala b/core/shared/src/main/scala/sigma/SigmaDsl.scala index 5e647cad0e..9cf632cc59 100644 --- a/core/shared/src/main/scala/sigma/SigmaDsl.scala +++ b/core/shared/src/main/scala/sigma/SigmaDsl.scala @@ -155,6 +155,9 @@ trait BigInt { def or(that: BigInt): BigInt def |(that: BigInt): BigInt = or(that) + /** + * @return a big integer whose value is `this xor that` + */ def xor(that: BigInt): BigInt def shiftLeft(bits: Int): BigInt diff --git a/core/shared/src/main/scala/sigma/serialization/TypeSerializer.scala b/core/shared/src/main/scala/sigma/serialization/TypeSerializer.scala index c21a3458c0..1936bbcd9a 100644 --- a/core/shared/src/main/scala/sigma/serialization/TypeSerializer.scala +++ b/core/shared/src/main/scala/sigma/serialization/TypeSerializer.scala @@ -4,7 +4,6 @@ import debox.cfor import sigma.VersionContext import sigma.ast.SCollectionType.{CollectionTypeCode, NestedCollectionTypeCode} import sigma.ast._ -import sigma.serialization.{CoreByteReader, CoreByteWriter, InvalidTypePrefix} import sigma.util.safeNewArray import sigma.validation.ValidationRules.{CheckPrimitiveTypeCode, CheckTypeCode} @@ -215,7 +214,6 @@ class TypeSerializer { STypeParam(ident.asInstanceOf[STypeVar]) } SFunc(tDom, tRange, tpeParams) - // todo: serialize tParams case _ => // todo: 6.0: replace 1008 check with identical behavior but other opcode, to activate // ReplacedRule(1008 -> new opcode) during 6.0 activation diff --git a/data/shared/src/main/scala/sigma/ast/methods.scala b/data/shared/src/main/scala/sigma/ast/methods.scala index b40cdca79c..67bb1c74fb 100644 --- a/data/shared/src/main/scala/sigma/ast/methods.scala +++ b/data/shared/src/main/scala/sigma/ast/methods.scala @@ -5,7 +5,6 @@ import org.ergoplatform.validation._ import sigma._ import sigma.ast.SCollection.{SBooleanArray, SBoxArray, SByteArray, SByteArray2, SHeaderArray} import sigma.ast.SMethod.{MethodCallIrBuilder, MethodCostFunc, javaMethodOf} -import sigma.ast.SNumericTypeMethods.BitwiseAndMethod import sigma.ast.SType.TypeCode import sigma.ast.syntax.{SValue, ValueOps} import sigma.data.ExactIntegral.{ByteIsExactIntegral, IntIsExactIntegral, LongIsExactIntegral, ShortIsExactIntegral} diff --git a/data/shared/src/main/scala/sigma/data/ExactNumeric.scala b/data/shared/src/main/scala/sigma/data/ExactNumeric.scala index 90d28e5370..9612cccc34 100644 --- a/data/shared/src/main/scala/sigma/data/ExactNumeric.scala +++ b/data/shared/src/main/scala/sigma/data/ExactNumeric.scala @@ -1,12 +1,8 @@ package sigma.data import debox.cfor -import sigma.Evaluation.stypeToRType -import sigma.{BigInt, Coll, Colls} +import sigma.{Coll, Colls} import sigma.data.ExactIntegral._ -import sigma.data.RType.SomeType - -import scala.collection.mutable /** Numeric operations with overflow checks. * Raise exception when overflow is detected. From d284f79b077dd77e0bf36d684b671cafde5f2e3b Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Tue, 3 Sep 2024 14:13:20 +0300 Subject: [PATCH 222/314] fixing post-merging failing test --- .../src/test/scala/sigmastate/ErgoTreeSpecification.scala | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/sc/shared/src/test/scala/sigmastate/ErgoTreeSpecification.scala b/sc/shared/src/test/scala/sigmastate/ErgoTreeSpecification.scala index c3c20422e9..aabb78e493 100644 --- a/sc/shared/src/test/scala/sigmastate/ErgoTreeSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/ErgoTreeSpecification.scala @@ -313,6 +313,8 @@ class ErgoTreeSpecification extends SigmaDslTesting with ContractsTestkit with C */ case class MInfo(methodId: Byte, method: SMethod, isResolvableFromIds: Boolean = true) + def isV6Activated = VersionContext.current.isV6SoftForkActivated + // NOTE, the type code constants are checked above // The methodId codes as checked here, they MUST be PRESERVED. // The following table should be made dependent on HF activation @@ -402,7 +404,11 @@ class ErgoTreeSpecification extends SigmaDslTesting with ContractsTestkit with C MInfo(7, timestampMethod), MInfo(8, nBitsMethod), MInfo(9, heightMethod), MInfo(10, extensionRootMethod), MInfo(11, minerPkMethod), MInfo(12, powOnetimePkMethod), MInfo(13, powNonceMethod), MInfo(14, powDistanceMethod), MInfo(15, votesMethod) - ), true) + ) ++ (if (VersionContext.current.isV6SoftForkActivated) { + Seq(MInfo(16, checkPowMethod)) + } else { + Seq.empty[MInfo] + }), true) }, { import SPreHeaderMethods._ (SPreHeader.typeId, Seq( From ed5b8f5383db1fba53a5d90887fb6efa21a13810 Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Wed, 4 Sep 2024 14:48:39 +0300 Subject: [PATCH 223/314] fixing SigmaTyperTest --- .../test/scala/sigmastate/lang/SigmaTyperTest.scala | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/sc/shared/src/test/scala/sigmastate/lang/SigmaTyperTest.scala b/sc/shared/src/test/scala/sigmastate/lang/SigmaTyperTest.scala index e8bfeb777f..3696a7e14e 100644 --- a/sc/shared/src/test/scala/sigmastate/lang/SigmaTyperTest.scala +++ b/sc/shared/src/test/scala/sigmastate/lang/SigmaTyperTest.scala @@ -523,7 +523,7 @@ class SigmaTyperTest extends AnyPropSpec typecheck(env, "1.toByte.toBytes", expected = MethodCall.typed[Value[SCollection[SByte.type]]]( Select(IntConstant(1), "toByte", Some(SByte)), - SNumericTypeMethods.getMethodByName("toBytes").withConcreteTypes(Map(STypeVar("TNum") -> SByte)), + SNumericTypeMethods.ToBytesMethod.withConcreteTypes(Map(STypeVar("TNum") -> SByte)), Vector(), Map() )) shouldBe SByteArray @@ -531,7 +531,7 @@ class SigmaTyperTest extends AnyPropSpec typecheck(env, "1.toShort.toBytes", expected = MethodCall.typed[Value[SCollection[SByte.type]]]( Select(IntConstant(1), "toShort", Some(SShort)), - SNumericTypeMethods.getMethodByName("toBytes").withConcreteTypes(Map(STypeVar("TNum") -> SShort)), + SNumericTypeMethods.ToBytesMethod.withConcreteTypes(Map(STypeVar("TNum") -> SShort)), Vector(), Map() )) shouldBe SByteArray @@ -539,7 +539,7 @@ class SigmaTyperTest extends AnyPropSpec typecheck(env, "1.toBytes", expected = MethodCall.typed[Value[SCollection[SByte.type]]]( IntConstant(1), - SNumericTypeMethods.getMethodByName("toBytes").withConcreteTypes(Map(STypeVar("TNum") -> SInt)), + SNumericTypeMethods.ToBytesMethod.withConcreteTypes(Map(STypeVar("TNum") -> SInt)), Vector(), Map() )) shouldBe SByteArray @@ -547,7 +547,7 @@ class SigmaTyperTest extends AnyPropSpec typecheck(env, "1.toLong.toBytes", expected = MethodCall.typed[Value[SCollection[SByte.type]]]( Select(IntConstant(1), "toLong", Some(SLong)), - SNumericTypeMethods.getMethodByName("toBytes").withConcreteTypes(Map(STypeVar("TNum") -> SLong)), + SNumericTypeMethods.ToBytesMethod.withConcreteTypes(Map(STypeVar("TNum") -> SLong)), Vector(), Map() )) shouldBe SByteArray @@ -555,7 +555,7 @@ class SigmaTyperTest extends AnyPropSpec typecheck(env, "1.toBigInt.toBytes", expected = MethodCall.typed[Value[SCollection[SByte.type]]]( Select(IntConstant(1), "toBigInt", Some(SBigInt)), - SNumericTypeMethods.getMethodByName("toBytes").withConcreteTypes(Map(STypeVar("TNum") -> SBigInt)), + SNumericTypeMethods.ToBytesMethod.withConcreteTypes(Map(STypeVar("TNum") -> SBigInt)), Vector(), Map() )) shouldBe SByteArray From b2de9cf057648691d395b036e14f2ade1049dff1 Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Fri, 6 Sep 2024 19:57:59 +0300 Subject: [PATCH 224/314] scaladoc --- .../src/main/scala/sigma/SigmaDsl.scala | 16 +++++++++---- .../src/main/scala/sigma/data/CBigInt.scala | 4 ++-- .../main/scala/sigma/data/ExactNumeric.scala | 23 +++++++++++++++++++ .../compiler/ir/primitives/UnBinOps.scala | 6 +++-- 4 files changed, 40 insertions(+), 9 deletions(-) diff --git a/core/shared/src/main/scala/sigma/SigmaDsl.scala b/core/shared/src/main/scala/sigma/SigmaDsl.scala index 9cf632cc59..6f9a3e2ffe 100644 --- a/core/shared/src/main/scala/sigma/SigmaDsl.scala +++ b/core/shared/src/main/scala/sigma/SigmaDsl.scala @@ -5,9 +5,7 @@ import java.math.BigInteger import sigma.data._ /** - * All `modQ` operations assume that Q is a global constant (an order of the only one cryptographically strong group - * which is used for all cryptographic operations). - * So it is globally and implicitly used in all methods. + * Functions defined for 256-bit signed integers * */ trait BigInt { /** Convert this BigInt value to Byte. @@ -160,9 +158,17 @@ trait BigInt { */ def xor(that: BigInt): BigInt - def shiftLeft(bits: Int): BigInt + /** + * @return a 256-bit signed integer whose value is (this << n). The shift distance, n, may be negative, + * in which case this method performs a right shift. (Computes floor(this * 2n).) + */ + def shiftLeft(n: Int): BigInt - def shiftRight(bits: Int): BigInt + /** + * @return a 256-bit signed integer whose value is (this >> n). Sign extension is performed. The shift distance, n, + * may be negative, in which case this method performs a left shift. (Computes floor(this / 2n).) + */ + def shiftRight(n: Int): BigInt } /** Base class for points on elliptic curves. */ diff --git a/core/shared/src/main/scala/sigma/data/CBigInt.scala b/core/shared/src/main/scala/sigma/data/CBigInt.scala index dbfec02844..ea69174877 100644 --- a/core/shared/src/main/scala/sigma/data/CBigInt.scala +++ b/core/shared/src/main/scala/sigma/data/CBigInt.scala @@ -52,7 +52,7 @@ case class CBigInt(override val wrappedValue: BigInteger) extends BigInt with Wr override def xor(that: BigInt): BigInt = CBigInt(wrappedValue.xor(that.asInstanceOf[CBigInt].wrappedValue)) - def shiftLeft(bits: Int): BigInt = CBigInt(wrappedValue.shiftLeft(bits).to256BitValueExact) + override def shiftLeft(n: Int): BigInt = CBigInt(wrappedValue.shiftLeft(n).to256BitValueExact) - def shiftRight(bits: Int): BigInt = CBigInt(wrappedValue.shiftRight(bits).to256BitValueExact) + override def shiftRight(n: Int): BigInt = CBigInt(wrappedValue.shiftRight(n).to256BitValueExact) } diff --git a/data/shared/src/main/scala/sigma/data/ExactNumeric.scala b/data/shared/src/main/scala/sigma/data/ExactNumeric.scala index 9612cccc34..56b4a9369e 100644 --- a/data/shared/src/main/scala/sigma/data/ExactNumeric.scala +++ b/data/shared/src/main/scala/sigma/data/ExactNumeric.scala @@ -38,6 +38,9 @@ trait ExactNumeric[T] { */ def toBigEndianBytes(x: T): Coll[Byte] + /** + * Returns a big-endian binary representation of this value as boolean array. + */ def toBits(x: T): Coll[Boolean] = { def isBitSet(byte: Byte)(bit: Int): Boolean = ((byte >> bit) & 1) == 1 @@ -57,16 +60,36 @@ trait ExactNumeric[T] { Colls.fromArray(res) } + /** + * @return a numeric value which is inverse of `x` (every bit, including sign, is flipped) + */ def bitwiseInverse(x: T): T + /** + * @return a numeric value which is `this | that` + */ def bitwiseOr(x: T, y: T): T + /** + * @return a numeric value which is `this && that` + */ def bitwiseAnd(x: T, y: T): T + /** + * @return a numeric value which is `this xor that` + */ def bitwiseXor(x: T, y: T): T + /** + * @return a value which is (this << n). The shift distance, n, may be negative, + * in which case this method performs a right shift. (Computes floor(this * 2n).) + */ def shiftLeft(x: T, bits: Int): T + /** + * @return a value which is (this >> n). Sign extension is performed. The shift distance, n, + * may be negative, in which case this method performs a left shift. (Computes floor(this / 2n).) + */ def shiftRight(x: T, bits: Int): T /** A value of type T which corresponds to integer 0. */ diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/primitives/UnBinOps.scala b/sc/shared/src/main/scala/sigma/compiler/ir/primitives/UnBinOps.scala index 62bfc29f68..b55596052e 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/primitives/UnBinOps.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/primitives/UnBinOps.scala @@ -45,6 +45,7 @@ trait UnBinOps extends Base { self: IRContext => def shouldPropagate(lhs: A, rhs: A) = true } + /** Base class for descriptors of binary operations where arguments are of different types. */ abstract class BinDiffArgsOp[A, B](val opName: String)(implicit val eResult: Elem[A]) { override def toString = opName @@ -91,13 +92,14 @@ trait UnBinOps extends Base { self: IRContext => override def transform(t: Transformer): Def[R] = ApplyBinOpLazy[A,R](op, t(lhs), t(rhs)) } - /** Graph node which represents application of the given binary operation to the given arguments. */ + /** Graph node which represents application of the given binary operation to the given arguments of different types + * where the second argument is lazy. */ case class ApplyBinOpDiffArgsLazy[A, B](op: BinDiffArgsOp[A, B], lhs: Ref[A], rhs: Ref[Thunk[B]]) extends BaseDef[A]()(op.eResult) { override def toString = s"$lhs $op { $rhs }" override def transform(t: Transformer): Def[A] = ApplyBinOpDiffArgsLazy[A, B](op, t(lhs), t(rhs)) } - /** Graph node which represents application of the given binary operation to the given arguments. */ + /** Graph node which represents application of the given binary operation to the given arguments of different types. */ case class ApplyBinOpDiffArgs[A, B](op: BinDiffArgsOp[A, B], lhs: Ref[A], rhs: Ref[B]) extends BaseDef[A]()(op.eResult) { override def toString = s"$op($lhs, $rhs)" override def transform(t: Transformer): Def[A] = ApplyBinOpDiffArgs[A, B](op, t(lhs), t(rhs)) From eccc9cae1b13def59988e60c201410a812982bd6 Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Tue, 10 Sep 2024 12:55:38 +0300 Subject: [PATCH 225/314] 6.0 methods for Byte in LSV6 --- .../src/main/scala/sigma/ast/methods.scala | 14 +- .../compiler/ir/primitives/NumericOps.scala | 2 +- .../scala/sigma/LanguageSpecificationV6.scala | 197 +++++++++++++++--- .../utxo/BasicOpsSpecification.scala | 17 ++ 4 files changed, 196 insertions(+), 34 deletions(-) diff --git a/data/shared/src/main/scala/sigma/ast/methods.scala b/data/shared/src/main/scala/sigma/ast/methods.scala index 67bb1c74fb..1e8fb911bb 100644 --- a/data/shared/src/main/scala/sigma/ast/methods.scala +++ b/data/shared/src/main/scala/sigma/ast/methods.scala @@ -161,13 +161,13 @@ trait SNumericTypeMethods extends MonoTypeMethods { private val subst = Map(tNum -> this.ownerType) - private val v5Methods = { + val v5Methods = { SNumericTypeMethods.v5Methods.map { m => m.copy(stype = applySubst(m.stype, subst).asFunc) } } - private val v6Methods = { + val v6Methods = { SNumericTypeMethods.v6Methods.map { m => m.copy( objType = this, // associate the method with the concrete numeric type @@ -306,7 +306,7 @@ object SNumericTypeMethods extends MethodsContainer { case SBigIntMethods => BigIntIsExactIntegral.bitwiseOr(obj.asInstanceOf[BigInt], other.head.asInstanceOf[BigInt]) } }) - .withInfo(PropertyCall, + .withInfo(MethodCall, """ Returns a big-endian representation of this numeric in a collection of Booleans. | Each boolean corresponds to one bit. """.stripMargin) @@ -323,7 +323,7 @@ object SNumericTypeMethods extends MethodsContainer { case SBigIntMethods => BigIntIsExactIntegral.bitwiseAnd(obj.asInstanceOf[BigInt], other.head.asInstanceOf[BigInt]) } }) - .withInfo(PropertyCall, + .withInfo(MethodCall, """ Returns a big-endian representation of this numeric in a collection of Booleans. | Each boolean corresponds to one bit. """.stripMargin) @@ -340,7 +340,7 @@ object SNumericTypeMethods extends MethodsContainer { case SBigIntMethods => BigIntIsExactIntegral.bitwiseXor(obj.asInstanceOf[BigInt], other.head.asInstanceOf[BigInt]) } }) - .withInfo(PropertyCall, + .withInfo(MethodCall, """ Returns a big-endian representation of this numeric in a collection of Booleans. | Each boolean corresponds to one bit. """.stripMargin) @@ -357,7 +357,7 @@ object SNumericTypeMethods extends MethodsContainer { case SBigIntMethods => BigIntIsExactIntegral.shiftLeft(obj.asInstanceOf[BigInt], other.head.asInstanceOf[Int]) } }) - .withInfo(PropertyCall, + .withInfo(MethodCall, """ Returns a big-endian representation of this numeric in a collection of Booleans. | Each boolean corresponds to one bit. """.stripMargin) @@ -374,7 +374,7 @@ object SNumericTypeMethods extends MethodsContainer { case SBigIntMethods => BigIntIsExactIntegral.shiftRight(obj.asInstanceOf[BigInt], other.head.asInstanceOf[Int]) } }) - .withInfo(PropertyCall, + .withInfo(MethodCall, """ Returns a big-endian representation of this numeric in a collection of Booleans. | Each boolean corresponds to one bit. """.stripMargin) diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/primitives/NumericOps.scala b/sc/shared/src/main/scala/sigma/compiler/ir/primitives/NumericOps.scala index 9a6b372033..5b858d8586 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/primitives/NumericOps.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/primitives/NumericOps.scala @@ -105,7 +105,7 @@ trait NumericOps extends Base { self: IRContext => } } - /** Descriptor of unary `ToBits` conversion operation. */ + /** Descriptor of unary `BitwiseInverse` conversion operation. */ case class NumericBitwiseInverse[T: Elem](n: ExactNumeric[T]) extends UnOp[T, T]("~") { override def applySeq(x: T): T = n.bitwiseInverse(x) } diff --git a/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala b/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala index dd577b5b38..57951586fb 100644 --- a/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala +++ b/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala @@ -50,38 +50,183 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite => testCases(cases, toByte) } - property("Byte methods equivalence (new features)") { - // TODO v6.0: implement as part of https://github.com/ScorexFoundation/sigmastate-interpreter/issues/474 - if (activatedVersionInTests < VersionContext.V6SoftForkVersion) { - // NOTE, for such versions the new features are not supported - // which is checked below + property("Byte methods - 6.0 features") { - lazy val toAbs = newFeature((x: Byte) => x.toAbs, "{ (x: Byte) => x.toAbs }", - sinceVersion = V6SoftForkVersion) + lazy val bitOr = newFeature( + { (x: (Byte, Byte)) => (x._1 | x._2).toByteExact }, + "{ (x: (Byte, Byte)) => x._1.bitwiseOr(x._2) }", + FuncValue( + Array((1, SPair(SByte, SByte))), + MethodCall.typed[Value[SByte.type]]( + SelectField.typed[Value[SByte.type]](ValUse(1, SPair(SByte, SByte)), 1.toByte), + SByteMethods.v6Methods.find(_.name == "bitwiseOr").get, + Vector(SelectField.typed[Value[SByte.type]](ValUse(1, SPair(SByte, SByte)),2.toByte)), + Map() + ) + ), + sinceVersion = V6SoftForkVersion) - lazy val compareTo = newFeature( - (x: (Byte, Byte)) => x._1.compareTo(x._2), - "{ (x: (Byte, Byte)) => x._1.compareTo(x._2) }", - sinceVersion = V6SoftForkVersion) + verifyCases( + Seq( + (1.toByte, 2.toByte) -> new Expected(ExpectedResult(Success(3.toByte), None)) + ), + bitOr + ) - lazy val bitOr = newFeature( - { (x: (Byte, Byte)) => (x._1 | x._2).toByteExact }, - "{ (x: (Byte, Byte)) => (x._1 | x._2) }", - sinceVersion = V6SoftForkVersion) + lazy val bitNot = newFeature( + { (x: Byte) => (~x).toByteExact }, + "{ (x: Byte) => x.bitwiseInverse }", + FuncValue( + Array((1, SByte)), + MethodCall.typed[Value[SByte.type]]( + ValUse(1, SByte), + SByteMethods.v6Methods.find(_.name == "bitwiseInverse").get, + Vector(), + Map() + ) + ), + sinceVersion = V6SoftForkVersion) - lazy val bitAnd = newFeature( - { (x: (Byte, Byte)) => (x._1 & x._2).toByteExact }, - "{ (x: (Byte, Byte)) => (x._1 & x._2) }", - sinceVersion = V6SoftForkVersion) + verifyCases( + Seq( + 1.toByte -> new Expected(ExpectedResult(Success((-2).toByte), None)) + ), + bitNot + ) - forAll { x: Byte => - Seq(toAbs).foreach(f => f.checkEquality(x)) - } + lazy val bitAnd = newFeature( + { (x: (Byte, Byte)) => (x._1 & x._2).toByteExact }, + "{ (x: (Byte, Byte)) => x._1.bitwiseAnd(x._2) }", + FuncValue( + Array((1, SPair(SByte, SByte))), + MethodCall.typed[Value[SByte.type]]( + SelectField.typed[Value[SByte.type]](ValUse(1, SPair(SByte, SByte)), 1.toByte), + SByteMethods.v6Methods.find(_.name == "bitwiseAnd").get, + Vector(SelectField.typed[Value[SByte.type]](ValUse(1, SPair(SByte, SByte)),2.toByte)), + Map() + ) + ), + sinceVersion = V6SoftForkVersion) - forAll { x: (Byte, Byte) => - Seq(compareTo, bitOr, bitAnd).foreach(_.checkEquality(x)) - } - } + verifyCases( + Seq( + (3.toByte, 5.toByte) -> new Expected(ExpectedResult(Success(1.toByte), None)) + ), + bitAnd + ) + + lazy val bitXor = newFeature( + { (x: (Byte, Byte)) => (x._1 ^ x._2).toByteExact }, + "{ (x: (Byte, Byte)) => x._1.bitwiseXor(x._2) }", + FuncValue( + Array((1, SPair(SByte, SByte))), + MethodCall.typed[Value[SByte.type]]( + SelectField.typed[Value[SByte.type]](ValUse(1, SPair(SByte, SByte)), 1.toByte), + SByteMethods.v6Methods.find(_.name == "bitwiseXor").get, + Vector(SelectField.typed[Value[SByte.type]](ValUse(1, SPair(SByte, SByte)),2.toByte)), + Map() + ) + ), + sinceVersion = V6SoftForkVersion) + + verifyCases( + Seq( + (3.toByte, 5.toByte) -> new Expected(ExpectedResult(Success(6.toByte), None)) + ), + bitXor + ) + + lazy val toBigEndianBytes = newFeature( + { x: Byte => Coll(x) }, + "{ (x: Byte) => x.toBytes }", + FuncValue( + Array((1, SByte)), + MethodCall.typed[Value[SCollection[SByte.type]]]( + ValUse(1, SByte), + SByteMethods.getMethodByName("toBytes"), + Vector(), + Map() + ) + ), + sinceVersion = V6SoftForkVersion) + + verifyCases( + Seq( + 127.toByte -> new Expected(ExpectedResult(Success(Coll(127.toByte)), None)) + ), + toBigEndianBytes + ) + + def byte2Bools(b: Byte): Seq[Boolean] = + (0 to 7 map isBitSet(b)).reverse + + def isBitSet(byte: Byte)(bit: Int): Boolean = + ((byte >> bit) & 1) == 1 + + lazy val toBits = newFeature[Byte, Coll[Boolean]]( + { x: Byte => Colls.fromArray(byte2Bools(x).toArray) }, + "{ (x: Byte) => x.toBits }", + FuncValue( + Array((1, SByte)), + MethodCall.typed[Value[SCollection[SByte.type]]]( + ValUse(1, SByte), + SByteMethods.getMethodByName("toBits"), + Vector(), + Map() + ) + ), + sinceVersion = V6SoftForkVersion) + + verifyCases( + Seq( + 83.toByte -> new Expected(ExpectedResult(Success(Coll(false, true, false, true, false, false, true, true)), None)), + -55.toByte -> new Expected(ExpectedResult(Success(Coll(true, true, false, false, true, false, false, true)), None)), + -1.toByte -> new Expected(ExpectedResult(Success(Coll(true, true, true, true, true, true, true, true)), None)) + ), + toBits + ) + + lazy val shiftLeft = newFeature( + { (x: (Byte, Int)) => (x._1 << x._2).toByte }, + "{ (x: (Byte, Int)) => x._1.shiftLeft(x._2) }", + FuncValue( + Array((1, SPair(SByte, SInt))), + MethodCall.typed[Value[SByte.type]]( + SelectField.typed[Value[SByte.type]](ValUse(1, SPair(SByte, SInt)), 1.toByte), + SByteMethods.v6Methods.find(_.name == "shiftLeft").get, + Vector(SelectField.typed[Value[SInt.type]](ValUse(1, SPair(SByte, SInt)), 2.toByte)), + Map() + ) + ), + sinceVersion = V6SoftForkVersion) + + verifyCases( + Seq( + (3.toByte, 3) -> new Expected(ExpectedResult(Success(24.toByte), None)) + ), + shiftLeft + ) + + lazy val shiftRight = newFeature( + { (x: (Byte, Int)) => (x._1 >> x._2).toByte }, + "{ (x: (Byte, Int)) => x._1.shiftRight(x._2) }", + FuncValue( + Array((1, SPair(SByte, SInt))), + MethodCall.typed[Value[SByte.type]]( + SelectField.typed[Value[SByte.type]](ValUse(1, SPair(SByte, SInt)), 1.toByte), + SByteMethods.v6Methods.find(_.name == "shiftRight").get, + Vector(SelectField.typed[Value[SInt.type]](ValUse(1, SPair(SByte, SInt)), 2.toByte)), + Map() + ) + ), + sinceVersion = V6SoftForkVersion) + + verifyCases( + Seq( + (24.toByte, 3) -> new Expected(ExpectedResult(Success(3.toByte), None)) + ), + shiftRight + ) } // TODO v6.0: enable as part of https://github.com/ScorexFoundation/sigmastate-interpreter/issues/474 diff --git a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala index f531c2b07d..a37a3d1079 100644 --- a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala @@ -360,6 +360,23 @@ class BasicOpsSpecification extends CompilerTestingCommons } } + property("Byte.shiftLeft - over limit 2") { + def shiftLeftTest(): Assertion = test("Byte.shiftLeft2", env, ext, + s"""{ + | val x = (-128).toByte + | val y = 1 + | x.shiftLeft(y) == 0 + |}""".stripMargin, + null + ) + + if (VersionContext.current.isV6SoftForkActivated) { + shiftLeftTest() + } else { + an[Exception] shouldBe thrownBy(shiftLeftTest()) + } + } + property("BigInt.shiftLeft") { def shiftLeftTest(): Assertion = test("BigInt.shiftLeft", env, ext, s"""{ From f566b7bd4bb93e41ad52357db6d1251979b865d2 Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Tue, 10 Sep 2024 14:09:02 +0300 Subject: [PATCH 226/314] 6.0 methods for Short in LSV6 --- .../scala/sigma/LanguageSpecificationV6.scala | 205 ++++++++++++++++-- 1 file changed, 182 insertions(+), 23 deletions(-) diff --git a/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala b/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala index 57951586fb..725b999f6e 100644 --- a/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala +++ b/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala @@ -6,11 +6,12 @@ import sigma.VersionContext.V6SoftForkVersion import org.ergoplatform.ErgoBox import org.ergoplatform.ErgoBox.Token import scorex.util.ModifierId +import scorex.utils.Shorts import sigma.ast.ErgoTree.ZeroHeader import sigma.ast.SCollection.SByteArray import sigma.ast.syntax.TrueSigmaProp import sigma.ast._ -import sigma.data.{CBigInt, CHeader, CBox, ExactNumeric} +import sigma.data.{CBigInt, CBox, CHeader, ExactNumeric} import sigma.eval.{CostDetails, SigmaDsl, TracedCost} import sigma.serialization.ValueCodes.OpCode import sigma.util.Extensions.{BooleanOps, ByteOps, IntOps, LongOps} @@ -229,36 +230,194 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite => ) } - // TODO v6.0: enable as part of https://github.com/ScorexFoundation/sigmastate-interpreter/issues/474 - property("Short methods equivalence (new features)") { - if (activatedVersionInTests < VersionContext.V6SoftForkVersion) { - // NOTE, for such versions the new features are not supported - // which is checked below + property("Short - 6.0 methods") { - lazy val toAbs = newFeature((x: Short) => x.toAbs, "{ (x: Short) => x.toAbs }", - sinceVersion = V6SoftForkVersion) + lazy val bitOr = newFeature( + { (x: (Short, Short)) => (x._1 | x._2).toShortExact }, + "{ (x: (Short, Short)) => x._1.bitwiseOr(x._2) }", + FuncValue( + Array((1, SPair(SShort, SShort))), + MethodCall.typed[Value[SShort.type]]( + SelectField.typed[Value[SShort.type]](ValUse(1,SPair(SShort, SShort)), 1.toByte), + SShortMethods.v6Methods.find(_.name == "bitwiseOr").get, + Vector(SelectField.typed[Value[SShort.type]](ValUse(1, SPair(SShort, SShort)),2.toByte)), + Map() + ) + ), + sinceVersion = V6SoftForkVersion) - lazy val compareTo = newFeature((x: (Short, Short)) => x._1.compareTo(x._2), - "{ (x: (Short, Short)) => x._1.compareTo(x._2) }", - sinceVersion = V6SoftForkVersion) + verifyCases( + Seq( + (1.toShort, 2.toShort) -> new Expected(ExpectedResult(Success(3.toShort), None)), + (1001.toShort, 2002.toShort) -> new Expected(ExpectedResult(Success(2043.toShort), None)) + ), + bitOr + ) - lazy val bitOr = newFeature( - { (x: (Short, Short)) => (x._1 | x._2).toShortExact }, - "{ (x: (Short, Short)) => x._1 | x._2 }", + lazy val bitNot = newFeature( + { (x: Short) => (~x).toShortExact }, + "{ (x: Short) => x.bitwiseInverse }", + FuncValue( + Array((1, SShort)), + MethodCall.typed[Value[SShort.type]]( + ValUse(1, SShort), + SShortMethods.v6Methods.find(_.name == "bitwiseInverse").get, + Vector(), + Map() + ) + ), sinceVersion = V6SoftForkVersion) - lazy val bitAnd = newFeature( + verifyCases( + Seq( + 1.toShort -> new Expected(ExpectedResult(Success((-2).toShort), None)), + 10001.toShort -> new Expected(ExpectedResult(Success((-10002).toShort), None)) + ), + bitNot + ) + + lazy val bitAnd = newFeature( { (x: (Short, Short)) => (x._1 & x._2).toShortExact }, - "{ (x: (Short, Short)) => x._1 & x._2 }", + "{ (x: (Short, Short)) => x._1.bitwiseAnd(x._2) }", + FuncValue( + Array((1, SPair(SShort, SShort))), + MethodCall.typed[Value[SShort.type]]( + SelectField.typed[Value[SShort.type]](ValUse(1, SPair(SShort, SShort)), 1.toByte), + SShortMethods.v6Methods.find(_.name == "bitwiseAnd").get, + Vector(SelectField.typed[Value[SShort.type]](ValUse(1, SPair(SShort, SShort)),2.toByte)), + Map() + ) + ), sinceVersion = V6SoftForkVersion) - forAll { x: Short => - Seq(toAbs).foreach(_.checkEquality(x)) - } - forAll { x: (Short, Short) => - Seq(compareTo, bitOr, bitAnd).foreach(_.checkEquality(x)) - } - } + verifyCases( + Seq( + (3.toShort, 5.toShort) -> new Expected(ExpectedResult(Success(1.toShort), None)), + (10001.toShort, 2202.toShort) -> new Expected(ExpectedResult(Success(16.toShort), None)) + ), + bitAnd + ) + + lazy val bitXor = newFeature( + { (x: (Short, Short)) => (x._1 ^ x._2).toShortExact }, + "{ (x: (Short, Short)) => x._1.bitwiseXor(x._2) }", + FuncValue( + Array((1, SPair(SShort, SShort))), + MethodCall.typed[Value[SShort.type]]( + SelectField.typed[Value[SShort.type]](ValUse(1, SPair(SShort, SShort)), 1.toByte), + SShortMethods.v6Methods.find(_.name == "bitwiseXor").get, + Vector(SelectField.typed[Value[SShort.type]](ValUse(1, SPair(SShort, SShort)),2.toByte)), + Map() + ) + ), + sinceVersion = V6SoftForkVersion) + + verifyCases( + Seq( + (3.toShort, 5.toShort) -> new Expected(ExpectedResult(Success(6.toShort), None)), + (10001.toShort, 2202.toShort) -> new Expected(ExpectedResult(Success(12171.toShort), None)) + ), + bitXor + ) + + lazy val toBigEndianBytes = newFeature[Short, Coll[Byte]]( + { x: Short => Colls.fromArray(Shorts.toByteArray(x)) }, + "{ (x: Short) => x.toBytes }", + FuncValue( + Array((1, SShort)), + MethodCall.typed[Value[SCollection[SShort.type]]]( + ValUse(1, SShort), + SShortMethods.getMethodByName("toBytes"), + Vector(), + Map() + ) + ), + sinceVersion = V6SoftForkVersion) + + verifyCases( + Seq( + 127.toShort -> new Expected(ExpectedResult(Success(Coll(0.toByte, 127.toByte)), None)), + Short.MaxValue -> new Expected(ExpectedResult(Success(Coll(127.toByte, (-1).toByte)), None)), + Short.MinValue -> new Expected(ExpectedResult(Success(Coll((-128).toByte, 0.toByte)), None)) + ), + toBigEndianBytes + ) + + def byte2Bools(b: Byte): Seq[Boolean] = + (0 to 7 map isBitSet(b)).reverse + + def isBitSet(byte: Byte)(bit: Int): Boolean = + ((byte >> bit) & 1) == 1 + + lazy val toBits = newFeature[Short, Coll[Boolean]]( + { x: Short => Colls.fromArray(Shorts.toByteArray(x).flatMap(b => byte2Bools(b).toArray)) }, + "{ (x: Short) => x.toBits }", + FuncValue( + Array((1, SShort)), + MethodCall.typed[Value[SCollection[SShort.type]]]( + ValUse(1, SShort), + SShortMethods.getMethodByName("toBits"), + Vector(), + Map() + ) + ), + sinceVersion = V6SoftForkVersion) + + verifyCases( + Seq( + 83.toShort -> new Expected(ExpectedResult(Success(Coll(false, false, false, false, false, false, false, false, false, true, false, true, false, false, true, true)), None)), + -55.toShort -> new Expected(ExpectedResult(Success(Coll(true, true, true, true, true, true, true, true, true, true, false, false, true, false, false, true)), None)), + -1.toShort-> new Expected(ExpectedResult(Success(Coll(true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true)), None)), + -10001.toShort-> new Expected(ExpectedResult(Success(Coll(true, true, false, true, true, false, false, false, true, true, true, false, true, true, true, true)), None)) + ), + toBits + ) + + lazy val shiftLeft = newFeature( + { (x: (Short, Int)) => (x._1 << x._2).toShort }, + "{ (x: (Short, Int)) => x._1.shiftLeft(x._2) }", + FuncValue( + Array((1, SPair(SShort, SInt))), + MethodCall.typed[Value[SShort.type]]( + SelectField.typed[Value[SShort.type]](ValUse(1, SPair(SShort, SInt)), 1.toByte), + SShortMethods.v6Methods.find(_.name == "shiftLeft").get, + Vector(SelectField.typed[Value[SInt.type]](ValUse(1, SPair(SShort, SInt)), 2.toByte)), + Map() + ) + ), + sinceVersion = V6SoftForkVersion) + + verifyCases( + Seq( + (3.toShort, 3) -> new Expected(ExpectedResult(Success(24.toShort), None)), + (3.toShort, 8) -> new Expected(ExpectedResult(Success(768.toShort), None)), + ((-2).toShort, 10) -> new Expected(ExpectedResult(Success((-2048).toShort), None)), + ), + shiftLeft + ) + + lazy val shiftRight = newFeature( + { (x: (Short, Int)) => (x._1 >> x._2).toShort }, + "{ (x: (Short, Int)) => x._1.shiftRight(x._2) }", + FuncValue( + Array((1, SPair(SShort, SInt))), + MethodCall.typed[Value[SShort.type]]( + SelectField.typed[Value[SShort.type]](ValUse(1, SPair(SShort, SInt)), 1.toByte), + SShortMethods.v6Methods.find(_.name == "shiftRight").get, + Vector(SelectField.typed[Value[SInt.type]](ValUse(1, SPair(SShort, SInt)), 2.toByte)), + Map() + ) + ), + sinceVersion = V6SoftForkVersion) + + verifyCases( + Seq( + (24.toShort, 3) -> new Expected(ExpectedResult(Success(3.toShort), None)), + (1600.toShort, 8) -> new Expected(ExpectedResult(Success(6.toShort), None)), + ((-3200).toShort, 8) -> new Expected(ExpectedResult(Success((-13).toShort), None)) + ), + shiftRight + ) } property("Int methods equivalence (new features)") { From 8cf4264e6c080d61193e8564c4f62ee1fec52ca1 Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Tue, 10 Sep 2024 15:19:07 +0300 Subject: [PATCH 227/314] 6.0 methods for Int in LSV6 --- .../scala/sigma/LanguageSpecificationV6.scala | 217 ++++++++++++++++-- 1 file changed, 194 insertions(+), 23 deletions(-) diff --git a/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala b/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala index 725b999f6e..fbc117235a 100644 --- a/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala +++ b/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala @@ -6,11 +6,11 @@ import sigma.VersionContext.V6SoftForkVersion import org.ergoplatform.ErgoBox import org.ergoplatform.ErgoBox.Token import scorex.util.ModifierId -import scorex.utils.Shorts +import scorex.utils.{Ints, Shorts} import sigma.ast.ErgoTree.ZeroHeader import sigma.ast.SCollection.SByteArray import sigma.ast.syntax.TrueSigmaProp -import sigma.ast._ +import sigma.ast.{SInt, _} import sigma.data.{CBigInt, CBox, CHeader, ExactNumeric} import sigma.eval.{CostDetails, SigmaDsl, TracedCost} import sigma.serialization.ValueCodes.OpCode @@ -420,30 +420,201 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite => ) } - property("Int methods equivalence (new features)") { - if (activatedVersionInTests < VersionContext.V6SoftForkVersion) { - // NOTE, for such versions the new features are not supported - // which is checked below - lazy val toAbs = newFeature((x: Int) => x.toAbs, "{ (x: Int) => x.toAbs }", - sinceVersion = V6SoftForkVersion) - lazy val compareTo = newFeature((x: (Int, Int)) => x._1.compareTo(x._2), - "{ (x: (Int, Int)) => x._1.compareTo(x._2) }", - sinceVersion = V6SoftForkVersion) - lazy val bitOr = newFeature( - { (x: (Int, Int)) => x._1 | x._2 }, - "{ (x: (Int, Int)) => x._1 | x._2 }", + property("Int - 6.0 methods") { + + lazy val bitOr = newFeature( + { (x: (Int, Int)) => (x._1 | x._2)}, + "{ (x: (Int, Int)) => x._1.bitwiseOr(x._2) }", + FuncValue( + Array((1, SPair(SInt, SInt))), + MethodCall.typed[Value[SInt.type]]( + SelectField.typed[Value[SInt.type]](ValUse(1,SPair(SInt, SInt)), 1.toByte), + SIntMethods.v6Methods.find(_.name == "bitwiseOr").get, + Vector(SelectField.typed[Value[SInt.type]](ValUse(1, SPair(SInt, SInt)),2.toByte)), + Map() + ) + ), sinceVersion = V6SoftForkVersion) - lazy val bitAnd = newFeature( + + verifyCases( + Seq( + (1, 2) -> new Expected(ExpectedResult(Success(3), None)), + (1001, 2002) -> new Expected(ExpectedResult(Success(2043), None)), + (100001, 20002) -> new Expected(ExpectedResult(Success(118435), None)) + ), + bitOr + ) + + lazy val bitNot = newFeature( + { (x: Int) => ~x }, + "{ (x: Int) => x.bitwiseInverse }", + FuncValue( + Array((1, SInt)), + MethodCall.typed[Value[SInt.type]]( + ValUse(1, SInt), + SIntMethods.v6Methods.find(_.name == "bitwiseInverse").get, + Vector(), + Map() + ) + ), + sinceVersion = V6SoftForkVersion) + + verifyCases( + Seq( + 1 -> new Expected(ExpectedResult(Success(-2), None)), + 10001 -> new Expected(ExpectedResult(Success(-10002), None)), + Int.MinValue -> new Expected(ExpectedResult(Success(Int.MaxValue), None)) + ), + bitNot + ) + + lazy val bitAnd = newFeature( { (x: (Int, Int)) => x._1 & x._2 }, - "{ (x: (Int, Int)) => x._1 & x._2 }", + "{ (x: (Int, Int)) => x._1.bitwiseAnd(x._2) }", + FuncValue( + Array((1, SPair(SInt, SInt))), + MethodCall.typed[Value[SInt.type]]( + SelectField.typed[Value[SInt.type]](ValUse(1, SPair(SInt, SInt)), 1.toByte), + SIntMethods.v6Methods.find(_.name == "bitwiseAnd").get, + Vector(SelectField.typed[Value[SInt.type]](ValUse(1, SPair(SInt, SInt)),2.toByte)), + Map() + ) + ), sinceVersion = V6SoftForkVersion) - forAll { x: Int => - Seq(toAbs).foreach(_.checkEquality(x)) - } - forAll { x: (Int, Int) => - Seq(compareTo, bitOr, bitAnd).foreach(_.checkEquality(x)) - } - } + + verifyCases( + Seq( + (3, 5) -> new Expected(ExpectedResult(Success(1), None)), + (10001, 2202) -> new Expected(ExpectedResult(Success(16), None)), + (-10001, 200202) -> new Expected(ExpectedResult(Success(198666), None)) + ), + bitAnd + ) + + lazy val bitXor = newFeature( + { (x: (Int, Int)) => (x._1 ^ x._2) }, + "{ (x: (Int, Int)) => x._1.bitwiseXor(x._2) }", + FuncValue( + Array((1, SPair(SInt, SInt))), + MethodCall.typed[Value[SInt.type]]( + SelectField.typed[Value[SInt.type]](ValUse(1, SPair(SInt, SInt)), 1.toByte), + SIntMethods.v6Methods.find(_.name == "bitwiseXor").get, + Vector(SelectField.typed[Value[SInt.type]](ValUse(1, SPair(SInt, SInt)),2.toByte)), + Map() + ) + ), + sinceVersion = V6SoftForkVersion) + + verifyCases( + Seq( + (3, 5) -> new Expected(ExpectedResult(Success(6), None)), + (10001, 2202) -> new Expected(ExpectedResult(Success(12171), None)), + (-10001, 200202) -> new Expected(ExpectedResult(Success(-207131), None)) + ), + bitXor + ) + + lazy val toBigEndianBytes = newFeature[Int, Coll[Byte]]( + { x: Int => Colls.fromArray(Ints.toByteArray(x)) }, + "{ (x: Int) => x.toBytes }", + FuncValue( + Array((1, SInt)), + MethodCall.typed[Value[SCollection[SInt.type]]]( + ValUse(1, SInt), + SIntMethods.getMethodByName("toBytes"), + Vector(), + Map() + ) + ), + sinceVersion = V6SoftForkVersion) + + verifyCases( + Seq( + 127 -> new Expected(ExpectedResult(Success(Coll(0.toByte, 0.toByte, 0.toByte, 127.toByte)), None)), + Short.MaxValue.toInt -> new Expected(ExpectedResult(Success(Coll(0.toByte, 0.toByte, 127.toByte, (-1).toByte)), None)), + Short.MinValue.toInt -> new Expected(ExpectedResult(Success(Coll((-1).toByte, (-1).toByte, (-128).toByte, 0.toByte)), None)), + Int.MaxValue.toInt -> new Expected(ExpectedResult(Success(Coll(127.toByte, (-1).toByte, (-1).toByte, (-1).toByte)), None)) + ), + toBigEndianBytes + ) + + def byte2Bools(b: Byte): Seq[Boolean] = + (0 to 7 map isBitSet(b)).reverse + + def isBitSet(byte: Byte)(bit: Int): Boolean = + ((byte >> bit) & 1) == 1 + + lazy val toBits = newFeature[Int, Coll[Boolean]]( + { x: Int => Colls.fromArray(Ints.toByteArray(x).flatMap(b => byte2Bools(b).toArray)) }, + "{ (x: Int) => x.toBits }", + FuncValue( + Array((1, SInt)), + MethodCall.typed[Value[SCollection[SInt.type]]]( + ValUse(1, SInt), + SIntMethods.getMethodByName("toBits"), + Vector(), + Map() + ) + ), + sinceVersion = V6SoftForkVersion) + + verifyCases( + Seq( + 83 -> new Expected(ExpectedResult(Success(Coll(false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, false, true, false, false, true, true)), None)), + -55 -> new Expected(ExpectedResult(Success(Coll(true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, false, false, true, false, false, true)), None)), + -1 -> new Expected(ExpectedResult(Success(Coll(true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true)), None)), + -10001 -> new Expected(ExpectedResult(Success(Coll(true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, false, true, true, false, false, false, true, true, true, false, true, true, true, true)), None)) + ), + toBits + ) + + lazy val shiftLeft = newFeature( + { (x: (Int, Int)) => (x._1 << x._2) }, + "{ (x: (Int, Int)) => x._1.shiftLeft(x._2) }", + FuncValue( + Array((1, SPair(SInt, SInt))), + MethodCall.typed[Value[SInt.type]]( + SelectField.typed[Value[SInt.type]](ValUse(1, SPair(SInt, SInt)), 1.toByte), + SIntMethods.v6Methods.find(_.name == "shiftLeft").get, + Vector(SelectField.typed[Value[SInt.type]](ValUse(1, SPair(SInt, SInt)), 2.toByte)), + Map() + ) + ), + sinceVersion = V6SoftForkVersion) + + verifyCases( + Seq( + (3, 3) -> new Expected(ExpectedResult(Success(24), None)), + (3, 8) -> new Expected(ExpectedResult(Success(768), None)), + (-2, 10) -> new Expected(ExpectedResult(Success(-2048), None)), + (-222, 10) -> new Expected(ExpectedResult(Success(-227328), None)) + ), + shiftLeft + ) + + lazy val shiftRight = newFeature( + { (x: (Int, Int)) => (x._1 >> x._2) }, + "{ (x: (Int, Int)) => x._1.shiftRight(x._2) }", + FuncValue( + Array((1, SPair(SInt, SInt))), + MethodCall.typed[Value[SInt.type]]( + SelectField.typed[Value[SInt.type]](ValUse(1, SPair(SInt, SInt)), 1.toByte), + SIntMethods.v6Methods.find(_.name == "shiftRight").get, + Vector(SelectField.typed[Value[SInt.type]](ValUse(1, SPair(SInt, SInt)), 2.toByte)), + Map() + ) + ), + sinceVersion = V6SoftForkVersion) + + verifyCases( + Seq( + (24, 3) -> new Expected(ExpectedResult(Success(3), None)), + (1600, 8) -> new Expected(ExpectedResult(Success(6), None)), + (-3200, 8) -> new Expected(ExpectedResult(Success(-13), None)), + (-320019, 18) -> new Expected(ExpectedResult(Success(-2), None)) + ), + shiftRight + ) } property("Long methods equivalence (new features)") { From fa2c2dfc7fe0f1dc0102901bf7ce75d1005af87c Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Wed, 11 Sep 2024 14:11:39 +0300 Subject: [PATCH 228/314] Long tests in LSV6, shift check in shiftRight --- .../main/scala/sigma/data/ExactIntegral.scala | 32 ++- .../scala/sigma/LanguageSpecificationV6.scala | 237 +++++++++++++++--- .../test/scala/sigma/SigmaDslTesting.scala | 7 +- 3 files changed, 242 insertions(+), 34 deletions(-) diff --git a/data/shared/src/main/scala/sigma/data/ExactIntegral.scala b/data/shared/src/main/scala/sigma/data/ExactIntegral.scala index 418bc1837b..4b0d9cb720 100644 --- a/data/shared/src/main/scala/sigma/data/ExactIntegral.scala +++ b/data/shared/src/main/scala/sigma/data/ExactIntegral.scala @@ -44,7 +44,13 @@ object ExactIntegral { override def bitwiseAnd(x: Byte, y: Byte): Byte = (x & y).toByte override def bitwiseXor(x: Byte, y: Byte): Byte = (x ^ y).toByte override def shiftLeft(x: Byte, bits: Int): Byte = (x << bits).toByte - override def shiftRight(x: Byte, bits: Int): Byte = (x >> bits).toByte + override def shiftRight(x: Byte, bits: Int): Byte = { + if (bits < 0 || bits >= 8){ + throw new IllegalArgumentException(s"Wrong argument in Byte.shiftRight: bits < 0 || bits >= 8 ($bits)") + } else { + (x >> bits).toByte + } + } } implicit object ShortIsExactIntegral extends ExactIntegral[Short] { @@ -59,7 +65,13 @@ object ExactIntegral { override def bitwiseAnd(x: Short, y: Short): Short = (x & y).toShort override def bitwiseXor(x: Short, y: Short): Short = (x ^ y).toShort override def shiftLeft(x: Short, y: Int): Short = (x << y).toShort - override def shiftRight(x: Short, bits: Int): Short = (x >> bits).toShort + override def shiftRight(x: Short, bits: Int): Short = { + if (bits < 0 || bits >= 16){ + throw new IllegalArgumentException(s"Wrong argument in Short.shiftRight: bits < 0 || bits >= 16 ($bits)") + } else { + (x >> bits).toShort + } + } } implicit object IntIsExactIntegral extends ExactIntegral[Int] { @@ -74,7 +86,13 @@ object ExactIntegral { override def bitwiseAnd(x: Int, y: Int): Int = x & y override def bitwiseXor(x: Int, y: Int): Int = x ^ y override def shiftLeft(x: Int, y: Int): Int = x << y - override def shiftRight(x: Int, bits: Int): Int = x >> bits + override def shiftRight(x: Int, bits: Int): Int = { + if (bits < 0 || bits >= 32){ + throw new IllegalArgumentException(s"Wrong argument in Int.shiftRight: bits < 0 || bits >= 32 ($bits)") + } else { + x >> bits + } + } } implicit object LongIsExactIntegral extends ExactIntegral[Long] { @@ -89,6 +107,12 @@ object ExactIntegral { override def bitwiseAnd(x: Long, y: Long): Long = x & y override def bitwiseXor(x: Long, y: Long): Long = x ^ y override def shiftLeft(x: Long, y: Int): Long = x << y - override def shiftRight(x: Long, bits: Int): Long = x >> bits + override def shiftRight(x: Long, bits: Int): Long = { + if (bits < 0 || bits >= 64){ + throw new IllegalArgumentException(s"Wrong argument in Long.shiftRight: bits < 0 || bits >= 64 ($bits)") + } else { + x >> bits + } + } } } diff --git a/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala b/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala index fbc117235a..b7dd5b028d 100644 --- a/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala +++ b/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala @@ -6,7 +6,7 @@ import sigma.VersionContext.V6SoftForkVersion import org.ergoplatform.ErgoBox import org.ergoplatform.ErgoBox.Token import scorex.util.ModifierId -import scorex.utils.{Ints, Shorts} +import scorex.utils.{Ints, Longs, Shorts} import sigma.ast.ErgoTree.ZeroHeader import sigma.ast.SCollection.SByteArray import sigma.ast.syntax.TrueSigmaProp @@ -20,7 +20,7 @@ import sigmastate.utils.Extensions.ByteOpsForSigma import sigmastate.utils.Helpers import java.math.BigInteger -import scala.util.Success +import scala.util.{Failure, Success} /** This suite tests all operations for v6.0 version of the language. * The base classes establish the infrastructure for the tests. @@ -226,7 +226,8 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite => Seq( (24.toByte, 3) -> new Expected(ExpectedResult(Success(3.toByte), None)) ), - shiftRight + shiftRight, + preGeneratedSamples = Some(Seq()) ) } @@ -416,7 +417,8 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite => (1600.toShort, 8) -> new Expected(ExpectedResult(Success(6.toShort), None)), ((-3200).toShort, 8) -> new Expected(ExpectedResult(Success((-13).toShort), None)) ), - shiftRight + shiftRight, + preGeneratedSamples = Some(Seq()) ) } @@ -613,38 +615,215 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite => (-3200, 8) -> new Expected(ExpectedResult(Success(-13), None)), (-320019, 18) -> new Expected(ExpectedResult(Success(-2), None)) ), - shiftRight + shiftRight, + preGeneratedSamples = Some(Seq()) ) } - property("Long methods equivalence (new features)") { - if (activatedVersionInTests < VersionContext.V6SoftForkVersion) { - // NOTE, for such versions the new features are not supported - // which is checked below - lazy val toAbs = newFeature((x: Long) => x.toAbs, "{ (x: Long) => x.toAbs }", - sinceVersion = V6SoftForkVersion) - lazy val compareTo = newFeature((x: (Long, Long)) => x._1.compareTo(x._2), - "{ (x: (Long, Long)) => x._1.compareTo(x._2) }", - sinceVersion = V6SoftForkVersion) + property("Long - 6.0 methods") { - lazy val bitOr = newFeature( - { (x: (Long, Long)) => x._1 | x._2 }, - "{ (x: (Long, Long)) => x._1 | x._2 }", - sinceVersion = V6SoftForkVersion) + lazy val bitOr = newFeature( + { (x: (Long, Long)) => (x._1 | x._2)}, + "{ (x: (Long, Long)) => x._1.bitwiseOr(x._2) }", + FuncValue( + Array((1, SPair(SLong, SLong))), + MethodCall.typed[Value[SLong.type]]( + SelectField.typed[Value[SLong.type]](ValUse(1,SPair(SLong, SLong)), 1.toByte), + SLongMethods.v6Methods.find(_.name == "bitwiseOr").get, + Vector(SelectField.typed[Value[SLong.type]](ValUse(1, SPair(SLong, SLong)),2.toByte)), + Map() + ) + ), + sinceVersion = V6SoftForkVersion) - lazy val bitAnd = newFeature( - { (x: (Long, Long)) => x._1 & x._2 }, - "{ (x: (Long, Long)) => x._1 & x._2 }", - sinceVersion = V6SoftForkVersion) + verifyCases( + Seq( + (1L, 2L) -> new Expected(ExpectedResult(Success(3L), None)), + (1001L, 2002L) -> new Expected(ExpectedResult(Success(2043L), None)), + (100001L, 20002L) -> new Expected(ExpectedResult(Success(118435L), None)), + (1000010111L, -22L) -> new Expected(ExpectedResult(Success(-1L), None)) + ), + bitOr, + failOnTestVectors = false + ) - forAll { x: Long => - Seq(toAbs).foreach(_.checkEquality(x)) - } - forAll { x: (Long, Long) => - Seq(compareTo, bitOr, bitAnd).foreach(_.checkEquality(x)) - } - } + lazy val bitNot = newFeature( + { (x: Long) => ~x }, + "{ (x: Long) => x.bitwiseInverse }", + FuncValue( + Array((1, SLong)), + MethodCall.typed[Value[SLong.type]]( + ValUse(1, SLong), + SLongMethods.v6Methods.find(_.name == "bitwiseInverse").get, + Vector(), + Map() + ) + ), + sinceVersion = V6SoftForkVersion) + verifyCases( + Seq( + 1L -> new Expected(ExpectedResult(Success(-2L), None)), + 10001L -> new Expected(ExpectedResult(Success(-10002L), None)), + Int.MinValue.toLong -> new Expected(ExpectedResult(Success(Int.MaxValue.toLong), None)), + Long.MinValue -> new Expected(ExpectedResult(Success(Long.MaxValue), None)), + Long.MaxValue -> new Expected(ExpectedResult(Success(Long.MinValue), None)) + ), + bitNot + ) + + lazy val bitAnd = newFeature( + { (x: (Long, Long)) => x._1 & x._2 }, + "{ (x: (Long, Long)) => x._1.bitwiseAnd(x._2) }", + FuncValue( + Array((1, SPair(SLong, SLong))), + MethodCall.typed[Value[SLong.type]]( + SelectField.typed[Value[SLong.type]](ValUse(1, SPair(SLong, SLong)), 1.toByte), + SLongMethods.v6Methods.find(_.name == "bitwiseAnd").get, + Vector(SelectField.typed[Value[SLong.type]](ValUse(1, SPair(SLong, SLong)),2.toByte)), + Map() + ) + ), + sinceVersion = V6SoftForkVersion) + + verifyCases( + Seq( + (3L, 5L) -> new Expected(ExpectedResult(Success(1L), None)), + (10001L, 2202L) -> new Expected(ExpectedResult(Success(16L), None)), + (-10001L, 200202L) -> new Expected(ExpectedResult(Success(198666L), None)), + (1000010111L, -22L) -> new Expected(ExpectedResult(Success(1000010090L), None)) + ), + bitAnd + ) + + lazy val bitXor = newFeature( + { (x: (Long, Long)) => (x._1 ^ x._2) }, + "{ (x: (Long, Long)) => x._1.bitwiseXor(x._2) }", + FuncValue( + Array((1, SPair(SLong, SLong))), + MethodCall.typed[Value[SLong.type]]( + SelectField.typed[Value[SLong.type]](ValUse(1, SPair(SLong, SLong)), 1.toByte), + SLongMethods.v6Methods.find(_.name == "bitwiseXor").get, + Vector(SelectField.typed[Value[SLong.type]](ValUse(1, SPair(SLong, SLong)),2.toByte)), + Map() + ) + ), + sinceVersion = V6SoftForkVersion) + + verifyCases( + Seq( + (3L, 5L) -> new Expected(ExpectedResult(Success(6L), None)), + (10001L, 2202L) -> new Expected(ExpectedResult(Success(12171L), None)), + (-10001L, 200202L) -> new Expected(ExpectedResult(Success(-207131L), None)), + (1000010111L, -22L) -> new Expected(ExpectedResult(Success(-1000010091L), None)) + ), + bitXor + ) + + lazy val toBigEndianBytes = newFeature[Long, Coll[Byte]]( + { x: Long => Colls.fromArray(Longs.toByteArray(x)) }, + "{ (x: Long) => x.toBytes }", + FuncValue( + Array((1, SLong)), + MethodCall.typed[Value[SCollection[SLong.type]]]( + ValUse(1, SLong), + SLongMethods.getMethodByName("toBytes"), + Vector(), + Map() + ) + ), + sinceVersion = V6SoftForkVersion) + + verifyCases( + Seq( + 127L -> new Expected(ExpectedResult(Success(Coll(0.toByte, 0.toByte, 0.toByte, 0.toByte, 0.toByte, 0.toByte, 0.toByte, 127.toByte)), None)), + Short.MaxValue.toLong -> new Expected(ExpectedResult(Success(Coll(0.toByte, 0.toByte, 0.toByte, 0.toByte, 0.toByte, 0.toByte, 127.toByte, (-1).toByte)), None)), + Short.MinValue.toLong -> new Expected(ExpectedResult(Success(Coll((-1).toByte, (-1).toByte, (-1).toByte, (-1).toByte, (-1).toByte, (-1).toByte, (-128).toByte, 0.toByte)), None)), + Int.MaxValue.toLong -> new Expected(ExpectedResult(Success(Coll(0.toByte, 0.toByte, 0.toByte, 0.toByte, 127.toByte, (-1).toByte, (-1).toByte, (-1).toByte)), None)) + ), + toBigEndianBytes + ) + + def byte2Bools(b: Byte): Seq[Boolean] = + (0 to 7 map isBitSet(b)).reverse + + def isBitSet(byte: Byte)(bit: Int): Boolean = + ((byte >> bit) & 1) == 1 + + lazy val toBits = newFeature[Long, Coll[Boolean]]( + { x: Long => Colls.fromArray(Longs.toByteArray(x).flatMap(b => byte2Bools(b).toArray)) }, + "{ (x: Long) => x.toBits }", + FuncValue( + Array((1, SLong)), + MethodCall.typed[Value[SCollection[SLong.type]]]( + ValUse(1, SLong), + SLongMethods.getMethodByName("toBits"), + Vector(), + Map() + ) + ), + sinceVersion = V6SoftForkVersion) + + verifyCases( + Seq( + 83L -> new Expected(ExpectedResult(Success(Colls.fromArray(Array.fill(57)(false)).append(Coll(true, false, true, false, false, true, true))), None)), + -55L -> new Expected(ExpectedResult(Success(Colls.fromArray(Array.fill(58)(true)).append(Coll(false, false, true, false, false, true))), None)), + -1L -> new Expected(ExpectedResult(Success(Colls.fromArray(Array.fill(64)(true))), None)), + -10001L -> new Expected(ExpectedResult(Success(Colls.fromArray(Array.fill(50)(true)).append(Coll( false, true, true, false, false, false, true, true, true, false, true, true, true, true))), None)) + ), + toBits + ) + + lazy val shiftLeft = newFeature( + { (x: (Long, Int)) => (x._1 << x._2) }, + "{ (x: (Long, Int)) => x._1.shiftLeft(x._2) }", + FuncValue( + Array((1, SPair(SLong, SInt))), + MethodCall.typed[Value[SLong.type]]( + SelectField.typed[Value[SLong.type]](ValUse(1, SPair(SLong, SInt)), 1.toByte), + SLongMethods.v6Methods.find(_.name == "shiftLeft").get, + Vector(SelectField.typed[Value[SInt.type]](ValUse(1, SPair(SLong, SInt)), 2.toByte)), + Map() + ) + ), + sinceVersion = V6SoftForkVersion) + + verifyCases( + Seq( + (3L, 3) -> new Expected(ExpectedResult(Success(24L), None)), + (3L, 8) -> new Expected(ExpectedResult(Success(768L), None)), + (-2L, 10) -> new Expected(ExpectedResult(Success(-2048L), None)), + (-222L, 10) -> new Expected(ExpectedResult(Success(-227328L), None)) + ), + shiftLeft + ) + + lazy val shiftRight = newFeature( + { (x: (Long, Int)) => if(x._2 < 0 || x._2 >= 64) throw new IllegalArgumentException() else (x._1 >> x._2) }, + "{ (x: (Long, Int)) => x._1.shiftRight(x._2) }", + FuncValue( + Array((1, SPair(SLong, SInt))), + MethodCall.typed[Value[SLong.type]]( + SelectField.typed[Value[SLong.type]](ValUse(1, SPair(SLong, SInt)), 1.toByte), + SLongMethods.v6Methods.find(_.name == "shiftRight").get, + Vector(SelectField.typed[Value[SInt.type]](ValUse(1, SPair(SLong, SInt)), 2.toByte)), + Map() + ) + ), + sinceVersion = V6SoftForkVersion) + + verifyCases( + Seq( + (24L, 3) -> new Expected(ExpectedResult(Success(3L), None)), + (1600L, 8) -> new Expected(ExpectedResult(Success(6L), None)), + (-3200L, 8) -> new Expected(ExpectedResult(Success(-13L), None)), + (-320019L, 18) -> new Expected(ExpectedResult(Success(-2L), None)), + (-320019L, 63) -> new Expected(ExpectedResult(Success(-1L), None)), + (24L, -1) -> new Expected(ExpectedResult(Failure(new IllegalArgumentException()), None)) + ), + shiftRight, + preGeneratedSamples = Some(Seq()) + ) } property("BigInt methods equivalence (new features)") { diff --git a/sc/shared/src/test/scala/sigma/SigmaDslTesting.scala b/sc/shared/src/test/scala/sigma/SigmaDslTesting.scala index d334ac4653..6ab62e39a9 100644 --- a/sc/shared/src/test/scala/sigma/SigmaDslTesting.scala +++ b/sc/shared/src/test/scala/sigma/SigmaDslTesting.scala @@ -940,7 +940,12 @@ class SigmaDslTesting extends AnyPropSpec funcRes.isFailure shouldBe true } if(isSupportedIn(VersionContext.current)) { - Try(scalaFunc(input)) shouldBe expected.value + val res = Try(scalaFunc(input)) + if(expected.value.isSuccess) { + res shouldBe expected.value + } else { + res.isFailure shouldBe true + } } else { Try(scalaFunc(input)).isFailure shouldBe true } From 48db43217fb1d3bf8846fb310e6520c4d30a2cb3 Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Wed, 11 Sep 2024 15:02:27 +0300 Subject: [PATCH 229/314] shiftLeft/shiftRight shift limit --- .../main/scala/sigma/data/BigIntegerOps.scala | 18 ++++++-- .../main/scala/sigma/data/ExactIntegral.scala | 42 +++++++++++++++---- 2 files changed, 50 insertions(+), 10 deletions(-) diff --git a/data/shared/src/main/scala/sigma/data/BigIntegerOps.scala b/data/shared/src/main/scala/sigma/data/BigIntegerOps.scala index 2e1d2f62ce..8d272439f4 100644 --- a/data/shared/src/main/scala/sigma/data/BigIntegerOps.scala +++ b/data/shared/src/main/scala/sigma/data/BigIntegerOps.scala @@ -101,9 +101,21 @@ object NumericOps { override def bitwiseXor(x: BigInt, y: BigInt): BigInt = x.xor(y) - override def shiftLeft(x: BigInt, y: Int): BigInt = x.shiftLeft(y) - - override def shiftRight(x: BigInt, y: Int): BigInt = x.shiftRight(y) + override def shiftLeft(x: BigInt, bits: Int): BigInt = { + if (bits < 0 || bits >= 256) { + throw new IllegalArgumentException(s"Wrong argument in BigInt.shiftRight: bits < 0 || bits >= 256 ($bits)") + } else { + x.shiftLeft(bits) + } + } + + override def shiftRight(x: BigInt, bits: Int): BigInt = { + if (bits < 0 || bits >= 256) { + throw new IllegalArgumentException(s"Wrong argument in BigInt.shiftRight: bits < 0 || bits >= 256 ($bits)") + } else { + x.shiftRight(bits) + } + } } /** The instance of [[scalan.ExactOrdering]] typeclass for [[BigInt]]. */ diff --git a/data/shared/src/main/scala/sigma/data/ExactIntegral.scala b/data/shared/src/main/scala/sigma/data/ExactIntegral.scala index 4b0d9cb720..2bd7fbe341 100644 --- a/data/shared/src/main/scala/sigma/data/ExactIntegral.scala +++ b/data/shared/src/main/scala/sigma/data/ExactIntegral.scala @@ -43,9 +43,15 @@ object ExactIntegral { override def bitwiseOr(x: Byte, y: Byte): Byte = (x | y).toByte override def bitwiseAnd(x: Byte, y: Byte): Byte = (x & y).toByte override def bitwiseXor(x: Byte, y: Byte): Byte = (x ^ y).toByte - override def shiftLeft(x: Byte, bits: Int): Byte = (x << bits).toByte + override def shiftLeft(x: Byte, bits: Int): Byte = { + if (bits < 0 || bits >= 8) { + throw new IllegalArgumentException(s"Wrong argument in Byte.shiftRight: bits < 0 || bits >= 8 ($bits)") + } else { + (x << bits).toByte + } + } override def shiftRight(x: Byte, bits: Int): Byte = { - if (bits < 0 || bits >= 8){ + if (bits < 0 || bits >= 8) { throw new IllegalArgumentException(s"Wrong argument in Byte.shiftRight: bits < 0 || bits >= 8 ($bits)") } else { (x >> bits).toByte @@ -64,7 +70,13 @@ object ExactIntegral { override def bitwiseOr(x: Short, y: Short): Short = (x | y).toShort override def bitwiseAnd(x: Short, y: Short): Short = (x & y).toShort override def bitwiseXor(x: Short, y: Short): Short = (x ^ y).toShort - override def shiftLeft(x: Short, y: Int): Short = (x << y).toShort + override def shiftLeft(x: Short, bits: Int): Short = { + if (bits < 0 || bits >= 16) { + throw new IllegalArgumentException(s"Wrong argument in Short.shiftRight: bits < 0 || bits >= 16 ($bits)") + } else { + (x << bits).toShort + } + } override def shiftRight(x: Short, bits: Int): Short = { if (bits < 0 || bits >= 16){ throw new IllegalArgumentException(s"Wrong argument in Short.shiftRight: bits < 0 || bits >= 16 ($bits)") @@ -85,9 +97,17 @@ object ExactIntegral { override def bitwiseOr(x: Int, y: Int): Int = x | y override def bitwiseAnd(x: Int, y: Int): Int = x & y override def bitwiseXor(x: Int, y: Int): Int = x ^ y - override def shiftLeft(x: Int, y: Int): Int = x << y + + override def shiftLeft(x: Int, bits: Int): Int = { + if (bits < 0 || bits >= 32) { + throw new IllegalArgumentException(s"Wrong argument in Byte.shiftRight: bits < 0 || bits >= 32 ($bits)") + } else { + x << bits + } + } + override def shiftRight(x: Int, bits: Int): Int = { - if (bits < 0 || bits >= 32){ + if (bits < 0 || bits >= 32) { throw new IllegalArgumentException(s"Wrong argument in Int.shiftRight: bits < 0 || bits >= 32 ($bits)") } else { x >> bits @@ -106,9 +126,17 @@ object ExactIntegral { override def bitwiseOr(x: Long, y: Long): Long = x | y override def bitwiseAnd(x: Long, y: Long): Long = x & y override def bitwiseXor(x: Long, y: Long): Long = x ^ y - override def shiftLeft(x: Long, y: Int): Long = x << y + + override def shiftLeft(x: Long, bits: Int): Long = { + if (bits < 0 || bits >= 64) { + throw new IllegalArgumentException(s"Wrong argument in Long.shiftRight: bits < 0 || bits >= 64 ($bits)") + } else { + x << bits + } + } + override def shiftRight(x: Long, bits: Int): Long = { - if (bits < 0 || bits >= 64){ + if (bits < 0 || bits >= 64) { throw new IllegalArgumentException(s"Wrong argument in Long.shiftRight: bits < 0 || bits >= 64 ($bits)") } else { x >> bits From a2f3030d877f692c80c24ab74318c08c7df06bbd Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Thu, 12 Sep 2024 00:01:40 +0300 Subject: [PATCH 230/314] bigint - LSV6 tests --- .../src/main/scala/sigma/ast/methods.scala | 4 +- .../scala/sigma/LanguageSpecificationV6.scala | 270 ++++++++++++++---- 2 files changed, 221 insertions(+), 53 deletions(-) diff --git a/data/shared/src/main/scala/sigma/ast/methods.scala b/data/shared/src/main/scala/sigma/ast/methods.scala index 1e8fb911bb..34c87096cd 100644 --- a/data/shared/src/main/scala/sigma/ast/methods.scala +++ b/data/shared/src/main/scala/sigma/ast/methods.scala @@ -360,7 +360,7 @@ object SNumericTypeMethods extends MethodsContainer { .withInfo(MethodCall, """ Returns a big-endian representation of this numeric in a collection of Booleans. | Each boolean corresponds to one bit. - """.stripMargin) + """.stripMargin) // todo: describe shift arg and its limits val ShiftRightMethod: SMethod = SMethod( this, "shiftRight", SFunc(Array(tNum, SInt), tNum), 13, BitwiseInverse_CostKind) @@ -377,7 +377,7 @@ object SNumericTypeMethods extends MethodsContainer { .withInfo(MethodCall, """ Returns a big-endian representation of this numeric in a collection of Booleans. | Each boolean corresponds to one bit. - """.stripMargin) + """.stripMargin) // todo: describe shift arg and its limits lazy val v5Methods = Array( ToByteMethod, // see Downcast diff --git a/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala b/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala index b7dd5b028d..6c1796cef0 100644 --- a/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala +++ b/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala @@ -205,7 +205,8 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite => Seq( (3.toByte, 3) -> new Expected(ExpectedResult(Success(24.toByte), None)) ), - shiftLeft + shiftLeft, + preGeneratedSamples = Some(Seq()) ) lazy val shiftRight = newFeature( @@ -394,7 +395,8 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite => (3.toShort, 8) -> new Expected(ExpectedResult(Success(768.toShort), None)), ((-2).toShort, 10) -> new Expected(ExpectedResult(Success((-2048).toShort), None)), ), - shiftLeft + shiftLeft, + preGeneratedSamples = Some(Seq()) ) lazy val shiftRight = newFeature( @@ -591,7 +593,8 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite => (-2, 10) -> new Expected(ExpectedResult(Success(-2048), None)), (-222, 10) -> new Expected(ExpectedResult(Success(-227328), None)) ), - shiftLeft + shiftLeft, + preGeneratedSamples = Some(Seq()) ) lazy val shiftRight = newFeature( @@ -643,8 +646,7 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite => (100001L, 20002L) -> new Expected(ExpectedResult(Success(118435L), None)), (1000010111L, -22L) -> new Expected(ExpectedResult(Success(-1L), None)) ), - bitOr, - failOnTestVectors = false + bitOr ) lazy val bitNot = newFeature( @@ -795,7 +797,8 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite => (-2L, 10) -> new Expected(ExpectedResult(Success(-2048L), None)), (-222L, 10) -> new Expected(ExpectedResult(Success(-227328L), None)) ), - shiftLeft + shiftLeft, + preGeneratedSamples = Some(Seq()) ) lazy val shiftRight = newFeature( @@ -826,7 +829,9 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite => ) } - property("BigInt methods equivalence (new features)") { + property("BigInt - 6.0 features") { + import sigma.data.OrderingOps.BigIntOrdering + if (activatedVersionInTests < VersionContext.V6SoftForkVersion) { // The `Upcast(bigInt, SBigInt)` node is never produced by ErgoScript compiler, but is still valid ErgoTree. // Fixed in 6.0 @@ -841,50 +846,6 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite => SBigInt.downcast(CBigInt(new BigInteger("0", 16)).asInstanceOf[AnyVal]), _.getMessage.contains("Cannot downcast value") ) - } else { - forAll { x: BigInteger => - SBigInt.upcast(CBigInt(x).asInstanceOf[AnyVal]) shouldBe CBigInt(x) - SBigInt.downcast(CBigInt(x).asInstanceOf[AnyVal]) shouldBe CBigInt(x) - } - } - - if (activatedVersionInTests < VersionContext.V6SoftForkVersion) { - // NOTE, for such versions the new features are not supported - // which is checked below - val toByte = newFeature((x: BigInt) => x.toByte, - "{ (x: BigInt) => x.toByte }", - FuncValue(Vector((1, SBigInt)), Downcast(ValUse(1, SBigInt), SByte)), - sinceVersion = V6SoftForkVersion) - val toShort = newFeature((x: BigInt) => x.toShort, - "{ (x: BigInt) => x.toShort }", - FuncValue(Vector((1, SBigInt)), Downcast(ValUse(1, SBigInt), SShort)), - sinceVersion = V6SoftForkVersion) - val toInt = newFeature((x: BigInt) => x.toInt, - "{ (x: BigInt) => x.toInt }", - FuncValue(Vector((1, SBigInt)), Downcast(ValUse(1, SBigInt), SInt)), - sinceVersion = V6SoftForkVersion) - val toLong = newFeature((x: BigInt) => x.toLong, - "{ (x: BigInt) => x.toLong }", - FuncValue(Vector((1, SBigInt)), Downcast(ValUse(1, SBigInt), SLong)), - sinceVersion = V6SoftForkVersion) - lazy val toAbs = newFeature((x: BigInt) => x.toAbs, "{ (x: BigInt) => x.toAbs }", - sinceVersion = V6SoftForkVersion) - lazy val compareTo = newFeature((x: (BigInt, BigInt)) => x._1.compareTo(x._2), - "{ (x: (BigInt, BigInt)) => x._1.compareTo(x._2) }", - sinceVersion = V6SoftForkVersion) - lazy val bitOr = newFeature({ (x: (BigInt, BigInt)) => x._1 | x._2 }, - "{ (x: (BigInt, BigInt)) => x._1 | x._2 }", - sinceVersion = V6SoftForkVersion) - lazy val bitAnd = newFeature({ (x: (BigInt, BigInt)) => x._1 & x._2 }, - "{ (x: (BigInt, BigInt)) => x._1 & x._2 }", - sinceVersion = V6SoftForkVersion) - - forAll { x: BigInt => - Seq(toByte, toShort, toInt, toLong, toAbs).foreach(_.checkEquality(x)) - } - forAll { x: (BigInt, BigInt) => - Seq(compareTo, bitOr, bitAnd).foreach(_.checkEquality(x)) - } forAll { x: Long => assertExceptionThrown( @@ -911,6 +872,10 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite => ) } } else { + forAll { x: BigInteger => + SBigInt.upcast(CBigInt(x).asInstanceOf[AnyVal]) shouldBe CBigInt(x) + SBigInt.downcast(CBigInt(x).asInstanceOf[AnyVal]) shouldBe CBigInt(x) + } forAll { x: Long => SLong.downcast(CBigInt(new BigInteger(x.toString)).asInstanceOf[AnyVal]) shouldBe x } @@ -924,6 +889,209 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite => SShort.downcast(CBigInt(new BigInteger(x.toString)).asInstanceOf[AnyVal]) shouldBe x } } + + lazy val bitOr = newFeature[(BigInt, BigInt), BigInt]( + { (x: (BigInt, BigInt)) => (x._1 | x._2)}, + "{ (x: (BigInt, BigInt)) => x._1.bitwiseOr(x._2) }", + FuncValue( + Array((1, SPair(SBigInt, SBigInt))), + MethodCall.typed[Value[SBigInt.type]]( + SelectField.typed[Value[SBigInt.type]](ValUse(1,SPair(SBigInt, SBigInt)), 1.toByte), + SBigIntMethods.v6Methods.find(_.name == "bitwiseOr").get, + Vector(SelectField.typed[Value[SBigInt.type]](ValUse(1, SPair(SBigInt, SBigInt)),2.toByte)), + Map() + ) + ), + sinceVersion = V6SoftForkVersion) + + verifyCases( + Seq( + (CBigInt(BigInteger.valueOf(1)), CBigInt(BigInteger.valueOf(2))) -> new Expected(ExpectedResult(Success(CBigInt(BigInteger.valueOf(3))), None)), + (CBigInt(BigInteger.valueOf(1001)), CBigInt(BigInteger.valueOf(2002))) -> new Expected(ExpectedResult(Success(CBigInt(BigInteger.valueOf(2043))), None)), + (CBigInt(BigInteger.valueOf(100001)), CBigInt(BigInteger.valueOf(20002))) -> new Expected(ExpectedResult(Success(CBigInt(BigInteger.valueOf(118435))), None)), + (CBigInt(BigInteger.valueOf(1000010111)), CBigInt(BigInteger.valueOf(-22))) -> new Expected(ExpectedResult(Success(CBigInt(BigInteger.valueOf(-1))), None)) + ), + bitOr + ) + + lazy val bitNot = newFeature[BigInt, BigInt]( + { (x: BigInt) => CBigInt(x.asInstanceOf[CBigInt].wrappedValue.not()) }, + "{ (x: BigInt) => x.bitwiseInverse }", + FuncValue( + Array((1, SBigInt)), + MethodCall.typed[Value[SBigInt.type]]( + ValUse(1, SBigInt), + SBigIntMethods.v6Methods.find(_.name == "bitwiseInverse").get, + Vector(), + Map() + ) + ), + sinceVersion = V6SoftForkVersion) + + verifyCases( + Seq( + CBigInt(BigInteger.valueOf(1)) -> new Expected(ExpectedResult(Success(CBigInt(BigInteger.valueOf(-2))), None)), + CBigInt(BigInteger.valueOf(10001)) -> new Expected(ExpectedResult(Success(CBigInt(BigInteger.valueOf(-10002))), None)), + CBigInt(BigInteger.valueOf(Int.MinValue)) -> new Expected(ExpectedResult(Success(CBigInt(BigInteger.valueOf(Int.MaxValue))), None)), + CBigInt(BigInteger.valueOf(Long.MinValue)) -> new Expected(ExpectedResult(Success(CBigInt(BigInteger.valueOf(Long.MaxValue))), None)), + CBigInt(BigInteger.valueOf(Long.MaxValue)) -> new Expected(ExpectedResult(Success(CBigInt(BigInteger.valueOf(Long.MinValue))), None)) + ), + bitNot + ) + + lazy val bitAnd = newFeature( + { (x: (BigInt, BigInt)) => x._1.asInstanceOf[CBigInt].and(x._2.asInstanceOf[CBigInt]) }, + "{ (x: (BigInt, BigInt)) => x._1.bitwiseAnd(x._2) }", + FuncValue( + Array((1, SPair(SBigInt, SBigInt))), + MethodCall.typed[Value[SBigInt.type]]( + SelectField.typed[Value[SBigInt.type]](ValUse(1, SPair(SBigInt, SBigInt)), 1.toByte), + SBigIntMethods.v6Methods.find(_.name == "bitwiseAnd").get, + Vector(SelectField.typed[Value[SBigInt.type]](ValUse(1, SPair(SBigInt, SBigInt)), 2.toByte)), + Map() + ) + ), + sinceVersion = V6SoftForkVersion) + + verifyCases( + Seq( + (CBigInt(BigInteger.valueOf(3)), CBigInt(BigInteger.valueOf(5))) -> new Expected(ExpectedResult(Success(CBigInt(BigInteger.valueOf(1))), None)), + (CBigInt(BigInteger.valueOf(10001)), CBigInt(BigInteger.valueOf(2202))) -> new Expected(ExpectedResult(Success(CBigInt(BigInteger.valueOf(16))), None)), + (CBigInt(BigInteger.valueOf(-10001)), CBigInt(BigInteger.valueOf(200202))) -> new Expected(ExpectedResult(Success(CBigInt(BigInteger.valueOf(198666))), None)), + (CBigInt(BigInteger.valueOf(1000010111)), CBigInt(BigInteger.valueOf(-22))) -> new Expected(ExpectedResult(Success(CBigInt(BigInteger.valueOf(1000010090))), None)) + ), + bitAnd + ) + + lazy val bitXor = newFeature( + { (x: (BigInt, BigInt)) => x._1.asInstanceOf[CBigInt].xor(x._2.asInstanceOf[CBigInt]) }, + "{ (x: (BigInt, BigInt)) => x._1.bitwiseXor(x._2) }", + FuncValue( + Array((1, SPair(SBigInt, SBigInt))), + MethodCall.typed[Value[SBigInt.type]]( + SelectField.typed[Value[SBigInt.type]](ValUse(1, SPair(SBigInt, SBigInt)), 1.toByte), + SBigIntMethods.v6Methods.find(_.name == "bitwiseXor").get, + Vector(SelectField.typed[Value[SBigInt.type]](ValUse(1, SPair(SBigInt, SBigInt)),2.toByte)), + Map() + ) + ), + sinceVersion = V6SoftForkVersion) + + verifyCases( + Seq( + (CBigInt(BigInteger.valueOf(3)), CBigInt(BigInteger.valueOf(5))) -> new Expected(ExpectedResult(Success(CBigInt(BigInteger.valueOf(6))), None)), + (CBigInt(BigInteger.valueOf(10001)), CBigInt(BigInteger.valueOf(2202))) -> new Expected(ExpectedResult(Success(CBigInt(BigInteger.valueOf(12171))), None)), + (CBigInt(BigInteger.valueOf(-10001)), CBigInt(BigInteger.valueOf(200202))) -> new Expected(ExpectedResult(Success(CBigInt(BigInteger.valueOf(-207131))), None)), + (CBigInt(BigInteger.valueOf(1000010111)), CBigInt(BigInteger.valueOf(-22))) -> new Expected(ExpectedResult(Success(CBigInt(BigInteger.valueOf(-1000010091))), None)) + ), + bitXor + ) + + lazy val toBigEndianBytes = newFeature[BigInt, Coll[Byte]]( + { x: BigInt => x.toBytes }, + "{ (x: BigInt) => x.toBytes }", + FuncValue( + Array((1, SBigInt)), + MethodCall.typed[Value[SCollection[SBigInt.type]]]( + ValUse(1, SBigInt), + SBigIntMethods.getMethodByName("toBytes"), + Vector(), + Map() + ) + ), + sinceVersion = V6SoftForkVersion) + + verifyCases( + Seq( + CBigInt(BigInteger.valueOf(127)) -> new Expected(ExpectedResult(Success(Coll(127.toByte)), None)), + CBigInt(BigInteger.valueOf(Short.MaxValue)) -> new Expected(ExpectedResult(Success(Coll(127.toByte, (-1).toByte)), None)), + CBigInt(BigInteger.valueOf(Short.MinValue)) -> new Expected(ExpectedResult(Success(Coll((-128).toByte, 0.toByte)), None)), + CBigInt(BigInteger.valueOf(Int.MaxValue)) -> new Expected(ExpectedResult(Success(Coll(127.toByte, (-1).toByte, (-1).toByte, (-1).toByte)), None)) + ), + toBigEndianBytes + ) + + def byte2Bools(b: Byte): Seq[Boolean] = + (0 to 7 map isBitSet(b)).reverse + + def isBitSet(byte: Byte)(bit: Int): Boolean = + ((byte >> bit) & 1) == 1 + + lazy val toBits = newFeature[BigInt, Coll[Boolean]]( + { x: BigInt => Colls.fromArray(x.toBytes.toArray.flatMap(b => byte2Bools(b).toArray)) }, + "{ (x: BigInt) => x.toBits }", + FuncValue( + Array((1, SBigInt)), + MethodCall.typed[Value[SCollection[SBigInt.type]]]( + ValUse(1, SBigInt), + SBigIntMethods.getMethodByName("toBits"), + Vector(), + Map() + ) + ), + sinceVersion = V6SoftForkVersion) + + verifyCases( + Seq( + CBigInt(BigInteger.valueOf(83)) -> new Expected(ExpectedResult(Success(Coll(false, true, false, true, false, false, true, true)), None)), + CBigInt(BigInteger.valueOf(-55)) -> new Expected(ExpectedResult(Success(Coll(true, true, false, false, true, false, false, true)), None)), + CBigInt(BigInteger.valueOf(-1L)) -> new Expected(ExpectedResult(Success(Colls.fromArray(Array.fill(8)(true))), None)), + CBigInt(BigInteger.valueOf(-10001L)) -> new Expected(ExpectedResult(Success(Coll(true,true,false,true,true,false,false,false,true,true,true,false,true,true,true,true)), None)) + ), + toBits + ) + + lazy val shiftLeft = newFeature( + { (x: (BigInt, Int)) => (x._1.asInstanceOf[BigInt].shiftLeft(x._2)) }, + "{ (x: (BigInt, Int)) => x._1.shiftLeft(x._2) }", + FuncValue( + Array((1, SPair(SBigInt, SInt))), + MethodCall.typed[Value[SBigInt.type]]( + SelectField.typed[Value[SBigInt.type]](ValUse(1, SPair(SBigInt, SInt)), 1.toByte), + SBigIntMethods.v6Methods.find(_.name == "shiftLeft").get, + Vector(SelectField.typed[Value[SInt.type]](ValUse(1, SPair(SBigInt, SInt)), 2.toByte)), + Map() + ) + ), + sinceVersion = V6SoftForkVersion) + + verifyCases( + Seq( + (CBigInt(BigInteger.valueOf(3)), 3) -> new Expected(ExpectedResult(Success(CBigInt(BigInteger.valueOf(24))), None)), + (CBigInt(BigInteger.valueOf(3)), 8) -> new Expected(ExpectedResult(Success(CBigInt(BigInteger.valueOf(768))), None)), + (CBigInt(BigInteger.valueOf(-2)), 10) -> new Expected(ExpectedResult(Success(CBigInt(BigInteger.valueOf(-2048))), None)), + (CBigInt(BigInteger.valueOf(-222)), 10) -> new Expected(ExpectedResult(Success(CBigInt(BigInteger.valueOf(-227328L))), None)) + ), + shiftLeft, + preGeneratedSamples = Some(Seq()) + ) + + lazy val shiftRight = newFeature( + { (x: (BigInt, Int)) => if(x._2 < 0 || x._2 >= 256) throw new IllegalArgumentException() else (x._1.asInstanceOf[BigInt].shiftRight(x._2)) }, + "{ (x: (BigInt, Int)) => x._1.shiftRight(x._2) }", + FuncValue( + Array((1, SPair(SBigInt, SInt))), + MethodCall.typed[Value[SBigInt.type]]( + SelectField.typed[Value[SBigInt.type]](ValUse(1, SPair(SBigInt, SInt)), 1.toByte), + SBigIntMethods.v6Methods.find(_.name == "shiftRight").get, + Vector(SelectField.typed[Value[SInt.type]](ValUse(1, SPair(SBigInt, SInt)), 2.toByte)), + Map() + ) + ), + sinceVersion = V6SoftForkVersion) + + verifyCases( + Seq( + (CBigInt(BigInteger.valueOf(24)), 3) -> new Expected(ExpectedResult(Success(CBigInt(BigInteger.valueOf(3))), None)), + (CBigInt(BigInteger.valueOf(1600)), 8) -> new Expected(ExpectedResult(Success(CBigInt(BigInteger.valueOf(6))), None)), + (CBigInt(BigInteger.valueOf(-3200)), 8) -> new Expected(ExpectedResult(Success(CBigInt(BigInteger.valueOf(-13))), None)), + (CBigInt(BigInteger.valueOf(-320019)), 18) -> new Expected(ExpectedResult(Success(CBigInt(BigInteger.valueOf(-2))), None)), + (CBigInt(BigInteger.valueOf(-320019)), 63) -> new Expected(ExpectedResult(Success(CBigInt(BigInteger.valueOf(-1))), None)), + (CBigInt(BigInteger.valueOf(24)), -1) -> new Expected(ExpectedResult(Failure(new IllegalArgumentException()), None)) + ), + shiftRight, + preGeneratedSamples = Some(Seq()) + ) } property("Box properties equivalence (new features)") { From 297265f0989d3b5e6f2ab7eaff6518479e29ed94 Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Thu, 12 Sep 2024 18:26:22 +0300 Subject: [PATCH 231/314] arg descs, 2.11 comp fix, BOS tests fixed --- .../src/main/scala/sigma/ast/methods.scala | 28 +++++++++---------- .../scala/sigma/LanguageSpecificationV6.scala | 10 +++---- .../utxo/BasicOpsSpecification.scala | 8 +++--- 3 files changed, 22 insertions(+), 24 deletions(-) diff --git a/data/shared/src/main/scala/sigma/ast/methods.scala b/data/shared/src/main/scala/sigma/ast/methods.scala index 34c87096cd..634145c6e1 100644 --- a/data/shared/src/main/scala/sigma/ast/methods.scala +++ b/data/shared/src/main/scala/sigma/ast/methods.scala @@ -289,10 +289,7 @@ object SNumericTypeMethods extends MethodsContainer { case SBigIntMethods => BigIntIsExactIntegral.bitwiseInverse(obj.asInstanceOf[BigInt]) } }) - .withInfo(PropertyCall, - """ Returns a big-endian representation of this numeric in a collection of Booleans. - | Each boolean corresponds to one bit. - """.stripMargin) + .withInfo(PropertyCall, desc = "Returns bitwise inverse of this numeric. ") val BitwiseOrMethod: SMethod = SMethod( this, "bitwiseOr", SFunc(Array(tNum, tNum), tNum), 9, BitwiseInverse_CostKind) @@ -307,9 +304,8 @@ object SNumericTypeMethods extends MethodsContainer { } }) .withInfo(MethodCall, - """ Returns a big-endian representation of this numeric in a collection of Booleans. - | Each boolean corresponds to one bit. - """.stripMargin) + """ Returns bitwise or of this numeric and provided one. """.stripMargin, + ArgInfo("that", "A numeric value to calculate or with.")) val BitwiseAndMethod: SMethod = SMethod( this, "bitwiseAnd", SFunc(Array(tNum, tNum), tNum), 10, BitwiseInverse_CostKind) @@ -324,9 +320,8 @@ object SNumericTypeMethods extends MethodsContainer { } }) .withInfo(MethodCall, - """ Returns a big-endian representation of this numeric in a collection of Booleans. - | Each boolean corresponds to one bit. - """.stripMargin) + """ Returns bitwise and of this numeric and provided one. """.stripMargin, + ArgInfo("that", "A numeric value to calculate and with.")) val BitwiseXorMethod: SMethod = SMethod( this, "bitwiseXor", SFunc(Array(tNum, tNum), tNum), 11, BitwiseInverse_CostKind) @@ -341,9 +336,8 @@ object SNumericTypeMethods extends MethodsContainer { } }) .withInfo(MethodCall, - """ Returns a big-endian representation of this numeric in a collection of Booleans. - | Each boolean corresponds to one bit. - """.stripMargin) + """ Returns bitwise xor of this numeric and provided one. """.stripMargin, + ArgInfo("that", "A numeric value to calculate xor with.")) val ShiftLeftMethod: SMethod = SMethod( this, "shiftLeft", SFunc(Array(tNum, SInt), tNum), 12, BitwiseInverse_CostKind) @@ -360,7 +354,9 @@ object SNumericTypeMethods extends MethodsContainer { .withInfo(MethodCall, """ Returns a big-endian representation of this numeric in a collection of Booleans. | Each boolean corresponds to one bit. - """.stripMargin) // todo: describe shift arg and its limits + """.stripMargin, + ArgInfo("bits", "Number of bit to shift to the left. Note, that bits value must be non-negative and less than " + + "the size of the number in bits (e.g. 64 for Long, 256 for BigInt)")) val ShiftRightMethod: SMethod = SMethod( this, "shiftRight", SFunc(Array(tNum, SInt), tNum), 13, BitwiseInverse_CostKind) @@ -377,7 +373,9 @@ object SNumericTypeMethods extends MethodsContainer { .withInfo(MethodCall, """ Returns a big-endian representation of this numeric in a collection of Booleans. | Each boolean corresponds to one bit. - """.stripMargin) // todo: describe shift arg and its limits + """.stripMargin, + ArgInfo("bits", "Number of bit to shift to the right. Note, that bits value must be non-negative and less than " + + "the size of the number in bits (e.g. 64 for Long, 256 for BigInt)")) lazy val v5Methods = Array( ToByteMethod, // see Downcast diff --git a/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala b/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala index 6c1796cef0..ddbc06b6b3 100644 --- a/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala +++ b/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala @@ -352,7 +352,7 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite => ((byte >> bit) & 1) == 1 lazy val toBits = newFeature[Short, Coll[Boolean]]( - { x: Short => Colls.fromArray(Shorts.toByteArray(x).flatMap(b => byte2Bools(b).toArray)) }, + { x: Short => Colls.fromArray(Shorts.toByteArray(x)).flatMap(b => Colls.fromArray(byte2Bools(b).toArray)) }, "{ (x: Short) => x.toBits }", FuncValue( Array((1, SShort)), @@ -393,7 +393,7 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite => Seq( (3.toShort, 3) -> new Expected(ExpectedResult(Success(24.toShort), None)), (3.toShort, 8) -> new Expected(ExpectedResult(Success(768.toShort), None)), - ((-2).toShort, 10) -> new Expected(ExpectedResult(Success((-2048).toShort), None)), + ((-2).toShort, 10) -> new Expected(ExpectedResult(Success((-2048).toShort), None)) ), shiftLeft, preGeneratedSamples = Some(Seq()) @@ -549,7 +549,7 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite => ((byte >> bit) & 1) == 1 lazy val toBits = newFeature[Int, Coll[Boolean]]( - { x: Int => Colls.fromArray(Ints.toByteArray(x).flatMap(b => byte2Bools(b).toArray)) }, + { x: Int => Colls.fromArray(Ints.toByteArray(x)).flatMap(b => Colls.fromArray(byte2Bools(b).toArray)) }, "{ (x: Int) => x.toBits }", FuncValue( Array((1, SInt)), @@ -753,7 +753,7 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite => ((byte >> bit) & 1) == 1 lazy val toBits = newFeature[Long, Coll[Boolean]]( - { x: Long => Colls.fromArray(Longs.toByteArray(x).flatMap(b => byte2Bools(b).toArray)) }, + { x: Long => Colls.fromArray(Longs.toByteArray(x)).flatMap(b => Colls.fromArray(byte2Bools(b).toArray)) }, "{ (x: Long) => x.toBits }", FuncValue( Array((1, SLong)), @@ -1018,7 +1018,7 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite => ((byte >> bit) & 1) == 1 lazy val toBits = newFeature[BigInt, Coll[Boolean]]( - { x: BigInt => Colls.fromArray(x.toBytes.toArray.flatMap(b => byte2Bools(b).toArray)) }, + { x: BigInt => x.toBytes.flatMap(b => Colls.fromArray(byte2Bools(b).toArray)) }, "{ (x: BigInt) => x.toBits }", FuncValue( Array((1, SBigInt)), diff --git a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala index a37a3d1079..a5d73d2442 100644 --- a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala @@ -354,7 +354,7 @@ class BasicOpsSpecification extends CompilerTestingCommons ) if (VersionContext.current.isV6SoftForkActivated) { - shiftLeftTest() + an[IllegalArgumentException] shouldBe thrownBy(shiftLeftTest()) } else { an[Exception] shouldBe thrownBy(shiftLeftTest()) } @@ -455,7 +455,7 @@ class BasicOpsSpecification extends CompilerTestingCommons ) if (VersionContext.current.isV6SoftForkActivated) { - shiftRightTest() + an[IllegalArgumentException] shouldBe thrownBy(shiftRightTest()) } else { an[Exception] shouldBe thrownBy(shiftRightTest()) } @@ -489,7 +489,7 @@ class BasicOpsSpecification extends CompilerTestingCommons ) if (VersionContext.current.isV6SoftForkActivated) { - shiftRightTest() + an[IllegalArgumentException] shouldBe thrownBy(shiftRightTest()) } else { an[Exception] shouldBe thrownBy(shiftRightTest()) } @@ -525,7 +525,7 @@ class BasicOpsSpecification extends CompilerTestingCommons ) if (VersionContext.current.isV6SoftForkActivated) { - shiftRightTest() + an[IllegalArgumentException] shouldBe thrownBy(shiftRightTest()) } else { an[Exception] shouldBe thrownBy(shiftRightTest()) } From 7e3b67625223a1db2f3af52c2a66b1eb8e13357b Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Mon, 16 Sep 2024 16:49:38 +0300 Subject: [PATCH 232/314] fixing method calls check test --- .../sigmastate/ErgoTreeSpecification.scala | 36 +++++++++++-------- 1 file changed, 22 insertions(+), 14 deletions(-) diff --git a/sc/shared/src/test/scala/sigmastate/ErgoTreeSpecification.scala b/sc/shared/src/test/scala/sigmastate/ErgoTreeSpecification.scala index 2f7217bc4c..df15125488 100644 --- a/sc/shared/src/test/scala/sigmastate/ErgoTreeSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/ErgoTreeSpecification.scala @@ -326,13 +326,19 @@ class ErgoTreeSpecification extends SigmaDslTesting with ContractsTestkit with C (SInt.typeId, Seq.empty[MInfo], false), (SLong.typeId, Seq.empty[MInfo], false), - { // SNumericType.typeId is erroneously shadowed by SGlobal.typeId - // this should be preserved in v3.x and fixed in v4.0 - (SNumericType.typeId, Seq( - MInfo(methodId = 1, SGlobalMethods.groupGeneratorMethod), - MInfo(2, SGlobalMethods.xorMethod) - ), true) - }, + (if(!isV6Activated) { + { // SNumericType.typeId is erroneously shadowed by SGlobal.typeId + // this should be preserved in v3.x and fixed in v4.0 + (SNumericType.typeId, Seq( + MInfo(methodId = 1, SGlobalMethods.groupGeneratorMethod), + MInfo(2, SGlobalMethods.xorMethod) + ), true) + } + } else { + // rechecking boolean again, after merging w. https://github.com/ScorexFoundation/sigmastate-interpreter/pull/1017 + // there will be check against numerics in 6.0 here + (SBoolean.typeId, Seq.empty[MInfo], true) + }), { // SBigInt inherit methods from SNumericType.methods // however they are not resolvable via SBigInt.typeId @@ -370,7 +376,7 @@ class ErgoTreeSpecification extends SigmaDslTesting with ContractsTestkit with C MInfo(5, IdMethod), MInfo(6, creationInfoMethod), MInfo(8, tokensMethod) - ) ++ (if (VersionContext.current.isV6SoftForkActivated) { + ) ++ (if (isV6Activated) { Seq(MInfo(7, getRegMethodV6)) } else { Seq(MInfo(7, getRegMethodV5)) @@ -404,8 +410,8 @@ class ErgoTreeSpecification extends SigmaDslTesting with ContractsTestkit with C MInfo(7, timestampMethod), MInfo(8, nBitsMethod), MInfo(9, heightMethod), MInfo(10, extensionRootMethod), MInfo(11, minerPkMethod), MInfo(12, powOnetimePkMethod), MInfo(13, powNonceMethod), MInfo(14, powDistanceMethod), MInfo(15, votesMethod) - ) ++ (if (VersionContext.current.isV6SoftForkActivated) { - Seq(MInfo(16, checkPowMethod)) + ) ++ (if (isV6Activated) { + Seq(MInfo(16, checkPowMethod)) // methods added in v6.0 } else { Seq.empty[MInfo] }), true) @@ -428,10 +434,11 @@ class ErgoTreeSpecification extends SigmaDslTesting with ContractsTestkit with C { import SGlobalMethods._ (SGlobal.typeId, Seq( MInfo(1, groupGeneratorMethod), MInfo(2, xorMethod) - ) ++ (if (isV6Activated) Seq( - // methods added in v6.0 - MInfo(3, serializeMethod) - ) else Seq.empty), true) + ) ++ (if (isV6Activated) { + Seq(MInfo(3, serializeMethod)) // methods added in v6.0 + } else { + Seq.empty[MInfo] + }), true) }, { import SCollectionMethods._ (SCollection.typeId, Seq( @@ -496,6 +503,7 @@ class ErgoTreeSpecification extends SigmaDslTesting with ContractsTestkit with C assert(canHaveMethods, s"Type $tyDesc should NOT have methods") val mc = MethodsContainer(tyDesc.typeId) + mc.methods.length shouldBe methods.length for (expectedMethod <- methods) { if (expectedMethod.isResolvableFromIds) { From 55d03cd38c3d4553520be75a837d561d68ca1cb8 Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Tue, 17 Sep 2024 01:50:22 +0300 Subject: [PATCH 233/314] addressing review comments --- .../src/main/scala/sigma/ast/methods.scala | 3 +- .../main/scala/sigma/data/ExactNumeric.scala | 9 ++-- .../scala/sigma/LanguageSpecificationV6.scala | 53 +++++++++++++------ 3 files changed, 40 insertions(+), 25 deletions(-) diff --git a/data/shared/src/main/scala/sigma/ast/methods.scala b/data/shared/src/main/scala/sigma/ast/methods.scala index 634145c6e1..6c401f8fc3 100644 --- a/data/shared/src/main/scala/sigma/ast/methods.scala +++ b/data/shared/src/main/scala/sigma/ast/methods.scala @@ -397,8 +397,7 @@ object SNumericTypeMethods extends MethodsContainer { ) protected override def getMethods(): Seq[SMethod] = { - // this .getMethods shouldn't ever be called - ??? + throw new Exception("SNumericTypeMethods.getMethods shouldn't ever be called") } /** Collection of names of numeric casting methods (like `toByte`, `toInt`, etc). */ diff --git a/data/shared/src/main/scala/sigma/data/ExactNumeric.scala b/data/shared/src/main/scala/sigma/data/ExactNumeric.scala index 56b4a9369e..244cc6b7b7 100644 --- a/data/shared/src/main/scala/sigma/data/ExactNumeric.scala +++ b/data/shared/src/main/scala/sigma/data/ExactNumeric.scala @@ -45,17 +45,14 @@ trait ExactNumeric[T] { def isBitSet(byte: Byte)(bit: Int): Boolean = ((byte >> bit) & 1) == 1 - def byte2Bools(b: Byte): Array[Boolean] = (0 to 7).toArray.reverse.map(isBitSet(b)) - val bytes = toBigEndianBytes(x) val l = bytes.length val res = new Array[Boolean](l * 8) - var offset = 0 cfor(0)(_ < l, _ + 1) { i => val b = bytes(i) - val bits = byte2Bools(b) - Array.copy(bits, 0, res, offset, 8) - offset += 8 + cfor(0)(_ < 8, _ + 1) { bitIdx => + res(i * 8 + (7 - bitIdx)) = isBitSet(b)(bitIdx) + } } Colls.fromArray(res) } diff --git a/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala b/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala index ddbc06b6b3..4ca378c35e 100644 --- a/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala +++ b/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala @@ -188,7 +188,7 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite => ) lazy val shiftLeft = newFeature( - { (x: (Byte, Int)) => (x._1 << x._2).toByte }, + { (x: (Byte, Int)) => if(x._2 < 0 || x._2 >= 8) throw new IllegalArgumentException() else (x._1 << x._2).toByte }, "{ (x: (Byte, Int)) => x._1.shiftLeft(x._2) }", FuncValue( Array((1, SPair(SByte, SInt))), @@ -203,14 +203,17 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite => verifyCases( Seq( - (3.toByte, 3) -> new Expected(ExpectedResult(Success(24.toByte), None)) + (3.toByte, 3) -> new Expected(ExpectedResult(Success(24.toByte), None)), + (3.toByte, 0) -> new Expected(ExpectedResult(Success(3.toByte), None)), + (3.toByte, -1) -> new Expected(ExpectedResult(Failure(new IllegalArgumentException()), None)), + (3.toByte, 8) -> new Expected(ExpectedResult(Failure(new IllegalArgumentException()), None)) ), shiftLeft, preGeneratedSamples = Some(Seq()) ) lazy val shiftRight = newFeature( - { (x: (Byte, Int)) => (x._1 >> x._2).toByte }, + { (x: (Byte, Int)) => if(x._2 < 0 || x._2 >= 8) throw new IllegalArgumentException() else (x._1 >> x._2).toByte }, "{ (x: (Byte, Int)) => x._1.shiftRight(x._2) }", FuncValue( Array((1, SPair(SByte, SInt))), @@ -225,7 +228,10 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite => verifyCases( Seq( - (24.toByte, 3) -> new Expected(ExpectedResult(Success(3.toByte), None)) + (24.toByte, 3) -> new Expected(ExpectedResult(Success(3.toByte), None)), + (24.toByte, 0) -> new Expected(ExpectedResult(Success(24.toByte), None)), + (24.toByte, -1) -> new Expected(ExpectedResult(Failure(new IllegalArgumentException()), None)), + (24.toByte, 8) -> new Expected(ExpectedResult(Failure(new IllegalArgumentException()), None)) ), shiftRight, preGeneratedSamples = Some(Seq()) @@ -376,7 +382,7 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite => ) lazy val shiftLeft = newFeature( - { (x: (Short, Int)) => (x._1 << x._2).toShort }, + { (x: (Short, Int)) => if(x._2 < 0 || x._2 >= 16) throw new IllegalArgumentException() else (x._1 << x._2).toShort }, "{ (x: (Short, Int)) => x._1.shiftLeft(x._2) }", FuncValue( Array((1, SPair(SShort, SInt))), @@ -393,14 +399,16 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite => Seq( (3.toShort, 3) -> new Expected(ExpectedResult(Success(24.toShort), None)), (3.toShort, 8) -> new Expected(ExpectedResult(Success(768.toShort), None)), - ((-2).toShort, 10) -> new Expected(ExpectedResult(Success((-2048).toShort), None)) + ((-2).toShort, 10) -> new Expected(ExpectedResult(Success((-2048).toShort), None)), + ((-2).toShort, 20) -> new Expected(ExpectedResult(Failure(new IllegalArgumentException()), None)), + (3.toShort, -1) -> new Expected(ExpectedResult(Failure(new IllegalArgumentException()), None)) ), shiftLeft, preGeneratedSamples = Some(Seq()) ) lazy val shiftRight = newFeature( - { (x: (Short, Int)) => (x._1 >> x._2).toShort }, + { (x: (Short, Int)) => if(x._2 < 0 || x._2 >= 16) throw new IllegalArgumentException() else (x._1 >> x._2).toShort }, "{ (x: (Short, Int)) => x._1.shiftRight(x._2) }", FuncValue( Array((1, SPair(SShort, SInt))), @@ -417,7 +425,9 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite => Seq( (24.toShort, 3) -> new Expected(ExpectedResult(Success(3.toShort), None)), (1600.toShort, 8) -> new Expected(ExpectedResult(Success(6.toShort), None)), - ((-3200).toShort, 8) -> new Expected(ExpectedResult(Success((-13).toShort), None)) + ((-3200).toShort, 8) -> new Expected(ExpectedResult(Success((-13).toShort), None)), + (3.toShort, -1) -> new Expected(ExpectedResult(Failure(new IllegalArgumentException()), None)), + (3.toShort, 16) -> new Expected(ExpectedResult(Failure(new IllegalArgumentException()), None)) ), shiftRight, preGeneratedSamples = Some(Seq()) @@ -573,7 +583,7 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite => ) lazy val shiftLeft = newFeature( - { (x: (Int, Int)) => (x._1 << x._2) }, + { (x: (Int, Int)) => if(x._2 < 0 || x._2 >= 32) throw new IllegalArgumentException() else (x._1 << x._2) }, "{ (x: (Int, Int)) => x._1.shiftLeft(x._2) }", FuncValue( Array((1, SPair(SInt, SInt))), @@ -591,14 +601,16 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite => (3, 3) -> new Expected(ExpectedResult(Success(24), None)), (3, 8) -> new Expected(ExpectedResult(Success(768), None)), (-2, 10) -> new Expected(ExpectedResult(Success(-2048), None)), - (-222, 10) -> new Expected(ExpectedResult(Success(-227328), None)) + (-222, 10) -> new Expected(ExpectedResult(Success(-227328), None)), + (-222, 32) -> new Expected(ExpectedResult(Failure(new IllegalArgumentException()), None)), + (-222, -1) -> new Expected(ExpectedResult(Failure(new IllegalArgumentException()), None)) ), shiftLeft, preGeneratedSamples = Some(Seq()) ) lazy val shiftRight = newFeature( - { (x: (Int, Int)) => (x._1 >> x._2) }, + { (x: (Int, Int)) => if(x._2 < 0 || x._2 >= 32) throw new IllegalArgumentException() else (x._1 >> x._2) }, "{ (x: (Int, Int)) => x._1.shiftRight(x._2) }", FuncValue( Array((1, SPair(SInt, SInt))), @@ -616,7 +628,9 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite => (24, 3) -> new Expected(ExpectedResult(Success(3), None)), (1600, 8) -> new Expected(ExpectedResult(Success(6), None)), (-3200, 8) -> new Expected(ExpectedResult(Success(-13), None)), - (-320019, 18) -> new Expected(ExpectedResult(Success(-2), None)) + (-320019, 18) -> new Expected(ExpectedResult(Success(-2), None)), + (-320019, 32) -> new Expected(ExpectedResult(Failure(new IllegalArgumentException()), None)), + (-320019, -1) -> new Expected(ExpectedResult(Failure(new IllegalArgumentException()), None)) ), shiftRight, preGeneratedSamples = Some(Seq()) @@ -777,7 +791,7 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite => ) lazy val shiftLeft = newFeature( - { (x: (Long, Int)) => (x._1 << x._2) }, + { (x: (Long, Int)) => if(x._2 < 0 || x._2 >= 32) throw new IllegalArgumentException() else (x._1 << x._2) }, "{ (x: (Long, Int)) => x._1.shiftLeft(x._2) }", FuncValue( Array((1, SPair(SLong, SInt))), @@ -795,7 +809,9 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite => (3L, 3) -> new Expected(ExpectedResult(Success(24L), None)), (3L, 8) -> new Expected(ExpectedResult(Success(768L), None)), (-2L, 10) -> new Expected(ExpectedResult(Success(-2048L), None)), - (-222L, 10) -> new Expected(ExpectedResult(Success(-227328L), None)) + (-222L, 10) -> new Expected(ExpectedResult(Success(-227328L), None)), + (-222L, -1) -> new Expected(ExpectedResult(Failure(new IllegalArgumentException()), None)), + (-222L, 64) -> new Expected(ExpectedResult(Failure(new IllegalArgumentException()), None)) ), shiftLeft, preGeneratedSamples = Some(Seq()) @@ -1042,7 +1058,7 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite => ) lazy val shiftLeft = newFeature( - { (x: (BigInt, Int)) => (x._1.asInstanceOf[BigInt].shiftLeft(x._2)) }, + { (x: (BigInt, Int)) => if(x._2 < 0 || x._2 >= 256) throw new IllegalArgumentException() else (x._1.asInstanceOf[BigInt].shiftLeft(x._2)) }, "{ (x: (BigInt, Int)) => x._1.shiftLeft(x._2) }", FuncValue( Array((1, SPair(SBigInt, SInt))), @@ -1060,7 +1076,9 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite => (CBigInt(BigInteger.valueOf(3)), 3) -> new Expected(ExpectedResult(Success(CBigInt(BigInteger.valueOf(24))), None)), (CBigInt(BigInteger.valueOf(3)), 8) -> new Expected(ExpectedResult(Success(CBigInt(BigInteger.valueOf(768))), None)), (CBigInt(BigInteger.valueOf(-2)), 10) -> new Expected(ExpectedResult(Success(CBigInt(BigInteger.valueOf(-2048))), None)), - (CBigInt(BigInteger.valueOf(-222)), 10) -> new Expected(ExpectedResult(Success(CBigInt(BigInteger.valueOf(-227328L))), None)) + (CBigInt(BigInteger.valueOf(-222)), 10) -> new Expected(ExpectedResult(Success(CBigInt(BigInteger.valueOf(-227328L))), None)), + (CBigInt(BigInteger.valueOf(-222)), -1) -> new Expected(ExpectedResult(Failure(new IllegalArgumentException()), None)), + (CBigInt(BigInteger.valueOf(-222)), 256) -> new Expected(ExpectedResult(Failure(new IllegalArgumentException()), None)) ), shiftLeft, preGeneratedSamples = Some(Seq()) @@ -1087,7 +1105,8 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite => (CBigInt(BigInteger.valueOf(-3200)), 8) -> new Expected(ExpectedResult(Success(CBigInt(BigInteger.valueOf(-13))), None)), (CBigInt(BigInteger.valueOf(-320019)), 18) -> new Expected(ExpectedResult(Success(CBigInt(BigInteger.valueOf(-2))), None)), (CBigInt(BigInteger.valueOf(-320019)), 63) -> new Expected(ExpectedResult(Success(CBigInt(BigInteger.valueOf(-1))), None)), - (CBigInt(BigInteger.valueOf(24)), -1) -> new Expected(ExpectedResult(Failure(new IllegalArgumentException()), None)) + (CBigInt(BigInteger.valueOf(24)), -1) -> new Expected(ExpectedResult(Failure(new IllegalArgumentException()), None)), + (CBigInt(BigInteger.valueOf(24)), 256) -> new Expected(ExpectedResult(Failure(new IllegalArgumentException()), None)) ), shiftRight, preGeneratedSamples = Some(Seq()) From 4343bc9d0bbaacebbc11dcbc4f476f8f73b3c40b Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Tue, 17 Sep 2024 13:01:56 +0300 Subject: [PATCH 234/314] fix for longToByteArray support in JS --- .../shared/src/main/scala/sigma/SigmaDataReflection.scala | 8 ++++++++ .../scala/sigmastate/utxo/BasicOpsSpecification.scala | 4 ++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/data/shared/src/main/scala/sigma/SigmaDataReflection.scala b/data/shared/src/main/scala/sigma/SigmaDataReflection.scala index a6e5de2a26..c64bdee877 100644 --- a/data/shared/src/main/scala/sigma/SigmaDataReflection.scala +++ b/data/shared/src/main/scala/sigma/SigmaDataReflection.scala @@ -86,6 +86,14 @@ object SigmaDataReflection { ) ) + registerClassEntry(classOf[LongToByteArray], + constructors = Array( + mkConstructor(Array(classOf[Value[_]])) { args => + new LongToByteArray(args(0).asInstanceOf[Value[SLong.type]]) + } + ) + ) + registerClassEntry(classOf[CalcBlake2b256], constructors = Array( mkConstructor(Array(classOf[Value[_]])) { args => diff --git a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala index 72f4063642..4a5a9be59e 100644 --- a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala @@ -213,8 +213,8 @@ class BasicOpsSpecification extends CompilerTestingCommons deserTest() } } - - property("serialize(long) is producing different result from longToByteArray()") { + + property("serialize(long) is producing different result from longToByteArray()") { def deserTest() = test("serialize", env, ext, s"""{ val l = -1000L From 1c2b99df06c840955f9dc7b57164ec6ee11979a0 Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Tue, 17 Sep 2024 17:35:17 +0300 Subject: [PATCH 235/314] more polishing in UnsignedBigInt impl --- .../src/main/scala/sigma/SigmaDsl.scala | 24 +++++++ .../src/main/scala/sigma/ast/SType.scala | 70 +++++++++++-------- .../src/main/scala/sigma/data/CBigInt.scala | 34 ++++++--- .../sigma/reflection/ReflectionData.scala | 30 +++++++- .../main/scala/sigma/util/Extensions.scala | 11 ++- .../scala/sigma/data/CSigmaDslBuilder.scala | 2 +- 6 files changed, 126 insertions(+), 45 deletions(-) diff --git a/core/shared/src/main/scala/sigma/SigmaDsl.scala b/core/shared/src/main/scala/sigma/SigmaDsl.scala index 8c8a3c2be6..3f060c1af2 100644 --- a/core/shared/src/main/scala/sigma/SigmaDsl.scala +++ b/core/shared/src/main/scala/sigma/SigmaDsl.scala @@ -170,8 +170,15 @@ trait BigInt { */ def shiftRight(n: Int): BigInt + /** + * @return unsigned representation of this BigInt, or exception if its value is negative + */ def toUnsigned: UnsignedBigInt + /** + * @return unsigned representation of this BigInt modulo `m`. Cryptographic mod operation is done, ie result is + * non-negative always + */ def toUnsignedMod(m: UnsignedBigInt): UnsignedBigInt } @@ -297,6 +304,23 @@ trait UnsignedBigInt { def subtractMod(that: UnsignedBigInt, m: UnsignedBigInt): UnsignedBigInt def multiplyMod(that: UnsignedBigInt, m: UnsignedBigInt): UnsignedBigInt + /** + * @return a big integer whose value is `this xor that` + */ + def xor(that: UnsignedBigInt): UnsignedBigInt + + /** + * @return a 256-bit signed integer whose value is (this << n). The shift distance, n, may be negative, + * in which case this method performs a right shift. (Computes floor(this * 2n).) + */ + def shiftLeft(n: Int): UnsignedBigInt + + /** + * @return a 256-bit signed integer whose value is (this >> n). Sign extension is performed. The shift distance, n, + * may be negative, in which case this method performs a left shift. (Computes floor(this / 2n).) + */ + def shiftRight(n: Int): UnsignedBigInt + def toSigned(): BigInt } diff --git a/core/shared/src/main/scala/sigma/ast/SType.scala b/core/shared/src/main/scala/sigma/ast/SType.scala index 815a70e222..c99b7b8e34 100644 --- a/core/shared/src/main/scala/sigma/ast/SType.scala +++ b/core/shared/src/main/scala/sigma/ast/SType.scala @@ -144,7 +144,7 @@ object SType { SBoolean, SString, STuple, SGroupElement, SSigmaProp, SContext, SGlobal, SHeader, SPreHeader, SAvlTree, SBox, SOption, SCollection, SBigInt ) - private val v6Types = v5Types ++ Seq(SByte, SShort, SInt, SLong) + private val v6Types = v5Types ++ Seq(SByte, SShort, SInt, SLong, SUnsignedBigInt) private val v5TypesMap = v5Types.map { t => (t.typeId, t) }.toMap @@ -398,6 +398,7 @@ case object SByte extends SPrimType with SEmbeddable with SNumericType with SMon 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 _ => sys.error(s"Cannot downcast value $v to the type $this") } } @@ -420,6 +421,7 @@ case object SShort extends SPrimType with SEmbeddable with SNumericType with SMo 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 _ => sys.error(s"Cannot downcast value $v to the type $this") } } @@ -444,6 +446,7 @@ case object SInt extends SPrimType with SEmbeddable with SNumericType with SMono 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 _ => sys.error(s"Cannot downcast value $v to the type $this") } } @@ -470,6 +473,7 @@ case object SLong extends SPrimType with SEmbeddable with SNumericType with SMon 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 _ => sys.error(s"Cannot downcast value $v to the type $this") } } @@ -687,15 +691,16 @@ object SOption extends STypeCompanion { override val reprClass: RClass[_] = RClass(classOf[Option[_]]) - type SBooleanOption = SOption[SBoolean.type] - type SByteOption = SOption[SByte.type] - type SShortOption = SOption[SShort.type] - type SIntOption = SOption[SInt.type] - type SLongOption = SOption[SLong.type] - type SBigIntOption = SOption[SBigInt.type] - type SGroupElementOption = SOption[SGroupElement.type] - type SBoxOption = SOption[SBox.type] - type SAvlTreeOption = SOption[SAvlTree.type] + type SBooleanOption = SOption[SBoolean.type] + type SByteOption = SOption[SByte.type] + type SShortOption = SOption[SShort.type] + type SIntOption = SOption[SInt.type] + type SLongOption = SOption[SLong.type] + type SBigIntOption = SOption[SBigInt.type] + type SUnsignedBigIntOption = SOption[SUnsignedBigInt.type] + type SGroupElementOption = SOption[SGroupElement.type] + type SBoxOption = SOption[SBox.type] + type SAvlTreeOption = SOption[SAvlTree.type] /** This descriptors are instantiated once here and then reused. */ implicit val SByteOption = SOption(SByte) @@ -704,6 +709,7 @@ object SOption extends STypeCompanion { implicit val SIntOption = SOption(SInt) implicit val SLongOption = SOption(SLong) implicit val SBigIntOption = SOption(SBigInt) + implicit val SUnsignedBigIntOption = SOption(SUnsignedBigInt) implicit val SBooleanOption = SOption(SBoolean) implicit val SAvlTreeOption = SOption(SAvlTree) implicit val SGroupElementOption = SOption(SGroupElement) @@ -764,29 +770,31 @@ object SCollection extends STypeCompanion { def apply[T <: SType](elemType: T): SCollection[T] = SCollectionType(elemType) def apply[T <: SType](implicit elemType: T, ov: Overloaded1): SCollection[T] = SCollectionType(elemType) - type SBooleanArray = SCollection[SBoolean.type] - type SByteArray = SCollection[SByte.type] - type SShortArray = SCollection[SShort.type] - type SIntArray = SCollection[SInt.type] - type SLongArray = SCollection[SLong.type] - type SBigIntArray = SCollection[SBigInt.type] - type SGroupElementArray = SCollection[SGroupElement.type] - type SBoxArray = SCollection[SBox.type] - type SAvlTreeArray = SCollection[SAvlTree.type] + type SBooleanArray = SCollection[SBoolean.type] + type SByteArray = SCollection[SByte.type] + type SShortArray = SCollection[SShort.type] + type SIntArray = SCollection[SInt.type] + type SLongArray = SCollection[SLong.type] + type SBigIntArray = SCollection[SBigInt.type] + type SUnsignedBigIntArray = SCollection[SUnsignedBigInt.type] + type SGroupElementArray = SCollection[SGroupElement.type] + type SBoxArray = SCollection[SBox.type] + type SAvlTreeArray = SCollection[SAvlTree.type] /** This descriptors are instantiated once here and then reused. */ - val SBooleanArray = SCollection(SBoolean) - val SByteArray = SCollection(SByte) - val SByteArray2 = SCollection(SCollection(SByte)) - val SShortArray = SCollection(SShort) - val SIntArray = SCollection(SInt) - val SLongArray = SCollection(SLong) - val SBigIntArray = SCollection(SBigInt) - val SGroupElementArray = SCollection(SGroupElement) - val SSigmaPropArray = SCollection(SSigmaProp) - val SBoxArray = SCollection(SBox) - val SAvlTreeArray = SCollection(SAvlTree) - val SHeaderArray = SCollection(SHeader) + val SBooleanArray = SCollection(SBoolean) + val SByteArray = SCollection(SByte) + val SByteArray2 = SCollection(SCollection(SByte)) + val SShortArray = SCollection(SShort) + val SIntArray = SCollection(SInt) + val SLongArray = SCollection(SLong) + val SBigIntArray = SCollection(SBigInt) + val SUnsignedBigIntArray = SCollection(SUnsignedBigInt) + val SGroupElementArray = SCollection(SGroupElement) + val SSigmaPropArray = SCollection(SSigmaProp) + val SBoxArray = SCollection(SBox) + val SAvlTreeArray = SCollection(SAvlTree) + val SHeaderArray = SCollection(SHeader) } /** Type descriptor of tuple type. */ diff --git a/core/shared/src/main/scala/sigma/data/CBigInt.scala b/core/shared/src/main/scala/sigma/data/CBigInt.scala index 1d1478e0c4..8212955103 100644 --- a/core/shared/src/main/scala/sigma/data/CBigInt.scala +++ b/core/shared/src/main/scala/sigma/data/CBigInt.scala @@ -28,11 +28,11 @@ case class CBigInt(override val wrappedValue: BigInteger) extends BigInt with Wr override def signum: Int = wrappedValue.signum() - override def add(that: BigInt): BigInt = CBigInt(wrappedValue.add(that.asInstanceOf[CBigInt].wrappedValue).to256BitValueExact) + override def add(that: BigInt): BigInt = CBigInt(wrappedValue.add(that.asInstanceOf[CBigInt].wrappedValue).toSignedBigIntValueExact) - override def subtract(that: BigInt): BigInt = CBigInt(wrappedValue.subtract(that.asInstanceOf[CBigInt].wrappedValue).to256BitValueExact) + override def subtract(that: BigInt): BigInt = CBigInt(wrappedValue.subtract(that.asInstanceOf[CBigInt].wrappedValue).toSignedBigIntValueExact) - override def multiply(that: BigInt): BigInt = CBigInt(wrappedValue.multiply(that.asInstanceOf[CBigInt].wrappedValue).to256BitValueExact) + override def multiply(that: BigInt): BigInt = CBigInt(wrappedValue.multiply(that.asInstanceOf[CBigInt].wrappedValue).toSignedBigIntValueExact) override def divide(that: BigInt): BigInt = CBigInt(wrappedValue.divide(that.asInstanceOf[CBigInt].wrappedValue)) @@ -44,7 +44,7 @@ case class CBigInt(override val wrappedValue: BigInteger) extends BigInt with Wr override def max(that: BigInt): BigInt = CBigInt(wrappedValue.max(that.asInstanceOf[CBigInt].wrappedValue)) - override def negate(): BigInt = CBigInt(wrappedValue.negate().to256BitValueExact) + override def negate(): BigInt = CBigInt(wrappedValue.negate().toSignedBigIntValueExact) override def and(that: BigInt): BigInt = CBigInt(wrappedValue.and(that.asInstanceOf[CBigInt].wrappedValue)) @@ -52,9 +52,9 @@ case class CBigInt(override val wrappedValue: BigInteger) extends BigInt with Wr override def xor(that: BigInt): BigInt = CBigInt(wrappedValue.xor(that.asInstanceOf[CBigInt].wrappedValue)) - override def shiftLeft(n: Int): BigInt = CBigInt(wrappedValue.shiftLeft(n).to256BitValueExact) + override def shiftLeft(n: Int): BigInt = CBigInt(wrappedValue.shiftLeft(n).toSignedBigIntValueExact) - override def shiftRight(n: Int): BigInt = CBigInt(wrappedValue.shiftRight(n).to256BitValueExact) + override def shiftRight(n: Int): BigInt = CBigInt(wrappedValue.shiftRight(n).toSignedBigIntValueExact) def toUnsigned: UnsignedBigInt = { if(this.wrappedValue.compareTo(BigInteger.ZERO) < 0){ @@ -88,12 +88,13 @@ case class CUnsignedBigInt(override val wrappedValue: BigInteger) extends Unsign override def compareTo(that: UnsignedBigInt): Int = wrappedValue.compareTo(that.asInstanceOf[CUnsignedBigInt].wrappedValue) - //todo: consider result's bits limit - override def add(that: UnsignedBigInt): UnsignedBigInt = CUnsignedBigInt(wrappedValue.add(that.asInstanceOf[CUnsignedBigInt].wrappedValue).to256BitValueExact) + override def add(that: UnsignedBigInt): UnsignedBigInt = CUnsignedBigInt(wrappedValue.add(that.asInstanceOf[CUnsignedBigInt].wrappedValue).toUnsignedBigIntValueExact) - override def subtract(that: UnsignedBigInt): UnsignedBigInt = CUnsignedBigInt(wrappedValue.subtract(that.asInstanceOf[CUnsignedBigInt].wrappedValue).to256BitValueExact) + override def subtract(that: UnsignedBigInt): UnsignedBigInt = { + CUnsignedBigInt(wrappedValue.subtract(that.asInstanceOf[CUnsignedBigInt].wrappedValue).toUnsignedBigIntValueExact) + } - override def multiply(that: UnsignedBigInt): UnsignedBigInt = CUnsignedBigInt(wrappedValue.multiply(that.asInstanceOf[CUnsignedBigInt].wrappedValue).to256BitValueExact) + override def multiply(that: UnsignedBigInt): UnsignedBigInt = CUnsignedBigInt(wrappedValue.multiply(that.asInstanceOf[CUnsignedBigInt].wrappedValue).toUnsignedBigIntValueExact) override def divide(that: UnsignedBigInt): UnsignedBigInt = CUnsignedBigInt(wrappedValue.divide(that.asInstanceOf[CUnsignedBigInt].wrappedValue)) @@ -129,7 +130,18 @@ case class CUnsignedBigInt(override val wrappedValue: BigInteger) extends Unsign CUnsignedBigInt(wrappedValue.multiply(thatBi).mod(mBi)) } + /** + * @return a big integer whose value is `this xor that` + */ + def xor(that: UnsignedBigInt): UnsignedBigInt = { + CUnsignedBigInt(wrappedValue.xor(that.asInstanceOf[CUnsignedBigInt].wrappedValue)) + } + + override def shiftLeft(n: Int): UnsignedBigInt = CUnsignedBigInt(wrappedValue.shiftLeft(n).toUnsignedBigIntValueExact) + + override def shiftRight(n: Int): UnsignedBigInt = CUnsignedBigInt(wrappedValue.shiftRight(n).toUnsignedBigIntValueExact) + override def toSigned(): BigInt = { - CBigInt(wrappedValue.to256BitValueExact) + CBigInt(wrappedValue.toSignedBigIntValueExact) } } diff --git a/core/shared/src/main/scala/sigma/reflection/ReflectionData.scala b/core/shared/src/main/scala/sigma/reflection/ReflectionData.scala index d94e7b7e0d..53d6c256f2 100644 --- a/core/shared/src/main/scala/sigma/reflection/ReflectionData.scala +++ b/core/shared/src/main/scala/sigma/reflection/ReflectionData.scala @@ -128,7 +128,35 @@ object ReflectionData { ) ) } - //todo: add UnsignedBigInt + { + val clazz = classOf[sigma.UnsignedBigInt] + val paramTypes = Array[Class[_]](clazz) + registerClassEntry(clazz, + methods = Map( + mkMethod(clazz, "add", paramTypes) { (obj, args) => + obj.asInstanceOf[UnsignedBigInt].add(args(0).asInstanceOf[UnsignedBigInt]) + }, + mkMethod(clazz, "max", paramTypes) { (obj, args) => + obj.asInstanceOf[UnsignedBigInt].max(args(0).asInstanceOf[UnsignedBigInt]) + }, + mkMethod(clazz, "min", paramTypes) { (obj, args) => + obj.asInstanceOf[UnsignedBigInt].min(args(0).asInstanceOf[UnsignedBigInt]) + }, + mkMethod(clazz, "subtract", paramTypes) { (obj, args) => + obj.asInstanceOf[UnsignedBigInt].subtract(args(0).asInstanceOf[UnsignedBigInt]) + }, + mkMethod(clazz, "multiply", paramTypes) { (obj, args) => + obj.asInstanceOf[UnsignedBigInt].multiply(args(0).asInstanceOf[UnsignedBigInt]) + }, + mkMethod(clazz, "mod", paramTypes) { (obj, args) => + obj.asInstanceOf[UnsignedBigInt].mod(args(0).asInstanceOf[UnsignedBigInt]) + }, + mkMethod(clazz, "divide", paramTypes) { (obj, args) => + obj.asInstanceOf[UnsignedBigInt].divide(args(0).asInstanceOf[UnsignedBigInt]) + } + ) + ) + } { val clazz = classOf[CollBuilder] registerClassEntry(clazz, diff --git a/core/shared/src/main/scala/sigma/util/Extensions.scala b/core/shared/src/main/scala/sigma/util/Extensions.scala index 624b3f5d6b..149d61f6c2 100644 --- a/core/shared/src/main/scala/sigma/util/Extensions.scala +++ b/core/shared/src/main/scala/sigma/util/Extensions.scala @@ -204,7 +204,7 @@ object Extensions { * not exactly fit in a 256 bit range. * @see BigInteger#longValueExact */ - @inline final def to256BitValueExact: BigInteger = { + @inline final def toSignedBigIntValueExact: BigInteger = { // Comparing with 255 is correct because bitLength() method excludes the sign bit. // For example, these are the boundary values: // (new BigInteger("80" + "00" * 31, 16)).bitLength() = 256 @@ -217,6 +217,15 @@ object Extensions { throw new ArithmeticException("BigInteger out of 256 bit range"); } + @inline final def toUnsignedBigIntValueExact: BigInteger = { + // todo: make the check soft-forkable + if (x.compareTo(BigInteger.ZERO) >= 0 && x.bitLength() <= 256) { + x + } else { + throw new ArithmeticException("Unsigned BigInteger out of 256 bit range or negative") + } + } + /** Converts `x` to [[sigma.BigInt]] */ def toBigInt: sigma.BigInt = CBigInt(x) } diff --git a/data/shared/src/main/scala/sigma/data/CSigmaDslBuilder.scala b/data/shared/src/main/scala/sigma/data/CSigmaDslBuilder.scala index e5bb8920ae..b74f91b133 100644 --- a/data/shared/src/main/scala/sigma/data/CSigmaDslBuilder.scala +++ b/data/shared/src/main/scala/sigma/data/CSigmaDslBuilder.scala @@ -150,7 +150,7 @@ class CSigmaDslBuilder extends SigmaDslBuilder { dsl => } override def byteArrayToBigInt(bytes: Coll[Byte]): BigInt = { - val bi = new BigInteger(bytes.toArray).to256BitValueExact + val bi = new BigInteger(bytes.toArray).toSignedBigIntValueExact this.BigInt(bi) } From cb51ba8bf3a100982a040d276356fd15f615c36a Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Tue, 17 Sep 2024 19:07:01 +0300 Subject: [PATCH 236/314] removing access to type before 6.0, more tests --- .../src/main/scala/sigma/ast/SType.scala | 25 ++++++++--- .../utxo/BasicOpsSpecification.scala | 44 ++++++++++++++++++- 2 files changed, 61 insertions(+), 8 deletions(-) diff --git a/core/shared/src/main/scala/sigma/ast/SType.scala b/core/shared/src/main/scala/sigma/ast/SType.scala index c99b7b8e34..7673c11dec 100644 --- a/core/shared/src/main/scala/sigma/ast/SType.scala +++ b/core/shared/src/main/scala/sigma/ast/SType.scala @@ -102,12 +102,23 @@ object SType { /** Immutable empty IndexedSeq, can be used to avoid repeated allocations. */ val EmptySeq: IndexedSeq[SType] = EmptyArray + private val v5PredefTypes = Array[SType]( + SBoolean, SByte, SShort, SInt, SLong, SBigInt, SContext, + SGlobal, SHeader, SPreHeader, SAvlTree, SGroupElement, SSigmaProp, SString, SBox, + SUnit, SAny) + + private val v6PredefTypes = v5PredefTypes ++ Array(SUnsignedBigInt) + + /** All pre-defined types should be listed here. Note, NoType is not listed. * Should be in sync with sigmastate.lang.Types.predefTypes. */ - val allPredefTypes: Seq[SType] = Array[SType]( - SBoolean, SByte, SShort, SInt, SLong, SBigInt, SUnsignedBigInt, SContext, - SGlobal, SHeader, SPreHeader, SAvlTree, SGroupElement, SSigmaProp, SString, SBox, - SUnit, SAny) + def allPredefTypes: Seq[SType] = { + if(VersionContext.current.isV6SoftForkActivated) { + v6PredefTypes + } else { + v5PredefTypes + } + } /** A mapping of object types supporting MethodCall operations. For each serialized * typeId this map contains a companion object which can be used to access the list of @@ -177,7 +188,7 @@ object SType { case SInt => x.isInstanceOf[Int] case SLong => x.isInstanceOf[Long] case SBigInt => x.isInstanceOf[BigInt] - case SUnsignedBigInt => x.isInstanceOf[UnsignedBigInt] + case SUnsignedBigInt if VersionContext.current.isV6SoftForkActivated => x.isInstanceOf[UnsignedBigInt] case SGroupElement => x.isInstanceOf[GroupElement] case SSigmaProp => x.isInstanceOf[SigmaProp] case SBox => x.isInstanceOf[Box] @@ -360,8 +371,6 @@ trait SNumericType extends SProduct with STypeCompanion { } object SNumericType extends STypeCompanion { - /** Array of all numeric types ordered by number of bytes in the representation. */ - final val allNumericTypes = Array(SByte, SShort, SInt, SLong, SBigInt, SUnsignedBigInt) // TODO v6.0: this typeId is now shadowed by SGlobal.typeId // see https://github.com/ScorexFoundation/sigmastate-interpreter/issues/667 @@ -537,6 +546,7 @@ case object SUnsignedBigInt extends SPrimType with SEmbeddable with SNumericType case x: Short => BigInteger.valueOf(x.toLong) case x: Int => BigInteger.valueOf(x.toLong) case x: Long => BigInteger.valueOf(x) + case x: UnsignedBigInt => x.asInstanceOf[CUnsignedBigInt].wrappedValue case _ => sys.error(s"Cannot upcast value $v to the type $this") } CUnsignedBigInt(bi) @@ -547,6 +557,7 @@ case object SUnsignedBigInt extends SPrimType with SEmbeddable with SNumericType case x: Short => BigInteger.valueOf(x.toLong) case x: Int => BigInteger.valueOf(x.toLong) case x: Long => BigInteger.valueOf(x) + case x: UnsignedBigInt => x.asInstanceOf[CUnsignedBigInt].wrappedValue case _ => sys.error(s"Cannot downcast value $v to the type $this") } CUnsignedBigInt(bi) diff --git a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala index 8c29783db5..2ecace1690 100644 --- a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala @@ -163,7 +163,11 @@ class BasicOpsSpecification extends CompilerTestingCommons true )} - deserTest() // todo: should fail < 6.0 + if (activatedVersionInTests < V6SoftForkVersion) { + an[Exception] should be thrownBy deserTest() + } else { + deserTest() + } } property("signed -> unsigned bigint conversion - positive bigint") { @@ -224,6 +228,44 @@ class BasicOpsSpecification extends CompilerTestingCommons } } + property("unsigned bigint - add") { + def conversionTest() = {test("add", env, ext, + s"""{ + | val a = unsignedBigInt("5") + | val b = unsignedBigInt("10") + | val res = a + b + | res == 15 + | } """.stripMargin, + null, + true + )} + + if (activatedVersionInTests < V6SoftForkVersion) { + an[Exception] should be thrownBy conversionTest() + } else { + conversionTest() + } + } + + property("unsigned bigint - subtract with neg result") { + def conversionTest() = {test("subtract", env, ext, + s"""{ + | val a = unsignedBigInt("5") + | val b = unsignedBigInt("10") + | val res = a - b + | res >= 0 + | } """.stripMargin, + null, + true + )} + + if (activatedVersionInTests < V6SoftForkVersion) { + an[Exception] should be thrownBy conversionTest() + } else { + an[Exception] should be thrownBy conversionTest() + } + } + property("unsigned -> signed bigint conversion") { def conversionTest() = {test("conversion", env, ext, s"""{ From 5f0c5c5cb299cf32ae5bf58e0e9bf686c2f378f7 Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Fri, 20 Sep 2024 16:11:07 +0300 Subject: [PATCH 237/314] scaladoc improvements, Ints.toBits --- core/shared/src/main/scala/sigma/SigmaDsl.scala | 9 ++++----- .../src/main/scala/sigma/ast/methods.scala | 14 +++++++------- .../main/scala/sigma/data/ExactIntegral.scala | 3 +-- .../sigmastate/utxo/BasicOpsSpecification.scala | 16 ++++++++++++++++ 4 files changed, 28 insertions(+), 14 deletions(-) diff --git a/core/shared/src/main/scala/sigma/SigmaDsl.scala b/core/shared/src/main/scala/sigma/SigmaDsl.scala index 6f9a3e2ffe..c2fd44550a 100644 --- a/core/shared/src/main/scala/sigma/SigmaDsl.scala +++ b/core/shared/src/main/scala/sigma/SigmaDsl.scala @@ -154,19 +154,18 @@ trait BigInt { def |(that: BigInt): BigInt = or(that) /** - * @return a big integer whose value is `this xor that` + * @return a big integer whose value is `this xor that`. + * This method returns a negative BigInteger if and only if exactly one of this and val are negative. */ def xor(that: BigInt): BigInt /** - * @return a 256-bit signed integer whose value is (this << n). The shift distance, n, may be negative, - * in which case this method performs a right shift. (Computes floor(this * 2n).) + * @return a 256-bit signed integer whose value is (this << n). `n` should be in 0..255 range (inclusive). */ def shiftLeft(n: Int): BigInt /** - * @return a 256-bit signed integer whose value is (this >> n). Sign extension is performed. The shift distance, n, - * may be negative, in which case this method performs a left shift. (Computes floor(this / 2n).) + * @return a 256-bit signed integer whose value is (this >> n). `n` should be in 0..255 range (inclusive). */ def shiftRight(n: Int): BigInt } diff --git a/data/shared/src/main/scala/sigma/ast/methods.scala b/data/shared/src/main/scala/sigma/ast/methods.scala index 6c401f8fc3..c980a22300 100644 --- a/data/shared/src/main/scala/sigma/ast/methods.scala +++ b/data/shared/src/main/scala/sigma/ast/methods.scala @@ -275,10 +275,10 @@ object SNumericTypeMethods extends MethodsContainer { """.stripMargin) /** Cost of inverting bits of a number. */ - val BitwiseInverse_CostKind = FixedCost(JitCost(5)) + val BitwiseOp_CostKind = FixedCost(JitCost(5)) val BitwiseInverseMethod: SMethod = SMethod( - this, "bitwiseInverse", SFunc(tNum, tNum), 8, BitwiseInverse_CostKind) + this, "bitwiseInverse", SFunc(tNum, tNum), 8, BitwiseOp_CostKind) .withIRInfo(MethodCallIrBuilder) .withUserDefinedInvoke({ (m: SMethod, obj: Any, _: Array[Any]) => m.objType match { @@ -292,7 +292,7 @@ object SNumericTypeMethods extends MethodsContainer { .withInfo(PropertyCall, desc = "Returns bitwise inverse of this numeric. ") val BitwiseOrMethod: SMethod = SMethod( - this, "bitwiseOr", SFunc(Array(tNum, tNum), tNum), 9, BitwiseInverse_CostKind) + this, "bitwiseOr", SFunc(Array(tNum, tNum), tNum), 9, BitwiseOp_CostKind) .withIRInfo(MethodCallIrBuilder) .withUserDefinedInvoke({ (m: SMethod, obj: Any, other: Array[Any]) => m.objType match { @@ -308,7 +308,7 @@ object SNumericTypeMethods extends MethodsContainer { ArgInfo("that", "A numeric value to calculate or with.")) val BitwiseAndMethod: SMethod = SMethod( - this, "bitwiseAnd", SFunc(Array(tNum, tNum), tNum), 10, BitwiseInverse_CostKind) + this, "bitwiseAnd", SFunc(Array(tNum, tNum), tNum), 10, BitwiseOp_CostKind) .withIRInfo(MethodCallIrBuilder) .withUserDefinedInvoke({ (m: SMethod, obj: Any, other: Array[Any]) => m.objType match { @@ -324,7 +324,7 @@ object SNumericTypeMethods extends MethodsContainer { ArgInfo("that", "A numeric value to calculate and with.")) val BitwiseXorMethod: SMethod = SMethod( - this, "bitwiseXor", SFunc(Array(tNum, tNum), tNum), 11, BitwiseInverse_CostKind) + this, "bitwiseXor", SFunc(Array(tNum, tNum), tNum), 11, BitwiseOp_CostKind) .withIRInfo(MethodCallIrBuilder) .withUserDefinedInvoke({ (m: SMethod, obj: Any, other: Array[Any]) => m.objType match { @@ -340,7 +340,7 @@ object SNumericTypeMethods extends MethodsContainer { ArgInfo("that", "A numeric value to calculate xor with.")) val ShiftLeftMethod: SMethod = SMethod( - this, "shiftLeft", SFunc(Array(tNum, SInt), tNum), 12, BitwiseInverse_CostKind) + this, "shiftLeft", SFunc(Array(tNum, SInt), tNum), 12, BitwiseOp_CostKind) .withIRInfo(MethodCallIrBuilder) .withUserDefinedInvoke({ (m: SMethod, obj: Any, other: Array[Any]) => m.objType match { @@ -359,7 +359,7 @@ object SNumericTypeMethods extends MethodsContainer { "the size of the number in bits (e.g. 64 for Long, 256 for BigInt)")) val ShiftRightMethod: SMethod = SMethod( - this, "shiftRight", SFunc(Array(tNum, SInt), tNum), 13, BitwiseInverse_CostKind) + this, "shiftRight", SFunc(Array(tNum, SInt), tNum), 13, BitwiseOp_CostKind) .withIRInfo(MethodCallIrBuilder) .withUserDefinedInvoke({ (m: SMethod, obj: Any, other: Array[Any]) => m.objType match { diff --git a/data/shared/src/main/scala/sigma/data/ExactIntegral.scala b/data/shared/src/main/scala/sigma/data/ExactIntegral.scala index 2bd7fbe341..86a9bfffce 100644 --- a/data/shared/src/main/scala/sigma/data/ExactIntegral.scala +++ b/data/shared/src/main/scala/sigma/data/ExactIntegral.scala @@ -61,8 +61,7 @@ object ExactIntegral { implicit object ShortIsExactIntegral extends ExactIntegral[Short] { val n = scala.math.Numeric.ShortIsIntegral - override def plus(x: Short, y: Short): - Short = x.addExact(y) + override def plus(x: Short, y: Short): Short = x.addExact(y) override def minus(x: Short, y: Short): Short = x.subtractExact(y) override def times(x: Short, y: Short): Short = x.multiplyExact(y) override def toBigEndianBytes(x: Short): Coll[Byte] = Colls.fromItems((x >> 8).toByte, x.toByte) diff --git a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala index a5d73d2442..6d21dd9edb 100644 --- a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala @@ -569,6 +569,22 @@ class BasicOpsSpecification extends CompilerTestingCommons } } + property("Int.toBits") { + def toBytesTest() = test("Int.toBytes", env, ext, + """{ + | val l = 1477959696 + | l.toBits == Coll(false, true, false, true, true, false, false, false, false, false, false, true, false, true, true ,true, true, true, true, false, false, false, false, false, false, false, false, true, false, false, false, false) + | }""".stripMargin, + null + ) + + if (VersionContext.current.isV6SoftForkActivated) { + toBytesTest() + } else { + an[Exception] shouldBe thrownBy(toBytesTest()) + } + } + property("Byte.toBytes") { def toBytesTest() = test("Byte.toBytes", env, ext, """{ From 43db8df7e01aceed7f5f6aebc13ecf23d44996cd Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Mon, 23 Sep 2024 13:02:22 +0300 Subject: [PATCH 238/314] scrypto 3.0.0 --- build.sbt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.sbt b/build.sbt index 85c59512d6..ab9d931172 100644 --- a/build.sbt +++ b/build.sbt @@ -82,9 +82,9 @@ ThisBuild / dynverSeparator := "-" val bouncycastleBcprov = "org.bouncycastle" % "bcprov-jdk15on" % "1.66" -val scrypto = "org.scorexfoundation" %% "scrypto" % "2.3.0-4-a0bc6176-SNAPSHOT" +val scrypto = "org.scorexfoundation" %% "scrypto" % "3.0.0" val scryptoDependency = - libraryDependencies += "org.scorexfoundation" %%% "scrypto" % "2.3.0-4-a0bc6176-SNAPSHOT" + libraryDependencies += "org.scorexfoundation" %%% "scrypto" % "3.0.0" val scorexUtil = "org.scorexfoundation" %% "scorex-util" % "0.2.1" val scorexUtilDependency = From 8136c8f620b9097cd6313d4971aafbc113507a50 Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Tue, 24 Sep 2024 19:37:07 +0300 Subject: [PATCH 239/314] new methods added to ReflectionData --- .../scala/sigma/reflection/ReflectionData.scala | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/core/shared/src/main/scala/sigma/reflection/ReflectionData.scala b/core/shared/src/main/scala/sigma/reflection/ReflectionData.scala index a2de9dd8c5..bfe7a639e3 100644 --- a/core/shared/src/main/scala/sigma/reflection/ReflectionData.scala +++ b/core/shared/src/main/scala/sigma/reflection/ReflectionData.scala @@ -162,6 +162,9 @@ object ReflectionData { mkMethod(clazz, "apply", Array[Class[_]](classOf[Int])) { (obj, args) => obj.asInstanceOf[Coll[_]].apply(args(0).asInstanceOf[Int]) }, + mkMethod(clazz, "get", Array[Class[_]](classOf[Int])) { (obj, args) => + obj.asInstanceOf[Coll[_]].apply(args(0).asInstanceOf[Int]) + }, mkMethod(clazz, "append", Array[Class[_]](classOf[Coll[_]])) { (obj, args) => obj.asInstanceOf[Coll[Any]].append(args(0).asInstanceOf[Coll[Any]]) }, @@ -170,6 +173,18 @@ object ReflectionData { }, mkMethod(clazz, "map", Array[Class[_]](classOf[Function1[_, _]], classOf[RType[_]])) { (obj, args) => obj.asInstanceOf[Coll[Any]].map(args(0).asInstanceOf[Any => Any])(args(1).asInstanceOf[RType[Any]]) + }, + mkMethod(clazz, "reverse", Array[Class[_]]()) { (obj, args) => + obj.asInstanceOf[Coll[Any]].reverse + }, + mkMethod(clazz, "distinct", Array[Class[_]]()) { (obj, args) => + obj.asInstanceOf[Coll[Any]].distinct + }, + mkMethod(clazz, "startsWith", Array[Class[_]](classOf[Coll[_]])) { (obj, args) => + obj.asInstanceOf[Coll[Any]].startsWith(args(0).asInstanceOf[Coll[Any]]) + }, + mkMethod(clazz, "endsWith", Array[Class[_]](classOf[Coll[_]])) { (obj, args) => + obj.asInstanceOf[Coll[Any]].endsWith(args(0).asInstanceOf[Coll[Any]]) } ) ) From 586aaddc6c7b2aec1dd195f8d15020490060f6fa Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Thu, 26 Sep 2024 19:35:02 +0300 Subject: [PATCH 240/314] LSV6 tests, predefined method --- .../sigma/reflection/ReflectionData.scala | 3 + .../main/scala/sigma/ast/SigmaPredef.scala | 22 ++++- .../scala/sigma/LanguageSpecificationV6.scala | 94 ++++++++++++++++++- .../sigmastate/ErgoTreeSpecification.scala | 2 +- .../utxo/BasicOpsSpecification.scala | 19 +++- 5 files changed, 133 insertions(+), 7 deletions(-) diff --git a/core/shared/src/main/scala/sigma/reflection/ReflectionData.scala b/core/shared/src/main/scala/sigma/reflection/ReflectionData.scala index a2de9dd8c5..ef0b37de10 100644 --- a/core/shared/src/main/scala/sigma/reflection/ReflectionData.scala +++ b/core/shared/src/main/scala/sigma/reflection/ReflectionData.scala @@ -450,6 +450,9 @@ object ReflectionData { }, mkMethod(clazz, "decodePoint", Array[Class[_]](cColl)) { (obj, args) => obj.asInstanceOf[SigmaDslBuilder].decodePoint(args(0).asInstanceOf[Coll[Byte]]) + }, + mkMethod(clazz, "fromBigEndianBytes", Array[Class[_]](cColl, classOf[RType[_]])) { (obj, args) => + obj.asInstanceOf[SigmaDslBuilder].fromBigEndianBytes(args(0).asInstanceOf[Coll[Byte]])(args(1).asInstanceOf[RType[_]]) } ) ) diff --git a/data/shared/src/main/scala/sigma/ast/SigmaPredef.scala b/data/shared/src/main/scala/sigma/ast/SigmaPredef.scala index 8b89851938..96573d095d 100644 --- a/data/shared/src/main/scala/sigma/ast/SigmaPredef.scala +++ b/data/shared/src/main/scala/sigma/ast/SigmaPredef.scala @@ -420,6 +420,25 @@ object SigmaPredef { ) ) + val FromBigEndianBytesFunc = PredefinedFunc("fromBigEndianBytes", + Lambda(Seq(paramT), Array("bytes" -> SByteArray), tT, None), + irInfo = PredefFuncInfo( + irBuilder = { case (u, args) => + val resType = u.opType.tRange.asInstanceOf[SFunc].tRange + MethodCall( + Global, + SGlobalMethods.fromBigEndianBytesMethod.withConcreteTypes(Map(tT -> resType)), + args.toIndexedSeq, + Map(tT -> resType) + ) + }), + docInfo = OperationInfo(MethodCall, + """Deserializes provided big endian bytes into a numeric value of given type. + """.stripMargin, + Seq(ArgInfo("bytes", "bytes to deserialize")) + ) + ) + val globalFuncs: Map[String, PredefinedFunc] = Seq( AllOfFunc, AnyOfFunc, @@ -448,7 +467,8 @@ object SigmaPredef { SubstConstantsFunc, ExecuteFromVarFunc, ExecuteFromSelfRegFunc, - SerializeFunc + SerializeFunc, + FromBigEndianBytesFunc ).map(f => f.name -> f).toMap def comparisonOp(symbolName: String, opDesc: ValueCompanion, desc: String, args: Seq[ArgInfo]) = { diff --git a/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala b/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala index 7605043cea..bbfd260f21 100644 --- a/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala +++ b/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala @@ -11,11 +11,10 @@ import sigma.ast.ErgoTree.ZeroHeader import sigma.ast.SCollection.SByteArray import sigma.ast.syntax.TrueSigmaProp import sigma.ast.{SInt, _} -import sigma.data.{CBigInt, CBox, CHeader, ExactNumeric} +import sigma.data.{CBigInt, CBox, CHeader, CSigmaDslBuilder, ExactNumeric, RType} import sigma.eval.{CostDetails, SigmaDsl, TracedCost} import sigma.serialization.ValueCodes.OpCode -import sigma.data.{RType} -import sigma.util.Extensions.{BooleanOps, ByteOps, IntOps, LongOps} +import sigma.util.Extensions.{BooleanOps, IntOps} import sigmastate.exceptions.MethodNotFound import sigmastate.utils.Extensions.ByteOpsForSigma import sigmastate.utils.Helpers @@ -1523,4 +1522,93 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite => ) } + + property("Global - fromBigEndianBytes") { + import sigma.data.OrderingOps.BigIntOrdering + + def byteFromBigEndianBytes: Feature[Byte, Boolean] = { + newFeature( + { (x: Byte) => CSigmaDslBuilder.fromBigEndianBytes[Byte](Colls.fromArray(Array(x))) == x}, + "{ (x: Byte) => fromBigEndianBytes[Byte](x.toBytes) == x }", + sinceVersion = VersionContext.V6SoftForkVersion + ) + } + + verifyCases( + Seq( + 5.toByte -> new Expected(ExpectedResult(Success(true), None)), + Byte.MaxValue -> new Expected(ExpectedResult(Success(true), None)), + Byte.MinValue -> new Expected(ExpectedResult(Success(true), None)) + ), + byteFromBigEndianBytes + ) + + def shortFromBigEndianBytes: Feature[Short, Boolean] = { + newFeature( + { (x: Short) => CSigmaDslBuilder.fromBigEndianBytes[Short](Colls.fromArray(Shorts.toByteArray(x))) == x}, + "{ (x: Short) => fromBigEndianBytes[Short](x.toBytes) == x }", + sinceVersion = VersionContext.V6SoftForkVersion + ) + } + + verifyCases( + Seq( + 5.toShort -> new Expected(ExpectedResult(Success(true), None)), + Short.MaxValue -> new Expected(ExpectedResult(Success(true), None)), + Short.MinValue -> new Expected(ExpectedResult(Success(true), None)) + ), + shortFromBigEndianBytes + ) + + def intFromBigEndianBytes: Feature[Int, Boolean] = { + newFeature( + { (x: Int) => CSigmaDslBuilder.fromBigEndianBytes[Int](Colls.fromArray(Ints.toByteArray(x))) == x}, + "{ (x: Int) => fromBigEndianBytes[Int](x.toBytes) == x }", + sinceVersion = VersionContext.V6SoftForkVersion + ) + } + + verifyCases( + Seq( + 5 -> new Expected(ExpectedResult(Success(true), None)), + Int.MaxValue -> new Expected(ExpectedResult(Success(true), None)) + ), + intFromBigEndianBytes + ) + + def longFromBigEndianBytes: Feature[Long, Boolean] = { + newFeature( + { (x: Long) => CSigmaDslBuilder.fromBigEndianBytes[Long](Colls.fromArray(Longs.toByteArray(x))) == x}, + "{ (x: Long) => fromBigEndianBytes[Long](x.toBytes) == x }", + sinceVersion = VersionContext.V6SoftForkVersion + ) + } + + verifyCases( + Seq( + 5L -> new Expected(ExpectedResult(Success(true), None)), + Long.MinValue -> new Expected(ExpectedResult(Success(true), None)) + ), + longFromBigEndianBytes + ) + + def bigIntFromBigEndianBytes: Feature[BigInt, Boolean] = { + newFeature( + { (x: BigInt) => CSigmaDslBuilder.fromBigEndianBytes[BigInt](x.toBytes) == x}, + "{ (x: BigInt) => Global.fromBigEndianBytes[BigInt](x.toBytes) == x }", + sinceVersion = VersionContext.V6SoftForkVersion + ) + } + + verifyCases( + Seq( + CBigInt(BigInteger.valueOf(50)) -> new Expected(ExpectedResult(Success(true), None)), + CBigInt(BigInteger.valueOf(-500000000000L)) -> new Expected(ExpectedResult(Success(true), None)), + CBigInt(sigma.crypto.CryptoConstants.groupOrder.divide(BigInteger.valueOf(2))) -> new Expected(ExpectedResult(Success(true), None)) + ), + bigIntFromBigEndianBytes + ) + + } + } diff --git a/sc/shared/src/test/scala/sigmastate/ErgoTreeSpecification.scala b/sc/shared/src/test/scala/sigmastate/ErgoTreeSpecification.scala index 4403716e5a..fee93248f7 100644 --- a/sc/shared/src/test/scala/sigmastate/ErgoTreeSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/ErgoTreeSpecification.scala @@ -516,7 +516,7 @@ class ErgoTreeSpecification extends SigmaDslTesting with ContractsTestkit with C (SGlobal.typeId, Seq( MInfo(1, groupGeneratorMethod), MInfo(2, xorMethod) ) ++ (if (isV6Activated) { - Seq(MInfo(3, serializeMethod)) // methods added in v6.0 + Seq(MInfo(3, serializeMethod), MInfo(5, fromBigEndianBytesMethod)) // methods added in v6.0 } else { Seq.empty[MInfo] }), true) diff --git a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala index 47815ea41f..16ffaa3dbb 100644 --- a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala @@ -622,6 +622,23 @@ class BasicOpsSpecification extends CompilerTestingCommons } } + property("Global.fromBigEndianBytes - Long.toBytes") { + def fromTest() = test("fromBigEndianBytes - long", env, ext, + s"""{ + | val l = 1088800L + | val ba = l.toBytes + | Global.fromBigEndianBytes[Long](ba) == l + |} + |""".stripMargin, + null + ) + if(VersionContext.current.isV6SoftForkActivated) { + fromTest() + } else { + an[Exception] should be thrownBy(fromTest()) + } + } + property("Global.fromBigEndianBytes - bigInt") { val bi = new BigInteger("9785856985394593489356430476450674590674598659865986594859056865984690568904") def fromTest() = test("fromBigEndianBytes - bigInt", env, ext, @@ -639,8 +656,6 @@ class BasicOpsSpecification extends CompilerTestingCommons } } - // todo: roundtrip with .toBytes - property("Int.toBytes") { def toBytesTest() = test("Int.toBytes", env, ext, """{ From 2cdc34eaeb57fc77824f65f4379887e4feb5ab76 Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Fri, 27 Sep 2024 00:20:34 +0300 Subject: [PATCH 241/314] fixing JS tests --- .../src/main/scala/sigma/compiler/ir/GraphIRReflection.scala | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/GraphIRReflection.scala b/sc/shared/src/main/scala/sigma/compiler/ir/GraphIRReflection.scala index dcdce623ac..79fba9bb96 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/GraphIRReflection.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/GraphIRReflection.scala @@ -1,5 +1,6 @@ package sigma.compiler.ir +import sigma.ast.SType import sigma.compiler.ir.primitives.Thunks import sigma.data.RType import sigma.reflection.ReflectionData.registerClassEntry @@ -510,6 +511,9 @@ object GraphIRReflection { }, mkMethod(clazz, "serialize", Array[Class[_]](classOf[Base#Ref[_]])) { (obj, args) => obj.asInstanceOf[ctx.SigmaDslBuilder].serialize(args(0).asInstanceOf[ctx.Ref[Any]]) + }, + mkMethod(clazz, "fromBigEndianBytes", Array[Class[_]](classOf[Base#Ref[_]], classOf[TypeDescs#Elem[_]])) { (obj, args) => + obj.asInstanceOf[ctx.SigmaDslBuilder].fromBigEndianBytes(args(0).asInstanceOf[ctx.Ref[ctx.Coll[Byte]]])(args(1).asInstanceOf[ctx.Elem[SType]]) } ) ) From d738ac54f5d4b96a5f5927e96bc1210fb9b02fc4 Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Fri, 27 Sep 2024 14:02:15 +0300 Subject: [PATCH 242/314] fixing JS tests --- .../scala/sigma/reflection/ReflectionData.scala | 2 +- .../main/scala/sigma/SigmaDataReflection.scala | 16 ++++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/core/shared/src/main/scala/sigma/reflection/ReflectionData.scala b/core/shared/src/main/scala/sigma/reflection/ReflectionData.scala index bfe7a639e3..d2165711f6 100644 --- a/core/shared/src/main/scala/sigma/reflection/ReflectionData.scala +++ b/core/shared/src/main/scala/sigma/reflection/ReflectionData.scala @@ -163,7 +163,7 @@ object ReflectionData { obj.asInstanceOf[Coll[_]].apply(args(0).asInstanceOf[Int]) }, mkMethod(clazz, "get", Array[Class[_]](classOf[Int])) { (obj, args) => - obj.asInstanceOf[Coll[_]].apply(args(0).asInstanceOf[Int]) + obj.asInstanceOf[Coll[_]].get(args(0).asInstanceOf[Int]) }, mkMethod(clazz, "append", Array[Class[_]](classOf[Coll[_]])) { (obj, args) => obj.asInstanceOf[Coll[Any]].append(args(0).asInstanceOf[Coll[Any]]) diff --git a/data/shared/src/main/scala/sigma/SigmaDataReflection.scala b/data/shared/src/main/scala/sigma/SigmaDataReflection.scala index c64bdee877..341ee647b3 100644 --- a/data/shared/src/main/scala/sigma/SigmaDataReflection.scala +++ b/data/shared/src/main/scala/sigma/SigmaDataReflection.scala @@ -317,6 +317,22 @@ object SigmaDataReflection { mkMethod(clazz, "flatMap_eval", Array[Class[_]](classOf[MethodCall], classOf[Coll[_]], classOf[Function1[_,_]], classOf[ErgoTreeEvaluator])) { (obj, args) => obj.asInstanceOf[SCollectionMethods.type].flatMap_eval(args(0).asInstanceOf[MethodCall], args(1).asInstanceOf[Coll[Any]], args(2).asInstanceOf[Any => Coll[Any]])(args(3).asInstanceOf[ErgoTreeEvaluator]) + }, + mkMethod(clazz, "reverse_eval", Array[Class[_]](classOf[MethodCall], classOf[Coll[_]], classOf[ErgoTreeEvaluator])) { (obj, args) => + obj.asInstanceOf[SCollectionMethods.type].reverse_eval(args(0).asInstanceOf[MethodCall], + args(1).asInstanceOf[Coll[Any]])(args(2).asInstanceOf[ErgoTreeEvaluator]) + }, + mkMethod(clazz, "distinct_eval", Array[Class[_]](classOf[MethodCall], classOf[Coll[_]], classOf[ErgoTreeEvaluator])) { (obj, args) => + obj.asInstanceOf[SCollectionMethods.type].distinct_eval(args(0).asInstanceOf[MethodCall], + args(1).asInstanceOf[Coll[Any]])(args(2).asInstanceOf[ErgoTreeEvaluator]) + }, + mkMethod(clazz, "startsWith_eval", Array[Class[_]](classOf[MethodCall], classOf[Coll[_]], classOf[Coll[_]], classOf[ErgoTreeEvaluator])) { (obj, args) => + obj.asInstanceOf[SCollectionMethods.type].startsWith_eval(args(0).asInstanceOf[MethodCall], + args(1).asInstanceOf[Coll[Any]], args(2).asInstanceOf[Coll[Any]])(args(3).asInstanceOf[ErgoTreeEvaluator]) + }, + mkMethod(clazz, "endsWith_eval", Array[Class[_]](classOf[MethodCall], classOf[Coll[_]], classOf[Coll[_]], classOf[ErgoTreeEvaluator])) { (obj, args) => + obj.asInstanceOf[SCollectionMethods.type].endsWith_eval(args(0).asInstanceOf[MethodCall], + args(1).asInstanceOf[Coll[Any]], args(2).asInstanceOf[Coll[Any]])(args(3).asInstanceOf[ErgoTreeEvaluator]) } ) ) From 1989d197dc9461683bd351e31be540271ac94bec Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Fri, 27 Sep 2024 15:15:07 +0300 Subject: [PATCH 243/314] LSV6 tests --- .../scala/sigma/LanguageSpecificationV6.scala | 90 +++++++++++++++++++ 1 file changed, 90 insertions(+) diff --git a/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala b/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala index 7605043cea..d9797e36bf 100644 --- a/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala +++ b/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala @@ -1523,4 +1523,94 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite => ) } + property("Coll.reverse") { + val f = newFeature[Coll[Int], Coll[Int]]( + { (xs: Coll[Int]) => xs.reverse }, + """{(xs: Coll[Int]) => xs.reverse }""".stripMargin, + sinceVersion = VersionContext.V6SoftForkVersion + ) + + verifyCases( + Seq( + Coll(1, 2) -> Expected(ExpectedResult(Success(Coll(2, 1)), None)), + Coll[Int]() -> Expected(ExpectedResult(Success(Coll[Int]()), None)) + ), + f + ) + } + + property("Coll.distinct") { + val f = newFeature[Coll[Int], Coll[Int]]( + { (xs: Coll[Int]) => xs.distinct }, + """{(xs: Coll[Int]) => xs.distinct }""".stripMargin, + sinceVersion = VersionContext.V6SoftForkVersion + ) + + verifyCases( + Seq( + Coll(1, 2) -> Expected(ExpectedResult(Success(Coll(1, 2)), None)), + Coll(1, 1, 2) -> Expected(ExpectedResult(Success(Coll(1, 2)), None)), + Coll(1, 2, 2) -> Expected(ExpectedResult(Success(Coll(1, 2)), None)), + Coll[Int]() -> Expected(ExpectedResult(Success(Coll[Int]()), None)) + ), + f + ) + } + + property("Coll.startsWith") { + val f = newFeature[(Coll[Int], Coll[Int]), Boolean]( + { (xs: (Coll[Int], Coll[Int])) => xs._1.startsWith(xs._2) }, + """{(xs: (Coll[Int], Coll[Int])) => xs._1.startsWith(xs._2) }""".stripMargin, + sinceVersion = VersionContext.V6SoftForkVersion + ) + + verifyCases( + Seq( + (Coll(1, 2, 3), Coll(1, 2)) -> Expected(ExpectedResult(Success(true), None)), + (Coll(1, 2, 3), Coll(1, 2, 3)) -> Expected(ExpectedResult(Success(true), None)), + (Coll(1, 2, 3), Coll(1, 2, 3, 4)) -> Expected(ExpectedResult(Success(false), None)), + (Coll[Int](), Coll[Int]()) -> Expected(ExpectedResult(Success(true), None)) + ), + f + ) + } + + property("Coll.endsWith") { + val f = newFeature[(Coll[Int], Coll[Int]), Boolean]( + { (xs: (Coll[Int], Coll[Int])) => xs._1.endsWith(xs._2) }, + """{(xs: (Coll[Int], Coll[Int])) => xs._1.endsWith(xs._2) }""".stripMargin, + sinceVersion = VersionContext.V6SoftForkVersion + ) + + verifyCases( + Seq( + (Coll(1, 2, 3), Coll(1, 2)) -> Expected(ExpectedResult(Success(false), None)), + (Coll(1, 2, 3), Coll(2, 3)) -> Expected(ExpectedResult(Success(true), None)), + (Coll(1, 2, 3), Coll(2, 3, 4)) -> Expected(ExpectedResult(Success(false), None)), + (Coll(1, 2, 3), Coll(1, 2, 3)) -> Expected(ExpectedResult(Success(true), None)), + (Coll[Int](), Coll[Int]()) -> Expected(ExpectedResult(Success(true), None)) + ), + f + ) + } + + property("Coll.get") { + val f = newFeature[(Coll[Int], Int), Option[Int]]( + { (xs: (Coll[Int], Int)) => xs._1.get(xs._2) }, + """{(xs: (Coll[Int], Int)) => xs._1.get(xs._2) }""".stripMargin, + sinceVersion = VersionContext.V6SoftForkVersion + ) + + verifyCases( + Seq( + (Coll(1, 2), 0) -> Expected(ExpectedResult(Success(Some(1)), None)), + (Coll(1, 2), 1) -> Expected(ExpectedResult(Success(Some(2)), None)), + (Coll(1, 2), -1) -> Expected(ExpectedResult(Success(None), None)), + (Coll(1, 2), 2) -> Expected(ExpectedResult(Success(None), None)), + (Coll[Int](), 0) -> Expected(ExpectedResult(Success(None), None)) + ), + f + ) + } + } From 6459b07aa6b92ee6131af7a35fa9f63aa428b927 Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Fri, 27 Sep 2024 16:06:10 +0300 Subject: [PATCH 244/314] fix ErgoTreeSpec --- .../src/test/scala/sigmastate/ErgoTreeSpecification.scala | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sc/shared/src/test/scala/sigmastate/ErgoTreeSpecification.scala b/sc/shared/src/test/scala/sigmastate/ErgoTreeSpecification.scala index 4403716e5a..f5db0217dc 100644 --- a/sc/shared/src/test/scala/sigmastate/ErgoTreeSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/ErgoTreeSpecification.scala @@ -561,7 +561,9 @@ class ErgoTreeSpecification extends SigmaDslTesting with ContractsTestkit with C EndsWithMethod, MapReduceMethod, */ - ), true) + ) ++ (if (isV6Activated) { + Seq(MInfo(30, ReverseMethod), MInfo(31, DistinctMethod), MInfo(32, StartsWithMethod), MInfo(33, EndsWithMethod), MInfo(34, GetMethod)) + } else Seq.empty), true) }, { import SOptionMethods._ (SOption.typeId, Seq( From a3f25ef4353e0fc7bfc67b55d5fc3156b4471c16 Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Mon, 30 Sep 2024 14:28:30 +0300 Subject: [PATCH 245/314] LSV6 tests --- .../scala/sigma/LanguageSpecificationV6.scala | 156 +++++++++++++++++- 1 file changed, 150 insertions(+), 6 deletions(-) diff --git a/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala b/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala index 7605043cea..822611ea71 100644 --- a/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala +++ b/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala @@ -1,24 +1,26 @@ package sigma -import org.ergoplatform.ErgoHeader +import org.ergoplatform.{ErgoBox, ErgoHeader, ErgoLikeTransaction, Input} import scorex.util.encode.Base16 import sigma.VersionContext.V6SoftForkVersion -import org.ergoplatform.ErgoBox import org.ergoplatform.ErgoBox.Token +import org.ergoplatform.settings.ErgoAlgos import scorex.util.ModifierId import scorex.utils.{Ints, Longs, Shorts} -import sigma.ast.ErgoTree.ZeroHeader +import sigma.ast.ErgoTree.{HeaderType, ZeroHeader} import sigma.ast.SCollection.SByteArray import sigma.ast.syntax.TrueSigmaProp import sigma.ast.{SInt, _} -import sigma.data.{CBigInt, CBox, CHeader, ExactNumeric} +import sigma.data.{AvlTreeData, AvlTreeFlags, CAnyValue, CAvlTree, CBigInt, CBox, CHeader, CSigmaProp, ExactNumeric, ProveDHTuple, RType} import sigma.eval.{CostDetails, SigmaDsl, TracedCost} import sigma.serialization.ValueCodes.OpCode -import sigma.data.{RType} -import sigma.util.Extensions.{BooleanOps, ByteOps, IntOps, LongOps} +import sigma.util.Extensions.{BooleanOps, IntOps} +import sigmastate.eval.{CContext, CPreHeader} import sigmastate.exceptions.MethodNotFound import sigmastate.utils.Extensions.ByteOpsForSigma import sigmastate.utils.Helpers +import sigma.Extensions.{ArrayOps, CollOps} +import sigma.interpreter.{ContextExtension, ProverResult} import java.math.BigInteger import scala.util.{Failure, Success} @@ -1523,4 +1525,146 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite => ) } + property("Context.getVar and getVarFromInput") { + + def contextData() = { + val input = CBox( + new ErgoBox( + 80946L, + new ErgoTree( + HeaderType @@ 16.toByte, + Vector( + SigmaPropConstant( + CSigmaProp( + ProveDHTuple( + Helpers.decodeECPoint("03c046fccb95549910767d0543f5e8ce41d66ae6a8720a46f4049cac3b3d26dafb"), + Helpers.decodeECPoint("023479c9c3b86a0d3c8be3db0a2d186788e9af1db76d55f3dad127d15185d83d03"), + Helpers.decodeECPoint("03d7898641cb6653585a8e1dabfa7f665e61e0498963e329e6e3744bd764db2d72"), + Helpers.decodeECPoint("037ae057d89ec0b46ff8e9ff4c37e85c12acddb611c3f636421bef1542c11b0441") + ) + ) + ) + ), + Right(ConstantPlaceholder(0, SSigmaProp)) + ), + Coll(), + Map( + ErgoBox.R4 -> ByteArrayConstant(Helpers.decodeBytes("34")), + ErgoBox.R5 -> TrueLeaf + ), + ModifierId @@ ("0000bfe96a7c0001e7a5ee00aafb80ff057fbe7f8c6680e33a3dc18001820100"), + 1.toShort, + 5 + ) + ) + + val tx = ErgoLikeTransaction( + IndexedSeq(), + IndexedSeq(input.wrappedValue) + ) + + val tx2 = ErgoLikeTransaction( + IndexedSeq(Input(input.ebox.id, ProverResult(Array.emptyByteArray, ContextExtension(Map(11.toByte -> BooleanConstant(true)))))), + IndexedSeq(input.wrappedValue) + ) + + val tx3 = ErgoLikeTransaction( + IndexedSeq(Input(input.ebox.id, ProverResult(Array.emptyByteArray, ContextExtension(Map(11.toByte -> IntConstant(0)))))), + IndexedSeq(input.wrappedValue) + ) + + val tx4 = ErgoLikeTransaction( + IndexedSeq(Input(input.ebox.id, ProverResult(Array.emptyByteArray, ContextExtension(Map(11.toByte -> BooleanConstant(false)))))), + IndexedSeq(input.wrappedValue) + ) + + val ctx = CContext( + _dataInputs = Coll[Box](), + headers = Coll[Header](), + preHeader = CPreHeader( + 0.toByte, + Colls.fromArray(Array.fill(32)(0.toByte)), + -755484979487531112L, + 9223372036854775807L, + 11, + Helpers.decodeGroupElement("0227a58e9b2537103338c237c52c1213bf44bdb344fa07d9df8ab826cca26ca08f"), + Helpers.decodeBytes("007f00") + ), + inputs = Coll[Box](input), + outputs = Coll[Box](), + height = 11, + selfBox = input.copy(), // in 3.x, 4.x implementation selfBox is never the same instance as input (see toSigmaContext) + selfIndex = 0, + lastBlockUtxoRootHash = CAvlTree( + AvlTreeData( + ErgoAlgos.decodeUnsafe("54d23dd080006bdb56800100356080935a80ffb77e90b800057f00661601807f17").toColl, + AvlTreeFlags(true, true, true), + 1211925457, + None + ) + ), + _minerPubKey = Helpers.decodeBytes("0227a58e9b2537103338c237c52c1213bf44bdb344fa07d9df8ab826cca26ca08f"), + vars = Colls + .replicate[AnyValue](10, null) // reserve 10 vars + .append(Coll[AnyValue]( + CAnyValue(Helpers.decodeBytes("00")), + CAnyValue(true))), + spendingTransaction = tx, + activatedScriptVersion = activatedVersionInTests, + currentErgoTreeVersion = ergoTreeVersionInTests + ) + val ctx2 = ctx.copy(spendingTransaction = tx2) + val ctx3 = ctx.copy(spendingTransaction = tx3, vars = ctx.vars.patch(11, Coll(CAnyValue(0)), 1)) + val ctx4 = ctx.copy(spendingTransaction = tx4, vars = ctx.vars.patch(11, Coll(CAnyValue(false)), 1)) + + (ctx, ctx2, ctx3, ctx4) + } + + def getVarFromInput = { + newFeature( + { (x: Context) => x.getVarFromInput[Boolean](0, 11)}, + "{ (x: Context) => x.getVarFromInput[Boolean](0, 11) }", + FuncValue( + Array((1, SContext)), + MethodCall.typed[Value[SOption[SBoolean.type]]]( + ValUse(1, SContext), + SContextMethods.getVarFromInputMethod.withConcreteTypes(Map(STypeVar("T") -> SBoolean)), + Array(ShortConstant(0.toShort), ByteConstant(11.toByte)), + Map(STypeVar("T") -> SBoolean) + ) + ), + sinceVersion = VersionContext.V6SoftForkVersion + ) + } + + val (ctx, ctx2, ctx3, ctx4) = contextData() + + verifyCases( + Seq( + ctx -> new Expected(ExpectedResult(Success(None), None)), // input with # provided does not exist + ctx2 -> new Expected(ExpectedResult(Success(Some(true)), None)), + ctx3 -> new Expected(ExpectedResult(Success(None), None)), // not expected type in context var + ctx4 -> new Expected(ExpectedResult(Success(Some(false)), None)) + ), + getVarFromInput + ) + + def getVar = { + newFeature( + { (x: Context) => x.getVar[Boolean](11)}, + "{ (x: Context) => CONTEXT.getVar[Boolean](11.toByte) }", + sinceVersion = VersionContext.V6SoftForkVersion + ) + } + + verifyCases( + Seq( + ctx2 -> new Expected(ExpectedResult(Success(Some(true)), None)), + ctx3 -> new Expected(ExpectedResult(Failure(new sigma.exceptions.InvalidType("Cannot getVar[Boolean](11): invalid type of value TestValue(0) at id=11")), None)), // not expected type in context var + ctx4 -> new Expected(ExpectedResult(Success(Some(false)), None)) + ), + getVar + ) + } + } From f24e9ad44614ed9c91949c7594eb68bb19f5569d Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Mon, 30 Sep 2024 16:04:25 +0300 Subject: [PATCH 246/314] predefined fn, LangSpec notes, polishing PR --- .../src/main/scala/sigma/ast/SMethod.scala | 7 +++++ .../main/scala/sigma/ast/SigmaPredef.scala | 15 ++++++++- .../src/main/scala/sigma/ast/methods.scala | 8 +++-- .../sigma/interpreter/ContextExtension.scala | 4 +++ docs/LangSpec.md | 14 ++++++++- .../sigma/compiler/phases/SigmaTyper.scala | 1 + .../utxo/BasicOpsSpecification.scala | 31 ++++++++++++++++--- 7 files changed, 70 insertions(+), 10 deletions(-) diff --git a/data/shared/src/main/scala/sigma/ast/SMethod.scala b/data/shared/src/main/scala/sigma/ast/SMethod.scala index 5c3e5faf40..e5481cee5b 100644 --- a/data/shared/src/main/scala/sigma/ast/SMethod.scala +++ b/data/shared/src/main/scala/sigma/ast/SMethod.scala @@ -302,6 +302,13 @@ object SMethod { (implicit cT: ClassTag[T], cA1: ClassTag[A1], cA2: ClassTag[A2]): RMethod = RClass(cT.runtimeClass).getMethod(methodName, cA1.runtimeClass, cA2.runtimeClass) + /** Return [[Method]] descriptor for the given `methodName` on the given `cT` type. + * @param methodName the name of the method to lookup + * @param cT the class where to search the methodName + * @param cA1 the class of the method's first argument + * @param cA2 the class of the method's second argument + * @param cA3 the class of the method's third argument + */ def javaMethodOf[T, A1, A2, A3] (methodName: String) (implicit cT: ClassTag[T], cA1: ClassTag[A1], cA2: ClassTag[A2], cA3: ClassTag[A3]): RMethod = diff --git a/data/shared/src/main/scala/sigma/ast/SigmaPredef.scala b/data/shared/src/main/scala/sigma/ast/SigmaPredef.scala index 8b89851938..7a28ee6dd9 100644 --- a/data/shared/src/main/scala/sigma/ast/SigmaPredef.scala +++ b/data/shared/src/main/scala/sigma/ast/SigmaPredef.scala @@ -146,6 +146,18 @@ object SigmaPredef { Seq(ArgInfo("varId", "\\lst{Byte} identifier of context variable"))) ) + val GetVarFromInputFunc = PredefinedFunc("getVarFromInput", + Lambda(Array(paramT), Array("inputId" -> SShort, "varId" -> SByte), SOption(tT), None), + PredefFuncInfo( + { case (Ident(_, SFunc(_, SOption(rtpe), _)), Seq(inputId: Constant[SNumericType]@unchecked, varId: Constant[SNumericType]@unchecked)) => + mkMethodCall(Context, SContextMethods.getVarFromInputMethod, IndexedSeq(SShort.downcast(inputId.value.asInstanceOf[AnyVal]), SByte.downcast(varId.value.asInstanceOf[AnyVal])), Map(tT -> rtpe)) + }), + OperationInfo(MethodCall, + "Get context variable with given \\lst{varId} and type.", + Seq(ArgInfo("inputId", "\\lst{Byte} index of input to read context variable from"), + ArgInfo("varId", "\\lst{Byte} identifier of context variable"))) + ) + def PKFunc(networkPrefix: NetworkPrefix) = PredefinedFunc("PK", Lambda(Array("input" -> SString), SSigmaProp, None), PredefFuncInfo( @@ -448,7 +460,8 @@ object SigmaPredef { SubstConstantsFunc, ExecuteFromVarFunc, ExecuteFromSelfRegFunc, - SerializeFunc + SerializeFunc, + GetVarFromInputFunc ).map(f => f.name -> f).toMap def comparisonOp(symbolName: String, opDesc: ValueCompanion, desc: String, args: Seq[ArgInfo]) = { diff --git a/data/shared/src/main/scala/sigma/ast/methods.scala b/data/shared/src/main/scala/sigma/ast/methods.scala index ae05152630..33ffa9c9b2 100644 --- a/data/shared/src/main/scala/sigma/ast/methods.scala +++ b/data/shared/src/main/scala/sigma/ast/methods.scala @@ -1586,16 +1586,18 @@ case object SContextMethods extends MonoTypeMethods { MethodCallIrBuilder, javaMethodOf[Context, Byte, RType[_]]("getVar"), { mtype => Array(mtype.tRange.asOption[SType].elemType) }) - .withInfo(MethodCall, "") // todo: desc + .withInfo(MethodCall, "Get context variable with given \\lst{varId} and type.") - // todo: costing, desc lazy val getVarFromInputMethod = SMethod( this, "getVarFromInput", SFunc(Array(SContext, SShort, SByte), SOption(tT), Array(paramT)), 12, GetVar.costKind, Seq(tT)) .withIRInfo( MethodCallIrBuilder, javaMethodOf[Context, Short, Byte, RType[_]]("getVarFromInput"), { mtype => Array(mtype.tRange.asOption[SType].elemType) }) - .withInfo(MethodCall, "Multiply this number with \\lst{other} by module Q.", ArgInfo("other", "Number to multiply with this.")) + .withInfo(MethodCall, "Get context variable with given \\lst{varId} and type.", + ArgInfo("inputIdx", "Index of input to read variable from."), + ArgInfo("varId", "Index of variable.") + ) private lazy val commonMethods = super.getMethods() ++ Array( dataInputsMethod, headersMethod, preHeaderMethod, inputsMethod, outputsMethod, heightMethod, selfMethod, diff --git a/data/shared/src/main/scala/sigma/interpreter/ContextExtension.scala b/data/shared/src/main/scala/sigma/interpreter/ContextExtension.scala index fd269c177c..f03d076d43 100644 --- a/data/shared/src/main/scala/sigma/interpreter/ContextExtension.scala +++ b/data/shared/src/main/scala/sigma/interpreter/ContextExtension.scala @@ -20,6 +20,10 @@ case class ContextExtension(values: scala.collection.Map[Byte, EvaluatedValue[_ ContextExtension(values ++ bindings) } + /** + * @param varId - index of context variable + * @return context variable with provided index or None if it is not there + */ def get(varId: Byte): Option[EvaluatedValue[_ <: SType]] = values.get(varId) } diff --git a/docs/LangSpec.md b/docs/LangSpec.md index 5b72a8659d..7ec7dd7729 100644 --- a/docs/LangSpec.md +++ b/docs/LangSpec.md @@ -919,7 +919,7 @@ def longToByteArray(input: Long): Coll[Byte] def decodePoint(bytes: Coll[Byte]): GroupElement -/** Extracts Context variable by id and type. +/** Extracts Context variable from self input by id and type. * ErgoScript is typed, so accessing a the variables is an operation which involves * some expected type given in brackets. Thus `getVar[Int](id)` expression should * evaluate to a valid value of the `Option[Int]` type. @@ -976,6 +976,18 @@ def decodePoint(bytes: Coll[Byte]): GroupElement */ def getVar[T](tag: Int): Option[T] +/** Extracts Context variable from any input by input id, variable id and variable type. + * Unlike getVar, it is not throwing exception when expected type does not match real type of the variable. + * Thus it can be used to get context variable from self without exception, using selfBoxIndex, e.g. + *
+  *   {
+  *       val idx = CONTEXT.selfBoxIndex
+  *       sigmaProp(CONTEXT.getVarFromInput[Int](idx.toShort, 1.toByte).get == 5)
+  *   }
+  * 
+ */ +def getVarFromInput[T](inputId: Short, varId: Byte): Option[T] + /** Construct a new SigmaProp value representing public key of Diffie Hellman * signature protocol. When executed as part of Sigma protocol allow to provide * for a verifier a zero-knowledge proof of secret knowledge. diff --git a/sc/shared/src/main/scala/sigma/compiler/phases/SigmaTyper.scala b/sc/shared/src/main/scala/sigma/compiler/phases/SigmaTyper.scala index cc771cbac9..833bd413b9 100644 --- a/sc/shared/src/main/scala/sigma/compiler/phases/SigmaTyper.scala +++ b/sc/shared/src/main/scala/sigma/compiler/phases/SigmaTyper.scala @@ -134,6 +134,7 @@ class SigmaTyper(val builder: SigmaBuilder, res case Apply(ApplyTypes(sel @ Select(obj, n, _), Seq(rangeTpe)), args) => + // downcast getVarFromInput arguments to short and byte val nArgs = if (n == SContextMethods.getVarFromInputMethod.name && args.length == 2 && args(0).isInstanceOf[Constant[_]] && diff --git a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala index df4e85de3b..b43fcdd90e 100644 --- a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala @@ -167,7 +167,7 @@ class BasicOpsSpecification extends CompilerTestingCommons 1.toByte -> IntConstant(5) ).toSeq test("R1", env, customExt, - "{ sigmaProp(CONTEXT.getVarFromInput[Int](0, 1).get == 5) }", + "{ sigmaProp(getVarFromInput[Int](0, 1).get == 5) }", null ) } @@ -179,19 +179,40 @@ class BasicOpsSpecification extends CompilerTestingCommons } } - property("getVarFromInput - invalid input") { + property("getVarFromInput - self index") { def getVarTest(): Assertion = { val customExt = Map( 1.toByte -> IntConstant(5) ).toSeq test("R1", env, customExt, - "{ sigmaProp(CONTEXT.getVarFromInput[Int](1, 1).get == 5) }", + """{ + | val idx = CONTEXT.selfBoxIndex + | sigmaProp(CONTEXT.getVarFromInput[Int](idx.toShort, 1.toByte).get == 5) + | }""".stripMargin, null ) } if (VersionContext.current.isV6SoftForkActivated) { + getVarTest() + } else { an[Exception] should be thrownBy getVarTest() + } + } + + property("getVarFromInput - invalid input") { + def getVarTest(): Assertion = { + val customExt = Map( + 1.toByte -> IntConstant(5) + ).toSeq + test("R1", env, customExt, + "{ sigmaProp(CONTEXT.getVarFromInput[Int](1, 1).isDefined == false) }", + null + ) + } + + if (VersionContext.current.isV6SoftForkActivated) { + getVarTest() } else { an[Exception] should be thrownBy getVarTest() } @@ -593,13 +614,13 @@ class BasicOpsSpecification extends CompilerTestingCommons 1.toByte -> IntConstant(5) ).toSeq test("R1", env, customExt, - "{ sigmaProp(CONTEXT.getVarFromInput[Int](0, 2).get == 5) }", + "{ sigmaProp(CONTEXT.getVarFromInput[Int](0, 2).isDefined == false) }", null ) } if (VersionContext.current.isV6SoftForkActivated) { - an[Exception] should be thrownBy getVarTest() + getVarTest() } else { an[Exception] should be thrownBy getVarTest() } From edc91baa371048578d5fdeb08b5c15cf33526b32 Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Mon, 30 Sep 2024 16:55:58 +0300 Subject: [PATCH 247/314] tests --- .../ErgoLikeTransactionSpec.scala | 32 ++++++++++++------- .../utxo/BasicOpsSpecification.scala | 7 ---- 2 files changed, 21 insertions(+), 18 deletions(-) diff --git a/sc/shared/src/test/scala/org/ergoplatform/ErgoLikeTransactionSpec.scala b/sc/shared/src/test/scala/org/ergoplatform/ErgoLikeTransactionSpec.scala index 6a7ef5a512..3fc9c7fd3d 100644 --- a/sc/shared/src/test/scala/org/ergoplatform/ErgoLikeTransactionSpec.scala +++ b/sc/shared/src/test/scala/org/ergoplatform/ErgoLikeTransactionSpec.scala @@ -7,8 +7,7 @@ import org.ergoplatform.settings.ErgoAlgos import scorex.util.encode.Base16 import scorex.util.{ModifierId, Random} import sigma.Extensions._ -import sigma.SigmaDslTesting -import sigma.ast.SCollection.SByteArray +import sigma.{SigmaDslTesting, VersionContext} import sigma.ast.SType._ import sigma.ast.syntax.{ErgoBoxCandidateRType, TrueSigmaProp} import sigma.ast._ @@ -20,9 +19,11 @@ import sigmastate.helpers.TestingHelpers.copyTransaction import sigmastate.utils.Helpers import sigma.SigmaDslTesting import sigma.Extensions._ +import sigma.ast.SCollection.SByteArray +import sigmastate.CrossVersionProps import sigmastate.utils.Helpers.EitherOps // required for Scala 2.11 -class ErgoLikeTransactionSpec extends SigmaDslTesting with JsonCodecs { +class ErgoLikeTransactionSpec extends SigmaDslTesting with CrossVersionProps with JsonCodecs { property("ErgoBox test vectors") { val token1 = "6e789ab7b2fffff12280a6cd01557f6fb22b7f80ff7aff8e1f7f15973d7f0001" @@ -99,14 +100,24 @@ class ErgoLikeTransactionSpec extends SigmaDslTesting with JsonCodecs { { // test case for R2 val res = b1.get(ErgoBox.R2).get - val exp = Coll( - (Digest32Coll @@ ErgoAlgos.decodeUnsafe(token1).toColl) -> 10000000L, - (Digest32Coll @@ ErgoAlgos.decodeUnsafe(token2).toColl) -> 500L - ).map(identity).toConstant - // TODO v6.0 (16h): fix collections equality and remove map(identity) - // (PairOfColl should be equal CollOverArray but now it is not) + + // 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) - res shouldBe exp + if(VersionContext.current.isV6SoftForkActivated) { + val exp = Coll( + (Digest32Coll @@ ErgoAlgos.decodeUnsafe(token1).toColl) -> 10000000L, + (Digest32Coll @@ ErgoAlgos.decodeUnsafe(token2).toColl) -> 500L + ).toConstant + res shouldBe exp + exp shouldBe res + } else { + val exp = Coll( + (Digest32Coll @@ ErgoAlgos.decodeUnsafe(token1).toColl) -> 10000000L, + (Digest32Coll @@ ErgoAlgos.decodeUnsafe(token2).toColl) -> 500L + ).map(identity).toConstant + res shouldBe exp + } } { // test case for R3 @@ -470,7 +481,6 @@ class ErgoLikeTransactionSpec extends SigmaDslTesting with JsonCodecs { // test equivalence of "from Json" and "from bytes" deserialization tx2.id shouldBe tx.id tx2.id shouldBe "d5c0a7908bbb8eefe72ad70a9f668dd47b748239fd34378d3588d5625dd75c82" - println(tx2.id) } property("Tuple in register test vector") { diff --git a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala index 431c5166e1..68fe1022e7 100644 --- a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala @@ -804,13 +804,6 @@ class BasicOpsSpecification extends CompilerTestingCommons } } - property("coll equality") { - def collTest() = test("R1", env, ext, - "{ SELF.tokens == Coll[(Coll[Byte], Long)]() }", - null - ) - } - property("Relation operations") { test("R1", env, ext, "{ allOf(Coll(getVar[Boolean](trueVar).get, true, true)) }", From 3901ba25b9052e4c7d68ad9b520dfdf011298ae1 Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Mon, 30 Sep 2024 17:04:54 +0300 Subject: [PATCH 248/314] merging w. 6.0.0, Header support --- data/jvm/src/main/scala/sigma/Platform.scala | 3 ++- .../src/test/scala/sigma/ast/SigmaBuilderTest.scala | 8 ++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/data/jvm/src/main/scala/sigma/Platform.scala b/data/jvm/src/main/scala/sigma/Platform.scala index 3d2d14274f..072ed763ad 100644 --- a/data/jvm/src/main/scala/sigma/Platform.scala +++ b/data/jvm/src/main/scala/sigma/Platform.scala @@ -31,8 +31,9 @@ object Platform { 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 => Nullable(mkConstant[SHeader.type](h, SHeader)) - // todo: check Header and UnsignedBigInt + // todo: check UnsignedBigInt case v: String if !VersionContext.current.isV6SoftForkActivated => Nullable(mkConstant[SString.type](v, SString)) diff --git a/interpreter/shared/src/test/scala/sigma/ast/SigmaBuilderTest.scala b/interpreter/shared/src/test/scala/sigma/ast/SigmaBuilderTest.scala index b125893438..4946789411 100644 --- a/interpreter/shared/src/test/scala/sigma/ast/SigmaBuilderTest.scala +++ b/interpreter/shared/src/test/scala/sigma/ast/SigmaBuilderTest.scala @@ -244,6 +244,14 @@ class SigmaBuilderTest extends AnyPropSpec with ScalaCheckPropertyChecks with Ma testColl[SGroupElement.type](v, c) } + property("liftToConstant Header") { + val h = TestData.h1 + val c = HeaderConstant(h) + test[SHeader.type](h, c) + testFailure(Array.fill(10)(h)) + testColl[SHeader.type](h, c) + } + property("liftToConstant ErgoBox") { val v = TestData.b2.asInstanceOf[CBox].wrappedValue val c = BoxConstant(TestData.b2) From 6128fbdb82c58e7ecf2018321b73d40073d62824 Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Tue, 1 Oct 2024 18:35:59 +0300 Subject: [PATCH 249/314] fixing ErgoTreeSpec --- data/shared/src/main/scala/sigma/ast/methods.scala | 4 ++-- .../serialization/MethodCallSerializerSpecification.scala | 1 - .../src/test/scala/sigmastate/ErgoTreeSpecification.scala | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/data/shared/src/main/scala/sigma/ast/methods.scala b/data/shared/src/main/scala/sigma/ast/methods.scala index abb35dbb0f..d0a92d1cc1 100644 --- a/data/shared/src/main/scala/sigma/ast/methods.scala +++ b/data/shared/src/main/scala/sigma/ast/methods.scala @@ -1696,12 +1696,12 @@ case object SGlobalMethods extends MonoTypeMethods { private lazy val EnDecodeNBitsCost = FixedCost(JitCost(5)) // the same cost for nbits encoding and decoding lazy val encodeNBitsMethod: SMethod = SMethod( - this, "encodeNbits", SFunc(Array(SGlobal, SBigInt), SLong), 3, EnDecodeNBitsCost) + this, "encodeNbits", SFunc(Array(SGlobal, SBigInt), SLong), 6, EnDecodeNBitsCost) .withIRInfo(MethodCallIrBuilder) .withInfo(MethodCall, "Encode big integer number as nbits", ArgInfo("bigInt", "Big integer")) lazy val decodeNBitsMethod: SMethod = SMethod( - this, "decodeNbits", SFunc(Array(SGlobal, SLong), SBigInt), 4, EnDecodeNBitsCost) + this, "decodeNbits", SFunc(Array(SGlobal, SLong), SBigInt), 7, EnDecodeNBitsCost) .withIRInfo(MethodCallIrBuilder) .withInfo(MethodCall, "Decode nbits-encoded big integer number", ArgInfo("nbits", "NBits-encoded argument")) diff --git a/interpreter/shared/src/test/scala/sigma/serialization/MethodCallSerializerSpecification.scala b/interpreter/shared/src/test/scala/sigma/serialization/MethodCallSerializerSpecification.scala index 26e0cef223..1ea607f628 100644 --- a/interpreter/shared/src/test/scala/sigma/serialization/MethodCallSerializerSpecification.scala +++ b/interpreter/shared/src/test/scala/sigma/serialization/MethodCallSerializerSpecification.scala @@ -112,4 +112,3 @@ class MethodCallSerializerSpecification extends SerializationSpecification { ) } } -} diff --git a/sc/shared/src/test/scala/sigmastate/ErgoTreeSpecification.scala b/sc/shared/src/test/scala/sigmastate/ErgoTreeSpecification.scala index 4403716e5a..8ae4c5073d 100644 --- a/sc/shared/src/test/scala/sigmastate/ErgoTreeSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/ErgoTreeSpecification.scala @@ -516,7 +516,7 @@ class ErgoTreeSpecification extends SigmaDslTesting with ContractsTestkit with C (SGlobal.typeId, Seq( MInfo(1, groupGeneratorMethod), MInfo(2, xorMethod) ) ++ (if (isV6Activated) { - Seq(MInfo(3, serializeMethod)) // methods added in v6.0 + Seq(MInfo(3, serializeMethod), MInfo(6, encodeNBitsMethod), MInfo(7, decodeNBitsMethod)) // methods added in v6.0 } else { Seq.empty[MInfo] }), true) From af792b53bac04e488aa55cbb6c4a318f796a7d7a Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Tue, 1 Oct 2024 19:21:31 +0300 Subject: [PATCH 250/314] addressing review comments --- data/shared/src/main/scala/sigma/data/CSigmaDslBuilder.scala | 2 +- sc/shared/src/test/scala/sigmastate/ErgoTreeSpecification.scala | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/data/shared/src/main/scala/sigma/data/CSigmaDslBuilder.scala b/data/shared/src/main/scala/sigma/data/CSigmaDslBuilder.scala index 75fbe460b9..2ae4f73703 100644 --- a/data/shared/src/main/scala/sigma/data/CSigmaDslBuilder.scala +++ b/data/shared/src/main/scala/sigma/data/CSigmaDslBuilder.scala @@ -232,7 +232,7 @@ class CSigmaDslBuilder extends SigmaDslBuilder { dsl => if (bytes.length > SBigInt.MaxSizeInBytes) { throw SerializerException(s"BigInt value doesn't not fit into ${SBigInt.MaxSizeInBytes} bytes in fromBigEndianBytes") } - CBigInt(new BigInteger(bytes.toArray)).asInstanceOf[T] + CBigInt(new BigInteger(bytes.toArray).to256BitValueExact).asInstanceOf[T] // todo: UnsignedBitInt case _ => throw new IllegalArgumentException("Unsupported type provided in fromBigEndianBytes") } diff --git a/sc/shared/src/test/scala/sigmastate/ErgoTreeSpecification.scala b/sc/shared/src/test/scala/sigmastate/ErgoTreeSpecification.scala index fee93248f7..7a4b8de827 100644 --- a/sc/shared/src/test/scala/sigmastate/ErgoTreeSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/ErgoTreeSpecification.scala @@ -516,6 +516,7 @@ class ErgoTreeSpecification extends SigmaDslTesting with ContractsTestkit with C (SGlobal.typeId, Seq( MInfo(1, groupGeneratorMethod), MInfo(2, xorMethod) ) ++ (if (isV6Activated) { + // id = 4 reserved for deserializeTo method Seq(MInfo(3, serializeMethod), MInfo(5, fromBigEndianBytesMethod)) // methods added in v6.0 } else { Seq.empty[MInfo] From 40fe947f569172da521ec8e1c8b317f882a00b12 Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Wed, 2 Oct 2024 16:27:44 +0300 Subject: [PATCH 251/314] versioned header check --- data/jvm/src/main/scala/sigma/Platform.scala | 2 +- .../shared/src/test/scala/sigma/ast/SigmaBuilderTest.scala | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/data/jvm/src/main/scala/sigma/Platform.scala b/data/jvm/src/main/scala/sigma/Platform.scala index 072ed763ad..104ea44d3d 100644 --- a/data/jvm/src/main/scala/sigma/Platform.scala +++ b/data/jvm/src/main/scala/sigma/Platform.scala @@ -31,7 +31,7 @@ object Platform { 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 => Nullable(mkConstant[SHeader.type](h, SHeader)) + case h: Header if VersionContext.current.isV6SoftForkActivated => Nullable(mkConstant[SHeader.type](h, SHeader)) // todo: check UnsignedBigInt diff --git a/interpreter/shared/src/test/scala/sigma/ast/SigmaBuilderTest.scala b/interpreter/shared/src/test/scala/sigma/ast/SigmaBuilderTest.scala index 4946789411..c1642627ee 100644 --- a/interpreter/shared/src/test/scala/sigma/ast/SigmaBuilderTest.scala +++ b/interpreter/shared/src/test/scala/sigma/ast/SigmaBuilderTest.scala @@ -247,7 +247,11 @@ class SigmaBuilderTest extends AnyPropSpec with ScalaCheckPropertyChecks with Ma property("liftToConstant Header") { val h = TestData.h1 val c = HeaderConstant(h) - test[SHeader.type](h, c) + if (VersionContext.current.isV6SoftForkActivated) { + testSuccess(h, c) + } else { + testFailure(h) + } testFailure(Array.fill(10)(h)) testColl[SHeader.type](h, c) } From 19c752da1ff6cb2054846641d097238ccfdd58ee Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Thu, 3 Oct 2024 11:44:28 +0300 Subject: [PATCH 252/314] fixing most of tests --- data/js/src/main/scala/sigma/Platform.scala | 1 + .../org/ergoplatform/ErgoScriptPredef.scala | 3 +- .../org/ergoplatform/ErgoTreePredefSpec.scala | 24 +++++------ .../TestingInterpreterSpecification.scala | 16 +++++--- .../utxo/AVLTreeScriptsSpecification.scala | 10 ++--- .../utxo/ContextEnrichingSpecification.scala | 14 +++---- .../ErgoLikeInterpreterSpecification.scala | 41 ++++++++++++------- .../AtomicSwapExampleSpecification.scala | 1 - ...alletAdvContractExampleSpecification.scala | 7 +--- ...ldWalletContractExampleSpecification.scala | 1 - .../DHTupleExampleSpecification.scala | 1 - .../DemurrageExampleSpecification.scala | 1 - .../sigmastate/utxo/examples/IcoExample.scala | 7 ++-- .../utxo/examples/LetsSpecification.scala | 4 +- .../examples/MixExampleSpecification.scala | 5 +-- .../RPSGameExampleSpecification.scala | 7 ++-- .../ReversibleTxExampleSpecification.scala | 11 +++-- .../TimedPaymentExampleSpecification.scala | 1 - .../XorGameExampleSpecification.scala | 7 ++-- 19 files changed, 82 insertions(+), 80 deletions(-) diff --git a/data/js/src/main/scala/sigma/Platform.scala b/data/js/src/main/scala/sigma/Platform.scala index 29c761c3f1..45d74ea2b2 100644 --- a/data/js/src/main/scala/sigma/Platform.scala +++ b/data/js/src/main/scala/sigma/Platform.scala @@ -31,6 +31,7 @@ object Platform { case ge: GroupElement => Nullable(mkConstant[SGroupElement.type](ge, SGroupElement)) case b: Boolean => Nullable(if (b) TrueLeaf else FalseLeaf) case v: String => Nullable(mkConstant[SString.type](v, SString)) + case h: Header if VersionContext.current.isV6SoftForkActivated => Nullable(mkConstant[SHeader.type](h, SHeader)) // The Box lifting was broken in v4.x. `SigmaDsl.Box(b)` was missing which means the // isCorrectType requirement would fail in ConstantNode constructor. diff --git a/sc/shared/src/main/scala/org/ergoplatform/ErgoScriptPredef.scala b/sc/shared/src/main/scala/org/ergoplatform/ErgoScriptPredef.scala index 9eec42a4fb..7bcf10d593 100644 --- a/sc/shared/src/main/scala/org/ergoplatform/ErgoScriptPredef.scala +++ b/sc/shared/src/main/scala/org/ergoplatform/ErgoScriptPredef.scala @@ -1,6 +1,7 @@ package org.ergoplatform import org.ergoplatform.ErgoAddressEncoder.NetworkPrefix +import sigma.Colls import sigma.ast.SType import sigma.ast.syntax.SigmaPropValue import sigma.ast.Value @@ -32,7 +33,7 @@ object ErgoScriptPredef { networkPrefix: NetworkPrefix) (implicit IR: IRContext): SigmaPropValue = { val env = emptyEnv + - ("tokenId" -> tokenId, "thresholdAmount" -> thresholdAmount) + ("tokenId" -> Colls.fromArray(tokenId), "thresholdAmount" -> thresholdAmount) val res = compileWithCosting(env, """{ | val sumValues = { (xs: Coll[Long]) => xs.fold(0L, { (acc: Long, amt: Long) => acc + amt }) } diff --git a/sc/shared/src/test/scala/org/ergoplatform/ErgoTreePredefSpec.scala b/sc/shared/src/test/scala/org/ergoplatform/ErgoTreePredefSpec.scala index eb086e88c8..40012c2806 100644 --- a/sc/shared/src/test/scala/org/ergoplatform/ErgoTreePredefSpec.scala +++ b/sc/shared/src/test/scala/org/ergoplatform/ErgoTreePredefSpec.scala @@ -58,8 +58,8 @@ class ErgoTreePredefSpec extends CompilerTestingCommons with CompilerCrossVersio boxesToSpend = inputBoxes, spendingTransaction, self = inputBox, activatedVersionInTests) - val pr = prover.prove(emptyEnv + (ScriptNameProp -> "boxCreationHeight_prove"), propTree, ctx, fakeMessage).get - verifier.verify(emptyEnv + (ScriptNameProp -> "boxCreationHeight_verify"), propTree, ctx, pr, fakeMessage).get._1 shouldBe true + val pr = prover.prove(emptyEnv, propTree, ctx, fakeMessage).get + verifier.verify(emptyEnv, propTree, ctx, pr, fakeMessage).get._1 shouldBe true } property("collect coins from the founders' box") { @@ -118,8 +118,8 @@ class ErgoTreePredefSpec extends CompilerTestingCommons with CompilerCrossVersio boxesToSpend = inputBoxes, spendingTransaction, self = inputBoxes.head, activatedVersionInTests) - val pr = prover.prove(emptyEnv + (ScriptNameProp -> "checkSpending_prove"), prop, ctx, fakeMessage).get - verifier.verify(emptyEnv + (ScriptNameProp -> "checkSpending_verify"), prop, ctx, pr, fakeMessage).get._1 shouldBe true + val pr = prover.prove(emptyEnv, prop, ctx, fakeMessage).get + verifier.verify(emptyEnv, prop, ctx, pr, fakeMessage).get._1 shouldBe true } } @@ -148,13 +148,13 @@ class ErgoTreePredefSpec extends CompilerTestingCommons with CompilerCrossVersio self = inputBoxes.head, activatedVersionInTests) // should not be able to collect before minerRewardDelay - val prove = prover.prove(emptyEnv + (ScriptNameProp -> "rewardOutputScript_prove"), prop, ctx, fakeMessage).get - verifier.verify(emptyEnv + (ScriptNameProp -> "rewardOutputScript_verify"), prop, prevBlockCtx, prove, fakeMessage) + val prove = prover.prove(emptyEnv, prop, ctx, fakeMessage).get + verifier.verify(emptyEnv, prop, prevBlockCtx, prove, fakeMessage) .getOrThrow should matchPattern { case (false,_) => } // should be able to collect after minerRewardDelay - val pr = prover.prove(emptyEnv + (ScriptNameProp -> "prove"), prop, ctx, fakeMessage).getOrThrow - verifier.verify(emptyEnv + (ScriptNameProp -> "verify"), prop, ctx, pr, fakeMessage).getOrThrow._1 shouldBe true + val pr = prover.prove(emptyEnv, prop, ctx, fakeMessage).getOrThrow + verifier.verify(emptyEnv, prop, ctx, pr, fakeMessage).getOrThrow._1 shouldBe true } property("create transaction collecting the emission box") { @@ -232,8 +232,8 @@ class ErgoTreePredefSpec extends CompilerTestingCommons with CompilerCrossVersio self = inputBoxes.head, activatedVersionInTests).withCostLimit(scriptCostLimitInTests * 10) - val pr = prover.prove(emptyEnv + (ScriptNameProp -> "tokenThresholdScript_prove"), prop, ctx, fakeMessage).getOrThrow - verifier.verify(emptyEnv + (ScriptNameProp -> "tokenThresholdScript_verify"), prop, ctx, pr, fakeMessage).getOrThrow._1 shouldBe true + val pr = prover.prove(emptyEnv, prop, ctx, fakeMessage).getOrThrow + verifier.verify(emptyEnv, prop, ctx, pr, fakeMessage).getOrThrow._1 shouldBe true } @@ -308,8 +308,8 @@ class ErgoTreePredefSpec extends CompilerTestingCommons with CompilerCrossVersio boxesToSpend = inputBoxes, spendingTransaction, self = inputBoxes.head, activatedVersionInTests) - val pr = prover.prove(emptyEnv + (ScriptNameProp -> "checkRewardTx_prove"), prop, ctx, fakeMessage).getOrThrow - verifier.verify(emptyEnv + (ScriptNameProp -> "checkRewardTx_verify"), prop, ctx, pr, fakeMessage).getOrThrow._1 shouldBe true + val pr = prover.prove(emptyEnv, prop, ctx, fakeMessage).getOrThrow + verifier.verify(emptyEnv, prop, ctx, pr, fakeMessage).getOrThrow._1 shouldBe true spendingTransaction } diff --git a/sc/shared/src/test/scala/sigmastate/TestingInterpreterSpecification.scala b/sc/shared/src/test/scala/sigmastate/TestingInterpreterSpecification.scala index 4ba6b1a9f7..42d424994d 100644 --- a/sc/shared/src/test/scala/sigmastate/TestingInterpreterSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/TestingInterpreterSpecification.scala @@ -12,7 +12,7 @@ import scorex.util.encode.{Base16, Base58} import sigma.Colls import sigma.VersionContext.V6SoftForkVersion import sigma.VersionContext -import sigma.data.{CAND, CAvlTree, CHeader, ProveDlog, SigmaBoolean, TrivialProp} +import sigma.data.{CAND, CAvlTree, CBox, CHeader, ProveDlog, SigmaBoolean, TrivialProp} import sigma.interpreter.ContextExtension import sigma.util.Extensions.IntOps import sigmastate.helpers.{CompilerTestingCommons, ErgoLikeContextTesting, ErgoLikeTestInterpreter, ErgoLikeTestProvingInterpreter} @@ -143,12 +143,18 @@ class TestingInterpreterSpecification extends CompilerTestingCommons val env = Map( "dk1" -> dk1, "dk2" -> dk2, - "bytes1" -> Array[Byte](1, 2, 3), - "bytes2" -> Array[Byte](4, 5, 6), - "box1" -> testBox(10, TrueTree, 0, Seq(), Map( + "bytes1" -> Colls.fromArray(Array[Byte](1, 2, 3)), + "bytes2" -> Colls.fromArray(Array[Byte](4, 5, 6)), + "box1" -> (if(VersionContext.current.isJitActivated) { + CBox(testBox(10, TrueTree, 0, Seq(), Map( + reg1 -> IntArrayConstant(Array[Int](1, 2, 3)), + reg2 -> BoolArrayConstant(Array[Boolean](true, false, true)) + )))} else { + testBox(10, TrueTree, 0, Seq(), Map( reg1 -> IntArrayConstant(Array[Int](1, 2, 3)), reg2 -> BoolArrayConstant(Array[Boolean](true, false, true)) - )) + )) + }) ) val prop = mkTestErgoTree(compile(env, code)(IR).asBoolValue.toSigmaProp) val challenge = Array.fill(32)(Random.nextInt(100).toByte) diff --git a/sc/shared/src/test/scala/sigmastate/utxo/AVLTreeScriptsSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/AVLTreeScriptsSpecification.scala index 6b0c0080c9..ca7f9dd7c7 100644 --- a/sc/shared/src/test/scala/sigmastate/utxo/AVLTreeScriptsSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/utxo/AVLTreeScriptsSpecification.scala @@ -15,14 +15,13 @@ import sigmastate.helpers.{CompilerTestingCommons, ContextEnrichingTestProvingIn import sigmastate.helpers.TestingHelpers._ import sigmastate.interpreter.Interpreter.ScriptNameProp import sigma.ast.syntax._ -import sigma.Coll +import sigma.{AvlTree, Coll, Colls, Context} import sigma.ast.SAvlTree import sigma.ast.syntax.{GetVarByteArray, OptionValueOps} import sigma.compiler.ir.IRContext import sigma.data.{AvlTreeData, AvlTreeFlags, CSigmaProp, TrivialProp} import sigma.eval.SigmaDsl import sigma.interpreter.ProverResult -import sigma.{AvlTree, Context} import sigmastate.eval.Extensions.AvlTreeOps @@ -39,9 +38,6 @@ class AVLTreeScriptsSpecification extends CompilerTestingCommons def genKey(str: String): ADKey = ADKey @@@ Blake2b256("key: " + str) def genValue(str: String): ADValue = ADValue @@@ Blake2b256("val: " + str) - val inKey = genKey("init key") - val inValue = genValue("init value") - property("avl tree - removals") { case class AvlTreeContract[Spec <: ContractSpec] (ops: Coll[Coll[Byte]], proof: Coll[Byte], prover: Spec#ProvingParty) @@ -204,7 +200,7 @@ class AVLTreeScriptsSpecification extends CompilerTestingCommons val treeData = new AvlTreeData(digest.toColl, AvlTreeFlags.ReadOnly, 32, None) - val env = Map("key" -> key, "proof" -> proof) + val env = Map("key" -> Colls.fromArray(key), "proof" -> Colls.fromArray(proof)) val prop = compile(env, """SELF.R4[AvlTree].get.contains(key, proof)""").asBoolValue.toSigmaProp val propExp = IR.builder.mkMethodCall( @@ -374,7 +370,7 @@ class AVLTreeScriptsSpecification extends CompilerTestingCommons val treeData = SigmaDsl.avlTree(new AvlTreeData(digest.toColl, AvlTreeFlags.ReadOnly, 32, None)) val env = Map("proofId" -> proofId.toLong, - "keys" -> ConcreteCollection.fromItems(genKey("3"), genKey("4"), genKey("5"))) + "keys" -> Colls.fromItems(Colls.fromArray(genKey("3")), Colls.fromArray(genKey("4")), Colls.fromArray(genKey("5")))) val prop = compile(env, """{ | val tree = SELF.R4[AvlTree].get diff --git a/sc/shared/src/test/scala/sigmastate/utxo/ContextEnrichingSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/ContextEnrichingSpecification.scala index fe3dac68b3..3b2baa62fe 100644 --- a/sc/shared/src/test/scala/sigmastate/utxo/ContextEnrichingSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/utxo/ContextEnrichingSpecification.scala @@ -5,8 +5,8 @@ import scorex.crypto.hash.Blake2b256 import sigma.ast._ import sigma.ast.syntax._ import sigmastate._ -import sigmastate.helpers.{ContextEnrichingTestProvingInterpreter, ErgoLikeContextTesting, ErgoLikeTestInterpreter, CompilerTestingCommons} -import sigma.Coll +import sigmastate.helpers.{CompilerTestingCommons, ContextEnrichingTestProvingInterpreter, ErgoLikeContextTesting, ErgoLikeTestInterpreter} +import sigma.{Coll, Colls} class ContextEnrichingSpecification extends CompilerTestingCommons @@ -19,7 +19,7 @@ class ContextEnrichingSpecification extends CompilerTestingCommons val preimage = prover.contextExtenders(1).value.asInstanceOf[Coll[Byte]] val pubkey = prover.dlogSecrets.head.publicImage - val env = Map("blake" -> Blake2b256(preimage.toArray), "pubkey" -> pubkey) + val env = Map("blake" -> Colls.fromArray(Blake2b256(preimage.toArray)), "pubkey" -> pubkey) val prop = compile(env, """{ | pubkey && blake2b256(getVar[Coll[Byte]](1).get) == blake @@ -49,7 +49,7 @@ class ContextEnrichingSpecification extends CompilerTestingCommons val preimage2 = prover.contextExtenders(2).value.asInstanceOf[Coll[Byte]] val pubkey = prover.dlogSecrets.head.publicImage - val env = Map("blake" -> Blake2b256(preimage1.append(preimage2).toArray), "pubkey" -> pubkey) + val env = Map("blake" -> Colls.fromArray(Blake2b256(preimage1.append(preimage2).toArray)), "pubkey" -> pubkey) val prop = compile(env, """{ | pubkey && blake2b256(getVar[Coll[Byte]](1).get ++ getVar[Coll[Byte]](2).get) == blake @@ -89,7 +89,7 @@ class ContextEnrichingSpecification extends CompilerTestingCommons .withContextExtender(k1, ByteArrayConstant(v1)) .withContextExtender(k2, ByteArrayConstant(v2)) - val env = Map("k1" -> k1.toInt, "k2" -> k2.toInt, "r" -> r) + val env = Map("k1" -> k1.toInt, "k2" -> k2.toInt, "r" -> Colls.fromArray(r)) val prop = compile(env, "{ xor(getVar[Coll[Byte]](k1).get, getVar[Coll[Byte]](k2).get) == r }").asBoolValue.toSigmaProp val propTree = mkTestErgoTree(prop) @@ -119,7 +119,7 @@ class ContextEnrichingSpecification extends CompilerTestingCommons val prover = new ContextEnrichingTestProvingInterpreter val preimage = prover.contextExtenders(1).value.asInstanceOf[Coll[Byte]] - val env = Map("blake" -> Blake2b256(preimage.toArray)) + val env = Map("blake" -> Colls.fromArray(Blake2b256(preimage.toArray))) val prop = compile(env, """{ | blake2b256(getVar[Coll[Byte]](1).get) == blake @@ -149,7 +149,7 @@ class ContextEnrichingSpecification extends CompilerTestingCommons val preimage1 = prover.contextExtenders(1).value.asInstanceOf[Coll[Byte]] val preimage2 = prover.contextExtenders(2).value.asInstanceOf[Coll[Byte]] - val env = Map("blake" -> Blake2b256(preimage2.append(preimage1).toArray)) + val env = Map("blake" -> Colls.fromArray(Blake2b256(preimage2.append(preimage1).toArray))) val prop = compile(env, """{ | blake2b256(getVar[Coll[Byte]](2).get ++ getVar[Coll[Byte]](1).get) == blake diff --git a/sc/shared/src/test/scala/sigmastate/utxo/ErgoLikeInterpreterSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/ErgoLikeInterpreterSpecification.scala index 615a826649..f7adc194b5 100644 --- a/sc/shared/src/test/scala/sigmastate/utxo/ErgoLikeInterpreterSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/utxo/ErgoLikeInterpreterSpecification.scala @@ -5,11 +5,12 @@ import org.ergoplatform.ErgoBox.R4 import org.ergoplatform._ import org.scalatest.TryValues._ import scorex.crypto.hash.Blake2b256 +import sigma.{Colls, VersionContext} import sigma.ast.SCollection.SByteArray import sigma.ast._ import sigmastate._ import sigma.ast.syntax._ -import sigma.data.{AvlTreeData, ProveDHTuple, ProveDlog, TrivialProp} +import sigma.data.{AvlTreeData, CBox, ProveDHTuple, ProveDlog, TrivialProp} import sigma.util.Extensions.EcpOps import sigma.validation.ValidationException import sigmastate.eval._ @@ -51,8 +52,8 @@ class ErgoLikeInterpreterSpecification extends CompilerTestingCommons .withErgoTreeVersion(ergoTreeVersionInTests) val e = compile(Map( - "h1" -> ErgoTree.withSegregation(ergoTreeHeaderInTests, h1).bytes, - "h2" -> ErgoTree.withSegregation(ergoTreeHeaderInTests, h2).bytes), + "h1" -> Colls.fromArray(ErgoTree.withSegregation(ergoTreeHeaderInTests, h1).bytes), + "h2" -> Colls.fromArray(ErgoTree.withSegregation(ergoTreeHeaderInTests, h2).bytes)), "h1 == h1") val exp = TrueLeaf e shouldBe exp @@ -192,7 +193,7 @@ class ErgoLikeInterpreterSpecification extends CompilerTestingCommons val spendingTransaction = createTransaction(newBoxes) def mixingRequestProp(sender: ProveDlog, timeout: Int): ErgoTree = { - val env = Map("sender" -> sender, "timeout" -> timeout, "properHash" -> properHash) + val env = Map("sender" -> sender, "timeout" -> timeout, "properHash" -> Colls.fromArray(properHash)) val compiledProp = compile(env, """{ | val notTimePassed = HEIGHT <= timeout @@ -459,9 +460,14 @@ class ErgoLikeInterpreterSpecification extends CompilerTestingCommons val pubkey1 = prover.dlogSecrets.head.publicImage val pubkey2 = prover.dlogSecrets(1).publicImage + val tb = testBox(value = 10, ergoTree = mkTestErgoTree(pubkey1), creationHeight = 0) + val brother = if(VersionContext.current.isJitActivated) { + CBox(tb) + } else { + tb + } - val brother = testBox(value = 10, ergoTree = mkTestErgoTree(pubkey1), creationHeight = 0) - val brotherWithWrongId = testBox(value = 10, + val tbWithWrongId = testBox(value = 10, ergoTree = mkTestErgoTree(pubkey1), creationHeight = 0, boxIndex = 120: Short) @@ -482,7 +488,7 @@ class ErgoLikeInterpreterSpecification extends CompilerTestingCommons val propExpected = BinAnd( EQ(SizeOf(Inputs), IntConstant(2)), - EQ(ExtractId(ByIndex(Inputs, 0)), ExtractId(BoxConstant(brother)))).toSigmaProp + EQ(ExtractId(ByIndex(Inputs, 0)), ExtractId(BoxConstant(tb)))).toSigmaProp prop shouldBe propExpected // try a version of the script that matches the white paper @@ -496,18 +502,18 @@ class ErgoLikeInterpreterSpecification extends CompilerTestingCommons currentHeight = 50, lastBlockUtxoRoot = AvlTreeData.dummy, minerPubkey = ErgoLikeContextTesting.dummyPubkey, - boxesToSpend = IndexedSeq(brother, s), + boxesToSpend = IndexedSeq(tb, s), spendingTransaction, self = s, activatedVersionInTests) - val pr = prover.prove(emptyEnv + (ScriptNameProp -> "prove_prop"), propTree, ctx, fakeMessage).getOrThrow - verifier.verify(emptyEnv + (ScriptNameProp -> "verify_prop"), propTree, ctx, pr, fakeMessage).getOrThrow._1 shouldBe true + val pr = prover.prove(emptyEnv, propTree, ctx, fakeMessage).getOrThrow + verifier.verify(emptyEnv, propTree, ctx, pr, fakeMessage).getOrThrow._1 shouldBe true val wrongCtx = ErgoLikeContextTesting( currentHeight = 50, lastBlockUtxoRoot = AvlTreeData.dummy, minerPubkey = ErgoLikeContextTesting.dummyPubkey, - boxesToSpend = IndexedSeq(brotherWithWrongId, s), + boxesToSpend = IndexedSeq(tbWithWrongId, s), spendingTransaction, self = s, activatedVersionInTests) @@ -522,9 +528,9 @@ class ErgoLikeInterpreterSpecification extends CompilerTestingCommons }""".stripMargin).asBoolValue.toSigmaProp val prop2Tree = mkTestErgoTree(prop2) - prover.prove(emptyEnv + (ScriptNameProp -> "prove_prop2"), prop2Tree, ctx, fakeMessage).isFailure shouldBe true + prover.prove(emptyEnv, prop2Tree, ctx, fakeMessage).isFailure shouldBe true verifier - .verify(emptyEnv + (ScriptNameProp -> "verify_prop2"), prop2Tree, ctx, pr, fakeMessage) + .verify(emptyEnv, prop2Tree, ctx, pr, fakeMessage) .getOrThrow._1 shouldBe false } @@ -547,7 +553,12 @@ class ErgoLikeInterpreterSpecification extends CompilerTestingCommons val newBoxes = IndexedSeq(newBox) val spendingTransaction = createTransaction(newBoxes) - val env = Map("friend" -> friend) + val friendVar = if(VersionContext.current.isJitActivated){ + CBox(friend) + } else { + friend + } + val env = Map("friend" -> friendVar) val prop = compile(env, """{ | @@ -623,7 +634,7 @@ class ErgoLikeInterpreterSpecification extends CompilerTestingCommons val helloHash = Blake2b256.hash(preimageHello) - val env = Map("helloHash" -> helloHash) + val env = Map("helloHash" -> Colls.fromArray(helloHash)) val prop = compile(env, """{ | val cond = INPUTS(0).value > 10 diff --git a/sc/shared/src/test/scala/sigmastate/utxo/examples/AtomicSwapExampleSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/examples/AtomicSwapExampleSpecification.scala index 131aba22d0..7323dc6118 100644 --- a/sc/shared/src/test/scala/sigmastate/utxo/examples/AtomicSwapExampleSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/utxo/examples/AtomicSwapExampleSpecification.scala @@ -39,7 +39,6 @@ class AtomicSwapExampleSpecification extends CompilerTestingCommons with Compile val deadlineB = 500 val env = Map( - ScriptNameProp -> "atomic", "height1" -> height1, "height2" -> height2, "deadlineBob" -> deadlineB, "deadlineAlice" -> deadlineA, "pubkeyA" -> pubkeyA, "pubkeyB" -> pubkeyB, "hx" -> hx) diff --git a/sc/shared/src/test/scala/sigmastate/utxo/examples/ColdWalletAdvContractExampleSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/examples/ColdWalletAdvContractExampleSpecification.scala index 9bcfd81ecf..ef100a36a5 100644 --- a/sc/shared/src/test/scala/sigmastate/utxo/examples/ColdWalletAdvContractExampleSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/utxo/examples/ColdWalletAdvContractExampleSpecification.scala @@ -9,6 +9,7 @@ import sigmastate.helpers.{CompilerTestingCommons, ContextEnrichingTestProvingIn import sigmastate.helpers.TestingHelpers._ import sigmastate.interpreter.Interpreter.ScriptNameProp import sigma.ast.syntax._ +import sigmastate.interpreter.Interpreter class ColdWalletAdvContractExampleSpecification extends CompilerTestingCommons @@ -35,7 +36,6 @@ class ColdWalletAdvContractExampleSpecification extends CompilerTestingCommons val minSpend = 100 val env = Map( - ScriptNameProp -> "env", "user1" -> alicePubKey, "user2" -> bobPubKey, "user3" -> carolPubKey, @@ -109,12 +109,9 @@ class ColdWalletAdvContractExampleSpecification extends CompilerTestingCommons ) ) - val dave = new ErgoLikeTestProvingInterpreter // paying to dave, some arbitrary user - val davePubKey = dave.dlogSecrets.head.publicImage - val firstWithdrawHeight = depositHeight + 1 // - val spendEnv = Map(ScriptNameProp -> "spendEnv") + val spendEnv = Interpreter.emptyEnv // One of Alice, Bob or Carol withdraws val firstWithdrawAmount1Key = depositAmount * percent1Key / 100 // less than or equal to percent diff --git a/sc/shared/src/test/scala/sigmastate/utxo/examples/ColdWalletContractExampleSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/examples/ColdWalletContractExampleSpecification.scala index 1948bc16d9..bfeb9732a8 100644 --- a/sc/shared/src/test/scala/sigmastate/utxo/examples/ColdWalletContractExampleSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/utxo/examples/ColdWalletContractExampleSpecification.scala @@ -31,7 +31,6 @@ class ColdWalletContractExampleSpecification extends CompilerTestingCommons val minSpend = 100 val env = Map( - ScriptNameProp -> "env", "alice" -> alicePubKey, "bob" -> bobPubKey, "blocksIn24h" -> IntConstant(blocksIn24h), diff --git a/sc/shared/src/test/scala/sigmastate/utxo/examples/DHTupleExampleSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/examples/DHTupleExampleSpecification.scala index 9246cc1c8e..60569d061e 100644 --- a/sc/shared/src/test/scala/sigmastate/utxo/examples/DHTupleExampleSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/utxo/examples/DHTupleExampleSpecification.scala @@ -38,7 +38,6 @@ class DHTupleExampleSpecification extends CompilerTestingCommons val g_x = alicePubKey.value // g_x is Alice's public key (g_x = g^x) val env = Map( - ScriptNameProp -> "env", "g" -> g.toGroupElement, "g_x" -> g_x.toGroupElement ) diff --git a/sc/shared/src/test/scala/sigmastate/utxo/examples/DemurrageExampleSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/examples/DemurrageExampleSpecification.scala index 4ec6922c38..6d4ff117d3 100644 --- a/sc/shared/src/test/scala/sigmastate/utxo/examples/DemurrageExampleSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/utxo/examples/DemurrageExampleSpecification.scala @@ -49,7 +49,6 @@ class DemurrageExampleSpecification extends CompilerTestingCommons val regScript = userProver.dlogSecrets.head.publicImage val env = Map( - ScriptNameProp -> "Demurrage", "demurragePeriod" -> demurragePeriod, "demurrageCoeff" -> demurrageCoeff, "regScript" -> regScript diff --git a/sc/shared/src/test/scala/sigmastate/utxo/examples/IcoExample.scala b/sc/shared/src/test/scala/sigmastate/utxo/examples/IcoExample.scala index 556c56bc03..9c81e4539d 100644 --- a/sc/shared/src/test/scala/sigmastate/utxo/examples/IcoExample.scala +++ b/sc/shared/src/test/scala/sigmastate/utxo/examples/IcoExample.scala @@ -252,8 +252,7 @@ class IcoExample extends CompilerTestingCommons private val feeBytes = feeProp.bytes val env = Map( - ScriptNameProp -> "withdrawalScriptEnv", - "feeBytes" -> feeBytes, + "feeBytes" -> Colls.fromArray(feeBytes), "projectPubKey" -> project.secrets.head.publicImage ) lazy val withdrawalScript: SigmaPropValue = compile(env, @@ -313,7 +312,7 @@ class IcoExample extends CompilerTestingCommons Blake2b256(ErgoTreeSerializer.DefaultSerializer.serializeErgoTree(withdrawalTree)) } - def issuanceScript: SigmaPropValue = compile(env.updated("nextStageScriptHash", wsHash), + def issuanceScript: SigmaPropValue = compile(env.updated("nextStageScriptHash", Colls.fromArray(wsHash)), """{ | val openTree = SELF.R5[AvlTree].get | @@ -349,7 +348,7 @@ class IcoExample extends CompilerTestingCommons Blake2b256(ErgoTreeSerializer.DefaultSerializer.serializeErgoTree(tree)) } - def fundingScript: SigmaPropValue = compile(env.updated("nextStageScriptHash", issuanceHash), + def fundingScript: SigmaPropValue = compile(env.updated("nextStageScriptHash", Colls.fromArray(issuanceHash)), """{ | | val selfIndexIsZero = INPUTS(0).id == SELF.id diff --git a/sc/shared/src/test/scala/sigmastate/utxo/examples/LetsSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/examples/LetsSpecification.scala index 556fbf9c06..609a127bec 100644 --- a/sc/shared/src/test/scala/sigmastate/utxo/examples/LetsSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/utxo/examples/LetsSpecification.scala @@ -178,7 +178,7 @@ class LetsSpecification extends CompilerTestingCommons with CompilerCrossVersion val letsTokenId = Digest32Coll @@ Colls.fromArray(Array.fill(32)(Random.nextInt(100).toByte)) - val env = Map(ScriptNameProp -> "withdrawalScriptEnv", "letsToken" -> ByteArrayConstant(letsTokenId)) + val env = Map("letsToken" -> ByteArrayConstant(letsTokenId)) private val miningRewardsDelay = 720 private val feeProp = ErgoTreePredef.feeProposition(miningRewardsDelay) // create ErgoTree v0 @@ -235,7 +235,7 @@ class LetsSpecification extends CompilerTestingCommons with CompilerCrossVersion def userContractHash = Blake2b256(ErgoTreeSerializer.DefaultSerializer.serializeErgoTree(exchangeTree)) - def managementScript = compile(env.updated("userContractHash", userContractHash), + def managementScript = compile(env.updated("userContractHash", Colls.fromArray(userContractHash)), """{ | | val selfOut = OUTPUTS(0) diff --git a/sc/shared/src/test/scala/sigmastate/utxo/examples/MixExampleSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/examples/MixExampleSpecification.scala index fc19a485ee..fdb241a908 100644 --- a/sc/shared/src/test/scala/sigmastate/utxo/examples/MixExampleSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/utxo/examples/MixExampleSpecification.scala @@ -3,6 +3,7 @@ package sigmastate.utxo.examples import java.math.BigInteger import org.ergoplatform.ErgoBox.{R4, R5} import scorex.crypto.hash.Blake2b256 +import sigma.Colls import sigma.data.{AvlTreeData, ProveDHTuple, ProveDlog} import sigma.util.Extensions.EcpOps import sigmastate.CompilerCrossVersionProps @@ -41,7 +42,6 @@ class MixExampleSpecification extends CompilerTestingCommons // val alicePubKey:ProveDlog = ProveDlog(g_x) val fullMixEnv = Map( - ScriptNameProp -> "fullMixEnv", "g" -> g.toGroupElement, "gX" -> gX.toGroupElement ) @@ -60,10 +60,9 @@ class MixExampleSpecification extends CompilerTestingCommons ).asSigmaProp) val halfMixEnv = Map( - ScriptNameProp -> "halfMixEnv", "g" -> g.toGroupElement, "gX" -> gX.toGroupElement, - "fullMixScriptHash" -> Blake2b256(fullMixScript.bytes) + "fullMixScriptHash" -> Colls.fromArray(Blake2b256(fullMixScript.bytes)) ) // Note that below script allows Alice to spend the half-mix output anytime before Bob spends it. diff --git a/sc/shared/src/test/scala/sigmastate/utxo/examples/RPSGameExampleSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/examples/RPSGameExampleSpecification.scala index c695b8e07d..3ca85e892b 100644 --- a/sc/shared/src/test/scala/sigmastate/utxo/examples/RPSGameExampleSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/utxo/examples/RPSGameExampleSpecification.scala @@ -4,6 +4,7 @@ package sigmastate.utxo.examples import org.ergoplatform.ErgoBox.{R4, R5, R6, R7} import scorex.crypto.hash.Blake2b256 import scorex.utils.Random +import sigma.Colls import sigma.data.{AvlTreeData, ProveDlog} import sigma.ast.{ByteArrayConstant, ByteConstant, ErgoTree, IntConstant, SigmaPropConstant} import sigmastate._ @@ -51,9 +52,8 @@ class RPSGameExampleSpecification extends CompilerTestingCommons val h = Blake2b256(s :+ a) // Alice's commitment val fullGameEnv = Map( - ScriptNameProp -> "fullGameScriptEnv", "alice" -> alicePubKey, - "k" -> h + "k" -> Colls.fromArray(h) ) val fullGameScript = mkTestErgoTree(compile(fullGameEnv, @@ -78,9 +78,8 @@ class RPSGameExampleSpecification extends CompilerTestingCommons ).asSigmaProp) val halfGameEnv = Map( - ScriptNameProp -> "halfGameScript", "alice" -> alicePubKey, - "fullGameScriptHash" -> Blake2b256(fullGameScript.bytes) + "fullGameScriptHash" -> Colls.fromArray(Blake2b256(fullGameScript.bytes)) ) // Note that below script allows Alice to spend the half-game output anytime before Bob spends it. diff --git a/sc/shared/src/test/scala/sigmastate/utxo/examples/ReversibleTxExampleSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/examples/ReversibleTxExampleSpecification.scala index 4294dc5b4b..fad547460f 100644 --- a/sc/shared/src/test/scala/sigmastate/utxo/examples/ReversibleTxExampleSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/utxo/examples/ReversibleTxExampleSpecification.scala @@ -3,13 +3,14 @@ package sigmastate.utxo.examples import org.ergoplatform.ErgoBox.{R4, R5} import org.ergoplatform._ import scorex.crypto.hash.Blake2b256 +import sigma.Colls import sigma.data.AvlTreeData import sigma.ast.{ErgoTree, IntConstant, SigmaPropConstant} import sigmastate._ import sigmastate.helpers.{CompilerTestingCommons, ContextEnrichingTestProvingInterpreter, ErgoLikeContextTesting, ErgoLikeTestInterpreter} import sigmastate.helpers.TestingHelpers._ -import sigmastate.interpreter.Interpreter.ScriptNameProp import sigma.ast.syntax._ +import sigmastate.interpreter.Interpreter class ReversibleTxExampleSpecification extends CompilerTestingCommons @@ -79,7 +80,6 @@ class ReversibleTxExampleSpecification extends CompilerTestingCommons val carolPubKey = carol.dlogSecrets.head.publicImage val withdrawEnv = Map( - ScriptNameProp -> "withdrawEnv", "carol" -> carolPubKey // this pub key can reverse payments ) @@ -94,12 +94,11 @@ class ReversibleTxExampleSpecification extends CompilerTestingCommons val blocksIn24h = 500 val feeProposition = ErgoTreePredef.feeProposition() val depositEnv = Map( - ScriptNameProp -> "depositEnv", "alice" -> alicePubKey, "blocksIn24h" -> blocksIn24h, "maxFee" -> 10L, - "feePropositionBytes" -> feeProposition.bytes, - "withdrawScriptHash" -> Blake2b256(withdrawScript.bytes) + "feePropositionBytes" -> Colls.fromArray(feeProposition.bytes), + "withdrawScriptHash" -> Colls.fromArray(Blake2b256(withdrawScript.bytes)) ) val depositScript = mkTestErgoTree(compile(depositEnv, @@ -189,7 +188,7 @@ class ReversibleTxExampleSpecification extends CompilerTestingCommons self = reversibleWithdrawOutput, activatedVersionInTests ) - val spendEnv = Map(ScriptNameProp -> "spendEnv") + val spendEnv = Interpreter.emptyEnv val proofBobSpend = bob.prove(spendEnv, withdrawScript, bobSpendContext, fakeMessage).get.proof diff --git a/sc/shared/src/test/scala/sigmastate/utxo/examples/TimedPaymentExampleSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/examples/TimedPaymentExampleSpecification.scala index 2657a49eb0..fb1c275fb8 100644 --- a/sc/shared/src/test/scala/sigmastate/utxo/examples/TimedPaymentExampleSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/utxo/examples/TimedPaymentExampleSpecification.scala @@ -27,7 +27,6 @@ class TimedPaymentExampleSpecification extends CompilerTestingCommons val bobPubKey = bob.dlogSecrets.head.publicImage val env = Map( - ScriptNameProp -> "env", "alice" -> alicePubKey ) diff --git a/sc/shared/src/test/scala/sigmastate/utxo/examples/XorGameExampleSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/examples/XorGameExampleSpecification.scala index b3d6d4eff8..8821ccb72e 100644 --- a/sc/shared/src/test/scala/sigmastate/utxo/examples/XorGameExampleSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/utxo/examples/XorGameExampleSpecification.scala @@ -4,6 +4,7 @@ package sigmastate.utxo.examples import org.ergoplatform.ErgoBox.{R4, R5, R6} import scorex.crypto.hash.Blake2b256 import scorex.utils.Random +import sigma.Colls import sigma.data.{AvlTreeData, ProveDlog} import sigma.ast.{ByteArrayConstant, ByteConstant, IntConstant, SigmaPropConstant} import sigmastate._ @@ -51,9 +52,8 @@ class XorGameExampleSpecification extends CompilerTestingCommons val h = Blake2b256(s :+ a) // Alice's commitment val fullGameEnv = Map( - ScriptNameProp -> "fullGameScriptEnv", "alice" -> alicePubKey, - "h" -> h + "h" -> Colls.fromArray(h) ) val fullGameScript = mkTestErgoTree(compile(fullGameEnv, @@ -73,9 +73,8 @@ class XorGameExampleSpecification extends CompilerTestingCommons ).asSigmaProp) val halfGameEnv = Map( - ScriptNameProp -> "halfGameScript", "alice" -> alicePubKey, - "fullGameScriptHash" -> Blake2b256(fullGameScript.bytes) + "fullGameScriptHash" -> Colls.fromArray(Blake2b256(fullGameScript.bytes)) ) // Note that below script allows Alice to spend the half-game output anytime before Bob spends it. From f77be78b0cbf5726f5575611decb2bbcd10be07c Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Thu, 3 Oct 2024 12:05:57 +0300 Subject: [PATCH 253/314] fixing JS tests --- data/js/src/main/scala/sigma/Platform.scala | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/data/js/src/main/scala/sigma/Platform.scala b/data/js/src/main/scala/sigma/Platform.scala index 45d74ea2b2..2bc9995cd2 100644 --- a/data/js/src/main/scala/sigma/Platform.scala +++ b/data/js/src/main/scala/sigma/Platform.scala @@ -14,23 +14,23 @@ object Platform { private[sigma] def liftToConstant(obj: Any, builder: SigmaBuilder): Nullable[Constant[SType]] = { import builder._ obj match { - case arr: Array[Boolean] => Nullable(mkCollectionConstant[SBoolean.type](arr, SBoolean)) - case arr: Array[Byte] => Nullable(mkCollectionConstant[SByte.type](arr, SByte)) - case arr: Array[Short] => Nullable(mkCollectionConstant[SShort.type](arr, SShort)) - case arr: Array[Int] => Nullable(mkCollectionConstant[SInt.type](arr, SInt)) - case arr: Array[Long] => Nullable(mkCollectionConstant[SLong.type](arr, SLong)) - case arr: Array[BigInteger] => Nullable(mkCollectionConstant[SBigInt.type](arr.map[BigInt](n => CBigInt(n)), SBigInt)) - case arr: Array[String] => Nullable(mkCollectionConstant[SString.type](arr, SString)) + 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 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 => Nullable(mkConstant[SBigInt.type](CBigInt(v), SBigInt)) + case v: BigInteger if !VersionContext.current.isV6SoftForkActivated => Nullable(mkConstant[SBigInt.type](CBigInt(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 v: String => Nullable(mkConstant[SString.type](v, SString)) + 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)) // The Box lifting was broken in v4.x. `SigmaDsl.Box(b)` was missing which means the @@ -38,7 +38,7 @@ object Platform { // 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 => + case b: ErgoBox if !VersionContext.current.isV6SoftForkActivated => 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 From 6c1ac1ebd439ea5185a0e124674dea9c7c9fac1b Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Thu, 3 Oct 2024 12:32:26 +0300 Subject: [PATCH 254/314] fix for AVLtreedata lift in JS --- data/js/src/main/scala/sigma/Platform.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/js/src/main/scala/sigma/Platform.scala b/data/js/src/main/scala/sigma/Platform.scala index 2bc9995cd2..64b17085ae 100644 --- a/data/js/src/main/scala/sigma/Platform.scala +++ b/data/js/src/main/scala/sigma/Platform.scala @@ -48,7 +48,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 => Nullable(mkConstant[SAvlTree.type](CAvlTree(avl), SAvlTree)) + case avl: AvlTreeData if !VersionContext.current.isV6SoftForkActivated => 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)) From e4a611d6cd9a66d9cef01374e02fa24f0960ed7d Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Fri, 4 Oct 2024 22:02:08 +0300 Subject: [PATCH 255/314] fixing MethodCallSerializerSpecification --- .../sigma/serialization/MethodCallSerializerSpecification.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interpreter/shared/src/test/scala/sigma/serialization/MethodCallSerializerSpecification.scala b/interpreter/shared/src/test/scala/sigma/serialization/MethodCallSerializerSpecification.scala index 1ea607f628..5ea171ba1f 100644 --- a/interpreter/shared/src/test/scala/sigma/serialization/MethodCallSerializerSpecification.scala +++ b/interpreter/shared/src/test/scala/sigma/serialization/MethodCallSerializerSpecification.scala @@ -40,7 +40,7 @@ class MethodCallSerializerSpecification extends SerializationSpecification { code } - an[ValidationException] should be thrownBy ( + an[SerializerException] should be thrownBy ( VersionContext.withVersions((VersionContext.V6SoftForkVersion - 1).toByte, 1) { code } From c5c37ffa6175f0841fcc1037c95889c36ef902cb Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Fri, 4 Oct 2024 22:27:50 +0300 Subject: [PATCH 256/314] fixing JS reflection --- .../main/scala/sigma/SigmaDataReflection.scala | 8 ++++++++ .../src/main/scala/sigma/ast/methods.scala | 18 ------------------ .../sigma/compiler/ir/GraphIRReflection.scala | 7 +++++++ 3 files changed, 15 insertions(+), 18 deletions(-) diff --git a/data/shared/src/main/scala/sigma/SigmaDataReflection.scala b/data/shared/src/main/scala/sigma/SigmaDataReflection.scala index c64bdee877..981bcc8b51 100644 --- a/data/shared/src/main/scala/sigma/SigmaDataReflection.scala +++ b/data/shared/src/main/scala/sigma/SigmaDataReflection.scala @@ -86,6 +86,14 @@ object SigmaDataReflection { ) ) + registerClassEntry(classOf[ByteArrayToLong], + constructors = Array( + mkConstructor(Array(classOf[Value[_]])) { args => + new ByteArrayToLong(args(0).asInstanceOf[Value[SByteArray]]) + } + ) + ) + registerClassEntry(classOf[LongToByteArray], constructors = Array( mkConstructor(Array(classOf[Value[_]])) { args => diff --git a/data/shared/src/main/scala/sigma/ast/methods.scala b/data/shared/src/main/scala/sigma/ast/methods.scala index 2f0bc6a69d..c6ea897353 100644 --- a/data/shared/src/main/scala/sigma/ast/methods.scala +++ b/data/shared/src/main/scala/sigma/ast/methods.scala @@ -1718,24 +1718,6 @@ case object SGlobalMethods extends MonoTypeMethods { .withIRInfo(MethodCallIrBuilder) .withInfo(MethodCall, "Decode nbits-encoded big integer number", ArgInfo("nbits", "NBits-encoded argument")) - /** - * encodeNBits evaluation with costing - */ - def encodeNbits_eval(mc: MethodCall, G: SigmaDslBuilder, bigInt: BigInt)(implicit E: ErgoTreeEvaluator): Long = { - E.addFixedCost(EnDecodeNBitsCost, encodeNBitsMethod.opDesc) { - NBitsUtils.encodeCompactBits(bigInt.asInstanceOf[CBigInt].wrappedValue) - } - } - - /** - * decodeNBits evaluation with costing - */ - def decodeNbits_eval(mc: MethodCall, G: SigmaDslBuilder, l: Long)(implicit E: ErgoTreeEvaluator): BigInt = { - E.addFixedCost(EnDecodeNBitsCost, decodeNBitsMethod.opDesc) { - CBigInt(NBitsUtils.decodeCompactBits(l).bigInteger) - } - } - lazy val serializeMethod = SMethod(this, "serialize", SFunc(Array(SGlobal, tT), SByteArray, Array(paramT)), 3, DynamicCost) .withIRInfo(MethodCallIrBuilder) diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/GraphIRReflection.scala b/sc/shared/src/main/scala/sigma/compiler/ir/GraphIRReflection.scala index 79fba9bb96..72438d2641 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/GraphIRReflection.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/GraphIRReflection.scala @@ -1,5 +1,6 @@ package sigma.compiler.ir +import sigma.{BigInt, SigmaDslBuilder} import sigma.ast.SType import sigma.compiler.ir.primitives.Thunks import sigma.data.RType @@ -512,6 +513,12 @@ object GraphIRReflection { mkMethod(clazz, "serialize", Array[Class[_]](classOf[Base#Ref[_]])) { (obj, args) => obj.asInstanceOf[ctx.SigmaDslBuilder].serialize(args(0).asInstanceOf[ctx.Ref[Any]]) }, + mkMethod(clazz, "encodeNbits", Array[Class[_]](classOf[Base#Ref[_]])) { (obj, args) => + obj.asInstanceOf[ctx.SigmaDslBuilder].encodeNbits(args(0).asInstanceOf[ctx.Ref[ctx.BigInt]]) + }, + mkMethod(clazz, "decodeNbits", Array[Class[_]](classOf[Base#Ref[_]])) { (obj, args) => + obj.asInstanceOf[ctx.SigmaDslBuilder].decodeNbits(args(0).asInstanceOf[ctx.Ref[Long]]) + }, mkMethod(clazz, "fromBigEndianBytes", Array[Class[_]](classOf[Base#Ref[_]], classOf[TypeDescs#Elem[_]])) { (obj, args) => obj.asInstanceOf[ctx.SigmaDslBuilder].fromBigEndianBytes(args(0).asInstanceOf[ctx.Ref[ctx.Coll[Byte]]])(args(1).asInstanceOf[ctx.Elem[SType]]) } From 1d47d5ffc69be4f9fe12a9713bb277b2775cd988 Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Mon, 7 Oct 2024 18:47:46 +0300 Subject: [PATCH 257/314] addressing review comments --- core/shared/src/main/scala/sigma/Colls.scala | 19 ++++++------ .../scala/sigma/data/CollsOverArrays.scala | 10 ++++-- .../src/test/scala/sigma/CollsTests.scala | 26 ++++++++++++++++ .../src/main/scala/sigma/ast/methods.scala | 31 +++++++++++++------ .../scala/sigma/LanguageSpecificationV6.scala | 8 +++-- 5 files changed, 72 insertions(+), 22 deletions(-) diff --git a/core/shared/src/main/scala/sigma/Colls.scala b/core/shared/src/main/scala/sigma/Colls.scala index f1633a68a4..d10026066b 100644 --- a/core/shared/src/main/scala/sigma/Colls.scala +++ b/core/shared/src/main/scala/sigma/Colls.scala @@ -45,13 +45,10 @@ trait Coll[@specialized A] { */ def apply(i: Int): A - /** The element at given index. - * Indices start at `0`; `xs.apply(0)` is the first element of collection `xs`. - * Note the indexing syntax `xs(i)` is a shorthand for `xs.apply(i)`. + /** The element at given index or None if there is no such element. Indices start at `0`. * * @param i the index - * @return the element at the given index - * @throws ArrayIndexOutOfBoundsException if `i < 0` or `length <= i` + * @return the element at the given index, or None if there is no such element */ def get(i: Int): Option[A] = { if (isDefinedAt(i)) { @@ -92,12 +89,16 @@ trait Coll[@specialized A] { * produces a collection ((x0, y0), ..., (xK, yK)) where K = min(N, M) */ def zip[@specialized B](ys: Coll[B]): Coll[(A, B)] - /** For this collection (x0, ..., xN) and other collection (y0, ..., yM) - * produces a collection ((x0, y0), ..., (xK, yK)) where K = min(N, M) */ + /** + * @return true if first elements of this collection form given `ys` collection, false otherwise. + * E.g. [1,2,3] starts with [1,2] + */ def startsWith(ys: Coll[A]): Boolean - /** For this collection (x0, ..., xN) and other collection (y0, ..., yM) - * produces a collection ((x0, y0), ..., (xK, yK)) where K = min(N, M) */ + /** + * @return true if last elements of this collection form given `ys` collection, false otherwise. + * E.g. [1,2,3] ends with [2,3] + */ def endsWith(ys: Coll[A]): Boolean /** Tests whether a predicate holds for at least one element of this collection. diff --git a/core/shared/src/main/scala/sigma/data/CollsOverArrays.scala b/core/shared/src/main/scala/sigma/data/CollsOverArrays.scala index 506dc001ea..eb4c1e4931 100644 --- a/core/shared/src/main/scala/sigma/data/CollsOverArrays.scala +++ b/core/shared/src/main/scala/sigma/data/CollsOverArrays.scala @@ -354,9 +354,15 @@ class PairOfCols[@specialized L, @specialized R](val ls: Coll[L], val rs: Coll[R def zip[@specialized B](ys: Coll[B]): PairColl[(L,R), B] = builder.pairColl(this, ys) - def startsWith(ys: Coll[(L, R)]): Boolean = toArray.startsWith(ys.toArray) + def startsWith(ys: Coll[(L, R)]): Boolean = ys match { + case yp: PairOfCols[L, R] => ls.startsWith(yp.ls) && rs.startsWith(yp.rs) + case _ => toArray.startsWith(ys.toArray) + } - def endsWith(ys: Coll[(L, R)]): Boolean = toArray.endsWith(ys.toArray) + def endsWith(ys: Coll[(L, R)]): Boolean = ys match { + case yp: PairOfCols[L, R] => ls.endsWith(yp.ls) && rs.endsWith(yp.rs) + case _ => toArray.endsWith(ys.toArray) + } override def indices: Coll[Int] = if (ls.length <= rs.length) ls.indices else rs.indices diff --git a/core/shared/src/test/scala/sigma/CollsTests.scala b/core/shared/src/test/scala/sigma/CollsTests.scala index 4886112742..da427ba576 100644 --- a/core/shared/src/test/scala/sigma/CollsTests.scala +++ b/core/shared/src/test/scala/sigma/CollsTests.scala @@ -386,6 +386,32 @@ class CollsTests extends AnyPropSpec with ScalaCheckPropertyChecks with Matchers } } + property("Coll.startsWith") { + val minSuccess = minSuccessful(50) + forAll(collGen, minSuccess) { col => + val n = col.length / 2 + val prefix = col.take(n) + val pairs = col.zip(col) + pairs.startsWith(prefix.zip(prefix)) shouldBe true + col.startsWith(prefix) shouldBe true + val pairOfCols = new PairOfCols[Int, Int](col, col) + pairOfCols.startsWith(pairOfCols.take(n)) shouldBe true + } + } + + property("Coll.endsWith") { + val minSuccess = minSuccessful(50) + forAll(collGen, minSuccess) { col => + val n = col.length / 2 + val suffix = col.slice(n, col.length) + col.endsWith(suffix) shouldBe true + val pairs = col.zip(col) + pairs.endsWith(suffix.zip(suffix)) shouldBe true + val pairOfCols = new PairOfCols[Int, Int](col, col) + pairOfCols.endsWith(pairOfCols.slice(n, col.length)) shouldBe true + } + } + property("Coll.equals") { def checkColls(repl: Coll[_], coll: Coll[_]) = { assert(coll == repl) diff --git a/data/shared/src/main/scala/sigma/ast/methods.scala b/data/shared/src/main/scala/sigma/ast/methods.scala index 855da4eb73..dc85205b37 100644 --- a/data/shared/src/main/scala/sigma/ast/methods.scala +++ b/data/shared/src/main/scala/sigma/ast/methods.scala @@ -1070,8 +1070,10 @@ object SCollectionMethods extends MethodsContainer with MethodByNameUnapply { // ======== 6.0 methods below =========== + private val reverseCostKind = Append.costKind + val ReverseMethod = SMethod(this, "reverse", - SFunc(Array(ThisType), ThisType, paramIVSeq), 30, Zip_CostKind) // todo: costing + SFunc(Array(ThisType), ThisType, paramIVSeq), 30, reverseCostKind) .withIRInfo(MethodCallIrBuilder) .withInfo(MethodCall, "") @@ -1087,10 +1089,12 @@ object SCollectionMethods extends MethodsContainer with MethodByNameUnapply { } } + private val distinctCostKind = PerItemCost(baseCost = JitCost(60), perChunkCost = JitCost(5), chunkSize = 100) + val DistinctMethod = SMethod(this, "distinct", - SFunc(Array(ThisType), ThisType, paramIVSeq), 31, Zip_CostKind) // todo: costing + SFunc(Array(ThisType), ThisType, paramIVSeq), 31, distinctCostKind) .withIRInfo(MethodCallIrBuilder) - .withInfo(MethodCall, "") + .withInfo(MethodCall, "Returns inversed collection.") /** Implements evaluation of Coll.reverse method call ErgoTree node. * Called via reflection based on naming convention. @@ -1104,10 +1108,13 @@ object SCollectionMethods extends MethodsContainer with MethodByNameUnapply { } } + private val startsWithCostKind = Zip_CostKind + val StartsWithMethod = SMethod(this, "startsWith", - SFunc(Array(ThisType, ThisType), SBoolean, paramIVSeq), 32, Zip_CostKind) // todo: costing + SFunc(Array(ThisType, ThisType), SBoolean, paramIVSeq), 32, startsWithCostKind) .withIRInfo(MethodCallIrBuilder) - .withInfo(MethodCall, "") + .withInfo(MethodCall, "Returns true if this collection starts with given one, false otherwise.", + ArgInfo("prefix", "Collection to be checked for being a prefix of this collection.")) /** Implements evaluation of Coll.zip method call ErgoTree node. * Called via reflection based on naming convention. @@ -1121,10 +1128,13 @@ object SCollectionMethods extends MethodsContainer with MethodByNameUnapply { } } + private val endsWithCostKind = Zip_CostKind + val EndsWithMethod = SMethod(this, "endsWith", - SFunc(Array(ThisType, ThisType), SBoolean, paramIVSeq), 33, Zip_CostKind) // todo: costing + SFunc(Array(ThisType, ThisType), SBoolean, paramIVSeq), 33, endsWithCostKind) .withIRInfo(MethodCallIrBuilder) - .withInfo(MethodCall, "") + .withInfo(MethodCall, "Returns true if this collection ends with given one, false otherwise.", + ArgInfo("suffix", "Collection to be checked for being a suffix of this collection.")) /** Implements evaluation of Coll.zip method call ErgoTree node. * Called via reflection based on naming convention. @@ -1139,9 +1149,12 @@ object SCollectionMethods extends MethodsContainer with MethodByNameUnapply { } val GetMethod = SMethod(this, "get", - SFunc(Array(ThisType, SInt), SOption(tIV), Array[STypeParam](tIV)), 34, ByIndex.costKind) //todo: costing + SFunc(Array(ThisType, SInt), SOption(tIV), Array[STypeParam](tIV)), 34, ByIndex.costKind) .withIRInfo(MethodCallIrBuilder) - .withInfo(MethodCall, "") + .withInfo(MethodCall, + "Returns Some(element) if there is an element at given index, None otherwise.", + ArgInfo("index", "Index of an element (starting from 0).") + ) private val v5Methods = super.getMethods() ++ Seq( SizeMethod, diff --git a/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala b/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala index ecd2c411ed..481c7101da 100644 --- a/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala +++ b/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala @@ -11,7 +11,7 @@ import sigma.ast.ErgoTree.ZeroHeader import sigma.ast.SCollection.SByteArray import sigma.ast.syntax.TrueSigmaProp import sigma.ast.{SInt, _} -import sigma.data.{CBigInt, CBox, CHeader, 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} @@ -1639,6 +1639,8 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite => Coll(1, 2) -> Expected(ExpectedResult(Success(Coll(1, 2)), None)), Coll(1, 1, 2) -> Expected(ExpectedResult(Success(Coll(1, 2)), None)), Coll(1, 2, 2) -> Expected(ExpectedResult(Success(Coll(1, 2)), None)), + Coll(2, 2, 2) -> Expected(ExpectedResult(Success(Coll(2)), None)), + Coll(3, 1, 2, 2, 2, 4, 4, 1) -> Expected(ExpectedResult(Success(Coll(3, 1, 2, 4)), None)), Coll[Int]() -> Expected(ExpectedResult(Success(Coll[Int]()), None)) ), f @@ -1656,8 +1658,10 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite => Seq( (Coll(1, 2, 3), Coll(1, 2)) -> Expected(ExpectedResult(Success(true), None)), (Coll(1, 2, 3), Coll(1, 2, 3)) -> Expected(ExpectedResult(Success(true), None)), + (Coll(1, 2, 3), Coll(1, 2, 4)) -> Expected(ExpectedResult(Success(false), None)), (Coll(1, 2, 3), Coll(1, 2, 3, 4)) -> Expected(ExpectedResult(Success(false), None)), - (Coll[Int](), Coll[Int]()) -> Expected(ExpectedResult(Success(true), None)) + (Coll[Int](), Coll[Int]()) -> Expected(ExpectedResult(Success(true), None)), + (Coll[Int](1, 2), Coll[Int]()) -> Expected(ExpectedResult(Success(true), None)) ), f ) From 08b02c7489f9eec8cd5168602b45037355b1d945 Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Mon, 7 Oct 2024 20:47:39 +0300 Subject: [PATCH 258/314] initial some test passing --- .../src/main/scala/sigma/SigmaDsl.scala | 4 +++ .../src/main/scala/sigma/ast/methods.scala | 17 ++++++++++- .../scala/sigma/data/CSigmaDslBuilder.scala | 8 +++++ .../sigma/compiler/ir/GraphBuilding.scala | 4 +++ .../ir/wrappers/sigma/SigmaDslUnit.scala | 2 ++ .../ir/wrappers/sigma/impl/SigmaDslImpl.scala | 29 +++++++++++++++++++ .../utxo/BasicOpsSpecification.scala | 21 ++++++++++++++ 7 files changed, 84 insertions(+), 1 deletion(-) diff --git a/core/shared/src/main/scala/sigma/SigmaDsl.scala b/core/shared/src/main/scala/sigma/SigmaDsl.scala index 8c639191a8..a0407ad97c 100644 --- a/core/shared/src/main/scala/sigma/SigmaDsl.scala +++ b/core/shared/src/main/scala/sigma/SigmaDsl.scala @@ -767,5 +767,9 @@ trait SigmaDslBuilder { /** Returns a number decoded from provided big-endian bytes array. */ def fromBigEndianBytes[T](bytes: Coll[Byte])(implicit cT: RType[T]): T + + def some[T](value: T)(implicit cT: RType[T]): Option[T] + + def none[T]()(implicit cT: RType[T]): Option[T] } diff --git a/data/shared/src/main/scala/sigma/ast/methods.scala b/data/shared/src/main/scala/sigma/ast/methods.scala index dc85205b37..74ca9cdd3f 100644 --- a/data/shared/src/main/scala/sigma/ast/methods.scala +++ b/data/shared/src/main/scala/sigma/ast/methods.scala @@ -1835,13 +1835,28 @@ case object SGlobalMethods extends MonoTypeMethods { Colls.fromArray(w.toBytes) } + lazy val someMethod = SMethod(this, "some", + SFunc(Array(SGlobal, tT), SOption(tT), Array(paramT)), 8, FixedCost(JitCost(5)), Seq(tT)) // todo: cost + .withIRInfo(MethodCallIrBuilder, + javaMethodOf[SigmaDslBuilder, Any, RType[_]]("some"), + { mtype => Array(mtype.tRange) }) + .withInfo(MethodCall, "", + ArgInfo("value", "value to be serialized")) + + lazy val noneMethod = SMethod(this, "none", + SFunc(Array(SGlobal, tT), SOption(tT), Array(paramT)), 9, FixedCost(JitCost(5))) // todo: cost + .withIRInfo(MethodCallIrBuilder) + .withInfo(MethodCall, "") + protected override def getMethods() = super.getMethods() ++ { if (VersionContext.current.isV6SoftForkActivated) { Seq( groupGeneratorMethod, xorMethod, serializeMethod, - fromBigEndianBytesMethod + fromBigEndianBytesMethod, + someMethod, + noneMethod ) } else { Seq( diff --git a/data/shared/src/main/scala/sigma/data/CSigmaDslBuilder.scala b/data/shared/src/main/scala/sigma/data/CSigmaDslBuilder.scala index 2ae4f73703..2259bcca5a 100644 --- a/data/shared/src/main/scala/sigma/data/CSigmaDslBuilder.scala +++ b/data/shared/src/main/scala/sigma/data/CSigmaDslBuilder.scala @@ -245,6 +245,14 @@ class CSigmaDslBuilder extends SigmaDslBuilder { dsl => DataSerializer.serialize(value.asInstanceOf[SType#WrappedType], tpe, w) Colls.fromArray(w.toBytes) } + + override def some[T](value: T)(implicit cT: RType[T]): Option[T] = { + Some(value) + } + + override def none[T]()(implicit cT: RType[T]): Option[T] = { + None + } } /** Default singleton instance of Global object, which implements global ErgoTree functions. */ 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 660ccc93ce..c1d1db40a2 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/GraphBuilding.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/GraphBuilding.scala @@ -1174,6 +1174,10 @@ trait GraphBuilding extends Base with DefRewriting { IR: IRContext => val bytes = asRep[Coll[Byte]](argsV(0)) val cT = stypeToElem(method.stype.tRange.withSubstTypes(typeSubst)) g.fromBigEndianBytes(bytes)(cT) + case SGlobalMethods.someMethod.name => + val value = asRep[tT.WrappedType](argsV(0)) + val cT = stypeToElem(typeSubst.apply(tT)).asInstanceOf[Elem[tT.WrappedType]] + g.some(value)(cT) case _ => throwError() } case (x: Ref[tNum], _: SNumericTypeMethods) => method.name match { diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/SigmaDslUnit.scala b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/SigmaDslUnit.scala index 11a306447e..d8a7a297bc 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/SigmaDslUnit.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/SigmaDslUnit.scala @@ -117,6 +117,8 @@ import scalan._ def xor(l: Ref[Coll[Byte]], r: Ref[Coll[Byte]]): Ref[Coll[Byte]] def serialize[T](value: Ref[T]): Ref[Coll[Byte]] def fromBigEndianBytes[T](bytes: Ref[Coll[Byte]])(implicit cT: Elem[T]): Ref[T] + def some[T](value: Ref[T])(implicit cT: Elem[T]): Ref[WOption[T]] + def none[T]()(implicit cT: Elem[T]): Ref[WOption[T]] }; trait CostModelCompanion; trait BigIntCompanion; diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/SigmaDslImpl.scala b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/SigmaDslImpl.scala index 2c87b0b139..de4370da50 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/SigmaDslImpl.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/SigmaDslImpl.scala @@ -1978,6 +1978,20 @@ object SigmaDslBuilder extends EntityObject("SigmaDslBuilder") { true, false, cT)) } + override def some[T](value: Ref[T])(implicit cT: Elem[T]): Ref[WOption[T]] = { + asRep[WOption[T]](mkMethodCall(self, + SigmaDslBuilderClass.getMethod("some", classOf[Sym], classOf[Elem[T]]), + Array[AnyRef](value, cT, Map(tT -> Evaluation.rtypeToSType(cT.sourceType))), + true, false, element[WOption[T]])) + } + + override def none[T]()(implicit cT: Elem[T]): Ref[WOption[T]] = { + asRep[WOption[T]](mkMethodCall(self, + SigmaDslBuilderClass.getMethod("none", classOf[Elem[T]]), + Array[AnyRef](cT, Map(tT -> Evaluation.rtypeToSType(cT.sourceType))), + true, false, element[WOption[T]])) + } + } implicit object LiftableSigmaDslBuilder @@ -2151,6 +2165,21 @@ object SigmaDslBuilder extends EntityObject("SigmaDslBuilder") { Array[AnyRef](bytes, cT), true, true, cT, Map(tT -> Evaluation.rtypeToSType(cT.sourceType)))) } + + def some[T](value: Ref[T])(implicit cT: Elem[T]): Ref[WOption[T]] = { + asRep[WOption[T]](mkMethodCall(source, + SigmaDslBuilderClass.getMethod("some", classOf[Sym], classOf[Elem[T]]), + Array[AnyRef](value, cT), + true, true, element[WOption[T]], Map(tT -> Evaluation.rtypeToSType(cT.sourceType)))) + } + + def none[T]()(implicit cT: Elem[T]): Ref[WOption[T]] = { + asRep[WOption[T]](mkMethodCall(source, + SigmaDslBuilderClass.getMethod("none", classOf[Elem[T]]), + Array[AnyRef](cT), + true, true, element[WOption[T]], Map(tT -> Evaluation.rtypeToSType(cT.sourceType)))) + } + } // entityUnref: single unref method for each type family diff --git a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala index 22810c125b..16817e08ae 100644 --- a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala @@ -1734,4 +1734,25 @@ class BasicOpsSpecification extends CompilerTestingCommons } } + property("Global.some") { + val ext: Seq[VarBinding] = Seq( + (intVar1, IntConstant(0)) + ) + def someTest(): Assertion = { + test("some", env, ext, + """{ + | val xo = Global.some[Int](5) + | xo.get == 5 + |}""".stripMargin, + null + ) + } + + if (VersionContext.current.isV6SoftForkActivated) { + someTest() + } else { + an[Exception] should be thrownBy someTest() + } + } + } From 2ba5a4fb7f50424a2a2395ceb08b43726c54785a Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Tue, 8 Oct 2024 14:57:32 +0300 Subject: [PATCH 259/314] PropertyCallSerializer fix, explicitTypeArgs fix, more tests --- .../src/main/scala/sigma/ast/methods.scala | 6 ++- .../PropertyCallSerializer.scala | 27 ++++++++++- .../sigma/compiler/ir/GraphBuilding.scala | 3 ++ .../ir/wrappers/sigma/impl/SigmaDslImpl.scala | 12 ++--- .../utxo/BasicOpsSpecification.scala | 45 ++++++++++++++++++- 5 files changed, 82 insertions(+), 11 deletions(-) diff --git a/data/shared/src/main/scala/sigma/ast/methods.scala b/data/shared/src/main/scala/sigma/ast/methods.scala index 74ca9cdd3f..62a8691eec 100644 --- a/data/shared/src/main/scala/sigma/ast/methods.scala +++ b/data/shared/src/main/scala/sigma/ast/methods.scala @@ -1844,8 +1844,10 @@ case object SGlobalMethods extends MonoTypeMethods { ArgInfo("value", "value to be serialized")) lazy val noneMethod = SMethod(this, "none", - SFunc(Array(SGlobal, tT), SOption(tT), Array(paramT)), 9, FixedCost(JitCost(5))) // todo: cost - .withIRInfo(MethodCallIrBuilder) + SFunc(Array(SGlobal), SOption(tT), Array(paramT)), 9, FixedCost(JitCost(5)), Seq(tT)) // todo: cost + .withIRInfo(MethodCallIrBuilder, + javaMethodOf[SigmaDslBuilder, RType[_]]("none"), + { mtype => Array(mtype.tRange) }) .withInfo(MethodCall, "") protected override def getMethods() = super.getMethods() ++ { diff --git a/data/shared/src/main/scala/sigma/serialization/PropertyCallSerializer.scala b/data/shared/src/main/scala/sigma/serialization/PropertyCallSerializer.scala index 10411e21ce..072e7a7ed5 100644 --- a/data/shared/src/main/scala/sigma/serialization/PropertyCallSerializer.scala +++ b/data/shared/src/main/scala/sigma/serialization/PropertyCallSerializer.scala @@ -5,6 +5,10 @@ import sigma.serialization.CoreByteWriter.{ArgInfo, DataInfo} import sigma.ast._ import sigma.ast.syntax.SValue import SigmaByteWriter._ +import debox.cfor +import sigma.util.safeNewArray + +import scala.collection.compat.immutable.ArraySeq case class PropertyCallSerializer(cons: (Value[SType], SMethod, IndexedSeq[Value[SType]], STypeSubst) => Value[SType]) extends ValueSerializer[MethodCall] { @@ -17,6 +21,10 @@ case class PropertyCallSerializer(cons: (Value[SType], SMethod, IndexedSeq[Value w.put(mc.method.objType.typeId, typeCodeInfo) w.put(mc.method.methodId, methodCodeInfo) w.putValue(mc.obj, objInfo) + mc.method.explicitTypeArgs.foreach { a => + val tpe = mc.typeSubst(a) // existence is checked in MethodCall constructor + w.putType(tpe) + } } override def parse(r: SigmaByteReader): Value[SType] = { @@ -24,7 +32,22 @@ case class PropertyCallSerializer(cons: (Value[SType], SMethod, IndexedSeq[Value val methodId = r.getByte() val obj = r.getValue() val method = SMethod.fromIds(typeId, methodId) - val specMethod = method.specializeFor(obj.tpe, SType.EmptySeq) - cons(obj, specMethod, Value.EmptySeq, EmptySubst) + + val (explicitTypeSubst: Map[STypeVar, SType], specMethod: SMethod) = if (method.hasExplicitTypeArgs) { + val nTypes = method.explicitTypeArgs.length + val res = safeNewArray[SType](nTypes) + cfor(0)(_ < nTypes, _ + 1) { i => + res(i) = r.getType() + } + val explicitTypes = ArraySeq.unsafeWrapArray(res) + val explicitTypeSubst = method.explicitTypeArgs.zip(explicitTypes).toMap + val specMethod = method.withConcreteTypes(explicitTypeSubst) + (explicitTypeSubst, specMethod) + } else { + val specMethod = method.specializeFor(obj.tpe, SType.EmptySeq) + (EmptySubst, specMethod) + } + + cons(obj, specMethod, Value.EmptySeq, explicitTypeSubst) } } 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 c1d1db40a2..b1c6f9de88 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/GraphBuilding.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/GraphBuilding.scala @@ -1178,6 +1178,9 @@ trait GraphBuilding extends Base with DefRewriting { IR: IRContext => val value = asRep[tT.WrappedType](argsV(0)) val cT = stypeToElem(typeSubst.apply(tT)).asInstanceOf[Elem[tT.WrappedType]] g.some(value)(cT) + case SGlobalMethods.noneMethod.name => + val cT = stypeToElem(typeSubst.apply(tT)).asInstanceOf[Elem[tT.WrappedType]] + g.none()(cT) case _ => throwError() } case (x: Ref[tNum], _: SNumericTypeMethods) => method.name match { diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/SigmaDslImpl.scala b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/SigmaDslImpl.scala index de4370da50..7e5de4bd3b 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/SigmaDslImpl.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/SigmaDslImpl.scala @@ -1974,22 +1974,22 @@ object SigmaDslBuilder extends EntityObject("SigmaDslBuilder") { override def fromBigEndianBytes[T](bytes: Ref[Coll[Byte]])(implicit cT: Elem[T]): Ref[T] = { asRep[T](mkMethodCall(self, SigmaDslBuilderClass.getMethod("fromBigEndianBytes", classOf[Sym], classOf[Elem[T]]), - Array[AnyRef](bytes, cT, Map(tT -> Evaluation.rtypeToSType(cT.sourceType))), - true, false, cT)) + Array[AnyRef](bytes, cT), + true, false, cT, Map(tT -> Evaluation.rtypeToSType(cT.sourceType)))) } override def some[T](value: Ref[T])(implicit cT: Elem[T]): Ref[WOption[T]] = { asRep[WOption[T]](mkMethodCall(self, SigmaDslBuilderClass.getMethod("some", classOf[Sym], classOf[Elem[T]]), - Array[AnyRef](value, cT, Map(tT -> Evaluation.rtypeToSType(cT.sourceType))), - true, false, element[WOption[T]])) + Array[AnyRef](value, cT), + true, false, element[WOption[T]], Map(tT -> Evaluation.rtypeToSType(cT.sourceType)))) } override def none[T]()(implicit cT: Elem[T]): Ref[WOption[T]] = { asRep[WOption[T]](mkMethodCall(self, SigmaDslBuilderClass.getMethod("none", classOf[Elem[T]]), - Array[AnyRef](cT, Map(tT -> Evaluation.rtypeToSType(cT.sourceType))), - true, false, element[WOption[T]])) + Array[AnyRef](cT), + true, false, element[WOption[T]], Map(tT -> Evaluation.rtypeToSType(cT.sourceType)))) } } diff --git a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala index 16817e08ae..1ae52d0971 100644 --- a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala @@ -989,7 +989,6 @@ class BasicOpsSpecification extends CompilerTestingCommons } } - // todo: failing, needs for Header (de)serialization support from https://github.com/ScorexFoundation/sigmastate-interpreter/pull/972 property("serialize - collection of collection of headers") { val td = new SigmaTestingData {} val h1 = td.TestData.h1 @@ -1755,4 +1754,48 @@ class BasicOpsSpecification extends CompilerTestingCommons } } + property("Global.some - computable value") { + val ext: Seq[VarBinding] = Seq( + (intVar1, IntConstant(0)) + ) + def someTest(): Assertion = { + test("some", env, ext, + """{ + | val i = getVar[Int](1) + | val xo = Global.some[Int](i.get) + | xo == i + |}""".stripMargin, + null + ) + } + + if (VersionContext.current.isV6SoftForkActivated) { + someTest() + } else { + an[Exception] should be thrownBy someTest() + } + } + + property("Global.none") { + val ext: Seq[VarBinding] = Seq( + (intVar1, IntConstant(0)) + ) + def someTest(): Assertion = { + test("some", env, ext, + """{ + | val xo = Global.some[Long](5L) + | val xn = Global.none[Long]() + | xn.isDefined == false && xn != xo + |}""".stripMargin, + null + ) + } + + if (VersionContext.current.isV6SoftForkActivated) { + someTest() + } else { + an[Exception] should be thrownBy someTest() + } + } + } From e5326307440970cc7aa5bbd8c2d839abeecb20e3 Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Tue, 8 Oct 2024 15:46:59 +0300 Subject: [PATCH 260/314] fixing ErgoTreeSpecification --- sc/shared/src/test/scala/sigmastate/ErgoTreeSpecification.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sc/shared/src/test/scala/sigmastate/ErgoTreeSpecification.scala b/sc/shared/src/test/scala/sigmastate/ErgoTreeSpecification.scala index b368a9da3d..9f8bc19d65 100644 --- a/sc/shared/src/test/scala/sigmastate/ErgoTreeSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/ErgoTreeSpecification.scala @@ -517,7 +517,7 @@ class ErgoTreeSpecification extends SigmaDslTesting with ContractsTestkit with C MInfo(1, groupGeneratorMethod), MInfo(2, xorMethod) ) ++ (if (isV6Activated) { // id = 4 reserved for deserializeTo method - Seq(MInfo(3, serializeMethod), MInfo(5, fromBigEndianBytesMethod)) // methods added in v6.0 + Seq(MInfo(3, serializeMethod), MInfo(5, fromBigEndianBytesMethod), MInfo(8, someMethod), MInfo(9, noneMethod)) // methods added in v6.0 } else { Seq.empty[MInfo] }), true) From 7452f5f59ade66a695852628c58bf84f034d888b Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Wed, 9 Oct 2024 14:26:13 +0300 Subject: [PATCH 261/314] JS reflection --- .../src/main/scala/sigma/reflection/ReflectionData.scala | 6 ++++++ .../main/scala/sigma/compiler/ir/GraphIRReflection.scala | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/core/shared/src/main/scala/sigma/reflection/ReflectionData.scala b/core/shared/src/main/scala/sigma/reflection/ReflectionData.scala index 9ad62356ca..16cbf62154 100644 --- a/core/shared/src/main/scala/sigma/reflection/ReflectionData.scala +++ b/core/shared/src/main/scala/sigma/reflection/ReflectionData.scala @@ -468,6 +468,12 @@ object ReflectionData { }, mkMethod(clazz, "fromBigEndianBytes", Array[Class[_]](cColl, classOf[RType[_]])) { (obj, args) => obj.asInstanceOf[SigmaDslBuilder].fromBigEndianBytes(args(0).asInstanceOf[Coll[Byte]])(args(1).asInstanceOf[RType[_]]) + }, + mkMethod(clazz, "some", Array[Class[_]](classOf[Object], classOf[RType[_]])) { (obj, args) => + obj.asInstanceOf[SigmaDslBuilder].some(args(0).asInstanceOf[Any])(args(1).asInstanceOf[RType[Any]]) + }, + mkMethod(clazz, "none", Array[Class[_]](classOf[RType[_]])) { (obj, args) => + obj.asInstanceOf[SigmaDslBuilder].none()(args(0).asInstanceOf[RType[_]]) } ) ) diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/GraphIRReflection.scala b/sc/shared/src/main/scala/sigma/compiler/ir/GraphIRReflection.scala index adea48af0a..4772ebd386 100644 --- a/sc/shared/src/main/scala/sigma/compiler/ir/GraphIRReflection.scala +++ b/sc/shared/src/main/scala/sigma/compiler/ir/GraphIRReflection.scala @@ -530,6 +530,12 @@ object GraphIRReflection { }, mkMethod(clazz, "fromBigEndianBytes", Array[Class[_]](classOf[Base#Ref[_]], classOf[TypeDescs#Elem[_]])) { (obj, args) => obj.asInstanceOf[ctx.SigmaDslBuilder].fromBigEndianBytes(args(0).asInstanceOf[ctx.Ref[ctx.Coll[Byte]]])(args(1).asInstanceOf[ctx.Elem[SType]]) + }, + mkMethod(clazz, "some", Array[Class[_]](classOf[Base#Ref[_]], classOf[TypeDescs#Elem[_]])) { (obj, args) => + obj.asInstanceOf[ctx.SigmaDslBuilder].some(args(0).asInstanceOf[ctx.Ref[Any]])(args(1).asInstanceOf[ctx.Elem[Any]]) + }, + mkMethod(clazz, "none", Array[Class[_]](classOf[TypeDescs#Elem[_]])) { (obj, args) => + obj.asInstanceOf[ctx.SigmaDslBuilder].none()(args(0).asInstanceOf[ctx.Elem[SType]]) } ) ) From 09ec5f11d21792c99adb903f485540eef43b652b Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Fri, 18 Oct 2024 13:48:50 +0300 Subject: [PATCH 262/314] ignoring bulletproof test, impoving comments --- core/shared/src/main/scala/sigma/ast/SType.scala | 7 +++++-- core/shared/src/main/scala/sigma/util/Extensions.scala | 1 - .../test/scala/sigmastate/utxo/BasicOpsSpecification.scala | 3 ++- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/core/shared/src/main/scala/sigma/ast/SType.scala b/core/shared/src/main/scala/sigma/ast/SType.scala index 7673c11dec..b69a988347 100644 --- a/core/shared/src/main/scala/sigma/ast/SType.scala +++ b/core/shared/src/main/scala/sigma/ast/SType.scala @@ -102,14 +102,15 @@ object SType { /** Immutable empty IndexedSeq, can be used to avoid repeated allocations. */ val EmptySeq: IndexedSeq[SType] = EmptyArray + // <= V5 types, see `allPredefTypes` scaladoc below private val v5PredefTypes = Array[SType]( SBoolean, SByte, SShort, SInt, SLong, SBigInt, SContext, SGlobal, SHeader, SPreHeader, SAvlTree, SGroupElement, SSigmaProp, SString, SBox, SUnit, SAny) + // V6 types, see `allPredefTypes` scaladoc below private val v6PredefTypes = v5PredefTypes ++ Array(SUnsignedBigInt) - /** 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] = { @@ -147,6 +148,8 @@ object SType { * (SByte, SShort, SInt, SLong, SBigInt) and the generic tNum type parameter is * specialized accordingly. * + * Also, SUnsignedBigInt type is added in v6.0. + * * This difference in behaviour is tested by `property("MethodCall on numerics")`. * * The regression tests in `property("MethodCall Codes")` should pass. @@ -487,7 +490,7 @@ case object SLong extends SPrimType with SEmbeddable with SNumericType with SMon } } -/** Type of 256-bit signed integer values. Implemented using [[java.math.BigInteger]]. */ +/** Type of 256-bit signed integer values. Implemented using [[java.math.BigInteger]]. */ case object SBigInt extends SPrimType with SEmbeddable with SNumericType with SMonoType { override type WrappedType = BigInt override val typeCode: TypeCode = 6: Byte diff --git a/core/shared/src/main/scala/sigma/util/Extensions.scala b/core/shared/src/main/scala/sigma/util/Extensions.scala index 149d61f6c2..5d1d9b7da8 100644 --- a/core/shared/src/main/scala/sigma/util/Extensions.scala +++ b/core/shared/src/main/scala/sigma/util/Extensions.scala @@ -218,7 +218,6 @@ object Extensions { } @inline final def toUnsignedBigIntValueExact: BigInteger = { - // todo: make the check soft-forkable if (x.compareTo(BigInteger.ZERO) >= 0 && x.bitLength() <= 256) { x } else { diff --git a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala index 07e5170af3..7a5f6ae668 100644 --- a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala @@ -463,7 +463,8 @@ class BasicOpsSpecification extends CompilerTestingCommons } } - property("Bulletproof verification for a range proof") { + // todo: finish the range proof verification script and test + ignore("Bulletproof verification for a range proof") { /* * Original range proof verifier code by Benedikt Bunz: * From 5cabedd6f73a3d0737a221919e51771a0c5653a2 Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Fri, 18 Oct 2024 14:42:40 +0300 Subject: [PATCH 263/314] equalsPairCollWithCollOverArray --- .../scala/sigma/data/CollsOverArrays.scala | 86 +++++++++++++------ .../ErgoLikeTransactionSpec.scala | 2 +- 2 files changed, 63 insertions(+), 25 deletions(-) diff --git a/core/shared/src/main/scala/sigma/data/CollsOverArrays.scala b/core/shared/src/main/scala/sigma/data/CollsOverArrays.scala index dc73253628..2d6a4a5cdf 100644 --- a/core/shared/src/main/scala/sigma/data/CollsOverArrays.scala +++ b/core/shared/src/main/scala/sigma/data/CollsOverArrays.scala @@ -1,6 +1,8 @@ package sigma.data import debox.{Buffer, cfor} +import sigma.Evaluation.stypeToRType +import sigma.data.CollOverArray.equalsPairCollWithCollOverArray import sigma.data.RType._ import sigma.util.{CollectionUtil, MaxArrayLength, safeConcatArrays_v5} import sigma.{Coll, CollBuilder, PairColl, VersionContext, requireSameLength} @@ -12,7 +14,9 @@ class CollOverArray[@specialized A](val toArray: Array[A], val builder: CollBuil s"Cannot create collection with size ${toArray.length} greater than $MaxArrayLength") override def tItem: RType[A] = tA + @inline def length: Int = toArray.length + @inline def apply(i: Int): A = toArray.apply(i) override def isEmpty: Boolean = length == 0 @@ -29,8 +33,11 @@ class CollOverArray[@specialized A](val toArray: Array[A], val builder: CollBuil } def foreach(f: A => Unit): Unit = toArray.foreach(f) + def exists(p: A => Boolean): Boolean = toArray.exists(p) + def forall(p: A => Boolean): Boolean = toArray.forall(p) + def filter(p: A => Boolean): Coll[A] = builder.fromArray(toArray.filter(p)) def foldLeft[B](zero: B, op: ((B, A)) => B): B = toArray.foldLeft(zero)((b, a) => op((b, a))) @@ -117,12 +124,14 @@ class CollOverArray[@specialized A](val toArray: Array[A], val builder: CollBuil override def unionSet(that: Coll[A]): Coll[A] = { val set = debox.Set.ofSize[A](this.length) val res = Buffer.ofSize[A](this.length) + @inline def addItemToSet(x: A) = { if (!set(x)) { set.add(x) res += x } } + def addToSet(arr: Array[A]) = { val limit = arr.length cfor(0)(_ < limit, _ + 1) { i => @@ -140,19 +149,41 @@ class CollOverArray[@specialized A](val toArray: Array[A], val builder: CollBuil override def equals(obj: scala.Any): Boolean = (this eq obj.asInstanceOf[AnyRef]) || (obj match { case obj: CollOverArray[_] if obj.tItem == this.tItem => java.util.Objects.deepEquals(obj.toArray, this.toArray) - case obj: PairColl[_, _] if obj.tItem == this.tItem => - if(VersionContext.current.isV6SoftForkActivated) { - java.util.Objects.deepEquals(obj.toArray, this.toArray) + case obj: PairColl[Any, Any] if obj.tItem == this.tItem => + if (VersionContext.current.isV6SoftForkActivated) { + equalsPairCollWithCollOverArray(obj, this.asInstanceOf[CollOverArray[Any]]) } else { false } case _ => false }) - override def hashCode() = CollectionUtil.deepHashCode(toArray) + override def hashCode(): Int = CollectionUtil.deepHashCode(toArray) } -private[sigma] class CollOverArrayBuilder extends CollBuilder { builder => +object CollOverArray { + + // comparing PairColl and CollOverArray instances + private[data] def equalsPairCollWithCollOverArray(pc: PairColl[Any, Any], coa: CollOverArray[Any]): Boolean = { + val ls = pc.ls + val rs = pc.rs + val ts = coa.toArray + if (ts.length == ls.length && ts.isInstanceOf[Array[(Any, Any)]]) { + val ta = ts.asInstanceOf[Array[(Any, Any)]] + var eq = true + cfor(0)(_ < ta.length && eq, _ + 1) { i => + eq = java.util.Objects.deepEquals(ta(i)._1, ls(i)) && java.util.Objects.deepEquals(ta(i)._2, rs(i)) + } + eq + } else { + false + } + } + +} + +private[sigma] class CollOverArrayBuilder extends CollBuilder { + builder => @inline override def pairColl[@specialized A, @specialized B](as: Coll[A], bs: Coll[B]): PairColl[A, B] = { if (VersionContext.current.isJitActivated) { @@ -176,12 +207,12 @@ private[sigma] class CollOverArrayBuilder extends CollBuilder { builder => } } - private def fromBoxedPairs[A, B](seq: Seq[(A, B)])(implicit tA: RType[A], tB: RType[B]): PairColl[A,B] = { + private def fromBoxedPairs[A, B](seq: Seq[(A, B)])(implicit tA: RType[A], tB: RType[B]): PairColl[A, B] = { val len = seq.length val resA = Array.ofDim[A](len)(tA.classTag) val resB = Array.ofDim[B](len)(tB.classTag) cfor(0)(_ < len, _ + 1) { i => - val item = seq.apply(i).asInstanceOf[(A,B)] + val item = seq.apply(i).asInstanceOf[(A, B)] resA(i) = item._1 resB(i) = item._2 } @@ -189,7 +220,7 @@ private[sigma] class CollOverArrayBuilder extends CollBuilder { builder => } override def fromItems[T](items: T*)(implicit cT: RType[T]): Coll[T] = cT match { - case pt: PairType[a,b] => + case pt: PairType[a, b] => val tA = pt.tFst val tB = pt.tSnd fromBoxedPairs(items)(tA, tB) @@ -198,16 +229,16 @@ private[sigma] class CollOverArrayBuilder extends CollBuilder { builder => } override def fromArray[@specialized T: RType](arr: Array[T]): Coll[T] = RType[T] match { - case pt: PairType[a,b] => + case pt: PairType[a, b] => val tA = pt.tFst val tB = pt.tSnd - fromBoxedPairs[a,b](arr.asInstanceOf[Array[(a,b)]])(tA, tB) + fromBoxedPairs[a, b](arr.asInstanceOf[Array[(a, b)]])(tA, tB) case _ => new CollOverArray(arr, builder) } override def replicate[@specialized T: RType](n: Int, v: T): Coll[T] = RType[T] match { - case pt: PairType[a,b] => + case pt: PairType[a, b] => val tA = pt.tFst val tB = pt.tSnd val tuple = v.asInstanceOf[(a, b)] @@ -216,8 +247,8 @@ private[sigma] class CollOverArrayBuilder extends CollBuilder { builder => fromArray(Array.fill(n)(v)) } - override def unzip[@specialized A, @specialized B](xs: Coll[(A,B)]): (Coll[A], Coll[B]) = xs match { - case pa: PairColl[_,_] => (pa.ls, pa.rs) + override def unzip[@specialized A, @specialized B](xs: Coll[(A, B)]): (Coll[A], Coll[B]) = xs match { + case pa: PairColl[_, _] => (pa.ls, pa.rs) case _ => val limit = xs.length implicit val tA = xs.tItem.tFst @@ -236,7 +267,7 @@ private[sigma] class CollOverArrayBuilder extends CollBuilder { builder => left.zip(right).map { case (l, r) => (l ^ r).toByte } override def emptyColl[T](implicit cT: RType[T]): Coll[T] = cT match { - case pt: PairType[a,b] => + case pt: PairType[a, b] => val ls = emptyColl(pt.tFst) val rs = emptyColl(pt.tSnd) pairColl(ls, rs).asInstanceOf[Coll[T]] @@ -245,14 +276,14 @@ private[sigma] class CollOverArrayBuilder extends CollBuilder { builder => } } -class PairOfCols[@specialized L, @specialized R](val ls: Coll[L], val rs: Coll[R]) extends PairColl[L,R] { +class PairOfCols[@specialized L, @specialized R](val ls: Coll[L], val rs: Coll[R]) extends PairColl[L, R] { override def equals(that: scala.Any): Boolean = (this eq that.asInstanceOf[AnyRef]) || (that match { - case that: PairColl[_,_] if that.tItem == this.tItem => + case that: PairColl[_, _] if that.tItem == this.tItem => ls == that.ls && rs == that.rs - case that: CollOverArray[_] if that.tItem == this.tItem => + case that: CollOverArray[Any] if that.tItem == this.tItem => if (VersionContext.current.isV6SoftForkActivated) { - java.util.Objects.deepEquals(that.toArray, this.toArray) + equalsPairCollWithCollOverArray(this.asInstanceOf[PairColl[Any, Any]], that) } else { false } @@ -260,7 +291,9 @@ class PairOfCols[@specialized L, @specialized R](val ls: Coll[L], val rs: Coll[R }) override def hashCode() = ls.hashCode() * 41 + rs.hashCode() + @inline implicit def tL: RType[L] = ls.tItem + @inline implicit def tR: RType[R] = rs.tItem override lazy val tItem: RType[(L, R)] = { @@ -268,8 +301,11 @@ class PairOfCols[@specialized L, @specialized R](val ls: Coll[L], val rs: Coll[R } override def builder: CollBuilder = ls.builder + override def toArray: Array[(L, R)] = ls.toArray.zip(rs.toArray) + @inline override def length: Int = if (ls.length <= rs.length) ls.length else rs.length + @inline override def apply(i: Int): (L, R) = (ls(i), rs(i)) override def isEmpty: Boolean = length == 0 @@ -317,7 +353,7 @@ class PairOfCols[@specialized L, @specialized R](val ls: Coll[L], val rs: Coll[R true } - override def filter(p: ((L, R)) => Boolean): Coll[(L,R)] = { + override def filter(p: ((L, R)) => Boolean): Coll[(L, R)] = { val len = ls.length val resL: Buffer[L] = Buffer.empty[L](ls.tItem.classTag) val resR: Buffer[R] = Buffer.empty[R](rs.tItem.classTag) @@ -346,9 +382,9 @@ class PairOfCols[@specialized L, @specialized R](val ls: Coll[L], val rs: Coll[R state } - override def slice(from: Int, until: Int): PairColl[L,R] = builder.pairColl(ls.slice(from, until), rs.slice(from, until)) + override def slice(from: Int, until: Int): PairColl[L, R] = builder.pairColl(ls.slice(from, until), rs.slice(from, until)) - def append(other: Coll[(L, R)]): Coll[(L,R)] = { + def append(other: Coll[(L, R)]): Coll[(L, R)] = { val arrs = builder.unzip(other) builder.pairColl(ls.append(arrs._1), rs.append(arrs._2)) } @@ -365,7 +401,7 @@ class PairOfCols[@specialized L, @specialized R](val ls: Coll[L], val rs: Coll[R } } - def zip[@specialized B](ys: Coll[B]): PairColl[(L,R), B] = builder.pairColl(this, ys) + def zip[@specialized B](ys: Coll[B]): PairColl[(L, R), B] = builder.pairColl(this, ys) def startsWith(ys: Coll[(L, R)]): Boolean = ys match { case yp: PairOfCols[L, R] => ls.startsWith(yp.ls) && rs.startsWith(yp.rs) @@ -421,18 +457,20 @@ class PairOfCols[@specialized L, @specialized R](val ls: Coll[L], val rs: Coll[R } override def unionSet(that: Coll[(L, R)]): Coll[(L, R)] = { - val set = new java.util.HashSet[(L,R)](32) + val set = new java.util.HashSet[(L, R)](32) implicit val ctL = ls.tItem.classTag implicit val ctR = rs.tItem.classTag val resL = Buffer.empty[L] val resR = Buffer.empty[R] - def addToSet(item: (L,R)) = { + + def addToSet(item: (L, R)) = { if (!set.contains(item)) { set.add(item) resL += item._1 resR += item._2 } } + var i = 0 val thisLen = math.min(ls.length, rs.length) while (i < thisLen) { diff --git a/sc/shared/src/test/scala/org/ergoplatform/ErgoLikeTransactionSpec.scala b/sc/shared/src/test/scala/org/ergoplatform/ErgoLikeTransactionSpec.scala index 3fc9c7fd3d..4b3aa2eab5 100644 --- a/sc/shared/src/test/scala/org/ergoplatform/ErgoLikeTransactionSpec.scala +++ b/sc/shared/src/test/scala/org/ergoplatform/ErgoLikeTransactionSpec.scala @@ -23,7 +23,7 @@ import sigma.ast.SCollection.SByteArray import sigmastate.CrossVersionProps import sigmastate.utils.Helpers.EitherOps // required for Scala 2.11 -class ErgoLikeTransactionSpec extends SigmaDslTesting with CrossVersionProps with JsonCodecs { + class ErgoLikeTransactionSpec extends SigmaDslTesting with CrossVersionProps with JsonCodecs { property("ErgoBox test vectors") { val token1 = "6e789ab7b2fffff12280a6cd01557f6fb22b7f80ff7aff8e1f7f15973d7f0001" From 9036aec8769a1dd724231d258d11eadf005cb400 Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Mon, 21 Oct 2024 23:04:16 +0300 Subject: [PATCH 264/314] improving tests in BasicOpsSpecification, type test for getVarFromInput --- .../src/main/scala/sigma/SigmaDsl.scala | 4 +- .../main/scala/sigmastate/eval/CContext.scala | 4 +- .../sigmastate/lang/SigmaTyperTest.scala | 6 + .../utxo/BasicOpsSpecification.scala | 221 ++++++++++-------- 4 files changed, 134 insertions(+), 101 deletions(-) diff --git a/core/shared/src/main/scala/sigma/SigmaDsl.scala b/core/shared/src/main/scala/sigma/SigmaDsl.scala index 422e4b7969..16331febfd 100644 --- a/core/shared/src/main/scala/sigma/SigmaDsl.scala +++ b/core/shared/src/main/scala/sigma/SigmaDsl.scala @@ -592,13 +592,13 @@ trait Context { /** * A variant of `getVar` to extract a context variable by id and type from any input * - * @param inputId - input index + * @param inputIndex - input index * @param id - context variable id * @tparam T - expected type of the variable * @return Some(value) if the variable is defined in the context AND has the given type. * None otherwise */ - def getVarFromInput[T](inputId: Short, id: Byte)(implicit cT: RType[T]): Option[T] + def getVarFromInput[T](inputIndex: Short, id: Byte)(implicit cT: RType[T]): Option[T] def vars: Coll[AnyValue] diff --git a/interpreter/shared/src/main/scala/sigmastate/eval/CContext.scala b/interpreter/shared/src/main/scala/sigmastate/eval/CContext.scala index bed0c4b013..b0e5b01186 100644 --- a/interpreter/shared/src/main/scala/sigmastate/eval/CContext.scala +++ b/interpreter/shared/src/main/scala/sigmastate/eval/CContext.scala @@ -73,8 +73,8 @@ case class CContext( } else None } - override def getVarFromInput[T](inputId: Short, id: Byte)(implicit tT: RType[T]): Option[T] = { - spendingTransaction.inputs.lift(inputId).flatMap(_.extension.get(id)) match { + override def getVarFromInput[T](inputIndex: Short, id: Byte)(implicit tT: RType[T]): Option[T] = { + spendingTransaction.inputs.lift(inputIndex).flatMap(_.extension.get(id)) match { case Some(v) if stypeToRType[SType](v.tpe) == tT => Some(v.value.asInstanceOf[T]) case _ => None diff --git a/sc/shared/src/test/scala/sigmastate/lang/SigmaTyperTest.scala b/sc/shared/src/test/scala/sigmastate/lang/SigmaTyperTest.scala index 5bfb72cd4f..c86cb11afc 100644 --- a/sc/shared/src/test/scala/sigmastate/lang/SigmaTyperTest.scala +++ b/sc/shared/src/test/scala/sigmastate/lang/SigmaTyperTest.scala @@ -687,6 +687,12 @@ class SigmaTyperTest extends AnyPropSpec typecheck(env, "CONTEXT.getVar[Int](1.toByte).get") shouldBe SInt } + property("SContext.getVarFromInput") { + runWithVersion(VersionContext.V6SoftForkVersion) { + typecheck(env, "CONTEXT.getVarFromInput[Int](1.toShort, 1.toByte).get") shouldBe SInt + } + } + property("SAvlTree.digest") { typecheck(env, "getVar[AvlTree](1).get.digest") shouldBe SByteArray } diff --git a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala index ea9539a65a..0eba3c9878 100644 --- a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala @@ -7,7 +7,7 @@ import scorex.util.encode.Base16 import scorex.utils.Ints import sigma.Extensions.ArrayOps import sigma.{SigmaTestingData, VersionContext} -import sigma.VersionContext.V6SoftForkVersion +import sigma.VersionContext.{V6SoftForkVersion, withVersions} import sigma.ast.SCollection.SByteArray import sigma.ast.SType.AnyOps import sigma.data.{AvlTreeData, CAnyValue, CSigmaDslBuilder} @@ -19,7 +19,7 @@ import sigmastate._ import sigmastate.helpers.TestingHelpers._ import sigmastate.helpers.{CompilerTestingCommons, ContextEnrichingTestProvingInterpreter, ErgoLikeContextTesting, ErgoLikeTestInterpreter} import sigma.interpreter.ContextExtension.VarBinding -import sigmastate.interpreter.CErgoTreeEvaluator.DefaultEvalSettings +import sigmastate.interpreter.CErgoTreeEvaluator.{DefaultEvalSettings, currentEvaluator} import sigmastate.interpreter.Interpreter._ import sigma.ast.Apply import sigma.eval.EvalSettings @@ -92,8 +92,11 @@ class BasicOpsSpecification extends CompilerTestingCommons // is not supported by ErgoScript Compiler) // In such cases we use expected property as the property to test propExp.asSigmaProp - } else - compile(env, script).asBoolValue.toSigmaProp + } else { + withVersions(VersionContext.MaxSupportedScriptVersion, ergoTreeVersionInTests) { + compile(env, script).asBoolValue.toSigmaProp + } + } if (propExp != null) prop shouldBe propExp @@ -145,20 +148,6 @@ class BasicOpsSpecification extends CompilerTestingCommons flexVerifier.verify(verifyEnv, tree, ctxExt, pr.proof, fakeMessage).get._1 shouldBe true } - property("Context.getVar") { - def varTest() = { - test("GetVar1", env, ext, - "{ CONTEXT.getVar[Int](intVar2.toByte).get == 2 }", - null - ) - } - - if(VersionContext.current.isV6SoftForkActivated) { - varTest() - } else { - an[Exception] should be thrownBy(varTest()) - } - } property("getVarFromInput") { def getVarTest(): Assertion = { @@ -174,7 +163,7 @@ class BasicOpsSpecification extends CompilerTestingCommons if (VersionContext.current.isV6SoftForkActivated) { getVarTest() } else { - an[Exception] should be thrownBy getVarTest() + an[sigma.validation.ValidationException] should be thrownBy getVarTest() } } @@ -195,7 +184,7 @@ class BasicOpsSpecification extends CompilerTestingCommons if (VersionContext.current.isV6SoftForkActivated) { getVarTest() } else { - an[Exception] should be thrownBy getVarTest() + an[sigma.validation.ValidationException] should be thrownBy getVarTest() } } @@ -213,13 +202,17 @@ class BasicOpsSpecification extends CompilerTestingCommons if (VersionContext.current.isV6SoftForkActivated) { getVarTest() } else { - an[Exception] should be thrownBy getVarTest() + an[sigma.validation.ValidationException] should be thrownBy getVarTest() } } + property("Byte.toBits") { - def toBitsTest() = test("Byte.toBits", env, ext, + val customExt = Map( + 1.toByte -> ByteConstant(1) + ).toSeq + def toBitsTest() = test("Byte.toBits", env, customExt, """{ - | val b = 1.toByte + | val b = getVar[Byte](1).get | b.toBits == Coll(false, false, false, false, false, false, false, true) |}""".stripMargin, null @@ -228,14 +221,17 @@ class BasicOpsSpecification extends CompilerTestingCommons if (VersionContext.current.isV6SoftForkActivated) { toBitsTest() } else { - an[Exception] shouldBe thrownBy(toBitsTest()) + an[sigma.validation.ValidationException] shouldBe thrownBy(toBitsTest()) } } property("Long.toBits") { - def toBitsTest() = test("Long.toBits", env, ext, + val customExt = Map( + 1.toByte -> LongConstant(1) + ).toSeq + def toBitsTest() = test("Long.toBits", env, customExt, """{ - | val b = 1L + | val b = getVar[Long](1).get | val ba = b.toBits | | // only rightmost bit is set @@ -247,7 +243,7 @@ class BasicOpsSpecification extends CompilerTestingCommons if (VersionContext.current.isV6SoftForkActivated) { toBitsTest() } else { - an[Exception] shouldBe thrownBy(toBitsTest()) + an[sigma.validation.ValidationException] shouldBe thrownBy(toBitsTest()) } } @@ -264,7 +260,7 @@ class BasicOpsSpecification extends CompilerTestingCommons if (VersionContext.current.isV6SoftForkActivated) { toBitsTest() } else { - an[Exception] shouldBe thrownBy(toBitsTest()) + an[sigma.validation.ValidationException] shouldBe thrownBy(toBitsTest()) } } @@ -281,10 +277,11 @@ class BasicOpsSpecification extends CompilerTestingCommons if (VersionContext.current.isV6SoftForkActivated) { bitwiseInverseTest() } else { - an[Exception] shouldBe thrownBy(bitwiseInverseTest()) + an[sigma.validation.ValidationException] shouldBe thrownBy(bitwiseInverseTest()) } } + property("Byte.bitwiseInverse") { def bitwiseInverseTest(): Assertion = test("Byte.bitwiseInverse", env, ext, s"""{ @@ -297,14 +294,17 @@ class BasicOpsSpecification extends CompilerTestingCommons if (VersionContext.current.isV6SoftForkActivated) { bitwiseInverseTest() } else { - an[Exception] shouldBe thrownBy(bitwiseInverseTest()) + an[sigma.validation.ValidationException] shouldBe thrownBy(bitwiseInverseTest()) } } property("Long.bitwiseInverse") { - def bitwiseInverseTest(): Assertion = test("Long.bitwiseInverse", env, ext, + val customExt = Map( + 1.toByte -> LongConstant(9223372036854775807L) + ).toSeq + def bitwiseInverseTest(): Assertion = test("Long.bitwiseInverse", env, customExt, s"""{ - | val l = 9223372036854775807L + | val l = getVar[Long](1).get | val lb = l.bitwiseInverse | lb.bitwiseInverse == l |}""".stripMargin, @@ -314,14 +314,18 @@ class BasicOpsSpecification extends CompilerTestingCommons if (VersionContext.current.isV6SoftForkActivated) { bitwiseInverseTest() } else { - an[Exception] shouldBe thrownBy(bitwiseInverseTest()) + an[sigma.validation.ValidationException] shouldBe thrownBy(bitwiseInverseTest()) } } + property("Byte.bitwiseOr") { - def bitwiseOrTest(): Assertion = test("Byte.bitwiseOrTest", env, ext, + val customExt = Map( + 1.toByte -> ByteConstant(127) + ).toSeq + def bitwiseOrTest(): Assertion = test("Byte.bitwiseOrTest", env, customExt, s"""{ - | val x = 127.toByte + | val x = getVar[Byte](1).get | val y = (-128).toByte | x.bitwiseOr(y) == -1 |}""".stripMargin, @@ -331,7 +335,7 @@ class BasicOpsSpecification extends CompilerTestingCommons if (VersionContext.current.isV6SoftForkActivated) { bitwiseOrTest() } else { - an[Exception] shouldBe thrownBy(bitwiseOrTest()) + an[sigma.validation.ValidationException] shouldBe thrownBy(bitwiseOrTest()) } } @@ -347,7 +351,7 @@ class BasicOpsSpecification extends CompilerTestingCommons if (VersionContext.current.isV6SoftForkActivated) { bitwiseOrTest() } else { - an[Exception] shouldBe thrownBy(bitwiseOrTest()) + an[sigma.validation.ValidationException] shouldBe thrownBy(bitwiseOrTest()) } } @@ -364,14 +368,17 @@ class BasicOpsSpecification extends CompilerTestingCommons if (VersionContext.current.isV6SoftForkActivated) { bitwiseAndTest() } else { - an[Exception] shouldBe thrownBy(bitwiseAndTest()) + an[sigma.validation.ValidationException] shouldBe thrownBy(bitwiseAndTest()) } } property("Short.bitwiseAnd") { - def bitwiseAndTest(): Assertion = test("Short.bitwiseAnd", env, ext, + val customExt = Map( + 1.toByte -> ShortConstant(32767) + ).toSeq + def bitwiseAndTest(): Assertion = test("Short.bitwiseAnd", env, customExt, s"""{ - | val x = (32767).toShort + | val x = getVar[Short](1).get | val y = (-32768).toShort | x.bitwiseAnd(y) == 0 |}""".stripMargin, @@ -381,14 +388,17 @@ class BasicOpsSpecification extends CompilerTestingCommons if (VersionContext.current.isV6SoftForkActivated) { bitwiseAndTest() } else { - an[Exception] shouldBe thrownBy(bitwiseAndTest()) + an[sigma.validation.ValidationException] shouldBe thrownBy(bitwiseAndTest()) } } property("Short.bitwiseXor") { - def bitwiseXorTest(): Assertion = test("Short.bitwiseXor", env, ext, + val customExt = Map( + 1.toByte -> ShortConstant(32767) + ).toSeq + def bitwiseXorTest(): Assertion = test("Short.bitwiseXor", env, customExt, s"""{ - | val x = (32767).toShort + | val x = getVar[Short](1).get | val y = (-32768).toShort | x.bitwiseXor(y) == -1 |}""".stripMargin, @@ -398,7 +408,7 @@ class BasicOpsSpecification extends CompilerTestingCommons if (VersionContext.current.isV6SoftForkActivated) { bitwiseXorTest() } else { - an[Exception] shouldBe thrownBy(bitwiseXorTest()) + an[sigma.validation.ValidationException] shouldBe thrownBy(bitwiseXorTest()) } } @@ -415,7 +425,7 @@ class BasicOpsSpecification extends CompilerTestingCommons if (VersionContext.current.isV6SoftForkActivated) { shiftLeftTest() } else { - an[Exception] shouldBe thrownBy(shiftLeftTest()) + an[sigma.validation.ValidationException] shouldBe thrownBy(shiftLeftTest()) } } @@ -432,7 +442,7 @@ class BasicOpsSpecification extends CompilerTestingCommons if (VersionContext.current.isV6SoftForkActivated) { an[IllegalArgumentException] shouldBe thrownBy(shiftLeftTest()) } else { - an[Exception] shouldBe thrownBy(shiftLeftTest()) + an[sigma.validation.ValidationException] shouldBe thrownBy(shiftLeftTest()) } } @@ -449,7 +459,7 @@ class BasicOpsSpecification extends CompilerTestingCommons if (VersionContext.current.isV6SoftForkActivated) { shiftLeftTest() } else { - an[Exception] shouldBe thrownBy(shiftLeftTest()) + an[sigma.validation.ValidationException] shouldBe thrownBy(shiftLeftTest()) } } @@ -466,7 +476,7 @@ class BasicOpsSpecification extends CompilerTestingCommons if (VersionContext.current.isV6SoftForkActivated) { shiftLeftTest() } else { - an[Exception] shouldBe thrownBy(shiftLeftTest()) + an[sigma.validation.ValidationException] shouldBe thrownBy(shiftLeftTest()) } } @@ -482,7 +492,7 @@ class BasicOpsSpecification extends CompilerTestingCommons if (VersionContext.current.isV6SoftForkActivated) { an[ArithmeticException] shouldBe thrownBy(shiftLeftTest()) } else { - an[Exception] shouldBe thrownBy(shiftLeftTest()) + an[sigma.validation.ValidationException] shouldBe thrownBy(shiftLeftTest()) } } @@ -499,7 +509,7 @@ class BasicOpsSpecification extends CompilerTestingCommons if (VersionContext.current.isV6SoftForkActivated) { shiftRightTest() } else { - an[Exception] shouldBe thrownBy(shiftRightTest()) + an[sigma.validation.ValidationException] shouldBe thrownBy(shiftRightTest()) } } @@ -516,7 +526,7 @@ class BasicOpsSpecification extends CompilerTestingCommons if (VersionContext.current.isV6SoftForkActivated) { shiftRightTest() } else { - an[Exception] shouldBe thrownBy(shiftRightTest()) + an[sigma.validation.ValidationException] shouldBe thrownBy(shiftRightTest()) } } @@ -533,10 +543,11 @@ class BasicOpsSpecification extends CompilerTestingCommons if (VersionContext.current.isV6SoftForkActivated) { an[IllegalArgumentException] shouldBe thrownBy(shiftRightTest()) } else { - an[Exception] shouldBe thrownBy(shiftRightTest()) + an[sigma.validation.ValidationException] shouldBe thrownBy(shiftRightTest()) } } + property("Long.shiftRight - neg") { def shiftRightTest(): Assertion = test("Long.shiftRight", env, ext, s"""{ @@ -550,7 +561,7 @@ class BasicOpsSpecification extends CompilerTestingCommons if (VersionContext.current.isV6SoftForkActivated) { shiftRightTest() } else { - an[Exception] shouldBe thrownBy(shiftRightTest()) + an[sigma.validation.ValidationException] shouldBe thrownBy(shiftRightTest()) } } @@ -567,7 +578,7 @@ class BasicOpsSpecification extends CompilerTestingCommons if (VersionContext.current.isV6SoftForkActivated) { an[IllegalArgumentException] shouldBe thrownBy(shiftRightTest()) } else { - an[Exception] shouldBe thrownBy(shiftRightTest()) + an[sigma.validation.ValidationException] shouldBe thrownBy(shiftRightTest()) } } @@ -585,7 +596,7 @@ class BasicOpsSpecification extends CompilerTestingCommons if (VersionContext.current.isV6SoftForkActivated) { shiftRightTest() } else { - an[Exception] shouldBe thrownBy(shiftRightTest()) + an[sigma.validation.ValidationException] shouldBe thrownBy(shiftRightTest()) } } @@ -603,7 +614,7 @@ class BasicOpsSpecification extends CompilerTestingCommons if (VersionContext.current.isV6SoftForkActivated) { an[IllegalArgumentException] shouldBe thrownBy(shiftRightTest()) } else { - an[Exception] shouldBe thrownBy(shiftRightTest()) + an[sigma.validation.ValidationException] shouldBe thrownBy(shiftRightTest()) } } @@ -621,7 +632,7 @@ class BasicOpsSpecification extends CompilerTestingCommons if (VersionContext.current.isV6SoftForkActivated) { getVarTest() } else { - an[Exception] should be thrownBy getVarTest() + an[sigma.validation.ValidationException] should be thrownBy getVarTest() } } @@ -642,7 +653,7 @@ class BasicOpsSpecification extends CompilerTestingCommons if(VersionContext.current.isV6SoftForkActivated) { reverseTest() } else { - an[Exception] shouldBe thrownBy(reverseTest()) + an[sigma.validation.ValidationException] shouldBe thrownBy(reverseTest()) } } @@ -663,7 +674,7 @@ class BasicOpsSpecification extends CompilerTestingCommons if(VersionContext.current.isV6SoftForkActivated) { reverseTest() } else { - an[Exception] shouldBe thrownBy(reverseTest()) + an[sigma.validation.ValidationException] shouldBe thrownBy(reverseTest()) } } @@ -687,7 +698,7 @@ class BasicOpsSpecification extends CompilerTestingCommons if(VersionContext.current.isV6SoftForkActivated) { reverseTest() } else { - an[Exception] shouldBe thrownBy(reverseTest()) + an[sigma.validation.ValidationException] shouldBe thrownBy(reverseTest()) } } @@ -711,7 +722,7 @@ class BasicOpsSpecification extends CompilerTestingCommons if(VersionContext.current.isV6SoftForkActivated) { reverseTest() } else { - an[Exception] shouldBe thrownBy(reverseTest()) + an[sigma.validation.ValidationException] shouldBe thrownBy(reverseTest()) } } @@ -735,7 +746,7 @@ class BasicOpsSpecification extends CompilerTestingCommons if(VersionContext.current.isV6SoftForkActivated) { reverseTest() } else { - an[Exception] shouldBe thrownBy(reverseTest()) + an[sigma.validation.ValidationException] shouldBe thrownBy(reverseTest()) } } @@ -759,7 +770,7 @@ class BasicOpsSpecification extends CompilerTestingCommons if(VersionContext.current.isV6SoftForkActivated) { reverseTest() } else { - an[Exception] shouldBe thrownBy(reverseTest()) + an[sigma.validation.ValidationException] shouldBe thrownBy(reverseTest()) } } @@ -777,7 +788,7 @@ class BasicOpsSpecification extends CompilerTestingCommons if(VersionContext.current.isV6SoftForkActivated) { getTest() } else { - an[Exception] shouldBe thrownBy(getTest()) + an[sigma.validation.ValidationException] shouldBe thrownBy(getTest()) } } @@ -793,7 +804,7 @@ class BasicOpsSpecification extends CompilerTestingCommons if(VersionContext.current.isV6SoftForkActivated) { fromTest() } else { - an[Exception] should be thrownBy(fromTest()) + an[sigma.validation.ValidationException] should be thrownBy(fromTest()) } } @@ -809,7 +820,7 @@ class BasicOpsSpecification extends CompilerTestingCommons if(VersionContext.current.isV6SoftForkActivated) { fromTest() } else { - an[Exception] should be thrownBy(fromTest()) + an[sigma.validation.ValidationException] should be thrownBy(fromTest()) } } @@ -825,7 +836,7 @@ class BasicOpsSpecification extends CompilerTestingCommons if(VersionContext.current.isV6SoftForkActivated) { fromTest() } else { - an[Exception] should be thrownBy(fromTest()) + an[sigma.validation.ValidationException] should be thrownBy(fromTest()) } } @@ -842,14 +853,17 @@ class BasicOpsSpecification extends CompilerTestingCommons if(VersionContext.current.isV6SoftForkActivated) { fromTest() } else { - an[Exception] should be thrownBy(fromTest()) + an[sigma.validation.ValidationException] should be thrownBy(fromTest()) } } property("Global.fromBigEndianBytes - Long.toBytes") { - def fromTest() = test("fromBigEndianBytes - long", env, ext, + val customExt = Map( + 1.toByte -> LongConstant(1088800L) + ).toSeq + def fromTest() = test("fromBigEndianBytes - long", env, customExt, s"""{ - | val l = 1088800L + | val l = getVar[Long](1).get | val ba = l.toBytes | Global.fromBigEndianBytes[Long](ba) == l |} @@ -859,7 +873,7 @@ class BasicOpsSpecification extends CompilerTestingCommons if(VersionContext.current.isV6SoftForkActivated) { fromTest() } else { - an[Exception] should be thrownBy(fromTest()) + an[sigma.validation.ValidationException] should be thrownBy(fromTest()) } } @@ -876,14 +890,17 @@ class BasicOpsSpecification extends CompilerTestingCommons if(VersionContext.current.isV6SoftForkActivated) { fromTest() } else { - an[Exception] should be thrownBy(fromTest()) + an[sigma.validation.ValidationException] should be thrownBy(fromTest()) } } property("Int.toBytes") { - def toBytesTest() = test("Int.toBytes", env, ext, + val customExt = Map( + 1.toByte -> IntConstant(1) + ).toSeq + def toBytesTest() = test("Int.toBytes", env, customExt, """{ - | val l = 1 + | val l = getVar[Int](1).get | l.toBytes == Coll(0.toByte, 0.toByte, 0.toByte, 1.toByte) | }""".stripMargin, null @@ -892,14 +909,17 @@ class BasicOpsSpecification extends CompilerTestingCommons if (VersionContext.current.isV6SoftForkActivated) { toBytesTest() } else { - an[Exception] shouldBe thrownBy(toBytesTest()) + an[sigma.validation.ValidationException] shouldBe thrownBy(toBytesTest()) } } property("Int.toBits") { - def toBytesTest() = test("Int.toBytes", env, ext, + val customExt = Map( + 1.toByte -> IntConstant(1477959696) + ).toSeq + def toBytesTest() = test("Int.toBytes", env, customExt, """{ - | val l = 1477959696 + | val l = getVar[Int](1).get | l.toBits == Coll(false, true, false, true, true, false, false, false, false, false, false, true, false, true, true ,true, true, true, true, false, false, false, false, false, false, false, false, true, false, false, false, false) | }""".stripMargin, null @@ -908,14 +928,17 @@ class BasicOpsSpecification extends CompilerTestingCommons if (VersionContext.current.isV6SoftForkActivated) { toBytesTest() } else { - an[Exception] shouldBe thrownBy(toBytesTest()) + an[sigma.validation.ValidationException] shouldBe thrownBy(toBytesTest()) } } property("Byte.toBytes") { - def toBytesTest() = test("Byte.toBytes", env, ext, + val customExt = Map( + 1.toByte -> ByteConstant(10) + ).toSeq + def toBytesTest() = test("Byte.toBytes", env, customExt, """{ - | val l = 10.toByte + | val l = getVar[Byte](1).get | l.toBytes == Coll(10.toByte) | }""".stripMargin, null @@ -924,7 +947,7 @@ class BasicOpsSpecification extends CompilerTestingCommons if (VersionContext.current.isV6SoftForkActivated) { toBytesTest() } else { - an[Exception] shouldBe thrownBy(toBytesTest()) + an[sigma.validation.ValidationException] shouldBe thrownBy(toBytesTest()) } } @@ -941,7 +964,7 @@ class BasicOpsSpecification extends CompilerTestingCommons if (VersionContext.current.isV6SoftForkActivated) { toBytesTest() } else { - an[Exception] shouldBe thrownBy(toBytesTest()) + an[sigma.validation.ValidationException] shouldBe thrownBy(toBytesTest()) } } @@ -956,7 +979,7 @@ class BasicOpsSpecification extends CompilerTestingCommons ) if (activatedVersionInTests < V6SoftForkVersion) { - an [sigma.exceptions.TyperException] should be thrownBy deserTest() + an [sigma.validation.ValidationException] should be thrownBy deserTest() } else { deserTest() } @@ -973,7 +996,7 @@ class BasicOpsSpecification extends CompilerTestingCommons ) if (activatedVersionInTests < V6SoftForkVersion) { - an [sigma.exceptions.TyperException] should be thrownBy deserTest() + an [sigma.validation.ValidationException] should be thrownBy deserTest() } else { deserTest() } @@ -990,7 +1013,7 @@ class BasicOpsSpecification extends CompilerTestingCommons ) if (activatedVersionInTests < V6SoftForkVersion) { - an [sigma.exceptions.TyperException] should be thrownBy deserTest() + an [sigma.validation.ValidationException] should be thrownBy deserTest() } else { deserTest() } @@ -1009,7 +1032,7 @@ class BasicOpsSpecification extends CompilerTestingCommons ) if (activatedVersionInTests < V6SoftForkVersion) { - an [sigma.exceptions.TyperException] should be thrownBy deserTest() + an [sigma.validation.ValidationException] should be thrownBy deserTest() } else { deserTest() } @@ -1030,7 +1053,7 @@ class BasicOpsSpecification extends CompilerTestingCommons ) if (activatedVersionInTests < V6SoftForkVersion) { - an [Exception] should be thrownBy deserTest() + an [sigma.validation.ValidationException] should be thrownBy deserTest() } else { deserTest() } @@ -1051,7 +1074,7 @@ class BasicOpsSpecification extends CompilerTestingCommons ) if (activatedVersionInTests < V6SoftForkVersion) { - an [Exception] should be thrownBy deserTest() + an [sigma.validation.ValidationException] should be thrownBy deserTest() } else { deserTest() } @@ -1075,7 +1098,7 @@ class BasicOpsSpecification extends CompilerTestingCommons ) if (activatedVersionInTests < V6SoftForkVersion) { - an [sigma.exceptions.TyperException] should be thrownBy deserTest() + an [sigma.validation.ValidationException] should be thrownBy deserTest() } else { deserTest() } @@ -1100,7 +1123,7 @@ class BasicOpsSpecification extends CompilerTestingCommons ) if (activatedVersionInTests < V6SoftForkVersion) { - an[Exception] should be thrownBy deserTest() + an[sigma.validation.ValidationException] should be thrownBy deserTest() } else { deserTest() } @@ -1122,7 +1145,7 @@ class BasicOpsSpecification extends CompilerTestingCommons ) if (activatedVersionInTests < V6SoftForkVersion) { - an[Exception] should be thrownBy deserTest() + an[sigma.validation.ValidationException] should be thrownBy deserTest() } else { // we have wrapped CostLimitException here an[Exception] should be thrownBy deserTest() @@ -1162,7 +1185,7 @@ class BasicOpsSpecification extends CompilerTestingCommons if(VersionContext.current.isV6SoftForkActivated) { optTest() } else { - an[Exception] shouldBe thrownBy(optTest()) + assertExceptionThrown(optTest(), _.isInstanceOf[NoSuchElementException]) } } @@ -1485,7 +1508,7 @@ class BasicOpsSpecification extends CompilerTestingCommons if(VersionContext.current.isV6SoftForkActivated) { holTest() } else { - an[Exception] shouldBe thrownBy(holTest()) + an[sigma.validation.ValidationException] shouldBe thrownBy(holTest()) } } @@ -1799,11 +1822,15 @@ class BasicOpsSpecification extends CompilerTestingCommons } property("Box.getReg") { + val customExt = Map( + 1.toByte -> IntConstant(0) + ).toSeq def getRegTest(): Assertion = { - test("Box.getReg", env, ext, + test("Box.getReg", env, customExt, """{ + | val idx = getVar[Int](1).get | val x = SELF - | x.getReg[Long](0).get == SELF.value && + | x.getReg[Long](idx).get == SELF.value && | x.getReg[Coll[(Coll[Byte], Long)]](2).get == SELF.tokens && | x.getReg[Int](9).isEmpty |}""".stripMargin, @@ -1814,7 +1841,7 @@ class BasicOpsSpecification extends CompilerTestingCommons if (VersionContext.current.isV6SoftForkActivated) { getRegTest() } else { - an[Exception] should be thrownBy getRegTest() + an[sigma.exceptions.ConstraintFailed] should be thrownBy getRegTest() } } @@ -1835,7 +1862,7 @@ class BasicOpsSpecification extends CompilerTestingCommons if (VersionContext.current.isV6SoftForkActivated) { getRegTest() } else { - an[Exception] should be thrownBy getRegTest() + an[java.nio.BufferUnderflowException] should be thrownBy getRegTest() } } From 8ae51e45a58bdd7d611f7a7692c6b1883fdb7ac4 Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Mon, 21 Oct 2024 23:15:19 +0300 Subject: [PATCH 265/314] split in LSV6 --- .../scala/sigma/LanguageSpecificationV6.scala | 177 +++++++++--------- 1 file changed, 90 insertions(+), 87 deletions(-) diff --git a/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala b/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala index 34b156fc79..15ce673332 100644 --- a/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala +++ b/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala @@ -1530,104 +1530,104 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite => ) } - property("Context.getVar and getVarFromInput") { - - def contextData() = { - val input = CBox( - new ErgoBox( - 80946L, - new ErgoTree( - HeaderType @@ 16.toByte, - Vector( - SigmaPropConstant( - CSigmaProp( - ProveDHTuple( - Helpers.decodeECPoint("03c046fccb95549910767d0543f5e8ce41d66ae6a8720a46f4049cac3b3d26dafb"), - Helpers.decodeECPoint("023479c9c3b86a0d3c8be3db0a2d186788e9af1db76d55f3dad127d15185d83d03"), - Helpers.decodeECPoint("03d7898641cb6653585a8e1dabfa7f665e61e0498963e329e6e3744bd764db2d72"), - Helpers.decodeECPoint("037ae057d89ec0b46ff8e9ff4c37e85c12acddb611c3f636421bef1542c11b0441") - ) + private def contextData() = { + val input = CBox( + new ErgoBox( + 80946L, + new ErgoTree( + HeaderType @@ 16.toByte, + Vector( + SigmaPropConstant( + CSigmaProp( + ProveDHTuple( + Helpers.decodeECPoint("03c046fccb95549910767d0543f5e8ce41d66ae6a8720a46f4049cac3b3d26dafb"), + Helpers.decodeECPoint("023479c9c3b86a0d3c8be3db0a2d186788e9af1db76d55f3dad127d15185d83d03"), + Helpers.decodeECPoint("03d7898641cb6653585a8e1dabfa7f665e61e0498963e329e6e3744bd764db2d72"), + Helpers.decodeECPoint("037ae057d89ec0b46ff8e9ff4c37e85c12acddb611c3f636421bef1542c11b0441") ) ) - ), - Right(ConstantPlaceholder(0, SSigmaProp)) - ), - Coll(), - Map( - ErgoBox.R4 -> ByteArrayConstant(Helpers.decodeBytes("34")), - ErgoBox.R5 -> TrueLeaf + ) ), - ModifierId @@ ("0000bfe96a7c0001e7a5ee00aafb80ff057fbe7f8c6680e33a3dc18001820100"), - 1.toShort, - 5 - ) + Right(ConstantPlaceholder(0, SSigmaProp)) + ), + Coll(), + Map( + ErgoBox.R4 -> ByteArrayConstant(Helpers.decodeBytes("34")), + ErgoBox.R5 -> TrueLeaf + ), + ModifierId @@ ("0000bfe96a7c0001e7a5ee00aafb80ff057fbe7f8c6680e33a3dc18001820100"), + 1.toShort, + 5 ) + ) - val tx = ErgoLikeTransaction( - IndexedSeq(), - IndexedSeq(input.wrappedValue) - ) + val tx = ErgoLikeTransaction( + IndexedSeq(), + IndexedSeq(input.wrappedValue) + ) - val tx2 = ErgoLikeTransaction( - IndexedSeq(Input(input.ebox.id, ProverResult(Array.emptyByteArray, ContextExtension(Map(11.toByte -> BooleanConstant(true)))))), - IndexedSeq(input.wrappedValue) - ) + val tx2 = ErgoLikeTransaction( + IndexedSeq(Input(input.ebox.id, ProverResult(Array.emptyByteArray, ContextExtension(Map(11.toByte -> BooleanConstant(true)))))), + IndexedSeq(input.wrappedValue) + ) - val tx3 = ErgoLikeTransaction( - IndexedSeq(Input(input.ebox.id, ProverResult(Array.emptyByteArray, ContextExtension(Map(11.toByte -> IntConstant(0)))))), - IndexedSeq(input.wrappedValue) - ) + val tx3 = ErgoLikeTransaction( + IndexedSeq(Input(input.ebox.id, ProverResult(Array.emptyByteArray, ContextExtension(Map(11.toByte -> IntConstant(0)))))), + IndexedSeq(input.wrappedValue) + ) - val tx4 = ErgoLikeTransaction( - IndexedSeq(Input(input.ebox.id, ProverResult(Array.emptyByteArray, ContextExtension(Map(11.toByte -> BooleanConstant(false)))))), - IndexedSeq(input.wrappedValue) - ) + val tx4 = ErgoLikeTransaction( + IndexedSeq(Input(input.ebox.id, ProverResult(Array.emptyByteArray, ContextExtension(Map(11.toByte -> BooleanConstant(false)))))), + IndexedSeq(input.wrappedValue) + ) - val ctx = CContext( - _dataInputs = Coll[Box](), - headers = Coll[Header](), - preHeader = CPreHeader( - 0.toByte, - Colls.fromArray(Array.fill(32)(0.toByte)), - -755484979487531112L, - 9223372036854775807L, - 11, - Helpers.decodeGroupElement("0227a58e9b2537103338c237c52c1213bf44bdb344fa07d9df8ab826cca26ca08f"), - Helpers.decodeBytes("007f00") - ), - inputs = Coll[Box](input), - outputs = Coll[Box](), - height = 11, - selfBox = input.copy(), // in 3.x, 4.x implementation selfBox is never the same instance as input (see toSigmaContext) - selfIndex = 0, - lastBlockUtxoRootHash = CAvlTree( - AvlTreeData( - ErgoAlgos.decodeUnsafe("54d23dd080006bdb56800100356080935a80ffb77e90b800057f00661601807f17").toColl, - AvlTreeFlags(true, true, true), - 1211925457, - None - ) - ), - _minerPubKey = Helpers.decodeBytes("0227a58e9b2537103338c237c52c1213bf44bdb344fa07d9df8ab826cca26ca08f"), - vars = Colls - .replicate[AnyValue](10, null) // reserve 10 vars - .append(Coll[AnyValue]( - CAnyValue(Helpers.decodeBytes("00")), - CAnyValue(true))), - spendingTransaction = tx, - activatedScriptVersion = activatedVersionInTests, - currentErgoTreeVersion = ergoTreeVersionInTests - ) - val ctx2 = ctx.copy(spendingTransaction = tx2) - val ctx3 = ctx.copy(spendingTransaction = tx3, vars = ctx.vars.patch(11, Coll(CAnyValue(0)), 1)) - val ctx4 = ctx.copy(spendingTransaction = tx4, vars = ctx.vars.patch(11, Coll(CAnyValue(false)), 1)) + val ctx = CContext( + _dataInputs = Coll[Box](), + headers = Coll[Header](), + preHeader = CPreHeader( + 0.toByte, + Colls.fromArray(Array.fill(32)(0.toByte)), + -755484979487531112L, + 9223372036854775807L, + 11, + Helpers.decodeGroupElement("0227a58e9b2537103338c237c52c1213bf44bdb344fa07d9df8ab826cca26ca08f"), + Helpers.decodeBytes("007f00") + ), + inputs = Coll[Box](input), + outputs = Coll[Box](), + height = 11, + selfBox = input.copy(), // in 3.x, 4.x implementation selfBox is never the same instance as input (see toSigmaContext) + selfIndex = 0, + lastBlockUtxoRootHash = CAvlTree( + AvlTreeData( + ErgoAlgos.decodeUnsafe("54d23dd080006bdb56800100356080935a80ffb77e90b800057f00661601807f17").toColl, + AvlTreeFlags(true, true, true), + 1211925457, + None + ) + ), + _minerPubKey = Helpers.decodeBytes("0227a58e9b2537103338c237c52c1213bf44bdb344fa07d9df8ab826cca26ca08f"), + vars = Colls + .replicate[AnyValue](10, null) // reserve 10 vars + .append(Coll[AnyValue]( + CAnyValue(Helpers.decodeBytes("00")), + CAnyValue(true))), + spendingTransaction = tx, + activatedScriptVersion = activatedVersionInTests, + currentErgoTreeVersion = ergoTreeVersionInTests + ) + val ctx2 = ctx.copy(spendingTransaction = tx2) + val ctx3 = ctx.copy(spendingTransaction = tx3, vars = ctx.vars.patch(11, Coll(CAnyValue(0)), 1)) + val ctx4 = ctx.copy(spendingTransaction = tx4, vars = ctx.vars.patch(11, Coll(CAnyValue(false)), 1)) + + (ctx, ctx2, ctx3, ctx4) + } - (ctx, ctx2, ctx3, ctx4) - } + property("getVarFromInput") { def getVarFromInput = { newFeature( - { (x: Context) => x.getVarFromInput[Boolean](0, 11)}, + { (x: Context) => x.getVarFromInput[Boolean](0, 11) }, "{ (x: Context) => x.getVarFromInput[Boolean](0, 11) }", FuncValue( Array((1, SContext)), @@ -1653,6 +1653,9 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite => ), getVarFromInput ) + } + + property("Context.getVar") { def getVar = { newFeature( @@ -1662,6 +1665,8 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite => ) } + val (_, ctx2, ctx3, ctx4) = contextData() + verifyCases( Seq( ctx2 -> new Expected(ExpectedResult(Success(Some(true)), None)), @@ -1672,8 +1677,6 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite => ) } - - property("Option.getOrElse with lazy default") { val trace = TracedCost( From 5f6b9ee529868dc1eef0fcbcbdd48397809b6ca4 Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Tue, 22 Oct 2024 23:53:34 +0300 Subject: [PATCH 266/314] LSV6 tests --- .../scala/sigma/LanguageSpecificationV6.scala | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala b/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala index a49ae45156..9281cb6c1e 100644 --- a/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala +++ b/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala @@ -1799,4 +1799,30 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite => ) } + property("Global.some") { + lazy val some = newFeature( + { (x: Byte) => CSigmaDslBuilder.some[Byte](x) }, + "{ (x: Byte) => Global.some[Byte](x) }", + sinceVersion = V6SoftForkVersion) + val cases = Seq( + (0.toByte, Success(Some(0.toByte))), + (1.toByte, Success(Some(1.toByte))) + ) + + testCases(cases, some) + } + + property("Global.none") { + lazy val some = newFeature( + { (x: Byte) => CSigmaDslBuilder.none[Byte]() }, + "{ (x: Byte) => Global.none[Byte]() }", + sinceVersion = V6SoftForkVersion) + val cases = Seq( + (0.toByte, Success(None)), + (1.toByte, Success(None)) + ) + + testCases(cases, some) + } + } From 03bfd6aca0115690b04b4c8b02f2b826f80f37b5 Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Wed, 23 Oct 2024 00:05:24 +0300 Subject: [PATCH 267/314] polishing --- data/shared/src/main/scala/sigma/ast/methods.scala | 10 +++++----- .../scala/sigmastate/utxo/BasicOpsSpecification.scala | 7 ++++--- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/data/shared/src/main/scala/sigma/ast/methods.scala b/data/shared/src/main/scala/sigma/ast/methods.scala index 62a8691eec..37ca4778f7 100644 --- a/data/shared/src/main/scala/sigma/ast/methods.scala +++ b/data/shared/src/main/scala/sigma/ast/methods.scala @@ -1836,19 +1836,19 @@ case object SGlobalMethods extends MonoTypeMethods { } lazy val someMethod = SMethod(this, "some", - SFunc(Array(SGlobal, tT), SOption(tT), Array(paramT)), 8, FixedCost(JitCost(5)), Seq(tT)) // todo: cost + SFunc(Array(SGlobal, tT), SOption(tT), Array(paramT)), 8, FixedCost(JitCost(5)), Seq(tT)) .withIRInfo(MethodCallIrBuilder, javaMethodOf[SigmaDslBuilder, Any, RType[_]]("some"), { mtype => Array(mtype.tRange) }) - .withInfo(MethodCall, "", - ArgInfo("value", "value to be serialized")) + .withInfo(MethodCall, "Wrap given input into optional value (Option()).", + ArgInfo("value", "Value to wrap into Option.")) lazy val noneMethod = SMethod(this, "none", - SFunc(Array(SGlobal), SOption(tT), Array(paramT)), 9, FixedCost(JitCost(5)), Seq(tT)) // todo: cost + SFunc(Array(SGlobal), SOption(tT), Array(paramT)), 9, FixedCost(JitCost(5)), Seq(tT)) .withIRInfo(MethodCallIrBuilder, javaMethodOf[SigmaDslBuilder, RType[_]]("none"), { mtype => Array(mtype.tRange) }) - .withInfo(MethodCall, "") + .withInfo(MethodCall, "Returns empty Option[T] of given type T.") protected override def getMethods() = super.getMethods() ++ { if (VersionContext.current.isV6SoftForkActivated) { diff --git a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala index f42114148e..f15e2e7179 100644 --- a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala @@ -27,6 +27,7 @@ import sigma.ast.Apply import sigma.eval.EvalSettings import sigma.exceptions.InvalidType import sigma.serialization.ErgoTreeSerializer +import sigma.validation.ValidationException import sigmastate.utils.Helpers import sigmastate.utils.Helpers._ @@ -1787,7 +1788,7 @@ class BasicOpsSpecification extends CompilerTestingCommons if (VersionContext.current.isV6SoftForkActivated) { someTest() } else { - an[Exception] should be thrownBy someTest() + an[sigmastate.exceptions.MethodNotFound] should be thrownBy someTest() } } @@ -1809,7 +1810,7 @@ class BasicOpsSpecification extends CompilerTestingCommons if (VersionContext.current.isV6SoftForkActivated) { someTest() } else { - an[Exception] should be thrownBy someTest() + an[sigmastate.exceptions.MethodNotFound] should be thrownBy someTest() } } @@ -1831,7 +1832,7 @@ class BasicOpsSpecification extends CompilerTestingCommons if (VersionContext.current.isV6SoftForkActivated) { someTest() } else { - an[Exception] should be thrownBy someTest() + an[sigmastate.exceptions.MethodNotFound] should be thrownBy someTest() } } From 1fbd4e598cd5331fe71ebe2492f5946c8c4bb095 Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Thu, 24 Oct 2024 19:54:12 +0300 Subject: [PATCH 268/314] Update docs/LangSpec.md Co-authored-by: Alexander Slesarenko --- docs/LangSpec.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/LangSpec.md b/docs/LangSpec.md index 7ec7dd7729..f1aace7de2 100644 --- a/docs/LangSpec.md +++ b/docs/LangSpec.md @@ -919,7 +919,7 @@ def longToByteArray(input: Long): Coll[Byte] def decodePoint(bytes: Coll[Byte]): GroupElement -/** Extracts Context variable from self input by id and type. +/** Extracts Context variable from SELF input by id and type. * ErgoScript is typed, so accessing a the variables is an operation which involves * some expected type given in brackets. Thus `getVar[Int](id)` expression should * evaluate to a valid value of the `Option[Int]` type. From 208a191534b54a197d40bd4fd6c338fa06a337f1 Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Thu, 24 Oct 2024 19:54:22 +0300 Subject: [PATCH 269/314] Update docs/LangSpec.md Co-authored-by: Alexander Slesarenko --- docs/LangSpec.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/LangSpec.md b/docs/LangSpec.md index f1aace7de2..16defff5ff 100644 --- a/docs/LangSpec.md +++ b/docs/LangSpec.md @@ -976,7 +976,7 @@ def decodePoint(bytes: Coll[Byte]): GroupElement */ def getVar[T](tag: Int): Option[T] -/** Extracts Context variable from any input by input id, variable id and variable type. +/** Extracts Context variable from any input by input index, variable id and variable type. * Unlike getVar, it is not throwing exception when expected type does not match real type of the variable. * Thus it can be used to get context variable from self without exception, using selfBoxIndex, e.g. *

From a160997209a0d9df7564079317aad6a089cb8744 Mon Sep 17 00:00:00 2001
From: Alexander Chepurnoy 
Date: Thu, 31 Oct 2024 15:44:18 +0300
Subject: [PATCH 270/314] UnsignedBigInt support in DataSerializerSpecification

---
 core/shared/src/main/scala/sigma/ast/SType.scala          | 2 +-
 core/shared/src/main/scala/sigma/util/Extensions.scala    | 8 ++++++++
 .../src/main/scala/sigma/data/DataValueComparer.scala     | 1 -
 .../sigma/serialization/DataSerializerSpecification.scala | 3 ++-
 .../sigma/serialization/generators/ObjectGenerators.scala | 2 ++
 .../sigma/serialization/generators/TypeGenerators.scala   | 8 +++++---
 .../src/test/scala/sigmastate/ErgoTreeSpecification.scala | 3 ++-
 7 files changed, 20 insertions(+), 7 deletions(-)

diff --git a/core/shared/src/main/scala/sigma/ast/SType.scala b/core/shared/src/main/scala/sigma/ast/SType.scala
index b69a988347..17a5ef10d7 100644
--- a/core/shared/src/main/scala/sigma/ast/SType.scala
+++ b/core/shared/src/main/scala/sigma/ast/SType.scala
@@ -322,7 +322,7 @@ object SPrimType {
   def unapply(t: SType): Option[SType] = SType.allPredefTypes.find(_ == t)
 
   /** Type code of the last valid prim type so that (1 to LastPrimTypeCode) is a range of valid codes. */
-  final val LastPrimTypeCode: Byte = 8: Byte
+  final val LastPrimTypeCode: Byte = 9: Byte
 
   /** Upper limit of the interval of valid type codes for primitive types */
   final val MaxPrimTypeCode: Byte = 11: Byte
diff --git a/core/shared/src/main/scala/sigma/util/Extensions.scala b/core/shared/src/main/scala/sigma/util/Extensions.scala
index 5d1d9b7da8..e97241ca3d 100644
--- a/core/shared/src/main/scala/sigma/util/Extensions.scala
+++ b/core/shared/src/main/scala/sigma/util/Extensions.scala
@@ -227,6 +227,14 @@ object Extensions {
 
     /** Converts `x` to [[sigma.BigInt]] */
     def toBigInt: sigma.BigInt = CBigInt(x)
+
+    /** Converts `x` to [[sigma.UnsignedBigInt]] */
+    def toUnsignedBigInt: sigma.UnsignedBigInt = {
+      if(x.compareTo(BigInteger.ZERO) < 0){
+        throw new IllegalArgumentException("toUnsignedBigInt arg < 0")
+      }
+      CUnsignedBigInt(x)
+    }
   }
 
   implicit class BigIntOps(val x: sigma.BigInt) extends AnyVal {
diff --git a/data/shared/src/main/scala/sigma/data/DataValueComparer.scala b/data/shared/src/main/scala/sigma/data/DataValueComparer.scala
index 39022a2e7e..e525b8f074 100644
--- a/data/shared/src/main/scala/sigma/data/DataValueComparer.scala
+++ b/data/shared/src/main/scala/sigma/data/DataValueComparer.scala
@@ -344,7 +344,6 @@ object DataValueComparer {
           okEqual = bi == r
         }
 
-      // todo: check costing
       case ubi: UnsignedBigInt => /** case 5 (see [[EQ_BigInt]]) */
         E.addFixedCost(EQ_BigInt) {
           okEqual = ubi == r
diff --git a/interpreter/shared/src/test/scala/sigma/serialization/DataSerializerSpecification.scala b/interpreter/shared/src/test/scala/sigma/serialization/DataSerializerSpecification.scala
index fe6f62dbe0..e17c21b03e 100644
--- a/interpreter/shared/src/test/scala/sigma/serialization/DataSerializerSpecification.scala
+++ b/interpreter/shared/src/test/scala/sigma/serialization/DataSerializerSpecification.scala
@@ -66,7 +66,7 @@ class DataSerializerSpecification extends SerializationSpecification {
     implicit val tagT = tT.classTag
     implicit val tAny = sigma.AnyType
 
-    val withVersion = if (tpe == SHeader) {
+    val withVersion = if (tpe == SHeader || tpe == SUnsignedBigInt) {
       Some(VersionContext.V6SoftForkVersion)
     } else {
       None
@@ -148,6 +148,7 @@ class DataSerializerSpecification extends SerializationSpecification {
     forAll { x: Long => roundtrip[SLong.type](x, SLong) }
     forAll { x: String => roundtrip[SString.type](x, SString) }
     forAll { x: BigInteger => roundtrip[SBigInt.type](x.toBigInt, SBigInt) }
+    forAll { x: BigInteger => roundtrip[SUnsignedBigInt.type](x.abs().toUnsignedBigInt, SUnsignedBigInt, Some(VersionContext.V6SoftForkVersion)) }
     forAll { x: EcPointType => roundtrip[SGroupElement.type](x.toGroupElement, SGroupElement) }
     forAll { x: SigmaBoolean => roundtrip[SSigmaProp.type](x.toSigmaProp, SSigmaProp) }
     forAll { x: ErgoBox => roundtrip[SBox.type](x, SBox) }
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 db6cd87330..9a4668d8e0 100644
--- a/interpreter/shared/src/test/scala/sigma/serialization/generators/ObjectGenerators.scala
+++ b/interpreter/shared/src/test/scala/sigma/serialization/generators/ObjectGenerators.scala
@@ -83,6 +83,7 @@ trait ObjectGenerators extends TypeGenerators
   implicit lazy val arbRegisterIdentifier: Arbitrary[RegisterId] = Arbitrary(registerIdentifierGen)
   implicit lazy val arbBigInteger: Arbitrary[BigInteger] = Arbitrary(Arbitrary.arbBigInt.arbitrary.map(_.bigInteger))
   implicit lazy val arbBigInt: Arbitrary[BigInt] = Arbitrary(arbBigInteger.arbitrary.map(SigmaDsl.BigInt(_)))
+  implicit lazy val arbUnsignedBigInt: Arbitrary[UnsignedBigInt] = Arbitrary(arbBigInteger.arbitrary.map(_.abs()).map(SigmaDsl.UnsignedBigInt(_)))
   implicit lazy val arbEcPointType: Arbitrary[dlogGroup.ElemType] = Arbitrary(Gen.const(()).flatMap(_ => CryptoConstants.dlogGroup.createRandomGenerator()))
   implicit lazy val arbGroupElement: Arbitrary[GroupElement] = Arbitrary(arbEcPointType.arbitrary.map(SigmaDsl.GroupElement(_)))
   implicit lazy val arbSigmaBoolean: Arbitrary[SigmaBoolean] = Arbitrary(Gen.oneOf(proveDHTGen, proveDHTGen))
@@ -305,6 +306,7 @@ trait ObjectGenerators extends TypeGenerators
     case SInt => arbInt
     case SLong => arbLong
     case SBigInt => arbBigInt
+    case SUnsignedBigInt => arbUnsignedBigInt
     case SGroupElement => arbGroupElement
     case SSigmaProp => arbSigmaProp
     case SBox => arbBox
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 70a215e831..dc7962de0e 100644
--- a/interpreter/shared/src/test/scala/sigma/serialization/generators/TypeGenerators.scala
+++ b/interpreter/shared/src/test/scala/sigma/serialization/generators/TypeGenerators.scala
@@ -11,6 +11,7 @@ trait TypeGenerators {
   implicit val intTypeGen: Gen[SInt.type] = Gen.const(SInt)
   implicit val longTypeGen: Gen[SLong.type] = Gen.const(SLong)
   implicit val bigIntTypeGen: Gen[SBigInt.type] = Gen.const(SBigInt)
+  implicit val unsignedBigIntTypeGen: Gen[SUnsignedBigInt.type] = Gen.const(SUnsignedBigInt)
   implicit val groupElementTypeGen: Gen[SGroupElement.type] = Gen.const(SGroupElement)
   implicit val sigmaPropTypeGen: Gen[SSigmaProp.type] = Gen.const(SSigmaProp)
   implicit val boxTypeGen: Gen[SBox.type] = Gen.const(SBox)
@@ -19,10 +20,10 @@ trait TypeGenerators {
   implicit val headerTypeGen: Gen[SHeader.type] = Gen.const(SHeader)
 
   implicit val primTypeGen: Gen[SPrimType] =
-    Gen.oneOf[SPrimType](SBoolean, SByte, SShort, SInt, SLong, SBigInt, SGroupElement, SSigmaProp, SUnit)
+    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] =
-    Gen.oneOf[SPredefType](SBoolean, SByte, SShort, SInt, SLong, SBigInt, SGroupElement, SSigmaProp, SUnit, SBox, SAvlTree, SHeader)
+    Gen.oneOf[SPredefType](SBoolean, SByte, SShort, SInt, SLong, SBigInt, SUnsignedBigInt, SGroupElement, SSigmaProp, SUnit, SBox, SAvlTree, SHeader)
   implicit val arbPredefType: Arbitrary[SPredefType] = Arbitrary(predefTypeGen)
 
   implicit def genToArbitrary[T: Gen]: Arbitrary[T] = Arbitrary(implicitly[Gen[T]])
@@ -34,7 +35,8 @@ trait TypeGenerators {
       shortTypeGen,
       intTypeGen,
       longTypeGen,
-      bigIntTypeGen
+      bigIntTypeGen,
+      unsignedBigIntTypeGen
     ))
   } yield STuple(values.toIndexedSeq)
 
diff --git a/sc/shared/src/test/scala/sigmastate/ErgoTreeSpecification.scala b/sc/shared/src/test/scala/sigmastate/ErgoTreeSpecification.scala
index 1c38ca45a0..83870757e3 100644
--- a/sc/shared/src/test/scala/sigmastate/ErgoTreeSpecification.scala
+++ b/sc/shared/src/test/scala/sigmastate/ErgoTreeSpecification.scala
@@ -264,7 +264,7 @@ class ErgoTreeSpecification extends SigmaDslTesting with ContractsTestkit with C
 
   val typeCodes = Table(
     ("constant", "expectedValue"),
-    (SPrimType.LastPrimTypeCode, 8),
+    (SPrimType.LastPrimTypeCode, 9),
     (SPrimType.MaxPrimTypeCode, 11)
   )
   
@@ -285,6 +285,7 @@ class ErgoTreeSpecification extends SigmaDslTesting with ContractsTestkit with C
     (SBigInt,  6, true, true, true),
     (SGroupElement, 7, true, true, false),
     (SSigmaProp,    8, true, true, false),
+    (SUnsignedBigInt, 9, true, true, true),
     (SBox,       99,  false, false, false),
     (SAvlTree,   100, false, false, false),
     (SContext,   101, false, false, false),

From fdf712e274c39719099354ee61e67fa6946b4962 Mon Sep 17 00:00:00 2001
From: Alexander Chepurnoy 
Date: Thu, 31 Oct 2024 17:59:12 +0300
Subject: [PATCH 271/314] ErgoTreeSpecification update

---
 .../src/main/scala/sigma/ast/methods.scala    | 16 +++----
 .../sigmastate/ErgoTreeSpecification.scala    | 48 +++++++++++++++++--
 2 files changed, 52 insertions(+), 12 deletions(-)

diff --git a/data/shared/src/main/scala/sigma/ast/methods.scala b/data/shared/src/main/scala/sigma/ast/methods.scala
index f3517ae496..9b0e5e8584 100644
--- a/data/shared/src/main/scala/sigma/ast/methods.scala
+++ b/data/shared/src/main/scala/sigma/ast/methods.scala
@@ -497,7 +497,7 @@ case object SBigIntMethods extends SNumericTypeMethods {
   private val ToUnsignedCostKind = FixedCost(JitCost(5))
 
   //id = 8 to make it after toBits
-  val ToUnsigned = SMethod(this, "toUnsigned", SFunc(this.ownerType, SUnsignedBigInt), 19, ToUnsignedCostKind)
+  val ToUnsigned = SMethod(this, "toUnsigned", SFunc(this.ownerType, SUnsignedBigInt), 14, ToUnsignedCostKind)
     .withIRInfo(MethodCallIrBuilder)
     .withInfo(MethodCall, "")
 
@@ -508,7 +508,7 @@ case object SBigIntMethods extends SNumericTypeMethods {
   }
 
 
-  val ToUnsignedMod = SMethod(this, "toUnsignedMod", SFunc(Array(this.ownerType, SUnsignedBigInt), SUnsignedBigInt), 20, ToUnsignedCostKind)
+  val ToUnsignedMod = SMethod(this, "toUnsignedMod", SFunc(Array(this.ownerType, SUnsignedBigInt), SUnsignedBigInt), 15, ToUnsignedCostKind)
     .withIRInfo(MethodCallIrBuilder)
     .withInfo(MethodCall, "")
 
@@ -541,7 +541,7 @@ case object SUnsignedBigIntMethods extends SNumericTypeMethods {
   final val ModInverseCostInfo = ToNBitsCostInfo
 
   // todo: check ids before and after merging with other PRs introducing new methods for Numeric
-  val ModInverseMethod = SMethod(this, "modInverse", SFunc(Array(this.ownerType, this.ownerType), this.ownerType), 19, ModInverseCostInfo.costKind)
+  val ModInverseMethod = SMethod(this, "modInverse", SFunc(Array(this.ownerType, this.ownerType), this.ownerType), 14, ModInverseCostInfo.costKind)
     .withIRInfo(MethodCallIrBuilder)
     .withInfo(MethodCall, "")
 
@@ -552,7 +552,7 @@ case object SUnsignedBigIntMethods extends SNumericTypeMethods {
   }
 
   // todo: costing
-  val PlusModMethod = SMethod(this, "plusMod", SFunc(Array(this.ownerType, this.ownerType, this.ownerType), this.ownerType), 20, ModInverseCostInfo.costKind)
+  val PlusModMethod = SMethod(this, "plusMod", SFunc(Array(this.ownerType, this.ownerType, this.ownerType), this.ownerType), 15, ModInverseCostInfo.costKind)
     .withIRInfo(MethodCallIrBuilder)
     .withInfo(MethodCall, "")
 
@@ -562,7 +562,7 @@ case object SUnsignedBigIntMethods extends SNumericTypeMethods {
     bi.plusMod(bi2, m)
   }
 
-  val SubtractModMethod = SMethod(this, "subtractMod", SFunc(Array(this.ownerType, this.ownerType, this.ownerType), this.ownerType), 21, ModInverseCostInfo.costKind)
+  val SubtractModMethod = SMethod(this, "subtractMod", SFunc(Array(this.ownerType, this.ownerType, this.ownerType), this.ownerType), 16, ModInverseCostInfo.costKind)
     .withIRInfo(MethodCallIrBuilder)
     .withInfo(MethodCall, "")
 
@@ -572,7 +572,7 @@ case object SUnsignedBigIntMethods extends SNumericTypeMethods {
     bi.subtractMod(bi2, m)
   }
 
-  val MultiplyModMethod = SMethod(this, "multiplyMod", SFunc(Array(this.ownerType, this.ownerType, this.ownerType), this.ownerType), 22, ModInverseCostInfo.costKind)
+  val MultiplyModMethod = SMethod(this, "multiplyMod", SFunc(Array(this.ownerType, this.ownerType, this.ownerType), this.ownerType), 17, ModInverseCostInfo.costKind)
     .withIRInfo(MethodCallIrBuilder)
     .withInfo(MethodCall, "")
 
@@ -582,7 +582,7 @@ case object SUnsignedBigIntMethods extends SNumericTypeMethods {
     bi.multiplyMod(bi2, m)
   }
 
-  val ModMethod = SMethod(this, "mod", SFunc(Array(this.ownerType, this.ownerType), this.ownerType), 23, ModInverseCostInfo.costKind)
+  val ModMethod = SMethod(this, "mod", SFunc(Array(this.ownerType, this.ownerType), this.ownerType), 18, ModInverseCostInfo.costKind)
     .withIRInfo(MethodCallIrBuilder)
     .withInfo(MethodCall, "")
 
@@ -592,7 +592,7 @@ case object SUnsignedBigIntMethods extends SNumericTypeMethods {
     bi.mod(m)
   }
 
-  val ToSignedMethod = SMethod(this, "toSigned", SFunc(Array(this.ownerType), SBigInt), 24, ModInverseCostInfo.costKind)
+  val ToSignedMethod = SMethod(this, "toSigned", SFunc(Array(this.ownerType), SBigInt), 19, ModInverseCostInfo.costKind)
     .withIRInfo(MethodCallIrBuilder)
     .withInfo(MethodCall, "")
 
diff --git a/sc/shared/src/test/scala/sigmastate/ErgoTreeSpecification.scala b/sc/shared/src/test/scala/sigmastate/ErgoTreeSpecification.scala
index 83870757e3..79aaa97f89 100644
--- a/sc/shared/src/test/scala/sigmastate/ErgoTreeSpecification.scala
+++ b/sc/shared/src/test/scala/sigmastate/ErgoTreeSpecification.scala
@@ -7,11 +7,13 @@ import sigma.ast.SCollection.SByteArray
 import sigma.ast._
 import sigma.ast.syntax.{SValue, SigmaPropValue, TrueSigmaProp}
 import sigma.data.RType.asType
-import sigma.data.{CBox, Nullable, RType, TrivialProp}
+import sigma.data.{Nullable, RType, TrivialProp}
 import sigma.validation.ValidationException
 import sigma.validation.ValidationRules.CheckTypeCode
 import ErgoTree.HeaderType
 import SCollectionMethods.checkValidFlatmap
+import sigma.ast.SBigIntMethods.{ToUnsigned, ToUnsignedMod}
+import sigma.ast.SUnsignedBigIntMethods.{ModInverseMethod, ModMethod, MultiplyModMethod, PlusModMethod, SubtractModMethod, ToSignedMethod}
 import sigmastate.eval.CProfiler
 import sigmastate.helpers.{ErgoLikeContextTesting, SigmaPPrint}
 import sigmastate.interpreter.Interpreter.ReductionResult
@@ -431,17 +433,55 @@ class ErgoTreeSpecification extends SigmaDslTesting with ContractsTestkit with C
           MInfo(10, BitwiseAndMethod, isResolvableFromIds = true),
           MInfo(11, BitwiseXorMethod, isResolvableFromIds = true),
           MInfo(12, ShiftLeftMethod, isResolvableFromIds = true),
-          MInfo(13, ShiftRightMethod, isResolvableFromIds = true)
+          MInfo(13, ShiftRightMethod, isResolvableFromIds = true),
+          MInfo(14, ToUnsigned, isResolvableFromIds = true),
+          MInfo(15, ToUnsignedMod, isResolvableFromIds = true)
         ) else Seq.empty)
         , true)
     },
+      {
+        if (isV6Activated) {
+          // SBigInt inherit methods from SNumericType.methods
+          // however they are not resolvable via SBigInt.typeId before v6.0
+          import SNumericTypeMethods._
+          (SUnsignedBigInt.typeId, Seq(
+            MInfo(methodId = 1, ToByteMethod, isResolvableFromIds = true),
+            MInfo(2, ToShortMethod, isResolvableFromIds = if (isV6Activated) true else false),
+            MInfo(3, ToIntMethod, isResolvableFromIds = if (isV6Activated) true else false),
+            MInfo(4, ToLongMethod, isResolvableFromIds = if (isV6Activated) true else false),
+            MInfo(5, ToBigIntMethod, isResolvableFromIds = if (isV6Activated) true else false),
+            MInfo(6, ToBytesMethod, isResolvableFromIds = if (isV6Activated) true else false),
+            MInfo(7, ToBitsMethod, isResolvableFromIds = if (isV6Activated) true else false),
+            MInfo(8, BitwiseInverseMethod, isResolvableFromIds = true),
+            MInfo(9, BitwiseOrMethod, isResolvableFromIds = true),
+            MInfo(10, BitwiseAndMethod, isResolvableFromIds = true),
+            MInfo(11, BitwiseXorMethod, isResolvableFromIds = true),
+            MInfo(12, ShiftLeftMethod, isResolvableFromIds = true),
+            MInfo(13, ShiftRightMethod, isResolvableFromIds = true),
+            MInfo(14, ModInverseMethod, true),
+            MInfo(15, PlusModMethod, true),
+            MInfo(16, SubtractModMethod, true),
+            MInfo(17, MultiplyModMethod, true),
+            MInfo(18, ModMethod, true),
+            MInfo(19, ToSignedMethod, true)
+          ), true)
+        } else {
+          (SUnsignedBigInt.typeId, Seq.empty, false)
+        }
+      },
     { import SGroupElementMethods._
       (SGroupElement.typeId,  Seq(
         MInfo(2, GetEncodedMethod),
         MInfo(3, ExponentiateMethod),
         MInfo(4, MultiplyMethod),
         MInfo(5, NegateMethod)
-      ), true)
+      ) ++ {
+        if(VersionContext.current.isV6SoftForkActivated) {
+          Seq(MInfo(6, ExponentiateUnsignedMethod))
+        } else {
+          Seq.empty
+        }
+      }, true)
     },
     { import SSigmaPropMethods._
       (SSigmaProp.typeId,  Seq(
@@ -626,7 +666,7 @@ class ErgoTreeSpecification extends SigmaDslTesting with ContractsTestkit with C
   }
 
   property("MethodCall on numerics") {
-    forAll(Table[STypeCompanion]("type", SByte, SShort, SInt, SLong, SBigInt)) { t =>
+    forAll(Table[STypeCompanion]("type", SByte, SShort, SInt, SLong, SBigInt, SUnsignedBigInt)) { t =>
       // this methods are expected to fail resolution in before v6.0
       if (!isV6Activated) {
         (1 to 7).foreach { methodId =>

From dde7f6e3bb5d2f35dd28160a9bd6c35e3df9b4d5 Mon Sep 17 00:00:00 2001
From: Alexander Chepurnoy 
Date: Thu, 31 Oct 2024 23:36:16 +0300
Subject: [PATCH 272/314] fixing DataJsonEncoderSpecification

---
 .../org/ergoplatform/sdk/DataJsonEncoderSpecification.scala     | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

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 5835f399cb..2457aacfea 100644
--- a/sdk/shared/src/test/scala/org/ergoplatform/sdk/DataJsonEncoderSpecification.scala
+++ b/sdk/shared/src/test/scala/org/ergoplatform/sdk/DataJsonEncoderSpecification.scala
@@ -44,7 +44,7 @@ class DataJsonEncoderSpecification extends SerializationSpecification {
     implicit val tT = Evaluation.stypeToRType(tpe)
     implicit val tagT = tT.classTag
 
-    val withVersion = if (tpe == SHeader) {
+    val withVersion = if (tpe == SHeader || tpe == SUnsignedBigInt) {
       Some(VersionContext.V6SoftForkVersion)
     } else {
       None

From a18967c96c9eee0f91c8e3cb8309f0083a5dbfc0 Mon Sep 17 00:00:00 2001
From: Alexander Chepurnoy 
Date: Fri, 1 Nov 2024 00:23:29 +0300
Subject: [PATCH 273/314] SigmaTyperTest fix

---
 .../DataSerializerSpecification.scala         |  3 ++-
 .../generators/TypeGenerators.scala           | 10 +++++--
 .../sdk/DataJsonEncoderSpecification.scala    | 26 +++++--------------
 3 files changed, 17 insertions(+), 22 deletions(-)

diff --git a/interpreter/shared/src/test/scala/sigma/serialization/DataSerializerSpecification.scala b/interpreter/shared/src/test/scala/sigma/serialization/DataSerializerSpecification.scala
index e17c21b03e..9201214e4f 100644
--- a/interpreter/shared/src/test/scala/sigma/serialization/DataSerializerSpecification.scala
+++ b/interpreter/shared/src/test/scala/sigma/serialization/DataSerializerSpecification.scala
@@ -67,10 +67,11 @@ class DataSerializerSpecification extends SerializationSpecification {
     implicit val tAny = sigma.AnyType
 
     val withVersion = if (tpe == SHeader || tpe == SUnsignedBigInt) {
-      Some(VersionContext.V6SoftForkVersion)
+      None // Some(VersionContext.V6SoftForkVersion)
     } else {
       None
     }
+
     forAll { xs: Array[T#WrappedType] =>
       roundtrip[SCollection[T]](xs.toColl, SCollection(tpe), withVersion)
       roundtrip[SType](xs.toColl.map(x => (x, x)).asWrappedType, SCollection(STuple(tpe, tpe)), withVersion)
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 dc7962de0e..699ef1c8f8 100644
--- a/interpreter/shared/src/test/scala/sigma/serialization/generators/TypeGenerators.scala
+++ b/interpreter/shared/src/test/scala/sigma/serialization/generators/TypeGenerators.scala
@@ -2,6 +2,7 @@ package sigma.serialization.generators
 
 import org.scalacheck.{Arbitrary, Gen}
 import org.scalacheck.Arbitrary.arbString
+import sigma.VersionContext
 import sigma.ast._
 
 trait TypeGenerators {
@@ -22,8 +23,13 @@ trait TypeGenerators {
   implicit val primTypeGen: Gen[SPrimType] =
     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] =
-    Gen.oneOf[SPredefType](SBoolean, SByte, SShort, SInt, SLong, SBigInt, SUnsignedBigInt, SGroupElement, SSigmaProp, SUnit, SBox, SAvlTree, SHeader)
+  implicit val predefTypeGen: Gen[SPredefType] = {
+    if(VersionContext.current.isV6SoftForkActivated){
+      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)
+    }
+  }
   implicit val arbPredefType: Arbitrary[SPredefType] = Arbitrary(predefTypeGen)
 
   implicit def genToArbitrary[T: Gen]: Arbitrary[T] = Arbitrary(implicitly[Gen[T]])
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 2457aacfea..7e73b6c93d 100644
--- a/sdk/shared/src/test/scala/org/ergoplatform/sdk/DataJsonEncoderSpecification.scala
+++ b/sdk/shared/src/test/scala/org/ergoplatform/sdk/DataJsonEncoderSpecification.scala
@@ -44,26 +44,20 @@ class DataJsonEncoderSpecification extends SerializationSpecification {
     implicit val tT = Evaluation.stypeToRType(tpe)
     implicit val tagT = tT.classTag
 
-    val withVersion = if (tpe == SHeader || tpe == SUnsignedBigInt) {
-      Some(VersionContext.V6SoftForkVersion)
-    } else {
-      None
-    }
 
     forAll { xs: Array[T#WrappedType] =>
-      roundtrip[SCollection[T]](xs.toColl, SCollection(tpe), withVersion)
-      roundtrip[SType](xs.toColl.map(x => (x, x)).asWrappedType, SCollection(STuple(tpe, tpe)), withVersion)
+      roundtrip[SCollection[T]](xs.toColl, SCollection(tpe))
+      roundtrip[SType](xs.toColl.map(x => (x, x)).asWrappedType, SCollection(STuple(tpe, tpe)))
 
       val nested = xs.toColl.map(x => Colls.fromItems[T#WrappedType](x, x))
-      roundtrip[SCollection[SCollection[T]]](nested, SCollection(SCollection(tpe)), withVersion)
+      roundtrip[SCollection[SCollection[T]]](nested, SCollection(SCollection(tpe)))
 
       roundtrip[SType](
         xs.toColl.map { x =>
           val arr = Colls.fromItems[T#WrappedType](x, x)
           (arr, arr)
         }.asWrappedType,
-        SCollection(STuple(SCollection(tpe), SCollection(tpe))),
-        withVersion
+        SCollection(STuple(SCollection(tpe), SCollection(tpe)))
       )
     }
   }
@@ -74,17 +68,11 @@ class DataJsonEncoderSpecification extends SerializationSpecification {
     @nowarn implicit val tag     : ClassTag[T#WrappedType] = tT.classTag
     @nowarn implicit val tAny    : RType[Any]              = sigma.AnyType
 
-    val withVersion = if (tpe == SHeader) {
-      Some(VersionContext.V6SoftForkVersion)
-    } else {
-      None
-    }
-
     forAll { in: (T#WrappedType, T#WrappedType) =>
       val (x,y) = (in._1, in._2)
-      roundtrip[SType]((x, y).asWrappedType, STuple(tpe, tpe), withVersion)
-      roundtrip[SType](((x, y), (x, y)).asWrappedType, STuple(STuple(tpe, tpe), STuple(tpe, tpe)), withVersion)
-      roundtrip[SType](((x, y), ((x, y), (x, y))).asWrappedType, STuple(STuple(tpe, tpe), STuple(STuple(tpe, tpe), STuple(tpe, tpe))), withVersion)
+      roundtrip[SType]((x, y).asWrappedType, STuple(tpe, tpe))
+      roundtrip[SType](((x, y), (x, y)).asWrappedType, STuple(STuple(tpe, tpe), STuple(tpe, tpe)))
+      roundtrip[SType](((x, y), ((x, y), (x, y))).asWrappedType, STuple(STuple(tpe, tpe), STuple(STuple(tpe, tpe), STuple(tpe, tpe))))
     }
   }
 

From 2d8af9d9c045a42951f15de1274e0c2582c4f3e8 Mon Sep 17 00:00:00 2001
From: Alexander Chepurnoy 
Date: Fri, 1 Nov 2024 18:27:47 +0300
Subject: [PATCH 274/314] adding UnsignedBigInt to JS reflection , pt1

---
 .../main/scala/sigma/crypto/Platform.scala    |  1 +
 core/js/src/main/scala/sigma/js/Isos.scala    | 14 +++++-
 .../sigma/reflection/ReflectionData.scala     | 15 +++++++
 data/js/src/main/scala/sigma/Platform.scala   |  1 +
 data/js/src/main/scala/sigma/js/Value.scala   |  6 +++
 .../src/main/scala/sigma/ast/methods.scala    |  1 -
 .../sigma/compiler/ir/GraphIRReflection.scala | 44 +++++++++++++++++++
 .../ir/wrappers/sigma/impl/SigmaDslImpl.scala |  3 +-
 8 files changed, 81 insertions(+), 4 deletions(-)

diff --git a/core/js/src/main/scala/sigma/crypto/Platform.scala b/core/js/src/main/scala/sigma/crypto/Platform.scala
index 88001ba140..777789ba24 100644
--- a/core/js/src/main/scala/sigma/crypto/Platform.scala
+++ b/core/js/src/main/scala/sigma/crypto/Platform.scala
@@ -253,6 +253,7 @@ object Platform {
     case _: Boolean => tpe == SBoolean
     case _: Byte | _: Short | _: Int | _: Long => tpe.isInstanceOf[SNumericType]
     case _: BigInt => tpe == SBigInt
+    case _: UnsignedBigInt => tpe == SUnsignedBigInt
     case _: String => tpe == SString
     case _: GroupElement => tpe.isGroupElement
     case _: SigmaProp => tpe.isSigmaProp
diff --git a/core/js/src/main/scala/sigma/js/Isos.scala b/core/js/src/main/scala/sigma/js/Isos.scala
index 767a358d62..bc88c46457 100644
--- a/core/js/src/main/scala/sigma/js/Isos.scala
+++ b/core/js/src/main/scala/sigma/js/Isos.scala
@@ -1,7 +1,7 @@
 package sigma.js
 
 import sigma.{Coll, Colls}
-import sigma.data.{CBigInt, Iso, RType}
+import sigma.data.{CBigInt, CUnsignedBigInt, Iso, RType}
 
 import java.math.BigInteger
 import scala.reflect.ClassTag
@@ -42,6 +42,18 @@ object Isos {
     }
   }
 
+  implicit val isoUnsignedBigInt: Iso[js.BigInt, sigma.UnsignedBigInt] = new Iso[js.BigInt, sigma.UnsignedBigInt] {
+    override def to(x: js.BigInt): sigma.UnsignedBigInt = {
+      CUnsignedBigInt(new BigInteger(x.toString(10)))
+    }
+
+    override def from(x: sigma.UnsignedBigInt): js.BigInt = {
+      val bi = x.asInstanceOf[CUnsignedBigInt].wrappedValue
+      val s  = bi.toString(10)
+      js.BigInt(s)
+    }
+  }
+
   implicit val isoBigIntToLong: Iso[js.BigInt, Long] = new Iso[js.BigInt, Long] {
     override def to(x: js.BigInt): Long = java.lang.Long.parseLong(x.toString(10))
 
diff --git a/core/shared/src/main/scala/sigma/reflection/ReflectionData.scala b/core/shared/src/main/scala/sigma/reflection/ReflectionData.scala
index 12e1d0eaa2..ef8e52e6cd 100644
--- a/core/shared/src/main/scala/sigma/reflection/ReflectionData.scala
+++ b/core/shared/src/main/scala/sigma/reflection/ReflectionData.scala
@@ -153,6 +153,21 @@ object ReflectionData {
         },
         mkMethod(clazz, "divide", paramTypes) { (obj, args) =>
           obj.asInstanceOf[UnsignedBigInt].divide(args(0).asInstanceOf[UnsignedBigInt])
+        },
+        mkMethod(clazz, "plusMod", paramTypes) { (obj, args) =>
+          obj.asInstanceOf[UnsignedBigInt].plusMod(args(0).asInstanceOf[UnsignedBigInt], args(1).asInstanceOf[UnsignedBigInt])
+        },
+        mkMethod(clazz, "subtractMod", paramTypes) { (obj, args) =>
+          obj.asInstanceOf[UnsignedBigInt].subtractMod(args(0).asInstanceOf[UnsignedBigInt], args(1).asInstanceOf[UnsignedBigInt])
+        },
+        mkMethod(clazz, "multiplyMod", paramTypes) { (obj, args) =>
+          obj.asInstanceOf[UnsignedBigInt].multiplyMod(args(0).asInstanceOf[UnsignedBigInt], args(1).asInstanceOf[UnsignedBigInt])
+        },
+        mkMethod(clazz, "mod", paramTypes) { (obj, args) =>
+          obj.asInstanceOf[UnsignedBigInt].mod(args(0).asInstanceOf[UnsignedBigInt])
+        },
+        mkMethod(clazz, "modInverse", paramTypes) { (obj, args) =>
+          obj.asInstanceOf[UnsignedBigInt].modInverse(args(0).asInstanceOf[UnsignedBigInt])
         }
       )
     )
diff --git a/data/js/src/main/scala/sigma/Platform.scala b/data/js/src/main/scala/sigma/Platform.scala
index 29c761c3f1..2fd4c937f0 100644
--- a/data/js/src/main/scala/sigma/Platform.scala
+++ b/data/js/src/main/scala/sigma/Platform.scala
@@ -28,6 +28,7 @@ object Platform {
       case v: Long => Nullable(mkConstant[SLong.type](v, SLong))
       case v: BigInteger => 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 => Nullable(mkConstant[SString.type](v, SString))
diff --git a/data/js/src/main/scala/sigma/js/Value.scala b/data/js/src/main/scala/sigma/js/Value.scala
index a65156bd43..77d6c8e104 100644
--- a/data/js/src/main/scala/sigma/js/Value.scala
+++ b/data/js/src/main/scala/sigma/js/Value.scala
@@ -81,6 +81,9 @@ object Value extends js.Object {
     case sigma.BigIntRType =>
       val v = data.asInstanceOf[js.BigInt]
       CBigInt(new BigInteger(v.toString(16), 16))
+    case sigma.UnsignedBigIntRType =>
+      val v = data.asInstanceOf[js.BigInt]
+      CUnsignedBigInt(new BigInteger(v.toString(16), 16))
     case sigma.GroupElementRType =>
       val ge = data.asInstanceOf[GroupElement]
       CGroupElement(ge.point)
@@ -121,6 +124,9 @@ object Value extends js.Object {
     case sigma.BigIntRType =>
       val hex = value.asInstanceOf[sigma.BigInt].toBigInteger.toString(10)
       js.BigInt(hex)
+    case sigma.UnsignedBigIntRType =>
+      val hex = value.asInstanceOf[sigma.BigInt].toBigInteger.toString(10)
+      js.BigInt(hex)
     case sigma.GroupElementRType =>
       val point = value.asInstanceOf[CGroupElement].wrappedValue.asInstanceOf[Platform.Ecp]
       new GroupElement(point)
diff --git a/data/shared/src/main/scala/sigma/ast/methods.scala b/data/shared/src/main/scala/sigma/ast/methods.scala
index 9b0e5e8584..73e21b4564 100644
--- a/data/shared/src/main/scala/sigma/ast/methods.scala
+++ b/data/shared/src/main/scala/sigma/ast/methods.scala
@@ -540,7 +540,6 @@ case object SUnsignedBigIntMethods extends SNumericTypeMethods {
   // todo: costing
   final val ModInverseCostInfo = ToNBitsCostInfo
 
-  // todo: check ids before and after merging with other PRs introducing new methods for Numeric
   val ModInverseMethod = SMethod(this, "modInverse", SFunc(Array(this.ownerType, this.ownerType), this.ownerType), 14, ModInverseCostInfo.costKind)
     .withIRInfo(MethodCallIrBuilder)
     .withInfo(MethodCall, "")
diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/GraphIRReflection.scala b/sc/shared/src/main/scala/sigma/compiler/ir/GraphIRReflection.scala
index 8f461e502e..a161a034f5 100644
--- a/sc/shared/src/main/scala/sigma/compiler/ir/GraphIRReflection.scala
+++ b/sc/shared/src/main/scala/sigma/compiler/ir/GraphIRReflection.scala
@@ -120,6 +120,50 @@ object GraphIRReflection {
     )
   }
 
+  { val clazz = classOf[SigmaDsl#UnsignedBigInt]
+    val ctx = null.asInstanceOf[SigmaDsl] // ok! type level only
+    registerClassEntry(clazz,
+      methods = Map(
+        mkMethod(clazz, "add", Array[Class[_]](classOf[Base#Ref[_]])) { (obj, args) =>
+          obj.asInstanceOf[ctx.UnsignedBigInt].add(args(0).asInstanceOf[ctx.Ref[ctx.UnsignedBigInt]])
+        },
+        mkMethod(clazz, "max", Array[Class[_]](classOf[Base#Ref[_]])) { (obj, args) =>
+          obj.asInstanceOf[ctx.UnsignedBigInt].max(args(0).asInstanceOf[ctx.Ref[ctx.UnsignedBigInt]])
+        },
+        mkMethod(clazz, "min", Array[Class[_]](classOf[Base#Ref[_]])) { (obj, args) =>
+          obj.asInstanceOf[ctx.UnsignedBigInt].min(args(0).asInstanceOf[ctx.Ref[ctx.UnsignedBigInt]])
+        },
+        mkMethod(clazz, "subtract", Array[Class[_]](classOf[Base#Ref[_]])) { (obj, args) =>
+          obj.asInstanceOf[ctx.UnsignedBigInt].subtract(args(0).asInstanceOf[ctx.Ref[ctx.UnsignedBigInt]])
+        },
+        mkMethod(clazz, "multiply", Array[Class[_]](classOf[Base#Ref[_]])) { (obj, args) =>
+          obj.asInstanceOf[ctx.UnsignedBigInt].multiply(args(0).asInstanceOf[ctx.Ref[ctx.UnsignedBigInt]])
+        },
+        mkMethod(clazz, "mod", Array[Class[_]](classOf[Base#Ref[_]])) { (obj, args) =>
+          obj.asInstanceOf[ctx.UnsignedBigInt].mod(args(0).asInstanceOf[ctx.Ref[ctx.UnsignedBigInt]])
+        },
+        mkMethod(clazz, "divide", Array[Class[_]](classOf[Base#Ref[_]])) { (obj, args) =>
+          obj.asInstanceOf[ctx.UnsignedBigInt].divide(args(0).asInstanceOf[ctx.Ref[ctx.UnsignedBigInt]])
+        },
+        mkMethod(clazz, "plusMod", Array[Class[_]](classOf[Base#Ref[_]])) { (obj, args) =>
+          obj.asInstanceOf[ctx.UnsignedBigInt].plusMod(args(0).asInstanceOf[ctx.Ref[ctx.UnsignedBigInt]], args(1).asInstanceOf[ctx.Ref[ctx.UnsignedBigInt]])
+        },
+        mkMethod(clazz, "subtractMod", Array[Class[_]](classOf[Base#Ref[_]])) { (obj, args) =>
+          obj.asInstanceOf[ctx.UnsignedBigInt].subtractMod(args(0).asInstanceOf[ctx.Ref[ctx.UnsignedBigInt]], args(1).asInstanceOf[ctx.Ref[ctx.UnsignedBigInt]])
+        },
+        mkMethod(clazz, "multiplyMod", Array[Class[_]](classOf[Base#Ref[_]])) { (obj, args) =>
+          obj.asInstanceOf[ctx.UnsignedBigInt].multiplyMod(args(0).asInstanceOf[ctx.Ref[ctx.UnsignedBigInt]], args(1).asInstanceOf[ctx.Ref[ctx.UnsignedBigInt]])
+        },
+        mkMethod(clazz, "mod", Array[Class[_]](classOf[Base#Ref[_]])) { (obj, args) =>
+          obj.asInstanceOf[ctx.UnsignedBigInt].mod(args(0).asInstanceOf[ctx.Ref[ctx.UnsignedBigInt]])
+        },
+        mkMethod(clazz, "modInverse", Array[Class[_]](classOf[Base#Ref[_]])) { (obj, args) =>
+          obj.asInstanceOf[ctx.UnsignedBigInt].modInverse(args(0).asInstanceOf[ctx.Ref[ctx.UnsignedBigInt]])
+        }
+      )
+    )
+  }
+
   { val clazz = classOf[sigma.compiler.ir.wrappers.sigma.Colls#CollBuilder]
     val ctx = null.asInstanceOf[IRContext] // ok! type level only
     registerClassEntry(clazz,
diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/SigmaDslImpl.scala b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/SigmaDslImpl.scala
index d9dbea493a..f82132d9a0 100644
--- a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/SigmaDslImpl.scala
+++ b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/SigmaDslImpl.scala
@@ -403,7 +403,6 @@ object UnsignedBigInt extends EntityObject("UnsignedBigInt") {
     }
   }
 
-
   implicit object LiftableUnsignedBigInt extends Liftable[SUnsignedBigInt, UnsignedBigInt] {
     lazy val eW: Elem[UnsignedBigInt] = unsignedBigIntElement
     lazy val sourceType: RType[SUnsignedBigInt] = {
@@ -522,7 +521,7 @@ object UnsignedBigInt extends EntityObject("UnsignedBigInt") {
     override protected def collectMethods: Map[RMethod, MethodDesc] = {
       super.collectMethods ++
         Elem.declaredMethods(RClass(classOf[UnsignedBigInt]), RClass(classOf[UnsignedBigInt]), Set(
-          "add", "subtract", "multiply", "divide", "mod", "min", "max"
+          "add", "subtract", "multiply", "divide", "mod", "min", "max", "plusMod", "subtractMod", "multiplyMod"
         ))
     }
   }

From 933b2cc9e3854dc9746a6cbcefca8812b75f9c28 Mon Sep 17 00:00:00 2001
From: Alexander Chepurnoy 
Date: Sat, 2 Nov 2024 02:07:22 +0300
Subject: [PATCH 275/314] improving UnsignedBigInt support in JS

---
 core/js/src/main/scala/sigma/js/Type.scala    |  3 ++
 .../src/main/scala/sigma/data/CBigInt.scala   |  5 +--
 .../shared/src/main/scala/sigma/package.scala |  2 +-
 .../sigma/reflection/ReflectionData.scala     | 35 ++++++++++---------
 data/js/src/main/scala/sigma/js/Value.scala   |  2 ++
 .../src/main/scala/sigma/ast/methods.scala    |  5 ++-
 .../scala/sigma/data/CSigmaDslBuilder.scala   |  9 +++--
 .../scala/sigma/data/DataValueComparer.scala  |  1 +
 .../scala/sigma/serialization/OpCodes.scala   |  1 +
 .../org/ergoplatform/dsl/ContractSyntax.scala |  1 +
 .../sigma/compiler/ir/GraphIRReflection.scala |  6 ++--
 .../ir/wrappers/sigma/impl/SigmaDslImpl.scala |  3 +-
 .../test/scala/sigma/SigmaDslTesting.scala    |  3 +-
 .../utxo/BasicOpsSpecification.scala          |  1 -
 .../org/ergoplatform/sdk/JavaHelpers.scala    | 10 ------
 .../org/ergoplatform/sdk/utils/Zero.scala     |  5 ++-
 16 files changed, 49 insertions(+), 43 deletions(-)

diff --git a/core/js/src/main/scala/sigma/js/Type.scala b/core/js/src/main/scala/sigma/js/Type.scala
index b323273a0c..069cca3e1e 100644
--- a/core/js/src/main/scala/sigma/js/Type.scala
+++ b/core/js/src/main/scala/sigma/js/Type.scala
@@ -35,6 +35,9 @@ object Type extends js.Object {
   /** Descriptor of ErgoScript type BigInt. */
   val BigInt = new Type(sigma.BigIntRType)
 
+  /** Descriptor of ErgoScript type BigInt. */
+  val UnsignedBigInt = new Type(sigma.UnsignedBigIntRType)
+
   /** Descriptor of ErgoScript type GroupElement. */
   val GroupElement = new Type(sigma.GroupElementRType)
 
diff --git a/core/shared/src/main/scala/sigma/data/CBigInt.scala b/core/shared/src/main/scala/sigma/data/CBigInt.scala
index 8212955103..3787e78a86 100644
--- a/core/shared/src/main/scala/sigma/data/CBigInt.scala
+++ b/core/shared/src/main/scala/sigma/data/CBigInt.scala
@@ -69,9 +69,9 @@ case class CBigInt(override val wrappedValue: BigInteger) extends BigInt with Wr
   }
 }
 
-/** A default implementation of [[BigInt]] interface.
+/** A default implementation of [[UnsignedBigInt]] interface.
   *
-  * @see [[BigInt]] for detailed descriptions
+  * @see [[UnsignedBigInt]] for detailed descriptions
   */
 case class CUnsignedBigInt(override val wrappedValue: BigInteger) extends UnsignedBigInt with WrapperOf[BigInteger] {
 
@@ -144,4 +144,5 @@ case class CUnsignedBigInt(override val wrappedValue: BigInteger) extends Unsign
   override def toSigned(): BigInt = {
     CBigInt(wrappedValue.toSignedBigIntValueExact)
   }
+
 }
diff --git a/core/shared/src/main/scala/sigma/package.scala b/core/shared/src/main/scala/sigma/package.scala
index 4473bd338f..41f90b33bb 100644
--- a/core/shared/src/main/scala/sigma/package.scala
+++ b/core/shared/src/main/scala/sigma/package.scala
@@ -26,7 +26,7 @@ package object sigma {
   implicit val StringType : RType[String]  = GeneralType(StringClassTag)
 
   implicit val BigIntRType      : RType[BigInt]       = GeneralType(BigIntClassTag)
-  implicit val UnsignedBigIntRType      : RType[UnsignedBigInt]       = GeneralType(UnsignedBigIntClassTag)
+  implicit val UnsignedBigIntRType : RType[UnsignedBigInt] = GeneralType(UnsignedBigIntClassTag)
   implicit val GroupElementRType: RType[GroupElement] = GeneralType(GroupElementClassTag)
   implicit val SigmaPropRType   : RType[SigmaProp]    = GeneralType(SigmaPropClassTag)
   implicit val SigmaBooleanRType: RType[SigmaBoolean] = GeneralType(SigmaBooleanClassTag)
diff --git a/core/shared/src/main/scala/sigma/reflection/ReflectionData.scala b/core/shared/src/main/scala/sigma/reflection/ReflectionData.scala
index ef8e52e6cd..204792ee50 100644
--- a/core/shared/src/main/scala/sigma/reflection/ReflectionData.scala
+++ b/core/shared/src/main/scala/sigma/reflection/ReflectionData.scala
@@ -130,44 +130,45 @@ object ReflectionData {
   }
   {
     val clazz      = classOf[sigma.UnsignedBigInt]
-    val paramTypes = Array[Class[_]](clazz)
+    val oneParamTypes = Array[Class[_]](clazz)
+    val twoParamTypes = Array[Class[_]](clazz, clazz)
     registerClassEntry(clazz,
       methods = Map(
-        mkMethod(clazz, "add", paramTypes) { (obj, args) =>
+        mkMethod(clazz, "add", oneParamTypes) { (obj, args) =>
           obj.asInstanceOf[UnsignedBigInt].add(args(0).asInstanceOf[UnsignedBigInt])
         },
-        mkMethod(clazz, "max", paramTypes) { (obj, args) =>
+        mkMethod(clazz, "max", oneParamTypes) { (obj, args) =>
           obj.asInstanceOf[UnsignedBigInt].max(args(0).asInstanceOf[UnsignedBigInt])
         },
-        mkMethod(clazz, "min", paramTypes) { (obj, args) =>
+        mkMethod(clazz, "min", oneParamTypes) { (obj, args) =>
           obj.asInstanceOf[UnsignedBigInt].min(args(0).asInstanceOf[UnsignedBigInt])
         },
-        mkMethod(clazz, "subtract", paramTypes) { (obj, args) =>
+        mkMethod(clazz, "subtract", oneParamTypes) { (obj, args) =>
           obj.asInstanceOf[UnsignedBigInt].subtract(args(0).asInstanceOf[UnsignedBigInt])
         },
-        mkMethod(clazz, "multiply", paramTypes) { (obj, args) =>
+        mkMethod(clazz, "multiply", oneParamTypes) { (obj, args) =>
           obj.asInstanceOf[UnsignedBigInt].multiply(args(0).asInstanceOf[UnsignedBigInt])
         },
-        mkMethod(clazz, "mod", paramTypes) { (obj, args) =>
+        mkMethod(clazz, "mod", oneParamTypes) { (obj, args) =>
           obj.asInstanceOf[UnsignedBigInt].mod(args(0).asInstanceOf[UnsignedBigInt])
         },
-        mkMethod(clazz, "divide", paramTypes) { (obj, args) =>
+        mkMethod(clazz, "divide", oneParamTypes) { (obj, args) =>
           obj.asInstanceOf[UnsignedBigInt].divide(args(0).asInstanceOf[UnsignedBigInt])
         },
-        mkMethod(clazz, "plusMod", paramTypes) { (obj, args) =>
+        mkMethod(clazz, "mod", oneParamTypes) { (obj, args) =>
+          obj.asInstanceOf[UnsignedBigInt].mod(args(0).asInstanceOf[UnsignedBigInt])
+        },
+        mkMethod(clazz, "modInverse", oneParamTypes) { (obj, args) =>
+          obj.asInstanceOf[UnsignedBigInt].modInverse(args(0).asInstanceOf[UnsignedBigInt])
+        },
+        mkMethod(clazz, "plusMod", twoParamTypes) { (obj, args) =>
           obj.asInstanceOf[UnsignedBigInt].plusMod(args(0).asInstanceOf[UnsignedBigInt], args(1).asInstanceOf[UnsignedBigInt])
         },
-        mkMethod(clazz, "subtractMod", paramTypes) { (obj, args) =>
+        mkMethod(clazz, "subtractMod", twoParamTypes) { (obj, args) =>
           obj.asInstanceOf[UnsignedBigInt].subtractMod(args(0).asInstanceOf[UnsignedBigInt], args(1).asInstanceOf[UnsignedBigInt])
         },
-        mkMethod(clazz, "multiplyMod", paramTypes) { (obj, args) =>
+        mkMethod(clazz, "multiplyMod", twoParamTypes) { (obj, args) =>
           obj.asInstanceOf[UnsignedBigInt].multiplyMod(args(0).asInstanceOf[UnsignedBigInt], args(1).asInstanceOf[UnsignedBigInt])
-        },
-        mkMethod(clazz, "mod", paramTypes) { (obj, args) =>
-          obj.asInstanceOf[UnsignedBigInt].mod(args(0).asInstanceOf[UnsignedBigInt])
-        },
-        mkMethod(clazz, "modInverse", paramTypes) { (obj, args) =>
-          obj.asInstanceOf[UnsignedBigInt].modInverse(args(0).asInstanceOf[UnsignedBigInt])
         }
       )
     )
diff --git a/data/js/src/main/scala/sigma/js/Value.scala b/data/js/src/main/scala/sigma/js/Value.scala
index 77d6c8e104..1fedb30250 100644
--- a/data/js/src/main/scala/sigma/js/Value.scala
+++ b/data/js/src/main/scala/sigma/js/Value.scala
@@ -164,6 +164,8 @@ object Value extends js.Object {
       n
     case sigma.BigIntRType =>
       data.asInstanceOf[js.BigInt]
+    case sigma.UnsignedBigIntRType =>
+      data.asInstanceOf[js.BigInt]
     case sigma.GroupElementRType =>
       data.asInstanceOf[GroupElement]
     case sigma.SigmaPropRType =>
diff --git a/data/shared/src/main/scala/sigma/ast/methods.scala b/data/shared/src/main/scala/sigma/ast/methods.scala
index 73e21b4564..b64abfde1f 100644
--- a/data/shared/src/main/scala/sigma/ast/methods.scala
+++ b/data/shared/src/main/scala/sigma/ast/methods.scala
@@ -3,7 +3,7 @@ package sigma.ast
 import org.ergoplatform._
 import org.ergoplatform.validation._
 import sigma.Evaluation.stypeToRType
-import sigma._
+import sigma.{UnsignedBigInt, _}
 import sigma.ast.SCollection.{SBooleanArray, SBoxArray, SByteArray, SByteArray2, SHeaderArray}
 import sigma.ast.SMethod.{MethodCallIrBuilder, MethodCostFunc, javaMethodOf}
 import sigma.ast.SType.TypeCode
@@ -536,7 +536,6 @@ case object SUnsignedBigIntMethods extends SNumericTypeMethods {
   final val ToNBitsCostInfo = OperationCostInfo(
     FixedCost(JitCost(5)), NamedDesc("NBitsMethodCall"))
 
-
   // todo: costing
   final val ModInverseCostInfo = ToNBitsCostInfo
 
@@ -1008,7 +1007,7 @@ object SCollectionMethods extends MethodsContainer with MethodByNameUnapply {
          | \lst{f} to each element of this collection and concatenating the results.
         """.stripMargin, ArgInfo("f", "the function to apply to each element."))
 
-  /** We assume all flatMap body patterns have similar executon cost. */
+  /** We assume all flatMap body patterns have similar execution cost. */
   final val CheckFlatmapBody_Info = OperationCostInfo(
     PerItemCost(baseCost = JitCost(20), perChunkCost = JitCost(20), chunkSize = 1),
     NamedDesc("CheckFlatmapBody"))
diff --git a/data/shared/src/main/scala/sigma/data/CSigmaDslBuilder.scala b/data/shared/src/main/scala/sigma/data/CSigmaDslBuilder.scala
index aebc95dd00..661cd183a1 100644
--- a/data/shared/src/main/scala/sigma/data/CSigmaDslBuilder.scala
+++ b/data/shared/src/main/scala/sigma/data/CSigmaDslBuilder.scala
@@ -5,9 +5,8 @@ import org.ergoplatform.ErgoBox
 import org.ergoplatform.validation.ValidationRules
 import scorex.crypto.hash.{Blake2b256, Sha256}
 import scorex.utils.{Ints, Longs}
-import sigma.ast.{AtLeast, SBigInt, SubstConstants}
+import sigma.ast.{AtLeast, SBigInt, SType, SUnsignedBigInt, SubstConstants}
 import scorex.utils.Longs
-import sigma.ast.{AtLeast, SType, SubstConstants}
 import sigma.crypto.{CryptoConstants, EcPointType, Ecp}
 import sigma.eval.Extensions.EvalCollOps
 import sigma.serialization.{DataSerializer, GroupElementSerializer, SigmaSerializer}
@@ -235,7 +234,11 @@ class CSigmaDslBuilder extends SigmaDslBuilder { dsl =>
           throw SerializerException(s"BigInt value doesn't not fit into ${SBigInt.MaxSizeInBytes} bytes in fromBigEndianBytes")
         }
         CBigInt(new BigInteger(bytes.toArray).toSignedBigIntValueExact).asInstanceOf[T]
-      // todo: UnsignedBitInt
+      case sigma.UnsignedBigIntRType =>
+        if (bytes.length > SUnsignedBigInt.MaxSizeInBytes) {
+          throw SerializerException(s"BigInt value doesn't not fit into ${SBigInt.MaxSizeInBytes} bytes in fromBigEndianBytes")
+        }
+        CUnsignedBigInt(new BigInteger(bytes.toArray).toSignedBigIntValueExact).asInstanceOf[T]
       case _ => throw new IllegalArgumentException("Unsupported type provided in fromBigEndianBytes")
     }
   }
diff --git a/data/shared/src/main/scala/sigma/data/DataValueComparer.scala b/data/shared/src/main/scala/sigma/data/DataValueComparer.scala
index e525b8f074..d44f3f8d68 100644
--- a/data/shared/src/main/scala/sigma/data/DataValueComparer.scala
+++ b/data/shared/src/main/scala/sigma/data/DataValueComparer.scala
@@ -139,6 +139,7 @@ object DataValueComparer {
   val descriptors: AVHashMap[RType[_], (OperationCostInfo[FixedCost], OperationCostInfo[PerItemCost])] =
     AVHashMap.fromSeq(Array[(RType[_], (OperationCostInfo[FixedCost], OperationCostInfo[PerItemCost]))](
       (BigIntRType, (EQ_BigInt, EQ_COA_BigInt)),
+      (UnsignedBigIntRType, (EQ_BigInt, EQ_COA_BigInt)),
       (GroupElementRType, (EQ_GroupElement, EQ_COA_GroupElement)),
       (AvlTreeRType, (EQ_AvlTree, EQ_COA_AvlTree)),
       (BoxRType, (EQ_Box, EQ_COA_Box)),
diff --git a/data/shared/src/main/scala/sigma/serialization/OpCodes.scala b/data/shared/src/main/scala/sigma/serialization/OpCodes.scala
index 70050d00ba..c4647669fa 100644
--- a/data/shared/src/main/scala/sigma/serialization/OpCodes.scala
+++ b/data/shared/src/main/scala/sigma/serialization/OpCodes.scala
@@ -153,6 +153,7 @@ object OpCodes {
   val OptionIsDefinedCode: OpCode = newOpCode(118)
 
   // Modular arithmetic operations codes
+  // todo: remove?
   val ModQCode     : OpCode = newOpCode(119)
   val PlusModQCode : OpCode = newOpCode(120)
   val MinusModQCode: OpCode = newOpCode(121)
diff --git a/sc/shared/src/main/scala/org/ergoplatform/dsl/ContractSyntax.scala b/sc/shared/src/main/scala/org/ergoplatform/dsl/ContractSyntax.scala
index 11cbaff739..2554489340 100644
--- a/sc/shared/src/main/scala/org/ergoplatform/dsl/ContractSyntax.scala
+++ b/sc/shared/src/main/scala/org/ergoplatform/dsl/ContractSyntax.scala
@@ -55,6 +55,7 @@ trait ContractSyntax { contract: SigmaContract =>
       case _: String => StringType
       case _: Unit => UnitType
       case _: sigma.BigInt => BigIntRType
+      case _: sigma.BigInt => UnsignedBigIntRType
       case _: GroupElement => GroupElementRType
       case _: ErgoBox => syntax.ErgoBoxRType // TODO remove this RType
       case _: Box => BoxRType
diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/GraphIRReflection.scala b/sc/shared/src/main/scala/sigma/compiler/ir/GraphIRReflection.scala
index a161a034f5..78e1c09ffa 100644
--- a/sc/shared/src/main/scala/sigma/compiler/ir/GraphIRReflection.scala
+++ b/sc/shared/src/main/scala/sigma/compiler/ir/GraphIRReflection.scala
@@ -145,13 +145,13 @@ object GraphIRReflection {
         mkMethod(clazz, "divide", Array[Class[_]](classOf[Base#Ref[_]])) { (obj, args) =>
           obj.asInstanceOf[ctx.UnsignedBigInt].divide(args(0).asInstanceOf[ctx.Ref[ctx.UnsignedBigInt]])
         },
-        mkMethod(clazz, "plusMod", Array[Class[_]](classOf[Base#Ref[_]])) { (obj, args) =>
+        mkMethod(clazz, "plusMod", Array[Class[_]](classOf[Base#Ref[_]], classOf[Base#Ref[_]])) { (obj, args) =>
           obj.asInstanceOf[ctx.UnsignedBigInt].plusMod(args(0).asInstanceOf[ctx.Ref[ctx.UnsignedBigInt]], args(1).asInstanceOf[ctx.Ref[ctx.UnsignedBigInt]])
         },
-        mkMethod(clazz, "subtractMod", Array[Class[_]](classOf[Base#Ref[_]])) { (obj, args) =>
+        mkMethod(clazz, "subtractMod", Array[Class[_]](classOf[Base#Ref[_]], classOf[Base#Ref[_]])) { (obj, args) =>
           obj.asInstanceOf[ctx.UnsignedBigInt].subtractMod(args(0).asInstanceOf[ctx.Ref[ctx.UnsignedBigInt]], args(1).asInstanceOf[ctx.Ref[ctx.UnsignedBigInt]])
         },
-        mkMethod(clazz, "multiplyMod", Array[Class[_]](classOf[Base#Ref[_]])) { (obj, args) =>
+        mkMethod(clazz, "multiplyMod", Array[Class[_]](classOf[Base#Ref[_]], classOf[Base#Ref[_]])) { (obj, args) =>
           obj.asInstanceOf[ctx.UnsignedBigInt].multiplyMod(args(0).asInstanceOf[ctx.Ref[ctx.UnsignedBigInt]], args(1).asInstanceOf[ctx.Ref[ctx.UnsignedBigInt]])
         },
         mkMethod(clazz, "mod", Array[Class[_]](classOf[Base#Ref[_]])) { (obj, args) =>
diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/SigmaDslImpl.scala b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/SigmaDslImpl.scala
index f82132d9a0..e0376b4c91 100644
--- a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/SigmaDslImpl.scala
+++ b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/SigmaDslImpl.scala
@@ -521,7 +521,8 @@ object UnsignedBigInt extends EntityObject("UnsignedBigInt") {
     override protected def collectMethods: Map[RMethod, MethodDesc] = {
       super.collectMethods ++
         Elem.declaredMethods(RClass(classOf[UnsignedBigInt]), RClass(classOf[UnsignedBigInt]), Set(
-          "add", "subtract", "multiply", "divide", "mod", "min", "max", "plusMod", "subtractMod", "multiplyMod"
+          "add", "subtract", "multiply", "divide", "mod", "modInverse",
+          "min", "max", "plusMod", "subtractMod", "multiplyMod"
         ))
     }
   }
diff --git a/sc/shared/src/test/scala/sigma/SigmaDslTesting.scala b/sc/shared/src/test/scala/sigma/SigmaDslTesting.scala
index de9e080862..7f3f28b791 100644
--- a/sc/shared/src/test/scala/sigma/SigmaDslTesting.scala
+++ b/sc/shared/src/test/scala/sigma/SigmaDslTesting.scala
@@ -1376,6 +1376,7 @@ class SigmaDslTesting extends AnyPropSpec
         case IntType => arbInt
         case LongType => arbLong
         case BigIntRType => arbBigInt
+        case UnsignedBigIntRType => arbUnsignedBigInt
         case GroupElementRType => arbGroupElement
         case SigmaPropRType => arbSigmaProp
         case BoxRType => arbBox
@@ -1404,7 +1405,7 @@ class SigmaDslTesting extends AnyPropSpec
     */
   def updateArbitrary[A](t: RType[A], sampled: Sampled[A]) = {
     t match {
-      case BigIntRType | GroupElementRType | SigmaPropRType |
+      case BigIntRType | UnsignedBigIntRType | GroupElementRType | SigmaPropRType |
            BoxRType | PreHeaderRType | HeaderRType | AvlTreeRType |
            _: CollType[_] | _: PairType[_,_] | _: OptionType[_] =>
         val newArb = Arbitrary(Gen.oneOf(sampled.samples))
diff --git a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala
index 11d5e9b00a..60dac9c16a 100644
--- a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala
+++ b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala
@@ -154,7 +154,6 @@ class BasicOpsSpecification extends CompilerTestingCommons
     flexVerifier.verify(verifyEnv, tree, ctxExt, pr.proof, fakeMessage).get._1 shouldBe true
   }
 
-
   property("getVarFromInput") {
     def getVarTest(): Assertion = {
       val customExt = Map(
diff --git a/sdk/shared/src/main/scala/org/ergoplatform/sdk/JavaHelpers.scala b/sdk/shared/src/main/scala/org/ergoplatform/sdk/JavaHelpers.scala
index 14cdf7f6bb..a46e7490db 100644
--- a/sdk/shared/src/main/scala/org/ergoplatform/sdk/JavaHelpers.scala
+++ b/sdk/shared/src/main/scala/org/ergoplatform/sdk/JavaHelpers.scala
@@ -315,16 +315,6 @@ object JavaHelpers {
 
   def collRType[T](tItem: RType[T]): RType[Coll[T]] = sigma.collRType(tItem)
 
-  def BigIntRType: RType[sigma.BigInt] = sigma.BigIntRType
-
-  def GroupElementRType: RType[sigma.GroupElement] = sigma.GroupElementRType
-
-  def SigmaPropRType: RType[sigma.SigmaProp] = sigma.SigmaPropRType
-
-  def AvlTreeRType: RType[sigma.AvlTree] = sigma.AvlTreeRType
-
-  def BoxRType: RType[sigma.Box] = sigma.BoxRType
-
   def SigmaDsl: CSigmaDslBuilder = sigma.eval.SigmaDsl
 
   def collFrom(arr: Array[Byte]): Coll[Byte] = {
diff --git a/sdk/shared/src/main/scala/org/ergoplatform/sdk/utils/Zero.scala b/sdk/shared/src/main/scala/org/ergoplatform/sdk/utils/Zero.scala
index 78dfe2dc94..a337ad44a8 100644
--- a/sdk/shared/src/main/scala/org/ergoplatform/sdk/utils/Zero.scala
+++ b/sdk/shared/src/main/scala/org/ergoplatform/sdk/utils/Zero.scala
@@ -1,7 +1,7 @@
 package org.ergoplatform.sdk.utils
 
 import org.ergoplatform.ErgoBox
-import sigma.data.{AvlTreeData, AvlTreeFlags, CAvlTree, CBigInt, CGroupElement, CSigmaProp, CollType, FuncType, OptionType, PairType, RType, TrivialProp, TupleType}
+import sigma.data.{AvlTreeData, AvlTreeFlags, CAvlTree, CBigInt, CGroupElement, CSigmaProp, CUnsignedBigInt, CollType, FuncType, OptionType, PairType, RType, TrivialProp, TupleType}
 import sigma.data.RType._
 import scorex.crypto.authds.avltree.batch.BatchAVLProver
 import scorex.crypto.hash.{Blake2b256, Digest32}
@@ -11,6 +11,7 @@ import sigma._
 import sigma.ast.ErgoTree
 import ErgoTree.HeaderType
 import sigma.crypto.CryptoConstants
+
 import java.math.BigInteger
 import scala.language.implicitConversions
 
@@ -48,6 +49,7 @@ object Zero extends ZeroLowPriority {
   implicit val IntIsZero: Zero[Int] = CZero(0)
   implicit val LongIsZero: Zero[Long] = CZero(0L)
   implicit val BigIntIsZero: Zero[BigInt] = CZero(CBigInt(BigInteger.ZERO))
+  implicit val UnsignedBigIntIsZero: Zero[UnsignedBigInt] = CZero(CUnsignedBigInt(BigInteger.ZERO))
   implicit val GroupElementIsZero: Zero[GroupElement] = CZero(CGroupElement(CryptoConstants.dlogGroup.identity))
   implicit val AvlTreeIsZero: Zero[AvlTree] = CZero({
     val avlProver = new BatchAVLProver[Digest32, Blake2b256.type](keyLength = 32, None)
@@ -88,6 +90,7 @@ object Zero extends ZeroLowPriority {
     case LongType => Zero[Long]
     case UnitType => Zero[Unit]
     case BigIntRType => Zero[BigInt]
+    case UnsignedBigIntRType => Zero[UnsignedBigInt]
     case BoxRType => Zero[Box]
     case GroupElementRType => Zero[GroupElement]
     case AvlTreeRType => Zero[AvlTree]

From 3a5c6d6d8d9029a5e002862a6e60c41973186a68 Mon Sep 17 00:00:00 2001
From: Alexander Chepurnoy 
Date: Mon, 4 Nov 2024 15:06:46 +0300
Subject: [PATCH 276/314] JS tests fixed

---
 .../sigma/reflection/ReflectionData.scala     | 27 +++++++++++++------
 .../scala/sigma/reflection/StaticImpl.scala   |  4 ++-
 .../sigma/compiler/ir/GraphIRReflection.scala | 12 +++++++++
 .../ir/wrappers/sigma/SigmaDslUnit.scala      |  2 +-
 .../ir/wrappers/sigma/impl/SigmaDslImpl.scala |  6 ++---
 .../scala/sigma/LanguageSpecificationV6.scala |  2 ++
 6 files changed, 40 insertions(+), 13 deletions(-)

diff --git a/core/shared/src/main/scala/sigma/reflection/ReflectionData.scala b/core/shared/src/main/scala/sigma/reflection/ReflectionData.scala
index 204792ee50..34bffbca34 100644
--- a/core/shared/src/main/scala/sigma/reflection/ReflectionData.scala
+++ b/core/shared/src/main/scala/sigma/reflection/ReflectionData.scala
@@ -101,35 +101,43 @@ object ReflectionData {
   }
   {
     val clazz      = classOf[sigma.BigInt]
-    val paramTypes = Array[Class[_]](clazz)
+    val noParamTypes = Array[Class[_]]()
+    val oneParamTypes = Array[Class[_]](clazz)
     registerClassEntry(clazz,
       methods = Map(
-        mkMethod(clazz, "add", paramTypes) { (obj, args) =>
+        mkMethod(clazz, "add", oneParamTypes) { (obj, args) =>
           obj.asInstanceOf[BigInt].add(args(0).asInstanceOf[BigInt])
         },
-        mkMethod(clazz, "max", paramTypes) { (obj, args) =>
+        mkMethod(clazz, "max", oneParamTypes) { (obj, args) =>
           obj.asInstanceOf[BigInt].max(args(0).asInstanceOf[BigInt])
         },
-        mkMethod(clazz, "min", paramTypes) { (obj, args) =>
+        mkMethod(clazz, "min", oneParamTypes) { (obj, args) =>
           obj.asInstanceOf[BigInt].min(args(0).asInstanceOf[BigInt])
         },
-        mkMethod(clazz, "subtract", paramTypes) { (obj, args) =>
+        mkMethod(clazz, "subtract", oneParamTypes) { (obj, args) =>
           obj.asInstanceOf[BigInt].subtract(args(0).asInstanceOf[BigInt])
         },
-        mkMethod(clazz, "multiply", paramTypes) { (obj, args) =>
+        mkMethod(clazz, "multiply", oneParamTypes) { (obj, args) =>
           obj.asInstanceOf[BigInt].multiply(args(0).asInstanceOf[BigInt])
         },
-        mkMethod(clazz, "mod", paramTypes) { (obj, args) =>
+        mkMethod(clazz, "mod", oneParamTypes) { (obj, args) =>
           obj.asInstanceOf[BigInt].mod(args(0).asInstanceOf[BigInt])
         },
-        mkMethod(clazz, "divide", paramTypes) { (obj, args) =>
+        mkMethod(clazz, "divide", oneParamTypes) { (obj, args) =>
           obj.asInstanceOf[BigInt].divide(args(0).asInstanceOf[BigInt])
+        },
+        mkMethod(clazz, "toUnsigned", noParamTypes) { (obj, _) =>
+          obj.asInstanceOf[BigInt].toUnsigned
+        },
+        mkMethod(clazz, "toUnsignedMod", Array[Class[_]](classOf[sigma.UnsignedBigInt])) { (obj, args) =>
+          obj.asInstanceOf[BigInt].toUnsignedMod(args(0).asInstanceOf[UnsignedBigInt])
         }
       )
     )
   }
   {
     val clazz      = classOf[sigma.UnsignedBigInt]
+    val noParamTypes = Array[Class[_]]()
     val oneParamTypes = Array[Class[_]](clazz)
     val twoParamTypes = Array[Class[_]](clazz, clazz)
     registerClassEntry(clazz,
@@ -169,6 +177,9 @@ object ReflectionData {
         },
         mkMethod(clazz, "multiplyMod", twoParamTypes) { (obj, args) =>
           obj.asInstanceOf[UnsignedBigInt].multiplyMod(args(0).asInstanceOf[UnsignedBigInt], args(1).asInstanceOf[UnsignedBigInt])
+        },
+        mkMethod(clazz, "toSigned", noParamTypes) { (obj, _) =>
+          obj.asInstanceOf[UnsignedBigInt].toSigned()
         }
       )
     )
diff --git a/core/shared/src/main/scala/sigma/reflection/StaticImpl.scala b/core/shared/src/main/scala/sigma/reflection/StaticImpl.scala
index e95eea1f59..6db911d9bc 100644
--- a/core/shared/src/main/scala/sigma/reflection/StaticImpl.scala
+++ b/core/shared/src/main/scala/sigma/reflection/StaticImpl.scala
@@ -72,7 +72,9 @@ class SRClass[T](val clazz: Class[T],
                          parameterTypes: Class[_]*): RMethod = {
     methods.get((name, parameterTypes)) match {
       case Some(m) => m
-      case _ => throw new NoSuchMethodException(s"${clazz.getName}.$name(${parameterTypes.map(_.getName).mkString(",")})")
+      case _ =>
+        println(methods)
+        throw new NoSuchMethodException(s"${clazz.getName}.$name(${parameterTypes.map(_.getName).mkString(",")})")
     }
   }
 
diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/GraphIRReflection.scala b/sc/shared/src/main/scala/sigma/compiler/ir/GraphIRReflection.scala
index 78e1c09ffa..ea665c247f 100644
--- a/sc/shared/src/main/scala/sigma/compiler/ir/GraphIRReflection.scala
+++ b/sc/shared/src/main/scala/sigma/compiler/ir/GraphIRReflection.scala
@@ -115,6 +115,12 @@ object GraphIRReflection {
         },
         mkMethod(clazz, "divide", Array[Class[_]](classOf[Base#Ref[_]])) { (obj, args) =>
           obj.asInstanceOf[ctx.BigInt].divide(args(0).asInstanceOf[ctx.Ref[ctx.BigInt]])
+        },
+        mkMethod(clazz, "toUnsigned", Array[Class[_]]()) { (obj, _) =>
+          obj.asInstanceOf[ctx.BigInt].toUnsigned()
+        },
+        mkMethod(clazz, "toUnsignedMod", Array[Class[_]](classOf[Base#Ref[_]])) { (obj, args) =>
+          obj.asInstanceOf[ctx.BigInt].toUnsignedMod(args(0).asInstanceOf[ctx.Ref[ctx.UnsignedBigInt]])
         }
       )
     )
@@ -159,6 +165,9 @@ object GraphIRReflection {
         },
         mkMethod(clazz, "modInverse", Array[Class[_]](classOf[Base#Ref[_]])) { (obj, args) =>
           obj.asInstanceOf[ctx.UnsignedBigInt].modInverse(args(0).asInstanceOf[ctx.Ref[ctx.UnsignedBigInt]])
+        },
+        mkMethod(clazz, "toSigned", Array[Class[_]]()) { (obj, _) =>
+          obj.asInstanceOf[ctx.UnsignedBigInt].toSigned
         }
       )
     )
@@ -410,6 +419,9 @@ object GraphIRReflection {
         mkMethod(clazz, "exp", Array[Class[_]](classOf[Base#Ref[_]])) { (obj, args) =>
           obj.asInstanceOf[ctx.GroupElement].exp(args(0).asInstanceOf[ctx.Ref[ctx.BigInt]])
         },
+        mkMethod(clazz, "expUnsigned", Array[Class[_]](classOf[Base#Ref[_]])) { (obj, args) =>
+          obj.asInstanceOf[ctx.GroupElement].expUnsigned(args(0).asInstanceOf[ctx.Ref[ctx.UnsignedBigInt]])
+        },
         mkMethod(clazz, "multiply", Array[Class[_]](classOf[Base#Ref[_]])) { (obj, args) =>
           obj.asInstanceOf[ctx.GroupElement].multiply(args(0).asInstanceOf[ctx.Ref[ctx.GroupElement]])
         },
diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/SigmaDslUnit.scala b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/SigmaDslUnit.scala
index 491a196f8d..f719bb6f8f 100644
--- a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/SigmaDslUnit.scala
+++ b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/SigmaDslUnit.scala
@@ -28,7 +28,7 @@ import scalan._
       def plusMod(that: Ref[UnsignedBigInt], m: Ref[UnsignedBigInt]): Ref[UnsignedBigInt]
       def subtractMod(that: Ref[UnsignedBigInt], m: Ref[UnsignedBigInt]): Ref[UnsignedBigInt]
       def multiplyMod(that: Ref[UnsignedBigInt], m: Ref[UnsignedBigInt]): Ref[UnsignedBigInt]
-      def toSigned: Ref[BigInt]
+      def toSigned(): Ref[BigInt]
     };
     trait GroupElement extends Def[GroupElement] {
       def exp(k: Ref[BigInt]): Ref[GroupElement];
diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/SigmaDslImpl.scala b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/SigmaDslImpl.scala
index e0376b4c91..576f4138a3 100644
--- a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/SigmaDslImpl.scala
+++ b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/SigmaDslImpl.scala
@@ -395,7 +395,7 @@ object UnsignedBigInt extends EntityObject("UnsignedBigInt") {
         true, false, element[UnsignedBigInt]))
     }
 
-    override def toSigned: Ref[BigInt] = {
+    override def toSigned(): Ref[BigInt] = {
       asRep[BigInt](mkMethodCall(self,
         UnsignedBigIntClass.getMethod("toSigned"),
         Array[AnyRef](),
@@ -499,7 +499,7 @@ object UnsignedBigInt extends EntityObject("UnsignedBigInt") {
         true, true, element[UnsignedBigInt]))
     }
 
-    def toSigned: Ref[BigInt] = {
+    def toSigned(): Ref[BigInt] = {
       asRep[BigInt](mkMethodCall(source,
         UnsignedBigIntClass.getMethod("toSigned"),
         Array[AnyRef](),
@@ -522,7 +522,7 @@ object UnsignedBigInt extends EntityObject("UnsignedBigInt") {
       super.collectMethods ++
         Elem.declaredMethods(RClass(classOf[UnsignedBigInt]), RClass(classOf[UnsignedBigInt]), Set(
           "add", "subtract", "multiply", "divide", "mod", "modInverse",
-          "min", "max", "plusMod", "subtractMod", "multiplyMod"
+          "min", "max", "plusMod", "subtractMod", "multiplyMod", "toSigned"
         ))
     }
   }
diff --git a/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala b/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala
index 15ce673332..9750c56b01 100644
--- a/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala
+++ b/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala
@@ -1950,4 +1950,6 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite =>
     )
   }
 
+
+
 }

From b1d2b1799f57b8314841b690957c27961eb8e706 Mon Sep 17 00:00:00 2001
From: Alexander Chepurnoy 
Date: Mon, 4 Nov 2024 16:03:44 +0300
Subject: [PATCH 277/314] toUnsigned test in LSV6

---
 .../src/main/scala/sigma/data/CBigInt.scala   |  2 +-
 .../scala/sigma/LanguageSpecificationV6.scala | 22 ++++++++++++++++---
 2 files changed, 20 insertions(+), 4 deletions(-)

diff --git a/core/shared/src/main/scala/sigma/data/CBigInt.scala b/core/shared/src/main/scala/sigma/data/CBigInt.scala
index 3787e78a86..0313c197e5 100644
--- a/core/shared/src/main/scala/sigma/data/CBigInt.scala
+++ b/core/shared/src/main/scala/sigma/data/CBigInt.scala
@@ -58,7 +58,7 @@ case class CBigInt(override val wrappedValue: BigInteger) extends BigInt with Wr
 
   def toUnsigned: UnsignedBigInt = {
     if(this.wrappedValue.compareTo(BigInteger.ZERO) < 0){
-      throw new ArithmeticException("BigInteger argument for .toUnsigned is negative in");
+      throw new ArithmeticException("BigInteger argument for .toUnsigned is negative");
     } else {
       CUnsignedBigInt(this.wrappedValue)
     }
diff --git a/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala b/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala
index 9750c56b01..77e353ca25 100644
--- a/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala
+++ b/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala
@@ -11,14 +11,12 @@ import sigma.ast.ErgoTree.{HeaderType, ZeroHeader}
 import sigma.ast.SCollection.SByteArray
 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.{CBigInt, CBox, CHeader, CSigmaDslBuilder, ExactNumeric, PairOfCols, RType}
+import sigma.data.{AvlTreeData, AvlTreeFlags, CAnyValue, CAvlTree, CBigInt, CBox, CHeader, CSigmaDslBuilder, CSigmaProp, CUnsignedBigInt, ExactNumeric, PairOfCols, ProveDHTuple, 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.data.{RType}
 import sigma.serialization.ValueCodes.OpCode
 import sigma.util.Extensions.{BooleanOps, ByteOps, IntOps, LongOps}
 import sigmastate.exceptions.MethodNotFound
@@ -1950,6 +1948,24 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite =>
     )
   }
 
+  property("BigInt.toUnsigned") {
+    import sigma.data.OrderingOps.BigIntOrdering
 
+    val f = newFeature[BigInt, UnsignedBigInt](
+      { (xs: BigInt) => xs.toUnsigned },
+      """{(xs: BigInt) => xs.toUnsigned }""".stripMargin,
+      sinceVersion = VersionContext.V6SoftForkVersion
+    )
+
+    verifyCases(
+      Seq(
+        CBigInt(new BigInteger("5")) -> Expected(ExpectedResult(Success(CUnsignedBigInt(new BigInteger("5"))), None)),
+        CBigInt(new BigInteger("-5")) -> Expected(ExpectedResult(Failure(new ArithmeticException("BigInteger argument for .toUnsigned is negative")), None)),
+        CBigInt(new BigInteger("0")) -> Expected(ExpectedResult(Success(CUnsignedBigInt(new BigInteger("0"))), None))
+        // , CBigInt(BigInteger.valueOf(Long.MinValue)) -> Expected(ExpectedResult(), None))
+      ),
+      f
+    )
+  }
 
 }

From f84bce55ab481fe8f01da6b09461291463bb5730 Mon Sep 17 00:00:00 2001
From: Alexander Chepurnoy 
Date: Mon, 4 Nov 2024 19:47:21 +0300
Subject: [PATCH 278/314] toUnsignedMod test in LSV6, more tests in BOS

---
 .../src/main/scala/sigma/ast/methods.scala    |  4 +-
 .../main/scala/sigma/data/BigIntegerOps.scala |  5 ++
 .../ir/wrappers/sigma/impl/SigmaDslImpl.scala |  2 +-
 .../scala/sigma/LanguageSpecificationV6.scala | 49 +++++++++++++++++--
 .../utxo/BasicOpsSpecification.scala          | 38 ++++++++++++++
 5 files changed, 92 insertions(+), 6 deletions(-)

diff --git a/data/shared/src/main/scala/sigma/ast/methods.scala b/data/shared/src/main/scala/sigma/ast/methods.scala
index b64abfde1f..710cb9a0aa 100644
--- a/data/shared/src/main/scala/sigma/ast/methods.scala
+++ b/data/shared/src/main/scala/sigma/ast/methods.scala
@@ -258,8 +258,6 @@ object SNumericTypeMethods extends MethodsContainer {
       .withCost(costOfNumericCast)
       .withInfo(PropertyCall, "Converts this numeric value to \\lst{BigInt}")
 
-  // todo: ToUnsignedBigInt
-
   /** Cost of: 1) creating Byte collection from a numeric value */
   val ToBytes_CostKind = FixedCost(JitCost(5))
 
@@ -273,6 +271,8 @@ object SNumericTypeMethods extends MethodsContainer {
           case SIntMethods => IntIsExactIntegral.toBigEndianBytes(obj.asInstanceOf[Int])
           case SLongMethods => LongIsExactIntegral.toBigEndianBytes(obj.asInstanceOf[Long])
           case SBigIntMethods => obj.asInstanceOf[BigInt].toBytes
+          case SUnsignedBigIntMethods => obj.asInstanceOf[UnsignedBigInt].toBytes
+          // todo: test
         }
       })
       .withInfo(PropertyCall,
diff --git a/data/shared/src/main/scala/sigma/data/BigIntegerOps.scala b/data/shared/src/main/scala/sigma/data/BigIntegerOps.scala
index 8d272439f4..d849479a17 100644
--- a/data/shared/src/main/scala/sigma/data/BigIntegerOps.scala
+++ b/data/shared/src/main/scala/sigma/data/BigIntegerOps.scala
@@ -13,6 +13,11 @@ object OrderingOps {
     def compare(x: BigInt, y: BigInt) = x.compareTo(y)
   }
   implicit object BigIntOrdering extends BigIntOrdering
+
+  trait UnsignedBigIntOrdering extends Ordering[UnsignedBigInt] {
+    def compare(x: UnsignedBigInt, y: UnsignedBigInt) = x.compareTo(y)
+  }
+  implicit object UnsignedBigIntOrdering extends UnsignedBigIntOrdering
 }
 
 object NumericOps {
diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/SigmaDslImpl.scala b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/SigmaDslImpl.scala
index 576f4138a3..4b64b51ab4 100644
--- a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/SigmaDslImpl.scala
+++ b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/SigmaDslImpl.scala
@@ -195,7 +195,7 @@ object BigInt extends EntityObject("BigInt") {
 
     def toUnsignedMod(that: Ref[UnsignedBigInt]): Ref[UnsignedBigInt] = {
       asRep[UnsignedBigInt](mkMethodCall(source,
-        BigIntClass.getMethod("UnsignedBigInt", classOf[Sym]),
+        BigIntClass.getMethod("toUnsignedMod", classOf[Sym]),
         Array[AnyRef](that),
         true, true, element[UnsignedBigInt](unsignedBigIntElement)))
     }
diff --git a/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala b/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala
index 77e353ca25..f096a36eba 100644
--- a/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala
+++ b/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala
@@ -1952,8 +1952,17 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite =>
     import sigma.data.OrderingOps.BigIntOrdering
 
     val f = newFeature[BigInt, UnsignedBigInt](
-      { (xs: BigInt) => xs.toUnsigned },
-      """{(xs: BigInt) => xs.toUnsigned }""".stripMargin,
+      { (x: BigInt) => x.toUnsigned },
+      """{(x: BigInt) => x.toUnsigned }""".stripMargin,
+      FuncValue(
+        Array((1, SBigInt)),
+        MethodCall.typed[Value[SUnsignedBigInt.type]](
+          ValUse(1, SBigInt),
+          SBigIntMethods.ToUnsigned,
+          IndexedSeq(),
+          Map()
+        )
+      ),
       sinceVersion = VersionContext.V6SoftForkVersion
     )
 
@@ -1962,7 +1971,41 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite =>
         CBigInt(new BigInteger("5")) -> Expected(ExpectedResult(Success(CUnsignedBigInt(new BigInteger("5"))), None)),
         CBigInt(new BigInteger("-5")) -> Expected(ExpectedResult(Failure(new ArithmeticException("BigInteger argument for .toUnsigned is negative")), None)),
         CBigInt(new BigInteger("0")) -> Expected(ExpectedResult(Success(CUnsignedBigInt(new BigInteger("0"))), None))
-        // , CBigInt(BigInteger.valueOf(Long.MinValue)) -> Expected(ExpectedResult(), None))
+      ),
+      f
+    )
+  }
+
+
+  property("BigInt.toUnsignedMod") {
+    import sigma.data.OrderingOps.BigIntOrdering
+    import sigma.data.OrderingOps.UnsignedBigIntOrdering
+
+    val f = newFeature[(BigInt, UnsignedBigInt), UnsignedBigInt](
+      { (xs: (BigInt, UnsignedBigInt)) => xs._1.toUnsignedMod(xs._2) },
+      """{ (xs: (BigInt, UnsignedBigInt)) => xs._1.toUnsignedMod(xs._2) }""".stripMargin,
+      FuncValue(
+        Array((1, SPair(SBigInt, SUnsignedBigInt))),
+        MethodCall.typed[Value[SUnsignedBigInt.type]](
+          SelectField.typed[Value[SBigInt.type]](ValUse(1, SPair(SBigInt, SUnsignedBigInt)), 1.toByte),
+          SBigIntMethods.ToUnsignedMod,
+          Array(
+            SelectField.typed[Value[SUnsignedBigInt.type]](
+              ValUse(1, SPair(SBigInt, SUnsignedBigInt)),
+              2.toByte
+            )
+          ),
+          Map()
+        )
+      ),
+      sinceVersion = VersionContext.V6SoftForkVersion
+    )
+
+    verifyCases(
+      Seq(
+        (CBigInt(new BigInteger("50")), CUnsignedBigInt(new BigInteger("10"))) -> Expected(ExpectedResult(Success(CUnsignedBigInt(new BigInteger("0"))), None)),
+        (CBigInt(new BigInteger("50")), CUnsignedBigInt(new BigInteger("0"))) -> Expected(ExpectedResult(Failure(new ArithmeticException("BigInteger: modulus not positive")), None)),
+        (CBigInt(new BigInteger("50")), CUnsignedBigInt(new BigInteger("-10"))) -> Expected(ExpectedResult(Failure(new ArithmeticException("BigInteger: modulus not positive")), None))
       ),
       f
     )
diff --git a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala
index 60dac9c16a..9c5087e26a 100644
--- a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala
+++ b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala
@@ -276,6 +276,24 @@ class BasicOpsSpecification extends CompilerTestingCommons
     }
   }
 
+  property("unsigned bigint - attempt to create from negative value") {
+    def conversionTest() = {test("conversion", env, ext,
+      s"""{
+         |  val m = unsignedBigInt("-5")
+         |  m >= 0
+         | } """.stripMargin,
+      null,
+      true
+    )}
+
+    if (activatedVersionInTests < V6SoftForkVersion) {
+      an[Exception] should be thrownBy conversionTest()
+    } else {
+      an[sigma.exceptions.InvalidArguments] should be thrownBy conversionTest()
+    }
+  }
+
+
   property("signed -> unsigned bigint conversion - negative bigint - mod") {
     def conversionTest() = {test("conversion", env, ext,
       s"""{
@@ -295,6 +313,26 @@ class BasicOpsSpecification extends CompilerTestingCommons
     }
   }
 
+  property("signed -> unsigned bigint conversion - negative bigint - mod - 2") {
+    def conversionTest() = {test("conversion", env, ext,
+      s"""{
+         |  val t = (bigInt("-1"), bigInt("5"))
+         |  val b = t._1
+         |  val m = t._2
+         |  val ub = b.toUnsignedMod(m.toUnsigned)
+         |  ub >= 0
+         | } """.stripMargin,
+      null,
+      true
+    )}
+
+    if (activatedVersionInTests < V6SoftForkVersion) {
+      an[Exception] should be thrownBy conversionTest()
+    } else {
+      conversionTest()
+    }
+  }
+
   property("unsigned bigint - add") {
     def conversionTest() = {test("add", env, ext,
       s"""{

From 1496770a5004839ffde950a88c4e4fc72199d474 Mon Sep 17 00:00:00 2001
From: Alexander Chepurnoy 
Date: Tue, 5 Nov 2024 19:59:46 +0300
Subject: [PATCH 279/314] tests for .toBytes, UnsignedBigInt support added to
 to new Numeric methods

---
 .../src/main/scala/sigma/ast/methods.scala    |  8 +++++
 .../utxo/BasicOpsSpecification.scala          | 36 ++++++++++++++++++-
 2 files changed, 43 insertions(+), 1 deletion(-)

diff --git a/data/shared/src/main/scala/sigma/ast/methods.scala b/data/shared/src/main/scala/sigma/ast/methods.scala
index 710cb9a0aa..5d21e91b16 100644
--- a/data/shared/src/main/scala/sigma/ast/methods.scala
+++ b/data/shared/src/main/scala/sigma/ast/methods.scala
@@ -13,6 +13,7 @@ import sigma.ast.syntax.{SValue, ValueOps}
 import sigma.data.ExactIntegral.{ByteIsExactIntegral, IntIsExactIntegral, LongIsExactIntegral, ShortIsExactIntegral}
 import sigma.data.NumericOps.BigIntIsExactIntegral
 import sigma.data.OverloadHack.Overloaded1
+import sigma.data.UnsignedBigIntNumericOps.UnsignedBigIntIsExactIntegral
 import sigma.data.{DataValueComparer, KeyValueColl, Nullable, RType, SigmaConstants}
 import sigma.eval.{CostDetails, ErgoTreeEvaluator, TracedCost}
 import sigma.reflection.RClass
@@ -295,6 +296,7 @@ object SNumericTypeMethods extends MethodsContainer {
           case SIntMethods => IntIsExactIntegral.toBits(obj.asInstanceOf[Int])
           case SLongMethods => LongIsExactIntegral.toBits(obj.asInstanceOf[Long])
           case SBigIntMethods => BigIntIsExactIntegral.toBits(obj.asInstanceOf[BigInt])
+          case SUnsignedBigIntMethods => UnsignedBigIntIsExactIntegral.toBits(obj.asInstanceOf[UnsignedBigInt])
         }
       })
       .withInfo(PropertyCall,
@@ -315,6 +317,7 @@ object SNumericTypeMethods extends MethodsContainer {
         case SIntMethods => IntIsExactIntegral.bitwiseInverse(obj.asInstanceOf[Int])
         case SLongMethods => LongIsExactIntegral.bitwiseInverse(obj.asInstanceOf[Long])
         case SBigIntMethods => BigIntIsExactIntegral.bitwiseInverse(obj.asInstanceOf[BigInt])
+        case SUnsignedBigIntMethods => UnsignedBigIntIsExactIntegral.bitwiseInverse(obj.asInstanceOf[UnsignedBigInt])
       }
     })
     .withInfo(PropertyCall, desc = "Returns bitwise inverse of this numeric. ")
@@ -329,6 +332,7 @@ object SNumericTypeMethods extends MethodsContainer {
         case SIntMethods => IntIsExactIntegral.bitwiseOr(obj.asInstanceOf[Int], other.head.asInstanceOf[Int])
         case SLongMethods => LongIsExactIntegral.bitwiseOr(obj.asInstanceOf[Long], other.head.asInstanceOf[Long])
         case SBigIntMethods => BigIntIsExactIntegral.bitwiseOr(obj.asInstanceOf[BigInt], other.head.asInstanceOf[BigInt])
+        case SUnsignedBigIntMethods => UnsignedBigIntIsExactIntegral.bitwiseOr(obj.asInstanceOf[UnsignedBigInt], other.head.asInstanceOf[UnsignedBigInt])
       }
     })
     .withInfo(MethodCall,
@@ -345,6 +349,7 @@ object SNumericTypeMethods extends MethodsContainer {
         case SIntMethods => IntIsExactIntegral.bitwiseAnd(obj.asInstanceOf[Int], other.head.asInstanceOf[Int])
         case SLongMethods => LongIsExactIntegral.bitwiseAnd(obj.asInstanceOf[Long], other.head.asInstanceOf[Long])
         case SBigIntMethods => BigIntIsExactIntegral.bitwiseAnd(obj.asInstanceOf[BigInt], other.head.asInstanceOf[BigInt])
+        case SUnsignedBigIntMethods => UnsignedBigIntIsExactIntegral.bitwiseAnd(obj.asInstanceOf[UnsignedBigInt], other.head.asInstanceOf[UnsignedBigInt])
       }
     })
     .withInfo(MethodCall,
@@ -361,6 +366,7 @@ object SNumericTypeMethods extends MethodsContainer {
         case SIntMethods => IntIsExactIntegral.bitwiseXor(obj.asInstanceOf[Int], other.head.asInstanceOf[Int])
         case SLongMethods => LongIsExactIntegral.bitwiseXor(obj.asInstanceOf[Long], other.head.asInstanceOf[Long])
         case SBigIntMethods => BigIntIsExactIntegral.bitwiseXor(obj.asInstanceOf[BigInt], other.head.asInstanceOf[BigInt])
+        case SUnsignedBigIntMethods => UnsignedBigIntIsExactIntegral.bitwiseXor(obj.asInstanceOf[UnsignedBigInt], other.head.asInstanceOf[UnsignedBigInt])
       }
     })
     .withInfo(MethodCall,
@@ -377,6 +383,7 @@ object SNumericTypeMethods extends MethodsContainer {
         case SIntMethods => IntIsExactIntegral.shiftLeft(obj.asInstanceOf[Int], other.head.asInstanceOf[Int])
         case SLongMethods => LongIsExactIntegral.shiftLeft(obj.asInstanceOf[Long], other.head.asInstanceOf[Int])
         case SBigIntMethods => BigIntIsExactIntegral.shiftLeft(obj.asInstanceOf[BigInt], other.head.asInstanceOf[Int])
+        case SUnsignedBigIntMethods => UnsignedBigIntIsExactIntegral.shiftLeft(obj.asInstanceOf[UnsignedBigInt], other.head.asInstanceOf[Int])
       }
     })
     .withInfo(MethodCall,
@@ -396,6 +403,7 @@ object SNumericTypeMethods extends MethodsContainer {
         case SIntMethods => IntIsExactIntegral.shiftRight(obj.asInstanceOf[Int], other.head.asInstanceOf[Int])
         case SLongMethods => LongIsExactIntegral.shiftRight(obj.asInstanceOf[Long], other.head.asInstanceOf[Int])
         case SBigIntMethods => BigIntIsExactIntegral.shiftRight(obj.asInstanceOf[BigInt], other.head.asInstanceOf[Int])
+        case SUnsignedBigIntMethods => UnsignedBigIntIsExactIntegral.shiftRight(obj.asInstanceOf[UnsignedBigInt], other.head.asInstanceOf[Int])
       }
     })
     .withInfo(MethodCall,
diff --git a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala
index 9c5087e26a..dc95969b08 100644
--- a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala
+++ b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala
@@ -28,7 +28,7 @@ import sigmastate.interpreter.Interpreter._
 import sigma.ast.Apply
 import sigma.eval.EvalSettings
 import sigma.exceptions.InvalidType
-import sigma.serialization.ErgoTreeSerializer
+import sigma.serialization.{ErgoTreeSerializer, SerializerException}
 import sigma.interpreter.{ContextExtension, ProverResult}
 import sigmastate.utils.Helpers
 import sigmastate.utils.Helpers._
@@ -793,6 +793,24 @@ class BasicOpsSpecification extends CompilerTestingCommons
     }
   }
 
+
+  property("UnsignedBigInt.toBits") {
+    def toBitsTest() = test("UnsignedBigInt.toBits", env, ext,
+      s"""{
+         | val b = bigInt("${CryptoConstants.groupOrder}")
+         | val ba = b.toBits
+         | ba.size == 256
+         |}""".stripMargin,
+      null
+    )
+
+    if (VersionContext.current.isV6SoftForkActivated) {
+      toBitsTest()
+    } else {
+      an[SerializerException] shouldBe thrownBy(toBitsTest())
+    }
+  }
+
   property("BigInt.bitwiseInverse") {
     def bitwiseInverseTest(): Assertion = test("BigInt.bitwiseInverse", env, ext,
       s"""{
@@ -1497,6 +1515,22 @@ class BasicOpsSpecification extends CompilerTestingCommons
     }
   }
 
+  property("UnsignedBigInt.toBytes") {
+    def toBytesTest() = test("UnsignedBigInt.toBytes", env, ext,
+      s"""{
+         |   val l = bigInt("${CryptoConstants.groupOrder}")
+         |   l.toBytes.size == 32
+         | }""".stripMargin,
+      null
+    )
+
+    if (VersionContext.current.isV6SoftForkActivated) {
+      toBytesTest()
+    } else {
+      an[SerializerException] shouldBe thrownBy(toBytesTest())
+    }
+  }
+
   property("serialize - byte array") {
     def deserTest() = test("serialize", env, ext,
       s"""{

From ac4bbbce2a1f8696356bbc1cce79129523b51b5d Mon Sep 17 00:00:00 2001
From: Alexander Chepurnoy 
Date: Wed, 6 Nov 2024 00:41:28 +0300
Subject: [PATCH 280/314] unsigned encoding, .toBytes & .toBits tests passing

---
 .../main/scala/sigma/crypto/BigIntegers.scala | 16 +++---
 .../src/main/scala/sigma/data/CBigInt.scala   |  3 +-
 .../serialization/CoreDataSerializer.scala    |  9 ++--
 .../scala/sigma/data/CSigmaDslBuilder.scala   |  4 +-
 .../sigma/data/UnsignedBigIntegerOps.scala    |  2 +-
 .../sigma/compiler/ir/GraphBuilding.scala     | 51 ++++++++++---------
 .../utxo/BasicOpsSpecification.scala          | 20 ++++----
 7 files changed, 57 insertions(+), 48 deletions(-)
 rename {data => core}/shared/src/main/scala/sigma/crypto/BigIntegers.scala (90%)

diff --git a/data/shared/src/main/scala/sigma/crypto/BigIntegers.scala b/core/shared/src/main/scala/sigma/crypto/BigIntegers.scala
similarity index 90%
rename from data/shared/src/main/scala/sigma/crypto/BigIntegers.scala
rename to core/shared/src/main/scala/sigma/crypto/BigIntegers.scala
index 4465184580..54a6927924 100644
--- a/data/shared/src/main/scala/sigma/crypto/BigIntegers.scala
+++ b/core/shared/src/main/scala/sigma/crypto/BigIntegers.scala
@@ -13,8 +13,9 @@ object BigIntegers {
   private val MAX_ITERATIONS = 1000
 
   /** Create the given number of random bits.
+    *
     * @param bitLength the number of random bits to create.
-    * @param random a source of randomness.
+    * @param random    a source of randomness.
     * @return a byte array containing random bits.
     */
   @throws[IllegalArgumentException]
@@ -38,8 +39,8 @@ object BigIntegers {
     * @return a positive BigInteger
     */
   def createRandomBigInteger(
-      bitLength: Int,
-      random: SecureRandom): BigInteger = {
+                              bitLength: Int,
+                              random: SecureRandom): BigInteger = {
     new BigInteger(1, createRandom(bitLength, random))
   }
 
@@ -52,9 +53,9 @@ object BigIntegers {
     * @return a random BigInteger value in the range [min,max]
     */
   def createRandomInRange(
-      min: BigInteger,
-      max: BigInteger,
-      random: SecureRandom): BigInteger = {
+                           min: BigInteger,
+                           max: BigInteger,
+                           random: SecureRandom): BigInteger = {
     val cmp = min.compareTo(max)
     if (cmp >= 0) {
       if (cmp > 0) throw new IllegalArgumentException("'min' may not be greater than 'max'")
@@ -64,7 +65,7 @@ object BigIntegers {
     if (min.bitLength > max.bitLength / 2)
       return createRandomInRange(ZERO, max.subtract(min), random).add(min)
 
-    for ( _ <- 0 until MAX_ITERATIONS ) {
+    for (_ <- 0 until MAX_ITERATIONS) {
       val x = createRandomBigInteger(max.bitLength, random)
       if (x.compareTo(min) >= 0 && x.compareTo(max) <= 0) return x
     }
@@ -96,6 +97,7 @@ object BigIntegers {
 
   /** Converts a byte array to a BigInteger, treating the array as bits of the unsigned
     * integer.
+    *
     * @param buf the byte array to convert
     * @return the resulting positive BigInteger
     */
diff --git a/core/shared/src/main/scala/sigma/data/CBigInt.scala b/core/shared/src/main/scala/sigma/data/CBigInt.scala
index 0313c197e5..9292ada68a 100644
--- a/core/shared/src/main/scala/sigma/data/CBigInt.scala
+++ b/core/shared/src/main/scala/sigma/data/CBigInt.scala
@@ -1,5 +1,6 @@
 package sigma.data
 
+import sigma.crypto.BigIntegers
 import sigma.util.Extensions.BigIntegerOps
 import sigma.{BigInt, Coll, Colls, UnsignedBigInt}
 
@@ -83,7 +84,7 @@ case class CUnsignedBigInt(override val wrappedValue: BigInteger) extends Unsign
 
   override def toLong: Long = wrappedValue.toLongExact
 
-  override def toBytes: Coll[Byte] = Colls.fromArray(wrappedValue.toByteArray)
+  override def toBytes: Coll[Byte] = Colls.fromArray(BigIntegers.asUnsignedByteArray(wrappedValue))
 
   override def compareTo(that: UnsignedBigInt): Int =
     wrappedValue.compareTo(that.asInstanceOf[CUnsignedBigInt].wrappedValue)
diff --git a/core/shared/src/main/scala/sigma/serialization/CoreDataSerializer.scala b/core/shared/src/main/scala/sigma/serialization/CoreDataSerializer.scala
index 5aa7d7600a..0d705412fc 100644
--- a/core/shared/src/main/scala/sigma/serialization/CoreDataSerializer.scala
+++ b/core/shared/src/main/scala/sigma/serialization/CoreDataSerializer.scala
@@ -2,8 +2,9 @@ package sigma.serialization
 
 import debox.cfor
 import sigma.ast._
+import sigma.crypto.BigIntegers
 import sigma.data._
-import sigma.util.Extensions.{CoreAvlTreeOps, BigIntOps, GroupElementOps, SigmaPropOps}
+import sigma.util.Extensions.{BigIntOps, CoreAvlTreeOps, GroupElementOps, SigmaPropOps}
 import sigma.validation.ValidationRules.CheckSerializableTypeCode
 import sigma.{Evaluation, _}
 
@@ -34,7 +35,7 @@ class CoreDataSerializer {
       w.putUShort(data.length)
       w.putBytes(data)
     case SUnsignedBigInt =>  // todo: versioning
-      val data = v.asInstanceOf[CUnsignedBigInt].wrappedValue.toByteArray
+      val data = BigIntegers.asUnsignedByteArray(v.asInstanceOf[CUnsignedBigInt].wrappedValue)
       w.putUShort(data.length)
       w.putBytes(data)
     case SGroupElement =>
@@ -114,11 +115,11 @@ class CoreDataSerializer {
         CBigInt(new BigInteger(valueBytes))
       case SUnsignedBigInt =>  // todo: versioning
         val size: Short = r.getUShort().toShort
-        if (size > SBigInt.MaxSizeInBytes + 1) { //todo: use encoding with no sign bit
+        if (size > SBigInt.MaxSizeInBytes) {
           throw new SerializerException(s"BigInt value doesn't not fit into ${SBigInt.MaxSizeInBytes} bytes: $size")
         }
         val valueBytes = r.getBytes(size)
-        CUnsignedBigInt(new BigInteger(valueBytes))
+        CUnsignedBigInt(BigIntegers.fromUnsignedByteArray(valueBytes))
       case SGroupElement =>
         CGroupElement(GroupElementSerializer.parse(r))
       case SSigmaProp =>
diff --git a/data/shared/src/main/scala/sigma/data/CSigmaDslBuilder.scala b/data/shared/src/main/scala/sigma/data/CSigmaDslBuilder.scala
index 661cd183a1..89fcffb531 100644
--- a/data/shared/src/main/scala/sigma/data/CSigmaDslBuilder.scala
+++ b/data/shared/src/main/scala/sigma/data/CSigmaDslBuilder.scala
@@ -7,7 +7,7 @@ import scorex.crypto.hash.{Blake2b256, Sha256}
 import scorex.utils.{Ints, Longs}
 import sigma.ast.{AtLeast, SBigInt, SType, SUnsignedBigInt, SubstConstants}
 import scorex.utils.Longs
-import sigma.crypto.{CryptoConstants, EcPointType, Ecp}
+import sigma.crypto.{BigIntegers, CryptoConstants, EcPointType, Ecp}
 import sigma.eval.Extensions.EvalCollOps
 import sigma.serialization.{DataSerializer, GroupElementSerializer, SigmaSerializer}
 import sigma.serialization.{GroupElementSerializer, SerializerException, SigmaSerializer}
@@ -238,7 +238,7 @@ class CSigmaDslBuilder extends SigmaDslBuilder { dsl =>
         if (bytes.length > SUnsignedBigInt.MaxSizeInBytes) {
           throw SerializerException(s"BigInt value doesn't not fit into ${SBigInt.MaxSizeInBytes} bytes in fromBigEndianBytes")
         }
-        CUnsignedBigInt(new BigInteger(bytes.toArray).toSignedBigIntValueExact).asInstanceOf[T]
+        CUnsignedBigInt(BigIntegers.fromUnsignedByteArray(bytes.toArray)).asInstanceOf[T]
       case _ => throw new IllegalArgumentException("Unsupported type provided in fromBigEndianBytes")
     }
   }
diff --git a/data/shared/src/main/scala/sigma/data/UnsignedBigIntegerOps.scala b/data/shared/src/main/scala/sigma/data/UnsignedBigIntegerOps.scala
index abbee376a5..e66740b1ea 100644
--- a/data/shared/src/main/scala/sigma/data/UnsignedBigIntegerOps.scala
+++ b/data/shared/src/main/scala/sigma/data/UnsignedBigIntegerOps.scala
@@ -95,7 +95,7 @@ object UnsignedBigIntNumericOps {
       * For example, the `Int` value `0x12131415` would yield the
       * collection of bytes [0x12, 0x13, 0x14, 0x15]
       */
-    override def toBigEndianBytes(x: UnsignedBigInt): Coll[Byte] = ???
+    override def toBigEndianBytes(x: UnsignedBigInt): Coll[Byte] = x.toBytes
 
     /**
       * @return a numeric value which is inverse of `x` (every bit, including sign, is flipped)
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 6048d884d1..caeded999c 100644
--- a/sc/shared/src/main/scala/sigma/compiler/ir/GraphBuilding.scala
+++ b/sc/shared/src/main/scala/sigma/compiler/ir/GraphBuilding.scala
@@ -1032,28 +1032,6 @@ trait GraphBuilding extends Base with DefRewriting { IR: IRContext =>
               opt.filter(asRep[t => Boolean](argsV(0)))
             case _ => throwError()
           }
-          case (ubi: Ref[UnsignedBigInt]@unchecked, SUnsignedBigIntMethods) => method.name match {
-            case SUnsignedBigIntMethods.ModMethod.name =>
-              val m = asRep[UnsignedBigInt](argsV(0))
-              ubi.mod(m)
-            case SUnsignedBigIntMethods.ModInverseMethod.name =>
-              val m = asRep[UnsignedBigInt](argsV(0))
-              ubi.modInverse(m)
-            case SUnsignedBigIntMethods.PlusModMethod.name =>
-              val that = asRep[UnsignedBigInt](argsV(0))
-              val m = asRep[UnsignedBigInt](argsV(1))
-              ubi.plusMod(that, m)
-            case SUnsignedBigIntMethods.SubtractModMethod.name =>
-              val that = asRep[UnsignedBigInt](argsV(0))
-              val m = asRep[UnsignedBigInt](argsV(1))
-              ubi.subtractMod(that, m)
-            case SUnsignedBigIntMethods.MultiplyModMethod.name =>
-              val that = asRep[UnsignedBigInt](argsV(0))
-              val m = asRep[UnsignedBigInt](argsV(1))
-              ubi.multiplyMod(that, m)
-            case SUnsignedBigIntMethods.ToSignedMethod.name =>
-              ubi.toSigned
-          }
           case (ge: Ref[GroupElement]@unchecked, SGroupElementMethods) => method.name match {
             case SGroupElementMethods.GetEncodedMethod.name =>
               ge.getEncoded
@@ -1226,7 +1204,7 @@ trait GraphBuilding extends Base with DefRewriting { IR: IRContext =>
               g.fromBigEndianBytes(bytes)(cT)
             case _ => throwError()
           }
-          case (x: Ref[tNum], _: SNumericTypeMethods) => method.name match {
+          case (x: Ref[tNum], ms: SNumericTypeMethods) => method.name match {
             case SNumericTypeMethods.ToBytesMethod.name =>
               val op = NumericToBigEndianBytes(elemToExactNumeric(x.elem))
               ApplyUnOp(op, x)
@@ -1263,6 +1241,33 @@ trait GraphBuilding extends Base with DefRewriting { IR: IRContext =>
               val bi = asRep[BigInt](x)
               val m = asRep[UnsignedBigInt](argsV(0))
               bi.toUnsignedMod(m)
+
+            case SUnsignedBigIntMethods.ModMethod.name if ms.isInstanceOf[SUnsignedBigIntMethods.type] =>
+              val ubi = asRep[UnsignedBigInt](x)
+              val m = asRep[UnsignedBigInt](argsV(0))
+              ubi.mod(m)
+            case SUnsignedBigIntMethods.ModInverseMethod.name if ms.isInstanceOf[SUnsignedBigIntMethods.type] =>
+              val ubi = asRep[UnsignedBigInt](x)
+              val m = asRep[UnsignedBigInt](argsV(0))
+              ubi.modInverse(m)
+            case SUnsignedBigIntMethods.PlusModMethod.name if ms.isInstanceOf[SUnsignedBigIntMethods.type] =>
+              val ubi = asRep[UnsignedBigInt](x)
+              val that = asRep[UnsignedBigInt](argsV(0))
+              val m = asRep[UnsignedBigInt](argsV(1))
+              ubi.plusMod(that, m)
+            case SUnsignedBigIntMethods.SubtractModMethod.name if ms.isInstanceOf[SUnsignedBigIntMethods.type] =>
+              val ubi = asRep[UnsignedBigInt](x)
+              val that = asRep[UnsignedBigInt](argsV(0))
+              val m = asRep[UnsignedBigInt](argsV(1))
+              ubi.subtractMod(that, m)
+            case SUnsignedBigIntMethods.MultiplyModMethod.name if ms.isInstanceOf[SUnsignedBigIntMethods.type] =>
+              val ubi = asRep[UnsignedBigInt](x)
+              val that = asRep[UnsignedBigInt](argsV(0))
+              val m = asRep[UnsignedBigInt](argsV(1))
+              ubi.multiplyMod(that, m)
+            case SUnsignedBigIntMethods.ToSignedMethod.name if ms.isInstanceOf[SUnsignedBigIntMethods.type] =>
+              val ubi = asRep[UnsignedBigInt](x)
+              ubi.toSigned()
             case _ => throwError()
           }
           case _ => throwError(s"Type ${stypeToRType(obj.tpe).name} doesn't have methods")
diff --git a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala
index dc95969b08..9a7afd40a4 100644
--- a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala
+++ b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala
@@ -30,6 +30,7 @@ import sigma.eval.EvalSettings
 import sigma.exceptions.InvalidType
 import sigma.serialization.{ErgoTreeSerializer, SerializerException}
 import sigma.interpreter.{ContextExtension, ProverResult}
+import sigma.validation.ValidationException
 import sigmastate.utils.Helpers
 import sigmastate.utils.Helpers._
 
@@ -797,7 +798,7 @@ class BasicOpsSpecification extends CompilerTestingCommons
   property("UnsignedBigInt.toBits") {
     def toBitsTest() = test("UnsignedBigInt.toBits", env, ext,
       s"""{
-         | val b = bigInt("${CryptoConstants.groupOrder}")
+         | val b = unsignedBigInt("${CryptoConstants.groupOrder}")
          | val ba = b.toBits
          | ba.size == 256
          |}""".stripMargin,
@@ -807,7 +808,7 @@ class BasicOpsSpecification extends CompilerTestingCommons
     if (VersionContext.current.isV6SoftForkActivated) {
       toBitsTest()
     } else {
-      an[SerializerException] shouldBe thrownBy(toBitsTest())
+      an[ValidationException] shouldBe thrownBy(toBitsTest())
     }
   }
 
@@ -1516,18 +1517,17 @@ class BasicOpsSpecification extends CompilerTestingCommons
   }
 
   property("UnsignedBigInt.toBytes") {
-    def toBytesTest() = test("UnsignedBigInt.toBytes", env, ext,
-      s"""{
-         |   val l = bigInt("${CryptoConstants.groupOrder}")
-         |   l.toBytes.size == 32
-         | }""".stripMargin,
-      null
-    )
+    val script = s"""{
+                    |   val l = unsignedBigInt("${CryptoConstants.groupOrder}")
+                    |   l.toBytes.size == 32
+                    | }""".stripMargin
+
+    def toBytesTest() = test("UnsignedBigInt.toBytes", env, ext, script, null)
 
     if (VersionContext.current.isV6SoftForkActivated) {
       toBytesTest()
     } else {
-      an[SerializerException] shouldBe thrownBy(toBytesTest())
+      an[ValidationException] shouldBe thrownBy(toBytesTest())
     }
   }
 

From a87bfb307651b35d927e186d097512ddf8c675b3 Mon Sep 17 00:00:00 2001
From: Alexander Chepurnoy 
Date: Wed, 6 Nov 2024 01:06:09 +0300
Subject: [PATCH 281/314] bitwiseInverse

---
 .../sigma/data/UnsignedBigIntegerOps.scala      |  9 +++++++--
 .../sigmastate/utxo/BasicOpsSpecification.scala | 17 +++++++++++++++++
 2 files changed, 24 insertions(+), 2 deletions(-)

diff --git a/data/shared/src/main/scala/sigma/data/UnsignedBigIntegerOps.scala b/data/shared/src/main/scala/sigma/data/UnsignedBigIntegerOps.scala
index e66740b1ea..e0170b14df 100644
--- a/data/shared/src/main/scala/sigma/data/UnsignedBigIntegerOps.scala
+++ b/data/shared/src/main/scala/sigma/data/UnsignedBigIntegerOps.scala
@@ -1,6 +1,7 @@
 package sigma.data
 
 import sigma._
+import sigma.crypto.BigIntegers
 import sigma.data.UnsignedBigIntOrderingOps.UnsignedBigIntOrdering
 import sigma.eval.Extensions.IntExt
 
@@ -98,9 +99,13 @@ object UnsignedBigIntNumericOps {
     override def toBigEndianBytes(x: UnsignedBigInt): Coll[Byte] = x.toBytes
 
     /**
-      * @return a numeric value which is inverse of `x` (every bit, including sign, is flipped)
+      * @return a numeric value which is inverse of `x` (every bit is flipped)
       */
-    override def bitwiseInverse(x: UnsignedBigInt): UnsignedBigInt = ???
+    override def bitwiseInverse(x: UnsignedBigInt): UnsignedBigInt = {
+      val bytes = BigIntegers.asUnsignedByteArray(x.asInstanceOf[CUnsignedBigInt].wrappedValue)
+      val res: Array[Byte] = bytes.map(b => (b ^ Byte.MinValue).toByte)
+      CUnsignedBigInt(BigIntegers.fromUnsignedByteArray(res))
+    }
 
     /**
       * @return a numeric value which is `this | that`
diff --git a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala
index 9a7afd40a4..6c95071a0b 100644
--- a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala
+++ b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala
@@ -829,6 +829,23 @@ class BasicOpsSpecification extends CompilerTestingCommons
     }
   }
 
+  property("UnsignedBigInt.bitwiseInverse") {
+    def bitwiseInverseTest(): Assertion = test("UnsignedBigInt.bitwiseInverse", env, ext,
+      s"""{
+         | val b = unsignedBigInt("${CryptoConstants.groupOrder}")
+         | val bi = b.bitwiseInverse
+         | bi.bitwiseInverse == b
+         |}""".stripMargin,
+      null
+    )
+
+    if (VersionContext.current.isV6SoftForkActivated) {
+      bitwiseInverseTest()
+    } else {
+      an[sigma.validation.ValidationException] shouldBe thrownBy(bitwiseInverseTest())
+    }
+  }
+
 
   property("Byte.bitwiseInverse") {
     def bitwiseInverseTest(): Assertion = test("Byte.bitwiseInverse", env, ext,

From 77be8a6710f1a8214acbba85ca24414e141c719d Mon Sep 17 00:00:00 2001
From: Alexander Chepurnoy 
Date: Mon, 11 Nov 2024 17:30:41 +0300
Subject: [PATCH 282/314] more .toBytes and .toBits tests

---
 .../utxo/BasicOpsSpecification.scala          | 34 +++++++++++++++++++
 1 file changed, 34 insertions(+)

diff --git a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala
index 6c95071a0b..210fcb690d 100644
--- a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala
+++ b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala
@@ -812,6 +812,24 @@ class BasicOpsSpecification extends CompilerTestingCommons
     }
   }
 
+  property("UnsignedBigInt.toBits - 2") {
+    def toBitsTest() = test("UnsignedBigInt.toBits", env, ext,
+      s"""{
+         | val b = unsignedBigInt("5")
+         | val ba = b.toBits
+         | ba.size == 8 && ba == Coll(false, false, false, false, false, true, false, true)
+         |}""".stripMargin,
+      null
+    )
+
+    if (VersionContext.current.isV6SoftForkActivated) {
+      toBitsTest()
+    } else {
+      an[ValidationException] shouldBe thrownBy(toBitsTest())
+    }
+  }
+
+
   property("BigInt.bitwiseInverse") {
     def bitwiseInverseTest(): Assertion = test("BigInt.bitwiseInverse", env, ext,
       s"""{
@@ -1548,6 +1566,22 @@ class BasicOpsSpecification extends CompilerTestingCommons
     }
   }
 
+  property("UnsignedBigInt.toBytes - 2") {
+    val script = s"""{
+                    |   val l = unsignedBigInt("5")
+                    |   val bs = l.toBytes
+                    |   bs.size == 1 && bs == Coll(5.toByte)
+                    | }""".stripMargin
+
+    def toBytesTest() = test("UnsignedBigInt.toBytes", env, ext, script, null)
+
+    if (VersionContext.current.isV6SoftForkActivated) {
+      toBytesTest()
+    } else {
+      an[ValidationException] shouldBe thrownBy(toBytesTest())
+    }
+  }
+
   property("serialize - byte array") {
     def deserTest() = test("serialize", env, ext,
       s"""{

From 626edc89f58d99e4a54f72c97c7374e6ee845edc Mon Sep 17 00:00:00 2001
From: Alexander Chepurnoy 
Date: Mon, 11 Nov 2024 20:14:39 +0300
Subject: [PATCH 283/314] bitwise or/and/xor and tests

---
 .../sigma/data/UnsignedBigIntegerOps.scala    | 20 +++-
 .../utxo/BasicOpsSpecification.scala          | 91 +++++++++++++++++++
 2 files changed, 108 insertions(+), 3 deletions(-)

diff --git a/data/shared/src/main/scala/sigma/data/UnsignedBigIntegerOps.scala b/data/shared/src/main/scala/sigma/data/UnsignedBigIntegerOps.scala
index e0170b14df..dd66ca1b4f 100644
--- a/data/shared/src/main/scala/sigma/data/UnsignedBigIntegerOps.scala
+++ b/data/shared/src/main/scala/sigma/data/UnsignedBigIntegerOps.scala
@@ -1,5 +1,7 @@
 package sigma.data
 
+import debox.cfor
+import scorex.util.encode.Base16
 import sigma._
 import sigma.crypto.BigIntegers
 import sigma.data.UnsignedBigIntOrderingOps.UnsignedBigIntOrdering
@@ -110,17 +112,29 @@ object UnsignedBigIntNumericOps {
     /**
       * @return a numeric value which is `this | that`
       */
-    override def bitwiseOr(x: UnsignedBigInt, y: UnsignedBigInt): UnsignedBigInt = ???
+    override def bitwiseOr(x: UnsignedBigInt, y: UnsignedBigInt): UnsignedBigInt = {
+      val vx = x.asInstanceOf[CUnsignedBigInt].wrappedValue
+      val vy = y.asInstanceOf[CUnsignedBigInt].wrappedValue
+      CUnsignedBigInt(vx.or(vy))
+    }
 
     /**
       * @return a numeric value which is `this && that`
       */
-    override def bitwiseAnd(x: UnsignedBigInt, y: UnsignedBigInt): UnsignedBigInt = ???
+    override def bitwiseAnd(x: UnsignedBigInt, y: UnsignedBigInt): UnsignedBigInt = {
+      val vx = x.asInstanceOf[CUnsignedBigInt].wrappedValue
+      val vy = y.asInstanceOf[CUnsignedBigInt].wrappedValue
+      CUnsignedBigInt(vx.and(vy))
+    }
 
     /**
       * @return a numeric value which is `this xor that`
       */
-    override def bitwiseXor(x: UnsignedBigInt, y: UnsignedBigInt): UnsignedBigInt = ???
+    override def bitwiseXor(x: UnsignedBigInt, y: UnsignedBigInt): UnsignedBigInt = {
+      val vx = x.asInstanceOf[CUnsignedBigInt].wrappedValue
+      val vy = y.asInstanceOf[CUnsignedBigInt].wrappedValue
+      CUnsignedBigInt(vx.xor(vy))
+    }
 
     /**
       * @return a value which is (this << n). The shift distance, n, may be negative,
diff --git a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala
index 210fcb690d..0ad8ac592a 100644
--- a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala
+++ b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala
@@ -938,6 +938,40 @@ class BasicOpsSpecification extends CompilerTestingCommons
     }
   }
 
+  property("UnsignedBigInt.bitwiseOr") {
+    def bitwiseOrTest(): Assertion = test("BigInt.bitwiseOr", env, ext,
+      s"""{
+         | val x = unsignedBigInt("${CryptoConstants.groupOrder}")
+         | x.bitwiseOr(x) == x
+         |}""".stripMargin,
+      null
+    )
+
+    if (VersionContext.current.isV6SoftForkActivated) {
+      bitwiseOrTest()
+    } else {
+      an[sigma.validation.ValidationException] shouldBe thrownBy(bitwiseOrTest())
+    }
+  }
+
+  property("UnsignedBigInt.bitwiseOr - 2") {
+    def bitwiseOrTest(): Assertion = test("BigInt.bitwiseOr", env, ext,
+      s"""{
+         | val x = unsignedBigInt("${CryptoConstants.groupOrder}")
+         | val y = unsignedBigInt("121")
+         | val z = unsignedBigInt("115792089237316195423570985008687907852837564279074904382605163141518161494393")
+         | x.bitwiseOr(y) == z && y.bitwiseOr(x) == z
+         |}""".stripMargin,
+      null
+    )
+
+    if (VersionContext.current.isV6SoftForkActivated) {
+      bitwiseOrTest()
+    } else {
+      an[sigma.validation.ValidationException] shouldBe thrownBy(bitwiseOrTest())
+    }
+  }
+
   property("BigInt.bitwiseAnd") {
     def bitwiseAndTest(): Assertion = test("BigInt.bitwiseAnd", env, ext,
       s"""{
@@ -955,6 +989,43 @@ class BasicOpsSpecification extends CompilerTestingCommons
     }
   }
 
+  property("UnsignedBigInt.bitwiseAnd") {
+    def bitwiseAndTest(): Assertion = test("UnsignedBigInt.bitwiseAnd", env, ext,
+      s"""{
+         | val x = unsignedBigInt("${CryptoConstants.groupOrder}")
+         | val y = 0.toBigInt.toUnsigned
+         | x.bitwiseAnd(y) == y
+         |}""".stripMargin,
+      null
+    )
+
+    if (VersionContext.current.isV6SoftForkActivated) {
+      bitwiseAndTest()
+    } else {
+      an[sigma.validation.ValidationException] shouldBe thrownBy(bitwiseAndTest())
+    }
+  }
+
+  property("UnsignedBigInt.bitwiseAnd - 2") {
+    def bitwiseAndTest(): Assertion = test("UnsignedBigInt.bitwiseAnd", env, ext,
+      s"""{
+         | val x = unsignedBigInt("${CryptoConstants.groupOrder}")
+         | val y = unsignedBigInt("1157920892373161954235709850086879078528375642790749043826051631415181614337")
+         | val z = unsignedBigInt("1157920892373161954235709850086879078522970439492889181512311797126516834561")
+         |
+         | // cross-checked with wolfram alpha
+         | x.bitwiseAnd(y) == z
+         |}""".stripMargin,
+      null
+    )
+
+    if (VersionContext.current.isV6SoftForkActivated) {
+      bitwiseAndTest()
+    } else {
+      an[sigma.validation.ValidationException] shouldBe thrownBy(bitwiseAndTest())
+    }
+  }
+
   property("Short.bitwiseAnd") {
     val customExt = Map(
       1.toByte -> ShortConstant(32767)
@@ -995,6 +1066,26 @@ class BasicOpsSpecification extends CompilerTestingCommons
     }
   }
 
+  property("UnsignedBigInt.bitwiseXor") {
+    def bitwiseAndTest(): Assertion = test("UnsignedBigInt.bitwiseXor", env, ext,
+      s"""{
+         | val x = unsignedBigInt("${CryptoConstants.groupOrder}")
+         | val y = unsignedBigInt("1157920892373161954235709850086879078528375642790749043826051631415181614337")
+         | val z = unsignedBigInt("114634168344943033469335275158601028774319999042879875063406591178680309439552")
+         |
+         | // cross-checked with wolfram alpha
+         | x.bitwiseXor(y) == z
+         |}""".stripMargin,
+      null
+    )
+
+    if (VersionContext.current.isV6SoftForkActivated) {
+      bitwiseAndTest()
+    } else {
+      an[sigma.validation.ValidationException] shouldBe thrownBy(bitwiseAndTest())
+    }
+  }
+
   property("Byte.shiftLeft") {
     def shiftLeftTest(): Assertion = test("Byte.shiftLeft", env, ext,
       s"""{

From aa246c3e6d441c6d72e7877052e0167c854166ac Mon Sep 17 00:00:00 2001
From: Alexander Chepurnoy 
Date: Mon, 11 Nov 2024 22:46:48 +0300
Subject: [PATCH 284/314] shiftLeft/shiftRight and tests

---
 .../sigma/data/UnsignedBigIntegerOps.scala    | 16 +++++++--
 .../utxo/BasicOpsSpecification.scala          | 35 +++++++++++++++++++
 2 files changed, 49 insertions(+), 2 deletions(-)

diff --git a/data/shared/src/main/scala/sigma/data/UnsignedBigIntegerOps.scala b/data/shared/src/main/scala/sigma/data/UnsignedBigIntegerOps.scala
index dd66ca1b4f..6aebb485f8 100644
--- a/data/shared/src/main/scala/sigma/data/UnsignedBigIntegerOps.scala
+++ b/data/shared/src/main/scala/sigma/data/UnsignedBigIntegerOps.scala
@@ -140,13 +140,25 @@ object UnsignedBigIntNumericOps {
       * @return a value which is (this << n). The shift distance, n, may be negative,
       *         in which case this method performs a right shift. (Computes floor(this * 2n).)
       */
-    override def shiftLeft(x: UnsignedBigInt, bits: Int): UnsignedBigInt = ???
+    override def shiftLeft(x: UnsignedBigInt, bits: Int): UnsignedBigInt = {
+      if (bits < 0 || bits >= 256) {
+        throw new IllegalArgumentException(s"Wrong argument in UnsignedBigInt.shiftLeft: bits < 0 || bits >= 256 ($bits)")
+      } else {
+        x.shiftLeft(bits)
+      }
+    }
 
     /**
       * @return a value which is (this >> n). Sign extension is performed. The shift distance, n,
       *         may be negative, in which case this method performs a left shift. (Computes floor(this / 2n).)
       */
-    override def shiftRight(x: UnsignedBigInt, bits: Int): UnsignedBigInt = ???
+    override def shiftRight(x: UnsignedBigInt, bits: Int): UnsignedBigInt = {
+      if (bits < 0 || bits >= 256) {
+        throw new IllegalArgumentException(s"Wrong argument in UnsignedBigInt.shiftLeft: bits < 0 || bits >= 256 ($bits)")
+      } else {
+        x.shiftRight(bits)
+      }
+    }
   }
 
   /** The instance of [[scalan.ExactOrdering]] typeclass for [[BigInt]]. */
diff --git a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala
index 0ad8ac592a..ae34c5bbfc 100644
--- a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala
+++ b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala
@@ -1154,6 +1154,23 @@ class BasicOpsSpecification extends CompilerTestingCommons
     }
   }
 
+  property("UnsignedBigInt.shiftLeft") {
+    def shiftLeftTest(): Assertion = test("UnsignedBigInt.shiftLeft", env, ext,
+      s"""{
+         | val x = unsignedBigInt("${CryptoConstants.groupOrder.divide(new BigInteger("8"))}")
+         | val y = unsignedBigInt("${CryptoConstants.groupOrder.divide(new BigInteger("2"))}")
+         | x.shiftLeft(2) == y
+         |}""".stripMargin,
+      null
+    )
+
+    if (VersionContext.current.isV6SoftForkActivated) {
+      shiftLeftTest()
+    } else {
+      an[sigma.validation.ValidationException] shouldBe thrownBy(shiftLeftTest())
+    }
+  }
+
   property("BigInt.shiftLeft over limits") {
     def shiftLeftTest(): Assertion = test("BigInt.shiftLeft", env, ext,
       s"""{
@@ -1292,6 +1309,24 @@ class BasicOpsSpecification extends CompilerTestingCommons
     }
   }
 
+  property("UnsignedBigInt.shiftRight") {
+    def shiftRightTest(): Assertion = test("UnsignedBigInt.shiftRight", env, ext,
+      s"""{
+         | val x = unsignedBigInt("${CryptoConstants.groupOrder}")
+         | val y = 3
+         | val z = unsignedBigInt("${CryptoConstants.groupOrder.divide(new BigInteger("8"))}")
+         | x.shiftRight(y) == z
+         |}""".stripMargin,
+      null
+    )
+
+    if (VersionContext.current.isV6SoftForkActivated) {
+      shiftRightTest()
+    } else {
+      an[sigma.validation.ValidationException] shouldBe thrownBy(shiftRightTest())
+    }
+  }
+
   property("getVarFromInput - invalid var") {
     def getVarTest(): Assertion = {
       val customExt = Map(

From 7fdcdbd8c80ac6a386dd93dea6b9928b4b1db7a1 Mon Sep 17 00:00:00 2001
From: Alexander Chepurnoy 
Date: Mon, 11 Nov 2024 23:02:46 +0300
Subject: [PATCH 285/314] more tests for shiftLeft/shiftRight

---
 .../utxo/BasicOpsSpecification.scala          | 51 +++++++++++++++++++
 1 file changed, 51 insertions(+)

diff --git a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala
index ae34c5bbfc..f7a9fab2ba 100644
--- a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala
+++ b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala
@@ -1171,6 +1171,39 @@ class BasicOpsSpecification extends CompilerTestingCommons
     }
   }
 
+  property("UnsignedBigInt.shiftLeft over limits") {
+    def shiftLeftTest(): Assertion = test("UnsignedBigInt.shiftLeft", env, ext,
+      s"""{
+         | val x = unsignedBigInt("${CryptoConstants.groupOrder}")
+         | x.shiftLeft(1) > x
+         |}""".stripMargin,
+      null
+    )
+
+    if (VersionContext.current.isV6SoftForkActivated) {
+      an[ArithmeticException] shouldBe thrownBy(shiftLeftTest())
+    } else {
+      an[sigma.validation.ValidationException] shouldBe thrownBy(shiftLeftTest())
+    }
+  }
+
+
+  property("UnsignedBigInt.shiftLeft - neg shift") {
+    def shiftLeftTest(): Assertion = test("UnsignedBigInt.shiftLeft", env, ext,
+      s"""{
+         | val x = unsignedBigInt("${CryptoConstants.groupOrder}")
+         | x.shiftLeft(-1) > x
+         |}""".stripMargin,
+      null
+    )
+
+    if (VersionContext.current.isV6SoftForkActivated) {
+      an[java.lang.IllegalArgumentException] shouldBe thrownBy(shiftLeftTest())
+    } else {
+      an[sigma.validation.ValidationException] shouldBe thrownBy(shiftLeftTest())
+    }
+  }
+
   property("BigInt.shiftLeft over limits") {
     def shiftLeftTest(): Assertion = test("BigInt.shiftLeft", env, ext,
       s"""{
@@ -1327,6 +1360,24 @@ class BasicOpsSpecification extends CompilerTestingCommons
     }
   }
 
+  property("UnsignedBigInt.shiftRight - neg shift") {
+    def shiftRightTest(): Assertion = test("UnsignedBigInt.shiftRight", env, ext,
+      s"""{
+         | val x = unsignedBigInt("${CryptoConstants.groupOrder.divide(new BigInteger("2"))}")
+         | val y = -2
+         | val z = unsignedBigInt("${CryptoConstants.groupOrder.divide(new BigInteger("8"))}")
+         | z.shiftRight(y) == x
+         |}""".stripMargin,
+      null
+    )
+
+    if (VersionContext.current.isV6SoftForkActivated) {
+      an[java.lang.IllegalArgumentException] shouldBe thrownBy(shiftRightTest())
+    } else {
+      an[sigma.validation.ValidationException] shouldBe thrownBy(shiftRightTest())
+    }
+  }
+
   property("getVarFromInput - invalid var") {
     def getVarTest(): Assertion = {
       val customExt = Map(

From 95661777a14ce07e1addec25141d51ad3c116879 Mon Sep 17 00:00:00 2001
From: Alexander Chepurnoy 
Date: Wed, 13 Nov 2024 14:15:31 +0300
Subject: [PATCH 286/314] LSV6 tests for UnsignedBigInt

---
 .../src/main/scala/sigma/SigmaDsl.scala       |   2 +
 .../src/main/scala/sigma/ast/SType.scala      |  14 +-
 .../src/main/scala/sigma/data/CBigInt.scala   |  16 +
 .../src/test/scala/sigma/VersionTesting.scala |   5 +-
 .../main/scala/sigma/ast/SigmaPredef.scala    |   2 +-
 .../src/main/scala/sigma/ast/methods.scala    |   4 +-
 .../sigma/data/UnsignedBigIntegerOps.scala    |  10 +-
 .../sigma/compiler/ir/GraphBuilding.scala     |   2 +-
 .../scala/sigma/LanguageSpecificationV6.scala | 421 +++++++++++++++++-
 .../sigmastate/ErgoTreeSpecification.scala    |   2 +-
 10 files changed, 456 insertions(+), 22 deletions(-)

diff --git a/core/shared/src/main/scala/sigma/SigmaDsl.scala b/core/shared/src/main/scala/sigma/SigmaDsl.scala
index 92250ac615..099f27ae8a 100644
--- a/core/shared/src/main/scala/sigma/SigmaDsl.scala
+++ b/core/shared/src/main/scala/sigma/SigmaDsl.scala
@@ -321,6 +321,8 @@ trait UnsignedBigInt {
     */
   def shiftRight(n: Int): UnsignedBigInt
 
+  def bitwiseInverse(): UnsignedBigInt
+
   def toSigned(): BigInt
 }
 
diff --git a/core/shared/src/main/scala/sigma/ast/SType.scala b/core/shared/src/main/scala/sigma/ast/SType.scala
index 17a5ef10d7..d255adca6b 100644
--- a/core/shared/src/main/scala/sigma/ast/SType.scala
+++ b/core/shared/src/main/scala/sigma/ast/SType.scala
@@ -549,10 +549,15 @@ case object SUnsignedBigInt extends SPrimType with SEmbeddable with SNumericType
       case x: Short => BigInteger.valueOf(x.toLong)
       case x: Int => BigInteger.valueOf(x.toLong)
       case x: Long => BigInteger.valueOf(x)
+ //     case x: BigInt => x.asInstanceOf[CBigInt].wrappedValue
       case x: UnsignedBigInt => x.asInstanceOf[CUnsignedBigInt].wrappedValue
       case _ => sys.error(s"Cannot upcast value $v to the type $this")
     }
-    CUnsignedBigInt(bi)
+    if(bi.compareTo(BigInteger.ZERO) >= 0) {
+      CUnsignedBigInt(bi)
+    } else {
+      sys.error(s"Cannot upcast negative value $v to the type $this")
+    }
   }
   override def downcast(v: AnyVal): UnsignedBigInt = {
     val bi = v match {
@@ -560,10 +565,15 @@ case object SUnsignedBigInt extends SPrimType with SEmbeddable with SNumericType
       case x: Short => BigInteger.valueOf(x.toLong)
       case x: Int => BigInteger.valueOf(x.toLong)
       case x: Long => BigInteger.valueOf(x)
+  //    case x: BigInt => x.asInstanceOf[CBigInt].wrappedValue
       case x: UnsignedBigInt => x.asInstanceOf[CUnsignedBigInt].wrappedValue
       case _ => sys.error(s"Cannot downcast value $v to the type $this")
     }
-    CUnsignedBigInt(bi)
+    if(bi.compareTo(BigInteger.ZERO) >= 0) {
+      CUnsignedBigInt(bi)
+    } else {
+      sys.error(s"Cannot upcast negative value $v to the type $this")
+    }
   }
 }
 
diff --git a/core/shared/src/main/scala/sigma/data/CBigInt.scala b/core/shared/src/main/scala/sigma/data/CBigInt.scala
index 9292ada68a..b8b3ad7a17 100644
--- a/core/shared/src/main/scala/sigma/data/CBigInt.scala
+++ b/core/shared/src/main/scala/sigma/data/CBigInt.scala
@@ -76,6 +76,11 @@ case class CBigInt(override val wrappedValue: BigInteger) extends BigInt with Wr
   */
 case class CUnsignedBigInt(override val wrappedValue: BigInteger) extends UnsignedBigInt with WrapperOf[BigInteger] {
 
+  if (wrappedValue.compareTo(BigInteger.ZERO) < 0) {
+    throw new IllegalArgumentException(s"Attempt to create unsigned value from negative big integer $wrappedValue")
+  }
+
+
   override def toByte: Byte = wrappedValue.toByteExact
 
   override def toShort: Short = wrappedValue.toShortExact
@@ -142,6 +147,17 @@ case class CUnsignedBigInt(override val wrappedValue: BigInteger) extends Unsign
 
   override def shiftRight(n: Int): UnsignedBigInt = CUnsignedBigInt(wrappedValue.shiftRight(n).toUnsignedBigIntValueExact)
 
+  override def bitwiseInverse(): UnsignedBigInt = {
+    val bytes = if(wrappedValue.compareTo(BigInteger.ZERO) == 0) {
+      Array(0: Byte)
+    } else {
+      BigIntegers.asUnsignedByteArray(wrappedValue)
+    }
+
+    val res: Array[Byte] = bytes.map(b => (~b & 0xff).toByte)
+    CUnsignedBigInt(BigIntegers.fromUnsignedByteArray(res))
+  }
+
   override def toSigned(): BigInt = {
     CBigInt(wrappedValue.toSignedBigIntValueExact)
   }
diff --git a/core/shared/src/test/scala/sigma/VersionTesting.scala b/core/shared/src/test/scala/sigma/VersionTesting.scala
index 08053a6c48..a73452a838 100644
--- a/core/shared/src/test/scala/sigma/VersionTesting.scala
+++ b/core/shared/src/test/scala/sigma/VersionTesting.scala
@@ -72,8 +72,9 @@ trait VersionTesting {
   protected def testFun_Run(testName: String, testFun: => Any): Unit = {
     def msg = s"""property("$testName")(ActivatedVersion = $activatedVersionInTests; ErgoTree version = $ergoTreeVersionInTests)"""
     if (printVersions) println(msg)
-    try testFun
-    catch {
+    try {
+      testFun
+    } catch {
       case t: Throwable =>
         if (!printVersions) {
           // wasn't printed, print it now
diff --git a/data/shared/src/main/scala/sigma/ast/SigmaPredef.scala b/data/shared/src/main/scala/sigma/ast/SigmaPredef.scala
index e976babbf2..28c51a706b 100644
--- a/data/shared/src/main/scala/sigma/ast/SigmaPredef.scala
+++ b/data/shared/src/main/scala/sigma/ast/SigmaPredef.scala
@@ -455,7 +455,7 @@ object SigmaPredef {
           val resType = u.opType.tRange.asInstanceOf[SFunc].tRange
           MethodCall(
             Global,
-            SGlobalMethods.fromBigEndianBytesMethod.withConcreteTypes(Map(tT -> resType)),
+            SGlobalMethods.FromBigEndianBytesMethod.withConcreteTypes(Map(tT -> resType)),
             args.toIndexedSeq,
             Map(tT -> resType)
           )
diff --git a/data/shared/src/main/scala/sigma/ast/methods.scala b/data/shared/src/main/scala/sigma/ast/methods.scala
index 5d21e91b16..ce8e71eef7 100644
--- a/data/shared/src/main/scala/sigma/ast/methods.scala
+++ b/data/shared/src/main/scala/sigma/ast/methods.scala
@@ -1989,7 +1989,7 @@ case object SGlobalMethods extends MonoTypeMethods {
   private val BigEndianBytesCostKind = FixedCost(JitCost(10))
 
   // id = 4 is reserved for deserializeTo ()
-  lazy val fromBigEndianBytesMethod = SMethod(
+  lazy val FromBigEndianBytesMethod = SMethod(
     this, "fromBigEndianBytes", SFunc(Array(SGlobal, SByteArray), tT, Array(paramT)), 5, BigEndianBytesCostKind, Seq(tT))
     .withIRInfo(MethodCallIrBuilder,
       javaMethodOf[SigmaDslBuilder, Coll[Byte], RType[_]]("fromBigEndianBytes"),
@@ -2033,7 +2033,7 @@ case object SGlobalMethods extends MonoTypeMethods {
         groupGeneratorMethod,
         xorMethod,
         serializeMethod,
-        fromBigEndianBytesMethod
+        FromBigEndianBytesMethod
       )
     } else {
       Seq(
diff --git a/data/shared/src/main/scala/sigma/data/UnsignedBigIntegerOps.scala b/data/shared/src/main/scala/sigma/data/UnsignedBigIntegerOps.scala
index 6aebb485f8..bf3dd3e33b 100644
--- a/data/shared/src/main/scala/sigma/data/UnsignedBigIntegerOps.scala
+++ b/data/shared/src/main/scala/sigma/data/UnsignedBigIntegerOps.scala
@@ -50,8 +50,8 @@ object UnsignedBigIntNumericOps {
     def fromInt(x: Int): UnsignedBigInt = x.toUnsignedBigInt
     def toInt(x: UnsignedBigInt): Int = x.toInt
     def toLong(x: UnsignedBigInt): Long = x.toLong
-    def toFloat(x: UnsignedBigInt): Float = ???
-    def toDouble(x: UnsignedBigInt): Double = ???
+    def toFloat(x: UnsignedBigInt): Float = x.toFloat
+    def toDouble(x: UnsignedBigInt): Double = x.toDouble
   }
 
   /** The instance of Integral for BigInt.
@@ -103,11 +103,7 @@ object UnsignedBigIntNumericOps {
     /**
       * @return a numeric value which is inverse of `x` (every bit is flipped)
       */
-    override def bitwiseInverse(x: UnsignedBigInt): UnsignedBigInt = {
-      val bytes = BigIntegers.asUnsignedByteArray(x.asInstanceOf[CUnsignedBigInt].wrappedValue)
-      val res: Array[Byte] = bytes.map(b => (b ^ Byte.MinValue).toByte)
-      CUnsignedBigInt(BigIntegers.fromUnsignedByteArray(res))
-    }
+    override def bitwiseInverse(x: UnsignedBigInt): UnsignedBigInt = x.bitwiseInverse()
 
     /**
       * @return a numeric value which is `this | that`
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 caeded999c..18ce41497d 100644
--- a/sc/shared/src/main/scala/sigma/compiler/ir/GraphBuilding.scala
+++ b/sc/shared/src/main/scala/sigma/compiler/ir/GraphBuilding.scala
@@ -1198,7 +1198,7 @@ trait GraphBuilding extends Base with DefRewriting { IR: IRContext =>
             case SGlobalMethods.serializeMethod.name =>
               val value = asRep[Any](argsV(0))
               g.serialize(value)
-            case SGlobalMethods.fromBigEndianBytesMethod.name =>
+            case SGlobalMethods.FromBigEndianBytesMethod.name =>
               val bytes = asRep[Coll[Byte]](argsV(0))
               val cT = stypeToElem(method.stype.tRange.withSubstTypes(typeSubst))
               g.fromBigEndianBytes(bytes)(cT)
diff --git a/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala b/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala
index f096a36eba..2c6aaaf74b 100644
--- a/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala
+++ b/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala
@@ -108,7 +108,6 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite =>
 
   // TODO v6.0: implement serialization roundtrip tests after merge with deserializeTo
 
-
   property("Boolean.toByte") {
     val toByte = newFeature((x: Boolean) => x.toByte, "{ (x: Boolean) => x.toByte }",
       sinceVersion = V6SoftForkVersion
@@ -1659,6 +1658,7 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite =>
       newFeature(
         { (x: Context) => x.getVar[Boolean](11)},
         "{ (x: Context) => CONTEXT.getVar[Boolean](11.toByte) }",
+        FuncValue(Array((1, SContext)), GetVar(11.toByte, SOption(SBoolean))),
         sinceVersion = VersionContext.V6SoftForkVersion
       )
     }
@@ -1768,11 +1768,31 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite =>
 
   property("Global - fromBigEndianBytes") {
     import sigma.data.OrderingOps.BigIntOrdering
+    import sigma.data.OrderingOps.UnsignedBigIntOrdering
 
     def byteFromBigEndianBytes: Feature[Byte, Boolean] = {
       newFeature(
         { (x: Byte) => CSigmaDslBuilder.fromBigEndianBytes[Byte](Colls.fromArray(Array(x))) == x},
         "{ (x: Byte) => fromBigEndianBytes[Byte](x.toBytes) == x }",
+        FuncValue(
+          Array((1, SByte)),
+          EQ(
+            MethodCall.typed[Value[SByte.type]](
+              Global,
+              SGlobalMethods.FromBigEndianBytesMethod.withConcreteTypes(Map(STypeVar("T") -> SByte)),
+              Array(
+                MethodCall.typed[Value[SCollection[SByte.type]]](
+                  ValUse(1, SByte),
+                  SByteMethods.getMethodByName("toBytes"),
+                  Vector(),
+                  Map()
+                )
+              ),
+              Map(STypeVar("T") -> SByte)
+            ),
+            ValUse(1, SByte)
+          )
+        ),
         sinceVersion = VersionContext.V6SoftForkVersion
       )
     }
@@ -1790,6 +1810,25 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite =>
       newFeature(
         { (x: Short) => CSigmaDslBuilder.fromBigEndianBytes[Short](Colls.fromArray(Shorts.toByteArray(x))) == x},
         "{ (x: Short) => fromBigEndianBytes[Short](x.toBytes) == x }",
+        FuncValue(
+          Array((1, SShort)),
+          EQ(
+            MethodCall.typed[Value[SShort.type]](
+              Global,
+              SGlobalMethods.FromBigEndianBytesMethod.withConcreteTypes(Map(STypeVar("T") -> SShort)),
+              Array(
+                MethodCall.typed[Value[SCollection[SByte.type]]](
+                  ValUse(1, SShort),
+                  SShortMethods.getMethodByName("toBytes"),
+                  Vector(),
+                  Map()
+                )
+              ),
+              Map(STypeVar("T") -> SShort)
+            ),
+            ValUse(1, SShort)
+          )
+        ),
         sinceVersion = VersionContext.V6SoftForkVersion
       )
     }
@@ -1807,6 +1846,25 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite =>
       newFeature(
         { (x: Int) => CSigmaDslBuilder.fromBigEndianBytes[Int](Colls.fromArray(Ints.toByteArray(x))) == x},
         "{ (x: Int) => fromBigEndianBytes[Int](x.toBytes) == x }",
+        FuncValue(
+          Array((1, SInt)),
+          EQ(
+            MethodCall.typed[Value[SInt.type]](
+              Global,
+              SGlobalMethods.FromBigEndianBytesMethod.withConcreteTypes(Map(STypeVar("T") -> SInt)),
+              Array(
+                MethodCall.typed[Value[SCollection[SByte.type]]](
+                  ValUse(1, SInt),
+                  SIntMethods.getMethodByName("toBytes"),
+                  Vector(),
+                  Map()
+                )
+              ),
+              Map(STypeVar("T") -> SInt)
+            ),
+            ValUse(1, SInt)
+          )
+        ),
         sinceVersion = VersionContext.V6SoftForkVersion
       )
     }
@@ -1823,6 +1881,25 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite =>
       newFeature(
         { (x: Long) => CSigmaDslBuilder.fromBigEndianBytes[Long](Colls.fromArray(Longs.toByteArray(x))) == x},
         "{ (x: Long) => fromBigEndianBytes[Long](x.toBytes) == x }",
+        FuncValue(
+          Array((1, SLong)),
+          EQ(
+            MethodCall.typed[Value[SLong.type]](
+              Global,
+              SGlobalMethods.FromBigEndianBytesMethod.withConcreteTypes(Map(STypeVar("T") -> SLong)),
+              Array(
+                MethodCall.typed[Value[SCollection[SByte.type]]](
+                  ValUse(1, SLong),
+                  SLongMethods.getMethodByName("toBytes"),
+                  Vector(),
+                  Map()
+                )
+              ),
+              Map(STypeVar("T") -> SLong)
+            ),
+            ValUse(1, SLong)
+          )
+        ),
         sinceVersion = VersionContext.V6SoftForkVersion
       )
     }
@@ -1839,6 +1916,25 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite =>
       newFeature(
         { (x: BigInt) => CSigmaDslBuilder.fromBigEndianBytes[BigInt](x.toBytes) == x},
         "{ (x: BigInt) => Global.fromBigEndianBytes[BigInt](x.toBytes) == x }",
+        FuncValue(
+          Array((1, SBigInt)),
+          EQ(
+            MethodCall.typed[Value[SBigInt.type]](
+              Global,
+              SGlobalMethods.FromBigEndianBytesMethod.withConcreteTypes(Map(STypeVar("T") -> SBigInt)),
+              Array(
+                MethodCall.typed[Value[SCollection[SByte.type]]](
+                  ValUse(1, SBigInt),
+                  SBigIntMethods.getMethodByName("toBytes"),
+                  IndexedSeq(),
+                  Map()
+                )
+              ),
+              Map(STypeVar("T") -> SBigInt)
+            ),
+            ValUse(1, SBigInt)
+          )
+        ),
         sinceVersion = VersionContext.V6SoftForkVersion
       )
     }
@@ -1852,12 +1948,57 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite =>
       bigIntFromBigEndianBytes
     )
 
+    def unsignedBigIntFromBigEndianBytes: Feature[UnsignedBigInt, Boolean] = {
+      newFeature(
+        { (x: UnsignedBigInt) => CSigmaDslBuilder.fromBigEndianBytes[UnsignedBigInt](x.toBytes) == x},
+        "{ (x: UnsignedBigInt) => Global.fromBigEndianBytes[UnsignedBigInt](x.toBytes) == x }",
+        FuncValue(
+          Array((1, SUnsignedBigInt)),
+          EQ(
+            MethodCall.typed[Value[SUnsignedBigInt.type]](
+              Global,
+              SGlobalMethods.FromBigEndianBytesMethod.withConcreteTypes(Map(STypeVar("T") -> SUnsignedBigInt)),
+              Array(
+                MethodCall.typed[Value[SCollection[SByte.type]]](
+                  ValUse(1, SUnsignedBigInt),
+                  SUnsignedBigIntMethods.getMethodByName("toBytes"),
+                  IndexedSeq(),
+                  Map()
+                )
+              ),
+              Map(STypeVar("T") -> SUnsignedBigInt)
+            ),
+            ValUse(1, SUnsignedBigInt)
+          )
+        ),
+        sinceVersion = VersionContext.V6SoftForkVersion
+      )
+    }
+
+    verifyCases(
+      Seq(
+        CUnsignedBigInt(BigInteger.valueOf(50)) -> new Expected(ExpectedResult(Success(true), None)),
+        CUnsignedBigInt(sigma.crypto.CryptoConstants.groupOrder.divide(BigInteger.valueOf(2))) -> new Expected(ExpectedResult(Success(true), None)),
+        CUnsignedBigInt(sigma.crypto.CryptoConstants.groupOrder) -> new Expected(ExpectedResult(Success(true), None))
+      ),
+      unsignedBigIntFromBigEndianBytes
+    )
+
   }
 
   property("Coll.reverse") {
     val f = newFeature[Coll[Int], Coll[Int]](
       { (xs: Coll[Int]) => xs.reverse },
       """{(xs: Coll[Int]) => xs.reverse }""".stripMargin,
+      FuncValue(
+        Array((1, SCollectionType(SInt))),
+        MethodCall.typed[Value[SCollection[SInt.type]]](
+          ValUse(1, SCollectionType(SInt)),
+          SCollectionMethods.ReverseMethod.withConcreteTypes(Map(STypeVar("IV") -> SInt)),
+          IndexedSeq(),
+          Map()
+        )
+      ),
       sinceVersion = VersionContext.V6SoftForkVersion
     )
 
@@ -1874,6 +2015,15 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite =>
     val f = newFeature[Coll[Int], Coll[Int]](
       { (xs: Coll[Int]) => xs.distinct },
       """{(xs: Coll[Int]) => xs.distinct }""".stripMargin,
+      FuncValue(
+        Array((1, SCollectionType(SInt))),
+        MethodCall.typed[Value[SCollection[SInt.type]]](
+          ValUse(1, SCollectionType(SInt)),
+          SCollectionMethods.DistinctMethod.withConcreteTypes(Map(STypeVar("IV") -> SInt)),
+          IndexedSeq(),
+          Map()
+        )
+      ),
       sinceVersion = VersionContext.V6SoftForkVersion
     )
 
@@ -1894,6 +2044,23 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite =>
     val f = newFeature[(Coll[Int], Coll[Int]), Boolean](
       { (xs: (Coll[Int], Coll[Int])) => xs._1.startsWith(xs._2) },
       """{(xs: (Coll[Int], Coll[Int])) => xs._1.startsWith(xs._2) }""".stripMargin,
+      FuncValue(
+        Array((1, SPair(SCollectionType(SInt), SCollectionType(SInt)))),
+        MethodCall.typed[Value[SBoolean.type]](
+          SelectField.typed[Value[SCollection[SInt.type]]](
+            ValUse(1, SPair(SCollectionType(SInt), SCollectionType(SInt))),
+            1.toByte
+          ),
+          SCollectionMethods.StartsWithMethod.withConcreteTypes(Map(STypeVar("IV") -> SInt)),
+          Array(
+            SelectField.typed[Value[SCollection[SInt.type]]](
+              ValUse(1, SPair(SCollectionType(SInt), SCollectionType(SInt))),
+              2.toByte
+            )
+          ),
+          Map()
+        )
+      ),
       sinceVersion = VersionContext.V6SoftForkVersion
     )
 
@@ -1914,7 +2081,24 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite =>
     val f = newFeature[(Coll[Int], Coll[Int]), Boolean](
       { (xs: (Coll[Int], Coll[Int])) => xs._1.endsWith(xs._2) },
       """{(xs: (Coll[Int], Coll[Int])) => xs._1.endsWith(xs._2) }""".stripMargin,
-      sinceVersion = VersionContext.V6SoftForkVersion
+      FuncValue(
+        Array((1, SPair(SCollectionType(SInt), SCollectionType(SInt)))),
+        MethodCall.typed[Value[SBoolean.type]](
+          SelectField.typed[Value[SCollection[SInt.type]]](
+            ValUse(1, SPair(SCollectionType(SInt), SCollectionType(SInt))),
+            1.toByte
+          ),
+          SCollectionMethods.EndsWithMethod.withConcreteTypes(Map(STypeVar("IV") -> SInt)),
+          Array(
+            SelectField.typed[Value[SCollection[SInt.type]]](
+              ValUse(1, SPair(SCollectionType(SInt), SCollectionType(SInt))),
+              2.toByte
+            )
+          ),
+          Map()
+        )
+      ),
+        sinceVersion = VersionContext.V6SoftForkVersion
     )
 
     verifyCases(
@@ -1933,7 +2117,21 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite =>
     val f = newFeature[(Coll[Int], Int), Option[Int]](
       { (xs: (Coll[Int], Int)) => xs._1.get(xs._2) },
       """{(xs: (Coll[Int], Int)) => xs._1.get(xs._2) }""".stripMargin,
-      sinceVersion = VersionContext.V6SoftForkVersion
+      FuncValue(
+        Array((1, SPair(SCollectionType(SInt), SInt))),
+        MethodCall.typed[Value[SOption[SInt.type]]](
+          SelectField.typed[Value[SCollection[SInt.type]]](
+            ValUse(1, SPair(SCollectionType(SInt), SInt)),
+            1.toByte
+          ),
+          SCollectionMethods.GetMethod.withConcreteTypes(Map(STypeVar("IV") -> SInt)),
+          Array(
+            SelectField.typed[Value[SInt.type]](ValUse(1, SPair(SCollectionType(SInt), SInt)), 2.toByte)
+          ),
+          Map()
+        )
+      ),
+        sinceVersion = VersionContext.V6SoftForkVersion
     )
 
     verifyCases(
@@ -1976,7 +2174,6 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite =>
     )
   }
 
-
   property("BigInt.toUnsignedMod") {
     import sigma.data.OrderingOps.BigIntOrdering
     import sigma.data.OrderingOps.UnsignedBigIntOrdering
@@ -2004,11 +2201,223 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite =>
     verifyCases(
       Seq(
         (CBigInt(new BigInteger("50")), CUnsignedBigInt(new BigInteger("10"))) -> Expected(ExpectedResult(Success(CUnsignedBigInt(new BigInteger("0"))), None)),
-        (CBigInt(new BigInteger("50")), CUnsignedBigInt(new BigInteger("0"))) -> Expected(ExpectedResult(Failure(new ArithmeticException("BigInteger: modulus not positive")), None)),
-        (CBigInt(new BigInteger("50")), CUnsignedBigInt(new BigInteger("-10"))) -> Expected(ExpectedResult(Failure(new ArithmeticException("BigInteger: modulus not positive")), None))
+        (CBigInt(new BigInteger("50")), CUnsignedBigInt(new BigInteger("0"))) -> Expected(ExpectedResult(Failure(new ArithmeticException("BigInteger: modulus not positive")), None))
       ),
       f
     )
   }
 
+  property("UnsignedBigInt methods") {
+    import sigma.data.OrderingOps.UnsignedBigIntOrdering
+
+    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) {
+        FuncValue(
+          Array((1, SPair(SUnsignedBigInt, SUnsignedBigInt))),
+          MethodCall.typed[Value[SUnsignedBigInt.type]](
+            SelectField.typed[Value[SUnsignedBigInt.type]](
+              ValUse(1, SPair(SUnsignedBigInt, SUnsignedBigInt)),
+              1.toByte
+            ),
+            SUnsignedBigIntMethods.getMethodByName("bitwiseOr"),
+            Vector(
+              SelectField.typed[Value[SUnsignedBigInt.type]](
+                ValUse(1, SPair(SUnsignedBigInt, SUnsignedBigInt)),
+                2.toByte
+              )
+            ),
+            Map()
+          )
+        )
+      } else {
+        null
+      },
+      sinceVersion = V6SoftForkVersion)
+
+    verifyCases(
+      Seq(
+        (CUnsignedBigInt(BigInteger.valueOf(1)), CUnsignedBigInt(BigInteger.valueOf(2))) -> new Expected(ExpectedResult(Success(CUnsignedBigInt(BigInteger.valueOf(3))), None)),
+        (CUnsignedBigInt(BigInteger.valueOf(1001)), CUnsignedBigInt(BigInteger.valueOf(2002))) -> new Expected(ExpectedResult(Success(CUnsignedBigInt(BigInteger.valueOf(2043))), None)),
+        (CUnsignedBigInt(BigInteger.valueOf(100001)), CUnsignedBigInt(BigInteger.valueOf(20002))) -> new Expected(ExpectedResult(Success(CUnsignedBigInt(BigInteger.valueOf(118435))), None))
+      ),
+      bitOr
+    )
+
+    lazy val bitNot = newFeature[UnsignedBigInt, UnsignedBigInt](
+      { (x: UnsignedBigInt) => x.bitwiseInverse() },
+      "{ (x: UnsignedBigInt) => x.bitwiseInverse }",
+      if (VersionContext.current.isV6SoftForkActivated) {
+        FuncValue(
+          Array((1, SUnsignedBigInt)),
+          MethodCall.typed[Value[SUnsignedBigInt.type]](
+            ValUse(1, SUnsignedBigInt),
+            SUnsignedBigIntMethods.getMethodByName("bitwiseInverse"),
+            Vector(),
+            Map()
+          )
+        )
+      } else {
+        null
+      },
+      sinceVersion = V6SoftForkVersion)
+
+    verifyCases(
+      Seq(
+        CUnsignedBigInt(BigInteger.valueOf(Byte.MaxValue)) -> new Expected(ExpectedResult(Success(CUnsignedBigInt(BigInteger.valueOf(128))), None)),
+        CUnsignedBigInt(BigInteger.valueOf(0)) -> new Expected(ExpectedResult(Success(CUnsignedBigInt(BigInteger.valueOf(255))), None)),
+        CUnsignedBigInt(BigInteger.valueOf(1)) -> new Expected(ExpectedResult(Success(CUnsignedBigInt(BigInteger.valueOf(254))), None)),
+        CUnsignedBigInt(BigInteger.valueOf(2)) -> new Expected(ExpectedResult(Success(CUnsignedBigInt(BigInteger.valueOf(253))), None)),
+        CUnsignedBigInt(BigInteger.valueOf(10001)) -> new Expected(ExpectedResult(Success(CUnsignedBigInt(BigInteger.valueOf(55534))), None)),
+        CUnsignedBigInt(BigInteger.valueOf(Int.MaxValue)) -> new Expected(ExpectedResult(Success(CUnsignedBigInt(BigInteger.valueOf(Int.MaxValue).add(BigInteger.ONE))), None)),
+        CUnsignedBigInt(BigInteger.valueOf(Long.MaxValue)) -> new Expected(ExpectedResult(Success(CUnsignedBigInt(BigInteger.valueOf(Long.MaxValue).add(BigInteger.ONE))), None))
+      ),
+      bitNot
+    )
+
+
+    lazy val bitAnd = newFeature(
+      { (x: (UnsignedBigInt, UnsignedBigInt)) => x._1.asInstanceOf[CUnsignedBigInt].and(x._2.asInstanceOf[CUnsignedBigInt]) },
+      "{ (x: (UnsignedBigInt, UnsignedBigInt)) => x._1.bitwiseAnd(x._2) }",
+      FuncValue(
+        Array((1, SPair(SUnsignedBigInt, SUnsignedBigInt))),
+        MethodCall.typed[Value[SUnsignedBigInt.type]](
+          SelectField.typed[Value[SUnsignedBigInt.type]](ValUse(1, SPair(SUnsignedBigInt, SUnsignedBigInt)), 1.toByte),
+          SUnsignedBigIntMethods.v6Methods.find(_.name == "bitwiseAnd").get,
+          Vector(SelectField.typed[Value[SUnsignedBigInt.type]](ValUse(1, SPair(SUnsignedBigInt, SUnsignedBigInt)), 2.toByte)),
+          Map()
+        )
+      ),
+      sinceVersion = V6SoftForkVersion)
+
+    verifyCases(
+      Seq(
+        (CUnsignedBigInt(BigInteger.valueOf(3)), CUnsignedBigInt(BigInteger.valueOf(5))) -> new Expected(ExpectedResult(Success(CUnsignedBigInt(BigInteger.valueOf(1))), None)),
+        (CUnsignedBigInt(BigInteger.valueOf(10001)), CUnsignedBigInt(BigInteger.valueOf(2202))) -> new Expected(ExpectedResult(Success(CUnsignedBigInt(BigInteger.valueOf(16))), None))
+      ),
+      bitAnd
+    )
+
+    lazy val bitXor = newFeature(
+      { (x: (UnsignedBigInt, UnsignedBigInt)) => x._1.asInstanceOf[CUnsignedBigInt].xor(x._2.asInstanceOf[CUnsignedBigInt]) },
+      "{ (x: (UnsignedBigInt, UnsignedBigInt)) => x._1.bitwiseXor(x._2) }",
+      FuncValue(
+        Array((1, SPair(SUnsignedBigInt, SUnsignedBigInt))),
+        MethodCall.typed[Value[SUnsignedBigInt.type]](
+          SelectField.typed[Value[SUnsignedBigInt.type]](ValUse(1, SPair(SUnsignedBigInt, SUnsignedBigInt)), 1.toByte),
+          SUnsignedBigIntMethods.v6Methods.find(_.name == "bitwiseXor").get,
+          Vector(SelectField.typed[Value[SUnsignedBigInt.type]](ValUse(1, SPair(SUnsignedBigInt, SUnsignedBigInt)),2.toByte)),
+          Map()
+        )
+      ),
+      sinceVersion = V6SoftForkVersion)
+
+    verifyCases(
+      Seq(
+        (CUnsignedBigInt(BigInteger.valueOf(3)), CUnsignedBigInt(BigInteger.valueOf(5))) -> new Expected(ExpectedResult(Success(CUnsignedBigInt(BigInteger.valueOf(6))), None)),
+        (CUnsignedBigInt(BigInteger.valueOf(10001)), CUnsignedBigInt(BigInteger.valueOf(2202))) -> new Expected(ExpectedResult(Success(CUnsignedBigInt(BigInteger.valueOf(12171))), None))
+      ),
+      bitXor
+    )
+
+    lazy val toBigEndianBytes = newFeature[UnsignedBigInt, Coll[Byte]](
+      { x: UnsignedBigInt => x.toBytes },
+      "{ (x: UnsignedBigInt) => x.toBytes }",
+      FuncValue(
+        Array((1, SUnsignedBigInt)),
+        MethodCall.typed[Value[SCollection[SUnsignedBigInt.type]]](
+          ValUse(1, SUnsignedBigInt),
+          SUnsignedBigIntMethods.getMethodByName("toBytes"),
+          Vector(),
+          Map()
+        )
+      ),
+      sinceVersion = V6SoftForkVersion)
+
+    verifyCases(
+      Seq(
+        CUnsignedBigInt(BigInteger.valueOf(127)) -> new Expected(ExpectedResult(Success(Coll(127.toByte)), None)),
+        CUnsignedBigInt(BigInteger.valueOf(Short.MaxValue)) -> new Expected(ExpectedResult(Success(Coll(127.toByte, (-1).toByte)), None)),
+        CUnsignedBigInt(BigInteger.valueOf(Int.MaxValue)) -> new Expected(ExpectedResult(Success(Coll(127.toByte, (-1).toByte, (-1).toByte, (-1).toByte)), None))
+      ),
+      toBigEndianBytes
+    )
+
+    def byte2Bools(b: Byte): Seq[Boolean] =
+      (0 to 7 map isBitSet(b)).reverse
+
+    def isBitSet(byte: Byte)(bit: Int): Boolean =
+      ((byte >> bit) & 1) == 1
+
+    lazy val toBits = newFeature[UnsignedBigInt, Coll[Boolean]](
+      { x: UnsignedBigInt => x.toBytes.flatMap(b => Colls.fromArray(byte2Bools(b).toArray))  },
+      "{ (x: UnsignedBigInt) => x.toBits }",
+      FuncValue(
+        Array((1, SUnsignedBigInt)),
+        MethodCall.typed[Value[SCollection[SUnsignedBigInt.type]]](
+          ValUse(1, SUnsignedBigInt),
+          SUnsignedBigIntMethods.getMethodByName("toBits"),
+          Vector(),
+          Map()
+        )
+      ),
+      sinceVersion = V6SoftForkVersion)
+
+    verifyCases(
+      Seq(
+        CUnsignedBigInt(BigInteger.valueOf(83)) -> new Expected(ExpectedResult(Success(Coll(false, true, false, true, false, false, true, true)), None))
+      ),
+      toBits
+    )
+
+    lazy val shiftLeft = newFeature(
+      { (x: (UnsignedBigInt, Int)) => if(x._2 < 0 || x._2 >= 256) throw new IllegalArgumentException() else (x._1.asInstanceOf[UnsignedBigInt].shiftLeft(x._2)) },
+      "{ (x: (UnsignedBigInt, Int)) => x._1.shiftLeft(x._2) }",
+      FuncValue(
+        Array((1, SPair(SUnsignedBigInt, SInt))),
+        MethodCall.typed[Value[SUnsignedBigInt.type]](
+          SelectField.typed[Value[SUnsignedBigInt.type]](ValUse(1, SPair(SUnsignedBigInt, SInt)), 1.toByte),
+          SUnsignedBigIntMethods.v6Methods.find(_.name == "shiftLeft").get,
+          Vector(SelectField.typed[Value[SInt.type]](ValUse(1, SPair(SUnsignedBigInt, SInt)), 2.toByte)),
+          Map()
+        )
+      ),
+      sinceVersion = V6SoftForkVersion)
+
+    verifyCases(
+      Seq(
+        (CUnsignedBigInt(BigInteger.valueOf(3)), 3) -> new Expected(ExpectedResult(Success(CUnsignedBigInt(BigInteger.valueOf(24))), None)),
+        (CUnsignedBigInt(BigInteger.valueOf(3)), 8) -> new Expected(ExpectedResult(Success(CUnsignedBigInt(BigInteger.valueOf(768))), None))
+      ),
+      shiftLeft,
+      preGeneratedSamples = Some(Seq())
+    )
+
+    lazy val shiftRight = newFeature(
+      { (x: (UnsignedBigInt, Int)) => if(x._2 < 0 || x._2 >= 256) throw new IllegalArgumentException() else (x._1.asInstanceOf[UnsignedBigInt].shiftRight(x._2)) },
+      "{ (x: (UnsignedBigInt, Int)) => x._1.shiftRight(x._2) }",
+      FuncValue(
+        Array((1, SPair(SUnsignedBigInt, SInt))),
+        MethodCall.typed[Value[SUnsignedBigInt.type]](
+          SelectField.typed[Value[SUnsignedBigInt.type]](ValUse(1, SPair(SUnsignedBigInt, SInt)), 1.toByte),
+          SUnsignedBigIntMethods.v6Methods.find(_.name == "shiftRight").get,
+          Vector(SelectField.typed[Value[SInt.type]](ValUse(1, SPair(SUnsignedBigInt, SInt)), 2.toByte)),
+          Map()
+        )
+      ),
+      sinceVersion = V6SoftForkVersion)
+
+    verifyCases(
+      Seq(
+        (CUnsignedBigInt(BigInteger.valueOf(24)), 3) -> new Expected(ExpectedResult(Success(CUnsignedBigInt(BigInteger.valueOf(3))), None)),
+        (CUnsignedBigInt(BigInteger.valueOf(1600)), 8) -> new Expected(ExpectedResult(Success(CUnsignedBigInt(BigInteger.valueOf(6))), None)),
+        (CUnsignedBigInt(BigInteger.valueOf(24)), -1) -> new Expected(ExpectedResult(Failure(new IllegalArgumentException()), None)),
+        (CUnsignedBigInt(BigInteger.valueOf(24)), 256) -> new Expected(ExpectedResult(Failure(new IllegalArgumentException()), None))
+      ),
+      shiftRight,
+      preGeneratedSamples = Some(Seq())
+    )
+  }
+
 }
diff --git a/sc/shared/src/test/scala/sigmastate/ErgoTreeSpecification.scala b/sc/shared/src/test/scala/sigmastate/ErgoTreeSpecification.scala
index 79aaa97f89..477dfec309 100644
--- a/sc/shared/src/test/scala/sigmastate/ErgoTreeSpecification.scala
+++ b/sc/shared/src/test/scala/sigmastate/ErgoTreeSpecification.scala
@@ -561,7 +561,7 @@ class ErgoTreeSpecification extends SigmaDslTesting with ContractsTestkit with C
         MInfo(1, groupGeneratorMethod), MInfo(2, xorMethod)
       ) ++ (if (isV6Activated) {
         // id = 4 reserved for deserializeTo method
-        Seq(MInfo(3, serializeMethod), MInfo(5, fromBigEndianBytesMethod)) // methods added in v6.0
+        Seq(MInfo(3, serializeMethod), MInfo(5, FromBigEndianBytesMethod)) // methods added in v6.0
       } else {
         Seq.empty[MInfo]
       }), true)

From 503f0c723f82bffbfee332c09ddec4cff9c24cf4 Mon Sep 17 00:00:00 2001
From: Alexander Chepurnoy 
Date: Wed, 13 Nov 2024 20:01:09 +0300
Subject: [PATCH 287/314] bitwiseInverse fix, tests fixes

---
 .../src/main/scala/sigma/SigmaDsl.scala       |  6 ++---
 .../main/scala/sigma/crypto/BigIntegers.scala |  3 +--
 .../src/main/scala/sigma/data/CBigInt.scala   | 12 ++++------
 .../main/scala/sigmastate/lang/Types.scala    |  2 +-
 .../scala/sigma/LanguageSpecificationV6.scala | 12 ++++------
 .../utxo/BasicOpsSpecification.scala          | 23 +++++++++++++++++--
 6 files changed, 34 insertions(+), 24 deletions(-)

diff --git a/core/shared/src/main/scala/sigma/SigmaDsl.scala b/core/shared/src/main/scala/sigma/SigmaDsl.scala
index 099f27ae8a..ed593124f2 100644
--- a/core/shared/src/main/scala/sigma/SigmaDsl.scala
+++ b/core/shared/src/main/scala/sigma/SigmaDsl.scala
@@ -1,7 +1,5 @@
 package sigma
 
-import sigma.ast.SType
-
 import java.math.BigInteger
 import sigma.data._
 
@@ -176,8 +174,8 @@ trait BigInt {
   def toUnsigned: UnsignedBigInt
 
   /**
-    * @return unsigned representation of this BigInt modulo `m`. Cryptographic mod operation is done, ie result is
-    *         non-negative always
+    * @return unsigned representation of this BigInt modulo `m`. Cryptographic mod operation is done, so result is
+    *         always non-negative
     */
   def toUnsignedMod(m: UnsignedBigInt): UnsignedBigInt
 }
diff --git a/core/shared/src/main/scala/sigma/crypto/BigIntegers.scala b/core/shared/src/main/scala/sigma/crypto/BigIntegers.scala
index 54a6927924..c7c7b0721e 100644
--- a/core/shared/src/main/scala/sigma/crypto/BigIntegers.scala
+++ b/core/shared/src/main/scala/sigma/crypto/BigIntegers.scala
@@ -13,9 +13,8 @@ object BigIntegers {
   private val MAX_ITERATIONS = 1000
 
   /** Create the given number of random bits.
-    *
     * @param bitLength the number of random bits to create.
-    * @param random    a source of randomness.
+    * @param random a source of randomness.
     * @return a byte array containing random bits.
     */
   @throws[IllegalArgumentException]
diff --git a/core/shared/src/main/scala/sigma/data/CBigInt.scala b/core/shared/src/main/scala/sigma/data/CBigInt.scala
index b8b3ad7a17..3ea57f0899 100644
--- a/core/shared/src/main/scala/sigma/data/CBigInt.scala
+++ b/core/shared/src/main/scala/sigma/data/CBigInt.scala
@@ -57,7 +57,7 @@ case class CBigInt(override val wrappedValue: BigInteger) extends BigInt with Wr
 
   override def shiftRight(n: Int): BigInt = CBigInt(wrappedValue.shiftRight(n).toSignedBigIntValueExact)
 
-  def toUnsigned: UnsignedBigInt = {
+  override def toUnsigned: UnsignedBigInt = {
     if(this.wrappedValue.compareTo(BigInteger.ZERO) < 0){
       throw new ArithmeticException("BigInteger argument for .toUnsigned is negative");
     } else {
@@ -65,9 +65,10 @@ case class CBigInt(override val wrappedValue: BigInteger) extends BigInt with Wr
     }
   }
 
-  def toUnsignedMod(m: UnsignedBigInt): UnsignedBigInt = {
+  override def toUnsignedMod(m: UnsignedBigInt): UnsignedBigInt = {
     CUnsignedBigInt(this.wrappedValue.mod(m.asInstanceOf[CUnsignedBigInt].wrappedValue))
   }
+
 }
 
 /** A default implementation of [[UnsignedBigInt]] interface.
@@ -148,12 +149,7 @@ case class CUnsignedBigInt(override val wrappedValue: BigInteger) extends Unsign
   override def shiftRight(n: Int): UnsignedBigInt = CUnsignedBigInt(wrappedValue.shiftRight(n).toUnsignedBigIntValueExact)
 
   override def bitwiseInverse(): UnsignedBigInt = {
-    val bytes = if(wrappedValue.compareTo(BigInteger.ZERO) == 0) {
-      Array(0: Byte)
-    } else {
-      BigIntegers.asUnsignedByteArray(wrappedValue)
-    }
-
+    val bytes = BigIntegers.asUnsignedByteArray(32, wrappedValue)
     val res: Array[Byte] = bytes.map(b => (~b & 0xff).toByte)
     CUnsignedBigInt(BigIntegers.fromUnsignedByteArray(res))
   }
diff --git a/parsers/shared/src/main/scala/sigmastate/lang/Types.scala b/parsers/shared/src/main/scala/sigmastate/lang/Types.scala
index d928e36f61..4402eb949a 100644
--- a/parsers/shared/src/main/scala/sigmastate/lang/Types.scala
+++ b/parsers/shared/src/main/scala/sigmastate/lang/Types.scala
@@ -34,7 +34,7 @@ trait Types extends Core {
     "Int"     -> SInt,
     "Long"    -> SLong,
     "BigInt"  -> SBigInt,
-    "UnsignedBigInt"  -> SUnsignedBigInt,
+    "UnsignedBigInt"  -> SUnsignedBigInt, // added in 6.0, but put in this map
     "AvlTree" -> SAvlTree,
     "Context" -> SContext,
     "GroupElement" -> SGroupElement,
diff --git a/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala b/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala
index 2c6aaaf74b..2f7b7a8f19 100644
--- a/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala
+++ b/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala
@@ -2265,13 +2265,11 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite =>
 
     verifyCases(
       Seq(
-        CUnsignedBigInt(BigInteger.valueOf(Byte.MaxValue)) -> new Expected(ExpectedResult(Success(CUnsignedBigInt(BigInteger.valueOf(128))), None)),
-        CUnsignedBigInt(BigInteger.valueOf(0)) -> new Expected(ExpectedResult(Success(CUnsignedBigInt(BigInteger.valueOf(255))), None)),
-        CUnsignedBigInt(BigInteger.valueOf(1)) -> new Expected(ExpectedResult(Success(CUnsignedBigInt(BigInteger.valueOf(254))), None)),
-        CUnsignedBigInt(BigInteger.valueOf(2)) -> new Expected(ExpectedResult(Success(CUnsignedBigInt(BigInteger.valueOf(253))), None)),
-        CUnsignedBigInt(BigInteger.valueOf(10001)) -> new Expected(ExpectedResult(Success(CUnsignedBigInt(BigInteger.valueOf(55534))), None)),
-        CUnsignedBigInt(BigInteger.valueOf(Int.MaxValue)) -> new Expected(ExpectedResult(Success(CUnsignedBigInt(BigInteger.valueOf(Int.MaxValue).add(BigInteger.ONE))), None)),
-        CUnsignedBigInt(BigInteger.valueOf(Long.MaxValue)) -> new Expected(ExpectedResult(Success(CUnsignedBigInt(BigInteger.valueOf(Long.MaxValue).add(BigInteger.ONE))), None))
+        CUnsignedBigInt(BigInteger.valueOf(Byte.MaxValue)) -> new Expected(ExpectedResult(Success(CUnsignedBigInt(new BigInteger("115792089237316195423570985008687907853269984665640564039457584007913129639808"))), None)),
+        CUnsignedBigInt(BigInteger.valueOf(0)) -> new Expected(ExpectedResult(Success(CUnsignedBigInt(BigInteger.valueOf(2).pow(256).subtract(BigInteger.ONE))), None)),
+        CUnsignedBigInt(BigInteger.valueOf(1)) -> new Expected(ExpectedResult(Success(CUnsignedBigInt(BigInteger.valueOf(2).pow(256).subtract(BigInteger.valueOf(2)))), None)),
+        CUnsignedBigInt(BigInteger.valueOf(2)) -> new Expected(ExpectedResult(Success(CUnsignedBigInt(BigInteger.valueOf(2).pow(256).subtract(BigInteger.valueOf(3)))), None)),
+        CUnsignedBigInt(BigInteger.valueOf(10001)) -> new Expected(ExpectedResult(Success(CUnsignedBigInt(BigInteger.valueOf(2).pow(256).subtract(BigInteger.valueOf(10002)))), None))
       ),
       bitNot
     )
diff --git a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala
index f7a9fab2ba..b83cdf0438 100644
--- a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala
+++ b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala
@@ -38,6 +38,7 @@ import java.math.BigInteger
 import scala.collection.compat.immutable.ArraySeq
 import java.security.SecureRandom
 import scala.annotation.tailrec
+import scala.util.Try
 
 class BasicOpsSpecification extends CompilerTestingCommons
   with CompilerCrossVersionProps {
@@ -390,6 +391,24 @@ class BasicOpsSpecification extends CompilerTestingCommons
     }
   }
 
+  property("unsigned -> signed overflow") {
+    def conversionTest() = {test("conversion", env, ext,
+      s"""{
+         |  val ub = unsignedBigInt("${CryptoConstants.groupOrder}")
+         |  ub.toSigned > 0
+         | } """.stripMargin,
+      null,
+      true
+    )}
+
+    if (activatedVersionInTests < V6SoftForkVersion) {
+      an[Exception] should be thrownBy conversionTest()
+    } else {
+      val t = Try(conversionTest())
+      t.failed.get.getCause.getMessage.startsWith("BigInteger out of 256 bit range")
+    }
+  }
+
   property("schnorr sig check") {
 
     val g = CGroupElement(SecP256K1Group.generator)
@@ -406,7 +425,7 @@ class BasicOpsSpecification extends CompilerTestingCommons
       val r = randBigInt
 
       val a: GroupElement = g.exp(CBigInt(r.bigInteger))
-      val z = (r + secretKey * BigInt(scorex.crypto.hash.Blake2b256(msg))) % CryptoConstants.groupOrder
+      val z = (r + secretKey * BigInt(scorex.crypto.hash.Blake2b256(msg))).mod(CryptoConstants.groupOrder)
 
       if(z.bitLength > 255) {
         (a, z)
@@ -420,7 +439,7 @@ class BasicOpsSpecification extends CompilerTestingCommons
 
     val message = Array.fill(5)(1.toByte)
 
-    val (a,z) = sign(message, holderSecret)
+    val (a, z) = sign(message, holderSecret)
 
     val customExt: Seq[(Byte, EvaluatedValue[_ <: SType])] = Map(
       0.toByte -> GroupElementConstant(holderPk),

From 6a15e5f30a3bf5370035874ee9b1fee35f60c1c7 Mon Sep 17 00:00:00 2001
From: Alexander Chepurnoy 
Date: Wed, 13 Nov 2024 23:37:34 +0300
Subject: [PATCH 288/314] expUnsigned test

---
 .../src/main/scala/sigma/ast/SType.scala      |  2 +-
 .../scala/sigma/LanguageSpecificationV6.scala | 22 ++++++++++++++++++-
 2 files changed, 22 insertions(+), 2 deletions(-)

diff --git a/core/shared/src/main/scala/sigma/ast/SType.scala b/core/shared/src/main/scala/sigma/ast/SType.scala
index d255adca6b..37e6c66ef3 100644
--- a/core/shared/src/main/scala/sigma/ast/SType.scala
+++ b/core/shared/src/main/scala/sigma/ast/SType.scala
@@ -108,7 +108,7 @@ object SType {
       SGlobal, SHeader, SPreHeader, SAvlTree, SGroupElement, SSigmaProp, SString, SBox,
       SUnit, SAny)
 
-  // V6 types, see `allPredefTypes` scaladoc below
+  // V6 types, see `allPredefTypes` scaladoc below. Contains SUnsignedBigInt type in addition to v5 types.
   private val v6PredefTypes = v5PredefTypes ++ Array(SUnsignedBigInt)
 
   /** All pre-defined types should be listed here. Note, NoType is not listed.
diff --git a/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala b/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala
index 2f7b7a8f19..2c4ce559a3 100644
--- a/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala
+++ b/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala
@@ -11,7 +11,7 @@ import sigma.ast.ErgoTree.{HeaderType, ZeroHeader}
 import sigma.ast.SCollection.SByteArray
 import sigma.ast.syntax.TrueSigmaProp
 import sigma.ast.{SInt, _}
-import sigma.data.{AvlTreeData, AvlTreeFlags, CAnyValue, CAvlTree, CBigInt, CBox, CHeader, CSigmaDslBuilder, CSigmaProp, CUnsignedBigInt, ExactNumeric, PairOfCols, ProveDHTuple, RType}
+import sigma.data.{AvlTreeData, AvlTreeFlags, CAnyValue, CAvlTree, CBigInt, CBox, CGroupElement, CHeader, CSigmaDslBuilder, CSigmaProp, CUnsignedBigInt, ExactNumeric, PairOfCols, ProveDHTuple, RType}
 import sigma.eval.{CostDetails, SigmaDsl, TracedCost}
 import sigma.serialization.ValueCodes.OpCode
 import sigma.util.Extensions.{BooleanOps, IntOps}
@@ -23,6 +23,7 @@ import sigmastate.exceptions.MethodNotFound
 import sigmastate.utils.Extensions.ByteOpsForSigma
 import sigmastate.utils.Helpers
 import sigma.Extensions.{ArrayOps, CollOps}
+import sigma.crypto.CryptoConstants
 import sigma.interpreter.{ContextExtension, ProverResult}
 
 import java.math.BigInteger
@@ -2417,5 +2418,24 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite =>
       preGeneratedSamples = Some(Seq())
     )
   }
+  
+  property("GroupElement.expUnsigned") {
+    import sigma.data.OrderingOps.UnsignedBigIntOrdering
+
+    val f = newFeature[(GroupElement, UnsignedBigInt), GroupElement](
+      { (xs: (GroupElement, UnsignedBigInt)) => xs._1.expUnsigned(xs._2) },
+      """{ (xs: (GroupElement, UnsignedBigInt)) => xs._1.expUnsigned(xs._2) }""".stripMargin,
+      sinceVersion = VersionContext.V6SoftForkVersion
+    )
+
+    verifyCases(
+      Seq(
+        (CGroupElement(CryptoConstants.dlogGroup.generator), CUnsignedBigInt(new BigInteger("1"))) -> Expected(ExpectedResult(Success(CGroupElement(CryptoConstants.dlogGroup.generator)), None)),
+        (CGroupElement(CryptoConstants.dlogGroup.generator), CUnsignedBigInt(new BigInteger("0"))) -> Expected(ExpectedResult(Success(CGroupElement(CryptoConstants.dlogGroup.identity)), None)),
+        (CGroupElement(CryptoConstants.dlogGroup.generator), CUnsignedBigInt(CryptoConstants.dlogGroup.order)) -> Expected(ExpectedResult(Success(CGroupElement(CryptoConstants.dlogGroup.identity)), None))
+      ),
+      f
+    )
+  }
 
 }

From b0e41a87811c00b2174911d3257bd6da79d74ece Mon Sep 17 00:00:00 2001
From: Alexander Chepurnoy 
Date: Thu, 14 Nov 2024 16:38:45 +0300
Subject: [PATCH 289/314] mod ops tests

---
 .../scala/sigma/LanguageSpecificationV6.scala | 221 ++++++++++++++++--
 1 file changed, 200 insertions(+), 21 deletions(-)

diff --git a/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala b/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala
index 2c4ce559a3..b5d7d59a06 100644
--- a/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala
+++ b/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala
@@ -2208,11 +2208,30 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite =>
     )
   }
 
+  property("GroupElement.expUnsigned") {
+    import sigma.data.OrderingOps.UnsignedBigIntOrdering
+
+    val f = newFeature[(GroupElement, UnsignedBigInt), GroupElement](
+      { (xs: (GroupElement, UnsignedBigInt)) => xs._1.expUnsigned(xs._2) },
+      """{ (xs: (GroupElement, UnsignedBigInt)) => xs._1.expUnsigned(xs._2) }""".stripMargin,
+      sinceVersion = VersionContext.V6SoftForkVersion
+    )
+
+    verifyCases(
+      Seq(
+        (CGroupElement(CryptoConstants.dlogGroup.generator), CUnsignedBigInt(new BigInteger("1"))) -> Expected(ExpectedResult(Success(CGroupElement(CryptoConstants.dlogGroup.generator)), None)),
+        (CGroupElement(CryptoConstants.dlogGroup.generator), CUnsignedBigInt(new BigInteger("0"))) -> Expected(ExpectedResult(Success(CGroupElement(CryptoConstants.dlogGroup.identity)), None)),
+        (CGroupElement(CryptoConstants.dlogGroup.generator), CUnsignedBigInt(CryptoConstants.dlogGroup.order)) -> Expected(ExpectedResult(Success(CGroupElement(CryptoConstants.dlogGroup.identity)), None))
+      ),
+      f
+    )
+  }
+
   property("UnsignedBigInt methods") {
     import sigma.data.OrderingOps.UnsignedBigIntOrdering
 
     lazy val bitOr = newFeature[(UnsignedBigInt, UnsignedBigInt), UnsignedBigInt](
-      { (x: (UnsignedBigInt, UnsignedBigInt)) => (x._1 | x._2)},
+      { (x: (UnsignedBigInt, UnsignedBigInt)) => (x._1 | x._2) },
       "{ (x: (UnsignedBigInt, UnsignedBigInt)) => x._1.bitwiseOr(x._2) }",
       if (VersionContext.current.isV6SoftForkActivated) {
         FuncValue(
@@ -2306,7 +2325,7 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite =>
         MethodCall.typed[Value[SUnsignedBigInt.type]](
           SelectField.typed[Value[SUnsignedBigInt.type]](ValUse(1, SPair(SUnsignedBigInt, SUnsignedBigInt)), 1.toByte),
           SUnsignedBigIntMethods.v6Methods.find(_.name == "bitwiseXor").get,
-          Vector(SelectField.typed[Value[SUnsignedBigInt.type]](ValUse(1, SPair(SUnsignedBigInt, SUnsignedBigInt)),2.toByte)),
+          Vector(SelectField.typed[Value[SUnsignedBigInt.type]](ValUse(1, SPair(SUnsignedBigInt, SUnsignedBigInt)), 2.toByte)),
           Map()
         )
       ),
@@ -2350,7 +2369,7 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite =>
       ((byte >> bit) & 1) == 1
 
     lazy val toBits = newFeature[UnsignedBigInt, Coll[Boolean]](
-      { x: UnsignedBigInt => x.toBytes.flatMap(b => Colls.fromArray(byte2Bools(b).toArray))  },
+      { x: UnsignedBigInt => x.toBytes.flatMap(b => Colls.fromArray(byte2Bools(b).toArray)) },
       "{ (x: UnsignedBigInt) => x.toBits }",
       FuncValue(
         Array((1, SUnsignedBigInt)),
@@ -2371,7 +2390,7 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite =>
     )
 
     lazy val shiftLeft = newFeature(
-      { (x: (UnsignedBigInt, Int)) => if(x._2 < 0 || x._2 >= 256) throw new IllegalArgumentException() else (x._1.asInstanceOf[UnsignedBigInt].shiftLeft(x._2)) },
+      { (x: (UnsignedBigInt, Int)) => if (x._2 < 0 || x._2 >= 256) throw new IllegalArgumentException() else (x._1.asInstanceOf[UnsignedBigInt].shiftLeft(x._2)) },
       "{ (x: (UnsignedBigInt, Int)) => x._1.shiftLeft(x._2) }",
       FuncValue(
         Array((1, SPair(SUnsignedBigInt, SInt))),
@@ -2389,12 +2408,11 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite =>
         (CUnsignedBigInt(BigInteger.valueOf(3)), 3) -> new Expected(ExpectedResult(Success(CUnsignedBigInt(BigInteger.valueOf(24))), None)),
         (CUnsignedBigInt(BigInteger.valueOf(3)), 8) -> new Expected(ExpectedResult(Success(CUnsignedBigInt(BigInteger.valueOf(768))), None))
       ),
-      shiftLeft,
-      preGeneratedSamples = Some(Seq())
+      shiftLeft
     )
 
     lazy val shiftRight = newFeature(
-      { (x: (UnsignedBigInt, Int)) => if(x._2 < 0 || x._2 >= 256) throw new IllegalArgumentException() else (x._1.asInstanceOf[UnsignedBigInt].shiftRight(x._2)) },
+      { (x: (UnsignedBigInt, Int)) => if (x._2 < 0 || x._2 >= 256) throw new IllegalArgumentException() else (x._1.asInstanceOf[UnsignedBigInt].shiftRight(x._2)) },
       "{ (x: (UnsignedBigInt, Int)) => x._1.shiftRight(x._2) }",
       FuncValue(
         Array((1, SPair(SUnsignedBigInt, SInt))),
@@ -2414,28 +2432,189 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite =>
         (CUnsignedBigInt(BigInteger.valueOf(24)), -1) -> new Expected(ExpectedResult(Failure(new IllegalArgumentException()), None)),
         (CUnsignedBigInt(BigInteger.valueOf(24)), 256) -> new Expected(ExpectedResult(Failure(new IllegalArgumentException()), None))
       ),
-      shiftRight,
-      preGeneratedSamples = Some(Seq())
+      shiftRight
     )
-  }
-  
-  property("GroupElement.expUnsigned") {
-    import sigma.data.OrderingOps.UnsignedBigIntOrdering
 
-    val f = newFeature[(GroupElement, UnsignedBigInt), GroupElement](
-      { (xs: (GroupElement, UnsignedBigInt)) => xs._1.expUnsigned(xs._2) },
-      """{ (xs: (GroupElement, UnsignedBigInt)) => xs._1.expUnsigned(xs._2) }""".stripMargin,
-      sinceVersion = VersionContext.V6SoftForkVersion
+    lazy val plusMod = newFeature(
+      { (x: (UnsignedBigInt, (UnsignedBigInt, UnsignedBigInt))) => x._1.asInstanceOf[UnsignedBigInt].plusMod(x._2._1, x._2._2) },
+      "{ (x: (UnsignedBigInt, (UnsignedBigInt, UnsignedBigInt))) => x._1.plusMod(x._2._1, x._2._2) }",
+      FuncValue(
+        Array((1, SPair(SUnsignedBigInt, SPair(SUnsignedBigInt, SUnsignedBigInt)))),
+        BlockValue(
+          Array(
+            ValDef(
+              3,
+              List(),
+              SelectField.typed[Value[STuple]](
+                ValUse(1, SPair(SUnsignedBigInt, SPair(SUnsignedBigInt, SUnsignedBigInt))),
+                2.toByte
+              )
+            )
+          ),
+          MethodCall.typed[Value[SUnsignedBigInt.type]](
+            SelectField.typed[Value[SUnsignedBigInt.type]](
+              ValUse(1, SPair(SUnsignedBigInt, SPair(SUnsignedBigInt, SUnsignedBigInt))),
+              1.toByte
+            ),
+            SUnsignedBigIntMethods.getMethodByName("plusMod"),
+            Array(
+              SelectField.typed[Value[SUnsignedBigInt.type]](
+                ValUse(3, SPair(SUnsignedBigInt, SUnsignedBigInt)),
+                1.toByte
+              ),
+              SelectField.typed[Value[SUnsignedBigInt.type]](
+                ValUse(3, SPair(SUnsignedBigInt, SUnsignedBigInt)),
+                2.toByte
+              )
+            ),
+            Map()
+          )
+        )
+      ),
+      sinceVersion = V6SoftForkVersion)
+
+    verifyCases(
+      Seq(
+        (CUnsignedBigInt(BigInteger.valueOf(24)),
+          (CUnsignedBigInt(BigInteger.valueOf(24)), CUnsignedBigInt(BigInteger.valueOf(10)))) ->
+          new Expected(ExpectedResult(Success(CUnsignedBigInt(BigInteger.valueOf(8))), None)),
+        (CUnsignedBigInt(BigInteger.valueOf(24)),
+          (CUnsignedBigInt(BigInteger.valueOf(24)), CUnsignedBigInt(BigInteger.valueOf(24)))) ->
+          new Expected(ExpectedResult(Success(CUnsignedBigInt(BigInteger.valueOf(0))), None)),
+        (CUnsignedBigInt(CryptoConstants.groupOrder),
+          (CUnsignedBigInt(CryptoConstants.groupOrder), CUnsignedBigInt(CryptoConstants.groupOrder))) ->
+          new Expected(ExpectedResult(Success(CUnsignedBigInt(BigInteger.valueOf(0))), None))
+      ),
+      plusMod
     )
 
+    lazy val subtractMod = newFeature(
+      { (x: (UnsignedBigInt, (UnsignedBigInt, UnsignedBigInt))) => x._1.asInstanceOf[UnsignedBigInt].subtractMod(x._2._1, x._2._2) },
+      "{ (x: (UnsignedBigInt, (UnsignedBigInt, UnsignedBigInt))) => x._1.subtractMod(x._2._1, x._2._2) }",
+      FuncValue(
+        Array((1, SPair(SUnsignedBigInt, SPair(SUnsignedBigInt, SUnsignedBigInt)))),
+        BlockValue(
+          Array(
+            ValDef(
+              3,
+              List(),
+              SelectField.typed[Value[STuple]](
+                ValUse(1, SPair(SUnsignedBigInt, SPair(SUnsignedBigInt, SUnsignedBigInt))),
+                2.toByte
+              )
+            )
+          ),
+          MethodCall.typed[Value[SUnsignedBigInt.type]](
+            SelectField.typed[Value[SUnsignedBigInt.type]](
+              ValUse(1, SPair(SUnsignedBigInt, SPair(SUnsignedBigInt, SUnsignedBigInt))),
+              1.toByte
+            ),
+            SUnsignedBigIntMethods.getMethodByName("subtractMod"),
+            Array(
+              SelectField.typed[Value[SUnsignedBigInt.type]](
+                ValUse(3, SPair(SUnsignedBigInt, SUnsignedBigInt)),
+                1.toByte
+              ),
+              SelectField.typed[Value[SUnsignedBigInt.type]](
+                ValUse(3, SPair(SUnsignedBigInt, SUnsignedBigInt)),
+                2.toByte
+              )
+            ),
+            Map()
+          )
+        )
+      ),
+      sinceVersion = V6SoftForkVersion)
+
     verifyCases(
       Seq(
-        (CGroupElement(CryptoConstants.dlogGroup.generator), CUnsignedBigInt(new BigInteger("1"))) -> Expected(ExpectedResult(Success(CGroupElement(CryptoConstants.dlogGroup.generator)), None)),
-        (CGroupElement(CryptoConstants.dlogGroup.generator), CUnsignedBigInt(new BigInteger("0"))) -> Expected(ExpectedResult(Success(CGroupElement(CryptoConstants.dlogGroup.identity)), None)),
-        (CGroupElement(CryptoConstants.dlogGroup.generator), CUnsignedBigInt(CryptoConstants.dlogGroup.order)) -> Expected(ExpectedResult(Success(CGroupElement(CryptoConstants.dlogGroup.identity)), None))
+        (CUnsignedBigInt(BigInteger.valueOf(0)),
+          (CUnsignedBigInt(BigInteger.valueOf(24)), CUnsignedBigInt(BigInteger.valueOf(10)))) ->
+          new Expected(ExpectedResult(Success(CUnsignedBigInt(BigInteger.valueOf(6))), None)),
+        (CUnsignedBigInt(BigInteger.valueOf(24)),
+          (CUnsignedBigInt(BigInteger.valueOf(24)), CUnsignedBigInt(BigInteger.valueOf(24)))) ->
+          new Expected(ExpectedResult(Success(CUnsignedBigInt(BigInteger.valueOf(0))), None))
       ),
-      f
+      subtractMod
     )
+
+    lazy val multiplyMod = newFeature(
+      { (x: (UnsignedBigInt, (UnsignedBigInt, UnsignedBigInt))) => x._1.asInstanceOf[UnsignedBigInt].multiplyMod(x._2._1, x._2._2) },
+      "{ (x: (UnsignedBigInt, (UnsignedBigInt, UnsignedBigInt))) => x._1.multiplyMod(x._2._1, x._2._2) }",
+      FuncValue(
+        Array((1, SPair(SUnsignedBigInt, SPair(SUnsignedBigInt, SUnsignedBigInt)))),
+        BlockValue(
+          Array(
+            ValDef(
+              3,
+              List(),
+              SelectField.typed[Value[STuple]](
+                ValUse(1, SPair(SUnsignedBigInt, SPair(SUnsignedBigInt, SUnsignedBigInt))),
+                2.toByte
+              )
+            )
+          ),
+          MethodCall.typed[Value[SUnsignedBigInt.type]](
+            SelectField.typed[Value[SUnsignedBigInt.type]](
+              ValUse(1, SPair(SUnsignedBigInt, SPair(SUnsignedBigInt, SUnsignedBigInt))),
+              1.toByte
+            ),
+            SUnsignedBigIntMethods.getMethodByName("multiplyMod"),
+            Array(
+              SelectField.typed[Value[SUnsignedBigInt.type]](
+                ValUse(3, SPair(SUnsignedBigInt, SUnsignedBigInt)),
+                1.toByte
+              ),
+              SelectField.typed[Value[SUnsignedBigInt.type]](
+                ValUse(3, SPair(SUnsignedBigInt, SUnsignedBigInt)),
+                2.toByte
+              )
+            ),
+            Map()
+          )
+        )
+      ),
+      sinceVersion = V6SoftForkVersion)
+
+    verifyCases(
+      Seq(
+        (CUnsignedBigInt(CryptoConstants.groupOrder),
+          (CUnsignedBigInt(CryptoConstants.groupOrder), CUnsignedBigInt(CryptoConstants.groupOrder))) ->
+          new Expected(ExpectedResult(Success(CUnsignedBigInt(BigInteger.valueOf(0))), None))
+      ),
+      multiplyMod
+    )
+
+    lazy val modInverse = newFeature(
+      { (x: (UnsignedBigInt, UnsignedBigInt)) => x._1.asInstanceOf[UnsignedBigInt].modInverse(x._2) },
+      "{ (x: (UnsignedBigInt, UnsignedBigInt)) => x._1.modInverse(x._2) }",
+      FuncValue(
+        Array((1, SPair(SUnsignedBigInt, SUnsignedBigInt))),
+        MethodCall.typed[Value[SUnsignedBigInt.type]](
+          SelectField.typed[Value[SUnsignedBigInt.type]](
+            ValUse(1, SPair(SUnsignedBigInt, SUnsignedBigInt)),
+            1.toByte
+          ),
+          SUnsignedBigIntMethods.getMethodByName("modInverse"),
+          Array(
+            SelectField.typed[Value[SUnsignedBigInt.type]](
+              ValUse(1, SPair(SUnsignedBigInt, SUnsignedBigInt)),
+              2.toByte
+            )
+          ),
+          Map()
+        )
+      ),
+      sinceVersion = V6SoftForkVersion)
+
+    verifyCases(
+      Seq(
+        (CUnsignedBigInt(BigInteger.valueOf(12)), CUnsignedBigInt(BigInteger.valueOf(5))) ->
+          new Expected(ExpectedResult(Success(CUnsignedBigInt(BigInteger.valueOf(3))), None))
+      ),
+      modInverse
+    )
+
   }
 
 }

From 8da5f8989ddd5624501399db7cac2ca1aba82c79 Mon Sep 17 00:00:00 2001
From: Alexander Chepurnoy 
Date: Thu, 14 Nov 2024 16:54:40 +0300
Subject: [PATCH 290/314] _eval mathods removed

---
 .../src/main/scala/sigma/ast/methods.scala    | 36 -------------------
 1 file changed, 36 deletions(-)

diff --git a/data/shared/src/main/scala/sigma/ast/methods.scala b/data/shared/src/main/scala/sigma/ast/methods.scala
index ce8e71eef7..10475ad23c 100644
--- a/data/shared/src/main/scala/sigma/ast/methods.scala
+++ b/data/shared/src/main/scala/sigma/ast/methods.scala
@@ -551,63 +551,27 @@ case object SUnsignedBigIntMethods extends SNumericTypeMethods {
     .withIRInfo(MethodCallIrBuilder)
     .withInfo(MethodCall, "")
 
-  def modInverse_eval(mc: MethodCall, bi: UnsignedBigInt, m: UnsignedBigInt)
-              (implicit E: ErgoTreeEvaluator): UnsignedBigInt = {
-    E.addCost(ModInverseCostInfo.costKind, mc.method.opDesc)
-    bi.modInverse(m)
-  }
-
   // todo: costing
   val PlusModMethod = SMethod(this, "plusMod", SFunc(Array(this.ownerType, this.ownerType, this.ownerType), this.ownerType), 15, ModInverseCostInfo.costKind)
     .withIRInfo(MethodCallIrBuilder)
     .withInfo(MethodCall, "")
 
-  def plusMod_eval(mc: MethodCall, bi: UnsignedBigInt, bi2: UnsignedBigInt, m: UnsignedBigInt)
-                     (implicit E: ErgoTreeEvaluator): UnsignedBigInt = {
-    E.addCost(ModInverseCostInfo.costKind, mc.method.opDesc) // todo: costing
-    bi.plusMod(bi2, m)
-  }
-
   val SubtractModMethod = SMethod(this, "subtractMod", SFunc(Array(this.ownerType, this.ownerType, this.ownerType), this.ownerType), 16, ModInverseCostInfo.costKind)
     .withIRInfo(MethodCallIrBuilder)
     .withInfo(MethodCall, "")
 
-  def subtractMod_eval(mc: MethodCall, bi: UnsignedBigInt, bi2: UnsignedBigInt, m: UnsignedBigInt)
-                  (implicit E: ErgoTreeEvaluator): UnsignedBigInt = {
-    E.addCost(ModInverseCostInfo.costKind, mc.method.opDesc) // todo: costing
-    bi.subtractMod(bi2, m)
-  }
-
   val MultiplyModMethod = SMethod(this, "multiplyMod", SFunc(Array(this.ownerType, this.ownerType, this.ownerType), this.ownerType), 17, ModInverseCostInfo.costKind)
     .withIRInfo(MethodCallIrBuilder)
     .withInfo(MethodCall, "")
 
-  def multiplyMod_eval(mc: MethodCall, bi: UnsignedBigInt, bi2: UnsignedBigInt, m: UnsignedBigInt)
-                  (implicit E: ErgoTreeEvaluator): UnsignedBigInt = {
-    E.addCost(ModInverseCostInfo.costKind, mc.method.opDesc) // todo: costing
-    bi.multiplyMod(bi2, m)
-  }
-
   val ModMethod = SMethod(this, "mod", SFunc(Array(this.ownerType, this.ownerType), this.ownerType), 18, ModInverseCostInfo.costKind)
     .withIRInfo(MethodCallIrBuilder)
     .withInfo(MethodCall, "")
 
-  def mod_eval(mc: MethodCall, bi: UnsignedBigInt, m: UnsignedBigInt)
-                      (implicit E: ErgoTreeEvaluator): UnsignedBigInt = {
-    E.addCost(ModInverseCostInfo.costKind, mc.method.opDesc) // todo: costing
-    bi.mod(m)
-  }
-
   val ToSignedMethod = SMethod(this, "toSigned", SFunc(Array(this.ownerType), SBigInt), 19, ModInverseCostInfo.costKind)
     .withIRInfo(MethodCallIrBuilder)
     .withInfo(MethodCall, "")
 
-  def toSigned_eval(mc: MethodCall, bi: UnsignedBigInt)
-              (implicit E: ErgoTreeEvaluator): BigInt = {
-    E.addCost(ModInverseCostInfo.costKind, mc.method.opDesc) // todo: costing
-    bi.toSigned()
-  }
-
   // no 6.0 versioning here as it is done in method containers
   protected override def getMethods(): Seq[SMethod]  = {
     super.getMethods() ++ Seq(

From 11bc3d0fac29406b0989632e801a074b818037bb Mon Sep 17 00:00:00 2001
From: Alexander Chepurnoy 
Date: Thu, 14 Nov 2024 18:01:43 +0300
Subject: [PATCH 291/314] More descriptions, some code cleaning

---
 .../src/main/scala/sigma/ast/methods.scala    | 27 +++++++++----------
 1 file changed, 12 insertions(+), 15 deletions(-)

diff --git a/data/shared/src/main/scala/sigma/ast/methods.scala b/data/shared/src/main/scala/sigma/ast/methods.scala
index 10475ad23c..d2ad912bc6 100644
--- a/data/shared/src/main/scala/sigma/ast/methods.scala
+++ b/data/shared/src/main/scala/sigma/ast/methods.scala
@@ -541,36 +541,36 @@ case object SUnsignedBigIntMethods extends SNumericTypeMethods {
   /** Type for which this container defines methods. */
   override def ownerType: SMonoType = SUnsignedBigInt
 
-  final val ToNBitsCostInfo = OperationCostInfo(
-    FixedCost(JitCost(5)), NamedDesc("NBitsMethodCall"))
-
   // todo: costing
-  final val ModInverseCostInfo = ToNBitsCostInfo
+  final val ModInverseCostInfo = OperationCostInfo(
+    FixedCost(JitCost(5)), NamedDesc("NBitsMethodCall"))
 
   val ModInverseMethod = SMethod(this, "modInverse", SFunc(Array(this.ownerType, this.ownerType), this.ownerType), 14, ModInverseCostInfo.costKind)
     .withIRInfo(MethodCallIrBuilder)
-    .withInfo(MethodCall, "")
+    .withInfo(MethodCall,
+      "Computes modular inverse of a value. Modular inverse of A mod C is the B value that makes A * B mod C = 1.",
+      ArgInfo("m", "modulo value")
+    )
 
-  // todo: costing
   val PlusModMethod = SMethod(this, "plusMod", SFunc(Array(this.ownerType, this.ownerType, this.ownerType), this.ownerType), 15, ModInverseCostInfo.costKind)
     .withIRInfo(MethodCallIrBuilder)
-    .withInfo(MethodCall, "")
+    .withInfo(MethodCall, "Modular addition", ArgInfo("that", "Addend") , ArgInfo("m", "modulo value"))
 
   val SubtractModMethod = SMethod(this, "subtractMod", SFunc(Array(this.ownerType, this.ownerType, this.ownerType), this.ownerType), 16, ModInverseCostInfo.costKind)
     .withIRInfo(MethodCallIrBuilder)
-    .withInfo(MethodCall, "")
+    .withInfo(MethodCall, "Modular subtraction", ArgInfo("that", "Subtrahend") , ArgInfo("m", "modulo value"))
 
   val MultiplyModMethod = SMethod(this, "multiplyMod", SFunc(Array(this.ownerType, this.ownerType, this.ownerType), this.ownerType), 17, ModInverseCostInfo.costKind)
     .withIRInfo(MethodCallIrBuilder)
-    .withInfo(MethodCall, "")
+    .withInfo(MethodCall, "Modular multiplication", ArgInfo("that", "Multiplier") , ArgInfo("m", "modulo value"))
 
   val ModMethod = SMethod(this, "mod", SFunc(Array(this.ownerType, this.ownerType), this.ownerType), 18, ModInverseCostInfo.costKind)
     .withIRInfo(MethodCallIrBuilder)
-    .withInfo(MethodCall, "")
+    .withInfo(MethodCall, "Cryptographic modulo operation", ArgInfo("m", "Modulo value"))
 
   val ToSignedMethod = SMethod(this, "toSigned", SFunc(Array(this.ownerType), SBigInt), 19, ModInverseCostInfo.costKind)
     .withIRInfo(MethodCallIrBuilder)
-    .withInfo(MethodCall, "")
+    .withInfo(MethodCall, "Convert this unsigned big int to signed (with possible exception if leftmost bit is set to 1).")
 
   // no 6.0 versioning here as it is done in method containers
   protected override def getMethods(): Seq[SMethod]  = {
@@ -616,7 +616,7 @@ case object SGroupElementMethods extends MonoTypeMethods {
       ArgInfo("k", "The power"))
 
   lazy val ExponentiateUnsignedMethod: SMethod = SMethod(
-    this, "expUnsigned", SFunc(Array(this.ownerType, SUnsignedBigInt), this.ownerType), 6, Exponentiate.costKind) // todo: recheck costing
+    this, "expUnsigned", SFunc(Array(this.ownerType, SUnsignedBigInt), this.ownerType), 6, Exponentiate.costKind)
     .withIRInfo(MethodCallIrBuilder)
     .withInfo("Exponentiate this \\lst{GroupElement} to the given number. Returns this to the power of k",
       ArgInfo("k", "The power"))
@@ -654,9 +654,6 @@ case object SGroupElementMethods extends MonoTypeMethods {
     })
   }
 
-  def expUnsigned_eval(mc: MethodCall, power: UnsignedBigInt)(implicit E: ErgoTreeEvaluator): GroupElement = {
-    ???
-  }
 }
 
 /** Methods of type `SigmaProp` which represent sigma-protocol propositions. */

From 8c5172be9c5c5191b4cded39b7e4aba620083a3a Mon Sep 17 00:00:00 2001
From: Alexander Chepurnoy 
Date: Thu, 14 Nov 2024 18:23:10 +0300
Subject: [PATCH 292/314] costing

---
 .../src/main/scala/sigma/ast/methods.scala    | 24 ++++++++++++-------
 1 file changed, 16 insertions(+), 8 deletions(-)

diff --git a/data/shared/src/main/scala/sigma/ast/methods.scala b/data/shared/src/main/scala/sigma/ast/methods.scala
index d2ad912bc6..f3ee0ad8a9 100644
--- a/data/shared/src/main/scala/sigma/ast/methods.scala
+++ b/data/shared/src/main/scala/sigma/ast/methods.scala
@@ -541,9 +541,7 @@ case object SUnsignedBigIntMethods extends SNumericTypeMethods {
   /** Type for which this container defines methods. */
   override def ownerType: SMonoType = SUnsignedBigInt
 
-  // todo: costing
-  final val ModInverseCostInfo = OperationCostInfo(
-    FixedCost(JitCost(5)), NamedDesc("NBitsMethodCall"))
+  final val ModInverseCostInfo = OperationCostInfo(FixedCost(JitCost(30)), NamedDesc("ModInverseMethodCall"))
 
   val ModInverseMethod = SMethod(this, "modInverse", SFunc(Array(this.ownerType, this.ownerType), this.ownerType), 14, ModInverseCostInfo.costKind)
     .withIRInfo(MethodCallIrBuilder)
@@ -552,23 +550,33 @@ case object SUnsignedBigIntMethods extends SNumericTypeMethods {
       ArgInfo("m", "modulo value")
     )
 
-  val PlusModMethod = SMethod(this, "plusMod", SFunc(Array(this.ownerType, this.ownerType, this.ownerType), this.ownerType), 15, ModInverseCostInfo.costKind)
+  final val PlusModCostInfo = OperationCostInfo(FixedCost(JitCost(30)), NamedDesc("ModInverseMethodCall"))
+
+  val PlusModMethod = SMethod(this, "plusMod", SFunc(Array(this.ownerType, this.ownerType, this.ownerType), this.ownerType), 15, PlusModCostInfo.costKind)
     .withIRInfo(MethodCallIrBuilder)
     .withInfo(MethodCall, "Modular addition", ArgInfo("that", "Addend") , ArgInfo("m", "modulo value"))
 
-  val SubtractModMethod = SMethod(this, "subtractMod", SFunc(Array(this.ownerType, this.ownerType, this.ownerType), this.ownerType), 16, ModInverseCostInfo.costKind)
+  final val SubtractModCostInfo = OperationCostInfo(FixedCost(JitCost(30)), NamedDesc("SubtractModMethodCall"))
+
+  val SubtractModMethod = SMethod(this, "subtractMod", SFunc(Array(this.ownerType, this.ownerType, this.ownerType), this.ownerType), 16, SubtractModCostInfo.costKind)
     .withIRInfo(MethodCallIrBuilder)
     .withInfo(MethodCall, "Modular subtraction", ArgInfo("that", "Subtrahend") , ArgInfo("m", "modulo value"))
 
-  val MultiplyModMethod = SMethod(this, "multiplyMod", SFunc(Array(this.ownerType, this.ownerType, this.ownerType), this.ownerType), 17, ModInverseCostInfo.costKind)
+  final val MultiplyModCostInfo = OperationCostInfo(FixedCost(JitCost(40)), NamedDesc("MultiplyModMethodCall"))
+
+  val MultiplyModMethod = SMethod(this, "multiplyMod", SFunc(Array(this.ownerType, this.ownerType, this.ownerType), this.ownerType), 17, MultiplyModCostInfo.costKind)
     .withIRInfo(MethodCallIrBuilder)
     .withInfo(MethodCall, "Modular multiplication", ArgInfo("that", "Multiplier") , ArgInfo("m", "modulo value"))
 
-  val ModMethod = SMethod(this, "mod", SFunc(Array(this.ownerType, this.ownerType), this.ownerType), 18, ModInverseCostInfo.costKind)
+  final val ModCostInfo = OperationCostInfo(FixedCost(JitCost(20)), NamedDesc("ModMethodCall"))
+
+  val ModMethod = SMethod(this, "mod", SFunc(Array(this.ownerType, this.ownerType), this.ownerType), 18, ModCostInfo.costKind)
     .withIRInfo(MethodCallIrBuilder)
     .withInfo(MethodCall, "Cryptographic modulo operation", ArgInfo("m", "Modulo value"))
 
-  val ToSignedMethod = SMethod(this, "toSigned", SFunc(Array(this.ownerType), SBigInt), 19, ModInverseCostInfo.costKind)
+  final val ToSignedCostInfo = OperationCostInfo(FixedCost(JitCost(10)), NamedDesc("ToSignedMethodCall"))
+
+  val ToSignedMethod = SMethod(this, "toSigned", SFunc(Array(this.ownerType), SBigInt), 19, ToSignedCostInfo.costKind)
     .withIRInfo(MethodCallIrBuilder)
     .withInfo(MethodCall, "Convert this unsigned big int to signed (with possible exception if leftmost bit is set to 1).")
 

From dd3364207921c34b5d12c41c424d0768b853b104 Mon Sep 17 00:00:00 2001
From: Alexander Chepurnoy 
Date: Thu, 14 Nov 2024 18:39:43 +0300
Subject: [PATCH 293/314] arith test

---
 .../sigma/compiler/ir/GraphBuilding.scala     |  4 +++-
 .../utxo/BasicOpsSpecification.scala          | 21 +++++++++++++++++++
 2 files changed, 24 insertions(+), 1 deletion(-)

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 18ce41497d..08fa21f7e9 100644
--- a/sc/shared/src/main/scala/sigma/compiler/ir/GraphBuilding.scala
+++ b/sc/shared/src/main/scala/sigma/compiler/ir/GraphBuilding.scala
@@ -346,7 +346,9 @@ trait GraphBuilding extends Base with DefRewriting { IR: IRContext =>
     (ByteElement,   ByteIsExactIntegral),
     (ShortElement,  ShortIsExactIntegral),
     (IntElement,    IntIsExactIntegral),
-    (LongElement,   LongIsExactIntegral)
+    (LongElement,   LongIsExactIntegral),
+    (bigIntElement, BigIntIsExactIntegral),
+    (unsignedBigIntElement, UnsignedBigIntIsExactIntegral)
   )
   protected lazy val elemToExactOrderingMap = Map[Elem[_], ExactOrdering[_]](
     (ByteElement,   ByteIsExactOrdering),
diff --git a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala
index b83cdf0438..d02b2666a1 100644
--- a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala
+++ b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala
@@ -481,6 +481,27 @@ class BasicOpsSpecification extends CompilerTestingCommons
     }
   }
 
+  property("unsigned bigint - arith") {
+    def miTest() = {
+      test("modInverse", env, ext,
+        s"""{
+           |   val bi1 = unsignedBigInt("248486720836984554860790790898080606")
+           |   val bi2 = unsignedBigInt("2484867208369845548607907908980997780606")
+           |   val m = (bi1 * bi1 + bi2 * bi1) / bi1 - bi2
+           |   m > 0
+           |}""".stripMargin,
+        null,
+        true
+      )
+    }
+
+    if (activatedVersionInTests < V6SoftForkVersion) {
+      an[Exception] should be thrownBy miTest()
+    } else {
+      miTest()
+    }
+  }
+
   property("mod") {
     def miTest() = {
       test("mod", env, ext,

From 8109a2887bfd43dff5b550ef7f6f661f731d0145 Mon Sep 17 00:00:00 2001
From: Alexander Chepurnoy 
Date: Thu, 14 Nov 2024 19:42:00 +0300
Subject: [PATCH 294/314] embeddable type list / serializers versioning, code
 cleaning , toUnsigned costing

---
 .../src/main/scala/sigma/SigmaDsl.scala       |  8 +++++-
 .../src/main/scala/sigma/ast/SType.scala      | 11 +++++---
 .../src/main/scala/sigma/data/CBigInt.scala   |  3 +++
 .../scala/sigma/reflection/StaticImpl.scala   |  4 +--
 .../serialization/CoreDataSerializer.scala    |  6 ++---
 .../sigma/serialization/TypeSerializer.scala  | 13 ++++++++--
 .../src/main/scala/sigma/ast/methods.scala    | 26 +++++--------------
 .../TypeSerializerSpecification.scala         |  3 ++-
 .../sigma/compiler/ir/GraphBuilding.scala     |  4 +--
 9 files changed, 42 insertions(+), 36 deletions(-)

diff --git a/core/shared/src/main/scala/sigma/SigmaDsl.scala b/core/shared/src/main/scala/sigma/SigmaDsl.scala
index ed593124f2..50b5aea92c 100644
--- a/core/shared/src/main/scala/sigma/SigmaDsl.scala
+++ b/core/shared/src/main/scala/sigma/SigmaDsl.scala
@@ -180,7 +180,9 @@ trait BigInt {
   def toUnsignedMod(m: UnsignedBigInt): UnsignedBigInt
 }
 
-
+/**
+  * Base class for unsigned 256-bits integers
+  */
 trait UnsignedBigInt {
   /** Convert this BigInt value to Byte.
     * @throws ArithmeticException if overflow happens.
@@ -338,6 +340,10 @@ trait GroupElement {
     */
   def exp(k: BigInt): GroupElement
 
+  /** Exponentiate this GroupElement to the given unsigned 256 bit integer.
+    * @param k The power.
+    * @return this to the power of k.
+    */
   def expUnsigned(k: UnsignedBigInt): GroupElement
 
   /** Group operation. */
diff --git a/core/shared/src/main/scala/sigma/ast/SType.scala b/core/shared/src/main/scala/sigma/ast/SType.scala
index 37e6c66ef3..3e915cf304 100644
--- a/core/shared/src/main/scala/sigma/ast/SType.scala
+++ b/core/shared/src/main/scala/sigma/ast/SType.scala
@@ -505,6 +505,7 @@ case object SBigInt extends SPrimType with SEmbeddable with SNumericType with SM
 
   override def numericTypeIndex: Int = 4
 
+  // no upcast to unsigned big int, use .toUnsigned / .toUnsignedMod instead
   override def upcast(v: AnyVal): BigInt = {
     v match {
       case x: Byte => CBigInt(BigInteger.valueOf(x.toLong))
@@ -515,6 +516,8 @@ case object SBigInt extends SPrimType with SEmbeddable with SNumericType with SM
       case _ => sys.error(s"Cannot upcast value $v to the type $this")
     }
   }
+
+  // no downcast to unsigned big int, use .toUnsigned / .toUnsignedMod instead
   override def downcast(v: AnyVal): BigInt = {
     v match {
       case x: Byte => CBigInt(BigInteger.valueOf(x.toLong))
@@ -542,14 +545,13 @@ case object SUnsignedBigInt extends SPrimType with SEmbeddable with SNumericType
 
   override def numericTypeIndex: Int = 5
 
-  // todo: consider upcast and downcast rules
+  // no upcast to signed big int, use .toSigned method
   override def upcast(v: AnyVal): UnsignedBigInt = {
     val bi = v match {
       case x: Byte => BigInteger.valueOf(x.toLong)
       case x: Short => BigInteger.valueOf(x.toLong)
       case x: Int => BigInteger.valueOf(x.toLong)
       case x: Long => BigInteger.valueOf(x)
- //     case x: BigInt => x.asInstanceOf[CBigInt].wrappedValue
       case x: UnsignedBigInt => x.asInstanceOf[CUnsignedBigInt].wrappedValue
       case _ => sys.error(s"Cannot upcast value $v to the type $this")
     }
@@ -559,17 +561,18 @@ case object SUnsignedBigInt extends SPrimType with SEmbeddable with SNumericType
       sys.error(s"Cannot upcast negative value $v to the type $this")
     }
   }
+
+  // no downcast to signed big int, use .toSigned method
   override def downcast(v: AnyVal): UnsignedBigInt = {
     val bi = v match {
       case x: Byte => BigInteger.valueOf(x.toLong)
       case x: Short => BigInteger.valueOf(x.toLong)
       case x: Int => BigInteger.valueOf(x.toLong)
       case x: Long => BigInteger.valueOf(x)
-  //    case x: BigInt => x.asInstanceOf[CBigInt].wrappedValue
       case x: UnsignedBigInt => x.asInstanceOf[CUnsignedBigInt].wrappedValue
       case _ => sys.error(s"Cannot downcast value $v to the type $this")
     }
-    if(bi.compareTo(BigInteger.ZERO) >= 0) {
+    if (bi.compareTo(BigInteger.ZERO) >= 0) {
       CUnsignedBigInt(bi)
     } else {
       sys.error(s"Cannot upcast negative value $v to the type $this")
diff --git a/core/shared/src/main/scala/sigma/data/CBigInt.scala b/core/shared/src/main/scala/sigma/data/CBigInt.scala
index 3ea57f0899..1fe1c2f503 100644
--- a/core/shared/src/main/scala/sigma/data/CBigInt.scala
+++ b/core/shared/src/main/scala/sigma/data/CBigInt.scala
@@ -81,6 +81,9 @@ case class CUnsignedBigInt(override val wrappedValue: BigInteger) extends Unsign
     throw new IllegalArgumentException(s"Attempt to create unsigned value from negative big integer $wrappedValue")
   }
 
+  if (wrappedValue.bitLength() > 256) {
+    throw new IllegalArgumentException(s"Too big unsigned big int value $wrappedValue")
+  }
 
   override def toByte: Byte = wrappedValue.toByteExact
 
diff --git a/core/shared/src/main/scala/sigma/reflection/StaticImpl.scala b/core/shared/src/main/scala/sigma/reflection/StaticImpl.scala
index 6db911d9bc..e95eea1f59 100644
--- a/core/shared/src/main/scala/sigma/reflection/StaticImpl.scala
+++ b/core/shared/src/main/scala/sigma/reflection/StaticImpl.scala
@@ -72,9 +72,7 @@ class SRClass[T](val clazz: Class[T],
                          parameterTypes: Class[_]*): RMethod = {
     methods.get((name, parameterTypes)) match {
       case Some(m) => m
-      case _ =>
-        println(methods)
-        throw new NoSuchMethodException(s"${clazz.getName}.$name(${parameterTypes.map(_.getName).mkString(",")})")
+      case _ => throw new NoSuchMethodException(s"${clazz.getName}.$name(${parameterTypes.map(_.getName).mkString(",")})")
     }
   }
 
diff --git a/core/shared/src/main/scala/sigma/serialization/CoreDataSerializer.scala b/core/shared/src/main/scala/sigma/serialization/CoreDataSerializer.scala
index 0d705412fc..f7c5e540f6 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 =>  // todo: versioning
+    case SUnsignedBigInt if VersionContext.current.isV6SoftForkActivated =>
       val data = BigIntegers.asUnsignedByteArray(v.asInstanceOf[CUnsignedBigInt].wrappedValue)
       w.putUShort(data.length)
       w.putBytes(data)
@@ -113,10 +113,10 @@ class CoreDataSerializer {
         }
         val valueBytes = r.getBytes(size)
         CBigInt(new BigInteger(valueBytes))
-      case SUnsignedBigInt =>  // todo: versioning
+      case SUnsignedBigInt if VersionContext.current.isV6SoftForkActivated =>
         val size: Short = r.getUShort().toShort
         if (size > SBigInt.MaxSizeInBytes) {
-          throw new SerializerException(s"BigInt value doesn't not fit into ${SBigInt.MaxSizeInBytes} bytes: $size")
+          throw SerializerException(s"BigInt value doesn't not fit into ${SBigInt.MaxSizeInBytes} bytes: $size")
         }
         val valueBytes = r.getBytes(size)
         CUnsignedBigInt(BigIntegers.fromUnsignedByteArray(valueBytes))
diff --git a/core/shared/src/main/scala/sigma/serialization/TypeSerializer.scala b/core/shared/src/main/scala/sigma/serialization/TypeSerializer.scala
index d5fb0047ee..aa5d43e229 100644
--- a/core/shared/src/main/scala/sigma/serialization/TypeSerializer.scala
+++ b/core/shared/src/main/scala/sigma/serialization/TypeSerializer.scala
@@ -242,7 +242,16 @@ class TypeSerializer {
 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. */
-    //todo: versioning
-  val embeddableIdToType = Array[SType](null, SBoolean, SByte, SShort, SInt, SLong, SBigInt, SGroupElement, SSigmaProp, SUnsignedBigInt)
+    def embeddableIdToType = {
+      if (VersionContext.current.isV6SoftForkActivated) {
+        embeddableV6
+      } else {
+        embeddableV5
+      }
+    }
+
+  private val embeddableV5 = Array[SType](null, SBoolean, SByte, SShort, SInt, SLong, SBigInt, SGroupElement, SSigmaProp)
+
+  private val embeddableV6 = Array[SType](null, SBoolean, SByte, SShort, SInt, SLong, SBigInt, SGroupElement, SSigmaProp, SUnsignedBigInt)
 
 }
\ No newline at end of file
diff --git a/data/shared/src/main/scala/sigma/ast/methods.scala b/data/shared/src/main/scala/sigma/ast/methods.scala
index f3ee0ad8a9..5c3c9a4483 100644
--- a/data/shared/src/main/scala/sigma/ast/methods.scala
+++ b/data/shared/src/main/scala/sigma/ast/methods.scala
@@ -2,12 +2,9 @@ package sigma.ast
 
 import org.ergoplatform._
 import org.ergoplatform.validation._
-import sigma.Evaluation.stypeToRType
 import sigma.{UnsignedBigInt, _}
 import sigma.ast.SCollection.{SBooleanArray, SBoxArray, SByteArray, SByteArray2, SHeaderArray}
 import sigma.ast.SMethod.{MethodCallIrBuilder, MethodCostFunc, javaMethodOf}
-import sigma.ast.SType.TypeCode
-import sigma.ast.SUnsignedBigIntMethods.ModInverseCostInfo
 import sigma.ast.SType.{TypeCode, paramT, tT}
 import sigma.ast.syntax.{SValue, ValueOps}
 import sigma.data.ExactIntegral.{ByteIsExactIntegral, IntIsExactIntegral, LongIsExactIntegral, ShortIsExactIntegral}
@@ -273,7 +270,6 @@ object SNumericTypeMethods extends MethodsContainer {
           case SLongMethods => LongIsExactIntegral.toBigEndianBytes(obj.asInstanceOf[Long])
           case SBigIntMethods => obj.asInstanceOf[BigInt].toBytes
           case SUnsignedBigIntMethods => obj.asInstanceOf[UnsignedBigInt].toBytes
-          // todo: test
         }
       })
       .withInfo(PropertyCall,
@@ -507,24 +503,16 @@ case object SBigIntMethods extends SNumericTypeMethods {
   //id = 8 to make it after toBits
   val ToUnsigned = SMethod(this, "toUnsigned", SFunc(this.ownerType, SUnsignedBigInt), 14, ToUnsignedCostKind)
     .withIRInfo(MethodCallIrBuilder)
-    .withInfo(MethodCall, "")
-
-  def toUnsigned_eval(mc: MethodCall, bi: BigInt)
-                     (implicit E: ErgoTreeEvaluator): UnsignedBigInt = {
-    E.addCost(ModInverseCostInfo.costKind, mc.method.opDesc)
-    bi.toUnsigned
-  }
+    .withInfo(MethodCall,
+        "Converts non-negative big integer to unsigned type, throws exception on negative big integer.")
 
+  private val ToUnsignedModCostKind = FixedCost(JitCost(15))
 
-  val ToUnsignedMod = SMethod(this, "toUnsignedMod", SFunc(Array(this.ownerType, SUnsignedBigInt), SUnsignedBigInt), 15, ToUnsignedCostKind)
+  val ToUnsignedMod = SMethod(this, "toUnsignedMod", SFunc(Array(this.ownerType, SUnsignedBigInt), SUnsignedBigInt), 15, ToUnsignedModCostKind)
     .withIRInfo(MethodCallIrBuilder)
-    .withInfo(MethodCall, "")
-
-  def toUnsignedMod_eval(mc: MethodCall, bi: BigInt, m: UnsignedBigInt)
-                        (implicit E: ErgoTreeEvaluator): UnsignedBigInt = {
-    E.addCost(ModInverseCostInfo.costKind, mc.method.opDesc)
-    bi.toUnsignedMod(m)
-  }
+    .withInfo(MethodCall,
+              "Converts non-negative big integer to unsigned type using cryptographic mod operation.",
+              ArgInfo("m", "modulo value"))
 
   protected override def getMethods(): Seq[SMethod]  = {
     if (VersionContext.current.isV6SoftForkActivated) {
diff --git a/interpreter/shared/src/test/scala/sigma/serialization/TypeSerializerSpecification.scala b/interpreter/shared/src/test/scala/sigma/serialization/TypeSerializerSpecification.scala
index 6419faf364..ce28a712fd 100644
--- a/interpreter/shared/src/test/scala/sigma/serialization/TypeSerializerSpecification.scala
+++ b/interpreter/shared/src/test/scala/sigma/serialization/TypeSerializerSpecification.scala
@@ -3,8 +3,9 @@ package sigma.serialization
 import org.scalacheck.Arbitrary._
 import org.scalatest.Assertion
 import sigma.ast._
+import sigmastate.CrossVersionProps
 
-class TypeSerializerSpecification extends SerializationSpecification {
+class TypeSerializerSpecification extends SerializationSpecification with CrossVersionProps {
 
   private def roundtrip[T <: SType](tpe: T, expected: Array[Byte]): Assertion = {
     val w = SigmaSerializer.startWriter()
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 08fa21f7e9..13918b08e6 100644
--- a/sc/shared/src/main/scala/sigma/compiler/ir/GraphBuilding.scala
+++ b/sc/shared/src/main/scala/sigma/compiler/ir/GraphBuilding.scala
@@ -20,9 +20,7 @@ import sigma.data.UnsignedBigIntNumericOps.{UnsignedBigIntIsExactIntegral, Unsig
 import sigma.exceptions.GraphBuildingException
 import sigma.serialization.OpCodes
 import sigma.{SigmaException, ast}
-import sigma.util.Extensions.ByteOps
-import sigma.{SigmaException, VersionContext, ast}
-import sigmastate.interpreter.Interpreter.ScriptEnv
+import sigma.VersionContext
 
 import scala.collection.mutable.ArrayBuffer
 

From ae0421a3853250902ad48ad7e73b105c083a9ae3 Mon Sep 17 00:00:00 2001
From: Alexander Chepurnoy 
Date: Thu, 14 Nov 2024 23:49:19 +0300
Subject: [PATCH 295/314] fixing JS test

---
 .../test/scala/sigmastate/utxo/BasicOpsSpecification.scala   | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala
index d02b2666a1..5ff340c391 100644
--- a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala
+++ b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala
@@ -405,7 +405,10 @@ class BasicOpsSpecification extends CompilerTestingCommons
       an[Exception] should be thrownBy conversionTest()
     } else {
       val t = Try(conversionTest())
-      t.failed.get.getCause.getMessage.startsWith("BigInteger out of 256 bit range")
+      t.failed.get match {
+        case e: java.lang.ArithmeticException => e.getMessage.startsWith("BigInteger out of 256 bit range") shouldBe true
+        case e: Throwable => e.getCause.getMessage.startsWith("BigInteger out of 256 bit range") shouldBe true
+      }
     }
   }
 

From aa3fbbdacb057e6be95f2f013d585dc1142b8626 Mon Sep 17 00:00:00 2001
From: Alexander Chepurnoy 
Date: Thu, 14 Nov 2024 23:53:57 +0300
Subject: [PATCH 296/314] JS test comment

---
 .../src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala   | 1 +
 1 file changed, 1 insertion(+)

diff --git a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala
index 5ff340c391..2271f6f6e2 100644
--- a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala
+++ b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala
@@ -405,6 +405,7 @@ class BasicOpsSpecification extends CompilerTestingCommons
       an[Exception] should be thrownBy conversionTest()
     } else {
       val t = Try(conversionTest())
+      // on JS exception is ArithmeticException directly, on JVM, ArithmeticException wrapped into InvocationTargetException
       t.failed.get match {
         case e: java.lang.ArithmeticException => e.getMessage.startsWith("BigInteger out of 256 bit range") shouldBe true
         case e: Throwable => e.getCause.getMessage.startsWith("BigInteger out of 256 bit range") shouldBe true

From cedcfbeeac7c1a261957e4b6a37a80a7ab6c0dc2 Mon Sep 17 00:00:00 2001
From: Alexander Chepurnoy 
Date: Fri, 15 Nov 2024 13:58:48 +0300
Subject: [PATCH 297/314] fixing tupleGen

---
 data/shared/src/main/scala/sigma/ast/syntax.scala          | 1 +
 .../serialization/SelectFieldSerializerSpecification.scala | 3 ++-
 .../sigma/serialization/TupleSerializerSpecification.scala | 3 ++-
 .../sigma/serialization/generators/ObjectGenerators.scala  | 7 +++++++
 .../sigma/serialization/generators/TypeGenerators.scala    | 6 +++++-
 5 files changed, 17 insertions(+), 3 deletions(-)

diff --git a/data/shared/src/main/scala/sigma/ast/syntax.scala b/data/shared/src/main/scala/sigma/ast/syntax.scala
index 5a257481cb..a20c7dd274 100644
--- a/data/shared/src/main/scala/sigma/ast/syntax.scala
+++ b/data/shared/src/main/scala/sigma/ast/syntax.scala
@@ -40,6 +40,7 @@ object syntax {
   type LongConstant = Constant[SLong.type]
   type StringConstant = Constant[SString.type]
   type BigIntConstant = Constant[SBigInt.type]
+  type UnsignedBigIntConstant = Constant[SUnsignedBigInt.type]
   type BoxConstant = Constant[SBox.type]
   type GroupElementConstant = Constant[SGroupElement.type]
   type SigmaPropConstant = Constant[SSigmaProp.type]
diff --git a/interpreter/shared/src/test/scala/sigma/serialization/SelectFieldSerializerSpecification.scala b/interpreter/shared/src/test/scala/sigma/serialization/SelectFieldSerializerSpecification.scala
index fb3bbcd326..1e1856c676 100644
--- a/interpreter/shared/src/test/scala/sigma/serialization/SelectFieldSerializerSpecification.scala
+++ b/interpreter/shared/src/test/scala/sigma/serialization/SelectFieldSerializerSpecification.scala
@@ -4,8 +4,9 @@ import org.scalacheck.Gen
 import sigma.ast.syntax.CollectionOps
 import sigma.ast.{FalseLeaf, IntConstant, SelectField, Tuple}
 import sigma.serialization.OpCodes.{SelectFieldCode, TupleCode}
+import sigmastate.CrossVersionProps
 
-class SelectFieldSerializerSpecification extends TableSerializationSpecification {
+class SelectFieldSerializerSpecification extends CrossVersionProps with TableSerializationSpecification {
 
   property("SelectField: Serializer round trip ") {
     forAll(tupleGen(2, 10)) { tuple: Tuple =>
diff --git a/interpreter/shared/src/test/scala/sigma/serialization/TupleSerializerSpecification.scala b/interpreter/shared/src/test/scala/sigma/serialization/TupleSerializerSpecification.scala
index e72890cbb7..04b4cffdc9 100644
--- a/interpreter/shared/src/test/scala/sigma/serialization/TupleSerializerSpecification.scala
+++ b/interpreter/shared/src/test/scala/sigma/serialization/TupleSerializerSpecification.scala
@@ -1,8 +1,9 @@
 package sigma.serialization
 
 import sigma.ast.{FalseLeaf, IntConstant, Tuple}
+import sigmastate.CrossVersionProps
 
-class TupleSerializerSpecification extends TableSerializationSpecification {
+class TupleSerializerSpecification extends TableSerializationSpecification with CrossVersionProps {
 
   property("Tuple: Serializer round trip ") {
     forAll(tupleGen(1, 10)) { tuple: Tuple =>
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 9a4668d8e0..1af51d4eee 100644
--- a/interpreter/shared/src/test/scala/sigma/serialization/generators/ObjectGenerators.scala
+++ b/interpreter/shared/src/test/scala/sigma/serialization/generators/ObjectGenerators.scala
@@ -143,6 +143,8 @@ trait ObjectGenerators extends TypeGenerators
     arbString.arbitrary.map { v => mkConstant[SString.type](v, SString) }
   lazy val bigIntConstGen: Gen[BigIntConstant] =
     arbBigInt.arbitrary.map { v => mkConstant[SBigInt.type](v, SBigInt) }
+  lazy val unsignedBigIntConstGen: Gen[UnsignedBigIntConstant] =
+    arbUnsignedBigInt.arbitrary.map { v => mkConstant[SUnsignedBigInt.type](v, SUnsignedBigInt) }
 
   lazy val byteArrayConstGen: Gen[CollectionConstant[SByte.type]] = for {
     bytes <- arrayOfRange(1, 100, arbByte.arbitrary)
@@ -327,6 +329,11 @@ trait ObjectGenerators extends TypeGenerators
       longConstGen,
       booleanConstGen,
       bigIntConstGen,
+      if(VersionContext.current.isV6SoftForkActivated) {
+        unsignedBigIntConstGen
+      } else {
+        bigIntConstGen
+      },
       groupElementConstGen,
       getVar[SInt.type],
       getVar[SLong.type],
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 699ef1c8f8..c27053ebf2 100644
--- a/interpreter/shared/src/test/scala/sigma/serialization/generators/TypeGenerators.scala
+++ b/interpreter/shared/src/test/scala/sigma/serialization/generators/TypeGenerators.scala
@@ -42,7 +42,11 @@ trait TypeGenerators {
       intTypeGen,
       longTypeGen,
       bigIntTypeGen,
-      unsignedBigIntTypeGen
+      if(VersionContext.current.isV6SoftForkActivated) {
+        unsignedBigIntTypeGen
+      } else {
+        bigIntTypeGen
+      }
     ))
   } yield STuple(values.toIndexedSeq)
 

From a66ab5564ac0602ce49df76862976ccbda42a2c7 Mon Sep 17 00:00:00 2001
From: Alexander Chepurnoy 
Date: Sat, 16 Nov 2024 00:06:11 +0300
Subject: [PATCH 298/314] compilation err fix

---
 .../serialization/SelectFieldSerializerSpecification.scala      | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/interpreter/shared/src/test/scala/sigma/serialization/SelectFieldSerializerSpecification.scala b/interpreter/shared/src/test/scala/sigma/serialization/SelectFieldSerializerSpecification.scala
index 1e1856c676..1c67806dbc 100644
--- a/interpreter/shared/src/test/scala/sigma/serialization/SelectFieldSerializerSpecification.scala
+++ b/interpreter/shared/src/test/scala/sigma/serialization/SelectFieldSerializerSpecification.scala
@@ -6,7 +6,7 @@ import sigma.ast.{FalseLeaf, IntConstant, SelectField, Tuple}
 import sigma.serialization.OpCodes.{SelectFieldCode, TupleCode}
 import sigmastate.CrossVersionProps
 
-class SelectFieldSerializerSpecification extends CrossVersionProps with TableSerializationSpecification {
+class SelectFieldSerializerSpecification extends TableSerializationSpecification with CrossVersionProps {
 
   property("SelectField: Serializer round trip ") {
     forAll(tupleGen(2, 10)) { tuple: Tuple =>

From 20f68c0a203e33f18b5e624d573a8444e14d8a69 Mon Sep 17 00:00:00 2001
From: Alexander Chepurnoy 
Date: Mon, 18 Nov 2024 18:37:32 +0300
Subject: [PATCH 299/314] decoding nbits from an Ergo block header

---
 .../TestingInterpreterSpecification.scala     |  2 +-
 .../utxo/BasicOpsSpecification.scala          | 37 +++++++++++++++++--
 2 files changed, 35 insertions(+), 4 deletions(-)

diff --git a/sc/shared/src/test/scala/sigmastate/TestingInterpreterSpecification.scala b/sc/shared/src/test/scala/sigmastate/TestingInterpreterSpecification.scala
index eda764ea66..f13a70206a 100644
--- a/sc/shared/src/test/scala/sigmastate/TestingInterpreterSpecification.scala
+++ b/sc/shared/src/test/scala/sigmastate/TestingInterpreterSpecification.scala
@@ -483,7 +483,7 @@ class TestingInterpreterSpecification extends CompilerTestingCommons
   property("checkPow") {
     val source = """ {
                    |     val h = CONTEXT.headers(0)
-                   |      h.checkPow
+                   |     h.checkPow
                    | }
                    | """.stripMargin
 
diff --git a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala
index 261fa9b96f..2d465cff30 100644
--- a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala
+++ b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala
@@ -12,7 +12,7 @@ import sigma.{SigmaTestingData, VersionContext}
 import sigma.VersionContext.{V6SoftForkVersion, withVersions}
 import sigma.ast.SCollection.SByteArray
 import sigma.ast.SType.AnyOps
-import sigma.data.{AvlTreeData, CAnyValue, CSigmaDslBuilder}
+import sigma.data.{AvlTreeData, CAnyValue, CHeader, CSigmaDslBuilder}
 import sigma.util.StringUtil._
 import sigma.ast._
 import sigma.ast.syntax._
@@ -28,6 +28,7 @@ import sigma.eval.EvalSettings
 import sigma.exceptions.InvalidType
 import sigma.serialization.ErgoTreeSerializer
 import sigma.interpreter.{ContextExtension, ProverResult}
+import sigma.util.NBitsUtils
 import sigmastate.utils.Helpers
 import sigmastate.utils.Helpers._
 
@@ -1083,7 +1084,6 @@ class BasicOpsSpecification extends CompilerTestingCommons
     }
   }
 
-  // todo: failing, needs for Header (de)serialization support from https://github.com/ScorexFoundation/sigmastate-interpreter/pull/972
   property("serialize - collection of collection of headers") {
     val td = new SigmaTestingData {}
     val h1 = td.TestData.h1
@@ -1109,7 +1109,6 @@ class BasicOpsSpecification extends CompilerTestingCommons
 
   // todo: roundtrip tests with deserializeTo from https://github.com/ScorexFoundation/sigmastate-interpreter/pull/979
 
-  // todo: move spam tests to dedicated test suite?
   property("serialize - not spam") {
     val customExt = Seq(21.toByte -> ShortArrayConstant((1 to Short.MaxValue).map(_.toShort).toArray),
       22.toByte -> ByteArrayConstant(Array.fill(1)(1.toByte)))
@@ -1239,6 +1238,38 @@ class BasicOpsSpecification extends CompilerTestingCommons
     }
   }
 
+  property("decoding nbits from an Ergo block header") {
+    // bytes of real mainnet block header at height 1,398,482
+    val headerBytes = "03720c6c532506a9bc4cceb6844efaa4096f66ba8a1d67ad7411ed1cb61dd5c008519fedd7d3b56984c43898f9e12aa866bc40e1ede2a6138940c9db2e20d633630024ee218d6a38392a8401c2b324b563e48d487c0f22dad940bd1c8a096084908ad71c77eec44ef083ba073deb8fa4a57b68d6296186c5d61e317849c760c16019b293cbfeb33288c9616f282288ee24c6d306577a76e7ac1cf87422ae0bdc6b44a449451a4e25070412d0d2ad55000000000295facb78290ac2b55f1453204d49df37be5bae9f185ed6704c1ba3ee372280c157221fa789df3f48"
+    val header1 = new CHeader(ErgoHeader.sigmaSerializer.fromBytes(Base16.decode(headerBytes).get))
+
+    val customExt = Seq(21.toByte -> HeaderConstant(header1))
+
+    def powTest() = {
+      test("Prop1", env, customExt,
+        """
+          |{
+          |   val h = getVar[Header](21).get
+          |
+          |   val n = h.nBits
+          |
+          |   val target = Global.decodeNbits(n)
+          |
+          |   target == bigInt("1146584469340160")
+          |}
+          |""".stripMargin,
+        propExp = null,
+        testExceededCost = false
+      )
+    }
+
+    if (activatedVersionInTests < V6SoftForkVersion) {
+      an[sigma.validation.ValidationException] should be thrownBy powTest()
+    } else {
+      powTest()
+    }
+  }
+
   property("Relation operations") {
     test("R1", env, ext,
       "{ allOf(Coll(getVar[Boolean](trueVar).get, true, true)) }",

From e37422983fe145e21e956fe210a6a4f903a1802a Mon Sep 17 00:00:00 2001
From: Alexander Chepurnoy 
Date: Mon, 18 Nov 2024 23:25:04 +0300
Subject: [PATCH 300/314] LSV6 test

---
 .../scala/sigma/data/CSigmaDslBuilder.scala   |  4 +-
 .../scala/sigma/LanguageSpecificationV6.scala | 49 ++++++++++++++++---
 2 files changed, 45 insertions(+), 8 deletions(-)

diff --git a/data/shared/src/main/scala/sigma/data/CSigmaDslBuilder.scala b/data/shared/src/main/scala/sigma/data/CSigmaDslBuilder.scala
index d0b585b0c7..9211837812 100644
--- a/data/shared/src/main/scala/sigma/data/CSigmaDslBuilder.scala
+++ b/data/shared/src/main/scala/sigma/data/CSigmaDslBuilder.scala
@@ -179,11 +179,11 @@ class CSigmaDslBuilder extends SigmaDslBuilder { dsl =>
 
   override def groupGenerator: GroupElement = _generatorElement
 
-  def encodeNbits(bi: BigInt): Long = {
+  override def encodeNbits(bi: BigInt): Long = {
     NBitsUtils.encodeCompactBits(bi.asInstanceOf[CBigInt].wrappedValue)
   }
 
-  def decodeNbits(l: Long): BigInt = {
+  override def decodeNbits(l: Long): BigInt = {
     CBigInt(NBitsUtils.decodeCompactBits(l).bigInteger)
   }
 
diff --git a/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala b/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala
index 15ce673332..c9858d02ca 100644
--- a/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala
+++ b/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala
@@ -12,19 +12,15 @@ import sigma.ast.SCollection.SByteArray
 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.{CBigInt, CBox, CHeader, CSigmaDslBuilder, ExactNumeric, PairOfCols, RType}
+import sigma.data.CSigmaDslBuilder
 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.data.{RType}
-import sigma.serialization.ValueCodes.OpCode
-import sigma.util.Extensions.{BooleanOps, ByteOps, IntOps, LongOps}
 import sigmastate.exceptions.MethodNotFound
 import sigmastate.utils.Extensions.ByteOpsForSigma
 import sigmastate.utils.Helpers
-import sigma.Extensions.{ArrayOps, CollOps}
+import sigma.Extensions.ArrayOps
 import sigma.interpreter.{ContextExtension, ProverResult}
 
 import java.math.BigInteger
@@ -1950,4 +1946,45 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite =>
     )
   }
 
+  property("Global.encodeNbits") {
+    import sigma.data.OrderingOps.BigIntOrdering
+
+    val f = newFeature[BigInt, Long](
+      { (bi: BigInt) => SigmaDsl.encodeNbits(bi) },
+      """{(bi: BigInt) => Global.encodeNbits(bi) }""".stripMargin,
+      sinceVersion = VersionContext.V6SoftForkVersion
+    )
+
+    //cases taken from Ergo blockchain and BitcoinJ / Ergo node tests
+    verifyCases(
+      Seq(
+        (CBigInt(new BigInteger("1146584469340160"))) -> Expected(ExpectedResult(Success(117707472L), None)),
+        (CBigInt(new BigInteger("130e0000000000000000000000000000000000000000000", 16))) -> Expected(ExpectedResult(Success(0x180130e0L), None)),
+        (CBigInt(new BigInteger("7fffff0000000000000000000000000000000000000000000000000000000000", 16))) -> Expected(ExpectedResult(Success(0x207fffffL), None))
+      ),
+      f
+    )
+  }
+
+  property("Global.decodeNbits") {
+    import sigma.data.OrderingOps.BigIntOrdering
+
+    val f = newFeature[Long, BigInt](
+      { (l: Long) => SigmaDsl.decodeNbits(l) },
+      """{(l: Long) => Global.decodeNbits(l) }""".stripMargin,
+      sinceVersion = VersionContext.V6SoftForkVersion
+    )
+
+    //cases taken from Ergo blockchain and BitcoinJ / Ergo node tests
+    verifyCases(
+      Seq(
+        (0x207fffffL) -> Expected(ExpectedResult(Success(CBigInt(new BigInteger("7fffff0000000000000000000000000000000000000000000000000000000000", 16))), None)),
+        (0x04923456L) -> Expected(ExpectedResult(Success(CBigInt(new BigInteger("-12345600", 16))), None)),
+        (0x04123456L) -> Expected(ExpectedResult(Success(CBigInt(new BigInteger("12345600", 16))), None)),
+        (0x01003456L) -> Expected(ExpectedResult(Success(CBigInt(new BigInteger("0", 16))), None))
+      ),
+      f
+    )
+  }
+
 }

From eb50ab4b0655b0f4ceea06a7e80e89c6f955d530 Mon Sep 17 00:00:00 2001
From: Alexander Chepurnoy 
Date: Tue, 19 Nov 2024 00:41:38 +0300
Subject: [PATCH 301/314] raising costs for encode/decode

---
 core/shared/src/main/scala/sigma/SigmaDsl.scala    | 4 ++--
 data/shared/src/main/scala/sigma/ast/methods.scala | 8 +++++---
 2 files changed, 7 insertions(+), 5 deletions(-)

diff --git a/core/shared/src/main/scala/sigma/SigmaDsl.scala b/core/shared/src/main/scala/sigma/SigmaDsl.scala
index 94a6f43988..c969969504 100644
--- a/core/shared/src/main/scala/sigma/SigmaDsl.scala
+++ b/core/shared/src/main/scala/sigma/SigmaDsl.scala
@@ -739,9 +739,9 @@ trait SigmaDslBuilder {
   def groupGenerator: GroupElement
 
   /**
-    * @return big integer provided as input approximately encoded using NBits,
+    * @return NBits-encoded approximate representation of given big integer,
     *         see (https://bitcoin.stackexchange.com/questions/57184/what-does-the-nbits-value-represent)
-    *         for format details
+    *         for NBits format details
     */
   def encodeNbits(bi: BigInt): Long
 
diff --git a/data/shared/src/main/scala/sigma/ast/methods.scala b/data/shared/src/main/scala/sigma/ast/methods.scala
index 917865a3bd..6539aa9e0d 100644
--- a/data/shared/src/main/scala/sigma/ast/methods.scala
+++ b/data/shared/src/main/scala/sigma/ast/methods.scala
@@ -1845,15 +1845,17 @@ case object SGlobalMethods extends MonoTypeMethods {
       "Decode a number from big endian bytes.",
       ArgInfo("first", "Bytes which are big-endian encoded number."))
 
-  private lazy val EnDecodeNBitsCost = FixedCost(JitCost(5)) // the same cost for nbits encoding and decoding
+  private lazy val EncodeNBitsCost = FixedCost(JitCost(25)) // the same cost for nbits encoding and decoding
+
+  private lazy val DecodeNBitsCost = FixedCost(JitCost(50)) // the same cost for nbits encoding and decoding
 
   lazy val encodeNBitsMethod: SMethod = SMethod(
-    this, "encodeNbits", SFunc(Array(SGlobal, SBigInt), SLong), 6, EnDecodeNBitsCost)
+    this, "encodeNbits", SFunc(Array(SGlobal, SBigInt), SLong), 6, EncodeNBitsCost)
     .withIRInfo(MethodCallIrBuilder)
     .withInfo(MethodCall, "Encode big integer number as nbits", ArgInfo("bigInt", "Big integer"))
 
   lazy val decodeNBitsMethod: SMethod = SMethod(
-    this, "decodeNbits", SFunc(Array(SGlobal, SLong), SBigInt), 7, EnDecodeNBitsCost)
+    this, "decodeNbits", SFunc(Array(SGlobal, SLong), SBigInt), 7, DecodeNBitsCost)
     .withIRInfo(MethodCallIrBuilder)
     .withInfo(MethodCall, "Decode nbits-encoded big integer number", ArgInfo("nbits", "NBits-encoded argument"))
 

From 367d320fe5f11766c9dd73e558db4cc3c34cdcba Mon Sep 17 00:00:00 2001
From: Alexander Chepurnoy 
Date: Tue, 19 Nov 2024 15:27:30 +0300
Subject: [PATCH 302/314] fixing cost comments

---
 data/shared/src/main/scala/sigma/ast/methods.scala | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/data/shared/src/main/scala/sigma/ast/methods.scala b/data/shared/src/main/scala/sigma/ast/methods.scala
index 6539aa9e0d..a8f674d995 100644
--- a/data/shared/src/main/scala/sigma/ast/methods.scala
+++ b/data/shared/src/main/scala/sigma/ast/methods.scala
@@ -1845,9 +1845,9 @@ case object SGlobalMethods extends MonoTypeMethods {
       "Decode a number from big endian bytes.",
       ArgInfo("first", "Bytes which are big-endian encoded number."))
 
-  private lazy val EncodeNBitsCost = FixedCost(JitCost(25)) // the same cost for nbits encoding and decoding
+  private lazy val EncodeNBitsCost = FixedCost(JitCost(25)) // cost for nbits encoding
 
-  private lazy val DecodeNBitsCost = FixedCost(JitCost(50)) // the same cost for nbits encoding and decoding
+  private lazy val DecodeNBitsCost = FixedCost(JitCost(50)) // cost for nbits decoding
 
   lazy val encodeNBitsMethod: SMethod = SMethod(
     this, "encodeNbits", SFunc(Array(SGlobal, SBigInt), SLong), 6, EncodeNBitsCost)

From f195072c03c32fad7032f064594a9616fbb122d2 Mon Sep 17 00:00:00 2001
From: Alexander Chepurnoy 
Date: Fri, 22 Nov 2024 12:48:03 +0300
Subject: [PATCH 303/314] Global.deserializeTo[] method

---
 .../src/main/scala/sigma/SigmaDsl.scala       |   4 +-
 .../sigma/reflection/ReflectionData.scala     |   3 +
 .../serialization/CoreDataSerializer.scala    |   2 +-
 .../scala/sigma/SigmaDataReflection.scala     |   5 +
 .../main/scala/sigma/ast/SigmaPredef.scala    |  20 ++
 .../src/main/scala/sigma/ast/methods.scala    |  20 ++
 .../src/main/scala/sigma/data/CHeader.scala   |   6 +-
 .../scala/sigma/data/CSigmaDslBuilder.scala   |  13 +-
 docs/LangSpec.md                              |   6 +-
 .../sigmastate/interpreter/Interpreter.scala  |   2 +-
 .../MethodCallSerializerSpecification.scala   |  27 +-
 .../special/sigma/SigmaTestingData.scala      |   7 +-
 .../main/scala/sigma/compiler/ir/Base.scala   |   2 +-
 .../sigma/compiler/ir/GraphBuilding.scala     |   7 +-
 .../sigma/compiler/ir/GraphIRReflection.scala |   4 +
 .../sigma/compiler/ir/TreeBuilding.scala      |  11 +-
 .../ir/wrappers/sigma/SigmaDslUnit.scala      |   1 +
 .../ir/wrappers/sigma/impl/SigmaDslImpl.scala |  26 +-
 .../sigma/compiler/phases/SigmaTyper.scala    |   7 +-
 .../scala/sigma/LanguageSpecificationV6.scala | 128 ++++++-
 .../sigmastate/ErgoTreeSpecification.scala    |   3 +-
 .../TestingInterpreterSpecification.scala     |   1 +
 .../utxo/BasicOpsSpecification.scala          | 337 +++++++++++++++++-
 .../ExecuteFromExamplesSpecification.scala    |   2 -
 24 files changed, 617 insertions(+), 27 deletions(-)

diff --git a/core/shared/src/main/scala/sigma/SigmaDsl.scala b/core/shared/src/main/scala/sigma/SigmaDsl.scala
index c969969504..d5e4d5e6c7 100644
--- a/core/shared/src/main/scala/sigma/SigmaDsl.scala
+++ b/core/shared/src/main/scala/sigma/SigmaDsl.scala
@@ -490,7 +490,6 @@ trait Header {
     * @return result of header's proof-of-work validation
     */
   def checkPow: Boolean
-
 }
 
 /** Runtime representation of Context ErgoTree type.
@@ -790,6 +789,9 @@ trait SigmaDslBuilder {
   /** Returns a byte-wise XOR of the two collections of bytes. */
   def xor(l: Coll[Byte], r: Coll[Byte]): Coll[Byte]
 
+  /** Deserializes provided `bytes` into a value of type `T`. **/
+  def deserializeTo[T](bytes: Coll[Byte])(implicit cT: RType[T]): T
+
   /** Returns a number decoded from provided big-endian bytes array. */
   def fromBigEndianBytes[T](bytes: Coll[Byte])(implicit cT: RType[T]): T
 }
diff --git a/core/shared/src/main/scala/sigma/reflection/ReflectionData.scala b/core/shared/src/main/scala/sigma/reflection/ReflectionData.scala
index 702f836fde..6935328d3c 100644
--- a/core/shared/src/main/scala/sigma/reflection/ReflectionData.scala
+++ b/core/shared/src/main/scala/sigma/reflection/ReflectionData.scala
@@ -469,6 +469,9 @@ object ReflectionData {
         mkMethod(clazz, "decodePoint", Array[Class[_]](cColl)) { (obj, args) =>
           obj.asInstanceOf[SigmaDslBuilder].decodePoint(args(0).asInstanceOf[Coll[Byte]])
         },
+        mkMethod(clazz, "deserializeTo", Array[Class[_]](cColl, classOf[RType[_]])) { (obj, args) =>
+          obj.asInstanceOf[SigmaDslBuilder].deserializeTo(args(0).asInstanceOf[Coll[Byte]])(args(1).asInstanceOf[RType[_]])
+        },
         mkMethod(clazz, "fromBigEndianBytes", Array[Class[_]](cColl, classOf[RType[_]])) { (obj, args) =>
           obj.asInstanceOf[SigmaDslBuilder].fromBigEndianBytes(args(0).asInstanceOf[Coll[Byte]])(args(1).asInstanceOf[RType[_]])
         },
diff --git a/core/shared/src/main/scala/sigma/serialization/CoreDataSerializer.scala b/core/shared/src/main/scala/sigma/serialization/CoreDataSerializer.scala
index 233494392a..d33b340284 100644
--- a/core/shared/src/main/scala/sigma/serialization/CoreDataSerializer.scala
+++ b/core/shared/src/main/scala/sigma/serialization/CoreDataSerializer.scala
@@ -135,7 +135,7 @@ class CoreDataSerializer {
     res
   }
 
-  def deserializeColl[T <: SType](len: Int, tpeElem: T, r: CoreByteReader): Coll[T#WrappedType] =
+  private def deserializeColl[T <: SType](len: Int, tpeElem: T, r: CoreByteReader): Coll[T#WrappedType] =
     tpeElem match {
       case SBoolean =>
         Colls.fromArray(r.getBits(len)).asInstanceOf[Coll[T#WrappedType]]
diff --git a/data/shared/src/main/scala/sigma/SigmaDataReflection.scala b/data/shared/src/main/scala/sigma/SigmaDataReflection.scala
index 0f7cb59150..0aae2210ce 100644
--- a/data/shared/src/main/scala/sigma/SigmaDataReflection.scala
+++ b/data/shared/src/main/scala/sigma/SigmaDataReflection.scala
@@ -359,6 +359,11 @@ object SigmaDataReflection {
           obj.asInstanceOf[SGlobalMethods.type].serialize_eval(args(0).asInstanceOf[MethodCall],
             args(1).asInstanceOf[SigmaDslBuilder],
             args(2).asInstanceOf[SType#WrappedType])(args(3).asInstanceOf[ErgoTreeEvaluator])
+        },
+        mkMethod(clazz, "deserializeTo_eval", Array[Class[_]](classOf[MethodCall], classOf[SigmaDslBuilder], classOf[Coll[_]], classOf[ErgoTreeEvaluator])) { (obj, args) =>
+          obj.asInstanceOf[SGlobalMethods.type].deserializeTo_eval(args(0).asInstanceOf[MethodCall],
+            args(1).asInstanceOf[SigmaDslBuilder],
+            args(2).asInstanceOf[Coll[Byte]])(args(3).asInstanceOf[ErgoTreeEvaluator])
         }
       )
     )
diff --git a/data/shared/src/main/scala/sigma/ast/SigmaPredef.scala b/data/shared/src/main/scala/sigma/ast/SigmaPredef.scala
index 4f18c170fd..5226d645ce 100644
--- a/data/shared/src/main/scala/sigma/ast/SigmaPredef.scala
+++ b/data/shared/src/main/scala/sigma/ast/SigmaPredef.scala
@@ -432,6 +432,25 @@ object SigmaPredef {
       )
     )
 
+    val DeserializeToFunc = PredefinedFunc("deserializeTo",
+      Lambda(Seq(paramT), Array("bytes" -> SByteArray), tT, None),
+      irInfo = PredefFuncInfo(
+        irBuilder = { case (u, args) =>
+          val resType = u.opType.tRange.asInstanceOf[SFunc].tRange
+          MethodCall(
+            Global,
+            SGlobalMethods.deserializeToMethod.withConcreteTypes(Map(tT -> resType)),
+            args.toIndexedSeq,
+            Map(tT -> resType)
+          )
+        }),
+      docInfo = OperationInfo(MethodCall,
+        """Deserializes provided bytes into a value of given type using the default serialization format.
+        """.stripMargin,
+        Seq(ArgInfo("bytes", "bytes to deserialize"))
+      )
+    )
+
     val FromBigEndianBytesFunc = PredefinedFunc("fromBigEndianBytes",
       Lambda(Seq(paramT), Array("bytes" -> SByteArray), tT, None),
       irInfo = PredefFuncInfo(
@@ -480,6 +499,7 @@ object SigmaPredef {
       ExecuteFromVarFunc,
       ExecuteFromSelfRegFunc,
       SerializeFunc,
+      DeserializeToFunc,
       GetVarFromInputFunc,
       FromBigEndianBytesFunc
     ).map(f => f.name -> f).toMap
diff --git a/data/shared/src/main/scala/sigma/ast/methods.scala b/data/shared/src/main/scala/sigma/ast/methods.scala
index a8f674d995..84bb4f0943 100644
--- a/data/shared/src/main/scala/sigma/ast/methods.scala
+++ b/data/shared/src/main/scala/sigma/ast/methods.scala
@@ -1754,6 +1754,7 @@ case object SHeaderMethods extends MonoTypeMethods {
   lazy val powDistanceMethod      = propertyCall("powDistance", SBigInt, 14, FixedCost(JitCost(10)))
   lazy val votesMethod            = propertyCall("votes", SByteArray, 15, FixedCost(JitCost(10)))
 
+  // methods added in 6.0 below
   // cost of checkPoW is 700 as about 2*32 hashes required, and 1 hash (id) over short data costs 10
   lazy val checkPowMethod = SMethod(
     this, "checkPow", SFunc(Array(SHeader), SBoolean), 16, FixedCost(JitCost(700)))
@@ -1824,6 +1825,15 @@ case object SGlobalMethods extends MonoTypeMethods {
     .withInfo(Xor, "Byte-wise XOR of two collections of bytes",
       ArgInfo("left", "left operand"), ArgInfo("right", "right operand"))
 
+  private val deserializeCostKind = PerItemCost(baseCost = JitCost(30), perChunkCost = JitCost(20), chunkSize = 32)
+
+  lazy val deserializeToMethod = SMethod(
+    this, "deserializeTo", SFunc(Array(SGlobal, SByteArray), tT, Array(paramT)), 4, deserializeCostKind, Seq(tT))
+    .withIRInfo(MethodCallIrBuilder,
+      javaMethodOf[SigmaDslBuilder, Coll[Byte], RType[_]]("deserializeTo"))
+    .withInfo(MethodCall, "Deserialize provided bytes into an object of requested type",
+      ArgInfo("first", "Bytes to deserialize"))
+
   /** Implements evaluation of Global.xor method call ErgoTree node.
     * Called via reflection based on naming convention.
     * @see SMethod.evalMethod, Xor.eval, Xor.xorWithCosting
@@ -1859,6 +1869,15 @@ case object SGlobalMethods extends MonoTypeMethods {
     .withIRInfo(MethodCallIrBuilder)
     .withInfo(MethodCall, "Decode nbits-encoded big integer number", ArgInfo("nbits", "NBits-encoded argument"))
 
+  def deserializeTo_eval(mc: MethodCall, G: SigmaDslBuilder, bytes: Coll[Byte])
+                        (implicit E: ErgoTreeEvaluator): Any = {
+    val tpe = mc.tpe
+    val cT = stypeToRType(tpe)
+    E.addSeqCost(deserializeCostKind, bytes.length, deserializeToMethod.opDesc) { () =>
+      G.deserializeTo(bytes)(cT)
+    }
+  }
+
   lazy val serializeMethod = SMethod(this, "serialize",
     SFunc(Array(SGlobal, tT), SByteArray, Array(paramT)), 3, DynamicCost)
       .withIRInfo(MethodCallIrBuilder)
@@ -1894,6 +1913,7 @@ case object SGlobalMethods extends MonoTypeMethods {
         groupGeneratorMethod,
         xorMethod,
         serializeMethod,
+        deserializeToMethod,
         encodeNBitsMethod,
         decodeNBitsMethod,
         fromBigEndianBytesMethod
diff --git a/data/shared/src/main/scala/sigma/data/CHeader.scala b/data/shared/src/main/scala/sigma/data/CHeader.scala
index aa5a5756d2..3acb295835 100644
--- a/data/shared/src/main/scala/sigma/data/CHeader.scala
+++ b/data/shared/src/main/scala/sigma/data/CHeader.scala
@@ -71,7 +71,11 @@ class CHeader(val ergoHeader: ErgoHeader) extends Header with WrapperOf[ErgoHead
   }
 
   override def checkPow: Boolean = {
-    Autolykos2PowValidation.checkPoWForVersion2(this)
+    if (version == 1) {
+      throw new Exception("Autolykos v1 is not supported") //todo: more specific exception?
+    } else {
+      Autolykos2PowValidation.checkPoWForVersion2(this)
+    }
   }
 
   override def toString: String =
diff --git a/data/shared/src/main/scala/sigma/data/CSigmaDslBuilder.scala b/data/shared/src/main/scala/sigma/data/CSigmaDslBuilder.scala
index 9211837812..f540df55c2 100644
--- a/data/shared/src/main/scala/sigma/data/CSigmaDslBuilder.scala
+++ b/data/shared/src/main/scala/sigma/data/CSigmaDslBuilder.scala
@@ -1,15 +1,18 @@
 package sigma.data
 
 import debox.cfor
-import org.ergoplatform.ErgoBox
+import org.ergoplatform.{ErgoBox, ErgoHeader}
 import org.ergoplatform.validation.ValidationRules
 import scorex.crypto.hash.{Blake2b256, Sha256}
+import scorex.util.serialization.VLQByteBufferReader
 import scorex.utils.{Ints, Longs}
 import sigma.ast.{AtLeast, SBigInt, SubstConstants}
 import scorex.utils.Longs
+import sigma.Evaluation.rtypeToSType
 import sigma.ast.{AtLeast, SType, SubstConstants}
 import sigma.crypto.{CryptoConstants, EcPointType, Ecp}
 import sigma.eval.Extensions.EvalCollOps
+import sigma.serialization.{ConstantStore, DataSerializer, GroupElementSerializer, SigmaByteReader, SigmaSerializer}
 import sigma.serialization.{DataSerializer, GroupElementSerializer, SigmaSerializer}
 import sigma.serialization.{GroupElementSerializer, SerializerException, SigmaSerializer}
 import sigma.util.Extensions.BigIntegerOps
@@ -18,6 +21,7 @@ import sigma.validation.SigmaValidationSettings
 import sigma.{AvlTree, BigInt, Box, Coll, CollBuilder, Evaluation, GroupElement, SigmaDslBuilder, SigmaProp, VersionContext}
 
 import java.math.BigInteger
+import java.nio.ByteBuffer
 
 /** A default implementation of [[SigmaDslBuilder]] interface.
   *
@@ -254,6 +258,13 @@ class CSigmaDslBuilder extends SigmaDslBuilder { dsl =>
     DataSerializer.serialize(value.asInstanceOf[SType#WrappedType], tpe, w)
     Colls.fromArray(w.toBytes)
   }
+
+  def deserializeTo[T](bytes: Coll[Byte])(implicit cT: RType[T]): T = {
+    val tpe = rtypeToSType(cT)
+    val reader = new SigmaByteReader(new VLQByteBufferReader(ByteBuffer.wrap(bytes.toArray)), new ConstantStore(), false)
+    val res = DataSerializer.deserialize(tpe, reader)
+    res.asInstanceOf[T]
+  }
 }
 
 /** Default singleton instance of Global object, which implements global ErgoTree functions. */
diff --git a/docs/LangSpec.md b/docs/LangSpec.md
index 16defff5ff..5cbb569a56 100644
--- a/docs/LangSpec.md
+++ b/docs/LangSpec.md
@@ -68,7 +68,7 @@ The following sections describe ErgoScript and its operations.
 #### Operations and constructs overview
 
 - Binary operations: `>, <, >=, <=, +, -, &&, ||, ==, !=, |, &, *, /, %, ^, ++`
-- predefined primitives: `serialize`, `blake2b256`, `byteArrayToBigInt`, `proveDlog` etc. 
+- predefined primitives: `deserializeTo`, `serialize`, `blake2b256`, `byteArrayToBigInt`, `proveDlog` etc. 
 - val declarations: `val h = blake2b256(pubkey)`
 - if-then-else clause: `if (x > 0) 1 else 0`
 - collection literals: `Coll(1, 2, 3, 4)`
@@ -903,6 +903,10 @@ def blake2b256(input: Coll[Byte]): Coll[Byte]
 /** Cryptographic hash function Sha256 (See scorex.crypto.hash.Sha256) */
 def sha256(input: Coll[Byte]): Coll[Byte]
 
+/** Create an instance of type T from bytes of its wrapped type. 
+See https://github.com/ScorexFoundation/sigmastate-interpreter/pull/979 for more details */
+def deserializeTo[T](input: Coll[Byte]): T
+
 /** Create BigInt from a collection of bytes. */
 def byteArrayToBigInt(input: Coll[Byte]): BigInt
 
diff --git a/interpreter/shared/src/main/scala/sigmastate/interpreter/Interpreter.scala b/interpreter/shared/src/main/scala/sigmastate/interpreter/Interpreter.scala
index 6bdf1656dc..88d7be4324 100644
--- a/interpreter/shared/src/main/scala/sigmastate/interpreter/Interpreter.scala
+++ b/interpreter/shared/src/main/scala/sigmastate/interpreter/Interpreter.scala
@@ -126,7 +126,7 @@ trait Interpreter {
     case _ => None
   }
 
-  /** Extracts proposition for ErgoTree handing soft-fork condition.
+  /** Extracts proposition for ErgoTree handling soft-fork condition.
     * @note soft-fork handler */
   protected def propositionFromErgoTree(ergoTree: ErgoTree, context: CTX): SigmaPropValue = {
     val validationSettings = context.validationSettings
diff --git a/interpreter/shared/src/test/scala/sigma/serialization/MethodCallSerializerSpecification.scala b/interpreter/shared/src/test/scala/sigma/serialization/MethodCallSerializerSpecification.scala
index 5ea171ba1f..d27b5cf22d 100644
--- a/interpreter/shared/src/test/scala/sigma/serialization/MethodCallSerializerSpecification.scala
+++ b/interpreter/shared/src/test/scala/sigma/serialization/MethodCallSerializerSpecification.scala
@@ -2,6 +2,7 @@ package sigma.serialization
 
 import sigma.VersionContext
 import sigma.ast.SCollection.SByteArray
+import sigma.ast.SType.tT
 import sigma.ast._
 import sigma.validation.ValidationException
 
@@ -51,7 +52,7 @@ class MethodCallSerializerSpecification extends SerializationSpecification {
     def code = {
       val b = ByteArrayConstant(Array(1.toByte, 2.toByte, 3.toByte))
       val expr = MethodCall(Global,
-        SGlobalMethods.serializeMethod.withConcreteTypes(Map(STypeVar("T") -> SByteArray)),
+        SGlobalMethods.serializeMethod.withConcreteTypes(Map(tT -> SByteArray)),
         Vector(b),
         Map()
       )
@@ -62,6 +63,30 @@ class MethodCallSerializerSpecification extends SerializationSpecification {
       code
     }
 
+    an[ValidationException] should be thrownBy (
+      VersionContext.withVersions((VersionContext.V6SoftForkVersion - 1).toByte, 1) {
+        code
+      }
+    )
+  }
+
+  property("MethodCall deserialization round trip for Global.deserializeTo[]") {
+    def code = {
+      val h = HeaderConstant(headerGen.sample.get)
+      val expr = MethodCall(h,
+        SGlobalMethods.deserializeToMethod.withConcreteTypes(Map(tT -> SHeader)),
+        Array(ByteArrayConstant(Array(1.toByte, 2.toByte, 3.toByte))), // wrong header bytes but ok for test
+        Map(tT -> SHeader)
+      )
+      roundTripTest(expr)
+    }
+
+    println(SGlobalMethods.deserializeToMethod.hasExplicitTypeArgs)
+
+    VersionContext.withVersions(VersionContext.V6SoftForkVersion, 1) {
+      code
+    }
+
     an[Exception] should be thrownBy (
       VersionContext.withVersions((VersionContext.V6SoftForkVersion - 1).toByte, 1) {
         code
diff --git a/interpreter/shared/src/test/scala/special/sigma/SigmaTestingData.scala b/interpreter/shared/src/test/scala/special/sigma/SigmaTestingData.scala
index b8bf76cacf..77d87a31f8 100644
--- a/interpreter/shared/src/test/scala/special/sigma/SigmaTestingData.scala
+++ b/interpreter/shared/src/test/scala/special/sigma/SigmaTestingData.scala
@@ -1,6 +1,6 @@
 package sigma
 
-import org.ergoplatform.ErgoBox
+import org.ergoplatform.{ErgoBox, ErgoHeader}
 import org.ergoplatform.settings.ErgoAlgos
 import org.scalacheck.Arbitrary.arbitrary
 import org.scalacheck.Gen.containerOfN
@@ -267,7 +267,10 @@ trait SigmaTestingData extends TestingCommons with ObjectGenerators {
 
     val h1: Header = create_h1()
 
-    val h2: Header = new CHeader(h1.asInstanceOf[CHeader].wrappedValue.copy(height = 2))
+    val eh1 = h1.asInstanceOf[CHeader].ergoHeader
+    val h2: Header = new CHeader(new ErgoHeader(eh1.version, eh1.parentId, eh1.ADProofsRoot, eh1.stateRoot,
+                                eh1.transactionsRoot, eh1.timestamp, eh1.nBits, 2, eh1.extensionRoot,
+                                eh1.powSolution, eh1.votes, eh1.unparsedBytes, null))
 
     val dlog_instances = new CloneSet(1000, ProveDlog(
       SigmaDsl.toECPoint(create_ge1()).asInstanceOf[EcPointType]
diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/Base.scala b/sc/shared/src/main/scala/sigma/compiler/ir/Base.scala
index 48e3e5d09e..d6f682abd5 100644
--- a/sc/shared/src/main/scala/sigma/compiler/ir/Base.scala
+++ b/sc/shared/src/main/scala/sigma/compiler/ir/Base.scala
@@ -169,7 +169,7 @@ abstract class Base { thisIR: IRContext =>
 
     /** Create a copy of this definition applying the given transformer to all `syms`. */
     def transform(t: Transformer): Def[T] =
-      !!!(s"Cannot transfrom definition using transform($this)", self)
+      !!!(s"Cannot transform definition using transform($this)", self)
 
     /** Clone this definition transforming all symbols using `t`.
       * If new Def[A] is created, it is added to the graph with collapsing and rewriting.
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 9b2fcc1baa..7d91b975b2 100644
--- a/sc/shared/src/main/scala/sigma/compiler/ir/GraphBuilding.scala
+++ b/sc/shared/src/main/scala/sigma/compiler/ir/GraphBuilding.scala
@@ -2,6 +2,7 @@ package sigma.compiler.ir
 
 import org.ergoplatform._
 import sigma.ast.SType.tT
+import sigma.{SigmaException, VersionContext, ast}
 import sigma.Evaluation.stypeToRType
 import sigma.ast.SType.tT
 import sigma.ast.TypeCodes.LastConstantCode
@@ -17,11 +18,11 @@ import sigma.data.{CSigmaDslBuilder, ExactIntegral, ExactNumeric, ExactOrdering,
 import sigma.exceptions.GraphBuildingException
 import sigma.serialization.OpCodes
 import sigma.util.Extensions.ByteOps
-import sigma.{SigmaException, VersionContext, ast}
 import sigmastate.interpreter.Interpreter.ScriptEnv
 
 import scala.collection.mutable.ArrayBuffer
 
+
 /** Perform translation of typed expression given by [[Value]] to a graph in IRContext.
   * Which be than be translated to [[ErgoTree]] by using [[TreeBuilding]].
   *
@@ -1184,6 +1185,10 @@ trait GraphBuilding extends Base with DefRewriting { IR: IRContext =>
             case SGlobalMethods.decodeNBitsMethod.name if VersionContext.current.isV6SoftForkActivated =>
               val c1 = asRep[Long](argsV(0))
               g.decodeNbits(c1)
+            case SGlobalMethods.deserializeToMethod.name if VersionContext.current.isV6SoftForkActivated =>
+              val c1 = asRep[Coll[Byte]](argsV(0))
+              val c2 = stypeToElem(method.stype.tRange.withSubstTypes(typeSubst))
+              g.deserializeTo(c1)(c2)
             case SGlobalMethods.serializeMethod.name =>
               val value = asRep[Any](argsV(0))
               g.serialize(value)
diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/GraphIRReflection.scala b/sc/shared/src/main/scala/sigma/compiler/ir/GraphIRReflection.scala
index ff64c3c699..6b83bc10c9 100644
--- a/sc/shared/src/main/scala/sigma/compiler/ir/GraphIRReflection.scala
+++ b/sc/shared/src/main/scala/sigma/compiler/ir/GraphIRReflection.scala
@@ -1,5 +1,6 @@
 package sigma.compiler.ir
 
+import sigma.Coll
 import sigma.{BigInt, SigmaDslBuilder}
 import sigma.ast.SType
 import sigma.compiler.ir.primitives.Thunks
@@ -540,6 +541,9 @@ object GraphIRReflection {
         },
         mkMethod(clazz, "fromBigEndianBytes", Array[Class[_]](classOf[Base#Ref[_]], classOf[TypeDescs#Elem[_]])) { (obj, args) =>
           obj.asInstanceOf[ctx.SigmaDslBuilder].fromBigEndianBytes(args(0).asInstanceOf[ctx.Ref[ctx.Coll[Byte]]])(args(1).asInstanceOf[ctx.Elem[SType]])
+        },
+        mkMethod(clazz, "deserializeTo", Array[Class[_]](classOf[Base#Ref[_]], classOf[TypeDescs#Elem[_]])) { (obj, args) =>
+          obj.asInstanceOf[ctx.SigmaDslBuilder].deserializeTo(args(0).asInstanceOf[ctx.Ref[ctx.Coll[Byte]]])(args(1).asInstanceOf[ctx.Elem[SType]])
         }
       )
     )
diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/TreeBuilding.scala b/sc/shared/src/main/scala/sigma/compiler/ir/TreeBuilding.scala
index 37ec47f2dc..652aeb4fe0 100644
--- a/sc/shared/src/main/scala/sigma/compiler/ir/TreeBuilding.scala
+++ b/sc/shared/src/main/scala/sigma/compiler/ir/TreeBuilding.scala
@@ -6,9 +6,9 @@ import sigma.Evaluation.{rtypeToSType, stypeToRType}
 import sigma.ast.SType.tT
 import sigma.ast._
 import sigma.ast.syntax.{ValueOps, _}
-import sigma.data.{ProveDHTuple, ProveDlog}
-import sigma.serialization.ConstantStore
 import sigma.serialization.OpCodes._
+import sigma.serialization.ConstantStore
+import sigma.data.{ProveDHTuple, ProveDlog}
 import sigma.serialization.ValueCodes.OpCode
 
 import scala.collection.mutable.ArrayBuffer
@@ -279,6 +279,13 @@ trait TreeBuilding extends Base { IR: IRContext =>
         val tpe = elemToSType(eVar)
         mkGetVar(id, tpe)
 
+      case SDBM.deserializeTo(g, bytes, eVar) =>
+        val tpe = elemToSType(eVar)
+        val typeSubst = Map(tT -> tpe): STypeSubst
+        // method specialization done to avoid serialization roundtrip issues
+        val method = SGlobalMethods.deserializeToMethod.withConcreteTypes(typeSubst)
+        builder.mkMethodCall(recurse(g), method, IndexedSeq(recurse(bytes)), typeSubst)
+
       case BIM.subtract(In(x), In(y)) =>
         mkArith(x.asNumValue, y.asNumValue, MinusCode)
       case BIM.add(In(x), In(y)) =>
diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/SigmaDslUnit.scala b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/SigmaDslUnit.scala
index 76ad93cac3..a8608651a2 100644
--- a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/SigmaDslUnit.scala
+++ b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/SigmaDslUnit.scala
@@ -120,6 +120,7 @@ import scalan._
       def decodeNbits(l: Ref[Long]): Ref[BigInt]
       def serialize[T](value: Ref[T]): Ref[Coll[Byte]]
       def fromBigEndianBytes[T](bytes: Ref[Coll[Byte]])(implicit cT: Elem[T]): Ref[T]
+      def deserializeTo[T](bytes: Ref[Coll[Byte]])(implicit cT: Elem[T]): Ref[T]
     };
     trait CostModelCompanion;
     trait BigIntCompanion;
diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/SigmaDslImpl.scala b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/SigmaDslImpl.scala
index 5ce0255533..336e4ed9f2 100644
--- a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/SigmaDslImpl.scala
+++ b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/SigmaDslImpl.scala
@@ -1379,6 +1379,7 @@ object Header extends EntityObject("Header") {
         ArraySeq.empty,
         true, false, element[Boolean]))
     }
+
   }
 
   implicit object LiftableHeader
@@ -1989,6 +1990,12 @@ object SigmaDslBuilder extends EntityObject("SigmaDslBuilder") {
         true, false, element[Coll[Byte]]))
     }
 
+    override def deserializeTo[T](l: Ref[Coll[Byte]])(implicit cT: Elem[T]): Ref[T] = {
+      asRep[T](mkMethodCall(self,
+        SigmaDslBuilderClass.getMethod("deserializeTo", classOf[Sym], classOf[Elem[T]]),
+        Array[AnyRef](l, cT),
+        true, false, element[T](cT), Map(tT -> Evaluation.rtypeToSType(cT.sourceType))))
+    }
     override def fromBigEndianBytes[T](bytes: Ref[Coll[Byte]])(implicit cT: Elem[T]): Ref[T] = {
       asRep[T](mkMethodCall(self,
         SigmaDslBuilderClass.getMethod("fromBigEndianBytes", classOf[Sym], classOf[Elem[T]]),
@@ -2176,6 +2183,13 @@ object SigmaDslBuilder extends EntityObject("SigmaDslBuilder") {
         true, true, element[Coll[Byte]]))
     }
 
+    def deserializeTo[T](bytes: Ref[Coll[Byte]])(implicit cT: Elem[T]): Ref[T] = {
+      asRep[T](mkMethodCall(source,
+        SigmaDslBuilderClass.getMethod("deserializeTo", classOf[Sym], classOf[Elem[_]]),
+        Array[AnyRef](bytes, cT),
+        true, true, element[T](cT), Map(tT -> Evaluation.rtypeToSType(cT.sourceType))))
+    }
+
     def fromBigEndianBytes[T](bytes: Ref[Coll[Byte]])(implicit cT: Elem[T]): Ref[T] = {
       asRep[T](mkMethodCall(source,
         SigmaDslBuilderClass.getMethod("fromBigEndianBytes", classOf[Sym], classOf[Elem[T]]),
@@ -2215,7 +2229,7 @@ object SigmaDslBuilder extends EntityObject("SigmaDslBuilder") {
         Elem.declaredMethods(RClass(classOf[SigmaDslBuilder]), RClass(classOf[SSigmaDslBuilder]), Set(
         "Colls", "verifyZK", "atLeast", "allOf", "allZK", "anyOf", "anyZK", "xorOf", "sigmaProp", "blake2b256",
           "sha256", "byteArrayToBigInt", "longToByteArray", "byteArrayToLong", "proveDlog", "proveDHTuple", "groupGenerator",
-          "substConstants", "decodePoint", "avlTree", "xor", "encodeNBits", "decodeNBits", "serialize", "fromBigEndianBytes"
+          "substConstants", "decodePoint", "avlTree", "xor", "encodeNBits", "decodeNBits", "serialize", "fromBigEndianBytes", "deserializeTo"
         ))
     }
   }
@@ -2394,6 +2408,16 @@ object SigmaDslBuilder extends EntityObject("SigmaDslBuilder") {
       def unapply(exp: Sym): Nullable[(Ref[SigmaDslBuilder], Ref[Coll[Byte]])] = unapply(exp.node)
     }
 
+    object deserializeTo {
+      def unapply(d: Def[_]): Nullable[(Ref[SigmaDslBuilder], Ref[Coll[Byte]], Elem[T]) forSome {type T}] = d match {
+        case MethodCall(receiver, method, args, _) if method.getName == "deserializeTo" && receiver.elem.isInstanceOf[SigmaDslBuilderElem[_]] =>
+          val res = (receiver, args(0), args(1))
+          Nullable(res).asInstanceOf[Nullable[(Ref[SigmaDslBuilder], Ref[Coll[Byte]], Elem[T]) forSome {type T}]]
+        case _ => Nullable.None
+      }
+      def unapply(exp: Sym): Nullable[(Ref[SigmaDslBuilder], Ref[Coll[Byte]], Elem[T]) forSome {type T}] = unapply(exp.node)
+    }
+
     /** This is necessary to handle CreateAvlTree in GraphBuilding (v6.0) */
     object avlTree {
       def unapply(d: Def[_]): Nullable[(Ref[SigmaDslBuilder], Ref[Byte], Ref[Coll[Byte]], Ref[Int], Ref[WOption[Int]])] = d match {
diff --git a/sc/shared/src/main/scala/sigma/compiler/phases/SigmaTyper.scala b/sc/shared/src/main/scala/sigma/compiler/phases/SigmaTyper.scala
index 833bd413b9..1bbf1fc4f5 100644
--- a/sc/shared/src/main/scala/sigma/compiler/phases/SigmaTyper.scala
+++ b/sc/shared/src/main/scala/sigma/compiler/phases/SigmaTyper.scala
@@ -37,13 +37,14 @@ class SigmaTyper(val builder: SigmaBuilder,
 
   private def processGlobalMethod(srcCtx: Nullable[SourceContext],
                                   method: SMethod,
-                                  args: IndexedSeq[SValue]) = {
+                                  args: IndexedSeq[SValue],
+                                  subst: Map[STypeVar, SType] = EmptySubst): SValue = {
     val global = Global.withPropagatedSrcCtx(srcCtx)
     val node = for {
       pf <- method.irInfo.irBuilder if lowerMethodCalls
-      res <- pf.lift((builder, global, method, args, EmptySubst))
+      res <- pf.lift((builder, global, method, args, subst))
     } yield res
-    node.getOrElse(mkMethodCall(global, method, args, EmptySubst).withPropagatedSrcCtx(srcCtx))
+    node.getOrElse(mkMethodCall(global, method, args, subst).withPropagatedSrcCtx(srcCtx))
   }
   /**
     * Rewrite tree to typed tree.  Checks constituent names and types.  Uses
diff --git a/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala b/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala
index c9858d02ca..c315292b77 100644
--- a/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala
+++ b/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala
@@ -9,10 +9,14 @@ import scorex.util.ModifierId
 import scorex.utils.{Ints, Longs, Shorts}
 import sigma.ast.ErgoTree.{HeaderType, ZeroHeader}
 import sigma.ast.SCollection.SByteArray
+import sigma.ast.SType.tT
 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.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}
@@ -104,8 +108,6 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite =>
     verifyCases(cases, serializeShort, preGeneratedSamples = None)
   }
 
-  // TODO v6.0: implement serialization roundtrip tests after merge with deserializeTo
-
 
   property("Boolean.toByte") {
     val toByte = newFeature((x: Boolean) => x.toByte, "{ (x: Boolean) => x.toByte }",
@@ -1526,6 +1528,128 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite =>
     )
   }
 
+  property("Global.deserializeTo - group element") {
+    def deserializeTo: Feature[GroupElement, Boolean] = {
+      newFeature(
+        { (x: GroupElement) => CSigmaDslBuilder.deserializeTo[GroupElement](x.getEncoded) == x},
+        "{ (x: GroupElement) => Global.deserializeTo[GroupElement](x.getEncoded) == x }",
+        FuncValue(
+          Array((1, SGroupElement)),
+          EQ(
+            MethodCall.typed[Value[SGroupElement.type]](
+              Global,
+              SGlobalMethods.deserializeToMethod.withConcreteTypes(Map(tT -> SGroupElement)),
+              Vector(
+                MethodCall.typed[Value[SCollection[SByte.type]]](
+                  ValUse(1, SGroupElement),
+                  SGroupElementMethods.getMethodByName("getEncoded"),
+                  IndexedSeq(),
+                  Map()
+                )
+              ),
+              Map(STypeVar("T") -> SGroupElement)
+            ),
+            ValUse(1, SGroupElement)
+          )
+        ),
+        sinceVersion = VersionContext.V6SoftForkVersion
+      )
+    }
+
+    verifyCases(
+      Seq(
+        CGroupElement(SecP256K1Group.generator) -> new Expected(ExpectedResult(Success(true), None))
+      ),
+      deserializeTo
+    )
+  }
+
+  property("Global.deserializeTo - header") {
+    val headerBytes = "02ac2101807f0000ca01ff0119db227f202201007f62000177a080005d440896d05d3f80dcff7f5e7f59007294c180808d0158d1ff6ba10000f901c7f0ef87dcfff17fffacb6ff7f7f1180d2ff7f1e24ffffe1ff937f807f0797b9ff6ebdae007e5c8c00b8403d3701557181c8df800001b6d5009e2201c6ff807d71808c00019780f087adb3fcdbc0b3441480887f80007f4b01cf7f013ff1ffff564a0000b9a54f00770e807f41ff88c00240000080c0250000000003bedaee069ff4829500b3c07c4d5fe6b3ea3d3bf76c5c28c1d4dcdb1bed0ade0c0000000000003105"
+    val header1 = new CHeader(ErgoHeader.sigmaSerializer.fromBytes(Base16.decode(headerBytes).get))
+
+    // v1 header below
+    val header2Bytes = "010000000000000000000000000000000000000000000000000000000000000000766ab7a313cd2fb66d135b0be6662aa02dfa8e5b17342c05a04396268df0bfbb93fb06aa44413ff57ac878fda9377207d5db0e78833556b331b4d9727b3153ba18b7a08878f2a7ee4389c5a1cece1e2724abe8b8adc8916240dd1bcac069177303f1f6cee9ba2d0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a8060117650100000003be7ad70c74f691345cbedba19f4844e7fc514e1188a7929f5ae261d5bb00bb6602da9385ac99014ddcffe88d2ac5f28ce817cd615f270a0a5eae58acfb9fd9f6a0000000030151dc631b7207d4420062aeb54e82b0cfb160ff6ace90ab7754f942c4c3266b"
+    val header2 = new CHeader(ErgoHeader.sigmaSerializer.fromBytes(Base16.decode(header2Bytes).get))
+
+    def deserializeTo: Feature[Header, Boolean] = {
+      newFeature(
+        { (x: Header) => CSigmaDslBuilder.deserializeTo[Header](CSigmaDslBuilder.serialize(x)) == x},
+        "{ (x: Header) => Global.deserializeTo[Header](serialize(x)) == x }",
+        FuncValue(
+          Array((1, SHeader)),
+          EQ(
+            MethodCall.typed[Value[SHeader.type]](
+              Global,
+              SGlobalMethods.deserializeToMethod.withConcreteTypes(Map(tT -> SHeader)),
+              Vector(
+                MethodCall.typed[Value[SCollection[SByte.type]]](
+                  Global,
+                  SGlobalMethods.serializeMethod.withConcreteTypes(
+                    Map(STypeVar("T") -> SHeader)
+                  ),
+                  Array(ValUse(1, SHeader)),
+                  Map()
+                )
+              ),
+              Map(STypeVar("T") -> SHeader)
+            ),
+            ValUse(1, SHeader)
+          )
+        ),
+        sinceVersion = VersionContext.V6SoftForkVersion
+      )
+    }
+
+    verifyCases(
+      Seq(
+        header1 -> new Expected(ExpectedResult(Success(true), None)),
+        header2 -> new Expected(ExpectedResult(Success(true), None))
+      ),
+      deserializeTo
+    )
+  }
+
+  property("Global.serialize & deserialize roundtrip - BigInt") {
+    import sigma.data.OrderingOps.BigIntOrdering
+
+    def deserializeTo: Feature[BigInt, Boolean] = {
+      newFeature(
+        { (x: BigInt) => CSigmaDslBuilder.deserializeTo[BigInt](CSigmaDslBuilder.serialize(x)) == x},
+        "{ (x: BigInt) => Global.deserializeTo[BigInt](serialize(x)) == x }",
+        FuncValue(
+          Array((1, SBigInt)),
+          EQ(
+            MethodCall.typed[Value[SBigInt.type]](
+              Global,
+              SGlobalMethods.deserializeToMethod.withConcreteTypes(Map(tT -> SBigInt)),
+              Vector(
+                MethodCall.typed[Value[SCollection[SByte.type]]](
+                  Global,
+                  SGlobalMethods.serializeMethod.withConcreteTypes(
+                    Map(STypeVar("T") -> SBigInt)
+                  ),
+                  Array(ValUse(1, SBigInt)),
+                  Map()
+                )
+              ),
+              Map(STypeVar("T") -> SBigInt)
+            ),
+            ValUse(1, SBigInt)
+          )
+        ),
+        sinceVersion = VersionContext.V6SoftForkVersion
+      )
+    }
+
+    val cases = Seq(
+      (CBigInt(BigInteger.ONE), new Expected(ExpectedResult(Success(true), None))),
+      (CBigInt(sigma.crypto.SecP256K1Group.q.divide(new BigInteger("2"))), new Expected(ExpectedResult(Success(true), None))),
+      (CBigInt(sigma.crypto.SecP256K1Group.p.divide(new BigInteger("2"))), new Expected(ExpectedResult(Success(true), None)))
+    )
+    verifyCases(cases, deserializeTo)
+  }
+
   private def contextData() = {
     val input = CBox(
       new ErgoBox(
diff --git a/sc/shared/src/test/scala/sigmastate/ErgoTreeSpecification.scala b/sc/shared/src/test/scala/sigmastate/ErgoTreeSpecification.scala
index fb86b3ab2b..381d21c6c1 100644
--- a/sc/shared/src/test/scala/sigmastate/ErgoTreeSpecification.scala
+++ b/sc/shared/src/test/scala/sigmastate/ErgoTreeSpecification.scala
@@ -519,8 +519,7 @@ class ErgoTreeSpecification extends SigmaDslTesting with ContractsTestkit with C
       (SGlobal.typeId, Seq(
         MInfo(1, groupGeneratorMethod), MInfo(2, xorMethod)
       ) ++ (if (isV6Activated) {
-        // id = 4 reserved for deserializeTo method
-        Seq(MInfo(3, serializeMethod), MInfo(5, fromBigEndianBytesMethod), MInfo(6, encodeNBitsMethod), MInfo(7, decodeNBitsMethod)) // methods added in v6.0
+        Seq(MInfo(3, serializeMethod), MInfo(4, deserializeToMethod), MInfo(5, fromBigEndianBytesMethod), MInfo(6, encodeNBitsMethod), MInfo(7, decodeNBitsMethod)) // methods added in v6.0
       } else {
         Seq.empty[MInfo]
       }), true)
diff --git a/sc/shared/src/test/scala/sigmastate/TestingInterpreterSpecification.scala b/sc/shared/src/test/scala/sigmastate/TestingInterpreterSpecification.scala
index f13a70206a..1af15c9ad0 100644
--- a/sc/shared/src/test/scala/sigmastate/TestingInterpreterSpecification.scala
+++ b/sc/shared/src/test/scala/sigmastate/TestingInterpreterSpecification.scala
@@ -16,6 +16,7 @@ import sigma.data.{CAND, CAvlTree, 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}
 import sigmastate.helpers.TestingHelpers._
diff --git a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala
index 2d465cff30..26c1866e57 100644
--- a/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala
+++ b/sc/shared/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala
@@ -3,20 +3,28 @@ package sigmastate.utxo
 import org.ergoplatform.ErgoBox.{AdditionalRegisters, R6, R8}
 import org.ergoplatform._
 import org.scalatest.Assertion
+import scorex.crypto.authds.{ADKey, ADValue}
+import scorex.crypto.authds.avltree.batch.{BatchAVLProver, Insert}
+import scorex.crypto.hash.{Blake2b256, Digest32}
+import scorex.util.ByteArrayBuilder
 import scorex.util.encode.Base16
 import org.scalatest.Assertion
 import scorex.util.encode.Base16
 import scorex.utils.Ints
+import scorex.util.serialization.VLQByteBufferWriter
+import scorex.utils.Longs
+import sigma.{Colls, SigmaTestingData}
 import sigma.Extensions.ArrayOps
 import sigma.{SigmaTestingData, VersionContext}
 import sigma.VersionContext.{V6SoftForkVersion, withVersions}
 import sigma.ast.SCollection.SByteArray
 import sigma.ast.SType.AnyOps
 import sigma.data.{AvlTreeData, CAnyValue, CHeader, CSigmaDslBuilder}
+import sigma.data.{AvlTreeData, AvlTreeFlags, CAND, CAnyValue, CHeader, CSigmaDslBuilder, CSigmaProp}
 import sigma.util.StringUtil._
 import sigma.ast._
 import sigma.ast.syntax._
-import sigma.crypto.CryptoConstants
+import sigma.crypto.{CryptoConstants, SecP256K1Group}
 import sigmastate._
 import sigmastate.helpers.TestingHelpers._
 import sigmastate.helpers.{CompilerTestingCommons, ContextEnrichingTestProvingInterpreter, ErgoLikeContextTesting, ErgoLikeTestInterpreter}
@@ -29,6 +37,8 @@ import sigma.exceptions.InvalidType
 import sigma.serialization.ErgoTreeSerializer
 import sigma.interpreter.{ContextExtension, ProverResult}
 import sigma.util.NBitsUtils
+import sigma.serialization.{DataSerializer, ErgoTreeSerializer, SigmaByteWriter}
+import sigma.util.Extensions
 import sigmastate.utils.Helpers
 import sigmastate.utils.Helpers._
 
@@ -54,7 +64,9 @@ class BasicOpsSpecification extends CompilerTestingCommons
   val booleanVar = 9.toByte
   val propVar1 = 10.toByte
   val propVar2 = 11.toByte
-  val lastExtVar = propVar2
+  val propVar3 = 12.toByte
+  val propBytesVar1 = 13.toByte
+  val lastExtVar = propBytesVar1
 
   val ext: Seq[VarBinding] = Seq(
     (intVar1, IntConstant(1)), (intVar2, IntConstant(2)),
@@ -71,7 +83,8 @@ class BasicOpsSpecification extends CompilerTestingCommons
     "proofVar2" -> CAnyValue(propVar2)
     )
 
-  def test(name: String, env: ScriptEnv,
+  def test(name: String,
+           env: ScriptEnv,
            ext: Seq[VarBinding],
            script: String,
            propExp: SValue,
@@ -82,7 +95,14 @@ class BasicOpsSpecification extends CompilerTestingCommons
       override lazy val contextExtenders: Map[Byte, EvaluatedValue[_ <: SType]] = {
         val p1 = dlogSecrets(0).publicImage
         val p2 = dlogSecrets(1).publicImage
-        (ext ++ Seq(propVar1 -> SigmaPropConstant(p1), propVar2 -> SigmaPropConstant(p2))).toMap
+        val d1 = dhSecrets(0).publicImage
+
+        (ext ++ Seq(
+          propVar1 -> SigmaPropConstant(p1),
+          propVar2 -> SigmaPropConstant(p2),
+          propVar3 -> SigmaPropConstant(CSigmaProp(CAND(Seq(p1, d1)))),
+          propBytesVar1 -> ByteArrayConstant(CSigmaProp(CAND(Seq(p1, d1))).propBytes)
+        )).toMap
       }
       override val evalSettings: EvalSettings = DefaultEvalSettings.copy(
         isMeasureOperationTime = true,
@@ -1270,6 +1290,315 @@ class BasicOpsSpecification extends CompilerTestingCommons
     }
   }
 
+  property("serialize - deserialize roundtrip") {
+    val customExt = Seq(21.toByte -> ShortArrayConstant((1 to 10).map(_.toShort).toArray))
+    def deserTest() = test("serialize", env, customExt,
+      s"""{
+            val src = getVar[Coll[Short]](21).get
+            val ba = serialize(src)
+            val restored = deserializeTo[Coll[Short]](ba)
+            src == restored
+          }""",
+      null,
+      true
+    )
+
+    if (activatedVersionInTests < V6SoftForkVersion) {
+      an[Exception] should be thrownBy deserTest()
+    } else {
+      deserTest()
+    }
+  }
+
+  property("deserializeTo - int") {
+    val value = -109253
+    val w = new VLQByteBufferWriter(new ByteArrayBuilder()).putInt(value)
+    val bytes = Base16.encode(w.toBytes)
+    def deserTest() = {test("deserializeTo", env, ext,
+      s"""{ val ba = fromBase16("$bytes"); Global.deserializeTo[Int](ba) == $value }""",
+      null,
+      true
+    )}
+
+    if (activatedVersionInTests < V6SoftForkVersion) {
+      an [sigma.validation.ValidationException] should be thrownBy deserTest()
+    } else {
+      deserTest()
+    }
+  }
+
+  property("deserializeTo - coll[int]") {
+    val writer = new SigmaByteWriter(new VLQByteBufferWriter(new ByteArrayBuilder()), None, None, None)
+    DataSerializer.serialize[SCollection[SInt.type]](Colls.fromArray(Array(IntConstant(5).value)), SCollection(SInt), writer)
+    val bytes = Base16.encode(writer.toBytes)
+
+    def deserTest() = {
+      test("deserializeTo", env, ext,
+        s"""{val ba = fromBase16("$bytes"); val coll = Global.deserializeTo[Coll[Int]](ba); coll(0) == 5 }""",
+        null,
+        true
+      )
+    }
+
+    if (activatedVersionInTests < V6SoftForkVersion) {
+      an [sigma.validation.ValidationException] should be thrownBy deserTest()
+    } else {
+      deserTest()
+    }
+  }
+
+  property("deserializeTo - long") {
+    val value = -10009253L
+
+    val w = new VLQByteBufferWriter(new ByteArrayBuilder()).putLong(value)
+    val bytes = Base16.encode(w.toBytes)
+
+    def deserTest() = test("deserializeTo", env, ext,
+      s"""{
+            val ba = fromBase16("$bytes");
+            Global.deserializeTo[Long](ba) == ${value}L
+          }""",
+      null,
+      true
+    )
+
+    if (activatedVersionInTests < V6SoftForkVersion) {
+      an [sigma.validation.ValidationException] should be thrownBy deserTest()
+    } else {
+      deserTest()
+    }
+  }
+
+  property("deserializeTo - box rountrip") {
+    def deserTest() = test("deserializeTo", env, ext,
+      s"""{
+            val b = INPUTS(0);
+            val ba = b.bytes;
+            Global.deserializeTo[Box](ba) == b
+          }""",
+      null,
+      true
+    )
+
+    if (activatedVersionInTests < V6SoftForkVersion) {
+      an [sigma.validation.ValidationException] should be thrownBy deserTest()
+    } else {
+      deserTest()
+    }
+  }
+
+  property("deserializeTo - bigint") {
+
+    val bigInt = SecP256K1Group.q.divide(new BigInteger("512"))
+    val biBytes = bigInt.toByteArray
+
+    val w = new VLQByteBufferWriter(new ByteArrayBuilder()).putUShort(biBytes.length)
+    val lengthBytes = w.toBytes
+
+    val bytes = Base16.encode(lengthBytes ++ biBytes)
+
+    def deserTest() = test("deserializeTo", env, ext,
+      s"""{
+            val ba = fromBase16("$bytes");
+            val b = Global.deserializeTo[BigInt](ba)
+            b == bigInt("${bigInt.toString}")
+          }""",
+      null,
+      true
+    )
+
+    if (activatedVersionInTests < V6SoftForkVersion) {
+      an [sigma.validation.ValidationException] should be thrownBy deserTest()
+    } else {
+      deserTest()
+    }
+  }
+
+  property("deserializeTo - short") {
+    val s = (-1925).toShort
+    val w = new VLQByteBufferWriter(new ByteArrayBuilder()).putShort(s)
+    val bytes = Base16.encode(w.toBytes)
+    def deserTest() = test("deserializeTo", env, ext,
+      s"""{
+            val ba = fromBase16("$bytes");
+            Global.deserializeTo[Short](ba) == -1925
+          }""",
+      null,
+      true
+    )
+
+    if (activatedVersionInTests < V6SoftForkVersion) {
+      an [sigma.validation.ValidationException] should be thrownBy deserTest()
+    } else {
+      deserTest()
+    }
+  }
+
+  property("deserializeTo - group element") {
+    val ge = Helpers.decodeGroupElement("026930cb9972e01534918a6f6d6b8e35bc398f57140d13eb3623ea31fbd069939b")
+    val ba = Base16.encode(ge.getEncoded.toArray)
+    def deserTest() = test("deserializeTo", env, Seq(21.toByte -> GroupElementConstant(ge)),
+      s"""{
+            val ge = getVar[GroupElement](21).get
+            val ba = fromBase16("$ba");
+            val ge2 = Global.deserializeTo[GroupElement](ba)
+            ba == ge2.getEncoded && ge == ge2
+          }""",
+      null,
+      true
+    )
+
+    if (activatedVersionInTests < V6SoftForkVersion) {
+       an [sigma.validation.ValidationException] should be thrownBy deserTest()
+    } else {
+      deserTest()
+    }
+  }
+
+  property("deserializeTo - sigmaprop roundtrip") {
+
+    def deserTest() = test("deserializeTo", env, ext,
+      s"""{
+            val bytes = getVar[Coll[Byte]]($propBytesVar1).get
+            val ba = bytes.slice(2, bytes.size)
+            val prop = Global.deserializeTo[SigmaProp](ba)
+            prop == getVar[SigmaProp]($propVar3).get && prop
+          }""",
+      null,
+      true
+    )
+
+    if (activatedVersionInTests < V6SoftForkVersion) {
+      an [sigma.validation.ValidationException] should be thrownBy deserTest()
+    } else {
+      deserTest()
+    }
+  }
+
+  property("deserializeTo - .propBytes") {
+    def deserTest() = test("deserializeTo", env, ext,
+      s"""{
+            val p1 = getVar[SigmaProp]($propVar1).get
+            val bytes = p1.propBytes
+            val ba = bytes.slice(2, bytes.size)
+            val prop = Global.deserializeTo[SigmaProp](ba)
+            prop == p1 && prop
+          }""",
+      null,
+      true
+    )
+
+    if (activatedVersionInTests < V6SoftForkVersion) {
+      an [sigma.validation.ValidationException] should be thrownBy deserTest()
+    } else {
+      deserTest()
+    }
+  }
+
+  property("deserializeTo - sigmaprop roundtrip - non evaluated") {
+
+    val script = GT(Height, IntConstant(-1)).toSigmaProp
+    val scriptBytes = ErgoTreeSerializer.DefaultSerializer.serializeErgoTree(ErgoTree.fromProposition(script))
+    val customExt = Seq(21.toByte -> ByteArrayConstant(scriptBytes))
+
+    def deserTest() = test("deserializeTo", env, customExt,
+      s"""{
+            val ba = getVar[Coll[Byte]](21).get
+            val prop = Global.deserializeTo[SigmaProp](ba)
+            prop
+          }""",
+      null,
+      true
+    )
+
+    if (activatedVersionInTests < V6SoftForkVersion) {
+      an [sigma.validation.ValidationException] should be thrownBy deserTest()
+    } else {
+      an [Exception] should be thrownBy deserTest()
+    }
+  }
+
+  property("deserializeTo - avltree") {
+    val elements = Seq(123, 22)
+    val treeElements = elements.map(i => Longs.toByteArray(i)).map(s => (ADKey @@@ Blake2b256(s), ADValue @@ s))
+    val avlProver = new BatchAVLProver[Digest32, Blake2b256.type](keyLength = 32, None)
+    treeElements.foreach(s => avlProver.performOneOperation(Insert(s._1, s._2)))
+    avlProver.generateProof()
+    val treeData = new AvlTreeData(avlProver.digest.toColl, AvlTreeFlags.ReadOnly, 32, None)
+    val treeBytes = AvlTreeData.serializer.toBytes(treeData)
+
+    val customExt = Seq(21.toByte -> ByteArrayConstant(treeBytes))
+
+    def deserTest() = test("deserializeTo", env, customExt,
+      s"""{
+            val ba = getVar[Coll[Byte]](21).get
+            val tree = Global.deserializeTo[AvlTree](ba)
+            tree.digest == fromBase16(${Base16.encode(treeData.digest.toArray)})
+              && tree.enabledOperations == 0
+              && tree.keyLength == 32
+              && tree.valueLengthOpt.isEmpty
+          }""",
+      null,
+      true
+    )
+
+    an [Exception] should be thrownBy deserTest()
+  }
+
+  property("deserializeTo - header") {
+    val td = new SigmaTestingData {}
+    val h1 = td.TestData.h1
+    val headerBytes = h1.asInstanceOf[CHeader].ergoHeader.bytes
+
+    val headerStateBytes = AvlTreeData.serializer.toBytes(Extensions.CoreAvlTreeOps(h1.stateRoot).toAvlTreeData)
+    val customExt = Seq(21.toByte -> ByteArrayConstant(headerBytes), 22.toByte -> ByteArrayConstant(headerStateBytes))
+
+    def deserTest() = test("deserializeTo", env, customExt,
+      s"""{
+            val ba = getVar[Coll[Byte]](21).get
+            val header = Global.deserializeTo[Header](ba)
+            val ba2 = getVar[Coll[Byte]](22).get
+            val tree = Global.deserializeTo[AvlTree](ba2)
+            val id = fromBase16("${Base16.encode(h1.id.toArray)}")
+            header.height == ${h1.height} && header.stateRoot == tree && header.id == id
+          }""",
+      null,
+      true
+    )
+
+    if (activatedVersionInTests < V6SoftForkVersion) {
+      an[sigma.validation.ValidationException] should be thrownBy deserTest()
+    } else {
+      deserTest()
+    }
+  }
+
+  property("deserializeTo - header option") {
+    val td = new SigmaTestingData {}
+    val h1 = td.TestData.h1.asInstanceOf[CHeader].ergoHeader
+    val headerBytes = Colls.fromArray(Array(1.toByte) ++ h1.bytes)
+
+    val customExt = Seq(21.toByte -> ByteArrayConstant(headerBytes))
+
+    def deserTest() = test("deserializeTo", env, customExt,
+      s"""{
+            val ba = getVar[Coll[Byte]](21).get
+            val headerOpt = Global.deserializeTo[Option[Header]](ba)
+            val header = headerOpt.get
+            val id = fromBase16("${Base16.encode(h1.id.toArray)}")
+            header.height == ${h1.height} && header.id == id
+          }""",
+      null,
+      true
+    )
+
+    if (activatedVersionInTests < V6SoftForkVersion) {
+      an[sigma.validation.ValidationException] should be thrownBy deserTest()
+    } else {
+      deserTest()
+    }
+  }
+
   property("Relation operations") {
     test("R1", env, ext,
       "{ allOf(Coll(getVar[Boolean](trueVar).get, true, true)) }",
diff --git a/sc/shared/src/test/scala/sigmastate/utxo/examples/ExecuteFromExamplesSpecification.scala b/sc/shared/src/test/scala/sigmastate/utxo/examples/ExecuteFromExamplesSpecification.scala
index b75b404aed..8090d87803 100644
--- a/sc/shared/src/test/scala/sigmastate/utxo/examples/ExecuteFromExamplesSpecification.scala
+++ b/sc/shared/src/test/scala/sigmastate/utxo/examples/ExecuteFromExamplesSpecification.scala
@@ -9,8 +9,6 @@ import sigma.ast.ByteArrayConstant
 class ExecuteFromExamplesSpecification extends CompilerTestingCommons { suite =>
   implicit lazy val IR = new TestingIRContext
 
-  private val reg1 = ErgoBox.nonMandatoryRegisters(0)
-
   case class OracleContract[Spec <: ContractSpec]
       (alice: Spec#ProvingParty)
       (implicit val spec: Spec) extends SigmaContractSyntax with StdContracts

From c0ea4b0cdd034be84a2d1c4b1950944adefbf9f3 Mon Sep 17 00:00:00 2001
From: Alexander Chepurnoy 
Date: Fri, 22 Nov 2024 13:33:30 +0300
Subject: [PATCH 304/314] Autolykos 2 validation for custom message

---
 .../src/main/scala/sigma/SigmaDsl.scala       |  3 +
 .../sigma/reflection/ReflectionData.scala     |  4 ++
 .../scala/sigma/SigmaDataReflection.scala     | 10 +++
 .../src/main/scala/sigma/ast/CostKind.scala   | 34 +++++++++
 .../src/main/scala/sigma/ast/SMethod.scala    |  5 +-
 .../src/main/scala/sigma/ast/methods.scala    | 23 ++++++
 .../src/main/scala/sigma/ast/trees.scala      | 12 ----
 .../scala/sigma/data/CSigmaDslBuilder.scala   |  9 ++-
 .../sigma/pow/Autolykos2PowValidation.scala   |  8 ++-
 .../MethodCallSerializerSpecification.scala   | 30 +++++++-
 .../scala/sigmastate/eval/BasicOpsTests.scala | 70 ++++++++++++++++++-
 .../sigma/compiler/ir/GraphBuilding.scala     | 14 ++++
 .../sigma/compiler/ir/GraphIRReflection.scala |  6 ++
 .../ir/wrappers/sigma/SigmaDslUnit.scala      |  1 +
 .../ir/wrappers/sigma/impl/SigmaDslImpl.scala | 17 ++++-
 .../scala/sigma/LanguageSpecificationV6.scala | 47 +++++++++++++
 .../sigmastate/ErgoTreeSpecification.scala    |  2 +-
 .../TestingInterpreterSpecification.scala     | 22 ++++++
 18 files changed, 295 insertions(+), 22 deletions(-)

diff --git a/core/shared/src/main/scala/sigma/SigmaDsl.scala b/core/shared/src/main/scala/sigma/SigmaDsl.scala
index d5e4d5e6c7..821080ec00 100644
--- a/core/shared/src/main/scala/sigma/SigmaDsl.scala
+++ b/core/shared/src/main/scala/sigma/SigmaDsl.scala
@@ -789,6 +789,9 @@ trait SigmaDslBuilder {
   /** Returns a byte-wise XOR of the two collections of bytes. */
   def xor(l: Coll[Byte], r: Coll[Byte]): Coll[Byte]
 
+  /** Calculates value of a custom Autolykos 2 hash function */
+  def powHit(k: Int, msg: Coll[Byte], nonce: Coll[Byte], h: Coll[Byte], N: Int): BigInt
+
   /** Deserializes provided `bytes` into a value of type `T`. **/
   def deserializeTo[T](bytes: Coll[Byte])(implicit cT: RType[T]): T
 
diff --git a/core/shared/src/main/scala/sigma/reflection/ReflectionData.scala b/core/shared/src/main/scala/sigma/reflection/ReflectionData.scala
index 6935328d3c..daf8e48e81 100644
--- a/core/shared/src/main/scala/sigma/reflection/ReflectionData.scala
+++ b/core/shared/src/main/scala/sigma/reflection/ReflectionData.scala
@@ -475,6 +475,10 @@ object ReflectionData {
         mkMethod(clazz, "fromBigEndianBytes", Array[Class[_]](cColl, classOf[RType[_]])) { (obj, args) =>
           obj.asInstanceOf[SigmaDslBuilder].fromBigEndianBytes(args(0).asInstanceOf[Coll[Byte]])(args(1).asInstanceOf[RType[_]])
         },
+        mkMethod(clazz, "powHit", Array[Class[_]](classOf[Int], cColl, cColl, cColl, classOf[Int])) { (obj, args) =>
+          obj.asInstanceOf[SigmaDslBuilder].powHit(args(0).asInstanceOf[Int], args(1).asInstanceOf[Coll[Byte]],
+            args(2).asInstanceOf[Coll[Byte]], args(3).asInstanceOf[Coll[Byte]], args(4).asInstanceOf[Int])
+        },
         mkMethod(clazz, "encodeNbits", Array[Class[_]](classOf[BigInt])) { (obj, args) =>
           obj.asInstanceOf[SigmaDslBuilder].encodeNbits(args(0).asInstanceOf[BigInt])
         },
diff --git a/data/shared/src/main/scala/sigma/SigmaDataReflection.scala b/data/shared/src/main/scala/sigma/SigmaDataReflection.scala
index 0aae2210ce..c79473afe1 100644
--- a/data/shared/src/main/scala/sigma/SigmaDataReflection.scala
+++ b/data/shared/src/main/scala/sigma/SigmaDataReflection.scala
@@ -364,6 +364,16 @@ object SigmaDataReflection {
           obj.asInstanceOf[SGlobalMethods.type].deserializeTo_eval(args(0).asInstanceOf[MethodCall],
             args(1).asInstanceOf[SigmaDslBuilder],
             args(2).asInstanceOf[Coll[Byte]])(args(3).asInstanceOf[ErgoTreeEvaluator])
+        },
+        mkMethod(clazz, "powHit_eval", Array[Class[_]](classOf[MethodCall], classOf[SigmaDslBuilder], classOf[Int], classOf[Coll[_]], classOf[Coll[_]], classOf[Coll[_]], classOf[Int], classOf[ErgoTreeEvaluator])) { (obj, args) =>
+          obj.asInstanceOf[SGlobalMethods.type].powHit_eval(args(0).asInstanceOf[MethodCall],
+            args(1).asInstanceOf[SigmaDslBuilder],
+            args(2).asInstanceOf[Int],
+            args(3).asInstanceOf[Coll[Byte]],
+            args(4).asInstanceOf[Coll[Byte]],
+            args(5).asInstanceOf[Coll[Byte]],
+            args(6).asInstanceOf[Int]
+          )(args(7).asInstanceOf[ErgoTreeEvaluator])
         }
       )
     )
diff --git a/data/shared/src/main/scala/sigma/ast/CostKind.scala b/data/shared/src/main/scala/sigma/ast/CostKind.scala
index 1fda6018ec..6116da2eed 100644
--- a/data/shared/src/main/scala/sigma/ast/CostKind.scala
+++ b/data/shared/src/main/scala/sigma/ast/CostKind.scala
@@ -1,5 +1,7 @@
 package sigma.ast
 
+import sigma.Coll
+
 import scala.runtime.Statics
 
 /** Cost descriptor of a single operation, usually associated with
@@ -52,5 +54,37 @@ abstract class TypeBasedCost extends CostKind {
   * See [[EQ]], [[NEQ]]. */
 case object DynamicCost extends CostKind
 
+/**
+  * Cost of  converting numeric value to the numeric value of the given type, i.e. Byte -> Int
+  */
+object NumericCastCostKind extends TypeBasedCost {
+  override def costFunc(targetTpe: SType): JitCost = targetTpe match {
+    case SBigInt => JitCost(30)
+    case _ => JitCost(10)
+  }
+}
+
+/**
+  * Cost of Global.powHit method, which is dependent on few parameters, see cost() function description
+  */
+object PowHitCostKind extends CostKind {
+  /**
+    * @param k - k parameter of Autolykos 2 (number of inputs in k-sum problem)"
+    * @param msg - message to calculate Autolykos hash 2 for
+    * @param nonce - used to pad the message to get Proof-of-Work hash function output with desirable properties
+    * @param h - PoW protocol specific padding for table uniqueness (e.g. block height in Ergo)
+    * @return cost of custom Autolykos2 hash function invocation
+    */
+  def cost(k: Int, msg: Coll[Byte], nonce: Coll[Byte], h: Coll[Byte]): JitCost = {
+    val chunkSize = CalcBlake2b256.costKind.chunkSize
+    val perChunkCost = CalcBlake2b256.costKind.perChunkCost
+    val baseCost = 300
+
+    // the heaviest part inside is k + 1 Blake2b256 invocations
+    val c = baseCost + (k + 1) * ((msg.length + nonce.length + h.length) / chunkSize + 1) * perChunkCost.value
+    JitCost(c)
+  }
+}
+
 
 
diff --git a/data/shared/src/main/scala/sigma/ast/SMethod.scala b/data/shared/src/main/scala/sigma/ast/SMethod.scala
index e5481cee5b..35b452fef0 100644
--- a/data/shared/src/main/scala/sigma/ast/SMethod.scala
+++ b/data/shared/src/main/scala/sigma/ast/SMethod.scala
@@ -155,8 +155,7 @@ case class SMethod(
     val methodName = name + "_eval"
     val m = try {
       objType.thisRClass.getMethod(methodName, paramTypes:_*)
-    }
-    catch { case e: NoSuchMethodException =>
+    } catch { case e: NoSuchMethodException =>
       throw new RuntimeException(s"Cannot find eval method def $methodName(${Seq(paramTypes:_*)})", e)
     }
     m
@@ -339,7 +338,7 @@ object SMethod {
     * @return an instance of [[SMethod]] which may contain generic type variables in the
     *         signature (see SMethod.stype). As a result `specializeFor` is called by
     *         deserializer to obtain monomorphic method descriptor.
-    * @consensus this is method is used in [[sigmastate.serialization.MethodCallSerializer]]
+    * @consensus this is method is used in [[sigma.serialization.MethodCallSerializer]]
     *            `parse` method and hence it is part of consensus protocol
     */
   def fromIds(typeId: Byte, methodId: Byte): SMethod = {
diff --git a/data/shared/src/main/scala/sigma/ast/methods.scala b/data/shared/src/main/scala/sigma/ast/methods.scala
index 84bb4f0943..1e3a6a80eb 100644
--- a/data/shared/src/main/scala/sigma/ast/methods.scala
+++ b/data/shared/src/main/scala/sigma/ast/methods.scala
@@ -2,6 +2,7 @@ package sigma.ast
 
 import org.ergoplatform._
 import org.ergoplatform.validation._
+import sigma.{Coll, VersionContext, _}
 import sigma.Evaluation.stypeToRType
 import sigma._
 import sigma.{VersionContext, _}
@@ -15,6 +16,7 @@ import sigma.data.NumericOps.BigIntIsExactIntegral
 import sigma.data.OverloadHack.Overloaded1
 import sigma.data.{CBigInt, DataValueComparer, KeyValueColl, Nullable, RType, SigmaConstants}
 import sigma.eval.{CostDetails, ErgoTreeEvaluator, TracedCost}
+import sigma.pow.Autolykos2PowValidation
 import sigma.reflection.RClass
 import sigma.serialization.CoreByteWriter.ArgInfo
 import sigma.serialization.{DataSerializer, SigmaByteWriter, SigmaSerializer}
@@ -1825,6 +1827,26 @@ case object SGlobalMethods extends MonoTypeMethods {
     .withInfo(Xor, "Byte-wise XOR of two collections of bytes",
       ArgInfo("left", "left operand"), ArgInfo("right", "right operand"))
 
+  lazy val powHitMethod = SMethod(
+    this, "powHit", SFunc(Array(SGlobal, SInt, SByteArray, SByteArray, SByteArray, SInt), SBigInt), methodId = 8,
+    PowHitCostKind)
+    .withIRInfo(MethodCallIrBuilder)
+    .withInfo(MethodCall,
+      "Calculating Proof-of-Work hit (Autolykos 2 hash value) for custom Autolykos 2 function",
+      ArgInfo("k", "k parameter of Autolykos 2 (number of inputs in k-sum problem)"),
+      ArgInfo("msg", "Message to calculate Autolykos hash 2 for"),
+      ArgInfo("nonce", "Nonce used to pad the message to get Proof-of-Work hash function output with desirable properties"),
+      ArgInfo("h", "PoW protocol specific padding for table uniqueness (e.g. block height in Ergo)"),
+      ArgInfo("N", "Size of table filled with pseudo-random data to find k elements in")
+    )
+
+  def powHit_eval(mc: MethodCall, G: SigmaDslBuilder, k: Int, msg: Coll[Byte], nonce: Coll[Byte], h: Coll[Byte], N: Int)
+                 (implicit E: ErgoTreeEvaluator): BigInt = {
+    val cost = PowHitCostKind.cost(k, msg, nonce, h)
+    E.addCost(FixedCost(cost), powHitMethod.opDesc)
+    CBigInt(Autolykos2PowValidation.hitForVersion2ForMessageWithChecks(k, msg.toArray, nonce.toArray, h.toArray, N).bigInteger)
+  }
+
   private val deserializeCostKind = PerItemCost(baseCost = JitCost(30), perChunkCost = JitCost(20), chunkSize = 32)
 
   lazy val deserializeToMethod = SMethod(
@@ -1913,6 +1935,7 @@ case object SGlobalMethods extends MonoTypeMethods {
         groupGeneratorMethod,
         xorMethod,
         serializeMethod,
+        powHitMethod,
         deserializeToMethod,
         encodeNBitsMethod,
         decodeNBitsMethod,
diff --git a/data/shared/src/main/scala/sigma/ast/trees.scala b/data/shared/src/main/scala/sigma/ast/trees.scala
index 39e666a389..fb9f84288e 100644
--- a/data/shared/src/main/scala/sigma/ast/trees.scala
+++ b/data/shared/src/main/scala/sigma/ast/trees.scala
@@ -414,18 +414,6 @@ trait NumericCastCompanion extends ValueCompanion {
   def costKind: TypeBasedCost = NumericCastCostKind
 }
 
-/** Cost of:
-  * 1) converting numeric value to the numeric value of the given type, i.e. Byte -> Int
-  * NOTE: the cost of BigInt casting is the same in JITC (comparing to AOTC) to simplify
-  * implementation.
-  */
-object NumericCastCostKind extends TypeBasedCost {
-  override def costFunc(targetTpe: SType): JitCost = targetTpe match {
-    case SBigInt => JitCost(30)
-    case _ => JitCost(10)
-  }
-}
-
 object Upcast extends NumericCastCompanion {
   override def opCode: OpCode = OpCodes.UpcastCode
   override def argInfos: Seq[ArgInfo] = UpcastInfo.argInfos
diff --git a/data/shared/src/main/scala/sigma/data/CSigmaDslBuilder.scala b/data/shared/src/main/scala/sigma/data/CSigmaDslBuilder.scala
index f540df55c2..0346c919b2 100644
--- a/data/shared/src/main/scala/sigma/data/CSigmaDslBuilder.scala
+++ b/data/shared/src/main/scala/sigma/data/CSigmaDslBuilder.scala
@@ -14,7 +14,8 @@ import sigma.crypto.{CryptoConstants, EcPointType, Ecp}
 import sigma.eval.Extensions.EvalCollOps
 import sigma.serialization.{ConstantStore, DataSerializer, GroupElementSerializer, SigmaByteReader, SigmaSerializer}
 import sigma.serialization.{DataSerializer, GroupElementSerializer, SigmaSerializer}
-import sigma.serialization.{GroupElementSerializer, SerializerException, SigmaSerializer}
+import sigma.serialization.SerializerException
+import sigma.pow.Autolykos2PowValidation
 import sigma.util.Extensions.BigIntegerOps
 import sigma.util.NBitsUtils
 import sigma.validation.SigmaValidationSettings
@@ -259,6 +260,12 @@ class CSigmaDslBuilder extends SigmaDslBuilder { dsl =>
     Colls.fromArray(w.toBytes)
   }
 
+  override def powHit(k: Int, msg: Coll[Byte], nonce: Coll[Byte], h: Coll[Byte], N: Int): BigInt = {
+    val bi = Autolykos2PowValidation.hitForVersion2ForMessageWithChecks(k, msg.toArray, nonce.toArray, h.toArray, N)
+    this.BigInt(bi.bigInteger)
+  }
+
+
   def deserializeTo[T](bytes: Coll[Byte])(implicit cT: RType[T]): T = {
     val tpe = rtypeToSType(cT)
     val reader = new SigmaByteReader(new VLQByteBufferReader(ByteBuffer.wrap(bytes.toArray)), new ConstantStore(), false)
diff --git a/data/shared/src/main/scala/sigma/pow/Autolykos2PowValidation.scala b/data/shared/src/main/scala/sigma/pow/Autolykos2PowValidation.scala
index 23cf722194..f51a625825 100644
--- a/data/shared/src/main/scala/sigma/pow/Autolykos2PowValidation.scala
+++ b/data/shared/src/main/scala/sigma/pow/Autolykos2PowValidation.scala
@@ -112,8 +112,14 @@ object Autolykos2PowValidation {
     toBigInt(hash(Bytes.concat(indexBytes, heightBytes, M)).drop(1))
   }
 
-  def hitForVersion2ForMessage(k: Int, msg: Array[Byte], nonce: Array[Byte], h: Array[Byte], N: Int): BigInt = {
+  def hitForVersion2ForMessageWithChecks(k: Int, msg: Array[Byte], nonce: Array[Byte], h: Array[Byte], N: Int): BigInt = {
+    require(k >= 2) // at least 2 elements needed for sum
+    require(k <= 32) // genIndexes function of Autolykos2 not supporting k > 32
+    require(N >= 16) // min table size
+    hitForVersion2ForMessage(k, msg, nonce, h, N)
+  }
 
+  private def hitForVersion2ForMessage(k: Int, msg: Array[Byte], nonce: Array[Byte], h: Array[Byte], N: Int): BigInt = {
     val prei8 = BigIntegers.fromUnsignedByteArray(hash(Bytes.concat(msg, nonce)).takeRight(8))
     val i = BigIntegers.asUnsignedByteArray(4, prei8.mod(BigInt(N).underlying()))
     val f = Blake2b256(Bytes.concat(i, h, M)).drop(1) // .drop(1) is the same as takeRight(31)
diff --git a/interpreter/shared/src/test/scala/sigma/serialization/MethodCallSerializerSpecification.scala b/interpreter/shared/src/test/scala/sigma/serialization/MethodCallSerializerSpecification.scala
index d27b5cf22d..4bfe3c6a25 100644
--- a/interpreter/shared/src/test/scala/sigma/serialization/MethodCallSerializerSpecification.scala
+++ b/interpreter/shared/src/test/scala/sigma/serialization/MethodCallSerializerSpecification.scala
@@ -1,5 +1,6 @@
 package sigma.serialization
 
+import scorex.utils.Ints
 import sigma.VersionContext
 import sigma.ast.SCollection.SByteArray
 import sigma.ast.SType.tT
@@ -41,7 +42,34 @@ class MethodCallSerializerSpecification extends SerializationSpecification {
       code
     }
 
-    an[SerializerException] should be thrownBy (
+    a[SerializerException] should be thrownBy (
+      VersionContext.withVersions((VersionContext.V6SoftForkVersion - 1).toByte, 1) {
+        code
+      }
+      )
+  }
+
+  property("MethodCall deserialization round trip for Global.powHit") {
+    val k = IntConstant(32)
+    val msg = ByteArrayConstant(Array.fill(5)(1.toByte))
+    val nonce = ByteArrayConstant(Array.fill(8)(2.toByte))
+    val h = ByteArrayConstant(Ints.toByteArray(5))
+    val N = IntConstant(1024 * 1024)
+
+    def code = {
+      val expr = MethodCall(Global,
+        SGlobalMethods.powHitMethod,
+        Vector(k, msg, nonce, h, N),
+        Map()
+      )
+      roundTripTest(expr)
+    }
+
+    VersionContext.withVersions(VersionContext.V6SoftForkVersion, 1) {
+      code
+    }
+
+    an[ValidationException] should be thrownBy (
       VersionContext.withVersions((VersionContext.V6SoftForkVersion - 1).toByte, 1) {
         code
       }
diff --git a/interpreter/shared/src/test/scala/sigmastate/eval/BasicOpsTests.scala b/interpreter/shared/src/test/scala/sigmastate/eval/BasicOpsTests.scala
index c4cd58a4ef..52cc6af66c 100644
--- a/interpreter/shared/src/test/scala/sigmastate/eval/BasicOpsTests.scala
+++ b/interpreter/shared/src/test/scala/sigmastate/eval/BasicOpsTests.scala
@@ -2,7 +2,10 @@ package sigmastate.eval
 
 import org.scalatest.funsuite.AnyFunSuite
 import org.scalatest.matchers.should.Matchers
-import sigma.ast.{BigIntConstant, ErgoTree, Global, JitCost, MethodCall, SBigIntMethods, SGlobalMethods}
+import sigma.ast.{BigIntConstant, ErgoTree, Global, JitCost, MethodCall, SGlobalMethods}
+import scorex.util.encode.Base16
+import sigma.Extensions.ArrayOps
+import sigma.ast.{ByteArrayConstant, IntConstant}
 import sigma.crypto.SecP256K1Group
 import sigma.data.{CBigInt, TrivialProp}
 import sigma.eval.SigmaDsl
@@ -13,6 +16,7 @@ import java.math.BigInteger
 import sigma.{ContractsTestkit, SigmaProp}
 import sigmastate.interpreter.{CErgoTreeEvaluator, CostAccumulator}
 import sigmastate.interpreter.CErgoTreeEvaluator.DefaultProfiler
+import sigma.{Box, VersionContext}
 
 import scala.language.implicitConversions
 
@@ -68,6 +72,69 @@ class BasicOpsTests extends AnyFunSuite with ContractsTestkit with Matchers {
     box.creationInfo._1 shouldBe a [Integer]
   }
 
+  test("xor evaluation") {
+    val es = CErgoTreeEvaluator.DefaultEvalSettings
+    val accumulator = new CostAccumulator(
+      initialCost = JitCost(0),
+      costLimit = Some(JitCost.fromBlockCost(es.scriptCostLimitInEvaluator)))
+
+    val context = new CContext(
+      noInputs.toColl, noHeaders, dummyPreHeader,
+      Array[Box]().toColl, Array[Box]().toColl, 0, null, 0, null,
+      dummyPubkey.toColl, Colls.emptyColl, null, VersionContext.V6SoftForkVersion, VersionContext.V6SoftForkVersion)
+
+    val evaluator = new CErgoTreeEvaluator(
+      context = context,
+      constants = ErgoTree.EmptyConstants,
+      coster = accumulator, DefaultProfiler, es)
+
+    val msg = Colls.fromArray(Base16.decode("0a101b8c6a4f2e").get)
+    VersionContext.withVersions(VersionContext.V6SoftForkVersion, VersionContext.V6SoftForkVersion) {
+      val res = MethodCall(Global, SGlobalMethods.xorMethod,
+        IndexedSeq(ByteArrayConstant(msg), ByteArrayConstant(msg)), Map.empty)
+        .evalTo[sigma.Coll[Byte]](Map.empty)(evaluator)
+
+      res should be(Colls.fromArray(Base16.decode("00000000000000").get))
+    }
+  }
+
+  /**
+    * Checks BigInt.nbits evaluation for SigmaDSL as well as AST interpreter (MethodCall) layers
+    */
+  test("powHit evaluation") {
+    val k = 32
+    val msg = Colls.fromArray(Base16.decode("0a101b8c6a4f2e").get)
+    val nonce = Colls.fromArray(Base16.decode("000000000000002c").get)
+    val hbs = Colls.fromArray(Base16.decode("00000000").get)
+    val N = 1024 * 1024
+
+    SigmaDsl.powHit(k, msg, nonce, hbs, N) shouldBe CBigInt(new BigInteger("326674862673836209462483453386286740270338859283019276168539876024851191344"))
+
+    val es = CErgoTreeEvaluator.DefaultEvalSettings
+    val accumulator = new CostAccumulator(
+      initialCost = JitCost(0),
+      costLimit = Some(JitCost.fromBlockCost(es.scriptCostLimitInEvaluator)))
+
+    val context = new CContext(
+      noInputs.toColl, noHeaders, dummyPreHeader,
+      Array[Box]().toColl, Array[Box]().toColl, 0, null, 0, null,
+      dummyPubkey.toColl, Colls.emptyColl, null, VersionContext.V6SoftForkVersion, VersionContext.V6SoftForkVersion)
+
+    val evaluator = new CErgoTreeEvaluator(
+      context = context,
+      constants = ErgoTree.EmptyConstants,
+      coster = accumulator, DefaultProfiler, es)
+
+    VersionContext.withVersions(VersionContext.V6SoftForkVersion, VersionContext.V6SoftForkVersion) {
+      val res = MethodCall(Global, SGlobalMethods.powHitMethod,
+        IndexedSeq(IntConstant(k), ByteArrayConstant(msg), ByteArrayConstant(nonce),
+          ByteArrayConstant(hbs), IntConstant(N)), Map.empty)
+        .evalTo[sigma.BigInt](Map.empty)(evaluator)
+
+      res should be(CBigInt(new BigInteger("326674862673836209462483453386286740270338859283019276168539876024851191344")))
+    }
+  }
+
   /**
     * Checks BigInt.nbits evaluation for SigmaDSL as well as AST interpreter (MethodCall) layers
     */
@@ -88,7 +155,6 @@ class BasicOpsTests extends AnyFunSuite with ContractsTestkit with Matchers {
         .evalTo[Long](Map.empty)(evaluator)
 
     res should be (NBitsUtils.encodeCompactBits(0))
-
   }
 
 }
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 7d91b975b2..8f392eedac 100644
--- a/sc/shared/src/main/scala/sigma/compiler/ir/GraphBuilding.scala
+++ b/sc/shared/src/main/scala/sigma/compiler/ir/GraphBuilding.scala
@@ -5,6 +5,7 @@ import sigma.ast.SType.tT
 import sigma.{SigmaException, VersionContext, ast}
 import sigma.Evaluation.stypeToRType
 import sigma.ast.SType.tT
+import sigma.{SigmaException, VersionContext, ast}
 import sigma.ast.TypeCodes.LastConstantCode
 import sigma.ast.Value.Typed
 import sigma.ast.syntax.{SValue, ValueOps}
@@ -1185,6 +1186,19 @@ trait GraphBuilding extends Base with DefRewriting { IR: IRContext =>
             case SGlobalMethods.decodeNBitsMethod.name if VersionContext.current.isV6SoftForkActivated =>
               val c1 = asRep[Long](argsV(0))
               g.decodeNbits(c1)
+            case SGlobalMethods.powHitMethod.name if VersionContext.current.isV6SoftForkActivated =>
+              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 =>
+              val c1 = asRep[BigInt](argsV(0))
+              g.encodeNbits(c1)
+            case SGlobalMethods.decodeNBitsMethod.name if VersionContext.current.isV6SoftForkActivated =>
+              val c1 = asRep[Long](argsV(0))
+              g.decodeNbits(c1)
             case SGlobalMethods.deserializeToMethod.name if VersionContext.current.isV6SoftForkActivated =>
               val c1 = asRep[Coll[Byte]](argsV(0))
               val c2 = stypeToElem(method.stype.tRange.withSubstTypes(typeSubst))
diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/GraphIRReflection.scala b/sc/shared/src/main/scala/sigma/compiler/ir/GraphIRReflection.scala
index 6b83bc10c9..b415c460a7 100644
--- a/sc/shared/src/main/scala/sigma/compiler/ir/GraphIRReflection.scala
+++ b/sc/shared/src/main/scala/sigma/compiler/ir/GraphIRReflection.scala
@@ -533,6 +533,12 @@ object GraphIRReflection {
         mkMethod(clazz, "serialize", Array[Class[_]](classOf[Base#Ref[_]])) { (obj, args) =>
           obj.asInstanceOf[ctx.SigmaDslBuilder].serialize(args(0).asInstanceOf[ctx.Ref[Any]])
         },
+        mkMethod(clazz, "powHit", Array[Class[_]](classOf[Base#Ref[_]], classOf[Base#Ref[_]],
+          classOf[Base#Ref[_]], classOf[Base#Ref[_]], classOf[Base#Ref[_]])) { (obj, args) =>
+          obj.asInstanceOf[ctx.SigmaDslBuilder].powHit(args(0).asInstanceOf[ctx.Ref[Int]],
+            args(1).asInstanceOf[ctx.Ref[ctx.Coll[Byte]]], args(2).asInstanceOf[ctx.Ref[ctx.Coll[Byte]]],
+            args(3).asInstanceOf[ctx.Ref[ctx.Coll[Byte]]], args(4).asInstanceOf[ctx.Ref[Int]])
+        },
         mkMethod(clazz, "encodeNbits", Array[Class[_]](classOf[Base#Ref[_]])) { (obj, args) =>
           obj.asInstanceOf[ctx.SigmaDslBuilder].encodeNbits(args(0).asInstanceOf[ctx.Ref[ctx.BigInt]])
         },
diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/SigmaDslUnit.scala b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/SigmaDslUnit.scala
index a8608651a2..1b6ac41077 100644
--- a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/SigmaDslUnit.scala
+++ b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/SigmaDslUnit.scala
@@ -118,6 +118,7 @@ import scalan._
       def xor(l: Ref[Coll[Byte]], r: Ref[Coll[Byte]]): Ref[Coll[Byte]]
       def encodeNbits(bi: Ref[BigInt]): Ref[Long]
       def decodeNbits(l: Ref[Long]): Ref[BigInt]
+      def powHit(k: Ref[Int], msg: Ref[Coll[Byte]], nonce: Ref[Coll[Byte]], h: Ref[Coll[Byte]], N: Ref[Int]): Ref[BigInt];
       def serialize[T](value: Ref[T]): Ref[Coll[Byte]]
       def fromBigEndianBytes[T](bytes: Ref[Coll[Byte]])(implicit cT: Elem[T]): Ref[T]
       def deserializeTo[T](bytes: Ref[Coll[Byte]])(implicit cT: Elem[T]): Ref[T]
diff --git a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/SigmaDslImpl.scala b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/SigmaDslImpl.scala
index 336e4ed9f2..7a3e5dd3b1 100644
--- a/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/SigmaDslImpl.scala
+++ b/sc/shared/src/main/scala/sigma/compiler/ir/wrappers/sigma/impl/SigmaDslImpl.scala
@@ -2003,6 +2003,14 @@ object SigmaDslBuilder extends EntityObject("SigmaDslBuilder") {
         true, false, cT))
     }
 
+
+    override def powHit(k: Ref[Int], msg: Ref[Coll[Byte]], nonce: Ref[Coll[Byte]], h: Ref[Coll[Byte]], N: Ref[Int]): Ref[BigInt] = {
+      asRep[BigInt](mkMethodCall(self,
+        SigmaDslBuilderClass.getMethod("powHit", classOf[Sym], classOf[Sym], classOf[Sym], classOf[Sym], classOf[Sym]),
+        Array[AnyRef](k, msg, nonce, h, N),
+        true, false, element[BigInt]))
+    }
+
     override def encodeNbits(bi: Ref[BigInt]): Ref[Long] = {
       asRep[Long](mkMethodCall(self,
         SigmaDslBuilderClass.getMethod("encodeNbits", classOf[Sym]),
@@ -2176,6 +2184,13 @@ object SigmaDslBuilder extends EntityObject("SigmaDslBuilder") {
         true, true, element[Coll[Byte]]))
     }
 
+    def powHit(k: Ref[Int], msg: Ref[Coll[Byte]], nonce: Ref[Coll[Byte]], h: Ref[Coll[Byte]], N: Ref[Int]): Ref[BigInt] = {
+      asRep[BigInt](mkMethodCall(source,
+        SigmaDslBuilderClass.getMethod("powHit", classOf[Sym], classOf[Sym], classOf[Sym], classOf[Sym], classOf[Sym]),
+        Array[AnyRef](k, msg, nonce, h, N),
+        true, true, element[BigInt]))
+    }
+
     def serialize[T](value: Ref[T]): Ref[Coll[Byte]] = {
       asRep[Coll[Byte]](mkMethodCall(source,
         SigmaDslBuilderClass.getMethod("serialize", classOf[Sym]),
@@ -2229,7 +2244,7 @@ object SigmaDslBuilder extends EntityObject("SigmaDslBuilder") {
         Elem.declaredMethods(RClass(classOf[SigmaDslBuilder]), RClass(classOf[SSigmaDslBuilder]), Set(
         "Colls", "verifyZK", "atLeast", "allOf", "allZK", "anyOf", "anyZK", "xorOf", "sigmaProp", "blake2b256",
           "sha256", "byteArrayToBigInt", "longToByteArray", "byteArrayToLong", "proveDlog", "proveDHTuple", "groupGenerator",
-          "substConstants", "decodePoint", "avlTree", "xor", "encodeNBits", "decodeNBits", "serialize", "fromBigEndianBytes", "deserializeTo"
+          "substConstants", "decodePoint", "avlTree", "xor", "encodeNBits", "decodeNBits", "serialize", "fromBigEndianBytes", "powHit", "deserializeTo"
         ))
     }
   }
diff --git a/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala b/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala
index c315292b77..c45fc327e7 100644
--- a/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala
+++ b/sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala
@@ -21,6 +21,11 @@ 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.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
@@ -1457,6 +1462,48 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite =>
     )
   }
 
+  property("Global.powHit") {
+    def powHit: Feature[Coll[Byte], sigma.BigInt] = newFeature(
+      { (x: Coll[Byte]) =>
+        val msg = x.slice(0, 7).toArray
+        val nonce = x.slice(7, 15).toArray
+        val h = x.slice(15, 19).toArray
+        CBigInt(Autolykos2PowValidation.hitForVersion2ForMessageWithChecks(32, msg, nonce, h, 1024 * 1024).bigInteger)
+      },
+      "{ (x: Coll[Byte]) => val msg = x.slice(0,7); val nonce = x.slice(7,15); val h = x.slice(15,19); " +
+        "Global.powHit(32, msg, nonce, h, 1024 * 1024) }",
+      FuncValue(
+        Array((1, SByteArray)),
+        MethodCall.typed[Value[SBigInt.type]](
+          Global,
+          SGlobalMethods.powHitMethod,
+          Array(
+            IntConstant(32),
+            Slice(ValUse(1, SByteArray), IntConstant(0), IntConstant(7)),
+            Slice(ValUse(1, SByteArray), IntConstant(7), IntConstant(15)),
+            Slice(ValUse(1, SByteArray), IntConstant(15), IntConstant(19)),
+            IntConstant(1048576)
+          ),
+          Map()
+        )
+      ),
+      sinceVersion = VersionContext.V6SoftForkVersion)
+
+    // bytes of real mainnet block header at height 614,440
+    val msg = Base16.decode("0a101b8c6a4f2e").get
+    val nonce = Base16.decode("000000000000002c").get
+    val h = Base16.decode("00000000").get
+    val x = Colls.fromArray(msg ++ nonce ++ h)
+    val hit = CBigInt(new BigInteger("326674862673836209462483453386286740270338859283019276168539876024851191344"))
+
+    verifyCases(
+      Seq(
+        x -> new Expected(ExpectedResult(Success(hit), None))
+      ),
+      powHit
+    )
+  }
+
   property("higher order lambdas") {
     val f = newFeature[Coll[Int], Coll[Int]](
       { (xs: Coll[Int]) =>
diff --git a/sc/shared/src/test/scala/sigmastate/ErgoTreeSpecification.scala b/sc/shared/src/test/scala/sigmastate/ErgoTreeSpecification.scala
index 381d21c6c1..2e8b7ecc17 100644
--- a/sc/shared/src/test/scala/sigmastate/ErgoTreeSpecification.scala
+++ b/sc/shared/src/test/scala/sigmastate/ErgoTreeSpecification.scala
@@ -519,7 +519,7 @@ class ErgoTreeSpecification extends SigmaDslTesting with ContractsTestkit with C
       (SGlobal.typeId, Seq(
         MInfo(1, groupGeneratorMethod), MInfo(2, xorMethod)
       ) ++ (if (isV6Activated) {
-        Seq(MInfo(3, serializeMethod), MInfo(4, deserializeToMethod), MInfo(5, fromBigEndianBytesMethod), MInfo(6, encodeNBitsMethod), MInfo(7, decodeNBitsMethod)) // methods added in v6.0
+        Seq(MInfo(3, serializeMethod), MInfo(4, deserializeToMethod), MInfo(5, fromBigEndianBytesMethod), MInfo(6, encodeNBitsMethod), MInfo(7, decodeNBitsMethod), MInfo(8, powHitMethod)) // methods added in v6.0
       } else {
         Seq.empty[MInfo]
       }), true)
diff --git a/sc/shared/src/test/scala/sigmastate/TestingInterpreterSpecification.scala b/sc/shared/src/test/scala/sigmastate/TestingInterpreterSpecification.scala
index 1af15c9ad0..52dec1a657 100644
--- a/sc/shared/src/test/scala/sigmastate/TestingInterpreterSpecification.scala
+++ b/sc/shared/src/test/scala/sigmastate/TestingInterpreterSpecification.scala
@@ -11,6 +11,7 @@ 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.data.{CAND, CAvlTree, CHeader, ProveDlog, SigmaBoolean, TrivialProp}
 import sigma.interpreter.ContextExtension
@@ -334,6 +335,27 @@ class TestingInterpreterSpecification extends CompilerTestingCommons
     testEval("Coll(1, 1).getOrElse(3, 1 + 1) == 2")
   }
 
+  property("Evaluate powHit") {
+    val source =
+      """
+        |{
+        | val b: BigInt = bigInt("1157920892373161954235709850086879078528375642790749043826051631415181614943")
+        | val k = 32
+        | val N = 1024 * 1024
+        | val msg = fromBase16("0a101b8c6a4f2e")
+        | val nonce = fromBase16("000000000000002c")
+        | val h = fromBase16("00000000")
+        |
+        | 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 {
+      testEval(source)
+    }
+  }
+
   property("Evaluation example #1") {
     val dk1 = prover.dlogSecrets(0).publicImage
     val dk2 = prover.dlogSecrets(1).publicImage

From fa4b4b4680cd02b93eba33c69569de6cae659e4d Mon Sep 17 00:00:00 2001
From: Alexander Chepurnoy 
Date: Fri, 22 Nov 2024 23:39:43 +0300
Subject: [PATCH 305/314] doc update

---
 .../src/main/scala/sigma/SigmaDsl.scala       |   2 -
 docs/LangSpec.md                              | 277 ++++++++++++++++--
 2 files changed, 247 insertions(+), 32 deletions(-)

diff --git a/core/shared/src/main/scala/sigma/SigmaDsl.scala b/core/shared/src/main/scala/sigma/SigmaDsl.scala
index 821080ec00..e295702331 100644
--- a/core/shared/src/main/scala/sigma/SigmaDsl.scala
+++ b/core/shared/src/main/scala/sigma/SigmaDsl.scala
@@ -1,7 +1,5 @@
 package sigma
 
-import sigma.ast.SType
-
 import java.math.BigInteger
 import sigma.data._
 
diff --git a/docs/LangSpec.md b/docs/LangSpec.md
index 5cbb569a56..3f5453072f 100644
--- a/docs/LangSpec.md
+++ b/docs/LangSpec.md
@@ -4,18 +4,18 @@
 
 ErgoScript is a language to write contracts for [Ergo
 blockchain](https://ergoplatform.org). ErgoScript contracts can be compiled to
-[ErgoTrees](https://ergoplatform.org/docs/ErgoTree.pdf), serialized and stored
+[ErgoTrees](https://ergoplatform.org/docs/ErgoTree.pdf), typed abstract serialized and stored
 in UTXOs.
 
 A good starting point to writing contracts is to use [ErgoScript by
-Example](https://github.com/ergoplatform/ergoscript-by-example) with [Ergo
+Example](https://github.com/ergoplatform/ergoscript-by-example), with [Ergo
 Playgrounds](https://github.com/ergoplatform/ergo-playgrounds) or
-[Appkit](https://github.com/ergoplatform/ergo-appkit).
+[Appkit](https://github.com/ergoplatform/ergo-appkit) or [Fleet](https://github.com/fleet-sdk) .
 
 ErgoScript compiler is
 [published](https://mvnrepository.com/artifact/org.scorexfoundation/sigma-state)
 as a library which is cross compiled for Java 7 and Java 8+ and thus can be used
-from any JVM lanugage and also on Android and JavaFX platforms.
+from any JVM langugage and also on Android and JavaFX platforms. It is also cross-compiled to JavaScript using Scala.js.
 
 The following example shows how source code of ErgoScript contract can be used
 to create new transaction using
@@ -56,7 +56,7 @@ The following sections describe ErgoScript and its operations.
 
 #### ErgoScript language features overview
 
-- syntax borrowed from Scala
+- syntax borrowed from Scala but simplified
 - standard syntax and semantics for well known constructs (operations, code blocks, if branches etc.)
 - high-order language with first-class lambdas which are used in collection operations
 - call-by-value (eager evaluation)
@@ -97,6 +97,7 @@ Type Name        |   Description
 `Int`            | 32 bit signed integer
 `Long`           | 64 bit signed integer
 `BigInt`         | 256 bit signed integer
+`UnsignedBigInt` | 256 bit unsigned integer
 `SigmaProp`      | a type representing a _sigma proposition_ which can be verified by executing a Sigma protocol with zero-knowledge proof of knowledge. Every contract should return a value of this type.
 `AvlTree`        | represents a digest of authenticated dynamic dictionary and can be used to verify proofs of operations performed on the dictionary
 `GroupElement`   | elliptic curve points
@@ -119,11 +120,12 @@ types as in the following example.
 Literals are used to introduce values of some types directly in program text
 like in the following example:
 ```
- val unit: Unit = ()       // unit constant
- val long: Int = 10        // interger value literal
- val bool: Boolean = true  // logical literal
- val arr = Coll(1, 2, 3)   // constructs a collection with given items
- val str = "abc"           // string of characters 
+ val unit: Unit = ()                           // unit constant
+ val long: Int = 10                            // interger value literal
+ val bool: Boolean = true                      // logical literal
+ val arr = Coll(1, 2, 3)                       // constructs a collection with given items
+ val str = "abc"                               // string of characters 
+ val ubi = unsignedBigInt("508473958676860")   // unsigned big integer
 ```
 Note that many types don't have literal syntax and their values are introduced 
 by applying operations, for example `deserialize` function can be used to introduce
@@ -167,9 +169,61 @@ class Numeric {
   
   /** Convert this Numeric value to BigInt. */
   def toBigInt: BigInt
+
+  /** Convert this Numeric value to UnsignedBigInt. */
+  def toUnsignedBigInt: UnsignedBigInt
+
+  /** Returns a big-endian representation of this value in a collection of bytes.
+    * For example, the `Int` value `0x12131415` would yield the
+    * collection of bytes [0x12, 0x13, 0x14, 0x15]
+    */
+  def toBytes(x: T): Coll[Byte]
+
+  /**
+   * Returns a big-endian binary representation of this value as boolean array.
+   */
+  def toBits(x: T): Coll[Boolean]
+
+  /**
+    * @return a numeric value which is inverse of `x` (every bit, including sign, is flipped)
+    */
+  def bitwiseInverse(x: T): T
+
+  /**
+    * @return a numeric value which is `this | that`
+    */
+  def bitwiseOr(x: T, y: T): T
+
+  /**
+    * @return a numeric value which is `this && that`
+    */
+  def bitwiseAnd(x: T, y: T): T
+
+  /**
+    * @return a numeric value which is `this xor that`
+    */
+  def bitwiseXor(x: T, y: T): T
+
+  /**
+    * @return a value which is (this << n). The shift distance, n, may be negative,
+    *         in which case this method performs a right shift. (Computes floor(this * 2n).)
+    */
+  def shiftLeft(x: T, bits: Int): T
+
+  /**
+    * @return a value which is (this >> n). Sign extension is performed. The shift distance, n,
+    *         may be negative, in which case this method performs a left shift. (Computes floor(this / 2n).)
+    */
+  def shiftRight(x: T, bits: Int): T
+ 
 }
 ```
 
+The only exception for conversions is about BigInt to and from UnsignedBigInt. To convert from signed big int to unsigned, use
+`.toUnsigned` method to convert signed big integer to unsigned, or `.toUnsignedMod(m)` to convert modulo `m` (and modulo
+ operation is cryptographic, ie always returns positive number modulo `m`). To convert from unsigned big int to signed,
+ use `.toSigned`.
+
 All the predefined numeric types inherit Numeric class and its methods.
 They can be thought as being pre-defined like the following.
 
@@ -179,8 +233,51 @@ class Short extends Numeric
 class Int extends Numeric
 class Long extends Numeric
 class BigInt extends Numeric
+class UnsignedBigInt extends Numeric
+```
+
+examples: 
+
+```
+val b = (126 + 1).toByte  // max byte value
+b.bitwiseInverse == (-128).toByte // min byte value
+```
+
+```
+val x = 4.toByte
+val y = 2
+x.shiftLeft(y) == 16.toByte
+```
+
+```
+val l = getVar[Long](1).get
+val ba = l.toBytes
+Global.fromBigEndianBytes[Long](ba) == l
+```
+
+In addition to all the methods from above, UnsignedBigInt type has support for modular arithmetics, namely, `modInverse`,
+`plusMod`, `subtractMod`, `multiplyMod`, `mod`. Examples:
+
+```
+val bi1 = unsignedBigInt("2")
+val bi2 = unsignedBigInt("4")
+val m = unsignedBigInt("575879797")
+bi1.subtractMod(bi2, m) > 0
 ```
 
+```
+val bi = unsignedBigInt("248486720836984554860790790898080606")
+val m = unsignedBigInt("575879797")
+bi.mod(m) < bi
+```
+
+```
+val bi = unsignedBigInt("248486720836984554860790790898080606")
+val m = unsignedBigInt("575879797")
+bi.modInverse(m) > 0 // returns multiplicative inverse of bi mod m
+```
+
+
 #### Context Data 
 
 Every script is executed in a context, which is a collection of data available
@@ -245,13 +342,34 @@ class Context {
     */
   def minerPubKey: Coll[Byte]
 
+  /** Extracts Context variable by id and type.
+    * ErgoScript is typed, so accessing a the variables is an operation which involves
+    * some expected type given in brackets. Thus `getVar[Int](id)` expression should
+    * evaluate to a valid value of the `Option[Int]` type.
+    */
+  def getVar[T](id: Byte): Option[T]
+
+  /**
+    * A variant of `getVar` to extract a context variable by id and type from any input
+    */
+  def getVarFromInput[T](inputIndex: Short, id: Byte): Option[T]
+
+  /** Returns new $coll with elements in reversed order.
+    *
+    *  @return A new $coll with all elements of this $coll in reversed order.
+    */
+  def reverse: Coll[T]
+
+  /** Builds a new $coll from this $coll without any duplicate elements.
+    *
+    *  @return  A new $coll which contains the first occurrence of every element of this $coll.
+    */
+  def distinct: Coll[T]
+  
 }
 
 /** Represents data of the block headers available in scripts. */
 class Header {  
-
-  /** Validate header's proof-of-work */  
-  def checkPow: Boolean
   
   /** Bytes representation of ModifierId of this Header */
   def id: Coll[Byte]
@@ -276,7 +394,7 @@ class Header {
 
   /** Current difficulty in a compressed view.
     * NOTE: actually it is unsigned Int*/
-  def nBits: Long  // actually it is unsigned Int 
+  def nBits: Long
 
   /** Block height */
   def height: Int
@@ -288,24 +406,16 @@ class Header {
     * Part of Autolykos solution (pk). 
     */
   def minerPk: GroupElement
-
-  /** One-time public key. Prevents revealing of miners secret. 
-    * Part of Autolykos solution (w). 
-    */
-  def powOnetimePk: GroupElement
-
+  
   /** Nonce value found by the miner. Part of Autolykos solution (n). */
   def powNonce: Coll[Byte]
-
-  /** Distance between pseudo-random number, corresponding to nonce `powNonce`
-    * and a secret, corresponding to `minerPk`. The lower `powDistance` is, the
-    * harder it was to find this solution. 
-    * Part of Autolykos solution (d).
-    */
-  def powDistance: BigInt
-
+  
   /** Miner votes for changing system parameters. */
   def votes: Coll[Byte]
+  
+  /** Validate header's proof-of-work */
+  def checkPow: Boolean
+
 }
 
 /** Only header fields that can be predicted by a miner. */
@@ -458,6 +568,12 @@ class GroupElement {
     * @return this to the power of k.
     */
   def exp(k: BigInt): GroupElement
+  
+  /** Exponentiate this GroupElement to the given unsigned 256 bit integer.
+    * @param k The power.
+    * @return this to the power of k.
+    */
+  def expUnsigned(k: UnsignedBigInt): GroupElement
 
   /** Group operation. */
   def multiply(that: GroupElement): GroupElement
@@ -669,8 +785,7 @@ class Option[A] {
   
   /** Returns the option's value if the option is nonempty, otherwise
     * return the result of evaluating `default`.
-    * NOTE: the `default` is evaluated even if the option contains the value
-    * i.e. not lazily.
+    * NOTE: the `default` is evaluated lazily.
     *
     * @param default  the default expression.
     */
@@ -845,6 +960,27 @@ class Coll[A] {
     *           to `elem`, or `-1`, if none exists.
     */
   def indexOf(elem: A, from: Int): Int
+
+  /** The element at given index or None if there is no such element. Indices start at `0`.
+    *
+    *  @param  i       the index
+    *  @return         the element at the given index, or None if there is no such element
+    */
+  def get(i: Int): Option[A]
+
+  /**
+    * @return true if first elements of this collection form given `ys` collection, false otherwise.
+    *         E.g. [1,2,3] starts with [1,2]
+    */
+  def startsWith(ys: Coll[A]): Boolean
+
+  /**
+    * @return true if last elements of this collection form given `ys` collection, false otherwise.
+    *         E.g. [1,2,3] ends with [2,3]
+    */
+  def endsWith(ys: Coll[A]): Boolean
+  
+  
 }
 ```
 
@@ -854,6 +990,14 @@ val myOutput = OUTPUTS(0)
 val myInput = INPUTS(0)
 ```
 
+or, if you want to get None instead of exception: 
+```
+val elemOpt = coll.get(0)
+if (elemOpt.isDefined) {
+  val elem = elemOpt.get
+}
+```
+
 Any collection have the `size` property which returns the number of elements in
 the collection.
 
@@ -868,6 +1012,73 @@ satisfying some predicate (condition)
 val ok = OUTPUTS.exists { (box: Box) => box.value > 1000 }
 ``` 
 
+### Predefined global functions
+
+There are some functions which do not belong to other types, thus they put under `Global` type. Those functions are:
+
+
+
+```
+{
+  /** The generator g of the group is an element of the group such that, when written
+    * multiplicative form, every element of the group is a power of g.
+    * @return the generator of this Dlog group
+    */
+  def groupGenerator: GroupElement
+
+  /**
+    * @return NBits-encoded approximate representation of given big integer,
+    *         see (https://bitcoin.stackexchange.com/questions/57184/what-does-the-nbits-value-represent)
+    *         for NBits format details
+    */
+  def encodeNbits(bi: BigInt): Long
+
+  /**
+    * @return big integer decoded from NBits value provided,
+    *         see (https://bitcoin.stackexchange.com/questions/57184/what-does-the-nbits-value-represent)
+    *         for format details
+    */
+  def decodeNbits(l: Long): BigInt
+  
+  
+  /** Serializes the given `value` into bytes using the default serialization format. */
+  def serialize[T](value: T)(implicit cT: RType[T]): Coll[Byte]
+
+  /** Returns a byte-wise XOR of the two collections of bytes. */
+  def xor(l: Coll[Byte], r: Coll[Byte]): Coll[Byte]
+
+  /** Calculates value of a custom Autolykos 2 hash function 
+    * @param k - k parameter of Autolykos 2 (number of inputs in k-sum problem)
+    * @param msg - message to calculate Autolykos hash 2 for
+    * @param nonce - used to pad the message to get Proof-of-Work hash function output with desirable properties
+    * @param h - PoW protocol specific padding for table uniqueness (e.g. block height in Ergo)
+    */
+  def powHit(k: Int, msg: Coll[Byte], nonce: Coll[Byte], h: Coll[Byte], N: Int): BigInt
+
+  /** Deserializes provided `bytes` into a value of type `T`. **/
+  def deserializeTo[T](bytes: Coll[Byte])(implicit cT: RType[T]): T
+
+  /** Returns a number decoded from provided big-endian bytes array. */
+  def fromBigEndianBytes[T](bytes: Coll[Byte])(implicit cT: RType[T]): T
+}
+```
+
+examples:
+
+```
+val h = getVar[Header](21).get
+val n = h.nBits
+val target = Global.decodeNbits(n)
+```
+
+```
+val src = getVar[Coll[Short]](21).get
+val ba = Global.serialize(src)
+val restored = Global.deserializeTo[Coll[Short]](ba)
+src == restored
+```
+
+
 ### Predefined global functions
 
 
@@ -1011,6 +1222,12 @@ def proveDlog(value: GroupElement): SigmaProp
   */
 def bigInt(input: String): BigInt
 
+/** Transforms Base16 encoded string literal into constant of type UnsignedBigInt.
+  * It is a compile-time operation and only string literal (constant) can be its
+  * argument.
+  */
+def unsignedBigInt(input: String): UnsignedBigInt
+
 /** Transforms Base16 encoded string literal into constant of type Coll[Byte].
   * It is a compile-time operation and only string literal (constant) can be its
   * argument.

From 912a523c9fc521a51bbb9cf0930ff55d57b672f5 Mon Sep 17 00:00:00 2001
From: Alexander Chepurnoy 
Date: Fri, 29 Nov 2024 19:19:01 +0300
Subject: [PATCH 306/314] Update core/js/src/main/scala/sigma/js/Type.scala

Co-authored-by: Alexander Slesarenko 
---
 core/js/src/main/scala/sigma/js/Type.scala | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/core/js/src/main/scala/sigma/js/Type.scala b/core/js/src/main/scala/sigma/js/Type.scala
index 069cca3e1e..ff391eba66 100644
--- a/core/js/src/main/scala/sigma/js/Type.scala
+++ b/core/js/src/main/scala/sigma/js/Type.scala
@@ -35,7 +35,7 @@ object Type extends js.Object {
   /** Descriptor of ErgoScript type BigInt. */
   val BigInt = new Type(sigma.BigIntRType)
 
-  /** Descriptor of ErgoScript type BigInt. */
+  /** Descriptor of ErgoScript type UnsignedBigInt. */
   val UnsignedBigInt = new Type(sigma.UnsignedBigIntRType)
 
   /** Descriptor of ErgoScript type GroupElement. */

From 0af752d440e89eba20701c561a952482d35ecbfa Mon Sep 17 00:00:00 2001
From: Alexander Chepurnoy 
Date: Fri, 29 Nov 2024 19:20:01 +0300
Subject: [PATCH 307/314] Update
 core/shared/src/main/scala/sigma/SigmaDsl.scala

Co-authored-by: Alexander Slesarenko 
---
 core/shared/src/main/scala/sigma/SigmaDsl.scala | 1 -
 1 file changed, 1 deletion(-)

diff --git a/core/shared/src/main/scala/sigma/SigmaDsl.scala b/core/shared/src/main/scala/sigma/SigmaDsl.scala
index 40cd2e5f96..1f3ff20a6e 100644
--- a/core/shared/src/main/scala/sigma/SigmaDsl.scala
+++ b/core/shared/src/main/scala/sigma/SigmaDsl.scala
@@ -207,7 +207,6 @@ trait UnsignedBigInt {
   /** Returns a big-endian representation of this BigInt in a collection of bytes.
     * For example, the value {@code 0x1213141516171819} would yield the
     * byte array {@code {0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19}}.
-    * @since 2.0
     */
   def toBytes: Coll[Byte]
 

From b545aa5eba4cfc86992a04c3d15fd650526d5f0a Mon Sep 17 00:00:00 2001
From: Alexander Chepurnoy 
Date: Fri, 29 Nov 2024 19:31:42 +0300
Subject: [PATCH 308/314] Update
 sc/shared/src/test/scala/sigmastate/ErgoTreeSpecification.scala

Co-authored-by: Alexander Slesarenko 
---
 sc/shared/src/test/scala/sigmastate/ErgoTreeSpecification.scala | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/sc/shared/src/test/scala/sigmastate/ErgoTreeSpecification.scala b/sc/shared/src/test/scala/sigmastate/ErgoTreeSpecification.scala
index cad5d4c152..0504a79c65 100644
--- a/sc/shared/src/test/scala/sigmastate/ErgoTreeSpecification.scala
+++ b/sc/shared/src/test/scala/sigmastate/ErgoTreeSpecification.scala
@@ -441,7 +441,7 @@ class ErgoTreeSpecification extends SigmaDslTesting with ContractsTestkit with C
     },
       {
         if (isV6Activated) {
-          // SBigInt inherit methods from SNumericType.methods
+          // SUnsignedBigInt inherit methods from SNumericType.methods
           // however they are not resolvable via SBigInt.typeId before v6.0
           import SNumericTypeMethods._
           (SUnsignedBigInt.typeId, Seq(

From ad3506e3aaaceabc9db522273b9373c3564e7293 Mon Sep 17 00:00:00 2001
From: Alexander Chepurnoy 
Date: Fri, 29 Nov 2024 21:35:53 +0300
Subject: [PATCH 309/314] addressing review comments

---
 .../src/main/scala/sigma/SigmaDsl.scala       | 35 +++++++++++++++----
 .../sigma/data/UnsignedBigIntegerOps.scala    | 13 ++-----
 .../org/ergoplatform/dsl/ContractSyntax.scala |  2 +-
 .../org/ergoplatform/sdk/JavaHelpers.scala    | 10 ++++++
 4 files changed, 43 insertions(+), 17 deletions(-)

diff --git a/core/shared/src/main/scala/sigma/SigmaDsl.scala b/core/shared/src/main/scala/sigma/SigmaDsl.scala
index 40cd2e5f96..566258dc9a 100644
--- a/core/shared/src/main/scala/sigma/SigmaDsl.scala
+++ b/core/shared/src/main/scala/sigma/SigmaDsl.scala
@@ -217,7 +217,8 @@ trait UnsignedBigInt {
     */
   def compareTo(that: UnsignedBigInt): Int
 
-  /** Returns a BigInt whose value is {@code (this + that)}.
+  /** Returns a BigInt whose value is {@code (this + that)}, or exception if result does not fit into 256 bits
+    * (consider using plusMod to avoid exception)
     *
     * @param  that value to be added to this BigInt.
     * @return { @code this + that}
@@ -225,7 +226,8 @@ trait UnsignedBigInt {
   def add(that: UnsignedBigInt): UnsignedBigInt
   def +(that: UnsignedBigInt): UnsignedBigInt = add(that)
 
-  /** Returns a BigInt whose value is {@code (this - that)}.
+  /** Returns a BigInt whose value is {@code (this - that)}, or exception if result is negative
+    * (consider using plusMod to avoid exception)
     *
     * @param  that value to be subtracted from this BigInt.
     * @return { @code this - that}
@@ -234,7 +236,8 @@ trait UnsignedBigInt {
 
   def -(that: UnsignedBigInt): UnsignedBigInt = subtract(that)
 
-  /** Returns a BigInt whose value is {@code (this * that)}.
+  /** Returns a BigInt whose value is {@code (this * that)} , or exception if result does not fit into 256 bits
+    * (consider using multiplyMod to avoid exception)
     *
     * @implNote An implementation may offer better algorithmic
     *           performance when { @code that == this}.
@@ -300,29 +303,48 @@ trait UnsignedBigInt {
   def |(that: UnsignedBigInt): UnsignedBigInt = or(that)
 
   def modInverse(m: UnsignedBigInt): UnsignedBigInt
+
+  /**
+    * @return this + that mod m , where mod is cryptographic mod operation
+    */
   def plusMod(that: UnsignedBigInt, m: UnsignedBigInt): UnsignedBigInt
+
+  /**
+    * @return this - that mod m , where mod is cryptographic mod operation, so result is always non-negative
+    */
   def subtractMod(that: UnsignedBigInt, m: UnsignedBigInt): UnsignedBigInt
+
+  /**
+    * @return this * that mod m , where mod is cryptographic mod operation
+    */
   def multiplyMod(that: UnsignedBigInt, m: UnsignedBigInt): UnsignedBigInt
 
   /**
-    * @return a big integer whose value is `this xor that`
+    * @return an unsigned big integer whose value is `this xor that`
     */
   def xor(that: UnsignedBigInt): UnsignedBigInt
 
   /**
-    * @return a 256-bit signed integer whose value is (this << n). The shift distance, n, may be negative,
+    * @return a 256-bit unsigned integer whose value is (this << n). The shift distance, n, may be negative,
     *         in which case this method performs a right shift. (Computes floor(this * 2n).)
     */
   def shiftLeft(n: Int): UnsignedBigInt
 
   /**
-    * @return a 256-bit signed integer whose value is (this >> n). Sign extension is performed. The shift distance, n,
+    * @return a 256-bit unsigned integer whose value is (this >> n). Sign extension is performed. The shift distance, n,
     *         may be negative, in which case this method performs a left shift. (Computes floor(this / 2n).)
     */
   def shiftRight(n: Int): UnsignedBigInt
 
+  /**
+    * @return an unsigned big integer value which is inverse of this (every bit is flipped)
+    */
   def bitwiseInverse(): UnsignedBigInt
 
+  /**
+    * @return signed version of the same value, or exception if the value does not fit into signed type (since it is
+    *         also about 256 bits, but one bit is encoding sign)
+    */
   def toSigned(): BigInt
 }
 
@@ -940,6 +962,7 @@ trait SigmaDslBuilder {
   /** Create DSL big integer from existing `java.math.BigInteger`*/
   def BigInt(n: BigInteger): BigInt
 
+  /** Create DSL unsigned big integer from existing `java.math.BigInteger`*/
   def UnsignedBigInt(n: BigInteger): UnsignedBigInt
 
   /** Extract `java.math.BigInteger` from DSL's `BigInt` type*/
diff --git a/data/shared/src/main/scala/sigma/data/UnsignedBigIntegerOps.scala b/data/shared/src/main/scala/sigma/data/UnsignedBigIntegerOps.scala
index bf3dd3e33b..e628703deb 100644
--- a/data/shared/src/main/scala/sigma/data/UnsignedBigIntegerOps.scala
+++ b/data/shared/src/main/scala/sigma/data/UnsignedBigIntegerOps.scala
@@ -54,16 +54,9 @@ object UnsignedBigIntNumericOps {
     def toDouble(x: UnsignedBigInt): Double = x.toDouble
   }
 
-  /** The instance of Integral for BigInt.
-    *
-    * Note: ExactIntegral was not defined for [[sigma.BigInt]] in v4.x.
-    * This is because arithmetic BigInt operations were handled in a special way
-    * (see `case op: ArithOp[t] if op.tpe == SBigInt =>` in RuntimeCosting.scala).
-    * As result [[scalan.primitives.UnBinOps.ApplyBinOp]] nodes were not created for
-    * BigInt operations in v4.x., and hence operation descriptors such as
-    * [[scalan.primitives.NumericOps.IntegralDivide]] and
-    * [[scalan.primitives.NumericOps.IntegralMod]] were not used for BigInt.
-    * NOTE: this instance is used in the new v5.0 interpreter.
+  /**
+    * The instance of Integral for UnsignedBigInt.
+    * Done similarly to BigIntIsIntegral.
     */
   object UnsignedBigIntIsIntegral extends UnsignedBigIntIsIntegral with UnsignedBigIntOrdering {
     def parseString(str: String): Option[UnsignedBigInt] = ???
diff --git a/sc/shared/src/main/scala/org/ergoplatform/dsl/ContractSyntax.scala b/sc/shared/src/main/scala/org/ergoplatform/dsl/ContractSyntax.scala
index 2554489340..34598627db 100644
--- a/sc/shared/src/main/scala/org/ergoplatform/dsl/ContractSyntax.scala
+++ b/sc/shared/src/main/scala/org/ergoplatform/dsl/ContractSyntax.scala
@@ -55,7 +55,7 @@ trait ContractSyntax { contract: SigmaContract =>
       case _: String => StringType
       case _: Unit => UnitType
       case _: sigma.BigInt => BigIntRType
-      case _: sigma.BigInt => UnsignedBigIntRType
+      case _: sigma.UnsignedBigInt => UnsignedBigIntRType
       case _: GroupElement => GroupElementRType
       case _: ErgoBox => syntax.ErgoBoxRType // TODO remove this RType
       case _: Box => BoxRType
diff --git a/sdk/shared/src/main/scala/org/ergoplatform/sdk/JavaHelpers.scala b/sdk/shared/src/main/scala/org/ergoplatform/sdk/JavaHelpers.scala
index a46e7490db..14cdf7f6bb 100644
--- a/sdk/shared/src/main/scala/org/ergoplatform/sdk/JavaHelpers.scala
+++ b/sdk/shared/src/main/scala/org/ergoplatform/sdk/JavaHelpers.scala
@@ -315,6 +315,16 @@ object JavaHelpers {
 
   def collRType[T](tItem: RType[T]): RType[Coll[T]] = sigma.collRType(tItem)
 
+  def BigIntRType: RType[sigma.BigInt] = sigma.BigIntRType
+
+  def GroupElementRType: RType[sigma.GroupElement] = sigma.GroupElementRType
+
+  def SigmaPropRType: RType[sigma.SigmaProp] = sigma.SigmaPropRType
+
+  def AvlTreeRType: RType[sigma.AvlTree] = sigma.AvlTreeRType
+
+  def BoxRType: RType[sigma.Box] = sigma.BoxRType
+
   def SigmaDsl: CSigmaDslBuilder = sigma.eval.SigmaDsl
 
   def collFrom(arr: Array[Byte]): Coll[Byte] = {

From 326b315141a1e754c43f41d7cdfefee01e194b31 Mon Sep 17 00:00:00 2001
From: Alexander Chepurnoy 
Date: Wed, 4 Dec 2024 12:51:18 +0300
Subject: [PATCH 310/314] UnsignedBigInt added to liftToConstant

---
 data/jvm/src/main/scala/sigma/Platform.scala | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/data/jvm/src/main/scala/sigma/Platform.scala b/data/jvm/src/main/scala/sigma/Platform.scala
index 104ea44d3d..8c5a8d1632 100644
--- a/data/jvm/src/main/scala/sigma/Platform.scala
+++ b/data/jvm/src/main/scala/sigma/Platform.scala
@@ -32,8 +32,7 @@ object Platform {
       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))
-
-      // todo: check UnsignedBigInt
+      case n: sigma.UnsignedBigInt => Nullable(mkConstant[SUnsignedBigInt.type](n, SUnsignedBigInt))
 
       case v: String if !VersionContext.current.isV6SoftForkActivated => Nullable(mkConstant[SString.type](v, SString))
 

From 6e34213338b877586727d8cb39a3f287eafbc8a9 Mon Sep 17 00:00:00 2001
From: Alexander Chepurnoy 
Date: Wed, 4 Dec 2024 13:10:34 +0300
Subject: [PATCH 311/314] versioning for SUnsignedBigInt check

---
 data/jvm/src/main/scala/sigma/Platform.scala | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/data/jvm/src/main/scala/sigma/Platform.scala b/data/jvm/src/main/scala/sigma/Platform.scala
index 8c5a8d1632..114465b02a 100644
--- a/data/jvm/src/main/scala/sigma/Platform.scala
+++ b/data/jvm/src/main/scala/sigma/Platform.scala
@@ -32,7 +32,7 @@ object Platform {
       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 n: sigma.UnsignedBigInt => Nullable(mkConstant[SUnsignedBigInt.type](n, SUnsignedBigInt))
+      case n: sigma.UnsignedBigInt if VersionContext.current.isV6SoftForkActivated => Nullable(mkConstant[SUnsignedBigInt.type](n, SUnsignedBigInt))
 
       case v: String if !VersionContext.current.isV6SoftForkActivated => Nullable(mkConstant[SString.type](v, SString))
 

From 38c2f63df8ac9b4b4dab555fdaa27cfddf5b303f Mon Sep 17 00:00:00 2001
From: Alexander Chepurnoy 
Date: Thu, 5 Dec 2024 11:55:20 +0300
Subject: [PATCH 312/314] Update
 interpreter/shared/src/test/scala/sigma/ast/SigmaBuilderTest.scala

Co-authored-by: Alexander Slesarenko 
---
 .../shared/src/test/scala/sigma/ast/SigmaBuilderTest.scala      | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/interpreter/shared/src/test/scala/sigma/ast/SigmaBuilderTest.scala b/interpreter/shared/src/test/scala/sigma/ast/SigmaBuilderTest.scala
index c1642627ee..029f7b3e9a 100644
--- a/interpreter/shared/src/test/scala/sigma/ast/SigmaBuilderTest.scala
+++ b/interpreter/shared/src/test/scala/sigma/ast/SigmaBuilderTest.scala
@@ -203,7 +203,7 @@ class SigmaBuilderTest extends AnyPropSpec with ScalaCheckPropertyChecks with Ma
     val v = "abc"
     val c = StringConstant(v)
     if (!VersionContext.current.isV6SoftForkActivated) {
-      // v6.0: String should be liftable at all (not supported in ErgoTree) (see https://github.com/ScorexFoundation/sigmastate-interpreter/issues/905)
+      // 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)
       testColl[SString.type](v, c)

From b85ba9c1dc97cb6ce944c6dcd2de2e3fecef629e Mon Sep 17 00:00:00 2001
From: Alexander Chepurnoy 
Date: Thu, 5 Dec 2024 14:47:34 +0300
Subject: [PATCH 313/314] cleared outdated comments in SigmaBuilderTest

---
 .../shared/src/test/scala/sigma/ast/SigmaBuilderTest.scala     | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/interpreter/shared/src/test/scala/sigma/ast/SigmaBuilderTest.scala b/interpreter/shared/src/test/scala/sigma/ast/SigmaBuilderTest.scala
index c1642627ee..d8e9573d8d 100644
--- a/interpreter/shared/src/test/scala/sigma/ast/SigmaBuilderTest.scala
+++ b/interpreter/shared/src/test/scala/sigma/ast/SigmaBuilderTest.scala
@@ -117,21 +117,18 @@ class SigmaBuilderTest extends AnyPropSpec with ScalaCheckPropertyChecks with Ma
 
   def testArray[T <: SType]
       (v: T#WrappedType, c: Constant[T])(implicit t: RType[T#WrappedType]) = {
-    // for any Byte and Short value `v`, lifting of array should succeed
     val arr = Array.fill[T#WrappedType](10)(v)(t.classTag)
     testSuccess(arr, TransformingSigmaBuilder.mkCollectionConstant(arr, c.tpe))
   }
 
   def testArrayFailure[T <: SType]
     (v: T#WrappedType, c: Constant[T])(implicit t: RType[T#WrappedType]) = {
-    // for any Byte and Short value `v`, lifting of array should succeed
     val arr = Array.fill[T#WrappedType](10)(v)(t.classTag)
     testFailure(arr)
   }
 
   def testColl[T <: SType]
       (v: T#WrappedType, c: Constant[T])(implicit t: RType[T#WrappedType]) = {
-    // for any Byte and Short value `v`, lifting of Coll should succeed
     val arr = Array.fill[T#WrappedType](10)(v)(t.classTag)
     val coll = arr.toColl
     testSuccess(coll, TransformingSigmaBuilder.mkCollectionConstant(coll, c.tpe))

From 2ad87f42c08ccdcee0c4fc930c62497c38e05a13 Mon Sep 17 00:00:00 2001
From: Alexander Chepurnoy 
Date: Thu, 5 Dec 2024 14:55:26 +0300
Subject: [PATCH 314/314] PreHeader added

---
 data/js/src/main/scala/sigma/Platform.scala  | 1 +
 data/jvm/src/main/scala/sigma/Platform.scala | 1 +
 2 files changed, 2 insertions(+)

diff --git a/data/js/src/main/scala/sigma/Platform.scala b/data/js/src/main/scala/sigma/Platform.scala
index a16db04bed..63c2ab5555 100644
--- a/data/js/src/main/scala/sigma/Platform.scala
+++ b/data/js/src/main/scala/sigma/Platform.scala
@@ -33,6 +33,7 @@ object Platform {
       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))
 
       // The Box lifting was broken in v4.x. `SigmaDsl.Box(b)` was missing which means the
       // isCorrectType requirement would fail in ConstantNode constructor.
diff --git a/data/jvm/src/main/scala/sigma/Platform.scala b/data/jvm/src/main/scala/sigma/Platform.scala
index 114465b02a..8fc5019bf9 100644
--- a/data/jvm/src/main/scala/sigma/Platform.scala
+++ b/data/jvm/src/main/scala/sigma/Platform.scala
@@ -32,6 +32,7 @@ object Platform {
       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 v: String if !VersionContext.current.isV6SoftForkActivated => Nullable(mkConstant[SString.type](v, SString))