@@ -4,11 +4,7 @@ import java.net.InetSocketAddress
4
4
import akka .actor .ActorSystem
5
5
import akka .testkit .{TestKit , TestProbe }
6
6
import com .miguno .akka .testing .VirtualTime
7
- import io .iohk .ethereum .Mocks .{
8
- MockValidatorsAlwaysSucceed ,
9
- MockValidatorsFailingOnBlockBodies ,
10
- MockValidatorsFailOnSpecificBlockNumber
11
- }
7
+ import io .iohk .ethereum .Mocks .{MockValidatorsAlwaysSucceed , MockValidatorsFailingOnBlockBodies }
12
8
import io .iohk .ethereum .BlockHelpers
13
9
import io .iohk .ethereum .Fixtures .{Blocks => FixtureBlocks }
14
10
import io .iohk .ethereum .blockchain .sync .PeersClient .BlacklistPeer
@@ -129,7 +125,7 @@ class BlockFetcherSpec extends TestKit(ActorSystem("BlockFetcherSpec_System")) w
129
125
peersClient.expectMsgPF() { case PeersClient .Request (msg, _, _) if msg == firstGetBlockHeadersRequest => () }
130
126
}
131
127
132
- " should not append new blocks if the received data does not match" in new TestSetup {
128
+ " should not enqueue requested blocks if the received bodies does not match" in new TestSetup {
133
129
134
130
// Important: Here we are forcing the mismatch between request headers and received bodies
135
131
override lazy val validators = new MockValidatorsFailingOnBlockBodies
@@ -151,6 +147,7 @@ class BlockFetcherSpec extends TestKit(ActorSystem("BlockFetcherSpec_System")) w
151
147
val getBlockBodiesResponse = BlockBodies (chain.map(_.body))
152
148
peersClient.reply(PeersClient .Response (fakePeer, getBlockBodiesResponse))
153
149
150
+ // Fetcher should blacklist the peer and retry asking for the same bodies
154
151
peersClient.expectMsgClass(classOf [BlacklistPeer ])
155
152
peersClient.expectMsgPF() { case PeersClient .Request (msg, _, _) if msg == getBlockBodiesRequest => () }
156
153
}
@@ -172,13 +169,13 @@ class BlockFetcherSpec extends TestKit(ActorSystem("BlockFetcherSpec_System")) w
172
169
peersClient.expectMsgPF() { case PeersClient .Request (msg, _, _) if msg == getBlockBodiesRequest1 => () }
173
170
174
171
// It will receive all the requested bodies, but splitted in 2 parts.
175
- val (subChain1, subChain2) = chain.splitAt(syncConfig.blockHeadersPerRequest / 2 )
172
+ val (subChain1, subChain2) = chain.splitAt(syncConfig.blockBodiesPerRequest / 2 )
176
173
177
174
val getBlockBodiesResponse1 = BlockBodies (subChain1.map(_.body))
178
175
peersClient.reply(PeersClient .Response (fakePeer, getBlockBodiesResponse1))
179
176
180
177
val getBlockHeadersRequest2 =
181
- GetBlockHeaders (Left (subChain1 .last.number + 1 ), syncConfig.blockHeadersPerRequest, skip = 0 , reverse = false )
178
+ GetBlockHeaders (Left (chain .last.number + 1 ), syncConfig.blockHeadersPerRequest, skip = 0 , reverse = false )
182
179
peersClient.expectMsgPF() { case PeersClient .Request (msg, _, _) if msg == getBlockHeadersRequest2 => () }
183
180
184
181
val getBlockBodiesRequest2 = GetBlockBodies (subChain2.map(_.hash))
@@ -188,13 +185,15 @@ class BlockFetcherSpec extends TestKit(ActorSystem("BlockFetcherSpec_System")) w
188
185
peersClient.reply(PeersClient .Response (fakePeer, getBlockBodiesResponse2))
189
186
190
187
peersClient.expectNoMessage()
191
- }
192
188
193
- " should ignore response, without blacklist the peer, in case a sub ordered block bodies chain is received" in new TestSetup {
189
+ importer.send(blockFetcher, PickBlocks (chain.size))
190
+ importer.ignoreMsg({ case BlockImporter .NotOnTop => true })
191
+ importer.expectMsgPF() { case BlockFetcher .PickedBlocks (blocks) =>
192
+ blocks.map(_.hash).toList shouldEqual chain.map(_.hash)
193
+ }
194
+ }
194
195
195
- // Important: Here (in a hacky way) we are enforcing received bodies
196
- // to be a sub ordered chain that fetcher can't append given their current state
197
- override lazy val validators = new MockValidatorsFailOnSpecificBlockNumber (1 )
196
+ " should stop requesting, without blacklist the peer, in case empty bodies are received" in new TestSetup {
198
197
199
198
startFetcher()
200
199
@@ -210,12 +209,31 @@ class BlockFetcherSpec extends TestKit(ActorSystem("BlockFetcherSpec_System")) w
210
209
val getBlockBodiesRequest1 = GetBlockBodies (chain.map(_.hash))
211
210
peersClient.expectMsgPF() { case PeersClient .Request (msg, _, _) if msg == getBlockBodiesRequest1 => () }
212
211
213
- val (subChain1, _) = chain.splitAt(syncConfig.blockHeadersPerRequest / 2 )
212
+ // It will receive part of the requested bodies.
213
+ val (subChain1, subChain2) = chain.splitAt(syncConfig.blockBodiesPerRequest / 2 )
214
214
215
215
val getBlockBodiesResponse1 = BlockBodies (subChain1.map(_.body))
216
216
peersClient.reply(PeersClient .Response (fakePeer, getBlockBodiesResponse1))
217
217
218
- peersClient.expectMsgPF() { case PeersClient .Request (msg, _, _) if msg == getBlockBodiesRequest1 => () }
218
+ val getBlockHeadersRequest2 =
219
+ GetBlockHeaders (Left (chain.last.number + 1 ), syncConfig.blockHeadersPerRequest, skip = 0 , reverse = false )
220
+ peersClient.expectMsgPF() { case PeersClient .Request (msg, _, _) if msg == getBlockHeadersRequest2 => () }
221
+
222
+ val getBlockBodiesRequest2 = GetBlockBodies (subChain2.map(_.hash))
223
+ peersClient.expectMsgPF() { case PeersClient .Request (msg, _, _) if msg == getBlockBodiesRequest2 => () }
224
+
225
+ // We receive empty bodies instead of the second part
226
+ val getBlockBodiesResponse2 = BlockBodies (List ())
227
+ peersClient.reply(PeersClient .Response (fakePeer, getBlockBodiesResponse2))
228
+
229
+ peersClient.expectNoMessage()
230
+
231
+ // If we try to pick the whole chain we should only receive the first part
232
+ importer.send(blockFetcher, PickBlocks (chain.size))
233
+ importer.ignoreMsg({ case BlockImporter .NotOnTop => true })
234
+ importer.expectMsgPF() { case BlockFetcher .PickedBlocks (blocks) =>
235
+ blocks.map(_.hash).toList shouldEqual subChain1.map(_.hash)
236
+ }
219
237
}
220
238
221
239
" should ensure blocks passed to importer are always forming chain" in new TestSetup {
0 commit comments