1
1
package io .iohk .ethereum .sync
2
2
3
3
import java .net .{InetSocketAddress , ServerSocket }
4
+ import java .nio .file .Files
4
5
import java .util .concurrent .TimeoutException
5
6
import java .util .concurrent .atomic .AtomicReference
6
7
@@ -9,9 +10,12 @@ import akka.testkit.TestProbe
9
10
import akka .util .{ByteString , Timeout }
10
11
import cats .effect .Resource
11
12
import io .iohk .ethereum .Mocks .MockValidatorsAlwaysSucceed
12
- import io .iohk .ethereum .blockchain .sync .{BlockchainHostActor , FastSync , TestSyncConfig }
13
- import io .iohk .ethereum .db .components .{SharedEphemDataSources , Storages }
14
- import io .iohk .ethereum .db .storage .AppStateStorage
13
+ import io .iohk .ethereum .blockchain .sync .regular .BlockBroadcasterActor
14
+ import io .iohk .ethereum .blockchain .sync .regular .BlockBroadcasterActor .BroadcastBlock
15
+ import io .iohk .ethereum .blockchain .sync .{BlockBroadcast , BlockchainHostActor , FastSync , TestSyncConfig }
16
+ import io .iohk .ethereum .db .components .{SharedRocksDbDataSources , Storages }
17
+ import io .iohk .ethereum .db .dataSource .{RocksDbConfig , RocksDbDataSource }
18
+ import io .iohk .ethereum .db .storage .{AppStateStorage , Namespaces }
15
19
import io .iohk .ethereum .db .storage .pruning .{ArchivePruning , PruningMode }
16
20
import io .iohk .ethereum .domain .{Account , Address , Block , Blockchain , BlockchainImpl }
17
21
import io .iohk .ethereum .ledger .InMemoryWorldStateProxy
@@ -22,6 +26,7 @@ import io.iohk.ethereum.network.discovery.Node
22
26
import io .iohk .ethereum .network .discovery .PeerDiscoveryManager .{DiscoveredNodesInfo , DiscoveryNodeInfo }
23
27
import io .iohk .ethereum .network .handshaker .{EtcHandshaker , EtcHandshakerConfiguration , Handshaker }
24
28
import io .iohk .ethereum .network .p2p .EthereumMessageDecoder
29
+ import io .iohk .ethereum .network .p2p .messages .CommonMessages .NewBlock
25
30
import io .iohk .ethereum .network .rlpx .AuthHandshaker
26
31
import io .iohk .ethereum .network .rlpx .RLPxConnectionHandler .RLPxConfiguration
27
32
import io .iohk .ethereum .network .{EtcPeerManagerActor , ForkResolver , KnownNodesManager , PeerEventBusActor , PeerManagerActor , ServerActor }
@@ -51,8 +56,8 @@ class FastSyncItSpec extends AsyncFlatSpec with Matchers with BeforeAndAfter {
51
56
_ <- peer1.startFastSync()
52
57
_ <- peer1.waitForFastSyncFinish()
53
58
} yield {
54
- assert(peer1.bl.getBestBlockNumber() == peer2.bl.getBestBlockNumber() - peer2.syncConfig .targetBlockOffset)
55
- assert(peer1.bl.getBestBlockNumber() == peer3.bl.getBestBlockNumber() - peer3.syncConfig .targetBlockOffset)
59
+ assert(peer1.bl.getBestBlockNumber() == peer2.bl.getBestBlockNumber() - peer2.testSyncConfig .targetBlockOffset)
60
+ assert(peer1.bl.getBestBlockNumber() == peer3.bl.getBestBlockNumber() - peer3.testSyncConfig .targetBlockOffset)
56
61
}
57
62
}
58
63
@@ -66,11 +71,25 @@ class FastSyncItSpec extends AsyncFlatSpec with Matchers with BeforeAndAfter {
66
71
_ <- peer1.waitForFastSyncFinish()
67
72
} yield {
68
73
val trie = peer1.getBestBlockTrie()
69
- assert(peer1.bl.getBestBlockNumber() == peer2.bl.getBestBlockNumber() - peer2.syncConfig .targetBlockOffset)
70
- assert(peer1.bl.getBestBlockNumber() == peer3.bl.getBestBlockNumber() - peer3.syncConfig .targetBlockOffset)
74
+ assert(peer1.bl.getBestBlockNumber() == peer2.bl.getBestBlockNumber() - peer2.testSyncConfig .targetBlockOffset)
75
+ assert(peer1.bl.getBestBlockNumber() == peer3.bl.getBestBlockNumber() - peer3.testSyncConfig .targetBlockOffset)
71
76
assert(trie.isDefined)
72
77
}
73
78
}
79
+
80
+
81
+ it should " should update target block" in customTestCaseResourceM(FakePeer .start2FakePeersRes()) {
82
+ case (peer1, peer2) =>
83
+ for {
84
+ _ <- peer2.importNBlocksToTheTopForm(peer2.getCurrentState(), 1000 )(IdentityUpdate )
85
+ _ <- peer1.connectToPeers(Set (peer2.node))
86
+ _ <- peer2.syncUntil(2000 )(IdentityUpdate ).startAndForget
87
+ _ <- peer1.startFastSync()
88
+ _ <- peer1.waitForFastSyncFinish()
89
+ } yield {
90
+ assert(peer1.bl.getBestBlockNumber() == peer2.bl.getBestBlockNumber() - peer2.testSyncConfig.targetBlockOffset)
91
+ }
92
+ }
74
93
}
75
94
76
95
object FastSyncItSpec {
@@ -108,7 +127,7 @@ object FastSyncItSpec {
108
127
109
128
val IdentityUpdate : (BigInt , InMemoryWorldStateProxy ) => InMemoryWorldStateProxy = (_, world) => world
110
129
111
- def updateWorldWithNRandomAcounts (n: Int , world : InMemoryWorldStateProxy ): InMemoryWorldStateProxy = {
130
+ def updateWorldWithNRandomAccounts (n: Int , world : InMemoryWorldStateProxy ): InMemoryWorldStateProxy = {
112
131
val resultWorld = (0 until n).foldLeft(world) { (world, num) =>
113
132
val randomBalance = num
114
133
val randomAddress = Address (num)
@@ -125,7 +144,7 @@ object FastSyncItSpec {
125
144
126
145
def updateStateAtBlock (blockWithUpdate : BigInt ): (BigInt , InMemoryWorldStateProxy ) => InMemoryWorldStateProxy = { (blockNr : BigInt , world : InMemoryWorldStateProxy ) =>
127
146
if (blockNr == blockWithUpdate) {
128
- updateWorldWithNRandomAcounts (1000 , world)
147
+ updateWorldWithNRandomAccounts (1000 , world)
129
148
} else {
130
149
IdentityUpdate (blockNr, world)
131
150
}
@@ -151,12 +170,30 @@ object FastSyncItSpec {
151
170
discoveryStatus = ServerStatus .NotListening
152
171
)
153
172
173
+ lazy val tempDir = Files .createTempDirectory(" temp-fast-sync" )
174
+
175
+ def getRockDbTestConfig (dbPath : String ) = {
176
+ new RocksDbConfig {
177
+ override val createIfMissing : Boolean = true
178
+ override val paranoidChecks : Boolean = false
179
+ override val path : String = dbPath
180
+ override val maxThreads : Int = 1
181
+ override val maxOpenFiles : Int = 32
182
+ override val verifyChecksums : Boolean = false
183
+ override val levelCompaction : Boolean = true
184
+ override val blockSize : Long = 16384
185
+ override val blockCacheSize : Long = 33554432
186
+ }
187
+ }
188
+
154
189
sealed trait LocalPruningConfigBuilder extends PruningConfigBuilder {
155
190
override lazy val pruningMode : PruningMode = ArchivePruning
156
191
}
157
192
158
193
lazy val nodeStatusHolder = new AtomicReference (nodeStatus)
159
- lazy val storagesInstance = new SharedEphemDataSources with LocalPruningConfigBuilder with Storages .DefaultStorages
194
+ lazy val storagesInstance = new SharedRocksDbDataSources with LocalPruningConfigBuilder with Storages .DefaultStorages {
195
+ override lazy val dataSource : RocksDbDataSource = RocksDbDataSource (getRockDbTestConfig(tempDir.toAbsolutePath.toString), Namespaces .nsSeq)
196
+ }
160
197
lazy val blockchainConfig = Config .blockchains.blockchainConfig
161
198
/**
162
199
* Default persist interval is 20s, which is too long for tests. As in all tests we treat peer as connected when
@@ -252,15 +289,21 @@ object FastSyncItSpec {
252
289
253
290
val testSyncConfig = syncConfig.copy(
254
291
minPeersToChooseTargetBlock = 1 ,
255
- peersScanInterval = 1 .second ,
292
+ peersScanInterval = 5 .milliseconds ,
256
293
blockHeadersPerRequest = 200 ,
257
294
blockBodiesPerRequest = 50 ,
258
295
receiptsPerRequest = 50 ,
259
296
fastSyncThrottle = 10 .milliseconds,
260
297
startRetryInterval = 50 .milliseconds,
261
- nodesPerRequest = 200
298
+ nodesPerRequest = 200 ,
299
+ maxTargetDifference = 1 ,
300
+ syncRetryInterval = 50 .milliseconds
262
301
)
263
302
303
+ lazy val broadcaster = new BlockBroadcast (etcPeerManager, testSyncConfig)
304
+
305
+ lazy val broadcasterActor = system.actorOf(BlockBroadcasterActor .props(broadcaster, peerEventBus, etcPeerManager, testSyncConfig, system.scheduler))
306
+
264
307
lazy val fastSync = system.actorOf(FastSync .props(
265
308
storagesInstance.storages.fastSyncStateStorage,
266
309
storagesInstance.storages.appStateStorage,
@@ -282,6 +325,10 @@ object FastSyncItSpec {
282
325
)
283
326
}
284
327
328
+ private def broadcastBlock (block : Block , td : BigInt ) = {
329
+ broadcasterActor ! BroadcastBlock (NewBlock (block, td))
330
+ }
331
+
285
332
def getCurrentState (): BlockchainState = {
286
333
val bestBlock = bl.getBestBlock()
287
334
val currentWorldState = getMptForBlock(bestBlock)
@@ -302,7 +349,10 @@ object FastSyncItSpec {
302
349
}
303
350
304
351
def shutdown (): Task [Unit ] = {
305
- Task .deferFuture(system.terminate()).map(_ => ())
352
+ for {
353
+ _ <- Task .deferFuture(system.terminate())
354
+ _ <- Task (storagesInstance.dataSource.destroy())
355
+ } yield ()
306
356
}
307
357
308
358
def connectToPeers (nodes : Set [DiscoveryNodeInfo ]): Task [Unit ] = {
@@ -343,12 +393,29 @@ object FastSyncItSpec {
343
393
go(startState.bestBlock, startState.currentTd, startState.currentWorldState, n)
344
394
}
345
395
396
+ def syncUntil (n : BigInt )(updateWorldForBlock : (BigInt , InMemoryWorldStateProxy ) => InMemoryWorldStateProxy ): Task [Unit ] = {
397
+ Task (bl.getBestBlock()).flatMap { block =>
398
+ if (block.number >= n) {
399
+ Task (())
400
+ } else {
401
+ Task {
402
+ val currentTd = bl.getTotalDifficultyByHash(block.hash).get
403
+ val currentWolrd = getMptForBlock(block)
404
+ val (newBlock, newTd, newWorld) = createChildBlock(block, currentTd, currentWolrd)(updateWorldForBlock)
405
+ bl.save(newBlock, Seq (), newTd, saveAsBestBlock = true )
406
+ bl.persistCachedNodes()
407
+ broadcastBlock(newBlock, newTd)
408
+ }.flatMap(_ => syncUntil(n)(updateWorldForBlock))
409
+ }
410
+ }
411
+ }
412
+
346
413
def startFastSync (): Task [Unit ] = Task {
347
414
fastSync ! FastSync .Start
348
415
}
349
416
350
417
def waitForFastSyncFinish (): Task [Boolean ] = {
351
- retryUntilWithDelay(Task (storagesInstance.storages.appStateStorage.isFastSyncDone()), 1 .second, 30 ){ isDone =>
418
+ retryUntilWithDelay(Task (storagesInstance.storages.appStateStorage.isFastSyncDone()), 1 .second, 90 ){ isDone =>
352
419
isDone
353
420
}
354
421
}
@@ -357,7 +424,7 @@ object FastSyncItSpec {
357
424
def getBestBlockTrie (): Option [MptNode ] = {
358
425
Try {
359
426
val bestBlock = bl.getBestBlock()
360
- val bestStateRoot = bestBlock.header.stateRoot
427
+ val bestStateRoot = bestBlock.header.stateRoot
361
428
MptTraversals .parseTrieIntoMemory(HashNode (bestStateRoot.toArray), storagesInstance.storages.stateStorage.getBackingStorage(bestBlock.number))
362
429
}.toOption
363
430
}
@@ -391,4 +458,4 @@ object FastSyncItSpec {
391
458
} { case (peer, peer1, peer2) => Task .parMap3(peer.shutdown(), peer1.shutdown(), peer2.shutdown())((_ ,_, _)=> ())}
392
459
}
393
460
}
394
- }
461
+ }
0 commit comments