Skip to content

Commit da11b98

Browse files
authored
[Kaizen] Unflake BlockImporterItSpec (#1047)
1 parent 7456a31 commit da11b98

File tree

1 file changed

+121
-119
lines changed

1 file changed

+121
-119
lines changed

src/it/scala/io/iohk/ethereum/ledger/BlockImporterItSpec.scala

Lines changed: 121 additions & 119 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@ import io.iohk.ethereum.utils.Config.SyncConfig
4040

4141
class BlockImporterItSpec
4242
extends MockFactory
43-
with TestSetupWithVmAndValidators
4443
with AnyFlatSpecLike
4544
with Matchers
4645
with BeforeAndAfterAll
@@ -54,114 +53,9 @@ class BlockImporterItSpec
5453
testScheduler.awaitTermination(60.second)
5554
}
5655

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-
// }
56+
"BlockImporter" should "not discard blocks of the main chain if the reorganisation failed" in new TestFixture() {
11857

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 {
163-
164-
val blockImporter = system.actorOf(
58+
override val blockImporter = system.actorOf(
16559
BlockImporter.props(
16660
fetcherProbe.ref,
16761
mkBlockImport(validators = successValidators),
@@ -184,8 +78,7 @@ class BlockImporterItSpec
18478
eventually(blockchainReader.getBestBlock().get shouldEqual oldBlock4)
18579
}
18680

187-
it should "return a correct new best block after reorganising longer chain to a shorter one if its weight is bigger" in {
188-
81+
it should "return a correct new best block after reorganising longer chain to a shorter one if its weight is bigger" in new StartedImportFixture() {
18982
//returning discarded initial chain
19083
blockchainWriter.save(oldBlock2, Nil, oldWeight2, saveAsBestBlock = true)
19184
blockchainWriter.save(oldBlock3, Nil, oldWeight3, saveAsBestBlock = true)
@@ -196,7 +89,7 @@ class BlockImporterItSpec
19689
eventually(blockchainReader.getBestBlock().get shouldEqual newBlock3)
19790
}
19891

199-
it should "return Unknown branch, in case of PickedBlocks with block that has a parent that's not in the chain" in {
92+
it should "return Unknown branch, in case of PickedBlocks with block that has a parent that's not in the chain" in new StartedImportFixture() {
20093
val newBlock4ParentOldBlock3: Block =
20194
getBlock(genesisBlock.number + 4, difficulty = 104, parent = oldBlock3.header.hash)
20295
val newBlock4WeightParentOldBlock3 = oldWeight3.increase(newBlock4ParentOldBlock3.header)
@@ -223,35 +116,35 @@ class BlockImporterItSpec
223116
eventually(blockchainReader.getBestBlock().get shouldEqual newBlock4ParentOldBlock3)
224117
}
225118

226-
it should "switch to a branch with a checkpoint" in {
119+
it should "switch to a branch with a checkpoint" in new StartedImportFixture() {
227120

228121
val checkpoint = ObjectGenerators.fakeCheckpointGen(3, 3).sample.get
229122
val oldBlock5WithCheckpoint: Block = checkpointBlockGenerator.generate(oldBlock4, checkpoint)
230123
blockchainWriter.save(oldBlock5WithCheckpoint, Nil, oldWeight4, saveAsBestBlock = true)
231124

232-
val newBranch = List(newBlock2, newBlock3)
125+
override val newBranch = List(newBlock2, newBlock3)
233126

234127
blockImporter ! BlockFetcher.PickedBlocks(NonEmptyList.fromListUnsafe(newBranch))
235128

236129
eventually(blockchainReader.getBestBlock().get shouldEqual oldBlock5WithCheckpoint)
237130
eventually(blockchain.getLatestCheckpointBlockNumber() shouldEqual oldBlock5WithCheckpoint.header.number)
238131
}
239132

240-
it should "switch to a branch with a newer checkpoint" in {
133+
it should "switch to a branch with a newer checkpoint" in new StartedImportFixture() {
241134

242135
val checkpoint = ObjectGenerators.fakeCheckpointGen(3, 3).sample.get
243136
val newBlock4WithCheckpoint: Block = checkpointBlockGenerator.generate(newBlock3, checkpoint)
244137
blockchainWriter.save(newBlock4WithCheckpoint, Nil, newWeight3, saveAsBestBlock = true)
245138

246-
val newBranch = List(newBlock4WithCheckpoint)
139+
override val newBranch = List(newBlock4WithCheckpoint)
247140

248141
blockImporter ! BlockFetcher.PickedBlocks(NonEmptyList.fromListUnsafe(newBranch))
249142

250143
eventually(blockchainReader.getBestBlock().get shouldEqual newBlock4WithCheckpoint)
251144
eventually(blockchain.getLatestCheckpointBlockNumber() shouldEqual newBlock4WithCheckpoint.header.number)
252145
}
253146

254-
it should "return a correct checkpointed block after receiving a request for generating a new checkpoint" in {
147+
it should "return a correct checkpointed block after receiving a request for generating a new checkpoint" in new StartedImportFixture() {
255148

256149
val parent = blockchainReader.getBestBlock().get
257150
val newBlock5: Block = getBlock(genesisBlock.number + 5, difficulty = 104, parent = parent.header.hash)
@@ -270,12 +163,12 @@ class BlockImporterItSpec
270163
eventually(blockchain.getLatestCheckpointBlockNumber() shouldEqual newBlock5.header.number + 1)
271164
}
272165

273-
it should "ask BlockFetcher to resolve missing node" in {
166+
it should "ask BlockFetcher to resolve missing node" in new TestFixture() {
274167
val parent = blockchainReader.getBestBlock().get
275168
val newBlock: Block = getBlock(genesisBlock.number + 5, difficulty = 104, parent = parent.header.hash)
276169
val invalidBlock = newBlock.copy(header = newBlock.header.copy(beneficiary = Address(111).bytes))
277170

278-
val blockImporter = system.actorOf(
171+
override val blockImporter = system.actorOf(
279172
BlockImporter.props(
280173
fetcherProbe.ref,
281174
mkBlockImport(validators = successValidators),
@@ -296,7 +189,7 @@ class BlockImporterItSpec
296189

297190
eventually {
298191
val msg = fetcherProbe
299-
.fishForMessage(Timeouts.longTimeout) {
192+
.fishForMessage(Timeouts.normalTimeout) {
300193
case BlockFetcher.FetchStateNode(_, _) => true
301194
case _ => false
302195
}
@@ -307,3 +200,112 @@ class BlockImporterItSpec
307200

308201
}
309202
}
203+
204+
class TestFixture extends TestSetupWithVmAndValidators {
205+
206+
override lazy val blockQueue: BlockQueue = BlockQueue(blockchain, blockchainReader, SyncConfig(Config.config))
207+
208+
val genesis: Block = Block(
209+
Fixtures.Blocks.Genesis.header.copy(stateRoot = ByteString(MerklePatriciaTrie.EmptyRootHash)),
210+
Fixtures.Blocks.Genesis.body
211+
)
212+
val genesisWeight: ChainWeight = ChainWeight.zero.increase(genesis.header)
213+
214+
blockchainWriter.save(genesis, Seq(), genesisWeight, saveAsBestBlock = true)
215+
216+
lazy val checkpointBlockGenerator: CheckpointBlockGenerator = new CheckpointBlockGenerator
217+
218+
val fetcherProbe: TestProbe = TestProbe()
219+
val ommersPoolProbe: TestProbe = TestProbe()
220+
val broadcasterProbe: TestProbe = TestProbe()
221+
val pendingTransactionsManagerProbe: TestProbe = TestProbe()
222+
val supervisor: TestProbe = TestProbe()
223+
224+
val emptyWorld: InMemoryWorldStateProxy = InMemoryWorldStateProxy(
225+
storagesInstance.storages.evmCodeStorage,
226+
blockchain.getBackingMptStorage(-1),
227+
(number: BigInt) => blockchainReader.getBlockHeaderByNumber(number).map(_.hash),
228+
blockchainConfig.accountStartNonce,
229+
ByteString(MerklePatriciaTrie.EmptyRootHash),
230+
noEmptyAccounts = false,
231+
ethCompatibleStorage = true
232+
)
233+
234+
override protected lazy val successValidators: Validators = new Mocks.MockValidatorsAlwaysSucceed {
235+
override val ommersValidator: OmmersValidator = (
236+
parentHash: ByteString,
237+
blockNumber: BigInt,
238+
ommers: Seq[BlockHeader],
239+
getBlockHeaderByHash: GetBlockHeaderByHash,
240+
getNBlocksBack: GetNBlocksBack
241+
) =>
242+
new StdOmmersValidator(blockHeaderValidator)
243+
.validate(parentHash, blockNumber, ommers, getBlockHeaderByHash, getNBlocksBack)
244+
}
245+
246+
override lazy val blockImport: BlockImport = mkBlockImport(
247+
validators = successValidators,
248+
blockExecutionOpt = Some(
249+
new BlockExecution(
250+
blockchain,
251+
blockchainReader,
252+
blockchainWriter,
253+
storagesInstance.storages.evmCodeStorage,
254+
blockchainConfig,
255+
consensus.blockPreparator,
256+
new BlockValidation(consensus, blockchainReader, blockQueue)
257+
) {
258+
override def executeAndValidateBlock(
259+
block: Block,
260+
alreadyValidated: Boolean = false
261+
): Either[BlockExecutionError, Seq[Receipt]] =
262+
Right(BlockResult(emptyWorld).receipts)
263+
}
264+
)
265+
)
266+
267+
val blockImporter: ActorRef = system.actorOf(
268+
BlockImporter.props(
269+
fetcherProbe.ref,
270+
blockImport,
271+
blockchain,
272+
blockchainReader,
273+
storagesInstance.storages.stateStorage,
274+
new BranchResolution(blockchain, blockchainReader),
275+
syncConfig,
276+
ommersPoolProbe.ref,
277+
broadcasterProbe.ref,
278+
pendingTransactionsManagerProbe.ref,
279+
supervisor.ref
280+
)
281+
)
282+
283+
val genesisBlock = blockchainReader.genesisBlock
284+
val block1: Block = getBlock(genesisBlock.number + 1, parent = genesisBlock.header.hash)
285+
// new chain is shorter but has a higher weight
286+
val newBlock2: Block = getBlock(genesisBlock.number + 2, difficulty = 108, parent = block1.header.hash)
287+
val newBlock3: Block = getBlock(genesisBlock.number + 3, difficulty = 300, parent = newBlock2.header.hash)
288+
val oldBlock2: Block = getBlock(genesisBlock.number + 2, difficulty = 102, parent = block1.header.hash)
289+
val oldBlock3: Block = getBlock(genesisBlock.number + 3, difficulty = 103, parent = oldBlock2.header.hash)
290+
val oldBlock4: Block = getBlock(genesisBlock.number + 4, difficulty = 104, parent = oldBlock3.header.hash)
291+
292+
val weight1: ChainWeight = ChainWeight.totalDifficultyOnly(block1.header.difficulty)
293+
val newWeight2: ChainWeight = weight1.increase(newBlock2.header)
294+
val newWeight3: ChainWeight = newWeight2.increase(newBlock3.header)
295+
val oldWeight2: ChainWeight = weight1.increase(oldBlock2.header)
296+
val oldWeight3: ChainWeight = oldWeight2.increase(oldBlock3.header)
297+
val oldWeight4: ChainWeight = oldWeight3.increase(oldBlock4.header)
298+
299+
//saving initial main chain
300+
blockchainWriter.save(block1, Nil, weight1, saveAsBestBlock = true)
301+
blockchainWriter.save(oldBlock2, Nil, oldWeight2, saveAsBestBlock = true)
302+
blockchainWriter.save(oldBlock3, Nil, oldWeight3, saveAsBestBlock = true)
303+
blockchainWriter.save(oldBlock4, Nil, oldWeight4, saveAsBestBlock = true)
304+
305+
val oldBranch: List[Block] = List(oldBlock2, oldBlock3, oldBlock4)
306+
val newBranch: List[Block] = List(newBlock2, newBlock3)
307+
}
308+
309+
class StartedImportFixture extends TestFixture {
310+
blockImporter ! BlockImporter.Start
311+
}

0 commit comments

Comments
 (0)