Skip to content

Commit

Permalink
Merge pull request #884 from ScorexFoundation/v5.0.9-RC
Browse files Browse the repository at this point in the history
Release Candidate v5.0.9
  • Loading branch information
aslesarenko authored Jun 21, 2023
2 parents 50ce9da + c728da6 commit 1abafe9
Show file tree
Hide file tree
Showing 29 changed files with 981 additions and 28 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -49,4 +49,5 @@ spam-tests/
.metals/
.vscode/
project/metals.sbt
/project/project/
/project/project/
.bsp/
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ be verified before the spending transaction is added to the blockchain.
To allow valid coin spending a
[verifier](sigmastate/src/main/scala/sigmastate/interpreter/Interpreter.scala)
is running the ErgoTree interpreter with the following three inputs:
- a quarding proposition given by an ErgoTree
- a guarding proposition given by an ErgoTree
- a blockchain _context_ of the transaction being verified
- a _proof_ (aka transaction signature) generated by a _prover_

Expand Down
29 changes: 24 additions & 5 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ organization := "org.scorexfoundation"

name := "sigma-state"

lazy val scala213 = "2.13.8"
lazy val scala213 = "2.13.9"
lazy val scala212 = "2.12.15"
lazy val scala211 = "2.11.12"

Expand Down Expand Up @@ -257,9 +257,28 @@ lazy val interpreterJS = interpreter.js
)
)

lazy val parsers = crossProject(JVMPlatform, JSPlatform)
.in(file("parsers"))
.dependsOn(interpreter % allConfigDependency)
.settings(libraryDefSettings)
.settings(libraryDependencies ++=
Seq(scorexUtil, fastparse) ++ circeDeps(scalaVersion.value)
)
.jvmSettings(
crossScalaSettings
)
.jsSettings(
crossScalaSettingsJS,
libraryDependencies ++= Seq(
"org.scala-js" %%% "scala-js-macrotask-executor" % "1.0.0"
),
useYarn := true
)
lazy val parsersJS = parsers.js
.enablePlugins(ScalaJSBundlerPlugin)

