@@ -3,25 +3,17 @@ package io.iohk.ethereum.ledger
3
3
import akka .actor .ActorRef
4
4
import akka .testkit .TestProbe
5
5
import akka .util .ByteString
6
-
7
6
import cats .data .NonEmptyList
8
-
9
7
import monix .execution .Scheduler
10
8
import monix .execution .schedulers .SchedulerService
11
9
12
10
import scala .concurrent .duration ._
13
-
14
11
import org .scalamock .scalatest .MockFactory
15
12
import org .scalatest .BeforeAndAfterAll
16
13
import org .scalatest .concurrent .Eventually
17
14
import org .scalatest .flatspec .AnyFlatSpecLike
18
15
import org .scalatest .matchers .should .Matchers
19
-
20
- import io .iohk .ethereum .Fixtures
21
- import io .iohk .ethereum .Mocks
22
- import io .iohk .ethereum .NormalPatience
23
- import io .iohk .ethereum .ObjectGenerators
24
- import io .iohk .ethereum .Timeouts
16
+ import io .iohk .ethereum .{Fixtures , Mocks , NormalPatience , ObjectGenerators , Timeouts , crypto }
25
17
import io .iohk .ethereum .blockchain .sync .regular .BlockFetcher
26
18
import io .iohk .ethereum .blockchain .sync .regular .BlockImporter
27
19
import io .iohk .ethereum .blockchain .sync .regular .BlockImporter .NewCheckpoint
@@ -32,15 +24,13 @@ import io.iohk.ethereum.consensus.blocks.CheckpointBlockGenerator
32
24
import io .iohk .ethereum .consensus .pow .validators .OmmersValidator
33
25
import io .iohk .ethereum .consensus .pow .validators .StdOmmersValidator
34
26
import io .iohk .ethereum .consensus .validators .Validators
35
- import io .iohk .ethereum .crypto
36
27
import io .iohk .ethereum .domain ._
37
28
import io .iohk .ethereum .mpt .MerklePatriciaTrie
38
29
import io .iohk .ethereum .utils .Config
39
30
import io .iohk .ethereum .utils .Config .SyncConfig
40
31
41
32
class BlockImporterItSpec
42
33
extends MockFactory
43
- with TestSetupWithVmAndValidators
44
34
with AnyFlatSpecLike
45
35
with Matchers
46
36
with BeforeAndAfterAll
@@ -54,114 +44,9 @@ class BlockImporterItSpec
54
44
testScheduler.awaitTermination(60 .second)
55
45
}
56
46
57
- override lazy val blockQueue : BlockQueue = BlockQueue (blockchain, blockchainReader, SyncConfig (Config .config))
58
-
59
- val genesis : Block = Block (
60
- Fixtures .Blocks .Genesis .header.copy(stateRoot = ByteString (MerklePatriciaTrie .EmptyRootHash )),
61
- Fixtures .Blocks .Genesis .body
62
- )
63
- val genesisWeight : ChainWeight = ChainWeight .zero.increase(genesis.header)
64
-
65
- blockchainWriter.save(genesis, Seq (), genesisWeight, saveAsBestBlock = true )
66
-
67
- lazy val checkpointBlockGenerator : CheckpointBlockGenerator = new CheckpointBlockGenerator
68
-
69
- val fetcherProbe : TestProbe = TestProbe ()
70
- val ommersPoolProbe : TestProbe = TestProbe ()
71
- val broadcasterProbe : TestProbe = TestProbe ()
72
- val pendingTransactionsManagerProbe : TestProbe = TestProbe ()
73
- val supervisor : TestProbe = TestProbe ()
74
-
75
- val emptyWorld : InMemoryWorldStateProxy = InMemoryWorldStateProxy (
76
- storagesInstance.storages.evmCodeStorage,
77
- blockchain.getBackingMptStorage(- 1 ),
78
- (number : BigInt ) => blockchainReader.getBlockHeaderByNumber(number).map(_.hash),
79
- blockchainConfig.accountStartNonce,
80
- ByteString (MerklePatriciaTrie .EmptyRootHash ),
81
- noEmptyAccounts = false ,
82
- ethCompatibleStorage = true
83
- )
84
-
85
- override protected lazy val successValidators : Validators = new Mocks .MockValidatorsAlwaysSucceed {
86
- override val ommersValidator : OmmersValidator = (
87
- parentHash : ByteString ,
88
- blockNumber : BigInt ,
89
- ommers : Seq [BlockHeader ],
90
- getBlockHeaderByHash : GetBlockHeaderByHash ,
91
- getNBlocksBack : GetNBlocksBack
92
- ) =>
93
- new StdOmmersValidator (blockHeaderValidator)
94
- .validate(parentHash, blockNumber, ommers, getBlockHeaderByHash, getNBlocksBack)
95
- }
96
-
97
- override lazy val blockImport : BlockImport = mkBlockImport(
98
- validators = successValidators,
99
- blockExecutionOpt = Some (
100
- new BlockExecution (
101
- blockchain,
102
- blockchainReader,
103
- blockchainWriter,
104
- storagesInstance.storages.evmCodeStorage,
105
- blockchainConfig,
106
- consensus.blockPreparator,
107
- new BlockValidation (consensus, blockchainReader, blockQueue)
108
- ) {
109
- override def executeAndValidateBlock (
110
- block : Block ,
111
- alreadyValidated : Boolean = false
112
- ): Either [BlockExecutionError , Seq [Receipt ]] =
113
- Right (BlockResult (emptyWorld).receipts)
114
- }
115
- )
116
- )
117
- // }
118
-
119
- val blockImporter : ActorRef = system.actorOf(
120
- BlockImporter .props(
121
- fetcherProbe.ref,
122
- blockImport,
123
- blockchain,
124
- blockchainReader,
125
- storagesInstance.storages.stateStorage,
126
- new BranchResolution (blockchain, blockchainReader),
127
- syncConfig,
128
- ommersPoolProbe.ref,
129
- broadcasterProbe.ref,
130
- pendingTransactionsManagerProbe.ref,
131
- supervisor.ref
132
- )
133
- )
134
-
135
- val genesisBlock = blockchainReader.genesisBlock
136
- val block1 : Block = getBlock(genesisBlock.number + 1 , parent = genesisBlock.header.hash)
137
- // new chain is shorter but has a higher weight
138
- val newBlock2 : Block = getBlock(genesisBlock.number + 2 , difficulty = 108 , parent = block1.header.hash)
139
- val newBlock3 : Block = getBlock(genesisBlock.number + 3 , difficulty = 300 , parent = newBlock2.header.hash)
140
- val oldBlock2 : Block = getBlock(genesisBlock.number + 2 , difficulty = 102 , parent = block1.header.hash)
141
- val oldBlock3 : Block = getBlock(genesisBlock.number + 3 , difficulty = 103 , parent = oldBlock2.header.hash)
142
- val oldBlock4 : Block = getBlock(genesisBlock.number + 4 , difficulty = 104 , parent = oldBlock3.header.hash)
143
-
144
- val weight1 : ChainWeight = ChainWeight .totalDifficultyOnly(block1.header.difficulty)
145
- val newWeight2 : ChainWeight = weight1.increase(newBlock2.header)
146
- val newWeight3 : ChainWeight = newWeight2.increase(newBlock3.header)
147
- val oldWeight2 : ChainWeight = weight1.increase(oldBlock2.header)
148
- val oldWeight3 : ChainWeight = oldWeight2.increase(oldBlock3.header)
149
- val oldWeight4 : ChainWeight = oldWeight3.increase(oldBlock4.header)
150
-
151
- // saving initial main chain
152
- blockchainWriter.save(block1, Nil , weight1, saveAsBestBlock = true )
153
- blockchainWriter.save(oldBlock2, Nil , oldWeight2, saveAsBestBlock = true )
154
- blockchainWriter.save(oldBlock3, Nil , oldWeight3, saveAsBestBlock = true )
155
- blockchainWriter.save(oldBlock4, Nil , oldWeight4, saveAsBestBlock = true )
156
-
157
- val oldBranch : List [Block ] = List (oldBlock2, oldBlock3, oldBlock4)
158
- val newBranch : List [Block ] = List (newBlock2, newBlock3)
159
-
160
- blockImporter ! BlockImporter .Start
161
-
162
- " BlockImporter" should " not discard blocks of the main chain if the reorganisation failed" in {
47
+ " BlockImporter" should " not discard blocks of the main chain if the reorganisation failed" in new TestFixture () {
163
48
164
- val blockImporter = system.actorOf(
49
+ override val blockImporter = system.actorOf(
165
50
BlockImporter .props(
166
51
fetcherProbe.ref,
167
52
mkBlockImport(validators = successValidators),
@@ -184,8 +69,7 @@ class BlockImporterItSpec
184
69
eventually(blockchainReader.getBestBlock().get shouldEqual oldBlock4)
185
70
}
186
71
187
- it should " return a correct new best block after reorganising longer chain to a shorter one if its weight is bigger" in {
188
-
72
+ it should " return a correct new best block after reorganising longer chain to a shorter one if its weight is bigger" in new StartedImportFixture () {
189
73
// returning discarded initial chain
190
74
blockchainWriter.save(oldBlock2, Nil , oldWeight2, saveAsBestBlock = true )
191
75
blockchainWriter.save(oldBlock3, Nil , oldWeight3, saveAsBestBlock = true )
@@ -196,7 +80,7 @@ class BlockImporterItSpec
196
80
eventually(blockchainReader.getBestBlock().get shouldEqual newBlock3)
197
81
}
198
82
199
- it should " return Unknown branch, in case of PickedBlocks with block that has a parent that's not in the chain" in {
83
+ it should " return Unknown branch, in case of PickedBlocks with block that has a parent that's not in the chain" in new StartedImportFixture () {
200
84
val newBlock4ParentOldBlock3 : Block =
201
85
getBlock(genesisBlock.number + 4 , difficulty = 104 , parent = oldBlock3.header.hash)
202
86
val newBlock4WeightParentOldBlock3 = oldWeight3.increase(newBlock4ParentOldBlock3.header)
@@ -223,35 +107,35 @@ class BlockImporterItSpec
223
107
eventually(blockchainReader.getBestBlock().get shouldEqual newBlock4ParentOldBlock3)
224
108
}
225
109
226
- it should " switch to a branch with a checkpoint" in {
110
+ it should " switch to a branch with a checkpoint" in new StartedImportFixture () {
227
111
228
112
val checkpoint = ObjectGenerators .fakeCheckpointGen(3 , 3 ).sample.get
229
113
val oldBlock5WithCheckpoint : Block = checkpointBlockGenerator.generate(oldBlock4, checkpoint)
230
114
blockchainWriter.save(oldBlock5WithCheckpoint, Nil , oldWeight4, saveAsBestBlock = true )
231
115
232
- val newBranch = List (newBlock2, newBlock3)
116
+ override val newBranch = List (newBlock2, newBlock3)
233
117
234
118
blockImporter ! BlockFetcher .PickedBlocks (NonEmptyList .fromListUnsafe(newBranch))
235
119
236
120
eventually(blockchainReader.getBestBlock().get shouldEqual oldBlock5WithCheckpoint)
237
121
eventually(blockchain.getLatestCheckpointBlockNumber() shouldEqual oldBlock5WithCheckpoint.header.number)
238
122
}
239
123
240
- it should " switch to a branch with a newer checkpoint" in {
124
+ it should " switch to a branch with a newer checkpoint" in new StartedImportFixture () {
241
125
242
126
val checkpoint = ObjectGenerators .fakeCheckpointGen(3 , 3 ).sample.get
243
127
val newBlock4WithCheckpoint : Block = checkpointBlockGenerator.generate(newBlock3, checkpoint)
244
128
blockchainWriter.save(newBlock4WithCheckpoint, Nil , newWeight3, saveAsBestBlock = true )
245
129
246
- val newBranch = List (newBlock4WithCheckpoint)
130
+ override val newBranch = List (newBlock4WithCheckpoint)
247
131
248
132
blockImporter ! BlockFetcher .PickedBlocks (NonEmptyList .fromListUnsafe(newBranch))
249
133
250
134
eventually(blockchainReader.getBestBlock().get shouldEqual newBlock4WithCheckpoint)
251
135
eventually(blockchain.getLatestCheckpointBlockNumber() shouldEqual newBlock4WithCheckpoint.header.number)
252
136
}
253
137
254
- it should " return a correct checkpointed block after receiving a request for generating a new checkpoint" in {
138
+ it should " return a correct checkpointed block after receiving a request for generating a new checkpoint" in new StartedImportFixture () {
255
139
256
140
val parent = blockchainReader.getBestBlock().get
257
141
val newBlock5 : Block = getBlock(genesisBlock.number + 5 , difficulty = 104 , parent = parent.header.hash)
@@ -270,12 +154,12 @@ class BlockImporterItSpec
270
154
eventually(blockchain.getLatestCheckpointBlockNumber() shouldEqual newBlock5.header.number + 1 )
271
155
}
272
156
273
- it should " ask BlockFetcher to resolve missing node" in {
157
+ it should " ask BlockFetcher to resolve missing node" in new TestFixture () {
274
158
val parent = blockchainReader.getBestBlock().get
275
159
val newBlock : Block = getBlock(genesisBlock.number + 5 , difficulty = 104 , parent = parent.header.hash)
276
160
val invalidBlock = newBlock.copy(header = newBlock.header.copy(beneficiary = Address (111 ).bytes))
277
161
278
- val blockImporter = system.actorOf(
162
+ override val blockImporter = system.actorOf(
279
163
BlockImporter .props(
280
164
fetcherProbe.ref,
281
165
mkBlockImport(validators = successValidators),
@@ -296,7 +180,7 @@ class BlockImporterItSpec
296
180
297
181
eventually {
298
182
val msg = fetcherProbe
299
- .fishForMessage(Timeouts .longTimeout ) {
183
+ .fishForMessage(Timeouts .normalTimeout ) {
300
184
case BlockFetcher .FetchStateNode (_, _) => true
301
185
case _ => false
302
186
}
@@ -307,3 +191,112 @@ class BlockImporterItSpec
307
191
308
192
}
309
193
}
194
+
195
+ class TestFixture extends TestSetupWithVmAndValidators {
196
+
197
+ override lazy val blockQueue : BlockQueue = BlockQueue (blockchain, blockchainReader, SyncConfig (Config .config))
198
+
199
+ val genesis : Block = Block (
200
+ Fixtures .Blocks .Genesis .header.copy(stateRoot = ByteString (MerklePatriciaTrie .EmptyRootHash )),
201
+ Fixtures .Blocks .Genesis .body
202
+ )
203
+ val genesisWeight : ChainWeight = ChainWeight .zero.increase(genesis.header)
204
+
205
+ blockchainWriter.save(genesis, Seq (), genesisWeight, saveAsBestBlock = true )
206
+
207
+ lazy val checkpointBlockGenerator : CheckpointBlockGenerator = new CheckpointBlockGenerator
208
+
209
+ val fetcherProbe : TestProbe = TestProbe ()
210
+ val ommersPoolProbe : TestProbe = TestProbe ()
211
+ val broadcasterProbe : TestProbe = TestProbe ()
212
+ val pendingTransactionsManagerProbe : TestProbe = TestProbe ()
213
+ val supervisor : TestProbe = TestProbe ()
214
+
215
+ val emptyWorld : InMemoryWorldStateProxy = InMemoryWorldStateProxy (
216
+ storagesInstance.storages.evmCodeStorage,
217
+ blockchain.getBackingMptStorage(- 1 ),
218
+ (number : BigInt ) => blockchainReader.getBlockHeaderByNumber(number).map(_.hash),
219
+ blockchainConfig.accountStartNonce,
220
+ ByteString (MerklePatriciaTrie .EmptyRootHash ),
221
+ noEmptyAccounts = false ,
222
+ ethCompatibleStorage = true
223
+ )
224
+
225
+ override protected lazy val successValidators : Validators = new Mocks .MockValidatorsAlwaysSucceed {
226
+ override val ommersValidator : OmmersValidator = (
227
+ parentHash : ByteString ,
228
+ blockNumber : BigInt ,
229
+ ommers : Seq [BlockHeader ],
230
+ getBlockHeaderByHash : GetBlockHeaderByHash ,
231
+ getNBlocksBack : GetNBlocksBack
232
+ ) =>
233
+ new StdOmmersValidator (blockHeaderValidator)
234
+ .validate(parentHash, blockNumber, ommers, getBlockHeaderByHash, getNBlocksBack)
235
+ }
236
+
237
+ override lazy val blockImport : BlockImport = mkBlockImport(
238
+ validators = successValidators,
239
+ blockExecutionOpt = Some (
240
+ new BlockExecution (
241
+ blockchain,
242
+ blockchainReader,
243
+ blockchainWriter,
244
+ storagesInstance.storages.evmCodeStorage,
245
+ blockchainConfig,
246
+ consensus.blockPreparator,
247
+ new BlockValidation (consensus, blockchainReader, blockQueue)
248
+ ) {
249
+ override def executeAndValidateBlock (
250
+ block : Block ,
251
+ alreadyValidated : Boolean = false
252
+ ): Either [BlockExecutionError , Seq [Receipt ]] =
253
+ Right (BlockResult (emptyWorld).receipts)
254
+ }
255
+ )
256
+ )
257
+
258
+ val blockImporter : ActorRef = system.actorOf(
259
+ BlockImporter .props(
260
+ fetcherProbe.ref,
261
+ blockImport,
262
+ blockchain,
263
+ blockchainReader,
264
+ storagesInstance.storages.stateStorage,
265
+ new BranchResolution (blockchain, blockchainReader),
266
+ syncConfig,
267
+ ommersPoolProbe.ref,
268
+ broadcasterProbe.ref,
269
+ pendingTransactionsManagerProbe.ref,
270
+ supervisor.ref
271
+ )
272
+ )
273
+
274
+ val genesisBlock = blockchainReader.genesisBlock
275
+ val block1 : Block = getBlock(genesisBlock.number + 1 , parent = genesisBlock.header.hash)
276
+ // new chain is shorter but has a higher weight
277
+ val newBlock2 : Block = getBlock(genesisBlock.number + 2 , difficulty = 108 , parent = block1.header.hash)
278
+ val newBlock3 : Block = getBlock(genesisBlock.number + 3 , difficulty = 300 , parent = newBlock2.header.hash)
279
+ val oldBlock2 : Block = getBlock(genesisBlock.number + 2 , difficulty = 102 , parent = block1.header.hash)
280
+ val oldBlock3 : Block = getBlock(genesisBlock.number + 3 , difficulty = 103 , parent = oldBlock2.header.hash)
281
+ val oldBlock4 : Block = getBlock(genesisBlock.number + 4 , difficulty = 104 , parent = oldBlock3.header.hash)
282
+
283
+ val weight1 : ChainWeight = ChainWeight .totalDifficultyOnly(block1.header.difficulty)
284
+ val newWeight2 : ChainWeight = weight1.increase(newBlock2.header)
285
+ val newWeight3 : ChainWeight = newWeight2.increase(newBlock3.header)
286
+ val oldWeight2 : ChainWeight = weight1.increase(oldBlock2.header)
287
+ val oldWeight3 : ChainWeight = oldWeight2.increase(oldBlock3.header)
288
+ val oldWeight4 : ChainWeight = oldWeight3.increase(oldBlock4.header)
289
+
290
+ // saving initial main chain
291
+ blockchainWriter.save(block1, Nil , weight1, saveAsBestBlock = true )
292
+ blockchainWriter.save(oldBlock2, Nil , oldWeight2, saveAsBestBlock = true )
293
+ blockchainWriter.save(oldBlock3, Nil , oldWeight3, saveAsBestBlock = true )
294
+ blockchainWriter.save(oldBlock4, Nil , oldWeight4, saveAsBestBlock = true )
295
+
296
+ val oldBranch : List [Block ] = List (oldBlock2, oldBlock3, oldBlock4)
297
+ val newBranch : List [Block ] = List (newBlock2, newBlock3)
298
+ }
299
+
300
+ class StartedImportFixture extends TestFixture {
301
+ blockImporter ! BlockImporter .Start
302
+ }
0 commit comments