Skip to content

Commit fe41195

Browse files
author
Leonor Boga
committed
ETCM-963 Refactoring write layer: "storeBlock" from Blockchain class
1 parent c538465 commit fe41195

34 files changed

+309
-188
lines changed

src/it/scala/io/iohk/ethereum/sync/util/CommonFakePeer.scala

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,20 +5,16 @@ import java.nio.file.Files
55
import java.nio.file.Path
66
import java.time.Clock
77
import java.util.concurrent.atomic.AtomicReference
8-
98
import akka.actor.ActorRef
109
import akka.actor.ActorSystem
1110
import akka.testkit.TestProbe
1211
import akka.util.ByteString
1312
import akka.util.Timeout
14-
1513
import monix.eval.Task
1614

1715
import scala.concurrent.duration.FiniteDuration
1816
import scala.concurrent.duration._
19-
2017
import org.bouncycastle.crypto.AsymmetricCipherKeyPair
21-
2218
import io.iohk.ethereum.Fixtures
2319
import io.iohk.ethereum.Timeouts
2420
import io.iohk.ethereum.blockchain.sync.BlockchainHostActor
@@ -36,11 +32,15 @@ import io.iohk.ethereum.db.storage.AppStateStorage
3632
import io.iohk.ethereum.db.storage.Namespaces
3733
import io.iohk.ethereum.db.storage.pruning.ArchivePruning
3834
import io.iohk.ethereum.db.storage.pruning.PruningMode
39-
import io.iohk.ethereum.domain.Block
40-
import io.iohk.ethereum.domain.Blockchain
41-
import io.iohk.ethereum.domain.BlockchainImpl
42-
import io.iohk.ethereum.domain.BlockchainReader
43-
import io.iohk.ethereum.domain.ChainWeight
35+
import io.iohk.ethereum.domain.{
36+
Block,
37+
Blockchain,
38+
BlockchainImpl,
39+
BlockchainMetadata,
40+
BlockchainReader,
41+
BlockchainWriter,
42+
ChainWeight
43+
}
4444
import io.iohk.ethereum.ledger.InMemoryWorldStateProxy
4545
import io.iohk.ethereum.mpt.MerklePatriciaTrie
4646
import io.iohk.ethereum.network.EtcPeerManagerActor
@@ -135,8 +135,13 @@ abstract class CommonFakePeer(peerName: String, fakePeerCustomConfig: FakePeerCu
135135
)
136136
)
137137

138-
val blockchainReader: BlockchainReader = BlockchainReader(storagesInstance.storages)
139-
val bl: BlockchainImpl = BlockchainImpl(storagesInstance.storages, blockchainReader)
138+
val blockchainMetadata = new BlockchainMetadata(
139+
storagesInstance.storages.appStateStorage.getBestBlockNumber(),
140+
storagesInstance.storages.appStateStorage.getLatestCheckpointBlockNumber()
141+
)
142+
val blockchainReader = BlockchainReader(storagesInstance.storages)
143+
val blockchainWriter = BlockchainWriter(storagesInstance.storages, blockchainMetadata)
144+
val bl: BlockchainImpl = BlockchainImpl(storagesInstance.storages, blockchainReader, blockchainMetadata)
140145
val evmCodeStorage = storagesInstance.storages.evmCodeStorage
141146