lazy val sc = (project in file("sc"))
.dependsOn(graphir % allConfigDependency, interpreter.jvm % allConfigDependency)
.dependsOn(graphir % allConfigDependency, interpreter.jvm % allConfigDependency, parsers.jvm % allConfigDependency)
.settings(libraryDefSettings)
.settings(libraryDependencies ++=
Seq(scorexUtil, fastparse) ++ circeDeps(scalaVersion.value)
Expand All @@ -268,7 +287,7 @@ lazy val sc = (project in file("sc"))

lazy val sdk = crossProject(JVMPlatform, JSPlatform)
.in(file("sdk"))
.dependsOn(corelib % allConfigDependency, interpreter % allConfigDependency)
.dependsOn(corelib % allConfigDependency, interpreter % allConfigDependency, parsers % allConfigDependency)
.settings(commonSettings ++ testSettings2,
commonDependenies2,
testingDependencies2,
Expand Down Expand Up @@ -298,13 +317,13 @@ lazy val sdkJS = sdk.js
)

lazy val sigma = (project in file("."))
.aggregate(common.jvm, corelib.jvm, graphir, interpreter.jvm, sc, sdk.jvm)
.aggregate(common.jvm, corelib.jvm, graphir, interpreter.jvm, parsers.jvm, sc, sdk.jvm)
.settings(libraryDefSettings, rootSettings)
.settings(publish / aggregate := false)
.settings(publishLocal / aggregate := false)

lazy val aggregateCompile = ScopeFilter(
inProjects(common.jvm, corelib.jvm, graphir, interpreter.jvm, sc, sdk.jvm),
inProjects(common.jvm, corelib.jvm, graphir, interpreter.jvm, parsers.jvm, sc, sdk.jvm),
inConfigurations(Compile))

lazy val rootSettings = Seq(
Expand Down
4 changes: 4 additions & 0 deletions docs/LangSpec.md
Original file line number Diff line number Diff line change
Expand Up @@ -643,6 +643,10 @@ class Option[A] {
/** Returns true if the option is an instance of Some(value), false otherwise.
*/
def isDefined: Boolean;

/** Returns true if the option is None, false otherwise.
*/
def isEmpty: Boolean;

/** Returns the option's value if the option is nonempty, otherwise
* return the result of evaluating `default`.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -680,6 +680,12 @@ trait ObjectGenerators extends TypeGenerators
ErgoTree.withoutSegregation))
} yield treeBuilder(prop)

lazy val ergoTreeWithSegregationGen: Gen[ErgoTree] = for {
sigmaBoolean <- Gen.delay(sigmaBooleanGen)
propWithConstants <- Gen.delay(logicalExprTreeNodeGen(Seq(AND.apply, OR.apply, XorOf.apply)).map(_.toSigmaProp))
prop <- Gen.oneOf(propWithConstants, sigmaBoolean.toSigmaProp)
} yield ErgoTree.withSegregation(prop)

def headerGen(stateRoot: AvlTree, parentId: Coll[Byte]): Gen[Header] = for {
id <- modifierIdBytesGen
version <- arbByte.arbitrary
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,20 @@ class SigmaParserTest extends AnyPropSpec with ScalaCheckPropertyChecks with Mat
}
}

def parseWithException(x: String): SValue = {
SigmaParser(x) match {
case Parsed.Success(v, _) => v
case f: Parsed.Failure =>
throw new ParserException(s"Syntax error: $f", Some(SourceContext.fromParserFailure(f)))
}
}

def parseType(x: String): SType = {
SigmaParser.parseType(x)
}

def fail(x: String, expectedLine: Int, expectedCol: Int): Unit = {
val compiler = new SigmaCompiler(ErgoAddressEncoder.TestnetNetworkPrefix)
val exception = the[ParserException] thrownBy compiler.parse(x)
val exception = the[ParserException] thrownBy parseWithException(x)
withClue(s"Exception: $exception, is missing source context:") { exception.source shouldBe defined }
val sourceContext = exception.source.get
sourceContext.line shouldBe expectedLine
Expand Down Expand Up @@ -539,11 +546,13 @@ class SigmaParserTest extends AnyPropSpec with ScalaCheckPropertyChecks with Mat
parse("X[Byte]") shouldBe ApplyTypes(Ident("X"), Seq(SByte))
parse("X[Int]") shouldBe ApplyTypes(Ident("X"), Seq(SInt))
parse("X[Int].isDefined") shouldBe Select(ApplyTypes(Ident("X"), Seq(SInt)), "isDefined")
parse("X[Int].isEmpty") shouldBe Select(ApplyTypes(Ident("X"), Seq(SInt)), "isEmpty")
parse("X[(Int, Boolean)]") shouldBe ApplyTypes(Ident("X"), Seq(STuple(SInt, SBoolean)))
parse("X[Int, Boolean]") shouldBe ApplyTypes(Ident("X"), Seq(SInt, SBoolean))
parse("SELF.R1[Int]") shouldBe ApplyTypes(Select(Ident("SELF"), "R1"), Seq(SInt))
parse("SELF.getReg[Int](1)") shouldBe Apply(ApplyTypes(Select(Ident("SELF"), "getReg"), Seq(SInt)), IndexedSeq(IntConstant(1)))
parse("SELF.R1[Int].isDefined") shouldBe Select(ApplyTypes(Select(Ident("SELF"), "R1"), Seq(SInt)),"isDefined")
parse("SELF.R1[Int].isEmpty") shouldBe Select(ApplyTypes(Select(Ident("SELF"), "R1"), Seq(SInt)),"isEmpty")
parse("f[Int](10)") shouldBe Apply(ApplyTypes(Ident("f"), Seq(SInt)), IndexedSeq(IntConstant(10)))
parse("INPUTS.map[Int]") shouldBe ApplyTypes(Select(Ident("INPUTS"), "map"), Seq(SInt))
parse("INPUTS.map[Int](10)") shouldBe Apply(ApplyTypes(Select(Ident("INPUTS"), "map"), Seq(SInt)), IndexedSeq(IntConstant(10)))
Expand Down
3 changes: 3 additions & 0 deletions sc/src/main/scala/sigmastate/lang/SigmaBinder.scala
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,9 @@ class SigmaBinder(env: ScriptEnv, builder: SigmaBuilder,
case a @ Apply(PKFunc.symNoType, args) =>
Some(PKFunc.irInfo.irBuilder(PKFunc.sym, args).withPropagatedSrcCtx(a.sourceContext))

case sel @ Select(obj, "isEmpty", _) =>
Some(mkLogicalNot(mkSelect(obj, "isDefined").asBoolValue).withPropagatedSrcCtx(sel.sourceContext))

})))(e)

def bind(e: SValue): SValue =
Expand Down
3 changes: 3 additions & 0 deletions sc/src/test/scala/sigmastate/eval/EvaluationTest.scala
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,14 @@ class EvaluationTest extends BaseCtxTests
val ctx = newErgoContext(height = 1, self)
// guarded register access: existing reg
reduce(emptyEnv, "lazy1", "SELF.R4[Int].isDefined && SELF.R4[Int].get == 10", ctx, true)
reduce(emptyEnv, "lazy4", "SELF.R4[Int].isEmpty == false && SELF.R4[Int].get == 10", ctx, true)
// guarded register access: non-existing reg
reduce(emptyEnv, "lazy2", "SELF.R5[Int].isDefined && SELF.R5[Int].get == 10", ctx, false)
reduce(emptyEnv, "lazy5", "SELF.R5[Int].isEmpty == false && SELF.R5[Int].get == 10", ctx, false)

// guarded register access: reading register if it is defined and another one is undefined
reduce(emptyEnv, "lazy3", "SELF.R4[Int].isDefined && (SELF.R5[Int].isDefined || SELF.R4[Int].get == 10)", ctx, true)
reduce(emptyEnv, "lazy6", "SELF.R4[Int].isEmpty == false && (SELF.R5[Int].isEmpty == false || SELF.R4[Int].get == 10)", ctx, true)
}

test("context data") {
Expand Down
2 changes: 1 addition & 1 deletion sc/src/test/scala/sigmastate/lang/SigmaBinderTest.scala
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ class SigmaBinderTest extends AnyPropSpec with ScalaCheckPropertyChecks with Mat
bind(env, "X[(Int, Boolean)]") shouldBe ApplyTypes(Ident("X"), Seq(STuple(SInt, SBoolean)))
bind(env, "X[Int, Boolean]") shouldBe ApplyTypes(Ident("X"), Seq(SInt, SBoolean))
bind(env, "SELF.R1[Int]") shouldBe ApplyTypes(Select(Self, "R1"), Seq(SInt))
bind(env, "SELF.R1[Int].isEmpty") shouldBe Select(ApplyTypes(Select(Self, "R1"), Seq(SInt)), "isEmpty")
bind(env, "SELF.R1[Int].isEmpty") shouldBe LogicalNot(Select(ApplyTypes(Select(Self, "R1"), Seq(SInt)), "isDefined").asBoolValue)
bind(env, "f[Int](10)") shouldBe Apply(ApplyTypes(Ident("f"), Seq(SInt)), IndexedSeq(IntConstant(10)))
bind(env, "INPUTS.map[Int]") shouldBe ApplyTypes(Select(Inputs, "map"), Seq(SInt))
bind(env, "INPUTS.map[Int](10)") shouldBe Apply(ApplyTypes(Select(Inputs, "map"), Seq(SInt)), IndexedSeq(IntConstant(10)))
Expand Down
3 changes: 1 addition & 2 deletions sc/src/test/scala/sigmastate/lang/SigmaTyperTest.scala
Original file line number Diff line number Diff line change
Expand Up @@ -299,8 +299,7 @@ class SigmaTyperTest extends AnyPropSpec
property("type parameters") {
typecheck(env, "SELF.R1[Int]") shouldBe SOption(SInt)
typecheck(env, "SELF.R1[Int].isDefined") shouldBe SBoolean
// TODO soft-fork: https://github.com/ScorexFoundation/sigmastate-interpreter/issues/479
// typecheck(env, "SELF.R1[Int].isEmpty") shouldBe SBoolean
typecheck(env, "SELF.R1[Int].isEmpty") shouldBe SBoolean
typecheck(env, "SELF.R1[Int].get") shouldBe SInt
// TODO soft-fork: https://github.com/ScorexFoundation/sigmastate-interpreter/issues/416
// typecheck(env, "SELF.getReg[Int](1)") shouldBe SOption.SIntOption
Expand Down
26 changes: 26 additions & 0 deletions sc/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala
Original file line number Diff line number Diff line change
Expand Up @@ -502,6 +502,32 @@ class BasicOpsSpecification extends CompilerTestingCommons
)
}

property("OptionIsEmpty") {
test("Def1", env, ext,
"{ SELF.R4[SigmaProp].isEmpty == false }",
ExtractRegisterAs[SSigmaProp.type](Self, reg1).isDefined.toSigmaProp,
true
)
// no value
test("Def2", env, ext,
"{ SELF.R8[Int].isEmpty }",
LogicalNot(ExtractRegisterAs[SInt.type](Self, R8).isDefined).toSigmaProp,
true
)

test("Def3", env, ext,
"{ getVar[Int](intVar2).isEmpty == false }",
GetVarInt(intVar2).isDefined.toSigmaProp,
true
)
// there should be no variable with this id
test("Def4", env, ext,
"{ getVar[Int](99).isEmpty }",
LogicalNot(GetVarInt(99).isDefined).toSigmaProp,
true
)
}

// TODO this is valid for BigIntModQ type (https://github.com/ScorexFoundation/sigmastate-interpreter/issues/554)
ignore("ByteArrayToBigInt: big int should always be positive") {
test("BATBI1", env, ext,
Expand Down
5 changes: 1 addition & 4 deletions sc/src/test/scala/special/sigma/SigmaDslSpecification.scala
Original file line number Diff line number Diff line change
Expand Up @@ -9099,15 +9099,12 @@ class SigmaDslSpecification extends SigmaDslTesting

// TODO v6.0 (3h): implement Option.fold
property("Option new methods") {
val isEmpty = newFeature({ (x: Option[Long]) => x.isEmpty },
"{ (x: Option[Long]) => x.isEmpty }")

val n = ExactNumeric.LongIsExactNumeric
val fold = newFeature({ (x: Option[Long]) => x.fold(5.toLong)( (v: Long) => n.plus(v, 1) ) },
"{ (x: Option[Long]) => x.fold(5, { (v: Long) => v + 1 }) }")

forAll { x: Option[Long] =>
Seq(isEmpty, fold).map(_.checkEquality(x))
Seq(fold).map(_.checkEquality(x))
}
}

Expand Down
Loading

0 comments on commit 1abafe9

Please sign in to comment.