From f60e5b0db54d6e8fb2a05e1a8315a29e1d6a866c Mon Sep 17 00:00:00 2001 From: Alexander Chepurnoy Date: Tue, 16 Apr 2024 23:21:13 +0300 Subject: [PATCH] close #2150: storing unparsed bytes --- .../ergoplatform/mining/AutolykosPowScheme.scala | 2 +- .../org/ergoplatform/mining/CandidateUtils.scala | 3 ++- .../ergoplatform/mining/DefaultFakePowScheme.scala | 2 +- .../modifiers/history/header/Header.scala | 10 +++++++--- .../modifiers/history/header/HeaderSerializer.scala | 13 +++++++++---- .../modifiers/history/header/HeaderWithoutPow.scala | 9 +++++---- .../modifiers/history/header/PreGenesisHeader.scala | 1 + .../network/HeaderSerializationSpecification.scala | 4 ++-- .../utils/generators/ErgoCoreGenerators.scala | 1 + .../ergoplatform/mining/CandidateGenerator.scala | 3 ++- 10 files changed, 31 insertions(+), 17 deletions(-) diff --git a/ergo-core/src/main/scala/org/ergoplatform/mining/AutolykosPowScheme.scala b/ergo-core/src/main/scala/org/ergoplatform/mining/AutolykosPowScheme.scala index 5dd710da26..58a574c02f 100644 --- a/ergo-core/src/main/scala/org/ergoplatform/mining/AutolykosPowScheme.scala +++ b/ergo-core/src/main/scala/org/ergoplatform/mining/AutolykosPowScheme.scala @@ -262,7 +262,7 @@ class AutolykosPowScheme(val k: Int, val n: Int) extends ScorexLogging { val (parentId, height) = AutolykosPowScheme.derivedHeaderFields(parentOpt) val h = HeaderWithoutPow(version, parentId, adProofsRoot, stateRoot, transactionsRoot, timestamp, - nBits, height, extensionHash, votes) + nBits, height, extensionHash, votes, Array.emptyByteArray) val msg = msgByHeader(h) val b = getB(nBits) val x = randomSecret() diff --git a/ergo-core/src/main/scala/org/ergoplatform/mining/CandidateUtils.scala b/ergo-core/src/main/scala/org/ergoplatform/mining/CandidateUtils.scala index 0ad1d87624..aee8cc3fc7 100644 --- a/ergo-core/src/main/scala/org/ergoplatform/mining/CandidateUtils.scala +++ b/ergo-core/src/main/scala/org/ergoplatform/mining/CandidateUtils.scala @@ -29,7 +29,8 @@ object CandidateUtils { candidate.nBits, height, extensionRoot, - candidate.votes + candidate.votes, + Array.emptyByteArray ) } } diff --git a/ergo-core/src/main/scala/org/ergoplatform/mining/DefaultFakePowScheme.scala b/ergo-core/src/main/scala/org/ergoplatform/mining/DefaultFakePowScheme.scala index 732bf25805..b6a3bdeff7 100644 --- a/ergo-core/src/main/scala/org/ergoplatform/mining/DefaultFakePowScheme.scala +++ b/ergo-core/src/main/scala/org/ergoplatform/mining/DefaultFakePowScheme.scala @@ -33,7 +33,7 @@ class DefaultFakePowScheme(k: Int, n: Int) extends AutolykosPowScheme(k, n) { val d: BigInt = q / (height + 10) val s = AutolykosSolution(pk, w, n, d) Some(Header(version, parentId, adProofsRoot, stateRoot, transactionsRoot, timestamp, - nBits, height, extensionHash, s, votes)) + nBits, height, extensionHash, s, votes, Array.emptyByteArray)) } override def realDifficulty(header: Header): PrivateKey = header.requiredDifficulty diff --git a/ergo-core/src/main/scala/org/ergoplatform/modifiers/history/header/Header.scala b/ergo-core/src/main/scala/org/ergoplatform/modifiers/history/header/Header.scala index 092dcd219f..389d235066 100644 --- a/ergo-core/src/main/scala/org/ergoplatform/modifiers/history/header/Header.scala +++ b/ergo-core/src/main/scala/org/ergoplatform/modifiers/history/header/Header.scala @@ -53,8 +53,9 @@ case class Header(override val version: Header.Version, override val extensionRoot: Digest32, powSolution: AutolykosSolution, override val votes: Array[Byte], //3 bytes + override val unparsedBytes: Array[Byte], override val sizeOpt: Option[Int] = None) extends HeaderWithoutPow(version, parentId, ADProofsRoot, stateRoot, transactionsRoot, timestamp, - nBits, height, extensionRoot, votes) with PreHeader with BlockSection { + nBits, height, extensionRoot, votes, unparsedBytes) with PreHeader with BlockSection { override def serializedId: Array[Header.Version] = Algos.hash(bytes) @@ -180,7 +181,8 @@ object Header extends ApiCodecs { "size" -> h.size.asJson, "extensionId" -> Algos.encode(h.extensionId).asJson, "transactionsId" -> Algos.encode(h.transactionsId).asJson, - "adProofsId" -> Algos.encode(h.ADProofsId).asJson + "adProofsId" -> Algos.encode(h.ADProofsId).asJson, + "unparsedBytes" -> Algos.encode(h.unparsedBytes).asJson ).asJson } @@ -197,8 +199,10 @@ object Header extends ApiCodecs { version <- c.downField("version").as[Byte] votes <- c.downField("votes").as[String] solutions <- c.downField("powSolutions").as[AutolykosSolution] + unparsedBytes <- c.downField("unparsedBytes").as[Option[Array[Byte]]] } yield Header(version, parentId, adProofsRoot, stateRoot, - transactionsRoot, timestamp, nBits, height, extensionHash, solutions, Algos.decode(votes).get) + transactionsRoot, timestamp, nBits, height, extensionHash, solutions, Algos.decode(votes).get, + unparsedBytes.getOrElse(Array.emptyByteArray)) } } diff --git a/ergo-core/src/main/scala/org/ergoplatform/modifiers/history/header/HeaderSerializer.scala b/ergo-core/src/main/scala/org/ergoplatform/modifiers/history/header/HeaderSerializer.scala index b6123e1141..bbe8829a05 100644 --- a/ergo-core/src/main/scala/org/ergoplatform/modifiers/history/header/HeaderSerializer.scala +++ b/ergo-core/src/main/scala/org/ergoplatform/modifiers/history/header/HeaderSerializer.scala @@ -32,7 +32,8 @@ object HeaderSerializer extends ErgoSerializer[Header] { // 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 > Header.InitialVersion) { - w.putUByte(0) + w.putUByte(h.unparsedBytes.length) + w.putBytes(h.unparsedBytes) } } @@ -56,15 +57,19 @@ object HeaderSerializer extends ErgoSerializer[Header] { // 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. - if (version > Header.InitialVersion) { + val unparsedBytes = if (version > Header.InitialVersion) { val newFieldsSize = r.getUByte() - if (newFieldsSize > 0) { + if (newFieldsSize > 0) { // todo: check protocol version? r.getBytes(newFieldsSize) + } else { + Array.emptyByteArray } + } else { + Array.emptyByteArray } HeaderWithoutPow(version, parentId, ADProofsRoot, stateRoot, transactionsRoot, timestamp, - nBits, height, extensionHash, votes) + nBits, height, extensionHash, votes, unparsedBytes) } override def parse(r: Reader): Header = { diff --git a/ergo-core/src/main/scala/org/ergoplatform/modifiers/history/header/HeaderWithoutPow.scala b/ergo-core/src/main/scala/org/ergoplatform/modifiers/history/header/HeaderWithoutPow.scala index ffe10380a2..067468f2c6 100644 --- a/ergo-core/src/main/scala/org/ergoplatform/modifiers/history/header/HeaderWithoutPow.scala +++ b/ergo-core/src/main/scala/org/ergoplatform/modifiers/history/header/HeaderWithoutPow.scala @@ -17,19 +17,20 @@ class HeaderWithoutPow(val version: Header.Version, // 1 byte val nBits: Long, //actually it is unsigned int val height: Int, val extensionRoot: Digest32, - val votes: Array[Byte]) { //3 bytes + val votes: Array[Byte], //3 bytes + val unparsedBytes: Array[Byte]) { def toHeader(powSolution: AutolykosSolution, headerSize: Option[Int] = None): Header = Header(version, parentId, ADProofsRoot, stateRoot, transactionsRoot, timestamp, - nBits, height, extensionRoot, powSolution, votes, headerSize) + nBits, height, extensionRoot, powSolution, votes, unparsedBytes, headerSize) } object HeaderWithoutPow { def apply(version: Header.Version, parentId: ModifierId, ADProofsRoot: Digest32, stateRoot: ADDigest, transactionsRoot: Digest32, timestamp: Header.Timestamp, nBits: Long, height: Int, - extensionRoot: Digest32, votes: Array[Byte]): HeaderWithoutPow = { + extensionRoot: Digest32, votes: Array[Byte], unparsedBytes: Array[Byte]): HeaderWithoutPow = { new HeaderWithoutPow(version, parentId, ADProofsRoot, stateRoot, transactionsRoot, timestamp, - nBits, height, extensionRoot, votes) + nBits, height, extensionRoot, votes, unparsedBytes) } } diff --git a/ergo-core/src/main/scala/org/ergoplatform/modifiers/history/header/PreGenesisHeader.scala b/ergo-core/src/main/scala/org/ergoplatform/modifiers/history/header/PreGenesisHeader.scala index 7cebffbc5e..4924c63783 100644 --- a/ergo-core/src/main/scala/org/ergoplatform/modifiers/history/header/PreGenesisHeader.scala +++ b/ergo-core/src/main/scala/org/ergoplatform/modifiers/history/header/PreGenesisHeader.scala @@ -18,6 +18,7 @@ object PreGenesisHeader extends Header( extensionRoot = null, powSolution = null, votes = null, + unparsedBytes = Array.emptyByteArray, sizeOpt = None) { override def serializedId: Array[Byte] = idToBytes(Header.GenesisParentId) diff --git a/ergo-core/src/test/scala/org/ergoplatform/network/HeaderSerializationSpecification.scala b/ergo-core/src/test/scala/org/ergoplatform/network/HeaderSerializationSpecification.scala index fb7821b255..f5445269a2 100644 --- a/ergo-core/src/test/scala/org/ergoplatform/network/HeaderSerializationSpecification.scala +++ b/ergo-core/src/test/scala/org/ergoplatform/network/HeaderSerializationSpecification.scala @@ -43,7 +43,7 @@ class HeaderSerializationSpecification extends ErgoCorePropertyTest { val votes = Array[Byte](4, 3, 0) val h = Header(version, parentId, adProofsRoot, stateRoot, transactionsRoot, timestamp, nBits, - height, extensionRoot, powSolution, votes) + height, extensionRoot, powSolution, votes, Array.emptyByteArray) h.id shouldBe "8cf6dca6b9505243e36192fa107735024c0000cf4594b1daa2dc4e13ee86f26f" @@ -141,7 +141,7 @@ class HeaderSerializationSpecification extends ErgoCorePropertyTest { val votes = Array[Byte](0, 0, 0) val h = Header(version, parentId, adProofsRoot, stateRoot, transactionsRoot, timestamp, nBits, - height, extensionRoot, powSolution, votes) + height, extensionRoot, powSolution, votes, Array.emptyByteArray) h.id shouldBe "f46c89e44f13a92d8409341490f97f05c85785fa8d2d2164332cc066eda95c39" diff --git a/ergo-core/src/test/scala/org/ergoplatform/utils/generators/ErgoCoreGenerators.scala b/ergo-core/src/test/scala/org/ergoplatform/utils/generators/ErgoCoreGenerators.scala index 0cbb42425e..cadc6ae8b9 100644 --- a/ergo-core/src/test/scala/org/ergoplatform/utils/generators/ErgoCoreGenerators.scala +++ b/ergo-core/src/test/scala/org/ergoplatform/utils/generators/ErgoCoreGenerators.scala @@ -172,6 +172,7 @@ object ErgoCoreGenerators { extensionHash, powSolution, Array.fill(3)(0: Byte), + Array.emptyByteArray, None ) diff --git a/src/main/scala/org/ergoplatform/mining/CandidateGenerator.scala b/src/main/scala/org/ergoplatform/mining/CandidateGenerator.scala index a42b50e6db..e7eb131d0d 100644 --- a/src/main/scala/org/ergoplatform/mining/CandidateGenerator.scala +++ b/src/main/scala/org/ergoplatform/mining/CandidateGenerator.scala @@ -903,7 +903,8 @@ object CandidateGenerator extends ScorexLogging { candidate.nBits, height, extensionRoot, - candidate.votes + candidate.votes, + Array.emptyByteArray ) }