diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000000..3f87541daf --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,65 @@ +name: CI + +on: + push: + branches: + - master + - develop + pull_request: + types: + - opened + - synchronize + +env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + +jobs: + build: + name: Test and publish a snapshot + strategy: + matrix: + os: [ubuntu-latest] + scala: [2.12.10, 2.11.12] + java: [adopt@1.11] + runs-on: ${{ matrix.os }} + steps: + - name: Checkout current branch (full) + uses: actions/checkout@v2 + with: + fetch-depth: 0 + + - name: Setup Java and Scala + uses: olafurpg/setup-scala@v10 + with: + java-version: ${{ matrix.java }} + + - name: Cache sbt + uses: actions/cache@v2 + with: + path: | + ~/.sbt + ~/.ivy2/cache + ~/.coursier/cache/v1 + ~/.cache/coursier/v1 + ~/AppData/Local/Coursier/Cache/v1 + ~/Library/Caches/Coursier/v1 + key: ${{ runner.os }}-sbt-cache-v2-${{ hashFiles('**/*.sbt') }}-${{ hashFiles('project/build.properties') }} + + - name: Runs tests and collect coverage + run: sbt -jvm-opts ci/ci.jvmopts ++${{ matrix.scala }} coverage test coverageReport coverageAggregate + + # - name: Upload coverage report + # run: sbt ++${{ matrix.scala }} coverageReport coverageAggregate coveralls + # env: + # COVERALLS_REPO_TOKEN: $${{ secrets.COVERALLS_REPO_TOKEN }} + + - name: Upload coverage report to Codecov + uses: codecov/codecov-action@v1 + with: + fail_ci_if_error: true + + - name: Publish a snapshot ${{ github.ref }} + run: sbt ++${{ matrix.scala }} publish + env: + SONATYPE_PASSWORD: ${{ secrets.SONATYPE_PASSWORD }} + SONATYPE_USERNAME: ${{ secrets.SONATYPE_USERNAME }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000000..cb74691dff --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,44 @@ +name: Publish a release + +on: + release: + types: [published] + +env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + +jobs: + publish_release: + name: Publish release to Sonatype + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + + - name: Setup Java and Scala + uses: olafurpg/setup-scala@v10 + with: + java-version: adopt@1.11 + + - name: Cache sbt + uses: actions/cache@v2 + with: + path: | + ~/.sbt + ~/.ivy2/cache + ~/.coursier/cache/v1 + ~/.cache/coursier/v1 + ~/AppData/Local/Coursier/Cache/v1 + ~/Library/Caches/Coursier/v1 + key: ${{ runner.os }}-sbt-cache-v2-${{ hashFiles('**/*.sbt') }}-${{ hashFiles('project/build.properties') }} + + - name: Import GPG key + run: ci/import_gpg.sh + env: + GPG_SIGNING_KEY: ${{ secrets.GPG_SIGNING_KEY }} + + - name: Publish release ${{ github.ref }} + run: sbt +publishSigned sonatypeBundleRelease + env: + PGP_PASSPHRASE: ${{ secrets.PGP_PASSPHRASE }} + SONATYPE_PASSWORD: ${{ secrets.SONATYPE_PASSWORD }} + SONATYPE_USERNAME: ${{ secrets.SONATYPE_USERNAME }} diff --git a/.gitignore b/.gitignore index 47dc20e13e..d621df577a 100644 --- a/.gitignore +++ b/.gitignore @@ -43,4 +43,5 @@ spam-tests/ .bloop/ .metals/ .vscode/ -project/metals.sbt \ No newline at end of file +project/metals.sbt +/project/project/ \ No newline at end of file diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 002d418bda..0000000000 --- a/.travis.yml +++ /dev/null @@ -1,35 +0,0 @@ -sudo: required -dist: trusty -before_cache: -- find $HOME/.sbt -name "*.lock" | xargs rm -- find $HOME/.ivy2 -name "ivydata-*.properties" | xargs rm -cache: - directories: - - "$HOME/.ivy2/cache" - - "$HOME/.sbt" -language: scala -scala: - - 2.12.10 - - 2.11.12 -jdk: -- oraclejdk8 -stages: -- test -- name: release - if: tag =~ ^v -- name: snapshot - if: "(NOT tag IS present) AND (type = push)" -jobs: - include: - - stage: test - script: sbt -jvm-opts .travis.jvmopts +coverage +test && sbt +coverageReport coverageAggregate coveralls - - stage: release - # decrypt the private key (exported via https://docs.scala-lang.org/overviews/contributors/index.html#export-your-pgp-key-pair ) - script: openssl aes-256-cbc -K $encrypted_98cf3af00429_key -iv $encrypted_98cf3af00429_iv -in ci/secring.asc.enc -out ci/secring.asc -d && gpg --import ci/secring.asc && sbt -jvm-opts .travis.jvmopts +publishSigned sonatypeBundleRelease - - stage: snapshot - script: sbt -jvm-opts .travis.jvmopts +publish -env: - global: - - secure: IGwd+lY2TfkAeX1SfzaYBwyhiiPaFrTxoF0e+4R1bkGxiGCce1hBYjn15z1HRfK+k3hgEZh/FBG7dv8LQfNWQ6AJY5PQ2zwckd4ArYMhTVpiY4eRzUMqO1/gjTCCbbTjfFKOMsR2pAw+TGeglqoX4eyziIaS8nR901dZcFvHuC1Fr5EdKFZ0x+WHnX8vaSQoDE4u1MoBnyo5cRVumXG+xvs1Q0nZXm/hd/Flfx5u3L7veKAkGtvbHmdsJoSSySTbc1MGYQtofQjbjd9AVvUhgfP32J63UCC2SqgWWKVvIjW+dUn414BV3lelnWR3FdzhC7AUJqYWVfSILh1aj3STnizRnjtCScmyoRz4ldUQ3jr4jBJOREUEus5YH2EqY1MGjX+8kUu9IjDYiQyNy1EdivcmMlXCOcAW2mi4rGDRxZOeFt1ZSHzxqSghZOFwvk/OFcdDzV4/3OnAcGz8LH5qjZU/edjmfkSls5CqxuAFqeD7RZWIu0ccjt6dzQZAf02lBX9kQuwIruC4x4E0iEjml7jmaEeOT4Hqk7wAo6EFMSEkj4EnS/Kln6Wr7JBut5qrMk0+PDgvxaKCaN8LeycCSQdoXfPO602WzfasNcOJexSmGMAE5NYfeXjq1h3F9AVHJ3TbNAOdlQTHbSOqt7WO10JphljYnFEu4aSzvaA3E60= - - secure: g4Egz1orKgCAgTckMYHHbpsFY8ppldLLUkBi0GasHN4M2zhfYlqzaJ+ZZ4soMPNshcS3XutGS+/ERF5zrnHF1C9h3txW6AJkgMkTF1q4UyKan25chdPnz1nNUrdQOvaCA4CzLIN3aQAHN40p44ELxfNTARTfbUAIcqNSrKmXZsUbhQg9yyM+gFL6cCw7SYQphC9GJq4mvW19dzzpU8MQ0AtktB6mscuUyiWgniHsnFAmeQBv0csCiMyjUsT1buIkO0gSvZBKkLXu7kXhash/mLjrBYGapVGGFORA3pWy9JCB9OfxV8Bj1wNUqPyAImjGgVfgK6RxOnQ/C4GTsf8uVH/sYIiPnzPmbCrO7fQee68/+SWtZc1kko8HuiqHvouNHmKQy+Hwku2AIdp6nZDhOuFtQTP1PbkYLrdNj1evAI6913rq51e7vDWTriWmOKjMz2m4Tj2HGJx0VS0pNOZkpxwVhHOdyc1UXurpBKgkYis1HVcaEM3trFzhsMf7kllNvJLA1COwg7KbVebKwA9gXfYrKAp6p76YMaSYodSDq9VaSDPF/2MVCZYXs+FAUZ3MzcsAZ7TegSX2OWrrneGArjcQgdMLUetm+UgBFZF7pG3BpjMLVwMgp9ulUNkq1sP1vLU08cvQv6A3W/kcyrVyCNzg80XTQqDpxz7hCTbyBSw= - - secure: gfhEv/PXEckwZPnwJHl4fBCJKCrCKK4KMeYCPNZZtKuV1gC4mZscvECm8r+kgB+o2G3i4tEIYcIC5Jbdcbjf4bk6uNZW/X3dna0irl/Mdswt7rTLzLan1rPz3k8Bylgs8ehETFBGr8HyNitEa8ODyaEXa84MPQaucXUmpHS+sUEhQn0Z70T70d1H9ZubUhGv9VLltNoSWkPGW5CPZlpQTHl63ZShfmylfQuQVTbVMdL8LLUHn2x2edlDKMGD8YPH5d+of0AKc3IKnlnMM36WjgYVsf1yehfLi0NH/b2Dzk7wLjetu/bw8Cu9Ne6/u0Lu83Hbh4DyS2iPQivDUGB+JXlHDFI4uji3GurnvpFDku1gbc4HVoFqhgOWyXQAiRllj2BXmq2vwp6797TUG4HrD2EVzIJV7eIZdWNN/QttZtNxNdSbBq8QQc92G2SU4q7PcogMSr0LpX05SfyL1sMgX2WeGzFzyMIu/+rAJhG0lPt7krBxEfQrRtTLdJ9eyeFjFQlxM6G/9gk68j+Nida6KunLwe9QEl2T+t1YbE4i9pndoCMJFxAOjirhw5OM3PfSWfb/mU7zXd4PSNK7RQIdOaPJff5C6UEM7h/iQ6riRZp1Pn7d/rxppTXsvUbtvwUYnkoOeUZyMvQNQsPI6Slns8jWl0zp5XiTmzSRVOuH3ME= diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000000..ff928680e4 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,4 @@ +## Releasing +To publish release version to Sonatype, do the following: +- make a tag with version number `vX.Y.Z` (used by `sbt-dynver` to set `version` in `build.sbt`); +- use the new tag to make a Github release, which triggers [`release.yml`](.github/workflows/release.yml) workflow and publishes release version to Sonatype; diff --git a/build.sbt b/build.sbt index 0cad69bd90..e6adf65cdf 100644 --- a/build.sbt +++ b/build.sbt @@ -43,39 +43,19 @@ lazy val commonSettings = Seq( , publishMavenStyle := true, - publishTo := sonatypePublishToBundle.value + publishTo := sonatypePublishToBundle.value, + scmInfo := Some( + ScmInfo( + url("https://github.com/ScorexFoundation/sigmastate-interpreter"), + "scm:git@github.com:ScorexFoundation/sigmastate-interpreter.git" + ) + ), ) -enablePlugins(GitVersioning) - -version in ThisBuild := { - if (git.gitCurrentTags.value.nonEmpty) { - git.gitDescribedVersion.value.get - } else { - if (git.gitHeadCommit.value.contains(git.gitCurrentBranch.value)) { - // see https://docs.travis-ci.com/user/environment-variables/#default-environment-variables - if (Try(sys.env("TRAVIS")).getOrElse("false") == "true") { - // pull request number, "false" if not a pull request - if (Try(sys.env("TRAVIS_PULL_REQUEST")).getOrElse("false") != "false") { - // build is triggered by a pull request - val prBranchName = Try(sys.env("TRAVIS_PULL_REQUEST_BRANCH")).get - val prHeadCommitSha = Try(sys.env("TRAVIS_PULL_REQUEST_SHA")).get - prBranchName + "-" + prHeadCommitSha.take(8) + "-SNAPSHOT" - } else { - // build is triggered by a push - val branchName = Try(sys.env("TRAVIS_BRANCH")).get - branchName + "-" + git.gitHeadCommit.value.get.take(8) + "-SNAPSHOT" - } - } else { - git.gitHeadCommit.value.get.take(8) + "-SNAPSHOT" - } - } else { - git.gitCurrentBranch.value + "-" + git.gitHeadCommit.value.get.take(8) + "-SNAPSHOT" - } - } -} - -git.gitUncommittedChanges in ThisBuild := true +// prefix version with "-SNAPSHOT" for builds without a git tag +dynverSonatypeSnapshots in ThisBuild := true +// use "-" instead of default "+" +dynverSeparator in ThisBuild := "-" val bouncycastleBcprov = "org.bouncycastle" % "bcprov-jdk15on" % "1.64" val scrypto = "org.scorexfoundation" %% "scrypto" % "2.1.10" diff --git a/.travis.jvmopts b/ci/ci.jvmopts similarity index 94% rename from .travis.jvmopts rename to ci/ci.jvmopts index 3d4461e517..2e608cfbfd 100644 --- a/.travis.jvmopts +++ b/ci/ci.jvmopts @@ -1,4 +1,4 @@ --Xmx4g +-Xmx6g -Xss2m -XX:+CMSClassUnloadingEnabled -XX:+UseConcMarkSweepGC diff --git a/ci/import_gpg.sh b/ci/import_gpg.sh new file mode 100755 index 0000000000..b1eb66e0bd --- /dev/null +++ b/ci/import_gpg.sh @@ -0,0 +1,21 @@ +#!/bin/bash +# setting up gpg2 for reading passphrase from parameters +# via https://github.com/beautiful-scala/scalastyle/blob/master/.github/workflows/release.yml#L16 +# from https://github.com/olafurpg/sbt-ci-release/issues/95 + +# setup gpg +mkdir ~/.gnupg && chmod 700 ~/.gnupg +echo use-agent >> ~/.gnupg/gpg.conf +echo pinentry-mode loopback >> ~/.gnupg/gpg.conf +echo allow-loopback-pinentry >> ~/.gnupg/gpg-agent.conf +chmod 600 ~/.gnupg/* +echo RELOADAGENT | gpg-connect-agent + +# decode key +# private key should be previously exported with: +# gpg --export-secret-keys [id] | base64 | pbcopy +# and stored as github repository secret under the following name (see env var name below) +printf "$GPG_SIGNING_KEY" | base64 --decode > ~/.gnupg/private.key + +# import key +gpg --no-tty --batch --yes --import ~/.gnupg/private.key diff --git a/ci/pubring.asc b/ci/pubring.asc deleted file mode 100644 index cf75b9dfab..0000000000 --- a/ci/pubring.asc +++ /dev/null @@ -1,30 +0,0 @@ ------BEGIN PGP PUBLIC KEY BLOCK----- - -mQENBF2utdgBCAClRGOfWeus4AlHvCBgJVXH2CLqXLKCBggE2vwKbKvFdW1DTPZQ -T1RI6zBtMdaSNVm4ISO4dOO67VGdajr8/6kFt2+di2b7hMVaULf4UgYuZ+vvVUPp -3oSEJnHheh5ZfjV+jvL5GSAu+vgnC8qbPutCEpXBfx5zAOdLtiyegzx72asJvvkz -ghvyXVrg8gnXVtiSBV1EpfES7gZJmpuzv2dYrCtL2irlRlySLQ5JFKXrfOQvf4K9 -TCxRye1UNb+3ybL0ilXoRn3jDS9RLbLxiVMjjx/Bqk/mc3MNMoa+juzvI6xIxFG0 -3fwNOTXdQ6gLCjHJ9/nFvygkBW5bkeMujBhhABEBAAG0JlNpZ21hc3RhdGUgYm90 -IDxkZW55c0B6YWRvcm96aG55aS5jb20+iQFUBBMBCAA+FiEEKOJ6Z66jjaRYxyIo -ypJUteBkD+QFAl2utdgCGwMFCQPCZwAFCwkIBwIGFQoJCAsCBBYCAwECHgECF4AA -CgkQypJUteBkD+Tt4Af/f5o2Yoc8ebOwMiNUYDkfUqFLzH1WySEKfAt2iXrIgVjV -NF6ddyaLadSYdU6HGJ6txn2a16TuItdBQJSTpnmiw1qtqNVJVRnUoytXeCYN0Utn -+3zYTOhkbhnIczGao+qlqhovfO8x+WPZ/2Fczm20A5TNAg7NzmeF7FP9OWLpnI4v -yktmAbpZaSoCZWC3ZPG2H3SOHUn8Lt0++ni4R0gT0HclwbyzuDgT0cmxarVzEFQQ -7nhNOhU1+1MYRpQ9wBUWFLwMvMUgA6rQeg7idtAXklGEZaN0RK3HpL1I+XAE9rYW -tdejY67u/hdInm33oqe5aJrPmH5DFNCpBpc2w2NzGbkBDQRdrrXYAQgAxGs1Fclq -MQJjIwu3dH+vBY5vdZ0M1Mhd2fjXu8s0tEZ8RjBBbtZ03KI5t97+oXs5rgKCCtRH -v+RfSDn1eTeKRIwYxsowd86SlC8rjhSAyJfWS7er7+4Jpsa1W91TucrMQMue4qEX -udlg18oNcX/MGDB+lPirL1zxp6jfysjlebx01dcKVj2a+rpyPeNNrV2M8Ywlm5/c -lmRciSXLMb+phhvcyYyvi4UmguQi7/o3hCNhRlEj4XqF6CT1S57X6nTuYRP1dcjG -GVxvlybrDIBV0oDGW0TEjGWaBwKOpqZDi8Jzj5P398nqnP0UDrW7q/qmrZcdE5ov -qYWERLqXzGwBFwARAQABiQE8BBgBCAAmFiEEKOJ6Z66jjaRYxyIoypJUteBkD+QF -Al2utdgCGwwFCQPCZwAACgkQypJUteBkD+Qbqwf+IR030kbKsE6rOLwlKUGN9pah -tZjoSxnq5K+nXn621K578z9r76rGkP84UeAvZqt2MkadhwyEqwv99DftoZCXNM8b -5oRsDOAbA0YTSPKIa8E7S8XhWzE6VCx+2DFtjrYeGhybVGd9aq6jeQgEkqioZT0n -l3acH1VsuFQdFNwBrEgAFORBt5zXtSn7lXmnOh4ZFeYCncdR3+L6nJ/PAPz0hWMz -CZjc7vGcEvAtTNb2brtHtvox0Gc0Xphe0iCaWyzN7P32+rJgsfCMj9FFQUxToZMY -ozM9at2zWzk9wOb41RLnY+rGBNQ3xNR23shWF4fcOwk6BIp+OYsSqnsEYYXuDw== -=huRW ------END PGP PUBLIC KEY BLOCK----- diff --git a/ci/secring.asc.enc b/ci/secring.asc.enc deleted file mode 100644 index 2cc0474c89..0000000000 Binary files a/ci/secring.asc.enc and /dev/null differ diff --git a/project/build.properties b/project/build.properties index 72f902892a..c06db1bb2e 100644 --- a/project/build.properties +++ b/project/build.properties @@ -1 +1 @@ -sbt.version=1.2.7 +sbt.version=1.4.5 diff --git a/project/plugins.sbt b/project/plugins.sbt index 7964090b4d..b9cfa44119 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -2,9 +2,9 @@ logLevel := Level.Warn addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.14.9") addSbtPlugin("com.eed3si9n" % "sbt-buildinfo" % "0.9.0") -addSbtPlugin("com.typesafe.sbt" % "sbt-git" % "1.0.0") addSbtPlugin("net.virtual-void" % "sbt-dependency-graph" % "0.9.2") addSbtPlugin("org.scoverage" % "sbt-scoverage" % "1.6.1") addSbtPlugin("org.scoverage" % "sbt-coveralls" % "1.2.7") -addSbtPlugin("org.xerial.sbt" % "sbt-sonatype" % "3.8") -addSbtPlugin("com.jsuereth" % "sbt-pgp" % "2.0.0") \ No newline at end of file +addSbtPlugin("org.xerial.sbt" % "sbt-sonatype" % "3.9.5") +addSbtPlugin("com.jsuereth" % "sbt-pgp" % "2.0.0") +addSbtPlugin("com.dwijnand" % "sbt-dynver" % "4.1.1") \ No newline at end of file diff --git a/sigmastate/src/main/scala/org/ergoplatform/ErgoLikeContext.scala b/sigmastate/src/main/scala/org/ergoplatform/ErgoLikeContext.scala index 6f5544e847..8467a24ee7 100644 --- a/sigmastate/src/main/scala/org/ergoplatform/ErgoLikeContext.scala +++ b/sigmastate/src/main/scala/org/ergoplatform/ErgoLikeContext.scala @@ -13,24 +13,40 @@ import sigmastate.serialization.OpCodes import sigmastate.serialization.OpCodes.OpCode import special.collection.Coll import special.sigma -import special.sigma.{AnyValue, Header, PreHeader} +import special.sigma.{AnyValue, PreHeader, Header} import spire.syntax.all.cfor -/** - * TODO lastBlockUtxoRoot should be calculated from headers if it is nonEmpty +/** Represents a script evaluation context to be passed to a prover and a verifier to execute and + * validate guarding proposition of input boxes of a transaction. * - * @param selfIndex - index of the box in `boxesToSpend` that contains the script we're evaluating - * @param lastBlockUtxoRoot - state root before current block application - * @param headers - fixed number of last block headers in descending order (first header is the newest one) - * @param preHeader - fields of block header with the current `spendingTransaction`, that can be predicted - * by a miner before it's formation - * @param dataBoxes - boxes, that corresponds to id's of `spendingTransaction.dataInputs` - * @param boxesToSpend - boxes, that corresponds to id's of `spendingTransaction.inputs` - * @param spendingTransaction - transaction that contains `self` box - * @param extension - prover-defined key-value pairs, that may be used inside a script - * @param validationSettings validataion parameters passed to Interpreter.verify to detect soft-fork conditions - * @param costLimit hard limit on accumulated execution cost, if exceeded lead to CostLimitException to be thrown - * @param initCost initial value of execution cost already accumulated before Interpreter.verify is called + * @param selfIndex - index of the box in `boxesToSpend` that contains the script we're evaluating + * @param lastBlockUtxoRoot - state root before current block application + * @param headers - fixed number of last block headers in descending order (first header is the newest one) + * @param preHeader - fields of block header with the current `spendingTransaction`, that can be predicted + * by a miner before it's formation + * @param dataBoxes - boxes, that corresponds to id's of `spendingTransaction.dataInputs` + * @param boxesToSpend - boxes, that corresponds to id's of `spendingTransaction.inputs` + * @param spendingTransaction - transaction that contains `self` box + * @param extension - prover-defined key-value pairs, that may be used inside a script + * @param validationSettings validation parameters passed to Interpreter.verify to detect soft-fork conditions + * @param costLimit hard limit on accumulated execution cost, if exceeded lead to CostLimitException to be thrown + * @param initCost initial value of execution cost already accumulated before Interpreter.verify is called + * @param activatedScriptVersion Maximum version of ErgoTree currently activated on the network. + * The activation is performed via miners voting. + * For verification of *mined* blocks this parameter should be passed according + * to the latest voted (activated) script version on the network. + * However this is not the case for *candidate* blocks. + * When `activatedScriptVersion > Interpreter.MaxSupportedScriptVersion` + * then the interpreter accept script without verification which is not + * what should happen for *candidate* blocks. + * This means Ergo node should always pass Interpreter.MaxSupportedScriptVersion + * as a value of ErgoLikeContext.activatedScriptVersion during + * verification of candidate blocks (which is a default). + * The following values are used for current and upcoming forks: + * - version 3.x this value must be 0 + * - in v4.0 must be 1 + * - in v5.x must be 2 + * etc. */ class ErgoLikeContext(val lastBlockUtxoRoot: AvlTreeData, val headers: Coll[Header], @@ -42,8 +58,10 @@ class ErgoLikeContext(val lastBlockUtxoRoot: AvlTreeData, val extension: ContextExtension, val validationSettings: SigmaValidationSettings, val costLimit: Long, - val initCost: Long + val initCost: Long, + val activatedScriptVersion: Byte ) extends InterpreterContext { + // TODO lastBlockUtxoRoot should be calculated from headers if it is nonEmpty /* NOHF PROOF: Added: assert(preHeader != null) @@ -93,30 +111,19 @@ class ErgoLikeContext(val lastBlockUtxoRoot: AvlTreeData, val self: ErgoBox = boxesToSpend(selfIndex) override def withCostLimit(newCostLimit: Long): ErgoLikeContext = - new ErgoLikeContext( - lastBlockUtxoRoot, headers, preHeader, - dataBoxes, boxesToSpend, spendingTransaction, selfIndex, extension, validationSettings, newCostLimit, initCost) + ErgoLikeContext.copy(this)(costLimit = newCostLimit) - override def withInitCost(newCost: Long): ErgoLikeContext = - new ErgoLikeContext( - lastBlockUtxoRoot, headers, preHeader, - dataBoxes, boxesToSpend, spendingTransaction, selfIndex, extension, validationSettings, costLimit, newCost) + override def withInitCost(newInitCost: Long): ErgoLikeContext = + ErgoLikeContext.copy(this)(initCost = newInitCost) override def withValidationSettings(newVs: SigmaValidationSettings): ErgoLikeContext = - new ErgoLikeContext( - lastBlockUtxoRoot, headers, preHeader, - dataBoxes, boxesToSpend, spendingTransaction, selfIndex, extension, newVs, costLimit, initCost) + ErgoLikeContext.copy(this)(validationSettings = newVs) override def withExtension(newExtension: ContextExtension): ErgoLikeContext = - new ErgoLikeContext( - lastBlockUtxoRoot, headers, preHeader, - dataBoxes, boxesToSpend, spendingTransaction, selfIndex, newExtension, validationSettings, costLimit, initCost) + ErgoLikeContext.copy(this)(extension = newExtension) def withTransaction(newSpendingTransaction: ErgoLikeTransactionTemplate[_ <: UnsignedInput]): ErgoLikeContext = - new ErgoLikeContext( - lastBlockUtxoRoot, headers, preHeader, - dataBoxes, boxesToSpend, newSpendingTransaction, selfIndex, extension, validationSettings, costLimit, initCost) - + ErgoLikeContext.copy(this)(spendingTransaction = newSpendingTransaction) override def toSigmaContext(isCost: Boolean, extensions: Map[Byte, AnyValue] = Map()): sigma.Context = { import Evaluation._ @@ -164,14 +171,18 @@ class ErgoLikeContext(val lastBlockUtxoRoot: AvlTreeData, extension == that.extension && validationSettings == that.validationSettings && costLimit == that.costLimit && - initCost == that.initCost + initCost == that.initCost && + activatedScriptVersion == that.activatedScriptVersion case _ => false } def canEqual(other: Any): Boolean = other.isInstanceOf[ErgoLikeContext] override def hashCode(): Int = { - val state = Array(lastBlockUtxoRoot, headers, preHeader, dataBoxes, boxesToSpend, spendingTransaction, selfIndex, extension, validationSettings, costLimit, initCost) + val state = Array( + lastBlockUtxoRoot, headers, preHeader, dataBoxes, boxesToSpend, spendingTransaction, + selfIndex, extension, validationSettings, costLimit, initCost, + activatedScriptVersion) var hashCode = 0 cfor(0)(_ < state.length, _ + 1) { i => hashCode = 31 * hashCode + state(i).hashCode @@ -179,7 +190,7 @@ class ErgoLikeContext(val lastBlockUtxoRoot: AvlTreeData, hashCode } - override def toString = s"ErgoLikeContext(lastBlockUtxoRoot=$lastBlockUtxoRoot, headers=$headers, preHeader=$preHeader, dataBoxes=$dataBoxes, boxesToSpend=$boxesToSpend, spendingTransaction=$spendingTransaction, selfIndex=$selfIndex, extension=$extension, validationSettings=$validationSettings, costLimit=$costLimit, initCost=$initCost)" + override def toString = s"ErgoLikeContext(lastBlockUtxoRoot=$lastBlockUtxoRoot, headers=$headers, preHeader=$preHeader, dataBoxes=$dataBoxes, boxesToSpend=$boxesToSpend, spendingTransaction=$spendingTransaction, selfIndex=$selfIndex, extension=$extension, validationSettings=$validationSettings, costLimit=$costLimit, initCost=$initCost, activatedScriptVersion=$activatedScriptVersion)" } object ErgoLikeContext { @@ -188,6 +199,29 @@ object ErgoLikeContext { /** Maximimum number of headers in `headers` collection of the context. */ val MaxHeaders = SigmaConstants.MaxHeaders.value + + /** Copies the given context allowing also to update fields. + * NOTE: it can be used ONLY for instances of ErgoLikeContext. + * @tparam T used here to limit use of this method to only ErgoLikeContext instances + * @return a new instance of [[ErgoLikeContext]]. */ + @inline def copy[T >: ErgoLikeContext <: ErgoLikeContext](ctx: T)( + lastBlockUtxoRoot: AvlTreeData = ctx.lastBlockUtxoRoot, + headers: Coll[Header] = ctx.headers, + preHeader: PreHeader = ctx.preHeader, + dataBoxes: IndexedSeq[ErgoBox] = ctx.dataBoxes, + boxesToSpend: IndexedSeq[ErgoBox] = ctx.boxesToSpend, + spendingTransaction: ErgoLikeTransactionTemplate[_ <: UnsignedInput] = ctx.spendingTransaction, + selfIndex: Int = ctx.selfIndex, + extension: ContextExtension = ctx.extension, + validationSettings: SigmaValidationSettings = ctx.validationSettings, + costLimit: Long = ctx.costLimit, + initCost: Long = ctx.initCost, + activatedScriptVersion: Byte = ctx.activatedScriptVersion): ErgoLikeContext = { + new ErgoLikeContext( + lastBlockUtxoRoot, headers, preHeader, dataBoxes, boxesToSpend, + spendingTransaction, selfIndex, extension, validationSettings, costLimit, initCost, + activatedScriptVersion) + } } /** When interpreted evaluates to a ByteArrayConstant built from Context.minerPubkey */ diff --git a/sigmastate/src/main/scala/org/ergoplatform/JsonCodecs.scala b/sigmastate/src/main/scala/org/ergoplatform/JsonCodecs.scala index 7391f8e324..28a905d342 100644 --- a/sigmastate/src/main/scala/org/ergoplatform/JsonCodecs.scala +++ b/sigmastate/src/main/scala/org/ergoplatform/JsonCodecs.scala @@ -400,7 +400,8 @@ trait JsonCodecs { "extension" -> ctx.extension.asJson, "validationSettings" -> ctx.validationSettings.asJson, "costLimit" -> ctx.costLimit.asJson, - "initCost" -> ctx.initCost.asJson + "initCost" -> ctx.initCost.asJson, + "scriptVersion" -> ctx.activatedScriptVersion.asJson ) }) @@ -417,7 +418,11 @@ trait JsonCodecs { validationSettings <- cursor.downField("validationSettings").as[SigmaValidationSettings] costLimit <- cursor.downField("costLimit").as[Long] initCost <- cursor.downField("initCost").as[Long] - } yield new ErgoLikeContext(lastBlockUtxoRoot, Colls.fromArray(headers.toArray), preHeader, - dataBoxes, boxesToSpend, spendingTransaction, selfIndex, extension, validationSettings, costLimit, initCost) + version <- cursor.downField("scriptVersion").as[Byte] + } yield new ErgoLikeContext( + lastBlockUtxoRoot, Colls.fromArray(headers.toArray), preHeader, + dataBoxes, boxesToSpend, spendingTransaction, selfIndex, extension, + validationSettings, costLimit, initCost, version + ) }) } diff --git a/sigmastate/src/main/scala/org/ergoplatform/validation/ValidationRules.scala b/sigmastate/src/main/scala/org/ergoplatform/validation/ValidationRules.scala index 478e1983b4..87aa64fde1 100644 --- a/sigmastate/src/main/scala/org/ergoplatform/validation/ValidationRules.scala +++ b/sigmastate/src/main/scala/org/ergoplatform/validation/ValidationRules.scala @@ -76,6 +76,12 @@ case class ValidationException(message: String, rule: ValidationRule, args: Seq[ override def fillInStackTrace(): Throwable = this // to avoid spending time on recording stack trace } +/** All validation rules which are used to check soft-forkable conditions. Each validation + * rule throws a [[org.ergoplatform.validation.ValidationException]]. Each + * ValidationException can be caught and handled with respect to + * [[SigmaValidationSettings]], which can be changed by miners via voting. + * Thus, the behavior of the rules can be overridden without breaking consensus. + */ object ValidationRules { /** The id of the first validation rule. Can be used as the beginning of the rules id range. */ val FirstRuleId = 1000.toShort diff --git a/sigmastate/src/main/scala/sigmastate/Values.scala b/sigmastate/src/main/scala/sigmastate/Values.scala index 09a5974289..17d0b860c8 100644 --- a/sigmastate/src/main/scala/sigmastate/Values.scala +++ b/sigmastate/src/main/scala/sigmastate/Values.scala @@ -37,7 +37,6 @@ import sigmastate.lang.SourceContext import special.collection.Coll import scala.collection.mutable -import scala.collection.mutable.ArrayBuffer object Values { @@ -1043,10 +1042,33 @@ object Values { /** Default header with constant segregation enabled. */ val ConstantSegregationHeader: Byte = (DefaultHeader | ConstantSegregationFlag).toByte + /** @return true if the constant segregation flag is set to 1 in the given header byte. */ @inline final def isConstantSegregation(header: Byte): Boolean = (header & ConstantSegregationFlag) != 0 + + /** @return true if the size flag is set to 1 in the given header byte. */ @inline final def hasSize(header: Byte): Boolean = (header & SizeFlag) != 0 + + /** @return a value of the version bits from the given header byte. */ @inline final def getVersion(header: Byte): Byte = (header & VersionMask).toByte + /** Update the version bits of the given header byte with the given version value. */ + @inline final def updateVersionBits(header: Byte, version: Byte): Byte = { + require(version < 8, s"ErgoTree.version should be < 8: $version") + (header | version).toByte + } + + /** Creates valid header byte with the given version. + * The SizeFlag is set if version > 0 */ + @inline def headerWithVersion(version: Byte): Byte = { + // take default header and embedd the given version in it + var h = updateVersionBits(DefaultHeader, version) + if (version > 0) { + // set SizeFlag if version is greater then 0 (see require() in ErgoTree constructor) + h = (h | ErgoTree.SizeFlag).toByte + } + h + } + def substConstants(root: SValue, constants: IndexedSeq[Constant[SType]]): SValue = { val store = new ConstantStore(constants) val substRule = strategy[Any] { @@ -1066,6 +1088,9 @@ object Values { def withoutSegregation(root: SigmaPropValue): ErgoTree = ErgoTree(ErgoTree.DefaultHeader, EmptyConstants, root) + def withoutSegregation(headerFlags: Byte, root: SigmaPropValue): ErgoTree = + ErgoTree((ErgoTree.DefaultHeader | headerFlags).toByte, EmptyConstants, root) + implicit def fromProposition(prop: SigmaPropValue): ErgoTree = { prop match { case SigmaPropConstant(_) => withoutSegregation(prop) @@ -1077,6 +1102,10 @@ object Values { withoutSegregation(pk.toSigmaProp) } + def fromSigmaBoolean(headerFlags: Byte, pk: SigmaBoolean): ErgoTree = { + withoutSegregation(headerFlags, pk.toSigmaProp) + } + /** Build ErgoTree via serialization of the value with ConstantSegregationHeader, constants segregated * from the tree and ConstantPlaceholders referring to the segregated constants. * diff --git a/sigmastate/src/main/scala/sigmastate/interpreter/Interpreter.scala b/sigmastate/src/main/scala/sigmastate/interpreter/Interpreter.scala index 58bb2a2dd6..5aee794a74 100644 --- a/sigmastate/src/main/scala/sigmastate/interpreter/Interpreter.scala +++ b/sigmastate/src/main/scala/sigmastate/interpreter/Interpreter.scala @@ -10,7 +10,7 @@ import sigmastate.basics.DLogProtocol.{DLogInteractiveProver, FirstDLogProverMes import scorex.util.ScorexLogging import sigmastate.SCollection.SByteArray import sigmastate.Values._ -import sigmastate.eval.{IRContext, Sized, Evaluation} +import sigmastate.eval.{IRContext, Evaluation} import sigmastate.lang.Terms.ValueOps import sigmastate.basics._ import sigmastate.interpreter.Interpreter.{ScriptEnv, VerificationResult} @@ -22,7 +22,7 @@ import org.ergoplatform.validation.ValidationRules._ import scalan.util.BenchmarkUtil import sigmastate.utils.Helpers._ -import scala.util.Try +import scala.util.{Try, Success} trait Interpreter extends ScorexLogging { @@ -231,6 +231,26 @@ trait Interpreter extends ScorexLogging { proof: Array[Byte], message: Array[Byte]): Try[VerificationResult] = { val (res, t) = BenchmarkUtil.measureTime(Try { + // TODO v5.0: the condition below should be revised if necessary + // The following conditions define behavior which depend on the version of ergoTree + // This works in addition to more fine-grained soft-forkability mechanism implemented + // using ValidationRules (see trySoftForkable method call here and in reduceToCrypto). + if (context.activatedScriptVersion > Interpreter.MaxSupportedScriptVersion) { + // > 90% has already switched to higher version, accept without verification + // NOTE: this path should never be taken for validation of candidate blocks + // in which case Ergo node should always pass Interpreter.MaxSupportedScriptVersion + // as the value of ErgoLikeContext.activatedScriptVersion. + // see also ErgoLikeContext ScalaDoc. + return Success(true -> context.initCost) + } else { + // activated version is within the supported range [0..MaxSupportedScriptVersion] + // however + if (ergoTree.version > context.activatedScriptVersion) { + throw new InterpreterException( + s"ErgoTree version ${ergoTree.version} is higher than activated ${context.activatedScriptVersion}") + } + // else proceed normally + } val initCost = JMath.addExact(ergoTree.complexity.toLong, context.initCost) val remainingLimit = context.costLimit - initCost @@ -346,6 +366,17 @@ object Interpreter { val emptyEnv: ScriptEnv = Map.empty[String, Any] val ScriptNameProp = "ScriptName" + /** Maximum version of ErgoTree supported by this interpreter release. + * See version bits in `ErgoTree.header` for more details. + * This value should be increased with each new protocol update via soft-fork. + * The following values are used for current and upcoming forks: + * - version 3.x this value must be 0 + * - in v4.0 must be 1 + * - in v5.x must be 2 + * etc. + */ + val MaxSupportedScriptVersion: Byte = 1 // supported versions 0 and 1 + def error(msg: String) = throw new InterpreterException(msg) } diff --git a/sigmastate/src/main/scala/sigmastate/interpreter/InterpreterContext.scala b/sigmastate/src/main/scala/sigmastate/interpreter/InterpreterContext.scala index 5965c533e1..fd9f054ca7 100644 --- a/sigmastate/src/main/scala/sigmastate/interpreter/InterpreterContext.scala +++ b/sigmastate/src/main/scala/sigmastate/interpreter/InterpreterContext.scala @@ -3,16 +3,21 @@ package sigmastate.interpreter import org.ergoplatform.validation.SigmaValidationSettings import sigmastate.SType import sigmastate.Values.EvaluatedValue -import sigmastate.eval.Evaluation import sigmastate.serialization.SigmaSerializer import sigmastate.utils.{SigmaByteReader, SigmaByteWriter} import special.sigma import special.sigma.AnyValue /** - * User-defined variables to be put into context + * User-defined variables to be put into context. + * Each variable is identified by `id: Byte` and can be accessed from a script + * using `getVar[T](id)` operation. + * The value of the variable is represented by [[sigmastate.Values.Constant]] instance, + * which contains both data value and [[SType]] descriptor. The descriptor is checked + * against the type `T` expected in the script operation. If the types don't match, + * exception is thrown and the box spending (protected by the script) fails. * - * @param values - key-value pairs + * @param values internal container of the key-value pairs */ case class ContextExtension(values: Map[Byte, EvaluatedValue[_ <: SType]]) { def add(bindings: (Byte, EvaluatedValue[_ <: SType])*): ContextExtension = @@ -25,27 +30,57 @@ object ContextExtension { object serializer extends SigmaSerializer[ContextExtension, ContextExtension] { override def serialize(obj: ContextExtension, w: SigmaByteWriter): Unit = { - w.putUByte(obj.values.size) + val size = obj.values.size + if (size > Byte.MaxValue) + error(s"Number of ContextExtension values $size exceeds ${Byte.MaxValue}.") + w.putUByte(size) obj.values.foreach { case (id, v) => w.put(id).putValue(v) } } override def parse(r: SigmaByteReader): ContextExtension = { val extSize = r.getByte() + if (extSize < 0) + error(s"Negative amount of context extension values: $extSize") val ext = (0 until extSize) .map(_ => (r.getByte(), r.getValue().asInstanceOf[EvaluatedValue[_ <: SType]])) .toMap[Byte, EvaluatedValue[_ <: SType]] ContextExtension(ext) } + } + } +/** Base class of the context passed to verifier and prover. + * @see [[sigmastate.interpreter.Interpreter]] + */ trait InterpreterContext { + /** Prover-defined key-value pairs, that may be used inside a script. */ val extension: ContextExtension + + /** Validation parameters passed to Interpreter.verify to detect soft-fork conditions. */ val validationSettings: SigmaValidationSettings + + /** Hard limit on accumulated execution cost. Exceeding it leads to CostLimitException + * to be thrown. + */ val costLimit: Long + + /** Initial value of execution cost already accumulated before `Interpreter.verify`(or + * `prove`) is called. + */ val initCost: Long + /** Maximum version of ErgoTree currently activated on the network. The activation is + * performed via miners voting. + * The maximum version supported by the interpreter is defined by + * `Interpreter.MaxSupportedScriptVersion`. As a result, the execution of the + * `Interpreter.verify` method depends on the relation between + * max supported and activated version. (see docs/aot-jit-switch.md). + */ + def activatedScriptVersion: Byte + /** Creates a new instance with costLimit updated with given value. */ def withCostLimit(newCostLimit: Long): InterpreterContext @@ -73,3 +108,4 @@ trait InterpreterContext { */ def toSigmaContext(isCost: Boolean, extensions: Map[Byte, AnyValue] = Map()): sigma.Context } + diff --git a/sigmastate/src/main/scala/sigmastate/serialization/SigmaSerializer.scala b/sigmastate/src/main/scala/sigmastate/serialization/SigmaSerializer.scala index 6e9dc86f4a..c486cf34bb 100644 --- a/sigmastate/src/main/scala/sigmastate/serialization/SigmaSerializer.scala +++ b/sigmastate/src/main/scala/sigmastate/serialization/SigmaSerializer.scala @@ -17,24 +17,30 @@ object SigmaSerializer { val MaxPropositionSize: Int = SigmaConstants.MaxPropositionBytes.value val MaxTreeDepth: Int = SigmaConstants.MaxTreeDepth.value - /** Helper function to be use in serializers. + /** Helper function to be use in serializers. * Starting position is marked and then used to compute number of consumed bytes. * val r = Serializer.startReader(bytes, pos) * val obj = r.getValue() - * obj -> r.consumed */ - def startReader(bytes: Array[Byte], pos: Int = 0): SigmaByteReader = { + * obj -> r.consumed + */ + def startReader(bytes: Array[Byte], + pos: Int = 0): SigmaByteReader = { val buf = ByteBuffer.wrap(bytes) buf.position(pos) - val r = new SigmaByteReader(new VLQByteBufferReader(buf), + val r = new SigmaByteReader( + new VLQByteBufferReader(buf), new ConstantStore(), resolvePlaceholdersToConstants = false, - maxTreeDepth = MaxTreeDepth).mark() + maxTreeDepth = MaxTreeDepth + ).mark() r } + /** Helper function to be use in serializers. */ def startReader(bytes: Array[Byte], constantStore: ConstantStore, - resolvePlaceholdersToConstants: Boolean)(implicit vs: SigmaValidationSettings): SigmaByteReader = { + resolvePlaceholdersToConstants: Boolean) + (implicit vs: SigmaValidationSettings): SigmaByteReader = { val buf = ByteBuffer.wrap(bytes) val r = new SigmaByteReader(new VLQByteBufferReader(buf), constantStore, diff --git a/sigmastate/src/main/scala/sigmastate/utils/SigmaByteReader.scala b/sigmastate/src/main/scala/sigmastate/utils/SigmaByteReader.scala index cf51dd8b5d..c736dc1d0a 100644 --- a/sigmastate/src/main/scala/sigmastate/utils/SigmaByteReader.scala +++ b/sigmastate/src/main/scala/sigmastate/utils/SigmaByteReader.scala @@ -8,6 +8,18 @@ import sigmastate.serialization._ import scorex.util.Extensions._ import spire.syntax.all.cfor +/** Reader used in the concrete implementations of [[SigmaSerializer]]. + * It decorates the given reader, delegates most of the methods to it, but also adds new + * methods. + * + * @param r the underlying reader this reader reads from + * @param constantStore the store of constants which is used to resolve + * [[sigmastate.Values.ConstantPlaceholder]] + * @param resolvePlaceholdersToConstants if true then resolved constants will be + * substituted in the tree instead of the placeholder. + * @param maxTreeDepth limit on the tree depth (recursive invocations) + * of the deserializer + */ class SigmaByteReader(val r: Reader, var constantStore: ConstantStore, var resolvePlaceholdersToConstants: Boolean, diff --git a/sigmastate/src/test/scala/org/ergoplatform/ErgoAddressSpecification.scala b/sigmastate/src/test/scala/org/ergoplatform/ErgoAddressSpecification.scala index bc4d2e733f..3db081079f 100644 --- a/sigmastate/src/test/scala/org/ergoplatform/ErgoAddressSpecification.scala +++ b/sigmastate/src/test/scala/org/ergoplatform/ErgoAddressSpecification.scala @@ -11,7 +11,7 @@ import sigmastate.basics.DLogProtocol.DLogProverInput import sigmastate.serialization.ErgoTreeSerializer.DefaultSerializer import sigmastate.serialization.ValueSerializer import scorex.util.encode.Base58 -import sigmastate.{SigmaAnd, SType} +import sigmastate.{SigmaAnd, SType, CrossVersionProps} import sigmastate.Values.{UnparsedErgoTree, Constant, EvaluatedValue, ByteArrayConstant, IntConstant, ErgoTree} import sigmastate.eval.IRContext import sigmastate.helpers._ @@ -23,7 +23,8 @@ import sigmastate.lang.exceptions.{CosterException, CostLimitException} import sigmastate.utils.Helpers._ import special.sigma.SigmaDslTesting -class ErgoAddressSpecification extends SigmaDslTesting with TryValues { +class ErgoAddressSpecification extends SigmaDslTesting + with TryValues with CrossVersionProps { private implicit val ergoAddressEncoder: ErgoAddressEncoder = new ErgoAddressEncoder(TestnetNetworkPrefix) @@ -186,7 +187,7 @@ class ErgoAddressSpecification extends SigmaDslTesting with TryValues { def testPay2SHAddress(address: Pay2SHAddress, scriptBytes: Array[Byte])(implicit IR: IRContext) = { val scriptId = 1.toByte val boxToSpend = testBox(10, address.script, creationHeight = 5) - val ctx = ErgoLikeContextTesting.dummy(boxToSpend) + val ctx = ErgoLikeContextTesting.dummy(boxToSpend, activatedVersionInTests) .withExtension(ContextExtension(Seq( scriptId -> ByteArrayConstant(scriptBytes) // provide script bytes in context variable ).toMap)) @@ -217,7 +218,7 @@ class ErgoAddressSpecification extends SigmaDslTesting with TryValues { def testPay2SHAddress(address: Pay2SHAddress, script: (Byte, EvaluatedValue[_ <: SType]), costLimit: Int = ScriptCostLimit.value): CostedProverResult = { val boxToSpend = testBox(10, address.script, creationHeight = 5) - val ctx = copyContext(ErgoLikeContextTesting.dummy(boxToSpend) + val ctx = copyContext(ErgoLikeContextTesting.dummy(boxToSpend, activatedVersionInTests) .withExtension(ContextExtension(Seq( script // provide script bytes in context variable ).toMap)))(costLimit = costLimit) diff --git a/sigmastate/src/test/scala/org/ergoplatform/ErgoLikeTransactionSpec.scala b/sigmastate/src/test/scala/org/ergoplatform/ErgoLikeTransactionSpec.scala index bd7a01cccc..66b942b531 100644 --- a/sigmastate/src/test/scala/org/ergoplatform/ErgoLikeTransactionSpec.scala +++ b/sigmastate/src/test/scala/org/ergoplatform/ErgoLikeTransactionSpec.scala @@ -6,12 +6,13 @@ import scorex.crypto.hash.Digest32 import scorex.util.{Random, ModifierId} import sigmastate.SCollection.SByteArray import sigmastate.{SSigmaProp, SPair, SInt, TrivialProp, SType} -import sigmastate.Values.{LongConstant, FalseLeaf, ConstantNode, SigmaPropConstant, ConstantPlaceholder, TrueSigmaProp, ByteArrayConstant, ErgoTree} +import sigmastate.Values.{LongConstant, FalseLeaf, ConstantNode, SigmaPropConstant, ConstantPlaceholder, TrueSigmaProp, ByteArrayConstant, IntConstant, ErgoTree} import sigmastate.interpreter.{ProverResult, ContextExtension} import sigmastate.serialization.SigmaSerializer import sigmastate.eval._ import sigmastate.eval.Extensions._ import sigmastate.SType._ +import sigmastate.helpers.TestingHelpers.copyTransaction import sigmastate.utils.Helpers import special.sigma.SigmaDslTesting @@ -270,4 +271,33 @@ class ErgoLikeTransactionSpec extends SigmaDslTesting { } } + property("context extension serialization") { + forAll { (tx: ErgoLikeTransaction, startIndex: Byte, endIndex: Byte) => + whenever(endIndex >= startIndex) { + val idRange = endIndex - startIndex + + val ce = ContextExtension(startIndex.to(endIndex).map(id => id.toByte -> IntConstant(4)).toMap) + val wrongInput = Input(tx.inputs.head.boxId, ProverResult(Array.emptyByteArray, ce)) + val ins = IndexedSeq(wrongInput) ++ tx.inputs.tail + val tx2 = copyTransaction(tx)(inputs = ins) + + def roundtrip() = { + val bs = ErgoLikeTransactionSerializer.toBytes(tx2) + val restored = ErgoLikeTransactionSerializer.parse( + SigmaSerializer.startReader(bs, 0) + ) + restored.inputs.head.extension.values.size shouldBe tx2.inputs.head.extension.values.size + } + + if(idRange < 127) { + roundtrip() + } else { + assertExceptionThrown( + roundtrip(), + { _ => true } + ) + } + } + } + } } diff --git a/sigmastate/src/test/scala/org/ergoplatform/ErgoScriptPredefSpec.scala b/sigmastate/src/test/scala/org/ergoplatform/ErgoScriptPredefSpec.scala index f0f9b17495..a3b099b478 100644 --- a/sigmastate/src/test/scala/org/ergoplatform/ErgoScriptPredefSpec.scala +++ b/sigmastate/src/test/scala/org/ergoplatform/ErgoScriptPredefSpec.scala @@ -23,7 +23,7 @@ import sigmastate.utils.Helpers._ import scala.util.Try -class ErgoScriptPredefSpec extends SigmaTestingCommons { +class ErgoScriptPredefSpec extends SigmaTestingCommons with CrossVersionProps { private implicit lazy val IR: TestingIRContext = new TestingIRContext { override val okPrintEvaluatedEntries: Boolean = false } @@ -56,7 +56,7 @@ class ErgoScriptPredefSpec extends SigmaTestingCommons { minerPubkey = pk, boxesToSpend = inputBoxes, spendingTransaction, - self = inputBox) + self = inputBox, activatedVersionInTests) val pr = prover.prove(emptyEnv + (ScriptNameProp -> "boxCreationHeight_prove"), prop, ctx, fakeMessage).get verifier.verify(emptyEnv + (ScriptNameProp -> "boxCreationHeight_verify"), prop, ctx, pr, fakeMessage).get._1 shouldBe true } @@ -114,7 +114,7 @@ class ErgoScriptPredefSpec extends SigmaTestingCommons { minerPubkey = ErgoLikeContextTesting.dummyPubkey, boxesToSpend = inputBoxes, spendingTransaction, - self = inputBoxes.head) + self = inputBoxes.head, activatedVersionInTests) val pr = prover.prove(emptyEnv + (ScriptNameProp -> "checkSpending_prove"), prop, ctx, fakeMessage).get verifier.verify(emptyEnv + (ScriptNameProp -> "checkSpending_verify"), prop, ctx, pr, fakeMessage).get._1 shouldBe true } @@ -135,14 +135,14 @@ class ErgoScriptPredefSpec extends SigmaTestingCommons { minerPubkey = ErgoLikeContextTesting.dummyPubkey, boxesToSpend = inputBoxes, spendingTransaction, - self = inputBoxes.head) + self = inputBoxes.head, activatedVersionInTests) val prevBlockCtx = ErgoLikeContextTesting( currentHeight = inputBoxes.head.creationHeight + settings.minerRewardDelay - 1, lastBlockUtxoRoot = AvlTreeData.dummy, minerPubkey = ErgoLikeContextTesting.dummyPubkey, boxesToSpend = inputBoxes, spendingTransaction, - self = inputBoxes.head) + self = inputBoxes.head, activatedVersionInTests) // should not be able to collect before minerRewardDelay val prove = prover.prove(emptyEnv + (ScriptNameProp -> "rewardOutputScript_prove"), prop, ctx, fakeMessage).get @@ -224,7 +224,8 @@ class ErgoScriptPredefSpec extends SigmaTestingCommons { minerPubkey = ErgoLikeContextTesting.dummyPubkey, boxesToSpend = inputBoxes, spendingTransaction, - self = inputBoxes.head).withCostLimit(CostTable.ScriptLimit * 10) + self = inputBoxes.head, + activatedVersionInTests).withCostLimit(CostTable.ScriptLimit * 10) val pr = prover.prove(emptyEnv + (ScriptNameProp -> "tokenThresholdScript_prove"), prop, ctx, fakeMessage).getOrThrow verifier.verify(emptyEnv + (ScriptNameProp -> "tokenThresholdScript_verify"), prop, ctx, pr, fakeMessage).getOrThrow._1 shouldBe true @@ -301,7 +302,7 @@ class ErgoScriptPredefSpec extends SigmaTestingCommons { minerPubkey = pkBytes, boxesToSpend = inputBoxes, spendingTransaction, - self = inputBoxes.head) + self = inputBoxes.head, activatedVersionInTests) val pr = prover.prove(emptyEnv + (ScriptNameProp -> "checkRewardTx_prove"), prop, ctx, fakeMessage).getOrThrow verifier.verify(emptyEnv + (ScriptNameProp -> "checkRewardTx_verify"), prop, ctx, pr, fakeMessage).getOrThrow._1 shouldBe true spendingTransaction diff --git a/sigmastate/src/test/scala/org/ergoplatform/dsl/TestContractSpec.scala b/sigmastate/src/test/scala/org/ergoplatform/dsl/TestContractSpec.scala index b63e9dbf3d..cccf35a72a 100644 --- a/sigmastate/src/test/scala/org/ergoplatform/dsl/TestContractSpec.scala +++ b/sigmastate/src/test/scala/org/ergoplatform/dsl/TestContractSpec.scala @@ -84,7 +84,8 @@ case class TestContractSpec(testSuite: SigmaTestingCommons)(implicit val IR: IRC dataBoxes = dataBoxes, boxesToSpend = boxesToSpend, spendingTransaction = createTransaction(dataBoxes, tx.outputs.map(_.ergoBox).toIndexedSeq), - selfIndex = boxesToSpend.indexOf(utxoBox.ergoBox) ) + selfIndex = boxesToSpend.indexOf(utxoBox.ergoBox), + activatedVersion = testSuite.activatedVersionInTests) ctx } def runDsl(extensions: Map[Byte, AnyValue] = Map()): SigmaProp = { diff --git a/sigmastate/src/test/scala/sigmastate/CalcSha256Specification.scala b/sigmastate/src/test/scala/sigmastate/CalcSha256Specification.scala index 5c86926b8c..7062c0153a 100644 --- a/sigmastate/src/test/scala/sigmastate/CalcSha256Specification.scala +++ b/sigmastate/src/test/scala/sigmastate/CalcSha256Specification.scala @@ -1,12 +1,12 @@ package sigmastate -import org.ergoplatform.ErgoLikeContext import org.scalatest.prop.TableFor2 import scorex.util.encode.Base16 import sigmastate.Values.{ByteArrayConstant, CollectionConstant} import sigmastate.helpers.{ContextEnrichingTestProvingInterpreter, ErgoLikeContextTesting, SigmaTestingCommons} -class CalcSha256Specification extends SigmaTestingCommons { +class CalcSha256Specification extends SigmaTestingCommons + with CrossVersionProps { implicit lazy val IR = new TestingIRContext def stringToByteConstant(in: String): CollectionConstant[SByte.type] = ByteArrayConstant(in.getBytes("UTF-8")) @@ -29,7 +29,7 @@ class CalcSha256Specification extends SigmaTestingCommons { property("CalcSha256: Should pass standard tests.") { val int = new ContextEnrichingTestProvingInterpreter() - val ctx = ErgoLikeContextTesting.dummy(fakeSelf) + val ctx = ErgoLikeContextTesting.dummy(fakeSelf, activatedVersionInTests) forAll(objects) { (in, result) => val expectedResult = decodeString(result) val calcSha256 = EQ(CalcSha256(stringToByteConstant(in)), expectedResult) diff --git a/sigmastate/src/test/scala/sigmastate/CostingSpecification.scala b/sigmastate/src/test/scala/sigmastate/CostingSpecification.scala index 4a3da0ad2b..ce20a30ea4 100644 --- a/sigmastate/src/test/scala/sigmastate/CostingSpecification.scala +++ b/sigmastate/src/test/scala/sigmastate/CostingSpecification.scala @@ -1,13 +1,12 @@ package sigmastate import org.ergoplatform.SigmaConstants.ScriptCostLimit -import org.ergoplatform.ErgoScriptPredef.TrueProp import org.ergoplatform.validation.ValidationRules import org.ergoplatform.{ErgoLikeContext, ErgoBox} import scorex.crypto.authds.avltree.batch.Lookup import scorex.crypto.authds.{ADDigest, ADKey} import scorex.crypto.hash.Blake2b256 -import sigmastate.Values.{TrueLeaf, BigIntConstant, AvlTreeConstant, ConstantPlaceholder, ByteArrayConstant, IntConstant, ErgoTree, BooleanConstant} +import sigmastate.Values._ import sigmastate.eval.Extensions._ import sigmastate.eval.Sized._ import sigmastate.eval._ @@ -19,7 +18,7 @@ import sigmastate.utxo.CostTable import sigmastate.utxo.CostTable._ import special.sigma.{SigmaTestingData, AvlTree} -class CostingSpecification extends SigmaTestingData { +class CostingSpecification extends SigmaTestingData with CrossVersionProps { implicit lazy val IR = new TestingIRContext { // override val okPrintEvaluatedEntries = true substFromCostTable = false @@ -55,37 +54,56 @@ class CostingSpecification extends SigmaTestingData { 3.toByte -> BigIntConstant(BigInt("12345678901").bigInteger) )) val tokenId = Blake2b256("tokenA") - val selfBox = createBox(0, TrueProp, Seq(tokenId -> 10L), - Map(ErgoBox.R4 -> ByteArrayConstant(Array[Byte](1, 2, 3)), - ErgoBox.R5 -> IntConstant(3), - ErgoBox.R6 -> AvlTreeConstant(avlTree))) - lazy val outBoxA = testBox(10, pkA, 0) - lazy val outBoxB = testBox(20, pkB, 0) - lazy val tx = createTransaction(IndexedSeq(dataBox), IndexedSeq(outBoxA, outBoxB)) - lazy val context = - new ErgoLikeContext( + + class TestData { + val headerFlags = ErgoTree.headerWithVersion(ergoTreeVersionInTests) + val selfBox = createBox(0, + ErgoTree.withoutSegregation(headerFlags, TrueSigmaProp), + Seq(tokenId -> 10L), + Map(ErgoBox.R4 -> ByteArrayConstant(Array[Byte](1, 2, 3)), + ErgoBox.R5 -> IntConstant(3), + ErgoBox.R6 -> AvlTreeConstant(avlTree))) + val outBoxA = testBox(10, ErgoTree.fromSigmaBoolean(headerFlags, pkA), 0) + val outBoxB = testBox(20, ErgoTree.fromSigmaBoolean(headerFlags, pkB), 0) + val dataBox = createBox(1000, + ErgoTree.withoutSegregation(headerFlags, TrueSigmaProp), + Seq(tokenId1 -> 10L, tokenId2 -> 20L), + Map(ErgoBox.R4 -> IntConstant(100), ErgoBox.R5 -> BooleanConstant(true))) + val tx = createTransaction(IndexedSeq(dataBox), IndexedSeq(outBoxA, outBoxB)) + val context = new ErgoLikeContext( lastBlockUtxoRoot = header2.stateRoot.asInstanceOf[CAvlTree].treeData, headers = headers, preHeader = preHeader, dataBoxes = IndexedSeq(dataBox), boxesToSpend = IndexedSeq(selfBox), - spendingTransaction = tx, selfIndex = 0, extension, ValidationRules.currentSettings, ScriptCostLimit.value, CostTable.interpreterInitCost) - - def cost(script: String)(expCost: Int): Unit = { - val ergoTree = compiler.compile(env, script) - val res = interpreter.reduceToCrypto(context, env, ergoTree).get._2 - if (printCosts) - println(script + s" --> cost $res") - res shouldBe ((expCost * CostTable.costFactorIncrease / CostTable.costFactorDecrease) + CostTable.interpreterInitCost).toLong + spendingTransaction = tx, selfIndex = 0, extension, + ValidationRules.currentSettings, ScriptCostLimit.value, + CostTable.interpreterInitCost, activatedVersionInTests + ) + + def cost(script: String)(expCost: Int): Unit = { + val ergoTree = compiler.compile(env, script) + val res = interpreter.reduceToCrypto(context, env, ergoTree).get._2 + if (printCosts) + println(script + s" --> cost $res") + res shouldBe ((expCost * CostTable.costFactorIncrease / CostTable.costFactorDecrease) + CostTable.interpreterInitCost).toLong + } + + val ContextVarAccess = getVarCost + selectField // `getVar(id)` + `.get` + val RegisterAccess = accessRegister + selectField // `getReg(id)` + `.get` + val GTConstCost = comparisonCost + constCost + val LengthGTConstCost = collLength + GTConstCost + val LengthGTCost = collLength + comparisonCost // can be used when constCost is already accumulated + + val OutputsCost = selectField + accessBox * tx.outputs.length + val InputsCost = selectField + accessBox * context.boxesToSpend.length + val DataInputsCost = selectField + accessBox * context.dataBoxes.length + val HeadersCost = selectField + val PreHeaderCost = selectField + val AccessHeaderCost = selectField + collByIndex + constCost } - val ContextVarAccess = getVarCost + selectField // `getVar(id)` + `.get` - val RegisterAccess = accessRegister + selectField // `getReg(id)` + `.get` - val GTConstCost = comparisonCost + constCost - val LengthGTConstCost = collLength + GTConstCost - val LengthGTCost = collLength + comparisonCost // can be used when constCost is already accumulated - property("basic (smoke) tests") { - + val d = new TestData; import d._ cost("{ getVar[Boolean](2).get }")(ContextVarAccess) cost("{ getVar[Int](1).get > 1 }")(ContextVarAccess + GTConstCost) @@ -102,6 +120,7 @@ class CostingSpecification extends SigmaTestingData { } property("logical op costs") { + val d = new TestData; import d._ cost("{ val cond = getVar[Boolean](2).get; cond && cond }")(ContextVarAccess + logicCost) cost("{ val cond = getVar[Boolean](2).get; cond || cond }")(ContextVarAccess + logicCost) cost("{ val cond = getVar[Boolean](2).get; cond || cond && true }")(ContextVarAccess + logicCost * 2 + constCost) @@ -113,27 +132,33 @@ class CostingSpecification extends SigmaTestingData { } property("atLeast costs") { + val d = new TestData; import d._ cost("{ atLeast(2, Coll(pkA, pkB, pkB)) }")( concreteCollectionItemCost * 3 + collToColl + proveDlogEvalCost * 2 + logicCost + constCost) } property("allZK costs") { + val d = new TestData; import d._ cost("{ pkA && pkB }") (proveDlogEvalCost * 2 + sigmaAndCost * 2) } property("anyZK costs") { + val d = new TestData; import d._ cost("{ pkA || pkB }") (proveDlogEvalCost * 2 + sigmaOrCost * 2) } property("blake2b256 costs") { + val d = new TestData; import d._ cost("{ blake2b256(key1).size > 0 }") (constCost + hashPerKb + LengthGTConstCost) } property("sha256 costs") { + val d = new TestData; import d._ cost("{ sha256(key1).size > 0 }") (constCost + hashPerKb + LengthGTConstCost) } property("byteArrayToBigInt") { + val d = new TestData; import d._ cost("{ byteArrayToBigInt(Coll[Byte](1.toByte)) > 0 }")( constCost // byte const + collToColl // concrete collection @@ -142,6 +167,7 @@ class CostingSpecification extends SigmaTestingData { } property("byteArrayToLong") { + val d = new TestData; import d._ cost("{ byteArrayToLong(Coll[Byte](1.toByte, 1.toByte, 1.toByte, 1.toByte, 1.toByte, 1.toByte, 1.toByte, 1.toByte)) > 0 }") ( constCost // byte const + collToColl // concrete collection @@ -150,22 +176,27 @@ class CostingSpecification extends SigmaTestingData { } property("longToByteArray") { + val d = new TestData; import d._ cost("{ longToByteArray(1L).size > 0 }") (constCost + castOp + LengthGTConstCost) } property("decodePoint and GroupElement.getEncoded") { + val d = new TestData; import d._ cost("{ decodePoint(groupGenerator.getEncoded) == groupGenerator }") (selectField + selectField + decodePointCost + comparisonCost) } property("GroupElement.negate") { + val d = new TestData; import d._ cost("{ groupGenerator.negate != groupGenerator }") (selectField + negateGroup + comparisonCost) } property("GroupElement.exp") { + val d = new TestData; import d._ cost("{ groupGenerator.exp(getVar[BigInt](3).get) == groupGenerator }") (selectField + expCost + ContextVarAccess + comparisonCost) } property("SELF box operations cost") { + val d = new TestData; import d._ cost("{ SELF.value > 0 }")(accessBox + extractCost + GTConstCost) cost("{ SELF.id.size > 0 }")(accessBox + extractCost + LengthGTConstCost) cost("{ SELF.tokens.size > 0 }")(accessBox + extractCost + LengthGTConstCost) @@ -173,14 +204,8 @@ class CostingSpecification extends SigmaTestingData { cost("{ SELF.R5[Int].get > 0 }")(accessBox + RegisterAccess + GTConstCost) } - lazy val OutputsCost = selectField + accessBox * tx.outputs.length - lazy val InputsCost = selectField + accessBox * context.boxesToSpend.length - lazy val DataInputsCost = selectField + accessBox * context.dataBoxes.length - lazy val HeadersCost = selectField - lazy val PreHeaderCost = selectField - lazy val AccessHeaderCost = selectField + collByIndex + constCost - property("Global operations cost") { + val d = new TestData; import d._ // TODO costing: related to https://github.com/ScorexFoundation/sigmastate-interpreter/issues/479 // cost("{ groupGenerator.isIdentity > 0 }")(selectField + selectField + GTConstCost) @@ -190,6 +215,7 @@ class CostingSpecification extends SigmaTestingData { } property("Context operations cost") { + val d = new TestData; import d._ cost("{ HEIGHT > 0 }")(selectField + GTConstCost) cost("{ OUTPUTS.size > 0 }")(OutputsCost + LengthGTConstCost) cost("{ INPUTS.size > 0 }")(InputsCost + LengthGTConstCost) @@ -202,6 +228,7 @@ class CostingSpecification extends SigmaTestingData { } property("PreHeader operations cost") { + val d = new TestData; import d._ cost("{ CONTEXT.preHeader.version > 0 }")(PreHeaderCost + selectField + castOp + GTConstCost) cost("{ CONTEXT.preHeader.parentId.size > 0 }")(PreHeaderCost + selectField + LengthGTConstCost) cost("{ CONTEXT.preHeader.timestamp > 0L }")(PreHeaderCost + selectField + GTConstCost) @@ -215,6 +242,7 @@ class CostingSpecification extends SigmaTestingData { } property("Header operations cost") { + val d = new TestData; import d._ val header = "CONTEXT.headers(0)" cost(s"{ $header.id.size > 0 }")(AccessHeaderCost + selectField + LengthGTCost) cost(s"{ $header.version > 0 }")(AccessHeaderCost + selectField + castOp + comparisonCost) @@ -243,6 +271,7 @@ class CostingSpecification extends SigmaTestingData { } property("AvlTree operations cost") { + val d = new TestData; import d._ val rootTree = "LastBlockUtxoRootHash" // cost(s"{ $rootTree.digest.size > 0 }")(AccessRootHash + selectField + LengthGTConstCost) // cost(s"{ $rootTree.enabledOperations > 0 }")(AccessRootHash + selectField + castOp + GTConstCost) @@ -288,6 +317,7 @@ class CostingSpecification extends SigmaTestingData { } property("Coll operations cost") { + val d = new TestData; import d._ val coll = "OUTPUTS" val nOutputs = tx.outputs.length val collBytes = "CONTEXT.headers(0).id" @@ -336,6 +366,7 @@ class CostingSpecification extends SigmaTestingData { } property("Option operations cost") { + val d = new TestData; import d._ val opt = "SELF.R5[Int]" val accessOpt = accessBox + accessRegister cost(s"{ $opt.get > 0 }")(accessOpt + selectField + GTConstCost) @@ -348,10 +379,12 @@ class CostingSpecification extends SigmaTestingData { } property("TrueLeaf cost") { + val d = new TestData; import d._ cost("{ true }")(constCost) } property("ErgoTree with TrueLeaf costs") { + val d = new TestData; import d._ val tree = ErgoTree(16, IndexedSeq(TrueLeaf), BoolToSigmaProp(ConstantPlaceholder(0, SBoolean))) val pr = interpreter.prove(tree, context, fakeMessage).get @@ -372,6 +405,7 @@ class CostingSpecification extends SigmaTestingData { } property("laziness of AND, OR costs") { + val d = new TestData; import d._ cost("{ val cond = getVar[Boolean](2).get; !(!cond && (1 / 0 == 1)) }")( ContextVarAccess + constCost * 2 + logicCost * 3 + multiply + comparisonCost) cost("{ val cond = getVar[Boolean](2).get; (cond || (1 / 0 == 1)) }")( diff --git a/sigmastate/src/test/scala/sigmastate/CrossVersionProps.scala b/sigmastate/src/test/scala/sigmastate/CrossVersionProps.scala new file mode 100644 index 0000000000..ac3bd3c101 --- /dev/null +++ b/sigmastate/src/test/scala/sigmastate/CrossVersionProps.scala @@ -0,0 +1,36 @@ +package sigmastate + +import org.scalatest.{PropSpecLike, Tag} +import org.scalactic.source.Position +import spire.syntax.all.cfor + +trait CrossVersionProps extends PropSpecLike with TestsBase { + + override protected def property(testName: String, testTags: Tag*) + (testFun: => Any) + (implicit pos: Position): Unit = { + + super.property(testName, testTags:_*) { + cfor(0)(_ < activatedVersions.length, _ + 1) { i => + val activatedVersion = activatedVersions(i) + _currActivatedVersion.withValue(activatedVersion) { + + cfor(0)( + i => i < ergoTreeVersions.length && ergoTreeVersions(i) <= activatedVersion, + _ + 1) { j => + val treeVersion = ergoTreeVersions(j) + _currErgoTreeVersion.withValue(treeVersion) { + try testFun + catch { + case t: Throwable => + println(s"ActivatedVersion = $activatedVersion; ErgoTree version = $treeVersion") + throw t + } + } + } + + } + } + } + } +} diff --git a/sigmastate/src/test/scala/sigmastate/FailingToProveSpec.scala b/sigmastate/src/test/scala/sigmastate/FailingToProveSpec.scala index ed166795f3..53a94af830 100644 --- a/sigmastate/src/test/scala/sigmastate/FailingToProveSpec.scala +++ b/sigmastate/src/test/scala/sigmastate/FailingToProveSpec.scala @@ -7,7 +7,8 @@ import org.scalatest.TryValues._ import sigmastate.interpreter.Interpreter.{ScriptNameProp, emptyEnv} import org.ergoplatform.ErgoScriptPredef._ -class FailingToProveSpec extends SigmaTestingCommons { +class FailingToProveSpec extends SigmaTestingCommons + with CrossVersionProps { implicit lazy val IR = new TestingIRContext /** * Both properties should work fine. @@ -42,7 +43,8 @@ class FailingToProveSpec extends SigmaTestingCommons { boxesToSpend = IndexedSeq(selfBox), spendingTransaction = tx, self = selfBox, - minerPubkey = ErgoLikeContextTesting.dummyPubkey) + minerPubkey = ErgoLikeContextTesting.dummyPubkey, + activatedVersion = activatedVersionInTests) val proof = interpreter.prove(emptyEnv + (ScriptNameProp -> "prove"), compiledScript, ctx, fakeMessage).success.value.proof verifier.verify(emptyEnv + (ScriptNameProp -> "verify"), compiledScript, ctx, proof, fakeMessage) should be a 'success } @@ -76,7 +78,8 @@ class FailingToProveSpec extends SigmaTestingCommons { boxesToSpend = IndexedSeq(selfBox), spendingTransaction = tx, self = selfBox, - minerPubkey = ErgoLikeContextTesting.dummyPubkey) + minerPubkey = ErgoLikeContextTesting.dummyPubkey, + activatedVersion = activatedVersionInTests) val proof = interpreter.prove(emptyEnv + (ScriptNameProp -> "prove"), compiledScript, ctx, fakeMessage).success.value.proof verifier.verify(emptyEnv + (ScriptNameProp -> "verify"), compiledScript, ctx, proof, fakeMessage) should be a 'success } diff --git a/sigmastate/src/test/scala/sigmastate/ScriptVersionSwitchSpecification.scala b/sigmastate/src/test/scala/sigmastate/ScriptVersionSwitchSpecification.scala new file mode 100644 index 0000000000..f8dd8a3a8e --- /dev/null +++ b/sigmastate/src/test/scala/sigmastate/ScriptVersionSwitchSpecification.scala @@ -0,0 +1,239 @@ +package sigmastate + +import org.ergoplatform.ErgoBox.AdditionalRegisters +import org.ergoplatform._ +import scorex.util.ModifierId +import sigmastate.Values.ErgoTree.{DefaultHeader, updateVersionBits} +import sigmastate.Values._ +import sigmastate.eval._ +import sigmastate.helpers.ErgoLikeContextTesting +import sigmastate.helpers.TestingHelpers.createBox +import sigmastate.interpreter.{Interpreter, ProverResult} +import sigmastate.lang.exceptions.InterpreterException +import sigmastate.utxo._ +import sigmastate.utils.Helpers._ +import special.collection._ +import special.sigma.{SigmaDslTesting, Box} +import sigmastate.helpers.TestingHelpers._ + +import scala.util.Success + +/** Specification to verify that the interpreter behaves according to docs/aot-jit-switch.md. */ +class ScriptVersionSwitchSpecification extends SigmaDslTesting + with CrossVersionProps { + override implicit val generatorDrivenConfig = PropertyCheckConfiguration(minSuccessful = 30) + implicit def IR = createIR() + + val b1 = CostingBox( + false, + new ErgoBox( + 1L, + new ErgoTree( + 0.toByte, + Vector(), + Right(BoolToSigmaProp(OR(ConcreteCollection(Array(FalseLeaf, AND(ConcreteCollection(Array(FalseLeaf, FalseLeaf), SBoolean))), SBoolean)))) + ), + Coll(), + Map(), + ModifierId @@ ("008677ffff7ff36dff00f68031140400007689ff014c9201ce8000a9ffe6ceff"), + 32767.toShort, + 32827 + ) + ) + + def createErgoTree(headerFlags: Byte)(implicit IR: IRContext): ErgoTree = { + val code = + s"""{ + | val func = { (x: Coll[Box]) => x.filter({(b: Box) => b.value > 1 }) } + | val v = func(getVar[Coll[Box]](1).get) + | val r = SELF.R4[Coll[Box]].get + | sigmaProp(v == r) + |} + """.stripMargin + val env = Interpreter.emptyEnv + + // The following ops are performed by frontend: typecheck, create graphs, compile to Tree + val compiledTree = { + val internalProp = compiler.typecheck(env, code) + val costingRes = getCostingResult(env, internalProp)(IR) + val calcF = costingRes.calcF + val tree = IR.buildTree(calcF) + tree + } + ErgoTree.withSegregation(headerFlags, compiledTree) + } + + def testProve(ergoTree: ErgoTree, activatedScriptVersion: Byte) = { + val tpeA = SCollection(SBox) + val input = Coll[Box](b1) + val newRegisters: AdditionalRegisters = Map( + ErgoBox.R4 -> Constant[SType](Coll[Box]().asInstanceOf[SType#WrappedType], tpeA) + ) + + val ctx = ErgoLikeContextTesting.dummy( + createBox(0, ergoTree, additionalRegisters = newRegisters), + activatedScriptVersion + ).withBindings( + 1.toByte -> Constant[SType](input.asInstanceOf[SType#WrappedType], tpeA) + ).asInstanceOf[ErgoLikeContext] + val prover = new FeatureProvingInterpreter() + val pr = prover.prove(ergoTree, ctx, fakeMessage).getOrThrow + pr + } + + def testVerify(ergoTree: ErgoTree, activatedScriptVersion: Byte) = { + val tpeA = SCollection(SBox) + val input = Coll[Box](b1) + val newRegisters: AdditionalRegisters = Map( + ErgoBox.R4 -> Constant[SType](Coll[Box]().asInstanceOf[SType#WrappedType], tpeA) + ) + + val ctx = ErgoLikeContextTesting.dummy( + createBox(0, ergoTree, additionalRegisters = newRegisters), + activatedScriptVersion + ).withBindings( + 1.toByte -> Constant[SType](input.asInstanceOf[SType#WrappedType], tpeA) + ).asInstanceOf[ErgoLikeContext] + + val verifier = new ErgoLikeInterpreter() { type CTX = ErgoLikeContext } + val pr = ProverResult(ProverResult.empty.proof, ctx.extension) + + // NOTE: exactly this overload should also be called in Ergo + verifier.verify(ergoTree, ctx, pr, fakeMessage).getOrThrow + } + + property("new versions of scripts will require size bit in the header") { + (1 to 7).foreach { version => + assertExceptionThrown( + createErgoTree(headerFlags = updateVersionBits(DefaultHeader, version.toByte)), + { t => + t.isInstanceOf[IllegalArgumentException] && + t.getMessage.contains("For newer version the size bit is required") + }) + } + } + + /** Rule#| SF Status| Block Type| Script Version | Release | Validation Action + * -----|----------|-----------|----------------|---------|-------- + * 1 | inactive | candidate | Script v1 | v4.0 | R4.0-AOT-cost, R4.0-AOT-verify + * 5 | inactive | mined | Script v1 | v4.0 | R4.0-AOT-cost, R4.0-AOT-verify + */ + property("Rules 1,5 | inactive SF | candidate or mined block | Script v1") { + val samples = genSamples[Coll[Box]](collOfN[Box](5), MinSuccessful(20)) + + // this execution corresponds to the normal validation action (R4.0-AOT-cost, R4.0-AOT-verify) + verifyCases( + { + def success[T](v: T, c: Int) = Expected(Success(v), c) + Seq( + (Coll[Box](), success(Coll[Box](), 37297)), + (Coll[Box](b1), success(Coll[Box](), 37397)) + ) + }, + existingFeature({ (x: Coll[Box]) => x.filter({ (b: Box) => b.value > 1 }) }, + "{ (x: Coll[Box]) => x.filter({(b: Box) => b.value > 1 }) }", + FuncValue( + Vector((1, SCollectionType(SBox))), + Filter( + ValUse(1, SCollectionType(SBox)), + FuncValue(Vector((3, SBox)), GT(ExtractAmount(ValUse(3, SBox)), LongConstant(1L))) + ) + )), + preGeneratedSamples = Some(samples)) + } + + /** Rule#| SF Status| Block Type| Script Version | Release | Validation Action + * -----|----------|-----------|----------------|---------|-------- + * 3 | inactive | candidate | Script v2 | v4.0 | skip-pool-tx (cannot handle) + * 7 | inactive | mined | Script v2 | v4.0 | skip-reject (cannot handle) + */ + property("Rules 3, 7 | inactive SF | candidate or mined block | Script v2") { + val headerFlags = ErgoTree.headerWithVersion( 2 /* Script v2 */) + val ergoTree = createErgoTree(headerFlags = headerFlags) + + // the prove is successful (since it is not part of consensus) + testProve(ergoTree, activatedScriptVersion = 1 /* SF Status: inactive */) + + // and verify is rejecting + assertExceptionThrown( + testVerify(ergoTree, activatedScriptVersion = 1 /* SF Status: inactive */), + { t => + t.isInstanceOf[InterpreterException] && + t.getMessage.contains(s"ErgoTree version ${ergoTree.version} is higher than activated 1") + }) + } + + /** Rule#| SF Status| Block Type| Script Version | Release | Validation Action + * -----|----------|-----------|----------------|---------|-------- + * 9 | active | candidate | Script v1 | v4.0 | R4.0-AOT-cost, R4.0-AOT-verify + */ + property("Rule 9 | active SF | candidate block | Script v1") { + val headerFlags = ErgoTree.headerWithVersion( 1 /* Script v1 */) + val ergoTree = createErgoTree(headerFlags = headerFlags) + + // Even though the SF is active and the v2 scripts can be accepted in `mined` blocks + // this test case is for `candidate` block, so we MUST use + // Interpreter.MaxSupportedScriptVersion + + // both prove and verify are accepting with full evaluation + val expectedCost = 5464L + val pr = testProve( + ergoTree, + activatedScriptVersion = Interpreter.MaxSupportedScriptVersion // special case for *candidate* block + ) + pr.proof shouldBe Array.emptyByteArray + pr.cost shouldBe expectedCost + + val (ok, cost) = testVerify( + ergoTree, + activatedScriptVersion = Interpreter.MaxSupportedScriptVersion // special case for *candidate* block + ) + ok shouldBe true + cost shouldBe expectedCost + } + + /** Rule#| SF Status| Block Type| Script Version | Release | Validation Action + * -----|----------|-----------|----------------|---------|-------- + * 11 | active | candidate | Script v2 | v4.0 | skip-pool-tx (cannot handle) + * 15 | active | mined | Script v2 | v4.0 | skip-accept (rely on majority) + */ + property("Rule 11, 15 | active SF | candidate or mined block | Script v2") { + val headerFlags = ErgoTree.headerWithVersion( 2 /* Script v2 */) + val ergoTree = createErgoTree(headerFlags = headerFlags) + + val activatedVersion = 2.toByte // SF Status: active + + // the prove is doing normal reduction and proof generation + val pr = testProve(ergoTree, activatedScriptVersion = activatedVersion) + pr.proof shouldBe Array.emptyByteArray + pr.cost shouldBe 5464 + + // and verify is accepting without evaluation + val expectedCost = 0L + val (ok, cost) = testVerify(ergoTree, activatedScriptVersion = activatedVersion) + ok shouldBe true + cost shouldBe expectedCost + } + + /** Rule#| SF Status| Block Type| Script Version | Release | Validation Action + * -----|----------|-----------|----------------|---------|-------- + * 13 | active | mined | Script v1 | v4.0 | skip-accept (rely on majority) + */ + property("Rule 13 | active SF | mined block | Script v1") { + val headerFlags = ErgoTree.headerWithVersion( 1 /* Script v1 */) + val ergoTree = createErgoTree(headerFlags = headerFlags) + + val activatedVersion = 2.toByte // SF Status: active + + // the prove is doing normal reduction and proof generation + val pr = testProve(ergoTree, activatedScriptVersion = activatedVersion) + pr.proof shouldBe Array.emptyByteArray + pr.cost shouldBe 5464 + + // and verify is accepting without evaluation + val (ok, cost) = testVerify(ergoTree, activatedScriptVersion = activatedVersion) + ok shouldBe true + cost shouldBe 0L + } + +} diff --git a/sigmastate/src/test/scala/sigmastate/SoftForkabilitySpecification.scala b/sigmastate/src/test/scala/sigmastate/SoftForkabilitySpecification.scala index 5cfbf67957..9af961b0db 100644 --- a/sigmastate/src/test/scala/sigmastate/SoftForkabilitySpecification.scala +++ b/sigmastate/src/test/scala/sigmastate/SoftForkabilitySpecification.scala @@ -19,7 +19,8 @@ import sigmastate.utxo.{DeserializeContext, SelectField} import special.sigma.SigmaTestingData import sigmastate.utils.Helpers._ -class SoftForkabilitySpecification extends SigmaTestingData { +class SoftForkabilitySpecification extends SigmaTestingData + with CrossVersionProps { implicit lazy val IR = new TestingIRContext lazy val prover = new ErgoLikeTestProvingInterpreter() @@ -47,7 +48,7 @@ class SoftForkabilitySpecification extends SigmaTestingData { def createContext(h: Int, tx: ErgoLikeTransaction, vs: SigmaValidationSettings) = ErgoLikeContextTesting(h, AvlTreeData.dummy, ErgoLikeContextTesting.dummyPubkey, IndexedSeq(fakeSelf), - tx, fakeSelf, vs = vs) + tx, fakeSelf, vs = vs, activatedVersion = activatedVersionInTests) def proveTx(name: String, tx: ErgoLikeTransaction, vs: SigmaValidationSettings): ProverResult = { val env = Map(ScriptNameProp -> (name + "_prove")) diff --git a/sigmastate/src/test/scala/sigmastate/TestingInterpreterSpecification.scala b/sigmastate/src/test/scala/sigmastate/TestingInterpreterSpecification.scala index ba1c3e3abb..0c58b52a5a 100644 --- a/sigmastate/src/test/scala/sigmastate/TestingInterpreterSpecification.scala +++ b/sigmastate/src/test/scala/sigmastate/TestingInterpreterSpecification.scala @@ -17,7 +17,8 @@ import sigmastate.utils.Helpers._ import scala.util.Random -class TestingInterpreterSpecification extends SigmaTestingCommons { +class TestingInterpreterSpecification extends SigmaTestingCommons + with CrossVersionProps { implicit lazy val IR = new TestingIRContext lazy val prover = new ErgoLikeTestProvingInterpreter() lazy val verifier = new ErgoLikeTestInterpreter @@ -28,7 +29,7 @@ class TestingInterpreterSpecification extends SigmaTestingCommons { ErgoLikeContextTesting(h, AvlTreeData.dummy, ErgoLikeContextTesting.dummyPubkey, IndexedSeq(fakeSelf), ErgoLikeTransaction(IndexedSeq.empty, IndexedSeq.empty), - fakeSelf) + fakeSelf, activatedVersionInTests) property("Reduction to crypto #1") { forAll() { i: Int => diff --git a/sigmastate/src/test/scala/sigmastate/TestsBase.scala b/sigmastate/src/test/scala/sigmastate/TestsBase.scala new file mode 100644 index 0000000000..5450799c02 --- /dev/null +++ b/sigmastate/src/test/scala/sigmastate/TestsBase.scala @@ -0,0 +1,20 @@ +package sigmastate + +import sigmastate.interpreter.Interpreter + +import scala.util.DynamicVariable + +trait TestsBase { + + val activatedVersions: Seq[Byte] = Array[Byte](0, 1) + + private[sigmastate] val _currActivatedVersion = new DynamicVariable[Byte](0) + def activatedVersionInTests: Byte = _currActivatedVersion.value + + val ergoTreeVersions: Seq[Byte] = + (0 to Interpreter.MaxSupportedScriptVersion).map(_.toByte).toArray[Byte] + + private[sigmastate] val _currErgoTreeVersion = new DynamicVariable[Byte](0) + def ergoTreeVersionInTests: Byte = _currErgoTreeVersion.value + +} diff --git a/sigmastate/src/test/scala/sigmastate/eval/ErgoScriptTestkit.scala b/sigmastate/src/test/scala/sigmastate/eval/ErgoScriptTestkit.scala index 593806f3f3..279b517c9b 100644 --- a/sigmastate/src/test/scala/sigmastate/eval/ErgoScriptTestkit.scala +++ b/sigmastate/src/test/scala/sigmastate/eval/ErgoScriptTestkit.scala @@ -4,7 +4,7 @@ import org.ergoplatform.ErgoAddressEncoder.TestnetNetworkPrefix import org.ergoplatform.validation.ValidationSpecification import scala.util.Success -import sigmastate.{AvlTreeData, SType} +import sigmastate.{AvlTreeData, SType, TestsBase} import sigmastate.Values.{EvaluatedValue, SValue, SigmaPropConstant, Value, BigIntArrayConstant} import org.ergoplatform.{Context => _, _} import sigmastate.utxo.CostTable @@ -20,7 +20,7 @@ import sigmastate.serialization.ErgoTreeSerializer.DefaultSerializer import scala.language.implicitConversions trait ErgoScriptTestkit extends ContractsTestkit with LangTests - with ValidationSpecification { self: BaseCtxTests => + with ValidationSpecification with TestsBase { self: BaseCtxTests => implicit lazy val IR: TestContext with IRContext = new TestContext with IRContext with CompiletimeCosting @@ -41,7 +41,7 @@ trait ErgoScriptTestkit extends ContractsTestkit with LangTests minerPubkey = ErgoLikeContextTesting.dummyPubkey, boxesToSpend = IndexedSeq(boxToSpend), spendingTransaction = tx1, - self = boxToSpend, + self = boxToSpend, activatedVersionInTests, extension = ContextExtension(extension)) ergoCtx } @@ -76,6 +76,7 @@ trait ErgoScriptTestkit extends ContractsTestkit with LangTests boxesToSpend = IndexedSeq(boxToSpend), spendingTransaction = tx1, self = boxToSpend, + activatedVersionInTests, extension = ContextExtension(Map( backerPubKeyId -> SigmaPropConstant(backerPubKey), projectPubKeyId -> SigmaPropConstant(projectPubKey), diff --git a/sigmastate/src/test/scala/sigmastate/helpers/ErgoLikeContextTesting.scala b/sigmastate/src/test/scala/sigmastate/helpers/ErgoLikeContextTesting.scala index 97f355331c..2ddd47e30b 100644 --- a/sigmastate/src/test/scala/sigmastate/helpers/ErgoLikeContextTesting.scala +++ b/sigmastate/src/test/scala/sigmastate/helpers/ErgoLikeContextTesting.scala @@ -6,7 +6,7 @@ import org.ergoplatform._ import org.ergoplatform.validation.{ValidationRules, SigmaValidationSettings} import sigmastate.AvlTreeData import sigmastate.eval._ -import sigmastate.interpreter.{ContextExtension, CryptoConstants} +import sigmastate.interpreter.{ContextExtension, CryptoConstants, Interpreter} import sigmastate.serialization.{SigmaSerializer, GroupElementSerializer} import special.collection.Coll import special.sigma.{Box, PreHeader, Header} @@ -41,10 +41,13 @@ object ErgoLikeContextTesting { boxesToSpend: IndexedSeq[ErgoBox], spendingTransaction: ErgoLikeTransactionTemplate[_ <: UnsignedInput], self: ErgoBox, + activatedVersion: Byte, extension: ContextExtension = ContextExtension.empty, vs: SigmaValidationSettings = ValidationRules.currentSettings): ErgoLikeContext = - new ErgoLikeContext(lastBlockUtxoRoot, noHeaders, dummyPreHeader(currentHeight, minerPubkey), noBoxes, - boxesToSpend, spendingTransaction, boxesToSpend.indexOf(self), extension, vs, ScriptCostLimit.value, 0L) + new ErgoLikeContext( + lastBlockUtxoRoot, noHeaders, dummyPreHeader(currentHeight, minerPubkey), noBoxes, + boxesToSpend, spendingTransaction, boxesToSpend.indexOf(self), extension, vs, + ScriptCostLimit.value, initCost = 0L, activatedVersion) def apply(currentHeight: Height, lastBlockUtxoRoot: AvlTreeData, @@ -52,32 +55,20 @@ object ErgoLikeContextTesting { dataBoxes: IndexedSeq[ErgoBox], boxesToSpend: IndexedSeq[ErgoBox], spendingTransaction: ErgoLikeTransactionTemplate[_ <: UnsignedInput], - selfIndex: Int) = - new ErgoLikeContext(lastBlockUtxoRoot, noHeaders, dummyPreHeader(currentHeight, minerPubkey), - dataBoxes, boxesToSpend, spendingTransaction, selfIndex, ContextExtension.empty, ValidationRules.currentSettings, ScriptCostLimit.value, 0L) - - - def dummy(selfDesc: ErgoBox): ErgoLikeContext = ErgoLikeContextTesting(currentHeight = 0, - lastBlockUtxoRoot = AvlTreeData.dummy, dummyPubkey, boxesToSpend = IndexedSeq(selfDesc), - spendingTransaction = ErgoLikeTransaction(IndexedSeq(), IndexedSeq()), self = selfDesc) - - def fromTransaction(tx: ErgoLikeTransaction, - blockchainState: BlockchainState, - boxesReader: ErgoBoxReader, - inputIndex: Int): Try[ErgoLikeContext] = Try { - - val boxes = tx.inputs.map(_.boxId).map(id => boxesReader.byId(id).get) - - val proverExtension = tx.inputs(inputIndex).spendingProof.extension - - ErgoLikeContextTesting(blockchainState.currentHeight, - blockchainState.lastBlockUtxoRoot, - dummyPubkey, - boxes, - tx, - boxes(inputIndex), - proverExtension) - } + selfIndex: Int, + activatedVersion: Byte) = + new ErgoLikeContext( + lastBlockUtxoRoot, noHeaders, dummyPreHeader(currentHeight, minerPubkey), + dataBoxes, boxesToSpend, spendingTransaction, selfIndex, ContextExtension.empty, + ValidationRules.currentSettings, ScriptCostLimit.value, + initCost = 0L, activatedVersion) + + + def dummy(selfDesc: ErgoBox, activatedVersion: Byte): ErgoLikeContext = + ErgoLikeContextTesting(currentHeight = 0, + lastBlockUtxoRoot = AvlTreeData.dummy, dummyPubkey, boxesToSpend = IndexedSeq(selfDesc), + spendingTransaction = ErgoLikeTransaction(IndexedSeq(), IndexedSeq()), self = selfDesc, + activatedVersion = activatedVersion) val noInputs: Array[Box] = Array[Box]() val noOutputs: Array[Box] = Array[Box]() diff --git a/sigmastate/src/test/scala/sigmastate/helpers/ErgoTransactionValidator.scala b/sigmastate/src/test/scala/sigmastate/helpers/ErgoTransactionValidator.scala index 1d1717ff6b..dbd54b450e 100644 --- a/sigmastate/src/test/scala/sigmastate/helpers/ErgoTransactionValidator.scala +++ b/sigmastate/src/test/scala/sigmastate/helpers/ErgoTransactionValidator.scala @@ -11,7 +11,7 @@ class ErgoLikeTestInterpreter(implicit override val IR: IRContext) extends ErgoL override type CTX = ErgoLikeContext } -class ErgoTransactionValidator(implicit IR: IRContext) { +class ErgoTransactionValidator(activatedVersion: Byte)(implicit IR: IRContext) { val verifier = new ErgoLikeTestInterpreter() def validate(tx: ErgoLikeTransaction, @@ -37,7 +37,7 @@ class ErgoTransactionValidator(implicit IR: IRContext) { val context = ErgoLikeContextTesting(blockchainState.currentHeight, blockchainState.lastBlockUtxoRoot, minerPubkey, boxes, - tx, box, proverExtension) + tx, box, activatedVersion, proverExtension) val verificationResult = verifier.verify( emptyEnv + (ScriptNameProp -> s"height_${blockchainState.currentHeight }_verify"), box.ergoTree, context, proof, msg) diff --git a/sigmastate/src/test/scala/sigmastate/helpers/NegativeTesting.scala b/sigmastate/src/test/scala/sigmastate/helpers/NegativeTesting.scala index 82f1a11f10..3fc245b684 100644 --- a/sigmastate/src/test/scala/sigmastate/helpers/NegativeTesting.scala +++ b/sigmastate/src/test/scala/sigmastate/helpers/NegativeTesting.scala @@ -14,7 +14,7 @@ trait NegativeTesting extends Matchers { def assertExceptionThrown(fun: => Any, assertion: Throwable => Boolean, clue: => String = ""): Unit = { try { fun - fail("exception is expected") + fail("exception is expected but hasn't been thrown") } catch { case e: Throwable => diff --git a/sigmastate/src/test/scala/sigmastate/helpers/SigmaTestingCommons.scala b/sigmastate/src/test/scala/sigmastate/helpers/SigmaTestingCommons.scala index d2d7deea37..0d2cf49649 100644 --- a/sigmastate/src/test/scala/sigmastate/helpers/SigmaTestingCommons.scala +++ b/sigmastate/src/test/scala/sigmastate/helpers/SigmaTestingCommons.scala @@ -18,7 +18,7 @@ import sigmastate.interpreter.Interpreter.{ScriptNameProp, ScriptEnv} import sigmastate.interpreter.{CryptoConstants, Interpreter} import sigmastate.lang.{Terms, TransformingSigmaBuilder, SigmaCompiler} import sigmastate.serialization.{ValueSerializer, SigmaSerializer} -import sigmastate.{SGroupElement, SType} +import sigmastate.{SGroupElement, SType, TestsBase} import sigmastate.eval.{CompiletimeCosting, IRContext, Evaluation, _} import sigmastate.interpreter.CryptoConstants.EcPointType import sigmastate.utils.Helpers._ @@ -31,11 +31,13 @@ trait SigmaTestingCommons extends PropSpec with PropertyChecks with GeneratorDrivenPropertyChecks with Matchers with TestUtils with TestContexts with ValidationSpecification - with NegativeTesting { + with NegativeTesting + with TestsBase { val fakeSelf: ErgoBox = createBox(0, TrueProp) - val fakeContext: ErgoLikeContext = ErgoLikeContextTesting.dummy(fakeSelf) + def fakeContext: ErgoLikeContext = + ErgoLikeContextTesting.dummy(fakeSelf, activatedVersionInTests) //fake message, in a real-life a message is to be derived from a spending transaction val fakeMessage = Blake2b256("Hello World") @@ -203,9 +205,11 @@ trait SigmaTestingCommons extends PropSpec val costCtx = calcCtx.copy(isCost = true) (costCtx, calcCtx) case _ => - val ergoCtx = ErgoLikeContextTesting.dummy(createBox(0, TrueProp)) - .withBindings(1.toByte -> Constant[SType](x.asInstanceOf[SType#WrappedType], tpeA)) - .withBindings(bindings: _*) + val ergoCtx = ErgoLikeContextTesting.dummy( + createBox(0, TrueProp), activatedVersionInTests + ).withBindings(1.toByte -> Constant[SType](x.asInstanceOf[SType#WrappedType], tpeA)) + .withBindings(bindings: _*) + val calcCtx = ergoCtx.toSigmaContext(isCost = false).asInstanceOf[CostingDataContext] val costCtx = calcCtx.copy(isCost = true) (costCtx, calcCtx) diff --git a/sigmastate/src/test/scala/sigmastate/helpers/TestingHelpers.scala b/sigmastate/src/test/scala/sigmastate/helpers/TestingHelpers.scala index bd520accd3..119572e737 100644 --- a/sigmastate/src/test/scala/sigmastate/helpers/TestingHelpers.scala +++ b/sigmastate/src/test/scala/sigmastate/helpers/TestingHelpers.scala @@ -3,7 +3,7 @@ package sigmastate.helpers import scorex.crypto.hash.Digest32 import special.collection.Coll import scorex.util.ModifierId -import org.ergoplatform.{ErgoLikeTransactionTemplate, ErgoLikeTransaction, ErgoLikeContext, UnsignedInput, ErgoBox, DataInput, ErgoBoxCandidate} +import org.ergoplatform.{ErgoLikeTransactionTemplate, ErgoLikeTransaction, ErgoLikeContext, UnsignedInput, Input, ErgoBox, DataInput, ErgoBoxCandidate} import sigmastate.Values.ErgoTree import org.ergoplatform.ErgoBox.{AdditionalRegisters, allZerosModifierId, TokenId} import org.ergoplatform.validation.SigmaValidationSettings @@ -56,6 +56,17 @@ object TestingHelpers { new ErgoBox(value, ergoTree, additionalTokens, additionalRegisters, transactionId, index, creationHeight) } + /** Copies the given transaction allowing also to update fields. + * NOTE: it can be used ONLY for instances of ErgoLikeTransaction. + * @tparam T used here to limit use of this method to only ErgoLikeTransaction instances + * @return a new instance of [[ErgoLikeTransaction]]. */ + def copyTransaction[T >: ErgoLikeTransaction <: ErgoLikeTransaction](tx: T)( + inputs: IndexedSeq[Input] = tx.inputs, + dataInputs: IndexedSeq[DataInput] = tx.dataInputs, + outputCandidates: IndexedSeq[ErgoBoxCandidate] = tx.outputCandidates) = { + new ErgoLikeTransaction(inputs, dataInputs, outputCandidates) + } + /** Copies the given context allowing also to update fields. */ def copyContext(ctx: ErgoLikeContext)( lastBlockUtxoRoot: AvlTreeData = ctx.lastBlockUtxoRoot, @@ -68,10 +79,12 @@ object TestingHelpers { extension: ContextExtension = ctx.extension, validationSettings: SigmaValidationSettings = ctx.validationSettings, costLimit: Long = ctx.costLimit, - initCost: Long = ctx.initCost): ErgoLikeContext = { + initCost: Long = ctx.initCost, + activatedScriptVersion: Byte = ctx.activatedScriptVersion): ErgoLikeContext = { new ErgoLikeContext( lastBlockUtxoRoot, headers, preHeader, dataBoxes, boxesToSpend, - spendingTransaction, selfIndex, extension, validationSettings, costLimit, initCost) + spendingTransaction, selfIndex, extension, validationSettings, + costLimit, initCost, activatedScriptVersion) } /** Creates a new box by updating some of the additional registers with the given new bindings. diff --git a/sigmastate/src/test/scala/sigmastate/serialization/BlockSerializerSpecification.scala b/sigmastate/src/test/scala/sigmastate/serialization/BlockSerializerSpecification.scala index 94890a1bb9..c07081b816 100644 --- a/sigmastate/src/test/scala/sigmastate/serialization/BlockSerializerSpecification.scala +++ b/sigmastate/src/test/scala/sigmastate/serialization/BlockSerializerSpecification.scala @@ -3,7 +3,7 @@ package sigmastate.serialization import org.scalacheck.Gen import sigmastate.SType import sigmastate.Values.Constant -import sigmastate.lang.{DeserializationSigmaBuilder, SigmaBuilder} +import sigmastate.lang.{SigmaBuilder, DeserializationSigmaBuilder} class BlockSerializerSpecification extends SerializationSpecification { diff --git a/sigmastate/src/test/scala/sigmastate/serialization/DeserializationResilience.scala b/sigmastate/src/test/scala/sigmastate/serialization/DeserializationResilience.scala index 7d0f9aaf9f..a368f579b0 100644 --- a/sigmastate/src/test/scala/sigmastate/serialization/DeserializationResilience.scala +++ b/sigmastate/src/test/scala/sigmastate/serialization/DeserializationResilience.scala @@ -3,7 +3,7 @@ package sigmastate.serialization import java.nio.ByteBuffer import org.ergoplatform.validation.ValidationException -import org.ergoplatform.{ErgoBoxCandidate, ErgoLikeContext, Outputs} +import org.ergoplatform.{ErgoBoxCandidate, Outputs} import org.scalacheck.Gen import scalan.util.BenchmarkUtil import scorex.util.serialization.{Reader, VLQByteBufferReader} @@ -13,7 +13,7 @@ import sigmastate.eval.Extensions._ import sigmastate.eval._ import sigmastate.helpers.{ErgoLikeContextTesting, ErgoLikeTestInterpreter, SigmaTestingCommons} import sigmastate.interpreter.Interpreter.{ScriptNameProp, emptyEnv} -import sigmastate.interpreter.{ContextExtension, CostedProverResult, CryptoConstants} +import sigmastate.interpreter.{ContextExtension, CryptoConstants, CostedProverResult} import sigmastate.lang.Terms._ import sigmastate.lang.exceptions.{DeserializeCallDepthExceeded, InputSizeLimitExceeded, InvalidTypePrefix, SerializerException} import sigmastate.serialization.OpCodes._ @@ -23,7 +23,8 @@ import sigmastate.utils.Helpers._ import scala.collection.mutable -class DeserializationResilience extends SerializationSpecification with SigmaTestingCommons { +class DeserializationResilience extends SerializationSpecification + with SigmaTestingCommons with CrossVersionProps { implicit lazy val IR: TestingIRContext = new TestingIRContext { // substFromCostTable = false @@ -264,7 +265,7 @@ class DeserializationResilience extends SerializationSpecification with SigmaTes assertExceptionThrown({ val verifier = new ErgoLikeTestInterpreter val pr = CostedProverResult(Array[Byte](), ContextExtension(Map()), 0L) - val ctx = ErgoLikeContextTesting.dummy(fakeSelf) + val ctx = ErgoLikeContextTesting.dummy(fakeSelf, activatedVersionInTests) val (res, calcTime) = BenchmarkUtil.measureTime { verifier.verify(emptyEnv + (ScriptNameProp -> "verify"), ErgoTree(ErgoTree.DefaultHeader, IndexedSeq(), recursiveScript), ctx, pr, fakeMessage) diff --git a/sigmastate/src/test/scala/sigmastate/serialization/ErgoTreeSerializerSpecification.scala b/sigmastate/src/test/scala/sigmastate/serialization/ErgoTreeSerializerSpecification.scala index 65259dd36e..4dd1cb21d4 100644 --- a/sigmastate/src/test/scala/sigmastate/serialization/ErgoTreeSerializerSpecification.scala +++ b/sigmastate/src/test/scala/sigmastate/serialization/ErgoTreeSerializerSpecification.scala @@ -2,7 +2,7 @@ package sigmastate.serialization import java.math.BigInteger -import sigmastate.Values.{ShortConstant, LongConstant, BigIntConstant, SigmaPropValue, IntConstant, ErgoTree, ByteConstant} +import sigmastate.Values.{ShortConstant, BigIntConstant, SigmaPropValue, IntConstant, ErgoTree, ByteConstant} import sigmastate._ import sigmastate.eval.{IRContext, CBigInt} import sigmastate.helpers.SigmaTestingCommons @@ -41,7 +41,9 @@ class ErgoTreeSerializerSpecification extends SerializationSpecification val (_, _, deserializedConstants, treeBytes) = DefaultSerializer .deserializeHeaderWithTreeBytes(SigmaSerializer.startReader(bytes)) deserializedConstants shouldEqual ergoTree.constants - val r = SigmaSerializer.startReader(treeBytes, new ConstantStore(deserializedConstants), + val r = SigmaSerializer.startReader( + treeBytes, + new ConstantStore(deserializedConstants), resolvePlaceholdersToConstants = true) val deserializedTree = ValueSerializer.deserialize(r) deserializedTree shouldEqual tree diff --git a/sigmastate/src/test/scala/sigmastate/serialization/SigSerializerSpecification.scala b/sigmastate/src/test/scala/sigmastate/serialization/SigSerializerSpecification.scala index 751df5c0cf..6adcd7a662 100644 --- a/sigmastate/src/test/scala/sigmastate/serialization/SigSerializerSpecification.scala +++ b/sigmastate/src/test/scala/sigmastate/serialization/SigSerializerSpecification.scala @@ -15,7 +15,8 @@ import sigmastate.utxo.Transformer import scala.util.Random -class SigSerializerSpecification extends SigmaTestingCommons with ObjectGenerators { +class SigSerializerSpecification extends SigmaTestingCommons + with ObjectGenerators with CrossVersionProps { implicit lazy val IR = new TestingIRContext private lazy implicit val arbExprGen: Arbitrary[SigmaBoolean] = Arbitrary(exprTreeGen) @@ -78,7 +79,7 @@ class SigSerializerSpecification extends SigmaTestingCommons with ObjectGenerato minerPubkey = ErgoLikeContextTesting.dummyPubkey, boxesToSpend = IndexedSeq(fakeSelf), spendingTransaction = ErgoLikeTransactionTesting.dummy, - self = fakeSelf) + self = fakeSelf, activatedVersionInTests) .withCostLimit(Long.MaxValue) // To avoid occasional cost limit exceptions which are irrelevant here try { diff --git a/sigmastate/src/test/scala/sigmastate/serialization/generators/ObjectGenerators.scala b/sigmastate/src/test/scala/sigmastate/serialization/generators/ObjectGenerators.scala index 63c6435612..673a7500dd 100644 --- a/sigmastate/src/test/scala/sigmastate/serialization/generators/ObjectGenerators.scala +++ b/sigmastate/src/test/scala/sigmastate/serialization/generators/ObjectGenerators.scala @@ -19,7 +19,7 @@ import sigmastate.basics.ProveDHTuple import sigmastate.eval.Extensions._ import sigmastate.eval.{CostingBox, SigmaDsl, _} import sigmastate.interpreter.CryptoConstants.EcPointType -import sigmastate.interpreter.{ProverResult, ContextExtension, CryptoConstants} +import sigmastate.interpreter.{ProverResult, ContextExtension, CryptoConstants, Interpreter} import sigmastate.lang.TransformingSigmaBuilder._ import sigmastate._ import sigmastate.utxo._ @@ -30,7 +30,10 @@ import scala.collection.JavaConverters._ import scala.collection.mutable.ListBuffer import scala.reflect.ClassTag -trait ObjectGenerators extends TypeGenerators with ValidationSpecification with ConcreteCollectionGenerators { +trait ObjectGenerators extends TypeGenerators + with ValidationSpecification + with ConcreteCollectionGenerators + with TestsBase { val ThresholdLimit = 10 @@ -199,7 +202,7 @@ trait ObjectGenerators extends TypeGenerators with ValidationSpecification with val unsignedShortGen: Gen[Short] = Gen.chooseNum(0, Short.MaxValue).map(_.toShort) val contextExtensionGen: Gen[ContextExtension] = for { - values <- Gen.sequence(contextExtensionValuesGen(0, 3)) + values <- Gen.sequence(contextExtensionValuesGen(0, 5)) } yield ContextExtension(values.asScala.toMap) val serializedProverResultGen: Gen[ProverResult] = for { @@ -786,7 +789,8 @@ trait ObjectGenerators extends TypeGenerators with ValidationSpecification with extension = extension, validationSettings = ValidationRules.currentSettings, costLimit = costLimit, - initCost = initCost + initCost = initCost, + activatedScriptVersion = activatedVersionInTests ) } diff --git a/sigmastate/src/test/scala/sigmastate/utxo/AVLTreeScriptsSpecification.scala b/sigmastate/src/test/scala/sigmastate/utxo/AVLTreeScriptsSpecification.scala index f230460d73..044c0e5777 100644 --- a/sigmastate/src/test/scala/sigmastate/utxo/AVLTreeScriptsSpecification.scala +++ b/sigmastate/src/test/scala/sigmastate/utxo/AVLTreeScriptsSpecification.scala @@ -22,7 +22,8 @@ import special.collection.Coll import special.sigma.{AvlTree, Context} -class AVLTreeScriptsSpecification extends SigmaTestingCommons { suite => +class AVLTreeScriptsSpecification extends SigmaTestingCommons + with CrossVersionProps { suite => import org.ergoplatform.dsl.AvlTreeHelpers._ lazy val spec = TestContractSpec(suite)(new TestingIRContext) lazy val prover = spec.ProvingParty("Alice") @@ -225,7 +226,7 @@ class AVLTreeScriptsSpecification extends SigmaTestingCommons { suite => minerPubkey = ErgoLikeContextTesting.dummyPubkey, boxesToSpend = IndexedSeq(s), spendingTransaction, - self = s) + self = s, activatedVersionInTests) val pr = prover.prove(prop, ctx, fakeMessage).get verifier.verify(prop, ctx, pr, fakeMessage).get._1 shouldBe true @@ -259,7 +260,7 @@ class AVLTreeScriptsSpecification extends SigmaTestingCommons { suite => minerPubkey = ErgoLikeContextTesting.dummyPubkey, boxesToSpend = IndexedSeq(selfBox), createTransaction(testBox(1, recipientProposition, 0)), - self = selfBox) + self = selfBox, activatedVersionInTests) avlProver.performOneOperation(Lookup(treeElements.head._1)) val bigLeafProof = avlProver.generateProof() @@ -336,7 +337,7 @@ class AVLTreeScriptsSpecification extends SigmaTestingCommons { suite => lastBlockUtxoRoot = AvlTreeData.dummy, minerPubkey = ErgoLikeContextTesting.dummyPubkey, boxesToSpend = IndexedSeq(s), - spendingTransaction, self = s) + spendingTransaction, self = s, activatedVersionInTests) val pr = prover.prove(prop, ctx, fakeMessage).get val ctxv = ctx.withExtension(pr.extension) @@ -388,7 +389,7 @@ class AVLTreeScriptsSpecification extends SigmaTestingCommons { suite => lastBlockUtxoRoot = AvlTreeData.dummy, minerPubkey = ErgoLikeContextTesting.dummyPubkey, boxesToSpend = IndexedSeq(s), - spendingTransaction, self = s) + spendingTransaction, self = s, activatedVersionInTests) val pr = prover.prove(env + (ScriptNameProp -> "prove"), prop, ctx, fakeMessage).get val ctxv = ctx.withExtension(pr.extension) diff --git a/sigmastate/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala b/sigmastate/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala index 5af6798676..34c948cd49 100644 --- a/sigmastate/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala +++ b/sigmastate/src/test/scala/sigmastate/utxo/BasicOpsSpecification.scala @@ -18,7 +18,8 @@ import SType.AnyOps import sigmastate.interpreter.CryptoConstants import sigmastate.utils.Helpers._ -class BasicOpsSpecification extends SigmaTestingCommons { +class BasicOpsSpecification extends SigmaTestingCommons + with CrossVersionProps { implicit lazy val IR = new TestingIRContext { override val okPrintEvaluatedEntries: Boolean = false } @@ -81,7 +82,7 @@ class BasicOpsSpecification extends SigmaTestingCommons { val ctx = ErgoLikeContextTesting(currentHeight = 0, lastBlockUtxoRoot = AvlTreeData.dummy, ErgoLikeContextTesting.dummyPubkey, boxesToSpend = IndexedSeq(boxToSpend), - spendingTransaction = tx, self = boxToSpend) + spendingTransaction = tx, self = boxToSpend, activatedVersionInTests) val pr = prover.prove(env + (ScriptNameProp -> s"${name}_prove"), prop, ctx, fakeMessage).getOrThrow diff --git a/sigmastate/src/test/scala/sigmastate/utxo/BlockchainSimulationSpecification.scala b/sigmastate/src/test/scala/sigmastate/utxo/BlockchainSimulationSpecification.scala index 70ebaa4f04..a3a071a341 100644 --- a/sigmastate/src/test/scala/sigmastate/utxo/BlockchainSimulationSpecification.scala +++ b/sigmastate/src/test/scala/sigmastate/utxo/BlockchainSimulationSpecification.scala @@ -1,22 +1,22 @@ package sigmastate.utxo -import java.io.{File, FileWriter} +import java.io.{FileWriter, File} import org.ergoplatform import org.ergoplatform.ErgoBox.TokenId import org.ergoplatform._ import org.scalacheck.Gen -import scorex.crypto.authds.avltree.batch.{BatchAVLProver, Insert, Remove} +import scorex.crypto.authds.avltree.batch.{Remove, BatchAVLProver, Insert} import scorex.crypto.authds.{ADDigest, ADKey, ADValue} -import scorex.crypto.hash.{Blake2b256, Digest32} +import scorex.crypto.hash.{Digest32, Blake2b256} import scorex.util._ -import sigmastate.Values.{IntConstant, LongConstant} -import sigmastate.helpers.{BlockchainState, ErgoLikeContextTesting, ErgoLikeTestProvingInterpreter, ErgoTransactionValidator, SigmaTestingCommons} +import sigmastate.Values.{LongConstant, IntConstant} +import sigmastate.helpers.{ErgoTransactionValidator, ErgoLikeContextTesting, ErgoLikeTestProvingInterpreter, SigmaTestingCommons, BlockchainState} import sigmastate.helpers.TestingHelpers._ import sigmastate.interpreter.ContextExtension import sigmastate.eval._ import sigmastate.interpreter.Interpreter.{ScriptNameProp, emptyEnv} -import sigmastate.{AvlTreeData, AvlTreeFlags, GE} +import sigmastate.{GE, AvlTreeData, AvlTreeFlags, CrossVersionProps} import scala.annotation.tailrec import scala.collection.concurrent.TrieMap @@ -24,7 +24,8 @@ import scala.collection.mutable import scala.util.Try -class BlockchainSimulationSpecification extends SigmaTestingCommons { +class BlockchainSimulationSpecification extends SigmaTestingCommons + with CrossVersionProps { import BlockchainSimulationSpecification._ implicit lazy val IR = new TestingIRContext @@ -43,6 +44,7 @@ class BlockchainSimulationSpecification extends SigmaTestingCommons { IndexedSeq(box), tx, box, + activatedVersionInTests, ContextExtension.empty) val env = emptyEnv + (ScriptNameProp -> s"height_${state.state.currentHeight}_prove") val proverResult = miner.prove(env, box.ergoTree, context, tx.messageToSign).get @@ -54,7 +56,7 @@ class BlockchainSimulationSpecification extends SigmaTestingCommons { } property("apply one valid block") { - val state = ValidationState.initialState() + val state = ValidationState.initialState(activatedVersionInTests) val miner = new ErgoLikeTestProvingInterpreter() val block = generateBlock(state, miner, 0) val updStateTry = state.applyBlock(block) @@ -62,7 +64,7 @@ class BlockchainSimulationSpecification extends SigmaTestingCommons { } property("too costly block") { - val state = ValidationState.initialState() + val state = ValidationState.initialState(activatedVersionInTests) val miner = new ErgoLikeTestProvingInterpreter() val block = generateBlock(state, miner, 0) val updStateTry = state.applyBlock(block, maxCost = 1) @@ -70,7 +72,7 @@ class BlockchainSimulationSpecification extends SigmaTestingCommons { } property("apply many blocks") { - val state = ValidationState.initialState() + val state = ValidationState.initialState(activatedVersionInTests) val miner = new ErgoLikeTestProvingInterpreter() @tailrec @@ -95,7 +97,7 @@ class BlockchainSimulationSpecification extends SigmaTestingCommons { def bench(numberOfBlocks: Int): Unit = { - val state = ValidationState.initialState() + val state = ValidationState.initialState(activatedVersionInTests) val miner = new ErgoLikeTestProvingInterpreter() val (_, time) = (0 until numberOfBlocks).foldLeft(state -> 0L) { case ((s, timeAcc), h) => @@ -185,8 +187,8 @@ object BlockchainSimulationSpecification { } - case class ValidationState(state: BlockchainState, boxesReader: InMemoryErgoBoxReader)(implicit IR: IRContext) { - val validator = new ErgoTransactionValidator + case class ValidationState(state: BlockchainState, boxesReader: InMemoryErgoBoxReader, activatedVersion: Byte)(implicit IR: IRContext) { + val validator = new ErgoTransactionValidator(activatedVersion) def applyBlock(block: Block, maxCost: Int = MaxBlockCost): Try[ValidationState] = Try { val height = state.currentHeight + 1 @@ -203,7 +205,7 @@ object BlockchainSimulationSpecification { boxesReader.applyBlock(block) val newState = BlockchainState(height, state.lastBlockUtxoRoot.copy(digest = boxesReader.digest)) - ValidationState(newState, boxesReader) + ValidationState(newState, boxesReader, activatedVersion) } } @@ -219,7 +221,7 @@ object BlockchainSimulationSpecification { ErgoLikeContextTesting.dummyPubkey ) - def initialState(block: Block = initBlock)(implicit IR: IRContext): ValidationState = { + def initialState(activatedVersion: Byte, block: Block = initBlock)(implicit IR: IRContext): ValidationState = { val keySize = 32 val prover = new BatchProver(keySize, None) @@ -230,7 +232,7 @@ object BlockchainSimulationSpecification { val boxReader = new InMemoryErgoBoxReader(prover) - ValidationState(bs, boxReader).applyBlock(block).get + ValidationState(bs, boxReader, activatedVersion).applyBlock(block).get } } diff --git a/sigmastate/src/test/scala/sigmastate/utxo/CollectionOperationsSpecification.scala b/sigmastate/src/test/scala/sigmastate/utxo/CollectionOperationsSpecification.scala index 470db0f676..5293ef0b59 100644 --- a/sigmastate/src/test/scala/sigmastate/utxo/CollectionOperationsSpecification.scala +++ b/sigmastate/src/test/scala/sigmastate/utxo/CollectionOperationsSpecification.scala @@ -12,7 +12,8 @@ import sigmastate.interpreter.Interpreter.{ScriptNameProp, emptyEnv} import sigmastate.serialization.OpCodes._ import sigmastate.utils.Helpers._ -class CollectionOperationsSpecification extends SigmaTestingCommons { +class CollectionOperationsSpecification extends SigmaTestingCommons + with CrossVersionProps { implicit lazy val IR: TestingIRContext = new TestingIRContext private val reg1 = ErgoBox.nonMandatoryRegisters.head @@ -26,7 +27,7 @@ class CollectionOperationsSpecification extends SigmaTestingCommons { minerPubkey = ErgoLikeContextTesting.dummyPubkey, boxesToSpend = toSpend, spendingTransaction = createTransaction(outputs), - self = selfBox) + self = selfBox, activatedVersionInTests) } private def assertProof(code: String, @@ -103,7 +104,7 @@ class CollectionOperationsSpecification extends SigmaTestingCommons { minerPubkey = ErgoLikeContextTesting.dummyPubkey, boxesToSpend = Array(fakeSelf), spendingTransaction, - self = fakeSelf) + self = fakeSelf, activatedVersionInTests) { val pr = prover.prove(prop, ctx, fakeMessage).get @@ -121,7 +122,7 @@ class CollectionOperationsSpecification extends SigmaTestingCommons { minerPubkey = ErgoLikeContextTesting.dummyPubkey, boxesToSpend = Array(fakeSelf), spendingTransaction = tx2, - self = fakeSelf) + self = fakeSelf, activatedVersionInTests) prover.prove(prop, ctx2, fakeMessage).isFailure shouldBe true } @@ -151,7 +152,7 @@ class CollectionOperationsSpecification extends SigmaTestingCommons { minerPubkey = ErgoLikeContextTesting.dummyPubkey, boxesToSpend = IndexedSeq(fakeSelf), spendingTransaction, - self = fakeSelf) + self = fakeSelf, activatedVersionInTests) val pr = prover.prove(prop, ctx, fakeMessage).get verifier.verify(prop, ctx, pr, fakeMessage).get._1 shouldBe true @@ -181,7 +182,7 @@ class CollectionOperationsSpecification extends SigmaTestingCommons { minerPubkey = ErgoLikeContextTesting.dummyPubkey, boxesToSpend = IndexedSeq(fakeSelf), spendingTransaction, - self = fakeSelf) + self = fakeSelf, activatedVersionInTests) prover.prove(prop, ctx, fakeMessage).isSuccess shouldBe false } @@ -221,7 +222,7 @@ class CollectionOperationsSpecification extends SigmaTestingCommons { minerPubkey = ErgoLikeContextTesting.dummyPubkey, boxesToSpend = IndexedSeq(s), spendingTransaction, - self = s) + self = s, activatedVersionInTests) val pr = prover.prove(emptyEnv + (ScriptNameProp -> "prove"), prop, ctx, fakeMessage).get verifier.verify(emptyEnv + (ScriptNameProp -> "verify"), prop, ctx, pr, fakeMessage).get._1 shouldBe true @@ -264,7 +265,7 @@ class CollectionOperationsSpecification extends SigmaTestingCommons { minerPubkey = ErgoLikeContextTesting.dummyPubkey, boxesToSpend = IndexedSeq(s), spendingTransaction, - self = s) + self = s, activatedVersionInTests) val pr = prover.prove(prop, ctx, fakeMessage).get verifier.verify(prop, ctx, pr, fakeMessage).get._1 shouldBe true @@ -295,7 +296,7 @@ class CollectionOperationsSpecification extends SigmaTestingCommons { minerPubkey = ErgoLikeContextTesting.dummyPubkey, boxesToSpend = IndexedSeq(s), spendingTransaction, - self = s) + self = s, activatedVersionInTests) val pr = prover.prove(prop, ctx, fakeMessage).get verifier.verify(prop, ctx, pr, fakeMessage) diff --git a/sigmastate/src/test/scala/sigmastate/utxo/ComplexSigSpecification.scala b/sigmastate/src/test/scala/sigmastate/utxo/ComplexSigSpecification.scala index 2a88e05826..a12b41e10e 100644 --- a/sigmastate/src/test/scala/sigmastate/utxo/ComplexSigSpecification.scala +++ b/sigmastate/src/test/scala/sigmastate/utxo/ComplexSigSpecification.scala @@ -9,7 +9,8 @@ import sigmastate.helpers.{ContextEnrichingTestProvingInterpreter, ErgoLikeConte import scala.util.Random -class ComplexSigSpecification extends SigmaTestingCommons { +class ComplexSigSpecification extends SigmaTestingCommons + with CrossVersionProps { implicit lazy val IR: TestingIRContext = new TestingIRContext private def proverGen: Gen[ContextEnrichingTestProvingInterpreter] = for { @@ -43,7 +44,7 @@ class ComplexSigSpecification extends SigmaTestingCommons { minerPubkey = ErgoLikeContextTesting.dummyPubkey, boxesToSpend = IndexedSeq(fakeSelf), spendingTransaction = ErgoLikeTransactionTesting.dummy, - self = fakeSelf) + self = fakeSelf, activatedVersionInTests) val prA = proverA.prove(compiledProp, ctx, fakeMessage).get verifier.verify(compiledProp, ctx, prA, fakeMessage).get._1 shouldBe true @@ -76,7 +77,7 @@ class ComplexSigSpecification extends SigmaTestingCommons { minerPubkey = ErgoLikeContextTesting.dummyPubkey, boxesToSpend = IndexedSeq(fakeSelf), spendingTransaction = ErgoLikeTransactionTesting.dummy, - self = fakeSelf) + self = fakeSelf, activatedVersionInTests) val prA = proverA.prove(compiledProp, ctx, fakeMessage).get verifier.verify(compiledProp, ctx, prA, fakeMessage).get._1 shouldBe true @@ -110,7 +111,7 @@ class ComplexSigSpecification extends SigmaTestingCommons { minerPubkey = ErgoLikeContextTesting.dummyPubkey, boxesToSpend = IndexedSeq(fakeSelf), spendingTransaction = ErgoLikeTransactionTesting.dummy, - self = fakeSelf) + self = fakeSelf, activatedVersionInTests) val prA = proverA.prove(compiledProp, ctx, fakeMessage).get verifier.verify(compiledProp, ctx, prA, fakeMessage).get._1 shouldBe true @@ -145,7 +146,7 @@ class ComplexSigSpecification extends SigmaTestingCommons { minerPubkey = ErgoLikeContextTesting.dummyPubkey, boxesToSpend = IndexedSeq(fakeSelf), spendingTransaction = ErgoLikeTransactionTesting.dummy, - self = fakeSelf) + self = fakeSelf, activatedVersionInTests) val prA = proverA.prove(compiledProp, ctx, fakeMessage).get verifier.verify(compiledProp, ctx, prA, fakeMessage).get._1 shouldBe true @@ -176,7 +177,7 @@ class ComplexSigSpecification extends SigmaTestingCommons { minerPubkey = ErgoLikeContextTesting.dummyPubkey, boxesToSpend = IndexedSeq(fakeSelf), spendingTransaction = ErgoLikeTransactionTesting.dummy, - self = fakeSelf) + self = fakeSelf, activatedVersionInTests) proverA.prove(compiledProp, ctx, fakeMessage).isFailure shouldBe true proverB.prove(compiledProp, ctx, fakeMessage).isFailure shouldBe true @@ -217,7 +218,7 @@ class ComplexSigSpecification extends SigmaTestingCommons { minerPubkey = ErgoLikeContextTesting.dummyPubkey, boxesToSpend = IndexedSeq(fakeSelf), spendingTransaction = ErgoLikeTransactionTesting.dummy, - self = fakeSelf) + self = fakeSelf, activatedVersionInTests) proverA.prove(compiledProp, ctx, fakeMessage).isFailure shouldBe true proverB.prove(compiledProp, ctx, fakeMessage).isFailure shouldBe true @@ -254,7 +255,7 @@ class ComplexSigSpecification extends SigmaTestingCommons { minerPubkey = ErgoLikeContextTesting.dummyPubkey, boxesToSpend = IndexedSeq(fakeSelf), spendingTransaction = ErgoLikeTransactionTesting.dummy, - self = fakeSelf) + self = fakeSelf, activatedVersionInTests) proverA.prove(compiledProp, ctx, fakeMessage).isFailure shouldBe true proverB.prove(compiledProp, ctx, fakeMessage).isFailure shouldBe true @@ -287,7 +288,7 @@ class ComplexSigSpecification extends SigmaTestingCommons { minerPubkey = ErgoLikeContextTesting.dummyPubkey, boxesToSpend = IndexedSeq(fakeSelf), spendingTransaction = ErgoLikeTransactionTesting.dummy, - self = fakeSelf) + self = fakeSelf, activatedVersionInTests) proverA.prove(compiledProp, ctx, fakeMessage).isFailure shouldBe true proverB.prove(compiledProp, ctx, fakeMessage).isFailure shouldBe true @@ -327,7 +328,7 @@ class ComplexSigSpecification extends SigmaTestingCommons { minerPubkey = ErgoLikeContextTesting.dummyPubkey, boxesToSpend = IndexedSeq(fakeSelf), spendingTransaction = ErgoLikeTransactionTesting.dummy, - self = fakeSelf) + self = fakeSelf, activatedVersionInTests) proverA.prove(compiledProp, ctx, fakeMessage).isFailure shouldBe true proverB.prove(compiledProp, ctx, fakeMessage).isFailure shouldBe true @@ -368,7 +369,7 @@ class ComplexSigSpecification extends SigmaTestingCommons { minerPubkey = ErgoLikeContextTesting.dummyPubkey, boxesToSpend = IndexedSeq(fakeSelf), spendingTransaction = ErgoLikeTransactionTesting.dummy, - self = fakeSelf) + self = fakeSelf, activatedVersionInTests) proverA.prove(compiledProp, ctx, fakeMessage).isFailure shouldBe true proverB.prove(compiledProp, ctx, fakeMessage).isFailure shouldBe true @@ -412,7 +413,7 @@ class ComplexSigSpecification extends SigmaTestingCommons { minerPubkey = ErgoLikeContextTesting.dummyPubkey, boxesToSpend = IndexedSeq(fakeSelf), spendingTransaction = ErgoLikeTransactionTesting.dummy, - self = fakeSelf) + self = fakeSelf, activatedVersionInTests) val prA = proverA.prove(compiledProp, ctx, fakeMessage).get verifier.verify(compiledProp, ctx, prA, fakeMessage).get._1 shouldBe true @@ -450,7 +451,7 @@ class ComplexSigSpecification extends SigmaTestingCommons { minerPubkey = ErgoLikeContextTesting.dummyPubkey, boxesToSpend = IndexedSeq(fakeSelf), spendingTransaction = ErgoLikeTransactionTesting.dummy, - self = fakeSelf) + self = fakeSelf, activatedVersionInTests) val prA = proverA.prove(compiledProp, ctx1, fakeMessage).get verifier.verify(compiledProp, ctx1, prA, fakeMessage).get._1 shouldBe true val prB = proverB.prove(compiledProp, ctx1, fakeMessage).get @@ -463,7 +464,7 @@ class ComplexSigSpecification extends SigmaTestingCommons { minerPubkey = ErgoLikeContextTesting.dummyPubkey, boxesToSpend = IndexedSeq(fakeSelf), spendingTransaction = ErgoLikeTransactionTesting.dummy, - self = fakeSelf) + self = fakeSelf, activatedVersionInTests) val prC = proverC.prove(compiledProp, ctx2, fakeMessage).get verifier.verify(compiledProp, ctx2, prC, fakeMessage).get._1 shouldBe true } @@ -492,7 +493,7 @@ class ComplexSigSpecification extends SigmaTestingCommons { minerPubkey = ErgoLikeContextTesting.dummyPubkey, boxesToSpend = IndexedSeq(fakeSelf), spendingTransaction = ErgoLikeTransactionTesting.dummy, - self = fakeSelf) + self = fakeSelf, activatedVersionInTests) val prA = proverA.prove(compiledProp, ctx1, fakeMessage).get verifier.verify(compiledProp, ctx1, prA, fakeMessage).get._1 shouldBe true @@ -507,7 +508,7 @@ class ComplexSigSpecification extends SigmaTestingCommons { minerPubkey = ErgoLikeContextTesting.dummyPubkey, boxesToSpend = IndexedSeq(fakeSelf), spendingTransaction = ErgoLikeTransactionTesting.dummy, - self = fakeSelf) + self = fakeSelf, activatedVersionInTests) val prA2 = proverA.prove(compiledProp, ctx2, fakeMessage).get verifier.verify(compiledProp, ctx2, prA2, fakeMessage).get._1 shouldBe true @@ -540,7 +541,7 @@ class ComplexSigSpecification extends SigmaTestingCommons { minerPubkey = ErgoLikeContextTesting.dummyPubkey, boxesToSpend = IndexedSeq(fakeSelf), spendingTransaction = ErgoLikeTransactionTesting.dummy, - self = fakeSelf) + self = fakeSelf, activatedVersionInTests) val prA = proverA.prove(compiledProp, ctx1, fakeMessage).get verifier.verify(compiledProp, ctx1, prA, fakeMessage).get._1 shouldBe true @@ -555,7 +556,7 @@ class ComplexSigSpecification extends SigmaTestingCommons { minerPubkey = ErgoLikeContextTesting.dummyPubkey, boxesToSpend = IndexedSeq(fakeSelf), spendingTransaction = ErgoLikeTransactionTesting.dummy, - self = fakeSelf) + self = fakeSelf, activatedVersionInTests) val prA2 = proverA.prove(compiledProp, ctx2, fakeMessage).get verifier.verify(compiledProp, ctx2, prA2, fakeMessage).get._1 shouldBe true @@ -590,7 +591,7 @@ class ComplexSigSpecification extends SigmaTestingCommons { minerPubkey = ErgoLikeContextTesting.dummyPubkey, boxesToSpend = IndexedSeq(fakeSelf), spendingTransaction = ErgoLikeTransactionTesting.dummy, - self = fakeSelf) + self = fakeSelf, activatedVersionInTests) // any prover alone (no added secrets) should fail allProvers.foreach(_.prove(prop, ctx, fakeMessage).isFailure shouldBe true) diff --git a/sigmastate/src/test/scala/sigmastate/utxo/ContextEnrichingSpecification.scala b/sigmastate/src/test/scala/sigmastate/utxo/ContextEnrichingSpecification.scala index a719c43ade..b073d0f8ab 100644 --- a/sigmastate/src/test/scala/sigmastate/utxo/ContextEnrichingSpecification.scala +++ b/sigmastate/src/test/scala/sigmastate/utxo/ContextEnrichingSpecification.scala @@ -1,6 +1,5 @@ package sigmastate.utxo -import org.ergoplatform.ErgoLikeContext import scorex.util.encode.Base16 import scorex.crypto.hash.Blake2b256 import sigmastate.Values._ @@ -10,7 +9,8 @@ import sigmastate.helpers.{ContextEnrichingTestProvingInterpreter, ErgoLikeConte import special.collection.Coll -class ContextEnrichingSpecification extends SigmaTestingCommons { +class ContextEnrichingSpecification extends SigmaTestingCommons + with CrossVersionProps { implicit lazy val IR: TestingIRContext = new TestingIRContext @@ -31,7 +31,7 @@ class ContextEnrichingSpecification extends SigmaTestingCommons { ) compiledScript shouldBe prop - val ctx = ErgoLikeContextTesting.dummy(fakeSelf) + val ctx = ErgoLikeContextTesting.dummy(fakeSelf, activatedVersionInTests) val pr = prover.prove(compiledScript, ctx, fakeMessage).get val ctxv = ctx.withExtension(pr.extension) @@ -63,7 +63,7 @@ class ContextEnrichingSpecification extends SigmaTestingCommons { ) compiledScript shouldBe prop - val ctx = ErgoLikeContextTesting.dummy(fakeSelf) + val ctx = ErgoLikeContextTesting.dummy(fakeSelf, activatedVersionInTests) val pr = prover.prove(compiledScript, ctx, fakeMessage).get val ctxv = ctx.withExtension(pr.extension) @@ -93,7 +93,7 @@ class ContextEnrichingSpecification extends SigmaTestingCommons { val prop = EQ(Xor(GetVarByteArray(k1).get, GetVarByteArray(k2).get), ByteArrayConstant(r)).toSigmaProp compiledScript shouldBe prop - val ctx = ErgoLikeContextTesting.dummy(fakeSelf) + val ctx = ErgoLikeContextTesting.dummy(fakeSelf, activatedVersionInTests) val pr = prover.prove(prop, ctx, fakeMessage).get val ctxv = ctx.withExtension(pr.extension) @@ -124,7 +124,7 @@ class ContextEnrichingSpecification extends SigmaTestingCommons { val prop = EQ(CalcBlake2b256(GetVarByteArray(1).get), ByteArrayConstant(Blake2b256(preimage.toArray))).toSigmaProp compiledScript shouldBe prop - val ctx = ErgoLikeContextTesting.dummy(fakeSelf) + val ctx = ErgoLikeContextTesting.dummy(fakeSelf, activatedVersionInTests) val pr = prover.prove(prop, ctx, fakeMessage).get val ctxv = ctx.withExtension(pr.extension) @@ -152,7 +152,7 @@ class ContextEnrichingSpecification extends SigmaTestingCommons { ByteArrayConstant(Blake2b256(preimage2.append(preimage1).toArray))).toSigmaProp compiledScript shouldBe prop - val ctx = ErgoLikeContextTesting.dummy(fakeSelf) + val ctx = ErgoLikeContextTesting.dummy(fakeSelf, activatedVersionInTests) val pr = prover.prove(prop, ctx, fakeMessage).get val ctxv = ctx.withExtension(pr.extension) diff --git a/sigmastate/src/test/scala/sigmastate/utxo/DistributedSigSpecification.scala b/sigmastate/src/test/scala/sigmastate/utxo/DistributedSigSpecification.scala index 21517dd96e..008ce2dd0b 100644 --- a/sigmastate/src/test/scala/sigmastate/utxo/DistributedSigSpecification.scala +++ b/sigmastate/src/test/scala/sigmastate/utxo/DistributedSigSpecification.scala @@ -10,12 +10,11 @@ import sigmastate.lang.Terms._ * See EIP-11 for generic signing procedure. * In some simple generic procedure is simplified. */ -class DistributedSigSpecification extends SigmaTestingCommons { +class DistributedSigSpecification extends SigmaTestingCommons + with CrossVersionProps { implicit lazy val IR: TestingIRContext = new TestingIRContext - private val ctx = fakeContext - /** * An example test where Alice (A) and Bob (B) are signing an input in a distributed way. A statement which * protects the box to spend is "pubkey_Alice && pubkey_Bob". Note that a signature in this case is about @@ -34,6 +33,7 @@ class DistributedSigSpecification extends SigmaTestingCommons { * proof ((a_Alice, a_Bob), e, (z_Alice, z_Bob)). */ property("distributed AND (2 out of 2)") { + val ctx = fakeContext val proverA = new ErgoLikeTestProvingInterpreter val proverB = new ErgoLikeTestProvingInterpreter val verifier: ContextEnrichingTestProvingInterpreter = new ContextEnrichingTestProvingInterpreter @@ -63,6 +63,7 @@ class DistributedSigSpecification extends SigmaTestingCommons { // 3-out-of-3 AND signature property("distributed AND (3 out of 3)") { + val ctx = fakeContext val proverA = new ErgoLikeTestProvingInterpreter val proverB = new ErgoLikeTestProvingInterpreter val proverC = new ErgoLikeTestProvingInterpreter @@ -121,6 +122,7 @@ class DistributedSigSpecification extends SigmaTestingCommons { * He's using his randomness from his first step and completes the (valid) signature. */ property("distributed THRESHOLD - 2 out of 3") { + val ctx = fakeContext val proverA = new ErgoLikeTestProvingInterpreter val proverB = new ErgoLikeTestProvingInterpreter val proverC = new ErgoLikeTestProvingInterpreter @@ -155,6 +157,7 @@ class DistributedSigSpecification extends SigmaTestingCommons { * Distributed threshold signature, 3 out of 4 case. */ property("distributed THRESHOLD - 3 out of 4") { + val ctx = fakeContext val proverA = new ErgoLikeTestProvingInterpreter val proverB = new ErgoLikeTestProvingInterpreter val proverC = new ErgoLikeTestProvingInterpreter @@ -203,6 +206,7 @@ class DistributedSigSpecification extends SigmaTestingCommons { * Distributed threshold signature, 3 out of 4 case, 1 real and 1 simulated secrets are of DH kind. */ property("distributed THRESHOLD - 3 out of 4 - w. DH") { + val ctx = fakeContext val proverA = new ErgoLikeTestProvingInterpreter val proverB = new ErgoLikeTestProvingInterpreter val proverC = new ErgoLikeTestProvingInterpreter @@ -248,7 +252,7 @@ class DistributedSigSpecification extends SigmaTestingCommons { } property("distributed THRESHOLD - 2 out of 5") { - + val ctx = fakeContext val proverA = new ErgoLikeTestProvingInterpreter val proverB = new ErgoLikeTestProvingInterpreter val proverC = new ErgoLikeTestProvingInterpreter @@ -285,7 +289,7 @@ class DistributedSigSpecification extends SigmaTestingCommons { } property("distributed THRESHOLD - 4 out of 8 - DH") { - + val ctx = fakeContext val proverA = new ErgoLikeTestProvingInterpreter val proverB = new ErgoLikeTestProvingInterpreter val proverC = new ErgoLikeTestProvingInterpreter @@ -377,6 +381,7 @@ class DistributedSigSpecification extends SigmaTestingCommons { } property("distributed THRESHOLD - (1-out-of-2) and (1-out-of-2) - DLOG and DH") { + val ctx = fakeContext val proverA = new ErgoLikeTestProvingInterpreter val proverB = new ErgoLikeTestProvingInterpreter val proverC = new ErgoLikeTestProvingInterpreter @@ -419,6 +424,7 @@ class DistributedSigSpecification extends SigmaTestingCommons { property("distributed THRESHOLD mixed via AND") { // atLeast(3, Coll(proveDlog(pkA), proveDlog(pkB), proveDlog(pkC), proveDlog(pkD), proveDlog(pkE))) && (proveDlog(pkB) || proveDlog(pkF)) + val ctx = fakeContext val proverA = new ErgoLikeTestProvingInterpreter val proverB = new ErgoLikeTestProvingInterpreter val proverC = new ErgoLikeTestProvingInterpreter diff --git a/sigmastate/src/test/scala/sigmastate/utxo/ErgoLikeInterpreterSpecification.scala b/sigmastate/src/test/scala/sigmastate/utxo/ErgoLikeInterpreterSpecification.scala index 9c2d2c439a..3ea0bf0058 100644 --- a/sigmastate/src/test/scala/sigmastate/utxo/ErgoLikeInterpreterSpecification.scala +++ b/sigmastate/src/test/scala/sigmastate/utxo/ErgoLikeInterpreterSpecification.scala @@ -22,7 +22,8 @@ import sigmastate.serialization.{ValueSerializer, SerializationSpecification} import sigmastate.utils.Helpers._ class ErgoLikeInterpreterSpecification extends SigmaTestingCommons - with SerializationSpecification { + with SerializationSpecification + with CrossVersionProps { implicit lazy val IR: TestingIRContext = new TestingIRContext private val reg1 = ErgoBox.nonMandatoryRegisters.head @@ -36,7 +37,7 @@ class ErgoLikeInterpreterSpecification extends SigmaTestingCommons val h1 = SigmaPropConstant(prover1.dlogSecrets.head.publicImage) val h2 = SigmaPropConstant(prover2.dlogSecrets.head.publicImage) - val ctx = ErgoLikeContextTesting.dummy(fakeSelf) + val ctx = ErgoLikeContextTesting.dummy(fakeSelf, activatedVersionInTests) val e = compile(Map("h1" -> h1.treeWithSegregation.bytes, "h2" -> h2.treeWithSegregation.bytes), "h1 == h1") val exp = TrueLeaf @@ -77,7 +78,7 @@ class ErgoLikeInterpreterSpecification extends SigmaTestingCommons minerPubkey = ErgoLikeContextTesting.dummyPubkey, boxesToSpend = IndexedSeq(fakeSelf), spendingTransaction = ErgoLikeTransactionTesting.dummy, - self = fakeSelf) + self = fakeSelf, activatedVersionInTests) val pr = prover.prove(prop, ctx, fakeMessage).get verifier.verify(prop, ctx, pr, fakeMessage).get._1 shouldBe true @@ -107,7 +108,7 @@ class ErgoLikeInterpreterSpecification extends SigmaTestingCommons minerPubkey = ErgoLikeContextTesting.dummyPubkey, boxesToSpend = IndexedSeq(fakeSelf), spendingTransaction = ErgoLikeTransactionTesting.dummy, - self = fakeSelf) + self = fakeSelf, activatedVersionInTests) val prA = proverA.prove(compiledProp, ctx, fakeMessage).get verifier.verify(compiledProp, ctx, prA, fakeMessage).get._1 shouldBe true @@ -134,7 +135,7 @@ class ErgoLikeInterpreterSpecification extends SigmaTestingCommons minerPubkey = ErgoLikeContextTesting.dummyPubkey, boxesToSpend = IndexedSeq(fakeSelf), spendingTransaction = ErgoLikeTransactionTesting.dummy, - self = fakeSelf) + self = fakeSelf, activatedVersionInTests) val prA = proverA.prove(compiledProp, ctx, fakeMessage).get @@ -189,7 +190,7 @@ class ErgoLikeInterpreterSpecification extends SigmaTestingCommons minerPubkey = ErgoLikeContextTesting.dummyPubkey, boxesToSpend = IndexedSeq(fakeSelf), spendingTransaction, - self = fakeSelf) + self = fakeSelf, activatedVersionInTests) //before timeout val prA = proverA.prove( @@ -252,7 +253,7 @@ class ErgoLikeInterpreterSpecification extends SigmaTestingCommons minerPubkey = ErgoLikeContextTesting.dummyPubkey, boxesToSpend = IndexedSeq(fakeSelf), spendingTransaction, - self = fakeSelf) + self = fakeSelf, activatedVersionInTests) val pr = prover.prove(prop, ctx, fakeMessage).get verifier.verify(prop, ctx, pr, fakeMessage) @@ -282,7 +283,7 @@ class ErgoLikeInterpreterSpecification extends SigmaTestingCommons minerPubkey = ErgoLikeContextTesting.dummyPubkey, boxesToSpend = IndexedSeq(fakeSelf), spendingTransaction, - self = fakeSelf) + self = fakeSelf, activatedVersionInTests) val pr = prover.prove(compiledProp, ctx, fakeMessage).get verifier.verify(compiledProp, ctx, pr, fakeMessage) @@ -318,7 +319,7 @@ class ErgoLikeInterpreterSpecification extends SigmaTestingCommons minerPubkey = ErgoLikeContextTesting.dummyPubkey, boxesToSpend = IndexedSeq(selfBox), createTransaction(testBox(1, recipientProposition, 0)), - self = selfBox) + self = selfBox, activatedVersionInTests) val proof = prover.prove(prop, ctx, fakeMessage).get @@ -362,7 +363,7 @@ class ErgoLikeInterpreterSpecification extends SigmaTestingCommons minerPubkey = ErgoLikeContextTesting.dummyPubkey, boxesToSpend = IndexedSeq(s1), spendingTransaction, - self = s1) + self = s1, activatedVersionInTests) val pr = prover.prove(emptyEnv + (ScriptNameProp -> "prove"), prop, ctx, fakeMessage).getOrThrow verifier.verify(emptyEnv + (ScriptNameProp -> "verify"), prop, ctx, pr, fakeMessage).getOrThrow._1 shouldBe true @@ -377,7 +378,7 @@ class ErgoLikeInterpreterSpecification extends SigmaTestingCommons minerPubkey = ErgoLikeContextTesting.dummyPubkey, boxesToSpend = IndexedSeq(s2), spendingTransaction, - self = s2) + self = s2, activatedVersionInTests) prover.prove(prop, wrongCtx, fakeMessage).isFailure shouldBe true verifier.verify(prop, wrongCtx, pr, fakeMessage).isFailure shouldBe true @@ -412,7 +413,7 @@ class ErgoLikeInterpreterSpecification extends SigmaTestingCommons minerPubkey = ErgoLikeContextTesting.dummyPubkey, boxesToSpend = IndexedSeq(selfBox), createTransaction(testBox(1, recipientProposition, 0)), - self = selfBox) + self = selfBox, activatedVersionInTests) val proof = prover.prove(prop, ctx, fakeMessage).get @@ -465,7 +466,7 @@ class ErgoLikeInterpreterSpecification extends SigmaTestingCommons minerPubkey = ErgoLikeContextTesting.dummyPubkey, boxesToSpend = IndexedSeq(brother, s), spendingTransaction, - self = s) + self = s, activatedVersionInTests) val pr = prover.prove(emptyEnv + (ScriptNameProp -> "prove_prop"), prop, ctx, fakeMessage).getOrThrow verifier.verify(emptyEnv + (ScriptNameProp -> "verify_prop"), prop, ctx, pr, fakeMessage).getOrThrow._1 shouldBe true @@ -476,7 +477,7 @@ class ErgoLikeInterpreterSpecification extends SigmaTestingCommons minerPubkey = ErgoLikeContextTesting.dummyPubkey, boxesToSpend = IndexedSeq(brotherWithWrongId, s), spendingTransaction, - self = s) + self = s, activatedVersionInTests) prover.prove(prop, wrongCtx, fakeMessage).isFailure shouldBe true verifier.verify(prop, wrongCtx, pr, fakeMessage).getOrThrow._1 shouldBe false @@ -545,7 +546,7 @@ class ErgoLikeInterpreterSpecification extends SigmaTestingCommons minerPubkey = ErgoLikeContextTesting.dummyPubkey, boxesToSpend = IndexedSeq(friend, s), spendingTransaction, - self = s) + self = s, activatedVersionInTests) val pr1 = prover.prove(prop, ctx1, fakeMessage).success.value verifier.verify(prop, ctx1, pr1, fakeMessage).success.value._1 shouldBe true @@ -556,7 +557,7 @@ class ErgoLikeInterpreterSpecification extends SigmaTestingCommons minerPubkey = ErgoLikeContextTesting.dummyPubkey, boxesToSpend = IndexedSeq(s, friend), spendingTransaction, - self = s) + self = s, activatedVersionInTests) val pr2 = prover.prove(prop, ctx2, fakeMessage).success.value verifier.verify(prop, ctx2, pr2, fakeMessage).success.value._1 shouldBe true @@ -570,7 +571,7 @@ class ErgoLikeInterpreterSpecification extends SigmaTestingCommons minerPubkey = ErgoLikeContextTesting.dummyPubkey, boxesToSpend = IndexedSeq(friendWithWrongId, s), spendingTransaction, - self = s) + self = s, activatedVersionInTests) prover.prove(prop, wrongCtx1, fakeMessage).isFailure shouldBe true verifier.verify(prop, wrongCtx1, pr1, fakeMessage).success.value._1 shouldBe false @@ -620,7 +621,7 @@ class ErgoLikeInterpreterSpecification extends SigmaTestingCommons minerPubkey = ErgoLikeContextTesting.dummyPubkey, boxesToSpend = IndexedSeq(input0, input1, input2, input3), spendingTransaction, - self = input3) + self = input3, activatedVersionInTests) val pr = prover.prove(emptyEnv + (ScriptNameProp -> "prove"), prop, ctx1, fakeMessage).get verifier.verify(emptyEnv + (ScriptNameProp -> "verify"), prop, ctx1, pr, fakeMessage).get._1 shouldBe true @@ -633,7 +634,7 @@ class ErgoLikeInterpreterSpecification extends SigmaTestingCommons copyBox(input0)(value = 20), // to go through `then` branch of `if` in the script input1, input2, input3), spendingTransaction, - self = input3) + self = input3, activatedVersionInTests) prover.prove(prop, ctx2, fakeMessage).isFailure shouldBe true } @@ -654,7 +655,7 @@ class ErgoLikeInterpreterSpecification extends SigmaTestingCommons minerPubkey = ErgoLikeContextTesting.dummyPubkey, boxesToSpend = IndexedSeq(box), createTransaction(IndexedSeq(testBox(10, TrueProp, 0))), - self = box) + self = box, activatedVersionInTests) an[RuntimeException] should be thrownBy prover.prove(emptyEnv + (ScriptNameProp -> "prove"), prop, ctx, fakeMessage).getOrThrow @@ -679,7 +680,7 @@ class ErgoLikeInterpreterSpecification extends SigmaTestingCommons minerPubkey = ErgoLikeContextTesting.dummyPubkey, boxesToSpend = IndexedSeq(box), createTransaction(IndexedSeq(testBox(10, TrueProp, 0))), - self = box) + self = box, activatedVersionInTests) val pr = prover.prove(prop, ctx, fakeMessage).get // make sure verifier will fail on deserializing context with mismatched type @@ -695,7 +696,7 @@ class ErgoLikeInterpreterSpecification extends SigmaTestingCommons property("DeserializeContext can return expression of non-Boolean/SigmaProp type") { def prove(ergoTree: ErgoTree, script: (Byte, EvaluatedValue[_ <: SType])): CostedProverResult = { val boxToSpend = testBox(10, ergoTree, creationHeight = 5) - val ctx = ErgoLikeContextTesting.dummy(boxToSpend) + val ctx = ErgoLikeContextTesting.dummy(boxToSpend, activatedVersionInTests) .withExtension( ContextExtension(Seq(script).toMap)) // provide script bytes in context variable diff --git a/sigmastate/src/test/scala/sigmastate/utxo/SpamSpecification.scala b/sigmastate/src/test/scala/sigmastate/utxo/SpamSpecification.scala deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/sigmastate/src/test/scala/sigmastate/utxo/ThresholdSpecification.scala b/sigmastate/src/test/scala/sigmastate/utxo/ThresholdSpecification.scala index b3a0f1f95e..2f3a2f1059 100644 --- a/sigmastate/src/test/scala/sigmastate/utxo/ThresholdSpecification.scala +++ b/sigmastate/src/test/scala/sigmastate/utxo/ThresholdSpecification.scala @@ -1,6 +1,5 @@ package sigmastate.utxo -import org.ergoplatform.{ErgoLikeContext, ErgoLikeTransaction} import sigmastate.basics.DLogProtocol.{DLogProverInput, ProveDlog} import sigmastate.Values.{ConcreteCollection, FalseLeaf, IntConstant, SigmaPropConstant, SigmaPropValue, TrueLeaf} import sigmastate._ @@ -40,7 +39,7 @@ class ThresholdSpecification extends SigmaTestingCommons { minerPubkey = ErgoLikeContextTesting.dummyPubkey, boxesToSpend = IndexedSeq(fakeSelf), spendingTransaction = ErgoLikeTransactionTesting.dummy, - self = fakeSelf) + self = fakeSelf, activatedVersionInTests) val env = Map("pubkeyA" -> pubkeyA, "pubkeyB" -> pubkeyB, "pubkeyC" -> pubkeyC) @@ -119,7 +118,7 @@ class ThresholdSpecification extends SigmaTestingCommons { minerPubkey = ErgoLikeContextTesting.dummyPubkey, boxesToSpend = IndexedSeq(fakeSelf), spendingTransaction = ErgoLikeTransactionTesting.dummy, - self = fakeSelf) + self = fakeSelf, activatedVersionInTests) case class TestCase(numTrue: Int, vector: Seq[SigmaPropValue], dlogOnlyVector: DlogOnlyVector) case class DlogOnlyVector(v: Seq[SigmaPropValue]) { @@ -289,7 +288,7 @@ class ThresholdSpecification extends SigmaTestingCommons { minerPubkey = ErgoLikeContextTesting.dummyPubkey, boxesToSpend = IndexedSeq(fakeSelf), spendingTransaction = ErgoLikeTransactionTesting.dummy, - self = fakeSelf) + self = fakeSelf, activatedVersionInTests) val verifier = new ErgoLikeTestInterpreter @@ -336,7 +335,7 @@ class ThresholdSpecification extends SigmaTestingCommons { minerPubkey = ErgoLikeContextTesting.dummyPubkey, boxesToSpend = IndexedSeq(fakeSelf), spendingTransaction = ErgoLikeTransactionTesting.dummy, - self = fakeSelf) + self = fakeSelf, activatedVersionInTests) val verifier = new ErgoLikeTestInterpreter diff --git a/sigmastate/src/test/scala/sigmastate/utxo/UsingContextPropertiesSpecification.scala b/sigmastate/src/test/scala/sigmastate/utxo/UsingContextPropertiesSpecification.scala index adde25a799..185be9a713 100644 --- a/sigmastate/src/test/scala/sigmastate/utxo/UsingContextPropertiesSpecification.scala +++ b/sigmastate/src/test/scala/sigmastate/utxo/UsingContextPropertiesSpecification.scala @@ -1,6 +1,6 @@ package sigmastate.utxo -import sigmastate.TrivialProp +import sigmastate.{TrivialProp, CrossVersionProps} import sigmastate.eval.{IRContext, CSigmaProp} import sigmastate.eval.Extensions._ import special.sigma.Context @@ -9,7 +9,8 @@ import org.ergoplatform.dsl.{SigmaContractSyntax, ContractSpec, TestContractSpec import org.ergoplatform.ErgoBox import scorex.crypto.hash.Blake2b256 -class UsingContextPropertiesSpecification extends SigmaTestingCommons { suite => +class UsingContextPropertiesSpecification extends SigmaTestingCommons + with CrossVersionProps { suite => lazy val spec = TestContractSpec(suite)(new TestingIRContext) lazy val prover = spec.ProvingParty("Alice") private implicit lazy val IR: IRContext = spec.IR diff --git a/sigmastate/src/test/scala/sigmastate/utxo/blockchain/BlockchainSimulationSpecification.scala b/sigmastate/src/test/scala/sigmastate/utxo/blockchain/BlockchainSimulationSpecification.scala index 9214d0bb12..f3a908e7bf 100644 --- a/sigmastate/src/test/scala/sigmastate/utxo/blockchain/BlockchainSimulationSpecification.scala +++ b/sigmastate/src/test/scala/sigmastate/utxo/blockchain/BlockchainSimulationSpecification.scala @@ -1,23 +1,23 @@ package sigmastate.utxo.blockchain -import java.io.{File, FileWriter} +import java.io.{FileWriter, File} -import org.scalacheck.Gen -import sigmastate.Values.{BooleanConstant, ErgoTree, GetVarBoolean, TrueLeaf} +import sigmastate.CrossVersionProps +import sigmastate.Values.{TrueLeaf, GetVarBoolean} import sigmastate.helpers.{ContextEnrichingTestProvingInterpreter, ErgoLikeTestProvingInterpreter} import sigmastate.interpreter.ContextExtension import sigmastate.utxo.blockchain.BlockchainSimulationTestingCommons._ import scala.collection.concurrent.TrieMap -import scala.util.Random -class BlockchainSimulationSpecification extends BlockchainSimulationTestingCommons { +class BlockchainSimulationSpecification extends BlockchainSimulationTestingCommons + with CrossVersionProps { implicit lazy val IR = new TestingIRContext property("apply one valid block") { - val state = ValidationState.initialState() + val state = ValidationState.initialState(activatedVersionInTests) val miner = new ErgoLikeTestProvingInterpreter() val block = generateBlock(state, miner, 0) val updStateTry = state.applyBlock(block) @@ -25,7 +25,7 @@ class BlockchainSimulationSpecification extends BlockchainSimulationTestingCommo } property("too costly block") { - val state = ValidationState.initialState() + val state = ValidationState.initialState(activatedVersionInTests) val miner = new ErgoLikeTestProvingInterpreter() val block = generateBlock(state, miner, 0) val updStateTry = state.applyBlock(block, maxCost = 1) @@ -33,13 +33,13 @@ class BlockchainSimulationSpecification extends BlockchainSimulationTestingCommo } property("apply many blocks") { - val state = ValidationState.initialState() + val state = ValidationState.initialState(activatedVersionInTests) val miner = new ErgoLikeTestProvingInterpreter() checkState(state, miner, 0, randomDeepness) } property("apply many blocks with enriched context") { - val state = ValidationState.initialState() + val state = ValidationState.initialState(activatedVersionInTests) val miner = new ErgoLikeTestProvingInterpreter() val varId = 1.toByte val prop = GetVarBoolean(varId).get.toSigmaProp @@ -56,7 +56,7 @@ class BlockchainSimulationSpecification extends BlockchainSimulationTestingCommo def bench(numberOfBlocks: Int): Unit = { - val state = ValidationState.initialState() + val state = ValidationState.initialState(activatedVersionInTests) val miner = new ContextEnrichingTestProvingInterpreter() val (_, time) = (0 until numberOfBlocks).foldLeft(state -> 0L) { case ((s, timeAcc), h) => diff --git a/sigmastate/src/test/scala/sigmastate/utxo/blockchain/BlockchainSimulationTestingCommons.scala b/sigmastate/src/test/scala/sigmastate/utxo/blockchain/BlockchainSimulationTestingCommons.scala index 4612112f85..fc8918652d 100644 --- a/sigmastate/src/test/scala/sigmastate/utxo/blockchain/BlockchainSimulationTestingCommons.scala +++ b/sigmastate/src/test/scala/sigmastate/utxo/blockchain/BlockchainSimulationTestingCommons.scala @@ -58,6 +58,7 @@ trait BlockchainSimulationTestingCommons extends SigmaTestingCommons { IndexedSeq(box), tx, box, + activatedVersionInTests, extension) val env = emptyEnv + (ScriptNameProp -> s"height_${state.state.currentHeight}_prove") val proverResult = prover.prove(env, box.ergoTree, context, tx.messageToSign).get @@ -119,8 +120,8 @@ object BlockchainSimulationTestingCommons extends SigmaTestingCommons { } - case class ValidationState(state: BlockchainState, boxesReader: InMemoryErgoBoxReader)(implicit IR: IRContext) { - val validator = new ErgoTransactionValidator + case class ValidationState(state: BlockchainState, boxesReader: InMemoryErgoBoxReader, activatedVersion: Byte)(implicit IR: IRContext) { + val validator = new ErgoTransactionValidator(activatedVersion) def applyBlock(block: FullBlock, maxCost: Int = MaxBlockCost): Try[ValidationState] = Try { val height = state.currentHeight + 1 @@ -138,7 +139,7 @@ object BlockchainSimulationTestingCommons extends SigmaTestingCommons { boxesReader.applyBlock(block) val newState = BlockchainState(height, state.lastBlockUtxoRoot.copy(digest = boxesReader.digest)) - ValidationState(newState, boxesReader) + ValidationState(newState, boxesReader, activatedVersion) } } @@ -154,7 +155,7 @@ object BlockchainSimulationTestingCommons extends SigmaTestingCommons { ErgoLikeContextTesting.dummyPubkey ) - def initialState(block: FullBlock = initBlock)(implicit IR: IRContext): ValidationState = { + def initialState(activatedVersion: Byte, block: FullBlock = initBlock)(implicit IR: IRContext): ValidationState = { val keySize = 32 val prover = new BatchProver(keySize, None) @@ -165,7 +166,7 @@ object BlockchainSimulationTestingCommons extends SigmaTestingCommons { val boxReader = new InMemoryErgoBoxReader(prover) - ValidationState(bs, boxReader).applyBlock(block).get + ValidationState(bs, boxReader, activatedVersion).applyBlock(block).get } } diff --git a/sigmastate/src/test/scala/sigmastate/utxo/examples/AtomicSwapExampleSpecification.scala b/sigmastate/src/test/scala/sigmastate/utxo/examples/AtomicSwapExampleSpecification.scala index 42bcf6bbe5..eb60bbfa6f 100644 --- a/sigmastate/src/test/scala/sigmastate/utxo/examples/AtomicSwapExampleSpecification.scala +++ b/sigmastate/src/test/scala/sigmastate/utxo/examples/AtomicSwapExampleSpecification.scala @@ -10,7 +10,7 @@ import sigmastate.helpers.{ContextEnrichingTestProvingInterpreter, ErgoLikeConte import sigmastate.lang.Terms._ import sigmastate.utxo.SizeOf -class AtomicSwapExampleSpecification extends SigmaTestingCommons { +class AtomicSwapExampleSpecification extends SigmaTestingCommons with CrossVersionProps { private implicit lazy val IR: TestingIRContext = new TestingIRContext /** @@ -103,7 +103,8 @@ class AtomicSwapExampleSpecification extends SigmaTestingCommons { minerPubkey = ErgoLikeContextTesting.dummyPubkey, boxesToSpend = IndexedSeq(fakeSelf), spendingTransaction = ErgoLikeTransactionTesting.dummy, - self = fakeSelf) + self = fakeSelf, + activatedVersionInTests) proverB.prove(env, prop1, ctxf1, fakeMessage).isSuccess shouldBe false //A can't withdraw her coins in chain1 (generate a valid proof) @@ -114,7 +115,10 @@ class AtomicSwapExampleSpecification extends SigmaTestingCommons { currentHeight = height2 + 1, lastBlockUtxoRoot = AvlTreeData.dummy, minerPubkey = ErgoLikeContextTesting.dummyPubkey, - boxesToSpend = IndexedSeq(fakeSelf), spendingTransaction = ErgoLikeTransactionTesting.dummy, self = fakeSelf) + boxesToSpend = IndexedSeq(fakeSelf), + spendingTransaction = ErgoLikeTransactionTesting.dummy, + self = fakeSelf, + activatedVersionInTests) proverB.prove(env, prop2, ctxf2, fakeMessage).isSuccess shouldBe false //Successful run below: @@ -126,7 +130,8 @@ class AtomicSwapExampleSpecification extends SigmaTestingCommons { minerPubkey = ErgoLikeContextTesting.dummyPubkey, boxesToSpend = IndexedSeq(fakeSelf), spendingTransaction = ErgoLikeTransactionTesting.dummy, - self = fakeSelf) + self = fakeSelf, + activatedVersionInTests) val pr = proverA.prove(env, prop2, ctx1, fakeMessage).get verifier.verify(env, prop2, ctx1, pr, fakeMessage).get._1 shouldBe true @@ -141,7 +146,8 @@ class AtomicSwapExampleSpecification extends SigmaTestingCommons { minerPubkey = ErgoLikeContextTesting.dummyPubkey, boxesToSpend = IndexedSeq(fakeSelf), spendingTransaction = ErgoLikeTransactionTesting.dummy, - self = fakeSelf) + self = fakeSelf, + activatedVersionInTests) val pr2 = proverB2.prove(env, prop1, ctx2, fakeMessage).get verifier.verify(env, prop1, ctx2, pr2, fakeMessage).get._1 shouldBe true diff --git a/sigmastate/src/test/scala/sigmastate/utxo/examples/CoinEmissionSpecification.scala b/sigmastate/src/test/scala/sigmastate/utxo/examples/CoinEmissionSpecification.scala index 31251cbb93..97eee44ab6 100644 --- a/sigmastate/src/test/scala/sigmastate/utxo/examples/CoinEmissionSpecification.scala +++ b/sigmastate/src/test/scala/sigmastate/utxo/examples/CoinEmissionSpecification.scala @@ -20,7 +20,8 @@ import sigmastate.eval._ * This script is corresponding to the whitepaper. Please note that Ergo has different contract * defined in ErgoScriptPredef. */ -class CoinEmissionSpecification extends SigmaTestingCommons with ScorexLogging { +class CoinEmissionSpecification extends SigmaTestingCommons + with ScorexLogging with CrossVersionProps { // don't use TestingIRContext, this suite also serves the purpose of testing the RuntimeIRContext implicit lazy val IR: TestingIRContext = new TestingIRContext { // uncomment if you want to log script evaluation @@ -138,7 +139,7 @@ block 1600 in 1622 ms, 30000000000 coins remain, defs: 61661 val initialBoxCandidate: ErgoBox = testBox(coinsTotal / 4, prop, 0, Seq(), Map(register -> IntConstant(-1))) val initBlock = FullBlock(IndexedSeq(createTransaction(initialBoxCandidate)), minerPubkey) - val genesisState = ValidationState.initialState(initBlock) + val genesisState = ValidationState.initialState(activatedVersionInTests, initBlock) val fromState = genesisState.boxesReader.byId(genesisState.boxesReader.allIds.head).get val initialBox = new ErgoBox(initialBoxCandidate.value, initialBoxCandidate.ergoTree, initialBoxCandidate.additionalTokens, initialBoxCandidate.additionalRegisters, @@ -173,6 +174,7 @@ block 1600 in 1622 ms, 30000000000 coins remain, defs: 61661 IndexedSeq(emissionBox), ut, emissionBox, + activatedVersionInTests, ContextExtension.empty) val proverResult = prover.prove(emptyEnv + (ScriptNameProp -> "prove"), prop, context, ut.messageToSign).get ut.toSigned(IndexedSeq(proverResult)) diff --git a/sigmastate/src/test/scala/sigmastate/utxo/examples/ColdWalletAdvContractExampleSpecification.scala b/sigmastate/src/test/scala/sigmastate/utxo/examples/ColdWalletAdvContractExampleSpecification.scala index fa03a9904d..f033d4f6b2 100644 --- a/sigmastate/src/test/scala/sigmastate/utxo/examples/ColdWalletAdvContractExampleSpecification.scala +++ b/sigmastate/src/test/scala/sigmastate/utxo/examples/ColdWalletAdvContractExampleSpecification.scala @@ -1,16 +1,17 @@ package sigmastate.utxo.examples -import org.ergoplatform.ErgoBox.{R4, R5, R6} +import org.ergoplatform.ErgoBox.{R6, R4, R5} import org.ergoplatform._ -import sigmastate.AvlTreeData -import sigmastate.Values.{IntConstant, LongConstant} -import sigmastate.helpers.{ContextEnrichingTestProvingInterpreter, ErgoLikeContextTesting, ErgoLikeTestInterpreter, ErgoLikeTestProvingInterpreter, SigmaTestingCommons} +import sigmastate.{AvlTreeData, CrossVersionProps} +import sigmastate.Values.{LongConstant, IntConstant} +import sigmastate.helpers.{ErgoLikeContextTesting, ErgoLikeTestInterpreter, ErgoLikeTestProvingInterpreter, SigmaTestingCommons, ContextEnrichingTestProvingInterpreter} import sigmastate.helpers.TestingHelpers._ import sigmastate.interpreter.Interpreter.ScriptNameProp import sigmastate.lang.Terms._ -class ColdWalletAdvContractExampleSpecification extends SigmaTestingCommons { +class ColdWalletAdvContractExampleSpecification extends SigmaTestingCommons + with CrossVersionProps { private implicit lazy val IR: TestingIRContext = new TestingIRContext import ErgoAddressEncoder._ @@ -134,7 +135,8 @@ class ColdWalletAdvContractExampleSpecification extends SigmaTestingCommons { minerPubkey = ErgoLikeContextTesting.dummyPubkey, boxesToSpend = IndexedSeq(depositOutput), spendingTransaction = firstWithdrawTx1Key, - self = depositOutput + self = depositOutput, + activatedVersionInTests ) val verifier = new ErgoLikeTestInterpreter @@ -170,7 +172,8 @@ class ColdWalletAdvContractExampleSpecification extends SigmaTestingCommons { minerPubkey = ErgoLikeContextTesting.dummyPubkey, boxesToSpend = IndexedSeq(depositOutput), spendingTransaction = firstWithdrawTx2Key, - self = depositOutput + self = depositOutput, + activatedVersionInTests ) val proofAliceBobWithdraw = alice.withSecrets(bob.dlogSecrets).prove(spendEnv, script, firstWithdrawContext2Key, fakeMessage).get.proof diff --git a/sigmastate/src/test/scala/sigmastate/utxo/examples/ColdWalletContractExampleSpecification.scala b/sigmastate/src/test/scala/sigmastate/utxo/examples/ColdWalletContractExampleSpecification.scala index 3987f84dfd..c0a860abbe 100644 --- a/sigmastate/src/test/scala/sigmastate/utxo/examples/ColdWalletContractExampleSpecification.scala +++ b/sigmastate/src/test/scala/sigmastate/utxo/examples/ColdWalletContractExampleSpecification.scala @@ -2,15 +2,16 @@ package sigmastate.utxo.examples import org.ergoplatform.ErgoBox.{R4, R5} import org.ergoplatform._ -import sigmastate.helpers.{ContextEnrichingTestProvingInterpreter, ErgoLikeContextTesting, ErgoLikeTestInterpreter, SigmaTestingCommons} +import sigmastate.helpers.{ContextEnrichingTestProvingInterpreter, ErgoLikeContextTesting, SigmaTestingCommons, ErgoLikeTestInterpreter} import sigmastate.helpers.TestingHelpers._ -import sigmastate.AvlTreeData -import sigmastate.Values.{IntConstant, LongConstant} +import sigmastate.{AvlTreeData, CrossVersionProps} +import sigmastate.Values.{LongConstant, IntConstant} import sigmastate.interpreter.Interpreter.ScriptNameProp import sigmastate.lang.Terms._ -class ColdWalletContractExampleSpecification extends SigmaTestingCommons { +class ColdWalletContractExampleSpecification extends SigmaTestingCommons + with CrossVersionProps { private implicit lazy val IR: TestingIRContext = new TestingIRContext import ErgoAddressEncoder._ @@ -100,7 +101,8 @@ class ColdWalletContractExampleSpecification extends SigmaTestingCommons { minerPubkey = ErgoLikeContextTesting.dummyPubkey, boxesToSpend = IndexedSeq(depositOutput), spendingTransaction = withdrawTxAliceAndBob, - self = depositOutput + self = depositOutput, + activatedVersionInTests ) val proofAliceAndBobWithdraw = alice.withSecrets(bob.dlogSecrets).prove(spendEnv, script, withdrawContextAliceandBob, fakeMessage).get.proof @@ -130,7 +132,8 @@ class ColdWalletContractExampleSpecification extends SigmaTestingCommons { minerPubkey = ErgoLikeContextTesting.dummyPubkey, boxesToSpend = IndexedSeq(depositOutput), spendingTransaction = firstWithdrawTx, - self = depositOutput + self = depositOutput, + activatedVersionInTests ) val proofAliceWithdraw = alice.prove(spendEnv, script, firstWithdrawContext, fakeMessage).get.proof @@ -159,7 +162,8 @@ class ColdWalletContractExampleSpecification extends SigmaTestingCommons { minerPubkey = ErgoLikeContextTesting.dummyPubkey, boxesToSpend = IndexedSeq(depositOutput), spendingTransaction = withdrawTxInvalid, - self = depositOutput + self = depositOutput, + activatedVersionInTests ) an [AssertionError] should be thrownBy ( @@ -193,7 +197,8 @@ class ColdWalletContractExampleSpecification extends SigmaTestingCommons { minerPubkey = ErgoLikeContextTesting.dummyPubkey, boxesToSpend = IndexedSeq(firstChangeOutput), spendingTransaction = secondWithdrawTx, - self = firstChangeOutput + self = firstChangeOutput, + activatedVersionInTests ) val proofAliceSecondWithdraw = alice.prove(spendEnv, script, secondWithdrawContext, fakeMessage).get.proof diff --git a/sigmastate/src/test/scala/sigmastate/utxo/examples/CoopExampleSpecification.scala b/sigmastate/src/test/scala/sigmastate/utxo/examples/CoopExampleSpecification.scala index c44e5acb35..3aa7968d19 100644 --- a/sigmastate/src/test/scala/sigmastate/utxo/examples/CoopExampleSpecification.scala +++ b/sigmastate/src/test/scala/sigmastate/utxo/examples/CoopExampleSpecification.scala @@ -5,13 +5,14 @@ import org.scalatest.Assertion import org.scalatest.TryValues._ import sigmastate.basics.DLogProtocol.ProveDlog import scorex.crypto.hash.Blake2b256 -import sigmastate.Values.{ByteArrayConstant, SigmaPropValue, BooleanConstant} +import sigmastate.Values.{ByteArrayConstant, BooleanConstant, SigmaPropValue} import sigmastate.helpers.{ContextEnrichingTestProvingInterpreter, ErgoLikeContextTesting, SigmaTestingCommons, ErgoLikeTestInterpreter} import sigmastate.helpers.TestingHelpers._ import sigmastate.lang.Terms._ -import sigmastate.AvlTreeData +import sigmastate.{AvlTreeData, CrossVersionProps} -class CoopExampleSpecification extends SigmaTestingCommons { +class CoopExampleSpecification extends SigmaTestingCommons + with CrossVersionProps { implicit lazy val IR = new TestingIRContext def mkTxFromOutputs(ergoBox: ErgoBox*): ErgoLikeTransaction = { @@ -27,7 +28,7 @@ class CoopExampleSpecification extends SigmaTestingCommons { minerPubkey = ErgoLikeContextTesting.dummyPubkey, boxesToSpend = IndexedSeq(self), spendingTransaction = tx, - self = self) + self = self, activatedVersionInTests) } def successProofTest(exp: SigmaPropValue, diff --git a/sigmastate/src/test/scala/sigmastate/utxo/examples/DHTupleExampleSpecification.scala b/sigmastate/src/test/scala/sigmastate/utxo/examples/DHTupleExampleSpecification.scala index 7d6382ad34..342aa15cfa 100644 --- a/sigmastate/src/test/scala/sigmastate/utxo/examples/DHTupleExampleSpecification.scala +++ b/sigmastate/src/test/scala/sigmastate/utxo/examples/DHTupleExampleSpecification.scala @@ -4,17 +4,18 @@ package sigmastate.utxo.examples import java.math.BigInteger import org.ergoplatform.ErgoBox.{R4, R5} -import sigmastate.AvlTreeData +import sigmastate.{AvlTreeData, CrossVersionProps} import sigmastate.Values.GroupElementConstant import sigmastate.basics.DLogProtocol.ProveDlog -import sigmastate.basics.{DiffieHellmanTupleProverInput, ProveDHTuple} -import sigmastate.helpers.{ContextEnrichingTestProvingInterpreter, ErgoLikeContextTesting, ErgoLikeTestInterpreter, SigmaTestingCommons} +import sigmastate.basics.{ProveDHTuple, DiffieHellmanTupleProverInput} +import sigmastate.helpers.{ContextEnrichingTestProvingInterpreter, ErgoLikeContextTesting, SigmaTestingCommons, ErgoLikeTestInterpreter} import sigmastate.helpers.TestingHelpers._ import sigmastate.interpreter.CryptoConstants import sigmastate.interpreter.Interpreter._ import sigmastate.lang.Terms._ -class DHTupleExampleSpecification extends SigmaTestingCommons { +class DHTupleExampleSpecification extends SigmaTestingCommons + with CrossVersionProps { private implicit lazy val IR = new TestingIRContext /** * let Alice's secret be x and Bob's be y @@ -84,7 +85,7 @@ class DHTupleExampleSpecification extends SigmaTestingCommons { minerPubkey = ErgoLikeContextTesting.dummyPubkey, boxesToSpend = IndexedSeq(inBox), spendingTransaction = tx, - self = inBox + self = inBox, activatedVersionInTests ) val dhtBob = DiffieHellmanTupleProverInput(y, ProveDHTuple(g, g_x, g_y, g_xy)) diff --git a/sigmastate/src/test/scala/sigmastate/utxo/examples/DemurrageExampleSpecification.scala b/sigmastate/src/test/scala/sigmastate/utxo/examples/DemurrageExampleSpecification.scala index f8f7edd717..838bbf35a8 100644 --- a/sigmastate/src/test/scala/sigmastate/utxo/examples/DemurrageExampleSpecification.scala +++ b/sigmastate/src/test/scala/sigmastate/utxo/examples/DemurrageExampleSpecification.scala @@ -9,7 +9,8 @@ import sigmastate.helpers.TestingHelpers._ import sigmastate.interpreter.ContextExtension import sigmastate.lang.Terms._ -class DemurrageExampleSpecification extends SigmaTestingCommons { +class DemurrageExampleSpecification extends SigmaTestingCommons + with CrossVersionProps { implicit lazy val IR = new TestingIRContext /** @@ -91,7 +92,7 @@ class DemurrageExampleSpecification extends SigmaTestingCommons { minerPubkey = ErgoLikeContextTesting.dummyPubkey, boxesToSpend = IndexedSeq(selfBox), spendingTransaction = tx1, - self = selfBox, + self = selfBox, activatedVersionInTests, extension = ce) //user can spend all the money @@ -111,7 +112,7 @@ class DemurrageExampleSpecification extends SigmaTestingCommons { minerPubkey = ErgoLikeContextTesting.dummyPubkey, boxesToSpend = IndexedSeq(selfBox), spendingTransaction = tx2, - self = selfBox, + self = selfBox, activatedVersionInTests, extension = ce) //user can spend all the money @@ -127,7 +128,7 @@ class DemurrageExampleSpecification extends SigmaTestingCommons { minerPubkey = ErgoLikeContextTesting.dummyPubkey, boxesToSpend = IndexedSeq(b, selfBox), spendingTransaction = tx3, - self = selfBox) + self = selfBox, activatedVersionInTests) assert(ctx3.spendingTransaction.outputs.head.propositionBytes sameElements ctx3.boxesToSpend(ctx3.selfIndex).propositionBytes) @@ -144,7 +145,7 @@ class DemurrageExampleSpecification extends SigmaTestingCommons { minerPubkey = ErgoLikeContextTesting.dummyPubkey, boxesToSpend = IndexedSeq(b2, selfBox), spendingTransaction = tx4, - self = selfBox, + self = selfBox, activatedVersionInTests, extension = ce) minerProver.prove(prop, ctx4, fakeMessage).isSuccess shouldBe false @@ -159,7 +160,7 @@ class DemurrageExampleSpecification extends SigmaTestingCommons { minerPubkey = ErgoLikeContextTesting.dummyPubkey, boxesToSpend = IndexedSeq(selfBox), spendingTransaction = tx5, - self = selfBox, + self = selfBox, activatedVersionInTests, extension = ce) val mProof2 = minerProver.prove(prop, ctx5, fakeMessage).get @@ -176,7 +177,7 @@ class DemurrageExampleSpecification extends SigmaTestingCommons { minerPubkey = ErgoLikeContextTesting.dummyPubkey, boxesToSpend = IndexedSeq(b3, selfBox6), spendingTransaction = tx6, - self = selfBox6, + self = selfBox6, activatedVersionInTests, extension = ce) val mProof3 = minerProver.prove(prop, ctx6, fakeMessage).get diff --git a/sigmastate/src/test/scala/sigmastate/utxo/examples/FsmExampleSpecification.scala b/sigmastate/src/test/scala/sigmastate/utxo/examples/FsmExampleSpecification.scala index d24fe63bed..2698231cb3 100644 --- a/sigmastate/src/test/scala/sigmastate/utxo/examples/FsmExampleSpecification.scala +++ b/sigmastate/src/test/scala/sigmastate/utxo/examples/FsmExampleSpecification.scala @@ -17,7 +17,8 @@ import sigmastate.serialization.ValueSerializer import sigmastate.utxo._ -class FsmExampleSpecification extends SigmaTestingCommons { +class FsmExampleSpecification extends SigmaTestingCommons + with CrossVersionProps { private implicit lazy val IR: TestingIRContext = new TestingIRContext /** * Similarly to the MAST-like example (in the MASTExampleSpecification class), we can do more complex contracts, @@ -150,7 +151,7 @@ class FsmExampleSpecification extends SigmaTestingCommons { minerPubkey = ErgoLikeContextTesting.dummyPubkey, boxesToSpend = IndexedSeq(fsmBox1), createTransaction(fsmBox2), - self = fsmBox1) + self = fsmBox1, activatedVersionInTests) val spendingProof = prover .withContextExtender(scriptVarId, ByteArrayConstant(ValueSerializer.serialize(script1))) @@ -170,7 +171,7 @@ class FsmExampleSpecification extends SigmaTestingCommons { minerPubkey = ErgoLikeContextTesting.dummyPubkey, boxesToSpend = IndexedSeq(fsmBox2), createTransaction(fsmBox1), - self = fsmBox2) + self = fsmBox2, activatedVersionInTests) val spendingProof2 = prover .withContextExtender(scriptVarId, ByteArrayConstant(ValueSerializer.serialize(script2))) @@ -198,7 +199,7 @@ class FsmExampleSpecification extends SigmaTestingCommons { minerPubkey = ErgoLikeContextTesting.dummyPubkey, boxesToSpend = IndexedSeq(fsmBox1), createTransaction(fsmBox3), - self = fsmBox1) + self = fsmBox1, activatedVersionInTests) //honest prover fails prover @@ -225,7 +226,7 @@ class FsmExampleSpecification extends SigmaTestingCommons { minerPubkey = ErgoLikeContextTesting.dummyPubkey, boxesToSpend = IndexedSeq(fsmBox2), createTransaction(fsmBox3), - self = fsmBox2) + self = fsmBox2, activatedVersionInTests) val spendingProof23 = prover .withContextExtender(scriptVarId, ByteArrayConstant(ValueSerializer.serialize(script3))) @@ -247,7 +248,7 @@ class FsmExampleSpecification extends SigmaTestingCommons { minerPubkey = ErgoLikeContextTesting.dummyPubkey, boxesToSpend = IndexedSeq(fsmBox3), createTransaction(freeBox), - self = fsmBox3) + self = fsmBox3, activatedVersionInTests) val spendingProof30 = prover .withContextExtender(scriptVarId, ByteArrayConstant(ValueSerializer.serialize(script4))) @@ -263,7 +264,7 @@ class FsmExampleSpecification extends SigmaTestingCommons { minerPubkey = ErgoLikeContextTesting.dummyPubkey, boxesToSpend = IndexedSeq(fsmBox2), createTransaction(freeBox), - self = fsmBox2) + self = fsmBox2, activatedVersionInTests) //honest prover fails prover diff --git a/sigmastate/src/test/scala/sigmastate/utxo/examples/IcoExample.scala b/sigmastate/src/test/scala/sigmastate/utxo/examples/IcoExample.scala index b38726f016..eb90bf297a 100644 --- a/sigmastate/src/test/scala/sigmastate/utxo/examples/IcoExample.scala +++ b/sigmastate/src/test/scala/sigmastate/utxo/examples/IcoExample.scala @@ -232,7 +232,8 @@ by miners via storage rent mechanism, potentially for decades or even centuries. reasonable to have an additional input from the project with the value equal to the value of the fee output. And so on. */ -class IcoExample extends SigmaTestingCommons { suite => +class IcoExample extends SigmaTestingCommons + with CrossVersionProps { suite => // Not mixed with TestContext since it is not possible to call commpiler.compile outside tests if mixed implicit lazy val IR: IRContext = new IRContext with CompiletimeCosting @@ -414,7 +415,7 @@ class IcoExample extends SigmaTestingCommons { suite => minerPubkey = ErgoLikeContextTesting.dummyPubkey, boxesToSpend = inputBoxes, spendingTransaction = fundingTx, - self = projectBoxBefore) + self = projectBoxBefore, activatedVersionInTests) val projectProver = new ContextEnrichingTestProvingInterpreter() .withContextExtender(1, ByteArrayConstant(proof)) @@ -451,7 +452,7 @@ class IcoExample extends SigmaTestingCommons { suite => minerPubkey = ErgoLikeContextTesting.dummyPubkey, boxesToSpend = IndexedSeq(projectBoxBeforeClosing), spendingTransaction = issuanceTx, - self = projectBoxBeforeClosing) + self = projectBoxBeforeClosing, activatedVersionInTests) val res = project.prove(env, issuanceScript, issuanceContext, fakeMessage).get println("token issuance script cost: " + res.cost) @@ -523,7 +524,7 @@ class IcoExample extends SigmaTestingCommons { suite => minerPubkey = ErgoLikeContextTesting.dummyPubkey, boxesToSpend = IndexedSeq(projectBoxBefore), spendingTransaction = fundingTx, - self = projectBoxBefore) + self = projectBoxBefore, activatedVersionInTests) val projectProver = new ContextEnrichingTestProvingInterpreter() diff --git a/sigmastate/src/test/scala/sigmastate/utxo/examples/LetsSpecification.scala b/sigmastate/src/test/scala/sigmastate/utxo/examples/LetsSpecification.scala index 97746d4381..6d1d0862cc 100644 --- a/sigmastate/src/test/scala/sigmastate/utxo/examples/LetsSpecification.scala +++ b/sigmastate/src/test/scala/sigmastate/utxo/examples/LetsSpecification.scala @@ -3,10 +3,10 @@ package sigmastate.utxo.examples import org.ergoplatform._ import org.ergoplatform.ErgoBox.{R4, R5} import scorex.crypto.authds.{ADKey, ADValue} -import scorex.crypto.authds.avltree.batch.{BatchAVLProver, Insert, Lookup} -import scorex.crypto.hash.{Blake2b256, Digest32} -import sigmastate.{AvlTreeData, AvlTreeFlags, TrivialProp} -import sigmastate.Values.{AvlTreeConstant, ByteArrayConstant, LongConstant, SigmaPropConstant} +import scorex.crypto.authds.avltree.batch.{Lookup, BatchAVLProver, Insert} +import scorex.crypto.hash.{Digest32, Blake2b256} +import sigmastate.{AvlTreeData, AvlTreeFlags, TrivialProp, CrossVersionProps} +import sigmastate.Values.{ByteArrayConstant, AvlTreeConstant, SigmaPropConstant, LongConstant} import sigmastate.eval.{IRContext, SigmaDsl} import sigmastate.helpers.{ContextEnrichingTestProvingInterpreter, ErgoLikeContextTesting, ErgoLikeTestProvingInterpreter, SigmaTestingCommons} import sigmastate.helpers.TestingHelpers._ @@ -166,7 +166,7 @@ import scala.util.Random some day this article will be continued! */ -class LetsSpecification extends SigmaTestingCommons { suite => +class LetsSpecification extends SigmaTestingCommons with CrossVersionProps { suite => // Not mixed with TestContext since it is not possible to call compiler.compile outside tests if mixed implicit lazy val IR: IRContext = new TestingIRContext @@ -308,7 +308,7 @@ class LetsSpecification extends SigmaTestingCommons { suite => minerPubkey = ErgoLikeContextTesting.dummyPubkey, boxesToSpend = IndexedSeq(projectBoxBefore), spendingTransaction = issuanceTx, - self = projectBoxBefore) + self = projectBoxBefore, activatedVersionInTests) val managementProver = new ContextEnrichingTestProvingInterpreter() .withContextExtender(1, ByteArrayConstant(proof)) @@ -356,7 +356,8 @@ class LetsSpecification extends SigmaTestingCommons { suite => dataBoxes = IndexedSeq(directoryBox), boxesToSpend = IndexedSeq(userBoxBefore0, userBoxBefore1), spendingTransaction = issuanceTx, - selfIndex = 0) + selfIndex = 0, + activatedVersionInTests) val managementProver = new ContextEnrichingTestProvingInterpreter() .withContextExtender(1, ByteArrayConstant(proof)) diff --git a/sigmastate/src/test/scala/sigmastate/utxo/examples/MASTExampleSpecification.scala b/sigmastate/src/test/scala/sigmastate/utxo/examples/MASTExampleSpecification.scala index a66e50993c..a2bc75a44b 100644 --- a/sigmastate/src/test/scala/sigmastate/utxo/examples/MASTExampleSpecification.scala +++ b/sigmastate/src/test/scala/sigmastate/utxo/examples/MASTExampleSpecification.scala @@ -26,7 +26,8 @@ import scala.util.Random * remain unrevealed, providing more privacy and saving space in a blockchain. * See more at https://bitcointechtalk.com/what-is-a-bitcoin-merklized-abstract-syntax-tree-mast-33fdf2da5e2f */ -class MASTExampleSpecification extends SigmaTestingCommons { +class MASTExampleSpecification extends SigmaTestingCommons + with CrossVersionProps { implicit lazy val IR = new TestingIRContext private val reg1 = ErgoBox.nonMandatoryRegisters.head @@ -55,7 +56,7 @@ class MASTExampleSpecification extends SigmaTestingCommons { minerPubkey = ErgoLikeContextTesting.dummyPubkey, boxesToSpend = IndexedSeq(input1), tx, - self = input1) + self = input1, activatedVersionInTests) val prover = new ContextEnrichingTestProvingInterpreter() @@ -109,7 +110,7 @@ class MASTExampleSpecification extends SigmaTestingCommons { minerPubkey = ErgoLikeContextTesting.dummyPubkey, boxesToSpend = IndexedSeq(selfBox), createTransaction(testBox(1, recipientProposition, 0)), - self = selfBox) + self = selfBox, activatedVersionInTests) avlProver.performOneOperation(Lookup(knownSecretTreeKey)) val knownSecretPathProof = avlProver.generateProof() diff --git a/sigmastate/src/test/scala/sigmastate/utxo/examples/MixExampleSpecification.scala b/sigmastate/src/test/scala/sigmastate/utxo/examples/MixExampleSpecification.scala index 507f8bb10d..1a7f6fb0e4 100644 --- a/sigmastate/src/test/scala/sigmastate/utxo/examples/MixExampleSpecification.scala +++ b/sigmastate/src/test/scala/sigmastate/utxo/examples/MixExampleSpecification.scala @@ -4,18 +4,19 @@ import java.math.BigInteger import org.ergoplatform.ErgoBox.{R4, R5} import scorex.crypto.hash.Blake2b256 -import sigmastate.AvlTreeData +import sigmastate.{AvlTreeData, CrossVersionProps} import sigmastate.Values.GroupElementConstant import sigmastate.basics.DLogProtocol.ProveDlog -import sigmastate.basics.{DiffieHellmanTupleProverInput, ProveDHTuple} -import sigmastate.helpers.{ContextEnrichingTestProvingInterpreter, ErgoLikeContextTesting, ErgoLikeTestInterpreter, SigmaTestingCommons} +import sigmastate.basics.{ProveDHTuple, DiffieHellmanTupleProverInput} +import sigmastate.helpers.{ContextEnrichingTestProvingInterpreter, ErgoLikeContextTesting, SigmaTestingCommons, ErgoLikeTestInterpreter} import sigmastate.helpers.TestingHelpers._ import sigmastate.interpreter.CryptoConstants import sigmastate.interpreter.Interpreter._ import sigmastate.lang.Terms._ import sigmastate.eval._ -class MixExampleSpecification extends SigmaTestingCommons { +class MixExampleSpecification extends SigmaTestingCommons + with CrossVersionProps { private implicit lazy val IR: TestingIRContext = new TestingIRContext property("Evaluation - Mix Example") { @@ -162,7 +163,7 @@ class MixExampleSpecification extends SigmaTestingCommons { minerPubkey = ErgoLikeContextTesting.dummyPubkey, boxesToSpend = IndexedSeq(halfMixOutput), spendingTransaction = fullMixTx, - self = halfMixOutput + self = halfMixOutput, activatedVersionInTests ) // bob (2nd player) is generating a proof and it is passing verification @@ -217,7 +218,7 @@ class MixExampleSpecification extends SigmaTestingCommons { minerPubkey = ErgoLikeContextTesting.dummyPubkey, boxesToSpend = IndexedSeq(aliceAnonBox), spendingTransaction = spendingTx, - self = aliceAnonBox + self = aliceAnonBox, activatedVersionInTests ) // To Do: Extract below g_y, g_xy from fullMixOutputs registers @@ -239,7 +240,7 @@ class MixExampleSpecification extends SigmaTestingCommons { minerPubkey = ErgoLikeContextTesting.dummyPubkey, boxesToSpend = IndexedSeq(bobAnonBox), spendingTransaction = spendingTx, - self = bobAnonBox + self = bobAnonBox, activatedVersionInTests ) val proofBobSpend = bob.prove(fullMixEnv, fullMixScript, bobSpendContext, fakeMessage).get.proof diff --git a/sigmastate/src/test/scala/sigmastate/utxo/examples/OracleExamplesSpecification.scala b/sigmastate/src/test/scala/sigmastate/utxo/examples/OracleExamplesSpecification.scala index edaf3cc23b..3e0b477302 100644 --- a/sigmastate/src/test/scala/sigmastate/utxo/examples/OracleExamplesSpecification.scala +++ b/sigmastate/src/test/scala/sigmastate/utxo/examples/OracleExamplesSpecification.scala @@ -22,7 +22,8 @@ import sigmastate.utxo._ import special.sigma.Context import sigmastate.utils.Helpers._ -class OracleExamplesSpecification extends SigmaTestingCommons { suite => +class OracleExamplesSpecification extends SigmaTestingCommons + with CrossVersionProps { suite => implicit lazy val IR: TestingIRContext = new TestingIRContext private val reg1 = ErgoBox.nonMandatoryRegisters(0) @@ -179,7 +180,7 @@ class OracleExamplesSpecification extends SigmaTestingCommons { suite => ErgoLikeContextTesting.dummyPubkey, boxesToSpend = IndexedSeq(sAlice, sBob), spendingTransaction, - self = sAlice) + self = sAlice, activatedVersionInTests) val alice = aliceTemplate .withContextExtender(22: Byte, BoxConstant(oracleBox)) @@ -256,7 +257,7 @@ class OracleExamplesSpecification extends SigmaTestingCommons { suite => minerPubkey = ErgoLikeContextTesting.dummyPubkey, boxesToSpend = IndexedSeq(sOracle, sAlice, sBob), spendingTransaction, - self = sOracle) + self = sOracle, activatedVersionInTests) val prA = alice.prove(emptyEnv + (ScriptNameProp -> "alice_prove"), prop, ctx, fakeMessage).get verifier.verify(emptyEnv + (ScriptNameProp -> "verify"), prop, ctx, prA, fakeMessage).get._1 shouldBe true diff --git a/sigmastate/src/test/scala/sigmastate/utxo/examples/RPSGameExampleSpecification.scala b/sigmastate/src/test/scala/sigmastate/utxo/examples/RPSGameExampleSpecification.scala index 2679ab1aa1..66a70e4380 100644 --- a/sigmastate/src/test/scala/sigmastate/utxo/examples/RPSGameExampleSpecification.scala +++ b/sigmastate/src/test/scala/sigmastate/utxo/examples/RPSGameExampleSpecification.scala @@ -12,7 +12,8 @@ import sigmastate.helpers.TestingHelpers._ import sigmastate.interpreter.Interpreter._ import sigmastate.lang.Terms._ -class RPSGameExampleSpecification extends SigmaTestingCommons { +class RPSGameExampleSpecification extends SigmaTestingCommons + with CrossVersionProps { implicit lazy val IR = new TestingIRContext /** RPS game: @@ -160,7 +161,8 @@ class RPSGameExampleSpecification extends SigmaTestingCommons { minerPubkey = ErgoLikeContextTesting.dummyPubkey, boxesToSpend = IndexedSeq(halfGameOutput), spendingTransaction = fullGameTx, - self = halfGameOutput // what is the use of self? + self = halfGameOutput, // what is the use of self? + activatedVersionInTests ) // bob (2nd player) is generating a proof and it is passing verification @@ -196,7 +198,7 @@ class RPSGameExampleSpecification extends SigmaTestingCommons { minerPubkey = ErgoLikeContextTesting.dummyPubkey, boxesToSpend = IndexedSeq(fullGameOutput0, fullGameOutput1), spendingTransaction = gameOverTx, - self = fullGameOutput0 + self = fullGameOutput0, activatedVersionInTests ) val winContext1 = ErgoLikeContextTesting( @@ -205,7 +207,7 @@ class RPSGameExampleSpecification extends SigmaTestingCommons { minerPubkey = ErgoLikeContextTesting.dummyPubkey, boxesToSpend = IndexedSeq(fullGameOutput0, fullGameOutput1), spendingTransaction = gameOverTx, - self = fullGameOutput1 + self = fullGameOutput1, activatedVersionInTests ) a - b match { @@ -221,7 +223,7 @@ class RPSGameExampleSpecification extends SigmaTestingCommons { minerPubkey = ErgoLikeContextTesting.dummyPubkey, boxesToSpend = IndexedSeq(fullGameOutput0), spendingTransaction = gameOverTx, - self = fullGameOutput0 + self = fullGameOutput0, activatedVersionInTests ) val proofAliceDraw = aliceProver.prove(fullGameEnv, fullGameScript, drawContextAlice, fakeMessage).get @@ -233,7 +235,7 @@ class RPSGameExampleSpecification extends SigmaTestingCommons { minerPubkey = ErgoLikeContextTesting.dummyPubkey, boxesToSpend = IndexedSeq(fullGameOutput1), spendingTransaction = gameOverTx, - self = fullGameOutput1 + self = fullGameOutput1, activatedVersionInTests ) val proofBobDraw = bobProver.prove(fullGameEnv, fullGameScript, drawContextBob, fakeMessage).get @@ -282,7 +284,8 @@ class RPSGameExampleSpecification extends SigmaTestingCommons { minerPubkey = ErgoLikeContextTesting.dummyPubkey, boxesToSpend = IndexedSeq(fullGameOutput0, fullGameOutput1), spendingTransaction = defaultWinTx, - self = fullGameOutput0 // what is the use of self? + self = fullGameOutput0, // what is the use of self? + activatedVersionInTests ) val defaultWinContext1 = ErgoLikeContextTesting( currentHeight = defaultWinHeight, @@ -290,7 +293,8 @@ class RPSGameExampleSpecification extends SigmaTestingCommons { minerPubkey = ErgoLikeContextTesting.dummyPubkey, boxesToSpend = IndexedSeq(fullGameOutput0, fullGameOutput1), spendingTransaction = defaultWinTx, - self = fullGameOutput1 // what is the use of self? + self = fullGameOutput1, // what is the use of self? + activatedVersionInTests ) val sDummy = Array[Byte]() // empty value for s; commitment cannot be opened but still Bob will be able to spend diff --git a/sigmastate/src/test/scala/sigmastate/utxo/examples/ReversibleTxExampleSpecification.scala b/sigmastate/src/test/scala/sigmastate/utxo/examples/ReversibleTxExampleSpecification.scala index 60a07f4999..40084dd8ef 100644 --- a/sigmastate/src/test/scala/sigmastate/utxo/examples/ReversibleTxExampleSpecification.scala +++ b/sigmastate/src/test/scala/sigmastate/utxo/examples/ReversibleTxExampleSpecification.scala @@ -11,7 +11,8 @@ import sigmastate.interpreter.Interpreter.ScriptNameProp import sigmastate.lang.Terms._ -class ReversibleTxExampleSpecification extends SigmaTestingCommons { +class ReversibleTxExampleSpecification extends SigmaTestingCommons + with CrossVersionProps { private implicit lazy val IR: TestingIRContext = new TestingIRContext import ErgoAddressEncoder._ @@ -150,7 +151,7 @@ class ReversibleTxExampleSpecification extends SigmaTestingCommons { minerPubkey = ErgoLikeContextTesting.dummyPubkey, boxesToSpend = IndexedSeq(depositOutput), spendingTransaction = withdrawTx, - self = depositOutput + self = depositOutput, activatedVersionInTests ) val proofWithdraw = alice.prove(depositEnv, depositScript, withdrawContext, fakeMessage).get.proof @@ -179,7 +180,7 @@ class ReversibleTxExampleSpecification extends SigmaTestingCommons { minerPubkey = ErgoLikeContextTesting.dummyPubkey, boxesToSpend = IndexedSeq(reversibleWithdrawOutput), spendingTransaction = bobSpendTx, - self = reversibleWithdrawOutput + self = reversibleWithdrawOutput, activatedVersionInTests ) val spendEnv = Map(ScriptNameProp -> "spendEnv") @@ -206,7 +207,7 @@ class ReversibleTxExampleSpecification extends SigmaTestingCommons { minerPubkey = ErgoLikeContextTesting.dummyPubkey, boxesToSpend = IndexedSeq(reversibleWithdrawOutput), spendingTransaction = carolSpendTx, - self = reversibleWithdrawOutput + self = reversibleWithdrawOutput, activatedVersionInTests ) val proofCarolSpend = carol.prove(spendEnv, withdrawScript, carolSpendContext, fakeMessage).get.proof diff --git a/sigmastate/src/test/scala/sigmastate/utxo/examples/Rule110Specification.scala b/sigmastate/src/test/scala/sigmastate/utxo/examples/Rule110Specification.scala index ae80e4311d..9619ead6c1 100644 --- a/sigmastate/src/test/scala/sigmastate/utxo/examples/Rule110Specification.scala +++ b/sigmastate/src/test/scala/sigmastate/utxo/examples/Rule110Specification.scala @@ -18,7 +18,8 @@ import sigmastate.utxo.blockchain.BlockchainSimulationTestingCommons._ * Wolfram's Rule110 implementations * */ -class Rule110Specification extends SigmaTestingCommons { +class Rule110Specification extends SigmaTestingCommons + with CrossVersionProps { implicit lazy val IR = new TestingIRContext private val reg1 = ErgoBox.nonMandatoryRegisters.head private val reg2 = ErgoBox.nonMandatoryRegisters(1) @@ -62,7 +63,7 @@ class Rule110Specification extends SigmaTestingCommons { minerPubkey = ErgoLikeContextTesting.dummyPubkey, boxesToSpend = IndexedSeq(input), tx, - self = input).withCostLimit(maxCost) + self = input, activatedVersionInTests).withCostLimit(maxCost) val pr = prover.prove(prop, ctx, fakeMessage).get verifier.verify(prop, ctx, pr, fakeMessage).get._1 shouldBe true @@ -224,7 +225,7 @@ class Rule110Specification extends SigmaTestingCommons { minerPubkey = ErgoLikeContextTesting.dummyPubkey, boxesToSpend = IndexedSeq(nIn0, nIn1, nIn2), nTx, - self = nIn0) + self = nIn0, activatedVersionInTests) val nProof = nProver.prove(prop, nCtx, fakeMessage).get verifier.verify(prop, nCtx, nProof, fakeMessage).get._1 shouldBe true @@ -246,7 +247,7 @@ class Rule110Specification extends SigmaTestingCommons { minerPubkey = ErgoLikeContextTesting.dummyPubkey, boxesToSpend = IndexedSeq(rIn0, rIn1), rTx, - self = rIn0) + self = rIn0, activatedVersionInTests) val rProof = rProver.prove(prop, rCtx, fakeMessage).get verifier.verify(prop, rCtx, rProof, fakeMessage).get._1 shouldBe true @@ -268,7 +269,7 @@ class Rule110Specification extends SigmaTestingCommons { minerPubkey = ErgoLikeContextTesting.dummyPubkey, boxesToSpend = IndexedSeq(lnIn0, lnIn1), lnTx, - self = lnIn0) + self = lnIn0, activatedVersionInTests) val lnProof = lnProver.prove(prop, lnCtx, fakeMessage).get verifier.verify(prop, lnCtx, lnProof, fakeMessage).get._1 shouldBe true @@ -289,7 +290,7 @@ class Rule110Specification extends SigmaTestingCommons { minerPubkey = ErgoLikeContextTesting.dummyPubkey, boxesToSpend = IndexedSeq(lIn0), lTx, - self = lIn0) + self = lIn0, activatedVersionInTests) val lProof = lProver.prove(prop, lCtx, fakeMessage).get verifier.verify(prop, lCtx, lProof, fakeMessage).get._1 shouldBe true @@ -409,7 +410,7 @@ class Rule110Specification extends SigmaTestingCommons { ErgoLikeContextTesting.dummyPubkey ) - val genesisState = ValidationState.initialState(initBlock) + val genesisState = ValidationState.initialState(activatedVersionInTests, initBlock) def byPos(state: ValidationState, row: Int, pos: Int) = state.boxesReader.byTwoInts(RowReg, row, ColumnReg, pos).get @@ -445,6 +446,7 @@ class Rule110Specification extends SigmaTestingCommons { IndexedSeq(left, center, right), ut, left, + activatedVersionInTests, ContextExtension.empty) val proverResultLeft = prover.prove(left.ergoTree, contextLeft, ut.messageToSign).get @@ -454,6 +456,7 @@ class Rule110Specification extends SigmaTestingCommons { IndexedSeq(left, center, right), ut, center, + activatedVersionInTests, ContextExtension.empty) val proverResultCenter = prover.prove(center.ergoTree, contextCenter, ut.messageToSign).get @@ -463,6 +466,7 @@ class Rule110Specification extends SigmaTestingCommons { IndexedSeq(left, center, right), ut, right, + activatedVersionInTests, ContextExtension.empty) val proverResultRight = prover.prove(right.ergoTree, contextRight, ut.messageToSign).get ut.toSigned(IndexedSeq(proverResultLeft, proverResultCenter, proverResultRight)) diff --git a/sigmastate/src/test/scala/sigmastate/utxo/examples/TimedPaymentExampleSpecification.scala b/sigmastate/src/test/scala/sigmastate/utxo/examples/TimedPaymentExampleSpecification.scala index ad0e561324..d795f35bef 100644 --- a/sigmastate/src/test/scala/sigmastate/utxo/examples/TimedPaymentExampleSpecification.scala +++ b/sigmastate/src/test/scala/sigmastate/utxo/examples/TimedPaymentExampleSpecification.scala @@ -10,7 +10,8 @@ import sigmastate.lang.Terms._ import sigmastate.lang.exceptions.InterpreterException -class TimedPaymentExampleSpecification extends SigmaTestingCommons { +class TimedPaymentExampleSpecification extends SigmaTestingCommons + with CrossVersionProps { private implicit lazy val IR: TestingIRContext = new TestingIRContext import ErgoAddressEncoder._ @@ -63,7 +64,8 @@ class TimedPaymentExampleSpecification extends SigmaTestingCommons { minerPubkey = ErgoLikeContextTesting.dummyPubkey, boxesToSpend = IndexedSeq(depositOutput), spendingTransaction = withdrawTx, - self = depositOutput + self = depositOutput, + activatedVersionInTests ) val proofWithdraw = alice.withContextExtender( @@ -80,7 +82,8 @@ class TimedPaymentExampleSpecification extends SigmaTestingCommons { minerPubkey = ErgoLikeContextTesting.dummyPubkey, boxesToSpend = IndexedSeq(depositOutput), spendingTransaction = withdrawTx, - self = depositOutput + self = depositOutput, + activatedVersionInTests ) an [InterpreterException] should be thrownBy (alice.withContextExtender( 1, IntConstant(confDeadline - 20) diff --git a/sigmastate/src/test/scala/sigmastate/utxo/examples/XorGameExampleSpecification.scala b/sigmastate/src/test/scala/sigmastate/utxo/examples/XorGameExampleSpecification.scala index 46d67b19d3..b53aa6beb6 100644 --- a/sigmastate/src/test/scala/sigmastate/utxo/examples/XorGameExampleSpecification.scala +++ b/sigmastate/src/test/scala/sigmastate/utxo/examples/XorGameExampleSpecification.scala @@ -12,7 +12,8 @@ import sigmastate.helpers.TestingHelpers._ import sigmastate.interpreter.Interpreter._ import sigmastate.lang.Terms._ -class XorGameExampleSpecification extends SigmaTestingCommons { +class XorGameExampleSpecification extends SigmaTestingCommons + with CrossVersionProps { private implicit lazy val IR: TestingIRContext = new TestingIRContext /** XOR game: @@ -149,7 +150,8 @@ class XorGameExampleSpecification extends SigmaTestingCommons { minerPubkey = ErgoLikeContextTesting.dummyPubkey, boxesToSpend = IndexedSeq(halfGameOutput), spendingTransaction = abortHalfGameTx, - self = halfGameOutput // what is the use of self? + self = halfGameOutput, // what is the use of self? + activatedVersionInTests ) val proofAbortHalfGame = alice.prove(halfGameEnv, halfGameScript, abortHalfGameContext, fakeMessage).get.proof @@ -185,7 +187,8 @@ class XorGameExampleSpecification extends SigmaTestingCommons { minerPubkey = ErgoLikeContextTesting.dummyPubkey, boxesToSpend = IndexedSeq(halfGameOutput), spendingTransaction = fullGameTx, - self = halfGameOutput // what is the use of self? + self = halfGameOutput, // what is the use of self? + activatedVersionInTests ) // bob (2nd player) is generating a proof and it is passing verification @@ -235,7 +238,8 @@ class XorGameExampleSpecification extends SigmaTestingCommons { minerPubkey = ErgoLikeContextTesting.dummyPubkey, boxesToSpend = IndexedSeq(fullGameOutput), spendingTransaction = gameOverTx, - self = fullGameOutput // what is the use of self? + self = fullGameOutput, // what is the use of self? + activatedVersionInTests ) val proofGameOver = winner.prove(fullGameEnv, fullGameScript, gameOverContext, fakeMessage).get @@ -262,7 +266,8 @@ class XorGameExampleSpecification extends SigmaTestingCommons { minerPubkey = ErgoLikeContextTesting.dummyPubkey, boxesToSpend = IndexedSeq(fullGameOutput), spendingTransaction = defaultWinTx, - self = fullGameOutput // what is the use of self? + self = fullGameOutput, // what is the use of self? + activatedVersionInTests ) val sDummy = Array[Byte]() // empty value for s; commitment cannot be opened but still Bob will be able to spend diff --git a/sigmastate/src/test/scala/special/sigma/SigmaDslSpecification.scala b/sigmastate/src/test/scala/special/sigma/SigmaDslSpecification.scala index 6e4c20feab..a5ad065d45 100644 --- a/sigmastate/src/test/scala/special/sigma/SigmaDslSpecification.scala +++ b/sigmastate/src/test/scala/special/sigma/SigmaDslSpecification.scala @@ -40,7 +40,7 @@ import scala.collection.mutable /** This suite tests every method of every SigmaDsl type to be equivalent to * the evaluation of the corresponding ErgoScript operation */ -class SigmaDslSpecification extends SigmaDslTesting { suite => +class SigmaDslSpecification extends SigmaDslTesting with CrossVersionProps { suite => override implicit val generatorDrivenConfig = PropertyCheckConfiguration(minSuccessful = 30) @@ -2349,8 +2349,6 @@ class SigmaDslSpecification extends SigmaDslTesting { suite => // doApply((CFunc[Int, Int](ctx, code), 10)) // } - lazy val ctx = ergoCtx.toSigmaContext(false) - property("Box properties equivalence") { val b1 = CostingBox( false, diff --git a/sigmastate/src/test/scala/special/sigma/SigmaDslTesting.scala b/sigmastate/src/test/scala/special/sigma/SigmaDslTesting.scala index 3c9265cb3c..580f9cd7c1 100644 --- a/sigmastate/src/test/scala/special/sigma/SigmaDslTesting.scala +++ b/sigmastate/src/test/scala/special/sigma/SigmaDslTesting.scala @@ -246,12 +246,14 @@ class SigmaDslTesting extends PropSpec new ErgoLikeContext( treeData, ctx.headers, ctx.preHeader, dataBoxes, boxesToSpend, tx, selfIndex, - extension, validationSettings, costLimit, initCost) + extension, validationSettings, costLimit, initCost, + activatedVersionInTests) } - /** Executes the default feature verification wrapper script using: - * 1) the given input - * 2) the given expected results (values and costs) + /** Executes the default feature verification wrapper script for the specific ErgoTree + * version. + * @param input the given input + * @param expected the given expected results (values and costs) */ def checkVerify(input: A, expected: Expected[B]): Unit = { val tpeA = Evaluation.rtypeToSType(oldF.tA) @@ -291,7 +293,8 @@ class SigmaDslTesting extends PropSpec pkAlice, DeserializeRegister(ErgoBox.R5, SSigmaProp), // deserialize pkBob DeserializeContext(2, SSigmaProp))) // deserialize pkCarol - ErgoTree.fromProposition(sigmastate.SigmaOr(prop, multisig)) + val header = ErgoTree.headerWithVersion(ergoTreeVersionInTests) + ErgoTree.withSegregation(header, sigmastate.SigmaOr(prop, multisig)) } val pkBobBytes = ValueSerializer.serialize(prover.pubKeys(1).toSigmaProp) @@ -332,7 +335,8 @@ class SigmaDslTesting extends PropSpec case _ => ErgoLikeContextTesting.dummy( - createBox(0, compiledTree, additionalRegisters = newRegisters) + createBox(0, compiledTree, additionalRegisters = newRegisters), + activatedVersionInTests ).withBindings( 1.toByte -> Constant[SType](input.asInstanceOf[SType#WrappedType], tpeA), 2.toByte -> ByteArrayConstant(pkCarolBytes) diff --git a/sigmastate/src/test/scala/special/sigma/SigmaTestingData.scala b/sigmastate/src/test/scala/special/sigma/SigmaTestingData.scala index cd0be01249..0568b8ec28 100644 --- a/sigmastate/src/test/scala/special/sigma/SigmaTestingData.scala +++ b/sigmastate/src/test/scala/special/sigma/SigmaTestingData.scala @@ -61,17 +61,6 @@ trait SigmaTestingData extends SigmaTestingCommons with SigmaTypeGens { val tokenId1: Digest32 = Blake2b256("id1") val tokenId2: Digest32 = Blake2b256("id2") - val inBox = createBox(10, TrivialProp.TrueProp, - Seq(tokenId1 -> 10L, tokenId2 -> 20L), - Map(ErgoBox.R4 -> IntConstant(100), ErgoBox.R5 -> BooleanConstant(true))) - - val dataBox = createBox(1000, TrivialProp.TrueProp, - Seq(tokenId1 -> 10L, tokenId2 -> 20L), - Map(ErgoBox.R4 -> IntConstant(100), ErgoBox.R5 -> BooleanConstant(true))) - - val outBox = createBox(10, TrivialProp.TrueProp, - Seq(tokenId1 -> 10L, tokenId2 -> 20L), - Map(ErgoBox.R4 -> IntConstant(100), ErgoBox.R5 -> BooleanConstant(true))) val header1: Header = CHeader(Blake2b256("Header.id").toColl, 0, @@ -114,12 +103,4 @@ trait SigmaTestingData extends SigmaTestingCommons with SigmaTypeGens { minerPk = SigmaDsl.groupGenerator, votes = Colls.emptyColl[Byte] ) - val ergoCtx = new ErgoLikeContext( - lastBlockUtxoRoot = header2.stateRoot.asInstanceOf[CAvlTree].treeData, - boxesToSpend = IndexedSeq(inBox), - spendingTransaction = new ErgoLikeTransaction(IndexedSeq(), IndexedSeq(DataInput(dataBox.id)), IndexedSeq(outBox)), - selfIndex = 0, headers = headers, preHeader = preHeader, dataBoxes = IndexedSeq(dataBox), - extension = ContextExtension(Map(2.toByte -> IntConstant(10))), - validationSettings = ValidationRules.currentSettings, - costLimit = ScriptCostLimit.value, initCost = 0L) }