Skip to content

Commit

Permalink
merging w. i675-2
Browse files Browse the repository at this point in the history
  • Loading branch information
kushti committed Oct 9, 2024
2 parents ae0a025 + e87ad02 commit 4b2b443
Show file tree
Hide file tree
Showing 17 changed files with 3,571 additions and 15 deletions.
14 changes: 14 additions & 0 deletions core/shared/src/main/scala/sigma/SigmaDsl.scala
Original file line number Diff line number Diff line change
Expand Up @@ -894,6 +894,20 @@ 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

/**
* 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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -507,6 +507,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, "encodeNbits", Array[Class[_]](classOf[BigInt])) { (obj, args) =>
obj.asInstanceOf[SigmaDslBuilder].encodeNbits(args(0).asInstanceOf[BigInt])
},
mkMethod(clazz, "decodeNbits", Array[Class[_]](classOf[Long])) { (obj, args) =>
obj.asInstanceOf[SigmaDslBuilder].decodeNbits(args(0).asInstanceOf[Long])
},
mkMethod(clazz, "some", Array[Class[_]](classOf[Object], classOf[RType[_]])) { (obj, args) =>
obj.asInstanceOf[SigmaDslBuilder].some(args(0).asInstanceOf[Any])(args(1).asInstanceOf[RType[Any]])
},
Expand Down
8 changes: 8 additions & 0 deletions data/shared/src/main/scala/sigma/SigmaDataReflection.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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 =>
Expand Down
21 changes: 19 additions & 2 deletions data/shared/src/main/scala/sigma/ast/methods.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ import org.ergoplatform.validation._
import sigma.{Coll, VersionContext, _}
import sigma.Evaluation.stypeToRType
import sigma._
import sigma.{VersionContext, _}
import sigma.ast.SCollection.{SBooleanArray, SBoxArray, SByteArray, SByteArray2, SHeaderArray}
import sigma.ast.SGlobalMethods.{decodeNBitsMethod, encodeNBitsMethod}
import sigma.ast.SMethod.{MethodCallIrBuilder, MethodCostFunc, javaMethodOf}
import sigma.ast.SType.TypeCode
import sigma.ast.SUnsignedBigIntMethods.ModInverseCostInfo
Expand All @@ -20,6 +22,7 @@ import sigma.pow.Autolykos2PowValidation
import sigma.reflection.RClass
import sigma.serialization.CoreByteWriter.ArgInfo
import sigma.serialization.{DataSerializer, SigmaByteWriter, SigmaSerializer}
import sigma.util.NBitsUtils
import sigma.utils.SparseArrayContainer

import scala.annotation.unused
Expand Down Expand Up @@ -1975,7 +1978,7 @@ case object SGlobalMethods extends MonoTypeMethods {
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,
this, "powHit", SFunc(Array(SGlobal, SInt, SByteArray, SByteArray, SByteArray, SInt), SBigInt), methodId = 10,
PowHitCostKind)
.withIRInfo(MethodCallIrBuilder)
.withInfo(MethodCall,
Expand Down Expand Up @@ -2034,6 +2037,18 @@ 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), 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), 7, EnDecodeNBitsCost)
.withIRInfo(MethodCallIrBuilder)
.withInfo(MethodCall, "Decode nbits-encoded big integer number", ArgInfo("nbits", "NBits-encoded argument"))

lazy val serializeMethod = SMethod(this, "serialize",
SFunc(Array(SGlobal, tT), SByteArray, Array(paramT)), 3, DynamicCost)
.withIRInfo(MethodCallIrBuilder)
Expand Down Expand Up @@ -2088,7 +2103,9 @@ case object SGlobalMethods extends MonoTypeMethods {
fromBigEndianBytesMethod,
someMethod,
noneMethod,
powHitMethod
powHitMethod,
encodeNBitsMethod,
decodeNBitsMethod
)
} else {
Seq(
Expand Down
9 changes: 9 additions & 0 deletions data/shared/src/main/scala/sigma/data/CSigmaDslBuilder.scala
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import sigma.serialization.{DataSerializer, GroupElementSerializer, SigmaSeriali
import sigma.serialization.SerializerException
import sigma.pow.Autolykos2PowValidation
import sigma.util.Extensions.BigIntegerOps
import sigma.util.NBitsUtils
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, UnsignedBigInt, VersionContext}
Expand Down Expand Up @@ -186,6 +187,14 @@ 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)
}

/**
* @return the identity of the Dlog group used in ErgoTree
*/
Expand Down
4 changes: 2 additions & 2 deletions data/shared/src/main/scala/sigma/eval/ErgoTreeEvaluator.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -295,7 +295,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)
Expand All @@ -307,16 +307,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)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ class MethodCallSerializerSpecification extends SerializationSpecification {
code
}

an[Exception] should be thrownBy (
an[SerializerException] should be thrownBy (
VersionContext.withVersions((VersionContext.V6SoftForkVersion - 1).toByte, 1) {
code
}
Expand Down Expand Up @@ -121,4 +121,47 @@ class MethodCallSerializerSpecification extends SerializationSpecification {
})
}

property("MethodCall deserialization round trip for Global.encodeNBits") {
def code = {
val bi = BigIntConstant(5)
val expr = MethodCall(Global,
SGlobalMethods.encodeNBitsMethod,
Vector(bi),
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
})
}

