@@ -109,13 +109,15 @@ class PivotBlockSelector(
109
109
timeout : Cancellable ,
110
110
headers : Map [ByteString , BlockHeaderWithVotes ]
111
111
): Unit = {
112
- val BlockHeaderWithVotes (mostPopularBlockHeader, updatedVotes) = headers.mostVotedHeader
112
+ // most voted header can return empty if we asked one peer and it returned us non expected block. Then headers map is empty
113
+ // so there is no most voted header
114
+ val maybeBlockHeaderWithVotes = headers.mostVotedHeader
113
115
// All peers responded - consensus reached
114
- if (peersToAsk.isEmpty && updatedVotes > = minPeersToChoosePivotBlock) {
116
+ if (peersToAsk.isEmpty && maybeBlockHeaderWithVotes.exists(hWv => hWv.votes > = minPeersToChoosePivotBlock) ) {
115
117
timeout.cancel()
116
- sendResponseAndCleanup(mostPopularBlockHeader )
118
+ sendResponseAndCleanup(maybeBlockHeaderWithVotes.get.header )
117
119
// Consensus could not be reached - ask additional peer if available
118
- } else if (! isPossibleToReachConsensus(peersToAsk.size, updatedVotes )) {
120
+ } else if (! isPossibleToReachConsensus(peersToAsk.size, maybeBlockHeaderWithVotes.map(_.votes).getOrElse( 0 ) )) {
119
121
timeout.cancel()
120
122
if (waitingPeers.nonEmpty) { // There are more peers to ask
121
123
val newTimeout = scheduler.scheduleOnce(peerResponseTimeout, self, ElectionPivotBlockTimeout )
@@ -208,9 +210,15 @@ object PivotBlockSelector {
208
210
}
209
211
210
212
implicit class SortableHeadersMap (headers : Map [ByteString , BlockHeaderWithVotes ]) {
211
- def mostVotedHeader : BlockHeaderWithVotes = headers.maxBy { case (_, headerWithVotes) =>
212
- headerWithVotes.votes
213
- }._2
213
+ def mostVotedHeader : Option [BlockHeaderWithVotes ] = {
214
+ if (headers.isEmpty) {
215
+ None
216
+ } else {
217
+ Some (headers.maxBy { case (_, headerWithVotes) =>
218
+ headerWithVotes.votes
219
+ }._2)
220
+ }
221
+ }
214
222
}
215
223
216
224
case class ElectionDetails (participants : List [Peer ], expectedPivotBlock : BigInt ) {
0 commit comments