Skip to content

Commit

Permalink
merging w. i969
Browse files Browse the repository at this point in the history
  • Loading branch information
kushti committed Jul 26, 2024
2 parents 40d5e54 + 1271a79 commit b677b18
Show file tree
Hide file tree
Showing 9 changed files with 135 additions and 41 deletions.
2 changes: 1 addition & 1 deletion core/shared/src/main/scala/sigma/SigmaDsl.scala
Original file line number Diff line number Diff line change
Expand Up @@ -467,7 +467,7 @@ trait Header {
def unparsedBytes: Coll[Byte]

/**
* @return bytes without proof of work, needed for working to get the proof on
* @return header bytes without proof of work, a PoW is generated over them
*/
def serializeWithoutPoW: Coll[Byte]

Expand Down
30 changes: 17 additions & 13 deletions core/shared/src/main/scala/sigma/ast/SType.scala
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import sigma.data.OverloadHack.Overloaded1
import sigma.data.{CBigInt, Nullable, SigmaConstants}
import sigma.reflection.{RClass, RMethod, ReflectionData}
import sigma.util.Extensions.{IntOps, LongOps, ShortOps}
import sigma.{AvlTree, BigInt, Box, Coll, Context, Evaluation, GroupElement, Header, PreHeader, SigmaDslBuilder, SigmaProp}
import sigma.{AvlTree, BigInt, Box, Coll, Context, Evaluation, GroupElement, Header, PreHeader, SigmaDslBuilder, SigmaProp, VersionContext}

import java.math.BigInteger

Expand Down Expand Up @@ -375,6 +375,7 @@ case object SByte extends SPrimType with SEmbeddable with SNumericType with SMon
case s: Short => s.toByteExact
case i: Int => i.toByteExact
case l: Long => l.toByteExact
case bi: BigInt if VersionContext.current.isV6SoftForkActivated => bi.toByte // toByteExact from int is called under the hood
case _ => sys.error(s"Cannot downcast value $v to the type $this")
}
}
Expand All @@ -396,6 +397,7 @@ case object SShort extends SPrimType with SEmbeddable with SNumericType with SMo
case s: Short => s
case i: Int => i.toShortExact
case l: Long => l.toShortExact
case bi: BigInt if VersionContext.current.isV6SoftForkActivated => bi.toShort // toShortExact from int is called under the hood
case _ => sys.error(s"Cannot downcast value $v to the type $this")
}
}
Expand All @@ -419,6 +421,7 @@ case object SInt extends SPrimType with SEmbeddable with SNumericType with SMono
case s: Short => s.toInt
case i: Int => i
case l: Long => l.toIntExact
case bi: BigInt if VersionContext.current.isV6SoftForkActivated => bi.toInt
case _ => sys.error(s"Cannot downcast value $v to the type $this")
}
}
Expand All @@ -444,6 +447,7 @@ case object SLong extends SPrimType with SEmbeddable with SNumericType with SMon
case s: Short => s.toLong
case i: Int => i.toLong
case l: Long => l
case bi: BigInt if VersionContext.current.isV6SoftForkActivated => bi.toLong
case _ => sys.error(s"Cannot downcast value $v to the type $this")
}
}
Expand All @@ -465,24 +469,24 @@ case object SBigInt extends SPrimType with SEmbeddable with SNumericType with SM
override def numericTypeIndex: Int = 4

