Skip to content

Commit

Permalink
Merge branch 'i969' of github.com:ScorexFoundation/sigmastate-interpr…
Browse files Browse the repository at this point in the history
…eter into i958-2
  • Loading branch information
kushti committed Jun 5, 2024
2 parents d6e1bec + 0d6b2e0 commit c50f00e
Show file tree
Hide file tree
Showing 25 changed files with 452 additions and 490 deletions.
9 changes: 7 additions & 2 deletions core/shared/src/main/scala/sigma/SigmaDsl.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
)
)
Expand Down
84 changes: 0 additions & 84 deletions core/shared/src/main/scala/sigma/util/NBitsUtils.scala

This file was deleted.

159 changes: 159 additions & 0 deletions data/shared/src/main/scala/org/ergoplatform/ErgoHeader.scala
Original file line number Diff line number Diff line change
@@ -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)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*/
Expand All @@ -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 {

Expand Down
30 changes: 5 additions & 25 deletions data/shared/src/main/scala/sigma/ast/methods.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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, "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)
}
}
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. */
Expand Down
Loading

0 comments on commit c50f00e

Please sign in to comment.