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 db796e4b75..048928d2e1 100644 --- a/ergo-core/src/main/scala/org/ergoplatform/mining/AutolykosPowScheme.scala +++ b/ergo-core/src/main/scala/org/ergoplatform/mining/AutolykosPowScheme.scala @@ -240,7 +240,7 @@ class AutolykosPowScheme(val k: Int, val n: Int) extends ScorexLogging { /** * Get target `b` from encoded difficulty `nBits` */ - private[mining] def getB(nBits: Long): BigInt = { + def getB(nBits: Long): BigInt = { q / DifficultySerializer.decodeCompactBits(nBits) } @@ -363,7 +363,7 @@ class AutolykosPowScheme(val k: Int, val n: Int) extends ScorexLogging { * Check nonces from `startNonce` to `endNonce` for message `m`, secrets `sk` and `x`, difficulty `b`. * Return AutolykosSolution if there is any valid nonce in this interval. */ - private[mining] def checkNonces(version: Header.Version, + def checkNonces(version: Header.Version, h: Array[Byte], m: Array[Byte], sk: BigInt, diff --git a/ergo-core/src/main/scala/org/ergoplatform/mining/AutolykosSolution.scala b/ergo-core/src/main/scala/org/ergoplatform/mining/AutolykosSolution.scala index cf745e685b..e75412828e 100644 --- a/ergo-core/src/main/scala/org/ergoplatform/mining/AutolykosSolution.scala +++ b/ergo-core/src/main/scala/org/ergoplatform/mining/AutolykosSolution.scala @@ -128,6 +128,10 @@ object AutolykosSolutionSerializer { serializer(blockVersion).serialize(solution, w) } + def toBytes(blockVersion: Version, solution: AutolykosSolution): Array[Byte] = { + serializer(blockVersion).toBytes(solution) + } + def parse(r: Reader, blockVersion: Version): AutolykosSolution = { serializer(blockVersion).parse(r) } 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..28a7ab1a51 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 @@ -56,7 +56,7 @@ case class Header(override val version: Header.Version, override val sizeOpt: Option[Int] = None) extends HeaderWithoutPow(version, parentId, ADProofsRoot, stateRoot, transactionsRoot, timestamp, nBits, height, extensionRoot, votes) with PreHeader with BlockSection { - override def serializedId: Array[Header.Version] = Algos.hash(bytes) + override def serializedId: Array[Byte] = Algos.hash(bytes) override type M = Header diff --git a/src/test/scala/org/ergoplatform/modifiers/history/HeadersSpec.scala b/src/test/scala/org/ergoplatform/modifiers/history/HeadersSpec.scala index e802139257..d824790887 100644 --- a/src/test/scala/org/ergoplatform/modifiers/history/HeadersSpec.scala +++ b/src/test/scala/org/ergoplatform/modifiers/history/HeadersSpec.scala @@ -1,7 +1,11 @@ package org.ergoplatform.modifiers.history -import com.google.common.primitives.Longs +import com.google.common.primitives.{Ints, Longs} +import org.ergoplatform.mining.{AutolykosPowScheme, AutolykosSolutionSerializer, randomSecret} +import org.ergoplatform.mining.difficulty.DifficultySerializer +import org.ergoplatform.modifiers.history.header.{Header, HeaderSerializer} import org.ergoplatform.utils.ErgoCorePropertyTest +import org.ergoplatform.utils.ErgoCoreTestConstants.powScheme import scorex.crypto.hash.Blake2b256 import scorex.util.ModifierId @@ -34,4 +38,30 @@ class HeadersSpec extends ErgoCorePropertyTest { } } + property("bytes can be added to the header") { + val pow = new AutolykosPowScheme(powScheme.k, powScheme.n) + + val difficulty = 10 + val ver = (Header.Interpreter50Version + 1).toByte + val nBits = DifficultySerializer.encodeCompactBits(difficulty) + val header = defaultHeaderGen.sample.get.copy(version = ver, nBits = nBits) + val bytesWithoutPow = HeaderSerializer.bytesWithoutPow(header) + bytesWithoutPow(bytesWithoutPow.length - 1) = 5 + val updByteWithoutPow: Array[Byte] = bytesWithoutPow ++ Array.fill(5)(5.toByte) + val msg = Blake2b256(updByteWithoutPow) + + val sk = randomSecret() + val x = randomSecret() + val b = pow.getB(header.nBits) + val hbs = Ints.toByteArray(header.height) + val N = pow.calcN(header) + val solution = pow.checkNonces(ver, hbs, msg, sk, x, b, N, 0, 1000).get + + require(pow.hitForVersion2ForMessage(msg, solution.n, hbs, N) < b) + + require(HeaderSerializer.parseBytesTry(updByteWithoutPow ++ AutolykosSolutionSerializer.toBytes(ver, solution)).isSuccess) + + // todo: but unparsed bytes are not stored in Header, so roundtrip is broken + } + }