property("MethodCall deserialization round trip for Global.decodeNBits") {
def code = {
val l = LongConstant(5)
val expr = MethodCall(Global,
SGlobalMethods.decodeNBitsMethod,
Vector(l),
Map()
)
roundTripTest(expr)
}

VersionContext.withVersions(VersionContext.V6SoftForkVersion, 1) {
code
}

an[ValidationException] should be thrownBy (
VersionContext.withVersions((VersionContext.V6SoftForkVersion - 1).toByte, 1) {
code
}
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,18 @@ import org.scalatest.matchers.should.Matchers
import scorex.util.encode.Base16
import sigma.Extensions.ArrayOps
import sigma.ast.{ByteArrayConstant, ErgoTree, Global, IntConstant, JitCost, MethodCall, SGlobalMethods}
import sigma.ast.{BigIntConstant, ErgoTree, Global, JitCost, MethodCall, SBigIntMethods, SGlobalMethods}
import sigma.crypto.SecP256K1Group
import sigma.data.{CBigInt, TrivialProp, CSigmaDslBuilder => SigmaDsl}
import sigma.data.{CBigInt, TrivialProp}
import sigma.data.{CSigmaDslBuilder => SigmaDsl}
import sigma.util.Extensions.SigmaBooleanOps
import sigma.util.NBitsUtils

import java.math.BigInteger
import sigma.{Box, ContractsTestkit, SigmaProp, VersionContext}
import sigmastate.interpreter.CErgoTreeEvaluator.DefaultProfiler
import sigma.{ContractsTestkit, SigmaProp}
import sigmastate.interpreter.{CErgoTreeEvaluator, CostAccumulator}
import sigmastate.interpreter.CErgoTreeEvaluator.DefaultProfiler
import sigma.{Box, VersionContext}

import scala.language.implicitConversions

Expand Down Expand Up @@ -76,7 +81,7 @@ class BasicOpsTests extends AnyFunSuite with ContractsTestkit with Matchers {
val context = new CContext(
noInputs.toColl, noHeaders, dummyPreHeader,
Array[Box]().toColl, Array[Box]().toColl, 0, null, 0, null,
dummyPubkey.toColl, Colls.emptyColl, VersionContext.V6SoftForkVersion, VersionContext.V6SoftForkVersion)
dummyPubkey.toColl, Colls.emptyColl, null, VersionContext.V6SoftForkVersion, VersionContext.V6SoftForkVersion)

val evaluator = new CErgoTreeEvaluator(
context = context,
Expand Down Expand Up @@ -113,7 +118,7 @@ class BasicOpsTests extends AnyFunSuite with ContractsTestkit with Matchers {
val context = new CContext(
noInputs.toColl, noHeaders, dummyPreHeader,
Array[Box]().toColl, Array[Box]().toColl, 0, null, 0, null,
dummyPubkey.toColl, Colls.emptyColl, VersionContext.V6SoftForkVersion, VersionContext.V6SoftForkVersion)
dummyPubkey.toColl, Colls.emptyColl, null, VersionContext.V6SoftForkVersion, VersionContext.V6SoftForkVersion)

val evaluator = new CErgoTreeEvaluator(
context = context,
Expand All @@ -130,4 +135,27 @@ 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.encodeNbits(CBigInt(BigInteger.valueOf(0))) 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(Global, SGlobalMethods.encodeNBitsMethod, IndexedSeq(BigIntConstant(BigInteger.valueOf(0))), Map.empty)
.evalTo[Long](Map.empty)(evaluator)

res should be (NBitsUtils.encodeCompactBits(0))

}

}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import sigma.ast.syntax.{SValue, ValueOps}
import sigma.ast._
import sigma.compiler.ir.core.MutableLazy
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}
Expand Down Expand Up @@ -1219,6 +1220,12 @@ 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)
case SGlobalMethods.powHitMethod.name if VersionContext.current.isV6SoftForkActivated =>
val k = asRep[Int](argsV(0))
val msg = asRep[Coll[Byte]](argsV(1))
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package sigma.compiler.ir

import sigma.Coll
import sigma.{BigInt, SigmaDslBuilder}
import sigma.ast.SType
import sigma.compiler.ir.primitives.Thunks
import sigma.data.RType
Expand Down Expand Up @@ -538,6 +539,12 @@ object GraphIRReflection {
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]])
},
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]])
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,8 @@ import scalan._
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 powHit(k: Ref[Int], msg: Ref[Coll[Byte]], nonce: Ref[Coll[Byte]], h: Ref[Coll[Byte]], N: Ref[Int]): Ref[BigInt];
def encodeNbits(bi: Ref[BigInt]): Ref[Long]
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]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2293,6 +2293,19 @@ object SigmaDslBuilder extends EntityObject("SigmaDslBuilder") {
true, false, element[WOption[T]], Map(tT -> Evaluation.rtypeToSType(cT.sourceType))))
}

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](l),
true, false, element[BigInt]))
}

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,
Expand Down Expand Up @@ -2489,6 +2502,20 @@ object SigmaDslBuilder extends EntityObject("SigmaDslBuilder") {
true, true, cT, Map(tT -> Evaluation.rtypeToSType(cT.sourceType))))
}

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]),
Array[AnyRef](l),
true, true, element[BigInt]))
}

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]]),
Expand Down Expand Up @@ -2522,7 +2549,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", "serialize", "deserializeTo", "fromBigEndianBytes", "powHit"
"decodePoint", "avlTree", "xor", "serialize", "deserializeTo", "fromBigEndianBytes", "powHit", "encodeNBits", "decodeNBits"
))
}
}
Expand Down
Loading

0 comments on commit 4b2b443

Please sign in to comment.