diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index a33887508b..98448bccfa 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -36,9 +36,16 @@ jobs:
env:
GPG_SIGNING_KEY: ${{ secrets.GPG_SIGNING_KEY }}
- - name: Publish release
+ - name: Publish ergo-wallet
run: sbt +ergoWallet/publishSigned sonatypeBundleRelease
env:
PGP_PASSPHRASE: ${{ secrets.PGP_PASSPHRASE }}
SONATYPE_PASSWORD: ${{ secrets.SONATYPE_PASSWORD }}
SONATYPE_USERNAME: ${{ secrets.SONATYPE_USERNAME }}
+
+ - name: Publish ergo-core
+ run: sbt +ergoCore/publishSigned sonatypeBundleRelease
+ env:
+ PGP_PASSPHRASE: ${{ secrets.PGP_PASSPHRASE }}
+ SONATYPE_PASSWORD: ${{ secrets.SONATYPE_PASSWORD }}
+ SONATYPE_USERNAME: ${{ secrets.SONATYPE_USERNAME }}
diff --git a/Dockerfile b/Dockerfile
index 95b719cb24..17be1a16aa 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -4,9 +4,10 @@ COPY build.sbt findbugs-exclude.xml ./
COPY project/ project/
COPY avldb/build.sbt avldb/build.sbt
COPY avldb/project/ avldb/project/
+COPY ergo-core/build.sbt ergo-core/build.sbt
+COPY ergo-core/project/ ergo-core/project/
COPY ergo-wallet/build.sbt ergo-wallet/build.sbt
COPY ergo-wallet/project/ ergo-wallet/project/
-COPY benchmarks/build.sbt benchmarks/build.sbt
RUN sbt update
COPY . ./
RUN sbt assembly
diff --git a/avldb/project/build.properties b/avldb/project/build.properties
index 31334bbd3d..c0bab04941 100644
--- a/avldb/project/build.properties
+++ b/avldb/project/build.properties
@@ -1 +1 @@
-sbt.version=1.1.1
+sbt.version=1.2.8
diff --git a/avldb/project/plugins.sbt b/avldb/project/plugins.sbt
index a083810279..0d12040ca8 100644
--- a/avldb/project/plugins.sbt
+++ b/avldb/project/plugins.sbt
@@ -2,8 +2,6 @@ logLevel := Level.Warn
addSbtPlugin("com.jsuereth" % "sbt-pgp" % "1.1.0")
-addSbtPlugin("com.github.tkawachi" % "sbt-lock" % "0.4.0")
-
addSbtPlugin("org.scalastyle" %% "scalastyle-sbt-plugin" % "1.0.0")
addSbtPlugin("org.scoverage" % "sbt-scoverage" % "1.5.1")
diff --git a/avldb/src/main/scala/scorex/core/serialization/ErgoSerializer.scala b/avldb/src/main/scala/org/ergoplatform/serialization/ErgoSerializer.scala
similarity index 95%
rename from avldb/src/main/scala/scorex/core/serialization/ErgoSerializer.scala
rename to avldb/src/main/scala/org/ergoplatform/serialization/ErgoSerializer.scala
index 972ac73792..cfc13412dc 100644
--- a/avldb/src/main/scala/scorex/core/serialization/ErgoSerializer.scala
+++ b/avldb/src/main/scala/org/ergoplatform/serialization/ErgoSerializer.scala
@@ -1,4 +1,4 @@
-package scorex.core.serialization
+package org.ergoplatform.serialization
import java.nio.ByteBuffer
import scorex.util.ByteArrayBuilder
diff --git a/avldb/src/main/scala/scorex/core/serialization/ManifestSerializer.scala b/avldb/src/main/scala/org/ergoplatform/serialization/ManifestSerializer.scala
similarity index 98%
rename from avldb/src/main/scala/scorex/core/serialization/ManifestSerializer.scala
rename to avldb/src/main/scala/org/ergoplatform/serialization/ManifestSerializer.scala
index 70bced053d..985eb421fe 100644
--- a/avldb/src/main/scala/scorex/core/serialization/ManifestSerializer.scala
+++ b/avldb/src/main/scala/org/ergoplatform/serialization/ManifestSerializer.scala
@@ -1,4 +1,4 @@
-package scorex.core.serialization
+package org.ergoplatform.serialization
import scorex.crypto.authds.avltree.batch.Constants.DigestType
import scorex.crypto.authds.avltree.batch.serialization.{BatchAVLProverManifest, ProxyInternalNode}
diff --git a/avldb/src/main/scala/scorex/core/serialization/SubtreeSerializer.scala b/avldb/src/main/scala/org/ergoplatform/serialization/SubtreeSerializer.scala
similarity index 97%
rename from avldb/src/main/scala/scorex/core/serialization/SubtreeSerializer.scala
rename to avldb/src/main/scala/org/ergoplatform/serialization/SubtreeSerializer.scala
index 0a1f6df970..f4822bbe3e 100644
--- a/avldb/src/main/scala/scorex/core/serialization/SubtreeSerializer.scala
+++ b/avldb/src/main/scala/org/ergoplatform/serialization/SubtreeSerializer.scala
@@ -1,4 +1,4 @@
-package scorex.core.serialization
+package org.ergoplatform.serialization
import scorex.crypto.authds.avltree.batch.Constants.DigestType
import scorex.crypto.authds.avltree.batch.{InternalProverNode, ProverLeaf, ProverNodes, VersionedLDBAVLStorage}
diff --git a/avldb/src/main/scala/scorex/crypto/authds/avltree/batch/ProverNodeSerializer.scala b/avldb/src/main/scala/scorex/crypto/authds/avltree/batch/ProverNodeSerializer.scala
index a2bffc75ca..9199acdd8f 100644
--- a/avldb/src/main/scala/scorex/crypto/authds/avltree/batch/ProverNodeSerializer.scala
+++ b/avldb/src/main/scala/scorex/crypto/authds/avltree/batch/ProverNodeSerializer.scala
@@ -1,7 +1,7 @@
package scorex.crypto.authds.avltree.batch
import com.google.common.primitives.Ints
-import scorex.core.serialization.ErgoSerializer
+import org.ergoplatform.serialization.ErgoSerializer
import scorex.crypto.authds.{ADKey, ADValue, Balance}
import scorex.crypto.authds.avltree.batch.Constants.{DigestType, hashFn}
import scorex.crypto.authds.avltree.batch.serialization.ProxyInternalNode
diff --git a/avldb/src/test/scala/scorex/crypto/authds/avltree/batch/VersionedLDBAVLStorageSpecification.scala b/avldb/src/test/scala/scorex/crypto/authds/avltree/batch/VersionedLDBAVLStorageSpecification.scala
index 1c72d26b84..810e986b00 100644
--- a/avldb/src/test/scala/scorex/crypto/authds/avltree/batch/VersionedLDBAVLStorageSpecification.scala
+++ b/avldb/src/test/scala/scorex/crypto/authds/avltree/batch/VersionedLDBAVLStorageSpecification.scala
@@ -6,7 +6,7 @@ import org.scalatest.Assertion
import org.scalatest.matchers.should.Matchers
import org.scalatest.propspec.AnyPropSpec
import org.scalatestplus.scalacheck.ScalaCheckPropertyChecks
-import scorex.core.serialization.{ManifestSerializer, SubtreeSerializer}
+import org.ergoplatform.serialization.{ManifestSerializer, SubtreeSerializer}
import scorex.crypto.authds.avltree.batch.helpers.TestHelper
import scorex.crypto.authds.{ADDigest, ADKey, ADValue, SerializedAdProof}
import scorex.util.encode.Base16
diff --git a/benchmarks/Jenkinsfile b/benchmarks/Jenkinsfile
deleted file mode 100644
index c15fda9f89..0000000000
--- a/benchmarks/Jenkinsfile
+++ /dev/null
@@ -1,11 +0,0 @@
-pipeline {
- agent { label 'slave' }
- stages {
-
- stage('org.ergoplatform.bench.BenchRunner') {
- steps {
- sh('sbt "benchmarks/test:runMain org.ergoplatform.bench.BenchRunner"')
- }
- }
- }
-}
diff --git a/benchmarks/build.sbt b/benchmarks/build.sbt
deleted file mode 100644
index 6e115c6490..0000000000
--- a/benchmarks/build.sbt
+++ /dev/null
@@ -1,6 +0,0 @@
-sourceDirectory in Jmh := (sourceDirectory in Test).value
-classDirectory in Jmh := (classDirectory in Test).value
-dependencyClasspath in Jmh := (dependencyClasspath in Test).value
-// rewire tasks, so that 'jmh:run' automatically invokes 'jmh:compile' (otherwise a clean 'jmh:run' would fail)
-compile in Jmh := (compile in Jmh).dependsOn(compile in Test).value
-run in Jmh := (run in Jmh).dependsOn(Keys.compile in Jmh).evaluated
\ No newline at end of file
diff --git a/benchmarks/src/test/resources/logback-bench.xml b/benchmarks/src/test/resources/logback-bench.xml
deleted file mode 100644
index 550b67da3a..0000000000
--- a/benchmarks/src/test/resources/logback-bench.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
- System.out
-
- ERROR
-
-
- [%thread] >> [%-5level] %logger{36} >> %d{HH:mm:ss.SSS} %msg%n
-
-
-
-
-
-
-
-
-
-
diff --git a/benchmarks/src/test/scala/org/ergoplatform/ModifiersApplicationBench.scala b/benchmarks/src/test/scala/org/ergoplatform/ModifiersApplicationBench.scala
deleted file mode 100644
index 60c2837582..0000000000
--- a/benchmarks/src/test/scala/org/ergoplatform/ModifiersApplicationBench.scala
+++ /dev/null
@@ -1,98 +0,0 @@
-package org.ergoplatform
-
-import org.ergoplatform.Utils.BenchReport
-import org.ergoplatform.modifiers.BlockSection
-import org.ergoplatform.modifiers.history.extension.Extension
-import org.ergoplatform.modifiers.history.BlockTransactions
-import org.ergoplatform.modifiers.history.header.Header
-import org.ergoplatform.nodeView.{ErgoModifiersCache, NVBenchmark}
-import org.ergoplatform.nodeView.history.ErgoHistory
-import org.ergoplatform.nodeView.state.StateType
-import org.ergoplatform.utils.HistoryTestHelpers
-
-import scala.annotation.tailrec
-
-object ModifiersApplicationBench extends HistoryTestHelpers with NVBenchmark {
-
- def main(args: Array[String]): Unit = {
-
- val startTs = System.currentTimeMillis()
-
- val cache = new ErgoModifiersCache(maxSize = 1024)
-
- val headers: Seq[Header] = readHeaders
- val payloads: Seq[BlockTransactions] = readPayloads
- val extensions: Seq[Extension] = readExtensions
-
- def bench(benchCase: String)
- (applicator: (Seq[BlockSection], ErgoHistory) => Any,
- mods: Seq[BlockSection]): (String, Long) = {
- val preparedHistory = applyModifiers(headers.take(mods.size / 2), unlockedHistory())._1
- val et = Utils.time(applicator(mods, preparedHistory)).toLong
- assert(preparedHistory.fullBlockHeight == mods.size / 2)
- s"Performance of `$benchCase`: $et ms" -> et
- }
-
- def applyModifiersWithCache(mods: Seq[BlockSection], his: ErgoHistory): (ErgoHistory, Int) = {
- mods.foreach(m => cache.put(m.id, m))
- @tailrec def applyLoop(applied: Seq[BlockSection]): Seq[BlockSection] = {
- cache.popCandidate(his) match {
- case Some(mod) =>
- his.append(mod).get
- applyLoop(mod +: applied)
- case None =>
- applied
- }
- }
-
- val appliedModsQty = applyLoop(Seq()).size
- his -> appliedModsQty
- }
-
- def applyModifiers(mods: Seq[BlockSection], his: ErgoHistory): (ErgoHistory, Int) = {
- @tailrec def applyLoop(rem: Seq[BlockSection],
- applied: Seq[BlockSection]): Seq[BlockSection] = {
- rem match {
- case m :: tail =>
- his.applicableTry(m)
- his.append(m)
- applyLoop(tail, m +: applied)
- case Nil =>
- applied
- }
- }
-
- val appliedModsQty = applyLoop(mods, Seq()).size
- his -> appliedModsQty
- }
-
- val modifiersDirectOrd = payloads ++ extensions
- val modifiersReversedOrd = modifiersDirectOrd.reverse
-
- val report0 = bench("Modifiers application in direct order")(applyModifiers, modifiersDirectOrd)
- val report1 = bench("Modifiers application in direct order (cache)")(applyModifiersWithCache, modifiersDirectOrd)
- val report2 = bench("Modifiers application in reversed order (cache)")(applyModifiersWithCache, modifiersReversedOrd)
-
- println(report0._1)
- println(report1._1)
- println(report2._1)
-
- val reports = Seq(report0, report1, report2).map { case (repStr, et) =>
- BenchReport(repStr, et)
- }
-
- Utils.dumpToFile("ModifiersApplicationBench", startTs, reports)
-
- System.exit(0)
- }
-
- def history(): ErgoHistory = generateHistory(verifyTransactions = true, StateType.Utxo,
- PoPoWBootstrap = false, blocksToKeep = -1)
-
- def unlockedHistory(): ErgoHistory = {
- val h = history()
- HistoryTestHelpers.allowToApplyOldBlocks(h)
- h
- }
-
-}
diff --git a/benchmarks/src/test/scala/org/ergoplatform/Utils.scala b/benchmarks/src/test/scala/org/ergoplatform/Utils.scala
deleted file mode 100644
index 70eaec61bf..0000000000
--- a/benchmarks/src/test/scala/org/ergoplatform/Utils.scala
+++ /dev/null
@@ -1,59 +0,0 @@
-package org.ergoplatform
-
-import java.io.{File, InputStream, PrintWriter}
-import java.net.URL
-
-import com.google.common.primitives.Ints
-import javax.net.ssl.HttpsURLConnection
-import org.ergoplatform.modifiers.BlockSection
-import org.ergoplatform.modifiers.history.HistoryModifierSerializer
-
-object Utils {
-
- final case class BenchReport(benchCase: String, et: Long)
-
- def getUrlInputStream(url: String,
- connectTimeout: Int = 5000,
- readTimeout: Int = 5000,
- requestMethod: String = "GET"): InputStream = {
- val u = new URL(url)
- val conn = u.openConnection.asInstanceOf[HttpsURLConnection]
- conn.setConnectTimeout(connectTimeout)
- conn.setReadTimeout(readTimeout)
- conn.setRequestMethod(requestMethod)
- conn.connect()
- conn.getInputStream
- }
-
- def readLength(implicit fis: InputStream): Option[Int] =
- Some(Stream.continually(fis.read().toByte).take(4).toArray).map(Ints.fromByteArray)
-
- def readBytes(length: Int)(implicit fis: InputStream): Option[Array[Byte]] =
- Some(Stream.continually(fis.read().toByte).take(length).toArray)
-
- def readModifier[M <: BlockSection](implicit fis: InputStream): Option[M] = {
- for {
- length <- readLength
- bytes <- readBytes(length)
- mod <- HistoryModifierSerializer.parseBytesTry(bytes).toOption.map(_.asInstanceOf[M])
- } yield mod
- }
-
- def dumpToFile(benchName: String, startTs: Long, reports: Seq[BenchReport]): Unit = {
- new File(s"target/bench/").mkdirs()
- val outWriter = new PrintWriter(new File(s"target/bench/bench-report.json"))
- val reportsStr = reports.map { case BenchReport(benchCase, et) =>
- s"""{"benchCase":"$benchCase","elapsedTime":$et}"""
- }.mkString(",")
- outWriter.write(s"""{"benchName":"$benchName","startTs":$startTs,"reports":[$reportsStr]}""")
- outWriter.close()
- }
-
- def time[R](block: => R): Double = {
- val t0 = System.nanoTime()
- block // call-by-name
- val t1 = System.nanoTime()
- (t1.toDouble - t0) / 1000000
- }
-
-}
diff --git a/benchmarks/src/test/scala/org/ergoplatform/bench/BenchActor.scala b/benchmarks/src/test/scala/org/ergoplatform/bench/BenchActor.scala
deleted file mode 100644
index c591aba9c9..0000000000
--- a/benchmarks/src/test/scala/org/ergoplatform/bench/BenchActor.scala
+++ /dev/null
@@ -1,63 +0,0 @@
-package org.ergoplatform.bench
-
-import akka.actor.{Actor, ActorRef, ActorSystem, Props}
-import org.ergoplatform.Utils
-import org.ergoplatform.Utils.BenchReport
-import org.ergoplatform.network.ErgoNodeViewSynchronizer.ReceivableMessages.FullBlockApplied
-import scorex.util.ScorexLogging
-
-import scala.concurrent.ExecutionContext
-import scala.concurrent.duration._
-import scala.language.postfixOps
-
-class BenchActor(threshold: Int) extends Actor with ScorexLogging {
-
- implicit val ec: ExecutionContext = context.dispatcher
-
- var counter = 0
- var start = 0L
- var finish = 0L
-
- val timeout: FiniteDuration = 2 hours
-
- override def preStart(): Unit = {
- context.system.eventStream.subscribe(self, classOf[FullBlockApplied])
- context.system.scheduler.scheduleOnce(timeout, self, BenchActor.Timeout)
- ()
- }
-
- override def receive: Receive = {
- case BenchActor.Start =>
- start = System.nanoTime()
- log.info(s"Starting bench..")
- case FullBlockApplied(_) =>
- self ! BenchActor.Inc
- case BenchActor.Inc =>
- counter += 1
- if (counter % 100 == 0 ) log.info(s"counter is $counter")
- if (counter >= threshold) {
- finish = System.nanoTime()
- val et = (finish - start) / 1000000
- log.info(s"$threshold modifiers applied, elapsed time: $et ms")
- Utils.dumpToFile("NodeViewHolder modifiers application", start, Seq(BenchReport(s"$threshold modifiers", et)))
- System.exit(0)
- }
- case BenchActor.Timeout =>
- log.error("Bench is taking too long. Shutting down on timeout.")
- System.exit(1)
- }
-
-}
-
-object BenchActor {
-
- def apply(threshold: Int)(implicit ac: ActorSystem): ActorRef = {
- ac.actorOf(Props.apply(classOf[BenchActor], threshold))
- }
-
- case object Timeout
-
- case object Inc
-
- case object Start
-}
diff --git a/benchmarks/src/test/scala/org/ergoplatform/bench/BenchRunner.scala b/benchmarks/src/test/scala/org/ergoplatform/bench/BenchRunner.scala
deleted file mode 100644
index 2dfdfbfd0e..0000000000
--- a/benchmarks/src/test/scala/org/ergoplatform/bench/BenchRunner.scala
+++ /dev/null
@@ -1,72 +0,0 @@
-package org.ergoplatform.bench
-
-import akka.actor.{ActorRef, ActorSystem}
-import org.ergoplatform.bench.misc.TempDir
-import org.ergoplatform.modifiers.BlockSection
-import org.ergoplatform.nodeView.history.ErgoHistory
-import org.ergoplatform.nodeView.history.storage.modifierprocessors.{FullBlockPruningProcessor, ToDownloadProcessor}
-import org.ergoplatform.nodeView.state.{ErgoState, StateType}
-import org.ergoplatform.nodeView.{ErgoNodeViewRef, NVBenchmark}
-import org.ergoplatform.settings.{Args, ErgoSettings}
-import org.ergoplatform.nodeView.ErgoNodeViewHolder.CurrentView
-import org.ergoplatform.nodeView.ErgoNodeViewHolder.ReceivableMessages.{GetDataFromCurrentView, LocallyGeneratedModifier}
-import scorex.util.ScorexLogging
-import scala.concurrent.ExecutionContextExecutor
-
-object BenchRunner extends ScorexLogging with NVBenchmark {
-
- implicit val system: ActorSystem = ActorSystem("bench")
- implicit val ec: ExecutionContextExecutor = system.dispatcher
-
- def main(args: Array[String]): Unit = {
- val threshold = args.headOption.getOrElse("1000").toInt
- val isUtxo = args.lift(2).isEmpty
- val state = if (isUtxo) StateType.Utxo else StateType.Digest
- val benchRef = BenchActor(threshold)
- val userDir = TempDir.createTempDir
-
- log.info(s"User dir is $userDir")
- log.info("Starting benchmark.")
-
- val realNetworkSettings = ErgoSettings.read(Args(Some("src/main/resources/application.conf"), None))
- val nodeSettings = realNetworkSettings.nodeSettings.copy(stateType = state)
-
- lazy val ergoSettings: ErgoSettings = realNetworkSettings
- .copy(directory = userDir.getAbsolutePath, nodeSettings = nodeSettings)
-
- log.info(s"Setting that being used:")
- log.info(s"$ergoSettings")
-
- val nodeViewHolderRef: ActorRef = ErgoNodeViewRef(ergoSettings)
-
- /**
- * It's a hack to set minimalFullBlockHeightVar to 0 and to avoid "Header Is Not Synced" error, cause
- * in our case we are considering only locally pre-generated modifiers.
- */
- nodeViewHolderRef ! GetDataFromCurrentView[ErgoState[_], Unit](adjust)
-
- log.info("Starting to read modifiers.")
- log.info("Finished read modifiers, starting to bench.")
- log.info(s"$threshold modifiers to go")
- runBench(benchRef, nodeViewHolderRef, (readHeaders ++ readExtensions ++ readPayloads).toVector)
- }
-
- private def adjust(v: CurrentView[ErgoState[_]]): Unit = {
- import scala.reflect.runtime.{universe => ru}
- val runtimeMirror = ru.runtimeMirror(getClass.getClassLoader)
- val procInstance = runtimeMirror.reflect(v.history.asInstanceOf[ToDownloadProcessor])
- val ppM = ru.typeOf[ToDownloadProcessor].member(ru.TermName("pruningProcessor")).asMethod
- val pp = procInstance.reflectMethod(ppM).apply().asInstanceOf[FullBlockPruningProcessor]
- val f = ru.typeOf[FullBlockPruningProcessor].member(ru.TermName("minimalFullBlockHeightVar")).asTerm.accessed.asTerm
- runtimeMirror.reflect(pp).reflectField(f).set(ErgoHistory.GenesisHeight)
- val f2 = ru.typeOf[FullBlockPruningProcessor].member(ru.TermName("isHeadersChainSyncedVar")).asTerm.accessed.asTerm
- runtimeMirror.reflect(pp).reflectField(f2).set(true: Boolean)
- ()
- }
-
- private def runBench(benchRef: ActorRef, nodeRef: ActorRef, modifiers: Vector[BlockSection]): Unit = {
- benchRef ! BenchActor.Start
- modifiers.foreach { m => nodeRef ! LocallyGeneratedModifier(m) }
- }
-
-}
diff --git a/benchmarks/src/test/scala/org/ergoplatform/bench/HistoryExtractor.scala b/benchmarks/src/test/scala/org/ergoplatform/bench/HistoryExtractor.scala
deleted file mode 100644
index 04e0540995..0000000000
--- a/benchmarks/src/test/scala/org/ergoplatform/bench/HistoryExtractor.scala
+++ /dev/null
@@ -1,36 +0,0 @@
-package org.ergoplatform.bench
-
-import java.io.FileOutputStream
-
-import org.ergoplatform.bench.misc.ModifierWriter
-import org.ergoplatform.nodeView.history.ErgoHistory
-import org.ergoplatform.settings.{Args, ErgoSettings}
-import scorex.util.ScorexLogging
-
-
-object HistoryExtractor extends ScorexLogging {
-
- def main(args: Array[String]): Unit = {
-
- lazy val cfgPath: Option[String] = args.headOption
- lazy val outputFile: String = args.lift(1).getOrElse("blocks.dat")
- lazy val ergoSettings: ErgoSettings = ErgoSettings.read(Args(cfgPath, None))
-
- val os = new FileOutputStream(outputFile)
- val h = ErgoHistory.readOrGenerate(ergoSettings)(null)
- val wholeChain = h.chainToHeader(None, h.bestHeaderOpt.get)
-
- var counter = 0
- wholeChain._2.headers.take(10000).foreach { header =>
- counter += 1
- if (counter % 100 == 0) { log.info(s"Processed $counter blocks.")}
- val b = h.getFullBlock(header).get
- ModifierWriter.write(b.header)(os)
- ModifierWriter.write(b.blockTransactions)(os)
- b.adProofs.foreach { p => ModifierWriter.write(p)(os) }
- os.flush()
- }
- os.close()
- }
-
-}
diff --git a/benchmarks/src/test/scala/org/ergoplatform/bench/misc/CrawlerConfig.scala b/benchmarks/src/test/scala/org/ergoplatform/bench/misc/CrawlerConfig.scala
deleted file mode 100644
index 7c8d7b7366..0000000000
--- a/benchmarks/src/test/scala/org/ergoplatform/bench/misc/CrawlerConfig.scala
+++ /dev/null
@@ -1,3 +0,0 @@
-package org.ergoplatform.bench.misc
-
-case class CrawlerConfig(file: String, threshold: Int)
diff --git a/benchmarks/src/test/scala/org/ergoplatform/bench/misc/ModifierWriter.scala b/benchmarks/src/test/scala/org/ergoplatform/bench/misc/ModifierWriter.scala
deleted file mode 100644
index 50e37cedd8..0000000000
--- a/benchmarks/src/test/scala/org/ergoplatform/bench/misc/ModifierWriter.scala
+++ /dev/null
@@ -1,41 +0,0 @@
-package org.ergoplatform.bench.misc
-
-import java.io.{InputStream, OutputStream}
-import com.google.common.primitives.Ints
-import org.ergoplatform.Utils._
-import org.ergoplatform.modifiers.{BlockSection, NetworkObjectTypeId}
-import org.ergoplatform.modifiers.history._
-import org.ergoplatform.modifiers.history.header.{Header, HeaderSerializer}
-import scorex.core.serialization.ErgoSerializer
-import scorex.core.NodeViewModifier
-
-object ModifierWriter {
-
- val modifierSerializers: Map[NetworkObjectTypeId.Value, ErgoSerializer[_ <: BlockSection]] =
- Map(Header.modifierTypeId -> HeaderSerializer,
- BlockTransactions.modifierTypeId -> BlockTransactionsSerializer,
- ADProofs.modifierTypeId -> ADProofsSerializer)
-
- def write(mod: NodeViewModifier)(implicit fos: OutputStream): Unit = {
- val typeId = mod.modifierTypeId
- val bytes = mod.bytes
- val length: Int = bytes.length
- val lengthBytes = Ints.toByteArray(length)
- val bytesToWrite = typeId +: (lengthBytes ++ bytes)
- fos.write(bytesToWrite)
- fos.flush()
- }
-
- def read(implicit fis: InputStream): Option[BlockSection] = for {
- typeId <- readModId
- length <- readLength
- bytes <- readBytes(length)
- mod <- modifierSerializers(typeId).parseBytesTry(bytes).toOption
- } yield mod
-
- private def readModId(implicit fis: InputStream): Option[NetworkObjectTypeId.Value] = {
- val int = fis.read()
- if (int == -1) { None } else { Some(NetworkObjectTypeId.fromByte(int.toByte)) }
- }
-
-}
diff --git a/benchmarks/src/test/scala/org/ergoplatform/bench/misc/TempDir.scala b/benchmarks/src/test/scala/org/ergoplatform/bench/misc/TempDir.scala
deleted file mode 100644
index 35e5c2b9a4..0000000000
--- a/benchmarks/src/test/scala/org/ergoplatform/bench/misc/TempDir.scala
+++ /dev/null
@@ -1,5 +0,0 @@
-package org.ergoplatform.bench.misc
-
-import org.ergoplatform.wallet.utils.TestFileUtils
-
-object TempDir extends TestFileUtils
diff --git a/benchmarks/src/test/scala/org/ergoplatform/db/LDBStoreBench.scala b/benchmarks/src/test/scala/org/ergoplatform/db/LDBStoreBench.scala
deleted file mode 100644
index cb21d133ab..0000000000
--- a/benchmarks/src/test/scala/org/ergoplatform/db/LDBStoreBench.scala
+++ /dev/null
@@ -1,95 +0,0 @@
-package org.ergoplatform.db
-
-import com.google.common.primitives.Longs
-import org.ergoplatform.modifiers.history.BlockTransactions
-import org.ergoplatform.settings.Algos
-import org.ergoplatform.utils.generators.ErgoTransactionGenerators
-import org.ergoplatform.wallet.utils.TestFileUtils
-import org.iq80.leveldb.Options
-import org.scalameter.KeyValue
-import org.scalameter.api.{Bench, Gen, _}
-import org.scalameter.picklers.Implicits._
-import scorex.crypto.hash.Digest32
-import scorex.util.idToBytes
-import scorex.db.LDBFactory.factory
-import scorex.db.{LDBKVStore, LDBVersionedStore}
-
-import scala.util.Random
-
-object LDBStoreBench
- extends Bench.ForkedTime
- with ErgoTransactionGenerators
- with TestFileUtils {
-
- private val options = new Options()
- options.createIfMissing(true)
- private val db1 = factory.open(createTempDir, options)
-
- private def storeLDB() = new LDBKVStore(db1)
- private def storeLVDB() = new LDBVersionedStore(createTempDir, initialKeepVersions = 400)
-
- private val modsNumGen = Gen.enumeration("modifiers number")(1000)
-
- val txsGen: Gen[Seq[BlockTransactions]] = modsNumGen.map { num =>
- (0 to num).flatMap { _ =>
- invalidBlockTransactionsGen(defaultMinerPk, 10).sample
- }
- }
-
- val txsWithDbGen: Gen[(Seq[BlockTransactions], LDBKVStore)] = txsGen.map { bts =>
- val toInsert = bts.map(bt => idToBytes(bt.headerId) -> bt.bytes).toArray
- val db = storeLDB()
- toInsert.grouped(5).foreach(kv => db.insert(kv.map(_._1), kv.map(_._2)).get)
- bts -> storeLDB
- }
-
- private val config = Seq[KeyValue](
- exec.minWarmupRuns -> 1,
- exec.maxWarmupRuns -> 1,
- exec.benchRuns -> 10,
- exec.requireGC -> true
- )
-
- private def randomVersion: Digest32 = Algos.hash(Longs.toByteArray(Random.nextLong()))
-
- private def benchWriteLDB(bts: Seq[BlockTransactions]): Unit = {
- val toInsert = bts.map(bt => idToBytes(bt.headerId) -> bt.bytes).toArray
- val db = storeLDB()
- toInsert.grouped(5).foreach(kv => db.insert(kv.map(_._1), kv.map(_._2)).get)
- }
-
- private def benchReadLDB(bts: Seq[BlockTransactions], db: LDBKVStore): Unit = {
- bts.foreach { bt => db.get(idToBytes(bt.headerId)) }
- }
-
- private def benchWriteLVDB(bts: Seq[BlockTransactions]): Unit = {
- val toInsert = bts.map(bt => idToBytes(bt.headerId) -> bt.bytes)
- val db = storeLVDB()
- db.update(randomVersion, List.empty, toInsert).get
- }
-
- private def benchWriteReadLVDB(bts: Seq[BlockTransactions]): Unit = {
- val toInsert = bts.map(bt => idToBytes(bt.headerId) -> bt.bytes)
- val db = storeLVDB()
- db.update(randomVersion, List.empty, toInsert).get
- bts.foreach { bt => db.get(idToBytes(bt.headerId)) }
- }
-
-
- performance of "LDBStore" in {
- performance of "LDBStore write" in {
- using(txsGen) config(config: _*) in (bts => benchWriteLDB(bts))
- }
- performance of "LDBStore read" in {
- using(txsWithDbGen) config(config: _*) in { case (bts, db) => benchReadLDB(bts, db) }
- }
-
- performance of "LVDBStore write" in {
- using(txsGen) config(config: _*) in (bts => benchWriteLVDB(bts))
- }
-
- performance of "LVDBStore write/read" in {
- using(txsGen) config(config: _*) in (bts => benchWriteReadLVDB(bts))
- }
- }
-}
diff --git a/benchmarks/src/test/scala/org/ergoplatform/db/LDBVersionedStoreRollbackBench.scala b/benchmarks/src/test/scala/org/ergoplatform/db/LDBVersionedStoreRollbackBench.scala
deleted file mode 100644
index d0301ac45f..0000000000
--- a/benchmarks/src/test/scala/org/ergoplatform/db/LDBVersionedStoreRollbackBench.scala
+++ /dev/null
@@ -1,38 +0,0 @@
-package org.ergoplatform.db
-
-import com.google.common.primitives.Ints
-import org.ergoplatform.Utils
-import org.ergoplatform.settings.Algos
-import org.ergoplatform.wallet.utils.TestFileUtils
-import scorex.util.Random
-import scorex.db.LDBVersionedStore
-
-object LDBVersionedStoreRollbackBench extends App with TestFileUtils {
-
- private val store = new LDBVersionedStore(createTempDir, initialKeepVersions = 400)
-
- private val numEpochs = 10000
- private val elemsAtStep = 500
-
- private def key(i: Int): Array[Byte] = Algos.hash(Ints.toByteArray(i))
-
- (0 to numEpochs).foreach { i =>
- val toInsert = (0 to elemsAtStep).map { i0 =>
- key(i0 + i * elemsAtStep) -> Random.randomBytes(1000)
- }
- val toRemove =
- if (i > 1) (0 to (elemsAtStep / 2)).map(_ => key(scala.util.Random.nextInt((i - 1) * elemsAtStep))) else Seq.empty
- val version = Algos.hash(key(i))
- store.update(version, toRemove, toInsert).get
- }
-
- private val version = store.rollbackVersions().head
-
- val et = Utils.time {
- val result = store.rollbackTo(version)
- require(result.isSuccess)
- }
-
- println(s"Performance of `LDBVersionedStore.rollback (max depth)` ($numEpochs epochs): $et ms")
-
-}
diff --git a/benchmarks/src/test/scala/org/ergoplatform/nodeView/NVBenchmark.scala b/benchmarks/src/test/scala/org/ergoplatform/nodeView/NVBenchmark.scala
deleted file mode 100644
index 96ba461c5a..0000000000
--- a/benchmarks/src/test/scala/org/ergoplatform/nodeView/NVBenchmark.scala
+++ /dev/null
@@ -1,30 +0,0 @@
-package org.ergoplatform.nodeView
-
-import org.ergoplatform.Utils
-import org.ergoplatform.modifiers.history.extension.Extension
-import org.ergoplatform.modifiers.history.header.Header
-import org.ergoplatform.modifiers.{ErgoFullBlock, BlockSection}
-import org.ergoplatform.modifiers.history.BlockTransactions
-
-trait NVBenchmark {
-
- val resourceUrlPrefix = "https://github.com/ergoplatform/static-data/raw/master/v2"
-
- def readHeaders: Seq[Header] = readModifiers[Header](s"$resourceUrlPrefix/headers.dat")
- def readPayloads: Seq[BlockTransactions] = readModifiers[BlockTransactions](s"$resourceUrlPrefix/payloads.dat")
- def readExtensions: Seq[Extension] = readModifiers[Extension](s"$resourceUrlPrefix/extensions.dat")
- def readBlocks: Seq[ErgoFullBlock] = readHeaders.zip(readPayloads).zip(readExtensions)
- .map { case ((h, txs), ext) => ErgoFullBlock(h, txs, ext, None) }
-
- def readModifiers[M <: BlockSection](path: String): Seq[M] = {
- val is = Utils.getUrlInputStream(path)
- Stream
- .continually {
- Utils.readModifier[M](is)
- }
- .takeWhile(_.isDefined)
- .flatten
- .toList
- }
-
-}
diff --git a/benchmarks/src/test/scala/org/ergoplatform/nodeView/mempool/ErgoMemPoolBenchmark.scala b/benchmarks/src/test/scala/org/ergoplatform/nodeView/mempool/ErgoMemPoolBenchmark.scala
deleted file mode 100644
index 1e8802027a..0000000000
--- a/benchmarks/src/test/scala/org/ergoplatform/nodeView/mempool/ErgoMemPoolBenchmark.scala
+++ /dev/null
@@ -1,63 +0,0 @@
-package org.ergoplatform.nodeView.mempool
-
-import org.ergoplatform.modifiers.mempool.{ErgoTransaction, UnconfirmedTransaction}
-import org.ergoplatform.utils.generators.ErgoTransactionGenerators
-import org.scalameter.KeyValue
-import org.scalameter.api._
-import org.scalameter.picklers.Implicits._
-
-import scala.util.{Random => Rng}
-
-object ErgoMemPoolBenchmark
- extends Bench.ForkedTime
- with ErgoTransactionGenerators {
-
- private val blockSizes = Gen.enumeration("txs in block")(50, 500, 1000)
- private val waitingSizes = Gen.enumeration("waitings")(1, 10)
-
- private def waitForTransactionsInSequence(txIncomeOrder: Seq[Seq[ErgoTransaction]] => Seq[ErgoTransaction]): Gen[Seq[ErgoTransaction]] = for {
- waitingSize <- waitingSizes
- transactionsPerBlock <- blockSizes
- } yield {
- val txsByWaitingGroups = for {_ <- 0 until waitingSize}
- yield {
- (for {_ <- 0 until transactionsPerBlock} yield {
- invalidErgoTransactionGen.sample
- }).flatten
- }
- txIncomeOrder(txsByWaitingGroups)
- }
-
- private val bestCaseGenerator = waitForTransactionsInSequence(_.flatten)
- private val avgCaseGenerator = waitForTransactionsInSequence(txs => Rng.shuffle(txs.flatten))
- private val worstCaseGenerator = waitForTransactionsInSequence(groups => {
- groups.flatMap(_.init) ++ groups.map(_.last)
- })
-
- private val config = Seq[KeyValue](
- exec.minWarmupRuns -> 10,
- exec.maxWarmupRuns -> 30,
- exec.benchRuns -> 20,
- exec.requireGC -> true
- )
-
- private def bench(txsInIncomeOrder: Seq[ErgoTransaction]): Unit = {
- var pool = ErgoMemPool.empty(settings)
- txsInIncomeOrder.foreach(tx => pool = pool.put(UnconfirmedTransaction(tx, None)))
- }
-
- performance of "ErgoMemPool awaiting" in {
- performance of "best case" in {
- using(bestCaseGenerator) config (config: _*) in (txsInIncomeOrder => bench(txsInIncomeOrder))
- }
-
- performance of "avg case" in {
- using(avgCaseGenerator) config (config: _*) in (txsInIncomeOrder => bench(txsInIncomeOrder))
- }
-
- performance of "worst case" in {
- using(worstCaseGenerator) config (config: _*) in (txsInIncomeOrder => bench(txsInIncomeOrder))
- }
- }
-
-}
diff --git a/benchmarks/src/test/scala/org/ergoplatform/nodeView/mempool/MempoolPerformanceBench.scala b/benchmarks/src/test/scala/org/ergoplatform/nodeView/mempool/MempoolPerformanceBench.scala
deleted file mode 100644
index c15db166f0..0000000000
--- a/benchmarks/src/test/scala/org/ergoplatform/nodeView/mempool/MempoolPerformanceBench.scala
+++ /dev/null
@@ -1,19 +0,0 @@
-package org.ergoplatform.nodeView.mempool
-
-import org.ergoplatform.modifiers.mempool.{ErgoTransaction, UnconfirmedTransaction}
-import org.ergoplatform.utils.generators.{ErgoGenerators, ErgoTransactionGenerators}
-import org.scalacheck.Gen
-import org.scalatest.propspec.AnyPropSpec
-import scorex.testkit.properties.mempool.MempoolFilterPerformanceTest
-
-class MempoolPerformanceBench extends AnyPropSpec
- with MempoolFilterPerformanceTest
- with ErgoGenerators
- with ErgoTransactionGenerators {
-
- override val memPool: ErgoMemPool = ErgoMemPool.empty(settings)
- override val memPoolGenerator: Gen[ErgoMemPool] = emptyMemPoolGen
- override val transactionGenerator: Gen[ErgoTransaction] = invalidErgoTransactionGen
- override val unconfirmedTxGenerator: Gen[UnconfirmedTransaction] =
- invalidErgoTransactionGen.map(tx => UnconfirmedTransaction(tx, None))
-}
diff --git a/benchmarks/src/test/scala/org/ergoplatform/nodeView/state/TransactionExecutionBenchmark.scala b/benchmarks/src/test/scala/org/ergoplatform/nodeView/state/TransactionExecutionBenchmark.scala
deleted file mode 100644
index bb5e4b7888..0000000000
--- a/benchmarks/src/test/scala/org/ergoplatform/nodeView/state/TransactionExecutionBenchmark.scala
+++ /dev/null
@@ -1,58 +0,0 @@
-package org.ergoplatform.nodeView.state
-
-import org.ergoplatform.Utils
-import org.ergoplatform.Utils.BenchReport
-import org.ergoplatform.modifiers.mempool.ErgoTransaction
-import org.ergoplatform.nodeView.NVBenchmark
-import org.ergoplatform.settings.{ErgoValidationSettingsUpdate, Parameters}
-import org.ergoplatform.settings.Parameters.MaxBlockCostIncrease
-import org.ergoplatform.utils.{HistoryTestHelpers, RandomWrapper}
-import scorex.core.validation.ValidationResult.Valid
-import scorex.db.ByteArrayWrapper
-
-import scala.collection.mutable
-import scala.util.Try
-
-object TransactionExecutionBenchmark extends HistoryTestHelpers with NVBenchmark {
-
- val WarmupRuns = 3
-
- override val parameters =
- new Parameters(height = 0,
- parametersTable = Parameters.DefaultParameters + (MaxBlockCostIncrease -> Int.MaxValue),
- proposedUpdate = ErgoValidationSettingsUpdate.empty
- )
-
- def main(args: Array[String]): Unit = {
-
- val startTs = System.currentTimeMillis()
-
- val bh = BoxHolder(genesisBoxes)
- val txs = (1 to 5000).foldLeft(mutable.WrappedArray.newBuilder[ErgoTransaction]) { case (txAcc, _) =>
- val (transactions, _) = validTransactionsFromBoxes(10000, bh.boxes.values.toVector, new RandomWrapper)
- val allBoxIds = bh.boxes.keys.toSet
- val txsFromBoxesOnly = transactions.filter { tx =>
- tx.inputs.map(i => ByteArrayWrapper(i.boxId)).forall(allBoxIds.contains) &&
- tx.dataInputs.map(i => ByteArrayWrapper(i.boxId)).forall(allBoxIds.contains)
- }
- txAcc ++= txsFromBoxesOnly
- }.result()
-
- val boxes = bh.boxes
- def bench: Long =
- Utils.time {
- assert(ErgoState.execTransactions(txs, emptyStateContext)(id => Try(boxes(ByteArrayWrapper(id)))) == Valid(178665000))
- }.toLong
-
- (0 to WarmupRuns).foreach(_ => bench)
- val et = bench
-
- println(s"Performance of `${txs.size} transactions execution`: $et ms")
-
- Utils.dumpToFile("TransactionExecutionBenchmark", startTs, Seq(BenchReport(s"${txs.size} transactions execution", et)))
-
- System.exit(0)
-
- }
-
-}
diff --git a/benchmarks/src/test/scala/org/ergoplatform/nodeView/state/UtxoStateBenchmark.scala b/benchmarks/src/test/scala/org/ergoplatform/nodeView/state/UtxoStateBenchmark.scala
deleted file mode 100644
index 5a257b0420..0000000000
--- a/benchmarks/src/test/scala/org/ergoplatform/nodeView/state/UtxoStateBenchmark.scala
+++ /dev/null
@@ -1,45 +0,0 @@
-package org.ergoplatform.nodeView.state
-
-import org.ergoplatform.Utils
-import org.ergoplatform.Utils.BenchReport
-import org.ergoplatform.modifiers.BlockSection
-import org.ergoplatform.nodeView.NVBenchmark
-import org.ergoplatform.settings.{Args, ErgoSettings}
-import org.ergoplatform.utils.HistoryTestHelpers
-
-object UtxoStateBenchmark extends HistoryTestHelpers with NVBenchmark {
-
- val WarmupRuns = 2
-
- def main(args: Array[String]): Unit = {
-
- val startTs = System.currentTimeMillis()
-
- val realNetworkSetting = ErgoSettings.read(Args(Some("src/main/resources/application.conf"), None))
-
- val blocks = readBlocks
-
- val transactionsQty = blocks.flatMap(_.transactions).size
-
- def bench(mods: Seq[BlockSection]): Long = {
- val state = ErgoState.generateGenesisUtxoState(createTempDir, realNetworkSetting)._1
- Utils.time {
- mods.foldLeft(state) { case (st, mod) =>
- st.applyModifier(mod, None)(_ => ()).get
- }
- }.toLong
- }
-
- (0 to WarmupRuns).foreach(_ => bench(blocks))
-
- val et = bench(blocks)
-
- println(s"Performance of `$transactionsQty transactions application`: $et ms")
-
- Utils.dumpToFile("UtxoStateBenchmark", startTs, Seq(BenchReport(s"$transactionsQty transactions application", et)))
-
- System.exit(0)
-
- }
-
-}
diff --git a/build.sbt b/build.sbt
index d38fbc514d..dccd41e4b1 100644
--- a/build.sbt
+++ b/build.sbt
@@ -38,61 +38,32 @@ val akkaVersion = "2.6.10"
val akkaHttpVersion = "10.2.4"
val sigmaStateVersion = "5.0.13"
+val ficusVersion = "1.4.7"
// for testing current sigmastate build (see sigmastate-ergo-it jenkins job)
val effectiveSigmaStateVersion = Option(System.getenv().get("SIGMASTATE_VERSION")).getOrElse(sigmaStateVersion)
val effectiveSigma = "org.scorexfoundation" %% "sigma-state" % effectiveSigmaStateVersion
-val apiDependencies = Seq(
- "io.circe" %% "circe-core" % circeVersion,
- "io.circe" %% "circe-generic" % circeVersion,
- "io.circe" %% "circe-parser" % circeVersion,
- "de.heikoseeberger" %% "akka-http-circe" % "1.20.0"
-)
libraryDependencies ++= Seq(
effectiveSigma.force()
.exclude("ch.qos.logback", "logback-classic")
.exclude("org.scorexfoundation", "scrypto"),
-
- // network dependencies
- "com.typesafe.akka" %% "akka-actor" % akkaVersion,
- "com.typesafe.akka" %% "akka-http-core" % akkaHttpVersion,
- "com.typesafe.akka" %% "akka-http" % akkaHttpVersion,
- "com.typesafe.akka" %% "akka-parsing" % akkaHttpVersion,
- "com.typesafe.akka" %% "akka-stream" % akkaVersion,
- "org.bitlet" % "weupnp" % "0.1.4",
// api dependencies
"io.circe" %% "circe-core" % circeVersion,
"io.circe" %% "circe-generic" % circeVersion,
"io.circe" %% "circe-parser" % circeVersion,
- "de.heikoseeberger" %% "akka-http-circe" % "1.20.0",
-
- "org.ethereum" % "leveldbjni-all" % "1.18.3",
- //the following pure-java leveldb implementation is needed only on specific platforms, such as 32-bit Raspberry Pi
- //in future, it could be reasonable to have special builds with this Java db only, and for most of platforms use
- //jni wrapper over native library included in leveldbjni-all
- "org.iq80.leveldb" % "leveldb" % "0.12",
-
- "javax.xml.bind" % "jaxb-api" % "2.4.0-b180830.0359",
- "com.iheart" %% "ficus" % "1.4.7",
+
"ch.qos.logback" % "logback-classic" % "1.3.5",
- "com.google.guava" % "guava" % "21.0",
- "com.github.ben-manes.caffeine" % "caffeine" % "2.9.3", // use 3.x only for java 11+
- "com.github.scopt" %% "scopt" % "4.0.1",
+ // test dependencies
"org.scala-lang.modules" %% "scala-async" % "0.9.7" % "test",
- "com.storm-enroute" %% "scalameter" % "0.8.+" % "test",
"org.scalactic" %% "scalactic" % "3.0.3" % "test",
"org.scalatest" %% "scalatest" % "3.2.10" % "test,it",
"org.scalacheck" %% "scalacheck" % "1.14.+" % "test",
"org.scalatestplus" %% "scalatestplus-scalacheck" % "3.1.0.0-RC2" % Test,
- "com.typesafe.akka" %% "akka-http-core" % akkaHttpVersion,
- "io.circe" %% "circe-core" % circeVersion,
- "io.circe" %% "circe-core" % circeVersion % "test",
-
"com.typesafe.akka" %% "akka-testkit" % akkaVersion % "test",
"com.typesafe.akka" %% "akka-http-testkit" % akkaHttpVersion % "test",
@@ -130,6 +101,8 @@ val opts = Seq(
javaOptions in run ++= opts
scalacOptions --= Seq("-Ywarn-numeric-widen", "-Ywarn-value-discard", "-Ywarn-unused:params", "-Xcheckinit")
+val scalacOpts = Seq("-Ywarn-numeric-widen", "-Ywarn-value-discard", "-Ywarn-unused:params", "-Xcheckinit")
+
sourceGenerators in Compile += Def.task {
val versionFile = (sourceManaged in Compile).value / "org" / "ergoplatform" / "Version.scala"
@@ -244,6 +217,14 @@ lazy val avldb = (project in file("avldb"))
// see https://github.com/scala/community-builds/issues/796#issuecomment-423395500
scalacOptions in(Compile, compile) ++= Seq("-release", "8"),
javacOptions in(Compile, compile) ++= javacReleaseOption,
+ libraryDependencies ++= Seq(
+ // database dependencies
+ "org.ethereum" % "leveldbjni-all" % "1.18.3",
+ //the following pure-java leveldb implementation is needed only on specific platforms, such as 32-bit Raspberry Pi
+ //in future, it could be reasonable to have special builds with this Java db only, and for most of platforms use
+ //jni wrapper over native library included in leveldbjni-all
+ "org.iq80.leveldb" % "leveldb" % "0.12"
+ )
)
lazy val avldb_benchmarks = (project in file("avldb/benchmarks"))
@@ -262,6 +243,21 @@ lazy val avldb_benchmarks = (project in file("avldb/benchmarks"))
.dependsOn(avldb)
.enablePlugins(JmhPlugin)
+lazy val ergoCore = (project in file("ergo-core"))
+ .dependsOn(avldb % "test->test;compile->compile")
+ .dependsOn(ergoWallet % "test->test;compile->compile")
+ .settings(
+ commonSettings,
+ name := "ergo-core",
+ libraryDependencies ++= Seq(
+ "com.iheart" %% "ficus" % ficusVersion,
+ effectiveSigma,
+ (effectiveSigma % Test).classifier("tests")
+ ),
+ scalacOptions in(Compile, compile) ++= Seq("-release", "8"),
+ scalacOptions in(Compile, compile) --= scalacOpts,
+ )
+
lazy val ergoWallet = (project in file("ergo-wallet"))
.disablePlugins(ScapegoatSbtPlugin) // not compatible with crossScalaVersions
.settings(
@@ -288,23 +284,42 @@ inConfig(It2Test)(Defaults.testSettings ++ Seq(
lazy val ergo = (project in file("."))
.settings(
- commonSettings,
+ commonSettings,
name := "ergo",
// 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"),
- javacOptions in(Compile, compile) ++= javacReleaseOption
+ javacOptions in(Compile, compile) ++= javacReleaseOption,
+ libraryDependencies ++= Seq(
+ // 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,
+ "org.bitlet" % "weupnp" % "0.1.4",
+ // command line args parsing
+ "com.github.scopt" %% "scopt" % "4.0.1",
+
+ // API dependencies
+ "de.heikoseeberger" %% "akka-http-circe" % "1.20.0",
+
+ // app dependencies
+ // jaxb-api is included only to avoid a runtime exception
+ "javax.xml.bind" % "jaxb-api" % "2.4.0-b180830.0359",
+
+ // caching, bloom filters, Longs/Ints
+ "com.google.guava" % "guava" % "21.0",
+ "com.github.ben-manes.caffeine" % "caffeine" % "2.9.3" // use 3.x only for java 11+
+ )
)
+ .dependsOn(ergoCore % "test->test;compile->compile")
.dependsOn(ergoWallet % "test->test;compile->compile")
.dependsOn(avldb % "test->test;compile->compile")
.configs(It2Test)
-lazy val benchmarks = (project in file("benchmarks"))
- .settings(commonSettings, name := "ergo-benchmarks")
- .dependsOn(ergo % "test->test")
- .enablePlugins(JmhPlugin)
// PGP key for signing a release build published to sonatype
// signing is done by sbt-pgp plugin
diff --git a/ergo-core/build.sbt b/ergo-core/build.sbt
new file mode 100644
index 0000000000..b92786aef0
--- /dev/null
+++ b/ergo-core/build.sbt
@@ -0,0 +1,4 @@
+// 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
diff --git a/ergo-core/project/build.properties b/ergo-core/project/build.properties
new file mode 100644
index 0000000000..7609b47819
--- /dev/null
+++ b/ergo-core/project/build.properties
@@ -0,0 +1 @@
+sbt.version = 1.2.8
\ No newline at end of file
diff --git a/ergo-core/project/plugins.sbt b/ergo-core/project/plugins.sbt
new file mode 100644
index 0000000000..bcd4c6d604
--- /dev/null
+++ b/ergo-core/project/plugins.sbt
@@ -0,0 +1,3 @@
+addSbtPlugin("com.jsuereth" % "sbt-pgp" % "1.1.0")
+addSbtPlugin("org.xerial.sbt" % "sbt-sonatype" % "2.0")
+addSbtPlugin("com.github.gseitz" % "sbt-release" % "1.0.8")
diff --git a/ergo-core/src/main/scala/org/ergoplatform/CriticalSystemException.scala b/ergo-core/src/main/scala/org/ergoplatform/CriticalSystemException.scala
new file mode 100644
index 0000000000..776e3f8b3a
--- /dev/null
+++ b/ergo-core/src/main/scala/org/ergoplatform/CriticalSystemException.scala
@@ -0,0 +1,4 @@
+package org.ergoplatform
+
+/** Exception that triggers system shutdown */
+case class CriticalSystemException(message: String) extends Exception(message)
diff --git a/src/main/scala/scorex/core/NodeViewComponent.scala b/ergo-core/src/main/scala/org/ergoplatform/NodeViewComponent.scala
similarity index 50%
rename from src/main/scala/scorex/core/NodeViewComponent.scala
rename to ergo-core/src/main/scala/org/ergoplatform/NodeViewComponent.scala
index 30573a7d29..23c39dc154 100644
--- a/src/main/scala/scorex/core/NodeViewComponent.scala
+++ b/ergo-core/src/main/scala/org/ergoplatform/NodeViewComponent.scala
@@ -1,3 +1,3 @@
-package scorex.core
+package org.ergoplatform
trait NodeViewComponent
diff --git a/src/main/scala/scorex/core/NodeViewModifier.scala b/ergo-core/src/main/scala/org/ergoplatform/NodeViewModifier.scala
similarity index 93%
rename from src/main/scala/scorex/core/NodeViewModifier.scala
rename to ergo-core/src/main/scala/org/ergoplatform/NodeViewModifier.scala
index c11288a0f6..cecf7f01f8 100644
--- a/src/main/scala/scorex/core/NodeViewModifier.scala
+++ b/ergo-core/src/main/scala/org/ergoplatform/NodeViewModifier.scala
@@ -1,9 +1,9 @@
-package scorex.core
+package org.ergoplatform
+import org.ergoplatform.core.BytesSerializable
import org.ergoplatform.modifiers.NetworkObjectTypeId
import org.ergoplatform.modifiers.mempool.ErgoTransaction
-import scorex.core.serialization.BytesSerializable
-import scorex.core.utils.ScorexEncoding
+import org.ergoplatform.utils.ScorexEncoding
sealed trait NodeViewModifier extends BytesSerializable with ScorexEncoding {self =>
diff --git a/src/main/scala/scorex/core/consensus/ContainsModifiers.scala b/ergo-core/src/main/scala/org/ergoplatform/consensus/ContainsModifiers.scala
similarity index 95%
rename from src/main/scala/scorex/core/consensus/ContainsModifiers.scala
rename to ergo-core/src/main/scala/org/ergoplatform/consensus/ContainsModifiers.scala
index 55a2af0107..84edb9eb46 100644
--- a/src/main/scala/scorex/core/consensus/ContainsModifiers.scala
+++ b/ergo-core/src/main/scala/org/ergoplatform/consensus/ContainsModifiers.scala
@@ -1,4 +1,4 @@
-package scorex.core.consensus
+package org.ergoplatform.consensus
import org.ergoplatform.modifiers.ErgoNodeViewModifier
import scorex.util.ModifierId
diff --git a/src/main/scala/scorex/core/consensus/ModifierSemanticValidity.scala b/ergo-core/src/main/scala/org/ergoplatform/consensus/ModifierSemanticValidity.scala
similarity index 93%
rename from src/main/scala/scorex/core/consensus/ModifierSemanticValidity.scala
rename to ergo-core/src/main/scala/org/ergoplatform/consensus/ModifierSemanticValidity.scala
index a88acfbae1..04ea984ba8 100644
--- a/src/main/scala/scorex/core/consensus/ModifierSemanticValidity.scala
+++ b/ergo-core/src/main/scala/org/ergoplatform/consensus/ModifierSemanticValidity.scala
@@ -1,4 +1,4 @@
-package scorex.core.consensus
+package org.ergoplatform.consensus
/**
* Outcome of modifier semantic validation
diff --git a/src/main/scala/scorex/core/consensus/PeerChainStatus.scala b/ergo-core/src/main/scala/org/ergoplatform/consensus/PeerChainStatus.scala
similarity index 95%
rename from src/main/scala/scorex/core/consensus/PeerChainStatus.scala
rename to ergo-core/src/main/scala/org/ergoplatform/consensus/PeerChainStatus.scala
index 5cc2da6361..70a2e87a70 100644
--- a/src/main/scala/scorex/core/consensus/PeerChainStatus.scala
+++ b/ergo-core/src/main/scala/org/ergoplatform/consensus/PeerChainStatus.scala
@@ -1,5 +1,4 @@
-package scorex.core.consensus
-
+package org.ergoplatform.consensus
/**
* Status of a peer's chain relatively to our
diff --git a/src/main/scala/scorex/core/consensus/ProgressInfo.scala b/ergo-core/src/main/scala/org/ergoplatform/consensus/ProgressInfo.scala
similarity index 90%
rename from src/main/scala/scorex/core/consensus/ProgressInfo.scala
rename to ergo-core/src/main/scala/org/ergoplatform/consensus/ProgressInfo.scala
index c292b3760f..1e0fb3249d 100644
--- a/src/main/scala/scorex/core/consensus/ProgressInfo.scala
+++ b/ergo-core/src/main/scala/org/ergoplatform/consensus/ProgressInfo.scala
@@ -1,8 +1,8 @@
-package scorex.core.consensus
+package org.ergoplatform.consensus
+import org.ergoplatform.PersistentNodeViewModifier
import org.ergoplatform.modifiers.NetworkObjectTypeId
-import scorex.core.utils.ScorexEncoder
-import scorex.core.PersistentNodeViewModifier
+import org.ergoplatform.utils.ScorexEncoder
import scorex.util.ModifierId
/**
diff --git a/src/main/scala/scorex/core/consensus/SyncInfo.scala b/ergo-core/src/main/scala/org/ergoplatform/consensus/SyncInfo.scala
similarity index 68%
rename from src/main/scala/scorex/core/consensus/SyncInfo.scala
rename to ergo-core/src/main/scala/org/ergoplatform/consensus/SyncInfo.scala
index 128b643fd9..9503673199 100644
--- a/src/main/scala/scorex/core/consensus/SyncInfo.scala
+++ b/ergo-core/src/main/scala/org/ergoplatform/consensus/SyncInfo.scala
@@ -1,6 +1,6 @@
-package scorex.core.consensus
+package org.ergoplatform.consensus
-import scorex.core.serialization.BytesSerializable
+import org.ergoplatform.core.BytesSerializable
/**
* Syncing info provides information about starting points this node recommends another to start
diff --git a/src/main/scala/scorex/core/serialization/BytesSerializable.scala b/ergo-core/src/main/scala/org/ergoplatform/core/BytesSerializable.scala
similarity index 79%
rename from src/main/scala/scorex/core/serialization/BytesSerializable.scala
rename to ergo-core/src/main/scala/org/ergoplatform/core/BytesSerializable.scala
index 27f8f6a0d9..e635675165 100644
--- a/src/main/scala/scorex/core/serialization/BytesSerializable.scala
+++ b/ergo-core/src/main/scala/org/ergoplatform/core/BytesSerializable.scala
@@ -1,4 +1,6 @@
-package scorex.core.serialization
+package org.ergoplatform.core
+
+import org.ergoplatform.serialization.ErgoSerializer
/**
* Basic interface for objects which can be represented as bytes
diff --git a/src/main/scala/scorex/core/core.scala b/ergo-core/src/main/scala/org/ergoplatform/core/core.scala
similarity index 90%
rename from src/main/scala/scorex/core/core.scala
rename to ergo-core/src/main/scala/org/ergoplatform/core/core.scala
index 1bc9628cfd..59d6d0ffdd 100644
--- a/src/main/scala/scorex/core/core.scala
+++ b/ergo-core/src/main/scala/org/ergoplatform/core/core.scala
@@ -1,8 +1,9 @@
-package scorex
+package org.ergoplatform
import org.ergoplatform.modifiers.NetworkObjectTypeId
-import scorex.core.network.message.InvData
-import scorex.core.utils.ScorexEncoder
+import org.ergoplatform.network.message.InvData
+import org.ergoplatform.utils.ScorexEncoder
+import scorex.util
import scorex.util.encode.Base16
import supertagged.TaggedType
diff --git a/src/main/scala/org/ergoplatform/http/api/ApiCodecs.scala b/ergo-core/src/main/scala/org/ergoplatform/http/api/ApiCodecs.scala
similarity index 66%
rename from src/main/scala/org/ergoplatform/http/api/ApiCodecs.scala
rename to ergo-core/src/main/scala/org/ergoplatform/http/api/ApiCodecs.scala
index 424c279c99..625531218f 100644
--- a/src/main/scala/org/ergoplatform/http/api/ApiCodecs.scala
+++ b/ergo-core/src/main/scala/org/ergoplatform/http/api/ApiCodecs.scala
@@ -6,21 +6,16 @@ import org.bouncycastle.util.BigIntegers
import org.ergoplatform.ErgoBox.RegisterId
import org.ergoplatform._
import org.ergoplatform.http.api.ApiEncoderOption.Detalization
-import org.ergoplatform.http.api.requests.{CryptoResult, ExecuteRequest, HintExtractionRequest}
import org.ergoplatform.mining.{groupElemFromBytes, groupElemToBytes}
import org.ergoplatform.modifiers.mempool.{ErgoTransaction, UnsignedErgoTransaction}
-import org.ergoplatform.nodeView.history.ErgoHistory.Difficulty
-import org.ergoplatform.nodeView.history.extra.ExtraIndexer.getAddress
-import org.ergoplatform.nodeView.history.extra.{BalanceInfo, IndexedErgoBox, IndexedErgoTransaction, IndexedToken}
-import org.ergoplatform.nodeView.wallet.persistence.WalletDigest
-import org.ergoplatform.nodeView.wallet.requests.{ExternalSecret, GenerateCommitmentsRequest, TransactionSigningRequest}
+import org.ergoplatform.nodeView.history.ErgoHistoryUtils.Difficulty
import org.ergoplatform.sdk.wallet.secrets.{DhtSecretKey, DlogSecretKey}
import org.ergoplatform.settings.{Algos, ErgoAlgos}
import org.ergoplatform.wallet.Constants.ScanId
import org.ergoplatform.wallet.boxes.TrackedBox
import org.ergoplatform.wallet.interface4j.SecretString
import org.ergoplatform.wallet.interpreter.TransactionHintsBag
-import scorex.core.validation.ValidationResult
+import org.ergoplatform.validation.ValidationResult
import scorex.crypto.authds.merkle.MerkleProof
import scorex.crypto.authds.{LeafData, Side}
import scorex.crypto.hash.Digest
@@ -33,9 +28,6 @@ import sigmastate.crypto.VerifierMessage.Challenge
import sigmastate.crypto._
import sigmastate.interpreter._
import sigmastate.serialization.OpCodes
-import sigma.AnyValue
-import org.ergoplatform.nodeView.state.SnapshotsInfo
-import org.ergoplatform.nodeView.state.UtxoState.ManifestId
import org.ergoplatform.sdk.JsonCodecs
import sigmastate.eval.Extensions.ArrayOps
@@ -88,15 +80,6 @@ trait ApiCodecs extends JsonCodecs {
implicit val proveDlogEncoder: Encoder[ProveDlog] = _.pkBytes.asJson
- implicit val balancesSnapshotEncoder: Encoder[WalletDigest] = { v =>
- import v._
- Json.obj(
- "height" -> height.asJson,
- "balance" -> walletBalance.asJson,
- "assets" -> walletAssetBalances.toMap.map(x => (x._1: String, x._2)).asJson //toMap to have assets as JSON map
- )
- }
-
// 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
@@ -246,25 +229,7 @@ trait ApiCodecs extends JsonCodecs {
}
}
- implicit val hintExtractionRequestEncoder: Encoder[HintExtractionRequest] = {hr =>
- Map(
- "tx" -> hr.tx.asJson,
- "real" -> hr.real.asJson,
- "simulated" -> hr.simulated.asJson,
- "inputsRaw" -> hr.inputs.asJson,
- "dataInputsRaw" -> hr.dataInputs.asJson
- ).asJson
- }
- implicit val hintExtractionRequestDecoder: Decoder[HintExtractionRequest] = {cursor =>
- for {
- tx <- cursor.downField("tx").as[ErgoTransaction]
- real <- cursor.downField("real").as[Seq[SigmaBoolean]]
- simulated <- cursor.downField("simulated").as[Seq[SigmaBoolean]]
- inputs <- cursor.downField("inputsRaw").as[Option[Seq[String]]]
- dataInputs <- cursor.downField("dataInputsRaw").as[Option[Seq[String]]]
- } yield HintExtractionRequest(tx, real, simulated, inputs, dataInputs)
- }
implicit val firstProverMessageEncoder: Encoder[FirstProverMessage] = {
case cmtDlog: FirstDLogProverMessage =>
@@ -424,160 +389,6 @@ trait ApiCodecs extends JsonCodecs {
publicHints <- Decoder.decodeMap[Int, Seq[Hint]].tryDecode(cursor.downField("publicHints"))
} yield TransactionHintsBag(secretHints.mapValues(HintsBag.apply), publicHints.mapValues(HintsBag.apply))
}
-
- implicit val SnapshotInfoEncoder: Encoder[SnapshotsInfo] = { si =>
- Json.obj(
- "availableManifests" -> si.availableManifests.map { case (height, manifest) =>
- height -> manifest
- }.asJson
- )
- }
-
- implicit val SnapshotInfoDecoder: Decoder[SnapshotsInfo] = { cursor =>
- for {
- availableManifests <- Decoder.decodeMap[Int, ManifestId].tryDecode(cursor.downField("availableManifests"))
- } yield new SnapshotsInfo(availableManifests)
- }
-
- implicit val transactionSigningRequestEncoder: Encoder[TransactionSigningRequest] = { tsr =>
- Json.obj(
- "tx" -> tsr.unsignedTx.asJson,
- "secrets" -> Json.obj(
- "dlog" -> tsr.dlogs.asJson,
- "dht" -> tsr.dhts.asJson
- ),
- "hints" -> tsr.hints.asJson,
- "inputsRaw" -> tsr.inputs.asJson,
- "dataInputsRaw" -> tsr.dataInputs.asJson
- )
- }
-
- implicit val transactionSigningRequestDecoder: Decoder[TransactionSigningRequest] = { cursor =>
- for {
- tx <- cursor.downField("tx").as[UnsignedErgoTransaction]
- dlogs <- cursor.downField("secrets").downField("dlog").as[Option[Seq[DlogSecretKey]]]
- dhts <- cursor.downField("secrets").downField("dht").as[Option[Seq[DhtSecretKey]]]
- hints <- cursor.downField("hints").as[Option[TransactionHintsBag]]
- inputs <- cursor.downField("inputsRaw").as[Option[Seq[String]]]
- dataInputs <- cursor.downField("dataInputsRaw").as[Option[Seq[String]]]
- secrets = (dlogs.getOrElse(Seq.empty) ++ dhts.getOrElse(Seq.empty)).map(ExternalSecret.apply)
- } yield TransactionSigningRequest(tx, hints.getOrElse(TransactionHintsBag.empty), secrets, inputs, dataInputs)
- }
-
- implicit val generateCommitmentsRequestEncoder: Encoder[GenerateCommitmentsRequest] = { gcr =>
- Json.obj(
- "tx" -> gcr.unsignedTx.asJson,
- "secrets" -> Json.obj(
- "dlog" -> gcr.dlogs.asJson,
- "dht" -> gcr.dhts.asJson,
- "inputsRaw" -> gcr.inputs.asJson,
- "dataInputsRaw" -> gcr.dataInputs.asJson
- )
- )
- }
-
- implicit val generateCommitmentsRequestDecoder: Decoder[GenerateCommitmentsRequest] = { cursor =>
- for {
- tx <- cursor.downField("tx").as[UnsignedErgoTransaction]
- dlogs <- cursor.downField("secrets").downField("dlog").as[Option[Seq[DlogSecretKey]]]
- dhts <- cursor.downField("secrets").downField("dht").as[Option[Seq[DhtSecretKey]]]
- secrets = (dlogs.getOrElse(Seq.empty) ++ dhts.getOrElse(Seq.empty)).map(ExternalSecret.apply)
- secretsOpt = if(secrets.isEmpty) None else Some(secrets)
- inputs <- cursor.downField("inputsRaw").as[Option[Seq[String]]]
- dataInputs <- cursor.downField("dataInputsRaw").as[Option[Seq[String]]]
- } yield GenerateCommitmentsRequest(tx, secretsOpt, inputs, dataInputs)
- }
-
- implicit val executeRequestDecoder = new Decoder[ExecuteRequest] {
- def apply(cursor: HCursor): Decoder.Result[ExecuteRequest] = {
- for {
- script <- cursor.downField("script").as[String]
- env <- cursor.downField("namedConstants").as[Map[String,AnyValue]]
- ctx <- cursor.downField("context").as[ErgoLikeContext]
- } yield ExecuteRequest(script, env.map({ case (k,v) => k -> v.value }), ctx)
- }
- }
-
- implicit val cryptResultEncoder: Encoder[CryptoResult] = {
- res =>
- val fields = Map(
- "value" -> res.value.asJson,
- "cost" -> res.cost.asJson
- )
- fields.asJson
- }
-
- implicit val indexedBoxEncoder: Encoder[IndexedErgoBox] = { iEb =>
- iEb.box.asJson.deepMerge(Json.obj(
- "globalIndex" -> iEb.globalIndex.asJson,
- "inclusionHeight" -> iEb.inclusionHeight.asJson,
- "address" -> ergoAddressEncoder.toString(getAddress(iEb.box.ergoTree)).asJson,
- "spentTransactionId" -> iEb.spendingTxIdOpt.asJson
- ))
- }
-
- implicit val indexedBoxSeqEncoder: Encoder[(Seq[IndexedErgoBox],Long)] = { iEbSeq =>
- Json.obj(
- "items" -> iEbSeq._1.asJson,
- "total" -> iEbSeq._2.asJson
- )
- }
-
- implicit val indexedTxEncoder: Encoder[IndexedErgoTransaction] = { iEt =>
- Json.obj(
- "id" -> iEt.txid.asJson,
- "blockId" -> iEt.blockId.asJson,
- "inclusionHeight" -> iEt.inclusionHeight.asJson,
- "timestamp" -> iEt.timestamp.asJson,
- "index" -> iEt.index.asJson,
- "globalIndex" -> iEt.globalIndex.asJson,
- "numConfirmations" -> iEt.numConfirmations.asJson,
- "inputs" -> iEt.inputs.asJson,
- "dataInputs" -> iEt.dataInputs.asJson,
- "outputs" -> iEt.outputs.asJson,
- "size" -> iEt.txSize.asJson
- )
- }
-
- implicit val indexedTxSeqEncoder: Encoder[(Seq[IndexedErgoTransaction],Long)] = { iEtSeq =>
- Json.obj(
- "items" -> iEtSeq._1.asJson,
- "total" -> iEtSeq._2.asJson
- )
- }
-
- implicit val IndexedTokenEncoder: Encoder[IndexedToken] = { token =>
- Json.obj(
- "id" -> token.tokenId.asJson,
- "boxId" -> token.boxId.asJson,
- "emissionAmount" -> token.amount.asJson,
- "name" -> token.name.asJson,
- "description" -> token.description.asJson,
- "decimals" -> token.decimals.asJson
- )
- }
-
- implicit val BalanceInfoEncoder: Encoder[BalanceInfo] = { bal =>
- Json.obj(
- "nanoErgs" -> bal.nanoErgs.asJson,
- "tokens" -> bal.tokens.map(token => {
- Json.obj(
- "tokenId" -> token._1.asJson,
- "amount" -> token._2.asJson,
- "decimals" -> bal.additionalTokenInfo(token._1)._2.asJson,
- "name" -> bal.additionalTokenInfo(token._1)._1.asJson
- )
- }).asJson
- )
- }
-
- implicit val TotalBalanceInfoEncoder: Encoder[(BalanceInfo,BalanceInfo)] = { tBal =>
- Json.obj(
- "confirmed" -> tBal._1.asJson,
- "unconfirmed" -> tBal._2.asJson
- )
- }
-
}
trait ApiEncoderOption
diff --git a/src/main/scala/org/ergoplatform/local/NipopowVerificationResult.scala b/ergo-core/src/main/scala/org/ergoplatform/local/NipopowVerificationResult.scala
similarity index 100%
rename from src/main/scala/org/ergoplatform/local/NipopowVerificationResult.scala
rename to ergo-core/src/main/scala/org/ergoplatform/local/NipopowVerificationResult.scala
diff --git a/src/main/scala/org/ergoplatform/local/NipopowVerifier.scala b/ergo-core/src/main/scala/org/ergoplatform/local/NipopowVerifier.scala
similarity index 100%
rename from src/main/scala/org/ergoplatform/local/NipopowVerifier.scala
rename to ergo-core/src/main/scala/org/ergoplatform/local/NipopowVerifier.scala
diff --git a/src/main/scala/org/ergoplatform/mining/AutolykosPowScheme.scala b/ergo-core/src/main/scala/org/ergoplatform/mining/AutolykosPowScheme.scala
similarity index 98%
rename from src/main/scala/org/ergoplatform/mining/AutolykosPowScheme.scala
rename to ergo-core/src/main/scala/org/ergoplatform/mining/AutolykosPowScheme.scala
index ad5af554a6..5dd710da26 100644
--- a/src/main/scala/org/ergoplatform/mining/AutolykosPowScheme.scala
+++ b/ergo-core/src/main/scala/org/ergoplatform/mining/AutolykosPowScheme.scala
@@ -10,7 +10,7 @@ import org.ergoplatform.modifiers.history.extension.ExtensionCandidate
import org.ergoplatform.modifiers.history.header.Header.{Timestamp, Version}
import org.ergoplatform.modifiers.history.header.{Header, HeaderSerializer, HeaderWithoutPow}
import org.ergoplatform.modifiers.mempool.ErgoTransaction
-import org.ergoplatform.nodeView.history.ErgoHistory
+import org.ergoplatform.nodeView.history.ErgoHistoryUtils.GenesisHeight
import org.ergoplatform.nodeView.mempool.TransactionMembershipProof
import scorex.crypto.authds.{ADDigest, SerializedAdProof}
import scorex.crypto.hash.{Blake2b256, Digest32}
@@ -45,7 +45,7 @@ class AutolykosPowScheme(val k: Int, val n: Int) extends ScorexLogging {
/**
* Number of elements in a table to find k-sum problem solution on top of
*/
- val NBase: Int = Math.pow(2, n).toInt
+ val NBase: Int = Math.pow(2, n.toDouble).toInt
/**
* Initial height since which table (`N` value) starting to increase by 5% per `IncreasePeriodForN` blocks
@@ -91,7 +91,7 @@ class AutolykosPowScheme(val k: Int, val n: Int) extends ScorexLogging {
/**
* Constant data to be added to hash function to increase its calculation time
*/
- val M: Array[Byte] = (0 until 1024).toArray.flatMap(i => Longs.toByteArray(i))
+ val M: Array[Byte] = (0 until 1024).toArray.flatMap(i => Longs.toByteArray(i.toLong))
/**
* Checks that `header` contains correct solution of the Autolykos PoW puzzle.
@@ -387,7 +387,7 @@ class AutolykosPowScheme(val k: Int, val n: Int) extends ScorexLogging {
def deriveExternalCandidate(blockCandidate: CandidateBlock,
pk: ProveDlog,
mandatoryTxIds: Seq[ModifierId]): WorkMessage = {
- val headerCandidate = CandidateGenerator.deriveUnprovenHeader(blockCandidate)
+ val headerCandidate = CandidateUtils.deriveUnprovenHeader(blockCandidate)
val msg = msgByHeader(headerCandidate)
val b = getB(blockCandidate.nBits)
val hOpt = if (blockCandidate.version == 1) {
@@ -417,7 +417,7 @@ object AutolykosPowScheme {
*/
def derivedHeaderFields(parentOpt: Option[Header]): (ModifierId, Int) = {
- val height = parentOpt.map(parent => parent.height + 1).getOrElse(ErgoHistory.GenesisHeight)
+ val height = parentOpt.map(parent => parent.height + 1).getOrElse(GenesisHeight)
val parentId: ModifierId = parentOpt.map(_.id).getOrElse(Header.GenesisParentId)
diff --git a/src/main/scala/org/ergoplatform/mining/AutolykosSolution.scala b/ergo-core/src/main/scala/org/ergoplatform/mining/AutolykosSolution.scala
similarity index 98%
rename from src/main/scala/org/ergoplatform/mining/AutolykosSolution.scala
rename to ergo-core/src/main/scala/org/ergoplatform/mining/AutolykosSolution.scala
index adeff25edc..b448135411 100644
--- a/src/main/scala/org/ergoplatform/mining/AutolykosSolution.scala
+++ b/ergo-core/src/main/scala/org/ergoplatform/mining/AutolykosSolution.scala
@@ -6,7 +6,7 @@ import org.bouncycastle.util.BigIntegers
import org.ergoplatform.http.api.ApiCodecs
import org.ergoplatform.modifiers.history.header.Header.Version
import org.ergoplatform.settings.Algos
-import scorex.core.serialization.ErgoSerializer
+import org.ergoplatform.serialization.ErgoSerializer
import scorex.util.serialization.{Reader, Writer}
import sigmastate.crypto.CryptoConstants
import sigmastate.crypto.CryptoConstants.EcPointType
diff --git a/src/main/scala/org/ergoplatform/mining/CandidateBlock.scala b/ergo-core/src/main/scala/org/ergoplatform/mining/CandidateBlock.scala
similarity index 100%
rename from src/main/scala/org/ergoplatform/mining/CandidateBlock.scala
rename to ergo-core/src/main/scala/org/ergoplatform/mining/CandidateBlock.scala
diff --git a/ergo-core/src/main/scala/org/ergoplatform/mining/CandidateUtils.scala b/ergo-core/src/main/scala/org/ergoplatform/mining/CandidateUtils.scala
new file mode 100644
index 0000000000..0ad1d87624
--- /dev/null
+++ b/ergo-core/src/main/scala/org/ergoplatform/mining/CandidateUtils.scala
@@ -0,0 +1,35 @@
+package org.ergoplatform.mining
+
+import org.ergoplatform.mining.AutolykosPowScheme.derivedHeaderFields
+import org.ergoplatform.modifiers.history.{ADProofs, BlockTransactions}
+import org.ergoplatform.modifiers.history.header.HeaderWithoutPow
+import scorex.crypto.hash.Digest32
+
+/**
+ * Functions related to block candidate generation
+ */
+object CandidateUtils {
+ /**
+ * Derives header without pow from [[CandidateBlock]].
+ */
+ def deriveUnprovenHeader(candidate: CandidateBlock): HeaderWithoutPow = {
+ val (parentId, height) = derivedHeaderFields(candidate.parentOpt)
+ val transactionsRoot =
+ BlockTransactions.transactionsRoot(candidate.transactions, candidate.version)
+ val adProofsRoot = ADProofs.proofDigest(candidate.adProofBytes)
+ val extensionRoot: Digest32 = candidate.extension.digest
+
+ HeaderWithoutPow(
+ candidate.version,
+ parentId,
+ adProofsRoot,
+ candidate.stateRoot,
+ transactionsRoot,
+ candidate.timestamp,
+ candidate.nBits,
+ height,
+ extensionRoot,
+ candidate.votes
+ )
+ }
+}
diff --git a/src/main/scala/org/ergoplatform/mining/NumericHash.scala b/ergo-core/src/main/scala/org/ergoplatform/mining/NumericHash.scala
similarity index 100%
rename from src/main/scala/org/ergoplatform/mining/NumericHash.scala
rename to ergo-core/src/main/scala/org/ergoplatform/mining/NumericHash.scala
diff --git a/src/main/scala/org/ergoplatform/mining/ProofOfUpcomingTransactions.scala b/ergo-core/src/main/scala/org/ergoplatform/mining/ProofOfUpcomingTransactions.scala
similarity index 100%
rename from src/main/scala/org/ergoplatform/mining/ProofOfUpcomingTransactions.scala
rename to ergo-core/src/main/scala/org/ergoplatform/mining/ProofOfUpcomingTransactions.scala
diff --git a/src/main/scala/org/ergoplatform/mining/WorkMessage.scala b/ergo-core/src/main/scala/org/ergoplatform/mining/WorkMessage.scala
similarity index 95%
rename from src/main/scala/org/ergoplatform/mining/WorkMessage.scala
rename to ergo-core/src/main/scala/org/ergoplatform/mining/WorkMessage.scala
index 3c815d44fc..4ca8f4641d 100644
--- a/src/main/scala/org/ergoplatform/mining/WorkMessage.scala
+++ b/ergo-core/src/main/scala/org/ergoplatform/mining/WorkMessage.scala
@@ -3,7 +3,7 @@ package org.ergoplatform.mining
import io.circe.syntax._
import io.circe.{Encoder, Json}
import org.ergoplatform.http.api.ApiCodecs
-import org.ergoplatform.nodeView.history.ErgoHistory.Height
+import org.ergoplatform.nodeView.history.ErgoHistoryUtils.Height
import sigmastate.crypto.DLogProtocol.ProveDlog
diff --git a/src/main/scala/org/ergoplatform/mining/difficulty/DifficultyAdjustment.scala b/ergo-core/src/main/scala/org/ergoplatform/mining/difficulty/DifficultyAdjustment.scala
similarity index 98%
rename from src/main/scala/org/ergoplatform/mining/difficulty/DifficultyAdjustment.scala
rename to ergo-core/src/main/scala/org/ergoplatform/mining/difficulty/DifficultyAdjustment.scala
index 1e2ed12deb..e61e45c952 100644
--- a/src/main/scala/org/ergoplatform/mining/difficulty/DifficultyAdjustment.scala
+++ b/ergo-core/src/main/scala/org/ergoplatform/mining/difficulty/DifficultyAdjustment.scala
@@ -1,7 +1,7 @@
package org.ergoplatform.mining.difficulty
import org.ergoplatform.modifiers.history.header.Header
-import org.ergoplatform.nodeView.history.ErgoHistory.{Difficulty, Height}
+import org.ergoplatform.nodeView.history.ErgoHistoryUtils.{Difficulty, Height}
import org.ergoplatform.settings.ChainSettings
import scorex.util.ScorexLogging
import scala.concurrent.duration.FiniteDuration
diff --git a/src/main/scala/org/ergoplatform/mining/difficulty/DifficultySerializer.scala b/ergo-core/src/main/scala/org/ergoplatform/mining/difficulty/DifficultySerializer.scala
similarity index 97%
rename from src/main/scala/org/ergoplatform/mining/difficulty/DifficultySerializer.scala
rename to ergo-core/src/main/scala/org/ergoplatform/mining/difficulty/DifficultySerializer.scala
index 6d3a2407f7..d719f9a95c 100644
--- a/src/main/scala/org/ergoplatform/mining/difficulty/DifficultySerializer.scala
+++ b/ergo-core/src/main/scala/org/ergoplatform/mining/difficulty/DifficultySerializer.scala
@@ -2,8 +2,8 @@ package org.ergoplatform.mining.difficulty
import java.math.BigInteger
-import org.ergoplatform.nodeView.history.ErgoHistory._
-import scorex.core.serialization.ErgoSerializer
+import org.ergoplatform.nodeView.history.ErgoHistoryUtils._
+import org.ergoplatform.serialization.ErgoSerializer
import scorex.util.serialization.{Reader, Writer}
/**
diff --git a/src/main/scala/org/ergoplatform/mining/mining.scala b/ergo-core/src/main/scala/org/ergoplatform/mining/mining.scala
similarity index 98%
rename from src/main/scala/org/ergoplatform/mining/mining.scala
rename to ergo-core/src/main/scala/org/ergoplatform/mining/mining.scala
index 526d2eeba2..e469225906 100644
--- a/src/main/scala/org/ergoplatform/mining/mining.scala
+++ b/ergo-core/src/main/scala/org/ergoplatform/mining/mining.scala
@@ -11,7 +11,7 @@ package object mining {
type PrivateKey = BigInt
- val PublicKeyLength: Byte = 33
+ val PublicKeyLength: Int = 33
val group: BcDlogGroup = CryptoConstants.dlogGroup
diff --git a/src/main/scala/org/ergoplatform/modifiers/BlockSection.scala b/ergo-core/src/main/scala/org/ergoplatform/modifiers/BlockSection.scala
similarity index 94%
rename from src/main/scala/org/ergoplatform/modifiers/BlockSection.scala
rename to ergo-core/src/main/scala/org/ergoplatform/modifiers/BlockSection.scala
index fea7be63e3..8ab1914591 100644
--- a/src/main/scala/org/ergoplatform/modifiers/BlockSection.scala
+++ b/ergo-core/src/main/scala/org/ergoplatform/modifiers/BlockSection.scala
@@ -1,10 +1,10 @@
package org.ergoplatform.modifiers
import io.circe.Encoder
+import org.ergoplatform.PersistentNodeViewModifier
import org.ergoplatform.modifiers.history.extension.Extension
import org.ergoplatform.modifiers.history.header.Header
import org.ergoplatform.modifiers.history.{ADProofs, BlockTransactions}
-import scorex.core.PersistentNodeViewModifier
/**
diff --git a/src/main/scala/org/ergoplatform/modifiers/ErgoFullBlock.scala b/ergo-core/src/main/scala/org/ergoplatform/modifiers/ErgoFullBlock.scala
similarity index 95%
rename from src/main/scala/org/ergoplatform/modifiers/ErgoFullBlock.scala
rename to ergo-core/src/main/scala/org/ergoplatform/modifiers/ErgoFullBlock.scala
index 42fd2c286e..23ca8e6c91 100644
--- a/src/main/scala/org/ergoplatform/modifiers/ErgoFullBlock.scala
+++ b/ergo-core/src/main/scala/org/ergoplatform/modifiers/ErgoFullBlock.scala
@@ -2,13 +2,13 @@ package org.ergoplatform.modifiers
import io.circe.syntax._
import io.circe.{Decoder, Encoder, HCursor, Json}
+import org.ergoplatform.TransactionsCarryingPersistentNodeViewModifier
import org.ergoplatform.http.api.ApiCodecs
import org.ergoplatform.modifiers.history.extension.Extension
import org.ergoplatform.modifiers.history.header.Header
import org.ergoplatform.modifiers.history.{ADProofs, BlockTransactions}
import org.ergoplatform.modifiers.mempool.ErgoTransaction
-import scorex.core.serialization.ErgoSerializer
-import scorex.core.TransactionsCarryingPersistentNodeViewModifier
+import org.ergoplatform.serialization.ErgoSerializer
import scorex.util.ModifierId
case class ErgoFullBlock(header: Header,
diff --git a/src/main/scala/org/ergoplatform/modifiers/ErgoNodeViewModifier.scala b/ergo-core/src/main/scala/org/ergoplatform/modifiers/ErgoNodeViewModifier.scala
similarity index 85%
rename from src/main/scala/org/ergoplatform/modifiers/ErgoNodeViewModifier.scala
rename to ergo-core/src/main/scala/org/ergoplatform/modifiers/ErgoNodeViewModifier.scala
index 635021bac1..34fff14e05 100644
--- a/src/main/scala/org/ergoplatform/modifiers/ErgoNodeViewModifier.scala
+++ b/ergo-core/src/main/scala/org/ergoplatform/modifiers/ErgoNodeViewModifier.scala
@@ -1,6 +1,6 @@
package org.ergoplatform.modifiers
-import scorex.core.serialization.BytesSerializable
+import org.ergoplatform.core.BytesSerializable
import scorex.util.{ModifierId, bytesToId}
trait ErgoNodeViewModifier { self: BytesSerializable =>
diff --git a/src/main/scala/org/ergoplatform/modifiers/NetworkObjectTypeId.scala b/ergo-core/src/main/scala/org/ergoplatform/modifiers/NetworkObjectTypeId.scala
similarity index 100%
rename from src/main/scala/org/ergoplatform/modifiers/NetworkObjectTypeId.scala
rename to ergo-core/src/main/scala/org/ergoplatform/modifiers/NetworkObjectTypeId.scala
diff --git a/src/main/scala/org/ergoplatform/modifiers/NonHeaderBlockSection.scala b/ergo-core/src/main/scala/org/ergoplatform/modifiers/NonHeaderBlockSection.scala
similarity index 100%
rename from src/main/scala/org/ergoplatform/modifiers/NonHeaderBlockSection.scala
rename to ergo-core/src/main/scala/org/ergoplatform/modifiers/NonHeaderBlockSection.scala
diff --git a/src/main/scala/org/ergoplatform/modifiers/history/ADProofs.scala b/ergo-core/src/main/scala/org/ergoplatform/modifiers/history/ADProofs.scala
similarity index 97%
rename from src/main/scala/org/ergoplatform/modifiers/history/ADProofs.scala
rename to ergo-core/src/main/scala/org/ergoplatform/modifiers/history/ADProofs.scala
index 14a4f1de15..f6404d0101 100644
--- a/src/main/scala/org/ergoplatform/modifiers/history/ADProofs.scala
+++ b/ergo-core/src/main/scala/org/ergoplatform/modifiers/history/ADProofs.scala
@@ -7,7 +7,7 @@ import org.ergoplatform.modifiers.{NetworkObjectTypeId, NonHeaderBlockSection, P
import org.ergoplatform.modifiers.state._
import org.ergoplatform.settings.Algos.HF
import org.ergoplatform.settings.{Algos, Constants}
-import scorex.core.serialization.ErgoSerializer
+import org.ergoplatform.serialization.ErgoSerializer
import scorex.crypto.authds.avltree.batch.{Lookup => _, _}
import scorex.crypto.authds.{ADDigest, ADValue, SerializedAdProof}
import scorex.crypto.hash.Digest32
@@ -97,7 +97,7 @@ object ADProofsSerializer extends ErgoSerializer[ADProofs] {
override def serialize(obj: ADProofs, w: Writer): Unit = {
w.putBytes(idToBytes(obj.headerId))
- w.putUInt(obj.proofBytes.size)
+ w.putUInt(obj.proofBytes.size.toLong)
w.putBytes(obj.proofBytes)
}
diff --git a/src/main/scala/org/ergoplatform/modifiers/history/BlockTransactions.scala b/ergo-core/src/main/scala/org/ergoplatform/modifiers/history/BlockTransactions.scala
similarity index 89%
rename from src/main/scala/org/ergoplatform/modifiers/history/BlockTransactions.scala
rename to ergo-core/src/main/scala/org/ergoplatform/modifiers/history/BlockTransactions.scala
index 4717faf501..7e52ede09a 100644
--- a/src/main/scala/org/ergoplatform/modifiers/history/BlockTransactions.scala
+++ b/ergo-core/src/main/scala/org/ergoplatform/modifiers/history/BlockTransactions.scala
@@ -2,15 +2,15 @@ package org.ergoplatform.modifiers.history
import io.circe.syntax._
import io.circe.{Decoder, Encoder, HCursor}
+import org.ergoplatform.TransactionsCarryingPersistentNodeViewModifier
import org.ergoplatform.http.api.ApiCodecs
import org.ergoplatform.modifiers.{BlockTransactionsTypeId, NetworkObjectTypeId, NonHeaderBlockSection}
import org.ergoplatform.modifiers.history.header.Header
import org.ergoplatform.modifiers.mempool.{ErgoTransaction, ErgoTransactionSerializer}
import org.ergoplatform.nodeView.mempool.TransactionMembershipProof
import org.ergoplatform.settings.{Algos, Constants}
-import scorex.core._
import org.ergoplatform.modifiers.history.header.Header.Version
-import scorex.core.serialization.ErgoSerializer
+import org.ergoplatform.serialization.ErgoSerializer
import scorex.crypto.authds.LeafData
import scorex.crypto.authds.merkle.{Leaf, MerkleProof, MerkleTree}
import scorex.crypto.hash.Digest32
@@ -137,9 +137,9 @@ object BlockTransactionsSerializer extends ErgoSerializer[BlockTransactions] {
override def serialize(bt: BlockTransactions, w: Writer): Unit = {
w.putBytes(idToBytes(bt.headerId))
if (bt.blockVersion > 1) {
- w.putUInt(MaxTransactionsInBlock + bt.blockVersion)
+ w.putUInt(MaxTransactionsInBlock.toLong + bt.blockVersion)
}
- w.putUInt(bt.txs.size)
+ w.putUInt(bt.txs.size.toLong)
bt.txs.foreach { tx =>
ErgoTransactionSerializer.serialize(tx, w)
}
@@ -150,15 +150,15 @@ object BlockTransactionsSerializer extends ErgoSerializer[BlockTransactions] {
val headerId: ModifierId = bytesToId(r.getBytes(Constants.ModifierIdSize))
val verOrCount = r.getUInt().toIntExact
- /**
- * A hack to avoid need for a database rescan if older version of the serializer was used to put.
- * block transactions into.
- *
- * We consider that in a block there could be no more than 10,000,000 transactions.
- *
- * Then the new serializer puts 10,000,000 + block version (while the old one just puts tx count with no version),
- * and the reader knows that a new serializer was used if the first unsigned integer read is more than 10,000,000.
- */
+ /*
+ * A hack to avoid need for a database rescan if older version of the serializer was used to put.
+ * block transactions into.
+ *
+ * We consider that in a block there could be no more than 10,000,000 transactions.
+ *
+ * Then the new serializer puts 10,000,000 + block version (while the old one just puts tx count with no version),
+ * and the reader knows that a new serializer was used if the first unsigned integer read is more than 10,000,000.
+ */
var blockVersion = 1: Byte
var txCount = verOrCount
if (verOrCount > MaxTransactionsInBlock) {
diff --git a/src/main/scala/org/ergoplatform/modifiers/history/HeaderChain.scala b/ergo-core/src/main/scala/org/ergoplatform/modifiers/history/HeaderChain.scala
similarity index 100%
rename from src/main/scala/org/ergoplatform/modifiers/history/HeaderChain.scala
rename to ergo-core/src/main/scala/org/ergoplatform/modifiers/history/HeaderChain.scala
diff --git a/src/main/scala/org/ergoplatform/modifiers/history/HistoryModifierSerializer.scala b/ergo-core/src/main/scala/org/ergoplatform/modifiers/history/HistoryModifierSerializer.scala
similarity index 96%
rename from src/main/scala/org/ergoplatform/modifiers/history/HistoryModifierSerializer.scala
rename to ergo-core/src/main/scala/org/ergoplatform/modifiers/history/HistoryModifierSerializer.scala
index 2d4e8ac6fd..5f6a72ff2a 100644
--- a/src/main/scala/org/ergoplatform/modifiers/history/HistoryModifierSerializer.scala
+++ b/ergo-core/src/main/scala/org/ergoplatform/modifiers/history/HistoryModifierSerializer.scala
@@ -3,7 +3,7 @@ package org.ergoplatform.modifiers.history
import org.ergoplatform.modifiers.BlockSection
import org.ergoplatform.modifiers.history.extension.{Extension, ExtensionSerializer}
import org.ergoplatform.modifiers.history.header.{Header, HeaderSerializer}
-import scorex.core.serialization.ErgoSerializer
+import org.ergoplatform.serialization.ErgoSerializer
import scorex.util.serialization.{Reader, Writer}
object HistoryModifierSerializer extends ErgoSerializer[BlockSection] {
diff --git a/src/main/scala/org/ergoplatform/modifiers/history/PreHeader.scala b/ergo-core/src/main/scala/org/ergoplatform/modifiers/history/PreHeader.scala
similarity index 95%
rename from src/main/scala/org/ergoplatform/modifiers/history/PreHeader.scala
rename to ergo-core/src/main/scala/org/ergoplatform/modifiers/history/PreHeader.scala
index da183f33eb..7710383183 100644
--- a/src/main/scala/org/ergoplatform/modifiers/history/PreHeader.scala
+++ b/ergo-core/src/main/scala/org/ergoplatform/modifiers/history/PreHeader.scala
@@ -3,7 +3,7 @@ package org.ergoplatform.modifiers.history
import org.ergoplatform.mining.AutolykosPowScheme
import org.ergoplatform.modifiers.history.header.Header
import org.ergoplatform.modifiers.history.header.Header._
-import org.ergoplatform.nodeView.history.ErgoHistory
+import org.ergoplatform.nodeView.history.ErgoHistoryUtils._
import org.ergoplatform.settings.Constants
import scorex.util._
import sigmastate.crypto.CryptoConstants.EcPointType
@@ -72,7 +72,7 @@ object PreHeader {
parentId = Header.GenesisParentId,
timestamp = 0,
nBits = Constants.InitialNBits,
- height = ErgoHistory.EmptyHistoryHeight,
+ height = EmptyHistoryHeight,
votes = Array.fill(3)(0.toByte),
minerPk = org.ergoplatform.mining.group.generator
)
diff --git a/src/main/scala/org/ergoplatform/modifiers/history/extension/Extension.scala b/ergo-core/src/main/scala/org/ergoplatform/modifiers/history/extension/Extension.scala
similarity index 98%
rename from src/main/scala/org/ergoplatform/modifiers/history/extension/Extension.scala
rename to ergo-core/src/main/scala/org/ergoplatform/modifiers/history/extension/Extension.scala
index c402d88342..c5dede1165 100644
--- a/src/main/scala/org/ergoplatform/modifiers/history/extension/Extension.scala
+++ b/ergo-core/src/main/scala/org/ergoplatform/modifiers/history/extension/Extension.scala
@@ -6,7 +6,7 @@ import io.circe.{Decoder, Encoder, HCursor}
import org.ergoplatform.http.api.ApiCodecs
import org.ergoplatform.modifiers.{ExtensionTypeId, NetworkObjectTypeId, NonHeaderBlockSection}
import org.ergoplatform.settings.Algos
-import scorex.core.serialization.ErgoSerializer
+import org.ergoplatform.serialization.ErgoSerializer
import scorex.crypto.authds.LeafData
import scorex.crypto.authds.merkle.MerkleTree
import scorex.crypto.hash.Digest32
diff --git a/src/main/scala/org/ergoplatform/modifiers/history/extension/ExtensionCandidate.scala b/ergo-core/src/main/scala/org/ergoplatform/modifiers/history/extension/ExtensionCandidate.scala
similarity index 100%
rename from src/main/scala/org/ergoplatform/modifiers/history/extension/ExtensionCandidate.scala
rename to ergo-core/src/main/scala/org/ergoplatform/modifiers/history/extension/ExtensionCandidate.scala
diff --git a/src/main/scala/org/ergoplatform/modifiers/history/extension/ExtensionSerializer.scala b/ergo-core/src/main/scala/org/ergoplatform/modifiers/history/extension/ExtensionSerializer.scala
similarity index 95%
rename from src/main/scala/org/ergoplatform/modifiers/history/extension/ExtensionSerializer.scala
rename to ergo-core/src/main/scala/org/ergoplatform/modifiers/history/extension/ExtensionSerializer.scala
index 7207b9c056..137e1813dd 100644
--- a/src/main/scala/org/ergoplatform/modifiers/history/extension/ExtensionSerializer.scala
+++ b/ergo-core/src/main/scala/org/ergoplatform/modifiers/history/extension/ExtensionSerializer.scala
@@ -1,7 +1,7 @@
package org.ergoplatform.modifiers.history.extension
import org.ergoplatform.settings.Constants
-import scorex.core.serialization.ErgoSerializer
+import org.ergoplatform.serialization.ErgoSerializer
import scorex.util.serialization.{Reader, Writer}
import scorex.util.{bytesToId, idToBytes}
diff --git a/src/main/scala/org/ergoplatform/modifiers/history/header/Header.scala b/ergo-core/src/main/scala/org/ergoplatform/modifiers/history/header/Header.scala
similarity index 97%
rename from src/main/scala/org/ergoplatform/modifiers/history/header/Header.scala
rename to ergo-core/src/main/scala/org/ergoplatform/modifiers/history/header/Header.scala
index df31f80686..24d5887ecd 100644
--- a/src/main/scala/org/ergoplatform/modifiers/history/header/Header.scala
+++ b/ergo-core/src/main/scala/org/ergoplatform/modifiers/history/header/Header.scala
@@ -8,11 +8,10 @@ import org.ergoplatform.mining.difficulty.DifficultySerializer
import org.ergoplatform.modifiers.history.extension.Extension
import org.ergoplatform.modifiers.history.{ADProofs, BlockTransactions, PreHeader}
import org.ergoplatform.modifiers.{BlockSection, HeaderTypeId, NetworkObjectTypeId, NonHeaderBlockSection}
-import org.ergoplatform.nodeView.history.ErgoHistory
-import org.ergoplatform.nodeView.history.ErgoHistory.Difficulty
+import org.ergoplatform.nodeView.history.ErgoHistoryUtils._
import org.ergoplatform.settings.{Algos, Constants}
import org.ergoplatform.wallet.interpreter.ErgoInterpreter
-import scorex.core.serialization.ErgoSerializer
+import org.ergoplatform.serialization.ErgoSerializer
import scorex.crypto.authds.ADDigest
import scorex.crypto.hash.Digest32
import scorex.util._
@@ -90,7 +89,7 @@ case class Header(override val version: Header.Version,
override lazy val serializer: ErgoSerializer[Header] = HeaderSerializer
- lazy val isGenesis: Boolean = height == ErgoHistory.GenesisHeight
+ lazy val isGenesis: Boolean = height == GenesisHeight
/**
* Checks that modifier m corresponds to this header
diff --git a/src/main/scala/org/ergoplatform/modifiers/history/header/HeaderSerializer.scala b/ergo-core/src/main/scala/org/ergoplatform/modifiers/history/header/HeaderSerializer.scala
similarity index 94%
rename from src/main/scala/org/ergoplatform/modifiers/history/header/HeaderSerializer.scala
rename to ergo-core/src/main/scala/org/ergoplatform/modifiers/history/header/HeaderSerializer.scala
index 0e09bd7714..b6123e1141 100644
--- a/src/main/scala/org/ergoplatform/modifiers/history/header/HeaderSerializer.scala
+++ b/ergo-core/src/main/scala/org/ergoplatform/modifiers/history/header/HeaderSerializer.scala
@@ -1,9 +1,9 @@
package org.ergoplatform.modifiers.history.header
+import org.ergoplatform.core.idToBytes
import org.ergoplatform.mining.AutolykosSolutionSerializer
import org.ergoplatform.mining.difficulty.DifficultySerializer
-import scorex.core.idToBytes
-import scorex.core.serialization.ErgoSerializer
+import org.ergoplatform.serialization.ErgoSerializer
import scorex.crypto.authds.ADDigest
import scorex.crypto.hash.Digest32
import scorex.util.serialization.{Reader, VLQByteBufferWriter, Writer}
@@ -26,13 +26,13 @@ object HeaderSerializer extends ErgoSerializer[Header] {
w.putULong(h.timestamp)
w.putBytes(h.extensionRoot)
DifficultySerializer.serialize(h.nBits, w)
- w.putUInt(h.height)
+ w.putUInt(h.height.toLong)
w.putBytes(h.votes)
// For block version >= 2, this new byte encodes length of possible new fields.
// Set to 0 for now, so no new fields.
if (h.version > Header.InitialVersion) {
- w.putUByte(0: Byte)
+ w.putUByte(0)
}
}
diff --git a/src/main/scala/org/ergoplatform/modifiers/history/header/HeaderWithoutPow.scala b/ergo-core/src/main/scala/org/ergoplatform/modifiers/history/header/HeaderWithoutPow.scala
similarity index 100%
rename from src/main/scala/org/ergoplatform/modifiers/history/header/HeaderWithoutPow.scala
rename to ergo-core/src/main/scala/org/ergoplatform/modifiers/history/header/HeaderWithoutPow.scala
diff --git a/src/main/scala/org/ergoplatform/modifiers/history/header/PreGenesisHeader.scala b/ergo-core/src/main/scala/org/ergoplatform/modifiers/history/header/PreGenesisHeader.scala
similarity index 77%
rename from src/main/scala/org/ergoplatform/modifiers/history/header/PreGenesisHeader.scala
rename to ergo-core/src/main/scala/org/ergoplatform/modifiers/history/header/PreGenesisHeader.scala
index 6fbf74dc3e..7cebffbc5e 100644
--- a/src/main/scala/org/ergoplatform/modifiers/history/header/PreGenesisHeader.scala
+++ b/ergo-core/src/main/scala/org/ergoplatform/modifiers/history/header/PreGenesisHeader.scala
@@ -1,7 +1,7 @@
package org.ergoplatform.modifiers.history.header
-import org.ergoplatform.nodeView.history.ErgoHistory
-import scorex.core.idToBytes
+import org.ergoplatform.core.idToBytes
+import org.ergoplatform.nodeView.history.ErgoHistoryUtils.EmptyHistoryHeight
/**
* A fake header that is used to fill the chain that starts from the beginning
@@ -14,7 +14,7 @@ object PreGenesisHeader extends Header(
transactionsRoot = null,
timestamp = 0L,
nBits = 0L,
- height = ErgoHistory.EmptyHistoryHeight,
+ height = EmptyHistoryHeight,
extensionRoot = null,
powSolution = null,
votes = null,
diff --git a/src/main/scala/org/ergoplatform/modifiers/history/popow/NipopowAlgos.scala b/ergo-core/src/main/scala/org/ergoplatform/modifiers/history/popow/NipopowAlgos.scala
similarity index 66%
rename from src/main/scala/org/ergoplatform/modifiers/history/popow/NipopowAlgos.scala
rename to ergo-core/src/main/scala/org/ergoplatform/modifiers/history/popow/NipopowAlgos.scala
index 16ac25d95c..a441cfe9ff 100644
--- a/src/main/scala/org/ergoplatform/modifiers/history/popow/NipopowAlgos.scala
+++ b/ergo-core/src/main/scala/org/ergoplatform/modifiers/history/popow/NipopowAlgos.scala
@@ -1,17 +1,15 @@
package org.ergoplatform.modifiers.history.popow
import org.ergoplatform.mining.AutolykosPowScheme
-import org.ergoplatform.mining.difficulty.{DifficultyAdjustment, DifficultySerializer}
+import org.ergoplatform.mining.difficulty.DifficultySerializer
import org.ergoplatform.modifiers.history.extension.{Extension, ExtensionCandidate}
import org.ergoplatform.modifiers.history.extension.Extension.InterlinksVectorPrefix
import org.ergoplatform.modifiers.history.header.Header
-import org.ergoplatform.nodeView.history.ErgoHistoryReader
import org.ergoplatform.settings.{Algos, ChainSettings, Constants}
import scorex.crypto.authds.merkle.BatchMerkleProof
import scorex.crypto.hash.Digest32
import scorex.util.{ModifierId, bytesToId, idToBytes}
-import scala.collection.mutable
import scala.util.{Failure, Success, Try}
/**
@@ -31,9 +29,6 @@ class NipopowAlgos(val chainSettings: ChainSettings) {
import NipopowAlgos._
private def powScheme: AutolykosPowScheme = chainSettings.powScheme
-
- private val diffAdjustment = new DifficultyAdjustment(chainSettings)
-
/**
* Computes interlinks vector for a header next to `prevHeader`.
*/
@@ -111,7 +106,7 @@ class NipopowAlgos(val chainSettings: ChainSettings) {
}
loop(level = 0).map { case (lvl, size) =>
- math.pow(2, lvl) * size // 2^µ * |C↑µ|
+ math.pow(2, lvl.toDouble) * size // 2^µ * |C↑µ|
}.max.toInt
}
@@ -163,106 +158,6 @@ class NipopowAlgos(val chainSettings: ChainSettings) {
NipopowProof(this, m, k, prefix, suffixHead, suffixTail, params.continuous)
}
- /**
- * Computes NiPoPow proof for the chain stored in `histReader`'s database,
- * or a prefix of the chain which contains a specific header (if `headerIdOpt` is specified).
- * In the latter case, header will be the first header of the suffix of max length `k`
- * (`suffixHead` field of the result).
- */
- def prove(histReader: ErgoHistoryReader,
- headerIdOpt: Option[ModifierId] = None)(params: PoPowParams): Try[NipopowProof] = Try {
- type Height = Int
-
- val k = params.k
- val m = params.m
-
- require(params.k >= 1, s"$k < 1")
- require(histReader.headersHeight >= k + m, s"Can not prove chain of size < ${k + m}")
-
- def linksWithIndexes(header: PoPowHeader): Seq[(ModifierId, Int)] = header.interlinks.tail.reverse.zipWithIndex
-
- def previousHeaderIdAtLevel(level: Int, currentHeader: PoPowHeader): Option[ModifierId] = {
- linksWithIndexes(currentHeader).find(_._2 == level).map(_._1)
- }
-
- @scala.annotation.tailrec
- def collectLevel(prevHeaderId: ModifierId,
- level: Int,
- anchoringHeight: Height,
- acc: Seq[PoPowHeader] = Seq.empty): Seq[PoPowHeader] = {
- val prevHeader = histReader.popowHeader(prevHeaderId).get // to be caught in outer (prove's) Try
- if (prevHeader.height < anchoringHeight) {
- acc
- } else {
- val newAcc = prevHeader +: acc
- previousHeaderIdAtLevel(level, prevHeader) match {
- case Some(newPrevHeaderId) => collectLevel(newPrevHeaderId, level, anchoringHeight, newAcc)
- case None => newAcc
- }
- }
- }
-
- def provePrefix(initAnchoringHeight: Height,
- lastHeader: PoPowHeader): Seq[PoPowHeader] = {
-
- val collected = mutable.TreeMap[ModifierId, PoPowHeader]()
-
- val levels = linksWithIndexes(lastHeader)
- levels.foldRight(initAnchoringHeight) { case ((prevHeaderId, levelIdx), anchoringHeight) =>
- val levelHeaders = collectLevel(prevHeaderId, levelIdx, anchoringHeight)
- levelHeaders.foreach(ph => collected.update(ph.id, ph))
- if (m < levelHeaders.length) {
- levelHeaders(levelHeaders.length - m).height
- } else {
- anchoringHeight
- }
- }
- collected.values.toSeq
- }
-
- val (suffixHead, suffixTail) = headerIdOpt match {
- case Some(headerId) =>
- val suffixHead = histReader.popowHeader(headerId).get // to be caught in outer (prove's) Try
- val suffixTail = histReader.bestHeadersAfter(suffixHead.header, k - 1)
- suffixHead -> suffixTail
- case None =>
- val suffix = histReader.lastHeaders(k).headers
- histReader.popowHeader(suffix.head.id).get -> suffix.tail // .get to be caught in outer (prove's) Try
- }
-
- val storedHeights = mutable.Set[Height]() // cache to filter out duplicate headers
- val prefixBuilder = mutable.ArrayBuilder.make[PoPowHeader]()
-
- val genesisHeight = 1
- prefixBuilder += histReader.popowHeader(genesisHeight).get // to be caught in outer (prove's) Try
- storedHeights += genesisHeight
-
- if (params.continuous) {
- // put headers needed to check difficulty of new blocks after suffix into prefix
- val epochLength = chainSettings.eip37EpochLength.getOrElse(chainSettings.epochLength)
- diffAdjustment.heightsForNextRecalculation(suffixHead.height, epochLength).foreach { height =>
- // check that header in or after suffix is not included, otherwise, sorting by height would be broken
- if (height < suffixHead.height) {
- histReader.popowHeader(height).foreach { ph =>
- prefixBuilder += ph
- storedHeights += ph.height
- }
- }
- }
- }
-
- provePrefix(genesisHeight, suffixHead).foreach { ph =>
- if (!storedHeights.contains(ph.height)) {
- prefixBuilder += ph
- storedHeights += ph.height
- }
- }
-
- val prefix = prefixBuilder.result().sortBy(_.height)
-
- NipopowProof(this, m, k, prefix, suffixHead, suffixTail, params.continuous)
- }
-
}
diff --git a/src/main/scala/org/ergoplatform/modifiers/history/popow/NipopowProof.scala b/ergo-core/src/main/scala/org/ergoplatform/modifiers/history/popow/NipopowProof.scala
similarity index 96%
rename from src/main/scala/org/ergoplatform/modifiers/history/popow/NipopowProof.scala
rename to ergo-core/src/main/scala/org/ergoplatform/modifiers/history/popow/NipopowProof.scala
index 21102217d3..a94aec7626 100644
--- a/src/main/scala/org/ergoplatform/modifiers/history/popow/NipopowProof.scala
+++ b/ergo-core/src/main/scala/org/ergoplatform/modifiers/history/popow/NipopowProof.scala
@@ -3,7 +3,7 @@ package org.ergoplatform.modifiers.history.popow
import io.circe.{Decoder, Encoder}
import org.ergoplatform.mining.difficulty.DifficultyAdjustment
import org.ergoplatform.modifiers.history.header.{Header, HeaderSerializer}
-import scorex.core.serialization.ErgoSerializer
+import org.ergoplatform.serialization.ErgoSerializer
import scorex.util.serialization.{Reader, Writer}
import scorex.util.Extensions.LongOps
@@ -178,21 +178,21 @@ object NipopowProof {
class NipopowProofSerializer(poPowAlgos: NipopowAlgos) extends ErgoSerializer[NipopowProof] {
override def serialize(obj: NipopowProof, w: Writer): Unit = {
- w.putUInt(obj.m)
- w.putUInt(obj.k)
- w.putUInt(obj.prefix.size)
+ w.putUInt(obj.m.toLong)
+ w.putUInt(obj.k.toLong)
+ w.putUInt(obj.prefix.size.toLong)
obj.prefix.foreach { h =>
val hBytes = h.bytes
- w.putUInt(hBytes.length)
+ w.putUInt(hBytes.length.toLong)
w.putBytes(hBytes)
}
val suffixHeadBytes = obj.suffixHead.bytes
- w.putUInt(suffixHeadBytes.length)
+ w.putUInt(suffixHeadBytes.length.toLong)
w.putBytes(suffixHeadBytes)
- w.putUInt(obj.suffixTail.size)
+ w.putUInt(obj.suffixTail.size.toLong)
obj.suffixTail.foreach { h =>
val hBytes = h.bytes
- w.putUInt(hBytes.length)
+ w.putUInt(hBytes.length.toLong)
w.putBytes(hBytes)
}
w.put(if (obj.continuous) 1 else 0)
diff --git a/src/main/scala/org/ergoplatform/modifiers/history/popow/PoPowHeader.scala b/ergo-core/src/main/scala/org/ergoplatform/modifiers/history/popow/PoPowHeader.scala
similarity index 96%
rename from src/main/scala/org/ergoplatform/modifiers/history/popow/PoPowHeader.scala
rename to ergo-core/src/main/scala/org/ergoplatform/modifiers/history/popow/PoPowHeader.scala
index 95aad0a2c9..bdd82ded9c 100644
--- a/src/main/scala/org/ergoplatform/modifiers/history/popow/PoPowHeader.scala
+++ b/ergo-core/src/main/scala/org/ergoplatform/modifiers/history/popow/PoPowHeader.scala
@@ -3,12 +3,13 @@ package org.ergoplatform.modifiers.history.popow
import cats.Traverse
import cats.implicits.{catsStdInstancesForEither, catsStdInstancesForList}
import io.circe.{Decoder, Encoder, Json}
+import org.ergoplatform.core.BytesSerializable
import org.ergoplatform.modifiers.ErgoFullBlock
import org.ergoplatform.modifiers.history.extension.Extension.merkleTree
import org.ergoplatform.modifiers.history.header.{Header, HeaderSerializer}
import org.ergoplatform.settings.Algos
import org.ergoplatform.settings.Algos.HF
-import scorex.core.serialization.{BytesSerializable, ErgoSerializer}
+import org.ergoplatform.serialization.ErgoSerializer
import scorex.crypto.authds.Side
import scorex.crypto.authds.merkle.BatchMerkleProof
import scorex.crypto.authds.merkle.serialization.BatchMerkleProofSerializer
@@ -144,12 +145,12 @@ object PoPowHeaderSerializer extends ErgoSerializer[PoPowHeader] {
override def serialize(obj: PoPowHeader, w: Writer): Unit = {
val headerBytes = obj.header.bytes
- w.putUInt(headerBytes.length)
+ w.putUInt(headerBytes.length.toLong)
w.putBytes(headerBytes)
- w.putUInt(obj.interlinks.size)
+ w.putUInt(obj.interlinks.size.toLong)
obj.interlinks.foreach(x => w.putBytes(idToBytes(x)))
val proofBytes = merkleProofSerializer.serialize(obj.interlinksProof)
- w.putUInt(proofBytes.length)
+ w.putUInt(proofBytes.length.toLong)
w.putBytes(proofBytes)
}
diff --git a/src/main/scala/org/ergoplatform/modifiers/history/popow/PoPowParams.scala b/ergo-core/src/main/scala/org/ergoplatform/modifiers/history/popow/PoPowParams.scala
similarity index 100%
rename from src/main/scala/org/ergoplatform/modifiers/history/popow/PoPowParams.scala
rename to ergo-core/src/main/scala/org/ergoplatform/modifiers/history/popow/PoPowParams.scala
diff --git a/src/main/scala/org/ergoplatform/modifiers/mempool/ErgoTransaction.scala b/ergo-core/src/main/scala/org/ergoplatform/modifiers/mempool/ErgoTransaction.scala
similarity index 96%
rename from src/main/scala/org/ergoplatform/modifiers/mempool/ErgoTransaction.scala
rename to ergo-core/src/main/scala/org/ergoplatform/modifiers/mempool/ErgoTransaction.scala
index 55fa39b005..02cc3ed275 100644
--- a/src/main/scala/org/ergoplatform/modifiers/mempool/ErgoTransaction.scala
+++ b/ergo-core/src/main/scala/org/ergoplatform/modifiers/mempool/ErgoTransaction.scala
@@ -3,11 +3,12 @@ package org.ergoplatform.modifiers.mempool
import io.circe.syntax._
import org.ergoplatform.ErgoBox.BoxId
import org.ergoplatform.SigmaConstants.{MaxBoxSize, MaxPropositionBytes}
-import org.ergoplatform._
+import org.ergoplatform.{EphemerealNodeViewModifier, _}
import org.ergoplatform.http.api.ApiCodecs
import org.ergoplatform.mining.emission.EmissionRules
import org.ergoplatform.modifiers.history.header.Header
import org.ergoplatform.modifiers.mempool.ErgoTransaction.unresolvedIndices
+import org.ergoplatform.modifiers.transaction.Transaction
import org.ergoplatform.modifiers.{ErgoNodeViewModifier, NetworkObjectTypeId, TransactionTypeId}
import org.ergoplatform.nodeView.ErgoContext
import org.ergoplatform.nodeView.state.ErgoStateContext
@@ -15,17 +16,14 @@ import org.ergoplatform.sdk.utils.ArithUtils.{addExact, multiplyExact}
import org.ergoplatform.sdk.wallet.protocol.context.TransactionContext
import org.ergoplatform.settings.ValidationRules._
import org.ergoplatform.settings.{Algos, ErgoValidationSettings}
-import org.ergoplatform.utils.BoxUtils
+import org.ergoplatform.utils.{BoxUtils, ScorexEncoding}
import org.ergoplatform.wallet.boxes.ErgoBoxAssetExtractor
import org.ergoplatform.wallet.interpreter.ErgoInterpreter
import org.ergoplatform.wallet.protocol.context.InputContext
import org.ergoplatform.wallet.serialization.JsonCodecsWrapper
-import scorex.core.EphemerealNodeViewModifier
-import scorex.core.serialization.ErgoSerializer
-import scorex.core.transaction.Transaction
-import scorex.core.utils.ScorexEncoding
-import scorex.core.validation.ValidationResult.fromValidationState
-import scorex.core.validation.{InvalidModifier, ModifierValidator, ValidationResult, ValidationState}
+import org.ergoplatform.serialization.ErgoSerializer
+import org.ergoplatform.validation.ValidationResult.fromValidationState
+import org.ergoplatform.validation.{InvalidModifier, ModifierValidator, ValidationResult, ValidationState}
import scorex.db.ByteArrayUtils
import scorex.util.serialization.{Reader, Writer}
import scorex.util.{ModifierId, ScorexLogging, bytesToId}
@@ -118,7 +116,7 @@ case class ErgoTransaction(override val inputs: IndexedSeq[Input],
// Cost limit per block
val maxCost = stateContext.currentParameters.maxBlockCost.toLong
- val input = inputs(inputIndex)
+ val input = inputs(inputIndex.toInt)
// Just in case, should always be true if client implementation is correct.
if (!box.id.sameElements(input.boxId)) {
@@ -191,7 +189,7 @@ case class ErgoTransaction(override val inputs: IndexedSeq[Input],
val totalAssetsAccessCost =
ErgoBoxAssetExtractor.totalAssetsAccessCost(inAssetsNum, inAssets.size, outAssetsNum, outAssets.size, tokenAccessCost)
- val newCost = addExact(currentTxCost, totalAssetsAccessCost)
+ val newCost = addExact(currentTxCost, totalAssetsAccessCost.toLong)
validationBefore
// Check that transaction is not too costly considering all the assets
@@ -225,7 +223,7 @@ case class ErgoTransaction(override val inputs: IndexedSeq[Input],
stateContext: ErgoStateContext): Try[Unit] = {
val res: Try[Unit] = Try {
- lazy val reemissionSettings = stateContext.ergoSettings.chainSettings.reemission
+ lazy val reemissionSettings = stateContext.chainSettings.reemission
lazy val reemissionRules = reemissionSettings.reemissionRules
lazy val reemissionTokenId = ModifierId @@@ reemissionSettings.reemissionTokenId
@@ -234,7 +232,7 @@ case class ErgoTransaction(override val inputs: IndexedSeq[Input],
lazy val emissionNftId = ModifierId @@@ reemissionSettings.emissionNftId
lazy val emissionNftIdBytes = reemissionSettings.emissionNftIdBytes
- lazy val chainSettings = stateContext.ergoSettings.chainSettings
+ lazy val chainSettings = stateContext.chainSettings
lazy val emissionRules = chainSettings.emissionRules
lazy val height = stateContext.currentHeight
@@ -328,7 +326,6 @@ case class ErgoTransaction(override val inputs: IndexedSeq[Input],
require(sentToReemission == toBurn, "Burning condition violated")
}
} else {
- Success(())
}
}
@@ -367,10 +364,10 @@ case class ErgoTransaction(override val inputs: IndexedSeq[Input],
// Cost of transaction initialization: we should read and parse all inputs and data inputs,
// and also iterate through all outputs to check rules
val initialCost: Long = addExact(
- ErgoInterpreter.interpreterInitCost,
- multiplyExact(boxesToSpend.size, stateContext.currentParameters.inputCost),
- multiplyExact(dataBoxes.size, stateContext.currentParameters.dataInputCost),
- multiplyExact(outputCandidates.size, stateContext.currentParameters.outputCost),
+ 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),
)
// Cost limit per block
@@ -436,7 +433,7 @@ case class ErgoTransaction(override val inputs: IndexedSeq[Input],
val currentTxCost = validation.result.payload.get
verifyInput(validation, boxesToSpend, dataBoxes, box, idx.toShort, stateContext, currentTxCost)
}
- .validate(txReemission, !stateContext.ergoSettings.chainSettings.reemission.checkReemissionRules ||
+ .validate(txReemission, !stateContext.chainSettings.reemission.checkReemissionRules ||
verifyReemissionSpending(boxesToSpend, outputCandidates, stateContext).isSuccess, InvalidModifier(id, id, modifierTypeId))
}
diff --git a/src/main/scala/org/ergoplatform/modifiers/mempool/UnsignedErgoTransaction.scala b/ergo-core/src/main/scala/org/ergoplatform/modifiers/mempool/UnsignedErgoTransaction.scala
similarity index 100%
rename from src/main/scala/org/ergoplatform/modifiers/mempool/UnsignedErgoTransaction.scala
rename to ergo-core/src/main/scala/org/ergoplatform/modifiers/mempool/UnsignedErgoTransaction.scala
diff --git a/src/main/scala/org/ergoplatform/modifiers/state/StateChanges.scala b/ergo-core/src/main/scala/org/ergoplatform/modifiers/state/StateChanges.scala
similarity index 100%
rename from src/main/scala/org/ergoplatform/modifiers/state/StateChanges.scala
rename to ergo-core/src/main/scala/org/ergoplatform/modifiers/state/StateChanges.scala
diff --git a/src/main/scala/scorex/core/transaction/TooHighCostError.scala b/ergo-core/src/main/scala/org/ergoplatform/modifiers/transaction/TooHighCostError.scala
similarity index 87%
rename from src/main/scala/scorex/core/transaction/TooHighCostError.scala
rename to ergo-core/src/main/scala/org/ergoplatform/modifiers/transaction/TooHighCostError.scala
index e86d3d6189..26557d7171 100644
--- a/src/main/scala/scorex/core/transaction/TooHighCostError.scala
+++ b/ergo-core/src/main/scala/org/ergoplatform/modifiers/transaction/TooHighCostError.scala
@@ -1,4 +1,4 @@
-package scorex.core.transaction
+package org.ergoplatform.modifiers.transaction
import org.ergoplatform.modifiers.mempool.ErgoTransaction
diff --git a/src/main/scala/scorex/core/transaction/Transaction.scala b/ergo-core/src/main/scala/org/ergoplatform/modifiers/transaction/Transaction.scala
similarity index 82%
rename from src/main/scala/scorex/core/transaction/Transaction.scala
rename to ergo-core/src/main/scala/org/ergoplatform/modifiers/transaction/Transaction.scala
index c170967ad1..1c5263c656 100644
--- a/src/main/scala/scorex/core/transaction/Transaction.scala
+++ b/ergo-core/src/main/scala/org/ergoplatform/modifiers/transaction/Transaction.scala
@@ -1,7 +1,7 @@
-package scorex.core.transaction
+package org.ergoplatform.modifiers.transaction
+import org.ergoplatform.EphemerealNodeViewModifier
import org.ergoplatform.modifiers.{NetworkObjectTypeId, TransactionTypeId}
-import scorex.core.EphemerealNodeViewModifier
import scorex.crypto.hash.Blake2b256
import scorex.util.{ModifierId, bytesToId}
diff --git a/src/main/scala/scorex/core/network/Handshake.scala b/ergo-core/src/main/scala/org/ergoplatform/network/Handshake.scala
similarity index 93%
rename from src/main/scala/scorex/core/network/Handshake.scala
rename to ergo-core/src/main/scala/org/ergoplatform/network/Handshake.scala
index 7588d7671f..bd80167127 100644
--- a/src/main/scala/scorex/core/network/Handshake.scala
+++ b/ergo-core/src/main/scala/org/ergoplatform/network/Handshake.scala
@@ -1,4 +1,4 @@
-package scorex.core.network
+package org.ergoplatform.network
/**
* Network message to be send when nodes establish a new connection.
diff --git a/src/main/scala/org/ergoplatform/network/ModePeerFeature.scala b/ergo-core/src/main/scala/org/ergoplatform/network/ModePeerFeature.scala
similarity index 87%
rename from src/main/scala/org/ergoplatform/network/ModePeerFeature.scala
rename to ergo-core/src/main/scala/org/ergoplatform/network/ModePeerFeature.scala
index b5b47f2556..14052929b3 100644
--- a/src/main/scala/org/ergoplatform/network/ModePeerFeature.scala
+++ b/ergo-core/src/main/scala/org/ergoplatform/network/ModePeerFeature.scala
@@ -2,10 +2,8 @@ package org.ergoplatform.network
import io.circe.{Encoder, Json}
import org.ergoplatform.nodeView.state.StateType
-import org.ergoplatform.settings.{NodeConfigurationSettings, PeerFeatureDescriptors}
-import scorex.core.network.PeerFeature
-import scorex.core.network.PeerFeature.Id
-import scorex.core.serialization.ErgoSerializer
+import org.ergoplatform.settings.{ClientCapabilities, PeerFeatureDescriptors}
+import org.ergoplatform.serialization.ErgoSerializer
import scorex.util.serialization.{Reader, Writer}
/**
@@ -25,7 +23,7 @@ case class ModePeerFeature(stateType: StateType,
blocksToKeep: Int) extends PeerFeature {
override type M = ModePeerFeature
- override val featureId: Id = PeerFeatureDescriptors.ModeFeatureId
+ override val featureId: PeerFeature.Id = PeerFeatureDescriptors.ModeFeatureId
override def serializer: ErgoSerializer[ModePeerFeature] = ModeFeatureSerializer
@@ -64,22 +62,22 @@ object ModePeerFeature {
*/
val UTXOSetBootstrapped = -2
- def apply(nodeSettings: NodeConfigurationSettings): ModePeerFeature = {
- val popowBootstrapped = if (nodeSettings.nipopowSettings.nipopowBootstrap) {
+ def apply(clientCapabilities: ClientCapabilities): ModePeerFeature = {
+ val popowBootstrapped = if (clientCapabilities.nipopowSettings.nipopowBootstrap) {
Some(NiPoPoWDefaultFlag)
} else {
None
}
- val blocksKept = if (nodeSettings.utxoSettings.utxoBootstrap) {
+ val blocksKept = if (clientCapabilities.utxoSettings.utxoBootstrap) {
UTXOSetBootstrapped
} else {
- nodeSettings.blocksToKeep
+ clientCapabilities.blocksToKeep
}
new ModePeerFeature(
- nodeSettings.stateType,
- nodeSettings.verifyTransactions,
+ clientCapabilities.stateType,
+ clientCapabilities.verifyTransactions,
popowBootstrapped,
blocksKept
)
diff --git a/src/main/scala/scorex/core/network/PeerFeature.scala b/ergo-core/src/main/scala/org/ergoplatform/network/PeerFeature.scala
similarity index 82%
rename from src/main/scala/scorex/core/network/PeerFeature.scala
rename to ergo-core/src/main/scala/org/ergoplatform/network/PeerFeature.scala
index 0275053ca0..64a831130c 100644
--- a/src/main/scala/scorex/core/network/PeerFeature.scala
+++ b/ergo-core/src/main/scala/org/ergoplatform/network/PeerFeature.scala
@@ -1,6 +1,7 @@
-package scorex.core.network
+package org.ergoplatform.network
-import scorex.core.serialization.{BytesSerializable, ErgoSerializer}
+import org.ergoplatform.core.BytesSerializable
+import org.ergoplatform.serialization.ErgoSerializer
/**
* An abstract trait to describe peer capabilities.
diff --git a/src/main/scala/scorex/core/network/PeerSpec.scala b/ergo-core/src/main/scala/org/ergoplatform/network/PeerSpec.scala
similarity index 89%
rename from src/main/scala/scorex/core/network/PeerSpec.scala
rename to ergo-core/src/main/scala/org/ergoplatform/network/PeerSpec.scala
index 99faeb6c2d..1dcd755400 100644
--- a/src/main/scala/scorex/core/network/PeerSpec.scala
+++ b/ergo-core/src/main/scala/org/ergoplatform/network/PeerSpec.scala
@@ -1,15 +1,14 @@
-package scorex.core.network
+package org.ergoplatform.network
+import org.ergoplatform.network.peer.{LocalAddressPeerFeature, RestApiUrlPeerFeature}
import org.ergoplatform.settings.PeerFeatureDescriptors
-
-import java.net.{InetAddress, InetSocketAddress, URL}
-import scorex.core.app.{ApplicationVersionSerializer, Version}
-import scorex.core.network.peer.{LocalAddressPeerFeature, RestApiUrlPeerFeature}
-import scorex.core.serialization.ErgoSerializer
+import org.ergoplatform.serialization.ErgoSerializer
import scorex.util.Extensions._
import scorex.util.ScorexLogging
import scorex.util.serialization.{Reader, Writer}
+import java.net.{InetAddress, InetSocketAddress, URL}
+
/**
* Declared information about peer
*
@@ -58,14 +57,14 @@ object PeerSpecSerializer extends ErgoSerializer[PeerSpec] with ScorexLogging {
val addr = isa.getAddress.getAddress
writer.put((addr.size + 4).toByteExact)
writer.putBytes(addr)
- writer.putUInt(isa.getPort)
+ writer.putUInt(isa.getPort.toLong)
}
w.put(obj.features.size.toByteExact)
obj.features.foreach { f =>
w.put(f.featureId)
val fBytes = f.bytes
- w.putUShort(fBytes.length.toShortExact)
+ w.putUShort(fBytes.length.toShortExact.toInt)
w.putBytes(fBytes)
}
}
@@ -87,10 +86,11 @@ object PeerSpecSerializer extends ErgoSerializer[PeerSpec] with ScorexLogging {
}
val featuresCount = r.getByte()
- val feats = (1 to featuresCount).flatMap { _ =>
+ require(featuresCount >= 0)
+ val feats = (1 to featuresCount.toInt).flatMap { _ =>
val featId = r.getByte()
val featBytesCount = r.getUShort().toShortExact
- val featChunk = r.getChunk(featBytesCount)
+ val featChunk = r.getChunk(featBytesCount.toInt)
//we ignore a feature found in the PeersData if we do not know how to parse it or failed to do that
val serializer = PeerFeatureDescriptors.FeatureSerializers.get(featId)
if (serializer.isEmpty) {
diff --git a/src/main/scala/scorex/core/app/Version.scala b/ergo-core/src/main/scala/org/ergoplatform/network/Version.scala
similarity index 92%
rename from src/main/scala/scorex/core/app/Version.scala
rename to ergo-core/src/main/scala/org/ergoplatform/network/Version.scala
index 197683bdb6..a91ae9b797 100644
--- a/src/main/scala/scorex/core/app/Version.scala
+++ b/ergo-core/src/main/scala/org/ergoplatform/network/Version.scala
@@ -1,6 +1,7 @@
-package scorex.core.app
+package org.ergoplatform.network
-import scorex.core.serialization.{BytesSerializable, ErgoSerializer}
+import org.ergoplatform.core.BytesSerializable
+import org.ergoplatform.serialization.ErgoSerializer
import scorex.util.serialization._
/**
diff --git a/ergo-core/src/main/scala/org/ergoplatform/network/message/InvData.scala b/ergo-core/src/main/scala/org/ergoplatform/network/message/InvData.scala
new file mode 100644
index 0000000000..1cad7677e1
--- /dev/null
+++ b/ergo-core/src/main/scala/org/ergoplatform/network/message/InvData.scala
@@ -0,0 +1,12 @@
+package org.ergoplatform.network.message
+
+import org.ergoplatform.modifiers.NetworkObjectTypeId
+import scorex.util.ModifierId
+
+/**
+ * P2P network message which is encoding "inventory", transactions or block sections the node has
+ *
+ * @param typeId
+ * @param ids
+ */
+case class InvData(typeId: NetworkObjectTypeId.Value, ids: Seq[ModifierId])
diff --git a/ergo-core/src/main/scala/org/ergoplatform/network/message/MessageConstants.scala b/ergo-core/src/main/scala/org/ergoplatform/network/message/MessageConstants.scala
new file mode 100644
index 0000000000..432de21206
--- /dev/null
+++ b/ergo-core/src/main/scala/org/ergoplatform/network/message/MessageConstants.scala
@@ -0,0 +1,14 @@
+package org.ergoplatform.network.message
+
+/**
+ * Type aliases and constants related to P2P network messages formats
+ */
+object MessageConstants {
+ type MessageCode = Byte
+
+ val MagicLength: Int = 4
+
+ val ChecksumLength: Int = 4
+
+ val HeaderLength: Int = MagicLength + 5
+}
diff --git a/src/main/scala/scorex/core/network/message/MessageSpec.scala b/ergo-core/src/main/scala/org/ergoplatform/network/message/MessageSpec.scala
similarity index 75%
rename from src/main/scala/scorex/core/network/message/MessageSpec.scala
rename to ergo-core/src/main/scala/org/ergoplatform/network/message/MessageSpec.scala
index 8681364741..f622f484b1 100644
--- a/src/main/scala/scorex/core/network/message/MessageSpec.scala
+++ b/ergo-core/src/main/scala/org/ergoplatform/network/message/MessageSpec.scala
@@ -1,7 +1,8 @@
-package scorex.core.network.message
+package org.ergoplatform.network.message
-import scorex.core.app.Version
-import scorex.core.serialization.ErgoSerializer
+import org.ergoplatform.network.Version
+import org.ergoplatform.network.message.MessageConstants._
+import org.ergoplatform.serialization.ErgoSerializer
/**
* Base trait for app p2p messages in the network
@@ -17,7 +18,7 @@ trait MessageSpec[Content] extends ErgoSerializer[Content] {
* Code which identifies what message type is contained in the payload
*/
- val messageCode: Message.MessageCode
+ val messageCode: MessageCode
/**
* Name of this message type. For debug purposes only.
diff --git a/ergo-core/src/main/scala/org/ergoplatform/network/message/SyncInfoMessageSpec.scala b/ergo-core/src/main/scala/org/ergoplatform/network/message/SyncInfoMessageSpec.scala
new file mode 100644
index 0000000000..824365b62b
--- /dev/null
+++ b/ergo-core/src/main/scala/org/ergoplatform/network/message/SyncInfoMessageSpec.scala
@@ -0,0 +1,24 @@
+package org.ergoplatform.network.message
+
+import org.ergoplatform.consensus.SyncInfo
+import org.ergoplatform.network.message.MessageConstants.MessageCode
+import org.ergoplatform.serialization.ErgoSerializer
+import scorex.util.serialization.{Reader, Writer}
+
+/**
+ * The `SyncInfo` message requests an `Inv` message that provides modifier ids
+ * required be sender to synchronize his blockchain with the recipient.
+ * It allows a peer which has been disconnected or started for the first
+ * time to get the data it needs to request the blocks it hasn't seen.
+ *
+ * Payload of this message should be determined in underlying applications.
+ */
+class SyncInfoMessageSpec[SI <: SyncInfo](serializer: ErgoSerializer[SI]) extends MessageSpecV1[SI] {
+
+ override val messageCode: MessageCode = 65: Byte
+ override val messageName: String = "Sync"
+
+ override def serialize(data: SI, w: Writer): Unit = serializer.serialize(data, w)
+
+ override def parse(r: Reader): SI = serializer.parse(r)
+}
diff --git a/src/main/scala/scorex/core/network/peer/LocalAddressPeerFeature.scala b/ergo-core/src/main/scala/org/ergoplatform/network/peer/LocalAddressPeerFeature.scala
similarity index 78%
rename from src/main/scala/scorex/core/network/peer/LocalAddressPeerFeature.scala
rename to ergo-core/src/main/scala/org/ergoplatform/network/peer/LocalAddressPeerFeature.scala
index 6ef6a2f5f5..07439ec300 100644
--- a/src/main/scala/scorex/core/network/peer/LocalAddressPeerFeature.scala
+++ b/ergo-core/src/main/scala/org/ergoplatform/network/peer/LocalAddressPeerFeature.scala
@@ -1,10 +1,10 @@
-package scorex.core.network.peer
+package org.ergoplatform.network.peer
+
+import org.ergoplatform.network.PeerFeature
import java.net.{InetAddress, InetSocketAddress}
import org.ergoplatform.settings.PeerFeatureDescriptors
-import scorex.core.network.PeerFeature
-import scorex.core.network.PeerFeature.Id
-import scorex.core.serialization.ErgoSerializer
+import org.ergoplatform.serialization.ErgoSerializer
import scorex.util.serialization._
import scorex.util.Extensions._
@@ -14,7 +14,7 @@ import scorex.util.Extensions._
*/
case class LocalAddressPeerFeature(address: InetSocketAddress) extends PeerFeature {
override type M = LocalAddressPeerFeature
- override val featureId: Id = PeerFeatureDescriptors.LocalAddressPeerFeatureId
+ override val featureId: PeerFeature.Id = PeerFeatureDescriptors.LocalAddressPeerFeatureId
override def serializer: LocalAddressPeerFeatureSerializer.type = LocalAddressPeerFeatureSerializer
}
@@ -25,7 +25,7 @@ object LocalAddressPeerFeatureSerializer extends ErgoSerializer[LocalAddressPeer
override def serialize(obj: LocalAddressPeerFeature, w: Writer): Unit = {
w.putBytes(obj.address.getAddress.getAddress)
- w.putUInt(obj.address.getPort)
+ w.putUInt(obj.address.getPort.toLong)
}
override def parse(r: Reader): LocalAddressPeerFeature = {
diff --git a/src/main/scala/scorex/core/network/peer/RestApiUrlPeerFeature.scala b/ergo-core/src/main/scala/org/ergoplatform/network/peer/RestApiUrlPeerFeature.scala
similarity index 82%
rename from src/main/scala/scorex/core/network/peer/RestApiUrlPeerFeature.scala
rename to ergo-core/src/main/scala/org/ergoplatform/network/peer/RestApiUrlPeerFeature.scala
index 7f74b765e9..54d9a911d1 100644
--- a/src/main/scala/scorex/core/network/peer/RestApiUrlPeerFeature.scala
+++ b/ergo-core/src/main/scala/org/ergoplatform/network/peer/RestApiUrlPeerFeature.scala
@@ -1,11 +1,10 @@
-package scorex.core.network.peer
+package org.ergoplatform.network.peer
-import scorex.core.network.PeerFeature
-import scorex.core.network.PeerFeature.Id
-import scorex.core.serialization.ErgoSerializer
+import org.ergoplatform.network.PeerFeature
+import org.ergoplatform.serialization.ErgoSerializer
import scorex.util.serialization._
-import java.net.URL
+import java.net.URL
import org.ergoplatform.settings.PeerFeatureDescriptors
/**
@@ -14,7 +13,7 @@ import org.ergoplatform.settings.PeerFeatureDescriptors
*/
case class RestApiUrlPeerFeature(restApiUrl: URL) extends PeerFeature {
override type M = RestApiUrlPeerFeature
- override val featureId: Id = PeerFeatureDescriptors.RestApiUrlFeatureId
+ override val featureId: PeerFeature.Id = PeerFeatureDescriptors.RestApiUrlFeatureId
override def serializer: RestApiUrlPeerFeatureSerializer.type = RestApiUrlPeerFeatureSerializer
}
diff --git a/src/main/scala/scorex/core/network/peer/SessionIdPeerFeature.scala b/ergo-core/src/main/scala/org/ergoplatform/network/peer/SessionIdPeerFeature.scala
similarity index 74%
rename from src/main/scala/scorex/core/network/peer/SessionIdPeerFeature.scala
rename to ergo-core/src/main/scala/org/ergoplatform/network/peer/SessionIdPeerFeature.scala
index 386f999a5f..608947e946 100644
--- a/src/main/scala/scorex/core/network/peer/SessionIdPeerFeature.scala
+++ b/ergo-core/src/main/scala/org/ergoplatform/network/peer/SessionIdPeerFeature.scala
@@ -1,10 +1,9 @@
-package scorex.core.network.peer
+package org.ergoplatform.network.peer
+import org.ergoplatform.network.PeerFeature
import org.ergoplatform.settings.PeerFeatureDescriptors
-import scorex.core.network.PeerFeature
-import scorex.core.network.PeerFeature.Id
-import scorex.core.network.message.Message
-import scorex.core.serialization.ErgoSerializer
+import org.ergoplatform.network.message.MessageConstants
+import org.ergoplatform.serialization.ErgoSerializer
import scorex.util.serialization._
/**
@@ -17,7 +16,7 @@ case class SessionIdPeerFeature(networkMagic: Array[Byte],
sessionId: Long = scala.util.Random.nextLong()) extends PeerFeature {
override type M = SessionIdPeerFeature
- override val featureId: Id = PeerFeatureDescriptors.SessionIdPeerFeatureId
+ override val featureId: PeerFeature.Id = PeerFeatureDescriptors.SessionIdPeerFeatureId
override def serializer: SessionIdPeerFeatureSerializer.type = SessionIdPeerFeatureSerializer
@@ -32,7 +31,7 @@ object SessionIdPeerFeatureSerializer extends ErgoSerializer[SessionIdPeerFeatur
}
override def parse(r: Reader): SessionIdPeerFeature = {
- val networkMagic = r.getBytes(Message.MagicLength)
+ val networkMagic = r.getBytes(MessageConstants.MagicLength)
val sessionId = r.getLong()
SessionIdPeerFeature(networkMagic, sessionId)
}
diff --git a/src/main/scala/org/ergoplatform/nodeView/ErgoContext.scala b/ergo-core/src/main/scala/org/ergoplatform/nodeView/ErgoContext.scala
similarity index 97%
rename from src/main/scala/org/ergoplatform/nodeView/ErgoContext.scala
rename to ergo-core/src/main/scala/org/ergoplatform/nodeView/ErgoContext.scala
index 132501df4b..b197e82e59 100644
--- a/src/main/scala/org/ergoplatform/nodeView/ErgoContext.scala
+++ b/ergo-core/src/main/scala/org/ergoplatform/nodeView/ErgoContext.scala
@@ -20,7 +20,7 @@ class ErgoContext(val stateContext: ErgoStateContext,
transactionContext.dataBoxes,
transactionContext.boxesToSpend,
transactionContext.spendingTransaction,
- inputContext.selfIndex,
+ inputContext.selfIndex.toInt,
inputContext.extension,
stateContext.validationSettings.sigmaSettings,
costLimit,
diff --git a/ergo-core/src/main/scala/org/ergoplatform/nodeView/LocallyGeneratedModifier.scala b/ergo-core/src/main/scala/org/ergoplatform/nodeView/LocallyGeneratedModifier.scala
new file mode 100644
index 0000000000..712a185d35
--- /dev/null
+++ b/ergo-core/src/main/scala/org/ergoplatform/nodeView/LocallyGeneratedModifier.scala
@@ -0,0 +1,8 @@
+package org.ergoplatform.nodeView
+
+import org.ergoplatform.modifiers.BlockSection
+
+/**
+ * Wrapper for locally generated block section
+ */
+case class LocallyGeneratedModifier(pmod: BlockSection)
diff --git a/ergo-core/src/main/scala/org/ergoplatform/nodeView/history/ErgoHistoryUtils.scala b/ergo-core/src/main/scala/org/ergoplatform/nodeView/history/ErgoHistoryUtils.scala
new file mode 100644
index 0000000000..3f1f3801fd
--- /dev/null
+++ b/ergo-core/src/main/scala/org/ergoplatform/nodeView/history/ErgoHistoryUtils.scala
@@ -0,0 +1,28 @@
+package org.ergoplatform.nodeView.history
+
+import org.ergoplatform.ErgoLikeContext
+import org.ergoplatform.modifiers.history.header.Header
+
+/**
+ * Repository for types, constants and functions related to blockchain database (ErgoHistory)
+ */
+object ErgoHistoryUtils {
+ /**
+ * Type for time, represents machine-specific timestamp of a transaction
+ * or block section, as milliseconds passed since beginning of UNIX
+ * epoch on the machine
+ */
+ type Time = Long
+
+ type Height = ErgoLikeContext.Height // Int
+ type Score = BigInt
+ type Difficulty = BigInt
+ type NBits = Long
+
+ val CharsetName = "UTF-8"
+
+ val EmptyHistoryHeight: Int = 0
+ val GenesisHeight: Int = EmptyHistoryHeight + 1 // first block has height == 1
+
+ def heightOf(headerOpt: Option[Header]): Int = headerOpt.map(_.height).getOrElse(EmptyHistoryHeight)
+}
diff --git a/src/main/scala/org/ergoplatform/nodeView/history/ErgoSyncInfo.scala b/ergo-core/src/main/scala/org/ergoplatform/nodeView/history/ErgoSyncInfo.scala
similarity index 94%
rename from src/main/scala/org/ergoplatform/nodeView/history/ErgoSyncInfo.scala
rename to ergo-core/src/main/scala/org/ergoplatform/nodeView/history/ErgoSyncInfo.scala
index e67a808b4d..bb5f6ee3ab 100644
--- a/src/main/scala/org/ergoplatform/nodeView/history/ErgoSyncInfo.scala
+++ b/ergo-core/src/main/scala/org/ergoplatform/nodeView/history/ErgoSyncInfo.scala
@@ -1,10 +1,10 @@
package org.ergoplatform.nodeView.history
+import org.ergoplatform.NodeViewModifier
+import org.ergoplatform.consensus.SyncInfo
import org.ergoplatform.modifiers.history.header.{Header, HeaderSerializer}
-import scorex.core.NodeViewModifier
-import scorex.core.consensus.SyncInfo
-import scorex.core.network.message.SyncInfoMessageSpec
-import scorex.core.serialization.ErgoSerializer
+import org.ergoplatform.network.message.SyncInfoMessageSpec
+import org.ergoplatform.serialization.ErgoSerializer
import scorex.util.serialization.{Reader, Writer}
import scorex.util.{ModifierId, ScorexLogging, bytesToId, idToBytes}
diff --git a/src/main/scala/org/ergoplatform/nodeView/history/storage/modifierprocessors/ExtensionValidator.scala b/ergo-core/src/main/scala/org/ergoplatform/nodeView/history/storage/modifierprocessors/ExtensionValidator.scala
similarity index 95%
rename from src/main/scala/org/ergoplatform/nodeView/history/storage/modifierprocessors/ExtensionValidator.scala
rename to ergo-core/src/main/scala/org/ergoplatform/nodeView/history/storage/modifierprocessors/ExtensionValidator.scala
index 4f6dd6b642..cfc6905d86 100644
--- a/src/main/scala/org/ergoplatform/nodeView/history/storage/modifierprocessors/ExtensionValidator.scala
+++ b/ergo-core/src/main/scala/org/ergoplatform/nodeView/history/storage/modifierprocessors/ExtensionValidator.scala
@@ -4,8 +4,8 @@ import org.ergoplatform.modifiers.history.extension.{Extension, ExtensionCandida
import org.ergoplatform.modifiers.history.header.Header
import org.ergoplatform.modifiers.history.popow.NipopowAlgos
import org.ergoplatform.settings.ValidationRules._
-import scorex.core.utils.ScorexEncoding
-import scorex.core.validation.{InvalidModifier, ValidationState}
+import org.ergoplatform.utils.ScorexEncoding
+import org.ergoplatform.validation.{InvalidModifier, ValidationState}
import scorex.util.bytesToId
/**
diff --git a/src/main/scala/org/ergoplatform/nodeView/mempool/TransactionMembershipProof.scala b/ergo-core/src/main/scala/org/ergoplatform/nodeView/mempool/TransactionMembershipProof.scala
similarity index 100%
rename from src/main/scala/org/ergoplatform/nodeView/mempool/TransactionMembershipProof.scala
rename to ergo-core/src/main/scala/org/ergoplatform/nodeView/mempool/TransactionMembershipProof.scala
diff --git a/src/main/scala/org/ergoplatform/nodeView/state/ErgoStateContext.scala b/ergo-core/src/main/scala/org/ergoplatform/nodeView/state/ErgoStateContext.scala
similarity index 92%
rename from src/main/scala/org/ergoplatform/nodeView/state/ErgoStateContext.scala
rename to ergo-core/src/main/scala/org/ergoplatform/nodeView/state/ErgoStateContext.scala
index ce478458ad..fcd6b6f680 100644
--- a/src/main/scala/org/ergoplatform/nodeView/state/ErgoStateContext.scala
+++ b/ergo-core/src/main/scala/org/ergoplatform/nodeView/state/ErgoStateContext.scala
@@ -1,19 +1,20 @@
package org.ergoplatform.nodeView.state
import org.ergoplatform.ErgoLikeContext.Height
+import org.ergoplatform.core.BytesSerializable
import org.ergoplatform.modifiers.ErgoFullBlock
import org.ergoplatform.modifiers.history._
import org.ergoplatform.modifiers.history.extension.{Extension, ExtensionSerializer}
import org.ergoplatform.modifiers.history.header.{Header, HeaderSerializer}
import org.ergoplatform.modifiers.history.popow.NipopowAlgos
-import org.ergoplatform.nodeView.history.ErgoHistory
+import org.ergoplatform.nodeView.history.ErgoHistoryUtils
import org.ergoplatform.nodeView.history.storage.modifierprocessors.ExtensionValidator
import org.ergoplatform.sdk.wallet.protocol.context.BlockchainStateContext
import org.ergoplatform.settings.ValidationRules._
import org.ergoplatform.settings._
-import scorex.core.serialization.{BytesSerializable, ErgoSerializer}
-import scorex.core.utils.ScorexEncoding
-import scorex.core.validation.{InvalidModifier, ModifierValidator, ValidationState}
+import org.ergoplatform.utils.ScorexEncoding
+import org.ergoplatform.serialization.ErgoSerializer
+import org.ergoplatform.validation.{InvalidModifier, ModifierValidator, ValidationState}
import scorex.crypto.authds.ADDigest
import scorex.util.ScorexLogging
import scorex.util.serialization.{Reader, Writer}
@@ -34,9 +35,9 @@ case class UpcomingStateContext(override val lastHeaders: Seq[Header],
override val genesisStateDigest: ADDigest,
override val currentParameters: Parameters,
override val validationSettings: ErgoValidationSettings,
- override val votingData: VotingData)(implicit ergoSettings: ErgoSettings)
+ override val votingData: VotingData)(implicit chainSettings: ChainSettings)
extends ErgoStateContext(lastHeaders, lastExtensionOpt, genesisStateDigest, currentParameters,
- validationSettings, votingData)(ergoSettings) {
+ validationSettings, votingData)(chainSettings) {
override def sigmaPreHeader: sigma.PreHeader = PreHeader.toSigma(predictedHeader)
@@ -65,7 +66,7 @@ class ErgoStateContext(val lastHeaders: Seq[Header],
val currentParameters: Parameters,
val validationSettings: ErgoValidationSettings,
val votingData: VotingData)
- (implicit val ergoSettings: ErgoSettings)
+ (implicit val chainSettings: ChainSettings)
extends BlockchainStateContext
with BytesSerializable
with ScorexEncoding
@@ -73,8 +74,8 @@ class ErgoStateContext(val lastHeaders: Seq[Header],
override type M = ErgoStateContext
- private val votingSettings = ergoSettings.chainSettings.voting
- private val popowAlgos = new NipopowAlgos(ergoSettings.chainSettings)
+ private val votingSettings = chainSettings.voting
+ private val popowAlgos = new NipopowAlgos(chainSettings)
override def sigmaPreHeader: sigma.PreHeader =
PreHeader.toSigma(lastHeaders.headOption.getOrElse(PreHeader.fake))
@@ -107,7 +108,7 @@ class ErgoStateContext(val lastHeaders: Seq[Header],
def lastHeaderOpt: Option[Header] = lastHeaders.headOption
- override def serializer: ErgoSerializer[M] = ErgoStateContextSerializer(ergoSettings)
+ override def serializer: ErgoSerializer[M] = ErgoStateContextSerializer(chainSettings)
/**
* @return state context corresponding to a block after last known one with fields provided
@@ -120,7 +121,7 @@ class ErgoStateContext(val lastHeaders: Seq[Header],
version: Byte): UpcomingStateContext = {
val upcomingHeader = PreHeader(lastHeaderOpt, version, minerPk, timestamp, nBits, votes)
val forkVote = votes.contains(Parameters.SoftFork)
- val height = ErgoHistory.heightOf(lastHeaderOpt) + 1
+ val height = ErgoHistoryUtils.heightOf(lastHeaderOpt) + 1
val (calculatedParams, updated) = currentParameters.update(height, forkVote, votingData.epochVotes, proposedUpdate, votingSettings)
val calculatedValidationSettings = validationSettings.updated(updated)
UpcomingStateContext(lastHeaders, lastExtensionOpt, upcomingHeader, genesisStateDigest, calculatedParams,
@@ -134,12 +135,12 @@ class ErgoStateContext(val lastHeaders: Seq[Header],
def simplifiedUpcoming(): UpcomingStateContext = {
val minerPk = org.ergoplatform.mining.group.generator
val version = lastHeaderOpt.map(_.version).getOrElse(Header.InitialVersion)
- val nBits = lastHeaderOpt.map(_.nBits).getOrElse(ergoSettings.chainSettings.initialNBits)
+ val nBits = lastHeaderOpt.map(_.nBits).getOrElse(chainSettings.initialNBits)
val timestamp = lastHeaderOpt.map(_.timestamp + 1).getOrElse(System.currentTimeMillis())
val votes = Array.emptyByteArray
val proposedUpdate = ErgoValidationSettingsUpdate.empty
val upcomingHeader = PreHeader(lastHeaderOpt, version, minerPk, timestamp, nBits, votes)
- val height = ErgoHistory.heightOf(lastHeaderOpt) + 1
+ val height = ErgoHistoryUtils.heightOf(lastHeaderOpt) + 1
val (calculatedParams, updated) = currentParameters.update(height, forkVote = false, votingData.epochVotes, proposedUpdate, votingSettings)
val calculatedValidationSettings = validationSettings.updated(updated)
UpcomingStateContext(lastHeaders, lastExtensionOpt, upcomingHeader, genesisStateDigest, calculatedParams,
@@ -227,14 +228,14 @@ class ErgoStateContext(val lastHeaders: Seq[Header],
val proposedVotes = votes.map(_ -> 1)
val newVoting = VotingData(proposedVotes)
new ErgoStateContext(newHeaders, extensionOpt, genesisStateDigest, params,
- extractedValidationSettings, newVoting)(ergoSettings)
+ extractedValidationSettings, newVoting)(chainSettings)
}
case _ =>
val newVotes = votes
val newVotingResults = newVotes.foldLeft(votingData) { case (v, id) => v.update(id) }
state.result.toTry.map { _ =>
new ErgoStateContext(newHeaders, extensionOpt, genesisStateDigest, currentParameters, validationSettings,
- newVotingResults)(ergoSettings)
+ newVotingResults)(chainSettings)
}
}
}.flatten
@@ -332,16 +333,16 @@ object ErgoStateContext {
*/
val eip27Vote: Byte = 8
- def empty(settings: ErgoSettings, parameters: Parameters): ErgoStateContext = {
- empty(settings.chainSettings.genesisStateDigest, settings, parameters)
+ def empty(chainSettings: ChainSettings, parameters: Parameters): ErgoStateContext = {
+ empty(chainSettings.genesisStateDigest, chainSettings, parameters)
}
/**
* Initialize empty state context
*/
- def empty(genesisStateDigest: ADDigest, settings: ErgoSettings, parameters: Parameters): ErgoStateContext = {
+ def empty(genesisStateDigest: ADDigest, chainSettings: ChainSettings, parameters: Parameters): ErgoStateContext = {
new ErgoStateContext(Seq.empty, None, genesisStateDigest, parameters, ErgoValidationSettings.initial,
- VotingData.empty)(settings)
+ VotingData.empty)(chainSettings)
}
/**
@@ -352,14 +353,14 @@ object ErgoStateContext {
def recover(genesisStateDigest: ADDigest,
extension: Extension,
lastHeaders: Seq[Header])
- (settings: ErgoSettings): Try[ErgoStateContext] = {
- val vs = settings.chainSettings.voting
+ (chainSettings: ChainSettings): Try[ErgoStateContext] = {
+ val vs = chainSettings.voting
if (lastHeaders.lastOption.exists(_.height % vs.votingLength == 0)) {
val currentHeader = lastHeaders.last
Parameters.parseExtension(currentHeader.height, extension).flatMap { params =>
ErgoValidationSettings.parseExtension(extension).map { validationSettings =>
new ErgoStateContext(lastHeaders.reverse, Some(extension), genesisStateDigest, params,
- validationSettings, VotingData.empty)(settings)
+ validationSettings, VotingData.empty)(chainSettings)
}
}
} else {
@@ -369,7 +370,7 @@ object ErgoStateContext {
}
-case class ErgoStateContextSerializer(ergoSettings: ErgoSettings) extends ErgoSerializer[ErgoStateContext] {
+case class ErgoStateContextSerializer(chainSettings: ChainSettings) extends ErgoSerializer[ErgoStateContext] {
private val Eip27SupportValue = 100 // see comment in serialize()
@@ -413,7 +414,7 @@ case class ErgoStateContextSerializer(ergoSettings: ErgoSettings) extends ErgoSe
}
new ErgoStateContext(lastHeaders, lastExtensionOpt, genesisDigest, params, validationSettings,
- votingData)(ergoSettings)
+ votingData)(chainSettings)
}
}
diff --git a/src/main/scala/org/ergoplatform/nodeView/state/StateType.scala b/ergo-core/src/main/scala/org/ergoplatform/nodeView/state/StateType.scala
similarity index 73%
rename from src/main/scala/org/ergoplatform/nodeView/state/StateType.scala
rename to ergo-core/src/main/scala/org/ergoplatform/nodeView/state/StateType.scala
index 8aa5ea8152..ca827e0f18 100644
--- a/src/main/scala/org/ergoplatform/nodeView/state/StateType.scala
+++ b/ergo-core/src/main/scala/org/ergoplatform/nodeView/state/StateType.scala
@@ -32,6 +32,8 @@ object StateType {
override val requireProofs: Boolean = true
}
+ val values: Seq[StateType] = Seq(Utxo, Digest)
+
def fromCode(code: StateTypeCode): StateType = if (code == Utxo.stateTypeCode) {
Utxo
} else if (code == Digest.stateTypeCode) {
@@ -40,17 +42,4 @@ object StateType {
throw new Exception(s"Unkown state type code $code")
}
- type UtxoType = Utxo.type
- type DigestType = Digest.type
-
- val values: Seq[StateType] = Seq(Utxo, Digest)
-
- /** This class allows to check the correspondence between concrete instances of [[StateType]] and [[ErgoState]]
- */
- sealed trait Evidence[ST <: StateType, S <: ErgoState[S]]
-
- implicit final object UtxoEvidence extends Evidence[UtxoType, UtxoState]
-
- implicit final object DigestEvidence extends Evidence[DigestType, DigestState]
-
}
diff --git a/src/main/scala/org/ergoplatform/nodeView/state/VotingData.scala b/ergo-core/src/main/scala/org/ergoplatform/nodeView/state/VotingData.scala
similarity index 93%
rename from src/main/scala/org/ergoplatform/nodeView/state/VotingData.scala
rename to ergo-core/src/main/scala/org/ergoplatform/nodeView/state/VotingData.scala
index 3b55bee3ec..d660db7f20 100644
--- a/src/main/scala/org/ergoplatform/nodeView/state/VotingData.scala
+++ b/ergo-core/src/main/scala/org/ergoplatform/nodeView/state/VotingData.scala
@@ -1,6 +1,6 @@
package org.ergoplatform.nodeView.state
-import scorex.core.serialization.ErgoSerializer
+import org.ergoplatform.serialization.ErgoSerializer
import scorex.util.serialization.{Reader, Writer}
import scorex.util.Extensions._
@@ -31,7 +31,7 @@ object VotingDataSerializer extends ErgoSerializer[VotingData] {
w.putUShort(obj.epochVotes.length)
obj.epochVotes.foreach { case (id, cnt) =>
w.put(id)
- w.putUInt(cnt)
+ w.putUInt(cnt.toLong)
}
}
diff --git a/ergo-core/src/main/scala/org/ergoplatform/reemission/ReemissionRules.scala b/ergo-core/src/main/scala/org/ergoplatform/reemission/ReemissionRules.scala
new file mode 100644
index 0000000000..895434220e
--- /dev/null
+++ b/ergo-core/src/main/scala/org/ergoplatform/reemission/ReemissionRules.scala
@@ -0,0 +1,40 @@
+package org.ergoplatform.reemission
+
+import org.ergoplatform.ErgoLikeContext.Height
+import org.ergoplatform.contracts.ReemissionContracts
+import org.ergoplatform.mining.emission.EmissionRules
+import org.ergoplatform.settings.ReemissionSettings
+import sigma.Coll
+
+
+/**
+ * Contains re-emission contracts (defined in `ReemissionContracts`) and helper functions
+ * for re-emission.
+ */
+class ReemissionRules(reemissionSettings: ReemissionSettings) extends ReemissionContracts {
+
+ override val reemissionNftIdBytes: Coll[Byte] = reemissionSettings.reemissionNftIdBytes
+ override val reemissionStartHeight: Height = reemissionSettings.reemissionStartHeight
+
+ /**
+ * How many ERG taken from emission to re-emission initially
+ */
+ val basicChargeAmount = 12 // in ERG
+
+ /**
+ * @return how many re-emission tokens can be unlocked at given height
+ */
+ def reemissionForHeight(height: Height,
+ emissionRules: EmissionRules): Long = {
+ val emission = emissionRules.emissionAtHeight(height.toLong)
+ if (height >= reemissionSettings.activationHeight &&
+ emission >= (basicChargeAmount + 3) * EmissionRules.CoinsInOneErgo) {
+ basicChargeAmount * EmissionRules.CoinsInOneErgo
+ } else if (height >= reemissionSettings.activationHeight &&
+ emission > 3 * EmissionRules.CoinsInOneErgo) {
+ emission - 3 * EmissionRules.CoinsInOneErgo
+ } else {
+ 0L
+ }
+ }
+}
diff --git a/src/main/scala/org/ergoplatform/settings/Algos.scala b/ergo-core/src/main/scala/org/ergoplatform/settings/Algos.scala
similarity index 90%
rename from src/main/scala/org/ergoplatform/settings/Algos.scala
rename to ergo-core/src/main/scala/org/ergoplatform/settings/Algos.scala
index 5239f9d7d0..ac80a7001d 100644
--- a/src/main/scala/org/ergoplatform/settings/Algos.scala
+++ b/ergo-core/src/main/scala/org/ergoplatform/settings/Algos.scala
@@ -1,18 +1,20 @@
package org.ergoplatform.settings
+import org.ergoplatform.utils
+import org.ergoplatform.utils.ScorexEncoder
import scorex.crypto.authds.LeafData
import scorex.crypto.authds.merkle.MerkleTree
import scorex.crypto.hash.Digest32
import scorex.util._
-object Algos extends ErgoAlgos with scorex.core.utils.ScorexEncoding {
+object Algos extends ErgoAlgos with utils.ScorexEncoding {
// ErgoAlgos in sigmastate extends scorex.util.ScorexEncoding where encoder is BytesEncoder
// but here we use scorex.core.utils.ScorexEncoding where encoder is ScorexEncoder
// After ScorexEncoder is moved (there is even a todo for that) from scorex.core to scorex.util
// we can fix this ugliness.
- override implicit val encoder: scorex.core.utils.ScorexEncoder = scorex.core.utils.ScorexEncoder.default
+ override implicit val encoder: ScorexEncoder = utils.ScorexEncoder.default
lazy val emptyMerkleTreeRoot: Digest32 = Algos.hash(LeafData @@ Array[Byte]())
diff --git a/src/main/scala/org/ergoplatform/settings/ChainSettings.scala b/ergo-core/src/main/scala/org/ergoplatform/settings/ChainSettings.scala
similarity index 100%
rename from src/main/scala/org/ergoplatform/settings/ChainSettings.scala
rename to ergo-core/src/main/scala/org/ergoplatform/settings/ChainSettings.scala
diff --git a/ergo-core/src/main/scala/org/ergoplatform/settings/ClientCapabilities.scala b/ergo-core/src/main/scala/org/ergoplatform/settings/ClientCapabilities.scala
new file mode 100644
index 0000000000..328763da98
--- /dev/null
+++ b/ergo-core/src/main/scala/org/ergoplatform/settings/ClientCapabilities.scala
@@ -0,0 +1,14 @@
+package org.ergoplatform.settings
+
+import org.ergoplatform.nodeView.state.StateType
+
+/**
+ * Features client may have enabled, they are reported to other peers
+ */
+trait ClientCapabilities {
+ val stateType: StateType
+ val verifyTransactions: Boolean
+ val blocksToKeep: Int
+ val utxoSettings: UtxoSettings
+ val nipopowSettings: NipopowSettings
+}
\ No newline at end of file
diff --git a/src/main/scala/org/ergoplatform/settings/Constants.scala b/ergo-core/src/main/scala/org/ergoplatform/settings/Constants.scala
similarity index 64%
rename from src/main/scala/org/ergoplatform/settings/Constants.scala
rename to ergo-core/src/main/scala/org/ergoplatform/settings/Constants.scala
index ab9a0e88ba..02090c6afd 100644
--- a/src/main/scala/org/ergoplatform/settings/Constants.scala
+++ b/ergo-core/src/main/scala/org/ergoplatform/settings/Constants.scala
@@ -1,19 +1,11 @@
package org.ergoplatform.settings
import org.ergoplatform.mining.difficulty.DifficultySerializer
-import org.ergoplatform.modifiers.NetworkObjectTypeId
-import org.ergoplatform.modifiers.history._
-import org.ergoplatform.modifiers.history.extension.{Extension, ExtensionSerializer}
-import org.ergoplatform.modifiers.history.header.{Header, HeaderSerializer}
-import org.ergoplatform.modifiers.mempool.{ErgoTransaction, ErgoTransactionSerializer}
-import org.ergoplatform.nodeView.history.ErgoHistory.Difficulty
-import scorex.core.NodeViewModifier
-import scorex.core.serialization.ErgoSerializer
+import org.ergoplatform.nodeView.history.ErgoHistoryUtils.Difficulty
import scorex.crypto.authds.avltree.batch.AvlTreeParameters
import sigmastate.Values
import sigmastate.Values.ErgoTree
-
object Constants {
/**
* Length of hash function output used around the Ergo code
@@ -48,18 +40,6 @@ object Constants {
// Number of last block headers available is scripts from ErgoStateContext
val LastHeadersInContext = 10
- /**
- * Serializers for block sections and transactions
- *
- * // todo: move to NodeViewSynchronizer, used only there
- */
- val modifierSerializers: Map[NetworkObjectTypeId.Value, ErgoSerializer[_ <: NodeViewModifier]] =
- Map(Header.modifierTypeId -> HeaderSerializer,
- Extension.modifierTypeId -> ExtensionSerializer,
- BlockTransactions.modifierTypeId -> BlockTransactionsSerializer,
- ADProofs.modifierTypeId -> ADProofsSerializer,
- ErgoTransaction.modifierTypeId -> ErgoTransactionSerializer)
-
val SoftForkEpochs = 32 //about 45.5 days
def TrueLeaf: ErgoTree = Values.TrueLeaf.toSigmaProp
diff --git a/src/main/scala/org/ergoplatform/settings/ErgoValidationSettings.scala b/ergo-core/src/main/scala/org/ergoplatform/settings/ErgoValidationSettings.scala
similarity index 94%
rename from src/main/scala/org/ergoplatform/settings/ErgoValidationSettings.scala
rename to ergo-core/src/main/scala/org/ergoplatform/settings/ErgoValidationSettings.scala
index 97bfb0d3f1..3961e5f159 100644
--- a/src/main/scala/org/ergoplatform/settings/ErgoValidationSettings.scala
+++ b/ergo-core/src/main/scala/org/ergoplatform/settings/ErgoValidationSettings.scala
@@ -1,10 +1,12 @@
package org.ergoplatform.settings
+import org.ergoplatform.core.BytesSerializable
import org.ergoplatform.http.api.ApiCodecs
import org.ergoplatform.modifiers.history.extension.{Extension, ExtensionCandidate}
+import org.ergoplatform.utils
import org.ergoplatform.validation.SigmaValidationSettings
-import scorex.core.serialization.{BytesSerializable, ErgoSerializer}
-import scorex.core.validation.{InvalidModifier, ModifierValidator, ValidationResult, ValidationSettings}
+import org.ergoplatform.serialization.ErgoSerializer
+import org.ergoplatform.validation.{InvalidModifier, ModifierValidator, ValidationResult, ValidationSettings}
import scorex.util.serialization.{Reader, Writer}
import scala.util.Try
@@ -113,7 +115,7 @@ object ErgoValidationSettings {
if (values.isEmpty) {
ErgoValidationSettings.initial
} else {
- val bytes = scorex.core.utils.concatBytes(values)
+ val bytes = utils.concatBytes(values)
ErgoValidationSettingsSerializer.parseBytes(bytes)
}
}
diff --git a/src/main/scala/org/ergoplatform/settings/ErgoValidationSettingsUpdate.scala b/ergo-core/src/main/scala/org/ergoplatform/settings/ErgoValidationSettingsUpdate.scala
similarity index 92%
rename from src/main/scala/org/ergoplatform/settings/ErgoValidationSettingsUpdate.scala
rename to ergo-core/src/main/scala/org/ergoplatform/settings/ErgoValidationSettingsUpdate.scala
index 9dccb5d9fa..a98066a696 100644
--- a/src/main/scala/org/ergoplatform/settings/ErgoValidationSettingsUpdate.scala
+++ b/ergo-core/src/main/scala/org/ergoplatform/settings/ErgoValidationSettingsUpdate.scala
@@ -1,7 +1,7 @@
package org.ergoplatform.settings
import org.ergoplatform.validation.RuleStatusSerializer
-import scorex.core.serialization.ErgoSerializer
+import org.ergoplatform.serialization.ErgoSerializer
import scorex.util.serialization.{Reader, Writer}
import sigmastate.serialization.ConstantStore
import sigmastate.utils.{SigmaByteReader, SigmaByteWriter}
@@ -27,12 +27,12 @@ object ErgoValidationSettingsUpdateSerializer extends ErgoSerializer[ErgoValidat
override def serialize(obj: ErgoValidationSettingsUpdate, w: Writer): Unit = {
val sigmaWriter = new SigmaByteWriter(w, None)
- w.putUInt(obj.rulesToDisable.length)
+ w.putUInt(obj.rulesToDisable.length.toLong)
obj.rulesToDisable.foreach { r =>
- w.putUShort(r)
+ w.putUShort(r.toInt)
}
- w.putUInt(obj.statusUpdates.length)
+ w.putUInt(obj.statusUpdates.length.toLong)
obj.statusUpdates.foreach { r =>
w.putUShort(r._1 - FirstRule)
RuleStatusSerializer.serialize(r._2, sigmaWriter)
diff --git a/ergo-core/src/main/scala/org/ergoplatform/settings/NipopowSettings.scala b/ergo-core/src/main/scala/org/ergoplatform/settings/NipopowSettings.scala
new file mode 100644
index 0000000000..fdcf5acd98
--- /dev/null
+++ b/ergo-core/src/main/scala/org/ergoplatform/settings/NipopowSettings.scala
@@ -0,0 +1,21 @@
+package org.ergoplatform.settings
+
+import net.ceedubs.ficus.Ficus._
+import net.ceedubs.ficus.readers.ValueReader
+
+/**
+ * Settings related to headers-chain bootstrapping with NiPoPoWs. See ergo.node.nipopow section for settings description.
+ */
+case class NipopowSettings(nipopowBootstrap: Boolean, p2pNipopows: Int)
+
+/**
+ * Custom settings reader for `NipopowSettings`
+ */
+trait NipopowSettingsReader {
+ implicit val nipopowSettingsReader: ValueReader[NipopowSettings] = { (cfg, path) =>
+ NipopowSettings(
+ cfg.as[Boolean](s"$path.nipopowBootstrap"),
+ cfg.as[Int](s"$path.p2pNipopows")
+ )
+ }
+}
\ No newline at end of file
diff --git a/src/main/scala/org/ergoplatform/settings/Parameters.scala b/ergo-core/src/main/scala/org/ergoplatform/settings/Parameters.scala
similarity index 98%
rename from src/main/scala/org/ergoplatform/settings/Parameters.scala
rename to ergo-core/src/main/scala/org/ergoplatform/settings/Parameters.scala
index 5a12fa813d..51d76084cf 100644
--- a/src/main/scala/org/ergoplatform/settings/Parameters.scala
+++ b/ergo-core/src/main/scala/org/ergoplatform/settings/Parameters.scala
@@ -3,8 +3,8 @@ package org.ergoplatform.settings
import com.google.common.primitives.Ints
import io.circe.Encoder
import io.circe.syntax._
-import org.ergoplatform.nodeView.history.ErgoHistory.Height
-import scorex.core.serialization.ErgoSerializer
+import org.ergoplatform.nodeView.history.ErgoHistoryUtils.Height
+import org.ergoplatform.serialization.ErgoSerializer
import scorex.util.serialization.{Reader, Writer}
import scorex.util.Extensions._
@@ -386,9 +386,9 @@ object ParametersSerializer extends ErgoSerializer[Parameters] with ApiCodecs {
override def serialize(params: Parameters, w: Writer): Unit = {
require(params.parametersTable.nonEmpty, s"$params is empty")
- w.putUInt(params.height)
+ w.putUInt(params.height.toLong)
val paramsSize = params.parametersTable.size
- w.putUInt(paramsSize)
+ w.putUInt(paramsSize.toLong)
params.parametersTable.foreach { case (k, v) =>
w.put(k)
w.putInt(v)
diff --git a/src/main/scala/org/ergoplatform/settings/PeerFeatureDescriptors.scala b/ergo-core/src/main/scala/org/ergoplatform/settings/PeerFeatureDescriptors.scala
similarity index 79%
rename from src/main/scala/org/ergoplatform/settings/PeerFeatureDescriptors.scala
rename to ergo-core/src/main/scala/org/ergoplatform/settings/PeerFeatureDescriptors.scala
index 43c2d2dfe1..b77a1db5b1 100644
--- a/src/main/scala/org/ergoplatform/settings/PeerFeatureDescriptors.scala
+++ b/ergo-core/src/main/scala/org/ergoplatform/settings/PeerFeatureDescriptors.scala
@@ -1,8 +1,7 @@
package org.ergoplatform.settings
-import org.ergoplatform.network.ModeFeatureSerializer
-import scorex.core.network.PeerFeature
-import scorex.core.network.peer.{LocalAddressPeerFeatureSerializer, RestApiUrlPeerFeatureSerializer, SessionIdPeerFeatureSerializer}
+import org.ergoplatform.network.{ModeFeatureSerializer, PeerFeature}
+import org.ergoplatform.network.peer.{LocalAddressPeerFeatureSerializer, RestApiUrlPeerFeatureSerializer, SessionIdPeerFeatureSerializer}
/**
* Repository of existing peer feature identifiers, stores their ids along with serializers
diff --git a/src/main/scala/org/ergoplatform/settings/ReemissionSettings.scala b/ergo-core/src/main/scala/org/ergoplatform/settings/ReemissionSettings.scala
similarity index 100%
rename from src/main/scala/org/ergoplatform/settings/ReemissionSettings.scala
rename to ergo-core/src/main/scala/org/ergoplatform/settings/ReemissionSettings.scala
diff --git a/src/main/scala/scorex/core/settings/Settings.scala b/ergo-core/src/main/scala/org/ergoplatform/settings/Settings.scala
similarity index 96%
rename from src/main/scala/scorex/core/settings/Settings.scala
rename to ergo-core/src/main/scala/org/ergoplatform/settings/Settings.scala
index c67890f61b..34f7701bba 100644
--- a/src/main/scala/scorex/core/settings/Settings.scala
+++ b/ergo-core/src/main/scala/org/ergoplatform/settings/Settings.scala
@@ -1,13 +1,13 @@
-package scorex.core.settings
+package org.ergoplatform.settings
-import java.io.File
-import java.net.{InetSocketAddress, URL}
import com.typesafe.config.{Config, ConfigFactory}
import net.ceedubs.ficus.Ficus._
import net.ceedubs.ficus.readers.ArbitraryTypeReader._
-import scorex.core.network.message.Message
+import org.ergoplatform.network.message.MessageConstants._
import scorex.util.ScorexLogging
+import java.io.File
+import java.net.{InetSocketAddress, URL}
import scala.concurrent.duration._
case class LoggingSettings(level: String)
@@ -97,6 +97,6 @@ object ScorexSettings extends ScorexLogging with SettingsReaders {
def fromConfig(config: Config): ScorexSettings = {
config.as[ScorexSettings](configPath)
- .ensuring(_.network.magicBytes.length == Message.MagicLength)
+ .ensuring(_.network.magicBytes.length == MagicLength)
}
}
diff --git a/src/main/scala/scorex/core/settings/SettingsReaders.scala b/ergo-core/src/main/scala/org/ergoplatform/settings/SettingsReaders.scala
similarity index 94%
rename from src/main/scala/scorex/core/settings/SettingsReaders.scala
rename to ergo-core/src/main/scala/org/ergoplatform/settings/SettingsReaders.scala
index 8daf6d167c..a41a8e2e2d 100644
--- a/src/main/scala/scorex/core/settings/SettingsReaders.scala
+++ b/ergo-core/src/main/scala/org/ergoplatform/settings/SettingsReaders.scala
@@ -1,10 +1,11 @@
-package scorex.core.settings
+package org.ergoplatform.settings
-import java.io.File
-import java.net.InetSocketAddress
import com.typesafe.config.Config
import net.ceedubs.ficus.readers.ValueReader
+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
diff --git a/ergo-core/src/main/scala/org/ergoplatform/settings/UtxoSettings.scala b/ergo-core/src/main/scala/org/ergoplatform/settings/UtxoSettings.scala
new file mode 100644
index 0000000000..64c14ccadf
--- /dev/null
+++ b/ergo-core/src/main/scala/org/ergoplatform/settings/UtxoSettings.scala
@@ -0,0 +1,22 @@
+package org.ergoplatform.settings
+
+import net.ceedubs.ficus.Ficus._
+import net.ceedubs.ficus.readers.ValueReader
+
+/**
+ * Settings related to state bootstrapping with UTXO set snapshots. See ergo.node.utxo section for settings description.
+ */
+case class UtxoSettings(utxoBootstrap: Boolean, storingUtxoSnapshots: Int, p2pUtxoSnapshots: Int)
+
+/**
+ * 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")
+ )
+ }
+}
\ No newline at end of file
diff --git a/src/main/scala/org/ergoplatform/settings/ValidationRules.scala b/ergo-core/src/main/scala/org/ergoplatform/settings/ValidationRules.scala
similarity index 98%
rename from src/main/scala/org/ergoplatform/settings/ValidationRules.scala
rename to ergo-core/src/main/scala/org/ergoplatform/settings/ValidationRules.scala
index 49d516c65f..96029c0994 100644
--- a/src/main/scala/org/ergoplatform/settings/ValidationRules.scala
+++ b/ergo-core/src/main/scala/org/ergoplatform/settings/ValidationRules.scala
@@ -6,10 +6,10 @@ import org.ergoplatform.modifiers.history.extension.Extension
import org.ergoplatform.modifiers.history.header.Header
import org.ergoplatform.modifiers.history.{ADProofs, BlockTransactions}
import org.ergoplatform.modifiers.mempool.ErgoTransaction
-import org.ergoplatform.nodeView.history.ErgoHistory
+import org.ergoplatform.nodeView.history.ErgoHistoryUtils._
import org.ergoplatform.wallet.boxes.ErgoBoxAssetExtractor
-import scorex.core.validation.{InvalidModifier, ModifierValidator}
-import scorex.core.validation.ValidationResult.Invalid
+import org.ergoplatform.validation.{InvalidModifier, ModifierValidator}
+import org.ergoplatform.validation.ValidationResult.Invalid
import scorex.util.ModifierId
object ValidationRules {
@@ -107,7 +107,7 @@ object ValidationRules {
hdrGenesisFromConfig -> RuleStatus(im => fatal(s"Genesis header id should be equal to id from the config. ${im.error}", im.modifierId, im.modifierTypeId),
Seq(classOf[Header]),
mayBeDisabled = false),
- hdrGenesisHeight -> RuleStatus(im => fatal(s"Genesis height should be ${ErgoHistory.GenesisHeight}. ${im.error}", im.modifierId, im.modifierTypeId),
+ hdrGenesisHeight -> RuleStatus(im => fatal(s"Genesis height should be ${GenesisHeight}. ${im.error}", im.modifierId, im.modifierTypeId),
Seq(classOf[Header]),
mayBeDisabled = false),
hdrParent -> RuleStatus(im => recoverable(s"Parent header with id ${im.error} is not defined", im.modifierId, im.modifierTypeId),
diff --git a/src/main/scala/org/ergoplatform/settings/VotingSettings.scala b/ergo-core/src/main/scala/org/ergoplatform/settings/VotingSettings.scala
similarity index 100%
rename from src/main/scala/org/ergoplatform/settings/VotingSettings.scala
rename to ergo-core/src/main/scala/org/ergoplatform/settings/VotingSettings.scala
diff --git a/src/main/scala/org/ergoplatform/utils/BoxUtils.scala b/ergo-core/src/main/scala/org/ergoplatform/utils/BoxUtils.scala
similarity index 93%
rename from src/main/scala/org/ergoplatform/utils/BoxUtils.scala
rename to ergo-core/src/main/scala/org/ergoplatform/utils/BoxUtils.scala
index 37931c9c7f..3802b08077 100644
--- a/src/main/scala/org/ergoplatform/utils/BoxUtils.scala
+++ b/ergo-core/src/main/scala/org/ergoplatform/utils/BoxUtils.scala
@@ -12,7 +12,7 @@ object BoxUtils {
/** Minimal amount for transaction for a box of maximum size*/
@inline
- def sufficientAmount(parameters: Parameters): Long = ErgoBox.MaxBoxSize * parameters.minValuePerByte
+ def sufficientAmount(parameters: Parameters): Long = ErgoBox.MaxBoxSize * parameters.minValuePerByte.toLong
/** Used when complete instance of ErgoBox is unavailable. */
@inline
@@ -39,5 +39,5 @@ object BoxUtils {
)
@inline
- def minimalErgoAmount(box: ErgoBox, parameters: Parameters): Long = box.bytes.length * parameters.minValuePerByte
+ def minimalErgoAmount(box: ErgoBox, parameters: Parameters): Long = box.bytes.length * parameters.minValuePerByte.toLong
}
diff --git a/src/main/scala/org/ergoplatform/utils/LoggingUtil.scala b/ergo-core/src/main/scala/org/ergoplatform/utils/LoggingUtil.scala
similarity index 100%
rename from src/main/scala/org/ergoplatform/utils/LoggingUtil.scala
rename to ergo-core/src/main/scala/org/ergoplatform/utils/LoggingUtil.scala
diff --git a/src/main/scala/scorex/core/utils/ScorexEncoder.scala b/ergo-core/src/main/scala/org/ergoplatform/utils/ScorexEncoder.scala
similarity index 95%
rename from src/main/scala/scorex/core/utils/ScorexEncoder.scala
rename to ergo-core/src/main/scala/org/ergoplatform/utils/ScorexEncoder.scala
index 1e9bf2b68b..e437be18f6 100644
--- a/src/main/scala/scorex/core/utils/ScorexEncoder.scala
+++ b/ergo-core/src/main/scala/org/ergoplatform/utils/ScorexEncoder.scala
@@ -1,6 +1,6 @@
-package scorex.core.utils
+package org.ergoplatform.utils
-import scorex.core.VersionTag
+import org.ergoplatform.core.VersionTag
import scorex.util.ModifierId
import scorex.util.encode.{Base16, BytesEncoder}
diff --git a/src/main/scala/scorex/core/utils/ScorexEncoding.scala b/ergo-core/src/main/scala/org/ergoplatform/utils/ScorexEncoding.scala
similarity index 85%
rename from src/main/scala/scorex/core/utils/ScorexEncoding.scala
rename to ergo-core/src/main/scala/org/ergoplatform/utils/ScorexEncoding.scala
index ae25a560dc..089d00b640 100644
--- a/src/main/scala/scorex/core/utils/ScorexEncoding.scala
+++ b/ergo-core/src/main/scala/org/ergoplatform/utils/ScorexEncoding.scala
@@ -1,4 +1,4 @@
-package scorex.core.utils
+package org.ergoplatform.utils
/**
* Trait with bytes to string encoder
diff --git a/src/main/scala/scorex/core/utils/utils.scala b/ergo-core/src/main/scala/org/ergoplatform/utils/utils.scala
similarity index 69%
rename from src/main/scala/scorex/core/utils/utils.scala
rename to ergo-core/src/main/scala/org/ergoplatform/utils/utils.scala
index 93eaf37b0f..e27399b445 100644
--- a/src/main/scala/scorex/core/utils/utils.scala
+++ b/ergo-core/src/main/scala/org/ergoplatform/utils/utils.scala
@@ -1,4 +1,4 @@
-package scorex.core
+package org.ergoplatform
import java.security.SecureRandom
import scala.annotation.tailrec
@@ -8,25 +8,6 @@ import scala.util.{Failure, Success, Try}
package object utils {
- @deprecated("Use scorex.util.ScorexLogging instead.", "scorex-util 0.1.0")
- type ScorexLogging = scorex.util.ScorexLogging
-
- /**
- * @param block - function to profile
- * @return - execution time in seconds and function result
- */
- def profile[R](block: => R): (Float, R) = {
- val t0 = System.nanoTime()
- val result = block // call-by-name
- val t1 = System.nanoTime()
- ((t1 - t0).toFloat / 1000000000, result)
- }
-
- def toTry(b: Boolean, msg: String): Try[Unit] = b match {
- case true => Success(Unit)
- case false => Failure(new Exception(msg))
- }
-
@tailrec
final def untilTimeout[T](timeout: FiniteDuration,
delay: FiniteDuration = 100.milliseconds)(fn: => T): T = {
@@ -58,22 +39,6 @@ package object utils {
result
}
- def concatFixLengthBytes(seq: Traversable[Array[Byte]]): Array[Byte] = seq.headOption match {
- case None => Array[Byte]()
- case Some(head) => concatFixLengthBytes(seq, head.length)
- }
-
-
- def concatFixLengthBytes(seq: Traversable[Array[Byte]], length: Int): Array[Byte] = {
- val result: Array[Byte] = new Array[Byte](seq.toSeq.length * length)
- var index = 0
- seq.foreach { s =>
- Array.copy(s, 0, result, index, length)
- index += length
- }
- result
- }
-
implicit class MapPimp[K, V](underlying: Map[K, V]) {
/**
* One liner for updating a Map with the possibility to handle case of missing Key
diff --git a/src/main/scala/scorex/core/validation/ModifierError.scala b/ergo-core/src/main/scala/org/ergoplatform/validation/ModifierError.scala
similarity index 98%
rename from src/main/scala/scorex/core/validation/ModifierError.scala
rename to ergo-core/src/main/scala/org/ergoplatform/validation/ModifierError.scala
index a80444668a..10c1f9729a 100644
--- a/src/main/scala/scorex/core/validation/ModifierError.scala
+++ b/ergo-core/src/main/scala/org/ergoplatform/validation/ModifierError.scala
@@ -1,4 +1,4 @@
-package scorex.core.validation
+package org.ergoplatform.validation
import org.ergoplatform.modifiers.NetworkObjectTypeId
import scorex.util.ModifierId
diff --git a/src/main/scala/scorex/core/validation/ModifierValidator.scala b/ergo-core/src/main/scala/org/ergoplatform/validation/ModifierValidator.scala
similarity index 97%
rename from src/main/scala/scorex/core/validation/ModifierValidator.scala
rename to ergo-core/src/main/scala/org/ergoplatform/validation/ModifierValidator.scala
index a8c35aea5b..c0a3c3f7f7 100644
--- a/src/main/scala/scorex/core/validation/ModifierValidator.scala
+++ b/ergo-core/src/main/scala/org/ergoplatform/validation/ModifierValidator.scala
@@ -1,9 +1,9 @@
-package scorex.core.validation
+package org.ergoplatform.validation
+import org.ergoplatform.consensus.ModifierSemanticValidity
import org.ergoplatform.modifiers.NetworkObjectTypeId
-import scorex.core.consensus.ModifierSemanticValidity
-import scorex.core.utils.ScorexEncoder
-import scorex.core.validation.ValidationResult._
+import org.ergoplatform.utils.ScorexEncoder
+import org.ergoplatform.validation.ValidationResult._
import scorex.util.{ModifierId, bytesToId}
import scala.util.{Failure, Success, Try}
@@ -16,7 +16,7 @@ import scala.util.{Failure, Success, Try}
* It is designed to perform multiple checks for the same object without any transformation.
* See the example of that
* kind of validation in Ergo `org.ergoplatform.nodeView.history.storage.modifierprocessors.HeadersProcessor.HeaderValidator`.
- * Some other examples could also be found in `scorex.core.validation.ValidationSpec`.
+ * Some other examples could also be found in `org.ergoplatform.validation.ValidationSpec`.
*
* The second distinction from cats `Validated` is that we do support both fail-fast and error-accumulating validation
* while cats `Validated` supports only accumulative approach.
diff --git a/src/main/scala/scorex/core/validation/ValidationResult.scala b/ergo-core/src/main/scala/org/ergoplatform/validation/ValidationResult.scala
similarity index 87%
rename from src/main/scala/scorex/core/validation/ValidationResult.scala
rename to ergo-core/src/main/scala/org/ergoplatform/validation/ValidationResult.scala
index 028e08b39c..812871112d 100644
--- a/src/main/scala/scorex/core/validation/ValidationResult.scala
+++ b/ergo-core/src/main/scala/org/ergoplatform/validation/ValidationResult.scala
@@ -1,9 +1,7 @@
-package scorex.core.validation
+package org.ergoplatform.validation
-import akka.http.scaladsl.server.Route
import io.circe.{ACursor, DecodingFailure}
-import scorex.core.api.http.ApiError
-import scorex.core.validation.ValidationResult.{Invalid, Valid}
+import org.ergoplatform.validation.ValidationResult.{Invalid, Valid}
import scala.concurrent.Future
import scala.language.implicitConversions
@@ -52,13 +50,6 @@ sealed trait ValidationResult[+T] {
case Invalid(_) => Left(DecodingFailure(message, cursor.history))
}
- /** Convert validation result to akka http route
- */
- def toApi(onSuccess: T => Route): Route = this match {
- case Valid(value) => onSuccess(value)
- case Invalid(_) => ApiError.BadRequest(message)
- }
-
}
object ValidationResult {
diff --git a/src/main/scala/scorex/core/validation/ValidationSettings.scala b/ergo-core/src/main/scala/org/ergoplatform/validation/ValidationSettings.scala
similarity index 88%
rename from src/main/scala/scorex/core/validation/ValidationSettings.scala
rename to ergo-core/src/main/scala/org/ergoplatform/validation/ValidationSettings.scala
index cabd24da9d..d9dd2c889c 100644
--- a/src/main/scala/scorex/core/validation/ValidationSettings.scala
+++ b/ergo-core/src/main/scala/org/ergoplatform/validation/ValidationSettings.scala
@@ -1,7 +1,7 @@
-package scorex.core.validation
+package org.ergoplatform.validation
import org.ergoplatform.modifiers.NetworkObjectTypeId
-import scorex.core.validation.ValidationResult.Invalid
+import org.ergoplatform.validation.ValidationResult.Invalid
import scorex.util.ModifierId
/**
diff --git a/src/it/scala/org/ergoplatform/it/DeepRollBackSpec.scala b/src/it/scala/org/ergoplatform/it/DeepRollBackSpec.scala
index 6411ec89a6..b1ea045021 100644
--- a/src/it/scala/org/ergoplatform/it/DeepRollBackSpec.scala
+++ b/src/it/scala/org/ergoplatform/it/DeepRollBackSpec.scala
@@ -1,10 +1,9 @@
package org.ergoplatform.it
import java.io.File
-
import com.typesafe.config.Config
import org.ergoplatform.it.container.{IntegrationSuite, Node}
-import org.ergoplatform.nodeView.history.ErgoHistory
+import org.ergoplatform.nodeView.history.ErgoHistoryUtils
import org.scalatest.freespec.AnyFreeSpec
import scala.async.Async
@@ -51,7 +50,7 @@ class DeepRollBackSpec extends AnyFreeSpec with IntegrationSuite {
// 1. Let the first node mine `chainLength + delta` blocks
Async.await(minerAIsolated.waitForHeight(chainLength + delta))
- val genesisA = Async.await(minerAIsolated.headerIdsByHeight(ErgoHistory.GenesisHeight)).head
+ val genesisA = Async.await(minerAIsolated.headerIdsByHeight(ErgoHistoryUtils.GenesisHeight)).head
val minerBIsolated: Node = docker.startDevNetNode(minerBConfig, isolatedPeersConfig,
specialVolumeOpt = Some((localVolumeB, remoteVolumeB))).get
@@ -59,7 +58,7 @@ class DeepRollBackSpec extends AnyFreeSpec with IntegrationSuite {
// 2. Let another node mine `chainLength` blocks
Async.await(minerBIsolated.waitForHeight(chainLength))
- val genesisB = Async.await(minerBIsolated.headerIdsByHeight(ErgoHistory.GenesisHeight)).head
+ val genesisB = Async.await(minerBIsolated.headerIdsByHeight(ErgoHistoryUtils.GenesisHeight)).head
genesisA should not equal genesisB
diff --git a/src/it/scala/org/ergoplatform/it/WalletSpec.scala b/src/it/scala/org/ergoplatform/it/WalletSpec.scala
index 3d22140ea0..fd041daaf7 100644
--- a/src/it/scala/org/ergoplatform/it/WalletSpec.scala
+++ b/src/it/scala/org/ergoplatform/it/WalletSpec.scala
@@ -12,7 +12,7 @@ import org.ergoplatform.it.util.RichEither
import org.ergoplatform.modifiers.mempool.UnsignedErgoTransaction
import org.ergoplatform.nodeView.wallet.requests.{PaymentRequest, PaymentRequestEncoder, RequestsHolder, RequestsHolderEncoder}
import org.ergoplatform.nodeView.wallet.{AugWalletTransaction, ErgoWalletServiceImpl}
-import org.ergoplatform.settings.{Args, ErgoSettings}
+import org.ergoplatform.settings.{Args, ErgoSettings, ErgoSettingsReader}
import org.ergoplatform.utils.{ErgoTestHelpers, WalletTestOps}
import org.ergoplatform.wallet.interface4j.SecretString
import org.ergoplatform.wallet.boxes.ErgoBoxSerializer
@@ -29,7 +29,7 @@ class WalletSpec extends AsyncWordSpec with IntegrationSuite with WalletTestOps
override implicit def executionContext: ExecutionContext = ErgoTestHelpers.defaultExecutionContext
- val ergoSettings: ErgoSettings = ErgoSettings.read(
+ val ergoSettings: ErgoSettings = ErgoSettingsReader.read(
Args(userConfigPathOpt = Some("src/test/resources/application.conf"), networkTypeOpt = None))
private val nodeConfig: Config = nonGeneratingPeerConfig.withFallback(nodeSeedConfigs.head)
diff --git a/src/it/scala/org/ergoplatform/it/container/Docker.scala b/src/it/scala/org/ergoplatform/it/container/Docker.scala
index 88fde59095..5e71e45426 100644
--- a/src/it/scala/org/ergoplatform/it/container/Docker.scala
+++ b/src/it/scala/org/ergoplatform/it/container/Docker.scala
@@ -5,7 +5,6 @@ import java.net.InetAddress
import java.nio.file.{Files, Path, Paths}
import java.util.concurrent.atomic.AtomicBoolean
import java.util.{Collections, Properties, UUID, List => JList, Map => JMap}
-
import cats.implicits._
import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.dataformat.javaprop.JavaPropsMapper
@@ -21,7 +20,7 @@ import net.ceedubs.ficus.Ficus._
import org.apache.commons.io.FileUtils
import org.asynchttpclient.Dsl.{config, _}
import org.ergoplatform.settings.NetworkType.{DevNet, MainNet, TestNet}
-import org.ergoplatform.settings.{ErgoSettings, NetworkType}
+import org.ergoplatform.settings.{ErgoSettings, ErgoSettingsReader, NetworkType}
import scorex.util.ScorexLogging
import scala.annotation.tailrec
@@ -176,7 +175,7 @@ class Docker(suiteConfig: Config = ConfigFactory.empty,
.withFallback(ConfigFactory.defaultApplication())
.withFallback(ConfigFactory.defaultReference())
.resolve()
- ErgoSettings.fromConfig(actualConfig)
+ ErgoSettingsReader.fromConfig(actualConfig)
}
private def enrichNodeConfig(networkType: NetworkType,
diff --git a/src/main/resources/api/openapi.yaml b/src/main/resources/api/openapi.yaml
index 5a59717f64..8c07b36cee 100644
--- a/src/main/resources/api/openapi.yaml
+++ b/src/main/resources/api/openapi.yaml
@@ -4479,6 +4479,25 @@ paths:
type: integer
format: int32
default: -1
+ - in: query
+ name: limit
+ required: false
+ description: amount of elements to retrieve
+ schema:
+ type: integer
+ format: int32
+ minimum: 1
+ default: 500
+ maximum: 2500
+ - in: query
+ name: offset
+ required: false
+ description: The number of items in list to skip
+ schema:
+ type: integer
+ format: int32
+ minimum: 0
+ default: 0
get:
security:
- ApiKeyAuth: [api_key]
@@ -4570,6 +4589,25 @@ paths:
type: integer
format: int32
default: -1
+ - in: query
+ name: limit
+ required: false
+ description: amount of elements to retrieve
+ schema:
+ type: integer
+ format: int32
+ minimum: 1
+ default: 500
+ maximum: 2500
+ - in: query
+ name: offset
+ required: false
+ description: The number of items in list to skip
+ schema:
+ type: integer
+ format: int32
+ minimum: 0
+ default: 0
get:
security:
- ApiKeyAuth: [api_key]
@@ -5529,6 +5567,25 @@ paths:
type: integer
format: int32
default: -1
+ - in: query
+ name: limit
+ required: false
+ description: amount of elements to retrieve
+ schema:
+ type: integer
+ format: int32
+ minimum: 1
+ default: 500
+ maximum: 2500
+ - in: query
+ name: offset
+ required: false
+ description: The number of items in list to skip
+ schema:
+ type: integer
+ format: int32
+ minimum: 0
+ default: 0
get:
security:
- ApiKeyAuth: [api_key]
@@ -5596,6 +5653,25 @@ paths:
type: integer
format: int32
default: -1
+ - in: query
+ name: limit
+ required: false
+ description: amount of elements to retrieve
+ schema:
+ type: integer
+ format: int32
+ minimum: 1
+ default: 500
+ maximum: 2500
+ - in: query
+ name: offset
+ required: false
+ description: The number of items in list to skip
+ schema:
+ type: integer
+ format: int32
+ minimum: 0
+ default: 0
get:
security:
- ApiKeyAuth: [api_key]
@@ -6592,4 +6668,4 @@ paths:
content:
application/json:
schema:
- $ref: '#/components/schemas/ApiError'
\ No newline at end of file
+ $ref: '#/components/schemas/ApiError'
diff --git a/src/main/resources/application.conf b/src/main/resources/application.conf
index d578aeb9ee..1295b7acb6 100644
--- a/src/main/resources/application.conf
+++ b/src/main/resources/application.conf
@@ -606,4 +606,20 @@ api-dispatcher {
# processed per actor before the thread jumps to the next actor.
# Set to 1 for as fair as possible.
throughput = 4
+}
+
+indexer-dispatcher {
+ # Dispatcher is the name of the event-based dispatcher
+ type = Dispatcher
+ # What kind of ExecutionService to use
+ executor = "fork-join-executor"
+ # Configuration for the fork join pool
+ fork-join-executor {
+ # Min number of threads to cap factor-based parallelism number to
+ parallelism-min = 1
+ # Parallelism (threads) ... ceil(available processors * factor)
+ parallelism-factor = 1.0
+ # Max number of threads to cap factor-based parallelism number to
+ parallelism-max = 4
+ }
}
\ No newline at end of file
diff --git a/src/main/resources/logback.xml b/src/main/resources/logback.xml
index 946b59a392..2929ac6ade 100644
--- a/src/main/resources/logback.xml
+++ b/src/main/resources/logback.xml
@@ -20,8 +20,8 @@
ergo-%d{yyyy-MM-dd}.%i.log.gz
-
- 30
+
+ 7
500MB
1GB
diff --git a/src/main/scala/org/ergoplatform/ErgoApp.scala b/src/main/scala/org/ergoplatform/ErgoApp.scala
index 88021c75b2..c483237aa6 100644
--- a/src/main/scala/org/ergoplatform/ErgoApp.scala
+++ b/src/main/scala/org/ergoplatform/ErgoApp.scala
@@ -13,15 +13,14 @@ import org.ergoplatform.network.{ErgoNodeViewSynchronizer, ErgoSyncTracker}
import org.ergoplatform.nodeView.history.ErgoSyncInfoMessageSpec
import org.ergoplatform.nodeView.history.extra.ExtraIndexer
import org.ergoplatform.nodeView.{ErgoNodeViewRef, ErgoReadersHolderRef}
-import org.ergoplatform.settings.{Args, ErgoSettings, NetworkType}
+import org.ergoplatform.settings.{Args, ErgoSettings, ErgoSettingsReader, NetworkType, ScorexSettings}
import scorex.core.api.http._
import scorex.core.app.ScorexContext
import scorex.core.network.NetworkController.ReceivableMessages.ShutdownNetwork
import scorex.core.network._
-import scorex.core.network.message.Message.MessageCode
-import scorex.core.network.message._
-import scorex.core.network.peer.PeerManagerRef
-import scorex.core.settings.ScorexSettings
+import org.ergoplatform.network.message.MessageConstants.MessageCode
+import org.ergoplatform.network.message._
+import org.ergoplatform.network.peer.PeerManagerRef
import scorex.util.ScorexLogging
import java.net.InetSocketAddress
@@ -36,7 +35,7 @@ class ErgoApp(args: Args) extends ScorexLogging {
log.info(s"Running with args: $args")
- private val ergoSettings: ErgoSettings = ErgoSettings.read(args)
+ private val ergoSettings: ErgoSettings = ErgoSettingsReader.read(args)
require(
ergoSettings.scorexSettings.restApi.apiKeyHash.isDefined,
@@ -108,13 +107,13 @@ class ErgoApp(args: Args) extends ScorexLogging {
None
}
- if(ergoSettings.nodeSettings.extraIndex)
- require(
- ergoSettings.nodeSettings.stateType.holdsUtxoSet && !ergoSettings.nodeSettings.isFullBlocksPruned,
- "Node must store full UTXO set and all blocks to run extra indexer."
- )
// Create an instance of ExtraIndexer actor (will start if "extraIndex = true" in config)
- private val indexer: ActorRef = ExtraIndexer(ergoSettings.chainSettings, ergoSettings.cacheSettings)
+ private val indexerOpt: Option[ActorRef] =
+ if (ergoSettings.nodeSettings.extraIndex) {
+ Some(ExtraIndexer(ergoSettings.chainSettings, ergoSettings.cacheSettings))
+ } else {
+ None
+ }
private val syncTracker = ErgoSyncTracker(scorexSettings.network)
@@ -184,7 +183,7 @@ class ErgoApp(args: Args) extends ScorexLogging {
private val apiRoutes: Seq[ApiRoute] = Seq(
EmissionApiRoute(ergoSettings),
ErgoUtilsApiRoute(ergoSettings),
- BlockchainApiRoute(readersHolderRef, ergoSettings, indexer),
+ BlockchainApiRoute(readersHolderRef, ergoSettings, indexerOpt),
ErgoPeersApiRoute(
peerManagerRef,
networkControllerRef,
@@ -291,8 +290,7 @@ object ErgoApp extends ScorexLogging {
/** Intentional user invoked remote shutdown */
case object RemoteShutdown extends CoordinatedShutdown.Reason
- /** Exception that triggers proper system shutdown */
- case class CriticalSystemException(message: String) extends Exception(message)
+
/** hard application exit in case actor system is not started yet*/
def forceStopApplication(code: Int = 1): Nothing = sys.exit(code)
diff --git a/src/main/scala/org/ergoplatform/GlobalConstants.scala b/src/main/scala/org/ergoplatform/GlobalConstants.scala
index 0025ba4fc9..5d396394ba 100644
--- a/src/main/scala/org/ergoplatform/GlobalConstants.scala
+++ b/src/main/scala/org/ergoplatform/GlobalConstants.scala
@@ -10,4 +10,6 @@ object GlobalConstants {
* (to avoid clashing between blockchain processing and API actors)
*/
val ApiDispatcher = "api-dispatcher"
+
+ val IndexerDispatcher = "indexer-dispatcher"
}
diff --git a/src/main/scala/org/ergoplatform/http/SwaggerRoute.scala b/src/main/scala/org/ergoplatform/http/SwaggerRoute.scala
index 65010727b0..b80966ad98 100644
--- a/src/main/scala/org/ergoplatform/http/SwaggerRoute.scala
+++ b/src/main/scala/org/ergoplatform/http/SwaggerRoute.scala
@@ -2,7 +2,7 @@ package org.ergoplatform.http
import akka.http.scaladsl.model.{ContentTypes, HttpEntity}
import akka.http.scaladsl.server.{Directives, Route}
-import scorex.core.settings.RESTApiSettings
+import org.ergoplatform.settings.RESTApiSettings
final case class SwaggerRoute(settings: RESTApiSettings, swaggerConfig: String)
extends Directives {
diff --git a/src/main/scala/scorex/core/api/http/ApiError.scala b/src/main/scala/org/ergoplatform/http/api/ApiError.scala
similarity index 97%
rename from src/main/scala/scorex/core/api/http/ApiError.scala
rename to src/main/scala/org/ergoplatform/http/api/ApiError.scala
index 39904c0196..72d36e86b4 100644
--- a/src/main/scala/scorex/core/api/http/ApiError.scala
+++ b/src/main/scala/org/ergoplatform/http/api/ApiError.scala
@@ -1,4 +1,4 @@
-package scorex.core.api.http
+package org.ergoplatform.http.api
import akka.http.scaladsl.model.{ContentTypes, HttpEntity, StatusCode, StatusCodes}
import akka.http.scaladsl.server.{Directives, Route}
diff --git a/src/main/scala/org/ergoplatform/http/api/ApiExtraCodecs.scala b/src/main/scala/org/ergoplatform/http/api/ApiExtraCodecs.scala
new file mode 100644
index 0000000000..250d8d88a4
--- /dev/null
+++ b/src/main/scala/org/ergoplatform/http/api/ApiExtraCodecs.scala
@@ -0,0 +1,116 @@
+package org.ergoplatform.http.api
+
+import io.circe._
+import io.circe.syntax._
+import org.ergoplatform.ErgoAddressEncoder
+import org.ergoplatform.sdk.JsonCodecs
+import org.ergoplatform.nodeView.history.extra.ExtraIndexer.getAddress
+import org.ergoplatform.nodeView.history.extra.{BalanceInfo, IndexedErgoBox, IndexedErgoTransaction, IndexedToken}
+import org.ergoplatform.nodeView.state.SnapshotsInfo
+import org.ergoplatform.nodeView.state.UtxoState.ManifestId
+import org.ergoplatform.nodeView.wallet.persistence.WalletDigest
+
+/**
+ * JSON codecs related to extra indices (available via /blockchain API methods), and also few codecs for wallet
+ * digest (wallet balances) and UTXO snapshot manifests
+ */
+trait ApiExtraCodecs extends JsonCodecs {
+
+ def ergoAddressEncoder: ErgoAddressEncoder
+
+ implicit val indexedBoxEncoder: Encoder[IndexedErgoBox] = { iEb =>
+ iEb.box.asJson.deepMerge(Json.obj(
+ "globalIndex" -> iEb.globalIndex.asJson,
+ "inclusionHeight" -> iEb.inclusionHeight.asJson,
+ "address" -> ergoAddressEncoder.toString(getAddress(iEb.box.ergoTree)(ergoAddressEncoder)).asJson,
+ "spentTransactionId" -> iEb.spendingTxIdOpt.asJson
+ ))
+ }
+
+ implicit val indexedBoxSeqEncoder: Encoder[(Seq[IndexedErgoBox], Long)] = { iEbSeq =>
+ Json.obj(
+ "items" -> iEbSeq._1.asJson,
+ "total" -> iEbSeq._2.asJson
+ )
+ }
+
+ implicit val indexedTxEncoder: Encoder[IndexedErgoTransaction] = { iEt =>
+ Json.obj(
+ "id" -> iEt.txid.asJson,
+ "blockId" -> iEt.blockId.asJson,
+ "inclusionHeight" -> iEt.inclusionHeight.asJson,
+ "timestamp" -> iEt.timestamp.asJson,
+ "index" -> iEt.index.asJson,
+ "globalIndex" -> iEt.globalIndex.asJson,
+ "numConfirmations" -> iEt.numConfirmations.asJson,
+ "inputs" -> iEt.inputs.asJson,
+ "dataInputs" -> iEt.dataInputs.asJson,
+ "outputs" -> iEt.outputs.asJson,
+ "size" -> iEt.size.asJson
+ )
+ }
+
+ implicit val indexedTxSeqEncoder: Encoder[(Seq[IndexedErgoTransaction], Long)] = { iEtSeq =>
+ Json.obj(
+ "items" -> iEtSeq._1.asJson,
+ "total" -> iEtSeq._2.asJson
+ )
+ }
+
+ implicit val IndexedTokenEncoder: Encoder[IndexedToken] = { token =>
+ Json.obj(
+ "id" -> token.tokenId.asJson,
+ "boxId" -> token.boxId.asJson,
+ "emissionAmount" -> token.amount.asJson,
+ "name" -> token.name.asJson,
+ "description" -> token.description.asJson,
+ "decimals" -> token.decimals.asJson
+ )
+ }
+
+ implicit val BalanceInfoEncoder: Encoder[BalanceInfo] = { bal =>
+ Json.obj(
+ "nanoErgs" -> bal.nanoErgs.asJson,
+ "tokens" -> bal.tokens.map(token => {
+ Json.obj(
+ "tokenId" -> token._1.asJson,
+ "amount" -> token._2.asJson,
+ "decimals" -> bal.additionalTokenInfo(token._1)._2.asJson,
+ "name" -> bal.additionalTokenInfo(token._1)._1.asJson
+ )
+ }).asJson
+ )
+ }
+
+ implicit val TotalBalanceInfoEncoder: Encoder[(BalanceInfo, BalanceInfo)] = { tBal =>
+ Json.obj(
+ "confirmed" -> tBal._1.asJson,
+ "unconfirmed" -> tBal._2.asJson
+ )
+ }
+
+
+ implicit val balancesSnapshotEncoder: Encoder[WalletDigest] = { v =>
+ import v._
+ Json.obj(
+ "height" -> height.asJson,
+ "balance" -> walletBalance.asJson,
+ "assets" -> walletAssetBalances.toMap.map(x => (x._1: String, x._2)).asJson //toMap to have assets as JSON map
+ )
+ }
+
+ implicit val SnapshotInfoEncoder: Encoder[SnapshotsInfo] = { si =>
+ Json.obj(
+ "availableManifests" -> si.availableManifests.map { case (height, manifest) =>
+ height -> manifest
+ }.asJson
+ )
+ }
+
+ implicit val SnapshotInfoDecoder: Decoder[SnapshotsInfo] = { cursor =>
+ for {
+ availableManifests <- Decoder.decodeMap[Int, ManifestId].tryDecode(cursor.downField("availableManifests"))
+ } yield new SnapshotsInfo(availableManifests)
+ }
+
+}
diff --git a/src/main/scala/org/ergoplatform/http/api/ApiRequestsCodecs.scala b/src/main/scala/org/ergoplatform/http/api/ApiRequestsCodecs.scala
new file mode 100644
index 0000000000..916a660eea
--- /dev/null
+++ b/src/main/scala/org/ergoplatform/http/api/ApiRequestsCodecs.scala
@@ -0,0 +1,107 @@
+package org.ergoplatform.http.api
+
+import io.circe._
+import io.circe.syntax._
+import org.ergoplatform.ErgoLikeContext
+import org.ergoplatform.http.api.requests.{CryptoResult, ExecuteRequest, HintExtractionRequest}
+import org.ergoplatform.modifiers.mempool.{ErgoTransaction, UnsignedErgoTransaction}
+import org.ergoplatform.nodeView.wallet.requests.{ExternalSecret, GenerateCommitmentsRequest, TransactionSigningRequest}
+import org.ergoplatform.sdk.wallet.secrets.{DhtSecretKey, DlogSecretKey}
+import org.ergoplatform.wallet.interpreter.TransactionHintsBag
+import sigma.AnyValue
+import sigmastate.Values.SigmaBoolean
+
+/**
+ * JSON codecs for HTTP API requests related entities
+ */
+trait ApiRequestsCodecs extends ApiCodecs {
+
+ implicit val hintExtractionRequestEncoder: Encoder[HintExtractionRequest] = { hr =>
+ Map(
+ "tx" -> hr.tx.asJson,
+ "real" -> hr.real.asJson,
+ "simulated" -> hr.simulated.asJson,
+ "inputsRaw" -> hr.inputs.asJson,
+ "dataInputsRaw" -> hr.dataInputs.asJson
+ ).asJson
+ }
+
+ implicit val hintExtractionRequestDecoder: Decoder[HintExtractionRequest] = { cursor =>
+ for {
+ tx <- cursor.downField("tx").as[ErgoTransaction]
+ real <- cursor.downField("real").as[Seq[SigmaBoolean]]
+ simulated <- cursor.downField("simulated").as[Seq[SigmaBoolean]]
+ inputs <- cursor.downField("inputsRaw").as[Option[Seq[String]]]
+ dataInputs <- cursor.downField("dataInputsRaw").as[Option[Seq[String]]]
+ } yield HintExtractionRequest(tx, real, simulated, inputs, dataInputs)
+ }
+
+ implicit val executeRequestDecoder = new Decoder[ExecuteRequest] {
+ def apply(cursor: HCursor): Decoder.Result[ExecuteRequest] = {
+ for {
+ script <- cursor.downField("script").as[String]
+ env <- cursor.downField("namedConstants").as[Map[String, AnyValue]]
+ ctx <- cursor.downField("context").as[ErgoLikeContext]
+ } yield ExecuteRequest(script, env.map({ case (k, v) => k -> v.value }), ctx)
+ }
+ }
+
+ implicit val cryptResultEncoder: Encoder[CryptoResult] = {
+ res =>
+ val fields = Map(
+ "value" -> res.value.asJson,
+ "cost" -> res.cost.asJson
+ )
+ fields.asJson
+ }
+
+ implicit val transactionSigningRequestEncoder: Encoder[TransactionSigningRequest] = { tsr =>
+ Json.obj(
+ "tx" -> tsr.unsignedTx.asJson,
+ "secrets" -> Json.obj(
+ "dlog" -> tsr.dlogs.asJson,
+ "dht" -> tsr.dhts.asJson
+ ),
+ "hints" -> tsr.hints.asJson,
+ "inputsRaw" -> tsr.inputs.asJson,
+ "dataInputsRaw" -> tsr.dataInputs.asJson
+ )
+ }
+
+ implicit val transactionSigningRequestDecoder: Decoder[TransactionSigningRequest] = { cursor =>
+ for {
+ tx <- cursor.downField("tx").as[UnsignedErgoTransaction]
+ dlogs <- cursor.downField("secrets").downField("dlog").as[Option[Seq[DlogSecretKey]]]
+ dhts <- cursor.downField("secrets").downField("dht").as[Option[Seq[DhtSecretKey]]]
+ hints <- cursor.downField("hints").as[Option[TransactionHintsBag]]
+ inputs <- cursor.downField("inputsRaw").as[Option[Seq[String]]]
+ dataInputs <- cursor.downField("dataInputsRaw").as[Option[Seq[String]]]
+ secrets = (dlogs.getOrElse(Seq.empty) ++ dhts.getOrElse(Seq.empty)).map(ExternalSecret.apply)
+ } yield TransactionSigningRequest(tx, hints.getOrElse(TransactionHintsBag.empty), secrets, inputs, dataInputs)
+ }
+
+ implicit val generateCommitmentsRequestEncoder: Encoder[GenerateCommitmentsRequest] = { gcr =>
+ Json.obj(
+ "tx" -> gcr.unsignedTx.asJson,
+ "secrets" -> Json.obj(
+ "dlog" -> gcr.dlogs.asJson,
+ "dht" -> gcr.dhts.asJson,
+ "inputsRaw" -> gcr.inputs.asJson,
+ "dataInputsRaw" -> gcr.dataInputs.asJson
+ )
+ )
+ }
+
+ implicit val generateCommitmentsRequestDecoder: Decoder[GenerateCommitmentsRequest] = { cursor =>
+ for {
+ tx <- cursor.downField("tx").as[UnsignedErgoTransaction]
+ dlogs <- cursor.downField("secrets").downField("dlog").as[Option[Seq[DlogSecretKey]]]
+ dhts <- cursor.downField("secrets").downField("dht").as[Option[Seq[DhtSecretKey]]]
+ secrets = (dlogs.getOrElse(Seq.empty) ++ dhts.getOrElse(Seq.empty)).map(ExternalSecret.apply)
+ secretsOpt = if (secrets.isEmpty) None else Some(secrets)
+ inputs <- cursor.downField("inputsRaw").as[Option[Seq[String]]]
+ dataInputs <- cursor.downField("dataInputsRaw").as[Option[Seq[String]]]
+ } yield GenerateCommitmentsRequest(tx, secretsOpt, inputs, dataInputs)
+ }
+
+}
diff --git a/src/main/scala/org/ergoplatform/http/api/BlockchainApiRoute.scala b/src/main/scala/org/ergoplatform/http/api/BlockchainApiRoute.scala
index e5cb090761..39c913bdee 100644
--- a/src/main/scala/org/ergoplatform/http/api/BlockchainApiRoute.scala
+++ b/src/main/scala/org/ergoplatform/http/api/BlockchainApiRoute.scala
@@ -10,16 +10,15 @@ import org.ergoplatform.http.api.SortDirection.{ASC, DESC, Direction, INVALID}
import org.ergoplatform.{ErgoAddress, ErgoAddressEncoder}
import org.ergoplatform.nodeView.ErgoReadersHolder.{GetDataFromHistory, GetReaders, Readers}
import org.ergoplatform.nodeView.history.ErgoHistoryReader
-import org.ergoplatform.nodeView.history.extra.ExtraIndexer.ReceivableMessages.GetSegmentTreshold
+import org.ergoplatform.nodeView.history.extra.ExtraIndexer.ReceivableMessages.GetSegmentThreshold
import org.ergoplatform.nodeView.history.extra.ExtraIndexer.{GlobalBoxIndexKey, GlobalTxIndexKey, getIndex}
import org.ergoplatform.nodeView.history.extra.IndexedErgoAddressSerializer.hashErgoTree
import org.ergoplatform.nodeView.history.extra.IndexedTokenSerializer.uniqueId
import org.ergoplatform.nodeView.history.extra._
import org.ergoplatform.nodeView.mempool.ErgoMemPoolReader
-import org.ergoplatform.settings.ErgoSettings
-import scorex.core.api.http.ApiError.{BadRequest, InternalError}
+import org.ergoplatform.settings.{ErgoSettings, RESTApiSettings}
+import org.ergoplatform.http.api.ApiError.{BadRequest, InternalError}
import scorex.core.api.http.ApiResponse
-import scorex.core.settings.RESTApiSettings
import scorex.util.{ModifierId, bytesToId}
import sigmastate.Values.ErgoTree
import spire.implicits.cfor
@@ -28,13 +27,14 @@ import scala.concurrent.duration.{Duration, SECONDS}
import scala.concurrent.{Await, Future}
import scala.util.Success
-case class BlockchainApiRoute(readersHolder: ActorRef, ergoSettings: ErgoSettings, indexer: ActorRef)
- (implicit val context: ActorRefFactory) extends ErgoBaseApiRoute with ApiCodecs {
+case class BlockchainApiRoute(readersHolder: ActorRef, ergoSettings: ErgoSettings, indexerOpt: Option[ActorRef])
+ (implicit val context: ActorRefFactory) extends ErgoBaseApiRoute with ApiCodecs with ApiExtraCodecs {
val settings: RESTApiSettings = ergoSettings.scorexSettings.restApi
- private implicit val segmentTreshold: Int =
- Await.result[Int]((indexer ? GetSegmentTreshold).asInstanceOf[Future[Int]], Duration(3, SECONDS))
+ private implicit val segmentTreshold: Int = indexerOpt.map { indexer =>
+ Await.result[Int]((indexer ? GetSegmentThreshold).asInstanceOf[Future[Int]], Duration(3, SECONDS))
+ }.getOrElse(0)
private val paging: Directive[(Int, Int)] = parameters("offset".as[Int] ? 0, "limit".as[Int] ? 5)
@@ -402,13 +402,3 @@ case class BlockchainApiRoute(readersHolder: ActorRef, ergoSettings: ErgoSetting
}
}
-
-object SortDirection {
-
- type Direction = Byte
-
- val ASC: Direction = 1.asInstanceOf[Direction]
- val DESC: Direction = 0.asInstanceOf[Direction]
- val INVALID: Direction = (-1).asInstanceOf[Direction]
-
-}
diff --git a/src/main/scala/org/ergoplatform/http/api/BlocksApiRoute.scala b/src/main/scala/org/ergoplatform/http/api/BlocksApiRoute.scala
index ebf82586d8..64a98e6044 100644
--- a/src/main/scala/org/ergoplatform/http/api/BlocksApiRoute.scala
+++ b/src/main/scala/org/ergoplatform/http/api/BlocksApiRoute.scala
@@ -7,14 +7,13 @@ import io.circe.Json
import io.circe.syntax._
import org.ergoplatform.modifiers.history.header.Header
import org.ergoplatform.modifiers.history.BlockTransactions
-import org.ergoplatform.modifiers.{NonHeaderBlockSection, ErgoFullBlock, BlockSection}
+import org.ergoplatform.modifiers.{BlockSection, ErgoFullBlock, NonHeaderBlockSection}
import org.ergoplatform.nodeView.ErgoReadersHolder.GetDataFromHistory
import org.ergoplatform.nodeView.history.ErgoHistoryReader
-import org.ergoplatform.settings.{Algos, ErgoSettings}
-import org.ergoplatform.nodeView.ErgoNodeViewHolder.ReceivableMessages.LocallyGeneratedModifier
-import scorex.core.api.http.ApiError.BadRequest
+import org.ergoplatform.settings.{Algos, ErgoSettings, RESTApiSettings}
+import org.ergoplatform.http.api.ApiError.BadRequest
+import org.ergoplatform.nodeView.LocallyGeneratedModifier
import scorex.core.api.http.ApiResponse
-import scorex.core.settings.RESTApiSettings
import scorex.crypto.authds.merkle.MerkleProof
import scorex.crypto.hash.Digest32
import scorex.util.ModifierId
diff --git a/src/main/scala/org/ergoplatform/http/api/EmissionApiRoute.scala b/src/main/scala/org/ergoplatform/http/api/EmissionApiRoute.scala
index 0a3f370868..7a6789cc15 100644
--- a/src/main/scala/org/ergoplatform/http/api/EmissionApiRoute.scala
+++ b/src/main/scala/org/ergoplatform/http/api/EmissionApiRoute.scala
@@ -5,10 +5,9 @@ import akka.http.scaladsl.server.Route
import io.circe.syntax._
import io.circe.{Encoder, Json}
import org.ergoplatform.mining.emission.EmissionRules
-import org.ergoplatform.settings.{ErgoSettings, ReemissionSettings}
+import org.ergoplatform.settings.{ErgoSettings, RESTApiSettings, ReemissionSettings}
import org.ergoplatform.{ErgoAddressEncoder, ErgoTreePredef, Pay2SAddress}
import scorex.core.api.http.ApiResponse
-import scorex.core.settings.RESTApiSettings
case class EmissionApiRoute(ergoSettings: ErgoSettings)
(implicit val context: ActorRefFactory) extends ErgoBaseApiRoute {
diff --git a/src/main/scala/org/ergoplatform/http/api/ErgoBaseApiRoute.scala b/src/main/scala/org/ergoplatform/http/api/ErgoBaseApiRoute.scala
index bc0ae49191..f12badfb0b 100644
--- a/src/main/scala/org/ergoplatform/http/api/ErgoBaseApiRoute.scala
+++ b/src/main/scala/org/ergoplatform/http/api/ErgoBaseApiRoute.scala
@@ -8,13 +8,13 @@ import org.ergoplatform.nodeView.ErgoReadersHolder.{GetReaders, Readers}
import org.ergoplatform.nodeView.mempool.ErgoMemPoolReader
import org.ergoplatform.nodeView.state.{ErgoStateReader, UtxoStateReader}
import org.ergoplatform.settings.{Algos, ErgoSettings}
-import scorex.core.api.http.{ApiError, ApiRoute}
+import scorex.core.api.http.ApiRoute
import scorex.util.{bytesToId, ModifierId}
import akka.pattern.ask
import io.circe.syntax.EncoderOps
import org.ergoplatform.nodeView.ErgoNodeViewHolder.ReceivableMessages.LocallyGeneratedTransaction
-import org.ergoplatform.nodeView.mempool.ErgoMemPool.ProcessingOutcome
-import org.ergoplatform.nodeView.mempool.ErgoMemPool.ProcessingOutcome._
+import org.ergoplatform.nodeView.mempool.ErgoMemPoolUtils.ProcessingOutcome
+import org.ergoplatform.nodeView.mempool.ErgoMemPoolUtils.ProcessingOutcome._
import scorex.util.encode.Base16
import sigmastate.Values.ErgoTree
import sigmastate.serialization.ErgoTreeSerializer
diff --git a/src/main/scala/org/ergoplatform/http/api/ErgoPeersApiRoute.scala b/src/main/scala/org/ergoplatform/http/api/ErgoPeersApiRoute.scala
index 6efe66f3cf..88bf56eeea 100644
--- a/src/main/scala/org/ergoplatform/http/api/ErgoPeersApiRoute.scala
+++ b/src/main/scala/org/ergoplatform/http/api/ErgoPeersApiRoute.scala
@@ -8,12 +8,12 @@ import io.circe.syntax._
import io.circe.{Encoder, Json}
import io.circe.generic.semiauto.deriveEncoder
import org.ergoplatform.network.ErgoSyncTracker
-import scorex.core.api.http.{ApiError, ApiResponse, ApiRoute}
+import scorex.core.api.http.{ApiResponse, ApiRoute}
import scorex.core.network.{ConnectedPeer, DeliveryTracker}
import scorex.core.network.NetworkController.ReceivableMessages.{ConnectTo, GetConnectedPeers, GetPeersStatus}
-import scorex.core.network.peer.{PeerInfo, PeersStatus}
-import scorex.core.network.peer.PeerManager.ReceivableMessages.{GetAllPeers, GetBlacklistedPeers}
-import scorex.core.settings.RESTApiSettings
+import org.ergoplatform.network.peer.{PeerInfo, PeersStatus}
+import org.ergoplatform.network.peer.PeerManager.ReceivableMessages.{GetAllPeers, GetBlacklistedPeers}
+import org.ergoplatform.settings.RESTApiSettings
import scala.concurrent.duration._
import scala.concurrent.ExecutionContext
diff --git a/src/main/scala/org/ergoplatform/http/api/ErgoUtilsApiRoute.scala b/src/main/scala/org/ergoplatform/http/api/ErgoUtilsApiRoute.scala
index 8684526663..87775dba7a 100644
--- a/src/main/scala/org/ergoplatform/http/api/ErgoUtilsApiRoute.scala
+++ b/src/main/scala/org/ergoplatform/http/api/ErgoUtilsApiRoute.scala
@@ -5,12 +5,11 @@ import akka.http.scaladsl.model.StatusCodes
import akka.http.scaladsl.server.Route
import io.circe.Json
import io.circe.syntax._
-import org.ergoplatform.settings.ErgoSettings
+import org.ergoplatform.http.api.ApiError.BadRequest
+import org.ergoplatform.settings.{ErgoSettings, RESTApiSettings}
import org.ergoplatform.{ErgoAddressEncoder, P2PKAddress}
-import scorex.core.api.http.ApiError.BadRequest
-import scorex.core.api.http.{ApiError, ApiResponse, ApiRoute}
-import scorex.core.settings.RESTApiSettings
-import scorex.core.utils.ScorexEncoding
+import scorex.core.api.http.{ApiResponse, ApiRoute}
+import org.ergoplatform.utils.ScorexEncoding
import scorex.crypto.hash.Blake2b256
import scorex.util.encode.Base16
import sigmastate.crypto.DLogProtocol.ProveDlog
diff --git a/src/main/scala/org/ergoplatform/http/api/InfoApiRoute.scala b/src/main/scala/org/ergoplatform/http/api/InfoApiRoute.scala
index e848955fb5..b78f974e61 100644
--- a/src/main/scala/org/ergoplatform/http/api/InfoApiRoute.scala
+++ b/src/main/scala/org/ergoplatform/http/api/InfoApiRoute.scala
@@ -6,8 +6,8 @@ import akka.http.scaladsl.server.Route
import akka.pattern.ask
import io.circe.syntax._
import org.ergoplatform.local.ErgoStatsCollector.{GetNodeInfo, NodeInfo}
+import org.ergoplatform.settings.RESTApiSettings
import scorex.core.api.http.ApiResponse
-import scorex.core.settings.RESTApiSettings
/**
diff --git a/src/main/scala/org/ergoplatform/http/api/MiningApiRoute.scala b/src/main/scala/org/ergoplatform/http/api/MiningApiRoute.scala
index c9ca7c1b8c..89a7dbb280 100644
--- a/src/main/scala/org/ergoplatform/http/api/MiningApiRoute.scala
+++ b/src/main/scala/org/ergoplatform/http/api/MiningApiRoute.scala
@@ -9,10 +9,9 @@ import org.ergoplatform.mining.CandidateGenerator.Candidate
import org.ergoplatform.mining.{AutolykosSolution, CandidateGenerator, ErgoMiner}
import org.ergoplatform.modifiers.mempool.ErgoTransaction
import org.ergoplatform.nodeView.wallet.ErgoAddressJsonEncoder
-import org.ergoplatform.settings.ErgoSettings
+import org.ergoplatform.settings.{ErgoSettings, RESTApiSettings}
import org.ergoplatform.{ErgoAddress, ErgoTreePredef, Pay2SAddress}
import scorex.core.api.http.ApiResponse
-import scorex.core.settings.RESTApiSettings
import sigmastate.crypto.DLogProtocol.ProveDlog
import scala.concurrent.Future
@@ -23,7 +22,7 @@ case class MiningApiRoute(miner: ActorRef,
val settings: RESTApiSettings = ergoSettings.scorexSettings.restApi
- implicit val addressEncoder: Encoder[ErgoAddress] = ErgoAddressJsonEncoder(ergoSettings).encoder
+ implicit val addressEncoder: Encoder[ErgoAddress] = ErgoAddressJsonEncoder(ergoSettings.chainSettings).encoder
override val route: Route = pathPrefix("mining") {
candidateR ~
diff --git a/src/main/scala/org/ergoplatform/http/api/NipopowApiRoute.scala b/src/main/scala/org/ergoplatform/http/api/NipopowApiRoute.scala
index 5ee2a74720..c8ab4c92e6 100644
--- a/src/main/scala/org/ergoplatform/http/api/NipopowApiRoute.scala
+++ b/src/main/scala/org/ergoplatform/http/api/NipopowApiRoute.scala
@@ -6,13 +6,12 @@ import akka.actor.{ActorRef, ActorRefFactory}
import akka.http.scaladsl.server.Route
import io.circe.Encoder
import io.circe.syntax._
-import org.ergoplatform.modifiers.history.popow.{PoPowHeader, NipopowProof}
+import org.ergoplatform.http.api.ApiError.BadRequest
+import org.ergoplatform.modifiers.history.popow.{NipopowProof, PoPowHeader}
import org.ergoplatform.nodeView.ErgoReadersHolder.GetDataFromHistory
import org.ergoplatform.nodeView.history.ErgoHistoryReader
-import org.ergoplatform.settings.ErgoSettings
-import scorex.core.api.http.ApiError.BadRequest
+import org.ergoplatform.settings.{ErgoSettings, RESTApiSettings}
import scorex.core.api.http.ApiResponse
-import scorex.core.settings.RESTApiSettings
import scorex.util.ModifierId
import scala.concurrent.Future
diff --git a/src/main/scala/org/ergoplatform/http/api/NodeApiRoute.scala b/src/main/scala/org/ergoplatform/http/api/NodeApiRoute.scala
index db92275c47..5b0222b53d 100644
--- a/src/main/scala/org/ergoplatform/http/api/NodeApiRoute.scala
+++ b/src/main/scala/org/ergoplatform/http/api/NodeApiRoute.scala
@@ -4,9 +4,8 @@ import akka.actor.{ActorRefFactory, ActorSystem}
import akka.http.scaladsl.server.Route
import org.ergoplatform.ErgoApp
import org.ergoplatform.ErgoApp.RemoteShutdown
-import org.ergoplatform.settings.ErgoSettings
+import org.ergoplatform.settings.{ErgoSettings, RESTApiSettings}
import scorex.core.api.http.ApiResponse
-import scorex.core.settings.RESTApiSettings
import scala.concurrent.duration._
diff --git a/src/main/scala/org/ergoplatform/http/api/ScanApiRoute.scala b/src/main/scala/org/ergoplatform/http/api/ScanApiRoute.scala
index f99af46995..752b4eb112 100644
--- a/src/main/scala/org/ergoplatform/http/api/ScanApiRoute.scala
+++ b/src/main/scala/org/ergoplatform/http/api/ScanApiRoute.scala
@@ -6,14 +6,13 @@ import io.circe.Encoder
import org.ergoplatform._
import org.ergoplatform.nodeView.wallet._
import org.ergoplatform.nodeView.wallet.scanning.{EqualsScanningPredicate, ScanRequest, ScanWalletInteraction}
-import org.ergoplatform.settings.ErgoSettings
-import scorex.core.api.http.ApiError.BadRequest
+import org.ergoplatform.settings.{ErgoSettings, RESTApiSettings}
import scorex.core.api.http.ApiResponse
-import scorex.core.settings.RESTApiSettings
import scala.util.{Failure, Success}
import ScanEntities._
import org.ergoplatform.ErgoBox.R1
+import org.ergoplatform.http.api.ApiError.BadRequest
import org.ergoplatform.wallet.Constants.ScanId
import sigmastate.Values.ByteArrayConstant
import sigmastate.serialization.ErgoTreeSerializer
@@ -66,19 +65,21 @@ case class ScanApiRoute(readersHolder: ActorRef, ergoSettings: ErgoSettings)
}
def unspentR: Route = (path("unspentBoxes" / IntNumber) & get & boxParams) {
- (scanIdInt, minConfNum, maxConfNum, minHeight, maxHeight) =>
+ (scanIdInt, minConfNum, maxConfNum, minHeight, maxHeight, limit, offset) =>
val scanId = ScanId @@ scanIdInt.toShort
val considerUnconfirmed = minConfNum == -1
withWallet(_.scanUnspentBoxes(scanId, considerUnconfirmed, minHeight, maxHeight).map {
_.filter(boxConfirmationFilter(_, minConfNum, maxConfNum))
+ .slice(offset, offset + limit)
})
}
def spentR: Route = (path("spentBoxes" / IntNumber) & get & boxParams) {
- (scanIdInt, minConfNum, maxConfNum, minHeight, maxHeight) =>
+ (scanIdInt, minConfNum, maxConfNum, minHeight, maxHeight, limit, offset) =>
val scanId = ScanId @@ scanIdInt.toShort
withWallet(_.scanSpentBoxes(scanId).map {
_.filter(boxConfirmationHeightFilter(_, minConfNum, maxConfNum, minHeight, maxHeight))
+ .slice(offset, offset + limit)
})
}
diff --git a/src/main/scala/org/ergoplatform/http/api/ScriptApiRoute.scala b/src/main/scala/org/ergoplatform/http/api/ScriptApiRoute.scala
index 908e18c00b..3ab560a3c1 100644
--- a/src/main/scala/org/ergoplatform/http/api/ScriptApiRoute.scala
+++ b/src/main/scala/org/ergoplatform/http/api/ScriptApiRoute.scala
@@ -6,14 +6,13 @@ import akka.pattern.ask
import io.circe.syntax._
import io.circe.{Encoder, Json}
import org.ergoplatform._
+import org.ergoplatform.http.api.ApiError.BadRequest
import org.ergoplatform.http.api.requests.{CryptoResult, ExecuteRequest}
import org.ergoplatform.nodeView.ErgoReadersHolder.{GetReaders, Readers}
import org.ergoplatform.nodeView.wallet.ErgoWalletReader
import org.ergoplatform.nodeView.wallet.requests.PaymentRequestDecoder
-import org.ergoplatform.settings.ErgoSettings
-import scorex.core.api.http.ApiError.BadRequest
+import org.ergoplatform.settings.{ErgoSettings, RESTApiSettings}
import scorex.core.api.http.ApiResponse
-import scorex.core.settings.RESTApiSettings
import scorex.util.encode.Base16
import sigmastate.Values.{ByteArrayConstant, ErgoTree}
import sigmastate._
@@ -29,7 +28,7 @@ import scala.util.{Failure, Success, Try}
case class ScriptApiRoute(readersHolder: ActorRef, ergoSettings: ErgoSettings)
- (implicit val context: ActorRefFactory) extends ErgoBaseApiRoute with ApiCodecs {
+ (implicit val context: ActorRefFactory) extends ErgoBaseApiRoute with ApiCodecs with ApiRequestsCodecs {
implicit val paymentRequestDecoder: PaymentRequestDecoder = new PaymentRequestDecoder(ergoSettings)
implicit val addressEncoder: ErgoAddressEncoder = ErgoAddressEncoder(ergoSettings.chainSettings.addressPrefix)
diff --git a/src/main/scala/org/ergoplatform/http/api/SortDirection.scala b/src/main/scala/org/ergoplatform/http/api/SortDirection.scala
new file mode 100644
index 0000000000..ec022abfc6
--- /dev/null
+++ b/src/main/scala/org/ergoplatform/http/api/SortDirection.scala
@@ -0,0 +1,14 @@
+package org.ergoplatform.http.api
+
+/**
+ * Encoded results sorting direction (in ascending or descending order)
+ */
+object SortDirection {
+
+ type Direction = Byte
+
+ val ASC: Direction = 1.toByte
+ val DESC: Direction = 0.toByte
+ val INVALID: Direction = (-1).toByte
+
+}
diff --git a/src/main/scala/org/ergoplatform/http/api/TransactionsApiRoute.scala b/src/main/scala/org/ergoplatform/http/api/TransactionsApiRoute.scala
index 3f5679c499..0cc95f24a3 100644
--- a/src/main/scala/org/ergoplatform/http/api/TransactionsApiRoute.scala
+++ b/src/main/scala/org/ergoplatform/http/api/TransactionsApiRoute.scala
@@ -7,15 +7,14 @@ import akka.pattern.ask
import io.circe.Json
import io.circe.syntax._
import org.ergoplatform.ErgoBox.{BoxId, NonMandatoryRegisterId, TokenId}
+import org.ergoplatform.http.api.ApiError.BadRequest
import org.ergoplatform.modifiers.mempool.{ErgoTransaction, ErgoTransactionSerializer, UnconfirmedTransaction}
import org.ergoplatform.nodeView.ErgoReadersHolder.{GetReaders, Readers}
import org.ergoplatform.nodeView.mempool.ErgoMemPoolReader
import org.ergoplatform.nodeView.mempool.HistogramStats.getFeeHistogram
import org.ergoplatform.nodeView.state.{ErgoStateReader, UtxoStateReader}
-import org.ergoplatform.settings.{Algos, ErgoSettings}
-import scorex.core.api.http.ApiError.BadRequest
-import scorex.core.api.http.{ApiError, ApiResponse}
-import scorex.core.settings.RESTApiSettings
+import org.ergoplatform.settings.{Algos, ErgoSettings, RESTApiSettings}
+import scorex.core.api.http.ApiResponse
import scorex.crypto.authds.ADKey
import scorex.util.encode.Base16
import sigmastate.SType
diff --git a/src/main/scala/org/ergoplatform/http/api/UtxoApiRoute.scala b/src/main/scala/org/ergoplatform/http/api/UtxoApiRoute.scala
index 4dac6ef738..1889d2a579 100644
--- a/src/main/scala/org/ergoplatform/http/api/UtxoApiRoute.scala
+++ b/src/main/scala/org/ergoplatform/http/api/UtxoApiRoute.scala
@@ -6,14 +6,10 @@ import akka.pattern.ask
import org.ergoplatform.ErgoBox
import org.ergoplatform.nodeView.ErgoReadersHolder.{GetReaders, Readers}
import org.ergoplatform.nodeView.mempool.ErgoMemPoolReader
-import org.ergoplatform.nodeView.state.{
- ErgoStateReader,
- UtxoSetSnapshotPersistence,
- UtxoStateReader
-}
+import org.ergoplatform.nodeView.state.{ErgoStateReader, UtxoSetSnapshotPersistence, UtxoStateReader}
+import org.ergoplatform.settings.RESTApiSettings
import org.ergoplatform.wallet.boxes.ErgoBoxSerializer
import scorex.core.api.http.ApiResponse
-import scorex.core.settings.RESTApiSettings
import scorex.crypto.authds.ADKey
import scorex.util.encode.Base16
@@ -22,7 +18,7 @@ import scala.concurrent.Future
case class UtxoApiRoute(readersHolder: ActorRef, override val settings: RESTApiSettings)(
implicit val context: ActorRefFactory
) extends ErgoBaseApiRoute
- with ApiCodecs {
+ with ApiCodecs with ApiExtraCodecs {
private def getState: Future[ErgoStateReader] =
(readersHolder ? GetReaders).mapTo[Readers].map(_.s)
diff --git a/src/main/scala/org/ergoplatform/http/api/WalletApiOperations.scala b/src/main/scala/org/ergoplatform/http/api/WalletApiOperations.scala
index 0dfee640d9..9beb7ecabf 100644
--- a/src/main/scala/org/ergoplatform/http/api/WalletApiOperations.scala
+++ b/src/main/scala/org/ergoplatform/http/api/WalletApiOperations.scala
@@ -14,18 +14,33 @@ trait WalletApiOperations extends ErgoBaseApiRoute {
val readersHolder: ActorRef
- private val isLegalBoxParamCombination: ((Int, Int, Int, Int)) => Boolean = {
- case (minConfNum, _, _, maxHeight) =>
+
+ val MaxLimit = 2500
+
+ private def isLegalOffset(offset: Int): Boolean = offset >= 0
+
+ private def isLegalLimit(limit: Int): Boolean = limit >= 1 && limit <= MaxLimit
+
+ private val isLegalBoxParamCombination: ((Int, Int, Int, Int, Int, Int)) => Boolean = {
+ case (minConfNum, _, _, maxHeight, limit, offset) =>
+ isLegalOffset(offset) &&
+ isLegalLimit(limit) &&
// maxInclusionHeight cannot be specified when we consider unconfirmed
!(minConfNum == -1 && maxHeight != -1)
}
- val boxParams: Directive[(Int, Int, Int, Int)] =
- parameters("minConfirmations".as[Int] ? 0, "maxConfirmations".as[Int] ? -1, "minInclusionHeight".as[Int] ? 0, "maxInclusionHeight".as[Int] ? -1)
- .tfilter(
- isLegalBoxParamCombination,
- ValidationRejection("maxInclusionHeight cannot be specified when we consider unconfirmed")
- )
+ val boxParams: Directive[(Int, Int, Int, Int, Int, Int)] =
+ parameters(
+ "minConfirmations".as[Int] ? 0,
+ "maxConfirmations".as[Int] ? -1,
+ "minInclusionHeight".as[Int] ? 0,
+ "maxInclusionHeight".as[Int] ? -1,
+ "limit".as[Int] ? 500,
+ "offset".as[Int] ? 0
+ ).tfilter(
+ isLegalBoxParamCombination,
+ ValidationRejection("maxInclusionHeight cannot be specified when we consider unconfirmed")
+ )
/**
* Filter function that filters boxes by height or number of confirmations.
diff --git a/src/main/scala/org/ergoplatform/http/api/WalletApiRoute.scala b/src/main/scala/org/ergoplatform/http/api/WalletApiRoute.scala
index 7669192f19..6a090e42d7 100644
--- a/src/main/scala/org/ergoplatform/http/api/WalletApiRoute.scala
+++ b/src/main/scala/org/ergoplatform/http/api/WalletApiRoute.scala
@@ -11,14 +11,13 @@ import org.ergoplatform.modifiers.mempool.{ErgoTransaction, UnconfirmedTransacti
import org.ergoplatform.nodeView.ErgoReadersHolder.{GetReaders, Readers}
import org.ergoplatform.nodeView.wallet._
import org.ergoplatform.nodeView.wallet.requests._
-import org.ergoplatform.settings.ErgoSettings
+import org.ergoplatform.settings.{ErgoSettings, RESTApiSettings}
import org.ergoplatform.wallet.interface4j.SecretString
import org.ergoplatform.wallet.Constants
import org.ergoplatform.wallet.Constants.ScanId
import org.ergoplatform.wallet.boxes.ErgoBoxSerializer
-import scorex.core.api.http.ApiError.{BadRequest, NotExists}
+import org.ergoplatform.http.api.ApiError.{BadRequest, NotExists}
import scorex.core.api.http.ApiResponse
-import scorex.core.settings.RESTApiSettings
import scorex.util.encode.Base16
import scala.concurrent.Future
@@ -29,7 +28,7 @@ import akka.http.scaladsl.server.MissingQueryParamRejection
case class WalletApiRoute(readersHolder: ActorRef,
nodeViewActorRef: ActorRef,
ergoSettings: ErgoSettings)
- (implicit val context: ActorRefFactory) extends WalletApiOperations with ApiCodecs {
+ (implicit val context: ActorRefFactory) extends WalletApiOperations with ApiCodecs with ApiExtraCodecs with ApiRequestsCodecs {
implicit val paymentRequestDecoder: PaymentRequestDecoder = new PaymentRequestDecoder(ergoSettings)
implicit val assetIssueRequestDecoder: AssetIssueRequestDecoder = new AssetIssueRequestDecoder(ergoSettings)
@@ -220,8 +219,8 @@ case class WalletApiRoute(readersHolder: ActorRef,
val utx = gcr.unsignedTx
val externalSecretsOpt = gcr.externalSecretsOpt
- val extInputsOpt = gcr.inputs.map(ErgoWalletService.stringsToBoxes)
- val extDataInputsOpt = gcr.dataInputs.map(ErgoWalletService.stringsToBoxes)
+ val extInputsOpt = gcr.inputs.map(ErgoWalletServiceUtils.stringsToBoxes)
+ val extDataInputsOpt = gcr.dataInputs.map(ErgoWalletServiceUtils.stringsToBoxes)
withWalletOp(_.generateCommitmentsFor(utx, externalSecretsOpt, extInputsOpt, extDataInputsOpt).map(_.response)) {
case Failure(e) => BadRequest(s"Bad request $gcr. ${Option(e.getMessage).getOrElse(e.toString)}")
@@ -306,23 +305,26 @@ case class WalletApiRoute(readersHolder: ActorRef,
}
def unspentBoxesR: Route = (path("boxes" / "unspent") & get & boxParams) {
- (minConfNum, maxConfNum, minHeight, maxHeight) =>
+ (minConfNum, maxConfNum, minHeight, maxHeight, limit, offset) =>
val considerUnconfirmed = minConfNum == -1
- withWallet {
- _.walletBoxes(unspentOnly = true, considerUnconfirmed)
- .map {
- _.filter(boxConfirmationHeightFilter(_, minConfNum, maxConfNum, minHeight, maxHeight))
+ withWallet { wallet =>
+ wallet.walletBoxes(unspentOnly = true, considerUnconfirmed)
+ .map { boxes =>
+ boxes
+ .filter(boxConfirmationHeightFilter(_, minConfNum, maxConfNum, minHeight, maxHeight))
+ .slice(offset, offset + limit)
}
}
}
def boxesR: Route = (path("boxes") & get & boxParams) {
- (minConfNum, maxConfNum, minHeight, maxHeight) =>
+ (minConfNum, maxConfNum, minHeight, maxHeight, limit, offset) =>
val considerUnconfirmed = minConfNum == -1
withWallet {
_.walletBoxes(unspentOnly = false, considerUnconfirmed = considerUnconfirmed)
.map {
_.filter(boxConfirmationHeightFilter(_, minConfNum, maxConfNum, minHeight, maxHeight))
+ .slice(offset, offset + limit)
}
}
}
@@ -477,8 +479,8 @@ case class WalletApiRoute(readersHolder: ActorRef,
def extractHintsR: Route = (path("extractHints") & post & entity(as[HintExtractionRequest])) { her =>
withWallet { w =>
- val extInputsOpt = her.inputs.map(ErgoWalletService.stringsToBoxes)
- val extDataInputsOpt = her.dataInputs.map(ErgoWalletService.stringsToBoxes)
+ val extInputsOpt = her.inputs.map(ErgoWalletServiceUtils.stringsToBoxes)
+ val extDataInputsOpt = her.dataInputs.map(ErgoWalletServiceUtils.stringsToBoxes)
w.extractHints(her.tx, her.real, her.simulated, extInputsOpt, extDataInputsOpt).map(_.transactionHintsBag)
}
diff --git a/src/main/scala/org/ergoplatform/local/ErgoStatsCollector.scala b/src/main/scala/org/ergoplatform/local/ErgoStatsCollector.scala
index c171e5ab28..39091b904a 100644
--- a/src/main/scala/org/ergoplatform/local/ErgoStatsCollector.scala
+++ b/src/main/scala/org/ergoplatform/local/ErgoStatsCollector.scala
@@ -10,14 +10,15 @@ import org.ergoplatform.modifiers.ErgoFullBlock
import org.ergoplatform.modifiers.history.header.Header
import org.ergoplatform.nodeView.ErgoReadersHolder.{GetReaders, Readers}
import org.ergoplatform.nodeView.history.ErgoHistory
+import org.ergoplatform.nodeView.history.ErgoHistoryUtils._
import org.ergoplatform.nodeView.state.{ErgoStateReader, StateType}
import org.ergoplatform.settings.{Algos, ErgoSettings, LaunchParameters, Parameters}
import scorex.core.network.ConnectedPeer
import scorex.core.network.NetworkController.ReceivableMessages.{GetConnectedPeers, GetPeersStatus}
-import org.ergoplatform.network.ErgoNodeViewSynchronizer.ReceivableMessages._
+import org.ergoplatform.network.ErgoNodeViewSynchronizerMessages._
import org.ergoplatform.network.ErgoSyncTracker
import scorex.util.ScorexLogging
-import scorex.core.network.peer.PeersStatus
+import org.ergoplatform.network.peer.PeersStatus
import java.net.URL
import scala.concurrent.ExecutionContextExecutor
@@ -86,7 +87,7 @@ class ErgoStatsCollector(readersHolder: ActorRef,
bestHeaderOpt = h.bestHeaderOpt,
headersScore = h.bestHeaderOpt.flatMap(m => h.scoreOf(m.id)),
fullBlocksScore = h.bestFullBlockOpt.flatMap(m => h.scoreOf(m.id)),
- genesisBlockIdOpt = h.headerIdsAtHeight(ErgoHistory.GenesisHeight).headOption,
+ genesisBlockIdOpt = h.headerIdsAtHeight(GenesisHeight).headOption,
stateRoot = Some(Algos.encode(s.rootDigest)),
stateVersion = Some(s.version),
parameters = s.stateContext.currentParameters
@@ -112,7 +113,7 @@ class ErgoStatsCollector(readersHolder: ActorRef,
case ChangedHistory(h: ErgoHistory@unchecked) if h.isInstanceOf[ErgoHistory] =>
if (nodeInfo.genesisBlockIdOpt.isEmpty) {
- nodeInfo = nodeInfo.copy(genesisBlockIdOpt = h.headerIdsAtHeight(ErgoHistory.GenesisHeight).headOption)
+ nodeInfo = nodeInfo.copy(genesisBlockIdOpt = h.headerIdsAtHeight(GenesisHeight).headOption)
}
nodeInfo = nodeInfo.copy(bestFullBlockOpt = h.bestFullBlockOpt,
diff --git a/src/main/scala/org/ergoplatform/local/MempoolAuditor.scala b/src/main/scala/org/ergoplatform/local/MempoolAuditor.scala
index 6578613c5e..d46670287f 100644
--- a/src/main/scala/org/ergoplatform/local/MempoolAuditor.scala
+++ b/src/main/scala/org/ergoplatform/local/MempoolAuditor.scala
@@ -9,9 +9,9 @@ import org.ergoplatform.nodeView.mempool.ErgoMemPoolReader
import org.ergoplatform.settings.ErgoSettings
import scorex.core.network.Broadcast
import scorex.core.network.NetworkController.ReceivableMessages.SendToNetwork
-import org.ergoplatform.network.ErgoNodeViewSynchronizer.ReceivableMessages.RecheckMempool
+import org.ergoplatform.network.ErgoNodeViewSynchronizerMessages.RecheckMempool
import org.ergoplatform.nodeView.state.{ErgoStateReader, UtxoStateReader}
-import scorex.core.network.message.{InvData, InvSpec, Message}
+import org.ergoplatform.network.message.{InvData, InvSpec, Message}
import scorex.util.ScorexLogging
import scala.concurrent.duration._
diff --git a/src/main/scala/org/ergoplatform/mining/CandidateGenerator.scala b/src/main/scala/org/ergoplatform/mining/CandidateGenerator.scala
index 17ef8af2a9..a42b50e6db 100644
--- a/src/main/scala/org/ergoplatform/mining/CandidateGenerator.scala
+++ b/src/main/scala/org/ergoplatform/mining/CandidateGenerator.scala
@@ -12,11 +12,12 @@ import org.ergoplatform.modifiers.history.extension.Extension
import org.ergoplatform.modifiers.history.header.{Header, HeaderWithoutPow}
import org.ergoplatform.modifiers.history.popow.NipopowAlgos
import org.ergoplatform.modifiers.mempool.{ErgoTransaction, UnconfirmedTransaction}
-import org.ergoplatform.network.ErgoNodeViewSynchronizer.ReceivableMessages._
-import org.ergoplatform.nodeView.ErgoNodeViewHolder.ReceivableMessages.{EliminateTransactions, LocallyGeneratedModifier}
+import org.ergoplatform.network.ErgoNodeViewSynchronizerMessages._
+import org.ergoplatform.nodeView.ErgoNodeViewHolder.ReceivableMessages.EliminateTransactions
import org.ergoplatform.nodeView.ErgoReadersHolder.{GetReaders, Readers}
-import org.ergoplatform.nodeView.history.ErgoHistory.Height
-import org.ergoplatform.nodeView.history.{ErgoHistory, ErgoHistoryReader}
+import org.ergoplatform.nodeView.LocallyGeneratedModifier
+import org.ergoplatform.nodeView.history.ErgoHistoryUtils.Height
+import org.ergoplatform.nodeView.history.{ErgoHistoryReader, ErgoHistoryUtils}
import org.ergoplatform.nodeView.mempool.ErgoMemPoolReader
import org.ergoplatform.nodeView.state.{ErgoState, ErgoStateContext, StateType, UtxoStateReader}
import org.ergoplatform.settings.{ErgoSettings, ErgoValidationSettingsUpdate, Parameters}
@@ -567,7 +568,7 @@ object CandidateGenerator extends ScorexLogging {
)
val ext = deriveWorkMessage(candidate)
log.info(
- s"Got candidate block at height ${ErgoHistory.heightOf(candidate.parentOpt) + 1}" +
+ s"Got candidate block at height ${ErgoHistoryUtils.heightOf(candidate.parentOpt) + 1}" +
s" with ${candidate.transactions.size} transactions, msg ${Base16.encode(ext.msg)}"
)
Success(
@@ -656,7 +657,7 @@ object CandidateGenerator extends ScorexLogging {
stateContext: ErgoStateContext,
assets: Coll[(TokenId, Long)] = Colls.emptyColl
): Seq[ErgoTransaction] = {
- val chainSettings = stateContext.ergoSettings.chainSettings
+ val chainSettings = stateContext.chainSettings
val propositionBytes = chainSettings.monetary.feePropositionBytes
val emission = chainSettings.emissionRules
diff --git a/src/main/scala/org/ergoplatform/mining/ErgoMiner.scala b/src/main/scala/org/ergoplatform/mining/ErgoMiner.scala
index 4379ebd26b..82b8630abd 100644
--- a/src/main/scala/org/ergoplatform/mining/ErgoMiner.scala
+++ b/src/main/scala/org/ergoplatform/mining/ErgoMiner.scala
@@ -5,10 +5,10 @@ import akka.pattern.StatusReply
import org.ergoplatform.mining.CandidateGenerator.GenerateCandidate
import org.ergoplatform.nodeView.state.DigestState
import org.ergoplatform.modifiers.history.header.Header
-import org.ergoplatform.nodeView.wallet.ErgoWalletActor.{FirstSecretResponse, GetFirstSecret, GetMiningPubKey, MiningPubKeyResponse}
+import org.ergoplatform.nodeView.wallet.ErgoWalletActorMessages.{FirstSecretResponse, GetFirstSecret, GetMiningPubKey, MiningPubKeyResponse}
import org.ergoplatform.settings.ErgoSettings
import org.ergoplatform.nodeView.ErgoNodeViewHolder.ReceivableMessages.GetDataFromCurrentView
-import org.ergoplatform.network.ErgoNodeViewSynchronizer.ReceivableMessages.FullBlockApplied
+import org.ergoplatform.network.ErgoNodeViewSynchronizerMessages.FullBlockApplied
import scorex.util.ScorexLogging
import sigmastate.crypto.DLogProtocol.{DLogProverInput, ProveDlog}
diff --git a/src/main/scala/org/ergoplatform/modifiers/history/popow/NipopowProverWithDbAlgs.scala b/src/main/scala/org/ergoplatform/modifiers/history/popow/NipopowProverWithDbAlgs.scala
new file mode 100644
index 0000000000..d4bffa263d
--- /dev/null
+++ b/src/main/scala/org/ergoplatform/modifiers/history/popow/NipopowProverWithDbAlgs.scala
@@ -0,0 +1,120 @@
+package org.ergoplatform.modifiers.history.popow
+
+import org.ergoplatform.mining.difficulty.DifficultyAdjustment
+import org.ergoplatform.nodeView.history.ErgoHistoryReader
+import org.ergoplatform.settings.ChainSettings
+import scorex.util.ModifierId
+
+import scala.collection.mutable
+import scala.util.Try
+
+/**
+ * Container for NiPoPoW methods working with blockchain database instead of in-memory collections,
+ * for performance's sake.
+ */
+object NipopowProverWithDbAlgs {
+
+ /**
+ * Computes NiPoPow proof for the chain stored in `histReader`'s database,
+ * or a prefix of the chain which contains a specific header (if `headerIdOpt` is specified).
+ * In the latter case, header will be the first header of the suffix of max length `k`
+ * (`suffixHead` field of the result).
+ */
+ def prove(histReader: ErgoHistoryReader,
+ headerIdOpt: Option[ModifierId] = None, chainSettings: ChainSettings)(params: PoPowParams): Try[NipopowProof] = {
+ val diffAdjustment = new DifficultyAdjustment(chainSettings)
+ Try {
+ type Height = Int
+
+ val k = params.k
+ val m = params.m
+
+ require(params.k >= 1, s"$k < 1")
+ require(histReader.headersHeight >= k + m, s"Can not prove chain of size < ${k + m}")
+
+ def linksWithIndexes(header: PoPowHeader): Seq[(ModifierId, Int)] = header.interlinks.tail.reverse.zipWithIndex
+
+ def previousHeaderIdAtLevel(level: Int, currentHeader: PoPowHeader): Option[ModifierId] = {
+ linksWithIndexes(currentHeader).find(_._2 == level).map(_._1)
+ }
+
+ @scala.annotation.tailrec
+ def collectLevel(prevHeaderId: ModifierId,
+ level: Int,
+ anchoringHeight: Height,
+ acc: Seq[PoPowHeader] = Seq.empty): Seq[PoPowHeader] = {
+ val prevHeader = histReader.popowHeader(prevHeaderId).get // to be caught in outer (prove's) Try
+ if (prevHeader.height < anchoringHeight) {
+ acc
+ } else {
+ val newAcc = prevHeader +: acc
+ previousHeaderIdAtLevel(level, prevHeader) match {
+ case Some(newPrevHeaderId) => collectLevel(newPrevHeaderId, level, anchoringHeight, newAcc)
+ case None => newAcc
+ }
+ }
+ }
+
+ def provePrefix(initAnchoringHeight: Height,
+ lastHeader: PoPowHeader): Seq[PoPowHeader] = {
+
+ val collected = mutable.TreeMap[ModifierId, PoPowHeader]()
+
+ val levels = linksWithIndexes(lastHeader)
+ levels.foldRight(initAnchoringHeight) { case ((prevHeaderId, levelIdx), anchoringHeight) =>
+ val levelHeaders = collectLevel(prevHeaderId, levelIdx, anchoringHeight)
+ levelHeaders.foreach(ph => collected.update(ph.id, ph))
+ if (m < levelHeaders.length) {
+ levelHeaders(levelHeaders.length - m).height
+ } else {
+ anchoringHeight
+ }
+ }
+ collected.values.toSeq
+ }
+
+ val (suffixHead, suffixTail) = headerIdOpt match {
+ case Some(headerId) =>
+ val suffixHead = histReader.popowHeader(headerId).get // to be caught in outer (prove's) Try
+ val suffixTail = histReader.bestHeadersAfter(suffixHead.header, k - 1)
+ suffixHead -> suffixTail
+ case None =>
+ val suffix = histReader.lastHeaders(k).headers
+ histReader.popowHeader(suffix.head.id).get -> suffix.tail // .get to be caught in outer (prove's) Try
+ }
+
+ val storedHeights = mutable.Set[Height]() // cache to filter out duplicate headers
+ val prefixBuilder = mutable.ArrayBuilder.make[PoPowHeader]()
+
+ val genesisHeight = 1
+ prefixBuilder += histReader.popowHeader(genesisHeight).get // to be caught in outer (prove's) Try
+ storedHeights += genesisHeight
+
+ if (params.continuous) {
+ // put headers needed to check difficulty of new blocks after suffix into prefix
+ val epochLength = chainSettings.eip37EpochLength.getOrElse(chainSettings.epochLength)
+ diffAdjustment.heightsForNextRecalculation(suffixHead.height, epochLength).foreach { height =>
+ // check that header in or after suffix is not included, otherwise, sorting by height would be broken
+ if (height < suffixHead.height) {
+ histReader.popowHeader(height).foreach { ph =>
+ prefixBuilder += ph
+ storedHeights += ph.height
+ }
+ }
+ }
+ }
+
+ provePrefix(genesisHeight, suffixHead).foreach { ph =>
+ if (!storedHeights.contains(ph.height)) {
+ prefixBuilder += ph
+ storedHeights += ph.height
+ }
+ }
+
+ val prefix = prefixBuilder.result().sortBy(_.height)
+
+ NipopowProof(new NipopowAlgos(chainSettings), m, k, prefix, suffixHead, suffixTail, params.continuous)
+ }
+ }
+
+}
diff --git a/src/main/scala/org/ergoplatform/network/ErgoNodeViewSynchronizer.scala b/src/main/scala/org/ergoplatform/network/ErgoNodeViewSynchronizer.scala
index 352a41ab70..3ab7e92f54 100644
--- a/src/main/scala/org/ergoplatform/network/ErgoNodeViewSynchronizer.scala
+++ b/src/main/scala/org/ergoplatform/network/ErgoNodeViewSynchronizer.scala
@@ -2,43 +2,40 @@ package org.ergoplatform.network
import akka.actor.SupervisorStrategy.{Restart, Stop}
import akka.actor.{Actor, ActorInitializationException, ActorKilledException, ActorRef, ActorRefFactory, DeathPactException, OneForOneStrategy, Props}
-import org.ergoplatform.modifiers.history.header.Header
+import org.ergoplatform.modifiers.history.header.{Header, HeaderSerializer}
import org.ergoplatform.modifiers.mempool.{ErgoTransaction, ErgoTransactionSerializer, UnconfirmedTransaction}
import org.ergoplatform.modifiers.{BlockSection, ManifestTypeId, NetworkObjectTypeId, SnapshotsInfoTypeId, UtxoSnapshotChunkTypeId}
-import org.ergoplatform.modifiers.history.popow.NipopowProof
import org.ergoplatform.nodeView.history.{ErgoSyncInfoV1, ErgoSyncInfoV2}
-import org.ergoplatform.nodeView.history._
-import ErgoNodeViewSynchronizer.{CheckModifiersToDownload, IncomingTxInfo, TransactionProcessingCacheRecord}
import org.ergoplatform.nodeView.ErgoNodeViewHolder.BlockAppliedTransactions
import org.ergoplatform.nodeView.history.{ErgoHistory, ErgoSyncInfo, ErgoSyncInfoMessageSpec}
-import org.ergoplatform.nodeView.mempool.{ErgoMemPool, ErgoMemPoolReader}
-import org.ergoplatform.settings.{Algos, Constants, ErgoSettings}
-import org.ergoplatform.nodeView.ErgoNodeViewHolder.ReceivableMessages._
-import org.ergoplatform.nodeView.ErgoNodeViewHolder.ReceivableMessages.{ChainIsHealthy, ChainIsStuck, GetNodeViewChanges, IsChainHealthy, ModifiersFromRemote}
+import org.ergoplatform.nodeView.mempool.ErgoMemPool
+import org.ergoplatform.settings.{Algos, ErgoSettings, NetworkSettings}
import org.ergoplatform.nodeView.ErgoNodeViewHolder._
-import scorex.core.consensus.{Equal, Fork, Nonsense, Older, Unknown, Younger}
+import org.ergoplatform.nodeView.ErgoNodeViewHolder.ReceivableMessages.{ChainIsHealthy, ChainIsStuck, GetNodeViewChanges, IsChainHealthy, ModifiersFromRemote, TransactionFromRemote}
import scorex.core.network.ModifiersStatus.Requested
-import scorex.core.{NodeViewModifier, idsToString}
+import org.ergoplatform.core.idsToString
import scorex.core.network.NetworkController.ReceivableMessages.{PenalizePeer, SendToNetwork}
-import org.ergoplatform.network.ErgoNodeViewSynchronizer.ReceivableMessages._
+import org.ergoplatform.network.ErgoNodeViewSynchronizerMessages._
import org.ergoplatform.nodeView.state.{ErgoStateReader, SnapshotsInfo, UtxoSetSnapshotPersistence, UtxoStateReader}
-import scorex.core.network.message._
-import org.ergoplatform.nodeView.wallet.ErgoWalletReader
-import scorex.core.network.message.{InvSpec, MessageSpec, ModifiersSpec, RequestModifierSpec}
+import org.ergoplatform.network.message._
+import org.ergoplatform.network.message.{InvSpec, MessageSpec, ModifiersSpec, RequestModifierSpec}
import scorex.core.network._
import scorex.core.network.{ConnectedPeer, ModifiersStatus, SendToPeer, SendToPeers}
-import scorex.core.network.message.{InvData, Message, ModifiersData}
-import scorex.core.settings.NetworkSettings
-import scorex.core.utils.ScorexEncoding
-import scorex.core.validation.MalformedModifierError
+import org.ergoplatform.network.message.{InvData, Message, ModifiersData}
+import org.ergoplatform.utils.ScorexEncoding
+import org.ergoplatform.validation.MalformedModifierError
import scorex.util.{ModifierId, ScorexLogging}
import scorex.core.network.DeliveryTracker
-import scorex.core.network.peer.PenaltyType
+import org.ergoplatform.network.peer.PenaltyType
import scorex.crypto.hash.Digest32
import org.ergoplatform.nodeView.state.UtxoState.{ManifestId, SubtreeId}
import org.ergoplatform.ErgoLikeContext.Height
-import scorex.core.serialization.{ErgoSerializer, ManifestSerializer, SubtreeSerializer}
-import scorex.core.transaction.TooHighCostError
+import org.ergoplatform.NodeViewModifier
+import org.ergoplatform.consensus.{Equal, Fork, Nonsense, Older, Unknown, Younger}
+import org.ergoplatform.modifiers.history.{ADProofs, ADProofsSerializer, BlockTransactions, BlockTransactionsSerializer}
+import org.ergoplatform.modifiers.history.extension.{Extension, ExtensionSerializer}
+import org.ergoplatform.modifiers.transaction.TooHighCostError
+import org.ergoplatform.serialization.{ErgoSerializer, ManifestSerializer, SubtreeSerializer}
import scorex.crypto.authds.avltree.batch.VersionedLDBAVLStorage.splitDigest
import scala.annotation.tailrec
@@ -59,6 +56,8 @@ class ErgoNodeViewSynchronizer(networkControllerRef: ActorRef,
deliveryTracker: DeliveryTracker)(implicit ex: ExecutionContext)
extends Actor with Synchronizer with ScorexLogging with ScorexEncoding {
+ import org.ergoplatform.network.ErgoNodeViewSynchronizer._
+
type EncodedManifestId = ModifierId
override val supervisorStrategy: OneForOneStrategy = OneForOneStrategy(
@@ -707,7 +706,7 @@ class ErgoNodeViewSynchronizer(networkControllerRef: ActorRef,
typeId: NetworkObjectTypeId.Value,
requestedModifiers: Map[ModifierId, Array[Byte]],
remote: ConnectedPeer): Unit = {
- Constants.modifierSerializers.get(typeId) match {
+ modifierSerializers.get(typeId) match {
case Some(serializer: ErgoSerializer[BlockSection]@unchecked) =>
// parse all modifiers and put them to modifiers cache
val parsed: Iterable[BlockSection] = parseModifiers(requestedModifiers, typeId, serializer, remote)
@@ -1614,127 +1613,13 @@ object ErgoNodeViewSynchronizer {
case object CheckModifiersToDownload
- object ReceivableMessages {
-
- // getLocalSyncInfo messages
- case object SendLocalSyncInfo
-
- /**
- * Check delivery of modifier with type `modifierTypeId` and id `modifierId`.
- * `source` may be defined if we expect modifier from concrete peer or None if
- * we just need some modifier, but don't know who have it
- *
- */
- case class CheckDelivery(source: ConnectedPeer,
- modifierTypeId: NetworkObjectTypeId.Value,
- modifierId: ModifierId)
-
- trait PeerManagerEvent
-
- case class HandshakedPeer(remote: ConnectedPeer) extends PeerManagerEvent
-
- case class DisconnectedPeer(peer: ConnectedPeer) extends PeerManagerEvent
-
- trait NodeViewHolderEvent
-
- trait NodeViewChange extends NodeViewHolderEvent
-
- case class ChangedHistory(reader: ErgoHistoryReader) extends NodeViewChange
-
- case class ChangedMempool(mempool: ErgoMemPoolReader) extends NodeViewChange
-
- case class ChangedVault(reader: ErgoWalletReader) extends NodeViewChange
-
- case class ChangedState(reader: ErgoStateReader) extends NodeViewChange
-
- /**
- * Event which is published when rollback happened (on finding a better chain)
- * @param branchPoint - block id which is last in the chain after rollback (before applying blocks from a fork)
- */
- case class Rollback(branchPoint: ModifierId) extends NodeViewHolderEvent
-
- case object RollbackFailed extends NodeViewHolderEvent
-
- // hierarchy of events regarding modifiers application outcome
- trait ModificationOutcome extends NodeViewHolderEvent
-
- trait InitialTransactionCheckOutcome extends ModificationOutcome {
- val transaction: UnconfirmedTransaction
- }
-
- case class FailedTransaction(transaction: UnconfirmedTransaction, error: Throwable) extends InitialTransactionCheckOutcome
-
- case class SuccessfulTransaction(transaction: UnconfirmedTransaction) extends InitialTransactionCheckOutcome
-
- /**
- * Transaction declined by the mempool (not permanently invalidated, so pool can accept it in future)
- */
- case class DeclinedTransaction(transaction: UnconfirmedTransaction) extends InitialTransactionCheckOutcome
-
- /**
- * Transaction which was failed not immediately but after sitting for some time in the mempool or during block
- * candidate generation
- */
- case class FailedOnRecheckTransaction(id : ModifierId, error: Throwable) extends ModificationOutcome
-
- /**
- * A signal that block section with id `modifierId` was invalidated due to `error`, but it may be valid in future
- */
- case class RecoverableFailedModification(typeId: NetworkObjectTypeId.Value, modifierId: ModifierId, error: Throwable) extends ModificationOutcome
-
- /**
- * A signal that block section with id `modifierId` was permanently invalidated during stateless checks
- */
- case class SyntacticallyFailedModification(typeId: NetworkObjectTypeId.Value, modifierId: ModifierId, error: Throwable) extends ModificationOutcome
-
- /**
- * Signal associated with stateful validation of a block section
- */
- case class SemanticallyFailedModification(typeId: NetworkObjectTypeId.Value, modifierId: ModifierId, error: Throwable) extends ModificationOutcome
-
- /**
- * Signal associated with stateless validation of a block section
- */
- case class SyntacticallySuccessfulModifier(typeId: NetworkObjectTypeId.Value, modifierId: ModifierId) extends ModificationOutcome
-
- /**
- * Signal sent by node view holder when a full block is applied to state
- * @param header - full block's header
- */
- case class FullBlockApplied(header: Header) extends ModificationOutcome
-
- /**
- * Signal sent after block sections processing (validation and application to state) done
- * @param headersCacheSize - headers cache size after processing
- * @param blockSectionsCacheSize - block sections cache size after processing
- * @param cleared - blocks removed from cache being overfull
- */
- case class BlockSectionsProcessingCacheUpdate(headersCacheSize: Int,
- blockSectionsCacheSize: Int,
- cleared: (NetworkObjectTypeId.Value, Seq[ModifierId]))
-
- /**
- * Command to re-check mempool to clean transactions become invalid while sitting in the mempool up
- * @param state - up-to-date state to check transaction against
- * @param mempool - mempool to check
- */
- case class RecheckMempool(state: UtxoStateReader, mempool: ErgoMemPoolReader)
-
- /**
- * Signal for a central node view holder component to initialize UTXO state from UTXO set snapshot
- * stored in the local database
- *
- * @param blockHeight - height of a block corresponding to the UTXO set snapshot
- * @param blockId - id of a block corresponding to the UTXO set snapshot
- */
- case class InitStateFromSnapshot(blockHeight: Height, blockId: ModifierId)
-
- /**
- * Command for a central node view holder component to process NiPoPoW proof,
- * and possibly initialize headers chain from a best NiPoPoW proof known, when enough proofs collected
- * @param nipopowProof - proof to initialize history from
- */
- case class ProcessNipopow(nipopowProof: NipopowProof)
- }
-
+ /**
+ * Serializers for block sections and transactions
+ */
+ val modifierSerializers: Map[NetworkObjectTypeId.Value, ErgoSerializer[_ <: NodeViewModifier]] =
+ Map(Header.modifierTypeId -> HeaderSerializer,
+ Extension.modifierTypeId -> ExtensionSerializer,
+ BlockTransactions.modifierTypeId -> BlockTransactionsSerializer,
+ ADProofs.modifierTypeId -> ADProofsSerializer,
+ ErgoTransaction.modifierTypeId -> ErgoTransactionSerializer)
}
diff --git a/src/main/scala/org/ergoplatform/network/ErgoNodeViewSynchronizerMessages.scala b/src/main/scala/org/ergoplatform/network/ErgoNodeViewSynchronizerMessages.scala
new file mode 100644
index 0000000000..e1cc4de78d
--- /dev/null
+++ b/src/main/scala/org/ergoplatform/network/ErgoNodeViewSynchronizerMessages.scala
@@ -0,0 +1,145 @@
+package org.ergoplatform.network
+
+import org.ergoplatform.modifiers.history.header.Header
+import org.ergoplatform.modifiers.mempool.UnconfirmedTransaction
+import org.ergoplatform.modifiers.NetworkObjectTypeId
+import org.ergoplatform.nodeView.history._
+import org.ergoplatform.nodeView.mempool.ErgoMemPoolReader
+import org.ergoplatform.nodeView.state.{ErgoStateReader, UtxoStateReader}
+import org.ergoplatform.nodeView.wallet.ErgoWalletReader
+import scorex.core.network.ConnectedPeer
+import scorex.util.ModifierId
+import org.ergoplatform.ErgoLikeContext.Height
+import org.ergoplatform.modifiers.history.popow.NipopowProof
+
+/**
+ * Repository of messages processed ErgoNodeViewSynchronizer actor
+ */
+object ErgoNodeViewSynchronizerMessages {
+ /**
+ * Signal which is instructing ErgoNodeViewSynchronizer to send sync message to peers (when it is needed)
+ */
+ case object SendLocalSyncInfo
+
+ /**
+ * Check delivery of modifier with type `modifierTypeId` and id `modifierId`.
+ * `source` may be defined if we expect modifier from concrete peer or None if
+ * we just need some modifier, but don't know who have it
+ *
+ */
+ case class CheckDelivery(source: ConnectedPeer,
+ modifierTypeId: NetworkObjectTypeId.Value,
+ modifierId: ModifierId)
+
+ trait PeerManagerEvent
+
+ case class HandshakedPeer(remote: ConnectedPeer) extends PeerManagerEvent
+
+ case class DisconnectedPeer(peer: ConnectedPeer) extends PeerManagerEvent
+
+ trait NodeViewHolderEvent
+
+ trait NodeViewChange extends NodeViewHolderEvent
+
+ case class ChangedHistory(reader: ErgoHistoryReader) extends NodeViewChange
+
+ case class ChangedMempool(mempool: ErgoMemPoolReader) extends NodeViewChange
+
+ case class ChangedVault(reader: ErgoWalletReader) extends NodeViewChange
+
+ case class ChangedState(reader: ErgoStateReader) extends NodeViewChange
+
+ /**
+ * Event which is published when rollback happened (on finding a better chain)
+ *
+ * @param branchPoint - block id which is last in the chain after rollback (before applying blocks from a fork)
+ */
+ case class Rollback(branchPoint: ModifierId) extends NodeViewHolderEvent
+
+ case object RollbackFailed extends NodeViewHolderEvent
+
+ // hierarchy of events regarding modifiers application outcome
+ trait ModificationOutcome extends NodeViewHolderEvent
+
+ trait InitialTransactionCheckOutcome extends ModificationOutcome {
+ val transaction: UnconfirmedTransaction
+ }
+
+ case class FailedTransaction(transaction: UnconfirmedTransaction, error: Throwable) extends InitialTransactionCheckOutcome
+
+ case class SuccessfulTransaction(transaction: UnconfirmedTransaction) extends InitialTransactionCheckOutcome
+
+ /**
+ * Transaction declined by the mempool (not permanently invalidated, so pool can accept it in future)
+ */
+ case class DeclinedTransaction(transaction: UnconfirmedTransaction) extends InitialTransactionCheckOutcome
+
+ /**
+ * Transaction which was failed not immediately but after sitting for some time in the mempool or during block
+ * candidate generation
+ */
+ case class FailedOnRecheckTransaction(id: ModifierId, error: Throwable) extends ModificationOutcome
+
+ /**
+ * A signal that block section with id `modifierId` was invalidated due to `error`, but it may be valid in future
+ */
+ case class RecoverableFailedModification(typeId: NetworkObjectTypeId.Value, modifierId: ModifierId, error: Throwable) extends ModificationOutcome
+
+ /**
+ * A signal that block section with id `modifierId` was permanently invalidated during stateless checks
+ */
+ case class SyntacticallyFailedModification(typeId: NetworkObjectTypeId.Value, modifierId: ModifierId, error: Throwable) extends ModificationOutcome
+
+ /**
+ * Signal associated with stateful validation of a block section
+ */
+ case class SemanticallyFailedModification(typeId: NetworkObjectTypeId.Value, modifierId: ModifierId, error: Throwable) extends ModificationOutcome
+
+ /**
+ * Signal associated with stateless validation of a block section
+ */
+ case class SyntacticallySuccessfulModifier(typeId: NetworkObjectTypeId.Value, modifierId: ModifierId) extends ModificationOutcome
+
+ /**
+ * Signal sent by node view holder when a full block is applied to state
+ *
+ * @param header - full block's header
+ */
+ case class FullBlockApplied(header: Header) extends ModificationOutcome
+
+ /**
+ * Signal sent after block sections processing (validation and application to state) done
+ *
+ * @param headersCacheSize - headers cache size after processing
+ * @param blockSectionsCacheSize - block sections cache size after processing
+ * @param cleared - blocks removed from cache being overfull
+ */
+ case class BlockSectionsProcessingCacheUpdate(headersCacheSize: Int,
+ blockSectionsCacheSize: Int,
+ cleared: (NetworkObjectTypeId.Value, Seq[ModifierId]))
+
+ /**
+ * Command to re-check mempool to clean transactions become invalid while sitting in the mempool up
+ *
+ * @param state - up-to-date state to check transaction against
+ * @param mempool - mempool to check
+ */
+ case class RecheckMempool(state: UtxoStateReader, mempool: ErgoMemPoolReader)
+
+ /**
+ * Signal for a central node view holder component to initialize UTXO state from UTXO set snapshot
+ * stored in the local database
+ *
+ * @param blockHeight - height of a block corresponding to the UTXO set snapshot
+ * @param blockId - id of a block corresponding to the UTXO set snapshot
+ */
+ case class InitStateFromSnapshot(blockHeight: Height, blockId: ModifierId)
+
+ /**
+ * Command for a central node view holder component to process NiPoPoW proof,
+ * and possibly initialize headers chain from a best NiPoPoW proof known, when enough proofs collected
+ *
+ * @param nipopowProof - proof to initialize history from
+ */
+ case class ProcessNipopow(nipopowProof: NipopowProof)
+}
diff --git a/src/main/scala/org/ergoplatform/network/ErgoPeerStatus.scala b/src/main/scala/org/ergoplatform/network/ErgoPeerStatus.scala
index 03f909912b..32b73f31b5 100644
--- a/src/main/scala/org/ergoplatform/network/ErgoPeerStatus.scala
+++ b/src/main/scala/org/ergoplatform/network/ErgoPeerStatus.scala
@@ -1,11 +1,9 @@
package org.ergoplatform.network
import io.circe.{Encoder, Json}
-import org.ergoplatform.nodeView.history.ErgoHistory.Height
-import scorex.core.app.Version
-import scorex.core.consensus.PeerChainStatus
+import org.ergoplatform.consensus.PeerChainStatus
+import org.ergoplatform.nodeView.history.ErgoHistoryUtils._
import scorex.core.network.ConnectedPeer
-import org.ergoplatform.nodeView.history.ErgoHistory.Time
/**
* Container for status of another peer
diff --git a/src/main/scala/org/ergoplatform/network/ErgoSyncTracker.scala b/src/main/scala/org/ergoplatform/network/ErgoSyncTracker.scala
index 3c406f9034..b307202821 100644
--- a/src/main/scala/org/ergoplatform/network/ErgoSyncTracker.scala
+++ b/src/main/scala/org/ergoplatform/network/ErgoSyncTracker.scala
@@ -1,16 +1,16 @@
package org.ergoplatform.network
-import org.ergoplatform.nodeView.history.{ErgoHistory, ErgoHistoryReader, ErgoSyncInfo, ErgoSyncInfoV1, ErgoSyncInfoV2}
-import org.ergoplatform.nodeView.history.ErgoHistory.{Height, Time}
-import scorex.core.consensus.{Fork, Older, PeerChainStatus, Unknown}
+import org.ergoplatform.consensus.{Fork, Older, PeerChainStatus, Unknown}
+import org.ergoplatform.nodeView.history.{ErgoHistoryReader, ErgoSyncInfo, ErgoSyncInfoV1, ErgoSyncInfoV2}
+import org.ergoplatform.nodeView.history.ErgoHistoryUtils._
+import org.ergoplatform.settings.NetworkSettings
import scorex.core.network.ConnectedPeer
-import scorex.core.settings.NetworkSettings
import scorex.util.ScorexLogging
import scala.collection.mutable
import scala.concurrent.duration._
-import scorex.core.utils.MapPimpMutable
+import org.ergoplatform.utils.MapPimpMutable
/**
* Data structures and methods to keep status of peers, find ones with expired status to send sync message etc
@@ -86,7 +86,7 @@ final case class ErgoSyncTracker(networkSettings: NetworkSettings) extends Score
val seniorsBefore = numOfSeniors()
statuses.adjust(peer){
case None =>
- ErgoPeerStatus(peer, status, height.getOrElse(ErgoHistory.EmptyHistoryHeight), None, None)
+ ErgoPeerStatus(peer, status, height.getOrElse(EmptyHistoryHeight), None, None)
case Some(existingPeer) =>
existingPeer.copy(status = status, height = height.getOrElse(existingPeer.height))
}
diff --git a/src/main/scala/org/ergoplatform/network/VersionBasedPeerFilteringRule.scala b/src/main/scala/org/ergoplatform/network/VersionBasedPeerFilteringRule.scala
index ed831e470e..e3b357eeb4 100644
--- a/src/main/scala/org/ergoplatform/network/VersionBasedPeerFilteringRule.scala
+++ b/src/main/scala/org/ergoplatform/network/VersionBasedPeerFilteringRule.scala
@@ -1,6 +1,5 @@
package org.ergoplatform.network
-import scorex.core.app.Version
import scorex.core.network.ConnectedPeer
/**
diff --git a/src/main/scala/scorex/core/network/message/BasicMessagesRepo.scala b/src/main/scala/org/ergoplatform/network/message/BasicMessagesRepo.scala
similarity index 91%
rename from src/main/scala/scorex/core/network/message/BasicMessagesRepo.scala
rename to src/main/scala/org/ergoplatform/network/message/BasicMessagesRepo.scala
index 673182b615..41ba8a43a5 100644
--- a/src/main/scala/scorex/core/network/message/BasicMessagesRepo.scala
+++ b/src/main/scala/org/ergoplatform/network/message/BasicMessagesRepo.scala
@@ -1,19 +1,18 @@
-package scorex.core.network.message
+package org.ergoplatform.network.message
+import org.ergoplatform.NodeViewModifier
import org.ergoplatform.modifiers.NetworkObjectTypeId
+import org.ergoplatform.network.{Handshake, PeerSpec, PeerSpecSerializer}
import org.ergoplatform.nodeView.state.SnapshotsInfo
import org.ergoplatform.nodeView.state.UtxoState.{ManifestId, SubtreeId}
import org.ergoplatform.settings.Algos
-import scorex.core.consensus.SyncInfo
-import scorex.core.network._
-import scorex.core.network.message.Message.MessageCode
-import scorex.core.serialization.ErgoSerializer
-import scorex.core.NodeViewModifier
+import org.ergoplatform.network.message.MessageConstants.MessageCode
import scorex.crypto.hash.Digest32
import scorex.util.Extensions._
import scorex.util.serialization.{Reader, Writer}
import scorex.util.{ModifierId, ScorexLogging, bytesToId, idToBytes}
import org.ergoplatform.sdk.wallet.Constants.ModifierIdLength
+
import scala.collection.immutable
/**
@@ -21,29 +20,11 @@ import scala.collection.immutable
*/
case class ModifiersData(typeId: NetworkObjectTypeId.Value, modifiers: Map[ModifierId, Array[Byte]])
-case class InvData(typeId: NetworkObjectTypeId.Value, ids: Seq[ModifierId])
-
case class NipopowProofData(m: Int, k: Int, headerId: Option[ModifierId]) {
def headerIdBytesOpt: Option[Array[Byte]] = headerId.map(Algos.decode).flatMap(_.toOption)
}
-/**
- * The `SyncInfo` message requests an `Inv` message that provides modifier ids
- * required be sender to synchronize his blockchain with the recipient.
- * It allows a peer which has been disconnected or started for the first
- * time to get the data it needs to request the blocks it hasn't seen.
- *
- * Payload of this message should be determined in underlying applications.
- */
-class SyncInfoMessageSpec[SI <: SyncInfo](serializer: ErgoSerializer[SI]) extends MessageSpecV1[SI] {
-
- override val messageCode: MessageCode = 65: Byte
- override val messageName: String = "Sync"
- override def serialize(data: SI, w: Writer): Unit = serializer.serialize(data, w)
-
- override def parse(r: Reader): SI = serializer.parse(r)
-}
/**
* The `Inv` message (inventory message) transmits one or more inventories of
@@ -180,7 +161,7 @@ object ModifiersSpec extends MessageSpecV1[ModifiersData] with ScorexLogging {
* messages to arrive over time.
*/
object GetPeersSpec extends MessageSpecV1[Unit] {
- override val messageCode: Message.MessageCode = 1: Byte
+ override val messageCode: MessageCode = 1: Byte
override val messageName: String = "GetPeers message"
@@ -194,7 +175,7 @@ object GetPeersSpec extends MessageSpecV1[Unit] {
object PeersSpec {
- val messageCode: Message.MessageCode = 2: Byte
+ val messageCode: MessageCode = 2: Byte
val messageName: String = "Peers message"
@@ -206,7 +187,7 @@ object PeersSpec {
*/
class PeersSpec(peersLimit: Int) extends MessageSpecV1[Seq[PeerSpec]] {
- override val messageCode: Message.MessageCode = PeersSpec.messageCode
+ override val messageCode: MessageCode = PeersSpec.messageCode
override val messageName: String = PeersSpec.messageName
diff --git a/src/main/scala/scorex/core/network/message/Message.scala b/src/main/scala/org/ergoplatform/network/message/Message.scala
similarity index 86%
rename from src/main/scala/scorex/core/network/message/Message.scala
rename to src/main/scala/org/ergoplatform/network/message/Message.scala
index 94c68e8d83..994e01ddeb 100644
--- a/src/main/scala/scorex/core/network/message/Message.scala
+++ b/src/main/scala/org/ergoplatform/network/message/Message.scala
@@ -1,10 +1,10 @@
-package scorex.core.network.message
+package org.ergoplatform.network.message
import akka.actor.DeadLetterSuppression
import scorex.core.network.ConnectedPeer
import scala.util.{Success, Try}
-
+import org.ergoplatform.network.message.MessageConstants._
/**
* Wrapper for a network message, whether come from external peer or generated locally
@@ -20,8 +20,6 @@ case class Message[Content](spec: MessageSpec[Content],
source: Option[ConnectedPeer])
extends DeadLetterSuppression {
- import Message._
-
/**
* Message data bytes
*/
@@ -52,13 +50,3 @@ case class Message[Content](spec: MessageSpec[Content],
}
}
-
-object Message {
- type MessageCode = Byte
-
- val MagicLength: Int = 4
-
- val ChecksumLength: Int = 4
-
- val HeaderLength: Int = MagicLength + 5
-}
diff --git a/src/main/scala/scorex/core/network/message/MessageSerializer.scala b/src/main/scala/org/ergoplatform/network/message/MessageSerializer.scala
similarity index 95%
rename from src/main/scala/scorex/core/network/message/MessageSerializer.scala
rename to src/main/scala/org/ergoplatform/network/message/MessageSerializer.scala
index 18c28c210e..d98e662e9c 100644
--- a/src/main/scala/scorex/core/network/message/MessageSerializer.scala
+++ b/src/main/scala/org/ergoplatform/network/message/MessageSerializer.scala
@@ -1,4 +1,4 @@
-package scorex.core.network.message
+package org.ergoplatform.network.message
import java.nio.ByteOrder
@@ -10,7 +10,7 @@ import scala.util.Try
class MessageSerializer(specs: Seq[MessageSpec[_]], magicBytes: Array[Byte]) {
- import Message.{ChecksumLength, HeaderLength, MagicLength}
+ import MessageConstants.{ChecksumLength, HeaderLength, MagicLength}
import scala.language.existentials
diff --git a/src/main/scala/scorex/core/network/peer/PeerDatabase.scala b/src/main/scala/org/ergoplatform/network/peer/PeerDatabase.scala
similarity index 97%
rename from src/main/scala/scorex/core/network/peer/PeerDatabase.scala
rename to src/main/scala/org/ergoplatform/network/peer/PeerDatabase.scala
index bf9f518bb5..5040fbe561 100644
--- a/src/main/scala/scorex/core/network/peer/PeerDatabase.scala
+++ b/src/main/scala/org/ergoplatform/network/peer/PeerDatabase.scala
@@ -1,7 +1,6 @@
-package scorex.core.network.peer
-
-import org.ergoplatform.nodeView.history.ErgoHistory
+package org.ergoplatform.network.peer
+import org.ergoplatform.nodeView.history.ErgoHistoryUtils._
import java.io.{ByteArrayInputStream, ByteArrayOutputStream, ObjectInputStream, ObjectOutputStream}
import java.net.{InetAddress, InetSocketAddress}
import org.ergoplatform.settings.ErgoSettings
@@ -30,7 +29,7 @@ final class PeerDatabase(settings: ErgoSettings) extends ScorexLogging {
/**
* banned peer ip -> ban expiration timestamp
*/
- private var blacklist = Map.empty[InetAddress, ErgoHistory.Time]
+ private var blacklist = Map.empty[InetAddress, Time]
/**
* penalized peer ip -> (accumulated penalty score, last penalty timestamp)
diff --git a/src/main/scala/scorex/core/network/peer/PeerInfo.scala b/src/main/scala/org/ergoplatform/network/peer/PeerInfo.scala
similarity index 89%
rename from src/main/scala/scorex/core/network/peer/PeerInfo.scala
rename to src/main/scala/org/ergoplatform/network/peer/PeerInfo.scala
index b95bafa938..8b191d5a3d 100644
--- a/src/main/scala/scorex/core/network/peer/PeerInfo.scala
+++ b/src/main/scala/org/ergoplatform/network/peer/PeerInfo.scala
@@ -1,9 +1,10 @@
-package scorex.core.network.peer
+package org.ergoplatform.network.peer
+
+import org.ergoplatform.network.{PeerSpec, PeerSpecSerializer, Version}
import java.net.InetSocketAddress
-import scorex.core.app.Version
-import scorex.core.network.{ConnectionDirection, Incoming, Outgoing, PeerSpec, PeerSpecSerializer}
-import scorex.core.serialization.ErgoSerializer
+import scorex.core.network.{ConnectionDirection, Incoming, Outgoing}
+import org.ergoplatform.serialization.ErgoSerializer
import scorex.util.serialization.{Reader, Writer}
/**
@@ -43,7 +44,7 @@ object PeerInfo {
}
/**
- * Serializer of [[scorex.core.network.peer.PeerInfo]]
+ * Serializer of [[org.ergoplatform.network.peer.PeerInfo]]
*/
object PeerInfoSerializer extends ErgoSerializer[PeerInfo] {
diff --git a/src/main/scala/scorex/core/network/peer/PeerManager.scala b/src/main/scala/org/ergoplatform/network/peer/PeerManager.scala
similarity index 99%
rename from src/main/scala/scorex/core/network/peer/PeerManager.scala
rename to src/main/scala/org/ergoplatform/network/peer/PeerManager.scala
index 5e40359bbe..65a6d24c7e 100644
--- a/src/main/scala/scorex/core/network/peer/PeerManager.scala
+++ b/src/main/scala/org/ergoplatform/network/peer/PeerManager.scala
@@ -1,8 +1,8 @@
-package scorex.core.network.peer
+package org.ergoplatform.network.peer
import java.net.{InetAddress, InetSocketAddress}
-
import akka.actor.{Actor, ActorRef, ActorSystem, Props}
+import org.ergoplatform.network.PeerSpec
import org.ergoplatform.settings.ErgoSettings
import scorex.core.app.ScorexContext
import scorex.core.network._
diff --git a/src/main/scala/scorex/core/network/peer/PenaltyType.scala b/src/main/scala/org/ergoplatform/network/peer/PenaltyType.scala
similarity index 95%
rename from src/main/scala/scorex/core/network/peer/PenaltyType.scala
rename to src/main/scala/org/ergoplatform/network/peer/PenaltyType.scala
index ac53def8e9..07409469f6 100644
--- a/src/main/scala/scorex/core/network/peer/PenaltyType.scala
+++ b/src/main/scala/org/ergoplatform/network/peer/PenaltyType.scala
@@ -1,4 +1,4 @@
-package scorex.core.network.peer
+package org.ergoplatform.network.peer
/**
* A trait describing all possible types of the network participant misbehavior.
diff --git a/src/main/scala/org/ergoplatform/nodeView/ErgoModifiersCache.scala b/src/main/scala/org/ergoplatform/nodeView/ErgoModifiersCache.scala
index b99d81c0eb..70ed8d8f3f 100644
--- a/src/main/scala/org/ergoplatform/nodeView/ErgoModifiersCache.scala
+++ b/src/main/scala/org/ergoplatform/nodeView/ErgoModifiersCache.scala
@@ -4,7 +4,7 @@ import org.ergoplatform.modifiers.BlockSection
import org.ergoplatform.modifiers.history.header.Header
import org.ergoplatform.nodeView.history.ErgoHistory
import scorex.core.{LRUCache, ModifiersCache}
-import scorex.core.validation.MalformedModifierError
+import org.ergoplatform.validation.MalformedModifierError
import scorex.util.ScorexLogging
import scala.util.Failure
diff --git a/src/main/scala/org/ergoplatform/nodeView/ErgoNodeViewHolder.scala b/src/main/scala/org/ergoplatform/nodeView/ErgoNodeViewHolder.scala
index fdcc3bb17f..8f81b7f201 100644
--- a/src/main/scala/org/ergoplatform/nodeView/ErgoNodeViewHolder.scala
+++ b/src/main/scala/org/ergoplatform/nodeView/ErgoNodeViewHolder.scala
@@ -2,27 +2,25 @@ package org.ergoplatform.nodeView
import akka.actor.SupervisorStrategy.Escalate
import akka.actor.{Actor, ActorRef, ActorSystem, OneForOneStrategy, Props}
-import org.ergoplatform.ErgoApp
-import org.ergoplatform.ErgoApp.CriticalSystemException
+import org.ergoplatform.{CriticalSystemException, ErgoApp, TransactionsCarryingPersistentNodeViewModifier}
+import org.ergoplatform.consensus.ProgressInfo
import org.ergoplatform.modifiers.history.header.Header
import org.ergoplatform.modifiers.mempool.{ErgoTransaction, UnconfirmedTransaction}
import org.ergoplatform.modifiers.{BlockSection, ErgoFullBlock, NetworkObjectTypeId}
import org.ergoplatform.nodeView.history.ErgoHistory
import org.ergoplatform.nodeView.mempool.ErgoMemPool
-import org.ergoplatform.nodeView.mempool.ErgoMemPool.ProcessingOutcome
+import org.ergoplatform.nodeView.mempool.ErgoMemPoolUtils.ProcessingOutcome
import org.ergoplatform.nodeView.state._
import org.ergoplatform.nodeView.wallet.ErgoWallet
import org.ergoplatform.wallet.utils.FileUtils
-import org.ergoplatform.settings.{Algos, Constants, ErgoSettings, LaunchParameters, NetworkType}
-import scorex.core._
-import org.ergoplatform.network.ErgoNodeViewSynchronizer.ReceivableMessages._
+import org.ergoplatform.settings.{Algos, Constants, ErgoSettings, LaunchParameters, NetworkType, ScorexSettings}
+import org.ergoplatform.core._
+import org.ergoplatform.network.ErgoNodeViewSynchronizerMessages._
import org.ergoplatform.nodeView.ErgoNodeViewHolder.{BlockAppliedTransactions, CurrentView, DownloadRequest}
import org.ergoplatform.nodeView.ErgoNodeViewHolder.ReceivableMessages._
import org.ergoplatform.modifiers.history.{ADProofs, HistoryModifierSerializer}
-import scorex.core.consensus.ProgressInfo
-import scorex.core.settings.ScorexSettings
-import scorex.core.utils.ScorexEncoding
-import scorex.core.validation.RecoverableModifierError
+import org.ergoplatform.utils.ScorexEncoding
+import org.ergoplatform.validation.RecoverableModifierError
import scorex.util.{ModifierId, ScorexLogging}
import spire.syntax.all.cfor
@@ -618,7 +616,7 @@ abstract class ErgoNodeViewHolder[State <: ErgoState[State]](settings: ErgoSetti
val recoveredStateTry = firstExtensionOpt
.fold[Try[ErgoStateContext]](Failure(new Exception("Could not find extension to recover from"))
- )(ext => ErgoStateContext.recover(settings.chainSettings.genesisStateDigest, ext, lastHeaders)(settings))
+ )(ext => ErgoStateContext.recover(settings.chainSettings.genesisStateDigest, ext, lastHeaders)(settings.chainSettings))
.flatMap { ctx =>
val recoverVersion = idToVersion(lastHeaders.last.id)
val recoverRoot = bestFullBlock.header.stateRoot
@@ -737,8 +735,6 @@ object ErgoNodeViewHolder {
*/
case class RecheckedTransactions(unconfirmedTxs: Iterable[UnconfirmedTransaction])
- case class LocallyGeneratedModifier(pmod: BlockSection)
-
case class EliminateTransactions(ids: Seq[ModifierId])
case object IsChainHealthy
diff --git a/src/main/scala/org/ergoplatform/nodeView/ErgoReadersHolder.scala b/src/main/scala/org/ergoplatform/nodeView/ErgoReadersHolder.scala
index 339ae47b80..a7df32ee3f 100644
--- a/src/main/scala/org/ergoplatform/nodeView/ErgoReadersHolder.scala
+++ b/src/main/scala/org/ergoplatform/nodeView/ErgoReadersHolder.scala
@@ -8,7 +8,7 @@ import org.ergoplatform.nodeView.mempool.ErgoMemPoolReader
import org.ergoplatform.nodeView.state.ErgoStateReader
import org.ergoplatform.nodeView.wallet.ErgoWalletReader
import org.ergoplatform.nodeView.ErgoNodeViewHolder.ReceivableMessages._
-import org.ergoplatform.network.ErgoNodeViewSynchronizer.ReceivableMessages._
+import org.ergoplatform.network.ErgoNodeViewSynchronizerMessages._
import scorex.util.ScorexLogging
import scala.concurrent.duration._
diff --git a/src/main/scala/org/ergoplatform/nodeView/history/ErgoHistory.scala b/src/main/scala/org/ergoplatform/nodeView/history/ErgoHistory.scala
index dc63c806d3..c001dd8e64 100644
--- a/src/main/scala/org/ergoplatform/nodeView/history/ErgoHistory.scala
+++ b/src/main/scala/org/ergoplatform/nodeView/history/ErgoHistory.scala
@@ -1,9 +1,9 @@
package org.ergoplatform.nodeView.history
import akka.actor.ActorContext
+import org.ergoplatform.consensus.ProgressInfo
import java.io.File
-import org.ergoplatform.ErgoLikeContext
import org.ergoplatform.mining.AutolykosPowScheme
import org.ergoplatform.modifiers.history._
import org.ergoplatform.modifiers.history.header.{Header, PreGenesisHeader}
@@ -12,10 +12,9 @@ import org.ergoplatform.nodeView.history.extra.ExtraIndexer.ReceivableMessages.S
import org.ergoplatform.nodeView.history.extra.ExtraIndexer.{IndexedHeightKey, NewestVersion, NewestVersionBytes, SchemaVersionKey, getIndex}
import org.ergoplatform.nodeView.history.storage.HistoryStorage
import org.ergoplatform.nodeView.history.storage.modifierprocessors._
-import org.ergoplatform.settings._
+import org.ergoplatform.settings.ErgoSettings
import org.ergoplatform.utils.LoggingUtil
-import scorex.core.consensus.ProgressInfo
-import scorex.core.validation.RecoverableModifierError
+import org.ergoplatform.validation.RecoverableModifierError
import scorex.util.{ModifierId, ScorexLogging, idToBytes}
import scala.util.{Failure, Success, Try}
@@ -234,25 +233,6 @@ trait ErgoHistory
object ErgoHistory extends ScorexLogging {
- /**
- * Type for time, represents machine-specific timestamp of a transaction
- * or block section, as miliseconds passed since beginning of UNIX
- * epoch on the machine
- */
- type Time = Long
-
- type Height = ErgoLikeContext.Height // Int
- type Score = BigInt
- type Difficulty = BigInt
- type NBits = Long
-
- val CharsetName = "UTF-8"
-
- val EmptyHistoryHeight: Int = 0
- val GenesisHeight: Int = EmptyHistoryHeight + 1 // first block has height == 1
-
- def heightOf(headerOpt: Option[Header]): Int = headerOpt.map(_.height).getOrElse(EmptyHistoryHeight)
-
def historyDir(settings: ErgoSettings): File = {
val dir = new File(s"${settings.directory}/history")
dir.mkdirs()
@@ -314,26 +294,6 @@ object ErgoHistory extends ScorexLogging {
repairIfNeeded(history)
- // temporary hack which is injecting nipopow proof to the database to make it possible to bootstrap with
- // nipopows + utxo set snapshot soon after 5.0.13 release
- // todo: remove after height 1,096,693 on the mainnet
- val bestHeaderHeight = history.headersHeight
- if (bestHeaderHeight > 1054000 && bestHeaderHeight < 1096693 && history.readPopowProofBytesFromDb().isEmpty) {
- // we store nipopow proof for height 1,044,469 corresponding to UTXO set snapshot
- // @ # 1,044,479 already taken by 5.0.12 nodes
- val block1044469Id = "25a11667e38e62412522c062d90b073afd9ed9551080ff4e0a67d1757ce18b98"
- history.popowProofBytes(
- history.P2PNipopowProofM,
- history.P2PNipopowProofK,
- Some(ModifierId @@ block1044469Id)) match {
- case Success(proofBytes) =>
- log.info("Writing nipopow proof bytes for height 1,044,469")
- db.insert(Array(history.NipopowSnapshotHeightKey -> proofBytes), Array.empty[BlockSection])
- case Failure(e) =>
- log.warn("Can't dump NiPoPoW proof bytes for height 1,044,469", e)
- }
- }
-
log.info("History database read")
if(ergoSettings.nodeSettings.extraIndex) // start extra indexer, if enabled
context.system.eventStream.publish(StartExtraIndexer(history))
diff --git a/src/main/scala/org/ergoplatform/nodeView/history/ErgoHistoryReader.scala b/src/main/scala/org/ergoplatform/nodeView/history/ErgoHistoryReader.scala
index 7dfd9c9ba4..3fde451134 100644
--- a/src/main/scala/org/ergoplatform/nodeView/history/ErgoHistoryReader.scala
+++ b/src/main/scala/org/ergoplatform/nodeView/history/ErgoHistoryReader.scala
@@ -1,18 +1,18 @@
package org.ergoplatform.nodeView.history
+import org.ergoplatform.NodeViewComponent
+import org.ergoplatform.consensus.{ContainsModifiers, Equal, Fork, ModifierSemanticValidity, Older, PeerChainStatus, Unknown, Younger}
import org.ergoplatform.modifiers.history._
import org.ergoplatform.modifiers.history.extension.Extension
import org.ergoplatform.modifiers.history.header.{Header, PreGenesisHeader}
import org.ergoplatform.modifiers.{BlockSection, ErgoFullBlock, NetworkObjectTypeId, NonHeaderBlockSection}
-import org.ergoplatform.nodeView.history.ErgoHistory.Height
+import org.ergoplatform.nodeView.history.ErgoHistoryUtils.{EmptyHistoryHeight, GenesisHeight, Height}
import org.ergoplatform.nodeView.history.extra.ExtraIndex
import org.ergoplatform.nodeView.history.storage._
-import org.ergoplatform.nodeView.history.storage.modifierprocessors._
+import org.ergoplatform.nodeView.history.storage.modifierprocessors.{BlockSectionProcessor, HeadersProcessor}
import org.ergoplatform.settings.{ErgoSettings, NipopowSettings}
-import scorex.core.NodeViewComponent
-import scorex.core.consensus.{ContainsModifiers, Equal, Fork, ModifierSemanticValidity, Older, PeerChainStatus, Unknown, Younger}
-import scorex.core.utils.ScorexEncoding
-import scorex.core.validation.MalformedModifierError
+import org.ergoplatform.utils.ScorexEncoding
+import org.ergoplatform.validation.MalformedModifierError
import scorex.util.{ModifierId, ScorexLogging}
import scala.annotation.tailrec
@@ -247,8 +247,8 @@ trait ErgoHistoryReader
syncInfo.lastHeaderIds.map(b => Header.modifierTypeId -> b)
} else if (syncInfo.lastHeaderIds.isEmpty) {
// if other node has no headers yet, send up to `size` headers from genesis
- val heightTo = Math.min(headersHeight, size + ErgoHistory.EmptyHistoryHeight)
- (ErgoHistory.GenesisHeight to heightTo).flatMap { height =>
+ val heightTo = Math.min(headersHeight, size + EmptyHistoryHeight)
+ (GenesisHeight to heightTo).flatMap { height =>
bestHeaderIdAtHeight(height).map(id => Header.modifierTypeId -> id)
}
} else {
@@ -258,7 +258,7 @@ trait ErgoHistoryReader
.find(m => isInBestChain(m))
.orElse(if (ids.contains(PreGenesisHeader.id)) Some(PreGenesisHeader.id) else None)
branchingPointOpt.toSeq.flatMap { branchingPoint =>
- val otherNodeHeight = heightOf(branchingPoint).getOrElse(ErgoHistory.GenesisHeight)
+ val otherNodeHeight = heightOf(branchingPoint).getOrElse(GenesisHeight)
val heightTo = Math.min(headersHeight, otherNodeHeight + size - 1)
(otherNodeHeight to heightTo).flatMap { height =>
bestHeaderIdAtHeight(height).map(id => Header.modifierTypeId -> id)
@@ -274,8 +274,8 @@ trait ErgoHistoryReader
def continuationIdsV2(syncV2: ErgoSyncInfoV2, size: Int): ModifierIds = {
if (syncV2.lastHeaders.isEmpty) {
// if other node has no headers yet, send up to `size` headers from genesis
- val heightTo = Math.min(headersHeight, size + ErgoHistory.EmptyHistoryHeight)
- (ErgoHistory.GenesisHeight to heightTo)
+ val heightTo = Math.min(headersHeight, size + EmptyHistoryHeight)
+ (GenesisHeight to heightTo)
.flatMap(height => bestHeaderIdAtHeight(height))
.map(h => Header.modifierTypeId -> h) //todo: remove modifierTypeId ?
} else {
diff --git a/src/main/scala/org/ergoplatform/nodeView/history/extra/BalanceInfo.scala b/src/main/scala/org/ergoplatform/nodeView/history/extra/BalanceInfo.scala
index adbd35eecc..c15c5ebf09 100644
--- a/src/main/scala/org/ergoplatform/nodeView/history/extra/BalanceInfo.scala
+++ b/src/main/scala/org/ergoplatform/nodeView/history/extra/BalanceInfo.scala
@@ -4,7 +4,7 @@ import org.ergoplatform.{ErgoAddressEncoder, ErgoBox}
import org.ergoplatform.nodeView.history.ErgoHistoryReader
import org.ergoplatform.nodeView.history.extra.ExtraIndexer.fastIdToBytes
import org.ergoplatform.nodeView.history.extra.IndexedTokenSerializer.uniqueId
-import scorex.core.serialization.ErgoSerializer
+import org.ergoplatform.serialization.ErgoSerializer
import scorex.util.{ModifierId, ScorexLogging, bytesToId}
import scorex.util.serialization.{Reader, Writer}
import spire.implicits.cfor
diff --git a/src/main/scala/org/ergoplatform/nodeView/history/extra/ExtraIndex.scala b/src/main/scala/org/ergoplatform/nodeView/history/extra/ExtraIndex.scala
new file mode 100644
index 0000000000..3d5bc02fe5
--- /dev/null
+++ b/src/main/scala/org/ergoplatform/nodeView/history/extra/ExtraIndex.scala
@@ -0,0 +1,11 @@
+package org.ergoplatform.nodeView.history.extra
+
+import scorex.util.{ModifierId, bytesToId}
+
+/**
+ * Base trait for all additional indexes made by ExtraIndexer
+ */
+trait ExtraIndex {
+ lazy val id: ModifierId = bytesToId(serializedId)
+ def serializedId: Array[Byte]
+}
diff --git a/src/main/scala/org/ergoplatform/nodeView/history/extra/ExtraIndexSerializer.scala b/src/main/scala/org/ergoplatform/nodeView/history/extra/ExtraIndexSerializer.scala
index e8d1c37a33..45a703fad9 100644
--- a/src/main/scala/org/ergoplatform/nodeView/history/extra/ExtraIndexSerializer.scala
+++ b/src/main/scala/org/ergoplatform/nodeView/history/extra/ExtraIndexSerializer.scala
@@ -1,6 +1,6 @@
package org.ergoplatform.nodeView.history.extra
-import scorex.core.serialization.ErgoSerializer
+import org.ergoplatform.serialization.ErgoSerializer
import scorex.util.serialization.{Reader, Writer}
object ExtraIndexSerializer extends ErgoSerializer[ExtraIndex]{
diff --git a/src/main/scala/org/ergoplatform/nodeView/history/extra/ExtraIndexer.scala b/src/main/scala/org/ergoplatform/nodeView/history/extra/ExtraIndexer.scala
index f0b0e4e34c..dbda566f34 100644
--- a/src/main/scala/org/ergoplatform/nodeView/history/extra/ExtraIndexer.scala
+++ b/src/main/scala/org/ergoplatform/nodeView/history/extra/ExtraIndexer.scala
@@ -1,15 +1,15 @@
package org.ergoplatform.nodeView.history.extra
-import akka.actor.{Actor, ActorRef, ActorSystem, Props}
+import akka.actor.{Actor, ActorRef, ActorSystem, Props, Stash}
import org.ergoplatform.ErgoBox.TokenId
-import org.ergoplatform.{ErgoAddress, ErgoAddressEncoder, Pay2SAddress}
+import org.ergoplatform.{ErgoAddress, ErgoAddressEncoder, GlobalConstants, Pay2SAddress}
import org.ergoplatform.modifiers.history.BlockTransactions
import org.ergoplatform.modifiers.history.header.Header
import org.ergoplatform.modifiers.mempool.ErgoTransaction
-import org.ergoplatform.network.ErgoNodeViewSynchronizer.ReceivableMessages.{FullBlockApplied, Rollback}
-import org.ergoplatform.nodeView.history.extra.ExtraIndexer.{GlobalBoxIndexKey, GlobalTxIndexKey, IndexedHeightKey, getIndex}
+import org.ergoplatform.network.ErgoNodeViewSynchronizerMessages.{FullBlockApplied, Rollback}
+import org.ergoplatform.nodeView.history.extra.ExtraIndexer._
import org.ergoplatform.nodeView.history.{ErgoHistory, ErgoHistoryReader}
-import org.ergoplatform.nodeView.history.extra.ExtraIndexer.ReceivableMessages.{GetSegmentTreshold, StartExtraIndexer}
+import org.ergoplatform.nodeView.history.extra.ExtraIndexer.ReceivableMessages._
import org.ergoplatform.nodeView.history.extra.IndexedErgoAddressSerializer.hashErgoTree
import org.ergoplatform.nodeView.history.extra.IndexedTokenSerializer.uniqueId
import org.ergoplatform.nodeView.history.storage.HistoryStorage
@@ -22,79 +22,87 @@ import java.nio.ByteBuffer
import scala.collection.mutable.ArrayBuffer
import spire.syntax.all.cfor
+import java.util.concurrent.ConcurrentHashMap
import scala.collection.mutable
+import scala.collection.concurrent
+import scala.concurrent.{ExecutionContextExecutor, Future}
+import scala.jdk.CollectionConverters._
/**
* Base trait for extra indexer actor and its test.
*/
-trait ExtraIndexerBase extends ScorexLogging {
+trait ExtraIndexerBase extends Actor with Stash with ScorexLogging {
- /**
- * Indexed block height
- */
- protected var indexedHeight: Int = 0
-
- /**
- * Indexed transaction count
- */
- protected var globalTxIndex: Long = 0L
-
- /**
- * Indexed box count
- */
- protected var globalBoxIndex: Long = 0L
-
- /**
- * Last block height when buffer contents were saved to database
- */
- protected var lastWroteToDB: Int = 0
+ private implicit val ec: ExecutionContextExecutor = context.dispatcher
/**
- * Max buffer size (determined by config)
- */
+ * Max buffer size (determined by config)
+ */
protected val saveLimit: Int
/**
- * Number of transaction/box numberic indexes object segments contain
- */
- protected implicit val segmentTreshold: Int
+ * Number of transaction/box numeric indexes object segments contain
+ */
+ protected implicit val segmentThreshold: Int
/**
- * Address encoder instance
- */
+ * Address encoder instance
+ */
protected implicit val addressEncoder: ErgoAddressEncoder
/**
- * Flag to signal when indexer has reached current block height
- */
- protected var caughtUp: Boolean = false
-
- /**
- * Flag to signal a rollback
- */
- protected var rollback: Boolean = false
-
- /**
- * Database handle
- */
+ * Database handle
+ */
protected var _history: ErgoHistory = _
protected def chainHeight: Int = _history.fullBlockHeight
+
protected def history: ErgoHistoryReader = _history.getReader
+
protected def historyStorage: HistoryStorage = _history.historyStorage
// fast access buffers
protected val general: ArrayBuffer[ExtraIndex] = ArrayBuffer.empty[ExtraIndex]
- protected val boxes: mutable.HashMap[ModifierId,IndexedErgoBox] = mutable.HashMap.empty[ModifierId,IndexedErgoBox]
- protected val trees: mutable.HashMap[ModifierId,IndexedErgoAddress] = mutable.HashMap.empty[ModifierId,IndexedErgoAddress]
- protected val tokens: mutable.HashMap[ModifierId,IndexedToken] = mutable.HashMap.empty[ModifierId,IndexedToken]
- protected val segments: mutable.HashMap[ModifierId,Segment[_]] = mutable.HashMap.empty[ModifierId,Segment[_]]
+ protected val boxes: mutable.HashMap[ModifierId, IndexedErgoBox] = mutable.HashMap.empty[ModifierId, IndexedErgoBox]
+ protected val trees: mutable.HashMap[ModifierId, IndexedErgoAddress] = mutable.HashMap.empty[ModifierId, IndexedErgoAddress]
+ protected val tokens: mutable.HashMap[ModifierId, IndexedToken] = mutable.HashMap.empty[ModifierId, IndexedToken]
+ protected val segments: mutable.HashMap[ModifierId, Segment[_]] = mutable.HashMap.empty[ModifierId, Segment[_]]
/**
- * Input tokens in a transaction
- */
+ * Input tokens in a transaction, cleared after every transaction
+ */
private val inputTokens: ArrayBuffer[(TokenId, Long)] = ArrayBuffer.empty[(TokenId, Long)]
+ /**
+ * Holds upcoming blocks to be indexed, and when empty, it is filled back from multiple threads
+ */
+ private val blockCache: concurrent.Map[Int, BlockTransactions] = new ConcurrentHashMap[Int, BlockTransactions]().asScala
+ private var readingUpTo: Int = 0
+
+ /**
+ * Get transactions for specified height, preferably from cache, or from database.
+ * If indexer is getting close to emptying cache, asynchronously reads 1000 blocks into it
+ *
+ * @param height - blockheight to get transations from
+ * @return transactions at height
+ */
+ private def getBlockTransactionsAt(height: Int): BlockTransactions = {
+ val txs = blockCache.remove(height).getOrElse(history.bestBlockTransactionsAt(height).get)
+ if (height % 1000 == 0) blockCache.keySet.filter(_ < height).map(blockCache.remove)
+ if (readingUpTo - height < 300 && chainHeight - height > 1000) {
+ readingUpTo = math.min(height + 1001, chainHeight)
+ val blockNums = height + 1 to readingUpTo by 50
+ blockNums.zip(blockNums.tail).map { range => // ranges of 50 blocks for each thread to read
+ Future {
+ (range._1 until range._2).foreach { blockNum =>
+ blockCache.put(blockNum, history.bestBlockTransactionsAt(blockNum).get)
+ }
+ }
+ }
+ }
+ txs
+ }
+
/**
* Spend an IndexedErgoBox from buffer or database. Also record tokens for later use in balance tracking logic.
*
@@ -125,34 +133,34 @@ trait ExtraIndexerBase extends ScorexLogging {
* @param id - hash of the (ergotree) address
* @param spendOrReceive - IndexedErgoBox to receive (Right) or spend (Left)
*/
- private def findAndUpdateTree(id: ModifierId, spendOrReceive: Either[IndexedErgoBox, IndexedErgoBox]): Unit = {
+ private def findAndUpdateTree(id: ModifierId, spendOrReceive: Either[IndexedErgoBox, IndexedErgoBox])(implicit state: IndexerState): Unit = {
trees.get(id).map { tree =>
spendOrReceive match {
- case Left(iEb) => tree.addTx(globalTxIndex).spendBox(iEb, Some(history)) // spend box
- case Right(iEb) => tree.addTx(globalTxIndex).addBox(iEb) // receive box
+ case Left(iEb) => tree.addTx(state.globalTxIndex).spendBox(iEb, Some(history)) // spend box
+ case Right(iEb) => tree.addTx(state.globalTxIndex).addBox(iEb) // receive box
}
return
}
history.typedExtraIndexById[IndexedErgoAddress](id) match { // address not found in last saveLimit modifiers
case Some(x) =>
spendOrReceive match {
- case Left(iEb) => trees.put(id, x.addTx(globalTxIndex).spendBox(iEb, Some(history))) // spend box
- case Right(iEb) => trees.put(id, x.addTx(globalTxIndex).addBox(iEb)) // receive box
+ case Left(iEb) => trees.put(id, x.addTx(state.globalTxIndex).spendBox(iEb, Some(history))) // spend box
+ case Right(iEb) => trees.put(id, x.addTx(state.globalTxIndex).addBox(iEb)) // receive box
}
case None => // address not found at all
spendOrReceive match {
case Left(iEb) => log.warn(s"Unknown address spent box ${bytesToId(iEb.box.id)}") // spend box should never happen by an unknown address
- case Right(iEb) => trees.put(id, IndexedErgoAddress(id).initBalance.addTx(globalTxIndex).addBox(iEb)) // receive box, new address
+ case Right(iEb) => trees.put(id, IndexedErgoAddress(id).initBalance.addTx(state.globalTxIndex).addBox(iEb)) // receive box, new address
}
}
}
/**
- * Add or subtract a box from a token in the buffer or in database.
- *
- * @param id - token id
- * @param spendOrReceive - IndexedErgoBox to receive (Right) or spend (Left)
- */
+ * Add or subtract a box from a token in the buffer or in database.
+ *
+ * @param id - token id
+ * @param spendOrReceive - IndexedErgoBox to receive (Right) or spend (Left)
+ */
private def findAndUpdateToken(id: ModifierId, spendOrReceive: Either[IndexedErgoBox, IndexedErgoBox]): Unit = {
tokens.get(id).map { token =>
spendOrReceive match {
@@ -180,38 +188,36 @@ trait ExtraIndexerBase extends ScorexLogging {
/**
* Write buffered indexes to database and clear buffers.
*/
- private def saveProgress(writeLog: Boolean = true): Unit = {
+ private def saveProgress(state: IndexerState, writeLog: Boolean = true): Unit = {
val start: Long = System.currentTimeMillis
// perform segmentation on big addresses and save their internal segment buffer
trees.values.foreach { tree =>
- if(tree.buffer.nonEmpty) {
- tree.buffer.values.foreach(seg => segments.put(seg.id, seg))
- tree.buffer.clear()
- }
- if(tree.txs.length > segmentTreshold || tree.boxes.length > segmentTreshold)
- tree.splitToSegments.foreach(seg => segments.put(seg.id, seg))
+ tree.buffer.values.foreach(seg => segments.put(seg.id, seg))
+ tree.splitToSegments.foreach(seg => segments.put(seg.id, seg))
}
// perform segmentation on big tokens and save their internal segment buffer
tokens.values.foreach { token =>
- if(token.buffer.nonEmpty) {
- token.buffer.values.foreach(seg => segments.put(seg.id, seg))
- token.buffer.clear()
- }
- if(token.boxes.length > segmentTreshold)
- token.splitToSegments.foreach(seg => segments.put(seg.id, seg))
+ token.buffer.values.foreach(seg => segments.put(seg.id, seg))
+ token.splitToSegments.foreach(seg => segments.put(seg.id, seg))
}
// insert modifiers and progress info to db
- historyStorage.insertExtra(Array((IndexedHeightKey, ByteBuffer.allocate(4).putInt(indexedHeight).array),
- (GlobalTxIndexKey, ByteBuffer.allocate(8).putLong(globalTxIndex).array),
- (GlobalBoxIndexKey,ByteBuffer.allocate(8).putLong(globalBoxIndex).array)),
- ((((general ++= boxes.values) ++= trees.values) ++= tokens.values) ++= segments.values).toArray)
-
- if (writeLog)
+ historyStorage.insertExtra(
+ Array(
+ (IndexedHeightKey, ByteBuffer.allocate(4).putInt(state.indexedHeight).array),
+ (GlobalTxIndexKey, ByteBuffer.allocate(8).putLong(state.globalTxIndex).array),
+ (GlobalBoxIndexKey, ByteBuffer.allocate(8).putLong(state.globalBoxIndex).array),
+ (RollbackToKey, ByteBuffer.allocate(4).putInt(state.rollbackTo).array)
+ ),
+ ((((general ++= boxes.values) ++= trees.values) ++= tokens.values) ++= segments.values).toArray
+ )
+
+ if (writeLog) {
log.info(s"Processed ${trees.size} ErgoTrees with ${boxes.size} boxes and inserted them to database in ${System.currentTimeMillis - start}ms")
+ }
// clear buffers for next batch
general.clear()
@@ -219,29 +225,29 @@ trait ExtraIndexerBase extends ScorexLogging {
trees.clear()
tokens.clear()
segments.clear()
-
- lastWroteToDB = indexedHeight
}
/**
* Process a batch of BlockTransactions into memory and occasionally write them to database.
*
- * @param bt - BlockTransaction to process
- * @param height - height of the block containing the transactions
+ * @param state - current indexer state
+ * @param headerOpt - header to index blocktransactions of (used after caught up with chain)
*/
- protected def index(bt: BlockTransactions, height: Int): Unit = {
-
- if (rollback || // rollback in progress
- (caughtUp && height <= indexedHeight)) // do not process older blocks again after caught up (due to actor message queue)
- return
+ protected def index(state: IndexerState, headerOpt: Option[Header] = None): IndexerState = {
+ val bt = headerOpt.flatMap { header =>
+ history.typedModifierById[BlockTransactions](header.transactionsId)
+ }.getOrElse(getBlockTransactionsAt(state.indexedHeight))
+ val height = headerOpt.map(_.height).getOrElse(state.indexedHeight)
var boxCount: Int = 0
+ implicit var newState: IndexerState = state
// record transactions and boxes
cfor(0)(_ < bt.txs.length, _ + 1) { n =>
val tx: ErgoTransaction = bt.txs(n)
val inputs: Array[Long] = Array.ofDim[Long](tx.inputs.length)
+ val outputs: Array[Long] = Array.ofDim[Long](tx.outputs.length)
inputTokens.clear()
@@ -262,156 +268,182 @@ trait ExtraIndexerBase extends ScorexLogging {
//process transaction outputs
cfor(0)(_ < tx.outputs.size, _ + 1) { i =>
- val iEb: IndexedErgoBox = new IndexedErgoBox(height, None, None, tx.outputs(i), globalBoxIndex)
+ val iEb: IndexedErgoBox = new IndexedErgoBox(height, None, None, tx.outputs(i), newState.globalBoxIndex)
boxes.put(iEb.id, iEb) // box by id
- general += NumericBoxIndex(globalBoxIndex, iEb.id) // box id by global box number
+ general += NumericBoxIndex(newState.globalBoxIndex, iEb.id) // box id by global box number
+ outputs(i) = iEb.globalIndex
// box by address
findAndUpdateTree(hashErgoTree(iEb.box.ergoTree), Right(boxes(iEb.id)))
// check if box is creating new tokens, if yes record them
cfor(0)(_ < iEb.box.additionalTokens.length, _ + 1) { j =>
- if (!inputTokens.exists(x => x._1 == iEb.box.additionalTokens(j)._1)) {
+ if (!inputTokens.exists(x => java.util.Arrays.equals(x._1.toArray, iEb.box.additionalTokens(j)._1.toArray))) {
val token = IndexedToken.fromBox(iEb, j)
tokens.get(token.tokenId) match {
case Some(t) => // same new token created in multiple boxes -> add amounts
- val newToken = IndexedToken(t.tokenId, t.boxId, t.amount + token.amount, t.name, t.description, t.decimals, t.boxes)
- newToken.buffer ++= t.buffer
- tokens.put(token.tokenId, newToken)
+ tokens.put(token.tokenId, t.addEmissionAmount(token.amount))
case None => tokens.put(token.tokenId, token) // new token
}
}
findAndUpdateToken(iEb.box.additionalTokens(j)._1.toModifierId, Right(iEb))
}
- globalBoxIndex += 1
+ newState = newState.incrementBoxIndex
boxCount += 1
}
//process transaction
- general += IndexedErgoTransaction(tx.id, height, globalTxIndex, inputs)
- general += NumericTxIndex(globalTxIndex, tx.id)
+ general += IndexedErgoTransaction.fromTx(tx, n, height, newState.globalTxIndex, inputs, outputs)
+ general += NumericTxIndex(newState.globalTxIndex, tx.id)
- globalTxIndex += 1
+ newState = newState.incrementTxIndex
}
log.info(s"Buffered block $height / $chainHeight [txs: ${bt.txs.length}, boxes: $boxCount] (buffer: $modCount / $saveLimit)")
- if (caughtUp) {
-
- indexedHeight = height // update height here after caught up with chain
-
- if (modCount >= saveLimit || // modifier limit reached to write to db
- history.fullBlockHeight == history.headersHeight) // write to db every block after chain synced
- saveProgress()
-
- } else if (modCount >= saveLimit)
- saveProgress() // active syncing, write to db after modifier limit
-
- }
-
- /**
- * Main indexer loop that tries to catch up with the already present blocks in database.
- */
- protected def run(): Unit = {
-
- indexedHeight = getIndex(IndexedHeightKey, history).getInt
- globalTxIndex = getIndex(GlobalTxIndexKey, history).getLong
- globalBoxIndex = getIndex(GlobalBoxIndexKey, history).getLong
-
- log.info(s"Started extra indexer at height $indexedHeight")
-
- while (indexedHeight < chainHeight && !rollback) {
- indexedHeight += 1
- index(history.bestBlockTransactionsAt(indexedHeight).get, indexedHeight)
- }
-
- saveProgress(false) // flush any remaining data
-
- if (rollback)
- log.info("Stopping indexer to perform rollback")
- else {
- caughtUp = true
- log.info("Indexer caught up with chain")
- }
-
+ val maxHeight = headerOpt.map(_.height).getOrElse(chainHeight)
+ newState.copy(caughtUp = newState.indexedHeight == maxHeight)
}
/**
* Remove all indexes after a given height and revert address balances.
*
+ * @param state - current state of indexer
* @param height - starting height
*/
- protected def removeAfter(height: Int): Unit = {
+ protected def removeAfter(state: IndexerState, height: Int): IndexerState = {
- saveProgress(false)
- log.info(s"Rolling back indexes from $indexedHeight to $height")
+ var newState: IndexerState = state
- val lastTxToKeep: ErgoTransaction = history.bestBlockTransactionsAt(height).get.txs.last
- val txTarget: Long = history.typedExtraIndexById[IndexedErgoTransaction](lastTxToKeep.id).get.globalIndex
- val boxTarget: Long = history.typedExtraIndexById[IndexedErgoBox](bytesToId(lastTxToKeep.outputs.last.id)).get.globalIndex
- val toRemove: ArrayBuffer[ModifierId] = ArrayBuffer.empty[ModifierId]
+ saveProgress(newState, writeLog = false)
+ log.info(s"Rolling back indexes from ${state.indexedHeight} to $height")
- // remove all tx indexes
- globalTxIndex -= 1
- while(globalTxIndex > txTarget) {
- val tx: IndexedErgoTransaction = NumericTxIndex.getTxByNumber(history, globalTxIndex).get
- tx.inputNums.map(NumericBoxIndex.getBoxByNumber(history, _).get).foreach { iEb => // undo all spendings
+ try {
+ val lastTxToKeep: ErgoTransaction = history.bestBlockTransactionsAt(height).get.txs.last
+ val txTarget: Long = history.typedExtraIndexById[IndexedErgoTransaction](lastTxToKeep.id).get.globalIndex
+ val boxTarget: Long = history.typedExtraIndexById[IndexedErgoBox](bytesToId(lastTxToKeep.outputs.last.id)).get.globalIndex
+ val toRemove: ArrayBuffer[ModifierId] = ArrayBuffer.empty[ModifierId]
- iEb.spendingHeightOpt = None
- iEb.spendingTxIdOpt = None
+ // remove all tx indexes
+ newState = newState.decrementTxIndex
+ while (newState.globalTxIndex > txTarget) {
+ val tx: IndexedErgoTransaction = NumericTxIndex.getTxByNumber(history, newState.globalTxIndex).get
+ tx.inputNums.map(NumericBoxIndex.getBoxByNumber(history, _).get).foreach { iEb => // undo all spendings
- val address = history.typedExtraIndexById[IndexedErgoAddress](hashErgoTree(iEb.box.ergoTree)).get.addBox(iEb, record = false)
- address.findAndModBox(iEb.globalIndex, history)
- historyStorage.insertExtra(Array.empty, Array[ExtraIndex](iEb, address) ++ address.buffer.values)
+ iEb.spendingHeightOpt = None
+ iEb.spendingTxIdOpt = None
+
+ val address = history.typedExtraIndexById[IndexedErgoAddress](hashErgoTree(iEb.box.ergoTree)).get.addBox(iEb, record = false)
+ address.findAndModBox(iEb.globalIndex, history)
+ historyStorage.insertExtra(Array.empty, Array[ExtraIndex](iEb, address) ++ address.buffer.values)
+
+ cfor(0)(_ < iEb.box.additionalTokens.length, _ + 1) { i =>
+ history.typedExtraIndexById[IndexedToken](IndexedToken.fromBox(iEb, i).id).map { token =>
+ token.findAndModBox(iEb.globalIndex, history)
+ historyStorage.insertExtra(Array.empty, Array[ExtraIndex](token) ++ token.buffer.values)
+ }
+ }
+ }
+ toRemove += tx.id // tx by id
+ toRemove += bytesToId(NumericTxIndex.indexToBytes(newState.globalTxIndex)) // tx id by number
+ newState = newState.decrementTxIndex
+ }
+ newState = newState.incrementTxIndex
+ // remove all box indexes, tokens and address balances
+ newState = newState.decrementBoxIndex
+ while (newState.globalBoxIndex > boxTarget) {
+ val iEb: IndexedErgoBox = NumericBoxIndex.getBoxByNumber(history, newState.globalBoxIndex).get
cfor(0)(_ < iEb.box.additionalTokens.length, _ + 1) { i =>
history.typedExtraIndexById[IndexedToken](IndexedToken.fromBox(iEb, i).id).map { token =>
- token.findAndModBox(iEb.globalIndex, history)
- historyStorage.insertExtra(Array.empty, Array[ExtraIndex](token) ++ token.buffer.values)
+ if (token.boxId == iEb.id) { // token created, delete
+ toRemove += token.id
+ log.info(s"Removing token ${token.tokenId} created in box ${iEb.id} at height ${iEb.inclusionHeight}")
+ } else // no token created, update
+ toRemove ++= token.rollback(txTarget, boxTarget, _history)
}
}
+ history.typedExtraIndexById[IndexedErgoAddress](hashErgoTree(iEb.box.ergoTree)).map { address =>
+ address.spendBox(iEb)
+ toRemove ++= address.rollback(txTarget, boxTarget, _history)
+ }
+ toRemove += iEb.id // box by id
+ toRemove += bytesToId(NumericBoxIndex.indexToBytes(newState.globalBoxIndex)) // box id by number
+ newState = newState.decrementBoxIndex
}
- toRemove += tx.id // tx by id
- toRemove += bytesToId(NumericTxIndex.indexToBytes(globalTxIndex)) // tx id by number
- globalTxIndex -= 1
+ newState = newState.incrementBoxIndex
+
+ // Save changes
+ newState = newState.copy(indexedHeight = height, rollbackTo = 0, caughtUp = true)
+ historyStorage.removeExtra(toRemove.toArray)
+ saveProgress(newState, writeLog = false)
+ } catch {
+ case t: Throwable => log.error(s"removeAfter during rollback failed due to: ${t.getMessage}", t)
}
- globalTxIndex += 1
-
- // remove all box indexes, tokens and address balances
- globalBoxIndex -= 1
- while(globalBoxIndex > boxTarget) {
- val iEb: IndexedErgoBox = NumericBoxIndex.getBoxByNumber(history, globalBoxIndex).get
- cfor(0)(_ < iEb.box.additionalTokens.length, _ + 1) { i =>
- history.typedExtraIndexById[IndexedToken](IndexedToken.fromBox(iEb, i).id).map { token =>
- if(token.boxId == iEb.id) // token created, delete
- toRemove += token.id
- else // no token created, update
- toRemove ++= token.rollback(txTarget, boxTarget, _history)
+
+ newState
+ }
+
+ protected def loaded(state: IndexerState): Receive = {
+
+ case Index() if !state.caughtUp && !state.rollbackInProgress =>
+ val newState = index(state.incrementIndexedHeight)
+ if (modCount >= saveLimit) saveProgress(newState)
+ context.become(loaded(newState))
+ self ! Index()
+
+ case Index() if state.caughtUp =>
+ if (modCount > 0) saveProgress(state)
+ blockCache.clear()
+ log.info("Indexer caught up with chain")
+
+ // after the indexer caught up with the chain, stay up to date
+ case FullBlockApplied(header: Header) if state.caughtUp && !state.rollbackInProgress =>
+ if (header.height == state.indexedHeight + 1) { // applied block is next in line
+ val newState: IndexerState = index(state.incrementIndexedHeight, Some(header))
+ saveProgress(newState)
+ context.become(loaded(newState))
+ } else if(header.height > state.indexedHeight + 1) { // applied block is ahead of indexer
+ context.become(loaded(state.copy(caughtUp = false)))
+ self ! Index()
+ } else // applied block has already been indexed, skipping duplicate
+ log.warn(s"Skipping block ${header.id} applied at height ${header.height}, indexed height is ${state.indexedHeight}")
+
+ case Rollback(branchPoint: ModifierId) =>
+ if (state.rollbackInProgress) {
+ log.warn(s"Rollback already in progress")
+ stash()
+ } else {
+ history.heightOf(branchPoint) match {
+ case Some(branchHeight) =>
+ if (branchHeight < state.indexedHeight) {
+ context.become (loaded (state.copy (rollbackTo = branchHeight) ) )
+ self ! RemoveAfter (branchHeight)
+ }
+ case None =>
+ log.error(s"No rollback height found for $branchPoint")
+ val newState = state.copy(rollbackTo = 0)
+ context.become(loaded(newState))
+ unstashAll()
}
}
- history.typedExtraIndexById[IndexedErgoAddress](hashErgoTree(iEb.box.ergoTree)).map { address =>
- address.spendBox(iEb)
- toRemove ++= address.rollback(txTarget, boxTarget, _history)
- }
- toRemove += iEb.id // box by id
- toRemove += bytesToId(NumericBoxIndex.indexToBytes(globalBoxIndex)) // box id by number
- globalBoxIndex -= 1
- }
- globalBoxIndex += 1
- // Reset indexer flags
- indexedHeight = height
- caughtUp = false
- rollback = false
+ case RemoveAfter(branchHeight: Int) if state.rollbackInProgress =>
+ blockCache.clear()
+ readingUpTo = 0
+ val newState = removeAfter(state, branchHeight)
+ context.become(loaded(newState))
+ log.info(s"Successfully rolled back indexes to $branchHeight")
+ unstashAll()
+
+ case GetSegmentThreshold =>
+ sender ! segmentThreshold
- // Save changes
- saveProgress(false)
- historyStorage.removeExtra(toRemove.toArray)
+ case _ =>
- log.info(s"Successfully rolled back indexes to $height")
}
}
@@ -419,16 +451,17 @@ trait ExtraIndexerBase extends ScorexLogging {
/**
* Actor that constructs an index of database elements.
+ *
* @param cacheSettings - cacheSettings to use for saveLimit size
- * @param ae - ergo address encoder to use for handling addresses
+ * @param ae - ergo address encoder to use for handling addresses
*/
class ExtraIndexer(cacheSettings: CacheSettings,
ae: ErgoAddressEncoder)
- extends Actor with ExtraIndexerBase {
+ extends ExtraIndexerBase {
override val saveLimit: Int = cacheSettings.history.extraCacheSize * 20
- override implicit val segmentTreshold: Int = 512
+ override implicit val segmentThreshold: Int = 512
override implicit val addressEncoder: ErgoAddressEncoder = ae
@@ -438,28 +471,28 @@ class ExtraIndexer(cacheSettings: CacheSettings,
context.system.eventStream.subscribe(self, classOf[StartExtraIndexer])
}
- override def postStop(): Unit =
- log.info(s"Stopped extra indexer at height ${if(lastWroteToDB > 0) lastWroteToDB else indexedHeight}")
-
- override def receive: Receive = {
+ override def postStop(): Unit = {
+ log.error(s"Stopped extra indexer")
+ super.postStop()
+ }
- case FullBlockApplied(header: Header) if caughtUp =>
- index(history.typedModifierById[BlockTransactions](header.transactionsId).get, header.height) // after the indexer caught up with the chain, stay up to date
+ override def preRestart(reason: Throwable, message: Option[Any]): Unit = {
+ log.error(s"Attempted extra indexer restart due to ${reason.getMessage} ", reason)
+ super.preRestart(reason, message)
+ }
- case Rollback(branchPoint: ModifierId) if _history != null => // only rollback if indexing is enabled
- val branchHeight: Int = history.heightOf(branchPoint).get
- rollback = branchHeight < indexedHeight
- if(rollback) {
- removeAfter(branchHeight)
- run() // restart indexer
- }
+ override def receive: Receive = {
case StartExtraIndexer(history: ErgoHistory) =>
_history = history
- run()
+ val state = IndexerState.fromHistory(history)
+ context.become(loaded(state))
+ log.info(s"Started extra indexer at height ${state.indexedHeight}")
+ self ! Index()
+ unstashAll()
+
+ case _ => stash()
- case GetSegmentTreshold =>
- sender ! segmentTreshold
}
}
@@ -470,6 +503,7 @@ object ExtraIndexer {
object ReceivableMessages {
/**
* Initialize ExtraIndexer and start indexing.
+ *
* @param history - handle to database
*/
case class StartExtraIndexer(history: ErgoHistory)
@@ -477,7 +511,19 @@ object ExtraIndexer {
/**
* Retreive the currently used segment treshold
*/
- case class GetSegmentTreshold()
+ case class GetSegmentThreshold()
+
+ /**
+ * Index block at current indexer height
+ */
+ case class Index()
+
+ /**
+ * Remove and roll back all indexes after branchHeight
+ *
+ * @param branchHeight - height of last block to keep
+ */
+ case class RemoveAfter(branchHeight: Int)
}
/**
@@ -494,7 +540,7 @@ object ExtraIndexer {
"0123456789abcdef".toCharArray.zipWithIndex.foreach { case (c, i) =>
index(c) = i.toByte
}
- "abcdef".toCharArray.foreach{ c =>
+ "abcdef".toCharArray.foreach { c =>
index(c.toUpper) = index(c)
}
index
@@ -502,39 +548,37 @@ object ExtraIndexer {
/**
* Faster id to bytes - no safety checks
+ *
* @param id - ModifierId to convert to byte representation
* @return an array of bytes
*/
private[extra] def fastIdToBytes(id: ModifierId): Array[Byte] = {
val x: Array[Byte] = new Array[Byte](id.length / 2)
- cfor(0)(_ < id.length, _ + 2) {i => x(i / 2) = ((hexIndex(id(i)) << 4) | hexIndex(id(i + 1))).toByte}
+ cfor(0)(_ < id.length, _ + 2) { i => x(i / 2) = ((hexIndex(id(i)) << 4) | hexIndex(id(i + 1))).toByte }
x
}
/**
- * Current newest database schema version. Used to force extra database resync.
- */
- val NewestVersion: Int = 4
+ * Current newest database schema version. Used to force extra database resync.
+ */
+ val NewestVersion: Int = 5
val NewestVersionBytes: Array[Byte] = ByteBuffer.allocate(4).putInt(NewestVersion).array
val IndexedHeightKey: Array[Byte] = Algos.hash("indexed height")
val GlobalTxIndexKey: Array[Byte] = Algos.hash("txns height")
val GlobalBoxIndexKey: Array[Byte] = Algos.hash("boxes height")
+ val RollbackToKey: Array[Byte] = Algos.hash("rollback to")
val SchemaVersionKey: Array[Byte] = Algos.hash("schema version")
def getIndex(key: Array[Byte], history: HistoryStorage): ByteBuffer =
- ByteBuffer.wrap(history.modifierBytesById(bytesToId(key)).getOrElse(Array.fill[Byte](8){0}))
+ ByteBuffer.wrap(history.modifierBytesById(bytesToId(key)).getOrElse(Array.fill[Byte](8) {
+ 0
+ }))
def getIndex(key: Array[Byte], history: ErgoHistoryReader): ByteBuffer = getIndex(key, history.historyStorage)
- def apply(chainSettings: ChainSettings, cacheSettings: CacheSettings)(implicit system: ActorSystem): ActorRef =
- system.actorOf(Props.create(classOf[ExtraIndexer], cacheSettings, chainSettings.addressEncoder))
-}
-
-/**
- * Base trait for all additional indexes made by ExtraIndexer
- */
-trait ExtraIndex {
- lazy val id: ModifierId = bytesToId(serializedId)
- def serializedId: Array[Byte]
+ def apply(chainSettings: ChainSettings, cacheSettings: CacheSettings)(implicit system: ActorSystem): ActorRef = {
+ val props = Props.create(classOf[ExtraIndexer], cacheSettings, chainSettings.addressEncoder)
+ system.actorOf(props.withDispatcher(GlobalConstants.IndexerDispatcher))
+ }
}
diff --git a/src/main/scala/org/ergoplatform/nodeView/history/extra/IndexedErgoAddress.scala b/src/main/scala/org/ergoplatform/nodeView/history/extra/IndexedErgoAddress.scala
index f7408a497a..c95acc381d 100644
--- a/src/main/scala/org/ergoplatform/nodeView/history/extra/IndexedErgoAddress.scala
+++ b/src/main/scala/org/ergoplatform/nodeView/history/extra/IndexedErgoAddress.scala
@@ -5,7 +5,7 @@ import org.ergoplatform.nodeView.history.{ErgoHistory, ErgoHistoryReader}
import org.ergoplatform.nodeView.history.extra.ExtraIndexer.{ExtraIndexTypeId, fastIdToBytes}
import org.ergoplatform.nodeView.history.extra.IndexedErgoAddressSerializer.hashErgoTree
import org.ergoplatform.settings.Algos
-import scorex.core.serialization.ErgoSerializer
+import org.ergoplatform.serialization.ErgoSerializer
import scorex.util.{ModifierId, bytesToId}
import scorex.util.serialization.{Reader, Writer}
import sigmastate.Values.ErgoTree
diff --git a/src/main/scala/org/ergoplatform/nodeView/history/extra/IndexedErgoBox.scala b/src/main/scala/org/ergoplatform/nodeView/history/extra/IndexedErgoBox.scala
index 1e1ad79c44..abb4318d2d 100644
--- a/src/main/scala/org/ergoplatform/nodeView/history/extra/IndexedErgoBox.scala
+++ b/src/main/scala/org/ergoplatform/nodeView/history/extra/IndexedErgoBox.scala
@@ -3,7 +3,7 @@ package org.ergoplatform.nodeView.history.extra
import org.ergoplatform.ErgoBox
import org.ergoplatform.nodeView.history.extra.ExtraIndexer.{ExtraIndexTypeId, fastIdToBytes}
import org.ergoplatform.wallet.boxes.ErgoBoxSerializer
-import scorex.core.serialization.ErgoSerializer
+import org.ergoplatform.serialization.ErgoSerializer
import scorex.util.{ModifierId, bytesToId}
import scorex.util.serialization.{Reader, Writer}
diff --git a/src/main/scala/org/ergoplatform/nodeView/history/extra/IndexedErgoTransaction.scala b/src/main/scala/org/ergoplatform/nodeView/history/extra/IndexedErgoTransaction.scala
index 8b35587686..963365a03c 100644
--- a/src/main/scala/org/ergoplatform/nodeView/history/extra/IndexedErgoTransaction.scala
+++ b/src/main/scala/org/ergoplatform/nodeView/history/extra/IndexedErgoTransaction.scala
@@ -3,9 +3,10 @@ package org.ergoplatform.nodeView.history.extra
import org.ergoplatform.modifiers.history.header.Header
import org.ergoplatform.nodeView.history.ErgoHistoryReader
import org.ergoplatform.DataInput
-import org.ergoplatform.modifiers.history.BlockTransactions
+import org.ergoplatform.modifiers.mempool.ErgoTransaction
import org.ergoplatform.nodeView.history.extra.ExtraIndexer.{ExtraIndexTypeId, fastIdToBytes}
-import scorex.core.serialization.ErgoSerializer
+import org.ergoplatform.serialization.ErgoSerializer
+import scorex.crypto.authds.ADKey
import scorex.util.serialization.{Reader, Writer}
import scorex.util.{ModifierId, bytesToId}
import spire.implicits.cfor
@@ -13,14 +14,21 @@ import spire.implicits.cfor
/**
* Minimum general information for transaction. Not storing the whole transation is done to save space.
* @param txid - id of this transaction
+ * @param index - index of transaction in parent block
* @param height - height of the block which includes this transaction
+ * @param size - size of this transaction in bytes
* @param globalIndex - serial number of this transaction counting from block 1
- * @param inputNums - list of transaction inputs (needed for rollback)
+ * @param inputNums - list of transaction inputs
+ * @param outputNums - list of transaction outputs
*/
case class IndexedErgoTransaction(txid: ModifierId,
+ index: Int,
height: Int,
+ size: Int,
globalIndex: Long,
- inputNums: Array[Long]) extends ExtraIndex {
+ inputNums: Array[Long],
+ outputNums: Array[Long],
+ dataInputs: Array[DataInput]) extends ExtraIndex {
override lazy val id: ModifierId = txid
override def serializedId: Array[Byte] = fastIdToBytes(id)
@@ -28,22 +36,16 @@ case class IndexedErgoTransaction(txid: ModifierId,
private var _blockId: ModifierId = ModifierId @@ ""
private var _inclusionHeight: Int = 0
private var _timestamp: Header.Timestamp = 0L
- private var _index: Int = 0
private var _numConfirmations: Int = 0
private var _inputs: IndexedSeq[IndexedErgoBox] = IndexedSeq.empty[IndexedErgoBox]
- private var _dataInputs: IndexedSeq[DataInput] = IndexedSeq.empty[DataInput]
private var _outputs: IndexedSeq[IndexedErgoBox] = IndexedSeq.empty[IndexedErgoBox]
- private var _txSize: Int = 0
def blockId: ModifierId = _blockId
def inclusionHeight: Int = _inclusionHeight
def timestamp: Header.Timestamp = _timestamp
- def index: Int = _index
def numConfirmations: Int = _numConfirmations
def inputs: IndexedSeq[IndexedErgoBox] = _inputs
- def dataInputs: IndexedSeq[DataInput] = _dataInputs
def outputs: IndexedSeq[IndexedErgoBox] = _outputs
- def txSize: Int = _txSize
/**
* Get all information related to this transaction from database.
@@ -53,17 +55,13 @@ case class IndexedErgoTransaction(txid: ModifierId,
def retrieveBody(history: ErgoHistoryReader): IndexedErgoTransaction = {
val header: Header = history.typedModifierById[Header](history.bestHeaderIdAtHeight(height).get).get
- val blockTxs: BlockTransactions = history.typedModifierById[BlockTransactions](header.transactionsId).get
_blockId = header.id
_inclusionHeight = height
_timestamp = header.timestamp
- _index = blockTxs.txs.indices.find(blockTxs.txs(_).id == txid).get
- _numConfirmations = history.bestFullBlockOpt.get.height - height
- _inputs = blockTxs.txs(_index).inputs.map(input => history.typedExtraIndexById[IndexedErgoBox](bytesToId(input.boxId)).get)
- _dataInputs = blockTxs.txs(_index).dataInputs
- _outputs = blockTxs.txs(_index).outputs.map(output => history.typedExtraIndexById[IndexedErgoBox](bytesToId(output.id)).get)
- _txSize = blockTxs.txs(_index).size
+ _numConfirmations = history.fullBlockHeight - height
+ _inputs = inputNums.flatMap(NumericBoxIndex.getBoxByNumber(history, _))
+ _outputs = outputNums.flatMap(NumericBoxIndex.getBoxByNumber(history, _))
this
}
@@ -74,24 +72,41 @@ object IndexedErgoTransactionSerializer extends ErgoSerializer[IndexedErgoTransa
override def serialize(iTx: IndexedErgoTransaction, w: Writer): Unit = {
w.putUByte(iTx.serializedId.length)
w.putBytes(iTx.serializedId)
+ w.putInt(iTx.index)
w.putInt(iTx.height)
+ w.putInt(iTx.size)
w.putLong(iTx.globalIndex)
w.putUShort(iTx.inputNums.length)
cfor(0)(_ < iTx.inputNums.length, _ + 1) { i => w.putLong(iTx.inputNums(i)) }
+ w.putUShort(iTx.outputNums.length)
+ cfor(0)(_ < iTx.outputNums.length, _ + 1) { i => w.putLong(iTx.outputNums(i)) }
+ w.putUShort(iTx.dataInputs.length)
+ cfor(0)(_ < iTx.dataInputs.length, _ + 1) { i => w.putBytes(iTx.dataInputs(i).boxId) }
}
override def parse(r: Reader): IndexedErgoTransaction = {
val idLen = r.getUByte()
val id = bytesToId(r.getBytes(idLen))
+ val index = r.getInt()
val height = r.getInt()
+ val size = r.getInt()
val globalIndex = r.getLong()
val inputCount: Int = r.getUShort()
val inputNums: Array[Long] = Array.ofDim[Long](inputCount)
cfor(0)(_ < inputCount, _ + 1) { i => inputNums(i) = r.getLong() }
- IndexedErgoTransaction(id, height, globalIndex, inputNums)
+ val outputCount: Int = r.getUShort()
+ val outputNums: Array[Long] = Array.ofDim[Long](outputCount)
+ cfor(0)(_ < outputCount, _ + 1) { i => outputNums(i) = r.getLong() }
+ val dataInputsCount = r.getUShort()
+ val dataInputs: Array[DataInput] = Array.ofDim[DataInput](dataInputsCount)
+ cfor(0)(_ < dataInputsCount, _ + 1) { i => dataInputs(i) = DataInput(ADKey @@ r.getBytes(32)) }
+ IndexedErgoTransaction(id, index, height, size, globalIndex, inputNums, outputNums, dataInputs)
}
}
object IndexedErgoTransaction {
val extraIndexTypeId: ExtraIndexTypeId = 10.toByte
+
+ def fromTx(tx: ErgoTransaction, index: Int, height: Int, globalIndex: Long, inputs: Array[Long], outputs: Array[Long]): IndexedErgoTransaction =
+ IndexedErgoTransaction(tx.id, index, height, tx.size, globalIndex, inputs, outputs, tx.dataInputs.toArray)
}
diff --git a/src/main/scala/org/ergoplatform/nodeView/history/extra/IndexedToken.scala b/src/main/scala/org/ergoplatform/nodeView/history/extra/IndexedToken.scala
index ec00019729..e29b0fc04d 100644
--- a/src/main/scala/org/ergoplatform/nodeView/history/extra/IndexedToken.scala
+++ b/src/main/scala/org/ergoplatform/nodeView/history/extra/IndexedToken.scala
@@ -6,7 +6,7 @@ import org.ergoplatform.nodeView.history.{ErgoHistory, ErgoHistoryReader}
import org.ergoplatform.nodeView.history.extra.ExtraIndexer.{ExtraIndexTypeId, fastIdToBytes}
import org.ergoplatform.nodeView.history.extra.IndexedTokenSerializer.{ByteColl, uniqueId}
import org.ergoplatform.settings.Algos
-import scorex.core.serialization.ErgoSerializer
+import org.ergoplatform.serialization.ErgoSerializer
import scorex.util.{ModifierId, bytesToId}
import scorex.util.serialization.{Reader, Writer}
import sigmastate.Values.CollectionConstant
@@ -49,9 +49,10 @@ case class IndexedToken(tokenId: ModifierId,
val toRemove: ArrayBuffer[ModifierId] = rollbackState(txTarget, boxTarget, history.getReader)
- if (boxCount == 0)
+ if (boxCount == 0) {
toRemove += id // all segments empty after rollback, delete parent
- else
+ log.info(s"Removing token $tokenId because no more boxes are associated with it")
+ } else
history.historyStorage.insertExtra(Array.empty, Array(this)) // save the changes made to this address
toRemove.toArray
@@ -100,6 +101,17 @@ case class IndexedToken(tokenId: ModifierId,
override private[extra] def filterMempool(boxes: Seq[ErgoBox]): Seq[ErgoBox] =
boxes.filter(_.additionalTokens.exists(_._1.toModifierId == tokenId))
+ /**
+ * Increase emission amount of this token. Sometimes tokens get created in multiple boxes.
+ * @param plus - emission amount to add
+ * @return updated token
+ */
+ private[extra] def addEmissionAmount(plus: Long): IndexedToken = {
+ val updated = IndexedToken(tokenId, boxId, amount + plus, name, description, decimals, boxes)
+ updated.buffer ++= buffer
+ updated
+ }
+
}
object IndexedTokenSerializer extends ErgoSerializer[IndexedToken] {
diff --git a/src/main/scala/org/ergoplatform/nodeView/history/extra/IndexerState.scala b/src/main/scala/org/ergoplatform/nodeView/history/extra/IndexerState.scala
new file mode 100644
index 0000000000..05dec8d177
--- /dev/null
+++ b/src/main/scala/org/ergoplatform/nodeView/history/extra/IndexerState.scala
@@ -0,0 +1,48 @@
+package org.ergoplatform.nodeView.history.extra
+
+import org.ergoplatform.nodeView.history.ErgoHistory
+import org.ergoplatform.nodeView.history.extra.ExtraIndexer._
+
+/**
+ * An immutable state for extra indexer
+ * @param indexedHeight - Indexed block height
+ * @param globalTxIndex - Indexed transaction count
+ * @param globalBoxIndex - Indexed box count
+ * @param rollbackTo - blockheight to rollback to, 0 if no rollback is in progress
+ * @param caughtUp - flag to indicate if the indexer is caught up with the chain and is listening for updates
+ */
+case class IndexerState(indexedHeight: Int,
+ globalTxIndex: Long,
+ globalBoxIndex: Long,
+ rollbackTo: Int,
+ caughtUp: Boolean) {
+
+ def rollbackInProgress: Boolean = rollbackTo > 0
+
+ def incrementIndexedHeight: IndexerState = copy(indexedHeight = indexedHeight + 1)
+
+ def incrementTxIndex: IndexerState = copy(globalTxIndex = globalTxIndex + 1)
+ def incrementBoxIndex: IndexerState = copy(globalBoxIndex = globalBoxIndex + 1)
+
+ def decrementTxIndex: IndexerState = copy(globalTxIndex = globalTxIndex - 1)
+ def decrementBoxIndex: IndexerState = copy(globalBoxIndex = globalBoxIndex - 1)
+
+}
+
+object IndexerState {
+
+ def fromHistory(history: ErgoHistory): IndexerState = {
+ val indexedHeight = getIndex(IndexedHeightKey, history).getInt
+ val globalTxIndex = getIndex(GlobalTxIndexKey, history).getLong
+ val globalBoxIndex = getIndex(GlobalBoxIndexKey, history).getLong
+ val rollbackTo = getIndex(RollbackToKey, history).getInt
+ IndexerState(
+ indexedHeight,
+ globalTxIndex,
+ globalBoxIndex,
+ rollbackTo,
+ caughtUp = indexedHeight == history.fullBlockHeight
+ )
+ }
+
+}
diff --git a/src/main/scala/org/ergoplatform/nodeView/history/extra/NumericIndex.scala b/src/main/scala/org/ergoplatform/nodeView/history/extra/NumericIndex.scala
index bfdcdbd9ad..24b171668b 100644
--- a/src/main/scala/org/ergoplatform/nodeView/history/extra/NumericIndex.scala
+++ b/src/main/scala/org/ergoplatform/nodeView/history/extra/NumericIndex.scala
@@ -3,7 +3,7 @@ package org.ergoplatform.nodeView.history.extra
import org.ergoplatform.nodeView.history.ErgoHistoryReader
import org.ergoplatform.nodeView.history.extra.ExtraIndexer.{ExtraIndexTypeId, fastIdToBytes}
import org.ergoplatform.settings.Algos
-import scorex.core.serialization.ErgoSerializer
+import org.ergoplatform.serialization.ErgoSerializer
import scorex.util.{ModifierId, bytesToId}
import scorex.util.serialization.{Reader, Writer}
diff --git a/src/main/scala/org/ergoplatform/nodeView/history/extra/Segment.scala b/src/main/scala/org/ergoplatform/nodeView/history/extra/Segment.scala
index e1f82c7d8b..c45a5c9595 100644
--- a/src/main/scala/org/ergoplatform/nodeView/history/extra/Segment.scala
+++ b/src/main/scala/org/ergoplatform/nodeView/history/extra/Segment.scala
@@ -18,7 +18,7 @@ import scala.reflect.ClassTag
/**
* Class to manage the tracking of transactions/boxes in relation to some other object (ErgoTree/token).
- * When [[ExtraIndexerBase.segmentTreshold]] number of transaction/box indexes are accumulated, new instances of the parent object are created to contain them.
+ * When [[ExtraIndexerBase.segmentThreshold]] number of transaction/box indexes are accumulated, new instances of the parent object are created to contain them.
* This mechanism is used to prevent excessive serialization/deserialization delays caused by objects with a lot of transaction/box indexes.
* @param parentId - identifier of parent object
* @param factory - parent object factory
@@ -96,15 +96,19 @@ abstract class Segment[T <: Segment[_] : ClassTag](val parentId: ModifierId,
buffer.get(segmentId) match {
case Some(segment) =>
val i: Int = binarySearch(segment.boxes, boxNumAbs)
- segment.boxes(i) = -segment.boxes(i)
+ if (i >= 0) {
+ segment.boxes(i) = -segment.boxes(i)
+ } else {
+ log.error(s"Box $boxNum not found in predicted segment of parent: ${segment.boxes.mkString("[", ",", "]")}")
+ }
case None =>
- log.warn(s"Box $boxNum not found in any segment of parent when trying to spend")
+ log.error(s"Box $boxNum not found in any segment of parent")
}
}
}
/**
- * Create an array of parent objects each containing [[ExtraIndexerBase.segmentTreshold]] number of transaction/box indexes.
+ * Create an array of parent objects each containing [[ExtraIndexerBase.segmentThreshold]] number of transaction/box indexes.
* These objects have their ids calculated by "txSegmentId" and "boxSegmentId" respectively.
*
* @return array of parent objects
@@ -307,8 +311,8 @@ abstract class Segment[T <: Segment[_] : ClassTag](val parentId: ModifierId,
txs.clear()
txs ++= tmp
if (txs.isEmpty && txSegmentCount > 0) { // entire current tx set removed, retrieving more from database if possible
- val segmentId = txSegmentId(parentId, txSegmentCount - 1)
- history.typedExtraIndexById[T](idMod(segmentId)).get.txs ++=: txs
+ val segmentId = idMod(txSegmentId(parentId, txSegmentCount - 1))
+ txs ++= history.typedExtraIndexById[T](segmentId).get.txs
toRemove += segmentId
txSegmentCount -= 1
}
@@ -320,8 +324,8 @@ abstract class Segment[T <: Segment[_] : ClassTag](val parentId: ModifierId,
boxes.clear()
boxes ++= tmp
if (boxes.isEmpty && boxSegmentCount > 0) { // entire current box set removed, retrieving more from database if possible
- val segmentId = boxSegmentId(parentId, boxSegmentCount - 1)
- history.typedExtraIndexById[T](idMod(segmentId)).get.boxes ++=: boxes
+ val segmentId = idMod(boxSegmentId(parentId, boxSegmentCount - 1))
+ boxes ++= history.typedExtraIndexById[T](segmentId).get.boxes
toRemove += segmentId
boxSegmentCount -= 1
}
@@ -418,19 +422,21 @@ object SegmentSerializer {
}
def serialize(s: Segment[_], w: Writer): Unit = {
- w.putUInt(s.txs.length)
+ w.putInt(s.txs.length)
cfor(0)(_ < s.txs.length, _ + 1) { i => w.putLong(s.txs(i)) }
- w.putUInt(s.boxes.length)
+ w.putInt(s.boxes.length)
cfor(0)(_ < s.boxes.length, _ + 1) { i => w.putLong(s.boxes(i)) }
w.putInt(s.boxSegmentCount)
w.putInt(s.txSegmentCount)
}
def parse(r: Reader, s: Segment[_]): Unit = {
- val txnsLen: Long = r.getUInt()
- cfor(0)(_ < txnsLen, _ + 1) { _ => s.txs.+=(r.getLong()) }
- val boxesLen: Long = r.getUInt()
- cfor(0)(_ < boxesLen, _ + 1) { _ => s.boxes.+=(r.getLong()) }
+ val txnsLen: Int = r.getInt()
+ s.txs.sizeHint(txnsLen)
+ cfor(0)(_ < txnsLen, _ + 1) { _ => s.txs += r.getLong() }
+ val boxesLen: Int = r.getInt()
+ s.boxes.sizeHint(boxesLen)
+ cfor(0)(_ < boxesLen, _ + 1) { _ => s.boxes += r.getLong() }
s.boxSegmentCount = r.getInt()
s.txSegmentCount = r.getInt()
}
diff --git a/src/main/scala/org/ergoplatform/nodeView/history/storage/HistoryStorage.scala b/src/main/scala/org/ergoplatform/nodeView/history/storage/HistoryStorage.scala
index 2b4559af84..53e06b3738 100644
--- a/src/main/scala/org/ergoplatform/nodeView/history/storage/HistoryStorage.scala
+++ b/src/main/scala/org/ergoplatform/nodeView/history/storage/HistoryStorage.scala
@@ -6,7 +6,7 @@ import org.ergoplatform.modifiers.history.HistoryModifierSerializer
import org.ergoplatform.modifiers.history.header.Header
import org.ergoplatform.nodeView.history.extra.{ExtraIndex, ExtraIndexSerializer, Segment}
import org.ergoplatform.settings.{Algos, CacheSettings, ErgoSettings}
-import scorex.core.utils.ScorexEncoding
+import org.ergoplatform.utils.ScorexEncoding
import scorex.db.{ByteArrayWrapper, LDBFactory, LDBKVStore}
import scorex.util.{ModifierId, ScorexLogging, idToBytes}
@@ -154,7 +154,6 @@ class HistoryStorage private(indexStore: LDBKVStore, objectsStore: LDBKVStore, e
objectsToInsert.map(mod => mod.serializedId),
objectsToInsert.map(mod => ExtraIndexSerializer.toBytes(mod))
)
- cfor(0)(_ < objectsToInsert.length, _ + 1) { i => val ei = objectsToInsert(i); extraCache.put(ei.id, ei)}
cfor(0)(_ < indexesToInsert.length, _ + 1) { i => extraStore.insert(indexesToInsert(i)._1, indexesToInsert(i)._2)}
}
diff --git a/src/main/scala/org/ergoplatform/nodeView/history/storage/modifierprocessors/BlockSectionProcessor.scala b/src/main/scala/org/ergoplatform/nodeView/history/storage/modifierprocessors/BlockSectionProcessor.scala
index eec47cb0bc..653e592452 100644
--- a/src/main/scala/org/ergoplatform/nodeView/history/storage/modifierprocessors/BlockSectionProcessor.scala
+++ b/src/main/scala/org/ergoplatform/nodeView/history/storage/modifierprocessors/BlockSectionProcessor.scala
@@ -1,8 +1,8 @@
package org.ergoplatform.nodeView.history.storage.modifierprocessors
-import org.ergoplatform.modifiers.{NonHeaderBlockSection, BlockSection}
-import scorex.core.consensus.ProgressInfo
-import scorex.core.utils.ScorexEncoding
+import org.ergoplatform.consensus.ProgressInfo
+import org.ergoplatform.modifiers.{BlockSection, NonHeaderBlockSection}
+import org.ergoplatform.utils.ScorexEncoding
import scala.util.Try
diff --git a/src/main/scala/org/ergoplatform/nodeView/history/storage/modifierprocessors/EmptyBlockSectionProcessor.scala b/src/main/scala/org/ergoplatform/nodeView/history/storage/modifierprocessors/EmptyBlockSectionProcessor.scala
index 8f602453f5..f7d35e3ea8 100644
--- a/src/main/scala/org/ergoplatform/nodeView/history/storage/modifierprocessors/EmptyBlockSectionProcessor.scala
+++ b/src/main/scala/org/ergoplatform/nodeView/history/storage/modifierprocessors/EmptyBlockSectionProcessor.scala
@@ -1,7 +1,7 @@
package org.ergoplatform.nodeView.history.storage.modifierprocessors
-import org.ergoplatform.modifiers.{NonHeaderBlockSection, BlockSection}
-import scorex.core.consensus.ProgressInfo
+import org.ergoplatform.consensus.ProgressInfo
+import org.ergoplatform.modifiers.{BlockSection, NonHeaderBlockSection}
import scala.util.{Failure, Success, Try}
diff --git a/src/main/scala/org/ergoplatform/nodeView/history/storage/modifierprocessors/FullBlockProcessor.scala b/src/main/scala/org/ergoplatform/nodeView/history/storage/modifierprocessors/FullBlockProcessor.scala
index 714dbabce4..8c84852f09 100644
--- a/src/main/scala/org/ergoplatform/nodeView/history/storage/modifierprocessors/FullBlockProcessor.scala
+++ b/src/main/scala/org/ergoplatform/nodeView/history/storage/modifierprocessors/FullBlockProcessor.scala
@@ -1,11 +1,12 @@
package org.ergoplatform.nodeView.history.storage.modifierprocessors
+import org.ergoplatform.consensus.ProgressInfo
import org.ergoplatform.modifiers.history._
import org.ergoplatform.modifiers.history.header.Header
-import org.ergoplatform.modifiers.{ErgoFullBlock, BlockSection}
-import org.ergoplatform.nodeView.history.ErgoHistory
+import org.ergoplatform.modifiers.{BlockSection, ErgoFullBlock}
+import org.ergoplatform.nodeView.history.ErgoHistoryUtils
+import org.ergoplatform.nodeView.history.ErgoHistoryUtils._
import org.ergoplatform.settings.Algos
-import scorex.core.consensus.ProgressInfo
import scorex.db.ByteArrayWrapper
import scorex.util.{ModifierId, bytesToId, idToBytes}
@@ -222,7 +223,7 @@ trait FullBlockProcessor extends HeadersProcessor {
s"New best block is ${toApply.last.header.encodedId} " +
s"with height ${toApply.last.header.height} " +
s"updates block ${prevBest.map(_.encodedId).getOrElse("None")} " +
- s"with height ${ErgoHistory.heightOf(prevBest.map(_.header))}"
+ s"with height ${ErgoHistoryUtils.heightOf(prevBest.map(_.header))}"
}
log.info(s"Full block ${appliedBlock.encodedId} appended, " +
s"going to apply ${toApply.length}$toRemoveStr modifiers. $newStatusStr")
@@ -285,6 +286,6 @@ object FullBlockProcessor {
def emptyCache: IncompleteFullChainCache = IncompleteFullChainCache(TreeMap.empty(ord))
def chainStatusKey(id: ModifierId): ByteArrayWrapper =
- ByteArrayWrapper(Algos.hash("main_chain".getBytes(ErgoHistory.CharsetName) ++ idToBytes(id)))
+ ByteArrayWrapper(Algos.hash("main_chain".getBytes(CharsetName) ++ idToBytes(id)))
}
diff --git a/src/main/scala/org/ergoplatform/nodeView/history/storage/modifierprocessors/FullBlockPruningProcessor.scala b/src/main/scala/org/ergoplatform/nodeView/history/storage/modifierprocessors/FullBlockPruningProcessor.scala
index d77b9e0def..95de235c49 100644
--- a/src/main/scala/org/ergoplatform/nodeView/history/storage/modifierprocessors/FullBlockPruningProcessor.scala
+++ b/src/main/scala/org/ergoplatform/nodeView/history/storage/modifierprocessors/FullBlockPruningProcessor.scala
@@ -1,7 +1,7 @@
package org.ergoplatform.nodeView.history.storage.modifierprocessors
import org.ergoplatform.modifiers.history.header.Header
-import org.ergoplatform.nodeView.history.ErgoHistory
+import org.ergoplatform.nodeView.history.ErgoHistoryUtils._
import org.ergoplatform.settings.ErgoSettings
/**
@@ -51,7 +51,7 @@ trait FullBlockPruningProcessor extends MinimalFullBlockHeightFunctions {
// we have constant min full block height corresponding to first block after utxo set snapshot
readMinimalFullBlockHeight()
} else {
- ErgoHistory.GenesisHeight // keep all blocks in history as no pruning set
+ GenesisHeight // keep all blocks in history as no pruning set
}
} else {
// Start from config.blocksToKeep blocks back
diff --git a/src/main/scala/org/ergoplatform/nodeView/history/storage/modifierprocessors/FullBlockSectionProcessor.scala b/src/main/scala/org/ergoplatform/nodeView/history/storage/modifierprocessors/FullBlockSectionProcessor.scala
index a702b88d5d..b9c36f987d 100644
--- a/src/main/scala/org/ergoplatform/nodeView/history/storage/modifierprocessors/FullBlockSectionProcessor.scala
+++ b/src/main/scala/org/ergoplatform/nodeView/history/storage/modifierprocessors/FullBlockSectionProcessor.scala
@@ -1,14 +1,14 @@
package org.ergoplatform.nodeView.history.storage.modifierprocessors
+import org.ergoplatform.consensus.ProgressInfo
import org.ergoplatform.modifiers.history._
import org.ergoplatform.modifiers.history.extension.Extension
import org.ergoplatform.modifiers.history.header.Header
import org.ergoplatform.modifiers.{BlockSection, ErgoFullBlock, NonHeaderBlockSection}
import org.ergoplatform.settings.ValidationRules._
import org.ergoplatform.settings.{Algos, ErgoValidationSettings}
-import scorex.core.consensus.ProgressInfo
-import scorex.core.utils.ScorexEncoding
-import scorex.core.validation.{ModifierValidator, _}
+import org.ergoplatform.utils.ScorexEncoding
+import org.ergoplatform.validation.{ModifierValidator, _}
import scorex.db.ByteArrayWrapper
import scorex.util.ModifierId
diff --git a/src/main/scala/org/ergoplatform/nodeView/history/storage/modifierprocessors/HeadersProcessor.scala b/src/main/scala/org/ergoplatform/nodeView/history/storage/modifierprocessors/HeadersProcessor.scala
index 1d6371f430..0a801ccd5e 100644
--- a/src/main/scala/org/ergoplatform/nodeView/history/storage/modifierprocessors/HeadersProcessor.scala
+++ b/src/main/scala/org/ergoplatform/nodeView/history/storage/modifierprocessors/HeadersProcessor.scala
@@ -1,23 +1,21 @@
package org.ergoplatform.nodeView.history.storage.modifierprocessors
import com.google.common.primitives.Ints
-import org.ergoplatform.ErgoApp.CriticalSystemException
+import org.ergoplatform.CriticalSystemException
import org.ergoplatform.ErgoLikeContext.Height
+import org.ergoplatform.consensus.{ModifierSemanticValidity, ProgressInfo}
import org.ergoplatform.mining.AutolykosPowScheme
import org.ergoplatform.mining.difficulty.DifficultyAdjustment
import org.ergoplatform.modifiers.BlockSection
import org.ergoplatform.modifiers.history._
import org.ergoplatform.modifiers.history.header.Header
-import org.ergoplatform.nodeView.history.ErgoHistory
-import org.ergoplatform.nodeView.history.ErgoHistory.{Difficulty, GenesisHeight, Height}
+import org.ergoplatform.nodeView.history.ErgoHistoryUtils._
import org.ergoplatform.nodeView.history.storage.HistoryStorage
import org.ergoplatform.settings.Constants.HashLength
import org.ergoplatform.settings.ValidationRules._
import org.ergoplatform.settings._
-import scorex.core.consensus.ProgressInfo
-import scorex.core.consensus.ModifierSemanticValidity
-import scorex.core.utils.ScorexEncoding
-import scorex.core.validation.{InvalidModifier, ModifierValidator, ValidationResult, ValidationState}
+import org.ergoplatform.utils.ScorexEncoding
+import org.ergoplatform.validation.{InvalidModifier, ModifierValidator, ValidationResult, ValidationState}
import scorex.db.ByteArrayWrapper
import scorex.util._
import scorex.util.encode.Base16
@@ -65,13 +63,13 @@ trait HeadersProcessor extends ToDownloadProcessor with PopowProcessor with Scor
// todo for performance reasons we may just use key like s"score$id" but this will require to resync the blockchain
protected def headerScoreKey(id: ModifierId): ByteArrayWrapper =
- ByteArrayWrapper(Algos.hash("score".getBytes(ErgoHistory.CharsetName) ++ idToBytes(id)))
+ ByteArrayWrapper(Algos.hash("score".getBytes(CharsetName) ++ idToBytes(id)))
protected def headerHeightKey(id: ModifierId): ByteArrayWrapper =
- ByteArrayWrapper(Algos.hash("height".getBytes(ErgoHistory.CharsetName) ++ idToBytes(id)))
+ ByteArrayWrapper(Algos.hash("height".getBytes(CharsetName) ++ idToBytes(id)))
protected[history] def validityKey(id: ModifierId): ByteArrayWrapper =
- ByteArrayWrapper(Algos.hash("validity".getBytes(ErgoHistory.CharsetName) ++ idToBytes(id)))
+ ByteArrayWrapper(Algos.hash("validity".getBytes(CharsetName) ++ idToBytes(id)))
override def writeMinimalFullBlockHeight(height: Height): Unit = {
historyStorage.insert(
@@ -80,7 +78,7 @@ trait HeadersProcessor extends ToDownloadProcessor with PopowProcessor with Scor
}
override def readMinimalFullBlockHeight(): Height = {
- historyStorage.getIndex(MinFullBlockHeightKey).map(Ints.fromByteArray).getOrElse(ErgoHistory.GenesisHeight)
+ historyStorage.getIndex(MinFullBlockHeightKey).map(Ints.fromByteArray).getOrElse(GenesisHeight)
}
def bestHeaderIdOpt: Option[ModifierId] = historyStorage.getIndex(BestHeaderKey).map(bytesToId)
@@ -93,12 +91,12 @@ trait HeadersProcessor extends ToDownloadProcessor with PopowProcessor with Scor
/**
* @return height of best header
*/
- def headersHeight: Height = bestHeaderIdOpt.flatMap(id => heightOf(id)).getOrElse(ErgoHistory.EmptyHistoryHeight)
+ def headersHeight: Height = bestHeaderIdOpt.flatMap(id => heightOf(id)).getOrElse(EmptyHistoryHeight)
/**
* @return height of best header with all block sections
*/
- def fullBlockHeight: Height = bestFullBlockIdOpt.flatMap(id => heightOf(id)).getOrElse(ErgoHistory.EmptyHistoryHeight)
+ def fullBlockHeight: Height = bestFullBlockIdOpt.flatMap(id => heightOf(id)).getOrElse(EmptyHistoryHeight)
/**
* @param id - id of ErgoPersistentModifier
@@ -386,7 +384,7 @@ trait HeadersProcessor extends ToDownloadProcessor with PopowProcessor with Scor
private def validationState: ValidationState[Unit] = ModifierValidator(ErgoValidationSettings.initial)
- private def time(): ErgoHistory.Time = System.currentTimeMillis()
+ private def time(): Time = System.currentTimeMillis()
def validate(header: Header): ValidationResult[Unit] = {
if (header.isGenesis) {
diff --git a/src/main/scala/org/ergoplatform/nodeView/history/storage/modifierprocessors/MinimalFullBlockHeightFunctions.scala b/src/main/scala/org/ergoplatform/nodeView/history/storage/modifierprocessors/MinimalFullBlockHeightFunctions.scala
index fc53aca3c0..08bcc1c4c5 100644
--- a/src/main/scala/org/ergoplatform/nodeView/history/storage/modifierprocessors/MinimalFullBlockHeightFunctions.scala
+++ b/src/main/scala/org/ergoplatform/nodeView/history/storage/modifierprocessors/MinimalFullBlockHeightFunctions.scala
@@ -1,6 +1,6 @@
package org.ergoplatform.nodeView.history.storage.modifierprocessors
-import org.ergoplatform.nodeView.history.ErgoHistory.Height
+import org.ergoplatform.nodeView.history.ErgoHistoryUtils.Height
/**
* Interface to methods providing updating and reading height of first full block stored in local database
diff --git a/src/main/scala/org/ergoplatform/nodeView/history/storage/modifierprocessors/PopowProcessor.scala b/src/main/scala/org/ergoplatform/nodeView/history/storage/modifierprocessors/PopowProcessor.scala
index 97ee72f9c9..8baa167e40 100644
--- a/src/main/scala/org/ergoplatform/nodeView/history/storage/modifierprocessors/PopowProcessor.scala
+++ b/src/main/scala/org/ergoplatform/nodeView/history/storage/modifierprocessors/PopowProcessor.scala
@@ -1,15 +1,15 @@
package org.ergoplatform.nodeView.history.storage.modifierprocessors
+import org.ergoplatform.consensus.ProgressInfo
import org.ergoplatform.local.{CorrectNipopowProofVerificationResult, NipopowProofVerificationResult, NipopowVerifier}
import org.ergoplatform.modifiers.BlockSection
import org.ergoplatform.modifiers.history.extension.Extension
import org.ergoplatform.modifiers.history.header.Header
-import org.ergoplatform.modifiers.history.popow.{NipopowAlgos, NipopowProof, NipopowProofSerializer, PoPowHeader, PoPowParams}
-import org.ergoplatform.nodeView.history.ErgoHistory.GenesisHeight
+import org.ergoplatform.modifiers.history.popow.{NipopowAlgos, NipopowProverWithDbAlgs, NipopowProof, NipopowProofSerializer, PoPowHeader, PoPowParams}
+import org.ergoplatform.nodeView.history.ErgoHistoryUtils.GenesisHeight
import org.ergoplatform.nodeView.history.ErgoHistoryReader
import org.ergoplatform.settings.{ChainSettings, NipopowSettings}
import org.ergoplatform.settings.Constants.HashLength
-import scorex.core.consensus.ProgressInfo
import scorex.db.ByteArrayWrapper
import scorex.util.{ModifierId, ScorexLogging}
@@ -108,7 +108,7 @@ trait PopowProcessor extends BasicReaders with ScorexLogging {
*/
def popowProof(m: Int, k: Int, headerIdOpt: Option[ModifierId]): Try[NipopowProof] = {
val proofParams = PoPowParams(m, k, continuous = true)
- nipopowAlgos.prove(historyReader, headerIdOpt = headerIdOpt)(proofParams)
+ NipopowProverWithDbAlgs.prove(historyReader, headerIdOpt = headerIdOpt, chainSettings)(proofParams)
}
/**
diff --git a/src/main/scala/org/ergoplatform/nodeView/history/storage/modifierprocessors/ToDownloadProcessor.scala b/src/main/scala/org/ergoplatform/nodeView/history/storage/modifierprocessors/ToDownloadProcessor.scala
index a2851553c5..090610c3c2 100644
--- a/src/main/scala/org/ergoplatform/nodeView/history/storage/modifierprocessors/ToDownloadProcessor.scala
+++ b/src/main/scala/org/ergoplatform/nodeView/history/storage/modifierprocessors/ToDownloadProcessor.scala
@@ -15,7 +15,7 @@ import scala.annotation.tailrec
trait ToDownloadProcessor
extends FullBlockPruningProcessor with UtxoSetSnapshotProcessor with BasicReaders with ScorexLogging {
- import scorex.core.utils.MapPimp
+ import org.ergoplatform.utils.MapPimp
protected val settings: ErgoSettings
diff --git a/src/main/scala/org/ergoplatform/nodeView/history/storage/modifierprocessors/UtxoSetSnapshotProcessor.scala b/src/main/scala/org/ergoplatform/nodeView/history/storage/modifierprocessors/UtxoSetSnapshotProcessor.scala
index 66f614da64..1d2972cfe9 100644
--- a/src/main/scala/org/ergoplatform/nodeView/history/storage/modifierprocessors/UtxoSetSnapshotProcessor.scala
+++ b/src/main/scala/org/ergoplatform/nodeView/history/storage/modifierprocessors/UtxoSetSnapshotProcessor.scala
@@ -2,14 +2,15 @@ package org.ergoplatform.nodeView.history.storage.modifierprocessors
import com.google.common.primitives.Ints
import org.ergoplatform.ErgoLikeContext.Height
-import org.ergoplatform.nodeView.history.{ErgoHistory, ErgoHistoryReader}
+import org.ergoplatform.nodeView.history.ErgoHistoryReader
+import org.ergoplatform.nodeView.history.ErgoHistoryUtils._
import org.ergoplatform.nodeView.history.storage.HistoryStorage
import org.ergoplatform.nodeView.state.{ErgoStateReader, UtxoState}
import org.ergoplatform.nodeView.state.UtxoState.SubtreeId
import org.ergoplatform.settings.{Algos, ErgoAlgos, ErgoSettings}
-import scorex.core.VersionTag
+import org.ergoplatform.core.VersionTag
import scorex.core.network.ConnectedPeer
-import scorex.core.serialization.SubtreeSerializer
+import org.ergoplatform.serialization.SubtreeSerializer
import scorex.crypto.authds.avltree.batch.serialization.{BatchAVLProverManifest, BatchAVLProverSubtree}
import scorex.crypto.hash.{Blake2b256, Digest32}
import scorex.db.LDBVersionedStore
@@ -46,7 +47,7 @@ trait UtxoSetSnapshotProcessor extends MinimalFullBlockHeightFunctions with Scor
* After first full-block block application not needed anymore.
*/
def isUtxoSnapshotApplied: Boolean = {
- readMinimalFullBlockHeight() > ErgoHistory.GenesisHeight
+ readMinimalFullBlockHeight() > GenesisHeight
}
/**
diff --git a/src/main/scala/org/ergoplatform/nodeView/mempool/ErgoMemPool.scala b/src/main/scala/org/ergoplatform/nodeView/mempool/ErgoMemPool.scala
index 75f626db88..df08cd4858 100644
--- a/src/main/scala/org/ergoplatform/nodeView/mempool/ErgoMemPool.scala
+++ b/src/main/scala/org/ergoplatform/nodeView/mempool/ErgoMemPool.scala
@@ -8,12 +8,12 @@ import org.ergoplatform.nodeView.state.{ErgoState, UtxoState}
import org.ergoplatform.settings.{ErgoSettings, MonetarySettings, NodeConfigurationSettings}
import scorex.util.{ModifierId, ScorexLogging, bytesToId}
import OrderedTxPool.weighted
-import org.ergoplatform.nodeView.mempool.ErgoMemPool.SortingOption
+import org.ergoplatform.nodeView.mempool.ErgoMemPoolUtils._
import spire.syntax.all.cfor
import scala.annotation.tailrec
import scala.collection.mutable
-import scala.util.{Failure, Random, Success, Try}
+import scala.util.{Failure, Success, Try}
/**
@@ -31,7 +31,6 @@ class ErgoMemPool private[mempool](private[mempool] val pool: OrderedTxPool,
(implicit settings: ErgoSettings)
extends ErgoMemPoolReader with ScorexLogging {
- import ErgoMemPool._
import EmissionRules.CoinsInOneErgo
/**
@@ -324,111 +323,12 @@ class ErgoMemPool private[mempool](private[mempool] val pool: OrderedTxPool,
}
object ErgoMemPool extends ScorexLogging {
-
/**
- * Hierarchy of sorting strategies for mempool transactions
+ * Create empty mempool
+ *
+ * @param settings - node settings (to get mempool settings from)
+ * @return empty mempool
*/
- sealed trait SortingOption
-
- object SortingOption {
- /**
- * Sort transactions by fee paid for transaction size, so fee/byte
- */
- case object FeePerByte extends SortingOption
-
- /**
- * Sort transactions by fee paid for transaction contracts validation cost, so fee/execution unit
- */
- case object FeePerCycle extends SortingOption
-
- /**
- * @return randomly chosen mempool sorting strategy
- */
- def random(): SortingOption = {
- if (Random.nextBoolean()) {
- FeePerByte
- } else {
- FeePerCycle
- }
- }
- }
-
- /**
- * Root of possible mempool transaction validation result family
- */
- sealed trait ProcessingOutcome {
- /**
- * Time when transaction validation was started
- */
- protected val validationStartTime: Long
-
- /**
- * We assume that validation ends when this processing result class is constructed
- */
- private val validationEndTime: Long = System.currentTimeMillis()
-
- /**
- * 5.0 JIT costing was designed in a way that 1000 cost units are roughly corresponding to 1 ms of 1 CPU core
- * on commodity hardware (of 2021). So if we do not know the exact cost of transaction, we can estimate it by
- * tracking validation time and then getting estimated validation cost by multiplying the time (in ms) by 1000
- */
- val costPerMs = 1000
-
- /**
- * Estimated validation cost, see comment for `costPerMs`
- */
- def cost: Int = {
- val timeDiff = validationEndTime - validationStartTime
- if (timeDiff == 0) {
- costPerMs
- } else if (timeDiff > 1000000) {
- Int.MaxValue // shouldn't be here, so this branch is mostly to have safe .toInt below
- } else {
- (timeDiff * costPerMs).toInt
- }
- }
- }
-
- object ProcessingOutcome {
-
- /**
- * Object signalling that a transaction is accepted to the memory pool
- */
- class Accepted(val tx: UnconfirmedTransaction,
- override protected val validationStartTime: Long) extends ProcessingOutcome {
- override val cost: Int = tx.lastCost.getOrElse(super.cost)
- }
-
- /**
- * Class signalling that a valid transaction was rejected as it is double-spending inputs of mempool transactions
- * and has no bigger weight (fee/byte) than them on average.
- *
- * @param winnerTxIds - identifiers of transactions won in replace-by-fee auction
- */
- class DoubleSpendingLoser(val winnerTxIds: Set[ModifierId],
- override protected val validationStartTime: Long) extends ProcessingOutcome
-
- /**
- * Class signalling that a transaction declined from being accepted into the memory pool
- */
- class Declined(val e: Throwable,
- override protected val validationStartTime: Long) extends ProcessingOutcome
-
-
- /**
- * Class signalling that a transaction turned out to be invalid when checked in the mempool
- */
- class Invalidated(val e: Throwable,
- override protected val validationStartTime: Long) extends ProcessingOutcome
-
- }
-
- /**
- * Create empty mempool
- *
- * @param settings - node settings (to get mempool settings from)
- * @return empty mempool
- */
def empty(settings: ErgoSettings): ErgoMemPool = {
val sortingOption = settings.nodeSettings.mempoolSorting
sortingOption match {
@@ -441,5 +341,4 @@ object ErgoMemPool extends ScorexLogging {
sortingOption
)(settings)
}
-
}
diff --git a/src/main/scala/org/ergoplatform/nodeView/mempool/ErgoMemPoolReader.scala b/src/main/scala/org/ergoplatform/nodeView/mempool/ErgoMemPoolReader.scala
index 884e7249e2..a3f31a1c61 100644
--- a/src/main/scala/org/ergoplatform/nodeView/mempool/ErgoMemPoolReader.scala
+++ b/src/main/scala/org/ergoplatform/nodeView/mempool/ErgoMemPoolReader.scala
@@ -1,10 +1,10 @@
package org.ergoplatform.nodeView.mempool
import org.ergoplatform.ErgoBox.BoxId
+import org.ergoplatform.NodeViewComponent
+import org.ergoplatform.consensus.ContainsModifiers
import org.ergoplatform.modifiers.mempool.{ErgoTransaction, UnconfirmedTransaction}
import org.ergoplatform.nodeView.mempool.OrderedTxPool.WeightedTxId
-import scorex.core.NodeViewComponent
-import scorex.core.consensus.ContainsModifiers
import scorex.util.ModifierId
trait ErgoMemPoolReader extends NodeViewComponent with ContainsModifiers[ErgoTransaction] {
diff --git a/src/main/scala/org/ergoplatform/nodeView/mempool/ErgoMemPoolUtils.scala b/src/main/scala/org/ergoplatform/nodeView/mempool/ErgoMemPoolUtils.scala
new file mode 100644
index 0000000000..a672fa5a26
--- /dev/null
+++ b/src/main/scala/org/ergoplatform/nodeView/mempool/ErgoMemPoolUtils.scala
@@ -0,0 +1,110 @@
+package org.ergoplatform.nodeView.mempool
+
+import org.ergoplatform.modifiers.mempool.UnconfirmedTransaction
+import scorex.util.{ModifierId, ScorexLogging}
+import scala.util.Random
+
+/**
+ * Additional types and functions used in ErgoMemPool
+ */
+object ErgoMemPoolUtils extends ScorexLogging {
+
+ /**
+ * Hierarchy of sorting strategies for mempool transactions
+ */
+ sealed trait SortingOption
+
+ object SortingOption {
+ /**
+ * Sort transactions by fee paid for transaction size, so fee/byte
+ */
+ case object FeePerByte extends SortingOption
+
+ /**
+ * Sort transactions by fee paid for transaction contracts validation cost, so fee/execution unit
+ */
+ case object FeePerCycle extends SortingOption
+
+ /**
+ * @return randomly chosen mempool sorting strategy
+ */
+ def random(): SortingOption = {
+ if (Random.nextBoolean()) {
+ FeePerByte
+ } else {
+ FeePerCycle
+ }
+ }
+ }
+
+ /**
+ * Root of possible mempool transaction validation result family
+ */
+ sealed trait ProcessingOutcome {
+ /**
+ * Time when transaction validation was started
+ */
+ protected val validationStartTime: Long
+
+ /**
+ * We assume that validation ends when this processing result class is constructed
+ */
+ private val validationEndTime: Long = System.currentTimeMillis()
+
+ /**
+ * 5.0 JIT costing was designed in a way that 1000 cost units are roughly corresponding to 1 ms of 1 CPU core
+ * on commodity hardware (of 2021). So if we do not know the exact cost of transaction, we can estimate it by
+ * tracking validation time and then getting estimated validation cost by multiplying the time (in ms) by 1000
+ */
+ val costPerMs = 1000
+
+ /**
+ * Estimated validation cost, see comment for `costPerMs`
+ */
+ def cost: Int = {
+ val timeDiff = validationEndTime - validationStartTime
+ if (timeDiff == 0) {
+ costPerMs
+ } else if (timeDiff > 1000000) {
+ Int.MaxValue // shouldn't be here, so this branch is mostly to have safe .toInt below
+ } else {
+ (timeDiff * costPerMs).toInt
+ }
+ }
+ }
+
+ object ProcessingOutcome {
+
+ /**
+ * Object signalling that a transaction is accepted to the memory pool
+ */
+ class Accepted(val tx: UnconfirmedTransaction,
+ override protected val validationStartTime: Long) extends ProcessingOutcome {
+ override val cost: Int = tx.lastCost.getOrElse(super.cost)
+ }
+
+ /**
+ * Class signalling that a valid transaction was rejected as it is double-spending inputs of mempool transactions
+ * and has no bigger weight (fee/byte) than them on average.
+ *
+ * @param winnerTxIds - identifiers of transactions won in replace-by-fee auction
+ */
+ class DoubleSpendingLoser(val winnerTxIds: Set[ModifierId],
+ override protected val validationStartTime: Long) extends ProcessingOutcome
+
+ /**
+ * Class signalling that a transaction declined from being accepted into the memory pool
+ */
+ class Declined(val e: Throwable,
+ override protected val validationStartTime: Long) extends ProcessingOutcome
+
+
+ /**
+ * Class signalling that a transaction turned out to be invalid when checked in the mempool
+ */
+ class Invalidated(val e: Throwable,
+ override protected val validationStartTime: Long) extends ProcessingOutcome
+
+ }
+
+}
diff --git a/src/main/scala/org/ergoplatform/nodeView/state/BoxHolder.scala b/src/main/scala/org/ergoplatform/nodeView/state/BoxHolder.scala
index 3fe970cd77..a28814973f 100644
--- a/src/main/scala/org/ergoplatform/nodeView/state/BoxHolder.scala
+++ b/src/main/scala/org/ergoplatform/nodeView/state/BoxHolder.scala
@@ -1,7 +1,7 @@
package org.ergoplatform.nodeView.state
import org.ergoplatform.ErgoBox
-import scorex.core.VersionTag
+import org.ergoplatform.core.VersionTag
import scorex.db.ByteArrayWrapper
import scala.collection.immutable.SortedMap
diff --git a/src/main/scala/org/ergoplatform/nodeView/state/DigestState.scala b/src/main/scala/org/ergoplatform/nodeView/state/DigestState.scala
index 0711bc1a3c..3c5a3a4721 100644
--- a/src/main/scala/org/ergoplatform/nodeView/state/DigestState.scala
+++ b/src/main/scala/org/ergoplatform/nodeView/state/DigestState.scala
@@ -1,21 +1,20 @@
package org.ergoplatform.nodeView.state
import java.io.File
-
import org.ergoplatform.ErgoBox
import org.ergoplatform.ErgoLikeContext.Height
import org.ergoplatform.modifiers.history.ADProofs
import org.ergoplatform.modifiers.history.header.Header
import org.ergoplatform.modifiers.mempool.ErgoTransaction
-import org.ergoplatform.modifiers.{ErgoFullBlock, BlockSection}
-import org.ergoplatform.nodeView.ErgoNodeViewHolder.ReceivableMessages.LocallyGeneratedModifier
+import org.ergoplatform.modifiers.{BlockSection, ErgoFullBlock}
import org.ergoplatform.nodeView.state.ErgoState.ModifierProcessing
import org.ergoplatform.settings._
import org.ergoplatform.utils.LoggingUtil
import org.ergoplatform.wallet.boxes.ErgoBoxSerializer
import scorex.db.{ByteArrayWrapper, LDBVersionedStore}
-import scorex.core._
-import scorex.core.utils.ScorexEncoding
+import org.ergoplatform.core._
+import org.ergoplatform.nodeView.LocallyGeneratedModifier
+import org.ergoplatform.utils.ScorexEncoding
import scorex.crypto.authds.ADDigest
import scorex.util.ScorexLogging
@@ -57,7 +56,7 @@ class DigestState protected(override val version: VersionTag,
.fold[Try[ErgoBox]](Failure(new Exception(s"Box with id ${Algos.encode(id)} not found")))(Success(_))
}
- ErgoState.execTransactions(transactions, currentStateContext)(checkBoxExistence)
+ ErgoState.execTransactions(transactions, currentStateContext, nodeSettings)(checkBoxExistence)
.toTry
.map(_ => ())
}
@@ -89,7 +88,7 @@ class DigestState protected(override val version: VersionTag,
@SuppressWarnings(Array("OptionGet"))
override def rollbackTo(version: VersionTag): Try[DigestState] = {
log.info(s"Rollback Digest State to version ${Algos.encoder.encode(version)}")
- val versionBytes = scorex.core.versionToBytes(version)
+ val versionBytes = org.ergoplatform.core.versionToBytes(version)
Try(store.rollbackTo(versionBytes)).map { _ =>
store.clean(nodeSettings.keepVersions)
val rootHash = ADDigest @@ store.get(versionBytes).get
@@ -145,7 +144,7 @@ class DigestState protected(override val version: VersionTag,
val toUpdate = DigestState.metadata(newVersion, newRootHash, newStateContext)
- store.update(scorex.core.versionToBytes(newVersion), Seq.empty, toUpdate).map { _ =>
+ store.update(org.ergoplatform.core.versionToBytes(newVersion), Seq.empty, toUpdate).map { _ =>
new DigestState(newVersion, newRootHash, store, ergoSettings)
}
}
@@ -165,7 +164,7 @@ object DigestState extends ScorexLogging with ScorexEncoding {
val store = new LDBVersionedStore(dir, initialKeepVersions = settings.nodeSettings.keepVersions)
val toUpdate = DigestState.metadata(version, rootHash, stateContext)
- store.update(scorex.core.versionToBytes(version), Seq.empty, toUpdate).map { _ =>
+ store.update(org.ergoplatform.core.versionToBytes(version), Seq.empty, toUpdate).map { _ =>
new DigestState(version, rootHash, store, settings)
}
}
@@ -209,7 +208,7 @@ object DigestState extends ScorexLogging with ScorexEncoding {
protected def metadata(newVersion: VersionTag,
newRootHash: ADDigest,
newStateContext: ErgoStateContext): Seq[(Array[Byte], Array[Byte])] = Seq(
- scorex.core.versionToBytes(newVersion) -> newRootHash,
+ org.ergoplatform.core.versionToBytes(newVersion) -> newRootHash,
ErgoStateReader.ContextKey -> newStateContext.bytes
)
diff --git a/src/main/scala/org/ergoplatform/nodeView/state/ErgoState.scala b/src/main/scala/org/ergoplatform/nodeView/state/ErgoState.scala
index 4290d96ecc..31362aa4d2 100644
--- a/src/main/scala/org/ergoplatform/nodeView/state/ErgoState.scala
+++ b/src/main/scala/org/ergoplatform/nodeView/state/ErgoState.scala
@@ -10,14 +10,14 @@ import org.ergoplatform.modifiers.BlockSection
import org.ergoplatform.modifiers.history.header.Header
import org.ergoplatform.modifiers.mempool.ErgoTransaction
import org.ergoplatform.modifiers.state.StateChanges
-import org.ergoplatform.nodeView.ErgoNodeViewHolder.ReceivableMessages.LocallyGeneratedModifier
-import org.ergoplatform.nodeView.history.ErgoHistory
+import org.ergoplatform.nodeView.history.ErgoHistoryUtils._
import org.ergoplatform.settings.ValidationRules._
-import org.ergoplatform.settings.{ChainSettings, Constants, ErgoSettings, LaunchParameters}
+import org.ergoplatform.settings.{ChainSettings, Constants, ErgoSettings, LaunchParameters, NodeConfigurationSettings}
import org.ergoplatform.wallet.interpreter.ErgoInterpreter
-import scorex.core.validation.ValidationResult.Valid
-import scorex.core.validation.{ModifierValidator, ValidationResult}
-import scorex.core.{VersionTag, idToVersion}
+import org.ergoplatform.validation.ValidationResult.Valid
+import org.ergoplatform.validation.{ModifierValidator, ValidationResult}
+import org.ergoplatform.core.{VersionTag, idToVersion}
+import org.ergoplatform.nodeView.LocallyGeneratedModifier
import scorex.crypto.authds.avltree.batch.{Insert, Lookup, Remove}
import scorex.crypto.authds.{ADDigest, ADValue}
import scorex.util.encode.Base16
@@ -103,7 +103,8 @@ object ErgoState extends ScorexLogging {
* @return Result of transactions execution with total cost inside
*/
def execTransactions(transactions: Seq[ErgoTransaction],
- currentStateContext: ErgoStateContext)
+ currentStateContext: ErgoStateContext,
+ nodeSettings: NodeConfigurationSettings)
(checkBoxExistence: ErgoBox.BoxId => Try[ErgoBox]): ValidationResult[Long] = {
val verifier: ErgoInterpreter = ErgoInterpreter(currentStateContext.currentParameters)
@@ -130,7 +131,7 @@ object ErgoState extends ScorexLogging {
}
}
- val checkpointHeight = currentStateContext.ergoSettings.nodeSettings.checkpoint.map(_.height).getOrElse(0)
+ val checkpointHeight = nodeSettings.checkpoint.map(_.height).getOrElse(0)
if (currentStateContext.currentHeight <= checkpointHeight) {
Valid(0L)
} else {
@@ -206,7 +207,7 @@ object ErgoState extends ScorexLogging {
additionalRegisters: AdditionalRegisters = Map.empty): ErgoBox = {
import sigmastate.eval._
- val creationHeight: Int = ErgoHistory.EmptyHistoryHeight
+ val creationHeight: Int = EmptyHistoryHeight
val transactionId: ModifierId = ErgoBox.allZerosModifierId
val boxIndex: Short = 0: Short
diff --git a/src/main/scala/org/ergoplatform/nodeView/state/ErgoStateReader.scala b/src/main/scala/org/ergoplatform/nodeView/state/ErgoStateReader.scala
index 18947880c5..9b57c853cf 100644
--- a/src/main/scala/org/ergoplatform/nodeView/state/ErgoStateReader.scala
+++ b/src/main/scala/org/ergoplatform/nodeView/state/ErgoStateReader.scala
@@ -1,10 +1,10 @@
package org.ergoplatform.nodeView.state
-import org.ergoplatform.ErgoBox
-import org.ergoplatform.nodeView.history.ErgoHistory.Height
+import org.ergoplatform.{ErgoBox, NodeViewComponent}
+import org.ergoplatform.nodeView.history.ErgoHistoryUtils.Height
import org.ergoplatform.nodeView.history.ErgoHistoryReader
import org.ergoplatform.settings.{Algos, Constants, ErgoSettings, LaunchParameters, Parameters}
-import scorex.core.{NodeViewComponent, VersionTag}
+import org.ergoplatform.core.VersionTag
import scorex.crypto.authds.ADDigest
import scorex.crypto.hash.Digest32
import scorex.db.LDBVersionedStore
@@ -66,10 +66,10 @@ object ErgoStateReader extends ScorexLogging {
*/
def storageStateContext(store: LDBVersionedStore, settings: ErgoSettings): ErgoStateContext = {
store.get(ErgoStateReader.ContextKey)
- .flatMap(b => ErgoStateContextSerializer(settings).parseBytesTry(b).toOption)
+ .flatMap(b => ErgoStateContextSerializer(settings.chainSettings).parseBytesTry(b).toOption)
.getOrElse {
log.warn("Can't read blockchain parameters from database")
- ErgoStateContext.empty(settings, LaunchParameters)
+ ErgoStateContext.empty(settings.chainSettings, LaunchParameters)
}
}
@@ -94,13 +94,13 @@ object ErgoStateReader extends ScorexLogging {
if (lastHeaders.size != Constants.LastHeadersInContext) {
Failure(new Exception(s"Only ${lastHeaders.size} headers found in reconstructStateContextBeforeEpoch"))
} else {
- val empty = ErgoStateContext.empty(settings, LaunchParameters)
+ val empty = ErgoStateContext.empty(settings.chainSettings, LaunchParameters)
val esc = new ErgoStateContext( lastHeaders,
None,
empty.genesisStateDigest,
empty.currentParameters,
empty.validationSettings,
- empty.votingData)(settings)
+ empty.votingData)(settings.chainSettings)
Success(esc)
}
}
diff --git a/src/main/scala/org/ergoplatform/nodeView/state/SnapshotsDb.scala b/src/main/scala/org/ergoplatform/nodeView/state/SnapshotsDb.scala
index 5170247a7c..5889c9458f 100644
--- a/src/main/scala/org/ergoplatform/nodeView/state/SnapshotsDb.scala
+++ b/src/main/scala/org/ergoplatform/nodeView/state/SnapshotsDb.scala
@@ -3,7 +3,7 @@ package org.ergoplatform.nodeView.state
import org.ergoplatform.ErgoLikeContext.Height
import org.ergoplatform.nodeView.state.UtxoState.{ManifestId, SubtreeId}
import org.ergoplatform.settings.{Algos, ErgoSettings}
-import scorex.core.serialization.ManifestSerializer
+import org.ergoplatform.serialization.ManifestSerializer
import scorex.crypto.authds.avltree.batch.VersionedLDBAVLStorage
import scorex.crypto.hash.Digest32
import scorex.db.{LDBFactory, LDBKVStore}
diff --git a/src/main/scala/org/ergoplatform/nodeView/state/SnapshotsInfo.scala b/src/main/scala/org/ergoplatform/nodeView/state/SnapshotsInfo.scala
index 575e5bdf7a..990359091c 100644
--- a/src/main/scala/org/ergoplatform/nodeView/state/SnapshotsInfo.scala
+++ b/src/main/scala/org/ergoplatform/nodeView/state/SnapshotsInfo.scala
@@ -3,7 +3,7 @@ package org.ergoplatform.nodeView.state
import org.ergoplatform.ErgoLikeContext.Height
import org.ergoplatform.nodeView.state.UtxoState.ManifestId
import org.ergoplatform.settings.Constants
-import scorex.core.serialization.ErgoSerializer
+import org.ergoplatform.serialization.ErgoSerializer
import scorex.crypto.hash.Digest32
import scorex.util.serialization.{Reader, Writer}
diff --git a/src/main/scala/org/ergoplatform/nodeView/state/UtxoSetSnapshotPersistence.scala b/src/main/scala/org/ergoplatform/nodeView/state/UtxoSetSnapshotPersistence.scala
index ad6f9193bf..1416bc11d7 100644
--- a/src/main/scala/org/ergoplatform/nodeView/state/UtxoSetSnapshotPersistence.scala
+++ b/src/main/scala/org/ergoplatform/nodeView/state/UtxoSetSnapshotPersistence.scala
@@ -7,7 +7,7 @@ import scorex.crypto.authds.avltree.batch.{PersistentBatchAVLProver, VersionedLD
import scorex.crypto.hash.Digest32
import scorex.util.ScorexLogging
import org.ergoplatform.settings.ErgoSettings
-import scorex.core.serialization.ManifestSerializer
+import org.ergoplatform.serialization.ManifestSerializer
import scala.concurrent.Future
import scala.util.Try
diff --git a/src/main/scala/org/ergoplatform/nodeView/state/UtxoState.scala b/src/main/scala/org/ergoplatform/nodeView/state/UtxoState.scala
index a4254f07b0..01b98a59ef 100644
--- a/src/main/scala/org/ergoplatform/nodeView/state/UtxoState.scala
+++ b/src/main/scala/org/ergoplatform/nodeView/state/UtxoState.scala
@@ -3,6 +3,7 @@ package org.ergoplatform.nodeView.state
import java.io.File
import org.ergoplatform.ErgoBox
import org.ergoplatform.ErgoLikeContext.Height
+import org.ergoplatform.core.VersionTag
import org.ergoplatform.modifiers.history.header.Header
import org.ergoplatform.modifiers.history.ADProofs
import org.ergoplatform.modifiers.mempool.ErgoTransaction
@@ -11,10 +12,10 @@ import org.ergoplatform.settings.Algos.HF
import org.ergoplatform.settings.ValidationRules.{fbDigestIncorrect, fbOperationFailed}
import org.ergoplatform.settings.{Algos, ErgoSettings, Parameters}
import org.ergoplatform.utils.LoggingUtil
-import org.ergoplatform.nodeView.ErgoNodeViewHolder.ReceivableMessages.LocallyGeneratedModifier
-import scorex.core._
-import scorex.core.utils.ScorexEncoding
-import scorex.core.validation.ModifierValidator
+import org.ergoplatform.utils.ScorexEncoding
+import org.ergoplatform.core._
+import org.ergoplatform.nodeView.LocallyGeneratedModifier
+import org.ergoplatform.validation.ModifierValidator
import scorex.crypto.authds.avltree.batch._
import scorex.crypto.authds.avltree.batch.serialization.{BatchAVLProverManifest, BatchAVLProverSubtree}
import scorex.crypto.authds.{ADDigest, ADValue}
@@ -49,7 +50,7 @@ class UtxoState(override val persistentProver: PersistentBatchAVLProver[Digest32
override def rollbackTo(version: VersionTag): Try[UtxoState] = persistentProver.synchronized {
val p = persistentProver
log.info(s"Rollback UtxoState to version ${Algos.encoder.encode(version)}")
- store.get(scorex.core.versionToBytes(version)) match {
+ store.get(versionToBytes(version)) match {
case Some(hash) =>
val rootHash: ADDigest = ADDigest @@ hash
val rollbackResult = p.rollback(rootHash).map { _ =>
@@ -80,7 +81,7 @@ class UtxoState(override val persistentProver: PersistentBatchAVLProver[Digest32
.orElse(boxById(id))
.fold[Try[ErgoBox]](Failure(new Exception(s"Box with id ${Algos.encode(id)} not found")))(Success(_))
- val txProcessing = ErgoState.execTransactions(transactions, currentStateContext)(checkBoxExistence)
+ val txProcessing = ErgoState.execTransactions(transactions, currentStateContext, ergoSettings.nodeSettings)(checkBoxExistence)
if (txProcessing.isValid) {
log.debug(s"Cost of block $headerId (${currentStateContext.currentHeight}): ${txProcessing.payload.getOrElse(0)}")
val blockOpsTry = ErgoState.stateChanges(transactions).flatMap { stateChanges =>
@@ -143,7 +144,8 @@ class UtxoState(override val persistentProver: PersistentBatchAVLProver[Digest32
var proofBytes = persistentProver.generateProofAndUpdateStorage(meta)
- if (!store.get(scorex.core.idToBytes(fb.id)).exists(w => java.util.Arrays.equals(w, fb.header.stateRoot))) {
+ if (!store.get(org.ergoplatform.core.idToBytes(fb.id))
+ .exists(w => java.util.Arrays.equals(w, fb.header.stateRoot))) {
throw new Exception("Storage kept roothash is not equal to the declared one")
}
@@ -192,7 +194,7 @@ class UtxoState(override val persistentProver: PersistentBatchAVLProver[Digest32
}
if (fb.adProofs.isEmpty) {
- if (fb.height >= estimatedTip.getOrElse(Int.MaxValue) - stateContext.ergoSettings.nodeSettings.adProofsSuffixLength) {
+ if (fb.height >= estimatedTip.getOrElse(Int.MaxValue) - ergoSettings.nodeSettings.adProofsSuffixLength) {
val adProofs = ADProofs(fb.header.id, proofBytes)
generate(LocallyGeneratedModifier(adProofs))
}
@@ -309,7 +311,7 @@ object UtxoState {
val store = new LDBVersionedStore(dir, initialKeepVersions = settings.nodeSettings.keepVersions)
- val defaultStateContext = ErgoStateContext.empty(settings, parameters)
+ val defaultStateContext = ErgoStateContext.empty(settings.chainSettings, parameters)
val storage = new VersionedLDBAVLStorage(store)
val persistentProver = PersistentBatchAVLProver.create(
p,
diff --git a/src/main/scala/org/ergoplatform/nodeView/state/UtxoStateReader.scala b/src/main/scala/org/ergoplatform/nodeView/state/UtxoStateReader.scala
index f717464185..a2c10bd248 100644
--- a/src/main/scala/org/ergoplatform/nodeView/state/UtxoStateReader.scala
+++ b/src/main/scala/org/ergoplatform/nodeView/state/UtxoStateReader.scala
@@ -4,13 +4,13 @@ import org.ergoplatform.ErgoBox
import org.ergoplatform.mining.emission.EmissionRules
import org.ergoplatform.modifiers.ErgoFullBlock
import org.ergoplatform.modifiers.mempool.{ErgoTransaction, UnconfirmedTransaction}
+import org.ergoplatform.modifiers.transaction.TooHighCostError
import org.ergoplatform.nodeView.mempool.ErgoMemPoolReader
import org.ergoplatform.settings.{Algos, ErgoSettings}
import org.ergoplatform.settings.Algos.HF
import org.ergoplatform.wallet.boxes.ErgoBoxSerializer
import org.ergoplatform.wallet.interpreter.ErgoInterpreter
-import scorex.core.transaction.TooHighCostError
-import scorex.core.validation.MalformedModifierError
+import org.ergoplatform.validation.MalformedModifierError
import scorex.crypto.authds.avltree.batch.{Lookup, PersistentBatchAVLProver, VersionedLDBAVLStorage}
import scorex.crypto.authds.{ADDigest, ADKey, SerializedAdProof}
import scorex.crypto.hash.Digest32
diff --git a/src/main/scala/org/ergoplatform/nodeView/wallet/BalancesSnapshot.scala b/src/main/scala/org/ergoplatform/nodeView/wallet/BalancesSnapshot.scala
index 96a6814898..888a1eed4e 100644
--- a/src/main/scala/org/ergoplatform/nodeView/wallet/BalancesSnapshot.scala
+++ b/src/main/scala/org/ergoplatform/nodeView/wallet/BalancesSnapshot.scala
@@ -1,6 +1,6 @@
package org.ergoplatform.nodeView.wallet
-import org.ergoplatform.nodeView.history.ErgoHistory.Height
+import org.ergoplatform.nodeView.history.ErgoHistoryUtils.Height
import org.ergoplatform.sdk.wallet.TokensMap
final case class BalancesSnapshot(height: Height, balance: Long, assetBalances: TokensMap)
diff --git a/src/main/scala/org/ergoplatform/nodeView/wallet/ErgoAddressJsonEncoder.scala b/src/main/scala/org/ergoplatform/nodeView/wallet/ErgoAddressJsonEncoder.scala
index acd5920bfe..2cc994fcef 100644
--- a/src/main/scala/org/ergoplatform/nodeView/wallet/ErgoAddressJsonEncoder.scala
+++ b/src/main/scala/org/ergoplatform/nodeView/wallet/ErgoAddressJsonEncoder.scala
@@ -2,20 +2,20 @@ package org.ergoplatform.nodeView.wallet
import io.circe.syntax._
import io.circe.{Decoder, DecodingFailure, Encoder}
-import org.ergoplatform.settings.ErgoSettings
+import org.ergoplatform.settings.ChainSettings
import org.ergoplatform.{ErgoAddress, ErgoAddressEncoder}
import scala.util.{Failure, Success}
-case class ErgoAddressJsonEncoder(settings: ErgoSettings) {
+case class ErgoAddressJsonEncoder(chainSettings: ChainSettings) {
implicit val encoder: Encoder[ErgoAddress] = { address =>
- ErgoAddressEncoder(settings.chainSettings.addressPrefix).toString(address).asJson
+ ErgoAddressEncoder(chainSettings.addressPrefix).toString(address).asJson
}
implicit val decoder: Decoder[ErgoAddress] = { cursor =>
def decodeString(addrStr: String) = {
- ErgoAddressEncoder(settings.chainSettings.addressPrefix).fromString(addrStr) match {
+ ErgoAddressEncoder(chainSettings.addressPrefix).fromString(addrStr) match {
case Success(address) => Right(address)
case Failure(exception) => Left(DecodingFailure(exception.toString, cursor.history))
}
diff --git a/src/main/scala/org/ergoplatform/nodeView/wallet/ErgoWallet.scala b/src/main/scala/org/ergoplatform/nodeView/wallet/ErgoWallet.scala
index 5971ff24ff..54c0808eb0 100644
--- a/src/main/scala/org/ergoplatform/nodeView/wallet/ErgoWallet.scala
+++ b/src/main/scala/org/ergoplatform/nodeView/wallet/ErgoWallet.scala
@@ -5,10 +5,10 @@ import org.ergoplatform.modifiers.mempool.ErgoTransaction
import org.ergoplatform.modifiers.{ErgoFullBlock, BlockSection}
import org.ergoplatform.nodeView.history.ErgoHistoryReader
import org.ergoplatform.nodeView.state.ErgoState
-import org.ergoplatform.nodeView.wallet.ErgoWalletActor._
+import org.ergoplatform.nodeView.wallet.ErgoWalletActorMessages._
import org.ergoplatform.settings.{ErgoSettings, Parameters}
import org.ergoplatform.wallet.boxes.{ReemissionData, ReplaceCompactCollectBoxSelector}
-import scorex.core.VersionTag
+import org.ergoplatform.core.VersionTag
import scorex.util.ScorexLogging
import scala.util.{Failure, Success, Try}
@@ -64,7 +64,7 @@ class ErgoWallet(historyReader: ErgoHistoryReader, settings: ErgoSettings, param
}
def rollback(to: VersionTag): Try[ErgoWallet] =
- historyReader.heightOf(scorex.core.versionToId(to)) match {
+ historyReader.heightOf(org.ergoplatform.core.versionToId(to)) match {
case Some(_) =>
walletActor ! Rollback(to)
Success(this)
diff --git a/src/main/scala/org/ergoplatform/nodeView/wallet/ErgoWalletActor.scala b/src/main/scala/org/ergoplatform/nodeView/wallet/ErgoWalletActor.scala
index 3c1594e091..c65599f212 100644
--- a/src/main/scala/org/ergoplatform/nodeView/wallet/ErgoWalletActor.scala
+++ b/src/main/scala/org/ergoplatform/nodeView/wallet/ErgoWalletActor.scala
@@ -4,32 +4,23 @@ import akka.actor.SupervisorStrategy.{Restart, Stop}
import akka.actor._
import akka.pattern.StatusReply
import org.ergoplatform.ErgoBox._
-import org.ergoplatform.modifiers.ErgoFullBlock
-import org.ergoplatform.modifiers.mempool.{ErgoTransaction, UnsignedErgoTransaction}
-import org.ergoplatform.network.ErgoNodeViewSynchronizer.ReceivableMessages.{ChangedMempool, ChangedState}
-import org.ergoplatform.nodeView.history.{ErgoHistory, ErgoHistoryReader}
+import org.ergoplatform.network.ErgoNodeViewSynchronizerMessages.{ChangedMempool, ChangedState}
+import org.ergoplatform.nodeView.history.ErgoHistoryReader
import org.ergoplatform.nodeView.mempool.ErgoMemPoolReader
import org.ergoplatform.nodeView.state.ErgoStateReader
-import org.ergoplatform.nodeView.wallet.ErgoWalletService.DeriveNextKeyResult
-import org.ergoplatform.nodeView.wallet.models.CollectedBoxes
-import org.ergoplatform.nodeView.wallet.requests.{ExternalSecret, TransactionGenerationRequest}
-import org.ergoplatform.nodeView.wallet.scanning.{Scan, ScanRequest}
+import org.ergoplatform.nodeView.wallet.ErgoWalletServiceUtils.DeriveNextKeyResult
import org.ergoplatform.sdk.wallet.secrets.DerivationPath
import org.ergoplatform.settings._
import org.ergoplatform.wallet.Constants.ScanId
-import org.ergoplatform.wallet.boxes.{BoxSelector, ChainStatus}
+import org.ergoplatform.wallet.boxes.BoxSelector
import org.ergoplatform.wallet.interface4j.SecretString
-import org.ergoplatform.wallet.interpreter.TransactionHintsBag
+import org.ergoplatform.nodeView.wallet.ErgoWalletActorMessages._
import org.ergoplatform._
-import scorex.core.VersionTag
-import scorex.core.utils.ScorexEncoding
-import scorex.util.{ModifierId, ScorexLogging}
-import sigmastate.Values.SigmaBoolean
-import sigmastate.crypto.DLogProtocol.{DLogProverInput, ProveDlog}
-
+import org.ergoplatform.core.VersionTag
+import org.ergoplatform.utils.ScorexEncoding
+import scorex.util.ScorexLogging
import scala.concurrent.duration._
-import scala.util.{Failure, Success, Try}
-
+import scala.util.{Failure, Success}
class ErgoWalletActor(settings: ErgoSettings,
parameters: Parameters,
@@ -38,8 +29,6 @@ class ErgoWalletActor(settings: ErgoSettings,
historyReader: ErgoHistoryReader)
extends Actor with Stash with ScorexLogging with ScorexEncoding {
- import ErgoWalletActor._
-
private val ergoAddressEncoder: ErgoAddressEncoder = settings.addressEncoder
override val supervisorStrategy: OneForOneStrategy =
@@ -530,392 +519,4 @@ object ErgoWalletActor extends ScorexLogging {
)
walletActorRef
}
-
- // Private signals the wallet actor sends to itself
- /**
- * A signal the wallet actor sends to itself to scan a block in the past
- *
- * @param blockHeight - height of a block to scan
- * @param rescan - scan a block even if height is out of order, to serve rescan requests from arbitrary height
- */
- private final case class ScanInThePast(blockHeight: ErgoHistory.Height, rescan: Boolean)
-
-
- // Publicly available signals for the wallet actor
-
- /**
- * Command to scan offchain transaction
- *
- * @param tx - offchain transaction
- */
- final case class ScanOffChain(tx: ErgoTransaction)
-
- /**
- * Command to scan a block
- *
- * @param block - block to scan
- */
- final case class ScanOnChain(block: ErgoFullBlock)
-
- /**
- * Rollback to previous version of the wallet, by throwing away effects of blocks after the version
- *
- * @param version
- */
- final case class Rollback(version: VersionTag)
-
- /**
- * Generate new transaction fulfilling given requests
- *
- * @param requests
- * @param inputsRaw
- * @param dataInputsRaw
- * @param sign
- */
- final case class GenerateTransaction(requests: Seq[TransactionGenerationRequest],
- inputsRaw: Seq[String],
- dataInputsRaw: Seq[String],
- sign: Boolean)
-
- /**
- * Request to generate commitments for an unsigned transaction
- *
- * @param utx - unsigned transaction
- * @param secrets - optionally, externally provided secrets
- * @param inputsOpt - optionally, externally provided inputs
- * @param dataInputsOpt - optionally, externally provided inputs
- */
- case class GenerateCommitmentsFor(utx: UnsignedErgoTransaction,
- secrets: Option[Seq[ExternalSecret]],
- inputsOpt: Option[Seq[ErgoBox]],
- dataInputsOpt: Option[Seq[ErgoBox]])
-
- /**
- * Response for commitments generation request
- *
- * @param response - hints to sign a transaction
- */
- case class GenerateCommitmentsResponse(response: Try[TransactionHintsBag])
-
- /**
- * A request to sign a transaction
- *
- * @param utx - unsigned transaction
- * @param secrets - additional secrets given to the prover
- * @param hints - hints used for transaction signing (commitments and partial proofs)
- * @param boxesToSpend - boxes the transaction is spending
- * @param dataBoxes - read-only inputs of the transaction
- */
- case class SignTransaction(utx: UnsignedErgoTransaction,
- secrets: Seq[ExternalSecret],
- hints: TransactionHintsBag,
- boxesToSpend: Option[Seq[ErgoBox]],
- dataBoxes: Option[Seq[ErgoBox]])
-
- /**
- *
- * @param chainStatus
- */
- final case class ReadBalances(chainStatus: ChainStatus)
-
- /**
- * Read a slice of wallet public keys
- *
- * @param from
- * @param until
- */
- final case class ReadPublicKeys(from: Int, until: Int)
-
- /**
- * Read all wallet public keys
- */
- final case class ReadExtendedPublicKeys()
-
- /**
- * Get the private key from seed based on a given derivation path
- */
- final case class GetPrivateKeyFromPath(path: DerivationPath)
-
- /**
- * Read wallet either from mnemonic or from secret storage
- */
- final case class ReadWallet(state: ErgoWalletState)
-
- /**
- * Initialize wallet with given wallet pass and optional mnemonic pass (according to BIP-32)
- *
- * @param walletPass
- * @param mnemonicPassOpt
- */
- final case class InitWallet(walletPass: SecretString, mnemonicPassOpt: Option[SecretString])
-
- /**
- * Restore wallet with mnemonic, optional mnemonic password and (mandatory) wallet encryption password
- *
- * @param mnemonic
- * @param mnemonicPassOpt
- * @param walletPass
- */
- final case class RestoreWallet(mnemonic: SecretString, mnemonicPassOpt: Option[SecretString], walletPass: SecretString, usePre1627KeyDerivation: Boolean)
-
- /**
- * Unlock wallet with wallet password
- *
- * @param walletPass
- */
- final case class UnlockWallet(walletPass: SecretString)
-
- /**
- * Derive key with given path according to BIP-32
- *
- * @param path
- */
- final case class DeriveKey(path: String)
-
- /**
- * Get boxes related to P2PK payments
- *
- * @param unspentOnly - return only unspent boxes
- * @param considerUnconfirmed - consider mempool (filter our unspent boxes spent in the pool if unspent = true, add
- * boxes created in the pool for both values of unspentOnly).
- */
- final case class GetWalletBoxes(unspentOnly: Boolean, considerUnconfirmed: Boolean)
-
- /**
- * Get boxes by requested params
- *
- * @param targetBalance - Balance requested by user
- * @param targetAssets - IDs and amounts of other tokens
- */
- final case class CollectWalletBoxes(targetBalance: Long, targetAssets: Map[ErgoBox.TokenId, Long])
-
- /**
- * Wallet's response for requested boxes
- *
- * @param result
- */
- final case class ReqBoxesResponse(result: Try[CollectedBoxes])
-
- /**
- * Get scan related transactions
- *
- * @param scanId - Scan identifier
- * @param includeUnconfirmed - whether to include transactions from mempool that match given scanId
- */
- final case class GetScanTransactions(scanId: ScanId, includeUnconfirmed: Boolean)
-
- /**
- * Response for requested scan related transactions
- *
- * @param result
- */
- final case class ScanRelatedTxsResponse(result: Seq[AugWalletTransaction])
-
- /**
- * Get unspent boxes related to a scan
- *
- * @param scanId - scan identifier
- * @param considerUnconfirmed - consider boxes from mempool
- * @param minHeight - min inclusion height of unspent boxes
- * @param maxHeight - max inclusion height of unspent boxes
- */
- final case class GetScanUnspentBoxes(scanId: ScanId, considerUnconfirmed: Boolean, minHeight: Int, maxHeight: Int)
-
- /**
- * Get spent boxes related to a scan
- *
- * @param scanId - scan identifier
- */
- final case class GetScanSpentBoxes(scanId: ScanId)
-
- /**
- * Set or update address for change outputs. Initially the address is set to root key address
- *
- * @param address
- */
- final case class UpdateChangeAddress(address: P2PKAddress)
-
- /**
- * Command to register new scan
- *
- * @param appRequest
- */
- final case class AddScan(appRequest: ScanRequest)
-
- /**
- * Wallet's response for scan registration request
- *
- * @param response
- */
- final case class AddScanResponse(response: Try[Scan])
-
- /**
- * Command to deregister a scan
- *
- * @param scanId
- */
- final case class RemoveScan(scanId: ScanId)
-
- /**
- * Wallet's response for scan removal request
- *
- * @param response
- */
- final case class RemoveScanResponse(response: Try[Unit])
-
- /**
- * Get wallet-related transaction
- *
- * @param id
- */
- final case class GetTransaction(id: ModifierId)
-
- final case class CheckSeed(mnemonic: SecretString, passOpt: Option[SecretString])
-
- /**
- * Get wallet-related transaction
- */
- case object GetTransactions
-
- /**
- * Get filtered scan-related txs
- * @param scanIds - scan identifiers
- * @param minHeight - minimal tx inclusion height
- * @param maxHeight - maximal tx inclusion height
- * @param minConfNum - minimal confirmations number
- * @param maxConfNum - maximal confirmations number
- * @param includeUnconfirmed - whether to include transactions from mempool that match given scanId
- */
- case class GetFilteredScanTxs(scanIds: List[ScanId],
- minHeight: Int,
- maxHeight: Int,
- minConfNum: Int,
- maxConfNum: Int,
- includeUnconfirmed: Boolean)
-
- /**
- * Derive next key-pair according to BIP-32
- * //todo: describe procedure or provide a link
- */
- case object DeriveNextKey
-
- /**
- * Lock wallet
- */
- case object LockWallet
-
- /**
- * Close wallet
- */
- case object CloseWallet
-
- /**
- * Rescan wallet
- */
- case class RescanWallet(fromHeight: Int)
-
- /**
- * Get wallet status
- */
- case object GetWalletStatus
-
- /**
- * Wallet status. To be sent in response to GetWalletStatus
- *
- * @param initialized - whether wallet is initialized or not
- * @param unlocked - whether wallet is unlocked or not
- * @param changeAddress - address used for change (optional)
- * @param height - last height scanned
- */
- case class WalletStatus(initialized: Boolean,
- unlocked: Boolean,
- changeAddress: Option[P2PKAddress],
- height: ErgoHistory.Height,
- error: Option[String])
-
- /**
- * Get root secret key (used in miner)
- */
- case object GetFirstSecret
-
- /**
- * Response with root secret key (used in miner)
- */
- case class FirstSecretResponse(secret: Try[DLogProverInput])
-
- /**
- * Get mining public key
- */
- case object GetMiningPubKey
-
- /**
- * Response with mining public key
- */
- case class MiningPubKeyResponse(miningPubKeyOpt: Option[ProveDlog])
-
- /**
- * Get registered scans list
- */
- case object ReadScans
-
- /**
- * Get registered scans list
- */
- case class ReadScansResponse(apps: Seq[Scan])
-
- /**
- * Remove association between a scan and a box (remove a box if its the only one which belongs to the
- * scan)
- *
- * @param scanId
- * @param boxId
- */
- case class StopTracking(scanId: ScanId, boxId: BoxId)
-
- /**
- * Wrapper for a result of StopTracking processing
- *
- * @param status
- */
- case class StopTrackingResponse(status: Try[Unit])
-
- /**
- * A request to extract hints from given transaction
- *
- * @param tx - transaction to extract hints from
- * @param real - public keys corresponing to the secrets known
- * @param simulated - public keys to simulate
- * @param inputsOpt - optionally, externally provided inputs
- * @param dataInputsOpt - optionally, externally provided inputs
- */
- case class ExtractHints(tx: ErgoTransaction,
- real: Seq[SigmaBoolean],
- simulated: Seq[SigmaBoolean],
- inputsOpt: Option[Seq[ErgoBox]],
- dataInputsOpt: Option[Seq[ErgoBox]])
-
- /**
- * Result of hints generation operation
- *
- * @param transactionHintsBag - hints for transaction
- */
- case class ExtractHintsResult(transactionHintsBag: TransactionHintsBag)
-
-
- /**
- * Add association between a scan and a box (and add the box to the database if it is not there)
- *
- * @param box
- * @param scanIds
- *
- */
- case class AddBox(box: ErgoBox, scanIds: Set[ScanId])
-
- /**
- * Wrapper for a result of AddBox processing
- *
- * @param status
- */
- case class AddBoxResponse(status: Try[Unit])
-
}
diff --git a/src/main/scala/org/ergoplatform/nodeView/wallet/ErgoWalletActorMessages.scala b/src/main/scala/org/ergoplatform/nodeView/wallet/ErgoWalletActorMessages.scala
new file mode 100644
index 0000000000..c1f12a4941
--- /dev/null
+++ b/src/main/scala/org/ergoplatform/nodeView/wallet/ErgoWalletActorMessages.scala
@@ -0,0 +1,414 @@
+package org.ergoplatform.nodeView.wallet
+
+import org.ergoplatform.ErgoBox._
+import org.ergoplatform.modifiers.ErgoFullBlock
+import org.ergoplatform.modifiers.mempool.{ErgoTransaction, UnsignedErgoTransaction}
+import org.ergoplatform.nodeView.history.ErgoHistoryUtils._
+import org.ergoplatform.nodeView.wallet.models.CollectedBoxes
+import org.ergoplatform.nodeView.wallet.requests.{ExternalSecret, TransactionGenerationRequest}
+import org.ergoplatform.nodeView.wallet.scanning.{Scan, ScanRequest}
+import org.ergoplatform.sdk.wallet.secrets.DerivationPath
+import org.ergoplatform.wallet.Constants.ScanId
+import org.ergoplatform.wallet.boxes.ChainStatus
+import org.ergoplatform.wallet.interface4j.SecretString
+import org.ergoplatform.wallet.interpreter.TransactionHintsBag
+import org.ergoplatform._
+import org.ergoplatform.core.VersionTag
+import scorex.util.ModifierId
+import sigmastate.Values.SigmaBoolean
+import sigmastate.crypto.DLogProtocol.{DLogProverInput, ProveDlog}
+import scala.util.Try
+
+/**
+ * Repository for messages processed by ErgoWalletActors
+ */
+object ErgoWalletActorMessages {
+
+ // Private signals the wallet actor sends to itself
+ /**
+ * A signal the wallet actor sends to itself to scan a block in the past
+ *
+ * @param blockHeight - height of a block to scan
+ * @param rescan - scan a block even if height is out of order, to serve rescan requests from arbitrary height
+ */
+ final case class ScanInThePast(blockHeight: Height, rescan: Boolean)
+
+
+ // Publicly available signals for the wallet actor
+
+ /**
+ * Command to scan offchain transaction
+ *
+ * @param tx - offchain transaction
+ */
+ final case class ScanOffChain(tx: ErgoTransaction)
+
+ /**
+ * Command to scan a block
+ *
+ * @param block - block to scan
+ */
+ final case class ScanOnChain(block: ErgoFullBlock)
+
+ /**
+ * Rollback to previous version of the wallet, by throwing away effects of blocks after the version
+ *
+ * @param version
+ */
+ final case class Rollback(version: VersionTag)
+
+ /**
+ * Generate new transaction fulfilling given requests
+ *
+ * @param requests
+ * @param inputsRaw
+ * @param dataInputsRaw
+ * @param sign
+ */
+ final case class GenerateTransaction(requests: Seq[TransactionGenerationRequest],
+ inputsRaw: Seq[String],
+ dataInputsRaw: Seq[String],
+ sign: Boolean)
+
+ /**
+ * Request to generate commitments for an unsigned transaction
+ *
+ * @param utx - unsigned transaction
+ * @param secrets - optionally, externally provided secrets
+ * @param inputsOpt - optionally, externally provided inputs
+ * @param dataInputsOpt - optionally, externally provided inputs
+ */
+ case class GenerateCommitmentsFor(utx: UnsignedErgoTransaction,
+ secrets: Option[Seq[ExternalSecret]],
+ inputsOpt: Option[Seq[ErgoBox]],
+ dataInputsOpt: Option[Seq[ErgoBox]])
+
+ /**
+ * Response for commitments generation request
+ *
+ * @param response - hints to sign a transaction
+ */
+ case class GenerateCommitmentsResponse(response: Try[TransactionHintsBag])
+
+ /**
+ * A request to sign a transaction
+ *
+ * @param utx - unsigned transaction
+ * @param secrets - additional secrets given to the prover
+ * @param hints - hints used for transaction signing (commitments and partial proofs)
+ * @param boxesToSpend - boxes the transaction is spending
+ * @param dataBoxes - read-only inputs of the transaction
+ */
+ case class SignTransaction(utx: UnsignedErgoTransaction,
+ secrets: Seq[ExternalSecret],
+ hints: TransactionHintsBag,
+ boxesToSpend: Option[Seq[ErgoBox]],
+ dataBoxes: Option[Seq[ErgoBox]])
+
+ /**
+ *
+ * @param chainStatus
+ */
+ final case class ReadBalances(chainStatus: ChainStatus)
+
+ /**
+ * Read a slice of wallet public keys
+ *
+ * @param from
+ * @param until
+ */
+ final case class ReadPublicKeys(from: Int, until: Int)
+
+ /**
+ * Read all wallet public keys
+ */
+ final case class ReadExtendedPublicKeys()
+
+ /**
+ * Get the private key from seed based on a given derivation path
+ */
+ final case class GetPrivateKeyFromPath(path: DerivationPath)
+
+ /**
+ * Read wallet either from mnemonic or from secret storage
+ */
+ final case class ReadWallet(state: ErgoWalletState)
+
+ /**
+ * Initialize wallet with given wallet pass and optional mnemonic pass (according to BIP-32)
+ *
+ * @param walletPass
+ * @param mnemonicPassOpt
+ */
+ final case class InitWallet(walletPass: SecretString, mnemonicPassOpt: Option[SecretString])
+
+ /**
+ * Restore wallet with mnemonic, optional mnemonic password and (mandatory) wallet encryption password
+ *
+ * @param mnemonic
+ * @param mnemonicPassOpt
+ * @param walletPass
+ */
+ final case class RestoreWallet(mnemonic: SecretString, mnemonicPassOpt: Option[SecretString], walletPass: SecretString, usePre1627KeyDerivation: Boolean)
+
+ /**
+ * Unlock wallet with wallet password
+ *
+ * @param walletPass
+ */
+ final case class UnlockWallet(walletPass: SecretString)
+
+ /**
+ * Derive key with given path according to BIP-32
+ *
+ * @param path
+ */
+ final case class DeriveKey(path: String)
+
+ /**
+ * Get boxes related to P2PK payments
+ *
+ * @param unspentOnly - return only unspent boxes
+ * @param considerUnconfirmed - consider mempool (filter our unspent boxes spent in the pool if unspent = true, add
+ * boxes created in the pool for both values of unspentOnly).
+ */
+ final case class GetWalletBoxes(unspentOnly: Boolean, considerUnconfirmed: Boolean)
+
+ /**
+ * Get boxes by requested params
+ *
+ * @param targetBalance - Balance requested by user
+ * @param targetAssets - IDs and amounts of other tokens
+ */
+ final case class CollectWalletBoxes(targetBalance: Long, targetAssets: Map[ErgoBox.TokenId, Long])
+
+ /**
+ * Wallet's response for requested boxes
+ *
+ * @param result
+ */
+ final case class ReqBoxesResponse(result: Try[CollectedBoxes])
+
+ /**
+ * Get scan related transactions
+ *
+ * @param scanId - Scan identifier
+ * @param includeUnconfirmed - whether to include transactions from mempool that match given scanId
+ */
+ final case class GetScanTransactions(scanId: ScanId, includeUnconfirmed: Boolean)
+
+ /**
+ * Response for requested scan related transactions
+ *
+ * @param result
+ */
+ final case class ScanRelatedTxsResponse(result: Seq[AugWalletTransaction])
+
+ /**
+ * Get unspent boxes related to a scan
+ *
+ * @param scanId - scan identifier
+ * @param considerUnconfirmed - consider boxes from mempool
+ * @param minHeight - min inclusion height of unspent boxes
+ * @param maxHeight - max inclusion height of unspent boxes
+ */
+ final case class GetScanUnspentBoxes(scanId: ScanId, considerUnconfirmed: Boolean, minHeight: Int, maxHeight: Int)
+
+ /**
+ * Get spent boxes related to a scan
+ *
+ * @param scanId - scan identifier
+ */
+ final case class GetScanSpentBoxes(scanId: ScanId)
+
+ /**
+ * Set or update address for change outputs. Initially the address is set to root key address
+ *
+ * @param address
+ */
+ final case class UpdateChangeAddress(address: P2PKAddress)
+
+ /**
+ * Command to register new scan
+ *
+ * @param appRequest
+ */
+ final case class AddScan(appRequest: ScanRequest)
+
+ /**
+ * Wallet's response for scan registration request
+ *
+ * @param response
+ */
+ final case class AddScanResponse(response: Try[Scan])
+
+ /**
+ * Command to deregister a scan
+ *
+ * @param scanId
+ */
+ final case class RemoveScan(scanId: ScanId)
+
+ /**
+ * Wallet's response for scan removal request
+ *
+ * @param response
+ */
+ final case class RemoveScanResponse(response: Try[Unit])
+
+ /**
+ * Get wallet-related transaction
+ *
+ * @param id
+ */
+ final case class GetTransaction(id: ModifierId)
+
+ final case class CheckSeed(mnemonic: SecretString, passOpt: Option[SecretString])
+
+ /**
+ * Get wallet-related transaction
+ */
+ case object GetTransactions
+
+ /**
+ * Get filtered scan-related txs
+ * @param scanIds - scan identifiers
+ * @param minHeight - minimal tx inclusion height
+ * @param maxHeight - maximal tx inclusion height
+ * @param minConfNum - minimal confirmations number
+ * @param maxConfNum - maximal confirmations number
+ * @param includeUnconfirmed - whether to include transactions from mempool that match given scanId
+ */
+ case class GetFilteredScanTxs(scanIds: List[ScanId],
+ minHeight: Int,
+ maxHeight: Int,
+ minConfNum: Int,
+ maxConfNum: Int,
+ includeUnconfirmed: Boolean)
+
+ /**
+ * Derive next key-pair according to BIP-32
+ * //todo: describe procedure or provide a link
+ */
+ case object DeriveNextKey
+
+ /**
+ * Lock wallet
+ */
+ case object LockWallet
+
+ /**
+ * Close wallet
+ */
+ case object CloseWallet
+
+ /**
+ * Rescan wallet
+ */
+ case class RescanWallet(fromHeight: Int)
+
+ /**
+ * Get wallet status
+ */
+ case object GetWalletStatus
+
+ /**
+ * Wallet status. To be sent in response to GetWalletStatus
+ *
+ * @param initialized - whether wallet is initialized or not
+ * @param unlocked - whether wallet is unlocked or not
+ * @param changeAddress - address used for change (optional)
+ * @param height - last height scanned
+ */
+ case class WalletStatus(initialized: Boolean,
+ unlocked: Boolean,
+ changeAddress: Option[P2PKAddress],
+ height: Height,
+ error: Option[String])
+
+ /**
+ * Get root secret key (used in miner)
+ */
+ case object GetFirstSecret
+
+ /**
+ * Response with root secret key (used in miner)
+ */
+ case class FirstSecretResponse(secret: Try[DLogProverInput])
+
+ /**
+ * Get mining public key
+ */
+ case object GetMiningPubKey
+
+ /**
+ * Response with mining public key
+ */
+ case class MiningPubKeyResponse(miningPubKeyOpt: Option[ProveDlog])
+
+ /**
+ * Get registered scans list
+ */
+ case object ReadScans
+
+ /**
+ * Get registered scans list
+ */
+ case class ReadScansResponse(apps: Seq[Scan])
+
+ /**
+ * Remove association between a scan and a box (remove a box if its the only one which belongs to the
+ * scan)
+ *
+ * @param scanId
+ * @param boxId
+ */
+ case class StopTracking(scanId: ScanId, boxId: BoxId)
+
+ /**
+ * Wrapper for a result of StopTracking processing
+ *
+ * @param status
+ */
+ case class StopTrackingResponse(status: Try[Unit])
+
+ /**
+ * A request to extract hints from given transaction
+ *
+ * @param tx - transaction to extract hints from
+ * @param real - public keys corresponing to the secrets known
+ * @param simulated - public keys to simulate
+ * @param inputsOpt - optionally, externally provided inputs
+ * @param dataInputsOpt - optionally, externally provided inputs
+ */
+ case class ExtractHints(tx: ErgoTransaction,
+ real: Seq[SigmaBoolean],
+ simulated: Seq[SigmaBoolean],
+ inputsOpt: Option[Seq[ErgoBox]],
+ dataInputsOpt: Option[Seq[ErgoBox]])
+
+ /**
+ * Result of hints generation operation
+ *
+ * @param transactionHintsBag - hints for transaction
+ */
+ case class ExtractHintsResult(transactionHintsBag: TransactionHintsBag)
+
+
+ /**
+ * Add association between a scan and a box (and add the box to the database if it is not there)
+ *
+ * @param box
+ * @param scanIds
+ *
+ */
+ case class AddBox(box: ErgoBox, scanIds: Set[ScanId])
+
+ /**
+ * Wrapper for a result of AddBox processing
+ *
+ * @param status
+ */
+ case class AddBoxResponse(status: Try[Unit])
+
+}
diff --git a/src/main/scala/org/ergoplatform/nodeView/wallet/ErgoWalletReader.scala b/src/main/scala/org/ergoplatform/nodeView/wallet/ErgoWalletReader.scala
index fd2d38ba76..ca8fa867d0 100644
--- a/src/main/scala/org/ergoplatform/nodeView/wallet/ErgoWalletReader.scala
+++ b/src/main/scala/org/ergoplatform/nodeView/wallet/ErgoWalletReader.scala
@@ -5,8 +5,8 @@ import akka.pattern.ask
import akka.util.Timeout
import org.ergoplatform.ErgoBox.BoxId
import org.ergoplatform.modifiers.mempool.{ErgoTransaction, UnsignedErgoTransaction}
-import org.ergoplatform.nodeView.wallet.ErgoWalletActor._
-import org.ergoplatform.nodeView.wallet.ErgoWalletService.DeriveNextKeyResult
+import org.ergoplatform.nodeView.wallet.ErgoWalletActorMessages._
+import org.ergoplatform.nodeView.wallet.ErgoWalletServiceUtils.DeriveNextKeyResult
import org.ergoplatform.nodeView.wallet.persistence.WalletDigest
import org.ergoplatform.nodeView.wallet.requests.{BoxesRequest, ExternalSecret, TransactionGenerationRequest}
import org.ergoplatform.nodeView.wallet.scanning.ScanRequest
@@ -16,8 +16,7 @@ import org.ergoplatform.wallet.boxes.ChainStatus
import org.ergoplatform.wallet.boxes.ChainStatus.{OffChain, OnChain}
import org.ergoplatform.wallet.interface4j.SecretString
import org.ergoplatform.wallet.interpreter.TransactionHintsBag
-import org.ergoplatform.{ErgoBox, P2PKAddress}
-import scorex.core.NodeViewComponent
+import org.ergoplatform.{ErgoBox, NodeViewComponent, P2PKAddress}
import scorex.util.ModifierId
import sigmastate.Values.SigmaBoolean
import sigmastate.crypto.DLogProtocol.DLogProverInput
diff --git a/src/main/scala/org/ergoplatform/nodeView/wallet/ErgoWalletService.scala b/src/main/scala/org/ergoplatform/nodeView/wallet/ErgoWalletService.scala
index 7ff6ab2d72..b84402e288 100644
--- a/src/main/scala/org/ergoplatform/nodeView/wallet/ErgoWalletService.scala
+++ b/src/main/scala/org/ergoplatform/nodeView/wallet/ErgoWalletService.scala
@@ -6,23 +6,22 @@ import org.ergoplatform._
import org.ergoplatform.modifiers.ErgoFullBlock
import org.ergoplatform.modifiers.mempool.{ErgoTransaction, UnsignedErgoTransaction}
import org.ergoplatform.nodeView.state.{ErgoStateContext, UtxoStateReader}
-import org.ergoplatform.nodeView.wallet.ErgoWalletService.DeriveNextKeyResult
+import org.ergoplatform.nodeView.wallet.ErgoWalletServiceUtils.DeriveNextKeyResult
import org.ergoplatform.nodeView.wallet.models.{ChangeBox, CollectedBoxes}
import org.ergoplatform.nodeView.wallet.persistence.{WalletRegistry, WalletStorage}
import org.ergoplatform.nodeView.wallet.requests.{ExternalSecret, TransactionGenerationRequest}
import org.ergoplatform.nodeView.wallet.scanning.{Scan, ScanRequest}
-import org.ergoplatform.sdk.wallet.secrets.{DerivationPath, ExtendedSecretKey}
+import org.ergoplatform.sdk.wallet.secrets.DerivationPath
import org.ergoplatform.settings.{ErgoSettings, Parameters}
import org.ergoplatform.wallet.Constants.ScanId
-import org.ergoplatform.wallet.boxes.{BoxSelector, ErgoBoxSerializer, TrackedBox}
+import org.ergoplatform.wallet.boxes.{BoxSelector, TrackedBox}
import org.ergoplatform.wallet.interface4j.SecretString
import org.ergoplatform.wallet.interpreter.{ErgoProvingInterpreter, TransactionHintsBag}
import org.ergoplatform.wallet.mnemonic.Mnemonic
import org.ergoplatform.wallet.secrets.JsonSecretStorage
import org.ergoplatform.wallet.settings.SecretStorageSettings
import org.ergoplatform.wallet.utils.FileUtils
-import scorex.util.encode.Base16
-import scorex.util.{ModifierId}
+import scorex.util.ModifierId
import sigmastate.Values.SigmaBoolean
import sigmastate.crypto.DLogProtocol.DLogProverInput
import sigma.Extensions.CollBytesOps
@@ -678,16 +677,4 @@ class ErgoWalletServiceImpl(override val ergoSettings: ErgoSettings) extends Erg
.map(ErgoTransaction.apply)
}
-}
-
-object ErgoWalletService {
- /**
- * Result of "deriveNextKey" operation
- */
- case class DeriveNextKeyResult(result: Try[(DerivationPath, P2PKAddress, ExtendedSecretKey)])
-
- // A helper which is deserializing Base16-encoded boxes to ErgoBox instances
- def stringsToBoxes(strings: Seq[String]): Seq[ErgoBox] =
- strings.map(in => Base16.decode(in).flatMap(ErgoBoxSerializer.parseBytesTry)).map(_.get)
-
-}
+}
\ No newline at end of file
diff --git a/src/main/scala/org/ergoplatform/nodeView/wallet/ErgoWalletServiceUtils.scala b/src/main/scala/org/ergoplatform/nodeView/wallet/ErgoWalletServiceUtils.scala
new file mode 100644
index 0000000000..c5bf8b97f0
--- /dev/null
+++ b/src/main/scala/org/ergoplatform/nodeView/wallet/ErgoWalletServiceUtils.scala
@@ -0,0 +1,23 @@
+package org.ergoplatform.nodeView.wallet
+
+import org.ergoplatform._
+import org.ergoplatform.sdk.wallet.secrets.{DerivationPath, ExtendedSecretKey}
+import org.ergoplatform.wallet.boxes.ErgoBoxSerializer
+import scorex.util.encode.Base16
+import scala.util.Try
+
+/**
+ * Additional types and functions used in ErgoWalletService
+ */
+object ErgoWalletServiceUtils {
+ /**
+ * Result of "deriveNextKey" operation
+ */
+ case class DeriveNextKeyResult(result: Try[(DerivationPath, P2PKAddress, ExtendedSecretKey)])
+
+ // A helper which is deserializing Base16-encoded boxes to ErgoBox instances
+ def stringsToBoxes(strings: Seq[String]): Seq[ErgoBox] =
+ strings.map(in => Base16.decode(in).flatMap(ErgoBoxSerializer.parseBytesTry)).map(_.get)
+
+}
+
diff --git a/src/main/scala/org/ergoplatform/nodeView/wallet/ErgoWalletState.scala b/src/main/scala/org/ergoplatform/nodeView/wallet/ErgoWalletState.scala
index 049893830f..03fe2cc98d 100644
--- a/src/main/scala/org/ergoplatform/nodeView/wallet/ErgoWalletState.scala
+++ b/src/main/scala/org/ergoplatform/nodeView/wallet/ErgoWalletState.scala
@@ -3,7 +3,7 @@ package org.ergoplatform.nodeView.wallet
import com.google.common.hash.BloomFilter
import org.ergoplatform.ErgoBox.BoxId
import org.ergoplatform._
-import org.ergoplatform.nodeView.history.ErgoHistory.Height
+import org.ergoplatform.nodeView.history.ErgoHistoryUtils.Height
import org.ergoplatform.nodeView.mempool.ErgoMemPoolReader
import org.ergoplatform.nodeView.state.{ErgoStateContext, ErgoStateReader, UtxoStateReader}
import org.ergoplatform.nodeView.wallet.ErgoWalletState.FilterFn
diff --git a/src/main/scala/org/ergoplatform/nodeView/wallet/ErgoWalletSupport.scala b/src/main/scala/org/ergoplatform/nodeView/wallet/ErgoWalletSupport.scala
index 247c6cd116..2854306ddd 100644
--- a/src/main/scala/org/ergoplatform/nodeView/wallet/ErgoWalletSupport.scala
+++ b/src/main/scala/org/ergoplatform/nodeView/wallet/ErgoWalletSupport.scala
@@ -5,7 +5,7 @@ import cats.implicits._
import org.ergoplatform.ErgoBox.{BoxId, R4, R5, R6}
import org.ergoplatform._
import org.ergoplatform.modifiers.mempool.UnsignedErgoTransaction
-import org.ergoplatform.nodeView.wallet.ErgoWalletService.DeriveNextKeyResult
+import org.ergoplatform.nodeView.wallet.ErgoWalletServiceUtils.DeriveNextKeyResult
import org.ergoplatform.nodeView.wallet.persistence.WalletStorage
import org.ergoplatform.nodeView.wallet.requests._
import org.ergoplatform.sdk.wallet.secrets.{DerivationPath, ExtendedPublicKey, ExtendedSecretKey}
@@ -283,7 +283,7 @@ trait ErgoWalletSupport extends ScorexLogging {
dataInputsRaw: Seq[String]): Try[(UnsignedErgoTransaction, IndexedSeq[ErgoBox], IndexedSeq[ErgoBox])] = Try {
require(requests.count(_.isInstanceOf[AssetIssueRequest]) <= 1, "Too many asset issuance requests")
- val userInputs = ErgoWalletService.stringsToBoxes(inputsRaw)
+ val userInputs = ErgoWalletServiceUtils.stringsToBoxes(inputsRaw)
val inputBoxes = if (userInputs.nonEmpty) {
// make TrackedBox sequence out of boxes provided
@@ -336,7 +336,7 @@ trait ErgoWalletSupport extends ScorexLogging {
val targetAssetsWithBurn = AssetUtils.mergeAssets(targetAssets, burnTokensMap)
val selectionOpt = boxSelector.select(inputBoxes.iterator, targetBalance, targetAssetsWithBurn)
- val dataInputs = ErgoWalletService.stringsToBoxes(dataInputsRaw).toIndexedSeq
+ val dataInputs = ErgoWalletServiceUtils.stringsToBoxes(dataInputsRaw).toIndexedSeq
selectionOpt.map { selectionResult =>
val changeAddressOpt: Option[ProveDlog] = state.getChangeAddress(addressEncoder).map(_.pubkey)
prepareUnsignedTransaction(outputs, state.getWalletHeight, selectionResult, dataInputs, changeAddressOpt) -> selectionResult.inputBoxes
diff --git a/src/main/scala/org/ergoplatform/nodeView/wallet/WalletTransaction.scala b/src/main/scala/org/ergoplatform/nodeView/wallet/WalletTransaction.scala
index c93660c0a6..edd19a8fcc 100644
--- a/src/main/scala/org/ergoplatform/nodeView/wallet/WalletTransaction.scala
+++ b/src/main/scala/org/ergoplatform/nodeView/wallet/WalletTransaction.scala
@@ -3,7 +3,7 @@ package org.ergoplatform.nodeView.wallet
import org.ergoplatform.modifiers.mempool.{ErgoTransaction, ErgoTransactionSerializer}
import org.ergoplatform.wallet.Constants
import org.ergoplatform.wallet.Constants.ScanId
-import scorex.core.serialization.ErgoSerializer
+import org.ergoplatform.serialization.ErgoSerializer
import scorex.util.ModifierId
import scorex.util.serialization.{Reader, Writer}
import scorex.util.Extensions._
diff --git a/src/main/scala/org/ergoplatform/nodeView/wallet/persistence/OffChainRegistry.scala b/src/main/scala/org/ergoplatform/nodeView/wallet/persistence/OffChainRegistry.scala
index 220a2b5afa..50f10904b9 100644
--- a/src/main/scala/org/ergoplatform/nodeView/wallet/persistence/OffChainRegistry.scala
+++ b/src/main/scala/org/ergoplatform/nodeView/wallet/persistence/OffChainRegistry.scala
@@ -1,6 +1,6 @@
package org.ergoplatform.nodeView.wallet.persistence
-import org.ergoplatform.nodeView.history.ErgoHistory
+import org.ergoplatform.nodeView.history.ErgoHistoryUtils._
import org.ergoplatform.nodeView.wallet.scanning.Scan
import org.ergoplatform.wallet.Constants
import org.ergoplatform.wallet.Constants.PaymentsScanId
@@ -92,7 +92,7 @@ case class OffChainRegistry(height: Int,
object OffChainRegistry {
def empty: OffChainRegistry =
- OffChainRegistry(ErgoHistory.EmptyHistoryHeight, ArraySeq.empty, ArraySeq.empty)
+ OffChainRegistry(EmptyHistoryHeight, ArraySeq.empty, ArraySeq.empty)
def init(walletRegistry: WalletRegistry):OffChainRegistry = {
val unspent = walletRegistry.unspentBoxes(PaymentsScanId)
diff --git a/src/main/scala/org/ergoplatform/nodeView/wallet/persistence/WalletDigest.scala b/src/main/scala/org/ergoplatform/nodeView/wallet/persistence/WalletDigest.scala
index 9223a4b91e..1b96025f1f 100644
--- a/src/main/scala/org/ergoplatform/nodeView/wallet/persistence/WalletDigest.scala
+++ b/src/main/scala/org/ergoplatform/nodeView/wallet/persistence/WalletDigest.scala
@@ -1,9 +1,9 @@
package org.ergoplatform.nodeView.wallet.persistence
-import org.ergoplatform.nodeView.history.ErgoHistory
+import org.ergoplatform.nodeView.history.ErgoHistoryUtils._
import org.ergoplatform.nodeView.wallet.IdUtils._
import org.ergoplatform.settings.Constants
-import scorex.core.serialization.ErgoSerializer
+import org.ergoplatform.serialization.ErgoSerializer
import scorex.util.Extensions._
import scorex.util.serialization.{Reader, Writer}
import sigmastate.eval.Extensions.ArrayByteOps
@@ -24,7 +24,7 @@ final case class WalletDigest(height: Int,
object WalletDigest {
val empty: WalletDigest =
- WalletDigest(ErgoHistory.EmptyHistoryHeight, 0, mutable.WrappedArray.empty)
+ WalletDigest(EmptyHistoryHeight, 0, mutable.WrappedArray.empty)
}
diff --git a/src/main/scala/org/ergoplatform/nodeView/wallet/persistence/WalletRegistry.scala b/src/main/scala/org/ergoplatform/nodeView/wallet/persistence/WalletRegistry.scala
index 1dc3753b5d..f3e7deba48 100644
--- a/src/main/scala/org/ergoplatform/nodeView/wallet/persistence/WalletRegistry.scala
+++ b/src/main/scala/org/ergoplatform/nodeView/wallet/persistence/WalletRegistry.scala
@@ -13,7 +13,7 @@ import org.ergoplatform.wallet.Constants
import org.ergoplatform.wallet.Constants.{PaymentsScanId, ScanId}
import org.ergoplatform.wallet.boxes.{TrackedBox, TrackedBoxSerializer}
import org.ergoplatform.wallet.transactions.TransactionBuilder
-import scorex.core.VersionTag
+import org.ergoplatform.core.VersionTag
import scorex.crypto.authds.ADKey
import scorex.db.LDBVersionedStore
import scorex.util.encode.Base16
@@ -314,7 +314,7 @@ class WalletRegistry(private val store: LDBVersionedStore)(ws: WalletSettings) e
def rollback(version: VersionTag): Try[Unit] = {
cache.clear()
- store.rollbackTo(scorex.core.versionToBytes(version))
+ store.rollbackTo(org.ergoplatform.core.versionToBytes(version))
}
/**
diff --git a/src/main/scala/org/ergoplatform/nodeView/wallet/persistence/WalletStorage.scala b/src/main/scala/org/ergoplatform/nodeView/wallet/persistence/WalletStorage.scala
index 617755f474..2f52c218f0 100644
--- a/src/main/scala/org/ergoplatform/nodeView/wallet/persistence/WalletStorage.scala
+++ b/src/main/scala/org/ergoplatform/nodeView/wallet/persistence/WalletStorage.scala
@@ -112,8 +112,8 @@ final class WalletStorage(store: LDBKVStore, settings: ErgoSettings) extends Sco
def readStateContext(parameters: Parameters): ErgoStateContext = {
cachedStateContext = Some(store
.get(StateContextKey)
- .flatMap(r => ErgoStateContextSerializer(settings).parseBytesTry(r).toOption)
- .getOrElse(ErgoStateContext.empty(settings, parameters))
+ .flatMap(r => ErgoStateContextSerializer(settings.chainSettings).parseBytesTry(r).toOption)
+ .getOrElse(ErgoStateContext.empty(settings.chainSettings, parameters))
)
cachedStateContext.get
}
diff --git a/src/main/scala/org/ergoplatform/nodeView/wallet/requests/AssetIssueRequest.scala b/src/main/scala/org/ergoplatform/nodeView/wallet/requests/AssetIssueRequest.scala
index 714e8cb61f..0dd6fd72d0 100644
--- a/src/main/scala/org/ergoplatform/nodeView/wallet/requests/AssetIssueRequest.scala
+++ b/src/main/scala/org/ergoplatform/nodeView/wallet/requests/AssetIssueRequest.scala
@@ -42,9 +42,9 @@ object AssetIssueRequest {
new AssetIssueRequest(Some(address), valueOpt, amount, name, description, decimals, registers)
}
-class AssetIssueRequestEncoder(settings: ErgoSettings) extends Encoder[AssetIssueRequest] with ApiCodecs {
+class AssetIssueRequestEncoder(ergoSettings: ErgoSettings) extends Encoder[AssetIssueRequest] with ApiCodecs {
- implicit val addressEncoder: Encoder[ErgoAddress] = ErgoAddressJsonEncoder(settings).encoder
+ implicit val addressEncoder: Encoder[ErgoAddress] = ErgoAddressJsonEncoder(ergoSettings.chainSettings).encoder
def apply(request: AssetIssueRequest): Json = {
Json.obj(
@@ -60,9 +60,9 @@ class AssetIssueRequestEncoder(settings: ErgoSettings) extends Encoder[AssetIssu
}
-class AssetIssueRequestDecoder(settings: ErgoSettings) extends Decoder[AssetIssueRequest] with ApiCodecs {
+class AssetIssueRequestDecoder(ergoSettings: ErgoSettings) extends Decoder[AssetIssueRequest] with ApiCodecs {
- val addressEncoders: ErgoAddressJsonEncoder = ErgoAddressJsonEncoder(settings)
+ val addressEncoders: ErgoAddressJsonEncoder = ErgoAddressJsonEncoder(ergoSettings.chainSettings)
implicit def addressDecoder: Decoder[ErgoAddress] = addressEncoders.decoder
diff --git a/src/main/scala/org/ergoplatform/nodeView/wallet/requests/PaymentRequest.scala b/src/main/scala/org/ergoplatform/nodeView/wallet/requests/PaymentRequest.scala
index 3537677ed7..9b44cdccb8 100644
--- a/src/main/scala/org/ergoplatform/nodeView/wallet/requests/PaymentRequest.scala
+++ b/src/main/scala/org/ergoplatform/nodeView/wallet/requests/PaymentRequest.scala
@@ -19,9 +19,9 @@ case class PaymentRequest(address: ErgoAddress,
registers: Map[NonMandatoryRegisterId, EvaluatedValue[_ <: SType]])
extends TransactionGenerationRequest
-class PaymentRequestEncoder(settings: ErgoSettings) extends Encoder[PaymentRequest] {
+class PaymentRequestEncoder(ergoSettings: ErgoSettings) extends Encoder[PaymentRequest] {
- implicit val addressEncoder: Encoder[ErgoAddress] = ErgoAddressJsonEncoder(settings).encoder
+ implicit val addressEncoder: Encoder[ErgoAddress] = ErgoAddressJsonEncoder(ergoSettings.chainSettings).encoder
def apply(request: PaymentRequest): Json = {
Json.obj(
@@ -34,9 +34,9 @@ class PaymentRequestEncoder(settings: ErgoSettings) extends Encoder[PaymentReque
}
-class PaymentRequestDecoder(settings: ErgoSettings) extends Decoder[PaymentRequest] {
+class PaymentRequestDecoder(ergoSettings: ErgoSettings) extends Decoder[PaymentRequest] {
- val addressEncoders: ErgoAddressJsonEncoder = ErgoAddressJsonEncoder(settings)
+ val addressEncoders: ErgoAddressJsonEncoder = ErgoAddressJsonEncoder(ergoSettings.chainSettings)
implicit def addressDecoder: Decoder[ErgoAddress] = addressEncoders.decoder
diff --git a/src/main/scala/org/ergoplatform/nodeView/wallet/requests/RequestsHolder.scala b/src/main/scala/org/ergoplatform/nodeView/wallet/requests/RequestsHolder.scala
index 39890f4562..4ff6d38fbb 100644
--- a/src/main/scala/org/ergoplatform/nodeView/wallet/requests/RequestsHolder.scala
+++ b/src/main/scala/org/ergoplatform/nodeView/wallet/requests/RequestsHolder.scala
@@ -26,10 +26,10 @@ case class RequestsHolder(requests: Seq[TransactionGenerationRequest],
}
-class RequestsHolderEncoder(settings: ErgoSettings) extends Encoder[RequestsHolder] with ApiCodecs {
+class RequestsHolderEncoder(ergoSettings: ErgoSettings) extends Encoder[RequestsHolder] with ApiCodecs {
- implicit val transactionRequestEncoder: TransactionRequestEncoder = new TransactionRequestEncoder(settings)
- implicit val addressEncoder: Encoder[ErgoAddress] = ErgoAddressJsonEncoder(settings).encoder
+ implicit val transactionRequestEncoder: TransactionRequestEncoder = new TransactionRequestEncoder(ergoSettings)
+ implicit val addressEncoder: Encoder[ErgoAddress] = ErgoAddressJsonEncoder(ergoSettings.chainSettings).encoder
def apply(holder: RequestsHolder): Json = {
Json.obj(
diff --git a/src/main/scala/org/ergoplatform/nodeView/wallet/requests/TransactionGenerationRequest.scala b/src/main/scala/org/ergoplatform/nodeView/wallet/requests/TransactionGenerationRequest.scala
index 545fa2f013..22047ebbee 100644
--- a/src/main/scala/org/ergoplatform/nodeView/wallet/requests/TransactionGenerationRequest.scala
+++ b/src/main/scala/org/ergoplatform/nodeView/wallet/requests/TransactionGenerationRequest.scala
@@ -8,13 +8,13 @@ import org.ergoplatform.settings.ErgoSettings
trait TransactionGenerationRequest
-class TransactionRequestEncoder(settings: ErgoSettings) extends Encoder[TransactionGenerationRequest] with ApiCodecs {
+class TransactionRequestEncoder(ergoSettings: ErgoSettings) extends Encoder[TransactionGenerationRequest] with ApiCodecs {
- implicit val addressEncoder: Encoder[ErgoAddress] = ErgoAddressJsonEncoder(settings).encoder
+ implicit val addressEncoder: Encoder[ErgoAddress] = ErgoAddressJsonEncoder(ergoSettings.chainSettings).encoder
def apply(request: TransactionGenerationRequest): Json = request match {
- case pr: PaymentRequest => new PaymentRequestEncoder(settings)(pr)
- case ar: AssetIssueRequest => new AssetIssueRequestEncoder(settings)(ar)
+ case pr: PaymentRequest => new PaymentRequestEncoder(ergoSettings)(pr)
+ case ar: AssetIssueRequest => new AssetIssueRequestEncoder(ergoSettings)(ar)
case br: BurnTokensRequest => new BurnTokensRequestEncoder()(br)
case other => throw new Exception(s"Unknown TransactionRequest type: $other")
}
diff --git a/src/main/scala/org/ergoplatform/nodeView/wallet/scanning/Scan.scala b/src/main/scala/org/ergoplatform/nodeView/wallet/scanning/Scan.scala
index 76aa9c3085..a13d2f3f4c 100644
--- a/src/main/scala/org/ergoplatform/nodeView/wallet/scanning/Scan.scala
+++ b/src/main/scala/org/ergoplatform/nodeView/wallet/scanning/Scan.scala
@@ -3,7 +3,7 @@ package org.ergoplatform.nodeView.wallet.scanning
import org.ergoplatform.http.api.ApiCodecs
import org.ergoplatform.nodeView.wallet.scanning.ScanWalletInteraction.ScanWalletInteraction
import org.ergoplatform.wallet.Constants.ScanId
-import scorex.core.serialization.ErgoSerializer
+import org.ergoplatform.serialization.ErgoSerializer
import scorex.util.serialization.{Reader, Writer}
import scala.util.{Failure, Success, Try}
diff --git a/src/main/scala/org/ergoplatform/nodeView/wallet/scanning/ScanningPredicateSerializer.scala b/src/main/scala/org/ergoplatform/nodeView/wallet/scanning/ScanningPredicateSerializer.scala
index 2c70437053..330c071373 100644
--- a/src/main/scala/org/ergoplatform/nodeView/wallet/scanning/ScanningPredicateSerializer.scala
+++ b/src/main/scala/org/ergoplatform/nodeView/wallet/scanning/ScanningPredicateSerializer.scala
@@ -2,7 +2,7 @@ package org.ergoplatform.nodeView.wallet.scanning
import org.ergoplatform.ErgoBox
import org.ergoplatform.ErgoBox.RegisterId
-import scorex.core.serialization.ErgoSerializer
+import org.ergoplatform.serialization.ErgoSerializer
import scorex.util.Extensions._
import scorex.util.serialization.{Reader, Writer}
import sigmastate.SType
diff --git a/src/main/scala/org/ergoplatform/reemission/ReemissionRules.scala b/src/main/scala/org/ergoplatform/reemission/ReemissionRulesUtils.scala
similarity index 65%
rename from src/main/scala/org/ergoplatform/reemission/ReemissionRules.scala
rename to src/main/scala/org/ergoplatform/reemission/ReemissionRulesUtils.scala
index 2660693fac..f149097489 100644
--- a/src/main/scala/org/ergoplatform/reemission/ReemissionRules.scala
+++ b/src/main/scala/org/ergoplatform/reemission/ReemissionRulesUtils.scala
@@ -1,57 +1,22 @@
package org.ergoplatform.reemission
-import org.ergoplatform.ErgoLikeContext.Height
-import org.ergoplatform.contracts.ReemissionContracts
import org.ergoplatform.mining.emission.EmissionRules
+import org.ergoplatform.settings.ErgoSettingsReader
import org.ergoplatform.{ErgoAddressEncoder, Pay2SAddress}
-import org.ergoplatform.settings.{ErgoSettings, ReemissionSettings}
import sigmastate.SBoolean
import sigmastate.Values.Value
import sigmastate.eval.CompiletimeIRContext
import sigmastate.lang.{CompilerSettings, SigmaCompiler, TransformingSigmaBuilder}
-import sigma.Coll
import scala.util.Try
-/**
- * Contains re-emission contracts (defined in `ReemissionContracts`) and helper functions
- * for re-emission.
- */
-class ReemissionRules(reemissionSettings: ReemissionSettings) extends ReemissionContracts {
-
- override val reemissionNftIdBytes: Coll[Byte] = reemissionSettings.reemissionNftIdBytes
- override val reemissionStartHeight: Height = reemissionSettings.reemissionStartHeight
-
- /**
- * How many ERG taken from emission to re-emission initially
- */
- val basicChargeAmount = 12 // in ERG
-
- /**
- * @return how many re-emission tokens can be unlocked at given height
- */
- def reemissionForHeight(height: Height,
- emissionRules: EmissionRules): Long = {
- val emission = emissionRules.emissionAtHeight(height)
- if (height >= reemissionSettings.activationHeight &&
- emission >= (basicChargeAmount + 3) * EmissionRules.CoinsInOneErgo) {
- basicChargeAmount * EmissionRules.CoinsInOneErgo
- } else if (height >= reemissionSettings.activationHeight &&
- emission > 3 * EmissionRules.CoinsInOneErgo) {
- emission - 3 * EmissionRules.CoinsInOneErgo
- } else {
- 0L
- }
- }
-}
-
-object ReemissionRules {
+object ReemissionRulesUtils {
/**
- * @param mainnet - whether to create address for mainnet or testnet
- * @return - P2S address for a box used to carry emission NFT and re-emission tokens
- * to inject them into the emission box on activation height
- */
+ * @param mainnet - whether to create address for mainnet or testnet
+ * @return - P2S address for a box used to carry emission NFT and re-emission tokens
+ * to inject them into the emission box on activation height
+ */
def injectionBoxP2SAddress(mainnet: Boolean): Pay2SAddress = {
val networkPrefix = if (mainnet) {
ErgoAddressEncoder.MainnetNetworkPrefix
@@ -79,7 +44,7 @@ object ReemissionRules {
println(new ErgoAddressEncoder(ErgoAddressEncoder.TestnetNetworkPrefix).fromString(p2sAddress.toString()))
println("injectioon box p2s: " + p2sAddress)
- val settings = ErgoSettings.read()
+ val settings = ErgoSettingsReader.read()
println("Monetary settings: " + settings.chainSettings.monetary)
println("Reemission settings: " + settings.chainSettings.reemission)
diff --git a/src/main/scala/org/ergoplatform/settings/ErgoSettings.scala b/src/main/scala/org/ergoplatform/settings/ErgoSettings.scala
index 41bdd67a43..8ada7c5c16 100644
--- a/src/main/scala/org/ergoplatform/settings/ErgoSettings.scala
+++ b/src/main/scala/org/ergoplatform/settings/ErgoSettings.scala
@@ -1,24 +1,12 @@
package org.ergoplatform.settings
-import java.io.{File, FileOutputStream}
-import java.nio.channels.Channels
-import ch.qos.logback.classic.{LoggerContext, Level}
-import org.slf4j.{Logger, LoggerFactory}
-import com.typesafe.config.{Config, ConfigFactory, ConfigValueFactory}
-import net.ceedubs.ficus.Ficus._
-import net.ceedubs.ficus.readers.ArbitraryTypeReader._
import org.ergoplatform.mining.groupElemFromBytes
-import org.ergoplatform.nodeView.state.StateType.Digest
-import org.ergoplatform.{ErgoAddressEncoder, ErgoApp, P2PKAddress}
-import scorex.core.settings.{ScorexSettings, SettingsReaders}
-import scorex.util.ScorexLogging
+import org.ergoplatform.{ErgoAddressEncoder, P2PKAddress}
import scorex.util.encode.Base16
import sigmastate.crypto.DLogProtocol.ProveDlog
-import java.net.{InetAddress, URL}
import scala.util.Try
-
case class ErgoSettings(directory: String,
networkType: NetworkType,
chainSettings: ChainSettings,
@@ -43,204 +31,7 @@ case class ErgoSettings(directory: String,
}
-object ErgoSettings extends ScorexLogging
- with PowSchemeReaders
- with NodeConfigurationReaders
- with SettingsReaders {
-
+object ErgoSettings {
val configPath: String = "ergo"
val scorexConfigPath: String = "scorex"
-
- def read(args: Args = Args.empty): ErgoSettings = {
- fromConfig(readConfig(args), args.networkTypeOpt)
- }
-
- def fromConfig(config: Config, desiredNetworkTypeOpt: Option[NetworkType] = None): ErgoSettings = {
- val directory = config.as[String](s"$configPath.directory")
- val networkTypeName = config.as[String](s"$configPath.networkType")
- val networkType = NetworkType.fromString(networkTypeName)
- .getOrElse(throw new Error(s"Unknown `networkType = $networkTypeName`"))
- val nodeSettings = config.as[NodeConfigurationSettings](s"$configPath.node")
- val chainSettings = config.as[ChainSettings](s"$configPath.chain")
- val walletSettings = config.as[WalletSettings](s"$configPath.wallet")
- val cacheSettings = config.as[CacheSettings](s"$configPath.cache")
- val scorexSettings = config.as[ScorexSettings](scorexConfigPath)
- val votingTargets = VotingTargets.fromConfig(config)
-
- overrideLogLevel(scorexSettings.logging.level)
-
- if (nodeSettings.stateType == Digest && nodeSettings.mining) {
- log.error("Malformed configuration file was provided! Mining is not possible with digest state. Aborting!")
- ErgoApp.forceStopApplication()
- }
-
- consistentSettings(
- ErgoSettings(
- directory,
- networkType,
- chainSettings,
- nodeSettings,
- scorexSettings,
- walletSettings,
- cacheSettings,
- votingTargets
- ),
- desiredNetworkTypeOpt
- )
- }
-
- // Helper method to read user-provided `configFile` with network-specific `fallbackConfig`
- // to be used for default fallback values before reference.conf (which is the last resort)
- private def configWithOverrides(configFile: File, fallbackConfig: Option[File]) = {
- val firstFallBack = fallbackConfig.map(ConfigFactory.parseFile).getOrElse(ConfigFactory.empty())
-
- val cfg = ConfigFactory.parseFile(configFile)
-
- val keystorePath = "ergo.wallet.secretStorage.secretDir"
-
- // Check that user-provided Ergo directory exists and has write access (if provided at all)
- val userDirOpt = Try(cfg.getString("ergo.directory")).toOption
- userDirOpt.foreach { ergoDirName =>
- require(new File(s"$ergoDirName").canWrite, s"Folder $ergoDirName does not exist or not writable")
- }
-
- // Check that user-provided wallet secret directory exists and has read access (if provided at all)
- val walletKeystoreDirOpt = Try(cfg.getString(keystorePath)).toOption
- walletKeystoreDirOpt.foreach { secretDirName =>
- require(new File(s"$secretDirName").canRead, s"Folder $secretDirName does not exist or not readable")
- }
-
- val fullConfig = ConfigFactory
- .defaultOverrides()
- .withFallback(cfg)
- .withFallback(firstFallBack)
- .withFallback(ConfigFactory.defaultApplication())
- .withFallback(ConfigFactory.defaultReference())
- .resolve()
-
- // If user provided only ergo.directory but not ergo.wallet.secretStorage.secretDir in his config,
- // set ergo.wallet.secretStorage.secretDir like in reference.conf (so ergo.directory + "/wallet/keystore")
- // Otherwise, a user may have an issue, especially with Powershell it seems from reports.
- userDirOpt.map { userDir =>
- if(walletKeystoreDirOpt.isEmpty) {
- fullConfig.withValue(keystorePath, ConfigValueFactory.fromAnyRef(userDir + "/wallet/keystore"))
- } else {
- fullConfig
- }
- }.getOrElse(fullConfig)
- }
-
- private def readConfig(args: Args): Config = {
-
- val networkConfigFileOpt = args.networkTypeOpt
- .flatMap { networkType =>
- val confName = s"${networkType.verboseName}.conf"
- val classLoader = ClassLoader.getSystemClassLoader
- val destDir = System.getProperty("java.io.tmpdir") + "/"
-
- Option(classLoader.getResourceAsStream(confName))
- .map { stream =>
- val source = Channels.newChannel(stream)
- val fileOut = new File(destDir, confName)
- val dest = new FileOutputStream(fileOut)
- dest.getChannel.transferFrom(source, 0, Long.MaxValue)
-
- source.close()
- dest.close()
-
- sys.addShutdownHook {
- new File(destDir, confName).delete
- }
-
- fileOut
- }
- }
-
- val userConfigFileOpt = for {
- filePathOpt <- args.userConfigPathOpt
- file = new File(filePathOpt)
- if file.exists
- } yield file
-
- networkConfigFileOpt.flatMap(_ => args.networkTypeOpt).fold(log.warn("Running without network config"))(
- x => log.info(s"Running in ${x.verboseName} network mode"))
-
- (networkConfigFileOpt, userConfigFileOpt) match {
- // if no user config is supplied, the library will handle overrides/application/reference automatically
- case (Some(networkConfigFile), None) =>
- log.warn("NO CONFIGURATION FILE WAS PROVIDED. STARTING WITH DEFAULT SETTINGS!")
- ConfigFactory
- .defaultOverrides()
- .withFallback(ConfigFactory.parseFile(networkConfigFile))
- .withFallback(ConfigFactory.defaultReference())
- .resolve()
- // application config needs to be resolved wrt both system properties *and* user-supplied config.
- case (Some(networkConfigFile), Some(file)) =>
- configWithOverrides(file, Some(networkConfigFile))
- case (None, Some(file)) =>
- configWithOverrides(file, None)
- case (None, None) =>
- ConfigFactory.load()
- }
- }
-
- protected[settings] def invalidRestApiUrl(url: URL): Boolean =
- Try(url.toURI).map { uri =>
- val inetAddress = InetAddress.getByName(url.getHost)
- Option(uri.getQuery).exists(_.nonEmpty) ||
- Option(uri.getPath).exists(_.nonEmpty) ||
- Option(uri.getFragment).exists(_.nonEmpty) ||
- inetAddress.isAnyLocalAddress ||
- inetAddress.isLoopbackAddress ||
- inetAddress.isSiteLocalAddress
- }.getOrElse(false)
-
- private def consistentSettings(settings: ErgoSettings,
- desiredNetworkTypeOpt: Option[NetworkType]): ErgoSettings = {
- val nodeSettings = settings.nodeSettings
- if (nodeSettings.keepVersions < 0) {
- failWithError("nodeSettings.keepVersions should not be negative")
- } else if (!nodeSettings.verifyTransactions && !nodeSettings.stateType.requireProofs) {
- failWithError("Can not use UTXO state when nodeSettings.verifyTransactions is false")
- } else if (desiredNetworkTypeOpt.exists(_ != settings.networkType)) {
- failWithError(s"Malformed network config. Desired networkType is `${desiredNetworkTypeOpt.get}`, " +
- s"but one declared in config is `${settings.networkType}`")
- } else if(settings.networkType.isMainNet &&
- nodeSettings.mining &&
- !settings.chainSettings.reemission.checkReemissionRules) {
- failWithError(s"Mining is enabled, but ergo.chain.reemission.checkReemissionRules = false , set it to true")
- } else if (settings.scorexSettings.restApi.publicUrl.exists(invalidRestApiUrl)) {
- failWithError(s"scorex.restApi.publicUrl should not contain query, path or fragment and should not " +
- s"be local or loopback address : ${settings.scorexSettings.restApi.publicUrl.get}")
- } else if (settings.nodeSettings.utxoSettings.p2pUtxoSnapshots <= 0) {
- failWithError(s"p2pUtxoSnapshots <= 0, must be 1 at least")
- } else if (settings.nodeSettings.extraIndex && settings.nodeSettings.isFullBlocksPruned) {
- failWithError(s"Extra indexes could be enabled only if there is no blockchain pruning")
- } else if (nodeSettings.nipopowSettings.nipopowBootstrap &&
- !(nodeSettings.utxoSettings.utxoBootstrap || nodeSettings.blocksToKeep >= 0)) {
- failWithError("nodeSettings.popowBootstrap can be set only if " +
- "nodeSettings.utxoBootstrap is set or nodeSettings.blocksToKeep >=0")
- } else if (nodeSettings.nipopowSettings.nipopowBootstrap && settings.chainSettings.genesisId.isEmpty) {
- failWithError("nodeSettings.popowBootstrap is set but genesisId is not")
- } else {
- settings
- }
- }
-
- private def failWithError(msg: String): Nothing = {
- log.error(s"Stop application due to malformed configuration file: $msg")
- ErgoApp.forceStopApplication()
- }
-
- /**
- * Override the log level at runtime with values provided in config/user provided config.
- */
- private def overrideLogLevel(level: String): Unit = level match {
- case "TRACE" | "ERROR" | "INFO" | "WARN" | "DEBUG" =>
- log.info(s"Log level set to $level")
- val loggerContext = LoggerFactory.getILoggerFactory.asInstanceOf[LoggerContext]
- val root = loggerContext.getLogger(Logger.ROOT_LOGGER_NAME)
- root.setLevel(Level.toLevel(level))
- case _ => log.warn("No log level configuration provided")
- }
}
diff --git a/src/main/scala/org/ergoplatform/settings/ErgoSettingsReader.scala b/src/main/scala/org/ergoplatform/settings/ErgoSettingsReader.scala
new file mode 100644
index 0000000000..4cacd4be02
--- /dev/null
+++ b/src/main/scala/org/ergoplatform/settings/ErgoSettingsReader.scala
@@ -0,0 +1,219 @@
+package org.ergoplatform.settings
+
+import java.io.{File, FileOutputStream}
+import java.nio.channels.Channels
+import ch.qos.logback.classic.{Level, LoggerContext}
+import org.slf4j.{Logger, LoggerFactory}
+import com.typesafe.config.{Config, ConfigFactory, ConfigValueFactory}
+import net.ceedubs.ficus.Ficus._
+import net.ceedubs.ficus.readers.ArbitraryTypeReader._
+import org.ergoplatform.nodeView.state.StateType.Digest
+import org.ergoplatform.ErgoApp
+import scorex.util.ScorexLogging
+import org.ergoplatform.settings.ErgoSettings.{configPath, scorexConfigPath}
+
+import java.net.{InetAddress, URL}
+import scala.util.Try
+
+/**
+ * Functions to read configs (ErgoSettings instances)
+ */
+object ErgoSettingsReader extends ScorexLogging
+ with PowSchemeReaders
+ with NodeConfigurationReaders
+ with SettingsReaders {
+
+ def read(args: Args = Args.empty): ErgoSettings = {
+ fromConfig(readConfig(args), args.networkTypeOpt)
+ }
+
+ def fromConfig(config: Config, desiredNetworkTypeOpt: Option[NetworkType] = None): ErgoSettings = {
+ val directory = config.as[String](s"$configPath.directory")
+ val networkTypeName = config.as[String](s"$configPath.networkType")
+ val networkType = NetworkType.fromString(networkTypeName)
+ .getOrElse(throw new Error(s"Unknown `networkType = $networkTypeName`"))
+ val nodeSettings = config.as[NodeConfigurationSettings](s"$configPath.node")
+ val chainSettings = config.as[ChainSettings](s"$configPath.chain")
+ val walletSettings = config.as[WalletSettings](s"$configPath.wallet")
+ val cacheSettings = config.as[CacheSettings](s"$configPath.cache")
+ val scorexSettings = config.as[ScorexSettings](scorexConfigPath)
+ val votingTargets = VotingTargets.fromConfig(config)
+
+ overrideLogLevel(scorexSettings.logging.level)
+
+ if (nodeSettings.stateType == Digest && nodeSettings.mining) {
+ log.error("Malformed configuration file was provided! Mining is not possible with digest state. Aborting!")
+ ErgoApp.forceStopApplication()
+ }
+
+ consistentSettings(
+ ErgoSettings(
+ directory,
+ networkType,
+ chainSettings,
+ nodeSettings,
+ scorexSettings,
+ walletSettings,
+ cacheSettings,
+ votingTargets
+ ),
+ desiredNetworkTypeOpt
+ )
+ }
+
+ // Helper method to read user-provided `configFile` with network-specific `fallbackConfig`
+ // to be used for default fallback values before reference.conf (which is the last resort)
+ private def configWithOverrides(configFile: File, fallbackConfig: Option[File]) = {
+ val firstFallBack = fallbackConfig.map(ConfigFactory.parseFile).getOrElse(ConfigFactory.empty())
+
+ val cfg = ConfigFactory.parseFile(configFile)
+
+ val keystorePath = "ergo.wallet.secretStorage.secretDir"
+
+ // Check that user-provided Ergo directory exists and has write access (if provided at all)
+ val userDirOpt = Try(cfg.getString("ergo.directory")).toOption
+ userDirOpt.foreach { ergoDirName =>
+ require(new File(s"$ergoDirName").canWrite, s"Folder $ergoDirName does not exist or not writable")
+ }
+
+ // Check that user-provided wallet secret directory exists and has read access (if provided at all)
+ val walletKeystoreDirOpt = Try(cfg.getString(keystorePath)).toOption
+ walletKeystoreDirOpt.foreach { secretDirName =>
+ require(new File(s"$secretDirName").canRead, s"Folder $secretDirName does not exist or not readable")
+ }
+
+ val fullConfig = ConfigFactory
+ .defaultOverrides()
+ .withFallback(cfg)
+ .withFallback(firstFallBack)
+ .withFallback(ConfigFactory.defaultApplication())
+ .withFallback(ConfigFactory.defaultReference())
+ .resolve()
+
+ // If user provided only ergo.directory but not ergo.wallet.secretStorage.secretDir in his config,
+ // set ergo.wallet.secretStorage.secretDir like in reference.conf (so ergo.directory + "/wallet/keystore")
+ // Otherwise, a user may have an issue, especially with Powershell it seems from reports.
+ userDirOpt.map { userDir =>
+ if(walletKeystoreDirOpt.isEmpty) {
+ fullConfig.withValue(keystorePath, ConfigValueFactory.fromAnyRef(userDir + "/wallet/keystore"))
+ } else {
+ fullConfig
+ }
+ }.getOrElse(fullConfig)
+ }
+
+ private def readConfig(args: Args): Config = {
+
+ val networkConfigFileOpt = args.networkTypeOpt
+ .flatMap { networkType =>
+ val confName = s"${networkType.verboseName}.conf"
+ val classLoader = ClassLoader.getSystemClassLoader
+ val destDir = System.getProperty("java.io.tmpdir") + "/"
+
+ Option(classLoader.getResourceAsStream(confName))
+ .map { stream =>
+ val source = Channels.newChannel(stream)
+ val fileOut = new File(destDir, confName)
+ val dest = new FileOutputStream(fileOut)
+ dest.getChannel.transferFrom(source, 0, Long.MaxValue)
+
+ source.close()
+ dest.close()
+
+ sys.addShutdownHook {
+ new File(destDir, confName).delete
+ }
+
+ fileOut
+ }
+ }
+
+ val userConfigFileOpt = for {
+ filePathOpt <- args.userConfigPathOpt
+ file = new File(filePathOpt)
+ if file.exists
+ } yield file
+
+ networkConfigFileOpt.flatMap(_ => args.networkTypeOpt).fold(log.warn("Running without network config"))(
+ x => log.info(s"Running in ${x.verboseName} network mode"))
+
+ (networkConfigFileOpt, userConfigFileOpt) match {
+ // if no user config is supplied, the library will handle overrides/application/reference automatically
+ case (Some(networkConfigFile), None) =>
+ log.warn("NO CONFIGURATION FILE WAS PROVIDED. STARTING WITH DEFAULT SETTINGS!")
+ ConfigFactory
+ .defaultOverrides()
+ .withFallback(ConfigFactory.parseFile(networkConfigFile))
+ .withFallback(ConfigFactory.defaultReference())
+ .resolve()
+ // application config needs to be resolved wrt both system properties *and* user-supplied config.
+ case (Some(networkConfigFile), Some(file)) =>
+ configWithOverrides(file, Some(networkConfigFile))
+ case (None, Some(file)) =>
+ configWithOverrides(file, None)
+ case (None, None) =>
+ ConfigFactory.load()
+ }
+ }
+
+ protected[settings] def invalidRestApiUrl(url: URL): Boolean =
+ Try(url.toURI).map { uri =>
+ val inetAddress = InetAddress.getByName(url.getHost)
+ Option(uri.getQuery).exists(_.nonEmpty) ||
+ Option(uri.getPath).exists(_.nonEmpty) ||
+ Option(uri.getFragment).exists(_.nonEmpty) ||
+ inetAddress.isAnyLocalAddress ||
+ inetAddress.isLoopbackAddress ||
+ inetAddress.isSiteLocalAddress
+ }.getOrElse(false)
+
+ private def consistentSettings(settings: ErgoSettings,
+ desiredNetworkTypeOpt: Option[NetworkType]): ErgoSettings = {
+ val nodeSettings = settings.nodeSettings
+ if (nodeSettings.keepVersions < 0) {
+ failWithError("nodeSettings.keepVersions should not be negative")
+ } else if (!nodeSettings.verifyTransactions && !nodeSettings.stateType.requireProofs) {
+ failWithError("Can not use UTXO state when nodeSettings.verifyTransactions is false")
+ } else if (desiredNetworkTypeOpt.exists(_ != settings.networkType)) {
+ failWithError(s"Malformed network config. Desired networkType is `${desiredNetworkTypeOpt.get}`, " +
+ s"but one declared in config is `${settings.networkType}`")
+ } else if(settings.networkType.isMainNet &&
+ nodeSettings.mining &&
+ !settings.chainSettings.reemission.checkReemissionRules) {
+ failWithError(s"Mining is enabled, but ergo.chain.reemission.checkReemissionRules = false , set it to true")
+ } else if (settings.scorexSettings.restApi.publicUrl.exists(invalidRestApiUrl)) {
+ failWithError(s"scorex.restApi.publicUrl should not contain query, path or fragment and should not " +
+ s"be local or loopback address : ${settings.scorexSettings.restApi.publicUrl.get}")
+ } else if (settings.nodeSettings.utxoSettings.p2pUtxoSnapshots <= 0) {
+ failWithError(s"p2pUtxoSnapshots <= 0, must be 1 at least")
+ } else if (settings.nodeSettings.extraIndex && settings.nodeSettings.isFullBlocksPruned) {
+ failWithError(s"Extra indexes could be enabled only if there is no blockchain pruning")
+ } else if (nodeSettings.nipopowSettings.nipopowBootstrap &&
+ !(nodeSettings.utxoSettings.utxoBootstrap || nodeSettings.blocksToKeep >= 0)) {
+ failWithError("nodeSettings.popowBootstrap can be set only if " +
+ "nodeSettings.utxoBootstrap is set or nodeSettings.blocksToKeep >=0")
+ } else if (nodeSettings.nipopowSettings.nipopowBootstrap && settings.chainSettings.genesisId.isEmpty) {
+ failWithError("nodeSettings.popowBootstrap is set but genesisId is not")
+ } else {
+ settings
+ }
+ }
+
+ private def failWithError(msg: String): Nothing = {
+ log.error(s"Stop application due to malformed configuration file: $msg")
+ ErgoApp.forceStopApplication()
+ }
+
+ /**
+ * Override the log level at runtime with values provided in config/user provided config.
+ */
+ private def overrideLogLevel(level: String): Unit = level match {
+ case "TRACE" | "ERROR" | "INFO" | "WARN" | "DEBUG" =>
+ log.info(s"Log level set to $level")
+ val loggerContext = LoggerFactory.getILoggerFactory.asInstanceOf[LoggerContext]
+ val root = loggerContext.getLogger(Logger.ROOT_LOGGER_NAME)
+ root.setLevel(Level.toLevel(level))
+ case _ => log.warn("No log level configuration provided")
+ }
+}
+
diff --git a/src/main/scala/org/ergoplatform/settings/NodeConfigurationSettings.scala b/src/main/scala/org/ergoplatform/settings/NodeConfigurationSettings.scala
index d1b60b5518..fdfbbc962f 100644
--- a/src/main/scala/org/ergoplatform/settings/NodeConfigurationSettings.scala
+++ b/src/main/scala/org/ergoplatform/settings/NodeConfigurationSettings.scala
@@ -3,7 +3,7 @@ package org.ergoplatform.settings
import net.ceedubs.ficus.Ficus._
import net.ceedubs.ficus.readers.ValueReader
import org.ergoplatform.ErgoLikeContext.Height
-import org.ergoplatform.nodeView.mempool.ErgoMemPool.SortingOption
+import org.ergoplatform.nodeView.mempool.ErgoMemPoolUtils.SortingOption
import org.ergoplatform.nodeView.state.StateType
import scorex.util.ModifierId
@@ -20,52 +20,16 @@ trait CheckpointingSettingsReader extends ModifierIdReader {
}
}
-/**
- * Settings related to state bootstrapping with UTXO set snapshots. See ergo.node.utxo section for settings description.
- */
-case class UtxoSettings(utxoBootstrap: Boolean, storingUtxoSnapshots: Int, p2pUtxoSnapshots: Int)
-
-/**
- * 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")
- )
- }
-}
-
-
-/**
- * Settings related to headers-chain bootstrapping with NiPoPoWs. See ergo.node.nipopow section for settings description.
- */
-case class NipopowSettings(nipopowBootstrap: Boolean, p2pNipopows: Int)
-
-/**
- * Custom settings reader for `NipopowSettings`
- */
-trait NipopowSettingsReader {
- implicit val nipopowSettingsReader: ValueReader[NipopowSettings] = { (cfg, path) =>
- NipopowSettings(
- cfg.as[Boolean](s"$path.nipopowBootstrap"),
- cfg.as[Int](s"$path.p2pNipopows")
- )
- }
-}
-
/**
* Configuration file for Ergo node regime
*
* @see src/main/resources/application.conf for parameters description
*/
-case class NodeConfigurationSettings(stateType: StateType,
- verifyTransactions: Boolean,
- blocksToKeep: Int,
- utxoSettings: UtxoSettings,
- nipopowSettings: NipopowSettings,
+case class NodeConfigurationSettings(override val stateType: StateType,
+ override val verifyTransactions: Boolean,
+ override val blocksToKeep: Int,
+ override val utxoSettings: UtxoSettings,
+ override val nipopowSettings: NipopowSettings,
mining: Boolean,
maxTransactionCost: Int,
maxTransactionSize: Int,
@@ -85,7 +49,7 @@ case class NodeConfigurationSettings(stateType: StateType,
adProofsSuffixLength: Int,
extraIndex: Boolean,
blacklistedTransactions: Seq[String] = Seq.empty,
- checkpoint: Option[CheckpointSettings] = None) {
+ checkpoint: Option[CheckpointSettings] = None) extends ClientCapabilities {
/**
* Whether the node keeping all the full blocks of the blockchain or not.
* @return true if the blockchain is pruned, false if not
diff --git a/src/main/scala/org/ergoplatform/tools/ValidationRulesPrinter.scala b/src/main/scala/org/ergoplatform/tools/ValidationRulesPrinter.scala
index ed668f4904..86239767b3 100644
--- a/src/main/scala/org/ergoplatform/tools/ValidationRulesPrinter.scala
+++ b/src/main/scala/org/ergoplatform/tools/ValidationRulesPrinter.scala
@@ -2,7 +2,7 @@ package org.ergoplatform.tools
import org.ergoplatform.modifiers.NetworkObjectTypeId
import org.ergoplatform.settings.ValidationRules
-import scorex.core.validation.InvalidModifier
+import org.ergoplatform.validation.InvalidModifier
import scorex.util.{ModifierId, ScorexLogging, bytesToId}
object ValidationRulesPrinter extends App with ScorexLogging {
diff --git a/src/main/scala/scorex/core/ModifiersCache.scala b/src/main/scala/scorex/core/ModifiersCache.scala
index e87a917cf1..71dc659fd3 100644
--- a/src/main/scala/scorex/core/ModifiersCache.scala
+++ b/src/main/scala/scorex/core/ModifiersCache.scala
@@ -1,8 +1,8 @@
package scorex.core
+import org.ergoplatform.consensus.ContainsModifiers
import org.ergoplatform.modifiers.{BlockSection, ErgoNodeViewModifier}
import org.ergoplatform.nodeView.history.ErgoHistory
-import scorex.core.consensus.ContainsModifiers
import scala.annotation.tailrec
import scala.collection.mutable
diff --git a/src/main/scala/scorex/core/api/http/ApiDirectives.scala b/src/main/scala/scorex/core/api/http/ApiDirectives.scala
index bebba07910..bb78146dda 100644
--- a/src/main/scala/scorex/core/api/http/ApiDirectives.scala
+++ b/src/main/scala/scorex/core/api/http/ApiDirectives.scala
@@ -1,8 +1,8 @@
package scorex.core.api.http
import akka.http.scaladsl.server.{AuthorizationFailedRejection, Directive0}
-import scorex.core.settings.RESTApiSettings
-import scorex.core.utils.ScorexEncoding
+import org.ergoplatform.settings.RESTApiSettings
+import org.ergoplatform.utils.ScorexEncoding
import scorex.crypto.hash.Blake2b256
trait ApiDirectives extends CorsHandler with ScorexEncoding {
diff --git a/src/main/scala/scorex/core/api/http/ApiErrorHandler.scala b/src/main/scala/scorex/core/api/http/ApiErrorHandler.scala
index e1ff032731..a8711e02c0 100644
--- a/src/main/scala/scorex/core/api/http/ApiErrorHandler.scala
+++ b/src/main/scala/scorex/core/api/http/ApiErrorHandler.scala
@@ -1,6 +1,7 @@
package scorex.core.api.http
import akka.http.scaladsl.server.ExceptionHandler
+import org.ergoplatform.http.api.ApiError
import scala.util.control.NonFatal
diff --git a/src/main/scala/scorex/core/api/http/ApiRejectionHandler.scala b/src/main/scala/scorex/core/api/http/ApiRejectionHandler.scala
index 628316b301..77d2cee772 100644
--- a/src/main/scala/scorex/core/api/http/ApiRejectionHandler.scala
+++ b/src/main/scala/scorex/core/api/http/ApiRejectionHandler.scala
@@ -1,6 +1,7 @@
package scorex.core.api.http
import akka.http.scaladsl.server._
+import org.ergoplatform.http.api.ApiError
object ApiRejectionHandler {
diff --git a/src/main/scala/scorex/core/api/http/ApiResponse.scala b/src/main/scala/scorex/core/api/http/ApiResponse.scala
index 19bd1a84d3..78690db8aa 100644
--- a/src/main/scala/scorex/core/api/http/ApiResponse.scala
+++ b/src/main/scala/scorex/core/api/http/ApiResponse.scala
@@ -4,6 +4,7 @@ import akka.http.scaladsl.model.{ContentTypes, HttpEntity, StatusCode, StatusCod
import akka.http.scaladsl.server.{Directives, Route}
import io.circe.syntax._
import io.circe.{Encoder, Json}
+import org.ergoplatform.http.api.ApiError
import scala.concurrent.Future
import scala.language.implicitConversions
diff --git a/src/main/scala/scorex/core/api/http/CompositeHttpService.scala b/src/main/scala/scorex/core/api/http/CompositeHttpService.scala
index fcba826590..2adcd13e09 100644
--- a/src/main/scala/scorex/core/api/http/CompositeHttpService.scala
+++ b/src/main/scala/scorex/core/api/http/CompositeHttpService.scala
@@ -4,8 +4,8 @@ import akka.actor.ActorSystem
import akka.http.scaladsl.model.StatusCodes
import akka.http.scaladsl.server.Route
import akka.http.scaladsl.server.directives.RouteDirectives
+import org.ergoplatform.settings.RESTApiSettings
import scorex.core.api.http.swagger.SwaggerConfigRoute
-import scorex.core.settings.RESTApiSettings
case class CompositeHttpService(system: ActorSystem, routes: Seq[ApiRoute], settings: RESTApiSettings, swaggerConf: String)
extends CorsHandler {
diff --git a/src/main/scala/scorex/core/api/http/swagger/SwaggerConfigRoute.scala b/src/main/scala/scorex/core/api/http/swagger/SwaggerConfigRoute.scala
index f5b104ed1d..79801be49a 100644
--- a/src/main/scala/scorex/core/api/http/swagger/SwaggerConfigRoute.scala
+++ b/src/main/scala/scorex/core/api/http/swagger/SwaggerConfigRoute.scala
@@ -3,8 +3,8 @@ package scorex.core.api.http.swagger
import akka.actor.ActorRefFactory
import akka.http.scaladsl.model.{ContentTypes, HttpEntity}
import akka.http.scaladsl.server.Route
+import org.ergoplatform.settings.RESTApiSettings
import scorex.core.api.http.ApiRoute
-import scorex.core.settings.RESTApiSettings
class SwaggerConfigRoute(swaggerConf: String, override val settings: RESTApiSettings)(implicit val context: ActorRefFactory)
extends ApiRoute {
diff --git a/src/main/scala/scorex/core/app/ScorexContext.scala b/src/main/scala/scorex/core/app/ScorexContext.scala
index 6af361ab9a..1ee96fa461 100644
--- a/src/main/scala/scorex/core/app/ScorexContext.scala
+++ b/src/main/scala/scorex/core/app/ScorexContext.scala
@@ -3,7 +3,7 @@ package scorex.core.app
import java.net.InetSocketAddress
import scorex.core.network.UPnPGateway
-import scorex.core.network.message.MessageSpec
+import org.ergoplatform.network.message.MessageSpec
case class ScorexContext(messageSpecs: Seq[MessageSpec[_]],
upnpGateway: Option[UPnPGateway],
diff --git a/src/main/scala/scorex/core/network/ConnectedPeer.scala b/src/main/scala/scorex/core/network/ConnectedPeer.scala
index b8e28ccd86..38461c3ddf 100644
--- a/src/main/scala/scorex/core/network/ConnectedPeer.scala
+++ b/src/main/scala/scorex/core/network/ConnectedPeer.scala
@@ -3,7 +3,7 @@ package scorex.core.network
import akka.actor.ActorRef
import io.circe.{Encoder, Json}
import org.ergoplatform.network.ModePeerFeature
-import scorex.core.network.peer.PeerInfo
+import org.ergoplatform.network.peer.PeerInfo
/**
* Peer connected to our node
diff --git a/src/main/scala/scorex/core/network/ConnectionDescription.scala b/src/main/scala/scorex/core/network/ConnectionDescription.scala
index 2f12775f01..024f6113b5 100644
--- a/src/main/scala/scorex/core/network/ConnectionDescription.scala
+++ b/src/main/scala/scorex/core/network/ConnectionDescription.scala
@@ -1,8 +1,8 @@
package scorex.core.network
import java.net.InetSocketAddress
-
import akka.actor.ActorRef
+import org.ergoplatform.network.PeerFeature
case class ConnectionDescription(connection: ActorRef,
connectionId: ConnectionId,
diff --git a/src/main/scala/scorex/core/network/DeliveryTracker.scala b/src/main/scala/scorex/core/network/DeliveryTracker.scala
index 3e8d37a578..158c1b5d11 100644
--- a/src/main/scala/scorex/core/network/DeliveryTracker.scala
+++ b/src/main/scala/scorex/core/network/DeliveryTracker.scala
@@ -2,15 +2,15 @@ package scorex.core.network
import akka.actor.Cancellable
import io.circe.{Encoder, Json}
+import org.ergoplatform.consensus.ContainsModifiers
import org.ergoplatform.modifiers.NetworkObjectTypeId
import org.ergoplatform.modifiers.history.header.Header
-import org.ergoplatform.network.ErgoNodeViewSynchronizer.ReceivableMessages.CheckDelivery
+import org.ergoplatform.network.ErgoNodeViewSynchronizerMessages.CheckDelivery
import org.ergoplatform.nodeView.mempool.ExpiringApproximateCache
import org.ergoplatform.settings.{ErgoSettings, NetworkCacheSettings}
-import scorex.core.consensus.ContainsModifiers
import scorex.core.network.DeliveryTracker._
import scorex.core.network.ModifiersStatus._
-import scorex.core.utils._
+import org.ergoplatform.utils._
import scorex.util.{ModifierId, ScorexLogging}
import scala.collection.mutable
diff --git a/src/main/scala/scorex/core/network/NetworkController.scala b/src/main/scala/scorex/core/network/NetworkController.scala
index 50a13552a4..60001e7154 100644
--- a/src/main/scala/scorex/core/network/NetworkController.scala
+++ b/src/main/scala/scorex/core/network/NetworkController.scala
@@ -6,16 +6,15 @@ import akka.io.Tcp._
import akka.io.{IO, Tcp}
import akka.pattern.ask
import akka.util.Timeout
-import scorex.core.app.{ScorexContext, Version}
-import org.ergoplatform.network.ErgoNodeViewSynchronizer.ReceivableMessages.{DisconnectedPeer, HandshakedPeer}
-import org.ergoplatform.network.ModePeerFeature
-import org.ergoplatform.nodeView.history.ErgoHistory
+import scorex.core.app.ScorexContext
+import org.ergoplatform.network.ErgoNodeViewSynchronizerMessages.{DisconnectedPeer, HandshakedPeer}
+import org.ergoplatform.network.{ModePeerFeature, Version}
import org.ergoplatform.settings.ErgoSettings
-import scorex.core.network.message.Message.MessageCode
-import scorex.core.network.message.Message
-import scorex.core.network.peer.PeerManager.ReceivableMessages._
-import scorex.core.network.peer.{LocalAddressPeerFeature, PeerInfo, PeerManager, PeersStatus, PenaltyType, RestApiUrlPeerFeature, SessionIdPeerFeature}
-import org.ergoplatform.nodeView.history.ErgoHistory.Time
+import org.ergoplatform.network.message.MessageConstants.MessageCode
+import org.ergoplatform.network.message.Message
+import org.ergoplatform.network.peer.PeerManager.ReceivableMessages._
+import org.ergoplatform.network.peer.{LocalAddressPeerFeature, PeerInfo, PeerManager, PeersStatus, PenaltyType, RestApiUrlPeerFeature, SessionIdPeerFeature}
+import org.ergoplatform.nodeView.history.ErgoHistoryUtils.Time
import scorex.core.utils.NetworkUtils
import scorex.util.ScorexLogging
@@ -69,7 +68,7 @@ class NetworkController(ergoSettings: ErgoSettings,
* Storing timestamp of a last message got via p2p network.
* Used to check whether connectivity is lost.
*/
- private var lastIncomingMessageTime: ErgoHistory.Time = 0L
+ private var lastIncomingMessageTime: Time = 0L
private val activityDelta: Long = 60 * 1000 // 1 min
//check own declared address for validity
diff --git a/src/main/scala/scorex/core/network/PeerConnectionHandler.scala b/src/main/scala/scorex/core/network/PeerConnectionHandler.scala
index 84bb3ac2f4..32dc1e25a9 100644
--- a/src/main/scala/scorex/core/network/PeerConnectionHandler.scala
+++ b/src/main/scala/scorex/core/network/PeerConnectionHandler.scala
@@ -4,13 +4,14 @@ import akka.actor.{Actor, ActorRef, Cancellable, Props, SupervisorStrategy}
import akka.io.Tcp
import akka.io.Tcp._
import akka.util.{ByteString, CompactByteString}
-import scorex.core.app.Version.Eip37ForkVersion
-import scorex.core.app.{ScorexContext, Version}
+import org.ergoplatform.network.{Handshake, PeerSpec, Version}
+import org.ergoplatform.network.Version.Eip37ForkVersion
+import scorex.core.app.ScorexContext
import scorex.core.network.NetworkController.ReceivableMessages.{Handshaked, PenalizePeer}
import scorex.core.network.PeerConnectionHandler.ReceivableMessages
-import scorex.core.network.message.{HandshakeSerializer, MessageSerializer}
-import scorex.core.network.peer.{PeerInfo, PenaltyType}
-import scorex.core.settings.ScorexSettings
+import org.ergoplatform.network.message.{HandshakeSerializer, MessageSerializer}
+import org.ergoplatform.network.peer.{PeerInfo, PenaltyType}
+import org.ergoplatform.settings.ScorexSettings
import scorex.util.ScorexLogging
import scala.annotation.tailrec
@@ -146,7 +147,7 @@ class PeerConnectionHandler(scorexSettings: ScorexSettings,
}
def localInterfaceWriting: Receive = {
- case msg: message.Message[_] =>
+ case msg: org.ergoplatform.network.message.Message[_] =>
log.info("Send message " + msg.spec + " to " + connectionId)
outMessagesCounter += 1
connection ! Write(messageSerializer.serialize(msg), ReceivableMessages.Ack(outMessagesCounter))
@@ -164,7 +165,7 @@ class PeerConnectionHandler(scorexSettings: ScorexSettings,
// operate in ACK mode until all buffered messages are transmitted
def localInterfaceBuffering: Receive = {
- case msg: message.Message[_] =>
+ case msg: org.ergoplatform.network.message.Message[_] =>
outMessagesCounter += 1
buffer(outMessagesCounter, messageSerializer.serialize(msg))
diff --git a/src/main/scala/scorex/core/network/PeerSynchronizer.scala b/src/main/scala/scorex/core/network/PeerSynchronizer.scala
index fddb446e12..6843b5b151 100644
--- a/src/main/scala/scorex/core/network/PeerSynchronizer.scala
+++ b/src/main/scala/scorex/core/network/PeerSynchronizer.scala
@@ -4,11 +4,12 @@ import akka.actor.SupervisorStrategy.{Restart, Stop}
import akka.actor.{Actor, ActorInitializationException, ActorKilledException, ActorRef, ActorSystem, DeathPactException, OneForOneStrategy, Props}
import akka.pattern.ask
import akka.util.Timeout
+import org.ergoplatform.network.PeerSpec
import scorex.core.network.NetworkController.ReceivableMessages.{PenalizePeer, SendToNetwork}
-import scorex.core.network.message.{GetPeersSpec, Message, MessageSpec, PeersSpec}
-import scorex.core.network.peer.{PeerInfo, PenaltyType}
-import scorex.core.network.peer.PeerManager.ReceivableMessages.{AddPeerIfEmpty, SeenPeers}
-import scorex.core.settings.NetworkSettings
+import org.ergoplatform.network.message.{GetPeersSpec, Message, MessageSpec, PeersSpec}
+import org.ergoplatform.network.peer.{PeerInfo, PenaltyType}
+import org.ergoplatform.network.peer.PeerManager.ReceivableMessages.{AddPeerIfEmpty, SeenPeers}
+import org.ergoplatform.settings.NetworkSettings
import scorex.util.ScorexLogging
import shapeless.syntax.typeable._
diff --git a/src/main/scala/scorex/core/network/Synchronizer.scala b/src/main/scala/scorex/core/network/Synchronizer.scala
index 27833d78c9..8e13836bf9 100644
--- a/src/main/scala/scorex/core/network/Synchronizer.scala
+++ b/src/main/scala/scorex/core/network/Synchronizer.scala
@@ -1,6 +1,6 @@
package scorex.core.network
-import scorex.core.network.message.MessageSpec
+import org.ergoplatform.network.message.MessageSpec
import scorex.util.ScorexLogging
import scala.util.{Failure, Success, Try}
diff --git a/src/main/scala/scorex/core/network/UPnP.scala b/src/main/scala/scorex/core/network/UPnP.scala
index 0d0d2a9123..2f82e4dcaa 100644
--- a/src/main/scala/scorex/core/network/UPnP.scala
+++ b/src/main/scala/scorex/core/network/UPnP.scala
@@ -1,9 +1,8 @@
package scorex.core.network
import java.net.{InetAddress, InetSocketAddress}
-
import org.bitlet.weupnp.{GatewayDevice, GatewayDiscover, PortMappingEntry}
-import scorex.core.settings.NetworkSettings
+import org.ergoplatform.settings.NetworkSettings
import scorex.util.ScorexLogging
import scala.collection.JavaConverters._
diff --git a/src/test/scala/org/ergoplatform/db/DBSpec.scala b/src/test/scala/org/ergoplatform/db/DBSpec.scala
index f2617ee32a..58f908be48 100644
--- a/src/test/scala/org/ergoplatform/db/DBSpec.scala
+++ b/src/test/scala/org/ergoplatform/db/DBSpec.scala
@@ -21,7 +21,7 @@ trait DBSpec extends TestFileUtils {
protected def byteString32(s: String): Array[Byte] = Algos.hash(byteString(s))
- protected def withDb(body: DB => Unit): Unit = {
+ protected def withDb[T](body: DB => T): T = {
val options = new Options()
options.createIfMissing(true)
options.verifyChecksums(true)
@@ -32,10 +32,10 @@ trait DBSpec extends TestFileUtils {
protected def versionId(s: String): Array[Byte] = byteString32(s)
- protected def withStore(body: LDBKVStore => Unit): Unit =
+ protected def withStore[T](body: LDBKVStore => T): T =
withDb { db: DB => body(new LDBKVStore(db)) }
- protected def withVersionedStore(keepVersions: Int)(body: LDBVersionedStore => Unit): Unit = {
+ protected def withVersionedStore[T](keepVersions: Int)(body: LDBVersionedStore => T): T = {
val db = new LDBVersionedStore(createTempDir, keepVersions)
try body(db) finally db.close()
}
diff --git a/src/test/scala/org/ergoplatform/http/routes/EmissionApiRouteSpec.scala b/src/test/scala/org/ergoplatform/http/routes/EmissionApiRouteSpec.scala
index 7d89b239a5..c48d4a6dbe 100644
--- a/src/test/scala/org/ergoplatform/http/routes/EmissionApiRouteSpec.scala
+++ b/src/test/scala/org/ergoplatform/http/routes/EmissionApiRouteSpec.scala
@@ -9,7 +9,7 @@ import io.circe.Json
import io.circe.syntax._
import org.ergoplatform.http.api.EmissionApiRoute
import org.ergoplatform.mining.emission.EmissionRules
-import org.ergoplatform.settings.{ErgoSettings, ReemissionSettings}
+import org.ergoplatform.settings.{ErgoSettings, ErgoSettingsReader, ReemissionSettings}
import org.scalatest.flatspec.AnyFlatSpec
import org.scalatest.matchers.should.Matchers
@@ -24,7 +24,7 @@ class EmissionApiRouteSpec extends AnyFlatSpec
implicit val timeout: RouteTestTimeout = RouteTestTimeout(15.seconds.dilated)
- val ergoSettings: ErgoSettings = ErgoSettings.read()
+ val ergoSettings: ErgoSettings = ErgoSettingsReader.read()
val coinEmission: EmissionRules = ergoSettings.chainSettings.emissionRules
val reemissionSettings: ReemissionSettings = ergoSettings.chainSettings.reemission
diff --git a/src/test/scala/org/ergoplatform/http/routes/ErgoPeersApiRouteSpec.scala b/src/test/scala/org/ergoplatform/http/routes/ErgoPeersApiRouteSpec.scala
index de1a6edc5d..371dc088be 100644
--- a/src/test/scala/org/ergoplatform/http/routes/ErgoPeersApiRouteSpec.scala
+++ b/src/test/scala/org/ergoplatform/http/routes/ErgoPeersApiRouteSpec.scala
@@ -14,8 +14,8 @@ import org.scalatest.flatspec.AnyFlatSpec
import org.scalatest.matchers.should.Matchers
import org.scalatestplus.scalacheck.ScalaCheckPropertyChecks
import scorex.core.network.NetworkController.ReceivableMessages.GetConnectedPeers
-import scorex.core.network.peer.PeerManager.ReceivableMessages.GetAllPeers
-import scorex.core.settings.RESTApiSettings
+import org.ergoplatform.network.peer.PeerManager.ReceivableMessages.GetAllPeers
+import org.ergoplatform.settings.RESTApiSettings
import java.net.InetSocketAddress
import scala.concurrent.Future
diff --git a/src/test/scala/org/ergoplatform/http/routes/InfoApiRoutesSpec.scala b/src/test/scala/org/ergoplatform/http/routes/InfoApiRoutesSpec.scala
index 706ff37ddd..8b5c67a621 100644
--- a/src/test/scala/org/ergoplatform/http/routes/InfoApiRoutesSpec.scala
+++ b/src/test/scala/org/ergoplatform/http/routes/InfoApiRoutesSpec.scala
@@ -16,8 +16,8 @@ import org.ergoplatform.local.ErgoStatsCollector.{GetNodeInfo, NodeInfo}
import org.ergoplatform.local.ErgoStatsCollectorRef
import org.ergoplatform.mining.difficulty.DifficultySerializer
import org.ergoplatform.modifiers.history.header.Header
-import org.ergoplatform.network.ErgoNodeViewSynchronizer.ReceivableMessages.ChangedHistory
-import org.ergoplatform.nodeView.history.ErgoHistory.Difficulty
+import org.ergoplatform.network.ErgoNodeViewSynchronizerMessages.ChangedHistory
+import org.ergoplatform.nodeView.history.ErgoHistoryUtils.Difficulty
import org.ergoplatform.utils.Stubs
import org.scalatest.flatspec.AnyFlatSpec
import org.scalatest.matchers.should.Matchers
diff --git a/src/test/scala/org/ergoplatform/http/routes/ScanApiRouteSpec.scala b/src/test/scala/org/ergoplatform/http/routes/ScanApiRouteSpec.scala
index fb4956190f..c3a1c33851 100644
--- a/src/test/scala/org/ergoplatform/http/routes/ScanApiRouteSpec.scala
+++ b/src/test/scala/org/ergoplatform/http/routes/ScanApiRouteSpec.scala
@@ -10,7 +10,7 @@ import org.ergoplatform.ErgoBox
import org.ergoplatform.http.api.ScanEntities.{ScanIdBoxId, ScanIdWrapper}
import org.ergoplatform.http.api.{ApiCodecs, ScanApiRoute}
import org.ergoplatform.nodeView.wallet.scanning._
-import org.ergoplatform.settings.{Args, ErgoSettings}
+import org.ergoplatform.settings.{Args, ErgoSettings, ErgoSettingsReader}
import org.ergoplatform.utils.Stubs
import org.ergoplatform.wallet.Constants.ScanId
import org.scalatest.flatspec.AnyFlatSpec
@@ -36,7 +36,7 @@ class ScanApiRouteSpec extends AnyFlatSpec
val prefix = "/scan"
- val ergoSettings: ErgoSettings = ErgoSettings.read(
+ val ergoSettings: ErgoSettings = ErgoSettingsReader.read(
Args(userConfigPathOpt = Some("src/test/resources/application.conf"), networkTypeOpt = None))
val route: Route = ScanApiRoute(utxoReadersRef, ergoSettings).route
diff --git a/src/test/scala/org/ergoplatform/http/routes/ScriptApiRouteSpec.scala b/src/test/scala/org/ergoplatform/http/routes/ScriptApiRouteSpec.scala
index acd2fd8de5..ff4b372c56 100644
--- a/src/test/scala/org/ergoplatform/http/routes/ScriptApiRouteSpec.scala
+++ b/src/test/scala/org/ergoplatform/http/routes/ScriptApiRouteSpec.scala
@@ -6,7 +6,7 @@ import akka.http.scaladsl.testkit.ScalatestRouteTest
import de.heikoseeberger.akkahttpcirce.FailFastCirceSupport
import io.circe.Json
import org.ergoplatform.{Pay2SAddress, Pay2SHAddress}
-import org.ergoplatform.settings.{Args, ErgoSettings}
+import org.ergoplatform.settings.{Args, ErgoSettings, ErgoSettingsReader}
import org.ergoplatform.utils.Stubs
import io.circe.syntax._
import org.ergoplatform.http.api.ScriptApiRoute
@@ -26,7 +26,7 @@ class ScriptApiRouteSpec extends AnyFlatSpec
val prefix = "/script"
- val ergoSettings: ErgoSettings = ErgoSettings.read(
+ val ergoSettings: ErgoSettings = ErgoSettingsReader.read(
Args(userConfigPathOpt = Some("src/test/resources/application.conf"), networkTypeOpt = None))
val route: Route = ScriptApiRoute(digestReadersRef, settings).route
diff --git a/src/test/scala/org/ergoplatform/http/routes/TransactionApiRouteSpec.scala b/src/test/scala/org/ergoplatform/http/routes/TransactionApiRouteSpec.scala
index 1e7860907f..2708b93390 100644
--- a/src/test/scala/org/ergoplatform/http/routes/TransactionApiRouteSpec.scala
+++ b/src/test/scala/org/ergoplatform/http/routes/TransactionApiRouteSpec.scala
@@ -11,12 +11,11 @@ import org.ergoplatform.ErgoBox.{AdditionalRegisters, NonMandatoryRegisterId, To
import org.ergoplatform.http.api.{ApiCodecs, TransactionsApiRoute}
import org.ergoplatform.modifiers.mempool.{ErgoTransaction, UnconfirmedTransaction}
import org.ergoplatform.nodeView.ErgoReadersHolder.{GetDataFromHistory, GetReaders, Readers}
-import org.ergoplatform.settings.Constants
+import org.ergoplatform.settings.{Constants, RESTApiSettings}
import org.ergoplatform.utils.Stubs
import org.ergoplatform.{DataInput, ErgoBox, ErgoBoxCandidate, Input}
import org.scalatest.flatspec.AnyFlatSpec
import org.scalatest.matchers.should.Matchers
-import scorex.core.settings.RESTApiSettings
import scorex.util.encode.Base16
import sigmastate.SType
import sigmastate.Values.{ByteArrayConstant, EvaluatedValue}
diff --git a/src/test/scala/org/ergoplatform/http/routes/UtilsApiRouteSpec.scala b/src/test/scala/org/ergoplatform/http/routes/UtilsApiRouteSpec.scala
index ea4f0e01ba..57503fb23a 100644
--- a/src/test/scala/org/ergoplatform/http/routes/UtilsApiRouteSpec.scala
+++ b/src/test/scala/org/ergoplatform/http/routes/UtilsApiRouteSpec.scala
@@ -1,7 +1,6 @@
package org.ergoplatform.http.routes
import java.net.InetSocketAddress
-
import akka.http.scaladsl.model.StatusCodes
import akka.http.scaladsl.server.Route
import akka.http.scaladsl.testkit.ScalatestRouteTest
@@ -10,9 +9,9 @@ import io.circe.Json
import org.ergoplatform.utils.Stubs
import org.ergoplatform.{P2PKAddress, Pay2SAddress, Pay2SHAddress}
import org.ergoplatform.http.api.ErgoUtilsApiRoute
+import org.ergoplatform.settings.RESTApiSettings
import org.scalatest.flatspec.AnyFlatSpec
import org.scalatest.matchers.should.Matchers
-import scorex.core.settings.RESTApiSettings
import scorex.util.encode.Base16
import sigmastate.serialization.ErgoTreeSerializer
diff --git a/src/test/scala/org/ergoplatform/http/routes/WalletApiRouteSpec.scala b/src/test/scala/org/ergoplatform/http/routes/WalletApiRouteSpec.scala
index 3aa73d9dc1..843c99b69f 100644
--- a/src/test/scala/org/ergoplatform/http/routes/WalletApiRouteSpec.scala
+++ b/src/test/scala/org/ergoplatform/http/routes/WalletApiRouteSpec.scala
@@ -6,11 +6,11 @@ import akka.http.scaladsl.testkit.{RouteTestTimeout, ScalatestRouteTest}
import de.heikoseeberger.akkahttpcirce.FailFastCirceSupport
import io.circe.syntax._
import io.circe.{Decoder, Json}
-import org.ergoplatform.http.api.{ApiCodecs, WalletApiRoute}
+import org.ergoplatform.http.api.{ApiCodecs, ApiExtraCodecs, ApiRequestsCodecs, WalletApiRoute}
import org.ergoplatform.modifiers.mempool.ErgoTransaction
import org.ergoplatform.nodeView.wallet.requests.{AssetIssueRequestEncoder, PaymentRequest, PaymentRequestEncoder, _}
import org.ergoplatform.nodeView.wallet.{AugWalletTransaction, ErgoAddressJsonEncoder}
-import org.ergoplatform.settings.{Args, Constants, ErgoSettings}
+import org.ergoplatform.settings.{Args, Constants, ErgoSettings, ErgoSettingsReader}
import org.ergoplatform.utils.Stubs
import org.ergoplatform.utils.generators.ErgoTransactionGenerators
import org.ergoplatform.{ErgoAddress, Pay2SAddress}
@@ -27,13 +27,15 @@ class WalletApiRouteSpec extends AnyFlatSpec
with ScalatestRouteTest
with Stubs
with FailFastCirceSupport
- with ApiCodecs {
+ with ApiCodecs
+ with ApiRequestsCodecs
+ with ApiExtraCodecs {
implicit val timeout: RouteTestTimeout = RouteTestTimeout(145.seconds)
val prefix = "/wallet"
- val ergoSettings: ErgoSettings = ErgoSettings.read(
+ val ergoSettings: ErgoSettings = ErgoSettingsReader.read(
Args(userConfigPathOpt = Some("src/test/resources/application.conf"), networkTypeOpt = None))
val route: Route = WalletApiRoute(digestReadersRef, nodeViewRef, settings).route
val failingNodeViewRef = system.actorOf(NodeViewStub.failingProps())
@@ -44,7 +46,7 @@ class WalletApiRouteSpec extends AnyFlatSpec
implicit val paymentRequestEncoder: PaymentRequestEncoder = new PaymentRequestEncoder(ergoSettings)
implicit val assetIssueRequestEncoder: AssetIssueRequestEncoder = new AssetIssueRequestEncoder(ergoSettings)
implicit val requestsHolderEncoder: RequestsHolderEncoder = new RequestsHolderEncoder(ergoSettings)
- implicit val addressJsonDecoder: Decoder[ErgoAddress] = ErgoAddressJsonEncoder(settings).decoder
+ implicit val addressJsonDecoder: Decoder[ErgoAddress] = ErgoAddressJsonEncoder(settings.chainSettings).decoder
val paymentRequest = PaymentRequest(Pay2SAddress(Constants.FalseLeaf)(addressEncoder), 100L, Seq.empty, Map.empty)
val assetIssueRequest = AssetIssueRequest(Pay2SAddress(Constants.FalseLeaf)(addressEncoder), None, 100L, "TEST", "Test", 8)
diff --git a/src/test/scala/org/ergoplatform/local/MempoolAuditorSpec.scala b/src/test/scala/org/ergoplatform/local/MempoolAuditorSpec.scala
index f018569c5e..749f9f41de 100644
--- a/src/test/scala/org/ergoplatform/local/MempoolAuditorSpec.scala
+++ b/src/test/scala/org/ergoplatform/local/MempoolAuditorSpec.scala
@@ -4,9 +4,9 @@ import akka.actor.{ActorRef, ActorSystem}
import akka.testkit.{TestActorRef, TestProbe}
import org.ergoplatform.ErgoAddressEncoder
import org.ergoplatform.modifiers.mempool.UnconfirmedTransaction
-import org.ergoplatform.network.ErgoNodeViewSynchronizer.ReceivableMessages.{FailedTransaction, RecheckMempool, SuccessfulTransaction}
+import org.ergoplatform.network.ErgoNodeViewSynchronizerMessages.{FailedTransaction, RecheckMempool, SuccessfulTransaction}
import org.ergoplatform.nodeView.ErgoNodeViewHolder.ReceivableMessages.{LocallyGeneratedTransaction, RecheckedTransactions}
-import org.ergoplatform.nodeView.mempool.ErgoMemPool.ProcessingOutcome
+import org.ergoplatform.nodeView.mempool.ErgoMemPoolUtils.ProcessingOutcome
import org.ergoplatform.nodeView.state.ErgoState
import org.ergoplatform.nodeView.state.wrapped.WrappedUtxoState
import org.ergoplatform.settings.{Algos, Constants, ErgoSettings}
@@ -86,7 +86,7 @@ class MempoolAuditorSpec extends AnyFlatSpec with NodeViewTestOps with ErgoTestH
applyBlock(block) shouldBe 'success
- scorex.core.utils.untilTimeout(cleanupDuration * 4, 100.millis) {
+ org.ergoplatform.utils.untilTimeout(cleanupDuration * 4, 100.millis) {
// first tx removed from pool during node view update
// another tx invalidated by `MempoolAuditor`
getPoolSize shouldBe 0
diff --git a/src/test/scala/org/ergoplatform/mining/AutolykosPowSchemeSpec.scala b/src/test/scala/org/ergoplatform/mining/AutolykosPowSchemeSpec.scala
index 173623f510..415120f93b 100644
--- a/src/test/scala/org/ergoplatform/mining/AutolykosPowSchemeSpec.scala
+++ b/src/test/scala/org/ergoplatform/mining/AutolykosPowSchemeSpec.scala
@@ -3,10 +3,10 @@ package org.ergoplatform.mining
import com.google.common.primitives.Ints
import org.ergoplatform.mining.difficulty.DifficultySerializer
import org.ergoplatform.modifiers.history.header.{Header, HeaderSerializer}
+import org.ergoplatform.testkit.utils.NoShrink
import org.ergoplatform.utils.ErgoPropertyTest
import org.scalacheck.Gen
import scorex.crypto.hash.Blake2b256
-import scorex.testkit.utils.NoShrink
import scorex.util.encode.Base16
class AutolykosPowSchemeSpec extends ErgoPropertyTest with NoShrink {
diff --git a/src/test/scala/org/ergoplatform/mining/CandidateGeneratorPropSpec.scala b/src/test/scala/org/ergoplatform/mining/CandidateGeneratorPropSpec.scala
index 1c666e18e4..4917d4d104 100644
--- a/src/test/scala/org/ergoplatform/mining/CandidateGeneratorPropSpec.scala
+++ b/src/test/scala/org/ergoplatform/mining/CandidateGeneratorPropSpec.scala
@@ -1,7 +1,7 @@
package org.ergoplatform.mining
import org.ergoplatform.ErgoTreePredef
-import org.ergoplatform.nodeView.history.ErgoHistory
+import org.ergoplatform.nodeView.history.ErgoHistoryUtils._
import org.ergoplatform.nodeView.state.ErgoStateContext
import org.ergoplatform.settings.MonetarySettings
import org.ergoplatform.utils.{ErgoPropertyTest, RandomWrapper}
@@ -199,11 +199,11 @@ class CandidateGeneratorPropSpec extends ErgoPropertyTest {
val bh = boxesHolderGen.sample.get
var us = createUtxoState(bh, parameters)
- val height = ErgoHistory.EmptyHistoryHeight
+ val height = EmptyHistoryHeight
val ms = MonetarySettings(minerRewardDelay = delta)
val st = settings.copy(chainSettings = settings.chainSettings.copy(monetary = ms))
- val sc = ErgoStateContext.empty(genesisStateDigest, st, parameters)
+ val sc = ErgoStateContext.empty(genesisStateDigest, st.chainSettings, parameters)
val txBoxes = bh.boxes.grouped(inputsNum).map(_.values.toIndexedSeq).toSeq
val blockTx =
@@ -248,7 +248,7 @@ class CandidateGeneratorPropSpec extends ErgoPropertyTest {
Gen.nonEmptyListOf(validErgoTransactionGenTemplate(minAssets = 0, propositionGen = feeProp))
) { btxs =>
val blockTxs = btxs.map(_._2)
- val height = ErgoHistory.EmptyHistoryHeight
+ val height = EmptyHistoryHeight
val txs = CandidateGenerator.collectRewards(
us.emissionBoxOpt,
height,
diff --git a/src/test/scala/org/ergoplatform/mining/CandidateGeneratorSpec.scala b/src/test/scala/org/ergoplatform/mining/CandidateGeneratorSpec.scala
index 148d5ebffb..d94938f591 100644
--- a/src/test/scala/org/ergoplatform/mining/CandidateGeneratorSpec.scala
+++ b/src/test/scala/org/ergoplatform/mining/CandidateGeneratorSpec.scala
@@ -9,12 +9,12 @@ import org.ergoplatform.mining.CandidateGenerator.{Candidate, GenerateCandidate}
import org.ergoplatform.modifiers.ErgoFullBlock
import org.ergoplatform.modifiers.history.header.Header
import org.ergoplatform.modifiers.mempool.{ErgoTransaction, UnsignedErgoTransaction}
-import org.ergoplatform.network.ErgoNodeViewSynchronizer.ReceivableMessages.FullBlockApplied
+import org.ergoplatform.network.ErgoNodeViewSynchronizerMessages.FullBlockApplied
import org.ergoplatform.nodeView.ErgoReadersHolder.{GetReaders, Readers}
import org.ergoplatform.nodeView.history.ErgoHistoryReader
import org.ergoplatform.nodeView.state.StateType
import org.ergoplatform.nodeView.{ErgoNodeViewRef, ErgoReadersHolderRef}
-import org.ergoplatform.settings.ErgoSettings
+import org.ergoplatform.settings.{ErgoSettings, ErgoSettingsReader}
import org.ergoplatform.utils.ErgoTestHelpers
import org.ergoplatform.{ErgoBox, ErgoBoxCandidate, ErgoTreePredef, Input}
import org.scalatest.concurrent.Eventually
@@ -34,7 +34,7 @@ class CandidateGeneratorSpec extends AnyFlatSpec with ErgoTestHelpers with Event
private val blockValidationDelay: FiniteDuration = 2.seconds
val defaultSettings: ErgoSettings = {
- val empty = ErgoSettings.read()
+ val empty = ErgoSettingsReader.read()
val nodeSettings = empty.nodeSettings.copy(
mining = true,
stateType = StateType.Utxo,
diff --git a/src/test/scala/org/ergoplatform/mining/ErgoMinerSpec.scala b/src/test/scala/org/ergoplatform/mining/ErgoMinerSpec.scala
index 25258277e3..c86eea5209 100644
--- a/src/test/scala/org/ergoplatform/mining/ErgoMinerSpec.scala
+++ b/src/test/scala/org/ergoplatform/mining/ErgoMinerSpec.scala
@@ -10,14 +10,14 @@ import org.ergoplatform.mining.ErgoMiner.StartMining
import org.ergoplatform.modifiers.ErgoFullBlock
import org.ergoplatform.modifiers.history.header.Header
import org.ergoplatform.modifiers.mempool.{ErgoTransaction, UnconfirmedTransaction, UnsignedErgoTransaction}
-import org.ergoplatform.network.ErgoNodeViewSynchronizer.ReceivableMessages.FullBlockApplied
+import org.ergoplatform.network.ErgoNodeViewSynchronizerMessages.FullBlockApplied
import org.ergoplatform.nodeView.ErgoNodeViewHolder.ReceivableMessages.LocallyGeneratedTransaction
import org.ergoplatform.nodeView.ErgoReadersHolder.{GetReaders, Readers}
import org.ergoplatform.nodeView.history.ErgoHistoryReader
import org.ergoplatform.nodeView.state._
import org.ergoplatform.nodeView.wallet._
import org.ergoplatform.nodeView.{ErgoNodeViewRef, ErgoReadersHolderRef}
-import org.ergoplatform.settings.ErgoSettings
+import org.ergoplatform.settings.{ErgoSettings, ErgoSettingsReader}
import org.ergoplatform.utils.ErgoTestHelpers
import org.ergoplatform.utils.generators.ValidBlocksGenerators
import org.ergoplatform.wallet.interpreter.ErgoInterpreter
@@ -47,7 +47,7 @@ class ErgoMinerSpec extends AnyFlatSpec with ErgoTestHelpers with ValidBlocksGen
await(minerRef.askWithStatus(GenerateCandidate(mandatoryTransactions, reply = true)).mapTo[Candidate].map(_.externalVersion))
val defaultSettings: ErgoSettings = {
- val empty = ErgoSettings.read()
+ val empty = ErgoSettingsReader.read()
val nodeSettings = empty.nodeSettings.copy(mining = true,
stateType = StateType.Utxo,
@@ -206,7 +206,7 @@ class ErgoMinerSpec extends AnyFlatSpec with ErgoTestHelpers with ValidBlocksGen
}
// wait for mempool to be cleaned
- scorex.core.utils.untilTimeout(5.minute, 500.millis) {
+ org.ergoplatform.utils.untilTimeout(5.minute, 500.millis) {
log.debug(s"Wait until transactions in mempool will be included into blocks. Currents size: ${requestReaders.m.size}")
requestReaders.m.size shouldBe 0
system.terminate()
@@ -376,7 +376,7 @@ class ErgoMinerSpec extends AnyFlatSpec with ErgoTestHelpers with ValidBlocksGen
system.eventStream.subscribe(testProbe.ref, newBlockSignal)
val forkSettings: ErgoSettings = {
- val empty = ErgoSettings.read()
+ val empty = ErgoSettingsReader.read()
val nodeSettings = empty.nodeSettings.copy(mining = true,
stateType = StateType.Utxo,
diff --git a/src/test/scala/org/ergoplatform/modifiers/history/PoPowAlgosSpec.scala b/src/test/scala/org/ergoplatform/modifiers/history/PoPowAlgosSpec.scala
index ea2a976724..a13fb887cf 100644
--- a/src/test/scala/org/ergoplatform/modifiers/history/PoPowAlgosSpec.scala
+++ b/src/test/scala/org/ergoplatform/modifiers/history/PoPowAlgosSpec.scala
@@ -1,6 +1,6 @@
package org.ergoplatform.modifiers.history
-import org.ergoplatform.modifiers.history.popow.{NipopowAlgos, NipopowProof, PoPowHeader, PoPowParams}
+import org.ergoplatform.modifiers.history.popow.{NipopowAlgos, NipopowProverWithDbAlgs, NipopowProof, PoPowHeader, PoPowParams}
import org.ergoplatform.modifiers.ErgoFullBlock
import org.ergoplatform.nodeView.state.StateType
import org.ergoplatform.utils.generators.ChainGenerator
@@ -127,7 +127,7 @@ class PoPowAlgosSpec extends AnyPropSpec with Matchers with HistoryTestHelpers w
val h = generateHistory(true, StateType.Digest, false,
10000, 10000, 10, None)
val hr = applyChain(h, blocksChain)
- val proof1 = nipopowAlgos.prove(hr)(poPowParams).get
+ val proof1 = NipopowProverWithDbAlgs.prove(hr, chainSettings = settings.chainSettings)(poPowParams).get
proof0.suffixHead.id shouldBe proof1.suffixHead.id
proof0.suffixTail.map(_.id) shouldBe proof1.suffixTail.map(_.id)
@@ -145,12 +145,12 @@ class PoPowAlgosSpec extends AnyPropSpec with Matchers with HistoryTestHelpers w
val h = generateHistory(true, StateType.Digest, false,
10000, 10000, 10, None)
val hr = applyChain(h, blocksChain.take(at))
- val proof0 = nipopowAlgos.prove(hr, None)(poPowParams).get
+ val proof0 = NipopowProverWithDbAlgs.prove(hr, None, chainSettings = settings.chainSettings)(poPowParams).get
val id = proof0.suffixHead.header.id
val hrf = applyChain(hr, blocksChain.drop(at))
- val proof1 = nipopowAlgos.prove(hrf, Some(id))(poPowParams).get
+ val proof1 = NipopowProverWithDbAlgs.prove(hrf, Some(id), chainSettings = settings.chainSettings)(poPowParams).get
proof0.suffixHead.id shouldBe proof1.suffixHead.id
proof0.suffixTail.map(_.id) shouldBe proof1.suffixTail.map(_.id)
diff --git a/src/test/scala/org/ergoplatform/modifiers/mempool/ErgoTransactionSpec.scala b/src/test/scala/org/ergoplatform/modifiers/mempool/ErgoTransactionSpec.scala
index 4901e7526b..371b356384 100644
--- a/src/test/scala/org/ergoplatform/modifiers/mempool/ErgoTransactionSpec.scala
+++ b/src/test/scala/org/ergoplatform/modifiers/mempool/ErgoTransactionSpec.scala
@@ -356,7 +356,7 @@ class ErgoTransactionSpec extends ErgoPropertyTest with ErgoTestConstants {
val maxCost = (Int.MaxValue - 10) / 10 // cannot use Int.MaxValue directly due to overflow when it is converted to block cost
val ps = Parameters(0, DefaultParameters.updated(MaxBlockCostIncrease, maxCost), emptyVSUpdate)
val sc = new ErgoStateContext(Seq.empty, None, genesisStateDigest, ps, ErgoValidationSettings.initial,
- VotingData.empty)(settings)
+ VotingData.empty)(settings.chainSettings)
.upcoming(org.ergoplatform.mining.group.generator,
0L,
settings.chainSettings.initialNBits,
@@ -478,7 +478,7 @@ class ErgoTransactionSpec extends ErgoPropertyTest with ErgoTestConstants {
LaunchParameters.parametersTable.updated(Parameters.BlockVersion, blockVersion),
LaunchParameters.proposedUpdate)
new ErgoStateContext(Seq(header), None, genesisStateDigest, params, ErgoValidationSettings.initial,
- VotingData.empty)(settings)
+ VotingData.empty)(settings.chainSettings)
}
def stateContextForTx(tx: ErgoTransaction, blockVersion: Byte): ErgoStateContext = {
diff --git a/src/test/scala/org/ergoplatform/modifiers/mempool/ExpirationSpecification.scala b/src/test/scala/org/ergoplatform/modifiers/mempool/ExpirationSpecification.scala
index 7398a9ce5f..38c67cad88 100644
--- a/src/test/scala/org/ergoplatform/modifiers/mempool/ExpirationSpecification.scala
+++ b/src/test/scala/org/ergoplatform/modifiers/mempool/ExpirationSpecification.scala
@@ -6,11 +6,13 @@ import org.ergoplatform.utils.ErgoPropertyTest
import org.ergoplatform.wallet.interpreter.ErgoInterpreter
import org.ergoplatform.{ErgoBox, ErgoBoxCandidate, Input}
import org.scalatest.Assertion
+import scorex.util.encode.Base16
import sigma.Colls
-import sigmastate.Values.ShortConstant
+import sigmastate.Values.{ErgoTree, ShortConstant}
import sigmastate.interpreter.{ContextExtension, ProverResult}
import sigmastate.eval._
import sigmastate.helpers.TestingHelpers._
+import sigmastate.serialization.ErgoTreeSerializer
class ExpirationSpecification extends ErgoPropertyTest {
@@ -18,9 +20,9 @@ class ExpirationSpecification extends ErgoPropertyTest {
private implicit val verifier: ErgoInterpreter = ErgoInterpreter(parameters)
- def falsify(box: ErgoBox): ErgoBox = {
+ def injectScript(box: ErgoBox, script: ErgoTree): ErgoBox = {
testBox(box.value,
- Constants.FalseLeaf,
+ script,
box.creationHeight,
box.additionalTokens.toArray.toSeq,
box.additionalRegisters,
@@ -49,7 +51,7 @@ class ExpirationSpecification extends ErgoPropertyTest {
val updContext = {
val inContext = new ErgoStateContext(Seq(fakeHeader), None, genesisStateDigest, parameters, validationSettingsNoIl,
- VotingData.empty)(settings)
+ VotingData.empty)(settings.chainSettings)
inContext.appendFullBlock(fb).get
}
@@ -68,6 +70,16 @@ class ExpirationSpecification extends ErgoPropertyTest {
}
}
+ property("successful spending w. invalid ergotree") {
+ forAll(unspendableErgoBoxGen()) { from =>
+ // invalid (unparseable) ergo tree
+ val etString = "0e1631393039303063646462363930366462363530336665"
+ val et = ErgoTreeSerializer.DefaultSerializer.deserializeErgoTree(Base16.decode(etString).get)
+ val modified = injectScript(from, et)
+ constructTest(modified, 0, _ => IndexedSeq(modified), expectedValidity = true)
+ }
+ }
+
property("successful spending w. max spending") {
forAll(unspendableErgoBoxGen()) { from =>
constructTest(from, 0, h => {
diff --git a/src/test/scala/org/ergoplatform/network/ActivePeerFilteringSpecification.scala b/src/test/scala/org/ergoplatform/network/ActivePeerFilteringSpecification.scala
index 8271050c45..3bd2e3d823 100644
--- a/src/test/scala/org/ergoplatform/network/ActivePeerFilteringSpecification.scala
+++ b/src/test/scala/org/ergoplatform/network/ActivePeerFilteringSpecification.scala
@@ -1,8 +1,8 @@
package org.ergoplatform.network
import org.ergoplatform.utils.ErgoPropertyTest
-import scorex.core.network.peer.PeerInfo
-import scorex.core.network.peer.PeerManager.ReceivableMessages.SeenPeers
+import org.ergoplatform.network.peer.PeerInfo
+import org.ergoplatform.network.peer.PeerManager.ReceivableMessages.SeenPeers
import java.net.{InetAddress, InetSocketAddress}
diff --git a/src/test/scala/org/ergoplatform/network/DeliveryTrackerSpec.scala b/src/test/scala/org/ergoplatform/network/DeliveryTrackerSpec.scala
new file mode 100644
index 0000000000..2372e5c085
--- /dev/null
+++ b/src/test/scala/org/ergoplatform/network/DeliveryTrackerSpec.scala
@@ -0,0 +1,73 @@
+package org.ergoplatform.network
+
+import akka.actor.{ActorRef, Cancellable}
+import io.circe._
+import io.circe.syntax._
+import org.ergoplatform.modifiers.NetworkObjectTypeId
+import org.ergoplatform.testkit.generators.ObjectGenerators
+import org.ergoplatform.utils.ErgoPropertyTest
+import scorex.util.ModifierId
+import scorex.core.network.DeliveryTracker
+import scorex.core.network.ModifiersStatus._
+
+
+class DeliveryTrackerSpec extends ErgoPropertyTest with ObjectGenerators {
+
+ property("tracker should accept requested modifiers, turn them into received and clear them") {
+ forAll(connectedPeerGen(ActorRef.noSender)) { peer =>
+ val tracker = DeliveryTracker.empty(settings)
+ val mid: ModifierId = ModifierId @@ "foo"
+ val mTypeId: NetworkObjectTypeId.Value = NetworkObjectTypeId.fromByte(104)
+ tracker.setRequested(mTypeId, mid, peer) { _ => Cancellable.alreadyCancelled}
+ val infoFields =
+ Seq(
+ "address" -> peer.connectionId.remoteAddress.toString.asJson,
+ "checks" -> 0.asJson
+ ) ++ peer.peerInfo.map(_.peerSpec.protocolVersion.toString.asJson).map("version" -> _)
+ tracker.fullInfo.asJson shouldBe Json.obj(
+ "invalidModifierApproxSize" -> 0.asJson,
+ "requested" -> Json.obj(
+ "104" -> Json.obj(
+ "foo" -> Json.obj(infoFields:_*)
+ )
+ ),
+ "received" -> Json.obj()
+ )
+
+ tracker.setReceived(mid, mTypeId, peer)
+ val infoFields2 =
+ Seq(
+ "address" -> peer.connectionId.remoteAddress.toString.asJson
+ ) ++ peer.peerInfo.map(_.peerSpec.protocolVersion.toString.asJson).map("version" -> _)
+
+ tracker.fullInfo.asJson shouldBe Json.obj(
+ "invalidModifierApproxSize" -> 0.asJson,
+ "requested" -> Json.obj(
+ "104" -> Json.obj(),
+ ),
+ "received" -> Json.obj(
+ "104" -> Json.obj(
+ "foo" -> Json.obj(infoFields2:_*)
+ ),
+ )
+ )
+ tracker.clearStatusForModifier(mid, mTypeId, Received)
+ tracker.fullInfo.asJson shouldBe Json.obj(
+ "invalidModifierApproxSize" -> 0.asJson,
+ "requested" -> Json.obj(
+ "104" -> Json.obj(),
+ ),
+ "received" -> Json.obj(
+ "104" -> Json.obj()
+ )
+ )
+
+ tracker.reset()
+ val fullInfoAfterReset = tracker.fullInfo
+ fullInfoAfterReset.invalidModifierApproxSize shouldBe 0
+ fullInfoAfterReset.requested.size shouldBe 0
+ fullInfoAfterReset.received.size shouldBe 0
+ }
+ }
+
+}
diff --git a/src/test/scala/org/ergoplatform/network/ErgoNodeViewSynchronizerSpecification.scala b/src/test/scala/org/ergoplatform/network/ErgoNodeViewSynchronizerSpecification.scala
index 2430aa7728..7b2c64cf4c 100644
--- a/src/test/scala/org/ergoplatform/network/ErgoNodeViewSynchronizerSpecification.scala
+++ b/src/test/scala/org/ergoplatform/network/ErgoNodeViewSynchronizerSpecification.scala
@@ -2,29 +2,29 @@ package org.ergoplatform.network
import akka.actor.{ActorRef, ActorSystem, Cancellable, Props}
import akka.testkit.TestProbe
+import org.ergoplatform.PersistentNodeViewModifier
import org.ergoplatform.modifiers.history.header.{Header, HeaderSerializer}
import org.ergoplatform.modifiers.{BlockSection, ErgoFullBlock}
-import org.ergoplatform.network.ErgoNodeViewSynchronizer.ReceivableMessages._
+import org.ergoplatform.network.ErgoNodeViewSynchronizerMessages._
import org.ergoplatform.nodeView.ErgoNodeViewHolder
import org.ergoplatform.nodeView.history.{ErgoHistory, ErgoHistoryReader, ErgoSyncInfoMessageSpec, ErgoSyncInfoV2}
import org.ergoplatform.nodeView.mempool.ErgoMemPool
import org.ergoplatform.nodeView.state.wrapped.WrappedUtxoState
import org.ergoplatform.nodeView.state.{StateType, UtxoState}
import org.ergoplatform.sanity.ErgoSanity._
-import org.ergoplatform.settings.ErgoSettings
+import org.ergoplatform.settings.{ErgoSettings, ErgoSettingsReader}
import org.ergoplatform.utils.HistoryTestHelpers
import org.ergoplatform.wallet.utils.FileUtils
import org.scalacheck.Gen
import org.scalatest.concurrent.Eventually
import org.scalatest.matchers.should.Matchers
-import scorex.core.PersistentNodeViewModifier
import scorex.core.network.ModifiersStatus.{Received, Unknown}
import scorex.core.network.NetworkController.ReceivableMessages.SendToNetwork
-import scorex.core.network.message._
-import scorex.core.network.peer.PeerInfo
+import org.ergoplatform.network.message._
+import org.ergoplatform.network.peer.PeerInfo
import scorex.core.network.{ConnectedPeer, DeliveryTracker}
-import scorex.core.serialization.ErgoSerializer
-import scorex.testkit.utils.AkkaFixture
+import org.ergoplatform.serialization.ErgoSerializer
+import org.ergoplatform.testkit.utils.AkkaFixture
import scala.concurrent.duration.{Duration, _}
import scala.concurrent.{Await, ExecutionContext, ExecutionContextExecutor}
@@ -126,7 +126,7 @@ class ErgoNodeViewSynchronizerSpecification extends HistoryTestHelpers with Matc
val h = localHistoryGen.sample.get
@SuppressWarnings(Array("org.wartremover.warts.OptionPartial"))
val s = localStateGen.sample.get
- val settings = ErgoSettings.read()
+ val settings = ErgoSettingsReader.read()
val pool = ErgoMemPool.empty(settings)
implicit val ec: ExecutionContextExecutor = system.dispatcher
val ncProbe = TestProbe("NetworkControllerProbe")
diff --git a/src/test/scala/org/ergoplatform/network/ErgoSyncInfoSpecification.scala b/src/test/scala/org/ergoplatform/network/ErgoSyncInfoSpecification.scala
index 3768260d27..b331e3e51a 100644
--- a/src/test/scala/org/ergoplatform/network/ErgoSyncInfoSpecification.scala
+++ b/src/test/scala/org/ergoplatform/network/ErgoSyncInfoSpecification.scala
@@ -5,7 +5,7 @@ import java.nio.ByteBuffer
import com.google.common.primitives.Ints
import org.ergoplatform.nodeView.history.{ErgoSyncInfoMessageSpec, ErgoSyncInfoV1}
import org.ergoplatform.utils.ErgoPropertyTest
-import scorex.core.network.message.{Message, MessageSerializer}
+import org.ergoplatform.network.message.{Message, MessageSerializer}
import scorex.crypto.hash
import scorex.util.ModifierId
import scorex.util.encode.Base16
diff --git a/src/test/scala/org/ergoplatform/network/ErgoSyncTrackerSpecification.scala b/src/test/scala/org/ergoplatform/network/ErgoSyncTrackerSpecification.scala
index b96081117e..0da8eeefda 100644
--- a/src/test/scala/org/ergoplatform/network/ErgoSyncTrackerSpecification.scala
+++ b/src/test/scala/org/ergoplatform/network/ErgoSyncTrackerSpecification.scala
@@ -1,9 +1,9 @@
package org.ergoplatform.network
+import org.ergoplatform.consensus.{Older, Younger}
import org.ergoplatform.utils.ErgoPropertyTest
-import scorex.core.consensus.{Older, Younger}
import scorex.core.network.{ConnectedPeer, ConnectionId, Incoming}
-import scorex.core.network.peer.PeerInfo
+import org.ergoplatform.network.peer.PeerInfo
class ErgoSyncTrackerSpecification extends ErgoPropertyTest {
property("getters test") {
diff --git a/src/test/scala/org/ergoplatform/network/HandshakeSpecification.scala b/src/test/scala/org/ergoplatform/network/HandshakeSpecification.scala
index b00ec2867d..44f71edebb 100644
--- a/src/test/scala/org/ergoplatform/network/HandshakeSpecification.scala
+++ b/src/test/scala/org/ergoplatform/network/HandshakeSpecification.scala
@@ -1,11 +1,9 @@
package org.ergoplatform.network
import java.nio.ByteBuffer
-
import org.ergoplatform.nodeView.state.StateType
import org.ergoplatform.utils.ErgoPropertyTest
-import scorex.core.app.Version
-import scorex.core.network.message.HandshakeSerializer
+import org.ergoplatform.network.message.HandshakeSerializer
import scorex.util.encode.Base16
class HandshakeSpecification extends ErgoPropertyTest with DecodingUtils {
diff --git a/src/test/scala/org/ergoplatform/network/InvSpecification.scala b/src/test/scala/org/ergoplatform/network/InvSpecification.scala
index 7c756ec079..e3d0bb41cb 100644
--- a/src/test/scala/org/ergoplatform/network/InvSpecification.scala
+++ b/src/test/scala/org/ergoplatform/network/InvSpecification.scala
@@ -5,7 +5,7 @@ import java.nio.ByteBuffer
import com.google.common.primitives.Ints
import org.ergoplatform.modifiers.history.header.Header
import org.ergoplatform.utils.ErgoPropertyTest
-import scorex.core.network.message.{InvData, InvSpec, Message, MessageSerializer}
+import org.ergoplatform.network.message.{InvData, InvSpec, Message, MessageSerializer}
import scorex.crypto.hash
import scorex.util.ModifierId
import scorex.util.encode.Base16
diff --git a/src/test/scala/org/ergoplatform/network/ModifiersSpecification.scala b/src/test/scala/org/ergoplatform/network/ModifiersSpecification.scala
index bc8e8d876f..d8dc4cd7d5 100644
--- a/src/test/scala/org/ergoplatform/network/ModifiersSpecification.scala
+++ b/src/test/scala/org/ergoplatform/network/ModifiersSpecification.scala
@@ -5,7 +5,7 @@ import java.nio.ByteBuffer
import com.google.common.primitives.Ints
import org.ergoplatform.modifiers.history.header.{Header, HeaderSerializer}
import org.ergoplatform.utils.ErgoPropertyTest
-import scorex.core.network.message.{Message, MessageSerializer, ModifiersData, ModifiersSpec}
+import org.ergoplatform.network.message.{Message, MessageSerializer, ModifiersData, ModifiersSpec}
import scorex.util.encode.Base16
/**
diff --git a/src/test/scala/org/ergoplatform/network/PeerFilteringRuleSpecification.scala b/src/test/scala/org/ergoplatform/network/PeerFilteringRuleSpecification.scala
index cd7ee1e71e..c2352f58ff 100644
--- a/src/test/scala/org/ergoplatform/network/PeerFilteringRuleSpecification.scala
+++ b/src/test/scala/org/ergoplatform/network/PeerFilteringRuleSpecification.scala
@@ -2,9 +2,7 @@ package org.ergoplatform.network
import akka.actor.ActorRef
import org.ergoplatform.utils.ErgoPropertyTest
-import scorex.core.app.Version
-import scorex.core.network.PeerSpec
-import scorex.core.network.peer.PeerInfo
+import org.ergoplatform.network.peer.PeerInfo
import scorex.core.network.{ConnectedPeer, ConnectionId}
class PeerFilteringRuleSpecification extends ErgoPropertyTest {
diff --git a/src/test/scala/org/ergoplatform/network/PeerSpecSerializerSpec.scala b/src/test/scala/org/ergoplatform/network/PeerSpecSerializerSpec.scala
new file mode 100644
index 0000000000..f343fd2ec0
--- /dev/null
+++ b/src/test/scala/org/ergoplatform/network/PeerSpecSerializerSpec.scala
@@ -0,0 +1,21 @@
+package org.ergoplatform.network
+
+import org.ergoplatform.testkit.generators.ObjectGenerators
+import org.ergoplatform.utils.ErgoPropertyTest
+import scorex.util.ByteArrayBuilder
+import scorex.util.serialization.{VLQByteBufferReader, VLQByteBufferWriter}
+
+import java.nio.ByteBuffer
+
+class PeerSpecSerializerSpec extends ErgoPropertyTest with ObjectGenerators {
+
+ property("All variants of peer spec should be serialized and deserialized successfully") {
+ forAll(peerSpecGen) { peerSpec =>
+ val writer = new VLQByteBufferWriter(new ByteArrayBuilder())
+ PeerSpecSerializer.serialize(peerSpec, writer)
+ val reader = new VLQByteBufferReader(ByteBuffer.wrap(writer.result().toBytes))
+ val actualPeerSpec = PeerSpecSerializer.parse(reader)
+ peerSpec shouldBe actualPeerSpec
+ }
+ }
+}
diff --git a/src/test/scala/org/ergoplatform/network/RequestModifiersSpecification.scala b/src/test/scala/org/ergoplatform/network/RequestModifiersSpecification.scala
index 7489c43871..03b2a842aa 100644
--- a/src/test/scala/org/ergoplatform/network/RequestModifiersSpecification.scala
+++ b/src/test/scala/org/ergoplatform/network/RequestModifiersSpecification.scala
@@ -5,7 +5,7 @@ import java.nio.ByteBuffer
import com.google.common.primitives.Ints
import org.ergoplatform.modifiers.history.header.Header
import org.ergoplatform.utils.ErgoPropertyTest
-import scorex.core.network.message.{InvData, Message, MessageSerializer, RequestModifierSpec}
+import org.ergoplatform.network.message.{InvData, Message, MessageSerializer, RequestModifierSpec}
import scorex.crypto.hash
import scorex.util.ModifierId
import scorex.util.encode.Base16
diff --git a/src/test/scala/org/ergoplatform/nodeView/ErgoModifiersCacheSpec.scala b/src/test/scala/org/ergoplatform/nodeView/ErgoModifiersCacheSpec.scala
index 29e67176bd..d84ac8be04 100644
--- a/src/test/scala/org/ergoplatform/nodeView/ErgoModifiersCacheSpec.scala
+++ b/src/test/scala/org/ergoplatform/nodeView/ErgoModifiersCacheSpec.scala
@@ -2,7 +2,7 @@ package org.ergoplatform.nodeView
import org.ergoplatform.modifiers.history.header.Header
import org.ergoplatform.modifiers.history.{ADProofs, BlockTransactions}
-import org.ergoplatform.nodeView.history.ErgoHistory
+import org.ergoplatform.nodeView.history.ErgoHistoryUtils._
import org.ergoplatform.nodeView.state.StateType
import org.ergoplatform.utils.{ErgoPropertyTest, HistoryTestHelpers}
import scorex.crypto.hash.Blake2b256
@@ -64,7 +64,7 @@ class ErgoModifiersCacheSpec extends ErgoPropertyTest with HistoryTestHelpers {
val c1 = modifiersCache.popCandidate(history0).value
c1.isInstanceOf[Header] shouldBe true
val h1 = c1.asInstanceOf[Header]
- h1.height shouldBe ErgoHistory.GenesisHeight
+ h1.height shouldBe GenesisHeight
val history1 = history0.append(c1).get._1
diff --git a/src/test/scala/org/ergoplatform/nodeView/NodeViewSynchronizerTests.scala b/src/test/scala/org/ergoplatform/nodeView/NodeViewSynchronizerTests.scala
index 9311d13c78..1c383c2dd5 100644
--- a/src/test/scala/org/ergoplatform/nodeView/NodeViewSynchronizerTests.scala
+++ b/src/test/scala/org/ergoplatform/nodeView/NodeViewSynchronizerTests.scala
@@ -2,10 +2,12 @@ package org.ergoplatform.nodeView
import akka.actor.{ActorRef, ActorSystem}
import akka.testkit.TestProbe
+import org.ergoplatform.consensus.SyncInfo
+import org.ergoplatform.core.BytesSerializable
import org.ergoplatform.modifiers.BlockSection
import org.ergoplatform.modifiers.history.header.Header
import org.ergoplatform.modifiers.mempool.{ErgoTransaction, UnconfirmedTransaction}
-import org.ergoplatform.network.ErgoNodeViewSynchronizer.ReceivableMessages._
+import org.ergoplatform.network.ErgoNodeViewSynchronizerMessages._
import org.ergoplatform.nodeView.ErgoNodeViewHolder.ReceivableMessages.{GetNodeViewChanges, ModifiersFromRemote}
import org.ergoplatform.nodeView.history.{ErgoHistory, ErgoSyncInfo, ErgoSyncInfoMessageSpec}
import org.ergoplatform.nodeView.mempool.ErgoMemPool
@@ -16,15 +18,14 @@ import org.ergoplatform.wallet.utils.TestFileUtils
import org.scalacheck.Gen
import org.scalatest.matchers.should.Matchers
import org.scalatest.propspec.AnyPropSpec
-import scorex.core.consensus.SyncInfo
import scorex.core.network.ConnectedPeer
import scorex.core.network.NetworkController.ReceivableMessages.{PenalizePeer, SendToNetwork}
-import scorex.core.network.message._
-import scorex.core.network.peer.PenaltyType
-import scorex.core.serialization.{BytesSerializable, ErgoSerializer, ManifestSerializer}
+import org.ergoplatform.network.message._
+import org.ergoplatform.network.peer.PenaltyType
+import org.ergoplatform.serialization.{ErgoSerializer, ManifestSerializer}
+import org.ergoplatform.testkit.generators.{SyntacticallyTargetedModifierProducer, TotallyValidModifierProducer}
+import org.ergoplatform.testkit.utils.AkkaFixture
import scorex.crypto.hash.Digest32
-import scorex.testkit.generators.{SyntacticallyTargetedModifierProducer, TotallyValidModifierProducer}
-import scorex.testkit.utils.AkkaFixture
import scorex.util.ScorexLogging
import scorex.util.serialization.{Reader, Writer}
import org.ergoplatform.utils.generators.ChainGenerator
diff --git a/src/test/scala/org/ergoplatform/nodeView/history/BlockSectionValidationSpecification.scala b/src/test/scala/org/ergoplatform/nodeView/history/BlockSectionValidationSpecification.scala
index 40feb58cef..fca3d13d93 100644
--- a/src/test/scala/org/ergoplatform/nodeView/history/BlockSectionValidationSpecification.scala
+++ b/src/test/scala/org/ergoplatform/nodeView/history/BlockSectionValidationSpecification.scala
@@ -1,12 +1,13 @@
package org.ergoplatform.nodeView.history
+import org.ergoplatform.consensus.ModifierSemanticValidity
import org.ergoplatform.modifiers.{BlockSection, NonHeaderBlockSection}
import org.ergoplatform.modifiers.history._
import org.ergoplatform.modifiers.history.extension.Extension
import org.ergoplatform.modifiers.history.header.Header
import org.ergoplatform.nodeView.state.StateType
+import org.ergoplatform.nodeView.history.ErgoHistoryUtils._
import org.ergoplatform.utils.HistoryTestHelpers
-import scorex.core.consensus.ModifierSemanticValidity
import scorex.crypto.hash.Blake2b256
import scorex.util.ModifierId
import scorex.util.encode.Base16
@@ -75,7 +76,7 @@ class BlockSectionValidationSpecification extends HistoryTestHelpers {
history.writeMinimalFullBlockHeight(history.bestHeaderOpt.get.height + 1)
history.isHeadersChainSyncedVar = true
history.applicableTry(section) shouldBe 'failure
- history.writeMinimalFullBlockHeight(ErgoHistory.GenesisHeight)
+ history.writeMinimalFullBlockHeight(GenesisHeight)
// should not be able to apply if corresponding header is marked as invalid
history.applicableTry(section) shouldBe 'success
diff --git a/src/test/scala/org/ergoplatform/nodeView/history/NonVerifyADHistorySpecification.scala b/src/test/scala/org/ergoplatform/nodeView/history/NonVerifyADHistorySpecification.scala
index b2cbb964ca..5001a9ddc1 100644
--- a/src/test/scala/org/ergoplatform/nodeView/history/NonVerifyADHistorySpecification.scala
+++ b/src/test/scala/org/ergoplatform/nodeView/history/NonVerifyADHistorySpecification.scala
@@ -1,15 +1,16 @@
package org.ergoplatform.nodeView.history
+import org.ergoplatform.consensus.{Equal, Fork, Older, Younger}
import org.ergoplatform.mining.difficulty.DifficultySerializer
import org.ergoplatform.modifiers.history.extension.Extension
import org.ergoplatform.modifiers.history.header.Header
import org.ergoplatform.modifiers.history.popow.NipopowAlgos
import org.ergoplatform.modifiers.history.HeaderChain
import org.ergoplatform.nodeView.state.StateType
+import org.ergoplatform.nodeView.history.ErgoHistoryUtils._
import org.ergoplatform.settings.Algos
import org.ergoplatform.utils.HistoryTestHelpers
import scorex.crypto.hash.Digest32
-import scorex.core.consensus.{Older, Younger, Fork, Equal}
import scala.util.Random
@@ -268,7 +269,7 @@ class NonVerifyADHistorySpecification extends HistoryTestHelpers {
val chain = genHeaderChain(BlocksInChain, history, diffBitsOpt = None, useRealTs = false)
chain.headers.foreach { header =>
- val inHeight = history.heightOf(header.parentId).getOrElse(ErgoHistory.EmptyHistoryHeight)
+ val inHeight = history.heightOf(header.parentId).getOrElse(EmptyHistoryHeight)
history.contains(header) shouldBe false
history.applicable(header) shouldBe true
diff --git a/src/test/scala/org/ergoplatform/nodeView/history/UtxoSetSnapshotProcessorSpecification.scala b/src/test/scala/org/ergoplatform/nodeView/history/UtxoSetSnapshotProcessorSpecification.scala
index 3903251054..def8600a21 100644
--- a/src/test/scala/org/ergoplatform/nodeView/history/UtxoSetSnapshotProcessorSpecification.scala
+++ b/src/test/scala/org/ergoplatform/nodeView/history/UtxoSetSnapshotProcessorSpecification.scala
@@ -1,12 +1,13 @@
package org.ergoplatform.nodeView.history
import org.ergoplatform.nodeView.history.storage.HistoryStorage
+import org.ergoplatform.nodeView.history.ErgoHistoryUtils._
import org.ergoplatform.nodeView.history.storage.modifierprocessors.UtxoSetSnapshotProcessor
import org.ergoplatform.nodeView.state.{StateType, UtxoState}
import org.ergoplatform.settings.{Algos, ErgoSettings}
import org.ergoplatform.utils.HistoryTestHelpers
-import scorex.core.VersionTag
-import scorex.core.serialization.{ManifestSerializer, SubtreeSerializer}
+import org.ergoplatform.core.VersionTag
+import org.ergoplatform.serialization.{ManifestSerializer, SubtreeSerializer}
import scorex.db.LDBVersionedStore
import scorex.util.ModifierId
@@ -19,7 +20,7 @@ class UtxoSetSnapshotProcessorSpecification extends HistoryTestHelpers {
val epochLength = 20
val utxoSetSnapshotProcessor = new UtxoSetSnapshotProcessor {
- var minimalFullBlockHeightVar = ErgoHistory.GenesisHeight
+ var minimalFullBlockHeightVar = GenesisHeight
override protected val settings: ErgoSettings = s.copy(chainSettings =
s.chainSettings.copy(voting = s.chainSettings.voting.copy(votingLength = epochLength)))
override protected val historyStorage: HistoryStorage = HistoryStorage(settings)
diff --git a/src/test/scala/org/ergoplatform/nodeView/history/VerifyADHistorySpecification.scala b/src/test/scala/org/ergoplatform/nodeView/history/VerifyADHistorySpecification.scala
index 0240d00afb..c5c8240ec7 100644
--- a/src/test/scala/org/ergoplatform/nodeView/history/VerifyADHistorySpecification.scala
+++ b/src/test/scala/org/ergoplatform/nodeView/history/VerifyADHistorySpecification.scala
@@ -1,16 +1,16 @@
package org.ergoplatform.nodeView.history
+import org.ergoplatform.consensus.ProgressInfo
import org.ergoplatform.modifiers.history.extension.Extension
import org.ergoplatform.modifiers.history.HeaderChain
import org.ergoplatform.modifiers.history.header.Header
+import org.ergoplatform.nodeView.history.ErgoHistoryUtils._
import org.ergoplatform.modifiers.{ErgoFullBlock, BlockSection}
import org.ergoplatform.nodeView.ErgoModifiersCache
import org.ergoplatform.nodeView.state.StateType
+import org.ergoplatform.testkit.utils.NoShrink
import org.ergoplatform.utils.HistoryTestHelpers
-import scorex.core.consensus.ProgressInfo
-import scorex.core.consensus.ModifierSemanticValidity.{Absent, Invalid, Unknown, Valid}
-import scorex.testkit.utils.NoShrink
-
+import org.ergoplatform.consensus.ModifierSemanticValidity._
import scala.collection.mutable.ArrayBuffer
import scala.util.Random
@@ -19,7 +19,7 @@ class VerifyADHistorySpecification extends HistoryTestHelpers with NoShrink {
type PM = BlockSection
private def genHistory(blocksNum: Int = 0,
- minFullHeight: Option[Int] = Some(ErgoHistory.GenesisHeight)): (ErgoHistory, Seq[ErgoFullBlock]) = {
+ minFullHeight: Option[Int] = Some(GenesisHeight)): (ErgoHistory, Seq[ErgoFullBlock]) = {
val inHistory = generateHistory(verifyTransactions = true, StateType.Digest, PoPoWBootstrap = false, BlocksToKeep)
minFullHeight.foreach { h =>
inHistory.writeMinimalFullBlockHeight(h)
diff --git a/src/test/scala/org/ergoplatform/nodeView/history/VerifyNonADHistorySpecification.scala b/src/test/scala/org/ergoplatform/nodeView/history/VerifyNonADHistorySpecification.scala
index cb024dd9bb..99e8786850 100644
--- a/src/test/scala/org/ergoplatform/nodeView/history/VerifyNonADHistorySpecification.scala
+++ b/src/test/scala/org/ergoplatform/nodeView/history/VerifyNonADHistorySpecification.scala
@@ -1,5 +1,6 @@
package org.ergoplatform.nodeView.history
+import org.ergoplatform.consensus.ProgressInfo
import org.ergoplatform.modifiers.{ErgoFullBlock, NetworkObjectTypeId}
import org.ergoplatform.modifiers.history._
import org.ergoplatform.modifiers.history.extension.Extension
@@ -8,10 +9,9 @@ import org.ergoplatform.nodeView.history.storage.modifierprocessors.FullBlockPro
import org.ergoplatform.nodeView.state.StateType
import org.ergoplatform.settings.Algos
import org.ergoplatform.utils.HistoryTestHelpers
-import scorex.core.consensus.ProgressInfo
class VerifyNonADHistorySpecification extends HistoryTestHelpers {
- import scorex.core.utils.MapPimp
+ import org.ergoplatform.utils.MapPimp
private def genHistory() =
generateHistory(verifyTransactions = true, StateType.Utxo, PoPoWBootstrap = false, BlocksToKeep)
diff --git a/src/test/scala/org/ergoplatform/nodeView/history/extra/ChainGenerator.scala b/src/test/scala/org/ergoplatform/nodeView/history/extra/ChainGenerator.scala
new file mode 100644
index 0000000000..144305ab33
--- /dev/null
+++ b/src/test/scala/org/ergoplatform/nodeView/history/extra/ChainGenerator.scala
@@ -0,0 +1,208 @@
+package org.ergoplatform.nodeView.history.extra
+
+import org.ergoplatform.ErgoBox.TokenId
+import org.ergoplatform.ErgoLikeContext.Height
+import org.ergoplatform.mining.difficulty.DifficultySerializer
+import org.ergoplatform.mining.{AutolykosPowScheme, CandidateBlock, CandidateGenerator}
+import org.ergoplatform.modifiers.ErgoFullBlock
+import org.ergoplatform.modifiers.history.extension.{Extension, ExtensionCandidate}
+import org.ergoplatform.modifiers.history.header.Header
+import org.ergoplatform.modifiers.history.popow.NipopowAlgos
+import org.ergoplatform.modifiers.mempool.{ErgoTransaction, UnsignedErgoTransaction}
+import org.ergoplatform.nodeView.history.ErgoHistory
+import org.ergoplatform.nodeView.history.ErgoHistoryUtils.GenesisHeight
+import org.ergoplatform.nodeView.state.{ErgoState, ErgoStateContext, UtxoState, UtxoStateReader}
+import org.ergoplatform.utils.ErgoTestHelpers
+import org.ergoplatform._
+import scorex.util.ModifierId
+import sigma.{Coll, Colls}
+import sigmastate.Values
+import sigmastate.crypto.DLogProtocol.ProveDlog
+import sigmastate.eval.Extensions._
+import sigmastate.eval._
+
+import java.io.File
+import scala.annotation.tailrec
+import scala.collection.mutable.ArrayBuffer
+import scala.concurrent.duration.{DurationInt, FiniteDuration}
+import scala.util.{Random, Try}
+
+object ChainGenerator extends ErgoTestHelpers {
+
+ val pow: AutolykosPowScheme = new AutolykosPowScheme(powScheme.k, powScheme.n)
+ val blockInterval: FiniteDuration = 2.minute
+ val EmissionTxCost: Long = 20000
+ val MinTxAmount: Long = 2000000
+ val RewardDelay: Int = initSettings.chainSettings.monetary.minerRewardDelay
+ val MaxTxsPerBlock: Int = 10
+ val minerPk: ProveDlog = defaultProver.hdKeys.head.publicImage
+ val selfAddressScript: Values.ErgoTree = P2PKAddress(minerPk).script
+ val minerProp: Values.ErgoTree = ErgoTreePredef.rewardOutputScript(RewardDelay, minerPk)
+ val votingEpochLength: Height = votingSettings.votingLength
+ val protocolVersion: Byte = initSettings.chainSettings.protocolVersion
+ val minimalSuffix = 2
+ val txCostLimit: Height = initSettings.nodeSettings.maxTransactionCost
+ val txSizeLimit: Height = initSettings.nodeSettings.maxTransactionSize
+
+ var startTime: Long = 0
+
+ def generate(length: Int, dir: File)(history: ErgoHistory): Unit = {
+ val stateDir = new File(s"${dir.getAbsolutePath}/state")
+ stateDir.mkdirs()
+ val (state, _) = ErgoState.generateGenesisUtxoState(stateDir, initSettings)
+ System.out.println(s"Going to generate a chain at ${dir.getAbsolutePath} starting from ${history.bestFullBlockOpt}")
+ startTime = System.currentTimeMillis() - (blockInterval * (length - 1)).toMillis
+ val chain = loop(state, None, None, Seq())(history)
+ System.out.println(s"Chain of length ${chain.length} generated")
+ history.bestHeaderOpt shouldBe history.bestFullBlockOpt.map(_.header)
+ history.bestFullBlockOpt.get.id shouldBe chain.last
+ System.out.println("History was generated successfully")
+ }
+
+ @tailrec
+ private def loop(state: UtxoState,
+ initBox: Option[ErgoBox],
+ last: Option[Header],
+ acc: Seq[ModifierId])(history: ErgoHistory): Seq[ModifierId] = {
+ val time: Long = last.map(_.timestamp + blockInterval.toMillis).getOrElse(startTime)
+ if (time < System.currentTimeMillis()) {
+ val (txs, lastOut) = genTransactions(last.map(_.height).getOrElse(GenesisHeight),
+ initBox, state.stateContext)
+
+ val candidate = genCandidate(defaultProver.hdPubKeys.head.key, last, time, txs, state)(history)
+ val block = proveCandidate(candidate.get)
+
+ history.append(block.header).get
+ block.blockSections.foreach(s => if (!history.contains(s)) history.append(s).get)
+
+ val outToPassNext = if (last.isEmpty) {
+ block.transactions.flatMap(_.outputs).find(_.ergoTree == minerProp)
+ } else {
+ lastOut
+ }
+
+ assert(outToPassNext.isDefined)
+
+ log.info(
+ s"Block ${block.id} with ${block.transactions.size} transactions at height ${block.header.height} generated")
+
+ loop(state.applyModifier(block, None)(_ => ()).get, outToPassNext, Some(block.header), acc :+ block.id)(history)
+ } else {
+ acc
+ }
+ }
+
+ private def moveTokens(inOpt: Option[ErgoBox], cond: Boolean): Coll[(TokenId, Long)] = {
+ val tokens: ArrayBuffer[(TokenId, Long)] = ArrayBuffer.empty[(TokenId, Long)]
+ inOpt match {
+ case Some(input) if cond =>
+ tokens += Tuple2(input.id.toTokenId, math.abs(Random.nextInt()))
+ case Some(tokenBox) if !cond =>
+ tokenBox.additionalTokens.toArray.foreach(tokens += _)
+ case _ =>
+ }
+ Colls.fromArray(tokens.toArray)
+ }
+
+ private def genTransactions(height: Height,
+ inOpt: Option[ErgoBox],
+ ctx: ErgoStateContext): (Seq[ErgoTransaction], Option[ErgoBox]) = {
+ inOpt
+ .find { bx =>
+ val canUnlock = (bx.creationHeight + RewardDelay <= height) || (bx.ergoTree != minerProp)
+ canUnlock && bx.ergoTree != initSettings.chainSettings.monetary.emissionBoxProposition && bx.value >= MinTxAmount
+ }
+ .map { input =>
+ val qty = MaxTxsPerBlock
+ val amount = input.value
+ val outs = (0 until qty).map(i => new ErgoBoxCandidate(amount, selfAddressScript, height, moveTokens(inOpt, i == 0)))
+ var i = 0
+ val x = outs
+ .foldLeft((Seq.empty[ErgoTransaction], input)) { case ((acc, in), out) =>
+ val inputs = IndexedSeq(in)
+ val newOut =
+ if (i > 0)
+ new ErgoBoxCandidate(amount, selfAddressScript, height, moveTokens(acc.lastOption.map(_.outputs.head), cond = false))
+ else
+ out
+ val unsignedTx = UnsignedErgoTransaction(inputs.map(box => new UnsignedInput(box.id)), IndexedSeq(newOut))
+ i += 1
+ defaultProver.sign(unsignedTx, inputs, emptyDataBoxes, ctx)
+ .fold(_ => acc -> in, tx => (acc :+ ErgoTransaction(tx)) -> unsignedTx.outputs.head)
+ }
+ ._1
+ (x, Some(x.last.outputs.head))
+ }
+ .getOrElse(Seq.empty -> inOpt)
+ }
+
+ private def genCandidate(minerPk: ProveDlog,
+ lastHeaderOpt: Option[Header],
+ ts: Long,
+ txsFromPool: Seq[ErgoTransaction],
+ state: UtxoStateReader)(history: ErgoHistory): Try[CandidateBlock] = Try {
+ val stateContext = state.stateContext
+ val nBits: Long = lastHeaderOpt
+ .map(parent => history.requiredDifficultyAfter(parent))
+ .map(d => DifficultySerializer.encodeCompactBits(d))
+ .getOrElse(settings.chainSettings.initialNBits)
+
+ val interlinks = lastHeaderOpt
+ .flatMap { h =>
+ history.typedModifierById[Extension](h.extensionId)
+ .flatMap(ext => NipopowAlgos.unpackInterlinks(ext.fields).toOption)
+ .map(nipopowAlgos.updateInterlinks(h, _))
+ }
+ .getOrElse(Seq.empty)
+ val interlinksExtension = nipopowAlgos.interlinksToExtension(interlinks)
+
+ val (extensionCandidate, votes: Array[Byte], version: Byte) = lastHeaderOpt.map { header =>
+ val newHeight = header.height + 1
+ val currentParams = stateContext.currentParameters
+ val betterVersion = protocolVersion > header.version
+ val votingFinishHeight: Option[Height] = currentParams.softForkStartingHeight
+ .map(_ + votingSettings.votingLength * votingSettings.softForkEpochs)
+ val forkVotingAllowed = votingFinishHeight.forall(fh => newHeight < fh)
+ val forkOrdered = settings.votingTargets.softFork != 0
+ val voteForFork = betterVersion && forkOrdered && forkVotingAllowed
+
+ if (newHeight % votingEpochLength == 0 && newHeight > 0) {
+ val (newParams, _) = currentParams.update(newHeight, voteForFork, stateContext.votingData.epochVotes, emptyVSUpdate, votingSettings)
+ (newParams.toExtensionCandidate ++ interlinksExtension,
+ newParams.suggestVotes(settings.votingTargets.targets, voteForFork),
+ newParams.blockVersion)
+ } else {
+ (nipopowAlgos.interlinksToExtension(interlinks),
+ currentParams.vote(settings.votingTargets.targets, stateContext.votingData.epochVotes, voteForFork),
+ currentParams.blockVersion)
+ }
+ }.getOrElse((interlinksExtension, Array(0: Byte, 0: Byte, 0: Byte), Header.InitialVersion))
+
+ val emissionTxOpt = CandidateGenerator.collectEmission(state, minerPk, emptyStateContext)
+ val txs = emissionTxOpt.toSeq ++ txsFromPool
+
+ state.proofsForTransactions(txs).map { case (adProof, adDigest) =>
+ CandidateBlock(lastHeaderOpt, version, nBits, adDigest, adProof, txs, ts, extensionCandidate, votes)
+ }
+ }.flatten
+
+ @tailrec
+ private def proveCandidate(candidate: CandidateBlock): ErgoFullBlock = {
+ log.info(s"Trying to prove block with parent ${candidate.parentOpt.map(_.encodedId)} and timestamp ${candidate.timestamp}")
+
+ pow.proveCandidate(candidate, defaultProver.hdKeys.head.privateInput.w) match {
+ case Some(fb) => fb
+ case _ =>
+ val interlinks = candidate.parentOpt
+ .map(nipopowAlgos.updateInterlinks(_, NipopowAlgos.unpackInterlinks(candidate.extension.fields).get))
+ .getOrElse(Seq.empty)
+ val minerTag = scorex.utils.Random.randomBytes(Extension.FieldKeySize)
+ proveCandidate {
+ candidate.copy(
+ extension = ExtensionCandidate(Seq(Array(0: Byte, 2: Byte) -> minerTag)) ++ nipopowAlgos.interlinksToExtension(interlinks)
+ )
+ }
+ }
+ }
+
+}
diff --git a/src/test/scala/org/ergoplatform/nodeView/history/extra/ExtraIndexerSpecification.scala b/src/test/scala/org/ergoplatform/nodeView/history/extra/ExtraIndexerSpecification.scala
index a377e8a2e7..b18e2e7536 100644
--- a/src/test/scala/org/ergoplatform/nodeView/history/extra/ExtraIndexerSpecification.scala
+++ b/src/test/scala/org/ergoplatform/nodeView/history/extra/ExtraIndexerSpecification.scala
@@ -1,80 +1,33 @@
package org.ergoplatform.nodeView.history.extra
-import org.ergoplatform.ErgoBox.TokenId
-import org.ergoplatform.ErgoLikeContext.Height
-import org.ergoplatform._
-import org.ergoplatform.mining.difficulty.DifficultySerializer
-import org.ergoplatform.mining.{AutolykosPowScheme, CandidateBlock, CandidateGenerator}
-import org.ergoplatform.modifiers.ErgoFullBlock
-import org.ergoplatform.modifiers.history.extension.{Extension, ExtensionCandidate}
-import org.ergoplatform.modifiers.history.header.Header
-import org.ergoplatform.modifiers.history.popow.NipopowAlgos
-import org.ergoplatform.modifiers.mempool.{ErgoTransaction, UnsignedErgoTransaction}
-import org.ergoplatform.nodeView.history.ErgoHistory
+import akka.actor.{ActorRef, ActorSystem, Props}
+import org.ergoplatform.network.ErgoNodeViewSynchronizerMessages.{FullBlockApplied, Rollback}
+import org.ergoplatform.nodeView.history.extra.ExtraIndexer.ReceivableMessages.Index
import org.ergoplatform.nodeView.history.extra.IndexedErgoAddressSerializer.hashErgoTree
import org.ergoplatform.nodeView.history.extra.SegmentSerializer.{boxSegmentId, txSegmentId}
-import org.ergoplatform.nodeView.mempool.ErgoMemPool.SortingOption
-import org.ergoplatform.nodeView.state._
-import org.ergoplatform.settings.{ErgoSettings, NetworkType, NipopowSettings, NodeConfigurationSettings, UtxoSettings}
-import org.ergoplatform.utils.{ErgoPropertyTest, ErgoTestHelpers, HistoryTestHelpers}
+import org.ergoplatform.nodeView.history.{ErgoHistory, ErgoHistoryReader}
+import org.ergoplatform.utils.HistoryTestHelpers
import scorex.util.{ModifierId, bytesToId}
-import sigmastate.Values
-import sigmastate.crypto.DLogProtocol.ProveDlog
-import sigmastate.eval.Extensions._
-import sigmastate.eval._
-import sigma.{Coll, Colls}
import spire.implicits.cfor
-import java.io.File
-import scala.annotation.tailrec
import scala.collection.mutable
-import scala.collection.mutable.ArrayBuffer
-import scala.concurrent.duration.{DurationInt, FiniteDuration}
import scala.reflect.ClassTag
-import scala.util.{Random, Try}
-class ExtraIndexerSpecification extends ErgoPropertyTest with ExtraIndexerBase with HistoryTestHelpers {
+class ExtraIndexerSpecification extends HistoryTestHelpers {
- type ID_LL = mutable.HashMap[ModifierId,(Long,Long)]
-
- override protected val saveLimit: Int = 1 // save every block
- override protected implicit val segmentTreshold: Int = 8 // split to smaller segments
- override protected implicit val addressEncoder: ErgoAddressEncoder = initSettings.chainSettings.addressEncoder
+ case class CreateDB()
- val nodeSettings: NodeConfigurationSettings = NodeConfigurationSettings(StateType.Utxo, verifyTransactions = true,
- -1, UtxoSettings(utxoBootstrap = false, 0, 2), NipopowSettings(nipopowBootstrap = false, 1), mining = false,
- ChainGenerator.txCostLimit, ChainGenerator.txSizeLimit, useExternalMiner = false, internalMinersCount = 1,
- internalMinerPollingInterval = 1.second, miningPubKeyHex = None, offlineGeneration = false,
- 200, 5.minutes, 100000, 1.minute, mempoolSorting = SortingOption.FeePerByte, rebroadcastCount = 20,
- 1000000, 100, adProofsSuffixLength = 112 * 1024, extraIndex = false)
+ type ID_LL = mutable.HashMap[ModifierId,(Long,Long)]
val HEIGHT: Int = 50
val BRANCHPOINT: Int = HEIGHT / 2
+ implicit val segmentThreshold: Int = 8
- def createDB(): Unit = {
- val dir: File = createTempDir
- dir.mkdirs()
-
- val fullHistorySettings: ErgoSettings = ErgoSettings(dir.getAbsolutePath, NetworkType.TestNet, initSettings.chainSettings,
- nodeSettings, settings.scorexSettings, settings.walletSettings, settings.cacheSettings)
+ val system: ActorSystem = ActorSystem.create("indexer-test")
+ val indexer: ActorRef = system.actorOf(Props.create(classOf[ExtraIndexerTestActor], this))
- _history = ErgoHistory.readOrGenerate(fullHistorySettings)(null)
-
- ChainGenerator.generate(HEIGHT, dir)(_history)
-
- // reset all variables
- indexedHeight = 0
- globalTxIndex = 0L
- globalBoxIndex = 0L
- lastWroteToDB = 0
- caughtUp = false
- rollback = false
- general.clear()
- boxes.clear()
- trees.clear()
- tokens.clear()
- segments.clear()
- }
+ var _history: ErgoHistory = _
+ def history: ErgoHistoryReader = _history.getReader
def manualIndex(limit: Int): (ID_LL, // address -> (erg,tokenSum)
ID_LL, // tokenId -> (boxesCount,_)
@@ -82,8 +35,8 @@ class ExtraIndexerSpecification extends ErgoPropertyTest with ExtraIndexerBase w
Int) = { // boxes indexed
var txsIndexed = 0
var boxesIndexed = 0
- val addresses: ID_LL = mutable.HashMap[ModifierId,(Long,Long)]()
- val indexedTokens: ID_LL = mutable.HashMap[ModifierId,(Long,Long)]()
+ val addresses: ID_LL = mutable.HashMap[ModifierId, (Long, Long)]()
+ val indexedTokens: ID_LL = mutable.HashMap[ModifierId, (Long, Long)]()
cfor(1)(_ <= limit, _ + 1) { i =>
_history.getReader.bestBlockTransactionsAt(i).get.txs.foreach { tx =>
txsIndexed += 1
@@ -119,18 +72,18 @@ class ExtraIndexerSpecification extends ErgoPropertyTest with ExtraIndexerBase w
segmentables.foreach { segmentable =>
history.typedExtraIndexById[T](segmentable._1) match {
case Some(obj: T) =>
- if(isChild) { // this is a segment
+ if (isChild) { // this is a segment
// check tx segments
- val txSegments: ID_LL = mutable.HashMap.empty[ModifierId,(Long,Long)]
+ val txSegments: ID_LL = mutable.HashMap.empty[ModifierId, (Long, Long)]
txSegments ++= (0 until obj.txSegmentCount).map(n => obj.idMod(txSegmentId(obj.parentId, n))).map(Tuple2(_, (0L, 0L)))
checkSegmentables(txSegments, isChild = true, check) shouldBe 0
// check box segments
- val boxSegments: ID_LL = mutable.HashMap.empty[ModifierId,(Long,Long)]
+ val boxSegments: ID_LL = mutable.HashMap.empty[ModifierId, (Long, Long)]
boxSegments ++= (0 until obj.boxSegmentCount).map(n => obj.idMod(boxSegmentId(obj.parentId, n))).map(Tuple2(_, (0L, 0L)))
checkSegmentables(boxSegments, isChild = true, check) shouldBe 0
- }else { // this is the parent object
+ } else { // this is the parent object
// check properties of object
- if(!check((obj, segmentable._2)))
+ if (!check((obj, segmentable._2)))
errors += 1
// check boxes in memory
obj.boxes.foreach { boxNum =>
@@ -169,9 +122,11 @@ class ExtraIndexerSpecification extends ErgoPropertyTest with ExtraIndexerBase w
})
property("extra indexer transactions") {
- createDB()
- run()
- cfor(0)(_ < globalTxIndex, _ + 1) {n =>
+ indexer ! CreateDB()
+ indexer ! Index()
+ Thread.sleep(5000)
+ val state = IndexerState.fromHistory(_history)
+ cfor(0)(_ < state.globalTxIndex, _ + 1) { n =>
val id = history.typedExtraIndexById[NumericTxIndex](bytesToId(NumericTxIndex.indexToBytes(n)))
id shouldNot be(empty)
history.typedExtraIndexById[IndexedErgoTransaction](id.get.m) shouldNot be(empty)
@@ -179,9 +134,11 @@ class ExtraIndexerSpecification extends ErgoPropertyTest with ExtraIndexerBase w
}
property("extra indexer boxes") {
- createDB()
- run()
- cfor(0)(_ < globalBoxIndex, _ + 1) { n =>
+ indexer ! CreateDB()
+ indexer ! Index()
+ Thread.sleep(5000)
+ val state = IndexerState.fromHistory(_history)
+ cfor(0)(_ < state.globalBoxIndex, _ + 1) { n =>
val id = history.typedExtraIndexById[NumericBoxIndex](bytesToId(NumericBoxIndex.indexToBytes(n)))
id shouldNot be(empty)
history.typedExtraIndexById[IndexedErgoBox](id.get.m) shouldNot be(empty)
@@ -189,32 +146,37 @@ class ExtraIndexerSpecification extends ErgoPropertyTest with ExtraIndexerBase w
}
property("extra indexer addresses") {
- createDB()
- run()
+ indexer ! CreateDB()
+ indexer ! Index()
+ Thread.sleep(5000)
val (addresses, _, _, _) = manualIndex(HEIGHT)
checkAddresses(addresses) shouldBe 0
}
property("extra indexer tokens") {
- createDB()
- run()
+ indexer ! CreateDB()
+ indexer ! Index()
+ Thread.sleep(5000)
val (_, indexedTokens, _, _) = manualIndex(HEIGHT)
checkTokens(indexedTokens) shouldBe 0
}
property("extra indexer rollback") {
- createDB()
+ indexer ! CreateDB()
+ indexer ! Index()
+ Thread.sleep(5000)
+ var state = IndexerState.fromHistory(_history)
- run()
-
- val txIndexBefore = globalTxIndex
- val boxIndexBefore = globalBoxIndex
+ val txIndexBefore = state.globalTxIndex
+ val boxIndexBefore = state.globalBoxIndex
// manually count balances
val (addresses, indexedTokens, txsIndexed, boxesIndexed) = manualIndex(BRANCHPOINT)
// perform rollback
- removeAfter(BRANCHPOINT)
+ indexer ! Rollback(history.bestHeaderIdAtHeight(BRANCHPOINT).get)
+ Thread.sleep(5000)
+ state = IndexerState.fromHistory(_history)
// address balances
checkAddresses(addresses) shouldBe 0
@@ -223,13 +185,13 @@ class ExtraIndexerSpecification extends ErgoPropertyTest with ExtraIndexerBase w
checkTokens(indexedTokens) shouldBe 0
// check indexnumbers
- globalTxIndex shouldBe txsIndexed
- globalBoxIndex shouldBe boxesIndexed
+ state.globalTxIndex shouldBe txsIndexed
+ state.globalBoxIndex shouldBe boxesIndexed
// check txs
- cfor(0)(_ < txIndexBefore, _ + 1) {txNum =>
+ cfor(0)(_ < txIndexBefore, _ + 1) { txNum =>
val txOpt = history.typedExtraIndexById[NumericTxIndex](bytesToId(NumericTxIndex.indexToBytes(txNum)))
- if(txNum < globalTxIndex)
+ if (txNum < state.globalTxIndex)
txOpt shouldNot be(empty)
else
txOpt shouldBe None
@@ -238,7 +200,7 @@ class ExtraIndexerSpecification extends ErgoPropertyTest with ExtraIndexerBase w
// check boxes
cfor(0)(_ < boxIndexBefore, _ + 1) { boxNum =>
val boxOpt = history.typedExtraIndexById[NumericBoxIndex](bytesToId(NumericBoxIndex.indexToBytes(boxNum)))
- if (boxNum < globalBoxIndex)
+ if (boxNum < state.globalBoxIndex)
boxOpt shouldNot be(empty)
else
boxOpt shouldBe None
@@ -246,7 +208,11 @@ class ExtraIndexerSpecification extends ErgoPropertyTest with ExtraIndexerBase w
// -------------------------------------------------------------------
// restart indexer to catch up
- run()
+ cfor(BRANCHPOINT)(_ <= HEIGHT, _ + 1) { i =>
+ indexer ! FullBlockApplied(history.bestHeaderAtHeight(i).get)
+ }
+ Thread.sleep(5000)
+ state = IndexerState.fromHistory(_history)
// Check addresses again
val (addresses2, indexedTokens2, _, _) = manualIndex(HEIGHT)
@@ -254,8 +220,8 @@ class ExtraIndexerSpecification extends ErgoPropertyTest with ExtraIndexerBase w
checkTokens(indexedTokens2) shouldBe 0
// check indexnumbers again
- globalTxIndex shouldBe txIndexBefore
- globalBoxIndex shouldBe boxIndexBefore
+ state.globalTxIndex shouldBe txIndexBefore
+ state.globalBoxIndex shouldBe boxIndexBefore
// check txs after caught up
cfor(0)(_ < txIndexBefore, _ + 1) { txNum =>
@@ -266,187 +232,5 @@ class ExtraIndexerSpecification extends ErgoPropertyTest with ExtraIndexerBase w
cfor(0)(_ < boxIndexBefore, _ + 1) { boxNum =>
history.typedExtraIndexById[NumericBoxIndex](bytesToId(NumericBoxIndex.indexToBytes(boxNum))) shouldNot be(empty)
}
-
- }
-
-}
-
-object ChainGenerator extends ErgoTestHelpers {
-
- val pow: AutolykosPowScheme = new AutolykosPowScheme(powScheme.k, powScheme.n)
- val blockInterval: FiniteDuration = 2.minute
- val EmissionTxCost: Long = 20000
- val MinTxAmount: Long = 2000000
- val RewardDelay: Int = initSettings.chainSettings.monetary.minerRewardDelay
- val MaxTxsPerBlock: Int = 10
- val minerPk: ProveDlog = defaultProver.hdKeys.head.publicImage
- val selfAddressScript: Values.ErgoTree = P2PKAddress(minerPk).script
- val minerProp: Values.ErgoTree = ErgoTreePredef.rewardOutputScript(RewardDelay, minerPk)
- val votingEpochLength: Height = votingSettings.votingLength
- val protocolVersion: Byte = initSettings.chainSettings.protocolVersion
- val minimalSuffix = 2
- val txCostLimit: Height = initSettings.nodeSettings.maxTransactionCost
- val txSizeLimit: Height = initSettings.nodeSettings.maxTransactionSize
-
- var startTime: Long = 0
-
- def generate(length: Int, dir: File)(history: ErgoHistory): Unit = {
- val stateDir = new File(s"${dir.getAbsolutePath}/state")
- stateDir.mkdirs()
- val (state, _) = ErgoState.generateGenesisUtxoState(stateDir, initSettings)
- System.out.println(s"Going to generate a chain at ${dir.getAbsolutePath} starting from ${history.bestFullBlockOpt}")
- startTime = System.currentTimeMillis() - (blockInterval * (length - 1)).toMillis
- val chain = loop(state, None, None, Seq())(history)
- System.out.println(s"Chain of length ${chain.length} generated")
- history.bestHeaderOpt shouldBe history.bestFullBlockOpt.map(_.header)
- history.bestFullBlockOpt.get.id shouldBe chain.last
- System.out.println("History was generated successfully")
}
-
- @tailrec
- private def loop(state: UtxoState,
- initBox: Option[ErgoBox],
- last: Option[Header],
- acc: Seq[ModifierId])(history: ErgoHistory): Seq[ModifierId] = {
- val time: Long = last.map(_.timestamp + blockInterval.toMillis).getOrElse(startTime)
- if (time < System.currentTimeMillis()) {
- val (txs, lastOut) = genTransactions(last.map(_.height).getOrElse(ErgoHistory.GenesisHeight),
- initBox, state.stateContext)
-
- val candidate = genCandidate(defaultProver.hdPubKeys.head.key, last, time, txs, state)(history)
- val block = proveCandidate(candidate.get)
-
- history.append(block.header).get
- block.blockSections.foreach(s => if (!history.contains(s)) history.append(s).get)
-
- val outToPassNext = if (last.isEmpty) {
- block.transactions.flatMap(_.outputs).find(_.ergoTree == minerProp)
- } else {
- lastOut
- }
-
- assert(outToPassNext.isDefined)
-
- log.info(
- s"Block ${block.id} with ${block.transactions.size} transactions at height ${block.header.height} generated")
-
- loop(state.applyModifier(block, None)(_ => ()).get, outToPassNext, Some(block.header), acc :+ block.id)(history)
- } else {
- acc
- }
- }
-
- private def moveTokens(inOpt: Option[ErgoBox], cond: Boolean): Coll[(TokenId, Long)] = {
- val tokens: ArrayBuffer[(TokenId, Long)] = ArrayBuffer.empty[(TokenId, Long)]
- inOpt match {
- case Some(input) if cond =>
- tokens += Tuple2(input.id.toTokenId, math.abs(Random.nextInt()))
- case Some(tokenBox) if !cond =>
- tokenBox.additionalTokens.toArray.foreach(tokens += _)
- case _ =>
- }
- Colls.fromArray(tokens.toArray)
- }
-
- private def genTransactions(height: Height,
- inOpt: Option[ErgoBox],
- ctx: ErgoStateContext): (Seq[ErgoTransaction], Option[ErgoBox]) = {
- inOpt
- .find { bx =>
- val canUnlock = (bx.creationHeight + RewardDelay <= height) || (bx.ergoTree != minerProp)
- canUnlock && bx.ergoTree != initSettings.chainSettings.monetary.emissionBoxProposition && bx.value >= MinTxAmount
- }
- .map { input =>
- val qty = MaxTxsPerBlock
- val amount = input.value
- val outs = (0 until qty).map(i => new ErgoBoxCandidate(amount, selfAddressScript, height, moveTokens(inOpt, i == 0)))
- var i = 0
- val x = outs
- .foldLeft((Seq.empty[ErgoTransaction], input)) { case ((acc, in), out) =>
- val inputs = IndexedSeq(in)
- val newOut =
- if (i > 0)
- new ErgoBoxCandidate(amount, selfAddressScript, height, moveTokens(acc.lastOption.map(_.outputs.head), cond = false))
- else
- out
- val unsignedTx = UnsignedErgoTransaction(inputs.map(box => new UnsignedInput(box.id)), IndexedSeq(newOut))
- i += 1
- defaultProver.sign(unsignedTx, inputs, emptyDataBoxes, ctx)
- .fold(_ => acc -> in, tx => (acc :+ ErgoTransaction(tx)) -> unsignedTx.outputs.head)
- }
- ._1
- (x, Some(x.last.outputs.head))
- }
- .getOrElse(Seq.empty -> inOpt)
- }
-
- private def genCandidate(minerPk: ProveDlog,
- lastHeaderOpt: Option[Header],
- ts: Long,
- txsFromPool: Seq[ErgoTransaction],
- state: UtxoStateReader)(history: ErgoHistory): Try[CandidateBlock] = Try {
- val stateContext = state.stateContext
- val nBits: Long = lastHeaderOpt
- .map(parent => history.requiredDifficultyAfter(parent))
- .map(d => DifficultySerializer.encodeCompactBits(d))
- .getOrElse(settings.chainSettings.initialNBits)
-
- val interlinks = lastHeaderOpt
- .flatMap { h =>
- history.typedModifierById[Extension](h.extensionId)
- .flatMap(ext => NipopowAlgos.unpackInterlinks(ext.fields).toOption)
- .map(nipopowAlgos.updateInterlinks(h, _))
- }
- .getOrElse(Seq.empty)
- val interlinksExtension = nipopowAlgos.interlinksToExtension(interlinks)
-
- val (extensionCandidate, votes: Array[Byte], version: Byte) = lastHeaderOpt.map { header =>
- val newHeight = header.height + 1
- val currentParams = stateContext.currentParameters
- val betterVersion = protocolVersion > header.version
- val votingFinishHeight: Option[Height] = currentParams.softForkStartingHeight
- .map(_ + votingSettings.votingLength * votingSettings.softForkEpochs)
- val forkVotingAllowed = votingFinishHeight.forall(fh => newHeight < fh)
- val forkOrdered = settings.votingTargets.softFork != 0
- val voteForFork = betterVersion && forkOrdered && forkVotingAllowed
-
- if (newHeight % votingEpochLength == 0 && newHeight > 0) {
- val (newParams, _) = currentParams.update(newHeight, voteForFork, stateContext.votingData.epochVotes, emptyVSUpdate, votingSettings)
- (newParams.toExtensionCandidate ++ interlinksExtension,
- newParams.suggestVotes(settings.votingTargets.targets, voteForFork),
- newParams.blockVersion)
- } else {
- (nipopowAlgos.interlinksToExtension(interlinks),
- currentParams.vote(settings.votingTargets.targets, stateContext.votingData.epochVotes, voteForFork),
- currentParams.blockVersion)
- }
- }.getOrElse((interlinksExtension, Array(0: Byte, 0: Byte, 0: Byte), Header.InitialVersion))
-
- val emissionTxOpt = CandidateGenerator.collectEmission(state, minerPk, emptyStateContext)
- val txs = emissionTxOpt.toSeq ++ txsFromPool
-
- state.proofsForTransactions(txs).map { case (adProof, adDigest) =>
- CandidateBlock(lastHeaderOpt, version, nBits, adDigest, adProof, txs, ts, extensionCandidate, votes)
- }
- }.flatten
-
- @tailrec
- private def proveCandidate(candidate: CandidateBlock): ErgoFullBlock = {
- log.info(s"Trying to prove block with parent ${candidate.parentOpt.map(_.encodedId)} and timestamp ${candidate.timestamp}")
-
- pow.proveCandidate(candidate, defaultProver.hdKeys.head.privateInput.w) match {
- case Some(fb) => fb
- case _ =>
- val interlinks = candidate.parentOpt
- .map(nipopowAlgos.updateInterlinks(_, NipopowAlgos.unpackInterlinks(candidate.extension.fields).get))
- .getOrElse(Seq.empty)
- val minerTag = scorex.utils.Random.randomBytes(Extension.FieldKeySize)
- proveCandidate {
- candidate.copy(
- extension = ExtensionCandidate(Seq(Array(0: Byte, 2: Byte) -> minerTag)) ++ nipopowAlgos.interlinksToExtension(interlinks)
- )
- }
- }
- }
-
}
diff --git a/src/test/scala/org/ergoplatform/nodeView/history/extra/ExtraIndexerTestActor.scala b/src/test/scala/org/ergoplatform/nodeView/history/extra/ExtraIndexerTestActor.scala
new file mode 100644
index 0000000000..e32c3c647f
--- /dev/null
+++ b/src/test/scala/org/ergoplatform/nodeView/history/extra/ExtraIndexerTestActor.scala
@@ -0,0 +1,55 @@
+package org.ergoplatform.nodeView.history.extra
+
+import org.ergoplatform._
+import org.ergoplatform.nodeView.history.ErgoHistory
+import org.ergoplatform.nodeView.mempool.ErgoMemPoolUtils.SortingOption
+import org.ergoplatform.nodeView.state._
+import org.ergoplatform.settings._
+import org.ergoplatform.wallet.utils.FileUtils
+import scorex.util.ModifierId
+
+import java.io.File
+import scala.collection.mutable
+import scala.concurrent.duration.DurationInt
+
+class ExtraIndexerTestActor(test: ExtraIndexerSpecification) extends ExtraIndexerBase with FileUtils {
+
+ override def receive: Receive = {
+ case test.CreateDB() => createDB()
+ }
+
+ type ID_LL = mutable.HashMap[ModifierId,(Long,Long)]
+
+ override protected val saveLimit: Int = 1 // save every block
+ override protected implicit val segmentThreshold: Int = 8 // split to smaller segments
+ override protected implicit val addressEncoder: ErgoAddressEncoder = test.initSettings.chainSettings.addressEncoder
+
+ val nodeSettings: NodeConfigurationSettings = NodeConfigurationSettings(StateType.Utxo, verifyTransactions = true,
+ -1, UtxoSettings(utxoBootstrap = false, 0, 2), NipopowSettings(nipopowBootstrap = false, 1), mining = false,
+ ChainGenerator.txCostLimit, ChainGenerator.txSizeLimit, useExternalMiner = false, internalMinersCount = 1,
+ internalMinerPollingInterval = 1.second, miningPubKeyHex = None, offlineGeneration = false,
+ 200, 5.minutes, 100000, 1.minute, mempoolSorting = SortingOption.FeePerByte, rebroadcastCount = 20,
+ 1000000, 100, adProofsSuffixLength = 112 * 1024, extraIndex = false)
+
+ def createDB(): Unit = {
+ val dir: File = createTempDir
+ dir.mkdirs()
+
+ val fullHistorySettings: ErgoSettings = ErgoSettings(dir.getAbsolutePath, NetworkType.TestNet, test.initSettings.chainSettings,
+ nodeSettings, test.initSettings.scorexSettings, test.initSettings.walletSettings, test.initSettings.cacheSettings)
+
+ _history = ErgoHistory.readOrGenerate(fullHistorySettings)(null)
+
+ ChainGenerator.generate(test.HEIGHT, dir)(_history)
+ test._history = _history
+
+ // reset all variables
+ general.clear()
+ boxes.clear()
+ trees.clear()
+ tokens.clear()
+ segments.clear()
+ context.become(receive.orElse(loaded(IndexerState(0, 0, 0, 0, caughtUp = false))))
+ }
+
+}
diff --git a/src/test/scala/org/ergoplatform/nodeView/history/storage/HistoryStorageSpec.scala b/src/test/scala/org/ergoplatform/nodeView/history/storage/HistoryStorageSpec.scala
index 7020d1fee7..fd50355f3f 100644
--- a/src/test/scala/org/ergoplatform/nodeView/history/storage/HistoryStorageSpec.scala
+++ b/src/test/scala/org/ergoplatform/nodeView/history/storage/HistoryStorageSpec.scala
@@ -3,7 +3,7 @@ package org.ergoplatform.nodeView.history.storage
import org.ergoplatform.modifiers.BlockSection
import org.ergoplatform.modifiers.history.ADProofs
import org.ergoplatform.modifiers.history.header.Header
-import org.ergoplatform.nodeView.history.ErgoHistory
+import org.ergoplatform.nodeView.history.ErgoHistoryUtils._
import org.ergoplatform.settings.Algos
import org.ergoplatform.utils.HistoryTestHelpers
import org.scalacheck.Gen
@@ -17,7 +17,7 @@ class HistoryStorageSpec extends HistoryTestHelpers {
property("Write Read Remove") {
val headers: Array[Header] = Gen.listOfN(20, defaultHeaderGen).sample.get.toArray
val modifiers: Array[ADProofs] = Gen.listOfN(20, randomADProofsGen).sample.get.toArray
- def validityKey(id: ModifierId) = ByteArrayWrapper(Algos.hash("validity".getBytes(ErgoHistory.CharsetName) ++ idToBytes(id)))
+ def validityKey(id: ModifierId) = ByteArrayWrapper(Algos.hash("validity".getBytes(CharsetName) ++ idToBytes(id)))
val indexes = headers.flatMap(h => Array(validityKey(h.id) -> Array(1.toByte)))
db.insert(indexes, (headers ++ modifiers).asInstanceOf[Array[BlockSection]]) shouldBe 'success
diff --git a/src/test/scala/org/ergoplatform/nodeView/mempool/ErgoMemPoolSpec.scala b/src/test/scala/org/ergoplatform/nodeView/mempool/ErgoMemPoolSpec.scala
index 38aaa799d3..b705ec11ad 100644
--- a/src/test/scala/org/ergoplatform/nodeView/mempool/ErgoMemPoolSpec.scala
+++ b/src/test/scala/org/ergoplatform/nodeView/mempool/ErgoMemPoolSpec.scala
@@ -1,9 +1,8 @@
package org.ergoplatform.nodeView.mempool
import org.ergoplatform.{ErgoBoxCandidate, Input}
-import org.ergoplatform.nodeView.mempool.ErgoMemPool.SortingOption
+import org.ergoplatform.nodeView.mempool.ErgoMemPoolUtils.{SortingOption, ProcessingOutcome}
import org.ergoplatform.modifiers.mempool.{ErgoTransaction, UnconfirmedTransaction}
-import org.ergoplatform.nodeView.mempool.ErgoMemPool.ProcessingOutcome
import org.ergoplatform.nodeView.state.wrapped.WrappedUtxoState
import org.ergoplatform.settings.ErgoSettings
import org.ergoplatform.utils.ErgoTestHelpers
diff --git a/src/test/scala/org/ergoplatform/nodeView/state/DigestStateSpecification.scala b/src/test/scala/org/ergoplatform/nodeView/state/DigestStateSpecification.scala
index 7cf71def1a..e9db1e9e72 100644
--- a/src/test/scala/org/ergoplatform/nodeView/state/DigestStateSpecification.scala
+++ b/src/test/scala/org/ergoplatform/nodeView/state/DigestStateSpecification.scala
@@ -5,7 +5,7 @@ import org.ergoplatform.modifiers.ErgoFullBlock
import org.ergoplatform.modifiers.history.ADProofs
import org.ergoplatform.modifiers.mempool.ErgoTransaction
import org.ergoplatform.utils.{ErgoPropertyTest, RandomWrapper}
-import scorex.core._
+import org.ergoplatform.core._
import scorex.crypto.authds.ADDigest
import sigmastate.interpreter.ProverResult
diff --git a/src/test/scala/org/ergoplatform/nodeView/state/ErgoStateSpecification.scala b/src/test/scala/org/ergoplatform/nodeView/state/ErgoStateSpecification.scala
index 059b4e0d1c..2260b25314 100644
--- a/src/test/scala/org/ergoplatform/nodeView/state/ErgoStateSpecification.scala
+++ b/src/test/scala/org/ergoplatform/nodeView/state/ErgoStateSpecification.scala
@@ -4,12 +4,12 @@ import org.ergoplatform.modifiers.ErgoFullBlock
import org.ergoplatform.modifiers.history.BlockTransactions
import org.ergoplatform.modifiers.history.header.Header
import org.ergoplatform.modifiers.mempool.ErgoTransaction
-import org.ergoplatform.settings.{Args, ErgoSettings}
+import org.ergoplatform.settings.{Args, ErgoSettingsReader}
import org.ergoplatform.utils.{ErgoPropertyTest, RandomWrapper}
import org.ergoplatform.wallet.boxes.ErgoBoxSerializer
import org.scalacheck.Gen
-import scorex.core.bytesToVersion
-import scorex.core.validation.ValidationResult.Valid
+import org.ergoplatform.core.bytesToVersion
+import org.ergoplatform.validation.ValidationResult.Valid
import scorex.db.ByteArrayWrapper
import scala.collection.mutable
@@ -66,7 +66,7 @@ class ErgoStateSpecification extends ErgoPropertyTest {
}
property("generateGenesisUtxoState & generateGenesisDigestState are compliant") {
- val settings = ErgoSettings.read(Args.empty)
+ val settings = ErgoSettingsReader.read(Args.empty)
val dir = createTempDir
val rootHash = createUtxoState(settings)._1.rootDigest
val expectedRootHash = ErgoState.generateGenesisDigestState(dir, settings).rootDigest
@@ -163,28 +163,28 @@ class ErgoStateSpecification extends ErgoPropertyTest {
val expectedCost = 185160
// successful validation
- ErgoState.execTransactions(txs, stateContext)(id => Try(boxes(ByteArrayWrapper(id)))) shouldBe Valid(expectedCost)
+ ErgoState.execTransactions(txs, stateContext, settings.nodeSettings)(id => Try(boxes(ByteArrayWrapper(id)))) shouldBe Valid(expectedCost)
// cost limit exception expected when crossing MaxBlockCost
val tooManyTxs = (1 to 10).flatMap(_ => generateTxs)
assert(
- ErgoState.execTransactions(tooManyTxs, stateContext)(id => Try(boxes(ByteArrayWrapper(id)))).errors.head.message.contains(
+ ErgoState.execTransactions(tooManyTxs, stateContext, settings.nodeSettings)(id => Try(boxes(ByteArrayWrapper(id)))).errors.head.message.contains(
"Accumulated cost of block transactions should not exceed "
)
)
// missing box in state
- ErgoState.execTransactions(txs, stateContext)(_ => Failure(new RuntimeException)).errors.head.message shouldBe
+ ErgoState.execTransactions(txs, stateContext, settings.nodeSettings)(_ => Failure(new RuntimeException)).errors.head.message shouldBe
"Every input of the transaction should be in UTXO. null"
// tx validation should kick in and detect block height violation
val invalidTx = invalidErgoTransactionGen.sample.get
assert(
- ErgoState.execTransactions(txs :+ invalidTx, stateContext)(id => Try(boxes.getOrElse(ByteArrayWrapper(id), invalidTx.outputs.head)))
+ ErgoState.execTransactions(txs :+ invalidTx, stateContext, settings.nodeSettings)(id => Try(boxes.getOrElse(ByteArrayWrapper(id), invalidTx.outputs.head)))
.errors.head.message.startsWith("Transaction outputs should have creationHeight not exceeding block height.")
)
// no transactions are valid
- assert(ErgoState.execTransactions(Seq.empty, stateContext)(id => Try(boxes(ByteArrayWrapper(id)))).isValid)
+ assert(ErgoState.execTransactions(Seq.empty, stateContext, settings.nodeSettings)(id => Try(boxes(ByteArrayWrapper(id)))).isValid)
}
}
diff --git a/src/test/scala/org/ergoplatform/nodeView/state/UtxoStateSpecification.scala b/src/test/scala/org/ergoplatform/nodeView/state/UtxoStateSpecification.scala
index e3dc146a8c..4ce52bc67c 100644
--- a/src/test/scala/org/ergoplatform/nodeView/state/UtxoStateSpecification.scala
+++ b/src/test/scala/org/ergoplatform/nodeView/state/UtxoStateSpecification.scala
@@ -9,13 +9,13 @@ import org.ergoplatform.modifiers.history.extension.Extension
import org.ergoplatform.modifiers.history.header.Header
import org.ergoplatform.modifiers.history.{ADProofs, BlockTransactions}
import org.ergoplatform.modifiers.mempool.{ErgoTransaction, UnsignedErgoTransaction}
-import org.ergoplatform.nodeView.history.ErgoHistory
+import org.ergoplatform.nodeView.history.ErgoHistoryUtils._
+import org.ergoplatform.modifiers.transaction.TooHighCostError
+import org.ergoplatform.core.idToVersion
import org.ergoplatform.nodeView.state.wrapped.WrappedUtxoState
import org.ergoplatform.settings.Constants
import org.ergoplatform.utils.{ErgoPropertyTest, RandomWrapper}
import org.ergoplatform.utils.generators.ErgoTransactionGenerators
-import scorex.core._
-import scorex.core.transaction.TooHighCostError
import scorex.crypto.authds.ADKey
import scorex.db.ByteArrayWrapper
import scorex.util.{ModifierId, bytesToId}
@@ -62,7 +62,7 @@ class UtxoStateSpecification extends ErgoPropertyTest with ErgoTransactionGenera
property("Founders should be able to spend genesis founders box") {
var (us, bh) = createUtxoState(settings)
val foundersBox = genesisBoxes.last
- var height: Int = ErgoHistory.GenesisHeight
+ var height: Int = GenesisHeight
val settingsPks = settings.chainSettings.foundersPubkeys
.map(str => groupElemFromBytes(Base16.decode(str).get))
@@ -160,7 +160,7 @@ class UtxoStateSpecification extends ErgoPropertyTest with ErgoTransactionGenera
property("proofsForTransactions") {
var (us: UtxoState, bh) = createUtxoState(settings)
- var height: Int = ErgoHistory.GenesisHeight
+ var height: Int = GenesisHeight
forAll(defaultHeaderGen) { header =>
val t = validTransactionsFromBoxHolder(bh, new RandomWrapper(Some(height)))
val txs = t._1
@@ -184,7 +184,7 @@ class UtxoStateSpecification extends ErgoPropertyTest with ErgoTransactionGenera
var bh = BoxHolder(Seq(genesisEmissionBox))
var us = createUtxoState(bh, parameters)
- var height: Int = ErgoHistory.GenesisHeight
+ var height: Int = GenesisHeight
// generate chain of correct full blocks
val chain = (0 until 10) map { _ =>
val header = defaultHeaderGen.sample.value
diff --git a/src/test/scala/org/ergoplatform/nodeView/state/wrapped/WrappedDigestState.scala b/src/test/scala/org/ergoplatform/nodeView/state/wrapped/WrappedDigestState.scala
index fe1933fad9..256b4c9492 100644
--- a/src/test/scala/org/ergoplatform/nodeView/state/wrapped/WrappedDigestState.scala
+++ b/src/test/scala/org/ergoplatform/nodeView/state/wrapped/WrappedDigestState.scala
@@ -1,11 +1,11 @@
package org.ergoplatform.nodeView.state.wrapped
-import org.ergoplatform.nodeView.ErgoNodeViewHolder.ReceivableMessages.LocallyGeneratedModifier
import org.ergoplatform.ErgoLikeContext.Height
import org.ergoplatform.modifiers.BlockSection
import org.ergoplatform.nodeView.state.DigestState
import org.ergoplatform.settings.ErgoSettings
-import scorex.core.VersionTag
+import org.ergoplatform.core.VersionTag
+import org.ergoplatform.nodeView.LocallyGeneratedModifier
import scala.util.Try
diff --git a/src/test/scala/org/ergoplatform/nodeView/state/wrapped/WrappedUtxoState.scala b/src/test/scala/org/ergoplatform/nodeView/state/wrapped/WrappedUtxoState.scala
index d747a4b5be..e0ee4aceed 100644
--- a/src/test/scala/org/ergoplatform/nodeView/state/wrapped/WrappedUtxoState.scala
+++ b/src/test/scala/org/ergoplatform/nodeView/state/wrapped/WrappedUtxoState.scala
@@ -1,17 +1,16 @@
package org.ergoplatform.nodeView.state.wrapped
import java.io.File
-
import akka.actor.ActorRef
-import org.ergoplatform.ErgoBox
-import org.ergoplatform.nodeView.ErgoNodeViewHolder.ReceivableMessages.LocallyGeneratedModifier
+import org.ergoplatform.{ErgoBox, TransactionsCarryingPersistentNodeViewModifier}
import org.ergoplatform.ErgoLikeContext.Height
import org.ergoplatform.modifiers.BlockSection
import org.ergoplatform.nodeView.state._
import org.ergoplatform.settings.{ErgoSettings, Parameters}
import org.ergoplatform.settings.Algos.HF
import org.ergoplatform.wallet.boxes.ErgoBoxSerializer
-import scorex.core.{TransactionsCarryingPersistentNodeViewModifier, VersionTag, idToVersion}
+import org.ergoplatform.core.{VersionTag, idToVersion}
+import org.ergoplatform.nodeView.LocallyGeneratedModifier
import scorex.crypto.authds.avltree.batch._
import scorex.crypto.hash.Digest32
import scorex.db.{ByteArrayWrapper, LDBVersionedStore}
diff --git a/src/test/scala/org/ergoplatform/nodeView/viewholder/ErgoNodeViewHolderSpec.scala b/src/test/scala/org/ergoplatform/nodeView/viewholder/ErgoNodeViewHolderSpec.scala
index 83e9243ad9..a07eadc8fb 100644
--- a/src/test/scala/org/ergoplatform/nodeView/viewholder/ErgoNodeViewHolderSpec.scala
+++ b/src/test/scala/org/ergoplatform/nodeView/viewholder/ErgoNodeViewHolderSpec.scala
@@ -4,22 +4,21 @@ import java.io.File
import org.ergoplatform.ErgoBoxCandidate
import org.ergoplatform.modifiers.ErgoFullBlock
import org.ergoplatform.modifiers.mempool.UnconfirmedTransaction
-import org.ergoplatform.nodeView.history.ErgoHistory
+import org.ergoplatform.nodeView.history.ErgoHistoryUtils._
import org.ergoplatform.nodeView.state.StateType.Utxo
import org.ergoplatform.nodeView.state._
import org.ergoplatform.nodeView.state.wrapped.WrappedUtxoState
import org.ergoplatform.settings.{Algos, Constants, ErgoSettings}
import org.ergoplatform.utils.{ErgoPropertyTest, HistoryTestHelpers, NodeViewTestConfig, NodeViewTestOps, TestCase}
import org.ergoplatform.nodeView.ErgoNodeViewHolder.ReceivableMessages._
-import org.ergoplatform.network.ErgoNodeViewSynchronizer.ReceivableMessages._
-import org.ergoplatform.nodeView.ErgoNodeViewHolder
+import org.ergoplatform.network.ErgoNodeViewSynchronizerMessages._
+import org.ergoplatform.nodeView.{ErgoNodeViewHolder, LocallyGeneratedModifier}
import org.ergoplatform.nodeView.ErgoNodeViewHolder.ReceivableMessages.ChainProgress
-import org.ergoplatform.nodeView.mempool.ErgoMemPool.ProcessingOutcome.Accepted
+import org.ergoplatform.nodeView.mempool.ErgoMemPoolUtils.ProcessingOutcome.Accepted
import scorex.crypto.authds.{ADKey, SerializedAdProof}
-import scorex.testkit.utils.NoShrink
import scorex.util.{ModifierId, bytesToId}
-class ErgoNodeViewHolderSpec extends ErgoPropertyTest with HistoryTestHelpers with NodeViewTestOps with NoShrink {
+class ErgoNodeViewHolderSpec extends ErgoPropertyTest with HistoryTestHelpers with NodeViewTestOps {
private val t0 = TestCase("check chain is healthy") { fixture =>
val (us, bh) = createUtxoState(settings)
@@ -55,7 +54,7 @@ class ErgoNodeViewHolderSpec extends ErgoPropertyTest with HistoryTestHelpers wi
val block = validFullBlock(None, us, bh)
getBestHeaderOpt shouldBe None
- getHistoryHeight shouldBe ErgoHistory.EmptyHistoryHeight
+ getHistoryHeight shouldBe EmptyHistoryHeight
subscribeEvents(classOf[SyntacticallySuccessfulModifier])
@@ -63,8 +62,8 @@ class ErgoNodeViewHolderSpec extends ErgoPropertyTest with HistoryTestHelpers wi
nodeViewHolderRef ! LocallyGeneratedModifier(block.header)
expectMsgType[SyntacticallySuccessfulModifier]
- getHistoryHeight shouldBe ErgoHistory.GenesisHeight
- getHeightOf(block.header.id) shouldBe Some(ErgoHistory.GenesisHeight)
+ getHistoryHeight shouldBe GenesisHeight
+ getHeightOf(block.header.id) shouldBe Some(GenesisHeight)
getLastHeadersLength(10) shouldBe 1
getBestHeaderOpt shouldBe Some(block.header)
}
@@ -76,7 +75,7 @@ class ErgoNodeViewHolderSpec extends ErgoPropertyTest with HistoryTestHelpers wi
val block = validFullBlock(Some(parentBlock), us, bh)
getBestHeaderOpt shouldBe None
- getHistoryHeight shouldBe ErgoHistory.EmptyHistoryHeight
+ getHistoryHeight shouldBe EmptyHistoryHeight
subscribeEvents(classOf[SyntacticallySuccessfulModifier])
@@ -317,7 +316,7 @@ class ErgoNodeViewHolderSpec extends ErgoPropertyTest with HistoryTestHelpers wi
val (us, bh) = createUtxoState(fixture.settings)
val block = validFullBlock(None, us, bh)
getBestHeaderOpt shouldBe None
- getHistoryHeight shouldBe ErgoHistory.EmptyHistoryHeight
+ getHistoryHeight shouldBe EmptyHistoryHeight
subscribeEvents(classOf[RecoverableFailedModification])
subscribeEvents(classOf[SyntacticallySuccessfulModifier])
@@ -327,8 +326,8 @@ class ErgoNodeViewHolderSpec extends ErgoPropertyTest with HistoryTestHelpers wi
nodeViewHolderRef ! LocallyGeneratedModifier(block.header)
expectMsgType[SyntacticallySuccessfulModifier]
val currentHeight = getHistoryHeight
- currentHeight shouldBe ErgoHistory.GenesisHeight
- getHeightOf(block.header.id) shouldBe Some(ErgoHistory.GenesisHeight)
+ currentHeight shouldBe GenesisHeight
+ getHeightOf(block.header.id) shouldBe Some(GenesisHeight)
val randomId = modifierIdGen.sample.value
val recoverableTxs = block.blockTransactions.copy(headerId = randomId)
@@ -371,7 +370,7 @@ class ErgoNodeViewHolderSpec extends ErgoPropertyTest with HistoryTestHelpers wi
val block = validFullBlock(None, us, bh)
getBestHeaderOpt shouldBe None
- getHistoryHeight shouldBe ErgoHistory.EmptyHistoryHeight
+ getHistoryHeight shouldBe EmptyHistoryHeight
subscribeEvents(classOf[RecoverableFailedModification])
subscribeEvents(classOf[SyntacticallySuccessfulModifier])
@@ -404,7 +403,7 @@ class ErgoNodeViewHolderSpec extends ErgoPropertyTest with HistoryTestHelpers wi
val block = validFullBlock(None, us, bh)
getBestHeaderOpt shouldBe None
- getHistoryHeight shouldBe ErgoHistory.EmptyHistoryHeight
+ getHistoryHeight shouldBe EmptyHistoryHeight
subscribeEvents(classOf[RecoverableFailedModification])
subscribeEvents(classOf[SyntacticallySuccessfulModifier])
@@ -414,7 +413,7 @@ class ErgoNodeViewHolderSpec extends ErgoPropertyTest with HistoryTestHelpers wi
nodeViewHolderRef ! LocallyGeneratedModifier(block.header)
expectMsgType[SyntacticallyFailedModification]
getBestHeaderOpt shouldBe None
- getHistoryHeight shouldBe ErgoHistory.EmptyHistoryHeight
+ getHistoryHeight shouldBe EmptyHistoryHeight
}
private val t15 = TestCase("apply genesis block header if it's equal to genesisId from config") { fixture =>
@@ -424,7 +423,7 @@ class ErgoNodeViewHolderSpec extends ErgoPropertyTest with HistoryTestHelpers wi
updateConfig(genesisIdConfig(Some(block.header.id)))
getBestHeaderOpt shouldBe None
- getHistoryHeight shouldBe ErgoHistory.EmptyHistoryHeight
+ getHistoryHeight shouldBe EmptyHistoryHeight
subscribeEvents(classOf[RecoverableFailedModification])
subscribeEvents(classOf[SyntacticallySuccessfulModifier])
@@ -432,8 +431,8 @@ class ErgoNodeViewHolderSpec extends ErgoPropertyTest with HistoryTestHelpers wi
nodeViewHolderRef ! LocallyGeneratedModifier(block.header)
expectMsgType[SyntacticallySuccessfulModifier]
- getHistoryHeight shouldBe ErgoHistory.GenesisHeight
- getHeightOf(block.header.id) shouldBe Some(ErgoHistory.GenesisHeight)
+ getHistoryHeight shouldBe GenesisHeight
+ getHeightOf(block.header.id) shouldBe Some(GenesisHeight)
}
private val t16 = TestCase("apply forks that include genesis block") { fixture =>
@@ -473,7 +472,7 @@ class ErgoNodeViewHolderSpec extends ErgoPropertyTest with HistoryTestHelpers wi
val header = validFullBlock(None, us, bh).header.copy(parentId = bytesToId(Array.fill(32)(9: Byte)))
getBestHeaderOpt shouldBe None
- getHistoryHeight shouldBe ErgoHistory.EmptyHistoryHeight
+ getHistoryHeight shouldBe EmptyHistoryHeight
subscribeEvents(classOf[RecoverableFailedModification])
subscribeEvents(classOf[SyntacticallySuccessfulModifier])
@@ -481,7 +480,7 @@ class ErgoNodeViewHolderSpec extends ErgoPropertyTest with HistoryTestHelpers wi
nodeViewHolderRef ! LocallyGeneratedModifier(header)
expectMsgType[SyntacticallyFailedModification]
- getHistoryHeight shouldBe ErgoHistory.EmptyHistoryHeight
+ getHistoryHeight shouldBe EmptyHistoryHeight
getHeightOf(header.id) shouldBe None
}
diff --git a/src/test/scala/org/ergoplatform/nodeView/viewholder/PrunedNodeViewHolderSpec.scala b/src/test/scala/org/ergoplatform/nodeView/viewholder/PrunedNodeViewHolderSpec.scala
index 621a2119dd..e1f69d6eec 100644
--- a/src/test/scala/org/ergoplatform/nodeView/viewholder/PrunedNodeViewHolderSpec.scala
+++ b/src/test/scala/org/ergoplatform/nodeView/viewholder/PrunedNodeViewHolderSpec.scala
@@ -3,13 +3,13 @@ package org.ergoplatform.nodeView.viewholder
import akka.actor.ActorRef
import org.ergoplatform.mining.DefaultFakePowScheme
import org.ergoplatform.modifiers.ErgoFullBlock
+import org.ergoplatform.nodeView.LocallyGeneratedModifier
import org.ergoplatform.nodeView.state.wrapped.WrappedUtxoState
import org.ergoplatform.nodeView.state.{DigestState, StateType}
-import org.ergoplatform.settings.{ErgoSettings, VotingSettings}
+import org.ergoplatform.settings.{ErgoSettings, ErgoSettingsReader, VotingSettings}
import org.ergoplatform.utils.fixtures.NodeViewFixture
import org.ergoplatform.utils.{ErgoPropertyTest, NodeViewTestOps}
-import org.ergoplatform.nodeView.ErgoNodeViewHolder.ReceivableMessages.LocallyGeneratedModifier
-import scorex.testkit.utils.NoShrink
+import org.ergoplatform.testkit.utils.NoShrink
import scala.concurrent.duration._
@@ -20,7 +20,7 @@ class PrunedNodeViewHolderSpec extends ErgoPropertyTest with NodeViewTestOps wit
private val BlockInterval = 2.minutes
def prunedSettings(blocksToKeep: Int): ErgoSettings = {
- val defaultSettings = ErgoSettings.read()
+ val defaultSettings = ErgoSettingsReader.read()
defaultSettings.copy(
chainSettings = defaultSettings.chainSettings.copy(
powScheme = new DefaultFakePowScheme(defaultSettings.chainSettings.powScheme.k, defaultSettings.chainSettings.powScheme.n),
diff --git a/src/test/scala/org/ergoplatform/nodeView/wallet/ErgoWalletSpec.scala b/src/test/scala/org/ergoplatform/nodeView/wallet/ErgoWalletSpec.scala
index 5f5967d4d3..73ef39d8ee 100644
--- a/src/test/scala/org/ergoplatform/nodeView/wallet/ErgoWalletSpec.scala
+++ b/src/test/scala/org/ergoplatform/nodeView/wallet/ErgoWalletSpec.scala
@@ -57,7 +57,7 @@ class ErgoWalletSpec extends ErgoPropertyTest with WalletTestOps with Eventually
log.info(s"Payment request $req")
val tx = await(wallet.generateTransaction(req)).get
log.info(s"Generated transaction $tx")
- val context = new ErgoStateContext(Seq(genesisBlock.header), Some(genesisBlock.extension), startDigest, parameters, validationSettingsNoIl, VotingData.empty)
+ val context = new ErgoStateContext(Seq(genesisBlock.header), Some(genesisBlock.extension), startDigest, parameters, validationSettingsNoIl, VotingData.empty)(settings.chainSettings)
val boxesToSpend = tx.inputs.map(i => genesisTx.outputs.find(o => java.util.Arrays.equals(o.id, i.boxId)).get)
tx.statefulValidity(boxesToSpend, emptyDataBoxes, context) shouldBe 'success
val block = makeNextBlock(getUtxoState, Seq(tx))
@@ -112,7 +112,7 @@ class ErgoWalletSpec extends ErgoPropertyTest with WalletTestOps with Eventually
startDigest,
parameters,
validationSettingsNoIl,
- VotingData.empty)
+ VotingData.empty)(settings.chainSettings)
val boxesToSpend = tx.inputs.map(i => genesisTx.outputs.find(o => java.util.Arrays.equals(o.id, i.boxId)).get)
tx.statefulValidity(boxesToSpend, emptyDataBoxes, context) shouldBe 'success
}
@@ -371,7 +371,7 @@ class ErgoWalletSpec extends ErgoPropertyTest with WalletTestOps with Eventually
startDigest,
parameters,
validationSettingsNoIl,
- VotingData.empty)
+ VotingData.empty)(settings.chainSettings)
val boxesToSpend = tx.inputs.map(i => genesisTx.outputs.find(o => java.util.Arrays.equals(o.id, i.boxId)).get)
tx.statefulValidity(boxesToSpend, emptyDataBoxes, context) shouldBe 'success
@@ -388,7 +388,7 @@ class ErgoWalletSpec extends ErgoPropertyTest with WalletTestOps with Eventually
log.info(s"Payment requests 2 $req2")
val tx2 = await(wallet.generateTransaction(req2)).get
log.info(s"Generated transaction $tx2")
- val context2 = new ErgoStateContext(Seq(block.header), Some(block.extension), startDigest, parameters, validationSettingsNoIl, VotingData.empty)
+ val context2 = new ErgoStateContext(Seq(block.header), Some(block.extension), startDigest, parameters, validationSettingsNoIl, VotingData.empty)(settings.chainSettings)
val knownBoxes = tx.outputs ++ genesisTx.outputs
val boxesToSpend2 = tx2.inputs.map(i => knownBoxes.find(o => java.util.Arrays.equals(o.id, i.boxId)).get)
tx2.statefulValidity(boxesToSpend2, emptyDataBoxes, context2) shouldBe 'success
diff --git a/src/test/scala/org/ergoplatform/nodeView/wallet/persistence/WalletRegistrySpec.scala b/src/test/scala/org/ergoplatform/nodeView/wallet/persistence/WalletRegistrySpec.scala
index 6b5dfb4977..b3f5581981 100644
--- a/src/test/scala/org/ergoplatform/nodeView/wallet/persistence/WalletRegistrySpec.scala
+++ b/src/test/scala/org/ergoplatform/nodeView/wallet/persistence/WalletRegistrySpec.scala
@@ -6,11 +6,11 @@ import org.ergoplatform.db.DBSpec
import org.ergoplatform.nodeView.wallet.WalletScanLogic.{ScanResults, SpentInputData}
import org.ergoplatform.utils.generators.WalletGenerators
import org.ergoplatform.wallet.boxes.TrackedBox
+import org.ergoplatform.core.VersionTag
import org.scalacheck.Gen
import org.scalatest.flatspec.AnyFlatSpec
import org.scalatest.matchers.should.Matchers
import org.scalatestplus.scalacheck.ScalaCheckPropertyChecks
-import scorex.core.VersionTag
import scorex.util.encode.Base16
import scala.collection.compat.immutable.ArraySeq
diff --git a/src/test/scala/org/ergoplatform/sanity/ErgoSanity.scala b/src/test/scala/org/ergoplatform/sanity/ErgoSanity.scala
index f40b10c22a..59f54536df 100644
--- a/src/test/scala/org/ergoplatform/sanity/ErgoSanity.scala
+++ b/src/test/scala/org/ergoplatform/sanity/ErgoSanity.scala
@@ -1,7 +1,7 @@
package org.ergoplatform.sanity
import akka.actor.ActorRef
-import org.ergoplatform.ErgoBox
+import org.ergoplatform.{ErgoBox, PersistentNodeViewModifier}
import org.ergoplatform.modifiers.history.header.Header
import org.ergoplatform.modifiers.history.BlockTransactions
import org.ergoplatform.modifiers.mempool.{ErgoTransaction, UnconfirmedTransaction}
@@ -14,16 +14,16 @@ import org.ergoplatform.nodeView.state.{DigestState, ErgoState, UtxoState}
import org.ergoplatform.sanity.ErgoSanity._
import org.ergoplatform.settings.ErgoSettings
import org.ergoplatform.settings.Constants.HashLength
+import org.ergoplatform.testkit.generators.{ModifierProducerTemplateItem, SynInvalid, Valid}
+import org.ergoplatform.testkit.properties.HistoryTests
+import org.ergoplatform.testkit.properties.mempool.{MempoolRemovalTest, MempoolTransactionsTest}
+import org.ergoplatform.testkit.properties.state.StateApplicationTest
import org.ergoplatform.utils.{ErgoTestHelpers, HistoryTestHelpers}
+import org.ergoplatform.core.bytesToId
import org.scalacheck.Gen
import scorex.core.network.DeliveryTracker
-import scorex.core.{PersistentNodeViewModifier, bytesToId}
import scorex.crypto.authds.ADDigest
import scorex.crypto.hash.{Blake2b256, Digest32}
-import scorex.testkit.generators.{ModifierProducerTemplateItem, SynInvalid, Valid}
-import scorex.testkit.properties._
-import scorex.testkit.properties.mempool.{MempoolRemovalTest, MempoolTransactionsTest}
-import scorex.testkit.properties.state.StateApplicationTest
import scorex.utils.Random
import scala.concurrent.ExecutionContext
diff --git a/src/test/scala/org/ergoplatform/sanity/ErgoSanityDigest.scala b/src/test/scala/org/ergoplatform/sanity/ErgoSanityDigest.scala
index d9b07a50e7..0b7d947f44 100644
--- a/src/test/scala/org/ergoplatform/sanity/ErgoSanityDigest.scala
+++ b/src/test/scala/org/ergoplatform/sanity/ErgoSanityDigest.scala
@@ -5,19 +5,19 @@ import akka.testkit.TestProbe
import org.ergoplatform.modifiers.ErgoFullBlock
import org.ergoplatform.modifiers.history.BlockTransactions
import org.ergoplatform.modifiers.history.header.HeaderSerializer
-import org.ergoplatform.network.ErgoNodeViewSynchronizer.ReceivableMessages.{ChangedHistory, ChangedMempool}
+import org.ergoplatform.network.ErgoNodeViewSynchronizerMessages.{ChangedHistory, ChangedMempool}
import org.ergoplatform.network.ErgoSyncTracker
import org.ergoplatform.nodeView.history.ErgoSyncInfoMessageSpec
import org.ergoplatform.nodeView.mempool.ErgoMemPool
import org.ergoplatform.nodeView.state.wrapped.{WrappedDigestState, WrappedUtxoState}
import org.ergoplatform.nodeView.state.{DigestState, StateType}
import org.ergoplatform.sanity.ErgoSanity._
-import org.ergoplatform.settings.ErgoSettings
+import org.ergoplatform.settings.ErgoSettingsReader
import org.scalacheck.Gen
-import scorex.core.idToBytes
+import org.ergoplatform.core.idToBytes
import scorex.core.network.{ConnectedPeer, DeliveryTracker}
-import scorex.core.network.peer.PeerInfo
-import scorex.core.serialization.ErgoSerializer
+import org.ergoplatform.network.peer.PeerInfo
+import org.ergoplatform.serialization.ErgoSerializer
import scala.concurrent.ExecutionContextExecutor
@@ -58,7 +58,7 @@ class ErgoSanityDigest extends ErgoSanity[DIGEST_ST] {
val h = historyGen.sample.get
@SuppressWarnings(Array("org.wartremover.warts.OptionPartial"))
val s = stateGen.sample.get
- val settings = ErgoSettings.read()
+ val settings = ErgoSettingsReader.read()
val pool = ErgoMemPool.empty(settings)
val v = h.bestFullBlockIdOpt.orElse(h.bestHeaderIdOpt)
v.foreach(id => s.store.update(idToBytes(id), Seq(), Seq()).get)
diff --git a/src/test/scala/org/ergoplatform/sanity/ErgoSanityUTXO.scala b/src/test/scala/org/ergoplatform/sanity/ErgoSanityUTXO.scala
index ef6107e35b..a7e55e929e 100644
--- a/src/test/scala/org/ergoplatform/sanity/ErgoSanityUTXO.scala
+++ b/src/test/scala/org/ergoplatform/sanity/ErgoSanityUTXO.scala
@@ -5,19 +5,19 @@ import akka.testkit.TestProbe
import org.ergoplatform.modifiers.ErgoFullBlock
import org.ergoplatform.modifiers.history.BlockTransactions
import org.ergoplatform.modifiers.history.header.{Header, HeaderSerializer}
-import org.ergoplatform.network.ErgoNodeViewSynchronizer.ReceivableMessages.{ChangedHistory, ChangedMempool}
+import org.ergoplatform.network.ErgoNodeViewSynchronizerMessages.{ChangedHistory, ChangedMempool}
import org.ergoplatform.network.ErgoSyncTracker
import org.ergoplatform.nodeView.history.ErgoSyncInfoMessageSpec
import org.ergoplatform.nodeView.mempool.ErgoMemPool
import org.ergoplatform.nodeView.state.StateType
import org.ergoplatform.nodeView.state.wrapped.WrappedUtxoState
import org.ergoplatform.sanity.ErgoSanity._
-import org.ergoplatform.settings.ErgoSettings
+import org.ergoplatform.settings.ErgoSettingsReader
import org.ergoplatform.utils.ErgoTestHelpers
import org.scalacheck.Gen
import scorex.core.network.{ConnectedPeer, DeliveryTracker}
-import scorex.core.network.peer.PeerInfo
-import scorex.core.serialization.ErgoSerializer
+import org.ergoplatform.network.peer.PeerInfo
+import org.ergoplatform.serialization.ErgoSerializer
import scala.concurrent.ExecutionContextExecutor
@@ -55,7 +55,7 @@ class ErgoSanityUTXO extends ErgoSanity[UTXO_ST] with ErgoTestHelpers {
val h = historyGen.sample.get
@SuppressWarnings(Array("org.wartremover.warts.OptionPartial"))
val s = stateGen.sample.get
- val settings = ErgoSettings.read()
+ val settings = ErgoSettingsReader.read()
val pool = ErgoMemPool.empty(settings)
implicit val ec: ExecutionContextExecutor = system.dispatcher
val ncProbe = TestProbe("NetworkControllerProbe")
diff --git a/src/test/scala/org/ergoplatform/serialization/JsonSerializationSpec.scala b/src/test/scala/org/ergoplatform/serialization/JsonSerializationSpec.scala
index 016696d708..09ff24da54 100644
--- a/src/test/scala/org/ergoplatform/serialization/JsonSerializationSpec.scala
+++ b/src/test/scala/org/ergoplatform/serialization/JsonSerializationSpec.scala
@@ -4,7 +4,7 @@ import io.circe.syntax._
import io.circe.{ACursor, Decoder, Encoder, Json}
import org.ergoplatform.ErgoBox
import org.ergoplatform.ErgoBox.{AdditionalRegisters, NonMandatoryRegisterId}
-import org.ergoplatform.http.api.ApiCodecs
+import org.ergoplatform.http.api.{ApiCodecs, ApiExtraCodecs, ApiRequestsCodecs}
import org.ergoplatform.http.api.ApiEncoderOption.HideDetails.implicitValue
import org.ergoplatform.http.api.ApiEncoderOption.{Detalization, ShowDetails}
import org.ergoplatform.modifiers.ErgoFullBlock
@@ -12,7 +12,7 @@ import org.ergoplatform.modifiers.history.popow.NipopowProof
import org.ergoplatform.modifiers.mempool.UnsignedErgoTransaction
import org.ergoplatform.nodeView.wallet.requests._
import org.ergoplatform.sdk.wallet.secrets.{DhtSecretKey, DlogSecretKey}
-import org.ergoplatform.settings.{Algos, ErgoSettings}
+import org.ergoplatform.settings.{Algos, ErgoSettingsReader}
import org.ergoplatform.utils.ErgoPropertyTest
import org.ergoplatform.utils.generators.WalletGenerators
import org.ergoplatform.wallet.Constants.ScanId
@@ -24,7 +24,11 @@ import sigmastate.Values.{ErgoTree, EvaluatedValue}
import scala.util.Random
-class JsonSerializationSpec extends ErgoPropertyTest with WalletGenerators with ApiCodecs {
+class JsonSerializationSpec extends ErgoPropertyTest
+ with WalletGenerators
+ with ApiCodecs
+ with ApiRequestsCodecs
+ with ApiExtraCodecs {
property("ErgoFullBlock should be encoded into JSON and decoded back correctly") {
@@ -52,7 +56,7 @@ class JsonSerializationSpec extends ErgoPropertyTest with WalletGenerators with
}
property("PaymentRequest should be serialized to json") {
- val ergoSettings = ErgoSettings.read()
+ val ergoSettings = ErgoSettingsReader.read()
implicit val requestEncoder: Encoder[PaymentRequest] = new PaymentRequestEncoder(ergoSettings)
implicit val requestDecoder: Decoder[PaymentRequest] = new PaymentRequestDecoder(ergoSettings)
forAll(paymentRequestGen) { request =>
@@ -88,7 +92,7 @@ class JsonSerializationSpec extends ErgoPropertyTest with WalletGenerators with
}
property("AssetIssueRequest should be serialized to json") {
- val ergoSettings = ErgoSettings.read()
+ val ergoSettings = ErgoSettingsReader.read()
implicit val requestEncoder: Encoder[AssetIssueRequest] = new AssetIssueRequestEncoder(ergoSettings)
implicit val requestDecoder: Decoder[AssetIssueRequest] = new AssetIssueRequestDecoder(ergoSettings)
forAll(assetIssueRequestGen) { request =>
diff --git a/src/test/scala/org/ergoplatform/serialization/SerializationTests.scala b/src/test/scala/org/ergoplatform/serialization/SerializationTests.scala
index 65ac78905d..c8a2c35dbd 100644
--- a/src/test/scala/org/ergoplatform/serialization/SerializationTests.scala
+++ b/src/test/scala/org/ergoplatform/serialization/SerializationTests.scala
@@ -6,15 +6,15 @@ import org.ergoplatform.modifiers.history.extension.ExtensionSerializer
import org.ergoplatform.modifiers.history.header.{Header, HeaderSerializer}
import org.ergoplatform.modifiers.history.popow.NipopowProofSerializer
import org.ergoplatform.modifiers.mempool.ErgoTransactionSerializer
+import org.ergoplatform.network.ErgoNodeViewSynchronizer
import org.ergoplatform.nodeView.history.ErgoSyncInfoSerializer
import org.ergoplatform.nodeView.wallet.persistence.WalletDigestSerializer
import org.ergoplatform.nodeView.state.ErgoStateContextSerializer
-import org.ergoplatform.settings.{Constants, ErgoValidationSettings, ErgoValidationSettingsSerializer, ErgoValidationSettingsUpdateSerializer}
+import org.ergoplatform.settings.{ErgoValidationSettings, ErgoValidationSettingsSerializer, ErgoValidationSettingsUpdateSerializer}
import org.ergoplatform.utils.ErgoPropertyTest
import org.ergoplatform.utils.generators.WalletGenerators
import org.scalacheck.Gen
import org.scalatest.Assertion
-import scorex.core.serialization.ErgoSerializer
class SerializationTests extends ErgoPropertyTest with WalletGenerators with scorex.testkit.SerializationTests {
@@ -30,7 +30,7 @@ class SerializationTests extends ErgoPropertyTest with WalletGenerators with sco
property("Serializers should be defined for all block sections") {
val block = invalidErgoFullBlockGen.sample.get
block.toSeq.foreach { s =>
- Constants.modifierSerializers.get(s.modifierTypeId) should not be None
+ ErgoNodeViewSynchronizer.modifierSerializers.get(s.modifierTypeId) should not be None
}
}
@@ -48,7 +48,7 @@ class SerializationTests extends ErgoPropertyTest with WalletGenerators with sco
}
property("ErgoStateContext serialization") {
- val serializer = ErgoStateContextSerializer(settings)
+ val serializer = ErgoStateContextSerializer(settings.chainSettings)
val b = ergoStateContextGen.sample.get
val recovered = serializer.parseBytes(serializer.toBytes(b))
serializer.toBytes(b) shouldEqual serializer.toBytes(recovered)
diff --git a/src/test/scala/org/ergoplatform/settings/ErgoSettingsSpecification.scala b/src/test/scala/org/ergoplatform/settings/ErgoSettingsSpecification.scala
index e222ec2d88..7d52cc5f71 100644
--- a/src/test/scala/org/ergoplatform/settings/ErgoSettingsSpecification.scala
+++ b/src/test/scala/org/ergoplatform/settings/ErgoSettingsSpecification.scala
@@ -1,9 +1,8 @@
package org.ergoplatform.settings
-import org.ergoplatform.nodeView.mempool.ErgoMemPool.SortingOption
+import org.ergoplatform.nodeView.mempool.ErgoMemPoolUtils.SortingOption
import org.ergoplatform.nodeView.state.StateType
import org.ergoplatform.utils.ErgoPropertyTest
-import scorex.core.settings.RESTApiSettings
import java.net.{InetSocketAddress, URL}
import scala.concurrent.duration._
@@ -14,12 +13,12 @@ class ErgoSettingsSpecification extends ErgoPropertyTest {
private val txSizeLimit = initSettings.nodeSettings.maxTransactionSize
property("should keep data user home by default") {
- val settings = ErgoSettings.read()
+ val settings = ErgoSettingsReader.read()
settings.directory shouldBe System.getProperty("user.dir") + "/.ergo_test/data"
}
property("should read default settings") {
- val settings = ErgoSettings.read()
+ val settings = ErgoSettingsReader.read()
settings.nodeSettings shouldBe NodeConfigurationSettings(
StateType.Utxo,
verifyTransactions = true,
@@ -68,7 +67,7 @@ class ErgoSettingsSpecification extends ErgoPropertyTest {
}
property("should read user settings from json file") {
- val settings = ErgoSettings.read(Args(Some("src/test/resources/settings.json"), None))
+ val settings = ErgoSettingsReader.read(Args(Some("src/test/resources/settings.json"), None))
settings.nodeSettings shouldBe NodeConfigurationSettings(
StateType.Utxo,
verifyTransactions = true,
@@ -110,7 +109,7 @@ class ErgoSettingsSpecification extends ErgoPropertyTest {
}
property("should read user settings from HOCON file") {
- val settings = ErgoSettings.read(Args(Some("src/test/resources/settings.conf"), None))
+ val settings = ErgoSettingsReader.read(Args(Some("src/test/resources/settings.conf"), None))
settings.nodeSettings shouldBe NodeConfigurationSettings(
StateType.Utxo,
verifyTransactions = true,
@@ -162,7 +161,7 @@ class ErgoSettingsSpecification extends ErgoPropertyTest {
"http://example.com?foo=bar"
).map(new URL(_))
- invalidUrls.forall(ErgoSettings.invalidRestApiUrl) shouldBe true
+ invalidUrls.forall(ErgoSettingsReader.invalidRestApiUrl) shouldBe true
val validUrls =
List(
@@ -172,7 +171,7 @@ class ErgoSettingsSpecification extends ErgoPropertyTest {
"http://82.90.21.31:80"
).map(new URL(_))
- validUrls.forall(url => !ErgoSettings.invalidRestApiUrl(url)) shouldBe true
+ validUrls.forall(url => !ErgoSettingsReader.invalidRestApiUrl(url)) shouldBe true
}
}
diff --git a/src/test/scala/org/ergoplatform/settings/VotingSpecification.scala b/src/test/scala/org/ergoplatform/settings/VotingSpecification.scala
index 2923aa7b31..1d444969e5 100644
--- a/src/test/scala/org/ergoplatform/settings/VotingSpecification.scala
+++ b/src/test/scala/org/ergoplatform/settings/VotingSpecification.scala
@@ -38,7 +38,7 @@ class VotingSpecification extends ErgoPropertyTest {
Seq(VR.CheckDeserializedScriptType.id -> DisabledRule, VR.CheckValidOpCode.id -> ReplacedRule((VR.FirstRuleId + 11).toShort)))
private val proposedUpdate2 = ErgoValidationSettingsUpdate(Seq(ValidationRules.fbOperationFailed), Seq())
val ctx: ErgoStateContext = {
- new ErgoStateContext(Seq.empty, None, genesisStateDigest, parameters, validationSettingsNoIl, VotingData.empty)(updSettings)
+ new ErgoStateContext(Seq.empty, None, genesisStateDigest, parameters, validationSettingsNoIl, VotingData.empty)(updSettings.chainSettings)
.upcoming(org.ergoplatform.mining.group.generator, 0L, settings.chainSettings.initialNBits, Array.fill(3)(0.toByte), emptyVSUpdate, 0.toByte)
}
val initialVs: ErgoValidationSettings = ctx.validationSettings
@@ -100,7 +100,7 @@ class VotingSpecification extends ErgoPropertyTest {
property("voting for non-existing parameter") {
val p: Parameters = Parameters(2, Map(BlockVersion -> 0), proposedUpdate)
val vr: VotingData = VotingData.empty
- val esc = new ErgoStateContext(Seq(), None, ADDigest @@ Array.fill(33)(0: Byte), p, validationSettingsNoIl, vr)(updSettings)
+ val esc = new ErgoStateContext(Seq(), None, ADDigest @@ Array.fill(33)(0: Byte), p, validationSettingsNoIl, vr)(updSettings.chainSettings)
val invalidVote = 100: Byte
val votes = Array(invalidVote , NoParameter, NoParameter)
@@ -119,7 +119,7 @@ class VotingSpecification extends ErgoPropertyTest {
val p: Parameters = Parameters(2, Map(StorageFeeFactorIncrease -> kInit, BlockVersion -> 0), proposedUpdate)
val vr: VotingData = VotingData.empty
- val esc = new ErgoStateContext(Seq(), None, ADDigest @@ Array.fill(33)(0: Byte), p, validationSettingsNoIl, vr)(updSettings)
+ val esc = new ErgoStateContext(Seq(), None, ADDigest @@ Array.fill(33)(0: Byte), p, validationSettingsNoIl, vr)(updSettings.chainSettings)
val votes = Array(StorageFeeFactorIncrease, NoParameter, NoParameter)
val h = defaultHeaderGen.sample.get.copy(height = 2, votes = votes, version = 0: Byte)
val esc2 = process(esc, p, h).get
@@ -152,7 +152,7 @@ class VotingSpecification extends ErgoPropertyTest {
val p: Parameters = Parameters(1, Map(BlockVersion -> 0), proposedUpdate)
val vr: VotingData = VotingData.empty
- val esc0 = new ErgoStateContext(Seq(), None, ADDigest @@ Array.fill(33)(0: Byte), p, validationSettings, vr)(updSettings)
+ val esc0 = new ErgoStateContext(Seq(), None, ADDigest @@ Array.fill(33)(0: Byte), p, validationSettings, vr)(updSettings.chainSettings)
checkValidationSettings(esc0.validationSettings, emptyVSUpdate)
val forkVote = Array(SoftFork, NoParameter, NoParameter)
val emptyVotes = Array(NoParameter, NoParameter, NoParameter)
@@ -259,7 +259,7 @@ class VotingSpecification extends ErgoPropertyTest {
val forkVote = Array(SoftFork, NoParameter, NoParameter)
val emptyVotes = Array(NoParameter, NoParameter, NoParameter)
- val esc0 = new ErgoStateContext(Seq(), None, ADDigest @@ Array.fill(33)(0: Byte), p, validationSettingsNoIl, vr)(updSettings)
+ val esc0 = new ErgoStateContext(Seq(), None, ADDigest @@ Array.fill(33)(0: Byte), p, validationSettingsNoIl, vr)(updSettings.chainSettings)
val h1 = defaultHeaderGen.sample.get.copy(votes = forkVote, version = 0: Byte, height = 1)
val esc1 = process(esc0, p, h1).get
@@ -317,7 +317,7 @@ class VotingSpecification extends ErgoPropertyTest {
property("hardfork - v2 - activation") {
val vr: VotingData = VotingData.empty
- val esc0 = new ErgoStateContext(Seq(), None, ADDigest @@ Array.fill(33)(0: Byte), parameters, ErgoValidationSettings.initial, vr)(updSettings)
+ val esc0 = new ErgoStateContext(Seq(), None, ADDigest @@ Array.fill(33)(0: Byte), parameters, ErgoValidationSettings.initial, vr)(updSettings.chainSettings)
val h1 = defaultHeaderGen.sample.get.copy(votes = Array.empty, version = 1: Byte, height = hfActivationHeight - 1)
val expectedParameters1 = Parameters(hfActivationHeight - 1, DefaultParameters, ErgoValidationSettingsUpdate.empty)
val esc1 = process(esc0, expectedParameters1, h1).get
diff --git a/src/test/scala/org/ergoplatform/testkit/SerializationTests.scala b/src/test/scala/org/ergoplatform/testkit/SerializationTests.scala
new file mode 100644
index 0000000000..f7a21004cc
--- /dev/null
+++ b/src/test/scala/org/ergoplatform/testkit/SerializationTests.scala
@@ -0,0 +1,16 @@
+package org.ergoplatform.testkit
+
+import org.scalacheck.Gen
+import org.scalatest.Assertion
+import org.scalatest.matchers.should.Matchers
+import org.scalatestplus.scalacheck.ScalaCheckPropertyChecks
+import org.ergoplatform.serialization.ErgoSerializer
+
+trait SerializationTests extends ScalaCheckPropertyChecks with Matchers {
+ def checkSerializationRoundtrip[A](generator: Gen[A], serializer: ErgoSerializer[A]): Assertion = {
+ forAll(generator) { b: A =>
+ val recovered = serializer.parseBytes(serializer.toBytes(b))
+ serializer.toBytes(b) shouldEqual serializer.toBytes(recovered)
+ }
+ }
+}
diff --git a/src/test/scala/org/ergoplatform/testkit/TestkitHelpers.scala b/src/test/scala/org/ergoplatform/testkit/TestkitHelpers.scala
new file mode 100644
index 0000000000..d38259c0d8
--- /dev/null
+++ b/src/test/scala/org/ergoplatform/testkit/TestkitHelpers.scala
@@ -0,0 +1,10 @@
+package org.ergoplatform.testkit
+
+trait TestkitHelpers {
+
+ val MinTestsOk = 100
+
+ def check(minTestsOk:Int)(f: Int => Unit): Unit = (0 until minTestsOk) foreach (i => f(i))
+
+ def check(f: Int => Unit): Unit = check(MinTestsOk)(f)
+}
diff --git a/src/test/scala/org/ergoplatform/testkit/generators/AllModifierProducers.scala b/src/test/scala/org/ergoplatform/testkit/generators/AllModifierProducers.scala
new file mode 100644
index 0000000000..ba9d379b59
--- /dev/null
+++ b/src/test/scala/org/ergoplatform/testkit/generators/AllModifierProducers.scala
@@ -0,0 +1,11 @@
+package org.ergoplatform.testkit.generators
+
+import org.ergoplatform.nodeView.state.ErgoState
+
+
+trait AllModifierProducers[ST <: ErgoState[ST]]
+ extends SemanticallyValidModifierProducer[ST]
+ with SyntacticallyTargetedModifierProducer
+ with ArbitraryTransactionsCarryingModifierProducer
+ with TotallyValidModifierProducer[ST]
+ with SemanticallyValidTransactionsCarryingModifier[ST]
diff --git a/src/test/scala/org/ergoplatform/testkit/generators/ArbitraryTransactionsCarryingModifierProducer.scala b/src/test/scala/org/ergoplatform/testkit/generators/ArbitraryTransactionsCarryingModifierProducer.scala
new file mode 100644
index 0000000000..4fc2d9244c
--- /dev/null
+++ b/src/test/scala/org/ergoplatform/testkit/generators/ArbitraryTransactionsCarryingModifierProducer.scala
@@ -0,0 +1,12 @@
+package org.ergoplatform.testkit.generators
+
+import org.ergoplatform.modifiers.history.BlockTransactions
+import org.ergoplatform.modifiers.mempool.ErgoTransaction
+import org.ergoplatform.nodeView.mempool.ErgoMemPool
+/**
+ * Produces a modifier with transactions, not necessary syntatically or semantically valid
+ */
+trait ArbitraryTransactionsCarryingModifierProducer{
+
+def modifierWithTransactions(memoryPoolOpt: Option[ErgoMemPool], customTransactionsOpt: Option[Seq[ErgoTransaction]]): BlockTransactions
+}
diff --git a/src/test/scala/org/ergoplatform/testkit/generators/CoreGenerators.scala b/src/test/scala/org/ergoplatform/testkit/generators/CoreGenerators.scala
new file mode 100644
index 0000000000..d7ba97731b
--- /dev/null
+++ b/src/test/scala/org/ergoplatform/testkit/generators/CoreGenerators.scala
@@ -0,0 +1,9 @@
+package org.ergoplatform.testkit.generators
+
+import org.scalacheck.Gen
+import org.ergoplatform.core.{VersionTag, idToVersion}
+
+//Generators of objects from scorex-core
+trait CoreGenerators extends ObjectGenerators {
+ lazy val versionTagGen: Gen[VersionTag] = modifierIdGen.map(id => idToVersion(id))
+}
diff --git a/src/test/scala/org/ergoplatform/testkit/generators/CustomModifierProducer.scala b/src/test/scala/org/ergoplatform/testkit/generators/CustomModifierProducer.scala
new file mode 100644
index 0000000000..ab4e38e421
--- /dev/null
+++ b/src/test/scala/org/ergoplatform/testkit/generators/CustomModifierProducer.scala
@@ -0,0 +1,17 @@
+package org.ergoplatform.testkit.generators
+
+import org.ergoplatform.modifiers.BlockSection
+import org.ergoplatform.nodeView.history.ErgoHistory
+import org.ergoplatform.nodeView.state.ErgoState
+
+sealed trait ModifierProducerTemplateItem
+
+case object SynInvalid extends ModifierProducerTemplateItem
+case object Valid extends ModifierProducerTemplateItem
+
+trait CustomModifierProducer[ST <: ErgoState[ST]] {
+
+ def customModifiers(history: ErgoHistory,
+ state: ST,
+ template: Seq[ModifierProducerTemplateItem]): Seq[BlockSection]
+}
diff --git a/src/test/scala/org/ergoplatform/testkit/generators/ObjectGenerators.scala b/src/test/scala/org/ergoplatform/testkit/generators/ObjectGenerators.scala
new file mode 100644
index 0000000000..a676b243e3
--- /dev/null
+++ b/src/test/scala/org/ergoplatform/testkit/generators/ObjectGenerators.scala
@@ -0,0 +1,114 @@
+package org.ergoplatform.testkit.generators
+
+import java.net.{InetAddress, InetSocketAddress, URL}
+import akka.actor.ActorRef
+import akka.util.ByteString
+import org.ergoplatform.NodeViewModifier
+import org.ergoplatform.modifiers.NetworkObjectTypeId
+import org.ergoplatform.network.{ModePeerFeature, PeerFeature, PeerSpec, Version}
+import org.ergoplatform.nodeView.state.StateType
+import org.scalacheck.Gen.{const, some}
+import org.scalacheck.{Arbitrary, Gen}
+import org.ergoplatform.network.message.{InvData, ModifiersData}
+import org.ergoplatform.network.peer.{PeerInfo, RestApiUrlPeerFeature}
+import scorex.core.network.{ConnectedPeer, ConnectionDirection, ConnectionId, Incoming, Outgoing}
+import scorex.util.{ModifierId, bytesToId}
+
+trait ObjectGenerators {
+
+ val MaxVersion = 999
+ val MaxIp = 255
+ val MaxPort = 65535
+
+ val modePeerFeatureGen = for {
+ utxo <- Gen.oneOf(true, false)
+ stateType <- if(utxo) StateType.Utxo else StateType.Digest
+ verifyingTransactions <- Gen.oneOf(true, false)
+ popowSuffix <- Gen.option(smallInt)
+ blocksToKeep <- smallInt
+ } yield ModePeerFeature(stateType, verifyingTransactions, popowSuffix, blocksToKeep)
+
+ lazy val smallInt: Gen[Int] = Gen.choose(0, 20)
+
+ lazy val nonEmptyBytesGen: Gen[Array[Byte]] = Gen.nonEmptyListOf(Arbitrary.arbitrary[Byte])
+ .map(_.toArray).suchThat(_.length > 0)
+
+ lazy val nonEmptyByteStringGen: Gen[ByteString] = nonEmptyBytesGen.map(ByteString(_))
+
+ def genBoundedBytes(minSize: Int, maxSize: Int): Gen[Array[Byte]] = {
+ Gen.choose(minSize, maxSize) flatMap { sz => Gen.listOfN(sz, Arbitrary.arbitrary[Byte]).map(_.toArray) }
+ }
+
+ def genBytes(size: Int): Gen[Array[Byte]] = genBoundedBytes(size, size)
+
+ lazy val positiveLongGen: Gen[Long] = Gen.choose(1, Long.MaxValue)
+
+ lazy val positiveByteGen: Gen[Byte] = Gen.choose(1, Byte.MaxValue)
+
+
+ lazy val modifierIdGen: Gen[ModifierId] = Gen.listOfN(NodeViewModifier.ModifierIdSize, Arbitrary.arbitrary[Byte])
+ .map(id => bytesToId(id.toArray))
+
+ lazy val modifierTypeIdGen: Gen[NetworkObjectTypeId.Value] = Arbitrary.arbitrary[Byte].map(t => NetworkObjectTypeId.fromByte(t))
+
+ lazy val invDataGen: Gen[InvData] = for {
+ modifierTypeId: NetworkObjectTypeId.Value <- modifierTypeIdGen
+ modifierIds: Seq[ModifierId] <- Gen.nonEmptyListOf(modifierIdGen) if modifierIds.nonEmpty
+ } yield InvData(modifierTypeId, modifierIds)
+
+ lazy val modifierWithIdGen: Gen[(ModifierId, Array[Byte])] = for {
+ id <- modifierIdGen
+ mod <- nonEmptyBytesGen
+ } yield id -> mod
+
+ lazy val modifiersGen: Gen[ModifiersData] = for {
+ modifierTypeId: NetworkObjectTypeId.Value <- modifierTypeIdGen
+ modifiers: Map[ModifierId, Array[Byte]] <- Gen.nonEmptyMap(modifierWithIdGen).suchThat(_.nonEmpty)
+ } yield ModifiersData(modifierTypeId, modifiers)
+
+ lazy val appVersionGen: Gen[Version] = for {
+ fd <- Gen.choose(0: Byte, Byte.MaxValue)
+ sd <- Gen.choose(0: Byte, Byte.MaxValue)
+ td <- Gen.choose(0: Byte, Byte.MaxValue)
+ } yield Version(fd, sd, td)
+
+ lazy val inetSocketAddressGen: Gen[InetSocketAddress] = for {
+ ip1 <- Gen.choose(0, MaxIp)
+ ip2 <- Gen.choose(0, MaxIp)
+ ip3 <- Gen.choose(0, MaxIp)
+ ip4 <- Gen.choose(0, MaxIp)
+ port <- Gen.choose(0, MaxPort)
+ } yield new InetSocketAddress(InetAddress.getByName(s"$ip1.$ip2.$ip3.$ip4"), port)
+
+ lazy val urlGen: Gen[URL] = for {
+ protocol <- Gen.frequency(5 -> const("http://"), 5 -> const("https://"))
+ ip1 <- Gen.choose(0, MaxIp)
+ ip2 <- Gen.choose(0, MaxIp)
+ ip3 <- Gen.choose(0, MaxIp)
+ ip4 <- Gen.choose(0, MaxIp)
+ host <- Gen.frequency(5 -> const(s"$ip1.$ip2.$ip3.$ip4"), 5 -> const("example.com"))
+ port <- Gen.choose(0, MaxPort)
+ suffix <- Gen.frequency(5 -> const("/"), 5 -> const(""))
+ } yield new URL(s"$protocol$host:$port$suffix")
+
+ lazy val connectionIdGen: Gen[ConnectionId] = for {
+ ip1 <- inetSocketAddressGen
+ ip2 <- inetSocketAddressGen
+ direction <- Gen.oneOf[ConnectionDirection](Seq[ConnectionDirection](Incoming, Outgoing))
+ } yield ConnectionId(ip1, ip2, direction)
+
+ def peerInfoGen: Gen[PeerInfo] = for {
+ peerSpec <- peerSpecGen
+ } yield PeerInfo(peerSpec, 0L, Some(Incoming), 0L)
+
+ def connectedPeerGen(peerRef: ActorRef): Gen[ConnectedPeer] = for {
+ connectionId <- connectionIdGen
+ peerInfo <- peerInfoGen
+ } yield ConnectedPeer(connectionId, peerRef, Some(peerInfo))
+
+ def peerSpecGen: Gen[PeerSpec] = for {
+ declaredAddress <- Gen.frequency(5 -> const(None), 5 -> some(inetSocketAddressGen))
+ features: Seq[PeerFeature] <- Gen.someOf(modePeerFeatureGen, urlGen.flatMap(url => RestApiUrlPeerFeature(url)))
+ version <- appVersionGen
+ } yield PeerSpec("ergoref", version, "ergo-node", declaredAddress, features)
+}
diff --git a/src/test/scala/org/ergoplatform/testkit/generators/SemanticallyInvalidModifierProducer.scala b/src/test/scala/org/ergoplatform/testkit/generators/SemanticallyInvalidModifierProducer.scala
new file mode 100644
index 0000000000..47cb9085aa
--- /dev/null
+++ b/src/test/scala/org/ergoplatform/testkit/generators/SemanticallyInvalidModifierProducer.scala
@@ -0,0 +1,8 @@
+package org.ergoplatform.testkit.generators
+
+import org.ergoplatform.modifiers.BlockSection
+import org.ergoplatform.nodeView.state.ErgoState
+
+trait SemanticallyInvalidModifierProducer[ST <: ErgoState[ST]] {
+ def semanticallyInvalidModifier(state: ST): BlockSection
+}
\ No newline at end of file
diff --git a/src/test/scala/org/ergoplatform/testkit/generators/SemanticallyValidModifierProducer.scala b/src/test/scala/org/ergoplatform/testkit/generators/SemanticallyValidModifierProducer.scala
new file mode 100644
index 0000000000..1dc87fead4
--- /dev/null
+++ b/src/test/scala/org/ergoplatform/testkit/generators/SemanticallyValidModifierProducer.scala
@@ -0,0 +1,10 @@
+package org.ergoplatform.testkit.generators
+
+import org.ergoplatform.modifiers.BlockSection
+import org.ergoplatform.nodeView.state.ErgoState
+
+trait SemanticallyValidModifierProducer[ST <: ErgoState[ST]] {
+ def semanticallyValidModifier(state: ST): BlockSection
+}
+
+
diff --git a/src/test/scala/org/ergoplatform/testkit/generators/SemanticallyValidTransactionsCarryingModifier.scala b/src/test/scala/org/ergoplatform/testkit/generators/SemanticallyValidTransactionsCarryingModifier.scala
new file mode 100644
index 0000000000..b57fb2d6ca
--- /dev/null
+++ b/src/test/scala/org/ergoplatform/testkit/generators/SemanticallyValidTransactionsCarryingModifier.scala
@@ -0,0 +1,12 @@
+package org.ergoplatform.testkit.generators
+
+import org.ergoplatform.modifiers.history.BlockTransactions
+import org.ergoplatform.modifiers.mempool.ErgoTransaction
+import org.ergoplatform.nodeView.state.ErgoState
+
+trait SemanticallyValidTransactionsCarryingModifier[ST <: ErgoState[ST]] {
+
+ def semanticallyValidModifier(state: ST): BlockTransactions
+ def genValidTransactionPair(state: ST): Seq[ErgoTransaction]
+ def semanticallyValidModifierWithCustomTransactions(state: ST, transactions: Seq[ErgoTransaction]): BlockTransactions
+}
diff --git a/src/test/scala/org/ergoplatform/testkit/generators/SyntacticallyTargetedModifierProducer.scala b/src/test/scala/org/ergoplatform/testkit/generators/SyntacticallyTargetedModifierProducer.scala
new file mode 100644
index 0000000000..172196f383
--- /dev/null
+++ b/src/test/scala/org/ergoplatform/testkit/generators/SyntacticallyTargetedModifierProducer.scala
@@ -0,0 +1,11 @@
+package org.ergoplatform.testkit.generators
+
+import org.ergoplatform.modifiers.BlockSection
+import org.ergoplatform.nodeView.history.ErgoHistory
+
+
+trait SyntacticallyTargetedModifierProducer {
+ def syntacticallyValidModifier(history: ErgoHistory): BlockSection
+
+ def syntacticallyInvalidModifier(history: ErgoHistory): BlockSection
+}
diff --git a/src/test/scala/org/ergoplatform/testkit/generators/TotallyValidModifierProducer.scala b/src/test/scala/org/ergoplatform/testkit/generators/TotallyValidModifierProducer.scala
new file mode 100644
index 0000000000..26b14b13d6
--- /dev/null
+++ b/src/test/scala/org/ergoplatform/testkit/generators/TotallyValidModifierProducer.scala
@@ -0,0 +1,13 @@
+package org.ergoplatform.testkit.generators
+
+import org.ergoplatform.modifiers.BlockSection
+import org.ergoplatform.nodeView.history.ErgoHistory
+import org.ergoplatform.nodeView.state.ErgoState
+
+
+trait TotallyValidModifierProducer[ST <: ErgoState[ST]] {
+
+ def totallyValidModifier(history: ErgoHistory, state: ST): BlockSection
+
+ def totallyValidModifiers(history: ErgoHistory, state: ST, count: Int): Seq[BlockSection]
+}
diff --git a/src/test/scala/org/ergoplatform/testkit/properties/HistoryTests.scala b/src/test/scala/org/ergoplatform/testkit/properties/HistoryTests.scala
new file mode 100644
index 0000000000..93db38e540
--- /dev/null
+++ b/src/test/scala/org/ergoplatform/testkit/properties/HistoryTests.scala
@@ -0,0 +1,86 @@
+package org.ergoplatform.testkit.properties
+
+import org.ergoplatform.consensus.ModifierSemanticValidity.Valid
+import org.ergoplatform.modifiers.BlockSection
+import org.ergoplatform.nodeView.history.ErgoHistory
+import org.ergoplatform.testkit.TestkitHelpers
+import org.ergoplatform.testkit.generators.SyntacticallyTargetedModifierProducer
+import org.scalacheck.Gen
+import org.scalatest.matchers.should.Matchers
+import org.scalatest.propspec.AnyPropSpec
+import org.scalatestplus.scalacheck.ScalaCheckPropertyChecks
+import scorex.util.ScorexLogging
+
+
+trait HistoryTests
+ extends AnyPropSpec
+ with ScalaCheckPropertyChecks
+ with Matchers
+ with ScorexLogging
+ with TestkitHelpers
+ with SyntacticallyTargetedModifierProducer {
+
+ val historyGen: Gen[ErgoHistory]
+
+ lazy val generatorWithValidModifier: Gen[(ErgoHistory, BlockSection)] = {
+ historyGen.map { h => (h, syntacticallyValidModifier(h))}
+ }
+
+ lazy val generatorWithInvalidModifier: Gen[(ErgoHistory, BlockSection)] = {
+ historyGen.map { h => (h, syntacticallyInvalidModifier(h))}
+ }
+
+ private def propertyNameGenerator(propName: String): String = s"HistoryTests: $propName"
+
+ property(propertyNameGenerator("applicable with valid modifier")) {
+ forAll(generatorWithValidModifier) { case (h, m) => h.applicableTry(m) shouldBe 'success}
+ }
+
+ property(propertyNameGenerator("append valid modifier")) {
+ forAll(generatorWithValidModifier) { case (h, m) => h.append(m).isSuccess shouldBe true }
+ }
+
+ property(propertyNameGenerator("contain valid modifier after appending")) {
+ forAll(generatorWithValidModifier) { case (h, m) =>
+ h.append(m)
+ h.contains(m) shouldBe true
+ }
+ }
+
+ property(propertyNameGenerator("find valid modifier after appending by modifierId")) {
+ forAll(generatorWithValidModifier) { case (h, m) =>
+ h.append(m)
+ h.modifierById(m.id) shouldBe defined
+ }
+ }
+
+ property(propertyNameGenerator("report semantically validation after appending valid modifier")) {
+ forAll(generatorWithValidModifier) { case (h, m) =>
+ h.append(m)
+ h.reportModifierIsValid(m).get
+ h.isSemanticallyValid(m.id) shouldBe Valid
+ }
+ }
+
+ property(propertyNameGenerator("not applicable with invalid modifier")) {
+ forAll(generatorWithInvalidModifier) { case (h, m) => h.applicableTry(m) shouldBe 'failure}
+ }
+
+ property(propertyNameGenerator("not append invalid modifier")) {
+ forAll(generatorWithInvalidModifier) { case (h, m) => h.append(m).isSuccess shouldBe false }
+ }
+
+ property(propertyNameGenerator("not contain invalid modifier after appending")) {
+ forAll(generatorWithInvalidModifier) { case (h, m) =>
+ h.append(m)
+ h.contains(m) shouldBe false
+ }
+ }
+
+ property(propertyNameGenerator("not finds valid modifier after appending by modifierId")) {
+ forAll(generatorWithInvalidModifier) { case (h, m) =>
+ h.append(m)
+ h.modifierById(m.id) shouldBe None
+ }
+ }
+}
diff --git a/src/test/scala/org/ergoplatform/testkit/properties/NodeViewHolderTests.scala b/src/test/scala/org/ergoplatform/testkit/properties/NodeViewHolderTests.scala
new file mode 100644
index 0000000000..a810831554
--- /dev/null
+++ b/src/test/scala/org/ergoplatform/testkit/properties/NodeViewHolderTests.scala
@@ -0,0 +1,339 @@
+package org.ergoplatform.testkit.properties
+
+import akka.actor._
+import akka.testkit.TestProbe
+import org.ergoplatform.modifiers.BlockSection
+import org.ergoplatform.nodeView.history.ErgoHistory
+import org.scalatest.matchers.should.Matchers
+import org.scalatest.propspec.AnyPropSpec
+import org.ergoplatform.nodeView.ErgoNodeViewHolder.CurrentView
+import org.ergoplatform.nodeView.ErgoNodeViewHolder.ReceivableMessages.GetDataFromCurrentView
+import org.ergoplatform.network.ErgoNodeViewSynchronizerMessages._
+import org.ergoplatform.nodeView.LocallyGeneratedModifier
+import org.ergoplatform.nodeView.state.ErgoState
+import org.ergoplatform.testkit.generators.{CustomModifierProducer, ModifierProducerTemplateItem, ObjectGenerators, SemanticallyInvalidModifierProducer, SynInvalid, SyntacticallyTargetedModifierProducer, TotallyValidModifierProducer, Valid}
+import org.ergoplatform.testkit.utils.AkkaFixture
+import scorex.testkit.generators._
+import scorex.util.ScorexLogging
+
+import scala.concurrent.Await
+import scala.concurrent.duration._
+
+@SuppressWarnings(Array("org.wartremover.warts.TraversableOps"))
+trait NodeViewHolderTests[ST <: ErgoState[ST]]
+ extends AnyPropSpec
+ with Matchers
+ with ScorexLogging
+ with SyntacticallyTargetedModifierProducer
+ with TotallyValidModifierProducer[ST]
+ with SemanticallyInvalidModifierProducer[ST]
+ with CustomModifierProducer[ST]
+ with ObjectGenerators {
+
+ def nodeViewHolder(implicit system: ActorSystem): (ActorRef, TestProbe, BlockSection, ST, ErgoHistory)
+
+ class HolderFixture extends AkkaFixture {
+ @SuppressWarnings(Array("org.wartremover.warts.PublicInference"))
+ val (node, eventListener, mod, s, h) = nodeViewHolder
+ }
+
+ private def withFixture(testCode: HolderFixture => Any): Unit = {
+ val fixture = new HolderFixture
+ try {
+ testCode(fixture)
+ } finally {
+ Await.result(fixture.system.terminate(), Duration.Inf)
+ }
+ }
+
+ private type CurrentViewType = CurrentView[ST]
+
+ private def withView[T](node: ActorRef)(f: CurrentViewType => T)
+ (implicit system: ActorSystem): T = {
+ val probe = TestProbe()
+ probe.send(node,
+ GetDataFromCurrentView[ST, CurrentViewType] { view => view })
+ val view = probe.expectMsgClass(10.seconds, classOf[CurrentViewType])
+ f(view)
+ }
+/* todo: fix
+ property("NodeViewHolder: modifiers from remote") {
+ withFixture { ctx =>
+ import ctx._
+ val p = TestProbe()
+
+ system.eventStream.subscribe(eventListener.ref, classOf[ModifiersRemovedFromCache])
+ p.send(node, ModifiersFromRemote(Seq(mod)))
+ eventListener.expectMsgType[ModifiersRemovedFromCache]
+ }
+ }*/
+
+ property("NodeViewHolder syntactically valid modifier subscription") {
+ withFixture { ctx =>
+ import ctx._
+ val p = TestProbe()
+
+ system.eventStream.subscribe(eventListener.ref, classOf[SyntacticallySuccessfulModifier])
+ p.send(node, GetDataFromCurrentView[ST, BlockSection] { v => totallyValidModifiers(v.history, v.state, 2).head })
+ val mod = p.expectMsgClass(classOf[BlockSection])
+ p.send(node, LocallyGeneratedModifier(mod))
+ eventListener.expectMsgType[SyntacticallySuccessfulModifier]
+ }
+ }
+
+ property("NodeViewHolder: syntactically failed modifier subscription") {
+ withFixture { ctx =>
+ import ctx._
+ val p = TestProbe()
+
+ system.eventStream.subscribe(eventListener.ref, classOf[SyntacticallyFailedModification])
+ val invalid = syntacticallyInvalidModifier(h)
+ p.send(node, LocallyGeneratedModifier(invalid))
+ eventListener.expectMsgType[SyntacticallyFailedModification]
+ }
+ }
+
+ property("NodeViewHolder: semantically valid modifier subscription") {
+ withFixture { ctx =>
+ import ctx._
+ val p = TestProbe()
+
+ system.eventStream.subscribe(eventListener.ref, classOf[SyntacticallySuccessfulModifier])
+ system.eventStream.subscribe(eventListener.ref, classOf[FullBlockApplied])
+ p.send(node, GetDataFromCurrentView[ST, BlockSection] { v => totallyValidModifiers(v.history, v.state, 2).head })
+ val mod = p.expectMsgClass(classOf[BlockSection])
+ p.send(node, LocallyGeneratedModifier(mod))
+ eventListener.expectMsgType[SyntacticallySuccessfulModifier]
+ eventListener.expectMsgType[FullBlockApplied]
+ }
+ }
+
+ property("NodeViewHolder: semantically failed modifier subscription") {
+ withFixture { ctx =>
+ import ctx._
+ val p = TestProbe()
+
+ system.eventStream.subscribe(eventListener.ref, classOf[SyntacticallySuccessfulModifier])
+ system.eventStream.subscribe(eventListener.ref, classOf[SemanticallyFailedModification])
+ p.send(node, GetDataFromCurrentView[ST, BlockSection] { v => semanticallyInvalidModifier(v.state) })
+ val invalid = p.expectMsgClass(classOf[BlockSection])
+ p.send(node, LocallyGeneratedModifier(invalid))
+ eventListener.expectMsgType[SyntacticallySuccessfulModifier]
+ eventListener.expectMsgType[SemanticallyFailedModification]
+ }
+ }
+
+ property("NodeViewHolder: syntactically/semantically valid modifier subscription") {
+ withFixture { ctx =>
+ import ctx._
+ val p = TestProbe()
+
+ system.eventStream.subscribe(eventListener.ref, classOf[SyntacticallySuccessfulModifier])
+ system.eventStream.subscribe(eventListener.ref, classOf[FullBlockApplied])
+ p.send(node, GetDataFromCurrentView[ST, BlockSection] { v => totallyValidModifiers(v.history, v.state, 2).head })
+ val mod = p.expectMsgClass(classOf[BlockSection])
+ p.send(node, LocallyGeneratedModifier(mod))
+ eventListener.expectMsgType[SyntacticallySuccessfulModifier]
+ eventListener.expectMsgType[FullBlockApplied]
+ }
+ }
+
+ property("NodeViewHolder: check state after creation") {
+ withFixture { ctx =>
+ import ctx._
+ val p = TestProbe()
+
+ p.send(node, GetDataFromCurrentView[ST, Boolean] { v =>
+ v.state.version == s.version
+ })
+ p.expectMsg(true)
+ }
+ }
+
+ property("NodeViewHolder: check that a valid modifier is applicable") {
+ withFixture { ctx =>
+ import ctx._
+ val p = TestProbe()
+
+ p.send(node, GetDataFromCurrentView[ST, Boolean] { v =>
+ v.history.applicableTry(mod).isSuccess
+ })
+ p.expectMsg(true)
+ }
+ }
+
+ property("NodeViewHolder: check that valid modifiers are applicable") {
+ withFixture { ctx =>
+ import ctx._
+ val p = TestProbe()
+
+ system.eventStream.subscribe(eventListener.ref, classOf[SyntacticallySuccessfulModifier])
+ system.eventStream.subscribe(eventListener.ref, classOf[SyntacticallyFailedModification])
+ p.send(node, GetDataFromCurrentView[ST, Seq[BlockSection]] { v =>
+ totallyValidModifiers(v.history, v.state, 10) //todo: fix magic number
+ })
+ val mods = p.expectMsgClass(classOf[Seq[BlockSection]])
+
+ mods.foreach { mod =>
+ p.send(node, LocallyGeneratedModifier(mod))
+ }
+
+ (1 to mods.size).foreach(_ => eventListener.expectMsgType[SyntacticallySuccessfulModifier])
+ }
+ }
+
+ property("NodeViewHolder: apply locally generated mod") {
+ withFixture { ctx =>
+ import ctx._
+ val p = TestProbe()
+
+ system.eventStream.subscribe(eventListener.ref, classOf[SyntacticallySuccessfulModifier])
+ system.eventStream.subscribe(eventListener.ref, classOf[SyntacticallyFailedModification])
+
+ val invalid = syntacticallyInvalidModifier(h)
+
+ p.send(node, LocallyGeneratedModifier(invalid))
+
+ eventListener.expectMsgType[SyntacticallyFailedModification]
+
+ p.send(node, LocallyGeneratedModifier(mod))
+
+ eventListener.expectMsgType[SyntacticallySuccessfulModifier]
+
+ p.send(node, GetDataFromCurrentView[ST, Boolean] { v =>
+ v.state.version == s.version && v.history.contains(mod.id)
+ })
+
+ p.expectMsg(true)
+ }
+ }
+
+ property("NodeViewHolder: simple forking") {
+ withFixture { ctx =>
+ import ctx._
+ val p = TestProbe()
+
+ val waitDuration = 5.seconds
+
+ system.eventStream.subscribe(eventListener.ref, classOf[SyntacticallySuccessfulModifier])
+ system.eventStream.subscribe(eventListener.ref, classOf[SyntacticallyFailedModification])
+
+ p.send(node, GetDataFromCurrentView[ST, Seq[BlockSection]] { v => totallyValidModifiers(v.history, v.state, 2) })
+ val initMods = p.expectMsgClass(waitDuration, classOf[Seq[BlockSection]])
+ initMods.foreach { mod =>
+ p.send(node, LocallyGeneratedModifier(mod))
+ eventListener.expectMsgType[SyntacticallySuccessfulModifier]
+ }
+
+ p.send(node, GetDataFromCurrentView[ST, BlockSection] { v =>
+ totallyValidModifiers(v.history, v.state, 2).head
+ })
+ val fork1Mod = p.expectMsgClass(waitDuration, classOf[BlockSection])
+
+ p.send(node, GetDataFromCurrentView[ST, BlockSection] { v =>
+ totallyValidModifiers(v.history, v.state, 2).head
+ })
+ val fork2Mod = p.expectMsgClass(waitDuration, classOf[BlockSection])
+
+ p.send(node, LocallyGeneratedModifier(fork1Mod))
+ p.send(node, LocallyGeneratedModifier(fork2Mod))
+ eventListener.expectMsgType[SyntacticallySuccessfulModifier]
+ eventListener.expectMsgType[SyntacticallySuccessfulModifier]
+
+ p.send(node, GetDataFromCurrentView[ST, Boolean] { v =>
+ v.history.contains(fork1Mod.id) || v.history.contains(fork2Mod.id)
+ })
+
+ p.expectMsg(10.seconds, true)
+ }
+ }
+
+ /**
+ * In this test we apply first a chain of 2 blocks and then a chain of 4 blocks, both started with the same
+ * common block. We are expecting to observe "switching" here, though with non-chain structures there could be no
+ * notion of switching, so what we check finally is that last block from the second chain is in "open surface"
+ * (list of open blocks which do not have successors yet, size of the list is 1 in case of blockchain)
+ */
+ property("NodeViewHolder: forking - switching") {
+ withFixture { ctx =>
+ import ctx._
+ val p = TestProbe()
+
+ val opCountBeforeFork = 10
+ val fork1OpCount = 2
+ val fork2OpCount = 4
+
+ val waitDuration = 10.seconds
+
+ //some base operations, we don't wanna have fork right from genesis
+ p.send(node, GetDataFromCurrentView[ST, Seq[BlockSection]] { v =>
+ totallyValidModifiers(v.history, v.state, opCountBeforeFork)
+ })
+ val plainMods = p.expectMsgClass(waitDuration, classOf[Seq[BlockSection]])
+ plainMods.foreach { mod => p.send(node, LocallyGeneratedModifier(mod)) }
+
+ p.send(node, GetDataFromCurrentView[ST, Seq[BlockSection]] { v =>
+ val mods = totallyValidModifiers(v.history, v.state, fork1OpCount)
+ assert(mods.head.parentId == v.history.bestFullBlockIdOpt.orElse(v.history.bestHeaderIdOpt).get)
+ mods
+ })
+ val fork1Mods = p.expectMsgClass(waitDuration, classOf[Seq[BlockSection]])
+
+ p.send(node, GetDataFromCurrentView[ST, Seq[BlockSection]] { v =>
+ totallyValidModifiers(v.history, v.state, fork2OpCount)
+ })
+ val fork2Mods = p.expectMsgClass(waitDuration, classOf[Seq[BlockSection]])
+
+ fork1Mods.foreach { mod => p.send(node, LocallyGeneratedModifier(mod)) }
+ fork2Mods.foreach { mod => p.send(node, LocallyGeneratedModifier(mod)) }
+
+ p.send(node, GetDataFromCurrentView[ST, Boolean] { v =>
+ v.history.bestFullBlockIdOpt.orElse(v.history.bestHeaderIdOpt).contains(fork2Mods.last.id)
+ })
+ p.expectMsg(true)
+ }
+ }
+
+ property("NodeViewHolder: forking - switching with an invalid block") {
+ withFixture { ctx =>
+ import ctx._
+
+ val opCountBeforeFork = 10
+ val fork1OpCount = 4
+
+ //some base operations, we don't wanna have fork right from genesis
+ withView(node) { v =>
+ totallyValidModifiers(v.history, v.state, opCountBeforeFork)
+ }.foreach {
+ mod => node ! LocallyGeneratedModifier(mod)
+ }
+ // generate the first fork with valid blocks
+ val fork1Mods = withView(node) { v =>
+ val mods = totallyValidModifiers(v.history, v.state, fork1OpCount)
+ assert(mods.head.parentId == v.history.bestFullBlockIdOpt.orElse(v.history.bestHeaderIdOpt).get)
+ mods
+ }
+ // generate the second fork with the invalid block
+ val fork2Mods = withView(node) { v =>
+ customModifiers(v.history, v.state,
+ Seq[ModifierProducerTemplateItem](Valid,
+ SynInvalid, // invalid modifier
+ Valid, Valid, Valid, Valid, Valid, Valid))
+ }
+ // apply the first fork with valid blocks
+ fork1Mods.foreach { mod => node ! LocallyGeneratedModifier(mod) }
+ // apply the second fork with invalid block
+ fork2Mods.foreach { mod => node ! LocallyGeneratedModifier(mod) }
+ // verify that open surface consist of last block of the first chain,
+ // or first block of the second chain, or both, but no any other option
+ withView(node) { v =>
+ v.history.bestFullBlockIdOpt.orElse(v.history.bestHeaderIdOpt).toSeq should (
+ contain only fork1Mods.last.id
+ or contain only fork2Mods.head.id
+ or contain only(fork1Mods.last.id, fork2Mods.head.id)
+ )
+ }
+ }
+ }
+
+}
diff --git a/src/test/scala/org/ergoplatform/testkit/properties/mempool/MemoryPoolTest.scala b/src/test/scala/org/ergoplatform/testkit/properties/mempool/MemoryPoolTest.scala
new file mode 100644
index 0000000000..8c9127d721
--- /dev/null
+++ b/src/test/scala/org/ergoplatform/testkit/properties/mempool/MemoryPoolTest.scala
@@ -0,0 +1,13 @@
+package org.ergoplatform.testkit.properties.mempool
+
+import org.ergoplatform.modifiers.mempool.{ErgoTransaction, UnconfirmedTransaction}
+import org.ergoplatform.nodeView.mempool.ErgoMemPool
+import org.scalacheck.Gen
+
+
+trait MemoryPoolTest {
+ val memPool: ErgoMemPool
+ val memPoolGenerator: Gen[ErgoMemPool]
+ val transactionGenerator: Gen[ErgoTransaction]
+ val unconfirmedTxGenerator: Gen[UnconfirmedTransaction]
+}
diff --git a/src/test/scala/org/ergoplatform/testkit/properties/mempool/MempoolFilterPerformanceTest.scala b/src/test/scala/org/ergoplatform/testkit/properties/mempool/MempoolFilterPerformanceTest.scala
new file mode 100644
index 0000000000..6cb9b785fa
--- /dev/null
+++ b/src/test/scala/org/ergoplatform/testkit/properties/mempool/MempoolFilterPerformanceTest.scala
@@ -0,0 +1,43 @@
+package org.ergoplatform.testkit.properties.mempool
+
+import java.security.MessageDigest
+import org.ergoplatform.modifiers.mempool.{ErgoTransaction, UnconfirmedTransaction}
+import org.ergoplatform.nodeView.mempool.ErgoMemPool
+import org.scalatest.matchers.should.Matchers
+import org.scalatest.propspec.AnyPropSpec
+import org.scalatestplus.scalacheck.ScalaCheckPropertyChecks
+
+trait MempoolFilterPerformanceTest
+ extends AnyPropSpec
+ with ScalaCheckPropertyChecks
+ with Matchers
+ with MemoryPoolTest {
+
+ var initializedMempool: Option[ErgoMemPool] = None
+
+ val thresholdInHashes = 500000
+
+ private val HeatJVMHashesCount = 1000000 //to heat up JVM, just in case it is cold
+
+ val thresholdSecs: Double = {
+ //heat up
+ (1 to HeatJVMHashesCount).foreach(i => MessageDigest.getInstance("SHA-256").digest(("dummy" + i).getBytes()))
+
+ val t0 = System.currentTimeMillis()
+ (1 to thresholdInHashes).foreach(i => MessageDigest.getInstance("SHA-256").digest(("dummy" + i).getBytes()))
+ val t = System.currentTimeMillis()
+ (t - t0) / 1000.0
+ }
+
+ property("Mempool should be able to store a lot of transactions") {
+ var m: ErgoMemPool = memPool
+ (0 until 1000) foreach { _ =>
+ forAll(transactionGenerator) { tx: ErgoTransaction =>
+ m = m.put(UnconfirmedTransaction(tx, None))
+ }
+ }
+ m.size should be > 1000
+ initializedMempool = Some(m)
+ }
+
+}
diff --git a/src/test/scala/org/ergoplatform/testkit/properties/mempool/MempoolRemovalTest.scala b/src/test/scala/org/ergoplatform/testkit/properties/mempool/MempoolRemovalTest.scala
new file mode 100644
index 0000000000..826fd601db
--- /dev/null
+++ b/src/test/scala/org/ergoplatform/testkit/properties/mempool/MempoolRemovalTest.scala
@@ -0,0 +1,41 @@
+package org.ergoplatform.testkit.properties.mempool
+
+import org.ergoplatform.modifiers.mempool.{ErgoTransaction, UnconfirmedTransaction}
+import org.ergoplatform.nodeView.history.ErgoHistory
+import org.ergoplatform.nodeView.mempool.ErgoMemPool
+import org.ergoplatform.testkit.TestkitHelpers
+import org.ergoplatform.testkit.generators.ArbitraryTransactionsCarryingModifierProducer
+import org.scalacheck.Gen
+import org.scalatest.matchers.should.Matchers
+import org.scalatest.propspec.AnyPropSpec
+import org.scalatestplus.scalacheck.ScalaCheckPropertyChecks
+import scorex.util.ScorexLogging
+
+trait MempoolRemovalTest extends AnyPropSpec
+ with ScalaCheckPropertyChecks
+ with Matchers
+ with ScorexLogging
+ with TestkitHelpers
+ with MemoryPoolTest
+ with ArbitraryTransactionsCarryingModifierProducer {
+
+ val historyGen: Gen[ErgoHistory]
+
+ //todo: this test doesn't check anything. It should be reworked as a test for node view holder
+ property("Transactions once added to block should be removed from Mempool") {
+ val min = 1
+ val max = 10
+ forAll(Gen.choose(min, max)) { _ =>
+ var m: ErgoMemPool = memPool
+ // var h: ErgoHistory = historyGen.sample.get
+ forAll(transactionGenerator) { tx: ErgoTransaction =>
+ m = m.put(UnconfirmedTransaction(tx, None))
+ }
+ // var prevMempoolSize = m.size
+ // val b = modifierWithTransactions(Some(m), None)
+ //todo: fix (m.size + b.transactions.get.size) shouldEqual prevMempoolSize
+ }
+ }
+}
+
+
diff --git a/src/test/scala/org/ergoplatform/testkit/properties/mempool/MempoolTransactionsTest.scala b/src/test/scala/org/ergoplatform/testkit/properties/mempool/MempoolTransactionsTest.scala
new file mode 100644
index 0000000000..7dbc08cd1b
--- /dev/null
+++ b/src/test/scala/org/ergoplatform/testkit/properties/mempool/MempoolTransactionsTest.scala
@@ -0,0 +1,155 @@
+package org.ergoplatform.testkit.properties.mempool
+
+import org.ergoplatform.modifiers.mempool.{ErgoTransaction, UnconfirmedTransaction}
+import org.ergoplatform.nodeView.mempool.ErgoMemPool
+import org.scalacheck.Gen
+import org.scalatest.matchers.should.Matchers
+import org.scalatest.propspec.AnyPropSpec
+import org.scalatestplus.scalacheck.ScalaCheckPropertyChecks
+
+@SuppressWarnings(Array("org.wartremover.warts.OptionPartial"))
+trait MempoolTransactionsTest
+ extends AnyPropSpec
+ with ScalaCheckPropertyChecks
+ with Matchers
+ with MemoryPoolTest {
+
+ val transactionSeqGenerator: Gen[Seq[ErgoTransaction]] = Gen.nonEmptyContainerOf[Seq, ErgoTransaction](transactionGenerator)
+ val unconfirmedTxSeqGenerator: Gen[Seq[UnconfirmedTransaction]] =
+ transactionSeqGenerator.map(txs => txs.map(tx => UnconfirmedTransaction(tx, None)))
+
+ property("Size of mempool should increase when adding a non-present transaction") {
+ forAll(memPoolGenerator, unconfirmedTxGenerator) { (mp: ErgoMemPool, unconfirmedTx: UnconfirmedTransaction) =>
+ val m: ErgoMemPool = mp.put(unconfirmedTx)
+ m.size shouldEqual 1
+ }
+ }
+
+ property("Size of mempool should not increase when adding a present transaction") {
+ forAll(memPoolGenerator, unconfirmedTxGenerator) { (mp: ErgoMemPool, unconfirmedTx: UnconfirmedTransaction) =>
+ val m: ErgoMemPool = mp.put(unconfirmedTx)
+ val m2: ErgoMemPool = m.put(unconfirmedTx)
+ m2.size shouldEqual 1
+ }
+ }
+
+ property("Size of mempool should increase when adding a collection of non-present transactions " +
+ "without duplicates (with check)") {
+ forAll(memPoolGenerator, unconfirmedTxSeqGenerator) { (mp: ErgoMemPool, unconfirmedTxs: Seq[UnconfirmedTransaction]) =>
+ val m: ErgoMemPool = mp.put(unconfirmedTxs)
+ m.size shouldEqual unconfirmedTxs.size
+ }
+ }
+
+ property("Size of mempool should increase for a number of unique non-present transactions " +
+ "when adding a collection of non-present txs with duplicates (with check)") {
+ forAll(memPoolGenerator, unconfirmedTxSeqGenerator) { (mp: ErgoMemPool, unconfirmedTxs: Seq[UnconfirmedTransaction]) =>
+ val m: ErgoMemPool = mp.put(unconfirmedTxs ++ unconfirmedTxs)
+ m.size shouldEqual unconfirmedTxs.size
+ }
+ }
+
+ property("Size of mempool should not increase when adding a collection of present transactions (with check)") {
+ forAll(memPoolGenerator, unconfirmedTxSeqGenerator) { (mp: ErgoMemPool, unconfirmedTxs: Seq[UnconfirmedTransaction]) =>
+ val m: ErgoMemPool = mp.put(unconfirmedTxs)
+ val m2: ErgoMemPool = m.put(unconfirmedTxs)
+ m2.size shouldEqual unconfirmedTxs.size
+ }
+ }
+
+ property("Size of mempool should increase when adding a collection of non-present transactions " +
+ "without duplicates (without check)") {
+ forAll(memPoolGenerator, unconfirmedTxSeqGenerator) { (mp: ErgoMemPool, unconfirmedTxs: Seq[UnconfirmedTransaction]) =>
+ val m: ErgoMemPool = mp.put(unconfirmedTxs)
+ m.size shouldEqual unconfirmedTxs.size
+ }
+ }
+
+ property("Size of mempool should increase for a number of unique non-present transactions " +
+ "when adding a collection of non-present transactions with duplicates (without check)") {
+ forAll(memPoolGenerator, unconfirmedTxSeqGenerator) { (mp: ErgoMemPool, unconfirmedTxs: Seq[UnconfirmedTransaction]) =>
+ val m: ErgoMemPool = mp.put(unconfirmedTxs ++ unconfirmedTxs)
+ m.size shouldEqual unconfirmedTxs.size
+ }
+ }
+
+ property("Size of mempool should not increase when adding a collection of present transactions (without check)") {
+ forAll(memPoolGenerator, unconfirmedTxSeqGenerator) { (mp: ErgoMemPool, unconfirmedTxs: Seq[UnconfirmedTransaction]) =>
+ val m: ErgoMemPool = mp.put(unconfirmedTxs)
+ val m2: ErgoMemPool = m.put(unconfirmedTxs)
+ m2.size shouldEqual unconfirmedTxs.size
+ }
+ }
+
+ property("Size of mempool should decrease when removing a present transaction") {
+ forAll(memPoolGenerator, unconfirmedTxSeqGenerator) { (mp: ErgoMemPool, unconfirmedTxs: Seq[UnconfirmedTransaction]) =>
+ val m: ErgoMemPool = mp.put(unconfirmedTxs)
+ val m2: ErgoMemPool = m.remove(unconfirmedTxs.headOption.get.transaction)
+ m2.size shouldBe unconfirmedTxs.size - 1
+ }
+ }
+
+ property("Size of mempool should not decrease when removing a non-present transaction") {
+ forAll(memPoolGenerator, unconfirmedTxSeqGenerator, unconfirmedTxGenerator) { (mp: ErgoMemPool, unconfirmedTxs: Seq[UnconfirmedTransaction], unconfirmedTx: UnconfirmedTransaction) =>
+ val m: ErgoMemPool = mp.put(unconfirmedTxs)
+ val m2: ErgoMemPool = m.remove(unconfirmedTx.transaction)
+ m2.size shouldBe unconfirmedTxs.size
+ }
+ }
+
+ property("Present transactions should be available by id") {
+ forAll(memPoolGenerator, unconfirmedTxGenerator) { (mp: ErgoMemPool, unconfirmedTx: UnconfirmedTransaction) =>
+ val m: ErgoMemPool = mp.put(unconfirmedTx)
+ m.modifierById(unconfirmedTx.transaction.id).isDefined shouldBe true
+ }
+ }
+
+ property("Non-present transactions should not be available by id") {
+ forAll(memPoolGenerator, unconfirmedTxSeqGenerator, unconfirmedTxGenerator) { (mp: ErgoMemPool, unconfirmedTxs: Seq[UnconfirmedTransaction], unconfirmedTx: UnconfirmedTransaction) =>
+ val m: ErgoMemPool = mp.put(unconfirmedTxs)
+ m.modifierById(unconfirmedTx.transaction.id).isDefined shouldBe false
+ }
+ }
+
+ property("Mempool should contain present transactions") {
+ forAll(memPoolGenerator, unconfirmedTxSeqGenerator) { (mp: ErgoMemPool, unconfirmedTxs: Seq[UnconfirmedTransaction]) =>
+ val m: ErgoMemPool = mp.put(unconfirmedTxs)
+ m.contains(unconfirmedTxs.headOption.get.transaction.id) shouldBe true
+ }
+ }
+
+ property("Mempool should not contain non-present transactions") {
+ forAll(memPoolGenerator, unconfirmedTxSeqGenerator, unconfirmedTxGenerator) { (mp: ErgoMemPool, unconfirmedTxs: Seq[UnconfirmedTransaction], unconfirmedTx: UnconfirmedTransaction) =>
+ val m: ErgoMemPool = mp.put(unconfirmedTxs)
+ m.contains(unconfirmedTx.transaction.id) shouldBe false
+ }
+ }
+
+ property("Present transactions should be obtained by their ids") {
+ forAll(memPoolGenerator, unconfirmedTxSeqGenerator, unconfirmedTxGenerator) { (mp: ErgoMemPool, unconfirmedTxs: Seq[UnconfirmedTransaction], unconfirmedTx: UnconfirmedTransaction) =>
+ val m: ErgoMemPool = mp.put(unconfirmedTxs :+ unconfirmedTx)
+ m.getAll(unconfirmedTxs.map(_.transaction.id)) sameElements unconfirmedTxs
+ }
+ }
+
+ property("Non-present transactions should not be obtained by their ids") {
+ forAll(memPoolGenerator, unconfirmedTxSeqGenerator, unconfirmedTxGenerator) { (mp: ErgoMemPool, unconfirmedTxs: Seq[UnconfirmedTransaction], unconfirmedTx: UnconfirmedTransaction) =>
+ val m: ErgoMemPool = mp.put(unconfirmedTx)
+ m.getAll(unconfirmedTxs.map(_.transaction.id)).size shouldBe 0
+ }
+ }
+
+ property("Required number of transactions should be taken from mempool") {
+ forAll(memPoolGenerator, unconfirmedTxSeqGenerator, unconfirmedTxGenerator) { (mp: ErgoMemPool, unconfirmedTxs: Seq[UnconfirmedTransaction], tx: UnconfirmedTransaction) =>
+ val m: ErgoMemPool = mp.put(unconfirmedTxs :+ tx)
+ m.take(unconfirmedTxs.size).size shouldBe unconfirmedTxs.size
+ }
+ }
+
+ property("Maximum number of transactions that can be taken should equals mempool size") {
+ forAll(memPoolGenerator, unconfirmedTxSeqGenerator) { (mp: ErgoMemPool, unconfirmedTxs: Seq[UnconfirmedTransaction]) =>
+ val m: ErgoMemPool = mp.put(unconfirmedTxs)
+ m.take(unconfirmedTxs.size + 1).size shouldBe m.size
+ }
+ }
+}
diff --git a/src/test/scala/org/ergoplatform/testkit/properties/state/StateApplicationTest.scala b/src/test/scala/org/ergoplatform/testkit/properties/state/StateApplicationTest.scala
new file mode 100644
index 0000000000..bdfd1c764d
--- /dev/null
+++ b/src/test/scala/org/ergoplatform/testkit/properties/state/StateApplicationTest.scala
@@ -0,0 +1,105 @@
+package org.ergoplatform.testkit.properties.state
+
+import org.ergoplatform.modifiers.BlockSection
+import org.ergoplatform.nodeView.state.{DigestState, ErgoState}
+import org.scalacheck.Gen
+import scala.collection.mutable.ListBuffer
+
+trait StateApplicationTest[ST <: ErgoState[ST]] extends StateTests[ST] {
+
+ lazy val stateGenWithValidModifier: Gen[(ST, BlockSection)] = {
+ stateGen.map { s => (s, semanticallyValidModifier(s)) }
+ }
+
+ lazy val stateGenWithInvalidModifier: Gen[(ST, BlockSection)] = {
+ stateGen.map { s => (s, semanticallyInvalidModifier(s))}
+ }
+
+ private def propertyNameGenerator(propName: String): String = s"StateTests: $propName"
+
+ property(propertyNameGenerator("apply modifier")) {
+ forAll(stateGenWithValidModifier) { case (s, m) =>
+ val ver = s.version
+ val sTry = s.applyModifier(m, None)(_ => ())
+ sTry.isSuccess shouldBe true
+ sTry.get.version == ver shouldBe false
+ }
+ }
+
+ property(propertyNameGenerator("do not apply same valid modifier twice")) {
+ forAll(stateGenWithValidModifier) { case (s, m) =>
+ val ver = s.version
+ val sTry = s.applyModifier(m, None)(_ => ())
+ sTry.isSuccess shouldBe true
+ val s2 = sTry.get
+ s2.version == ver shouldBe false
+ s2.applyModifier(m, None)(_ => ()).isSuccess shouldBe false
+ }
+ }
+
+ property(propertyNameGenerator("do not apply invalid modifier")) {
+ forAll(stateGenWithInvalidModifier) { case (s, m) =>
+ val sTry = s.applyModifier(m, None)(_ => ())
+ sTry.isSuccess shouldBe false
+ }
+ }
+
+ property(propertyNameGenerator("apply valid modifier after rollback")) {
+ forAll(stateGenWithValidModifier) { case (s, m) =>
+ val ver = s.version
+ s.store.setKeepVersions(10)
+ val sTry = s.applyModifier(m, Some(0))(_ => ())
+ sTry.isSuccess shouldBe true
+ val s2 = sTry.get
+ s2.version == ver shouldBe false
+ val ver2 = s2.version
+
+ val s3 = s2.rollbackTo(ver).get
+ s3.version == ver shouldBe true
+
+ val sTry2 = s3.applyModifier(m, None)(_ => ())
+ sTry2.isSuccess shouldBe true
+ val s4 = sTry2.get
+ s4.version == ver shouldBe false
+ s4.version == ver2 shouldBe true
+ }
+ }
+
+ property(propertyNameGenerator("application after rollback is possible")) {
+ forAll(stateGen) { s =>
+ s.store.setKeepVersions(10)
+ val maxRollbackDepth = s match {
+ case ds: DigestState =>
+ ds.store.rollbackVersions().size
+ case _ =>
+ 10
+ }
+ @SuppressWarnings(Array("org.wartremover.warts.OptionPartial"))
+ val rollbackDepth = Gen.chooseNum(1, maxRollbackDepth).sample.get
+ val buf = new ListBuffer[BlockSection]()
+ val ver = s.version
+
+ val s2 = (0 until rollbackDepth).foldLeft(s) { case (state, _) =>
+ val modifier = semanticallyValidModifier(state)
+ buf += modifier
+ val sTry = state.applyModifier(modifier, Some(rollbackDepth))(_ => ())
+ sTry shouldBe 'success
+ sTry.get
+ }
+
+ val lastVersion = s2.version
+ val rollbackTry = s2.rollbackTo(ver)
+ rollbackTry.toOption shouldBe defined
+ val s3 = rollbackTry.get
+ s3.version == ver shouldBe true
+
+ val s4 = buf.foldLeft(s3) { case (state, m) =>
+ val sTry = state.applyModifier(m, Some(0))(_ => ())
+ sTry shouldBe 'success
+ sTry.get
+ }
+
+ s4.version == lastVersion shouldBe true
+ }
+ }
+}
diff --git a/src/test/scala/org/ergoplatform/testkit/properties/state/StateTests.scala b/src/test/scala/org/ergoplatform/testkit/properties/state/StateTests.scala
new file mode 100644
index 0000000000..6cd442ba94
--- /dev/null
+++ b/src/test/scala/org/ergoplatform/testkit/properties/state/StateTests.scala
@@ -0,0 +1,23 @@
+package org.ergoplatform.testkit.properties.state
+
+import org.ergoplatform.nodeView.state.ErgoState
+import org.ergoplatform.testkit.TestkitHelpers
+import org.ergoplatform.testkit.generators.{CoreGenerators, SemanticallyInvalidModifierProducer, SemanticallyValidModifierProducer}
+import org.scalacheck.Gen
+import org.scalatest.matchers.should.Matchers
+import org.scalatest.propspec.AnyPropSpec
+import org.scalatestplus.scalacheck.ScalaCheckPropertyChecks
+
+trait StateTests[ST <: ErgoState[ST]]
+ extends AnyPropSpec
+ with ScalaCheckPropertyChecks
+ with Matchers
+ with CoreGenerators
+ with TestkitHelpers
+ with SemanticallyValidModifierProducer[ST]
+ with SemanticallyInvalidModifierProducer[ST] {
+
+ val checksToMake = 10
+
+ val stateGen: Gen[ST]
+}
diff --git a/src/test/scala/org/ergoplatform/testkit/utils/AkkaFixture.scala b/src/test/scala/org/ergoplatform/testkit/utils/AkkaFixture.scala
new file mode 100644
index 0000000000..21ea378464
--- /dev/null
+++ b/src/test/scala/org/ergoplatform/testkit/utils/AkkaFixture.scala
@@ -0,0 +1,15 @@
+package org.ergoplatform.testkit.utils
+
+import java.util.concurrent.atomic.AtomicInteger
+
+import akka.actor.ActorSystem
+import akka.testkit.{ImplicitSender, TestKit}
+
+object SysId {
+ private val i = new AtomicInteger()
+ def incrementAndGet(): Int = i.incrementAndGet()
+}
+
+class AkkaFixture
+ extends TestKit(ActorSystem("WithIsoFix-%d".format(SysId.incrementAndGet())))
+ with ImplicitSender
diff --git a/src/test/scala/org/ergoplatform/testkit/utils/NoShrink.scala b/src/test/scala/org/ergoplatform/testkit/utils/NoShrink.scala
new file mode 100644
index 0000000000..0fa3909083
--- /dev/null
+++ b/src/test/scala/org/ergoplatform/testkit/utils/NoShrink.scala
@@ -0,0 +1,7 @@
+package org.ergoplatform.testkit.utils
+
+import org.scalacheck.Shrink
+
+trait NoShrink {
+ protected implicit def noShrink[A]: Shrink[A] = Shrink(_ => Stream.empty)
+}
diff --git a/src/test/scala/org/ergoplatform/tools/ChainGenerator.scala b/src/test/scala/org/ergoplatform/tools/ChainGenerator.scala
index 7fb07b62f9..a74c1f1a67 100644
--- a/src/test/scala/org/ergoplatform/tools/ChainGenerator.scala
+++ b/src/test/scala/org/ergoplatform/tools/ChainGenerator.scala
@@ -9,8 +9,8 @@ import org.ergoplatform.modifiers.history.header.Header
import org.ergoplatform.modifiers.history.popow.NipopowAlgos
import org.ergoplatform.modifiers.mempool.{ErgoTransaction, UnsignedErgoTransaction}
import org.ergoplatform.nodeView.history.ErgoHistory
-import org.ergoplatform.nodeView.history.ErgoHistory.Height
-import org.ergoplatform.nodeView.mempool.ErgoMemPool.SortingOption
+import org.ergoplatform.nodeView.history.ErgoHistoryUtils._
+import org.ergoplatform.nodeView.mempool.ErgoMemPoolUtils.SortingOption
import org.ergoplatform.nodeView.state._
import org.ergoplatform.settings._
import org.ergoplatform.utils.{ErgoTestHelpers, HistoryTestHelpers}
@@ -32,7 +32,7 @@ import scala.util.Try
object ChainGenerator extends App with ErgoTestHelpers {
val realNetworkSetting = {
- val initSettings = ErgoSettings.read(Args(None, Some(NetworkType.TestNet)))
+ val initSettings = ErgoSettingsReader.read(Args(None, Some(NetworkType.TestNet)))
initSettings.copy(chainSettings = initSettings.chainSettings.copy(genesisId = None))
}
@@ -94,7 +94,7 @@ object ChainGenerator extends App with ErgoTestHelpers {
acc: Seq[ModifierId]): Seq[ModifierId] = {
val time: Long = last.map(_.timestamp + blockInterval.toMillis).getOrElse(startTime)
if (time < System.currentTimeMillis()) {
- val (txs, lastOut) = genTransactions(last.map(_.height).getOrElse(ErgoHistory.GenesisHeight),
+ val (txs, lastOut) = genTransactions(last.map(_.height).getOrElse(GenesisHeight),
initBox, state.stateContext)
val candidate = genCandidate(prover.hdPubKeys.head.key, last, time, txs, state)
diff --git a/src/test/scala/org/ergoplatform/tools/DifficultyControlSimulator.scala b/src/test/scala/org/ergoplatform/tools/DifficultyControlSimulator.scala
index 8c38a167e4..dd743deb3d 100644
--- a/src/test/scala/org/ergoplatform/tools/DifficultyControlSimulator.scala
+++ b/src/test/scala/org/ergoplatform/tools/DifficultyControlSimulator.scala
@@ -2,8 +2,8 @@ package org.ergoplatform.tools
import org.ergoplatform.mining.difficulty.{DifficultyAdjustment, DifficultySerializer}
import org.ergoplatform.modifiers.history.header.Header
-import org.ergoplatform.nodeView.history.ErgoHistory.Difficulty
-import org.ergoplatform.settings.ErgoSettings
+import org.ergoplatform.nodeView.history.ErgoHistoryUtils.Difficulty
+import org.ergoplatform.settings.ErgoSettingsReader
import org.ergoplatform.utils.generators.ErgoGenerators
import scala.annotation.tailrec
@@ -86,7 +86,7 @@ object DifficultyControlSimulator extends App with ErgoGenerators {
def printTestnetData(): Unit = {
val baseHeader = defaultHeaderGen.sample.get
- val chainSettings = ErgoSettings.read().chainSettings.copy(epochLength = 1)
+ val chainSettings = ErgoSettingsReader.read().chainSettings.copy(epochLength = 1)
val difficultyControl = new DifficultyAdjustment(chainSettings)
val headers = Source.fromResource("difficulty.csv").getLines().toSeq.tail.map { line =>
diff --git a/src/test/scala/org/ergoplatform/utils/ErgoPropertyTest.scala b/src/test/scala/org/ergoplatform/utils/ErgoPropertyTest.scala
index 7ec6cd2466..ebf658e012 100644
--- a/src/test/scala/org/ergoplatform/utils/ErgoPropertyTest.scala
+++ b/src/test/scala/org/ergoplatform/utils/ErgoPropertyTest.scala
@@ -1,9 +1,9 @@
package org.ergoplatform.utils
+import org.ergoplatform.testkit.utils.NoShrink
import org.ergoplatform.utils.generators.{ErgoGenerators, ValidBlocksGenerators}
import org.scalatest.propspec.AnyPropSpec
import org.scalatestplus.scalacheck.ScalaCheckPropertyChecks
-import scorex.testkit.utils.NoShrink
trait ErgoPropertyTest extends AnyPropSpec
with ScalaCheckPropertyChecks
diff --git a/src/test/scala/org/ergoplatform/utils/ErgoTestConstants.scala b/src/test/scala/org/ergoplatform/utils/ErgoTestConstants.scala
index 51d7e80597..4cd5bc4311 100644
--- a/src/test/scala/org/ergoplatform/utils/ErgoTestConstants.scala
+++ b/src/test/scala/org/ergoplatform/utils/ErgoTestConstants.scala
@@ -6,6 +6,7 @@ import org.ergoplatform.mining.emission.EmissionRules
import org.ergoplatform.mining.{AutolykosPowScheme, DefaultFakePowScheme}
import org.ergoplatform.modifiers.history.extension.ExtensionCandidate
import org.ergoplatform.modifiers.history.popow.NipopowAlgos
+import org.ergoplatform.network.{PeerSpec, Version}
import org.ergoplatform.nodeView.state._
import org.ergoplatform.sdk.wallet.secrets.ExtendedSecretKey
import org.ergoplatform.settings.Constants.HashLength
@@ -16,8 +17,6 @@ import org.ergoplatform.wallet.interface4j.SecretString
import org.ergoplatform.wallet.interpreter.{ErgoInterpreter, ErgoProvingInterpreter}
import org.ergoplatform.wallet.mnemonic.Mnemonic
import org.ergoplatform.{DataInput, ErgoBox, ErgoTreePredef}
-import scorex.core.app.Version
-import scorex.core.network.PeerSpec
import scorex.crypto.authds.ADDigest
import scorex.crypto.hash.Digest32
import scorex.util.ScorexLogging
@@ -46,7 +45,7 @@ trait ErgoTestConstants extends ScorexLogging {
Parameters(0, Parameters.DefaultParameters ++ extension, ErgoValidationSettingsUpdate.empty)
}
- val initSettings: ErgoSettings = ErgoSettings.read(Args(Some("src/test/resources/application.conf"), None))
+ val initSettings: ErgoSettings = ErgoSettingsReader.read(Args(Some("src/test/resources/application.conf"), None))
implicit val settings: ErgoSettings = initSettings
@@ -82,9 +81,9 @@ trait ErgoTestConstants extends ScorexLogging {
val defaultVersion: Byte = 0
lazy val powScheme: AutolykosPowScheme = settings.chainSettings.powScheme.ensuring(_.isInstanceOf[DefaultFakePowScheme])
val emptyVSUpdate = ErgoValidationSettingsUpdate.empty
- val emptyStateContext: UpcomingStateContext = ErgoStateContext.empty(genesisStateDigest, settings, parameters)
+ val emptyStateContext: UpcomingStateContext = ErgoStateContext.empty(genesisStateDigest, settings.chainSettings, parameters)
.upcoming(defaultMinerPkPoint, defaultTimestamp, defaultNBits, defaultVotes, emptyVSUpdate, defaultVersion)
- def stateContextWith(parameters: Parameters): UpcomingStateContext = ErgoStateContext.empty(genesisStateDigest, settings, parameters)
+ def stateContextWith(parameters: Parameters): UpcomingStateContext = ErgoStateContext.empty(genesisStateDigest, settings.chainSettings, parameters)
.upcoming(defaultMinerPkPoint, defaultTimestamp, defaultNBits, defaultVotes, emptyVSUpdate, defaultVersion)
val startHeight: Int = emptyStateContext.currentHeight
val startDigest: ADDigest = emptyStateContext.genesisStateDigest
diff --git a/src/test/scala/org/ergoplatform/utils/ErgoTestHelpers.scala b/src/test/scala/org/ergoplatform/utils/ErgoTestHelpers.scala
index bf9d61ac3e..b7164a6103 100644
--- a/src/test/scala/org/ergoplatform/utils/ErgoTestHelpers.scala
+++ b/src/test/scala/org/ergoplatform/utils/ErgoTestHelpers.scala
@@ -3,8 +3,7 @@ package org.ergoplatform.utils
import org.ergoplatform.ErgoBoxCandidate
import org.ergoplatform.utils.generators.ValidBlocksGenerators
import org.scalatest.{EitherValues, OptionValues}
-import scorex.core.network.peer.PeerInfo
-import scorex.core.utils.ScorexEncoding
+import org.ergoplatform.network.peer.PeerInfo
import scorex.util.ScorexLogging
import java.net.InetSocketAddress
diff --git a/src/test/scala/org/ergoplatform/utils/HistoryTestHelpers.scala b/src/test/scala/org/ergoplatform/utils/HistoryTestHelpers.scala
index b38d920120..c6b1c00233 100644
--- a/src/test/scala/org/ergoplatform/utils/HistoryTestHelpers.scala
+++ b/src/test/scala/org/ergoplatform/utils/HistoryTestHelpers.scala
@@ -1,12 +1,12 @@
package org.ergoplatform.utils
+import org.ergoplatform.nodeView.history.ErgoHistoryUtils._
import org.ergoplatform.nodeView.history.ErgoHistory
import org.ergoplatform.nodeView.history.storage.modifierprocessors.{EmptyBlockSectionProcessor, FullBlockPruningProcessor, ToDownloadProcessor}
-import org.ergoplatform.nodeView.mempool.ErgoMemPool.SortingOption
+import org.ergoplatform.nodeView.mempool.ErgoMemPoolUtils.SortingOption
import org.ergoplatform.nodeView.state.StateType
-import org.ergoplatform.settings._
+import org.ergoplatform.settings.{ScorexSettings, _}
import org.scalacheck.Gen
-import scorex.core.settings.ScorexSettings
import scorex.util.ModifierId
import scorex.util.encode.Base16
@@ -84,7 +84,7 @@ object HistoryTestHelpers {
val ppM = ru.typeOf[ToDownloadProcessor].member(ru.TermName("pruningProcessor")).asMethod
val pp = procInstance.reflectMethod(ppM).apply().asInstanceOf[FullBlockPruningProcessor]
val f = ru.typeOf[FullBlockPruningProcessor].member(ru.TermName("minimalFullBlockHeightVar")).asTerm.accessed.asTerm
- runtimeMirror.reflect(pp).reflectField(f).set(ErgoHistory.GenesisHeight)
+ runtimeMirror.reflect(pp).reflectField(f).set(GenesisHeight)
val f2 = ru.typeOf[FullBlockPruningProcessor].member(ru.TermName("isHeadersChainSyncedVar")).asTerm.accessed.asTerm
runtimeMirror.reflect(pp).reflectField(f2).set(true)
}
diff --git a/src/test/scala/org/ergoplatform/utils/NodeViewTestConfig.scala b/src/test/scala/org/ergoplatform/utils/NodeViewTestConfig.scala
index 8df386a697..3b708d9d06 100644
--- a/src/test/scala/org/ergoplatform/utils/NodeViewTestConfig.scala
+++ b/src/test/scala/org/ergoplatform/utils/NodeViewTestConfig.scala
@@ -2,7 +2,7 @@ package org.ergoplatform.utils
import org.ergoplatform.mining.DefaultFakePowScheme
import org.ergoplatform.nodeView.state.StateType
-import org.ergoplatform.settings.{ErgoSettings, NipopowSettings}
+import org.ergoplatform.settings.{ErgoSettings, ErgoSettingsReader, NipopowSettings}
case class NodeViewTestConfig(stateType: StateType,
@@ -10,7 +10,7 @@ case class NodeViewTestConfig(stateType: StateType,
popowBootstrap: Boolean) {
def toSettings: ErgoSettings = {
- val defaultSettings = ErgoSettings.read()
+ val defaultSettings = ErgoSettingsReader.read()
defaultSettings.copy(
chainSettings = defaultSettings.chainSettings.copy(
powScheme = new DefaultFakePowScheme(defaultSettings.chainSettings.powScheme.k, defaultSettings.chainSettings.powScheme.n)
diff --git a/src/test/scala/org/ergoplatform/utils/NodeViewTestOps.scala b/src/test/scala/org/ergoplatform/utils/NodeViewTestOps.scala
index d78b852d81..b161221615 100644
--- a/src/test/scala/org/ergoplatform/utils/NodeViewTestOps.scala
+++ b/src/test/scala/org/ergoplatform/utils/NodeViewTestOps.scala
@@ -6,14 +6,15 @@ import akka.util.Timeout
import org.ergoplatform.modifiers.history.extension.Extension
import org.ergoplatform.modifiers.history.header.Header
import org.ergoplatform.modifiers.mempool.ErgoTransaction
-import org.ergoplatform.modifiers.{ErgoFullBlock, BlockSection}
+import org.ergoplatform.modifiers.{BlockSection, ErgoFullBlock}
import org.ergoplatform.nodeView.history.ErgoHistory
import org.ergoplatform.nodeView.state.{ErgoState, StateType, UtxoState}
import org.ergoplatform.settings.Algos
import org.ergoplatform.nodeView.ErgoNodeViewHolder.CurrentView
-import org.ergoplatform.nodeView.ErgoNodeViewHolder.ReceivableMessages.{GetDataFromCurrentView, LocallyGeneratedModifier}
-import org.ergoplatform.network.ErgoNodeViewSynchronizer.ReceivableMessages._
-import scorex.core.validation.MalformedModifierError
+import org.ergoplatform.nodeView.ErgoNodeViewHolder.ReceivableMessages.GetDataFromCurrentView
+import org.ergoplatform.network.ErgoNodeViewSynchronizerMessages._
+import org.ergoplatform.nodeView.LocallyGeneratedModifier
+import org.ergoplatform.validation.MalformedModifierError
import scorex.util.ModifierId
import scala.concurrent.duration._
diff --git a/src/test/scala/org/ergoplatform/utils/Stubs.scala b/src/test/scala/org/ergoplatform/utils/Stubs.scala
index b68886a573..53186f5a77 100644
--- a/src/test/scala/org/ergoplatform/utils/Stubs.scala
+++ b/src/test/scala/org/ergoplatform/utils/Stubs.scala
@@ -9,22 +9,23 @@ import org.ergoplatform.mining.{AutolykosSolution, CandidateGenerator, ErgoMiner
import org.ergoplatform.modifiers.ErgoFullBlock
import org.ergoplatform.modifiers.history.header.Header
import org.ergoplatform.modifiers.mempool.{ErgoTransaction, UnconfirmedTransaction}
+import org.ergoplatform.network.{Handshake, PeerSpec, Version}
import org.ergoplatform.nodeView.ErgoNodeViewHolder.ReceivableMessages.LocallyGeneratedTransaction
import org.ergoplatform.nodeView.ErgoReadersHolder.{GetDataFromHistory, GetReaders, Readers}
-import org.ergoplatform.nodeView.history.ErgoHistory
+import org.ergoplatform.nodeView.history.{ErgoHistory, ErgoHistoryUtils}
import org.ergoplatform.nodeView.mempool.ErgoMemPool
-import org.ergoplatform.nodeView.mempool.ErgoMemPool.{ProcessingOutcome, SortingOption}
+import org.ergoplatform.nodeView.mempool.ErgoMemPoolUtils.{ProcessingOutcome, SortingOption}
import org.ergoplatform.nodeView.state.wrapped.WrappedUtxoState
import org.ergoplatform.nodeView.state.{DigestState, ErgoStateContext, StateType}
-import org.ergoplatform.nodeView.wallet.ErgoWalletActor._
-import org.ergoplatform.nodeView.wallet.ErgoWalletService.DeriveNextKeyResult
+import org.ergoplatform.nodeView.wallet.ErgoWalletActorMessages._
+import org.ergoplatform.nodeView.wallet.ErgoWalletServiceUtils.DeriveNextKeyResult
import org.ergoplatform.nodeView.wallet._
import org.ergoplatform.nodeView.wallet.persistence.WalletDigest
import org.ergoplatform.nodeView.wallet.scanning.Scan
import org.ergoplatform.sanity.ErgoSanity.HT
import org.ergoplatform.sdk.wallet.secrets.{DerivationPath, ExtendedSecretKey}
import org.ergoplatform.settings.Constants.HashLength
-import org.ergoplatform.settings._
+import org.ergoplatform.settings.{ScorexSettings, _}
import org.ergoplatform.utils.generators.{ChainGenerator, ErgoGenerators, ErgoTransactionGenerators}
import org.ergoplatform.wallet.Constants.{PaymentsScanId, ScanId}
import org.ergoplatform.wallet.boxes.{ChainStatus, TrackedBox}
@@ -33,11 +34,9 @@ import org.ergoplatform.wallet.interpreter.ErgoProvingInterpreter
import org.ergoplatform.wallet.mnemonic.Mnemonic
import org.ergoplatform.wallet.utils.TestFileUtils
import org.scalacheck.Gen
-import scorex.core.app.Version
import scorex.core.network.NetworkController.ReceivableMessages.GetConnectedPeers
-import scorex.core.network.peer.PeerManager.ReceivableMessages.{GetAllPeers, GetBlacklistedPeers}
-import scorex.core.network.{Handshake, PeerSpec}
-import scorex.core.settings.ScorexSettings
+import org.ergoplatform.network.peer.PeerManager.ReceivableMessages.{GetAllPeers, GetBlacklistedPeers}
+import org.ergoplatform.network.PeerSpec
import scorex.crypto.authds.ADDigest
import scorex.crypto.hash.Digest32
import scorex.db.ByteArrayWrapper
@@ -182,7 +181,7 @@ trait Stubs extends ErgoGenerators with ErgoTestHelpers with ChainGenerator with
case RescanWallet(_) => sender ! Success(())
- case GetWalletStatus => sender() ! WalletStatus(true, true, None, ErgoHistory.GenesisHeight, error = None)
+ case GetWalletStatus => sender() ! WalletStatus(true, true, None, ErgoHistoryUtils.GenesisHeight, error = None)
case _: CheckSeed => sender() ! true
@@ -257,7 +256,7 @@ trait Stubs extends ErgoGenerators with ErgoTestHelpers with ChainGenerator with
sender() ! Success(tx)
case SignTransaction(tx, secrets, hints, boxesToSpendOpt, dataBoxesOpt) =>
- val sc = ErgoStateContext.empty(settings, parameters)
+ val sc = ErgoStateContext.empty(settings.chainSettings, parameters)
sender() ! ergoWalletService.signTransaction(Some(prover), tx, secrets, hints, boxesToSpendOpt, dataBoxesOpt, parameters, sc) { boxId =>
utxoState.versionedBoxHolder.get(ByteArrayWrapper(boxId))
}
diff --git a/src/test/scala/org/ergoplatform/utils/WalletTestOps.scala b/src/test/scala/org/ergoplatform/utils/WalletTestOps.scala
index 42407311f2..f88e087f4a 100644
--- a/src/test/scala/org/ergoplatform/utils/WalletTestOps.scala
+++ b/src/test/scala/org/ergoplatform/utils/WalletTestOps.scala
@@ -5,7 +5,7 @@ import org.ergoplatform._
import org.ergoplatform.mining.CandidateGenerator
import org.ergoplatform.modifiers.ErgoFullBlock
import org.ergoplatform.modifiers.mempool.ErgoTransaction
-import org.ergoplatform.nodeView.history.ErgoHistory
+import org.ergoplatform.nodeView.history.ErgoHistoryUtils._
import org.ergoplatform.nodeView.state.{ErgoState, UtxoState}
import org.ergoplatform.nodeView.wallet.ErgoWallet
import org.ergoplatform.nodeView.wallet.IdUtils._
@@ -70,7 +70,7 @@ trait WalletTestOps extends NodeViewBaseOps {
def getUtxoState(implicit ctx: Ctx): UtxoState = getCurrentState.asInstanceOf[UtxoState]
def getHeightOf(state: ErgoState[_])(implicit ctx: Ctx): Option[Int] =
- getHistory.heightOf(scorex.core.versionToId(state.version))
+ getHistory.heightOf(org.ergoplatform.core.versionToId(state.version))
def makeGenesisBlock(script: ProveDlog, assets: Seq[(TokenId, Long)] = Seq.empty)
(implicit ctx: Ctx): ErgoFullBlock = {
@@ -86,7 +86,7 @@ trait WalletTestOps extends NodeViewBaseOps {
}
CandidateGenerator.collectRewards(Some(genesisEmissionBox),
- ErgoHistory.EmptyHistoryHeight,
+ EmptyHistoryHeight,
Seq.empty,
publicKey,
emptyStateContext,
@@ -97,7 +97,7 @@ trait WalletTestOps extends NodeViewBaseOps {
val inputs = IndexedSeq(new Input(genesisEmissionBox.id, emptyProverResult))
val assets: Seq[(TokenId, Long)] = replaceNewAssetStub(assetsIn, inputs)
CandidateGenerator.collectRewards(Some(genesisEmissionBox),
- ErgoHistory.EmptyHistoryHeight,
+ EmptyHistoryHeight,
Seq.empty,
publicKey,
emptyStateContext,
diff --git a/src/test/scala/org/ergoplatform/utils/generators/ErgoGenerators.scala b/src/test/scala/org/ergoplatform/utils/generators/ErgoGenerators.scala
index ad49b7557a..311ce9d00b 100644
--- a/src/test/scala/org/ergoplatform/utils/generators/ErgoGenerators.scala
+++ b/src/test/scala/org/ergoplatform/utils/generators/ErgoGenerators.scala
@@ -13,6 +13,7 @@ import org.ergoplatform.nodeView.history.{ErgoSyncInfo, ErgoSyncInfoV1, ErgoSync
import org.ergoplatform.nodeView.mempool.ErgoMemPool
import org.ergoplatform.nodeView.state.StateType
import org.ergoplatform.settings.{Constants, ErgoValidationSettings, ErgoValidationSettingsUpdate, ValidationRules}
+import org.ergoplatform.testkit.generators.CoreGenerators
import org.ergoplatform.utils.ErgoTestConstants
import org.ergoplatform.validation.{ChangedRule, DisabledRule, EnabledRule, ReplacedRule}
import org.ergoplatform.wallet.utils.Generators
@@ -21,7 +22,6 @@ import org.scalacheck.{Arbitrary, Gen}
import org.scalatest.matchers.should.Matchers
import scorex.crypto.authds.{ADDigest, SerializedAdProof}
import scorex.crypto.hash.Digest32
-import scorex.testkit.generators.CoreGenerators
import sigmastate.Values.ErgoTree
import sigmastate.crypto.CryptoConstants.EcPointType
import sigmastate.crypto.DLogProtocol.{DLogProverInput, ProveDlog}
diff --git a/src/test/scala/org/ergoplatform/utils/generators/ErgoTransactionGenerators.scala b/src/test/scala/org/ergoplatform/utils/generators/ErgoTransactionGenerators.scala
index 978617e43d..e80b368edb 100644
--- a/src/test/scala/org/ergoplatform/utils/generators/ErgoTransactionGenerators.scala
+++ b/src/test/scala/org/ergoplatform/utils/generators/ErgoTransactionGenerators.scala
@@ -5,7 +5,7 @@ import org.ergoplatform.modifiers.ErgoFullBlock
import org.ergoplatform.modifiers.history.BlockTransactions
import org.ergoplatform.modifiers.history.header.Header
import org.ergoplatform.modifiers.mempool.{ErgoTransaction, UnsignedErgoTransaction}
-import org.ergoplatform.nodeView.history.ErgoHistory
+import org.ergoplatform.nodeView.history.ErgoHistoryUtils._
import org.ergoplatform.nodeView.state.wrapped.WrappedUtxoState
import org.ergoplatform.nodeView.state.{BoxHolder, ErgoStateContext, VotingData}
import org.ergoplatform.nodeView.wallet.requests.{ExternalSecret, TransactionSigningRequest}
@@ -61,7 +61,7 @@ trait ErgoTransactionGenerators extends ErgoGenerators with Generators {
def ergoBoxGenForTokens(tokens: Seq[(TokenId, Long)],
propositionGen: Gen[ErgoTree]): Gen[ErgoBox] = {
- ergoBoxGen(propGen = propositionGen, tokensGen = Gen.oneOf(tokens, tokens), heightGen = ErgoHistory.EmptyHistoryHeight)
+ ergoBoxGen(propGen = propositionGen, tokensGen = Gen.oneOf(tokens, tokens), heightGen = EmptyHistoryHeight)
}
def unspendableErgoBoxGen(minValue: Long = parameters.minValuePerByte * 200,
@@ -324,13 +324,13 @@ trait ErgoTransactionGenerators extends ErgoGenerators with Generators {
} yield {
blocks match {
case _ :: _ =>
- val sc = new ErgoStateContext(Seq(), None, startDigest, parameters, validationSettingsNoIl, VotingData.empty)
+ val sc = new ErgoStateContext(Seq(), None, startDigest, parameters, validationSettingsNoIl, VotingData.empty)(settings.chainSettings)
blocks.foldLeft(sc -> 1) { case ((c, h), b) =>
val block = b.copy(header = b.header.copy(height = h, votes = votes(h - 1)))
c.appendFullBlock(block).get -> (h + 1)
}._1
case _ =>
- ErgoStateContext.empty(stateRoot, settings, parameters)
+ ErgoStateContext.empty(stateRoot, settings.chainSettings, parameters)
}
}
diff --git a/src/test/scala/org/ergoplatform/utils/generators/ValidBlocksGenerators.scala b/src/test/scala/org/ergoplatform/utils/generators/ValidBlocksGenerators.scala
index b579b50cd7..e24688951b 100644
--- a/src/test/scala/org/ergoplatform/utils/generators/ValidBlocksGenerators.scala
+++ b/src/test/scala/org/ergoplatform/utils/generators/ValidBlocksGenerators.scala
@@ -10,14 +10,14 @@ import org.ergoplatform.modifiers.mempool.ErgoTransaction
import org.ergoplatform.nodeView.state._
import org.ergoplatform.nodeView.state.wrapped.WrappedUtxoState
import org.ergoplatform.settings.{Algos, Constants, ErgoSettings, Parameters}
+import org.ergoplatform.testkit.TestkitHelpers
import org.ergoplatform.utils.{LoggingUtil, RandomLike, RandomWrapper}
import org.ergoplatform.wallet.utils.TestFileUtils
import org.scalatest.matchers.should.Matchers
-import scorex.core.VersionTag
+import org.ergoplatform.core.VersionTag
import scorex.crypto.authds.avltree.batch.Remove
import scorex.crypto.authds.ADDigest
import scorex.db.ByteArrayWrapper
-import scorex.testkit.TestkitHelpers
import scala.annotation.tailrec
import scala.collection.mutable
diff --git a/src/test/scala/scorex/core/network/DeliveryTrackerSpec.scala b/src/test/scala/scorex/core/network/DeliveryTrackerSpec.scala
index 4c7e5ad532..c5b6395e62 100644
--- a/src/test/scala/scorex/core/network/DeliveryTrackerSpec.scala
+++ b/src/test/scala/scorex/core/network/DeliveryTrackerSpec.scala
@@ -4,9 +4,9 @@ import akka.actor.{ActorRef, Cancellable}
import io.circe._
import io.circe.syntax._
import org.ergoplatform.modifiers.NetworkObjectTypeId
+import org.ergoplatform.testkit.generators.ObjectGenerators
import org.ergoplatform.utils.ErgoPropertyTest
import scorex.core.network.ModifiersStatus.Received
-import scorex.testkit.generators.ObjectGenerators
import scorex.util.ModifierId
class DeliveryTrackerSpec extends ErgoPropertyTest with ObjectGenerators {
diff --git a/src/test/scala/scorex/core/network/PeerSpecSerializerSpec.scala b/src/test/scala/scorex/core/network/PeerSpecSerializerSpec.scala
index 13b8c3d0be..bc82776b49 100644
--- a/src/test/scala/scorex/core/network/PeerSpecSerializerSpec.scala
+++ b/src/test/scala/scorex/core/network/PeerSpecSerializerSpec.scala
@@ -1,7 +1,8 @@
package scorex.core.network
+import org.ergoplatform.network.PeerSpecSerializer
+import org.ergoplatform.testkit.generators.ObjectGenerators
import org.ergoplatform.utils.ErgoPropertyTest
-import scorex.testkit.generators.ObjectGenerators
import scorex.util.ByteArrayBuilder
import scorex.util.serialization.{VLQByteBufferReader, VLQByteBufferWriter}
diff --git a/src/test/scala/scorex/testkit/SerializationTests.scala b/src/test/scala/scorex/testkit/SerializationTests.scala
index b4ed96389e..b69e3f0f4a 100644
--- a/src/test/scala/scorex/testkit/SerializationTests.scala
+++ b/src/test/scala/scorex/testkit/SerializationTests.scala
@@ -4,7 +4,7 @@ import org.scalacheck.Gen
import org.scalatest.Assertion
import org.scalatest.matchers.should.Matchers
import org.scalatestplus.scalacheck.ScalaCheckPropertyChecks
-import scorex.core.serialization.ErgoSerializer
+import org.ergoplatform.serialization.ErgoSerializer
trait SerializationTests extends ScalaCheckPropertyChecks with Matchers {
def checkSerializationRoundtrip[A](generator: Gen[A], serializer: ErgoSerializer[A]): Assertion = {
diff --git a/src/test/scala/scorex/testkit/generators/AllModifierProducers.scala b/src/test/scala/scorex/testkit/generators/AllModifierProducers.scala
index 857fd49393..bb5b9feedc 100644
--- a/src/test/scala/scorex/testkit/generators/AllModifierProducers.scala
+++ b/src/test/scala/scorex/testkit/generators/AllModifierProducers.scala
@@ -2,10 +2,9 @@ package scorex.testkit.generators
import org.ergoplatform.nodeView.state.ErgoState
-
trait AllModifierProducers[ST <: ErgoState[ST]]
extends SemanticallyValidModifierProducer[ST]
with SyntacticallyTargetedModifierProducer
with ArbitraryTransactionsCarryingModifierProducer
with TotallyValidModifierProducer[ST]
- with SemanticallyValidTransactionsCarryingModifier[ST]
+ with SemanticallyValidTransactionsCarryingModifier[ST]
\ No newline at end of file
diff --git a/src/test/scala/scorex/testkit/generators/CoreGenerators.scala b/src/test/scala/scorex/testkit/generators/CoreGenerators.scala
index 54c6c3d752..95e646742f 100644
--- a/src/test/scala/scorex/testkit/generators/CoreGenerators.scala
+++ b/src/test/scala/scorex/testkit/generators/CoreGenerators.scala
@@ -1,7 +1,7 @@
package scorex.testkit.generators
import org.scalacheck.Gen
-import scorex.core.{VersionTag, idToVersion}
+import org.ergoplatform.core.{VersionTag, idToVersion}
//Generators of objects from scorex-core
trait CoreGenerators extends ObjectGenerators {
diff --git a/src/test/scala/scorex/testkit/generators/ObjectGenerators.scala b/src/test/scala/scorex/testkit/generators/ObjectGenerators.scala
index f99112fab7..800b7ac8d6 100644
--- a/src/test/scala/scorex/testkit/generators/ObjectGenerators.scala
+++ b/src/test/scala/scorex/testkit/generators/ObjectGenerators.scala
@@ -3,16 +3,15 @@ package scorex.testkit.generators
import java.net.{InetAddress, InetSocketAddress, URL}
import akka.actor.ActorRef
import akka.util.ByteString
+import org.ergoplatform.NodeViewModifier
import org.ergoplatform.modifiers.NetworkObjectTypeId
-import org.ergoplatform.network.ModePeerFeature
+import org.ergoplatform.network.{ModePeerFeature, PeerFeature, PeerSpec, Version}
import org.ergoplatform.nodeView.state.StateType
import org.scalacheck.Gen.{const, some}
import org.scalacheck.{Arbitrary, Gen}
-import scorex.core.app.Version
-import scorex.core.network.message.{InvData, ModifiersData}
+import org.ergoplatform.network.message.{InvData, ModifiersData}
import scorex.core.network._
-import scorex.core.network.peer.{PeerInfo, RestApiUrlPeerFeature}
-import scorex.core.NodeViewModifier
+import org.ergoplatform.network.peer.{PeerInfo, RestApiUrlPeerFeature}
import scorex.util.{ModifierId, bytesToId}
trait ObjectGenerators {
diff --git a/src/test/scala/scorex/testkit/properties/HistoryTests.scala b/src/test/scala/scorex/testkit/properties/HistoryTests.scala
index 31e2d726e8..2e3daf1c52 100644
--- a/src/test/scala/scorex/testkit/properties/HistoryTests.scala
+++ b/src/test/scala/scorex/testkit/properties/HistoryTests.scala
@@ -1,14 +1,14 @@
package scorex.testkit.properties
+import org.ergoplatform.consensus.ModifierSemanticValidity.Valid
import org.ergoplatform.modifiers.BlockSection
import org.ergoplatform.nodeView.history.ErgoHistory
+import org.ergoplatform.testkit.TestkitHelpers
+import org.ergoplatform.testkit.generators.SyntacticallyTargetedModifierProducer
import org.scalacheck.Gen
import org.scalatest.matchers.should.Matchers
import org.scalatest.propspec.AnyPropSpec
import org.scalatestplus.scalacheck.ScalaCheckPropertyChecks
-import scorex.core.consensus.ModifierSemanticValidity.Valid
-import scorex.testkit.TestkitHelpers
-import scorex.testkit.generators.SyntacticallyTargetedModifierProducer
import scorex.util.ScorexLogging
diff --git a/src/test/scala/scorex/testkit/properties/NodeViewHolderTests.scala b/src/test/scala/scorex/testkit/properties/NodeViewHolderTests.scala
index 775b58d8d0..bf9118c1ba 100644
--- a/src/test/scala/scorex/testkit/properties/NodeViewHolderTests.scala
+++ b/src/test/scala/scorex/testkit/properties/NodeViewHolderTests.scala
@@ -6,12 +6,13 @@ import org.ergoplatform.modifiers.BlockSection
import org.ergoplatform.nodeView.history.ErgoHistory
import org.scalatest.matchers.should.Matchers
import org.scalatest.propspec.AnyPropSpec
+import org.ergoplatform.network.ErgoNodeViewSynchronizerMessages._
import org.ergoplatform.nodeView.ErgoNodeViewHolder.CurrentView
-import org.ergoplatform.nodeView.ErgoNodeViewHolder.ReceivableMessages.{GetDataFromCurrentView, LocallyGeneratedModifier}
-import org.ergoplatform.network.ErgoNodeViewSynchronizer.ReceivableMessages._
+import org.ergoplatform.nodeView.ErgoNodeViewHolder.ReceivableMessages.GetDataFromCurrentView
+import org.ergoplatform.nodeView.LocallyGeneratedModifier
import org.ergoplatform.nodeView.state.ErgoState
-import scorex.testkit.generators._
-import scorex.testkit.utils.AkkaFixture
+import org.ergoplatform.testkit.generators
+import org.ergoplatform.testkit.utils.AkkaFixture
import scorex.util.ScorexLogging
import scala.concurrent.Await
@@ -22,11 +23,11 @@ trait NodeViewHolderTests[ST <: ErgoState[ST]]
extends AnyPropSpec
with Matchers
with ScorexLogging
- with SyntacticallyTargetedModifierProducer
- with TotallyValidModifierProducer[ST]
- with SemanticallyInvalidModifierProducer[ST]
- with CustomModifierProducer[ST]
- with ObjectGenerators {
+ with generators.SyntacticallyTargetedModifierProducer
+ with generators.TotallyValidModifierProducer[ST]
+ with generators.SemanticallyInvalidModifierProducer[ST]
+ with generators.CustomModifierProducer[ST]
+ with generators.ObjectGenerators {
def nodeViewHolder(implicit system: ActorSystem): (ActorRef, TestProbe, BlockSection, ST, ErgoHistory)
@@ -314,9 +315,9 @@ trait NodeViewHolderTests[ST <: ErgoState[ST]]
// generate the second fork with the invalid block
val fork2Mods = withView(node) { v =>
customModifiers(v.history, v.state,
- Seq[ModifierProducerTemplateItem](Valid,
- SynInvalid, // invalid modifier
- Valid, Valid, Valid, Valid, Valid, Valid))
+ Seq[generators.ModifierProducerTemplateItem](generators.Valid,
+ generators.SynInvalid, // invalid modifier
+ generators.Valid, generators.Valid, generators.Valid, generators.Valid, generators.Valid, generators.Valid))
}
// apply the first fork with valid blocks
fork1Mods.foreach { mod => node ! LocallyGeneratedModifier(mod) }
diff --git a/src/test/scala/scorex/testkit/properties/mempool/MempoolRemovalTest.scala b/src/test/scala/scorex/testkit/properties/mempool/MempoolRemovalTest.scala
index 5506e6ac35..ed5361cbc3 100644
--- a/src/test/scala/scorex/testkit/properties/mempool/MempoolRemovalTest.scala
+++ b/src/test/scala/scorex/testkit/properties/mempool/MempoolRemovalTest.scala
@@ -3,12 +3,12 @@ package scorex.testkit.properties.mempool
import org.ergoplatform.modifiers.mempool.{ErgoTransaction, UnconfirmedTransaction}
import org.ergoplatform.nodeView.history.ErgoHistory
import org.ergoplatform.nodeView.mempool.ErgoMemPool
+import org.ergoplatform.testkit.TestkitHelpers
+import org.ergoplatform.testkit.generators.ArbitraryTransactionsCarryingModifierProducer
import org.scalacheck.Gen
import org.scalatest.matchers.should.Matchers
import org.scalatest.propspec.AnyPropSpec
import org.scalatestplus.scalacheck.ScalaCheckPropertyChecks
-import scorex.testkit.TestkitHelpers
-import scorex.testkit.generators.ArbitraryTransactionsCarryingModifierProducer
import scorex.util.ScorexLogging
trait MempoolRemovalTest extends AnyPropSpec
diff --git a/src/test/scala/scorex/testkit/properties/state/StateApplicationTest.scala b/src/test/scala/scorex/testkit/properties/state/StateApplicationTest.scala
index 805550fffe..410b5fcaa9 100644
--- a/src/test/scala/scorex/testkit/properties/state/StateApplicationTest.scala
+++ b/src/test/scala/scorex/testkit/properties/state/StateApplicationTest.scala
@@ -3,6 +3,7 @@ package scorex.testkit.properties.state
import org.ergoplatform.modifiers.BlockSection
import org.ergoplatform.nodeView.state.{DigestState, ErgoState}
import org.scalacheck.Gen
+
import scala.collection.mutable.ListBuffer
diff --git a/src/test/scala/scorex/testkit/properties/state/StateTests.scala b/src/test/scala/scorex/testkit/properties/state/StateTests.scala
index 78c1452c8f..67a7aefdaa 100644
--- a/src/test/scala/scorex/testkit/properties/state/StateTests.scala
+++ b/src/test/scala/scorex/testkit/properties/state/StateTests.scala
@@ -1,12 +1,12 @@
package scorex.testkit.properties.state
import org.ergoplatform.nodeView.state.ErgoState
+import org.ergoplatform.testkit.{TestkitHelpers, generators}
+import org.ergoplatform.testkit.generators.{CoreGenerators, SemanticallyInvalidModifierProducer}
import org.scalacheck.Gen
import org.scalatest.matchers.should.Matchers
import org.scalatest.propspec.AnyPropSpec
import org.scalatestplus.scalacheck.ScalaCheckPropertyChecks
-import scorex.testkit.TestkitHelpers
-import scorex.testkit.generators.{CoreGenerators, SemanticallyInvalidModifierProducer, SemanticallyValidModifierProducer}
trait StateTests[ST <: ErgoState[ST]]
extends AnyPropSpec
@@ -14,7 +14,7 @@ trait StateTests[ST <: ErgoState[ST]]
with Matchers
with CoreGenerators
with TestkitHelpers
- with SemanticallyValidModifierProducer[ST]
+ with generators.SemanticallyValidModifierProducer[ST]
with SemanticallyInvalidModifierProducer[ST] {
val checksToMake = 10
diff --git a/src/test/scala/scorex/testkit/utils/AkkaFixture.scala b/src/test/scala/scorex/testkit/utils/AkkaFixture.scala
index c3aa3b978e..e5ff1f476f 100644
--- a/src/test/scala/scorex/testkit/utils/AkkaFixture.scala
+++ b/src/test/scala/scorex/testkit/utils/AkkaFixture.scala
@@ -1,7 +1,6 @@
package scorex.testkit.utils
import java.util.concurrent.atomic.AtomicInteger
-
import akka.actor.ActorSystem
import akka.testkit.{ImplicitSender, TestKit}