override def upcast(v: AnyVal): BigInt = {
val bi = v match {
case x: Byte => BigInteger.valueOf(x.toLong)
case x: Short => BigInteger.valueOf(x.toLong)
case x: Int => BigInteger.valueOf(x.toLong)
case x: Long => BigInteger.valueOf(x)
v match {
case x: Byte => CBigInt(BigInteger.valueOf(x.toLong))
case x: Short => CBigInt(BigInteger.valueOf(x.toLong))
case x: Int => CBigInt(BigInteger.valueOf(x.toLong))
case x: Long => CBigInt(BigInteger.valueOf(x))
case x: BigInt if VersionContext.current.isV6SoftForkActivated => x
case _ => sys.error(s"Cannot upcast value $v to the type $this")
}
CBigInt(bi)
}
override def downcast(v: AnyVal): BigInt = {
val bi = v match {
case x: Byte => BigInteger.valueOf(x.toLong)
case x: Short => BigInteger.valueOf(x.toLong)
case x: Int => BigInteger.valueOf(x.toLong)
case x: Long => BigInteger.valueOf(x)
v match {
case x: Byte => CBigInt(BigInteger.valueOf(x.toLong))
case x: Short => CBigInt(BigInteger.valueOf(x.toLong))
case x: Int => CBigInt(BigInteger.valueOf(x.toLong))
case x: Long => CBigInt(BigInteger.valueOf(x))
case x: BigInt if VersionContext.current.isV6SoftForkActivated => x
case _ => sys.error(s"Cannot downcast value $v to the type $this")
}
CBigInt(bi)
}
}

Expand Down
12 changes: 6 additions & 6 deletions data/shared/src/main/scala/org/ergoplatform/ErgoHeader.scala
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,10 @@ import sigma.serialization.{GroupElementSerializer, SigmaByteReader, SigmaByteWr
* @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) {
class AutolykosSolution(val pk: EcPointType,
val w: EcPointType,
val n: Array[Byte],
val d: BigInt) {

val encodedPk: Array[Byte] = GroupElementSerializer.toBytes(pk)

Expand Down Expand Up @@ -52,7 +52,7 @@ object AutolykosSolution {
val nonce = r.getBytes(8)
val dBytesLength = r.getUByte()
val d = BigInt(BigIntegers.fromUnsignedByteArray(r.getBytes(dBytesLength)))
AutolykosSolution(pk, w, nonce, d)
new AutolykosSolution(pk, w, nonce, d)
}
}

Expand All @@ -66,7 +66,7 @@ object AutolykosSolution {
override def parse(r: SigmaByteReader): AutolykosSolution = {
val pk = GroupElementSerializer.parse(r)
val nonce = r.getBytes(8)
AutolykosSolution(pk, wForV2, nonce, dForV2)
new AutolykosSolution(pk, wForV2, nonce, dForV2)
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion data/shared/src/main/scala/sigma/data/CHeader.scala
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ object CHeader {
votes: Coll[Byte],
unparsedBytes: Coll[Byte]): CHeader = {

val solution = AutolykosSolution(
val solution = new AutolykosSolution(
minerPk.asInstanceOf[CGroupElement].wrappedValue,
powOnetimePk.asInstanceOf[CGroupElement].wrappedValue,
powNonce.toArray,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ trait SerializationSpecification extends AnyPropSpec
}
withVersion match {
case Some(ver) =>
VersionContext.withVersions(ver, 1) {
VersionContext.withVersions(ver, 0) {
test()
}
case None =>
Expand Down
77 changes: 60 additions & 17 deletions sc/shared/src/test/scala/sigma/LanguageSpecificationV6.scala
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package sigma

import sigma.ast.{Apply, Downcast, FixedCost, FixedCostItem, FuncValue, GetVar, Global, JitCost, MethodCall, NamedDesc, OptionGet, SBigInt, SByte, SGlobalMethods, SInt, SLong, SShort, STypeVar, ValUse}
import sigma.data.{CBigInt, ExactNumeric, RType}
import sigma.eval.{SigmaDsl, TracedCost}
import sigma.ast.{Apply, Downcast, FixedCost, FixedCostItem, FuncValue, GetVar, JitCost, OptionGet, SBigInt, SByte, SInt, SLong, SShort, ValUse}
import sigma.data.{CBigInt, ExactNumeric}
import sigma.eval.SigmaDsl
import sigma.util.Extensions.{BooleanOps, ByteOps, IntOps, LongOps}
import sigmastate.exceptions.MethodNotFound

Expand Down Expand Up @@ -172,21 +172,26 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite =>
}

property("BigInt methods equivalence (new features)") {
// TODO v6.0: the behavior of `upcast` for BigInt is different from all other Numeric types (see https://github.com/ScorexFoundation/sigmastate-interpreter/issues/877)
// The `Upcast(bigInt, SBigInt)` node is never produced by ErgoScript compiler, but is still valid ErgoTree.
// It makes sense to fix this inconsistency as part of upcoming forks
assertExceptionThrown(
SBigInt.upcast(CBigInt(new BigInteger("0", 16)).asInstanceOf[AnyVal]),
_.getMessage.contains("Cannot upcast value")
)
if (activatedVersionInTests < VersionContext.V6SoftForkVersion) {
// The `Upcast(bigInt, SBigInt)` node is never produced by ErgoScript compiler, but is still valid ErgoTree.
// Fixed in 6.0
assertExceptionThrown(
SBigInt.upcast(CBigInt(new BigInteger("0", 16)).asInstanceOf[AnyVal]),
_.getMessage.contains("Cannot upcast value")
)

// TODO v6.0: the behavior of `downcast` for BigInt is different from all other Numeric types (see https://github.com/ScorexFoundation/sigmastate-interpreter/issues/877)
// The `Downcast(bigInt, SBigInt)` node is never produced by ErgoScript compiler, but is still valid ErgoTree.
// It makes sense to fix this inconsistency as part of HF
assertExceptionThrown(
SBigInt.downcast(CBigInt(new BigInteger("0", 16)).asInstanceOf[AnyVal]),
_.getMessage.contains("Cannot downcast value")
)
// The `Downcast(bigInt, SBigInt)` node is never produced by ErgoScript compiler, but is still valid ErgoTree.
// Fixed in 6.0
assertExceptionThrown(
SBigInt.downcast(CBigInt(new BigInteger("0", 16)).asInstanceOf[AnyVal]),
_.getMessage.contains("Cannot downcast value")
)
} else {
forAll { x: BigInteger =>
SBigInt.upcast(CBigInt(x).asInstanceOf[AnyVal]) shouldBe CBigInt(x)
SBigInt.downcast(CBigInt(x).asInstanceOf[AnyVal]) shouldBe CBigInt(x)
}
}

if (activatedVersionInTests < VersionContext.V6SoftForkVersion) {
// NOTE, for such versions the new features are not supported
Expand Down Expand Up @@ -225,6 +230,44 @@ class LanguageSpecificationV6 extends LanguageSpecificationBase { suite =>
forAll { x: (BigInt, BigInt) =>
Seq(compareTo, bitOr, bitAnd).foreach(_.checkEquality(x))
}

forAll { x: Long =>
assertExceptionThrown(
SLong.downcast(CBigInt(new BigInteger(x.toString)).asInstanceOf[AnyVal]),
_.getMessage.contains("Cannot downcast value")
)
}
forAll { x: Int =>
assertExceptionThrown(
SInt.downcast(CBigInt(new BigInteger(x.toString)).asInstanceOf[AnyVal]),
_.getMessage.contains("Cannot downcast value")
)
}
forAll { x: Byte =>
assertExceptionThrown(
SByte.downcast(CBigInt(new BigInteger(x.toString)).asInstanceOf[AnyVal]),
_.getMessage.contains("Cannot downcast value")
)
}
forAll { x: Short =>
assertExceptionThrown(
SShort.downcast(CBigInt(new BigInteger(x.toString)).asInstanceOf[AnyVal]),
_.getMessage.contains("Cannot downcast value")
)
}
} else {
forAll { x: Long =>
SLong.downcast(CBigInt(new BigInteger(x.toString)).asInstanceOf[AnyVal]) shouldBe x
}
forAll { x: Int =>
SInt.downcast(CBigInt(new BigInteger(x.toString)).asInstanceOf[AnyVal]) shouldBe x
}
forAll { x: Byte =>
SByte.downcast(CBigInt(new BigInteger(x.toString)).asInstanceOf[AnyVal]) shouldBe x
}
forAll { x: Short =>
SShort.downcast(CBigInt(new BigInteger(x.toString)).asInstanceOf[AnyVal]) shouldBe x
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ import org.scalatest.BeforeAndAfterAll
import scorex.util.encode.Base58
import sigma.Colls
import sigma.VersionContext.V6SoftForkVersion
import sigma.VersionContext
import sigma.crypto.CryptoConstants
import sigma.data.{CAND, CAvlTree, ProveDlog, SigmaBoolean, TrivialProp}
import sigma.interpreter.ContextExtension
import sigma.util.Extensions.IntOps
Expand Down Expand Up @@ -272,6 +274,46 @@ class TestingInterpreterSpecification extends CompilerTestingCommons
testWithCasting("toBigInt")
}

property("BigInt downcasting to byte") {
def test() = testEval("{ sigmaProp(0L.toBigInt.toByte <= CONTEXT.preHeader.version) }")
if(VersionContext.current.isV6SoftForkActivated) {
test()
} else {
an[Exception] shouldBe thrownBy(test())
}
}

property("BigInt downcasting to short") {
def test() = testEval("{ sigmaProp(0L.toBigInt.toShort <= CONTEXT.preHeader.version.toShort) }")
if(VersionContext.current.isV6SoftForkActivated) {
test()
} else {
an[Exception] shouldBe thrownBy(test())
}
}

property("BigInt downcasting to int") {
def test() = testEval("{ sigmaProp(1L.toBigInt.toInt < CONTEXT.preHeader.timestamp.toInt) }")
if(VersionContext.current.isV6SoftForkActivated) {
test()
} else {
an[Exception] shouldBe thrownBy(test())
}
}

property("BigInt downcasting to long") {
def test() = testEval("{ sigmaProp(1L.toBigInt.toLong < CONTEXT.preHeader.timestamp) }")
if(VersionContext.current.isV6SoftForkActivated) {
test()
} else {
an[Exception] shouldBe thrownBy(test())
}
}

property("upcasting to bigint") {
testEval("{ sigmaProp(1L.toBigInt < bigInt(\"2\")) }")
}

property("Evaluate arithmetic ops") {
def testWithCasting(castSuffix: String): Unit = {
testEval(s"1.$castSuffix + 2.$castSuffix == 3.$castSuffix")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,11 @@ trait JsonCodecs {
).asJson
})

/**
* JSON decoder for Header instance. Field "unparsedBytes" is optional for now, to preserve compatibility
* with clients using older JSON decoders (before node 5.0.23). Better to add an (empty) field anyway if possible.
* This field could become mandatory in future.
*/
implicit val headerDecoder: Decoder[Header] = Decoder.instance({ cursor =>
for {
version <- cursor.downField("version").as[Byte]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ class DataJsonEncoderSpecification extends SerializationSpecification {

withVersion match {
case Some(ver) =>
VersionContext.withVersions(ver, 1) {
VersionContext.withVersions(ver, 0) {
test()
}
case None =>
Expand Down Expand Up @@ -233,7 +233,7 @@ class DataJsonEncoderSpecification extends SerializationSpecification {
}

if (tpe == SHeader) {
VersionContext.withVersions(VersionContext.V6SoftForkVersion, 1) {
VersionContext.withVersions(VersionContext.V6SoftForkVersion, 0) {
test()
}
} else {
Expand Down

0 comments on commit b677b18

Please sign in to comment.