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) =>