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)) })