@@ -3,6 +3,7 @@ package io.iohk.ethereum.sync
3
3
import com .typesafe .config .ConfigValueFactory
4
4
import io .iohk .ethereum .FreeSpecBase
5
5
import io .iohk .ethereum .metrics .{Metrics , MetricsConfig }
6
+ import io .iohk .ethereum .network .PeerId
6
7
import io .iohk .ethereum .sync .util .RegularSyncItSpecUtils .FakePeer
7
8
import io .iohk .ethereum .sync .util .SyncCommonItSpec ._
8
9
import io .iohk .ethereum .utils .Config
@@ -76,6 +77,108 @@ class RegularSyncItSpec extends FreeSpecBase with Matchers with BeforeAndAfterAl
76
77
}
77
78
}
78
79
80
+ " peers should keep being synced on checkpoints" in customTestCaseResourceM(
81
+ FakePeer .start2FakePeersRes()
82
+ ) { case (peer1, peer2) =>
83
+ val blockNumber : Int = 2000
84
+ for {
85
+ _ <- peer1.importBlocksUntil(blockNumber)(IdentityUpdate )
86
+ _ <- peer1.startRegularSync()
87
+ _ <- peer2.startRegularSync()
88
+ _ <- peer2.connectToPeers(Set (peer1.node))
89
+ _ <- peer2.waitForRegularSyncLoadLastBlock(blockNumber)
90
+ _ <- peer2.addCheckpointedBlock(peer2.bl.getBestBlock().get)
91
+ _ <- peer1.waitForRegularSyncLoadLastBlock(blockNumber + 1 )
92
+ } yield {
93
+ assert(peer1.bl.getBestBlock().get.hash == peer2.bl.getBestBlock().get.hash)
94
+ assert(peer1.bl.getLatestCheckpointBlockNumber() == peer2.bl.getLatestCheckpointBlockNumber())
95
+ }
96
+ }
97
+
98
+ " peers should keep being synced on checkpoints even if 2 checkpoints are issued to different forks at the same time" in customTestCaseResourceM(
99
+ FakePeer .start2FakePeersRes()
100
+ ) { case (peer1, peer2) =>
101
+ val blockNumber : Int = 2000
102
+ for {
103
+ _ <- peer1.importBlocksUntil(blockNumber)(IdentityUpdate )
104
+ _ <- peer1.startRegularSync()
105
+ _ <- peer2.startRegularSync()
106
+ _ <- peer2.connectToPeers(Set (peer1.node))
107
+ _ <- peer2.waitForRegularSyncLoadLastBlock(blockNumber)
108
+ _ <- peer2.mineNewBlocks(100 .milliseconds, 2 )(IdentityUpdate )
109
+ _ <- peer2.waitForRegularSyncLoadLastBlock(blockNumber + 2 )
110
+ _ <- peer2.addCheckpointedBlock(peer2.bl.getBestBlock().get)
111
+ _ <- peer2.waitForRegularSyncLoadLastBlock(blockNumber + 3 )
112
+ _ <- peer1.addCheckpointedBlock(peer1.bl.getBestBlock().get)
113
+ _ <- peer2.waitForRegularSyncLoadLastBlock(blockNumber + 4 )
114
+ _ <- peer1.mineNewBlocks(100 .milliseconds, 1 )(IdentityUpdate )
115
+ _ <- peer2.waitForRegularSyncLoadLastBlock(blockNumber + 5 )
116
+ } yield {
117
+ assert(peer1.bl.getBestBlock().get.hash == peer2.bl.getBestBlock().get.hash)
118
+ assert(peer1.bl.getLatestCheckpointBlockNumber() == peer2.bl.getLatestCheckpointBlockNumber())
119
+ }
120
+ }
121
+
122
+ " peers should chose the branch with a checkpoint discarding blocks that come after the checkpoint" in customTestCaseResourceM(
123
+ FakePeer .start2FakePeersRes()
124
+ ) { case (peer1, peer2) =>
125
+ val lenght = 26
126
+ for {
127
+ _ <- peer1.importBlocksUntil(20 )(IdentityUpdate )
128
+ _ <- peer2.importBlocksUntil(30 )(IdentityUpdate )
129
+ _ <- peer1.startRegularSync()
130
+ _ <- peer2.startRegularSync()
131
+ _ <- peer2.addCheckpointedBlock(peer2.bl.getBlockByNumber(25 ).get)
132
+ _ <- peer2.waitForRegularSyncLoadLastBlock(lenght)
133
+ _ <- peer1.connectToPeers(Set (peer2.node))
134
+ _ <- peer1.waitForRegularSyncLoadLastBlock(lenght)
135
+ } yield {
136
+ assert(peer1.bl.getBestBlock().get.hash == peer2.bl.getBestBlock().get.hash)
137
+ assert(peer1.bl.getBestBlock().get.number == peer2.bl.getBestBlock().get.number && peer1.bl.getBestBlock().get.number == lenght)
138
+ assert(peer1.bl.getLatestCheckpointBlockNumber() == peer2.bl.getLatestCheckpointBlockNumber())
139
+ }
140
+ }
141
+
142
+ " peers should choose the branch with a checkpoint even if it's shorter" in customTestCaseResourceM(
143
+ FakePeer .start2FakePeersRes()
144
+ ) { case (peer1, peer2) =>
145
+ for {
146
+ _ <- peer1.importBlocksUntil(4 )(IdentityUpdate )
147
+ _ <- peer2.importBlocksUntil(8 )(IdentityUpdate )
148
+ _ <- peer1.startRegularSync()
149
+ _ <- peer2.startRegularSync()
150
+ _ <- peer1.addCheckpointedBlock(peer1.bl.getBestBlock().get)
151
+ _ = Thread .sleep(5000 )
152
+ _ <- peer1.waitForRegularSyncLoadLastBlock(5 )
153
+ _ <- peer1.connectToPeers(Set (peer2.node))
154
+ // TODO: remove the following line and the test should still work. Currently reorganisation is only triggered when the checkpoint is explicitly propagated,
155
+ // but it should also work when 2 new peers with conflicting branches connect
156
+ _ <- peer2.getCheckpointFromPeer(peer1.bl.getBestBlock().get, PeerId (" Peer1" ))
157
+ _ <- peer2.waitForRegularSyncLoadLastBlock(5 )
158
+ } yield {
159
+ assert(peer1.bl.getBestBlock().get.hash == peer2.bl.getBestBlock().get.hash)
160
+ assert(peer1.bl.getLatestCheckpointBlockNumber() == peer2.bl.getLatestCheckpointBlockNumber())
161
+ }
162
+ }
163
+
164
+ " a peer should reorganise when receives a checkpoint older than the current best from a peer" in customTestCaseResourceM(
165
+ FakePeer .start2FakePeersRes()
166
+ ) { case (peer1, peer2) =>
167
+ for {
168
+ _ <- peer1.importBlocksUntil(20 )(IdentityUpdate )
169
+ _ <- peer2.importBlocksUntil(30 )(IdentityUpdate )
170
+ _ <- peer1.startRegularSync()
171
+ _ <- peer2.startRegularSync()
172
+ _ <- peer1.addCheckpointedBlock(peer1.bl.getBestBlock().get)
173
+ _ <- peer1.waitForRegularSyncLoadLastBlock(21 )
174
+ _ <- peer2.getCheckpointFromPeer(peer1.bl.getBestBlock().get, PeerId (" Peer1" ))
175
+ _ <- peer2.waitForRegularSyncLoadLastBlock(21 )
176
+ } yield {
177
+ assert(peer1.bl.getBestBlock().get.hash == peer2.bl.getBestBlock().get.hash)
178
+ assert(peer1.bl.getLatestCheckpointBlockNumber() == peer2.bl.getLatestCheckpointBlockNumber())
179
+ }
180
+ }
181
+
79
182
" peers with divergent chains will be forced to resolve branches" in customTestCaseResourceM(
80
183
FakePeer .start2FakePeersRes()
81
184
) { case (peer1, peer2) =>
0 commit comments