Skip to content

Commit cbf21d2

Browse files
authored
[ETCM-927] enhance BlockchainTests/ValidBlocks/bcMultiChainTest/ChainAtoChainB_difficultyB test
* [ETCM-927] enhance BlockchainTests/ValidBlocks/bcMultiChainTest/ChainAtoChainB_difficultyB test * [ETCM-927] improve error messages in EthBlockService.getBlockByHash() * [ETCM-781] inserted blocks causing chain reorganizion are now valid * [ETCM-927] fix test compilation error following merge * [ETCM-927] syntax simplification * [ETCM-927] make TestEthBlockServiceWrapper.getBlockByHash easier to read
1 parent cf30683 commit cbf21d2

File tree

9 files changed

+122
-33
lines changed

9 files changed

+122
-33
lines changed

src/main/scala/io/iohk/ethereum/jsonrpc/EthBlocksService.scala

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import io.iohk.ethereum.domain.{Blockchain, BlockchainReader}
55
import monix.eval.Task
66
import org.bouncycastle.util.encoders.Hex
77
import io.iohk.ethereum.consensus.Consensus
8+
import io.iohk.ethereum.ledger.BlockQueue
89

910
object EthBlocksService {
1011
case class BestBlockNumberRequest()
@@ -38,7 +39,8 @@ object EthBlocksService {
3839
class EthBlocksService(
3940
val blockchain: Blockchain,
4041
val blockchainReader: BlockchainReader,
41-
val consensus: Consensus
42+
val consensus: Consensus,
43+
val blockQueue: BlockQueue
4244
) extends ResolveBlock {
4345
import EthBlocksService._
4446

@@ -71,8 +73,8 @@ class EthBlocksService(
7173
*/
7274
def getByBlockHash(request: BlockByBlockHashRequest): ServiceResponse[BlockByBlockHashResponse] = Task {
7375
val BlockByBlockHashRequest(blockHash, fullTxs) = request
74-
val blockOpt = blockchainReader.getBlockByHash(blockHash)
75-
val weight = blockchain.getChainWeightByHash(blockHash)
76+
val blockOpt = blockchainReader.getBlockByHash(blockHash) orElse blockQueue.getBlockByHash(blockHash)
77+
val weight = blockchain.getChainWeightByHash(blockHash) orElse blockQueue.getChainWeightByHash(blockHash)
7678

7779
val blockResponseOpt = blockOpt.map(block => BlockResponse(block, weight, fullTxs = fullTxs))
7880
Right(BlockByBlockHashResponse(blockResponseOpt))

src/main/scala/io/iohk/ethereum/jsonrpc/TestService.scala

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,10 @@ class TestService(
136136
def setChainParams(request: SetChainParamsRequest): ServiceResponse[SetChainParamsResponse] = {
137137
currentConfig = buildNewConfig(request.chainParams.blockchainParams)
138138

139+
// clear ledger's cache on test start
140+
// setChainParams is expected to be the first remote call for each test
141+
testModeComponentsProvider.clearState()
142+
139143
val genesisData = GenesisData(
140144
nonce = request.chainParams.genesis.nonce,
141145
mixHash = Some(request.chainParams.genesis.mixHash),
@@ -158,6 +162,9 @@ class TestService(
158162

159163
// remove current genesis (Try because it may not exist)
160164
Try(blockchain.removeBlock(blockchain.genesisHeader.hash, withState = false))
165+
// TODO clear the storage ? When relaunching some tests on the same running test mantis client,
166+
// we end up with duplicate blocks because they are still present in the storage layer
167+
// for example: bcMultiChainTest/ChainAtoChainB_BlockHash_Istanbul
161168

162169
// load the new genesis
163170
val genesisDataLoader = new GenesisDataLoader(blockchain, blockchainReader, stateStorage, currentConfig)
@@ -276,15 +283,20 @@ class TestService(
276283
testModeComponentsProvider
277284
.blockImport(currentConfig, preimageCache, sealEngine)
278285
.importBlock(value)
279-
.flatMap(handleResult)
286+
.flatMap(handleResult(value))
280287
}
281288
}
282289

283-
private def handleResult(blockImportResult: BlockImportResult): ServiceResponse[ImportRawBlockResponse] = {
290+
private def handleResult(
291+
block: Block
292+
)(blockImportResult: BlockImportResult): ServiceResponse[ImportRawBlockResponse] = {
284293
blockImportResult match {
285294
case BlockImportedToTop(blockImportData) =>
286295
val blockHash = s"0x${ByteStringUtils.hash2string(blockImportData.head.block.header.hash)}"
287296
ImportRawBlockResponse(blockHash).rightNow
297+
case BlockEnqueued | ChainReorganised(_, _, _) =>
298+
val blockHash = s"0x${ByteStringUtils.hash2string(block.hash)}"
299+
ImportRawBlockResponse(blockHash).rightNow
288300
case e =>
289301
log.warn("Block import failed with {}", e)
290302
Task.now(Left(JsonRpcError(-1, "block validation failed!", None)))

src/main/scala/io/iohk/ethereum/ledger/BlockQueue.scala

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,14 @@ class BlockQueue(blockchain: Blockchain, val maxQueuedBlockNumberAhead: Int, val
8282
def isQueued(hash: ByteString): Boolean =
8383
blocks.contains(hash)
8484

85+
/**
86+
* Returns the weight of the block corresponding to the hash, or None if not found
87+
* @param hash the block's hash to get the weight from
88+
* @return the weight of the block corresponding to the hash, or None if not found
89+
*/
90+
def getChainWeightByHash(hash: ByteString): Option[ChainWeight] =
91+
blocks.get(hash).flatMap(_.weight)
92+
8593
/**
8694
* Takes a branch going from descendant block upwards to the oldest ancestor
8795
* @param descendant the youngest block to be removed
@@ -124,6 +132,14 @@ class BlockQueue(blockchain: Blockchain, val maxQueuedBlockNumberAhead: Int, val
124132
parentToChildren -= block.header.hash
125133
}
126134

135+
/**
136+
* Clear the BlockQueue
137+
*/
138+
def clear(): Unit = {
139+
blocks.clear()
140+
parentToChildren.clear()
141+
}
142+
127143
/**
128144
* Removes stale blocks - too old or too young in relation the current best block number
129145
* @param bestBlockNumber - best block number of the main chain
@@ -193,4 +209,5 @@ class BlockQueue(blockchain: Blockchain, val maxQueuedBlockNumberAhead: Int, val
193209
private def isNumberOutOfRange(blockNumber: BigInt, bestBlockNumber: BigInt): Boolean =
194210
blockNumber - bestBlockNumber > maxQueuedBlockNumberAhead ||
195211
bestBlockNumber - blockNumber > maxQueuedBlockNumberBehind
212+
196213
}

src/main/scala/io/iohk/ethereum/nodebuilder/NodeBuilder.scala

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -432,8 +432,9 @@ trait TestServiceBuilder {
432432
}
433433

434434
trait TestEthBlockServiceBuilder extends EthBlocksServiceBuilder {
435-
self: TestBlockchainBuilder with TestModeServiceBuilder with ConsensusBuilder =>
436-
override lazy val ethBlocksService = new TestEthBlockServiceWrapper(blockchain, blockchainReader, consensus)
435+
self: TestBlockchainBuilder with TestModeServiceBuilder with ConsensusBuilder with BlockQueueBuilder =>
436+
override lazy val ethBlocksService =
437+
new TestEthBlockServiceWrapper(blockchain, blockchainReader, consensus, blockQueue)
437438
}
438439

439440
trait EthProofServiceBuilder {
@@ -509,9 +510,9 @@ trait EthTxServiceBuilder {
509510
}
510511

511512
trait EthBlocksServiceBuilder {
512-
self: BlockchainBuilder with ConsensusBuilder =>
513+
self: BlockchainBuilder with ConsensusBuilder with BlockQueueBuilder =>
513514

514-
lazy val ethBlocksService = new EthBlocksService(blockchain, blockchainReader, consensus)
515+
lazy val ethBlocksService = new EthBlocksService(blockchain, blockchainReader, consensus, blockQueue)
515516
}
516517

517518
trait EthUserServiceBuilder {

src/main/scala/io/iohk/ethereum/testmode/TestEthBlockServiceWrapper.scala

Lines changed: 35 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,22 @@ import io.iohk.ethereum.jsonrpc.{
66
BaseBlockResponse,
77
BaseTransactionResponse,
88
EthBlocksService,
9+
JsonRpcError,
910
ServiceResponse,
1011
TransactionData
1112
}
1213
import io.iohk.ethereum.utils.Logger
14+
import io.iohk.ethereum.utils.ByteStringUtils._
1315
import akka.util.ByteString
1416
import io.iohk.ethereum.consensus.Consensus
17+
import io.iohk.ethereum.ledger.BlockQueue
1518

1619
class TestEthBlockServiceWrapper(
1720
blockchain: Blockchain,
1821
blockchainReader: BlockchainReader,
19-
consensus: Consensus
20-
) extends EthBlocksService(blockchain, blockchainReader, consensus)
22+
consensus: Consensus,
23+
blockQueue: BlockQueue
24+
) extends EthBlocksService(blockchain, blockchainReader, consensus, blockQueue)
2125
with Logger {
2226

2327
/**
@@ -31,10 +35,29 @@ class TestEthBlockServiceWrapper(
3135
): ServiceResponse[EthBlocksService.BlockByBlockHashResponse] = super
3236
.getByBlockHash(request)
3337
.map(
34-
_.map(blockByBlockResponse => {
35-
val fullBlock = blockchainReader.getBlockByNumber(blockByBlockResponse.blockResponse.get.number).get
36-
BlockByBlockHashResponse(blockByBlockResponse.blockResponse.map(response => toEthResponse(fullBlock, response)))
37-
})
38+
_.flatMap {
39+
40+
case BlockByBlockHashResponse(None) =>
41+
Left(JsonRpcError.LogicError(s"EthBlockService: unable to find block for hash ${request.blockHash.toHex}"))
42+
43+
case BlockByBlockHashResponse(Some(baseBlockResponse)) if baseBlockResponse.hash.isEmpty =>
44+
Left(JsonRpcError.LogicError(s"missing hash for block $baseBlockResponse"))
45+
46+
case BlockByBlockHashResponse(Some(baseBlockResponse)) =>
47+
val ethResponseOpt = for {
48+
hash <- baseBlockResponse.hash
49+
fullBlock <- blockchainReader.getBlockByHash(hash) orElse blockQueue.getBlockByHash(hash)
50+
} yield toEthResponse(fullBlock, baseBlockResponse)
51+
52+
ethResponseOpt match {
53+
case None =>
54+
Left(
55+
JsonRpcError.LogicError(s"Ledger: unable to find block for hash=${baseBlockResponse.hash.get.toHex}")
56+
)
57+
case Some(_) =>
58+
Right(BlockByBlockHashResponse(ethResponseOpt))
59+
}
60+
}
3861
)
3962

4063
/**
@@ -122,9 +145,9 @@ final case class EthTransactionResponse(
122145
gasPrice: BigInt,
123146
gas: BigInt,
124147
input: ByteString,
125-
r: ByteString,
126-
s: ByteString,
127-
v: ByteString
148+
r: BigInt,
149+
s: BigInt,
150+
v: BigInt
128151
) extends BaseTransactionResponse
129152

130153
object EthTransactionResponse {
@@ -149,8 +172,8 @@ object EthTransactionResponse {
149172
gasPrice = stx.tx.gasPrice,
150173
gas = stx.tx.gasLimit,
151174
input = stx.tx.payload,
152-
r = UInt256(stx.signature.r).bytes,
153-
s = UInt256(stx.signature.s).bytes,
154-
v = ByteString(stx.signature.v)
175+
r = stx.signature.r,
176+
s = stx.signature.s,
177+
v = stx.signature.v
155178
)
156179
}

src/main/scala/io/iohk/ethereum/testmode/TestModeComponentsProvider.scala

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ package io.iohk.ethereum.testmode
22

33
import akka.util.ByteString
44
import io.iohk.ethereum.consensus.difficulty.DifficultyCalculator
5-
import io.iohk.ethereum.consensus.{Consensus, ConsensusConfig}
5+
import io.iohk.ethereum.consensus.ConsensusConfig
66
import io.iohk.ethereum.crypto
77
import io.iohk.ethereum.db.storage.EvmCodeStorage
88
import io.iohk.ethereum.domain.{BlockchainImpl, BlockchainReader, UInt256}
@@ -13,9 +13,10 @@ import io.iohk.ethereum.utils.Config.SyncConfig
1313
import monix.execution.Scheduler
1414
import io.iohk.ethereum.ledger.BlockImport
1515
import io.iohk.ethereum.ledger.BlockValidation
16-
import io.iohk.ethereum.ledger.BlockExecution
1716
import io.iohk.ethereum.ledger.BlockQueue
1817

18+
import scala.collection.immutable.HashMap
19+
1920
/** Provides a ledger or consensus instances with modifiable blockchain config (used in test mode). */
2021
class TestModeComponentsProvider(
2122
blockchain: BlockchainImpl,
@@ -28,14 +29,19 @@ class TestModeComponentsProvider(
2829
vm: VMImpl
2930
) {
3031

32+
// private var cache = HashMap.empty[(BlockchainConfig, SealEngineType), BlockImport]
33+
private val internalBlockQueue = BlockQueue(blockchain, syncConfig)
34+
35+
def blockQueue(): BlockQueue = internalBlockQueue
36+
3137
def blockImport(
3238
blockchainConfig: BlockchainConfig,
3339
preimageCache: collection.concurrent.Map[ByteString, UInt256],
3440
sealEngine: SealEngineType
3541
): BlockImport = {
36-
val blockQueue = BlockQueue(blockchain, syncConfig)
42+
// val blockQueue = BlockQueue(blockchain, syncConfig)
3743
val consensuz = consensus(blockchainConfig, sealEngine)
38-
val blockValidation = new BlockValidation(consensuz, blockchainReader, blockQueue)
44+
val blockValidation = new BlockValidation(consensuz, blockchainReader, internalBlockQueue)
3945
val blockExecution =
4046
new TestModeBlockExecution(
4147
blockchain,
@@ -50,13 +56,22 @@ class TestModeComponentsProvider(
5056
new BlockImport(
5157
blockchain,
5258
blockchainReader,
53-
blockQueue,
59+
internalBlockQueue,
5460
blockValidation,
5561
blockExecution,
5662
validationExecutionContext
5763
)
5864
}
5965

66+
/**
67+
* Clear the internal builder state
68+
*/
69+
def clearState(): Unit = {
70+
// blockQueue = BlockQueue(blockchain, syncConfig)
71+
// cache = cache.empty
72+
internalBlockQueue.clear()
73+
}
74+
6075
def stxLedger(blockchainConfig: BlockchainConfig, sealEngine: SealEngineType): StxLedger =
6176
new StxLedger(
6277
blockchain,

src/main/scala/io/iohk/ethereum/testmode/TestModeServiceBuilder.scala

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,9 @@
11
package io.iohk.ethereum.testmode
22

3-
import akka.util.ByteString
4-
import cats.data.NonEmptyList
53
import io.iohk.ethereum.consensus.difficulty.DifficultyCalculator
64
import io.iohk.ethereum.consensus.{Consensus, ConsensusBuilder, ConsensusConfigBuilder}
7-
import io.iohk.ethereum.domain._
85
import io.iohk.ethereum.ledger._
96
import io.iohk.ethereum.nodebuilder.{ActorSystemBuilder, _}
10-
import monix.eval.Task
117
import monix.execution.Scheduler
128

139
trait TestModeServiceBuilder extends StxLedgerBuilder {
@@ -18,6 +14,7 @@ trait TestModeServiceBuilder extends StxLedgerBuilder {
1814
with ConsensusBuilder
1915
with ActorSystemBuilder
2016
with ConsensusConfigBuilder
17+
with BlockQueueBuilder
2118
with VmBuilder =>
2219

2320
val scheduler = Scheduler(system.dispatchers.lookup("validation-context"))
@@ -34,6 +31,26 @@ trait TestModeServiceBuilder extends StxLedgerBuilder {
3431
vm
3532
)
3633

34+
override lazy val blockQueue: BlockQueue = testModeComponentsProvider.blockQueue();
35+
36+
//<<<<<<< HEAD
37+
//=======
38+
// private def testLedger: Ledger = testModeComponentsProvider.ledger(blockchainConfig, SealEngineType.NoReward)
39+
//
40+
// class TestLedgerProxy extends Ledger {
41+
// override def consensus: Consensus = testLedger.consensus
42+
// override def checkBlockStatus(blockHash: ByteString): BlockStatus = testLedger.checkBlockStatus(blockHash)
43+
// override def getBlockByHash(hash: ByteString): Option[Block] = testLedger.getBlockByHash(hash)
44+
// override def importBlock(block: Block)(implicit
45+
// blockExecutionScheduler: Scheduler
46+
// ): Task[BlockImportResult] = testLedger.importBlock(block)
47+
// override def resolveBranch(headers: NonEmptyList[BlockHeader]): BranchResolutionResult =
48+
// testLedger.resolveBranch(headers)
49+
// override def getChainWeightByHash(hash: ByteString): Option[ChainWeight] = testLedger.getChainWeightByHash(hash)
50+
// }
51+
//
52+
// override lazy val ledger: Ledger = new TestLedgerProxy
53+
//>>>>>>> f521a3125 ([ETCM-927] enhance BlockchainTests/ValidBlocks/bcMultiChainTest/ChainAtoChainB_difficultyB test)
3754
override lazy val stxLedger: StxLedger =
3855
testModeComponentsProvider.stxLedger(blockchainConfig, SealEngineType.NoReward)
3956
}

src/test/scala/io/iohk/ethereum/jsonrpc/EthBlocksServiceSpec.scala

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -397,13 +397,15 @@ class EthBlocksServiceSpec
397397
class TestSetup(implicit system: ActorSystem) extends MockFactory with EphemBlockchainTestSetup {
398398
val blockGenerator = mock[PoWBlockGenerator]
399399
val appStateStorage = mock[AppStateStorage]
400+
400401
override lazy val consensus: TestConsensus = buildTestConsensus().withBlockGenerator(blockGenerator)
401402
override lazy val consensusConfig = ConsensusConfigs.consensusConfig
402403

403404
lazy val ethBlocksService = new EthBlocksService(
404405
blockchain,
405406
blockchainReader,
406-
consensus
407+
consensus,
408+
blockQueue
407409
)
408410

409411
val blockToRequest = Block(Fixtures.Blocks.Block3125369.header, Fixtures.Blocks.Block3125369.body)

src/test/scala/io/iohk/ethereum/jsonrpc/JsonRpcControllerFixture.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ import io.iohk.ethereum.domain.{Block, BlockBody, SignedTransaction}
1515
import io.iohk.ethereum.jsonrpc.server.controllers.JsonRpcBaseController.JsonRpcConfig
1616
import io.iohk.ethereum.keystore.KeyStore
1717
import io.iohk.ethereum.ledger.{BloomFilter, InMemoryWorldStateProxy, StxLedger}
18-
import io.iohk.ethereum.mpt.MerklePatriciaTrie
1918
import io.iohk.ethereum.network.p2p.messages.Capability
2019
import io.iohk.ethereum.nodebuilder.ApisBuilder
2120
import io.iohk.ethereum.utils.{Config, FilterConfig}
@@ -45,6 +44,7 @@ class JsonRpcControllerFixture(implicit system: ActorSystem)
4544
val blockGenerator = mock[PoWBlockGenerator]
4645

4746
val syncingController = TestProbe()
47+
4848
override lazy val stxLedger = mock[StxLedger]
4949
override lazy val validators = mock[ValidatorsExecutor]
5050
(() => validators.signedTransactionValidator)
@@ -101,7 +101,7 @@ class JsonRpcControllerFixture(implicit system: ActorSystem)
101101
getTransactionFromPoolTimeout
102102
)
103103

104-
val ethBlocksService = new EthBlocksService(blockchain, blockchainReader, consensus)
104+
val ethBlocksService = new EthBlocksService(blockchain, blockchainReader, consensus, blockQueue)
105105

106106
val ethTxService = new EthTxService(
107107
blockchain,

0 commit comments

Comments
 (0)