Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
4c7150e
create actor FastSyncBranchResolver
biandratti Jan 18, 2021
9533d94
ETCM-313 Download skeleton and then batch headers in parallel
enriquerodbe Jan 13, 2021
01dd4b2
Implement HeaderSkeleton class
enriquerodbe Jan 14, 2021
59039eb
Validate if skeleton header matches downloaded batch
enriquerodbe Jan 14, 2021
74d8c99
Improve validations
enriquerodbe Jan 14, 2021
e3c4b39
Handle wrong skeleton from master peer
enriquerodbe Jan 14, 2021
2a5f54f
Fix incorrect example
enriquerodbe Jan 14, 2021
195efd9
Validate PoW of skeleton headers
enriquerodbe Jan 15, 2021
640cc9b
Fix bugs found with tests
enriquerodbe Jan 15, 2021
150bfd6
Add call to the branch resolver
enriquerodbe Jan 19, 2021
56acc7e
Add missing config entries
robinraju Jan 20, 2021
8fd1a4b
Fix unit tests
robinraju Jan 25, 2021
c46ab2b
Apply scalafmt
robinraju Jan 25, 2021
fbbf4c9
Cleanup tests
robinraju Jan 25, 2021
a4110e9
Fastsync: stick with the same master peer while requesting skeleton h…
robinraju Jan 25, 2021
9ee535e
[ETCM-313] Integrate branch resolver actor with fast sync
robinraju Feb 1, 2021
42c3609
[ETCM-313] Fix integration tests, format error messages
robinraju Feb 1, 2021
e2ae8bf
create actor FastSyncBranchResolver
biandratti Jan 18, 2021
e59e0a0
create actor FastSyncBranchResolver
biandratti Jan 18, 2021
4d2bd58
Merge branch 'ETCM-311-fast_sync_improvements' of github.com:input-ou…
Mar 1, 2021
6d918a9
Merge ETCM-311 into branch
Mar 2, 2021
141ec18
[ETCM-316] Fast-sync branch resolver (#887)
biandratti Mar 4, 2021
7108438
Merge branch 'develop' into ETCM-313-skeleton
ten15bit Mar 4, 2021
e96572d
[ETCM-313] Reworked header skeleton (still needs refactoring)
Mar 10, 2021
d1dc7e5
[ETCM-313] Remove empty method
Mar 10, 2021
319832e
Merge develop into branch
Mar 10, 2021
cd43b26
Fix SyncController tests, add more logging
Mar 10, 2021
bc95500
Remove logging that broke integration tests (timeout)
Mar 10, 2021
fb91d63
[ETCM-313] More refactorings
Mar 10, 2021
6983153
[ETCM-313] Fix integration tests
Mar 10, 2021
6a2bd69
[ETCM-313] Re-request header skeleton in case of errors
Mar 11, 2021
92385c0
[ETCM-313] Remove skeleton handler name
Mar 11, 2021
49f6e0c
Merge develop into branch
Mar 11, 2021
ee41808
[ETCM-313] Small fixes and better logs
Mar 11, 2021
d613a3f
[ETCM-313] Update the default number of requested block headers to no…
Mar 12, 2021
84f2c47
[ETCM-313] Adapt branchresolver recent blocks request.
robinraju Mar 16, 2021
20855b4
Merge branch 'develop' into ETCM-313-skeleton
ten15bit Mar 16, 2021
1495388
Merge branch 'develop' into ETCM-313-skeleton
ten15bit Mar 16, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ class EthashTestBlockHeaderValidator(blockchainConfig: BlockchainConfig) extends

protected def difficulty: DifficultyCalculator = DifficultyCalculator(blockchainConfig)

def validateEvenMore(blockHeader: BlockHeader, parentHeader: BlockHeader): Either[BlockHeaderError, BlockHeaderValid] =
override def validateEvenMore(blockHeader: BlockHeader): Either[BlockHeaderError, BlockHeaderValid] =
Right(BlockHeaderValid)

}
24 changes: 14 additions & 10 deletions src/it/scala/io/iohk/ethereum/sync/FastSyncItSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -59,49 +59,53 @@ class FastSyncItSpec extends FlatSpecBase with Matchers with BeforeAndAfterAll {

it should "sync blockchain with state nodes when peer do not response with full responses" in
customTestCaseResourceM(
FakePeer.start3FakePeersRes(
FakePeer.start4FakePeersRes(
fakePeerCustomConfig2 = FakePeerCustomConfig(HostConfig()),
fakePeerCustomConfig3 = FakePeerCustomConfig(HostConfig())
)
) { case (peer1, peer2, peer3) =>
) { case (peer1, peer2, peer3, peer4) =>
for {
_ <- peer2.importBlocksUntil(1000)(updateStateAtBlock(500))
_ <- peer3.importBlocksUntil(1000)(updateStateAtBlock(500))
_ <- peer1.connectToPeers(Set(peer2.node, peer3.node))
_ <- peer4.importBlocksUntil(1000)(updateStateAtBlock(500))

_ <- peer1.connectToPeers(Set(peer2.node, peer3.node, peer4.node))
_ <- peer1.startFastSync().delayExecution(50.milliseconds)
_ <- peer1.waitForFastSyncFinish()
} yield {
val trie = peer1.getBestBlockTrie()
val synchronizingPeerHaveAllData = peer1.containsExpectedDataUpToAccountAtBlock(1000, 500)
// due to the fact that function generating state is deterministic both peer2 and peer3 ends up with exactly same
// due to the fact that function generating state is deterministic both peer3 and peer4 ends up with exactly same
// state, so peer1 can get whole trie from both of them.
assert(peer1.bl.getBestBlockNumber() == peer2.bl.getBestBlockNumber() - peer2.testSyncConfig.pivotBlockOffset)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just calling out the removal of this line, and the same at old line# 103 below, in case this was done in error.

Image of Steven Steven

assert(peer1.bl.getBestBlockNumber() == peer3.bl.getBestBlockNumber() - peer3.testSyncConfig.pivotBlockOffset)
assert(peer1.bl.getBestBlockNumber() == peer4.bl.getBestBlockNumber() - peer4.testSyncConfig.pivotBlockOffset)
assert(trie.isDefined)
assert(synchronizingPeerHaveAllData)
}
}

it should "sync blockchain with state nodes when one of the peers send empty state responses" in
customTestCaseResourceM(
FakePeer.start3FakePeersRes(
FakePeer.start4FakePeersRes(
fakePeerCustomConfig2 = FakePeerCustomConfig(HostConfig()),
fakePeerCustomConfig3 = FakePeerCustomConfig(HostConfig().copy(maxMptComponentsPerMessage = 0))
)
) { case (peer1, peer2, peer3) =>
) { case (peer1, peer2, peer3, peer4) =>
for {
_ <- peer2.importBlocksUntil(1000)(updateStateAtBlock(500))
_ <- peer3.importBlocksUntil(1000)(updateStateAtBlock(500))
_ <- peer1.connectToPeers(Set(peer2.node, peer3.node))
_ <- peer4.importBlocksUntil(1000)(updateStateAtBlock(500))

_ <- peer1.connectToPeers(Set(peer2.node, peer3.node, peer4.node))
_ <- peer1.startFastSync().delayExecution(50.milliseconds)
_ <- peer1.waitForFastSyncFinish()
} yield {
val trie = peer1.getBestBlockTrie()
val synchronizingPeerHaveAllData = peer1.containsExpectedDataUpToAccountAtBlock(1000, 500)
// due to the fact that function generating state is deterministic both peer2 and peer3 ends up with exactly same
// due to the fact that function generating state is deterministic both peer3 and peer4 ends up with exactly same
// state, so peer1 can get whole trie from both of them.
assert(peer1.bl.getBestBlockNumber() == peer2.bl.getBestBlockNumber() - peer2.testSyncConfig.pivotBlockOffset)
assert(peer1.bl.getBestBlockNumber() == peer3.bl.getBestBlockNumber() - peer3.testSyncConfig.pivotBlockOffset)
assert(peer1.bl.getBestBlockNumber() == peer4.bl.getBestBlockNumber() - peer4.testSyncConfig.pivotBlockOffset)
assert(trie.isDefined)
assert(synchronizingPeerHaveAllData)
}
Expand Down
3 changes: 2 additions & 1 deletion src/it/scala/io/iohk/ethereum/sync/util/CommonFakePeer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,8 @@ abstract class CommonFakePeer(peerName: String, fakePeerCustomConfig: FakePeerCu
startRetryInterval = 50.milliseconds,
nodesPerRequest = 200,
maxTargetDifference = 1,
syncRetryInterval = 50.milliseconds
syncRetryInterval = 50.milliseconds,
blacklistDuration = 100.seconds
)

lazy val broadcaster = new BlockBroadcast(etcPeerManager)
Expand Down
8 changes: 7 additions & 1 deletion src/main/resources/application.conf
Original file line number Diff line number Diff line change
Expand Up @@ -369,7 +369,9 @@ mantis {
max-concurrent-requests = 50

# Requested number of block headers when syncing from other peers
block-headers-per-request = 200
# Will cause an error if it's higher than max-blocks-headers-per-message of the peer we're requesting from,
# so this number should not be set very high.
block-headers-per-request = 100

# Requested number of block bodies when syncing from other peers
block-bodies-per-request = 128
Expand Down Expand Up @@ -469,6 +471,10 @@ mantis {
# (peer.bestKnownBlock - pivot-block-offset) - node.curentPivotBlock > max-pivot-age
# it fast sync pivot block has become stale and it needs update
max-pivot-block-age = 96

# Maximum number of retries performed by fast sync when the master peer sends invalid block headers.
# On reaching this limit, it will perform branch resolving.
fast-sync-max-batch-retries = 5
}

pruning {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ object Blacklist {

case object WrongBlockHeaders extends BlacklistReason {
val reasonType: BlacklistReasonType = WrongBlockHeadersType
val description: String = "Wrong blockheaders response (empty or not chain forming)"
val description: String = "Wrong blockheaders response: Peer didn't respond with requested block headers."
}
case object BlockHeaderValidationFailed extends BlacklistReason {
val reasonType: BlacklistReasonType = BlockHeaderValidationFailedType
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ trait PeerListSupportNg { self: Actor with ActorLogging =>

private implicit val ec: ExecutionContext = context.dispatcher

protected val bigIntReverseOrdering: Ordering[BigInt] = Ordering[BigInt].reverse

def etcPeerManager: ActorRef
def peerEventBus: ActorRef
def blacklist: Blacklist
Expand Down Expand Up @@ -44,6 +46,9 @@ trait PeerListSupportNg { self: Actor with ActorLogging =>

def getPeerById(peerId: PeerId): Option[Peer] = handshakedPeers.get(peerId).map(_.peer)

def getPeerWithHighestBlock: Option[PeerWithInfo] =
peersToDownloadFrom.values.toList.sortBy(_.peerInfo.maxBlockNumber)(bigIntReverseOrdering).headOption

def blacklistIfHandshaked(peerId: PeerId, duration: FiniteDuration, reason: BlacklistReason): Unit =
handshakedPeers.get(peerId).foreach(_ => blacklist.add(peerId, duration, reason))

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,15 @@ class PeerRequestHandler[RequestMsg <: Message, ResponseMsg <: Message: ClassTag

import PeerRequestHandler._

val initiator: ActorRef = context.parent
private val initiator: ActorRef = context.parent

val timeout: Cancellable = scheduler.scheduleOnce(responseTimeout, self, Timeout)
private val timeout: Cancellable = scheduler.scheduleOnce(responseTimeout, self, Timeout)

val startTime: Long = System.currentTimeMillis()
private val startTime: Long = System.currentTimeMillis()

private def subscribeMessageClassifier = MessageClassifier(Set(responseMsgCode), PeerSelector.WithId(peer.id))

def timeTakenSoFar(): Long = System.currentTimeMillis() - startTime
private def timeTakenSoFar(): Long = System.currentTimeMillis() - startTime

override def preStart(): Unit = {
etcPeerManager ! EtcPeerManagerActor.SendMessage(toSerializable(requestMsg), peer.id)
Expand Down Expand Up @@ -79,8 +79,8 @@ object PeerRequestHandler {
)(implicit scheduler: Scheduler, toSerializable: RequestMsg => MessageSerializable): Props =
Props(new PeerRequestHandler(peer, responseTimeout, etcPeerManager, peerEventBus, requestMsg, responseMsgCode))

case class RequestFailed(peer: Peer, reason: String)
case class ResponseReceived[T](peer: Peer, response: T, timeTaken: Long)
final case class RequestFailed(peer: Peer, reason: String)
final case class ResponseReceived[T](peer: Peer, response: T, timeTaken: Long)

private case object Timeout
}
Loading