142147
val genesis: Block = Block(

src/it/scala/io/iohk/ethereum/sync/util/FastSyncItSpecUtils.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ object FastSyncItSpecUtils {
3636
storagesInstance.storages.appStateStorage,
3737
bl,
3838
blockchainReader,
39+
blockchainWriter,
3940
storagesInstance.storages.evmCodeStorage,
4041
storagesInstance.storages.nodeStorage,
4142
validators,

src/it/scala/io/iohk/ethereum/txExecTest/ECIP1017Test.scala

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,8 +78,12 @@ class ECIP1017Test extends AnyFlatSpec with Matchers {
7878

7979
(startBlock to endBlock).foreach { blockToExecute =>
8080
val storages = FixtureProvider.prepareStorages(blockToExecute - 1, fixtures)
81+
val blockchainMetadata = new BlockchainMetadata(
82+
storages.appStateStorage.getBestBlockNumber(),
83+
storages.appStateStorage.getLatestCheckpointBlockNumber()
84+
)
8185
val blockchainReader = BlockchainReader(storages)
82-
val blockchain = BlockchainImpl(storages, blockchainReader)
86+
val blockchain = BlockchainImpl(storages, blockchainReader, blockchainMetadata)
8387
val blockValidation =
8488
new BlockValidation(consensus, blockchainReader, BlockQueue(blockchain, syncConfig))
8589
val blockExecution =

src/it/scala/io/iohk/ethereum/txExecTest/ForksTest.scala

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,11 @@ class ForksTest extends AnyFlatSpec with Matchers {
7272
(startBlock to endBlock).foreach { blockToExecute =>
7373
val storages = FixtureProvider.prepareStorages(blockToExecute - 1, fixtures)
7474
val blockchainReader = BlockchainReader(storages)
75-
val blockchain = BlockchainImpl(storages, blockchainReader)
75+
val blockchainMetadata = new BlockchainMetadata(
76+
storages.appStateStorage.getBestBlockNumber(),
77+
storages.appStateStorage.getLatestCheckpointBlockNumber()
78+
)
79+
val blockchain = BlockchainImpl(storages, blockchainReader, blockchainMetadata)
7680
val blockValidation =
7781
new BlockValidation(consensus, blockchainReader, BlockQueue(blockchain, syncConfig))
7882
val blockExecution =
Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,18 @@
11
package io.iohk.ethereum.txExecTest
22

33
import io.iohk.ethereum.blockchain.sync.EphemBlockchainTestSetup
4-
import io.iohk.ethereum.domain.BlockchainImpl
5-
import io.iohk.ethereum.domain.BlockchainReader
6-
import io.iohk.ethereum.domain.BlockchainStorages
4+
import io.iohk.ethereum.domain.{BlockchainImpl, BlockchainMetadata, BlockchainReader, BlockchainStorages}
75
import io.iohk.ethereum.ledger.VMImpl
86

97
trait ScenarioSetup extends EphemBlockchainTestSetup {
108
protected val testBlockchainStorages: BlockchainStorages
119

10+
override lazy val blockchainMetadata = new BlockchainMetadata(
11+
testBlockchainStorages.appStateStorage.getBestBlockNumber(),
12+
testBlockchainStorages.appStateStorage.getLatestCheckpointBlockNumber()
13+
)
1214
override lazy val blockchainReader: BlockchainReader = BlockchainReader(testBlockchainStorages)
13-
override lazy val blockchain: BlockchainImpl = BlockchainImpl(testBlockchainStorages, blockchainReader)
15+
override lazy val blockchain: BlockchainImpl =
16+
BlockchainImpl(testBlockchainStorages, blockchainReader, blockchainMetadata)
1417
override lazy val vm: VMImpl = new VMImpl
1518
}

src/main/scala/io/iohk/ethereum/blockchain/sync/SyncController.scala

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,14 @@ import akka.actor.ActorRef
66
import akka.actor.PoisonPill
77
import akka.actor.Props
88
import akka.actor.Scheduler
9-
109
import io.iohk.ethereum.blockchain.sync.fast.FastSync
1110
import io.iohk.ethereum.blockchain.sync.regular.RegularSync
1211
import io.iohk.ethereum.consensus.validators.Validators
1312
import io.iohk.ethereum.db.storage.AppStateStorage
1413
import io.iohk.ethereum.db.storage.EvmCodeStorage
1514
import io.iohk.ethereum.db.storage.FastSyncStateStorage
1615
import io.iohk.ethereum.db.storage.NodeStorage
17-
import io.iohk.ethereum.domain.Blockchain
18-
import io.iohk.ethereum.domain.BlockchainReader
16+
import io.iohk.ethereum.domain.{Blockchain, BlockchainReader, BlockchainWriter}
1917
import io.iohk.ethereum.ledger.BlockImport
2018
import io.iohk.ethereum.ledger.BranchResolution
2119
import io.iohk.ethereum.utils.Config.SyncConfig
@@ -24,6 +22,7 @@ class SyncController(
2422
appStateStorage: AppStateStorage,
2523
blockchain: Blockchain,
2624
blockchainReader: BlockchainReader,
25+
blockchainWriter: BlockchainWriter,
2726
evmCodeStorage: EvmCodeStorage,
2827
nodeStorage: NodeStorage,
2928
fastSyncStateStorage: FastSyncStateStorage,
@@ -92,6 +91,7 @@ class SyncController(
9291
appStateStorage,
9392
blockchain,
9493
blockchainReader,
94+
blockchainWriter,
9595
evmCodeStorage,
9696
nodeStorage,
9797
validators,
@@ -139,6 +139,7 @@ object SyncController {
139139
appStateStorage: AppStateStorage,
140140
blockchain: Blockchain,
141141
blockchainReader: BlockchainReader,
142+
blockchainWriter: BlockchainWriter,
142143
evmCodeStorage: EvmCodeStorage,
143144
nodeStorage: NodeStorage,
144145
syncStateStorage: FastSyncStateStorage,
@@ -156,6 +157,7 @@ object SyncController {
156157
appStateStorage,
157158
blockchain,
158159
blockchainReader,
160+
blockchainWriter,
159161
evmCodeStorage,
160162
nodeStorage,
161163
syncStateStorage,

src/main/scala/io/iohk/ethereum/blockchain/sync/fast/FastSync.scala

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ class FastSync(
5454
val appStateStorage: AppStateStorage,
5555
val blockchain: Blockchain,
5656
val blockchainReader: BlockchainReader,
57+
blockchainWriter: BlockchainWriter,
5758
evmCodeStorage: EvmCodeStorage,
5859
nodeStorage: NodeStorage,
5960
val validators: Validators,
@@ -588,7 +589,7 @@ class FastSync(
588589
}
589590

590591
private def updateSyncState(header: BlockHeader, parentWeight: ChainWeight): Unit = {
591-
blockchain
592+
blockchainWriter
592593
.storeBlockHeader(header)
593594
.and(blockchain.storeChainWeight(header.hash, parentWeight.increase(header)))
594595
.commit()
@@ -798,7 +799,7 @@ class FastSync(
798799
requestedHashes
799800
.zip(blockBodies)
800801
.map { case (hash, body) =>
801-
blockchain.storeBlockBody(hash, body)
802+
blockchainWriter.storeBlockBody(hash, body)
802803
}
803804
.reduce(_.and(_))
804805
.commit()
@@ -1147,6 +1148,7 @@ object FastSync {
11471148
appStateStorage: AppStateStorage,
11481149
blockchain: Blockchain,
11491150
blockchainReader: BlockchainReader,
1151+
blockchainWriter: BlockchainWriter,
11501152
evmCodeStorage: EvmCodeStorage,
11511153
nodeStorage: NodeStorage,
11521154
validators: Validators,
@@ -1162,6 +1164,7 @@ object FastSync {
11621164
appStateStorage,
11631165
blockchain,
11641166
blockchainReader,
1167+
blockchainWriter,
11651168
evmCodeStorage,
11661169
nodeStorage,
11671170
validators,

src/main/scala/io/iohk/ethereum/domain/Blockchain.scala

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ import io.iohk.ethereum.db.storage.NodeStorage.NodeHash
1515
import io.iohk.ethereum.db.storage.TransactionMappingStorage.TransactionLocation
1616
import io.iohk.ethereum.db.storage._
1717
import io.iohk.ethereum.domain
18-
import io.iohk.ethereum.domain.BlockchainImpl.BestBlockLatestCheckpointNumbers
1918
import io.iohk.ethereum.jsonrpc.ProofService.StorageProof
2019
import io.iohk.ethereum.ledger.InMemoryWorldStateProxy
2120
import io.iohk.ethereum.ledger.InMemoryWorldStateProxyStorage
@@ -139,7 +138,8 @@ class BlockchainImpl(
139138
protected val transactionMappingStorage: TransactionMappingStorage,
140139
protected val appStateStorage: AppStateStorage,
141140
protected val stateStorage: StateStorage,
142-
blockchainReader: BlockchainReader
141+
blockchainReader: BlockchainReader,
142+
blockchainMetadata: BlockchainMetadata
143143
) extends Blockchain
144144
with Logger {
145145

@@ -164,7 +164,7 @@ class BlockchainImpl(
164164

165165
override def getBestBlockNumber(): BigInt = {
166166
val bestSavedBlockNumber = appStateStorage.getBestBlockNumber()
167-
val bestKnownBlockNumber = bestKnownBlockAndLatestCheckpoint.get().bestBlockNumber
167+
val bestKnownBlockNumber = blockchainMetadata.bestKnownBlockAndLatestCheckpoint.get().bestBlockNumber
168168
log.debug(
169169
"Current best saved block number {}. Current best known block number {}",
170170
bestSavedBlockNumber,
@@ -177,7 +177,7 @@ class BlockchainImpl(
177177
}
178178

179179
override def getLatestCheckpointBlockNumber(): BigInt =
180-
bestKnownBlockAndLatestCheckpoint.get().latestCheckpointNumber
180+
blockchainMetadata.bestKnownBlockAndLatestCheckpoint.get().latestCheckpointNumber
181181

182182
//returns the best known block if it's available in the storage, otherwise the best stored block
183183
override def getBestBlock(): Option[Block] = {
@@ -311,10 +311,12 @@ class BlockchainImpl(
311311
}
312312

313313
private def saveBestKnownBlock(bestBlockNumber: BigInt): Unit =
314-
bestKnownBlockAndLatestCheckpoint.updateAndGet(_.copy(bestBlockNumber = bestBlockNumber))
314+
blockchainMetadata.bestKnownBlockAndLatestCheckpoint.updateAndGet(_.copy(bestBlockNumber = bestBlockNumber))
315315

316316
private def saveBestKnownBlockAndLatestCheckpointNumber(number: BigInt, latestCheckpointNumber: BigInt): Unit =
317-
bestKnownBlockAndLatestCheckpoint.set(BestBlockLatestCheckpointNumbers(number, latestCheckpointNumber))
317+
blockchainMetadata.bestKnownBlockAndLatestCheckpoint.set(
318+
BestBlockLatestCheckpointNumbers(number, latestCheckpointNumber)
319+
)
318320

319321
def storeChainWeight(blockhash: ByteString, weight: ChainWeight): DataSourceBatchUpdate =
320322
chainWeightStorage.put(blockhash, weight)
@@ -461,7 +463,11 @@ trait BlockchainStorages {
461463
}
462464

463465
object BlockchainImpl {
464-
def apply(storages: BlockchainStorages, blockchainReader: BlockchainReader): BlockchainImpl =
466+
def apply(
467+
storages: BlockchainStorages,
468+
blockchainReader: BlockchainReader,
469+
metadata: BlockchainMetadata
470+
): BlockchainImpl =
465471
new BlockchainImpl(
466472
blockHeadersStorage = storages.blockHeadersStorage,
467473
blockBodiesStorage = storages.blockBodiesStorage,
@@ -471,8 +477,7 @@ object BlockchainImpl {
471477
transactionMappingStorage = storages.transactionMappingStorage,
472478
appStateStorage = storages.appStateStorage,
473479
stateStorage = storages.stateStorage,
474-
blockchainReader = blockchainReader
480+
blockchainReader = blockchainReader,
481+
blockchainMetadata = metadata
475482
)
476-
477-
private case class BestBlockLatestCheckpointNumbers(bestBlockNumber: BigInt, latestCheckpointNumber: BigInt)
478483
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package io.iohk.ethereum.domain
2+
3+
import java.util.concurrent.atomic.AtomicReference
4+
5+
class BlockchainMetadata(bestBlockNumber: BigInt, latestCheckpointNumber: BigInt) {
6+
lazy val bestKnownBlockAndLatestCheckpoint: AtomicReference[BestBlockLatestCheckpointNumbers] =
7+
new AtomicReference(BestBlockLatestCheckpointNumbers(bestBlockNumber, latestCheckpointNumber))
8+
}
9+
10+
case class BestBlockLatestCheckpointNumbers(bestBlockNumber: BigInt, latestCheckpointNumber: BigInt)
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
package io.iohk.ethereum.domain
2+
3+
import akka.util.ByteString
4+
import io.iohk.ethereum.db.dataSource.DataSourceBatchUpdate
5+
import io.iohk.ethereum.db.storage.TransactionMappingStorage.TransactionLocation
6+
import io.iohk.ethereum.db.storage.{
7+
BlockBodiesStorage,
8+
BlockHeadersStorage,
9+
BlockNumberMappingStorage,
10+
TransactionMappingStorage
11+
}
12+
import io.iohk.ethereum.utils.Logger
13+
14+
class BlockchainWriter(
15+
blockHeadersStorage: BlockHeadersStorage,
16+
blockBodiesStorage: BlockBodiesStorage,
17+
blockNumberMappingStorage: BlockNumberMappingStorage,
18+
transactionMappingStorage: TransactionMappingStorage
19+
) extends Logger {
20+
21+
/**
22+
* Persists a block in the underlying Blockchain Database
23+
* Note: all store* do not update the database immediately, rather they create
24+
* a [[io.iohk.ethereum.db.dataSource.DataSourceBatchUpdate]] which then has to be committed (atomic operation)
25+
*
26+
* @param block Block to be saved
27+
*/
28+
def storeBlock(block: Block): DataSourceBatchUpdate = {
29+
storeBlockHeader(block.header).and(storeBlockBody(block.header.hash, block.body))
30+
}
31+
32+
def storeBlockHeader(blockHeader: BlockHeader): DataSourceBatchUpdate = {
33+
val hash = blockHeader.hash
34+
blockHeadersStorage.put(hash, blockHeader).and(saveBlockNumberMapping(blockHeader.number, hash))
35+
}
36+
37+
def storeBlockBody(blockHash: ByteString, blockBody: BlockBody): DataSourceBatchUpdate = {
38+
blockBodiesStorage.put(blockHash, blockBody).and(saveTxsLocations(blockHash, blockBody))
39+
}
40+
41+
private def saveBlockNumberMapping(number: BigInt, hash: ByteString): DataSourceBatchUpdate =
42+
blockNumberMappingStorage.put(number, hash)
43+
44+
private def saveTxsLocations(blockHash: ByteString, blockBody: BlockBody): DataSourceBatchUpdate =
45+
blockBody.transactionList.zipWithIndex.foldLeft(transactionMappingStorage.emptyBatchUpdate) {
46+
case (updates, (tx, index)) =>
47+
updates.and(transactionMappingStorage.put(tx.hash, TransactionLocation(blockHash, index)))
48+
}
49+
}
50+
51+
object BlockchainWriter {
52+
def apply(storages: BlockchainStorages): BlockchainWriter =
53+
new BlockchainWriter(
54+
storages.blockHeadersStorage,
55+
storages.blockBodiesStorage,
56+
storages.blockNumberMappingStorage,
57+
storages.transactionMappingStorage
58+
)
59+
}

0 commit comments

Comments
 (0)