@@ -5,7 +5,11 @@ import java.net.InetSocketAddress
55import akka .actor .ActorSystem
66import akka .testkit .{TestKit , TestProbe }
77import com .miguno .akka .testing .VirtualTime
8- import io .iohk .ethereum .Mocks .{MockValidatorsAlwaysSucceed , MockValidatorsFailingOnBlockBodies }
8+ import io .iohk .ethereum .Mocks .{
9+ MockValidatorsAlwaysSucceed ,
10+ MockValidatorsFailingOnBlockBodies ,
11+ MockValidatorsFailOnSpecificBlockNumber
12+ }
913import io .iohk .ethereum .BlockHelpers
1014import io .iohk .ethereum .Fixtures .{Blocks => FixtureBlocks }
1115import io .iohk .ethereum .blockchain .sync .PeersClient .BlacklistPeer
@@ -151,6 +155,69 @@ class BlockFetcherSpec extends TestKit(ActorSystem("BlockFetcherSpec_System")) w
151155 peersClient.expectMsgClass(classOf [BlacklistPeer ])
152156 peersClient.expectMsgPF() { case PeersClient .Request (msg, _, _) if msg == getBlockBodiesRequest => () }
153157 }
158+
159+ " should be able to handle block bodies received in several parts" in new TestSetup {
160+
161+ startFetcher()
162+
163+ val getBlockHeadersRequest =
164+ GetBlockHeaders (Left (1 ), syncConfig.blockHeadersPerRequest, skip = 0 , reverse = false )
165+ peersClient.expectMsgPF() { case PeersClient .Request (msg, _, _) if msg == getBlockHeadersRequest => () }
166+
167+ val chain = BlockHelpers .generateChain(syncConfig.blockHeadersPerRequest, FixtureBlocks .Genesis .block)
168+
169+ val getBlockHeadersResponse = BlockHeaders (chain.map(_.header))
170+ peersClient.reply(PeersClient .Response (fakePeer, getBlockHeadersResponse))
171+
172+ val getBlockBodiesRequest1 = GetBlockBodies (chain.map(_.hash))
173+ peersClient.expectMsgPF() { case PeersClient .Request (msg, _, _) if msg == getBlockBodiesRequest1 => () }
174+
175+ // It will receive all the requested bodies, but splitted in 2 parts.
176+ val (subChain1, subChain2) = chain.splitAt(syncConfig.blockHeadersPerRequest / 2 )
177+
178+ val getBlockBodiesResponse1 = BlockBodies (subChain1.map(_.body))
179+ peersClient.reply(PeersClient .Response (fakePeer, getBlockBodiesResponse1))
180+
181+ val getBlockHeadersRequest2 =
182+ GetBlockHeaders (Left (subChain1.last.number + 1 ), syncConfig.blockHeadersPerRequest, skip = 0 , reverse = false )
183+ peersClient.expectMsgPF() { case PeersClient .Request (msg, _, _) if msg == getBlockHeadersRequest2 => () }
184+
185+ val getBlockBodiesRequest2 = GetBlockBodies (subChain2.map(_.hash))
186+ peersClient.expectMsgPF() { case PeersClient .Request (msg, _, _) if msg == getBlockBodiesRequest2 => () }
187+
188+ val getBlockBodiesResponse2 = BlockBodies (subChain2.map(_.body))
189+ peersClient.reply(PeersClient .Response (fakePeer, getBlockBodiesResponse2))
190+
191+ peersClient.expectNoMessage()
192+ }
193+
194+ " should ignore response, without blacklist the peer, in case a sub ordered block bodies chain is received" in new TestSetup {
195+
196+ // Important: Here (in a hacky way) we are enforcing that received bodies
197+ // will be a sub ordered chain that fetcher can't append given their current state
198+ override lazy val validators = new MockValidatorsFailOnSpecificBlockNumber (1 )
199+
200+ startFetcher()
201+
202+ val getBlockHeadersRequest =
203+ GetBlockHeaders (Left (1 ), syncConfig.blockHeadersPerRequest, skip = 0 , reverse = false )
204+ peersClient.expectMsgPF() { case PeersClient .Request (msg, _, _) if msg == getBlockHeadersRequest => () }
205+
206+ val chain = BlockHelpers .generateChain(syncConfig.blockHeadersPerRequest, FixtureBlocks .Genesis .block)
207+
208+ val getBlockHeadersResponse = BlockHeaders (chain.map(_.header))
209+ peersClient.reply(PeersClient .Response (fakePeer, getBlockHeadersResponse))
210+
211+ val getBlockBodiesRequest1 = GetBlockBodies (chain.map(_.hash))
212+ peersClient.expectMsgPF() { case PeersClient .Request (msg, _, _) if msg == getBlockBodiesRequest1 => () }
213+
214+ val (subChain1, _) = chain.splitAt(syncConfig.blockHeadersPerRequest / 2 )
215+
216+ val getBlockBodiesResponse1 = BlockBodies (subChain1.map(_.body))
217+ peersClient.reply(PeersClient .Response (fakePeer, getBlockBodiesResponse1))
218+
219+ peersClient.expectMsgPF() { case PeersClient .Request (msg, _, _) if msg == getBlockBodiesRequest1 => () }
220+ }
154221 }
155222
156223 trait TestSetup extends TestSyncConfig {
0 commit comments