Skip to content

Commit 8932dc1

Browse files
author
Michal Mrozek
committed
[ECTM-104] PR fixes
1 parent e192874 commit 8932dc1

File tree

3 files changed

+102
-86
lines changed

3 files changed

+102
-86
lines changed

src/main/scala/io/iohk/ethereum/blockchain/sync/FastSync.scala

Lines changed: 23 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -68,10 +68,10 @@ class FastSync(
6868
log.info(s"FastSync interrupted during pivot block update, choosing new pivot block")
6969
val syncingHandler = new SyncingHandler(syncState)
7070
val pivotBlockSelector = context.actorOf(
71-
FastSyncPivotBlockSelector.props(etcPeerManager, peerEventBus, syncConfig, scheduler),
71+
PivotBlockSelector.props(etcPeerManager, peerEventBus, syncConfig, scheduler, context.self),
7272
"pivot-block-selector"
7373
)
74-
pivotBlockSelector ! FastSyncPivotBlockSelector.ChoosePivotBlock
74+
pivotBlockSelector ! PivotBlockSelector.SelectPivotBlock
7575
context become syncingHandler.waitingForPivotBlockUpdate(ImportedLastBlock)
7676
} else {
7777
log.info(
@@ -86,28 +86,27 @@ class FastSync(
8686

8787
def startFromScratch(): Unit = {
8888
val pivotBlockSelector = context.actorOf(
89-
FastSyncPivotBlockSelector.props(etcPeerManager, peerEventBus, syncConfig, scheduler),
89+
PivotBlockSelector.props(etcPeerManager, peerEventBus, syncConfig, scheduler, context.self),
9090
"pivot-block-selector"
9191
)
92-
pivotBlockSelector ! FastSyncPivotBlockSelector.ChoosePivotBlock
92+
pivotBlockSelector ! PivotBlockSelector.SelectPivotBlock
9393
context become waitingForPivotBlock
9494
}
9595

96-
def waitingForPivotBlock: Receive = handleCommonMessages orElse {
97-
case FastSyncPivotBlockSelector.Result(pivotBlockHeader) =>
98-
if (pivotBlockHeader.number < 1) {
99-
log.info("Unable to start block synchronization in fast mode: pivot block is less than 1")
100-
appStateStorage.fastSyncDone().commit()
101-
context become idle
102-
syncController ! Done
103-
} else {
104-
val initialSyncState =
105-
SyncState(
106-
pivotBlockHeader,
107-
safeDownloadTarget = pivotBlockHeader.number + syncConfig.fastSyncBlockValidationX
108-
)
109-
startWithState(initialSyncState)
110-
}
96+
def waitingForPivotBlock: Receive = handleCommonMessages orElse { case PivotBlockSelector.Result(pivotBlockHeader) =>
97+
if (pivotBlockHeader.number < 1) {
98+
log.info("Unable to start block synchronization in fast mode: pivot block is less than 1")
99+
appStateStorage.fastSyncDone().commit()
100+
context become idle
101+
syncController ! Done
102+
} else {
103+
val initialSyncState =
104+
SyncState(
105+
pivotBlockHeader,
106+
safeDownloadTarget = pivotBlockHeader.number + syncConfig.fastSyncBlockValidationX
107+
)
108+
startWithState(initialSyncState)
109+
}
111110
}
112111

113112
// scalastyle:off number.of.methods
@@ -189,7 +188,7 @@ class FastSync(
189188
}
190189

191190
def waitingForPivotBlockUpdate(processState: FinalBlockProcessingResult): Receive = handleCommonMessages orElse {
192-
case FastSyncPivotBlockSelector.Result(pivotBlockHeader) =>
191+
case PivotBlockSelector.Result(pivotBlockHeader) =>
193192
log.info(s"New pivot block with number ${pivotBlockHeader.number} received")
194193
if (pivotBlockHeader.number >= syncState.pivotBlock.number) {
195194
updatePivotSyncState(processState, pivotBlockHeader)
@@ -215,8 +214,10 @@ class FastSync(
215214
} else {
216215
log.info("Asking for new pivot block")
217216
val pivotBlockSelector =
218-
context.actorOf(FastSyncPivotBlockSelector.props(etcPeerManager, peerEventBus, syncConfig, scheduler))
219-
pivotBlockSelector ! FastSyncPivotBlockSelector.ChoosePivotBlock
217+
context.actorOf(
218+
PivotBlockSelector.props(etcPeerManager, peerEventBus, syncConfig, scheduler, context.self)
219+
)
220+
pivotBlockSelector ! PivotBlockSelector.SelectPivotBlock
220221
context become waitingForPivotBlockUpdate(state)
221222
}
222223
} else {

src/main/scala/io/iohk/ethereum/blockchain/sync/FastSyncPivotBlockSelector.scala renamed to src/main/scala/io/iohk/ethereum/blockchain/sync/PivotBlockSelector.scala

Lines changed: 51 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -8,60 +8,48 @@ import io.iohk.ethereum.network.PeerEventBusActor.PeerEvent.MessageFromPeer
88
import io.iohk.ethereum.network.PeerEventBusActor.SubscriptionClassifier.MessageClassifier
99
import io.iohk.ethereum.network.PeerEventBusActor.{PeerSelector, Subscribe, Unsubscribe}
1010
import io.iohk.ethereum.network.p2p.messages.PV62.{BlockHeaders, GetBlockHeaders}
11-
import io.iohk.ethereum.network.{EtcPeerManagerActor, PeerId}
11+
import io.iohk.ethereum.network.{EtcPeerManagerActor, Peer, PeerId}
1212
import io.iohk.ethereum.utils.Config.SyncConfig
1313
import scala.concurrent.ExecutionContext.Implicits.global
1414
import scala.concurrent.duration.FiniteDuration
1515

16-
class FastSyncPivotBlockSelector(
16+
class PivotBlockSelector(
1717
val etcPeerManager: ActorRef,
1818
val peerEventBus: ActorRef,
1919
val syncConfig: SyncConfig,
20-
val scheduler: Scheduler
20+
val scheduler: Scheduler,
21+
fastSync: ActorRef
2122
) extends Actor
2223
with ActorLogging
2324
with PeerListSupport
2425
with BlacklistSupport {
2526

26-
import FastSyncPivotBlockSelector._
27+
import PivotBlockSelector._
2728
import syncConfig._
2829

29-
val fastSync: ActorRef = context.parent
30-
3130
def handleCommonMessages: Receive = handlePeerListMessages orElse handleBlacklistMessages
3231

3332
override def receive: Receive = idle
3433

35-
def idle: Receive = handleCommonMessages orElse { case ChoosePivotBlock =>
36-
val peersUsedToChooseTarget = peersToDownloadFrom.collect { case (peer, PeerInfo(_, _, true, maxBlockNumber, _)) =>
37-
(peer, maxBlockNumber)
38-
}
39-
40-
val peersSortedByBestNumber = peersUsedToChooseTarget.toList.sortBy { case (_, number) => -number }
41-
val bestPeerBestBlockNumber = peersSortedByBestNumber.headOption
42-
.map { case (_, bestPeerBestBlockNumber) => bestPeerBestBlockNumber }
43-
.getOrElse(BigInt(0))
44-
val expectedPivotBlock = (bestPeerBestBlockNumber - syncConfig.pivotBlockOffset).max(0)
45-
val correctPeers = peersSortedByBestNumber
46-
.takeWhile { case (_, number) => number >= expectedPivotBlock }
47-
.map { case (peer, _) => peer }
34+
def idle: Receive = handleCommonMessages orElse { case SelectPivotBlock =>
35+
val election @ ElectionDetails(correctPeers, expectedPivotBlock) = collectVoters
4836

49-
if (correctPeers.size >= minPeersToChoosePivotBlock) {
37+
if (election.isEnoughVoters(minPeersToChoosePivotBlock)) {
5038

5139
val (peersToAsk, waitingPeers) = correctPeers.splitAt(minPeersToChoosePivotBlock + peersToChoosePivotBlockMargin)
5240

5341
log.info(
5442
"Trying to choose fast sync pivot block using {} peers ({} correct ones). Ask {} peers for block nr {}",
55-
peersUsedToChooseTarget.size,
43+
peersToDownloadFrom.size,
5644
correctPeers.size,
5745
peersToAsk.size,
5846
expectedPivotBlock
5947
)
6048

6149
peersToAsk.foreach(peer => obtainBlockHeaderFromPeer(peer.id, expectedPivotBlock))
6250

63-
val timeout = scheduler.scheduleOnce(peerResponseTimeout, self, PivotBlockTimeout)
64-
context become waitingForPivotBlock(
51+
val timeout = scheduler.scheduleOnce(peerResponseTimeout, self, ElectionPivotBlockTimeout)
52+
context become runningPivotBlockElection(
6553
peersToAsk.map(_.id).toSet,
6654
waitingPeers.map(_.id),
6755
expectedPivotBlock,
@@ -73,14 +61,14 @@ class FastSyncPivotBlockSelector(
7361
"Cannot pick pivot block. Need at least {} peers, but there are only {} which meet the criteria ({} all available at the moment). Retrying in {}",
7462
minPeersToChoosePivotBlock,
7563
correctPeers.size,
76-
peersUsedToChooseTarget.size,
64+
peersToDownloadFrom.size,
7765
startRetryInterval
7866
)
7967
scheduleRetry(startRetryInterval)
8068
}
8169
}
8270

83-
def waitingForPivotBlock(
71+
def runningPivotBlockElection(
8472
peersToAsk: Set[PeerId],
8573
waitingPeers: List[PeerId],
8674
pivotBlockNumber: BigInt,
@@ -105,7 +93,7 @@ class FastSyncPivotBlockSelector(
10593
blacklist(peerId, blacklistDuration, "Did not respond with pivot block header, blacklisting")
10694
votingProcess(updatedPeersToAsk, waitingPeers, pivotBlockNumber, timeout, headers)
10795
}
108-
case PivotBlockTimeout =>
96+
case ElectionPivotBlockTimeout =>
10997
peersToAsk.foreach { peerId =>
11098
blacklist(peerId, blacklistDuration, "Did not respond with pivot block header (timeout), blacklisting")
11199
}
@@ -130,12 +118,12 @@ class FastSyncPivotBlockSelector(
130118
} else if (!isPossibleToReachConsensus(peersToAsk.size, updatedVotes)) {
131119
timeout.cancel()
132120
if (waitingPeers.nonEmpty) { // There are more peers to ask
133-
val newTimeout = scheduler.scheduleOnce(peerResponseTimeout, self, PivotBlockTimeout)
121+
val newTimeout = scheduler.scheduleOnce(peerResponseTimeout, self, ElectionPivotBlockTimeout)
134122
val additionalPeer :: newWaitingPeers = waitingPeers
135123

136124
obtainBlockHeaderFromPeer(additionalPeer, pivotBlockNumber)
137125

138-
context become waitingForPivotBlock(
126+
context become runningPivotBlockElection(
139127
peersToAsk + additionalPeer,
140128
newWaitingPeers,
141129
pivotBlockNumber,
@@ -149,7 +137,7 @@ class FastSyncPivotBlockSelector(
149137
}
150138
// Continue voting
151139
} else {
152-
context become waitingForPivotBlock(
140+
context become runningPivotBlockElection(
153141
peersToAsk,
154142
waitingPeers,
155143
pivotBlockNumber,
@@ -163,7 +151,7 @@ class FastSyncPivotBlockSelector(
163151
peersLeft + bestHeaderVotes >= minPeersToChoosePivotBlock
164152

165153
def scheduleRetry(interval: FiniteDuration): Unit = {
166-
scheduler.scheduleOnce(interval, self, ChoosePivotBlock)
154+
scheduler.scheduleOnce(interval, self, SelectPivotBlock)
167155
context become idle
168156
}
169157

@@ -181,16 +169,39 @@ class FastSyncPivotBlockSelector(
181169
peer
182170
)
183171
}
184-
}
185172

186-
object FastSyncPivotBlockSelector {
187-
def props(etcPeerManager: ActorRef, peerEventBus: ActorRef, syncConfig: SyncConfig, scheduler: Scheduler): Props =
188-
Props(new FastSyncPivotBlockSelector(etcPeerManager: ActorRef, peerEventBus, syncConfig, scheduler))
173+
private def collectVoters: ElectionDetails = {
174+
val peersUsedToChooseTarget = peersToDownloadFrom.collect { case (peer, PeerInfo(_, _, true, maxBlockNumber, _)) =>
175+
(peer, maxBlockNumber)
176+
}
189177

190-
case object ChoosePivotBlock
178+
val peersSortedByBestNumber = peersUsedToChooseTarget.toList.sortBy { case (_, number) => -number }
179+
val bestPeerBestBlockNumber = peersSortedByBestNumber.headOption
180+
.map { case (_, bestPeerBestBlockNumber) => bestPeerBestBlockNumber }
181+
.getOrElse(BigInt(0))
182+
val expectedPivotBlock = (bestPeerBestBlockNumber - syncConfig.pivotBlockOffset).max(0)
183+
val correctPeers = peersSortedByBestNumber
184+
.takeWhile { case (_, number) => number >= expectedPivotBlock }
185+
.map { case (peer, _) => peer }
186+
187+
ElectionDetails(correctPeers, expectedPivotBlock)
188+
}
189+
}
190+
191+
object PivotBlockSelector {
192+
def props(
193+
etcPeerManager: ActorRef,
194+
peerEventBus: ActorRef,
195+
syncConfig: SyncConfig,
196+
scheduler: Scheduler,
197+
fastSync: ActorRef
198+
): Props =
199+
Props(new PivotBlockSelector(etcPeerManager: ActorRef, peerEventBus, syncConfig, scheduler, fastSync))
200+
201+
case object SelectPivotBlock
191202
case class Result(targetBlockHeader: BlockHeader)
192203

193-
case object PivotBlockTimeout
204+
case object ElectionPivotBlockTimeout
194205

195206
case class BlockHeaderWithVotes(header: BlockHeader, votes: Int = 1) {
196207
def vote: BlockHeaderWithVotes = copy(votes = votes + 1)
@@ -201,4 +212,8 @@ object FastSyncPivotBlockSelector {
201212
headerWithVotes.votes
202213
}._2
203214
}
215+
216+
case class ElectionDetails(participants: List[Peer], expectedPivotBlock: BigInt) {
217+
def isEnoughVoters(minNumberOfVoters: Int): Boolean = participants.size >= minNumberOfVoters
218+
}
204219
}

0 commit comments

Comments
 (0)