@@ -72,7 +72,7 @@ class FastSync(
72
72
def startWithState (syncState : SyncState ): Unit = {
73
73
log.info(s " Starting with existing state and asking for new pivot block " )
74
74
val syncingHandler = new SyncingHandler (syncState)
75
- syncingHandler.askForPivotBlockUpdate(NodeRestart )
75
+ syncingHandler.askForPivotBlockUpdate(SyncRestart )
76
76
}
77
77
78
78
def startFromScratch (): Unit = {
@@ -205,39 +205,48 @@ class FastSync(
205
205
scheduler.scheduleOnce(syncConfig.pivotBlockReScheduleInterval, self, UpdatePivotBlock (updateReason))
206
206
}
207
207
208
+ private def stalePivotAfterRestart (
209
+ newPivot : BlockHeader ,
210
+ currentState : SyncState ,
211
+ updateReason : PivotBlockUpdateReason
212
+ ): Boolean = {
213
+ newPivot.number == currentState.pivotBlock.number && updateReason.isSyncRestart
214
+ }
215
+
216
+ private def newPivotIsGoodEnough (
217
+ newPivot : BlockHeader ,
218
+ currentState : SyncState ,
219
+ updateReason : PivotBlockUpdateReason
220
+ ): Boolean = {
221
+ newPivot.number >= currentState.pivotBlock.number && ! stalePivotAfterRestart(newPivot, currentState, updateReason)
222
+ }
223
+
208
224
def waitingForPivotBlockUpdate (updateReason : PivotBlockUpdateReason ): Receive = handleCommonMessages orElse {
209
- case PivotBlockSelector .Result (pivotBlockHeader) =>
225
+ case PivotBlockSelector .Result (pivotBlockHeader)
226
+ if newPivotIsGoodEnough(pivotBlockHeader, syncState, updateReason) =>
210
227
log.info(s " New pivot block with number ${pivotBlockHeader.number} received " )
211
- if (pivotBlockHeader.number >= syncState.pivotBlock.number) {
212
- if (pivotBlockHeader.number == syncState.pivotBlock.number && updateReason.nodeRestart) {
213
- // it can happen after quick node restart than pivot block has not changed in the network. To keep whole
214
- // fast sync machinery running as expected we need to make sure that we will receive better pivot than current
215
- log.info(" Received stale pivot after restart, asking for new pivot" )
216
- reScheduleAskForNewPivot(updateReason)
217
- } else {
218
- updatePivotSyncState(updateReason, pivotBlockHeader)
219
- syncState = syncState.copy(updatingPivotBlock = false )
220
- context become this .receive
221
- processSyncing()
222
- }
223
- } else {
224
- log.info(" Received target block is older than old one, re-scheduling asking for new one" )
225
- reScheduleAskForNewPivot(updateReason)
226
- }
228
+ updatePivotSyncState(updateReason, pivotBlockHeader)
229
+ context become this .receive
230
+ processSyncing()
231
+
232
+ case PivotBlockSelector .Result (pivotBlockHeader)
233
+ if ! newPivotIsGoodEnough(pivotBlockHeader, syncState, updateReason) =>
234
+ log.info(" Received pivot block is older than old one, re-scheduling asking for new one" )
235
+ reScheduleAskForNewPivot(updateReason)
227
236
228
237
case PersistSyncState => persistSyncState()
229
238
230
239
case UpdatePivotBlock (state) => updatePivotBlock(state)
231
240
}
232
241
233
- private def updatePivotBlock (state : PivotBlockUpdateReason ): Unit = {
242
+ private def updatePivotBlock (updateReason : PivotBlockUpdateReason ): Unit = {
234
243
if (syncState.pivotBlockUpdateFailures <= syncConfig.maximumTargetUpdateFailures) {
235
244
if (assignedHandlers.nonEmpty || syncState.blockChainWorkQueued) {
236
245
log.info(s " Still waiting for some responses, rescheduling pivot block update " )
237
- scheduler.scheduleOnce(1 .second, self, UpdatePivotBlock (state ))
246
+ scheduler.scheduleOnce(1 .second, self, UpdatePivotBlock (updateReason ))
238
247
processSyncing()
239
248
} else {
240
- askForPivotBlockUpdate(state )
249
+ askForPivotBlockUpdate(updateReason )
241
250
}
242
251
} else {
243
252
log.warning(s " Sync failure! Number of pivot block update failures reached maximum. " )
@@ -253,8 +262,9 @@ class FastSync(
253
262
// Empty root has means that there were no transactions in blockchain, and Mpt trie is empty
254
263
// Asking for this root would result only with empty transactions
255
264
if (syncState.pivotBlock.stateRoot == ByteString (MerklePatriciaTrie .EmptyRootHash )) {
256
- syncState = syncState.copy(stateSyncFinished = true )
265
+ syncState = syncState.copy(stateSyncFinished = true , updatingPivotBlock = false )
257
266
} else {
267
+ syncState = syncState.copy(updatingPivotBlock = false )
258
268
stateSyncRestartRequested = false
259
269
syncStateScheduler ! StartSyncingTo (pivotBlockHeader.stateRoot, pivotBlockHeader.number)
260
270
}
@@ -276,7 +286,7 @@ class FastSync(
276
286
syncState =
277
287
syncState.updatePivotBlock(pivotBlockHeader, syncConfig.fastSyncBlockValidationX, updateFailures = true )
278
288
279
- case NodeRestart =>
289
+ case SyncRestart =>
280
290
// in case of node restart we are sure that new pivotBlockHeader > current pivotBlockHeader
281
291
syncState = syncState.updatePivotBlock(
282
292
pivotBlockHeader,
@@ -541,7 +551,7 @@ class FastSync(
541
551
(info.maxBlockNumber - syncConfig.pivotBlockOffset) - state.pivotBlock.number >= syncConfig.maxPivotBlockAge
542
552
}
543
553
544
- private def getPeerWithTooFreshNewBlock (
554
+ private def getPeersWithFreshEnoughPivot (
545
555
peers : NonEmptyList [(Peer , PeerInfo )],
546
556
state : SyncState ,
547
557
syncConfig : SyncConfig
@@ -569,7 +579,7 @@ class FastSync(
569
579
(peerWithBestBlockInNetwork._2.maxBlockNumber - syncConfig.pivotBlockOffset) - syncState.pivotBlock.number
570
580
571
581
val peersWithTooFreshPossiblePivotBlock =
572
- getPeerWithTooFreshNewBlock (NonEmptyList .fromListUnsafe(currentPeers), syncState, syncConfig)
582
+ getPeersWithFreshEnoughPivot (NonEmptyList .fromListUnsafe(currentPeers), syncState, syncConfig)
573
583
574
584
if (peersWithTooFreshPossiblePivotBlock.isEmpty) {
575
585
log.info(
@@ -830,7 +840,8 @@ object FastSync {
830
840
copy(
831
841
pivotBlock = newPivot,
832
842
safeDownloadTarget = newPivot.number + numberOfSafeBlocks,
833
- pivotBlockUpdateFailures = if (updateFailures) pivotBlockUpdateFailures + 1 else pivotBlockUpdateFailures
843
+ pivotBlockUpdateFailures = if (updateFailures) pivotBlockUpdateFailures + 1 else pivotBlockUpdateFailures,
844
+ updatingPivotBlock = false
834
845
)
835
846
836
847
def isBlockchainWorkFinished : Boolean = {
@@ -861,14 +872,14 @@ object FastSync {
861
872
case object ImportedPivotBlock extends HeaderProcessingResult
862
873
863
874
sealed abstract class PivotBlockUpdateReason {
864
- def nodeRestart : Boolean = this match {
875
+ def isSyncRestart : Boolean = this match {
865
876
case ImportedLastBlock => false
866
877
case LastBlockValidationFailed => false
867
- case NodeRestart => true
878
+ case SyncRestart => true
868
879
}
869
880
}
870
881
871
882
case object ImportedLastBlock extends PivotBlockUpdateReason
872
883
case object LastBlockValidationFailed extends PivotBlockUpdateReason
873
- case object NodeRestart extends PivotBlockUpdateReason
884
+ case object SyncRestart extends PivotBlockUpdateReason
874
885
}
0 commit comments