diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 17d49677ab..de56162027 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -21,7 +21,7 @@ jobs: strategy: matrix: os: [ubuntu-latest] - scala: [2.13.8, 2.12.10, 2.11.12] + scala: [2.13.12, 2.12.18, 2.11.12] java: [adopt@1.8] runs-on: ${{ matrix.os }} steps: @@ -62,7 +62,7 @@ jobs: strategy: matrix: os: [ubuntu-latest] - scala: [2.12.10] + scala: [2.12.18] java: [adopt@1.8] runs-on: ${{ matrix.os }} steps: diff --git a/.github/workflows/release-binaries.yml b/.github/workflows/release-binaries.yml new file mode 100644 index 0000000000..adf302ea2d --- /dev/null +++ b/.github/workflows/release-binaries.yml @@ -0,0 +1,27 @@ +name: Publish release-binaries + +on: + release: + types: [published] + +env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + +jobs: + release-binaries: + name: Publish release binaries + runs-on: macos-latest + env: + ERGO_RELEASE_PLATFORM: macos-x64 + ERGO_RELEASE_TAG: ${{ github.event.release.tag_name }} + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-python@v4 + - name: Download ergo node jar + run: | + echo $GITHUB_REF + gh release download $ERGO_RELEASE_TAG -p "ergo*" + - name: Create release binary files + run: python ci/release-binaries.py + - name: Put binary files into release + run: gh release upload $ERGO_RELEASE_TAG $(echo $(find release -name "ergo-node-*")) diff --git a/avldb/build.sbt b/avldb/build.sbt index 7add06c7d9..c37c3f36c4 100644 --- a/avldb/build.sbt +++ b/avldb/build.sbt @@ -1,24 +1,33 @@ import sbt.Keys.testFrameworks +val scala211 = "2.11.12" +val scala212 = "2.12.18" +val scala213 = "2.13.12" + name := "avldb" +val Versions = new { + + val spire = (scalaVersion: String) => + if (scalaVersion == scala213) "0.17.0" + else "0.14.1" + + val scalameter = (scalaVersion: String) => + if (scalaVersion == scala213) "0.19" + else "0.9" +} + libraryDependencies ++= Seq( "javax.xml.bind" % "jaxb-api" % "2.4.0-b180830.0359", "ch.qos.logback" % "logback-classic" % "1.2.3", "com.google.guava" % "guava" % "23.0", - "org.scorexfoundation" %% "scrypto" % "2.3.0" -) - -libraryDependencies ++= Seq( + "org.scorexfoundation" %% "scrypto" % "2.3.0", "org.scalatest" %% "scalatest" % "3.1.1" % "test", "org.scalacheck" %% "scalacheck" % "1.14.3" % "test", "org.scalatestplus" %% "scalatestplus-scalacheck" % "3.1.0.0-RC2" % Test, - "com.storm-enroute" %% "scalameter" % "0.9" % "test" -) - -libraryDependencies ++= Seq( + "com.storm-enroute" %% "scalameter" % Versions.scalameter(scalaVersion.value) % "test", "org.ethereum" % "leveldbjni-all" % "1.18.3", - "org.typelevel" %% "spire" % "0.14.1" + "org.typelevel" %% "spire" % Versions.spire(scalaVersion.value) ) testOptions in Test := Seq(Tests.Filter(t => !t.matches(".*Benchmark$"))) @@ -38,13 +47,13 @@ publishTo := { pomIncludeRepository := { _ => false } -scalacOptions ++= Seq("-Xfatal-warnings", "-feature", "-deprecation") +scalacOptions ++= Seq("-feature", "-deprecation") // set bytecode version to 8 to fix NoSuchMethodError for various ByteBuffer methods // see https://github.com/eclipse/jetty.project/issues/3244 // these options applied only in "compile" task since scalac crashes on scaladoc compilation with "-release 8" // see https://github.com/scala/community-builds/issues/796#issuecomment-423395500 -scalacOptions in(Compile, compile) ++= Seq("-release", "8") -scalacOptions --= Seq("-Ywarn-numeric-widen", "-Ywarn-value-discard") +scalacOptions in(Compile, compile) ++= (if (scalaBinaryVersion.value == "2.11") Seq() else Seq("-release", "8")) +scalacOptions --= Seq("-Ywarn-numeric-widen", "-Ywarn-value-discard", "-Ywarn-unused:params", "-Xfatal-warnings") enablePlugins(ReproducibleBuildsPlugin) \ No newline at end of file diff --git a/avldb/src/main/scala/scorex/crypto/authds/avltree/batch/VersionedLDBAVLStorage.scala b/avldb/src/main/scala/scorex/crypto/authds/avltree/batch/VersionedLDBAVLStorage.scala index 2d541569e7..95d8e536dc 100644 --- a/avldb/src/main/scala/scorex/crypto/authds/avltree/batch/VersionedLDBAVLStorage.scala +++ b/avldb/src/main/scala/scorex/crypto/authds/avltree/batch/VersionedLDBAVLStorage.scala @@ -114,7 +114,7 @@ class VersionedLDBAVLStorage(store: LDBVersionedStore) } def dumpSubtree(sid: DigestType): Try[Unit] = { - val builder = mutable.ArrayBuilder.make[Byte]() + val builder = new mutable.ArrayBuilder.ofByte builder.sizeHint(200000) subtreeLoop(sid, builder) dumpStorage.insert(sid, builder.result()) @@ -141,7 +141,7 @@ class VersionedLDBAVLStorage(store: LDBVersionedStore) require(rootNodeLabel.sameElements(expectedRootHash), "Root node hash changed") - val manifestBuilder = mutable.ArrayBuilder.make[Byte]() + val manifestBuilder = new mutable.ArrayBuilder.ofByte manifestBuilder.sizeHint(200000) manifestBuilder += rootNodeHeight manifestBuilder += manifestDepth diff --git a/avldb/src/main/scala/scorex/db/ByteArrayUtils.scala b/avldb/src/main/scala/scorex/db/ByteArrayUtils.scala index c39784f919..23a5b92280 100644 --- a/avldb/src/main/scala/scorex/db/ByteArrayUtils.scala +++ b/avldb/src/main/scala/scorex/db/ByteArrayUtils.scala @@ -2,14 +2,14 @@ package scorex.db object ByteArrayUtils { - import java.util.Comparator - // Java comparator - val BYTE_ARRAY_COMPARATOR: Comparator[Array[Byte]] = (o1: Array[Byte], o2: Array[Byte]) => compare(o1, o2) - + object BYTE_ARRAY_COMPARATOR extends Ordering[Array[Byte]] { + def compare(o1: Array[Byte], o2: Array[Byte]) = compare(o1, o2) + } // Scala comparator - implicit val ByteArrayOrdering: Ordering[Array[Byte]] = - (o1: Array[Byte], o2: Array[Byte]) => ByteArrayUtils.compare(o1, o2) + implicit object ByteArrayOrdering extends Ordering[Array[Byte]] { + def compare(o1: Array[Byte], o2: Array[Byte]) = ByteArrayUtils.compare(o1, o2) + } def compare(o1: Array[Byte], o2: Array[Byte]): Int = { val len = Math.min(o1.length, o2.length) diff --git a/avldb/src/main/scala/scorex/db/LDBKVStore.scala b/avldb/src/main/scala/scorex/db/LDBKVStore.scala index 035e43510a..1c8215315f 100644 --- a/avldb/src/main/scala/scorex/db/LDBKVStore.scala +++ b/avldb/src/main/scala/scorex/db/LDBKVStore.scala @@ -82,7 +82,7 @@ class LDBKVStore(protected val db: DB) extends KVStoreReader with ScorexLogging breakable { while (i.hasNext) { val key = i.next().getKey - if (ByteArrayUtils.compare(key, last) <= 0) res = Some(key) else break + if (ByteArrayUtils.compare(key, last) <= 0) res = Some(key) else break() } } res diff --git a/avldb/src/test/scala/scorex/db/ByteArrayUtilsSpec.scala b/avldb/src/test/scala/scorex/db/ByteArrayUtilsSpec.scala index 714954f611..2e39a304c5 100644 --- a/avldb/src/test/scala/scorex/db/ByteArrayUtilsSpec.scala +++ b/avldb/src/test/scala/scorex/db/ByteArrayUtilsSpec.scala @@ -6,6 +6,8 @@ import org.scalatest.matchers.should.Matchers import org.scalatest.propspec.AnyPropSpec import org.scalatestplus.scalacheck.ScalaCheckPropertyChecks +import scala.math.Ordering.Implicits._ + class ByteArrayUtilsSpec extends AnyPropSpec with ScalaCheckPropertyChecks with Matchers { lazy val nonEmptyBytesGen: Gen[Array[Byte]] = Gen.nonEmptyListOf(Arbitrary.arbitrary[Byte]) @@ -13,10 +15,11 @@ class ByteArrayUtilsSpec extends AnyPropSpec with ScalaCheckPropertyChecks with property("compare works properly") { - //Simple and inefficient way to order byte arrays, based on - // https://stackoverflow.com/questions/7109943/how-to-define-orderingarraybyte - // but we compare unsigned bytes - val ordering: Ordering[Array[Byte]] = Ordering.by((_: Array[Byte]).toIterable.map(_ & 0xFF)) + val ordering: Ordering[Array[Byte]] = + new Ordering[Array[Byte]] { + override def compare(o1: Array[Byte], o2: Array[Byte]): Int = + implicitly[Ordering[Seq[Int]]].compare(o1.toSeq.map(_ & 0xFF), o2.toSeq.map(_ & 0xFF)) + } forAll(nonEmptyBytesGen, nonEmptyBytesGen) { case (bs1, bs2) => val efficientOrdering = Seq(bs1, bs2).sorted(ByteArrayUtils.ByteArrayOrdering) diff --git a/build.sbt b/build.sbt index dccd41e4b1..c173d2fc1c 100644 --- a/build.sbt +++ b/build.sbt @@ -5,8 +5,8 @@ logLevel := Level.Debug // this values should be in sync with ergo-wallet/build.sbt val scala211 = "2.11.12" -val scala212 = "2.12.10" -val scala213 = "2.13.8" +val scala212 = "2.12.18" +val scala213 = "2.13.12" lazy val commonSettings = Seq( organization := "org.ergoplatform", @@ -44,16 +44,10 @@ val ficusVersion = "1.4.7" val effectiveSigmaStateVersion = Option(System.getenv().get("SIGMASTATE_VERSION")).getOrElse(sigmaStateVersion) val effectiveSigma = "org.scorexfoundation" %% "sigma-state" % effectiveSigmaStateVersion - libraryDependencies ++= Seq( effectiveSigma.force() .exclude("ch.qos.logback", "logback-classic") .exclude("org.scorexfoundation", "scrypto"), - - // api dependencies - "io.circe" %% "circe-core" % circeVersion, - "io.circe" %% "circe-generic" % circeVersion, - "io.circe" %% "circe-parser" % circeVersion, "ch.qos.logback" % "logback-classic" % "1.3.5", @@ -208,14 +202,17 @@ scapegoatDisabledInspections := Seq("FinalModifierOnCaseClass") Test / testOptions := Seq(Tests.Filter(s => !s.endsWith("Bench"))) lazy val avldb = (project in file("avldb")) + .disablePlugins(ScapegoatSbtPlugin) // not compatible with crossScalaVersions .settings( + crossScalaVersions := Seq(scala213, scalaVersion.value, scala211), commonSettings, name := "avldb", // set bytecode version to 8 to fix NoSuchMethodError for various ByteBuffer methods // see https://github.com/eclipse/jetty.project/issues/3244 // these options applied only in "compile" task since scalac crashes on scaladoc compilation with "-release 8" // see https://github.com/scala/community-builds/issues/796#issuecomment-423395500 - scalacOptions in(Compile, compile) ++= Seq("-release", "8"), + scalacOptions in(Compile, compile) ++= (if (scalaBinaryVersion.value == "2.11") Seq() else Seq("-release", "8")), + scalacOptions in(Compile, compile) --= scalacOpts, javacOptions in(Compile, compile) ++= javacReleaseOption, libraryDependencies ++= Seq( // database dependencies @@ -244,9 +241,11 @@ lazy val avldb_benchmarks = (project in file("avldb/benchmarks")) .enablePlugins(JmhPlugin) lazy val ergoCore = (project in file("ergo-core")) + .disablePlugins(ScapegoatSbtPlugin) // not compatible with crossScalaVersions .dependsOn(avldb % "test->test;compile->compile") .dependsOn(ergoWallet % "test->test;compile->compile") .settings( + crossScalaVersions := Seq(scala213, scalaVersion.value, scala211), commonSettings, name := "ergo-core", libraryDependencies ++= Seq( @@ -254,7 +253,7 @@ lazy val ergoCore = (project in file("ergo-core")) effectiveSigma, (effectiveSigma % Test).classifier("tests") ), - scalacOptions in(Compile, compile) ++= Seq("-release", "8"), + scalacOptions in(Compile, compile) ++= (if (scalaBinaryVersion.value == "2.11") Seq() else Seq("-release", "8")), scalacOptions in(Compile, compile) --= scalacOpts, ) @@ -293,12 +292,18 @@ lazy val ergo = (project in file(".")) scalacOptions in(Compile, compile) ++= Seq("-release", "8"), javacOptions in(Compile, compile) ++= javacReleaseOption, libraryDependencies ++= Seq( + // api dependencies + "io.circe" %% "circe-core" % circeVersion, + "io.circe" %% "circe-generic" % circeVersion, + "io.circe" %% "circe-parser" % circeVersion, // network dependencies "com.typesafe.akka" %% "akka-stream" % akkaVersion, // required for akka-http to compile "com.typesafe.akka" %% "akka-actor" % akkaVersion, // required for akka-http to compile "com.typesafe.akka" %% "akka-http" % akkaHttpVersion, "com.typesafe.akka" %% "akka-http-core" % akkaHttpVersion, "com.typesafe.akka" %% "akka-parsing" % akkaHttpVersion, + "com.typesafe.akka" %% "akka-slf4j" % akkaVersion, + "org.bitlet" % "weupnp" % "0.1.4", // command line args parsing "com.github.scopt" %% "scopt" % "4.0.1", diff --git a/ci/ergo.icns b/ci/ergo.icns new file mode 100644 index 0000000000..31e74399d7 Binary files /dev/null and b/ci/ergo.icns differ diff --git a/ci/release-binaries.py b/ci/release-binaries.py new file mode 100644 index 0000000000..6c79be04c0 --- /dev/null +++ b/ci/release-binaries.py @@ -0,0 +1,227 @@ +import os +import tarfile +import urllib.request +import zipfile +import shutil +import logging +import subprocess +from multiprocessing.pool import ThreadPool +from itertools import repeat + +MICROSOFT_URL = "https://aka.ms/download-jdk/microsoft-jdk-21.0.1-" +JRE_SUBFOLDER = "jdk-21.0.1+12" +JDKS = { + "windows-x64": "windows-x64.zip", + "linux-x64": "linux-x64.tar.gz", + "macos-x64": "macos-x64.tar.gz", + "windows-aarch64": "windows-aarch64.zip", + "linux-aarch64": "linux-aarch64.tar.gz", + "macos-aarch64": "macos-aarch64.tar.gz", +} + +# Specific to ergo-node .jap, collected with jdeps +JLINK_MODULES = "java.base,java.compiler,java.desktop,java.management,java.naming,java.rmi,java.sql,jdk.unsupported" + +MAIN_JRE = os.environ.get("ERGO_RELEASE_PLATFORM") +VERSION = os.environ.get("ERGO_RELEASE_TAG") + +JAR_FILENAME = f"ergo-{VERSION}.jar" +SCRIPT_LOGO = f""" + + .-*%@#+-. + .-+#@@%*=-=*%@@#+-. + +@@#+- :=*@@+ + -@@: ......... :@@- + .@@- #@@@@@@@% -@@: .@@@@@@@-:@@@@@%*. .+%@@@%+. .+%@@@%+. + %@+ .*@@*. =@@. :@@:.... :@@:..+@@ =@@=. .=*= -@@=. .=@@= + #@# .%@@= *@% :@@%%%%%.:@@+++%@# @@= .+++++ %@+ =@@ + =@@. .*@@= .@@= :@@-:::: :@@+#@@- #@# .==*@@.#@# *@% + *@% =@@@*+++= %@* :@@*****::@@. =@@: .#@@*+*%@% *@@*+*%@#. + #@# +#######* *@% =======..== :== .-=++-. .-=+=-. + %@*. .+@@. + .#@@@#+-. .-+#@@%*: Node version: {VERSION} + .-+#@@@#%@@#+-. + + +""" +def download_jdk(url): + final_url = MICROSOFT_URL + url + logging.warning(f"Downloading {final_url}") + urllib.request.urlretrieve(final_url, url) + +def unarchive_jdk(filename, directory): + logging.warning(f"Extracting {filename} into {directory}") + if filename.endswith("tar.gz"): + tar = tarfile.open(filename, "r:gz") + tar.extractall(directory) + tar.close() + elif filename.endswith("zip"): + with zipfile.ZipFile(filename, 'r') as zip_ref: + zip_ref.extractall(directory) + +def create_jre(jlink, target_jre_dir, out_jre_dir): + subprocess.run([ + jlink, + "--module-path", + os.path.join(target_jre_dir, "jmods"), + "--add-modules", + JLINK_MODULES, + "--strip-debug", + "--compress", "2", + "--no-header-files", + "--no-man-pages", + "--output", + out_jre_dir + ], check=True) + +def make_windows(target): + app_dir = f"{target}/ergo-node" + os.makedirs(app_dir, exist_ok=True) + app_script = f""" +Write-Host @" + +{SCRIPT_LOGO} + +"@ -ForegroundColor Red +jre/bin/java -jar -Xmx4G {JAR_FILENAME} --mainnet -c ergo.conf + """ + with open(f"{app_dir}/ergo-node.ps1", "w") as f: + f.write(app_script) + + shutil.copytree(f"{target}/jre", f"{app_dir}/jre") + shutil.copyfile(JAR_FILENAME, f"{app_dir}/{JAR_FILENAME}") + shutil.copyfile("ergo.conf", f"{app_dir}/ergo.conf") + shutil.make_archive(f"release/ergo-node-{VERSION}-{target}", 'zip', app_dir) + +def make_linux(target): + app_dir = f"{target}/ergo-node" + os.makedirs(app_dir, exist_ok=True) + + app_script = f"""#!/bin/env sh +echo '\033[0;31m' +cat << EOF + +{SCRIPT_LOGO} + +EOF +echo '\033[0m' +./jre/bin/java -jar -Xmx4G {JAR_FILENAME} --mainnet -c ergo.conf +exit + """ + with open(f"{app_dir}/ergo-node.sh", "w") as f: + f.write(app_script) + os.chmod(f"{app_dir}/ergo-node.sh", 0o755) + + shutil.copytree(f"{target}/jre", f"{app_dir}/jre") + shutil.copyfile(JAR_FILENAME, f"{app_dir}/{JAR_FILENAME}") + shutil.copyfile("ergo.conf", f"{app_dir}/ergo.conf") + with tarfile.open(f"release/ergo-node-{VERSION}-{target}.tar.gz", "w:gz") as tar: + tar.add(app_dir) + +def make_macos(target): + app_dir = f"{target}/ErgoNode.app" + os.makedirs(app_dir, exist_ok=True) + os.makedirs(f"{app_dir}/Contents/MacOS", exist_ok=True) + os.makedirs(f"{app_dir}/Contents/Resources", exist_ok=True) + + info_plist = f"""<?xml version="1.0" encoding="UTF-8"?> + <!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> + <plist version="1.0"> + <dict> + <key>CFBundleExecutable</key> + <string>start.command</string> + <key>CFBundleIdentifier</key> + <string>org.ergoplatform.ergo-node</string> + <key>CFBundleName</key> + <string>Ergo Node</string> + <key>CFBundleIconFile</key> + <string>ergo.icns</string> + <key>CFBundleVersion</key> + <string>{VERSION}</string> + </dict> + </plist> + """ + with open(f"{app_dir}/Contents/info.plist", "w") as f: + f.write(info_plist) + + app_script = f"""#!/bin/zsh +SRC=$(cd "$(dirname "$0")"; pwd -P) +echo '\033[0;31m' +cat << EOF + +{SCRIPT_LOGO} + +EOF +echo '\033[0m' +$SRC/jre/bin/java -jar -Xmx4G $SRC/{JAR_FILENAME} --mainnet -c $SRC/ergo.conf + +exit + """ + app_script_file = "ergo-node.sh" + with open(f"{app_dir}/Contents/MacOS/{app_script_file}", "w") as f: + f.write(app_script) + + # Require nested script for macos Terminal app to open + start_command = f"""#!/bin/zsh +MY_PATH=$(cd "$(dirname "$0")"; pwd -P) +open -a Terminal $MY_PATH/{app_script_file} + """ + start_command_file = "start.command" + with open(f"{app_dir}/Contents/MacOS/{start_command_file}", "w") as f: + f.write(start_command) + os.chmod(f"{app_dir}/Contents/MacOS/{app_script_file}", 0o755) + os.chmod(f"{app_dir}/Contents/MacOS/{start_command_file}", 0o755) + + shutil.copytree(f"{target}/jre", f"{app_dir}/Contents/MacOS/jre") + shutil.copyfile(JAR_FILENAME, f"{app_dir}/Contents/MacOS/{JAR_FILENAME}") + shutil.copyfile("ergo.conf", f"{app_dir}/Contents/MacOS/ergo.conf") + shutil.copyfile("ci/ergo.icns", f"{app_dir}/Contents/Resources/ergo.icns") + + with tarfile.open(f"release/ergo-node-{VERSION}-{target}.tar.gz", "w:gz") as tar: + tar.add(app_dir) + +def process_download(entry): + (os_type, filename) = entry + download_jdk(filename) + unarchive_jdk(filename, os_type) + +def process_jres(os_type, main_jre): + logging.warning(f"Creating jre for {os_type}") + if (os_type.startswith("macos")): + create_jre(main_jre, os.path.join(os_type, JRE_SUBFOLDER, "Contents", "Home"), os_type + "/jre") + make_macos(os_type) + if (os_type.startswith("linux")): + create_jre(main_jre, os.path.join(os_type, JRE_SUBFOLDER), os_type + "/jre") + make_linux(os_type) + if (os_type.startswith("windows")): + create_jre(main_jre, os.path.join(os_type, JRE_SUBFOLDER), os_type + "/jre") + make_windows(os_type) + +def get_main_jre(jre, subfolder) -> str: + if (jre.startswith("windows")): + return os.path.join(jre, subfolder, "bin", "jlink.exe") + elif (jre.startswith("macos")): + return os.path.join(jre, subfolder, "Contents", "Home", "bin", "jlink") + else: #linux + return os.path.join(jre, subfolder, "bin", "jlink") + +logging.warning(f"Starting release binaries for ergo-node") + +main_jre = get_main_jre(MAIN_JRE, JRE_SUBFOLDER) +os.makedirs("release", exist_ok=True) + +ergo_conf = """ +ergo { + node { + mining = false + } +} +""" +with open("ergo.conf", "w") as f: + f.write(ergo_conf) + +with ThreadPool(JDKS.__len__()) as pool: + pool.map(process_download, JDKS.items()) + +with ThreadPool(JDKS.__len__()) as pool: + pool.starmap(process_jres, zip(JDKS.keys(), repeat(main_jre))) diff --git a/ergo-core/build.sbt b/ergo-core/build.sbt index b92786aef0..33edb4387e 100644 --- a/ergo-core/build.sbt +++ b/ergo-core/build.sbt @@ -1,4 +1,19 @@ // this values should be in sync with root (i.e. ../build.sbt) val scala211 = "2.11.12" -val scala212 = "2.12.10" -val scala213 = "2.13.8" \ No newline at end of file +val scala212 = "2.12.18" +val scala213 = "2.13.12" + +val deps211 = Seq( + "io.circe" %% "circe-core" % "0.10.0", + "io.circe" %% "circe-generic" % "0.10.0", + "io.circe" %% "circe-parser" % "0.10.0") +val deps212 = Seq( + "io.circe" %% "circe-core" % "0.13.0", + "io.circe" %% "circe-generic" % "0.13.0", + "io.circe" %% "circe-parser" % "0.13.0") + +libraryDependencies ++= Seq() ++ + (if (scalaVersion.value == scala211) deps211 else deps212) + +scalacOptions ++= (if (scalaBinaryVersion.value == scala211) Seq("-language:implicitConversions") else Seq()) +scalacOptions --= Seq("-Ywarn-numeric-widen", "-Ywarn-value-discard", "-Ywarn-unused:params", "-Xfatal-warnings") \ No newline at end of file diff --git a/ergo-core/src/main/scala/org/ergoplatform/http/api/ApiCodecs.scala b/ergo-core/src/main/scala/org/ergoplatform/http/api/ApiCodecs.scala index 625531218f..1b6c9b2214 100644 --- a/ergo-core/src/main/scala/org/ergoplatform/http/api/ApiCodecs.scala +++ b/ergo-core/src/main/scala/org/ergoplatform/http/api/ApiCodecs.scala @@ -1,5 +1,6 @@ package org.ergoplatform.http.api +import cats.syntax.either._ import io.circe._ import io.circe.syntax._ import org.bouncycastle.util.BigIntegers @@ -30,8 +31,10 @@ import sigmastate.interpreter._ import sigmastate.serialization.OpCodes import org.ergoplatform.sdk.JsonCodecs import sigmastate.eval.Extensions.ArrayOps +import sigmastate.utils.Helpers._ import java.math.BigInteger +import scala.annotation.nowarn import scala.util.{Failure, Success, Try} @@ -42,68 +45,67 @@ trait ApiCodecs extends JsonCodecs { fromTry(validationResult.toTry) } - implicit val leafDataEncoder: Encoder[LeafData] = xs => Base16.encode(xs).asJson + implicit val leafDataEncoder: Encoder[LeafData] = Encoder.instance(xs => Base16.encode(xs).asJson) - implicit val digestEncoder: Encoder[Digest] = x => Base16.encode(x).asJson + implicit val digestEncoder: Encoder[Digest] = Encoder.instance(x => Base16.encode(x).asJson) - implicit val sideEncoder: Encoder[Side] = _.toByte.asJson + implicit val sideEncoder: Encoder[Side] = Encoder.instance(_.toByte.asJson) implicit val ergoAddressEncoder: ErgoAddressEncoder = null - protected implicit def merkleProofEncoder[D <: Digest]: Encoder[MerkleProof[D]] = { proof => + protected implicit def merkleProofEncoder[D <: Digest]: Encoder[MerkleProof[D]] = Encoder.instance({ proof => Json.obj( "leafData" -> proof.leafData.asJson, - "levels" -> proof.levels.asJson, - ) - } + "levels" -> proof.levels.asJson) + }) - implicit val secretStringEncoder: Encoder[SecretString] = { secret => + implicit val secretStringEncoder: Encoder[SecretString] = Encoder.instance({ secret => secret.toStringUnsecure.asJson - } + }) - implicit val bigIntEncoder: Encoder[BigInt] = { bigInt => + implicit val bigIntEncoder: Encoder[BigInt] = Encoder.instance({ bigInt => JsonNumber.fromDecimalStringUnsafe(bigInt.toString).asJson - } + }) implicit val difficultyEncoder: Encoder[Difficulty] = bigIntEncoder - implicit val ecPointDecoder: Decoder[EcPointType] = { implicit cursor => + implicit val ecPointDecoder: Decoder[EcPointType] = Decoder.instance { implicit cursor => for { str <- cursor.as[String] bytes <- fromTry(Algos.decode(str)) } yield groupElemFromBytes(bytes) } - implicit val ecPointEncoder: Encoder[EcPointType] = { point: EcPointType => + implicit val ecPointEncoder: Encoder[EcPointType] = Encoder.instance({ point: EcPointType => groupElemToBytes(point).asJson - } + }) - implicit val proveDlogEncoder: Encoder[ProveDlog] = _.pkBytes.asJson + implicit val proveDlogEncoder: Encoder[ProveDlog] = Encoder.instance(_.pkBytes.asJson) // this val is named "anyRegisterIdEncoder" because parent trait already contains // "registerIdEncoder" which is actually a KeyEncoder for NonMandatoryRegisterId // todo: rename "registerIdEncoder" into "nonMandatoryRegisterId" in parent trait in sigma repo - implicit val anyRegisterIdEncoder: Encoder[RegisterId] = { regId => + implicit val anyRegisterIdEncoder: Encoder[RegisterId] = Encoder.instance({ regId => s"R${regId.number}".asJson - } + }) // todo: see comment for "RegisterIdEncoder" above - implicit val anyRegisterIdDecoder: Decoder[RegisterId] = { implicit cursor => + implicit val anyRegisterIdDecoder: Decoder[RegisterId] = Decoder.instance({ implicit cursor => for { regId <- cursor.as[String] reg <- fromOption(ErgoBox.registerByName.get(regId)) } yield reg - } + }) - implicit val scanIdEncoder: Encoder[ScanId] = { scanId => + implicit val scanIdEncoder: Encoder[ScanId] = Encoder.instance({ scanId => scanId.toShort.asJson - } + }) - implicit val scanIdDecoder: Decoder[ScanId] = { c: HCursor => + implicit val scanIdDecoder: Decoder[ScanId] = Decoder.instance({ c: HCursor => ScanId @@ c.as[Short] - } + }) - implicit def trackedBoxEncoder(implicit opts: Detalization): Encoder[TrackedBox] = { box => + implicit def trackedBoxEncoder(implicit opts: Detalization): Encoder[TrackedBox] = Encoder.instance({ box => val plainFields = Map( "spent" -> box.spendingStatus.spent.asJson, "onchain" -> box.chainStatus.onChain.asJson, @@ -124,7 +126,7 @@ trait ApiCodecs extends JsonCodecs { ("spendingTransactionId" -> box.spendingTxIdOpt.asJson) } fieldsWithTx.asJson - } + }) implicit val secretBigIntEncoder: Encoder[BigInteger] = Encoder.instance { w => ErgoAlgos.encode(BigIntegers.asUnsignedByteArray(CryptoConstants.groupSize, w)).asJson @@ -143,7 +145,7 @@ trait ApiCodecs extends JsonCodecs { .map(DLogProverInput.apply) .map(DlogSecretKey.apply) - implicit val dhtSecretWrapperEncoder: Encoder[DhtSecretKey] = { dht => + implicit val dhtSecretWrapperEncoder: Encoder[DhtSecretKey] = Encoder.instance({ dht => Json.obj( "secret" -> dht.privateInput.w.asJson, "g" -> dht.privateInput.commonInput.g.asJson, @@ -151,9 +153,9 @@ trait ApiCodecs extends JsonCodecs { "u" -> dht.privateInput.commonInput.u.asJson, "v" -> dht.privateInput.commonInput.v.asJson ) - } + }) - implicit val dhtSecretWrapperDecoder: Decoder[DhtSecretKey] = { cursor => + implicit val dhtSecretWrapperDecoder: Decoder[DhtSecretKey] = Decoder.instance({ cursor => for { secret <- cursor.downField("secret").as[BigInteger] g <- cursor.downField("g").as[EcPointType] @@ -161,39 +163,41 @@ trait ApiCodecs extends JsonCodecs { u <- cursor.downField("u").as[EcPointType] v <- cursor.downField("v").as[EcPointType] } yield DhtSecretKey(DiffieHellmanTupleProverInput(secret, ProveDHTuple(g, h, u, v))) - } + }) - implicit val unsignedTransactionEncoder: Encoder[UnsignedErgoTransaction] = { tx => + implicit val unsignedTransactionEncoder: Encoder[UnsignedErgoTransaction] = Encoder.instance({ tx => tx.asInstanceOf[UnsignedErgoLikeTransaction].asJson - } + }) - implicit val unsignedTransactionDecoder: Decoder[UnsignedErgoTransaction] = { cursor => + implicit val unsignedTransactionDecoder: Decoder[UnsignedErgoTransaction] = Decoder.instance({ cursor => for { ergoLikeTx <- cursor.as[UnsignedErgoLikeTransaction] } yield UnsignedErgoTransaction(ergoLikeTx) - } + }) - implicit val transactionEncoder: Encoder[ErgoTransaction] = { tx => + implicit val transactionEncoder: Encoder[ErgoTransaction] = Encoder.instance({ tx => tx.asInstanceOf[ErgoLikeTransaction].asJson .mapObject(_.add("size", tx.size.asJson)) - } + }) - implicit val transactionDecoder: Decoder[ErgoTransaction] = { cursor => + implicit val transactionDecoder: Decoder[ErgoTransaction] = Decoder.instance({ cursor => for { ergoLikeTx <- cursor.as[ErgoLikeTransaction] } yield ErgoTransaction(ergoLikeTx) - } + }) - implicit val sigmaLeafEncoder: Encoder[SigmaLeaf] = { + @nowarn + implicit val sigmaLeafEncoder: Encoder[SigmaLeaf] = Encoder.instance({ leaf => val op = leaf.opCode.toByte.asJson leaf match { case dlog: ProveDlog => Map("op" -> op, "h" -> dlog.value.asJson).asJson case dht: ProveDHTuple => Map("op" -> op, "g" -> dht.g.asJson, "h" -> dht.h.asJson, "u" -> dht.u.asJson, "v" -> dht.v.asJson).asJson } - } + }) - implicit val sigmaBooleanEncoder: Encoder[SigmaBoolean] = { + @nowarn + implicit val sigmaBooleanEncoder: Encoder[SigmaBoolean] = Encoder.instance({ sigma => val op = sigma.opCode.toByte.asJson sigma match { @@ -207,7 +211,7 @@ trait ApiCodecs extends JsonCodecs { case th: CTHRESHOLD => Map("op" -> op, "args" -> th.children.map(_.asJson).asJson).asJson } - } + }) implicit val sigmaLeafDecoder: Decoder[SigmaLeaf] = Decoder.instance { c => c.downField("op").as[Byte].flatMap { @@ -231,15 +235,15 @@ trait ApiCodecs extends JsonCodecs { - implicit val firstProverMessageEncoder: Encoder[FirstProverMessage] = { + implicit val firstProverMessageEncoder: Encoder[FirstProverMessage] = Encoder.instance({ case cmtDlog: FirstDLogProverMessage => Json.obj("type" -> "dlog".asJson, "a" -> cmtDlog.ecData.asJson) case cmtDht: FirstDHTupleProverMessage => Json.obj("type" -> "dht".asJson, "a" -> cmtDht.a.asJson, "b" -> cmtDht.b.asJson) case _ => ??? - } + }) - implicit val firstProverMessageDecoder: Decoder[FirstProverMessage] = { c => + implicit val firstProverMessageDecoder: Decoder[FirstProverMessage] = Decoder.instance { c => c.downField("type").as[String].flatMap { case h: String if h == "dlog" => for { @@ -255,20 +259,21 @@ trait ApiCodecs extends JsonCodecs { } } - implicit val positionEncoder: Encoder[NodePosition] = { np => + implicit val positionEncoder: Encoder[NodePosition] = Encoder.instance { np => np.positions.mkString("-").asJson } - implicit val positionDecoder: Decoder[NodePosition] = { c => + implicit val positionDecoder: Decoder[NodePosition] = Decoder.instance { c => c.as[String].flatMap {s => Try(s.split("-").map(_.toInt)) match { - case Success(seq) => Right(NodePosition(seq)) + case Success(seq: Array[Int]) => Right(NodePosition(seq)) case Failure(e) => Left(DecodingFailure.fromThrowable(e, List())) } } } - implicit val commitmentHintEncoder: Encoder[CommitmentHint] = { ch => + @nowarn + implicit val commitmentHintEncoder: Encoder[CommitmentHint] = Encoder.instance { ch => val commonFields: Json = (ch match { case own: OwnCommitment => Json.obj("hint" -> "cmtWithSecret".asJson, "secret" -> own.secretRandomness.asJson) @@ -309,7 +314,8 @@ trait ApiCodecs extends JsonCodecs { } } - implicit val proofEncoder: Encoder[SecretProven] = { sp => + @nowarn + implicit val proofEncoder: Encoder[SecretProven] = Encoder.instance { sp => val proofType = sp match { case _: RealSecretProof => "proofReal" case _: SimulatedSecretProof => "proofSimulated" @@ -324,7 +330,7 @@ trait ApiCodecs extends JsonCodecs { ) } - implicit val secretProofDecoder: Decoder[SecretProven] = { c => + implicit val secretProofDecoder: Decoder[SecretProven] = Decoder.instance { c => c.downField("hint").as[String].flatMap { case h: String if h == "proofReal" => for { @@ -358,20 +364,20 @@ trait ApiCodecs extends JsonCodecs { } } - implicit val hintEncoder: Encoder[Hint] = { + implicit val hintEncoder: Encoder[Hint] = Encoder.instance { case cmt: CommitmentHint => cmt.asJson case proof: SecretProven => proof.asJson case _ => ??? } - implicit val hintDecoder: Decoder[Hint] = { cursor => + implicit val hintDecoder: Decoder[Hint] = Decoder.instance { cursor => Seq(commitmentHintDecoder, secretProofDecoder) .map(_.apply(cursor)) .find(_.isRight) .getOrElse(Left(DecodingFailure("Can not find suitable decoder", cursor.history))) } - implicit val txHintsEncoder: Encoder[TransactionHintsBag] = { bag => + implicit val txHintsEncoder: Encoder[TransactionHintsBag] = Encoder.instance { bag => Json.obj( "secretHints" -> bag.secretHints.map { case (inputIdx, inputHints) => @@ -383,11 +389,12 @@ trait ApiCodecs extends JsonCodecs { ) } - implicit val txHintsDecoder: Decoder[TransactionHintsBag] = { cursor => + @nowarn + implicit val txHintsDecoder: Decoder[TransactionHintsBag] = Decoder.instance { cursor => for { secretHints <- Decoder.decodeMap[Int, Seq[Hint]].tryDecode(cursor.downField("secretHints")) publicHints <- Decoder.decodeMap[Int, Seq[Hint]].tryDecode(cursor.downField("publicHints")) - } yield TransactionHintsBag(secretHints.mapValues(HintsBag.apply), publicHints.mapValues(HintsBag.apply)) + } yield TransactionHintsBag(secretHints.mapValues(HintsBag.apply).toMap, publicHints.mapValues(HintsBag.apply).toMap) } } diff --git a/ergo-core/src/main/scala/org/ergoplatform/mining/AutolykosSolution.scala b/ergo-core/src/main/scala/org/ergoplatform/mining/AutolykosSolution.scala index b448135411..cf745e685b 100644 --- a/ergo-core/src/main/scala/org/ergoplatform/mining/AutolykosSolution.scala +++ b/ergo-core/src/main/scala/org/ergoplatform/mining/AutolykosSolution.scala @@ -1,5 +1,7 @@ package org.ergoplatform.mining +import cats.syntax.either._ +import sigmastate.utils.Helpers._ import io.circe.syntax._ import io.circe.{Decoder, Encoder, HCursor} import org.bouncycastle.util.BigIntegers @@ -35,7 +37,7 @@ object AutolykosSolution extends ApiCodecs { val wForV2: EcPointType = CryptoConstants.dlogGroup.generator val dForV2: BigInt = 0 - implicit val jsonEncoder: Encoder[AutolykosSolution] = { s: AutolykosSolution => + implicit val jsonEncoder: Encoder[AutolykosSolution] = Encoder.instance { s: AutolykosSolution => Map( "pk" -> s.pk.asJson, "w" -> s.w.asJson, @@ -44,7 +46,7 @@ object AutolykosSolution extends ApiCodecs { ).asJson } - implicit val jsonDecoder: Decoder[AutolykosSolution] = { c: HCursor => + implicit val jsonDecoder: Decoder[AutolykosSolution] = Decoder.instance { c: HCursor => for { pkOpt <- c.downField("pk").as[Option[EcPointType]] wOpt <- c.downField("w").as[Option[EcPointType]] diff --git a/ergo-core/src/main/scala/org/ergoplatform/mining/CandidateBlock.scala b/ergo-core/src/main/scala/org/ergoplatform/mining/CandidateBlock.scala index c09cf73276..55848369c4 100644 --- a/ergo-core/src/main/scala/org/ergoplatform/mining/CandidateBlock.scala +++ b/ergo-core/src/main/scala/org/ergoplatform/mining/CandidateBlock.scala @@ -24,7 +24,7 @@ case class CandidateBlock(parentOpt: Option[Header], object CandidateBlock { - implicit val jsonEncoder: Encoder[CandidateBlock] = (c: CandidateBlock) => + implicit val jsonEncoder: Encoder[CandidateBlock] = Encoder.instance((c: CandidateBlock) => Map( "parentId" -> c.parentOpt.map(p => Algos.encode(p.id)).getOrElse("None").asJson, "version" -> c.version.asJson, @@ -36,6 +36,6 @@ object CandidateBlock { "transactionsNumber" -> c.transactions.length.asJson, "votes" -> Algos.encode(c.votes).asJson, "extensionHash" -> Algos.encode(c.extension.digest).asJson - ).asJson + ).asJson) } diff --git a/ergo-core/src/main/scala/org/ergoplatform/mining/ProofOfUpcomingTransactions.scala b/ergo-core/src/main/scala/org/ergoplatform/mining/ProofOfUpcomingTransactions.scala index d3798f72cc..1e7f87ba22 100644 --- a/ergo-core/src/main/scala/org/ergoplatform/mining/ProofOfUpcomingTransactions.scala +++ b/ergo-core/src/main/scala/org/ergoplatform/mining/ProofOfUpcomingTransactions.scala @@ -1,5 +1,7 @@ package org.ergoplatform.mining +import cats.syntax.either._ +import sigmastate.utils.Helpers._ import io.circe.{Encoder, Json} import org.ergoplatform.modifiers.history.BlockTransactions import org.ergoplatform.nodeView.mempool.TransactionMembershipProof @@ -33,7 +35,7 @@ object ProofOfUpcomingTransactions { import TransactionMembershipProof.txMembershipProofEncoder - implicit val encoder: Encoder[ProofOfUpcomingTransactions] = { p: ProofOfUpcomingTransactions => + implicit val encoder: Encoder[ProofOfUpcomingTransactions] = Encoder.instance { p: ProofOfUpcomingTransactions => val preimageBytes = HeaderSerializer.bytesWithoutPow(p.minHeader) Json.obj( "msgPreimage" -> Algos.encode(preimageBytes).asJson, diff --git a/ergo-core/src/main/scala/org/ergoplatform/mining/WorkMessage.scala b/ergo-core/src/main/scala/org/ergoplatform/mining/WorkMessage.scala index 4ca8f4641d..b79ffd1d08 100644 --- a/ergo-core/src/main/scala/org/ergoplatform/mining/WorkMessage.scala +++ b/ergo-core/src/main/scala/org/ergoplatform/mining/WorkMessage.scala @@ -25,7 +25,7 @@ case class WorkMessage(msg: Array[Byte], object WorkMessage extends ApiCodecs { - implicit val encoder: Encoder[WorkMessage] = { workMessage: WorkMessage => + implicit val encoder: Encoder[WorkMessage] = Encoder.instance { workMessage: WorkMessage => Json.obj( List( "msg" -> Some(workMessage.msg.asJson), diff --git a/ergo-core/src/main/scala/org/ergoplatform/mining/difficulty/DifficultySerializer.scala b/ergo-core/src/main/scala/org/ergoplatform/mining/difficulty/DifficultySerializer.scala index d719f9a95c..a4aefe426d 100644 --- a/ergo-core/src/main/scala/org/ergoplatform/mining/difficulty/DifficultySerializer.scala +++ b/ergo-core/src/main/scala/org/ergoplatform/mining/difficulty/DifficultySerializer.scala @@ -68,7 +68,7 @@ object DifficultySerializer extends ErgoSerializer[NBits] { } /** Parse 4 bytes from the byte array (starting at the offset) as unsigned 32-bit integer in big endian format. */ - def readUint32BE(bytes: Array[Byte]): Long = ((bytes(0) & 0xffl) << 24) | ((bytes(1) & 0xffl) << 16) | ((bytes(2) & 0xffl) << 8) | (bytes(3) & 0xffl) + def readUint32BE(bytes: Array[Byte]): Long = ((bytes(0) & 0xffL) << 24) | ((bytes(1) & 0xffL) << 16) | ((bytes(2) & 0xffL) << 8) | (bytes(3) & 0xffL) def uint32ToByteArrayBE(value: Long): Array[Byte] = { Array(0xFF & (value >> 24), 0xFF & (value >> 16), 0xFF & (value >> 8), 0xFF & value).map(_.toByte) diff --git a/ergo-core/src/main/scala/org/ergoplatform/modifiers/BlockSection.scala b/ergo-core/src/main/scala/org/ergoplatform/modifiers/BlockSection.scala index 2fc0c38ff8..0050b77090 100644 --- a/ergo-core/src/main/scala/org/ergoplatform/modifiers/BlockSection.scala +++ b/ergo-core/src/main/scala/org/ergoplatform/modifiers/BlockSection.scala @@ -18,7 +18,7 @@ trait BlockSection extends ErgoNodeViewModifier { object BlockSection { - implicit val jsonEncoder: Encoder[BlockSection] = { + implicit val jsonEncoder: Encoder[BlockSection] = Encoder.instance { case h: Header => Header.jsonEncoder(h) case bt: BlockTransactions => BlockTransactions.jsonEncoder(bt) case adp: ADProofs => ADProofs.jsonEncoder(adp) diff --git a/ergo-core/src/main/scala/org/ergoplatform/modifiers/ErgoFullBlock.scala b/ergo-core/src/main/scala/org/ergoplatform/modifiers/ErgoFullBlock.scala index f90d5c72f2..f59e9cb360 100644 --- a/ergo-core/src/main/scala/org/ergoplatform/modifiers/ErgoFullBlock.scala +++ b/ergo-core/src/main/scala/org/ergoplatform/modifiers/ErgoFullBlock.scala @@ -1,5 +1,7 @@ package org.ergoplatform.modifiers +import cats.syntax.either._ +import sigmastate.utils.Helpers._ import io.circe.syntax._ import io.circe.{Decoder, Encoder, HCursor, Json} import org.ergoplatform.http.api.ApiCodecs @@ -49,7 +51,7 @@ object ErgoFullBlock extends ApiCodecs { val modifierTypeId: NetworkObjectTypeId.Value = FullBlockTypeId.value - implicit val jsonEncoder: Encoder[ErgoFullBlock] = { b: ErgoFullBlock => + implicit val jsonEncoder: Encoder[ErgoFullBlock] = Encoder.instance { b: ErgoFullBlock => Json.obj( "header" -> b.header.asJson, "blockTransactions" -> b.blockTransactions.asJson, @@ -59,7 +61,7 @@ object ErgoFullBlock extends ApiCodecs { ) } - implicit val jsonDecoder: Decoder[ErgoFullBlock] = { c: HCursor => + implicit val jsonDecoder: Decoder[ErgoFullBlock] = Decoder.instance { c: HCursor => for { header <- c.downField("header").as[Header] transactions <- c.downField("blockTransactions").as[BlockTransactions] @@ -68,7 +70,7 @@ object ErgoFullBlock extends ApiCodecs { } yield ErgoFullBlock(header, transactions, extension, adProofs) } - val blockSizeEncoder: Encoder[ErgoFullBlock] = { b: ErgoFullBlock => + val blockSizeEncoder: Encoder[ErgoFullBlock] = Encoder.instance { b: ErgoFullBlock => Json.obj( "id" -> b.header.id.asJson, "size" -> b.size.asJson diff --git a/ergo-core/src/main/scala/org/ergoplatform/modifiers/history/ADProofs.scala b/ergo-core/src/main/scala/org/ergoplatform/modifiers/history/ADProofs.scala index f6404d0101..380600129c 100644 --- a/ergo-core/src/main/scala/org/ergoplatform/modifiers/history/ADProofs.scala +++ b/ergo-core/src/main/scala/org/ergoplatform/modifiers/history/ADProofs.scala @@ -1,5 +1,7 @@ package org.ergoplatform.modifiers.history +import cats.syntax.either._ +import sigmastate.utils.Helpers._ import io.circe.syntax._ import io.circe.{Decoder, Encoder, HCursor} import org.ergoplatform.http.api.ApiCodecs @@ -75,7 +77,7 @@ object ADProofs extends ApiCodecs { def proofDigest(proofBytes: SerializedAdProof): Digest32 = Algos.hash(proofBytes) - implicit val jsonEncoder: Encoder[ADProofs] = { proof: ADProofs => + implicit val jsonEncoder: Encoder[ADProofs] = Encoder.instance { proof: ADProofs => Map( "headerId" -> Algos.encode(proof.headerId).asJson, "proofBytes" -> Algos.encode(proof.proofBytes).asJson, @@ -84,7 +86,7 @@ object ADProofs extends ApiCodecs { ).asJson } - implicit val jsonDecoder: Decoder[ADProofs] = { c: HCursor => + implicit val jsonDecoder: Decoder[ADProofs] = Decoder.instance { c: HCursor => for { headerId <- c.downField("headerId").as[ModifierId] proofBytes <- c.downField("proofBytes").as[Array[Byte]] diff --git a/ergo-core/src/main/scala/org/ergoplatform/modifiers/history/BlockTransactions.scala b/ergo-core/src/main/scala/org/ergoplatform/modifiers/history/BlockTransactions.scala index c88cf31a38..e14c98a784 100644 --- a/ergo-core/src/main/scala/org/ergoplatform/modifiers/history/BlockTransactions.scala +++ b/ergo-core/src/main/scala/org/ergoplatform/modifiers/history/BlockTransactions.scala @@ -1,5 +1,7 @@ package org.ergoplatform.modifiers.history +import cats.syntax.either._ +import sigmastate.utils.Helpers._ import io.circe.syntax._ import io.circe.{Decoder, Encoder, HCursor} import org.ergoplatform.http.api.ApiCodecs @@ -17,6 +19,7 @@ import scorex.util.serialization.{Reader, Writer} import scorex.util.{ModifierId, bytesToId, idToBytes} import scorex.util.Extensions._ +import scala.annotation.nowarn import scala.collection.mutable @@ -28,6 +31,7 @@ import scala.collection.mutable * @param txs - transactions of the block * @param sizeOpt - (optional) size of the section (cached to not be calculated again) */ +@nowarn case class BlockTransactions(headerId: ModifierId, blockVersion: Version, txs: Seq[ErgoTransaction], @@ -110,7 +114,7 @@ object BlockTransactions extends ApiCodecs { def proofValid(transactionsDigest: Digest32, proof: TransactionMembershipProof): Boolean = proofValid(transactionsDigest, proof.proof) - implicit val jsonEncoder: Encoder[BlockTransactions] = { bt: BlockTransactions => + implicit val jsonEncoder: Encoder[BlockTransactions] = Encoder.instance { bt: BlockTransactions => Map( "headerId" -> Algos.encode(bt.headerId).asJson, "transactions" -> bt.txs.map(_.asJson).asJson, @@ -119,13 +123,14 @@ object BlockTransactions extends ApiCodecs { ).asJson } - implicit val jsonDecoder: Decoder[BlockTransactions] = { c: HCursor => + @nowarn + implicit val jsonDecoder: Decoder[BlockTransactions] = Decoder.instance { c: HCursor => for { headerId <- c.downField("headerId").as[ModifierId] transactions <- c.downField("transactions").as[mutable.WrappedArray[ErgoTransaction]] blockVersion <- c.downField("blockVersion").as[Version] size <- c.downField("size").as[Int] - } yield BlockTransactions(headerId, blockVersion, transactions, Some(size)) + } yield BlockTransactions(headerId, blockVersion, transactions.toSeq, Some(size)) } } diff --git a/ergo-core/src/main/scala/org/ergoplatform/modifiers/history/extension/Extension.scala b/ergo-core/src/main/scala/org/ergoplatform/modifiers/history/extension/Extension.scala index c5dede1165..43c3869ef8 100644 --- a/ergo-core/src/main/scala/org/ergoplatform/modifiers/history/extension/Extension.scala +++ b/ergo-core/src/main/scala/org/ergoplatform/modifiers/history/extension/Extension.scala @@ -1,5 +1,7 @@ package org.ergoplatform.modifiers.history.extension +import cats.syntax.either._ +import sigmastate.utils.Helpers._ import com.google.common.primitives.Bytes import io.circe.syntax._ import io.circe.{Decoder, Encoder, HCursor} @@ -87,7 +89,7 @@ object Extension extends ApiCodecs { Algos.merkleTree(LeafData @@ fields.map(kvToLeaf)) } - implicit val jsonEncoder: Encoder[Extension] = { e: Extension => + implicit val jsonEncoder: Encoder[Extension] = Encoder.instance { e: Extension => Map( "headerId" -> Algos.encode(e.headerId).asJson, "digest" -> Algos.encode(e.digest).asJson, @@ -95,7 +97,7 @@ object Extension extends ApiCodecs { ).asJson } - implicit val jsonDecoder: Decoder[Extension] = { c: HCursor => + implicit val jsonDecoder: Decoder[Extension] = Decoder.instance { c: HCursor => for { headerId <- c.downField("headerId").as[ModifierId] fields <- c.downField("fields").as[List[(Array[Byte], Array[Byte])]] diff --git a/ergo-core/src/main/scala/org/ergoplatform/modifiers/history/extension/ExtensionCandidate.scala b/ergo-core/src/main/scala/org/ergoplatform/modifiers/history/extension/ExtensionCandidate.scala index 2bd7bd1097..61513e3360 100644 --- a/ergo-core/src/main/scala/org/ergoplatform/modifiers/history/extension/ExtensionCandidate.scala +++ b/ergo-core/src/main/scala/org/ergoplatform/modifiers/history/extension/ExtensionCandidate.scala @@ -6,7 +6,7 @@ import scorex.crypto.authds.LeafData import scorex.crypto.authds.merkle.{BatchMerkleProof, Leaf, MerkleProof, MerkleTree} import scorex.crypto.hash.Digest32 import scorex.util.ModifierId - +import scala.annotation.nowarn import scala.collection.mutable /** * Extension block section with header id not provided @@ -44,11 +44,13 @@ class ExtensionCandidate(val fields: Seq[(Array[Byte], Array[Byte])]) { * @param keys - array of 2-byte keys * @return BatchMerkleProof or None if keys not found */ + @nowarn def batchProofFor(keys: Array[Byte]*): Option[BatchMerkleProof[Digest32]] = { val indices = keys.flatMap(key => fields.find(_._1 sameElements key) .map(Extension.kvToLeaf) .map(kv => Leaf[Digest32](LeafData @@ kv)(Algos.hash).hash) - .flatMap(leafData => interlinksMerkleTree.elementsHashIndex.get(new mutable.WrappedArray.ofByte(leafData)))) + .flatMap(leafData => interlinksMerkleTree.elementsHashIndex.get( + new mutable.WrappedArray.ofByte(leafData)))) if (indices.isEmpty) None else interlinksMerkleTree.proofByIndices(indices)(Algos.hash) } } diff --git a/ergo-core/src/main/scala/org/ergoplatform/modifiers/history/extension/ExtensionSerializer.scala b/ergo-core/src/main/scala/org/ergoplatform/modifiers/history/extension/ExtensionSerializer.scala index 137e1813dd..5c1516b6f9 100644 --- a/ergo-core/src/main/scala/org/ergoplatform/modifiers/history/extension/ExtensionSerializer.scala +++ b/ergo-core/src/main/scala/org/ergoplatform/modifiers/history/extension/ExtensionSerializer.scala @@ -5,6 +5,8 @@ import org.ergoplatform.serialization.ErgoSerializer import scorex.util.serialization.{Reader, Writer} import scorex.util.{bytesToId, idToBytes} +import scala.annotation.nowarn + object ExtensionSerializer extends ErgoSerializer[Extension] { override def serialize(obj: Extension, w: Writer): Unit = { @@ -17,6 +19,7 @@ object ExtensionSerializer extends ErgoSerializer[Extension] { } } + @nowarn override def parse(r: Reader): Extension = { val startPosition = r.position val headerId = bytesToId(r.getBytes(Constants.ModifierIdSize)) diff --git a/ergo-core/src/main/scala/org/ergoplatform/modifiers/history/header/Header.scala b/ergo-core/src/main/scala/org/ergoplatform/modifiers/history/header/Header.scala index 24d5887ecd..092dcd219f 100644 --- a/ergo-core/src/main/scala/org/ergoplatform/modifiers/history/header/Header.scala +++ b/ergo-core/src/main/scala/org/ergoplatform/modifiers/history/header/Header.scala @@ -1,5 +1,7 @@ package org.ergoplatform.modifiers.history.header +import cats.syntax.either._ +import sigmastate.utils.Helpers._ import io.circe.syntax._ import io.circe.{Decoder, Encoder, HCursor} import org.ergoplatform.http.api.ApiCodecs @@ -19,6 +21,7 @@ import sigmastate.crypto.CryptoConstants.EcPointType import sigmastate.eval.Extensions._ import sigmastate.eval.{CAvlTree, CBigInt, CGroupElement, CHeader} +import scala.annotation.nowarn import scala.concurrent.duration.FiniteDuration /** @@ -72,6 +75,7 @@ case class Header(override val version: Header.Version, /** * Expected identifiers of the block sections corresponding to this header */ + @nowarn lazy val sectionIds: Seq[(NetworkObjectTypeId.Value, ModifierId)] = Array( (ADProofs.modifierTypeId, ADProofsId), @@ -158,7 +162,7 @@ object Header extends ApiCodecs { lazy val GenesisParentId: ModifierId = bytesToId(Array.fill(Constants.HashLength)(0: Byte)) - implicit val jsonEncoder: Encoder[Header] = { h: Header => + implicit val jsonEncoder: Encoder[Header] = Encoder.instance { h: Header => Map( "id" -> Algos.encode(h.id).asJson, "transactionsRoot" -> Algos.encode(h.transactionsRoot).asJson, @@ -180,7 +184,7 @@ object Header extends ApiCodecs { ).asJson } - implicit val jsonDecoder: Decoder[Header] = { c: HCursor => + implicit val jsonDecoder: Decoder[Header] = Decoder.instance { c: HCursor => for { transactionsRoot <- c.downField("transactionsRoot").as[Digest32] adProofsRoot <- c.downField("adProofsRoot").as[Digest32] diff --git a/ergo-core/src/main/scala/org/ergoplatform/modifiers/history/popow/NipopowProof.scala b/ergo-core/src/main/scala/org/ergoplatform/modifiers/history/popow/NipopowProof.scala index 512b068df8..c963877ada 100644 --- a/ergo-core/src/main/scala/org/ergoplatform/modifiers/history/popow/NipopowProof.scala +++ b/ergo-core/src/main/scala/org/ergoplatform/modifiers/history/popow/NipopowProof.scala @@ -1,5 +1,7 @@ package org.ergoplatform.modifiers.history.popow +import cats.syntax.either._ +import sigmastate.utils.Helpers._ import io.circe.{Decoder, Encoder} import org.ergoplatform.mining.difficulty.DifficultyAdjustment import org.ergoplatform.modifiers.history.header.{Header, HeaderSerializer} @@ -159,7 +161,7 @@ object NipopowProof { import io.circe.syntax._ import PoPowHeader._ - implicit val nipopowProofEncoder: Encoder[NipopowProof] = { proof: NipopowProof => + implicit val nipopowProofEncoder: Encoder[NipopowProof] = Encoder.instance { proof: NipopowProof => Map( "m" -> proof.m.asJson, "k" -> proof.k.asJson, @@ -170,7 +172,7 @@ object NipopowProof { ).asJson } - def nipopowProofDecoder(poPowAlgos: NipopowAlgos): Decoder[NipopowProof] = { c => + def nipopowProofDecoder(poPowAlgos: NipopowAlgos): Decoder[NipopowProof] = Decoder.instance { c => for { m <- c.downField("m").as[Int] k <- c.downField("k").as[Int] diff --git a/ergo-core/src/main/scala/org/ergoplatform/modifiers/history/popow/PoPowHeader.scala b/ergo-core/src/main/scala/org/ergoplatform/modifiers/history/popow/PoPowHeader.scala index bdd82ded9c..80bcccc649 100644 --- a/ergo-core/src/main/scala/org/ergoplatform/modifiers/history/popow/PoPowHeader.scala +++ b/ergo-core/src/main/scala/org/ergoplatform/modifiers/history/popow/PoPowHeader.scala @@ -1,5 +1,7 @@ package org.ergoplatform.modifiers.history.popow +import cats.syntax.either._ +import sigmastate.utils.Helpers._ import cats.Traverse import cats.implicits.{catsStdInstancesForEither, catsStdInstancesForList} import io.circe.{Decoder, Encoder, Json} @@ -72,11 +74,11 @@ object PoPowHeader { } } - implicit val interlinksEncoder: Encoder[Seq[ModifierId]] = { interlinksVector: Seq[ModifierId] => + implicit val interlinksEncoder: Encoder[Seq[ModifierId]] = Encoder.instance { interlinksVector: Seq[ModifierId] => interlinksVector.map(id => id: String).asJson } - implicit val batchMerkleProofEncoder: Encoder[BatchMerkleProof[Digest32]] = { proof: BatchMerkleProof[Digest32] => + implicit val batchMerkleProofEncoder: Encoder[BatchMerkleProof[Digest32]] = Encoder.instance { proof: BatchMerkleProof[Digest32] => import org.ergoplatform.wallet.serialization.JsonCodecsWrapper.arrayBytesEncoder val indicesAsJson = proof.indices.map(i => Json.obj(fields = @@ -93,7 +95,7 @@ object PoPowHeader { ) } - implicit val batchMerkleProofDecoder: Decoder[BatchMerkleProof[Digest32]] = { p => + implicit val batchMerkleProofDecoder: Decoder[BatchMerkleProof[Digest32]] = Decoder.instance { p => import org.ergoplatform.wallet.serialization.JsonCodecsWrapper.arrayBytesDecoder for { @@ -116,7 +118,7 @@ object PoPowHeader { proofBytes.map(p => Digest32 @@ p) zip proofSides.map(s => Side @@ s)) } - implicit val popowHeaderJsonEncoder: Encoder[PoPowHeader] = { p: PoPowHeader => + implicit val popowHeaderJsonEncoder: Encoder[PoPowHeader] = Encoder.instance { p: PoPowHeader => Map( "header" -> p.header.asJson, //order in JSON array is preserved according to RFC 7159 @@ -125,7 +127,7 @@ object PoPowHeader { ).asJson } - implicit val popowHeaderJsonDecoder: Decoder[PoPowHeader] = { c => + implicit val popowHeaderJsonDecoder: Decoder[PoPowHeader] = Decoder.instance { c => for { header <- c.downField("header").as[Header] interlinks <- c.downField("interlinks").as[Seq[String]] diff --git a/ergo-core/src/main/scala/org/ergoplatform/modifiers/mempool/ErgoTransaction.scala b/ergo-core/src/main/scala/org/ergoplatform/modifiers/mempool/ErgoTransaction.scala index 2e97fdc87c..ab5c064f53 100644 --- a/ergo-core/src/main/scala/org/ergoplatform/modifiers/mempool/ErgoTransaction.scala +++ b/ergo-core/src/main/scala/org/ergoplatform/modifiers/mempool/ErgoTransaction.scala @@ -31,6 +31,7 @@ import sigmastate.serialization.ConstantStore import sigmastate.utils.{SigmaByteReader, SigmaByteWriter} import java.util +import scala.annotation.nowarn import scala.collection.mutable import scala.util.{Failure, Success, Try} @@ -174,6 +175,7 @@ case class ErgoTransaction(override val inputs: IndexedSeq[Input], .validate(txBoxPropositionSize, out.propositionBytes.length <= MaxPropositionBytes.value, InvalidModifier(s"$id: output $out", id, modifierTypeId)) } + @nowarn private def verifyAssets(validationBefore: ValidationState[Long], outAssets: Map[Seq[Byte], Long], outAssetsNum: Int, @@ -368,8 +370,7 @@ case class ErgoTransaction(override val inputs: IndexedSeq[Input], ErgoInterpreter.interpreterInitCost.toLong, multiplyExact(boxesToSpend.size.toLong, stateContext.currentParameters.inputCost.toLong), multiplyExact(dataBoxes.size.toLong, stateContext.currentParameters.dataInputCost.toLong), - multiplyExact(outputCandidates.size.toLong, stateContext.currentParameters.outputCost.toLong), - ) + multiplyExact(outputCandidates.size.toLong, stateContext.currentParameters.outputCost.toLong)) // Cost limit per block val maxCost = stateContext.currentParameters.maxBlockCost.toLong diff --git a/ergo-core/src/main/scala/org/ergoplatform/network/ModePeerFeature.scala b/ergo-core/src/main/scala/org/ergoplatform/network/ModePeerFeature.scala index 14052929b3..373b0d79ee 100644 --- a/ergo-core/src/main/scala/org/ergoplatform/network/ModePeerFeature.scala +++ b/ergo-core/src/main/scala/org/ergoplatform/network/ModePeerFeature.scala @@ -83,7 +83,7 @@ object ModePeerFeature { ) } - implicit val jsonEncoder: Encoder[ModePeerFeature] = { mf: ModePeerFeature => + implicit val jsonEncoder: Encoder[ModePeerFeature] = Encoder.instance { mf: ModePeerFeature => Json.obj( "state" -> mf.stateType.toString.asJson, "verifyingTransactions" -> mf.verifyingTransactions.asJson, diff --git a/ergo-core/src/main/scala/org/ergoplatform/nodeView/mempool/TransactionMembershipProof.scala b/ergo-core/src/main/scala/org/ergoplatform/nodeView/mempool/TransactionMembershipProof.scala index 2a93fefb83..415ff76a69 100644 --- a/ergo-core/src/main/scala/org/ergoplatform/nodeView/mempool/TransactionMembershipProof.scala +++ b/ergo-core/src/main/scala/org/ergoplatform/nodeView/mempool/TransactionMembershipProof.scala @@ -19,14 +19,14 @@ case class TransactionMembershipProof(txId: ModifierId, proof: MerkleProof[Diges object TransactionMembershipProof extends JsonCodecs { - implicit val merkleProofEncoder: Encoder[MerkleProof[Digest32]] = { mp: MerkleProof[Digest32] => + implicit val merkleProofEncoder: Encoder[MerkleProof[Digest32]] = Encoder.instance { mp: MerkleProof[Digest32] => Json.obj( "leaf" -> Algos.encode(mp.leafData).asJson, "levels" -> mp.levels.map{case (digest, side) => Algos.encode(side +: digest)}.asJson ) } - implicit val txMembershipProofEncoder: Encoder[TransactionMembershipProof] = { tmp: TransactionMembershipProof => + implicit val txMembershipProofEncoder: Encoder[TransactionMembershipProof] = Encoder.instance { tmp: TransactionMembershipProof => tmp.proof.asJson } diff --git a/ergo-core/src/main/scala/org/ergoplatform/nodeView/state/ErgoStateContext.scala b/ergo-core/src/main/scala/org/ergoplatform/nodeView/state/ErgoStateContext.scala index fcd6b6f680..d4ac70befb 100644 --- a/ergo-core/src/main/scala/org/ergoplatform/nodeView/state/ErgoStateContext.scala +++ b/ergo-core/src/main/scala/org/ergoplatform/nodeView/state/ErgoStateContext.scala @@ -23,6 +23,7 @@ import sigmastate.eval.Extensions.ArrayOps import sigmastate.eval.SigmaDsl import sigma.Coll +import scala.collection.compat.immutable.ArraySeq import scala.util.{Failure, Success, Try} /** @@ -122,7 +123,8 @@ class ErgoStateContext(val lastHeaders: Seq[Header], val upcomingHeader = PreHeader(lastHeaderOpt, version, minerPk, timestamp, nBits, votes) val forkVote = votes.contains(Parameters.SoftFork) val height = ErgoHistoryUtils.heightOf(lastHeaderOpt) + 1 - val (calculatedParams, updated) = currentParameters.update(height, forkVote, votingData.epochVotes, proposedUpdate, votingSettings) + val (calculatedParams, updated) = + currentParameters.update(height, forkVote, ArraySeq.unsafeWrapArray(votingData.epochVotes), proposedUpdate, votingSettings) val calculatedValidationSettings = validationSettings.updated(updated) UpcomingStateContext(lastHeaders, lastExtensionOpt, upcomingHeader, genesisStateDigest, calculatedParams, calculatedValidationSettings, votingData) @@ -141,7 +143,8 @@ class ErgoStateContext(val lastHeaders: Seq[Header], val proposedUpdate = ErgoValidationSettingsUpdate.empty val upcomingHeader = PreHeader(lastHeaderOpt, version, minerPk, timestamp, nBits, votes) val height = ErgoHistoryUtils.heightOf(lastHeaderOpt) + 1 - val (calculatedParams, updated) = currentParameters.update(height, forkVote = false, votingData.epochVotes, proposedUpdate, votingSettings) + val (calculatedParams, updated) = + currentParameters.update(height, forkVote = false, ArraySeq.unsafeWrapArray(votingData.epochVotes), proposedUpdate, votingSettings) val calculatedValidationSettings = validationSettings.updated(updated) UpcomingStateContext(lastHeaders, lastExtensionOpt, upcomingHeader, genesisStateDigest, calculatedParams, calculatedValidationSettings, votingData) @@ -176,7 +179,8 @@ class ErgoStateContext(val lastHeaders: Seq[Header], .validateNoFailure(exParseValidationSettings, parsedValidationSettingsTry, extension.id, extension.modifierTypeId) .validateTry(parsedParamsTry, e => ModifierValidator.fatal("Failed to parse parameters", extension.id, extension.modifierTypeId, e)) { case (vs, parsedParams) => - vs.validateTry(parsedValidationSettingsTry, e => ModifierValidator.fatal("Failed to parse validation settings", extension.id, extension.modifierTypeId, e)) { + vs.validateTry(parsedValidationSettingsTry, + e => ModifierValidator.fatal("Failed to parse validation settings", extension.id, extension.modifierTypeId, e)) { case (currentValidationState, parsedSettings) => /* @@ -192,7 +196,7 @@ class ErgoStateContext(val lastHeaders: Seq[Header], parsedParams -> parsedSettings } else { val (params, settingsUpdates) = currentParameters - .update(height, forkVote, votingData.epochVotes, parsedParams.proposedUpdate, votingSettings) + .update(height, forkVote, ArraySeq.unsafeWrapArray(votingData.epochVotes), parsedParams.proposedUpdate, votingSettings) val settings = validationSettings.updated(settingsUpdates) params -> settings } diff --git a/ergo-core/src/main/scala/org/ergoplatform/settings/ChainSettings.scala b/ergo-core/src/main/scala/org/ergoplatform/settings/ChainSettings.scala index 18029e21e4..e748487acd 100644 --- a/ergo-core/src/main/scala/org/ergoplatform/settings/ChainSettings.scala +++ b/ergo-core/src/main/scala/org/ergoplatform/settings/ChainSettings.scala @@ -1,5 +1,7 @@ package org.ergoplatform.settings +import cats.syntax.either._ +import sigmastate.utils.Helpers._ import org.ergoplatform.ErgoAddressEncoder import org.ergoplatform.mining.AutolykosPowScheme import org.ergoplatform.mining.difficulty.DifficultySerializer diff --git a/ergo-core/src/main/scala/org/ergoplatform/settings/NipopowSettings.scala b/ergo-core/src/main/scala/org/ergoplatform/settings/NipopowSettings.scala index fdcf5acd98..9908622112 100644 --- a/ergo-core/src/main/scala/org/ergoplatform/settings/NipopowSettings.scala +++ b/ergo-core/src/main/scala/org/ergoplatform/settings/NipopowSettings.scala @@ -1,5 +1,6 @@ package org.ergoplatform.settings +import com.typesafe.config.Config import net.ceedubs.ficus.Ficus._ import net.ceedubs.ficus.readers.ValueReader @@ -12,7 +13,9 @@ case class NipopowSettings(nipopowBootstrap: Boolean, p2pNipopows: Int) * Custom settings reader for `NipopowSettings` */ trait NipopowSettingsReader { - implicit val nipopowSettingsReader: ValueReader[NipopowSettings] = { (cfg, path) => + implicit val nipopowSettingsReader: ValueReader[NipopowSettings] = + new ValueReader[NipopowSettings] + { def read(cfg: Config, path: String) = NipopowSettings( cfg.as[Boolean](s"$path.nipopowBootstrap"), cfg.as[Int](s"$path.p2pNipopows") diff --git a/ergo-core/src/main/scala/org/ergoplatform/settings/Parameters.scala b/ergo-core/src/main/scala/org/ergoplatform/settings/Parameters.scala index 001734789b..ba590ddcad 100644 --- a/ergo-core/src/main/scala/org/ergoplatform/settings/Parameters.scala +++ b/ergo-core/src/main/scala/org/ergoplatform/settings/Parameters.scala @@ -14,6 +14,8 @@ import org.ergoplatform.modifiers.history.extension.{Extension, ExtensionCandida import Extension.SystemParametersPrefix import org.ergoplatform.sdk.BlockchainParameters +import scala.annotation.nowarn + /** * System parameters which could be readjusted via collective miners decision. */ @@ -139,6 +141,7 @@ class Parameters(val height: Height, } //Update non-fork parameters + @nowarn def updateParams(parametersTable: Map[Byte, Int], epochVotes: Seq[(Byte, Int)], votingSettings: VotingSettings): Map[Byte, Int] = { @@ -406,7 +409,7 @@ object ParametersSerializer extends ErgoSerializer[Parameters] with ApiCodecs { Parameters(height, table.toMap, proposedUpdate) } - implicit val jsonEncoder: Encoder[Parameters] = { p: Parameters => + implicit val jsonEncoder: Encoder[Parameters] = Encoder.instance { p: Parameters => Map( "height" -> p.height.asJson, "blockVersion" -> p.blockVersion.asJson, diff --git a/ergo-core/src/main/scala/org/ergoplatform/settings/SettingsReaders.scala b/ergo-core/src/main/scala/org/ergoplatform/settings/SettingsReaders.scala index a41a8e2e2d..6c359110ab 100644 --- a/ergo-core/src/main/scala/org/ergoplatform/settings/SettingsReaders.scala +++ b/ergo-core/src/main/scala/org/ergoplatform/settings/SettingsReaders.scala @@ -7,11 +7,25 @@ import java.io.File import java.net.InetSocketAddress trait SettingsReaders { - implicit val fileReader: ValueReader[File] = (cfg, path) => new File(cfg.getString(path)) - implicit val byteValueReader: ValueReader[Byte] = (cfg, path) => cfg.getInt(path).toByte - implicit val inetSocketAddressReader: ValueReader[InetSocketAddress] = { (config: Config, path: String) => - val string = config.getString(path) - val index = string.lastIndexOf(':') - new InetSocketAddress(string.substring(0, index), string.substring(index + 1).toInt) + implicit val fileReader: ValueReader[File] = { + new ValueReader[File] { + def read(cfg: Config, path: String) = new File(cfg.getString(path)) + } + } + + implicit val byteValueReader: ValueReader[Byte] = { + new ValueReader[Byte] { + def read(cfg: Config, path: String) = cfg.getInt(path).toByte + } + } + + implicit val inetSocketAddressReader: ValueReader[InetSocketAddress] = { + new ValueReader[InetSocketAddress] { + def read(config: Config, path: String) = { + val string = config.getString(path) + val index = string.lastIndexOf(':') + new InetSocketAddress(string.substring(0, index), string.substring(index + 1).toInt) + } + } } } diff --git a/ergo-core/src/main/scala/org/ergoplatform/settings/UtxoSettings.scala b/ergo-core/src/main/scala/org/ergoplatform/settings/UtxoSettings.scala index 64c14ccadf..949b92fffb 100644 --- a/ergo-core/src/main/scala/org/ergoplatform/settings/UtxoSettings.scala +++ b/ergo-core/src/main/scala/org/ergoplatform/settings/UtxoSettings.scala @@ -1,5 +1,6 @@ package org.ergoplatform.settings +import com.typesafe.config.Config import net.ceedubs.ficus.Ficus._ import net.ceedubs.ficus.readers.ValueReader @@ -12,11 +13,13 @@ case class UtxoSettings(utxoBootstrap: Boolean, storingUtxoSnapshots: Int, p2pUt * Custom settings reader for `UtxoSettings` */ trait UtxoSettingsReader { - implicit val utxoSettingsReader: ValueReader[UtxoSettings] = { (cfg, path) => - UtxoSettings( - cfg.as[Boolean](s"$path.utxoBootstrap"), - cfg.as[Int](s"$path.storingUtxoSnapshots"), - cfg.as[Int](s"$path.p2pUtxoSnapshots") - ) + implicit val utxoSettingsReader: ValueReader[UtxoSettings] = { + new ValueReader[UtxoSettings] { + def read(cfg: Config, path: String) = UtxoSettings( + cfg.as[Boolean](s"$path.utxoBootstrap"), + cfg.as[Int](s"$path.storingUtxoSnapshots"), + cfg.as[Int](s"$path.p2pUtxoSnapshots") + ) + } } } \ No newline at end of file diff --git a/ergo-core/src/main/scala/org/ergoplatform/utils/utils.scala b/ergo-core/src/main/scala/org/ergoplatform/utils/utils.scala index e27399b445..10b681e46e 100644 --- a/ergo-core/src/main/scala/org/ergoplatform/utils/utils.scala +++ b/ergo-core/src/main/scala/org/ergoplatform/utils/utils.scala @@ -28,7 +28,7 @@ package object utils { r } - def concatBytes(seq: Traversable[Array[Byte]]): Array[Byte] = { + def concatBytes(seq: Iterable[Array[Byte]]): Array[Byte] = { val length: Int = seq.map(_.length).sum val result: Array[Byte] = new Array[Byte](length) var pos: Int = 0 diff --git a/ergo-core/src/main/scala/org/ergoplatform/validation/ModifierValidator.scala b/ergo-core/src/main/scala/org/ergoplatform/validation/ModifierValidator.scala index c0a3c3f7f7..dab7a2db33 100644 --- a/ergo-core/src/main/scala/org/ergoplatform/validation/ModifierValidator.scala +++ b/ergo-core/src/main/scala/org/ergoplatform/validation/ModifierValidator.scala @@ -1,5 +1,7 @@ package org.ergoplatform.validation +import cats.syntax.either._ +import sigmastate.utils.Helpers._ import org.ergoplatform.consensus.ModifierSemanticValidity import org.ergoplatform.modifiers.NetworkObjectTypeId import org.ergoplatform.utils.ScorexEncoder @@ -100,7 +102,7 @@ case class ValidationState[T](result: ValidationResult[T], settings: ValidationS /** Validate the first argument equals the second. This should not be used with `ModifierId` of type `Array[Byte]`. * The `error` callback will be provided with detail on argument values for better reporting */ - def validateEquals[A](id: Short, given: => A, expected: => A, modifierId: ModifierId, modifierTypeId: NetworkObjectTypeId.Value): ValidationState[T] = { + def validateEquals[A](id: Short, `given`: => A, expected: => A, modifierId: ModifierId, modifierTypeId: NetworkObjectTypeId.Value): ValidationState[T] = { pass((given, expected) match { case _ if !settings.isActive(id) => result case (a: Array[_], b: Array[_]) if a sameElements[Any] b => result @@ -112,7 +114,7 @@ case class ValidationState[T](result: ValidationResult[T], settings: ValidationS /** Validate the `id`s are equal. The `error` callback will be provided with detail on argument values */ - def validateEqualIds(id: Short, given: => ModifierId, expected: => ModifierId, modifierTypeId: NetworkObjectTypeId.Value): ValidationState[T] = { + def validateEqualIds(id: Short, `given`: => ModifierId, expected: => ModifierId, modifierTypeId: NetworkObjectTypeId.Value): ValidationState[T] = { pass { if (!settings.isActive(id) || given == expected) result else settings.getError(id, InvalidModifier(s"Given: ${e.encodeId(given)}, expected ${e.encodeId(expected)}", given, modifierTypeId)) diff --git a/ergo-core/src/main/scala/org/ergoplatform/validation/ValidationResult.scala b/ergo-core/src/main/scala/org/ergoplatform/validation/ValidationResult.scala index 812871112d..818cb9b4ce 100644 --- a/ergo-core/src/main/scala/org/ergoplatform/validation/ValidationResult.scala +++ b/ergo-core/src/main/scala/org/ergoplatform/validation/ValidationResult.scala @@ -4,7 +4,6 @@ import io.circe.{ACursor, DecodingFailure} import org.ergoplatform.validation.ValidationResult.{Invalid, Valid} import scala.concurrent.Future -import scala.language.implicitConversions import scala.util.{Failure, Success, Try} /** Base trait for the result of validation diff --git a/ergo-wallet/build.sbt b/ergo-wallet/build.sbt index e9dcf17c62..dc11c38c80 100644 --- a/ergo-wallet/build.sbt +++ b/ergo-wallet/build.sbt @@ -1,22 +1,23 @@ // this values should be in sync with root (i.e. ../build.sbt) val scala211 = "2.11.12" -val scala212 = "2.12.10" -val scala213 = "2.13.8" - -val circeVersion = "0.13.0" -val circeVersion211 = "0.10.0" +val scala212 = "2.12.18" +val scala213 = "2.13.12" + +val deps211 = Seq( + "io.circe" %% "circe-core" % "0.10.0", + "io.circe" %% "circe-generic" % "0.10.0", + "io.circe" %% "circe-parser" % "0.10.0") +val deps212 = Seq( + "io.circe" %% "circe-core" % "0.13.0", + "io.circe" %% "circe-generic" % "0.13.0", + "io.circe" %% "circe-parser" % "0.13.0") libraryDependencies ++= Seq( "org.scodec" %% "scodec-bits" % "1.1.34", - - "io.circe" %% "circe-core" % (if (scalaVersion.value == scala211) circeVersion211 else circeVersion), - "io.circe" %% "circe-generic" % (if (scalaVersion.value == scala211) circeVersion211 else circeVersion), - "io.circe" %% "circe-parser" % (if (scalaVersion.value == scala211) circeVersion211 else circeVersion), - "org.scalatest" %% "scalatest" % "3.1.1" % "test", "org.scalacheck" %% "scalacheck" % "1.14.3" % "test", - "org.scalatestplus" %% "scalatestplus-scalacheck" % "3.1.0.0-RC2" % Test -) + "org.scalatestplus" %% "scalatestplus-scalacheck" % "3.1.0.0-RC2" % Test, +) ++ (if (scalaVersion.value == scala211) deps211 else deps212) publishMavenStyle in ThisBuild := true diff --git a/src/main/resources/api/openapi-ai.yaml b/src/main/resources/api/openapi-ai.yaml index 39e61442c4..73f675fffb 100644 --- a/src/main/resources/api/openapi-ai.yaml +++ b/src/main/resources/api/openapi-ai.yaml @@ -1,7 +1,7 @@ openapi: "3.0.2" info: - version: "5.0.18" + version: "5.0.19" title: Ergo Node API description: Specification of Ergo Node API for ChatGPT plugin. The following endpoints supported diff --git a/src/main/resources/api/openapi.yaml b/src/main/resources/api/openapi.yaml index 46e9ce2732..d152c8c94d 100644 --- a/src/main/resources/api/openapi.yaml +++ b/src/main/resources/api/openapi.yaml @@ -1,7 +1,7 @@ openapi: "3.0.2" info: - version: "5.0.18" + version: "5.0.19" title: Ergo Node API description: API docs for Ergo Node. Models are shared between all Ergo products contact: diff --git a/src/main/resources/application.conf b/src/main/resources/application.conf index 7d43da2452..c2fe8298a7 100644 --- a/src/main/resources/application.conf +++ b/src/main/resources/application.conf @@ -363,6 +363,11 @@ bounded-mailbox { } akka { + log-dead-letters = 0 + loggers = ["akka.event.slf4j.Slf4jLogger"] + loglevel = "DEBUG" + logging-filter = "akka.event.slf4j.Slf4jLoggingFilter" + actor.mailbox.requirements { "akka.dispatch.BoundedMessageQueueSemantics" = bounded-mailbox } @@ -431,7 +436,7 @@ scorex { nodeName = "ergo-node" # Network protocol version to be sent in handshakes - appVersion = 5.0.18 + appVersion = 5.0.19 # Network agent name. May contain information about client code # stack, starting from core code-base up to the end graphical interface. diff --git a/src/main/scala/org/ergoplatform/http/api/ApiError.scala b/src/main/scala/org/ergoplatform/http/api/ApiError.scala index 72d36e86b4..81ad547fbd 100644 --- a/src/main/scala/org/ergoplatform/http/api/ApiError.scala +++ b/src/main/scala/org/ergoplatform/http/api/ApiError.scala @@ -4,8 +4,6 @@ import akka.http.scaladsl.model.{ContentTypes, HttpEntity, StatusCode, StatusCod import akka.http.scaladsl.server.{Directives, Route} import io.circe.syntax._ -import scala.language.implicitConversions - case class ApiError(statusCode: StatusCode, reason: String = "") { def apply(detail: String): Route = complete(detail) diff --git a/src/main/scala/org/ergoplatform/http/api/BlockchainApiRoute.scala b/src/main/scala/org/ergoplatform/http/api/BlockchainApiRoute.scala index 39c913bdee..0be225d035 100644 --- a/src/main/scala/org/ergoplatform/http/api/BlockchainApiRoute.scala +++ b/src/main/scala/org/ergoplatform/http/api/BlockchainApiRoute.scala @@ -244,10 +244,9 @@ case class BlockchainApiRoute(readersHolder: ActorRef, ergoSettings: ErgoSetting private def getBoxesByAddressUnspent(addr: ErgoAddress, offset: Int, limit: Int, sortDir: Direction, unconfirmed: Boolean): Future[Seq[IndexedErgoBox]] = getHistoryWithMempool.map { case (history, mempool) => - getAddress(addr)(history) match { - case Some(addr) => addr.retrieveUtxos(history, mempool, offset, limit, sortDir, unconfirmed) - case None => Seq.empty[IndexedErgoBox] - } + getAddress(addr)(history) + .getOrElse(IndexedErgoAddress(hashErgoTree(addr.script))) + .retrieveUtxos(history, mempool, offset, limit, sortDir, unconfirmed) } private def validateAndGetBoxesByAddressUnspent(address: ErgoAddress, @@ -312,10 +311,9 @@ case class BlockchainApiRoute(readersHolder: ActorRef, ergoSettings: ErgoSetting private def getBoxesByErgoTreeUnspent(tree: ErgoTree, offset: Int, limit: Int, sortDir: Direction, unconfirmed: Boolean): Future[Seq[IndexedErgoBox]] = getHistoryWithMempool.map { case (history, mempool) => - getAddress(tree)(history) match { - case Some(addr) => addr.retrieveUtxos(history, mempool, offset, limit, sortDir, unconfirmed) - case None => Seq.empty[IndexedErgoBox] - } + getAddress(tree)(history) + .getOrElse(IndexedErgoAddress(hashErgoTree(tree))) + .retrieveUtxos(history, mempool, offset, limit, sortDir, unconfirmed) } private def getBoxesByErgoTreeUnspentR: Route = (post & pathPrefix("box" / "unspent" / "byErgoTree") & ergoTree & paging & sortDir & unconfirmed) { (tree, offset, limit, dir, unconfirmed) => @@ -352,10 +350,9 @@ case class BlockchainApiRoute(readersHolder: ActorRef, ergoSettings: ErgoSetting private def getBoxesByTokenIdUnspent(id: ModifierId, offset: Int, limit: Int, sortDir: Direction, unconfirmed: Boolean): Future[Seq[IndexedErgoBox]] = getHistoryWithMempool.map { case (history, mempool) => - history.typedExtraIndexById[IndexedToken](uniqueId(id)) match { - case Some(token) => token.retrieveUtxos(history, mempool, offset, limit, sortDir, unconfirmed) - case None => Seq.empty[IndexedErgoBox] - } + history.typedExtraIndexById[IndexedToken](uniqueId(id)) + .getOrElse(IndexedToken(id)) + .retrieveUtxos(history, mempool, offset, limit, sortDir, unconfirmed) } private def getBoxesByTokenIdUnspentR: Route = (get & pathPrefix("box" / "unspent" / "byTokenId") & modifierId & paging & sortDir & unconfirmed) { (id, offset, limit, dir, unconfirmed) =>