Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Boolean.toByte with versioning #940

Open
wants to merge 8 commits into
base: v6.0.0
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions core/shared/src/main/scala/sigma/VersionContext.scala
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package sigma

import VersionContext.{EvolutionVersion, JitActivationVersion}
import VersionContext.{JitActivationVersion, V6SoftForkVersion}

import scala.util.DynamicVariable

Expand All @@ -24,7 +24,7 @@ case class VersionContext(activatedVersion: Byte, ergoTreeVersion: Byte) {

/** @return true, if the activated script version of Ergo protocol on the network is
* including Evolution update. */
def isEvolutionActivated: Boolean = activatedVersion >= EvolutionVersion
def isV6SoftForkActivated: Boolean = activatedVersion >= V6SoftForkVersion
}

object VersionContext {
Expand All @@ -48,7 +48,7 @@ object VersionContext {
/**
* The version of ErgoTree corresponding to "evolution" (6.0) soft-fork
*/
val EvolutionVersion: Byte = 3
val V6SoftForkVersion: Byte = 3

private val _defaultContext = VersionContext(
activatedVersion = 1 /* v4.x */,
Expand Down
20 changes: 13 additions & 7 deletions data/shared/src/main/scala/sigma/ast/methods.scala
Original file line number Diff line number Diff line change
Expand Up @@ -272,13 +272,19 @@ case object SBooleanMethods extends MonoTypeMethods {
override def ownerType: SMonoType = SBoolean

val ToByte = "toByte"
protected override def getMethods() = super.getMethods()
/* TODO soft-fork: https://github.com/ScorexFoundation/sigmastate-interpreter/issues/479
++ Seq(
SMethod(this, ToByte, SFunc(this, SByte), 1)
.withInfo(PropertyCall, "Convert true to 1 and false to 0"),
)
*/

lazy val ToByteMethod: SMethod = SMethod(
this, ToByte, SFunc(this.ownerType, SByte), 1, FixedCost(JitCost(1)))
.withInfo(PropertyCall, "Convert true to 1 and false to 0")

protected override def getMethods(): Seq[SMethod] = {
if (VersionContext.current.isV6SoftForkActivated) {
super.getMethods() ++ Seq(ToByteMethod)
} else {
super.getMethods()
}
}

}

/** Methods of ErgoTree type `Byte`. */
Expand Down
6 changes: 6 additions & 0 deletions sc/shared/src/main/scala/scalan/primitives/LogicalOps.scala
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@ trait LogicalOps extends Base { self: Scalan =>
override def applySeq(x: Boolean): Int = if (x) 1 else 0
}

/** Boolean to Byte conversion unary operation. */
val BooleanToByte = new UnOp[Boolean, Byte]("ToByte") {
override def applySeq(x: Boolean): Byte = if (x) 1.toByte else 0.toByte
}

/** Extension methods over `Ref[Boolean]`. */
implicit class RepBooleanOps(value: Ref[Boolean]) {
def &&(y: Ref[Boolean]): Ref[Boolean] = And(value, y)
Expand All @@ -40,6 +45,7 @@ trait LogicalOps extends Base { self: Scalan =>

def unary_!() : Ref[Boolean] = Not(value)
def toInt: Ref[Int] = BooleanToInt(value)
def toByte: Ref[Byte] = BooleanToByte(value)
}


Expand Down
5 changes: 5 additions & 0 deletions sc/shared/src/main/scala/sigmastate/eval/GraphBuilding.scala
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import sigma.ast.Value.Typed
import sigma.ast._
import sigma.ast.syntax.{SValue, ValueOps}
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 @@ -496,6 +497,10 @@ trait GraphBuilding extends SigmaLibrary { IR: IRContext =>
else
error(s"The type of $obj is expected to be Collection to select 'size' property", obj.sourceContext.toOption)

case Select(obj, SBooleanMethods.ToByte, _) if obj.tpe == SBoolean && VersionContext.current.isV6SoftForkActivated =>
val bool = eval(obj.asBoolValue)
bool.toByte

// Rule: proof.isProven --> IsValid(proof)
case Select(p, SSigmaPropMethods.IsProven, _) if p.tpe == SSigmaProp =>
eval(SigmaPropIsProven(p.asSigmaProp))
Expand Down
10 changes: 8 additions & 2 deletions sc/shared/src/test/scala/sigmastate/ErgoTreeSpecification.scala
Original file line number Diff line number Diff line change
Expand Up @@ -318,7 +318,6 @@ class ErgoTreeSpecification extends SigmaDslTesting with ContractsTestkit {
// The following table should be made dependent on HF activation
val methods = Table(
("typeId", "methods", "CanHaveMethods"),
(SBoolean.typeId, Seq.empty[MInfo], true),
(SByte.typeId, Seq.empty[MInfo], false),
(SShort.typeId, Seq.empty[MInfo], false),
(SInt.typeId, Seq.empty[MInfo], false),
Expand All @@ -332,7 +331,14 @@ class ErgoTreeSpecification extends SigmaDslTesting with ContractsTestkit {
), true)
},


{
import SBoolean._
if (VersionContext.current.isV6SoftForkActivated) {
(SBoolean.typeId, Seq(MInfo(1, SBooleanMethods.ToByteMethod)), true)
} else {
(SBoolean.typeId, Seq.empty[MInfo], true)
}
},
{ // SBigInt inherit methods from SNumericType.methods
// however they are not resolvable via SBigInt.typeId
import SNumericTypeMethods._
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import org.scalatest.BeforeAndAfterAll
import scorex.util.encode.Base58
import sigma.crypto.CryptoConstants
import sigma.data.{AvlTreeData, CAND, ProveDlog, SigmaBoolean, TrivialProp}
import sigma.VersionContext.V6SoftForkVersion
import sigma.util.Extensions.IntOps
import sigmastate.helpers.{CompilerTestingCommons, ErgoLikeContextTesting, ErgoLikeTestInterpreter, ErgoLikeTestProvingInterpreter}
import sigmastate.helpers.TestingHelpers._
Expand Down Expand Up @@ -204,6 +205,21 @@ class TestingInterpreterSpecification extends CompilerTestingCommons
|}""".stripMargin)
}

property("Evaluate boolean casting ops") {
val source =
"""
|{
| val bool: Boolean = true
| bool.toByte == 1.toByte && false.toByte == 0.toByte
|}
|""".stripMargin
if (activatedVersionInTests < V6SoftForkVersion) {
an [sigmastate.exceptions.MethodNotFound] should be thrownBy testEval(source)
} else {
testEval(source)
}
}

property("Evaluate numeric casting ops") {
def testWithCasting(castSuffix: String): Unit = {
testEval(s"OUTPUTS.size.toByte.$castSuffix == 0.$castSuffix")
Expand Down
Loading