Skip to content

Commit

Permalink
Merge branch 'develop' into feature/ETCM-126-getProof
Browse files Browse the repository at this point in the history
  • Loading branch information
lemastero committed Oct 20, 2020
2 parents 9e27d4d + 30b2764 commit 18855f4
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 12 deletions.
13 changes: 9 additions & 4 deletions README.md
Expand Up @@ -2,13 +2,18 @@

Ethereum-like Blockchain Scala client built by IOHK's Team Grothendieck.

### Status
### Status - Release

Continuous Integration Build Status [FIXME]
For continuous integration we're using:
- [Buildkite](https://buildkite.com/input-output-hk/mantis) to run all the Scala build steps [![Build status](https://badge.buildkite.com/8a284e6f0af90afa544e06c8136b519f9f287f005ca581d8ed.svg?branch=master&theme=github)](https://buildkite.com/input-output-hk/mantis)
- [Hydra](https://hydra.project42.iohkdev.io/project/mantis) to test that the Nix build steps work and run each of the Ops test suites.

Unit Test Code Coverage Status [FIXME]
You can check the latest build results of the current branch by clicking the status icon in the header of the Github file browser.

Unit Test Code Coverage Status - TBD

### Docs - FIXME: Update docs!

// FIXME: Should we continue using this? or should we migrate to atlassian wiki?
For more details on configuration and functionality check out our [wiki](http://mantis.readthedocs.io) (also at [wiki](https://github.com/input-output-hk/mantis/wiki))

### Download the client
Expand Down
Expand Up @@ -109,13 +109,15 @@ class PivotBlockSelector(
timeout: Cancellable,
headers: Map[ByteString, BlockHeaderWithVotes]
): Unit = {
val BlockHeaderWithVotes(mostPopularBlockHeader, updatedVotes) = headers.mostVotedHeader
// most voted header can return empty if we asked one peer and it returned us non expected block. Then headers map is empty
// so there is no most voted header
val maybeBlockHeaderWithVotes = headers.mostVotedHeader
// All peers responded - consensus reached
if (peersToAsk.isEmpty && updatedVotes >= minPeersToChoosePivotBlock) {
if (peersToAsk.isEmpty && maybeBlockHeaderWithVotes.exists(hWv => hWv.votes >= minPeersToChoosePivotBlock)) {
timeout.cancel()
sendResponseAndCleanup(mostPopularBlockHeader)
sendResponseAndCleanup(maybeBlockHeaderWithVotes.get.header)
// Consensus could not be reached - ask additional peer if available
} else if (!isPossibleToReachConsensus(peersToAsk.size, updatedVotes)) {
} else if (!isPossibleToReachConsensus(peersToAsk.size, maybeBlockHeaderWithVotes.map(_.votes).getOrElse(0))) {
timeout.cancel()
if (waitingPeers.nonEmpty) { // There are more peers to ask
val newTimeout = scheduler.scheduleOnce(peerResponseTimeout, self, ElectionPivotBlockTimeout)
Expand Down Expand Up @@ -206,11 +208,11 @@ object PivotBlockSelector {
case class BlockHeaderWithVotes(header: BlockHeader, votes: Int = 1) {
def vote: BlockHeaderWithVotes = copy(votes = votes + 1)
}

import cats.implicits._
implicit class SortableHeadersMap(headers: Map[ByteString, BlockHeaderWithVotes]) {
def mostVotedHeader: BlockHeaderWithVotes = headers.maxBy { case (_, headerWithVotes) =>
headerWithVotes.votes
}._2
def mostVotedHeader: Option[BlockHeaderWithVotes] = {
headers.toList.maximumByOption { case (_, headerWithVotes) => headerWithVotes.votes }.map(_._2)
}
}

case class ElectionDetails(participants: List[Peer], expectedPivotBlock: BigInt) {
Expand Down
Expand Up @@ -188,6 +188,37 @@ class PivotBlockSelectorSpec
)
}

it should "handle case when one peer responded with wrong block header" in new TestSetup {
override def minPeersToChoosePivotBlock: Int = 1

updateHandshakedPeers(HandshakedPeers(singlePeer))

pivotBlockSelector ! SelectPivotBlock

peerMessageBus.expectMsgAllOf(
Subscribe(MessageClassifier(Set(BlockHeaders.code), PeerSelector.WithId(peer1.id)))
)

etcPeerManager.expectMsgAllOf(
EtcPeerManagerActor.SendMessage(GetBlockHeaders(Left(expectedPivotBlock), 1, 0, reverse = false), peer1.id)
)

// peer responds with block header number
pivotBlockSelector ! MessageFromPeer(
BlockHeaders(Seq(pivotBlockHeader.copy(number = expectedPivotBlock + 1))),
peer1.id
)

peerMessageBus.expectMsgAllOf(
Unsubscribe(MessageClassifier(Set(BlockHeaders.code), PeerSelector.WithId(peer1.id))),
Unsubscribe()
)
time.advance(syncConfig.syncRetryInterval)

fastSync.expectNoMessage() // consensus not reached - process have to be repeated
peerMessageBus.expectNoMessage()
}

it should "not ask additional peers if not needed" in new TestSetup {
override val minPeersToChoosePivotBlock = 2
override val peersToChoosePivotBlockMargin = 1
Expand Down

0 comments on commit 18855f4

Please sign in to comment.