From b0fed5d61516cfd7bb0d723c8e68ccd6023458a2 Mon Sep 17 00:00:00 2001 From: Mike Aksarin Date: Mon, 16 Jul 2018 12:56:03 +0300 Subject: [PATCH 01/11] Long chain synchronization integration test added --- build.sbt | 1 - src/it/resources/template.conf | 2 + src/it/scala/org/ergoplatform/it/Docker.scala | 25 +++++++---- .../ergoplatform/it/FourNodeSyncSpec.scala | 35 ++++++++++++++++ .../org/ergoplatform/it/FourNodesSuite.scala | 22 ---------- .../ergoplatform/it/IntegrationSuite.scala | 41 +++++++++---------- .../org/ergoplatform/it/LongChainSpec.scala | 26 ++++++++++++ src/it/scala/org/ergoplatform/it/Node.scala | 2 +- .../it/NodesSynchronizationSpec.scala | 29 ------------- .../it/util/IntegrationTest.scala | 12 ------ 10 files changed, 100 insertions(+), 95 deletions(-) create mode 100644 src/it/scala/org/ergoplatform/it/FourNodeSyncSpec.scala delete mode 100644 src/it/scala/org/ergoplatform/it/FourNodesSuite.scala create mode 100644 src/it/scala/org/ergoplatform/it/LongChainSpec.scala delete mode 100644 src/it/scala/org/ergoplatform/it/NodesSynchronizationSpec.scala delete mode 100644 src/it/scala/org/ergoplatform/it/util/IntegrationTest.scala diff --git a/build.sbt b/build.sbt index f014e37ccf..6d953e45d2 100644 --- a/build.sbt +++ b/build.sbt @@ -106,7 +106,6 @@ configs(IntegrationTest extend(Test)) inConfig(IntegrationTest)(Seq( parallelExecution := false, test := (test dependsOn docker).value, - testOptions += Tests.Filter(_.endsWith("Suite")) )) dockerfile in docker := { diff --git a/src/it/resources/template.conf b/src/it/resources/template.conf index 7b4b4d15a9..95648b3030 100644 --- a/src/it/resources/template.conf +++ b/src/it/resources/template.conf @@ -40,6 +40,8 @@ ergo { scorex { network { + maxPacketSize = 2048576 + maxInvObjects = 10 bindAddress = "0.0.0.0:9001" knownPeers = [] } diff --git a/src/it/scala/org/ergoplatform/it/Docker.scala b/src/it/scala/org/ergoplatform/it/Docker.scala index 5eebd00868..18d6dad11b 100644 --- a/src/it/scala/org/ergoplatform/it/Docker.scala +++ b/src/it/scala/org/ergoplatform/it/Docker.scala @@ -6,6 +6,7 @@ import java.nio.file.{Files, 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 import com.google.common.collect.ImmutableMap @@ -23,7 +24,8 @@ import scorex.core.utils.ScorexLogging import scala.annotation.tailrec import scala.collection.JavaConverters._ -import scala.concurrent.{ExecutionContext, Future, blocking} +import scala.concurrent.{Await, ExecutionContext, Future, blocking} +import scala.concurrent.duration._ import scala.util.control.NonFatal import scala.util.{Failure, Random, Try} @@ -61,15 +63,20 @@ class Docker(suiteConfig: Config = ConfigFactory.empty, tag: String = "ergo_inte } } - def startNodes(nodeConfigs: Seq[Config]): Future[Seq[Node]] = { + def startNodes(nodeConfigs: List[Config]): Try[List[Node]] = { log.trace(s"Starting ${nodeConfigs.size} containers") - val tryNodes: Seq[Try[Node]] = nodeConfigs.map(startNode) + val nodes: Try[List[Node]] = nodeConfigs.map(startNode).sequence + blocking(Thread.sleep(nodeConfigs.size * 5000)) + nodes + } + + def waitForStartupBlocking(nodes: List[Node]): List[Node] = { log.debug("Waiting for nodes to start") - blocking(Thread.sleep(tryNodes.size * 5000)) - val futureNodes: Seq[Future[Node]] = tryNodes map { tryNode => - Future.fromTry(tryNode.map(node => node.waitForStartup)).flatten - } - Future.sequence(futureNodes) + Await.result(waitForStartup(nodes), nodes.size * 90.seconds) + } + + def waitForStartup(nodes: List[Node]): Future[List[Node]] = { + Future.sequence(nodes map { _.waitForStartup }) } def startNode(nodeConfig: Config): Try[Node] = { @@ -330,7 +337,7 @@ object Docker { val defaultConfigTemplate: Config = ConfigFactory.parseResources("template.conf") val nodesJointConfig: Config = ConfigFactory.parseResources("nodes.conf").resolve() - val nodeConfigs: Seq[Config] = nodesJointConfig.getConfigList("nodes").asScala + val nodeConfigs: List[Config] = nodesJointConfig.getConfigList("nodes").asScala.toList private val jsonMapper = new ObjectMapper private val propsMapper = new JavaPropsMapper diff --git a/src/it/scala/org/ergoplatform/it/FourNodeSyncSpec.scala b/src/it/scala/org/ergoplatform/it/FourNodeSyncSpec.scala new file mode 100644 index 0000000000..e6769bad43 --- /dev/null +++ b/src/it/scala/org/ergoplatform/it/FourNodeSyncSpec.scala @@ -0,0 +1,35 @@ +package org.ergoplatform.it + +import org.scalatest.FreeSpec + +import scala.concurrent.duration._ +import scala.concurrent.{Await, Future} + +class FourNodeSyncSpec extends FreeSpec with IntegrationSuite { + + val blocksCount = 5 + + val forkDepth = blocksCount + val minerConfig = Docker.nodeConfigs.head + + val nonGeneratingConfig = nonGeneratingPeerConfig.withFallback(Docker.nodeConfigs(1)) + val onlineGeneratingConfigs = Docker.nodeConfigs.slice(2, 2).map(onlineGeneratingPeerConfig.withFallback) + val nodeConfigs = minerConfig +: nonGeneratingConfig +: onlineGeneratingConfigs + + val nodes: List[Node] = docker.startNodes(nodeConfigs).success.value + + s"Generate $blocksCount blocks" in { + val result = for { + b <- Future.traverse(nodes)(_.height).map(_.max) + _ <- Future.traverse(nodes)(_.waitForHeight(b + blocksCount)) + headers <- Future.traverse(nodes)(_.headerIdsByHeight(b + blocksCount - forkDepth)) + } yield { + log.debug(s"Headers at height ${b + blocksCount - forkDepth}: ${headers.mkString(",")}") + val headerIdsAtSameHeight = headers.flatten + val sample = headerIdsAtSameHeight.head + headerIdsAtSameHeight should contain only sample + } + Await.result(result, 10.minutes) + } +} + diff --git a/src/it/scala/org/ergoplatform/it/FourNodesSuite.scala b/src/it/scala/org/ergoplatform/it/FourNodesSuite.scala deleted file mode 100644 index 3ebc7045e9..0000000000 --- a/src/it/scala/org/ergoplatform/it/FourNodesSuite.scala +++ /dev/null @@ -1,22 +0,0 @@ -package org.ergoplatform.it - -import org.scalatest.Suite - -import scala.collection.immutable.IndexedSeq - -class FourNodesSuite extends IntegrationSuite { - - private val nodesCount = 4 - - protected val nodeConfigs = { - val src = Docker.nodeConfigs.take(nodesCount) - src.head +: - nonGeneratingPeerConfig.withFallback(src.tail.head) +: - src.tail.tail.map(onlineGeneratingPeerConfig.withFallback) - } - - protected def nodeSuites(nodes: Seq[Node]): IndexedSeq[Suite] = IndexedSeq( - new NodesSynchronizationSpec(nodes) - ) - -} diff --git a/src/it/scala/org/ergoplatform/it/IntegrationSuite.scala b/src/it/scala/org/ergoplatform/it/IntegrationSuite.scala index 343337dab9..800688f442 100644 --- a/src/it/scala/org/ergoplatform/it/IntegrationSuite.scala +++ b/src/it/scala/org/ergoplatform/it/IntegrationSuite.scala @@ -1,36 +1,29 @@ package org.ergoplatform.it -import com.typesafe.config.{Config, ConfigFactory} -import org.ergoplatform.it.util.IntegrationTest -import org.scalatest.{BeforeAndAfterAll, FreeSpec, Suite} +import com.typesafe.config.ConfigFactory +import org.ergoplatform.utils.ErgoTestHelpers +import org.scalatest.concurrent.{IntegrationPatience, ScalaFutures} +import org.scalatest.{BeforeAndAfterAll, Suite, TryValues} +import scorex.core.utils.ScorexLogging -import scala.collection.immutable.IndexedSeq -import scala.concurrent.{Await, Future} -import scala.concurrent.duration._ +import scala.concurrent.ExecutionContext -trait IntegrationSuite extends FreeSpec with BeforeAndAfterAll with IntegrationTest { +trait IntegrationSuite + extends BeforeAndAfterAll + with ErgoTestHelpers + with TryValues + with ScalaFutures + with IntegrationPatience + with ScorexLogging { this: Suite => - protected def nodeConfigs: Seq[Config] - protected def nodeSuites(nodes: Seq[Node]): IndexedSeq[Suite] + implicit def executionContext: ExecutionContext = ErgoTestHelpers.defaultExecutionContext protected val docker: Docker = Docker(getClass) - protected lazy val futureNodes: Future[Seq[Node]] = docker.startNodes(nodeConfigs) override protected def beforeAll(): Unit = { log.debug("Starting tests") } - override def nestedSuites: IndexedSeq[Suite] = { - val futureSuits = futureNodes - .map(nodeSuites) - .recover { - case e => - fail(e) - IndexedSeq.empty - } - Await.result(futureSuits, 3.minutes) - } - override protected def afterAll(): Unit = docker.close() protected val nonGeneratingPeerConfig = ConfigFactory.parseString( @@ -46,4 +39,10 @@ trait IntegrationSuite extends FreeSpec with BeforeAndAfterAll with IntegrationT """.stripMargin ) + protected val noDelayConfig = ConfigFactory.parseString( + """ + |ergo.node.miningDelay=30ms + """.stripMargin + ) + } diff --git a/src/it/scala/org/ergoplatform/it/LongChainSpec.scala b/src/it/scala/org/ergoplatform/it/LongChainSpec.scala new file mode 100644 index 0000000000..cd892cc8e0 --- /dev/null +++ b/src/it/scala/org/ergoplatform/it/LongChainSpec.scala @@ -0,0 +1,26 @@ +package org.ergoplatform.it + +import org.scalatest.FreeSpec + +import scala.async.Async.{async, await} +import scala.concurrent.Await +import scala.concurrent.duration._ + +class LongChainSpec extends FreeSpec with IntegrationSuite { + + s"Synchronize long blocks" in { + val minerConfig = noDelayConfig.withFallback(Docker.nodeConfigs.head) + val followerConfig = nonGeneratingPeerConfig.withFallback(Docker.nodeConfigs(1)) + val miner = docker.startNode(minerConfig).success.value + val blocksCount = miner.settings.scorexSettings.network.maxInvObjects + log.info(s"Config maxInvObjects = $blocksCount") + val check = async { + await(miner.waitForHeight(blocksCount)) + val follower = docker.startNode(followerConfig).success.value + await(follower.waitForHeight(blocksCount)) + succeed + } + Await.result(check, 5.minutes) + } +} + diff --git a/src/it/scala/org/ergoplatform/it/Node.scala b/src/it/scala/org/ergoplatform/it/Node.scala index 25b439ac3f..dac828287e 100644 --- a/src/it/scala/org/ergoplatform/it/Node.scala +++ b/src/it/scala/org/ergoplatform/it/Node.scala @@ -9,7 +9,7 @@ import scala.concurrent.ExecutionContext import scala.concurrent.duration.FiniteDuration -class Node(settings: ErgoSettings, val nodeInfo: NodeInfo, override val client: AsyncHttpClient) +class Node(val settings: ErgoSettings, val nodeInfo: NodeInfo, override val client: AsyncHttpClient) (implicit override val ec: ExecutionContext) extends NodeApi with NetworkNodeApi { // todo after addresses will added // val privateKey: String = config.getString("private-key") diff --git a/src/it/scala/org/ergoplatform/it/NodesSynchronizationSpec.scala b/src/it/scala/org/ergoplatform/it/NodesSynchronizationSpec.scala deleted file mode 100644 index 0fa0a033e8..0000000000 --- a/src/it/scala/org/ergoplatform/it/NodesSynchronizationSpec.scala +++ /dev/null @@ -1,29 +0,0 @@ -package org.ergoplatform.it - -import org.ergoplatform.it.util.IntegrationTest -import org.scalatest.FreeSpec - -import scala.concurrent.Await -import scala.concurrent.duration._ -import scala.concurrent.Future.traverse - -class NodesSynchronizationSpec(nodes: Seq[Node]) extends FreeSpec with IntegrationTest { - - val blocksCount = 5 - val forkDepth = blocksCount - - s"Generate $blocksCount blocks" in { - val result = for { - b <- traverse(nodes)(_.height).map(_.max) - _ <- traverse(nodes)(_.waitForHeight(b + blocksCount)) - headers <- traverse(nodes)(_.headerIdsByHeight(b + blocksCount - forkDepth)) - } yield { - log.debug(s"Headers at height ${b + blocksCount - forkDepth}: ${headers.mkString(",")}") - val headerIdsAtSameHeight = headers.flatten - val sample = headerIdsAtSameHeight.head - headerIdsAtSameHeight should contain only sample - } - Await.result(result, 10.minutes) - } -} - diff --git a/src/it/scala/org/ergoplatform/it/util/IntegrationTest.scala b/src/it/scala/org/ergoplatform/it/util/IntegrationTest.scala deleted file mode 100644 index 85e3a7b2fd..0000000000 --- a/src/it/scala/org/ergoplatform/it/util/IntegrationTest.scala +++ /dev/null @@ -1,12 +0,0 @@ -package org.ergoplatform.it.util - -import org.ergoplatform.utils.ErgoTestHelpers -import org.scalatest.concurrent.{IntegrationPatience, ScalaFutures} - -import scala.concurrent.ExecutionContext - -trait IntegrationTest extends ErgoTestHelpers with ScalaFutures with IntegrationPatience { - - implicit def ec: ExecutionContext = ErgoTestHelpers.defaultExecutionContext - -} From bd8cf8d76310ab58357d5751565dad8950fab8d5 Mon Sep 17 00:00:00 2001 From: Mike Aksarin Date: Mon, 16 Jul 2018 18:43:26 +0300 Subject: [PATCH 02/11] Configured LongChainSpec to pass, though there are still the problems with long packet length (Invalid packet length: 124088935) --- .../org/ergoplatform/it/IntegrationSuite.scala | 2 +- .../scala/org/ergoplatform/it/LongChainSpec.scala | 13 ++++++------- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/src/it/scala/org/ergoplatform/it/IntegrationSuite.scala b/src/it/scala/org/ergoplatform/it/IntegrationSuite.scala index 800688f442..56163ea47c 100644 --- a/src/it/scala/org/ergoplatform/it/IntegrationSuite.scala +++ b/src/it/scala/org/ergoplatform/it/IntegrationSuite.scala @@ -41,7 +41,7 @@ trait IntegrationSuite protected val noDelayConfig = ConfigFactory.parseString( """ - |ergo.node.miningDelay=30ms + |ergo.node.miningDelay=500ms """.stripMargin ) diff --git a/src/it/scala/org/ergoplatform/it/LongChainSpec.scala b/src/it/scala/org/ergoplatform/it/LongChainSpec.scala index cd892cc8e0..3a4a143f34 100644 --- a/src/it/scala/org/ergoplatform/it/LongChainSpec.scala +++ b/src/it/scala/org/ergoplatform/it/LongChainSpec.scala @@ -12,15 +12,14 @@ class LongChainSpec extends FreeSpec with IntegrationSuite { val minerConfig = noDelayConfig.withFallback(Docker.nodeConfigs.head) val followerConfig = nonGeneratingPeerConfig.withFallback(Docker.nodeConfigs(1)) val miner = docker.startNode(minerConfig).success.value - val blocksCount = miner.settings.scorexSettings.network.maxInvObjects - log.info(s"Config maxInvObjects = $blocksCount") - val check = async { - await(miner.waitForHeight(blocksCount)) - val follower = docker.startNode(followerConfig).success.value - await(follower.waitForHeight(blocksCount)) + val blocksCount = 250 + val check = async { + await(miner.waitForHeight(blocksCount)) + val follower = docker.startNode(followerConfig).success.value + await(follower.waitForHeight(blocksCount)) succeed } - Await.result(check, 5.minutes) + Await.result(check, 10.minutes) } } From eac42a3a086f7809f3dd3ffcea703553dcc14f25 Mon Sep 17 00:00:00 2001 From: Mike Aksarin Date: Mon, 16 Jul 2018 19:50:44 +0300 Subject: [PATCH 03/11] Enlarged timeout for LongChainSpec to pass there are still the problems with long packet length (Invalid packet length: 124088935) --- src/it/scala/org/ergoplatform/it/IntegrationSuite.scala | 2 +- src/it/scala/org/ergoplatform/it/LongChainSpec.scala | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/it/scala/org/ergoplatform/it/IntegrationSuite.scala b/src/it/scala/org/ergoplatform/it/IntegrationSuite.scala index 56163ea47c..e8ba04f21b 100644 --- a/src/it/scala/org/ergoplatform/it/IntegrationSuite.scala +++ b/src/it/scala/org/ergoplatform/it/IntegrationSuite.scala @@ -41,7 +41,7 @@ trait IntegrationSuite protected val noDelayConfig = ConfigFactory.parseString( """ - |ergo.node.miningDelay=500ms + |ergo.node.miningDelay=300ms """.stripMargin ) diff --git a/src/it/scala/org/ergoplatform/it/LongChainSpec.scala b/src/it/scala/org/ergoplatform/it/LongChainSpec.scala index 3a4a143f34..c7e857ac60 100644 --- a/src/it/scala/org/ergoplatform/it/LongChainSpec.scala +++ b/src/it/scala/org/ergoplatform/it/LongChainSpec.scala @@ -12,14 +12,14 @@ class LongChainSpec extends FreeSpec with IntegrationSuite { val minerConfig = noDelayConfig.withFallback(Docker.nodeConfigs.head) val followerConfig = nonGeneratingPeerConfig.withFallback(Docker.nodeConfigs(1)) val miner = docker.startNode(minerConfig).success.value - val blocksCount = 250 + val blocksCount = 300 val check = async { await(miner.waitForHeight(blocksCount)) val follower = docker.startNode(followerConfig).success.value await(follower.waitForHeight(blocksCount)) succeed } - Await.result(check, 10.minutes) + Await.result(check, 15.minutes) } } From 90838d2bdd78aeaa53ed8ed510241459b61e8105 Mon Sep 17 00:00:00 2001 From: catena Date: Tue, 17 Jul 2018 17:14:20 +0300 Subject: [PATCH 04/11] Do not recalculate UTXO state digest when not needed. close #363 --- .../nodeView/state/ErgoState.scala | 3 ++- .../nodeView/state/UtxoState.scala | 27 ++++++++++--------- .../nodeView/WrappedUtxoState.scala | 16 ++++++++++- 3 files changed, 32 insertions(+), 14 deletions(-) diff --git a/src/main/scala/org/ergoplatform/nodeView/state/ErgoState.scala b/src/main/scala/org/ergoplatform/nodeView/state/ErgoState.scala index ebf1519b47..e175c12611 100644 --- a/src/main/scala/org/ergoplatform/nodeView/state/ErgoState.scala +++ b/src/main/scala/org/ergoplatform/nodeView/state/ErgoState.scala @@ -141,7 +141,8 @@ object ErgoState extends ScorexLogging { settings.nodeSettings.stateType match { case StateType.Digest => DigestState.create(None, None, dir, settings) - case StateType.Utxo if dir.listFiles().nonEmpty => UtxoState.create(dir, constants) + case StateType.Utxo if dir.listFiles().nonEmpty => + UtxoState.create(dir, constants, settings.chainSettings.monetary.afterGenesisStateDigest) case _ => ErgoState.generateGenesisUtxoState(dir, constants)._1 } } diff --git a/src/main/scala/org/ergoplatform/nodeView/state/UtxoState.scala b/src/main/scala/org/ergoplatform/nodeView/state/UtxoState.scala index c1d9c23d2d..c99033b69b 100644 --- a/src/main/scala/org/ergoplatform/nodeView/state/UtxoState.scala +++ b/src/main/scala/org/ergoplatform/nodeView/state/UtxoState.scala @@ -24,7 +24,8 @@ import scala.util.{Failure, Success, Try} * * @param store - database where persistent UTXO set authenticated with the help of an AVL+ tree is residing */ -class UtxoState(override val version: VersionTag, +class UtxoState(override val rootHash: ADDigest, + override val version: VersionTag, override val store: Store, override val constants: StateConstants) extends ErgoState[UtxoState] @@ -40,16 +41,15 @@ class UtxoState(override val version: VersionTag, override val maxRollbackDepth = 10 - override lazy val rootHash: ADDigest = persistentProver.digest - override def rollbackTo(version: VersionTag): Try[UtxoState] = { val p = persistentProver log.info(s"Rollback UtxoState to version ${Algos.encoder.encode(version)}") store.get(ByteArrayWrapper(version)) match { case Some(hash) => - val rollbackResult = p.rollback(ADDigest @@ hash.data).map { _ => - new UtxoState(version, store, constants) { - override protected lazy val persistentProver = p + val rootHash: ADDigest = ADDigest @@ hash.data + val rollbackResult = p.rollback(rootHash).map { _ => + new UtxoState(rootHash, version, store, constants) { + override protected lazy val persistentProver: PersistentBatchAVLProver[Digest32, HF] = p } } store.clean(constants.keepVersions) @@ -118,7 +118,7 @@ class UtxoState(override val version: VersionTag, log.info(s"Valid modifier with header ${fb.header.encodedId} and emission box " + s"${emissionBox.map(e => Algos.encode(e.id))} applied to UtxoState with root hash ${Algos.encode(rootHash)}") - new UtxoState(VersionTag @@ fb.id, store, constants) + new UtxoState(fb.header.stateRoot, VersionTag @@ fb.id, store, constants) } stateTry.recoverWith[UtxoState] { case e => log.warn(s"Error while applying full block with header ${fb.header.encodedId} to UTXOState with root" + @@ -128,7 +128,7 @@ class UtxoState(override val version: VersionTag, } case h: Header => - Success(new UtxoState(VersionTag @@ h.id, this.store, constants)) + Success(new UtxoState(rootHash, VersionTag @@ h.id, this.store, constants)) case a: Any => log.info(s"Unhandled modifier: $a") @@ -159,10 +159,13 @@ object UtxoState { Seq(idStateDigestIdxElem, stateDigestIdIdxElem, bestVersion, eb, cb) } - def create(dir: File, constants: StateConstants): UtxoState = { + def create(dir: File, constants: StateConstants, genesisDigest: ADDigest): UtxoState = { val store = new LSMStore(dir, keepVersions = constants.keepVersions) - val dbVersion = store.get(ByteArrayWrapper(bestVersionKey)).map(VersionTag @@ _.data) - new UtxoState(dbVersion.getOrElse(ErgoState.genesisStateVersion), store, constants) + val dbVersionOpt = store.get(ByteArrayWrapper(bestVersionKey)).map(VersionTag @@ _.data) + val dbVersion = dbVersionOpt.getOrElse(ErgoState.genesisStateVersion) + val rootHash: ADDigest = dbVersionOpt.flatMap(v => store.get(ByteArrayWrapper(v)).map(d => ADDigest @@ d.data)) + .getOrElse(genesisDigest) + new UtxoState(rootHash, dbVersion, store, constants) } @SuppressWarnings(Array("OptionGet", "TryGet")) @@ -176,7 +179,7 @@ object UtxoState { val store = new LSMStore(dir, keepVersions = constants.keepVersions) val defaultStateContext = ErgoStateContext(0, p.digest) - new UtxoState(ErgoState.genesisStateVersion, store, constants) { + new UtxoState(p.digest, ErgoState.genesisStateVersion, store, constants) { override protected lazy val persistentProver = PersistentBatchAVLProver.create( p, diff --git a/src/test/scala/org/ergoplatform/nodeView/WrappedUtxoState.scala b/src/test/scala/org/ergoplatform/nodeView/WrappedUtxoState.scala index 16ab764260..1faca16d09 100644 --- a/src/test/scala/org/ergoplatform/nodeView/WrappedUtxoState.scala +++ b/src/test/scala/org/ergoplatform/nodeView/WrappedUtxoState.scala @@ -10,7 +10,12 @@ import org.ergoplatform.mining.emission.CoinsEmission import org.ergoplatform.modifiers.ErgoPersistentModifier import org.ergoplatform.modifiers.mempool.ErgoTransaction import org.ergoplatform.nodeView.state._ +import org.ergoplatform.settings.Algos +import org.ergoplatform.settings.Algos.HF import scorex.core.{TransactionsCarryingPersistentNodeViewModifier, VersionTag} +import scorex.crypto.authds.ADDigest +import scorex.crypto.authds.avltree.batch._ +import scorex.crypto.hash.Digest32 import scala.util.{Failure, Success, Try} @@ -19,7 +24,16 @@ class WrappedUtxoState(override val version: VersionTag, store: Store, val versionedBoxHolder: VersionedInMemoryBoxHolder, constants: StateConstants) - extends UtxoState(version, store, constants) { + extends { + val digest: ADDigest = { + // todo do not recalculate? + implicit val hf = Algos.hash + val bp: BatchAVLProver[Digest32, HF] = new BatchAVLProver[Digest32, HF](keyLength = 32, valueLengthOpt = None) + val np = NodeParameters(keySize = 32, valueSize = None, labelSize = 32) + val storage: VersionedAVLStorage[Digest32] = new VersionedIODBAVLStorage(store, np) + PersistentBatchAVLProver.create(bp, storage).get.digest + } + } with UtxoState(digest, version, store, constants) { def size: Int = versionedBoxHolder.size From 209133bd3e7177b8de269fe05f56d7cdc8cd2146 Mon Sep 17 00:00:00 2001 From: catena Date: Tue, 17 Jul 2018 21:56:56 +0300 Subject: [PATCH 05/11] Process persistentProver from state to state --- .../nodeView/state/UtxoState.scala | 60 ++++++++++++------- .../nodeView/WrappedUtxoState.scala | 9 ++- 2 files changed, 41 insertions(+), 28 deletions(-) diff --git a/src/main/scala/org/ergoplatform/nodeView/state/UtxoState.scala b/src/main/scala/org/ergoplatform/nodeView/state/UtxoState.scala index c99033b69b..e5b44bcdf1 100644 --- a/src/main/scala/org/ergoplatform/nodeView/state/UtxoState.scala +++ b/src/main/scala/org/ergoplatform/nodeView/state/UtxoState.scala @@ -20,11 +20,14 @@ import scorex.crypto.hash.Digest32 import scala.util.{Failure, Success, Try} /** - * Utxo set implementation. + * Utxo set implementation * - * @param store - database where persistent UTXO set authenticated with the help of an AVL+ tree is residing + * @param persistentProver - persistent prover that build authenticated AVL+ tree on top of utxo set + * @param store - storage of persistentProver that also keeps metadata + * @param version - current state version + * @param constants - constants, that do not change with state version changes */ -class UtxoState(override val rootHash: ADDigest, +class UtxoState(persistentProver: PersistentBatchAVLProver[Digest32, HF], override val version: VersionTag, override val store: Store, override val constants: StateConstants) @@ -32,6 +35,8 @@ class UtxoState(override val rootHash: ADDigest, with TransactionValidation[ErgoTransaction] with UtxoStateReader { + override def rootHash: ADDigest = persistentProver.digest + private def onAdProofGenerated(proof: ADProofs): Unit = { if (constants.nodeViewHolderRef.isEmpty) log.warn("Got proof while nodeViewHolderRef is empty") constants.nodeViewHolderRef.foreach(h => h ! LocallyGeneratedModifier(proof)) @@ -48,7 +53,7 @@ class UtxoState(override val rootHash: ADDigest, case Some(hash) => val rootHash: ADDigest = ADDigest @@ hash.data val rollbackResult = p.rollback(rootHash).map { _ => - new UtxoState(rootHash, version, store, constants) { + new UtxoState(p, version, store, constants) { override protected lazy val persistentProver: PersistentBatchAVLProver[Digest32, HF] = p } } @@ -118,7 +123,7 @@ class UtxoState(override val rootHash: ADDigest, log.info(s"Valid modifier with header ${fb.header.encodedId} and emission box " + s"${emissionBox.map(e => Algos.encode(e.id))} applied to UtxoState with root hash ${Algos.encode(rootHash)}") - new UtxoState(fb.header.stateRoot, VersionTag @@ fb.id, store, constants) + new UtxoState(persistentProver, VersionTag @@ fb.id, store, constants) } stateTry.recoverWith[UtxoState] { case e => log.warn(s"Error while applying full block with header ${fb.header.encodedId} to UTXOState with root" + @@ -128,7 +133,7 @@ class UtxoState(override val rootHash: ADDigest, } case h: Header => - Success(new UtxoState(rootHash, VersionTag @@ h.id, this.store, constants)) + Success(new UtxoState(persistentProver, VersionTag @@ h.id, this.store, constants)) case a: Any => log.info(s"Unhandled modifier: $a") @@ -143,6 +148,18 @@ class UtxoState(override val rootHash: ADDigest, } object UtxoState { + + def apply(version: VersionTag, store: Store, constants: StateConstants): UtxoState = { + val persistentProver: PersistentBatchAVLProver[Digest32, HF] = { + val bp = new BatchAVLProver[Digest32, HF](keyLength = 32, valueLengthOpt = None) + val np = NodeParameters(keySize = 32, valueSize = None, labelSize = 32) + val storage: VersionedIODBAVLStorage[Digest32] = new VersionedIODBAVLStorage(store, np)(Algos.hash) + PersistentBatchAVLProver.create(bp, storage).get + } + new UtxoState(persistentProver, version: VersionTag, store: Store, constants: StateConstants) + + } + private lazy val bestVersionKey = Algos.hash("best state version") val EmissionBoxIdKey = Algos.hash("emission box id key") @@ -161,11 +178,9 @@ object UtxoState { def create(dir: File, constants: StateConstants, genesisDigest: ADDigest): UtxoState = { val store = new LSMStore(dir, keepVersions = constants.keepVersions) - val dbVersionOpt = store.get(ByteArrayWrapper(bestVersionKey)).map(VersionTag @@ _.data) - val dbVersion = dbVersionOpt.getOrElse(ErgoState.genesisStateVersion) - val rootHash: ADDigest = dbVersionOpt.flatMap(v => store.get(ByteArrayWrapper(v)).map(d => ADDigest @@ d.data)) - .getOrElse(genesisDigest) - new UtxoState(rootHash, dbVersion, store, constants) + val dbVersion = store.get(ByteArrayWrapper(bestVersionKey)).map(VersionTag @@ _.data) + .getOrElse(ErgoState.genesisStateVersion) + UtxoState(dbVersion, store, constants) } @SuppressWarnings(Array("OptionGet", "TryGet")) @@ -178,17 +193,16 @@ object UtxoState { val store = new LSMStore(dir, keepVersions = constants.keepVersions) val defaultStateContext = ErgoStateContext(0, p.digest) - - new UtxoState(p.digest, ErgoState.genesisStateVersion, store, constants) { - override protected lazy val persistentProver = - PersistentBatchAVLProver.create( - p, - storage, - metadata(ErgoState.genesisStateVersion, p.digest, currentEmissionBoxOpt, defaultStateContext), - paranoidChecks = true - ).get - - assert(persistentProver.digest.sameElements(storage.version.get)) - } + val np = NodeParameters(keySize = 32, valueSize = None, labelSize = 32) + val storage: VersionedIODBAVLStorage[Digest32] = new VersionedIODBAVLStorage(store, np)(Algos.hash) + val persistentProver = PersistentBatchAVLProver.create( + p, + storage, + metadata(ErgoState.genesisStateVersion, p.digest, currentEmissionBoxOpt, defaultStateContext), + paranoidChecks = true + ).get + + new UtxoState(persistentProver, ErgoState.genesisStateVersion, store, constants) } } + diff --git a/src/test/scala/org/ergoplatform/nodeView/WrappedUtxoState.scala b/src/test/scala/org/ergoplatform/nodeView/WrappedUtxoState.scala index 1faca16d09..d501dcebcc 100644 --- a/src/test/scala/org/ergoplatform/nodeView/WrappedUtxoState.scala +++ b/src/test/scala/org/ergoplatform/nodeView/WrappedUtxoState.scala @@ -25,15 +25,14 @@ class WrappedUtxoState(override val version: VersionTag, val versionedBoxHolder: VersionedInMemoryBoxHolder, constants: StateConstants) extends { - val digest: ADDigest = { + val prover: PersistentBatchAVLProver[Digest32, HF] = { // todo do not recalculate? - implicit val hf = Algos.hash val bp: BatchAVLProver[Digest32, HF] = new BatchAVLProver[Digest32, HF](keyLength = 32, valueLengthOpt = None) val np = NodeParameters(keySize = 32, valueSize = None, labelSize = 32) - val storage: VersionedAVLStorage[Digest32] = new VersionedIODBAVLStorage(store, np) - PersistentBatchAVLProver.create(bp, storage).get.digest + val storage: VersionedAVLStorage[Digest32] = new VersionedIODBAVLStorage(store, np)(Algos.hash) + PersistentBatchAVLProver.create(bp, storage).get } - } with UtxoState(digest, version, store, constants) { + } with UtxoState(prover, version, store, constants) { def size: Int = versionedBoxHolder.size From fd7a8864a7194d2fe8b53ccf693f192fa5ebc781 Mon Sep 17 00:00:00 2001 From: catena Date: Tue, 17 Jul 2018 22:04:08 +0300 Subject: [PATCH 06/11] TODO with problems --- .../history/storage/modifierprocessors/FullBlockProcessor.scala | 1 + 1 file changed, 1 insertion(+) 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 46de7d1221..80d6224fd1 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 @@ -37,6 +37,7 @@ trait FullBlockProcessor extends HeadersProcessor { */ protected def processFullBlock(fullBlock: ErgoFullBlock, newMod: ErgoPersistentModifier): ProgressInfo[ErgoPersistentModifier] = { + // TODO this is very inefficient - in most cases we do not need to calculate `bestFullChain` val bestFullChain = calculateBestFullChain(fullBlock) val newBestAfterThis = bestFullChain.last.header processing(ToProcess(fullBlock, newMod, newBestAfterThis, config.blocksToKeep, bestFullChain)) From 58f73f61132b0ffa67b31ff7cc08ef2cb9d354ce Mon Sep 17 00:00:00 2001 From: catena Date: Tue, 17 Jul 2018 23:07:27 +0300 Subject: [PATCH 07/11] Reorder logs for clean application time --- src/main/scala/org/ergoplatform/ErgoApp.scala | 1 - .../org/ergoplatform/nodeView/state/UtxoState.scala | 12 ++++++------ 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/src/main/scala/org/ergoplatform/ErgoApp.scala b/src/main/scala/org/ergoplatform/ErgoApp.scala index 48c1170139..9c1ca895f9 100644 --- a/src/main/scala/org/ergoplatform/ErgoApp.scala +++ b/src/main/scala/org/ergoplatform/ErgoApp.scala @@ -43,7 +43,6 @@ class ErgoApp(args: Seq[String]) extends Application { val readersHolderRef: ActorRef = ErgoReadersHolderRef(nodeViewHolderRef) - val minerRef: ActorRef = ErgoMinerRef(ergoSettings, nodeViewHolderRef, readersHolderRef, timeProvider, emission) val statsCollectorRef: ActorRef = ErgoStatsCollectorRef(nodeViewHolderRef, peerManagerRef, ergoSettings, timeProvider) diff --git a/src/main/scala/org/ergoplatform/nodeView/state/UtxoState.scala b/src/main/scala/org/ergoplatform/nodeView/state/UtxoState.scala index e5b44bcdf1..d9fc3e4cfd 100644 --- a/src/main/scala/org/ergoplatform/nodeView/state/UtxoState.scala +++ b/src/main/scala/org/ergoplatform/nodeView/state/UtxoState.scala @@ -35,7 +35,7 @@ class UtxoState(persistentProver: PersistentBatchAVLProver[Digest32, HF], with TransactionValidation[ErgoTransaction] with UtxoStateReader { - override def rootHash: ADDigest = persistentProver.digest + override lazy val rootHash: ADDigest = persistentProver.digest private def onAdProofGenerated(proof: ADProofs): Unit = { if (constants.nodeViewHolderRef.isEmpty) log.warn("Got proof while nodeViewHolderRef is empty") @@ -101,8 +101,8 @@ class UtxoState(persistentProver: PersistentBatchAVLProver[Digest32, HF], case fb: ErgoFullBlock => val height = fb.header.height - log.debug(s"Trying to apply full block with header ${fb.header.encodedId} at height $height " + - s"to UtxoState with root hash ${Algos.encode(rootHash)}") + log.debug(s"Trying to apply full block with header ${fb.header.encodedId} at height $height") + val inRoot = rootHash val stateTry: Try[UtxoState] = applyTransactions(fb.blockTransactions.txs, fb.header.stateRoot, height).map { _: Unit => val emissionBox = extractEmissionBox(fb) @@ -122,13 +122,13 @@ class UtxoState(persistentProver: PersistentBatchAVLProver[Digest32, HF], } log.info(s"Valid modifier with header ${fb.header.encodedId} and emission box " + - s"${emissionBox.map(e => Algos.encode(e.id))} applied to UtxoState with root hash ${Algos.encode(rootHash)}") + s"${emissionBox.map(e => Algos.encode(e.id))} applied to UtxoState with root hash ${Algos.encode(inRoot)}") new UtxoState(persistentProver, VersionTag @@ fb.id, store, constants) } stateTry.recoverWith[UtxoState] { case e => log.warn(s"Error while applying full block with header ${fb.header.encodedId} to UTXOState with root" + - s" ${Algos.encode(rootHash)}: ", e) - persistentProver.rollback(rootHash).ensuring(persistentProver.digest.sameElements(rootHash)) + s" ${Algos.encode(inRoot)}: ", e) + persistentProver.rollback(inRoot).ensuring(persistentProver.digest.sameElements(inRoot)) Failure(e) } From 68e033fd3b24908639cf149c10c06b970e61b47f Mon Sep 17 00:00:00 2001 From: catena Date: Tue, 17 Jul 2018 23:16:14 +0300 Subject: [PATCH 08/11] Invalidate cached value on pruning --- .../nodeView/history/storage/HistoryStorage.scala | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) 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 af64e4f797..08f3c511b8 100644 --- a/src/main/scala/org/ergoplatform/nodeView/history/storage/HistoryStorage.scala +++ b/src/main/scala/org/ergoplatform/nodeView/history/storage/HistoryStorage.scala @@ -17,8 +17,10 @@ class HistoryStorage(indexStore: Store, objectsStore: ObjectsStore, config: Cach .maximumSize(config.historyStorageCacheSize) .build[String, ErgoPersistentModifier] + private def keyById(id: ModifierId): String = Algos.encode(id) + def modifierById(id: ModifierId): Option[ErgoPersistentModifier] = { - val key = Algos.encode(id) + val key = keyById(id) Option(modifiersCache.getIfPresent(key)) match { case Some(e) => log.trace(s"Got modifier $key from cache") @@ -55,7 +57,10 @@ class HistoryStorage(indexStore: Store, objectsStore: ObjectsStore, config: Cach indexesToInsert) } - def remove(idsToRemove: Seq[ModifierId]): Unit = idsToRemove.foreach(id => objectsStore.delete(id)) + def remove(idsToRemove: Seq[ModifierId]): Unit = idsToRemove.foreach { id => + modifiersCache.invalidate(keyById(id)) + objectsStore.delete(id) + } override def close(): Unit = { log.warn("Closing history storage...") From 6b1cbd5f02c8bedf0acab18aa0d05df2438854f9 Mon Sep 17 00:00:00 2001 From: catena Date: Wed, 18 Jul 2018 08:36:54 +0300 Subject: [PATCH 09/11] Remove recreated prover from StateReader --- .../org/ergoplatform/nodeView/state/UtxoState.scala | 10 ++++------ .../ergoplatform/nodeView/state/UtxoStateReader.scala | 6 +----- 2 files changed, 5 insertions(+), 11 deletions(-) diff --git a/src/main/scala/org/ergoplatform/nodeView/state/UtxoState.scala b/src/main/scala/org/ergoplatform/nodeView/state/UtxoState.scala index d9fc3e4cfd..7a51644dcd 100644 --- a/src/main/scala/org/ergoplatform/nodeView/state/UtxoState.scala +++ b/src/main/scala/org/ergoplatform/nodeView/state/UtxoState.scala @@ -27,7 +27,7 @@ import scala.util.{Failure, Success, Try} * @param version - current state version * @param constants - constants, that do not change with state version changes */ -class UtxoState(persistentProver: PersistentBatchAVLProver[Digest32, HF], +class UtxoState(override val persistentProver: PersistentBatchAVLProver[Digest32, HF], override val version: VersionTag, override val store: Store, override val constants: StateConstants) @@ -35,7 +35,8 @@ class UtxoState(persistentProver: PersistentBatchAVLProver[Digest32, HF], with TransactionValidation[ErgoTransaction] with UtxoStateReader { - override lazy val rootHash: ADDigest = persistentProver.digest + + override def rootHash: ADDigest = persistentProver.digest private def onAdProofGenerated(proof: ADProofs): Unit = { if (constants.nodeViewHolderRef.isEmpty) log.warn("Got proof while nodeViewHolderRef is empty") @@ -53,9 +54,7 @@ class UtxoState(persistentProver: PersistentBatchAVLProver[Digest32, HF], case Some(hash) => val rootHash: ADDigest = ADDigest @@ hash.data val rollbackResult = p.rollback(rootHash).map { _ => - new UtxoState(p, version, store, constants) { - override protected lazy val persistentProver: PersistentBatchAVLProver[Digest32, HF] = p - } + new UtxoState(p, version, store, constants) } store.clean(constants.keepVersions) rollbackResult @@ -108,7 +107,6 @@ class UtxoState(persistentProver: PersistentBatchAVLProver[Digest32, HF], val emissionBox = extractEmissionBox(fb) val newStateContext = stateContext.appendHeader(fb.header) val md = metadata(VersionTag @@ fb.id, fb.header.stateRoot, emissionBox, newStateContext) - val proofBytes = persistentProver.generateProofAndUpdateStorage(md) val proofHash = ADProofs.proofDigest(proofBytes) if (fb.aDProofs.isEmpty) onAdProofGenerated(ADProofs(fb.header.id, proofBytes)) diff --git a/src/main/scala/org/ergoplatform/nodeView/state/UtxoStateReader.scala b/src/main/scala/org/ergoplatform/nodeView/state/UtxoStateReader.scala index 8d40af8f1e..d2b4127e38 100644 --- a/src/main/scala/org/ergoplatform/nodeView/state/UtxoStateReader.scala +++ b/src/main/scala/org/ergoplatform/nodeView/state/UtxoStateReader.scala @@ -22,11 +22,7 @@ trait UtxoStateReader extends ErgoStateReader with TransactionValidation[ErgoTra private lazy val np = NodeParameters(keySize = 32, valueSize = None, labelSize = 32) protected lazy val storage = new VersionedIODBAVLStorage(store, np) - - protected lazy val persistentProver: PersistentBatchAVLProver[Digest32, HF] = { - val bp = new BatchAVLProver[Digest32, HF](keyLength = 32, valueLengthOpt = None) - PersistentBatchAVLProver.create(bp, storage).get - } + protected val persistentProver: PersistentBatchAVLProver[Digest32, HF] override def validate(tx: ErgoTransaction): Try[Unit] = tx.statelessValidity .flatMap(_ => tx.statefulValidity(tx.inputs.flatMap(i => boxById(i.boxId)), stateContext).map(_ => Unit)) From 0c338147390f8110890cb47ba195ae3dbcb5abad Mon Sep 17 00:00:00 2001 From: catena Date: Wed, 18 Jul 2018 09:07:32 +0300 Subject: [PATCH 10/11] Remove UTXOState.appy --- .../history/storage/HistoryStorage.scala | 1 + .../nodeView/state/ErgoState.scala | 3 +-- .../nodeView/state/UtxoState.scala | 23 ++++++++----------- 3 files changed, 11 insertions(+), 16 deletions(-) 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 08f3c511b8..d0d9e0eacf 100644 --- a/src/main/scala/org/ergoplatform/nodeView/history/storage/HistoryStorage.scala +++ b/src/main/scala/org/ergoplatform/nodeView/history/storage/HistoryStorage.scala @@ -17,6 +17,7 @@ class HistoryStorage(indexStore: Store, objectsStore: ObjectsStore, config: Cach .maximumSize(config.historyStorageCacheSize) .build[String, ErgoPersistentModifier] + // TODO remove when modifierId will be string private def keyById(id: ModifierId): String = Algos.encode(id) def modifierById(id: ModifierId): Option[ErgoPersistentModifier] = { diff --git a/src/main/scala/org/ergoplatform/nodeView/state/ErgoState.scala b/src/main/scala/org/ergoplatform/nodeView/state/ErgoState.scala index e175c12611..ebf1519b47 100644 --- a/src/main/scala/org/ergoplatform/nodeView/state/ErgoState.scala +++ b/src/main/scala/org/ergoplatform/nodeView/state/ErgoState.scala @@ -141,8 +141,7 @@ object ErgoState extends ScorexLogging { settings.nodeSettings.stateType match { case StateType.Digest => DigestState.create(None, None, dir, settings) - case StateType.Utxo if dir.listFiles().nonEmpty => - UtxoState.create(dir, constants, settings.chainSettings.monetary.afterGenesisStateDigest) + case StateType.Utxo if dir.listFiles().nonEmpty => UtxoState.create(dir, constants) case _ => ErgoState.generateGenesisUtxoState(dir, constants)._1 } } diff --git a/src/main/scala/org/ergoplatform/nodeView/state/UtxoState.scala b/src/main/scala/org/ergoplatform/nodeView/state/UtxoState.scala index 7a51644dcd..6d6ed9eb81 100644 --- a/src/main/scala/org/ergoplatform/nodeView/state/UtxoState.scala +++ b/src/main/scala/org/ergoplatform/nodeView/state/UtxoState.scala @@ -147,17 +147,6 @@ class UtxoState(override val persistentProver: PersistentBatchAVLProver[Digest32 object UtxoState { - def apply(version: VersionTag, store: Store, constants: StateConstants): UtxoState = { - val persistentProver: PersistentBatchAVLProver[Digest32, HF] = { - val bp = new BatchAVLProver[Digest32, HF](keyLength = 32, valueLengthOpt = None) - val np = NodeParameters(keySize = 32, valueSize = None, labelSize = 32) - val storage: VersionedIODBAVLStorage[Digest32] = new VersionedIODBAVLStorage(store, np)(Algos.hash) - PersistentBatchAVLProver.create(bp, storage).get - } - new UtxoState(persistentProver, version: VersionTag, store: Store, constants: StateConstants) - - } - private lazy val bestVersionKey = Algos.hash("best state version") val EmissionBoxIdKey = Algos.hash("emission box id key") @@ -174,11 +163,17 @@ object UtxoState { Seq(idStateDigestIdxElem, stateDigestIdIdxElem, bestVersion, eb, cb) } - def create(dir: File, constants: StateConstants, genesisDigest: ADDigest): UtxoState = { + def create(dir: File, constants: StateConstants): UtxoState = { val store = new LSMStore(dir, keepVersions = constants.keepVersions) - val dbVersion = store.get(ByteArrayWrapper(bestVersionKey)).map(VersionTag @@ _.data) + val version = store.get(ByteArrayWrapper(bestVersionKey)).map(VersionTag @@ _.data) .getOrElse(ErgoState.genesisStateVersion) - UtxoState(dbVersion, store, constants) + val persistentProver: PersistentBatchAVLProver[Digest32, HF] = { + val bp = new BatchAVLProver[Digest32, HF](keyLength = 32, valueLengthOpt = None) + val np = NodeParameters(keySize = 32, valueSize = None, labelSize = 32) + val storage: VersionedIODBAVLStorage[Digest32] = new VersionedIODBAVLStorage(store, np)(Algos.hash) + PersistentBatchAVLProver.create(bp, storage).get + } + new UtxoState(persistentProver, version, store, constants) } @SuppressWarnings(Array("OptionGet", "TryGet")) From bd6ce08396183bd3481436a54a91cdce7a88d155 Mon Sep 17 00:00:00 2001 From: catena Date: Wed, 18 Jul 2018 09:09:49 +0300 Subject: [PATCH 11/11] WrappedUtxoState - do not recreate persistentProver --- .../nodeView/WrappedUtxoState.scala | 21 +++++++------------ 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/src/test/scala/org/ergoplatform/nodeView/WrappedUtxoState.scala b/src/test/scala/org/ergoplatform/nodeView/WrappedUtxoState.scala index d501dcebcc..c0ad242e66 100644 --- a/src/test/scala/org/ergoplatform/nodeView/WrappedUtxoState.scala +++ b/src/test/scala/org/ergoplatform/nodeView/WrappedUtxoState.scala @@ -20,19 +20,12 @@ import scorex.crypto.hash.Digest32 import scala.util.{Failure, Success, Try} -class WrappedUtxoState(override val version: VersionTag, +class WrappedUtxoState(prover: PersistentBatchAVLProver[Digest32, HF], + override val version: VersionTag, store: Store, val versionedBoxHolder: VersionedInMemoryBoxHolder, constants: StateConstants) - extends { - val prover: PersistentBatchAVLProver[Digest32, HF] = { - // todo do not recalculate? - val bp: BatchAVLProver[Digest32, HF] = new BatchAVLProver[Digest32, HF](keyLength = 32, valueLengthOpt = None) - val np = NodeParameters(keySize = 32, valueSize = None, labelSize = 32) - val storage: VersionedAVLStorage[Digest32] = new VersionedIODBAVLStorage(store, np)(Algos.hash) - PersistentBatchAVLProver.create(bp, storage).get - } - } with UtxoState(prover, version, store, constants) { + extends UtxoState(prover, version, store, constants) { def size: Int = versionedBoxHolder.size @@ -41,7 +34,7 @@ class WrappedUtxoState(override val version: VersionTag, override def rollbackTo(version: VersionTag): Try[WrappedUtxoState] = super.rollbackTo(version) match { case Success(us) => val updHolder = versionedBoxHolder.rollback(ByteArrayWrapper(us.version)) - Success(new WrappedUtxoState(version, us.store, updHolder, constants)) + Success(new WrappedUtxoState(us.persistentProver, version, us.store, updHolder, constants)) case Failure(e) => Failure(e) } @@ -56,10 +49,10 @@ class WrappedUtxoState(override val version: VersionTag, ByteArrayWrapper(us.version), changes.toRemove.map(_.boxId).map(ByteArrayWrapper.apply), changes.toAppend.map(_.box)) - Success(new WrappedUtxoState(VersionTag @@ mod.id, us.store, updHolder, constants)) + Success(new WrappedUtxoState(us.persistentProver, VersionTag @@ mod.id, us.store, updHolder, constants)) case _ => val updHolder = versionedBoxHolder.applyChanges(ByteArrayWrapper(us.version), Seq(), Seq()) - Success(new WrappedUtxoState(VersionTag @@ mod.id, us.store, updHolder, constants)) + Success(new WrappedUtxoState(us.persistentProver, VersionTag @@ mod.id, us.store, updHolder, constants)) } case Failure(e) => Failure(e) } @@ -85,6 +78,6 @@ object WrappedUtxoState { IndexedSeq(version), Map(version -> (Seq() -> boxHolder.sortedBoxes.toSeq))) - new WrappedUtxoState(ErgoState.genesisStateVersion, us.store, vbh, constants) + new WrappedUtxoState(us.persistentProver, ErgoState.genesisStateVersion, us.store, vbh, constants) } } \ No newline at end of file