Skip to content

Commit d46f871

Browse files
author
GRYE
committed
Fixed fast sync tests
1 parent 0700791 commit d46f871

File tree

7 files changed

+430
-545
lines changed

7 files changed

+430
-545
lines changed

src/main/scala/encry/view/state/avlTree/AvlTree.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,7 @@ final case class AvlTree[K : Hashable : Order, V](rootNode: Node[K, V], storage:
147147
kSer: Serializer[K],
148148
vSer: Serializer[V]
149149
): (Option[Node[K, V]], OperationInfo[K, V]) = node match {
150+
case _: EmptyNode[K, V] => (None, prevOpsInfo)
150151
case shadowNode: ShadowNode[K, V] =>
151152
val restoredNode = shadowNode.restoreFullNode(storage)
152153
delete(restoredNode, key, prevOpsInfo)

src/test/scala/encry/modifiers/InstanceFactory.scala

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,17 @@ import encry.consensus.EncrySupplyController
44
import encry.modifiers.mempool._
55
import encry.modifiers.state.Keys
66
import encry.settings.{EncryAppSettings, NodeSettings}
7+
import encry.storage.VersionalStorage.{StorageKey, StorageValue, StorageVersion}
78
import encry.storage.levelDb.versionalLevelDB.{LevelDbFactory, VLDBWrapper, VersionalLevelDBCompanion}
9+
import encry.utils.implicits.UTXO.combineAll
810
import encry.utils.{EncryGenerator, FileHelper, NetworkTimeProvider, TestHelper}
911
import encry.view.history.History
1012
import encry.view.history.storage.HistoryStorage
13+
import encry.view.state.UtxoState
14+
import encry.view.state.avlTree.AvlTree
1115
import io.iohk.iodb.LSMStore
1216
import org.encryfoundation.common.modifiers.history.{Block, Header, Payload}
17+
import org.encryfoundation.common.modifiers.mempool.transaction.EncryAddress.Address
1318
import org.encryfoundation.common.modifiers.mempool.transaction.{Input, Transaction}
1419
import org.encryfoundation.common.modifiers.state.box.{AssetBox, EncryProposition}
1520
import org.encryfoundation.common.modifiers.state.box.Box.Amount
@@ -170,6 +175,58 @@ trait InstanceFactory extends Keys with EncryGenerator {
170175
Block(header, Payload(header.id, txs))
171176
}
172177

178+
def generateNextBlockAndInsert(history: History,
179+
tree: AvlTree[StorageKey, StorageValue],
180+
insert: Boolean,
181+
difficultyDiff: BigInt = 0,
182+
prevId: Option[ModifierId] = None,
183+
txsQty: Int = 100,
184+
additionalDifficulty: BigInt = 0,
185+
addressOpt: Option[Address] = None): (Block, AvlTree[StorageKey, StorageValue]) = {
186+
187+
import encry.utils.implicits.UTXO._
188+
import encry.view.state.avlTree.utils.implicits.Instances._
189+
190+
val previousHeaderId: ModifierId =
191+
prevId.getOrElse(history.getBestHeader.map(_.id).getOrElse(Header.GenesisParentId))
192+
val requiredDifficulty: Difficulty = history.getBestHeader.map(parent =>
193+
history.requiredDifficultyAfter(parent).getOrElse(Difficulty @@ BigInt(0)))
194+
.getOrElse(history.settings.constants.InitialDifficulty)
195+
196+
val txs = { addressOpt match {
197+
case Some(address) => if (txsQty != 0) genValidPaymentTxsToAddr(Scarand.nextInt(txsQty), address) else Seq.empty
198+
case None => if (txsQty != 0) genValidPaymentTxs(Scarand.nextInt(txsQty)) else Seq.empty
199+
}
200+
201+
} ++ Seq(coinbaseAt(history.getBestHeaderHeight + 1))
202+
203+
val combinedStateChange: UtxoState.StateChange = combineAll(txs.map(UtxoState.tx2StateChange).toList)
204+
val newStateRoot = tree.getOperationsRootHash(
205+
combinedStateChange.outputsToDb.toList, combinedStateChange.inputsToDb.toList
206+
).get
207+
208+
val header = genHeader.copy(
209+
parentId = previousHeaderId,
210+
height = history.getBestHeaderHeight + 1,
211+
difficulty = Difficulty @@ (requiredDifficulty + difficultyDiff + additionalDifficulty),
212+
transactionsRoot = Payload.rootHash(txs.map(_.id)),
213+
stateRoot = newStateRoot
214+
)
215+
216+
val block = Block(header, Payload(header.id, txs))
217+
218+
val newTree: AvlTree[StorageKey, StorageValue] = if (insert)
219+
tree.insertAndDeleteMany(
220+
StorageVersion !@@ block.id,
221+
combinedStateChange.outputsToDb.toList,
222+
combinedStateChange.inputsToDb.toList,
223+
Height @@ block.header.height
224+
) else tree
225+
226+
(block, newTree)
227+
228+
}
229+
173230
def genForkOn(qty: Int,
174231
addDifficulty: BigInt = 0,
175232
from: Int,

src/test/scala/encry/network/DeliveryManagerTests/DMUtils.scala

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package encry.network.DeliveryManagerTests
22

3+
import java.io.File
34
import java.net.InetSocketAddress
5+
46
import akka.actor.ActorSystem
57
import akka.testkit.{TestActorRef, TestProbe}
68
import encry.local.miner.Miner.{DisableMining, StartMining}
@@ -10,10 +12,18 @@ import encry.network.DeliveryManager.FullBlockChainIsSynced
1012
import encry.network.NodeViewSynchronizer.ReceivableMessages.UpdatedHistory
1113
import encry.network.PeerConnectionHandler.{ConnectedPeer, Incoming}
1214
import encry.settings.EncryAppSettings
15+
import encry.storage.VersionalStorage.{StorageKey, StorageValue}
16+
import encry.storage.levelDb.versionalLevelDB.{LevelDbFactory, VLDBWrapper, VersionalLevelDBCompanion}
17+
import encry.utils.FileHelper
18+
import encry.view.fast.sync.FastSyncTestsUtils.settings
1319
import encry.view.history.History
20+
import encry.view.state.avlTree.AvlTree
1421
import org.encryfoundation.common.modifiers.history.Block
22+
import org.encryfoundation.common.modifiers.mempool.transaction.EncryAddress.Address
1523
import org.encryfoundation.common.network.BasicMessagesRepo.Handshake
1624
import org.encryfoundation.common.utils.TaggedTypes.ModifierId
25+
import org.iq80.leveldb.Options
26+
1727
import scala.collection.mutable
1828
import scala.collection.mutable.WrappedArray
1929

@@ -44,6 +54,36 @@ object DMUtils extends InstanceFactory {
4454
(a, blocks :+ block)
4555
}
4656

57+
def generateBlocksWithTree(qty: Int,
58+
history: History,
59+
prevTreeOpt: Option[AvlTree[StorageKey, StorageValue]] = None,
60+
addressOpt: Option[Address] = None): (History, List[Block], AvlTree[StorageKey, StorageValue]) = {
61+
62+
import encry.view.state.avlTree.utils.implicits.Instances._
63+
64+
val avl: AvlTree[StorageKey, StorageValue] = prevTreeOpt match {
65+
case Some(t) => t
66+
case None =>
67+
val dir: File = FileHelper.getRandomTempDir
68+
val storage: VLDBWrapper = {
69+
val levelDBInit = LevelDbFactory.factory.open(dir, new Options)
70+
VLDBWrapper(VersionalLevelDBCompanion(levelDBInit, settings.levelDB, keySize = 32))
71+
}
72+
73+
AvlTree[StorageKey, StorageValue](storage)
74+
}
75+
76+
(0 until qty).foldLeft(history, List.empty[Block], avl) {
77+
case ((prevHistory, blocks, tree), _) =>
78+
val (block: Block, newTree: AvlTree[StorageKey, StorageValue]) =
79+
generateNextBlockAndInsert(prevHistory, tree, prevTreeOpt.isEmpty, addressOpt = addressOpt)
80+
prevHistory.append(block.header)
81+
prevHistory.append(block.payload)
82+
val newHist = prevHistory.reportModifierIsValid(block)
83+
(newHist, blocks :+ block, newTree)
84+
}
85+
}
86+
4787
def toKey(id: ModifierId): WrappedArray.ofByte = new mutable.WrappedArray.ofByte(id)
4888

4989
def createPeer(port: Int,

src/test/scala/encry/view/fast/sync/FastSyncTestsUtils.scala

Lines changed: 41 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -8,72 +8,57 @@ import encry.settings.TestNetSettings
88
import encry.storage.VersionalStorage.{StorageKey, StorageValue, StorageVersion}
99
import encry.storage.levelDb.versionalLevelDB.{LevelDbFactory, VLDBWrapper, VersionalLevelDBCompanion}
1010
import encry.utils.FileHelper
11-
import encry.view.fast.sync.SnapshotHolder.SnapshotManifest
11+
import encry.view.fast.sync.SnapshotHolder.{SnapshotChunk, SnapshotManifest}
1212
import encry.view.history.History
13-
import encry.view.state.UtxoState
1413
import encry.view.state.avlTree.AvlTree
1514
import org.iq80.leveldb.Options
1615
import scorex.utils.Random
1716
import encry.view.state.avlTree.utils.implicits.Instances._
1817
import org.encryfoundation.common.modifiers.history.Block
18+
import org.encryfoundation.common.modifiers.mempool.transaction.EncryAddress.Address
1919
import org.encryfoundation.common.utils.Algos
20-
import org.encryfoundation.common.utils.TaggedTypes.Height
2120

2221
object FastSyncTestsUtils extends InstanceFactory with TestNetSettings {
2322

24-
// def initializeTestState(
25-
// from: Int = 0,
26-
// to: Int = 100
27-
// ): (AvlTree[StorageKey, StorageValue],
28-
// SnapshotProcessor,
29-
// SnapshotDownloadController,
30-
// List[Block],
31-
// SnapshotManifest,
32-
// History) = {
33-
// val firstDir: File = FileHelper.getRandomTempDir
34-
// val firstStorage: VLDBWrapper = {
35-
// val levelDBInit = LevelDbFactory.factory.open(firstDir, new Options)
36-
// VLDBWrapper(VersionalLevelDBCompanion(levelDBInit, settings.levelDB, keySize = 32))
37-
// }
38-
// val history = generateDummyHistory(settings)
39-
// val (_, blocks) = DMUtils.generateBlocks(5, history)
40-
//
41-
// val boxes: List[(StorageKey, StorageValue)] = blocks
42-
// .flatMap(_.payload.txs.flatMap(_.newBoxes))
43-
// .map { bx =>
44-
// (StorageKey !@@ bx.id, StorageValue @@ bx.bytes)
45-
// }
46-
//
47-
// val firstAvl: AvlTree[StorageKey, StorageValue] = AvlTree[StorageKey, StorageValue](firstStorage)
48-
// val secondAvl = firstAvl
49-
// .insertAndDeleteMany(
50-
// StorageVersion @@ Random.randomBytes(),
51-
// boxes,
52-
// List.empty
53-
// )
54-
//
55-
// val newBlocks = blocks.map(l => Block(l.header.copy(stateRoot = secondAvl.rootHash), l.payload))
56-
// val history1 = generateDummyHistory(settings)
57-
// val historyNew1 = newBlocks.foldLeft(history1) {
58-
// case (history, block) =>
59-
// history.append(block.header)
60-
// history.append(block.payload)
61-
// history.reportModifierIsValid(block)
62-
// }
63-
//
64-
// val snapshotProcessor: SnapshotProcessor = SnapshotProcessor
65-
// .create(settings, tmpDir)
66-
// .processNewSnapshot(UtxoState(secondAvl, Height @@ 0, settings.constants), newBlocks.last).right.get
67-
//
68-
// val snapshotDownloadController = SnapshotDownloadController.empty(settings)
69-
//
70-
// (secondAvl,
71-
// snapshotProcessor,
72-
// snapshotDownloadController,
73-
// newBlocks,
74-
// snapshotProcessor.manifestById(StorageKey @@ Algos.hash(secondAvl.rootHash ++ newBlocks.last.id)).get,
75-
// historyNew1)
76-
// }
23+
def initializeTestState(initialBlocksQty: Int = 90,
24+
additionalBlocksQty: Int = 10,
25+
addressOpt: Option[Address] = None
26+
): (AvlTree[StorageKey, StorageValue],
27+
SnapshotProcessor,
28+
SnapshotDownloadController,
29+
List[Block],
30+
SnapshotManifest,
31+
History) = {
32+
33+
val (history, blocks, tree) = DMUtils.generateBlocksWithTree(initialBlocksQty, generateDummyHistory(settings), None, addressOpt)
34+
val (_, additionalBlocks, _) = DMUtils.generateBlocksWithTree(additionalBlocksQty, history, Some(tree), addressOpt)
35+
36+
val chunk = SnapshotChunk(tree.rootNode, tree.rootHash)
37+
38+
val snapshotProcessor: SnapshotProcessor = SnapshotProcessor
39+
.create(settings.copy(levelDB = settings.levelDB.copy(maxVersions = 10)), tmpDir)
40+
.initializeApplicableChunksCache(history, history.getBestBlockHeight).right.get
41+
.updateCache(chunk)
42+
43+
val mans = snapshotProcessor.potentialManifestsIds
44+
val sp = snapshotProcessor.createNewSnapshot(
45+
Algos.hash(blocks.last.header.stateRoot ++ blocks.last.header.id),
46+
mans,
47+
List(chunk)
48+
).right.get
49+
50+
val newProc = sp.processNewBlock(additionalBlocks.last, history).right.get
51+
52+
val snapshotDownloadController = SnapshotDownloadController.empty(settings)
53+
54+
55+
(tree,
56+
newProc,
57+
snapshotDownloadController,
58+
blocks ++ additionalBlocks,
59+
newProc.actualManifest.get,
60+
history)
61+
}
7762

7863
def createAvl(address: String, from: Int, to: Int): AvlTree[StorageKey, StorageValue] = {
7964
val firstDir: File = FileHelper.getRandomTempDir
Lines changed: 34 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,47 +1,34 @@
1-
//package encry.view.fastSync
2-
//
3-
//import java.io.File
4-
//import SnapshotChunkProto.SnapshotChunkMessage
5-
//import encry.view.state.avlTree.utils.implicits.Instances._
6-
//import encry.modifiers.InstanceFactory
7-
//import encry.settings.TestNetSettings
8-
//import encry.storage.VersionalStorage.{ StorageKey, StorageValue, StorageVersion }
9-
//import encry.storage.levelDb.versionalLevelDB.{ LevelDbFactory, VLDBWrapper, VersionalLevelDBCompanion }
10-
//import encry.utils.FileHelper
11-
//import encry.view.fastSync.SnapshotHolder.SnapshotChunkSerializer
12-
//import encry.view.state.UtxoState
13-
//import encry.view.state.avlTree.AvlTree
14-
//import org.encryfoundation.common.utils.TaggedTypes.Height
15-
//import org.iq80.leveldb.Options
16-
//import org.scalatest.{ Matchers, OneInstancePerTest, WordSpecLike }
17-
//import scorex.utils.Random
18-
//import scala.util.Try
19-
//
20-
//class SnapshotChunkSerializerTest
21-
// extends WordSpecLike
22-
// with Matchers
23-
// with InstanceFactory
24-
// with OneInstancePerTest
25-
// with TestNetSettings {
26-
//
27-
// "SnapshotChunkSerializer" should {
28-
// "serialize|deserialize correctly" in {
29-
// val avl1 = createAvl("9gKDVmfsA6J4b78jDBx6JmS86Zph98NnjnUqTJBkW7zitQMReia")
30-
// val block1 = generateGenesisBlock(Height @@ 1)
31-
// val snapshotProcessor: SnapshotProcessor = SnapshotProcessor.create(settings, tmpDir)
32-
// val processor1: SnapshotProcessor =
33-
// snapshotProcessor.processNewSnapshot(UtxoState(avl1, Height @@ 0, settings.constants), block1)
34-
// val manifest1: SnapshotHolder.SnapshotManifest = processor1.bestPotentialManifest.get
35-
// val chunk: SnapshotChunkMessage = processor1.getChunkById(manifest1.chunksKeys.head).get
36-
// val chunkR: SnapshotHolder.SnapshotChunk = SnapshotChunkSerializer.fromProto(chunk).get
37-
//
38-
// val bytesChunk: Array[Byte] = SnapshotChunkSerializer.toProto(chunkR).toByteArray
39-
// bytesChunk.isEmpty shouldBe false
40-
// val ser: SnapshotChunkMessage = Try(SnapshotChunkMessage.parseFrom(bytesChunk)).get
41-
// val deser: SnapshotHolder.SnapshotChunk = SnapshotChunkSerializer.fromProto(ser).get
42-
//
43-
// chunkR.id.sameElements(deser.id) shouldBe true
44-
// }
45-
// }
46-
//
47-
//}
1+
package encry.view.fast.sync
2+
3+
import SnapshotChunkProto.SnapshotChunkMessage
4+
import encry.modifiers.InstanceFactory
5+
import encry.settings.TestNetSettings
6+
import encry.view.fast.sync.SnapshotHolder.SnapshotChunkSerializer
7+
import org.scalatest.{Matchers, OneInstancePerTest, WordSpecLike}
8+
import encry.view.fast.sync.FastSyncTestsUtils._
9+
10+
import scala.util.Try
11+
12+
class SnapshotChunkSerializerTest extends WordSpecLike
13+
with Matchers
14+
with InstanceFactory
15+
with OneInstancePerTest
16+
with TestNetSettings {
17+
18+
"SnapshotChunkSerializer" should {
19+
"serialize|deserialize correctly" in {
20+
val (_, processor, _, _, manifest, _) = initializeTestState()
21+
22+
val chunk: SnapshotChunkMessage = processor.getChunkById(manifest.chunksKeys.head).get
23+
val chunkR: SnapshotHolder.SnapshotChunk = SnapshotChunkSerializer.fromProto(chunk).get
24+
25+
val bytesChunk: Array[Byte] = SnapshotChunkSerializer.toProto(chunkR).toByteArray
26+
bytesChunk.isEmpty shouldBe false
27+
val ser: SnapshotChunkMessage = Try(SnapshotChunkMessage.parseFrom(bytesChunk)).get
28+
val deser: SnapshotHolder.SnapshotChunk = SnapshotChunkSerializer.fromProto(ser).get
29+
30+
chunkR.id.sameElements(deser.id) shouldBe true
31+
}
32+
}
33+
34+
}

0 commit comments

Comments
 (0)